From mboxrd@z Thu Jan 1 00:00:00 1970 From: Jyri Sarha Subject: Re: [PATCH v5 6/9] ASoC: hdmi-codec: Use HDMI notifications to add jack support Date: Tue, 8 Mar 2016 00:31:00 +0200 Message-ID: <56DE0124.6080208@ti.com> References: <1456930153-11853-1-git-send-email-p.zabel@pengutronix.de> <1456930153-11853-7-git-send-email-p.zabel@pengutronix.de> Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii"; Format="flowed" Content-Transfer-Encoding: 7bit Return-path: In-Reply-To: <1456930153-11853-7-git-send-email-p.zabel@pengutronix.de> List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: alsa-devel-bounces@alsa-project.org To: Philipp Zabel , alsa-devel@alsa-project.org Cc: Jean-Francois Moine , Koro Chen , Lars-Peter Clausen , Russell King - ARM Linux , Arnaud Pouliquen , Liam Girdwood , Daniel Kurtz , Cawa Cheng , Mark Brown , linux-mediatek@lists.infradead.org, kernel@pengutronix.de, Matthias Brugger List-Id: linux-mediatek@lists.infradead.org I don't think this patch was updated according to updated "video: rmk's HDMI notification prototype": On 03/02/16 16:49, Philipp Zabel wrote: > Use HDMI connection / disconnection notifications to update an ALSA > jack object. Also make a copy of the ELD block after every change. > > Signed-off-by: Philipp Zabel > --- > include/sound/hdmi-codec.h | 6 +++ > sound/soc/codecs/hdmi-codec.c | 85 +++++++++++++++++++++++++++++++++++++++---- > 2 files changed, 83 insertions(+), 8 deletions(-) > > diff --git a/include/sound/hdmi-codec.h b/include/sound/hdmi-codec.h > index 15fe70f..8b6219d 100644 > --- a/include/sound/hdmi-codec.h > +++ b/include/sound/hdmi-codec.h > @@ -99,6 +99,12 @@ struct hdmi_codec_pdata { > int max_i2s_channels; > }; > > +struct snd_soc_codec; > +struct snd_soc_jack; > + > +int hdmi_codec_set_jack_detect(struct snd_soc_codec *codec, > + struct snd_soc_jack *jack); > + > #define HDMI_CODEC_DRV_NAME "hdmi-audio-codec" > > #endif /* __HDMI_CODEC_H__ */ > diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c > index 687332d..7d5db11 100644 > --- a/sound/soc/codecs/hdmi-codec.c > +++ b/sound/soc/codecs/hdmi-codec.c > @@ -12,9 +12,12 @@ > * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > * General Public License for more details. > */ > +#include This should be hdmi-notifier.h. "select HDMI_NOTIFIERS" also needs to be added to SND_SOC_HDMI_CODEC config option for compilation to succeed. > #include > +#include > #include > #include > +#include > #include > #include > #include > @@ -27,11 +30,16 @@ > struct hdmi_codec_priv { > struct hdmi_codec_pdata hcd; > struct snd_soc_dai_driver *daidrv; > + struct snd_soc_jack *jack; > struct hdmi_codec_daifmt daifmt[2]; > struct mutex current_stream_lock; > struct snd_pcm_substream *current_stream; > struct snd_pcm_hw_constraint_list ratec; > + struct mutex eld_lock; > uint8_t eld[MAX_ELD_BYTES]; > + struct device *dev; > + struct notifier_block nb; > + unsigned int jack_status; > }; > > static const struct snd_soc_dapm_widget hdmi_widgets[] = { > @@ -86,7 +94,7 @@ 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; > + int ret; > > dev_dbg(dai->dev, "%s()\n", __func__); > > @@ -106,17 +114,15 @@ static int hdmi_codec_startup(struct snd_pcm_substream *substream, > } > > if (hcp->hcd.ops->get_eld) { > + mutex_lock(&hcp->eld_lock); > ret = hcp->hcd.ops->get_eld(dai->dev->parent, hcp->eld, > sizeof(hcp->eld)); > - > - if (!ret) { > + if (!ret) > ret = snd_pcm_hw_constraint_eld(substream->runtime, > hcp->eld); > - if (ret) > - return ret; > - } > + mutex_unlock(&hcp->eld_lock); > } > - return 0; > + return ret; > } > > static void hdmi_codec_shutdown(struct snd_pcm_substream *substream, > @@ -326,6 +332,62 @@ static struct snd_soc_codec_driver hdmi_codec = { > .num_dapm_routes = ARRAY_SIZE(hdmi_routes), > }; > > +static void hdmi_codec_jack_report(struct hdmi_codec_priv *hcp, > + unsigned int jack_status) > +{ > + if (!hcp->jack) > + return; > + > + if (jack_status != hcp->jack_status) { > + snd_soc_jack_report(hcp->jack, jack_status, SND_JACK_LINEOUT); > + hcp->jack_status = jack_status; > + } > +} > + > +static int hdmi_codec_notify(struct notifier_block *nb, unsigned long event, > + void *data) > +{ > + struct hdmi_codec_priv *hcp = container_of(nb, struct hdmi_codec_priv, > + nb); > + union hdmi_event *event_block = data; > + > + if (hcp->dev->parent != event_block->base.source) > + return NOTIFY_OK; > + > + if (!hcp->jack) > + return NOTIFY_OK; > + > + switch (event) { > + case HDMI_CONNECTED: > + hdmi_codec_jack_report(hcp, SND_JACK_LINEOUT); > + break; > + case HDMI_DISCONNECTED: > + hdmi_codec_jack_report(hcp, 0); > + break; > + case HDMI_NEW_ELD: > + mutex_lock(&hcp->eld_lock); > + memcpy(hcp->eld, event_block->eld.eld, sizeof(hcp->eld)); > + mutex_unlock(&hcp->eld_lock); > + break; > + } > + > + return NOTIFY_OK; > +} > + > +int hdmi_codec_set_jack_detect(struct snd_soc_codec *codec, > + struct snd_soc_jack *jack) > +{ > + struct hdmi_codec_priv *hcp = snd_soc_codec_get_drvdata(codec); > + > + hcp->jack = jack; > + hcp->nb.notifier_call = hdmi_codec_notify; > + > + hdmi_register_notifier(&hcp->nb); > + > + return 0; > +} > +EXPORT_SYMBOL_GPL(hdmi_codec_set_jack_detect); > + > static int hdmi_codec_probe(struct platform_device *pdev) > { > struct hdmi_codec_pdata *hcd = pdev->dev.platform_data; > @@ -354,6 +416,7 @@ static int hdmi_codec_probe(struct platform_device *pdev) > > hcp->hcd = *hcd; > mutex_init(&hcp->current_stream_lock); > + mutex_init(&hcp->eld_lock); > > hcp->daidrv = devm_kzalloc(dev, dai_count * sizeof(*hcp->daidrv), > GFP_KERNEL); > @@ -370,6 +433,8 @@ static int hdmi_codec_probe(struct platform_device *pdev) > if (hcd->spdif) > hcp->daidrv[i] = hdmi_spdif_dai; > > + dev_set_drvdata(dev, hcp); > + > ret = snd_soc_register_codec(dev, &hdmi_codec, hcp->daidrv, > dai_count); > if (ret) { > @@ -378,12 +443,16 @@ static int hdmi_codec_probe(struct platform_device *pdev) > return ret; > } > > - dev_set_drvdata(dev, hcp); > + hcp->dev = dev; > + > return 0; > } > > static int hdmi_codec_remove(struct platform_device *pdev) > { > + struct hdmi_codec_priv *hcp = platform_get_drvdata(pdev); > + > + hdmi_unregister_notifier(&hcp->nb); > snd_soc_unregister_codec(&pdev->dev); > return 0; > } >