3030#define CML_RT5682_CODEC_DAI "rt5682-aif1"
3131#define NAME_SIZE 32
3232
33+ #define SOF_RT1011_SPEAKER_WL BIT(0)
34+ #define SOF_RT1011_SPEAKER_WR BIT(1)
35+ #define SOF_RT1011_SPEAKER_TL BIT(2)
36+ #define SOF_RT1011_SPEAKER_TR BIT(3)
37+ #define SPK_CH 4
38+
39+ /* Default: Woofer speakers */
40+ static unsigned long sof_rt1011_quirk = SOF_RT1011_SPEAKER_WL |
41+ SOF_RT1011_SPEAKER_WR ;
42+
43+ static int sof_rt1011_quirk_cb (const struct dmi_system_id * id )
44+ {
45+ sof_rt1011_quirk = (unsigned long )id -> driver_data ;
46+ return 1 ;
47+ }
48+
49+ static const struct dmi_system_id sof_rt1011_quirk_table [] = {
50+ {
51+ .callback = sof_rt1011_quirk_cb ,
52+ .matches = {
53+ DMI_MATCH (DMI_SYS_VENDOR , "Google" ),
54+ DMI_MATCH (DMI_PRODUCT_NAME , "Helios" ),
55+ },
56+ .driver_data = (void * )(SOF_RT1011_SPEAKER_WL | SOF_RT1011_SPEAKER_WR |
57+ SOF_RT1011_SPEAKER_TL | SOF_RT1011_SPEAKER_TR ),
58+ },
59+ {
60+ }
61+ };
62+
3363static struct snd_soc_jack hdmi_jack [3 ];
3464
3565struct hdmi_pcm {
@@ -48,26 +78,30 @@ struct card_private {
4878static const struct snd_kcontrol_new cml_controls [] = {
4979 SOC_DAPM_PIN_SWITCH ("Headphone Jack" ),
5080 SOC_DAPM_PIN_SWITCH ("Headset Mic" ),
51- SOC_DAPM_PIN_SWITCH ("TL Ext Spk" ),
52- SOC_DAPM_PIN_SWITCH ("TR Ext Spk" ),
5381 SOC_DAPM_PIN_SWITCH ("WL Ext Spk" ),
5482 SOC_DAPM_PIN_SWITCH ("WR Ext Spk" ),
5583};
5684
85+ static const struct snd_kcontrol_new cml_rt1011_tt_controls [] = {
86+ SOC_DAPM_PIN_SWITCH ("TL Ext Spk" ),
87+ SOC_DAPM_PIN_SWITCH ("TR Ext Spk" ),
88+ };
89+
5790static const struct snd_soc_dapm_widget cml_rt1011_rt5682_widgets [] = {
58- SND_SOC_DAPM_SPK ("TL Ext Spk" , NULL ),
59- SND_SOC_DAPM_SPK ("TR Ext Spk" , NULL ),
6091 SND_SOC_DAPM_SPK ("WL Ext Spk" , NULL ),
6192 SND_SOC_DAPM_SPK ("WR Ext Spk" , NULL ),
6293 SND_SOC_DAPM_HP ("Headphone Jack" , NULL ),
6394 SND_SOC_DAPM_MIC ("Headset Mic" , NULL ),
6495 SND_SOC_DAPM_MIC ("SoC DMIC" , NULL ),
6596};
6697
98+ static const struct snd_soc_dapm_widget cml_rt1011_tt_widgets [] = {
99+ SND_SOC_DAPM_SPK ("TL Ext Spk" , NULL ),
100+ SND_SOC_DAPM_SPK ("TR Ext Spk" , NULL ),
101+ };
102+
67103static const struct snd_soc_dapm_route cml_rt1011_rt5682_map [] = {
68- /*speaker*/
69- {"TL Ext Spk" , NULL , "TL SPO" },
70- {"TR Ext Spk" , NULL , "TR SPO" },
104+ /*WL/WR speaker*/
71105 {"WL Ext Spk" , NULL , "WL SPO" },
72106 {"WR Ext Spk" , NULL , "WR SPO" },
73107
@@ -82,6 +116,12 @@ static const struct snd_soc_dapm_route cml_rt1011_rt5682_map[] = {
82116 {"DMic" , NULL , "SoC DMIC" },
83117};
84118
119+ static const struct snd_soc_dapm_route cml_rt1011_tt_map [] = {
120+ /*TL/TR speaker*/
121+ {"TL Ext Spk" , NULL , "TL SPO" },
122+ {"TR Ext Spk" , NULL , "TR SPO" },
123+ };
124+
85125static int cml_rt5682_codec_init (struct snd_soc_pcm_runtime * rtd )
86126{
87127 struct card_private * ctx = snd_soc_card_get_drvdata (rtd -> card );
@@ -121,6 +161,35 @@ static int cml_rt5682_codec_init(struct snd_soc_pcm_runtime *rtd)
121161 return ret ;
122162};
123163
164+ static int cml_rt1011_spk_init (struct snd_soc_pcm_runtime * rtd )
165+ {
166+ int ret = 0 ;
167+ struct snd_soc_card * card = rtd -> card ;
168+
169+ if (sof_rt1011_quirk & (SOF_RT1011_SPEAKER_TL |
170+ SOF_RT1011_SPEAKER_TR )) {
171+
172+ ret = snd_soc_add_card_controls (card , cml_rt1011_tt_controls ,
173+ ARRAY_SIZE (cml_rt1011_tt_controls ));
174+ if (ret )
175+ return ret ;
176+
177+ ret = snd_soc_dapm_new_controls (& card -> dapm ,
178+ cml_rt1011_tt_widgets ,
179+ ARRAY_SIZE (cml_rt1011_tt_widgets ));
180+ if (ret )
181+ return ret ;
182+
183+ ret = snd_soc_dapm_add_routes (& card -> dapm , cml_rt1011_tt_map ,
184+ ARRAY_SIZE (cml_rt1011_tt_map ));
185+
186+ if (ret )
187+ return ret ;
188+ }
189+
190+ return ret ;
191+ }
192+
124193static int cml_rt5682_hw_params (struct snd_pcm_substream * substream ,
125194 struct snd_pcm_hw_params * params )
126195{
@@ -191,30 +260,38 @@ static int cml_rt1011_hw_params(struct snd_pcm_substream *substream,
191260 * The feedback is captured for each codec individually.
192261 * Hence all 4 codecs use 1 Tx slot each for feedback.
193262 */
194- if (!strcmp (codec_dai -> component -> name , "i2c-10EC1011:00" )) {
195- ret = snd_soc_dai_set_tdm_slot (codec_dai ,
196- 0x4 , 0x1 , 4 , 24 );
197- if (ret < 0 )
198- break ;
199- }
200- if (!strcmp (codec_dai -> component -> name , "i2c-10EC1011:02" )) {
201- ret = snd_soc_dai_set_tdm_slot (codec_dai ,
202- 0x1 , 0x1 , 4 , 24 );
203- if (ret < 0 )
204- break ;
263+ if (sof_rt1011_quirk & (SOF_RT1011_SPEAKER_WL |
264+ SOF_RT1011_SPEAKER_WR )) {
265+ if (!strcmp (codec_dai -> component -> name , "i2c-10EC1011:00" )) {
266+ ret = snd_soc_dai_set_tdm_slot (codec_dai ,
267+ 0x4 , 0x1 , 4 , 24 );
268+ if (ret < 0 )
269+ break ;
270+ }
271+
272+ if (!strcmp (codec_dai -> component -> name , "i2c-10EC1011:01" )) {
273+ ret = snd_soc_dai_set_tdm_slot (codec_dai ,
274+ 0x8 , 0x2 , 4 , 24 );
275+ if (ret < 0 )
276+ break ;
277+ }
205278 }
206- /* TDM Rx slot 2 is used for Right Woofer & Tweeters pair */
207- if (!strcmp (codec_dai -> component -> name , "i2c-10EC1011:01" )) {
208- ret = snd_soc_dai_set_tdm_slot (codec_dai ,
209- 0x8 , 0x2 , 4 , 24 );
210- if (ret < 0 )
211- break ;
212- }
213- if (!strcmp (codec_dai -> component -> name , "i2c-10EC1011:03" )) {
214- ret = snd_soc_dai_set_tdm_slot (codec_dai ,
215- 0x2 , 0x2 , 4 , 24 );
216- if (ret < 0 )
217- break ;
279+
280+ if (sof_rt1011_quirk & (SOF_RT1011_SPEAKER_TL |
281+ SOF_RT1011_SPEAKER_TR )) {
282+ if (!strcmp (codec_dai -> component -> name , "i2c-10EC1011:02" )) {
283+ ret = snd_soc_dai_set_tdm_slot (codec_dai ,
284+ 0x1 , 0x1 , 4 , 24 );
285+ if (ret < 0 )
286+ break ;
287+ }
288+
289+ if (!strcmp (codec_dai -> component -> name , "i2c-10EC1011:03" )) {
290+ ret = snd_soc_dai_set_tdm_slot (codec_dai ,
291+ 0x2 , 0x2 , 4 , 24 );
292+ if (ret < 0 )
293+ break ;
294+ }
218295 }
219296 }
220297 if (ret < 0 )
@@ -302,9 +379,7 @@ SND_SOC_DAILINK_DEF(ssp1_pin,
302379SND_SOC_DAILINK_DEF (ssp1_codec ,
303380 DAILINK_COMP_ARRAY (
304381 /* WL */ COMP_CODEC ("i2c-10EC1011:00" , CML_RT1011_CODEC_DAI ),
305- /* WR */ COMP_CODEC ("i2c-10EC1011:01" , CML_RT1011_CODEC_DAI ),
306- /* TL */ COMP_CODEC ("i2c-10EC1011:02" , CML_RT1011_CODEC_DAI ),
307- /* TR */ COMP_CODEC ("i2c-10EC1011:03" , CML_RT1011_CODEC_DAI )));
382+ /* WR */ COMP_CODEC ("i2c-10EC1011:01" , CML_RT1011_CODEC_DAI )));
308383
309384SND_SOC_DAILINK_DEF (dmic_pin ,
310385 DAILINK_COMP_ARRAY (COMP_CPU ("DMIC01 Pin" )));
@@ -398,6 +473,7 @@ static struct snd_soc_dai_link cml_rt1011_rt5682_dailink[] = {
398473 .dpcm_playback = 1 ,
399474 .dpcm_capture = 1 , /* Capture stream provides Feedback */
400475 .no_pcm = 1 ,
476+ .init = cml_rt1011_spk_init ,
401477 .ops = & cml_rt1011_ops ,
402478 SND_SOC_DAILINK_REG (ssp1_pin , ssp1_codec , platform ),
403479 },
@@ -412,14 +488,6 @@ static struct snd_soc_codec_conf rt1011_conf[] = {
412488 .dlc = COMP_CODEC_CONF ("i2c-10EC1011:01" ),
413489 .name_prefix = "WR" ,
414490 },
415- {
416- .dlc = COMP_CODEC_CONF ("i2c-10EC1011:02" ),
417- .name_prefix = "TL" ,
418- },
419- {
420- .dlc = COMP_CODEC_CONF ("i2c-10EC1011:03" ),
421- .name_prefix = "TR" ,
422- },
423491};
424492
425493/* Cometlake audio machine driver for RT1011 and RT5682 */
@@ -441,10 +509,12 @@ static struct snd_soc_card snd_soc_card_cml = {
441509
442510static int snd_cml_rt1011_probe (struct platform_device * pdev )
443511{
512+ struct snd_soc_dai_link_component * rt1011_dais_components ;
513+ struct snd_soc_codec_conf * rt1011_dais_confs ;
444514 struct card_private * ctx ;
445515 struct snd_soc_acpi_mach * mach ;
446516 const char * platform_name ;
447- int ret ;
517+ int ret , i ;
448518
449519 ctx = devm_kzalloc (& pdev -> dev , sizeof (* ctx ), GFP_KERNEL );
450520 if (!ctx )
@@ -455,6 +525,73 @@ static int snd_cml_rt1011_probe(struct platform_device *pdev)
455525 snd_soc_card_cml .dev = & pdev -> dev ;
456526 platform_name = mach -> mach_params .platform ;
457527
528+ dmi_check_system (sof_rt1011_quirk_table );
529+
530+ dev_info (& pdev -> dev , "sof_rt1011_quirk = %lx\n" , sof_rt1011_quirk );
531+
532+ if (sof_rt1011_quirk & (SOF_RT1011_SPEAKER_TL |
533+ SOF_RT1011_SPEAKER_TR )) {
534+ rt1011_dais_confs = devm_kzalloc (& pdev -> dev ,
535+ sizeof (struct snd_soc_codec_conf ) *
536+ SPK_CH , GFP_KERNEL );
537+
538+ if (!rt1011_dais_confs )
539+ return - ENOMEM ;
540+
541+ rt1011_dais_components = devm_kzalloc (& pdev -> dev ,
542+ sizeof (struct snd_soc_dai_link_component ) *
543+ SPK_CH , GFP_KERNEL );
544+
545+ if (!rt1011_dais_components )
546+ return - ENOMEM ;
547+
548+ for (i = 0 ; i < SPK_CH ; i ++ ) {
549+ rt1011_dais_confs [i ].dlc .name = devm_kasprintf (& pdev -> dev ,
550+ GFP_KERNEL ,
551+ "i2c-10EC1011:0%d" ,
552+ i );
553+
554+ if (!rt1011_dais_confs [i ].dlc .name )
555+ return - ENOMEM ;
556+
557+ switch (i ) {
558+ case 0 :
559+ rt1011_dais_confs [i ].name_prefix = "WL" ;
560+ break ;
561+ case 1 :
562+ rt1011_dais_confs [i ].name_prefix = "WR" ;
563+ break ;
564+ case 2 :
565+ rt1011_dais_confs [i ].name_prefix = "TL" ;
566+ break ;
567+ case 3 :
568+ rt1011_dais_confs [i ].name_prefix = "TR" ;
569+ break ;
570+ default :
571+ return - EINVAL ;
572+ }
573+ rt1011_dais_components [i ].name = devm_kasprintf (& pdev -> dev ,
574+ GFP_KERNEL ,
575+ "i2c-10EC1011:0%d" ,
576+ i );
577+ if (!rt1011_dais_components [i ].name )
578+ return - ENOMEM ;
579+
580+ rt1011_dais_components [i ].dai_name = CML_RT1011_CODEC_DAI ;
581+ }
582+
583+ snd_soc_card_cml .codec_conf = rt1011_dais_confs ;
584+ snd_soc_card_cml .num_configs = SPK_CH ;
585+
586+ for (i = 0 ; i < ARRAY_SIZE (cml_rt1011_rt5682_dailink ); i ++ ) {
587+ if (!strcmp (cml_rt1011_rt5682_dailink [i ].codecs -> dai_name ,
588+ CML_RT1011_CODEC_DAI )) {
589+ cml_rt1011_rt5682_dailink [i ].codecs = rt1011_dais_components ;
590+ cml_rt1011_rt5682_dailink [i ].num_codecs = SPK_CH ;
591+ }
592+ }
593+ }
594+
458595 /* set platform name for each dailink */
459596 ret = snd_soc_fixup_dai_links_platform_name (& snd_soc_card_cml ,
460597 platform_name );
@@ -482,5 +619,6 @@ MODULE_DESCRIPTION("Cometlake Audio Machine driver - RT1011 and RT5682 in I2S mo
482619MODULE_AUTHOR ("Naveen Manohar <naveen.m@intel.com>" );
483620MODULE_AUTHOR ("Sathya Prakash M R <sathya.prakash.m.r@intel.com>" );
484621MODULE_AUTHOR ("Shuming Fan <shumingf@realtek.com>" );
622+ MODULE_AUTHOR ("Mac Chiang <mac.chiang@intel.com>" );
485623MODULE_LICENSE ("GPL v2" );
486624MODULE_ALIAS ("platform:cml_rt1011_rt5682" );
0 commit comments