Commit 2016d5ed authored by Mark Brown's avatar Mark Brown

Merge remote-tracking branch 'asoc/topic/intel' into asoc-next

parents 05325120 7d3d6e06
...@@ -161,6 +161,8 @@ ...@@ -161,6 +161,8 @@
* *
* %SKL_TKL_U32_D0I3_CAPS: Specifies the D0i3 capability for module * %SKL_TKL_U32_D0I3_CAPS: Specifies the D0i3 capability for module
* *
* %SKL_TKN_U32_DMA_BUF_SIZE: DMA buffer size in millisec
*
* module_id and loadable flags dont have tokens as these values will be * module_id and loadable flags dont have tokens as these values will be
* read from the DSP FW manifest * read from the DSP FW manifest
*/ */
...@@ -213,8 +215,10 @@ enum SKL_TKNS { ...@@ -213,8 +215,10 @@ enum SKL_TKNS {
SKL_TKN_U32_LIB_COUNT, SKL_TKN_U32_LIB_COUNT,
SKL_TKN_STR_LIB_NAME, SKL_TKN_STR_LIB_NAME,
SKL_TKN_U32_PMODE, SKL_TKN_U32_PMODE,
SKL_TKL_U32_D0I3_CAPS, SKL_TKL_U32_D0I3_CAPS, /* Typo added at v4.10 */
SKL_TKN_MAX = SKL_TKL_U32_D0I3_CAPS, SKL_TKN_U32_D0I3_CAPS = SKL_TKL_U32_D0I3_CAPS,
SKL_TKN_U32_DMA_BUF_SIZE,
SKL_TKN_MAX = SKL_TKN_U32_DMA_BUF_SIZE,
}; };
#endif #endif
...@@ -2848,6 +2848,10 @@ static const struct dmi_system_id dmi_platform_intel_braswell[] = { ...@@ -2848,6 +2848,10 @@ static const struct dmi_system_id dmi_platform_intel_braswell[] = {
DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad Tablet B"), DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad Tablet B"),
}, },
}, },
{}
};
static const struct dmi_system_id dmi_platform_intel_bytcht_jdmode2[] = {
{ {
.ident = "Lenovo Thinkpad Tablet 10", .ident = "Lenovo Thinkpad Tablet 10",
.matches = { .matches = {
...@@ -2882,6 +2886,11 @@ static int rt5670_i2c_probe(struct i2c_client *i2c, ...@@ -2882,6 +2886,11 @@ static int rt5670_i2c_probe(struct i2c_client *i2c,
rt5670->pdata.dmic1_data_pin = RT5670_DMIC_DATA_IN2P; rt5670->pdata.dmic1_data_pin = RT5670_DMIC_DATA_IN2P;
rt5670->pdata.dev_gpio = true; rt5670->pdata.dev_gpio = true;
rt5670->pdata.jd_mode = 1; rt5670->pdata.jd_mode = 1;
} else if (dmi_check_system(dmi_platform_intel_bytcht_jdmode2)) {
rt5670->pdata.dmic_en = true;
rt5670->pdata.dmic1_data_pin = RT5670_DMIC_DATA_IN2P;
rt5670->pdata.dev_gpio = true;
rt5670->pdata.jd_mode = 2;
} }
rt5670->regmap = devm_regmap_init_i2c(i2c, &rt5670_regmap); rt5670->regmap = devm_regmap_init_i2c(i2c, &rt5670_regmap);
......
...@@ -41,15 +41,6 @@ ...@@ -41,15 +41,6 @@
#define RT5677_PR_BASE (RT5677_PR_RANGE_BASE + (0 * RT5677_PR_SPACING)) #define RT5677_PR_BASE (RT5677_PR_RANGE_BASE + (0 * RT5677_PR_SPACING))
/* GPIO indexes defined by ACPI */
enum {
RT5677_GPIO_PLUG_DET = 0,
RT5677_GPIO_MIC_PRESENT_L = 1,
RT5677_GPIO_HOTWORD_DET_L = 2,
RT5677_GPIO_DSP_INT = 3,
RT5677_GPIO_HP_AMP_SHDN_L = 4,
};
static const struct regmap_range_cfg rt5677_ranges[] = { static const struct regmap_range_cfg rt5677_ranges[] = {
{ {
.name = "PR", .name = "PR",
...@@ -5030,7 +5021,6 @@ static const struct regmap_config rt5677_regmap = { ...@@ -5030,7 +5021,6 @@ static const struct regmap_config rt5677_regmap = {
static const struct i2c_device_id rt5677_i2c_id[] = { static const struct i2c_device_id rt5677_i2c_id[] = {
{ "rt5677", RT5677 }, { "rt5677", RT5677 },
{ "rt5676", RT5676 }, { "rt5676", RT5676 },
{ "RT5677CE:00", RT5677 },
{ } { }
}; };
MODULE_DEVICE_TABLE(i2c, rt5677_i2c_id); MODULE_DEVICE_TABLE(i2c, rt5677_i2c_id);
...@@ -5041,28 +5031,19 @@ static const struct of_device_id rt5677_of_match[] = { ...@@ -5041,28 +5031,19 @@ static const struct of_device_id rt5677_of_match[] = {
}; };
MODULE_DEVICE_TABLE(of, rt5677_of_match); MODULE_DEVICE_TABLE(of, rt5677_of_match);
static const struct acpi_gpio_params plug_det_gpio = { RT5677_GPIO_PLUG_DET, 0, false }; #ifdef CONFIG_ACPI
static const struct acpi_gpio_params mic_present_gpio = { RT5677_GPIO_MIC_PRESENT_L, 0, false }; static const struct acpi_device_id rt5677_acpi_match[] = {
static const struct acpi_gpio_params headphone_enable_gpio = { RT5677_GPIO_HP_AMP_SHDN_L, 0, false }; { "RT5677CE", RT5677 },
{ }
static const struct acpi_gpio_mapping bdw_rt5677_gpios[] = {
{ "plug-det-gpios", &plug_det_gpio, 1 },
{ "mic-present-gpios", &mic_present_gpio, 1 },
{ "headphone-enable-gpios", &headphone_enable_gpio, 1 },
{ NULL },
}; };
MODULE_DEVICE_TABLE(acpi, rt5677_acpi_match);
#endif
static void rt5677_read_acpi_properties(struct rt5677_priv *rt5677, static void rt5677_read_acpi_properties(struct rt5677_priv *rt5677,
struct device *dev) struct device *dev)
{ {
int ret;
u32 val; u32 val;
ret = acpi_dev_add_driver_gpios(ACPI_COMPANION(dev),
bdw_rt5677_gpios);
if (ret)
dev_warn(dev, "Failed to add driver gpios\n");
if (!device_property_read_u32(dev, "DCLK", &val)) if (!device_property_read_u32(dev, "DCLK", &val))
rt5677->pdata.dmic2_clk_pin = val; rt5677->pdata.dmic2_clk_pin = val;
...@@ -5301,6 +5282,7 @@ static struct i2c_driver rt5677_i2c_driver = { ...@@ -5301,6 +5282,7 @@ static struct i2c_driver rt5677_i2c_driver = {
.driver = { .driver = {
.name = "rt5677", .name = "rt5677",
.of_match_table = rt5677_of_match, .of_match_table = rt5677_of_match,
.acpi_match_table = ACPI_PTR(rt5677_acpi_match),
}, },
.probe = rt5677_i2c_probe, .probe = rt5677_i2c_probe,
.remove = rt5677_i2c_remove, .remove = rt5677_i2c_remove,
......
...@@ -214,6 +214,18 @@ config SND_SOC_INTEL_BYT_CHT_DA7213_MACH ...@@ -214,6 +214,18 @@ config SND_SOC_INTEL_BYT_CHT_DA7213_MACH
platforms with DA7212/7213 audio codec. platforms with DA7212/7213 audio codec.
If unsure select "N". If unsure select "N".
config SND_SOC_INTEL_BYT_CHT_ES8316_MACH
tristate "ASoC Audio driver for Intel Baytrail & Cherrytrail with ES8316 codec"
depends on X86_INTEL_LPSS && I2C && ACPI
select SND_SOC_ES8316
select SND_SST_ATOM_HIFI2_PLATFORM
select SND_SST_IPC_ACPI
select SND_SOC_INTEL_SST_MATCH if ACPI
help
This adds support for ASoC machine driver for Intel(R) Baytrail &
Cherrytrail platforms with ES8316 audio codec.
If unsure select "N".
config SND_SOC_INTEL_BYT_CHT_NOCODEC_MACH config SND_SOC_INTEL_BYT_CHT_NOCODEC_MACH
tristate "ASoC Audio driver for Intel Baytrail & Cherrytrail platform with no codec (MinnowBoard MAX, Up)" tristate "ASoC Audio driver for Intel Baytrail & Cherrytrail platform with no codec (MinnowBoard MAX, Up)"
depends on X86_INTEL_LPSS && I2C && ACPI depends on X86_INTEL_LPSS && I2C && ACPI
...@@ -226,6 +238,36 @@ config SND_SOC_INTEL_BYT_CHT_NOCODEC_MACH ...@@ -226,6 +238,36 @@ config SND_SOC_INTEL_BYT_CHT_NOCODEC_MACH
connector connector
If unsure select "N". If unsure select "N".
config SND_SOC_INTEL_KBL_RT5663_MAX98927_MACH
tristate "ASoC Audio driver for KBL with RT5663 and MAX98927 in I2S Mode"
depends on X86_INTEL_LPSS && I2C
select SND_SOC_INTEL_SST
select SND_SOC_INTEL_SKYLAKE
select SND_SOC_RT5663
select SND_SOC_MAX98927
select SND_SOC_DMIC
select SND_SOC_HDAC_HDMI
help
This adds support for ASoC Onboard Codec I2S machine driver. This will
create an alsa sound card for RT5663 + MAX98927.
Say Y if you have such a device.
If unsure select "N".
config SND_SOC_INTEL_KBL_RT5663_RT5514_MAX98927_MACH
tristate "ASoC Audio driver for KBL with RT5663, RT5514 and MAX98927 in I2S Mode"
depends on X86_INTEL_LPSS && I2C
select SND_SOC_INTEL_SST
select SND_SOC_INTEL_SKYLAKE
select SND_SOC_RT5663
select SND_SOC_RT5514
select SND_SOC_MAX98927
select SND_SOC_HDAC_HDMI
help
This adds support for ASoC Onboard Codec I2S machine driver. This will
create an alsa sound card for RT5663 + RT5514 + MAX98927.
Say Y if you have such a device.
If unsure select "N".
config SND_SOC_INTEL_SKYLAKE config SND_SOC_INTEL_SKYLAKE
tristate tristate
select SND_HDA_EXT_CORE select SND_HDA_EXT_CORE
......
...@@ -690,7 +690,7 @@ static int sst_pcm_new(struct snd_soc_pcm_runtime *rtd) ...@@ -690,7 +690,7 @@ static int sst_pcm_new(struct snd_soc_pcm_runtime *rtd)
snd_dma_continuous_data(GFP_DMA), snd_dma_continuous_data(GFP_DMA),
SST_MIN_BUFFER, SST_MAX_BUFFER); SST_MIN_BUFFER, SST_MAX_BUFFER);
if (retval) { if (retval) {
dev_err(rtd->dev, "dma buffer allocationf fail\n"); dev_err(rtd->dev, "dma buffer allocation failure\n");
return retval; return retval;
} }
} }
......
...@@ -258,7 +258,7 @@ static ssize_t firmware_version_show(struct device *dev, ...@@ -258,7 +258,7 @@ static ssize_t firmware_version_show(struct device *dev,
} }
DEVICE_ATTR_RO(firmware_version); static DEVICE_ATTR_RO(firmware_version);
static const struct attribute *sst_fw_version_attrs[] = { static const struct attribute *sst_fw_version_attrs[] = {
&dev_attr_firmware_version.attr, &dev_attr_firmware_version.attr,
...@@ -382,37 +382,6 @@ void sst_context_cleanup(struct intel_sst_drv *ctx) ...@@ -382,37 +382,6 @@ void sst_context_cleanup(struct intel_sst_drv *ctx)
} }
EXPORT_SYMBOL_GPL(sst_context_cleanup); EXPORT_SYMBOL_GPL(sst_context_cleanup);
static inline void sst_save_shim64(struct intel_sst_drv *ctx,
void __iomem *shim,
struct sst_shim_regs64 *shim_regs)
{
unsigned long irq_flags;
spin_lock_irqsave(&ctx->ipc_spin_lock, irq_flags);
shim_regs->imrx = sst_shim_read64(shim, SST_IMRX);
shim_regs->csr = sst_shim_read64(shim, SST_CSR);
spin_unlock_irqrestore(&ctx->ipc_spin_lock, irq_flags);
}
static inline void sst_restore_shim64(struct intel_sst_drv *ctx,
void __iomem *shim,
struct sst_shim_regs64 *shim_regs)
{
unsigned long irq_flags;
/*
* we only need to restore IMRX for this case, rest will be
* initialize by FW or driver when firmware is loaded
*/
spin_lock_irqsave(&ctx->ipc_spin_lock, irq_flags);
sst_shim_write64(shim, SST_IMRX, shim_regs->imrx);
sst_shim_write64(shim, SST_CSR, shim_regs->csr);
spin_unlock_irqrestore(&ctx->ipc_spin_lock, irq_flags);
}
void sst_configure_runtime_pm(struct intel_sst_drv *ctx) void sst_configure_runtime_pm(struct intel_sst_drv *ctx)
{ {
pm_runtime_set_autosuspend_delay(ctx->dev, SST_SUSPEND_DELAY); pm_runtime_set_autosuspend_delay(ctx->dev, SST_SUSPEND_DELAY);
...@@ -432,8 +401,6 @@ void sst_configure_runtime_pm(struct intel_sst_drv *ctx) ...@@ -432,8 +401,6 @@ void sst_configure_runtime_pm(struct intel_sst_drv *ctx)
pm_runtime_set_active(ctx->dev); pm_runtime_set_active(ctx->dev);
else else
pm_runtime_put_noidle(ctx->dev); pm_runtime_put_noidle(ctx->dev);
sst_save_shim64(ctx, ctx->shim, ctx->shim_regs64);
} }
EXPORT_SYMBOL_GPL(sst_configure_runtime_pm); EXPORT_SYMBOL_GPL(sst_configure_runtime_pm);
...@@ -457,8 +424,6 @@ static int intel_sst_runtime_suspend(struct device *dev) ...@@ -457,8 +424,6 @@ static int intel_sst_runtime_suspend(struct device *dev)
flush_workqueue(ctx->post_msg_wq); flush_workqueue(ctx->post_msg_wq);
ctx->ops->reset(ctx); ctx->ops->reset(ctx);
/* save the shim registers because PMC doesn't save state */
sst_save_shim64(ctx, ctx->shim, ctx->shim_regs64);
return ret; return ret;
} }
...@@ -499,23 +464,23 @@ static int intel_sst_suspend(struct device *dev) ...@@ -499,23 +464,23 @@ static int intel_sst_suspend(struct device *dev)
fw_save = kzalloc(sizeof(*fw_save), GFP_KERNEL); fw_save = kzalloc(sizeof(*fw_save), GFP_KERNEL);
if (!fw_save) if (!fw_save)
return -ENOMEM; return -ENOMEM;
fw_save->iram = kzalloc(ctx->iram_end - ctx->iram_base, GFP_KERNEL); fw_save->iram = kvzalloc(ctx->iram_end - ctx->iram_base, GFP_KERNEL);
if (!fw_save->iram) { if (!fw_save->iram) {
ret = -ENOMEM; ret = -ENOMEM;
goto iram; goto iram;
} }
fw_save->dram = kzalloc(ctx->dram_end - ctx->dram_base, GFP_KERNEL); fw_save->dram = kvzalloc(ctx->dram_end - ctx->dram_base, GFP_KERNEL);
if (!fw_save->dram) { if (!fw_save->dram) {
ret = -ENOMEM; ret = -ENOMEM;
goto dram; goto dram;
} }
fw_save->sram = kzalloc(SST_MAILBOX_SIZE, GFP_KERNEL); fw_save->sram = kvzalloc(SST_MAILBOX_SIZE, GFP_KERNEL);
if (!fw_save->sram) { if (!fw_save->sram) {
ret = -ENOMEM; ret = -ENOMEM;
goto sram; goto sram;
} }
fw_save->ddr = kzalloc(ctx->ddr_end - ctx->ddr_base, GFP_KERNEL); fw_save->ddr = kvzalloc(ctx->ddr_end - ctx->ddr_base, GFP_KERNEL);
if (!fw_save->ddr) { if (!fw_save->ddr) {
ret = -ENOMEM; ret = -ENOMEM;
goto ddr; goto ddr;
...@@ -530,11 +495,11 @@ static int intel_sst_suspend(struct device *dev) ...@@ -530,11 +495,11 @@ static int intel_sst_suspend(struct device *dev)
ctx->ops->reset(ctx); ctx->ops->reset(ctx);
return 0; return 0;
ddr: ddr:
kfree(fw_save->sram); kvfree(fw_save->sram);
sram: sram:
kfree(fw_save->dram); kvfree(fw_save->dram);
dram: dram:
kfree(fw_save->iram); kvfree(fw_save->iram);
iram: iram:
kfree(fw_save); kfree(fw_save);
return ret; return ret;
...@@ -562,10 +527,10 @@ static int intel_sst_resume(struct device *dev) ...@@ -562,10 +527,10 @@ static int intel_sst_resume(struct device *dev)
memcpy32_toio(ctx->mailbox, fw_save->sram, SST_MAILBOX_SIZE); memcpy32_toio(ctx->mailbox, fw_save->sram, SST_MAILBOX_SIZE);
memcpy32_toio(ctx->ddr, fw_save->ddr, ctx->ddr_end - ctx->ddr_base); memcpy32_toio(ctx->ddr, fw_save->ddr, ctx->ddr_end - ctx->ddr_base);
kfree(fw_save->sram); kvfree(fw_save->sram);
kfree(fw_save->dram); kvfree(fw_save->dram);
kfree(fw_save->iram); kvfree(fw_save->iram);
kfree(fw_save->ddr); kvfree(fw_save->ddr);
kfree(fw_save); kfree(fw_save);
block = sst_create_block(ctx, 0, FW_DWNL_ID); block = sst_create_block(ctx, 0, FW_DWNL_ID);
......
...@@ -317,31 +317,11 @@ struct sst_ipc_reg { ...@@ -317,31 +317,11 @@ struct sst_ipc_reg {
int ipcd; int ipcd;
}; };
struct sst_shim_regs64 {
u64 csr;
u64 pisr;
u64 pimr;
u64 isrx;
u64 isrd;
u64 imrx;
u64 imrd;
u64 ipcx;
u64 ipcd;
u64 isrsc;
u64 isrlpesc;
u64 imrsc;
u64 imrlpesc;
u64 ipcsc;
u64 ipclpesc;
u64 clkctl;
u64 csr2;
};
struct sst_fw_save { struct sst_fw_save {
void *iram; void *iram; /* allocated via kvmalloc() */
void *dram; void *dram; /* allocated via kvmalloc() */
void *sram; void *sram; /* allocated via kvmalloc() */
void *ddr; void *ddr; /* allocated via kvmalloc() */
}; };
/** /**
...@@ -356,7 +336,6 @@ struct sst_fw_save { ...@@ -356,7 +336,6 @@ struct sst_fw_save {
* @dram : SST DRAM pointer * @dram : SST DRAM pointer
* @pdata : SST info passed as a part of pci platform data * @pdata : SST info passed as a part of pci platform data
* @shim_phy_add : SST shim phy addr * @shim_phy_add : SST shim phy addr
* @shim_regs64: Struct to save shim registers
* @ipc_dispatch_list : ipc messages dispatched * @ipc_dispatch_list : ipc messages dispatched
* @rx_list : to copy the process_reply/process_msg from DSP * @rx_list : to copy the process_reply/process_msg from DSP
* @ipc_post_msg_wq : wq to post IPC messages context * @ipc_post_msg_wq : wq to post IPC messages context
...@@ -398,7 +377,6 @@ struct intel_sst_drv { ...@@ -398,7 +377,6 @@ struct intel_sst_drv {
unsigned int ddr_end; unsigned int ddr_end;
unsigned int ddr_base; unsigned int ddr_base;
unsigned int mailbox_recv_offset; unsigned int mailbox_recv_offset;
struct sst_shim_regs64 *shim_regs64;
struct list_head block_list; struct list_head block_list;
struct list_head ipc_dispatch_list; struct list_head ipc_dispatch_list;
struct sst_platform_info *pdata; struct sst_platform_info *pdata;
......
...@@ -303,8 +303,6 @@ static int sst_acpi_probe(struct platform_device *pdev) ...@@ -303,8 +303,6 @@ static int sst_acpi_probe(struct platform_device *pdev)
dev_err(dev, "No matching machine driver found\n"); dev_err(dev, "No matching machine driver found\n");
return -ENODEV; return -ENODEV;
} }
if (mach->machine_quirk)
mach = mach->machine_quirk(mach);
pdata = mach->pdata; pdata = mach->pdata;
...@@ -360,23 +358,9 @@ static int sst_acpi_probe(struct platform_device *pdev) ...@@ -360,23 +358,9 @@ static int sst_acpi_probe(struct platform_device *pdev)
if (ret < 0) if (ret < 0)
return ret; return ret;
/* need to save shim registers in BYT */
ctx->shim_regs64 = devm_kzalloc(ctx->dev, sizeof(*ctx->shim_regs64),
GFP_KERNEL);
if (!ctx->shim_regs64) {
ret = -ENOMEM;
goto do_sst_cleanup;
}
sst_configure_runtime_pm(ctx); sst_configure_runtime_pm(ctx);
platform_set_drvdata(pdev, ctx); platform_set_drvdata(pdev, ctx);
return ret; return ret;
do_sst_cleanup:
sst_context_cleanup(ctx);
platform_set_drvdata(pdev, NULL);
dev_err(ctx->dev, "failed with %d\n", ret);
return ret;
} }
/** /**
...@@ -453,12 +437,20 @@ static const struct dmi_system_id cht_table[] = { ...@@ -453,12 +437,20 @@ static const struct dmi_system_id cht_table[] = {
static struct sst_acpi_mach cht_surface_mach = { static struct sst_acpi_mach cht_surface_mach = {
"10EC5640", "cht-bsw-rt5645", "intel/fw_sst_22a8.bin", "cht-bsw", NULL, .id = "10EC5640",
&chv_platform_data }; .drv_name = "cht-bsw-rt5645",
.fw_filename = "intel/fw_sst_22a8.bin",
.board = "cht-bsw",
.pdata = &chv_platform_data,
};
static struct sst_acpi_mach byt_thinkpad_10 = { static struct sst_acpi_mach byt_thinkpad_10 = {
"10EC5640", "cht-bsw-rt5672", "intel/fw_sst_0f28.bin", "cht-bsw", NULL, .id = "10EC5640",
&byt_rvp_platform_data }; .drv_name = "cht-bsw-rt5672",
.fw_filename = "intel/fw_sst_0f28.bin",
.board = "cht-bsw",
.pdata = &byt_rvp_platform_data,
};
static struct sst_acpi_mach *cht_quirk(void *arg) static struct sst_acpi_mach *cht_quirk(void *arg)
{ {
...@@ -486,68 +478,182 @@ static struct sst_acpi_mach *byt_quirk(void *arg) ...@@ -486,68 +478,182 @@ static struct sst_acpi_mach *byt_quirk(void *arg)
static struct sst_acpi_mach sst_acpi_bytcr[] = { static struct sst_acpi_mach sst_acpi_bytcr[] = {
{"10EC5640", "bytcr_rt5640", "intel/fw_sst_0f28.bin", "bytcr_rt5640", byt_quirk, {
&byt_rvp_platform_data }, .id = "10EC5640",
{"10EC5642", "bytcr_rt5640", "intel/fw_sst_0f28.bin", "bytcr_rt5640", NULL, .drv_name = "bytcr_rt5640",
&byt_rvp_platform_data }, .fw_filename = "intel/fw_sst_0f28.bin",
{"INTCCFFD", "bytcr_rt5640", "intel/fw_sst_0f28.bin", "bytcr_rt5640", NULL, .board = "bytcr_rt5640",
&byt_rvp_platform_data }, .machine_quirk = byt_quirk,
{"10EC5651", "bytcr_rt5651", "intel/fw_sst_0f28.bin", "bytcr_rt5651", NULL, .pdata = &byt_rvp_platform_data,
&byt_rvp_platform_data }, },
{"DLGS7212", "bytcht_da7213", "intel/fw_sst_0f28.bin", "bytcht_da7213", NULL, {
&byt_rvp_platform_data }, .id = "10EC5642",
{"DLGS7213", "bytcht_da7213", "intel/fw_sst_0f28.bin", "bytcht_da7213", NULL, .drv_name = "bytcr_rt5640",
&byt_rvp_platform_data }, .fw_filename = "intel/fw_sst_0f28.bin",
.board = "bytcr_rt5640",
.pdata = &byt_rvp_platform_data
},
{
.id = "INTCCFFD",
.drv_name = "bytcr_rt5640",
.fw_filename = "intel/fw_sst_0f28.bin",
.board = "bytcr_rt5640",
.pdata = &byt_rvp_platform_data
},
{
.id = "10EC5651",
.drv_name = "bytcr_rt5651",
.fw_filename = "intel/fw_sst_0f28.bin",
.board = "bytcr_rt5651",
.pdata = &byt_rvp_platform_data
},
{
.id = "DLGS7212",
.drv_name = "bytcht_da7213",
.fw_filename = "intel/fw_sst_0f28.bin",
.board = "bytcht_da7213",
.pdata = &byt_rvp_platform_data
},
{
.id = "DLGS7213",
.drv_name = "bytcht_da7213",
.fw_filename = "intel/fw_sst_0f28.bin",
.board = "bytcht_da7213",
.pdata = &byt_rvp_platform_data
},
/* some Baytrail platforms rely on RT5645, use CHT machine driver */ /* some Baytrail platforms rely on RT5645, use CHT machine driver */
{"10EC5645", "cht-bsw-rt5645", "intel/fw_sst_0f28.bin", "cht-bsw", NULL, {
&byt_rvp_platform_data }, .id = "10EC5645",
{"10EC5648", "cht-bsw-rt5645", "intel/fw_sst_0f28.bin", "cht-bsw", NULL, .drv_name = "cht-bsw-rt5645",
&byt_rvp_platform_data }, .fw_filename = "intel/fw_sst_0f28.bin",
.board = "cht-bsw",
.pdata = &byt_rvp_platform_data
},
{
.id = "10EC5648",
.drv_name = "cht-bsw-rt5645",
.fw_filename = "intel/fw_sst_0f28.bin",
.board = "cht-bsw",
.pdata = &byt_rvp_platform_data
},
#if IS_ENABLED(CONFIG_SND_SOC_INTEL_BYT_CHT_NOCODEC_MACH) #if IS_ENABLED(CONFIG_SND_SOC_INTEL_BYT_CHT_NOCODEC_MACH)
/* /*
* This is always last in the table so that it is selected only when * This is always last in the table so that it is selected only when
* enabled explicitly and there is no codec-related information in SSDT * enabled explicitly and there is no codec-related information in SSDT
*/ */
{"80860F28", "bytcht_nocodec", "intel/fw_sst_0f28.bin", "bytcht_nocodec", NULL, {
&byt_rvp_platform_data }, .id = "80860F28",
.drv_name = "bytcht_nocodec",
.fw_filename = "intel/fw_sst_0f28.bin",
.board = "bytcht_nocodec",
.pdata = &byt_rvp_platform_data
},
#endif #endif
{}, {},
}; };
/* Cherryview-based platforms: CherryTrail and Braswell */ /* Cherryview-based platforms: CherryTrail and Braswell */
static struct sst_acpi_mach sst_acpi_chv[] = { static struct sst_acpi_mach sst_acpi_chv[] = {
{"10EC5670", "cht-bsw-rt5672", "intel/fw_sst_22a8.bin", "cht-bsw", NULL, {
&chv_platform_data }, .id = "10EC5670",
{"10EC5672", "cht-bsw-rt5672", "intel/fw_sst_22a8.bin", "cht-bsw", NULL, .drv_name = "cht-bsw-rt5672",
&chv_platform_data }, .fw_filename = "intel/fw_sst_22a8.bin",
{"10EC5645", "cht-bsw-rt5645", "intel/fw_sst_22a8.bin", "cht-bsw", NULL, .board = "cht-bsw",
&chv_platform_data }, .pdata = &chv_platform_data
{"10EC5650", "cht-bsw-rt5645", "intel/fw_sst_22a8.bin", "cht-bsw", NULL, },
&chv_platform_data }, {
{"10EC3270", "cht-bsw-rt5645", "intel/fw_sst_22a8.bin", "cht-bsw", NULL, .id = "10EC5672",
&chv_platform_data }, .drv_name = "cht-bsw-rt5672",
.fw_filename = "intel/fw_sst_22a8.bin",
{"193C9890", "cht-bsw-max98090", "intel/fw_sst_22a8.bin", "cht-bsw", NULL, .board = "cht-bsw",
&chv_platform_data }, .pdata = &chv_platform_data
{"DLGS7212", "bytcht_da7213", "intel/fw_sst_22a8.bin", "bytcht_da7213", NULL, },
&chv_platform_data }, {
{"DLGS7213", "bytcht_da7213", "intel/fw_sst_22a8.bin", "bytcht_da7213", NULL, .id = "10EC5645",
&chv_platform_data }, .drv_name = "cht-bsw-rt5645",
.fw_filename = "intel/fw_sst_22a8.bin",
.board = "cht-bsw",
.pdata = &chv_platform_data
},
{
.id = "10EC5650",
.drv_name = "cht-bsw-rt5645",
.fw_filename = "intel/fw_sst_22a8.bin",
.board = "cht-bsw",
.pdata = &chv_platform_data
},
{
.id = "10EC3270",
.drv_name = "cht-bsw-rt5645",
.fw_filename = "intel/fw_sst_22a8.bin",
.board = "cht-bsw",
.pdata = &chv_platform_data
},
{
.id = "193C9890",
.drv_name = "cht-bsw-max98090",
.fw_filename = "intel/fw_sst_22a8.bin",
.board = "cht-bsw",
.pdata = &chv_platform_data
},
{
.id = "DLGS7212",
.drv_name = "bytcht_da7213",
.fw_filename = "intel/fw_sst_22a8.bin",
.board = "bytcht_da7213",
.pdata = &chv_platform_data
},
{
.id = "DLGS7213",
.drv_name = "bytcht_da7213",
.fw_filename = "intel/fw_sst_22a8.bin",
.board = "bytcht_da7213",
.pdata = &chv_platform_data
},
{
.id = "ESSX8316",
.drv_name = "bytcht_es8316",
.fw_filename = "intel/fw_sst_22a8.bin",
.board = "bytcht_es8316",
.pdata = &chv_platform_data
},
/* some CHT-T platforms rely on RT5640, use Baytrail machine driver */ /* some CHT-T platforms rely on RT5640, use Baytrail machine driver */
{"10EC5640", "bytcr_rt5640", "intel/fw_sst_22a8.bin", "bytcr_rt5640", cht_quirk, {
&chv_platform_data }, .id = "10EC5640",
{"10EC3276", "bytcr_rt5640", "intel/fw_sst_22a8.bin", "bytcr_rt5640", NULL, .drv_name = "bytcr_rt5640",
&chv_platform_data }, .fw_filename = "intel/fw_sst_22a8.bin",
.board = "bytcr_rt5640",
.machine_quirk = cht_quirk,
.pdata = &chv_platform_data
},
{
.id = "10EC3276",
.drv_name = "bytcr_rt5640",
.fw_filename = "intel/fw_sst_22a8.bin",
.board = "bytcr_rt5640",
.pdata = &chv_platform_data
},
/* some CHT-T platforms rely on RT5651, use Baytrail machine driver */ /* some CHT-T platforms rely on RT5651, use Baytrail machine driver */
{"10EC5651", "bytcr_rt5651", "intel/fw_sst_22a8.bin", "bytcr_rt5651", NULL, {
&chv_platform_data }, .id = "10EC5651",
.drv_name = "bytcr_rt5651",
.fw_filename = "intel/fw_sst_22a8.bin",
.board = "bytcr_rt5651",
.pdata = &chv_platform_data
},
#if IS_ENABLED(CONFIG_SND_SOC_INTEL_BYT_CHT_NOCODEC_MACH) #if IS_ENABLED(CONFIG_SND_SOC_INTEL_BYT_CHT_NOCODEC_MACH)
/* /*
* This is always last in the table so that it is selected only when * This is always last in the table so that it is selected only when
* enabled explicitly and there is no codec-related information in SSDT * enabled explicitly and there is no codec-related information in SSDT
*/ */
{"808622A8", "bytcht_nocodec", "intel/fw_sst_22a8.bin", "bytcht_nocodec", NULL, {
&chv_platform_data }, .id = "808622A8",
.drv_name = "bytcht_nocodec",
.fw_filename = "intel/fw_sst_22a8.bin",
.board = "bytcht_nocodec",
.pdata = &chv_platform_data
},
#endif #endif
{}, {},
}; };
......
...@@ -11,7 +11,10 @@ snd-soc-sst-cht-bsw-rt5672-objs := cht_bsw_rt5672.o ...@@ -11,7 +11,10 @@ snd-soc-sst-cht-bsw-rt5672-objs := cht_bsw_rt5672.o
snd-soc-sst-cht-bsw-rt5645-objs := cht_bsw_rt5645.o snd-soc-sst-cht-bsw-rt5645-objs := cht_bsw_rt5645.o
snd-soc-sst-cht-bsw-max98090_ti-objs := cht_bsw_max98090_ti.o snd-soc-sst-cht-bsw-max98090_ti-objs := cht_bsw_max98090_ti.o
snd-soc-sst-byt-cht-da7213-objs := bytcht_da7213.o snd-soc-sst-byt-cht-da7213-objs := bytcht_da7213.o
snd-soc-sst-byt-cht-es8316-objs := bytcht_es8316.o
snd-soc-sst-byt-cht-nocodec-objs := bytcht_nocodec.o snd-soc-sst-byt-cht-nocodec-objs := bytcht_nocodec.o
snd-soc-kbl_rt5663_max98927-objs := kbl_rt5663_max98927.o
snd-soc-kbl_rt5663_rt5514_max98927-objs := kbl_rt5663_rt5514_max98927.o
snd-soc-skl_rt286-objs := skl_rt286.o snd-soc-skl_rt286-objs := skl_rt286.o
snd-skl_nau88l25_max98357a-objs := skl_nau88l25_max98357a.o snd-skl_nau88l25_max98357a-objs := skl_nau88l25_max98357a.o
snd-soc-skl_nau88l25_ssm4567-objs := skl_nau88l25_ssm4567.o snd-soc-skl_nau88l25_ssm4567-objs := skl_nau88l25_ssm4567.o
...@@ -29,7 +32,10 @@ obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_RT5672_MACH) += snd-soc-sst-cht-bsw-rt5672.o ...@@ -29,7 +32,10 @@ obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_RT5672_MACH) += snd-soc-sst-cht-bsw-rt5672.o
obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_RT5645_MACH) += snd-soc-sst-cht-bsw-rt5645.o obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_RT5645_MACH) += snd-soc-sst-cht-bsw-rt5645.o
obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_MAX98090_TI_MACH) += snd-soc-sst-cht-bsw-max98090_ti.o obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_MAX98090_TI_MACH) += snd-soc-sst-cht-bsw-max98090_ti.o
obj-$(CONFIG_SND_SOC_INTEL_BYT_CHT_DA7213_MACH) += snd-soc-sst-byt-cht-da7213.o obj-$(CONFIG_SND_SOC_INTEL_BYT_CHT_DA7213_MACH) += snd-soc-sst-byt-cht-da7213.o
obj-$(CONFIG_SND_SOC_INTEL_BYT_CHT_ES8316_MACH) += snd-soc-sst-byt-cht-es8316.o
obj-$(CONFIG_SND_SOC_INTEL_BYT_CHT_NOCODEC_MACH) += snd-soc-sst-byt-cht-nocodec.o obj-$(CONFIG_SND_SOC_INTEL_BYT_CHT_NOCODEC_MACH) += snd-soc-sst-byt-cht-nocodec.o
obj-$(CONFIG_SND_SOC_INTEL_KBL_RT5663_MAX98927_MACH) += snd-soc-kbl_rt5663_max98927.o
obj-$(CONFIG_SND_SOC_INTEL_KBL_RT5663_RT5514_MAX98927_MACH) += snd-soc-kbl_rt5663_rt5514_max98927.o
obj-$(CONFIG_SND_SOC_INTEL_SKL_RT286_MACH) += snd-soc-skl_rt286.o obj-$(CONFIG_SND_SOC_INTEL_SKL_RT286_MACH) += snd-soc-skl_rt286.o
obj-$(CONFIG_SND_SOC_INTEL_SKL_NAU88L25_MAX98357A_MACH) += snd-skl_nau88l25_max98357a.o obj-$(CONFIG_SND_SOC_INTEL_SKL_NAU88L25_MAX98357A_MACH) += snd-skl_nau88l25_max98357a.o
obj-$(CONFIG_SND_SOC_INTEL_SKL_NAU88L25_SSM4567_MACH) += snd-soc-skl_nau88l25_ssm4567.o obj-$(CONFIG_SND_SOC_INTEL_SKL_NAU88L25_SSM4567_MACH) += snd-soc-skl_nau88l25_ssm4567.o
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <linux/acpi.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/gpio/consumer.h> #include <linux/gpio/consumer.h>
...@@ -120,6 +121,26 @@ static struct snd_soc_jack_gpio mic_jack_gpio = { ...@@ -120,6 +121,26 @@ static struct snd_soc_jack_gpio mic_jack_gpio = {
.invert = 1, .invert = 1,
}; };
/* GPIO indexes defined by ACPI */
enum {
RT5677_GPIO_PLUG_DET = 0,
RT5677_GPIO_MIC_PRESENT_L = 1,
RT5677_GPIO_HOTWORD_DET_L = 2,
RT5677_GPIO_DSP_INT = 3,
RT5677_GPIO_HP_AMP_SHDN_L = 4,
};
static const struct acpi_gpio_params plug_det_gpio = { RT5677_GPIO_PLUG_DET, 0, false };
static const struct acpi_gpio_params mic_present_gpio = { RT5677_GPIO_MIC_PRESENT_L, 0, false };
static const struct acpi_gpio_params headphone_enable_gpio = { RT5677_GPIO_HP_AMP_SHDN_L, 0, false };
static const struct acpi_gpio_mapping bdw_rt5677_gpios[] = {
{ "plug-det-gpios", &plug_det_gpio, 1 },
{ "mic-present-gpios", &mic_present_gpio, 1 },
{ "headphone-enable-gpios", &headphone_enable_gpio, 1 },
{ NULL },
};
static int broadwell_ssp0_fixup(struct snd_soc_pcm_runtime *rtd, static int broadwell_ssp0_fixup(struct snd_soc_pcm_runtime *rtd,
struct snd_pcm_hw_params *params) struct snd_pcm_hw_params *params)
{ {
...@@ -184,6 +205,11 @@ static int bdw_rt5677_init(struct snd_soc_pcm_runtime *rtd) ...@@ -184,6 +205,11 @@ static int bdw_rt5677_init(struct snd_soc_pcm_runtime *rtd)
snd_soc_card_get_drvdata(rtd->card); snd_soc_card_get_drvdata(rtd->card);
struct snd_soc_codec *codec = rtd->codec; struct snd_soc_codec *codec = rtd->codec;
struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
int ret;
ret = devm_acpi_dev_add_driver_gpios(codec->dev, bdw_rt5677_gpios);
if (ret)
dev_warn(codec->dev, "Failed to add driver gpios\n");
/* Enable codec ASRC function for Stereo DAC/Stereo1 ADC/DMIC/I2S1. /* Enable codec ASRC function for Stereo DAC/Stereo1 ADC/DMIC/I2S1.
* The ASRC clock source is clk_i2s1_asrc. * The ASRC clock source is clk_i2s1_asrc.
......
...@@ -242,31 +242,31 @@ static int broxton_da7219_fe_init(struct snd_soc_pcm_runtime *rtd) ...@@ -242,31 +242,31 @@ static int broxton_da7219_fe_init(struct snd_soc_pcm_runtime *rtd)
return 0; return 0;
} }
static unsigned int rates[] = { static const unsigned int rates[] = {
48000, 48000,
}; };
static struct snd_pcm_hw_constraint_list constraints_rates = { static const struct snd_pcm_hw_constraint_list constraints_rates = {
.count = ARRAY_SIZE(rates), .count = ARRAY_SIZE(rates),
.list = rates, .list = rates,
.mask = 0, .mask = 0,
}; };
static unsigned int channels[] = { static const unsigned int channels[] = {
DUAL_CHANNEL, DUAL_CHANNEL,
}; };
static struct snd_pcm_hw_constraint_list constraints_channels = { static const struct snd_pcm_hw_constraint_list constraints_channels = {
.count = ARRAY_SIZE(channels), .count = ARRAY_SIZE(channels),
.list = channels, .list = channels,
.mask = 0, .mask = 0,
}; };
static unsigned int channels_quad[] = { static const unsigned int channels_quad[] = {
QUAD_CHANNEL, QUAD_CHANNEL,
}; };
static struct snd_pcm_hw_constraint_list constraints_channels_quad = { static const struct snd_pcm_hw_constraint_list constraints_channels_quad = {
.count = ARRAY_SIZE(channels_quad), .count = ARRAY_SIZE(channels_quad),
.list = channels_quad, .list = channels_quad,
.mask = 0, .mask = 0,
......
...@@ -207,11 +207,11 @@ static const struct snd_soc_ops broxton_rt298_ops = { ...@@ -207,11 +207,11 @@ static const struct snd_soc_ops broxton_rt298_ops = {
.hw_params = broxton_rt298_hw_params, .hw_params = broxton_rt298_hw_params,
}; };
static unsigned int rates[] = { static const unsigned int rates[] = {
48000, 48000,
}; };
static struct snd_pcm_hw_constraint_list constraints_rates = { static const struct snd_pcm_hw_constraint_list constraints_rates = {
.count = ARRAY_SIZE(rates), .count = ARRAY_SIZE(rates),
.list = rates, .list = rates,
.mask = 0, .mask = 0,
...@@ -222,19 +222,16 @@ static int broxton_dmic_fixup(struct snd_soc_pcm_runtime *rtd, ...@@ -222,19 +222,16 @@ static int broxton_dmic_fixup(struct snd_soc_pcm_runtime *rtd,
{ {
struct snd_interval *channels = hw_param_interval(params, struct snd_interval *channels = hw_param_interval(params,
SNDRV_PCM_HW_PARAM_CHANNELS); SNDRV_PCM_HW_PARAM_CHANNELS);
if (params_channels(params) == 2) channels->min = channels->max = 4;
channels->min = channels->max = 2;
else
channels->min = channels->max = 4;
return 0; return 0;
} }
static unsigned int channels_dmic[] = { static const unsigned int channels_dmic[] = {
2, 4, 1, 2, 3, 4,
}; };
static struct snd_pcm_hw_constraint_list constraints_dmic_channels = { static const struct snd_pcm_hw_constraint_list constraints_dmic_channels = {
.count = ARRAY_SIZE(channels_dmic), .count = ARRAY_SIZE(channels_dmic),
.list = channels_dmic, .list = channels_dmic,
.mask = 0, .mask = 0,
...@@ -256,11 +253,11 @@ static const struct snd_soc_ops broxton_dmic_ops = { ...@@ -256,11 +253,11 @@ static const struct snd_soc_ops broxton_dmic_ops = {
.startup = broxton_dmic_startup, .startup = broxton_dmic_startup,
}; };
static unsigned int channels[] = { static const unsigned int channels[] = {
2, 2,
}; };
static struct snd_pcm_hw_constraint_list constraints_channels = { static const struct snd_pcm_hw_constraint_list constraints_channels = {
.count = ARRAY_SIZE(channels), .count = ARRAY_SIZE(channels),
.list = channels, .list = channels,
.mask = 0, .mask = 0,
......
...@@ -67,20 +67,27 @@ static struct snd_soc_jack_pin hs_jack_pins[] = { ...@@ -67,20 +67,27 @@ static struct snd_soc_jack_pin hs_jack_pins[] = {
static struct snd_soc_jack_gpio hs_jack_gpios[] = { static struct snd_soc_jack_gpio hs_jack_gpios[] = {
{ {
.name = "hp-gpio", .name = "hp",
.idx = 0,
.report = SND_JACK_HEADPHONE | SND_JACK_LINEOUT, .report = SND_JACK_HEADPHONE | SND_JACK_LINEOUT,
.debounce_time = 200, .debounce_time = 200,
}, },
{ {
.name = "mic-gpio", .name = "mic",
.idx = 1,
.invert = 1, .invert = 1,
.report = SND_JACK_MICROPHONE, .report = SND_JACK_MICROPHONE,
.debounce_time = 200, .debounce_time = 200,
}, },
}; };
static const struct acpi_gpio_params hp_gpios = { 0, 0, false };
static const struct acpi_gpio_params mic_gpios = { 1, 0, false };
static const struct acpi_gpio_mapping acpi_byt_max98090_gpios[] = {
{ "hp-gpios", &hp_gpios, 1 },
{ "mic-gpios", &mic_gpios, 1 },
{},
};
static int byt_max98090_init(struct snd_soc_pcm_runtime *runtime) static int byt_max98090_init(struct snd_soc_pcm_runtime *runtime)
{ {
int ret; int ret;
...@@ -140,8 +147,9 @@ static struct snd_soc_card byt_max98090_card = { ...@@ -140,8 +147,9 @@ static struct snd_soc_card byt_max98090_card = {
static int byt_max98090_probe(struct platform_device *pdev) static int byt_max98090_probe(struct platform_device *pdev)
{ {
int ret_val = 0; struct device *dev = &pdev->dev;
struct byt_max98090_private *priv; struct byt_max98090_private *priv;
int ret_val;
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_ATOMIC); priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_ATOMIC);
if (!priv) { if (!priv) {
...@@ -149,6 +157,10 @@ static int byt_max98090_probe(struct platform_device *pdev) ...@@ -149,6 +157,10 @@ static int byt_max98090_probe(struct platform_device *pdev)
return -ENOMEM; return -ENOMEM;
} }
ret_val = devm_acpi_dev_add_driver_gpios(dev->parent, acpi_byt_max98090_gpios);
if (ret_val)
dev_dbg(dev, "Unable to add GPIO mapping table\n");
byt_max98090_card.dev = &pdev->dev; byt_max98090_card.dev = &pdev->dev;
snd_soc_card_set_drvdata(&byt_max98090_card, priv); snd_soc_card_set_drvdata(&byt_max98090_card, priv);
ret_val = devm_snd_soc_register_card(&pdev->dev, &byt_max98090_card); ret_val = devm_snd_soc_register_card(&pdev->dev, &byt_max98090_card);
...@@ -158,7 +170,7 @@ static int byt_max98090_probe(struct platform_device *pdev) ...@@ -158,7 +170,7 @@ static int byt_max98090_probe(struct platform_device *pdev)
return ret_val; return ret_val;
} }
return ret_val; return 0;
} }
static int byt_max98090_remove(struct platform_device *pdev) static int byt_max98090_remove(struct platform_device *pdev)
......
/*
* bytcht_es8316.c - ASoc Machine driver for Intel Baytrail/Cherrytrail
* platforms with Everest ES8316 SoC
*
* Copyright (C) 2017 Endless Mobile, Inc.
* Authors: David Yang <yangxiaohua@everest-semi.com>,
* Daniel Drake <drake@endlessm.com>
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/device.h>
#include <linux/slab.h>
#include <asm/platform_sst_audio.h>
#include <linux/clk.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include "../atom/sst-atom-controls.h"
#include "../common/sst-acpi.h"
#include "../common/sst-dsp.h"
struct byt_cht_es8316_private {
struct clk *mclk;
};
#define CODEC_DAI1 "ES8316 HiFi"
static inline struct snd_soc_dai *get_codec_dai(struct snd_soc_card *card)
{
struct snd_soc_pcm_runtime *rtd;
list_for_each_entry(rtd, &card->rtd_list, list) {
if (!strncmp(rtd->codec_dai->name, CODEC_DAI1,
strlen(CODEC_DAI1)))
return rtd->codec_dai;
}
return NULL;
}
static const struct snd_soc_dapm_widget byt_cht_es8316_widgets[] = {
SND_SOC_DAPM_HP("Headphone", NULL),
/*
* The codec supports two analog microphone inputs. I have only
* tested MIC1. A DMIC route could also potentially be added
* if such functionality is found on another platform.
*/
SND_SOC_DAPM_MIC("Microphone 1", NULL),
SND_SOC_DAPM_MIC("Microphone 2", NULL),
};
static const struct snd_soc_dapm_route byt_cht_es8316_audio_map[] = {
{"MIC1", NULL, "Microphone 1"},
{"MIC2", NULL, "Microphone 2"},
{"Headphone", NULL, "HPOL"},
{"Headphone", NULL, "HPOR"},
{"Playback", NULL, "ssp2 Tx"},
{"ssp2 Tx", NULL, "codec_out0"},
{"ssp2 Tx", NULL, "codec_out1"},
{"codec_in0", NULL, "ssp2 Rx" },
{"codec_in1", NULL, "ssp2 Rx" },
{"ssp2 Rx", NULL, "Capture"},
};
static const struct snd_kcontrol_new byt_cht_es8316_controls[] = {
SOC_DAPM_PIN_SWITCH("Headphone"),
SOC_DAPM_PIN_SWITCH("Microphone 1"),
SOC_DAPM_PIN_SWITCH("Microphone 2"),
};
static int byt_cht_es8316_init(struct snd_soc_pcm_runtime *runtime)
{
struct snd_soc_card *card = runtime->card;
struct byt_cht_es8316_private *priv = snd_soc_card_get_drvdata(card);
int ret;
card->dapm.idle_bias_off = true;
/*
* The firmware might enable the clock at boot (this information
* may or may not be reflected in the enable clock register).
* To change the rate we must disable the clock first to cover these
* cases. Due to common clock framework restrictions that do not allow
* to disable a clock that has not been enabled, we need to enable
* the clock first.
*/
ret = clk_prepare_enable(priv->mclk);
if (!ret)
clk_disable_unprepare(priv->mclk);
ret = clk_set_rate(priv->mclk, 19200000);
if (ret)
dev_err(card->dev, "unable to set MCLK rate\n");
ret = clk_prepare_enable(priv->mclk);
if (ret)
dev_err(card->dev, "unable to enable MCLK\n");
ret = snd_soc_dai_set_sysclk(runtime->codec_dai, 0, 19200000,
SND_SOC_CLOCK_IN);
if (ret < 0) {
dev_err(card->dev, "can't set codec clock %d\n", ret);
return ret;
}
return 0;
}
static const struct snd_soc_pcm_stream byt_cht_es8316_dai_params = {
.formats = SNDRV_PCM_FMTBIT_S24_LE,
.rate_min = 48000,
.rate_max = 48000,
.channels_min = 2,
.channels_max = 2,
};
static int byt_cht_es8316_codec_fixup(struct snd_soc_pcm_runtime *rtd,
struct snd_pcm_hw_params *params)
{
struct snd_interval *rate = hw_param_interval(params,
SNDRV_PCM_HW_PARAM_RATE);
struct snd_interval *channels = hw_param_interval(params,
SNDRV_PCM_HW_PARAM_CHANNELS);
int ret;
/* The DSP will covert the FE rate to 48k, stereo */
rate->min = rate->max = 48000;
channels->min = channels->max = 2;
/* set SSP2 to 24-bit */
params_set_format(params, SNDRV_PCM_FORMAT_S24_LE);
/*
* Default mode for SSP configuration is TDM 4 slot, override config
* with explicit setting to I2S 2ch 24-bit. The word length is set with
* dai_set_tdm_slot() since there is no other API exposed
*/
ret = snd_soc_dai_set_fmt(rtd->cpu_dai,
SND_SOC_DAIFMT_I2S |
SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBS_CFS
);
if (ret < 0) {
dev_err(rtd->dev, "can't set format to I2S, err %d\n", ret);
return ret;
}
ret = snd_soc_dai_set_tdm_slot(rtd->cpu_dai, 0x3, 0x3, 2, 24);
if (ret < 0) {
dev_err(rtd->dev, "can't set I2S config, err %d\n", ret);
return ret;
}
return 0;
}
static int byt_cht_es8316_aif1_startup(struct snd_pcm_substream *substream)
{
return snd_pcm_hw_constraint_single(substream->runtime,
SNDRV_PCM_HW_PARAM_RATE, 48000);
}
static const struct snd_soc_ops byt_cht_es8316_aif1_ops = {
.startup = byt_cht_es8316_aif1_startup,
};
static struct snd_soc_dai_link byt_cht_es8316_dais[] = {
[MERR_DPCM_AUDIO] = {
.name = "Audio Port",
.stream_name = "Audio",
.cpu_dai_name = "media-cpu-dai",
.codec_dai_name = "snd-soc-dummy-dai",
.codec_name = "snd-soc-dummy",
.platform_name = "sst-mfld-platform",
.nonatomic = true,
.dynamic = 1,
.dpcm_playback = 1,
.dpcm_capture = 1,
.ops = &byt_cht_es8316_aif1_ops,
},
[MERR_DPCM_DEEP_BUFFER] = {
.name = "Deep-Buffer Audio Port",
.stream_name = "Deep-Buffer Audio",
.cpu_dai_name = "deepbuffer-cpu-dai",
.codec_dai_name = "snd-soc-dummy-dai",
.codec_name = "snd-soc-dummy",
.platform_name = "sst-mfld-platform",
.nonatomic = true,
.dynamic = 1,
.dpcm_playback = 1,
.ops = &byt_cht_es8316_aif1_ops,
},
[MERR_DPCM_COMPR] = {
.name = "Compressed Port",
.stream_name = "Compress",
.cpu_dai_name = "compress-cpu-dai",
.codec_dai_name = "snd-soc-dummy-dai",
.codec_name = "snd-soc-dummy",
.platform_name = "sst-mfld-platform",
},
/* back ends */
{
/* Only SSP2 has been tested here, so BYT-CR platforms that
* require SSP0 will not work.
*/
.name = "SSP2-Codec",
.id = 1,
.cpu_dai_name = "ssp2-port",
.platform_name = "sst-mfld-platform",
.no_pcm = 1,
.codec_dai_name = "ES8316 HiFi",
.codec_name = "i2c-ESSX8316:00",
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBS_CFS,
.be_hw_params_fixup = byt_cht_es8316_codec_fixup,
.nonatomic = true,
.dpcm_playback = 1,
.dpcm_capture = 1,
.init = byt_cht_es8316_init,
},
};
/* SoC card */
static struct snd_soc_card byt_cht_es8316_card = {
.name = "bytcht-es8316",
.owner = THIS_MODULE,
.dai_link = byt_cht_es8316_dais,
.num_links = ARRAY_SIZE(byt_cht_es8316_dais),
.dapm_widgets = byt_cht_es8316_widgets,
.num_dapm_widgets = ARRAY_SIZE(byt_cht_es8316_widgets),
.dapm_routes = byt_cht_es8316_audio_map,
.num_dapm_routes = ARRAY_SIZE(byt_cht_es8316_audio_map),
.controls = byt_cht_es8316_controls,
.num_controls = ARRAY_SIZE(byt_cht_es8316_controls),
.fully_routed = true,
};
static int snd_byt_cht_es8316_mc_probe(struct platform_device *pdev)
{
int ret = 0;
struct byt_cht_es8316_private *priv;
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_ATOMIC);
if (!priv)
return -ENOMEM;
/* register the soc card */
byt_cht_es8316_card.dev = &pdev->dev;
snd_soc_card_set_drvdata(&byt_cht_es8316_card, priv);
priv->mclk = devm_clk_get(&pdev->dev, "pmc_plt_clk_3");
if (IS_ERR(priv->mclk)) {
ret = PTR_ERR(priv->mclk);
dev_err(&pdev->dev,
"Failed to get MCLK from pmc_plt_clk_3: %d\n",
ret);
return ret;
}
ret = devm_snd_soc_register_card(&pdev->dev, &byt_cht_es8316_card);
if (ret) {
dev_err(&pdev->dev, "snd_soc_register_card failed %d\n", ret);
return ret;
}
platform_set_drvdata(pdev, &byt_cht_es8316_card);
return ret;
}
static struct platform_driver snd_byt_cht_es8316_mc_driver = {
.driver = {
.name = "bytcht_es8316",
},
.probe = snd_byt_cht_es8316_mc_probe,
};
module_platform_driver(snd_byt_cht_es8316_mc_driver);
MODULE_DESCRIPTION("ASoC Intel(R) Baytrail/Cherrytrail Machine driver");
MODULE_AUTHOR("David Yang <yangxiaohua@everest-semi.com>");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:bytcht_es8316");
...@@ -85,11 +85,11 @@ static int codec_fixup(struct snd_soc_pcm_runtime *rtd, ...@@ -85,11 +85,11 @@ static int codec_fixup(struct snd_soc_pcm_runtime *rtd,
return 0; return 0;
} }
static unsigned int rates_48000[] = { static const unsigned int rates_48000[] = {
48000, 48000,
}; };
static struct snd_pcm_hw_constraint_list constraints_48000 = { static const struct snd_pcm_hw_constraint_list constraints_48000 = {
.count = ARRAY_SIZE(rates_48000), .count = ARRAY_SIZE(rates_48000),
.list = rates_48000, .list = rates_48000,
}; };
......
...@@ -203,11 +203,11 @@ static int byt_rt5651_codec_fixup(struct snd_soc_pcm_runtime *rtd, ...@@ -203,11 +203,11 @@ static int byt_rt5651_codec_fixup(struct snd_soc_pcm_runtime *rtd,
return 0; return 0;
} }
static unsigned int rates_48000[] = { static const unsigned int rates_48000[] = {
48000, 48000,
}; };
static struct snd_pcm_hw_constraint_list constraints_48000 = { static const struct snd_pcm_hw_constraint_list constraints_48000 = {
.count = ARRAY_SIZE(rates_48000), .count = ARRAY_SIZE(rates_48000),
.list = rates_48000, .list = rates_48000,
}; };
......
...@@ -39,18 +39,6 @@ struct cht_mc_private { ...@@ -39,18 +39,6 @@ struct cht_mc_private {
bool ts3a227e_present; bool ts3a227e_present;
}; };
static inline struct snd_soc_dai *cht_get_codec_dai(struct snd_soc_card *card)
{
struct snd_soc_pcm_runtime *rtd;
list_for_each_entry(rtd, &card->rtd_list, list) {
if (!strncmp(rtd->codec_dai->name, CHT_CODEC_DAI,
strlen(CHT_CODEC_DAI)))
return rtd->codec_dai;
}
return NULL;
}
static const struct snd_soc_dapm_widget cht_dapm_widgets[] = { static const struct snd_soc_dapm_widget cht_dapm_widgets[] = {
SND_SOC_DAPM_HP("Headphone", NULL), SND_SOC_DAPM_HP("Headphone", NULL),
SND_SOC_DAPM_MIC("Headset Mic", NULL), SND_SOC_DAPM_MIC("Headset Mic", NULL),
......
...@@ -19,6 +19,8 @@ ...@@ -19,6 +19,8 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/clk.h>
#include <asm/cpu_device_id.h>
#include <sound/pcm.h> #include <sound/pcm.h>
#include <sound/pcm_params.h> #include <sound/pcm_params.h>
#include <sound/soc.h> #include <sound/soc.h>
...@@ -31,8 +33,11 @@ ...@@ -31,8 +33,11 @@
#define CHT_PLAT_CLK_3_HZ 19200000 #define CHT_PLAT_CLK_3_HZ 19200000
#define CHT_CODEC_DAI "rt5670-aif1" #define CHT_CODEC_DAI "rt5670-aif1"
static struct snd_soc_jack cht_bsw_headset; struct cht_mc_private {
static char cht_bsw_codec_name[16]; struct snd_soc_jack headset;
char codec_name[16];
struct clk *mclk;
};
/* Headset jack detection DAPM pins */ /* Headset jack detection DAPM pins */
static struct snd_soc_jack_pin cht_bsw_headset_pins[] = { static struct snd_soc_jack_pin cht_bsw_headset_pins[] = {
...@@ -64,6 +69,7 @@ static int platform_clock_control(struct snd_soc_dapm_widget *w, ...@@ -64,6 +69,7 @@ static int platform_clock_control(struct snd_soc_dapm_widget *w,
struct snd_soc_dapm_context *dapm = w->dapm; struct snd_soc_dapm_context *dapm = w->dapm;
struct snd_soc_card *card = dapm->card; struct snd_soc_card *card = dapm->card;
struct snd_soc_dai *codec_dai; struct snd_soc_dai *codec_dai;
struct cht_mc_private *ctx = snd_soc_card_get_drvdata(card);
int ret; int ret;
codec_dai = cht_get_codec_dai(card); codec_dai = cht_get_codec_dai(card);
...@@ -73,6 +79,15 @@ static int platform_clock_control(struct snd_soc_dapm_widget *w, ...@@ -73,6 +79,15 @@ static int platform_clock_control(struct snd_soc_dapm_widget *w,
} }
if (SND_SOC_DAPM_EVENT_ON(event)) { if (SND_SOC_DAPM_EVENT_ON(event)) {
if (ctx->mclk) {
ret = clk_prepare_enable(ctx->mclk);
if (ret < 0) {
dev_err(card->dev,
"could not configure MCLK state");
return ret;
}
}
/* set codec PLL source to the 19.2MHz platform clock (MCLK) */ /* set codec PLL source to the 19.2MHz platform clock (MCLK) */
ret = snd_soc_dai_set_pll(codec_dai, 0, RT5670_PLL1_S_MCLK, ret = snd_soc_dai_set_pll(codec_dai, 0, RT5670_PLL1_S_MCLK,
CHT_PLAT_CLK_3_HZ, 48000 * 512); CHT_PLAT_CLK_3_HZ, 48000 * 512);
...@@ -96,6 +111,9 @@ static int platform_clock_control(struct snd_soc_dapm_widget *w, ...@@ -96,6 +111,9 @@ static int platform_clock_control(struct snd_soc_dapm_widget *w,
*/ */
snd_soc_dai_set_sysclk(codec_dai, RT5670_SCLK_S_RCCLK, snd_soc_dai_set_sysclk(codec_dai, RT5670_SCLK_S_RCCLK,
48000 * 512, SND_SOC_CLOCK_IN); 48000 * 512, SND_SOC_CLOCK_IN);
if (ctx->mclk)
clk_disable_unprepare(ctx->mclk);
} }
return 0; return 0;
} }
...@@ -171,6 +189,7 @@ static int cht_codec_init(struct snd_soc_pcm_runtime *runtime) ...@@ -171,6 +189,7 @@ static int cht_codec_init(struct snd_soc_pcm_runtime *runtime)
int ret; int ret;
struct snd_soc_dai *codec_dai = runtime->codec_dai; struct snd_soc_dai *codec_dai = runtime->codec_dai;
struct snd_soc_codec *codec = codec_dai->codec; struct snd_soc_codec *codec = codec_dai->codec;
struct cht_mc_private *ctx = snd_soc_card_get_drvdata(runtime->card);
/* TDM 4 slots 24 bit, set Rx & Tx bitmask to 4 active slots */ /* TDM 4 slots 24 bit, set Rx & Tx bitmask to 4 active slots */
ret = snd_soc_dai_set_tdm_slot(codec_dai, 0xF, 0xF, 4, 24); ret = snd_soc_dai_set_tdm_slot(codec_dai, 0xF, 0xF, 4, 24);
...@@ -194,13 +213,37 @@ static int cht_codec_init(struct snd_soc_pcm_runtime *runtime) ...@@ -194,13 +213,37 @@ static int cht_codec_init(struct snd_soc_pcm_runtime *runtime)
RT5670_CLK_SEL_I2S1_ASRC); RT5670_CLK_SEL_I2S1_ASRC);
ret = snd_soc_card_jack_new(runtime->card, "Headset", ret = snd_soc_card_jack_new(runtime->card, "Headset",
SND_JACK_HEADSET | SND_JACK_BTN_0 | SND_JACK_HEADSET | SND_JACK_BTN_0 |
SND_JACK_BTN_1 | SND_JACK_BTN_2, &cht_bsw_headset, SND_JACK_BTN_1 | SND_JACK_BTN_2,
cht_bsw_headset_pins, ARRAY_SIZE(cht_bsw_headset_pins)); &ctx->headset,
cht_bsw_headset_pins,
ARRAY_SIZE(cht_bsw_headset_pins));
if (ret) if (ret)
return ret; return ret;
rt5670_set_jack_detect(codec, &cht_bsw_headset); rt5670_set_jack_detect(codec, &ctx->headset);
if (ctx->mclk) {
/*
* The firmware might enable the clock at
* boot (this information may or may not
* be reflected in the enable clock register).
* To change the rate we must disable the clock
* first to cover these cases. Due to common
* clock framework restrictions that do not allow
* to disable a clock that has not been enabled,
* we need to enable the clock first.
*/
ret = clk_prepare_enable(ctx->mclk);
if (!ret)
clk_disable_unprepare(ctx->mclk);
ret = clk_set_rate(ctx->mclk, CHT_PLAT_CLK_3_HZ);
if (ret) {
dev_err(runtime->dev, "unable to set MCLK rate\n");
return ret;
}
}
return 0; return 0;
} }
...@@ -341,34 +384,62 @@ static struct snd_soc_card snd_soc_card_cht = { ...@@ -341,34 +384,62 @@ static struct snd_soc_card snd_soc_card_cht = {
.resume_post = cht_resume_post, .resume_post = cht_resume_post,
}; };
static bool is_valleyview(void)
{
static const struct x86_cpu_id cpu_ids[] = {
{ X86_VENDOR_INTEL, 6, 55 }, /* Valleyview, Bay Trail */
{}
};
if (!x86_match_cpu(cpu_ids))
return false;
return true;
}
#define RT5672_I2C_DEFAULT "i2c-10EC5670:00" #define RT5672_I2C_DEFAULT "i2c-10EC5670:00"
static int snd_cht_mc_probe(struct platform_device *pdev) static int snd_cht_mc_probe(struct platform_device *pdev)
{ {
int ret_val = 0; int ret_val = 0;
struct cht_mc_private *drv;
struct sst_acpi_mach *mach = pdev->dev.platform_data; struct sst_acpi_mach *mach = pdev->dev.platform_data;
const char *i2c_name; const char *i2c_name;
int i; int i;
strcpy(cht_bsw_codec_name, RT5672_I2C_DEFAULT); drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_ATOMIC);
if (!drv)
return -ENOMEM;
strcpy(drv->codec_name, RT5672_I2C_DEFAULT);
/* fixup codec name based on HID */ /* fixup codec name based on HID */
if (mach) { if (mach) {
i2c_name = sst_acpi_find_name_from_hid(mach->id); i2c_name = sst_acpi_find_name_from_hid(mach->id);
if (i2c_name) { if (i2c_name) {
snprintf(cht_bsw_codec_name, sizeof(cht_bsw_codec_name), snprintf(drv->codec_name, sizeof(drv->codec_name),
"i2c-%s", i2c_name); "i2c-%s", i2c_name);
for (i = 0; i < ARRAY_SIZE(cht_dailink); i++) { for (i = 0; i < ARRAY_SIZE(cht_dailink); i++) {
if (!strcmp(cht_dailink[i].codec_name, if (!strcmp(cht_dailink[i].codec_name,
RT5672_I2C_DEFAULT)) { RT5672_I2C_DEFAULT)) {
cht_dailink[i].codec_name = cht_dailink[i].codec_name =
cht_bsw_codec_name; drv->codec_name;
break; break;
} }
} }
} }
} }
if (is_valleyview()) {
drv->mclk = devm_clk_get(&pdev->dev, "pmc_plt_clk_3");
if (IS_ERR(drv->mclk)) {
dev_err(&pdev->dev,
"Failed to get MCLK from pmc_plt_clk_3: %ld\n",
PTR_ERR(drv->mclk));
return PTR_ERR(drv->mclk);
}
}
snd_soc_card_set_drvdata(&snd_soc_card_cht, drv);
/* register the soc card */ /* register the soc card */
snd_soc_card_cht.dev = &pdev->dev; snd_soc_card_cht.dev = &pdev->dev;
ret_val = devm_snd_soc_register_card(&pdev->dev, &snd_soc_card_cht); ret_val = devm_snd_soc_register_card(&pdev->dev, &snd_soc_card_cht);
......
This diff is collapsed.
This diff is collapsed.
...@@ -266,21 +266,21 @@ static int skylake_nau8825_fe_init(struct snd_soc_pcm_runtime *rtd) ...@@ -266,21 +266,21 @@ static int skylake_nau8825_fe_init(struct snd_soc_pcm_runtime *rtd)
return 0; return 0;
} }
static unsigned int rates[] = { static const unsigned int rates[] = {
48000, 48000,
}; };
static struct snd_pcm_hw_constraint_list constraints_rates = { static const struct snd_pcm_hw_constraint_list constraints_rates = {
.count = ARRAY_SIZE(rates), .count = ARRAY_SIZE(rates),
.list = rates, .list = rates,
.mask = 0, .mask = 0,
}; };
static unsigned int channels[] = { static const unsigned int channels[] = {
2, 2,
}; };
static struct snd_pcm_hw_constraint_list constraints_channels = { static const struct snd_pcm_hw_constraint_list constraints_channels = {
.count = ARRAY_SIZE(channels), .count = ARRAY_SIZE(channels),
.list = channels, .list = channels,
.mask = 0, .mask = 0,
...@@ -348,11 +348,11 @@ static int skylake_dmic_fixup(struct snd_soc_pcm_runtime *rtd, ...@@ -348,11 +348,11 @@ static int skylake_dmic_fixup(struct snd_soc_pcm_runtime *rtd,
return 0; return 0;
} }
static unsigned int channels_dmic[] = { static const unsigned int channels_dmic[] = {
2, 4, 2, 4,
}; };
static struct snd_pcm_hw_constraint_list constraints_dmic_channels = { static const struct snd_pcm_hw_constraint_list constraints_dmic_channels = {
.count = ARRAY_SIZE(channels_dmic), .count = ARRAY_SIZE(channels_dmic),
.list = channels_dmic, .list = channels_dmic,
.mask = 0, .mask = 0,
...@@ -384,11 +384,11 @@ static const struct snd_soc_ops skylake_dmic_ops = { ...@@ -384,11 +384,11 @@ static const struct snd_soc_ops skylake_dmic_ops = {
.startup = skylake_dmic_startup, .startup = skylake_dmic_startup,
}; };
static unsigned int rates_16000[] = { static const unsigned int rates_16000[] = {
16000, 16000,
}; };
static struct snd_pcm_hw_constraint_list constraints_16000 = { static const struct snd_pcm_hw_constraint_list constraints_16000 = {
.count = ARRAY_SIZE(rates_16000), .count = ARRAY_SIZE(rates_16000),
.list = rates_16000, .list = rates_16000,
}; };
......
...@@ -297,21 +297,21 @@ static int skylake_nau8825_fe_init(struct snd_soc_pcm_runtime *rtd) ...@@ -297,21 +297,21 @@ static int skylake_nau8825_fe_init(struct snd_soc_pcm_runtime *rtd)
return 0; return 0;
} }
static unsigned int rates[] = { static const unsigned int rates[] = {
48000, 48000,
}; };
static struct snd_pcm_hw_constraint_list constraints_rates = { static const struct snd_pcm_hw_constraint_list constraints_rates = {
.count = ARRAY_SIZE(rates), .count = ARRAY_SIZE(rates),
.list = rates, .list = rates,
.mask = 0, .mask = 0,
}; };
static unsigned int channels[] = { static const unsigned int channels[] = {
2, 2,
}; };
static struct snd_pcm_hw_constraint_list constraints_channels = { static const struct snd_pcm_hw_constraint_list constraints_channels = {
.count = ARRAY_SIZE(channels), .count = ARRAY_SIZE(channels),
.list = channels, .list = channels,
.mask = 0, .mask = 0,
...@@ -397,11 +397,11 @@ static const struct snd_soc_ops skylake_nau8825_ops = { ...@@ -397,11 +397,11 @@ static const struct snd_soc_ops skylake_nau8825_ops = {
.hw_params = skylake_nau8825_hw_params, .hw_params = skylake_nau8825_hw_params,
}; };
static unsigned int channels_dmic[] = { static const unsigned int channels_dmic[] = {
2, 4, 2, 4,
}; };
static struct snd_pcm_hw_constraint_list constraints_dmic_channels = { static const struct snd_pcm_hw_constraint_list constraints_dmic_channels = {
.count = ARRAY_SIZE(channels_dmic), .count = ARRAY_SIZE(channels_dmic),
.list = channels_dmic, .list = channels_dmic,
.mask = 0, .mask = 0,
...@@ -433,11 +433,11 @@ static const struct snd_soc_ops skylake_dmic_ops = { ...@@ -433,11 +433,11 @@ static const struct snd_soc_ops skylake_dmic_ops = {
.startup = skylake_dmic_startup, .startup = skylake_dmic_startup,
}; };
static unsigned int rates_16000[] = { static const unsigned int rates_16000[] = {
16000, 16000,
}; };
static struct snd_pcm_hw_constraint_list constraints_16000 = { static const struct snd_pcm_hw_constraint_list constraints_16000 = {
.count = ARRAY_SIZE(rates_16000), .count = ARRAY_SIZE(rates_16000),
.list = rates_16000, .list = rates_16000,
}; };
......
...@@ -43,6 +43,7 @@ struct skl_rt286_private { ...@@ -43,6 +43,7 @@ struct skl_rt286_private {
enum { enum {
SKL_DPCM_AUDIO_PB = 0, SKL_DPCM_AUDIO_PB = 0,
SKL_DPCM_AUDIO_DB_PB,
SKL_DPCM_AUDIO_CP, SKL_DPCM_AUDIO_CP,
SKL_DPCM_AUDIO_REF_CP, SKL_DPCM_AUDIO_REF_CP,
SKL_DPCM_AUDIO_DMIC_CP, SKL_DPCM_AUDIO_DMIC_CP,
...@@ -165,21 +166,21 @@ static int skylake_hdmi_init(struct snd_soc_pcm_runtime *rtd) ...@@ -165,21 +166,21 @@ static int skylake_hdmi_init(struct snd_soc_pcm_runtime *rtd)
return 0; return 0;
} }
static unsigned int rates[] = { static const unsigned int rates[] = {
48000, 48000,
}; };
static struct snd_pcm_hw_constraint_list constraints_rates = { static const struct snd_pcm_hw_constraint_list constraints_rates = {
.count = ARRAY_SIZE(rates), .count = ARRAY_SIZE(rates),
.list = rates, .list = rates,
.mask = 0, .mask = 0,
}; };
static unsigned int channels[] = { static const unsigned int channels[] = {
2, 2,
}; };
static struct snd_pcm_hw_constraint_list constraints_channels = { static const struct snd_pcm_hw_constraint_list constraints_channels = {
.count = ARRAY_SIZE(channels), .count = ARRAY_SIZE(channels),
.list = channels, .list = channels,
.mask = 0, .mask = 0,
...@@ -264,11 +265,11 @@ static int skylake_dmic_fixup(struct snd_soc_pcm_runtime *rtd, ...@@ -264,11 +265,11 @@ static int skylake_dmic_fixup(struct snd_soc_pcm_runtime *rtd,
return 0; return 0;
} }
static unsigned int channels_dmic[] = { static const unsigned int channels_dmic[] = {
2, 4, 2, 4,
}; };
static struct snd_pcm_hw_constraint_list constraints_dmic_channels = { static const struct snd_pcm_hw_constraint_list constraints_dmic_channels = {
.count = ARRAY_SIZE(channels_dmic), .count = ARRAY_SIZE(channels_dmic),
.list = channels_dmic, .list = channels_dmic,
.mask = 0, .mask = 0,
...@@ -310,6 +311,23 @@ static struct snd_soc_dai_link skylake_rt286_dais[] = { ...@@ -310,6 +311,23 @@ static struct snd_soc_dai_link skylake_rt286_dais[] = {
.dpcm_playback = 1, .dpcm_playback = 1,
.ops = &skylake_rt286_fe_ops, .ops = &skylake_rt286_fe_ops,
}, },
[SKL_DPCM_AUDIO_DB_PB] = {
.name = "Skl Deepbuffer Port",
.stream_name = "Deep Buffer Audio",
.cpu_dai_name = "Deepbuffer Pin",
.platform_name = "0000:00:1f.3",
.nonatomic = 1,
.dynamic = 1,
.codec_name = "snd-soc-dummy",
.codec_dai_name = "snd-soc-dummy-dai",
.trigger = {
SND_SOC_DPCM_TRIGGER_POST,
SND_SOC_DPCM_TRIGGER_POST
},
.dpcm_playback = 1,
.ops = &skylake_rt286_fe_ops,
},
[SKL_DPCM_AUDIO_CP] = { [SKL_DPCM_AUDIO_CP] = {
.name = "Skl Audio Capture Port", .name = "Skl Audio Capture Port",
.stream_name = "Audio Record", .stream_name = "Audio Record",
......
...@@ -43,6 +43,9 @@ static inline bool sst_acpi_find_package_from_hid(const u8 hid[ACPI_ID_LEN], ...@@ -43,6 +43,9 @@ static inline bool sst_acpi_find_package_from_hid(const u8 hid[ACPI_ID_LEN],
/* acpi match */ /* acpi match */
struct sst_acpi_mach *sst_acpi_find_machine(struct sst_acpi_mach *machines); struct sst_acpi_mach *sst_acpi_find_machine(struct sst_acpi_mach *machines);
/* acpi check hid */
bool sst_acpi_check_hid(const u8 hid[ACPI_ID_LEN]);
/* Descriptor for SST ASoC machine driver */ /* Descriptor for SST ASoC machine driver */
struct sst_acpi_mach { struct sst_acpi_mach {
/* ACPI ID for the matching machine driver. Audio codec for instance */ /* ACPI ID for the matching machine driver. Audio codec for instance */
...@@ -55,5 +58,25 @@ struct sst_acpi_mach { ...@@ -55,5 +58,25 @@ struct sst_acpi_mach {
/* board name */ /* board name */
const char *board; const char *board;
struct sst_acpi_mach * (*machine_quirk)(void *arg); struct sst_acpi_mach * (*machine_quirk)(void *arg);
const void *quirk_data;
void *pdata; void *pdata;
}; };
#define SST_ACPI_MAX_CODECS 3
/**
* struct sst_codecs: Structure to hold secondary codec information apart from
* the matched one, this data will be passed to the quirk function to match
* with the ACPI detected devices
*
* @num_codecs: number of secondary codecs used in the platform
* @codecs: holds the codec IDs
*
*/
struct sst_codecs {
int num_codecs;
u8 codecs[SST_ACPI_MAX_CODECS][ACPI_ID_LEN];
};
/* check all codecs */
struct sst_acpi_mach *sst_acpi_codec_list(void *arg);
...@@ -77,6 +77,10 @@ struct sst_addr { ...@@ -77,6 +77,10 @@ struct sst_addr {
u32 dram_offset; u32 dram_offset;
u32 dsp_iram_offset; u32 dsp_iram_offset;
u32 dsp_dram_offset; u32 dsp_dram_offset;
u32 sram0_base;
u32 sram1_base;
u32 w0_stat_sz;
u32 w0_up_sz;
void __iomem *lpe; void __iomem *lpe;
void __iomem *shim; void __iomem *shim;
void __iomem *pci_cfg; void __iomem *pci_cfg;
......
...@@ -63,16 +63,33 @@ static acpi_status sst_acpi_mach_match(acpi_handle handle, u32 level, ...@@ -63,16 +63,33 @@ static acpi_status sst_acpi_mach_match(acpi_handle handle, u32 level,
return AE_OK; return AE_OK;
} }
bool sst_acpi_check_hid(const u8 hid[ACPI_ID_LEN])
{
acpi_status status;
bool found = false;
status = acpi_get_devices(hid, sst_acpi_mach_match, &found, NULL);
if (ACPI_FAILURE(status))
return false;
return found;
}
EXPORT_SYMBOL_GPL(sst_acpi_check_hid);
struct sst_acpi_mach *sst_acpi_find_machine(struct sst_acpi_mach *machines) struct sst_acpi_mach *sst_acpi_find_machine(struct sst_acpi_mach *machines)
{ {
struct sst_acpi_mach *mach; struct sst_acpi_mach *mach;
bool found = false;
for (mach = machines; mach->id[0]; mach++) for (mach = machines; mach->id[0]; mach++) {
if (ACPI_SUCCESS(acpi_get_devices(mach->id, if (sst_acpi_check_hid(mach->id) == true) {
sst_acpi_mach_match, if (mach->machine_quirk == NULL)
&found, NULL)) && found) return mach;
return mach;
if (mach->machine_quirk(mach) != NULL)
return mach;
}
}
return NULL; return NULL;
} }
EXPORT_SYMBOL_GPL(sst_acpi_find_machine); EXPORT_SYMBOL_GPL(sst_acpi_find_machine);
...@@ -134,5 +151,23 @@ bool sst_acpi_find_package_from_hid(const u8 hid[ACPI_ID_LEN], ...@@ -134,5 +151,23 @@ bool sst_acpi_find_package_from_hid(const u8 hid[ACPI_ID_LEN],
} }
EXPORT_SYMBOL_GPL(sst_acpi_find_package_from_hid); EXPORT_SYMBOL_GPL(sst_acpi_find_package_from_hid);
struct sst_acpi_mach *sst_acpi_codec_list(void *arg)
{
struct sst_acpi_mach *mach = arg;
struct sst_codecs *codec_list = (struct sst_codecs *) mach->quirk_data;
int i;
if (mach->quirk_data == NULL)
return mach;
for (i = 0; i < codec_list->num_codecs; i++) {
if (sst_acpi_check_hid(codec_list->codecs[i]) != true)
return NULL;
}
return mach;
}
EXPORT_SYMBOL_GPL(sst_acpi_codec_list);
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("Intel Common ACPI Match module"); MODULE_DESCRIPTION("Intel Common ACPI Match module");
snd-soc-skl-objs := skl.o skl-pcm.o skl-nhlt.o skl-messages.o \ snd-soc-skl-objs := skl.o skl-pcm.o skl-nhlt.o skl-messages.o \
skl-topology.o skl-topology.o
ifdef CONFIG_DEBUG_FS
snd-soc-skl-objs += skl-debug.o
endif
obj-$(CONFIG_SND_SOC_INTEL_SKYLAKE) += snd-soc-skl.o obj-$(CONFIG_SND_SOC_INTEL_SKYLAKE) += snd-soc-skl.o
# Skylake IPC Support # Skylake IPC Support
......
...@@ -573,6 +573,10 @@ int bxt_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, ...@@ -573,6 +573,10 @@ int bxt_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq,
sst->fw_ops = bxt_fw_ops; sst->fw_ops = bxt_fw_ops;
sst->addr.lpe = mmio_base; sst->addr.lpe = mmio_base;
sst->addr.shim = mmio_base; sst->addr.shim = mmio_base;
sst->addr.sram0_base = BXT_ADSP_SRAM0_BASE;
sst->addr.sram1_base = BXT_ADSP_SRAM1_BASE;
sst->addr.w0_stat_sz = SKL_ADSP_W0_STAT_SZ;
sst->addr.w0_up_sz = SKL_ADSP_W0_UP_SZ;
sst_dsp_mailbox_init(sst, (BXT_ADSP_SRAM0_BASE + SKL_ADSP_W0_STAT_SZ), sst_dsp_mailbox_init(sst, (BXT_ADSP_SRAM0_BASE + SKL_ADSP_W0_STAT_SZ),
SKL_ADSP_W0_UP_SZ, BXT_ADSP_SRAM1_BASE, SKL_ADSP_W1_SZ); SKL_ADSP_W0_UP_SZ, BXT_ADSP_SRAM1_BASE, SKL_ADSP_W1_SZ);
......
/*
* skl-debug.c - Debugfs for skl driver
*
* Copyright (C) 2016-17 Intel Corp
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*/
#include <linux/pci.h>
#include <linux/debugfs.h>
#include "skl.h"
#include "skl-sst-dsp.h"
#include "skl-sst-ipc.h"
#include "skl-tplg-interface.h"
#include "skl-topology.h"
#include "../common/sst-dsp.h"
#include "../common/sst-dsp-priv.h"
#define MOD_BUF PAGE_SIZE
#define FW_REG_BUF PAGE_SIZE
#define FW_REG_SIZE 0x60
struct skl_debug {
struct skl *skl;
struct device *dev;
struct dentry *fs;
struct dentry *modules;
u8 fw_read_buff[FW_REG_BUF];
};
static ssize_t skl_print_pins(struct skl_module_pin *m_pin, char *buf,
int max_pin, ssize_t size, bool direction)
{
int i;
ssize_t ret = 0;
for (i = 0; i < max_pin; i++)
ret += snprintf(buf + size, MOD_BUF - size,
"%s %d\n\tModule %d\n\tInstance %d\n\t"
"In-used %s\n\tType %s\n"
"\tState %d\n\tIndex %d\n",
direction ? "Input Pin:" : "Output Pin:",
i, m_pin[i].id.module_id,
m_pin[i].id.instance_id,
m_pin[i].in_use ? "Used" : "Unused",
m_pin[i].is_dynamic ? "Dynamic" : "Static",
m_pin[i].pin_state, i);
return ret;
}
static ssize_t skl_print_fmt(struct skl_module_fmt *fmt, char *buf,
ssize_t size, bool direction)
{
return snprintf(buf + size, MOD_BUF - size,
"%s\n\tCh %d\n\tFreq %d\n\tBit depth %d\n\t"
"Valid bit depth %d\n\tCh config %#x\n\tInterleaving %d\n\t"
"Sample Type %d\n\tCh Map %#x\n",
direction ? "Input Format:" : "Output Format:",
fmt->channels, fmt->s_freq, fmt->bit_depth,
fmt->valid_bit_depth, fmt->ch_cfg,
fmt->interleaving_style, fmt->sample_type,
fmt->ch_map);
}
static ssize_t module_read(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
struct skl_module_cfg *mconfig = file->private_data;
char *buf;
ssize_t ret;
buf = kzalloc(MOD_BUF, GFP_KERNEL);
if (!buf)
return -ENOMEM;
ret = snprintf(buf, MOD_BUF, "Module:\n\tUUID %pUL\n\tModule id %d\n"
"\tInstance id %d\n\tPvt_id %d\n", mconfig->guid,
mconfig->id.module_id, mconfig->id.instance_id,
mconfig->id.pvt_id);
ret += snprintf(buf + ret, MOD_BUF - ret,
"Resources:\n\tMCPS %#x\n\tIBS %#x\n\tOBS %#x\t\n",
mconfig->mcps, mconfig->ibs, mconfig->obs);
ret += snprintf(buf + ret, MOD_BUF - ret,
"Module data:\n\tCore %d\n\tIn queue %d\n\t"
"Out queue %d\n\tType %s\n",
mconfig->core_id, mconfig->max_in_queue,
mconfig->max_out_queue,
mconfig->is_loadable ? "loadable" : "inbuilt");
ret += skl_print_fmt(mconfig->in_fmt, buf, ret, true);
ret += skl_print_fmt(mconfig->out_fmt, buf, ret, false);
ret += snprintf(buf + ret, MOD_BUF - ret,
"Fixup:\n\tParams %#x\n\tConverter %#x\n",
mconfig->params_fixup, mconfig->converter);
ret += snprintf(buf + ret, MOD_BUF - ret,
"Module Gateway:\n\tType %#x\n\tVbus %#x\n\tHW conn %#x\n\tSlot %#x\n",
mconfig->dev_type, mconfig->vbus_id,
mconfig->hw_conn_type, mconfig->time_slot);
ret += snprintf(buf + ret, MOD_BUF - ret,
"Pipeline:\n\tID %d\n\tPriority %d\n\tConn Type %d\n\t"
"Pages %#x\n", mconfig->pipe->ppl_id,
mconfig->pipe->pipe_priority, mconfig->pipe->conn_type,
mconfig->pipe->memory_pages);
ret += snprintf(buf + ret, MOD_BUF - ret,
"\tParams:\n\t\tHost DMA %d\n\t\tLink DMA %d\n",
mconfig->pipe->p_params->host_dma_id,
mconfig->pipe->p_params->link_dma_id);
ret += snprintf(buf + ret, MOD_BUF - ret,
"\tPCM params:\n\t\tCh %d\n\t\tFreq %d\n\t\tFormat %d\n",
mconfig->pipe->p_params->ch,
mconfig->pipe->p_params->s_freq,
mconfig->pipe->p_params->s_fmt);
ret += snprintf(buf + ret, MOD_BUF - ret,
"\tLink %#x\n\tStream %#x\n",
mconfig->pipe->p_params->linktype,
mconfig->pipe->p_params->stream);
ret += snprintf(buf + ret, MOD_BUF - ret,
"\tState %d\n\tPassthru %s\n",
mconfig->pipe->state,
mconfig->pipe->passthru ? "true" : "false");
ret += skl_print_pins(mconfig->m_in_pin, buf,
mconfig->max_in_queue, ret, true);
ret += skl_print_pins(mconfig->m_out_pin, buf,
mconfig->max_out_queue, ret, false);
ret += snprintf(buf + ret, MOD_BUF - ret,
"Other:\n\tDomain %d\n\tHomogenous Input %s\n\t"
"Homogenous Output %s\n\tIn Queue Mask %d\n\t"
"Out Queue Mask %d\n\tDMA ID %d\n\tMem Pages %d\n\t"
"Module Type %d\n\tModule State %d\n",
mconfig->domain,
mconfig->homogenous_inputs ? "true" : "false",
mconfig->homogenous_outputs ? "true" : "false",
mconfig->in_queue_mask, mconfig->out_queue_mask,
mconfig->dma_id, mconfig->mem_pages, mconfig->m_state,
mconfig->m_type);
ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret);
kfree(buf);
return ret;
}
static const struct file_operations mcfg_fops = {
.open = simple_open,
.read = module_read,
.llseek = default_llseek,
};
void skl_debug_init_module(struct skl_debug *d,
struct snd_soc_dapm_widget *w,
struct skl_module_cfg *mconfig)
{
if (!debugfs_create_file(w->name, 0444,
d->modules, mconfig,
&mcfg_fops))
dev_err(d->dev, "%s: module debugfs init failed\n", w->name);
}
static ssize_t fw_softreg_read(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
struct skl_debug *d = file->private_data;
struct sst_dsp *sst = d->skl->skl_sst->dsp;
size_t w0_stat_sz = sst->addr.w0_stat_sz;
void __iomem *in_base = sst->mailbox.in_base;
void __iomem *fw_reg_addr;
unsigned int offset;
char *tmp;
ssize_t ret = 0;
tmp = kzalloc(FW_REG_BUF, GFP_KERNEL);
if (!tmp)
return -ENOMEM;
fw_reg_addr = in_base - w0_stat_sz;
memset(d->fw_read_buff, 0, FW_REG_BUF);
if (w0_stat_sz > 0)
__iowrite32_copy(d->fw_read_buff, fw_reg_addr, w0_stat_sz >> 2);
for (offset = 0; offset < FW_REG_SIZE; offset += 16) {
ret += snprintf(tmp + ret, FW_REG_BUF - ret, "%#.4x: ", offset);
hex_dump_to_buffer(d->fw_read_buff + offset, 16, 16, 4,
tmp + ret, FW_REG_BUF - ret, 0);
ret += strlen(tmp + ret);
/* print newline for each offset */
if (FW_REG_BUF - ret > 0)
tmp[ret++] = '\n';
}
ret = simple_read_from_buffer(user_buf, count, ppos, tmp, ret);
kfree(tmp);
return ret;
}
static const struct file_operations soft_regs_ctrl_fops = {
.open = simple_open,
.read = fw_softreg_read,
.llseek = default_llseek,
};
struct skl_debug *skl_debugfs_init(struct skl *skl)
{
struct skl_debug *d;
d = devm_kzalloc(&skl->pci->dev, sizeof(*d), GFP_KERNEL);
if (!d)
return NULL;
/* create the debugfs dir with platform component's debugfs as parent */
d->fs = debugfs_create_dir("dsp",
skl->platform->component.debugfs_root);
if (IS_ERR(d->fs) || !d->fs) {
dev_err(&skl->pci->dev, "debugfs root creation failed\n");
return NULL;
}
d->skl = skl;
d->dev = &skl->pci->dev;
/* now create the module dir */
d->modules = debugfs_create_dir("modules", d->fs);
if (IS_ERR(d->modules) || !d->modules) {
dev_err(&skl->pci->dev, "modules debugfs create failed\n");
goto err;
}
if (!debugfs_create_file("fw_soft_regs_rd", 0444, d->fs, d,
&soft_regs_ctrl_fops)) {
dev_err(d->dev, "fw soft regs control debugfs init failed\n");
goto err;
}
return d;
err:
debugfs_remove_recursive(d->fs);
return NULL;
}
...@@ -507,6 +507,8 @@ static void skl_setup_cpr_gateway_cfg(struct skl_sst *ctx, ...@@ -507,6 +507,8 @@ static void skl_setup_cpr_gateway_cfg(struct skl_sst *ctx,
struct skl_module_cfg *mconfig, struct skl_module_cfg *mconfig,
struct skl_cpr_cfg *cpr_mconfig) struct skl_cpr_cfg *cpr_mconfig)
{ {
u32 dma_io_buf;
cpr_mconfig->gtw_cfg.node_id = skl_get_node_id(ctx, mconfig); cpr_mconfig->gtw_cfg.node_id = skl_get_node_id(ctx, mconfig);
if (cpr_mconfig->gtw_cfg.node_id == SKL_NON_GATEWAY_CPR_NODE_ID) { if (cpr_mconfig->gtw_cfg.node_id == SKL_NON_GATEWAY_CPR_NODE_ID) {
...@@ -514,10 +516,29 @@ static void skl_setup_cpr_gateway_cfg(struct skl_sst *ctx, ...@@ -514,10 +516,29 @@ static void skl_setup_cpr_gateway_cfg(struct skl_sst *ctx,
return; return;
} }
if (SKL_CONN_SOURCE == mconfig->hw_conn_type) switch (mconfig->hw_conn_type) {
cpr_mconfig->gtw_cfg.dma_buffer_size = 2 * mconfig->obs; case SKL_CONN_SOURCE:
else if (mconfig->dev_type == SKL_DEVICE_HDAHOST)
cpr_mconfig->gtw_cfg.dma_buffer_size = 2 * mconfig->ibs; dma_io_buf = mconfig->ibs;
else
dma_io_buf = mconfig->obs;
break;
case SKL_CONN_SINK:
if (mconfig->dev_type == SKL_DEVICE_HDAHOST)
dma_io_buf = mconfig->obs;
else
dma_io_buf = mconfig->ibs;
break;
default:
dev_warn(ctx->dev, "wrong connection type: %d\n",
mconfig->hw_conn_type);
return;
}
cpr_mconfig->gtw_cfg.dma_buffer_size =
mconfig->dma_buffer_size * dma_io_buf;
cpr_mconfig->cpr_feature_mask = 0; cpr_mconfig->cpr_feature_mask = 0;
cpr_mconfig->gtw_cfg.config_length = 0; cpr_mconfig->gtw_cfg.config_length = 0;
...@@ -707,6 +728,7 @@ static u16 skl_get_module_param_size(struct skl_sst *ctx, ...@@ -707,6 +728,7 @@ static u16 skl_get_module_param_size(struct skl_sst *ctx,
return param_size; return param_size;
case SKL_MODULE_TYPE_BASE_OUTFMT: case SKL_MODULE_TYPE_BASE_OUTFMT:
case SKL_MODULE_TYPE_MIC_SELECT:
case SKL_MODULE_TYPE_KPB: case SKL_MODULE_TYPE_KPB:
return sizeof(struct skl_base_outfmt_cfg); return sizeof(struct skl_base_outfmt_cfg);
...@@ -761,6 +783,7 @@ static int skl_set_module_format(struct skl_sst *ctx, ...@@ -761,6 +783,7 @@ static int skl_set_module_format(struct skl_sst *ctx,
break; break;
case SKL_MODULE_TYPE_BASE_OUTFMT: case SKL_MODULE_TYPE_BASE_OUTFMT:
case SKL_MODULE_TYPE_MIC_SELECT:
case SKL_MODULE_TYPE_KPB: case SKL_MODULE_TYPE_KPB:
skl_set_base_outfmt_format(ctx, module_config, *param_data); skl_set_base_outfmt_format(ctx, module_config, *param_data);
break; break;
......
...@@ -1249,12 +1249,16 @@ static int skl_platform_soc_probe(struct snd_soc_platform *platform) ...@@ -1249,12 +1249,16 @@ static int skl_platform_soc_probe(struct snd_soc_platform *platform)
pm_runtime_get_sync(platform->dev); pm_runtime_get_sync(platform->dev);
if ((ebus_to_hbus(ebus))->ppcap) { if ((ebus_to_hbus(ebus))->ppcap) {
skl->platform = platform;
/* init debugfs */
skl->debugfs = skl_debugfs_init(skl);
ret = skl_tplg_init(platform, ebus); ret = skl_tplg_init(platform, ebus);
if (ret < 0) { if (ret < 0) {
dev_err(platform->dev, "Failed to init topology!\n"); dev_err(platform->dev, "Failed to init topology!\n");
return ret; return ret;
} }
skl->platform = platform;
/* load the firmwares, since all is set */ /* load the firmwares, since all is set */
ops = skl_get_dsp_ops(skl->pci->device); 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, ...@@ -553,6 +553,11 @@ int skl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq,
sst = skl->dsp; sst = skl->dsp;
sst->addr.lpe = mmio_base; sst->addr.lpe = mmio_base;
sst->addr.shim = mmio_base; sst->addr.shim = mmio_base;
sst->addr.sram0_base = SKL_ADSP_SRAM0_BASE;
sst->addr.sram1_base = SKL_ADSP_SRAM1_BASE;
sst->addr.w0_stat_sz = SKL_ADSP_W0_STAT_SZ;
sst->addr.w0_up_sz = SKL_ADSP_W0_UP_SZ;
sst_dsp_mailbox_init(sst, (SKL_ADSP_SRAM0_BASE + SKL_ADSP_W0_STAT_SZ), sst_dsp_mailbox_init(sst, (SKL_ADSP_SRAM0_BASE + SKL_ADSP_W0_STAT_SZ),
SKL_ADSP_W0_UP_SZ, SKL_ADSP_SRAM1_BASE, SKL_ADSP_W1_SZ); SKL_ADSP_W0_UP_SZ, SKL_ADSP_SRAM1_BASE, SKL_ADSP_W1_SZ);
......
...@@ -36,6 +36,19 @@ ...@@ -36,6 +36,19 @@
#define SKL_IN_DIR_BIT_MASK BIT(0) #define SKL_IN_DIR_BIT_MASK BIT(0)
#define SKL_PIN_COUNT_MASK GENMASK(7, 4) #define SKL_PIN_COUNT_MASK GENMASK(7, 4)
static const int mic_mono_list[] = {
0, 1, 2, 3,
};
static const int mic_stereo_list[][SKL_CH_STEREO] = {
{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3},
};
static const int mic_trio_list[][SKL_CH_TRIO] = {
{0, 1, 2}, {0, 1, 3}, {0, 2, 3}, {1, 2, 3},
};
static const int mic_quatro_list[][SKL_CH_QUATRO] = {
{0, 1, 2, 3},
};
void skl_tplg_d0i3_get(struct skl *skl, enum d0i3_capability caps) void skl_tplg_d0i3_get(struct skl *skl, enum d0i3_capability caps)
{ {
struct skl_d0i3_data *d0i3 = &skl->skl_sst->d0i3; struct skl_d0i3_data *d0i3 = &skl->skl_sst->d0i3;
...@@ -1314,6 +1327,111 @@ static int skl_tplg_tlv_control_set(struct snd_kcontrol *kcontrol, ...@@ -1314,6 +1327,111 @@ static int skl_tplg_tlv_control_set(struct snd_kcontrol *kcontrol,
return 0; return 0;
} }
static int skl_tplg_mic_control_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_dapm_widget *w = snd_soc_dapm_kcontrol_widget(kcontrol);
struct skl_module_cfg *mconfig = w->priv;
struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value;
u32 ch_type = *((u32 *)ec->dobj.private);
if (mconfig->dmic_ch_type == ch_type)
ucontrol->value.enumerated.item[0] =
mconfig->dmic_ch_combo_index;
else
ucontrol->value.enumerated.item[0] = 0;
return 0;
}
static int skl_fill_mic_sel_params(struct skl_module_cfg *mconfig,
struct skl_mic_sel_config *mic_cfg, struct device *dev)
{
struct skl_specific_cfg *sp_cfg = &mconfig->formats_config;
sp_cfg->caps_size = sizeof(struct skl_mic_sel_config);
sp_cfg->set_params = SKL_PARAM_SET;
sp_cfg->param_id = 0x00;
if (!sp_cfg->caps) {
sp_cfg->caps = devm_kzalloc(dev, sp_cfg->caps_size, GFP_KERNEL);
if (!sp_cfg->caps)
return -ENOMEM;
}
mic_cfg->mic_switch = SKL_MIC_SEL_SWITCH;
mic_cfg->flags = 0;
memcpy(sp_cfg->caps, mic_cfg, sp_cfg->caps_size);
return 0;
}
static int skl_tplg_mic_control_set(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_dapm_widget *w = snd_soc_dapm_kcontrol_widget(kcontrol);
struct skl_module_cfg *mconfig = w->priv;
struct skl_mic_sel_config mic_cfg = {0};
struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value;
u32 ch_type = *((u32 *)ec->dobj.private);
const int *list;
u8 in_ch, out_ch, index;
mconfig->dmic_ch_type = ch_type;
mconfig->dmic_ch_combo_index = ucontrol->value.enumerated.item[0];
/* enum control index 0 is INVALID, so no channels to be set */
if (mconfig->dmic_ch_combo_index == 0)
return 0;
/* No valid channel selection map for index 0, so offset by 1 */
index = mconfig->dmic_ch_combo_index - 1;
switch (ch_type) {
case SKL_CH_MONO:
if (mconfig->dmic_ch_combo_index > ARRAY_SIZE(mic_mono_list))
return -EINVAL;
list = &mic_mono_list[index];
break;
case SKL_CH_STEREO:
if (mconfig->dmic_ch_combo_index > ARRAY_SIZE(mic_stereo_list))
return -EINVAL;
list = mic_stereo_list[index];
break;
case SKL_CH_TRIO:
if (mconfig->dmic_ch_combo_index > ARRAY_SIZE(mic_trio_list))
return -EINVAL;
list = mic_trio_list[index];
break;
case SKL_CH_QUATRO:
if (mconfig->dmic_ch_combo_index > ARRAY_SIZE(mic_quatro_list))
return -EINVAL;
list = mic_quatro_list[index];
break;
default:
dev_err(w->dapm->dev,
"Invalid channel %d for mic_select module\n",
ch_type);
return -EINVAL;
}
/* channel type enum map to number of chanels for that type */
for (out_ch = 0; out_ch < ch_type; out_ch++) {
in_ch = list[out_ch];
mic_cfg.blob[out_ch][in_ch] = SKL_DEFAULT_MIC_SEL_GAIN;
}
return skl_fill_mic_sel_params(mconfig, &mic_cfg, w->dapm->dev);
}
/* /*
* Fill the dma id for host and link. In case of passthrough * Fill the dma id for host and link. In case of passthrough
* pipeline, this will both host and link in the same * pipeline, this will both host and link in the same
...@@ -1666,6 +1784,14 @@ static const struct snd_soc_tplg_bytes_ext_ops skl_tlv_ops[] = { ...@@ -1666,6 +1784,14 @@ static const struct snd_soc_tplg_bytes_ext_ops skl_tlv_ops[] = {
skl_tplg_tlv_control_set}, skl_tplg_tlv_control_set},
}; };
static const struct snd_soc_tplg_kcontrol_ops skl_tplg_kcontrol_ops[] = {
{
.id = SKL_CONTROL_TYPE_MIC_SELECT,
.get = skl_tplg_mic_control_get,
.put = skl_tplg_mic_control_set,
},
};
static int skl_tplg_fill_pipe_tkn(struct device *dev, static int skl_tplg_fill_pipe_tkn(struct device *dev,
struct skl_pipe *pipe, u32 tkn, struct skl_pipe *pipe, u32 tkn,
u32 tkn_val) u32 tkn_val)
...@@ -1995,7 +2121,7 @@ static int skl_tplg_get_token(struct device *dev, ...@@ -1995,7 +2121,7 @@ static int skl_tplg_get_token(struct device *dev,
mconfig->converter = tkn_elem->value; mconfig->converter = tkn_elem->value;
break; break;
case SKL_TKL_U32_D0I3_CAPS: case SKL_TKN_U32_D0I3_CAPS:
mconfig->d0i3_caps = tkn_elem->value; mconfig->d0i3_caps = tkn_elem->value;
break; break;
...@@ -2070,12 +2196,26 @@ static int skl_tplg_get_token(struct device *dev, ...@@ -2070,12 +2196,26 @@ static int skl_tplg_get_token(struct device *dev,
break; break;
case SKL_TKN_U32_CAPS_SET_PARAMS:
mconfig->formats_config.set_params =
tkn_elem->value;
break;
case SKL_TKN_U32_CAPS_PARAMS_ID:
mconfig->formats_config.param_id =
tkn_elem->value;
break;
case SKL_TKN_U32_PROC_DOMAIN: case SKL_TKN_U32_PROC_DOMAIN:
mconfig->domain = mconfig->domain =
tkn_elem->value; tkn_elem->value;
break; break;
case SKL_TKN_U32_DMA_BUF_SIZE:
mconfig->dma_buffer_size = tkn_elem->value;
break;
case SKL_TKN_U8_IN_PIN_TYPE: case SKL_TKN_U8_IN_PIN_TYPE:
case SKL_TKN_U8_OUT_PIN_TYPE: case SKL_TKN_U8_OUT_PIN_TYPE:
case SKL_TKN_U8_CONN_TYPE: case SKL_TKN_U8_CONN_TYPE:
...@@ -2147,7 +2287,7 @@ static int skl_tplg_get_tokens(struct device *dev, ...@@ -2147,7 +2287,7 @@ static int skl_tplg_get_tokens(struct device *dev,
tuple_size += tkn_count * sizeof(*tkn_elem); tuple_size += tkn_count * sizeof(*tkn_elem);
} }
return 0; return off;
} }
/* /*
...@@ -2198,10 +2338,11 @@ static int skl_tplg_get_pvt_data(struct snd_soc_tplg_dapm_widget *tplg_w, ...@@ -2198,10 +2338,11 @@ static int skl_tplg_get_pvt_data(struct snd_soc_tplg_dapm_widget *tplg_w,
num_blocks = ret; num_blocks = ret;
off += array->size; off += array->size;
array = (struct snd_soc_tplg_vendor_array *)(tplg_w->priv.data + off);
/* Read the BLOCK_TYPE and BLOCK_SIZE descriptor */ /* Read the BLOCK_TYPE and BLOCK_SIZE descriptor */
while (num_blocks > 0) { while (num_blocks > 0) {
array = (struct snd_soc_tplg_vendor_array *)
(tplg_w->priv.data + off);
ret = skl_tplg_get_desc_blocks(dev, array); ret = skl_tplg_get_desc_blocks(dev, array);
if (ret < 0) if (ret < 0)
...@@ -2237,7 +2378,9 @@ static int skl_tplg_get_pvt_data(struct snd_soc_tplg_dapm_widget *tplg_w, ...@@ -2237,7 +2378,9 @@ static int skl_tplg_get_pvt_data(struct snd_soc_tplg_dapm_widget *tplg_w,
memcpy(mconfig->formats_config.caps, data, memcpy(mconfig->formats_config.caps, data,
mconfig->formats_config.caps_size); mconfig->formats_config.caps_size);
--num_blocks; --num_blocks;
ret = mconfig->formats_config.caps_size;
} }
off += ret;
} }
return 0; return 0;
...@@ -2329,6 +2472,9 @@ static int skl_tplg_widget_load(struct snd_soc_component *cmpnt, ...@@ -2329,6 +2472,9 @@ static int skl_tplg_widget_load(struct snd_soc_component *cmpnt,
ret = skl_tplg_get_pvt_data(tplg_w, skl, bus->dev, mconfig); ret = skl_tplg_get_pvt_data(tplg_w, skl, bus->dev, mconfig);
if (ret < 0) if (ret < 0)
return ret; return ret;
skl_debug_init_module(skl->debugfs, w, mconfig);
bind_event: bind_event:
if (tplg_w->event_type == 0) { if (tplg_w->event_type == 0) {
dev_dbg(bus->dev, "ASoC: No event handler required\n"); dev_dbg(bus->dev, "ASoC: No event handler required\n");
...@@ -2377,14 +2523,34 @@ static int skl_init_algo_data(struct device *dev, struct soc_bytes_ext *be, ...@@ -2377,14 +2523,34 @@ static int skl_init_algo_data(struct device *dev, struct soc_bytes_ext *be,
return 0; return 0;
} }
static int skl_init_enum_data(struct device *dev, struct soc_enum *se,
struct snd_soc_tplg_enum_control *ec)
{
void *data;
if (ec->priv.size) {
data = devm_kzalloc(dev, sizeof(ec->priv.size), GFP_KERNEL);
if (!data)
return -ENOMEM;
memcpy(data, ec->priv.data, ec->priv.size);
se->dobj.private = data;
}
return 0;
}
static int skl_tplg_control_load(struct snd_soc_component *cmpnt, static int skl_tplg_control_load(struct snd_soc_component *cmpnt,
struct snd_kcontrol_new *kctl, struct snd_kcontrol_new *kctl,
struct snd_soc_tplg_ctl_hdr *hdr) struct snd_soc_tplg_ctl_hdr *hdr)
{ {
struct soc_bytes_ext *sb; struct soc_bytes_ext *sb;
struct snd_soc_tplg_bytes_control *tplg_bc; struct snd_soc_tplg_bytes_control *tplg_bc;
struct snd_soc_tplg_enum_control *tplg_ec;
struct hdac_ext_bus *ebus = snd_soc_component_get_drvdata(cmpnt); struct hdac_ext_bus *ebus = snd_soc_component_get_drvdata(cmpnt);
struct hdac_bus *bus = ebus_to_hbus(ebus); struct hdac_bus *bus = ebus_to_hbus(ebus);
struct soc_enum *se;
switch (hdr->ops.info) { switch (hdr->ops.info) {
case SND_SOC_TPLG_CTL_BYTES: case SND_SOC_TPLG_CTL_BYTES:
...@@ -2398,6 +2564,17 @@ static int skl_tplg_control_load(struct snd_soc_component *cmpnt, ...@@ -2398,6 +2564,17 @@ static int skl_tplg_control_load(struct snd_soc_component *cmpnt,
} }
break; break;
case SND_SOC_TPLG_CTL_ENUM:
tplg_ec = container_of(hdr,
struct snd_soc_tplg_enum_control, hdr);
if (kctl->access & SNDRV_CTL_ELEM_ACCESS_READWRITE) {
se = (struct soc_enum *)kctl->private_value;
if (tplg_ec->priv.size)
return skl_init_enum_data(bus->dev, se,
tplg_ec);
}
break;
default: default:
dev_warn(bus->dev, "Control load not supported %d:%d:%d\n", dev_warn(bus->dev, "Control load not supported %d:%d:%d\n",
hdr->ops.get, hdr->ops.put, hdr->ops.info); hdr->ops.get, hdr->ops.put, hdr->ops.info);
...@@ -2626,6 +2803,8 @@ static struct snd_soc_tplg_ops skl_tplg_ops = { ...@@ -2626,6 +2803,8 @@ static struct snd_soc_tplg_ops skl_tplg_ops = {
.control_load = skl_tplg_control_load, .control_load = skl_tplg_control_load,
.bytes_ext_ops = skl_tlv_ops, .bytes_ext_ops = skl_tlv_ops,
.bytes_ext_ops_count = ARRAY_SIZE(skl_tlv_ops), .bytes_ext_ops_count = ARRAY_SIZE(skl_tlv_ops),
.io_ops = skl_tplg_kcontrol_ops,
.io_ops_count = ARRAY_SIZE(skl_tplg_kcontrol_ops),
.manifest = skl_manifest_load, .manifest = skl_manifest_load,
}; };
......
...@@ -39,6 +39,11 @@ ...@@ -39,6 +39,11 @@
#define MODULE_MAX_IN_PINS 8 #define MODULE_MAX_IN_PINS 8
#define MODULE_MAX_OUT_PINS 8 #define MODULE_MAX_OUT_PINS 8
#define SKL_MIC_CH_SUPPORT 4
#define SKL_MIC_MAX_CH_SUPPORT 8
#define SKL_DEFAULT_MIC_SEL_GAIN 0x3FF
#define SKL_MIC_SEL_SWITCH 0x3
enum skl_channel_index { enum skl_channel_index {
SKL_CHANNEL_LEFT = 0, SKL_CHANNEL_LEFT = 0,
SKL_CHANNEL_RIGHT = 1, SKL_CHANNEL_RIGHT = 1,
...@@ -309,11 +314,14 @@ struct skl_module_cfg { ...@@ -309,11 +314,14 @@ struct skl_module_cfg {
u8 dev_type; u8 dev_type;
u8 dma_id; u8 dma_id;
u8 time_slot; u8 time_slot;
u8 dmic_ch_combo_index;
u32 dmic_ch_type;
u32 params_fixup; u32 params_fixup;
u32 converter; u32 converter;
u32 vbus_id; u32 vbus_id;
u32 mem_pages; u32 mem_pages;
enum d0i3_capability d0i3_caps; enum d0i3_capability d0i3_caps;
u32 dma_buffer_size; /* in milli seconds */
struct skl_module_pin *m_in_pin; struct skl_module_pin *m_in_pin;
struct skl_module_pin *m_out_pin; struct skl_module_pin *m_out_pin;
enum skl_module_type m_type; enum skl_module_type m_type;
...@@ -342,6 +350,19 @@ struct skl_module_deferred_bind { ...@@ -342,6 +350,19 @@ struct skl_module_deferred_bind {
struct list_head node; struct list_head node;
}; };
struct skl_mic_sel_config {
u16 mic_switch;
u16 flags;
u16 blob[SKL_MIC_MAX_CH_SUPPORT][SKL_MIC_MAX_CH_SUPPORT];
} __packed;
enum skl_channel {
SKL_CH_MONO = 1,
SKL_CH_STEREO = 2,
SKL_CH_TRIO = 3,
SKL_CH_QUATRO = 4,
};
static inline struct skl *get_skl_ctx(struct device *dev) static inline struct skl *get_skl_ctx(struct device *dev)
{ {
struct hdac_ext_bus *ebus = dev_get_drvdata(dev); struct hdac_ext_bus *ebus = dev_get_drvdata(dev);
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
* SST types start at higher to avoid any overlapping in future * SST types start at higher to avoid any overlapping in future
*/ */
#define SKL_CONTROL_TYPE_BYTE_TLV 0x100 #define SKL_CONTROL_TYPE_BYTE_TLV 0x100
#define SKL_CONTROL_TYPE_MIC_SELECT 0x102
#define HDA_SST_CFG_MAX 900 /* size of copier cfg*/ #define HDA_SST_CFG_MAX 900 /* size of copier cfg*/
#define MAX_IN_QUEUE 8 #define MAX_IN_QUEUE 8
...@@ -82,6 +83,7 @@ enum skl_module_type { ...@@ -82,6 +83,7 @@ enum skl_module_type {
SKL_MODULE_TYPE_ALGO, SKL_MODULE_TYPE_ALGO,
SKL_MODULE_TYPE_BASE_OUTFMT, SKL_MODULE_TYPE_BASE_OUTFMT,
SKL_MODULE_TYPE_KPB, SKL_MODULE_TYPE_KPB,
SKL_MODULE_TYPE_MIC_SELECT,
}; };
enum skl_core_affinity { enum skl_core_affinity {
......
...@@ -866,6 +866,7 @@ static void skl_remove(struct pci_dev *pci) ...@@ -866,6 +866,7 @@ static void skl_remove(struct pci_dev *pci)
/* codec removal, invoke bus_device_remove */ /* codec removal, invoke bus_device_remove */
snd_hdac_ext_bus_device_remove(ebus); snd_hdac_ext_bus_device_remove(ebus);
skl->debugfs = NULL;
skl_platform_unregister(&pci->dev); skl_platform_unregister(&pci->dev);
skl_free_dsp(skl); skl_free_dsp(skl);
skl_machine_device_unregister(skl); skl_machine_device_unregister(skl);
...@@ -876,29 +877,120 @@ static void skl_remove(struct pci_dev *pci) ...@@ -876,29 +877,120 @@ static void skl_remove(struct pci_dev *pci)
dev_set_drvdata(&pci->dev, NULL); dev_set_drvdata(&pci->dev, NULL);
} }
static struct sst_codecs skl_codecs = {
.num_codecs = 1,
.codecs = {"NAU88L25"}
};
static struct sst_codecs kbl_codecs = {
.num_codecs = 1,
.codecs = {"NAU88L25"}
};
static struct sst_codecs bxt_codecs = {
.num_codecs = 1,
.codecs = {"MX98357A"}
};
static struct sst_codecs kbl_poppy_codecs = {
.num_codecs = 1,
.codecs = {"10EC5663"}
};
static struct sst_codecs kbl_5663_5514_codecs = {
.num_codecs = 2,
.codecs = {"10EC5663", "10EC5514"}
};
static struct sst_acpi_mach sst_skl_devdata[] = { static struct sst_acpi_mach sst_skl_devdata[] = {
{ "INT343A", "skl_alc286s_i2s", "intel/dsp_fw_release.bin", NULL, NULL, NULL }, {
{ "INT343B", "skl_n88l25_s4567", "intel/dsp_fw_release.bin", .id = "INT343A",
NULL, NULL, &skl_dmic_data }, .drv_name = "skl_alc286s_i2s",
{ "MX98357A", "skl_n88l25_m98357a", "intel/dsp_fw_release.bin", .fw_filename = "intel/dsp_fw_release.bin",
NULL, NULL, &skl_dmic_data }, },
{
.id = "INT343B",
.drv_name = "skl_n88l25_s4567",
.fw_filename = "intel/dsp_fw_release.bin",
.machine_quirk = sst_acpi_codec_list,
.quirk_data = &skl_codecs,
.pdata = &skl_dmic_data
},
{
.id = "MX98357A",
.drv_name = "skl_n88l25_m98357a",
.fw_filename = "intel/dsp_fw_release.bin",
.machine_quirk = sst_acpi_codec_list,
.quirk_data = &skl_codecs,
.pdata = &skl_dmic_data
},
{} {}
}; };
static struct sst_acpi_mach sst_bxtp_devdata[] = { static struct sst_acpi_mach sst_bxtp_devdata[] = {
{ "INT343A", "bxt_alc298s_i2s", "intel/dsp_fw_bxtn.bin", NULL, NULL, NULL }, {
{ "DLGS7219", "bxt_da7219_max98357a_i2s", "intel/dsp_fw_bxtn.bin", NULL, NULL, NULL }, .id = "INT343A",
.drv_name = "bxt_alc298s_i2s",
.fw_filename = "intel/dsp_fw_bxtn.bin",
},
{
.id = "DLGS7219",
.drv_name = "bxt_da7219_max98357a_i2s",
.fw_filename = "intel/dsp_fw_bxtn.bin",
.machine_quirk = sst_acpi_codec_list,
.quirk_data = &bxt_codecs,
},
}; };
static struct sst_acpi_mach sst_kbl_devdata[] = { static struct sst_acpi_mach sst_kbl_devdata[] = {
{ "INT343A", "kbl_alc286s_i2s", "intel/dsp_fw_kbl.bin", NULL, NULL, NULL }, {
{ "INT343B", "kbl_n88l25_s4567", "intel/dsp_fw_kbl.bin", NULL, NULL, &skl_dmic_data }, .id = "INT343A",
{ "MX98357A", "kbl_n88l25_m98357a", "intel/dsp_fw_kbl.bin", NULL, NULL, &skl_dmic_data }, .drv_name = "kbl_alc286s_i2s",
.fw_filename = "intel/dsp_fw_kbl.bin",
},
{
.id = "INT343B",
.drv_name = "kbl_n88l25_s4567",
.fw_filename = "intel/dsp_fw_kbl.bin",
.machine_quirk = sst_acpi_codec_list,
.quirk_data = &kbl_codecs,
.pdata = &skl_dmic_data
},
{
.id = "MX98357A",
.drv_name = "kbl_n88l25_m98357a",
.fw_filename = "intel/dsp_fw_kbl.bin",
.machine_quirk = sst_acpi_codec_list,
.quirk_data = &kbl_codecs,
.pdata = &skl_dmic_data
},
{
.id = "MX98927",
.drv_name = "kbl_r5514_5663_max",
.fw_filename = "intel/dsp_fw_kbl.bin",
.machine_quirk = sst_acpi_codec_list,
.quirk_data = &kbl_5663_5514_codecs,
.pdata = &skl_dmic_data
},
{
.id = "MX98927",
.drv_name = "kbl_rt5663_m98927",
.fw_filename = "intel/dsp_fw_kbl.bin",
.machine_quirk = sst_acpi_codec_list,
.quirk_data = &kbl_poppy_codecs,
.pdata = &skl_dmic_data
},
{} {}
}; };
static struct sst_acpi_mach sst_glk_devdata[] = { static struct sst_acpi_mach sst_glk_devdata[] = {
{ "INT343A", "glk_alc298s_i2s", "intel/dsp_fw_glk.bin", NULL, NULL, NULL }, {
.id = "INT343A",
.drv_name = "glk_alc298s_i2s",
.fw_filename = "intel/dsp_fw_glk.bin",
},
}; };
/* PCI IDs */ /* PCI IDs */
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include <sound/hda_register.h> #include <sound/hda_register.h>
#include <sound/hdaudio_ext.h> #include <sound/hdaudio_ext.h>
#include <sound/soc.h>
#include "skl-nhlt.h" #include "skl-nhlt.h"
#define SKL_SUSPEND_DELAY 2000 #define SKL_SUSPEND_DELAY 2000
...@@ -42,6 +43,8 @@ struct skl_dsp_resource { ...@@ -42,6 +43,8 @@ struct skl_dsp_resource {
u32 mem; u32 mem;
}; };
struct skl_debug;
struct skl { struct skl {
struct hdac_ext_bus ebus; struct hdac_ext_bus ebus;
struct pci_dev *pci; struct pci_dev *pci;
...@@ -66,6 +69,8 @@ struct skl { ...@@ -66,6 +69,8 @@ struct skl {
int supend_active; int supend_active;
struct work_struct probe_work; struct work_struct probe_work;
struct skl_debug *debugfs;
}; };
#define skl_to_ebus(s) (&(s)->ebus) #define skl_to_ebus(s) (&(s)->ebus)
...@@ -116,4 +121,22 @@ void skl_update_d0i3c(struct device *dev, bool enable); ...@@ -116,4 +121,22 @@ void skl_update_d0i3c(struct device *dev, bool enable);
int skl_nhlt_create_sysfs(struct skl *skl); int skl_nhlt_create_sysfs(struct skl *skl);
void skl_nhlt_remove_sysfs(struct skl *skl); void skl_nhlt_remove_sysfs(struct skl *skl);
struct skl_module_cfg;
#ifdef CONFIG_DEBUG_FS
struct skl_debug *skl_debugfs_init(struct skl *skl);
void skl_debug_init_module(struct skl_debug *d,
struct snd_soc_dapm_widget *w,
struct skl_module_cfg *mconfig);
#else
static inline struct skl_debug *skl_debugfs_init(struct skl *skl)
{
return NULL;
}
static inline void skl_debug_init_module(struct skl_debug *d,
struct snd_soc_dapm_widget *w,
struct skl_module_cfg *mconfig)
{}
#endif
#endif /* __SOUND_SOC_SKL_H */ #endif /* __SOUND_SOC_SKL_H */
...@@ -68,6 +68,20 @@ static int pmdown_time = 5000; ...@@ -68,6 +68,20 @@ static int pmdown_time = 5000;
module_param(pmdown_time, int, 0); module_param(pmdown_time, int, 0);
MODULE_PARM_DESC(pmdown_time, "DAPM stream powerdown time (msecs)"); MODULE_PARM_DESC(pmdown_time, "DAPM stream powerdown time (msecs)");
/* If a DMI filed contain strings in this blacklist (e.g.
* "Type2 - Board Manufacturer" or "Type1 - TBD by OEM"), it will be taken
* as invalid and dropped when setting the card long name from DMI info.
*/
static const char * const dmi_blacklist[] = {
"To be filled by OEM",
"TBD by OEM",
"Default String",
"Board Manufacturer",
"Board Vendor Name",
"Board Product Name",
NULL, /* terminator */
};
/* returns the minimum number of bytes needed to represent /* returns the minimum number of bytes needed to represent
* a particular given value */ * a particular given value */
static int min_bytes_needed(unsigned long val) static int min_bytes_needed(unsigned long val)
...@@ -1933,6 +1947,22 @@ static void cleanup_dmi_name(char *name) ...@@ -1933,6 +1947,22 @@ static void cleanup_dmi_name(char *name)
name[j] = '\0'; name[j] = '\0';
} }
/* Check if a DMI field is valid, i.e. not containing any string
* in the black list.
*/
static int is_dmi_valid(const char *field)
{
int i = 0;
while (dmi_blacklist[i]) {
if (strstr(field, dmi_blacklist[i]))
return 0;
i++;
}
return 1;
}
/** /**
* snd_soc_set_dmi_name() - Register DMI names to card * snd_soc_set_dmi_name() - Register DMI names to card
* @card: The card to register DMI names * @card: The card to register DMI names
...@@ -1975,17 +2005,18 @@ int snd_soc_set_dmi_name(struct snd_soc_card *card, const char *flavour) ...@@ -1975,17 +2005,18 @@ int snd_soc_set_dmi_name(struct snd_soc_card *card, const char *flavour)
/* make up dmi long name as: vendor.product.version.board */ /* make up dmi long name as: vendor.product.version.board */
vendor = dmi_get_system_info(DMI_BOARD_VENDOR); vendor = dmi_get_system_info(DMI_BOARD_VENDOR);
if (!vendor) { if (!vendor || !is_dmi_valid(vendor)) {
dev_warn(card->dev, "ASoC: no DMI vendor name!\n"); dev_warn(card->dev, "ASoC: no DMI vendor name!\n");
return 0; return 0;
} }
snprintf(card->dmi_longname, sizeof(card->snd_card->longname), snprintf(card->dmi_longname, sizeof(card->snd_card->longname),
"%s", vendor); "%s", vendor);
cleanup_dmi_name(card->dmi_longname); cleanup_dmi_name(card->dmi_longname);
product = dmi_get_system_info(DMI_PRODUCT_NAME); product = dmi_get_system_info(DMI_PRODUCT_NAME);
if (product) { if (product && is_dmi_valid(product)) {
len = strlen(card->dmi_longname); len = strlen(card->dmi_longname);
snprintf(card->dmi_longname + len, snprintf(card->dmi_longname + len,
longname_buf_size - len, longname_buf_size - len,
...@@ -1999,7 +2030,7 @@ int snd_soc_set_dmi_name(struct snd_soc_card *card, const char *flavour) ...@@ -1999,7 +2030,7 @@ int snd_soc_set_dmi_name(struct snd_soc_card *card, const char *flavour)
* name in the product version field * name in the product version field
*/ */
product_version = dmi_get_system_info(DMI_PRODUCT_VERSION); product_version = dmi_get_system_info(DMI_PRODUCT_VERSION);
if (product_version) { if (product_version && is_dmi_valid(product_version)) {
len = strlen(card->dmi_longname); len = strlen(card->dmi_longname);
snprintf(card->dmi_longname + len, snprintf(card->dmi_longname + len,
longname_buf_size - len, longname_buf_size - len,
...@@ -2012,7 +2043,7 @@ int snd_soc_set_dmi_name(struct snd_soc_card *card, const char *flavour) ...@@ -2012,7 +2043,7 @@ int snd_soc_set_dmi_name(struct snd_soc_card *card, const char *flavour)
} }
board = dmi_get_system_info(DMI_BOARD_NAME); board = dmi_get_system_info(DMI_BOARD_NAME);
if (board) { if (board && is_dmi_valid(board)) {
len = strlen(card->dmi_longname); len = strlen(card->dmi_longname);
snprintf(card->dmi_longname + len, snprintf(card->dmi_longname + len,
longname_buf_size - len, longname_buf_size - len,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment