1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16#include <linux/module.h>
17#include <linux/delay.h>
18#include <sound/pcm.h>
19#include <sound/pcm_params.h>
20#include <sound/soc.h>
21#include <sound/soc-dapm.h>
22#include <sound/initval.h>
23
24#include <sound/uda134x.h>
25#include <sound/l3.h>
26
27#include "uda134x.h"
28
29
30#define POWER_OFF_ON_STANDBY 1
31
32
33
34
35
36
37
38
39
40
41
42
43#define UDA134X_RATES SNDRV_PCM_RATE_8000_48000
44#define UDA134X_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | \
45 SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_S20_3LE)
46
47struct uda134x_priv {
48 int sysclk;
49 int dai_fmt;
50
51 struct snd_pcm_substream *master_substream;
52 struct snd_pcm_substream *slave_substream;
53};
54
55
56static const char uda134x_reg[UDA134X_REGS_NUM] = {
57
58 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
59
60 0x00, 0x83, 0x00, 0x40, 0x80, 0x00,
61};
62
63
64
65
66static inline unsigned int uda134x_read_reg_cache(struct snd_soc_codec *codec,
67 unsigned int reg)
68{
69 u8 *cache = codec->reg_cache;
70
71 if (reg >= UDA134X_REGS_NUM)
72 return -1;
73 return cache[reg];
74}
75
76
77
78
79static inline void uda134x_write_reg_cache(struct snd_soc_codec *codec,
80 u8 reg, unsigned int value)
81{
82 u8 *cache = codec->reg_cache;
83
84 if (reg >= UDA134X_REGS_NUM)
85 return;
86 cache[reg] = value;
87}
88
89
90
91
92
93static int uda134x_write(struct snd_soc_codec *codec, unsigned int reg,
94 unsigned int value)
95{
96 int ret;
97 u8 addr;
98 u8 data = value;
99 struct uda134x_platform_data *pd = codec->control_data;
100
101 pr_debug("%s reg: %02X, value:%02X\n", __func__, reg, value);
102
103 if (reg >= UDA134X_REGS_NUM) {
104 printk(KERN_ERR "%s unkown register: reg: %u",
105 __func__, reg);
106 return -EINVAL;
107 }
108
109 uda134x_write_reg_cache(codec, reg, value);
110
111 switch (reg) {
112 case UDA134X_STATUS0:
113 case UDA134X_STATUS1:
114 addr = UDA134X_STATUS_ADDR;
115 break;
116 case UDA134X_DATA000:
117 case UDA134X_DATA001:
118 case UDA134X_DATA010:
119 addr = UDA134X_DATA0_ADDR;
120 break;
121 case UDA134X_DATA1:
122 addr = UDA134X_DATA1_ADDR;
123 break;
124 default:
125
126 addr = (reg | UDA134X_EXTADDR_PREFIX);
127
128 ret = l3_write(&pd->l3,
129 UDA134X_DATA0_ADDR, &addr, 1);
130 if (ret != 1)
131 return -EIO;
132
133 addr = UDA134X_DATA0_ADDR;
134 data = (value | UDA134X_EXTDATA_PREFIX);
135 break;
136 }
137
138 ret = l3_write(&pd->l3,
139 addr, &data, 1);
140 if (ret != 1)
141 return -EIO;
142
143 return 0;
144}
145
146static inline void uda134x_reset(struct snd_soc_codec *codec)
147{
148 u8 reset_reg = uda134x_read_reg_cache(codec, UDA134X_STATUS0);
149 uda134x_write(codec, UDA134X_STATUS0, reset_reg | (1<<6));
150 msleep(1);
151 uda134x_write(codec, UDA134X_STATUS0, reset_reg & ~(1<<6));
152}
153
154static int uda134x_mute(struct snd_soc_dai *dai, int mute)
155{
156 struct snd_soc_codec *codec = dai->codec;
157 u8 mute_reg = uda134x_read_reg_cache(codec, UDA134X_DATA010);
158
159 pr_debug("%s mute: %d\n", __func__, mute);
160
161 if (mute)
162 mute_reg |= (1<<2);
163 else
164 mute_reg &= ~(1<<2);
165
166 uda134x_write(codec, UDA134X_DATA010, mute_reg);
167
168 return 0;
169}
170
171static int uda134x_startup(struct snd_pcm_substream *substream,
172 struct snd_soc_dai *dai)
173{
174 struct snd_soc_pcm_runtime *rtd = substream->private_data;
175 struct snd_soc_device *socdev = rtd->socdev;
176 struct snd_soc_codec *codec = socdev->card->codec;
177 struct uda134x_priv *uda134x = codec->private_data;
178 struct snd_pcm_runtime *master_runtime;
179
180 if (uda134x->master_substream) {
181 master_runtime = uda134x->master_substream->runtime;
182
183 pr_debug("%s constraining to %d bits at %d\n", __func__,
184 master_runtime->sample_bits,
185 master_runtime->rate);
186
187 snd_pcm_hw_constraint_minmax(substream->runtime,
188 SNDRV_PCM_HW_PARAM_RATE,
189 master_runtime->rate,
190 master_runtime->rate);
191
192 snd_pcm_hw_constraint_minmax(substream->runtime,
193 SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
194 master_runtime->sample_bits,
195 master_runtime->sample_bits);
196
197 uda134x->slave_substream = substream;
198 } else
199 uda134x->master_substream = substream;
200
201 return 0;
202}
203
204static void uda134x_shutdown(struct snd_pcm_substream *substream,
205 struct snd_soc_dai *dai)
206{
207 struct snd_soc_pcm_runtime *rtd = substream->private_data;
208 struct snd_soc_device *socdev = rtd->socdev;
209 struct snd_soc_codec *codec = socdev->card->codec;
210 struct uda134x_priv *uda134x = codec->private_data;
211
212 if (uda134x->master_substream == substream)
213 uda134x->master_substream = uda134x->slave_substream;
214
215 uda134x->slave_substream = NULL;
216}
217
218static int uda134x_hw_params(struct snd_pcm_substream *substream,
219 struct snd_pcm_hw_params *params,
220 struct snd_soc_dai *dai)
221{
222 struct snd_soc_pcm_runtime *rtd = substream->private_data;
223 struct snd_soc_device *socdev = rtd->socdev;
224 struct snd_soc_codec *codec = socdev->card->codec;
225 struct uda134x_priv *uda134x = codec->private_data;
226 u8 hw_params;
227
228 if (substream == uda134x->slave_substream) {
229 pr_debug("%s ignoring hw_params for slave substream\n",
230 __func__);
231 return 0;
232 }
233
234 hw_params = uda134x_read_reg_cache(codec, UDA134X_STATUS0);
235 hw_params &= STATUS0_SYSCLK_MASK;
236 hw_params &= STATUS0_DAIFMT_MASK;
237
238 pr_debug("%s sysclk: %d, rate:%d\n", __func__,
239 uda134x->sysclk, params_rate(params));
240
241
242 switch (uda134x->sysclk / params_rate(params)) {
243 case 512:
244 break;
245 case 384:
246 hw_params |= (1<<4);
247 break;
248 case 256:
249 hw_params |= (1<<5);
250 break;
251 default:
252 printk(KERN_ERR "%s unsupported fs\n", __func__);
253 return -EINVAL;
254 }
255
256 pr_debug("%s dai_fmt: %d, params_format:%d\n", __func__,
257 uda134x->dai_fmt, params_format(params));
258
259
260 switch (uda134x->dai_fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
261 case SND_SOC_DAIFMT_I2S:
262 break;
263 case SND_SOC_DAIFMT_RIGHT_J:
264 switch (params_format(params)) {
265 case SNDRV_PCM_FORMAT_S16_LE:
266 hw_params |= (1<<1);
267 break;
268 case SNDRV_PCM_FORMAT_S18_3LE:
269 hw_params |= (1<<2);
270 break;
271 case SNDRV_PCM_FORMAT_S20_3LE:
272 hw_params |= ((1<<2) | (1<<1));
273 break;
274 default:
275 printk(KERN_ERR "%s unsupported format (right)\n",
276 __func__);
277 return -EINVAL;
278 }
279 break;
280 case SND_SOC_DAIFMT_LEFT_J:
281 hw_params |= (1<<3);
282 break;
283 default:
284 printk(KERN_ERR "%s unsupported format\n", __func__);
285 return -EINVAL;
286 }
287
288 uda134x_write(codec, UDA134X_STATUS0, hw_params);
289
290 return 0;
291}
292
293static int uda134x_set_dai_sysclk(struct snd_soc_dai *codec_dai,
294 int clk_id, unsigned int freq, int dir)
295{
296 struct snd_soc_codec *codec = codec_dai->codec;
297 struct uda134x_priv *uda134x = codec->private_data;
298
299 pr_debug("%s clk_id: %d, freq: %u, dir: %d\n", __func__,
300 clk_id, freq, dir);
301
302
303
304
305
306 if ((freq >= (256 * 8000)) && (freq <= (512 * 48000))) {
307 uda134x->sysclk = freq;
308 return 0;
309 }
310
311 printk(KERN_ERR "%s unsupported sysclk\n", __func__);
312 return -EINVAL;
313}
314
315static int uda134x_set_dai_fmt(struct snd_soc_dai *codec_dai,
316 unsigned int fmt)
317{
318 struct snd_soc_codec *codec = codec_dai->codec;
319 struct uda134x_priv *uda134x = codec->private_data;
320
321 pr_debug("%s fmt: %08X\n", __func__, fmt);
322
323
324 if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS) {
325 printk(KERN_ERR "%s unsupported slave mode\n", __func__);
326 return -EINVAL;
327 }
328
329
330 if ((fmt & SND_SOC_DAIFMT_INV_MASK) != SND_SOC_DAIFMT_NB_NF) {
331 printk(KERN_ERR "%s unsupported clock inversion\n", __func__);
332 return -EINVAL;
333 }
334
335
336
337 uda134x->dai_fmt = fmt;
338
339 return 0;
340}
341
342static int uda134x_set_bias_level(struct snd_soc_codec *codec,
343 enum snd_soc_bias_level level)
344{
345 u8 reg;
346 struct uda134x_platform_data *pd = codec->control_data;
347 int i;
348 u8 *cache = codec->reg_cache;
349
350 pr_debug("%s bias level %d\n", __func__, level);
351
352 switch (level) {
353 case SND_SOC_BIAS_ON:
354
355 reg = uda134x_read_reg_cache(codec, UDA134X_STATUS1);
356 uda134x_write(codec, UDA134X_STATUS1, reg | 0x03);
357 break;
358 case SND_SOC_BIAS_PREPARE:
359
360 if (pd->power) {
361 pd->power(1);
362
363 for (i = 0; i < ARRAY_SIZE(uda134x_reg); i++)
364 codec->write(codec, i, *cache++);
365 }
366 break;
367 case SND_SOC_BIAS_STANDBY:
368
369 reg = uda134x_read_reg_cache(codec, UDA134X_STATUS1);
370 uda134x_write(codec, UDA134X_STATUS1, reg & ~(0x03));
371 break;
372 case SND_SOC_BIAS_OFF:
373
374 if (pd->power)
375 pd->power(0);
376 break;
377 }
378 codec->bias_level = level;
379 return 0;
380}
381
382static const char *uda134x_dsp_setting[] = {"Flat", "Minimum1",
383 "Minimum2", "Maximum"};
384static const char *uda134x_deemph[] = {"None", "32Khz", "44.1Khz", "48Khz"};
385static const char *uda134x_mixmode[] = {"Differential", "Analog1",
386 "Analog2", "Both"};
387
388static const struct soc_enum uda134x_mixer_enum[] = {
389SOC_ENUM_SINGLE(UDA134X_DATA010, 0, 0x04, uda134x_dsp_setting),
390SOC_ENUM_SINGLE(UDA134X_DATA010, 3, 0x04, uda134x_deemph),
391SOC_ENUM_SINGLE(UDA134X_EA010, 0, 0x04, uda134x_mixmode),
392};
393
394static const struct snd_kcontrol_new uda1341_snd_controls[] = {
395SOC_SINGLE("Master Playback Volume", UDA134X_DATA000, 0, 0x3F, 1),
396SOC_SINGLE("Capture Volume", UDA134X_EA010, 2, 0x07, 0),
397SOC_SINGLE("Analog1 Volume", UDA134X_EA000, 0, 0x1F, 1),
398SOC_SINGLE("Analog2 Volume", UDA134X_EA001, 0, 0x1F, 1),
399
400SOC_SINGLE("Mic Sensitivity", UDA134X_EA010, 2, 7, 0),
401SOC_SINGLE("Mic Volume", UDA134X_EA101, 0, 0x1F, 0),
402
403SOC_SINGLE("Tone Control - Bass", UDA134X_DATA001, 2, 0xF, 0),
404SOC_SINGLE("Tone Control - Treble", UDA134X_DATA001, 0, 3, 0),
405
406SOC_ENUM("Sound Processing Filter", uda134x_mixer_enum[0]),
407SOC_ENUM("PCM Playback De-emphasis", uda134x_mixer_enum[1]),
408SOC_ENUM("Input Mux", uda134x_mixer_enum[2]),
409
410SOC_SINGLE("AGC Switch", UDA134X_EA100, 4, 1, 0),
411SOC_SINGLE("AGC Target Volume", UDA134X_EA110, 0, 0x03, 1),
412SOC_SINGLE("AGC Timing", UDA134X_EA110, 2, 0x07, 0),
413
414SOC_SINGLE("DAC +6dB Switch", UDA134X_STATUS1, 6, 1, 0),
415SOC_SINGLE("ADC +6dB Switch", UDA134X_STATUS1, 5, 1, 0),
416SOC_SINGLE("ADC Polarity Switch", UDA134X_STATUS1, 4, 1, 0),
417SOC_SINGLE("DAC Polarity Switch", UDA134X_STATUS1, 3, 1, 0),
418SOC_SINGLE("Double Speed Playback Switch", UDA134X_STATUS1, 2, 1, 0),
419SOC_SINGLE("DC Filter Enable Switch", UDA134X_STATUS0, 0, 1, 0),
420};
421
422static const struct snd_kcontrol_new uda1340_snd_controls[] = {
423SOC_SINGLE("Master Playback Volume", UDA134X_DATA000, 0, 0x3F, 1),
424
425SOC_SINGLE("Tone Control - Bass", UDA134X_DATA001, 2, 0xF, 0),
426SOC_SINGLE("Tone Control - Treble", UDA134X_DATA001, 0, 3, 0),
427
428SOC_ENUM("Sound Processing Filter", uda134x_mixer_enum[0]),
429SOC_ENUM("PCM Playback De-emphasis", uda134x_mixer_enum[1]),
430
431SOC_SINGLE("DC Filter Enable Switch", UDA134X_STATUS0, 0, 1, 0),
432};
433
434static struct snd_soc_dai_ops uda134x_dai_ops = {
435 .startup = uda134x_startup,
436 .shutdown = uda134x_shutdown,
437 .hw_params = uda134x_hw_params,
438 .digital_mute = uda134x_mute,
439 .set_sysclk = uda134x_set_dai_sysclk,
440 .set_fmt = uda134x_set_dai_fmt,
441};
442
443struct snd_soc_dai uda134x_dai = {
444 .name = "UDA134X",
445
446 .playback = {
447 .stream_name = "Playback",
448 .channels_min = 1,
449 .channels_max = 2,
450 .rates = UDA134X_RATES,
451 .formats = UDA134X_FORMATS,
452 },
453
454 .capture = {
455 .stream_name = "Capture",
456 .channels_min = 1,
457 .channels_max = 2,
458 .rates = UDA134X_RATES,
459 .formats = UDA134X_FORMATS,
460 },
461
462 .ops = &uda134x_dai_ops,
463};
464EXPORT_SYMBOL(uda134x_dai);
465
466
467static int uda134x_soc_probe(struct platform_device *pdev)
468{
469 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
470 struct snd_soc_codec *codec;
471 struct uda134x_priv *uda134x;
472 void *codec_setup_data = socdev->codec_data;
473 int ret = -ENOMEM;
474 struct uda134x_platform_data *pd;
475
476 printk(KERN_INFO "UDA134X SoC Audio Codec\n");
477
478 if (!codec_setup_data) {
479 printk(KERN_ERR "UDA134X SoC codec: "
480 "missing L3 bitbang function\n");
481 return -ENODEV;
482 }
483
484 pd = codec_setup_data;
485 switch (pd->model) {
486 case UDA134X_UDA1340:
487 case UDA134X_UDA1341:
488 case UDA134X_UDA1344:
489 break;
490 default:
491 printk(KERN_ERR "UDA134X SoC codec: "
492 "unsupported model %d\n",
493 pd->model);
494 return -EINVAL;
495 }
496
497 socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
498 if (socdev->card->codec == NULL)
499 return ret;
500
501 codec = socdev->card->codec;
502
503 uda134x = kzalloc(sizeof(struct uda134x_priv), GFP_KERNEL);
504 if (uda134x == NULL)
505 goto priv_err;
506 codec->private_data = uda134x;
507
508 codec->reg_cache = kmemdup(uda134x_reg, sizeof(uda134x_reg),
509 GFP_KERNEL);
510 if (codec->reg_cache == NULL)
511 goto reg_err;
512
513 mutex_init(&codec->mutex);
514
515 codec->reg_cache_size = sizeof(uda134x_reg);
516 codec->reg_cache_step = 1;
517
518 codec->name = "UDA134X";
519 codec->owner = THIS_MODULE;
520 codec->dai = &uda134x_dai;
521 codec->num_dai = 1;
522 codec->read = uda134x_read_reg_cache;
523 codec->write = uda134x_write;
524#ifdef POWER_OFF_ON_STANDBY
525 codec->set_bias_level = uda134x_set_bias_level;
526#endif
527 INIT_LIST_HEAD(&codec->dapm_widgets);
528 INIT_LIST_HEAD(&codec->dapm_paths);
529
530 codec->control_data = codec_setup_data;
531
532 if (pd->power)
533 pd->power(1);
534
535 uda134x_reset(codec);
536
537
538 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
539 if (ret < 0) {
540 printk(KERN_ERR "UDA134X: failed to register pcms\n");
541 goto pcm_err;
542 }
543
544 switch (pd->model) {
545 case UDA134X_UDA1340:
546 case UDA134X_UDA1344:
547 ret = snd_soc_add_controls(codec, uda1340_snd_controls,
548 ARRAY_SIZE(uda1340_snd_controls));
549 break;
550 case UDA134X_UDA1341:
551 ret = snd_soc_add_controls(codec, uda1341_snd_controls,
552 ARRAY_SIZE(uda1341_snd_controls));
553 break;
554 default:
555 printk(KERN_ERR "%s unkown codec type: %d",
556 __func__, pd->model);
557 return -EINVAL;
558 }
559
560 if (ret < 0) {
561 printk(KERN_ERR "UDA134X: failed to register controls\n");
562 goto pcm_err;
563 }
564
565 ret = snd_soc_init_card(socdev);
566 if (ret < 0) {
567 printk(KERN_ERR "UDA134X: failed to register card\n");
568 goto card_err;
569 }
570
571 return 0;
572
573card_err:
574 snd_soc_free_pcms(socdev);
575 snd_soc_dapm_free(socdev);
576pcm_err:
577 kfree(codec->reg_cache);
578reg_err:
579 kfree(codec->private_data);
580priv_err:
581 kfree(codec);
582 return ret;
583}
584
585
586static int uda134x_soc_remove(struct platform_device *pdev)
587{
588 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
589 struct snd_soc_codec *codec = socdev->card->codec;
590
591 uda134x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
592 uda134x_set_bias_level(codec, SND_SOC_BIAS_OFF);
593
594 snd_soc_free_pcms(socdev);
595 snd_soc_dapm_free(socdev);
596
597 kfree(codec->private_data);
598 kfree(codec->reg_cache);
599 kfree(codec);
600
601 return 0;
602}
603
604#if defined(CONFIG_PM)
605static int uda134x_soc_suspend(struct platform_device *pdev,
606 pm_message_t state)
607{
608 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
609 struct snd_soc_codec *codec = socdev->card->codec;
610
611 uda134x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
612 uda134x_set_bias_level(codec, SND_SOC_BIAS_OFF);
613 return 0;
614}
615
616static int uda134x_soc_resume(struct platform_device *pdev)
617{
618 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
619 struct snd_soc_codec *codec = socdev->card->codec;
620
621 uda134x_set_bias_level(codec, SND_SOC_BIAS_PREPARE);
622 uda134x_set_bias_level(codec, SND_SOC_BIAS_ON);
623 return 0;
624}
625#else
626#define uda134x_soc_suspend NULL
627#define uda134x_soc_resume NULL
628#endif
629
630struct snd_soc_codec_device soc_codec_dev_uda134x = {
631 .probe = uda134x_soc_probe,
632 .remove = uda134x_soc_remove,
633 .suspend = uda134x_soc_suspend,
634 .resume = uda134x_soc_resume,
635};
636EXPORT_SYMBOL_GPL(soc_codec_dev_uda134x);
637
638static int __init uda134x_init(void)
639{
640 return snd_soc_register_dai(&uda134x_dai);
641}
642module_init(uda134x_init);
643
644static void __exit uda134x_exit(void)
645{
646 snd_soc_unregister_dai(&uda134x_dai);
647}
648module_exit(uda134x_exit);
649
650MODULE_DESCRIPTION("UDA134X ALSA soc codec driver");
651MODULE_AUTHOR("Zoltan Devai, Christian Pellegrin <chripell@evolware.org>");
652MODULE_LICENSE("GPL");
653