1 From 05f3d2f7b8c5711ba867434ee8cb43882e1523d8 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 076/782] Add support for Allo Piano DAC 2.1 plus add-on board
7 The Piano DAC 2.1 has support for 4 channels with subwoofer.
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>
13 Add clock changes and mute gpios (#1938)
15 Also improve code style and adhere to ALSA coding conventions.
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>
21 PianoPlus: Dual Mono & Dual Stereo features added (#2069)
23 allo-piano-dac-plus: Master volume added + fixes
25 Master volume added, which controls both DACs volumes.
27 See: https://github.com/raspberrypi/linux/pull/2149
29 Also fix initial max volume, default mode value, and unmute.
31 Signed-off-by: allocom <sparky-dev@allo.com>
33 ASoC: allo-piano-dac-plus: fix S24_LE format
35 Remove set_bclk_ratio call so 24-bit data is transmitted in
38 Signed-off-by: Matthias Reichl <hias@horus.com>
40 sound/soc/bcm/allo-piano-dac-plus.c | 1011 +++++++++++++++++++++++++++
41 1 file changed, 1011 insertions(+)
42 create mode 100644 sound/soc/bcm/allo-piano-dac-plus.c
45 +++ b/sound/soc/bcm/allo-piano-dac-plus.c
48 + * ALSA ASoC Machine Driver for Allo Piano DAC Plus Subwoofer
50 + * Author: Baswaraj K <jaikumar@cem-solutions.net>
52 + * based on code by Daniel Matuschek <info@crazy-audio.com>
53 + * based on code by Florian Meier <florian.meier@koalo.de>
55 + * This program is free software; you can redistribute it and/or
56 + * modify it under the terms of the GNU General Public License
57 + * version 2 as published by the Free Software Foundation.
59 + * This program is distributed in the hope that it will be useful, but
60 + * WITHOUT ANY WARRANTY; without even the implied warranty of
61 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
62 + * General Public License for more details.
65 +#include <linux/module.h>
66 +#include <linux/platform_device.h>
67 +#include <linux/gpio/consumer.h>
68 +#include <sound/core.h>
69 +#include <sound/pcm.h>
70 +#include <sound/pcm_params.h>
71 +#include <sound/soc.h>
72 +#include <linux/firmware.h>
73 +#include <linux/delay.h>
74 +#include <sound/tlv.h>
75 +#include "../codecs/pcm512x.h"
77 +#define P_DAC_LEFT_MUTE 0x10
78 +#define P_DAC_RIGHT_MUTE 0x01
79 +#define P_DAC_MUTE 0x11
80 +#define P_DAC_UNMUTE 0x00
92 + unsigned int dual_mode;
93 + unsigned int set_lowpass;
94 + unsigned int set_mode;
95 + unsigned int set_rate;
96 + unsigned int dsp_page_number;
99 +static bool digital_gain_0db_limit = true;
102 +static struct gpio_desc *mute_gpio[2];
104 +static const char * const allo_piano_mode_texts[] = {
111 +static const SOC_ENUM_SINGLE_DECL(allo_piano_mode_enum,
112 + 0, 0, allo_piano_mode_texts);
114 +static const char * const allo_piano_dual_mode_texts[] = {
120 +static const SOC_ENUM_SINGLE_DECL(allo_piano_dual_mode_enum,
121 + 0, 0, allo_piano_dual_mode_texts);
123 +static const char * const allo_piano_dsp_low_pass_texts[] = {
141 +static const SOC_ENUM_SINGLE_DECL(allo_piano_enum,
142 + 0, 0, allo_piano_dsp_low_pass_texts);
144 +static int __snd_allo_piano_dsp_program(struct snd_soc_pcm_runtime *rtd,
145 + unsigned int mode, unsigned int rate, unsigned int lowpass)
147 + const struct firmware *fw;
148 + struct snd_soc_card *card = rtd->card;
149 + struct glb_pool *glb_ptr = card->drvdata;
150 + char firmware_name[60];
151 + int ret = 0, dac = 0;
155 + else if (rate <= 68000)
157 + else if (rate <= 92000)
159 + else if (rate <= 136000)
161 + else if (rate <= 184000)
167 + glb_ptr->set_lowpass = lowpass = 0;
170 + glb_ptr->set_mode = mode = 0;
173 + glb_ptr->dual_mode = 0;
175 + /* same configuration loaded */
176 + if ((rate == glb_ptr->set_rate) && (lowpass == glb_ptr->set_lowpass)
177 + && (mode == glb_ptr->set_mode))
185 + snd_soc_component_write(rtd->codec_dais[0]->component,
186 + PCM512x_MUTE, P_DAC_UNMUTE);
187 + snd_soc_component_write(rtd->codec_dais[1]->component,
188 + PCM512x_MUTE, P_DAC_MUTE);
189 + glb_ptr->set_rate = rate;
190 + glb_ptr->set_mode = mode;
191 + glb_ptr->set_lowpass = lowpass;
195 + snd_soc_component_write(rtd->codec_dais[0]->component,
196 + PCM512x_MUTE, P_DAC_UNMUTE);
197 + snd_soc_component_write(rtd->codec_dais[1]->component,
198 + PCM512x_MUTE, P_DAC_UNMUTE);
201 + for (dac = 0; dac < rtd->num_codecs; dac++) {
202 + struct dsp_code *dsp_code_read;
205 + if (dac == 0) { /* high */
206 + snprintf(firmware_name, sizeof(firmware_name),
207 + "allo/piano/2.2/allo-piano-dsp-%d-%d-%d.bin",
208 + rate, ((lowpass * 10) + 60), dac);
210 + snprintf(firmware_name, sizeof(firmware_name),
211 + "allo/piano/2.%d/allo-piano-dsp-%d-%d-%d.bin",
212 + (mode - 1), rate, ((lowpass * 10) + 60), dac);
215 + dev_info(rtd->card->dev, "Dsp Firmware File Name: %s\n",
218 + ret = request_firmware(&fw, firmware_name, rtd->card->dev);
220 + dev_err(rtd->card->dev,
221 + "Error: Allo Piano Firmware %s missing. %d\n",
222 + firmware_name, ret);
226 + while (i < (fw->size - 1)) {
227 + dsp_code_read = (struct dsp_code *)&fw->data[i];
229 + if (dsp_code_read->offset == 0) {
230 + glb_ptr->dsp_page_number = dsp_code_read->val;
231 + ret = snd_soc_component_write(rtd->codec_dais[dac]->component,
232 + PCM512x_PAGE_BASE(0),
233 + dsp_code_read->val);
235 + } else if (dsp_code_read->offset != 0) {
236 + ret = snd_soc_component_write(rtd->codec_dais[dac]->component,
237 + (PCM512x_PAGE_BASE(
238 + glb_ptr->dsp_page_number) +
239 + dsp_code_read->offset),
240 + dsp_code_read->val);
243 + dev_err(rtd->card->dev,
244 + "Failed to write Register: %d\n", ret);
245 + release_firmware(fw);
250 + release_firmware(fw);
252 + glb_ptr->set_rate = rate;
253 + glb_ptr->set_mode = mode;
254 + glb_ptr->set_lowpass = lowpass;
261 +static int snd_allo_piano_dsp_program(struct snd_soc_pcm_runtime *rtd,
262 + unsigned int mode, unsigned int rate, unsigned int lowpass)
264 + struct snd_soc_card *card = rtd->card;
265 + struct glb_pool *glb_ptr = card->drvdata;
268 + mutex_lock(&glb_ptr->lock);
270 + ret = __snd_allo_piano_dsp_program(rtd, mode, rate, lowpass);
272 + mutex_unlock(&glb_ptr->lock);
277 +static int snd_allo_piano_dual_mode_get(struct snd_kcontrol *kcontrol,
278 + struct snd_ctl_elem_value *ucontrol)
280 + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
281 + struct glb_pool *glb_ptr = card->drvdata;
283 + ucontrol->value.integer.value[0] = glb_ptr->dual_mode;
288 +static int snd_allo_piano_dual_mode_put(struct snd_kcontrol *kcontrol,
289 + struct snd_ctl_elem_value *ucontrol)
291 + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
292 + struct glb_pool *glb_ptr = card->drvdata;
293 + struct snd_soc_pcm_runtime *rtd;
294 + struct snd_card *snd_card_ptr = card->snd_card;
295 + struct snd_kcontrol *kctl;
296 + struct soc_mixer_control *mc;
297 + unsigned int left_val = 0, right_val = 0;
299 + rtd = snd_soc_get_pcm_runtime(card, card->dai_link[0].name);
301 + if (ucontrol->value.integer.value[0] > 0) {
302 + glb_ptr->dual_mode = ucontrol->value.integer.value[0];
303 + glb_ptr->set_mode = 0;
305 + if (glb_ptr->set_mode <= 0) {
306 + glb_ptr->dual_mode = 1;
307 + glb_ptr->set_mode = 0;
309 + glb_ptr->dual_mode = 0;
314 + if (glb_ptr->dual_mode == 1) { // Dual Mono
315 + snd_soc_component_write(rtd->codec_dais[0]->component,
316 + PCM512x_MUTE, P_DAC_RIGHT_MUTE);
317 + snd_soc_component_write(rtd->codec_dais[1]->component,
318 + PCM512x_MUTE, P_DAC_LEFT_MUTE);
319 + snd_soc_component_write(rtd->codec_dais[0]->component,
320 + PCM512x_DIGITAL_VOLUME_3, 0xff);
321 + snd_soc_component_write(rtd->codec_dais[1]->component,
322 + PCM512x_DIGITAL_VOLUME_2, 0xff);
324 + list_for_each_entry(kctl, &snd_card_ptr->controls, list) {
325 + if (!strncmp(kctl->id.name, "Digital Playback Volume",
326 + sizeof(kctl->id.name))) {
327 + mc = (struct soc_mixer_control *)
328 + kctl->private_value;
329 + mc->rreg = mc->reg;
334 + snd_soc_component_read(rtd->codec_dais[0]->component,
335 + PCM512x_DIGITAL_VOLUME_2, &left_val);
336 + snd_soc_component_read(rtd->codec_dais[1]->component,
337 + PCM512x_DIGITAL_VOLUME_3, &right_val);
339 + list_for_each_entry(kctl, &snd_card_ptr->controls, list) {
340 + if (!strncmp(kctl->id.name, "Digital Playback Volume",
341 + sizeof(kctl->id.name))) {
342 + mc = (struct soc_mixer_control *)
343 + kctl->private_value;
344 + mc->rreg = PCM512x_DIGITAL_VOLUME_3;
349 + snd_soc_component_write(rtd->codec_dais[0]->component,
350 + PCM512x_DIGITAL_VOLUME_3, left_val);
351 + snd_soc_component_write(rtd->codec_dais[1]->component,
352 + PCM512x_DIGITAL_VOLUME_2, right_val);
353 + snd_soc_component_write(rtd->codec_dais[0]->component,
354 + PCM512x_MUTE, P_DAC_UNMUTE);
355 + snd_soc_component_write(rtd->codec_dais[1]->component,
356 + PCM512x_MUTE, P_DAC_UNMUTE);
362 +static int snd_allo_piano_mode_get(struct snd_kcontrol *kcontrol,
363 + struct snd_ctl_elem_value *ucontrol)
365 + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
366 + struct glb_pool *glb_ptr = card->drvdata;
368 + ucontrol->value.integer.value[0] = glb_ptr->set_mode;
372 +static int snd_allo_piano_mode_put(struct snd_kcontrol *kcontrol,
373 + struct snd_ctl_elem_value *ucontrol)
375 + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
376 + struct snd_soc_pcm_runtime *rtd;
377 + struct glb_pool *glb_ptr = card->drvdata;
378 + struct snd_card *snd_card_ptr = card->snd_card;
379 + struct snd_kcontrol *kctl;
380 + struct soc_mixer_control *mc;
381 + unsigned int left_val = 0, right_val = 0;
383 + rtd = snd_soc_get_pcm_runtime(card, card->dai_link[0].name);
385 + if ((glb_ptr->dual_mode == 1) &&
386 + (ucontrol->value.integer.value[0] > 0)) {
387 + snd_soc_component_read(rtd->codec_dais[0]->component,
388 + PCM512x_DIGITAL_VOLUME_2, &left_val);
389 + snd_soc_component_read(rtd->codec_dais[1]->component,
390 + PCM512x_DIGITAL_VOLUME_2, &right_val);
392 + list_for_each_entry(kctl, &snd_card_ptr->controls, list) {
393 + if (!strncmp(kctl->id.name, "Digital Playback Volume",
394 + sizeof(kctl->id.name))) {
395 + mc = (struct soc_mixer_control *)
396 + kctl->private_value;
397 + mc->rreg = PCM512x_DIGITAL_VOLUME_3;
401 + snd_soc_component_write(rtd->codec_dais[0]->component,
402 + PCM512x_DIGITAL_VOLUME_3, left_val);
403 + snd_soc_component_write(rtd->codec_dais[1]->component,
404 + PCM512x_DIGITAL_VOLUME_3, right_val);
407 + return(snd_allo_piano_dsp_program(rtd,
408 + ucontrol->value.integer.value[0],
409 + glb_ptr->set_rate, glb_ptr->set_lowpass));
412 +static int snd_allo_piano_lowpass_get(struct snd_kcontrol *kcontrol,
413 + struct snd_ctl_elem_value *ucontrol)
415 + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
416 + struct glb_pool *glb_ptr = card->drvdata;
418 + ucontrol->value.integer.value[0] = glb_ptr->set_lowpass;
422 +static int snd_allo_piano_lowpass_put(struct snd_kcontrol *kcontrol,
423 + struct snd_ctl_elem_value *ucontrol)
425 + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
426 + struct snd_soc_pcm_runtime *rtd;
427 + struct glb_pool *glb_ptr = card->drvdata;
429 + rtd = snd_soc_get_pcm_runtime(card, card->dai_link[0].name);
430 + return(snd_allo_piano_dsp_program(rtd,
431 + glb_ptr->set_mode, glb_ptr->set_rate,
432 + ucontrol->value.integer.value[0]));
435 +static int pcm512x_get_reg_sub(struct snd_kcontrol *kcontrol,
436 + struct snd_ctl_elem_value *ucontrol)
438 + struct soc_mixer_control *mc =
439 + (struct soc_mixer_control *)kcontrol->private_value;
440 + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
441 + struct glb_pool *glb_ptr = card->drvdata;
442 + struct snd_soc_pcm_runtime *rtd;
443 + unsigned int left_val = 0;
444 + unsigned int right_val = 0;
446 + rtd = snd_soc_get_pcm_runtime(card, card->dai_link[0].name);
447 + ret = snd_soc_component_read(rtd->codec_dais[1]->component,
448 + PCM512x_DIGITAL_VOLUME_3, &right_val);
452 + if (glb_ptr->dual_mode != 1) {
453 + ret = snd_soc_component_read(rtd->codec_dais[1]->component,
454 + PCM512x_DIGITAL_VOLUME_2, &left_val);
459 + left_val = right_val;
462 + ucontrol->value.integer.value[0] =
463 + (~(left_val >> mc->shift)) & mc->max;
464 + ucontrol->value.integer.value[1] =
465 + (~(right_val >> mc->shift)) & mc->max;
470 +static int pcm512x_set_reg_sub(struct snd_kcontrol *kcontrol,
471 + struct snd_ctl_elem_value *ucontrol)
473 + struct soc_mixer_control *mc =
474 + (struct soc_mixer_control *)kcontrol->private_value;
475 + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
476 + struct glb_pool *glb_ptr = card->drvdata;
477 + struct snd_soc_pcm_runtime *rtd;
478 + unsigned int left_val = (ucontrol->value.integer.value[0] & mc->max);
479 + unsigned int right_val = (ucontrol->value.integer.value[1] & mc->max);
482 + rtd = snd_soc_get_pcm_runtime(card, card->dai_link[0].name);
483 + if (glb_ptr->dual_mode != 1) {
484 + ret = snd_soc_component_write(rtd->codec_dais[1]->component,
485 + PCM512x_DIGITAL_VOLUME_2, (~left_val));
490 + if (digital_gain_0db_limit) {
491 + ret = snd_soc_limit_volume(card, "Subwoofer Playback Volume",
494 + dev_warn(card->dev, "Failed to set volume limit: %d\n",
498 + ret = snd_soc_component_write(rtd->codec_dais[1]->component,
499 + PCM512x_DIGITAL_VOLUME_3, (~right_val));
506 +static int pcm512x_get_reg_sub_switch(struct snd_kcontrol *kcontrol,
507 + struct snd_ctl_elem_value *ucontrol)
509 + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
510 + struct snd_soc_pcm_runtime *rtd;
514 + rtd = snd_soc_get_pcm_runtime(card, card->dai_link[0].name);
515 + ret = snd_soc_component_read(rtd->codec_dais[1]->component, PCM512x_MUTE, &val);
519 + ucontrol->value.integer.value[0] =
520 + (val & P_DAC_LEFT_MUTE) ? P_UNMUTE : P_MUTE;
521 + ucontrol->value.integer.value[1] =
522 + (val & P_DAC_RIGHT_MUTE) ? P_UNMUTE : P_MUTE;
527 +static int pcm512x_set_reg_sub_switch(struct snd_kcontrol *kcontrol,
528 + struct snd_ctl_elem_value *ucontrol)
530 + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
531 + struct snd_soc_pcm_runtime *rtd;
532 + struct glb_pool *glb_ptr = card->drvdata;
533 + unsigned int left_val = (ucontrol->value.integer.value[0]);
534 + unsigned int right_val = (ucontrol->value.integer.value[1]);
537 + rtd = snd_soc_get_pcm_runtime(card, card->dai_link[0].name);
538 + if (glb_ptr->set_mode != 1) {
539 + ret = snd_soc_component_write(rtd->codec_dais[1]->component, PCM512x_MUTE,
540 + ~((left_val & 0x01)<<4 | (right_val & 0x01)));
548 +static int pcm512x_get_reg_master(struct snd_kcontrol *kcontrol,
549 + struct snd_ctl_elem_value *ucontrol)
551 + struct soc_mixer_control *mc =
552 + (struct soc_mixer_control *)kcontrol->private_value;
553 + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
554 + struct glb_pool *glb_ptr = card->drvdata;
555 + struct snd_soc_pcm_runtime *rtd;
556 + unsigned int left_val = 0, right_val = 0;
559 + rtd = snd_soc_get_pcm_runtime(card, card->dai_link[0].name);
561 + ret = snd_soc_component_read(rtd->codec_dais[0]->component,
562 + PCM512x_DIGITAL_VOLUME_2, &left_val);
566 + if (glb_ptr->dual_mode == 1) {
567 + ret = snd_soc_component_read(rtd->codec_dais[1]->component,
568 + PCM512x_DIGITAL_VOLUME_3, &right_val);
572 + ret = snd_soc_component_read(rtd->codec_dais[0]->component,
573 + PCM512x_DIGITAL_VOLUME_3, &right_val);
578 + ucontrol->value.integer.value[0] =
579 + (~(left_val >> mc->shift)) & mc->max;
580 + ucontrol->value.integer.value[1] =
581 + (~(right_val >> mc->shift)) & mc->max;
586 +static int pcm512x_set_reg_master(struct snd_kcontrol *kcontrol,
587 + struct snd_ctl_elem_value *ucontrol)
589 + struct soc_mixer_control *mc =
590 + (struct soc_mixer_control *)kcontrol->private_value;
591 + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
592 + struct glb_pool *glb_ptr = card->drvdata;
593 + struct snd_soc_pcm_runtime *rtd;
594 + unsigned int left_val = (ucontrol->value.integer.value[0] & mc->max);
595 + unsigned int right_val = (ucontrol->value.integer.value[1] & mc->max);
598 + rtd = snd_soc_get_pcm_runtime(card, card->dai_link[0].name);
600 + if (digital_gain_0db_limit) {
601 + ret = snd_soc_limit_volume(card, "Master Playback Volume",
604 + dev_warn(card->dev, "Failed to set volume limit: %d\n",
608 + if (glb_ptr->dual_mode != 1) {
609 + ret = snd_soc_component_write(rtd->codec_dais[1]->component,
610 + PCM512x_DIGITAL_VOLUME_2, (~left_val));
614 + ret = snd_soc_component_write(rtd->codec_dais[0]->component,
615 + PCM512x_DIGITAL_VOLUME_3, (~right_val));
621 + ret = snd_soc_component_write(rtd->codec_dais[1]->component,
622 + PCM512x_DIGITAL_VOLUME_3, (~right_val));
626 + ret = snd_soc_component_write(rtd->codec_dais[0]->component,
627 + PCM512x_DIGITAL_VOLUME_2, (~left_val));
633 +static int pcm512x_get_reg_master_switch(struct snd_kcontrol *kcontrol,
634 + struct snd_ctl_elem_value *ucontrol)
636 + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
637 + struct glb_pool *glb_ptr = card->drvdata;
638 + struct snd_soc_pcm_runtime *rtd;
642 + rtd = snd_soc_get_pcm_runtime(card, card->dai_link[0].name);
644 + ret = snd_soc_component_read(rtd->codec_dais[0]->component, PCM512x_MUTE, &val);
648 + ucontrol->value.integer.value[0] =
649 + (val & P_DAC_LEFT_MUTE) ? P_UNMUTE : P_MUTE;
651 + if (glb_ptr->dual_mode == 1) {
652 + ret = snd_soc_component_read(rtd->codec_dais[1]->component, PCM512x_MUTE, &val);
656 + ucontrol->value.integer.value[1] =
657 + (val & P_DAC_RIGHT_MUTE) ? P_UNMUTE : P_MUTE;
662 +static int pcm512x_set_reg_master_switch(struct snd_kcontrol *kcontrol,
663 + struct snd_ctl_elem_value *ucontrol)
665 + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
666 + struct snd_soc_pcm_runtime *rtd;
667 + struct glb_pool *glb_ptr = card->drvdata;
668 + unsigned int left_val = (ucontrol->value.integer.value[0]);
669 + unsigned int right_val = (ucontrol->value.integer.value[1]);
672 + rtd = snd_soc_get_pcm_runtime(card, card->dai_link[0].name);
673 + if (glb_ptr->dual_mode == 1) {
674 + ret = snd_soc_component_write(rtd->codec_dais[0]->component, PCM512x_MUTE,
675 + ~((left_val & 0x01)<<4));
678 + ret = snd_soc_component_write(rtd->codec_dais[1]->component, PCM512x_MUTE,
679 + ~((right_val & 0x01)));
683 + } else if (glb_ptr->set_mode == 1) {
684 + ret = snd_soc_component_write(rtd->codec_dais[0]->component, PCM512x_MUTE,
685 + ~((left_val & 0x01)<<4 | (right_val & 0x01)));
690 + ret = snd_soc_component_write(rtd->codec_dais[0]->component, PCM512x_MUTE,
691 + ~((left_val & 0x01)<<4 | (right_val & 0x01)));
695 + ret = snd_soc_component_write(rtd->codec_dais[1]->component, PCM512x_MUTE,
696 + ~((left_val & 0x01)<<4 | (right_val & 0x01)));
703 +static const DECLARE_TLV_DB_SCALE(digital_tlv_sub, -10350, 50, 1);
704 +static const DECLARE_TLV_DB_SCALE(digital_tlv_master, -10350, 50, 1);
706 +static const struct snd_kcontrol_new allo_piano_controls[] = {
707 + SOC_ENUM_EXT("Subwoofer mode Route",
708 + allo_piano_mode_enum,
709 + snd_allo_piano_mode_get,
710 + snd_allo_piano_mode_put),
712 + SOC_ENUM_EXT("Dual Mode Route",
713 + allo_piano_dual_mode_enum,
714 + snd_allo_piano_dual_mode_get,
715 + snd_allo_piano_dual_mode_put),
717 + SOC_ENUM_EXT("Lowpass Route", allo_piano_enum,
718 + snd_allo_piano_lowpass_get,
719 + snd_allo_piano_lowpass_put),
721 + SOC_DOUBLE_R_EXT_TLV("Subwoofer Playback Volume",
722 + PCM512x_DIGITAL_VOLUME_2,
723 + PCM512x_DIGITAL_VOLUME_3, 0, 255, 1,
724 + pcm512x_get_reg_sub,
725 + pcm512x_set_reg_sub,
728 + SOC_DOUBLE_EXT("Subwoofer Playback Switch",
730 + PCM512x_RQML_SHIFT,
731 + PCM512x_RQMR_SHIFT, 1, 1,
732 + pcm512x_get_reg_sub_switch,
733 + pcm512x_set_reg_sub_switch),
735 + SOC_DOUBLE_R_EXT_TLV("Master Playback Volume",
736 + PCM512x_DIGITAL_VOLUME_2,
737 + PCM512x_DIGITAL_VOLUME_3, 0, 255, 1,
738 + pcm512x_get_reg_master,
739 + pcm512x_set_reg_master,
740 + digital_tlv_master),
742 + SOC_DOUBLE_EXT("Master Playback Switch",
744 + PCM512x_RQML_SHIFT,
745 + PCM512x_RQMR_SHIFT, 1, 1,
746 + pcm512x_get_reg_master_switch,
747 + pcm512x_set_reg_master_switch),
750 +static int snd_allo_piano_dac_init(struct snd_soc_pcm_runtime *rtd)
752 + struct snd_soc_card *card = rtd->card;
753 + struct glb_pool *glb_ptr;
755 + glb_ptr = kmalloc(sizeof(struct glb_pool), GFP_KERNEL);
759 + memset(glb_ptr, 0x00, sizeof(glb_ptr));
760 + card->drvdata = glb_ptr;
761 + glb_ptr->dual_mode = 2;
762 + glb_ptr->set_mode = 0;
764 + mutex_init(&glb_ptr->lock);
766 + if (digital_gain_0db_limit) {
769 + ret = snd_soc_limit_volume(card, "Digital Playback Volume",
772 + dev_warn(card->dev, "Failed to set volume limit: %d\n",
778 +static void snd_allo_piano_gpio_mute(struct snd_soc_card *card)
781 + gpiod_set_value_cansleep(mute_gpio[0], P_MUTE);
784 + gpiod_set_value_cansleep(mute_gpio[1], P_MUTE);
787 +static void snd_allo_piano_gpio_unmute(struct snd_soc_card *card)
790 + gpiod_set_value_cansleep(mute_gpio[0], P_UNMUTE);
793 + gpiod_set_value_cansleep(mute_gpio[1], P_UNMUTE);
796 +static int snd_allo_piano_set_bias_level(struct snd_soc_card *card,
797 + struct snd_soc_dapm_context *dapm, enum snd_soc_bias_level level)
799 + struct snd_soc_pcm_runtime *rtd;
800 + struct snd_soc_dai *codec_dai;
802 + rtd = snd_soc_get_pcm_runtime(card, card->dai_link[0].name);
803 + codec_dai = rtd->codec_dai;
805 + if (dapm->dev != codec_dai->dev)
809 + case SND_SOC_BIAS_PREPARE:
810 + if (dapm->bias_level != SND_SOC_BIAS_STANDBY)
813 + snd_allo_piano_gpio_unmute(card);
816 + case SND_SOC_BIAS_STANDBY:
817 + if (dapm->bias_level != SND_SOC_BIAS_PREPARE)
820 + snd_allo_piano_gpio_mute(card);
830 +static int snd_allo_piano_dac_startup(
831 + struct snd_pcm_substream *substream)
833 + struct snd_soc_pcm_runtime *rtd = substream->private_data;
834 + struct snd_soc_card *card = rtd->card;
836 + snd_allo_piano_gpio_mute(card);
841 +static int snd_allo_piano_dac_hw_params(
842 + struct snd_pcm_substream *substream,
843 + struct snd_pcm_hw_params *params)
845 + struct snd_soc_pcm_runtime *rtd = substream->private_data;
846 + unsigned int rate = params_rate(params);
847 + struct snd_soc_card *card = rtd->card;
848 + struct glb_pool *glb_ptr = card->drvdata;
849 + int ret = 0, val = 0, dac;
851 + for (dac = 0; (glb_mclk && dac < 2); dac++) {
852 + /* Configure the PLL clock reference for both the Codecs */
853 + ret = snd_soc_component_read(rtd->codec_dais[dac]->component,
854 + PCM512x_RATE_DET_4, &val);
856 + dev_err(rtd->codec_dais[dac]->component->dev,
857 + "Failed to read register PCM512x_RATE_DET_4\n");
862 + snd_soc_component_write(rtd->codec_dais[dac]->component,
866 + dev_info(rtd->codec_dais[dac]->component->dev,
867 + "Setting BCLK as input clock & Enable PLL\n");
869 + snd_soc_component_write(rtd->codec_dais[dac]->component,
873 + snd_soc_component_write(rtd->codec_dais[dac]->component,
877 + dev_info(rtd->codec_dais[dac]->component->dev,
878 + "Setting SCLK as input clock & disabled PLL\n");
882 + ret = snd_allo_piano_dsp_program(rtd, glb_ptr->set_mode, rate,
883 + glb_ptr->set_lowpass);
890 +static int snd_allo_piano_dac_prepare(
891 + struct snd_pcm_substream *substream)
893 + struct snd_soc_pcm_runtime *rtd = substream->private_data;
894 + struct snd_soc_card *card = rtd->card;
896 + snd_allo_piano_gpio_unmute(card);
901 +/* machine stream operations */
902 +static struct snd_soc_ops snd_allo_piano_dac_ops = {
903 + .startup = snd_allo_piano_dac_startup,
904 + .hw_params = snd_allo_piano_dac_hw_params,
905 + .prepare = snd_allo_piano_dac_prepare,
908 +static struct snd_soc_dai_link_component allo_piano_2_1_codecs[] = {
910 + .dai_name = "pcm512x-hifi",
913 + .dai_name = "pcm512x-hifi",
917 +static struct snd_soc_dai_link snd_allo_piano_dac_dai[] = {
919 + .name = "PianoDACPlus",
920 + .stream_name = "PianoDACPlus",
921 + .cpu_dai_name = "bcm2708-i2s.0",
922 + .platform_name = "bcm2708-i2s.0",
923 + .codecs = allo_piano_2_1_codecs,
925 + .dai_fmt = SND_SOC_DAIFMT_I2S |
926 + SND_SOC_DAIFMT_NB_NF |
927 + SND_SOC_DAIFMT_CBS_CFS,
928 + .ops = &snd_allo_piano_dac_ops,
929 + .init = snd_allo_piano_dac_init,
933 +/* audio machine driver */
934 +static struct snd_soc_card snd_allo_piano_dac = {
935 + .name = "PianoDACPlus",
936 + .owner = THIS_MODULE,
937 + .dai_link = snd_allo_piano_dac_dai,
938 + .num_links = ARRAY_SIZE(snd_allo_piano_dac_dai),
939 + .controls = allo_piano_controls,
940 + .num_controls = ARRAY_SIZE(allo_piano_controls),
943 +static int snd_allo_piano_dac_probe(struct platform_device *pdev)
945 + struct snd_soc_card *card = &snd_allo_piano_dac;
946 + int ret = 0, i = 0;
948 + card->dev = &pdev->dev;
949 + platform_set_drvdata(pdev, &snd_allo_piano_dac);
951 + if (pdev->dev.of_node) {
952 + struct device_node *i2s_node;
953 + struct snd_soc_dai_link *dai;
955 + dai = &snd_allo_piano_dac_dai[0];
956 + i2s_node = of_parse_phandle(pdev->dev.of_node,
957 + "i2s-controller", 0);
959 + for (i = 0; i < card->num_links; i++) {
960 + dai->cpu_dai_name = NULL;
961 + dai->cpu_of_node = i2s_node;
962 + dai->platform_name = NULL;
963 + dai->platform_of_node = i2s_node;
966 + digital_gain_0db_limit =
967 + !of_property_read_bool(pdev->dev.of_node,
968 + "allo,24db_digital_gain");
970 + glb_mclk = of_property_read_bool(pdev->dev.of_node,
973 + allo_piano_2_1_codecs[0].of_node =
974 + of_parse_phandle(pdev->dev.of_node, "audio-codec", 0);
975 + if (!allo_piano_2_1_codecs[0].of_node) {
976 + dev_err(&pdev->dev,
977 + "Property 'audio-codec' missing or invalid\n");
981 + allo_piano_2_1_codecs[1].of_node =
982 + of_parse_phandle(pdev->dev.of_node, "audio-codec", 1);
983 + if (!allo_piano_2_1_codecs[1].of_node) {
984 + dev_err(&pdev->dev,
985 + "Property 'audio-codec' missing or invalid\n");
989 + mute_gpio[0] = devm_gpiod_get_optional(&pdev->dev, "mute1",
991 + if (IS_ERR(mute_gpio[0])) {
992 + ret = PTR_ERR(mute_gpio[0]);
993 + dev_err(&pdev->dev,
994 + "failed to get mute1 gpio6: %d\n", ret);
998 + mute_gpio[1] = devm_gpiod_get_optional(&pdev->dev, "mute2",
1000 + if (IS_ERR(mute_gpio[1])) {
1001 + ret = PTR_ERR(mute_gpio[1]);
1002 + dev_err(&pdev->dev,
1003 + "failed to get mute2 gpio25: %d\n", ret);
1007 + if (mute_gpio[0] && mute_gpio[1])
1008 + snd_allo_piano_dac.set_bias_level =
1009 + snd_allo_piano_set_bias_level;
1011 + ret = snd_soc_register_card(&snd_allo_piano_dac);
1013 + dev_err(&pdev->dev,
1014 + "snd_soc_register_card() failed: %d\n", ret);
1018 + if ((mute_gpio[0]) && (mute_gpio[1]))
1019 + snd_allo_piano_gpio_mute(&snd_allo_piano_dac);
1027 +static int snd_allo_piano_dac_remove(struct platform_device *pdev)
1029 + struct snd_soc_card *card = platform_get_drvdata(pdev);
1031 + kfree(&card->drvdata);
1032 + snd_allo_piano_gpio_mute(&snd_allo_piano_dac);
1033 + return snd_soc_unregister_card(&snd_allo_piano_dac);
1036 +static const struct of_device_id snd_allo_piano_dac_of_match[] = {
1037 + { .compatible = "allo,piano-dac-plus", },
1038 + { /* sentinel */ },
1041 +MODULE_DEVICE_TABLE(of, snd_allo_piano_dac_of_match);
1043 +static struct platform_driver snd_allo_piano_dac_driver = {
1045 + .name = "snd-allo-piano-dac-plus",
1046 + .owner = THIS_MODULE,
1047 + .of_match_table = snd_allo_piano_dac_of_match,
1049 + .probe = snd_allo_piano_dac_probe,
1050 + .remove = snd_allo_piano_dac_remove,
1053 +module_platform_driver(snd_allo_piano_dac_driver);
1055 +MODULE_AUTHOR("Baswaraj K <jaikumar@cem-solutions.net>");
1056 +MODULE_DESCRIPTION("ALSA ASoC Machine Driver for Allo Piano DAC Plus");
1057 +MODULE_LICENSE("GPL v2");