Skip to content

Commit 5a8b266

Browse files
brentluplbossart
authored andcommitted
ASoC: Intel: sof_cs42l42: support arbitrary DAI link sequence
Currently there are two types of DAI Link sequences defined in topology files, one starts from speaker link and the other starts from headphone link. Type 1: SPK - HP - DMIC - HDMI Type 2: HP - DMIC - HDMI - SPK Here we add a macro SOF_CS42L42_DAILINK to define the DAI Link sequence in quirk and refactor the sof_card_dai_links_create() function to support arbitrary DAI Link sequence. Signed-off-by: Brent Lu <brent.lu@intel.com>
1 parent 17f68f8 commit 5a8b266

1 file changed

Lines changed: 230 additions & 112 deletions

File tree

sound/soc/intel/boards/sof_cs42l42.c

Lines changed: 230 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,19 @@
3737
#define SOF_CS42L42_NUM_HDMIDEV_MASK (GENMASK(9, 7))
3838
#define SOF_CS42L42_NUM_HDMIDEV(quirk) \
3939
(((quirk) << SOF_CS42L42_NUM_HDMIDEV_SHIFT) & SOF_CS42L42_NUM_HDMIDEV_MASK)
40-
#define SOF_MAX98357A_SPEAKER_AMP_PRESENT BIT(10)
40+
#define SOF_CS42L42_DAILINK_SHIFT 10
41+
#define SOF_CS42L42_DAILINK_MASK (GENMASK(24, 10))
42+
#define SOF_CS42L42_DAILINK(link1, link2, link3, link4, link5) \
43+
((((link1) | ((link2) << 3) | ((link3) << 6) | ((link4) << 9) | ((link5) << 12)) << SOF_CS42L42_DAILINK_SHIFT) & SOF_CS42L42_DAILINK_MASK)
44+
#define SOF_MAX98357A_SPEAKER_AMP_PRESENT BIT(25)
45+
46+
enum {
47+
LINK_NONE = 0,
48+
LINK_HP = 1,
49+
LINK_SPK = 2,
50+
LINK_DMIC = 3,
51+
LINK_HDMI = 4,
52+
};
4153

4254
/* Default: SSP2 */
4355
static unsigned long sof_cs42l42_quirk = SOF_CS42L42_SSP_CODEC(2);
@@ -265,133 +277,166 @@ static struct snd_soc_dai_link_component dmic_component[] = {
265277
}
266278
};
267279

268-
static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev,
269-
int ssp_codec,
270-
int ssp_amp,
271-
int dmic_be_num,
272-
int hdmi_num)
280+
static int create_spk_amp_dai_links(struct device *dev,
281+
struct snd_soc_dai_link *links,
282+
struct snd_soc_dai_link_component *cpus,
283+
int *id, int ssp_amp)
273284
{
274-
struct snd_soc_dai_link_component *idisp_components;
275-
struct snd_soc_dai_link_component *cpus;
276-
struct snd_soc_dai_link *links;
277-
int i, id = 0;
278-
279-
links = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link) *
280-
sof_audio_card_cs42l42.num_links, GFP_KERNEL);
281-
cpus = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link_component) *
282-
sof_audio_card_cs42l42.num_links, GFP_KERNEL);
283-
if (!links || !cpus)
284-
goto devm_err;
285+
int ret = 0;
285286

286287
/* speaker amp */
287-
if (sof_cs42l42_quirk & SOF_SPEAKER_AMP_PRESENT) {
288-
links[id].name = devm_kasprintf(dev, GFP_KERNEL,
289-
"SSP%d-Codec", ssp_amp);
290-
if (!links[id].name)
291-
goto devm_err;
288+
if (!(sof_cs42l42_quirk & SOF_SPEAKER_AMP_PRESENT))
289+
return 0;
292290

293-
links[id].id = id;
291+
links[*id].name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-Codec",
292+
ssp_amp);
293+
if (!links[*id].name) {
294+
ret = -ENOMEM;
295+
goto devm_err;
296+
}
294297

295-
if (sof_cs42l42_quirk & SOF_MAX98357A_SPEAKER_AMP_PRESENT) {
296-
max_98357a_dai_link(&links[id]);
297-
} else {
298-
dev_err(dev, "no amp defined\n");
299-
goto devm_err;
300-
}
298+
links[*id].id = *id;
301299

302-
links[id].platforms = platform_component;
303-
links[id].num_platforms = ARRAY_SIZE(platform_component);
304-
links[id].dpcm_playback = 1;
305-
links[id].no_pcm = 1;
306-
links[id].cpus = &cpus[id];
307-
links[id].num_cpus = 1;
308-
309-
links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,
310-
"SSP%d Pin",
311-
ssp_amp);
312-
if (!links[id].cpus->dai_name)
313-
goto devm_err;
300+
if (sof_cs42l42_quirk & SOF_MAX98357A_SPEAKER_AMP_PRESENT) {
301+
max_98357a_dai_link(&links[*id]);
302+
} else {
303+
dev_err(dev, "no amp defined\n");
304+
ret = -EINVAL;
305+
goto devm_err;
306+
}
314307

315-
id++;
308+
links[*id].platforms = platform_component;
309+
links[*id].num_platforms = ARRAY_SIZE(platform_component);
310+
links[*id].dpcm_playback = 1;
311+
links[*id].no_pcm = 1;
312+
links[*id].cpus = &cpus[*id];
313+
links[*id].num_cpus = 1;
314+
315+
links[*id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,
316+
"SSP%d Pin", ssp_amp);
317+
if (!links[*id].cpus->dai_name) {
318+
ret = -ENOMEM;
319+
goto devm_err;
316320
}
317321

322+
(*id)++;
323+
324+
devm_err:
325+
return ret;
326+
}
327+
328+
static int create_hp_codec_dai_links(struct device *dev,
329+
struct snd_soc_dai_link *links,
330+
struct snd_soc_dai_link_component *cpus,
331+
int *id, int ssp_codec)
332+
{
318333
/* codec SSP */
319-
links[id].name = devm_kasprintf(dev, GFP_KERNEL,
320-
"SSP%d-Codec", ssp_codec);
321-
if (!links[id].name)
334+
links[*id].name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-Codec",
335+
ssp_codec);
336+
if (!links[*id].name)
322337
goto devm_err;
323338

324-
links[id].id = id;
325-
links[id].codecs = cs42l42_component;
326-
links[id].num_codecs = ARRAY_SIZE(cs42l42_component);
327-
links[id].platforms = platform_component;
328-
links[id].num_platforms = ARRAY_SIZE(platform_component);
329-
links[id].init = sof_cs42l42_init;
330-
links[id].exit = sof_cs42l42_exit;
331-
links[id].ops = &sof_cs42l42_ops;
332-
links[id].dpcm_playback = 1;
333-
links[id].dpcm_capture = 1;
334-
links[id].no_pcm = 1;
335-
links[id].cpus = &cpus[id];
336-
links[id].num_cpus = 1;
337-
338-
links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,
339-
"SSP%d Pin",
340-
ssp_codec);
341-
if (!links[id].cpus->dai_name)
339+
links[*id].id = *id;
340+
links[*id].codecs = cs42l42_component;
341+
links[*id].num_codecs = ARRAY_SIZE(cs42l42_component);
342+
links[*id].platforms = platform_component;
343+
links[*id].num_platforms = ARRAY_SIZE(platform_component);
344+
links[*id].init = sof_cs42l42_init;
345+
links[*id].exit = sof_cs42l42_exit;
346+
links[*id].ops = &sof_cs42l42_ops;
347+
links[*id].dpcm_playback = 1;
348+
links[*id].dpcm_capture = 1;
349+
links[*id].no_pcm = 1;
350+
links[*id].cpus = &cpus[*id];
351+
links[*id].num_cpus = 1;
352+
353+
links[*id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,
354+
"SSP%d Pin",
355+
ssp_codec);
356+
if (!links[*id].cpus->dai_name)
342357
goto devm_err;
343358

344-
id++;
359+
(*id)++;
360+
361+
return 0;
362+
363+
devm_err:
364+
return -ENOMEM;
365+
}
366+
367+
static int create_dmic_dai_links(struct device *dev,
368+
struct snd_soc_dai_link *links,
369+
struct snd_soc_dai_link_component *cpus,
370+
int *id, int dmic_be_num)
371+
{
372+
int i;
345373

346374
/* dmic */
347-
if (dmic_be_num > 0) {
348-
/* at least we have dmic01 */
349-
links[id].name = "dmic01";
350-
links[id].cpus = &cpus[id];
351-
links[id].cpus->dai_name = "DMIC01 Pin";
352-
links[id].init = dmic_init;
353-
if (dmic_be_num > 1) {
354-
/* set up 2 BE links at most */
355-
links[id + 1].name = "dmic16k";
356-
links[id + 1].cpus = &cpus[id + 1];
357-
links[id + 1].cpus->dai_name = "DMIC16k Pin";
358-
dmic_be_num = 2;
359-
}
375+
if (dmic_be_num <= 0)
376+
return 0;
377+
378+
/* at least we have dmic01 */
379+
links[*id].name = "dmic01";
380+
links[*id].cpus = &cpus[*id];
381+
links[*id].cpus->dai_name = "DMIC01 Pin";
382+
links[*id].init = dmic_init;
383+
if (dmic_be_num > 1) {
384+
/* set up 2 BE links at most */
385+
links[*id + 1].name = "dmic16k";
386+
links[*id + 1].cpus = &cpus[*id + 1];
387+
links[*id + 1].cpus->dai_name = "DMIC16k Pin";
388+
dmic_be_num = 2;
360389
}
361390

362391
for (i = 0; i < dmic_be_num; i++) {
363-
links[id].id = id;
364-
links[id].num_cpus = 1;
365-
links[id].codecs = dmic_component;
366-
links[id].num_codecs = ARRAY_SIZE(dmic_component);
367-
links[id].platforms = platform_component;
368-
links[id].num_platforms = ARRAY_SIZE(platform_component);
369-
links[id].ignore_suspend = 1;
370-
links[id].dpcm_capture = 1;
371-
links[id].no_pcm = 1;
372-
id++;
392+
links[*id].id = *id;
393+
links[*id].num_cpus = 1;
394+
links[*id].codecs = dmic_component;
395+
links[*id].num_codecs = ARRAY_SIZE(dmic_component);
396+
links[*id].platforms = platform_component;
397+
links[*id].num_platforms = ARRAY_SIZE(platform_component);
398+
links[*id].ignore_suspend = 1;
399+
links[*id].dpcm_capture = 1;
400+
links[*id].no_pcm = 1;
401+
402+
(*id)++;
373403
}
374404

405+
return 0;
406+
}
407+
408+
static int create_hdmi_dai_links(struct device *dev,
409+
struct snd_soc_dai_link *links,
410+
struct snd_soc_dai_link_component *cpus,
411+
int *id, int hdmi_num)
412+
{
413+
struct snd_soc_dai_link_component *idisp_components;
414+
int i;
415+
375416
/* HDMI */
376-
if (hdmi_num > 0) {
377-
idisp_components = devm_kzalloc(dev,
378-
sizeof(struct snd_soc_dai_link_component) *
379-
hdmi_num, GFP_KERNEL);
380-
if (!idisp_components)
381-
goto devm_err;
382-
}
417+
if (hdmi_num <= 0)
418+
return 0;
419+
420+
idisp_components = devm_kzalloc(dev,
421+
sizeof(struct snd_soc_dai_link_component) *
422+
hdmi_num, GFP_KERNEL);
423+
if (!idisp_components)
424+
goto devm_err;
425+
383426
for (i = 1; i <= hdmi_num; i++) {
384-
links[id].name = devm_kasprintf(dev, GFP_KERNEL,
385-
"iDisp%d", i);
386-
if (!links[id].name)
427+
links[*id].name = devm_kasprintf(dev, GFP_KERNEL,
428+
"iDisp%d", i);
429+
if (!links[*id].name)
387430
goto devm_err;
388431

389-
links[id].id = id;
390-
links[id].cpus = &cpus[id];
391-
links[id].num_cpus = 1;
392-
links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,
393-
"iDisp%d Pin", i);
394-
if (!links[id].cpus->dai_name)
432+
links[*id].id = *id;
433+
links[*id].cpus = &cpus[*id];
434+
links[*id].num_cpus = 1;
435+
links[*id].cpus->dai_name = devm_kasprintf(dev,
436+
GFP_KERNEL,
437+
"iDisp%d Pin",
438+
i);
439+
if (!links[*id].cpus->dai_name)
395440
goto devm_err;
396441

397442
idisp_components[i - 1].name = "ehdaudio0D2";
@@ -402,14 +447,86 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev,
402447
if (!idisp_components[i - 1].dai_name)
403448
goto devm_err;
404449

405-
links[id].codecs = &idisp_components[i - 1];
406-
links[id].num_codecs = 1;
407-
links[id].platforms = platform_component;
408-
links[id].num_platforms = ARRAY_SIZE(platform_component);
409-
links[id].init = sof_hdmi_init;
410-
links[id].dpcm_playback = 1;
411-
links[id].no_pcm = 1;
412-
id++;
450+
links[*id].codecs = &idisp_components[i - 1];
451+
links[*id].num_codecs = 1;
452+
links[*id].platforms = platform_component;
453+
links[*id].num_platforms = ARRAY_SIZE(platform_component);
454+
links[*id].init = sof_hdmi_init;
455+
links[*id].dpcm_playback = 1;
456+
links[*id].no_pcm = 1;
457+
458+
(*id)++;
459+
}
460+
461+
return 0;
462+
463+
devm_err:
464+
return -ENOMEM;
465+
}
466+
467+
static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev,
468+
int ssp_codec,
469+
int ssp_amp,
470+
int dmic_be_num,
471+
int hdmi_num)
472+
{
473+
struct snd_soc_dai_link_component *cpus;
474+
struct snd_soc_dai_link *links;
475+
int ret, id = 0, link_seq;
476+
477+
links = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link) *
478+
sof_audio_card_cs42l42.num_links, GFP_KERNEL);
479+
cpus = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link_component) *
480+
sof_audio_card_cs42l42.num_links, GFP_KERNEL);
481+
if (!links || !cpus)
482+
goto devm_err;
483+
484+
link_seq = (sof_cs42l42_quirk & SOF_CS42L42_DAILINK_MASK) >> SOF_CS42L42_DAILINK_SHIFT;
485+
486+
while (link_seq) {
487+
int link_type = link_seq & 0x07;
488+
489+
switch (link_type) {
490+
case LINK_HP:
491+
ret = create_hp_codec_dai_links(dev, links, cpus, &id, ssp_codec);
492+
if (ret < 0) {
493+
dev_err(dev, "fail to create hp codec dai links, ret %d\n",
494+
ret);
495+
goto devm_err;
496+
}
497+
break;
498+
case LINK_SPK:
499+
ret = create_spk_amp_dai_links(dev, links, cpus, &id, ssp_amp);
500+
if (ret < 0) {
501+
dev_err(dev, "fail to create spk amp dai links, ret %d\n",
502+
ret);
503+
goto devm_err;
504+
}
505+
break;
506+
case LINK_DMIC:
507+
ret = create_dmic_dai_links(dev, links, cpus, &id, dmic_be_num);
508+
if (ret < 0) {
509+
dev_err(dev, "fail to create dmic dai links, ret %d\n",
510+
ret);
511+
goto devm_err;
512+
}
513+
break;
514+
case LINK_HDMI:
515+
ret = create_hdmi_dai_links(dev, links, cpus, &id, hdmi_num);
516+
if (ret < 0) {
517+
dev_err(dev, "fail to create hdmi dai links, ret %d\n",
518+
ret);
519+
goto devm_err;
520+
}
521+
break;
522+
case LINK_NONE:
523+
/* caught here if it's not used as terminator in macro */
524+
default:
525+
dev_err(dev, "invalid link type %d\n", link_type);
526+
goto devm_err;
527+
}
528+
529+
link_seq >>= 3;
413530
}
414531

415532
return links;
@@ -490,7 +607,8 @@ static const struct platform_device_id board_ids[] = {
490607
.driver_data = (kernel_ulong_t)(SOF_CS42L42_SSP_CODEC(2) |
491608
SOF_SPEAKER_AMP_PRESENT |
492609
SOF_MAX98357A_SPEAKER_AMP_PRESENT |
493-
SOF_CS42L42_SSP_AMP(1)),
610+
SOF_CS42L42_SSP_AMP(1)) |
611+
SOF_CS42L42_DAILINK(LINK_SPK, LINK_HP, LINK_DMIC, LINK_HDMI, LINK_NONE),
494612
},
495613
{ }
496614
};

0 commit comments

Comments
 (0)