04060d92d9993f4107c74b652bc94c2b398fb44e
[oweals/openwrt.git] /
1 From 649b1181f032801c12e17196618c032cdb3cb587 Mon Sep 17 00:00:00 2001
2 From: Raashid Muhammed <raashidmuhammed@zilogic.com>
3 Date: Mon, 27 Mar 2017 12:35:00 +0530
4 Subject: [PATCH 080/454] Add support for Allo Piano DAC 2.1 plus add-on board
5  for Raspberry Pi.
6
7 The Piano DAC 2.1 has support for 4 channels with subwoofer.
8
9 Signed-off-by: Baswaraj K <jaikumar@cem-solutions.net>
10 Reviewed-by: Vijay Kumar B. <vijaykumar@zilogic.com>
11 Reviewed-by: Raashid Muhammed <raashidmuhammed@zilogic.com>
12
13 Add clock changes and mute gpios (#1938)
14
15 Also improve code style and adhere to ALSA coding conventions.
16
17 Signed-off-by: Baswaraj K <jaikumar@cem-solutions.net>
18 Reviewed-by: Vijay Kumar B. <vijaykumar@zilogic.com>
19 Reviewed-by: Raashid Muhammed <raashidmuhammed@zilogic.com>
20
21 PianoPlus: Dual Mono & Dual Stereo features added (#2069)
22
23 allo-piano-dac-plus: Master volume added + fixes
24
25 Master volume added, which controls both DACs volumes.
26
27 See: https://github.com/raspberrypi/linux/pull/2149
28
29 Also fix initial max volume, default mode value, and unmute.
30
31 Signed-off-by: allocom <sparky-dev@allo.com>
32 ---
33  sound/soc/bcm/Kconfig               |    7 +
34  sound/soc/bcm/Makefile              |    2 +
35  sound/soc/bcm/allo-piano-dac-plus.c | 1014 +++++++++++++++++++++++++++
36  3 files changed, 1023 insertions(+)
37  create mode 100644 sound/soc/bcm/allo-piano-dac-plus.c
38
39 --- a/sound/soc/bcm/Kconfig
40 +++ b/sound/soc/bcm/Kconfig
41 @@ -131,3 +131,10 @@ config SND_BCM2708_SOC_ALLO_PIANO_DAC
42         select SND_SOC_PCM512x_I2C
43         help
44           Say Y or M if you want to add support for Allo Piano DAC.
45 +
46 +config SND_BCM2708_SOC_ALLO_PIANO_DAC_PLUS
47 +       tristate "Support for Allo Piano DAC Plus"
48 +       depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
49 +       select SND_SOC_PCM512x_I2C
50 +       help
51 +         Say Y or M if you want to add support for Allo Piano DAC Plus.
52 --- a/sound/soc/bcm/Makefile
53 +++ b/sound/soc/bcm/Makefile
54 @@ -25,6 +25,7 @@ snd-soc-audioinjector-pi-soundcard-objs
55  snd-soc-digidac1-soundcard-objs := digidac1-soundcard.o
56  snd-soc-dionaudio-loco-objs := dionaudio_loco.o
57  snd-soc-allo-piano-dac-objs := allo-piano-dac.o
58 +snd-soc-allo-piano-dac-plus-objs := allo-piano-dac-plus.o
59  
60  obj-$(CONFIG_SND_BCM2708_SOC_ADAU1977_ADC) += snd-soc-adau1977-adc.o
61  obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP) += snd-soc-hifiberry-amp.o
62 @@ -42,3 +43,4 @@ obj-$(CONFIG_SND_AUDIOINJECTOR_PI_SOUNDC
63  obj-$(CONFIG_SND_DIGIDAC1_SOUNDCARD) += snd-soc-digidac1-soundcard.o
64  obj-$(CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO) += snd-soc-dionaudio-loco.o
65  obj-$(CONFIG_SND_BCM2708_SOC_ALLO_PIANO_DAC) += snd-soc-allo-piano-dac.o
66 +obj-$(CONFIG_SND_BCM2708_SOC_ALLO_PIANO_DAC_PLUS) += snd-soc-allo-piano-dac-plus.o
67 --- /dev/null
68 +++ b/sound/soc/bcm/allo-piano-dac-plus.c
69 @@ -0,0 +1,1014 @@
70 +/*
71 + * ALSA ASoC Machine Driver for Allo Piano DAC Plus Subwoofer
72 + *
73 + * Author:     Baswaraj K <jaikumar@cem-solutions.net>
74 + *             Copyright 2016
75 + *             based on code by Daniel Matuschek <info@crazy-audio.com>
76 + *             based on code by Florian Meier <florian.meier@koalo.de>
77 + *
78 + * This program is free software; you can redistribute it and/or
79 + * modify it under the terms of the GNU General Public License
80 + * version 2 as published by the Free Software Foundation.
81 + *
82 + * This program is distributed in the hope that it will be useful, but
83 + * WITHOUT ANY WARRANTY; without even the implied warranty of
84 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
85 + * General Public License for more details.
86 + */
87 +
88 +#include <linux/module.h>
89 +#include <linux/platform_device.h>
90 +#include <linux/gpio/consumer.h>
91 +#include <sound/core.h>
92 +#include <sound/pcm.h>
93 +#include <sound/pcm_params.h>
94 +#include <sound/soc.h>
95 +#include <linux/firmware.h>
96 +#include <linux/delay.h>
97 +#include <sound/tlv.h>
98 +#include "../codecs/pcm512x.h"
99 +
100 +#define P_DAC_LEFT_MUTE                0x10
101 +#define P_DAC_RIGHT_MUTE       0x01
102 +#define P_DAC_MUTE             0x11
103 +#define P_DAC_UNMUTE           0x00
104 +#define P_MUTE                 1
105 +#define P_UNMUTE               0
106 +
107 +struct dsp_code {
108 +       char i2c_addr;
109 +       char offset;
110 +       char val;
111 +};
112 +
113 +struct glb_pool {
114 +       struct mutex lock;
115 +       unsigned int dual_mode;
116 +       unsigned int set_lowpass;
117 +       unsigned int set_mode;
118 +       unsigned int set_rate;
119 +       unsigned int dsp_page_number;
120 +};
121 +
122 +static bool digital_gain_0db_limit = true;
123 +bool glb_mclk;
124 +
125 +static struct gpio_desc *mute_gpio[2];
126 +
127 +static const char * const allo_piano_mode_texts[] = {
128 +       "None",
129 +       "2.0",
130 +       "2.1",
131 +       "2.2",
132 +};
133 +
134 +static const SOC_ENUM_SINGLE_DECL(allo_piano_mode_enum,
135 +               0, 0, allo_piano_mode_texts);
136 +
137 +static const char * const allo_piano_dual_mode_texts[] = {
138 +       "None",
139 +       "Dual-Mono",
140 +       "Dual-Stereo",
141 +};
142 +
143 +static const SOC_ENUM_SINGLE_DECL(allo_piano_dual_mode_enum,
144 +               0, 0, allo_piano_dual_mode_texts);
145 +
146 +static const char * const allo_piano_dsp_low_pass_texts[] = {
147 +       "60",
148 +       "70",
149 +       "80",
150 +       "90",
151 +       "100",
152 +       "110",
153 +       "120",
154 +       "130",
155 +       "140",
156 +       "150",
157 +       "160",
158 +       "170",
159 +       "180",
160 +       "190",
161 +       "200",
162 +};
163 +
164 +static const SOC_ENUM_SINGLE_DECL(allo_piano_enum,
165 +               0, 0, allo_piano_dsp_low_pass_texts);
166 +
167 +static int __snd_allo_piano_dsp_program(struct snd_soc_pcm_runtime *rtd,
168 +               unsigned int mode, unsigned int rate, unsigned int lowpass)
169 +{
170 +       const struct firmware *fw;
171 +       struct snd_soc_card *card = rtd->card;
172 +       struct glb_pool *glb_ptr = card->drvdata;
173 +       char firmware_name[60];
174 +       int ret = 0, dac = 0;
175 +
176 +       if (rate <= 46000)
177 +               rate = 44100;
178 +       else if (rate <= 68000)
179 +               rate = 48000;
180 +       else if (rate <= 92000)
181 +               rate = 88200;
182 +       else if (rate <= 136000)
183 +               rate = 96000;
184 +       else if (rate <= 184000)
185 +               rate = 176400;
186 +       else
187 +               rate = 192000;
188 +
189 +       if (lowpass > 14)
190 +               glb_ptr->set_lowpass = lowpass = 0;
191 +
192 +       if (mode > 3)
193 +               glb_ptr->set_mode = mode = 0;
194 +
195 +       if (mode > 0)
196 +               glb_ptr->dual_mode = 0;
197 +
198 +       /* same configuration loaded */
199 +       if ((rate == glb_ptr->set_rate) && (lowpass == glb_ptr->set_lowpass)
200 +                       && (mode == glb_ptr->set_mode))
201 +               return 0;
202 +
203 +       switch (mode) {
204 +       case 0: /* None */
205 +               return 1;
206 +
207 +       case 1: /* 2.0 */
208 +               snd_soc_write(rtd->codec_dais[0]->codec,
209 +                               PCM512x_MUTE, P_DAC_UNMUTE);
210 +               snd_soc_write(rtd->codec_dais[1]->codec,
211 +                               PCM512x_MUTE, P_DAC_MUTE);
212 +               glb_ptr->set_rate = rate;
213 +               glb_ptr->set_mode = mode;
214 +               glb_ptr->set_lowpass = lowpass;
215 +               return 1;
216 +
217 +       default:
218 +               snd_soc_write(rtd->codec_dais[0]->codec,
219 +                               PCM512x_MUTE, P_DAC_UNMUTE);
220 +               snd_soc_write(rtd->codec_dais[1]->codec,
221 +                               PCM512x_MUTE, P_DAC_UNMUTE);
222 +       }
223 +
224 +       for (dac = 0; dac < rtd->num_codecs; dac++) {
225 +               struct dsp_code *dsp_code_read;
226 +               struct snd_soc_codec *codec = rtd->codec_dais[dac]->codec;
227 +               int i = 1;
228 +
229 +               if (dac == 0) { /* high */
230 +                       snprintf(firmware_name, sizeof(firmware_name),
231 +                               "allo/piano/2.2/allo-piano-dsp-%d-%d-%d.bin",
232 +                               rate, ((lowpass * 10) + 60), dac);
233 +               } else { /* low */
234 +                       snprintf(firmware_name, sizeof(firmware_name),
235 +                               "allo/piano/2.%d/allo-piano-dsp-%d-%d-%d.bin",
236 +                               (mode - 1), rate, ((lowpass * 10) + 60), dac);
237 +               }
238 +
239 +               dev_info(codec->dev, "Dsp Firmware File Name: %s\n",
240 +                               firmware_name);
241 +
242 +               ret = request_firmware(&fw, firmware_name, codec->dev);
243 +               if (ret < 0) {
244 +                       dev_err(codec->dev,
245 +                               "Error: Allo Piano Firmware %s missing. %d\n",
246 +                               firmware_name, ret);
247 +                       goto err;
248 +               }
249 +
250 +               while (i < (fw->size - 1)) {
251 +                       dsp_code_read = (struct dsp_code *)&fw->data[i];
252 +
253 +                       if (dsp_code_read->offset == 0) {
254 +                               glb_ptr->dsp_page_number = dsp_code_read->val;
255 +                               ret = snd_soc_write(rtd->codec_dais[dac]->codec,
256 +                                               PCM512x_PAGE_BASE(0),
257 +                                               dsp_code_read->val);
258 +
259 +                       } else if (dsp_code_read->offset != 0) {
260 +                               ret = snd_soc_write(rtd->codec_dais[dac]->codec,
261 +                                       (PCM512x_PAGE_BASE(
262 +                                               glb_ptr->dsp_page_number) +
263 +                                       dsp_code_read->offset),
264 +                                       dsp_code_read->val);
265 +                       }
266 +                       if (ret < 0) {
267 +                               dev_err(codec->dev,
268 +                                       "Failed to write Register: %d\n", ret);
269 +                               release_firmware(fw);
270 +                               goto err;
271 +                       }
272 +                       i = i + 3;
273 +               }
274 +               release_firmware(fw);
275 +       }
276 +       glb_ptr->set_rate = rate;
277 +       glb_ptr->set_mode = mode;
278 +       glb_ptr->set_lowpass = lowpass;
279 +       return 1;
280 +
281 +err:
282 +       return ret;
283 +}
284 +
285 +static int snd_allo_piano_dsp_program(struct snd_soc_pcm_runtime *rtd,
286 +               unsigned int mode, unsigned int rate, unsigned int lowpass)
287 +{
288 +       struct snd_soc_card *card = rtd->card;
289 +       struct glb_pool *glb_ptr = card->drvdata;
290 +       int ret = 0;
291 +
292 +       mutex_lock(&glb_ptr->lock);
293 +
294 +       ret = __snd_allo_piano_dsp_program(rtd, mode, rate, lowpass);
295 +
296 +       mutex_unlock(&glb_ptr->lock);
297 +
298 +       return ret;
299 +}
300 +
301 +static int snd_allo_piano_dual_mode_get(struct snd_kcontrol *kcontrol,
302 +               struct snd_ctl_elem_value *ucontrol)
303 +{
304 +       struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
305 +       struct glb_pool *glb_ptr = card->drvdata;
306 +
307 +       ucontrol->value.integer.value[0] = glb_ptr->dual_mode;
308 +
309 +       return 0;
310 +}
311 +
312 +static int snd_allo_piano_dual_mode_put(struct snd_kcontrol *kcontrol,
313 +               struct snd_ctl_elem_value *ucontrol)
314 +{
315 +       struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
316 +       struct glb_pool *glb_ptr = card->drvdata;
317 +       struct snd_soc_pcm_runtime *rtd;
318 +       struct snd_card *snd_card_ptr = card->snd_card;
319 +       struct snd_kcontrol *kctl;
320 +       struct soc_mixer_control *mc;
321 +       unsigned int left_val = 0, right_val = 0;
322 +
323 +       rtd = snd_soc_get_pcm_runtime(card, card->dai_link[0].name);
324 +
325 +       if (ucontrol->value.integer.value[0] > 0) {
326 +               glb_ptr->dual_mode = ucontrol->value.integer.value[0];
327 +               glb_ptr->set_mode = 0;
328 +       } else {
329 +               if (glb_ptr->set_mode <= 0) {
330 +                       glb_ptr->dual_mode = 1;
331 +                       glb_ptr->set_mode = 0;
332 +               } else {
333 +                       glb_ptr->dual_mode = 0;
334 +                       return 0;
335 +               }
336 +       }
337 +
338 +       if (glb_ptr->dual_mode == 1) { // Dual Mono
339 +               snd_soc_write(rtd->codec_dais[0]->codec,
340 +                               PCM512x_MUTE, P_DAC_RIGHT_MUTE);
341 +               snd_soc_write(rtd->codec_dais[1]->codec,
342 +                               PCM512x_MUTE, P_DAC_LEFT_MUTE);
343 +               snd_soc_write(rtd->codec_dais[0]->codec,
344 +                               PCM512x_DIGITAL_VOLUME_3, 0xff);
345 +               snd_soc_write(rtd->codec_dais[1]->codec,
346 +                               PCM512x_DIGITAL_VOLUME_2, 0xff);
347 +
348 +               list_for_each_entry(kctl, &snd_card_ptr->controls, list) {
349 +                       if (!strncmp(kctl->id.name, "Digital Playback Volume",
350 +                                       sizeof(kctl->id.name))) {
351 +                               mc = (struct soc_mixer_control *)
352 +                                       kctl->private_value;
353 +                               mc->rreg = mc->reg;
354 +                               break;
355 +                       }
356 +               }
357 +       } else {
358 +               left_val = snd_soc_read(rtd->codec_dais[0]->codec,
359 +                                               PCM512x_DIGITAL_VOLUME_2);
360 +               right_val = snd_soc_read(rtd->codec_dais[1]->codec,
361 +                                               PCM512x_DIGITAL_VOLUME_3);
362 +
363 +               list_for_each_entry(kctl, &snd_card_ptr->controls, list) {
364 +                       if (!strncmp(kctl->id.name, "Digital Playback Volume",
365 +                                       sizeof(kctl->id.name))) {
366 +                               mc = (struct soc_mixer_control *)
367 +                                       kctl->private_value;
368 +                               mc->rreg = PCM512x_DIGITAL_VOLUME_3;
369 +                               break;
370 +                       }
371 +               }
372 +
373 +               snd_soc_write(rtd->codec_dais[0]->codec,
374 +                               PCM512x_DIGITAL_VOLUME_3, left_val);
375 +               snd_soc_write(rtd->codec_dais[1]->codec,
376 +                               PCM512x_DIGITAL_VOLUME_2, right_val);
377 +               snd_soc_write(rtd->codec_dais[0]->codec,
378 +                               PCM512x_MUTE, P_DAC_UNMUTE);
379 +               snd_soc_write(rtd->codec_dais[1]->codec,
380 +                               PCM512x_MUTE, P_DAC_UNMUTE);
381 +       }
382 +
383 +       return 0;
384 +}
385 +
386 +static int snd_allo_piano_mode_get(struct snd_kcontrol *kcontrol,
387 +               struct snd_ctl_elem_value *ucontrol)
388 +{
389 +       struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
390 +       struct glb_pool *glb_ptr = card->drvdata;
391 +
392 +       ucontrol->value.integer.value[0] = glb_ptr->set_mode;
393 +       return 0;
394 +}
395 +
396 +static int snd_allo_piano_mode_put(struct snd_kcontrol *kcontrol,
397 +               struct snd_ctl_elem_value *ucontrol)
398 +{
399 +       struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
400 +       struct snd_soc_pcm_runtime *rtd;
401 +       struct glb_pool *glb_ptr = card->drvdata;
402 +       struct snd_card *snd_card_ptr = card->snd_card;
403 +       struct snd_kcontrol *kctl;
404 +       struct soc_mixer_control *mc;
405 +       unsigned int left_val = 0, right_val = 0;
406 +
407 +       rtd = snd_soc_get_pcm_runtime(card, card->dai_link[0].name);
408 +
409 +       if ((glb_ptr->dual_mode == 1) &&
410 +                       (ucontrol->value.integer.value[0] > 0)) {
411 +               left_val = snd_soc_read(rtd->codec_dais[0]->codec,
412 +                                               PCM512x_DIGITAL_VOLUME_2);
413 +               right_val = snd_soc_read(rtd->codec_dais[1]->codec,
414 +                                               PCM512x_DIGITAL_VOLUME_2);
415 +
416 +               list_for_each_entry(kctl, &snd_card_ptr->controls, list) {
417 +                       if (!strncmp(kctl->id.name, "Digital Playback Volume",
418 +                                       sizeof(kctl->id.name))) {
419 +                               mc = (struct soc_mixer_control *)
420 +                                       kctl->private_value;
421 +                               mc->rreg = PCM512x_DIGITAL_VOLUME_3;
422 +                               break;
423 +                       }
424 +               }
425 +               snd_soc_write(rtd->codec_dais[0]->codec,
426 +                               PCM512x_DIGITAL_VOLUME_3, left_val);
427 +               snd_soc_write(rtd->codec_dais[1]->codec,
428 +                               PCM512x_DIGITAL_VOLUME_3, right_val);
429 +       }
430 +
431 +       return(snd_allo_piano_dsp_program(rtd,
432 +                               ucontrol->value.integer.value[0],
433 +                               glb_ptr->set_rate, glb_ptr->set_lowpass));
434 +}
435 +
436 +static int snd_allo_piano_lowpass_get(struct snd_kcontrol *kcontrol,
437 +               struct snd_ctl_elem_value *ucontrol)
438 +{
439 +       struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
440 +       struct glb_pool *glb_ptr = card->drvdata;
441 +
442 +       ucontrol->value.integer.value[0] = glb_ptr->set_lowpass;
443 +       return 0;
444 +}
445 +
446 +static int snd_allo_piano_lowpass_put(struct snd_kcontrol *kcontrol,
447 +               struct snd_ctl_elem_value *ucontrol)
448 +{
449 +       struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
450 +       struct snd_soc_pcm_runtime *rtd;
451 +       struct glb_pool *glb_ptr = card->drvdata;
452 +
453 +       rtd = snd_soc_get_pcm_runtime(card, card->dai_link[0].name);
454 +       return(snd_allo_piano_dsp_program(rtd,
455 +                               glb_ptr->set_mode, glb_ptr->set_rate,
456 +                               ucontrol->value.integer.value[0]));
457 +}
458 +
459 +static int pcm512x_get_reg_sub(struct snd_kcontrol *kcontrol,
460 +               struct snd_ctl_elem_value *ucontrol)
461 +{
462 +       struct soc_mixer_control *mc =
463 +               (struct soc_mixer_control *)kcontrol->private_value;
464 +       struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
465 +       struct glb_pool *glb_ptr = card->drvdata;
466 +       struct snd_soc_pcm_runtime *rtd;
467 +       unsigned int left_val = 0;
468 +       unsigned int right_val = 0;
469 +
470 +       rtd = snd_soc_get_pcm_runtime(card, card->dai_link[0].name);
471 +       right_val = snd_soc_read(rtd->codec_dais[1]->codec,
472 +                       PCM512x_DIGITAL_VOLUME_3);
473 +       if (right_val < 0)
474 +               return right_val;
475 +
476 +       if (glb_ptr->dual_mode != 1) {
477 +               left_val = snd_soc_read(rtd->codec_dais[1]->codec,
478 +                               PCM512x_DIGITAL_VOLUME_2);
479 +               if (left_val < 0)
480 +                       return left_val;
481 +
482 +       } else {
483 +               left_val = right_val;
484 +       }
485 +
486 +       ucontrol->value.integer.value[0] =
487 +                               (~(left_val >> mc->shift)) & mc->max;
488 +       ucontrol->value.integer.value[1] =
489 +                               (~(right_val >> mc->shift)) & mc->max;
490 +
491 +       return 0;
492 +}
493 +
494 +static int pcm512x_set_reg_sub(struct snd_kcontrol *kcontrol,
495 +               struct snd_ctl_elem_value *ucontrol)
496 +{
497 +       struct soc_mixer_control *mc =
498 +               (struct soc_mixer_control *)kcontrol->private_value;
499 +       struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
500 +       struct glb_pool *glb_ptr = card->drvdata;
501 +       struct snd_soc_pcm_runtime *rtd;
502 +       unsigned int left_val = (ucontrol->value.integer.value[0] & mc->max);
503 +       unsigned int right_val = (ucontrol->value.integer.value[1] & mc->max);
504 +       int ret = 0;
505 +
506 +       rtd = snd_soc_get_pcm_runtime(card, card->dai_link[0].name);
507 +       if (glb_ptr->dual_mode != 1) {
508 +               ret = snd_soc_write(rtd->codec_dais[1]->codec,
509 +                               PCM512x_DIGITAL_VOLUME_2, (~left_val));
510 +               if (ret < 0)
511 +                       return ret;
512 +       }
513 +
514 +       if (digital_gain_0db_limit) {
515 +               ret = snd_soc_limit_volume(card, "Subwoofer Playback Volume",
516 +                                       207);
517 +               if (ret < 0)
518 +                       dev_warn(card->dev, "Failed to set volume limit: %d\n",
519 +                               ret);
520 +       }
521 +
522 +       ret = snd_soc_write(rtd->codec_dais[1]->codec,
523 +                       PCM512x_DIGITAL_VOLUME_3, (~right_val));
524 +       if (ret < 0)
525 +               return ret;
526 +
527 +       return 1;
528 +}
529 +
530 +static int pcm512x_get_reg_sub_switch(struct snd_kcontrol *kcontrol,
531 +               struct snd_ctl_elem_value *ucontrol)
532 +{
533 +       struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
534 +       struct snd_soc_pcm_runtime *rtd;
535 +       int val = 0;
536 +
537 +       rtd = snd_soc_get_pcm_runtime(card, card->dai_link[0].name);
538 +       val = snd_soc_read(rtd->codec_dais[1]->codec, PCM512x_MUTE);
539 +       if (val < 0)
540 +               return val;
541 +
542 +       ucontrol->value.integer.value[0] =
543 +                       (val & P_DAC_LEFT_MUTE) ? P_UNMUTE : P_MUTE;
544 +       ucontrol->value.integer.value[1] =
545 +                       (val & P_DAC_RIGHT_MUTE) ? P_UNMUTE : P_MUTE;
546 +
547 +       return val;
548 +}
549 +
550 +static int pcm512x_set_reg_sub_switch(struct snd_kcontrol *kcontrol,
551 +               struct snd_ctl_elem_value *ucontrol)
552 +{
553 +       struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
554 +       struct snd_soc_pcm_runtime *rtd;
555 +       struct glb_pool *glb_ptr = card->drvdata;
556 +       unsigned int left_val = (ucontrol->value.integer.value[0]);
557 +       unsigned int right_val = (ucontrol->value.integer.value[1]);
558 +       int ret = 0;
559 +
560 +       rtd = snd_soc_get_pcm_runtime(card, card->dai_link[0].name);
561 +       if (glb_ptr->set_mode != 1) {
562 +               ret = snd_soc_write(rtd->codec_dais[1]->codec, PCM512x_MUTE,
563 +                               ~((left_val & 0x01)<<4 | (right_val & 0x01)));
564 +               if (ret < 0)
565 +                       return ret;
566 +       }
567 +       return 1;
568 +
569 +}
570 +
571 +static int pcm512x_get_reg_master(struct snd_kcontrol *kcontrol,
572 +               struct snd_ctl_elem_value *ucontrol)
573 +{
574 +       struct soc_mixer_control *mc =
575 +               (struct soc_mixer_control *)kcontrol->private_value;
576 +       struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
577 +       struct glb_pool *glb_ptr = card->drvdata;
578 +       struct snd_soc_pcm_runtime *rtd;
579 +       unsigned int left_val = 0, right_val = 0;
580 +
581 +       rtd = snd_soc_get_pcm_runtime(card, card->dai_link[0].name);
582 +
583 +       left_val = snd_soc_read(rtd->codec_dais[0]->codec,
584 +                       PCM512x_DIGITAL_VOLUME_2);
585 +       if (left_val < 0)
586 +               return left_val;
587 +
588 +       if (glb_ptr->dual_mode == 1) {
589 +               right_val = snd_soc_read(rtd->codec_dais[1]->codec,
590 +                               PCM512x_DIGITAL_VOLUME_3);
591 +               if (right_val < 0)
592 +                       return right_val;
593 +       } else {
594 +               right_val = snd_soc_read(rtd->codec_dais[0]->codec,
595 +                               PCM512x_DIGITAL_VOLUME_3);
596 +               if (right_val < 0)
597 +                       return right_val;
598 +       }
599 +
600 +       ucontrol->value.integer.value[0] =
601 +               (~(left_val  >> mc->shift)) & mc->max;
602 +       ucontrol->value.integer.value[1] =
603 +               (~(right_val >> mc->shift)) & mc->max;
604 +
605 +       return 0;
606 +}
607 +
608 +static int pcm512x_set_reg_master(struct snd_kcontrol *kcontrol,
609 +               struct snd_ctl_elem_value *ucontrol)
610 +{
611 +       struct soc_mixer_control *mc =
612 +               (struct soc_mixer_control *)kcontrol->private_value;
613 +       struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
614 +       struct glb_pool *glb_ptr = card->drvdata;
615 +       struct snd_soc_pcm_runtime *rtd;
616 +       unsigned int left_val = (ucontrol->value.integer.value[0] & mc->max);
617 +       unsigned int right_val = (ucontrol->value.integer.value[1] & mc->max);
618 +       int ret = 0;
619 +
620 +       rtd = snd_soc_get_pcm_runtime(card, card->dai_link[0].name);
621 +
622 +       if (digital_gain_0db_limit) {
623 +               ret = snd_soc_limit_volume(card, "Master Playback Volume",
624 +                                       207);
625 +               if (ret < 0)
626 +                       dev_warn(card->dev, "Failed to set volume limit: %d\n",
627 +                               ret);
628 +       }
629 +
630 +       if (glb_ptr->dual_mode != 1) {
631 +               ret = snd_soc_write(rtd->codec_dais[1]->codec,
632 +                               PCM512x_DIGITAL_VOLUME_2, (~left_val));
633 +               if (ret < 0)
634 +                       return ret;
635 +
636 +               ret = snd_soc_write(rtd->codec_dais[0]->codec,
637 +                               PCM512x_DIGITAL_VOLUME_3, (~right_val));
638 +               if (ret < 0)
639 +                       return ret;
640 +
641 +       }
642 +
643 +       ret = snd_soc_write(rtd->codec_dais[1]->codec,
644 +                       PCM512x_DIGITAL_VOLUME_3, (~right_val));
645 +       if (ret < 0)
646 +               return ret;
647 +
648 +       ret = snd_soc_write(rtd->codec_dais[0]->codec,
649 +                       PCM512x_DIGITAL_VOLUME_2, (~left_val));
650 +       if (ret < 0)
651 +               return ret;
652 +       return 1;
653 +}
654 +
655 +static int pcm512x_get_reg_master_switch(struct snd_kcontrol *kcontrol,
656 +               struct snd_ctl_elem_value *ucontrol)
657 +{
658 +       struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
659 +       struct glb_pool *glb_ptr = card->drvdata;
660 +       struct snd_soc_pcm_runtime *rtd;
661 +       int val = 0;
662 +
663 +       rtd = snd_soc_get_pcm_runtime(card, card->dai_link[0].name);
664 +
665 +       val = snd_soc_read(rtd->codec_dais[0]->codec, PCM512x_MUTE);
666 +       if (val < 0)
667 +               return val;
668 +
669 +       ucontrol->value.integer.value[0] =
670 +                       (val & P_DAC_LEFT_MUTE) ? P_UNMUTE : P_MUTE;
671 +
672 +       if (glb_ptr->dual_mode == 1) {
673 +               val = snd_soc_read(rtd->codec_dais[1]->codec, PCM512x_MUTE);
674 +               if (val < 0)
675 +                       return val;
676 +       }
677 +       ucontrol->value.integer.value[1] =
678 +                       (val & P_DAC_RIGHT_MUTE) ? P_UNMUTE : P_MUTE;
679 +
680 +       return val;
681 +}
682 +
683 +static int pcm512x_set_reg_master_switch(struct snd_kcontrol *kcontrol,
684 +               struct snd_ctl_elem_value *ucontrol)
685 +{
686 +       struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
687 +       struct snd_soc_pcm_runtime *rtd;
688 +       struct glb_pool *glb_ptr = card->drvdata;
689 +       unsigned int left_val = (ucontrol->value.integer.value[0]);
690 +       unsigned int right_val = (ucontrol->value.integer.value[1]);
691 +       int ret = 0;
692 +
693 +       rtd = snd_soc_get_pcm_runtime(card, card->dai_link[0].name);
694 +       if (glb_ptr->dual_mode == 1) {
695 +               ret = snd_soc_write(rtd->codec_dais[0]->codec, PCM512x_MUTE,
696 +                               ~((left_val & 0x01)<<4));
697 +               if (ret < 0)
698 +                       return ret;
699 +               ret = snd_soc_write(rtd->codec_dais[1]->codec, PCM512x_MUTE,
700 +                               ~((right_val & 0x01)));
701 +               if (ret < 0)
702 +                       return ret;
703 +
704 +       } else if (glb_ptr->set_mode == 1) {
705 +               ret = snd_soc_write(rtd->codec_dais[0]->codec, PCM512x_MUTE,
706 +                               ~((left_val & 0x01)<<4 | (right_val & 0x01)));
707 +               if (ret < 0)
708 +                       return ret;
709 +
710 +       } else {
711 +               ret = snd_soc_write(rtd->codec_dais[0]->codec, PCM512x_MUTE,
712 +                               ~((left_val & 0x01)<<4 | (right_val & 0x01)));
713 +               if (ret < 0)
714 +                       return ret;
715 +
716 +               ret = snd_soc_write(rtd->codec_dais[1]->codec, PCM512x_MUTE,
717 +                               ~((left_val & 0x01)<<4 | (right_val & 0x01)));
718 +               if (ret < 0)
719 +                       return ret;
720 +       }
721 +       return 1;
722 +}
723 +
724 +static const DECLARE_TLV_DB_SCALE(digital_tlv_sub, -10350, 50, 1);
725 +static const DECLARE_TLV_DB_SCALE(digital_tlv_master, -10350, 50, 1);
726 +
727 +static const struct snd_kcontrol_new allo_piano_controls[] = {
728 +       SOC_ENUM_EXT("Subwoofer mode Route",
729 +                       allo_piano_mode_enum,
730 +                       snd_allo_piano_mode_get,
731 +                       snd_allo_piano_mode_put),
732 +
733 +       SOC_ENUM_EXT("Dual Mode Route",
734 +                       allo_piano_dual_mode_enum,
735 +                       snd_allo_piano_dual_mode_get,
736 +                       snd_allo_piano_dual_mode_put),
737 +
738 +       SOC_ENUM_EXT("Lowpass Route", allo_piano_enum,
739 +                       snd_allo_piano_lowpass_get,
740 +                       snd_allo_piano_lowpass_put),
741 +
742 +       SOC_DOUBLE_R_EXT_TLV("Subwoofer Playback Volume",
743 +                       PCM512x_DIGITAL_VOLUME_2,
744 +                       PCM512x_DIGITAL_VOLUME_3, 0, 255, 1,
745 +                       pcm512x_get_reg_sub,
746 +                       pcm512x_set_reg_sub,
747 +                       digital_tlv_sub),
748 +
749 +       SOC_DOUBLE_EXT("Subwoofer Playback Switch",
750 +                       PCM512x_MUTE,
751 +                       PCM512x_RQML_SHIFT,
752 +                       PCM512x_RQMR_SHIFT, 1, 1,
753 +                       pcm512x_get_reg_sub_switch,
754 +                       pcm512x_set_reg_sub_switch),
755 +
756 +       SOC_DOUBLE_R_EXT_TLV("Master Playback Volume",
757 +                       PCM512x_DIGITAL_VOLUME_2,
758 +                       PCM512x_DIGITAL_VOLUME_3, 0, 255, 1,
759 +                       pcm512x_get_reg_master,
760 +                       pcm512x_set_reg_master,
761 +                       digital_tlv_master),
762 +
763 +       SOC_DOUBLE_EXT("Master Playback Switch",
764 +                       PCM512x_MUTE,
765 +                       PCM512x_RQML_SHIFT,
766 +                       PCM512x_RQMR_SHIFT, 1, 1,
767 +                       pcm512x_get_reg_master_switch,
768 +                       pcm512x_set_reg_master_switch),
769 +};
770 +
771 +static int snd_allo_piano_dac_init(struct snd_soc_pcm_runtime *rtd)
772 +{
773 +       struct snd_soc_card *card = rtd->card;
774 +       struct glb_pool *glb_ptr;
775 +
776 +       glb_ptr = kmalloc(sizeof(struct glb_pool), GFP_KERNEL);
777 +       if (!glb_ptr)
778 +               return -ENOMEM;
779 +
780 +       memset(glb_ptr, 0x00, sizeof(glb_ptr));
781 +       card->drvdata = glb_ptr;
782 +       glb_ptr->dual_mode = 2;
783 +       glb_ptr->set_mode = 0;
784 +
785 +       mutex_init(&glb_ptr->lock);
786 +
787 +       if (digital_gain_0db_limit) {
788 +               int ret;
789 +
790 +               ret = snd_soc_limit_volume(card, "Digital Playback Volume",
791 +                                       207);
792 +               if (ret < 0)
793 +                       dev_warn(card->dev, "Failed to set volume limit: %d\n",
794 +                               ret);
795 +       }
796 +       return 0;
797 +}
798 +
799 +static void snd_allo_piano_gpio_mute(struct snd_soc_card *card)
800 +{
801 +       if (mute_gpio[0])
802 +               gpiod_set_value_cansleep(mute_gpio[0], P_MUTE);
803 +
804 +       if (mute_gpio[1])
805 +               gpiod_set_value_cansleep(mute_gpio[1], P_MUTE);
806 +}
807 +
808 +static void snd_allo_piano_gpio_unmute(struct snd_soc_card *card)
809 +{
810 +       if (mute_gpio[0])
811 +               gpiod_set_value_cansleep(mute_gpio[0], P_UNMUTE);
812 +
813 +       if (mute_gpio[1])
814 +               gpiod_set_value_cansleep(mute_gpio[1], P_UNMUTE);
815 +}
816 +
817 +static int snd_allo_piano_set_bias_level(struct snd_soc_card *card,
818 +       struct snd_soc_dapm_context *dapm, enum snd_soc_bias_level level)
819 +{
820 +       struct snd_soc_pcm_runtime *rtd;
821 +       struct snd_soc_dai *codec_dai;
822 +
823 +       rtd = snd_soc_get_pcm_runtime(card, card->dai_link[0].name);
824 +       codec_dai = rtd->codec_dai;
825 +
826 +       if (dapm->dev != codec_dai->dev)
827 +               return 0;
828 +
829 +       switch (level) {
830 +       case SND_SOC_BIAS_PREPARE:
831 +               if (dapm->bias_level != SND_SOC_BIAS_STANDBY)
832 +                       break;
833 +               /* UNMUTE DAC */
834 +               snd_allo_piano_gpio_unmute(card);
835 +               break;
836 +
837 +       case SND_SOC_BIAS_STANDBY:
838 +               if (dapm->bias_level != SND_SOC_BIAS_PREPARE)
839 +                       break;
840 +               /* MUTE DAC */
841 +               snd_allo_piano_gpio_mute(card);
842 +               break;
843 +
844 +       default:
845 +               break;
846 +       }
847 +
848 +       return 0;
849 +}
850 +
851 +static int snd_allo_piano_dac_startup(
852 +       struct snd_pcm_substream *substream)
853 +{
854 +       struct snd_soc_pcm_runtime *rtd = substream->private_data;
855 +       struct snd_soc_card *card = rtd->card;
856 +
857 +       snd_allo_piano_gpio_mute(card);
858 +
859 +       return 0;
860 +}
861 +
862 +static int snd_allo_piano_dac_hw_params(
863 +               struct snd_pcm_substream *substream,
864 +               struct snd_pcm_hw_params *params)
865 +{
866 +       struct snd_soc_pcm_runtime *rtd = substream->private_data;
867 +       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
868 +       unsigned int sample_bits =
869 +               snd_pcm_format_physical_width(params_format(params));
870 +       unsigned int rate = params_rate(params);
871 +       struct snd_soc_card *card = rtd->card;
872 +       struct glb_pool *glb_ptr = card->drvdata;
873 +       int ret = 0, val = 0, dac;
874 +
875 +       for (dac = 0; (glb_mclk && dac < 2); dac++) {
876 +               /* Configure the PLL clock reference for both the Codecs */
877 +               val = snd_soc_read(rtd->codec_dais[dac]->codec,
878 +                                       PCM512x_RATE_DET_4);
879 +               if (val < 0) {
880 +                       dev_err(rtd->codec_dais[dac]->codec->dev,
881 +                               "Failed to read register PCM512x_RATE_DET_4\n");
882 +                       return val;
883 +               }
884 +
885 +               if (val & 0x40) {
886 +                       snd_soc_write(rtd->codec_dais[dac]->codec,
887 +                                       PCM512x_PLL_REF,
888 +                                       PCM512x_SREF_BCK);
889 +
890 +                       dev_info(rtd->codec_dais[dac]->codec->dev,
891 +                               "Setting BCLK as input clock & Enable PLL\n");
892 +               } else {
893 +                       snd_soc_write(rtd->codec_dais[dac]->codec,
894 +                                       PCM512x_PLL_EN,
895 +                                       0x00);
896 +
897 +                       snd_soc_write(rtd->codec_dais[dac]->codec,
898 +                                       PCM512x_PLL_REF,
899 +                                       PCM512x_SREF_SCK);
900 +
901 +                       dev_info(rtd->codec_dais[dac]->codec->dev,
902 +                               "Setting SCLK as input clock & disabled PLL\n");
903 +               }
904 +       }
905 +
906 +       ret = snd_allo_piano_dsp_program(rtd, glb_ptr->set_mode, rate,
907 +                                               glb_ptr->set_lowpass);
908 +       if (ret < 0)
909 +               return ret;
910 +
911 +       ret = snd_soc_dai_set_bclk_ratio(cpu_dai, sample_bits * 2);
912 +
913 +       return ret;
914 +}
915 +
916 +static int snd_allo_piano_dac_prepare(
917 +       struct snd_pcm_substream *substream)
918 +{
919 +       struct snd_soc_pcm_runtime *rtd = substream->private_data;
920 +       struct snd_soc_card *card = rtd->card;
921 +
922 +       snd_allo_piano_gpio_unmute(card);
923 +
924 +       return 0;
925 +}
926 +
927 +/* machine stream operations */
928 +static struct snd_soc_ops snd_allo_piano_dac_ops = {
929 +       .startup = snd_allo_piano_dac_startup,
930 +       .hw_params = snd_allo_piano_dac_hw_params,
931 +       .prepare = snd_allo_piano_dac_prepare,
932 +};
933 +
934 +static struct snd_soc_dai_link_component allo_piano_2_1_codecs[] = {
935 +       {
936 +               .dai_name = "pcm512x-hifi",
937 +       },
938 +       {
939 +               .dai_name = "pcm512x-hifi",
940 +       },
941 +};
942 +
943 +static struct snd_soc_dai_link snd_allo_piano_dac_dai[] = {
944 +       {
945 +               .name           = "PianoDACPlus",
946 +               .stream_name    = "PianoDACPlus",
947 +               .cpu_dai_name   = "bcm2708-i2s.0",
948 +               .platform_name  = "bcm2708-i2s.0",
949 +               .codecs         = allo_piano_2_1_codecs,
950 +               .num_codecs     = 2,
951 +               .dai_fmt        = SND_SOC_DAIFMT_I2S |
952 +                               SND_SOC_DAIFMT_NB_NF |
953 +                               SND_SOC_DAIFMT_CBS_CFS,
954 +               .ops            = &snd_allo_piano_dac_ops,
955 +               .init           = snd_allo_piano_dac_init,
956 +       },
957 +};
958 +
959 +/* audio machine driver */
960 +static struct snd_soc_card snd_allo_piano_dac = {
961 +       .name = "PianoDACPlus",
962 +       .owner = THIS_MODULE,
963 +       .dai_link = snd_allo_piano_dac_dai,
964 +       .num_links = ARRAY_SIZE(snd_allo_piano_dac_dai),
965 +       .controls = allo_piano_controls,
966 +       .num_controls = ARRAY_SIZE(allo_piano_controls),
967 +};
968 +
969 +static int snd_allo_piano_dac_probe(struct platform_device *pdev)
970 +{
971 +       struct snd_soc_card *card = &snd_allo_piano_dac;
972 +       int ret = 0, i = 0;
973 +
974 +       card->dev = &pdev->dev;
975 +       platform_set_drvdata(pdev, &snd_allo_piano_dac);
976 +
977 +       if (pdev->dev.of_node) {
978 +               struct device_node *i2s_node;
979 +               struct snd_soc_dai_link *dai;
980 +
981 +               dai = &snd_allo_piano_dac_dai[0];
982 +               i2s_node = of_parse_phandle(pdev->dev.of_node,
983 +                                               "i2s-controller", 0);
984 +               if (i2s_node) {
985 +                       for (i = 0; i < card->num_links; i++) {
986 +                               dai->cpu_dai_name = NULL;
987 +                               dai->cpu_of_node = i2s_node;
988 +                               dai->platform_name = NULL;
989 +                               dai->platform_of_node = i2s_node;
990 +                       }
991 +               }
992 +               digital_gain_0db_limit =
993 +                       !of_property_read_bool(pdev->dev.of_node,
994 +                                               "allo,24db_digital_gain");
995 +
996 +               glb_mclk = of_property_read_bool(pdev->dev.of_node,
997 +                                               "allo,glb_mclk");
998 +
999 +               allo_piano_2_1_codecs[0].of_node =
1000 +                       of_parse_phandle(pdev->dev.of_node, "audio-codec", 0);
1001 +               if (!allo_piano_2_1_codecs[0].of_node) {
1002 +                       dev_err(&pdev->dev,
1003 +                               "Property 'audio-codec' missing or invalid\n");
1004 +                       return -EINVAL;
1005 +               }
1006 +
1007 +               allo_piano_2_1_codecs[1].of_node =
1008 +                       of_parse_phandle(pdev->dev.of_node, "audio-codec", 1);
1009 +               if (!allo_piano_2_1_codecs[1].of_node) {
1010 +                       dev_err(&pdev->dev,
1011 +                               "Property 'audio-codec' missing or invalid\n");
1012 +                       return -EINVAL;
1013 +               }
1014 +
1015 +               mute_gpio[0] = devm_gpiod_get_optional(&pdev->dev, "mute1",
1016 +                                                       GPIOD_OUT_LOW);
1017 +               if (IS_ERR(mute_gpio[0])) {
1018 +                       ret = PTR_ERR(mute_gpio[0]);
1019 +                       dev_err(&pdev->dev,
1020 +                               "failed to get mute1 gpio6: %d\n", ret);
1021 +                       return ret;
1022 +               }
1023 +
1024 +               mute_gpio[1] = devm_gpiod_get_optional(&pdev->dev, "mute2",
1025 +                                                       GPIOD_OUT_LOW);
1026 +               if (IS_ERR(mute_gpio[1])) {
1027 +                       ret = PTR_ERR(mute_gpio[1]);
1028 +                       dev_err(&pdev->dev,
1029 +                               "failed to get mute2 gpio25: %d\n", ret);
1030 +                       return ret;
1031 +               }
1032 +
1033 +               if (mute_gpio[0] && mute_gpio[1])
1034 +                       snd_allo_piano_dac.set_bias_level =
1035 +                               snd_allo_piano_set_bias_level;
1036 +
1037 +               ret = snd_soc_register_card(&snd_allo_piano_dac);
1038 +               if (ret < 0) {
1039 +                       dev_err(&pdev->dev,
1040 +                               "snd_soc_register_card() failed: %d\n", ret);
1041 +                       return ret;
1042 +               }
1043 +
1044 +               if ((mute_gpio[0]) && (mute_gpio[1]))
1045 +                       snd_allo_piano_gpio_mute(&snd_allo_piano_dac);
1046 +
1047 +               return 0;
1048 +       }
1049 +
1050 +       return -EINVAL;
1051 +}
1052 +
1053 +static int snd_allo_piano_dac_remove(struct platform_device *pdev)
1054 +{
1055 +       struct snd_soc_card *card = platform_get_drvdata(pdev);
1056 +
1057 +       kfree(&card->drvdata);
1058 +       snd_allo_piano_gpio_mute(&snd_allo_piano_dac);
1059 +       return snd_soc_unregister_card(&snd_allo_piano_dac);
1060 +}
1061 +
1062 +static const struct of_device_id snd_allo_piano_dac_of_match[] = {
1063 +       { .compatible = "allo,piano-dac-plus", },
1064 +       { /* sentinel */ },
1065 +};
1066 +
1067 +MODULE_DEVICE_TABLE(of, snd_allo_piano_dac_of_match);
1068 +
1069 +static struct platform_driver snd_allo_piano_dac_driver = {
1070 +       .driver = {
1071 +               .name = "snd-allo-piano-dac-plus",
1072 +               .owner = THIS_MODULE,
1073 +               .of_match_table = snd_allo_piano_dac_of_match,
1074 +       },
1075 +       .probe = snd_allo_piano_dac_probe,
1076 +       .remove = snd_allo_piano_dac_remove,
1077 +};
1078 +
1079 +module_platform_driver(snd_allo_piano_dac_driver);
1080 +
1081 +MODULE_AUTHOR("Baswaraj K <jaikumar@cem-solutions.net>");
1082 +MODULE_DESCRIPTION("ALSA ASoC Machine Driver for Allo Piano DAC Plus");
1083 +MODULE_LICENSE("GPL v2");