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