Unified · Split
| @@ -161,6 +161,8 @@ · 160 unmodified lines | ||
| 161 | 161 | * |
| 162 | 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 | 166 | * module_id and loadable flags dont have tokens as these values will be |
| 165 | 167 | * read from the DSP FW manifest |
| 166 | 168 | */ |
| @@ -213,8 +215,10 @@ enum SKL_TKNS { · 46 unmodified lines | ||
| 213 | 215 | SKL_TKN_U32_LIB_COUNT, |
| 214 | 216 | SKL_TKN_STR_LIB_NAME, |
| 215 | 217 | SKL_TKN_U32_PMODE, |
| 216 | − SKL_TKL_U32_D0I3_CAPS, | |
| 217 | − SKL_TKN_MAX = SKL_TKL_U32_D0I3_CAPS, | |
| 218 | + SKL_TKL_U32_D0I3_CAPS, /* Typo added at v4.10 */ | |
| 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 | 224 | #endif |
| @@ -2848,6 +2848,10 @@ static const struct dmi_system_id dmi_platform_intel_braswell[] = { · 2847 unmodified lines | ||
| 2848 | 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 | 2856 | .ident = "Lenovo Thinkpad Tablet 10", |
| 2853 | 2857 | .matches = { |
| @@ -2882,6 +2886,11 @@ static int rt5670_i2c_probe(struct i2c_client *i2c, · 28 unmodified lines | ||
| 2882 | 2886 | rt5670->pdata.dmic1_data_pin = RT5670_DMIC_DATA_IN2P; |
| 2883 | 2887 | rt5670->pdata.dev_gpio = true; |
| 2884 | 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 | 2896 | rt5670->regmap = devm_regmap_init_i2c(i2c, &rt5670_regmap); |
| @@ -41,15 +41,6 @@ · 40 unmodified lines | ||
| 41 | 41 | |
| 42 | 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 | 44 | static const struct regmap_range_cfg rt5677_ranges[] = { |
| 54 | 45 | { |
| 55 | 46 | .name = "PR", |
| @@ -5030,7 +5021,6 @@ static const struct regmap_config rt5677_regmap = { · 4974 unmodified lines | ||
| 5030 | 5021 | static const struct i2c_device_id rt5677_i2c_id[] = { |
| 5031 | 5022 | { "rt5677", RT5677 }, |
| 5032 | 5023 | { "rt5676", RT5676 }, |
| 5033 | − { "RT5677CE:00", RT5677 }, | |
| 5034 | 5024 | { } |
| 5035 | 5025 | }; |
| 5036 | 5026 | MODULE_DEVICE_TABLE(i2c, rt5677_i2c_id); |
| @@ -5041,28 +5031,19 @@ static const struct of_device_id rt5677_of_match[] = { · 4 unmodified lines | ||
| 5041 | 5031 | }; |
| 5042 | 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 }; | |
| 5045 | −static const struct acpi_gpio_params mic_present_gpio = { RT5677_GPIO_MIC_PRESENT_L, 0, false }; | |
| 5046 | −static const struct acpi_gpio_params headphone_enable_gpio = { RT5677_GPIO_HP_AMP_SHDN_L, 0, false }; | |
| 5047 | − | |
| 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 }, | |
| 5034 | +#ifdef CONFIG_ACPI | |
| 5035 | +static const struct acpi_device_id rt5677_acpi_match[] = { | |
| 5036 | + { "RT5677CE", RT5677 }, | |
| 5037 | + { } | |
| 5053 | 5038 | }; |
| 5039 | +MODULE_DEVICE_TABLE(acpi, rt5677_acpi_match); | |
| 5040 | +#endif | |
| 5054 | 5041 | |
| 5055 | 5042 | static void rt5677_read_acpi_properties(struct rt5677_priv *rt5677, |
| 5056 | 5043 | struct device *dev) |
| 5057 | 5044 | { |
| 5058 | − int ret; | |
| 5059 | 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 | 5047 | if (!device_property_read_u32(dev, "DCLK", &val)) |
| 5067 | 5048 | rt5677->pdata.dmic2_clk_pin = val; |
| 5068 | 5049 | |
| @@ -5301,6 +5282,7 @@ static struct i2c_driver rt5677_i2c_driver = { · 232 unmodified lines | ||
| 5301 | 5282 | .driver = { |
| 5302 | 5283 | .name = "rt5677", |
| 5303 | 5284 | .of_match_table = rt5677_of_match, |
| 5285 | + .acpi_match_table = ACPI_PTR(rt5677_acpi_match), | |
| 5304 | 5286 | }, |
| 5305 | 5287 | .probe = rt5677_i2c_probe, |
| 5306 | 5288 | .remove = rt5677_i2c_remove, |
| @@ -214,6 +214,18 @@ config SND_SOC_INTEL_BYT_CHT_DA7213_MACH · 213 unmodified lines | ||
| 214 | 214 | platforms with DA7212/7213 audio codec. |
| 215 | 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 | 229 | config SND_SOC_INTEL_BYT_CHT_NOCODEC_MACH |
| 218 | 230 | tristate "ASoC Audio driver for Intel Baytrail & Cherrytrail platform with no codec (MinnowBoard MAX, Up)" |
| 219 | 231 | depends on X86_INTEL_LPSS && I2C && ACPI |
| @@ -226,6 +238,36 @@ config SND_SOC_INTEL_BYT_CHT_NOCODEC_MACH · 6 unmodified lines | ||
| 226 | 238 | connector |
| 227 | 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 | 271 | config SND_SOC_INTEL_SKYLAKE |
| 230 | 272 | tristate |
| 231 | 273 | select SND_HDA_EXT_CORE |
| @@ -690,7 +690,7 @@ static int sst_pcm_new(struct snd_soc_pcm_runtime *rtd) · 689 unmodified lines | ||
| 690 | 690 | snd_dma_continuous_data(GFP_DMA), |
| 691 | 691 | SST_MIN_BUFFER, SST_MAX_BUFFER); |
| 692 | 692 | if (retval) { |
| 693 | − dev_err(rtd->dev, "dma buffer allocationf fail\n"); | |
| 693 | + dev_err(rtd->dev, "dma buffer allocation failure\n"); | |
| 694 | 694 | return retval; |
| 695 | 695 | } |
| 696 | 696 | } |
| @@ -258,7 +258,7 @@ static ssize_t firmware_version_show(struct device *dev, · 257 unmodified lines | ||
| 258 | 258 | |
| 259 | 259 | } |
| 260 | 260 | |
| 261 | −DEVICE_ATTR_RO(firmware_version); | |
| 261 | +static DEVICE_ATTR_RO(firmware_version); | |
| 262 | 262 | |
| 263 | 263 | static const struct attribute *sst_fw_version_attrs[] = { |
| 264 | 264 | &dev_attr_firmware_version.attr, |
| @@ -382,37 +382,6 @@ void sst_context_cleanup(struct intel_sst_drv *ctx) · 117 unmodified lines | ||
| 382 | 382 | } |
| 383 | 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 | 385 | void sst_configure_runtime_pm(struct intel_sst_drv *ctx) |
| 417 | 386 | { |
| 418 | 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) · 13 unmodified lines | ||
| 432 | 401 | pm_runtime_set_active(ctx->dev); |
| 433 | 402 | else |
| 434 | 403 | pm_runtime_put_noidle(ctx->dev); |
| 435 | − | |
| 436 | − sst_save_shim64(ctx, ctx->shim, ctx->shim_regs64); | |
| 437 | 404 | } |
| 438 | 405 | EXPORT_SYMBOL_GPL(sst_configure_runtime_pm); |
| 439 | 406 | |
| @@ -457,8 +424,6 @@ static int intel_sst_runtime_suspend(struct device *dev) · 17 unmodified lines | ||
| 457 | 424 | flush_workqueue(ctx->post_msg_wq); |
| 458 | 425 | |
| 459 | 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 | 428 | return ret; |
| 464 | 429 | } |
| @@ -499,23 +464,23 @@ static int intel_sst_suspend(struct device *dev) · 34 unmodified lines | ||
| 499 | 464 | fw_save = kzalloc(sizeof(*fw_save), GFP_KERNEL); |
| 500 | 465 | if (!fw_save) |
| 501 | 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 | 468 | if (!fw_save->iram) { |
| 504 | 469 | ret = -ENOMEM; |
| 505 | 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 | 473 | if (!fw_save->dram) { |
| 509 | 474 | ret = -ENOMEM; |
| 510 | 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 | 478 | if (!fw_save->sram) { |
| 514 | 479 | ret = -ENOMEM; |
| 515 | 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 | 484 | if (!fw_save->ddr) { |
| 520 | 485 | ret = -ENOMEM; |
| 521 | 486 | goto ddr; |
| @@ -530,11 +495,11 @@ static int intel_sst_suspend(struct device *dev) · 8 unmodified lines | ||
| 530 | 495 | ctx->ops->reset(ctx); |
| 531 | 496 | return 0; |
| 532 | 497 | ddr: |
| 533 | − kfree(fw_save->sram); | |
| 498 | + kvfree(fw_save->sram); | |
| 534 | 499 | sram: |
| 535 | − kfree(fw_save->dram); | |
| 500 | + kvfree(fw_save->dram); | |
| 536 | 501 | dram: |
| 537 | − kfree(fw_save->iram); | |
| 502 | + kvfree(fw_save->iram); | |
| 538 | 503 | iram: |
| 539 | 504 | kfree(fw_save); |
| 540 | 505 | return ret; |
| @@ -562,10 +527,10 @@ static int intel_sst_resume(struct device *dev) · 21 unmodified lines | ||
| 562 | 527 | memcpy32_toio(ctx->mailbox, fw_save->sram, SST_MAILBOX_SIZE); |
| 563 | 528 | memcpy32_toio(ctx->ddr, fw_save->ddr, ctx->ddr_end - ctx->ddr_base); |
| 564 | 529 | |
| 565 | − kfree(fw_save->sram); | |
| 566 | − kfree(fw_save->dram); | |
| 567 | − kfree(fw_save->iram); | |
| 568 | − kfree(fw_save->ddr); | |
| 530 | + kvfree(fw_save->sram); | |
| 531 | + kvfree(fw_save->dram); | |
| 532 | + kvfree(fw_save->iram); | |
| 533 | + kvfree(fw_save->ddr); | |
| 569 | 534 | kfree(fw_save); |
| 570 | 535 | |
| 571 | 536 | block = sst_create_block(ctx, 0, FW_DWNL_ID); |
| @@ -317,31 +317,11 @@ struct sst_ipc_reg { · 316 unmodified lines | ||
| 317 | 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 | 320 | struct sst_fw_save { |
| 341 | − void *iram; | |
| 342 | − void *dram; | |
| 343 | − void *sram; | |
| 344 | − void *ddr; | |
| 321 | + void *iram; /* allocated via kvmalloc() */ | |
| 322 | + void *dram; /* allocated via kvmalloc() */ | |
| 323 | + void *sram; /* allocated via kvmalloc() */ | |
| 324 | + void *ddr; /* allocated via kvmalloc() */ | |
| 345 | 325 | }; |
| 346 | 326 | |
| 347 | 327 | /** |
| @@ -356,7 +336,6 @@ struct sst_fw_save { · 8 unmodified lines | ||
| 356 | 336 | * @dram : SST DRAM pointer |
| 357 | 337 | * @pdata : SST info passed as a part of pci platform data |
| 358 | 338 | * @shim_phy_add : SST shim phy addr |
| 359 | − * @shim_regs64: Struct to save shim registers | |
| 360 | 339 | * @ipc_dispatch_list : ipc messages dispatched |
| 361 | 340 | * @rx_list : to copy the process_reply/process_msg from DSP |
| 362 | 341 | * @ipc_post_msg_wq : wq to post IPC messages context |
| @@ -398,7 +377,6 @@ struct intel_sst_drv { · 35 unmodified lines | ||
| 398 | 377 | unsigned int ddr_end; |
| 399 | 378 | unsigned int ddr_base; |
| 400 | 379 | unsigned int mailbox_recv_offset; |
| 401 | − struct sst_shim_regs64 *shim_regs64; | |
| 402 | 380 | struct list_head block_list; |
| 403 | 381 | struct list_head ipc_dispatch_list; |
| 404 | 382 | struct sst_platform_info *pdata; |
| @@ -303,8 +303,6 @@ static int sst_acpi_probe(struct platform_device *pdev) · 302 unmodified lines | ||
| 303 | 303 | dev_err(dev, "No matching machine driver found\n"); |
| 304 | 304 | return -ENODEV; |
| 305 | 305 | } |
| 306 | − if (mach->machine_quirk) | |
| 307 | − mach = mach->machine_quirk(mach); | |
| 308 | 306 | |
| 309 | 307 | pdata = mach->pdata; |
| 310 | 308 | |
| @@ -360,23 +358,9 @@ static int sst_acpi_probe(struct platform_device *pdev) · 49 unmodified lines | ||
| 360 | 358 | if (ret < 0) |
| 361 | 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 | 361 | sst_configure_runtime_pm(ctx); |
| 372 | 362 | platform_set_drvdata(pdev, ctx); |
| 373 | 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[] = { · 70 unmodified lines | ||
| 453 | 437 | |
| 454 | 438 | |
| 455 | 439 | static struct sst_acpi_mach cht_surface_mach = { |
| 456 | − "10EC5640", "cht-bsw-rt5645", "intel/fw_sst_22a8.bin", "cht-bsw", NULL, | |
| 457 | − &chv_platform_data }; | |
| 440 | + .id = "10EC5640", | |
| 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 | 447 | static struct sst_acpi_mach byt_thinkpad_10 = { |
| 460 | − "10EC5640", "cht-bsw-rt5672", "intel/fw_sst_0f28.bin", "cht-bsw", NULL, | |
| 461 | − &byt_rvp_platform_data }; | |
| 448 | + .id = "10EC5640", | |
| 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 | 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) · 21 unmodified lines | ||
| 486 | 478 | |
| 487 | 479 | |
| 488 | 480 | static struct sst_acpi_mach sst_acpi_bytcr[] = { |
| 489 | − {"10EC5640", "bytcr_rt5640", "intel/fw_sst_0f28.bin", "bytcr_rt5640", byt_quirk, | |
| 490 | − &byt_rvp_platform_data }, | |
| 491 | − {"10EC5642", "bytcr_rt5640", "intel/fw_sst_0f28.bin", "bytcr_rt5640", NULL, | |
| 492 | − &byt_rvp_platform_data }, | |
| 493 | − {"INTCCFFD", "bytcr_rt5640", "intel/fw_sst_0f28.bin", "bytcr_rt5640", NULL, | |
| 494 | − &byt_rvp_platform_data }, | |
| 495 | − {"10EC5651", "bytcr_rt5651", "intel/fw_sst_0f28.bin", "bytcr_rt5651", NULL, | |
| 496 | − &byt_rvp_platform_data }, | |
| 497 | − {"DLGS7212", "bytcht_da7213", "intel/fw_sst_0f28.bin", "bytcht_da7213", NULL, | |
| 498 | − &byt_rvp_platform_data }, | |
| 499 | − {"DLGS7213", "bytcht_da7213", "intel/fw_sst_0f28.bin", "bytcht_da7213", NULL, | |
| 500 | − &byt_rvp_platform_data }, | |
| 481 | + { | |
| 482 | + .id = "10EC5640", | |
| 483 | + .drv_name = "bytcr_rt5640", | |
| 484 | + .fw_filename = "intel/fw_sst_0f28.bin", | |
| 485 | + .board = "bytcr_rt5640", | |
| 486 | + .machine_quirk = byt_quirk, | |
| 487 | + .pdata = &byt_rvp_platform_data, | |
| 488 | + }, | |
| 489 | + { | |
| 490 | + .id = "10EC5642", | |
| 491 | + .drv_name = "bytcr_rt5640", | |
| 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 | 524 | /* some Baytrail platforms rely on RT5645, use CHT machine driver */ |
| 502 | − {"10EC5645", "cht-bsw-rt5645", "intel/fw_sst_0f28.bin", "cht-bsw", NULL, | |
| 503 | − &byt_rvp_platform_data }, | |
| 504 | − {"10EC5648", "cht-bsw-rt5645", "intel/fw_sst_0f28.bin", "cht-bsw", NULL, | |
| 505 | − &byt_rvp_platform_data }, | |
| 525 | + { | |
| 526 | + .id = "10EC5645", | |
| 527 | + .drv_name = "cht-bsw-rt5645", | |
| 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 | 539 | #if IS_ENABLED(CONFIG_SND_SOC_INTEL_BYT_CHT_NOCODEC_MACH) |
| 507 | 540 | /* |
| 508 | 541 | * This is always last in the table so that it is selected only when |
| 509 | 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, | |
| 512 | − &byt_rvp_platform_data }, | |
| 544 | + { | |
| 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 | 551 | #endif |
| 514 | 552 | {}, |
| 515 | 553 | }; |
| 516 | 554 | |
| 517 | 555 | /* Cherryview-based platforms: CherryTrail and Braswell */ |
| 518 | 556 | static struct sst_acpi_mach sst_acpi_chv[] = { |
| 519 | − {"10EC5670", "cht-bsw-rt5672", "intel/fw_sst_22a8.bin", "cht-bsw", NULL, | |
| 520 | − &chv_platform_data }, | |
| 521 | − {"10EC5672", "cht-bsw-rt5672", "intel/fw_sst_22a8.bin", "cht-bsw", NULL, | |
| 522 | − &chv_platform_data }, | |
| 523 | − {"10EC5645", "cht-bsw-rt5645", "intel/fw_sst_22a8.bin", "cht-bsw", NULL, | |
| 524 | − &chv_platform_data }, | |
| 525 | − {"10EC5650", "cht-bsw-rt5645", "intel/fw_sst_22a8.bin", "cht-bsw", NULL, | |
| 526 | − &chv_platform_data }, | |
| 527 | − {"10EC3270", "cht-bsw-rt5645", "intel/fw_sst_22a8.bin", "cht-bsw", NULL, | |
| 528 | − &chv_platform_data }, | |
| 529 | − | |
| 530 | − {"193C9890", "cht-bsw-max98090", "intel/fw_sst_22a8.bin", "cht-bsw", NULL, | |
| 531 | − &chv_platform_data }, | |
| 532 | − {"DLGS7212", "bytcht_da7213", "intel/fw_sst_22a8.bin", "bytcht_da7213", NULL, | |
| 533 | − &chv_platform_data }, | |
| 534 | − {"DLGS7213", "bytcht_da7213", "intel/fw_sst_22a8.bin", "bytcht_da7213", NULL, | |
| 535 | − &chv_platform_data }, | |
| 557 | + { | |
| 558 | + .id = "10EC5670", | |
| 559 | + .drv_name = "cht-bsw-rt5672", | |
| 560 | + .fw_filename = "intel/fw_sst_22a8.bin", | |
| 561 | + .board = "cht-bsw", | |
| 562 | + .pdata = &chv_platform_data | |
| 563 | + }, | |
| 564 | + { | |
| 565 | + .id = "10EC5672", | |
| 566 | + .drv_name = "cht-bsw-rt5672", | |
| 567 | + .fw_filename = "intel/fw_sst_22a8.bin", | |
| 568 | + .board = "cht-bsw", | |
| 569 | + .pdata = &chv_platform_data | |
| 570 | + }, | |
| 571 | + { | |
| 572 | + .id = "10EC5645", | |
| 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 | 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, | |
| 538 | − &chv_platform_data }, | |
| 539 | − {"10EC3276", "bytcr_rt5640", "intel/fw_sst_22a8.bin", "bytcr_rt5640", NULL, | |
| 540 | − &chv_platform_data }, | |
| 622 | + { | |
| 623 | + .id = "10EC5640", | |
| 624 | + .drv_name = "bytcr_rt5640", | |
| 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 | 637 | /* some CHT-T platforms rely on RT5651, use Baytrail machine driver */ |
| 542 | − {"10EC5651", "bytcr_rt5651", "intel/fw_sst_22a8.bin", "bytcr_rt5651", NULL, | |
| 543 | − &chv_platform_data }, | |
| 638 | + { | |
| 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 | 645 | #if IS_ENABLED(CONFIG_SND_SOC_INTEL_BYT_CHT_NOCODEC_MACH) |
| 545 | 646 | /* |
| 546 | 647 | * This is always last in the table so that it is selected only when |
| 547 | 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, | |
| 550 | − &chv_platform_data }, | |
| 650 | + { | |
| 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 | 657 | #endif |
| 552 | 658 | {}, |
| 553 | 659 | }; |
| @@ -11,7 +11,10 @@ snd-soc-sst-cht-bsw-rt5672-objs := cht_bsw_rt5672.o · 10 unmodified lines | ||
| 11 | 11 | snd-soc-sst-cht-bsw-rt5645-objs := cht_bsw_rt5645.o |
| 12 | 12 | snd-soc-sst-cht-bsw-max98090_ti-objs := cht_bsw_max98090_ti.o |
| 13 | 13 | snd-soc-sst-byt-cht-da7213-objs := bytcht_da7213.o |
| 14 | +snd-soc-sst-byt-cht-es8316-objs := bytcht_es8316.o | |
| 14 | 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 | 18 | snd-soc-skl_rt286-objs := skl_rt286.o |
| 16 | 19 | snd-skl_nau88l25_max98357a-objs := skl_nau88l25_max98357a.o |
| 17 | 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 · 11 unmodified lines | ||
| 29 | 32 | obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_RT5645_MACH) += snd-soc-sst-cht-bsw-rt5645.o |
| 30 | 33 | obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_MAX98090_TI_MACH) += snd-soc-sst-cht-bsw-max98090_ti.o |
| 31 | 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 | 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 | 39 | obj-$(CONFIG_SND_SOC_INTEL_SKL_RT286_MACH) += snd-soc-skl_rt286.o |
| 34 | 40 | obj-$(CONFIG_SND_SOC_INTEL_SKL_NAU88L25_MAX98357A_MACH) += snd-skl_nau88l25_max98357a.o |
| 35 | 41 | obj-$(CONFIG_SND_SOC_INTEL_SKL_NAU88L25_SSM4567_MACH) += snd-soc-skl_nau88l25_ssm4567.o |
| @@ -16,6 +16,7 @@ · 15 unmodified lines | ||
| 16 | 16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 17 | 17 | */ |
| 18 | 18 | |
| 19 | +#include <linux/acpi.h> | |
| 19 | 20 | #include <linux/module.h> |
| 20 | 21 | #include <linux/platform_device.h> |
| 21 | 22 | #include <linux/gpio/consumer.h> |
| @@ -120,6 +121,26 @@ static struct snd_soc_jack_gpio mic_jack_gpio = { · 98 unmodified lines | ||
| 120 | 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 | 144 | static int broadwell_ssp0_fixup(struct snd_soc_pcm_runtime *rtd, |
| 124 | 145 | struct snd_pcm_hw_params *params) |
| 125 | 146 | { |
| @@ -184,6 +205,11 @@ static int bdw_rt5677_init(struct snd_soc_pcm_runtime *rtd) · 58 unmodified lines | ||
| 184 | 205 | snd_soc_card_get_drvdata(rtd->card); |
| 185 | 206 | struct snd_soc_codec *codec = rtd->codec; |
| 186 | 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 | 214 | /* Enable codec ASRC function for Stereo DAC/Stereo1 ADC/DMIC/I2S1. |
| 189 | 215 | * The ASRC clock source is clk_i2s1_asrc. |
| @@ -242,31 +242,31 @@ static int broxton_da7219_fe_init(struct snd_soc_pcm_runtime *rtd) · 241 unmodified lines | ||
| 242 | 242 | return 0; |
| 243 | 243 | } |
| 244 | 244 | |
| 245 | −static unsigned int rates[] = { | |
| 245 | +static const unsigned int rates[] = { | |
| 246 | 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 | 250 | .count = ARRAY_SIZE(rates), |
| 251 | 251 | .list = rates, |
| 252 | 252 | .mask = 0, |
| 253 | 253 | }; |
| 254 | 254 | |
| 255 | −static unsigned int channels[] = { | |
| 255 | +static const unsigned int channels[] = { | |
| 256 | 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 | 260 | .count = ARRAY_SIZE(channels), |
| 261 | 261 | .list = channels, |
| 262 | 262 | .mask = 0, |
| 263 | 263 | }; |
| 264 | 264 | |
| 265 | −static unsigned int channels_quad[] = { | |
| 265 | +static const unsigned int channels_quad[] = { | |
| 266 | 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 | 270 | .count = ARRAY_SIZE(channels_quad), |
| 271 | 271 | .list = channels_quad, |
| 272 | 272 | .mask = 0, |
| @@ -207,11 +207,11 @@ static const struct snd_soc_ops broxton_rt298_ops = { · 206 unmodified lines | ||
| 207 | 207 | .hw_params = broxton_rt298_hw_params, |
| 208 | 208 | }; |
| 209 | 209 | |
| 210 | −static unsigned int rates[] = { | |
| 210 | +static const unsigned int rates[] = { | |
| 211 | 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 | 215 | .count = ARRAY_SIZE(rates), |
| 216 | 216 | .list = rates, |
| 217 | 217 | .mask = 0, |
| @@ -222,19 +222,16 @@ static int broxton_dmic_fixup(struct snd_soc_pcm_runtime *rtd, · 4 unmodified lines | ||
| 222 | 222 | { |
| 223 | 223 | struct snd_interval *channels = hw_param_interval(params, |
| 224 | 224 | SNDRV_PCM_HW_PARAM_CHANNELS); |
| 225 | − if (params_channels(params) == 2) | |
| 226 | − channels->min = channels->max = 2; | |
| 227 | − else | |
| 228 | − channels->min = channels->max = 4; | |
| 225 | + channels->min = channels->max = 4; | |
| 229 | 226 | |
| 230 | 227 | return 0; |
| 231 | 228 | } |
| 232 | 229 | |
| 233 | −static unsigned int channels_dmic[] = { | |
| 234 | − 2, 4, | |
| 230 | +static const unsigned int channels_dmic[] = { | |
| 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 | 235 | .count = ARRAY_SIZE(channels_dmic), |
| 239 | 236 | .list = channels_dmic, |
| 240 | 237 | .mask = 0, |
| @@ -256,11 +253,11 @@ static const struct snd_soc_ops broxton_dmic_ops = { · 15 unmodified lines | ||
| 256 | 253 | .startup = broxton_dmic_startup, |
| 257 | 254 | }; |
| 258 | 255 | |
| 259 | −static unsigned int channels[] = { | |
| 256 | +static const unsigned int channels[] = { | |
| 260 | 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 | 261 | .count = ARRAY_SIZE(channels), |
| 265 | 262 | .list = channels, |
| 266 | 263 | .mask = 0, |
| @@ -67,20 +67,27 @@ static struct snd_soc_jack_pin hs_jack_pins[] = { · 66 unmodified lines | ||
| 67 | 67 | |
| 68 | 68 | static struct snd_soc_jack_gpio hs_jack_gpios[] = { |
| 69 | 69 | { |
| 70 | − .name = "hp-gpio", | |
| 71 | − .idx = 0, | |
| 70 | + .name = "hp", | |
| 72 | 71 | .report = SND_JACK_HEADPHONE | SND_JACK_LINEOUT, |
| 73 | 72 | .debounce_time = 200, |
| 74 | 73 | }, |
| 75 | 74 | { |
| 76 | − .name = "mic-gpio", | |
| 77 | − .idx = 1, | |
| 75 | + .name = "mic", | |
| 78 | 76 | .invert = 1, |
| 79 | 77 | .report = SND_JACK_MICROPHONE, |
| 80 | 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 | 91 | static int byt_max98090_init(struct snd_soc_pcm_runtime *runtime) |
| 85 | 92 | { |
| 86 | 93 | int ret; |
| @@ -140,8 +147,9 @@ static struct snd_soc_card byt_max98090_card = { · 53 unmodified lines | ||
| 140 | 147 | |
| 141 | 148 | static int byt_max98090_probe(struct platform_device *pdev) |
| 142 | 149 | { |
| 143 | − int ret_val = 0; | |
| 150 | + struct device *dev = &pdev->dev; | |
| 144 | 151 | struct byt_max98090_private *priv; |
| 152 | + int ret_val; | |
| 145 | 153 | |
| 146 | 154 | priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_ATOMIC); |
| 147 | 155 | if (!priv) { |
| @@ -149,6 +157,10 @@ static int byt_max98090_probe(struct platform_device *pdev) · 1 unmodified line | ||
| 149 | 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 | 164 | byt_max98090_card.dev = &pdev->dev; |
| 153 | 165 | snd_soc_card_set_drvdata(&byt_max98090_card, priv); |
| 154 | 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) · 3 unmodified lines | ||
| 158 | 170 | return ret_val; |
| 159 | 171 | } |
| 160 | 172 | |
| 161 | − return ret_val; | |
| 173 | + return 0; | |
| 162 | 174 | } |
| 163 | 175 | |
| 164 | 176 | static int byt_max98090_remove(struct platform_device *pdev) |
| @@ -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"); | |
| @@ -85,11 +85,11 @@ static int codec_fixup(struct snd_soc_pcm_runtime *rtd, · 84 unmodified lines | ||
| 85 | 85 | return 0; |
| 86 | 86 | } |
| 87 | 87 | |
| 88 | −static unsigned int rates_48000[] = { | |
| 88 | +static const unsigned int rates_48000[] = { | |
| 89 | 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 | 93 | .count = ARRAY_SIZE(rates_48000), |
| 94 | 94 | .list = rates_48000, |
| 95 | 95 | }; |
| @@ -203,11 +203,11 @@ static int byt_rt5651_codec_fixup(struct snd_soc_pcm_runtime *rtd, · 202 unmodified lines | ||
| 203 | 203 | return 0; |
| 204 | 204 | } |
| 205 | 205 | |
| 206 | −static unsigned int rates_48000[] = { | |
| 206 | +static const unsigned int rates_48000[] = { | |
| 207 | 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 | 211 | .count = ARRAY_SIZE(rates_48000), |
| 212 | 212 | .list = rates_48000, |
| 213 | 213 | }; |
| @@ -39,18 +39,6 @@ struct cht_mc_private { · 38 unmodified lines | ||
| 39 | 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 | 42 | static const struct snd_soc_dapm_widget cht_dapm_widgets[] = { |
| 55 | 43 | SND_SOC_DAPM_HP("Headphone", NULL), |
| 56 | 44 | SND_SOC_DAPM_MIC("Headset Mic", NULL), |
| @@ -19,6 +19,8 @@ · 18 unmodified lines | ||
| 19 | 19 | #include <linux/module.h> |
| 20 | 20 | #include <linux/platform_device.h> |
| 21 | 21 | #include <linux/slab.h> |
| 22 | +#include <linux/clk.h> | |
| 23 | +#include <asm/cpu_device_id.h> | |
| 22 | 24 | #include <sound/pcm.h> |
| 23 | 25 | #include <sound/pcm_params.h> |
| 24 | 26 | #include <sound/soc.h> |
| @@ -31,8 +33,11 @@ · 6 unmodified lines | ||
| 31 | 33 | #define CHT_PLAT_CLK_3_HZ 19200000 |
| 32 | 34 | #define CHT_CODEC_DAI "rt5670-aif1" |
| 33 | 35 | |
| 34 | −static struct snd_soc_jack cht_bsw_headset; | |
| 35 | −static char cht_bsw_codec_name[16]; | |
| 36 | +struct cht_mc_private { | |
| 37 | + struct snd_soc_jack headset; | |
| 38 | + char codec_name[16]; | |
| 39 | + struct clk *mclk; | |
| 40 | +}; | |
| 36 | 41 | |
| 37 | 42 | /* Headset jack detection DAPM pins */ |
| 38 | 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, · 25 unmodified lines | ||
| 64 | 69 | struct snd_soc_dapm_context *dapm = w->dapm; |
| 65 | 70 | struct snd_soc_card *card = dapm->card; |
| 66 | 71 | struct snd_soc_dai *codec_dai; |
| 72 | + struct cht_mc_private *ctx = snd_soc_card_get_drvdata(card); | |
| 67 | 73 | int ret; |
| 68 | 74 | |
| 69 | 75 | codec_dai = cht_get_codec_dai(card); |
| @@ -73,6 +79,15 @@ static int platform_clock_control(struct snd_soc_dapm_widget *w, · 3 unmodified lines | ||
| 73 | 79 | } |
| 74 | 80 | |
| 75 | 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 | 91 | /* set codec PLL source to the 19.2MHz platform clock (MCLK) */ |
| 77 | 92 | ret = snd_soc_dai_set_pll(codec_dai, 0, RT5670_PLL1_S_MCLK, |
| 78 | 93 | CHT_PLAT_CLK_3_HZ, 48000 * 512); |
| @@ -96,6 +111,9 @@ static int platform_clock_control(struct snd_soc_dapm_widget *w, · 17 unmodified lines | ||
| 96 | 111 | */ |
| 97 | 112 | snd_soc_dai_set_sysclk(codec_dai, RT5670_SCLK_S_RCCLK, |
| 98 | 113 | 48000 * 512, SND_SOC_CLOCK_IN); |
| 114 | + | |
| 115 | + if (ctx->mclk) | |
| 116 | + clk_disable_unprepare(ctx->mclk); | |
| 99 | 117 | } |
| 100 | 118 | return 0; |
| 101 | 119 | } |
| @@ -171,6 +189,7 @@ static int cht_codec_init(struct snd_soc_pcm_runtime *runtime) · 69 unmodified lines | ||
| 171 | 189 | int ret; |
| 172 | 190 | struct snd_soc_dai *codec_dai = runtime->codec_dai; |
| 173 | 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 | 194 | /* TDM 4 slots 24 bit, set Rx & Tx bitmask to 4 active slots */ |
| 176 | 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) · 17 unmodified lines | ||
| 194 | 213 | RT5670_CLK_SEL_I2S1_ASRC); |
| 195 | 214 | |
| 196 | 215 | ret = snd_soc_card_jack_new(runtime->card, "Headset", |
| 197 | − SND_JACK_HEADSET | SND_JACK_BTN_0 | | |
| 198 | − SND_JACK_BTN_1 | SND_JACK_BTN_2, &cht_bsw_headset, | |
| 199 | − cht_bsw_headset_pins, ARRAY_SIZE(cht_bsw_headset_pins)); | |
| 216 | + SND_JACK_HEADSET | SND_JACK_BTN_0 | | |
| 217 | + SND_JACK_BTN_1 | SND_JACK_BTN_2, | |
| 218 | + &ctx->headset, | |
| 219 | + cht_bsw_headset_pins, | |
| 220 | + ARRAY_SIZE(cht_bsw_headset_pins)); | |
| 200 | 221 | if (ret) |
| 201 | 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 | 247 | return 0; |
| 205 | 248 | } |
| 206 | 249 | |
| @@ -341,34 +384,62 @@ static struct snd_soc_card snd_soc_card_cht = { · 134 unmodified lines | ||
| 341 | 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 | 399 | #define RT5672_I2C_DEFAULT "i2c-10EC5670:00" |
| 345 | 400 | |
| 346 | 401 | static int snd_cht_mc_probe(struct platform_device *pdev) |
| 347 | 402 | { |
| 348 | 403 | int ret_val = 0; |
| 404 | + struct cht_mc_private *drv; | |
| 349 | 405 | struct sst_acpi_mach *mach = pdev->dev.platform_data; |
| 350 | 406 | const char *i2c_name; |
| 351 | 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 | 415 | /* fixup codec name based on HID */ |
| 356 | 416 | if (mach) { |
| 357 | 417 | i2c_name = sst_acpi_find_name_from_hid(mach->id); |
| 358 | 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 | 420 | "i2c-%s", i2c_name); |
| 361 | 421 | for (i = 0; i < ARRAY_SIZE(cht_dailink); i++) { |
| 362 | 422 | if (!strcmp(cht_dailink[i].codec_name, |
| 363 | 423 | RT5672_I2C_DEFAULT)) { |
| 364 | 424 | cht_dailink[i].codec_name = |
| 365 | − cht_bsw_codec_name; | |
| 425 | + drv->codec_name; | |
| 366 | 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 | 443 | /* register the soc card */ |
| 373 | 444 | snd_soc_card_cht.dev = &pdev->dev; |
| 374 | 445 | ret_val = devm_snd_soc_register_card(&pdev->dev, &snd_soc_card_cht); |
| @@ -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"); | |
| @@ -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"); | |
| @@ -266,21 +266,21 @@ static int skylake_nau8825_fe_init(struct snd_soc_pcm_runtime *rtd) · 265 unmodified lines | ||
| 266 | 266 | return 0; |
| 267 | 267 | } |
| 268 | 268 | |
| 269 | −static unsigned int rates[] = { | |
| 269 | +static const unsigned int rates[] = { | |
| 270 | 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 | 274 | .count = ARRAY_SIZE(rates), |
| 275 | 275 | .list = rates, |
| 276 | 276 | .mask = 0, |
| 277 | 277 | }; |
| 278 | 278 | |
| 279 | −static unsigned int channels[] = { | |
| 279 | +static const unsigned int channels[] = { | |
| 280 | 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 | 284 | .count = ARRAY_SIZE(channels), |
| 285 | 285 | .list = channels, |
| 286 | 286 | .mask = 0, |
| @@ -348,11 +348,11 @@ static int skylake_dmic_fixup(struct snd_soc_pcm_runtime *rtd, · 61 unmodified lines | ||
| 348 | 348 | return 0; |
| 349 | 349 | } |
| 350 | 350 | |
| 351 | −static unsigned int channels_dmic[] = { | |
| 351 | +static const unsigned int channels_dmic[] = { | |
| 352 | 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 | 356 | .count = ARRAY_SIZE(channels_dmic), |
| 357 | 357 | .list = channels_dmic, |
| 358 | 358 | .mask = 0, |
| @@ -384,11 +384,11 @@ static const struct snd_soc_ops skylake_dmic_ops = { · 25 unmodified lines | ||
| 384 | 384 | .startup = skylake_dmic_startup, |
| 385 | 385 | }; |
| 386 | 386 | |
| 387 | −static unsigned int rates_16000[] = { | |
| 387 | +static const unsigned int rates_16000[] = { | |
| 388 | 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 | 392 | .count = ARRAY_SIZE(rates_16000), |
| 393 | 393 | .list = rates_16000, |
| 394 | 394 | }; |
| @@ -297,21 +297,21 @@ static int skylake_nau8825_fe_init(struct snd_soc_pcm_runtime *rtd) · 296 unmodified lines | ||
| 297 | 297 | return 0; |
| 298 | 298 | } |
| 299 | 299 | |
| 300 | −static unsigned int rates[] = { | |
| 300 | +static const unsigned int rates[] = { | |
| 301 | 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 | 305 | .count = ARRAY_SIZE(rates), |
| 306 | 306 | .list = rates, |
| 307 | 307 | .mask = 0, |
| 308 | 308 | }; |
| 309 | 309 | |
| 310 | −static unsigned int channels[] = { | |
| 310 | +static const unsigned int channels[] = { | |
| 311 | 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 | 315 | .count = ARRAY_SIZE(channels), |
| 316 | 316 | .list = channels, |
| 317 | 317 | .mask = 0, |
| @@ -397,11 +397,11 @@ static const struct snd_soc_ops skylake_nau8825_ops = { · 79 unmodified lines | ||
| 397 | 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 | 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 | 405 | .count = ARRAY_SIZE(channels_dmic), |
| 406 | 406 | .list = channels_dmic, |
| 407 | 407 | .mask = 0, |
| @@ -433,11 +433,11 @@ static const struct snd_soc_ops skylake_dmic_ops = { · 25 unmodified lines | ||
| 433 | 433 | .startup = skylake_dmic_startup, |
| 434 | 434 | }; |
| 435 | 435 | |
| 436 | −static unsigned int rates_16000[] = { | |
| 436 | +static const unsigned int rates_16000[] = { | |
| 437 | 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 | 441 | .count = ARRAY_SIZE(rates_16000), |
| 442 | 442 | .list = rates_16000, |
| 443 | 443 | }; |
| @@ -43,6 +43,7 @@ struct skl_rt286_private { · 42 unmodified lines | ||
| 43 | 43 | |
| 44 | 44 | enum { |
| 45 | 45 | SKL_DPCM_AUDIO_PB = 0, |
| 46 | + SKL_DPCM_AUDIO_DB_PB, | |
| 46 | 47 | SKL_DPCM_AUDIO_CP, |
| 47 | 48 | SKL_DPCM_AUDIO_REF_CP, |
| 48 | 49 | SKL_DPCM_AUDIO_DMIC_CP, |
| @@ -165,21 +166,21 @@ static int skylake_hdmi_init(struct snd_soc_pcm_runtime *rtd) · 116 unmodified lines | ||
| 165 | 166 | return 0; |
| 166 | 167 | } |
| 167 | 168 | |
| 168 | −static unsigned int rates[] = { | |
| 169 | +static const unsigned int rates[] = { | |
| 169 | 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 | 174 | .count = ARRAY_SIZE(rates), |
| 174 | 175 | .list = rates, |
| 175 | 176 | .mask = 0, |
| 176 | 177 | }; |
| 177 | 178 | |
| 178 | −static unsigned int channels[] = { | |
| 179 | +static const unsigned int channels[] = { | |
| 179 | 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 | 184 | .count = ARRAY_SIZE(channels), |
| 184 | 185 | .list = channels, |
| 185 | 186 | .mask = 0, |
| @@ -264,11 +265,11 @@ static int skylake_dmic_fixup(struct snd_soc_pcm_runtime *rtd, · 78 unmodified lines | ||
| 264 | 265 | return 0; |
| 265 | 266 | } |
| 266 | 267 | |
| 267 | −static unsigned int channels_dmic[] = { | |
| 268 | +static const unsigned int channels_dmic[] = { | |
| 268 | 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 | 273 | .count = ARRAY_SIZE(channels_dmic), |
| 273 | 274 | .list = channels_dmic, |
| 274 | 275 | .mask = 0, |
| @@ -310,6 +311,23 @@ static struct snd_soc_dai_link skylake_rt286_dais[] = { · 35 unmodified lines | ||
| 310 | 311 | .dpcm_playback = 1, |
| 311 | 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 | 331 | [SKL_DPCM_AUDIO_CP] = { |
| 314 | 332 | .name = "Skl Audio Capture Port", |
| 315 | 333 | .stream_name = "Audio Record", |
| @@ -43,6 +43,9 @@ static inline bool sst_acpi_find_package_from_hid(const u8 hid[ACPI_ID_LEN], · 42 unmodified lines | ||
| 43 | 43 | /* acpi match */ |
| 44 | 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 | 49 | /* Descriptor for SST ASoC machine driver */ |
| 47 | 50 | struct sst_acpi_mach { |
| 48 | 51 | /* ACPI ID for the matching machine driver. Audio codec for instance */ |
| @@ -55,5 +58,25 @@ struct sst_acpi_mach { · 6 unmodified lines | ||
| 55 | 58 | /* board name */ |
| 56 | 59 | const char *board; |
| 57 | 60 | struct sst_acpi_mach * (*machine_quirk)(void *arg); |
| 61 | + const void *quirk_data; | |
| 58 | 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); | |
| @@ -77,6 +77,10 @@ struct sst_addr { · 76 unmodified lines | ||
| 77 | 77 | u32 dram_offset; |
| 78 | 78 | u32 dsp_iram_offset; |
| 79 | 79 | u32 dsp_dram_offset; |
| 80 | + u32 sram0_base; | |
| 81 | + u32 sram1_base; | |
| 82 | + u32 w0_stat_sz; | |
| 83 | + u32 w0_up_sz; | |
| 80 | 84 | void __iomem *lpe; |
| 81 | 85 | void __iomem *shim; |
| 82 | 86 | void __iomem *pci_cfg; |
| @@ -63,16 +63,33 @@ static acpi_status sst_acpi_mach_match(acpi_handle handle, u32 level, · 62 unmodified lines | ||
| 63 | 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 | 80 | struct sst_acpi_mach *sst_acpi_find_machine(struct sst_acpi_mach *machines) |
| 67 | 81 | { |
| 68 | 82 | struct sst_acpi_mach *mach; |
| 69 | − bool found = false; | |
| 70 | 83 | |
| 71 | − for (mach = machines; mach->id[0]; mach++) | |
| 72 | − if (ACPI_SUCCESS(acpi_get_devices(mach->id, | |
| 73 | − sst_acpi_mach_match, | |
| 74 | − &found, NULL)) && found) | |
| 75 | − return mach; | |
| 84 | + for (mach = machines; mach->id[0]; mach++) { | |
| 85 | + if (sst_acpi_check_hid(mach->id) == true) { | |
| 86 | + if (mach->machine_quirk == NULL) | |
| 87 | + return mach; | |
| 88 | + | |
| 89 | + if (mach->machine_quirk(mach) != NULL) | |
| 90 | + return mach; | |
| 91 | + } | |
| 92 | + } | |
| 76 | 93 | return NULL; |
| 77 | 94 | } |
| 78 | 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], · 55 unmodified lines | ||
| 134 | 151 | } |
| 135 | 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 | 172 | MODULE_LICENSE("GPL v2"); |
| 138 | 173 | MODULE_DESCRIPTION("Intel Common ACPI Match module"); |
| @@ -1,6 +1,10 @@ | ||
| 1 | 1 | snd-soc-skl-objs := skl.o skl-pcm.o skl-nhlt.o skl-messages.o \ |
| 2 | 2 | skl-topology.o |
| 3 | 3 | |
| 4 | +ifdef CONFIG_DEBUG_FS | |
| 5 | + snd-soc-skl-objs += skl-debug.o | |
| 6 | +endif | |
| 7 | + | |
| 4 | 8 | obj-$(CONFIG_SND_SOC_INTEL_SKYLAKE) += snd-soc-skl.o |
| 5 | 9 | |
| 6 | 10 | # Skylake IPC Support |
| @@ -573,6 +573,10 @@ int bxt_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, · 572 unmodified lines | ||
| 573 | 573 | sst->fw_ops = bxt_fw_ops; |
| 574 | 574 | sst->addr.lpe = mmio_base; |
| 575 | 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 | 581 | sst_dsp_mailbox_init(sst, (BXT_ADSP_SRAM0_BASE + SKL_ADSP_W0_STAT_SZ), |
| 578 | 582 | SKL_ADSP_W0_UP_SZ, BXT_ADSP_SRAM1_BASE, SKL_ADSP_W1_SZ); |
| @@ -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 | +} | |
| @@ -507,6 +507,8 @@ static void skl_setup_cpr_gateway_cfg(struct skl_sst *ctx, · 506 unmodified lines | ||
| 507 | 507 | struct skl_module_cfg *mconfig, |
| 508 | 508 | struct skl_cpr_cfg *cpr_mconfig) |
| 509 | 509 | { |
| 510 | + u32 dma_io_buf; | |
| 511 | + | |
| 510 | 512 | cpr_mconfig->gtw_cfg.node_id = skl_get_node_id(ctx, mconfig); |
| 511 | 513 | |
| 512 | 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, · 1 unmodified line | ||
| 514 | 516 | return; |
| 515 | 517 | } |
| 516 | 518 | |
| 517 | − if (SKL_CONN_SOURCE == mconfig->hw_conn_type) | |
| 518 | − cpr_mconfig->gtw_cfg.dma_buffer_size = 2 * mconfig->obs; | |
| 519 | − else | |
| 520 | − cpr_mconfig->gtw_cfg.dma_buffer_size = 2 * mconfig->ibs; | |
| 519 | + switch (mconfig->hw_conn_type) { | |
| 520 | + case SKL_CONN_SOURCE: | |
| 521 | + if (mconfig->dev_type == SKL_DEVICE_HDAHOST) | |
| 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 | 543 | cpr_mconfig->cpr_feature_mask = 0; |
| 523 | 544 | cpr_mconfig->gtw_cfg.config_length = 0; |
| @@ -707,6 +728,7 @@ static u16 skl_get_module_param_size(struct skl_sst *ctx, · 183 unmodified lines | ||
| 707 | 728 | return param_size; |
| 708 | 729 | |
| 709 | 730 | case SKL_MODULE_TYPE_BASE_OUTFMT: |
| 731 | + case SKL_MODULE_TYPE_MIC_SELECT: | |
| 710 | 732 | case SKL_MODULE_TYPE_KPB: |
| 711 | 733 | return sizeof(struct skl_base_outfmt_cfg); |
| 712 | 734 | |
| @@ -761,6 +783,7 @@ static int skl_set_module_format(struct skl_sst *ctx, · 48 unmodified lines | ||
| 761 | 783 | break; |
| 762 | 784 | |
| 763 | 785 | case SKL_MODULE_TYPE_BASE_OUTFMT: |
| 786 | + case SKL_MODULE_TYPE_MIC_SELECT: | |
| 764 | 787 | case SKL_MODULE_TYPE_KPB: |
| 765 | 788 | skl_set_base_outfmt_format(ctx, module_config, *param_data); |
| 766 | 789 | break; |
| @@ -1249,12 +1249,16 @@ static int skl_platform_soc_probe(struct snd_soc_platform *platform) · 1248 unmodified lines | ||
| 1249 | 1249 | |
| 1250 | 1250 | pm_runtime_get_sync(platform->dev); |
| 1251 | 1251 | if ((ebus_to_hbus(ebus))->ppcap) { |
| 1252 | + skl->platform = platform; | |
| 1253 | + | |
| 1254 | + /* init debugfs */ | |
| 1255 | + skl->debugfs = skl_debugfs_init(skl); | |
| 1256 | + | |
| 1252 | 1257 | ret = skl_tplg_init(platform, ebus); |
| 1253 | 1258 | if (ret < 0) { |
| 1254 | 1259 | dev_err(platform->dev, "Failed to init topology!\n"); |
| 1255 | 1260 | return ret; |
| 1256 | 1261 | } |
| 1257 | − skl->platform = platform; | |
| 1258 | 1262 | |
| 1259 | 1263 | /* load the firmwares, since all is set */ |
| 1260 | 1264 | ops = skl_get_dsp_ops(skl->pci->device); |
| @@ -553,6 +553,11 @@ int skl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, · 552 unmodified lines | ||
| 553 | 553 | sst = skl->dsp; |
| 554 | 554 | sst->addr.lpe = mmio_base; |
| 555 | 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 | 561 | sst_dsp_mailbox_init(sst, (SKL_ADSP_SRAM0_BASE + SKL_ADSP_W0_STAT_SZ), |
| 557 | 562 | SKL_ADSP_W0_UP_SZ, SKL_ADSP_SRAM1_BASE, SKL_ADSP_W1_SZ); |
| 558 | 563 | |
| @@ -36,6 +36,19 @@ · 35 unmodified lines | ||
| 36 | 36 | #define SKL_IN_DIR_BIT_MASK BIT(0) |
| 37 | 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 | 52 | void skl_tplg_d0i3_get(struct skl *skl, enum d0i3_capability caps) |
| 40 | 53 | { |
| 41 | 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, · 1272 unmodified lines | ||
| 1314 | 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 | 1436 | * Fill the dma id for host and link. In case of passthrough |
| 1319 | 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[] = { · 346 unmodified lines | ||
| 1666 | 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 | 1795 | static int skl_tplg_fill_pipe_tkn(struct device *dev, |
| 1670 | 1796 | struct skl_pipe *pipe, u32 tkn, |
| 1671 | 1797 | u32 tkn_val) |
| @@ -1995,7 +2121,7 @@ static int skl_tplg_get_token(struct device *dev, · 323 unmodified lines | ||
| 1995 | 2121 | mconfig->converter = tkn_elem->value; |
| 1996 | 2122 | break; |
| 1997 | 2123 | |
| 1998 | − case SKL_TKL_U32_D0I3_CAPS: | |
| 2124 | + case SKL_TKN_U32_D0I3_CAPS: | |
| 1999 | 2125 | mconfig->d0i3_caps = tkn_elem->value; |
| 2000 | 2126 | break; |
| 2001 | 2127 | |
| @@ -2070,12 +2196,26 @@ static int skl_tplg_get_token(struct device *dev, · 68 unmodified lines | ||
| 2070 | 2196 | |
| 2071 | 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 | 2209 | case SKL_TKN_U32_PROC_DOMAIN: |
| 2074 | 2210 | mconfig->domain = |
| 2075 | 2211 | tkn_elem->value; |
| 2076 | 2212 | |
| 2077 | 2213 | break; |
| 2078 | 2214 | |
| 2215 | + case SKL_TKN_U32_DMA_BUF_SIZE: | |
| 2216 | + mconfig->dma_buffer_size = tkn_elem->value; | |
| 2217 | + break; | |
| 2218 | + | |
| 2079 | 2219 | case SKL_TKN_U8_IN_PIN_TYPE: |
| 2080 | 2220 | case SKL_TKN_U8_OUT_PIN_TYPE: |
| 2081 | 2221 | case SKL_TKN_U8_CONN_TYPE: |
| @@ -2147,7 +2287,7 @@ static int skl_tplg_get_tokens(struct device *dev, · 65 unmodified lines | ||
| 2147 | 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, · 44 unmodified lines | ||
| 2198 | 2338 | num_blocks = ret; |
| 2199 | 2339 | |
| 2200 | 2340 | off += array->size; |
| 2201 | − array = (struct snd_soc_tplg_vendor_array *)(tplg_w->priv.data + off); | |
| 2202 | − | |
| 2203 | 2341 | /* Read the BLOCK_TYPE and BLOCK_SIZE descriptor */ |
| 2204 | 2342 | while (num_blocks > 0) { |
| 2343 | + array = (struct snd_soc_tplg_vendor_array *) | |
| 2344 | + (tplg_w->priv.data + off); | |
| 2345 | + | |
| 2205 | 2346 | ret = skl_tplg_get_desc_blocks(dev, array); |
| 2206 | 2347 | |
| 2207 | 2348 | if (ret < 0) |
| @@ -2237,7 +2378,9 @@ static int skl_tplg_get_pvt_data(struct snd_soc_tplg_dapm_widget *tplg_w, · 29 unmodified lines | ||
| 2237 | 2378 | memcpy(mconfig->formats_config.caps, data, |
| 2238 | 2379 | mconfig->formats_config.caps_size); |
| 2239 | 2380 | --num_blocks; |
| 2381 | + ret = mconfig->formats_config.caps_size; | |
| 2240 | 2382 | } |
| 2383 | + off += ret; | |
| 2241 | 2384 | } |
| 2242 | 2385 | |
| 2243 | 2386 | return 0; |
| @@ -2329,6 +2472,9 @@ static int skl_tplg_widget_load(struct snd_soc_component *cmpnt, · 85 unmodified lines | ||
| 2329 | 2472 | ret = skl_tplg_get_pvt_data(tplg_w, skl, bus->dev, mconfig); |
| 2330 | 2473 | if (ret < 0) |
| 2331 | 2474 | return ret; |
| 2475 | + | |
| 2476 | + skl_debug_init_module(skl->debugfs, w, mconfig); | |
| 2477 | + | |
| 2332 | 2478 | bind_event: |
| 2333 | 2479 | if (tplg_w->event_type == 0) { |
| 2334 | 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, · 42 unmodified lines | ||
| 2377 | 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 | 2544 | static int skl_tplg_control_load(struct snd_soc_component *cmpnt, |
| 2381 | 2545 | struct snd_kcontrol_new *kctl, |
| 2382 | 2546 | struct snd_soc_tplg_ctl_hdr *hdr) |
| 2383 | 2547 | { |
| 2384 | 2548 | struct soc_bytes_ext *sb; |
| 2385 | 2549 | struct snd_soc_tplg_bytes_control *tplg_bc; |
| 2550 | + struct snd_soc_tplg_enum_control *tplg_ec; | |
| 2386 | 2551 | struct hdac_ext_bus *ebus = snd_soc_component_get_drvdata(cmpnt); |
| 2387 | 2552 | struct hdac_bus *bus = ebus_to_hbus(ebus); |
| 2553 | + struct soc_enum *se; | |
| 2388 | 2554 | |
| 2389 | 2555 | switch (hdr->ops.info) { |
| 2390 | 2556 | case SND_SOC_TPLG_CTL_BYTES: |
| @@ -2398,6 +2564,17 @@ static int skl_tplg_control_load(struct snd_soc_component *cmpnt, · 7 unmodified lines | ||
| 2398 | 2564 | } |
| 2399 | 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 | 2578 | default: |
| 2402 | 2579 | dev_warn(bus->dev, "Control load not supported %d:%d:%d\n", |
| 2403 | 2580 | hdr->ops.get, hdr->ops.put, hdr->ops.info); |
| @@ -2626,6 +2803,8 @@ static struct snd_soc_tplg_ops skl_tplg_ops = { · 222 unmodified lines | ||
| 2626 | 2803 | .control_load = skl_tplg_control_load, |
| 2627 | 2804 | .bytes_ext_ops = skl_tlv_ops, |
| 2628 | 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 | 2808 | .manifest = skl_manifest_load, |
| 2630 | 2809 | }; |
| 2631 | 2810 | |
| @@ -39,6 +39,11 @@ · 38 unmodified lines | ||
| 39 | 39 | #define MODULE_MAX_IN_PINS 8 |
| 40 | 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 | 47 | enum skl_channel_index { |
| 43 | 48 | SKL_CHANNEL_LEFT = 0, |
| 44 | 49 | SKL_CHANNEL_RIGHT = 1, |
| @@ -309,11 +314,14 @@ struct skl_module_cfg { · 264 unmodified lines | ||
| 309 | 314 | u8 dev_type; |
| 310 | 315 | u8 dma_id; |
| 311 | 316 | u8 time_slot; |
| 317 | + u8 dmic_ch_combo_index; | |
| 318 | + u32 dmic_ch_type; | |
| 312 | 319 | u32 params_fixup; |
| 313 | 320 | u32 converter; |
| 314 | 321 | u32 vbus_id; |
| 315 | 322 | u32 mem_pages; |
| 316 | 323 | enum d0i3_capability d0i3_caps; |
| 324 | + u32 dma_buffer_size; /* in milli seconds */ | |
| 317 | 325 | struct skl_module_pin *m_in_pin; |
| 318 | 326 | struct skl_module_pin *m_out_pin; |
| 319 | 327 | enum skl_module_type m_type; |
| @@ -342,6 +350,19 @@ struct skl_module_deferred_bind { · 22 unmodified lines | ||
| 342 | 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 | 366 | static inline struct skl *get_skl_ctx(struct device *dev) |
| 346 | 367 | { |
| 347 | 368 | struct hdac_ext_bus *ebus = dev_get_drvdata(dev); |
| @@ -24,6 +24,7 @@ · 23 unmodified lines | ||
| 24 | 24 | * SST types start at higher to avoid any overlapping in future |
| 25 | 25 | */ |
| 26 | 26 | #define SKL_CONTROL_TYPE_BYTE_TLV 0x100 |
| 27 | +#define SKL_CONTROL_TYPE_MIC_SELECT 0x102 | |
| 27 | 28 | |
| 28 | 29 | #define HDA_SST_CFG_MAX 900 /* size of copier cfg*/ |
| 29 | 30 | #define MAX_IN_QUEUE 8 |
| @@ -82,6 +83,7 @@ enum skl_module_type { · 52 unmodified lines | ||
| 82 | 83 | SKL_MODULE_TYPE_ALGO, |
| 83 | 84 | SKL_MODULE_TYPE_BASE_OUTFMT, |
| 84 | 85 | SKL_MODULE_TYPE_KPB, |
| 86 | + SKL_MODULE_TYPE_MIC_SELECT, | |
| 85 | 87 | }; |
| 86 | 88 | |
| 87 | 89 | enum skl_core_affinity { |
| @@ -866,6 +866,7 @@ static void skl_remove(struct pci_dev *pci) · 865 unmodified lines | ||
| 866 | 866 | /* codec removal, invoke bus_device_remove */ |
| 867 | 867 | snd_hdac_ext_bus_device_remove(ebus); |
| 868 | 868 | |
| 869 | + skl->debugfs = NULL; | |
| 869 | 870 | skl_platform_unregister(&pci->dev); |
| 870 | 871 | skl_free_dsp(skl); |
| 871 | 872 | skl_machine_device_unregister(skl); |
| @@ -876,29 +877,120 @@ static void skl_remove(struct pci_dev *pci) · 4 unmodified lines | ||
| 876 | 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 | 906 | static struct sst_acpi_mach sst_skl_devdata[] = { |
| 880 | − { "INT343A", "skl_alc286s_i2s", "intel/dsp_fw_release.bin", NULL, NULL, NULL }, | |
| 881 | − { "INT343B", "skl_n88l25_s4567", "intel/dsp_fw_release.bin", | |
| 882 | − NULL, NULL, &skl_dmic_data }, | |
| 883 | − { "MX98357A", "skl_n88l25_m98357a", "intel/dsp_fw_release.bin", | |
| 884 | − NULL, NULL, &skl_dmic_data }, | |
| 907 | + { | |
| 908 | + .id = "INT343A", | |
| 909 | + .drv_name = "skl_alc286s_i2s", | |
| 910 | + .fw_filename = "intel/dsp_fw_release.bin", | |
| 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 | 931 | static struct sst_acpi_mach sst_bxtp_devdata[] = { |
| 889 | − { "INT343A", "bxt_alc298s_i2s", "intel/dsp_fw_bxtn.bin", NULL, NULL, NULL }, | |
| 890 | − { "DLGS7219", "bxt_da7219_max98357a_i2s", "intel/dsp_fw_bxtn.bin", NULL, NULL, NULL }, | |
| 932 | + { | |
| 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 | 946 | static struct sst_acpi_mach sst_kbl_devdata[] = { |
| 894 | − { "INT343A", "kbl_alc286s_i2s", "intel/dsp_fw_kbl.bin", NULL, NULL, NULL }, | |
| 895 | − { "INT343B", "kbl_n88l25_s4567", "intel/dsp_fw_kbl.bin", NULL, NULL, &skl_dmic_data }, | |
| 896 | − { "MX98357A", "kbl_n88l25_m98357a", "intel/dsp_fw_kbl.bin", NULL, NULL, &skl_dmic_data }, | |
| 947 | + { | |
| 948 | + .id = "INT343A", | |
| 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 | 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 | 996 | /* PCI IDs */ |
| @@ -23,6 +23,7 @@ · 22 unmodified lines | ||
| 23 | 23 | |
| 24 | 24 | #include <sound/hda_register.h> |
| 25 | 25 | #include <sound/hdaudio_ext.h> |
| 26 | +#include <sound/soc.h> | |
| 26 | 27 | #include "skl-nhlt.h" |
| 27 | 28 | |
| 28 | 29 | #define SKL_SUSPEND_DELAY 2000 |
| @@ -42,6 +43,8 @@ struct skl_dsp_resource { · 13 unmodified lines | ||
| 42 | 43 | u32 mem; |
| 43 | 44 | }; |
| 44 | 45 | |
| 46 | +struct skl_debug; | |
| 47 | + | |
| 45 | 48 | struct skl { |
| 46 | 49 | struct hdac_ext_bus ebus; |
| 47 | 50 | struct pci_dev *pci; |
| @@ -66,6 +69,8 @@ struct skl { · 18 unmodified lines | ||
| 66 | 69 | int supend_active; |
| 67 | 70 | |
| 68 | 71 | struct work_struct probe_work; |
| 72 | + | |
| 73 | + struct skl_debug *debugfs; | |
| 69 | 74 | }; |
| 70 | 75 | |
| 71 | 76 | #define skl_to_ebus(s) (&(s)->ebus) |
| @@ -116,4 +121,22 @@ void skl_update_d0i3c(struct device *dev, bool enable); · 44 unmodified lines | ||
| 116 | 121 | int skl_nhlt_create_sysfs(struct skl *skl); |
| 117 | 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 | 142 | #endif /* __SOUND_SOC_SKL_H */ |
| @@ -68,6 +68,20 @@ static int pmdown_time = 5000; · 67 unmodified lines | ||
| 68 | 68 | module_param(pmdown_time, int, 0); |
| 69 | 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 | 85 | /* returns the minimum number of bytes needed to represent |
| 72 | 86 | * a particular given value */ |
| 73 | 87 | static int min_bytes_needed(unsigned long val) |
| @@ -1933,6 +1947,22 @@ static void cleanup_dmi_name(char *name) · 1859 unmodified lines | ||
| 1933 | 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 | 1967 | * snd_soc_set_dmi_name() - Register DMI names to card |
| 1938 | 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) · 36 unmodified lines | ||
| 1975 | 2005 | |
| 1976 | 2006 | /* make up dmi long name as: vendor.product.version.board */ |
| 1977 | 2007 | vendor = dmi_get_system_info(DMI_BOARD_VENDOR); |
| 1978 | − if (!vendor) { | |
| 2008 | + if (!vendor || !is_dmi_valid(vendor)) { | |
| 1979 | 2009 | dev_warn(card->dev, "ASoC: no DMI vendor name!\n"); |
| 1980 | 2010 | return 0; |
| 1981 | 2011 | } |
| 1982 | 2012 | |
| 2013 | + | |
| 1983 | 2014 | snprintf(card->dmi_longname, sizeof(card->snd_card->longname), |
| 1984 | 2015 | "%s", vendor); |
| 1985 | 2016 | cleanup_dmi_name(card->dmi_longname); |
| 1986 | 2017 | |
| 1987 | 2018 | product = dmi_get_system_info(DMI_PRODUCT_NAME); |
| 1988 | − if (product) { | |
| 2019 | + if (product && is_dmi_valid(product)) { | |
| 1989 | 2020 | len = strlen(card->dmi_longname); |
| 1990 | 2021 | snprintf(card->dmi_longname + len, |
| 1991 | 2022 | longname_buf_size - len, |
| @@ -1999,7 +2030,7 @@ int snd_soc_set_dmi_name(struct snd_soc_card *card, const char *flavour) · 7 unmodified lines | ||
| 1999 | 2030 | * name in the product version field |
| 2000 | 2031 | */ |
| 2001 | 2032 | product_version = dmi_get_system_info(DMI_PRODUCT_VERSION); |
| 2002 | − if (product_version) { | |
| 2033 | + if (product_version && is_dmi_valid(product_version)) { | |
| 2003 | 2034 | len = strlen(card->dmi_longname); |
| 2004 | 2035 | snprintf(card->dmi_longname + len, |
| 2005 | 2036 | longname_buf_size - len, |
| @@ -2012,7 +2043,7 @@ int snd_soc_set_dmi_name(struct snd_soc_card *card, const char *flavour) · 6 unmodified lines | ||
| 2012 | 2043 | } |
| 2013 | 2044 | |
| 2014 | 2045 | board = dmi_get_system_info(DMI_BOARD_NAME); |
| 2015 | − if (board) { | |
| 2046 | + if (board && is_dmi_valid(board)) { | |
| 2016 | 2047 | len = strlen(card->dmi_longname); |
| 2017 | 2048 | snprintf(card->dmi_longname + len, |
| 2018 | 2049 | longname_buf_size - len, |