forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-01-31 f70575805708cabdedea7498aaa3f710fde4d920
kernel/sound/soc/meson/axg-toddr.c
....@@ -18,12 +18,17 @@
1818 #define CTRL0_TODDR_SEL_RESAMPLE BIT(30)
1919 #define CTRL0_TODDR_EXT_SIGNED BIT(29)
2020 #define CTRL0_TODDR_PP_MODE BIT(28)
21
+#define CTRL0_TODDR_SYNC_CH BIT(27)
2122 #define CTRL0_TODDR_TYPE_MASK GENMASK(15, 13)
2223 #define CTRL0_TODDR_TYPE(x) ((x) << 13)
2324 #define CTRL0_TODDR_MSB_POS_MASK GENMASK(12, 8)
2425 #define CTRL0_TODDR_MSB_POS(x) ((x) << 8)
2526 #define CTRL0_TODDR_LSB_POS_MASK GENMASK(7, 3)
2627 #define CTRL0_TODDR_LSB_POS(x) ((x) << 3)
28
+#define CTRL1_TODDR_FORCE_FINISH BIT(25)
29
+#define CTRL1_SEL_SHIFT 28
30
+
31
+#define TODDR_MSB_POS 31
2732
2833 static int axg_toddr_pcm_new(struct snd_soc_pcm_runtime *rtd,
2934 struct snd_soc_dai *dai)
....@@ -31,19 +36,28 @@
3136 return axg_fifo_pcm_new(rtd, SNDRV_PCM_STREAM_CAPTURE);
3237 }
3338
39
+static int g12a_toddr_dai_prepare(struct snd_pcm_substream *substream,
40
+ struct snd_soc_dai *dai)
41
+{
42
+ struct axg_fifo *fifo = snd_soc_dai_get_drvdata(dai);
43
+
44
+ /* Reset the write pointer to the FIFO_INIT_ADDR */
45
+ regmap_update_bits(fifo->map, FIFO_CTRL1,
46
+ CTRL1_TODDR_FORCE_FINISH, 0);
47
+ regmap_update_bits(fifo->map, FIFO_CTRL1,
48
+ CTRL1_TODDR_FORCE_FINISH, CTRL1_TODDR_FORCE_FINISH);
49
+ regmap_update_bits(fifo->map, FIFO_CTRL1,
50
+ CTRL1_TODDR_FORCE_FINISH, 0);
51
+
52
+ return 0;
53
+}
54
+
3455 static int axg_toddr_dai_hw_params(struct snd_pcm_substream *substream,
3556 struct snd_pcm_hw_params *params,
3657 struct snd_soc_dai *dai)
3758 {
3859 struct axg_fifo *fifo = snd_soc_dai_get_drvdata(dai);
39
- unsigned int type, width, msb = 31;
40
-
41
- /*
42
- * NOTE:
43
- * Almost all backend will place the MSB at bit 31, except SPDIF Input
44
- * which will put it at index 28. When adding support for the SPDIF
45
- * Input, we'll need to find which type of backend we are connected to.
46
- */
60
+ unsigned int type, width;
4761
4862 switch (params_physical_width(params)) {
4963 case 8:
....@@ -66,8 +80,8 @@
6680 CTRL0_TODDR_MSB_POS_MASK |
6781 CTRL0_TODDR_LSB_POS_MASK,
6882 CTRL0_TODDR_TYPE(type) |
69
- CTRL0_TODDR_MSB_POS(msb) |
70
- CTRL0_TODDR_LSB_POS(msb - (width - 1)));
83
+ CTRL0_TODDR_MSB_POS(TODDR_MSB_POS) |
84
+ CTRL0_TODDR_LSB_POS(TODDR_MSB_POS - (width - 1)));
7185
7286 return 0;
7387 }
....@@ -76,7 +90,6 @@
7690 struct snd_soc_dai *dai)
7791 {
7892 struct axg_fifo *fifo = snd_soc_dai_get_drvdata(dai);
79
- unsigned int fifo_threshold;
8093 int ret;
8194
8295 /* Enable pclk to access registers and clock the fifo ip */
....@@ -93,11 +106,6 @@
93106
94107 /* Apply single buffer mode to the interface */
95108 regmap_update_bits(fifo->map, FIFO_CTRL0, CTRL0_TODDR_PP_MODE, 0);
96
-
97
- /* TODDR does not have a configurable fifo depth */
98
- fifo_threshold = AXG_FIFO_MIN_CNT - 1;
99
- regmap_update_bits(fifo->map, FIFO_CTRL1, CTRL1_THRESHOLD_MASK,
100
- CTRL1_THRESHOLD(fifo_threshold));
101109
102110 return 0;
103111 }
....@@ -130,16 +138,11 @@
130138 };
131139
132140 static const char * const axg_toddr_sel_texts[] = {
133
- "IN 0", "IN 1", "IN 2", "IN 3", "IN 4", "IN 6"
141
+ "IN 0", "IN 1", "IN 2", "IN 3", "IN 4", "IN 5", "IN 6", "IN 7"
134142 };
135143
136
-static const unsigned int axg_toddr_sel_values[] = {
137
- 0, 1, 2, 3, 4, 6
138
-};
139
-
140
-static SOC_VALUE_ENUM_SINGLE_DECL(axg_toddr_sel_enum, FIFO_CTRL0,
141
- CTRL0_SEL_SHIFT, CTRL0_SEL_MASK,
142
- axg_toddr_sel_texts, axg_toddr_sel_values);
144
+static SOC_ENUM_SINGLE_DECL(axg_toddr_sel_enum, FIFO_CTRL0, CTRL0_SEL_SHIFT,
145
+ axg_toddr_sel_texts);
143146
144147 static const struct snd_kcontrol_new axg_toddr_in_mux =
145148 SOC_DAPM_ENUM("Input Source", axg_toddr_sel_enum);
....@@ -151,7 +154,9 @@
151154 SND_SOC_DAPM_AIF_IN("IN 2", NULL, 0, SND_SOC_NOPM, 0, 0),
152155 SND_SOC_DAPM_AIF_IN("IN 3", NULL, 0, SND_SOC_NOPM, 0, 0),
153156 SND_SOC_DAPM_AIF_IN("IN 4", NULL, 0, SND_SOC_NOPM, 0, 0),
157
+ SND_SOC_DAPM_AIF_IN("IN 5", NULL, 0, SND_SOC_NOPM, 0, 0),
154158 SND_SOC_DAPM_AIF_IN("IN 6", NULL, 0, SND_SOC_NOPM, 0, 0),
159
+ SND_SOC_DAPM_AIF_IN("IN 7", NULL, 0, SND_SOC_NOPM, 0, 0),
155160 };
156161
157162 static const struct snd_soc_dapm_route axg_toddr_dapm_routes[] = {
....@@ -161,7 +166,9 @@
161166 { "SRC SEL", "IN 2", "IN 2" },
162167 { "SRC SEL", "IN 3", "IN 3" },
163168 { "SRC SEL", "IN 4", "IN 4" },
169
+ { "SRC SEL", "IN 5", "IN 5" },
164170 { "SRC SEL", "IN 6", "IN 6" },
171
+ { "SRC SEL", "IN 7", "IN 7" },
165172 };
166173
167174 static const struct snd_soc_component_driver axg_toddr_component_drv = {
....@@ -169,18 +176,160 @@
169176 .num_dapm_widgets = ARRAY_SIZE(axg_toddr_dapm_widgets),
170177 .dapm_routes = axg_toddr_dapm_routes,
171178 .num_dapm_routes = ARRAY_SIZE(axg_toddr_dapm_routes),
172
- .ops = &axg_fifo_pcm_ops
179
+ .open = axg_fifo_pcm_open,
180
+ .close = axg_fifo_pcm_close,
181
+ .hw_params = axg_fifo_pcm_hw_params,
182
+ .hw_free = axg_fifo_pcm_hw_free,
183
+ .pointer = axg_fifo_pcm_pointer,
184
+ .trigger = axg_fifo_pcm_trigger,
173185 };
174186
175187 static const struct axg_fifo_match_data axg_toddr_match_data = {
176
- .component_drv = &axg_toddr_component_drv,
177
- .dai_drv = &axg_toddr_dai_drv
188
+ .field_threshold = REG_FIELD(FIFO_CTRL1, 16, 23),
189
+ .component_drv = &axg_toddr_component_drv,
190
+ .dai_drv = &axg_toddr_dai_drv
191
+};
192
+
193
+static int g12a_toddr_dai_startup(struct snd_pcm_substream *substream,
194
+ struct snd_soc_dai *dai)
195
+{
196
+ struct axg_fifo *fifo = snd_soc_dai_get_drvdata(dai);
197
+ int ret;
198
+
199
+ ret = axg_toddr_dai_startup(substream, dai);
200
+ if (ret)
201
+ return ret;
202
+
203
+ /*
204
+ * Make sure the first channel ends up in the at beginning of the output
205
+ * As weird as it looks, without this the first channel may be misplaced
206
+ * in memory, with a random shift of 2 channels.
207
+ */
208
+ regmap_update_bits(fifo->map, FIFO_CTRL0, CTRL0_TODDR_SYNC_CH,
209
+ CTRL0_TODDR_SYNC_CH);
210
+
211
+ return 0;
212
+}
213
+
214
+static const struct snd_soc_dai_ops g12a_toddr_ops = {
215
+ .prepare = g12a_toddr_dai_prepare,
216
+ .hw_params = axg_toddr_dai_hw_params,
217
+ .startup = g12a_toddr_dai_startup,
218
+ .shutdown = axg_toddr_dai_shutdown,
219
+};
220
+
221
+static struct snd_soc_dai_driver g12a_toddr_dai_drv = {
222
+ .name = "TODDR",
223
+ .capture = {
224
+ .stream_name = "Capture",
225
+ .channels_min = 1,
226
+ .channels_max = AXG_FIFO_CH_MAX,
227
+ .rates = AXG_FIFO_RATES,
228
+ .formats = AXG_FIFO_FORMATS,
229
+ },
230
+ .ops = &g12a_toddr_ops,
231
+ .pcm_new = axg_toddr_pcm_new,
232
+};
233
+
234
+static const struct snd_soc_component_driver g12a_toddr_component_drv = {
235
+ .dapm_widgets = axg_toddr_dapm_widgets,
236
+ .num_dapm_widgets = ARRAY_SIZE(axg_toddr_dapm_widgets),
237
+ .dapm_routes = axg_toddr_dapm_routes,
238
+ .num_dapm_routes = ARRAY_SIZE(axg_toddr_dapm_routes),
239
+ .open = axg_fifo_pcm_open,
240
+ .close = axg_fifo_pcm_close,
241
+ .hw_params = g12a_fifo_pcm_hw_params,
242
+ .hw_free = axg_fifo_pcm_hw_free,
243
+ .pointer = axg_fifo_pcm_pointer,
244
+ .trigger = axg_fifo_pcm_trigger,
245
+};
246
+
247
+static const struct axg_fifo_match_data g12a_toddr_match_data = {
248
+ .field_threshold = REG_FIELD(FIFO_CTRL1, 16, 23),
249
+ .component_drv = &g12a_toddr_component_drv,
250
+ .dai_drv = &g12a_toddr_dai_drv
251
+};
252
+
253
+static const char * const sm1_toddr_sel_texts[] = {
254
+ "IN 0", "IN 1", "IN 2", "IN 3", "IN 4", "IN 5", "IN 6", "IN 7",
255
+ "IN 8", "IN 9", "IN 10", "IN 11", "IN 12", "IN 13", "IN 14", "IN 15"
256
+};
257
+
258
+static SOC_ENUM_SINGLE_DECL(sm1_toddr_sel_enum, FIFO_CTRL1, CTRL1_SEL_SHIFT,
259
+ sm1_toddr_sel_texts);
260
+
261
+static const struct snd_kcontrol_new sm1_toddr_in_mux =
262
+ SOC_DAPM_ENUM("Input Source", sm1_toddr_sel_enum);
263
+
264
+static const struct snd_soc_dapm_widget sm1_toddr_dapm_widgets[] = {
265
+ SND_SOC_DAPM_MUX("SRC SEL", SND_SOC_NOPM, 0, 0, &sm1_toddr_in_mux),
266
+ SND_SOC_DAPM_AIF_IN("IN 0", NULL, 0, SND_SOC_NOPM, 0, 0),
267
+ SND_SOC_DAPM_AIF_IN("IN 1", NULL, 0, SND_SOC_NOPM, 0, 0),
268
+ SND_SOC_DAPM_AIF_IN("IN 2", NULL, 0, SND_SOC_NOPM, 0, 0),
269
+ SND_SOC_DAPM_AIF_IN("IN 3", NULL, 0, SND_SOC_NOPM, 0, 0),
270
+ SND_SOC_DAPM_AIF_IN("IN 4", NULL, 0, SND_SOC_NOPM, 0, 0),
271
+ SND_SOC_DAPM_AIF_IN("IN 5", NULL, 0, SND_SOC_NOPM, 0, 0),
272
+ SND_SOC_DAPM_AIF_IN("IN 6", NULL, 0, SND_SOC_NOPM, 0, 0),
273
+ SND_SOC_DAPM_AIF_IN("IN 7", NULL, 0, SND_SOC_NOPM, 0, 0),
274
+ SND_SOC_DAPM_AIF_IN("IN 8", NULL, 0, SND_SOC_NOPM, 0, 0),
275
+ SND_SOC_DAPM_AIF_IN("IN 9", NULL, 0, SND_SOC_NOPM, 0, 0),
276
+ SND_SOC_DAPM_AIF_IN("IN 10", NULL, 0, SND_SOC_NOPM, 0, 0),
277
+ SND_SOC_DAPM_AIF_IN("IN 11", NULL, 0, SND_SOC_NOPM, 0, 0),
278
+ SND_SOC_DAPM_AIF_IN("IN 12", NULL, 0, SND_SOC_NOPM, 0, 0),
279
+ SND_SOC_DAPM_AIF_IN("IN 13", NULL, 0, SND_SOC_NOPM, 0, 0),
280
+ SND_SOC_DAPM_AIF_IN("IN 14", NULL, 0, SND_SOC_NOPM, 0, 0),
281
+ SND_SOC_DAPM_AIF_IN("IN 15", NULL, 0, SND_SOC_NOPM, 0, 0),
282
+};
283
+
284
+static const struct snd_soc_dapm_route sm1_toddr_dapm_routes[] = {
285
+ { "Capture", NULL, "SRC SEL" },
286
+ { "SRC SEL", "IN 0", "IN 0" },
287
+ { "SRC SEL", "IN 1", "IN 1" },
288
+ { "SRC SEL", "IN 2", "IN 2" },
289
+ { "SRC SEL", "IN 3", "IN 3" },
290
+ { "SRC SEL", "IN 4", "IN 4" },
291
+ { "SRC SEL", "IN 5", "IN 5" },
292
+ { "SRC SEL", "IN 6", "IN 6" },
293
+ { "SRC SEL", "IN 7", "IN 7" },
294
+ { "SRC SEL", "IN 8", "IN 8" },
295
+ { "SRC SEL", "IN 9", "IN 9" },
296
+ { "SRC SEL", "IN 10", "IN 10" },
297
+ { "SRC SEL", "IN 11", "IN 11" },
298
+ { "SRC SEL", "IN 12", "IN 12" },
299
+ { "SRC SEL", "IN 13", "IN 13" },
300
+ { "SRC SEL", "IN 14", "IN 14" },
301
+ { "SRC SEL", "IN 15", "IN 15" },
302
+};
303
+
304
+static const struct snd_soc_component_driver sm1_toddr_component_drv = {
305
+ .dapm_widgets = sm1_toddr_dapm_widgets,
306
+ .num_dapm_widgets = ARRAY_SIZE(sm1_toddr_dapm_widgets),
307
+ .dapm_routes = sm1_toddr_dapm_routes,
308
+ .num_dapm_routes = ARRAY_SIZE(sm1_toddr_dapm_routes),
309
+ .open = axg_fifo_pcm_open,
310
+ .close = axg_fifo_pcm_close,
311
+ .hw_params = g12a_fifo_pcm_hw_params,
312
+ .hw_free = axg_fifo_pcm_hw_free,
313
+ .pointer = axg_fifo_pcm_pointer,
314
+ .trigger = axg_fifo_pcm_trigger,
315
+};
316
+
317
+static const struct axg_fifo_match_data sm1_toddr_match_data = {
318
+ .field_threshold = REG_FIELD(FIFO_CTRL1, 12, 23),
319
+ .component_drv = &sm1_toddr_component_drv,
320
+ .dai_drv = &g12a_toddr_dai_drv
178321 };
179322
180323 static const struct of_device_id axg_toddr_of_match[] = {
181324 {
182325 .compatible = "amlogic,axg-toddr",
183326 .data = &axg_toddr_match_data,
327
+ }, {
328
+ .compatible = "amlogic,g12a-toddr",
329
+ .data = &g12a_toddr_match_data,
330
+ }, {
331
+ .compatible = "amlogic,sm1-toddr",
332
+ .data = &sm1_toddr_match_data,
184333 }, {}
185334 };
186335 MODULE_DEVICE_TABLE(of, axg_toddr_of_match);