2
2
* ALSA ASoC Machine Driver for Allo Boss DAC
3
3
*
4
4
* Author: Baswaraj K <[email protected] >
5
- * Copyright 2016
6
- * based on code by Daniel Matuschek, Stuart MacLean <[email protected] >
5
+ * Copyright 2017
6
+ * based on code by Daniel Matuschek,
7
+ * Stuart MacLean <[email protected] >
7
8
* based on code by Florian Meier <[email protected] >
8
9
*
9
10
* This program is free software; you can redistribute it and/or
17
18
*/
18
19
19
20
#include <linux/module.h>
21
+ #include <linux/gpio/consumer.h>
20
22
#include <linux/platform_device.h>
21
23
#include <linux/clk.h>
22
24
#include <linux/delay.h>
@@ -36,6 +38,8 @@ struct pcm512x_priv {
36
38
struct clk * sclk ;
37
39
};
38
40
41
+ static struct gpio_desc * mute_gpio ;
42
+
39
43
/* Clock rate of CLK44EN attached to GPIO6 pin */
40
44
#define CLK_44EN_RATE 45158400UL
41
45
/* Clock rate of CLK48EN attached to GPIO3 pin */
@@ -111,6 +115,7 @@ static int snd_allo_boss_clk_for_rate(int sample_rate)
111
115
case 44100 :
112
116
case 88200 :
113
117
case 176400 :
118
+ case 352800 :
114
119
type = ALLO_BOSS_CLK44EN ;
115
120
break ;
116
121
default :
@@ -138,7 +143,7 @@ static void snd_allo_boss_set_sclk(struct snd_soc_codec *codec,
138
143
static int snd_allo_boss_init (struct snd_soc_pcm_runtime * rtd )
139
144
{
140
145
struct snd_soc_codec * codec = rtd -> codec ;
141
- struct pcm512x_priv * priv ;
146
+ struct pcm512x_priv * priv = snd_soc_codec_get_drvdata ( codec ) ;
142
147
143
148
if (slave )
144
149
snd_soc_allo_boss_master = false;
@@ -150,15 +155,22 @@ static int snd_allo_boss_init(struct snd_soc_pcm_runtime *rtd)
150
155
struct snd_soc_dai_link * dai = rtd -> dai_link ;
151
156
152
157
dai -> name = "BossDAC" ;
153
- dai -> stream_name = "BossDAC " ;
158
+ dai -> stream_name = "Boss DAC HiFi [Master] " ;
154
159
dai -> dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
155
160
| SND_SOC_DAIFMT_CBM_CFM ;
156
161
157
162
snd_soc_update_bits (codec , PCM512x_BCLK_LRCLK_CFG , 0x31 , 0x11 );
158
163
snd_soc_update_bits (codec , PCM512x_MASTER_MODE , 0x03 , 0x03 );
159
164
snd_soc_update_bits (codec , PCM512x_MASTER_CLKDIV_2 , 0x7f , 63 );
165
+ /*
166
+ * Default sclk to CLK_48EN_RATE, otherwise codec
167
+ * pcm512x_dai_startup_master method could call
168
+ * snd_pcm_hw_constraint_ratnums using CLK_44EN/64
169
+ * which will mask 384k sample rate.
170
+ */
171
+ if (!IS_ERR (priv -> sclk ))
172
+ clk_set_rate (priv -> sclk , CLK_48EN_RATE );
160
173
} else {
161
- priv = snd_soc_codec_get_drvdata (codec );
162
174
priv -> sclk = ERR_PTR (- ENOENT );
163
175
}
164
176
@@ -218,6 +230,52 @@ static int snd_allo_boss_set_bclk_ratio_pro(
218
230
return snd_soc_dai_set_bclk_ratio (cpu_dai , bratio );
219
231
}
220
232
233
+ static void snd_allo_boss_gpio_mute (struct snd_soc_card * card )
234
+ {
235
+ if (mute_gpio )
236
+ gpiod_set_value_cansleep (mute_gpio , 1 );
237
+ }
238
+
239
+ static void snd_allo_boss_gpio_unmute (struct snd_soc_card * card )
240
+ {
241
+ if (mute_gpio )
242
+ gpiod_set_value_cansleep (mute_gpio , 0 );
243
+ }
244
+
245
+ static int snd_allo_boss_set_bias_level (struct snd_soc_card * card ,
246
+ struct snd_soc_dapm_context * dapm , enum snd_soc_bias_level level )
247
+ {
248
+ struct snd_soc_pcm_runtime * rtd ;
249
+ struct snd_soc_dai * codec_dai ;
250
+
251
+ rtd = snd_soc_get_pcm_runtime (card , card -> dai_link [0 ].name );
252
+ codec_dai = rtd -> codec_dai ;
253
+
254
+ if (dapm -> dev != codec_dai -> dev )
255
+ return 0 ;
256
+
257
+ switch (level ) {
258
+ case SND_SOC_BIAS_PREPARE :
259
+ if (dapm -> bias_level != SND_SOC_BIAS_STANDBY )
260
+ break ;
261
+ /* UNMUTE DAC */
262
+ snd_allo_boss_gpio_unmute (card );
263
+ break ;
264
+
265
+ case SND_SOC_BIAS_STANDBY :
266
+ if (dapm -> bias_level != SND_SOC_BIAS_PREPARE )
267
+ break ;
268
+ /* MUTE DAC */
269
+ snd_allo_boss_gpio_mute (card );
270
+ break ;
271
+
272
+ default :
273
+ break ;
274
+ }
275
+
276
+ return 0 ;
277
+ }
278
+
221
279
static int snd_allo_boss_hw_params (
222
280
struct snd_pcm_substream * substream , struct snd_pcm_hw_params * params )
223
281
{
@@ -239,23 +297,6 @@ static int snd_allo_boss_hw_params(
239
297
ret = snd_allo_boss_update_rate_den (
240
298
substream , params );
241
299
} else {
242
- if (snd_allo_boss_is_sclk (rtd -> codec )) {
243
- snd_soc_update_bits (rtd -> codec , PCM512x_PLL_EN ,
244
- PCM512x_PLLE , 0x01 );
245
- snd_soc_update_bits (rtd -> codec , PCM512x_PLL_REF ,
246
- PCM512x_SREF , PCM512x_SREF_BCK );
247
- dev_dbg (rtd -> codec -> dev ,
248
- "Setting BCLK as input clock and Enable PLL\n" );
249
- } else {
250
- snd_soc_update_bits (rtd -> codec , PCM512x_PLL_EN ,
251
- PCM512x_PLLE , 0x00 );
252
- snd_soc_update_bits (rtd -> codec , PCM512x_PLL_REF ,
253
- PCM512x_SREF , PCM512x_SREF_SCK );
254
-
255
- dev_dbg (rtd -> codec -> dev ,
256
- "Setting SCLK as input clock and disabled PLL\n" );
257
- }
258
-
259
300
ret = snd_soc_dai_set_bclk_ratio (cpu_dai , sample_bits * 2 );
260
301
}
261
302
return ret ;
@@ -266,8 +307,23 @@ static int snd_allo_boss_startup(
266
307
{
267
308
struct snd_soc_pcm_runtime * rtd = substream -> private_data ;
268
309
struct snd_soc_codec * codec = rtd -> codec ;
310
+ struct snd_soc_card * card = rtd -> card ;
269
311
270
312
snd_soc_update_bits (codec , PCM512x_GPIO_CONTROL_1 , 0x08 , 0x08 );
313
+ snd_allo_boss_gpio_mute (card );
314
+
315
+ if (snd_soc_allo_boss_master ) {
316
+ struct pcm512x_priv * priv = snd_soc_codec_get_drvdata (codec );
317
+ /*
318
+ * Default sclk to CLK_48EN_RATE, otherwise codec
319
+ * pcm512x_dai_startup_master method could call
320
+ * snd_pcm_hw_constraint_ratnums using CLK_44EN/64
321
+ * which will mask 384k sample rate.
322
+ */
323
+ if (!IS_ERR (priv -> sclk ))
324
+ clk_set_rate (priv -> sclk , CLK_48EN_RATE );
325
+ }
326
+
271
327
return 0 ;
272
328
}
273
329
@@ -280,11 +336,21 @@ static void snd_allo_boss_shutdown(
280
336
snd_soc_update_bits (codec , PCM512x_GPIO_CONTROL_1 , 0x08 , 0x00 );
281
337
}
282
338
339
+ static int snd_allo_boss_prepare (
340
+ struct snd_pcm_substream * substream )
341
+ {
342
+ struct snd_soc_pcm_runtime * rtd = substream -> private_data ;
343
+ struct snd_soc_card * card = rtd -> card ;
344
+
345
+ snd_allo_boss_gpio_unmute (card );
346
+ return 0 ;
347
+ }
283
348
/* machine stream operations */
284
349
static struct snd_soc_ops snd_allo_boss_ops = {
285
350
.hw_params = snd_allo_boss_hw_params ,
286
351
.startup = snd_allo_boss_startup ,
287
352
.shutdown = snd_allo_boss_shutdown ,
353
+ .prepare = snd_allo_boss_prepare ,
288
354
};
289
355
290
356
static struct snd_soc_dai_link snd_allo_boss_dai [] = {
@@ -335,19 +401,40 @@ static int snd_allo_boss_probe(struct platform_device *pdev)
335
401
digital_gain_0db_limit = !of_property_read_bool (
336
402
pdev -> dev .of_node , "allo,24db_digital_gain" );
337
403
slave = of_property_read_bool (pdev -> dev .of_node ,
338
- "allo,slave" );
339
- }
404
+ "allo,slave" );
405
+
406
+ mute_gpio = devm_gpiod_get_optional (& pdev -> dev , "mute" ,
407
+ GPIOD_OUT_LOW );
408
+ if (IS_ERR (mute_gpio )) {
409
+ ret = PTR_ERR (mute_gpio );
410
+ dev_err (& pdev -> dev ,
411
+ "failed to get mute gpio: %d\n" , ret );
412
+ return ret ;
413
+ }
340
414
341
- ret = snd_soc_register_card (& snd_allo_boss );
342
- if (ret )
343
- dev_err (& pdev -> dev ,
344
- "snd_soc_register_card() failed: %d\n" , ret );
415
+ if (mute_gpio )
416
+ snd_allo_boss .set_bias_level =
417
+ snd_allo_boss_set_bias_level ;
345
418
346
- return ret ;
419
+ ret = snd_soc_register_card (& snd_allo_boss );
420
+ if (ret ) {
421
+ dev_err (& pdev -> dev ,
422
+ "snd_soc_register_card() failed: %d\n" , ret );
423
+ return ret ;
424
+ }
425
+
426
+ if (mute_gpio )
427
+ snd_allo_boss_gpio_mute (& snd_allo_boss );
428
+
429
+ return 0 ;
430
+ }
431
+
432
+ return - EINVAL ;
347
433
}
348
434
349
435
static int snd_allo_boss_remove (struct platform_device * pdev )
350
436
{
437
+ snd_allo_boss_gpio_mute (& snd_allo_boss );
351
438
return snd_soc_unregister_card (& snd_allo_boss );
352
439
}
353
440
0 commit comments