Unverified Commit a3440da4 authored by Mark Brown's avatar Mark Brown
Browse files

ASoC: Map missing jack kcontrols

Merge series from Alper Nebi Yasak <alpernebiyasak@gmail.com>:

This patchset adds missing jack kcontrols for each independently
detectable audio peripheral and maps jack pins to those kcontrols
accordingly, with the primary intent to enable/improve jack detection
handling in PulseAudio and PipeWire through JackControl UCM values.

Usually it's just splitting a joint anything-is-connected "Headset Jack"
kcontrol (from [1]) into those like "Headphone Jack" and "Headset Mic"
(similar to a previous series for Intel Chromebooks [2]). This split is
important to avoid automatically switching to a nonexistent external
microphone when a headphone-only device is connected.

When the underlying hardware seems to support it, this also adds a "Line
Out" kcontrol. This is important in case the hardware can actually
support a line-level connection via a different configuration (bypassing
output amplifiers?), or simply for userspace to display "Line Out"
instead of "Headphones" to the user for connected line-out devices.

Beyond the mappings, I had to add PIN_SWITCH card kcontrols and DAPM
widgets to avoid "unknown pin" errors on my devices, so tried to do them
for all. For Intel devices I saw a pattern of routing things to
"Platform Clock" and added to that as well. Looking at patch 5/7 of a
Mediatek-related series [3], I can only guess that routes could be
further improved, but don't know exactly how for each device. And one
more concern is I don't know if the names conflict with any controls
from codecs, although I tried to keep to names of existing widgets.

As far as I can tell, the root cause for most of why these are missing
originates to things being developed for ChromeOS, whose userspace reads
the jack input device and doesn't care for these kcontrols. There's
non-ChromeOS cases as well, maybe things got copy-pasted around and
people didn't need or couldn't figure out how to get more specific than
a single jack kcontrol. The secondary intent in this patchset is to fix
this *everywhere*, so future copy-pastes result in the right behaviour.

For more context also see:

[1] ASoC: soc-card: Create jack kcontrol without pins
https://lore.kernel.org/alsa-devel/20220408041114.6024-1-akihiko.odaki@gmail.com/

[2] ASoC: Intel: Chromebooks: remap jack pins
https://lore.kernel.org/alsa-devel/20220616214055.134943-1-pierre-louis.bossart@linux.intel.com/

[3] ASoC: mediatek: Allow separate handling of headphone and headset mic jack
https://lore.kernel.org/alsa-devel/20220922235951.252532-1-nfraprado@collabora.com/

[4] ASoC: rk3399_gru_sound: Add DAPM pins, kcontrols for jack detection
https://lore.kernel.org/alsa-devel/20200721182709.6895-1-alpernebiyasak@gmail.com/

This applies onto next-20230802. Unfortunately most of it is untested
except for a few Chromebooks I have (Kevin, Lick, Hana, Cozmo), because
I'm intentionally generalizing to everything.
parents 495c9e5e d27224a4
Loading
Loading
Loading
Loading
+31 −10
Original line number Diff line number Diff line
@@ -28,6 +28,21 @@
#define RT5682_PLL_FREQ (48000 * 512)

static struct snd_soc_jack cz_jack;
static struct snd_soc_jack_pin cz_jack_pins[] = {
	{
		.pin = "Headphone Jack",
		.mask = SND_JACK_HEADPHONE,
	},
	{
		.pin = "Headset Mic",
		.mask = SND_JACK_MICROPHONE,
	},
	{
		.pin = "Line Out",
		.mask = SND_JACK_LINEOUT,
	},
};

static struct clk *da7219_dai_wclk;
static struct clk *da7219_dai_bclk;
static struct clk *rt5682_dai_wclk;
@@ -66,11 +81,13 @@ static int cz_da7219_init(struct snd_soc_pcm_runtime *rtd)
	if (IS_ERR(da7219_dai_bclk))
		return PTR_ERR(da7219_dai_bclk);

	ret = snd_soc_card_jack_new(card, "Headset Jack",
	ret = snd_soc_card_jack_new_pins(card, "Headset Jack",
					 SND_JACK_HEADSET | SND_JACK_LINEOUT |
					 SND_JACK_BTN_0 | SND_JACK_BTN_1 |
					 SND_JACK_BTN_2 | SND_JACK_BTN_3,
				&cz_jack);
					 &cz_jack,
					 cz_jack_pins,
					 ARRAY_SIZE(cz_jack_pins));
	if (ret) {
		dev_err(card->dev, "HP jack creation failed %d\n", ret);
		return ret;
@@ -146,11 +163,13 @@ static int cz_rt5682_init(struct snd_soc_pcm_runtime *rtd)
	if (IS_ERR(rt5682_dai_bclk))
		return PTR_ERR(rt5682_dai_bclk);

	ret = snd_soc_card_jack_new(card, "Headset Jack",
	ret = snd_soc_card_jack_new_pins(card, "Headset Jack",
					 SND_JACK_HEADSET | SND_JACK_LINEOUT |
					 SND_JACK_BTN_0 | SND_JACK_BTN_1 |
					 SND_JACK_BTN_2 | SND_JACK_BTN_3,
				    &cz_jack);
					 &cz_jack,
					 cz_jack_pins,
					 ARRAY_SIZE(cz_jack_pins));
	if (ret) {
		dev_err(card->dev, "HP jack creation failed %d\n", ret);
		return ret;
@@ -631,6 +650,7 @@ static struct snd_soc_dai_link cz_dai_5682_98357[] = {
static const struct snd_soc_dapm_widget cz_widgets[] = {
	SND_SOC_DAPM_HP("Headphones", NULL),
	SND_SOC_DAPM_SPK("Speakers", NULL),
	SND_SOC_DAPM_LINE("Line Out", NULL),
	SND_SOC_DAPM_MIC("Headset Mic", NULL),
	SND_SOC_DAPM_MIC("Int Mic", NULL),
};
@@ -654,6 +674,7 @@ static const struct snd_soc_dapm_route cz_rt5682_audio_route[] = {
static const struct snd_kcontrol_new cz_mc_controls[] = {
	SOC_DAPM_PIN_SWITCH("Headphones"),
	SOC_DAPM_PIN_SWITCH("Speakers"),
	SOC_DAPM_PIN_SWITCH("Line Out"),
	SOC_DAPM_PIN_SWITCH("Headset Mic"),
	SOC_DAPM_PIN_SWITCH("Int Mic"),
};
+17 −5
Original line number Diff line number Diff line
@@ -42,6 +42,16 @@
#define CZ_PLAT_CLK 24000000

static struct snd_soc_jack cz_jack;
static struct snd_soc_jack_pin cz_jack_pins[] = {
	{
		.pin = "Headphones",
		.mask = SND_JACK_HEADPHONE,
	},
	{
		.pin = "Headset Mic",
		.mask = SND_JACK_MICROPHONE,
	},
};

static int cz_aif1_hw_params(struct snd_pcm_substream *substream,
			     struct snd_pcm_hw_params *params)
@@ -76,11 +86,13 @@ static int cz_init(struct snd_soc_pcm_runtime *rtd)
	codec = asoc_rtd_to_codec(rtd, 0)->component;
	card = rtd->card;

	ret = snd_soc_card_jack_new(card, "Headset Jack",
	ret = snd_soc_card_jack_new_pins(card, "Headset Jack",
					 SND_JACK_HEADPHONE | SND_JACK_MICROPHONE |
					 SND_JACK_BTN_0 | SND_JACK_BTN_1 |
					 SND_JACK_BTN_2 | SND_JACK_BTN_3,
				&cz_jack);
					 &cz_jack,
					 cz_jack_pins,
					 ARRAY_SIZE(cz_jack_pins));
	if (ret) {
		dev_err(card->dev, "HP jack creation failed %d\n", ret);
		return ret;
+182 −44
Original line number Diff line number Diff line
@@ -28,7 +28,6 @@
#include "../../codecs/nau8821.h"
#include "acp-mach.h"

static struct snd_soc_jack vg_headset;
#define PCO_PLAT_CLK 48000000
#define RT5682_PLL_FREQ (48000 * 512)
#define DUAL_CHANNEL	2
@@ -52,8 +51,6 @@ const struct dmi_system_id acp_quirk_table[] = {
};
EXPORT_SYMBOL_GPL(acp_quirk_table);

static struct snd_soc_jack pco_jack;

static const unsigned int channels[] = {
	DUAL_CHANNEL,
};
@@ -87,6 +84,28 @@ static int acp_clk_enable(struct acp_card_drvdata *drvdata,
SND_SOC_DAILINK_DEF(rt5682,
	DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10EC5682:00", "rt5682-aif1")));

static struct snd_soc_jack rt5682_jack;
static struct snd_soc_jack_pin rt5682_jack_pins[] = {
	{
		.pin = "Headphone Jack",
		.mask = SND_JACK_HEADPHONE,
	},
	{
		.pin = "Headset Mic",
		.mask = SND_JACK_MICROPHONE,
	},
};

static const struct snd_kcontrol_new rt5682_controls[] = {
	SOC_DAPM_PIN_SWITCH("Headphone Jack"),
	SOC_DAPM_PIN_SWITCH("Headset Mic"),
};

static const struct snd_soc_dapm_widget rt5682_widgets[] = {
	SND_SOC_DAPM_HP("Headphone Jack", NULL),
	SND_SOC_DAPM_MIC("Headset Mic", NULL),
};

static const struct snd_soc_dapm_route rt5682_map[] = {
	{ "Headphone Jack", NULL, "HPOL" },
	{ "Headphone Jack", NULL, "HPOR" },
@@ -110,22 +129,38 @@ static int acp_card_rt5682_init(struct snd_soc_pcm_runtime *rtd)
	drvdata->wclk = clk_get(component->dev, "rt5682-dai-wclk");
	drvdata->bclk = clk_get(component->dev, "rt5682-dai-bclk");

	ret = snd_soc_card_jack_new(card, "Headset Jack",
	ret = snd_soc_dapm_new_controls(&card->dapm, rt5682_widgets,
					ARRAY_SIZE(rt5682_widgets));
	if (ret) {
		dev_err(rtd->dev, "unable to add widget dapm controls, ret %d\n", ret);
		return ret;
	}

	ret = snd_soc_add_card_controls(card, rt5682_controls,
					ARRAY_SIZE(rt5682_controls));
	if (ret) {
		dev_err(rtd->dev, "unable to add card controls, ret %d\n", ret);
		return ret;
	}

	ret = snd_soc_card_jack_new_pins(card, "Headset Jack",
					 SND_JACK_HEADSET | SND_JACK_LINEOUT |
					 SND_JACK_BTN_0 | SND_JACK_BTN_1 |
					 SND_JACK_BTN_2 | SND_JACK_BTN_3,
				    &pco_jack);
					 &rt5682_jack,
					 rt5682_jack_pins,
					 ARRAY_SIZE(rt5682_jack_pins));
	if (ret) {
		dev_err(card->dev, "HP jack creation failed %d\n", ret);
		return ret;
	}

	snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
	snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_1, KEY_VOICECOMMAND);
	snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_2, KEY_VOLUMEUP);
	snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN);
	snd_jack_set_key(rt5682_jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
	snd_jack_set_key(rt5682_jack.jack, SND_JACK_BTN_1, KEY_VOICECOMMAND);
	snd_jack_set_key(rt5682_jack.jack, SND_JACK_BTN_2, KEY_VOLUMEUP);
	snd_jack_set_key(rt5682_jack.jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN);

	ret = snd_soc_component_set_jack(component, &pco_jack, NULL);
	ret = snd_soc_component_set_jack(component, &rt5682_jack, NULL);
	if (ret) {
		dev_err(rtd->dev, "Headset Jack call-back failed: %d\n", ret);
		return ret;
@@ -275,6 +310,28 @@ static const struct snd_soc_ops acp_card_rt5682_ops = {
SND_SOC_DAILINK_DEF(rt5682s,
		    DAILINK_COMP_ARRAY(COMP_CODEC("i2c-RTL5682:00", "rt5682s-aif1")));

static struct snd_soc_jack rt5682s_jack;
static struct snd_soc_jack_pin rt5682s_jack_pins[] = {
	{
		.pin = "Headphone Jack",
		.mask = SND_JACK_HEADPHONE,
	},
	{
		.pin = "Headset Mic",
		.mask = SND_JACK_MICROPHONE,
	},
};

static const struct snd_kcontrol_new rt5682s_controls[] = {
	SOC_DAPM_PIN_SWITCH("Headphone Jack"),
	SOC_DAPM_PIN_SWITCH("Headset Mic"),
};

static const struct snd_soc_dapm_widget rt5682s_widgets[] = {
	SND_SOC_DAPM_HP("Headphone Jack", NULL),
	SND_SOC_DAPM_MIC("Headset Mic", NULL),
};

static const struct snd_soc_dapm_route rt5682s_map[] = {
	{ "Headphone Jack", NULL, "HPOL" },
	{ "Headphone Jack", NULL, "HPOR" },
@@ -299,22 +356,38 @@ static int acp_card_rt5682s_init(struct snd_soc_pcm_runtime *rtd)
		drvdata->bclk = clk_get(component->dev, "rt5682-dai-bclk");
	}

	ret = snd_soc_card_jack_new(card, "Headset Jack",
	ret = snd_soc_dapm_new_controls(&card->dapm, rt5682s_widgets,
					ARRAY_SIZE(rt5682s_widgets));
	if (ret) {
		dev_err(rtd->dev, "unable to add widget dapm controls, ret %d\n", ret);
		return ret;
	}

	ret = snd_soc_add_card_controls(card, rt5682s_controls,
					ARRAY_SIZE(rt5682s_controls));
	if (ret) {
		dev_err(rtd->dev, "unable to add card controls, ret %d\n", ret);
		return ret;
	}

	ret = snd_soc_card_jack_new_pins(card, "Headset Jack",
					 SND_JACK_HEADSET | SND_JACK_LINEOUT |
					 SND_JACK_BTN_0 | SND_JACK_BTN_1 |
					 SND_JACK_BTN_2 | SND_JACK_BTN_3,
				    &pco_jack);
					 &rt5682s_jack,
					 rt5682s_jack_pins,
					 ARRAY_SIZE(rt5682s_jack_pins));
	if (ret) {
		dev_err(card->dev, "HP jack creation failed %d\n", ret);
		return ret;
	}

	snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
	snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_1, KEY_VOICECOMMAND);
	snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_2, KEY_VOLUMEUP);
	snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN);
	snd_jack_set_key(rt5682s_jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
	snd_jack_set_key(rt5682s_jack.jack, SND_JACK_BTN_1, KEY_VOICECOMMAND);
	snd_jack_set_key(rt5682s_jack.jack, SND_JACK_BTN_2, KEY_VOLUMEUP);
	snd_jack_set_key(rt5682s_jack.jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN);

	ret = snd_soc_component_set_jack(component, &pco_jack, NULL);
	ret = snd_soc_component_set_jack(component, &rt5682s_jack, NULL);
	if (ret) {
		dev_err(rtd->dev, "Headset Jack call-back failed: %d\n", ret);
		return ret;
@@ -762,6 +835,28 @@ static const struct snd_soc_ops acp_max98388_ops = {
SND_SOC_DAILINK_DEF(nau8825,
		    DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10508825:00", "nau8825-hifi")));

static struct snd_soc_jack nau8825_jack;
static struct snd_soc_jack_pin nau8825_jack_pins[] = {
	{
		.pin = "Headphone Jack",
		.mask = SND_JACK_HEADPHONE,
	},
	{
		.pin = "Headset Mic",
		.mask = SND_JACK_MICROPHONE,
	},
};

static const struct snd_kcontrol_new nau8825_controls[] = {
	SOC_DAPM_PIN_SWITCH("Headphone Jack"),
	SOC_DAPM_PIN_SWITCH("Headset Mic"),
};

static const struct snd_soc_dapm_widget nau8825_widgets[] = {
	SND_SOC_DAPM_HP("Headphone Jack", NULL),
	SND_SOC_DAPM_MIC("Headset Mic", NULL),
};

static const struct snd_soc_dapm_route nau8825_map[] = {
	{ "Headphone Jack", NULL, "HPOL" },
	{ "Headphone Jack", NULL, "HPOR" },
@@ -780,22 +875,38 @@ static int acp_card_nau8825_init(struct snd_soc_pcm_runtime *rtd)
	if (drvdata->hs_codec_id != NAU8825)
		return -EINVAL;

	ret = snd_soc_card_jack_new(card, "Headset Jack",
	ret = snd_soc_dapm_new_controls(&card->dapm, nau8825_widgets,
					ARRAY_SIZE(nau8825_widgets));
	if (ret) {
		dev_err(rtd->dev, "unable to add widget dapm controls, ret %d\n", ret);
		return ret;
	}

	ret = snd_soc_add_card_controls(card, nau8825_controls,
					ARRAY_SIZE(nau8825_controls));
	if (ret) {
		dev_err(rtd->dev, "unable to add card controls, ret %d\n", ret);
		return ret;
	}

	ret = snd_soc_card_jack_new_pins(card, "Headset Jack",
					 SND_JACK_HEADSET | SND_JACK_LINEOUT |
					 SND_JACK_BTN_0 | SND_JACK_BTN_1 |
					 SND_JACK_BTN_2 | SND_JACK_BTN_3,
					 &pco_jack);
					 &nau8825_jack,
					 nau8825_jack_pins,
					 ARRAY_SIZE(nau8825_jack_pins));
	if (ret) {
		dev_err(card->dev, "HP jack creation failed %d\n", ret);
		return ret;
	}

	snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
	snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_1, KEY_VOICECOMMAND);
	snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_2, KEY_VOLUMEUP);
	snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN);
	snd_jack_set_key(nau8825_jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
	snd_jack_set_key(nau8825_jack.jack, SND_JACK_BTN_1, KEY_VOICECOMMAND);
	snd_jack_set_key(nau8825_jack.jack, SND_JACK_BTN_2, KEY_VOLUMEUP);
	snd_jack_set_key(nau8825_jack.jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN);

	ret = snd_soc_component_set_jack(component, &pco_jack, NULL);
	ret = snd_soc_component_set_jack(component, &nau8825_jack, NULL);
	if (ret) {
		dev_err(rtd->dev, "Headset Jack call-back failed: %d\n", ret);
		return ret;
@@ -921,8 +1032,25 @@ static int platform_clock_control(struct snd_soc_dapm_widget *w,
	return ret;
}

static struct snd_soc_jack nau8821_jack;
static struct snd_soc_jack_pin nau8821_jack_pins[] = {
	{
		.pin = "Headphone Jack",
		.mask = SND_JACK_HEADPHONE,
	},
	{
		.pin = "Headset Mic",
		.mask = SND_JACK_MICROPHONE,
	},
};

static const struct snd_kcontrol_new nau8821_controls[] = {
	SOC_DAPM_PIN_SWITCH("Headphone Jack"),
	SOC_DAPM_PIN_SWITCH("Headset Mic"),
};

static const struct snd_soc_dapm_widget nau8821_widgets[] = {
	SND_SOC_DAPM_HP("Headphone jack", NULL),
	SND_SOC_DAPM_HP("Headphone Jack", NULL),
	SND_SOC_DAPM_MIC("Headset Mic", NULL),
	SND_SOC_DAPM_MIC("Int Mic", NULL),
	SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0,
@@ -932,12 +1060,12 @@ static const struct snd_soc_dapm_widget nau8821_widgets[] = {

static const struct snd_soc_dapm_route nau8821_audio_route[] = {
	/* HP jack connectors - unknown if we have jack detection */
	{ "Headphone jack", NULL, "HPOL" },
	{ "Headphone jack", NULL, "HPOR" },
	{ "Headphone Jack", NULL, "HPOL" },
	{ "Headphone Jack", NULL, "HPOR" },
	{ "MICL", NULL, "Headset Mic" },
	{ "MICR", NULL, "Headset Mic" },
	{ "DMIC", NULL, "Int Mic" },
	{ "Headphone jack", NULL, "Platform Clock" },
	{ "Headphone Jack", NULL, "Platform Clock" },
	{ "Headset Mic", NULL, "Platform Clock" },
	{ "Int Mic", NULL, "Platform Clock" },
};
@@ -966,21 +1094,31 @@ static int acp_8821_init(struct snd_soc_pcm_runtime *rtd)
		return ret;
	}

	ret = snd_soc_card_jack_new(card, "Headset Jack",
	ret = snd_soc_add_card_controls(card, nau8821_controls,
					ARRAY_SIZE(nau8821_controls));
	if (ret) {
		dev_err(rtd->dev, "unable to add card controls, ret %d\n", ret);
		return ret;
	}

	ret = snd_soc_card_jack_new_pins(card, "Headset Jack",
					 SND_JACK_HEADSET | SND_JACK_LINEOUT |
					 SND_JACK_BTN_0 | SND_JACK_BTN_1 |
					 SND_JACK_BTN_2 | SND_JACK_BTN_3,
				    &vg_headset);
					 &nau8821_jack,
					 nau8821_jack_pins,
					 ARRAY_SIZE(nau8821_jack_pins));
	if (ret) {
		dev_err(rtd->dev, "Headset Jack creation failed %d\n", ret);
		return ret;
	}
	snd_jack_set_key(vg_headset.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
	snd_jack_set_key(vg_headset.jack, SND_JACK_BTN_1, KEY_VOICECOMMAND);
	snd_jack_set_key(vg_headset.jack, SND_JACK_BTN_2, KEY_VOLUMEUP);
	snd_jack_set_key(vg_headset.jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN);

	nau8821_enable_jack_detect(component, &vg_headset);
	snd_jack_set_key(nau8821_jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
	snd_jack_set_key(nau8821_jack.jack, SND_JACK_BTN_1, KEY_VOICECOMMAND);
	snd_jack_set_key(nau8821_jack.jack, SND_JACK_BTN_2, KEY_VOLUMEUP);
	snd_jack_set_key(nau8821_jack.jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN);

	nau8821_enable_jack_detect(component, &nau8821_jack);

	return snd_soc_dapm_add_routes(&rtd->card->dapm, nau8821_audio_route,
				       ARRAY_SIZE(nau8821_audio_route));
+18 −5
Original line number Diff line number Diff line
@@ -28,6 +28,17 @@
#define DUAL_CHANNEL		2

static struct snd_soc_jack pco_jack;
static struct snd_soc_jack_pin pco_jack_pins[] = {
	{
		.pin = "Headphone Jack",
		.mask = SND_JACK_HEADPHONE,
	},
	{
		.pin = "Headset Mic",
		.mask = SND_JACK_MICROPHONE,
	},
};

static struct clk *rt5682_dai_wclk;
static struct clk *rt5682_dai_bclk;
static struct gpio_desc *dmic_sel;
@@ -86,11 +97,13 @@ static int acp3x_5682_init(struct snd_soc_pcm_runtime *rtd)
	rt5682_dai_wclk = clk_get(component->dev, "rt5682-dai-wclk");
	rt5682_dai_bclk = clk_get(component->dev, "rt5682-dai-bclk");

	ret = snd_soc_card_jack_new(card, "Headset Jack",
	ret = snd_soc_card_jack_new_pins(card, "Headset Jack",
					 SND_JACK_HEADSET | SND_JACK_LINEOUT |
					 SND_JACK_BTN_0 | SND_JACK_BTN_1 |
					 SND_JACK_BTN_2 | SND_JACK_BTN_3,
				&pco_jack);
					 &pco_jack,
					 pco_jack_pins,
					 ARRAY_SIZE(pco_jack_pins));
	if (ret) {
		dev_err(card->dev, "HP jack creation failed %d\n", ret);
		return ret;
+22 −3
Original line number Diff line number Diff line
@@ -37,6 +37,16 @@ static struct snd_soc_jack_gpio headset_jack_gpios[] = {
};

static struct snd_soc_jack headset_jack;
static struct snd_soc_jack_pin headset_jack_pins[] = {
	{
		.pin = "Headphone",
		.mask = SND_JACK_HEADPHONE,
	},
	{
		.pin = "Mic Jack",
		.mask = SND_JACK_MICROPHONE,
	},
};

static int imx_es8328_dai_init(struct snd_soc_pcm_runtime *rtd)
{
@@ -46,9 +56,11 @@ static int imx_es8328_dai_init(struct snd_soc_pcm_runtime *rtd)

	/* Headphone jack detection */
	if (gpio_is_valid(data->jack_gpio)) {
		ret = snd_soc_card_jack_new(rtd->card, "Headphone",
					    SND_JACK_HEADPHONE | SND_JACK_BTN_0,
					    &headset_jack);
		ret = snd_soc_card_jack_new_pins(rtd->card, "Headphone",
						 SND_JACK_HEADSET | SND_JACK_BTN_0,
						 &headset_jack,
						 headset_jack_pins,
						 ARRAY_SIZE(headset_jack_pins));
		if (ret)
			return ret;

@@ -68,6 +80,11 @@ static const struct snd_soc_dapm_widget imx_es8328_dapm_widgets[] = {
	SND_SOC_DAPM_REGULATOR_SUPPLY("audio-amp", 1, 0),
};

static const struct snd_kcontrol_new imx_es8328_controls[] = {
	SOC_DAPM_PIN_SWITCH("Headphone"),
	SOC_DAPM_PIN_SWITCH("Mic Jack"),
};

static int imx_es8328_probe(struct platform_device *pdev)
{
	struct device_node *np = pdev->dev.of_node;
@@ -183,6 +200,8 @@ static int imx_es8328_probe(struct platform_device *pdev)
	data->card.dev = dev;
	data->card.dapm_widgets = imx_es8328_dapm_widgets;
	data->card.num_dapm_widgets = ARRAY_SIZE(imx_es8328_dapm_widgets);
	data->card.controls = imx_es8328_controls;
	data->card.num_controls = ARRAY_SIZE(imx_es8328_controls);
	ret = snd_soc_of_parse_card_name(&data->card, "model");
	if (ret) {
		dev_err(dev, "Unable to parse card name\n");
Loading