mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-10 15:13:44 -04:00
ASoC: wcd938x: enable t14s audio headset
Merge series from srinivas.kandagatla@linaro.org: On Lenovo ThinkPad T14s, the headset is connected via a HiFi Switch to support CTIA and OMTP headsets. This switch is used to minimise pop and click during headset type switching. This patchset adds required bindings and changes to codec and dts to tnable the regulator required to power this switch along with wiring up gpio that control the headset switching. Without this patchset, there will be lots of noise on headset and mic will not we functional.
This commit is contained in:
@@ -23,9 +23,15 @@ properties:
|
||||
- qcom,wcd9380-codec
|
||||
- qcom,wcd9385-codec
|
||||
|
||||
mux-controls:
|
||||
description: A reference to the audio mux switch for
|
||||
switching CTIA/OMTP Headset types
|
||||
maxItems: 1
|
||||
|
||||
us-euro-gpios:
|
||||
description: GPIO spec for swapping gnd and mic segments
|
||||
maxItems: 1
|
||||
deprecated: true
|
||||
|
||||
required:
|
||||
- compatible
|
||||
|
||||
@@ -2239,6 +2239,7 @@ config SND_SOC_WCD938X
|
||||
tristate
|
||||
depends on SOUNDWIRE || !SOUNDWIRE
|
||||
select SND_SOC_WCD_CLASSH
|
||||
select MULTIPLEXER
|
||||
|
||||
config SND_SOC_WCD938X_SDW
|
||||
tristate "WCD9380/WCD9385 Codec - SDW"
|
||||
|
||||
@@ -1260,7 +1260,7 @@ static void wcd_correct_swch_plug(struct work_struct *work)
|
||||
if (pt_gnd_mic_swap_cnt == mbhc->swap_thr) {
|
||||
/* US_EU gpio present, flip switch */
|
||||
if (mbhc->cfg->swap_gnd_mic) {
|
||||
if (mbhc->cfg->swap_gnd_mic(component, true))
|
||||
if (mbhc->cfg->swap_gnd_mic(component))
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -194,7 +194,7 @@ struct wcd_mbhc_config {
|
||||
int num_btn;
|
||||
bool mono_stero_detection;
|
||||
bool typec_analog_mux;
|
||||
bool (*swap_gnd_mic)(struct snd_soc_component *component, bool active);
|
||||
bool (*swap_gnd_mic)(struct snd_soc_component *component);
|
||||
bool hs_ext_micbias;
|
||||
bool gnd_det_en;
|
||||
uint32_t linein_th;
|
||||
|
||||
@@ -2656,7 +2656,7 @@ static void wcd937x_dt_parse_micbias_info(struct device *dev, struct wcd937x_pri
|
||||
dev_warn(dev, "Micbias3 DT property not found\n");
|
||||
}
|
||||
|
||||
static bool wcd937x_swap_gnd_mic(struct snd_soc_component *component, bool active)
|
||||
static bool wcd937x_swap_gnd_mic(struct snd_soc_component *component)
|
||||
{
|
||||
int value;
|
||||
struct wcd937x_priv *wcd937x;
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include <linux/regmap.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/soc-dapm.h>
|
||||
#include <linux/mux/consumer.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
|
||||
#include "wcd-clsh-v2.h"
|
||||
@@ -172,6 +173,8 @@ struct wcd938x_priv {
|
||||
int variant;
|
||||
struct gpio_desc *reset_gpio;
|
||||
struct gpio_desc *us_euro_gpio;
|
||||
struct mux_control *us_euro_mux;
|
||||
unsigned int mux_state;
|
||||
u32 micb1_mv;
|
||||
u32 micb2_mv;
|
||||
u32 micb3_mv;
|
||||
@@ -182,6 +185,7 @@ struct wcd938x_priv {
|
||||
bool comp1_enable;
|
||||
bool comp2_enable;
|
||||
bool ldoh;
|
||||
bool mux_setup_done;
|
||||
};
|
||||
|
||||
static const SNDRV_CTL_TLVD_DECLARE_DB_MINMAX(ear_pa_gain, 600, -1800);
|
||||
@@ -3229,17 +3233,28 @@ static void wcd938x_dt_parse_micbias_info(struct device *dev, struct wcd938x_pri
|
||||
dev_info(dev, "%s: Micbias4 DT property not found\n", __func__);
|
||||
}
|
||||
|
||||
static bool wcd938x_swap_gnd_mic(struct snd_soc_component *component, bool active)
|
||||
static bool wcd938x_swap_gnd_mic(struct snd_soc_component *component)
|
||||
{
|
||||
int value;
|
||||
struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
|
||||
struct device *dev = component->dev;
|
||||
int ret;
|
||||
|
||||
struct wcd938x_priv *wcd938x;
|
||||
if (wcd938x->us_euro_mux) {
|
||||
if (wcd938x->mux_setup_done)
|
||||
mux_control_deselect(wcd938x->us_euro_mux);
|
||||
|
||||
wcd938x = snd_soc_component_get_drvdata(component);
|
||||
ret = mux_control_try_select(wcd938x->us_euro_mux, !wcd938x->mux_state);
|
||||
if (ret) {
|
||||
dev_err(dev, "Error (%d) Unable to select us/euro mux state\n", ret);
|
||||
wcd938x->mux_setup_done = false;
|
||||
return false;
|
||||
}
|
||||
wcd938x->mux_setup_done = true;
|
||||
} else {
|
||||
gpiod_set_value(wcd938x->us_euro_gpio, !wcd938x->mux_state);
|
||||
}
|
||||
|
||||
value = gpiod_get_value(wcd938x->us_euro_gpio);
|
||||
|
||||
gpiod_set_value(wcd938x->us_euro_gpio, !value);
|
||||
wcd938x->mux_state = !wcd938x->mux_state;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -3255,11 +3270,26 @@ static int wcd938x_populate_dt_data(struct wcd938x_priv *wcd938x, struct device
|
||||
return dev_err_probe(dev, PTR_ERR(wcd938x->reset_gpio),
|
||||
"Failed to get reset gpio\n");
|
||||
|
||||
wcd938x->us_euro_gpio = devm_gpiod_get_optional(dev, "us-euro",
|
||||
GPIOD_OUT_LOW);
|
||||
if (IS_ERR(wcd938x->us_euro_gpio))
|
||||
return dev_err_probe(dev, PTR_ERR(wcd938x->us_euro_gpio),
|
||||
"us-euro swap Control GPIO not found\n");
|
||||
wcd938x->us_euro_mux = devm_mux_control_get(dev, NULL);
|
||||
if (IS_ERR(wcd938x->us_euro_mux)) {
|
||||
if (PTR_ERR(wcd938x->us_euro_mux) == -EPROBE_DEFER)
|
||||
return -EPROBE_DEFER;
|
||||
|
||||
/* mux is optional and now fallback to using gpio */
|
||||
wcd938x->us_euro_mux = NULL;
|
||||
wcd938x->us_euro_gpio = devm_gpiod_get_optional(dev, "us-euro", GPIOD_OUT_LOW);
|
||||
if (IS_ERR(wcd938x->us_euro_gpio))
|
||||
return dev_err_probe(dev, PTR_ERR(wcd938x->us_euro_gpio),
|
||||
"us-euro swap Control GPIO not found\n");
|
||||
} else {
|
||||
ret = mux_control_try_select(wcd938x->us_euro_mux, wcd938x->mux_state);
|
||||
if (ret) {
|
||||
dev_err(dev, "Error (%d) Unable to select us/euro mux state\n", ret);
|
||||
wcd938x->mux_setup_done = false;
|
||||
return ret;
|
||||
}
|
||||
wcd938x->mux_setup_done = true;
|
||||
}
|
||||
|
||||
cfg->swap_gnd_mic = wcd938x_swap_gnd_mic;
|
||||
|
||||
@@ -3575,6 +3605,9 @@ static void wcd938x_remove(struct platform_device *pdev)
|
||||
pm_runtime_set_suspended(dev);
|
||||
pm_runtime_dont_use_autosuspend(dev);
|
||||
|
||||
if (wcd938x->us_euro_mux && wcd938x->mux_setup_done)
|
||||
mux_control_deselect(wcd938x->us_euro_mux);
|
||||
|
||||
regulator_bulk_disable(WCD938X_MAX_SUPPLY, wcd938x->supplies);
|
||||
regulator_bulk_free(WCD938X_MAX_SUPPLY, wcd938x->supplies);
|
||||
}
|
||||
|
||||
@@ -3214,7 +3214,7 @@ static void wcd939x_dt_parse_micbias_info(struct device *dev, struct wcd939x_pri
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_TYPEC)
|
||||
static bool wcd939x_swap_gnd_mic(struct snd_soc_component *component, bool active)
|
||||
static bool wcd939x_swap_gnd_mic(struct snd_soc_component *component)
|
||||
{
|
||||
struct wcd939x_priv *wcd939x = snd_soc_component_get_drvdata(component);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user