1515#include "../../codecs/rt1011.h"
1616#include "../../codecs/rt1015.h"
1717#include "../../codecs/rt1308.h"
18+ #include "../common/soc-intel-quirks.h"
1819#include "sof_realtek_common.h"
1920
2021/*
21- * Current only 2-amp configuration is supported for rt1011
22+ * Common structures and functions
23+ */
24+ static const struct snd_kcontrol_new realtek_4spk_kcontrols [] = {
25+ SOC_DAPM_PIN_SWITCH ("WL Ext Spk" ),
26+ SOC_DAPM_PIN_SWITCH ("WR Ext Spk" ),
27+ SOC_DAPM_PIN_SWITCH ("TL Ext Spk" ),
28+ SOC_DAPM_PIN_SWITCH ("TR Ext Spk" ),
29+ };
30+
31+ static const struct snd_soc_dapm_widget realtek_4spk_widgets [] = {
32+ SND_SOC_DAPM_SPK ("WL Ext Spk" , NULL ),
33+ SND_SOC_DAPM_SPK ("WR Ext Spk" , NULL ),
34+ SND_SOC_DAPM_SPK ("TL Ext Spk" , NULL ),
35+ SND_SOC_DAPM_SPK ("TR Ext Spk" , NULL ),
36+ };
37+
38+ /* helper function to get the number of specific codec */
39+ static unsigned int get_num_codecs (const char * hid )
40+ {
41+ struct acpi_device * adev ;
42+ unsigned int dev_num = 0 ;
43+
44+ for_each_acpi_dev_match (adev , hid , NULL , -1 )
45+ dev_num ++ ;
46+
47+ return dev_num ;
48+ }
49+
50+ /*
51+ * Realtek ALC1011
2252 */
2353static const struct snd_soc_dapm_route speaker_map_lr [] = {
2454 /* speaker */
2555 { "Left Spk" , NULL , "Left SPO" },
2656 { "Right Spk" , NULL , "Right SPO" },
2757};
2858
29- /*
30- * Make sure device's Unique ID follows this configuration:
31- *
32- * Two speakers:
33- * 0: left, 1: right
34- * Four speakers:
35- * 0: Woofer left, 1: Woofer right
36- * 2: Tweeter left, 3: Tweeter right
37- */
38- static struct snd_soc_codec_conf rt1011_codec_confs [] = {
59+ static const struct snd_soc_dapm_route rt1011_4spk_routes [] = {
60+ {"WL Ext Spk" , NULL , "WL SPO" },
61+ {"WR Ext Spk" , NULL , "WR SPO" },
62+ {"TL Ext Spk" , NULL , "TL SPO" },
63+ {"TR Ext Spk" , NULL , "TR SPO" },
64+ };
65+
66+ static struct snd_soc_codec_conf rt1011_2spk_codec_confs [] = {
3967 {
4068 .dlc = COMP_CODEC_CONF (RT1011_DEV0_NAME ),
4169 .name_prefix = "Left" ,
@@ -46,6 +74,25 @@ static struct snd_soc_codec_conf rt1011_codec_confs[] = {
4674 },
4775};
4876
77+ static struct snd_soc_codec_conf rt1011_4spk_codec_confs [] = {
78+ {
79+ .dlc = COMP_CODEC_CONF (RT1011_DEV0_NAME ),
80+ .name_prefix = "WL" ,
81+ },
82+ {
83+ .dlc = COMP_CODEC_CONF (RT1011_DEV1_NAME ),
84+ .name_prefix = "WR" ,
85+ },
86+ {
87+ .dlc = COMP_CODEC_CONF (RT1011_DEV2_NAME ),
88+ .name_prefix = "TL" ,
89+ },
90+ {
91+ .dlc = COMP_CODEC_CONF (RT1011_DEV3_NAME ),
92+ .name_prefix = "TR" ,
93+ },
94+ };
95+
4996static struct snd_soc_dai_link_component rt1011_dai_link_components [] = {
5097 {
5198 .name = RT1011_DEV0_NAME ,
@@ -55,6 +102,14 @@ static struct snd_soc_dai_link_component rt1011_dai_link_components[] = {
55102 .name = RT1011_DEV1_NAME ,
56103 .dai_name = RT1011_CODEC_DAI ,
57104 },
105+ {
106+ .name = RT1011_DEV2_NAME ,
107+ .dai_name = RT1011_CODEC_DAI ,
108+ },
109+ {
110+ .name = RT1011_DEV3_NAME ,
111+ .dai_name = RT1011_CODEC_DAI ,
112+ },
58113};
59114
60115static const struct {
@@ -63,6 +118,8 @@ static const struct {
63118} rt1011_tdm_mask [] = {
64119 {.tx = 0x4 , .rx = 0x1 },
65120 {.tx = 0x8 , .rx = 0x2 },
121+ {.tx = 0x1 , .rx = 0x1 },
122+ {.tx = 0x2 , .rx = 0x2 },
66123};
67124
68125static int rt1011_hw_params (struct snd_pcm_substream * substream ,
@@ -118,28 +175,109 @@ static const struct snd_soc_ops rt1011_ops = {
118175static int rt1011_init (struct snd_soc_pcm_runtime * rtd )
119176{
120177 struct snd_soc_card * card = rtd -> card ;
178+ unsigned int num_codecs = get_num_codecs (RT1011_ACPI_HID );
121179 int ret ;
122180
123- ret = snd_soc_dapm_add_routes (& card -> dapm , speaker_map_lr ,
124- ARRAY_SIZE (speaker_map_lr ));
125- if (ret )
126- dev_err (rtd -> dev , "Speaker map addition failed: %d\n" , ret );
181+ switch (num_codecs ) {
182+ case 2 :
183+ if (!soc_intel_is_cml ()) {
184+ ret = snd_soc_dapm_add_routes (& card -> dapm , speaker_map_lr ,
185+ ARRAY_SIZE (speaker_map_lr ));
186+ if (ret ) {
187+ dev_err (rtd -> dev , "fail to add rt1011 routes, ret %d\n" ,
188+ ret );
189+ return ret ;
190+ }
191+
192+ break ;
193+ }
194+
195+ /*
196+ * register speaker widgets "WL Ext Spk" and "WR Ext Spk" to
197+ * keep backward compatible with cml devices
198+ */
199+ fallthrough ;
200+ case 4 :
201+ ret = snd_soc_dapm_new_controls (& card -> dapm , realtek_4spk_widgets ,
202+ num_codecs );
203+ if (ret ) {
204+ dev_err (rtd -> dev , "fail to add rt1011 widgets, ret %d\n" ,
205+ ret );
206+ return ret ;
207+ }
208+
209+ ret = snd_soc_add_card_controls (card , realtek_4spk_kcontrols ,
210+ num_codecs );
211+ if (ret ) {
212+ dev_err (rtd -> dev , "fail to add rt1011 controls, ret %d\n" ,
213+ ret );
214+ return ret ;
215+ }
216+
217+ ret = snd_soc_dapm_add_routes (& card -> dapm , rt1011_4spk_routes ,
218+ num_codecs );
219+ if (ret ) {
220+ dev_err (rtd -> dev , "fail to add rt1011 routes, ret %d\n" ,
221+ ret );
222+ return ret ;
223+ }
224+ break ;
225+ default :
226+ dev_err (rtd -> dev , "rt1011: invalid num_codecs %d\n" , num_codecs );
227+ return - EINVAL ;
228+ }
229+
127230 return ret ;
128231}
129232
130- void sof_rt1011_dai_link (struct snd_soc_dai_link * link )
233+ void sof_rt1011_dai_link (struct device * dev , struct snd_soc_dai_link * link )
131234{
235+ unsigned int num_codecs = get_num_codecs (RT1011_ACPI_HID );
236+
132237 link -> codecs = rt1011_dai_link_components ;
133- link -> num_codecs = ARRAY_SIZE (rt1011_dai_link_components );
238+
239+ switch (num_codecs ) {
240+ case 2 :
241+ case 4 :
242+ link -> num_codecs = num_codecs ;
243+ break ;
244+ default :
245+ dev_err (dev , "rt1011: invalid num_codecs %d\n" , num_codecs );
246+ break ;
247+ }
248+
134249 link -> init = rt1011_init ;
135250 link -> ops = & rt1011_ops ;
136251}
137252EXPORT_SYMBOL_NS (sof_rt1011_dai_link , SND_SOC_INTEL_SOF_REALTEK_COMMON );
138253
139- void sof_rt1011_codec_conf (struct snd_soc_card * card )
254+ void sof_rt1011_codec_conf (struct device * dev , struct snd_soc_card * card )
140255{
141- card -> codec_conf = rt1011_codec_confs ;
142- card -> num_configs = ARRAY_SIZE (rt1011_codec_confs );
256+ unsigned int num_codecs = get_num_codecs (RT1011_ACPI_HID );
257+
258+ switch (num_codecs ) {
259+ case 2 :
260+ if (soc_intel_is_cml ()) {
261+ /*
262+ * use name prefix 'WL' and 'WR' for speaker widgets to
263+ * keep backward compatible with cml devices
264+ */
265+ card -> codec_conf = rt1011_4spk_codec_confs ;
266+ } else {
267+ card -> codec_conf = rt1011_2spk_codec_confs ;
268+ }
269+
270+ card -> num_configs = num_codecs ;
271+ break ;
272+ case 4 :
273+ card -> codec_conf = rt1011_4spk_codec_confs ;
274+ card -> num_configs = ARRAY_SIZE (rt1011_4spk_codec_confs );
275+ break ;
276+ default :
277+ dev_err (dev , "rt1011: invalid num_codecs %d\n" , num_codecs );
278+ break ;
279+ }
280+
143281}
144282EXPORT_SYMBOL_NS (sof_rt1011_codec_conf , SND_SOC_INTEL_SOF_REALTEK_COMMON );
145283
0 commit comments