@@ -70,6 +70,64 @@ static int dmic_init(struct snd_soc_pcm_runtime *rtd)
7070 return 0 ;
7171}
7272
73+ /*
74+ * HDA External Codec DAI Link
75+ */
76+ static const struct snd_soc_dapm_widget hda_widgets [] = {
77+ SND_SOC_DAPM_MIC ("Analog In" , NULL ),
78+ SND_SOC_DAPM_MIC ("Digital In" , NULL ),
79+ SND_SOC_DAPM_MIC ("Alt Analog In" , NULL ),
80+
81+ SND_SOC_DAPM_HP ("Analog Out" , NULL ),
82+ SND_SOC_DAPM_SPK ("Digital Out" , NULL ),
83+ SND_SOC_DAPM_HP ("Alt Analog Out" , NULL ),
84+ };
85+
86+ static const struct snd_soc_dapm_route hda_routes [] = {
87+ { "Codec Input Pin1" , NULL , "Analog In" },
88+ { "Codec Input Pin2" , NULL , "Digital In" },
89+ { "Codec Input Pin3" , NULL , "Alt Analog In" },
90+
91+ { "Analog Out" , NULL , "Codec Output Pin1" },
92+ { "Digital Out" , NULL , "Codec Output Pin2" },
93+ { "Alt Analog Out" , NULL , "Codec Output Pin3" },
94+
95+ /* CODEC BE connections */
96+ { "codec0_in" , NULL , "Analog CPU Capture" },
97+ { "Analog CPU Capture" , NULL , "Analog Codec Capture" },
98+ { "codec1_in" , NULL , "Digital CPU Capture" },
99+ { "Digital CPU Capture" , NULL , "Digital Codec Capture" },
100+ { "codec2_in" , NULL , "Alt Analog CPU Capture" },
101+ { "Alt Analog CPU Capture" , NULL , "Alt Analog Codec Capture" },
102+
103+ { "Analog Codec Playback" , NULL , "Analog CPU Playback" },
104+ { "Analog CPU Playback" , NULL , "codec0_out" },
105+ { "Digital Codec Playback" , NULL , "Digital CPU Playback" },
106+ { "Digital CPU Playback" , NULL , "codec1_out" },
107+ { "Alt Analog Codec Playback" , NULL , "Alt Analog CPU Playback" },
108+ { "Alt Analog CPU Playback" , NULL , "codec2_out" },
109+ };
110+
111+ static int hda_init (struct snd_soc_pcm_runtime * rtd )
112+ {
113+ struct snd_soc_card * card = rtd -> card ;
114+ int ret ;
115+
116+ ret = snd_soc_dapm_new_controls (& card -> dapm , hda_widgets ,
117+ ARRAY_SIZE (hda_widgets ));
118+ if (ret ) {
119+ dev_err (rtd -> dev , "fail to add hda widgets, ret %d\n" , ret );
120+ return ret ;
121+ }
122+
123+ ret = snd_soc_dapm_add_routes (& card -> dapm , hda_routes ,
124+ ARRAY_SIZE (hda_routes ));
125+ if (ret )
126+ dev_err (rtd -> dev , "fail to add hda routes, ret %d\n" , ret );
127+
128+ return ret ;
129+ }
130+
73131/*
74132 * DAI Link Helpers
75133 */
@@ -79,6 +137,11 @@ enum sof_dmic_be_type {
79137 SOF_DMIC_16K ,
80138};
81139
140+ enum sof_hda_be_type {
141+ SOF_HDA_ANALOG ,
142+ SOF_HDA_DIGITAL ,
143+ };
144+
82145/* DEFAULT_LINK_ORDER: the order used in sof_rt5682 */
83146#define DEFAULT_LINK_ORDER SOF_LINK_ORDER(SOF_LINK_CODEC, \
84147 SOF_LINK_DMIC01, \
@@ -95,6 +158,16 @@ static struct snd_soc_dai_link_component dmic_component[] = {
95158 }
96159};
97160
161+ SND_SOC_DAILINK_DEF (hda_analog_cpus ,
162+ DAILINK_COMP_ARRAY (COMP_CPU ("Analog CPU DAI" )));
163+ SND_SOC_DAILINK_DEF (hda_analog_codecs ,
164+ DAILINK_COMP_ARRAY (COMP_CODEC ("ehdaudio0D0" , "Analog Codec DAI" )));
165+
166+ SND_SOC_DAILINK_DEF (hda_digital_cpus ,
167+ DAILINK_COMP_ARRAY (COMP_CPU ("Digital CPU DAI" )));
168+ SND_SOC_DAILINK_DEF (hda_digital_codecs ,
169+ DAILINK_COMP_ARRAY (COMP_CODEC ("ehdaudio0D0" , "Digital Codec DAI" )));
170+
98171static struct snd_soc_dai_link_component platform_component [] = {
99172 {
100173 /* name might be overridden during probe */
@@ -380,6 +453,55 @@ static int set_hdmi_in_link(struct device *dev, struct snd_soc_dai_link *link,
380453 return 0 ;
381454}
382455
456+ static int set_hda_codec_link (struct device * dev , struct snd_soc_dai_link * link ,
457+ int be_id , enum sof_hda_be_type be_type )
458+ {
459+ switch (be_type ) {
460+ case SOF_HDA_ANALOG :
461+ dev_dbg (dev , "link %d: hda analog\n" , be_id );
462+
463+ link -> name = "Analog Playback and Capture" ;
464+
465+ /* cpus */
466+ link -> cpus = hda_analog_cpus ;
467+ link -> num_cpus = ARRAY_SIZE (hda_analog_cpus );
468+
469+ /* codecs */
470+ link -> codecs = hda_analog_codecs ;
471+ link -> num_codecs = ARRAY_SIZE (hda_analog_codecs );
472+ break ;
473+ case SOF_HDA_DIGITAL :
474+ dev_dbg (dev , "link %d: hda digital\n" , be_id );
475+
476+ link -> name = "Digital Playback and Capture" ;
477+
478+ /* cpus */
479+ link -> cpus = hda_digital_cpus ;
480+ link -> num_cpus = ARRAY_SIZE (hda_digital_cpus );
481+
482+ /* codecs */
483+ link -> codecs = hda_digital_codecs ;
484+ link -> num_codecs = ARRAY_SIZE (hda_digital_codecs );
485+ break ;
486+ default :
487+ dev_err (dev , "invalid be type %d\n" , be_type );
488+ return - EINVAL ;
489+ }
490+
491+ /* platforms */
492+ link -> platforms = platform_component ;
493+ link -> num_platforms = ARRAY_SIZE (platform_component );
494+
495+ link -> id = be_id ;
496+ if (be_type == SOF_HDA_ANALOG )
497+ link -> init = hda_init ;
498+ link -> no_pcm = 1 ;
499+ link -> dpcm_capture = 1 ;
500+ link -> dpcm_playback = 1 ;
501+
502+ return 0 ;
503+ }
504+
383505static int calculate_num_links (struct sof_card_private * ctx )
384506{
385507 int num_links = 0 ;
@@ -409,6 +531,10 @@ static int calculate_num_links(struct sof_card_private *ctx)
409531 /* HDMI-In */
410532 num_links += hweight32 (ctx -> ssp_mask_hdmi_in );
411533
534+ /* HDA external codec */
535+ if (ctx -> hda_codec_present )
536+ num_links += 2 ;
537+
412538 return num_links ;
413539}
414540
@@ -566,6 +692,32 @@ int sof_intel_board_set_dai_link(struct device *dev, struct snd_soc_card *card,
566692 be_id ++ ;
567693 }
568694 break ;
695+ case SOF_LINK_HDA :
696+ /* HDA external codec */
697+ if (!ctx -> hda_codec_present )
698+ continue ;
699+
700+ ret = set_hda_codec_link (dev , & links [idx ], be_id ,
701+ SOF_HDA_ANALOG );
702+ if (ret ) {
703+ dev_err (dev , "fail to set hda analog link, ret %d\n" ,
704+ ret );
705+ return ret ;
706+ }
707+
708+ idx ++ ;
709+ be_id ++ ;
710+
711+ ret = set_hda_codec_link (dev , & links [idx ], be_id ,
712+ SOF_HDA_DIGITAL );
713+ if (ret ) {
714+ dev_err (dev , "fail to set hda digital link, ret %d\n" ,
715+ ret );
716+ return ret ;
717+ }
718+
719+ idx ++ ;
720+ break ;
569721 case SOF_LINK_NONE :
570722 /* caught here if it's not used as terminator in macro */
571723 fallthrough ;
0 commit comments