summaryrefslogtreecommitdiffstats
path: root/sound/soc/intel
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2020-06-04 20:07:38 +0200
committerLinus Torvalds <torvalds@linux-foundation.org>2020-06-04 20:07:38 +0200
commit631d6914085b4eea8d68a84f800974a6ad8fb5c0 (patch)
treed38b189458bb186a016816c41c7e7321ba5e94ba /sound/soc/intel
parentMerge branch 'pcmcia-next' of git://git.kernel.org/pub/scm/linux/kernel/git/b... (diff)
parentALSA: es1688: Add the missed snd_card_free() (diff)
downloadlinux-631d6914085b4eea8d68a84f800974a6ad8fb5c0.tar.xz
linux-631d6914085b4eea8d68a84f800974a6ad8fb5c0.zip
Merge tag 'sound-5.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
Pull sound updates from Takashi Iwai: "It was another busy development cycle, and the majority of changes are found in ASoC side. Below are Some highlights. ASoC core: - Lots of core cleanups and refactorings, still on-going work by Morimoto-san ASoC drivers: - Continued work on cleaning up and improving the Intel SOF stuff, along with new platform support including SoundWire - Fixes to make the Marvell SSPA driver work upstream - Support for AMD Renoir ACP, Dialog DA7212, Freescale EASRC and i.MX8M, Intel Elkhard Lake, Maxim MAX98390, Nuvoton NAU8812 and NAU8814 and Realtek RT1016. USB-audio: - Improvement for sync and implicit feedback streams with the more accurate frame size calculation and full-duplex support - Support for RME Babyface Pro and Prioneer DJ DJM HD-audio: - Fixes for Mic mute LED on HP machines - Re-enable support of Intel SST driver for SKL/KBL platforms FireWire: - Lots of refactoring, add support for RME FireFace and MOTU UltraLite-mk3" * tag 'sound-5.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (428 commits) ALSA: es1688: Add the missed snd_card_free() ALSA: hda: add sienna_cichlid audio asic id for sienna_cichlid up ALSA: usb-audio: Add Pioneer DJ DJM-900NXS2 support ASoC: qcom: q6asm-dai: kCFI fix ASoC: soc-card: add snd_soc_card_remove_dai_link() ASoC: soc-card: add snd_soc_card_add_dai_link() ASoC: soc-card: add snd_soc_card_set_bias_level_post() ASoC: soc-card: add snd_soc_card_set_bias_level() ASoC: soc-card: add snd_soc_card_remove() ASoC: soc-card: add snd_soc_card_late_probe() ASoC: soc-card: add snd_soc_card_probe() ASoC: soc-card: add probed bit field to snd_soc_card ASoC: soc-card: add snd_soc_card_resume_post() ASoC: soc-card: add snd_soc_card_resume_pre() ASoC: soc-card: add snd_soc_card_suspend_post() ASoC: soc-card: add snd_soc_card_suspend_pre() ASoC: soc-card: move snd_soc_card_subclass to soc-card ASoC: soc-card: move snd_soc_card_get_codec_dai() to soc-card ASoC: soc-card: move snd_soc_card_set/get_drvdata() to soc-card ASoC: soc-card: move snd_soc_card_jack_new() to soc-card ...
Diffstat (limited to 'sound/soc/intel')
-rw-r--r--sound/soc/intel/Kconfig8
-rw-r--r--sound/soc/intel/Makefile2
-rw-r--r--sound/soc/intel/atom/Makefile2
-rw-r--r--sound/soc/intel/atom/sst-atom-controls.h2
-rw-r--r--sound/soc/intel/atom/sst-mfld-platform-compress.c43
-rw-r--r--sound/soc/intel/atom/sst-mfld-platform-pcm.c16
-rw-r--r--sound/soc/intel/atom/sst-mfld-platform.h2
-rw-r--r--sound/soc/intel/atom/sst/Makefile2
-rw-r--r--sound/soc/intel/baytrail/sst-baytrail-ipc.c4
-rw-r--r--sound/soc/intel/boards/Kconfig83
-rw-r--r--sound/soc/intel/boards/Makefile6
-rw-r--r--sound/soc/intel/boards/bdw-rt5650.c29
-rw-r--r--sound/soc/intel/boards/bdw-rt5677.c26
-rw-r--r--sound/soc/intel/boards/broadwell.c43
-rw-r--r--sound/soc/intel/boards/bytcht_cx2072x.c5
-rw-r--r--sound/soc/intel/boards/bytcht_da7213.c3
-rw-r--r--sound/soc/intel/boards/bytcht_es8316.c3
-rw-r--r--sound/soc/intel/boards/bytcr_rt5640.c19
-rw-r--r--sound/soc/intel/boards/bytcr_rt5651.c6
-rw-r--r--sound/soc/intel/boards/cht_bsw_max98090_ti.c3
-rw-r--r--sound/soc/intel/boards/cht_bsw_nau8824.c7
-rw-r--r--sound/soc/intel/boards/cht_bsw_rt5645.c3
-rw-r--r--sound/soc/intel/boards/cht_bsw_rt5672.c3
-rw-r--r--sound/soc/intel/boards/cml_rt1011_rt5682.c224
-rw-r--r--sound/soc/intel/boards/ehl_rt5660.c323
-rw-r--r--sound/soc/intel/boards/glk_rt5682_max98357a.c2
-rw-r--r--sound/soc/intel/boards/hda_dsp_common.c2
-rw-r--r--sound/soc/intel/boards/hda_dsp_common.h2
-rw-r--r--sound/soc/intel/boards/kbl_da7219_max98357a.c2
-rw-r--r--sound/soc/intel/boards/kbl_da7219_max98927.c2
-rw-r--r--sound/soc/intel/boards/kbl_rt5660.c2
-rw-r--r--sound/soc/intel/boards/skl_hda_dsp_common.c2
-rw-r--r--sound/soc/intel/boards/skl_hda_dsp_common.h2
-rw-r--r--sound/soc/intel/boards/skl_hda_dsp_generic.c33
-rw-r--r--sound/soc/intel/boards/sof_da7219_max98373.c23
-rw-r--r--sound/soc/intel/boards/sof_maxim_common.c2
-rw-r--r--sound/soc/intel/boards/sof_maxim_common.h2
-rw-r--r--sound/soc/intel/boards/sof_pcm512x.c11
-rw-r--r--sound/soc/intel/boards/sof_rt5682.c2
-rw-r--r--sound/soc/intel/boards/sof_sdw.c65
-rw-r--r--sound/soc/intel/boards/sof_sdw_common.h2
-rw-r--r--sound/soc/intel/boards/sof_sdw_dmic.c2
-rw-r--r--sound/soc/intel/boards/sof_sdw_hdmi.c11
-rw-r--r--sound/soc/intel/boards/sof_sdw_rt1308.c4
-rw-r--r--sound/soc/intel/boards/sof_sdw_rt5682.c5
-rw-r--r--sound/soc/intel/boards/sof_sdw_rt700.c13
-rw-r--r--sound/soc/intel/boards/sof_sdw_rt711.c13
-rw-r--r--sound/soc/intel/boards/sof_sdw_rt715.c2
-rw-r--r--sound/soc/intel/boards/sof_wm8804.c298
-rw-r--r--sound/soc/intel/common/Makefile2
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-bxt-match.c4
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-cfl-match.c2
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-cml-match.c2
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-cnl-match.c2
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-ehl-match.c9
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-glk-match.c2
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-hda-match.c2
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-icl-match.c2
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-jsl-match.c2
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-kbl-match.c2
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-skl-match.c2
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-tgl-match.c2
-rw-r--r--sound/soc/intel/common/soc-intel-quirks.h2
-rw-r--r--sound/soc/intel/common/sst-dsp.c9
-rw-r--r--sound/soc/intel/haswell/sst-haswell-dsp.c185
-rw-r--r--sound/soc/intel/skylake/Makefile2
-rw-r--r--sound/soc/intel/skylake/skl-i2s.h2
-rw-r--r--sound/soc/intel/skylake/skl-ssp-clk.c2
-rw-r--r--sound/soc/intel/skylake/skl-sst-utils.c2
-rw-r--r--sound/soc/intel/skylake/skl-topology.c184
-rw-r--r--sound/soc/intel/skylake/skl-topology.h5
-rw-r--r--sound/soc/intel/skylake/skl.h2
72 files changed, 1486 insertions, 315 deletions
diff --git a/sound/soc/intel/Kconfig b/sound/soc/intel/Kconfig
index c8de0bb5bed9..36f547939f0a 100644
--- a/sound/soc/intel/Kconfig
+++ b/sound/soc/intel/Kconfig
@@ -209,12 +209,8 @@ config SND_SOC_INTEL_SKYLAKE_SSP_CLK
config SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC
bool "HDAudio codec support"
help
- This option broke audio on Linus' Skylake laptop in December 2018
- and the race conditions during the probe were not fixed since.
- This option is DEPRECATED, all HDaudio codec support needs
- to be handled by the SOF driver.
- Distributions should not enable this option and there are no known
- users of this capability.
+ If you have Intel Skylake or Kabylake with HDaudio codec
+ and DMIC present then enable this option by saying Y.
config SND_SOC_INTEL_SKYLAKE_COMMON
tristate
diff --git a/sound/soc/intel/Makefile b/sound/soc/intel/Makefile
index 8160520fd74c..e16d6dc4d4e6 100644
--- a/sound/soc/intel/Makefile
+++ b/sound/soc/intel/Makefile
@@ -1,4 +1,4 @@
-# SPDX-License-Identifier: GPL-2.0
+# SPDX-License-Identifier: GPL-2.0-only
# Core support
obj-$(CONFIG_SND_SOC) += common/
diff --git a/sound/soc/intel/atom/Makefile b/sound/soc/intel/atom/Makefile
index 1dc60471b399..a9326d5ec44c 100644
--- a/sound/soc/intel/atom/Makefile
+++ b/sound/soc/intel/atom/Makefile
@@ -1,4 +1,4 @@
-# SPDX-License-Identifier: GPL-2.0
+# SPDX-License-Identifier: GPL-2.0-only
snd-soc-sst-atom-hifi2-platform-objs := sst-mfld-platform-pcm.o \
sst-mfld-platform-compress.o \
sst-atom-controls.o
diff --git a/sound/soc/intel/atom/sst-atom-controls.h b/sound/soc/intel/atom/sst-atom-controls.h
index 5356e954a732..620b48d2a064 100644
--- a/sound/soc/intel/atom/sst-atom-controls.h
+++ b/sound/soc/intel/atom/sst-atom-controls.h
@@ -410,7 +410,7 @@ struct sst_cmd_set_gain_dual {
struct sst_cmd_set_params {
struct sst_destination_id dst;
u16 command_id;
- char params[0];
+ char params[];
} __packed;
diff --git a/sound/soc/intel/atom/sst-mfld-platform-compress.c b/sound/soc/intel/atom/sst-mfld-platform-compress.c
index 4a7a9426a3b9..1595e01a7e12 100644
--- a/sound/soc/intel/atom/sst-mfld-platform-compress.c
+++ b/sound/soc/intel/atom/sst-mfld-platform-compress.c
@@ -39,7 +39,8 @@ static void sst_drain_notify(void *arg)
snd_compr_drain_notify(cstream);
}
-static int sst_platform_compr_open(struct snd_compr_stream *cstream)
+static int sst_platform_compr_open(struct snd_soc_component *component,
+ struct snd_compr_stream *cstream)
{
int ret_val = 0;
@@ -72,7 +73,8 @@ out_ops:
return ret_val;
}
-static int sst_platform_compr_free(struct snd_compr_stream *cstream)
+static int sst_platform_compr_free(struct snd_soc_component *component,
+ struct snd_compr_stream *cstream)
{
struct sst_runtime_stream *stream;
int ret_val = 0, str_id;
@@ -91,15 +93,14 @@ static int sst_platform_compr_free(struct snd_compr_stream *cstream)
return 0;
}
-static int sst_platform_compr_set_params(struct snd_compr_stream *cstream,
- struct snd_compr_params *params)
+static int sst_platform_compr_set_params(struct snd_soc_component *component,
+ struct snd_compr_stream *cstream,
+ struct snd_compr_params *params)
{
struct sst_runtime_stream *stream;
int retval;
struct snd_sst_params str_params;
struct sst_compress_cb cb;
- struct snd_soc_pcm_runtime *rtd = cstream->private_data;
- struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
struct sst_data *ctx = snd_soc_component_get_drvdata(component);
stream = cstream->runtime->private_data;
@@ -166,7 +167,8 @@ static int sst_platform_compr_set_params(struct snd_compr_stream *cstream,
return 0;
}
-static int sst_platform_compr_trigger(struct snd_compr_stream *cstream, int cmd)
+static int sst_platform_compr_trigger(struct snd_soc_component *component,
+ struct snd_compr_stream *cstream, int cmd)
{
struct sst_runtime_stream *stream = cstream->runtime->private_data;
@@ -199,8 +201,9 @@ static int sst_platform_compr_trigger(struct snd_compr_stream *cstream, int cmd)
return -EINVAL;
}
-static int sst_platform_compr_pointer(struct snd_compr_stream *cstream,
- struct snd_compr_tstamp *tstamp)
+static int sst_platform_compr_pointer(struct snd_soc_component *component,
+ struct snd_compr_stream *cstream,
+ struct snd_compr_tstamp *tstamp)
{
struct sst_runtime_stream *stream;
@@ -212,8 +215,9 @@ static int sst_platform_compr_pointer(struct snd_compr_stream *cstream,
return 0;
}
-static int sst_platform_compr_ack(struct snd_compr_stream *cstream,
- size_t bytes)
+static int sst_platform_compr_ack(struct snd_soc_component *component,
+ struct snd_compr_stream *cstream,
+ size_t bytes)
{
struct sst_runtime_stream *stream;
@@ -224,8 +228,9 @@ static int sst_platform_compr_ack(struct snd_compr_stream *cstream,
return 0;
}
-static int sst_platform_compr_get_caps(struct snd_compr_stream *cstream,
- struct snd_compr_caps *caps)
+static int sst_platform_compr_get_caps(struct snd_soc_component *component,
+ struct snd_compr_stream *cstream,
+ struct snd_compr_caps *caps)
{
struct sst_runtime_stream *stream =
cstream->runtime->private_data;
@@ -233,8 +238,9 @@ static int sst_platform_compr_get_caps(struct snd_compr_stream *cstream,
return stream->compr_ops->get_caps(caps);
}
-static int sst_platform_compr_get_codec_caps(struct snd_compr_stream *cstream,
- struct snd_compr_codec_caps *codec)
+static int sst_platform_compr_get_codec_caps(struct snd_soc_component *component,
+ struct snd_compr_stream *cstream,
+ struct snd_compr_codec_caps *codec)
{
struct sst_runtime_stream *stream =
cstream->runtime->private_data;
@@ -242,8 +248,9 @@ static int sst_platform_compr_get_codec_caps(struct snd_compr_stream *cstream,
return stream->compr_ops->get_codec_caps(codec);
}
-static int sst_platform_compr_set_metadata(struct snd_compr_stream *cstream,
- struct snd_compr_metadata *metadata)
+static int sst_platform_compr_set_metadata(struct snd_soc_component *component,
+ struct snd_compr_stream *cstream,
+ struct snd_compr_metadata *metadata)
{
struct sst_runtime_stream *stream =
cstream->runtime->private_data;
@@ -251,7 +258,7 @@ static int sst_platform_compr_set_metadata(struct snd_compr_stream *cstream,
return stream->compr_ops->set_metadata(sst->dev, stream->id, metadata);
}
-const struct snd_compr_ops sst_platform_compr_ops = {
+const struct snd_compress_ops sst_platform_compress_ops = {
.open = sst_platform_compr_open,
.free = sst_platform_compr_free,
diff --git a/sound/soc/intel/atom/sst-mfld-platform-pcm.c b/sound/soc/intel/atom/sst-mfld-platform-pcm.c
index 82f2b6357778..8817eaae6bb7 100644
--- a/sound/soc/intel/atom/sst-mfld-platform-pcm.c
+++ b/sound/soc/intel/atom/sst-mfld-platform-pcm.c
@@ -392,7 +392,7 @@ static int sst_enable_ssp(struct snd_pcm_substream *substream,
{
int ret = 0;
- if (!dai->active) {
+ if (!snd_soc_dai_active(dai)) {
ret = sst_handle_vb_timer(dai, true);
sst_fill_ssp_defaults(dai);
}
@@ -405,7 +405,7 @@ static int sst_be_hw_params(struct snd_pcm_substream *substream,
{
int ret = 0;
- if (dai->active == 1)
+ if (snd_soc_dai_active(dai) == 1)
ret = send_ssp_cmd(dai, dai->name, 1);
return ret;
}
@@ -414,7 +414,7 @@ static int sst_set_format(struct snd_soc_dai *dai, unsigned int fmt)
{
int ret = 0;
- if (!dai->active)
+ if (!snd_soc_dai_active(dai))
return 0;
ret = sst_fill_ssp_config(dai, fmt);
@@ -429,7 +429,7 @@ static int sst_platform_set_ssp_slot(struct snd_soc_dai *dai,
int slots, int slot_width) {
int ret = 0;
- if (!dai->active)
+ if (!snd_soc_dai_active(dai))
return ret;
ret = sst_fill_ssp_slot(dai, tx_mask, rx_mask, slots, slot_width);
@@ -442,7 +442,7 @@ static int sst_platform_set_ssp_slot(struct snd_soc_dai *dai,
static void sst_disable_ssp(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
- if (!dai->active) {
+ if (!snd_soc_dai_active(dai)) {
send_ssp_cmd(dai, dai->name, 0);
sst_handle_vb_timer(dai, false);
}
@@ -684,7 +684,7 @@ static const struct snd_soc_component_driver sst_soc_platform_drv = {
.open = sst_soc_open,
.trigger = sst_soc_trigger,
.pointer = sst_soc_pointer,
- .compr_ops = &sst_platform_compr_ops,
+ .compress_ops = &sst_platform_compress_ops,
.pcm_construct = sst_soc_pcm_new,
};
@@ -743,7 +743,7 @@ static int sst_soc_prepare(struct device *dev)
for_each_card_rtds(drv->soc_card, rtd) {
struct snd_soc_dai *dai = asoc_rtd_to_cpu(rtd, 0);
- if (dai->active) {
+ if (snd_soc_dai_active(dai)) {
send_ssp_cmd(dai, dai->name, 0);
sst_handle_vb_timer(dai, false);
}
@@ -764,7 +764,7 @@ static void sst_soc_complete(struct device *dev)
for_each_card_rtds(drv->soc_card, rtd) {
struct snd_soc_dai *dai = asoc_rtd_to_cpu(rtd, 0);
- if (dai->active) {
+ if (snd_soc_dai_active(dai)) {
sst_handle_vb_timer(dai, true);
send_ssp_cmd(dai, dai->name, 1);
}
diff --git a/sound/soc/intel/atom/sst-mfld-platform.h b/sound/soc/intel/atom/sst-mfld-platform.h
index fe4749cfa4f5..10c9ecfa7038 100644
--- a/sound/soc/intel/atom/sst-mfld-platform.h
+++ b/sound/soc/intel/atom/sst-mfld-platform.h
@@ -17,7 +17,7 @@
#include "sst-atom-controls.h"
extern struct sst_device *sst;
-extern const struct snd_compr_ops sst_platform_compr_ops;
+extern const struct snd_compress_ops sst_platform_compress_ops;
#define DRV_NAME "sst"
diff --git a/sound/soc/intel/atom/sst/Makefile b/sound/soc/intel/atom/sst/Makefile
index 795d1cf8f386..f17c905df3e2 100644
--- a/sound/soc/intel/atom/sst/Makefile
+++ b/sound/soc/intel/atom/sst/Makefile
@@ -1,4 +1,4 @@
-# SPDX-License-Identifier: GPL-2.0
+# SPDX-License-Identifier: GPL-2.0-only
snd-intel-sst-core-objs := sst.o sst_ipc.o sst_stream.o sst_drv_interface.o sst_loader.o sst_pvt.o
snd-intel-sst-pci-objs += sst_pci.o
snd-intel-sst-acpi-objs += sst_acpi.o
diff --git a/sound/soc/intel/baytrail/sst-baytrail-ipc.c b/sound/soc/intel/baytrail/sst-baytrail-ipc.c
index 74274bd38f7a..34746fd871b0 100644
--- a/sound/soc/intel/baytrail/sst-baytrail-ipc.c
+++ b/sound/soc/intel/baytrail/sst-baytrail-ipc.c
@@ -666,8 +666,8 @@ static bool byt_is_dsp_busy(struct sst_dsp *dsp)
{
u64 ipcx;
- ipcx = sst_dsp_shim_read_unlocked(dsp, SST_IPCX);
- return (ipcx & (SST_IPCX_BUSY | SST_IPCX_DONE));
+ ipcx = sst_dsp_shim_read64_unlocked(dsp, SST_IPCX);
+ return (ipcx & (SST_BYT_IPCX_BUSY | SST_BYT_IPCX_DONE));
}
int sst_byt_dsp_init(struct device *dev, struct sst_pdata *pdata)
diff --git a/sound/soc/intel/boards/Kconfig b/sound/soc/intel/boards/Kconfig
index 556c3104e641..a2a5798c9139 100644
--- a/sound/soc/intel/boards/Kconfig
+++ b/sound/soc/intel/boards/Kconfig
@@ -243,7 +243,7 @@ if SND_SOC_INTEL_SKL
config SND_SOC_INTEL_SKL_RT286_MACH
tristate "SKL with RT286 I2S mode"
- depends on I2C && ACPI
+ depends on I2C && ACPI && GPIOLIB
depends on MFD_INTEL_LPSS || COMPILE_TEST
select SND_SOC_RT286
select SND_SOC_DMIC
@@ -256,7 +256,7 @@ config SND_SOC_INTEL_SKL_RT286_MACH
config SND_SOC_INTEL_SKL_NAU88L25_SSM4567_MACH
tristate "SKL with NAU88L25 and SSM4567 in I2S Mode"
- depends on I2C && ACPI
+ depends on I2C && ACPI && GPIOLIB
depends on MFD_INTEL_LPSS || COMPILE_TEST
select SND_SOC_NAU8825
select SND_SOC_SSM4567
@@ -270,7 +270,7 @@ config SND_SOC_INTEL_SKL_NAU88L25_SSM4567_MACH
config SND_SOC_INTEL_SKL_NAU88L25_MAX98357A_MACH
tristate "SKL with NAU88L25 and MAX98357A in I2S Mode"
- depends on I2C && ACPI
+ depends on I2C && ACPI && GPIOLIB
depends on MFD_INTEL_LPSS || COMPILE_TEST
select SND_SOC_NAU8825
select SND_SOC_MAX98357A
@@ -299,7 +299,7 @@ if SND_SOC_INTEL_APL
config SND_SOC_INTEL_BXT_DA7219_MAX98357A_MACH
tristate "Broxton with DA7219 and MAX98357A in I2S Mode"
- depends on I2C && ACPI
+ depends on I2C && ACPI && GPIOLIB
depends on MFD_INTEL_LPSS || COMPILE_TEST
depends on SND_HDA_CODEC_HDMI
select SND_SOC_INTEL_BXT_DA7219_MAX98357A_COMMON
@@ -311,7 +311,7 @@ config SND_SOC_INTEL_BXT_DA7219_MAX98357A_MACH
config SND_SOC_INTEL_BXT_RT298_MACH
tristate "Broxton with RT298 I2S mode"
- depends on I2C && ACPI
+ depends on I2C && ACPI && GPIOLIB
depends on MFD_INTEL_LPSS || COMPILE_TEST
select SND_SOC_RT298
select SND_SOC_DMIC
@@ -324,11 +324,26 @@ config SND_SOC_INTEL_BXT_RT298_MACH
endif ## SND_SOC_INTEL_APL
+if SND_SOC_SOF_APOLLOLAKE
+
+config SND_SOC_INTEL_SOF_WM8804_MACH
+ tristate "SOF with Wolfson/Cirrus WM8804 codec"
+ depends on I2C && ACPI
+ depends on MFD_INTEL_LPSS || COMPILE_TEST
+ select SND_SOC_WM8804_I2C
+ help
+ This adds support for ASoC machine driver for Intel platforms
+ with the Wolfson/Cirrus WM8804 I2S audio codec.
+ Say Y or m if you have such a device. This is a recommended option.
+ If unsure select "N".
+
+endif ## SND_SOC_SOF_APOLLOLAKE
+
if SND_SOC_INTEL_KBL
config SND_SOC_INTEL_KBL_RT5663_MAX98927_MACH
tristate "KBL with RT5663 and MAX98927 in I2S Mode"
- depends on I2C && ACPI
+ depends on I2C && ACPI && GPIOLIB
depends on MFD_INTEL_LPSS || COMPILE_TEST
select SND_SOC_RT5663
select SND_SOC_MAX98927
@@ -370,7 +385,7 @@ config SND_SOC_INTEL_KBL_DA7219_MAX98357A_MACH
config SND_SOC_INTEL_KBL_DA7219_MAX98927_MACH
tristate "KBL with DA7219 and MAX98927 in I2S Mode"
- depends on I2C && ACPI
+ depends on I2C && ACPI && GPIOLIB
depends on MFD_INTEL_LPSS || COMPILE_TEST
select SND_SOC_DA7219
select SND_SOC_MAX98927
@@ -396,13 +411,13 @@ config SND_SOC_INTEL_KBL_RT5660_MACH
endif ## SND_SOC_INTEL_KBL
-if SND_SOC_SOF_GEMINILAKE && SND_SOC_SOF_HDA_LINK
+if SND_SOC_SOF_GEMINILAKE
config SND_SOC_INTEL_GLK_DA7219_MAX98357A_MACH
tristate "GLK with DA7219 and MAX98357A in I2S Mode"
- depends on I2C && ACPI
+ depends on I2C && ACPI && GPIOLIB
depends on MFD_INTEL_LPSS || COMPILE_TEST
- depends on SND_HDA_CODEC_HDMI
+ depends on SND_HDA_CODEC_HDMI && SND_SOC_SOF_HDA_AUDIO_CODEC
select SND_SOC_INTEL_BXT_DA7219_MAX98357A_COMMON
help
This adds support for ASoC machine driver for Geminilake platforms
@@ -412,10 +427,10 @@ config SND_SOC_INTEL_GLK_DA7219_MAX98357A_MACH
config SND_SOC_INTEL_GLK_RT5682_MAX98357A_MACH
tristate "GLK with RT5682 and MAX98357A in I2S Mode"
- depends on I2C && ACPI
+ depends on I2C && ACPI && GPIOLIB
depends on MFD_INTEL_LPSS || COMPILE_TEST
- depends on SND_HDA_CODEC_HDMI
- select SND_SOC_RT5682
+ depends on SND_HDA_CODEC_HDMI && SND_SOC_SOF_HDA_AUDIO_CODEC
+ select SND_SOC_RT5682_I2C
select SND_SOC_MAX98357A
select SND_SOC_DMIC
select SND_SOC_HDAC_HDMI
@@ -425,13 +440,14 @@ config SND_SOC_INTEL_GLK_RT5682_MAX98357A_MACH
Say Y if you have such a device.
If unsure select "N".
-endif ## SND_SOC_SOF_GEMINILAKE && SND_SOC_SOF_HDA_LINK
+endif ## SND_SOC_SOF_GEMINILAKE
if SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC || SND_SOC_SOF_HDA_AUDIO_CODEC
config SND_SOC_INTEL_SKL_HDA_DSP_GENERIC_MACH
tristate "SKL/KBL/BXT/APL with HDA Codecs"
depends on SND_HDA_CODEC_HDMI
+ depends on GPIOLIB
select SND_SOC_HDAC_HDMI
select SND_SOC_DMIC
# SND_SOC_HDAC_HDA is already selected
@@ -446,13 +462,13 @@ endif ## SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC || SND_SOC_SOF_HDA_AUDIO_CODEC
if SND_SOC_SOF_HDA_LINK || SND_SOC_SOF_BAYTRAIL
config SND_SOC_INTEL_SOF_RT5682_MACH
tristate "SOF with rt5682 codec in I2S Mode"
- depends on I2C && ACPI
- depends on (SND_SOC_SOF_HDA_LINK && (MFD_INTEL_LPSS || COMPILE_TEST)) ||\
+ depends on I2C && ACPI && GPIOLIB
+ depends on ((SND_HDA_CODEC_HDMI && SND_SOC_SOF_HDA_AUDIO_CODEC) &&\
+ (MFD_INTEL_LPSS || COMPILE_TEST)) ||\
(SND_SOC_SOF_BAYTRAIL && (X86_INTEL_LPSS || COMPILE_TEST))
- depends on SND_HDA_CODEC_HDMI
select SND_SOC_MAX98373
select SND_SOC_RT1015
- select SND_SOC_RT5682
+ select SND_SOC_RT5682_I2C
select SND_SOC_DMIC
select SND_SOC_HDAC_HDMI
help
@@ -480,7 +496,7 @@ if (SND_SOC_SOF_COMETLAKE_LP && SND_SOC_SOF_HDA_LINK)
config SND_SOC_INTEL_CML_LP_DA7219_MAX98357A_MACH
tristate "CML_LP with DA7219 and MAX98357A in I2S Mode"
- depends on I2C && ACPI
+ depends on I2C && ACPI && GPIOLIB
depends on MFD_INTEL_LPSS || COMPILE_TEST
select SND_SOC_INTEL_BXT_DA7219_MAX98357A_COMMON
help
@@ -491,11 +507,11 @@ config SND_SOC_INTEL_CML_LP_DA7219_MAX98357A_MACH
config SND_SOC_INTEL_SOF_CML_RT1011_RT5682_MACH
tristate "CML with RT1011 and RT5682 in I2S Mode"
- depends on I2C && ACPI
+ depends on I2C && ACPI && GPIOLIB
depends on MFD_INTEL_LPSS || COMPILE_TEST
- depends on SND_HDA_CODEC_HDMI
+ depends on SND_HDA_CODEC_HDMI && SND_SOC_SOF_HDA_AUDIO_CODEC
select SND_SOC_RT1011
- select SND_SOC_RT5682
+ select SND_SOC_RT5682_I2C
select SND_SOC_DMIC
select SND_SOC_HDAC_HDMI
help
@@ -510,9 +526,9 @@ if SND_SOC_SOF_JASPERLAKE
config SND_SOC_INTEL_SOF_DA7219_MAX98373_MACH
tristate "SOF with DA7219 and MAX98373/MAX98360A in I2S Mode"
- depends on I2C && ACPI
+ depends on I2C && ACPI && GPIOLIB
depends on MFD_INTEL_LPSS || COMPILE_TEST
- depends on SND_HDA_CODEC_HDMI
+ depends on SND_HDA_CODEC_HDMI && SND_SOC_SOF_HDA_AUDIO_CODEC
select SND_SOC_DA7219
select SND_SOC_MAX98373
select SND_SOC_DMIC
@@ -524,15 +540,30 @@ config SND_SOC_INTEL_SOF_DA7219_MAX98373_MACH
endif ## SND_SOC_SOF_JASPERLAKE
+if SND_SOC_SOF_ELKHARTLAKE
+
+config SND_SOC_INTEL_EHL_RT5660_MACH
+ tristate "EHL with RT5660 in I2S mode"
+ depends on I2C && ACPI && GPIOLIB
+ depends on MFD_INTEL_LPSS || COMPILE_TEST
+ depends on SND_HDA_CODEC_HDMI && SND_SOC_SOF_HDA_AUDIO_CODEC
+ select SND_SOC_RT5660
+ select SND_SOC_DMIC
+ help
+ This adds support for ASoC machine driver for Elkhart Lake
+ platform with RT5660 I2S audio codec.
+
+endif ## SND_SOC_SOF_ELKHARTLAKE
+
if SND_SOC_SOF_INTEL_SOUNDWIRE
config SND_SOC_INTEL_SOUNDWIRE_SOF_MACH
tristate "SoundWire generic machine driver"
- depends on I2C && ACPI
+ depends on I2C && ACPI && GPIOLIB
depends on MFD_INTEL_LPSS || COMPILE_TEST
depends on SND_SOC_INTEL_USER_FRIENDLY_LONG_NAMES || COMPILE_TEST
depends on SOUNDWIRE
- depends on SND_HDA_CODEC_HDMI
+ depends on SND_HDA_CODEC_HDMI && SND_SOC_SOF_HDA_AUDIO_CODEC
select SND_SOC_RT700_SDW
select SND_SOC_RT711_SDW
select SND_SOC_RT1308_SDW
diff --git a/sound/soc/intel/boards/Makefile b/sound/soc/intel/boards/Makefile
index 1ef6e60bc2a0..15684610f8c6 100644
--- a/sound/soc/intel/boards/Makefile
+++ b/sound/soc/intel/boards/Makefile
@@ -1,4 +1,4 @@
-# SPDX-License-Identifier: GPL-2.0
+# SPDX-License-Identifier: GPL-2.0-only
snd-soc-sst-haswell-objs := haswell.o
snd-soc-sst-byt-rt5640-mach-objs := byt-rt5640.o
snd-soc-sst-byt-max98090-mach-objs := byt-max98090.o
@@ -8,6 +8,7 @@ snd-soc-sst-broadwell-objs := broadwell.o
snd-soc-sst-bxt-da7219_max98357a-objs := bxt_da7219_max98357a.o hda_dsp_common.o
snd-soc-sst-bxt-rt298-objs := bxt_rt298.o hda_dsp_common.o
snd-soc-sst-sof-pcm512x-objs := sof_pcm512x.o hda_dsp_common.o
+snd-soc-sst-sof-wm8804-objs := sof_wm8804.o
snd-soc-sst-glk-rt5682_max98357a-objs := glk_rt5682_max98357a.o hda_dsp_common.o
snd-soc-sst-bytcr-rt5640-objs := bytcr_rt5640.o
snd-soc-sst-bytcr-rt5651-objs := bytcr_rt5651.o
@@ -31,6 +32,7 @@ snd-soc-skl_hda_dsp-objs := skl_hda_dsp_generic.o skl_hda_dsp_common.o hda_dsp_c
snd-skl_nau88l25_max98357a-objs := skl_nau88l25_max98357a.o
snd-soc-skl_nau88l25_ssm4567-objs := skl_nau88l25_ssm4567.o
snd-soc-sof_da7219_max98373-objs := sof_da7219_max98373.o hda_dsp_common.o
+snd-soc-ehl-rt5660-objs := ehl_rt5660.o hda_dsp_common.o
snd-soc-sof-sdw-objs += sof_sdw.o \
sof_sdw_rt711.o sof_sdw_rt700.o \
sof_sdw_rt1308.o sof_sdw_rt715.o \
@@ -43,6 +45,7 @@ obj-$(CONFIG_SND_SOC_INTEL_BYT_MAX98090_MACH) += snd-soc-sst-byt-max98090-mach.o
obj-$(CONFIG_SND_SOC_INTEL_BXT_DA7219_MAX98357A_COMMON) += snd-soc-sst-bxt-da7219_max98357a.o
obj-$(CONFIG_SND_SOC_INTEL_BXT_RT298_MACH) += snd-soc-sst-bxt-rt298.o
obj-$(CONFIG_SND_SOC_INTEL_SOF_PCM512x_MACH) += snd-soc-sst-sof-pcm512x.o
+obj-$(CONFIG_SND_SOC_INTEL_SOF_WM8804_MACH) += snd-soc-sst-sof-wm8804.o
obj-$(CONFIG_SND_SOC_INTEL_GLK_RT5682_MAX98357A_MACH) += snd-soc-sst-glk-rt5682_max98357a.o
obj-$(CONFIG_SND_SOC_INTEL_BROADWELL_MACH) += snd-soc-sst-broadwell.o
obj-$(CONFIG_SND_SOC_INTEL_BDW_RT5650_MACH) += snd-soc-sst-bdw-rt5650-mach.o
@@ -68,4 +71,5 @@ obj-$(CONFIG_SND_SOC_INTEL_SKL_NAU88L25_MAX98357A_MACH) += snd-skl_nau88l25_max9
obj-$(CONFIG_SND_SOC_INTEL_SKL_NAU88L25_SSM4567_MACH) += snd-soc-skl_nau88l25_ssm4567.o
obj-$(CONFIG_SND_SOC_INTEL_SKL_HDA_DSP_GENERIC_MACH) += snd-soc-skl_hda_dsp.o
obj-$(CONFIG_SND_SOC_INTEL_SOF_DA7219_MAX98373_MACH) += snd-soc-sof_da7219_max98373.o
+obj-$(CONFIG_SND_SOC_INTEL_EHL_RT5660_MACH) += snd-soc-ehl-rt5660.o
obj-$(CONFIG_SND_SOC_INTEL_SOUNDWIRE_SOF_MACH) += snd-soc-sof-sdw.o
diff --git a/sound/soc/intel/boards/bdw-rt5650.c b/sound/soc/intel/boards/bdw-rt5650.c
index af2f50293208..a97e912adf4b 100644
--- a/sound/soc/intel/boards/bdw-rt5650.c
+++ b/sound/soc/intel/boards/bdw-rt5650.c
@@ -162,6 +162,34 @@ static int bdw_rt5650_rtd_init(struct snd_soc_pcm_runtime *rtd)
}
#endif
+static const unsigned int channels[] = {
+ 2, 4,
+};
+
+static const struct snd_pcm_hw_constraint_list constraints_channels = {
+ .count = ARRAY_SIZE(channels),
+ .list = channels,
+ .mask = 0,
+};
+
+static int bdw_rt5650_fe_startup(struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+
+ /* Board supports stereo and quad configurations for capture */
+ if (substream->stream != SNDRV_PCM_STREAM_CAPTURE)
+ return 0;
+
+ runtime->hw.channels_max = 4;
+ return snd_pcm_hw_constraint_list(runtime, 0,
+ SNDRV_PCM_HW_PARAM_CHANNELS,
+ &constraints_channels);
+}
+
+static const struct snd_soc_ops bdw_rt5650_fe_ops = {
+ .startup = bdw_rt5650_fe_startup,
+};
+
static int bdw_rt5650_init(struct snd_soc_pcm_runtime *rtd)
{
struct bdw_rt5650_priv *bdw_rt5650 =
@@ -234,6 +262,7 @@ static struct snd_soc_dai_link bdw_rt5650_dais[] = {
.name = "System PCM",
.stream_name = "System Playback",
.dynamic = 1,
+ .ops = &bdw_rt5650_fe_ops,
#if !IS_ENABLED(CONFIG_SND_SOC_SOF_BROADWELL)
.init = bdw_rt5650_rtd_init,
#endif
diff --git a/sound/soc/intel/boards/bdw-rt5677.c b/sound/soc/intel/boards/bdw-rt5677.c
index cc41a348295e..5f96d7ac0a22 100644
--- a/sound/soc/intel/boards/bdw-rt5677.c
+++ b/sound/soc/intel/boards/bdw-rt5677.c
@@ -222,6 +222,31 @@ static int bdw_rt5677_rtd_init(struct snd_soc_pcm_runtime *rtd)
}
#endif
+static const unsigned int channels[] = {
+ 2,
+};
+
+static const struct snd_pcm_hw_constraint_list constraints_channels = {
+ .count = ARRAY_SIZE(channels),
+ .list = channels,
+ .mask = 0,
+};
+
+static int bdw_rt5677_fe_startup(struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+
+ /* Board supports stereo configuration only */
+ runtime->hw.channels_max = 2;
+ return snd_pcm_hw_constraint_list(runtime, 0,
+ SNDRV_PCM_HW_PARAM_CHANNELS,
+ &constraints_channels);
+}
+
+static const struct snd_soc_ops bdw_rt5677_fe_ops = {
+ .startup = bdw_rt5677_fe_startup,
+};
+
static int bdw_rt5677_init(struct snd_soc_pcm_runtime *rtd)
{
struct bdw_rt5677_priv *bdw_rt5677 =
@@ -321,6 +346,7 @@ static struct snd_soc_dai_link bdw_rt5677_dais[] = {
},
.dpcm_capture = 1,
.dpcm_playback = 1,
+ .ops = &bdw_rt5677_fe_ops,
SND_SOC_DAILINK_REG(fe, dummy, platform),
},
diff --git a/sound/soc/intel/boards/broadwell.c b/sound/soc/intel/boards/broadwell.c
index f9a8336a0541..42f8723beef2 100644
--- a/sound/soc/intel/boards/broadwell.c
+++ b/sound/soc/intel/boards/broadwell.c
@@ -143,6 +143,31 @@ static int broadwell_rtd_init(struct snd_soc_pcm_runtime *rtd)
}
#endif
+static const unsigned int channels[] = {
+ 2,
+};
+
+static const struct snd_pcm_hw_constraint_list constraints_channels = {
+ .count = ARRAY_SIZE(channels),
+ .list = channels,
+ .mask = 0,
+};
+
+static int broadwell_fe_startup(struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+
+ /* Board supports stereo configuration only */
+ runtime->hw.channels_max = 2;
+ return snd_pcm_hw_constraint_list(runtime, 0,
+ SNDRV_PCM_HW_PARAM_CHANNELS,
+ &constraints_channels);
+}
+
+static const struct snd_soc_ops broadwell_fe_ops = {
+ .startup = broadwell_fe_startup,
+};
+
SND_SOC_DAILINK_DEF(system,
DAILINK_COMP_ARRAY(COMP_CPU("System Pin")));
@@ -180,6 +205,7 @@ static struct snd_soc_dai_link broadwell_rt286_dais[] = {
.init = broadwell_rtd_init,
#endif
.trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
+ .ops = &broadwell_fe_ops,
.dpcm_playback = 1,
.dpcm_capture = 1,
SND_SOC_DAILINK_REG(system, dummy, platform),
@@ -230,7 +256,8 @@ static struct snd_soc_dai_link broadwell_rt286_dais[] = {
},
};
-static int broadwell_suspend(struct snd_soc_card *card){
+static int broadwell_disable_jack(struct snd_soc_card *card)
+{
struct snd_soc_component *component;
for_each_card_components(card, component) {
@@ -241,9 +268,15 @@ static int broadwell_suspend(struct snd_soc_card *card){
break;
}
}
+
return 0;
}
+static int broadwell_suspend(struct snd_soc_card *card)
+{
+ return broadwell_disable_jack(card);
+}
+
static int broadwell_resume(struct snd_soc_card *card){
struct snd_soc_component *component;
@@ -292,8 +325,16 @@ static int broadwell_audio_probe(struct platform_device *pdev)
return devm_snd_soc_register_card(&pdev->dev, &broadwell_rt286);
}
+static int broadwell_audio_remove(struct platform_device *pdev)
+{
+ struct snd_soc_card *card = platform_get_drvdata(pdev);
+
+ return broadwell_disable_jack(card);
+}
+
static struct platform_driver broadwell_audio = {
.probe = broadwell_audio_probe,
+ .remove = broadwell_audio_remove,
.driver = {
.name = "broadwell-audio",
},
diff --git a/sound/soc/intel/boards/bytcht_cx2072x.c b/sound/soc/intel/boards/bytcht_cx2072x.c
index 3b3df7c9008c..fad937610494 100644
--- a/sound/soc/intel/boards/bytcht_cx2072x.c
+++ b/sound/soc/intel/boards/bytcht_cx2072x.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: GPL-2.0-only
//
// ASoC DPCM Machine driver for Baytrail / Cherrytrail platforms with
// CX2072X codec
@@ -261,6 +261,9 @@ static int snd_byt_cht_cx2072x_probe(struct platform_device *pdev)
static struct platform_driver snd_byt_cht_cx2072x_driver = {
.driver = {
.name = "bytcht_cx2072x",
+#if IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL)
+ .pm = &snd_soc_pm_ops,
+#endif
},
.probe = snd_byt_cht_cx2072x_probe,
};
diff --git a/sound/soc/intel/boards/bytcht_da7213.c b/sound/soc/intel/boards/bytcht_da7213.c
index 5e96e7d02733..f3791ff2bad1 100644
--- a/sound/soc/intel/boards/bytcht_da7213.c
+++ b/sound/soc/intel/boards/bytcht_da7213.c
@@ -272,6 +272,9 @@ static int bytcht_da7213_probe(struct platform_device *pdev)
static struct platform_driver bytcht_da7213_driver = {
.driver = {
.name = "bytcht_da7213",
+#if IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL)
+ .pm = &snd_soc_pm_ops,
+#endif
},
.probe = bytcht_da7213_probe,
};
diff --git a/sound/soc/intel/boards/bytcht_es8316.c b/sound/soc/intel/boards/bytcht_es8316.c
index ddcd070100ef..9e5fc9430628 100644
--- a/sound/soc/intel/boards/bytcht_es8316.c
+++ b/sound/soc/intel/boards/bytcht_es8316.c
@@ -605,6 +605,9 @@ static int snd_byt_cht_es8316_mc_remove(struct platform_device *pdev)
static struct platform_driver snd_byt_cht_es8316_mc_driver = {
.driver = {
.name = "bytcht_es8316",
+#if IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL)
+ .pm = &snd_soc_pm_ops,
+#endif
},
.probe = snd_byt_cht_es8316_mc_probe,
.remove = snd_byt_cht_es8316_mc_remove,
diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c
index 08f4ae964b02..30f70bbdf89c 100644
--- a/sound/soc/intel/boards/bytcr_rt5640.c
+++ b/sound/soc/intel/boards/bytcr_rt5640.c
@@ -742,6 +742,18 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = {
BYT_RT5640_SSP0_AIF1 |
BYT_RT5640_MCLK_EN),
},
+ { /* Toshiba Encore WT8-A */
+ .matches = {
+ DMI_EXACT_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "TOSHIBA WT8-A"),
+ },
+ .driver_data = (void *)(BYT_RT5640_DMIC1_MAP |
+ BYT_RT5640_JD_SRC_JD2_IN4N |
+ BYT_RT5640_OVCD_TH_2000UA |
+ BYT_RT5640_OVCD_SF_0P75 |
+ BYT_RT5640_JD_NOT_INV |
+ BYT_RT5640_MCLK_EN),
+ },
{ /* Catch-all for generic Insyde tablets, must be last */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Insyde"),
@@ -898,9 +910,6 @@ static int byt_rt5640_init(struct snd_soc_pcm_runtime *runtime)
if (ret)
return ret;
- snd_soc_dapm_ignore_suspend(&card->dapm, "Headphone");
- snd_soc_dapm_ignore_suspend(&card->dapm, "Speaker");
-
if (byt_rt5640_quirk & BYT_RT5640_MCLK_EN) {
/*
* The firmware might enable the clock at
@@ -1053,7 +1062,6 @@ static struct snd_soc_dai_link byt_rt5640_dais[] = {
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBS_CFS,
.be_hw_params_fixup = byt_rt5640_codec_fixup,
- .ignore_suspend = 1,
.nonatomic = true,
.dpcm_playback = 1,
.dpcm_capture = 1,
@@ -1311,6 +1319,9 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev)
static struct platform_driver snd_byt_rt5640_mc_driver = {
.driver = {
.name = "bytcr_rt5640",
+#if IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL)
+ .pm = &snd_soc_pm_ops,
+#endif
},
.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 214ef41e23e6..520e916e329c 100644
--- a/sound/soc/intel/boards/bytcr_rt5651.c
+++ b/sound/soc/intel/boards/bytcr_rt5651.c
@@ -601,8 +601,6 @@ static int byt_rt5651_init(struct snd_soc_pcm_runtime *runtime)
dev_err(card->dev, "unable to add card controls\n");
return ret;
}
- snd_soc_dapm_ignore_suspend(&card->dapm, "Headphone");
- snd_soc_dapm_ignore_suspend(&card->dapm, "Speaker");
if (byt_rt5651_quirk & BYT_RT5651_MCLK_EN) {
/*
@@ -775,7 +773,6 @@ static struct snd_soc_dai_link byt_rt5651_dais[] = {
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBS_CFS,
.be_hw_params_fixup = byt_rt5651_codec_fixup,
- .ignore_suspend = 1,
.nonatomic = true,
.dpcm_playback = 1,
.dpcm_capture = 1,
@@ -1100,6 +1097,9 @@ static int snd_byt_rt5651_mc_probe(struct platform_device *pdev)
static struct platform_driver snd_byt_rt5651_mc_driver = {
.driver = {
.name = "bytcr_rt5651",
+#if IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL)
+ .pm = &snd_soc_pm_ops,
+#endif
},
.probe = snd_byt_rt5651_mc_probe,
};
diff --git a/sound/soc/intel/boards/cht_bsw_max98090_ti.c b/sound/soc/intel/boards/cht_bsw_max98090_ti.c
index 135701738a44..767ac2ae03e2 100644
--- a/sound/soc/intel/boards/cht_bsw_max98090_ti.c
+++ b/sound/soc/intel/boards/cht_bsw_max98090_ti.c
@@ -616,6 +616,9 @@ static int snd_cht_mc_remove(struct platform_device *pdev)
static struct platform_driver snd_cht_mc_driver = {
.driver = {
.name = "cht-bsw-max98090",
+#if IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL)
+ .pm = &snd_soc_pm_ops,
+#endif
},
.probe = snd_cht_mc_probe,
.remove = snd_cht_mc_remove,
diff --git a/sound/soc/intel/boards/cht_bsw_nau8824.c b/sound/soc/intel/boards/cht_bsw_nau8824.c
index f456150f89c2..2f7c94d335c1 100644
--- a/sound/soc/intel/boards/cht_bsw_nau8824.c
+++ b/sound/soc/intel/boards/cht_bsw_nau8824.c
@@ -108,7 +108,7 @@ static int cht_codec_init(struct snd_soc_pcm_runtime *runtime)
}
/* NAU88L24 supports 4 butons headset detection
- * KEY_MEDIA
+ * KEY_PLAYPAUSE
* KEY_VOICECOMMAND
* KEY_VOLUMEUP
* KEY_VOLUMEDOWN
@@ -122,7 +122,7 @@ static int cht_codec_init(struct snd_soc_pcm_runtime *runtime)
"Headset Jack creation failed %d\n", ret);
return ret;
}
- snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_MEDIA);
+ snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOICECOMMAND);
snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEUP);
snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN);
@@ -282,6 +282,9 @@ static int snd_cht_mc_probe(struct platform_device *pdev)
static struct platform_driver snd_cht_mc_driver = {
.driver = {
.name = "cht-bsw-nau8824",
+#if IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL)
+ .pm = &snd_soc_pm_ops,
+#endif
},
.probe = snd_cht_mc_probe,
};
diff --git a/sound/soc/intel/boards/cht_bsw_rt5645.c b/sound/soc/intel/boards/cht_bsw_rt5645.c
index e64eca56e426..22de138ffa33 100644
--- a/sound/soc/intel/boards/cht_bsw_rt5645.c
+++ b/sound/soc/intel/boards/cht_bsw_rt5645.c
@@ -680,6 +680,9 @@ static int snd_cht_mc_probe(struct platform_device *pdev)
static struct platform_driver snd_cht_mc_driver = {
.driver = {
.name = "cht-bsw-rt5645",
+#if IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL)
+ .pm = &snd_soc_pm_ops,
+#endif
},
.probe = snd_cht_mc_probe,
};
diff --git a/sound/soc/intel/boards/cht_bsw_rt5672.c b/sound/soc/intel/boards/cht_bsw_rt5672.c
index 097023a3ec14..7a43c70a1378 100644
--- a/sound/soc/intel/boards/cht_bsw_rt5672.c
+++ b/sound/soc/intel/boards/cht_bsw_rt5672.c
@@ -459,6 +459,9 @@ static int snd_cht_mc_probe(struct platform_device *pdev)
static struct platform_driver snd_cht_mc_driver = {
.driver = {
.name = "cht-bsw-rt5672",
+#if IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL)
+ .pm = &snd_soc_pm_ops,
+#endif
},
.probe = snd_cht_mc_probe,
};
diff --git a/sound/soc/intel/boards/cml_rt1011_rt5682.c b/sound/soc/intel/boards/cml_rt1011_rt5682.c
index 8167b2977e1d..68eff29daf8f 100644
--- a/sound/soc/intel/boards/cml_rt1011_rt5682.c
+++ b/sound/soc/intel/boards/cml_rt1011_rt5682.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: GPL-2.0-only
// Copyright(c) 2019 Intel Corporation.
/*
@@ -30,6 +30,36 @@
#define CML_RT5682_CODEC_DAI "rt5682-aif1"
#define NAME_SIZE 32
+#define SOF_RT1011_SPEAKER_WL BIT(0)
+#define SOF_RT1011_SPEAKER_WR BIT(1)
+#define SOF_RT1011_SPEAKER_TL BIT(2)
+#define SOF_RT1011_SPEAKER_TR BIT(3)
+#define SPK_CH 4
+
+/* Default: Woofer speakers */
+static unsigned long sof_rt1011_quirk = SOF_RT1011_SPEAKER_WL |
+ SOF_RT1011_SPEAKER_WR;
+
+static int sof_rt1011_quirk_cb(const struct dmi_system_id *id)
+{
+ sof_rt1011_quirk = (unsigned long)id->driver_data;
+ return 1;
+}
+
+static const struct dmi_system_id sof_rt1011_quirk_table[] = {
+ {
+ .callback = sof_rt1011_quirk_cb,
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Google"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Helios"),
+ },
+ .driver_data = (void *)(SOF_RT1011_SPEAKER_WL | SOF_RT1011_SPEAKER_WR |
+ SOF_RT1011_SPEAKER_TL | SOF_RT1011_SPEAKER_TR),
+ },
+ {
+ }
+};
+
static struct snd_soc_jack hdmi_jack[3];
struct hdmi_pcm {
@@ -48,15 +78,16 @@ struct card_private {
static const struct snd_kcontrol_new cml_controls[] = {
SOC_DAPM_PIN_SWITCH("Headphone Jack"),
SOC_DAPM_PIN_SWITCH("Headset Mic"),
- SOC_DAPM_PIN_SWITCH("TL Ext Spk"),
- SOC_DAPM_PIN_SWITCH("TR Ext Spk"),
SOC_DAPM_PIN_SWITCH("WL Ext Spk"),
SOC_DAPM_PIN_SWITCH("WR Ext Spk"),
};
+static const struct snd_kcontrol_new cml_rt1011_tt_controls[] = {
+ SOC_DAPM_PIN_SWITCH("TL Ext Spk"),
+ SOC_DAPM_PIN_SWITCH("TR Ext Spk"),
+};
+
static const struct snd_soc_dapm_widget cml_rt1011_rt5682_widgets[] = {
- SND_SOC_DAPM_SPK("TL Ext Spk", NULL),
- SND_SOC_DAPM_SPK("TR Ext Spk", NULL),
SND_SOC_DAPM_SPK("WL Ext Spk", NULL),
SND_SOC_DAPM_SPK("WR Ext Spk", NULL),
SND_SOC_DAPM_HP("Headphone Jack", NULL),
@@ -64,10 +95,13 @@ static const struct snd_soc_dapm_widget cml_rt1011_rt5682_widgets[] = {
SND_SOC_DAPM_MIC("SoC DMIC", NULL),
};
+static const struct snd_soc_dapm_widget cml_rt1011_tt_widgets[] = {
+ SND_SOC_DAPM_SPK("TL Ext Spk", NULL),
+ SND_SOC_DAPM_SPK("TR Ext Spk", NULL),
+};
+
static const struct snd_soc_dapm_route cml_rt1011_rt5682_map[] = {
- /*speaker*/
- {"TL Ext Spk", NULL, "TL SPO"},
- {"TR Ext Spk", NULL, "TR SPO"},
+ /*WL/WR speaker*/
{"WL Ext Spk", NULL, "WL SPO"},
{"WR Ext Spk", NULL, "WR SPO"},
@@ -82,6 +116,12 @@ static const struct snd_soc_dapm_route cml_rt1011_rt5682_map[] = {
{"DMic", NULL, "SoC DMIC"},
};
+static const struct snd_soc_dapm_route cml_rt1011_tt_map[] = {
+ /*TL/TR speaker*/
+ {"TL Ext Spk", NULL, "TL SPO" },
+ {"TR Ext Spk", NULL, "TR SPO" },
+};
+
static int cml_rt5682_codec_init(struct snd_soc_pcm_runtime *rtd)
{
struct card_private *ctx = snd_soc_card_get_drvdata(rtd->card);
@@ -121,6 +161,35 @@ static int cml_rt5682_codec_init(struct snd_soc_pcm_runtime *rtd)
return ret;
};
+static int cml_rt1011_spk_init(struct snd_soc_pcm_runtime *rtd)
+{
+ int ret = 0;
+ struct snd_soc_card *card = rtd->card;
+
+ if (sof_rt1011_quirk & (SOF_RT1011_SPEAKER_TL |
+ SOF_RT1011_SPEAKER_TR)) {
+
+ ret = snd_soc_add_card_controls(card, cml_rt1011_tt_controls,
+ ARRAY_SIZE(cml_rt1011_tt_controls));
+ if (ret)
+ return ret;
+
+ ret = snd_soc_dapm_new_controls(&card->dapm,
+ cml_rt1011_tt_widgets,
+ ARRAY_SIZE(cml_rt1011_tt_widgets));
+ if (ret)
+ return ret;
+
+ ret = snd_soc_dapm_add_routes(&card->dapm, cml_rt1011_tt_map,
+ ARRAY_SIZE(cml_rt1011_tt_map));
+
+ if (ret)
+ return ret;
+ }
+
+ return ret;
+}
+
static int cml_rt5682_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
@@ -191,30 +260,38 @@ static int cml_rt1011_hw_params(struct snd_pcm_substream *substream,
* The feedback is captured for each codec individually.
* Hence all 4 codecs use 1 Tx slot each for feedback.
*/
- if (!strcmp(codec_dai->component->name, "i2c-10EC1011:00")) {
- ret = snd_soc_dai_set_tdm_slot(codec_dai,
- 0x4, 0x1, 4, 24);
- if (ret < 0)
- break;
- }
- if (!strcmp(codec_dai->component->name, "i2c-10EC1011:02")) {
- ret = snd_soc_dai_set_tdm_slot(codec_dai,
- 0x1, 0x1, 4, 24);
- if (ret < 0)
- break;
+ if (sof_rt1011_quirk & (SOF_RT1011_SPEAKER_WL |
+ SOF_RT1011_SPEAKER_WR)) {
+ if (!strcmp(codec_dai->component->name, "i2c-10EC1011:00")) {
+ ret = snd_soc_dai_set_tdm_slot(codec_dai,
+ 0x4, 0x1, 4, 24);
+ if (ret < 0)
+ break;
+ }
+
+ if (!strcmp(codec_dai->component->name, "i2c-10EC1011:01")) {
+ ret = snd_soc_dai_set_tdm_slot(codec_dai,
+ 0x8, 0x2, 4, 24);
+ if (ret < 0)
+ break;
+ }
}
- /* TDM Rx slot 2 is used for Right Woofer & Tweeters pair */
- if (!strcmp(codec_dai->component->name, "i2c-10EC1011:01")) {
- ret = snd_soc_dai_set_tdm_slot(codec_dai,
- 0x8, 0x2, 4, 24);
- if (ret < 0)
- break;
- }
- if (!strcmp(codec_dai->component->name, "i2c-10EC1011:03")) {
- ret = snd_soc_dai_set_tdm_slot(codec_dai,
- 0x2, 0x2, 4, 24);
- if (ret < 0)
- break;
+
+ if (sof_rt1011_quirk & (SOF_RT1011_SPEAKER_TL |
+ SOF_RT1011_SPEAKER_TR)) {
+ if (!strcmp(codec_dai->component->name, "i2c-10EC1011:02")) {
+ ret = snd_soc_dai_set_tdm_slot(codec_dai,
+ 0x1, 0x1, 4, 24);
+ if (ret < 0)
+ break;
+ }
+
+ if (!strcmp(codec_dai->component->name, "i2c-10EC1011:03")) {
+ ret = snd_soc_dai_set_tdm_slot(codec_dai,
+ 0x2, 0x2, 4, 24);
+ if (ret < 0)
+ break;
+ }
}
}
if (ret < 0)
@@ -302,9 +379,7 @@ SND_SOC_DAILINK_DEF(ssp1_pin,
SND_SOC_DAILINK_DEF(ssp1_codec,
DAILINK_COMP_ARRAY(
/* WL */ COMP_CODEC("i2c-10EC1011:00", CML_RT1011_CODEC_DAI),
- /* WR */ COMP_CODEC("i2c-10EC1011:01", CML_RT1011_CODEC_DAI),
- /* TL */ COMP_CODEC("i2c-10EC1011:02", CML_RT1011_CODEC_DAI),
- /* TR */ COMP_CODEC("i2c-10EC1011:03", CML_RT1011_CODEC_DAI)));
+ /* WR */ COMP_CODEC("i2c-10EC1011:01", CML_RT1011_CODEC_DAI)));
SND_SOC_DAILINK_DEF(dmic_pin,
DAILINK_COMP_ARRAY(COMP_CPU("DMIC01 Pin")));
@@ -398,6 +473,7 @@ static struct snd_soc_dai_link cml_rt1011_rt5682_dailink[] = {
.dpcm_playback = 1,
.dpcm_capture = 1, /* Capture stream provides Feedback */
.no_pcm = 1,
+ .init = cml_rt1011_spk_init,
.ops = &cml_rt1011_ops,
SND_SOC_DAILINK_REG(ssp1_pin, ssp1_codec, platform),
},
@@ -412,14 +488,6 @@ static struct snd_soc_codec_conf rt1011_conf[] = {
.dlc = COMP_CODEC_CONF("i2c-10EC1011:01"),
.name_prefix = "WR",
},
- {
- .dlc = COMP_CODEC_CONF("i2c-10EC1011:02"),
- .name_prefix = "TL",
- },
- {
- .dlc = COMP_CODEC_CONF("i2c-10EC1011:03"),
- .name_prefix = "TR",
- },
};
/* Cometlake audio machine driver for RT1011 and RT5682 */
@@ -441,10 +509,12 @@ static struct snd_soc_card snd_soc_card_cml = {
static int snd_cml_rt1011_probe(struct platform_device *pdev)
{
+ struct snd_soc_dai_link_component *rt1011_dais_components;
+ struct snd_soc_codec_conf *rt1011_dais_confs;
struct card_private *ctx;
struct snd_soc_acpi_mach *mach;
const char *platform_name;
- int ret;
+ int ret, i;
ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
if (!ctx)
@@ -455,6 +525,73 @@ static int snd_cml_rt1011_probe(struct platform_device *pdev)
snd_soc_card_cml.dev = &pdev->dev;
platform_name = mach->mach_params.platform;
+ dmi_check_system(sof_rt1011_quirk_table);
+
+ dev_info(&pdev->dev, "sof_rt1011_quirk = %lx\n", sof_rt1011_quirk);
+
+ if (sof_rt1011_quirk & (SOF_RT1011_SPEAKER_TL |
+ SOF_RT1011_SPEAKER_TR)) {
+ rt1011_dais_confs = devm_kzalloc(&pdev->dev,
+ sizeof(struct snd_soc_codec_conf) *
+ SPK_CH, GFP_KERNEL);
+
+ if (!rt1011_dais_confs)
+ return -ENOMEM;
+
+ rt1011_dais_components = devm_kzalloc(&pdev->dev,
+ sizeof(struct snd_soc_dai_link_component) *
+ SPK_CH, GFP_KERNEL);
+
+ if (!rt1011_dais_components)
+ return -ENOMEM;
+
+ for (i = 0; i < SPK_CH; i++) {
+ rt1011_dais_confs[i].dlc.name = devm_kasprintf(&pdev->dev,
+ GFP_KERNEL,
+ "i2c-10EC1011:0%d",
+ i);
+
+ if (!rt1011_dais_confs[i].dlc.name)
+ return -ENOMEM;
+
+ switch (i) {
+ case 0:
+ rt1011_dais_confs[i].name_prefix = "WL";
+ break;
+ case 1:
+ rt1011_dais_confs[i].name_prefix = "WR";
+ break;
+ case 2:
+ rt1011_dais_confs[i].name_prefix = "TL";
+ break;
+ case 3:
+ rt1011_dais_confs[i].name_prefix = "TR";
+ break;
+ default:
+ return -EINVAL;
+ }
+ rt1011_dais_components[i].name = devm_kasprintf(&pdev->dev,
+ GFP_KERNEL,
+ "i2c-10EC1011:0%d",
+ i);
+ if (!rt1011_dais_components[i].name)
+ return -ENOMEM;
+
+ rt1011_dais_components[i].dai_name = CML_RT1011_CODEC_DAI;
+ }
+
+ snd_soc_card_cml.codec_conf = rt1011_dais_confs;
+ snd_soc_card_cml.num_configs = SPK_CH;
+
+ for (i = 0; i < ARRAY_SIZE(cml_rt1011_rt5682_dailink); i++) {
+ if (!strcmp(cml_rt1011_rt5682_dailink[i].codecs->dai_name,
+ CML_RT1011_CODEC_DAI)) {
+ cml_rt1011_rt5682_dailink[i].codecs = rt1011_dais_components;
+ cml_rt1011_rt5682_dailink[i].num_codecs = SPK_CH;
+ }
+ }
+ }
+
/* set platform name for each dailink */
ret = snd_soc_fixup_dai_links_platform_name(&snd_soc_card_cml,
platform_name);
@@ -482,5 +619,6 @@ MODULE_DESCRIPTION("Cometlake Audio Machine driver - RT1011 and RT5682 in I2S mo
MODULE_AUTHOR("Naveen Manohar <naveen.m@intel.com>");
MODULE_AUTHOR("Sathya Prakash M R <sathya.prakash.m.r@intel.com>");
MODULE_AUTHOR("Shuming Fan <shumingf@realtek.com>");
+MODULE_AUTHOR("Mac Chiang <mac.chiang@intel.com>");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:cml_rt1011_rt5682");
diff --git a/sound/soc/intel/boards/ehl_rt5660.c b/sound/soc/intel/boards/ehl_rt5660.c
new file mode 100644
index 000000000000..78160e3b1615
--- /dev/null
+++ b/sound/soc/intel/boards/ehl_rt5660.c
@@ -0,0 +1,323 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// Copyright (c) 2020 Intel Corporation
+
+/*
+ * ehl_rt5660 - ASOC Machine driver for Elkhart Lake platforms
+ * with rt5660 codec
+ */
+
+#include <linux/acpi.h>
+#include <sound/core.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/gfp.h>
+#include <sound/jack.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-acpi.h>
+
+#include "hda_dsp_common.h"
+#include "../../codecs/rt5660.h"
+
+#define DUAL_CHANNEL 2
+#define HDMI_LINK_START 3
+#define HDMI_LINE_END 6
+#define NAME_SIZE 32
+#define IDISP_CODEC_MASK 0x4
+
+struct sof_card_private {
+ struct list_head hdmi_pcm_list;
+ bool idisp_codec;
+};
+
+static const struct snd_kcontrol_new rt5660_controls[] = {
+ SOC_DAPM_PIN_SWITCH("Speaker"),
+ /* There are two MICBIAS in rt5660, each for one MIC */
+ SOC_DAPM_PIN_SWITCH("Headset Mic"),
+ SOC_DAPM_PIN_SWITCH("Headset Mic2"),
+ SOC_DAPM_PIN_SWITCH("Line Out"),
+};
+
+static const struct snd_soc_dapm_widget rt5660_widgets[] = {
+ SND_SOC_DAPM_SPK("Speaker", NULL),
+ SND_SOC_DAPM_MIC("Headset Mic", NULL),
+ SND_SOC_DAPM_MIC("Headset Mic2", NULL),
+ SND_SOC_DAPM_MIC("SoC DMIC", NULL),
+ SND_SOC_DAPM_LINE("Line Out", NULL),
+};
+
+static const struct snd_soc_dapm_route rt5660_map[] = {
+ {"Speaker", NULL, "SPO"},
+
+ {"Headset Mic", NULL, "MICBIAS1"},
+ {"Headset Mic2", NULL, "MICBIAS2"},
+
+ {"IN1P", NULL, "Headset Mic"},
+ {"IN2P", NULL, "Headset Mic2"},
+
+ {"Line Out", NULL, "LOUTL"},
+ {"Line Out", NULL, "LOUTR"},
+
+ {"DMic", NULL, "SoC DMIC"},
+};
+
+struct sof_hdmi_pcm {
+ struct list_head head;
+ struct snd_soc_dai *codec_dai;
+ int device;
+};
+
+static int hdmi_init(struct snd_soc_pcm_runtime *rtd)
+{
+ struct sof_card_private *ctx = snd_soc_card_get_drvdata(rtd->card);
+ struct snd_soc_dai *dai = asoc_rtd_to_codec(rtd, 0);
+ struct sof_hdmi_pcm *pcm;
+
+ pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL);
+ if (!pcm)
+ return -ENOMEM;
+
+ /* dai_link id is 1:1 mapped to the PCM device */
+ pcm->device = rtd->dai_link->id;
+ pcm->codec_dai = dai;
+
+ list_add_tail(&pcm->head, &ctx->hdmi_pcm_list);
+
+ return 0;
+}
+
+static int card_late_probe(struct snd_soc_card *card)
+{
+ struct sof_card_private *ctx = snd_soc_card_get_drvdata(card);
+ struct sof_hdmi_pcm *pcm;
+
+ if (list_empty(&ctx->hdmi_pcm_list))
+ return -ENOENT;
+
+ if (!ctx->idisp_codec)
+ return 0;
+
+ pcm = list_first_entry(&ctx->hdmi_pcm_list, struct sof_hdmi_pcm, head);
+
+ return hda_dsp_hdmi_build_controls(card, pcm->codec_dai->component);
+}
+
+static int rt5660_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
+ int ret;
+
+ ret = snd_soc_dai_set_sysclk(codec_dai,
+ RT5660_SCLK_S_PLL1,
+ params_rate(params) * 512,
+ SND_SOC_CLOCK_IN);
+ if (ret < 0) {
+ dev_err(rtd->dev, "snd_soc_dai_set_sysclk err = %d\n", ret);
+ return ret;
+ }
+
+ ret = snd_soc_dai_set_pll(codec_dai, 0,
+ RT5660_PLL1_S_BCLK,
+ params_rate(params) * 50,
+ params_rate(params) * 512);
+ if (ret < 0)
+ dev_err(codec_dai->dev, "can't set codec pll: %d\n", ret);
+
+ return ret;
+}
+
+static struct snd_soc_ops rt5660_ops = {
+ .hw_params = rt5660_hw_params,
+};
+
+SND_SOC_DAILINK_DEF(ssp0_pin,
+ DAILINK_COMP_ARRAY(COMP_CPU("SSP0 Pin")));
+
+SND_SOC_DAILINK_DEF(rt5660_codec,
+ DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10EC5660:00", "rt5660-aif1")));
+
+SND_SOC_DAILINK_DEF(platform,
+ DAILINK_COMP_ARRAY(COMP_PLATFORM("0000:00:1f.3")));
+
+SND_SOC_DAILINK_DEF(dmic_pin,
+ DAILINK_COMP_ARRAY(COMP_CPU("DMIC01 Pin")));
+SND_SOC_DAILINK_DEF(dmic_codec,
+ DAILINK_COMP_ARRAY(COMP_CODEC("dmic-codec", "dmic-hifi")));
+SND_SOC_DAILINK_DEF(dmic16k,
+ DAILINK_COMP_ARRAY(COMP_CPU("DMIC16k Pin")));
+
+SND_SOC_DAILINK_DEF(idisp1_pin,
+ DAILINK_COMP_ARRAY(COMP_CPU("iDisp1 Pin")));
+SND_SOC_DAILINK_DEF(idisp1_codec,
+ DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi1")));
+
+SND_SOC_DAILINK_DEF(idisp2_pin,
+ DAILINK_COMP_ARRAY(COMP_CPU("iDisp2 Pin")));
+SND_SOC_DAILINK_DEF(idisp2_codec,
+ DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi2")));
+
+SND_SOC_DAILINK_DEF(idisp3_pin,
+ DAILINK_COMP_ARRAY(COMP_CPU("iDisp3 Pin")));
+SND_SOC_DAILINK_DEF(idisp3_codec,
+ DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi3")));
+
+SND_SOC_DAILINK_DEF(idisp4_pin,
+ DAILINK_COMP_ARRAY(COMP_CPU("iDisp4 Pin")));
+SND_SOC_DAILINK_DEF(idisp4_codec,
+ DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi4")));
+
+static struct snd_soc_dai_link ehl_rt5660_dailink[] = {
+ /* back ends */
+ {
+ .name = "SSP0-Codec",
+ .id = 0,
+ .no_pcm = 1,
+ .dpcm_playback = 1,
+ .dpcm_capture = 1,
+ .ops = &rt5660_ops,
+ .nonatomic = true,
+ SND_SOC_DAILINK_REG(ssp0_pin, rt5660_codec, platform),
+ },
+ {
+ .name = "dmic48k",
+ .id = 1,
+ .ignore_suspend = 1,
+ .dpcm_capture = 1,
+ .no_pcm = 1,
+ SND_SOC_DAILINK_REG(dmic_pin, dmic_codec, platform),
+ },
+ {
+ .name = "dmic16k",
+ .id = 2,
+ .ignore_suspend = 1,
+ .dpcm_capture = 1,
+ .no_pcm = 1,
+ SND_SOC_DAILINK_REG(dmic16k, dmic_codec, platform),
+ },
+ {
+ .name = "iDisp1",
+ .id = 5,
+ .init = hdmi_init,
+ .dpcm_playback = 1,
+ .no_pcm = 1,
+ SND_SOC_DAILINK_REG(idisp1_pin, idisp1_codec, platform),
+ },
+ {
+ .name = "iDisp2",
+ .id = 6,
+ .init = hdmi_init,
+ .dpcm_playback = 1,
+ .no_pcm = 1,
+ SND_SOC_DAILINK_REG(idisp2_pin, idisp2_codec, platform),
+ },
+ {
+ .name = "iDisp3",
+ .id = 7,
+ .init = hdmi_init,
+ .dpcm_playback = 1,
+ .no_pcm = 1,
+ SND_SOC_DAILINK_REG(idisp3_pin, idisp3_codec, platform),
+ },
+ {
+ .name = "iDisp4",
+ .id = 8,
+ .init = hdmi_init,
+ .dpcm_playback = 1,
+ .no_pcm = 1,
+ SND_SOC_DAILINK_REG(idisp4_pin, idisp4_codec, platform),
+ },
+};
+
+/* SoC card */
+static struct snd_soc_card snd_soc_card_ehl_rt5660 = {
+ .name = "ehl-rt5660",
+ .owner = THIS_MODULE,
+ .dai_link = ehl_rt5660_dailink,
+ .num_links = ARRAY_SIZE(ehl_rt5660_dailink),
+ .dapm_widgets = rt5660_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(rt5660_widgets),
+ .dapm_routes = rt5660_map,
+ .num_dapm_routes = ARRAY_SIZE(rt5660_map),
+ .controls = rt5660_controls,
+ .num_controls = ARRAY_SIZE(rt5660_controls),
+ .fully_routed = true,
+ .late_probe = card_late_probe,
+};
+
+/* If hdmi codec is not supported, switch to use dummy codec */
+static void hdmi_link_init(struct snd_soc_card *card,
+ struct sof_card_private *ctx,
+ struct snd_soc_acpi_mach *mach)
+{
+ struct snd_soc_dai_link *link;
+ int i;
+
+ if (mach->mach_params.common_hdmi_codec_drv &&
+ (mach->mach_params.codec_mask & IDISP_CODEC_MASK)) {
+ ctx->idisp_codec = true;
+ return;
+ }
+
+ /*
+ * if HDMI is not enabled in kernel config, or
+ * hdmi codec is not supported
+ */
+ for (i = HDMI_LINK_START; i <= HDMI_LINE_END; i++) {
+ link = &card->dai_link[i];
+ link->codecs[0].name = "snd-soc-dummy";
+ link->codecs[0].dai_name = "snd-soc-dummy-dai";
+ }
+}
+
+static int snd_ehl_rt5660_probe(struct platform_device *pdev)
+{
+ struct snd_soc_acpi_mach *mach;
+ struct snd_soc_card *card = &snd_soc_card_ehl_rt5660;
+ struct sof_card_private *ctx;
+ int ret;
+
+ card->dev = &pdev->dev;
+
+ ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
+ if (!ctx)
+ return -ENOMEM;
+ INIT_LIST_HEAD(&ctx->hdmi_pcm_list);
+ snd_soc_card_set_drvdata(card, ctx);
+
+ mach = pdev->dev.platform_data;
+ ret = snd_soc_fixup_dai_links_platform_name(card,
+ mach->mach_params.platform);
+ if (ret)
+ return ret;
+
+ hdmi_link_init(card, ctx, mach);
+
+ return devm_snd_soc_register_card(&pdev->dev, card);
+}
+
+static const struct platform_device_id ehl_board_ids[] = {
+ { .name = "ehl_rt5660" },
+ { }
+};
+
+static struct platform_driver snd_ehl_rt5660_driver = {
+ .driver = {
+ .name = "ehl_rt5660",
+ .pm = &snd_soc_pm_ops,
+ },
+ .probe = snd_ehl_rt5660_probe,
+ .id_table = ehl_board_ids,
+};
+
+module_platform_driver(snd_ehl_rt5660_driver);
+
+MODULE_DESCRIPTION("ASoC Intel(R) Elkhartlake + rt5660 Machine driver");
+MODULE_AUTHOR("libin.yang@intel.com");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:ehl_rt5660");
diff --git a/sound/soc/intel/boards/glk_rt5682_max98357a.c b/sound/soc/intel/boards/glk_rt5682_max98357a.c
index f13158e4a1fc..48eda1a8aa6c 100644
--- a/sound/soc/intel/boards/glk_rt5682_max98357a.c
+++ b/sound/soc/intel/boards/glk_rt5682_max98357a.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: GPL-2.0-only
// Copyright(c) 2018 Intel Corporation.
/*
diff --git a/sound/soc/intel/boards/hda_dsp_common.c b/sound/soc/intel/boards/hda_dsp_common.c
index 9179f07f9ee4..244b57fba64c 100644
--- a/sound/soc/intel/boards/hda_dsp_common.c
+++ b/sound/soc/intel/boards/hda_dsp_common.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: GPL-2.0-only
//
// Copyright(c) 2019 Intel Corporation. All rights reserved.
diff --git a/sound/soc/intel/boards/hda_dsp_common.h b/sound/soc/intel/boards/hda_dsp_common.h
index 431f7f09dccb..727edd256962 100644
--- a/sound/soc/intel/boards/hda_dsp_common.h
+++ b/sound/soc/intel/boards/hda_dsp_common.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright(c) 2019 Intel Corporation.
*/
diff --git a/sound/soc/intel/boards/kbl_da7219_max98357a.c b/sound/soc/intel/boards/kbl_da7219_max98357a.c
index 32cd90b8d4c4..dc3d897ad280 100644
--- a/sound/soc/intel/boards/kbl_da7219_max98357a.c
+++ b/sound/soc/intel/boards/kbl_da7219_max98357a.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: GPL-2.0-only
// Copyright(c) 2017-18 Intel Corporation.
/*
diff --git a/sound/soc/intel/boards/kbl_da7219_max98927.c b/sound/soc/intel/boards/kbl_da7219_max98927.c
index abd4e3839678..cc9b5eab8b4a 100644
--- a/sound/soc/intel/boards/kbl_da7219_max98927.c
+++ b/sound/soc/intel/boards/kbl_da7219_max98927.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: GPL-2.0-only
// Copyright(c) 2018 Intel Corporation.
/*
diff --git a/sound/soc/intel/boards/kbl_rt5660.c b/sound/soc/intel/boards/kbl_rt5660.c
index 6460e3f0c974..d2a078454784 100644
--- a/sound/soc/intel/boards/kbl_rt5660.c
+++ b/sound/soc/intel/boards/kbl_rt5660.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: GPL-2.0-only
// Copyright(c) 2018-19 Canonical Corporation.
/*
diff --git a/sound/soc/intel/boards/skl_hda_dsp_common.c b/sound/soc/intel/boards/skl_hda_dsp_common.c
index 78ff5f24c40e..07bfb2e64b3b 100644
--- a/sound/soc/intel/boards/skl_hda_dsp_common.c
+++ b/sound/soc/intel/boards/skl_hda_dsp_common.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: GPL-2.0-only
// Copyright(c) 2015-18 Intel Corporation.
/*
diff --git a/sound/soc/intel/boards/skl_hda_dsp_common.h b/sound/soc/intel/boards/skl_hda_dsp_common.h
index e8545d13062f..507750ef67f3 100644
--- a/sound/soc/intel/boards/skl_hda_dsp_common.h
+++ b/sound/soc/intel/boards/skl_hda_dsp_common.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright(c) 2015-18 Intel Corporation.
*/
diff --git a/sound/soc/intel/boards/skl_hda_dsp_generic.c b/sound/soc/intel/boards/skl_hda_dsp_generic.c
index 3be764299ab0..79c8947f840b 100644
--- a/sound/soc/intel/boards/skl_hda_dsp_generic.c
+++ b/sound/soc/intel/boards/skl_hda_dsp_generic.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: GPL-2.0-only
// Copyright(c) 2015-18 Intel Corporation.
/*
@@ -113,6 +113,8 @@ static char hda_soc_components[30];
#define IDISP_ROUTE_COUNT (IDISP_DAI_COUNT * 2)
#define IDISP_CODEC_MASK 0x4
+#define HDA_CODEC_AUTOSUSPEND_DELAY_MS 1000
+
static int skl_hda_fill_card_info(struct snd_soc_acpi_mach_params *mach_params)
{
struct snd_soc_card *card = &hda_soc_card;
@@ -168,6 +170,29 @@ static int skl_hda_fill_card_info(struct snd_soc_acpi_mach_params *mach_params)
return 0;
}
+static void skl_set_hda_codec_autosuspend_delay(struct snd_soc_card *card)
+{
+ struct snd_soc_pcm_runtime *rtd;
+ struct hdac_hda_priv *hda_pvt;
+ struct snd_soc_dai *dai;
+
+ for_each_card_rtds(card, rtd) {
+ if (!strstr(rtd->dai_link->codecs->name, "ehdaudio"))
+ continue;
+ dai = asoc_rtd_to_codec(rtd, 0);
+ hda_pvt = snd_soc_component_get_drvdata(dai->component);
+ if (hda_pvt) {
+ /*
+ * all codecs are on the same bus, so it's sufficient
+ * to look up only the first one
+ */
+ snd_hda_set_power_save(hda_pvt->codec.bus,
+ HDA_CODEC_AUTOSUSPEND_DELAY_MS);
+ break;
+ }
+ }
+}
+
static int skl_hda_audio_probe(struct platform_device *pdev)
{
struct snd_soc_acpi_mach *mach;
@@ -206,7 +231,11 @@ static int skl_hda_audio_probe(struct platform_device *pdev)
hda_soc_card.components = hda_soc_components;
}
- return devm_snd_soc_register_card(&pdev->dev, &hda_soc_card);
+ ret = devm_snd_soc_register_card(&pdev->dev, &hda_soc_card);
+ if (!ret)
+ skl_set_hda_codec_autosuspend_delay(&hda_soc_card);
+
+ return ret;
}
static struct platform_driver skl_hda_audio = {
diff --git a/sound/soc/intel/boards/sof_da7219_max98373.c b/sound/soc/intel/boards/sof_da7219_max98373.c
index b707dd3b5625..703703858595 100644
--- a/sound/soc/intel/boards/sof_da7219_max98373.c
+++ b/sound/soc/intel/boards/sof_da7219_max98373.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: GPL-2.0-only
// Copyright(c) 2019 Intel Corporation.
/*
@@ -86,6 +86,8 @@ static const struct snd_soc_dapm_widget widgets[] = {
SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0,
platform_clock_control, SND_SOC_DAPM_POST_PMD |
SND_SOC_DAPM_PRE_PMU),
+
+ SND_SOC_DAPM_MIC("SoC DMIC", NULL),
};
static const struct snd_soc_dapm_route audio_map[] = {
@@ -99,6 +101,9 @@ static const struct snd_soc_dapm_route audio_map[] = {
{ "Left Spk", NULL, "Left BE_OUT" },
{ "Right Spk", NULL, "Right BE_OUT" },
+
+ /* digital mics */
+ {"DMic", NULL, "SoC DMIC"},
};
/* For MAX98360A amp */
@@ -111,6 +116,8 @@ static const struct snd_soc_dapm_widget max98360a_widgets[] = {
SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0,
platform_clock_control, SND_SOC_DAPM_POST_PMD |
SND_SOC_DAPM_PRE_PMU),
+
+ SND_SOC_DAPM_MIC("SoC DMIC", NULL),
};
static const struct snd_soc_dapm_route max98360a_map[] = {
@@ -123,6 +130,9 @@ static const struct snd_soc_dapm_route max98360a_map[] = {
{ "Headset Mic", NULL, "Platform Clock" },
{"Spk", NULL, "Speaker"},
+
+ /* digital mics */
+ {"DMic", NULL, "SoC DMIC"},
};
static struct snd_soc_jack headset;
@@ -265,6 +275,9 @@ SND_SOC_DAILINK_DEF(dmic_pin,
SND_SOC_DAILINK_DEF(dmic_codec,
DAILINK_COMP_ARRAY(COMP_CODEC("dmic-codec", "dmic-hifi")));
+SND_SOC_DAILINK_DEF(dmic16k_pin,
+ DAILINK_COMP_ARRAY(COMP_CPU("DMIC16k Pin")));
+
SND_SOC_DAILINK_DEF(idisp1_pin,
DAILINK_COMP_ARRAY(COMP_CPU("iDisp1 Pin")));
SND_SOC_DAILINK_DEF(idisp1_codec,
@@ -337,6 +350,14 @@ static struct snd_soc_dai_link dais[] = {
.no_pcm = 1,
SND_SOC_DAILINK_REG(idisp3_pin, idisp3_codec, platform),
},
+ {
+ .name = "dmic16k",
+ .id = 6,
+ .ignore_suspend = 1,
+ .dpcm_capture = 1,
+ .no_pcm = 1,
+ SND_SOC_DAILINK_REG(dmic16k_pin, dmic_codec, platform),
+ }
};
static struct snd_soc_card card_da7219_m98373 = {
diff --git a/sound/soc/intel/boards/sof_maxim_common.c b/sound/soc/intel/boards/sof_maxim_common.c
index 463b39a7ccfd..1a549b32d1c9 100644
--- a/sound/soc/intel/boards/sof_maxim_common.c
+++ b/sound/soc/intel/boards/sof_maxim_common.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: GPL-2.0-only
//
// Copyright(c) 2020 Intel Corporation. All rights reserved.
#include <linux/string.h>
diff --git a/sound/soc/intel/boards/sof_maxim_common.h b/sound/soc/intel/boards/sof_maxim_common.h
index 406bf0e81155..785b34335368 100644
--- a/sound/soc/intel/boards/sof_maxim_common.h
+++ b/sound/soc/intel/boards/sof_maxim_common.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright(c) 2020 Intel Corporation.
*/
diff --git a/sound/soc/intel/boards/sof_pcm512x.c b/sound/soc/intel/boards/sof_pcm512x.c
index fb7811899999..9fa8a4911276 100644
--- a/sound/soc/intel/boards/sof_pcm512x.c
+++ b/sound/soc/intel/boards/sof_pcm512x.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: GPL-2.0-only
// Copyright(c) 2018-2020 Intel Corporation.
/*
@@ -126,7 +126,6 @@ static struct snd_soc_dai_link_component platform_component[] = {
}
};
-#if IS_ENABLED(CONFIG_SND_HDA_CODEC_HDMI)
static int sof_card_late_probe(struct snd_soc_card *card)
{
struct sof_card_private *ctx = snd_soc_card_get_drvdata(card);
@@ -146,12 +145,6 @@ static int sof_card_late_probe(struct snd_soc_card *card)
return hda_dsp_hdmi_build_controls(card, pcm->codec_dai->component);
}
-#else
-static int sof_card_late_probe(struct snd_soc_card *card)
-{
- return 0;
-}
-#endif
static const struct snd_kcontrol_new sof_controls[] = {
SOC_DAPM_PIN_SWITCH("Ext Spk"),
@@ -374,14 +367,12 @@ static int sof_audio_probe(struct platform_device *pdev)
sof_pcm512x_quirk = SOF_PCM512X_SSP_CODEC(2);
} else {
dmic_be_num = 2;
-#if IS_ENABLED(CONFIG_SND_HDA_CODEC_HDMI)
if (mach->mach_params.common_hdmi_codec_drv &&
(mach->mach_params.codec_mask & IDISP_CODEC_MASK))
ctx->idisp_codec = true;
/* links are always present in topology */
hdmi_num = 3;
-#endif
}
dmi_check_system(sof_pcm512x_quirk_table);
diff --git a/sound/soc/intel/boards/sof_rt5682.c b/sound/soc/intel/boards/sof_rt5682.c
index 8c29431b5847..13a48b0c35ae 100644
--- a/sound/soc/intel/boards/sof_rt5682.c
+++ b/sound/soc/intel/boards/sof_rt5682.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: GPL-2.0-only
// Copyright(c) 2019-2020 Intel Corporation.
/*
diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c
index a64dc563b47e..e1c1a8ba78e6 100644
--- a/sound/soc/intel/boards/sof_sdw.c
+++ b/sound/soc/intel/boards/sof_sdw.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: GPL-2.0-only
// Copyright (c) 2020 Intel Corporation
/*
@@ -411,25 +411,36 @@ static int create_codec_dai_name(struct device *dev,
static int set_codec_init_func(const struct snd_soc_acpi_link_adr *link,
struct snd_soc_dai_link *dai_links,
- bool playback)
+ bool playback, int group_id)
{
int i;
- for (i = 0; i < link->num_adr; i++) {
- unsigned int part_id;
- int codec_index;
-
- part_id = SDW_PART_ID(link->adr_d[i].adr);
- codec_index = find_codec_info_part(part_id);
+ do {
+ /*
+ * Initialize the codec. If codec is part of an aggregated
+ * group (group_id>0), initialize all codecs belonging to
+ * same group.
+ */
+ for (i = 0; i < link->num_adr; i++) {
+ unsigned int part_id;
+ int codec_index;
- if (codec_index < 0)
- return codec_index;
+ part_id = SDW_PART_ID(link->adr_d[i].adr);
+ codec_index = find_codec_info_part(part_id);
- if (codec_info_list[codec_index].init)
- codec_info_list[codec_index].init(link, dai_links,
- &codec_info_list[codec_index],
- playback);
- }
+ if (codec_index < 0)
+ return codec_index;
+ /* The group_id is > 0 iff the codec is aggregated */
+ if (link->adr_d[i].endpoints->group_id != group_id)
+ continue;
+ if (codec_info_list[codec_index].init)
+ codec_info_list[codec_index].init(link,
+ dai_links,
+ &codec_info_list[codec_index],
+ playback);
+ }
+ link++;
+ } while (link->mask && group_id);
return 0;
}
@@ -623,7 +634,7 @@ static int create_sdw_dailink(struct device *dev, int *be_index,
NULL, &sdw_ops);
ret = set_codec_init_func(link, dai_links + (*be_index)++,
- playback);
+ playback, group_id);
if (ret < 0) {
dev_err(dev, "failed to init codec %d", codec_index);
return ret;
@@ -652,9 +663,7 @@ static int sof_card_dai_links_create(struct device *dev,
struct snd_soc_card *card)
{
int ssp_num, sdw_be_num = 0, hdmi_num = 0, dmic_num;
-#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC)
struct snd_soc_dai_link_component *idisp_components;
-#endif
struct snd_soc_dai_link_component *ssp_components;
struct snd_soc_acpi_mach_params *mach_params;
const struct snd_soc_acpi_link_adr *adr_link;
@@ -675,10 +684,8 @@ static int sof_card_dai_links_create(struct device *dev,
for (i = 0; i < ARRAY_SIZE(codec_info_list); i++)
codec_info_list[i].amp_num = 0;
-#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC)
hdmi_num = sof_sdw_quirk & SOF_SDW_TGL_HDMI ?
SOF_TGL_HDMI_COUNT : SOF_PRE_TGL_HDMI_COUNT;
-#endif
ssp_mask = SOF_SSP_GET_PORT(sof_sdw_quirk);
/*
@@ -838,7 +845,6 @@ DMIC:
INC_ID(be_id, cpu_id, link_id);
}
-#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC)
/* HDMI */
if (hdmi_num > 0) {
idisp_components = devm_kcalloc(dev, hdmi_num,
@@ -875,7 +881,6 @@ DMIC:
sof_sdw_hdmi_init, NULL);
INC_ID(be_id, cpu_id, link_id);
}
-#endif
card->dai_link = links;
card->num_links = num_links;
@@ -898,6 +903,7 @@ static int mc_probe(struct platform_device *pdev)
struct snd_soc_card *card = &card_sof_sdw;
struct snd_soc_acpi_mach *mach;
struct mc_private *ctx;
+ int amp_num = 0, i;
int ret;
dev_dbg(&pdev->dev, "Entry %s\n", __func__);
@@ -908,9 +914,7 @@ static int mc_probe(struct platform_device *pdev)
dmi_check_system(sof_sdw_quirk_table);
-#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC)
INIT_LIST_HEAD(&ctx->hdmi_pcm_list);
-#endif
card->dev = &pdev->dev;
@@ -924,9 +928,18 @@ static int mc_probe(struct platform_device *pdev)
snd_soc_card_set_drvdata(card, ctx);
+ /*
+ * the default amp_num is zero for each codec and
+ * amp_num will only be increased for active amp
+ * codecs on used platform
+ */
+ for (i = 0; i < ARRAY_SIZE(codec_info_list); i++)
+ amp_num += codec_info_list[i].amp_num;
+
card->components = devm_kasprintf(card->dev, GFP_KERNEL,
- "cfg-spk:%d",
- (sof_sdw_quirk & SOF_SDW_FOUR_SPK) ? 4 : 2);
+ "cfg-spk:%d cfg-amp:%d",
+ (sof_sdw_quirk & SOF_SDW_FOUR_SPK)
+ ? 4 : 2, amp_num);
if (!card->components)
return -ENOMEM;
diff --git a/sound/soc/intel/boards/sof_sdw_common.h b/sound/soc/intel/boards/sof_sdw_common.h
index dd593ff3575b..69b363b8a686 100644
--- a/sound/soc/intel/boards/sof_sdw_common.h
+++ b/sound/soc/intel/boards/sof_sdw_common.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0
+/* SPDX-License-Identifier: GPL-2.0-only
* Copyright (c) 2020 Intel Corporation
*/
diff --git a/sound/soc/intel/boards/sof_sdw_dmic.c b/sound/soc/intel/boards/sof_sdw_dmic.c
index e92176bf0ad4..89b0824b2381 100644
--- a/sound/soc/intel/boards/sof_sdw_dmic.c
+++ b/sound/soc/intel/boards/sof_sdw_dmic.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: GPL-2.0-only
// Copyright (c) 2020 Intel Corporation
/*
diff --git a/sound/soc/intel/boards/sof_sdw_hdmi.c b/sound/soc/intel/boards/sof_sdw_hdmi.c
index c7b5612a39e6..0654b38a7e0d 100644
--- a/sound/soc/intel/boards/sof_sdw_hdmi.c
+++ b/sound/soc/intel/boards/sof_sdw_hdmi.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: GPL-2.0-only
// Copyright (c) 2020 Intel Corporation
/*
@@ -16,7 +16,6 @@
#include "../../codecs/hdac_hdmi.h"
#include "hda_dsp_common.h"
-#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC)
static struct snd_soc_jack hdmi[MAX_HDMI_NUM];
struct hdmi_pcm {
@@ -28,7 +27,7 @@ struct hdmi_pcm {
int sof_sdw_hdmi_init(struct snd_soc_pcm_runtime *rtd)
{
struct mc_private *ctx = snd_soc_card_get_drvdata(rtd->card);
- struct snd_soc_dai *dai = rtd->codec_dai;
+ struct snd_soc_dai *dai = asoc_rtd_to_codec(rtd, 0);
struct hdmi_pcm *pcm;
pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL);
@@ -89,9 +88,3 @@ int sof_sdw_hdmi_card_late_probe(struct snd_soc_card *card)
return hdac_hdmi_jack_port_init(component, &card->dapm);
}
-#else
-int hdmi_card_late_probe(struct snd_soc_card *card)
-{
- return 0;
-}
-#endif
diff --git a/sound/soc/intel/boards/sof_sdw_rt1308.c b/sound/soc/intel/boards/sof_sdw_rt1308.c
index 321768e54d08..177cc781ada6 100644
--- a/sound/soc/intel/boards/sof_sdw_rt1308.c
+++ b/sound/soc/intel/boards/sof_sdw_rt1308.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: GPL-2.0-only
// Copyright (c) 2020 Intel Corporation
/*
@@ -93,7 +93,7 @@ static int rt1308_i2s_hw_params(struct snd_pcm_substream *substream,
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_card *card = rtd->card;
- struct snd_soc_dai *codec_dai = rtd->codec_dai;
+ struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
int clk_id, clk_freq, pll_out;
int err;
diff --git a/sound/soc/intel/boards/sof_sdw_rt5682.c b/sound/soc/intel/boards/sof_sdw_rt5682.c
index 5aa6211a1ed9..da354ba83939 100644
--- a/sound/soc/intel/boards/sof_sdw_rt5682.c
+++ b/sound/soc/intel/boards/sof_sdw_rt5682.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: GPL-2.0-only
// Copyright (c) 2020 Intel Corporation
/*
@@ -47,7 +47,8 @@ static int rt5682_rtd_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_card *card = rtd->card;
struct mc_private *ctx = snd_soc_card_get_drvdata(card);
- struct snd_soc_component *component = rtd->codec_dai->component;
+ struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
+ struct snd_soc_component *component = codec_dai->component;
struct snd_soc_jack *jack;
int ret;
diff --git a/sound/soc/intel/boards/sof_sdw_rt700.c b/sound/soc/intel/boards/sof_sdw_rt700.c
index 2ee4e6910d7f..5f50491ba5ee 100644
--- a/sound/soc/intel/boards/sof_sdw_rt700.c
+++ b/sound/soc/intel/boards/sof_sdw_rt700.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: GPL-2.0-only
// Copyright (c) 2020 Intel Corporation
/*
@@ -47,7 +47,8 @@ static int rt700_rtd_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_card *card = rtd->card;
struct mc_private *ctx = snd_soc_card_get_drvdata(card);
- struct snd_soc_component *component = rtd->codec_dai->component;
+ struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
+ struct snd_soc_component *component = codec_dai->component;
struct snd_soc_jack *jack;
int ret;
@@ -94,10 +95,10 @@ static int rt700_rtd_init(struct snd_soc_pcm_runtime *rtd)
jack = &ctx->sdw_headset;
- snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_VOLUMEUP);
- snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_PLAYPAUSE);
- snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEDOWN);
- snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOICECOMMAND);
+ snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
+ snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOICECOMMAND);
+ snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEUP);
+ snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN);
ret = snd_soc_component_set_jack(component, jack, NULL);
if (ret)
diff --git a/sound/soc/intel/boards/sof_sdw_rt711.c b/sound/soc/intel/boards/sof_sdw_rt711.c
index 2a4917e3d561..d4d75c8dc6b7 100644
--- a/sound/soc/intel/boards/sof_sdw_rt711.c
+++ b/sound/soc/intel/boards/sof_sdw_rt711.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: GPL-2.0-only
// Copyright (c) 2020 Intel Corporation
/*
@@ -71,7 +71,8 @@ static int rt711_rtd_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_card *card = rtd->card;
struct mc_private *ctx = snd_soc_card_get_drvdata(card);
- struct snd_soc_component *component = rtd->codec_dai->component;
+ struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
+ struct snd_soc_component *component = codec_dai->component;
struct snd_soc_jack *jack;
int ret;
@@ -118,10 +119,10 @@ static int rt711_rtd_init(struct snd_soc_pcm_runtime *rtd)
jack = &ctx->sdw_headset;
- snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_VOLUMEUP);
- snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_PLAYPAUSE);
- snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEDOWN);
- snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOICECOMMAND);
+ snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
+ snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOICECOMMAND);
+ snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEUP);
+ snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN);
ret = snd_soc_component_set_jack(component, jack, NULL);
diff --git a/sound/soc/intel/boards/sof_sdw_rt715.c b/sound/soc/intel/boards/sof_sdw_rt715.c
index 321e1cbc03ed..9b298f79e784 100644
--- a/sound/soc/intel/boards/sof_sdw_rt715.c
+++ b/sound/soc/intel/boards/sof_sdw_rt715.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: GPL-2.0-only
// Copyright (c) 2020 Intel Corporation
/*
diff --git a/sound/soc/intel/boards/sof_wm8804.c b/sound/soc/intel/boards/sof_wm8804.c
new file mode 100644
index 000000000000..c13fd20da559
--- /dev/null
+++ b/sound/soc/intel/boards/sof_wm8804.c
@@ -0,0 +1,298 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// Copyright (c) 2018-2020, Intel Corporation
+//
+// sof-wm8804.c - ASoC machine driver for Up and Up2 board
+// based on WM8804/Hifiberry Digi+
+
+
+#include <linux/acpi.h>
+#include <linux/dmi.h>
+#include <linux/gpio/consumer.h>
+#include <linux/gpio/machine.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-acpi.h>
+#include "../../codecs/wm8804.h"
+
+struct sof_card_private {
+ struct gpio_desc *gpio_44;
+ struct gpio_desc *gpio_48;
+ int sample_rate;
+};
+
+#define SOF_WM8804_UP2_QUIRK BIT(0)
+
+static unsigned long sof_wm8804_quirk;
+
+static int sof_wm8804_quirk_cb(const struct dmi_system_id *id)
+{
+ sof_wm8804_quirk = (unsigned long)id->driver_data;
+ return 1;
+}
+
+static const struct dmi_system_id sof_wm8804_quirk_table[] = {
+ {
+ .callback = sof_wm8804_quirk_cb,
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "AAEON"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "UP-APL01"),
+ },
+ .driver_data = (void *)SOF_WM8804_UP2_QUIRK,
+ },
+ {}
+};
+
+static int sof_wm8804_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct sof_card_private *ctx = snd_soc_card_get_drvdata(rtd->card);
+ struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
+ struct snd_soc_component *codec = codec_dai->component;
+ const int sysclk = 27000000; /* This is fixed on this board */
+ int samplerate;
+ long mclk_freq;
+ int mclk_div;
+ int sampling_freq;
+ bool clk_44;
+ int ret;
+
+ samplerate = params_rate(params);
+ if (samplerate == ctx->sample_rate)
+ return 0;
+
+ ctx->sample_rate = 0;
+
+ if (samplerate <= 96000) {
+ mclk_freq = samplerate * 256;
+ mclk_div = WM8804_MCLKDIV_256FS;
+ } else {
+ mclk_freq = samplerate * 128;
+ mclk_div = WM8804_MCLKDIV_128FS;
+ }
+
+ switch (samplerate) {
+ case 32000:
+ sampling_freq = 0x03;
+ break;
+ case 44100:
+ sampling_freq = 0x00;
+ break;
+ case 48000:
+ sampling_freq = 0x02;
+ break;
+ case 88200:
+ sampling_freq = 0x08;
+ break;
+ case 96000:
+ sampling_freq = 0x0a;
+ break;
+ case 176400:
+ sampling_freq = 0x0c;
+ break;
+ case 192000:
+ sampling_freq = 0x0e;
+ break;
+ default:
+ dev_err(rtd->card->dev,
+ "unsupported samplerate %d\n", samplerate);
+ return -EINVAL;
+ }
+
+ if (samplerate % 16000)
+ clk_44 = true; /* use 44.1 kHz root frequency */
+ else
+ clk_44 = false;
+
+ if (!(IS_ERR_OR_NULL(ctx->gpio_44) ||
+ IS_ERR_OR_NULL(ctx->gpio_48))) {
+ /*
+ * ensure both GPIOs are LOW first, then drive the
+ * relevant one to HIGH
+ */
+ if (clk_44) {
+ gpiod_set_value_cansleep(ctx->gpio_48, !clk_44);
+ gpiod_set_value_cansleep(ctx->gpio_44, clk_44);
+ } else {
+ gpiod_set_value_cansleep(ctx->gpio_44, clk_44);
+ gpiod_set_value_cansleep(ctx->gpio_48, !clk_44);
+ }
+ }
+
+ snd_soc_dai_set_clkdiv(codec_dai, WM8804_MCLK_DIV, mclk_div);
+ snd_soc_dai_set_pll(codec_dai, 0, 0, sysclk, mclk_freq);
+
+ ret = snd_soc_dai_set_sysclk(codec_dai, WM8804_TX_CLKSRC_PLL,
+ sysclk, SND_SOC_CLOCK_OUT);
+ if (ret < 0) {
+ dev_err(rtd->card->dev,
+ "Failed to set WM8804 SYSCLK: %d\n", ret);
+ return ret;
+ }
+
+ /* set sampling frequency status bits */
+ snd_soc_component_update_bits(codec, WM8804_SPDTX4, 0x0f,
+ sampling_freq);
+
+ ctx->sample_rate = samplerate;
+
+ return 0;
+}
+
+/* machine stream operations */
+static struct snd_soc_ops sof_wm8804_ops = {
+ .hw_params = sof_wm8804_hw_params,
+};
+
+SND_SOC_DAILINK_DEF(ssp5_pin,
+ DAILINK_COMP_ARRAY(COMP_CPU("SSP5 Pin")));
+
+SND_SOC_DAILINK_DEF(ssp5_codec,
+ DAILINK_COMP_ARRAY(COMP_CODEC("i2c-1AEC8804:00", "wm8804-spdif")));
+
+SND_SOC_DAILINK_DEF(platform,
+ DAILINK_COMP_ARRAY(COMP_PLATFORM("0000:00:0e.0")));
+
+static struct snd_soc_dai_link dailink[] = {
+ /* back ends */
+ {
+ .name = "SSP5-Codec",
+ .id = 0,
+ .no_pcm = 1,
+ .nonatomic = true,
+ .dpcm_playback = 1,
+ .dpcm_capture = 1,
+ .ops = &sof_wm8804_ops,
+ SND_SOC_DAILINK_REG(ssp5_pin, ssp5_codec, platform),
+ },
+};
+
+/* SoC card */
+static struct snd_soc_card sof_wm8804_card = {
+ .name = "wm8804", /* sof- prefix added automatically */
+ .owner = THIS_MODULE,
+ .dai_link = dailink,
+ .num_links = ARRAY_SIZE(dailink),
+};
+
+ /* i2c-<HID>:00 with HID being 8 chars */
+static char codec_name[SND_ACPI_I2C_ID_LEN];
+
+/*
+ * to control the HifiBerry Digi+ PRO, it's required to toggle GPIO to
+ * select the clock source. On the Up2 board, this means
+ * Pin29/BCM5/Linux GPIO 430 and Pin 31/BCM6/ Linux GPIO 404.
+ *
+ * Using the ACPI device name is not very nice, but since we only use
+ * the value for the Up2 board there is no risk of conflict with other
+ * platforms.
+ */
+
+static struct gpiod_lookup_table up2_gpios_table = {
+ /* .dev_id is set during probe */
+ .table = {
+ GPIO_LOOKUP("INT3452:01", 73, "BCM-GPIO5", GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP("INT3452:01", 74, "BCM-GPIO6", GPIO_ACTIVE_HIGH),
+ { },
+ },
+};
+
+static int sof_wm8804_probe(struct platform_device *pdev)
+{
+ struct snd_soc_card *card;
+ struct snd_soc_acpi_mach *mach;
+ struct sof_card_private *ctx;
+ struct acpi_device *adev;
+ int dai_index = 0;
+ int ret;
+ int i;
+
+ ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
+ if (!ctx)
+ return -ENOMEM;
+
+ mach = pdev->dev.platform_data;
+ card = &sof_wm8804_card;
+ card->dev = &pdev->dev;
+
+ dmi_check_system(sof_wm8804_quirk_table);
+
+ if (sof_wm8804_quirk & SOF_WM8804_UP2_QUIRK) {
+ up2_gpios_table.dev_id = dev_name(&pdev->dev);
+ gpiod_add_lookup_table(&up2_gpios_table);
+
+ /*
+ * The gpios are required for specific boards with
+ * local oscillators, and optional in other cases.
+ * Since we can't identify when they are needed, use
+ * the GPIO as non-optional
+ */
+
+ ctx->gpio_44 = devm_gpiod_get(&pdev->dev, "BCM-GPIO5",
+ GPIOD_OUT_LOW);
+ if (IS_ERR(ctx->gpio_44)) {
+ ret = PTR_ERR(ctx->gpio_44);
+ dev_err(&pdev->dev,
+ "could not get BCM-GPIO5: %d\n",
+ ret);
+ return ret;
+ }
+
+ ctx->gpio_48 = devm_gpiod_get(&pdev->dev, "BCM-GPIO6",
+ GPIOD_OUT_LOW);
+ if (IS_ERR(ctx->gpio_48)) {
+ ret = PTR_ERR(ctx->gpio_48);
+ dev_err(&pdev->dev,
+ "could not get BCM-GPIO6: %d\n",
+ ret);
+ return ret;
+ }
+ }
+
+ /* fix index of codec dai */
+ for (i = 0; i < ARRAY_SIZE(dailink); i++) {
+ if (!strcmp(dailink[i].codecs->name, "i2c-1AEC8804:00")) {
+ dai_index = i;
+ break;
+ }
+ }
+
+ /* fixup codec name based on HID */
+ adev = acpi_dev_get_first_match_dev(mach->id, NULL, -1);
+ if (adev) {
+ snprintf(codec_name, sizeof(codec_name),
+ "%s%s", "i2c-", acpi_dev_name(adev));
+ put_device(&adev->dev);
+ dailink[dai_index].codecs->name = codec_name;
+ }
+
+ snd_soc_card_set_drvdata(card, ctx);
+
+ return devm_snd_soc_register_card(&pdev->dev, card);
+}
+
+static int sof_wm8804_remove(struct platform_device *pdev)
+{
+ if (sof_wm8804_quirk & SOF_WM8804_UP2_QUIRK)
+ gpiod_remove_lookup_table(&up2_gpios_table);
+ return 0;
+}
+
+static struct platform_driver sof_wm8804_driver = {
+ .driver = {
+ .name = "sof-wm8804",
+ .pm = &snd_soc_pm_ops,
+ },
+ .probe = sof_wm8804_probe,
+ .remove = sof_wm8804_remove,
+};
+module_platform_driver(sof_wm8804_driver);
+
+MODULE_DESCRIPTION("ASoC Intel(R) SOF + WM8804 Machine driver");
+MODULE_AUTHOR("Pierre-Louis Bossart");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:sof-wm8804");
diff --git a/sound/soc/intel/common/Makefile b/sound/soc/intel/common/Makefile
index bd352878f89a..2674c9790fa1 100644
--- a/sound/soc/intel/common/Makefile
+++ b/sound/soc/intel/common/Makefile
@@ -1,4 +1,4 @@
-# SPDX-License-Identifier: GPL-2.0
+# SPDX-License-Identifier: GPL-2.0-only
snd-soc-sst-dsp-objs := sst-dsp.o
snd-soc-sst-acpi-objs := sst-acpi.o
snd-soc-sst-ipc-objs := sst-ipc.o
diff --git a/sound/soc/intel/common/soc-acpi-intel-bxt-match.c b/sound/soc/intel/common/soc-acpi-intel-bxt-match.c
index f5092bc48364..32f77e29c2ff 100644
--- a/sound/soc/intel/common/soc-acpi-intel-bxt-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-bxt-match.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: GPL-2.0-only
/*
* soc-acpi-intel-bxt-match.c - tables and support for BXT ACPI enumeration.
*
@@ -71,7 +71,7 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_bxt_machines[] = {
},
{
.id = "1AEC8804",
- .drv_name = "bxt-wm8804",
+ .drv_name = "sof-wm8804",
.sof_fw_filename = "sof-apl.ri",
.sof_tplg_filename = "sof-apl-wm8804.tplg",
},
diff --git a/sound/soc/intel/common/soc-acpi-intel-cfl-match.c b/sound/soc/intel/common/soc-acpi-intel-cfl-match.c
index ff9d6938b9f6..27b4b73d94d4 100644
--- a/sound/soc/intel/common/soc-acpi-intel-cfl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-cfl-match.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: GPL-2.0-only
/*
* soc-apci-intel-cfl-match.c - tables and support for CFL ACPI enumeration.
*
diff --git a/sound/soc/intel/common/soc-acpi-intel-cml-match.c b/sound/soc/intel/common/soc-acpi-intel-cml-match.c
index 7d85bd5aff9f..cdea0c09fe0a 100644
--- a/sound/soc/intel/common/soc-acpi-intel-cml-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-cml-match.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: GPL-2.0-only
/*
* soc-acpi-intel-cml-match.c - tables and support for CML ACPI enumeration.
*
diff --git a/sound/soc/intel/common/soc-acpi-intel-cnl-match.c b/sound/soc/intel/common/soc-acpi-intel-cnl-match.c
index 828980d5630d..6a0bcc1a8429 100644
--- a/sound/soc/intel/common/soc-acpi-intel-cnl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-cnl-match.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: GPL-2.0-only
/*
* soc-acpi-intel-cnl-match.c - tables and support for CNL ACPI enumeration.
*
diff --git a/sound/soc/intel/common/soc-acpi-intel-ehl-match.c b/sound/soc/intel/common/soc-acpi-intel-ehl-match.c
index a1290c3fa99f..45e07d886013 100644
--- a/sound/soc/intel/common/soc-acpi-intel-ehl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-ehl-match.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: GPL-2.0-only
/*
* soc-apci-intel-ehl-match.c - tables and support for EHL ACPI enumeration.
*
@@ -8,8 +8,15 @@
#include <sound/soc-acpi.h>
#include <sound/soc-acpi-intel-match.h>
+#include "../skylake/skl.h"
struct snd_soc_acpi_mach snd_soc_acpi_intel_ehl_machines[] = {
+ {
+ .id = "INTC1027",
+ .drv_name = "ehl_rt5660",
+ .sof_fw_filename = "sof-ehl.ri",
+ .sof_tplg_filename = "sof-ehl-rt5660.tplg",
+ },
{},
};
EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_ehl_machines);
diff --git a/sound/soc/intel/common/soc-acpi-intel-glk-match.c b/sound/soc/intel/common/soc-acpi-intel-glk-match.c
index 60dea358fa04..26cb3b16cdd3 100644
--- a/sound/soc/intel/common/soc-acpi-intel-glk-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-glk-match.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: GPL-2.0-only
/*
* soc-acpi-intel-glk-match.c - tables and support for GLK ACPI enumeration.
*
diff --git a/sound/soc/intel/common/soc-acpi-intel-hda-match.c b/sound/soc/intel/common/soc-acpi-intel-hda-match.c
index cc972d2ac691..aa9cb522aac9 100644
--- a/sound/soc/intel/common/soc-acpi-intel-hda-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-hda-match.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: GPL-2.0-only
// Copyright (c) 2018, Intel Corporation.
/*
diff --git a/sound/soc/intel/common/soc-acpi-intel-icl-match.c b/sound/soc/intel/common/soc-acpi-intel-icl-match.c
index 16ec9f382b0f..6927bbbc66fc 100644
--- a/sound/soc/intel/common/soc-acpi-intel-icl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-icl-match.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: GPL-2.0-only
/*
* soc-acpi-intel-icl-match.c - tables and support for ICL ACPI enumeration.
*
diff --git a/sound/soc/intel/common/soc-acpi-intel-jsl-match.c b/sound/soc/intel/common/soc-acpi-intel-jsl-match.c
index 4388a32718d8..859f8a1bd914 100644
--- a/sound/soc/intel/common/soc-acpi-intel-jsl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-jsl-match.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: GPL-2.0-only
/*
* soc-apci-intel-jsl-match.c - tables and support for JSL ACPI enumeration.
*
diff --git a/sound/soc/intel/common/soc-acpi-intel-kbl-match.c b/sound/soc/intel/common/soc-acpi-intel-kbl-match.c
index e200baa11011..a4fbe6707ca7 100644
--- a/sound/soc/intel/common/soc-acpi-intel-kbl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-kbl-match.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: GPL-2.0-only
/*
* soc-acpi-intel-kbl-match.c - tables and support for KBL ACPI enumeration.
*
diff --git a/sound/soc/intel/common/soc-acpi-intel-skl-match.c b/sound/soc/intel/common/soc-acpi-intel-skl-match.c
index 42fa40a8d932..26f9ce146523 100644
--- a/sound/soc/intel/common/soc-acpi-intel-skl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-skl-match.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: GPL-2.0-only
/*
* soc-acpi-intel-skl-match.c - tables and support for SKL ACPI enumeration.
*
diff --git a/sound/soc/intel/common/soc-acpi-intel-tgl-match.c b/sound/soc/intel/common/soc-acpi-intel-tgl-match.c
index 449d9d2286ae..5a56f4359479 100644
--- a/sound/soc/intel/common/soc-acpi-intel-tgl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-tgl-match.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: GPL-2.0-only
/*
* soc-apci-intel-tgl-match.c - tables and support for ICL ACPI enumeration.
*
diff --git a/sound/soc/intel/common/soc-intel-quirks.h b/sound/soc/intel/common/soc-intel-quirks.h
index a9176150c6ed..b07df3059926 100644
--- a/sound/soc/intel/common/soc-intel-quirks.h
+++ b/sound/soc/intel/common/soc-intel-quirks.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0-only */
/*
* soc-intel-quirks.h - prototypes for quirk autodetection
*
diff --git a/sound/soc/intel/common/sst-dsp.c b/sound/soc/intel/common/sst-dsp.c
index ec66be269b69..36c077aa386e 100644
--- a/sound/soc/intel/common/sst-dsp.c
+++ b/sound/soc/intel/common/sst-dsp.c
@@ -10,7 +10,7 @@
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/platform_device.h>
-#include <linux/io.h>
+#include <linux/io-64-nonatomic-lo-hi.h>
#include <linux/delay.h>
#include "sst-dsp.h"
@@ -34,16 +34,13 @@ EXPORT_SYMBOL_GPL(sst_shim32_read);
void sst_shim32_write64(void __iomem *addr, u32 offset, u64 value)
{
- memcpy_toio(addr + offset, &value, sizeof(value));
+ writeq(value, addr + offset);
}
EXPORT_SYMBOL_GPL(sst_shim32_write64);
u64 sst_shim32_read64(void __iomem *addr, u32 offset)
{
- u64 val;
-
- memcpy_fromio(&val, addr + offset, sizeof(val));
- return val;
+ return readq(addr + offset);
}
EXPORT_SYMBOL_GPL(sst_shim32_read64);
diff --git a/sound/soc/intel/haswell/sst-haswell-dsp.c b/sound/soc/intel/haswell/sst-haswell-dsp.c
index 88c3f63bded9..de80e19454c1 100644
--- a/sound/soc/intel/haswell/sst-haswell-dsp.c
+++ b/sound/soc/intel/haswell/sst-haswell-dsp.c
@@ -243,45 +243,92 @@ static irqreturn_t hsw_irq(int irq, void *context)
return ret;
}
+#define CSR_DEFAULT_VALUE 0x8480040E
+#define ISC_DEFAULT_VALUE 0x0
+#define ISD_DEFAULT_VALUE 0x0
+#define IMC_DEFAULT_VALUE 0x7FFF0003
+#define IMD_DEFAULT_VALUE 0x7FFF0003
+#define IPCC_DEFAULT_VALUE 0x0
+#define IPCD_DEFAULT_VALUE 0x0
+#define CLKCTL_DEFAULT_VALUE 0x7FF
+#define CSR2_DEFAULT_VALUE 0x0
+#define LTR_CTRL_DEFAULT_VALUE 0x0
+#define HMD_CTRL_DEFAULT_VALUE 0x0
+
+static void hsw_set_shim_defaults(struct sst_dsp *sst)
+{
+ sst_dsp_shim_write_unlocked(sst, SST_CSR, CSR_DEFAULT_VALUE);
+ sst_dsp_shim_write_unlocked(sst, SST_ISRX, ISC_DEFAULT_VALUE);
+ sst_dsp_shim_write_unlocked(sst, SST_ISRD, ISD_DEFAULT_VALUE);
+ sst_dsp_shim_write_unlocked(sst, SST_IMRX, IMC_DEFAULT_VALUE);
+ sst_dsp_shim_write_unlocked(sst, SST_IMRD, IMD_DEFAULT_VALUE);
+ sst_dsp_shim_write_unlocked(sst, SST_IPCX, IPCC_DEFAULT_VALUE);
+ sst_dsp_shim_write_unlocked(sst, SST_IPCD, IPCD_DEFAULT_VALUE);
+ sst_dsp_shim_write_unlocked(sst, SST_CLKCTL, CLKCTL_DEFAULT_VALUE);
+ sst_dsp_shim_write_unlocked(sst, SST_CSR2, CSR2_DEFAULT_VALUE);
+ sst_dsp_shim_write_unlocked(sst, SST_LTRC, LTR_CTRL_DEFAULT_VALUE);
+ sst_dsp_shim_write_unlocked(sst, SST_HMDC, HMD_CTRL_DEFAULT_VALUE);
+}
+
+/* all clock-gating minus DCLCGE and DTCGE */
+#define SST_VDRTCL2_CG_OTHER 0xB7D
+
static void hsw_set_dsp_D3(struct sst_dsp *sst)
{
- u32 val;
u32 reg;
- /* Disable core clock gating (VDRTCTL2.DCLCGE = 0) */
+ /* disable clock core gating */
reg = readl(sst->addr.pci_cfg + SST_VDRTCTL2);
- reg &= ~(SST_VDRTCL2_DCLCGE | SST_VDRTCL2_DTCGE);
+ reg &= ~(SST_VDRTCL2_DCLCGE);
writel(reg, sst->addr.pci_cfg + SST_VDRTCTL2);
- /* enable power gating and switch off DRAM & IRAM blocks */
- val = readl(sst->addr.pci_cfg + SST_VDRTCTL0);
- val |= SST_VDRTCL0_DSRAMPGE_MASK |
- SST_VDRTCL0_ISRAMPGE_MASK;
- val &= ~(SST_VDRTCL0_D3PGD | SST_VDRTCL0_D3SRAMPGD);
- writel(val, sst->addr.pci_cfg + SST_VDRTCTL0);
+ /* stall, reset and set 24MHz XOSC */
+ sst_dsp_shim_update_bits_unlocked(sst, SST_CSR,
+ SST_CSR_24MHZ_LPCS | SST_CSR_STALL | SST_CSR_RST,
+ SST_CSR_24MHZ_LPCS | SST_CSR_STALL | SST_CSR_RST);
- /* switch off audio PLL */
- val = readl(sst->addr.pci_cfg + SST_VDRTCTL2);
- val |= SST_VDRTCL2_APLLSE_MASK;
- writel(val, sst->addr.pci_cfg + SST_VDRTCTL2);
+ /* DRAM power gating all */
+ reg = readl(sst->addr.pci_cfg + SST_VDRTCTL0);
+ reg |= SST_VDRTCL0_ISRAMPGE_MASK |
+ SST_VDRTCL0_DSRAMPGE_MASK;
+ reg &= ~(SST_VDRTCL0_D3SRAMPGD);
+ reg |= SST_VDRTCL0_D3PGD;
+ writel(reg, sst->addr.pci_cfg + SST_VDRTCTL0);
+ udelay(50);
- /* disable MCLK(clkctl.smos = 0) */
- sst_dsp_shim_update_bits_unlocked(sst, SST_CLKCTL,
- SST_CLKCTL_MASK, 0);
+ /* PLL shutdown enable */
+ reg = readl(sst->addr.pci_cfg + SST_VDRTCTL2);
+ reg |= SST_VDRTCL2_APLLSE_MASK;
+ writel(reg, sst->addr.pci_cfg + SST_VDRTCTL2);
- /* Set D3 state, delay 50 us */
- val = readl(sst->addr.pci_cfg + SST_PMCS);
- val |= SST_PMCS_PS_MASK;
- writel(val, sst->addr.pci_cfg + SST_PMCS);
- udelay(50);
+ /* disable MCLK */
+ sst_dsp_shim_update_bits_unlocked(sst, SST_CLKCTL,
+ SST_CLKCTL_MASK, 0);
- /* Enable core clock gating (VDRTCTL2.DCLCGE = 1), delay 50 us */
+ /* switch clock gating */
+ reg = readl(sst->addr.pci_cfg + SST_VDRTCTL2);
+ reg |= SST_VDRTCL2_CG_OTHER;
+ reg &= ~(SST_VDRTCL2_DTCGE);
+ writel(reg, sst->addr.pci_cfg + SST_VDRTCTL2);
+ /* enable DTCGE separatelly */
reg = readl(sst->addr.pci_cfg + SST_VDRTCTL2);
- reg |= SST_VDRTCL2_DCLCGE | SST_VDRTCL2_DTCGE;
+ reg |= SST_VDRTCL2_DTCGE;
writel(reg, sst->addr.pci_cfg + SST_VDRTCTL2);
+ /* set shim defaults */
+ hsw_set_shim_defaults(sst);
+
+ /* set D3 */
+ reg = readl(sst->addr.pci_cfg + SST_PMCS);
+ reg |= SST_PMCS_PS_MASK;
+ writel(reg, sst->addr.pci_cfg + SST_PMCS);
udelay(50);
+ /* enable clock core gating */
+ reg = readl(sst->addr.pci_cfg + SST_VDRTCTL2);
+ reg |= SST_VDRTCL2_DCLCGE;
+ writel(reg, sst->addr.pci_cfg + SST_VDRTCTL2);
+ udelay(50);
}
static void hsw_reset(struct sst_dsp *sst)
@@ -299,75 +346,62 @@ static void hsw_reset(struct sst_dsp *sst)
SST_CSR_RST | SST_CSR_STALL, SST_CSR_STALL);
}
+/* recommended CSR state for power-up */
+#define SST_CSR_D0_MASK (0x18A09C0C | SST_CSR_DCS_MASK)
+
static int hsw_set_dsp_D0(struct sst_dsp *sst)
{
- int tries = 10;
- u32 reg, fw_dump_bit;
+ u32 reg;
- /* Disable core clock gating (VDRTCTL2.DCLCGE = 0) */
+ /* disable clock core gating */
reg = readl(sst->addr.pci_cfg + SST_VDRTCTL2);
- reg &= ~(SST_VDRTCL2_DCLCGE | SST_VDRTCL2_DTCGE);
+ reg &= ~(SST_VDRTCL2_DCLCGE);
writel(reg, sst->addr.pci_cfg + SST_VDRTCTL2);
- /* Disable D3PG (VDRTCTL0.D3PGD = 1) */
- reg = readl(sst->addr.pci_cfg + SST_VDRTCTL0);
- reg |= SST_VDRTCL0_D3PGD;
- writel(reg, sst->addr.pci_cfg + SST_VDRTCTL0);
+ /* switch clock gating */
+ reg = readl(sst->addr.pci_cfg + SST_VDRTCTL2);
+ reg |= SST_VDRTCL2_CG_OTHER;
+ reg &= ~(SST_VDRTCL2_DTCGE);
+ writel(reg, sst->addr.pci_cfg + SST_VDRTCTL2);
- /* Set D0 state */
+ /* set D0 */
reg = readl(sst->addr.pci_cfg + SST_PMCS);
- reg &= ~SST_PMCS_PS_MASK;
+ reg &= ~(SST_PMCS_PS_MASK);
writel(reg, sst->addr.pci_cfg + SST_PMCS);
- /* check that ADSP shim is enabled */
- while (tries--) {
- reg = readl(sst->addr.pci_cfg + SST_PMCS) & SST_PMCS_PS_MASK;
- if (reg == 0)
- goto finish;
-
- msleep(1);
- }
-
- return -ENODEV;
-
-finish:
- /* select SSP1 19.2MHz base clock, SSP clock 0, turn off Low Power Clock */
- sst_dsp_shim_update_bits_unlocked(sst, SST_CSR,
- SST_CSR_S1IOCS | SST_CSR_SBCS1 | SST_CSR_LPCS, 0x0);
+ /* DRAM power gating none */
+ reg = readl(sst->addr.pci_cfg + SST_VDRTCTL0);
+ reg &= ~(SST_VDRTCL0_ISRAMPGE_MASK |
+ SST_VDRTCL0_DSRAMPGE_MASK);
+ reg |= SST_VDRTCL0_D3SRAMPGD;
+ reg |= SST_VDRTCL0_D3PGD;
+ writel(reg, sst->addr.pci_cfg + SST_VDRTCTL0);
+ mdelay(10);
- /* stall DSP core, set clk to 192/96Mhz */
- sst_dsp_shim_update_bits_unlocked(sst,
- SST_CSR, SST_CSR_STALL | SST_CSR_DCS_MASK,
- SST_CSR_STALL | SST_CSR_DCS(4));
+ /* set shim defaults */
+ hsw_set_shim_defaults(sst);
- /* Set 24MHz MCLK, prevent local clock gating, enable SSP0 clock */
+ /* restore MCLK */
sst_dsp_shim_update_bits_unlocked(sst, SST_CLKCTL,
- SST_CLKCTL_MASK | SST_CLKCTL_DCPLCG | SST_CLKCTL_SCOE0,
- SST_CLKCTL_MASK | SST_CLKCTL_DCPLCG | SST_CLKCTL_SCOE0);
+ SST_CLKCTL_MASK, SST_CLKCTL_MASK);
- /* Stall and reset core, set CSR */
- hsw_reset(sst);
-
- /* Enable core clock gating (VDRTCTL2.DCLCGE = 1), delay 50 us */
+ /* PLL shutdown disable */
reg = readl(sst->addr.pci_cfg + SST_VDRTCTL2);
- reg |= SST_VDRTCL2_DCLCGE | SST_VDRTCL2_DTCGE;
+ reg &= ~(SST_VDRTCL2_APLLSE_MASK);
writel(reg, sst->addr.pci_cfg + SST_VDRTCTL2);
+ sst_dsp_shim_update_bits_unlocked(sst, SST_CSR,
+ SST_CSR_D0_MASK, SST_CSR_SBCS0 | SST_CSR_SBCS1 |
+ SST_CSR_STALL | SST_CSR_DCS(4));
udelay(50);
- /* switch on audio PLL */
+ /* enable clock core gating */
reg = readl(sst->addr.pci_cfg + SST_VDRTCTL2);
- reg &= ~SST_VDRTCL2_APLLSE_MASK;
+ reg |= SST_VDRTCL2_DCLCGE;
writel(reg, sst->addr.pci_cfg + SST_VDRTCTL2);
- /* set default power gating control, enable power gating control for all blocks. that is,
- can't be accessed, please enable each block before accessing. */
- reg = readl(sst->addr.pci_cfg + SST_VDRTCTL0);
- reg |= SST_VDRTCL0_DSRAMPGE_MASK | SST_VDRTCL0_ISRAMPGE_MASK;
- /* for D0, always enable the block(DSRAM[0]) used for FW dump */
- fw_dump_bit = 1 << SST_VDRTCL0_DSRAMPGE_SHIFT;
- writel(reg & ~fw_dump_bit, sst->addr.pci_cfg + SST_VDRTCTL0);
-
+ /* clear reset */
+ sst_dsp_shim_update_bits_unlocked(sst, SST_CSR, SST_CSR_RST, 0);
/* disable DMA finish function for SSP0 & SSP1 */
sst_dsp_shim_update_bits_unlocked(sst, SST_CSR2, SST_CSR2_SDFD_SSP1,
@@ -384,12 +418,6 @@ finish:
sst_dsp_shim_update_bits(sst, SST_IMRD, (SST_IMRD_DONE | SST_IMRD_BUSY |
SST_IMRD_SSP0 | SST_IMRD_DMAC), 0x0);
- /* clear IPC registers */
- sst_dsp_shim_write(sst, SST_IPCX, 0x0);
- sst_dsp_shim_write(sst, SST_IPCD, 0x0);
- sst_dsp_shim_write(sst, 0x80, 0x6);
- sst_dsp_shim_write(sst, 0xe0, 0x300a);
-
return 0;
}
@@ -415,11 +443,6 @@ static void hsw_sleep(struct sst_dsp *sst)
{
dev_dbg(sst->dev, "HSW_PM dsp runtime suspend\n");
- /* put DSP into reset and stall */
- sst_dsp_shim_update_bits(sst, SST_CSR,
- SST_CSR_24MHZ_LPCS | SST_CSR_RST | SST_CSR_STALL,
- SST_CSR_RST | SST_CSR_STALL | SST_CSR_24MHZ_LPCS);
-
hsw_set_dsp_D3(sst);
dev_dbg(sst->dev, "HSW_PM dsp runtime suspend exit\n");
}
diff --git a/sound/soc/intel/skylake/Makefile b/sound/soc/intel/skylake/Makefile
index 48544ff1a3e6..dd39149b89b1 100644
--- a/sound/soc/intel/skylake/Makefile
+++ b/sound/soc/intel/skylake/Makefile
@@ -1,4 +1,4 @@
-# SPDX-License-Identifier: GPL-2.0
+# SPDX-License-Identifier: GPL-2.0-only
snd-soc-skl-objs := skl.o skl-pcm.o skl-nhlt.o skl-messages.o skl-topology.o \
skl-sst-ipc.o skl-sst-dsp.o cnl-sst-dsp.o skl-sst-cldma.o \
skl-sst.o bxt-sst.o cnl-sst.o skl-sst-utils.o
diff --git a/sound/soc/intel/skylake/skl-i2s.h b/sound/soc/intel/skylake/skl-i2s.h
index d7c15873c0d4..dfce91e11be1 100644
--- a/sound/soc/intel/skylake/skl-i2s.h
+++ b/sound/soc/intel/skylake/skl-i2s.h
@@ -46,7 +46,7 @@ struct skl_i2s_config_mclk {
struct skl_i2s_config_mclk_ext {
u32 mdivctrl;
u32 mdivr_count;
- u32 mdivr[0];
+ u32 mdivr[];
} __packed;
struct skl_i2s_config_blob_signature {
diff --git a/sound/soc/intel/skylake/skl-ssp-clk.c b/sound/soc/intel/skylake/skl-ssp-clk.c
index bd43885f3805..a3a73c26f9aa 100644
--- a/sound/soc/intel/skylake/skl-ssp-clk.c
+++ b/sound/soc/intel/skylake/skl-ssp-clk.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: GPL-2.0-only
// Copyright(c) 2015-17 Intel Corporation
/*
diff --git a/sound/soc/intel/skylake/skl-sst-utils.c b/sound/soc/intel/skylake/skl-sst-utils.c
index d43cbf4a71ef..b233f89517c1 100644
--- a/sound/soc/intel/skylake/skl-sst-utils.c
+++ b/sound/soc/intel/skylake/skl-sst-utils.c
@@ -290,7 +290,7 @@ int snd_skl_parse_uuids(struct sst_dsp *ctx, const struct firmware *fw,
goto free_uuid_list;
}
- guid_copy(&module->uuid, (guid_t *)&mod_entry->uuid);
+ import_guid(&module->uuid, mod_entry->uuid);
module->id = (i | (index << 12));
module->is_loadable = mod_entry->type.load_type;
diff --git a/sound/soc/intel/skylake/skl-topology.c b/sound/soc/intel/skylake/skl-topology.c
index 69cd7a81bf2a..b9aab47d1202 100644
--- a/sound/soc/intel/skylake/skl-topology.c
+++ b/sound/soc/intel/skylake/skl-topology.c
@@ -14,6 +14,7 @@
#include <linux/uuid.h>
#include <sound/intel-nhlt.h>
#include <sound/soc.h>
+#include <sound/soc-acpi.h>
#include <sound/soc-topology.h>
#include <uapi/sound/snd_sst_tokens.h>
#include <uapi/sound/skl-tplg-interface.h>
@@ -578,6 +579,38 @@ static int skl_tplg_unload_pipe_modules(struct skl_dev *skl,
return ret;
}
+static bool skl_tplg_is_multi_fmt(struct skl_dev *skl, struct skl_pipe *pipe)
+{
+ struct skl_pipe_fmt *cur_fmt;
+ struct skl_pipe_fmt *next_fmt;
+ int i;
+
+ if (pipe->nr_cfgs <= 1)
+ return false;
+
+ if (pipe->conn_type != SKL_PIPE_CONN_TYPE_FE)
+ return true;
+
+ for (i = 0; i < pipe->nr_cfgs - 1; i++) {
+ if (pipe->direction == SNDRV_PCM_STREAM_PLAYBACK) {
+ cur_fmt = &pipe->configs[i].out_fmt;
+ next_fmt = &pipe->configs[i + 1].out_fmt;
+ } else {
+ cur_fmt = &pipe->configs[i].in_fmt;
+ next_fmt = &pipe->configs[i + 1].in_fmt;
+ }
+
+ if (!CHECK_HW_PARAMS(cur_fmt->channels, cur_fmt->freq,
+ cur_fmt->bps,
+ next_fmt->channels,
+ next_fmt->freq,
+ next_fmt->bps))
+ return true;
+ }
+
+ return false;
+}
+
/*
* Here, we select pipe format based on the pipe type and pipe
* direction to determine the current config index for the pipeline.
@@ -600,6 +633,14 @@ skl_tplg_get_pipe_config(struct skl_dev *skl, struct skl_module_cfg *mconfig)
return 0;
}
+ if (skl_tplg_is_multi_fmt(skl, pipe)) {
+ pipe->cur_config_idx = pipe->pipe_config_idx;
+ pipe->memory_pages = pconfig->mem_pages;
+ dev_dbg(skl->dev, "found pipe config idx:%d\n",
+ pipe->cur_config_idx);
+ return 0;
+ }
+
if (pipe->conn_type == SKL_PIPE_CONN_TYPE_NONE) {
dev_dbg(skl->dev, "No conn_type detected, take 0th config\n");
pipe->cur_config_idx = 0;
@@ -1314,6 +1355,68 @@ static int skl_tplg_pga_event(struct snd_soc_dapm_widget *w,
return 0;
}
+static int skl_tplg_multi_config_set_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol,
+ bool is_set)
+{
+ struct snd_soc_component *component =
+ snd_soc_kcontrol_component(kcontrol);
+ struct hdac_bus *bus = snd_soc_component_get_drvdata(component);
+ struct skl_dev *skl = bus_to_skl(bus);
+ struct skl_pipeline *ppl;
+ struct skl_pipe *pipe = NULL;
+ struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value;
+ u32 *pipe_id;
+
+ if (!ec)
+ return -EINVAL;
+
+ if (is_set && ucontrol->value.enumerated.item[0] > ec->items)
+ return -EINVAL;
+
+ pipe_id = ec->dobj.private;
+
+ list_for_each_entry(ppl, &skl->ppl_list, node) {
+ if (ppl->pipe->ppl_id == *pipe_id) {
+ pipe = ppl->pipe;
+ break;
+ }
+ }
+ if (!pipe)
+ return -EIO;
+
+ if (is_set)
+ pipe->pipe_config_idx = ucontrol->value.enumerated.item[0];
+ else
+ ucontrol->value.enumerated.item[0] = pipe->pipe_config_idx;
+
+ return 0;
+}
+
+static int skl_tplg_multi_config_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ return skl_tplg_multi_config_set_get(kcontrol, ucontrol, false);
+}
+
+static int skl_tplg_multi_config_set(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ return skl_tplg_multi_config_set_get(kcontrol, ucontrol, true);
+}
+
+static int skl_tplg_multi_config_get_dmic(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ return skl_tplg_multi_config_set_get(kcontrol, ucontrol, false);
+}
+
+static int skl_tplg_multi_config_set_dmic(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ return skl_tplg_multi_config_set_get(kcontrol, ucontrol, true);
+}
+
static int skl_tplg_tlv_control_get(struct snd_kcontrol *kcontrol,
unsigned int __user *data, unsigned int size)
{
@@ -1853,6 +1956,16 @@ static const struct snd_soc_tplg_kcontrol_ops skl_tplg_kcontrol_ops[] = {
.get = skl_tplg_mic_control_get,
.put = skl_tplg_mic_control_set,
},
+ {
+ .id = SKL_CONTROL_TYPE_MULTI_IO_SELECT,
+ .get = skl_tplg_multi_config_get,
+ .put = skl_tplg_multi_config_set,
+ },
+ {
+ .id = SKL_CONTROL_TYPE_MULTI_IO_SELECT_DMIC,
+ .get = skl_tplg_multi_config_get_dmic,
+ .put = skl_tplg_multi_config_set_dmic,
+ }
};
static int skl_tplg_fill_pipe_cfg(struct device *dev,
@@ -1989,7 +2102,7 @@ static int skl_tplg_get_uuid(struct device *dev, guid_t *guid,
struct snd_soc_tplg_vendor_uuid_elem *uuid_tkn)
{
if (uuid_tkn->token == SKL_TKN_UUID) {
- guid_copy(guid, (guid_t *)&uuid_tkn->uuid);
+ import_guid(guid, uuid_tkn->uuid);
return 0;
}
@@ -3013,12 +3126,21 @@ static int skl_tplg_control_load(struct snd_soc_component *cmpnt,
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) {
+ if (kctl->access & SNDRV_CTL_ELEM_ACCESS_READ) {
se = (struct soc_enum *)kctl->private_value;
if (tplg_ec->priv.size)
- return skl_init_enum_data(bus->dev, se,
- tplg_ec);
+ skl_init_enum_data(bus->dev, se, tplg_ec);
}
+
+ /*
+ * now that the control initializations are done, remove
+ * write permission for the DMIC configuration enums to
+ * avoid conflicts between NHLT settings and user interaction
+ */
+
+ if (hdr->ops.get == SKL_CONTROL_TYPE_MULTI_IO_SELECT_DMIC)
+ kctl->access = SNDRV_CTL_ELEM_ACCESS_READ;
+
break;
default:
@@ -3376,8 +3498,8 @@ static int skl_tplg_get_manifest_tkn(struct device *dev,
dev_err(dev, "Too many UUID tokens\n");
return -EINVAL;
}
- guid_copy(&skl->modules[uuid_index++]->uuid,
- (guid_t *)&array->uuid->uuid);
+ import_guid(&skl->modules[uuid_index++]->uuid,
+ array->uuid->uuid);
tuple_size += sizeof(*array->uuid);
continue;
@@ -3488,6 +3610,37 @@ static int skl_manifest_load(struct snd_soc_component *cmpnt, int index,
return 0;
}
+static void skl_tplg_complete(struct snd_soc_component *component)
+{
+ struct snd_soc_dobj *dobj;
+ struct snd_soc_acpi_mach *mach =
+ dev_get_platdata(component->card->dev);
+ int i;
+
+ list_for_each_entry(dobj, &component->dobj_list, list) {
+ struct snd_kcontrol *kcontrol = dobj->control.kcontrol;
+ struct soc_enum *se =
+ (struct soc_enum *)kcontrol->private_value;
+ char **texts = dobj->control.dtexts;
+ char chan_text[4];
+
+ if (dobj->type != SND_SOC_DOBJ_ENUM ||
+ dobj->control.kcontrol->put !=
+ skl_tplg_multi_config_set_dmic)
+ continue;
+ sprintf(chan_text, "c%d", mach->mach_params.dmic_num);
+
+ for (i = 0; i < se->items; i++) {
+ struct snd_ctl_elem_value val;
+
+ if (strstr(texts[i], chan_text)) {
+ val.value.enumerated.item[0] = i;
+ kcontrol->put(kcontrol, &val);
+ }
+ }
+ }
+}
+
static struct snd_soc_tplg_ops skl_tplg_ops = {
.widget_load = skl_tplg_widget_load,
.control_load = skl_tplg_control_load,
@@ -3497,6 +3650,7 @@ static struct snd_soc_tplg_ops skl_tplg_ops = {
.io_ops_count = ARRAY_SIZE(skl_tplg_kcontrol_ops),
.manifest = skl_manifest_load,
.dai_load = skl_dai_load,
+ .complete = skl_tplg_complete,
};
/*
@@ -3565,8 +3719,20 @@ int skl_tplg_init(struct snd_soc_component *component, struct hdac_bus *bus)
ret = request_firmware(&fw, skl->tplg_name, bus->dev);
if (ret < 0) {
- dev_info(bus->dev, "tplg fw %s load failed with %d, falling back to dfw_sst.bin",
- skl->tplg_name, ret);
+ char alt_tplg_name[64];
+
+ snprintf(alt_tplg_name, sizeof(alt_tplg_name), "%s-tplg.bin",
+ skl->mach->drv_name);
+ dev_info(bus->dev, "tplg fw %s load failed with %d, trying alternative tplg name %s",
+ skl->tplg_name, ret, alt_tplg_name);
+
+ ret = request_firmware(&fw, alt_tplg_name, bus->dev);
+ if (!ret)
+ goto component_load;
+
+ dev_info(bus->dev, "tplg %s failed with %d, falling back to dfw_sst.bin",
+ alt_tplg_name, ret);
+
ret = request_firmware(&fw, "dfw_sst.bin", bus->dev);
if (ret < 0) {
dev_err(bus->dev, "Fallback tplg fw %s load failed with %d\n",
@@ -3575,6 +3741,8 @@ int skl_tplg_init(struct snd_soc_component *component, struct hdac_bus *bus)
}
}
+component_load:
+
/*
* The complete tplg for SKL is loaded as index 0, we don't use
* any other index
diff --git a/sound/soc/intel/skylake/skl-topology.h b/sound/soc/intel/skylake/skl-topology.h
index e967800dbb62..9889f728752c 100644
--- a/sound/soc/intel/skylake/skl-topology.h
+++ b/sound/soc/intel/skylake/skl-topology.h
@@ -119,7 +119,7 @@ struct skl_cpr_gtw_cfg {
struct skl_dma_control {
u32 node_id;
u32 config_length;
- u32 config_data[0];
+ u32 config_data[];
} __packed;
struct skl_cpr_cfg {
@@ -152,7 +152,7 @@ struct skl_up_down_mixer_cfg {
struct skl_algo_cfg {
struct skl_base_cfg base_cfg;
- char params[0];
+ char params[];
} __packed;
struct skl_base_outfmt_cfg {
@@ -306,6 +306,7 @@ struct skl_pipe {
struct skl_path_config configs[SKL_MAX_PATH_CONFIGS];
struct list_head w_list;
bool passthru;
+ u32 pipe_config_idx;
};
enum skl_module_state {
diff --git a/sound/soc/intel/skylake/skl.h b/sound/soc/intel/skylake/skl.h
index 2bfbf59277c4..26057f38a014 100644
--- a/sound/soc/intel/skylake/skl.h
+++ b/sound/soc/intel/skylake/skl.h
@@ -49,7 +49,7 @@ struct skl_astate_param {
struct skl_astate_config {
u32 count;
- struct skl_astate_param astate_table[0];
+ struct skl_astate_param astate_table[];
};
struct skl_fw_config {