forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-01-31 f70575805708cabdedea7498aaa3f710fde4d920
kernel/sound/soc/fsl/fsl-asoc-card.c
....@@ -15,6 +15,8 @@
1515 #endif
1616 #include <sound/pcm_params.h>
1717 #include <sound/soc.h>
18
+#include <sound/jack.h>
19
+#include <sound/simple_card_utils.h>
1820
1921 #include "fsl_esai.h"
2022 #include "fsl_sai.h"
....@@ -33,8 +35,7 @@
3335 #define DAI_FMT_BASE (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF)
3436
3537 /**
36
- * CODEC private data
37
- *
38
+ * struct codec_priv - CODEC private data
3839 * @mclk_freq: Clock rate of MCLK
3940 * @mclk_id: MCLK (or main clock) id for set_sysclk()
4041 * @fll_id: FLL (or secordary clock) id for set_sysclk()
....@@ -48,11 +49,10 @@
4849 };
4950
5051 /**
51
- * CPU private data
52
- *
53
- * @sysclk_freq[2]: SYSCLK rates for set_sysclk()
54
- * @sysclk_dir[2]: SYSCLK directions for set_sysclk()
55
- * @sysclk_id[2]: SYSCLK ids for set_sysclk()
52
+ * struct cpu_priv - CPU private data
53
+ * @sysclk_freq: SYSCLK rates for set_sysclk()
54
+ * @sysclk_dir: SYSCLK directions for set_sysclk()
55
+ * @sysclk_id: SYSCLK ids for set_sysclk()
5656 * @slot_width: Slot width of each frame
5757 *
5858 * Note: [1] for tx and [0] for rx
....@@ -65,13 +65,15 @@
6565 };
6666
6767 /**
68
- * Freescale Generic ASOC card private data
69
- *
70
- * @dai_link[3]: DAI link structure including normal one and DPCM link
68
+ * struct fsl_asoc_card_priv - Freescale Generic ASOC card private data
69
+ * @dai_link: DAI link structure including normal one and DPCM link
70
+ * @hp_jack: Headphone Jack structure
71
+ * @mic_jack: Microphone Jack structure
7172 * @pdev: platform device pointer
7273 * @codec_priv: CODEC private data
7374 * @cpu_priv: CPU private data
7475 * @card: ASoC card structure
76
+ * @streams: Mask of current active streams
7577 * @sample_rate: Current sample rate
7678 * @sample_format: Current sample format
7779 * @asrc_rate: ASRC sample rate used by Back-Ends
....@@ -82,10 +84,13 @@
8284
8385 struct fsl_asoc_card_priv {
8486 struct snd_soc_dai_link dai_link[3];
87
+ struct asoc_simple_jack hp_jack;
88
+ struct asoc_simple_jack mic_jack;
8589 struct platform_device *pdev;
8690 struct codec_priv codec_priv;
8791 struct cpu_priv cpu_priv;
8892 struct snd_soc_card card;
93
+ u8 streams;
8994 u32 sample_rate;
9095 snd_pcm_format_t sample_format;
9196 u32 asrc_rate;
....@@ -94,8 +99,8 @@
9499 char name[32];
95100 };
96101
97
-/**
98
- * This dapm route map exsits for DPCM link only.
102
+/*
103
+ * This dapm route map exists for DPCM link only.
99104 * The other routes shall go through Device Tree.
100105 *
101106 * Note: keep all ASRC routes in the second half
....@@ -112,11 +117,18 @@
112117
113118 static const struct snd_soc_dapm_route audio_map_ac97[] = {
114119 /* 1st half -- Normal DAPM routes */
115
- {"Playback", NULL, "AC97 Playback"},
116
- {"AC97 Capture", NULL, "Capture"},
120
+ {"AC97 Playback", NULL, "CPU AC97 Playback"},
121
+ {"CPU AC97 Capture", NULL, "AC97 Capture"},
117122 /* 2nd half -- ASRC DAPM routes */
118
- {"AC97 Playback", NULL, "ASRC-Playback"},
119
- {"ASRC-Capture", NULL, "AC97 Capture"},
123
+ {"CPU AC97 Playback", NULL, "ASRC-Playback"},
124
+ {"ASRC-Capture", NULL, "CPU AC97 Capture"},
125
+};
126
+
127
+static const struct snd_soc_dapm_route audio_map_tx[] = {
128
+ /* 1st half -- Normal DAPM routes */
129
+ {"Playback", NULL, "CPU-Playback"},
130
+ /* 2nd half -- ASRC DAPM routes */
131
+ {"CPU-Playback", NULL, "ASRC-Playback"},
120132 };
121133
122134 /* Add all possible widgets into here without being redundant */
....@@ -138,40 +150,98 @@
138150 static int fsl_asoc_card_hw_params(struct snd_pcm_substream *substream,
139151 struct snd_pcm_hw_params *params)
140152 {
141
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
153
+ struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
142154 struct fsl_asoc_card_priv *priv = snd_soc_card_get_drvdata(rtd->card);
143155 bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
156
+ struct codec_priv *codec_priv = &priv->codec_priv;
144157 struct cpu_priv *cpu_priv = &priv->cpu_priv;
145158 struct device *dev = rtd->card->dev;
159
+ unsigned int pll_out;
146160 int ret;
147161
148162 priv->sample_rate = params_rate(params);
149163 priv->sample_format = params_format(params);
164
+ priv->streams |= BIT(substream->stream);
150165
151
- /*
152
- * If codec-dai is DAI Master and all configurations are already in the
153
- * set_bias_level(), bypass the remaining settings in hw_params().
154
- * Note: (dai_fmt & CBM_CFM) includes CBM_CFM and CBM_CFS.
155
- */
156
- if ((priv->card.set_bias_level &&
157
- priv->dai_fmt & SND_SOC_DAIFMT_CBM_CFM) ||
158
- fsl_asoc_card_is_ac97(priv))
166
+ if (fsl_asoc_card_is_ac97(priv))
159167 return 0;
160168
161169 /* Specific configurations of DAIs starts from here */
162
- ret = snd_soc_dai_set_sysclk(rtd->cpu_dai, cpu_priv->sysclk_id[tx],
170
+ ret = snd_soc_dai_set_sysclk(asoc_rtd_to_cpu(rtd, 0), cpu_priv->sysclk_id[tx],
163171 cpu_priv->sysclk_freq[tx],
164172 cpu_priv->sysclk_dir[tx]);
165173 if (ret && ret != -ENOTSUPP) {
166174 dev_err(dev, "failed to set sysclk for cpu dai\n");
167
- return ret;
175
+ goto fail;
168176 }
169177
170178 if (cpu_priv->slot_width) {
171
- ret = snd_soc_dai_set_tdm_slot(rtd->cpu_dai, 0x3, 0x3, 2,
179
+ ret = snd_soc_dai_set_tdm_slot(asoc_rtd_to_cpu(rtd, 0), 0x3, 0x3, 2,
172180 cpu_priv->slot_width);
173181 if (ret && ret != -ENOTSUPP) {
174182 dev_err(dev, "failed to set TDM slot for cpu dai\n");
183
+ goto fail;
184
+ }
185
+ }
186
+
187
+ /* Specific configuration for PLL */
188
+ if (codec_priv->pll_id && codec_priv->fll_id) {
189
+ if (priv->sample_format == SNDRV_PCM_FORMAT_S24_LE)
190
+ pll_out = priv->sample_rate * 384;
191
+ else
192
+ pll_out = priv->sample_rate * 256;
193
+
194
+ ret = snd_soc_dai_set_pll(asoc_rtd_to_codec(rtd, 0),
195
+ codec_priv->pll_id,
196
+ codec_priv->mclk_id,
197
+ codec_priv->mclk_freq, pll_out);
198
+ if (ret) {
199
+ dev_err(dev, "failed to start FLL: %d\n", ret);
200
+ goto fail;
201
+ }
202
+
203
+ ret = snd_soc_dai_set_sysclk(asoc_rtd_to_codec(rtd, 0),
204
+ codec_priv->fll_id,
205
+ pll_out, SND_SOC_CLOCK_IN);
206
+
207
+ if (ret && ret != -ENOTSUPP) {
208
+ dev_err(dev, "failed to set SYSCLK: %d\n", ret);
209
+ goto fail;
210
+ }
211
+ }
212
+
213
+ return 0;
214
+
215
+fail:
216
+ priv->streams &= ~BIT(substream->stream);
217
+ return ret;
218
+}
219
+
220
+static int fsl_asoc_card_hw_free(struct snd_pcm_substream *substream)
221
+{
222
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
223
+ struct fsl_asoc_card_priv *priv = snd_soc_card_get_drvdata(rtd->card);
224
+ struct codec_priv *codec_priv = &priv->codec_priv;
225
+ struct device *dev = rtd->card->dev;
226
+ int ret;
227
+
228
+ priv->streams &= ~BIT(substream->stream);
229
+
230
+ if (!priv->streams && codec_priv->pll_id && codec_priv->fll_id) {
231
+ /* Force freq to be 0 to avoid error message in codec */
232
+ ret = snd_soc_dai_set_sysclk(asoc_rtd_to_codec(rtd, 0),
233
+ codec_priv->mclk_id,
234
+ 0,
235
+ SND_SOC_CLOCK_IN);
236
+ if (ret) {
237
+ dev_err(dev, "failed to switch away from FLL: %d\n", ret);
238
+ return ret;
239
+ }
240
+
241
+ ret = snd_soc_dai_set_pll(asoc_rtd_to_codec(rtd, 0),
242
+ codec_priv->pll_id, 0, 0, 0);
243
+ if (ret && ret != -ENOTSUPP) {
244
+ dev_err(dev, "failed to stop FLL: %d\n", ret);
175245 return ret;
176246 }
177247 }
....@@ -181,6 +251,7 @@
181251
182252 static const struct snd_soc_ops fsl_asoc_card_ops = {
183253 .hw_params = fsl_asoc_card_hw_params,
254
+ .hw_free = fsl_asoc_card_hw_free,
184255 };
185256
186257 static int be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
....@@ -200,103 +271,49 @@
200271 return 0;
201272 }
202273
274
+SND_SOC_DAILINK_DEFS(hifi,
275
+ DAILINK_COMP_ARRAY(COMP_EMPTY()),
276
+ DAILINK_COMP_ARRAY(COMP_EMPTY()),
277
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
278
+
279
+SND_SOC_DAILINK_DEFS(hifi_fe,
280
+ DAILINK_COMP_ARRAY(COMP_EMPTY()),
281
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
282
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
283
+
284
+SND_SOC_DAILINK_DEFS(hifi_be,
285
+ DAILINK_COMP_ARRAY(COMP_EMPTY()),
286
+ DAILINK_COMP_ARRAY(COMP_EMPTY()),
287
+ DAILINK_COMP_ARRAY(COMP_DUMMY()));
288
+
203289 static struct snd_soc_dai_link fsl_asoc_card_dai[] = {
204290 /* Default ASoC DAI Link*/
205291 {
206292 .name = "HiFi",
207293 .stream_name = "HiFi",
208294 .ops = &fsl_asoc_card_ops,
295
+ SND_SOC_DAILINK_REG(hifi),
209296 },
210297 /* DPCM Link between Front-End and Back-End (Optional) */
211298 {
212299 .name = "HiFi-ASRC-FE",
213300 .stream_name = "HiFi-ASRC-FE",
214
- .codec_name = "snd-soc-dummy",
215
- .codec_dai_name = "snd-soc-dummy-dai",
216301 .dpcm_playback = 1,
217302 .dpcm_capture = 1,
218303 .dynamic = 1,
304
+ SND_SOC_DAILINK_REG(hifi_fe),
219305 },
220306 {
221307 .name = "HiFi-ASRC-BE",
222308 .stream_name = "HiFi-ASRC-BE",
223
- .platform_name = "snd-soc-dummy",
224309 .be_hw_params_fixup = be_hw_params_fixup,
225310 .ops = &fsl_asoc_card_ops,
226311 .dpcm_playback = 1,
227312 .dpcm_capture = 1,
228313 .no_pcm = 1,
314
+ SND_SOC_DAILINK_REG(hifi_be),
229315 },
230316 };
231
-
232
-static int fsl_asoc_card_set_bias_level(struct snd_soc_card *card,
233
- struct snd_soc_dapm_context *dapm,
234
- enum snd_soc_bias_level level)
235
-{
236
- struct fsl_asoc_card_priv *priv = snd_soc_card_get_drvdata(card);
237
- struct snd_soc_pcm_runtime *rtd;
238
- struct snd_soc_dai *codec_dai;
239
- struct codec_priv *codec_priv = &priv->codec_priv;
240
- struct device *dev = card->dev;
241
- unsigned int pll_out;
242
- int ret;
243
-
244
- rtd = snd_soc_get_pcm_runtime(card, card->dai_link[0].name);
245
- codec_dai = rtd->codec_dai;
246
- if (dapm->dev != codec_dai->dev)
247
- return 0;
248
-
249
- switch (level) {
250
- case SND_SOC_BIAS_PREPARE:
251
- if (dapm->bias_level != SND_SOC_BIAS_STANDBY)
252
- break;
253
-
254
- if (priv->sample_format == SNDRV_PCM_FORMAT_S24_LE)
255
- pll_out = priv->sample_rate * 384;
256
- else
257
- pll_out = priv->sample_rate * 256;
258
-
259
- ret = snd_soc_dai_set_pll(codec_dai, codec_priv->pll_id,
260
- codec_priv->mclk_id,
261
- codec_priv->mclk_freq, pll_out);
262
- if (ret) {
263
- dev_err(dev, "failed to start FLL: %d\n", ret);
264
- return ret;
265
- }
266
-
267
- ret = snd_soc_dai_set_sysclk(codec_dai, codec_priv->fll_id,
268
- pll_out, SND_SOC_CLOCK_IN);
269
- if (ret && ret != -ENOTSUPP) {
270
- dev_err(dev, "failed to set SYSCLK: %d\n", ret);
271
- return ret;
272
- }
273
- break;
274
-
275
- case SND_SOC_BIAS_STANDBY:
276
- if (dapm->bias_level != SND_SOC_BIAS_PREPARE)
277
- break;
278
-
279
- ret = snd_soc_dai_set_sysclk(codec_dai, codec_priv->mclk_id,
280
- codec_priv->mclk_freq,
281
- SND_SOC_CLOCK_IN);
282
- if (ret && ret != -ENOTSUPP) {
283
- dev_err(dev, "failed to switch away from FLL: %d\n", ret);
284
- return ret;
285
- }
286
-
287
- ret = snd_soc_dai_set_pll(codec_dai, codec_priv->pll_id, 0, 0, 0);
288
- if (ret) {
289
- dev_err(dev, "failed to stop FLL: %d\n", ret);
290
- return ret;
291
- }
292
- break;
293
-
294
- default:
295
- break;
296
- }
297
-
298
- return 0;
299
-}
300317
301318 static int fsl_asoc_card_audmux_init(struct device_node *np,
302319 struct fsl_asoc_card_priv *priv)
....@@ -426,19 +443,57 @@
426443 return 0;
427444 }
428445
446
+static int hp_jack_event(struct notifier_block *nb, unsigned long event,
447
+ void *data)
448
+{
449
+ struct snd_soc_jack *jack = (struct snd_soc_jack *)data;
450
+ struct snd_soc_dapm_context *dapm = &jack->card->dapm;
451
+
452
+ if (event & SND_JACK_HEADPHONE)
453
+ /* Disable speaker if headphone is plugged in */
454
+ snd_soc_dapm_disable_pin(dapm, "Ext Spk");
455
+ else
456
+ snd_soc_dapm_enable_pin(dapm, "Ext Spk");
457
+
458
+ return 0;
459
+}
460
+
461
+static struct notifier_block hp_jack_nb = {
462
+ .notifier_call = hp_jack_event,
463
+};
464
+
465
+static int mic_jack_event(struct notifier_block *nb, unsigned long event,
466
+ void *data)
467
+{
468
+ struct snd_soc_jack *jack = (struct snd_soc_jack *)data;
469
+ struct snd_soc_dapm_context *dapm = &jack->card->dapm;
470
+
471
+ if (event & SND_JACK_MICROPHONE)
472
+ /* Disable dmic if microphone is plugged in */
473
+ snd_soc_dapm_disable_pin(dapm, "DMIC");
474
+ else
475
+ snd_soc_dapm_enable_pin(dapm, "DMIC");
476
+
477
+ return 0;
478
+}
479
+
480
+static struct notifier_block mic_jack_nb = {
481
+ .notifier_call = mic_jack_event,
482
+};
483
+
429484 static int fsl_asoc_card_late_probe(struct snd_soc_card *card)
430485 {
431486 struct fsl_asoc_card_priv *priv = snd_soc_card_get_drvdata(card);
432487 struct snd_soc_pcm_runtime *rtd = list_first_entry(
433488 &card->rtd_list, struct snd_soc_pcm_runtime, list);
434
- struct snd_soc_dai *codec_dai = rtd->codec_dai;
489
+ struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
435490 struct codec_priv *codec_priv = &priv->codec_priv;
436491 struct device *dev = card->dev;
437492 int ret;
438493
439494 if (fsl_asoc_card_is_ac97(priv)) {
440495 #if IS_ENABLED(CONFIG_SND_AC97_CODEC)
441
- struct snd_soc_component *component = rtd->codec_dai->component;
496
+ struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
442497 struct snd_ac97 *ac97 = snd_soc_component_get_drvdata(component);
443498
444499 /*
....@@ -468,10 +523,14 @@
468523 struct device_node *cpu_np, *codec_np, *asrc_np;
469524 struct device_node *np = pdev->dev.of_node;
470525 struct platform_device *asrc_pdev = NULL;
526
+ struct device_node *bitclkmaster = NULL;
527
+ struct device_node *framemaster = NULL;
471528 struct platform_device *cpu_pdev;
472529 struct fsl_asoc_card_priv *priv;
473
- struct i2c_client *codec_dev;
530
+ struct device *codec_dev = NULL;
474531 const char *codec_dai_name;
532
+ const char *codec_dev_name;
533
+ unsigned int daifmt;
475534 u32 width;
476535 int ret;
477536
....@@ -497,10 +556,23 @@
497556 }
498557
499558 codec_np = of_parse_phandle(np, "audio-codec", 0);
500
- if (codec_np)
501
- codec_dev = of_find_i2c_device_by_node(codec_np);
502
- else
503
- codec_dev = NULL;
559
+ if (codec_np) {
560
+ struct platform_device *codec_pdev;
561
+ struct i2c_client *codec_i2c;
562
+
563
+ codec_i2c = of_find_i2c_device_by_node(codec_np);
564
+ if (codec_i2c) {
565
+ codec_dev = &codec_i2c->dev;
566
+ codec_dev_name = codec_i2c->name;
567
+ }
568
+ if (!codec_dev) {
569
+ codec_pdev = of_find_device_by_node(codec_np);
570
+ if (codec_pdev) {
571
+ codec_dev = &codec_pdev->dev;
572
+ codec_dev_name = codec_pdev->name;
573
+ }
574
+ }
575
+ }
504576
505577 asrc_np = of_parse_phandle(np, "audio-asrc", 0);
506578 if (asrc_np)
....@@ -508,7 +580,7 @@
508580
509581 /* Get the MCLK rate only, and leave it controlled by CODEC drivers */
510582 if (codec_dev) {
511
- struct clk *codec_clk = clk_get(&codec_dev->dev, NULL);
583
+ struct clk *codec_clk = clk_get(codec_dev, NULL);
512584
513585 if (!IS_ERR(codec_clk)) {
514586 priv->codec_priv.mclk_freq = clk_get_rate(codec_clk);
....@@ -523,10 +595,14 @@
523595 /* Assign a default DAI format, and allow each card to overwrite it */
524596 priv->dai_fmt = DAI_FMT_BASE;
525597
598
+ memcpy(priv->dai_link, fsl_asoc_card_dai,
599
+ sizeof(struct snd_soc_dai_link) * ARRAY_SIZE(priv->dai_link));
600
+
601
+ priv->card.dapm_routes = audio_map;
602
+ priv->card.num_dapm_routes = ARRAY_SIZE(audio_map);
526603 /* Diversify the card configurations */
527604 if (of_device_is_compatible(np, "fsl,imx-audio-cs42888")) {
528605 codec_dai_name = "cs42888";
529
- priv->card.set_bias_level = NULL;
530606 priv->cpu_priv.sysclk_freq[TX] = priv->codec_priv.mclk_freq;
531607 priv->cpu_priv.sysclk_freq[RX] = priv->codec_priv.mclk_freq;
532608 priv->cpu_priv.sysclk_dir[TX] = SND_SOC_CLOCK_OUT;
....@@ -541,64 +617,118 @@
541617 codec_dai_name = "sgtl5000";
542618 priv->codec_priv.mclk_id = SGTL5000_SYSCLK;
543619 priv->dai_fmt |= SND_SOC_DAIFMT_CBM_CFM;
620
+ } else if (of_device_is_compatible(np, "fsl,imx-audio-tlv320aic32x4")) {
621
+ codec_dai_name = "tlv320aic32x4-hifi";
622
+ priv->dai_fmt |= SND_SOC_DAIFMT_CBM_CFM;
544623 } else if (of_device_is_compatible(np, "fsl,imx-audio-wm8962")) {
545624 codec_dai_name = "wm8962";
546
- priv->card.set_bias_level = fsl_asoc_card_set_bias_level;
547625 priv->codec_priv.mclk_id = WM8962_SYSCLK_MCLK;
548626 priv->codec_priv.fll_id = WM8962_SYSCLK_FLL;
549627 priv->codec_priv.pll_id = WM8962_FLL;
550628 priv->dai_fmt |= SND_SOC_DAIFMT_CBM_CFM;
551629 } else if (of_device_is_compatible(np, "fsl,imx-audio-wm8960")) {
552630 codec_dai_name = "wm8960-hifi";
553
- priv->card.set_bias_level = fsl_asoc_card_set_bias_level;
554631 priv->codec_priv.fll_id = WM8960_SYSCLK_AUTO;
555632 priv->codec_priv.pll_id = WM8960_SYSCLK_AUTO;
556633 priv->dai_fmt |= SND_SOC_DAIFMT_CBM_CFM;
557634 } else if (of_device_is_compatible(np, "fsl,imx-audio-ac97")) {
558635 codec_dai_name = "ac97-hifi";
559
- priv->card.set_bias_level = NULL;
560636 priv->dai_fmt = SND_SOC_DAIFMT_AC97;
637
+ priv->card.dapm_routes = audio_map_ac97;
638
+ priv->card.num_dapm_routes = ARRAY_SIZE(audio_map_ac97);
639
+ } else if (of_device_is_compatible(np, "fsl,imx-audio-mqs")) {
640
+ codec_dai_name = "fsl-mqs-dai";
641
+ priv->dai_fmt = SND_SOC_DAIFMT_LEFT_J |
642
+ SND_SOC_DAIFMT_CBS_CFS |
643
+ SND_SOC_DAIFMT_NB_NF;
644
+ priv->dai_link[1].dpcm_capture = 0;
645
+ priv->dai_link[2].dpcm_capture = 0;
646
+ priv->card.dapm_routes = audio_map_tx;
647
+ priv->card.num_dapm_routes = ARRAY_SIZE(audio_map_tx);
648
+ } else if (of_device_is_compatible(np, "fsl,imx-audio-wm8524")) {
649
+ codec_dai_name = "wm8524-hifi";
650
+ priv->dai_fmt |= SND_SOC_DAIFMT_CBS_CFS;
651
+ priv->dai_link[1].dpcm_capture = 0;
652
+ priv->dai_link[2].dpcm_capture = 0;
653
+ priv->cpu_priv.slot_width = 32;
654
+ priv->card.dapm_routes = audio_map_tx;
655
+ priv->card.num_dapm_routes = ARRAY_SIZE(audio_map_tx);
561656 } else {
562657 dev_err(&pdev->dev, "unknown Device Tree compatible\n");
563658 ret = -EINVAL;
564659 goto asrc_fail;
565660 }
566661
662
+ /* Format info from DT is optional. */
663
+ daifmt = snd_soc_of_parse_daifmt(np, NULL,
664
+ &bitclkmaster, &framemaster);
665
+ daifmt &= ~SND_SOC_DAIFMT_MASTER_MASK;
666
+ if (bitclkmaster || framemaster) {
667
+ if (codec_np == bitclkmaster)
668
+ daifmt |= (codec_np == framemaster) ?
669
+ SND_SOC_DAIFMT_CBM_CFM : SND_SOC_DAIFMT_CBM_CFS;
670
+ else
671
+ daifmt |= (codec_np == framemaster) ?
672
+ SND_SOC_DAIFMT_CBS_CFM : SND_SOC_DAIFMT_CBS_CFS;
673
+
674
+ /* Override dai_fmt with value from DT */
675
+ priv->dai_fmt = daifmt;
676
+ }
677
+
678
+ /* Change direction according to format */
679
+ if (priv->dai_fmt & SND_SOC_DAIFMT_CBM_CFM) {
680
+ priv->cpu_priv.sysclk_dir[TX] = SND_SOC_CLOCK_IN;
681
+ priv->cpu_priv.sysclk_dir[RX] = SND_SOC_CLOCK_IN;
682
+ }
683
+
684
+ of_node_put(bitclkmaster);
685
+ of_node_put(framemaster);
686
+
567687 if (!fsl_asoc_card_is_ac97(priv) && !codec_dev) {
568688 dev_err(&pdev->dev, "failed to find codec device\n");
569
- ret = -EINVAL;
689
+ ret = -EPROBE_DEFER;
570690 goto asrc_fail;
571691 }
572692
573693 /* Common settings for corresponding Freescale CPU DAI driver */
574
- if (strstr(cpu_np->name, "ssi")) {
694
+ if (of_node_name_eq(cpu_np, "ssi")) {
575695 /* Only SSI needs to configure AUDMUX */
576696 ret = fsl_asoc_card_audmux_init(np, priv);
577697 if (ret) {
578698 dev_err(&pdev->dev, "failed to init audmux\n");
579699 goto asrc_fail;
580700 }
581
- } else if (strstr(cpu_np->name, "esai")) {
701
+ } else if (of_node_name_eq(cpu_np, "esai")) {
702
+ struct clk *esai_clk = clk_get(&cpu_pdev->dev, "extal");
703
+
704
+ if (!IS_ERR(esai_clk)) {
705
+ priv->cpu_priv.sysclk_freq[TX] = clk_get_rate(esai_clk);
706
+ priv->cpu_priv.sysclk_freq[RX] = clk_get_rate(esai_clk);
707
+ clk_put(esai_clk);
708
+ } else if (PTR_ERR(esai_clk) == -EPROBE_DEFER) {
709
+ ret = -EPROBE_DEFER;
710
+ goto asrc_fail;
711
+ }
712
+
582713 priv->cpu_priv.sysclk_id[1] = ESAI_HCKT_EXTAL;
583714 priv->cpu_priv.sysclk_id[0] = ESAI_HCKR_EXTAL;
584
- } else if (strstr(cpu_np->name, "sai")) {
715
+ } else if (of_node_name_eq(cpu_np, "sai")) {
585716 priv->cpu_priv.sysclk_id[1] = FSL_SAI_CLK_MAST1;
586717 priv->cpu_priv.sysclk_id[0] = FSL_SAI_CLK_MAST1;
587718 }
588719
589
- snprintf(priv->name, sizeof(priv->name), "%s-audio",
590
- fsl_asoc_card_is_ac97(priv) ? "ac97" :
591
- codec_dev->name);
592
-
593720 /* Initialize sound card */
594721 priv->pdev = pdev;
595722 priv->card.dev = &pdev->dev;
596
- priv->card.name = priv->name;
723
+ priv->card.owner = THIS_MODULE;
724
+ ret = snd_soc_of_parse_card_name(&priv->card, "model");
725
+ if (ret) {
726
+ snprintf(priv->name, sizeof(priv->name), "%s-audio",
727
+ fsl_asoc_card_is_ac97(priv) ? "ac97" : codec_dev_name);
728
+ priv->card.name = priv->name;
729
+ }
597730 priv->card.dai_link = priv->dai_link;
598
- priv->card.dapm_routes = fsl_asoc_card_is_ac97(priv) ?
599
- audio_map_ac97 : audio_map;
600731 priv->card.late_probe = fsl_asoc_card_late_probe;
601
- priv->card.num_dapm_routes = ARRAY_SIZE(audio_map);
602732 priv->card.dapm_widgets = fsl_asoc_card_dapm_widgets;
603733 priv->card.num_dapm_widgets = ARRAY_SIZE(fsl_asoc_card_dapm_widgets);
604734
....@@ -606,21 +736,20 @@
606736 if (!asrc_pdev)
607737 priv->card.num_dapm_routes /= 2;
608738
609
- memcpy(priv->dai_link, fsl_asoc_card_dai,
610
- sizeof(struct snd_soc_dai_link) * ARRAY_SIZE(priv->dai_link));
611
-
612
- ret = snd_soc_of_parse_audio_routing(&priv->card, "audio-routing");
613
- if (ret) {
614
- dev_err(&pdev->dev, "failed to parse audio-routing: %d\n", ret);
615
- goto asrc_fail;
739
+ if (of_property_read_bool(np, "audio-routing")) {
740
+ ret = snd_soc_of_parse_audio_routing(&priv->card, "audio-routing");
741
+ if (ret) {
742
+ dev_err(&pdev->dev, "failed to parse audio-routing: %d\n", ret);
743
+ goto asrc_fail;
744
+ }
616745 }
617746
618747 /* Normal DAI Link */
619
- priv->dai_link[0].cpu_of_node = cpu_np;
620
- priv->dai_link[0].codec_dai_name = codec_dai_name;
748
+ priv->dai_link[0].cpus->of_node = cpu_np;
749
+ priv->dai_link[0].codecs->dai_name = codec_dai_name;
621750
622751 if (!fsl_asoc_card_is_ac97(priv))
623
- priv->dai_link[0].codec_of_node = codec_np;
752
+ priv->dai_link[0].codecs->of_node = codec_np;
624753 else {
625754 u32 idx;
626755
....@@ -631,29 +760,29 @@
631760 goto asrc_fail;
632761 }
633762
634
- priv->dai_link[0].codec_name =
763
+ priv->dai_link[0].codecs->name =
635764 devm_kasprintf(&pdev->dev, GFP_KERNEL,
636765 "ac97-codec.%u",
637766 (unsigned int)idx);
638
- if (!priv->dai_link[0].codec_name) {
767
+ if (!priv->dai_link[0].codecs->name) {
639768 ret = -ENOMEM;
640769 goto asrc_fail;
641770 }
642771 }
643772
644
- priv->dai_link[0].platform_of_node = cpu_np;
773
+ priv->dai_link[0].platforms->of_node = cpu_np;
645774 priv->dai_link[0].dai_fmt = priv->dai_fmt;
646775 priv->card.num_links = 1;
647776
648777 if (asrc_pdev) {
649778 /* DPCM DAI Links only if ASRC exsits */
650
- priv->dai_link[1].cpu_of_node = asrc_np;
651
- priv->dai_link[1].platform_of_node = asrc_np;
652
- priv->dai_link[2].codec_dai_name = codec_dai_name;
653
- priv->dai_link[2].codec_of_node = codec_np;
654
- priv->dai_link[2].codec_name =
655
- priv->dai_link[0].codec_name;
656
- priv->dai_link[2].cpu_of_node = cpu_np;
779
+ priv->dai_link[1].cpus->of_node = asrc_np;
780
+ priv->dai_link[1].platforms->of_node = asrc_np;
781
+ priv->dai_link[2].codecs->dai_name = codec_dai_name;
782
+ priv->dai_link[2].codecs->of_node = codec_np;
783
+ priv->dai_link[2].codecs->name =
784
+ priv->dai_link[0].codecs->name;
785
+ priv->dai_link[2].cpus->of_node = cpu_np;
657786 priv->dai_link[2].dai_fmt = priv->dai_fmt;
658787 priv->card.num_links = 3;
659788
....@@ -665,17 +794,23 @@
665794 goto asrc_fail;
666795 }
667796
668
- ret = of_property_read_u32(asrc_np, "fsl,asrc-width", &width);
797
+ ret = of_property_read_u32(asrc_np, "fsl,asrc-format",
798
+ &priv->asrc_format);
669799 if (ret) {
670
- dev_err(&pdev->dev, "failed to get output rate\n");
671
- ret = -EINVAL;
672
- goto asrc_fail;
673
- }
800
+ /* Fallback to old binding; translate to asrc_format */
801
+ ret = of_property_read_u32(asrc_np, "fsl,asrc-width",
802
+ &width);
803
+ if (ret) {
804
+ dev_err(&pdev->dev,
805
+ "failed to decide output format\n");
806
+ goto asrc_fail;
807
+ }
674808
675
- if (width == 24)
676
- priv->asrc_format = SNDRV_PCM_FORMAT_S24_LE;
677
- else
678
- priv->asrc_format = SNDRV_PCM_FORMAT_S16_LE;
809
+ if (width == 24)
810
+ priv->asrc_format = SNDRV_PCM_FORMAT_S24_LE;
811
+ else
812
+ priv->asrc_format = SNDRV_PCM_FORMAT_S16_LE;
813
+ }
679814 }
680815
681816 /* Finish card registering */
....@@ -683,8 +818,37 @@
683818 snd_soc_card_set_drvdata(&priv->card, priv);
684819
685820 ret = devm_snd_soc_register_card(&pdev->dev, &priv->card);
686
- if (ret && ret != -EPROBE_DEFER)
687
- dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret);
821
+ if (ret) {
822
+ if (ret != -EPROBE_DEFER)
823
+ dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret);
824
+ goto asrc_fail;
825
+ }
826
+
827
+ /*
828
+ * Properties "hp-det-gpio" and "mic-det-gpio" are optional, and
829
+ * asoc_simple_init_jack uses these properties for creating
830
+ * Headphone Jack and Microphone Jack.
831
+ *
832
+ * The notifier is initialized in snd_soc_card_jack_new(), then
833
+ * snd_soc_jack_notifier_register can be called.
834
+ */
835
+ if (of_property_read_bool(np, "hp-det-gpio")) {
836
+ ret = asoc_simple_init_jack(&priv->card, &priv->hp_jack,
837
+ 1, NULL, "Headphone Jack");
838
+ if (ret)
839
+ goto asrc_fail;
840
+
841
+ snd_soc_jack_notifier_register(&priv->hp_jack.jack, &hp_jack_nb);
842
+ }
843
+
844
+ if (of_property_read_bool(np, "mic-det-gpio")) {
845
+ ret = asoc_simple_init_jack(&priv->card, &priv->mic_jack,
846
+ 0, NULL, "Mic Jack");
847
+ if (ret)
848
+ goto asrc_fail;
849
+
850
+ snd_soc_jack_notifier_register(&priv->mic_jack.jack, &mic_jack_nb);
851
+ }
688852
689853 asrc_fail:
690854 of_node_put(asrc_np);
....@@ -700,9 +864,12 @@
700864 { .compatible = "fsl,imx-audio-ac97", },
701865 { .compatible = "fsl,imx-audio-cs42888", },
702866 { .compatible = "fsl,imx-audio-cs427x", },
867
+ { .compatible = "fsl,imx-audio-tlv320aic32x4", },
703868 { .compatible = "fsl,imx-audio-sgtl5000", },
704869 { .compatible = "fsl,imx-audio-wm8962", },
705870 { .compatible = "fsl,imx-audio-wm8960", },
871
+ { .compatible = "fsl,imx-audio-mqs", },
872
+ { .compatible = "fsl,imx-audio-wm8524", },
706873 {}
707874 };
708875 MODULE_DEVICE_TABLE(of, fsl_asoc_card_dt_ids);