mirror of
https://github.com/torvalds/linux.git
synced 2026-09-13 15:40:03 +02:00
ASoC: ux500: Allow repeated MSP prepare calls
ALSA can call the DAI prepare callback again after an XRUN without
first shutting down the stream. The MSP open helper rejects the second
call with -EBUSY because the direction remains configured.
Track successful playback and capture configurations at the DAI layer.
Make repeated prepare calls no-ops and only close directions which were
successfully prepared.
Fixes: 3592b7f69a ("ASoC: Ux500: Add MSP I2S-driver")
Assisted-by: LLM
Signed-off-by: Linus Walleij <linusw@kernel.org>
Link: https://patch.msgid.link/20260902-ux500-msp-fixes-v2-8-4b60b002d55a@kernel.org
Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
parent
7b819677b5
commit
dc1a1b1e22
|
|
@ -388,15 +388,21 @@ static void ux500_msp_dai_shutdown(struct snd_pcm_substream *substream,
|
|||
int ret;
|
||||
struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dai->dev);
|
||||
bool is_playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
|
||||
unsigned int configured = is_playback ? PLAYBACK_CONFIGURED :
|
||||
CAPTURE_CONFIGURED;
|
||||
unsigned int dir = is_playback ? MSP_DIR_TX : MSP_DIR_RX;
|
||||
|
||||
dev_dbg(dai->dev, "%s: MSP %d (%s): Enter.\n", __func__, dai->id,
|
||||
snd_pcm_stream_str(substream));
|
||||
|
||||
if (ux500_msp_i2s_close(drvdata->msp,
|
||||
is_playback ? MSP_DIR_TX : MSP_DIR_RX)) {
|
||||
dev_err(dai->dev,
|
||||
"%s: Error: MSP %d (%s): Unable to close i2s.\n",
|
||||
__func__, dai->id, snd_pcm_stream_str(substream));
|
||||
if (drvdata->configured & configured) {
|
||||
if (ux500_msp_i2s_close(drvdata->msp, dir)) {
|
||||
dev_err(dai->dev,
|
||||
"%s: Error: MSP %d (%s): Unable to close i2s.\n",
|
||||
__func__, dai->id,
|
||||
snd_pcm_stream_str(substream));
|
||||
}
|
||||
drvdata->configured &= ~configured;
|
||||
}
|
||||
|
||||
/* Disable and unprepare clocks */
|
||||
|
|
@ -414,14 +420,20 @@ static void ux500_msp_dai_shutdown(struct snd_pcm_substream *substream,
|
|||
static int ux500_msp_dai_prepare(struct snd_pcm_substream *substream,
|
||||
struct snd_soc_dai *dai)
|
||||
{
|
||||
int ret = 0;
|
||||
struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dai->dev);
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
struct ux500_msp_config msp_config;
|
||||
bool is_playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
|
||||
unsigned int configured = is_playback ? PLAYBACK_CONFIGURED :
|
||||
CAPTURE_CONFIGURED;
|
||||
int ret;
|
||||
|
||||
dev_dbg(dai->dev, "%s: MSP %d (%s): Enter (rate = %d).\n", __func__,
|
||||
dai->id, snd_pcm_stream_str(substream), runtime->rate);
|
||||
|
||||
if (drvdata->configured & configured)
|
||||
return 0;
|
||||
|
||||
ret = setup_msp_config(substream, dai, &msp_config);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
|
@ -433,7 +445,9 @@ static int ux500_msp_dai_prepare(struct snd_pcm_substream *substream,
|
|||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
drvdata->configured |= configured;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ux500_msp_dai_hw_params(struct snd_pcm_substream *substream,
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ struct ux500_msp_i2s_drvdata {
|
|||
struct ux500_msp *msp;
|
||||
struct regulator *reg_vape;
|
||||
unsigned int fmt;
|
||||
unsigned int configured;
|
||||
unsigned int tx_mask;
|
||||
unsigned int rx_mask;
|
||||
int slots;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user