diff mbox series

[RFC,1/3] ASoC: simple-card-utils: add support for componants provideing jack events via set_jack

Message ID 20211228190931.df5d518220080a734532ebfd@uvos.xyz
State New
Headers show
Series [RFC,1/3] ASoC: simple-card-utils: add support for componants provideing jack events via set_jack | expand

Commit Message

Carl Philipp Klemm Dec. 28, 2021, 6:09 p.m. UTC
This allows componants that want a jack to report state on to do so by calling
set_jack on components implementing this function.

Im not entirely sure this is the right way to do this so RFC

Signed-off-by: Carl Philipp Klemm <philipp@uvos.xyz>
---
 include/sound/simple_card_utils.h     |  6 ++--
 sound/soc/generic/simple-card-utils.c | 47 +++++++++++++++++++--------
 2 files changed, 36 insertions(+), 17 deletions(-)

Comments

Kuninori Morimoto Jan. 6, 2022, 1:47 a.m. UTC | #1
Hi Carl

> Yes, so asoc-audio-graph-card currently only supports headphone jack plug
> detection on devices that provide a simple gpio to sense plug state. The
> intent of this patch is to allow the componant driver to implement jack
> detection in cases where something else has to be done to sense state,
> sutch as comunicating with device firmware or using a shared irq. See
> the other patches in this series for an example. This is performed by
> sharing the jack with the component via set_jack().

OK, I see.
It seems other drivers are using dai_link->init for detecting and set_jack().

I guess we can call set_jack() at asoc_simple_init_jack() and
call asoc_simple_init_hp() at dai_link->init ?

It is not tested, but I added sample code below.
I hope my understanding was correct and it solves your issue.

> sutch as comunicating with device firmware or using a shared irq. See
> the other patches in this series for an example. This is performed by

I now noticed that I had mailing list issue...

Thank you for your help !!

-----------
From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Subject: [PATCH] ASoC: simple_card_utils: call snd_soc_component_set_jack() at
 asoc_simple_init_jack()

Current simple-card / audio-graph-card are detecting HP/MIC at card->probe
timing (= A), and not calling snd_soc_component_set_jack() for it.
Other sound card drivers are using dai_link->init timing (= B) for
both detecting and set_jack().

	static int snd_soc_bind_card(...)
	{
		....
(A)		ret = snd_soc_card_probe(card);
		...
		for_each_card_rtds(card, rtd) {
(B)			ret = soc_init_pcm_runtime(card, rtd);
			...
		}
		...
	}

This patch do
(a) call set_jack() (= Y) at asoc_simple_init_jack() (= X) which is
    used to detect HP/MIC.
(b) call it from dai_link->init timing (= B) instead of card->probe
    timing (= A).
(c) remove card->init (= A) timing function from
    simple-card / audio-graph-card.

(X)	int asoc_simple_init_jack(...)
	{
		...
		if (gpio_is_valid(det)) {
			...

			snd_soc_card_jack_new(...);
			snd_soc_jack_add_gpios(...);
			for_each_card_components(card, component)
(Y)				snd_soc_component_set_jack(component, ...);
		}
		...
	}

One note here is that simple-card needs PREFIX to detecting HP/MIC,
but it is not needed on audio-graph-card.
Thus simple-card uses local function for it, and audio-graph-card is
using global function and sharing the code with
audio-graph-card / audio-graph-card2 / audio-graph-card2-custom-sample /
tegra_audio_graph_card.

Reported-by: Carl Philipp Klemm <philipp@uvos.xyz>
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
---
 include/sound/simple_card_utils.h             |  2 +-
 sound/soc/generic/audio-graph-card.c          |  3 +-
 .../generic/audio-graph-card2-custom-sample.c |  3 +-
 sound/soc/generic/audio-graph-card2.c         |  3 +-
 sound/soc/generic/simple-card-utils.c         | 14 ++++++-
 sound/soc/generic/simple-card.c               | 40 ++++++++++---------
 sound/soc/tegra/tegra_audio_graph_card.c      |  2 +-
 7 files changed, 39 insertions(+), 28 deletions(-)

diff --git a/include/sound/simple_card_utils.h b/include/sound/simple_card_utils.h
index df430f1c2a10..34891da5a0fa 100644
--- a/include/sound/simple_card_utils.h
+++ b/include/sound/simple_card_utils.h
@@ -182,7 +182,7 @@ int asoc_simple_init_priv(struct asoc_simple_priv *priv,
 			       struct link_info *li);
 int asoc_simple_remove(struct platform_device *pdev);
 
-int asoc_graph_card_probe(struct snd_soc_card *card);
+int asoc_graph_dai_init(struct snd_soc_pcm_runtime *rtd);
 int asoc_graph_is_ports0(struct device_node *port);
 
 #ifdef DEBUG
diff --git a/sound/soc/generic/audio-graph-card.c b/sound/soc/generic/audio-graph-card.c
index 2b598af8feef..456db1f894af 100644
--- a/sound/soc/generic/audio-graph-card.c
+++ b/sound/soc/generic/audio-graph-card.c
@@ -259,7 +259,7 @@ static int graph_link_init(struct asoc_simple_priv *priv,
 	if (ret < 0)
 		return ret;
 
-	dai_link->init		= asoc_simple_dai_init;
+	dai_link->init		= asoc_graph_dai_init;
 	dai_link->ops		= &graph_ops;
 	if (priv->ops)
 		dai_link->ops	= priv->ops;
@@ -716,7 +716,6 @@ static int graph_probe(struct platform_device *pdev)
 	card = simple_priv_to_card(priv);
 	card->dapm_widgets	= graph_dapm_widgets;
 	card->num_dapm_widgets	= ARRAY_SIZE(graph_dapm_widgets);
-	card->probe		= asoc_graph_card_probe;
 
 	if (of_device_get_match_data(dev))
 		priv->dpcm_selectable = 1;
diff --git a/sound/soc/generic/audio-graph-card2-custom-sample.c b/sound/soc/generic/audio-graph-card2-custom-sample.c
index 4a2c743e286c..da6cb69faa8d 100644
--- a/sound/soc/generic/audio-graph-card2-custom-sample.c
+++ b/sound/soc/generic/audio-graph-card2-custom-sample.c
@@ -34,8 +34,7 @@ static int custom_card_probe(struct snd_soc_card *card)
 
 	custom_priv->custom_params = 1;
 
-	/* you can use generic probe function */
-	return asoc_graph_card_probe(card);
+	return 0;
 }
 
 static int custom_hook_pre(struct asoc_simple_priv *priv)
diff --git a/sound/soc/generic/audio-graph-card2.c b/sound/soc/generic/audio-graph-card2.c
index c3947347dda3..75a1aeb75d2c 100644
--- a/sound/soc/generic/audio-graph-card2.c
+++ b/sound/soc/generic/audio-graph-card2.c
@@ -710,7 +710,7 @@ static void graph_link_init(struct asoc_simple_priv *priv,
 		daiclk = snd_soc_daifmt_clock_provider_fliped(daiclk);
 
 	dai_link->dai_fmt	= daifmt | daiclk;
-	dai_link->init		= asoc_simple_dai_init;
+	dai_link->init		= asoc_graph_dai_init;
 	dai_link->ops		= &graph_ops;
 	if (priv->ops)
 		dai_link->ops	= priv->ops;
@@ -1180,7 +1180,6 @@ int audio_graph2_parse_of(struct asoc_simple_priv *priv, struct device *dev,
 	if (!li)
 		return -ENOMEM;
 
-	card->probe	= asoc_graph_card_probe;
 	card->owner	= THIS_MODULE;
 	card->dev	= dev;
 
diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c
index 850e968677f1..398fc4cb1d07 100644
--- a/sound/soc/generic/simple-card-utils.c
+++ b/sound/soc/generic/simple-card-utils.c
@@ -588,6 +588,8 @@ int asoc_simple_init_jack(struct snd_soc_card *card,
 		return -EPROBE_DEFER;
 
 	if (gpio_is_valid(det)) {
+		struct snd_soc_component *component;
+
 		sjack->pin.pin		= pin_name;
 		sjack->pin.mask		= mask;
 
@@ -603,6 +605,9 @@ int asoc_simple_init_jack(struct snd_soc_card *card,
 
 		snd_soc_jack_add_gpios(&sjack->jack, 1,
 				       &sjack->gpio);
+
+		for_each_card_components(card, component)
+			snd_soc_component_set_jack(component, &sjack->jack, NULL);
 	}
 
 	return 0;
@@ -758,11 +763,16 @@ int asoc_simple_remove(struct platform_device *pdev)
 }
 EXPORT_SYMBOL_GPL(asoc_simple_remove);
 
-int asoc_graph_card_probe(struct snd_soc_card *card)
+int asoc_graph_dai_init(struct snd_soc_pcm_runtime *rtd)
 {
+	struct snd_soc_card *card = rtd->card;
 	struct asoc_simple_priv *priv = snd_soc_card_get_drvdata(card);
 	int ret;
 
+	ret = asoc_simple_dai_init(rtd);
+	if (ret < 0)
+		return ret;
+
 	ret = asoc_simple_init_hp(card, &priv->hp_jack, NULL);
 	if (ret < 0)
 		return ret;
@@ -773,7 +783,7 @@ int asoc_graph_card_probe(struct snd_soc_card *card)
 
 	return 0;
 }
-EXPORT_SYMBOL_GPL(asoc_graph_card_probe);
+EXPORT_SYMBOL_GPL(asoc_graph_dai_init);
 
 int asoc_graph_is_ports0(struct device_node *np)
 {
diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c
index a89d1cfdda32..e76bfae6ced4 100644
--- a/sound/soc/generic/simple-card.c
+++ b/sound/soc/generic/simple-card.c
@@ -149,6 +149,27 @@ static int simple_parse_node(struct asoc_simple_priv *priv,
 	return 0;
 }
 
+static int simple_dai_init(struct snd_soc_pcm_runtime *rtd)
+{
+	struct snd_soc_card *card = rtd->card;
+	struct asoc_simple_priv *priv = snd_soc_card_get_drvdata(card);
+	int ret;
+
+	ret = asoc_simple_dai_init(rtd);
+	if (ret < 0)
+		return ret;
+
+	ret = asoc_simple_init_hp(card, &priv->hp_jack, PREFIX);
+	if (ret < 0)
+		return ret;
+
+	ret = asoc_simple_init_mic(card, &priv->mic_jack, PREFIX);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
 static int simple_link_init(struct asoc_simple_priv *priv,
 			    struct device_node *node,
 			    struct device_node *codec,
@@ -164,7 +185,7 @@ static int simple_link_init(struct asoc_simple_priv *priv,
 	if (ret < 0)
 		return 0;
 
-	dai_link->init			= asoc_simple_dai_init;
+	dai_link->init			= simple_dai_init;
 	dai_link->ops			= &simple_ops;
 
 	return asoc_simple_set_dailink_name(dev, dai_link, name);
@@ -587,22 +608,6 @@ static int simple_get_dais_count(struct asoc_simple_priv *priv,
 				    simple_count_dpcm);
 }
 
-static int simple_soc_probe(struct snd_soc_card *card)
-{
-	struct asoc_simple_priv *priv = snd_soc_card_get_drvdata(card);
-	int ret;
-
-	ret = asoc_simple_init_hp(card, &priv->hp_jack, PREFIX);
-	if (ret < 0)
-		return ret;
-
-	ret = asoc_simple_init_mic(card, &priv->mic_jack, PREFIX);
-	if (ret < 0)
-		return ret;
-
-	return 0;
-}
-
 static int asoc_simple_probe(struct platform_device *pdev)
 {
 	struct asoc_simple_priv *priv;
@@ -620,7 +625,6 @@ static int asoc_simple_probe(struct platform_device *pdev)
 	card = simple_priv_to_card(priv);
 	card->owner		= THIS_MODULE;
 	card->dev		= dev;
-	card->probe		= simple_soc_probe;
 	card->driver_name       = "simple-card";
 
 	li = devm_kzalloc(dev, sizeof(*li), GFP_KERNEL);
diff --git a/sound/soc/tegra/tegra_audio_graph_card.c b/sound/soc/tegra/tegra_audio_graph_card.c
index 1f2c5018bf5a..404762d40389 100644
--- a/sound/soc/tegra/tegra_audio_graph_card.c
+++ b/sound/soc/tegra/tegra_audio_graph_card.c
@@ -184,7 +184,7 @@ static int tegra_audio_graph_card_probe(struct snd_soc_card *card)
 		return PTR_ERR(priv->clk_plla_out0);
 	}
 
-	return asoc_graph_card_probe(card);
+	return 0;
 }
 
 static int tegra_audio_graph_probe(struct platform_device *pdev)
Carl Philipp Klemm Jan. 8, 2022, 1:57 p.m. UTC | #2
Hi,

> (X)	int asoc_simple_init_jack(...)
> 	{
> 		...
> 		if (gpio_is_valid(det)) {
> 			...
> 
> 			snd_soc_card_jack_new(...);
> 			snd_soc_jack_add_gpios(...);
> 			for_each_card_components(card, component)
> (Y)				snd_soc_component_set_jack(component, ...);
> 		}
> 		...
> 	}

So for the case of cpcap codec on motorola mapphones this dosent help,
because we dont have a gpio to sense plug state, thus no gpio in dts
and thus gpio_is_valid will return false, therefore, no jack.

Moving 

sjack->pin.pin		= pin_name;
sjack->pin.mask		= mask;

snd_soc_card_jack_new(card, pin_name, mask,
		      &sjack->jack,
		      &sjack->pin, 1);

and

for_each_card_components(card, component)
			snd_soc_component_set_jack(component, &sjack->jack, NULL);

outside of the if block should make this work, at least cpcap gets the jack then.
Kuninori Morimoto Jan. 10, 2022, 11:27 p.m. UTC | #3
Hi Carl

>> (X)	int asoc_simple_init_jack(...)
>> 	{
>> 		...
>> 		if (gpio_is_valid(det)) {
>> 			...
>> 
>> 			snd_soc_card_jack_new(...);
>> 			snd_soc_jack_add_gpios(...);
>> 			for_each_card_components(card, component)
>> (Y)				snd_soc_component_set_jack(component, ...);
>> 		}
>> 		...
>> 	}
>
> So for the case of cpcap codec on motorola mapphones this dosent help,
> because we dont have a gpio to sense plug state, thus no gpio in dts
> and thus gpio_is_valid will return false, therefore, no jack.
>
> Moving 
>
> sjack->pin.pin		= pin_name;
> sjack->pin.mask		= mask;
>
> snd_soc_card_jack_new(card, pin_name, mask,
> 		      &sjack->jack,
> 		      &sjack->pin, 1);
>
> and
>
> for_each_card_components(card, component)
> 			snd_soc_component_set_jack(component, &sjack->jack, NULL);
>
> outside of the if block should make this work, at least cpcap gets the jack then.

I see.

simple-card is checking hp-det-gpio on DT now.
I guess it can help you if simple-card also check "hp-det" (no gpio)
(and customize previous patch) ?
Is "enable-hp" better naming... ?

Best regards
---
Kuninori Morimoto
diff mbox series

Patch

diff --git a/include/sound/simple_card_utils.h b/include/sound/simple_card_utils.h
index 51b3b485a92e..547ad537613d 100644
--- a/include/sound/simple_card_utils.h
+++ b/include/sound/simple_card_utils.h
@@ -57,8 +57,8 @@  struct asoc_simple_priv {
 		struct prop_nums num;
 		unsigned int mclk_fs;
 	} *dai_props;
-	struct asoc_simple_jack hp_jack;
-	struct asoc_simple_jack mic_jack;
+	struct asoc_simple_jack *hp_jack;
+	struct asoc_simple_jack *mic_jack;
 	struct snd_soc_dai_link *dai_link;
 	struct asoc_simple_dai *dais;
 	struct snd_soc_dai_link_component *dlcs;
@@ -173,7 +173,7 @@  int asoc_simple_parse_pin_switches(struct snd_soc_card *card,
 				   char *prefix);
 
 int asoc_simple_init_jack(struct snd_soc_card *card,
-			       struct asoc_simple_jack *sjack,
+			       struct asoc_simple_jack **sjack,
 			       int is_hp, char *prefix, char *pin);
 int asoc_simple_init_priv(struct asoc_simple_priv *priv,
 			       struct link_info *li);
diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c
index 10c63b73900c..1899feba16cc 100644
--- a/sound/soc/generic/simple-card-utils.c
+++ b/sound/soc/generic/simple-card-utils.c
@@ -395,6 +395,7 @@  int asoc_simple_dai_init(struct snd_soc_pcm_runtime *rtd)
 	struct asoc_simple_priv *priv = snd_soc_card_get_drvdata(rtd->card);
 	struct simple_dai_props *props = simple_priv_to_props(priv, rtd->num);
 	struct asoc_simple_dai *dai;
+	struct snd_soc_component *component;
 	int i, ret;
 
 	for_each_prop_dai_codec(props, i, dai) {
@@ -412,6 +413,21 @@  int asoc_simple_dai_init(struct snd_soc_pcm_runtime *rtd)
 	if (ret < 0)
 		return ret;
 
+	for_each_rtd_components(rtd, i, component) {
+		if (component->driver->set_jack) {
+			if (!priv->hp_jack) {
+				priv->hp_jack = devm_kzalloc(priv->snd_card.dev,
+					sizeof(*priv->hp_jack), GFP_KERNEL);
+				snd_soc_card_jack_new(&priv->snd_card,
+					"Headphones",
+					SND_JACK_HEADPHONE,
+					&priv->hp_jack->jack,
+					NULL, 0);
+			}
+			snd_soc_component_set_jack(component, &priv->hp_jack->jack, NULL);
+		}
+	}
+
 	return 0;
 }
 EXPORT_SYMBOL_GPL(asoc_simple_dai_init);
@@ -554,7 +570,7 @@  int asoc_simple_parse_pin_switches(struct snd_soc_card *card,
 EXPORT_SYMBOL_GPL(asoc_simple_parse_pin_switches);
 
 int asoc_simple_init_jack(struct snd_soc_card *card,
-			  struct asoc_simple_jack *sjack,
+			  struct asoc_simple_jack **sjack,
 			  int is_hp, char *prefix,
 			  char *pin)
 {
@@ -569,8 +585,6 @@  int asoc_simple_init_jack(struct snd_soc_card *card,
 	if (!prefix)
 		prefix = "";
 
-	sjack->gpio.gpio = -ENOENT;
-
 	if (is_hp) {
 		snprintf(prop, sizeof(prop), "%shp-det-gpio", prefix);
 		pin_name	= pin ? pin : "Headphones";
@@ -588,21 +602,26 @@  int asoc_simple_init_jack(struct snd_soc_card *card,
 		return -EPROBE_DEFER;
 
 	if (gpio_is_valid(det)) {
-		sjack->pin.pin		= pin_name;
-		sjack->pin.mask		= mask;
+		struct asoc_simple_jack *sjack_d;
+
+		sjack = devm_kzalloc(dev, sizeof(*(*sjack)), GFP_KERNEL);
+		sjack_d = *sjack;
+
+		sjack_d->pin.pin		= pin_name;
+		sjack_d->pin.mask		= mask;
 
-		sjack->gpio.name	= gpio_name;
-		sjack->gpio.report	= mask;
-		sjack->gpio.gpio	= det;
-		sjack->gpio.invert	= !!(flags & OF_GPIO_ACTIVE_LOW);
-		sjack->gpio.debounce_time = 150;
+		sjack_d->gpio.name	= gpio_name;
+		sjack_d->gpio.report	= mask;
+		sjack_d->gpio.gpio	= det;
+		sjack_d->gpio.invert	= !!(flags & OF_GPIO_ACTIVE_LOW);
+		sjack_d->gpio.debounce_time = 150;
 
 		snd_soc_card_jack_new(card, pin_name, mask,
-				      &sjack->jack,
-				      &sjack->pin, 1);
+				      &sjack_d->jack,
+				      &sjack_d->pin, 1);
 
-		snd_soc_jack_add_gpios(&sjack->jack, 1,
-				       &sjack->gpio);
+		snd_soc_jack_add_gpios(&sjack_d->jack, 1,
+				       &sjack_d->gpio);
 	}
 
 	return 0;