30
30
#define CML_RT5682_CODEC_DAI "rt5682-aif1"
31
31
#define NAME_SIZE 32
32
32
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
+
33
63
static struct snd_soc_jack hdmi_jack [3 ];
34
64
35
65
struct hdmi_pcm {
@@ -48,26 +78,30 @@ struct card_private {
48
78
static const struct snd_kcontrol_new cml_controls [] = {
49
79
SOC_DAPM_PIN_SWITCH ("Headphone Jack" ),
50
80
SOC_DAPM_PIN_SWITCH ("Headset Mic" ),
51
- SOC_DAPM_PIN_SWITCH ("TL Ext Spk" ),
52
- SOC_DAPM_PIN_SWITCH ("TR Ext Spk" ),
53
81
SOC_DAPM_PIN_SWITCH ("WL Ext Spk" ),
54
82
SOC_DAPM_PIN_SWITCH ("WR Ext Spk" ),
55
83
};
56
84
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
+
57
90
static 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 ),
60
91
SND_SOC_DAPM_SPK ("WL Ext Spk" , NULL ),
61
92
SND_SOC_DAPM_SPK ("WR Ext Spk" , NULL ),
62
93
SND_SOC_DAPM_HP ("Headphone Jack" , NULL ),
63
94
SND_SOC_DAPM_MIC ("Headset Mic" , NULL ),
64
95
SND_SOC_DAPM_MIC ("SoC DMIC" , NULL ),
65
96
};
66
97
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
+
67
103
static 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*/
71
105
{"WL Ext Spk" , NULL , "WL SPO" },
72
106
{"WR Ext Spk" , NULL , "WR SPO" },
73
107
@@ -82,6 +116,12 @@ static const struct snd_soc_dapm_route cml_rt1011_rt5682_map[] = {
82
116
{"DMic" , NULL , "SoC DMIC" },
83
117
};
84
118
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
+
85
125
static int cml_rt5682_codec_init (struct snd_soc_pcm_runtime * rtd )
86
126
{
87
127
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)
121
161
return ret ;
122
162
};
123
163
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
+
124
193
static int cml_rt5682_hw_params (struct snd_pcm_substream * substream ,
125
194
struct snd_pcm_hw_params * params )
126
195
{
@@ -191,30 +260,38 @@ static int cml_rt1011_hw_params(struct snd_pcm_substream *substream,
191
260
* The feedback is captured for each codec individually.
192
261
* Hence all 4 codecs use 1 Tx slot each for feedback.
193
262
*/
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
+ }
205
278
}
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
+ }
218
295
}
219
296
}
220
297
if (ret < 0 )
@@ -302,9 +379,7 @@ SND_SOC_DAILINK_DEF(ssp1_pin,
302
379
SND_SOC_DAILINK_DEF (ssp1_codec ,
303
380
DAILINK_COMP_ARRAY (
304
381
/* 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 )));
308
383
309
384
SND_SOC_DAILINK_DEF (dmic_pin ,
310
385
DAILINK_COMP_ARRAY (COMP_CPU ("DMIC01 Pin" )));
@@ -398,6 +473,7 @@ static struct snd_soc_dai_link cml_rt1011_rt5682_dailink[] = {
398
473
.dpcm_playback = 1 ,
399
474
.dpcm_capture = 1 , /* Capture stream provides Feedback */
400
475
.no_pcm = 1 ,
476
+ .init = cml_rt1011_spk_init ,
401
477
.ops = & cml_rt1011_ops ,
402
478
SND_SOC_DAILINK_REG (ssp1_pin , ssp1_codec , platform ),
403
479
},
@@ -412,14 +488,6 @@ static struct snd_soc_codec_conf rt1011_conf[] = {
412
488
.dlc = COMP_CODEC_CONF ("i2c-10EC1011:01" ),
413
489
.name_prefix = "WR" ,
414
490
},
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
- },
423
491
};
424
492
425
493
/* Cometlake audio machine driver for RT1011 and RT5682 */
@@ -441,10 +509,12 @@ static struct snd_soc_card snd_soc_card_cml = {
441
509
442
510
static int snd_cml_rt1011_probe (struct platform_device * pdev )
443
511
{
512
+ struct snd_soc_dai_link_component * rt1011_dais_components ;
513
+ struct snd_soc_codec_conf * rt1011_dais_confs ;
444
514
struct card_private * ctx ;
445
515
struct snd_soc_acpi_mach * mach ;
446
516
const char * platform_name ;
447
- int ret ;
517
+ int ret , i ;
448
518
449
519
ctx = devm_kzalloc (& pdev -> dev , sizeof (* ctx ), GFP_KERNEL );
450
520
if (!ctx )
@@ -455,6 +525,73 @@ static int snd_cml_rt1011_probe(struct platform_device *pdev)
455
525
snd_soc_card_cml .dev = & pdev -> dev ;
456
526
platform_name = mach -> mach_params .platform ;
457
527
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
+
458
595
/* set platform name for each dailink */
459
596
ret = snd_soc_fixup_dai_links_platform_name (& snd_soc_card_cml ,
460
597
platform_name );
@@ -482,5 +619,6 @@ MODULE_DESCRIPTION("Cometlake Audio Machine driver - RT1011 and RT5682 in I2S mo
482
619
MODULE_AUTHOR ("Naveen Manohar <naveen.m@intel.com>" );
483
620
MODULE_AUTHOR ("Sathya Prakash M R <sathya.prakash.m.r@intel.com>" );
484
621
MODULE_AUTHOR ("Shuming Fan <shumingf@realtek.com>" );
622
+ MODULE_AUTHOR ("Mac Chiang <mac.chiang@intel.com>" );
485
623
MODULE_LICENSE ("GPL v2" );
486
624
MODULE_ALIAS ("platform:cml_rt1011_rt5682" );
0 commit comments