forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-01-05 071106ecf68c401173c58808b1cf5f68cc50d390
kernel/sound/soc/meson/axg-tdmout.c
....@@ -24,6 +24,7 @@
2424 #define TDMOUT_CTRL1 0x04
2525 #define TDMOUT_CTRL1_TYPE_MASK GENMASK(6, 4)
2626 #define TDMOUT_CTRL1_TYPE(x) ((x) << 4)
27
+#define SM1_TDMOUT_CTRL1_GAIN_EN 7
2728 #define TDMOUT_CTRL1_MSB_POS_MASK GENMASK(12, 8)
2829 #define TDMOUT_CTRL1_MSB_POS(x) ((x) << 8)
2930 #define TDMOUT_CTRL1_SEL_SHIFT 24
....@@ -50,25 +51,6 @@
5051 .reg_stride = 4,
5152 .max_register = TDMOUT_MASK_VAL,
5253 };
53
-
54
-static const struct snd_kcontrol_new axg_tdmout_controls[] = {
55
- SOC_DOUBLE("Lane 0 Volume", TDMOUT_GAIN0, 0, 8, 255, 0),
56
- SOC_DOUBLE("Lane 1 Volume", TDMOUT_GAIN0, 16, 24, 255, 0),
57
- SOC_DOUBLE("Lane 2 Volume", TDMOUT_GAIN1, 0, 8, 255, 0),
58
- SOC_DOUBLE("Lane 3 Volume", TDMOUT_GAIN1, 16, 24, 255, 0),
59
- SOC_SINGLE("Gain Enable Switch", TDMOUT_CTRL1,
60
- TDMOUT_CTRL1_GAIN_EN, 1, 0),
61
-};
62
-
63
-static const char * const tdmout_sel_texts[] = {
64
- "IN 0", "IN 1", "IN 2",
65
-};
66
-
67
-static SOC_ENUM_SINGLE_DECL(axg_tdmout_sel_enum, TDMOUT_CTRL1,
68
- TDMOUT_CTRL1_SEL_SHIFT, tdmout_sel_texts);
69
-
70
-static const struct snd_kcontrol_new axg_tdmout_in_mux =
71
- SOC_DAPM_ENUM("Input Source", axg_tdmout_sel_enum);
7254
7355 static struct snd_soc_dai *
7456 axg_tdmout_get_be(struct snd_soc_dapm_widget *w)
....@@ -124,20 +106,21 @@
124106 regmap_update_bits(map, TDMOUT_CTRL0, TDMOUT_CTRL0_ENABLE, 0);
125107 }
126108
127
-static int axg_tdmout_prepare(struct regmap *map, struct axg_tdm_stream *ts)
109
+static int axg_tdmout_prepare(struct regmap *map,
110
+ const struct axg_tdm_formatter_hw *quirks,
111
+ struct axg_tdm_stream *ts)
128112 {
129
- unsigned int val = 0;
113
+ unsigned int val, skew = quirks->skew_offset;
130114
131115 /* Set the stream skew */
132116 switch (ts->iface->fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
133117 case SND_SOC_DAIFMT_I2S:
134118 case SND_SOC_DAIFMT_DSP_A:
135
- val |= TDMOUT_CTRL0_INIT_BITNUM(1);
136119 break;
137120
138121 case SND_SOC_DAIFMT_LEFT_J:
139122 case SND_SOC_DAIFMT_DSP_B:
140
- val |= TDMOUT_CTRL0_INIT_BITNUM(2);
123
+ skew += 1;
141124 break;
142125
143126 default:
....@@ -145,6 +128,8 @@
145128 ts->iface->fmt & SND_SOC_DAIFMT_FORMAT_MASK);
146129 return -EINVAL;
147130 }
131
+
132
+ val = TDMOUT_CTRL0_INIT_BITNUM(skew);
148133
149134 /* Set the slot width */
150135 val |= TDMOUT_CTRL0_BITNUM(ts->iface->slot_width - 1);
....@@ -194,6 +179,25 @@
194179 return axg_tdm_formatter_set_channel_masks(map, ts, TDMOUT_MASK0);
195180 }
196181
182
+static const struct snd_kcontrol_new axg_tdmout_controls[] = {
183
+ SOC_DOUBLE("Lane 0 Volume", TDMOUT_GAIN0, 0, 8, 255, 0),
184
+ SOC_DOUBLE("Lane 1 Volume", TDMOUT_GAIN0, 16, 24, 255, 0),
185
+ SOC_DOUBLE("Lane 2 Volume", TDMOUT_GAIN1, 0, 8, 255, 0),
186
+ SOC_DOUBLE("Lane 3 Volume", TDMOUT_GAIN1, 16, 24, 255, 0),
187
+ SOC_SINGLE("Gain Enable Switch", TDMOUT_CTRL1,
188
+ TDMOUT_CTRL1_GAIN_EN, 1, 0),
189
+};
190
+
191
+static const char * const axg_tdmout_sel_texts[] = {
192
+ "IN 0", "IN 1", "IN 2",
193
+};
194
+
195
+static SOC_ENUM_SINGLE_DECL(axg_tdmout_sel_enum, TDMOUT_CTRL1,
196
+ TDMOUT_CTRL1_SEL_SHIFT, axg_tdmout_sel_texts);
197
+
198
+static const struct snd_kcontrol_new axg_tdmout_in_mux =
199
+ SOC_DAPM_ENUM("Input Source", axg_tdmout_sel_enum);
200
+
197201 static const struct snd_soc_dapm_widget axg_tdmout_dapm_widgets[] = {
198202 SND_SOC_DAPM_AIF_IN("IN 0", NULL, 0, SND_SOC_NOPM, 0, 0),
199203 SND_SOC_DAPM_AIF_IN("IN 1", NULL, 0, SND_SOC_NOPM, 0, 0),
....@@ -233,13 +237,90 @@
233237 .component_drv = &axg_tdmout_component_drv,
234238 .regmap_cfg = &axg_tdmout_regmap_cfg,
235239 .ops = &axg_tdmout_ops,
236
- .invert_sclk = true,
240
+ .quirks = &(const struct axg_tdm_formatter_hw) {
241
+ .skew_offset = 1,
242
+ },
243
+};
244
+
245
+static const struct axg_tdm_formatter_driver g12a_tdmout_drv = {
246
+ .component_drv = &axg_tdmout_component_drv,
247
+ .regmap_cfg = &axg_tdmout_regmap_cfg,
248
+ .ops = &axg_tdmout_ops,
249
+ .quirks = &(const struct axg_tdm_formatter_hw) {
250
+ .skew_offset = 2,
251
+ },
252
+};
253
+
254
+static const struct snd_kcontrol_new sm1_tdmout_controls[] = {
255
+ SOC_DOUBLE("Lane 0 Volume", TDMOUT_GAIN0, 0, 8, 255, 0),
256
+ SOC_DOUBLE("Lane 1 Volume", TDMOUT_GAIN0, 16, 24, 255, 0),
257
+ SOC_DOUBLE("Lane 2 Volume", TDMOUT_GAIN1, 0, 8, 255, 0),
258
+ SOC_DOUBLE("Lane 3 Volume", TDMOUT_GAIN1, 16, 24, 255, 0),
259
+ SOC_SINGLE("Gain Enable Switch", TDMOUT_CTRL1,
260
+ SM1_TDMOUT_CTRL1_GAIN_EN, 1, 0),
261
+};
262
+
263
+static const char * const sm1_tdmout_sel_texts[] = {
264
+ "IN 0", "IN 1", "IN 2", "IN 3", "IN 4",
265
+};
266
+
267
+static SOC_ENUM_SINGLE_DECL(sm1_tdmout_sel_enum, TDMOUT_CTRL1,
268
+ TDMOUT_CTRL1_SEL_SHIFT, sm1_tdmout_sel_texts);
269
+
270
+static const struct snd_kcontrol_new sm1_tdmout_in_mux =
271
+ SOC_DAPM_ENUM("Input Source", sm1_tdmout_sel_enum);
272
+
273
+static const struct snd_soc_dapm_widget sm1_tdmout_dapm_widgets[] = {
274
+ SND_SOC_DAPM_AIF_IN("IN 0", NULL, 0, SND_SOC_NOPM, 0, 0),
275
+ SND_SOC_DAPM_AIF_IN("IN 1", NULL, 0, SND_SOC_NOPM, 0, 0),
276
+ SND_SOC_DAPM_AIF_IN("IN 2", NULL, 0, SND_SOC_NOPM, 0, 0),
277
+ SND_SOC_DAPM_AIF_IN("IN 3", NULL, 0, SND_SOC_NOPM, 0, 0),
278
+ SND_SOC_DAPM_AIF_IN("IN 4", NULL, 0, SND_SOC_NOPM, 0, 0),
279
+ SND_SOC_DAPM_MUX("SRC SEL", SND_SOC_NOPM, 0, 0, &sm1_tdmout_in_mux),
280
+ SND_SOC_DAPM_PGA_E("ENC", SND_SOC_NOPM, 0, 0, NULL, 0,
281
+ axg_tdm_formatter_event,
282
+ (SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD)),
283
+ SND_SOC_DAPM_AIF_OUT("OUT", NULL, 0, SND_SOC_NOPM, 0, 0),
284
+};
285
+
286
+static const struct snd_soc_dapm_route sm1_tdmout_dapm_routes[] = {
287
+ { "SRC SEL", "IN 0", "IN 0" },
288
+ { "SRC SEL", "IN 1", "IN 1" },
289
+ { "SRC SEL", "IN 2", "IN 2" },
290
+ { "SRC SEL", "IN 3", "IN 3" },
291
+ { "SRC SEL", "IN 4", "IN 4" },
292
+ { "ENC", NULL, "SRC SEL" },
293
+ { "OUT", NULL, "ENC" },
294
+};
295
+
296
+static const struct snd_soc_component_driver sm1_tdmout_component_drv = {
297
+ .controls = sm1_tdmout_controls,
298
+ .num_controls = ARRAY_SIZE(sm1_tdmout_controls),
299
+ .dapm_widgets = sm1_tdmout_dapm_widgets,
300
+ .num_dapm_widgets = ARRAY_SIZE(sm1_tdmout_dapm_widgets),
301
+ .dapm_routes = sm1_tdmout_dapm_routes,
302
+ .num_dapm_routes = ARRAY_SIZE(sm1_tdmout_dapm_routes),
303
+};
304
+
305
+static const struct axg_tdm_formatter_driver sm1_tdmout_drv = {
306
+ .component_drv = &sm1_tdmout_component_drv,
307
+ .regmap_cfg = &axg_tdmout_regmap_cfg,
308
+ .ops = &axg_tdmout_ops,
309
+ .quirks = &(const struct axg_tdm_formatter_hw) {
310
+ .skew_offset = 2,
311
+ },
237312 };
238313
239314 static const struct of_device_id axg_tdmout_of_match[] = {
240315 {
241316 .compatible = "amlogic,axg-tdmout",
242317 .data = &axg_tdmout_drv,
318
+ }, {
319
+ .compatible = "amlogic,g12a-tdmout",
320
+ .data = &g12a_tdmout_drv,
321
+ }, {
322
+ .compatible = "amlogic,sm1-tdmout",
323
+ .data = &sm1_tdmout_drv,
243324 }, {}
244325 };
245326 MODULE_DEVICE_TABLE(of, axg_tdmout_of_match);