~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/sound/soc/amd/acp/acp-sdw-sof-mach.c

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.12 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

Diff markup

Differences between /sound/soc/amd/acp/acp-sdw-sof-mach.c (Architecture sparc) and /sound/soc/amd/acp/acp-sdw-sof-mach.c (Architecture ppc)


  1 // SPDX-License-Identifier: GPL-2.0-only            1 // SPDX-License-Identifier: GPL-2.0-only
  2 // Copyright(c) 2024 Advanced Micro Devices, I      2 // Copyright(c) 2024 Advanced Micro Devices, Inc.
  3                                                     3 
  4 /*                                                  4 /*
  5  *  acp-sdw-sof-mach - ASoC Machine driver for      5  *  acp-sdw-sof-mach - ASoC Machine driver for AMD SoundWire platforms
  6  */                                                 6  */
  7                                                     7 
  8 #include <linux/bitmap.h>                           8 #include <linux/bitmap.h>
  9 #include <linux/device.h>                           9 #include <linux/device.h>
 10 #include <linux/dmi.h>                             10 #include <linux/dmi.h>
 11 #include <linux/module.h>                          11 #include <linux/module.h>
 12 #include <linux/soundwire/sdw.h>                   12 #include <linux/soundwire/sdw.h>
 13 #include <linux/soundwire/sdw_type.h>              13 #include <linux/soundwire/sdw_type.h>
 14 #include <sound/soc.h>                             14 #include <sound/soc.h>
 15 #include <sound/soc-acpi.h>                        15 #include <sound/soc-acpi.h>
 16 #include "soc_amd_sdw_common.h"                    16 #include "soc_amd_sdw_common.h"
 17 #include "../../codecs/rt711.h"                    17 #include "../../codecs/rt711.h"
 18                                                    18 
 19 static unsigned long sof_sdw_quirk = RT711_JD1     19 static unsigned long sof_sdw_quirk = RT711_JD1;
 20 static int quirk_override = -1;                    20 static int quirk_override = -1;
 21 module_param_named(quirk, quirk_override, int,     21 module_param_named(quirk, quirk_override, int, 0444);
 22 MODULE_PARM_DESC(quirk, "Board-specific quirk      22 MODULE_PARM_DESC(quirk, "Board-specific quirk override");
 23                                                    23 
 24 static void log_quirks(struct device *dev)         24 static void log_quirks(struct device *dev)
 25 {                                                  25 {
 26         if (SOC_JACK_JDSRC(sof_sdw_quirk))         26         if (SOC_JACK_JDSRC(sof_sdw_quirk))
 27                 dev_dbg(dev, "quirk realtek,ja     27                 dev_dbg(dev, "quirk realtek,jack-detect-source %ld\n",
 28                         SOC_JACK_JDSRC(sof_sdw     28                         SOC_JACK_JDSRC(sof_sdw_quirk));
 29         if (sof_sdw_quirk & ASOC_SDW_ACP_DMIC)     29         if (sof_sdw_quirk & ASOC_SDW_ACP_DMIC)
 30                 dev_dbg(dev, "quirk SOC_SDW_AC     30                 dev_dbg(dev, "quirk SOC_SDW_ACP_DMIC enabled\n");
 31 }                                                  31 }
 32                                                    32 
 33 static int sof_sdw_quirk_cb(const struct dmi_s     33 static int sof_sdw_quirk_cb(const struct dmi_system_id *id)
 34 {                                                  34 {
 35         sof_sdw_quirk = (unsigned long)id->dri     35         sof_sdw_quirk = (unsigned long)id->driver_data;
 36         return 1;                                  36         return 1;
 37 }                                                  37 }
 38                                                    38 
 39 static const struct dmi_system_id sof_sdw_quir     39 static const struct dmi_system_id sof_sdw_quirk_table[] = {
 40         {                                          40         {
 41                 .callback = sof_sdw_quirk_cb,      41                 .callback = sof_sdw_quirk_cb,
 42                 .matches = {                       42                 .matches = {
 43                         DMI_MATCH(DMI_SYS_VEND     43                         DMI_MATCH(DMI_SYS_VENDOR, "AMD"),
 44                         DMI_MATCH(DMI_PRODUCT_     44                         DMI_MATCH(DMI_PRODUCT_NAME, "Birman-PHX"),
 45                 },                                 45                 },
 46                 .driver_data = (void *)RT711_J     46                 .driver_data = (void *)RT711_JD2,
 47         },                                         47         },
 48         {}                                         48         {}
 49 };                                                 49 };
 50                                                    50 
 51 static struct snd_soc_dai_link_component platf     51 static struct snd_soc_dai_link_component platform_component[] = {
 52         {                                          52         {
 53                 /* name might be overridden du     53                 /* name might be overridden during probe */
 54                 .name = "0000:04:00.5",            54                 .name = "0000:04:00.5",
 55         }                                          55         }
 56 };                                                 56 };
 57                                                    57 
 58 static const struct snd_soc_ops sdw_ops = {        58 static const struct snd_soc_ops sdw_ops = {
 59         .startup = asoc_sdw_startup,               59         .startup = asoc_sdw_startup,
 60         .prepare = asoc_sdw_prepare,               60         .prepare = asoc_sdw_prepare,
 61         .trigger = asoc_sdw_trigger,               61         .trigger = asoc_sdw_trigger,
 62         .hw_params = asoc_sdw_hw_params,           62         .hw_params = asoc_sdw_hw_params,
 63         .hw_free = asoc_sdw_hw_free,               63         .hw_free = asoc_sdw_hw_free,
 64         .shutdown = asoc_sdw_shutdown,             64         .shutdown = asoc_sdw_shutdown,
 65 };                                                 65 };
 66                                                    66 
 67 static int get_acp63_cpu_pin_id(u32 sdw_link_i     67 static int get_acp63_cpu_pin_id(u32 sdw_link_id, int be_id, int *cpu_pin_id, struct device *dev)
 68 {                                                  68 {
 69         switch (sdw_link_id) {                     69         switch (sdw_link_id) {
 70         case AMD_SDW0:                             70         case AMD_SDW0:
 71                 switch (be_id) {                   71                 switch (be_id) {
 72                 case SOC_SDW_JACK_OUT_DAI_ID:      72                 case SOC_SDW_JACK_OUT_DAI_ID:
 73                         *cpu_pin_id = ACP63_SW     73                         *cpu_pin_id = ACP63_SW0_AUDIO0_TX;
 74                         break;                     74                         break;
 75                 case SOC_SDW_JACK_IN_DAI_ID:       75                 case SOC_SDW_JACK_IN_DAI_ID:
 76                         *cpu_pin_id = ACP63_SW     76                         *cpu_pin_id = ACP63_SW0_AUDIO0_RX;
 77                         break;                     77                         break;
 78                 case SOC_SDW_AMP_OUT_DAI_ID:       78                 case SOC_SDW_AMP_OUT_DAI_ID:
 79                         *cpu_pin_id = ACP63_SW     79                         *cpu_pin_id = ACP63_SW0_AUDIO1_TX;
 80                         break;                     80                         break;
 81                 case SOC_SDW_AMP_IN_DAI_ID:        81                 case SOC_SDW_AMP_IN_DAI_ID:
 82                         *cpu_pin_id = ACP63_SW     82                         *cpu_pin_id = ACP63_SW0_AUDIO1_RX;
 83                         break;                     83                         break;
 84                 case SOC_SDW_DMIC_DAI_ID:          84                 case SOC_SDW_DMIC_DAI_ID:
 85                         *cpu_pin_id = ACP63_SW     85                         *cpu_pin_id = ACP63_SW0_AUDIO2_RX;
 86                         break;                     86                         break;
 87                 default:                           87                 default:
 88                         dev_err(dev, "Invalid      88                         dev_err(dev, "Invalid be id:%d\n", be_id);
 89                         return -EINVAL;            89                         return -EINVAL;
 90                 }                                  90                 }
 91                 break;                             91                 break;
 92         case AMD_SDW1:                             92         case AMD_SDW1:
 93                 switch (be_id) {                   93                 switch (be_id) {
 94                 case SOC_SDW_JACK_OUT_DAI_ID:      94                 case SOC_SDW_JACK_OUT_DAI_ID:
 95                 case SOC_SDW_AMP_OUT_DAI_ID:       95                 case SOC_SDW_AMP_OUT_DAI_ID:
 96                         *cpu_pin_id = ACP63_SW     96                         *cpu_pin_id = ACP63_SW1_AUDIO0_TX;
 97                         break;                     97                         break;
 98                 case SOC_SDW_JACK_IN_DAI_ID:       98                 case SOC_SDW_JACK_IN_DAI_ID:
 99                 case SOC_SDW_AMP_IN_DAI_ID:        99                 case SOC_SDW_AMP_IN_DAI_ID:
100                 case SOC_SDW_DMIC_DAI_ID:         100                 case SOC_SDW_DMIC_DAI_ID:
101                         *cpu_pin_id = ACP63_SW    101                         *cpu_pin_id = ACP63_SW1_AUDIO0_RX;
102                         break;                    102                         break;
103                 default:                          103                 default:
104                         dev_err(dev, "invalid     104                         dev_err(dev, "invalid be_id:%d\n", be_id);
105                         return -EINVAL;           105                         return -EINVAL;
106                 }                                 106                 }
107                 break;                            107                 break;
108         default:                                  108         default:
109                 dev_err(dev, "Invalid link id:    109                 dev_err(dev, "Invalid link id:%d\n", sdw_link_id);
110                 return -EINVAL;                   110                 return -EINVAL;
111         }                                         111         }
112         return 0;                                 112         return 0;
113 }                                                 113 }
114                                                   114 
115 static const char * const type_strings[] = {"S    115 static const char * const type_strings[] = {"SimpleJack", "SmartAmp", "SmartMic"};
116                                                   116 
117 static int create_sdw_dailink(struct snd_soc_c    117 static int create_sdw_dailink(struct snd_soc_card *card,
118                               struct asoc_sdw_    118                               struct asoc_sdw_dailink *sof_dai,
119                               struct snd_soc_d    119                               struct snd_soc_dai_link **dai_links,
120                               int *be_id, stru    120                               int *be_id, struct snd_soc_codec_conf **codec_conf)
121 {                                                 121 {
122         struct device *dev = card->dev;           122         struct device *dev = card->dev;
123         struct asoc_sdw_mc_private *ctx = snd_    123         struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card);
124         struct amd_mc_ctx *amd_ctx = (struct a    124         struct amd_mc_ctx *amd_ctx = (struct amd_mc_ctx *)ctx->private;
125         struct asoc_sdw_endpoint *sof_end;        125         struct asoc_sdw_endpoint *sof_end;
126         int cpu_pin_id;                           126         int cpu_pin_id;
127         int stream;                               127         int stream;
128         int ret;                                  128         int ret;
129                                                   129 
130         list_for_each_entry(sof_end, &sof_dai-    130         list_for_each_entry(sof_end, &sof_dai->endpoints, list) {
131                 if (sof_end->name_prefix) {       131                 if (sof_end->name_prefix) {
132                         (*codec_conf)->dlc.nam    132                         (*codec_conf)->dlc.name = sof_end->codec_name;
133                         (*codec_conf)->name_pr    133                         (*codec_conf)->name_prefix = sof_end->name_prefix;
134                         (*codec_conf)++;          134                         (*codec_conf)++;
135                 }                                 135                 }
136                                                   136 
137                 if (sof_end->include_sidecar)     137                 if (sof_end->include_sidecar) {
138                         ret = sof_end->codec_i    138                         ret = sof_end->codec_info->add_sidecar(card, dai_links, codec_conf);
139                         if (ret)                  139                         if (ret)
140                                 return ret;       140                                 return ret;
141                 }                                 141                 }
142         }                                         142         }
143                                                   143 
144         for_each_pcm_streams(stream) {            144         for_each_pcm_streams(stream) {
145                 static const char * const sdw_    145                 static const char * const sdw_stream_name[] = {
146                         "SDW%d-PIN%d-PLAYBACK"    146                         "SDW%d-PIN%d-PLAYBACK",
147                         "SDW%d-PIN%d-CAPTURE",    147                         "SDW%d-PIN%d-CAPTURE",
148                         "SDW%d-PIN%d-PLAYBACK-    148                         "SDW%d-PIN%d-PLAYBACK-%s",
149                         "SDW%d-PIN%d-CAPTURE-%    149                         "SDW%d-PIN%d-CAPTURE-%s",
150                 };                                150                 };
151                 struct snd_soc_dai_link_ch_map    151                 struct snd_soc_dai_link_ch_map *codec_maps;
152                 struct snd_soc_dai_link_compon    152                 struct snd_soc_dai_link_component *codecs;
153                 struct snd_soc_dai_link_compon    153                 struct snd_soc_dai_link_component *cpus;
154                 int num_cpus = hweight32(sof_d    154                 int num_cpus = hweight32(sof_dai->link_mask[stream]);
155                 int num_codecs = sof_dai->num_    155                 int num_codecs = sof_dai->num_devs[stream];
156                 int playback, capture;            156                 int playback, capture;
157                 int i = 0, j = 0;                 157                 int i = 0, j = 0;
158                 char *name;                       158                 char *name;
159                                                   159 
160                 if (!sof_dai->num_devs[stream]    160                 if (!sof_dai->num_devs[stream])
161                         continue;                 161                         continue;
162                                                   162 
163                 sof_end = list_first_entry(&so    163                 sof_end = list_first_entry(&sof_dai->endpoints,
164                                            str    164                                            struct asoc_sdw_endpoint, list);
165                                                   165 
166                 *be_id = sof_end->dai_info->da    166                 *be_id = sof_end->dai_info->dailink[stream];
167                 if (*be_id < 0) {                 167                 if (*be_id < 0) {
168                         dev_err(dev, "Invalid     168                         dev_err(dev, "Invalid dailink id %d\n", *be_id);
169                         return -EINVAL;           169                         return -EINVAL;
170                 }                                 170                 }
171                                                   171 
172                 switch (amd_ctx->acp_rev) {       172                 switch (amd_ctx->acp_rev) {
173                 case ACP63_PCI_REV:               173                 case ACP63_PCI_REV:
174                         ret = get_acp63_cpu_pi    174                         ret = get_acp63_cpu_pin_id(ffs(sof_end->link_mask - 1),
175                                                   175                                                    *be_id, &cpu_pin_id, dev);
176                         if (ret)                  176                         if (ret)
177                                 return ret;       177                                 return ret;
178                         break;                    178                         break;
179                 default:                          179                 default:
180                         return -EINVAL;           180                         return -EINVAL;
181                 }                                 181                 }
182                 /* create stream name accordin    182                 /* create stream name according to first link id */
183                 if (ctx->append_dai_type) {       183                 if (ctx->append_dai_type) {
184                         name = devm_kasprintf(    184                         name = devm_kasprintf(dev, GFP_KERNEL,
185                                                   185                                               sdw_stream_name[stream + 2],
186                                                   186                                               ffs(sof_end->link_mask) - 1,
187                                                   187                                               cpu_pin_id,
188                                                   188                                               type_strings[sof_end->dai_info->dai_type]);
189                 } else {                          189                 } else {
190                         name = devm_kasprintf(    190                         name = devm_kasprintf(dev, GFP_KERNEL,
191                                                   191                                               sdw_stream_name[stream],
192                                                   192                                               ffs(sof_end->link_mask) - 1,
193                                                   193                                               cpu_pin_id);
194                 }                                 194                 }
195                 if (!name)                        195                 if (!name)
196                         return -ENOMEM;           196                         return -ENOMEM;
197                                                   197 
198                 cpus = devm_kcalloc(dev, num_c    198                 cpus = devm_kcalloc(dev, num_cpus, sizeof(*cpus), GFP_KERNEL);
199                 if (!cpus)                        199                 if (!cpus)
200                         return -ENOMEM;           200                         return -ENOMEM;
201                                                   201 
202                 codecs = devm_kcalloc(dev, num    202                 codecs = devm_kcalloc(dev, num_codecs, sizeof(*codecs), GFP_KERNEL);
203                 if (!codecs)                      203                 if (!codecs)
204                         return -ENOMEM;           204                         return -ENOMEM;
205                                                   205 
206                 codec_maps = devm_kcalloc(dev,    206                 codec_maps = devm_kcalloc(dev, num_codecs, sizeof(*codec_maps), GFP_KERNEL);
207                 if (!codec_maps)                  207                 if (!codec_maps)
208                         return -ENOMEM;           208                         return -ENOMEM;
209                                                   209 
210                 list_for_each_entry(sof_end, &    210                 list_for_each_entry(sof_end, &sof_dai->endpoints, list) {
211                         if (!sof_end->dai_info    211                         if (!sof_end->dai_info->direction[stream])
212                                 continue;         212                                 continue;
213                                                   213 
214                         int link_num = ffs(sof    214                         int link_num = ffs(sof_end->link_mask) - 1;
215                                                   215 
216                         cpus[i].dai_name = dev    216                         cpus[i].dai_name = devm_kasprintf(dev, GFP_KERNEL,
217                                                   217                                                           "SDW%d Pin%d",
218                                                   218                                                           link_num, cpu_pin_id);
219                         dev_dbg(dev, "cpu[%d].    219                         dev_dbg(dev, "cpu[%d].dai_name:%s\n", i, cpus[i].dai_name);
220                         if (!cpus[i].dai_name)    220                         if (!cpus[i].dai_name)
221                                 return -ENOMEM    221                                 return -ENOMEM;
222                                                   222 
223                         codec_maps[j].cpu = i;    223                         codec_maps[j].cpu = i;
224                         codec_maps[j].codec =     224                         codec_maps[j].codec = j;
225                                                   225 
226                         codecs[j].name = sof_e    226                         codecs[j].name = sof_end->codec_name;
227                         codecs[j].dai_name = s    227                         codecs[j].dai_name = sof_end->dai_info->dai_name;
228                         j++;                      228                         j++;
229                 }                                 229                 }
230                                                   230 
231                 WARN_ON(j != num_codecs);         231                 WARN_ON(j != num_codecs);
232                                                   232 
233                 playback = (stream == SNDRV_PC    233                 playback = (stream == SNDRV_PCM_STREAM_PLAYBACK);
234                 capture = (stream == SNDRV_PCM    234                 capture = (stream == SNDRV_PCM_STREAM_CAPTURE);
235                                                   235 
236                 asoc_sdw_init_dai_link(dev, *d    236                 asoc_sdw_init_dai_link(dev, *dai_links, be_id, name, playback, capture,
237                                        cpus, n    237                                        cpus, num_cpus, platform_component,
238                                        ARRAY_S    238                                        ARRAY_SIZE(platform_component), codecs, num_codecs,
239                                        asoc_sd    239                                        asoc_sdw_rtd_init, &sdw_ops);
240                                                   240 
241                 /*                                241                 /*
242                  * SoundWire DAILINKs use 'str    242                  * SoundWire DAILINKs use 'stream' functions and Bank Switch operations
243                  * based on wait_for_completio    243                  * based on wait_for_completion(), tag them as 'nonatomic'.
244                  */                               244                  */
245                 (*dai_links)->nonatomic = true    245                 (*dai_links)->nonatomic = true;
246                 (*dai_links)->ch_maps = codec_    246                 (*dai_links)->ch_maps = codec_maps;
247                                                   247 
248                 list_for_each_entry(sof_end, &    248                 list_for_each_entry(sof_end, &sof_dai->endpoints, list) {
249                         if (sof_end->dai_info-    249                         if (sof_end->dai_info->init)
250                                 sof_end->dai_i    250                                 sof_end->dai_info->init(card, *dai_links,
251                                                   251                                                         sof_end->codec_info,
252                                                   252                                                         playback);
253                 }                                 253                 }
254                                                   254 
255                 (*dai_links)++;                   255                 (*dai_links)++;
256         }                                         256         }
257                                                   257 
258         return 0;                                 258         return 0;
259 }                                                 259 }
260                                                   260 
261 static int create_sdw_dailinks(struct snd_soc_    261 static int create_sdw_dailinks(struct snd_soc_card *card,
262                                struct snd_soc_    262                                struct snd_soc_dai_link **dai_links, int *be_id,
263                                struct asoc_sdw    263                                struct asoc_sdw_dailink *sof_dais,
264                                struct snd_soc_    264                                struct snd_soc_codec_conf **codec_conf)
265 {                                                 265 {
266         int ret;                                  266         int ret;
267                                                   267 
268         /* generate DAI links by each sdw link    268         /* generate DAI links by each sdw link */
269         while (sof_dais->initialised) {           269         while (sof_dais->initialised) {
270                 int current_be_id;                270                 int current_be_id;
271                                                   271 
272                 ret = create_sdw_dailink(card,    272                 ret = create_sdw_dailink(card, sof_dais, dai_links,
273                                          &curr    273                                          &current_be_id, codec_conf);
274                 if (ret)                          274                 if (ret)
275                         return ret;               275                         return ret;
276                                                   276 
277                 /* Update the be_id to match t    277                 /* Update the be_id to match the highest ID used for SDW link */
278                 if (*be_id < current_be_id)       278                 if (*be_id < current_be_id)
279                         *be_id = current_be_id    279                         *be_id = current_be_id;
280                                                   280 
281                 sof_dais++;                       281                 sof_dais++;
282         }                                         282         }
283                                                   283 
284         return 0;                                 284         return 0;
285 }                                                 285 }
286                                                   286 
287 static int create_dmic_dailinks(struct snd_soc    287 static int create_dmic_dailinks(struct snd_soc_card *card,
288                                 struct snd_soc    288                                 struct snd_soc_dai_link **dai_links, int *be_id)
289 {                                                 289 {
290         struct device *dev = card->dev;           290         struct device *dev = card->dev;
291         int ret;                                  291         int ret;
292                                                   292 
293         ret = asoc_sdw_init_simple_dai_link(de    293         ret = asoc_sdw_init_simple_dai_link(dev, *dai_links, be_id, "acp-dmic-codec",
294                                             0,    294                                             0, 1, // DMIC only supports capture
295                                             "a    295                                             "acp-sof-dmic", platform_component->name,
296                                             AR    296                                             ARRAY_SIZE(platform_component),
297                                             "d    297                                             "dmic-codec", "dmic-hifi",
298                                             as    298                                             asoc_sdw_dmic_init, NULL);
299         if (ret)                                  299         if (ret)
300                 return ret;                       300                 return ret;
301                                                   301 
302         (*dai_links)++;                           302         (*dai_links)++;
303                                                   303 
304         return 0;                                 304         return 0;
305 }                                                 305 }
306                                                   306 
307 static int sof_card_dai_links_create(struct sn    307 static int sof_card_dai_links_create(struct snd_soc_card *card)
308 {                                                 308 {
309         struct device *dev = card->dev;           309         struct device *dev = card->dev;
310         struct snd_soc_acpi_mach *mach = dev_g    310         struct snd_soc_acpi_mach *mach = dev_get_platdata(card->dev);
311         int sdw_be_num = 0, dmic_num = 0;         311         int sdw_be_num = 0, dmic_num = 0;
312         struct asoc_sdw_mc_private *ctx = snd_    312         struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card);
313         struct snd_soc_acpi_mach_params *mach_    313         struct snd_soc_acpi_mach_params *mach_params = &mach->mach_params;
314         struct snd_soc_codec_conf *codec_conf;    314         struct snd_soc_codec_conf *codec_conf;
315         struct asoc_sdw_endpoint *sof_ends;       315         struct asoc_sdw_endpoint *sof_ends;
316         struct asoc_sdw_dailink *sof_dais;        316         struct asoc_sdw_dailink *sof_dais;
317         struct snd_soc_dai_link *dai_links;       317         struct snd_soc_dai_link *dai_links;
318         int num_devs = 0;                         318         int num_devs = 0;
319         int num_ends = 0;                         319         int num_ends = 0;
320         int num_links;                            320         int num_links;
321         int be_id = 0;                            321         int be_id = 0;
322         int ret;                                  322         int ret;
323                                                   323 
324         ret = asoc_sdw_count_sdw_endpoints(car    324         ret = asoc_sdw_count_sdw_endpoints(card, &num_devs, &num_ends);
325         if (ret < 0) {                            325         if (ret < 0) {
326                 dev_err(dev, "failed to count     326                 dev_err(dev, "failed to count devices/endpoints: %d\n", ret);
327                 return ret;                       327                 return ret;
328         }                                         328         }
329                                                   329 
330         /* One per DAI link, worst case is a D    330         /* One per DAI link, worst case is a DAI link for every endpoint */
331         sof_dais = kcalloc(num_ends, sizeof(*s    331         sof_dais = kcalloc(num_ends, sizeof(*sof_dais), GFP_KERNEL);
332         if (!sof_dais)                            332         if (!sof_dais)
333                 return -ENOMEM;                   333                 return -ENOMEM;
334                                                   334 
335         /* One per endpoint, ie. each DAI on e    335         /* One per endpoint, ie. each DAI on each codec/amp */
336         sof_ends = kcalloc(num_ends, sizeof(*s    336         sof_ends = kcalloc(num_ends, sizeof(*sof_ends), GFP_KERNEL);
337         if (!sof_ends) {                          337         if (!sof_ends) {
338                 ret = -ENOMEM;                    338                 ret = -ENOMEM;
339                 goto err_dai;                     339                 goto err_dai;
340         }                                         340         }
341                                                   341 
342         ret = asoc_sdw_parse_sdw_endpoints(car    342         ret = asoc_sdw_parse_sdw_endpoints(card, sof_dais, sof_ends, &num_devs);
343         if (ret < 0)                              343         if (ret < 0)
344                 goto err_end;                     344                 goto err_end;
345                                                   345 
346         sdw_be_num = ret;                         346         sdw_be_num = ret;
347                                                   347 
348         /* enable dmic */                         348         /* enable dmic */
349         if (sof_sdw_quirk & ASOC_SDW_ACP_DMIC     349         if (sof_sdw_quirk & ASOC_SDW_ACP_DMIC || mach_params->dmic_num)
350                 dmic_num = 1;                     350                 dmic_num = 1;
351                                                   351 
352         dev_dbg(dev, "sdw %d, dmic %d", sdw_be    352         dev_dbg(dev, "sdw %d, dmic %d", sdw_be_num, dmic_num);
353                                                   353 
354         codec_conf = devm_kcalloc(dev, num_dev    354         codec_conf = devm_kcalloc(dev, num_devs, sizeof(*codec_conf), GFP_KERNEL);
355         if (!codec_conf) {                        355         if (!codec_conf) {
356                 ret = -ENOMEM;                    356                 ret = -ENOMEM;
357                 goto err_end;                     357                 goto err_end;
358         }                                         358         }
359                                                   359 
360         /* allocate BE dailinks */                360         /* allocate BE dailinks */
361         num_links = sdw_be_num + dmic_num;        361         num_links = sdw_be_num + dmic_num;
362         dai_links = devm_kcalloc(dev, num_link    362         dai_links = devm_kcalloc(dev, num_links, sizeof(*dai_links), GFP_KERNEL);
363         if (!dai_links) {                         363         if (!dai_links) {
364                 ret = -ENOMEM;                    364                 ret = -ENOMEM;
365         goto err_end;                             365         goto err_end;
366         }                                         366         }
367                                                   367 
368         card->codec_conf = codec_conf;            368         card->codec_conf = codec_conf;
369         card->num_configs = num_devs;             369         card->num_configs = num_devs;
370         card->dai_link = dai_links;               370         card->dai_link = dai_links;
371         card->num_links = num_links;              371         card->num_links = num_links;
372                                                   372 
373         /* SDW */                                 373         /* SDW */
374         if (sdw_be_num) {                         374         if (sdw_be_num) {
375                 ret = create_sdw_dailinks(card    375                 ret = create_sdw_dailinks(card, &dai_links, &be_id,
376                                           sof_    376                                           sof_dais, &codec_conf);
377                 if (ret)                          377                 if (ret)
378                         goto err_end;             378                         goto err_end;
379         }                                         379         }
380                                                   380 
381         /* dmic */                                381         /* dmic */
382         if (dmic_num > 0) {                       382         if (dmic_num > 0) {
383                 if (ctx->ignore_internal_dmic)    383                 if (ctx->ignore_internal_dmic) {
384                         dev_warn(dev, "Ignorin    384                         dev_warn(dev, "Ignoring ACP DMIC\n");
385                 } else {                          385                 } else {
386                         ret = create_dmic_dail    386                         ret = create_dmic_dailinks(card, &dai_links, &be_id);
387                         if (ret)                  387                         if (ret)
388                                 goto err_end;     388                                 goto err_end;
389                 }                                 389                 }
390         }                                         390         }
391                                                   391 
392         WARN_ON(codec_conf != card->codec_conf    392         WARN_ON(codec_conf != card->codec_conf + card->num_configs);
393         WARN_ON(dai_links != card->dai_link +     393         WARN_ON(dai_links != card->dai_link + card->num_links);
394                                                   394 
395 err_end:                                          395 err_end:
396         kfree(sof_ends);                          396         kfree(sof_ends);
397 err_dai:                                          397 err_dai:
398         kfree(sof_dais);                          398         kfree(sof_dais);
399                                                   399 
400         return ret;                               400         return ret;
401 }                                                 401 }
402                                                   402 
403 static int mc_probe(struct platform_device *pd    403 static int mc_probe(struct platform_device *pdev)
404 {                                                 404 {
405         struct snd_soc_acpi_mach *mach = dev_g    405         struct snd_soc_acpi_mach *mach = dev_get_platdata(&pdev->dev);
406         struct snd_soc_card *card;                406         struct snd_soc_card *card;
407         struct amd_mc_ctx *amd_ctx;               407         struct amd_mc_ctx *amd_ctx;
408         struct asoc_sdw_mc_private *ctx;          408         struct asoc_sdw_mc_private *ctx;
409         int amp_num = 0, i;                       409         int amp_num = 0, i;
410         int ret;                                  410         int ret;
411                                                   411 
412         amd_ctx = devm_kzalloc(&pdev->dev, siz    412         amd_ctx = devm_kzalloc(&pdev->dev, sizeof(*amd_ctx), GFP_KERNEL);
413         if (!amd_ctx)                             413         if (!amd_ctx)
414                 return -ENOMEM;                   414                 return -ENOMEM;
415                                                   415 
416         amd_ctx->acp_rev = mach->mach_params.s    416         amd_ctx->acp_rev = mach->mach_params.subsystem_rev;
417         amd_ctx->max_sdw_links = ACP63_SDW_MAX    417         amd_ctx->max_sdw_links = ACP63_SDW_MAX_LINKS;
418         ctx = devm_kzalloc(&pdev->dev, sizeof(    418         ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
419         if (!ctx)                                 419         if (!ctx)
420                 return -ENOMEM;                   420                 return -ENOMEM;
421         ctx->codec_info_list_count = asoc_sdw_    421         ctx->codec_info_list_count = asoc_sdw_get_codec_info_list_count();
422         ctx->private = amd_ctx;                   422         ctx->private = amd_ctx;
423         card = &ctx->card;                        423         card = &ctx->card;
424         card->dev = &pdev->dev;                   424         card->dev = &pdev->dev;
425         card->name = "amd-soundwire";             425         card->name = "amd-soundwire";
426         card->owner = THIS_MODULE;                426         card->owner = THIS_MODULE;
427         card->late_probe = asoc_sdw_card_late_    427         card->late_probe = asoc_sdw_card_late_probe;
428                                                   428 
429         snd_soc_card_set_drvdata(card, ctx);      429         snd_soc_card_set_drvdata(card, ctx);
430                                                   430 
431         dmi_check_system(sof_sdw_quirk_table);    431         dmi_check_system(sof_sdw_quirk_table);
432                                                   432 
433         if (quirk_override != -1) {               433         if (quirk_override != -1) {
434                 dev_info(card->dev, "Overridin    434                 dev_info(card->dev, "Overriding quirk 0x%lx => 0x%x\n",
435                          sof_sdw_quirk, quirk_    435                          sof_sdw_quirk, quirk_override);
436                 sof_sdw_quirk = quirk_override    436                 sof_sdw_quirk = quirk_override;
437         }                                         437         }
438                                                   438 
439         log_quirks(card->dev);                    439         log_quirks(card->dev);
440                                                   440 
441         ctx->mc_quirk = sof_sdw_quirk;            441         ctx->mc_quirk = sof_sdw_quirk;
442         /* reset amp_num to ensure amp_num++ s    442         /* reset amp_num to ensure amp_num++ starts from 0 in each probe */
443         for (i = 0; i < ctx->codec_info_list_c    443         for (i = 0; i < ctx->codec_info_list_count; i++)
444                 codec_info_list[i].amp_num = 0    444                 codec_info_list[i].amp_num = 0;
445                                                   445 
446         ret = sof_card_dai_links_create(card);    446         ret = sof_card_dai_links_create(card);
447         if (ret < 0)                              447         if (ret < 0)
448                 return ret;                       448                 return ret;
449                                                   449 
450         /*                                        450         /*
451          * the default amp_num is zero for eac    451          * the default amp_num is zero for each codec and
452          * amp_num will only be increased for     452          * amp_num will only be increased for active amp
453          * codecs on used platform                453          * codecs on used platform
454          */                                       454          */
455         for (i = 0; i < ctx->codec_info_list_c    455         for (i = 0; i < ctx->codec_info_list_count; i++)
456                 amp_num += codec_info_list[i].    456                 amp_num += codec_info_list[i].amp_num;
457                                                   457 
458         card->components = devm_kasprintf(card    458         card->components = devm_kasprintf(card->dev, GFP_KERNEL,
459                                           " cf    459                                           " cfg-amp:%d", amp_num);
460         if (!card->components)                    460         if (!card->components)
461                 return -ENOMEM;                   461                 return -ENOMEM;
462                                                   462 
463         /* Register the card */                   463         /* Register the card */
464         ret = devm_snd_soc_register_card(card-    464         ret = devm_snd_soc_register_card(card->dev, card);
465         if (ret) {                                465         if (ret) {
466                 dev_err_probe(card->dev, ret,     466                 dev_err_probe(card->dev, ret, "snd_soc_register_card failed %d\n", ret);
467                 asoc_sdw_mc_dailink_exit_loop(    467                 asoc_sdw_mc_dailink_exit_loop(card);
468                 return ret;                       468                 return ret;
469         }                                         469         }
470                                                   470 
471         platform_set_drvdata(pdev, card);         471         platform_set_drvdata(pdev, card);
472                                                   472 
473         return ret;                               473         return ret;
474 }                                                 474 }
475                                                   475 
476 static void mc_remove(struct platform_device *    476 static void mc_remove(struct platform_device *pdev)
477 {                                                 477 {
478         struct snd_soc_card *card = platform_g    478         struct snd_soc_card *card = platform_get_drvdata(pdev);
479                                                   479 
480         asoc_sdw_mc_dailink_exit_loop(card);      480         asoc_sdw_mc_dailink_exit_loop(card);
481 }                                                 481 }
482                                                   482 
483 static const struct platform_device_id mc_id_t    483 static const struct platform_device_id mc_id_table[] = {
484         { "amd_sof_sdw", },                       484         { "amd_sof_sdw", },
485         {}                                        485         {}
486 };                                                486 };
487 MODULE_DEVICE_TABLE(platform, mc_id_table);       487 MODULE_DEVICE_TABLE(platform, mc_id_table);
488                                                   488 
489 static struct platform_driver sof_sdw_driver =    489 static struct platform_driver sof_sdw_driver = {
490         .driver = {                               490         .driver = {
491                 .name = "amd_sof_sdw",            491                 .name = "amd_sof_sdw",
492                 .pm = &snd_soc_pm_ops,            492                 .pm = &snd_soc_pm_ops,
493         },                                        493         },
494         .probe = mc_probe,                        494         .probe = mc_probe,
495         .remove = mc_remove,                      495         .remove = mc_remove,
496         .id_table = mc_id_table,                  496         .id_table = mc_id_table,
497 };                                                497 };
498                                                   498 
499 module_platform_driver(sof_sdw_driver);           499 module_platform_driver(sof_sdw_driver);
500                                                   500 
501 MODULE_DESCRIPTION("ASoC AMD SoundWire Generic    501 MODULE_DESCRIPTION("ASoC AMD SoundWire Generic Machine driver");
502 MODULE_AUTHOR("Vijendar Mukunda <Vijendar.Muku    502 MODULE_AUTHOR("Vijendar Mukunda <Vijendar.Mukunda@amd.com");
503 MODULE_LICENSE("GPL");                            503 MODULE_LICENSE("GPL");
504 MODULE_IMPORT_NS(SND_SOC_SDW_UTILS);              504 MODULE_IMPORT_NS(SND_SOC_SDW_UTILS);
505                                                   505 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php