Skip to content

Commit 43aea89

Browse files
committed
ASoC: fsl_xcvr: enable some interrupts
Merge series from Shengjiu Wang <shengjiu.wang@nxp.com>: Enable interrupt of cmdc status update and the interrupts for wrong preamble received.
2 parents 6a646e6 + 1e5d0f1 commit 43aea89

2 files changed

Lines changed: 86 additions & 13 deletions

File tree

sound/soc/fsl/fsl_xcvr.c

Lines changed: 81 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ struct fsl_xcvr {
5353
struct snd_aes_iec958 rx_iec958;
5454
struct snd_aes_iec958 tx_iec958;
5555
u8 cap_ds[FSL_XCVR_CAPDS_SIZE];
56+
struct work_struct work_rst;
57+
spinlock_t lock; /* Protect hw_reset and trigger */
5658
};
5759

5860
static const struct fsl_xcvr_pll_conf {
@@ -663,7 +665,10 @@ static int fsl_xcvr_trigger(struct snd_pcm_substream *substream, int cmd,
663665
{
664666
struct fsl_xcvr *xcvr = snd_soc_dai_get_drvdata(dai);
665667
bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
666-
int ret;
668+
unsigned long lock_flags;
669+
int ret = 0;
670+
671+
spin_lock_irqsave(&xcvr->lock, lock_flags);
667672

668673
switch (cmd) {
669674
case SNDRV_PCM_TRIGGER_START:
@@ -675,7 +680,7 @@ static int fsl_xcvr_trigger(struct snd_pcm_substream *substream, int cmd,
675680
FSL_XCVR_EXT_CTRL_DPTH_RESET(tx));
676681
if (ret < 0) {
677682
dev_err(dai->dev, "Failed to set DPATH RESET: %d\n", ret);
678-
return ret;
683+
goto release_lock;
679684
}
680685

681686
if (tx) {
@@ -687,7 +692,7 @@ static int fsl_xcvr_trigger(struct snd_pcm_substream *substream, int cmd,
687692
FSL_XCVR_ISR_CMDC_TX_EN);
688693
if (ret < 0) {
689694
dev_err(dai->dev, "err updating isr %d\n", ret);
690-
return ret;
695+
goto release_lock;
691696
}
692697
fallthrough;
693698
case FSL_XCVR_MODE_SPDIF:
@@ -696,7 +701,7 @@ static int fsl_xcvr_trigger(struct snd_pcm_substream *substream, int cmd,
696701
FSL_XCVR_TX_DPTH_CTRL_STRT_DATA_TX);
697702
if (ret < 0) {
698703
dev_err(dai->dev, "Failed to start DATA_TX: %d\n", ret);
699-
return ret;
704+
goto release_lock;
700705
}
701706
break;
702707
}
@@ -707,14 +712,14 @@ static int fsl_xcvr_trigger(struct snd_pcm_substream *substream, int cmd,
707712
FSL_XCVR_EXT_CTRL_DMA_DIS(tx), 0);
708713
if (ret < 0) {
709714
dev_err(dai->dev, "Failed to enable DMA: %d\n", ret);
710-
return ret;
715+
goto release_lock;
711716
}
712717

713718
ret = regmap_update_bits(xcvr->regmap, FSL_XCVR_EXT_IER0,
714719
FSL_XCVR_IRQ_EARC_ALL, FSL_XCVR_IRQ_EARC_ALL);
715720
if (ret < 0) {
716721
dev_err(dai->dev, "Error while setting IER0: %d\n", ret);
717-
return ret;
722+
goto release_lock;
718723
}
719724

720725
/* clear DPATH RESET */
@@ -723,7 +728,7 @@ static int fsl_xcvr_trigger(struct snd_pcm_substream *substream, int cmd,
723728
0);
724729
if (ret < 0) {
725730
dev_err(dai->dev, "Failed to clear DPATH RESET: %d\n", ret);
726-
return ret;
731+
goto release_lock;
727732
}
728733

729734
break;
@@ -736,14 +741,14 @@ static int fsl_xcvr_trigger(struct snd_pcm_substream *substream, int cmd,
736741
FSL_XCVR_EXT_CTRL_DMA_DIS(tx));
737742
if (ret < 0) {
738743
dev_err(dai->dev, "Failed to disable DMA: %d\n", ret);
739-
return ret;
744+
goto release_lock;
740745
}
741746

742747
ret = regmap_update_bits(xcvr->regmap, FSL_XCVR_EXT_IER0,
743748
FSL_XCVR_IRQ_EARC_ALL, 0);
744749
if (ret < 0) {
745750
dev_err(dai->dev, "Failed to clear IER0: %d\n", ret);
746-
return ret;
751+
goto release_lock;
747752
}
748753

749754
if (tx) {
@@ -754,7 +759,7 @@ static int fsl_xcvr_trigger(struct snd_pcm_substream *substream, int cmd,
754759
FSL_XCVR_TX_DPTH_CTRL_STRT_DATA_TX);
755760
if (ret < 0) {
756761
dev_err(dai->dev, "Failed to stop DATA_TX: %d\n", ret);
757-
return ret;
762+
goto release_lock;
758763
}
759764
if (xcvr->soc_data->spdif_only)
760765
break;
@@ -768,17 +773,20 @@ static int fsl_xcvr_trigger(struct snd_pcm_substream *substream, int cmd,
768773
if (ret < 0) {
769774
dev_err(dai->dev,
770775
"Err updating ISR %d\n", ret);
771-
return ret;
776+
goto release_lock;
772777
}
773778
break;
774779
}
775780
}
776781
break;
777782
default:
778-
return -EINVAL;
783+
ret = -EINVAL;
784+
break;
779785
}
780786

781-
return 0;
787+
release_lock:
788+
spin_unlock_irqrestore(&xcvr->lock, lock_flags);
789+
return ret;
782790
}
783791

784792
static int fsl_xcvr_load_firmware(struct fsl_xcvr *xcvr)
@@ -1198,6 +1206,34 @@ static const struct regmap_config fsl_xcvr_regmap_cfg = {
11981206
.cache_type = REGCACHE_FLAT,
11991207
};
12001208

1209+
static void reset_rx_work(struct work_struct *work)
1210+
{
1211+
struct fsl_xcvr *xcvr = container_of(work, struct fsl_xcvr, work_rst);
1212+
struct device *dev = &xcvr->pdev->dev;
1213+
unsigned long lock_flags;
1214+
u32 ext_ctrl;
1215+
1216+
dev_dbg(dev, "reset rx path\n");
1217+
spin_lock_irqsave(&xcvr->lock, lock_flags);
1218+
regmap_read(xcvr->regmap, FSL_XCVR_EXT_CTRL, &ext_ctrl);
1219+
1220+
if (!(ext_ctrl & FSL_XCVR_EXT_CTRL_DMA_RD_DIS)) {
1221+
regmap_update_bits(xcvr->regmap, FSL_XCVR_EXT_CTRL,
1222+
FSL_XCVR_EXT_CTRL_DMA_RD_DIS,
1223+
FSL_XCVR_EXT_CTRL_DMA_RD_DIS);
1224+
regmap_update_bits(xcvr->regmap, FSL_XCVR_EXT_CTRL,
1225+
FSL_XCVR_EXT_CTRL_RX_DPTH_RESET,
1226+
FSL_XCVR_EXT_CTRL_RX_DPTH_RESET);
1227+
regmap_update_bits(xcvr->regmap, FSL_XCVR_EXT_CTRL,
1228+
FSL_XCVR_EXT_CTRL_DMA_RD_DIS,
1229+
0);
1230+
regmap_update_bits(xcvr->regmap, FSL_XCVR_EXT_CTRL,
1231+
FSL_XCVR_EXT_CTRL_RX_DPTH_RESET,
1232+
0);
1233+
}
1234+
spin_unlock_irqrestore(&xcvr->lock, lock_flags);
1235+
}
1236+
12011237
static irqreturn_t irq0_isr(int irq, void *devid)
12021238
{
12031239
struct fsl_xcvr *xcvr = (struct fsl_xcvr *)devid;
@@ -1265,6 +1301,33 @@ static irqreturn_t irq0_isr(int irq, void *devid)
12651301
dev_dbg(dev, "DMA write request\n");
12661302
isr_clr |= FSL_XCVR_IRQ_DMA_WR_REQ;
12671303
}
1304+
if (isr & FSL_XCVR_IRQ_CMDC_STATUS_UPD) {
1305+
dev_dbg(dev, "CMDC status update\n");
1306+
isr_clr |= FSL_XCVR_IRQ_CMDC_STATUS_UPD;
1307+
}
1308+
if (isr & FSL_XCVR_IRQ_PREAMBLE_MISMATCH) {
1309+
dev_dbg(dev, "Preamble mismatch\n");
1310+
isr_clr |= FSL_XCVR_IRQ_PREAMBLE_MISMATCH;
1311+
}
1312+
if (isr & FSL_XCVR_IRQ_UNEXP_PRE_REC) {
1313+
dev_dbg(dev, "Unexpected preamble received\n");
1314+
isr_clr |= FSL_XCVR_IRQ_UNEXP_PRE_REC;
1315+
}
1316+
if (isr & FSL_XCVR_IRQ_M_W_PRE_MISMATCH) {
1317+
dev_dbg(dev, "M/W preamble mismatch\n");
1318+
isr_clr |= FSL_XCVR_IRQ_M_W_PRE_MISMATCH;
1319+
}
1320+
if (isr & FSL_XCVR_IRQ_B_PRE_MISMATCH) {
1321+
dev_dbg(dev, "B preamble mismatch\n");
1322+
isr_clr |= FSL_XCVR_IRQ_B_PRE_MISMATCH;
1323+
}
1324+
1325+
if (isr & (FSL_XCVR_IRQ_PREAMBLE_MISMATCH |
1326+
FSL_XCVR_IRQ_UNEXP_PRE_REC |
1327+
FSL_XCVR_IRQ_M_W_PRE_MISMATCH |
1328+
FSL_XCVR_IRQ_B_PRE_MISMATCH)) {
1329+
schedule_work(&xcvr->work_rst);
1330+
}
12681331

12691332
if (isr_clr) {
12701333
regmap_write(regmap, FSL_XCVR_EXT_ISR_CLR, isr_clr);
@@ -1411,11 +1474,16 @@ static int fsl_xcvr_probe(struct platform_device *pdev)
14111474
fsl_xcvr_comp.name);
14121475
}
14131476

1477+
INIT_WORK(&xcvr->work_rst, reset_rx_work);
1478+
spin_lock_init(&xcvr->lock);
14141479
return ret;
14151480
}
14161481

14171482
static void fsl_xcvr_remove(struct platform_device *pdev)
14181483
{
1484+
struct fsl_xcvr *xcvr = dev_get_drvdata(&pdev->dev);
1485+
1486+
cancel_work_sync(&xcvr->work_rst);
14191487
pm_runtime_disable(&pdev->dev);
14201488
}
14211489

sound/soc/fsl/fsl_xcvr.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,11 @@
165165
FSL_XCVR_IRQ_MUTE | \
166166
FSL_XCVR_IRQ_FIFO_UOFL_ERR | \
167167
FSL_XCVR_IRQ_HOST_WAKEUP | \
168+
FSL_XCVR_IRQ_CMDC_STATUS_UPD |\
169+
FSL_XCVR_IRQ_B_PRE_MISMATCH |\
170+
FSL_XCVR_IRQ_M_W_PRE_MISMATCH |\
171+
FSL_XCVR_IRQ_PREAMBLE_MISMATCH |\
172+
FSL_XCVR_IRQ_UNEXP_PRE_REC |\
168173
FSL_XCVR_IRQ_ARC_MODE)
169174

170175
#define FSL_XCVR_ISR_CMDC_TX_EN BIT(3)

0 commit comments

Comments
 (0)