Skip to content

Commit b11d266

Browse files
jbrun3tbroonie
authored andcommitted
ASoC: meson: axg-fifo: use threaded irq to check periods
With the AXG audio subsystem, there is a possible random channel shift on TDM capture, when the slot number per lane is more than 2, and there is more than one lane used. The problem has been there since the introduction of the axg audio support but such scenario is pretty uncommon. This is why there is no loud complains about the problem. Solving the problem require to make the links non-atomic and use the trigger() callback to start FEs and BEs in the appropriate order. This was tried in the past and reverted because it caused the block irq to sleep while atomic. However, instead of reverting, the solution is to call snd_pcm_period_elapsed() in a non atomic context. Use the bottom half of a threaded IRQ to do so. Fixes: 6dc4fa1 ("ASoC: meson: add axg fifo base driver") Signed-off-by: Jerome Brunet <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Mark Brown <[email protected]>
1 parent bda1650 commit b11d266

File tree

1 file changed

+19
-10
lines changed

1 file changed

+19
-10
lines changed

sound/soc/meson/axg-fifo.c

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -204,18 +204,26 @@ static irqreturn_t axg_fifo_pcm_irq_block(int irq, void *dev_id)
204204
unsigned int status;
205205

206206
regmap_read(fifo->map, FIFO_STATUS1, &status);
207-
208207
status = FIELD_GET(STATUS1_INT_STS, status);
208+
axg_fifo_ack_irq(fifo, status);
209+
210+
/* Use the thread to call period elapsed on nonatomic links */
209211
if (status & FIFO_INT_COUNT_REPEAT)
210-
snd_pcm_period_elapsed(ss);
211-
else
212-
dev_dbg(axg_fifo_dev(ss), "unexpected irq - STS 0x%02x\n",
213-
status);
212+
return IRQ_WAKE_THREAD;
214213

215-
/* Ack irqs */
216-
axg_fifo_ack_irq(fifo, status);
214+
dev_dbg(axg_fifo_dev(ss), "unexpected irq - STS 0x%02x\n",
215+
status);
216+
217+
return IRQ_NONE;
218+
}
219+
220+
static irqreturn_t axg_fifo_pcm_irq_block_thread(int irq, void *dev_id)
221+
{
222+
struct snd_pcm_substream *ss = dev_id;
223+
224+
snd_pcm_period_elapsed(ss);
217225

218-
return IRQ_RETVAL(status);
226+
return IRQ_HANDLED;
219227
}
220228

221229
int axg_fifo_pcm_open(struct snd_soc_component *component,
@@ -243,8 +251,9 @@ int axg_fifo_pcm_open(struct snd_soc_component *component,
243251
if (ret)
244252
return ret;
245253

246-
ret = request_irq(fifo->irq, axg_fifo_pcm_irq_block, 0,
247-
dev_name(dev), ss);
254+
ret = request_threaded_irq(fifo->irq, axg_fifo_pcm_irq_block,
255+
axg_fifo_pcm_irq_block_thread,
256+
IRQF_ONESHOT, dev_name(dev), ss);
248257
if (ret)
249258
return ret;
250259

0 commit comments

Comments
 (0)