summaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/codecs/Kconfig2
-rw-r--r--sound/soc/codecs/nau8822.c2
-rw-r--r--sound/soc/codecs/sgtl5000.c26
-rw-r--r--sound/soc/codecs/wm8904.c7
-rw-r--r--sound/soc/fsl/fsl_dsp.c74
-rw-r--r--sound/soc/fsl/fsl_sai.c24
-rw-r--r--sound/soc/fsl/fsl_sai.h3
-rw-r--r--sound/soc/fsl/fsl_spdif.c18
8 files changed, 149 insertions, 7 deletions
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 64c5d64cf4eb..e83c333a81cb 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -722,7 +722,7 @@ config SND_SOC_HDAC_HDA
select SND_HDA
config SND_SOC_ICS43432
- tristate
+ tristate "InvenSense ICS43432 I2S microphone codec"
config SND_SOC_INNO_RK3036
tristate "Inno codec driver for RK3036 SoC"
diff --git a/sound/soc/codecs/nau8822.c b/sound/soc/codecs/nau8822.c
index 78db3bd0b3bc..a57e7ea0c4fe 100644
--- a/sound/soc/codecs/nau8822.c
+++ b/sound/soc/codecs/nau8822.c
@@ -351,6 +351,8 @@ static const struct snd_kcontrol_new nau8822_snd_controls[] = {
NAU8822_REG_LHP_VOLUME,
NAU8822_REG_RHP_VOLUME, 0, 63, 0, spk_tlv),
+ SOC_SINGLE("Speaker RInversion Switch",
+ NAU8822_REG_RIGHT_SPEAKER_CONTROL, 4, 1, 0),
SOC_DOUBLE_R("Speaker ZC Switch",
NAU8822_REG_LSPKOUT_VOLUME,
NAU8822_REG_RSPKOUT_VOLUME, 7, 1, 0),
diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c
index 8a1e485982d8..130efc243b38 100644
--- a/sound/soc/codecs/sgtl5000.c
+++ b/sound/soc/codecs/sgtl5000.c
@@ -1514,8 +1514,34 @@ err:
return ret;
}
+static int sgtl5000_suspend(struct snd_soc_component *component)
+{
+ struct sgtl5000_priv *sgtl5000 = snd_soc_component_get_drvdata(component);
+
+ clk_disable_unprepare(sgtl5000->mclk);
+
+ return 0;
+}
+
+static int sgtl5000_resume(struct snd_soc_component *component)
+{
+ int ret;
+ struct sgtl5000_priv *sgtl5000 = snd_soc_component_get_drvdata(component);
+
+ ret = clk_prepare_enable(sgtl5000->mclk);
+ if (ret)
+ dev_err(component->dev, "Error enabling clock %d\n", ret);
+
+ /* Need 8 clocks before I2C accesses */
+ udelay(1);
+
+ return ret;
+}
+
static const struct snd_soc_component_driver sgtl5000_driver = {
.probe = sgtl5000_probe,
+ .suspend = sgtl5000_suspend,
+ .resume = sgtl5000_resume,
.set_bias_level = sgtl5000_set_bias_level,
.controls = sgtl5000_snd_controls,
.num_controls = ARRAY_SIZE(sgtl5000_snd_controls),
diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c
index 9e8c564f6e9c..b174a9381c0c 100644
--- a/sound/soc/codecs/wm8904.c
+++ b/sound/soc/codecs/wm8904.c
@@ -1417,6 +1417,13 @@ static int wm8904_set_sysclk(struct snd_soc_dai *dai, int clk_id,
struct snd_soc_component *component = dai->component;
struct wm8904_priv *priv = snd_soc_component_get_drvdata(component);
+ /*
+ * If using sound-simple-card this is called with clk_id fixed to 0.
+ * Assume we want WM8904_CLK_MCLK for now in that case.
+ */
+ if (clk_id == 0)
+ clk_id = WM8904_CLK_MCLK;
+
switch (clk_id) {
case WM8904_CLK_MCLK:
priv->sysclk_src = clk_id;
diff --git a/sound/soc/fsl/fsl_dsp.c b/sound/soc/fsl/fsl_dsp.c
index e64f9bb8af71..1bb72b10e41a 100644
--- a/sound/soc/fsl/fsl_dsp.c
+++ b/sound/soc/fsl/fsl_dsp.c
@@ -70,6 +70,63 @@
#include "fsl_dsp_pool.h"
#include "fsl_dsp_xaf_api.h"
+#define DSP_DISABLE_FUSE 0x8
+#define DSP_DISABLE_MASK 0x1
+
+struct dsp_sc_msg_misc {
+ struct imx_sc_rpc_msg hdr;
+ u32 word;
+} __packed;
+
+static int dsp_sc_get_fuse(struct imx_sc_ipc *ipc, u32 word, u32 *fuse)
+{
+ struct dsp_sc_msg_misc msg;
+ struct imx_sc_rpc_msg *hdr = &msg.hdr;
+ int ret;
+
+ hdr->ver = IMX_SC_RPC_VERSION;
+ hdr->svc = IMX_SC_RPC_SVC_MISC;
+ hdr->func = IMX_SC_MISC_FUNC_OTP_FUSE_READ;
+ hdr->size = 2;
+
+ msg.word = word;
+
+ ret = imx_scu_call_rpc(ipc, &msg, true);
+ if (ret)
+ return ret;
+
+ *fuse = msg.word;
+
+ return ret;
+}
+
+static int check_dsp_is_available(void)
+{
+ uint32_t fuse = 0xffff;
+ int ret = 0;
+ struct imx_sc_ipc *ipcHandle;;
+
+ ret = imx_scu_get_handle(&ipcHandle);
+ if (ret) {
+ /* We're not running on a iMX8 or iMX8X, so there is no DSP */
+ return -EINVAL;
+ }
+
+ ret = dsp_sc_get_fuse(ipcHandle, DSP_DISABLE_FUSE, &fuse);
+ if (ret) {
+ pr_err("sc_misc_otp_fuse_read fail! %d\n", ret);
+ return -EINVAL;
+ }
+
+ pr_debug("DSP disable fuse[%i] = 0x%x\n", DSP_DISABLE_FUSE, fuse);
+ if (fuse & DSP_DISABLE_MASK) {
+ pr_info("%s: HiFi4 DSP not available on this silicon\n", __func__);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
/* ...allocate new client */
struct xf_client *xf_client_alloc(struct fsl_dsp *dsp_priv)
{
@@ -1653,7 +1710,22 @@ static struct platform_driver fsl_dsp_driver = {
.pm = &fsl_dsp_pm,
},
};
-module_platform_driver(fsl_dsp_driver);
+
+static int __init fsl_dsp_driver_init(void)
+{
+ /* do not install the driver if no DSP is found */
+ if (check_dsp_is_available())
+ return -EINVAL;
+
+ return platform_driver_register(&fsl_dsp_driver);
+}
+module_init(fsl_dsp_driver_init);
+
+static void __exit fsl_dsp_driver_exit(void)
+{
+ platform_driver_unregister(&fsl_dsp_driver);
+}
+module_exit(fsl_dsp_driver_exit);
MODULE_DESCRIPTION("Freescale DSP driver");
MODULE_ALIAS("platform:fsl-dsp");
diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c
index d9958a52e871..ec572612bb50 100644
--- a/sound/soc/fsl/fsl_sai.c
+++ b/sound/soc/fsl/fsl_sai.c
@@ -73,6 +73,17 @@ static struct fsl_sai_soc_data fsl_sai_imx7ulp = {
.constrain_period_size = false,
};
+static struct fsl_sai_soc_data fsl_sai_imx8mp = {
+ .imx = true,
+ .dataline = 0xff,
+ .fifos = 8,
+ .fifo_depth = 128,
+ .flags = 0,
+ .reg_offset = 8,
+ .constrain_period_size = false,
+ .mclk_gated_by_bce = true,
+};
+
static struct fsl_sai_soc_data fsl_sai_imx8mq = {
.imx = true,
.dataline = 0xff,
@@ -782,6 +793,18 @@ static int fsl_sai_hw_params(struct snd_pcm_substream *substream,
FSL_SAI_CR5_FBT_MASK, val_cr5);
regmap_write(sai->regmap, FSL_SAI_xMR(tx),
~0UL - ((1 << min(channels, slots)) - 1));
+
+ /*
+ * Some audio codecs need the MCLK during setup of the codec, however
+ * for the i.MX 8M Plus it is gated with the receiver/transmiter BCE
+ * bit. So enable the bit already here.
+ */
+ if (sai->soc->mclk_gated_by_bce) {
+ /* Switch on MCLK early */
+ regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx, offset),
+ FSL_SAI_CSR_BCE, FSL_SAI_CSR_BCE);
+ }
+
return 0;
}
@@ -1270,6 +1293,7 @@ static const struct of_device_id fsl_sai_ids[] = {
{ .compatible = "fsl,imx6sx-sai", .data = &fsl_sai_imx6sx },
{ .compatible = "fsl,imx6ul-sai", .data = &fsl_sai_imx6ul },
{ .compatible = "fsl,imx7ulp-sai", .data = &fsl_sai_imx7ulp },
+ { .compatible = "fsl,imx8mp-sai", .data = &fsl_sai_imx8mp },
{ .compatible = "fsl,imx8mq-sai", .data = &fsl_sai_imx8mq },
{ .compatible = "fsl,imx8qm-sai", .data = &fsl_sai_imx8qm },
{ /* sentinel */ }
diff --git a/sound/soc/fsl/fsl_sai.h b/sound/soc/fsl/fsl_sai.h
index 8476cfffaa25..54e491182db8 100644
--- a/sound/soc/fsl/fsl_sai.h
+++ b/sound/soc/fsl/fsl_sai.h
@@ -89,6 +89,7 @@
/* SAI Transmit/Receive Control Register */
#define FSL_SAI_CSR_TERE BIT(31)
#define FSL_SAI_CSR_SE BIT(30)
+#define FSL_SAI_CSR_BCE BIT(28)
#define FSL_SAI_CSR_FR BIT(25)
#define FSL_SAI_CSR_SR BIT(24)
#define FSL_SAI_CSR_xF_SHIFT 16
@@ -225,6 +226,8 @@ struct fsl_sai_soc_data {
bool imx;
/* True for EDMA because it needs period size multiple of maxburst */
bool constrain_period_size;
+ /* Set to true if the MCLK to the output pin is gated with bce */
+ bool mclk_gated_by_bce;
};
struct fsl_sai_verid {
diff --git a/sound/soc/fsl/fsl_spdif.c b/sound/soc/fsl/fsl_spdif.c
index 49f5a8551143..07f9ae81861c 100644
--- a/sound/soc/fsl/fsl_spdif.c
+++ b/sound/soc/fsl/fsl_spdif.c
@@ -530,10 +530,10 @@ static int fsl_spdif_startup(struct snd_pcm_substream *substream,
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
scr = SCR_TXFIFO_AUTOSYNC | SCR_TXFIFO_CTRL_NORMAL |
SCR_TXSEL_NORMAL | SCR_USRC_SEL_CHIP |
- SCR_TXFIFO_FSEL_IF8;
+ SCR_TXFIFO_FSEL_IF8 | SCR_VAL_CLEAR;
mask = SCR_TXFIFO_AUTOSYNC_MASK | SCR_TXFIFO_CTRL_MASK |
SCR_TXSEL_MASK | SCR_USRC_SEL_MASK |
- SCR_TXFIFO_FSEL_MASK;
+ SCR_TXFIFO_FSEL_MASK | SCR_VAL_MASK;
} else {
scr = SCR_RXFIFO_FSEL_IF8 | SCR_RXFIFO_AUTOSYNC;
mask = SCR_RXFIFO_FSEL_MASK | SCR_RXFIFO_AUTOSYNC_MASK|
@@ -1525,12 +1525,20 @@ static int fsl_spdif_probe(struct platform_device *pdev)
&spdif_priv->cpu_dai_drv, 1);
if (ret) {
dev_err(&pdev->dev, "failed to register DAI: %d\n", ret);
- return ret;
+ goto disable_pm_runtime;
}
ret = imx_pcm_dma_init(pdev, IMX_SPDIF_DMABUF_SIZE);
- if (ret && ret != -EPROBE_DEFER)
- dev_err(&pdev->dev, "imx_pcm_dma_init failed: %d\n", ret);
+ if (ret) {
+ if (ret != -EPROBE_DEFER)
+ dev_err(&pdev->dev, "imx_pcm_dma_init failed: %d\n", ret);
+ goto disable_pm_runtime;
+ }
+
+ return 0;
+
+disable_pm_runtime:
+ pm_runtime_disable(&pdev->dev);
return ret;
}