diff options
author | Mark Brown <broonie@kernel.org> | 2017-07-03 11:51:30 -0400 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2017-07-03 11:51:30 -0400 |
commit | 2016d5ed401133539779d8a070abbe42fe9cb3da (patch) | |
tree | 96e1b8b348b2650345057fcaf7324983e6c2559f | |
parent | 05325120861066e1e3e726eda54e429802725a64 (diff) | |
parent | 7d3d6e0645dd3689e625161b9e312108e66b2b51 (diff) |
Merge remote-tracking branch 'asoc/topic/intel' into asoc-next
38 files changed, 2806 insertions, 264 deletions
diff --git a/include/uapi/sound/snd_sst_tokens.h b/include/uapi/sound/snd_sst_tokens.h index 93392bedcc58..dedb2056160d 100644 --- a/include/uapi/sound/snd_sst_tokens.h +++ b/include/uapi/sound/snd_sst_tokens.h | |||
@@ -161,6 +161,8 @@ | |||
161 | * | 161 | * |
162 | * %SKL_TKL_U32_D0I3_CAPS: Specifies the D0i3 capability for module | 162 | * %SKL_TKL_U32_D0I3_CAPS: Specifies the D0i3 capability for module |
163 | * | 163 | * |
164 | * %SKL_TKN_U32_DMA_BUF_SIZE: DMA buffer size in millisec | ||
165 | * | ||
164 | * module_id and loadable flags dont have tokens as these values will be | 166 | * module_id and loadable flags dont have tokens as these values will be |
165 | * read from the DSP FW manifest | 167 | * read from the DSP FW manifest |
166 | */ | 168 | */ |
@@ -213,8 +215,10 @@ enum SKL_TKNS { | |||
213 | SKL_TKN_U32_LIB_COUNT, | 215 | SKL_TKN_U32_LIB_COUNT, |
214 | SKL_TKN_STR_LIB_NAME, | 216 | SKL_TKN_STR_LIB_NAME, |
215 | SKL_TKN_U32_PMODE, | 217 | SKL_TKN_U32_PMODE, |
216 | SKL_TKL_U32_D0I3_CAPS, | 218 | SKL_TKL_U32_D0I3_CAPS, /* Typo added at v4.10 */ |
217 | SKL_TKN_MAX = SKL_TKL_U32_D0I3_CAPS, | 219 | SKL_TKN_U32_D0I3_CAPS = SKL_TKL_U32_D0I3_CAPS, |
220 | SKL_TKN_U32_DMA_BUF_SIZE, | ||
221 | SKL_TKN_MAX = SKL_TKN_U32_DMA_BUF_SIZE, | ||
218 | }; | 222 | }; |
219 | 223 | ||
220 | #endif | 224 | #endif |
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..dc20d91f62e6 --- /dev/null +++ b/sound/soc/intel/skylake/skl-debug.c | |||
@@ -0,0 +1,261 @@ | |||
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.h" | ||
24 | #include "../common/sst-dsp-priv.h" | ||
25 | |||
26 | #define MOD_BUF PAGE_SIZE | ||
27 | #define FW_REG_BUF PAGE_SIZE | ||
28 | #define FW_REG_SIZE 0x60 | ||
29 | |||
30 | struct skl_debug { | ||
31 | struct skl *skl; | ||
32 | struct device *dev; | ||
33 | |||
34 | struct dentry *fs; | ||
35 | struct dentry *modules; | ||
36 | u8 fw_read_buff[FW_REG_BUF]; | ||
37 | }; | ||
38 | |||
39 | static ssize_t skl_print_pins(struct skl_module_pin *m_pin, char *buf, | ||
40 | int max_pin, ssize_t size, bool direction) | ||
41 | { | ||
42 | int i; | ||
43 | ssize_t ret = 0; | ||
44 | |||
45 | for (i = 0; i < max_pin; i++) | ||
46 | ret += snprintf(buf + size, MOD_BUF - size, | ||
47 | "%s %d\n\tModule %d\n\tInstance %d\n\t" | ||
48 | "In-used %s\n\tType %s\n" | ||
49 | "\tState %d\n\tIndex %d\n", | ||
50 | direction ? "Input Pin:" : "Output Pin:", | ||
51 | i, m_pin[i].id.module_id, | ||
52 | m_pin[i].id.instance_id, | ||
53 | m_pin[i].in_use ? "Used" : "Unused", | ||
54 | m_pin[i].is_dynamic ? "Dynamic" : "Static", | ||
55 | m_pin[i].pin_state, i); | ||
56 | return ret; | ||
57 | } | ||
58 | |||
59 | static ssize_t skl_print_fmt(struct skl_module_fmt *fmt, char *buf, | ||
60 | ssize_t size, bool direction) | ||
61 | { | ||
62 | return snprintf(buf + size, MOD_BUF - size, | ||
63 | "%s\n\tCh %d\n\tFreq %d\n\tBit depth %d\n\t" | ||
64 | "Valid bit depth %d\n\tCh config %#x\n\tInterleaving %d\n\t" | ||
65 | "Sample Type %d\n\tCh Map %#x\n", | ||
66 | direction ? "Input Format:" : "Output Format:", | ||
67 | fmt->channels, fmt->s_freq, fmt->bit_depth, | ||
68 | fmt->valid_bit_depth, fmt->ch_cfg, | ||
69 | fmt->interleaving_style, fmt->sample_type, | ||
70 | fmt->ch_map); | ||
71 | } | ||
72 | |||
73 | static ssize_t module_read(struct file *file, char __user *user_buf, | ||
74 | size_t count, loff_t *ppos) | ||
75 | { | ||
76 | struct skl_module_cfg *mconfig = file->private_data; | ||
77 | char *buf; | ||
78 | ssize_t ret; | ||
79 | |||
80 | buf = kzalloc(MOD_BUF, GFP_KERNEL); | ||
81 | if (!buf) | ||
82 | return -ENOMEM; | ||
83 | |||
84 | ret = snprintf(buf, MOD_BUF, "Module:\n\tUUID %pUL\n\tModule id %d\n" | ||
85 | "\tInstance id %d\n\tPvt_id %d\n", mconfig->guid, | ||
86 | mconfig->id.module_id, mconfig->id.instance_id, | ||
87 | mconfig->id.pvt_id); | ||
88 | |||
89 | ret += snprintf(buf + ret, MOD_BUF - ret, | ||
90 | "Resources:\n\tMCPS %#x\n\tIBS %#x\n\tOBS %#x\t\n", | ||
91 | mconfig->mcps, mconfig->ibs, mconfig->obs); | ||
92 | |||
93 | ret += snprintf(buf + ret, MOD_BUF - ret, | ||
94 | "Module data:\n\tCore %d\n\tIn queue %d\n\t" | ||
95 | "Out queue %d\n\tType %s\n", | ||
96 | mconfig->core_id, mconfig->max_in_queue, | ||
97 | mconfig->max_out_queue, | ||
98 | mconfig->is_loadable ? "loadable" : "inbuilt"); | ||
99 | |||
100 | ret += skl_print_fmt(mconfig->in_fmt, buf, ret, true); | ||
101 | ret += skl_print_fmt(mconfig->out_fmt, buf, ret, false); | ||
102 | |||
103 | ret += snprintf(buf + ret, MOD_BUF - ret, | ||
104 | "Fixup:\n\tParams %#x\n\tConverter %#x\n", | ||
105 | mconfig->params_fixup, mconfig->converter); | ||
106 | |||
107 | ret += snprintf(buf + ret, MOD_BUF - ret, | ||
108 | "Module Gateway:\n\tType %#x\n\tVbus %#x\n\tHW conn %#x\n\tSlot %#x\n", | ||
109 | mconfig->dev_type, mconfig->vbus_id, | ||
110 | mconfig->hw_conn_type, mconfig->time_slot); | ||
111 | |||
112 | ret += snprintf(buf + ret, MOD_BUF - ret, | ||
113 | "Pipeline:\n\tID %d\n\tPriority %d\n\tConn Type %d\n\t" | ||
114 | "Pages %#x\n", mconfig->pipe->ppl_id, | ||
115 | mconfig->pipe->pipe_priority, mconfig->pipe->conn_type, | ||
116 | mconfig->pipe->memory_pages); | ||
117 | |||
118 | ret += snprintf(buf + ret, MOD_BUF - ret, | ||
119 | "\tParams:\n\t\tHost DMA %d\n\t\tLink DMA %d\n", | ||
120 | mconfig->pipe->p_params->host_dma_id, | ||
121 | mconfig->pipe->p_params->link_dma_id); | ||
122 | |||
123 | ret += snprintf(buf + ret, MOD_BUF - ret, | ||
124 | "\tPCM params:\n\t\tCh %d\n\t\tFreq %d\n\t\tFormat %d\n", | ||
125 | mconfig->pipe->p_params->ch, | ||
126 | mconfig->pipe->p_params->s_freq, | ||
127 | mconfig->pipe->p_params->s_fmt); | ||
128 | |||
129 | ret += snprintf(buf + ret, MOD_BUF - ret, | ||
130 | "\tLink %#x\n\tStream %#x\n", | ||
131 | mconfig->pipe->p_params->linktype, | ||
132 | mconfig->pipe->p_params->stream); | ||
133 | |||
134 | ret += snprintf(buf + ret, MOD_BUF - ret, | ||
135 | "\tState %d\n\tPassthru %s\n", | ||
136 | mconfig->pipe->state, | ||
137 | mconfig->pipe->passthru ? "true" : "false"); | ||
138 | |||
139 | ret += skl_print_pins(mconfig->m_in_pin, buf, | ||
140 | mconfig->max_in_queue, ret, true); | ||
141 | ret += skl_print_pins(mconfig->m_out_pin, buf, | ||
142 | mconfig->max_out_queue, ret, false); | ||
143 | |||
144 | ret += snprintf(buf + ret, MOD_BUF - ret, | ||
145 | "Other:\n\tDomain %d\n\tHomogenous Input %s\n\t" | ||
146 | "Homogenous Output %s\n\tIn Queue Mask %d\n\t" | ||
147 | "Out Queue Mask %d\n\tDMA ID %d\n\tMem Pages %d\n\t" | ||
148 | "Module Type %d\n\tModule State %d\n", | ||
149 | mconfig->domain, | ||
150 | mconfig->homogenous_inputs ? "true" : "false", | ||
151 | mconfig->homogenous_outputs ? "true" : "false", | ||
152 | mconfig->in_queue_mask, mconfig->out_queue_mask, | ||
153 | mconfig->dma_id, mconfig->mem_pages, mconfig->m_state, | ||
154 | mconfig->m_type); | ||
155 | |||
156 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret); | ||
157 | |||
158 | kfree(buf); | ||
159 | return ret; | ||
160 | } | ||
161 | |||
162 | static const struct file_operations mcfg_fops = { | ||
163 | .open = simple_open, | ||
164 | .read = module_read, | ||
165 | .llseek = default_llseek, | ||
166 | }; | ||
167 | |||
168 | |||
169 | void skl_debug_init_module(struct skl_debug *d, | ||
170 | struct snd_soc_dapm_widget *w, | ||
171 | struct skl_module_cfg *mconfig) | ||
172 | { | ||
173 | if (!debugfs_create_file(w->name, 0444, | ||
174 | d->modules, mconfig, | ||
175 | &mcfg_fops)) | ||
176 | dev_err(d->dev, "%s: module debugfs init failed\n", w->name); | ||
177 | } | ||
178 | |||
179 | static ssize_t fw_softreg_read(struct file *file, char __user *user_buf, | ||
180 | size_t count, loff_t *ppos) | ||
181 | { | ||
182 | struct skl_debug *d = file->private_data; | ||
183 | struct sst_dsp *sst = d->skl->skl_sst->dsp; | ||
184 | size_t w0_stat_sz = sst->addr.w0_stat_sz; | ||
185 | void __iomem *in_base = sst->mailbox.in_base; | ||
186 | void __iomem *fw_reg_addr; | ||
187 | unsigned int offset; | ||
188 | char *tmp; | ||
189 | ssize_t ret = 0; | ||
190 | |||
191 | tmp = kzalloc(FW_REG_BUF, GFP_KERNEL); | ||
192 | if (!tmp) | ||
193 | return -ENOMEM; | ||
194 | |||
195 | fw_reg_addr = in_base - w0_stat_sz; | ||
196 | memset(d->fw_read_buff, 0, FW_REG_BUF); | ||
197 | |||
198 | if (w0_stat_sz > 0) | ||
199 | __iowrite32_copy(d->fw_read_buff, fw_reg_addr, w0_stat_sz >> 2); | ||
200 | |||
201 | for (offset = 0; offset < FW_REG_SIZE; offset += 16) { | ||
202 | ret += snprintf(tmp + ret, FW_REG_BUF - ret, "%#.4x: ", offset); | ||
203 | hex_dump_to_buffer(d->fw_read_buff + offset, 16, 16, 4, | ||
204 | tmp + ret, FW_REG_BUF - ret, 0); | ||
205 | ret += strlen(tmp + ret); | ||
206 | |||
207 | /* print newline for each offset */ | ||
208 | if (FW_REG_BUF - ret > 0) | ||
209 | tmp[ret++] = '\n'; | ||
210 | } | ||
211 | |||
212 | ret = simple_read_from_buffer(user_buf, count, ppos, tmp, ret); | ||
213 | kfree(tmp); | ||
214 | |||
215 | return ret; | ||
216 | } | ||
217 | |||
218 | static const struct file_operations soft_regs_ctrl_fops = { | ||
219 | .open = simple_open, | ||
220 | .read = fw_softreg_read, | ||
221 | .llseek = default_llseek, | ||
222 | }; | ||
223 | |||
224 | struct skl_debug *skl_debugfs_init(struct skl *skl) | ||
225 | { | ||
226 | struct skl_debug *d; | ||
227 | |||
228 | d = devm_kzalloc(&skl->pci->dev, sizeof(*d), GFP_KERNEL); | ||
229 | if (!d) | ||
230 | return NULL; | ||
231 | |||
232 | /* create the debugfs dir with platform component's debugfs as parent */ | ||
233 | d->fs = debugfs_create_dir("dsp", | ||
234 | skl->platform->component.debugfs_root); | ||
235 | if (IS_ERR(d->fs) || !d->fs) { | ||
236 | dev_err(&skl->pci->dev, "debugfs root creation failed\n"); | ||
237 | return NULL; | ||
238 | } | ||
239 | |||
240 | d->skl = skl; | ||
241 | d->dev = &skl->pci->dev; | ||
242 | |||
243 | /* now create the module dir */ | ||
244 | d->modules = debugfs_create_dir("modules", d->fs); | ||
245 | if (IS_ERR(d->modules) || !d->modules) { | ||
246 | dev_err(&skl->pci->dev, "modules debugfs create failed\n"); | ||
247 | goto err; | ||
248 | } | ||
249 | |||
250 | if (!debugfs_create_file("fw_soft_regs_rd", 0444, d->fs, d, | ||
251 | &soft_regs_ctrl_fops)) { | ||
252 | dev_err(d->dev, "fw soft regs control debugfs init failed\n"); | ||
253 | goto err; | ||
254 | } | ||
255 | |||
256 | return d; | ||
257 | |||
258 | err: | ||
259 | debugfs_remove_recursive(d->fs); | ||
260 | return NULL; | ||
261 | } | ||
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..334917ee41cf 100644 --- a/sound/soc/intel/skylake/skl.c +++ b/sound/soc/intel/skylake/skl.c | |||
@@ -866,6 +866,7 @@ 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 = NULL; | ||
869 | skl_platform_unregister(&pci->dev); | 870 | skl_platform_unregister(&pci->dev); |
870 | skl_free_dsp(skl); | 871 | skl_free_dsp(skl); |
871 | skl_machine_device_unregister(skl); | 872 | skl_machine_device_unregister(skl); |
@@ -876,29 +877,120 @@ static void skl_remove(struct pci_dev *pci) | |||
876 | dev_set_drvdata(&pci->dev, NULL); | 877 | dev_set_drvdata(&pci->dev, NULL); |
877 | } | 878 | } |
878 | 879 | ||
880 | static struct sst_codecs skl_codecs = { | ||
881 | .num_codecs = 1, | ||
882 | .codecs = {"NAU88L25"} | ||
883 | }; | ||
884 | |||
885 | static struct sst_codecs kbl_codecs = { | ||
886 | .num_codecs = 1, | ||
887 | .codecs = {"NAU88L25"} | ||
888 | }; | ||
889 | |||
890 | static struct sst_codecs bxt_codecs = { | ||
891 | .num_codecs = 1, | ||
892 | .codecs = {"MX98357A"} | ||
893 | }; | ||
894 | |||
895 | static struct sst_codecs kbl_poppy_codecs = { | ||
896 | .num_codecs = 1, | ||
897 | .codecs = {"10EC5663"} | ||
898 | }; | ||
899 | |||
900 | static struct sst_codecs kbl_5663_5514_codecs = { | ||
901 | .num_codecs = 2, | ||
902 | .codecs = {"10EC5663", "10EC5514"} | ||
903 | }; | ||
904 | |||
905 | |||
879 | static struct sst_acpi_mach sst_skl_devdata[] = { | 906 | static struct sst_acpi_mach sst_skl_devdata[] = { |
880 | { "INT343A", "skl_alc286s_i2s", "intel/dsp_fw_release.bin", NULL, NULL, NULL }, | 907 | { |
881 | { "INT343B", "skl_n88l25_s4567", "intel/dsp_fw_release.bin", | 908 | .id = "INT343A", |
882 | NULL, NULL, &skl_dmic_data }, | 909 | .drv_name = "skl_alc286s_i2s", |
883 | { "MX98357A", "skl_n88l25_m98357a", "intel/dsp_fw_release.bin", | 910 | .fw_filename = "intel/dsp_fw_release.bin", |
884 | NULL, NULL, &skl_dmic_data }, | 911 | }, |
912 | { | ||
913 | .id = "INT343B", | ||
914 | .drv_name = "skl_n88l25_s4567", | ||
915 | .fw_filename = "intel/dsp_fw_release.bin", | ||
916 | .machine_quirk = sst_acpi_codec_list, | ||
917 | .quirk_data = &skl_codecs, | ||
918 | .pdata = &skl_dmic_data | ||
919 | }, | ||
920 | { | ||
921 | .id = "MX98357A", | ||
922 | .drv_name = "skl_n88l25_m98357a", | ||
923 | .fw_filename = "intel/dsp_fw_release.bin", | ||
924 | .machine_quirk = sst_acpi_codec_list, | ||
925 | .quirk_data = &skl_codecs, | ||
926 | .pdata = &skl_dmic_data | ||
927 | }, | ||
885 | {} | 928 | {} |
886 | }; | 929 | }; |
887 | 930 | ||
888 | static struct sst_acpi_mach sst_bxtp_devdata[] = { | 931 | static struct sst_acpi_mach sst_bxtp_devdata[] = { |
889 | { "INT343A", "bxt_alc298s_i2s", "intel/dsp_fw_bxtn.bin", NULL, NULL, NULL }, | 932 | { |
890 | { "DLGS7219", "bxt_da7219_max98357a_i2s", "intel/dsp_fw_bxtn.bin", NULL, NULL, NULL }, | 933 | .id = "INT343A", |
934 | .drv_name = "bxt_alc298s_i2s", | ||
935 | .fw_filename = "intel/dsp_fw_bxtn.bin", | ||
936 | }, | ||
937 | { | ||
938 | .id = "DLGS7219", | ||
939 | .drv_name = "bxt_da7219_max98357a_i2s", | ||
940 | .fw_filename = "intel/dsp_fw_bxtn.bin", | ||
941 | .machine_quirk = sst_acpi_codec_list, | ||
942 | .quirk_data = &bxt_codecs, | ||
943 | }, | ||
891 | }; | 944 | }; |
892 | 945 | ||
893 | static struct sst_acpi_mach sst_kbl_devdata[] = { | 946 | static struct sst_acpi_mach sst_kbl_devdata[] = { |
894 | { "INT343A", "kbl_alc286s_i2s", "intel/dsp_fw_kbl.bin", NULL, NULL, NULL }, | 947 | { |
895 | { "INT343B", "kbl_n88l25_s4567", "intel/dsp_fw_kbl.bin", NULL, NULL, &skl_dmic_data }, | 948 | .id = "INT343A", |
896 | { "MX98357A", "kbl_n88l25_m98357a", "intel/dsp_fw_kbl.bin", NULL, NULL, &skl_dmic_data }, | 949 | .drv_name = "kbl_alc286s_i2s", |
950 | .fw_filename = "intel/dsp_fw_kbl.bin", | ||
951 | }, | ||
952 | { | ||
953 | .id = "INT343B", | ||
954 | .drv_name = "kbl_n88l25_s4567", | ||
955 | .fw_filename = "intel/dsp_fw_kbl.bin", | ||
956 | .machine_quirk = sst_acpi_codec_list, | ||
957 | .quirk_data = &kbl_codecs, | ||
958 | .pdata = &skl_dmic_data | ||
959 | }, | ||
960 | { | ||
961 | .id = "MX98357A", | ||
962 | .drv_name = "kbl_n88l25_m98357a", | ||
963 | .fw_filename = "intel/dsp_fw_kbl.bin", | ||
964 | .machine_quirk = sst_acpi_codec_list, | ||
965 | .quirk_data = &kbl_codecs, | ||
966 | .pdata = &skl_dmic_data | ||
967 | }, | ||
968 | { | ||
969 | .id = "MX98927", | ||
970 | .drv_name = "kbl_r5514_5663_max", | ||
971 | .fw_filename = "intel/dsp_fw_kbl.bin", | ||
972 | .machine_quirk = sst_acpi_codec_list, | ||
973 | .quirk_data = &kbl_5663_5514_codecs, | ||
974 | .pdata = &skl_dmic_data | ||
975 | }, | ||
976 | { | ||
977 | .id = "MX98927", | ||
978 | .drv_name = "kbl_rt5663_m98927", | ||
979 | .fw_filename = "intel/dsp_fw_kbl.bin", | ||
980 | .machine_quirk = sst_acpi_codec_list, | ||
981 | .quirk_data = &kbl_poppy_codecs, | ||
982 | .pdata = &skl_dmic_data | ||
983 | }, | ||
984 | |||
897 | {} | 985 | {} |
898 | }; | 986 | }; |
899 | 987 | ||
900 | static struct sst_acpi_mach sst_glk_devdata[] = { | 988 | static struct sst_acpi_mach sst_glk_devdata[] = { |
901 | { "INT343A", "glk_alc298s_i2s", "intel/dsp_fw_glk.bin", NULL, NULL, NULL }, | 989 | { |
990 | .id = "INT343A", | ||
991 | .drv_name = "glk_alc298s_i2s", | ||
992 | .fw_filename = "intel/dsp_fw_glk.bin", | ||
993 | }, | ||
902 | }; | 994 | }; |
903 | 995 | ||
904 | /* PCI IDs */ | 996 | /* PCI IDs */ |
diff --git a/sound/soc/intel/skylake/skl.h b/sound/soc/intel/skylake/skl.h index 2a630fcb7f08..a6b134b4c037 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,22 @@ 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_debug_init_module(struct skl_debug *d, | ||
129 | struct snd_soc_dapm_widget *w, | ||
130 | struct skl_module_cfg *mconfig); | ||
131 | #else | ||
132 | static inline struct skl_debug *skl_debugfs_init(struct skl *skl) | ||
133 | { | ||
134 | return NULL; | ||
135 | } | ||
136 | static inline void skl_debug_init_module(struct skl_debug *d, | ||
137 | struct snd_soc_dapm_widget *w, | ||
138 | struct skl_module_cfg *mconfig) | ||
139 | {} | ||
140 | #endif | ||
141 | |||
119 | #endif /* __SOUND_SOC_SKL_H */ | 142 | #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, |