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 */
4355static 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