summaryrefslogtreecommitdiff
path: root/sound/soc/intel
diff options
context:
space:
mode:
authorStefan Agner <stefan.agner@toradex.com>2017-12-13 21:31:49 +0100
committerMarcel Ziswiler <marcel.ziswiler@toradex.com>2017-12-21 15:14:59 +0100
commit688f897ddd96968cf59a2d67afe2a394a0bf8ab3 (patch)
treee303dd2f94a5c670a318008c891674e116558e6b /sound/soc/intel
parenta898b45a9c18bd9d723f82576a5b32a102808a09 (diff)
parentfb2d2dee504a963efdcb76517b5cdf25444cf535 (diff)
Merge remote-tracking branch 'linux-fslc/4.9-1.0.x-imx' into toradex_4.9-1.0.x-imx-next
Diffstat (limited to 'sound/soc/intel')
-rw-r--r--sound/soc/intel/Kconfig31
-rw-r--r--sound/soc/intel/atom/sst/sst_acpi.c37
-rw-r--r--sound/soc/intel/boards/bytcr_rt5640.c28
-rw-r--r--sound/soc/intel/boards/bytcr_rt5651.c3
-rw-r--r--sound/soc/intel/boards/cht_bsw_rt5645.c98
-rw-r--r--sound/soc/intel/skylake/skl-sst.c3
-rw-r--r--sound/soc/intel/skylake/skl-topology.c2
7 files changed, 157 insertions, 45 deletions
diff --git a/sound/soc/intel/Kconfig b/sound/soc/intel/Kconfig
index fd5d1e091038..e18fe9d6f08f 100644
--- a/sound/soc/intel/Kconfig
+++ b/sound/soc/intel/Kconfig
@@ -33,11 +33,9 @@ config SND_SOC_INTEL_SST
select SND_SOC_INTEL_SST_MATCH if ACPI
depends on (X86 || COMPILE_TEST)
-# firmware stuff depends DW_DMAC_CORE; since there is no depends-on from
-# the reverse selection, each machine driver needs to select
-# SND_SOC_INTEL_SST_FIRMWARE carefully depending on DW_DMAC_CORE
config SND_SOC_INTEL_SST_FIRMWARE
tristate
+ select DW_DMAC_CORE
config SND_SOC_INTEL_SST_ACPI
tristate
@@ -47,16 +45,18 @@ config SND_SOC_INTEL_SST_MATCH
config SND_SOC_INTEL_HASWELL
tristate
+ select SND_SOC_INTEL_SST
select SND_SOC_INTEL_SST_FIRMWARE
config SND_SOC_INTEL_BAYTRAIL
tristate
+ select SND_SOC_INTEL_SST
+ select SND_SOC_INTEL_SST_FIRMWARE
config SND_SOC_INTEL_HASWELL_MACH
tristate "ASoC Audio DSP support for Intel Haswell Lynxpoint"
depends on X86_INTEL_LPSS && I2C && I2C_DESIGNWARE_PLATFORM
- depends on DW_DMAC_CORE
- select SND_SOC_INTEL_SST
+ depends on DMADEVICES
select SND_SOC_INTEL_HASWELL
select SND_SOC_RT5640
help
@@ -99,9 +99,8 @@ config SND_SOC_INTEL_BXT_RT298_MACH
config SND_SOC_INTEL_BYT_RT5640_MACH
tristate "ASoC Audio driver for Intel Baytrail with RT5640 codec"
depends on X86_INTEL_LPSS && I2C
- depends on DW_DMAC_CORE && (SND_SST_IPC_ACPI = n)
- select SND_SOC_INTEL_SST
- select SND_SOC_INTEL_SST_FIRMWARE
+ depends on DMADEVICES
+ depends on SND_SST_IPC_ACPI = n
select SND_SOC_INTEL_BAYTRAIL
select SND_SOC_RT5640
help
@@ -112,9 +111,8 @@ config SND_SOC_INTEL_BYT_RT5640_MACH
config SND_SOC_INTEL_BYT_MAX98090_MACH
tristate "ASoC Audio driver for Intel Baytrail with MAX98090 codec"
depends on X86_INTEL_LPSS && I2C
- depends on DW_DMAC_CORE && (SND_SST_IPC_ACPI = n)
- select SND_SOC_INTEL_SST
- select SND_SOC_INTEL_SST_FIRMWARE
+ depends on DMADEVICES
+ depends on SND_SST_IPC_ACPI = n
select SND_SOC_INTEL_BAYTRAIL
select SND_SOC_MAX98090
help
@@ -123,9 +121,8 @@ config SND_SOC_INTEL_BYT_MAX98090_MACH
config SND_SOC_INTEL_BDW_RT5677_MACH
tristate "ASoC Audio driver for Intel Broadwell with RT5677 codec"
- depends on X86_INTEL_LPSS && GPIOLIB && I2C && DW_DMAC
- depends on DW_DMAC_CORE=y
- select SND_SOC_INTEL_SST
+ depends on X86_INTEL_LPSS && GPIOLIB && I2C
+ depends on DMADEVICES
select SND_SOC_INTEL_HASWELL
select SND_SOC_RT5677
help
@@ -134,10 +131,8 @@ config SND_SOC_INTEL_BDW_RT5677_MACH
config SND_SOC_INTEL_BROADWELL_MACH
tristate "ASoC Audio DSP support for Intel Broadwell Wildcatpoint"
- depends on X86_INTEL_LPSS && I2C && DW_DMAC && \
- I2C_DESIGNWARE_PLATFORM
- depends on DW_DMAC_CORE
- select SND_SOC_INTEL_SST
+ depends on X86_INTEL_LPSS && I2C && I2C_DESIGNWARE_PLATFORM
+ depends on DMADEVICES
select SND_SOC_INTEL_HASWELL
select SND_SOC_RT286
help
diff --git a/sound/soc/intel/atom/sst/sst_acpi.c b/sound/soc/intel/atom/sst/sst_acpi.c
index 0a88537ca58a..0bfa68862460 100644
--- a/sound/soc/intel/atom/sst/sst_acpi.c
+++ b/sound/soc/intel/atom/sst/sst_acpi.c
@@ -400,6 +400,7 @@ static int sst_acpi_remove(struct platform_device *pdev)
static unsigned long cht_machine_id;
#define CHT_SURFACE_MACH 1
+#define BYT_THINKPAD_10 2
static int cht_surface_quirk_cb(const struct dmi_system_id *id)
{
@@ -407,6 +408,23 @@ static int cht_surface_quirk_cb(const struct dmi_system_id *id)
return 1;
}
+static int byt_thinkpad10_quirk_cb(const struct dmi_system_id *id)
+{
+ cht_machine_id = BYT_THINKPAD_10;
+ return 1;
+}
+
+
+static const struct dmi_system_id byt_table[] = {
+ {
+ .callback = byt_thinkpad10_quirk_cb,
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "20C3001VHH"),
+ },
+ },
+ { }
+};
static const struct dmi_system_id cht_table[] = {
{
@@ -424,6 +442,10 @@ static struct sst_acpi_mach cht_surface_mach = {
"10EC5640", "cht-bsw-rt5645", "intel/fw_sst_22a8.bin", "cht-bsw", NULL,
&chv_platform_data };
+static struct sst_acpi_mach byt_thinkpad_10 = {
+ "10EC5640", "cht-bsw-rt5672", "intel/fw_sst_0f28.bin", "cht-bsw", NULL,
+ &byt_rvp_platform_data };
+
static struct sst_acpi_mach *cht_quirk(void *arg)
{
struct sst_acpi_mach *mach = arg;
@@ -436,8 +458,21 @@ static struct sst_acpi_mach *cht_quirk(void *arg)
return mach;
}
+static struct sst_acpi_mach *byt_quirk(void *arg)
+{
+ struct sst_acpi_mach *mach = arg;
+
+ dmi_check_system(byt_table);
+
+ if (cht_machine_id == BYT_THINKPAD_10)
+ return &byt_thinkpad_10;
+ else
+ return mach;
+}
+
+
static struct sst_acpi_mach sst_acpi_bytcr[] = {
- {"10EC5640", "bytcr_rt5640", "intel/fw_sst_0f28.bin", "bytcr_rt5640", NULL,
+ {"10EC5640", "bytcr_rt5640", "intel/fw_sst_0f28.bin", "bytcr_rt5640", byt_quirk,
&byt_rvp_platform_data },
{"10EC5642", "bytcr_rt5640", "intel/fw_sst_0f28.bin", "bytcr_rt5640", NULL,
&byt_rvp_platform_data },
diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c
index bff77a1f27fc..c17f262f0834 100644
--- a/sound/soc/intel/boards/bytcr_rt5640.c
+++ b/sound/soc/intel/boards/bytcr_rt5640.c
@@ -57,9 +57,7 @@ struct byt_rt5640_private {
struct clk *mclk;
};
-static unsigned long byt_rt5640_quirk = BYT_RT5640_DMIC1_MAP |
- BYT_RT5640_DMIC_EN |
- BYT_RT5640_MCLK_EN;
+static unsigned long byt_rt5640_quirk = BYT_RT5640_MCLK_EN;
static void log_quirks(struct device *dev)
{
@@ -144,7 +142,7 @@ static int platform_clock_control(struct snd_soc_dapm_widget *w,
* for Jack detection and button press
*/
ret = snd_soc_dai_set_sysclk(codec_dai, RT5640_SCLK_S_RCCLK,
- 0,
+ 48000 * 512,
SND_SOC_CLOCK_IN);
if (!ret) {
if ((byt_rt5640_quirk & BYT_RT5640_MCLK_EN) && priv->mclk)
@@ -389,6 +387,16 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = {
BYT_RT5640_SSP0_AIF1),
},
+ {
+ .callback = byt_rt5640_quirk_cb,
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Insyde"),
+ },
+ .driver_data = (unsigned long *)(BYT_RT5640_IN3_MAP |
+ BYT_RT5640_MCLK_EN |
+ BYT_RT5640_SSP0_AIF1),
+
+ },
{}
};
@@ -613,7 +621,7 @@ static struct snd_soc_dai_link byt_rt5640_dais[] = {
.codec_dai_name = "snd-soc-dummy-dai",
.codec_name = "snd-soc-dummy",
.platform_name = "sst-mfld-platform",
- .ignore_suspend = 1,
+ .nonatomic = true,
.dynamic = 1,
.dpcm_playback = 1,
.dpcm_capture = 1,
@@ -626,7 +634,6 @@ static struct snd_soc_dai_link byt_rt5640_dais[] = {
.codec_dai_name = "snd-soc-dummy-dai",
.codec_name = "snd-soc-dummy",
.platform_name = "sst-mfld-platform",
- .ignore_suspend = 1,
.nonatomic = true,
.dynamic = 1,
.dpcm_playback = 1,
@@ -653,6 +660,7 @@ static struct snd_soc_dai_link byt_rt5640_dais[] = {
| SND_SOC_DAIFMT_CBS_CFS,
.be_hw_params_fixup = byt_rt5640_codec_fixup,
.ignore_suspend = 1,
+ .nonatomic = true,
.dpcm_playback = 1,
.dpcm_capture = 1,
.init = byt_rt5640_init,
@@ -738,6 +746,13 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev)
if (res_info->acpi_ipc_irq_index == 0) {
byt_rt5640_quirk |= BYT_RT5640_SSP0_AIF2;
}
+
+ /* change defaults for Baytrail-CR capture */
+ byt_rt5640_quirk |= BYT_RT5640_IN1_MAP;
+ byt_rt5640_quirk |= BYT_RT5640_DIFF_MIC;
+ } else {
+ byt_rt5640_quirk |= (BYT_RT5640_DMIC1_MAP |
+ BYT_RT5640_DMIC_EN);
}
/* check quirks before creating card */
@@ -792,7 +807,6 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev)
static struct platform_driver snd_byt_rt5640_mc_driver = {
.driver = {
.name = "bytcr_rt5640",
- .pm = &snd_soc_pm_ops,
},
.probe = snd_byt_rt5640_mc_probe,
};
diff --git a/sound/soc/intel/boards/bytcr_rt5651.c b/sound/soc/intel/boards/bytcr_rt5651.c
index 35f591eab3c9..ae49f8199e45 100644
--- a/sound/soc/intel/boards/bytcr_rt5651.c
+++ b/sound/soc/intel/boards/bytcr_rt5651.c
@@ -235,7 +235,6 @@ static struct snd_soc_dai_link byt_rt5651_dais[] = {
.codec_dai_name = "snd-soc-dummy-dai",
.codec_name = "snd-soc-dummy",
.platform_name = "sst-mfld-platform",
- .ignore_suspend = 1,
.nonatomic = true,
.dynamic = 1,
.dpcm_playback = 1,
@@ -249,7 +248,6 @@ static struct snd_soc_dai_link byt_rt5651_dais[] = {
.codec_dai_name = "snd-soc-dummy-dai",
.codec_name = "snd-soc-dummy",
.platform_name = "sst-mfld-platform",
- .ignore_suspend = 1,
.nonatomic = true,
.dynamic = 1,
.dpcm_playback = 1,
@@ -319,7 +317,6 @@ static int snd_byt_rt5651_mc_probe(struct platform_device *pdev)
static struct platform_driver snd_byt_rt5651_mc_driver = {
.driver = {
.name = "bytcr_rt5651",
- .pm = &snd_soc_pm_ops,
},
.probe = snd_byt_rt5651_mc_probe,
};
diff --git a/sound/soc/intel/boards/cht_bsw_rt5645.c b/sound/soc/intel/boards/cht_bsw_rt5645.c
index 16c94c45ce50..90525614c20a 100644
--- a/sound/soc/intel/boards/cht_bsw_rt5645.c
+++ b/sound/soc/intel/boards/cht_bsw_rt5645.c
@@ -24,6 +24,9 @@
#include <linux/acpi.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
+#include <asm/cpu_device_id.h>
+#include <asm/platform_sst_audio.h>
+#include <linux/clk.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
@@ -45,6 +48,7 @@ struct cht_mc_private {
struct snd_soc_jack jack;
struct cht_acpi_card *acpi_card;
char codec_name[16];
+ struct clk *mclk;
};
static inline struct snd_soc_dai *cht_get_codec_dai(struct snd_soc_card *card)
@@ -65,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_card *card = dapm->card;
struct snd_soc_dai *codec_dai;
+ struct cht_mc_private *ctx = snd_soc_card_get_drvdata(card);
int ret;
codec_dai = cht_get_codec_dai(card);
@@ -73,19 +78,30 @@ static int platform_clock_control(struct snd_soc_dapm_widget *w,
return -EIO;
}
- if (!SND_SOC_DAPM_EVENT_OFF(event))
- return 0;
+ 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;
+ }
+ }
+ } else {
+ /* Set codec sysclk source to its internal clock because codec PLL will
+ * be off when idle and MCLK will also be off when codec is
+ * runtime suspended. Codec needs clock for jack detection and button
+ * press. MCLK is turned off with clock framework or ACPI.
+ */
+ ret = snd_soc_dai_set_sysclk(codec_dai, RT5645_SCLK_S_RCCLK,
+ 48000 * 512, SND_SOC_CLOCK_IN);
+ if (ret < 0) {
+ dev_err(card->dev, "can't set codec sysclk: %d\n", ret);
+ return ret;
+ }
- /* Set codec sysclk source to its internal clock because codec PLL will
- * be off when idle and MCLK will also be off by ACPI when codec is
- * runtime suspended. Codec needs clock for jack detection and button
- * press.
- */
- ret = snd_soc_dai_set_sysclk(codec_dai, RT5645_SCLK_S_RCCLK,
- 0, SND_SOC_CLOCK_IN);
- if (ret < 0) {
- dev_err(card->dev, "can't set codec sysclk: %d\n", ret);
- return ret;
+ if (ctx->mclk)
+ clk_disable_unprepare(ctx->mclk);
}
return 0;
@@ -97,7 +113,7 @@ static const struct snd_soc_dapm_widget cht_dapm_widgets[] = {
SND_SOC_DAPM_MIC("Int Mic", NULL),
SND_SOC_DAPM_SPK("Ext Spk", NULL),
SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0,
- platform_clock_control, SND_SOC_DAPM_POST_PMD),
+ platform_clock_control, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
};
static const struct snd_soc_dapm_route cht_rt5645_audio_map[] = {
@@ -225,6 +241,26 @@ static int cht_codec_init(struct snd_soc_pcm_runtime *runtime)
rt5645_set_jack_detect(codec, &ctx->jack, &ctx->jack, &ctx->jack);
+ 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;
}
@@ -349,6 +385,18 @@ static struct cht_acpi_card snd_soc_cards[] = {
static char cht_rt5640_codec_name[16]; /* i2c-<HID>:00 with HID being 8 chars */
+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;
+}
+
static int snd_cht_mc_probe(struct platform_device *pdev)
{
int ret_val = 0;
@@ -358,22 +406,32 @@ static int snd_cht_mc_probe(struct platform_device *pdev)
struct sst_acpi_mach *mach;
const char *i2c_name = NULL;
int dai_index = 0;
+ bool found = false;
drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_ATOMIC);
if (!drv)
return -ENOMEM;
+ mach = (&pdev->dev)->platform_data;
+
for (i = 0; i < ARRAY_SIZE(snd_soc_cards); i++) {
- if (acpi_dev_found(snd_soc_cards[i].codec_id)) {
+ if (acpi_dev_found(snd_soc_cards[i].codec_id) &&
+ (!strncmp(snd_soc_cards[i].codec_id, mach->id, 8))) {
dev_dbg(&pdev->dev,
"found codec %s\n", snd_soc_cards[i].codec_id);
card = snd_soc_cards[i].soc_card;
drv->acpi_card = &snd_soc_cards[i];
+ found = true;
break;
}
}
+
+ if (!found) {
+ dev_err(&pdev->dev, "No matching HID found in supported list\n");
+ return -ENODEV;
+ }
+
card->dev = &pdev->dev;
- mach = card->dev->platform_data;
sprintf(drv->codec_name, "i2c-%s:00", drv->acpi_card->codec_id);
/* set correct codec name */
@@ -391,6 +449,16 @@ static int snd_cht_mc_probe(struct platform_device *pdev)
cht_dailink[dai_index].codec_name = cht_rt5640_codec_name;
}
+ 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(card, drv);
ret_val = devm_snd_soc_register_card(&pdev->dev, card);
if (ret_val) {
diff --git a/sound/soc/intel/skylake/skl-sst.c b/sound/soc/intel/skylake/skl-sst.c
index 8fc3178bc79c..b30bd384c8d3 100644
--- a/sound/soc/intel/skylake/skl-sst.c
+++ b/sound/soc/intel/skylake/skl-sst.c
@@ -515,6 +515,9 @@ EXPORT_SYMBOL_GPL(skl_sst_init_fw);
void skl_sst_dsp_cleanup(struct device *dev, struct skl_sst *ctx)
{
+
+ if (ctx->dsp->fw)
+ release_firmware(ctx->dsp->fw);
skl_clear_module_table(ctx->dsp);
skl_freeup_uuid_list(ctx);
skl_ipc_free(&ctx->ipc);
diff --git a/sound/soc/intel/skylake/skl-topology.c b/sound/soc/intel/skylake/skl-topology.c
index b5b1934d8550..bef8a4546c12 100644
--- a/sound/soc/intel/skylake/skl-topology.c
+++ b/sound/soc/intel/skylake/skl-topology.c
@@ -448,7 +448,7 @@ static int skl_tplg_set_module_init_data(struct snd_soc_dapm_widget *w)
if (bc->set_params != SKL_PARAM_INIT)
continue;
- mconfig->formats_config.caps = (u32 *)&bc->params;
+ mconfig->formats_config.caps = (u32 *)bc->params;
mconfig->formats_config.caps_size = bc->size;
break;