From f70575805708cabdedea7498aaa3f710fde4d920 Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Wed, 31 Jan 2024 03:29:01 +0000
Subject: [PATCH] add lvds1024*800

---
 kernel/sound/soc/codecs/inno_rk3036.c |  250 +++++++++++++++++++++++++------------------------
 1 files changed, 126 insertions(+), 124 deletions(-)

diff --git a/kernel/sound/soc/codecs/inno_rk3036.c b/kernel/sound/soc/codecs/inno_rk3036.c
index 85a336b..5694f4c 100644
--- a/kernel/sound/soc/codecs/inno_rk3036.c
+++ b/kernel/sound/soc/codecs/inno_rk3036.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-only
 /*
  * Driver of Inno codec for rk3036 by Rockchip Inc.
  *
@@ -14,6 +15,7 @@
 
 #include <linux/platform_device.h>
 #include <linux/of.h>
+#include <linux/of_gpio.h>
 #include <linux/clk.h>
 #include <linux/regmap.h>
 #include <linux/device.h>
@@ -28,69 +30,39 @@
 	struct clk *pclk;
 	struct regmap *regmap;
 	struct device *dev;
+	struct gpio_desc *pa_ctl;
 };
 
 static const DECLARE_TLV_DB_MINMAX(rk3036_codec_hp_tlv, -39, 0);
 
-static int rk3036_codec_antipop_info(struct snd_kcontrol *kcontrol,
-				     struct snd_ctl_elem_info *uinfo)
+static int rk3036_codec_antipop_event(struct snd_soc_dapm_widget *w,
+				      struct snd_kcontrol *kcontrol, int event)
 {
-	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
-	uinfo->count = 2;
-	uinfo->value.integer.min = 0;
-	uinfo->value.integer.max = 1;
-
-	return 0;
-}
-
-static int rk3036_codec_antipop_get(struct snd_kcontrol *kcontrol,
-				    struct snd_ctl_elem_value *ucontrol)
-{
-	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
-	int val, ret, regval;
-
-	ret = snd_soc_component_read(component, INNO_R09, &regval);
-	if (ret)
-		return ret;
-	val = ((regval >> INNO_R09_HPL_ANITPOP_SHIFT) &
-	       INNO_R09_HP_ANTIPOP_MSK) == INNO_R09_HP_ANTIPOP_ON;
-	ucontrol->value.integer.value[0] = val;
-
-	val = ((regval >> INNO_R09_HPR_ANITPOP_SHIFT) &
-	       INNO_R09_HP_ANTIPOP_MSK) == INNO_R09_HP_ANTIPOP_ON;
-	ucontrol->value.integer.value[1] = val;
-
-	return 0;
-}
-
-static int rk3036_codec_antipop_put(struct snd_kcontrol *kcontrol,
-				    struct snd_ctl_elem_value *ucontrol)
-{
-	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
 	int val, ret, regmsk;
 
-	val = (ucontrol->value.integer.value[0] ?
-	       INNO_R09_HP_ANTIPOP_ON : INNO_R09_HP_ANTIPOP_OFF) <<
-	      INNO_R09_HPL_ANITPOP_SHIFT;
-	val |= (ucontrol->value.integer.value[1] ?
-		INNO_R09_HP_ANTIPOP_ON : INNO_R09_HP_ANTIPOP_OFF) <<
-	       INNO_R09_HPR_ANITPOP_SHIFT;
-
-	regmsk = INNO_R09_HP_ANTIPOP_MSK << INNO_R09_HPL_ANITPOP_SHIFT |
-		 INNO_R09_HP_ANTIPOP_MSK << INNO_R09_HPR_ANITPOP_SHIFT;
+	regmsk = INNO_R09_HP_ANTIPOP_MSK << w->shift;
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		val = INNO_R09_HP_ANTIPOP_ON << w->shift;
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		val = INNO_R09_HP_ANTIPOP_OFF << w->shift;
+		break;
+	default:
+		return 0;
+	}
 
 	ret = snd_soc_component_update_bits(component, INNO_R09,
 					    regmsk, val);
 	if (ret < 0)
 		return ret;
 
+	/* Need to wait POP Sound VCM is stable */
+	msleep(50);
+
 	return 0;
 }
-
-#define SOC_RK3036_CODEC_ANTIPOP_DECL(xname) \
-{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
-	.info = rk3036_codec_antipop_info, .get = rk3036_codec_antipop_get, \
-	.put = rk3036_codec_antipop_put, }
 
 static const struct snd_kcontrol_new rk3036_codec_dapm_controls[] = {
 	SOC_DOUBLE_R_RANGE_TLV("Headphone Volume", INNO_R07, INNO_R08,
@@ -100,68 +72,64 @@
 		INNO_R06_VOUTR_CZ_SHIFT, 1, 0),
 	SOC_DOUBLE("Headphone Switch", INNO_R09, INNO_R09_HPL_MUTE_SHIFT,
 		INNO_R09_HPR_MUTE_SHIFT, 1, 0),
-	SOC_RK3036_CODEC_ANTIPOP_DECL("Anti-pop Switch"),
-};
-
-static const struct snd_kcontrol_new rk3036_codec_hpl_mixer_controls[] = {
-	SOC_DAPM_SINGLE("DAC Left Out Switch", INNO_R09,
-			INNO_R09_DACL_SWITCH_SHIFT, 1, 0),
-};
-
-static const struct snd_kcontrol_new rk3036_codec_hpr_mixer_controls[] = {
-	SOC_DAPM_SINGLE("DAC Right Out Switch", INNO_R09,
-			INNO_R09_DACR_SWITCH_SHIFT, 1, 0),
-};
-
-static const struct snd_kcontrol_new rk3036_codec_hpl_switch_controls[] = {
-	SOC_DAPM_SINGLE("HP Left Out Switch", INNO_R05,
-			INNO_R05_HPL_WORK_SHIFT, 1, 0),
-};
-
-static const struct snd_kcontrol_new rk3036_codec_hpr_switch_controls[] = {
-	SOC_DAPM_SINGLE("HP Right Out Switch", INNO_R05,
-			INNO_R05_HPR_WORK_SHIFT, 1, 0),
 };
 
 static const struct snd_soc_dapm_widget rk3036_codec_dapm_widgets[] = {
-	SND_SOC_DAPM_SUPPLY_S("DAC PWR", 1, INNO_R06,
-			      INNO_R06_DAC_EN_SHIFT, 0, NULL, 0),
-	SND_SOC_DAPM_SUPPLY_S("DACL VREF", 2, INNO_R04,
-			      INNO_R04_DACL_VREF_SHIFT, 0, NULL, 0),
-	SND_SOC_DAPM_SUPPLY_S("DACR VREF", 2, INNO_R04,
-			      INNO_R04_DACR_VREF_SHIFT, 0, NULL, 0),
-	SND_SOC_DAPM_SUPPLY_S("DACL HiLo VREF", 3, INNO_R06,
-			      INNO_R06_DACL_HILO_VREF_SHIFT, 0, NULL, 0),
-	SND_SOC_DAPM_SUPPLY_S("DACR HiLo VREF", 3, INNO_R06,
-			      INNO_R06_DACR_HILO_VREF_SHIFT, 0, NULL, 0),
-	SND_SOC_DAPM_SUPPLY_S("DACR CLK", 3, INNO_R04,
-			      INNO_R04_DACR_CLK_SHIFT, 0, NULL, 0),
-	SND_SOC_DAPM_SUPPLY_S("DACL CLK", 3, INNO_R04,
-			      INNO_R04_DACL_CLK_SHIFT, 0, NULL, 0),
+	/* Using S3(Step3) as the starting step by datasheet */
+	SND_SOC_DAPM_SUPPLY_S("DAC PWR", 0, INNO_R06,
+			      INNO_R06_DAC_EN_SHIFT, 0, NULL,
+			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_SUPPLY_S("DACL VREF", 1, INNO_R04,
+			      INNO_R04_DACL_VREF_SHIFT, 0, NULL,
+			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_SUPPLY_S("DACR VREF", 1, INNO_R04,
+			      INNO_R04_DACR_VREF_SHIFT, 0, NULL,
+			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_SUPPLY_S("DACL ANTI-POP", 2, SND_SOC_NOPM,
+			      INNO_R09_HPL_ANITPOP_SHIFT, 0, rk3036_codec_antipop_event,
+			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_SUPPLY_S("DACR ANTI-POP", 2, SND_SOC_NOPM,
+			      INNO_R09_HPR_ANITPOP_SHIFT, 0, rk3036_codec_antipop_event,
+			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_SUPPLY_S("HPL OUT EN", 3, INNO_R05,
+			      INNO_R05_HPL_EN_SHIFT, 0, NULL,
+			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_SUPPLY_S("HPR OUT EN", 3, INNO_R05,
+			      INNO_R05_HPR_EN_SHIFT, 0, NULL,
+			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_SUPPLY_S("HPL OUT WORK", 4, INNO_R05,
+			      INNO_R05_HPL_WORK_SHIFT, 0, NULL,
+			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_SUPPLY_S("HPR OUT WORK", 4, INNO_R05,
+			      INNO_R05_HPR_WORK_SHIFT, 0, NULL,
+			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_SUPPLY_S("DACL HiLo VREF", 5, INNO_R06,
+			      INNO_R06_DACL_HILO_VREF_SHIFT, 0, NULL,
+			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_SUPPLY_S("DACR HiLo VREF", 5, INNO_R06,
+			      INNO_R06_DACR_HILO_VREF_SHIFT, 0, NULL,
+			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_SUPPLY_S("DACL CLK", 6, INNO_R04,
+			      INNO_R04_DACL_CLK_SHIFT, 0, NULL,
+			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_SUPPLY_S("DACR CLK", 6, INNO_R04,
+			      INNO_R04_DACR_CLK_SHIFT, 0, NULL,
+			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_SUPPLY_S("DACL WORK", 7, INNO_R04,
+			      INNO_R04_DACL_SW_SHIFT, 0, NULL,
+			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_SUPPLY_S("DACR WORK", 7, INNO_R04,
+			      INNO_R04_DACR_SW_SHIFT, 0, NULL,
+			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
 
-	SND_SOC_DAPM_DAC("DACL", "Left Playback", INNO_R04,
-			 INNO_R04_DACL_SW_SHIFT, 0),
-	SND_SOC_DAPM_DAC("DACR", "Right Playback", INNO_R04,
-			 INNO_R04_DACR_SW_SHIFT, 0),
+	SND_SOC_DAPM_DAC_E("DACL", "Left Playback", INNO_R09,
+			 INNO_R09_DACL_SWITCH_SHIFT, 0, NULL,
+			 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_DAC_E("DACR", "Right Playback", INNO_R09,
+			 INNO_R09_DACR_SWITCH_SHIFT, 0, NULL,
+			 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
 
-	SND_SOC_DAPM_MIXER("Left Headphone Mixer", SND_SOC_NOPM, 0, 0,
-		rk3036_codec_hpl_mixer_controls,
-		ARRAY_SIZE(rk3036_codec_hpl_mixer_controls)),
-	SND_SOC_DAPM_MIXER("Right Headphone Mixer", SND_SOC_NOPM, 0, 0,
-		rk3036_codec_hpr_mixer_controls,
-		ARRAY_SIZE(rk3036_codec_hpr_mixer_controls)),
-
-	SND_SOC_DAPM_PGA("HP Left Out", INNO_R05,
-			 INNO_R05_HPL_EN_SHIFT, 0, NULL, 0),
-	SND_SOC_DAPM_PGA("HP Right Out", INNO_R05,
-			 INNO_R05_HPR_EN_SHIFT, 0, NULL, 0),
-
-	SND_SOC_DAPM_MIXER("HP Left Switch",  SND_SOC_NOPM, 0, 0,
-			   rk3036_codec_hpl_switch_controls,
-			   ARRAY_SIZE(rk3036_codec_hpl_switch_controls)),
-	SND_SOC_DAPM_MIXER("HP Right Switch",  SND_SOC_NOPM, 0, 0,
-			   rk3036_codec_hpr_switch_controls,
-			   ARRAY_SIZE(rk3036_codec_hpr_switch_controls)),
+	SND_SOC_DAPM_AIF_IN("DAI-IN", "Playback", 0, SND_SOC_NOPM, 0, 0),
 
 	SND_SOC_DAPM_OUTPUT("HPL"),
 	SND_SOC_DAPM_OUTPUT("HPR"),
@@ -170,28 +138,39 @@
 static const struct snd_soc_dapm_route rk3036_codec_dapm_routes[] = {
 	{"DACL VREF", NULL, "DAC PWR"},
 	{"DACR VREF", NULL, "DAC PWR"},
+	{"DACL ANTI-POP", NULL, "DAC PWR"},
+	{"DACR ANTI-POP", NULL, "DAC PWR"},
+	{"HPL OUT EN", NULL, "DAC PWR"},
+	{"HPR OUT EN", NULL, "DAC PWR"},
+	{"HPL OUT WORK", NULL, "DAC PWR"},
+	{"HPR OUT WORK", NULL, "DAC PWR"},
 	{"DACL HiLo VREF", NULL, "DAC PWR"},
 	{"DACR HiLo VREF", NULL, "DAC PWR"},
 	{"DACL CLK", NULL, "DAC PWR"},
 	{"DACR CLK", NULL, "DAC PWR"},
+	{"DACL WORK", NULL, "DAC PWR"},
+	{"DACR WORK", NULL, "DAC PWR"},
 
 	{"DACL", NULL, "DACL VREF"},
+	{"DACL", NULL, "DACL ANTI-POP"},
+	{"DACL", NULL, "HPL OUT EN"},
+	{"DACL", NULL, "HPL OUT WORK"},
 	{"DACL", NULL, "DACL HiLo VREF"},
 	{"DACL", NULL, "DACL CLK"},
+	{"DACL", NULL, "DACL WORK"},
 	{"DACR", NULL, "DACR VREF"},
+	{"DACR", NULL, "DACR ANTI-POP"},
+	{"DACR", NULL, "HPR OUT EN"},
+	{"DACR", NULL, "HPR OUT WORK"},
 	{"DACR", NULL, "DACR HiLo VREF"},
 	{"DACR", NULL, "DACR CLK"},
+	{"DACR", NULL, "DACR WORK"},
 
-	{"Left Headphone Mixer", "DAC Left Out Switch", "DACL"},
-	{"Right Headphone Mixer", "DAC Right Out Switch", "DACR"},
-	{"HP Left Out", NULL, "Left Headphone Mixer"},
-	{"HP Right Out", NULL, "Right Headphone Mixer"},
+	{"DACL", NULL, "DAI-IN"},
+	{"DACR", NULL, "DAI-IN"},
 
-	{"HP Left Switch", "HP Left Out Switch", "HP Left Out"},
-	{"HP Right Switch", "HP Right Out Switch", "HP Right Out"},
-
-	{"HPL", NULL, "HP Left Switch"},
-	{"HPR", NULL, "HP Right Switch"},
+	{"HPL", NULL, "DACL"},
+	{"HPR", NULL, "DACR"},
 };
 
 static int rk3036_codec_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
@@ -298,6 +277,20 @@
 	return 0;
 }
 
+static int rk3308_mute_stream(struct snd_soc_dai *dai, int mute, int stream)
+{
+	struct snd_soc_component *component = dai->component;
+	struct rk3036_codec_priv *priv = snd_soc_component_get_drvdata(component);
+
+	if (stream == SNDRV_PCM_STREAM_CAPTURE)
+		return 0;
+
+	if (priv->pa_ctl)
+		gpiod_direction_output(priv->pa_ctl, !mute);
+
+	return 0;
+}
+
 #define RK3036_CODEC_RATES (SNDRV_PCM_RATE_8000  | \
 			    SNDRV_PCM_RATE_16000 | \
 			    SNDRV_PCM_RATE_32000 | \
@@ -313,6 +306,7 @@
 static const struct snd_soc_dai_ops rk3036_codec_dai_ops = {
 	.set_fmt	= rk3036_codec_dai_set_fmt,
 	.hw_params	= rk3036_codec_dai_hw_params,
+	.mute_stream    = rk3308_mute_stream,
 };
 
 static struct snd_soc_dai_driver rk3036_codec_dai_driver[] = {
@@ -353,17 +347,18 @@
 				       enum snd_soc_bias_level level)
 {
 	switch (level) {
-	case SND_SOC_BIAS_STANDBY:
-		/* set a big current for capacitor charging. */
-		snd_soc_component_write(component, INNO_R10, INNO_R10_MAX_CUR);
-		/* start precharge */
+	case SND_SOC_BIAS_PREPARE:
+		/* start precharge and waiting finish. */
 		snd_soc_component_write(component, INNO_R06, INNO_R06_DAC_PRECHARGE);
+		msleep(20);
 
 		break;
 
-	case SND_SOC_BIAS_OFF:
-		/* set a big current for capacitor discharging. */
-		snd_soc_component_write(component, INNO_R10, INNO_R10_MAX_CUR);
+	case SND_SOC_BIAS_STANDBY:
+		if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF) {
+			/* set a big current for capacitor charging. */
+			snd_soc_component_write(component, INNO_R10, INNO_R10_MAX_CUR);
+		}
 		/* start discharge. */
 		snd_soc_component_write(component, INNO_R06, INNO_R06_DAC_DISCHARGE);
 
@@ -404,7 +399,6 @@
 {
 	struct rk3036_codec_priv *priv;
 	struct device_node *of_node = pdev->dev.of_node;
-	struct resource *res;
 	void __iomem *base;
 	struct regmap *grf;
 	int ret;
@@ -413,8 +407,7 @@
 	if (!priv)
 		return -ENOMEM;
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	base = devm_ioremap_resource(&pdev->dev, res);
+	base = devm_platform_ioremap_resource(pdev, 0);
 	if (IS_ERR(base))
 		return PTR_ERR(base);
 
@@ -437,6 +430,15 @@
 		return ret;
 	}
 
+	priv->pa_ctl = devm_gpiod_get_optional(&pdev->dev, "pa-ctl",
+					       GPIOD_OUT_LOW);
+	if (!priv->pa_ctl) {
+		dev_info(&pdev->dev, "Don't need pa-ctl gpio\n");
+	} else if (IS_ERR(priv->pa_ctl)) {
+		dev_err(&pdev->dev, "Unable to claim gpio pa-ctl\n");
+		return PTR_ERR(priv->pa_ctl);
+	}
+
 	priv->pclk = devm_clk_get(&pdev->dev, "acodec_pclk");
 	if (IS_ERR(priv->pclk))
 		return PTR_ERR(priv->pclk);

--
Gitblit v1.6.2