forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-01-31 f70575805708cabdedea7498aaa3f710fde4d920
kernel/sound/soc/codecs/cs42xx8.c
....@@ -14,6 +14,7 @@
1414 #include <linux/delay.h>
1515 #include <linux/module.h>
1616 #include <linux/of_device.h>
17
+#include <linux/gpio/consumer.h>
1718 #include <linux/pm_runtime.h>
1819 #include <linux/regulator/consumer.h>
1920 #include <sound/pcm_params.h>
....@@ -45,6 +46,8 @@
4546 bool slave_mode;
4647 unsigned long sysclk;
4748 u32 tx_channels;
49
+ struct gpio_desc *gpiod_reset;
50
+ u32 rate[2];
4851 };
4952
5053 /* -127.5dB to 0dB with step of 0.5dB */
....@@ -174,21 +177,27 @@
174177 };
175178
176179 struct cs42xx8_ratios {
177
- unsigned int ratio;
178
- unsigned char speed;
179
- unsigned char mclk;
180
+ unsigned int mfreq;
181
+ unsigned int min_mclk;
182
+ unsigned int max_mclk;
183
+ unsigned int ratio[3];
180184 };
181185
186
+/*
187
+ * According to reference mannual, define the cs42xx8_ratio struct
188
+ * MFreq2 | MFreq1 | MFreq0 | Description | SSM | DSM | QSM |
189
+ * 0 | 0 | 0 |1.029MHz to 12.8MHz | 256 | 128 | 64 |
190
+ * 0 | 0 | 1 |1.536MHz to 19.2MHz | 384 | 192 | 96 |
191
+ * 0 | 1 | 0 |2.048MHz to 25.6MHz | 512 | 256 | 128 |
192
+ * 0 | 1 | 1 |3.072MHz to 38.4MHz | 768 | 384 | 192 |
193
+ * 1 | x | x |4.096MHz to 51.2MHz |1024 | 512 | 256 |
194
+ */
182195 static const struct cs42xx8_ratios cs42xx8_ratios[] = {
183
- { 64, CS42XX8_FM_QUAD, CS42XX8_FUNCMOD_MFREQ_256(4) },
184
- { 96, CS42XX8_FM_QUAD, CS42XX8_FUNCMOD_MFREQ_384(4) },
185
- { 128, CS42XX8_FM_QUAD, CS42XX8_FUNCMOD_MFREQ_512(4) },
186
- { 192, CS42XX8_FM_QUAD, CS42XX8_FUNCMOD_MFREQ_768(4) },
187
- { 256, CS42XX8_FM_SINGLE, CS42XX8_FUNCMOD_MFREQ_256(1) },
188
- { 384, CS42XX8_FM_SINGLE, CS42XX8_FUNCMOD_MFREQ_384(1) },
189
- { 512, CS42XX8_FM_SINGLE, CS42XX8_FUNCMOD_MFREQ_512(1) },
190
- { 768, CS42XX8_FM_SINGLE, CS42XX8_FUNCMOD_MFREQ_768(1) },
191
- { 1024, CS42XX8_FM_SINGLE, CS42XX8_FUNCMOD_MFREQ_1024(1) }
196
+ { 0, 1029000, 12800000, {256, 128, 64} },
197
+ { 2, 1536000, 19200000, {384, 192, 96} },
198
+ { 4, 2048000, 25600000, {512, 256, 128} },
199
+ { 6, 3072000, 38400000, {768, 384, 192} },
200
+ { 8, 4096000, 51200000, {1024, 512, 256} },
192201 };
193202
194203 static int cs42xx8_set_dai_sysclk(struct snd_soc_dai *codec_dai,
....@@ -255,14 +264,68 @@
255264 struct snd_soc_component *component = dai->component;
256265 struct cs42xx8_priv *cs42xx8 = snd_soc_component_get_drvdata(component);
257266 bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
258
- u32 ratio = cs42xx8->sysclk / params_rate(params);
259
- u32 i, fm, val, mask;
267
+ u32 ratio[2];
268
+ u32 rate[2];
269
+ u32 fm[2];
270
+ u32 i, val, mask;
271
+ bool condition1, condition2;
260272
261273 if (tx)
262274 cs42xx8->tx_channels = params_channels(params);
263275
276
+ rate[tx] = params_rate(params);
277
+ rate[!tx] = cs42xx8->rate[!tx];
278
+
279
+ ratio[tx] = rate[tx] > 0 ? cs42xx8->sysclk / rate[tx] : 0;
280
+ ratio[!tx] = rate[!tx] > 0 ? cs42xx8->sysclk / rate[!tx] : 0;
281
+
282
+ /* Get functional mode for tx and rx according to rate */
283
+ for (i = 0; i < 2; i++) {
284
+ if (cs42xx8->slave_mode) {
285
+ fm[i] = CS42XX8_FM_AUTO;
286
+ } else {
287
+ if (rate[i] < 50000) {
288
+ fm[i] = CS42XX8_FM_SINGLE;
289
+ } else if (rate[i] > 50000 && rate[i] < 100000) {
290
+ fm[i] = CS42XX8_FM_DOUBLE;
291
+ } else if (rate[i] > 100000 && rate[i] < 200000) {
292
+ fm[i] = CS42XX8_FM_QUAD;
293
+ } else {
294
+ dev_err(component->dev,
295
+ "unsupported sample rate\n");
296
+ return -EINVAL;
297
+ }
298
+ }
299
+ }
300
+
264301 for (i = 0; i < ARRAY_SIZE(cs42xx8_ratios); i++) {
265
- if (cs42xx8_ratios[i].ratio == ratio)
302
+ /* Is the ratio[tx] valid ? */
303
+ condition1 = ((fm[tx] == CS42XX8_FM_AUTO) ?
304
+ (cs42xx8_ratios[i].ratio[0] == ratio[tx] ||
305
+ cs42xx8_ratios[i].ratio[1] == ratio[tx] ||
306
+ cs42xx8_ratios[i].ratio[2] == ratio[tx]) :
307
+ (cs42xx8_ratios[i].ratio[fm[tx]] == ratio[tx])) &&
308
+ cs42xx8->sysclk >= cs42xx8_ratios[i].min_mclk &&
309
+ cs42xx8->sysclk <= cs42xx8_ratios[i].max_mclk;
310
+
311
+ if (!ratio[tx])
312
+ condition1 = true;
313
+
314
+ /* Is the ratio[!tx] valid ? */
315
+ condition2 = ((fm[!tx] == CS42XX8_FM_AUTO) ?
316
+ (cs42xx8_ratios[i].ratio[0] == ratio[!tx] ||
317
+ cs42xx8_ratios[i].ratio[1] == ratio[!tx] ||
318
+ cs42xx8_ratios[i].ratio[2] == ratio[!tx]) :
319
+ (cs42xx8_ratios[i].ratio[fm[!tx]] == ratio[!tx]));
320
+
321
+ if (!ratio[!tx])
322
+ condition2 = true;
323
+
324
+ /*
325
+ * Both ratio[tx] and ratio[!tx] is valid, then we get
326
+ * a proper MFreq.
327
+ */
328
+ if (condition1 && condition2)
266329 break;
267330 }
268331
....@@ -271,19 +334,35 @@
271334 return -EINVAL;
272335 }
273336
274
- mask = CS42XX8_FUNCMOD_MFREQ_MASK;
275
- val = cs42xx8_ratios[i].mclk;
337
+ cs42xx8->rate[tx] = params_rate(params);
276338
277
- fm = cs42xx8->slave_mode ? CS42XX8_FM_AUTO : cs42xx8_ratios[i].speed;
339
+ mask = CS42XX8_FUNCMOD_MFREQ_MASK;
340
+ val = cs42xx8_ratios[i].mfreq;
278341
279342 regmap_update_bits(cs42xx8->regmap, CS42XX8_FUNCMOD,
280343 CS42XX8_FUNCMOD_xC_FM_MASK(tx) | mask,
281
- CS42XX8_FUNCMOD_xC_FM(tx, fm) | val);
344
+ CS42XX8_FUNCMOD_xC_FM(tx, fm[tx]) | val);
282345
283346 return 0;
284347 }
285348
286
-static int cs42xx8_digital_mute(struct snd_soc_dai *dai, int mute)
349
+static int cs42xx8_hw_free(struct snd_pcm_substream *substream,
350
+ struct snd_soc_dai *dai)
351
+{
352
+ struct snd_soc_component *component = dai->component;
353
+ struct cs42xx8_priv *cs42xx8 = snd_soc_component_get_drvdata(component);
354
+ bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
355
+
356
+ /* Clear stored rate */
357
+ cs42xx8->rate[tx] = 0;
358
+
359
+ regmap_update_bits(cs42xx8->regmap, CS42XX8_FUNCMOD,
360
+ CS42XX8_FUNCMOD_xC_FM_MASK(tx),
361
+ CS42XX8_FUNCMOD_xC_FM(tx, CS42XX8_FM_AUTO));
362
+ return 0;
363
+}
364
+
365
+static int cs42xx8_mute(struct snd_soc_dai *dai, int mute, int direction)
287366 {
288367 struct snd_soc_component *component = dai->component;
289368 struct cs42xx8_priv *cs42xx8 = snd_soc_component_get_drvdata(component);
....@@ -300,7 +379,9 @@
300379 .set_fmt = cs42xx8_set_dai_fmt,
301380 .set_sysclk = cs42xx8_set_dai_sysclk,
302381 .hw_params = cs42xx8_hw_params,
303
- .digital_mute = cs42xx8_digital_mute,
382
+ .hw_free = cs42xx8_hw_free,
383
+ .mute_stream = cs42xx8_mute,
384
+ .no_capture_mute = 1,
304385 };
305386
306387 static struct snd_soc_dai_driver cs42xx8_dai = {
....@@ -467,6 +548,13 @@
467548 return -EINVAL;
468549 }
469550
551
+ cs42xx8->gpiod_reset = devm_gpiod_get_optional(dev, "reset",
552
+ GPIOD_OUT_HIGH);
553
+ if (IS_ERR(cs42xx8->gpiod_reset))
554
+ return PTR_ERR(cs42xx8->gpiod_reset);
555
+
556
+ gpiod_set_value_cansleep(cs42xx8->gpiod_reset, 0);
557
+
470558 cs42xx8->clk = devm_clk_get(dev, "mclk");
471559 if (IS_ERR(cs42xx8->clk)) {
472560 dev_err(dev, "failed to get the clock: %ld\n",
....@@ -547,6 +635,8 @@
547635 return ret;
548636 }
549637
638
+ gpiod_set_value_cansleep(cs42xx8->gpiod_reset, 0);
639
+
550640 ret = regulator_bulk_enable(ARRAY_SIZE(cs42xx8->supplies),
551641 cs42xx8->supplies);
552642 if (ret) {
....@@ -586,6 +676,8 @@
586676 regulator_bulk_disable(ARRAY_SIZE(cs42xx8->supplies),
587677 cs42xx8->supplies);
588678
679
+ gpiod_set_value_cansleep(cs42xx8->gpiod_reset, 1);
680
+
589681 clk_disable_unprepare(cs42xx8->clk);
590682
591683 return 0;
....@@ -593,6 +685,8 @@
593685 #endif
594686
595687 const struct dev_pm_ops cs42xx8_pm = {
688
+ SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
689
+ pm_runtime_force_resume)
596690 SET_RUNTIME_PM_OPS(cs42xx8_runtime_suspend, cs42xx8_runtime_resume, NULL)
597691 };
598692 EXPORT_SYMBOL_GPL(cs42xx8_pm);