1 // SPDX-License-Identifier: (GPL-2.0 OR MIT)
3 // Copyright (c) 2018 BayLibre, SAS.
4 // Author: Jerome Brunet <jbrunet@baylibre.com>
6 #include <linux/module.h>
7 #include <linux/of_platform.h>
9 #include <sound/soc-dai.h>
14 struct snd_soc_card card
;
18 struct axg_dai_link_tdm_mask
{
23 struct axg_dai_link_tdm_data
{
26 unsigned int slot_width
;
29 struct axg_dai_link_tdm_mask
*codec_masks
;
32 #define PREFIX "amlogic,"
34 static int axg_card_reallocate_links(struct axg_card
*priv
,
35 unsigned int num_links
)
37 struct snd_soc_dai_link
*links
;
40 links
= krealloc(priv
->card
.dai_link
,
41 num_links
* sizeof(*priv
->card
.dai_link
),
42 GFP_KERNEL
| __GFP_ZERO
);
43 ldata
= krealloc(priv
->link_data
,
44 num_links
* sizeof(*priv
->link_data
),
45 GFP_KERNEL
| __GFP_ZERO
);
47 if (!links
|| !ldata
) {
48 dev_err(priv
->card
.dev
, "failed to allocate links\n");
52 priv
->card
.dai_link
= links
;
53 priv
->link_data
= ldata
;
54 priv
->card
.num_links
= num_links
;
58 static int axg_card_parse_dai(struct snd_soc_card
*card
,
59 struct device_node
*node
,
60 struct device_node
**dai_of_node
,
61 const char **dai_name
)
63 struct of_phandle_args args
;
66 if (!dai_name
|| !dai_of_node
|| !node
)
69 ret
= of_parse_phandle_with_args(node
, "sound-dai",
70 "#sound-dai-cells", 0, &args
);
72 if (ret
!= -EPROBE_DEFER
)
73 dev_err(card
->dev
, "can't parse dai %d\n", ret
);
76 *dai_of_node
= args
.np
;
78 return snd_soc_get_dai_name(&args
, dai_name
);
81 static int axg_card_set_link_name(struct snd_soc_card
*card
,
82 struct snd_soc_dai_link
*link
,
85 char *name
= devm_kasprintf(card
->dev
, GFP_KERNEL
, "%s.%s",
86 prefix
, link
->cpu_of_node
->full_name
);
91 link
->stream_name
= name
;
96 static void axg_card_clean_references(struct axg_card
*priv
)
98 struct snd_soc_card
*card
= &priv
->card
;
99 struct snd_soc_dai_link
*link
;
100 struct snd_soc_dai_link_component
*codec
;
103 if (card
->dai_link
) {
104 for_each_card_prelinks(card
, i
, link
) {
105 of_node_put(link
->cpu_of_node
);
106 for_each_link_codecs(link
, j
, codec
)
107 of_node_put(codec
->of_node
);
112 for (i
= 0; i
< card
->num_aux_devs
; i
++)
113 of_node_put(card
->aux_dev
[i
].codec_of_node
);
116 kfree(card
->dai_link
);
117 kfree(priv
->link_data
);
120 static int axg_card_add_aux_devices(struct snd_soc_card
*card
)
122 struct device_node
*node
= card
->dev
->of_node
;
123 struct snd_soc_aux_dev
*aux
;
126 num
= of_count_phandle_with_args(node
, "audio-aux-devs", NULL
);
127 if (num
== -ENOENT
) {
129 * It is ok to have no auxiliary devices but for this card it
130 * is a strange situtation. Let's warn the about it.
132 dev_warn(card
->dev
, "card has no auxiliary devices\n");
134 } else if (num
< 0) {
135 dev_err(card
->dev
, "error getting auxiliary devices: %d\n",
140 aux
= devm_kcalloc(card
->dev
, num
, sizeof(*aux
), GFP_KERNEL
);
144 card
->num_aux_devs
= num
;
146 for (i
= 0; i
< card
->num_aux_devs
; i
++, aux
++) {
148 of_parse_phandle(node
, "audio-aux-devs", i
);
149 if (!aux
->codec_of_node
)
156 static int axg_card_tdm_be_hw_params(struct snd_pcm_substream
*substream
,
157 struct snd_pcm_hw_params
*params
)
159 struct snd_soc_pcm_runtime
*rtd
= substream
->private_data
;
160 struct axg_card
*priv
= snd_soc_card_get_drvdata(rtd
->card
);
161 struct axg_dai_link_tdm_data
*be
=
162 (struct axg_dai_link_tdm_data
*)priv
->link_data
[rtd
->num
];
163 struct snd_soc_dai
*codec_dai
;
168 mclk
= params_rate(params
) * be
->mclk_fs
;
170 for_each_rtd_codec_dai(rtd
, i
, codec_dai
) {
171 ret
= snd_soc_dai_set_sysclk(codec_dai
, 0, mclk
,
173 if (ret
&& ret
!= -ENOTSUPP
)
177 ret
= snd_soc_dai_set_sysclk(rtd
->cpu_dai
, 0, mclk
,
179 if (ret
&& ret
!= -ENOTSUPP
)
186 static const struct snd_soc_ops axg_card_tdm_be_ops
= {
187 .hw_params
= axg_card_tdm_be_hw_params
,
190 static int axg_card_tdm_dai_init(struct snd_soc_pcm_runtime
*rtd
)
192 struct axg_card
*priv
= snd_soc_card_get_drvdata(rtd
->card
);
193 struct axg_dai_link_tdm_data
*be
=
194 (struct axg_dai_link_tdm_data
*)priv
->link_data
[rtd
->num
];
195 struct snd_soc_dai
*codec_dai
;
198 for_each_rtd_codec_dai(rtd
, i
, codec_dai
) {
199 ret
= snd_soc_dai_set_tdm_slot(codec_dai
,
200 be
->codec_masks
[i
].tx
,
201 be
->codec_masks
[i
].rx
,
202 be
->slots
, be
->slot_width
);
203 if (ret
&& ret
!= -ENOTSUPP
) {
204 dev_err(codec_dai
->dev
,
205 "setting tdm link slots failed\n");
210 ret
= axg_tdm_set_tdm_slots(rtd
->cpu_dai
, be
->tx_mask
, be
->rx_mask
,
211 be
->slots
, be
->slot_width
);
213 dev_err(rtd
->cpu_dai
->dev
, "setting tdm link slots failed\n");
220 static int axg_card_tdm_dai_lb_init(struct snd_soc_pcm_runtime
*rtd
)
222 struct axg_card
*priv
= snd_soc_card_get_drvdata(rtd
->card
);
223 struct axg_dai_link_tdm_data
*be
=
224 (struct axg_dai_link_tdm_data
*)priv
->link_data
[rtd
->num
];
227 /* The loopback rx_mask is the pad tx_mask */
228 ret
= axg_tdm_set_tdm_slots(rtd
->cpu_dai
, NULL
, be
->tx_mask
,
229 be
->slots
, be
->slot_width
);
231 dev_err(rtd
->cpu_dai
->dev
, "setting tdm link slots failed\n");
238 static int axg_card_add_tdm_loopback(struct snd_soc_card
*card
,
241 struct axg_card
*priv
= snd_soc_card_get_drvdata(card
);
242 struct snd_soc_dai_link
*pad
= &card
->dai_link
[*index
];
243 struct snd_soc_dai_link
*lb
;
247 ret
= axg_card_reallocate_links(priv
, card
->num_links
+ 1);
251 lb
= &card
->dai_link
[*index
+ 1];
253 lb
->name
= kasprintf(GFP_KERNEL
, "%s-lb", pad
->name
);
257 lb
->stream_name
= lb
->name
;
258 lb
->cpu_of_node
= pad
->cpu_of_node
;
259 lb
->cpu_dai_name
= "TDM Loopback";
260 lb
->codec_name
= "snd-soc-dummy";
261 lb
->codec_dai_name
= "snd-soc-dummy-dai";
262 lb
->dpcm_capture
= 1;
264 lb
->ops
= &axg_card_tdm_be_ops
;
265 lb
->init
= axg_card_tdm_dai_lb_init
;
267 /* Provide the same link data to the loopback */
268 priv
->link_data
[*index
+ 1] = priv
->link_data
[*index
];
271 * axg_card_clean_references() will iterate over this link,
272 * make sure the node count is balanced
274 of_node_get(lb
->cpu_of_node
);
276 /* Let add_links continue where it should */
282 static unsigned int axg_card_parse_daifmt(struct device_node
*node
,
283 struct device_node
*cpu_node
)
285 struct device_node
*bitclkmaster
= NULL
;
286 struct device_node
*framemaster
= NULL
;
289 daifmt
= snd_soc_of_parse_daifmt(node
, PREFIX
,
290 &bitclkmaster
, &framemaster
);
291 daifmt
&= ~SND_SOC_DAIFMT_MASTER_MASK
;
293 /* If no master is provided, default to cpu master */
294 if (!bitclkmaster
|| bitclkmaster
== cpu_node
) {
295 daifmt
|= (!framemaster
|| framemaster
== cpu_node
) ?
296 SND_SOC_DAIFMT_CBS_CFS
: SND_SOC_DAIFMT_CBS_CFM
;
298 daifmt
|= (!framemaster
|| framemaster
== cpu_node
) ?
299 SND_SOC_DAIFMT_CBM_CFS
: SND_SOC_DAIFMT_CBM_CFM
;
302 of_node_put(bitclkmaster
);
303 of_node_put(framemaster
);
308 static int axg_card_parse_cpu_tdm_slots(struct snd_soc_card
*card
,
309 struct snd_soc_dai_link
*link
,
310 struct device_node
*node
,
311 struct axg_dai_link_tdm_data
*be
)
317 be
->tx_mask
= devm_kcalloc(card
->dev
, AXG_TDM_NUM_LANES
,
318 sizeof(*be
->tx_mask
), GFP_KERNEL
);
319 be
->rx_mask
= devm_kcalloc(card
->dev
, AXG_TDM_NUM_LANES
,
320 sizeof(*be
->rx_mask
), GFP_KERNEL
);
321 if (!be
->tx_mask
|| !be
->rx_mask
)
324 for (i
= 0, tx
= 0; i
< AXG_TDM_NUM_LANES
; i
++) {
325 snprintf(propname
, 32, "dai-tdm-slot-tx-mask-%d", i
);
326 snd_soc_of_get_slot_mask(node
, propname
, &be
->tx_mask
[i
]);
327 tx
= max(tx
, be
->tx_mask
[i
]);
330 /* Disable playback is the interface has no tx slots */
332 link
->dpcm_playback
= 0;
334 for (i
= 0, rx
= 0; i
< AXG_TDM_NUM_LANES
; i
++) {
335 snprintf(propname
, 32, "dai-tdm-slot-rx-mask-%d", i
);
336 snd_soc_of_get_slot_mask(node
, propname
, &be
->rx_mask
[i
]);
337 rx
= max(rx
, be
->rx_mask
[i
]);
340 /* Disable capture is the interface has no rx slots */
342 link
->dpcm_capture
= 0;
344 /* ... but the interface should at least have one of them */
346 dev_err(card
->dev
, "tdm link has no cpu slots\n");
350 of_property_read_u32(node
, "dai-tdm-slot-num", &be
->slots
);
353 * If the slot number is not provided, set it such as it
354 * accommodates the largest mask
356 be
->slots
= fls(max(tx
, rx
));
357 } else if (be
->slots
< fls(max(tx
, rx
)) || be
->slots
> 32) {
359 * Error if the slots can't accommodate the largest mask or
360 * if it is just too big
362 dev_err(card
->dev
, "bad slot number\n");
366 of_property_read_u32(node
, "dai-tdm-slot-width", &be
->slot_width
);
371 static int axg_card_parse_codecs_masks(struct snd_soc_card
*card
,
372 struct snd_soc_dai_link
*link
,
373 struct device_node
*node
,
374 struct axg_dai_link_tdm_data
*be
)
376 struct axg_dai_link_tdm_mask
*codec_mask
;
377 struct device_node
*np
;
379 codec_mask
= devm_kcalloc(card
->dev
, link
->num_codecs
,
380 sizeof(*codec_mask
), GFP_KERNEL
);
384 be
->codec_masks
= codec_mask
;
386 for_each_child_of_node(node
, np
) {
387 snd_soc_of_get_slot_mask(np
, "dai-tdm-slot-rx-mask",
389 snd_soc_of_get_slot_mask(np
, "dai-tdm-slot-tx-mask",
398 static int axg_card_parse_tdm(struct snd_soc_card
*card
,
399 struct device_node
*node
,
402 struct axg_card
*priv
= snd_soc_card_get_drvdata(card
);
403 struct snd_soc_dai_link
*link
= &card
->dai_link
[*index
];
404 struct axg_dai_link_tdm_data
*be
;
407 /* Allocate tdm link parameters */
408 be
= devm_kzalloc(card
->dev
, sizeof(*be
), GFP_KERNEL
);
411 priv
->link_data
[*index
] = be
;
414 link
->ops
= &axg_card_tdm_be_ops
;
415 link
->init
= axg_card_tdm_dai_init
;
416 link
->dai_fmt
= axg_card_parse_daifmt(node
, link
->cpu_of_node
);
418 of_property_read_u32(node
, "mclk-fs", &be
->mclk_fs
);
420 ret
= axg_card_parse_cpu_tdm_slots(card
, link
, node
, be
);
422 dev_err(card
->dev
, "error parsing tdm link slots\n");
426 ret
= axg_card_parse_codecs_masks(card
, link
, node
, be
);
430 /* Add loopback if the pad dai has playback */
431 if (link
->dpcm_playback
) {
432 ret
= axg_card_add_tdm_loopback(card
, index
);
440 static int axg_card_set_be_link(struct snd_soc_card
*card
,
441 struct snd_soc_dai_link
*link
,
442 struct device_node
*node
)
444 struct snd_soc_dai_link_component
*codec
;
445 struct device_node
*np
;
449 link
->dpcm_playback
= 1;
450 link
->dpcm_capture
= 1;
452 num_codecs
= of_get_child_count(node
);
454 dev_err(card
->dev
, "be link %s has no codec\n",
459 codec
= devm_kcalloc(card
->dev
, num_codecs
, sizeof(*codec
), GFP_KERNEL
);
463 link
->codecs
= codec
;
464 link
->num_codecs
= num_codecs
;
466 for_each_child_of_node(node
, np
) {
467 ret
= axg_card_parse_dai(card
, np
, &codec
->of_node
,
477 ret
= axg_card_set_link_name(card
, link
, "be");
479 dev_err(card
->dev
, "error setting %pOFn link name\n", np
);
484 static int axg_card_set_fe_link(struct snd_soc_card
*card
,
485 struct snd_soc_dai_link
*link
,
489 link
->dpcm_merged_format
= 1;
490 link
->dpcm_merged_chan
= 1;
491 link
->dpcm_merged_rate
= 1;
492 link
->codec_dai_name
= "snd-soc-dummy-dai";
493 link
->codec_name
= "snd-soc-dummy";
496 link
->dpcm_playback
= 1;
498 link
->dpcm_capture
= 1;
500 return axg_card_set_link_name(card
, link
, "fe");
503 static int axg_card_cpu_is_capture_fe(struct device_node
*np
)
505 return of_device_is_compatible(np
, PREFIX
"axg-toddr");
508 static int axg_card_cpu_is_playback_fe(struct device_node
*np
)
510 return of_device_is_compatible(np
, PREFIX
"axg-frddr");
513 static int axg_card_cpu_is_tdm_iface(struct device_node
*np
)
515 return of_device_is_compatible(np
, PREFIX
"axg-tdm-iface");
518 static int axg_card_add_link(struct snd_soc_card
*card
, struct device_node
*np
,
521 struct snd_soc_dai_link
*dai_link
= &card
->dai_link
[*index
];
524 ret
= axg_card_parse_dai(card
, np
, &dai_link
->cpu_of_node
,
525 &dai_link
->cpu_dai_name
);
529 if (axg_card_cpu_is_playback_fe(dai_link
->cpu_of_node
))
530 ret
= axg_card_set_fe_link(card
, dai_link
, true);
531 else if (axg_card_cpu_is_capture_fe(dai_link
->cpu_of_node
))
532 ret
= axg_card_set_fe_link(card
, dai_link
, false);
534 ret
= axg_card_set_be_link(card
, dai_link
, np
);
539 if (axg_card_cpu_is_tdm_iface(dai_link
->cpu_of_node
))
540 ret
= axg_card_parse_tdm(card
, np
, index
);
545 static int axg_card_add_links(struct snd_soc_card
*card
)
547 struct axg_card
*priv
= snd_soc_card_get_drvdata(card
);
548 struct device_node
*node
= card
->dev
->of_node
;
549 struct device_node
*np
;
552 num
= of_get_child_count(node
);
554 dev_err(card
->dev
, "card has no links\n");
558 ret
= axg_card_reallocate_links(priv
, num
);
563 for_each_child_of_node(node
, np
) {
564 ret
= axg_card_add_link(card
, np
, &i
);
576 static int axg_card_parse_of_optional(struct snd_soc_card
*card
,
577 const char *propname
,
578 int (*func
)(struct snd_soc_card
*c
,
581 /* If property is not provided, don't fail ... */
582 if (!of_property_read_bool(card
->dev
->of_node
, propname
))
585 /* ... but do fail if it is provided and the parsing fails */
586 return func(card
, propname
);
589 static const struct of_device_id axg_card_of_match
[] = {
590 { .compatible
= "amlogic,axg-sound-card", },
593 MODULE_DEVICE_TABLE(of
, axg_card_of_match
);
595 static int axg_card_probe(struct platform_device
*pdev
)
597 struct device
*dev
= &pdev
->dev
;
598 struct axg_card
*priv
;
601 priv
= devm_kzalloc(dev
, sizeof(*priv
), GFP_KERNEL
);
605 platform_set_drvdata(pdev
, priv
);
606 snd_soc_card_set_drvdata(&priv
->card
, priv
);
608 priv
->card
.owner
= THIS_MODULE
;
609 priv
->card
.dev
= dev
;
611 ret
= snd_soc_of_parse_card_name(&priv
->card
, "model");
615 ret
= axg_card_parse_of_optional(&priv
->card
, "audio-routing",
616 snd_soc_of_parse_audio_routing
);
618 dev_err(dev
, "error while parsing routing\n");
622 ret
= axg_card_parse_of_optional(&priv
->card
, "audio-widgets",
623 snd_soc_of_parse_audio_simple_widgets
);
625 dev_err(dev
, "error while parsing widgets\n");
629 ret
= axg_card_add_links(&priv
->card
);
633 ret
= axg_card_add_aux_devices(&priv
->card
);
637 ret
= devm_snd_soc_register_card(dev
, &priv
->card
);
644 axg_card_clean_references(priv
);
648 static int axg_card_remove(struct platform_device
*pdev
)
650 struct axg_card
*priv
= platform_get_drvdata(pdev
);
652 axg_card_clean_references(priv
);
657 static struct platform_driver axg_card_pdrv
= {
658 .probe
= axg_card_probe
,
659 .remove
= axg_card_remove
,
661 .name
= "axg-sound-card",
662 .of_match_table
= axg_card_of_match
,
665 module_platform_driver(axg_card_pdrv
);
667 MODULE_DESCRIPTION("Amlogic AXG ALSA machine driver");
668 MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>");
669 MODULE_LICENSE("GPL v2");