mirror of
https://github.com/torvalds/linux.git
synced 2024-11-25 13:41:51 +00:00
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:
commit
43aea89ac2
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user