2023-01-04 02:58:39

by Chancel Liu

[permalink] [raw]
Subject: [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


2023-01-04 03:01:13

by Chancel Liu

[permalink] [raw]
Subject: [RESEND v2 2/3] ASoC: fsl_xcvr: Add support for i.MX93 platform

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 <[email protected]>
---
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

2023-01-04 03:10:46

by Chancel Liu

[permalink] [raw]
Subject: [RESEND v2 3/3] ASoC: fsl_xcvr: Add constraints of period size while using eDMA

eDMA on i.MX93 platform requires the period size to be multiple of
maxburst.

Signed-off-by: Chancel Liu <[email protected]>
---
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

2023-01-04 03:14:22

by Chancel Liu

[permalink] [raw]
Subject: [RESEND v2 1/3] ASoC: dt-bindings: fsl,xcvr: Add compatible string for i.MX93 platform

Add compatible string "fsl,imx93-xcvr" for i.MX93 platform.

Acked-by: Krzysztof Kozlowski <[email protected]>
Signed-off-by: Chancel Liu <[email protected]>
---
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:
--
2.25.1

2023-01-09 17:30:59

by Mark Brown

[permalink] [raw]
Subject: Re: [RESEND v2 0/3] Add support for XCVR on i.MX93 platform

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