forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-01-31 f70575805708cabdedea7498aaa3f710fde4d920
kernel/sound/soc/codecs/inno_rk3036.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * Driver of Inno codec for rk3036 by Rockchip Inc.
34 *
....@@ -14,6 +15,7 @@
1415
1516 #include <linux/platform_device.h>
1617 #include <linux/of.h>
18
+#include <linux/of_gpio.h>
1719 #include <linux/clk.h>
1820 #include <linux/regmap.h>
1921 #include <linux/device.h>
....@@ -28,69 +30,39 @@
2830 struct clk *pclk;
2931 struct regmap *regmap;
3032 struct device *dev;
33
+ struct gpio_desc *pa_ctl;
3134 };
3235
3336 static const DECLARE_TLV_DB_MINMAX(rk3036_codec_hp_tlv, -39, 0);
3437
35
-static int rk3036_codec_antipop_info(struct snd_kcontrol *kcontrol,
36
- struct snd_ctl_elem_info *uinfo)
38
+static int rk3036_codec_antipop_event(struct snd_soc_dapm_widget *w,
39
+ struct snd_kcontrol *kcontrol, int event)
3740 {
38
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
39
- uinfo->count = 2;
40
- uinfo->value.integer.min = 0;
41
- uinfo->value.integer.max = 1;
42
-
43
- return 0;
44
-}
45
-
46
-static int rk3036_codec_antipop_get(struct snd_kcontrol *kcontrol,
47
- struct snd_ctl_elem_value *ucontrol)
48
-{
49
- struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
50
- int val, ret, regval;
51
-
52
- ret = snd_soc_component_read(component, INNO_R09, &regval);
53
- if (ret)
54
- return ret;
55
- val = ((regval >> INNO_R09_HPL_ANITPOP_SHIFT) &
56
- INNO_R09_HP_ANTIPOP_MSK) == INNO_R09_HP_ANTIPOP_ON;
57
- ucontrol->value.integer.value[0] = val;
58
-
59
- val = ((regval >> INNO_R09_HPR_ANITPOP_SHIFT) &
60
- INNO_R09_HP_ANTIPOP_MSK) == INNO_R09_HP_ANTIPOP_ON;
61
- ucontrol->value.integer.value[1] = val;
62
-
63
- return 0;
64
-}
65
-
66
-static int rk3036_codec_antipop_put(struct snd_kcontrol *kcontrol,
67
- struct snd_ctl_elem_value *ucontrol)
68
-{
69
- struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
41
+ struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
7042 int val, ret, regmsk;
7143
72
- val = (ucontrol->value.integer.value[0] ?
73
- INNO_R09_HP_ANTIPOP_ON : INNO_R09_HP_ANTIPOP_OFF) <<
74
- INNO_R09_HPL_ANITPOP_SHIFT;
75
- val |= (ucontrol->value.integer.value[1] ?
76
- INNO_R09_HP_ANTIPOP_ON : INNO_R09_HP_ANTIPOP_OFF) <<
77
- INNO_R09_HPR_ANITPOP_SHIFT;
78
-
79
- regmsk = INNO_R09_HP_ANTIPOP_MSK << INNO_R09_HPL_ANITPOP_SHIFT |
80
- INNO_R09_HP_ANTIPOP_MSK << INNO_R09_HPR_ANITPOP_SHIFT;
44
+ regmsk = INNO_R09_HP_ANTIPOP_MSK << w->shift;
45
+ switch (event) {
46
+ case SND_SOC_DAPM_PRE_PMU:
47
+ val = INNO_R09_HP_ANTIPOP_ON << w->shift;
48
+ break;
49
+ case SND_SOC_DAPM_POST_PMD:
50
+ val = INNO_R09_HP_ANTIPOP_OFF << w->shift;
51
+ break;
52
+ default:
53
+ return 0;
54
+ }
8155
8256 ret = snd_soc_component_update_bits(component, INNO_R09,
8357 regmsk, val);
8458 if (ret < 0)
8559 return ret;
8660
61
+ /* Need to wait POP Sound VCM is stable */
62
+ msleep(50);
63
+
8764 return 0;
8865 }
89
-
90
-#define SOC_RK3036_CODEC_ANTIPOP_DECL(xname) \
91
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
92
- .info = rk3036_codec_antipop_info, .get = rk3036_codec_antipop_get, \
93
- .put = rk3036_codec_antipop_put, }
9466
9567 static const struct snd_kcontrol_new rk3036_codec_dapm_controls[] = {
9668 SOC_DOUBLE_R_RANGE_TLV("Headphone Volume", INNO_R07, INNO_R08,
....@@ -100,68 +72,64 @@
10072 INNO_R06_VOUTR_CZ_SHIFT, 1, 0),
10173 SOC_DOUBLE("Headphone Switch", INNO_R09, INNO_R09_HPL_MUTE_SHIFT,
10274 INNO_R09_HPR_MUTE_SHIFT, 1, 0),
103
- SOC_RK3036_CODEC_ANTIPOP_DECL("Anti-pop Switch"),
104
-};
105
-
106
-static const struct snd_kcontrol_new rk3036_codec_hpl_mixer_controls[] = {
107
- SOC_DAPM_SINGLE("DAC Left Out Switch", INNO_R09,
108
- INNO_R09_DACL_SWITCH_SHIFT, 1, 0),
109
-};
110
-
111
-static const struct snd_kcontrol_new rk3036_codec_hpr_mixer_controls[] = {
112
- SOC_DAPM_SINGLE("DAC Right Out Switch", INNO_R09,
113
- INNO_R09_DACR_SWITCH_SHIFT, 1, 0),
114
-};
115
-
116
-static const struct snd_kcontrol_new rk3036_codec_hpl_switch_controls[] = {
117
- SOC_DAPM_SINGLE("HP Left Out Switch", INNO_R05,
118
- INNO_R05_HPL_WORK_SHIFT, 1, 0),
119
-};
120
-
121
-static const struct snd_kcontrol_new rk3036_codec_hpr_switch_controls[] = {
122
- SOC_DAPM_SINGLE("HP Right Out Switch", INNO_R05,
123
- INNO_R05_HPR_WORK_SHIFT, 1, 0),
12475 };
12576
12677 static const struct snd_soc_dapm_widget rk3036_codec_dapm_widgets[] = {
127
- SND_SOC_DAPM_SUPPLY_S("DAC PWR", 1, INNO_R06,
128
- INNO_R06_DAC_EN_SHIFT, 0, NULL, 0),
129
- SND_SOC_DAPM_SUPPLY_S("DACL VREF", 2, INNO_R04,
130
- INNO_R04_DACL_VREF_SHIFT, 0, NULL, 0),
131
- SND_SOC_DAPM_SUPPLY_S("DACR VREF", 2, INNO_R04,
132
- INNO_R04_DACR_VREF_SHIFT, 0, NULL, 0),
133
- SND_SOC_DAPM_SUPPLY_S("DACL HiLo VREF", 3, INNO_R06,
134
- INNO_R06_DACL_HILO_VREF_SHIFT, 0, NULL, 0),
135
- SND_SOC_DAPM_SUPPLY_S("DACR HiLo VREF", 3, INNO_R06,
136
- INNO_R06_DACR_HILO_VREF_SHIFT, 0, NULL, 0),
137
- SND_SOC_DAPM_SUPPLY_S("DACR CLK", 3, INNO_R04,
138
- INNO_R04_DACR_CLK_SHIFT, 0, NULL, 0),
139
- SND_SOC_DAPM_SUPPLY_S("DACL CLK", 3, INNO_R04,
140
- INNO_R04_DACL_CLK_SHIFT, 0, NULL, 0),
78
+ /* Using S3(Step3) as the starting step by datasheet */
79
+ SND_SOC_DAPM_SUPPLY_S("DAC PWR", 0, INNO_R06,
80
+ INNO_R06_DAC_EN_SHIFT, 0, NULL,
81
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
82
+ SND_SOC_DAPM_SUPPLY_S("DACL VREF", 1, INNO_R04,
83
+ INNO_R04_DACL_VREF_SHIFT, 0, NULL,
84
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
85
+ SND_SOC_DAPM_SUPPLY_S("DACR VREF", 1, INNO_R04,
86
+ INNO_R04_DACR_VREF_SHIFT, 0, NULL,
87
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
88
+ SND_SOC_DAPM_SUPPLY_S("DACL ANTI-POP", 2, SND_SOC_NOPM,
89
+ INNO_R09_HPL_ANITPOP_SHIFT, 0, rk3036_codec_antipop_event,
90
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
91
+ SND_SOC_DAPM_SUPPLY_S("DACR ANTI-POP", 2, SND_SOC_NOPM,
92
+ INNO_R09_HPR_ANITPOP_SHIFT, 0, rk3036_codec_antipop_event,
93
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
94
+ SND_SOC_DAPM_SUPPLY_S("HPL OUT EN", 3, INNO_R05,
95
+ INNO_R05_HPL_EN_SHIFT, 0, NULL,
96
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
97
+ SND_SOC_DAPM_SUPPLY_S("HPR OUT EN", 3, INNO_R05,
98
+ INNO_R05_HPR_EN_SHIFT, 0, NULL,
99
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
100
+ SND_SOC_DAPM_SUPPLY_S("HPL OUT WORK", 4, INNO_R05,
101
+ INNO_R05_HPL_WORK_SHIFT, 0, NULL,
102
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
103
+ SND_SOC_DAPM_SUPPLY_S("HPR OUT WORK", 4, INNO_R05,
104
+ INNO_R05_HPR_WORK_SHIFT, 0, NULL,
105
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
106
+ SND_SOC_DAPM_SUPPLY_S("DACL HiLo VREF", 5, INNO_R06,
107
+ INNO_R06_DACL_HILO_VREF_SHIFT, 0, NULL,
108
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
109
+ SND_SOC_DAPM_SUPPLY_S("DACR HiLo VREF", 5, INNO_R06,
110
+ INNO_R06_DACR_HILO_VREF_SHIFT, 0, NULL,
111
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
112
+ SND_SOC_DAPM_SUPPLY_S("DACL CLK", 6, INNO_R04,
113
+ INNO_R04_DACL_CLK_SHIFT, 0, NULL,
114
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
115
+ SND_SOC_DAPM_SUPPLY_S("DACR CLK", 6, INNO_R04,
116
+ INNO_R04_DACR_CLK_SHIFT, 0, NULL,
117
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
118
+ SND_SOC_DAPM_SUPPLY_S("DACL WORK", 7, INNO_R04,
119
+ INNO_R04_DACL_SW_SHIFT, 0, NULL,
120
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
121
+ SND_SOC_DAPM_SUPPLY_S("DACR WORK", 7, INNO_R04,
122
+ INNO_R04_DACR_SW_SHIFT, 0, NULL,
123
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
141124
142
- SND_SOC_DAPM_DAC("DACL", "Left Playback", INNO_R04,
143
- INNO_R04_DACL_SW_SHIFT, 0),
144
- SND_SOC_DAPM_DAC("DACR", "Right Playback", INNO_R04,
145
- INNO_R04_DACR_SW_SHIFT, 0),
125
+ SND_SOC_DAPM_DAC_E("DACL", "Left Playback", INNO_R09,
126
+ INNO_R09_DACL_SWITCH_SHIFT, 0, NULL,
127
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
128
+ SND_SOC_DAPM_DAC_E("DACR", "Right Playback", INNO_R09,
129
+ INNO_R09_DACR_SWITCH_SHIFT, 0, NULL,
130
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
146131
147
- SND_SOC_DAPM_MIXER("Left Headphone Mixer", SND_SOC_NOPM, 0, 0,
148
- rk3036_codec_hpl_mixer_controls,
149
- ARRAY_SIZE(rk3036_codec_hpl_mixer_controls)),
150
- SND_SOC_DAPM_MIXER("Right Headphone Mixer", SND_SOC_NOPM, 0, 0,
151
- rk3036_codec_hpr_mixer_controls,
152
- ARRAY_SIZE(rk3036_codec_hpr_mixer_controls)),
153
-
154
- SND_SOC_DAPM_PGA("HP Left Out", INNO_R05,
155
- INNO_R05_HPL_EN_SHIFT, 0, NULL, 0),
156
- SND_SOC_DAPM_PGA("HP Right Out", INNO_R05,
157
- INNO_R05_HPR_EN_SHIFT, 0, NULL, 0),
158
-
159
- SND_SOC_DAPM_MIXER("HP Left Switch", SND_SOC_NOPM, 0, 0,
160
- rk3036_codec_hpl_switch_controls,
161
- ARRAY_SIZE(rk3036_codec_hpl_switch_controls)),
162
- SND_SOC_DAPM_MIXER("HP Right Switch", SND_SOC_NOPM, 0, 0,
163
- rk3036_codec_hpr_switch_controls,
164
- ARRAY_SIZE(rk3036_codec_hpr_switch_controls)),
132
+ SND_SOC_DAPM_AIF_IN("DAI-IN", "Playback", 0, SND_SOC_NOPM, 0, 0),
165133
166134 SND_SOC_DAPM_OUTPUT("HPL"),
167135 SND_SOC_DAPM_OUTPUT("HPR"),
....@@ -170,28 +138,39 @@
170138 static const struct snd_soc_dapm_route rk3036_codec_dapm_routes[] = {
171139 {"DACL VREF", NULL, "DAC PWR"},
172140 {"DACR VREF", NULL, "DAC PWR"},
141
+ {"DACL ANTI-POP", NULL, "DAC PWR"},
142
+ {"DACR ANTI-POP", NULL, "DAC PWR"},
143
+ {"HPL OUT EN", NULL, "DAC PWR"},
144
+ {"HPR OUT EN", NULL, "DAC PWR"},
145
+ {"HPL OUT WORK", NULL, "DAC PWR"},
146
+ {"HPR OUT WORK", NULL, "DAC PWR"},
173147 {"DACL HiLo VREF", NULL, "DAC PWR"},
174148 {"DACR HiLo VREF", NULL, "DAC PWR"},
175149 {"DACL CLK", NULL, "DAC PWR"},
176150 {"DACR CLK", NULL, "DAC PWR"},
151
+ {"DACL WORK", NULL, "DAC PWR"},
152
+ {"DACR WORK", NULL, "DAC PWR"},
177153
178154 {"DACL", NULL, "DACL VREF"},
155
+ {"DACL", NULL, "DACL ANTI-POP"},
156
+ {"DACL", NULL, "HPL OUT EN"},
157
+ {"DACL", NULL, "HPL OUT WORK"},
179158 {"DACL", NULL, "DACL HiLo VREF"},
180159 {"DACL", NULL, "DACL CLK"},
160
+ {"DACL", NULL, "DACL WORK"},
181161 {"DACR", NULL, "DACR VREF"},
162
+ {"DACR", NULL, "DACR ANTI-POP"},
163
+ {"DACR", NULL, "HPR OUT EN"},
164
+ {"DACR", NULL, "HPR OUT WORK"},
182165 {"DACR", NULL, "DACR HiLo VREF"},
183166 {"DACR", NULL, "DACR CLK"},
167
+ {"DACR", NULL, "DACR WORK"},
184168
185
- {"Left Headphone Mixer", "DAC Left Out Switch", "DACL"},
186
- {"Right Headphone Mixer", "DAC Right Out Switch", "DACR"},
187
- {"HP Left Out", NULL, "Left Headphone Mixer"},
188
- {"HP Right Out", NULL, "Right Headphone Mixer"},
169
+ {"DACL", NULL, "DAI-IN"},
170
+ {"DACR", NULL, "DAI-IN"},
189171
190
- {"HP Left Switch", "HP Left Out Switch", "HP Left Out"},
191
- {"HP Right Switch", "HP Right Out Switch", "HP Right Out"},
192
-
193
- {"HPL", NULL, "HP Left Switch"},
194
- {"HPR", NULL, "HP Right Switch"},
172
+ {"HPL", NULL, "DACL"},
173
+ {"HPR", NULL, "DACR"},
195174 };
196175
197176 static int rk3036_codec_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
....@@ -298,6 +277,20 @@
298277 return 0;
299278 }
300279
280
+static int rk3308_mute_stream(struct snd_soc_dai *dai, int mute, int stream)
281
+{
282
+ struct snd_soc_component *component = dai->component;
283
+ struct rk3036_codec_priv *priv = snd_soc_component_get_drvdata(component);
284
+
285
+ if (stream == SNDRV_PCM_STREAM_CAPTURE)
286
+ return 0;
287
+
288
+ if (priv->pa_ctl)
289
+ gpiod_direction_output(priv->pa_ctl, !mute);
290
+
291
+ return 0;
292
+}
293
+
301294 #define RK3036_CODEC_RATES (SNDRV_PCM_RATE_8000 | \
302295 SNDRV_PCM_RATE_16000 | \
303296 SNDRV_PCM_RATE_32000 | \
....@@ -313,6 +306,7 @@
313306 static const struct snd_soc_dai_ops rk3036_codec_dai_ops = {
314307 .set_fmt = rk3036_codec_dai_set_fmt,
315308 .hw_params = rk3036_codec_dai_hw_params,
309
+ .mute_stream = rk3308_mute_stream,
316310 };
317311
318312 static struct snd_soc_dai_driver rk3036_codec_dai_driver[] = {
....@@ -353,17 +347,18 @@
353347 enum snd_soc_bias_level level)
354348 {
355349 switch (level) {
356
- case SND_SOC_BIAS_STANDBY:
357
- /* set a big current for capacitor charging. */
358
- snd_soc_component_write(component, INNO_R10, INNO_R10_MAX_CUR);
359
- /* start precharge */
350
+ case SND_SOC_BIAS_PREPARE:
351
+ /* start precharge and waiting finish. */
360352 snd_soc_component_write(component, INNO_R06, INNO_R06_DAC_PRECHARGE);
353
+ msleep(20);
361354
362355 break;
363356
364
- case SND_SOC_BIAS_OFF:
365
- /* set a big current for capacitor discharging. */
366
- snd_soc_component_write(component, INNO_R10, INNO_R10_MAX_CUR);
357
+ case SND_SOC_BIAS_STANDBY:
358
+ if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF) {
359
+ /* set a big current for capacitor charging. */
360
+ snd_soc_component_write(component, INNO_R10, INNO_R10_MAX_CUR);
361
+ }
367362 /* start discharge. */
368363 snd_soc_component_write(component, INNO_R06, INNO_R06_DAC_DISCHARGE);
369364
....@@ -404,7 +399,6 @@
404399 {
405400 struct rk3036_codec_priv *priv;
406401 struct device_node *of_node = pdev->dev.of_node;
407
- struct resource *res;
408402 void __iomem *base;
409403 struct regmap *grf;
410404 int ret;
....@@ -413,8 +407,7 @@
413407 if (!priv)
414408 return -ENOMEM;
415409
416
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
417
- base = devm_ioremap_resource(&pdev->dev, res);
410
+ base = devm_platform_ioremap_resource(pdev, 0);
418411 if (IS_ERR(base))
419412 return PTR_ERR(base);
420413
....@@ -437,6 +430,15 @@
437430 return ret;
438431 }
439432
433
+ priv->pa_ctl = devm_gpiod_get_optional(&pdev->dev, "pa-ctl",
434
+ GPIOD_OUT_LOW);
435
+ if (!priv->pa_ctl) {
436
+ dev_info(&pdev->dev, "Don't need pa-ctl gpio\n");
437
+ } else if (IS_ERR(priv->pa_ctl)) {
438
+ dev_err(&pdev->dev, "Unable to claim gpio pa-ctl\n");
439
+ return PTR_ERR(priv->pa_ctl);
440
+ }
441
+
440442 priv->pclk = devm_clk_get(&pdev->dev, "acodec_pclk");
441443 if (IS_ERR(priv->pclk))
442444 return PTR_ERR(priv->pclk);