If the hdmi-codec is on a codec-to-codec link, the substream pointer it receives is completely made up by snd_soc_dai_link_event(). The pointer will be different between startup() and shutdown().
The hdmi-codec complains when this happens even if it is not really a problem. The current_substream pointer is not used for anything useful apart from getting the exclusive ownership of the device.
Remove current_substream pointer and replace the exclusive locking mechanism with a simple variable and some atomic operations.
Signed-off-by: Jerome Brunet jbrunet@baylibre.com --- sound/soc/codecs/hdmi-codec.c | 58 ++++++++++------------------------- 1 file changed, 16 insertions(+), 42 deletions(-)
diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c index eb31d7eddcbf..4d32f93f6be6 100644 --- a/sound/soc/codecs/hdmi-codec.c +++ b/sound/soc/codecs/hdmi-codec.c @@ -280,11 +280,10 @@ struct hdmi_codec_priv { struct hdmi_codec_pdata hcd; struct snd_soc_dai_driver *daidrv; struct hdmi_codec_daifmt daifmt[2]; - struct mutex current_stream_lock; - struct snd_pcm_substream *current_stream; uint8_t eld[MAX_ELD_BYTES]; struct snd_pcm_chmap *chmap_info; unsigned int chmap_idx; + unsigned long busy; };
static const struct snd_soc_dapm_widget hdmi_widgets[] = { @@ -392,42 +391,22 @@ static int hdmi_codec_chmap_ctl_get(struct snd_kcontrol *kcontrol, return 0; }
-static int hdmi_codec_new_stream(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai); - int ret = 0; - - mutex_lock(&hcp->current_stream_lock); - if (!hcp->current_stream) { - hcp->current_stream = substream; - } else if (hcp->current_stream != substream) { - dev_err(dai->dev, "Only one simultaneous stream supported!\n"); - ret = -EINVAL; - } - mutex_unlock(&hcp->current_stream_lock); - - return ret; -} - static int hdmi_codec_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai); int ret = 0;
- ret = hdmi_codec_new_stream(substream, dai); - if (ret) - return ret; + ret = test_and_set_bit(0, &hcp->busy); + if (ret) { + dev_err(dai->dev, "Only one simultaneous stream supported!\n"); + return -EINVAL; + }
if (hcp->hcd.ops->audio_startup) { ret = hcp->hcd.ops->audio_startup(dai->dev->parent, hcp->hcd.data); - if (ret) { - mutex_lock(&hcp->current_stream_lock); - hcp->current_stream = NULL; - mutex_unlock(&hcp->current_stream_lock); - return ret; - } + if (ret) + goto err; }
if (hcp->hcd.ops->get_eld) { @@ -437,17 +416,18 @@ static int hdmi_codec_startup(struct snd_pcm_substream *substream, if (!ret) { ret = snd_pcm_hw_constraint_eld(substream->runtime, hcp->eld); - if (ret) { - mutex_lock(&hcp->current_stream_lock); - hcp->current_stream = NULL; - mutex_unlock(&hcp->current_stream_lock); - return ret; - } + if (ret) + goto err; } /* Select chmap supported */ hdmi_codec_eld_chmap(hcp); } return 0; + +err: + /* Release the exclusive lock on error */ + clear_bit(0, &hcp->busy); + return ret; }
static void hdmi_codec_shutdown(struct snd_pcm_substream *substream, @@ -455,14 +435,10 @@ static void hdmi_codec_shutdown(struct snd_pcm_substream *substream, { struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai);
- WARN_ON(hcp->current_stream != substream); - hcp->chmap_idx = HDMI_CODEC_CHMAP_IDX_UNKNOWN; hcp->hcd.ops->audio_shutdown(dai->dev->parent, hcp->hcd.data);
- mutex_lock(&hcp->current_stream_lock); - hcp->current_stream = NULL; - mutex_unlock(&hcp->current_stream_lock); + clear_bit(0, &hcp->busy); }
static int hdmi_codec_hw_params(struct snd_pcm_substream *substream, @@ -761,8 +737,6 @@ static int hdmi_codec_probe(struct platform_device *pdev) return -ENOMEM;
hcp->hcd = *hcd; - mutex_init(&hcp->current_stream_lock); - hcp->daidrv = devm_kcalloc(dev, dai_count, sizeof(*hcp->daidrv), GFP_KERNEL); if (!hcp->daidrv)