summaryrefslogtreecommitdiff
path: root/sound/soc/fsl
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/fsl')
-rw-r--r--sound/soc/fsl/fsl-asoc-card.c4
-rw-r--r--sound/soc/fsl/fsl_sai.c6
-rw-r--r--sound/soc/fsl/fsl_xcvr.c155
-rw-r--r--sound/soc/fsl/fsl_xcvr.h7
-rw-r--r--sound/soc/fsl/imx-hdmi.c2
-rw-r--r--sound/soc/fsl/imx-pcm-rpmsg.c6
6 files changed, 124 insertions, 56 deletions
diff --git a/sound/soc/fsl/fsl-asoc-card.c b/sound/soc/fsl/fsl-asoc-card.c
index 8d14b5593658..8099a829c304 100644
--- a/sound/soc/fsl/fsl-asoc-card.c
+++ b/sound/soc/fsl/fsl-asoc-card.c
@@ -297,7 +297,7 @@ SND_SOC_DAILINK_DEFS(hifi_be,
DAILINK_COMP_ARRAY(COMP_EMPTY()),
DAILINK_COMP_ARRAY(COMP_DUMMY()));
-static struct snd_soc_dai_link fsl_asoc_card_dai[] = {
+static const struct snd_soc_dai_link fsl_asoc_card_dai[] = {
/* Default ASoC DAI Link*/
{
.name = "HiFi",
@@ -855,7 +855,7 @@ static int fsl_asoc_card_probe(struct platform_device *pdev)
ret = devm_snd_soc_register_card(&pdev->dev, &priv->card);
if (ret) {
- dev_err_probe(&pdev->dev, ret, "snd_soc_register_card failed\n");
+ dev_err_probe(&pdev->dev, ret, "snd_soc_register_card failed: %d\n", ret);
goto asrc_fail;
}
diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c
index 35a52c3a020d..1b197478b3d9 100644
--- a/sound/soc/fsl/fsl_sai.c
+++ b/sound/soc/fsl/fsl_sai.c
@@ -281,6 +281,7 @@ static int fsl_sai_set_dai_fmt_tr(struct snd_soc_dai *cpu_dai,
val_cr4 |= FSL_SAI_CR4_MF;
sai->is_pdm_mode = false;
+ sai->is_dsp_mode = false;
/* DAI mode */
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
case SND_SOC_DAIFMT_I2S:
@@ -1459,14 +1460,17 @@ static int fsl_sai_probe(struct platform_device *pdev)
if (sai->soc_data->use_imx_pcm) {
ret = imx_pcm_dma_init(pdev);
if (ret) {
+ dev_err_probe(dev, ret, "PCM DMA init failed\n");
if (!IS_ENABLED(CONFIG_SND_SOC_IMX_PCM_DMA))
dev_err(dev, "Error: You must enable the imx-pcm-dma support!\n");
goto err_pm_get_sync;
}
} else {
ret = devm_snd_dmaengine_pcm_register(dev, NULL, 0);
- if (ret)
+ if (ret) {
+ dev_err_probe(dev, ret, "Registering PCM dmaengine failed\n");
goto err_pm_get_sync;
+ }
}
ret = devm_snd_soc_register_component(dev, &fsl_component,
diff --git a/sound/soc/fsl/fsl_xcvr.c b/sound/soc/fsl/fsl_xcvr.c
index 2a6802fb2a8b..2a78243df752 100644
--- a/sound/soc/fsl/fsl_xcvr.c
+++ b/sound/soc/fsl/fsl_xcvr.c
@@ -21,6 +21,8 @@
struct fsl_xcvr_soc_data {
const char *fw_name;
+ bool spdif_only;
+ bool use_edma;
};
struct fsl_xcvr {
@@ -261,6 +263,9 @@ static int fsl_xcvr_en_phy_pll(struct fsl_xcvr *xcvr, u32 freq, bool tx)
u32 i, div = 0, log2;
int ret;
+ if (xcvr->soc_data->spdif_only)
+ return 0;
+
for (i = 0; i < ARRAY_SIZE(fsl_xcvr_pll_cfg); i++) {
if (fsl_xcvr_pll_cfg[i].fout % freq == 0) {
div = fsl_xcvr_pll_cfg[i].fout / freq;
@@ -353,6 +358,7 @@ static int fsl_xcvr_en_aud_pll(struct fsl_xcvr *xcvr, u32 freq)
struct device *dev = &xcvr->pdev->dev;
int ret;
+ freq = xcvr->soc_data->spdif_only ? freq / 10 : freq;
clk_disable_unprepare(xcvr->phy_clk);
ret = clk_set_rate(xcvr->phy_clk, freq);
if (ret < 0) {
@@ -365,6 +371,8 @@ static int fsl_xcvr_en_aud_pll(struct fsl_xcvr *xcvr, u32 freq)
return ret;
}
+ if (xcvr->soc_data->spdif_only)
+ return 0;
/* Release AI interface from reset */
ret = regmap_write(xcvr->regmap, FSL_XCVR_PHY_AI_CTRL_SET,
FSL_XCVR_PHY_AI_CTRL_AI_RESETN);
@@ -531,6 +539,16 @@ static int fsl_xcvr_startup(struct snd_pcm_substream *substream,
return -EBUSY;
}
+ /*
+ * EDMA controller needs period size to be a multiple of
+ * tx/rx maxburst
+ */
+ if (xcvr->soc_data->use_edma)
+ snd_pcm_hw_constraint_step(substream->runtime, 0,
+ SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
+ tx ? xcvr->dma_prms_tx.maxburst :
+ xcvr->dma_prms_rx.maxburst);
+
switch (xcvr->mode) {
case FSL_XCVR_MODE_SPDIF:
case FSL_XCVR_MODE_ARC:
@@ -547,10 +565,12 @@ static int fsl_xcvr_startup(struct snd_pcm_substream *substream,
xcvr->streams |= BIT(substream->stream);
- /* Disable XCVR controls if there is stream started */
- fsl_xcvr_activate_ctl(dai, fsl_xcvr_mode_kctl.name, false);
- fsl_xcvr_activate_ctl(dai, fsl_xcvr_arc_mode_kctl.name, false);
- fsl_xcvr_activate_ctl(dai, fsl_xcvr_earc_capds_kctl.name, false);
+ if (!xcvr->soc_data->spdif_only) {
+ /* Disable XCVR controls if there is stream started */
+ fsl_xcvr_activate_ctl(dai, fsl_xcvr_mode_kctl.name, false);
+ fsl_xcvr_activate_ctl(dai, fsl_xcvr_arc_mode_kctl.name, false);
+ fsl_xcvr_activate_ctl(dai, fsl_xcvr_earc_capds_kctl.name, false);
+ }
return 0;
}
@@ -567,12 +587,13 @@ static void fsl_xcvr_shutdown(struct snd_pcm_substream *substream,
/* Enable XCVR controls if there is no stream started */
if (!xcvr->streams) {
- fsl_xcvr_activate_ctl(dai, fsl_xcvr_mode_kctl.name, true);
- fsl_xcvr_activate_ctl(dai, fsl_xcvr_arc_mode_kctl.name,
- (xcvr->mode == FSL_XCVR_MODE_ARC));
- fsl_xcvr_activate_ctl(dai, fsl_xcvr_earc_capds_kctl.name,
- (xcvr->mode == FSL_XCVR_MODE_EARC));
-
+ if (!xcvr->soc_data->spdif_only) {
+ fsl_xcvr_activate_ctl(dai, fsl_xcvr_mode_kctl.name, true);
+ fsl_xcvr_activate_ctl(dai, fsl_xcvr_arc_mode_kctl.name,
+ (xcvr->mode == FSL_XCVR_MODE_ARC));
+ fsl_xcvr_activate_ctl(dai, fsl_xcvr_earc_capds_kctl.name,
+ (xcvr->mode == FSL_XCVR_MODE_EARC));
+ }
ret = regmap_update_bits(xcvr->regmap, FSL_XCVR_EXT_IER0,
FSL_XCVR_IRQ_EARC_ALL, 0);
if (ret < 0) {
@@ -673,7 +694,10 @@ static int fsl_xcvr_trigger(struct snd_pcm_substream *substream, int cmd,
dev_err(dai->dev, "Failed to stop DATA_TX: %d\n", ret);
return ret;
}
- fallthrough;
+ if (xcvr->soc_data->spdif_only)
+ break;
+ else
+ fallthrough;
case FSL_XCVR_MODE_EARC:
/* clear ISR_CMDC_TX_EN, W1C */
ret = regmap_write(xcvr->regmap,
@@ -877,9 +901,13 @@ static int fsl_xcvr_dai_probe(struct snd_soc_dai *dai)
snd_soc_dai_init_dma_data(dai, &xcvr->dma_prms_tx, &xcvr->dma_prms_rx);
- snd_soc_add_dai_controls(dai, &fsl_xcvr_mode_kctl, 1);
- snd_soc_add_dai_controls(dai, &fsl_xcvr_arc_mode_kctl, 1);
- snd_soc_add_dai_controls(dai, &fsl_xcvr_earc_capds_kctl, 1);
+ if (xcvr->soc_data->spdif_only)
+ xcvr->mode = FSL_XCVR_MODE_SPDIF;
+ else {
+ snd_soc_add_dai_controls(dai, &fsl_xcvr_mode_kctl, 1);
+ snd_soc_add_dai_controls(dai, &fsl_xcvr_arc_mode_kctl, 1);
+ snd_soc_add_dai_controls(dai, &fsl_xcvr_earc_capds_kctl, 1);
+ }
snd_soc_add_dai_controls(dai, fsl_xcvr_tx_ctls,
ARRAY_SIZE(fsl_xcvr_tx_ctls));
snd_soc_add_dai_controls(dai, fsl_xcvr_rx_ctls,
@@ -930,10 +958,11 @@ static const struct reg_default fsl_xcvr_reg_defaults[] = {
{ FSL_XCVR_ISR_SET, 0x00000000 },
{ FSL_XCVR_ISR_CLR, 0x00000000 },
{ FSL_XCVR_ISR_TOG, 0x00000000 },
- { FSL_XCVR_RX_DPTH_CTRL, 0x00002C89 },
- { FSL_XCVR_RX_DPTH_CTRL_SET, 0x00002C89 },
- { FSL_XCVR_RX_DPTH_CTRL_CLR, 0x00002C89 },
- { FSL_XCVR_RX_DPTH_CTRL_TOG, 0x00002C89 },
+ { FSL_XCVR_CLK_CTRL, 0x0000018F },
+ { FSL_XCVR_RX_DPTH_CTRL, 0x00040CC1 },
+ { FSL_XCVR_RX_DPTH_CTRL_SET, 0x00040CC1 },
+ { FSL_XCVR_RX_DPTH_CTRL_CLR, 0x00040CC1 },
+ { FSL_XCVR_RX_DPTH_CTRL_TOG, 0x00040CC1 },
{ FSL_XCVR_RX_DPTH_CNTR_CTRL, 0x00000000 },
{ FSL_XCVR_RX_DPTH_CNTR_CTRL_SET, 0x00000000 },
{ FSL_XCVR_RX_DPTH_CNTR_CTRL_CLR, 0x00000000 },
@@ -966,6 +995,12 @@ static const struct reg_default fsl_xcvr_reg_defaults[] = {
static bool fsl_xcvr_readable_reg(struct device *dev, unsigned int reg)
{
+ struct fsl_xcvr *xcvr = dev_get_drvdata(dev);
+
+ if (xcvr->soc_data->spdif_only)
+ if ((reg >= FSL_XCVR_IER && reg <= FSL_XCVR_PHY_AI_RDATA) ||
+ reg > FSL_XCVR_TX_DPTH_BCRR)
+ return false;
switch (reg) {
case FSL_XCVR_VERSION:
case FSL_XCVR_EXT_CTRL:
@@ -991,6 +1026,12 @@ static bool fsl_xcvr_readable_reg(struct device *dev, unsigned int reg)
case FSL_XCVR_RX_DPTH_CTRL_SET:
case FSL_XCVR_RX_DPTH_CTRL_CLR:
case FSL_XCVR_RX_DPTH_CTRL_TOG:
+ case FSL_XCVR_RX_CS_DATA_0:
+ case FSL_XCVR_RX_CS_DATA_1:
+ case FSL_XCVR_RX_CS_DATA_2:
+ case FSL_XCVR_RX_CS_DATA_3:
+ case FSL_XCVR_RX_CS_DATA_4:
+ case FSL_XCVR_RX_CS_DATA_5:
case FSL_XCVR_RX_DPTH_CNTR_CTRL:
case FSL_XCVR_RX_DPTH_CNTR_CTRL_SET:
case FSL_XCVR_RX_DPTH_CNTR_CTRL_CLR:
@@ -1027,6 +1068,11 @@ static bool fsl_xcvr_readable_reg(struct device *dev, unsigned int reg)
static bool fsl_xcvr_writeable_reg(struct device *dev, unsigned int reg)
{
+ struct fsl_xcvr *xcvr = dev_get_drvdata(dev);
+
+ if (xcvr->soc_data->spdif_only)
+ if (reg >= FSL_XCVR_IER && reg <= FSL_XCVR_PHY_AI_RDATA)
+ return false;
switch (reg) {
case FSL_XCVR_EXT_CTRL:
case FSL_XCVR_EXT_IER0:
@@ -1103,32 +1149,34 @@ static irqreturn_t irq0_isr(int irq, void *devid)
if (isr & FSL_XCVR_IRQ_NEW_CS) {
dev_dbg(dev, "Received new CS block\n");
isr_clr |= FSL_XCVR_IRQ_NEW_CS;
- /* Data RAM is 4KiB, last two pages: 8 and 9. Select page 8. */
- regmap_update_bits(xcvr->regmap, FSL_XCVR_EXT_CTRL,
- FSL_XCVR_EXT_CTRL_PAGE_MASK,
- FSL_XCVR_EXT_CTRL_PAGE(8));
-
- /* Find updated CS buffer */
- reg_ctrl = xcvr->ram_addr + FSL_XCVR_RX_CS_CTRL_0;
- reg_buff = xcvr->ram_addr + FSL_XCVR_RX_CS_BUFF_0;
- memcpy_fromio(&val, reg_ctrl, sizeof(val));
- if (!val) {
- reg_ctrl = xcvr->ram_addr + FSL_XCVR_RX_CS_CTRL_1;
- reg_buff = xcvr->ram_addr + FSL_XCVR_RX_CS_BUFF_1;
+ if (!xcvr->soc_data->spdif_only) {
+ /* Data RAM is 4KiB, last two pages: 8 and 9. Select page 8. */
+ regmap_update_bits(xcvr->regmap, FSL_XCVR_EXT_CTRL,
+ FSL_XCVR_EXT_CTRL_PAGE_MASK,
+ FSL_XCVR_EXT_CTRL_PAGE(8));
+
+ /* Find updated CS buffer */
+ reg_ctrl = xcvr->ram_addr + FSL_XCVR_RX_CS_CTRL_0;
+ reg_buff = xcvr->ram_addr + FSL_XCVR_RX_CS_BUFF_0;
memcpy_fromio(&val, reg_ctrl, sizeof(val));
- }
+ if (!val) {
+ reg_ctrl = xcvr->ram_addr + FSL_XCVR_RX_CS_CTRL_1;
+ reg_buff = xcvr->ram_addr + FSL_XCVR_RX_CS_BUFF_1;
+ memcpy_fromio(&val, reg_ctrl, sizeof(val));
+ }
- if (val) {
- /* copy CS buffer */
- memcpy_fromio(&xcvr->rx_iec958.status, reg_buff,
- sizeof(xcvr->rx_iec958.status));
- for (i = 0; i < 6; i++) {
- val = *(u32 *)(xcvr->rx_iec958.status + i*4);
- *(u32 *)(xcvr->rx_iec958.status + i*4) =
- bitrev32(val);
+ if (val) {
+ /* copy CS buffer */
+ memcpy_fromio(&xcvr->rx_iec958.status, reg_buff,
+ sizeof(xcvr->rx_iec958.status));
+ for (i = 0; i < 6; i++) {
+ val = *(u32 *)(xcvr->rx_iec958.status + i*4);
+ *(u32 *)(xcvr->rx_iec958.status + i*4) =
+ bitrev32(val);
+ }
+ /* clear CS control register */
+ memset_io(reg_ctrl, 0, sizeof(val));
}
- /* clear CS control register */
- memset_io(reg_ctrl, 0, sizeof(val));
}
}
if (isr & FSL_XCVR_IRQ_NEW_UD) {
@@ -1168,8 +1216,14 @@ static const struct fsl_xcvr_soc_data fsl_xcvr_imx8mp_data = {
.fw_name = "imx/xcvr/xcvr-imx8mp.bin",
};
+static const struct fsl_xcvr_soc_data fsl_xcvr_imx93_data = {
+ .spdif_only = true,
+ .use_edma = true,
+};
+
static const struct of_device_id fsl_xcvr_dt_ids[] = {
{ .compatible = "fsl,imx8mp-xcvr", .data = &fsl_xcvr_imx8mp_data },
+ { .compatible = "fsl,imx93-xcvr", .data = &fsl_xcvr_imx93_data},
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, fsl_xcvr_dt_ids);
@@ -1229,7 +1283,7 @@ static int fsl_xcvr_probe(struct platform_device *pdev)
return PTR_ERR(xcvr->regmap);
}
- xcvr->reset = devm_reset_control_get_exclusive(dev, NULL);
+ xcvr->reset = devm_reset_control_get_optional_exclusive(dev, NULL);
if (IS_ERR(xcvr->reset)) {
dev_err(dev, "failed to get XCVR reset control\n");
return PTR_ERR(xcvr->reset);
@@ -1306,12 +1360,14 @@ static __maybe_unused int fsl_xcvr_runtime_suspend(struct device *dev)
if (ret < 0)
dev_err(dev, "Failed to clear IER0: %d\n", ret);
- /* Assert M0+ reset */
- ret = regmap_update_bits(xcvr->regmap, FSL_XCVR_EXT_CTRL,
- FSL_XCVR_EXT_CTRL_CORE_RESET,
- FSL_XCVR_EXT_CTRL_CORE_RESET);
- if (ret < 0)
- dev_err(dev, "Failed to assert M0+ core: %d\n", ret);
+ if (!xcvr->soc_data->spdif_only) {
+ /* Assert M0+ reset */
+ ret = regmap_update_bits(xcvr->regmap, FSL_XCVR_EXT_CTRL,
+ FSL_XCVR_EXT_CTRL_CORE_RESET,
+ FSL_XCVR_EXT_CTRL_CORE_RESET);
+ if (ret < 0)
+ dev_err(dev, "Failed to assert M0+ core: %d\n", ret);
+ }
regcache_cache_only(xcvr->regmap, true);
@@ -1367,6 +1423,9 @@ static __maybe_unused int fsl_xcvr_runtime_resume(struct device *dev)
goto stop_spba_clk;
}
+ if (xcvr->soc_data->spdif_only)
+ return 0;
+
ret = reset_control_deassert(xcvr->reset);
if (ret) {
dev_err(dev, "failed to deassert M0+ reset.\n");
diff --git a/sound/soc/fsl/fsl_xcvr.h b/sound/soc/fsl/fsl_xcvr.h
index 4769b0fca21d..044058fc6aa2 100644
--- a/sound/soc/fsl/fsl_xcvr.h
+++ b/sound/soc/fsl/fsl_xcvr.h
@@ -49,6 +49,13 @@
#define FSL_XCVR_RX_DPTH_CTRL_CLR 0x188
#define FSL_XCVR_RX_DPTH_CTRL_TOG 0x18c
+#define FSL_XCVR_RX_CS_DATA_0 0x190
+#define FSL_XCVR_RX_CS_DATA_1 0x194
+#define FSL_XCVR_RX_CS_DATA_2 0x198
+#define FSL_XCVR_RX_CS_DATA_3 0x19C
+#define FSL_XCVR_RX_CS_DATA_4 0x1A0
+#define FSL_XCVR_RX_CS_DATA_5 0x1A4
+
#define FSL_XCVR_RX_DPTH_CNTR_CTRL 0x1C0
#define FSL_XCVR_RX_DPTH_CNTR_CTRL_SET 0x1C4
#define FSL_XCVR_RX_DPTH_CNTR_CTRL_CLR 0x1C8
diff --git a/sound/soc/fsl/imx-hdmi.c b/sound/soc/fsl/imx-hdmi.c
index a780cf5a65ff..b6cc7e6c2a32 100644
--- a/sound/soc/fsl/imx-hdmi.c
+++ b/sound/soc/fsl/imx-hdmi.c
@@ -202,7 +202,7 @@ static int imx_hdmi_probe(struct platform_device *pdev)
snd_soc_card_set_drvdata(&data->card, data);
ret = devm_snd_soc_register_card(&pdev->dev, &data->card);
if (ret) {
- dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret);
+ dev_err_probe(&pdev->dev, ret, "snd_soc_register_card failed\n");
goto fail;
}
diff --git a/sound/soc/fsl/imx-pcm-rpmsg.c b/sound/soc/fsl/imx-pcm-rpmsg.c
index 2f310994f7ee..6614b3447649 100644
--- a/sound/soc/fsl/imx-pcm-rpmsg.c
+++ b/sound/soc/fsl/imx-pcm-rpmsg.c
@@ -140,7 +140,6 @@ static int imx_rpmsg_pcm_hw_params(struct snd_soc_component *component,
{
struct rpmsg_info *info = dev_get_drvdata(component->dev);
struct rpmsg_msg *msg;
- int ret = 0;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
msg = &info->msg[TX_HW_PARAM];
@@ -184,7 +183,7 @@ static int imx_rpmsg_pcm_hw_params(struct snd_soc_component *component,
info->send_message(msg, info);
- return ret;
+ return 0;
}
static snd_pcm_uframes_t imx_rpmsg_pcm_pointer(struct snd_soc_component *component,
@@ -282,7 +281,6 @@ static int imx_rpmsg_pcm_close(struct snd_soc_component *component,
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
struct rpmsg_info *info = dev_get_drvdata(component->dev);
struct rpmsg_msg *msg;
- int ret = 0;
/* Flush work in workqueue to make TX_CLOSE is the last message */
flush_workqueue(info->rpmsg_wq);
@@ -305,7 +303,7 @@ static int imx_rpmsg_pcm_close(struct snd_soc_component *component,
dev_warn(rtd->dev, "Msg is dropped!, number is %d\n",
info->msg_drop_count[substream->stream]);
- return ret;
+ return 0;
}
static int imx_rpmsg_pcm_prepare(struct snd_soc_component *component,