1 // SPDX-License-Identifier: GPL-2.0
2 //
3 // simple-card-utils.c
4 //
5 // Copyright (c) 2016 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
6
7 #include <dt-bindings/sound/audio-graph.h>
8 #include <linux/cleanup.h>
9 #include <linux/clk.h>
10 #include <linux/gpio/consumer.h>
11 #include <linux/module.h>
12 #include <linux/of.h>
13 #include <linux/of_graph.h>
14 #include <sound/jack.h>
15 #include <sound/pcm_params.h>
16 #include <sound/simple_card_utils.h>
17
18 #define simple_ret(priv, ret) _simple_ret(priv, __func__, ret)
_simple_ret(struct simple_util_priv * priv,const char * func,int ret)19 static inline int _simple_ret(struct simple_util_priv *priv,
20 const char *func, int ret)
21 {
22 return snd_soc_ret(simple_priv_to_dev(priv), ret, "at %s()\n", func);
23 }
24
simple_util_get_sample_fmt(struct simple_util_data * data)25 int simple_util_get_sample_fmt(struct simple_util_data *data)
26 {
27 int i;
28 int val = -EINVAL;
29
30 struct {
31 char *fmt;
32 u32 val;
33 } of_sample_fmt_table[] = {
34 { "s8", SNDRV_PCM_FORMAT_S8},
35 { "s16_le", SNDRV_PCM_FORMAT_S16_LE},
36 { "s24_le", SNDRV_PCM_FORMAT_S24_LE},
37 { "s24_3le", SNDRV_PCM_FORMAT_S24_3LE},
38 { "s32_le", SNDRV_PCM_FORMAT_S32_LE},
39 };
40
41 for (i = 0; i < ARRAY_SIZE(of_sample_fmt_table); i++) {
42 if (!strcmp(data->convert_sample_format,
43 of_sample_fmt_table[i].fmt)) {
44 val = of_sample_fmt_table[i].val;
45 break;
46 }
47 }
48 return val;
49 }
50 EXPORT_SYMBOL_GPL(simple_util_get_sample_fmt);
51
simple_fixup_sample_fmt(struct simple_util_data * data,struct snd_pcm_hw_params * params)52 static void simple_fixup_sample_fmt(struct simple_util_data *data,
53 struct snd_pcm_hw_params *params)
54 {
55 int val;
56 struct snd_mask *mask = hw_param_mask(params,
57 SNDRV_PCM_HW_PARAM_FORMAT);
58
59 val = simple_util_get_sample_fmt(data);
60 if (val >= 0) {
61 snd_mask_none(mask);
62 snd_mask_set(mask, val);
63 }
64 }
65
simple_util_parse_convert(struct device_node * np,char * prefix,struct simple_util_data * data)66 void simple_util_parse_convert(struct device_node *np,
67 char *prefix,
68 struct simple_util_data *data)
69 {
70 char prop[128];
71
72 if (!np)
73 return;
74
75 if (!prefix)
76 prefix = "";
77
78 /* sampling rate convert */
79 snprintf(prop, sizeof(prop), "%s%s", prefix, "convert-rate");
80 of_property_read_u32(np, prop, &data->convert_rate);
81
82 /* channels transfer */
83 snprintf(prop, sizeof(prop), "%s%s", prefix, "convert-channels");
84 of_property_read_u32(np, prop, &data->convert_channels);
85
86 /* convert sample format */
87 snprintf(prop, sizeof(prop), "%s%s", prefix, "convert-sample-format");
88 of_property_read_string(np, prop, &data->convert_sample_format);
89 }
90 EXPORT_SYMBOL_GPL(simple_util_parse_convert);
91
92 /**
93 * simple_util_is_convert_required() - Query if HW param conversion was requested
94 * @data: Link data.
95 *
96 * Returns true if any HW param conversion was requested for this DAI link with
97 * any "convert-xxx" properties.
98 */
simple_util_is_convert_required(const struct simple_util_data * data)99 bool simple_util_is_convert_required(const struct simple_util_data *data)
100 {
101 return data->convert_rate ||
102 data->convert_channels ||
103 data->convert_sample_format;
104 }
105 EXPORT_SYMBOL_GPL(simple_util_is_convert_required);
106
simple_util_parse_daifmt(struct device * dev,struct device_node * node,struct device_node * codec,char * prefix,unsigned int * retfmt)107 int simple_util_parse_daifmt(struct device *dev,
108 struct device_node *node,
109 struct device_node *codec,
110 char *prefix,
111 unsigned int *retfmt)
112 {
113 struct device_node *bitclkmaster = NULL;
114 struct device_node *framemaster = NULL;
115 unsigned int daifmt;
116
117 daifmt = snd_soc_daifmt_parse_format(node, prefix);
118
119 snd_soc_daifmt_parse_clock_provider_as_phandle(node, prefix, &bitclkmaster, &framemaster);
120 if (!bitclkmaster && !framemaster) {
121 /*
122 * No dai-link level and master setting was not found from
123 * sound node level, revert back to legacy DT parsing and
124 * take the settings from codec node.
125 */
126 dev_dbg(dev, "Revert to legacy daifmt parsing\n");
127
128 daifmt |= snd_soc_daifmt_parse_clock_provider_as_flag(codec, NULL);
129 } else {
130 daifmt |= snd_soc_daifmt_clock_provider_from_bitmap(
131 ((codec == bitclkmaster) << 4) | (codec == framemaster));
132 }
133
134 of_node_put(bitclkmaster);
135 of_node_put(framemaster);
136
137 *retfmt = daifmt;
138
139 return 0;
140 }
141 EXPORT_SYMBOL_GPL(simple_util_parse_daifmt);
142
simple_util_parse_tdm_width_map(struct simple_util_priv * priv,struct device_node * np,struct simple_util_dai * dai)143 int simple_util_parse_tdm_width_map(struct simple_util_priv *priv, struct device_node *np,
144 struct simple_util_dai *dai)
145 {
146 struct device *dev = simple_priv_to_dev(priv);
147 int n, i, ret;
148 u32 *p;
149
150 /*
151 * NOTE
152 *
153 * Clang doesn't allow to use "goto end" before calling __free(),
154 * because it bypasses the initialization. Use simple_ret() directly.
155 */
156
157 n = of_property_count_elems_of_size(np, "dai-tdm-slot-width-map", sizeof(u32));
158 if (n <= 0)
159 return 0;
160
161 if (n % 3) {
162 dev_err(dev, "Invalid number of cells for dai-tdm-slot-width-map\n");
163 return simple_ret(priv, -EINVAL); /* see NOTE */
164 }
165
166 ret = -ENOMEM;
167 dai->tdm_width_map = devm_kcalloc(dev, n, sizeof(*dai->tdm_width_map), GFP_KERNEL);
168 if (!dai->tdm_width_map)
169 return simple_ret(priv, ret); /* see NOTE */
170
171 u32 *array_values __free(kfree) = kcalloc(n, sizeof(*array_values), GFP_KERNEL);
172 if (!array_values)
173 goto end;
174
175 ret = of_property_read_u32_array(np, "dai-tdm-slot-width-map", array_values, n);
176 if (ret < 0) {
177 dev_err(dev, "Could not read dai-tdm-slot-width-map: %d\n", ret);
178 goto end;
179 }
180
181 p = array_values;
182 for (i = 0; i < n / 3; ++i) {
183 dai->tdm_width_map[i].sample_bits = *p++;
184 dai->tdm_width_map[i].slot_width = *p++;
185 dai->tdm_width_map[i].slot_count = *p++;
186 }
187
188 dai->n_tdm_widths = i;
189 ret = 0;
190 end:
191 return simple_ret(priv, ret);
192 }
193 EXPORT_SYMBOL_GPL(simple_util_parse_tdm_width_map);
194
simple_util_set_dailink_name(struct simple_util_priv * priv,struct snd_soc_dai_link * dai_link,const char * fmt,...)195 int simple_util_set_dailink_name(struct simple_util_priv *priv,
196 struct snd_soc_dai_link *dai_link,
197 const char *fmt, ...)
198 {
199 struct device *dev = simple_priv_to_dev(priv);
200 va_list ap;
201 char *name = NULL;
202 int ret = -ENOMEM;
203
204 va_start(ap, fmt);
205 name = devm_kvasprintf(dev, GFP_KERNEL, fmt, ap);
206 va_end(ap);
207
208 if (name) {
209 ret = 0;
210
211 dai_link->name = name;
212 dai_link->stream_name = name;
213 }
214
215 return simple_ret(priv, ret);
216 }
217 EXPORT_SYMBOL_GPL(simple_util_set_dailink_name);
218
simple_util_parse_card_name(struct simple_util_priv * priv,char * prefix)219 int simple_util_parse_card_name(struct simple_util_priv *priv,
220 char *prefix)
221 {
222 struct snd_soc_card *card = simple_priv_to_card(priv);
223 int ret;
224
225 if (!prefix)
226 prefix = "";
227
228 /* Parse the card name from DT */
229 ret = snd_soc_of_parse_card_name(card, "label");
230 if (ret < 0 || !card->name) {
231 char prop[128];
232
233 snprintf(prop, sizeof(prop), "%sname", prefix);
234 ret = snd_soc_of_parse_card_name(card, prop);
235 if (ret < 0)
236 goto end;
237 }
238
239 if (!card->name && card->dai_link)
240 card->name = card->dai_link->name;
241 end:
242 return simple_ret(priv, ret);
243 }
244 EXPORT_SYMBOL_GPL(simple_util_parse_card_name);
245
simple_clk_enable(struct simple_util_dai * dai)246 static int simple_clk_enable(struct simple_util_dai *dai)
247 {
248 if (dai)
249 return clk_prepare_enable(dai->clk);
250
251 return 0;
252 }
253
simple_clk_disable(struct simple_util_dai * dai)254 static void simple_clk_disable(struct simple_util_dai *dai)
255 {
256 if (dai)
257 clk_disable_unprepare(dai->clk);
258 }
259
simple_util_parse_clk(struct device * dev,struct device_node * node,struct simple_util_dai * simple_dai,struct snd_soc_dai_link_component * dlc)260 int simple_util_parse_clk(struct device *dev,
261 struct device_node *node,
262 struct simple_util_dai *simple_dai,
263 struct snd_soc_dai_link_component *dlc)
264 {
265 struct clk *clk;
266 u32 val;
267
268 /*
269 * Parse dai->sysclk come from "clocks = <&xxx>"
270 * (if system has common clock)
271 * or "system-clock-frequency = <xxx>"
272 * or device's module clock.
273 */
274 clk = devm_get_clk_from_child(dev, node, NULL);
275 simple_dai->clk_fixed = of_property_read_bool(
276 node, "system-clock-fixed");
277 if (!IS_ERR(clk)) {
278 simple_dai->sysclk = clk_get_rate(clk);
279
280 simple_dai->clk = clk;
281 } else if (!of_property_read_u32(node, "system-clock-frequency", &val)) {
282 simple_dai->sysclk = val;
283 simple_dai->clk_fixed = true;
284 } else {
285 clk = devm_get_clk_from_child(dev, dlc->of_node, NULL);
286 if (!IS_ERR(clk))
287 simple_dai->sysclk = clk_get_rate(clk);
288 }
289
290 if (of_property_read_bool(node, "system-clock-direction-out"))
291 simple_dai->clk_direction = SND_SOC_CLOCK_OUT;
292
293 return 0;
294 }
295 EXPORT_SYMBOL_GPL(simple_util_parse_clk);
296
simple_check_fixed_sysclk(struct device * dev,struct simple_util_dai * dai,unsigned int * fixed_sysclk)297 static int simple_check_fixed_sysclk(struct device *dev,
298 struct simple_util_dai *dai,
299 unsigned int *fixed_sysclk)
300 {
301 if (dai->clk_fixed) {
302 if (*fixed_sysclk && *fixed_sysclk != dai->sysclk) {
303 dev_err(dev, "inconsistent fixed sysclk rates (%u vs %u)\n",
304 *fixed_sysclk, dai->sysclk);
305 return -EINVAL;
306 }
307 *fixed_sysclk = dai->sysclk;
308 }
309
310 return 0;
311 }
312
simple_util_startup(struct snd_pcm_substream * substream)313 int simple_util_startup(struct snd_pcm_substream *substream)
314 {
315 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
316 struct simple_util_priv *priv = snd_soc_card_get_drvdata(rtd->card);
317 struct simple_dai_props *props = runtime_simple_priv_to_props(priv, rtd);
318 struct simple_util_dai *dai;
319 unsigned int fixed_sysclk = 0;
320 int i1, i2, i;
321 int ret;
322
323 for_each_prop_dai_cpu(props, i1, dai) {
324 ret = simple_clk_enable(dai);
325 if (ret)
326 goto cpu_err;
327 ret = simple_check_fixed_sysclk(rtd->dev, dai, &fixed_sysclk);
328 if (ret)
329 goto cpu_err;
330 }
331
332 for_each_prop_dai_codec(props, i2, dai) {
333 ret = simple_clk_enable(dai);
334 if (ret)
335 goto codec_err;
336 ret = simple_check_fixed_sysclk(rtd->dev, dai, &fixed_sysclk);
337 if (ret)
338 goto codec_err;
339 }
340
341 if (fixed_sysclk && props->mclk_fs) {
342 unsigned int fixed_rate = fixed_sysclk / props->mclk_fs;
343
344 if (fixed_sysclk % props->mclk_fs) {
345 dev_err(rtd->dev, "fixed sysclk %u not divisible by mclk_fs %u\n",
346 fixed_sysclk, props->mclk_fs);
347 ret = -EINVAL;
348 goto codec_err;
349 }
350 ret = snd_pcm_hw_constraint_minmax(substream->runtime, SNDRV_PCM_HW_PARAM_RATE,
351 fixed_rate, fixed_rate);
352 if (ret < 0)
353 goto codec_err;
354 }
355
356 return 0;
357
358 codec_err:
359 for_each_prop_dai_codec(props, i, dai) {
360 if (i >= i2)
361 break;
362 simple_clk_disable(dai);
363 }
364 cpu_err:
365 for_each_prop_dai_cpu(props, i, dai) {
366 if (i >= i1)
367 break;
368 simple_clk_disable(dai);
369 }
370
371 return simple_ret(priv, ret);
372 }
373 EXPORT_SYMBOL_GPL(simple_util_startup);
374
simple_util_shutdown(struct snd_pcm_substream * substream)375 void simple_util_shutdown(struct snd_pcm_substream *substream)
376 {
377 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
378 struct simple_util_priv *priv = snd_soc_card_get_drvdata(rtd->card);
379 struct simple_dai_props *props = runtime_simple_priv_to_props(priv, rtd);
380 struct simple_util_dai *dai;
381 int i;
382
383 for_each_prop_dai_cpu(props, i, dai) {
384 struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, i);
385
386 if (props->mclk_fs && !dai->clk_fixed && !snd_soc_dai_active(cpu_dai))
387 snd_soc_dai_set_sysclk(cpu_dai, 0, 0, dai->clk_direction);
388
389 simple_clk_disable(dai);
390 }
391 for_each_prop_dai_codec(props, i, dai) {
392 struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, i);
393
394 if (props->mclk_fs && !dai->clk_fixed && !snd_soc_dai_active(codec_dai))
395 snd_soc_dai_set_sysclk(codec_dai, 0, 0, dai->clk_direction);
396
397 simple_clk_disable(dai);
398 }
399 }
400 EXPORT_SYMBOL_GPL(simple_util_shutdown);
401
simple_set_clk_rate(struct simple_util_priv * priv,struct simple_util_dai * simple_dai,unsigned long rate)402 static int simple_set_clk_rate(struct simple_util_priv *priv,
403 struct simple_util_dai *simple_dai,
404 unsigned long rate)
405 {
406 struct device *dev = simple_priv_to_dev(priv);
407 int ret = -EINVAL;
408
409 if (!simple_dai)
410 return 0;
411
412 if (simple_dai->clk_fixed && rate != simple_dai->sysclk) {
413 dev_err(dev, "dai %s invalid clock rate %lu\n", simple_dai->name, rate);
414 goto end;
415 }
416
417 if (!simple_dai->clk)
418 return 0;
419
420 if (clk_get_rate(simple_dai->clk) == rate)
421 return 0;
422
423 ret = clk_set_rate(simple_dai->clk, rate);
424 end:
425 return simple_ret(priv, ret);
426 }
427
simple_set_tdm(struct simple_util_priv * priv,struct snd_soc_dai * dai,struct simple_util_dai * simple_dai,struct snd_pcm_hw_params * params)428 static int simple_set_tdm(struct simple_util_priv *priv,
429 struct snd_soc_dai *dai,
430 struct simple_util_dai *simple_dai,
431 struct snd_pcm_hw_params *params)
432 {
433 int sample_bits = params_width(params);
434 int slot_width, slot_count;
435 int i, ret;
436
437 if (!simple_dai || !simple_dai->tdm_width_map)
438 return 0;
439
440 slot_width = simple_dai->slot_width;
441 slot_count = simple_dai->slots;
442
443 if (slot_width == 0)
444 slot_width = sample_bits;
445
446 for (i = 0; i < simple_dai->n_tdm_widths; ++i) {
447 if (simple_dai->tdm_width_map[i].sample_bits == sample_bits) {
448 slot_width = simple_dai->tdm_width_map[i].slot_width;
449 slot_count = simple_dai->tdm_width_map[i].slot_count;
450 break;
451 }
452 }
453
454 ret = snd_soc_dai_set_tdm_slot(dai,
455 simple_dai->tx_slot_mask,
456 simple_dai->rx_slot_mask,
457 slot_count,
458 slot_width);
459
460 return simple_ret(priv, ret);
461 }
462
simple_util_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params)463 int simple_util_hw_params(struct snd_pcm_substream *substream,
464 struct snd_pcm_hw_params *params)
465 {
466 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
467 struct simple_util_dai *pdai;
468 struct snd_soc_dai *sdai;
469 struct simple_util_priv *priv = snd_soc_card_get_drvdata(rtd->card);
470 struct simple_dai_props *props = runtime_simple_priv_to_props(priv, rtd);
471 enum simple_util_sysclk_order order = props->sysclk_order;
472 unsigned int mclk, mclk_fs = 0;
473 int i, ret;
474
475 if (props->mclk_fs)
476 mclk_fs = props->mclk_fs;
477
478 if (mclk_fs) {
479 struct snd_soc_component *component;
480 mclk = params_rate(params) * mclk_fs;
481
482 for_each_prop_dai_codec(props, i, pdai) {
483 ret = simple_set_clk_rate(priv, pdai, mclk);
484 if (ret < 0)
485 goto end;
486 }
487
488 for_each_prop_dai_cpu(props, i, pdai) {
489 ret = simple_set_clk_rate(priv, pdai, mclk);
490 if (ret < 0)
491 goto end;
492 }
493
494 /* Ensure sysclk is set on all components in case any
495 * (such as platform components) are missed by calls to
496 * snd_soc_dai_set_sysclk.
497 */
498 for_each_rtd_components(rtd, i, component) {
499 ret = snd_soc_component_set_sysclk(component, 0, 0,
500 mclk, SND_SOC_CLOCK_IN);
501 if (ret && ret != -ENOTSUPP)
502 goto end;
503 }
504
505 if (order == SIMPLE_SYSCLK_ORDER_CPU_FIRST) {
506 /* CPU first */
507 for_each_rtd_cpu_dais(rtd, i, sdai) {
508 pdai = simple_props_to_dai_cpu(props, i);
509 ret = snd_soc_dai_set_sysclk(sdai, 0, mclk, pdai->clk_direction);
510 if (ret && ret != -ENOTSUPP)
511 goto end;
512 }
513
514 for_each_rtd_codec_dais(rtd, i, sdai) {
515 pdai = simple_props_to_dai_codec(props, i);
516 ret = snd_soc_dai_set_sysclk(sdai, 0, mclk, pdai->clk_direction);
517 if (ret && ret != -ENOTSUPP)
518 goto end;
519 }
520 } else {
521 /* default: codec first */
522 for_each_rtd_codec_dais(rtd, i, sdai) {
523 pdai = simple_props_to_dai_codec(props, i);
524 ret = snd_soc_dai_set_sysclk(sdai, 0, mclk, pdai->clk_direction);
525 if (ret && ret != -ENOTSUPP)
526 goto end;
527 }
528
529 for_each_rtd_cpu_dais(rtd, i, sdai) {
530 pdai = simple_props_to_dai_cpu(props, i);
531 ret = snd_soc_dai_set_sysclk(sdai, 0, mclk, pdai->clk_direction);
532 if (ret && ret != -ENOTSUPP)
533 goto end;
534 }
535 }
536 }
537
538 for_each_prop_dai_codec(props, i, pdai) {
539 sdai = snd_soc_rtd_to_codec(rtd, i);
540 ret = simple_set_tdm(priv, sdai, pdai, params);
541 if (ret < 0)
542 goto end;
543 }
544
545 for_each_prop_dai_cpu(props, i, pdai) {
546 sdai = snd_soc_rtd_to_cpu(rtd, i);
547 ret = simple_set_tdm(priv, sdai, pdai, params);
548 if (ret < 0)
549 goto end;
550 }
551 ret = 0;
552 end:
553 return simple_ret(priv, ret);
554 }
555 EXPORT_SYMBOL_GPL(simple_util_hw_params);
556
simple_util_be_hw_params_fixup(struct snd_soc_pcm_runtime * rtd,struct snd_pcm_hw_params * params)557 int simple_util_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
558 struct snd_pcm_hw_params *params)
559 {
560 struct simple_util_priv *priv = snd_soc_card_get_drvdata(rtd->card);
561 struct simple_dai_props *dai_props = runtime_simple_priv_to_props(priv, rtd);
562 struct simple_util_data *data = &dai_props->adata;
563 struct snd_interval *rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
564 struct snd_interval *channels = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
565
566 if (data->convert_rate)
567 rate->min =
568 rate->max = data->convert_rate;
569
570 if (data->convert_channels)
571 channels->min =
572 channels->max = data->convert_channels;
573
574 if (data->convert_sample_format)
575 simple_fixup_sample_fmt(data, params);
576
577 return 0;
578 }
579 EXPORT_SYMBOL_GPL(simple_util_be_hw_params_fixup);
580
simple_init_dai(struct simple_util_priv * priv,struct snd_soc_dai * dai,struct simple_util_dai * simple_dai)581 static int simple_init_dai(struct simple_util_priv *priv,
582 struct snd_soc_dai *dai, struct simple_util_dai *simple_dai)
583 {
584 int ret;
585
586 if (!simple_dai)
587 return 0;
588
589 if (simple_dai->sysclk) {
590 ret = snd_soc_dai_set_sysclk(dai, 0, simple_dai->sysclk,
591 simple_dai->clk_direction);
592 if (ret && ret != -ENOTSUPP) {
593 dev_err(dai->dev, "simple-card: set_sysclk error\n");
594 goto end;
595 }
596 }
597
598 if (simple_dai->slots) {
599 ret = snd_soc_dai_set_tdm_slot(dai,
600 simple_dai->tx_slot_mask,
601 simple_dai->rx_slot_mask,
602 simple_dai->slots,
603 simple_dai->slot_width);
604 if (ret && ret != -ENOTSUPP) {
605 dev_err(dai->dev, "simple-card: set_tdm_slot error\n");
606 goto end;
607 }
608 }
609 ret = 0;
610 end:
611 return simple_ret(priv, ret);
612 }
613
simple_component_is_codec(struct snd_soc_component * component)614 static inline int simple_component_is_codec(struct snd_soc_component *component)
615 {
616 return component->driver->endianness;
617 }
618
simple_init_for_codec2codec(struct simple_util_priv * priv,struct snd_soc_pcm_runtime * rtd,struct simple_dai_props * dai_props)619 static int simple_init_for_codec2codec(struct simple_util_priv *priv,
620 struct snd_soc_pcm_runtime *rtd,
621 struct simple_dai_props *dai_props)
622 {
623 struct snd_soc_dai_link *dai_link = rtd->dai_link;
624 struct snd_soc_component *component;
625 struct snd_soc_pcm_stream *c2c_params;
626 struct snd_pcm_hardware hw;
627 int i, ret, stream;
628
629 /* Do nothing if it already has Codec2Codec settings */
630 if (dai_link->c2c_params)
631 return 0;
632
633 /* Do nothing if it was DPCM :: BE */
634 if (dai_link->no_pcm)
635 return 0;
636
637 /* Only Codecs */
638 for_each_rtd_components(rtd, i, component) {
639 if (!simple_component_is_codec(component))
640 return 0;
641 }
642
643 /* Assumes the capabilities are the same for all supported streams */
644 for_each_pcm_streams(stream) {
645 ret = snd_soc_runtime_calc_hw(rtd, &hw, stream);
646 if (ret == 0)
647 break;
648 }
649
650 if (ret < 0) {
651 dev_err(rtd->dev, "simple-card: no valid dai_link params\n");
652 goto end;
653 }
654
655 ret = -ENOMEM;
656 c2c_params = devm_kzalloc(rtd->dev, sizeof(*c2c_params), GFP_KERNEL);
657 if (!c2c_params)
658 goto end;
659
660 c2c_params->formats = hw.formats;
661 c2c_params->rates = hw.rates;
662 c2c_params->rate_min = hw.rate_min;
663 c2c_params->rate_max = hw.rate_max;
664 c2c_params->channels_min = hw.channels_min;
665 c2c_params->channels_max = hw.channels_max;
666
667 dai_link->c2c_params = c2c_params;
668 dai_link->num_c2c_params = 1;
669
670 ret = 0;
671 end:
672 return simple_ret(priv, ret);
673 }
674
simple_util_dai_init(struct snd_soc_pcm_runtime * rtd)675 int simple_util_dai_init(struct snd_soc_pcm_runtime *rtd)
676 {
677 struct simple_util_priv *priv = snd_soc_card_get_drvdata(rtd->card);
678 struct simple_dai_props *props = runtime_simple_priv_to_props(priv, rtd);
679 struct simple_util_dai *dai;
680 int i, ret;
681
682 for_each_prop_dai_codec(props, i, dai) {
683 ret = simple_init_dai(priv, snd_soc_rtd_to_codec(rtd, i), dai);
684 if (ret < 0)
685 goto end;
686 }
687 for_each_prop_dai_cpu(props, i, dai) {
688 ret = simple_init_dai(priv, snd_soc_rtd_to_cpu(rtd, i), dai);
689 if (ret < 0)
690 goto end;
691 }
692
693 ret = simple_init_for_codec2codec(priv, rtd, props);
694 end:
695 return simple_ret(priv, ret);
696 }
697 EXPORT_SYMBOL_GPL(simple_util_dai_init);
698
simple_util_canonicalize_platform(struct snd_soc_dai_link_component * platforms,struct snd_soc_dai_link_component * cpus)699 void simple_util_canonicalize_platform(struct snd_soc_dai_link_component *platforms,
700 struct snd_soc_dai_link_component *cpus)
701 {
702 /*
703 * Assumes Platform == CPU
704 *
705 * Some CPU might be using soc-generic-dmaengine-pcm. This means CPU and Platform
706 * are different Component, but are sharing same component->dev.
707 *
708 * Let's assume Platform is same as CPU if it doesn't identify Platform on DT.
709 * see
710 * simple-card.c :: simple_count_noml()
711 */
712 if (!platforms->of_node)
713 snd_soc_dlc_use_cpu_as_platform(platforms, cpus);
714 }
715 EXPORT_SYMBOL_GPL(simple_util_canonicalize_platform);
716
simple_util_canonicalize_cpu(struct snd_soc_dai_link_component * cpus,int is_single_links)717 void simple_util_canonicalize_cpu(struct snd_soc_dai_link_component *cpus,
718 int is_single_links)
719 {
720 /*
721 * In snd_soc_add_pcm_runtime() will check cpu name after
722 * of_node matching if dai_link has cpu_dai_name.
723 * but, it will never match if name was created by
724 * fmt_single_name() remove cpu_dai_name if cpu_args
725 * was 0. See:
726 * fmt_single_name()
727 * fmt_multiple_name()
728 */
729 if (is_single_links)
730 cpus->dai_name = NULL;
731 }
732 EXPORT_SYMBOL_GPL(simple_util_canonicalize_cpu);
733
simple_util_clean_reference(struct snd_soc_card * card)734 void simple_util_clean_reference(struct snd_soc_card *card)
735 {
736 struct snd_soc_dai_link *dai_link;
737 struct snd_soc_dai_link_component *cpu;
738 struct snd_soc_dai_link_component *codec;
739 int i, j;
740
741 for_each_card_prelinks(card, i, dai_link) {
742 for_each_link_cpus(dai_link, j, cpu)
743 of_node_put(cpu->of_node);
744 for_each_link_codecs(dai_link, j, codec)
745 of_node_put(codec->of_node);
746 }
747 }
748 EXPORT_SYMBOL_GPL(simple_util_clean_reference);
749
simple_util_parse_routing(struct snd_soc_card * card,char * prefix)750 int simple_util_parse_routing(struct snd_soc_card *card,
751 char *prefix)
752 {
753 struct device_node *node = card->dev->of_node;
754 char prop[128];
755
756 if (!prefix)
757 prefix = "";
758
759 snprintf(prop, sizeof(prop), "%s%s", prefix, "routing");
760
761 if (!of_property_present(node, prop))
762 return 0;
763
764 return snd_soc_of_parse_audio_routing(card, prop);
765 }
766 EXPORT_SYMBOL_GPL(simple_util_parse_routing);
767
simple_util_parse_widgets(struct snd_soc_card * card,char * prefix)768 int simple_util_parse_widgets(struct snd_soc_card *card,
769 char *prefix)
770 {
771 struct device_node *node = card->dev->of_node;
772 char prop[128];
773
774 if (!prefix)
775 prefix = "";
776
777 snprintf(prop, sizeof(prop), "%s%s", prefix, "widgets");
778
779 if (of_property_present(node, prop))
780 return snd_soc_of_parse_audio_simple_widgets(card, prop);
781
782 /* no widgets is not error */
783 return 0;
784 }
785 EXPORT_SYMBOL_GPL(simple_util_parse_widgets);
786
simple_util_parse_pin_switches(struct snd_soc_card * card,char * prefix)787 int simple_util_parse_pin_switches(struct snd_soc_card *card,
788 char *prefix)
789 {
790 char prop[128];
791
792 if (!prefix)
793 prefix = "";
794
795 snprintf(prop, sizeof(prop), "%s%s", prefix, "pin-switches");
796
797 return snd_soc_of_parse_pin_switches(card, prop);
798 }
799 EXPORT_SYMBOL_GPL(simple_util_parse_pin_switches);
800
simple_util_init_jack(struct snd_soc_card * card,struct simple_util_jack * sjack,int is_hp,char * prefix,char * pin)801 int simple_util_init_jack(struct snd_soc_card *card,
802 struct simple_util_jack *sjack,
803 int is_hp, char *prefix,
804 char *pin)
805 {
806 struct device *dev = card->dev;
807 struct gpio_desc *desc;
808 char prop[128];
809 char *pin_name;
810 char *gpio_name;
811 int mask;
812 int error;
813
814 if (!prefix)
815 prefix = "";
816
817 if (is_hp) {
818 snprintf(prop, sizeof(prop), "%shp-det", prefix);
819 pin_name = pin ? pin : "Headphones";
820 gpio_name = "Headphone detection";
821 mask = SND_JACK_HEADPHONE;
822 } else {
823 snprintf(prop, sizeof(prop), "%smic-det", prefix);
824 pin_name = pin ? pin : "Mic Jack";
825 gpio_name = "Mic detection";
826 mask = SND_JACK_MICROPHONE;
827 }
828
829 desc = gpiod_get_optional(dev, prop, GPIOD_IN);
830 error = PTR_ERR_OR_ZERO(desc);
831 if (error)
832 return error;
833
834 if (desc) {
835 error = gpiod_set_consumer_name(desc, gpio_name);
836 if (error)
837 return error;
838
839 sjack->pin.pin = pin_name;
840 sjack->pin.mask = mask;
841
842 sjack->gpio.name = gpio_name;
843 sjack->gpio.report = mask;
844 sjack->gpio.desc = desc;
845 sjack->gpio.debounce_time = 150;
846
847 snd_soc_card_jack_new_pins(card, pin_name, mask, &sjack->jack,
848 &sjack->pin, 1);
849
850 snd_soc_jack_add_gpios(&sjack->jack, 1, &sjack->gpio);
851 }
852
853 return 0;
854 }
855 EXPORT_SYMBOL_GPL(simple_util_init_jack);
856
simple_util_init_aux_jacks(struct simple_util_priv * priv,char * prefix)857 int simple_util_init_aux_jacks(struct simple_util_priv *priv, char *prefix)
858 {
859 struct snd_soc_card *card = simple_priv_to_card(priv);
860 struct snd_soc_component *component;
861 int found_jack_index = 0;
862 int type = 0;
863 int num = 0;
864 int ret;
865
866 if (priv->aux_jacks)
867 return 0;
868
869 for_each_card_auxs(card, component) {
870 type = snd_soc_component_get_jack_type(component);
871 if (type > 0)
872 num++;
873 }
874 if (num < 1)
875 return 0;
876
877 priv->aux_jacks = devm_kcalloc(card->dev, num,
878 sizeof(struct snd_soc_jack), GFP_KERNEL);
879 if (!priv->aux_jacks)
880 return simple_ret(priv, -ENOMEM);
881
882 for_each_card_auxs(card, component) {
883 char id[128];
884 struct snd_soc_jack *jack;
885
886 if (found_jack_index >= num)
887 break;
888
889 type = snd_soc_component_get_jack_type(component);
890 if (type <= 0)
891 continue;
892
893 /* create jack */
894 jack = &(priv->aux_jacks[found_jack_index++]);
895 snprintf(id, sizeof(id), "%s-jack", component->name);
896 ret = snd_soc_card_jack_new(card, id, type, jack);
897 if (ret)
898 continue;
899
900 (void)snd_soc_component_set_jack(component, jack, NULL);
901 }
902 return 0;
903 }
904 EXPORT_SYMBOL_GPL(simple_util_init_aux_jacks);
905
906 static struct simple_util_dai dummy_util_dais = {
907 .name = "dummy_util_dais",
908 };
909
simple_util_init_priv(struct simple_util_priv * priv,struct link_info * li)910 int simple_util_init_priv(struct simple_util_priv *priv,
911 struct link_info *li)
912 {
913 struct snd_soc_card *card = simple_priv_to_card(priv);
914 struct device *dev = simple_priv_to_dev(priv);
915 struct snd_soc_dai_link *dai_link;
916 struct simple_dai_props *dai_props;
917 struct simple_util_dai *dais;
918 struct snd_soc_dai_link_component *dlcs;
919 struct snd_soc_codec_conf *cconf = NULL;
920 int i, dai_num = 0, dlc_num = 0, cnf_num = 0;
921
922 dai_props = devm_kcalloc(dev, li->link, sizeof(*dai_props), GFP_KERNEL);
923 dai_link = devm_kcalloc(dev, li->link, sizeof(*dai_link), GFP_KERNEL);
924 if (!dai_props || !dai_link)
925 return -ENOMEM;
926
927 /*
928 * dais (= CPU+Codec)
929 * dlcs (= CPU+Codec+Platform)
930 */
931 for (i = 0; i < li->link; i++) {
932 int cc = li->num[i].cpus + li->num[i].codecs;
933
934 dai_num += cc;
935 dlc_num += cc + li->num[i].platforms;
936
937 if (!li->num[i].cpus)
938 cnf_num += li->num[i].codecs;
939 }
940
941 dais = devm_kcalloc(dev, dai_num, sizeof(*dais), GFP_KERNEL);
942 dlcs = devm_kcalloc(dev, dlc_num, sizeof(*dlcs), GFP_KERNEL);
943 if (!dais || !dlcs)
944 return -ENOMEM;
945
946 if (cnf_num) {
947 cconf = devm_kcalloc(dev, cnf_num, sizeof(*cconf), GFP_KERNEL);
948 if (!cconf)
949 return -ENOMEM;
950 }
951
952 dev_dbg(dev, "link %d, dais %d, ccnf %d\n",
953 li->link, dai_num, cnf_num);
954
955 priv->dai_props = dai_props;
956 priv->dai_link = dai_link;
957 priv->dais = dais;
958 priv->dlcs = dlcs;
959 priv->codec_conf = cconf;
960
961 card->dai_link = priv->dai_link;
962 card->num_links = li->link;
963 card->codec_conf = cconf;
964 card->num_configs = cnf_num;
965
966 for (i = 0; i < li->link; i++) {
967 if (li->num[i].cpus) {
968 /* Normal CPU */
969 dai_link[i].cpus = dlcs;
970 dai_props[i].num.cpus =
971 dai_link[i].num_cpus = li->num[i].cpus;
972 dai_props[i].cpu_dai = dais;
973
974 dlcs += li->num[i].cpus;
975 dais += li->num[i].cpus;
976 } else {
977 /* DPCM Be's CPU = dummy */
978 dai_link[i].cpus = &snd_soc_dummy_dlc;
979 dai_props[i].num.cpus =
980 dai_link[i].num_cpus = 1;
981 dai_props[i].cpu_dai = &dummy_util_dais;
982 }
983
984 if (li->num[i].codecs) {
985 /* Normal Codec */
986 dai_link[i].codecs = dlcs;
987 dai_props[i].num.codecs =
988 dai_link[i].num_codecs = li->num[i].codecs;
989 dai_props[i].codec_dai = dais;
990
991 dlcs += li->num[i].codecs;
992 dais += li->num[i].codecs;
993
994 if (!li->num[i].cpus) {
995 /* DPCM Be's Codec */
996 dai_props[i].codec_conf = cconf;
997 cconf += li->num[i].codecs;
998 }
999 } else {
1000 /* DPCM Fe's Codec = dummy */
1001 dai_link[i].codecs = &snd_soc_dummy_dlc;
1002 dai_props[i].num.codecs =
1003 dai_link[i].num_codecs = 1;
1004 dai_props[i].codec_dai = &dummy_util_dais;
1005 }
1006
1007 if (li->num[i].platforms) {
1008 /* Have Platform */
1009 dai_link[i].platforms = dlcs;
1010 dai_props[i].num.platforms =
1011 dai_link[i].num_platforms = li->num[i].platforms;
1012
1013 dlcs += li->num[i].platforms;
1014 } else {
1015 /* Doesn't have Platform */
1016 dai_link[i].platforms = NULL;
1017 dai_props[i].num.platforms =
1018 dai_link[i].num_platforms = 0;
1019 }
1020 }
1021
1022 return 0;
1023 }
1024 EXPORT_SYMBOL_GPL(simple_util_init_priv);
1025
simple_util_remove(struct platform_device * pdev)1026 void simple_util_remove(struct platform_device *pdev)
1027 {
1028 struct snd_soc_card *card = platform_get_drvdata(pdev);
1029
1030 simple_util_clean_reference(card);
1031 }
1032 EXPORT_SYMBOL_GPL(simple_util_remove);
1033
graph_util_card_probe(struct snd_soc_card * card)1034 int graph_util_card_probe(struct snd_soc_card *card)
1035 {
1036 struct simple_util_priv *priv = snd_soc_card_get_drvdata(card);
1037 int ret;
1038
1039 ret = simple_util_init_hp(card, &priv->hp_jack, NULL);
1040 if (ret < 0)
1041 goto end;
1042
1043 ret = simple_util_init_mic(card, &priv->mic_jack, NULL);
1044 end:
1045 return simple_ret(priv, ret);
1046 }
1047 EXPORT_SYMBOL_GPL(graph_util_card_probe);
1048
graph_util_is_ports0(struct device_node * np)1049 int graph_util_is_ports0(struct device_node *np)
1050 {
1051 struct device_node *parent __free(device_node) = of_get_parent(np);
1052 struct device_node *port;
1053
1054 /* np is "endpoint" or "port" */
1055 if (of_node_name_eq(np, "endpoint"))
1056 port = parent;
1057 else
1058 port = np;
1059
1060 struct device_node *ports __free(device_node) = of_get_parent(port);
1061 const char *at = strchr(kbasename(ports->full_name), '@');
1062
1063 /*
1064 * Since child iteration order may differ
1065 * between a base DT and DT overlays,
1066 * string match "ports" or "ports@0" in the node name instead.
1067 */
1068 return !at || !strcmp(at, "@0");
1069 }
1070 EXPORT_SYMBOL_GPL(graph_util_is_ports0);
1071
graph_get_dai_id(struct device_node * ep)1072 static int graph_get_dai_id(struct device_node *ep)
1073 {
1074 struct device_node *node __free(device_node) = of_graph_get_port_parent(ep);
1075 struct device_node *port __free(device_node) = of_get_parent(ep);
1076 struct of_endpoint info;
1077 int i, id;
1078 int ret;
1079
1080 /* use driver specified DAI ID if exist */
1081 ret = snd_soc_get_dai_id(ep);
1082 if (ret != -ENOTSUPP)
1083 return ret;
1084
1085 /* use endpoint/port reg if exist */
1086 ret = of_graph_parse_endpoint(ep, &info);
1087 if (ret == 0) {
1088 /*
1089 * Because it will count port/endpoint if it doesn't have "reg".
1090 * But, we can't judge whether it has "no reg", or "reg = <0>"
1091 * only of_graph_parse_endpoint().
1092 * We need to check "reg" property
1093 */
1094
1095 /* check port first */
1096 ret = of_property_present(port, "reg");
1097 if (ret)
1098 return info.port;
1099
1100 /* check endpoint 2nd as backup */
1101 if (of_property_present(ep, "reg"))
1102 return info.id;
1103 }
1104
1105 /*
1106 * Non HDMI sound case, counting port/endpoint on its DT
1107 * is enough. Let's count it.
1108 */
1109 i = 0;
1110 id = -1;
1111 for_each_of_graph_port(node, p) {
1112 if (port == p) {
1113 id = i;
1114 break;
1115 }
1116 i++;
1117 }
1118
1119 if (id < 0)
1120 return -ENODEV;
1121
1122 return id;
1123 }
1124
graph_util_parse_dai(struct simple_util_priv * priv,struct device_node * ep,struct snd_soc_dai_link_component * dlc,int * is_single_link)1125 int graph_util_parse_dai(struct simple_util_priv *priv, struct device_node *ep,
1126 struct snd_soc_dai_link_component *dlc, int *is_single_link)
1127 {
1128 struct device *dev = simple_priv_to_dev(priv);
1129 struct device_node *node;
1130 struct of_phandle_args args = {};
1131 struct snd_soc_dai_link_component resolved_dlc = {};
1132 struct snd_soc_dai *dai;
1133 const char *fallback_dai_name;
1134 int ret;
1135
1136 if (!ep)
1137 return 0;
1138
1139 node = of_graph_get_port_parent(ep);
1140
1141 /*
1142 * Try to find from DAI node
1143 */
1144 args.np = ep;
1145 dai = snd_soc_get_dai_via_args(&args);
1146 if (dai) {
1147 const char *dai_name = snd_soc_dai_name_get(dai);
1148 const struct of_phandle_args *dai_args = snd_soc_copy_dai_args(dev, &args);
1149
1150 ret = -ENOMEM;
1151 if (!dai_args)
1152 goto err;
1153
1154 dlc->of_node = node;
1155 dlc->dai_name = dai_name;
1156 dlc->dai_args = dai_args;
1157 } else {
1158 /* Get dai->name */
1159 args.np = node;
1160 args.args[0] = graph_get_dai_id(ep);
1161 args.args_count = (of_graph_get_endpoint_count(node) > 1);
1162
1163 ret = snd_soc_get_dlc(&args, &resolved_dlc);
1164 if (ret < 0)
1165 goto err;
1166
1167 /* Keep fallback dai_name valid across component rebind */
1168 fallback_dai_name = resolved_dlc.dai_name;
1169 if (fallback_dai_name) {
1170 fallback_dai_name = devm_kstrdup_const(dev, fallback_dai_name,
1171 GFP_KERNEL);
1172 ret = -ENOMEM;
1173 if (!fallback_dai_name)
1174 goto err;
1175 }
1176
1177 dlc->of_node = resolved_dlc.of_node;
1178 dlc->dai_name = fallback_dai_name;
1179 dlc->dai_args = resolved_dlc.dai_args;
1180 }
1181
1182 if (is_single_link)
1183 *is_single_link = of_graph_get_endpoint_count(node) == 1;
1184 ret = 0;
1185 err:
1186 if (ret < 0)
1187 of_node_put(node);
1188
1189 return simple_ret(priv, ret);
1190 }
1191 EXPORT_SYMBOL_GPL(graph_util_parse_dai);
1192
graph_util_parse_link_direction(struct device_node * np,bool * playback_only,bool * capture_only)1193 void graph_util_parse_link_direction(struct device_node *np,
1194 bool *playback_only, bool *capture_only)
1195 {
1196 bool is_playback_only = of_property_read_bool(np, "playback-only");
1197 bool is_capture_only = of_property_read_bool(np, "capture-only");
1198
1199 if (playback_only && is_playback_only)
1200 *playback_only = is_playback_only;
1201 if (capture_only && is_capture_only)
1202 *capture_only = is_capture_only;
1203 }
1204 EXPORT_SYMBOL_GPL(graph_util_parse_link_direction);
1205
1206 static enum snd_soc_trigger_order
__graph_util_parse_trigger_order(struct simple_util_priv * priv,struct device_node * np,const char * prop)1207 __graph_util_parse_trigger_order(struct simple_util_priv *priv,
1208 struct device_node *np,
1209 const char *prop)
1210 {
1211 u32 val[SND_SOC_TRIGGER_SIZE];
1212 int ret;
1213
1214 ret = of_property_read_u32_array(np, prop, val, SND_SOC_TRIGGER_SIZE);
1215 if (ret == 0) {
1216 struct device *dev = simple_priv_to_dev(priv);
1217 u32 order = (val[0] << 8) +
1218 (val[1] << 4) +
1219 (val[2]);
1220
1221 switch (order) {
1222 case (SND_SOC_TRIGGER_LINK << 8) +
1223 (SND_SOC_TRIGGER_COMPONENT << 4) +
1224 (SND_SOC_TRIGGER_DAI):
1225 return SND_SOC_TRIGGER_ORDER_DEFAULT;
1226
1227 case (SND_SOC_TRIGGER_LINK << 8) +
1228 (SND_SOC_TRIGGER_DAI << 4) +
1229 (SND_SOC_TRIGGER_COMPONENT):
1230 return SND_SOC_TRIGGER_ORDER_LDC;
1231
1232 default:
1233 dev_err(dev, "unsupported trigger order [0x%x]\n", order);
1234 }
1235 }
1236
1237 /* SND_SOC_TRIGGER_ORDER_MAX means error */
1238 return SND_SOC_TRIGGER_ORDER_MAX;
1239 }
1240
graph_util_parse_trigger_order(struct simple_util_priv * priv,struct device_node * np,enum snd_soc_trigger_order * trigger_start,enum snd_soc_trigger_order * trigger_stop)1241 void graph_util_parse_trigger_order(struct simple_util_priv *priv,
1242 struct device_node *np,
1243 enum snd_soc_trigger_order *trigger_start,
1244 enum snd_soc_trigger_order *trigger_stop)
1245 {
1246 static enum snd_soc_trigger_order order;
1247
1248 /*
1249 * We can use it like below
1250 *
1251 * #include <dt-bindings/sound/audio-graph.h>
1252 *
1253 * link-trigger-order = <SND_SOC_TRIGGER_LINK
1254 * SND_SOC_TRIGGER_COMPONENT
1255 * SND_SOC_TRIGGER_DAI>;
1256 */
1257
1258 order = __graph_util_parse_trigger_order(priv, np, "link-trigger-order");
1259 if (order < SND_SOC_TRIGGER_ORDER_MAX) {
1260 *trigger_start = order;
1261 *trigger_stop = order;
1262 }
1263
1264 order = __graph_util_parse_trigger_order(priv, np, "link-trigger-order-start");
1265 if (order < SND_SOC_TRIGGER_ORDER_MAX)
1266 *trigger_start = order;
1267
1268 order = __graph_util_parse_trigger_order(priv, np, "link-trigger-order-stop");
1269 if (order < SND_SOC_TRIGGER_ORDER_MAX)
1270 *trigger_stop = order;
1271
1272 return;
1273 }
1274 EXPORT_SYMBOL_GPL(graph_util_parse_trigger_order);
1275
1276 /* Module information */
1277 MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");
1278 MODULE_DESCRIPTION("ALSA SoC Simple Card Utils");
1279 MODULE_LICENSE("GPL v2");
1280