diff options
Diffstat (limited to 'sound')
-rw-r--r-- | sound/soc/codecs/Kconfig | 2 | ||||
-rw-r--r-- | sound/soc/codecs/nau8822.c | 2 | ||||
-rw-r--r-- | sound/soc/codecs/sgtl5000.c | 26 | ||||
-rw-r--r-- | sound/soc/codecs/wm8904.c | 7 | ||||
-rw-r--r-- | sound/soc/fsl/fsl_dsp.c | 74 | ||||
-rw-r--r-- | sound/soc/fsl/fsl_sai.c | 24 | ||||
-rw-r--r-- | sound/soc/fsl/fsl_sai.h | 3 | ||||
-rw-r--r-- | sound/soc/fsl/fsl_spdif.c | 18 |
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; } |