diff mbox series

ASoC: hdmi-codec: register hpd callback on component probe

Message ID 20231106104013.704356-1-jbrunet@baylibre.com
State Accepted
Commit 15be353d55f9e12e34f9a819f51eb41fdef5eda8
Headers show
Series ASoC: hdmi-codec: register hpd callback on component probe | expand

Commit Message

Jerome Brunet Nov. 6, 2023, 10:40 a.m. UTC
The HDMI hotplug callback to the hdmi-codec is currently registered when
jack is set.

The hotplug not only serves to report the ASoC jack state but also to get
the ELD. It should be registered when the component probes instead, so it
does not depend on the card driver registering a jack for the HDMI to
properly report the ELD.

Fixes: 25ce4f2b3593 ("ASoC: hdmi-codec: Get ELD in before reporting plugged event")
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
---
 sound/soc/codecs/hdmi-codec.c | 27 +++++++++++++++++++--------
 1 file changed, 19 insertions(+), 8 deletions(-)

Comments

Mark Brown Nov. 6, 2023, 1:03 p.m. UTC | #1
On Mon, 06 Nov 2023 11:40:11 +0100, Jerome Brunet wrote:
> The HDMI hotplug callback to the hdmi-codec is currently registered when
> jack is set.
> 
> The hotplug not only serves to report the ASoC jack state but also to get
> the ELD. It should be registered when the component probes instead, so it
> does not depend on the card driver registering a jack for the HDMI to
> properly report the ELD.
> 
> [...]

Applied to

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next

Thanks!

[1/1] ASoC: hdmi-codec: register hpd callback on component probe
      commit: 15be353d55f9e12e34f9a819f51eb41fdef5eda8

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark
Zhengqiao Xia Dec. 15, 2023, 4:51 a.m. UTC | #2
Hi Jerome,

After my testing, I found that this patch will cause the audio on the
external display to not work properly after restart.
You move the plugged_cb to run in hdmi_probe, at this time hcp- > jack =
NULL, the driver cannot report `*SND_JACK_LINEOUT*` normally.

static void hdmi_codec_jack_report(struct hdmi_codec_priv *hcp,
				   unsigned int jack_status)
{
	printk("xzq-866 hdmi_codec_jack_report: jack=%x, jack_status=%d",
hcp->jack, jack_status != hcp->jack_status);
	if (hcp->jack && jack_status != hcp->jack_status) {
		snd_soc_jack_report(hcp->jack, jack_status, SND_JACK_LINEOUT);
		hcp->jack_status = jack_status;
	}
}

So we must call  *plugged_cb*  in *hdmi_codec_set_jack,  *Can you make some
changes?

On Mon, Nov 6, 2023 at 6:40 PM Jerome Brunet <jbrunet@baylibre.com> wrote:

> The HDMI hotplug callback to the hdmi-codec is currently registered when
> jack is set.
>
> The hotplug not only serves to report the ASoC jack state but also to get
> the ELD. It should be registered when the component probes instead, so it
> does not depend on the card driver registering a jack for the HDMI to
> properly report the ELD.
>
> Fixes: 25ce4f2b3593 ("ASoC: hdmi-codec: Get ELD in before reporting
> plugged event")
> Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
> ---
>  sound/soc/codecs/hdmi-codec.c | 27 +++++++++++++++++++--------
>  1 file changed, 19 insertions(+), 8 deletions(-)
>
> diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c
> index 09eef6042aad..20da1eaa4f1c 100644
> --- a/sound/soc/codecs/hdmi-codec.c
> +++ b/sound/soc/codecs/hdmi-codec.c
> @@ -877,18 +877,13 @@ static int hdmi_codec_set_jack(struct
> snd_soc_component *component,
>                                void *data)
>  {
>         struct hdmi_codec_priv *hcp =
> snd_soc_component_get_drvdata(component);
> -       int ret = -ENOTSUPP;
>
>         if (hcp->hcd.ops->hook_plugged_cb) {
>                 hcp->jack = jack;
> -               ret = hcp->hcd.ops->hook_plugged_cb(component->dev->parent,
> -                                                   hcp->hcd.data,
> -                                                   plugged_cb,
> -                                                   component->dev);
> -               if (ret)
> -                       hcp->jack = NULL;
> +               return 0;
>         }
> -       return ret;
> +
> +       return -ENOTSUPP;
>  }
>
>  static int hdmi_dai_spdif_probe(struct snd_soc_dai *dai)
> @@ -982,6 +977,21 @@ static int hdmi_of_xlate_dai_id(struct
> snd_soc_component *component,
>         return ret;
>  }
>
> +static int hdmi_probe(struct snd_soc_component *component)
> +{
> +       struct hdmi_codec_priv *hcp =
> snd_soc_component_get_drvdata(component);
> +       int ret = 0;
> +
> +       if (hcp->hcd.ops->hook_plugged_cb) {
> +               ret = hcp->hcd.ops->hook_plugged_cb(component->dev->parent,
> +                                                   hcp->hcd.data,
> +                                                   plugged_cb,
> +                                                   component->dev);
> +       }
> +
> +       return ret;
> +}
> +
>  static void hdmi_remove(struct snd_soc_component *component)
>  {
>         struct hdmi_codec_priv *hcp =
> snd_soc_component_get_drvdata(component);
> @@ -992,6 +1002,7 @@ static void hdmi_remove(struct snd_soc_component
> *component)
>  }
>
>  static const struct snd_soc_component_driver hdmi_driver = {
> +       .probe                  = hdmi_probe,
>         .remove                 = hdmi_remove,
>         .dapm_widgets           = hdmi_widgets,
>         .num_dapm_widgets       = ARRAY_SIZE(hdmi_widgets),
>
Jerome Brunet Dec. 15, 2023, 7:57 a.m. UTC | #3
On Fri 15 Dec 2023 at 12:51, Zhengqiao Xia <xiazhengqiao@huaqin.corp-partner.google.com> wrote:

> Hi Jerome,
>
> After my testing, I found that this patch will cause the audio on the external display to not work properly after
> restart. 
> You move the plugged_cb to run in hdmi_probe, at this time hcp- > jack = NULL, the driver cannot report `SND_JACK_LINEOUT
> ` normally.
> static void hdmi_codec_jack_report(struct hdmi_codec_priv *hcp,
> 				   unsigned int jack_status)
> {
> 	printk("xzq-866 hdmi_codec_jack_report: jack=%x, jack_status=%d", hcp->jack, jack_status != hcp->jack_status);
> 	if (hcp->jack && jack_status != hcp->jack_status) {
> 		snd_soc_jack_report(hcp->jack, jack_status, SND_JACK_LINEOUT);
> 		hcp->jack_status = jack_status;
> 	}
> }
> So we must call  plugged_cb  in hdmi_codec_set_jack,  Can you make some changes?

Hi Zhengqiao,

That is unfortunate. Sorry.

This patch has changed when the hpd callback is registered, no when it
comes in effect. This is still dependent on calling .set_jack() and it
is not happening any later than it was before. So, in theory, it should
not have changed anything, if your driver actually relies on the HPD
event.

Trying to guess what is happening for you, I suppose your HDMI driver is
"faking" an HPD event to report the initial jack status when the
hook_plugged_cb() is called. Could you point me to the hdmi driver you
are using so I can have a look ?

My reference when testing this was dw-hdmi-i2s-audio and it does not do
that, it just registers the callback. I think this is what it supposed
to do TBH.

An idea I have been thinking about for a while is have the hdmi-codec
insert the jack in the card itself, instead of the card doing. That
would give the jack "for free" to any user of the HDMI codec and might
also solve your issue. It would require a small rework of the cards doing
the hdmi jack register, but there are not many of these AFAIK.

>
> On Mon, Nov 6, 2023 at 6:40 PM Jerome Brunet <jbrunet@baylibre.com> wrote:
>
>  The HDMI hotplug callback to the hdmi-codec is currently registered when
>  jack is set.
>
>  The hotplug not only serves to report the ASoC jack state but also to get
>  the ELD. It should be registered when the component probes instead, so it
>  does not depend on the card driver registering a jack for the HDMI to
>  properly report the ELD.
>
>  Fixes: 25ce4f2b3593 ("ASoC: hdmi-codec: Get ELD in before reporting plugged event")
>  Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
>  ---
>   sound/soc/codecs/hdmi-codec.c | 27 +++++++++++++++++++--------
>   1 file changed, 19 insertions(+), 8 deletions(-)
>
>  diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c
>  index 09eef6042aad..20da1eaa4f1c 100644
>  --- a/sound/soc/codecs/hdmi-codec.c
>  +++ b/sound/soc/codecs/hdmi-codec.c
>  @@ -877,18 +877,13 @@ static int hdmi_codec_set_jack(struct snd_soc_component *component,
>                                 void *data)
>   {
>          struct hdmi_codec_priv *hcp = snd_soc_component_get_drvdata(component);
>  -       int ret = -ENOTSUPP;
>
>          if (hcp->hcd.ops->hook_plugged_cb) {
>                  hcp->jack = jack;
>  -               ret = hcp->hcd.ops->hook_plugged_cb(component->dev->parent,
>  -                                                   hcp->hcd.data,
>  -                                                   plugged_cb,
>  -                                                   component->dev);
>  -               if (ret)
>  -                       hcp->jack = NULL;
>  +               return 0;
>          }
>  -       return ret;
>  +
>  +       return -ENOTSUPP;
>   }
>
>   static int hdmi_dai_spdif_probe(struct snd_soc_dai *dai)
>  @@ -982,6 +977,21 @@ static int hdmi_of_xlate_dai_id(struct snd_soc_component *component,
>          return ret;
>   }
>
>  +static int hdmi_probe(struct snd_soc_component *component)
>  +{
>  +       struct hdmi_codec_priv *hcp = snd_soc_component_get_drvdata(component);
>  +       int ret = 0;
>  +
>  +       if (hcp->hcd.ops->hook_plugged_cb) {
>  +               ret = hcp->hcd.ops->hook_plugged_cb(component->dev->parent,
>  +                                                   hcp->hcd.data,
>  +                                                   plugged_cb,
>  +                                                   component->dev);
>  +       }
>  +
>  +       return ret;
>  +}
>  +
>   static void hdmi_remove(struct snd_soc_component *component)
>   {
>          struct hdmi_codec_priv *hcp = snd_soc_component_get_drvdata(component);
>  @@ -992,6 +1002,7 @@ static void hdmi_remove(struct snd_soc_component *component)
>   }
>
>   static const struct snd_soc_component_driver hdmi_driver = {
>  +       .probe                  = hdmi_probe,
>          .remove                 = hdmi_remove,
>          .dapm_widgets           = hdmi_widgets,
>          .num_dapm_widgets       = ARRAY_SIZE(hdmi_widgets),
diff mbox series

Patch

diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c
index 09eef6042aad..20da1eaa4f1c 100644
--- a/sound/soc/codecs/hdmi-codec.c
+++ b/sound/soc/codecs/hdmi-codec.c
@@ -877,18 +877,13 @@  static int hdmi_codec_set_jack(struct snd_soc_component *component,
 			       void *data)
 {
 	struct hdmi_codec_priv *hcp = snd_soc_component_get_drvdata(component);
-	int ret = -ENOTSUPP;
 
 	if (hcp->hcd.ops->hook_plugged_cb) {
 		hcp->jack = jack;
-		ret = hcp->hcd.ops->hook_plugged_cb(component->dev->parent,
-						    hcp->hcd.data,
-						    plugged_cb,
-						    component->dev);
-		if (ret)
-			hcp->jack = NULL;
+		return 0;
 	}
-	return ret;
+
+	return -ENOTSUPP;
 }
 
 static int hdmi_dai_spdif_probe(struct snd_soc_dai *dai)
@@ -982,6 +977,21 @@  static int hdmi_of_xlate_dai_id(struct snd_soc_component *component,
 	return ret;
 }
 
+static int hdmi_probe(struct snd_soc_component *component)
+{
+	struct hdmi_codec_priv *hcp = snd_soc_component_get_drvdata(component);
+	int ret = 0;
+
+	if (hcp->hcd.ops->hook_plugged_cb) {
+		ret = hcp->hcd.ops->hook_plugged_cb(component->dev->parent,
+						    hcp->hcd.data,
+						    plugged_cb,
+						    component->dev);
+	}
+
+	return ret;
+}
+
 static void hdmi_remove(struct snd_soc_component *component)
 {
 	struct hdmi_codec_priv *hcp = snd_soc_component_get_drvdata(component);
@@ -992,6 +1002,7 @@  static void hdmi_remove(struct snd_soc_component *component)
 }
 
 static const struct snd_soc_component_driver hdmi_driver = {
+	.probe			= hdmi_probe,
 	.remove			= hdmi_remove,
 	.dapm_widgets		= hdmi_widgets,
 	.num_dapm_widgets	= ARRAY_SIZE(hdmi_widgets),