From 7f7ea09cdfa44c447c31db4884c1bb958d27f10a Mon Sep 17 00:00:00 2001
From: paul-1 <6473457+paul-1@users.noreply.github.com>
Date: Wed, 4 Nov 2020 19:11:37 -0500
Subject: [PATCH] Update Allo Piano Dac Driver for 5.4.y kernels

Add unique names to the individual dac coded drivers
Remove some of the codec controls that are not used.

Signed-off-by: Paul Hermann <paul@picoreplayer.org>
---
 sound/soc/bcm/allo-piano-dac-plus.c | 129 +++++++++++++++++++++-------
 1 file changed, 97 insertions(+), 32 deletions(-)

--- a/sound/soc/bcm/allo-piano-dac-plus.c
+++ b/sound/soc/bcm/allo-piano-dac-plus.c
@@ -2,7 +2,8 @@
  * ALSA ASoC Machine Driver for Allo Piano DAC Plus Subwoofer
  *
  * Author:	Baswaraj K <jaikumar@cem-solutions.net>
- *		Copyright 2016
+ *		Copyright 2020
+ *		based on code by David Knell <david.knell@gmail.com)
  *		based on code by Daniel Matuschek <info@crazy-audio.com>
  *		based on code by Florian Meier <florian.meier@koalo.de>
  *
@@ -276,8 +277,15 @@ static int snd_allo_piano_dual_mode_put(
 				PCM512x_DIGITAL_VOLUME_2, 0xff);
 
 		list_for_each_entry(kctl, &snd_card_ptr->controls, list) {
-			if (!strncmp(kctl->id.name, "Digital Playback Volume",
-					sizeof(kctl->id.name))) {
+			if (!strncmp(kctl->id.name, "Main Digital Playback Volume",
+				sizeof(kctl->id.name))) {
+				mc = (struct soc_mixer_control *)
+					kctl->private_value;
+				mc->rreg = mc->reg;
+				break;
+			}
+			if (!strncmp(kctl->id.name, "Sub Digital Playback Volume",
+				sizeof(kctl->id.name))) {
 				mc = (struct soc_mixer_control *)
 					kctl->private_value;
 				mc->rreg = mc->reg;
@@ -291,13 +299,20 @@ static int snd_allo_piano_dual_mode_put(
 						PCM512x_DIGITAL_VOLUME_3, &right_val);
 
 		list_for_each_entry(kctl, &snd_card_ptr->controls, list) {
-			if (!strncmp(kctl->id.name, "Digital Playback Volume",
-					sizeof(kctl->id.name))) {
+			if (!strncmp(kctl->id.name, "Main Digital Playback Volume",
+				sizeof(kctl->id.name))) {
 				mc = (struct soc_mixer_control *)
 					kctl->private_value;
 				mc->rreg = PCM512x_DIGITAL_VOLUME_3;
 				break;
 			}
+			if (!strncmp(kctl->id.name, "Sub Digital Playback Volume",
+				sizeof(kctl->id.name))) {
+				mc = (struct soc_mixer_control *)
+					kctl->private_value;
+				mc->rreg = PCM512x_DIGITAL_VOLUME_2;
+				break;
+			}
 		}
 
 		snd_soc_component_write(rtd->codec_dais[0]->component,
@@ -344,13 +359,20 @@ static int snd_allo_piano_mode_put(struc
 						PCM512x_DIGITAL_VOLUME_2, &right_val);
 
 		list_for_each_entry(kctl, &snd_card_ptr->controls, list) {
-			if (!strncmp(kctl->id.name, "Digital Playback Volume",
-					sizeof(kctl->id.name))) {
+			if (!strncmp(kctl->id.name, "Main Digital Playback Volume",
+				sizeof(kctl->id.name))) {
 				mc = (struct soc_mixer_control *)
 					kctl->private_value;
 				mc->rreg = PCM512x_DIGITAL_VOLUME_3;
 				break;
 			}
+			if (!strncmp(kctl->id.name, "Sub Digital Playback Volume",
+				sizeof(kctl->id.name))) {
+				mc = (struct soc_mixer_control *)
+					kctl->private_value;
+				mc->rreg = PCM512x_DIGITAL_VOLUME_2;
+				break;
+			}
 		}
 		snd_soc_component_write(rtd->codec_dais[0]->component,
 				PCM512x_DIGITAL_VOLUME_3, left_val);
@@ -434,12 +456,6 @@ static int pcm512x_set_reg_sub(struct sn
 	int ret = 0;
 
 	rtd = snd_soc_get_pcm_runtime(card, card->dai_link[0].name);
-	if (glb_ptr->dual_mode != 1) {
-		ret = snd_soc_component_write(rtd->codec_dais[1]->component,
-				PCM512x_DIGITAL_VOLUME_2, (~left_val));
-		if (ret < 0)
-			return ret;
-	}
 
 	if (digital_gain_0db_limit) {
 		ret = snd_soc_limit_volume(card, "Subwoofer Playback Volume",
@@ -449,6 +465,13 @@ static int pcm512x_set_reg_sub(struct sn
 				ret);
 	}
 
+	if (glb_ptr->dual_mode != 1) {
+		ret = snd_soc_component_write(rtd->codec_dais[1]->component,
+				PCM512x_DIGITAL_VOLUME_2, (~left_val));
+		if (ret < 0)
+			return ret;
+	}
+
 	ret = snd_soc_component_write(rtd->codec_dais[1]->component,
 			PCM512x_DIGITAL_VOLUME_3, (~right_val));
 	if (ret < 0)
@@ -674,7 +697,7 @@ static const struct snd_kcontrol_new all
 
 	SOC_DOUBLE_R_EXT_TLV("Subwoofer Playback Volume",
 			PCM512x_DIGITAL_VOLUME_2,
-			PCM512x_DIGITAL_VOLUME_3, 0, 255, 1,
+			PCM512x_DIGITAL_VOLUME_3, 0, 207, 1,
 			pcm512x_get_reg_sub,
 			pcm512x_set_reg_sub,
 			digital_tlv_sub),
@@ -688,7 +711,7 @@ static const struct snd_kcontrol_new all
 
 	SOC_DOUBLE_R_EXT_TLV("Master Playback Volume",
 			PCM512x_DIGITAL_VOLUME_2,
-			PCM512x_DIGITAL_VOLUME_3, 0, 255, 1,
+			PCM512x_DIGITAL_VOLUME_3, 0, 207, 1,
 			pcm512x_get_reg_master,
 			pcm512x_set_reg_master,
 			digital_tlv_master),
@@ -701,10 +724,28 @@ static const struct snd_kcontrol_new all
 			pcm512x_set_reg_master_switch),
 };
 
+static const char * const codec_ctl_pfx[] = { "Main", "Sub" };
+static const char * const codec_ctl_name[] = {
+	"Digital Playback Volume",
+	"Digital Playback Switch",
+	"Auto Mute Mono Switch",
+	"Auto Mute Switch",
+	"Auto Mute Time Left",
+	"Auto Mute Time Right",
+	"Clock Missing Period",
+	"Max Overclock DAC",
+	"Max Overclock DSP",
+	"Max Overclock PLL",
+	"Volume Ramp Down Emergency Rate",
+	"Volume Ramp Down Emergency Step"
+};
+
 static int snd_allo_piano_dac_init(struct snd_soc_pcm_runtime *rtd)
 {
 	struct snd_soc_card *card = rtd->card;
 	struct glb_pool *glb_ptr;
+	struct snd_kcontrol *kctl;
+	int i, j;
 
 	glb_ptr = kzalloc(sizeof(struct glb_pool), GFP_KERNEL);
 	if (!glb_ptr)
@@ -719,12 +760,37 @@ static int snd_allo_piano_dac_init(struc
 	if (digital_gain_0db_limit) {
 		int ret;
 
-		ret = snd_soc_limit_volume(card, "Digital Playback Volume",
-					207);
-		if (ret < 0)
-			dev_warn(card->dev, "Failed to set volume limit: %d\n",
-				ret);
+		//Set volume limit on both dacs
+		for (i = 0; i < ARRAY_SIZE(codec_ctl_pfx); i++) {
+			char cname[256];
+
+			sprintf(cname, "%s %s", codec_ctl_pfx[i], codec_ctl_name[0]);
+			ret = snd_soc_limit_volume(card, cname, 207);
+			if (ret < 0)
+				dev_warn(card->dev, "Failed to set volume limit: %d\n",
+					ret);
+		}
+	}
+
+	// Remove codec controls
+	for (i = 0; i < ARRAY_SIZE(codec_ctl_pfx); i++) {
+		// Start at 1, leave the Digital Volume control.
+		for (j = 1; j < ARRAY_SIZE(codec_ctl_name); j++) {
+			char cname[256];
+
+			sprintf(cname, "%s %s", codec_ctl_pfx[i], codec_ctl_name[j]);
+			kctl = snd_soc_card_get_kcontrol(card, cname);
+			if (!kctl) {
+				dev_err(rtd->card->dev, "Control %s not found\n",
+				       cname);
+			} else {
+				kctl->vd[0].access =
+					SNDRV_CTL_ELEM_ACCESS_READWRITE;
+				snd_ctl_remove(card->snd_card, kctl);
+			}
+		}
 	}
+
 	return 0;
 }
 
@@ -868,10 +934,10 @@ static struct snd_soc_dai_link_component
 };
 
 SND_SOC_DAILINK_DEFS(allo_piano_dai_plus,
-	DAILINK_COMP_ARRAY(COMP_CPU("bcm2708-i2s.0")),
-	DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "pcm512x-hifi"),
-			   COMP_CODEC(NULL, "pcm512x-hifi")),
-	DAILINK_COMP_ARRAY(COMP_PLATFORM("bcm2708-i2s.0")));
+	DAILINK_COMP_ARRAY(COMP_EMPTY()),
+	DAILINK_COMP_ARRAY(COMP_CODEC("pcm512x.1-004c", "pcm512x-hifi"),
+			   COMP_CODEC("pcm512x.1-004d", "pcm512x-hifi")),
+	DAILINK_COMP_ARRAY(COMP_EMPTY()));
 
 static struct snd_soc_dai_link snd_allo_piano_dac_dai[] = {
 	{
@@ -964,17 +1030,16 @@ static int snd_allo_piano_dac_probe(stru
 			snd_allo_piano_dac.set_bias_level =
 				snd_allo_piano_set_bias_level;
 
-		ret = snd_soc_register_card(&snd_allo_piano_dac);
-		if (ret < 0) {
-			dev_err(&pdev->dev,
-				"snd_soc_register_card() failed: %d\n", ret);
-			return ret;
-		}
-
 		if ((mute_gpio[0]) && (mute_gpio[1]))
 			snd_allo_piano_gpio_mute(&snd_allo_piano_dac);
 
-		return 0;
+		ret = devm_snd_soc_register_card(&pdev->dev, &snd_allo_piano_dac);
+
+		if (ret && ret != -EPROBE_DEFER)
+			dev_err(&pdev->dev,
+				"snd_soc_register_card() failed: %d\n", ret);
+		return ret;
+
 	}
 
 	return -EINVAL;