[RESEND v2 0/3] Add support for XCVR on i.MX93 platform
This patchset supports XCVR on i.MX93 platform.
changes in v2: - remove unnecessary code which causes kernel test robot reporting error
Chancel Liu (3): ASoC: dt-bindings: fsl,xcvr: Add compatible string for i.MX93 platform ASoC: fsl_xcvr: Add support for i.MX93 platform ASoC: fsl_xcvr: Add constraints of period size while using eDMA
.../devicetree/bindings/sound/fsl,xcvr.yaml | 1 + sound/soc/fsl/fsl_xcvr.c | 155 ++++++++++++------ sound/soc/fsl/fsl_xcvr.h | 7 + 3 files changed, 115 insertions(+), 48 deletions(-)
-- 2.25.1
Add compatible string "fsl,imx93-xcvr" for i.MX93 platform.
Acked-by: Krzysztof Kozlowski krzysztof.kozlowski@linaro.org Signed-off-by: Chancel Liu chancel.liu@nxp.com --- Documentation/devicetree/bindings/sound/fsl,xcvr.yaml | 1 + 1 file changed, 1 insertion(+)
diff --git a/Documentation/devicetree/bindings/sound/fsl,xcvr.yaml b/Documentation/devicetree/bindings/sound/fsl,xcvr.yaml index 223b8ea693dc..799b362ba498 100644 --- a/Documentation/devicetree/bindings/sound/fsl,xcvr.yaml +++ b/Documentation/devicetree/bindings/sound/fsl,xcvr.yaml @@ -21,6 +21,7 @@ properties: compatible: enum: - fsl,imx8mp-xcvr + - fsl,imx93-xcvr
reg: items:
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@nxp.com --- 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
On Wed, Jan 4, 2023 at 10:40 AM Chancel Liu chancel.liu@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@nxp.com
Acked-by: Shengjiu Wang shengjiu.wang@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
- */
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
eDMA on i.MX93 platform requires the period size to be multiple of maxburst.
Signed-off-by: Chancel Liu chancel.liu@nxp.com --- sound/soc/fsl/fsl_xcvr.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
diff --git a/sound/soc/fsl/fsl_xcvr.c b/sound/soc/fsl/fsl_xcvr.c index b794158a7876..2a78243df752 100644 --- a/sound/soc/fsl/fsl_xcvr.c +++ b/sound/soc/fsl/fsl_xcvr.c @@ -22,6 +22,7 @@ struct fsl_xcvr_soc_data { const char *fw_name; bool spdif_only; + bool use_edma; };
struct fsl_xcvr { @@ -538,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: @@ -1207,6 +1218,7 @@ static const struct fsl_xcvr_soc_data fsl_xcvr_imx8mp_data = {
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[] = {
On Wed, Jan 4, 2023 at 10:40 AM Chancel Liu chancel.liu@nxp.com wrote:
eDMA on i.MX93 platform requires the period size to be multiple of maxburst.
Signed-off-by: Chancel Liu chancel.liu@nxp.com
Acked-by: Shengjiu Wang shengjiu.wang@gmail.com
Best regards Wang shengjiu
sound/soc/fsl/fsl_xcvr.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
diff --git a/sound/soc/fsl/fsl_xcvr.c b/sound/soc/fsl/fsl_xcvr.c index b794158a7876..2a78243df752 100644 --- a/sound/soc/fsl/fsl_xcvr.c +++ b/sound/soc/fsl/fsl_xcvr.c @@ -22,6 +22,7 @@ struct fsl_xcvr_soc_data { const char *fw_name; bool spdif_only;
bool use_edma;
};
struct fsl_xcvr { @@ -538,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:
@@ -1207,6 +1218,7 @@ static const struct fsl_xcvr_soc_data fsl_xcvr_imx8mp_data = {
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[] = {
2.25.1
On Wed, 04 Jan 2023 10:39:50 +0800, Chancel Liu wrote:
This patchset supports XCVR on i.MX93 platform.
changes in v2:
- remove unnecessary code which causes kernel test robot reporting error
Chancel Liu (3): ASoC: dt-bindings: fsl,xcvr: Add compatible string for i.MX93 platform ASoC: fsl_xcvr: Add support for i.MX93 platform ASoC: fsl_xcvr: Add constraints of period size while using eDMA
[...]
Applied to
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next
Thanks!
[1/3] ASoC: dt-bindings: fsl,xcvr: Add compatible string for i.MX93 platform commit: 0a22003c637b71a1dbd8bb521c09736b52349256 [2/3] ASoC: fsl_xcvr: Add support for i.MX93 platform commit: e240b9329a300af7b7c1eba2ce0abbf19e6c540b [3/3] ASoC: fsl_xcvr: Add constraints of period size while using eDMA commit: 1760df5b7ee6a0bfc8ad47f4db490c36c5546be8
All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks, Mark
participants (3)
-
Chancel Liu
-
Mark Brown
-
Shengjiu Wang