1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2020 Texas Instruments Incorporated - http://www.ti.com
4 * Author: Peter Ujfalusi <peter.ujfalusi@ti.com>
8 #include <linux/module.h>
10 #include <linux/platform_device.h>
12 #include <sound/core.h>
13 #include <sound/pcm.h>
14 #include <sound/pcm_params.h>
15 #include <sound/soc.h>
17 #include "davinci-mcasp.h"
20 * Maximum number of configuration entries for prefixes:
21 * CPB: 2 (mcasp10 + codec)
22 * IVI: 3 (mcasp0 + 2x codec)
24 #define J721E_CODEC_CONF_COUNT 5
26 #define J721E_AUDIO_DOMAIN_CPB 0
27 #define J721E_AUDIO_DOMAIN_IVI 1
29 #define J721E_CLK_PARENT_48000 0
30 #define J721E_CLK_PARENT_44100 1
32 #define J721E_MAX_CLK_HSDIV 128
33 #define PCM1368A_MAX_SYSCLK 36864000
35 #define J721E_DAI_FMT (SND_SOC_DAIFMT_RIGHT_J | \
36 SND_SOC_DAIFMT_NB_NF | \
37 SND_SOC_DAIFMT_CBS_CFS)
39 enum j721e_board_type
{
44 struct j721e_audio_match_data
{
45 enum j721e_board_type board_type
;
47 unsigned int pll_rates
[2];
50 static unsigned int ratios_for_pcm3168a
[] = {
56 struct j721e_audio_clocks
{
58 struct clk
*parent
[2];
61 struct j721e_audio_domain
{
62 struct j721e_audio_clocks codec
;
63 struct j721e_audio_clocks mcasp
;
67 unsigned int active_link
;
73 struct snd_soc_card card
;
74 struct snd_soc_dai_link
*dai_links
;
75 struct snd_soc_codec_conf codec_conf
[J721E_CODEC_CONF_COUNT
];
76 struct snd_interval rate_range
;
77 const struct j721e_audio_match_data
*match_data
;
79 unsigned int hsdiv_rates
[2];
81 struct j721e_audio_domain audio_domains
[2];
86 static const struct snd_soc_dapm_widget j721e_cpb_dapm_widgets
[] = {
87 SND_SOC_DAPM_HP("CPB Stereo HP 1", NULL
),
88 SND_SOC_DAPM_HP("CPB Stereo HP 2", NULL
),
89 SND_SOC_DAPM_HP("CPB Stereo HP 3", NULL
),
90 SND_SOC_DAPM_LINE("CPB Line Out", NULL
),
91 SND_SOC_DAPM_MIC("CPB Stereo Mic 1", NULL
),
92 SND_SOC_DAPM_MIC("CPB Stereo Mic 2", NULL
),
93 SND_SOC_DAPM_LINE("CPB Line In", NULL
),
96 static const struct snd_soc_dapm_route j721e_cpb_dapm_routes
[] = {
97 {"CPB Stereo HP 1", NULL
, "codec-1 AOUT1L"},
98 {"CPB Stereo HP 1", NULL
, "codec-1 AOUT1R"},
99 {"CPB Stereo HP 2", NULL
, "codec-1 AOUT2L"},
100 {"CPB Stereo HP 2", NULL
, "codec-1 AOUT2R"},
101 {"CPB Stereo HP 3", NULL
, "codec-1 AOUT3L"},
102 {"CPB Stereo HP 3", NULL
, "codec-1 AOUT3R"},
103 {"CPB Line Out", NULL
, "codec-1 AOUT4L"},
104 {"CPB Line Out", NULL
, "codec-1 AOUT4R"},
106 {"codec-1 AIN1L", NULL
, "CPB Stereo Mic 1"},
107 {"codec-1 AIN1R", NULL
, "CPB Stereo Mic 1"},
108 {"codec-1 AIN2L", NULL
, "CPB Stereo Mic 2"},
109 {"codec-1 AIN2R", NULL
, "CPB Stereo Mic 2"},
110 {"codec-1 AIN3L", NULL
, "CPB Line In"},
111 {"codec-1 AIN3R", NULL
, "CPB Line In"},
114 static const struct snd_soc_dapm_widget j721e_ivi_codec_a_dapm_widgets
[] = {
115 SND_SOC_DAPM_LINE("IVI A Line Out 1", NULL
),
116 SND_SOC_DAPM_LINE("IVI A Line Out 2", NULL
),
117 SND_SOC_DAPM_LINE("IVI A Line Out 3", NULL
),
118 SND_SOC_DAPM_LINE("IVI A Line Out 4", NULL
),
119 SND_SOC_DAPM_MIC("IVI A Stereo Mic 1", NULL
),
120 SND_SOC_DAPM_MIC("IVI A Stereo Mic 2", NULL
),
121 SND_SOC_DAPM_LINE("IVI A Line In", NULL
),
124 static const struct snd_soc_dapm_route j721e_codec_a_dapm_routes
[] = {
125 {"IVI A Line Out 1", NULL
, "codec-a AOUT1L"},
126 {"IVI A Line Out 1", NULL
, "codec-a AOUT1R"},
127 {"IVI A Line Out 2", NULL
, "codec-a AOUT2L"},
128 {"IVI A Line Out 2", NULL
, "codec-a AOUT2R"},
129 {"IVI A Line Out 3", NULL
, "codec-a AOUT3L"},
130 {"IVI A Line Out 3", NULL
, "codec-a AOUT3R"},
131 {"IVI A Line Out 4", NULL
, "codec-a AOUT4L"},
132 {"IVI A Line Out 4", NULL
, "codec-a AOUT4R"},
134 {"codec-a AIN1L", NULL
, "IVI A Stereo Mic 1"},
135 {"codec-a AIN1R", NULL
, "IVI A Stereo Mic 1"},
136 {"codec-a AIN2L", NULL
, "IVI A Stereo Mic 2"},
137 {"codec-a AIN2R", NULL
, "IVI A Stereo Mic 2"},
138 {"codec-a AIN3L", NULL
, "IVI A Line In"},
139 {"codec-a AIN3R", NULL
, "IVI A Line In"},
142 static const struct snd_soc_dapm_widget j721e_ivi_codec_b_dapm_widgets
[] = {
143 SND_SOC_DAPM_LINE("IVI B Line Out 1", NULL
),
144 SND_SOC_DAPM_LINE("IVI B Line Out 2", NULL
),
145 SND_SOC_DAPM_LINE("IVI B Line Out 3", NULL
),
146 SND_SOC_DAPM_LINE("IVI B Line Out 4", NULL
),
147 SND_SOC_DAPM_MIC("IVI B Stereo Mic 1", NULL
),
148 SND_SOC_DAPM_MIC("IVI B Stereo Mic 2", NULL
),
149 SND_SOC_DAPM_LINE("IVI B Line In", NULL
),
152 static const struct snd_soc_dapm_route j721e_codec_b_dapm_routes
[] = {
153 {"IVI B Line Out 1", NULL
, "codec-b AOUT1L"},
154 {"IVI B Line Out 1", NULL
, "codec-b AOUT1R"},
155 {"IVI B Line Out 2", NULL
, "codec-b AOUT2L"},
156 {"IVI B Line Out 2", NULL
, "codec-b AOUT2R"},
157 {"IVI B Line Out 3", NULL
, "codec-b AOUT3L"},
158 {"IVI B Line Out 3", NULL
, "codec-b AOUT3R"},
159 {"IVI B Line Out 4", NULL
, "codec-b AOUT4L"},
160 {"IVI B Line Out 4", NULL
, "codec-b AOUT4R"},
162 {"codec-b AIN1L", NULL
, "IVI B Stereo Mic 1"},
163 {"codec-b AIN1R", NULL
, "IVI B Stereo Mic 1"},
164 {"codec-b AIN2L", NULL
, "IVI B Stereo Mic 2"},
165 {"codec-b AIN2R", NULL
, "IVI B Stereo Mic 2"},
166 {"codec-b AIN3L", NULL
, "IVI B Line In"},
167 {"codec-b AIN3R", NULL
, "IVI B Line In"},
170 static int j721e_configure_refclk(struct j721e_priv
*priv
,
171 unsigned int audio_domain
, unsigned int rate
)
173 struct j721e_audio_domain
*domain
= &priv
->audio_domains
[audio_domain
];
178 if (!(rate
% 8000) && priv
->pll_rates
[J721E_CLK_PARENT_48000
])
179 clk_id
= J721E_CLK_PARENT_48000
;
180 else if (!(rate
% 11025) && priv
->pll_rates
[J721E_CLK_PARENT_44100
])
181 clk_id
= J721E_CLK_PARENT_44100
;
185 for (i
= 0; i
< ARRAY_SIZE(ratios_for_pcm3168a
); i
++) {
186 scki
= ratios_for_pcm3168a
[i
] * rate
;
188 if (priv
->pll_rates
[clk_id
] / scki
<= J721E_MAX_CLK_HSDIV
) {
195 dev_err(priv
->dev
, "No valid clock configuration for %u Hz\n",
200 if (priv
->hsdiv_rates
[domain
->parent_clk_id
] != scki
) {
202 "%s configuration for %u Hz: %s, %dxFS (SCKI: %u Hz)\n",
203 audio_domain
== J721E_AUDIO_DOMAIN_CPB
? "CPB" : "IVI",
205 clk_id
== J721E_CLK_PARENT_48000
? "PLL4" : "PLL15",
206 ratios_for_pcm3168a
[i
], scki
);
208 if (domain
->parent_clk_id
!= clk_id
) {
209 ret
= clk_set_parent(domain
->codec
.target
,
210 domain
->codec
.parent
[clk_id
]);
214 ret
= clk_set_parent(domain
->mcasp
.target
,
215 domain
->mcasp
.parent
[clk_id
]);
219 domain
->parent_clk_id
= clk_id
;
222 ret
= clk_set_rate(domain
->codec
.target
, scki
);
224 dev_err(priv
->dev
, "codec set rate failed for %u Hz\n",
229 ret
= clk_set_rate(domain
->mcasp
.target
, scki
);
231 priv
->hsdiv_rates
[domain
->parent_clk_id
] = scki
;
233 dev_err(priv
->dev
, "mcasp set rate failed for %u Hz\n",
242 static int j721e_rule_rate(struct snd_pcm_hw_params
*params
,
243 struct snd_pcm_hw_rule
*rule
)
245 struct snd_interval
*t
= rule
->private;
247 return snd_interval_refine(hw_param_interval(params
, rule
->var
), t
);
250 static int j721e_audio_startup(struct snd_pcm_substream
*substream
)
252 struct snd_soc_pcm_runtime
*rtd
= asoc_substream_to_rtd(substream
);
253 struct j721e_priv
*priv
= snd_soc_card_get_drvdata(rtd
->card
);
254 unsigned int domain_id
= rtd
->dai_link
->id
;
255 struct j721e_audio_domain
*domain
= &priv
->audio_domains
[domain_id
];
256 struct snd_soc_dai
*cpu_dai
= asoc_rtd_to_cpu(rtd
, 0);
257 struct snd_soc_dai
*codec_dai
;
258 unsigned int active_rate
;
262 mutex_lock(&priv
->mutex
);
266 if (priv
->audio_domains
[J721E_AUDIO_DOMAIN_CPB
].rate
)
267 active_rate
= priv
->audio_domains
[J721E_AUDIO_DOMAIN_CPB
].rate
;
269 active_rate
= priv
->audio_domains
[J721E_AUDIO_DOMAIN_IVI
].rate
;
272 ret
= snd_pcm_hw_constraint_single(substream
->runtime
,
273 SNDRV_PCM_HW_PARAM_RATE
,
276 ret
= snd_pcm_hw_rule_add(substream
->runtime
, 0,
277 SNDRV_PCM_HW_PARAM_RATE
,
278 j721e_rule_rate
, &priv
->rate_range
,
279 SNDRV_PCM_HW_PARAM_RATE
, -1);
281 mutex_unlock(&priv
->mutex
);
286 /* Reset TDM slots to 32 */
287 ret
= snd_soc_dai_set_tdm_slot(cpu_dai
, 0x3, 0x3, 2, 32);
288 if (ret
&& ret
!= -ENOTSUPP
)
291 for_each_rtd_codec_dais(rtd
, i
, codec_dai
) {
292 ret
= snd_soc_dai_set_tdm_slot(codec_dai
, 0x3, 0x3, 2, 32);
293 if (ret
&& ret
!= -ENOTSUPP
)
300 static int j721e_audio_hw_params(struct snd_pcm_substream
*substream
,
301 struct snd_pcm_hw_params
*params
)
303 struct snd_soc_pcm_runtime
*rtd
= asoc_substream_to_rtd(substream
);
304 struct snd_soc_card
*card
= rtd
->card
;
305 struct j721e_priv
*priv
= snd_soc_card_get_drvdata(card
);
306 unsigned int domain_id
= rtd
->dai_link
->id
;
307 struct j721e_audio_domain
*domain
= &priv
->audio_domains
[domain_id
];
308 struct snd_soc_dai
*cpu_dai
= asoc_rtd_to_cpu(rtd
, 0);
309 struct snd_soc_dai
*codec_dai
;
310 unsigned int sysclk_rate
;
315 mutex_lock(&priv
->mutex
);
317 if (domain
->rate
&& domain
->rate
!= params_rate(params
)) {
322 if (params_width(params
) == 16)
325 ret
= snd_soc_dai_set_tdm_slot(cpu_dai
, 0x3, 0x3, 2, slot_width
);
326 if (ret
&& ret
!= -ENOTSUPP
)
329 for_each_rtd_codec_dais(rtd
, i
, codec_dai
) {
330 ret
= snd_soc_dai_set_tdm_slot(codec_dai
, 0x3, 0x3, 2,
332 if (ret
&& ret
!= -ENOTSUPP
)
336 ret
= j721e_configure_refclk(priv
, domain_id
, params_rate(params
));
340 sysclk_rate
= priv
->hsdiv_rates
[domain
->parent_clk_id
];
341 for_each_rtd_codec_dais(rtd
, i
, codec_dai
) {
342 ret
= snd_soc_dai_set_sysclk(codec_dai
, 0, sysclk_rate
,
344 if (ret
&& ret
!= -ENOTSUPP
) {
346 "codec set_sysclk failed for %u Hz\n",
352 ret
= snd_soc_dai_set_sysclk(cpu_dai
, MCASP_CLK_HCLK_AUXCLK
,
353 sysclk_rate
, SND_SOC_CLOCK_IN
);
355 if (ret
&& ret
!= -ENOTSUPP
) {
356 dev_err(priv
->dev
, "mcasp set_sysclk failed for %u Hz\n",
359 domain
->rate
= params_rate(params
);
364 mutex_unlock(&priv
->mutex
);
368 static void j721e_audio_shutdown(struct snd_pcm_substream
*substream
)
370 struct snd_soc_pcm_runtime
*rtd
= asoc_substream_to_rtd(substream
);
371 struct j721e_priv
*priv
= snd_soc_card_get_drvdata(rtd
->card
);
372 unsigned int domain_id
= rtd
->dai_link
->id
;
373 struct j721e_audio_domain
*domain
= &priv
->audio_domains
[domain_id
];
375 mutex_lock(&priv
->mutex
);
378 if (!domain
->active
) {
380 domain
->active_link
= 0;
383 mutex_unlock(&priv
->mutex
);
386 static const struct snd_soc_ops j721e_audio_ops
= {
387 .startup
= j721e_audio_startup
,
388 .hw_params
= j721e_audio_hw_params
,
389 .shutdown
= j721e_audio_shutdown
,
392 static int j721e_audio_init(struct snd_soc_pcm_runtime
*rtd
)
394 struct j721e_priv
*priv
= snd_soc_card_get_drvdata(rtd
->card
);
395 unsigned int domain_id
= rtd
->dai_link
->id
;
396 struct j721e_audio_domain
*domain
= &priv
->audio_domains
[domain_id
];
397 struct snd_soc_dai
*cpu_dai
= asoc_rtd_to_cpu(rtd
, 0);
398 struct snd_soc_dai
*codec_dai
;
399 unsigned int sysclk_rate
;
402 /* Set up initial clock configuration */
403 ret
= j721e_configure_refclk(priv
, domain_id
, 48000);
407 sysclk_rate
= priv
->hsdiv_rates
[domain
->parent_clk_id
];
408 for_each_rtd_codec_dais(rtd
, i
, codec_dai
) {
409 ret
= snd_soc_dai_set_sysclk(codec_dai
, 0, sysclk_rate
,
411 if (ret
&& ret
!= -ENOTSUPP
)
415 ret
= snd_soc_dai_set_sysclk(cpu_dai
, MCASP_CLK_HCLK_AUXCLK
,
416 sysclk_rate
, SND_SOC_CLOCK_IN
);
417 if (ret
&& ret
!= -ENOTSUPP
)
420 /* Set initial tdm slots */
421 ret
= snd_soc_dai_set_tdm_slot(cpu_dai
, 0x3, 0x3, 2, 32);
422 if (ret
&& ret
!= -ENOTSUPP
)
425 for_each_rtd_codec_dais(rtd
, i
, codec_dai
) {
426 ret
= snd_soc_dai_set_tdm_slot(codec_dai
, 0x3, 0x3, 2, 32);
427 if (ret
&& ret
!= -ENOTSUPP
)
434 static int j721e_audio_init_ivi(struct snd_soc_pcm_runtime
*rtd
)
436 struct snd_soc_dapm_context
*dapm
= &rtd
->card
->dapm
;
438 snd_soc_dapm_new_controls(dapm
, j721e_ivi_codec_a_dapm_widgets
,
439 ARRAY_SIZE(j721e_ivi_codec_a_dapm_widgets
));
440 snd_soc_dapm_add_routes(dapm
, j721e_codec_a_dapm_routes
,
441 ARRAY_SIZE(j721e_codec_a_dapm_routes
));
442 snd_soc_dapm_new_controls(dapm
, j721e_ivi_codec_b_dapm_widgets
,
443 ARRAY_SIZE(j721e_ivi_codec_b_dapm_widgets
));
444 snd_soc_dapm_add_routes(dapm
, j721e_codec_b_dapm_routes
,
445 ARRAY_SIZE(j721e_codec_b_dapm_routes
));
447 return j721e_audio_init(rtd
);
450 static int j721e_get_clocks(struct device
*dev
,
451 struct j721e_audio_clocks
*clocks
, char *prefix
)
457 clocks
->target
= devm_clk_get(dev
, prefix
);
458 if (IS_ERR(clocks
->target
)) {
459 ret
= PTR_ERR(clocks
->target
);
460 if (ret
!= -EPROBE_DEFER
)
461 dev_err(dev
, "failed to acquire %s: %d\n",
466 clk_name
= kasprintf(GFP_KERNEL
, "%s-48000", prefix
);
468 parent
= devm_clk_get(dev
, clk_name
);
470 if (IS_ERR(parent
)) {
471 ret
= PTR_ERR(parent
);
472 if (ret
== -EPROBE_DEFER
)
475 dev_dbg(dev
, "no 48KHz parent for %s: %d\n", prefix
, ret
);
478 clocks
->parent
[J721E_CLK_PARENT_48000
] = parent
;
483 clk_name
= kasprintf(GFP_KERNEL
, "%s-44100", prefix
);
485 parent
= devm_clk_get(dev
, clk_name
);
487 if (IS_ERR(parent
)) {
488 ret
= PTR_ERR(parent
);
489 if (ret
== -EPROBE_DEFER
)
492 dev_dbg(dev
, "no 44.1KHz parent for %s: %d\n", prefix
, ret
);
495 clocks
->parent
[J721E_CLK_PARENT_44100
] = parent
;
500 if (!clocks
->parent
[J721E_CLK_PARENT_44100
] &&
501 !clocks
->parent
[J721E_CLK_PARENT_48000
]) {
502 dev_err(dev
, "At least one parent clock is needed for %s\n",
510 static const struct j721e_audio_match_data j721e_cpb_data
= {
511 .board_type
= J721E_BOARD_CPB
,
512 .num_links
= 2, /* CPB pcm3168a */
514 [J721E_CLK_PARENT_44100
] = 1083801600, /* PLL15 */
515 [J721E_CLK_PARENT_48000
] = 1179648000, /* PLL4 */
519 static const struct j721e_audio_match_data j721e_cpb_ivi_data
= {
520 .board_type
= J721E_BOARD_CPB_IVI
,
521 .num_links
= 4, /* CPB pcm3168a + 2x pcm3168a on IVI */
523 [J721E_CLK_PARENT_44100
] = 1083801600, /* PLL15 */
524 [J721E_CLK_PARENT_48000
] = 1179648000, /* PLL4 */
528 static const struct j721e_audio_match_data j7200_cpb_data
= {
529 .board_type
= J721E_BOARD_CPB
,
530 .num_links
= 2, /* CPB pcm3168a */
532 [J721E_CLK_PARENT_48000
] = 2359296000u, /* PLL4 */
536 static const struct of_device_id j721e_audio_of_match
[] = {
538 .compatible
= "ti,j721e-cpb-audio",
539 .data
= &j721e_cpb_data
,
541 .compatible
= "ti,j721e-cpb-ivi-audio",
542 .data
= &j721e_cpb_ivi_data
,
544 .compatible
= "ti,j7200-cpb-audio",
545 .data
= &j7200_cpb_data
,
549 MODULE_DEVICE_TABLE(of
, j721e_audio_of_match
);
551 static int j721e_calculate_rate_range(struct j721e_priv
*priv
)
553 const struct j721e_audio_match_data
*match_data
= priv
->match_data
;
554 struct j721e_audio_clocks
*domain_clocks
;
555 unsigned int min_rate
, max_rate
, pll_rate
;
558 domain_clocks
= &priv
->audio_domains
[J721E_AUDIO_DOMAIN_CPB
].mcasp
;
560 pll
= clk_get_parent(domain_clocks
->parent
[J721E_CLK_PARENT_44100
]);
561 if (IS_ERR_OR_NULL(pll
)) {
562 priv
->pll_rates
[J721E_CLK_PARENT_44100
] =
563 match_data
->pll_rates
[J721E_CLK_PARENT_44100
];
565 priv
->pll_rates
[J721E_CLK_PARENT_44100
] = clk_get_rate(pll
);
569 pll
= clk_get_parent(domain_clocks
->parent
[J721E_CLK_PARENT_48000
]);
570 if (IS_ERR_OR_NULL(pll
)) {
571 priv
->pll_rates
[J721E_CLK_PARENT_48000
] =
572 match_data
->pll_rates
[J721E_CLK_PARENT_48000
];
574 priv
->pll_rates
[J721E_CLK_PARENT_48000
] = clk_get_rate(pll
);
578 if (!priv
->pll_rates
[J721E_CLK_PARENT_44100
] &&
579 !priv
->pll_rates
[J721E_CLK_PARENT_48000
]) {
580 dev_err(priv
->dev
, "At least one PLL is needed\n");
584 if (priv
->pll_rates
[J721E_CLK_PARENT_44100
])
585 pll_rate
= priv
->pll_rates
[J721E_CLK_PARENT_44100
];
587 pll_rate
= priv
->pll_rates
[J721E_CLK_PARENT_48000
];
589 min_rate
= pll_rate
/ J721E_MAX_CLK_HSDIV
;
590 min_rate
/= ratios_for_pcm3168a
[ARRAY_SIZE(ratios_for_pcm3168a
) - 1];
592 if (priv
->pll_rates
[J721E_CLK_PARENT_48000
])
593 pll_rate
= priv
->pll_rates
[J721E_CLK_PARENT_48000
];
595 pll_rate
= priv
->pll_rates
[J721E_CLK_PARENT_44100
];
597 if (pll_rate
> PCM1368A_MAX_SYSCLK
)
598 pll_rate
= PCM1368A_MAX_SYSCLK
;
600 max_rate
= pll_rate
/ ratios_for_pcm3168a
[0];
602 snd_interval_any(&priv
->rate_range
);
603 priv
->rate_range
.min
= min_rate
;
604 priv
->rate_range
.max
= max_rate
;
609 static int j721e_soc_probe_cpb(struct j721e_priv
*priv
, int *link_idx
,
612 struct device_node
*node
= priv
->dev
->of_node
;
613 struct snd_soc_dai_link_component
*compnent
;
614 struct device_node
*dai_node
, *codec_node
;
615 struct j721e_audio_domain
*domain
;
616 int comp_count
, comp_idx
;
619 dai_node
= of_parse_phandle(node
, "ti,cpb-mcasp", 0);
621 dev_err(priv
->dev
, "CPB McASP node is not provided\n");
625 codec_node
= of_parse_phandle(node
, "ti,cpb-codec", 0);
627 dev_err(priv
->dev
, "CPB codec node is not provided\n");
631 domain
= &priv
->audio_domains
[J721E_AUDIO_DOMAIN_CPB
];
632 ret
= j721e_get_clocks(priv
->dev
, &domain
->codec
, "cpb-codec-scki");
636 ret
= j721e_get_clocks(priv
->dev
, &domain
->mcasp
, "cpb-mcasp-auxclk");
641 * Common Processor Board, two links
642 * Link 1: McASP10 -> pcm3168a_1 DAC
643 * Link 2: McASP10 <- pcm3168a_1 ADC
646 compnent
= devm_kzalloc(priv
->dev
, comp_count
* sizeof(*compnent
),
652 priv
->dai_links
[*link_idx
].cpus
= &compnent
[comp_idx
++];
653 priv
->dai_links
[*link_idx
].num_cpus
= 1;
654 priv
->dai_links
[*link_idx
].codecs
= &compnent
[comp_idx
++];
655 priv
->dai_links
[*link_idx
].num_codecs
= 1;
656 priv
->dai_links
[*link_idx
].platforms
= &compnent
[comp_idx
++];
657 priv
->dai_links
[*link_idx
].num_platforms
= 1;
659 priv
->dai_links
[*link_idx
].name
= "CPB PCM3168A Playback";
660 priv
->dai_links
[*link_idx
].stream_name
= "CPB PCM3168A Analog";
661 priv
->dai_links
[*link_idx
].cpus
->of_node
= dai_node
;
662 priv
->dai_links
[*link_idx
].platforms
->of_node
= dai_node
;
663 priv
->dai_links
[*link_idx
].codecs
->of_node
= codec_node
;
664 priv
->dai_links
[*link_idx
].codecs
->dai_name
= "pcm3168a-dac";
665 priv
->dai_links
[*link_idx
].playback_only
= 1;
666 priv
->dai_links
[*link_idx
].id
= J721E_AUDIO_DOMAIN_CPB
;
667 priv
->dai_links
[*link_idx
].dai_fmt
= J721E_DAI_FMT
;
668 priv
->dai_links
[*link_idx
].init
= j721e_audio_init
;
669 priv
->dai_links
[*link_idx
].ops
= &j721e_audio_ops
;
672 priv
->dai_links
[*link_idx
].cpus
= &compnent
[comp_idx
++];
673 priv
->dai_links
[*link_idx
].num_cpus
= 1;
674 priv
->dai_links
[*link_idx
].codecs
= &compnent
[comp_idx
++];
675 priv
->dai_links
[*link_idx
].num_codecs
= 1;
676 priv
->dai_links
[*link_idx
].platforms
= &compnent
[comp_idx
++];
677 priv
->dai_links
[*link_idx
].num_platforms
= 1;
679 priv
->dai_links
[*link_idx
].name
= "CPB PCM3168A Capture";
680 priv
->dai_links
[*link_idx
].stream_name
= "CPB PCM3168A Analog";
681 priv
->dai_links
[*link_idx
].cpus
->of_node
= dai_node
;
682 priv
->dai_links
[*link_idx
].platforms
->of_node
= dai_node
;
683 priv
->dai_links
[*link_idx
].codecs
->of_node
= codec_node
;
684 priv
->dai_links
[*link_idx
].codecs
->dai_name
= "pcm3168a-adc";
685 priv
->dai_links
[*link_idx
].capture_only
= 1;
686 priv
->dai_links
[*link_idx
].id
= J721E_AUDIO_DOMAIN_CPB
;
687 priv
->dai_links
[*link_idx
].dai_fmt
= J721E_DAI_FMT
;
688 priv
->dai_links
[*link_idx
].init
= j721e_audio_init
;
689 priv
->dai_links
[*link_idx
].ops
= &j721e_audio_ops
;
692 priv
->codec_conf
[*conf_idx
].dlc
.of_node
= codec_node
;
693 priv
->codec_conf
[*conf_idx
].name_prefix
= "codec-1";
695 priv
->codec_conf
[*conf_idx
].dlc
.of_node
= dai_node
;
696 priv
->codec_conf
[*conf_idx
].name_prefix
= "McASP10";
702 static int j721e_soc_probe_ivi(struct j721e_priv
*priv
, int *link_idx
,
705 struct device_node
*node
= priv
->dev
->of_node
;
706 struct snd_soc_dai_link_component
*compnent
;
707 struct device_node
*dai_node
, *codeca_node
, *codecb_node
;
708 struct j721e_audio_domain
*domain
;
709 int comp_count
, comp_idx
;
712 if (priv
->match_data
->board_type
!= J721E_BOARD_CPB_IVI
)
715 dai_node
= of_parse_phandle(node
, "ti,ivi-mcasp", 0);
717 dev_err(priv
->dev
, "IVI McASP node is not provided\n");
721 codeca_node
= of_parse_phandle(node
, "ti,ivi-codec-a", 0);
723 dev_err(priv
->dev
, "IVI codec-a node is not provided\n");
727 codecb_node
= of_parse_phandle(node
, "ti,ivi-codec-b", 0);
729 dev_warn(priv
->dev
, "IVI codec-b node is not provided\n");
733 domain
= &priv
->audio_domains
[J721E_AUDIO_DOMAIN_IVI
];
734 ret
= j721e_get_clocks(priv
->dev
, &domain
->codec
, "ivi-codec-scki");
738 ret
= j721e_get_clocks(priv
->dev
, &domain
->mcasp
, "ivi-mcasp-auxclk");
743 * IVI extension, two links
744 * Link 1: McASP0 -> pcm3168a_a DAC
746 * Link 2: McASP0 <- pcm3168a_a ADC
750 compnent
= devm_kzalloc(priv
->dev
, comp_count
* sizeof(*compnent
),
756 priv
->dai_links
[*link_idx
].cpus
= &compnent
[comp_idx
++];
757 priv
->dai_links
[*link_idx
].num_cpus
= 1;
758 priv
->dai_links
[*link_idx
].platforms
= &compnent
[comp_idx
++];
759 priv
->dai_links
[*link_idx
].num_platforms
= 1;
760 priv
->dai_links
[*link_idx
].codecs
= &compnent
[comp_idx
];
761 priv
->dai_links
[*link_idx
].num_codecs
= 2;
764 priv
->dai_links
[*link_idx
].name
= "IVI 2xPCM3168A Playback";
765 priv
->dai_links
[*link_idx
].stream_name
= "IVI 2xPCM3168A Analog";
766 priv
->dai_links
[*link_idx
].cpus
->of_node
= dai_node
;
767 priv
->dai_links
[*link_idx
].platforms
->of_node
= dai_node
;
768 priv
->dai_links
[*link_idx
].codecs
[0].of_node
= codeca_node
;
769 priv
->dai_links
[*link_idx
].codecs
[0].dai_name
= "pcm3168a-dac";
770 priv
->dai_links
[*link_idx
].codecs
[1].of_node
= codecb_node
;
771 priv
->dai_links
[*link_idx
].codecs
[1].dai_name
= "pcm3168a-dac";
772 priv
->dai_links
[*link_idx
].playback_only
= 1;
773 priv
->dai_links
[*link_idx
].id
= J721E_AUDIO_DOMAIN_IVI
;
774 priv
->dai_links
[*link_idx
].dai_fmt
= J721E_DAI_FMT
;
775 priv
->dai_links
[*link_idx
].init
= j721e_audio_init_ivi
;
776 priv
->dai_links
[*link_idx
].ops
= &j721e_audio_ops
;
779 priv
->dai_links
[*link_idx
].cpus
= &compnent
[comp_idx
++];
780 priv
->dai_links
[*link_idx
].num_cpus
= 1;
781 priv
->dai_links
[*link_idx
].platforms
= &compnent
[comp_idx
++];
782 priv
->dai_links
[*link_idx
].num_platforms
= 1;
783 priv
->dai_links
[*link_idx
].codecs
= &compnent
[comp_idx
];
784 priv
->dai_links
[*link_idx
].num_codecs
= 2;
786 priv
->dai_links
[*link_idx
].name
= "IVI 2xPCM3168A Capture";
787 priv
->dai_links
[*link_idx
].stream_name
= "IVI 2xPCM3168A Analog";
788 priv
->dai_links
[*link_idx
].cpus
->of_node
= dai_node
;
789 priv
->dai_links
[*link_idx
].platforms
->of_node
= dai_node
;
790 priv
->dai_links
[*link_idx
].codecs
[0].of_node
= codeca_node
;
791 priv
->dai_links
[*link_idx
].codecs
[0].dai_name
= "pcm3168a-adc";
792 priv
->dai_links
[*link_idx
].codecs
[1].of_node
= codecb_node
;
793 priv
->dai_links
[*link_idx
].codecs
[1].dai_name
= "pcm3168a-adc";
794 priv
->dai_links
[*link_idx
].capture_only
= 1;
795 priv
->dai_links
[*link_idx
].id
= J721E_AUDIO_DOMAIN_IVI
;
796 priv
->dai_links
[*link_idx
].dai_fmt
= J721E_DAI_FMT
;
797 priv
->dai_links
[*link_idx
].init
= j721e_audio_init
;
798 priv
->dai_links
[*link_idx
].ops
= &j721e_audio_ops
;
801 priv
->codec_conf
[*conf_idx
].dlc
.of_node
= codeca_node
;
802 priv
->codec_conf
[*conf_idx
].name_prefix
= "codec-a";
805 priv
->codec_conf
[*conf_idx
].dlc
.of_node
= codecb_node
;
806 priv
->codec_conf
[*conf_idx
].name_prefix
= "codec-b";
809 priv
->codec_conf
[*conf_idx
].dlc
.of_node
= dai_node
;
810 priv
->codec_conf
[*conf_idx
].name_prefix
= "McASP0";
816 static int j721e_soc_probe(struct platform_device
*pdev
)
818 struct device_node
*node
= pdev
->dev
.of_node
;
819 struct snd_soc_card
*card
;
820 const struct of_device_id
*match
;
821 struct j721e_priv
*priv
;
822 int link_cnt
, conf_cnt
, ret
;
825 dev_err(&pdev
->dev
, "of node is missing.\n");
829 match
= of_match_node(j721e_audio_of_match
, node
);
831 dev_err(&pdev
->dev
, "No compatible match found\n");
835 priv
= devm_kzalloc(&pdev
->dev
, sizeof(*priv
), GFP_KERNEL
);
839 priv
->match_data
= match
->data
;
841 priv
->dai_links
= devm_kcalloc(&pdev
->dev
, priv
->match_data
->num_links
,
842 sizeof(*priv
->dai_links
), GFP_KERNEL
);
843 if (!priv
->dai_links
)
846 priv
->audio_domains
[J721E_AUDIO_DOMAIN_CPB
].parent_clk_id
= -1;
847 priv
->audio_domains
[J721E_AUDIO_DOMAIN_IVI
].parent_clk_id
= -1;
848 priv
->dev
= &pdev
->dev
;
850 card
->dev
= &pdev
->dev
;
851 card
->owner
= THIS_MODULE
;
852 card
->dapm_widgets
= j721e_cpb_dapm_widgets
;
853 card
->num_dapm_widgets
= ARRAY_SIZE(j721e_cpb_dapm_widgets
);
854 card
->dapm_routes
= j721e_cpb_dapm_routes
;
855 card
->num_dapm_routes
= ARRAY_SIZE(j721e_cpb_dapm_routes
);
856 card
->fully_routed
= 1;
858 if (snd_soc_of_parse_card_name(card
, "model")) {
859 dev_err(&pdev
->dev
, "Card name is not provided\n");
865 ret
= j721e_soc_probe_cpb(priv
, &link_cnt
, &conf_cnt
);
869 ret
= j721e_soc_probe_ivi(priv
, &link_cnt
, &conf_cnt
);
873 card
->dai_link
= priv
->dai_links
;
874 card
->num_links
= link_cnt
;
876 card
->codec_conf
= priv
->codec_conf
;
877 card
->num_configs
= conf_cnt
;
879 ret
= j721e_calculate_rate_range(priv
);
883 snd_soc_card_set_drvdata(card
, priv
);
885 mutex_init(&priv
->mutex
);
886 ret
= devm_snd_soc_register_card(&pdev
->dev
, card
);
888 dev_err(&pdev
->dev
, "devm_snd_soc_register_card() failed: %d\n",
894 static struct platform_driver j721e_soc_driver
= {
896 .name
= "j721e-audio",
897 .pm
= &snd_soc_pm_ops
,
898 .of_match_table
= j721e_audio_of_match
,
900 .probe
= j721e_soc_probe
,
903 module_platform_driver(j721e_soc_driver
);
905 MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@ti.com>");
906 MODULE_DESCRIPTION("ASoC machine driver for j721e Common Processor Board");
907 MODULE_LICENSE("GPL v2");