Merge remote-tracking branches 'asoc/fix/intel', 'asoc/fix/topology' and 'asoc/fix/sti' into asoc-linus
This commit is contained in:
commit
dc9617cb81
|
@ -933,6 +933,7 @@ static int soc_tplg_denum_create_texts(struct soc_enum *se,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
se->texts = (const char * const *)se->dobj.control.dtexts;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
|
|
|
@ -1299,6 +1299,7 @@ struct uniperif {
|
||||||
int ver; /* IP version, used by register access macros */
|
int ver; /* IP version, used by register access macros */
|
||||||
struct regmap_field *clk_sel;
|
struct regmap_field *clk_sel;
|
||||||
struct regmap_field *valid_sel;
|
struct regmap_field *valid_sel;
|
||||||
|
spinlock_t irq_lock; /* use to prevent race condition with IRQ */
|
||||||
|
|
||||||
/* capabilities */
|
/* capabilities */
|
||||||
const struct snd_pcm_hardware *hw;
|
const struct snd_pcm_hardware *hw;
|
||||||
|
|
|
@ -65,10 +65,13 @@ static irqreturn_t uni_player_irq_handler(int irq, void *dev_id)
|
||||||
unsigned int status;
|
unsigned int status;
|
||||||
unsigned int tmp;
|
unsigned int tmp;
|
||||||
|
|
||||||
if (player->state == UNIPERIF_STATE_STOPPED) {
|
spin_lock(&player->irq_lock);
|
||||||
/* Unexpected IRQ: do nothing */
|
if (!player->substream)
|
||||||
return IRQ_NONE;
|
goto irq_spin_unlock;
|
||||||
}
|
|
||||||
|
snd_pcm_stream_lock(player->substream);
|
||||||
|
if (player->state == UNIPERIF_STATE_STOPPED)
|
||||||
|
goto stream_unlock;
|
||||||
|
|
||||||
/* Get interrupt status & clear them immediately */
|
/* Get interrupt status & clear them immediately */
|
||||||
status = GET_UNIPERIF_ITS(player);
|
status = GET_UNIPERIF_ITS(player);
|
||||||
|
@ -88,9 +91,7 @@ static irqreturn_t uni_player_irq_handler(int irq, void *dev_id)
|
||||||
SET_UNIPERIF_ITM_BCLR_FIFO_ERROR(player);
|
SET_UNIPERIF_ITM_BCLR_FIFO_ERROR(player);
|
||||||
|
|
||||||
/* Stop the player */
|
/* Stop the player */
|
||||||
snd_pcm_stream_lock(player->substream);
|
|
||||||
snd_pcm_stop(player->substream, SNDRV_PCM_STATE_XRUN);
|
snd_pcm_stop(player->substream, SNDRV_PCM_STATE_XRUN);
|
||||||
snd_pcm_stream_unlock(player->substream);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = IRQ_HANDLED;
|
ret = IRQ_HANDLED;
|
||||||
|
@ -104,9 +105,7 @@ static irqreturn_t uni_player_irq_handler(int irq, void *dev_id)
|
||||||
SET_UNIPERIF_ITM_BCLR_DMA_ERROR(player);
|
SET_UNIPERIF_ITM_BCLR_DMA_ERROR(player);
|
||||||
|
|
||||||
/* Stop the player */
|
/* Stop the player */
|
||||||
snd_pcm_stream_lock(player->substream);
|
|
||||||
snd_pcm_stop(player->substream, SNDRV_PCM_STATE_XRUN);
|
snd_pcm_stop(player->substream, SNDRV_PCM_STATE_XRUN);
|
||||||
snd_pcm_stream_unlock(player->substream);
|
|
||||||
|
|
||||||
ret = IRQ_HANDLED;
|
ret = IRQ_HANDLED;
|
||||||
}
|
}
|
||||||
|
@ -116,7 +115,8 @@ static irqreturn_t uni_player_irq_handler(int irq, void *dev_id)
|
||||||
if (!player->underflow_enabled) {
|
if (!player->underflow_enabled) {
|
||||||
dev_err(player->dev,
|
dev_err(player->dev,
|
||||||
"unexpected Underflow recovering\n");
|
"unexpected Underflow recovering\n");
|
||||||
return -EPERM;
|
ret = -EPERM;
|
||||||
|
goto stream_unlock;
|
||||||
}
|
}
|
||||||
/* Read the underflow recovery duration */
|
/* Read the underflow recovery duration */
|
||||||
tmp = GET_UNIPERIF_STATUS_1_UNDERFLOW_DURATION(player);
|
tmp = GET_UNIPERIF_STATUS_1_UNDERFLOW_DURATION(player);
|
||||||
|
@ -138,13 +138,16 @@ static irqreturn_t uni_player_irq_handler(int irq, void *dev_id)
|
||||||
dev_err(player->dev, "Underflow recovery failed\n");
|
dev_err(player->dev, "Underflow recovery failed\n");
|
||||||
|
|
||||||
/* Stop the player */
|
/* Stop the player */
|
||||||
snd_pcm_stream_lock(player->substream);
|
|
||||||
snd_pcm_stop(player->substream, SNDRV_PCM_STATE_XRUN);
|
snd_pcm_stop(player->substream, SNDRV_PCM_STATE_XRUN);
|
||||||
snd_pcm_stream_unlock(player->substream);
|
|
||||||
|
|
||||||
ret = IRQ_HANDLED;
|
ret = IRQ_HANDLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stream_unlock:
|
||||||
|
snd_pcm_stream_unlock(player->substream);
|
||||||
|
irq_spin_unlock:
|
||||||
|
spin_unlock(&player->irq_lock);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -588,6 +591,7 @@ static int uni_player_ctl_iec958_put(struct snd_kcontrol *kcontrol,
|
||||||
struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai);
|
struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai);
|
||||||
struct uniperif *player = priv->dai_data.uni;
|
struct uniperif *player = priv->dai_data.uni;
|
||||||
struct snd_aes_iec958 *iec958 = &player->stream_settings.iec958;
|
struct snd_aes_iec958 *iec958 = &player->stream_settings.iec958;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
mutex_lock(&player->ctrl_lock);
|
mutex_lock(&player->ctrl_lock);
|
||||||
iec958->status[0] = ucontrol->value.iec958.status[0];
|
iec958->status[0] = ucontrol->value.iec958.status[0];
|
||||||
|
@ -596,12 +600,14 @@ static int uni_player_ctl_iec958_put(struct snd_kcontrol *kcontrol,
|
||||||
iec958->status[3] = ucontrol->value.iec958.status[3];
|
iec958->status[3] = ucontrol->value.iec958.status[3];
|
||||||
mutex_unlock(&player->ctrl_lock);
|
mutex_unlock(&player->ctrl_lock);
|
||||||
|
|
||||||
|
spin_lock_irqsave(&player->irq_lock, flags);
|
||||||
if (player->substream && player->substream->runtime)
|
if (player->substream && player->substream->runtime)
|
||||||
uni_player_set_channel_status(player,
|
uni_player_set_channel_status(player,
|
||||||
player->substream->runtime);
|
player->substream->runtime);
|
||||||
else
|
else
|
||||||
uni_player_set_channel_status(player, NULL);
|
uni_player_set_channel_status(player, NULL);
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&player->irq_lock, flags);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -686,9 +692,12 @@ static int uni_player_startup(struct snd_pcm_substream *substream,
|
||||||
{
|
{
|
||||||
struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai);
|
struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai);
|
||||||
struct uniperif *player = priv->dai_data.uni;
|
struct uniperif *player = priv->dai_data.uni;
|
||||||
|
unsigned long flags;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&player->irq_lock, flags);
|
||||||
player->substream = substream;
|
player->substream = substream;
|
||||||
|
spin_unlock_irqrestore(&player->irq_lock, flags);
|
||||||
|
|
||||||
player->clk_adj = 0;
|
player->clk_adj = 0;
|
||||||
|
|
||||||
|
@ -986,12 +995,15 @@ static void uni_player_shutdown(struct snd_pcm_substream *substream,
|
||||||
{
|
{
|
||||||
struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai);
|
struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai);
|
||||||
struct uniperif *player = priv->dai_data.uni;
|
struct uniperif *player = priv->dai_data.uni;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&player->irq_lock, flags);
|
||||||
if (player->state != UNIPERIF_STATE_STOPPED)
|
if (player->state != UNIPERIF_STATE_STOPPED)
|
||||||
/* Stop the player */
|
/* Stop the player */
|
||||||
uni_player_stop(player);
|
uni_player_stop(player);
|
||||||
|
|
||||||
player->substream = NULL;
|
player->substream = NULL;
|
||||||
|
spin_unlock_irqrestore(&player->irq_lock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int uni_player_parse_dt_audio_glue(struct platform_device *pdev,
|
static int uni_player_parse_dt_audio_glue(struct platform_device *pdev,
|
||||||
|
@ -1096,6 +1108,7 @@ int uni_player_init(struct platform_device *pdev,
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_init(&player->ctrl_lock);
|
mutex_init(&player->ctrl_lock);
|
||||||
|
spin_lock_init(&player->irq_lock);
|
||||||
|
|
||||||
/* Ensure that disabled by default */
|
/* Ensure that disabled by default */
|
||||||
SET_UNIPERIF_CONFIG_BACK_STALL_REQ_DISABLE(player);
|
SET_UNIPERIF_CONFIG_BACK_STALL_REQ_DISABLE(player);
|
||||||
|
|
|
@ -46,10 +46,15 @@ static irqreturn_t uni_reader_irq_handler(int irq, void *dev_id)
|
||||||
struct uniperif *reader = dev_id;
|
struct uniperif *reader = dev_id;
|
||||||
unsigned int status;
|
unsigned int status;
|
||||||
|
|
||||||
|
spin_lock(&reader->irq_lock);
|
||||||
|
if (!reader->substream)
|
||||||
|
goto irq_spin_unlock;
|
||||||
|
|
||||||
|
snd_pcm_stream_lock(reader->substream);
|
||||||
if (reader->state == UNIPERIF_STATE_STOPPED) {
|
if (reader->state == UNIPERIF_STATE_STOPPED) {
|
||||||
/* Unexpected IRQ: do nothing */
|
/* Unexpected IRQ: do nothing */
|
||||||
dev_warn(reader->dev, "unexpected IRQ\n");
|
dev_warn(reader->dev, "unexpected IRQ\n");
|
||||||
return IRQ_HANDLED;
|
goto stream_unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get interrupt status & clear them immediately */
|
/* Get interrupt status & clear them immediately */
|
||||||
|
@ -60,13 +65,16 @@ static irqreturn_t uni_reader_irq_handler(int irq, void *dev_id)
|
||||||
if (unlikely(status & UNIPERIF_ITS_FIFO_ERROR_MASK(reader))) {
|
if (unlikely(status & UNIPERIF_ITS_FIFO_ERROR_MASK(reader))) {
|
||||||
dev_err(reader->dev, "FIFO error detected\n");
|
dev_err(reader->dev, "FIFO error detected\n");
|
||||||
|
|
||||||
snd_pcm_stream_lock(reader->substream);
|
|
||||||
snd_pcm_stop(reader->substream, SNDRV_PCM_STATE_XRUN);
|
snd_pcm_stop(reader->substream, SNDRV_PCM_STATE_XRUN);
|
||||||
snd_pcm_stream_unlock(reader->substream);
|
|
||||||
|
|
||||||
return IRQ_HANDLED;
|
ret = IRQ_HANDLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stream_unlock:
|
||||||
|
snd_pcm_stream_unlock(reader->substream);
|
||||||
|
irq_spin_unlock:
|
||||||
|
spin_unlock(&reader->irq_lock);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -347,8 +355,13 @@ static int uni_reader_startup(struct snd_pcm_substream *substream,
|
||||||
{
|
{
|
||||||
struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai);
|
struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai);
|
||||||
struct uniperif *reader = priv->dai_data.uni;
|
struct uniperif *reader = priv->dai_data.uni;
|
||||||
|
unsigned long flags;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&reader->irq_lock, flags);
|
||||||
|
reader->substream = substream;
|
||||||
|
spin_unlock_irqrestore(&reader->irq_lock, flags);
|
||||||
|
|
||||||
if (!UNIPERIF_TYPE_IS_TDM(reader))
|
if (!UNIPERIF_TYPE_IS_TDM(reader))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -373,11 +386,15 @@ static void uni_reader_shutdown(struct snd_pcm_substream *substream,
|
||||||
{
|
{
|
||||||
struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai);
|
struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai);
|
||||||
struct uniperif *reader = priv->dai_data.uni;
|
struct uniperif *reader = priv->dai_data.uni;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&reader->irq_lock, flags);
|
||||||
if (reader->state != UNIPERIF_STATE_STOPPED) {
|
if (reader->state != UNIPERIF_STATE_STOPPED) {
|
||||||
/* Stop the reader */
|
/* Stop the reader */
|
||||||
uni_reader_stop(reader);
|
uni_reader_stop(reader);
|
||||||
}
|
}
|
||||||
|
reader->substream = NULL;
|
||||||
|
spin_unlock_irqrestore(&reader->irq_lock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct snd_soc_dai_ops uni_reader_dai_ops = {
|
static const struct snd_soc_dai_ops uni_reader_dai_ops = {
|
||||||
|
@ -412,6 +429,8 @@ int uni_reader_init(struct platform_device *pdev,
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
spin_lock_init(&reader->irq_lock);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(uni_reader_init);
|
EXPORT_SYMBOL_GPL(uni_reader_init);
|
||||||
|
|
Loading…
Reference in New Issue