[RESEND v2 2/3] ASoC: fsl_xcvr: Add support for i.MX93 platform
Shengjiu Wang
shengjiu.wang at gmail.com
Thu Jan 5 10:54:47 CET 2023
On Wed, Jan 4, 2023 at 10:40 AM Chancel Liu <chancel.liu at nxp.com> wrote:
> Add compatible string and specific soc data to support XCVR on i.MX93
> platform. XCVR IP on i.MX93 is cut to SPDIF only by removing external
> PHY.
>
> Signed-off-by: Chancel Liu <chancel.liu at nxp.com>
>
Acked-by: Shengjiu Wang <shengjiu.wang at gmail.com>
best regards
wang Shengjiu
> ---
> sound/soc/fsl/fsl_xcvr.c | 143 ++++++++++++++++++++++++++-------------
> sound/soc/fsl/fsl_xcvr.h | 7 ++
> 2 files changed, 102 insertions(+), 48 deletions(-)
>
> diff --git a/sound/soc/fsl/fsl_xcvr.c b/sound/soc/fsl/fsl_xcvr.c
> index 2a6802fb2a8b..b794158a7876 100644
> --- a/sound/soc/fsl/fsl_xcvr.c
> +++ b/sound/soc/fsl/fsl_xcvr.c
> @@ -21,6 +21,7 @@
>
> struct fsl_xcvr_soc_data {
> const char *fw_name;
> + bool spdif_only;
> };
>
> struct fsl_xcvr {
> @@ -261,6 +262,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 +357,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 +370,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);
> @@ -547,10 +554,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 +576,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 +683,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 +890,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 +947,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 +984,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 +1015,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 +1057,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 +1138,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 +1205,13 @@ 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,
> +};
> +
> 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 +1271,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 +1348,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 +1411,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
> --
> 2.25.1
>
>
More information about the Alsa-devel
mailing list