Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Add generic AMD Soundwire machine driver for Legacy(No

Merge series from Vijendar Mukunda <Vijendar.Mukunda@amd.com>:

This patch series add SoundWire machines for RT711, RT714, RT1316 and
RT722 codecs for ACP 6.3 platform. Also, it adds a generic SoundWire
machine driver code for legacy(No DSP) stack.

+646 -48
+29
sound/soc/amd/acp/Kconfig
··· 119 119 help 120 120 This option enables SOF sound card support for ACP audio. 121 121 122 + config SND_SOC_AMD_SDW_MACH_COMMON 123 + tristate 124 + help 125 + This option enables common SoundWire Machine driver module for 126 + AMD platforms. 127 + 122 128 config SND_SOC_AMD_SOF_SDW_MACH 123 129 tristate "AMD SOF Soundwire Machine Driver Support" 124 130 depends on X86 && PCI && ACPI 125 131 depends on SOUNDWIRE 132 + select SND_SOC_AMD_SDW_MACH_COMMON 126 133 select SND_SOC_SDW_UTILS 127 134 select SND_SOC_DMIC 128 135 select SND_SOC_RT711_SDW ··· 140 133 help 141 134 This option enables SOF sound card support for SoundWire enabled 142 135 AMD platforms along with ACP PDM controller. 136 + Say Y if you want to enable SoundWire based machine driver support 137 + on AMD platform. 138 + If unsure select "N". 139 + 140 + config SND_SOC_AMD_LEGACY_SDW_MACH 141 + tristate "AMD Legacy(No DSP) Soundwire Machine Driver Support" 142 + depends on X86 && PCI && ACPI 143 + depends on SOUNDWIRE 144 + select SND_SOC_AMD_SDW_MACH_COMMON 145 + select SND_SOC_SDW_UTILS 146 + select SND_SOC_DMIC 147 + select SND_SOC_RT711_SDW 148 + select SND_SOC_RT711_SDCA_SDW 149 + select SND_SOC_RT712_SDCA_SDW 150 + select SND_SOC_RT712_SDCA_DMIC_SDW 151 + select SND_SOC_RT1316_SDW 152 + select SND_SOC_RT715_SDW 153 + select SND_SOC_RT715_SDCA_SDW 154 + select SND_SOC_RT722_SDCA_SDW 155 + help 156 + This option enables Legacy(No DSP) sound card support for SoundWire 157 + enabled AMD platforms along with ACP PDM controller. 143 158 Say Y if you want to enable SoundWire based machine driver support 144 159 on AMD platform. 145 160 If unsure select "N".
+4
sound/soc/amd/acp/Makefile
··· 23 23 snd-acp-legacy-mach-y := acp-legacy-mach.o acp3x-es83xx/acp3x-es83xx.o 24 24 snd-acp-sof-mach-y := acp-sof-mach.o 25 25 snd-soc-acpi-amd-match-y := amd-acp63-acpi-match.o 26 + snd-acp-sdw-mach-y := acp-sdw-mach-common.o 26 27 snd-acp-sdw-sof-mach-y += acp-sdw-sof-mach.o 28 + snd-acp-sdw-legacy-mach-y += acp-sdw-legacy-mach.o 27 29 28 30 obj-$(CONFIG_SND_SOC_AMD_ACP_PCM) += snd-acp-pcm.o 29 31 obj-$(CONFIG_SND_SOC_AMD_ACP_I2S) += snd-acp-i2s.o ··· 43 41 obj-$(CONFIG_SND_SOC_AMD_LEGACY_MACH) += snd-acp-legacy-mach.o 44 42 obj-$(CONFIG_SND_SOC_AMD_SOF_MACH) += snd-acp-sof-mach.o 45 43 obj-$(CONFIG_SND_SOC_ACPI_AMD_MATCH) += snd-soc-acpi-amd-match.o 44 + obj-$(CONFIG_SND_SOC_AMD_SDW_MACH_COMMON) += snd-acp-sdw-mach.o 46 45 obj-$(CONFIG_SND_SOC_AMD_SOF_SDW_MACH) += snd-acp-sdw-sof-mach.o 46 + obj-$(CONFIG_SND_SOC_AMD_LEGACY_SDW_MACH) += snd-acp-sdw-legacy-mach.o
+486
sound/soc/amd/acp/acp-sdw-legacy-mach.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + // Copyright(c) 2024 Advanced Micro Devices, Inc. 3 + 4 + /* 5 + * acp-sdw-legacy-mach - ASoC legacy Machine driver for AMD SoundWire platforms 6 + */ 7 + 8 + #include <linux/bitmap.h> 9 + #include <linux/device.h> 10 + #include <linux/dmi.h> 11 + #include <linux/module.h> 12 + #include <linux/soundwire/sdw.h> 13 + #include <linux/soundwire/sdw_type.h> 14 + #include <sound/soc.h> 15 + #include <sound/soc-acpi.h> 16 + #include "soc_amd_sdw_common.h" 17 + #include "../../codecs/rt711.h" 18 + 19 + static unsigned long soc_sdw_quirk = RT711_JD1; 20 + static int quirk_override = -1; 21 + module_param_named(quirk, quirk_override, int, 0444); 22 + MODULE_PARM_DESC(quirk, "Board-specific quirk override"); 23 + 24 + static void log_quirks(struct device *dev) 25 + { 26 + if (SOC_JACK_JDSRC(soc_sdw_quirk)) 27 + dev_dbg(dev, "quirk realtek,jack-detect-source %ld\n", 28 + SOC_JACK_JDSRC(soc_sdw_quirk)); 29 + if (soc_sdw_quirk & ASOC_SDW_ACP_DMIC) 30 + dev_dbg(dev, "quirk SOC_SDW_ACP_DMIC enabled\n"); 31 + } 32 + 33 + static int soc_sdw_quirk_cb(const struct dmi_system_id *id) 34 + { 35 + soc_sdw_quirk = (unsigned long)id->driver_data; 36 + return 1; 37 + } 38 + 39 + static const struct dmi_system_id soc_sdw_quirk_table[] = { 40 + { 41 + .callback = soc_sdw_quirk_cb, 42 + .matches = { 43 + DMI_MATCH(DMI_SYS_VENDOR, "AMD"), 44 + DMI_MATCH(DMI_PRODUCT_NAME, "Birman-PHX"), 45 + }, 46 + .driver_data = (void *)RT711_JD2, 47 + }, 48 + {} 49 + }; 50 + 51 + static const struct snd_soc_ops sdw_ops = { 52 + .startup = asoc_sdw_startup, 53 + .prepare = asoc_sdw_prepare, 54 + .trigger = asoc_sdw_trigger, 55 + .hw_params = asoc_sdw_hw_params, 56 + .hw_free = asoc_sdw_hw_free, 57 + .shutdown = asoc_sdw_shutdown, 58 + }; 59 + 60 + static const char * const type_strings[] = {"SimpleJack", "SmartAmp", "SmartMic"}; 61 + 62 + static int create_sdw_dailink(struct snd_soc_card *card, 63 + struct asoc_sdw_dailink *soc_dai, 64 + struct snd_soc_dai_link **dai_links, 65 + int *be_id, struct snd_soc_codec_conf **codec_conf, 66 + struct snd_soc_dai_link_component *sdw_platform_component) 67 + { 68 + struct device *dev = card->dev; 69 + struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card); 70 + struct amd_mc_ctx *amd_ctx = (struct amd_mc_ctx *)ctx->private; 71 + struct asoc_sdw_endpoint *soc_end; 72 + int cpu_pin_id; 73 + int stream; 74 + int ret; 75 + 76 + list_for_each_entry(soc_end, &soc_dai->endpoints, list) { 77 + if (soc_end->name_prefix) { 78 + (*codec_conf)->dlc.name = soc_end->codec_name; 79 + (*codec_conf)->name_prefix = soc_end->name_prefix; 80 + (*codec_conf)++; 81 + } 82 + 83 + if (soc_end->include_sidecar) { 84 + ret = soc_end->codec_info->add_sidecar(card, dai_links, codec_conf); 85 + if (ret) 86 + return ret; 87 + } 88 + } 89 + 90 + for_each_pcm_streams(stream) { 91 + static const char * const sdw_stream_name[] = { 92 + "SDW%d-PIN%d-PLAYBACK", 93 + "SDW%d-PIN%d-CAPTURE", 94 + "SDW%d-PIN%d-PLAYBACK-%s", 95 + "SDW%d-PIN%d-CAPTURE-%s", 96 + }; 97 + struct snd_soc_dai_link_ch_map *codec_maps; 98 + struct snd_soc_dai_link_component *codecs; 99 + struct snd_soc_dai_link_component *cpus; 100 + int num_cpus = hweight32(soc_dai->link_mask[stream]); 101 + int num_codecs = soc_dai->num_devs[stream]; 102 + int playback, capture; 103 + int j = 0; 104 + char *name; 105 + 106 + if (!soc_dai->num_devs[stream]) 107 + continue; 108 + 109 + soc_end = list_first_entry(&soc_dai->endpoints, 110 + struct asoc_sdw_endpoint, list); 111 + 112 + *be_id = soc_end->dai_info->dailink[stream]; 113 + if (*be_id < 0) { 114 + dev_err(dev, "Invalid dailink id %d\n", *be_id); 115 + return -EINVAL; 116 + } 117 + 118 + switch (amd_ctx->acp_rev) { 119 + case ACP63_PCI_REV: 120 + ret = get_acp63_cpu_pin_id(ffs(soc_end->link_mask - 1), 121 + *be_id, &cpu_pin_id, dev); 122 + if (ret) 123 + return ret; 124 + break; 125 + default: 126 + return -EINVAL; 127 + } 128 + /* create stream name according to first link id */ 129 + if (ctx->append_dai_type) { 130 + name = devm_kasprintf(dev, GFP_KERNEL, 131 + sdw_stream_name[stream + 2], 132 + ffs(soc_end->link_mask) - 1, 133 + cpu_pin_id, 134 + type_strings[soc_end->dai_info->dai_type]); 135 + } else { 136 + name = devm_kasprintf(dev, GFP_KERNEL, 137 + sdw_stream_name[stream], 138 + ffs(soc_end->link_mask) - 1, 139 + cpu_pin_id); 140 + } 141 + if (!name) 142 + return -ENOMEM; 143 + 144 + cpus = devm_kcalloc(dev, num_cpus, sizeof(*cpus), GFP_KERNEL); 145 + if (!cpus) 146 + return -ENOMEM; 147 + 148 + codecs = devm_kcalloc(dev, num_codecs, sizeof(*codecs), GFP_KERNEL); 149 + if (!codecs) 150 + return -ENOMEM; 151 + 152 + codec_maps = devm_kcalloc(dev, num_codecs, sizeof(*codec_maps), GFP_KERNEL); 153 + if (!codec_maps) 154 + return -ENOMEM; 155 + 156 + list_for_each_entry(soc_end, &soc_dai->endpoints, list) { 157 + if (!soc_end->dai_info->direction[stream]) 158 + continue; 159 + 160 + int link_num = ffs(soc_end->link_mask) - 1; 161 + 162 + cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, 163 + "SDW%d Pin%d", 164 + link_num, cpu_pin_id); 165 + dev_dbg(dev, "cpu->dai_name:%s\n", cpus->dai_name); 166 + if (!cpus->dai_name) 167 + return -ENOMEM; 168 + 169 + codec_maps[j].cpu = 0; 170 + codec_maps[j].codec = j; 171 + 172 + codecs[j].name = soc_end->codec_name; 173 + codecs[j].dai_name = soc_end->dai_info->dai_name; 174 + j++; 175 + } 176 + 177 + WARN_ON(j != num_codecs); 178 + 179 + playback = (stream == SNDRV_PCM_STREAM_PLAYBACK); 180 + capture = (stream == SNDRV_PCM_STREAM_CAPTURE); 181 + 182 + asoc_sdw_init_dai_link(dev, *dai_links, be_id, name, playback, capture, 183 + cpus, num_cpus, sdw_platform_component, 184 + 1, codecs, num_codecs, 185 + 0, asoc_sdw_rtd_init, &sdw_ops); 186 + /* 187 + * SoundWire DAILINKs use 'stream' functions and Bank Switch operations 188 + * based on wait_for_completion(), tag them as 'nonatomic'. 189 + */ 190 + (*dai_links)->nonatomic = true; 191 + (*dai_links)->ch_maps = codec_maps; 192 + 193 + list_for_each_entry(soc_end, &soc_dai->endpoints, list) { 194 + if (soc_end->dai_info->init) 195 + soc_end->dai_info->init(card, *dai_links, 196 + soc_end->codec_info, 197 + playback); 198 + } 199 + 200 + (*dai_links)++; 201 + } 202 + 203 + return 0; 204 + } 205 + 206 + static int create_sdw_dailinks(struct snd_soc_card *card, 207 + struct snd_soc_dai_link **dai_links, int *be_id, 208 + struct asoc_sdw_dailink *soc_dais, 209 + struct snd_soc_codec_conf **codec_conf) 210 + { 211 + struct device *dev = card->dev; 212 + struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card); 213 + struct amd_mc_ctx *amd_ctx = (struct amd_mc_ctx *)ctx->private; 214 + struct snd_soc_dai_link_component *sdw_platform_component; 215 + int ret; 216 + 217 + sdw_platform_component = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link_component), 218 + GFP_KERNEL); 219 + if (!sdw_platform_component) 220 + return -ENOMEM; 221 + 222 + switch (amd_ctx->acp_rev) { 223 + case ACP63_PCI_REV: 224 + sdw_platform_component->name = "amd_ps_sdw_dma.0"; 225 + break; 226 + default: 227 + return -EINVAL; 228 + } 229 + 230 + /* generate DAI links by each sdw link */ 231 + while (soc_dais->initialised) { 232 + int current_be_id; 233 + 234 + ret = create_sdw_dailink(card, soc_dais, dai_links, 235 + &current_be_id, codec_conf, sdw_platform_component); 236 + if (ret) 237 + return ret; 238 + 239 + /* Update the be_id to match the highest ID used for SDW link */ 240 + if (*be_id < current_be_id) 241 + *be_id = current_be_id; 242 + 243 + soc_dais++; 244 + } 245 + 246 + return 0; 247 + } 248 + 249 + static int create_dmic_dailinks(struct snd_soc_card *card, 250 + struct snd_soc_dai_link **dai_links, int *be_id, int no_pcm) 251 + { 252 + struct device *dev = card->dev; 253 + struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card); 254 + struct amd_mc_ctx *amd_ctx = (struct amd_mc_ctx *)ctx->private; 255 + struct snd_soc_dai_link_component *pdm_cpu; 256 + struct snd_soc_dai_link_component *pdm_platform; 257 + int ret; 258 + 259 + pdm_cpu = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link_component), GFP_KERNEL); 260 + if (!pdm_cpu) 261 + return -ENOMEM; 262 + 263 + pdm_platform = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link_component), GFP_KERNEL); 264 + if (!pdm_platform) 265 + return -ENOMEM; 266 + 267 + switch (amd_ctx->acp_rev) { 268 + case ACP63_PCI_REV: 269 + pdm_cpu->name = "acp_ps_pdm_dma.0"; 270 + pdm_platform->name = "acp_ps_pdm_dma.0"; 271 + break; 272 + default: 273 + return -EINVAL; 274 + } 275 + 276 + *be_id = ACP_DMIC_BE_ID; 277 + ret = asoc_sdw_init_simple_dai_link(dev, *dai_links, be_id, "acp-dmic-codec", 278 + 0, 1, // DMIC only supports capture 279 + pdm_cpu->name, pdm_platform->name, 1, 280 + "dmic-codec.0", "dmic-hifi", no_pcm, 281 + asoc_sdw_dmic_init, NULL); 282 + if (ret) 283 + return ret; 284 + 285 + (*dai_links)++; 286 + 287 + return 0; 288 + } 289 + 290 + static int soc_card_dai_links_create(struct snd_soc_card *card) 291 + { 292 + struct device *dev = card->dev; 293 + struct snd_soc_acpi_mach *mach = dev_get_platdata(card->dev); 294 + int sdw_be_num = 0, dmic_num = 0; 295 + struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card); 296 + struct snd_soc_acpi_mach_params *mach_params = &mach->mach_params; 297 + struct asoc_sdw_endpoint *soc_ends __free(kfree) = NULL; 298 + struct asoc_sdw_dailink *soc_dais __free(kfree) = NULL; 299 + struct snd_soc_codec_conf *codec_conf; 300 + struct snd_soc_dai_link *dai_links; 301 + int num_devs = 0; 302 + int num_ends = 0; 303 + int num_links; 304 + int be_id = 0; 305 + int ret; 306 + 307 + ret = asoc_sdw_count_sdw_endpoints(card, &num_devs, &num_ends); 308 + if (ret < 0) { 309 + dev_err(dev, "failed to count devices/endpoints: %d\n", ret); 310 + return ret; 311 + } 312 + 313 + /* One per DAI link, worst case is a DAI link for every endpoint */ 314 + soc_dais = kcalloc(num_ends, sizeof(*soc_dais), GFP_KERNEL); 315 + if (!soc_dais) 316 + return -ENOMEM; 317 + 318 + /* One per endpoint, ie. each DAI on each codec/amp */ 319 + soc_ends = kcalloc(num_ends, sizeof(*soc_ends), GFP_KERNEL); 320 + if (!soc_ends) 321 + return -ENOMEM; 322 + 323 + ret = asoc_sdw_parse_sdw_endpoints(card, soc_dais, soc_ends, &num_devs); 324 + if (ret < 0) 325 + return ret; 326 + 327 + sdw_be_num = ret; 328 + 329 + /* enable dmic */ 330 + if (soc_sdw_quirk & ASOC_SDW_ACP_DMIC || mach_params->dmic_num) 331 + dmic_num = 1; 332 + 333 + dev_dbg(dev, "sdw %d, dmic %d", sdw_be_num, dmic_num); 334 + 335 + codec_conf = devm_kcalloc(dev, num_devs, sizeof(*codec_conf), GFP_KERNEL); 336 + if (!codec_conf) 337 + return -ENOMEM; 338 + 339 + /* allocate BE dailinks */ 340 + num_links = sdw_be_num + dmic_num; 341 + dai_links = devm_kcalloc(dev, num_links, sizeof(*dai_links), GFP_KERNEL); 342 + if (!dai_links) 343 + return -ENOMEM; 344 + 345 + card->codec_conf = codec_conf; 346 + card->num_configs = num_devs; 347 + card->dai_link = dai_links; 348 + card->num_links = num_links; 349 + 350 + /* SDW */ 351 + if (sdw_be_num) { 352 + ret = create_sdw_dailinks(card, &dai_links, &be_id, 353 + soc_dais, &codec_conf); 354 + if (ret) 355 + return ret; 356 + } 357 + 358 + /* dmic */ 359 + if (dmic_num > 0) { 360 + if (ctx->ignore_internal_dmic) { 361 + dev_warn(dev, "Ignoring ACP DMIC\n"); 362 + } else { 363 + ret = create_dmic_dailinks(card, &dai_links, &be_id, 0); 364 + if (ret) 365 + return ret; 366 + } 367 + } 368 + 369 + WARN_ON(codec_conf != card->codec_conf + card->num_configs); 370 + WARN_ON(dai_links != card->dai_link + card->num_links); 371 + 372 + return ret; 373 + } 374 + 375 + static int mc_probe(struct platform_device *pdev) 376 + { 377 + struct snd_soc_acpi_mach *mach = dev_get_platdata(&pdev->dev); 378 + struct snd_soc_card *card; 379 + struct amd_mc_ctx *amd_ctx; 380 + struct asoc_sdw_mc_private *ctx; 381 + int amp_num = 0, i; 382 + int ret; 383 + 384 + amd_ctx = devm_kzalloc(&pdev->dev, sizeof(*amd_ctx), GFP_KERNEL); 385 + if (!amd_ctx) 386 + return -ENOMEM; 387 + 388 + amd_ctx->acp_rev = mach->mach_params.subsystem_rev; 389 + amd_ctx->max_sdw_links = ACP63_SDW_MAX_LINKS; 390 + ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); 391 + if (!ctx) 392 + return -ENOMEM; 393 + ctx->codec_info_list_count = asoc_sdw_get_codec_info_list_count(); 394 + ctx->private = amd_ctx; 395 + card = &ctx->card; 396 + card->dev = &pdev->dev; 397 + card->name = "amd-soundwire"; 398 + card->owner = THIS_MODULE; 399 + card->late_probe = asoc_sdw_card_late_probe; 400 + 401 + snd_soc_card_set_drvdata(card, ctx); 402 + 403 + dmi_check_system(soc_sdw_quirk_table); 404 + 405 + if (quirk_override != -1) { 406 + dev_info(card->dev, "Overriding quirk 0x%lx => 0x%x\n", 407 + soc_sdw_quirk, quirk_override); 408 + soc_sdw_quirk = quirk_override; 409 + } 410 + 411 + log_quirks(card->dev); 412 + 413 + ctx->mc_quirk = soc_sdw_quirk; 414 + dev_dbg(card->dev, "legacy quirk 0x%lx\n", ctx->mc_quirk); 415 + /* reset amp_num to ensure amp_num++ starts from 0 in each probe */ 416 + for (i = 0; i < ctx->codec_info_list_count; i++) 417 + codec_info_list[i].amp_num = 0; 418 + 419 + ret = soc_card_dai_links_create(card); 420 + if (ret < 0) 421 + return ret; 422 + 423 + /* 424 + * the default amp_num is zero for each codec and 425 + * amp_num will only be increased for active amp 426 + * codecs on used platform 427 + */ 428 + for (i = 0; i < ctx->codec_info_list_count; i++) 429 + amp_num += codec_info_list[i].amp_num; 430 + 431 + card->components = devm_kasprintf(card->dev, GFP_KERNEL, 432 + " cfg-amp:%d", amp_num); 433 + if (!card->components) 434 + return -ENOMEM; 435 + if (mach->mach_params.dmic_num) { 436 + card->components = devm_kasprintf(card->dev, GFP_KERNEL, 437 + "%s mic:dmic cfg-mics:%d", 438 + card->components, 439 + mach->mach_params.dmic_num); 440 + if (!card->components) 441 + return -ENOMEM; 442 + } 443 + 444 + /* Register the card */ 445 + ret = devm_snd_soc_register_card(card->dev, card); 446 + if (ret) { 447 + dev_err_probe(card->dev, ret, "snd_soc_register_card failed %d\n", ret); 448 + asoc_sdw_mc_dailink_exit_loop(card); 449 + return ret; 450 + } 451 + 452 + platform_set_drvdata(pdev, card); 453 + 454 + return ret; 455 + } 456 + 457 + static void mc_remove(struct platform_device *pdev) 458 + { 459 + struct snd_soc_card *card = platform_get_drvdata(pdev); 460 + 461 + asoc_sdw_mc_dailink_exit_loop(card); 462 + } 463 + 464 + static const struct platform_device_id mc_id_table[] = { 465 + { "amd_sdw", }, 466 + {} 467 + }; 468 + MODULE_DEVICE_TABLE(platform, mc_id_table); 469 + 470 + static struct platform_driver soc_sdw_driver = { 471 + .driver = { 472 + .name = "amd_sdw", 473 + .pm = &snd_soc_pm_ops, 474 + }, 475 + .probe = mc_probe, 476 + .remove = mc_remove, 477 + .id_table = mc_id_table, 478 + }; 479 + 480 + module_platform_driver(soc_sdw_driver); 481 + 482 + MODULE_DESCRIPTION("ASoC AMD SoundWire Legacy Generic Machine driver"); 483 + MODULE_AUTHOR("Vijendar Mukunda <Vijendar.Mukunda@amd.com>"); 484 + MODULE_LICENSE("GPL"); 485 + MODULE_IMPORT_NS(SND_SOC_SDW_UTILS); 486 + MODULE_IMPORT_NS(SND_SOC_AMD_SDW_MACH);
+64
sound/soc/amd/acp/acp-sdw-mach-common.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + // Copyright(c) 2024 Advanced Micro Devices, Inc. 3 + 4 + /* 5 + * acp-sdw-mach-common - Common machine driver helper functions for 6 + * legacy(No DSP) stack and SOF stack. 7 + */ 8 + 9 + #include <linux/device.h> 10 + #include <linux/module.h> 11 + #include "soc_amd_sdw_common.h" 12 + 13 + int get_acp63_cpu_pin_id(u32 sdw_link_id, int be_id, int *cpu_pin_id, struct device *dev) 14 + { 15 + switch (sdw_link_id) { 16 + case AMD_SDW0: 17 + switch (be_id) { 18 + case SOC_SDW_JACK_OUT_DAI_ID: 19 + *cpu_pin_id = ACP63_SW0_AUDIO0_TX; 20 + break; 21 + case SOC_SDW_JACK_IN_DAI_ID: 22 + *cpu_pin_id = ACP63_SW0_AUDIO0_RX; 23 + break; 24 + case SOC_SDW_AMP_OUT_DAI_ID: 25 + *cpu_pin_id = ACP63_SW0_AUDIO1_TX; 26 + break; 27 + case SOC_SDW_AMP_IN_DAI_ID: 28 + *cpu_pin_id = ACP63_SW0_AUDIO1_RX; 29 + break; 30 + case SOC_SDW_DMIC_DAI_ID: 31 + *cpu_pin_id = ACP63_SW0_AUDIO2_RX; 32 + break; 33 + default: 34 + dev_err(dev, "Invalid be id:%d\n", be_id); 35 + return -EINVAL; 36 + } 37 + break; 38 + case AMD_SDW1: 39 + switch (be_id) { 40 + case SOC_SDW_JACK_OUT_DAI_ID: 41 + case SOC_SDW_AMP_OUT_DAI_ID: 42 + *cpu_pin_id = ACP63_SW1_AUDIO0_TX; 43 + break; 44 + case SOC_SDW_JACK_IN_DAI_ID: 45 + case SOC_SDW_AMP_IN_DAI_ID: 46 + case SOC_SDW_DMIC_DAI_ID: 47 + *cpu_pin_id = ACP63_SW1_AUDIO0_RX; 48 + break; 49 + default: 50 + dev_err(dev, "invalid be_id:%d\n", be_id); 51 + return -EINVAL; 52 + } 53 + break; 54 + default: 55 + dev_err(dev, "Invalid link id:%d\n", sdw_link_id); 56 + return -EINVAL; 57 + } 58 + return 0; 59 + } 60 + EXPORT_SYMBOL_NS_GPL(get_acp63_cpu_pin_id, SND_SOC_AMD_SDW_MACH); 61 + 62 + MODULE_DESCRIPTION("AMD SoundWire Common Machine driver"); 63 + MODULE_AUTHOR("Vijendar Mukunda <Vijendar.Mukunda@amd.com>"); 64 + MODULE_LICENSE("GPL");
+1 -48
sound/soc/amd/acp/acp-sdw-sof-mach.c
··· 64 64 .shutdown = asoc_sdw_shutdown, 65 65 }; 66 66 67 - static int get_acp63_cpu_pin_id(u32 sdw_link_id, int be_id, int *cpu_pin_id, struct device *dev) 68 - { 69 - switch (sdw_link_id) { 70 - case AMD_SDW0: 71 - switch (be_id) { 72 - case SOC_SDW_JACK_OUT_DAI_ID: 73 - *cpu_pin_id = ACP63_SW0_AUDIO0_TX; 74 - break; 75 - case SOC_SDW_JACK_IN_DAI_ID: 76 - *cpu_pin_id = ACP63_SW0_AUDIO0_RX; 77 - break; 78 - case SOC_SDW_AMP_OUT_DAI_ID: 79 - *cpu_pin_id = ACP63_SW0_AUDIO1_TX; 80 - break; 81 - case SOC_SDW_AMP_IN_DAI_ID: 82 - *cpu_pin_id = ACP63_SW0_AUDIO1_RX; 83 - break; 84 - case SOC_SDW_DMIC_DAI_ID: 85 - *cpu_pin_id = ACP63_SW0_AUDIO2_RX; 86 - break; 87 - default: 88 - dev_err(dev, "Invalid be id:%d\n", be_id); 89 - return -EINVAL; 90 - } 91 - break; 92 - case AMD_SDW1: 93 - switch (be_id) { 94 - case SOC_SDW_JACK_OUT_DAI_ID: 95 - case SOC_SDW_AMP_OUT_DAI_ID: 96 - *cpu_pin_id = ACP63_SW1_AUDIO0_TX; 97 - break; 98 - case SOC_SDW_JACK_IN_DAI_ID: 99 - case SOC_SDW_AMP_IN_DAI_ID: 100 - case SOC_SDW_DMIC_DAI_ID: 101 - *cpu_pin_id = ACP63_SW1_AUDIO0_RX; 102 - break; 103 - default: 104 - dev_err(dev, "invalid be_id:%d\n", be_id); 105 - return -EINVAL; 106 - } 107 - break; 108 - default: 109 - dev_err(dev, "Invalid link id:%d\n", sdw_link_id); 110 - return -EINVAL; 111 - } 112 - return 0; 113 - } 114 - 115 67 static const char * const type_strings[] = {"SimpleJack", "SmartAmp", "SmartMic"}; 116 68 117 69 static int create_sdw_dailink(struct snd_soc_card *card, ··· 443 491 MODULE_AUTHOR("Vijendar Mukunda <Vijendar.Mukunda@amd.com"); 444 492 MODULE_LICENSE("GPL"); 445 493 MODULE_IMPORT_NS(SND_SOC_SDW_UTILS); 494 + MODULE_IMPORT_NS(SND_SOC_AMD_SDW_MACH);
+54
sound/soc/amd/acp/amd-acp63-acpi-match.c
··· 73 73 {} 74 74 }; 75 75 76 + static const struct snd_soc_acpi_endpoint rt722_endpoints[] = { 77 + { 78 + .num = 0, 79 + .aggregated = 0, 80 + .group_position = 0, 81 + .group_id = 0, 82 + }, 83 + { 84 + .num = 1, 85 + .aggregated = 0, 86 + .group_position = 0, 87 + .group_id = 0, 88 + }, 89 + { 90 + .num = 2, 91 + .aggregated = 0, 92 + .group_position = 0, 93 + .group_id = 0, 94 + }, 95 + }; 96 + 97 + static const struct snd_soc_acpi_adr_device rt722_0_single_adr[] = { 98 + { 99 + .adr = 0x000030025d072201ull, 100 + .num_endpoints = ARRAY_SIZE(rt722_endpoints), 101 + .endpoints = rt722_endpoints, 102 + .name_prefix = "rt722" 103 + } 104 + }; 105 + 106 + static const struct snd_soc_acpi_link_adr acp63_rt722_only[] = { 107 + { 108 + .mask = BIT(0), 109 + .num_adr = ARRAY_SIZE(rt722_0_single_adr), 110 + .adr_d = rt722_0_single_adr, 111 + }, 112 + {} 113 + }; 114 + 76 115 struct snd_soc_acpi_mach snd_soc_acpi_amd_acp63_sof_sdw_machines[] = { 77 116 { 78 117 .link_mask = BIT(0) | BIT(1), ··· 123 84 {}, 124 85 }; 125 86 EXPORT_SYMBOL(snd_soc_acpi_amd_acp63_sof_sdw_machines); 87 + 88 + struct snd_soc_acpi_mach snd_soc_acpi_amd_acp63_sdw_machines[] = { 89 + { 90 + .link_mask = BIT(0), 91 + .links = acp63_rt722_only, 92 + .drv_name = "amd_sdw", 93 + }, 94 + { 95 + .link_mask = BIT(0) | BIT(1), 96 + .links = acp63_4_in_1_sdca, 97 + .drv_name = "amd_sdw", 98 + }, 99 + {}, 100 + }; 101 + EXPORT_SYMBOL(snd_soc_acpi_amd_acp63_sdw_machines); 126 102 127 103 MODULE_DESCRIPTION("AMD ACP6.3 tables and support for ACPI enumeration"); 128 104 MODULE_LICENSE("GPL");
+4
sound/soc/amd/acp/soc_amd_sdw_common.h
··· 36 36 #define ACP63_SW1_AUDIO0_TX 0 37 37 #define ACP63_SW1_AUDIO0_RX 1 38 38 39 + #define ACP_DMIC_BE_ID 4 40 + 39 41 struct amd_mc_ctx { 40 42 unsigned int acp_rev; 41 43 unsigned int max_sdw_links; 42 44 }; 45 + 46 + int get_acp63_cpu_pin_id(u32 sdw_link_id, int be_id, int *cpu_pin_id, struct device *dev); 43 47 44 48 #endif
+1
sound/soc/amd/mach-config.h
··· 23 23 extern struct snd_soc_acpi_mach snd_soc_acpi_amd_rmb_sof_machines[]; 24 24 extern struct snd_soc_acpi_mach snd_soc_acpi_amd_vangogh_sof_machines[]; 25 25 extern struct snd_soc_acpi_mach snd_soc_acpi_amd_acp63_sof_machines[]; 26 + extern struct snd_soc_acpi_mach snd_soc_acpi_amd_acp63_sdw_machines[]; 26 27 extern struct snd_soc_acpi_mach snd_soc_acpi_amd_acp63_sof_sdw_machines[]; 27 28 extern struct snd_soc_acpi_mach snd_soc_acpi_amd_acp70_sof_machines[]; 28 29
+1
sound/soc/amd/ps/pci-ps.c
··· 598 598 dev_err(&pci->dev, "ACP platform devices creation failed\n"); 599 599 goto de_init; 600 600 } 601 + adata->machines = snd_soc_acpi_amd_acp63_sdw_machines; 601 602 ret = acp63_machine_register(&pci->dev); 602 603 if (ret) { 603 604 dev_err(&pci->dev, "ACP machine register failed\n");
+2
sound/soc/amd/ps/ps-sdw-dma.c
··· 445 445 .trigger = acp63_sdw_dma_trigger, 446 446 .pointer = acp63_sdw_dma_pointer, 447 447 .pcm_construct = acp63_sdw_dma_new, 448 + .use_dai_pcm_id = true, 449 + 448 450 }; 449 451 450 452 static int acp63_sdw_platform_probe(struct platform_device *pdev)