Skip to content

Commit e240b93

Browse files
Chancel Liubroonie
authored andcommitted
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]> Acked-by: Shengjiu Wang <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Mark Brown <[email protected]>
1 parent 0a22003 commit e240b93

File tree

2 files changed

+102
-48
lines changed

2 files changed

+102
-48
lines changed

sound/soc/fsl/fsl_xcvr.c

Lines changed: 95 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
struct fsl_xcvr_soc_data {
2323
const char *fw_name;
24+
bool spdif_only;
2425
};
2526

2627
struct fsl_xcvr {
@@ -261,6 +262,9 @@ static int fsl_xcvr_en_phy_pll(struct fsl_xcvr *xcvr, u32 freq, bool tx)
261262
u32 i, div = 0, log2;
262263
int ret;
263264

265+
if (xcvr->soc_data->spdif_only)
266+
return 0;
267+
264268
for (i = 0; i < ARRAY_SIZE(fsl_xcvr_pll_cfg); i++) {
265269
if (fsl_xcvr_pll_cfg[i].fout % freq == 0) {
266270
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)
353357
struct device *dev = &xcvr->pdev->dev;
354358
int ret;
355359

360+
freq = xcvr->soc_data->spdif_only ? freq / 10 : freq;
356361
clk_disable_unprepare(xcvr->phy_clk);
357362
ret = clk_set_rate(xcvr->phy_clk, freq);
358363
if (ret < 0) {
@@ -365,6 +370,8 @@ static int fsl_xcvr_en_aud_pll(struct fsl_xcvr *xcvr, u32 freq)
365370
return ret;
366371
}
367372

373+
if (xcvr->soc_data->spdif_only)
374+
return 0;
368375
/* Release AI interface from reset */
369376
ret = regmap_write(xcvr->regmap, FSL_XCVR_PHY_AI_CTRL_SET,
370377
FSL_XCVR_PHY_AI_CTRL_AI_RESETN);
@@ -547,10 +554,12 @@ static int fsl_xcvr_startup(struct snd_pcm_substream *substream,
547554

548555
xcvr->streams |= BIT(substream->stream);
549556

550-
/* Disable XCVR controls if there is stream started */
551-
fsl_xcvr_activate_ctl(dai, fsl_xcvr_mode_kctl.name, false);
552-
fsl_xcvr_activate_ctl(dai, fsl_xcvr_arc_mode_kctl.name, false);
553-
fsl_xcvr_activate_ctl(dai, fsl_xcvr_earc_capds_kctl.name, false);
557+
if (!xcvr->soc_data->spdif_only) {
558+
/* Disable XCVR controls if there is stream started */
559+
fsl_xcvr_activate_ctl(dai, fsl_xcvr_mode_kctl.name, false);
560+
fsl_xcvr_activate_ctl(dai, fsl_xcvr_arc_mode_kctl.name, false);
561+
fsl_xcvr_activate_ctl(dai, fsl_xcvr_earc_capds_kctl.name, false);
562+
}
554563

555564
return 0;
556565
}
@@ -567,12 +576,13 @@ static void fsl_xcvr_shutdown(struct snd_pcm_substream *substream,
567576

568577
/* Enable XCVR controls if there is no stream started */
569578
if (!xcvr->streams) {
570-
fsl_xcvr_activate_ctl(dai, fsl_xcvr_mode_kctl.name, true);
571-
fsl_xcvr_activate_ctl(dai, fsl_xcvr_arc_mode_kctl.name,
572-
(xcvr->mode == FSL_XCVR_MODE_ARC));
573-
fsl_xcvr_activate_ctl(dai, fsl_xcvr_earc_capds_kctl.name,
574-
(xcvr->mode == FSL_XCVR_MODE_EARC));
575-
579+
if (!xcvr->soc_data->spdif_only) {
580+
fsl_xcvr_activate_ctl(dai, fsl_xcvr_mode_kctl.name, true);
581+
fsl_xcvr_activate_ctl(dai, fsl_xcvr_arc_mode_kctl.name,
582+
(xcvr->mode == FSL_XCVR_MODE_ARC));
583+
fsl_xcvr_activate_ctl(dai, fsl_xcvr_earc_capds_kctl.name,
584+
(xcvr->mode == FSL_XCVR_MODE_EARC));
585+
}
576586
ret = regmap_update_bits(xcvr->regmap, FSL_XCVR_EXT_IER0,
577587
FSL_XCVR_IRQ_EARC_ALL, 0);
578588
if (ret < 0) {
@@ -673,7 +683,10 @@ static int fsl_xcvr_trigger(struct snd_pcm_substream *substream, int cmd,
673683
dev_err(dai->dev, "Failed to stop DATA_TX: %d\n", ret);
674684
return ret;
675685
}
676-
fallthrough;
686+
if (xcvr->soc_data->spdif_only)
687+
break;
688+
else
689+
fallthrough;
677690
case FSL_XCVR_MODE_EARC:
678691
/* clear ISR_CMDC_TX_EN, W1C */
679692
ret = regmap_write(xcvr->regmap,
@@ -877,9 +890,13 @@ static int fsl_xcvr_dai_probe(struct snd_soc_dai *dai)
877890

878891
snd_soc_dai_init_dma_data(dai, &xcvr->dma_prms_tx, &xcvr->dma_prms_rx);
879892

880-
snd_soc_add_dai_controls(dai, &fsl_xcvr_mode_kctl, 1);
881-
snd_soc_add_dai_controls(dai, &fsl_xcvr_arc_mode_kctl, 1);
882-
snd_soc_add_dai_controls(dai, &fsl_xcvr_earc_capds_kctl, 1);
893+
if (xcvr->soc_data->spdif_only)
894+
xcvr->mode = FSL_XCVR_MODE_SPDIF;
895+
else {
896+
snd_soc_add_dai_controls(dai, &fsl_xcvr_mode_kctl, 1);
897+
snd_soc_add_dai_controls(dai, &fsl_xcvr_arc_mode_kctl, 1);
898+
snd_soc_add_dai_controls(dai, &fsl_xcvr_earc_capds_kctl, 1);
899+
}
883900
snd_soc_add_dai_controls(dai, fsl_xcvr_tx_ctls,
884901
ARRAY_SIZE(fsl_xcvr_tx_ctls));
885902
snd_soc_add_dai_controls(dai, fsl_xcvr_rx_ctls,
@@ -930,10 +947,11 @@ static const struct reg_default fsl_xcvr_reg_defaults[] = {
930947
{ FSL_XCVR_ISR_SET, 0x00000000 },
931948
{ FSL_XCVR_ISR_CLR, 0x00000000 },
932949
{ FSL_XCVR_ISR_TOG, 0x00000000 },
933-
{ FSL_XCVR_RX_DPTH_CTRL, 0x00002C89 },
934-
{ FSL_XCVR_RX_DPTH_CTRL_SET, 0x00002C89 },
935-
{ FSL_XCVR_RX_DPTH_CTRL_CLR, 0x00002C89 },
936-
{ FSL_XCVR_RX_DPTH_CTRL_TOG, 0x00002C89 },
950+
{ FSL_XCVR_CLK_CTRL, 0x0000018F },
951+
{ FSL_XCVR_RX_DPTH_CTRL, 0x00040CC1 },
952+
{ FSL_XCVR_RX_DPTH_CTRL_SET, 0x00040CC1 },
953+
{ FSL_XCVR_RX_DPTH_CTRL_CLR, 0x00040CC1 },
954+
{ FSL_XCVR_RX_DPTH_CTRL_TOG, 0x00040CC1 },
937955
{ FSL_XCVR_RX_DPTH_CNTR_CTRL, 0x00000000 },
938956
{ FSL_XCVR_RX_DPTH_CNTR_CTRL_SET, 0x00000000 },
939957
{ FSL_XCVR_RX_DPTH_CNTR_CTRL_CLR, 0x00000000 },
@@ -966,6 +984,12 @@ static const struct reg_default fsl_xcvr_reg_defaults[] = {
966984

967985
static bool fsl_xcvr_readable_reg(struct device *dev, unsigned int reg)
968986
{
987+
struct fsl_xcvr *xcvr = dev_get_drvdata(dev);
988+
989+
if (xcvr->soc_data->spdif_only)
990+
if ((reg >= FSL_XCVR_IER && reg <= FSL_XCVR_PHY_AI_RDATA) ||
991+
reg > FSL_XCVR_TX_DPTH_BCRR)
992+
return false;
969993
switch (reg) {
970994
case FSL_XCVR_VERSION:
971995
case FSL_XCVR_EXT_CTRL:
@@ -991,6 +1015,12 @@ static bool fsl_xcvr_readable_reg(struct device *dev, unsigned int reg)
9911015
case FSL_XCVR_RX_DPTH_CTRL_SET:
9921016
case FSL_XCVR_RX_DPTH_CTRL_CLR:
9931017
case FSL_XCVR_RX_DPTH_CTRL_TOG:
1018+
case FSL_XCVR_RX_CS_DATA_0:
1019+
case FSL_XCVR_RX_CS_DATA_1:
1020+
case FSL_XCVR_RX_CS_DATA_2:
1021+
case FSL_XCVR_RX_CS_DATA_3:
1022+
case FSL_XCVR_RX_CS_DATA_4:
1023+
case FSL_XCVR_RX_CS_DATA_5:
9941024
case FSL_XCVR_RX_DPTH_CNTR_CTRL:
9951025
case FSL_XCVR_RX_DPTH_CNTR_CTRL_SET:
9961026
case FSL_XCVR_RX_DPTH_CNTR_CTRL_CLR:
@@ -1027,6 +1057,11 @@ static bool fsl_xcvr_readable_reg(struct device *dev, unsigned int reg)
10271057

10281058
static bool fsl_xcvr_writeable_reg(struct device *dev, unsigned int reg)
10291059
{
1060+
struct fsl_xcvr *xcvr = dev_get_drvdata(dev);
1061+
1062+
if (xcvr->soc_data->spdif_only)
1063+
if (reg >= FSL_XCVR_IER && reg <= FSL_XCVR_PHY_AI_RDATA)
1064+
return false;
10301065
switch (reg) {
10311066
case FSL_XCVR_EXT_CTRL:
10321067
case FSL_XCVR_EXT_IER0:
@@ -1103,32 +1138,34 @@ static irqreturn_t irq0_isr(int irq, void *devid)
11031138
if (isr & FSL_XCVR_IRQ_NEW_CS) {
11041139
dev_dbg(dev, "Received new CS block\n");
11051140
isr_clr |= FSL_XCVR_IRQ_NEW_CS;
1106-
/* Data RAM is 4KiB, last two pages: 8 and 9. Select page 8. */
1107-
regmap_update_bits(xcvr->regmap, FSL_XCVR_EXT_CTRL,
1108-
FSL_XCVR_EXT_CTRL_PAGE_MASK,
1109-
FSL_XCVR_EXT_CTRL_PAGE(8));
1110-
1111-
/* Find updated CS buffer */
1112-
reg_ctrl = xcvr->ram_addr + FSL_XCVR_RX_CS_CTRL_0;
1113-
reg_buff = xcvr->ram_addr + FSL_XCVR_RX_CS_BUFF_0;
1114-
memcpy_fromio(&val, reg_ctrl, sizeof(val));
1115-
if (!val) {
1116-
reg_ctrl = xcvr->ram_addr + FSL_XCVR_RX_CS_CTRL_1;
1117-
reg_buff = xcvr->ram_addr + FSL_XCVR_RX_CS_BUFF_1;
1141+
if (!xcvr->soc_data->spdif_only) {
1142+
/* Data RAM is 4KiB, last two pages: 8 and 9. Select page 8. */
1143+
regmap_update_bits(xcvr->regmap, FSL_XCVR_EXT_CTRL,
1144+
FSL_XCVR_EXT_CTRL_PAGE_MASK,
1145+
FSL_XCVR_EXT_CTRL_PAGE(8));
1146+
1147+
/* Find updated CS buffer */
1148+
reg_ctrl = xcvr->ram_addr + FSL_XCVR_RX_CS_CTRL_0;
1149+
reg_buff = xcvr->ram_addr + FSL_XCVR_RX_CS_BUFF_0;
11181150
memcpy_fromio(&val, reg_ctrl, sizeof(val));
1119-
}
1151+
if (!val) {
1152+
reg_ctrl = xcvr->ram_addr + FSL_XCVR_RX_CS_CTRL_1;
1153+
reg_buff = xcvr->ram_addr + FSL_XCVR_RX_CS_BUFF_1;
1154+
memcpy_fromio(&val, reg_ctrl, sizeof(val));
1155+
}
11201156

1121-
if (val) {
1122-
/* copy CS buffer */
1123-
memcpy_fromio(&xcvr->rx_iec958.status, reg_buff,
1124-
sizeof(xcvr->rx_iec958.status));
1125-
for (i = 0; i < 6; i++) {
1126-
val = *(u32 *)(xcvr->rx_iec958.status + i*4);
1127-
*(u32 *)(xcvr->rx_iec958.status + i*4) =
1128-
bitrev32(val);
1157+
if (val) {
1158+
/* copy CS buffer */
1159+
memcpy_fromio(&xcvr->rx_iec958.status, reg_buff,
1160+
sizeof(xcvr->rx_iec958.status));
1161+
for (i = 0; i < 6; i++) {
1162+
val = *(u32 *)(xcvr->rx_iec958.status + i*4);
1163+
*(u32 *)(xcvr->rx_iec958.status + i*4) =
1164+
bitrev32(val);
1165+
}
1166+
/* clear CS control register */
1167+
memset_io(reg_ctrl, 0, sizeof(val));
11291168
}
1130-
/* clear CS control register */
1131-
memset_io(reg_ctrl, 0, sizeof(val));
11321169
}
11331170
}
11341171
if (isr & FSL_XCVR_IRQ_NEW_UD) {
@@ -1168,8 +1205,13 @@ static const struct fsl_xcvr_soc_data fsl_xcvr_imx8mp_data = {
11681205
.fw_name = "imx/xcvr/xcvr-imx8mp.bin",
11691206
};
11701207

1208+
static const struct fsl_xcvr_soc_data fsl_xcvr_imx93_data = {
1209+
.spdif_only = true,
1210+
};
1211+
11711212
static const struct of_device_id fsl_xcvr_dt_ids[] = {
11721213
{ .compatible = "fsl,imx8mp-xcvr", .data = &fsl_xcvr_imx8mp_data },
1214+
{ .compatible = "fsl,imx93-xcvr", .data = &fsl_xcvr_imx93_data},
11731215
{ /* sentinel */ }
11741216
};
11751217
MODULE_DEVICE_TABLE(of, fsl_xcvr_dt_ids);
@@ -1229,7 +1271,7 @@ static int fsl_xcvr_probe(struct platform_device *pdev)
12291271
return PTR_ERR(xcvr->regmap);
12301272
}
12311273

1232-
xcvr->reset = devm_reset_control_get_exclusive(dev, NULL);
1274+
xcvr->reset = devm_reset_control_get_optional_exclusive(dev, NULL);
12331275
if (IS_ERR(xcvr->reset)) {
12341276
dev_err(dev, "failed to get XCVR reset control\n");
12351277
return PTR_ERR(xcvr->reset);
@@ -1306,12 +1348,14 @@ static __maybe_unused int fsl_xcvr_runtime_suspend(struct device *dev)
13061348
if (ret < 0)
13071349
dev_err(dev, "Failed to clear IER0: %d\n", ret);
13081350

1309-
/* Assert M0+ reset */
1310-
ret = regmap_update_bits(xcvr->regmap, FSL_XCVR_EXT_CTRL,
1311-
FSL_XCVR_EXT_CTRL_CORE_RESET,
1312-
FSL_XCVR_EXT_CTRL_CORE_RESET);
1313-
if (ret < 0)
1314-
dev_err(dev, "Failed to assert M0+ core: %d\n", ret);
1351+
if (!xcvr->soc_data->spdif_only) {
1352+
/* Assert M0+ reset */
1353+
ret = regmap_update_bits(xcvr->regmap, FSL_XCVR_EXT_CTRL,
1354+
FSL_XCVR_EXT_CTRL_CORE_RESET,
1355+
FSL_XCVR_EXT_CTRL_CORE_RESET);
1356+
if (ret < 0)
1357+
dev_err(dev, "Failed to assert M0+ core: %d\n", ret);
1358+
}
13151359

13161360
regcache_cache_only(xcvr->regmap, true);
13171361

@@ -1367,6 +1411,9 @@ static __maybe_unused int fsl_xcvr_runtime_resume(struct device *dev)
13671411
goto stop_spba_clk;
13681412
}
13691413

1414+
if (xcvr->soc_data->spdif_only)
1415+
return 0;
1416+
13701417
ret = reset_control_deassert(xcvr->reset);
13711418
if (ret) {
13721419
dev_err(dev, "failed to deassert M0+ reset.\n");

sound/soc/fsl/fsl_xcvr.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,13 @@
4949
#define FSL_XCVR_RX_DPTH_CTRL_CLR 0x188
5050
#define FSL_XCVR_RX_DPTH_CTRL_TOG 0x18c
5151

52+
#define FSL_XCVR_RX_CS_DATA_0 0x190
53+
#define FSL_XCVR_RX_CS_DATA_1 0x194
54+
#define FSL_XCVR_RX_CS_DATA_2 0x198
55+
#define FSL_XCVR_RX_CS_DATA_3 0x19C
56+
#define FSL_XCVR_RX_CS_DATA_4 0x1A0
57+
#define FSL_XCVR_RX_CS_DATA_5 0x1A4
58+
5259
#define FSL_XCVR_RX_DPTH_CNTR_CTRL 0x1C0
5360
#define FSL_XCVR_RX_DPTH_CNTR_CTRL_SET 0x1C4
5461
#define FSL_XCVR_RX_DPTH_CNTR_CTRL_CLR 0x1C8

0 commit comments

Comments
 (0)