From b22da3d8526a935aa31e086e63f60ff3246cb61c Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Sat, 09 Dec 2023 07:24:11 +0000
Subject: [PATCH] add stmac read mac form eeprom
---
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, ®val);
- 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