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