[PATCH v2 0/7] ASoC: samsung: midas-audio: Add GPIO-based headset jack detection
Many of Samsung's Exynos 4 devices share the same midas-audio driver to handle the codec setup. While most of these devices, including the Midas itself, use the jack detection provided by the WM8994 driver, other devices such as the Samsung Galaxy Tab 3 8.0 (lt01) use two GPIOs and an ADC channel to determine jack insertion, the jack's type, and button presses (for headsets with volume up/down/play buttons).
In the downstream kernel, this behavior is implemented in the sec-jack driver[1], and the per-device settings are configured in *-jack.c files in the mach folder (see e.g. the Tab 3's implementation[2]).
This patchset implements this mechanism in the midas_wm1811.c driver, and adds new DTS options to allow for its configuration. It also enables jack detection for the Samsung Galaxy Tab 3 8.0.
A very similar mechanism was already present in the aries_wm8994.c driver[3]; this implementation heavily borrows from it, though there are a few extra cleanups as well.
Signed-off-by: Artur Weber aweber.kernel@gmail.com
[1] https://github.com/gr8nole/android_kernel_samsung_smdk4x12/blob/lineage-14.1... [2] https://github.com/gr8nole/android_kernel_samsung_smdk4x12/blob/lineage-14.1... [3] https://github.com/torvalds/linux/blob/master/sound/soc/samsung/aries_wm8994...
--- Changes in v2: - Added vendor prefix to threshold properties - Added separate headset mic bias regulator - Changed some cases of dev_err + return with return dev_err_probe - Added an extra patch to replace some previous dev_err + return cases with dev_err_probe - Moved tab3 DTS wm1811 codec config changes to separate commit
--- Artur Weber (7): ASoC: dt-bindings: samsung,midas-audio: Add headset mic bias supply ASoC: dt-bindings: samsung,midas-audio: Add GPIO-based headset jack detection ASoC: samsung: midas_wm1811: Add headset mic bias supply support ASoC: samsung: midas_wm1811: Add GPIO-based headset jack detection ASoC: samsung: midas_wm1811: Use dev_err_probe where appropriate ARM: dts: samsung: exynos4212-tab3: Fix headset mic, add jack detection ARM: dts: samsung: exynos4212-tab3: Fix up wm1811 codec config
.../bindings/sound/samsung,midas-audio.yaml | 33 ++ arch/arm/boot/dts/samsung/exynos4212-tab3.dtsi | 31 +- sound/soc/samsung/Kconfig | 2 +- sound/soc/samsung/midas_wm1811.c | 343 +++++++++++++++++++-- 4 files changed, 379 insertions(+), 30 deletions(-) --- base-commit: e67572cd2204894179d89bd7b984072f19313b03 change-id: 20240502-midas-wm1811-gpio-jack-b10226b17ecc
Best regards,
Some devices use a separate mic bias supply (also referred to as "ear mic bias") to enable/disable the headset mic.
Add the DT property headset-mic-bias-supply to allow for specifying this supply.
Signed-off-by: Artur Weber aweber.kernel@gmail.com --- Documentation/devicetree/bindings/sound/samsung,midas-audio.yaml | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/Documentation/devicetree/bindings/sound/samsung,midas-audio.yaml b/Documentation/devicetree/bindings/sound/samsung,midas-audio.yaml index 6ec80f529d84..6ed53dd0bb53 100644 --- a/Documentation/devicetree/bindings/sound/samsung,midas-audio.yaml +++ b/Documentation/devicetree/bindings/sound/samsung,midas-audio.yaml @@ -53,6 +53,9 @@ properties: submic-bias-supply: description: Supply for the micbias on the Sub microphone
+ headset-mic-bias-supply: + description: Supply for the micbias on the Headset microphone + fm-sel-gpios: maxItems: 1 description: GPIO pin for FM selection
Some Samsung devices that share the midas-audio driver use a GPIO-based approach to headset jack detection, as opposed to using the built-in jack detection provided by the wm8994 driver. This setup uses two GPIOs (one for jack detection and another for key detection) and an ADC channel for determining the jack type or button pressed.
Add DT configuration values that allow for describing these setups.
Signed-off-by: Artur Weber aweber.kernel@gmail.com --- Changes in v2: - Added vendor prefix to threshold properties - Dropped pipe (|) character from description: field --- .../bindings/sound/samsung,midas-audio.yaml | 30 ++++++++++++++++++++++ 1 file changed, 30 insertions(+)
diff --git a/Documentation/devicetree/bindings/sound/samsung,midas-audio.yaml b/Documentation/devicetree/bindings/sound/samsung,midas-audio.yaml index 6ed53dd0bb53..6b760a73e8bf 100644 --- a/Documentation/devicetree/bindings/sound/samsung,midas-audio.yaml +++ b/Documentation/devicetree/bindings/sound/samsung,midas-audio.yaml @@ -64,6 +64,36 @@ properties: maxItems: 1 description: GPIO pin for line out selection
+ headset-detect-gpios: + maxItems: 1 + description: GPIO for detection of headset insertion + + headset-key-gpios: + maxItems: 1 + description: GPIO for detection of headset key press + + io-channels: + maxItems: 1 + description: IO channel to read micbias voltage for headset detection + + io-channel-names: + const: headset-detect + + samsung,headset-4pole-threshold-microvolt: + minItems: 2 + maxItems: 2 + description: + Array containing minimum and maximum IO channel value for 4-pole + (with microphone/button) headsets. If the IO channel value is + outside of this range, a 3-pole headset is assumed. + + samsung,headset-button-threshold-microvolt: + minItems: 3 + maxItems: 3 + description: + Array of minimum (inclusive) IO channel values for headset button + detection, in order: "Media", "Volume Up" and "Volume Down". + required: - compatible - cpu
On Wed, 08 May 2024 12:58:50 +0200, Artur Weber wrote:
Some Samsung devices that share the midas-audio driver use a GPIO-based approach to headset jack detection, as opposed to using the built-in jack detection provided by the wm8994 driver. This setup uses two GPIOs (one for jack detection and another for key detection) and an ADC channel for determining the jack type or button pressed.
Add DT configuration values that allow for describing these setups.
Signed-off-by: Artur Weber aweber.kernel@gmail.com
Changes in v2:
- Added vendor prefix to threshold properties
- Dropped pipe (|) character from description: field
.../bindings/sound/samsung,midas-audio.yaml | 30 ++++++++++++++++++++++ 1 file changed, 30 insertions(+)
My bot found errors running 'make dt_binding_check' on your patch:
yamllint warnings/errors: ./Documentation/devicetree/bindings/sound/samsung,midas-audio.yaml:95:26: [error] syntax error: mapping values are not allowed here (syntax)
dtschema/dtc warnings/errors: make[2]: *** Deleting file 'Documentation/devicetree/bindings/sound/samsung,midas-audio.example.dts' Documentation/devicetree/bindings/sound/samsung,midas-audio.yaml:95:26: mapping values are not allowed in this context make[2]: *** [Documentation/devicetree/bindings/Makefile:26: Documentation/devicetree/bindings/sound/samsung,midas-audio.example.dts] Error 1 make[2]: *** Waiting for unfinished jobs.... ./Documentation/devicetree/bindings/sound/samsung,midas-audio.yaml:95:26: mapping values are not allowed in this context /builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/sound/samsung,midas-audio.yaml: ignoring, error parsing file make[1]: *** [/builds/robherring/dt-review-ci/linux/Makefile:1430: dt_binding_check] Error 2 make: *** [Makefile:240: __sub-make] Error 2
doc reference errors (make refcheckdocs):
See https://patchwork.ozlabs.org/project/devicetree-bindings/patch/20240508-mida...
The base for the series is generally the latest rc1. A different dependency should be noted in *this* patch.
If you already ran 'make dt_binding_check' and didn't see the above error(s), then make sure 'yamllint' is installed and dt-schema is up to date:
pip3 install dtschema --upgrade
Please check and re-submit after running the above command yourself. Note that DT_SCHEMA_FILES can be set to your schema file to speed up checking your schema. However, it must be unset to test all examples with your schema.
Some devices use a headset mic bias supply (sometimes referred to as "ear mic bias") to enable/disable the headset mic.
Add support for getting the supply from DT and setting it up accordingly to the value of the Headset Mic switch.
Signed-off-by: Artur Weber aweber.kernel@gmail.com --- Changes in v2: - Added this commit --- sound/soc/samsung/midas_wm1811.c | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-)
diff --git a/sound/soc/samsung/midas_wm1811.c b/sound/soc/samsung/midas_wm1811.c index f31244156ff6..ab0a4804b45e 100644 --- a/sound/soc/samsung/midas_wm1811.c +++ b/sound/soc/samsung/midas_wm1811.c @@ -29,6 +29,7 @@ struct midas_priv { struct regulator *reg_mic_bias; struct regulator *reg_submic_bias; + struct regulator *reg_headset_mic_bias; struct gpio_desc *gpio_fm_sel; struct gpio_desc *gpio_lineout_sel; unsigned int fll1_rate; @@ -201,6 +202,25 @@ static int midas_submic_bias(struct snd_soc_dapm_widget *w, return 0; }
+static int midas_headset_mic_bias(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_card *card = w->dapm->card; + struct midas_priv *priv = snd_soc_card_get_drvdata(card); + + if (!priv->reg_headset_mic_bias) + return 0; + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + return regulator_enable(priv->reg_headset_mic_bias); + case SND_SOC_DAPM_POST_PMD: + return regulator_disable(priv->reg_headset_mic_bias); + } + + return 0; +} + static int midas_fm_set(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { @@ -271,7 +291,7 @@ static const struct snd_soc_dapm_widget midas_dapm_widgets[] = { SND_SOC_DAPM_LINE("FM In", midas_fm_set),
SND_SOC_DAPM_HP("Headphone", NULL), - SND_SOC_DAPM_MIC("Headset Mic", NULL), + SND_SOC_DAPM_MIC("Headset Mic", midas_headset_mic_bias), SND_SOC_DAPM_MIC("Main Mic", midas_mic_bias), SND_SOC_DAPM_MIC("Sub Mic", midas_submic_bias), }; @@ -455,6 +475,17 @@ static int midas_probe(struct platform_device *pdev) return PTR_ERR(priv->reg_submic_bias); }
+ priv->reg_headset_mic_bias = devm_regulator_get_optional(dev, + "headset-mic-bias"); + if (IS_ERR(priv->reg_headset_mic_bias)) { + ret = PTR_ERR(priv->reg_headset_mic_bias); + if (ret == -ENODEV) + priv->reg_headset_mic_bias = NULL; + else + return dev_err_probe(dev, ret, + "Failed to get headset mic bias regulator\n"); + } + priv->gpio_fm_sel = devm_gpiod_get_optional(dev, "fm-sel", GPIOD_OUT_HIGH); if (IS_ERR(priv->gpio_fm_sel)) { dev_err(dev, "Failed to get FM selection GPIO\n");
Some Samsung devices that use the midas_wm1811 driver use a GPIO-based method for detecting whether the headset jack is plugged in, as well as detecting which headset buttons are pressed. There are two GPIOs: a "headset detect" GPIO responsible for detecting jack insertion, and a "headset key" GPIO which triggers when a button on the headset is pressed. The plug type and the button pressed are determined based on information from an ADC channel. The headset mic is enabled by a headset mic bias regulator.
Add support for the GPIO-based headset jack detection mechanism, and make it configurable from the device tree.
This implementation borrows somewhat from the aries_wm8994.c driver, though there are a few changes to make the code cleaner, and to add support for DT-based configuration.
Notably, a dependency on IIO is introduced, to accommodate the ADC reading requirement.
Signed-off-by: Artur Weber aweber.kernel@gmail.com --- Changes in v2: - Added separate headset mic bias regulator - Added samsung preset to threshold properties - Replaced dev_err+return with return dev_err_probe where needed --- sound/soc/samsung/Kconfig | 2 +- sound/soc/samsung/midas_wm1811.c | 286 +++++++++++++++++++++++++++++++++++++-- 2 files changed, 277 insertions(+), 11 deletions(-)
diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig index 93c2b1b08d0a..4b1ea7b2c796 100644 --- a/sound/soc/samsung/Kconfig +++ b/sound/soc/samsung/Kconfig @@ -140,7 +140,7 @@ config SND_SOC_SAMSUNG_ARIES_WM8994
config SND_SOC_SAMSUNG_MIDAS_WM1811 tristate "SoC I2S Audio support for Midas boards" - depends on SND_SOC_SAMSUNG + depends on SND_SOC_SAMSUNG && IIO select SND_SAMSUNG_I2S select SND_SOC_WM8994 help diff --git a/sound/soc/samsung/midas_wm1811.c b/sound/soc/samsung/midas_wm1811.c index ab0a4804b45e..ce94550ee32e 100644 --- a/sound/soc/samsung/midas_wm1811.c +++ b/sound/soc/samsung/midas_wm1811.c @@ -7,7 +7,9 @@
#include <linux/clk.h> #include <linux/gpio/consumer.h> +#include <linux/iio/consumer.h> #include <linux/mfd/wm8994/registers.h> +#include <linux/input-event-codes.h> #include <linux/module.h> #include <linux/of.h> #include <linux/regulator/consumer.h> @@ -32,6 +34,9 @@ struct midas_priv { struct regulator *reg_headset_mic_bias; struct gpio_desc *gpio_fm_sel; struct gpio_desc *gpio_lineout_sel; + struct gpio_desc *gpio_headset_detect; + struct gpio_desc *gpio_headset_key; + struct iio_channel *adc_headset_detect; unsigned int fll1_rate;
struct snd_soc_jack headset_jack; @@ -48,6 +53,131 @@ static struct snd_soc_jack_pin headset_jack_pins[] = { }, };
+/* + * min_mv/max_mv values in this struct are set up based on DT values. + */ +static struct snd_soc_jack_zone headset_jack_zones[] = { + { .jack_type = SND_JACK_HEADPHONE, }, + { .jack_type = SND_JACK_HEADSET, }, + { .jack_type = SND_JACK_HEADPHONE, }, +}; + +/* + * This is used for manual detection in headset_key_check, we reuse the + * structure since it's convenient. + * + * min_mv/max_mv values in this struct are set up based on DT values. + */ +static struct snd_soc_jack_zone headset_key_zones[] = { + { .jack_type = SND_JACK_BTN_0, }, /* Media */ + { .jack_type = SND_JACK_BTN_1, }, /* Volume Up */ + { .jack_type = SND_JACK_BTN_2, }, /* Volume Down */ +}; + +static int headset_jack_check(void *data) +{ + struct midas_priv *priv = (struct midas_priv *) data; + int adc, jack_type, ret; + int bias_already_on = 0; + + if (!gpiod_get_value_cansleep(priv->gpio_headset_detect)) + return 0; + + if (priv->reg_headset_mic_bias) { + /* + * Get state of Headset Mic switch by checking the headset mic + * bias regulator + */ + bias_already_on = \ + regulator_is_enabled(priv->reg_headset_mic_bias); + + /* + * If it's not enabled yet, temporarily enable headset mic bias + * for ADC measurement + */ + if (bias_already_on < 0) + pr_err("%s: Failed to get headset mic bias state: %d", + __func__, ret); + else if (!bias_already_on) { + ret = regulator_enable(priv->reg_headset_mic_bias); + if (ret) + pr_err("%s: Failed to enable micbias: %d\n", + __func__, ret); + } + } + + /* Sleep for a small amount of time to get the value to stabilize */ + msleep(20); + + ret = iio_read_channel_processed(priv->adc_headset_detect, &adc); + if (ret) { + pr_err("%s: Failed to read ADC (%d), assuming headphones\n", + __func__, ret); + return SND_JACK_HEADPHONE; + } + pr_debug("%s: ADC value is %d\n", __func__, adc); + + jack_type = snd_soc_jack_get_type(&priv->headset_jack, adc); + + /* + * Revert the headset mic bias supply to its previous state + * (i.e. if it was disabled before the check, disable it again) + */ + if (priv->reg_headset_mic_bias && bias_already_on == 0) { + ret = regulator_disable(priv->reg_headset_mic_bias); + if (ret) + pr_err("%s: Failed to disable micbias: %d\n", + __func__, ret); + } + + return jack_type; +} + +static int headset_key_check(void *data) +{ + struct midas_priv *priv = (struct midas_priv *) data; + int adc, i, ret; + + if (!gpiod_get_value_cansleep(priv->gpio_headset_key)) + return 0; + + /* Filter out keypresses when 4 pole jack not detected */ + if (!(priv->headset_jack.status & SND_JACK_MICROPHONE)) + return 0; + + ret = iio_read_channel_processed(priv->adc_headset_detect, &adc); + if (ret) { + pr_err("%s: Failed to read ADC (%d), can't detect key type\n", + __func__, ret); + return 0; + } + pr_debug("%s: ADC value is %d\n", __func__, adc); + + for (i = 0; i < ARRAY_SIZE(headset_key_zones); i++) { + if (adc >= headset_key_zones[i].min_mv && + adc <= headset_key_zones[i].max_mv) { + return headset_key_zones[i].jack_type; + } + } + + return 0; +} + +static struct snd_soc_jack_gpio headset_gpio[] = { + { + .name = "Headset Jack", + .report = SND_JACK_HEADSET, + .debounce_time = 150, + .jack_status_check = headset_jack_check, + }, + { + .name = "Headset Key", + .report = SND_JACK_BTN_0 | SND_JACK_BTN_1 | SND_JACK_BTN_2, + .debounce_time = 30, + .jack_status_check = headset_key_check, + }, +}; + static int midas_start_fll1(struct snd_soc_pcm_runtime *rtd, unsigned int rate) { struct snd_soc_card *card = rtd->card; @@ -335,18 +465,67 @@ static int midas_late_probe(struct snd_soc_card *card) return ret; }
- ret = snd_soc_card_jack_new_pins(card, "Headset", - SND_JACK_HEADSET | SND_JACK_MECHANICAL | - SND_JACK_BTN_0 | SND_JACK_BTN_1 | SND_JACK_BTN_2 | - SND_JACK_BTN_3 | SND_JACK_BTN_4 | SND_JACK_BTN_5, - &priv->headset_jack, - headset_jack_pins, - ARRAY_SIZE(headset_jack_pins)); - if (ret) + if (!priv->gpio_headset_detect) { + ret = snd_soc_card_jack_new_pins(card, "Headset", + SND_JACK_HEADSET | SND_JACK_MECHANICAL | + SND_JACK_BTN_0 | SND_JACK_BTN_1 | + SND_JACK_BTN_2 | SND_JACK_BTN_3 | + SND_JACK_BTN_4 | SND_JACK_BTN_5, + &priv->headset_jack, + headset_jack_pins, + ARRAY_SIZE(headset_jack_pins)); + if (ret) + return ret; + + wm8958_mic_detect(aif1_dai->component, &priv->headset_jack, + NULL, NULL, NULL, NULL); + } else { + /* Some devices (n8000, t310) use a GPIO to detect the jack. */ + ret = snd_soc_card_jack_new_pins(card, "Headset", + SND_JACK_HEADSET | SND_JACK_BTN_0 | + SND_JACK_BTN_1 | SND_JACK_BTN_2, + &priv->headset_jack, + headset_jack_pins, + ARRAY_SIZE(headset_jack_pins)); + if (ret) { + dev_err(card->dev, + "Failed to set up headset pins: %d\n", ret); + return ret; + } + + ret = snd_soc_jack_add_zones(&priv->headset_jack, + ARRAY_SIZE(headset_jack_zones), + headset_jack_zones); + if (ret) { + dev_err(card->dev, + "Failed to set up headset zones: %d\n", ret); + return ret; + } + + headset_gpio[0].data = priv; + headset_gpio[0].desc = priv->gpio_headset_detect; + + headset_gpio[1].data = priv; + headset_gpio[1].desc = priv->gpio_headset_key; + + snd_jack_set_key(priv->headset_jack.jack, + SND_JACK_BTN_0, KEY_MEDIA); + snd_jack_set_key(priv->headset_jack.jack, + SND_JACK_BTN_1, KEY_VOLUMEUP); + snd_jack_set_key(priv->headset_jack.jack, + SND_JACK_BTN_2, KEY_VOLUMEDOWN); + + ret = snd_soc_jack_add_gpios(&priv->headset_jack, + ARRAY_SIZE(headset_gpio), + headset_gpio); + if (ret) + dev_err(card->dev, + "Failed to set up headset jack GPIOs: %d\n", + ret); + return ret; + }
- wm8958_mic_detect(aif1_dai->component, &priv->headset_jack, - NULL, NULL, NULL, NULL); return 0; }
@@ -453,6 +632,9 @@ static int midas_probe(struct platform_device *pdev) struct snd_soc_card *card = &midas_card; struct device *dev = &pdev->dev; static struct snd_soc_dai_link *dai_link; + enum iio_chan_type channel_type; + u32 fourpole_threshold[2]; + u32 button_threshold[3]; struct midas_priv *priv; int ret, i;
@@ -499,6 +681,90 @@ static int midas_probe(struct platform_device *pdev) return PTR_ERR(priv->gpio_lineout_sel); }
+ priv->gpio_headset_detect = devm_gpiod_get_optional(dev, + "headset-detect", GPIOD_IN); + if (IS_ERR(priv->gpio_headset_detect)) + return dev_err_probe(dev, PTR_ERR(priv->gpio_headset_detect), + "Failed to get headset jack detect GPIO\n"); + + if (priv->gpio_headset_detect) { + priv->adc_headset_detect = devm_iio_channel_get(dev, + "headset-detect"); + if (IS_ERR(priv->adc_headset_detect)) + return dev_err_probe(dev, + PTR_ERR(priv->adc_headset_detect), + "Failed to get ADC channel\n"); + + ret = iio_get_channel_type(priv->adc_headset_detect, + &channel_type); + if (ret) { + dev_err(dev, "Failed to get ADC channel type\n"); + return ret; + } + + if (channel_type != IIO_VOLTAGE) { + dev_err(dev, "ADC channel is not voltage\n"); + return ret; + } + + priv->gpio_headset_key = devm_gpiod_get(dev, "headset-key", + GPIOD_IN); + if (IS_ERR(priv->gpio_headset_key)) + return dev_err_probe(dev, + PTR_ERR(priv->gpio_headset_key), + "Failed to get headset key GPIO\n"); + + ret = of_property_read_u32_array(dev->of_node, + "samsung,headset-4pole-threshold-microvolt", + fourpole_threshold, + ARRAY_SIZE(fourpole_threshold)); + if (ret) { + dev_err(dev, "Failed to get 4-pole jack detection threshold\n"); + return ret; + } + + if (fourpole_threshold[0] > fourpole_threshold[1]) { + dev_err(dev, "Invalid 4-pole jack detection threshold value\n"); + return -EINVAL; + } + + headset_jack_zones[0].max_mv = (fourpole_threshold[0]); + headset_jack_zones[1].min_mv = (fourpole_threshold[0] + 1); + + headset_jack_zones[1].max_mv = (fourpole_threshold[1]); + headset_jack_zones[2].min_mv = (fourpole_threshold[1] + 1); + + ret = of_property_read_u32_array(dev->of_node, + "samsung,headset-button-threshold-microvolt", + button_threshold, + ARRAY_SIZE(button_threshold)); + if (ret) { + dev_err(dev, "Failed to get headset button detection threshold\n"); + return ret; + } + + if (button_threshold[0] > button_threshold[1] || + button_threshold[1] > button_threshold[2]) { + dev_err(dev, "Invalid headset button detection threshold value\n"); + return -EINVAL; + } + + for (i = 0; i < 3; i++) { + if (i != 0 && button_threshold[i] <= 0) { + dev_err(dev, "Invalid headset button detection threshold value\n"); + return -EINVAL; + } + + headset_key_zones[i].min_mv = button_threshold[i]; + + if (i == 2) + headset_key_zones[i].max_mv = UINT_MAX; + else + headset_key_zones[i].max_mv = \ + (button_threshold[i+1] - 1); + } + } + ret = snd_soc_of_parse_card_name(card, "model"); if (ret < 0) { dev_err(dev, "Card name is not specified\n");
Since we're already using it in the newly-added GPIO requests for jack detection, extend it to the previous checks as well.
Signed-off-by: Artur Weber aweber.kernel@gmail.com --- Changes in v2: - Added this commit --- sound/soc/samsung/midas_wm1811.c | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-)
diff --git a/sound/soc/samsung/midas_wm1811.c b/sound/soc/samsung/midas_wm1811.c index ce94550ee32e..91f4be98723c 100644 --- a/sound/soc/samsung/midas_wm1811.c +++ b/sound/soc/samsung/midas_wm1811.c @@ -646,16 +646,14 @@ static int midas_probe(struct platform_device *pdev) card->dev = dev;
priv->reg_mic_bias = devm_regulator_get(dev, "mic-bias"); - if (IS_ERR(priv->reg_mic_bias)) { - dev_err(dev, "Failed to get mic bias regulator\n"); - return PTR_ERR(priv->reg_mic_bias); - } + if (IS_ERR(priv->reg_mic_bias)) + return dev_err_probe(dev, PTR_ERR(priv->reg_mic_bias), + "Failed to get mic bias regulator\n");
priv->reg_submic_bias = devm_regulator_get(dev, "submic-bias"); - if (IS_ERR(priv->reg_submic_bias)) { - dev_err(dev, "Failed to get submic bias regulator\n"); - return PTR_ERR(priv->reg_submic_bias); - } + if (IS_ERR(priv->reg_submic_bias)) + return dev_err_probe(dev, PTR_ERR(priv->reg_submic_bias), + "Failed to get submic bias regulator\n");
priv->reg_headset_mic_bias = devm_regulator_get_optional(dev, "headset-mic-bias"); @@ -669,17 +667,15 @@ static int midas_probe(struct platform_device *pdev) }
priv->gpio_fm_sel = devm_gpiod_get_optional(dev, "fm-sel", GPIOD_OUT_HIGH); - if (IS_ERR(priv->gpio_fm_sel)) { - dev_err(dev, "Failed to get FM selection GPIO\n"); - return PTR_ERR(priv->gpio_fm_sel); - } + if (IS_ERR(priv->gpio_fm_sel)) + return dev_err_probe(dev, PTR_ERR(priv->gpio_fm_sel), + "Failed to get FM selection GPIO\n");
priv->gpio_lineout_sel = devm_gpiod_get_optional(dev, "lineout-sel", GPIOD_OUT_HIGH); - if (IS_ERR(priv->gpio_lineout_sel)) { - dev_err(dev, "Failed to get line out selection GPIO\n"); - return PTR_ERR(priv->gpio_lineout_sel); - } + if (IS_ERR(priv->gpio_lineout_sel)) + return dev_err_probe(dev, PTR_ERR(priv->gpio_lineout_sel), + "Failed to get line out selection GPIO\n");
priv->gpio_headset_detect = devm_gpiod_get_optional(dev, "headset-detect", GPIOD_IN);
Set up headset mic bias regulator and add the necessary properties to the samsung,midas-audio node to allow for headset jack detection.
Signed-off-by: Artur Weber aweber.kernel@gmail.com --- Changes in v2: - Added headset mic bias regulator - Added samsung prefix to threshold properties - Dropped wm1811 config changes --- arch/arm/boot/dts/samsung/exynos4212-tab3.dtsi | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+)
diff --git a/arch/arm/boot/dts/samsung/exynos4212-tab3.dtsi b/arch/arm/boot/dts/samsung/exynos4212-tab3.dtsi index e5254e32aa8f..8dc81112172c 100644 --- a/arch/arm/boot/dts/samsung/exynos4212-tab3.dtsi +++ b/arch/arm/boot/dts/samsung/exynos4212-tab3.dtsi @@ -294,11 +294,30 @@ submic_bias_reg: voltage-regulator-5 { regulator-max-microvolt = <2800000>; };
+ earmic_bias_reg: voltage-regulator-6 { + compatible = "regulator-fixed"; + regulator-name = "EAR_MICBIAS_LDO_2.8V"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + gpio = <&gpm0 0 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + sound: sound { compatible = "samsung,midas-audio"; model = "TAB3"; mic-bias-supply = <&mic_bias_reg>; submic-bias-supply = <&submic_bias_reg>; + headset-mic-bias-supply = <&earmic_bias_reg>; + + lineout-sel-gpios = <&gpj1 2 GPIO_ACTIVE_HIGH>; + + headset-detect-gpios = <&gpx0 4 GPIO_ACTIVE_LOW>; + headset-key-gpios = <&gpx3 6 GPIO_ACTIVE_LOW>; + samsung,headset-4pole-threshold-microvolt = <710 2000>; + samsung,headset-button-threshold-microvolt = <0 130 260>; + io-channel-names = "headset-detect"; + io-channels = <&adc 0>;
audio-routing = "HP", "HPOUT1L", "HP", "HPOUT1R", @@ -345,6 +364,11 @@ wlan_pwrseq: sdhci3-pwrseq { }; };
+&adc { + vdd-supply = <&ldo3_reg>; + status = "okay"; +}; + &bus_acp { devfreq = <&bus_dmc>; status = "okay";
Drop incorrect interrupt parent and add MCLK2 clock.
Signed-off-by: Artur Weber aweber.kernel@gmail.com --- Changes in v2: - Split out wm1811 changes from midas-audio config change patch --- arch/arm/boot/dts/samsung/exynos4212-tab3.dtsi | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/arch/arm/boot/dts/samsung/exynos4212-tab3.dtsi b/arch/arm/boot/dts/samsung/exynos4212-tab3.dtsi index 8dc81112172c..20e5e7ba6b92 100644 --- a/arch/arm/boot/dts/samsung/exynos4212-tab3.dtsi +++ b/arch/arm/boot/dts/samsung/exynos4212-tab3.dtsi @@ -529,12 +529,11 @@ &i2c_4 { wm1811: audio-codec@1a { compatible = "wlf,wm1811"; reg = <0x1a>; - clocks = <&pmu_system_controller 0>; - clock-names = "MCLK1"; + clocks = <&pmu_system_controller 0>, + <&s5m8767_osc S2MPS11_CLK_BT>; + clock-names = "MCLK1", "MCLK2"; interrupt-controller; #interrupt-cells = <2>; - interrupt-parent = <&gpx3>; - interrupts = <6 IRQ_TYPE_LEVEL_HIGH>;
gpio-controller; #gpio-cells = <2>;
On 08/05/2024 12:58, Artur Weber wrote:
Drop incorrect interrupt parent and add MCLK2 clock.
1. Separate patches. 2. Missing explanation why. "Incorrect" says a bit, but not too much. Also, imprecise - you remove all interrupts, not just incorrect parent.
Please provide proper rationale, why this is not correct and information that bluetooth 32 kHz clock feeds both bluetooth module and audio codec.
Best regards, Krzysztof
participants (3)
-
Artur Weber
-
Krzysztof Kozlowski
-
Rob Herring (Arm)