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.
This commit is contained in:
Mark Brown 2024-10-22 20:48:31 +01:00
commit 43aea89ac2
No known key found for this signature in database
GPG Key ID: 24D68B725D5487D0
2 changed files with 86 additions and 13 deletions

View File

@ -53,6 +53,8 @@ struct fsl_xcvr {
struct snd_aes_iec958 rx_iec958;
struct snd_aes_iec958 tx_iec958;
u8 cap_ds[FSL_XCVR_CAPDS_SIZE];
struct work_struct work_rst;
spinlock_t lock; /* Protect hw_reset and trigger */
};
static const struct fsl_xcvr_pll_conf {
@ -663,7 +665,10 @@ static int fsl_xcvr_trigger(struct snd_pcm_substream *substream, int cmd,
{
struct fsl_xcvr *xcvr = snd_soc_dai_get_drvdata(dai);
bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
int ret;
unsigned long lock_flags;
int ret = 0;
spin_lock_irqsave(&xcvr->lock, lock_flags);
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
@ -675,7 +680,7 @@ static int fsl_xcvr_trigger(struct snd_pcm_substream *substream, int cmd,
FSL_XCVR_EXT_CTRL_DPTH_RESET(tx));
if (ret < 0) {
dev_err(dai->dev, "Failed to set DPATH RESET: %d\n", ret);
return ret;
goto release_lock;
}
if (tx) {
@ -687,7 +692,7 @@ static int fsl_xcvr_trigger(struct snd_pcm_substream *substream, int cmd,
FSL_XCVR_ISR_CMDC_TX_EN);
if (ret < 0) {
dev_err(dai->dev, "err updating isr %d\n", ret);
return ret;
goto release_lock;
}
fallthrough;
case FSL_XCVR_MODE_SPDIF:
@ -696,7 +701,7 @@ static int fsl_xcvr_trigger(struct snd_pcm_substream *substream, int cmd,
FSL_XCVR_TX_DPTH_CTRL_STRT_DATA_TX);
if (ret < 0) {
dev_err(dai->dev, "Failed to start DATA_TX: %d\n", ret);
return ret;
goto release_lock;
}
break;
}
@ -707,14 +712,14 @@ static int fsl_xcvr_trigger(struct snd_pcm_substream *substream, int cmd,
FSL_XCVR_EXT_CTRL_DMA_DIS(tx), 0);
if (ret < 0) {
dev_err(dai->dev, "Failed to enable DMA: %d\n", ret);
return ret;
goto release_lock;
}
ret = regmap_update_bits(xcvr->regmap, FSL_XCVR_EXT_IER0,
FSL_XCVR_IRQ_EARC_ALL, FSL_XCVR_IRQ_EARC_ALL);
if (ret < 0) {
dev_err(dai->dev, "Error while setting IER0: %d\n", ret);
return ret;
goto release_lock;
}
/* clear DPATH RESET */
@ -723,7 +728,7 @@ static int fsl_xcvr_trigger(struct snd_pcm_substream *substream, int cmd,
0);
if (ret < 0) {
dev_err(dai->dev, "Failed to clear DPATH RESET: %d\n", ret);
return ret;
goto release_lock;
}
break;
@ -736,14 +741,14 @@ static int fsl_xcvr_trigger(struct snd_pcm_substream *substream, int cmd,
FSL_XCVR_EXT_CTRL_DMA_DIS(tx));
if (ret < 0) {
dev_err(dai->dev, "Failed to disable DMA: %d\n", ret);
return ret;
goto release_lock;
}
ret = regmap_update_bits(xcvr->regmap, FSL_XCVR_EXT_IER0,
FSL_XCVR_IRQ_EARC_ALL, 0);
if (ret < 0) {
dev_err(dai->dev, "Failed to clear IER0: %d\n", ret);
return ret;
goto release_lock;
}
if (tx) {
@ -754,7 +759,7 @@ static int fsl_xcvr_trigger(struct snd_pcm_substream *substream, int cmd,
FSL_XCVR_TX_DPTH_CTRL_STRT_DATA_TX);
if (ret < 0) {
dev_err(dai->dev, "Failed to stop DATA_TX: %d\n", ret);
return ret;
goto release_lock;
}
if (xcvr->soc_data->spdif_only)
break;
@ -768,17 +773,20 @@ static int fsl_xcvr_trigger(struct snd_pcm_substream *substream, int cmd,
if (ret < 0) {
dev_err(dai->dev,
"Err updating ISR %d\n", ret);
return ret;
goto release_lock;
}
break;
}
}
break;
default:
return -EINVAL;
ret = -EINVAL;
break;
}
return 0;
release_lock:
spin_unlock_irqrestore(&xcvr->lock, lock_flags);
return ret;
}
static int fsl_xcvr_load_firmware(struct fsl_xcvr *xcvr)
@ -1198,6 +1206,34 @@ static const struct regmap_config fsl_xcvr_regmap_cfg = {
.cache_type = REGCACHE_FLAT,
};
static void reset_rx_work(struct work_struct *work)
{
struct fsl_xcvr *xcvr = container_of(work, struct fsl_xcvr, work_rst);
struct device *dev = &xcvr->pdev->dev;
unsigned long lock_flags;
u32 ext_ctrl;
dev_dbg(dev, "reset rx path\n");
spin_lock_irqsave(&xcvr->lock, lock_flags);
regmap_read(xcvr->regmap, FSL_XCVR_EXT_CTRL, &ext_ctrl);
if (!(ext_ctrl & FSL_XCVR_EXT_CTRL_DMA_RD_DIS)) {
regmap_update_bits(xcvr->regmap, FSL_XCVR_EXT_CTRL,
FSL_XCVR_EXT_CTRL_DMA_RD_DIS,
FSL_XCVR_EXT_CTRL_DMA_RD_DIS);
regmap_update_bits(xcvr->regmap, FSL_XCVR_EXT_CTRL,
FSL_XCVR_EXT_CTRL_RX_DPTH_RESET,
FSL_XCVR_EXT_CTRL_RX_DPTH_RESET);
regmap_update_bits(xcvr->regmap, FSL_XCVR_EXT_CTRL,
FSL_XCVR_EXT_CTRL_DMA_RD_DIS,
0);
regmap_update_bits(xcvr->regmap, FSL_XCVR_EXT_CTRL,
FSL_XCVR_EXT_CTRL_RX_DPTH_RESET,
0);
}
spin_unlock_irqrestore(&xcvr->lock, lock_flags);
}
static irqreturn_t irq0_isr(int irq, void *devid)
{
struct fsl_xcvr *xcvr = (struct fsl_xcvr *)devid;
@ -1265,6 +1301,33 @@ static irqreturn_t irq0_isr(int irq, void *devid)
dev_dbg(dev, "DMA write request\n");
isr_clr |= FSL_XCVR_IRQ_DMA_WR_REQ;
}
if (isr & FSL_XCVR_IRQ_CMDC_STATUS_UPD) {
dev_dbg(dev, "CMDC status update\n");
isr_clr |= FSL_XCVR_IRQ_CMDC_STATUS_UPD;
}
if (isr & FSL_XCVR_IRQ_PREAMBLE_MISMATCH) {
dev_dbg(dev, "Preamble mismatch\n");
isr_clr |= FSL_XCVR_IRQ_PREAMBLE_MISMATCH;
}
if (isr & FSL_XCVR_IRQ_UNEXP_PRE_REC) {
dev_dbg(dev, "Unexpected preamble received\n");
isr_clr |= FSL_XCVR_IRQ_UNEXP_PRE_REC;
}
if (isr & FSL_XCVR_IRQ_M_W_PRE_MISMATCH) {
dev_dbg(dev, "M/W preamble mismatch\n");
isr_clr |= FSL_XCVR_IRQ_M_W_PRE_MISMATCH;
}
if (isr & FSL_XCVR_IRQ_B_PRE_MISMATCH) {
dev_dbg(dev, "B preamble mismatch\n");
isr_clr |= FSL_XCVR_IRQ_B_PRE_MISMATCH;
}
if (isr & (FSL_XCVR_IRQ_PREAMBLE_MISMATCH |
FSL_XCVR_IRQ_UNEXP_PRE_REC |
FSL_XCVR_IRQ_M_W_PRE_MISMATCH |
FSL_XCVR_IRQ_B_PRE_MISMATCH)) {
schedule_work(&xcvr->work_rst);
}
if (isr_clr) {
regmap_write(regmap, FSL_XCVR_EXT_ISR_CLR, isr_clr);
@ -1411,11 +1474,16 @@ static int fsl_xcvr_probe(struct platform_device *pdev)
fsl_xcvr_comp.name);
}
INIT_WORK(&xcvr->work_rst, reset_rx_work);
spin_lock_init(&xcvr->lock);
return ret;
}
static void fsl_xcvr_remove(struct platform_device *pdev)
{
struct fsl_xcvr *xcvr = dev_get_drvdata(&pdev->dev);
cancel_work_sync(&xcvr->work_rst);
pm_runtime_disable(&pdev->dev);
}

View File

@ -165,6 +165,11 @@
FSL_XCVR_IRQ_MUTE | \
FSL_XCVR_IRQ_FIFO_UOFL_ERR | \
FSL_XCVR_IRQ_HOST_WAKEUP | \
FSL_XCVR_IRQ_CMDC_STATUS_UPD |\
FSL_XCVR_IRQ_B_PRE_MISMATCH |\
FSL_XCVR_IRQ_M_W_PRE_MISMATCH |\
FSL_XCVR_IRQ_PREAMBLE_MISMATCH |\
FSL_XCVR_IRQ_UNEXP_PRE_REC |\
FSL_XCVR_IRQ_ARC_MODE)
#define FSL_XCVR_ISR_CMDC_TX_EN BIT(3)