diff options
Diffstat (limited to 'sound/soc')
37 files changed, 2811 insertions, 262 deletions
diff --git a/sound/soc/codecs/rt5670.c b/sound/soc/codecs/rt5670.c index d95d2e693dc6..a5f15a104c47 100644 --- a/sound/soc/codecs/rt5670.c +++ b/sound/soc/codecs/rt5670.c | |||
| @@ -2848,6 +2848,10 @@ static const struct dmi_system_id dmi_platform_intel_braswell[] = { | |||
| 2848 | DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad Tablet B"), | 2848 | DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad Tablet B"), |
| 2849 | }, | 2849 | }, |
| 2850 | }, | 2850 | }, |
| 2851 | {} | ||
| 2852 | }; | ||
| 2853 | |||
| 2854 | static const struct dmi_system_id dmi_platform_intel_bytcht_jdmode2[] = { | ||
| 2851 | { | 2855 | { |
| 2852 | .ident = "Lenovo Thinkpad Tablet 10", | 2856 | .ident = "Lenovo Thinkpad Tablet 10", |
| 2853 | .matches = { | 2857 | .matches = { |
| @@ -2882,6 +2886,11 @@ static int rt5670_i2c_probe(struct i2c_client *i2c, | |||
| 2882 | rt5670->pdata.dmic1_data_pin = RT5670_DMIC_DATA_IN2P; | 2886 | rt5670->pdata.dmic1_data_pin = RT5670_DMIC_DATA_IN2P; |
| 2883 | rt5670->pdata.dev_gpio = true; | 2887 | rt5670->pdata.dev_gpio = true; |
| 2884 | rt5670->pdata.jd_mode = 1; | 2888 | rt5670->pdata.jd_mode = 1; |
| 2889 | } else if (dmi_check_system(dmi_platform_intel_bytcht_jdmode2)) { | ||
| 2890 | rt5670->pdata.dmic_en = true; | ||
| 2891 | rt5670->pdata.dmic1_data_pin = RT5670_DMIC_DATA_IN2P; | ||
| 2892 | rt5670->pdata.dev_gpio = true; | ||
| 2893 | rt5670->pdata.jd_mode = 2; | ||
| 2885 | } | 2894 | } |
| 2886 | 2895 | ||
| 2887 | rt5670->regmap = devm_regmap_init_i2c(i2c, &rt5670_regmap); | 2896 | rt5670->regmap = devm_regmap_init_i2c(i2c, &rt5670_regmap); |
diff --git a/sound/soc/codecs/rt5677.c b/sound/soc/codecs/rt5677.c index 65ac4518ad06..36e530a36c82 100644 --- a/sound/soc/codecs/rt5677.c +++ b/sound/soc/codecs/rt5677.c | |||
| @@ -41,15 +41,6 @@ | |||
| 41 | 41 | ||
| 42 | #define RT5677_PR_BASE (RT5677_PR_RANGE_BASE + (0 * RT5677_PR_SPACING)) | 42 | #define RT5677_PR_BASE (RT5677_PR_RANGE_BASE + (0 * RT5677_PR_SPACING)) |
| 43 | 43 | ||
| 44 | /* GPIO indexes defined by ACPI */ | ||
| 45 | enum { | ||
| 46 | RT5677_GPIO_PLUG_DET = 0, | ||
| 47 | RT5677_GPIO_MIC_PRESENT_L = 1, | ||
| 48 | RT5677_GPIO_HOTWORD_DET_L = 2, | ||
| 49 | RT5677_GPIO_DSP_INT = 3, | ||
| 50 | RT5677_GPIO_HP_AMP_SHDN_L = 4, | ||
| 51 | }; | ||
| 52 | |||
| 53 | static const struct regmap_range_cfg rt5677_ranges[] = { | 44 | static const struct regmap_range_cfg rt5677_ranges[] = { |
| 54 | { | 45 | { |
| 55 | .name = "PR", | 46 | .name = "PR", |
| @@ -5030,7 +5021,6 @@ static const struct regmap_config rt5677_regmap = { | |||
| 5030 | static const struct i2c_device_id rt5677_i2c_id[] = { | 5021 | static const struct i2c_device_id rt5677_i2c_id[] = { |
| 5031 | { "rt5677", RT5677 }, | 5022 | { "rt5677", RT5677 }, |
| 5032 | { "rt5676", RT5676 }, | 5023 | { "rt5676", RT5676 }, |
| 5033 | { "RT5677CE:00", RT5677 }, | ||
| 5034 | { } | 5024 | { } |
| 5035 | }; | 5025 | }; |
| 5036 | MODULE_DEVICE_TABLE(i2c, rt5677_i2c_id); | 5026 | MODULE_DEVICE_TABLE(i2c, rt5677_i2c_id); |
| @@ -5041,28 +5031,19 @@ static const struct of_device_id rt5677_of_match[] = { | |||
| 5041 | }; | 5031 | }; |
| 5042 | MODULE_DEVICE_TABLE(of, rt5677_of_match); | 5032 | MODULE_DEVICE_TABLE(of, rt5677_of_match); |
| 5043 | 5033 | ||
| 5044 | static const struct acpi_gpio_params plug_det_gpio = { RT5677_GPIO_PLUG_DET, 0, false }; | 5034 | #ifdef CONFIG_ACPI |
| 5045 | static const struct acpi_gpio_params mic_present_gpio = { RT5677_GPIO_MIC_PRESENT_L, 0, false }; | 5035 | static const struct acpi_device_id rt5677_acpi_match[] = { |
| 5046 | static const struct acpi_gpio_params headphone_enable_gpio = { RT5677_GPIO_HP_AMP_SHDN_L, 0, false }; | 5036 | { "RT5677CE", RT5677 }, |
| 5047 | 5037 | { } | |
| 5048 | static const struct acpi_gpio_mapping bdw_rt5677_gpios[] = { | ||
| 5049 | { "plug-det-gpios", &plug_det_gpio, 1 }, | ||
| 5050 | { "mic-present-gpios", &mic_present_gpio, 1 }, | ||
| 5051 | { "headphone-enable-gpios", &headphone_enable_gpio, 1 }, | ||
| 5052 | { NULL }, | ||
| 5053 | }; | 5038 | }; |
| 5039 | MODULE_DEVICE_TABLE(acpi, rt5677_acpi_match); | ||
| 5040 | #endif | ||
| 5054 | 5041 | ||
| 5055 | static void rt5677_read_acpi_properties(struct rt5677_priv *rt5677, | 5042 | static void rt5677_read_acpi_properties(struct rt5677_priv *rt5677, |
| 5056 | struct device *dev) | 5043 | struct device *dev) |
| 5057 | { | 5044 | { |
| 5058 | int ret; | ||
| 5059 | u32 val; | 5045 | u32 val; |
| 5060 | 5046 | ||
| 5061 | ret = acpi_dev_add_driver_gpios(ACPI_COMPANION(dev), | ||
| 5062 | bdw_rt5677_gpios); | ||
| 5063 | if (ret) | ||
| 5064 | dev_warn(dev, "Failed to add driver gpios\n"); | ||
| 5065 | |||
| 5066 | if (!device_property_read_u32(dev, "DCLK", &val)) | 5047 | if (!device_property_read_u32(dev, "DCLK", &val)) |
| 5067 | rt5677->pdata.dmic2_clk_pin = val; | 5048 | rt5677->pdata.dmic2_clk_pin = val; |
| 5068 | 5049 | ||
| @@ -5301,6 +5282,7 @@ static struct i2c_driver rt5677_i2c_driver = { | |||
| 5301 | .driver = { | 5282 | .driver = { |
| 5302 | .name = "rt5677", | 5283 | .name = "rt5677", |
| 5303 | .of_match_table = rt5677_of_match, | 5284 | .of_match_table = rt5677_of_match, |
| 5285 | .acpi_match_table = ACPI_PTR(rt5677_acpi_match), | ||
| 5304 | }, | 5286 | }, |
| 5305 | .probe = rt5677_i2c_probe, | 5287 | .probe = rt5677_i2c_probe, |
| 5306 | .remove = rt5677_i2c_remove, | 5288 | .remove = rt5677_i2c_remove, |
diff --git a/sound/soc/intel/Kconfig b/sound/soc/intel/Kconfig index 67968ef3bbda..b301bfff1c09 100644 --- a/sound/soc/intel/Kconfig +++ b/sound/soc/intel/Kconfig | |||
| @@ -214,6 +214,18 @@ config SND_SOC_INTEL_BYT_CHT_DA7213_MACH | |||
| 214 | platforms with DA7212/7213 audio codec. | 214 | platforms with DA7212/7213 audio codec. |
| 215 | If unsure select "N". | 215 | If unsure select "N". |
| 216 | 216 | ||
| 217 | config SND_SOC_INTEL_BYT_CHT_ES8316_MACH | ||
| 218 | tristate "ASoC Audio driver for Intel Baytrail & Cherrytrail with ES8316 codec" | ||
| 219 | depends on X86_INTEL_LPSS && I2C && ACPI | ||
| 220 | select SND_SOC_ES8316 | ||
| 221 | select SND_SST_ATOM_HIFI2_PLATFORM | ||
| 222 | select SND_SST_IPC_ACPI | ||
| 223 | select SND_SOC_INTEL_SST_MATCH if ACPI | ||
| 224 | help | ||
| 225 | This adds support for ASoC machine driver for Intel(R) Baytrail & | ||
| 226 | Cherrytrail platforms with ES8316 audio codec. | ||
| 227 | If unsure select "N". | ||
| 228 | |||
| 217 | config SND_SOC_INTEL_BYT_CHT_NOCODEC_MACH | 229 | config SND_SOC_INTEL_BYT_CHT_NOCODEC_MACH |
| 218 | tristate "ASoC Audio driver for Intel Baytrail & Cherrytrail platform with no codec (MinnowBoard MAX, Up)" | 230 | tristate "ASoC Audio driver for Intel Baytrail & Cherrytrail platform with no codec (MinnowBoard MAX, Up)" |
| 219 | depends on X86_INTEL_LPSS && I2C && ACPI | 231 | depends on X86_INTEL_LPSS && I2C && ACPI |
| @@ -226,6 +238,36 @@ config SND_SOC_INTEL_BYT_CHT_NOCODEC_MACH | |||
| 226 | connector | 238 | connector |
| 227 | If unsure select "N". | 239 | If unsure select "N". |
| 228 | 240 | ||
| 241 | config SND_SOC_INTEL_KBL_RT5663_MAX98927_MACH | ||
| 242 | tristate "ASoC Audio driver for KBL with RT5663 and MAX98927 in I2S Mode" | ||
| 243 | depends on X86_INTEL_LPSS && I2C | ||
| 244 | select SND_SOC_INTEL_SST | ||
| 245 | select SND_SOC_INTEL_SKYLAKE | ||
| 246 | select SND_SOC_RT5663 | ||
| 247 | select SND_SOC_MAX98927 | ||
| 248 | select SND_SOC_DMIC | ||
| 249 | select SND_SOC_HDAC_HDMI | ||
| 250 | help | ||
| 251 | This adds support for ASoC Onboard Codec I2S machine driver. This will | ||
| 252 | create an alsa sound card for RT5663 + MAX98927. | ||
| 253 | Say Y if you have such a device. | ||
| 254 | If unsure select "N". | ||
| 255 | |||
| 256 | config SND_SOC_INTEL_KBL_RT5663_RT5514_MAX98927_MACH | ||
| 257 | tristate "ASoC Audio driver for KBL with RT5663, RT5514 and MAX98927 in I2S Mode" | ||
| 258 | depends on X86_INTEL_LPSS && I2C | ||
| 259 | select SND_SOC_INTEL_SST | ||
| 260 | select SND_SOC_INTEL_SKYLAKE | ||
| 261 | select SND_SOC_RT5663 | ||
| 262 | select SND_SOC_RT5514 | ||
| 263 | select SND_SOC_MAX98927 | ||
| 264 | select SND_SOC_HDAC_HDMI | ||
| 265 | help | ||
| 266 | This adds support for ASoC Onboard Codec I2S machine driver. This will | ||
| 267 | create an alsa sound card for RT5663 + RT5514 + MAX98927. | ||
| 268 | Say Y if you have such a device. | ||
| 269 | If unsure select "N". | ||
| 270 | |||
| 229 | config SND_SOC_INTEL_SKYLAKE | 271 | config SND_SOC_INTEL_SKYLAKE |
| 230 | tristate | 272 | tristate |
| 231 | select SND_HDA_EXT_CORE | 273 | select SND_HDA_EXT_CORE |
diff --git a/sound/soc/intel/atom/sst-mfld-platform-pcm.c b/sound/soc/intel/atom/sst-mfld-platform-pcm.c index 21cac1c8dd4c..b082b31023d5 100644 --- a/sound/soc/intel/atom/sst-mfld-platform-pcm.c +++ b/sound/soc/intel/atom/sst-mfld-platform-pcm.c | |||
| @@ -690,7 +690,7 @@ static int sst_pcm_new(struct snd_soc_pcm_runtime *rtd) | |||
| 690 | snd_dma_continuous_data(GFP_DMA), | 690 | snd_dma_continuous_data(GFP_DMA), |
| 691 | SST_MIN_BUFFER, SST_MAX_BUFFER); | 691 | SST_MIN_BUFFER, SST_MAX_BUFFER); |
| 692 | if (retval) { | 692 | if (retval) { |
| 693 | dev_err(rtd->dev, "dma buffer allocationf fail\n"); | 693 | dev_err(rtd->dev, "dma buffer allocation failure\n"); |
| 694 | return retval; | 694 | return retval; |
| 695 | } | 695 | } |
| 696 | } | 696 | } |
diff --git a/sound/soc/intel/atom/sst/sst.c b/sound/soc/intel/atom/sst/sst.c index f9ba71315e33..8afdff457579 100644 --- a/sound/soc/intel/atom/sst/sst.c +++ b/sound/soc/intel/atom/sst/sst.c | |||
| @@ -258,7 +258,7 @@ static ssize_t firmware_version_show(struct device *dev, | |||
| 258 | 258 | ||
| 259 | } | 259 | } |
| 260 | 260 | ||
| 261 | DEVICE_ATTR_RO(firmware_version); | 261 | static DEVICE_ATTR_RO(firmware_version); |
| 262 | 262 | ||
| 263 | static const struct attribute *sst_fw_version_attrs[] = { | 263 | static const struct attribute *sst_fw_version_attrs[] = { |
| 264 | &dev_attr_firmware_version.attr, | 264 | &dev_attr_firmware_version.attr, |
| @@ -382,37 +382,6 @@ void sst_context_cleanup(struct intel_sst_drv *ctx) | |||
| 382 | } | 382 | } |
| 383 | EXPORT_SYMBOL_GPL(sst_context_cleanup); | 383 | EXPORT_SYMBOL_GPL(sst_context_cleanup); |
| 384 | 384 | ||
| 385 | static inline void sst_save_shim64(struct intel_sst_drv *ctx, | ||
| 386 | void __iomem *shim, | ||
| 387 | struct sst_shim_regs64 *shim_regs) | ||
| 388 | { | ||
| 389 | unsigned long irq_flags; | ||
| 390 | |||
| 391 | spin_lock_irqsave(&ctx->ipc_spin_lock, irq_flags); | ||
| 392 | |||
| 393 | shim_regs->imrx = sst_shim_read64(shim, SST_IMRX); | ||
| 394 | shim_regs->csr = sst_shim_read64(shim, SST_CSR); | ||
| 395 | |||
| 396 | |||
| 397 | spin_unlock_irqrestore(&ctx->ipc_spin_lock, irq_flags); | ||
| 398 | } | ||
| 399 | |||
| 400 | static inline void sst_restore_shim64(struct intel_sst_drv *ctx, | ||
| 401 | void __iomem *shim, | ||
| 402 | struct sst_shim_regs64 *shim_regs) | ||
| 403 | { | ||
| 404 | unsigned long irq_flags; | ||
| 405 | |||
| 406 | /* | ||
| 407 | * we only need to restore IMRX for this case, rest will be | ||
| 408 | * initialize by FW or driver when firmware is loaded | ||
| 409 | */ | ||
| 410 | spin_lock_irqsave(&ctx->ipc_spin_lock, irq_flags); | ||
| 411 | sst_shim_write64(shim, SST_IMRX, shim_regs->imrx); | ||
| 412 | sst_shim_write64(shim, SST_CSR, shim_regs->csr); | ||
| 413 | spin_unlock_irqrestore(&ctx->ipc_spin_lock, irq_flags); | ||
| 414 | } | ||
| 415 | |||
| 416 | void sst_configure_runtime_pm(struct intel_sst_drv *ctx) | 385 | void sst_configure_runtime_pm(struct intel_sst_drv *ctx) |
| 417 | { | 386 | { |
| 418 | pm_runtime_set_autosuspend_delay(ctx->dev, SST_SUSPEND_DELAY); | 387 | pm_runtime_set_autosuspend_delay(ctx->dev, SST_SUSPEND_DELAY); |
| @@ -432,8 +401,6 @@ void sst_configure_runtime_pm(struct intel_sst_drv *ctx) | |||
| 432 | pm_runtime_set_active(ctx->dev); | 401 | pm_runtime_set_active(ctx->dev); |
| 433 | else | 402 | else |
| 434 | pm_runtime_put_noidle(ctx->dev); | 403 | pm_runtime_put_noidle(ctx->dev); |
| 435 | |||
| 436 | sst_save_shim64(ctx, ctx->shim, ctx->shim_regs64); | ||
| 437 | } | 404 | } |
| 438 | EXPORT_SYMBOL_GPL(sst_configure_runtime_pm); | 405 | EXPORT_SYMBOL_GPL(sst_configure_runtime_pm); |
| 439 | 406 | ||
| @@ -457,8 +424,6 @@ static int intel_sst_runtime_suspend(struct device *dev) | |||
| 457 | flush_workqueue(ctx->post_msg_wq); | 424 | flush_workqueue(ctx->post_msg_wq); |
| 458 | 425 | ||
| 459 | ctx->ops->reset(ctx); | 426 | ctx->ops->reset(ctx); |
| 460 | /* save the shim registers because PMC doesn't save state */ | ||
| 461 | sst_save_shim64(ctx, ctx->shim, ctx->shim_regs64); | ||
| 462 | 427 | ||
| 463 | return ret; | 428 | return ret; |
| 464 | } | 429 | } |
| @@ -499,23 +464,23 @@ static int intel_sst_suspend(struct device *dev) | |||
| 499 | fw_save = kzalloc(sizeof(*fw_save), GFP_KERNEL); | 464 | fw_save = kzalloc(sizeof(*fw_save), GFP_KERNEL); |
| 500 | if (!fw_save) | 465 | if (!fw_save) |
| 501 | return -ENOMEM; | 466 | return -ENOMEM; |
| 502 | fw_save->iram = kzalloc(ctx->iram_end - ctx->iram_base, GFP_KERNEL); | 467 | fw_save->iram = kvzalloc(ctx->iram_end - ctx->iram_base, GFP_KERNEL); |
| 503 | if (!fw_save->iram) { | 468 | if (!fw_save->iram) { |
| 504 | ret = -ENOMEM; | 469 | ret = -ENOMEM; |
| 505 | goto iram; | 470 | goto iram; |
| 506 | } | 471 | } |
| 507 | fw_save->dram = kzalloc(ctx->dram_end - ctx->dram_base, GFP_KERNEL); | 472 | fw_save->dram = kvzalloc(ctx->dram_end - ctx->dram_base, GFP_KERNEL); |
| 508 | if (!fw_save->dram) { | 473 | if (!fw_save->dram) { |
| 509 | ret = -ENOMEM; | 474 | ret = -ENOMEM; |
| 510 | goto dram; | 475 | goto dram; |
| 511 | } | 476 | } |
| 512 | fw_save->sram = kzalloc(SST_MAILBOX_SIZE, GFP_KERNEL); | 477 | fw_save->sram = kvzalloc(SST_MAILBOX_SIZE, GFP_KERNEL); |
| 513 | if (!fw_save->sram) { | 478 | if (!fw_save->sram) { |
| 514 | ret = -ENOMEM; | 479 | ret = -ENOMEM; |
| 515 | goto sram; | 480 | goto sram; |
| 516 | } | 481 | } |
| 517 | 482 | ||
| 518 | fw_save->ddr = kzalloc(ctx->ddr_end - ctx->ddr_base, GFP_KERNEL); | 483 | fw_save->ddr = kvzalloc(ctx->ddr_end - ctx->ddr_base, GFP_KERNEL); |
| 519 | if (!fw_save->ddr) { | 484 | if (!fw_save->ddr) { |
| 520 | ret = -ENOMEM; | 485 | ret = -ENOMEM; |
| 521 | goto ddr; | 486 | goto ddr; |
| @@ -530,11 +495,11 @@ static int intel_sst_suspend(struct device *dev) | |||
| 530 | ctx->ops->reset(ctx); | 495 | ctx->ops->reset(ctx); |
| 531 | return 0; | 496 | return 0; |
| 532 | ddr: | 497 | ddr: |
| 533 | kfree(fw_save->sram); | 498 | kvfree(fw_save->sram); |
| 534 | sram: | 499 | sram: |
| 535 | kfree(fw_save->dram); | 500 | kvfree(fw_save->dram); |
| 536 | dram: | 501 | dram: |
| 537 | kfree(fw_save->iram); | 502 | kvfree(fw_save->iram); |
| 538 | iram: | 503 | iram: |
| 539 | kfree(fw_save); | 504 | kfree(fw_save); |
| 540 | return ret; | 505 | return ret; |
| @@ -562,10 +527,10 @@ static int intel_sst_resume(struct device *dev) | |||
| 562 | memcpy32_toio(ctx->mailbox, fw_save->sram, SST_MAILBOX_SIZE); | 527 | memcpy32_toio(ctx->mailbox, fw_save->sram, SST_MAILBOX_SIZE); |
| 563 | memcpy32_toio(ctx->ddr, fw_save->ddr, ctx->ddr_end - ctx->ddr_base); | 528 | memcpy32_toio(ctx->ddr, fw_save->ddr, ctx->ddr_end - ctx->ddr_base); |
| 564 | 529 | ||
| 565 | kfree(fw_save->sram); | 530 | kvfree(fw_save->sram); |
| 566 | kfree(fw_save->dram); | 531 | kvfree(fw_save->dram); |
| 567 | kfree(fw_save->iram); | 532 | kvfree(fw_save->iram); |
| 568 | kfree(fw_save->ddr); | 533 | kvfree(fw_save->ddr); |
| 569 | kfree(fw_save); | 534 | kfree(fw_save); |
| 570 | 535 | ||
| 571 | block = sst_create_block(ctx, 0, FW_DWNL_ID); | 536 | block = sst_create_block(ctx, 0, FW_DWNL_ID); |
diff --git a/sound/soc/intel/atom/sst/sst.h b/sound/soc/intel/atom/sst/sst.h index 5c9a51cc77aa..e02e2b4cc08f 100644 --- a/sound/soc/intel/atom/sst/sst.h +++ b/sound/soc/intel/atom/sst/sst.h | |||
| @@ -317,31 +317,11 @@ struct sst_ipc_reg { | |||
| 317 | int ipcd; | 317 | int ipcd; |
| 318 | }; | 318 | }; |
| 319 | 319 | ||
| 320 | struct sst_shim_regs64 { | ||
| 321 | u64 csr; | ||
| 322 | u64 pisr; | ||
| 323 | u64 pimr; | ||
| 324 | u64 isrx; | ||
| 325 | u64 isrd; | ||
| 326 | u64 imrx; | ||
| 327 | u64 imrd; | ||
| 328 | u64 ipcx; | ||
| 329 | u64 ipcd; | ||
| 330 | u64 isrsc; | ||
| 331 | u64 isrlpesc; | ||
| 332 | u64 imrsc; | ||
| 333 | u64 imrlpesc; | ||
| 334 | u64 ipcsc; | ||
| 335 | u64 ipclpesc; | ||
| 336 | u64 clkctl; | ||
| 337 | u64 csr2; | ||
| 338 | }; | ||
| 339 | |||
| 340 | struct sst_fw_save { | 320 | struct sst_fw_save { |
| 341 | void *iram; | 321 | void *iram; /* allocated via kvmalloc() */ |
| 342 | void *dram; | 322 | void *dram; /* allocated via kvmalloc() */ |
| 343 | void *sram; | 323 | void *sram; /* allocated via kvmalloc() */ |
| 344 | void *ddr; | 324 | void *ddr; /* allocated via kvmalloc() */ |
| 345 | }; | 325 | }; |
| 346 | 326 | ||
| 347 | /** | 327 | /** |
| @@ -356,7 +336,6 @@ struct sst_fw_save { | |||
| 356 | * @dram : SST DRAM pointer | 336 | * @dram : SST DRAM pointer |
| 357 | * @pdata : SST info passed as a part of pci platform data | 337 | * @pdata : SST info passed as a part of pci platform data |
| 358 | * @shim_phy_add : SST shim phy addr | 338 | * @shim_phy_add : SST shim phy addr |
| 359 | * @shim_regs64: Struct to save shim registers | ||
| 360 | * @ipc_dispatch_list : ipc messages dispatched | 339 | * @ipc_dispatch_list : ipc messages dispatched |
| 361 | * @rx_list : to copy the process_reply/process_msg from DSP | 340 | * @rx_list : to copy the process_reply/process_msg from DSP |
| 362 | * @ipc_post_msg_wq : wq to post IPC messages context | 341 | * @ipc_post_msg_wq : wq to post IPC messages context |
| @@ -398,7 +377,6 @@ struct intel_sst_drv { | |||
| 398 | unsigned int ddr_end; | 377 | unsigned int ddr_end; |
| 399 | unsigned int ddr_base; | 378 | unsigned int ddr_base; |
| 400 | unsigned int mailbox_recv_offset; | 379 | unsigned int mailbox_recv_offset; |
| 401 | struct sst_shim_regs64 *shim_regs64; | ||
| 402 | struct list_head block_list; | 380 | struct list_head block_list; |
| 403 | struct list_head ipc_dispatch_list; | 381 | struct list_head ipc_dispatch_list; |
| 404 | struct sst_platform_info *pdata; | 382 | struct sst_platform_info *pdata; |
diff --git a/sound/soc/intel/atom/sst/sst_acpi.c b/sound/soc/intel/atom/sst/sst_acpi.c index dd250b8b26f2..0e928d54305d 100644 --- a/sound/soc/intel/atom/sst/sst_acpi.c +++ b/sound/soc/intel/atom/sst/sst_acpi.c | |||
| @@ -303,8 +303,6 @@ static int sst_acpi_probe(struct platform_device *pdev) | |||
| 303 | dev_err(dev, "No matching machine driver found\n"); | 303 | dev_err(dev, "No matching machine driver found\n"); |
| 304 | return -ENODEV; | 304 | return -ENODEV; |
| 305 | } | 305 | } |
| 306 | if (mach->machine_quirk) | ||
| 307 | mach = mach->machine_quirk(mach); | ||
| 308 | 306 | ||
| 309 | pdata = mach->pdata; | 307 | pdata = mach->pdata; |
| 310 | 308 | ||
| @@ -360,23 +358,9 @@ static int sst_acpi_probe(struct platform_device *pdev) | |||
| 360 | if (ret < 0) | 358 | if (ret < 0) |
| 361 | return ret; | 359 | return ret; |
| 362 | 360 | ||
| 363 | /* need to save shim registers in BYT */ | ||
| 364 | ctx->shim_regs64 = devm_kzalloc(ctx->dev, sizeof(*ctx->shim_regs64), | ||
| 365 | GFP_KERNEL); | ||
| 366 | if (!ctx->shim_regs64) { | ||
| 367 | ret = -ENOMEM; | ||
| 368 | goto do_sst_cleanup; | ||
| 369 | } | ||
| 370 | |||
| 371 | sst_configure_runtime_pm(ctx); | 361 | sst_configure_runtime_pm(ctx); |
| 372 | platform_set_drvdata(pdev, ctx); | 362 | platform_set_drvdata(pdev, ctx); |
| 373 | return ret; | 363 | return ret; |
| 374 | |||
| 375 | do_sst_cleanup: | ||
| 376 | sst_context_cleanup(ctx); | ||
| 377 | platform_set_drvdata(pdev, NULL); | ||
| 378 | dev_err(ctx->dev, "failed with %d\n", ret); | ||
| 379 | return ret; | ||
| 380 | } | 364 | } |
| 381 | 365 | ||
| 382 | /** | 366 | /** |
| @@ -453,12 +437,20 @@ static const struct dmi_system_id cht_table[] = { | |||
| 453 | 437 | ||
| 454 | 438 | ||
| 455 | static struct sst_acpi_mach cht_surface_mach = { | 439 | static struct sst_acpi_mach cht_surface_mach = { |
| 456 | "10EC5640", "cht-bsw-rt5645", "intel/fw_sst_22a8.bin", "cht-bsw", NULL, | 440 | .id = "10EC5640", |
| 457 | &chv_platform_data }; | 441 | .drv_name = "cht-bsw-rt5645", |
| 442 | .fw_filename = "intel/fw_sst_22a8.bin", | ||
| 443 | .board = "cht-bsw", | ||
| 444 | .pdata = &chv_platform_data, | ||
| 445 | }; | ||
| 458 | 446 | ||
| 459 | static struct sst_acpi_mach byt_thinkpad_10 = { | 447 | static struct sst_acpi_mach byt_thinkpad_10 = { |
| 460 | "10EC5640", "cht-bsw-rt5672", "intel/fw_sst_0f28.bin", "cht-bsw", NULL, | 448 | .id = "10EC5640", |
| 461 | &byt_rvp_platform_data }; | 449 | .drv_name = "cht-bsw-rt5672", |
| 450 | .fw_filename = "intel/fw_sst_0f28.bin", | ||
| 451 | .board = "cht-bsw", | ||
| 452 | .pdata = &byt_rvp_platform_data, | ||
| 453 | }; | ||
| 462 | 454 | ||
| 463 | static struct sst_acpi_mach *cht_quirk(void *arg) | 455 | static struct sst_acpi_mach *cht_quirk(void *arg) |
| 464 | { | 456 | { |
| @@ -486,68 +478,182 @@ static struct sst_acpi_mach *byt_quirk(void *arg) | |||
| 486 | 478 | ||
| 487 | 479 | ||
| 488 | static struct sst_acpi_mach sst_acpi_bytcr[] = { | 480 | static struct sst_acpi_mach sst_acpi_bytcr[] = { |
| 489 | {"10EC5640", "bytcr_rt5640", "intel/fw_sst_0f28.bin", "bytcr_rt5640", byt_quirk, | 481 | { |
| 490 | &byt_rvp_platform_data }, | 482 | .id = "10EC5640", |
| 491 | {"10EC5642", "bytcr_rt5640", "intel/fw_sst_0f28.bin", "bytcr_rt5640", NULL, | 483 | .drv_name = "bytcr_rt5640", |
| 492 | &byt_rvp_platform_data }, | 484 | .fw_filename = "intel/fw_sst_0f28.bin", |
| 493 | {"INTCCFFD", "bytcr_rt5640", "intel/fw_sst_0f28.bin", "bytcr_rt5640", NULL, | 485 | .board = "bytcr_rt5640", |
| 494 | &byt_rvp_platform_data }, | 486 | .machine_quirk = byt_quirk, |
| 495 | {"10EC5651", "bytcr_rt5651", "intel/fw_sst_0f28.bin", "bytcr_rt5651", NULL, | 487 | .pdata = &byt_rvp_platform_data, |
| 496 | &byt_rvp_platform_data }, | 488 | }, |
| 497 | {"DLGS7212", "bytcht_da7213", "intel/fw_sst_0f28.bin", "bytcht_da7213", NULL, | 489 | { |
| 498 | &byt_rvp_platform_data }, | 490 | .id = "10EC5642", |
| 499 | {"DLGS7213", "bytcht_da7213", "intel/fw_sst_0f28.bin", "bytcht_da7213", NULL, | 491 | .drv_name = "bytcr_rt5640", |
| 500 | &byt_rvp_platform_data }, | 492 | .fw_filename = "intel/fw_sst_0f28.bin", |
| 493 | .board = "bytcr_rt5640", | ||
| 494 | .pdata = &byt_rvp_platform_data | ||
| 495 | }, | ||
| 496 | { | ||
| 497 | .id = "INTCCFFD", | ||
| 498 | .drv_name = "bytcr_rt5640", | ||
| 499 | .fw_filename = "intel/fw_sst_0f28.bin", | ||
| 500 | .board = "bytcr_rt5640", | ||
| 501 | .pdata = &byt_rvp_platform_data | ||
| 502 | }, | ||
| 503 | { | ||
| 504 | .id = "10EC5651", | ||
| 505 | .drv_name = "bytcr_rt5651", | ||
| 506 | .fw_filename = "intel/fw_sst_0f28.bin", | ||
| 507 | .board = "bytcr_rt5651", | ||
| 508 | .pdata = &byt_rvp_platform_data | ||
| 509 | }, | ||
| 510 | { | ||
| 511 | .id = "DLGS7212", | ||
| 512 | .drv_name = "bytcht_da7213", | ||
| 513 | .fw_filename = "intel/fw_sst_0f28.bin", | ||
| 514 | .board = "bytcht_da7213", | ||
| 515 | .pdata = &byt_rvp_platform_data | ||
| 516 | }, | ||
| 517 | { | ||
| 518 | .id = "DLGS7213", | ||
| 519 | .drv_name = "bytcht_da7213", | ||
| 520 | .fw_filename = "intel/fw_sst_0f28.bin", | ||
| 521 | .board = "bytcht_da7213", | ||
| 522 | .pdata = &byt_rvp_platform_data | ||
| 523 | }, | ||
| 501 | /* some Baytrail platforms rely on RT5645, use CHT machine driver */ | 524 | /* some Baytrail platforms rely on RT5645, use CHT machine driver */ |
| 502 | {"10EC5645", "cht-bsw-rt5645", "intel/fw_sst_0f28.bin", "cht-bsw", NULL, | 525 | { |
| 503 | &byt_rvp_platform_data }, | 526 | .id = "10EC5645", |
| 504 | {"10EC5648", "cht-bsw-rt5645", "intel/fw_sst_0f28.bin", "cht-bsw", NULL, | 527 | .drv_name = "cht-bsw-rt5645", |
| 505 | &byt_rvp_platform_data }, | 528 | .fw_filename = "intel/fw_sst_0f28.bin", |
| 529 | .board = "cht-bsw", | ||
| 530 | .pdata = &byt_rvp_platform_data | ||
| 531 | }, | ||
| 532 | { | ||
| 533 | .id = "10EC5648", | ||
| 534 | .drv_name = "cht-bsw-rt5645", | ||
| 535 | .fw_filename = "intel/fw_sst_0f28.bin", | ||
| 536 | .board = "cht-bsw", | ||
| 537 | .pdata = &byt_rvp_platform_data | ||
| 538 | }, | ||
| 506 | #if IS_ENABLED(CONFIG_SND_SOC_INTEL_BYT_CHT_NOCODEC_MACH) | 539 | #if IS_ENABLED(CONFIG_SND_SOC_INTEL_BYT_CHT_NOCODEC_MACH) |
| 507 | /* | 540 | /* |
| 508 | * This is always last in the table so that it is selected only when | 541 | * This is always last in the table so that it is selected only when |
| 509 | * enabled explicitly and there is no codec-related information in SSDT | 542 | * enabled explicitly and there is no codec-related information in SSDT |
| 510 | */ | 543 | */ |
| 511 | {"80860F28", "bytcht_nocodec", "intel/fw_sst_0f28.bin", "bytcht_nocodec", NULL, | 544 | { |
| 512 | &byt_rvp_platform_data }, | 545 | .id = "80860F28", |
| 546 | .drv_name = "bytcht_nocodec", | ||
| 547 | .fw_filename = "intel/fw_sst_0f28.bin", | ||
| 548 | .board = "bytcht_nocodec", | ||
| 549 | .pdata = &byt_rvp_platform_data | ||
| 550 | }, | ||
| 513 | #endif | 551 | #endif |
| 514 | {}, | 552 | {}, |
| 515 | }; | 553 | }; |
| 516 | 554 | ||
| 517 | /* Cherryview-based platforms: CherryTrail and Braswell */ | 555 | /* Cherryview-based platforms: CherryTrail and Braswell */ |
| 518 | static struct sst_acpi_mach sst_acpi_chv[] = { | 556 | static struct sst_acpi_mach sst_acpi_chv[] = { |
| 519 | {"10EC5670", "cht-bsw-rt5672", "intel/fw_sst_22a8.bin", "cht-bsw", NULL, | 557 | { |
| 520 | &chv_platform_data }, | 558 | .id = "10EC5670", |
| 521 | {"10EC5672", "cht-bsw-rt5672", "intel/fw_sst_22a8.bin", "cht-bsw", NULL, | 559 | .drv_name = "cht-bsw-rt5672", |
| 522 | &chv_platform_data }, | 560 | .fw_filename = "intel/fw_sst_22a8.bin", |
| 523 | {"10EC5645", "cht-bsw-rt5645", "intel/fw_sst_22a8.bin", "cht-bsw", NULL, | 561 | .board = "cht-bsw", |
| 524 | &chv_platform_data }, | 562 | .pdata = &chv_platform_data |
| 525 | {"10EC5650", "cht-bsw-rt5645", "intel/fw_sst_22a8.bin", "cht-bsw", NULL, | 563 | }, |
| 526 | &chv_platform_data }, | 564 | { |
| 527 | {"10EC3270", "cht-bsw-rt5645", "intel/fw_sst_22a8.bin", "cht-bsw", NULL, | 565 | .id = "10EC5672", |
| 528 | &chv_platform_data }, | 566 | .drv_name = "cht-bsw-rt5672", |
| 529 | 567 | .fw_filename = "intel/fw_sst_22a8.bin", | |
| 530 | {"193C9890", "cht-bsw-max98090", "intel/fw_sst_22a8.bin", "cht-bsw", NULL, | 568 | .board = "cht-bsw", |
| 531 | &chv_platform_data }, | 569 | .pdata = &chv_platform_data |
| 532 | {"DLGS7212", "bytcht_da7213", "intel/fw_sst_22a8.bin", "bytcht_da7213", NULL, | 570 | }, |
| 533 | &chv_platform_data }, | 571 | { |
| 534 | {"DLGS7213", "bytcht_da7213", "intel/fw_sst_22a8.bin", "bytcht_da7213", NULL, | 572 | .id = "10EC5645", |
| 535 | &chv_platform_data }, | 573 | .drv_name = "cht-bsw-rt5645", |
| 574 | .fw_filename = "intel/fw_sst_22a8.bin", | ||
| 575 | .board = "cht-bsw", | ||
| 576 | .pdata = &chv_platform_data | ||
| 577 | }, | ||
| 578 | { | ||
| 579 | .id = "10EC5650", | ||
| 580 | .drv_name = "cht-bsw-rt5645", | ||
| 581 | .fw_filename = "intel/fw_sst_22a8.bin", | ||
| 582 | .board = "cht-bsw", | ||
| 583 | .pdata = &chv_platform_data | ||
| 584 | }, | ||
| 585 | { | ||
| 586 | .id = "10EC3270", | ||
| 587 | .drv_name = "cht-bsw-rt5645", | ||
| 588 | .fw_filename = "intel/fw_sst_22a8.bin", | ||
| 589 | .board = "cht-bsw", | ||
| 590 | .pdata = &chv_platform_data | ||
| 591 | }, | ||
| 592 | |||
| 593 | { | ||
| 594 | .id = "193C9890", | ||
| 595 | .drv_name = "cht-bsw-max98090", | ||
| 596 | .fw_filename = "intel/fw_sst_22a8.bin", | ||
| 597 | .board = "cht-bsw", | ||
| 598 | .pdata = &chv_platform_data | ||
| 599 | }, | ||
| 600 | { | ||
| 601 | .id = "DLGS7212", | ||
| 602 | .drv_name = "bytcht_da7213", | ||
| 603 | .fw_filename = "intel/fw_sst_22a8.bin", | ||
| 604 | .board = "bytcht_da7213", | ||
| 605 | .pdata = &chv_platform_data | ||
| 606 | }, | ||
| 607 | { | ||
| 608 | .id = "DLGS7213", | ||
| 609 | .drv_name = "bytcht_da7213", | ||
| 610 | .fw_filename = "intel/fw_sst_22a8.bin", | ||
| 611 | .board = "bytcht_da7213", | ||
| 612 | .pdata = &chv_platform_data | ||
| 613 | }, | ||
| 614 | { | ||
| 615 | .id = "ESSX8316", | ||
| 616 | .drv_name = "bytcht_es8316", | ||
| 617 | .fw_filename = "intel/fw_sst_22a8.bin", | ||
| 618 | .board = "bytcht_es8316", | ||
| 619 | .pdata = &chv_platform_data | ||
| 620 | }, | ||
| 536 | /* some CHT-T platforms rely on RT5640, use Baytrail machine driver */ | 621 | /* some CHT-T platforms rely on RT5640, use Baytrail machine driver */ |
| 537 | {"10EC5640", "bytcr_rt5640", "intel/fw_sst_22a8.bin", "bytcr_rt5640", cht_quirk, | 622 | { |
| 538 | &chv_platform_data }, | 623 | .id = "10EC5640", |
| 539 | {"10EC3276", "bytcr_rt5640", "intel/fw_sst_22a8.bin", "bytcr_rt5640", NULL, | 624 | .drv_name = "bytcr_rt5640", |
| 540 | &chv_platform_data }, | 625 | .fw_filename = "intel/fw_sst_22a8.bin", |
| 626 | .board = "bytcr_rt5640", | ||
| 627 | .machine_quirk = cht_quirk, | ||
| 628 | .pdata = &chv_platform_data | ||
| 629 | }, | ||
| 630 | { | ||
| 631 | .id = "10EC3276", | ||
| 632 | .drv_name = "bytcr_rt5640", | ||
| 633 | .fw_filename = "intel/fw_sst_22a8.bin", | ||
| 634 | .board = "bytcr_rt5640", | ||
| 635 | .pdata = &chv_platform_data | ||
| 636 | }, | ||
| 541 | /* some CHT-T platforms rely on RT5651, use Baytrail machine driver */ | 637 | /* some CHT-T platforms rely on RT5651, use Baytrail machine driver */ |
| 542 | {"10EC5651", "bytcr_rt5651", "intel/fw_sst_22a8.bin", "bytcr_rt5651", NULL, | 638 | { |
| 543 | &chv_platform_data }, | 639 | .id = "10EC5651", |
| 640 | .drv_name = "bytcr_rt5651", | ||
| 641 | .fw_filename = "intel/fw_sst_22a8.bin", | ||
| 642 | .board = "bytcr_rt5651", | ||
| 643 | .pdata = &chv_platform_data | ||
| 644 | }, | ||
| 544 | #if IS_ENABLED(CONFIG_SND_SOC_INTEL_BYT_CHT_NOCODEC_MACH) | 645 | #if IS_ENABLED(CONFIG_SND_SOC_INTEL_BYT_CHT_NOCODEC_MACH) |
| 545 | /* | 646 | /* |
| 546 | * This is always last in the table so that it is selected only when | 647 | * This is always last in the table so that it is selected only when |
| 547 | * enabled explicitly and there is no codec-related information in SSDT | 648 | * enabled explicitly and there is no codec-related information in SSDT |
| 548 | */ | 649 | */ |
| 549 | {"808622A8", "bytcht_nocodec", "intel/fw_sst_22a8.bin", "bytcht_nocodec", NULL, | 650 | { |
| 550 | &chv_platform_data }, | 651 | .id = "808622A8", |
| 652 | .drv_name = "bytcht_nocodec", | ||
| 653 | .fw_filename = "intel/fw_sst_22a8.bin", | ||
| 654 | .board = "bytcht_nocodec", | ||
| 655 | .pdata = &chv_platform_data | ||
| 656 | }, | ||
| 551 | #endif | 657 | #endif |
| 552 | {}, | 658 | {}, |
| 553 | }; | 659 | }; |
diff --git a/sound/soc/intel/boards/Makefile b/sound/soc/intel/boards/Makefile index 56896e09445d..a5c5bc5732a2 100644 --- a/sound/soc/intel/boards/Makefile +++ b/sound/soc/intel/boards/Makefile | |||
| @@ -11,7 +11,10 @@ snd-soc-sst-cht-bsw-rt5672-objs := cht_bsw_rt5672.o | |||
| 11 | snd-soc-sst-cht-bsw-rt5645-objs := cht_bsw_rt5645.o | 11 | snd-soc-sst-cht-bsw-rt5645-objs := cht_bsw_rt5645.o |
| 12 | snd-soc-sst-cht-bsw-max98090_ti-objs := cht_bsw_max98090_ti.o | 12 | snd-soc-sst-cht-bsw-max98090_ti-objs := cht_bsw_max98090_ti.o |
| 13 | snd-soc-sst-byt-cht-da7213-objs := bytcht_da7213.o | 13 | snd-soc-sst-byt-cht-da7213-objs := bytcht_da7213.o |
| 14 | snd-soc-sst-byt-cht-es8316-objs := bytcht_es8316.o | ||
| 14 | snd-soc-sst-byt-cht-nocodec-objs := bytcht_nocodec.o | 15 | snd-soc-sst-byt-cht-nocodec-objs := bytcht_nocodec.o |
| 16 | snd-soc-kbl_rt5663_max98927-objs := kbl_rt5663_max98927.o | ||
| 17 | snd-soc-kbl_rt5663_rt5514_max98927-objs := kbl_rt5663_rt5514_max98927.o | ||
| 15 | snd-soc-skl_rt286-objs := skl_rt286.o | 18 | snd-soc-skl_rt286-objs := skl_rt286.o |
| 16 | snd-skl_nau88l25_max98357a-objs := skl_nau88l25_max98357a.o | 19 | snd-skl_nau88l25_max98357a-objs := skl_nau88l25_max98357a.o |
| 17 | snd-soc-skl_nau88l25_ssm4567-objs := skl_nau88l25_ssm4567.o | 20 | snd-soc-skl_nau88l25_ssm4567-objs := skl_nau88l25_ssm4567.o |
| @@ -29,7 +32,10 @@ obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_RT5672_MACH) += snd-soc-sst-cht-bsw-rt5672.o | |||
| 29 | obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_RT5645_MACH) += snd-soc-sst-cht-bsw-rt5645.o | 32 | obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_RT5645_MACH) += snd-soc-sst-cht-bsw-rt5645.o |
| 30 | obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_MAX98090_TI_MACH) += snd-soc-sst-cht-bsw-max98090_ti.o | 33 | obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_MAX98090_TI_MACH) += snd-soc-sst-cht-bsw-max98090_ti.o |
| 31 | obj-$(CONFIG_SND_SOC_INTEL_BYT_CHT_DA7213_MACH) += snd-soc-sst-byt-cht-da7213.o | 34 | obj-$(CONFIG_SND_SOC_INTEL_BYT_CHT_DA7213_MACH) += snd-soc-sst-byt-cht-da7213.o |
| 35 | obj-$(CONFIG_SND_SOC_INTEL_BYT_CHT_ES8316_MACH) += snd-soc-sst-byt-cht-es8316.o | ||
| 32 | obj-$(CONFIG_SND_SOC_INTEL_BYT_CHT_NOCODEC_MACH) += snd-soc-sst-byt-cht-nocodec.o | 36 | obj-$(CONFIG_SND_SOC_INTEL_BYT_CHT_NOCODEC_MACH) += snd-soc-sst-byt-cht-nocodec.o |
| 37 | obj-$(CONFIG_SND_SOC_INTEL_KBL_RT5663_MAX98927_MACH) += snd-soc-kbl_rt5663_max98927.o | ||
| 38 | obj-$(CONFIG_SND_SOC_INTEL_KBL_RT5663_RT5514_MAX98927_MACH) += snd-soc-kbl_rt5663_rt5514_max98927.o | ||
| 33 | obj-$(CONFIG_SND_SOC_INTEL_SKL_RT286_MACH) += snd-soc-skl_rt286.o | 39 | obj-$(CONFIG_SND_SOC_INTEL_SKL_RT286_MACH) += snd-soc-skl_rt286.o |
| 34 | obj-$(CONFIG_SND_SOC_INTEL_SKL_NAU88L25_MAX98357A_MACH) += snd-skl_nau88l25_max98357a.o | 40 | obj-$(CONFIG_SND_SOC_INTEL_SKL_NAU88L25_MAX98357A_MACH) += snd-skl_nau88l25_max98357a.o |
| 35 | obj-$(CONFIG_SND_SOC_INTEL_SKL_NAU88L25_SSM4567_MACH) += snd-soc-skl_nau88l25_ssm4567.o | 41 | obj-$(CONFIG_SND_SOC_INTEL_SKL_NAU88L25_SSM4567_MACH) += snd-soc-skl_nau88l25_ssm4567.o |
diff --git a/sound/soc/intel/boards/bdw-rt5677.c b/sound/soc/intel/boards/bdw-rt5677.c index 14d9693c1641..058b8ccedf02 100644 --- a/sound/soc/intel/boards/bdw-rt5677.c +++ b/sound/soc/intel/boards/bdw-rt5677.c | |||
| @@ -16,6 +16,7 @@ | |||
| 16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | 16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 17 | */ | 17 | */ |
| 18 | 18 | ||
| 19 | #include <linux/acpi.h> | ||
| 19 | #include <linux/module.h> | 20 | #include <linux/module.h> |
| 20 | #include <linux/platform_device.h> | 21 | #include <linux/platform_device.h> |
| 21 | #include <linux/gpio/consumer.h> | 22 | #include <linux/gpio/consumer.h> |
| @@ -120,6 +121,26 @@ static struct snd_soc_jack_gpio mic_jack_gpio = { | |||
| 120 | .invert = 1, | 121 | .invert = 1, |
| 121 | }; | 122 | }; |
| 122 | 123 | ||
| 124 | /* GPIO indexes defined by ACPI */ | ||
| 125 | enum { | ||
| 126 | RT5677_GPIO_PLUG_DET = 0, | ||
| 127 | RT5677_GPIO_MIC_PRESENT_L = 1, | ||
| 128 | RT5677_GPIO_HOTWORD_DET_L = 2, | ||
| 129 | RT5677_GPIO_DSP_INT = 3, | ||
| 130 | RT5677_GPIO_HP_AMP_SHDN_L = 4, | ||
| 131 | }; | ||
| 132 | |||
| 133 | static const struct acpi_gpio_params plug_det_gpio = { RT5677_GPIO_PLUG_DET, 0, false }; | ||
| 134 | static const struct acpi_gpio_params mic_present_gpio = { RT5677_GPIO_MIC_PRESENT_L, 0, false }; | ||
| 135 | static const struct acpi_gpio_params headphone_enable_gpio = { RT5677_GPIO_HP_AMP_SHDN_L, 0, false }; | ||
| 136 | |||
| 137 | static const struct acpi_gpio_mapping bdw_rt5677_gpios[] = { | ||
| 138 | { "plug-det-gpios", &plug_det_gpio, 1 }, | ||
| 139 | { "mic-present-gpios", &mic_present_gpio, 1 }, | ||
| 140 | { "headphone-enable-gpios", &headphone_enable_gpio, 1 }, | ||
| 141 | { NULL }, | ||
| 142 | }; | ||
| 143 | |||
| 123 | static int broadwell_ssp0_fixup(struct snd_soc_pcm_runtime *rtd, | 144 | static int broadwell_ssp0_fixup(struct snd_soc_pcm_runtime *rtd, |
| 124 | struct snd_pcm_hw_params *params) | 145 | struct snd_pcm_hw_params *params) |
| 125 | { | 146 | { |
| @@ -184,6 +205,11 @@ static int bdw_rt5677_init(struct snd_soc_pcm_runtime *rtd) | |||
| 184 | snd_soc_card_get_drvdata(rtd->card); | 205 | snd_soc_card_get_drvdata(rtd->card); |
| 185 | struct snd_soc_codec *codec = rtd->codec; | 206 | struct snd_soc_codec *codec = rtd->codec; |
| 186 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); | 207 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); |
| 208 | int ret; | ||
| 209 | |||
| 210 | ret = devm_acpi_dev_add_driver_gpios(codec->dev, bdw_rt5677_gpios); | ||
| 211 | if (ret) | ||
| 212 | dev_warn(codec->dev, "Failed to add driver gpios\n"); | ||
| 187 | 213 | ||
| 188 | /* Enable codec ASRC function for Stereo DAC/Stereo1 ADC/DMIC/I2S1. | 214 | /* Enable codec ASRC function for Stereo DAC/Stereo1 ADC/DMIC/I2S1. |
| 189 | * The ASRC clock source is clk_i2s1_asrc. | 215 | * The ASRC clock source is clk_i2s1_asrc. |
diff --git a/sound/soc/intel/boards/bxt_da7219_max98357a.c b/sound/soc/intel/boards/bxt_da7219_max98357a.c index 1866e31b6c29..ce35ec7884d1 100644 --- a/sound/soc/intel/boards/bxt_da7219_max98357a.c +++ b/sound/soc/intel/boards/bxt_da7219_max98357a.c | |||
| @@ -242,31 +242,31 @@ static int broxton_da7219_fe_init(struct snd_soc_pcm_runtime *rtd) | |||
| 242 | return 0; | 242 | return 0; |
| 243 | } | 243 | } |
| 244 | 244 | ||
| 245 | static unsigned int rates[] = { | 245 | static const unsigned int rates[] = { |
| 246 | 48000, | 246 | 48000, |
| 247 | }; | 247 | }; |
| 248 | 248 | ||
| 249 | static struct snd_pcm_hw_constraint_list constraints_rates = { | 249 | static const struct snd_pcm_hw_constraint_list constraints_rates = { |
| 250 | .count = ARRAY_SIZE(rates), | 250 | .count = ARRAY_SIZE(rates), |
| 251 | .list = rates, | 251 | .list = rates, |
| 252 | .mask = 0, | 252 | .mask = 0, |
| 253 | }; | 253 | }; |
| 254 | 254 | ||
| 255 | static unsigned int channels[] = { | 255 | static const unsigned int channels[] = { |
| 256 | DUAL_CHANNEL, | 256 | DUAL_CHANNEL, |
| 257 | }; | 257 | }; |
| 258 | 258 | ||
| 259 | static struct snd_pcm_hw_constraint_list constraints_channels = { | 259 | static const struct snd_pcm_hw_constraint_list constraints_channels = { |
| 260 | .count = ARRAY_SIZE(channels), | 260 | .count = ARRAY_SIZE(channels), |
| 261 | .list = channels, | 261 | .list = channels, |
| 262 | .mask = 0, | 262 | .mask = 0, |
| 263 | }; | 263 | }; |
| 264 | 264 | ||
| 265 | static unsigned int channels_quad[] = { | 265 | static const unsigned int channels_quad[] = { |
| 266 | QUAD_CHANNEL, | 266 | QUAD_CHANNEL, |
| 267 | }; | 267 | }; |
| 268 | 268 | ||
| 269 | static struct snd_pcm_hw_constraint_list constraints_channels_quad = { | 269 | static const struct snd_pcm_hw_constraint_list constraints_channels_quad = { |
| 270 | .count = ARRAY_SIZE(channels_quad), | 270 | .count = ARRAY_SIZE(channels_quad), |
| 271 | .list = channels_quad, | 271 | .list = channels_quad, |
| 272 | .mask = 0, | 272 | .mask = 0, |
diff --git a/sound/soc/intel/boards/bxt_rt298.c b/sound/soc/intel/boards/bxt_rt298.c index 1a68d043c803..0c3a3cbcb884 100644 --- a/sound/soc/intel/boards/bxt_rt298.c +++ b/sound/soc/intel/boards/bxt_rt298.c | |||
| @@ -207,11 +207,11 @@ static const struct snd_soc_ops broxton_rt298_ops = { | |||
| 207 | .hw_params = broxton_rt298_hw_params, | 207 | .hw_params = broxton_rt298_hw_params, |
| 208 | }; | 208 | }; |
| 209 | 209 | ||
| 210 | static unsigned int rates[] = { | 210 | static const unsigned int rates[] = { |
| 211 | 48000, | 211 | 48000, |
| 212 | }; | 212 | }; |
| 213 | 213 | ||
| 214 | static struct snd_pcm_hw_constraint_list constraints_rates = { | 214 | static const struct snd_pcm_hw_constraint_list constraints_rates = { |
| 215 | .count = ARRAY_SIZE(rates), | 215 | .count = ARRAY_SIZE(rates), |
| 216 | .list = rates, | 216 | .list = rates, |
| 217 | .mask = 0, | 217 | .mask = 0, |
| @@ -222,19 +222,16 @@ static int broxton_dmic_fixup(struct snd_soc_pcm_runtime *rtd, | |||
| 222 | { | 222 | { |
| 223 | struct snd_interval *channels = hw_param_interval(params, | 223 | struct snd_interval *channels = hw_param_interval(params, |
| 224 | SNDRV_PCM_HW_PARAM_CHANNELS); | 224 | SNDRV_PCM_HW_PARAM_CHANNELS); |
| 225 | if (params_channels(params) == 2) | 225 | channels->min = channels->max = 4; |
| 226 | channels->min = channels->max = 2; | ||
| 227 | else | ||
| 228 | channels->min = channels->max = 4; | ||
| 229 | 226 | ||
| 230 | return 0; | 227 | return 0; |
| 231 | } | 228 | } |
| 232 | 229 | ||
| 233 | static unsigned int channels_dmic[] = { | 230 | static const unsigned int channels_dmic[] = { |
| 234 | 2, 4, | 231 | 1, 2, 3, 4, |
| 235 | }; | 232 | }; |
| 236 | 233 | ||
| 237 | static struct snd_pcm_hw_constraint_list constraints_dmic_channels = { | 234 | static const struct snd_pcm_hw_constraint_list constraints_dmic_channels = { |
| 238 | .count = ARRAY_SIZE(channels_dmic), | 235 | .count = ARRAY_SIZE(channels_dmic), |
| 239 | .list = channels_dmic, | 236 | .list = channels_dmic, |
| 240 | .mask = 0, | 237 | .mask = 0, |
| @@ -256,11 +253,11 @@ static const struct snd_soc_ops broxton_dmic_ops = { | |||
| 256 | .startup = broxton_dmic_startup, | 253 | .startup = broxton_dmic_startup, |
| 257 | }; | 254 | }; |
| 258 | 255 | ||
| 259 | static unsigned int channels[] = { | 256 | static const unsigned int channels[] = { |
| 260 | 2, | 257 | 2, |
| 261 | }; | 258 | }; |
| 262 | 259 | ||
| 263 | static struct snd_pcm_hw_constraint_list constraints_channels = { | 260 | static const struct snd_pcm_hw_constraint_list constraints_channels = { |
| 264 | .count = ARRAY_SIZE(channels), | 261 | .count = ARRAY_SIZE(channels), |
| 265 | .list = channels, | 262 | .list = channels, |
| 266 | .mask = 0, | 263 | .mask = 0, |
diff --git a/sound/soc/intel/boards/byt-max98090.c b/sound/soc/intel/boards/byt-max98090.c index d9f81b8d915d..047be7fa0ce9 100644 --- a/sound/soc/intel/boards/byt-max98090.c +++ b/sound/soc/intel/boards/byt-max98090.c | |||
| @@ -67,20 +67,27 @@ static struct snd_soc_jack_pin hs_jack_pins[] = { | |||
| 67 | 67 | ||
| 68 | static struct snd_soc_jack_gpio hs_jack_gpios[] = { | 68 | static struct snd_soc_jack_gpio hs_jack_gpios[] = { |
| 69 | { | 69 | { |
| 70 | .name = "hp-gpio", | 70 | .name = "hp", |
| 71 | .idx = 0, | ||
| 72 | .report = SND_JACK_HEADPHONE | SND_JACK_LINEOUT, | 71 | .report = SND_JACK_HEADPHONE | SND_JACK_LINEOUT, |
| 73 | .debounce_time = 200, | 72 | .debounce_time = 200, |
| 74 | }, | 73 | }, |
| 75 | { | 74 | { |
| 76 | .name = "mic-gpio", | 75 | .name = "mic", |
| 77 | .idx = 1, | ||
| 78 | .invert = 1, | 76 | .invert = 1, |
| 79 | .report = SND_JACK_MICROPHONE, | 77 | .report = SND_JACK_MICROPHONE, |
| 80 | .debounce_time = 200, | 78 | .debounce_time = 200, |
| 81 | }, | 79 | }, |
| 82 | }; | 80 | }; |
| 83 | 81 | ||
| 82 | static const struct acpi_gpio_params hp_gpios = { 0, 0, false }; | ||
| 83 | static const struct acpi_gpio_params mic_gpios = { 1, 0, false }; | ||
| 84 | |||
| 85 | static const struct acpi_gpio_mapping acpi_byt_max98090_gpios[] = { | ||
| 86 | { "hp-gpios", &hp_gpios, 1 }, | ||
| 87 | { "mic-gpios", &mic_gpios, 1 }, | ||
| 88 | {}, | ||
| 89 | }; | ||
| 90 | |||
| 84 | static int byt_max98090_init(struct snd_soc_pcm_runtime *runtime) | 91 | static int byt_max98090_init(struct snd_soc_pcm_runtime *runtime) |
| 85 | { | 92 | { |
| 86 | int ret; | 93 | int ret; |
| @@ -140,8 +147,9 @@ static struct snd_soc_card byt_max98090_card = { | |||
| 140 | 147 | ||
| 141 | static int byt_max98090_probe(struct platform_device *pdev) | 148 | static int byt_max98090_probe(struct platform_device *pdev) |
| 142 | { | 149 | { |
| 143 | int ret_val = 0; | 150 | struct device *dev = &pdev->dev; |
| 144 | struct byt_max98090_private *priv; | 151 | struct byt_max98090_private *priv; |
| 152 | int ret_val; | ||
| 145 | 153 | ||
| 146 | priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_ATOMIC); | 154 | priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_ATOMIC); |
| 147 | if (!priv) { | 155 | if (!priv) { |
| @@ -149,6 +157,10 @@ static int byt_max98090_probe(struct platform_device *pdev) | |||
| 149 | return -ENOMEM; | 157 | return -ENOMEM; |
| 150 | } | 158 | } |
| 151 | 159 | ||
| 160 | ret_val = devm_acpi_dev_add_driver_gpios(dev->parent, acpi_byt_max98090_gpios); | ||
| 161 | if (ret_val) | ||
| 162 | dev_dbg(dev, "Unable to add GPIO mapping table\n"); | ||
| 163 | |||
| 152 | byt_max98090_card.dev = &pdev->dev; | 164 | byt_max98090_card.dev = &pdev->dev; |
| 153 | snd_soc_card_set_drvdata(&byt_max98090_card, priv); | 165 | snd_soc_card_set_drvdata(&byt_max98090_card, priv); |
| 154 | ret_val = devm_snd_soc_register_card(&pdev->dev, &byt_max98090_card); | 166 | ret_val = devm_snd_soc_register_card(&pdev->dev, &byt_max98090_card); |
| @@ -158,7 +170,7 @@ static int byt_max98090_probe(struct platform_device *pdev) | |||
| 158 | return ret_val; | 170 | return ret_val; |
| 159 | } | 171 | } |
| 160 | 172 | ||
| 161 | return ret_val; | 173 | return 0; |
| 162 | } | 174 | } |
| 163 | 175 | ||
| 164 | static int byt_max98090_remove(struct platform_device *pdev) | 176 | static int byt_max98090_remove(struct platform_device *pdev) |
diff --git a/sound/soc/intel/boards/bytcht_es8316.c b/sound/soc/intel/boards/bytcht_es8316.c new file mode 100644 index 000000000000..52635462dac6 --- /dev/null +++ b/sound/soc/intel/boards/bytcht_es8316.c | |||
| @@ -0,0 +1,300 @@ | |||
| 1 | /* | ||
| 2 | * bytcht_es8316.c - ASoc Machine driver for Intel Baytrail/Cherrytrail | ||
| 3 | * platforms with Everest ES8316 SoC | ||
| 4 | * | ||
| 5 | * Copyright (C) 2017 Endless Mobile, Inc. | ||
| 6 | * Authors: David Yang <yangxiaohua@everest-semi.com>, | ||
| 7 | * Daniel Drake <drake@endlessm.com> | ||
| 8 | * | ||
| 9 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
| 10 | * | ||
| 11 | * This program is free software; you can redistribute it and/or modify | ||
| 12 | * it under the terms of the GNU General Public License as published by | ||
| 13 | * the Free Software Foundation; version 2 of the License. | ||
| 14 | * | ||
| 15 | * This program is distributed in the hope that it will be useful, but | ||
| 16 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 18 | * General Public License for more details. | ||
| 19 | * | ||
| 20 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
| 21 | */ | ||
| 22 | #include <linux/init.h> | ||
| 23 | #include <linux/module.h> | ||
| 24 | #include <linux/platform_device.h> | ||
| 25 | #include <linux/device.h> | ||
| 26 | #include <linux/slab.h> | ||
| 27 | #include <asm/platform_sst_audio.h> | ||
| 28 | #include <linux/clk.h> | ||
| 29 | #include <sound/pcm.h> | ||
| 30 | #include <sound/pcm_params.h> | ||
| 31 | #include <sound/soc.h> | ||
| 32 | #include "../atom/sst-atom-controls.h" | ||
| 33 | #include "../common/sst-acpi.h" | ||
| 34 | #include "../common/sst-dsp.h" | ||
| 35 | |||
| 36 | struct byt_cht_es8316_private { | ||
| 37 | struct clk *mclk; | ||
| 38 | }; | ||
| 39 | |||
| 40 | #define CODEC_DAI1 "ES8316 HiFi" | ||
| 41 | |||
| 42 | static inline struct snd_soc_dai *get_codec_dai(struct snd_soc_card *card) | ||
| 43 | { | ||
| 44 | struct snd_soc_pcm_runtime *rtd; | ||
| 45 | |||
| 46 | list_for_each_entry(rtd, &card->rtd_list, list) { | ||
| 47 | if (!strncmp(rtd->codec_dai->name, CODEC_DAI1, | ||
| 48 | strlen(CODEC_DAI1))) | ||
| 49 | return rtd->codec_dai; | ||
| 50 | } | ||
| 51 | return NULL; | ||
| 52 | } | ||
| 53 | |||
| 54 | static const struct snd_soc_dapm_widget byt_cht_es8316_widgets[] = { | ||
| 55 | SND_SOC_DAPM_HP("Headphone", NULL), | ||
| 56 | |||
| 57 | /* | ||
| 58 | * The codec supports two analog microphone inputs. I have only | ||
| 59 | * tested MIC1. A DMIC route could also potentially be added | ||
| 60 | * if such functionality is found on another platform. | ||
| 61 | */ | ||
| 62 | SND_SOC_DAPM_MIC("Microphone 1", NULL), | ||
| 63 | SND_SOC_DAPM_MIC("Microphone 2", NULL), | ||
| 64 | }; | ||
| 65 | |||
| 66 | static const struct snd_soc_dapm_route byt_cht_es8316_audio_map[] = { | ||
| 67 | {"MIC1", NULL, "Microphone 1"}, | ||
| 68 | {"MIC2", NULL, "Microphone 2"}, | ||
| 69 | |||
| 70 | {"Headphone", NULL, "HPOL"}, | ||
| 71 | {"Headphone", NULL, "HPOR"}, | ||
| 72 | |||
| 73 | {"Playback", NULL, "ssp2 Tx"}, | ||
| 74 | {"ssp2 Tx", NULL, "codec_out0"}, | ||
| 75 | {"ssp2 Tx", NULL, "codec_out1"}, | ||
| 76 | {"codec_in0", NULL, "ssp2 Rx" }, | ||
| 77 | {"codec_in1", NULL, "ssp2 Rx" }, | ||
| 78 | {"ssp2 Rx", NULL, "Capture"}, | ||
| 79 | }; | ||
| 80 | |||
| 81 | static const struct snd_kcontrol_new byt_cht_es8316_controls[] = { | ||
| 82 | SOC_DAPM_PIN_SWITCH("Headphone"), | ||
| 83 | SOC_DAPM_PIN_SWITCH("Microphone 1"), | ||
| 84 | SOC_DAPM_PIN_SWITCH("Microphone 2"), | ||
| 85 | }; | ||
| 86 | |||
| 87 | static int byt_cht_es8316_init(struct snd_soc_pcm_runtime *runtime) | ||
| 88 | { | ||
| 89 | struct snd_soc_card *card = runtime->card; | ||
| 90 | struct byt_cht_es8316_private *priv = snd_soc_card_get_drvdata(card); | ||
| 91 | int ret; | ||
| 92 | |||
| 93 | card->dapm.idle_bias_off = true; | ||
| 94 | |||
| 95 | /* | ||
| 96 | * The firmware might enable the clock at boot (this information | ||
| 97 | * may or may not be reflected in the enable clock register). | ||
| 98 | * To change the rate we must disable the clock first to cover these | ||
| 99 | * cases. Due to common clock framework restrictions that do not allow | ||
| 100 | * to disable a clock that has not been enabled, we need to enable | ||
| 101 | * the clock first. | ||
| 102 | */ | ||
| 103 | ret = clk_prepare_enable(priv->mclk); | ||
| 104 | if (!ret) | ||
| 105 | clk_disable_unprepare(priv->mclk); | ||
| 106 | |||
| 107 | ret = clk_set_rate(priv->mclk, 19200000); | ||
| 108 | if (ret) | ||
| 109 | dev_err(card->dev, "unable to set MCLK rate\n"); | ||
| 110 | |||
| 111 | ret = clk_prepare_enable(priv->mclk); | ||
| 112 | if (ret) | ||
| 113 | dev_err(card->dev, "unable to enable MCLK\n"); | ||
| 114 | |||
| 115 | ret = snd_soc_dai_set_sysclk(runtime->codec_dai, 0, 19200000, | ||
| 116 | SND_SOC_CLOCK_IN); | ||
| 117 | if (ret < 0) { | ||
| 118 | dev_err(card->dev, "can't set codec clock %d\n", ret); | ||
| 119 | return ret; | ||
| 120 | } | ||
| 121 | |||
| 122 | return 0; | ||
| 123 | } | ||
| 124 | |||
| 125 | static const struct snd_soc_pcm_stream byt_cht_es8316_dai_params = { | ||
| 126 | .formats = SNDRV_PCM_FMTBIT_S24_LE, | ||
| 127 | .rate_min = 48000, | ||
| 128 | .rate_max = 48000, | ||
| 129 | .channels_min = 2, | ||
| 130 | .channels_max = 2, | ||
| 131 | }; | ||
| 132 | |||
| 133 | static int byt_cht_es8316_codec_fixup(struct snd_soc_pcm_runtime *rtd, | ||
| 134 | struct snd_pcm_hw_params *params) | ||
| 135 | { | ||
| 136 | struct snd_interval *rate = hw_param_interval(params, | ||
| 137 | SNDRV_PCM_HW_PARAM_RATE); | ||
| 138 | struct snd_interval *channels = hw_param_interval(params, | ||
| 139 | SNDRV_PCM_HW_PARAM_CHANNELS); | ||
| 140 | int ret; | ||
| 141 | |||
| 142 | /* The DSP will covert the FE rate to 48k, stereo */ | ||
| 143 | rate->min = rate->max = 48000; | ||
| 144 | channels->min = channels->max = 2; | ||
| 145 | |||
| 146 | /* set SSP2 to 24-bit */ | ||
| 147 | params_set_format(params, SNDRV_PCM_FORMAT_S24_LE); | ||
| 148 | |||
| 149 | /* | ||
| 150 | * Default mode for SSP configuration is TDM 4 slot, override config | ||
| 151 | * with explicit setting to I2S 2ch 24-bit. The word length is set with | ||
| 152 | * dai_set_tdm_slot() since there is no other API exposed | ||
| 153 | */ | ||
| 154 | ret = snd_soc_dai_set_fmt(rtd->cpu_dai, | ||
| 155 | SND_SOC_DAIFMT_I2S | | ||
| 156 | SND_SOC_DAIFMT_NB_NF | | ||
| 157 | SND_SOC_DAIFMT_CBS_CFS | ||
| 158 | ); | ||
| 159 | if (ret < 0) { | ||
| 160 | dev_err(rtd->dev, "can't set format to I2S, err %d\n", ret); | ||
| 161 | return ret; | ||
| 162 | } | ||
| 163 | |||
| 164 | ret = snd_soc_dai_set_tdm_slot(rtd->cpu_dai, 0x3, 0x3, 2, 24); | ||
| 165 | if (ret < 0) { | ||
| 166 | dev_err(rtd->dev, "can't set I2S config, err %d\n", ret); | ||
| 167 | return ret; | ||
| 168 | } | ||
| 169 | |||
| 170 | return 0; | ||
| 171 | } | ||
| 172 | |||
| 173 | static int byt_cht_es8316_aif1_startup(struct snd_pcm_substream *substream) | ||
| 174 | { | ||
| 175 | return snd_pcm_hw_constraint_single(substream->runtime, | ||
| 176 | SNDRV_PCM_HW_PARAM_RATE, 48000); | ||
| 177 | } | ||
| 178 | |||
| 179 | static const struct snd_soc_ops byt_cht_es8316_aif1_ops = { | ||
| 180 | .startup = byt_cht_es8316_aif1_startup, | ||
| 181 | }; | ||
| 182 | |||
| 183 | static struct snd_soc_dai_link byt_cht_es8316_dais[] = { | ||
| 184 | [MERR_DPCM_AUDIO] = { | ||
| 185 | .name = "Audio Port", | ||
| 186 | .stream_name = "Audio", | ||
| 187 | .cpu_dai_name = "media-cpu-dai", | ||
| 188 | .codec_dai_name = "snd-soc-dummy-dai", | ||
| 189 | .codec_name = "snd-soc-dummy", | ||
| 190 | .platform_name = "sst-mfld-platform", | ||
| 191 | .nonatomic = true, | ||
| 192 | .dynamic = 1, | ||
| 193 | .dpcm_playback = 1, | ||
| 194 | .dpcm_capture = 1, | ||
| 195 | .ops = &byt_cht_es8316_aif1_ops, | ||
| 196 | }, | ||
| 197 | |||
| 198 | [MERR_DPCM_DEEP_BUFFER] = { | ||
| 199 | .name = "Deep-Buffer Audio Port", | ||
| 200 | .stream_name = "Deep-Buffer Audio", | ||
| 201 | .cpu_dai_name = "deepbuffer-cpu-dai", | ||
| 202 | .codec_dai_name = "snd-soc-dummy-dai", | ||
| 203 | .codec_name = "snd-soc-dummy", | ||
| 204 | .platform_name = "sst-mfld-platform", | ||
| 205 | .nonatomic = true, | ||
| 206 | .dynamic = 1, | ||
| 207 | .dpcm_playback = 1, | ||
| 208 | .ops = &byt_cht_es8316_aif1_ops, | ||
| 209 | }, | ||
| 210 | |||
| 211 | [MERR_DPCM_COMPR] = { | ||
| 212 | .name = "Compressed Port", | ||
| 213 | .stream_name = "Compress", | ||
| 214 | .cpu_dai_name = "compress-cpu-dai", | ||
| 215 | .codec_dai_name = "snd-soc-dummy-dai", | ||
| 216 | .codec_name = "snd-soc-dummy", | ||
| 217 | .platform_name = "sst-mfld-platform", | ||
| 218 | }, | ||
| 219 | |||
| 220 | /* back ends */ | ||
| 221 | { | ||
| 222 | /* Only SSP2 has been tested here, so BYT-CR platforms that | ||
| 223 | * require SSP0 will not work. | ||
| 224 | */ | ||
| 225 | .name = "SSP2-Codec", | ||
| 226 | .id = 1, | ||
| 227 | .cpu_dai_name = "ssp2-port", | ||
| 228 | .platform_name = "sst-mfld-platform", | ||
| 229 | .no_pcm = 1, | ||
| 230 | .codec_dai_name = "ES8316 HiFi", | ||
| 231 | .codec_name = "i2c-ESSX8316:00", | ||
| 232 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | ||
| 233 | | SND_SOC_DAIFMT_CBS_CFS, | ||
| 234 | .be_hw_params_fixup = byt_cht_es8316_codec_fixup, | ||
| 235 | .nonatomic = true, | ||
| 236 | .dpcm_playback = 1, | ||
| 237 | .dpcm_capture = 1, | ||
| 238 | .init = byt_cht_es8316_init, | ||
| 239 | }, | ||
| 240 | }; | ||
| 241 | |||
| 242 | |||
| 243 | /* SoC card */ | ||
| 244 | static struct snd_soc_card byt_cht_es8316_card = { | ||
| 245 | .name = "bytcht-es8316", | ||
| 246 | .owner = THIS_MODULE, | ||
| 247 | .dai_link = byt_cht_es8316_dais, | ||
| 248 | .num_links = ARRAY_SIZE(byt_cht_es8316_dais), | ||
| 249 | .dapm_widgets = byt_cht_es8316_widgets, | ||
| 250 | .num_dapm_widgets = ARRAY_SIZE(byt_cht_es8316_widgets), | ||
| 251 | .dapm_routes = byt_cht_es8316_audio_map, | ||
| 252 | .num_dapm_routes = ARRAY_SIZE(byt_cht_es8316_audio_map), | ||
| 253 | .controls = byt_cht_es8316_controls, | ||
| 254 | .num_controls = ARRAY_SIZE(byt_cht_es8316_controls), | ||
| 255 | .fully_routed = true, | ||
| 256 | }; | ||
| 257 | |||
| 258 | static int snd_byt_cht_es8316_mc_probe(struct platform_device *pdev) | ||
| 259 | { | ||
| 260 | int ret = 0; | ||
| 261 | struct byt_cht_es8316_private *priv; | ||
| 262 | |||
| 263 | priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_ATOMIC); | ||
| 264 | if (!priv) | ||
| 265 | return -ENOMEM; | ||
| 266 | |||
| 267 | /* register the soc card */ | ||
| 268 | byt_cht_es8316_card.dev = &pdev->dev; | ||
| 269 | snd_soc_card_set_drvdata(&byt_cht_es8316_card, priv); | ||
| 270 | |||
| 271 | priv->mclk = devm_clk_get(&pdev->dev, "pmc_plt_clk_3"); | ||
| 272 | if (IS_ERR(priv->mclk)) { | ||
| 273 | ret = PTR_ERR(priv->mclk); | ||
| 274 | dev_err(&pdev->dev, | ||
| 275 | "Failed to get MCLK from pmc_plt_clk_3: %d\n", | ||
| 276 | ret); | ||
| 277 | return ret; | ||
| 278 | } | ||
| 279 | |||
| 280 | ret = devm_snd_soc_register_card(&pdev->dev, &byt_cht_es8316_card); | ||
| 281 | if (ret) { | ||
| 282 | dev_err(&pdev->dev, "snd_soc_register_card failed %d\n", ret); | ||
| 283 | return ret; | ||
| 284 | } | ||
| 285 | platform_set_drvdata(pdev, &byt_cht_es8316_card); | ||
| 286 | return ret; | ||
| 287 | } | ||
| 288 | |||
| 289 | static struct platform_driver snd_byt_cht_es8316_mc_driver = { | ||
| 290 | .driver = { | ||
| 291 | .name = "bytcht_es8316", | ||
| 292 | }, | ||
| 293 | .probe = snd_byt_cht_es8316_mc_probe, | ||
| 294 | }; | ||
| 295 | |||
| 296 | module_platform_driver(snd_byt_cht_es8316_mc_driver); | ||
| 297 | MODULE_DESCRIPTION("ASoC Intel(R) Baytrail/Cherrytrail Machine driver"); | ||
| 298 | MODULE_AUTHOR("David Yang <yangxiaohua@everest-semi.com>"); | ||
| 299 | MODULE_LICENSE("GPL v2"); | ||
| 300 | MODULE_ALIAS("platform:bytcht_es8316"); | ||
diff --git a/sound/soc/intel/boards/bytcht_nocodec.c b/sound/soc/intel/boards/bytcht_nocodec.c index 89853eeaaf9d..1dd9441806fa 100644 --- a/sound/soc/intel/boards/bytcht_nocodec.c +++ b/sound/soc/intel/boards/bytcht_nocodec.c | |||
| @@ -85,11 +85,11 @@ static int codec_fixup(struct snd_soc_pcm_runtime *rtd, | |||
| 85 | return 0; | 85 | return 0; |
| 86 | } | 86 | } |
| 87 | 87 | ||
| 88 | static unsigned int rates_48000[] = { | 88 | static const unsigned int rates_48000[] = { |
| 89 | 48000, | 89 | 48000, |
| 90 | }; | 90 | }; |
| 91 | 91 | ||
| 92 | static struct snd_pcm_hw_constraint_list constraints_48000 = { | 92 | static const struct snd_pcm_hw_constraint_list constraints_48000 = { |
| 93 | .count = ARRAY_SIZE(rates_48000), | 93 | .count = ARRAY_SIZE(rates_48000), |
| 94 | .list = rates_48000, | 94 | .list = rates_48000, |
| 95 | }; | 95 | }; |
diff --git a/sound/soc/intel/boards/bytcr_rt5651.c b/sound/soc/intel/boards/bytcr_rt5651.c index 8164bec63bf1..4a3516b38c2c 100644 --- a/sound/soc/intel/boards/bytcr_rt5651.c +++ b/sound/soc/intel/boards/bytcr_rt5651.c | |||
| @@ -203,11 +203,11 @@ static int byt_rt5651_codec_fixup(struct snd_soc_pcm_runtime *rtd, | |||
| 203 | return 0; | 203 | return 0; |
| 204 | } | 204 | } |
| 205 | 205 | ||
| 206 | static unsigned int rates_48000[] = { | 206 | static const unsigned int rates_48000[] = { |
| 207 | 48000, | 207 | 48000, |
| 208 | }; | 208 | }; |
| 209 | 209 | ||
| 210 | static struct snd_pcm_hw_constraint_list constraints_48000 = { | 210 | static const struct snd_pcm_hw_constraint_list constraints_48000 = { |
| 211 | .count = ARRAY_SIZE(rates_48000), | 211 | .count = ARRAY_SIZE(rates_48000), |
| 212 | .list = rates_48000, | 212 | .list = rates_48000, |
| 213 | }; | 213 | }; |
diff --git a/sound/soc/intel/boards/cht_bsw_max98090_ti.c b/sound/soc/intel/boards/cht_bsw_max98090_ti.c index 742bc0d4e681..20755ecc7f9e 100644 --- a/sound/soc/intel/boards/cht_bsw_max98090_ti.c +++ b/sound/soc/intel/boards/cht_bsw_max98090_ti.c | |||
| @@ -39,18 +39,6 @@ struct cht_mc_private { | |||
| 39 | bool ts3a227e_present; | 39 | bool ts3a227e_present; |
| 40 | }; | 40 | }; |
| 41 | 41 | ||
| 42 | static inline struct snd_soc_dai *cht_get_codec_dai(struct snd_soc_card *card) | ||
| 43 | { | ||
| 44 | struct snd_soc_pcm_runtime *rtd; | ||
| 45 | |||
| 46 | list_for_each_entry(rtd, &card->rtd_list, list) { | ||
| 47 | if (!strncmp(rtd->codec_dai->name, CHT_CODEC_DAI, | ||
| 48 | strlen(CHT_CODEC_DAI))) | ||
| 49 | return rtd->codec_dai; | ||
| 50 | } | ||
| 51 | return NULL; | ||
| 52 | } | ||
| 53 | |||
| 54 | static const struct snd_soc_dapm_widget cht_dapm_widgets[] = { | 42 | static const struct snd_soc_dapm_widget cht_dapm_widgets[] = { |
| 55 | SND_SOC_DAPM_HP("Headphone", NULL), | 43 | SND_SOC_DAPM_HP("Headphone", NULL), |
| 56 | SND_SOC_DAPM_MIC("Headset Mic", NULL), | 44 | SND_SOC_DAPM_MIC("Headset Mic", NULL), |
diff --git a/sound/soc/intel/boards/cht_bsw_rt5672.c b/sound/soc/intel/boards/cht_bsw_rt5672.c index e4d46d4360d7..bc2a52de06a3 100644 --- a/sound/soc/intel/boards/cht_bsw_rt5672.c +++ b/sound/soc/intel/boards/cht_bsw_rt5672.c | |||
| @@ -19,6 +19,8 @@ | |||
| 19 | #include <linux/module.h> | 19 | #include <linux/module.h> |
| 20 | #include <linux/platform_device.h> | 20 | #include <linux/platform_device.h> |
| 21 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
| 22 | #include <linux/clk.h> | ||
| 23 | #include <asm/cpu_device_id.h> | ||
| 22 | #include <sound/pcm.h> | 24 | #include <sound/pcm.h> |
| 23 | #include <sound/pcm_params.h> | 25 | #include <sound/pcm_params.h> |
| 24 | #include <sound/soc.h> | 26 | #include <sound/soc.h> |
| @@ -31,8 +33,11 @@ | |||
| 31 | #define CHT_PLAT_CLK_3_HZ 19200000 | 33 | #define CHT_PLAT_CLK_3_HZ 19200000 |
| 32 | #define CHT_CODEC_DAI "rt5670-aif1" | 34 | #define CHT_CODEC_DAI "rt5670-aif1" |
| 33 | 35 | ||
| 34 | static struct snd_soc_jack cht_bsw_headset; | 36 | struct cht_mc_private { |
| 35 | static char cht_bsw_codec_name[16]; | 37 | struct snd_soc_jack headset; |
| 38 | char codec_name[16]; | ||
| 39 | struct clk *mclk; | ||
| 40 | }; | ||
| 36 | 41 | ||
| 37 | /* Headset jack detection DAPM pins */ | 42 | /* Headset jack detection DAPM pins */ |
| 38 | static struct snd_soc_jack_pin cht_bsw_headset_pins[] = { | 43 | static struct snd_soc_jack_pin cht_bsw_headset_pins[] = { |
| @@ -64,6 +69,7 @@ static int platform_clock_control(struct snd_soc_dapm_widget *w, | |||
| 64 | struct snd_soc_dapm_context *dapm = w->dapm; | 69 | struct snd_soc_dapm_context *dapm = w->dapm; |
| 65 | struct snd_soc_card *card = dapm->card; | 70 | struct snd_soc_card *card = dapm->card; |
| 66 | struct snd_soc_dai *codec_dai; | 71 | struct snd_soc_dai *codec_dai; |
| 72 | struct cht_mc_private *ctx = snd_soc_card_get_drvdata(card); | ||
| 67 | int ret; | 73 | int ret; |
| 68 | 74 | ||
| 69 | codec_dai = cht_get_codec_dai(card); | 75 | codec_dai = cht_get_codec_dai(card); |
| @@ -73,6 +79,15 @@ static int platform_clock_control(struct snd_soc_dapm_widget *w, | |||
| 73 | } | 79 | } |
| 74 | 80 | ||
| 75 | if (SND_SOC_DAPM_EVENT_ON(event)) { | 81 | if (SND_SOC_DAPM_EVENT_ON(event)) { |
| 82 | if (ctx->mclk) { | ||
| 83 | ret = clk_prepare_enable(ctx->mclk); | ||
| 84 | if (ret < 0) { | ||
| 85 | dev_err(card->dev, | ||
| 86 | "could not configure MCLK state"); | ||
| 87 | return ret; | ||
| 88 | } | ||
| 89 | } | ||
| 90 | |||
| 76 | /* set codec PLL source to the 19.2MHz platform clock (MCLK) */ | 91 | /* set codec PLL source to the 19.2MHz platform clock (MCLK) */ |
| 77 | ret = snd_soc_dai_set_pll(codec_dai, 0, RT5670_PLL1_S_MCLK, | 92 | ret = snd_soc_dai_set_pll(codec_dai, 0, RT5670_PLL1_S_MCLK, |
| 78 | CHT_PLAT_CLK_3_HZ, 48000 * 512); | 93 | CHT_PLAT_CLK_3_HZ, 48000 * 512); |
| @@ -96,6 +111,9 @@ static int platform_clock_control(struct snd_soc_dapm_widget *w, | |||
| 96 | */ | 111 | */ |
| 97 | snd_soc_dai_set_sysclk(codec_dai, RT5670_SCLK_S_RCCLK, | 112 | snd_soc_dai_set_sysclk(codec_dai, RT5670_SCLK_S_RCCLK, |
| 98 | 48000 * 512, SND_SOC_CLOCK_IN); | 113 | 48000 * 512, SND_SOC_CLOCK_IN); |
| 114 | |||
| 115 | if (ctx->mclk) | ||
| 116 | clk_disable_unprepare(ctx->mclk); | ||
| 99 | } | 117 | } |
| 100 | return 0; | 118 | return 0; |
| 101 | } | 119 | } |
| @@ -171,6 +189,7 @@ static int cht_codec_init(struct snd_soc_pcm_runtime *runtime) | |||
| 171 | int ret; | 189 | int ret; |
| 172 | struct snd_soc_dai *codec_dai = runtime->codec_dai; | 190 | struct snd_soc_dai *codec_dai = runtime->codec_dai; |
| 173 | struct snd_soc_codec *codec = codec_dai->codec; | 191 | struct snd_soc_codec *codec = codec_dai->codec; |
| 192 | struct cht_mc_private *ctx = snd_soc_card_get_drvdata(runtime->card); | ||
| 174 | 193 | ||
| 175 | /* TDM 4 slots 24 bit, set Rx & Tx bitmask to 4 active slots */ | 194 | /* TDM 4 slots 24 bit, set Rx & Tx bitmask to 4 active slots */ |
| 176 | ret = snd_soc_dai_set_tdm_slot(codec_dai, 0xF, 0xF, 4, 24); | 195 | ret = snd_soc_dai_set_tdm_slot(codec_dai, 0xF, 0xF, 4, 24); |
| @@ -194,13 +213,37 @@ static int cht_codec_init(struct snd_soc_pcm_runtime *runtime) | |||
| 194 | RT5670_CLK_SEL_I2S1_ASRC); | 213 | RT5670_CLK_SEL_I2S1_ASRC); |
| 195 | 214 | ||
| 196 | ret = snd_soc_card_jack_new(runtime->card, "Headset", | 215 | ret = snd_soc_card_jack_new(runtime->card, "Headset", |
| 197 | SND_JACK_HEADSET | SND_JACK_BTN_0 | | 216 | SND_JACK_HEADSET | SND_JACK_BTN_0 | |
| 198 | SND_JACK_BTN_1 | SND_JACK_BTN_2, &cht_bsw_headset, | 217 | SND_JACK_BTN_1 | SND_JACK_BTN_2, |
| 199 | cht_bsw_headset_pins, ARRAY_SIZE(cht_bsw_headset_pins)); | 218 | &ctx->headset, |
| 219 | cht_bsw_headset_pins, | ||
| 220 | ARRAY_SIZE(cht_bsw_headset_pins)); | ||
| 200 | if (ret) | 221 | if (ret) |
| 201 | return ret; | 222 | return ret; |
| 202 | 223 | ||
| 203 | rt5670_set_jack_detect(codec, &cht_bsw_headset); | 224 | rt5670_set_jack_detect(codec, &ctx->headset); |
| 225 | if (ctx->mclk) { | ||
| 226 | /* | ||
| 227 | * The firmware might enable the clock at | ||
| 228 | * boot (this information may or may not | ||
| 229 | * be reflected in the enable clock register). | ||
| 230 | * To change the rate we must disable the clock | ||
| 231 | * first to cover these cases. Due to common | ||
| 232 | * clock framework restrictions that do not allow | ||
| 233 | * to disable a clock that has not been enabled, | ||
| 234 | * we need to enable the clock first. | ||
| 235 | */ | ||
| 236 | ret = clk_prepare_enable(ctx->mclk); | ||
| 237 | if (!ret) | ||
| 238 | clk_disable_unprepare(ctx->mclk); | ||
| 239 | |||
| 240 | ret = clk_set_rate(ctx->mclk, CHT_PLAT_CLK_3_HZ); | ||
| 241 | |||
| 242 | if (ret) { | ||
| 243 | dev_err(runtime->dev, "unable to set MCLK rate\n"); | ||
| 244 | return ret; | ||
| 245 | } | ||
| 246 | } | ||
| 204 | return 0; | 247 | return 0; |
| 205 | } | 248 | } |
| 206 | 249 | ||
| @@ -341,34 +384,62 @@ static struct snd_soc_card snd_soc_card_cht = { | |||
| 341 | .resume_post = cht_resume_post, | 384 | .resume_post = cht_resume_post, |
| 342 | }; | 385 | }; |
| 343 | 386 | ||
| 387 | static bool is_valleyview(void) | ||
| 388 | { | ||
| 389 | static const struct x86_cpu_id cpu_ids[] = { | ||
| 390 | { X86_VENDOR_INTEL, 6, 55 }, /* Valleyview, Bay Trail */ | ||
| 391 | {} | ||
| 392 | }; | ||
| 393 | |||
| 394 | if (!x86_match_cpu(cpu_ids)) | ||
| 395 | return false; | ||
| 396 | return true; | ||
| 397 | } | ||
| 398 | |||
| 344 | #define RT5672_I2C_DEFAULT "i2c-10EC5670:00" | 399 | #define RT5672_I2C_DEFAULT "i2c-10EC5670:00" |
| 345 | 400 | ||
| 346 | static int snd_cht_mc_probe(struct platform_device *pdev) | 401 | static int snd_cht_mc_probe(struct platform_device *pdev) |
| 347 | { | 402 | { |
| 348 | int ret_val = 0; | 403 | int ret_val = 0; |
| 404 | struct cht_mc_private *drv; | ||
| 349 | struct sst_acpi_mach *mach = pdev->dev.platform_data; | 405 | struct sst_acpi_mach *mach = pdev->dev.platform_data; |
| 350 | const char *i2c_name; | 406 | const char *i2c_name; |
| 351 | int i; | 407 | int i; |
| 352 | 408 | ||
| 353 | strcpy(cht_bsw_codec_name, RT5672_I2C_DEFAULT); | 409 | drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_ATOMIC); |
| 410 | if (!drv) | ||
| 411 | return -ENOMEM; | ||
| 412 | |||
| 413 | strcpy(drv->codec_name, RT5672_I2C_DEFAULT); | ||
| 354 | 414 | ||
| 355 | /* fixup codec name based on HID */ | 415 | /* fixup codec name based on HID */ |
| 356 | if (mach) { | 416 | if (mach) { |
| 357 | i2c_name = sst_acpi_find_name_from_hid(mach->id); | 417 | i2c_name = sst_acpi_find_name_from_hid(mach->id); |
| 358 | if (i2c_name) { | 418 | if (i2c_name) { |
| 359 | snprintf(cht_bsw_codec_name, sizeof(cht_bsw_codec_name), | 419 | snprintf(drv->codec_name, sizeof(drv->codec_name), |
| 360 | "i2c-%s", i2c_name); | 420 | "i2c-%s", i2c_name); |
| 361 | for (i = 0; i < ARRAY_SIZE(cht_dailink); i++) { | 421 | for (i = 0; i < ARRAY_SIZE(cht_dailink); i++) { |
| 362 | if (!strcmp(cht_dailink[i].codec_name, | 422 | if (!strcmp(cht_dailink[i].codec_name, |
| 363 | RT5672_I2C_DEFAULT)) { | 423 | RT5672_I2C_DEFAULT)) { |
| 364 | cht_dailink[i].codec_name = | 424 | cht_dailink[i].codec_name = |
| 365 | cht_bsw_codec_name; | 425 | drv->codec_name; |
| 366 | break; | 426 | break; |
| 367 | } | 427 | } |
| 368 | } | 428 | } |
| 369 | } | 429 | } |
| 370 | } | 430 | } |
| 371 | 431 | ||
| 432 | if (is_valleyview()) { | ||
| 433 | drv->mclk = devm_clk_get(&pdev->dev, "pmc_plt_clk_3"); | ||
| 434 | if (IS_ERR(drv->mclk)) { | ||
| 435 | dev_err(&pdev->dev, | ||
| 436 | "Failed to get MCLK from pmc_plt_clk_3: %ld\n", | ||
| 437 | PTR_ERR(drv->mclk)); | ||
| 438 | return PTR_ERR(drv->mclk); | ||
| 439 | } | ||
| 440 | } | ||
| 441 | snd_soc_card_set_drvdata(&snd_soc_card_cht, drv); | ||
| 442 | |||
| 372 | /* register the soc card */ | 443 | /* register the soc card */ |
| 373 | snd_soc_card_cht.dev = &pdev->dev; | 444 | snd_soc_card_cht.dev = &pdev->dev; |
| 374 | ret_val = devm_snd_soc_register_card(&pdev->dev, &snd_soc_card_cht); | 445 | ret_val = devm_snd_soc_register_card(&pdev->dev, &snd_soc_card_cht); |
diff --git a/sound/soc/intel/boards/kbl_rt5663_max98927.c b/sound/soc/intel/boards/kbl_rt5663_max98927.c new file mode 100644 index 000000000000..f9ba97788157 --- /dev/null +++ b/sound/soc/intel/boards/kbl_rt5663_max98927.c | |||
| @@ -0,0 +1,687 @@ | |||
| 1 | /* | ||
| 2 | * Intel Kabylake I2S Machine Driver with MAXIM98927 | ||
| 3 | * and RT5663 Codecs | ||
| 4 | * | ||
| 5 | * Copyright (C) 2017, Intel Corporation. All rights reserved. | ||
| 6 | * | ||
| 7 | * Modified from: | ||
| 8 | * Intel Skylake I2S Machine driver | ||
| 9 | * | ||
| 10 | * This program is free software; you can redistribute it and/or | ||
| 11 | * modify it under the terms of the GNU General Public License version | ||
| 12 | * 2 as published by the Free Software Foundation. | ||
| 13 | * | ||
| 14 | * This program is distributed in the hope that it will be useful, | ||
| 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 17 | * GNU General Public License for more details. | ||
| 18 | */ | ||
| 19 | |||
| 20 | #include <linux/module.h> | ||
| 21 | #include <linux/platform_device.h> | ||
| 22 | #include <sound/core.h> | ||
| 23 | #include <sound/jack.h> | ||
| 24 | #include <sound/pcm.h> | ||
| 25 | #include <sound/pcm_params.h> | ||
| 26 | #include <sound/soc.h> | ||
| 27 | #include "../../codecs/rt5663.h" | ||
| 28 | #include "../../codecs/hdac_hdmi.h" | ||
| 29 | #include "../skylake/skl.h" | ||
| 30 | |||
| 31 | #define KBL_REALTEK_CODEC_DAI "rt5663-aif" | ||
| 32 | #define KBL_MAXIM_CODEC_DAI "max98927-aif1" | ||
| 33 | #define DMIC_CH(p) p->list[p->count-1] | ||
| 34 | #define MAXIM_DEV0_NAME "i2c-MX98927:00" | ||
| 35 | #define MAXIM_DEV1_NAME "i2c-MX98927:01" | ||
| 36 | |||
| 37 | static struct snd_soc_card kabylake_audio_card; | ||
| 38 | static const struct snd_pcm_hw_constraint_list *dmic_constraints; | ||
| 39 | static struct snd_soc_jack skylake_hdmi[3]; | ||
| 40 | |||
| 41 | struct kbl_hdmi_pcm { | ||
| 42 | struct list_head head; | ||
| 43 | struct snd_soc_dai *codec_dai; | ||
| 44 | int device; | ||
| 45 | }; | ||
| 46 | |||
| 47 | struct kbl_rt5663_private { | ||
| 48 | struct snd_soc_jack kabylake_headset; | ||
| 49 | struct list_head hdmi_pcm_list; | ||
| 50 | }; | ||
| 51 | |||
| 52 | enum { | ||
| 53 | KBL_DPCM_AUDIO_PB = 0, | ||
| 54 | KBL_DPCM_AUDIO_CP, | ||
| 55 | KBL_DPCM_AUDIO_REF_CP, | ||
| 56 | KBL_DPCM_AUDIO_DMIC_CP, | ||
| 57 | KBL_DPCM_AUDIO_HDMI1_PB, | ||
| 58 | KBL_DPCM_AUDIO_HDMI2_PB, | ||
| 59 | KBL_DPCM_AUDIO_HDMI3_PB, | ||
| 60 | }; | ||
| 61 | |||
| 62 | static const struct snd_kcontrol_new kabylake_controls[] = { | ||
| 63 | SOC_DAPM_PIN_SWITCH("Headphone Jack"), | ||
| 64 | SOC_DAPM_PIN_SWITCH("Headset Mic"), | ||
| 65 | SOC_DAPM_PIN_SWITCH("Left Spk"), | ||
| 66 | SOC_DAPM_PIN_SWITCH("Right Spk"), | ||
| 67 | }; | ||
| 68 | |||
| 69 | static const struct snd_soc_dapm_widget kabylake_widgets[] = { | ||
| 70 | SND_SOC_DAPM_HP("Headphone Jack", NULL), | ||
| 71 | SND_SOC_DAPM_MIC("Headset Mic", NULL), | ||
| 72 | SND_SOC_DAPM_SPK("Left Spk", NULL), | ||
| 73 | SND_SOC_DAPM_SPK("Right Spk", NULL), | ||
| 74 | SND_SOC_DAPM_MIC("SoC DMIC", NULL), | ||
| 75 | SND_SOC_DAPM_SPK("DP", NULL), | ||
| 76 | SND_SOC_DAPM_SPK("HDMI", NULL), | ||
| 77 | |||
| 78 | }; | ||
| 79 | |||
| 80 | static const struct snd_soc_dapm_route kabylake_map[] = { | ||
| 81 | /* HP jack connectors - unknown if we have jack detection */ | ||
| 82 | { "Headphone Jack", NULL, "HPOL" }, | ||
| 83 | { "Headphone Jack", NULL, "HPOR" }, | ||
| 84 | |||
| 85 | /* speaker */ | ||
| 86 | { "Left Spk", NULL, "Left BE_OUT" }, | ||
| 87 | { "Right Spk", NULL, "Right BE_OUT" }, | ||
| 88 | |||
| 89 | /* other jacks */ | ||
| 90 | { "IN1P", NULL, "Headset Mic" }, | ||
| 91 | { "IN1N", NULL, "Headset Mic" }, | ||
| 92 | { "DMic", NULL, "SoC DMIC" }, | ||
| 93 | |||
| 94 | { "HDMI", NULL, "hif5 Output" }, | ||
| 95 | { "DP", NULL, "hif6 Output" }, | ||
| 96 | |||
| 97 | /* CODEC BE connections */ | ||
| 98 | { "Left HiFi Playback", NULL, "ssp0 Tx" }, | ||
| 99 | { "Right HiFi Playback", NULL, "ssp0 Tx" }, | ||
| 100 | { "ssp0 Tx", NULL, "codec0_out" }, | ||
| 101 | |||
| 102 | { "AIF Playback", NULL, "ssp1 Tx" }, | ||
| 103 | { "ssp1 Tx", NULL, "codec1_out" }, | ||
| 104 | |||
| 105 | { "codec0_in", NULL, "ssp1 Rx" }, | ||
| 106 | { "ssp1 Rx", NULL, "AIF Capture" }, | ||
| 107 | |||
| 108 | /* DMIC */ | ||
| 109 | { "dmic01_hifi", NULL, "DMIC01 Rx" }, | ||
| 110 | { "DMIC01 Rx", NULL, "DMIC AIF" }, | ||
| 111 | |||
| 112 | { "hifi3", NULL, "iDisp3 Tx"}, | ||
| 113 | { "iDisp3 Tx", NULL, "iDisp3_out"}, | ||
| 114 | { "hifi2", NULL, "iDisp2 Tx"}, | ||
| 115 | { "iDisp2 Tx", NULL, "iDisp2_out"}, | ||
| 116 | { "hifi1", NULL, "iDisp1 Tx"}, | ||
| 117 | { "iDisp1 Tx", NULL, "iDisp1_out"}, | ||
| 118 | }; | ||
| 119 | |||
| 120 | static struct snd_soc_codec_conf max98927_codec_conf[] = { | ||
| 121 | { | ||
| 122 | .dev_name = MAXIM_DEV0_NAME, | ||
| 123 | .name_prefix = "Right", | ||
| 124 | }, | ||
| 125 | { | ||
| 126 | .dev_name = MAXIM_DEV1_NAME, | ||
| 127 | .name_prefix = "Left", | ||
| 128 | }, | ||
| 129 | }; | ||
| 130 | |||
| 131 | static struct snd_soc_dai_link_component max98927_codec_components[] = { | ||
| 132 | { /* Left */ | ||
| 133 | .name = MAXIM_DEV0_NAME, | ||
| 134 | .dai_name = KBL_MAXIM_CODEC_DAI, | ||
| 135 | }, | ||
| 136 | { /* Right */ | ||
| 137 | .name = MAXIM_DEV1_NAME, | ||
| 138 | .dai_name = KBL_MAXIM_CODEC_DAI, | ||
| 139 | }, | ||
| 140 | }; | ||
| 141 | |||
| 142 | static int kabylake_rt5663_fe_init(struct snd_soc_pcm_runtime *rtd) | ||
| 143 | { | ||
| 144 | int ret; | ||
| 145 | struct snd_soc_dapm_context *dapm; | ||
| 146 | struct snd_soc_component *component = rtd->cpu_dai->component; | ||
| 147 | |||
| 148 | dapm = snd_soc_component_get_dapm(component); | ||
| 149 | ret = snd_soc_dapm_ignore_suspend(dapm, "Reference Capture"); | ||
| 150 | if (ret) { | ||
| 151 | dev_err(rtd->dev, "Ref Cap ignore suspend failed %d\n", ret); | ||
| 152 | return ret; | ||
| 153 | } | ||
| 154 | |||
| 155 | return ret; | ||
| 156 | } | ||
| 157 | |||
| 158 | static int kabylake_rt5663_codec_init(struct snd_soc_pcm_runtime *rtd) | ||
| 159 | { | ||
| 160 | int ret; | ||
| 161 | struct kbl_rt5663_private *ctx = snd_soc_card_get_drvdata(rtd->card); | ||
| 162 | struct snd_soc_codec *codec = rtd->codec; | ||
| 163 | |||
| 164 | /* | ||
| 165 | * Headset buttons map to the google Reference headset. | ||
| 166 | * These can be configured by userspace. | ||
| 167 | */ | ||
| 168 | ret = snd_soc_card_jack_new(&kabylake_audio_card, "Headset Jack", | ||
| 169 | SND_JACK_HEADSET | SND_JACK_BTN_0 | SND_JACK_BTN_1 | | ||
| 170 | SND_JACK_BTN_2 | SND_JACK_BTN_3, &ctx->kabylake_headset, | ||
| 171 | NULL, 0); | ||
| 172 | if (ret) { | ||
| 173 | dev_err(rtd->dev, "Headset Jack creation failed %d\n", ret); | ||
| 174 | return ret; | ||
| 175 | } | ||
| 176 | |||
| 177 | rt5663_set_jack_detect(codec, &ctx->kabylake_headset); | ||
| 178 | ret = snd_soc_dapm_ignore_suspend(&rtd->card->dapm, "SoC DMIC"); | ||
| 179 | if (ret) { | ||
| 180 | dev_err(rtd->dev, "SoC DMIC ignore suspend failed %d\n", ret); | ||
| 181 | return ret; | ||
| 182 | } | ||
| 183 | |||
| 184 | return ret; | ||
| 185 | } | ||
| 186 | |||
| 187 | static int kabylake_hdmi1_init(struct snd_soc_pcm_runtime *rtd) | ||
| 188 | { | ||
| 189 | struct kbl_rt5663_private *ctx = snd_soc_card_get_drvdata(rtd->card); | ||
| 190 | struct snd_soc_dai *dai = rtd->codec_dai; | ||
| 191 | struct kbl_hdmi_pcm *pcm; | ||
| 192 | |||
| 193 | pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL); | ||
| 194 | if (!pcm) | ||
| 195 | return -ENOMEM; | ||
| 196 | |||
| 197 | pcm->device = KBL_DPCM_AUDIO_HDMI1_PB; | ||
| 198 | pcm->codec_dai = dai; | ||
| 199 | |||
| 200 | list_add_tail(&pcm->head, &ctx->hdmi_pcm_list); | ||
| 201 | |||
| 202 | return 0; | ||
| 203 | } | ||
| 204 | |||
| 205 | static int kabylake_hdmi2_init(struct snd_soc_pcm_runtime *rtd) | ||
| 206 | { | ||
| 207 | struct kbl_rt5663_private *ctx = snd_soc_card_get_drvdata(rtd->card); | ||
| 208 | struct snd_soc_dai *dai = rtd->codec_dai; | ||
| 209 | struct kbl_hdmi_pcm *pcm; | ||
| 210 | |||
| 211 | pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL); | ||
| 212 | if (!pcm) | ||
| 213 | return -ENOMEM; | ||
| 214 | |||
| 215 | pcm->device = KBL_DPCM_AUDIO_HDMI2_PB; | ||
| 216 | pcm->codec_dai = dai; | ||
| 217 | |||
| 218 | list_add_tail(&pcm->head, &ctx->hdmi_pcm_list); | ||
| 219 | |||
| 220 | return 0; | ||
| 221 | } | ||
| 222 | |||
| 223 | static int kabylake_hdmi3_init(struct snd_soc_pcm_runtime *rtd) | ||
| 224 | { | ||
| 225 | struct kbl_rt5663_private *ctx = snd_soc_card_get_drvdata(rtd->card); | ||
| 226 | struct snd_soc_dai *dai = rtd->codec_dai; | ||
| 227 | struct kbl_hdmi_pcm *pcm; | ||
| 228 | |||
| 229 | pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL); | ||
| 230 | if (!pcm) | ||
| 231 | return -ENOMEM; | ||
| 232 | |||
| 233 | pcm->device = KBL_DPCM_AUDIO_HDMI3_PB; | ||
| 234 | pcm->codec_dai = dai; | ||
| 235 | |||
| 236 | list_add_tail(&pcm->head, &ctx->hdmi_pcm_list); | ||
| 237 | |||
| 238 | return 0; | ||
| 239 | } | ||
| 240 | |||
| 241 | static unsigned int rates[] = { | ||
| 242 | 48000, | ||
| 243 | }; | ||
| 244 | |||
| 245 | static struct snd_pcm_hw_constraint_list constraints_rates = { | ||
| 246 | .count = ARRAY_SIZE(rates), | ||
| 247 | .list = rates, | ||
| 248 | .mask = 0, | ||
| 249 | }; | ||
| 250 | |||
| 251 | static unsigned int channels[] = { | ||
| 252 | 2, | ||
| 253 | }; | ||
| 254 | |||
| 255 | static struct snd_pcm_hw_constraint_list constraints_channels = { | ||
| 256 | .count = ARRAY_SIZE(channels), | ||
| 257 | .list = channels, | ||
| 258 | .mask = 0, | ||
| 259 | }; | ||
| 260 | |||
| 261 | static int kbl_fe_startup(struct snd_pcm_substream *substream) | ||
| 262 | { | ||
| 263 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
| 264 | |||
| 265 | /* | ||
| 266 | * On this platform for PCM device we support, | ||
| 267 | * 48Khz | ||
| 268 | * stereo | ||
| 269 | * 16 bit audio | ||
| 270 | */ | ||
| 271 | |||
| 272 | runtime->hw.channels_max = 2; | ||
| 273 | snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, | ||
| 274 | &constraints_channels); | ||
| 275 | |||
| 276 | runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE; | ||
| 277 | snd_pcm_hw_constraint_msbits(runtime, 0, 16, 16); | ||
| 278 | |||
| 279 | snd_pcm_hw_constraint_list(runtime, 0, | ||
| 280 | SNDRV_PCM_HW_PARAM_RATE, &constraints_rates); | ||
| 281 | |||
| 282 | return 0; | ||
| 283 | } | ||
| 284 | |||
| 285 | static const struct snd_soc_ops kabylake_rt5663_fe_ops = { | ||
| 286 | .startup = kbl_fe_startup, | ||
| 287 | }; | ||
| 288 | |||
| 289 | static int kabylake_ssp_fixup(struct snd_soc_pcm_runtime *rtd, | ||
| 290 | struct snd_pcm_hw_params *params) | ||
| 291 | { | ||
| 292 | struct snd_interval *rate = hw_param_interval(params, | ||
| 293 | SNDRV_PCM_HW_PARAM_RATE); | ||
| 294 | struct snd_interval *channels = hw_param_interval(params, | ||
| 295 | SNDRV_PCM_HW_PARAM_CHANNELS); | ||
| 296 | struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); | ||
| 297 | |||
| 298 | /* The ADSP will convert the FE rate to 48k, stereo */ | ||
| 299 | rate->min = rate->max = 48000; | ||
| 300 | channels->min = channels->max = 2; | ||
| 301 | /* set SSP1 to 24 bit */ | ||
| 302 | snd_mask_none(fmt); | ||
| 303 | snd_mask_set(fmt, SNDRV_PCM_FORMAT_S24_LE); | ||
| 304 | |||
| 305 | return 0; | ||
| 306 | } | ||
| 307 | |||
| 308 | static int kabylake_rt5663_hw_params(struct snd_pcm_substream *substream, | ||
| 309 | struct snd_pcm_hw_params *params) | ||
| 310 | { | ||
| 311 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
| 312 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
| 313 | int ret; | ||
| 314 | |||
| 315 | ret = snd_soc_dai_set_sysclk(codec_dai, | ||
| 316 | RT5663_SCLK_S_MCLK, 24576000, SND_SOC_CLOCK_IN); | ||
| 317 | /* use ASRC for internal clocks, as PLL rate isn't multiple of BCLK */ | ||
| 318 | rt5663_sel_asrc_clk_src(codec_dai->codec, RT5663_DA_STEREO_FILTER, 1); | ||
| 319 | |||
| 320 | if (ret < 0) | ||
| 321 | dev_err(rtd->dev, "snd_soc_dai_set_sysclk err = %d\n", ret); | ||
| 322 | |||
| 323 | return ret; | ||
| 324 | } | ||
| 325 | |||
| 326 | static struct snd_soc_ops kabylake_rt5663_ops = { | ||
| 327 | .hw_params = kabylake_rt5663_hw_params, | ||
| 328 | }; | ||
| 329 | |||
| 330 | static int kabylake_dmic_fixup(struct snd_soc_pcm_runtime *rtd, | ||
| 331 | struct snd_pcm_hw_params *params) | ||
| 332 | { | ||
| 333 | struct snd_interval *channels = hw_param_interval(params, | ||
| 334 | SNDRV_PCM_HW_PARAM_CHANNELS); | ||
| 335 | |||
| 336 | if (params_channels(params) == 2 || DMIC_CH(dmic_constraints) == 2) | ||
| 337 | channels->min = channels->max = 2; | ||
| 338 | else | ||
| 339 | channels->min = channels->max = 4; | ||
| 340 | |||
| 341 | return 0; | ||
| 342 | } | ||
| 343 | |||
| 344 | static unsigned int channels_dmic[] = { | ||
| 345 | 2, 4, | ||
| 346 | }; | ||
| 347 | |||
| 348 | static struct snd_pcm_hw_constraint_list constraints_dmic_channels = { | ||
| 349 | .count = ARRAY_SIZE(channels_dmic), | ||
| 350 | .list = channels_dmic, | ||
| 351 | .mask = 0, | ||
| 352 | }; | ||
| 353 | |||
| 354 | static const unsigned int dmic_2ch[] = { | ||
| 355 | 2, | ||
| 356 | }; | ||
| 357 | |||
| 358 | static const struct snd_pcm_hw_constraint_list constraints_dmic_2ch = { | ||
| 359 | .count = ARRAY_SIZE(dmic_2ch), | ||
| 360 | .list = dmic_2ch, | ||
| 361 | .mask = 0, | ||
| 362 | }; | ||
| 363 | |||
| 364 | static int kabylake_dmic_startup(struct snd_pcm_substream *substream) | ||
| 365 | { | ||
| 366 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
| 367 | |||
| 368 | runtime->hw.channels_max = DMIC_CH(dmic_constraints); | ||
| 369 | snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, | ||
| 370 | dmic_constraints); | ||
| 371 | |||
| 372 | return snd_pcm_hw_constraint_list(substream->runtime, 0, | ||
| 373 | SNDRV_PCM_HW_PARAM_RATE, &constraints_rates); | ||
| 374 | } | ||
| 375 | |||
| 376 | static struct snd_soc_ops kabylake_dmic_ops = { | ||
| 377 | .startup = kabylake_dmic_startup, | ||
| 378 | }; | ||
| 379 | |||
| 380 | static unsigned int rates_16000[] = { | ||
| 381 | 16000, | ||
| 382 | }; | ||
| 383 | |||
| 384 | static struct snd_pcm_hw_constraint_list constraints_16000 = { | ||
| 385 | .count = ARRAY_SIZE(rates_16000), | ||
| 386 | .list = rates_16000, | ||
| 387 | }; | ||
| 388 | |||
| 389 | static const unsigned int ch_mono[] = { | ||
| 390 | 1, | ||
| 391 | }; | ||
| 392 | |||
| 393 | static const struct snd_pcm_hw_constraint_list constraints_refcap = { | ||
| 394 | .count = ARRAY_SIZE(ch_mono), | ||
| 395 | .list = ch_mono, | ||
| 396 | }; | ||
| 397 | |||
| 398 | static int kabylake_refcap_startup(struct snd_pcm_substream *substream) | ||
| 399 | { | ||
| 400 | substream->runtime->hw.channels_max = 1; | ||
| 401 | snd_pcm_hw_constraint_list(substream->runtime, 0, | ||
| 402 | SNDRV_PCM_HW_PARAM_CHANNELS, | ||
| 403 | &constraints_refcap); | ||
| 404 | |||
| 405 | return snd_pcm_hw_constraint_list(substream->runtime, 0, | ||
| 406 | SNDRV_PCM_HW_PARAM_RATE, | ||
| 407 | &constraints_16000); | ||
| 408 | } | ||
| 409 | |||
| 410 | static struct snd_soc_ops skylaye_refcap_ops = { | ||
| 411 | .startup = kabylake_refcap_startup, | ||
| 412 | }; | ||
| 413 | |||
| 414 | /* kabylake digital audio interface glue - connects codec <--> CPU */ | ||
| 415 | static struct snd_soc_dai_link kabylake_dais[] = { | ||
| 416 | /* Front End DAI links */ | ||
| 417 | [KBL_DPCM_AUDIO_PB] = { | ||
| 418 | .name = "Kbl Audio Port", | ||
| 419 | .stream_name = "Audio", | ||
| 420 | .cpu_dai_name = "System Pin", | ||
| 421 | .platform_name = "0000:00:1f.3", | ||
| 422 | .dynamic = 1, | ||
| 423 | .codec_name = "snd-soc-dummy", | ||
| 424 | .codec_dai_name = "snd-soc-dummy-dai", | ||
| 425 | .nonatomic = 1, | ||
| 426 | .init = kabylake_rt5663_fe_init, | ||
| 427 | .trigger = { | ||
| 428 | SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, | ||
| 429 | .dpcm_playback = 1, | ||
| 430 | .ops = &kabylake_rt5663_fe_ops, | ||
| 431 | }, | ||
| 432 | [KBL_DPCM_AUDIO_CP] = { | ||
| 433 | .name = "Kbl Audio Capture Port", | ||
| 434 | .stream_name = "Audio Record", | ||
| 435 | .cpu_dai_name = "System Pin", | ||
| 436 | .platform_name = "0000:00:1f.3", | ||
| 437 | .dynamic = 1, | ||
| 438 | .codec_name = "snd-soc-dummy", | ||
| 439 | .codec_dai_name = "snd-soc-dummy-dai", | ||
| 440 | .nonatomic = 1, | ||
| 441 | .trigger = { | ||
| 442 | SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, | ||
| 443 | .dpcm_capture = 1, | ||
| 444 | .ops = &kabylake_rt5663_fe_ops, | ||
| 445 | }, | ||
| 446 | [KBL_DPCM_AUDIO_REF_CP] = { | ||
| 447 | .name = "Kbl Audio Reference cap", | ||
| 448 | .stream_name = "Wake on Voice", | ||
| 449 | .cpu_dai_name = "Reference Pin", | ||
| 450 | .codec_name = "snd-soc-dummy", | ||
| 451 | .codec_dai_name = "snd-soc-dummy-dai", | ||
| 452 | .platform_name = "0000:00:1f.3", | ||
| 453 | .init = NULL, | ||
| 454 | .dpcm_capture = 1, | ||
| 455 | .nonatomic = 1, | ||
| 456 | .dynamic = 1, | ||
| 457 | .ops = &skylaye_refcap_ops, | ||
| 458 | }, | ||
| 459 | [KBL_DPCM_AUDIO_DMIC_CP] = { | ||
| 460 | .name = "Kbl Audio DMIC cap", | ||
| 461 | .stream_name = "dmiccap", | ||
| 462 | .cpu_dai_name = "DMIC Pin", | ||
| 463 | .codec_name = "snd-soc-dummy", | ||
| 464 | .codec_dai_name = "snd-soc-dummy-dai", | ||
| 465 | .platform_name = "0000:00:1f.3", | ||
| 466 | .init = NULL, | ||
| 467 | .dpcm_capture = 1, | ||
| 468 | .nonatomic = 1, | ||
| 469 | .dynamic = 1, | ||
| 470 | .ops = &kabylake_dmic_ops, | ||
| 471 | }, | ||
| 472 | [KBL_DPCM_AUDIO_HDMI1_PB] = { | ||
| 473 | .name = "Kbl HDMI Port1", | ||
| 474 | .stream_name = "Hdmi1", | ||
| 475 | .cpu_dai_name = "HDMI1 Pin", | ||
| 476 | .codec_name = "snd-soc-dummy", | ||
| 477 | .codec_dai_name = "snd-soc-dummy-dai", | ||
| 478 | .platform_name = "0000:00:1f.3", | ||
| 479 | .dpcm_playback = 1, | ||
| 480 | .init = NULL, | ||
| 481 | .trigger = { | ||
| 482 | SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, | ||
| 483 | .nonatomic = 1, | ||
| 484 | .dynamic = 1, | ||
| 485 | }, | ||
| 486 | [KBL_DPCM_AUDIO_HDMI2_PB] = { | ||
| 487 | .name = "Kbl HDMI Port2", | ||
| 488 | .stream_name = "Hdmi2", | ||
| 489 | .cpu_dai_name = "HDMI2 Pin", | ||
| 490 | .codec_name = "snd-soc-dummy", | ||
| 491 | .codec_dai_name = "snd-soc-dummy-dai", | ||
| 492 | .platform_name = "0000:00:1f.3", | ||
| 493 | .dpcm_playback = 1, | ||
| 494 | .init = NULL, | ||
| 495 | .trigger = { | ||
| 496 | SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, | ||
| 497 | .nonatomic = 1, | ||
| 498 | .dynamic = 1, | ||
| 499 | }, | ||
| 500 | [KBL_DPCM_AUDIO_HDMI3_PB] = { | ||
| 501 | .name = "Kbl HDMI Port3", | ||
| 502 | .stream_name = "Hdmi3", | ||
| 503 | .cpu_dai_name = "HDMI3 Pin", | ||
| 504 | .codec_name = "snd-soc-dummy", | ||
| 505 | .codec_dai_name = "snd-soc-dummy-dai", | ||
| 506 | .platform_name = "0000:00:1f.3", | ||
| 507 | .trigger = { | ||
| 508 | SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, | ||
| 509 | .dpcm_playback = 1, | ||
| 510 | .init = NULL, | ||
| 511 | .nonatomic = 1, | ||
| 512 | .dynamic = 1, | ||
| 513 | }, | ||
| 514 | |||
| 515 | /* Back End DAI links */ | ||
| 516 | { | ||
| 517 | /* SSP0 - Codec */ | ||
| 518 | .name = "SSP0-Codec", | ||
| 519 | .id = 0, | ||
| 520 | .cpu_dai_name = "SSP0 Pin", | ||
| 521 | .platform_name = "0000:00:1f.3", | ||
| 522 | .no_pcm = 1, | ||
| 523 | .codecs = max98927_codec_components, | ||
| 524 | .num_codecs = ARRAY_SIZE(max98927_codec_components), | ||
| 525 | .dai_fmt = SND_SOC_DAIFMT_I2S | | ||
| 526 | SND_SOC_DAIFMT_NB_NF | | ||
| 527 | SND_SOC_DAIFMT_CBS_CFS, | ||
| 528 | .ignore_pmdown_time = 1, | ||
| 529 | .be_hw_params_fixup = kabylake_ssp_fixup, | ||
| 530 | .dpcm_playback = 1, | ||
| 531 | }, | ||
| 532 | { | ||
| 533 | /* SSP1 - Codec */ | ||
| 534 | .name = "SSP1-Codec", | ||
| 535 | .id = 1, | ||
| 536 | .cpu_dai_name = "SSP1 Pin", | ||
| 537 | .platform_name = "0000:00:1f.3", | ||
| 538 | .no_pcm = 1, | ||
| 539 | .codec_name = "i2c-10EC5663:00", | ||
| 540 | .codec_dai_name = KBL_REALTEK_CODEC_DAI, | ||
| 541 | .init = kabylake_rt5663_codec_init, | ||
| 542 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | | ||
| 543 | SND_SOC_DAIFMT_CBS_CFS, | ||
| 544 | .ignore_pmdown_time = 1, | ||
| 545 | .be_hw_params_fixup = kabylake_ssp_fixup, | ||
| 546 | .ops = &kabylake_rt5663_ops, | ||
| 547 | .dpcm_playback = 1, | ||
| 548 | .dpcm_capture = 1, | ||
| 549 | }, | ||
| 550 | { | ||
| 551 | .name = "dmic01", | ||
| 552 | .id = 2, | ||
| 553 | .cpu_dai_name = "DMIC01 Pin", | ||
| 554 | .codec_name = "dmic-codec", | ||
| 555 | .codec_dai_name = "dmic-hifi", | ||
| 556 | .platform_name = "0000:00:1f.3", | ||
| 557 | .be_hw_params_fixup = kabylake_dmic_fixup, | ||
| 558 | .ignore_suspend = 1, | ||
| 559 | .dpcm_capture = 1, | ||
| 560 | .no_pcm = 1, | ||
| 561 | }, | ||
| 562 | { | ||
| 563 | .name = "iDisp1", | ||
| 564 | .id = 3, | ||
| 565 | .cpu_dai_name = "iDisp1 Pin", | ||
| 566 | .codec_name = "ehdaudio0D2", | ||
| 567 | .codec_dai_name = "intel-hdmi-hifi1", | ||
| 568 | .platform_name = "0000:00:1f.3", | ||
| 569 | .dpcm_playback = 1, | ||
| 570 | .init = kabylake_hdmi1_init, | ||
| 571 | .no_pcm = 1, | ||
| 572 | }, | ||
| 573 | { | ||
| 574 | .name = "iDisp2", | ||
| 575 | .id = 4, | ||
| 576 | .cpu_dai_name = "iDisp2 Pin", | ||
| 577 | .codec_name = "ehdaudio0D2", | ||
| 578 | .codec_dai_name = "intel-hdmi-hifi2", | ||
| 579 | .platform_name = "0000:00:1f.3", | ||
| 580 | .init = kabylake_hdmi2_init, | ||
| 581 | .dpcm_playback = 1, | ||
| 582 | .no_pcm = 1, | ||
| 583 | }, | ||
| 584 | { | ||
| 585 | .name = "iDisp3", | ||
| 586 | .id = 5, | ||
| 587 | .cpu_dai_name = "iDisp3 Pin", | ||
| 588 | .codec_name = "ehdaudio0D2", | ||
| 589 | .codec_dai_name = "intel-hdmi-hifi3", | ||
| 590 | .platform_name = "0000:00:1f.3", | ||
| 591 | .init = kabylake_hdmi3_init, | ||
| 592 | .dpcm_playback = 1, | ||
| 593 | .no_pcm = 1, | ||
| 594 | }, | ||
| 595 | }; | ||
| 596 | |||
| 597 | #define NAME_SIZE 32 | ||
| 598 | static int kabylake_card_late_probe(struct snd_soc_card *card) | ||
| 599 | { | ||
| 600 | struct kbl_rt5663_private *ctx = snd_soc_card_get_drvdata(card); | ||
| 601 | struct kbl_hdmi_pcm *pcm; | ||
| 602 | int err, i = 0; | ||
| 603 | char jack_name[NAME_SIZE]; | ||
| 604 | |||
| 605 | list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) { | ||
| 606 | snprintf(jack_name, sizeof(jack_name), | ||
| 607 | "HDMI/DP, pcm=%d Jack", pcm->device); | ||
| 608 | err = snd_soc_card_jack_new(card, jack_name, | ||
| 609 | SND_JACK_AVOUT, &skylake_hdmi[i], | ||
| 610 | NULL, 0); | ||
| 611 | |||
| 612 | if (err) | ||
| 613 | return err; | ||
| 614 | |||
| 615 | err = hdac_hdmi_jack_init(pcm->codec_dai, pcm->device, | ||
| 616 | &skylake_hdmi[i]); | ||
| 617 | if (err < 0) | ||
| 618 | return err; | ||
| 619 | |||
| 620 | i++; | ||
| 621 | } | ||
| 622 | |||
| 623 | return 0; | ||
| 624 | } | ||
| 625 | |||
| 626 | /* kabylake audio machine driver for SPT + RT5663 */ | ||
| 627 | static struct snd_soc_card kabylake_audio_card = { | ||
| 628 | .name = "kblrt5663max", | ||
| 629 | .owner = THIS_MODULE, | ||
| 630 | .dai_link = kabylake_dais, | ||
| 631 | .num_links = ARRAY_SIZE(kabylake_dais), | ||
| 632 | .controls = kabylake_controls, | ||
| 633 | .num_controls = ARRAY_SIZE(kabylake_controls), | ||
| 634 | .dapm_widgets = kabylake_widgets, | ||
| 635 | .num_dapm_widgets = ARRAY_SIZE(kabylake_widgets), | ||
| 636 | .dapm_routes = kabylake_map, | ||
| 637 | .num_dapm_routes = ARRAY_SIZE(kabylake_map), | ||
| 638 | .codec_conf = max98927_codec_conf, | ||
| 639 | .num_configs = ARRAY_SIZE(max98927_codec_conf), | ||
| 640 | .fully_routed = true, | ||
| 641 | .late_probe = kabylake_card_late_probe, | ||
| 642 | }; | ||
| 643 | |||
| 644 | static int kabylake_audio_probe(struct platform_device *pdev) | ||
| 645 | { | ||
| 646 | struct kbl_rt5663_private *ctx; | ||
| 647 | struct skl_machine_pdata *pdata; | ||
| 648 | |||
| 649 | ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_ATOMIC); | ||
| 650 | if (!ctx) | ||
| 651 | return -ENOMEM; | ||
| 652 | |||
| 653 | INIT_LIST_HEAD(&ctx->hdmi_pcm_list); | ||
| 654 | |||
| 655 | kabylake_audio_card.dev = &pdev->dev; | ||
| 656 | snd_soc_card_set_drvdata(&kabylake_audio_card, ctx); | ||
| 657 | |||
| 658 | pdata = dev_get_drvdata(&pdev->dev); | ||
| 659 | if (pdata) | ||
| 660 | dmic_constraints = pdata->dmic_num == 2 ? | ||
| 661 | &constraints_dmic_2ch : &constraints_dmic_channels; | ||
| 662 | |||
| 663 | return devm_snd_soc_register_card(&pdev->dev, &kabylake_audio_card); | ||
| 664 | } | ||
| 665 | |||
| 666 | static const struct platform_device_id kbl_board_ids[] = { | ||
| 667 | { .name = "kbl_rt5663_m98927" }, | ||
| 668 | { } | ||
| 669 | }; | ||
| 670 | |||
| 671 | static struct platform_driver kabylake_audio = { | ||
| 672 | .probe = kabylake_audio_probe, | ||
| 673 | .driver = { | ||
| 674 | .name = "kbl_rt5663_m98927", | ||
| 675 | .pm = &snd_soc_pm_ops, | ||
| 676 | }, | ||
| 677 | .id_table = kbl_board_ids, | ||
| 678 | }; | ||
| 679 | |||
| 680 | module_platform_driver(kabylake_audio) | ||
| 681 | |||
| 682 | /* Module information */ | ||
| 683 | MODULE_DESCRIPTION("Audio Machine driver-RT5663 & MAX98927 in I2S mode"); | ||
| 684 | MODULE_AUTHOR("Naveen M <naveen.m@intel.com>"); | ||
| 685 | MODULE_AUTHOR("Harsha Priya <harshapriya.n@intel.com>"); | ||
| 686 | MODULE_LICENSE("GPL v2"); | ||
| 687 | MODULE_ALIAS("platform:kbl_rt5663_m98927"); | ||
diff --git a/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c b/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c new file mode 100644 index 000000000000..3fe4a0807095 --- /dev/null +++ b/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c | |||
| @@ -0,0 +1,640 @@ | |||
| 1 | /* | ||
| 2 | * Intel Kabylake I2S Machine Driver with MAXIM98927 | ||
| 3 | * RT5514 and RT5663 Codecs | ||
| 4 | * | ||
| 5 | * Copyright (C) 2017, Intel Corporation. All rights reserved. | ||
| 6 | * | ||
| 7 | * Modified from: | ||
| 8 | * Intel Kabylake I2S Machine driver supporting MAXIM98927 and | ||
| 9 | * RT5663 codecs | ||
| 10 | * | ||
| 11 | * This program is free software; you can redistribute it and/or | ||
| 12 | * modify it under the terms of the GNU General Public License version | ||
| 13 | * 2 as published by the Free Software Foundation. | ||
| 14 | * | ||
| 15 | * This program is distributed in the hope that it will be useful, | ||
| 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 18 | * GNU General Public License for more details. | ||
| 19 | */ | ||
| 20 | |||
| 21 | #include <linux/module.h> | ||
| 22 | #include <linux/platform_device.h> | ||
| 23 | #include <sound/core.h> | ||
| 24 | #include <sound/jack.h> | ||
| 25 | #include <sound/pcm.h> | ||
| 26 | #include <sound/pcm_params.h> | ||
| 27 | #include <sound/soc.h> | ||
| 28 | #include "../../codecs/rt5514.h" | ||
| 29 | #include "../../codecs/rt5663.h" | ||
| 30 | #include "../../codecs/hdac_hdmi.h" | ||
| 31 | #include "../skylake/skl.h" | ||
| 32 | |||
| 33 | #define KBL_REALTEK_CODEC_DAI "rt5663-aif" | ||
| 34 | #define KBL_REALTEK_DMIC_CODEC_DAI "rt5514-aif1" | ||
| 35 | #define KBL_MAXIM_CODEC_DAI "max98927-aif1" | ||
| 36 | #define MAXIM_DEV0_NAME "i2c-MX98927:00" | ||
| 37 | #define MAXIM_DEV1_NAME "i2c-MX98927:01" | ||
| 38 | #define RT5514_DEV_NAME "i2c-10EC5514:00" | ||
| 39 | #define RT5663_DEV_NAME "i2c-10EC5663:00" | ||
| 40 | #define RT5514_AIF1_BCLK_FREQ (48000 * 8 * 16) | ||
| 41 | #define RT5514_AIF1_SYSCLK_FREQ 12288000 | ||
| 42 | #define NAME_SIZE 32 | ||
| 43 | |||
| 44 | #define DMIC_CH(p) p->list[p->count-1] | ||
| 45 | |||
| 46 | |||
| 47 | static struct snd_soc_card kabylake_audio_card; | ||
| 48 | static const struct snd_pcm_hw_constraint_list *dmic_constraints; | ||
| 49 | |||
| 50 | struct kbl_hdmi_pcm { | ||
| 51 | struct list_head head; | ||
| 52 | struct snd_soc_dai *codec_dai; | ||
| 53 | int device; | ||
| 54 | }; | ||
| 55 | |||
| 56 | struct kbl_codec_private { | ||
| 57 | struct snd_soc_jack kabylake_headset; | ||
| 58 | struct list_head hdmi_pcm_list; | ||
| 59 | struct snd_soc_jack kabylake_hdmi[2]; | ||
| 60 | }; | ||
| 61 | |||
| 62 | enum { | ||
| 63 | KBL_DPCM_AUDIO_PB = 0, | ||
| 64 | KBL_DPCM_AUDIO_CP, | ||
| 65 | KBL_DPCM_AUDIO_DMIC_CP, | ||
| 66 | KBL_DPCM_AUDIO_HDMI1_PB, | ||
| 67 | KBL_DPCM_AUDIO_HDMI2_PB, | ||
| 68 | }; | ||
| 69 | |||
| 70 | static const struct snd_kcontrol_new kabylake_controls[] = { | ||
| 71 | SOC_DAPM_PIN_SWITCH("Headphone Jack"), | ||
| 72 | SOC_DAPM_PIN_SWITCH("Headset Mic"), | ||
| 73 | SOC_DAPM_PIN_SWITCH("Left Spk"), | ||
| 74 | SOC_DAPM_PIN_SWITCH("Right Spk"), | ||
| 75 | SOC_DAPM_PIN_SWITCH("DMIC"), | ||
| 76 | }; | ||
| 77 | |||
| 78 | static const struct snd_soc_dapm_widget kabylake_widgets[] = { | ||
| 79 | SND_SOC_DAPM_HP("Headphone Jack", NULL), | ||
| 80 | SND_SOC_DAPM_MIC("Headset Mic", NULL), | ||
| 81 | SND_SOC_DAPM_SPK("Left Spk", NULL), | ||
| 82 | SND_SOC_DAPM_SPK("Right Spk", NULL), | ||
| 83 | SND_SOC_DAPM_MIC("DMIC", NULL), | ||
| 84 | SND_SOC_DAPM_SPK("DP", NULL), | ||
| 85 | SND_SOC_DAPM_SPK("HDMI", NULL), | ||
| 86 | |||
| 87 | }; | ||
| 88 | |||
| 89 | static const struct snd_soc_dapm_route kabylake_map[] = { | ||
| 90 | /* Headphones */ | ||
| 91 | { "Headphone Jack", NULL, "HPOL" }, | ||
| 92 | { "Headphone Jack", NULL, "HPOR" }, | ||
| 93 | |||
| 94 | /* speaker */ | ||
| 95 | { "Left Spk", NULL, "Left BE_OUT" }, | ||
| 96 | { "Right Spk", NULL, "Right BE_OUT" }, | ||
| 97 | |||
| 98 | /* other jacks */ | ||
| 99 | { "IN1P", NULL, "Headset Mic" }, | ||
| 100 | { "IN1N", NULL, "Headset Mic" }, | ||
| 101 | |||
| 102 | { "HDMI", NULL, "hif5 Output" }, | ||
| 103 | { "DP", NULL, "hif6 Output" }, | ||
| 104 | |||
| 105 | /* CODEC BE connections */ | ||
| 106 | { "Left HiFi Playback", NULL, "ssp0 Tx" }, | ||
| 107 | { "Right HiFi Playback", NULL, "ssp0 Tx" }, | ||
| 108 | { "ssp0 Tx", NULL, "codec0_out" }, | ||
| 109 | |||
| 110 | { "AIF Playback", NULL, "ssp1 Tx" }, | ||
| 111 | { "ssp1 Tx", NULL, "codec1_out" }, | ||
| 112 | |||
| 113 | { "codec0_in", NULL, "ssp1 Rx" }, | ||
| 114 | { "ssp1 Rx", NULL, "AIF Capture" }, | ||
| 115 | |||
| 116 | { "codec1_in", NULL, "ssp0 Rx" }, | ||
| 117 | { "ssp0 Rx", NULL, "AIF1 Capture" }, | ||
| 118 | |||
| 119 | /* DMIC */ | ||
| 120 | { "DMIC1L", NULL, "DMIC" }, | ||
| 121 | { "DMIC1R", NULL, "DMIC" }, | ||
| 122 | { "DMIC2L", NULL, "DMIC" }, | ||
| 123 | { "DMIC2R", NULL, "DMIC" }, | ||
| 124 | |||
| 125 | { "hifi2", NULL, "iDisp2 Tx" }, | ||
| 126 | { "iDisp2 Tx", NULL, "iDisp2_out" }, | ||
| 127 | { "hifi1", NULL, "iDisp1 Tx" }, | ||
| 128 | { "iDisp1 Tx", NULL, "iDisp1_out" }, | ||
| 129 | }; | ||
| 130 | |||
| 131 | static struct snd_soc_codec_conf max98927_codec_conf[] = { | ||
| 132 | { | ||
| 133 | .dev_name = MAXIM_DEV0_NAME, | ||
| 134 | .name_prefix = "Right", | ||
| 135 | }, | ||
| 136 | { | ||
| 137 | .dev_name = MAXIM_DEV1_NAME, | ||
| 138 | .name_prefix = "Left", | ||
| 139 | }, | ||
| 140 | }; | ||
| 141 | |||
| 142 | static struct snd_soc_dai_link_component ssp0_codec_components[] = { | ||
| 143 | { /* Left */ | ||
| 144 | .name = MAXIM_DEV0_NAME, | ||
| 145 | .dai_name = KBL_MAXIM_CODEC_DAI, | ||
| 146 | }, | ||
| 147 | { /* Right */ | ||
| 148 | .name = MAXIM_DEV1_NAME, | ||
| 149 | .dai_name = KBL_MAXIM_CODEC_DAI, | ||
| 150 | }, | ||
| 151 | { /*dmic */ | ||
| 152 | .name = RT5514_DEV_NAME, | ||
| 153 | .dai_name = KBL_REALTEK_DMIC_CODEC_DAI, | ||
| 154 | }, | ||
| 155 | }; | ||
| 156 | |||
| 157 | static int kabylake_rt5663_fe_init(struct snd_soc_pcm_runtime *rtd) | ||
| 158 | { | ||
| 159 | struct snd_soc_dapm_context *dapm; | ||
| 160 | struct snd_soc_component *component = rtd->cpu_dai->component; | ||
| 161 | int ret; | ||
| 162 | |||
| 163 | dapm = snd_soc_component_get_dapm(component); | ||
| 164 | ret = snd_soc_dapm_ignore_suspend(dapm, "Reference Capture"); | ||
| 165 | if (ret) | ||
| 166 | dev_err(rtd->dev, "Ref Cap -Ignore suspend failed = %d\n", ret); | ||
| 167 | |||
| 168 | return ret; | ||
| 169 | } | ||
| 170 | |||
| 171 | static int kabylake_rt5663_codec_init(struct snd_soc_pcm_runtime *rtd) | ||
| 172 | { | ||
| 173 | int ret; | ||
| 174 | struct kbl_codec_private *ctx = snd_soc_card_get_drvdata(rtd->card); | ||
| 175 | struct snd_soc_codec *codec = rtd->codec; | ||
| 176 | |||
| 177 | /* | ||
| 178 | * Headset buttons map to the google Reference headset. | ||
| 179 | * These can be configured by userspace. | ||
| 180 | */ | ||
| 181 | ret = snd_soc_card_jack_new(&kabylake_audio_card, "Headset Jack", | ||
| 182 | SND_JACK_HEADSET | SND_JACK_BTN_0 | SND_JACK_BTN_1 | | ||
| 183 | SND_JACK_BTN_2 | SND_JACK_BTN_3, &ctx->kabylake_headset, | ||
| 184 | NULL, 0); | ||
| 185 | if (ret) { | ||
| 186 | dev_err(rtd->dev, "Headset Jack creation failed %d\n", ret); | ||
| 187 | return ret; | ||
| 188 | } | ||
| 189 | |||
| 190 | rt5663_set_jack_detect(codec, &ctx->kabylake_headset); | ||
| 191 | |||
| 192 | ret = snd_soc_dapm_ignore_suspend(&rtd->card->dapm, "DMIC"); | ||
| 193 | if (ret) | ||
| 194 | dev_err(rtd->dev, "DMIC - Ignore suspend failed = %d\n", ret); | ||
| 195 | |||
| 196 | return ret; | ||
| 197 | } | ||
| 198 | |||
| 199 | static int kabylake_hdmi_init(struct snd_soc_pcm_runtime *rtd, int device) | ||
| 200 | { | ||
| 201 | struct kbl_codec_private *ctx = snd_soc_card_get_drvdata(rtd->card); | ||
| 202 | struct snd_soc_dai *dai = rtd->codec_dai; | ||
| 203 | struct kbl_hdmi_pcm *pcm; | ||
| 204 | |||
| 205 | pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL); | ||
| 206 | if (!pcm) | ||
| 207 | return -ENOMEM; | ||
| 208 | |||
| 209 | pcm->device = device; | ||
| 210 | pcm->codec_dai = dai; | ||
| 211 | |||
| 212 | list_add_tail(&pcm->head, &ctx->hdmi_pcm_list); | ||
| 213 | |||
| 214 | return 0; | ||
| 215 | } | ||
| 216 | |||
| 217 | static int kabylake_hdmi1_init(struct snd_soc_pcm_runtime *rtd) | ||
| 218 | { | ||
| 219 | return kabylake_hdmi_init(rtd, KBL_DPCM_AUDIO_HDMI1_PB); | ||
| 220 | } | ||
| 221 | |||
| 222 | static int kabylake_hdmi2_init(struct snd_soc_pcm_runtime *rtd) | ||
| 223 | { | ||
| 224 | return kabylake_hdmi_init(rtd, KBL_DPCM_AUDIO_HDMI2_PB); | ||
| 225 | } | ||
| 226 | |||
| 227 | static const unsigned int rates[] = { | ||
| 228 | 48000, | ||
| 229 | }; | ||
| 230 | |||
| 231 | static const struct snd_pcm_hw_constraint_list constraints_rates = { | ||
| 232 | .count = ARRAY_SIZE(rates), | ||
| 233 | .list = rates, | ||
| 234 | .mask = 0, | ||
| 235 | }; | ||
| 236 | |||
| 237 | static const unsigned int channels[] = { | ||
| 238 | 2, | ||
| 239 | }; | ||
| 240 | |||
| 241 | static const struct snd_pcm_hw_constraint_list constraints_channels = { | ||
| 242 | .count = ARRAY_SIZE(channels), | ||
| 243 | .list = channels, | ||
| 244 | .mask = 0, | ||
| 245 | }; | ||
| 246 | |||
| 247 | static int kbl_fe_startup(struct snd_pcm_substream *substream) | ||
| 248 | { | ||
| 249 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
| 250 | |||
| 251 | /* | ||
| 252 | * On this platform for PCM device we support, | ||
| 253 | * 48Khz | ||
| 254 | * stereo | ||
| 255 | * 16 bit audio | ||
| 256 | */ | ||
| 257 | |||
| 258 | runtime->hw.channels_max = 2; | ||
| 259 | snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, | ||
| 260 | &constraints_channels); | ||
| 261 | |||
| 262 | runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE; | ||
| 263 | snd_pcm_hw_constraint_msbits(runtime, 0, 16, 16); | ||
| 264 | |||
| 265 | snd_pcm_hw_constraint_list(runtime, 0, | ||
| 266 | SNDRV_PCM_HW_PARAM_RATE, &constraints_rates); | ||
| 267 | |||
| 268 | return 0; | ||
| 269 | } | ||
| 270 | |||
| 271 | static const struct snd_soc_ops kabylake_rt5663_fe_ops = { | ||
| 272 | .startup = kbl_fe_startup, | ||
| 273 | }; | ||
| 274 | |||
| 275 | static int kabylake_ssp_fixup(struct snd_soc_pcm_runtime *rtd, | ||
| 276 | struct snd_pcm_hw_params *params) | ||
| 277 | { | ||
| 278 | struct snd_interval *rate = hw_param_interval(params, | ||
| 279 | SNDRV_PCM_HW_PARAM_RATE); | ||
| 280 | struct snd_interval *channels = hw_param_interval(params, | ||
| 281 | SNDRV_PCM_HW_PARAM_CHANNELS); | ||
| 282 | struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); | ||
| 283 | struct snd_soc_dpcm *dpcm = container_of( | ||
| 284 | params, struct snd_soc_dpcm, hw_params); | ||
| 285 | struct snd_soc_dai_link *fe_dai_link = dpcm->fe->dai_link; | ||
| 286 | struct snd_soc_dai_link *be_dai_link = dpcm->be->dai_link; | ||
| 287 | |||
| 288 | /* | ||
| 289 | * The ADSP will convert the FE rate to 48k, stereo, 24 bit | ||
| 290 | */ | ||
| 291 | if (!strcmp(fe_dai_link->name, "Kbl Audio Port") || | ||
| 292 | !strcmp(fe_dai_link->name, "Kbl Audio Capture Port")) { | ||
| 293 | rate->min = rate->max = 48000; | ||
| 294 | channels->min = channels->max = 2; | ||
| 295 | snd_mask_none(fmt); | ||
| 296 | snd_mask_set(fmt, SNDRV_PCM_FORMAT_S24_LE); | ||
| 297 | } else if (!strcmp(fe_dai_link->name, "Kbl Audio DMIC cap")) { | ||
| 298 | if (params_channels(params) == 2 || | ||
| 299 | DMIC_CH(dmic_constraints) == 2) | ||
| 300 | channels->min = channels->max = 2; | ||
| 301 | else | ||
| 302 | channels->min = channels->max = 4; | ||
| 303 | } | ||
| 304 | /* | ||
| 305 | * The speaker on the SSP0 supports S16_LE and not S24_LE. | ||
| 306 | * thus changing the mask here | ||
| 307 | */ | ||
| 308 | if (!strcmp(be_dai_link->name, "SSP0-Codec")) | ||
| 309 | snd_mask_set(fmt, SNDRV_PCM_FORMAT_S16_LE); | ||
| 310 | |||
| 311 | return 0; | ||
| 312 | } | ||
| 313 | |||
| 314 | static int kabylake_rt5663_hw_params(struct snd_pcm_substream *substream, | ||
| 315 | struct snd_pcm_hw_params *params) | ||
| 316 | { | ||
| 317 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
| 318 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
| 319 | int ret; | ||
| 320 | |||
| 321 | /* use ASRC for internal clocks, as PLL rate isn't multiple of BCLK */ | ||
| 322 | rt5663_sel_asrc_clk_src(codec_dai->codec, RT5663_DA_STEREO_FILTER, 1); | ||
| 323 | |||
| 324 | ret = snd_soc_dai_set_sysclk(codec_dai, | ||
| 325 | RT5663_SCLK_S_MCLK, 24576000, SND_SOC_CLOCK_IN); | ||
| 326 | if (ret < 0) | ||
| 327 | dev_err(rtd->dev, "snd_soc_dai_set_sysclk err = %d\n", ret); | ||
| 328 | |||
| 329 | return ret; | ||
| 330 | } | ||
| 331 | |||
| 332 | static struct snd_soc_ops kabylake_rt5663_ops = { | ||
| 333 | .hw_params = kabylake_rt5663_hw_params, | ||
| 334 | }; | ||
| 335 | |||
| 336 | static int kabylake_ssp0_hw_params(struct snd_pcm_substream *substream, | ||
| 337 | struct snd_pcm_hw_params *params) | ||
| 338 | { | ||
| 339 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
| 340 | int ret = 0, j; | ||
| 341 | |||
| 342 | for (j = 0; j < rtd->num_codecs; j++) { | ||
| 343 | struct snd_soc_dai *codec_dai = rtd->codec_dais[j]; | ||
| 344 | |||
| 345 | if (!strcmp(codec_dai->component->name, RT5514_DEV_NAME)) { | ||
| 346 | ret = snd_soc_dai_set_tdm_slot(codec_dai, 0xF, 0, 8, 16); | ||
| 347 | if (ret < 0) { | ||
| 348 | dev_err(rtd->dev, "set TDM slot err:%d\n", ret); | ||
| 349 | return ret; | ||
| 350 | } | ||
| 351 | |||
| 352 | ret = snd_soc_dai_set_pll(codec_dai, 0, | ||
| 353 | RT5514_PLL1_S_BCLK, RT5514_AIF1_BCLK_FREQ, | ||
| 354 | RT5514_AIF1_SYSCLK_FREQ); | ||
| 355 | if (ret < 0) { | ||
| 356 | dev_err(rtd->dev, "set bclk err: %d\n", ret); | ||
| 357 | return ret; | ||
| 358 | } | ||
| 359 | |||
| 360 | ret = snd_soc_dai_set_sysclk(codec_dai, | ||
| 361 | RT5514_SCLK_S_PLL1, RT5514_AIF1_SYSCLK_FREQ, | ||
| 362 | SND_SOC_CLOCK_IN); | ||
| 363 | if (ret < 0) { | ||
| 364 | dev_err(rtd->dev, "set sclk err: %d\n", ret); | ||
| 365 | return ret; | ||
| 366 | } | ||
| 367 | } | ||
| 368 | if (!strcmp(codec_dai->component->name, MAXIM_DEV0_NAME) || | ||
| 369 | !strcmp(codec_dai->component->name, MAXIM_DEV1_NAME)) { | ||
| 370 | ret = snd_soc_dai_set_tdm_slot(codec_dai, 0xF0, 3, 8, 16); | ||
| 371 | if (ret < 0) { | ||
| 372 | dev_err(rtd->dev, "set TDM slot err:%d\n", ret); | ||
| 373 | return ret; | ||
| 374 | } | ||
| 375 | } | ||
| 376 | } | ||
| 377 | return ret; | ||
| 378 | } | ||
| 379 | |||
| 380 | static struct snd_soc_ops kabylake_ssp0_ops = { | ||
| 381 | .hw_params = kabylake_ssp0_hw_params, | ||
| 382 | }; | ||
| 383 | |||
| 384 | static const unsigned int channels_dmic[] = { | ||
| 385 | 4, | ||
| 386 | }; | ||
| 387 | |||
| 388 | static const struct snd_pcm_hw_constraint_list constraints_dmic_channels = { | ||
| 389 | .count = ARRAY_SIZE(channels_dmic), | ||
| 390 | .list = channels_dmic, | ||
| 391 | .mask = 0, | ||
| 392 | }; | ||
| 393 | |||
| 394 | static const unsigned int dmic_2ch[] = { | ||
| 395 | 4, | ||
| 396 | }; | ||
| 397 | |||
| 398 | static const struct snd_pcm_hw_constraint_list constraints_dmic_2ch = { | ||
| 399 | .count = ARRAY_SIZE(dmic_2ch), | ||
| 400 | .list = dmic_2ch, | ||
| 401 | .mask = 0, | ||
| 402 | }; | ||
| 403 | |||
| 404 | static int kabylake_dmic_startup(struct snd_pcm_substream *substream) | ||
| 405 | { | ||
| 406 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
| 407 | |||
| 408 | runtime->hw.channels_max = DMIC_CH(dmic_constraints); | ||
| 409 | snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, | ||
| 410 | dmic_constraints); | ||
| 411 | |||
| 412 | return snd_pcm_hw_constraint_list(substream->runtime, 0, | ||
| 413 | SNDRV_PCM_HW_PARAM_RATE, &constraints_rates); | ||
| 414 | } | ||
| 415 | |||
| 416 | static struct snd_soc_ops kabylake_dmic_ops = { | ||
| 417 | .startup = kabylake_dmic_startup, | ||
| 418 | }; | ||
| 419 | |||
| 420 | /* kabylake digital audio interface glue - connects codec <--> CPU */ | ||
| 421 | static struct snd_soc_dai_link kabylake_dais[] = { | ||
| 422 | /* Front End DAI links */ | ||
| 423 | [KBL_DPCM_AUDIO_PB] = { | ||
| 424 | .name = "Kbl Audio Port", | ||
| 425 | .stream_name = "Audio", | ||
| 426 | .cpu_dai_name = "System Pin", | ||
| 427 | .platform_name = "0000:00:1f.3", | ||
| 428 | .dynamic = 1, | ||
| 429 | .codec_name = "snd-soc-dummy", | ||
| 430 | .codec_dai_name = "snd-soc-dummy-dai", | ||
| 431 | .nonatomic = 1, | ||
| 432 | .init = kabylake_rt5663_fe_init, | ||
| 433 | .trigger = { | ||
| 434 | SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, | ||
| 435 | .dpcm_playback = 1, | ||
| 436 | .ops = &kabylake_rt5663_fe_ops, | ||
| 437 | }, | ||
| 438 | [KBL_DPCM_AUDIO_CP] = { | ||
| 439 | .name = "Kbl Audio Capture Port", | ||
| 440 | .stream_name = "Audio Record", | ||
| 441 | .cpu_dai_name = "System Pin", | ||
| 442 | .platform_name = "0000:00:1f.3", | ||
| 443 | .dynamic = 1, | ||
| 444 | .codec_name = "snd-soc-dummy", | ||
| 445 | .codec_dai_name = "snd-soc-dummy-dai", | ||
| 446 | .nonatomic = 1, | ||
| 447 | .trigger = { | ||
| 448 | SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, | ||
| 449 | .dpcm_capture = 1, | ||
| 450 | .ops = &kabylake_rt5663_fe_ops, | ||
| 451 | }, | ||
| 452 | [KBL_DPCM_AUDIO_DMIC_CP] = { | ||
| 453 | .name = "Kbl Audio DMIC cap", | ||
| 454 | .stream_name = "dmiccap", | ||
| 455 | .cpu_dai_name = "DMIC Pin", | ||
| 456 | .codec_name = "snd-soc-dummy", | ||
| 457 | .codec_dai_name = "snd-soc-dummy-dai", | ||
| 458 | .platform_name = "0000:00:1f.3", | ||
| 459 | .init = NULL, | ||
| 460 | .dpcm_capture = 1, | ||
| 461 | .nonatomic = 1, | ||
| 462 | .dynamic = 1, | ||
| 463 | .ops = &kabylake_dmic_ops, | ||
| 464 | }, | ||
| 465 | [KBL_DPCM_AUDIO_HDMI1_PB] = { | ||
| 466 | .name = "Kbl HDMI Port1", | ||
| 467 | .stream_name = "Hdmi1", | ||
| 468 | .cpu_dai_name = "HDMI1 Pin", | ||
| 469 | .codec_name = "snd-soc-dummy", | ||
| 470 | .codec_dai_name = "snd-soc-dummy-dai", | ||
| 471 | .platform_name = "0000:00:1f.3", | ||
| 472 | .dpcm_playback = 1, | ||
| 473 | .init = NULL, | ||
| 474 | .trigger = { | ||
| 475 | SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, | ||
| 476 | .nonatomic = 1, | ||
| 477 | .dynamic = 1, | ||
| 478 | }, | ||
| 479 | [KBL_DPCM_AUDIO_HDMI2_PB] = { | ||
| 480 | .name = "Kbl HDMI Port2", | ||
| 481 | .stream_name = "Hdmi2", | ||
| 482 | .cpu_dai_name = "HDMI2 Pin", | ||
| 483 | .codec_name = "snd-soc-dummy", | ||
| 484 | .codec_dai_name = "snd-soc-dummy-dai", | ||
| 485 | .platform_name = "0000:00:1f.3", | ||
| 486 | .dpcm_playback = 1, | ||
| 487 | .init = NULL, | ||
| 488 | .trigger = { | ||
| 489 | SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, | ||
| 490 | .nonatomic = 1, | ||
| 491 | .dynamic = 1, | ||
| 492 | }, | ||
| 493 | /* Back End DAI links */ | ||
| 494 | /* single Back end dai for both max speakers and dmic */ | ||
| 495 | { | ||
| 496 | /* SSP0 - Codec */ | ||
| 497 | .name = "SSP0-Codec", | ||
| 498 | .id = 0, | ||
| 499 | .cpu_dai_name = "SSP0 Pin", | ||
| 500 | .platform_name = "0000:00:1f.3", | ||
| 501 | .no_pcm = 1, | ||
| 502 | .codecs = ssp0_codec_components, | ||
| 503 | .num_codecs = ARRAY_SIZE(ssp0_codec_components), | ||
| 504 | .dai_fmt = SND_SOC_DAIFMT_DSP_B | | ||
| 505 | SND_SOC_DAIFMT_NB_NF | | ||
| 506 | SND_SOC_DAIFMT_CBS_CFS, | ||
| 507 | .ignore_pmdown_time = 1, | ||
| 508 | .be_hw_params_fixup = kabylake_ssp_fixup, | ||
| 509 | .dpcm_playback = 1, | ||
| 510 | .dpcm_capture = 1, | ||
| 511 | .ops = &kabylake_ssp0_ops, | ||
| 512 | }, | ||
| 513 | { | ||
| 514 | .name = "SSP1-Codec", | ||
| 515 | .id = 1, | ||
| 516 | .cpu_dai_name = "SSP1 Pin", | ||
| 517 | .platform_name = "0000:00:1f.3", | ||
| 518 | .no_pcm = 1, | ||
| 519 | .codec_name = RT5663_DEV_NAME, | ||
| 520 | .codec_dai_name = KBL_REALTEK_CODEC_DAI, | ||
| 521 | .init = kabylake_rt5663_codec_init, | ||
| 522 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | | ||
| 523 | SND_SOC_DAIFMT_CBS_CFS, | ||
| 524 | .ignore_pmdown_time = 1, | ||
| 525 | .be_hw_params_fixup = kabylake_ssp_fixup, | ||
| 526 | .ops = &kabylake_rt5663_ops, | ||
| 527 | .dpcm_playback = 1, | ||
| 528 | .dpcm_capture = 1, | ||
| 529 | }, | ||
| 530 | { | ||
| 531 | .name = "iDisp1", | ||
| 532 | .id = 3, | ||
| 533 | .cpu_dai_name = "iDisp1 Pin", | ||
| 534 | .codec_name = "ehdaudio0D2", | ||
| 535 | .codec_dai_name = "intel-hdmi-hifi1", | ||
| 536 | .platform_name = "0000:00:1f.3", | ||
| 537 | .dpcm_playback = 1, | ||
| 538 | .init = kabylake_hdmi1_init, | ||
| 539 | .no_pcm = 1, | ||
| 540 | }, | ||
| 541 | { | ||
| 542 | .name = "iDisp2", | ||
| 543 | .id = 4, | ||
| 544 | .cpu_dai_name = "iDisp2 Pin", | ||
| 545 | .codec_name = "ehdaudio0D2", | ||
| 546 | .codec_dai_name = "intel-hdmi-hifi2", | ||
| 547 | .platform_name = "0000:00:1f.3", | ||
| 548 | .init = kabylake_hdmi2_init, | ||
| 549 | .dpcm_playback = 1, | ||
| 550 | .no_pcm = 1, | ||
| 551 | }, | ||
| 552 | }; | ||
| 553 | |||
| 554 | static int kabylake_card_late_probe(struct snd_soc_card *card) | ||
| 555 | { | ||
| 556 | struct kbl_codec_private *ctx = snd_soc_card_get_drvdata(card); | ||
| 557 | struct kbl_hdmi_pcm *pcm; | ||
| 558 | int err, i = 0; | ||
| 559 | char jack_name[NAME_SIZE]; | ||
| 560 | |||
| 561 | list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) { | ||
| 562 | err = snd_soc_card_jack_new(card, jack_name, | ||
| 563 | SND_JACK_AVOUT, &ctx->kabylake_hdmi[i], | ||
| 564 | NULL, 0); | ||
| 565 | |||
| 566 | if (err) | ||
| 567 | return err; | ||
| 568 | err = hdac_hdmi_jack_init(pcm->codec_dai, pcm->device, | ||
| 569 | &ctx->kabylake_hdmi[i]); | ||
| 570 | if (err < 0) | ||
| 571 | return err; | ||
| 572 | i++; | ||
| 573 | } | ||
| 574 | |||
| 575 | return 0; | ||
| 576 | } | ||
| 577 | |||
| 578 | /* | ||
| 579 | * kabylake audio machine driver for MAX98927 + RT5514 + RT5663 | ||
| 580 | */ | ||
| 581 | static struct snd_soc_card kabylake_audio_card = { | ||
| 582 | .name = "kbl_r5514_5663_max", | ||
| 583 | .owner = THIS_MODULE, | ||
| 584 | .dai_link = kabylake_dais, | ||
| 585 | .num_links = ARRAY_SIZE(kabylake_dais), | ||
| 586 | .controls = kabylake_controls, | ||
| 587 | .num_controls = ARRAY_SIZE(kabylake_controls), | ||
| 588 | .dapm_widgets = kabylake_widgets, | ||
| 589 | .num_dapm_widgets = ARRAY_SIZE(kabylake_widgets), | ||
| 590 | .dapm_routes = kabylake_map, | ||
| 591 | .num_dapm_routes = ARRAY_SIZE(kabylake_map), | ||
| 592 | .codec_conf = max98927_codec_conf, | ||
| 593 | .num_configs = ARRAY_SIZE(max98927_codec_conf), | ||
| 594 | .fully_routed = true, | ||
| 595 | .late_probe = kabylake_card_late_probe, | ||
| 596 | }; | ||
| 597 | |||
| 598 | static int kabylake_audio_probe(struct platform_device *pdev) | ||
| 599 | { | ||
| 600 | struct kbl_codec_private *ctx; | ||
| 601 | struct skl_machine_pdata *pdata; | ||
| 602 | |||
| 603 | ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_ATOMIC); | ||
| 604 | if (!ctx) | ||
| 605 | return -ENOMEM; | ||
| 606 | |||
| 607 | INIT_LIST_HEAD(&ctx->hdmi_pcm_list); | ||
| 608 | |||
| 609 | kabylake_audio_card.dev = &pdev->dev; | ||
| 610 | snd_soc_card_set_drvdata(&kabylake_audio_card, ctx); | ||
| 611 | |||
| 612 | pdata = dev_get_drvdata(&pdev->dev); | ||
| 613 | if (pdata) | ||
| 614 | dmic_constraints = pdata->dmic_num == 2 ? | ||
| 615 | &constraints_dmic_2ch : &constraints_dmic_channels; | ||
| 616 | |||
| 617 | return devm_snd_soc_register_card(&pdev->dev, &kabylake_audio_card); | ||
| 618 | } | ||
| 619 | |||
| 620 | static const struct platform_device_id kbl_board_ids[] = { | ||
| 621 | { .name = "kbl_r5514_5663_max" }, | ||
| 622 | { } | ||
| 623 | }; | ||
| 624 | |||
| 625 | static struct platform_driver kabylake_audio = { | ||
| 626 | .probe = kabylake_audio_probe, | ||
| 627 | .driver = { | ||
| 628 | .name = "kbl_r5514_5663_max", | ||
| 629 | .pm = &snd_soc_pm_ops, | ||
| 630 | }, | ||
| 631 | .id_table = kbl_board_ids, | ||
| 632 | }; | ||
| 633 | |||
| 634 | module_platform_driver(kabylake_audio) | ||
| 635 | |||
| 636 | /* Module information */ | ||
| 637 | MODULE_DESCRIPTION("Audio Machine driver-RT5663 RT5514 & MAX98927"); | ||
| 638 | MODULE_AUTHOR("Harsha Priya <harshapriya.n@intel.com>"); | ||
| 639 | MODULE_LICENSE("GPL v2"); | ||
| 640 | MODULE_ALIAS("platform:kbl_r5514_5663_max"); | ||
diff --git a/sound/soc/intel/boards/skl_nau88l25_max98357a.c b/sound/soc/intel/boards/skl_nau88l25_max98357a.c index 3b12bc1fa518..5ed0aa27b467 100644 --- a/sound/soc/intel/boards/skl_nau88l25_max98357a.c +++ b/sound/soc/intel/boards/skl_nau88l25_max98357a.c | |||
| @@ -266,21 +266,21 @@ static int skylake_nau8825_fe_init(struct snd_soc_pcm_runtime *rtd) | |||
| 266 | return 0; | 266 | return 0; |
| 267 | } | 267 | } |
| 268 | 268 | ||
| 269 | static unsigned int rates[] = { | 269 | static const unsigned int rates[] = { |
| 270 | 48000, | 270 | 48000, |
| 271 | }; | 271 | }; |
| 272 | 272 | ||
| 273 | static struct snd_pcm_hw_constraint_list constraints_rates = { | 273 | static const struct snd_pcm_hw_constraint_list constraints_rates = { |
| 274 | .count = ARRAY_SIZE(rates), | 274 | .count = ARRAY_SIZE(rates), |
| 275 | .list = rates, | 275 | .list = rates, |
| 276 | .mask = 0, | 276 | .mask = 0, |
| 277 | }; | 277 | }; |
| 278 | 278 | ||
| 279 | static unsigned int channels[] = { | 279 | static const unsigned int channels[] = { |
| 280 | 2, | 280 | 2, |
| 281 | }; | 281 | }; |
| 282 | 282 | ||
| 283 | static struct snd_pcm_hw_constraint_list constraints_channels = { | 283 | static const struct snd_pcm_hw_constraint_list constraints_channels = { |
| 284 | .count = ARRAY_SIZE(channels), | 284 | .count = ARRAY_SIZE(channels), |
| 285 | .list = channels, | 285 | .list = channels, |
| 286 | .mask = 0, | 286 | .mask = 0, |
| @@ -348,11 +348,11 @@ static int skylake_dmic_fixup(struct snd_soc_pcm_runtime *rtd, | |||
| 348 | return 0; | 348 | return 0; |
| 349 | } | 349 | } |
| 350 | 350 | ||
| 351 | static unsigned int channels_dmic[] = { | 351 | static const unsigned int channels_dmic[] = { |
| 352 | 2, 4, | 352 | 2, 4, |
| 353 | }; | 353 | }; |
| 354 | 354 | ||
| 355 | static struct snd_pcm_hw_constraint_list constraints_dmic_channels = { | 355 | static const struct snd_pcm_hw_constraint_list constraints_dmic_channels = { |
| 356 | .count = ARRAY_SIZE(channels_dmic), | 356 | .count = ARRAY_SIZE(channels_dmic), |
| 357 | .list = channels_dmic, | 357 | .list = channels_dmic, |
| 358 | .mask = 0, | 358 | .mask = 0, |
| @@ -384,11 +384,11 @@ static const struct snd_soc_ops skylake_dmic_ops = { | |||
| 384 | .startup = skylake_dmic_startup, | 384 | .startup = skylake_dmic_startup, |
| 385 | }; | 385 | }; |
| 386 | 386 | ||
| 387 | static unsigned int rates_16000[] = { | 387 | static const unsigned int rates_16000[] = { |
| 388 | 16000, | 388 | 16000, |
| 389 | }; | 389 | }; |
| 390 | 390 | ||
| 391 | static struct snd_pcm_hw_constraint_list constraints_16000 = { | 391 | static const struct snd_pcm_hw_constraint_list constraints_16000 = { |
| 392 | .count = ARRAY_SIZE(rates_16000), | 392 | .count = ARRAY_SIZE(rates_16000), |
| 393 | .list = rates_16000, | 393 | .list = rates_16000, |
| 394 | }; | 394 | }; |
diff --git a/sound/soc/intel/boards/skl_nau88l25_ssm4567.c b/sound/soc/intel/boards/skl_nau88l25_ssm4567.c index eb7751b0599b..01b8b140bb08 100644 --- a/sound/soc/intel/boards/skl_nau88l25_ssm4567.c +++ b/sound/soc/intel/boards/skl_nau88l25_ssm4567.c | |||
| @@ -297,21 +297,21 @@ static int skylake_nau8825_fe_init(struct snd_soc_pcm_runtime *rtd) | |||
| 297 | return 0; | 297 | return 0; |
| 298 | } | 298 | } |
| 299 | 299 | ||
| 300 | static unsigned int rates[] = { | 300 | static const unsigned int rates[] = { |
| 301 | 48000, | 301 | 48000, |
| 302 | }; | 302 | }; |
| 303 | 303 | ||
| 304 | static struct snd_pcm_hw_constraint_list constraints_rates = { | 304 | static const struct snd_pcm_hw_constraint_list constraints_rates = { |
| 305 | .count = ARRAY_SIZE(rates), | 305 | .count = ARRAY_SIZE(rates), |
| 306 | .list = rates, | 306 | .list = rates, |
| 307 | .mask = 0, | 307 | .mask = 0, |
| 308 | }; | 308 | }; |
| 309 | 309 | ||
| 310 | static unsigned int channels[] = { | 310 | static const unsigned int channels[] = { |
| 311 | 2, | 311 | 2, |
| 312 | }; | 312 | }; |
| 313 | 313 | ||
| 314 | static struct snd_pcm_hw_constraint_list constraints_channels = { | 314 | static const struct snd_pcm_hw_constraint_list constraints_channels = { |
| 315 | .count = ARRAY_SIZE(channels), | 315 | .count = ARRAY_SIZE(channels), |
| 316 | .list = channels, | 316 | .list = channels, |
| 317 | .mask = 0, | 317 | .mask = 0, |
| @@ -397,11 +397,11 @@ static const struct snd_soc_ops skylake_nau8825_ops = { | |||
| 397 | .hw_params = skylake_nau8825_hw_params, | 397 | .hw_params = skylake_nau8825_hw_params, |
| 398 | }; | 398 | }; |
| 399 | 399 | ||
| 400 | static unsigned int channels_dmic[] = { | 400 | static const unsigned int channels_dmic[] = { |
| 401 | 2, 4, | 401 | 2, 4, |
| 402 | }; | 402 | }; |
| 403 | 403 | ||
| 404 | static struct snd_pcm_hw_constraint_list constraints_dmic_channels = { | 404 | static const struct snd_pcm_hw_constraint_list constraints_dmic_channels = { |
| 405 | .count = ARRAY_SIZE(channels_dmic), | 405 | .count = ARRAY_SIZE(channels_dmic), |
| 406 | .list = channels_dmic, | 406 | .list = channels_dmic, |
| 407 | .mask = 0, | 407 | .mask = 0, |
| @@ -433,11 +433,11 @@ static const struct snd_soc_ops skylake_dmic_ops = { | |||
| 433 | .startup = skylake_dmic_startup, | 433 | .startup = skylake_dmic_startup, |
| 434 | }; | 434 | }; |
| 435 | 435 | ||
| 436 | static unsigned int rates_16000[] = { | 436 | static const unsigned int rates_16000[] = { |
| 437 | 16000, | 437 | 16000, |
| 438 | }; | 438 | }; |
| 439 | 439 | ||
| 440 | static struct snd_pcm_hw_constraint_list constraints_16000 = { | 440 | static const struct snd_pcm_hw_constraint_list constraints_16000 = { |
| 441 | .count = ARRAY_SIZE(rates_16000), | 441 | .count = ARRAY_SIZE(rates_16000), |
| 442 | .list = rates_16000, | 442 | .list = rates_16000, |
| 443 | }; | 443 | }; |
diff --git a/sound/soc/intel/boards/skl_rt286.c b/sound/soc/intel/boards/skl_rt286.c index f5ab7b8d51d1..2bc4cfca594e 100644 --- a/sound/soc/intel/boards/skl_rt286.c +++ b/sound/soc/intel/boards/skl_rt286.c | |||
| @@ -43,6 +43,7 @@ struct skl_rt286_private { | |||
| 43 | 43 | ||
| 44 | enum { | 44 | enum { |
| 45 | SKL_DPCM_AUDIO_PB = 0, | 45 | SKL_DPCM_AUDIO_PB = 0, |
| 46 | SKL_DPCM_AUDIO_DB_PB, | ||
| 46 | SKL_DPCM_AUDIO_CP, | 47 | SKL_DPCM_AUDIO_CP, |
| 47 | SKL_DPCM_AUDIO_REF_CP, | 48 | SKL_DPCM_AUDIO_REF_CP, |
| 48 | SKL_DPCM_AUDIO_DMIC_CP, | 49 | SKL_DPCM_AUDIO_DMIC_CP, |
| @@ -165,21 +166,21 @@ static int skylake_hdmi_init(struct snd_soc_pcm_runtime *rtd) | |||
| 165 | return 0; | 166 | return 0; |
| 166 | } | 167 | } |
| 167 | 168 | ||
| 168 | static unsigned int rates[] = { | 169 | static const unsigned int rates[] = { |
| 169 | 48000, | 170 | 48000, |
| 170 | }; | 171 | }; |
| 171 | 172 | ||
| 172 | static struct snd_pcm_hw_constraint_list constraints_rates = { | 173 | static const struct snd_pcm_hw_constraint_list constraints_rates = { |
| 173 | .count = ARRAY_SIZE(rates), | 174 | .count = ARRAY_SIZE(rates), |
| 174 | .list = rates, | 175 | .list = rates, |
| 175 | .mask = 0, | 176 | .mask = 0, |
| 176 | }; | 177 | }; |
| 177 | 178 | ||
| 178 | static unsigned int channels[] = { | 179 | static const unsigned int channels[] = { |
| 179 | 2, | 180 | 2, |
| 180 | }; | 181 | }; |
| 181 | 182 | ||
| 182 | static struct snd_pcm_hw_constraint_list constraints_channels = { | 183 | static const struct snd_pcm_hw_constraint_list constraints_channels = { |
| 183 | .count = ARRAY_SIZE(channels), | 184 | .count = ARRAY_SIZE(channels), |
| 184 | .list = channels, | 185 | .list = channels, |
| 185 | .mask = 0, | 186 | .mask = 0, |
| @@ -264,11 +265,11 @@ static int skylake_dmic_fixup(struct snd_soc_pcm_runtime *rtd, | |||
| 264 | return 0; | 265 | return 0; |
| 265 | } | 266 | } |
| 266 | 267 | ||
| 267 | static unsigned int channels_dmic[] = { | 268 | static const unsigned int channels_dmic[] = { |
| 268 | 2, 4, | 269 | 2, 4, |
| 269 | }; | 270 | }; |
| 270 | 271 | ||
| 271 | static struct snd_pcm_hw_constraint_list constraints_dmic_channels = { | 272 | static const struct snd_pcm_hw_constraint_list constraints_dmic_channels = { |
| 272 | .count = ARRAY_SIZE(channels_dmic), | 273 | .count = ARRAY_SIZE(channels_dmic), |
| 273 | .list = channels_dmic, | 274 | .list = channels_dmic, |
| 274 | .mask = 0, | 275 | .mask = 0, |
| @@ -310,6 +311,23 @@ static struct snd_soc_dai_link skylake_rt286_dais[] = { | |||
| 310 | .dpcm_playback = 1, | 311 | .dpcm_playback = 1, |
| 311 | .ops = &skylake_rt286_fe_ops, | 312 | .ops = &skylake_rt286_fe_ops, |
| 312 | }, | 313 | }, |
| 314 | [SKL_DPCM_AUDIO_DB_PB] = { | ||
| 315 | .name = "Skl Deepbuffer Port", | ||
| 316 | .stream_name = "Deep Buffer Audio", | ||
| 317 | .cpu_dai_name = "Deepbuffer Pin", | ||
| 318 | .platform_name = "0000:00:1f.3", | ||
| 319 | .nonatomic = 1, | ||
| 320 | .dynamic = 1, | ||
| 321 | .codec_name = "snd-soc-dummy", | ||
| 322 | .codec_dai_name = "snd-soc-dummy-dai", | ||
| 323 | .trigger = { | ||
| 324 | SND_SOC_DPCM_TRIGGER_POST, | ||
| 325 | SND_SOC_DPCM_TRIGGER_POST | ||
| 326 | }, | ||
| 327 | .dpcm_playback = 1, | ||
| 328 | .ops = &skylake_rt286_fe_ops, | ||
| 329 | |||
| 330 | }, | ||
| 313 | [SKL_DPCM_AUDIO_CP] = { | 331 | [SKL_DPCM_AUDIO_CP] = { |
| 314 | .name = "Skl Audio Capture Port", | 332 | .name = "Skl Audio Capture Port", |
| 315 | .stream_name = "Audio Record", | 333 | .stream_name = "Audio Record", |
diff --git a/sound/soc/intel/common/sst-acpi.h b/sound/soc/intel/common/sst-acpi.h index 214e000667ae..afe9b87b8bd5 100644 --- a/sound/soc/intel/common/sst-acpi.h +++ b/sound/soc/intel/common/sst-acpi.h | |||
| @@ -43,6 +43,9 @@ static inline bool sst_acpi_find_package_from_hid(const u8 hid[ACPI_ID_LEN], | |||
| 43 | /* acpi match */ | 43 | /* acpi match */ |
| 44 | struct sst_acpi_mach *sst_acpi_find_machine(struct sst_acpi_mach *machines); | 44 | struct sst_acpi_mach *sst_acpi_find_machine(struct sst_acpi_mach *machines); |
| 45 | 45 | ||
| 46 | /* acpi check hid */ | ||
| 47 | bool sst_acpi_check_hid(const u8 hid[ACPI_ID_LEN]); | ||
| 48 | |||
| 46 | /* Descriptor for SST ASoC machine driver */ | 49 | /* Descriptor for SST ASoC machine driver */ |
| 47 | struct sst_acpi_mach { | 50 | struct sst_acpi_mach { |
| 48 | /* ACPI ID for the matching machine driver. Audio codec for instance */ | 51 | /* ACPI ID for the matching machine driver. Audio codec for instance */ |
| @@ -55,5 +58,25 @@ struct sst_acpi_mach { | |||
| 55 | /* board name */ | 58 | /* board name */ |
| 56 | const char *board; | 59 | const char *board; |
| 57 | struct sst_acpi_mach * (*machine_quirk)(void *arg); | 60 | struct sst_acpi_mach * (*machine_quirk)(void *arg); |
| 61 | const void *quirk_data; | ||
| 58 | void *pdata; | 62 | void *pdata; |
| 59 | }; | 63 | }; |
| 64 | |||
| 65 | #define SST_ACPI_MAX_CODECS 3 | ||
| 66 | |||
| 67 | /** | ||
| 68 | * struct sst_codecs: Structure to hold secondary codec information apart from | ||
| 69 | * the matched one, this data will be passed to the quirk function to match | ||
| 70 | * with the ACPI detected devices | ||
| 71 | * | ||
| 72 | * @num_codecs: number of secondary codecs used in the platform | ||
| 73 | * @codecs: holds the codec IDs | ||
| 74 | * | ||
| 75 | */ | ||
| 76 | struct sst_codecs { | ||
| 77 | int num_codecs; | ||
| 78 | u8 codecs[SST_ACPI_MAX_CODECS][ACPI_ID_LEN]; | ||
| 79 | }; | ||
| 80 | |||
| 81 | /* check all codecs */ | ||
| 82 | struct sst_acpi_mach *sst_acpi_codec_list(void *arg); | ||
diff --git a/sound/soc/intel/common/sst-dsp-priv.h b/sound/soc/intel/common/sst-dsp-priv.h index d13c84364c3c..8734040d64d3 100644 --- a/sound/soc/intel/common/sst-dsp-priv.h +++ b/sound/soc/intel/common/sst-dsp-priv.h | |||
| @@ -77,6 +77,10 @@ struct sst_addr { | |||
| 77 | u32 dram_offset; | 77 | u32 dram_offset; |
| 78 | u32 dsp_iram_offset; | 78 | u32 dsp_iram_offset; |
| 79 | u32 dsp_dram_offset; | 79 | u32 dsp_dram_offset; |
| 80 | u32 sram0_base; | ||
| 81 | u32 sram1_base; | ||
| 82 | u32 w0_stat_sz; | ||
| 83 | u32 w0_up_sz; | ||
| 80 | void __iomem *lpe; | 84 | void __iomem *lpe; |
| 81 | void __iomem *shim; | 85 | void __iomem *shim; |
| 82 | void __iomem *pci_cfg; | 86 | void __iomem *pci_cfg; |
diff --git a/sound/soc/intel/common/sst-match-acpi.c b/sound/soc/intel/common/sst-match-acpi.c index 1070f3ad23e5..56d26f36a3cb 100644 --- a/sound/soc/intel/common/sst-match-acpi.c +++ b/sound/soc/intel/common/sst-match-acpi.c | |||
| @@ -63,16 +63,33 @@ static acpi_status sst_acpi_mach_match(acpi_handle handle, u32 level, | |||
| 63 | return AE_OK; | 63 | return AE_OK; |
| 64 | } | 64 | } |
| 65 | 65 | ||
| 66 | bool sst_acpi_check_hid(const u8 hid[ACPI_ID_LEN]) | ||
| 67 | { | ||
| 68 | acpi_status status; | ||
| 69 | bool found = false; | ||
| 70 | |||
| 71 | status = acpi_get_devices(hid, sst_acpi_mach_match, &found, NULL); | ||
| 72 | |||
| 73 | if (ACPI_FAILURE(status)) | ||
| 74 | return false; | ||
| 75 | |||
| 76 | return found; | ||
| 77 | } | ||
| 78 | EXPORT_SYMBOL_GPL(sst_acpi_check_hid); | ||
| 79 | |||
| 66 | struct sst_acpi_mach *sst_acpi_find_machine(struct sst_acpi_mach *machines) | 80 | struct sst_acpi_mach *sst_acpi_find_machine(struct sst_acpi_mach *machines) |
| 67 | { | 81 | { |
| 68 | struct sst_acpi_mach *mach; | 82 | struct sst_acpi_mach *mach; |
| 69 | bool found = false; | ||
| 70 | 83 | ||
| 71 | for (mach = machines; mach->id[0]; mach++) | 84 | for (mach = machines; mach->id[0]; mach++) { |
| 72 | if (ACPI_SUCCESS(acpi_get_devices(mach->id, | 85 | if (sst_acpi_check_hid(mach->id) == true) { |
| 73 | sst_acpi_mach_match, | 86 | if (mach->machine_quirk == NULL) |
| 74 | &found, NULL)) && found) | 87 | return mach; |
| 75 | return mach; | 88 | |
| 89 | if (mach->machine_quirk(mach) != NULL) | ||
| 90 | return mach; | ||
| 91 | } | ||
| 92 | } | ||
| 76 | return NULL; | 93 | return NULL; |
| 77 | } | 94 | } |
| 78 | EXPORT_SYMBOL_GPL(sst_acpi_find_machine); | 95 | EXPORT_SYMBOL_GPL(sst_acpi_find_machine); |
| @@ -134,5 +151,23 @@ bool sst_acpi_find_package_from_hid(const u8 hid[ACPI_ID_LEN], | |||
| 134 | } | 151 | } |
| 135 | EXPORT_SYMBOL_GPL(sst_acpi_find_package_from_hid); | 152 | EXPORT_SYMBOL_GPL(sst_acpi_find_package_from_hid); |
| 136 | 153 | ||
| 154 | struct sst_acpi_mach *sst_acpi_codec_list(void *arg) | ||
| 155 | { | ||
| 156 | struct sst_acpi_mach *mach = arg; | ||
| 157 | struct sst_codecs *codec_list = (struct sst_codecs *) mach->quirk_data; | ||
| 158 | int i; | ||
| 159 | |||
| 160 | if (mach->quirk_data == NULL) | ||
| 161 | return mach; | ||
| 162 | |||
| 163 | for (i = 0; i < codec_list->num_codecs; i++) { | ||
| 164 | if (sst_acpi_check_hid(codec_list->codecs[i]) != true) | ||
| 165 | return NULL; | ||
| 166 | } | ||
| 167 | |||
| 168 | return mach; | ||
| 169 | } | ||
| 170 | EXPORT_SYMBOL_GPL(sst_acpi_codec_list); | ||
| 171 | |||
| 137 | MODULE_LICENSE("GPL v2"); | 172 | MODULE_LICENSE("GPL v2"); |
| 138 | MODULE_DESCRIPTION("Intel Common ACPI Match module"); | 173 | MODULE_DESCRIPTION("Intel Common ACPI Match module"); |
diff --git a/sound/soc/intel/skylake/Makefile b/sound/soc/intel/skylake/Makefile index 60fbc9bbe473..e7d77722d560 100644 --- a/sound/soc/intel/skylake/Makefile +++ b/sound/soc/intel/skylake/Makefile | |||
| @@ -1,6 +1,10 @@ | |||
| 1 | snd-soc-skl-objs := skl.o skl-pcm.o skl-nhlt.o skl-messages.o \ | 1 | snd-soc-skl-objs := skl.o skl-pcm.o skl-nhlt.o skl-messages.o \ |
| 2 | skl-topology.o | 2 | skl-topology.o |
| 3 | 3 | ||
| 4 | ifdef CONFIG_DEBUG_FS | ||
| 5 | snd-soc-skl-objs += skl-debug.o | ||
| 6 | endif | ||
| 7 | |||
| 4 | obj-$(CONFIG_SND_SOC_INTEL_SKYLAKE) += snd-soc-skl.o | 8 | obj-$(CONFIG_SND_SOC_INTEL_SKYLAKE) += snd-soc-skl.o |
| 5 | 9 | ||
| 6 | # Skylake IPC Support | 10 | # Skylake IPC Support |
diff --git a/sound/soc/intel/skylake/bxt-sst.c b/sound/soc/intel/skylake/bxt-sst.c index f5e7dbb1ba39..cf11b84888b9 100644 --- a/sound/soc/intel/skylake/bxt-sst.c +++ b/sound/soc/intel/skylake/bxt-sst.c | |||
| @@ -573,6 +573,10 @@ int bxt_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, | |||
| 573 | sst->fw_ops = bxt_fw_ops; | 573 | sst->fw_ops = bxt_fw_ops; |
| 574 | sst->addr.lpe = mmio_base; | 574 | sst->addr.lpe = mmio_base; |
| 575 | sst->addr.shim = mmio_base; | 575 | sst->addr.shim = mmio_base; |
| 576 | sst->addr.sram0_base = BXT_ADSP_SRAM0_BASE; | ||
| 577 | sst->addr.sram1_base = BXT_ADSP_SRAM1_BASE; | ||
| 578 | sst->addr.w0_stat_sz = SKL_ADSP_W0_STAT_SZ; | ||
| 579 | sst->addr.w0_up_sz = SKL_ADSP_W0_UP_SZ; | ||
| 576 | 580 | ||
| 577 | sst_dsp_mailbox_init(sst, (BXT_ADSP_SRAM0_BASE + SKL_ADSP_W0_STAT_SZ), | 581 | sst_dsp_mailbox_init(sst, (BXT_ADSP_SRAM0_BASE + SKL_ADSP_W0_STAT_SZ), |
| 578 | SKL_ADSP_W0_UP_SZ, BXT_ADSP_SRAM1_BASE, SKL_ADSP_W1_SZ); | 582 | SKL_ADSP_W0_UP_SZ, BXT_ADSP_SRAM1_BASE, SKL_ADSP_W1_SZ); |
diff --git a/sound/soc/intel/skylake/skl-debug.c b/sound/soc/intel/skylake/skl-debug.c new file mode 100644 index 000000000000..75497b1fda45 --- /dev/null +++ b/sound/soc/intel/skylake/skl-debug.c | |||
| @@ -0,0 +1,268 @@ | |||
| 1 | /* | ||
| 2 | * skl-debug.c - Debugfs for skl driver | ||
| 3 | * | ||
| 4 | * Copyright (C) 2016-17 Intel Corp | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License as published by | ||
| 8 | * the Free Software Foundation; version 2 of the License. | ||
| 9 | * | ||
| 10 | * This program is distributed in the hope that it will be useful, but | ||
| 11 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 13 | * General Public License for more details. | ||
| 14 | */ | ||
| 15 | |||
| 16 | #include <linux/pci.h> | ||
| 17 | #include <linux/debugfs.h> | ||
| 18 | #include "skl.h" | ||
| 19 | #include "skl-sst-dsp.h" | ||
| 20 | #include "skl-sst-ipc.h" | ||
| 21 | #include "skl-tplg-interface.h" | ||
| 22 | #include "skl-topology.h" | ||
| 23 | #include "../common/sst-dsp-priv.h" | ||
| 24 | |||
| 25 | #define MOD_BUF PAGE_SIZE | ||
| 26 | #define FW_REG_BUF PAGE_SIZE | ||
| 27 | #define FW_REG_SIZE 0x60 | ||
| 28 | |||
| 29 | struct skl_debug { | ||
| 30 | struct skl *skl; | ||
| 31 | struct device *dev; | ||
| 32 | |||
| 33 | struct dentry *fs; | ||
| 34 | struct dentry *modules; | ||
| 35 | u8 fw_read_buff[FW_REG_BUF]; | ||
| 36 | }; | ||
| 37 | |||
| 38 | static ssize_t skl_print_pins(struct skl_module_pin *m_pin, char *buf, | ||
| 39 | int max_pin, ssize_t size, bool direction) | ||
| 40 | { | ||
| 41 | int i; | ||
| 42 | ssize_t ret = 0; | ||
| 43 | |||
| 44 | for (i = 0; i < max_pin; i++) | ||
| 45 | ret += snprintf(buf + size, MOD_BUF - size, | ||
| 46 | "%s %d\n\tModule %d\n\tInstance %d\n\t" | ||
| 47 | "In-used %s\n\tType %s\n" | ||
| 48 | "\tState %d\n\tIndex %d\n", | ||
| 49 | direction ? "Input Pin:" : "Output Pin:", | ||
| 50 | i, m_pin[i].id.module_id, | ||
| 51 | m_pin[i].id.instance_id, | ||
| 52 | m_pin[i].in_use ? "Used" : "Unused", | ||
| 53 | m_pin[i].is_dynamic ? "Dynamic" : "Static", | ||
| 54 | m_pin[i].pin_state, i); | ||
| 55 | return ret; | ||
| 56 | } | ||
| 57 | |||
| 58 | static ssize_t skl_print_fmt(struct skl_module_fmt *fmt, char *buf, | ||
| 59 | ssize_t size, bool direction) | ||
| 60 | { | ||
| 61 | return snprintf(buf + size, MOD_BUF - size, | ||
| 62 | "%s\n\tCh %d\n\tFreq %d\n\tBit depth %d\n\t" | ||
| 63 | "Valid bit depth %d\n\tCh config %#x\n\tInterleaving %d\n\t" | ||
| 64 | "Sample Type %d\n\tCh Map %#x\n", | ||
| 65 | direction ? "Input Format:" : "Output Format:", | ||
| 66 | fmt->channels, fmt->s_freq, fmt->bit_depth, | ||
| 67 | fmt->valid_bit_depth, fmt->ch_cfg, | ||
| 68 | fmt->interleaving_style, fmt->sample_type, | ||
| 69 | fmt->ch_map); | ||
| 70 | } | ||
| 71 | |||
| 72 | static ssize_t module_read(struct file *file, char __user *user_buf, | ||
| 73 | size_t count, loff_t *ppos) | ||
| 74 | { | ||
| 75 | struct skl_module_cfg *mconfig = file->private_data; | ||
| 76 | char *buf; | ||
| 77 | ssize_t ret; | ||
| 78 | |||
| 79 | buf = kzalloc(MOD_BUF, GFP_KERNEL); | ||
| 80 | if (!buf) | ||
| 81 | return -ENOMEM; | ||
| 82 | |||
| 83 | ret = snprintf(buf, MOD_BUF, "Module:\n\tUUID %pUL\n\tModule id %d\n" | ||
| 84 | "\tInstance id %d\n\tPvt_id %d\n", mconfig->guid, | ||
| 85 | mconfig->id.module_id, mconfig->id.instance_id, | ||
| 86 | mconfig->id.pvt_id); | ||
| 87 | |||
| 88 | ret += snprintf(buf + ret, MOD_BUF - ret, | ||
| 89 | "Resources:\n\tMCPS %#x\n\tIBS %#x\n\tOBS %#x\t\n", | ||
| 90 | mconfig->mcps, mconfig->ibs, mconfig->obs); | ||
| 91 | |||
| 92 | ret += snprintf(buf + ret, MOD_BUF - ret, | ||
| 93 | "Module data:\n\tCore %d\n\tIn queue %d\n\t" | ||
| 94 | "Out queue %d\n\tType %s\n", | ||
| 95 | mconfig->core_id, mconfig->max_in_queue, | ||
| 96 | mconfig->max_out_queue, | ||
| 97 | mconfig->is_loadable ? "loadable" : "inbuilt"); | ||
| 98 | |||
| 99 | ret += skl_print_fmt(mconfig->in_fmt, buf, ret, true); | ||
| 100 | ret += skl_print_fmt(mconfig->out_fmt, buf, ret, false); | ||
| 101 | |||
| 102 | ret += snprintf(buf + ret, MOD_BUF - ret, | ||
| 103 | "Fixup:\n\tParams %#x\n\tConverter %#x\n", | ||
| 104 | mconfig->params_fixup, mconfig->converter); | ||
| 105 | |||
| 106 | ret += snprintf(buf + ret, MOD_BUF - ret, | ||
| 107 | "Module Gateway:\n\tType %#x\n\tVbus %#x\n\tHW conn %#x\n\tSlot %#x\n", | ||
| 108 | mconfig->dev_type, mconfig->vbus_id, | ||
| 109 | mconfig->hw_conn_type, mconfig->time_slot); | ||
| 110 | |||
| 111 | ret += snprintf(buf + ret, MOD_BUF - ret, | ||
| 112 | "Pipeline:\n\tID %d\n\tPriority %d\n\tConn Type %d\n\t" | ||
| 113 | "Pages %#x\n", mconfig->pipe->ppl_id, | ||
| 114 | mconfig->pipe->pipe_priority, mconfig->pipe->conn_type, | ||
| 115 | mconfig->pipe->memory_pages); | ||
| 116 | |||
| 117 | ret += snprintf(buf + ret, MOD_BUF - ret, | ||
| 118 | "\tParams:\n\t\tHost DMA %d\n\t\tLink DMA %d\n", | ||
| 119 | mconfig->pipe->p_params->host_dma_id, | ||
| 120 | mconfig->pipe->p_params->link_dma_id); | ||
| 121 | |||
| 122 | ret += snprintf(buf + ret, MOD_BUF - ret, | ||
| 123 | "\tPCM params:\n\t\tCh %d\n\t\tFreq %d\n\t\tFormat %d\n", | ||
| 124 | mconfig->pipe->p_params->ch, | ||
| 125 | mconfig->pipe->p_params->s_freq, | ||
| 126 | mconfig->pipe->p_params->s_fmt); | ||
| 127 | |||
| 128 | ret += snprintf(buf + ret, MOD_BUF - ret, | ||
| 129 | "\tLink %#x\n\tStream %#x\n", | ||
| 130 | mconfig->pipe->p_params->linktype, | ||
| 131 | mconfig->pipe->p_params->stream); | ||
| 132 | |||
| 133 | ret += snprintf(buf + ret, MOD_BUF - ret, | ||
| 134 | "\tState %d\n\tPassthru %s\n", | ||
| 135 | mconfig->pipe->state, | ||
| 136 | mconfig->pipe->passthru ? "true" : "false"); | ||
| 137 | |||
| 138 | ret += skl_print_pins(mconfig->m_in_pin, buf, | ||
| 139 | mconfig->max_in_queue, ret, true); | ||
| 140 | ret += skl_print_pins(mconfig->m_out_pin, buf, | ||
| 141 | mconfig->max_out_queue, ret, false); | ||
| 142 | |||
| 143 | ret += snprintf(buf + ret, MOD_BUF - ret, | ||
| 144 | "Other:\n\tDomain %d\n\tHomogenous Input %s\n\t" | ||
| 145 | "Homogenous Output %s\n\tIn Queue Mask %d\n\t" | ||
| 146 | "Out Queue Mask %d\n\tDMA ID %d\n\tMem Pages %d\n\t" | ||
| 147 | "Module Type %d\n\tModule State %d\n", | ||
| 148 | mconfig->domain, | ||
| 149 | mconfig->homogenous_inputs ? "true" : "false", | ||
| 150 | mconfig->homogenous_outputs ? "true" : "false", | ||
| 151 | mconfig->in_queue_mask, mconfig->out_queue_mask, | ||
| 152 | mconfig->dma_id, mconfig->mem_pages, mconfig->m_state, | ||
| 153 | mconfig->m_type); | ||
| 154 | |||
| 155 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret); | ||
| 156 | |||
| 157 | kfree(buf); | ||
| 158 | return ret; | ||
| 159 | } | ||
| 160 | |||
| 161 | static const struct file_operations mcfg_fops = { | ||
| 162 | .open = simple_open, | ||
| 163 | .read = module_read, | ||
| 164 | .llseek = default_llseek, | ||
| 165 | }; | ||
| 166 | |||
| 167 | |||
| 168 | void skl_debug_init_module(struct skl_debug *d, | ||
| 169 | struct snd_soc_dapm_widget *w, | ||
| 170 | struct skl_module_cfg *mconfig) | ||
| 171 | { | ||
| 172 | if (!debugfs_create_file(w->name, 0444, | ||
| 173 | d->modules, mconfig, | ||
| 174 | &mcfg_fops)) | ||
| 175 | dev_err(d->dev, "%s: module debugfs init failed\n", w->name); | ||
| 176 | } | ||
| 177 | |||
| 178 | static ssize_t fw_softreg_read(struct file *file, char __user *user_buf, | ||
| 179 | size_t count, loff_t *ppos) | ||
| 180 | { | ||
| 181 | struct skl_debug *d = file->private_data; | ||
| 182 | struct sst_dsp *sst = d->skl->skl_sst->dsp; | ||
| 183 | size_t w0_stat_sz = sst->addr.w0_stat_sz; | ||
| 184 | void __iomem *in_base = sst->mailbox.in_base; | ||
| 185 | void __iomem *fw_reg_addr; | ||
| 186 | unsigned int offset; | ||
| 187 | char *tmp; | ||
| 188 | ssize_t ret = 0; | ||
| 189 | |||
| 190 | tmp = kzalloc(FW_REG_BUF, GFP_KERNEL); | ||
| 191 | if (!tmp) | ||
| 192 | return -ENOMEM; | ||
| 193 | |||
| 194 | fw_reg_addr = in_base - w0_stat_sz; | ||
| 195 | memset(d->fw_read_buff, 0, FW_REG_BUF); | ||
| 196 | |||
| 197 | if (w0_stat_sz > 0) | ||
| 198 | __iowrite32_copy(d->fw_read_buff, fw_reg_addr, w0_stat_sz >> 2); | ||
| 199 | |||
| 200 | for (offset = 0; offset < FW_REG_SIZE; offset += 16) { | ||
| 201 | ret += snprintf(tmp + ret, FW_REG_BUF - ret, "%#.4x: ", offset); | ||
| 202 | hex_dump_to_buffer(d->fw_read_buff + offset, 16, 16, 4, | ||
| 203 | tmp + ret, FW_REG_BUF - ret, 0); | ||
| 204 | ret += strlen(tmp + ret); | ||
| 205 | |||
| 206 | /* print newline for each offset */ | ||
| 207 | if (FW_REG_BUF - ret > 0) | ||
| 208 | tmp[ret++] = '\n'; | ||
| 209 | } | ||
| 210 | |||
| 211 | ret = simple_read_from_buffer(user_buf, count, ppos, tmp, ret); | ||
| 212 | kfree(tmp); | ||
| 213 | |||
| 214 | return ret; | ||
| 215 | } | ||
| 216 | |||
| 217 | static const struct file_operations soft_regs_ctrl_fops = { | ||
| 218 | .open = simple_open, | ||
| 219 | .read = fw_softreg_read, | ||
| 220 | .llseek = default_llseek, | ||
| 221 | }; | ||
| 222 | |||
| 223 | struct skl_debug *skl_debugfs_init(struct skl *skl) | ||
| 224 | { | ||
| 225 | struct skl_debug *d; | ||
| 226 | |||
| 227 | d = devm_kzalloc(&skl->pci->dev, sizeof(*d), GFP_KERNEL); | ||
| 228 | if (!d) | ||
| 229 | return NULL; | ||
| 230 | |||
| 231 | /* create the debugfs dir with platform component's debugfs as parent */ | ||
| 232 | d->fs = debugfs_create_dir("dsp", | ||
| 233 | skl->platform->component.debugfs_root); | ||
| 234 | if (IS_ERR(d->fs) || !d->fs) { | ||
| 235 | dev_err(&skl->pci->dev, "debugfs root creation failed\n"); | ||
| 236 | return NULL; | ||
| 237 | } | ||
| 238 | |||
| 239 | d->skl = skl; | ||
| 240 | d->dev = &skl->pci->dev; | ||
| 241 | |||
| 242 | /* now create the module dir */ | ||
| 243 | d->modules = debugfs_create_dir("modules", d->fs); | ||
| 244 | if (IS_ERR(d->modules) || !d->modules) { | ||
| 245 | dev_err(&skl->pci->dev, "modules debugfs create failed\n"); | ||
| 246 | goto err; | ||
| 247 | } | ||
| 248 | |||
| 249 | if (!debugfs_create_file("fw_soft_regs_rd", 0444, d->fs, d, | ||
| 250 | &soft_regs_ctrl_fops)) { | ||
| 251 | dev_err(d->dev, "fw soft regs control debugfs init failed\n"); | ||
| 252 | goto err; | ||
| 253 | } | ||
| 254 | |||
| 255 | return d; | ||
| 256 | |||
| 257 | err: | ||
| 258 | debugfs_remove_recursive(d->fs); | ||
| 259 | return NULL; | ||
| 260 | } | ||
| 261 | |||
| 262 | void skl_debugfs_exit(struct skl_debug *d) | ||
| 263 | { | ||
| 264 | debugfs_remove_recursive(d->fs); | ||
| 265 | |||
| 266 | kfree(d); | ||
| 267 | |||
| 268 | } | ||
diff --git a/sound/soc/intel/skylake/skl-messages.c b/sound/soc/intel/skylake/skl-messages.c index ab1adc0c9cc3..eca85827dbd2 100644 --- a/sound/soc/intel/skylake/skl-messages.c +++ b/sound/soc/intel/skylake/skl-messages.c | |||
| @@ -507,6 +507,8 @@ static void skl_setup_cpr_gateway_cfg(struct skl_sst *ctx, | |||
| 507 | struct skl_module_cfg *mconfig, | 507 | struct skl_module_cfg *mconfig, |
| 508 | struct skl_cpr_cfg *cpr_mconfig) | 508 | struct skl_cpr_cfg *cpr_mconfig) |
| 509 | { | 509 | { |
| 510 | u32 dma_io_buf; | ||
| 511 | |||
| 510 | cpr_mconfig->gtw_cfg.node_id = skl_get_node_id(ctx, mconfig); | 512 | cpr_mconfig->gtw_cfg.node_id = skl_get_node_id(ctx, mconfig); |
| 511 | 513 | ||
| 512 | if (cpr_mconfig->gtw_cfg.node_id == SKL_NON_GATEWAY_CPR_NODE_ID) { | 514 | if (cpr_mconfig->gtw_cfg.node_id == SKL_NON_GATEWAY_CPR_NODE_ID) { |
| @@ -514,10 +516,29 @@ static void skl_setup_cpr_gateway_cfg(struct skl_sst *ctx, | |||
| 514 | return; | 516 | return; |
| 515 | } | 517 | } |
| 516 | 518 | ||
| 517 | if (SKL_CONN_SOURCE == mconfig->hw_conn_type) | 519 | switch (mconfig->hw_conn_type) { |
| 518 | cpr_mconfig->gtw_cfg.dma_buffer_size = 2 * mconfig->obs; | 520 | case SKL_CONN_SOURCE: |
| 519 | else | 521 | if (mconfig->dev_type == SKL_DEVICE_HDAHOST) |
| 520 | cpr_mconfig->gtw_cfg.dma_buffer_size = 2 * mconfig->ibs; | 522 | dma_io_buf = mconfig->ibs; |
| 523 | else | ||
| 524 | dma_io_buf = mconfig->obs; | ||
| 525 | break; | ||
| 526 | |||
| 527 | case SKL_CONN_SINK: | ||
| 528 | if (mconfig->dev_type == SKL_DEVICE_HDAHOST) | ||
| 529 | dma_io_buf = mconfig->obs; | ||
| 530 | else | ||
| 531 | dma_io_buf = mconfig->ibs; | ||
| 532 | break; | ||
| 533 | |||
| 534 | default: | ||
| 535 | dev_warn(ctx->dev, "wrong connection type: %d\n", | ||
| 536 | mconfig->hw_conn_type); | ||
| 537 | return; | ||
| 538 | } | ||
| 539 | |||
| 540 | cpr_mconfig->gtw_cfg.dma_buffer_size = | ||
| 541 | mconfig->dma_buffer_size * dma_io_buf; | ||
| 521 | 542 | ||
| 522 | cpr_mconfig->cpr_feature_mask = 0; | 543 | cpr_mconfig->cpr_feature_mask = 0; |
| 523 | cpr_mconfig->gtw_cfg.config_length = 0; | 544 | cpr_mconfig->gtw_cfg.config_length = 0; |
| @@ -707,6 +728,7 @@ static u16 skl_get_module_param_size(struct skl_sst *ctx, | |||
| 707 | return param_size; | 728 | return param_size; |
| 708 | 729 | ||
| 709 | case SKL_MODULE_TYPE_BASE_OUTFMT: | 730 | case SKL_MODULE_TYPE_BASE_OUTFMT: |
| 731 | case SKL_MODULE_TYPE_MIC_SELECT: | ||
| 710 | case SKL_MODULE_TYPE_KPB: | 732 | case SKL_MODULE_TYPE_KPB: |
| 711 | return sizeof(struct skl_base_outfmt_cfg); | 733 | return sizeof(struct skl_base_outfmt_cfg); |
| 712 | 734 | ||
| @@ -761,6 +783,7 @@ static int skl_set_module_format(struct skl_sst *ctx, | |||
| 761 | break; | 783 | break; |
| 762 | 784 | ||
| 763 | case SKL_MODULE_TYPE_BASE_OUTFMT: | 785 | case SKL_MODULE_TYPE_BASE_OUTFMT: |
| 786 | case SKL_MODULE_TYPE_MIC_SELECT: | ||
| 764 | case SKL_MODULE_TYPE_KPB: | 787 | case SKL_MODULE_TYPE_KPB: |
| 765 | skl_set_base_outfmt_format(ctx, module_config, *param_data); | 788 | skl_set_base_outfmt_format(ctx, module_config, *param_data); |
| 766 | break; | 789 | break; |
diff --git a/sound/soc/intel/skylake/skl-pcm.c b/sound/soc/intel/skylake/skl-pcm.c index e91bbcffc856..0ebea34a4988 100644 --- a/sound/soc/intel/skylake/skl-pcm.c +++ b/sound/soc/intel/skylake/skl-pcm.c | |||
| @@ -1249,12 +1249,16 @@ static int skl_platform_soc_probe(struct snd_soc_platform *platform) | |||
| 1249 | 1249 | ||
| 1250 | pm_runtime_get_sync(platform->dev); | 1250 | pm_runtime_get_sync(platform->dev); |
| 1251 | if ((ebus_to_hbus(ebus))->ppcap) { | 1251 | if ((ebus_to_hbus(ebus))->ppcap) { |
| 1252 | skl->platform = platform; | ||
| 1253 | |||
| 1254 | /* init debugfs */ | ||
| 1255 | skl->debugfs = skl_debugfs_init(skl); | ||
| 1256 | |||
| 1252 | ret = skl_tplg_init(platform, ebus); | 1257 | ret = skl_tplg_init(platform, ebus); |
| 1253 | if (ret < 0) { | 1258 | if (ret < 0) { |
| 1254 | dev_err(platform->dev, "Failed to init topology!\n"); | 1259 | dev_err(platform->dev, "Failed to init topology!\n"); |
| 1255 | return ret; | 1260 | return ret; |
| 1256 | } | 1261 | } |
| 1257 | skl->platform = platform; | ||
| 1258 | 1262 | ||
| 1259 | /* load the firmwares, since all is set */ | 1263 | /* load the firmwares, since all is set */ |
| 1260 | ops = skl_get_dsp_ops(skl->pci->device); | 1264 | ops = skl_get_dsp_ops(skl->pci->device); |
diff --git a/sound/soc/intel/skylake/skl-sst.c b/sound/soc/intel/skylake/skl-sst.c index 155e456b7a3a..aba9ea11ac74 100644 --- a/sound/soc/intel/skylake/skl-sst.c +++ b/sound/soc/intel/skylake/skl-sst.c | |||
| @@ -553,6 +553,11 @@ int skl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, | |||
| 553 | sst = skl->dsp; | 553 | sst = skl->dsp; |
| 554 | sst->addr.lpe = mmio_base; | 554 | sst->addr.lpe = mmio_base; |
| 555 | sst->addr.shim = mmio_base; | 555 | sst->addr.shim = mmio_base; |
| 556 | sst->addr.sram0_base = SKL_ADSP_SRAM0_BASE; | ||
| 557 | sst->addr.sram1_base = SKL_ADSP_SRAM1_BASE; | ||
| 558 | sst->addr.w0_stat_sz = SKL_ADSP_W0_STAT_SZ; | ||
| 559 | sst->addr.w0_up_sz = SKL_ADSP_W0_UP_SZ; | ||
| 560 | |||
| 556 | sst_dsp_mailbox_init(sst, (SKL_ADSP_SRAM0_BASE + SKL_ADSP_W0_STAT_SZ), | 561 | sst_dsp_mailbox_init(sst, (SKL_ADSP_SRAM0_BASE + SKL_ADSP_W0_STAT_SZ), |
| 557 | SKL_ADSP_W0_UP_SZ, SKL_ADSP_SRAM1_BASE, SKL_ADSP_W1_SZ); | 562 | SKL_ADSP_W0_UP_SZ, SKL_ADSP_SRAM1_BASE, SKL_ADSP_W1_SZ); |
| 558 | 563 | ||
diff --git a/sound/soc/intel/skylake/skl-topology.c b/sound/soc/intel/skylake/skl-topology.c index 64a0f8ed33e1..68c3f121efc3 100644 --- a/sound/soc/intel/skylake/skl-topology.c +++ b/sound/soc/intel/skylake/skl-topology.c | |||
| @@ -36,6 +36,19 @@ | |||
| 36 | #define SKL_IN_DIR_BIT_MASK BIT(0) | 36 | #define SKL_IN_DIR_BIT_MASK BIT(0) |
| 37 | #define SKL_PIN_COUNT_MASK GENMASK(7, 4) | 37 | #define SKL_PIN_COUNT_MASK GENMASK(7, 4) |
| 38 | 38 | ||
| 39 | static const int mic_mono_list[] = { | ||
| 40 | 0, 1, 2, 3, | ||
| 41 | }; | ||
| 42 | static const int mic_stereo_list[][SKL_CH_STEREO] = { | ||
| 43 | {0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}, | ||
| 44 | }; | ||
| 45 | static const int mic_trio_list[][SKL_CH_TRIO] = { | ||
| 46 | {0, 1, 2}, {0, 1, 3}, {0, 2, 3}, {1, 2, 3}, | ||
| 47 | }; | ||
| 48 | static const int mic_quatro_list[][SKL_CH_QUATRO] = { | ||
| 49 | {0, 1, 2, 3}, | ||
| 50 | }; | ||
| 51 | |||
| 39 | void skl_tplg_d0i3_get(struct skl *skl, enum d0i3_capability caps) | 52 | void skl_tplg_d0i3_get(struct skl *skl, enum d0i3_capability caps) |
| 40 | { | 53 | { |
| 41 | struct skl_d0i3_data *d0i3 = &skl->skl_sst->d0i3; | 54 | struct skl_d0i3_data *d0i3 = &skl->skl_sst->d0i3; |
| @@ -1314,6 +1327,111 @@ static int skl_tplg_tlv_control_set(struct snd_kcontrol *kcontrol, | |||
| 1314 | return 0; | 1327 | return 0; |
| 1315 | } | 1328 | } |
| 1316 | 1329 | ||
| 1330 | static int skl_tplg_mic_control_get(struct snd_kcontrol *kcontrol, | ||
| 1331 | struct snd_ctl_elem_value *ucontrol) | ||
| 1332 | { | ||
| 1333 | struct snd_soc_dapm_widget *w = snd_soc_dapm_kcontrol_widget(kcontrol); | ||
| 1334 | struct skl_module_cfg *mconfig = w->priv; | ||
| 1335 | struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value; | ||
| 1336 | u32 ch_type = *((u32 *)ec->dobj.private); | ||
| 1337 | |||
| 1338 | if (mconfig->dmic_ch_type == ch_type) | ||
| 1339 | ucontrol->value.enumerated.item[0] = | ||
| 1340 | mconfig->dmic_ch_combo_index; | ||
| 1341 | else | ||
| 1342 | ucontrol->value.enumerated.item[0] = 0; | ||
| 1343 | |||
| 1344 | return 0; | ||
| 1345 | } | ||
| 1346 | |||
| 1347 | static int skl_fill_mic_sel_params(struct skl_module_cfg *mconfig, | ||
| 1348 | struct skl_mic_sel_config *mic_cfg, struct device *dev) | ||
| 1349 | { | ||
| 1350 | struct skl_specific_cfg *sp_cfg = &mconfig->formats_config; | ||
| 1351 | |||
| 1352 | sp_cfg->caps_size = sizeof(struct skl_mic_sel_config); | ||
| 1353 | sp_cfg->set_params = SKL_PARAM_SET; | ||
| 1354 | sp_cfg->param_id = 0x00; | ||
| 1355 | if (!sp_cfg->caps) { | ||
| 1356 | sp_cfg->caps = devm_kzalloc(dev, sp_cfg->caps_size, GFP_KERNEL); | ||
| 1357 | if (!sp_cfg->caps) | ||
| 1358 | return -ENOMEM; | ||
| 1359 | } | ||
| 1360 | |||
| 1361 | mic_cfg->mic_switch = SKL_MIC_SEL_SWITCH; | ||
| 1362 | mic_cfg->flags = 0; | ||
| 1363 | memcpy(sp_cfg->caps, mic_cfg, sp_cfg->caps_size); | ||
| 1364 | |||
| 1365 | return 0; | ||
| 1366 | } | ||
| 1367 | |||
| 1368 | static int skl_tplg_mic_control_set(struct snd_kcontrol *kcontrol, | ||
| 1369 | struct snd_ctl_elem_value *ucontrol) | ||
| 1370 | { | ||
| 1371 | struct snd_soc_dapm_widget *w = snd_soc_dapm_kcontrol_widget(kcontrol); | ||
| 1372 | struct skl_module_cfg *mconfig = w->priv; | ||
| 1373 | struct skl_mic_sel_config mic_cfg = {0}; | ||
| 1374 | struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value; | ||
| 1375 | u32 ch_type = *((u32 *)ec->dobj.private); | ||
| 1376 | const int *list; | ||
| 1377 | u8 in_ch, out_ch, index; | ||
| 1378 | |||
| 1379 | mconfig->dmic_ch_type = ch_type; | ||
| 1380 | mconfig->dmic_ch_combo_index = ucontrol->value.enumerated.item[0]; | ||
| 1381 | |||
| 1382 | /* enum control index 0 is INVALID, so no channels to be set */ | ||
| 1383 | if (mconfig->dmic_ch_combo_index == 0) | ||
| 1384 | return 0; | ||
| 1385 | |||
| 1386 | /* No valid channel selection map for index 0, so offset by 1 */ | ||
| 1387 | index = mconfig->dmic_ch_combo_index - 1; | ||
| 1388 | |||
| 1389 | switch (ch_type) { | ||
| 1390 | case SKL_CH_MONO: | ||
| 1391 | if (mconfig->dmic_ch_combo_index > ARRAY_SIZE(mic_mono_list)) | ||
| 1392 | return -EINVAL; | ||
| 1393 | |||
| 1394 | list = &mic_mono_list[index]; | ||
| 1395 | break; | ||
| 1396 | |||
| 1397 | case SKL_CH_STEREO: | ||
| 1398 | if (mconfig->dmic_ch_combo_index > ARRAY_SIZE(mic_stereo_list)) | ||
| 1399 | return -EINVAL; | ||
| 1400 | |||
| 1401 | list = mic_stereo_list[index]; | ||
| 1402 | break; | ||
| 1403 | |||
| 1404 | case SKL_CH_TRIO: | ||
| 1405 | if (mconfig->dmic_ch_combo_index > ARRAY_SIZE(mic_trio_list)) | ||
| 1406 | return -EINVAL; | ||
| 1407 | |||
| 1408 | list = mic_trio_list[index]; | ||
| 1409 | break; | ||
| 1410 | |||
| 1411 | case SKL_CH_QUATRO: | ||
| 1412 | if (mconfig->dmic_ch_combo_index > ARRAY_SIZE(mic_quatro_list)) | ||
| 1413 | return -EINVAL; | ||
| 1414 | |||
| 1415 | list = mic_quatro_list[index]; | ||
| 1416 | break; | ||
| 1417 | |||
| 1418 | default: | ||
| 1419 | dev_err(w->dapm->dev, | ||
| 1420 | "Invalid channel %d for mic_select module\n", | ||
| 1421 | ch_type); | ||
| 1422 | return -EINVAL; | ||
| 1423 | |||
| 1424 | } | ||
| 1425 | |||
| 1426 | /* channel type enum map to number of chanels for that type */ | ||
| 1427 | for (out_ch = 0; out_ch < ch_type; out_ch++) { | ||
| 1428 | in_ch = list[out_ch]; | ||
| 1429 | mic_cfg.blob[out_ch][in_ch] = SKL_DEFAULT_MIC_SEL_GAIN; | ||
| 1430 | } | ||
| 1431 | |||
| 1432 | return skl_fill_mic_sel_params(mconfig, &mic_cfg, w->dapm->dev); | ||
| 1433 | } | ||
| 1434 | |||
| 1317 | /* | 1435 | /* |
| 1318 | * Fill the dma id for host and link. In case of passthrough | 1436 | * Fill the dma id for host and link. In case of passthrough |
| 1319 | * pipeline, this will both host and link in the same | 1437 | * pipeline, this will both host and link in the same |
| @@ -1666,6 +1784,14 @@ static const struct snd_soc_tplg_bytes_ext_ops skl_tlv_ops[] = { | |||
| 1666 | skl_tplg_tlv_control_set}, | 1784 | skl_tplg_tlv_control_set}, |
| 1667 | }; | 1785 | }; |
| 1668 | 1786 | ||
| 1787 | static const struct snd_soc_tplg_kcontrol_ops skl_tplg_kcontrol_ops[] = { | ||
| 1788 | { | ||
| 1789 | .id = SKL_CONTROL_TYPE_MIC_SELECT, | ||
| 1790 | .get = skl_tplg_mic_control_get, | ||
| 1791 | .put = skl_tplg_mic_control_set, | ||
| 1792 | }, | ||
| 1793 | }; | ||
| 1794 | |||
| 1669 | static int skl_tplg_fill_pipe_tkn(struct device *dev, | 1795 | static int skl_tplg_fill_pipe_tkn(struct device *dev, |
| 1670 | struct skl_pipe *pipe, u32 tkn, | 1796 | struct skl_pipe *pipe, u32 tkn, |
| 1671 | u32 tkn_val) | 1797 | u32 tkn_val) |
| @@ -1995,7 +2121,7 @@ static int skl_tplg_get_token(struct device *dev, | |||
| 1995 | mconfig->converter = tkn_elem->value; | 2121 | mconfig->converter = tkn_elem->value; |
| 1996 | break; | 2122 | break; |
| 1997 | 2123 | ||
| 1998 | case SKL_TKL_U32_D0I3_CAPS: | 2124 | case SKL_TKN_U32_D0I3_CAPS: |
| 1999 | mconfig->d0i3_caps = tkn_elem->value; | 2125 | mconfig->d0i3_caps = tkn_elem->value; |
| 2000 | break; | 2126 | break; |
| 2001 | 2127 | ||
| @@ -2070,12 +2196,26 @@ static int skl_tplg_get_token(struct device *dev, | |||
| 2070 | 2196 | ||
| 2071 | break; | 2197 | break; |
| 2072 | 2198 | ||
| 2199 | case SKL_TKN_U32_CAPS_SET_PARAMS: | ||
| 2200 | mconfig->formats_config.set_params = | ||
| 2201 | tkn_elem->value; | ||
| 2202 | break; | ||
| 2203 | |||
| 2204 | case SKL_TKN_U32_CAPS_PARAMS_ID: | ||
| 2205 | mconfig->formats_config.param_id = | ||
| 2206 | tkn_elem->value; | ||
| 2207 | break; | ||
| 2208 | |||
| 2073 | case SKL_TKN_U32_PROC_DOMAIN: | 2209 | case SKL_TKN_U32_PROC_DOMAIN: |
| 2074 | mconfig->domain = | 2210 | mconfig->domain = |
| 2075 | tkn_elem->value; | 2211 | tkn_elem->value; |
| 2076 | 2212 | ||
| 2077 | break; | 2213 | break; |
| 2078 | 2214 | ||
| 2215 | case SKL_TKN_U32_DMA_BUF_SIZE: | ||
| 2216 | mconfig->dma_buffer_size = tkn_elem->value; | ||
| 2217 | break; | ||
| 2218 | |||
| 2079 | case SKL_TKN_U8_IN_PIN_TYPE: | 2219 | case SKL_TKN_U8_IN_PIN_TYPE: |
| 2080 | case SKL_TKN_U8_OUT_PIN_TYPE: | 2220 | case SKL_TKN_U8_OUT_PIN_TYPE: |
| 2081 | case SKL_TKN_U8_CONN_TYPE: | 2221 | case SKL_TKN_U8_CONN_TYPE: |
| @@ -2147,7 +2287,7 @@ static int skl_tplg_get_tokens(struct device *dev, | |||
| 2147 | tuple_size += tkn_count * sizeof(*tkn_elem); | 2287 | tuple_size += tkn_count * sizeof(*tkn_elem); |
| 2148 | } | 2288 | } |
| 2149 | 2289 | ||
| 2150 | return 0; | 2290 | return off; |
| 2151 | } | 2291 | } |
| 2152 | 2292 | ||
| 2153 | /* | 2293 | /* |
| @@ -2198,10 +2338,11 @@ static int skl_tplg_get_pvt_data(struct snd_soc_tplg_dapm_widget *tplg_w, | |||
| 2198 | num_blocks = ret; | 2338 | num_blocks = ret; |
| 2199 | 2339 | ||
| 2200 | off += array->size; | 2340 | off += array->size; |
| 2201 | array = (struct snd_soc_tplg_vendor_array *)(tplg_w->priv.data + off); | ||
| 2202 | |||
| 2203 | /* Read the BLOCK_TYPE and BLOCK_SIZE descriptor */ | 2341 | /* Read the BLOCK_TYPE and BLOCK_SIZE descriptor */ |
| 2204 | while (num_blocks > 0) { | 2342 | while (num_blocks > 0) { |
| 2343 | array = (struct snd_soc_tplg_vendor_array *) | ||
| 2344 | (tplg_w->priv.data + off); | ||
| 2345 | |||
| 2205 | ret = skl_tplg_get_desc_blocks(dev, array); | 2346 | ret = skl_tplg_get_desc_blocks(dev, array); |
| 2206 | 2347 | ||
| 2207 | if (ret < 0) | 2348 | if (ret < 0) |
| @@ -2237,7 +2378,9 @@ static int skl_tplg_get_pvt_data(struct snd_soc_tplg_dapm_widget *tplg_w, | |||
| 2237 | memcpy(mconfig->formats_config.caps, data, | 2378 | memcpy(mconfig->formats_config.caps, data, |
| 2238 | mconfig->formats_config.caps_size); | 2379 | mconfig->formats_config.caps_size); |
| 2239 | --num_blocks; | 2380 | --num_blocks; |
| 2381 | ret = mconfig->formats_config.caps_size; | ||
| 2240 | } | 2382 | } |
| 2383 | off += ret; | ||
| 2241 | } | 2384 | } |
| 2242 | 2385 | ||
| 2243 | return 0; | 2386 | return 0; |
| @@ -2329,6 +2472,9 @@ static int skl_tplg_widget_load(struct snd_soc_component *cmpnt, | |||
| 2329 | ret = skl_tplg_get_pvt_data(tplg_w, skl, bus->dev, mconfig); | 2472 | ret = skl_tplg_get_pvt_data(tplg_w, skl, bus->dev, mconfig); |
| 2330 | if (ret < 0) | 2473 | if (ret < 0) |
| 2331 | return ret; | 2474 | return ret; |
| 2475 | |||
| 2476 | skl_debug_init_module(skl->debugfs, w, mconfig); | ||
| 2477 | |||
| 2332 | bind_event: | 2478 | bind_event: |
| 2333 | if (tplg_w->event_type == 0) { | 2479 | if (tplg_w->event_type == 0) { |
| 2334 | dev_dbg(bus->dev, "ASoC: No event handler required\n"); | 2480 | dev_dbg(bus->dev, "ASoC: No event handler required\n"); |
| @@ -2377,14 +2523,34 @@ static int skl_init_algo_data(struct device *dev, struct soc_bytes_ext *be, | |||
| 2377 | return 0; | 2523 | return 0; |
| 2378 | } | 2524 | } |
| 2379 | 2525 | ||
| 2526 | static int skl_init_enum_data(struct device *dev, struct soc_enum *se, | ||
| 2527 | struct snd_soc_tplg_enum_control *ec) | ||
| 2528 | { | ||
| 2529 | |||
| 2530 | void *data; | ||
| 2531 | |||
| 2532 | if (ec->priv.size) { | ||
| 2533 | data = devm_kzalloc(dev, sizeof(ec->priv.size), GFP_KERNEL); | ||
| 2534 | if (!data) | ||
| 2535 | return -ENOMEM; | ||
| 2536 | memcpy(data, ec->priv.data, ec->priv.size); | ||
| 2537 | se->dobj.private = data; | ||
| 2538 | } | ||
| 2539 | |||
| 2540 | return 0; | ||
| 2541 | |||
| 2542 | } | ||
| 2543 | |||
| 2380 | static int skl_tplg_control_load(struct snd_soc_component *cmpnt, | 2544 | static int skl_tplg_control_load(struct snd_soc_component *cmpnt, |
| 2381 | struct snd_kcontrol_new *kctl, | 2545 | struct snd_kcontrol_new *kctl, |
| 2382 | struct snd_soc_tplg_ctl_hdr *hdr) | 2546 | struct snd_soc_tplg_ctl_hdr *hdr) |
| 2383 | { | 2547 | { |
| 2384 | struct soc_bytes_ext *sb; | 2548 | struct soc_bytes_ext *sb; |
| 2385 | struct snd_soc_tplg_bytes_control *tplg_bc; | 2549 | struct snd_soc_tplg_bytes_control *tplg_bc; |
| 2550 | struct snd_soc_tplg_enum_control *tplg_ec; | ||
| 2386 | struct hdac_ext_bus *ebus = snd_soc_component_get_drvdata(cmpnt); | 2551 | struct hdac_ext_bus *ebus = snd_soc_component_get_drvdata(cmpnt); |
| 2387 | struct hdac_bus *bus = ebus_to_hbus(ebus); | 2552 | struct hdac_bus *bus = ebus_to_hbus(ebus); |
| 2553 | struct soc_enum *se; | ||
| 2388 | 2554 | ||
| 2389 | switch (hdr->ops.info) { | 2555 | switch (hdr->ops.info) { |
| 2390 | case SND_SOC_TPLG_CTL_BYTES: | 2556 | case SND_SOC_TPLG_CTL_BYTES: |
| @@ -2398,6 +2564,17 @@ static int skl_tplg_control_load(struct snd_soc_component *cmpnt, | |||
| 2398 | } | 2564 | } |
| 2399 | break; | 2565 | break; |
| 2400 | 2566 | ||
| 2567 | case SND_SOC_TPLG_CTL_ENUM: | ||
| 2568 | tplg_ec = container_of(hdr, | ||
| 2569 | struct snd_soc_tplg_enum_control, hdr); | ||
| 2570 | if (kctl->access & SNDRV_CTL_ELEM_ACCESS_READWRITE) { | ||
| 2571 | se = (struct soc_enum *)kctl->private_value; | ||
| 2572 | if (tplg_ec->priv.size) | ||
| 2573 | return skl_init_enum_data(bus->dev, se, | ||
| 2574 | tplg_ec); | ||
| 2575 | } | ||
| 2576 | break; | ||
| 2577 | |||
| 2401 | default: | 2578 | default: |
| 2402 | dev_warn(bus->dev, "Control load not supported %d:%d:%d\n", | 2579 | dev_warn(bus->dev, "Control load not supported %d:%d:%d\n", |
| 2403 | hdr->ops.get, hdr->ops.put, hdr->ops.info); | 2580 | hdr->ops.get, hdr->ops.put, hdr->ops.info); |
| @@ -2626,6 +2803,8 @@ static struct snd_soc_tplg_ops skl_tplg_ops = { | |||
| 2626 | .control_load = skl_tplg_control_load, | 2803 | .control_load = skl_tplg_control_load, |
| 2627 | .bytes_ext_ops = skl_tlv_ops, | 2804 | .bytes_ext_ops = skl_tlv_ops, |
| 2628 | .bytes_ext_ops_count = ARRAY_SIZE(skl_tlv_ops), | 2805 | .bytes_ext_ops_count = ARRAY_SIZE(skl_tlv_ops), |
| 2806 | .io_ops = skl_tplg_kcontrol_ops, | ||
| 2807 | .io_ops_count = ARRAY_SIZE(skl_tplg_kcontrol_ops), | ||
| 2629 | .manifest = skl_manifest_load, | 2808 | .manifest = skl_manifest_load, |
| 2630 | }; | 2809 | }; |
| 2631 | 2810 | ||
diff --git a/sound/soc/intel/skylake/skl-topology.h b/sound/soc/intel/skylake/skl-topology.h index cc64d6bdb4f6..c25e8868b84e 100644 --- a/sound/soc/intel/skylake/skl-topology.h +++ b/sound/soc/intel/skylake/skl-topology.h | |||
| @@ -39,6 +39,11 @@ | |||
| 39 | #define MODULE_MAX_IN_PINS 8 | 39 | #define MODULE_MAX_IN_PINS 8 |
| 40 | #define MODULE_MAX_OUT_PINS 8 | 40 | #define MODULE_MAX_OUT_PINS 8 |
| 41 | 41 | ||
| 42 | #define SKL_MIC_CH_SUPPORT 4 | ||
| 43 | #define SKL_MIC_MAX_CH_SUPPORT 8 | ||
| 44 | #define SKL_DEFAULT_MIC_SEL_GAIN 0x3FF | ||
| 45 | #define SKL_MIC_SEL_SWITCH 0x3 | ||
| 46 | |||
| 42 | enum skl_channel_index { | 47 | enum skl_channel_index { |
| 43 | SKL_CHANNEL_LEFT = 0, | 48 | SKL_CHANNEL_LEFT = 0, |
| 44 | SKL_CHANNEL_RIGHT = 1, | 49 | SKL_CHANNEL_RIGHT = 1, |
| @@ -309,11 +314,14 @@ struct skl_module_cfg { | |||
| 309 | u8 dev_type; | 314 | u8 dev_type; |
| 310 | u8 dma_id; | 315 | u8 dma_id; |
| 311 | u8 time_slot; | 316 | u8 time_slot; |
| 317 | u8 dmic_ch_combo_index; | ||
| 318 | u32 dmic_ch_type; | ||
| 312 | u32 params_fixup; | 319 | u32 params_fixup; |
| 313 | u32 converter; | 320 | u32 converter; |
| 314 | u32 vbus_id; | 321 | u32 vbus_id; |
| 315 | u32 mem_pages; | 322 | u32 mem_pages; |
| 316 | enum d0i3_capability d0i3_caps; | 323 | enum d0i3_capability d0i3_caps; |
| 324 | u32 dma_buffer_size; /* in milli seconds */ | ||
| 317 | struct skl_module_pin *m_in_pin; | 325 | struct skl_module_pin *m_in_pin; |
| 318 | struct skl_module_pin *m_out_pin; | 326 | struct skl_module_pin *m_out_pin; |
| 319 | enum skl_module_type m_type; | 327 | enum skl_module_type m_type; |
| @@ -342,6 +350,19 @@ struct skl_module_deferred_bind { | |||
| 342 | struct list_head node; | 350 | struct list_head node; |
| 343 | }; | 351 | }; |
| 344 | 352 | ||
| 353 | struct skl_mic_sel_config { | ||
| 354 | u16 mic_switch; | ||
| 355 | u16 flags; | ||
| 356 | u16 blob[SKL_MIC_MAX_CH_SUPPORT][SKL_MIC_MAX_CH_SUPPORT]; | ||
| 357 | } __packed; | ||
| 358 | |||
| 359 | enum skl_channel { | ||
| 360 | SKL_CH_MONO = 1, | ||
| 361 | SKL_CH_STEREO = 2, | ||
| 362 | SKL_CH_TRIO = 3, | ||
| 363 | SKL_CH_QUATRO = 4, | ||
| 364 | }; | ||
| 365 | |||
| 345 | static inline struct skl *get_skl_ctx(struct device *dev) | 366 | static inline struct skl *get_skl_ctx(struct device *dev) |
| 346 | { | 367 | { |
| 347 | struct hdac_ext_bus *ebus = dev_get_drvdata(dev); | 368 | struct hdac_ext_bus *ebus = dev_get_drvdata(dev); |
diff --git a/sound/soc/intel/skylake/skl-tplg-interface.h b/sound/soc/intel/skylake/skl-tplg-interface.h index 7a2febf99019..f8d1749a2e0c 100644 --- a/sound/soc/intel/skylake/skl-tplg-interface.h +++ b/sound/soc/intel/skylake/skl-tplg-interface.h | |||
| @@ -24,6 +24,7 @@ | |||
| 24 | * SST types start at higher to avoid any overlapping in future | 24 | * SST types start at higher to avoid any overlapping in future |
| 25 | */ | 25 | */ |
| 26 | #define SKL_CONTROL_TYPE_BYTE_TLV 0x100 | 26 | #define SKL_CONTROL_TYPE_BYTE_TLV 0x100 |
| 27 | #define SKL_CONTROL_TYPE_MIC_SELECT 0x102 | ||
| 27 | 28 | ||
| 28 | #define HDA_SST_CFG_MAX 900 /* size of copier cfg*/ | 29 | #define HDA_SST_CFG_MAX 900 /* size of copier cfg*/ |
| 29 | #define MAX_IN_QUEUE 8 | 30 | #define MAX_IN_QUEUE 8 |
| @@ -82,6 +83,7 @@ enum skl_module_type { | |||
| 82 | SKL_MODULE_TYPE_ALGO, | 83 | SKL_MODULE_TYPE_ALGO, |
| 83 | SKL_MODULE_TYPE_BASE_OUTFMT, | 84 | SKL_MODULE_TYPE_BASE_OUTFMT, |
| 84 | SKL_MODULE_TYPE_KPB, | 85 | SKL_MODULE_TYPE_KPB, |
| 86 | SKL_MODULE_TYPE_MIC_SELECT, | ||
| 85 | }; | 87 | }; |
| 86 | 88 | ||
| 87 | enum skl_core_affinity { | 89 | enum skl_core_affinity { |
diff --git a/sound/soc/intel/skylake/skl.c b/sound/soc/intel/skylake/skl.c index 4c9b5781282b..410ce83f4a49 100644 --- a/sound/soc/intel/skylake/skl.c +++ b/sound/soc/intel/skylake/skl.c | |||
| @@ -866,6 +866,8 @@ static void skl_remove(struct pci_dev *pci) | |||
| 866 | /* codec removal, invoke bus_device_remove */ | 866 | /* codec removal, invoke bus_device_remove */ |
| 867 | snd_hdac_ext_bus_device_remove(ebus); | 867 | snd_hdac_ext_bus_device_remove(ebus); |
| 868 | 868 | ||
| 869 | skl_debugfs_exit(skl->debugfs); | ||
| 870 | skl->debugfs = NULL; | ||
| 869 | skl_platform_unregister(&pci->dev); | 871 | skl_platform_unregister(&pci->dev); |
| 870 | skl_free_dsp(skl); | 872 | skl_free_dsp(skl); |
| 871 | skl_machine_device_unregister(skl); | 873 | skl_machine_device_unregister(skl); |
| @@ -876,29 +878,120 @@ static void skl_remove(struct pci_dev *pci) | |||
| 876 | dev_set_drvdata(&pci->dev, NULL); | 878 | dev_set_drvdata(&pci->dev, NULL); |
| 877 | } | 879 | } |
| 878 | 880 | ||
| 881 | static struct sst_codecs skl_codecs = { | ||
| 882 | .num_codecs = 1, | ||
| 883 | .codecs = {"NAU88L25"} | ||
| 884 | }; | ||
| 885 | |||
| 886 | static struct sst_codecs kbl_codecs = { | ||
| 887 | .num_codecs = 1, | ||
| 888 | .codecs = {"NAU88L25"} | ||
| 889 | }; | ||
| 890 | |||
| 891 | static struct sst_codecs bxt_codecs = { | ||
| 892 | .num_codecs = 1, | ||
| 893 | .codecs = {"MX98357A"} | ||
| 894 | }; | ||
| 895 | |||
| 896 | static struct sst_codecs kbl_poppy_codecs = { | ||
| 897 | .num_codecs = 1, | ||
| 898 | .codecs = {"10EC5663"} | ||
| 899 | }; | ||
| 900 | |||
| 901 | static struct sst_codecs kbl_5663_5514_codecs = { | ||
| 902 | .num_codecs = 2, | ||
| 903 | .codecs = {"10EC5663", "10EC5514"} | ||
| 904 | }; | ||
| 905 | |||
| 906 | |||
| 879 | static struct sst_acpi_mach sst_skl_devdata[] = { | 907 | static struct sst_acpi_mach sst_skl_devdata[] = { |
| 880 | { "INT343A", "skl_alc286s_i2s", "intel/dsp_fw_release.bin", NULL, NULL, NULL }, | 908 | { |
| 881 | { "INT343B", "skl_n88l25_s4567", "intel/dsp_fw_release.bin", | 909 | .id = "INT343A", |
| 882 | NULL, NULL, &skl_dmic_data }, | 910 | .drv_name = "skl_alc286s_i2s", |
| 883 | { "MX98357A", "skl_n88l25_m98357a", "intel/dsp_fw_release.bin", | 911 | .fw_filename = "intel/dsp_fw_release.bin", |
| 884 | NULL, NULL, &skl_dmic_data }, | 912 | }, |
| 913 | { | ||
| 914 | .id = "INT343B", | ||
| 915 | .drv_name = "skl_n88l25_s4567", | ||
| 916 | .fw_filename = "intel/dsp_fw_release.bin", | ||
| 917 | .machine_quirk = sst_acpi_codec_list, | ||
| 918 | .quirk_data = &skl_codecs, | ||
| 919 | .pdata = &skl_dmic_data | ||
| 920 | }, | ||
| 921 | { | ||
| 922 | .id = "MX98357A", | ||
| 923 | .drv_name = "skl_n88l25_m98357a", | ||
| 924 | .fw_filename = "intel/dsp_fw_release.bin", | ||
| 925 | .machine_quirk = sst_acpi_codec_list, | ||
| 926 | .quirk_data = &skl_codecs, | ||
| 927 | .pdata = &skl_dmic_data | ||
| 928 | }, | ||
| 885 | {} | 929 | {} |
| 886 | }; | 930 | }; |
| 887 | 931 | ||
| 888 | static struct sst_acpi_mach sst_bxtp_devdata[] = { | 932 | static struct sst_acpi_mach sst_bxtp_devdata[] = { |
| 889 | { "INT343A", "bxt_alc298s_i2s", "intel/dsp_fw_bxtn.bin", NULL, NULL, NULL }, | 933 | { |
| 890 | { "DLGS7219", "bxt_da7219_max98357a_i2s", "intel/dsp_fw_bxtn.bin", NULL, NULL, NULL }, | 934 | .id = "INT343A", |
| 935 | .drv_name = "bxt_alc298s_i2s", | ||
| 936 | .fw_filename = "intel/dsp_fw_bxtn.bin", | ||
| 937 | }, | ||
| 938 | { | ||
| 939 | .id = "DLGS7219", | ||
| 940 | .drv_name = "bxt_da7219_max98357a_i2s", | ||
| 941 | .fw_filename = "intel/dsp_fw_bxtn.bin", | ||
| 942 | .machine_quirk = sst_acpi_codec_list, | ||
| 943 | .quirk_data = &bxt_codecs, | ||
| 944 | }, | ||
| 891 | }; | 945 | }; |
| 892 | 946 | ||
| 893 | static struct sst_acpi_mach sst_kbl_devdata[] = { | 947 | static struct sst_acpi_mach sst_kbl_devdata[] = { |
| 894 | { "INT343A", "kbl_alc286s_i2s", "intel/dsp_fw_kbl.bin", NULL, NULL, NULL }, | 948 | { |
| 895 | { "INT343B", "kbl_n88l25_s4567", "intel/dsp_fw_kbl.bin", NULL, NULL, &skl_dmic_data }, | 949 | .id = "INT343A", |
| 896 | { "MX98357A", "kbl_n88l25_m98357a", "intel/dsp_fw_kbl.bin", NULL, NULL, &skl_dmic_data }, | 950 | .drv_name = "kbl_alc286s_i2s", |
| 951 | .fw_filename = "intel/dsp_fw_kbl.bin", | ||
| 952 | }, | ||
| 953 | { | ||
| 954 | .id = "INT343B", | ||
| 955 | .drv_name = "kbl_n88l25_s4567", | ||
| 956 | .fw_filename = "intel/dsp_fw_kbl.bin", | ||
| 957 | .machine_quirk = sst_acpi_codec_list, | ||
| 958 | .quirk_data = &kbl_codecs, | ||
| 959 | .pdata = &skl_dmic_data | ||
| 960 | }, | ||
| 961 | { | ||
| 962 | .id = "MX98357A", | ||
| 963 | .drv_name = "kbl_n88l25_m98357a", | ||
| 964 | .fw_filename = "intel/dsp_fw_kbl.bin", | ||
| 965 | .machine_quirk = sst_acpi_codec_list, | ||
| 966 | .quirk_data = &kbl_codecs, | ||
| 967 | .pdata = &skl_dmic_data | ||
| 968 | }, | ||
| 969 | { | ||
| 970 | .id = "MX98927", | ||
| 971 | .drv_name = "kbl_r5514_5663_max", | ||
| 972 | .fw_filename = "intel/dsp_fw_kbl.bin", | ||
| 973 | .machine_quirk = sst_acpi_codec_list, | ||
| 974 | .quirk_data = &kbl_5663_5514_codecs, | ||
| 975 | .pdata = &skl_dmic_data | ||
| 976 | }, | ||
| 977 | { | ||
| 978 | .id = "MX98927", | ||
| 979 | .drv_name = "kbl_rt5663_m98927", | ||
| 980 | .fw_filename = "intel/dsp_fw_kbl.bin", | ||
| 981 | .machine_quirk = sst_acpi_codec_list, | ||
| 982 | .quirk_data = &kbl_poppy_codecs, | ||
| 983 | .pdata = &skl_dmic_data | ||
| 984 | }, | ||
| 985 | |||
| 897 | {} | 986 | {} |
| 898 | }; | 987 | }; |
| 899 | 988 | ||
| 900 | static struct sst_acpi_mach sst_glk_devdata[] = { | 989 | static struct sst_acpi_mach sst_glk_devdata[] = { |
| 901 | { "INT343A", "glk_alc298s_i2s", "intel/dsp_fw_glk.bin", NULL, NULL, NULL }, | 990 | { |
| 991 | .id = "INT343A", | ||
| 992 | .drv_name = "glk_alc298s_i2s", | ||
| 993 | .fw_filename = "intel/dsp_fw_glk.bin", | ||
| 994 | }, | ||
| 902 | }; | 995 | }; |
| 903 | 996 | ||
| 904 | /* PCI IDs */ | 997 | /* PCI IDs */ |
diff --git a/sound/soc/intel/skylake/skl.h b/sound/soc/intel/skylake/skl.h index 2a630fcb7f08..14e7778d7f80 100644 --- a/sound/soc/intel/skylake/skl.h +++ b/sound/soc/intel/skylake/skl.h | |||
| @@ -23,6 +23,7 @@ | |||
| 23 | 23 | ||
| 24 | #include <sound/hda_register.h> | 24 | #include <sound/hda_register.h> |
| 25 | #include <sound/hdaudio_ext.h> | 25 | #include <sound/hdaudio_ext.h> |
| 26 | #include <sound/soc.h> | ||
| 26 | #include "skl-nhlt.h" | 27 | #include "skl-nhlt.h" |
| 27 | 28 | ||
| 28 | #define SKL_SUSPEND_DELAY 2000 | 29 | #define SKL_SUSPEND_DELAY 2000 |
| @@ -42,6 +43,8 @@ struct skl_dsp_resource { | |||
| 42 | u32 mem; | 43 | u32 mem; |
| 43 | }; | 44 | }; |
| 44 | 45 | ||
| 46 | struct skl_debug; | ||
| 47 | |||
| 45 | struct skl { | 48 | struct skl { |
| 46 | struct hdac_ext_bus ebus; | 49 | struct hdac_ext_bus ebus; |
| 47 | struct pci_dev *pci; | 50 | struct pci_dev *pci; |
| @@ -66,6 +69,8 @@ struct skl { | |||
| 66 | int supend_active; | 69 | int supend_active; |
| 67 | 70 | ||
| 68 | struct work_struct probe_work; | 71 | struct work_struct probe_work; |
| 72 | |||
| 73 | struct skl_debug *debugfs; | ||
| 69 | }; | 74 | }; |
| 70 | 75 | ||
| 71 | #define skl_to_ebus(s) (&(s)->ebus) | 76 | #define skl_to_ebus(s) (&(s)->ebus) |
| @@ -116,4 +121,25 @@ void skl_update_d0i3c(struct device *dev, bool enable); | |||
| 116 | int skl_nhlt_create_sysfs(struct skl *skl); | 121 | int skl_nhlt_create_sysfs(struct skl *skl); |
| 117 | void skl_nhlt_remove_sysfs(struct skl *skl); | 122 | void skl_nhlt_remove_sysfs(struct skl *skl); |
| 118 | 123 | ||
| 124 | struct skl_module_cfg; | ||
| 125 | |||
| 126 | #ifdef CONFIG_DEBUG_FS | ||
| 127 | struct skl_debug *skl_debugfs_init(struct skl *skl); | ||
| 128 | void skl_debugfs_exit(struct skl_debug *d); | ||
| 129 | void skl_debug_init_module(struct skl_debug *d, | ||
| 130 | struct snd_soc_dapm_widget *w, | ||
| 131 | struct skl_module_cfg *mconfig); | ||
| 132 | #else | ||
| 133 | static inline struct skl_debug *skl_debugfs_init(struct skl *skl) | ||
| 134 | { | ||
| 135 | return NULL; | ||
| 136 | } | ||
| 137 | static inline void skl_debugfs_exit(struct skl_debug *d) | ||
| 138 | {} | ||
| 139 | static inline void skl_debug_init_module(struct skl_debug *d, | ||
| 140 | struct snd_soc_dapm_widget *w, | ||
| 141 | struct skl_module_cfg *mconfig) | ||
| 142 | {} | ||
| 143 | #endif | ||
| 144 | |||
| 119 | #endif /* __SOUND_SOC_SKL_H */ | 145 | #endif /* __SOUND_SOC_SKL_H */ |
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 754e3ef8d7ae..180bfbfe833d 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c | |||
| @@ -68,6 +68,20 @@ static int pmdown_time = 5000; | |||
| 68 | module_param(pmdown_time, int, 0); | 68 | module_param(pmdown_time, int, 0); |
| 69 | MODULE_PARM_DESC(pmdown_time, "DAPM stream powerdown time (msecs)"); | 69 | MODULE_PARM_DESC(pmdown_time, "DAPM stream powerdown time (msecs)"); |
| 70 | 70 | ||
| 71 | /* If a DMI filed contain strings in this blacklist (e.g. | ||
| 72 | * "Type2 - Board Manufacturer" or "Type1 - TBD by OEM"), it will be taken | ||
| 73 | * as invalid and dropped when setting the card long name from DMI info. | ||
| 74 | */ | ||
| 75 | static const char * const dmi_blacklist[] = { | ||
| 76 | "To be filled by OEM", | ||
| 77 | "TBD by OEM", | ||
| 78 | "Default String", | ||
| 79 | "Board Manufacturer", | ||
| 80 | "Board Vendor Name", | ||
| 81 | "Board Product Name", | ||
| 82 | NULL, /* terminator */ | ||
| 83 | }; | ||
| 84 | |||
| 71 | /* returns the minimum number of bytes needed to represent | 85 | /* returns the minimum number of bytes needed to represent |
| 72 | * a particular given value */ | 86 | * a particular given value */ |
| 73 | static int min_bytes_needed(unsigned long val) | 87 | static int min_bytes_needed(unsigned long val) |
| @@ -1933,6 +1947,22 @@ static void cleanup_dmi_name(char *name) | |||
| 1933 | name[j] = '\0'; | 1947 | name[j] = '\0'; |
| 1934 | } | 1948 | } |
| 1935 | 1949 | ||
| 1950 | /* Check if a DMI field is valid, i.e. not containing any string | ||
| 1951 | * in the black list. | ||
| 1952 | */ | ||
| 1953 | static int is_dmi_valid(const char *field) | ||
| 1954 | { | ||
| 1955 | int i = 0; | ||
| 1956 | |||
| 1957 | while (dmi_blacklist[i]) { | ||
| 1958 | if (strstr(field, dmi_blacklist[i])) | ||
| 1959 | return 0; | ||
| 1960 | i++; | ||
| 1961 | } | ||
| 1962 | |||
| 1963 | return 1; | ||
| 1964 | } | ||
| 1965 | |||
| 1936 | /** | 1966 | /** |
| 1937 | * snd_soc_set_dmi_name() - Register DMI names to card | 1967 | * snd_soc_set_dmi_name() - Register DMI names to card |
| 1938 | * @card: The card to register DMI names | 1968 | * @card: The card to register DMI names |
| @@ -1975,17 +2005,18 @@ int snd_soc_set_dmi_name(struct snd_soc_card *card, const char *flavour) | |||
| 1975 | 2005 | ||
| 1976 | /* make up dmi long name as: vendor.product.version.board */ | 2006 | /* make up dmi long name as: vendor.product.version.board */ |
| 1977 | vendor = dmi_get_system_info(DMI_BOARD_VENDOR); | 2007 | vendor = dmi_get_system_info(DMI_BOARD_VENDOR); |
| 1978 | if (!vendor) { | 2008 | if (!vendor || !is_dmi_valid(vendor)) { |
| 1979 | dev_warn(card->dev, "ASoC: no DMI vendor name!\n"); | 2009 | dev_warn(card->dev, "ASoC: no DMI vendor name!\n"); |
| 1980 | return 0; | 2010 | return 0; |
| 1981 | } | 2011 | } |
| 1982 | 2012 | ||
| 2013 | |||
| 1983 | snprintf(card->dmi_longname, sizeof(card->snd_card->longname), | 2014 | snprintf(card->dmi_longname, sizeof(card->snd_card->longname), |
| 1984 | "%s", vendor); | 2015 | "%s", vendor); |
| 1985 | cleanup_dmi_name(card->dmi_longname); | 2016 | cleanup_dmi_name(card->dmi_longname); |
| 1986 | 2017 | ||
| 1987 | product = dmi_get_system_info(DMI_PRODUCT_NAME); | 2018 | product = dmi_get_system_info(DMI_PRODUCT_NAME); |
| 1988 | if (product) { | 2019 | if (product && is_dmi_valid(product)) { |
| 1989 | len = strlen(card->dmi_longname); | 2020 | len = strlen(card->dmi_longname); |
| 1990 | snprintf(card->dmi_longname + len, | 2021 | snprintf(card->dmi_longname + len, |
| 1991 | longname_buf_size - len, | 2022 | longname_buf_size - len, |
| @@ -1999,7 +2030,7 @@ int snd_soc_set_dmi_name(struct snd_soc_card *card, const char *flavour) | |||
| 1999 | * name in the product version field | 2030 | * name in the product version field |
| 2000 | */ | 2031 | */ |
| 2001 | product_version = dmi_get_system_info(DMI_PRODUCT_VERSION); | 2032 | product_version = dmi_get_system_info(DMI_PRODUCT_VERSION); |
| 2002 | if (product_version) { | 2033 | if (product_version && is_dmi_valid(product_version)) { |
| 2003 | len = strlen(card->dmi_longname); | 2034 | len = strlen(card->dmi_longname); |
| 2004 | snprintf(card->dmi_longname + len, | 2035 | snprintf(card->dmi_longname + len, |
| 2005 | longname_buf_size - len, | 2036 | longname_buf_size - len, |
| @@ -2012,7 +2043,7 @@ int snd_soc_set_dmi_name(struct snd_soc_card *card, const char *flavour) | |||
| 2012 | } | 2043 | } |
| 2013 | 2044 | ||
| 2014 | board = dmi_get_system_info(DMI_BOARD_NAME); | 2045 | board = dmi_get_system_info(DMI_BOARD_NAME); |
| 2015 | if (board) { | 2046 | if (board && is_dmi_valid(board)) { |
| 2016 | len = strlen(card->dmi_longname); | 2047 | len = strlen(card->dmi_longname); |
| 2017 | snprintf(card->dmi_longname + len, | 2048 | snprintf(card->dmi_longname + len, |
| 2018 | longname_buf_size - len, | 2049 | longname_buf_size - len, |
