diff options
Diffstat (limited to 'sound/soc/codecs/wcd938x.c')
-rw-r--r-- | sound/soc/codecs/wcd938x.c | 131 |
1 files changed, 71 insertions, 60 deletions
diff --git a/sound/soc/codecs/wcd938x.c b/sound/soc/codecs/wcd938x.c index 1ae498c32391..711f373ece24 100644 --- a/sound/soc/codecs/wcd938x.c +++ b/sound/soc/codecs/wcd938x.c @@ -11,7 +11,6 @@ #include <linux/pm_runtime.h> #include <linux/component.h> #include <sound/tlv.h> -#include <linux/of_gpio.h> #include <linux/of.h> #include <sound/jack.h> #include <sound/pcm.h> @@ -19,14 +18,17 @@ #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" #include "wcd-mbhc-v2.h" #include "wcd938x.h" +#define CHIPID_WCD9380 0x0 +#define CHIPID_WCD9385 0x5 + #define WCD938X_MAX_MICBIAS (4) -#define WCD938X_MAX_SUPPLY (4) #define WCD938X_MBHC_MAX_BUTTONS (8) #define TX_ADC_MAX (4) @@ -74,11 +76,6 @@ wcd938x_ear_pa_put_gain, tlv_array) enum { - WCD9380 = 0, - WCD9385 = 5, -}; - -enum { /* INTR_CTRL_INT_MASK_0 */ WCD938X_IRQ_MBHC_BUTTON_PRESS_DET = 0, WCD938X_IRQ_MBHC_BUTTON_RELEASE_DET, @@ -159,9 +156,7 @@ struct wcd938x_priv { struct wcd_mbhc_intr intr_ids; struct wcd_clsh_ctrl *clsh_info; struct irq_domain *virq; - struct regmap_irq_chip *wcd_regmap_irq_chip; struct regmap_irq_chip_data *irq_chip; - struct regulator_bulk_data supplies[WCD938X_MAX_SUPPLY]; struct snd_soc_jack *jack; unsigned long status_mask; s32 micb_ref[WCD938X_MAX_MICBIAS]; @@ -170,9 +165,10 @@ struct wcd938x_priv { u32 tx_mode[TX_ADC_MAX]; int flyback_cur_det_disable; int ear_rx_path; - int variant; - int reset_gpio; + 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; @@ -183,6 +179,11 @@ struct wcd938x_priv { bool comp1_enable; bool comp2_enable; bool ldoh; + bool mux_setup_done; +}; + +static const char * const wcd938x_supplies[] = { + "vdd-rxtx", "vdd-io", "vdd-buck", "vdd-mic-bias", }; static const SNDRV_CTL_TLVD_DECLARE_DB_MINMAX(ear_pa_gain, 600, -1800); @@ -272,7 +273,7 @@ static const struct regmap_irq wcd938x_irqs[WCD938X_NUM_IRQS] = { REGMAP_IRQ_REG(WCD938X_IRQ_HPHR_SURGE_DET_INT, 2, 0x08), }; -static struct regmap_irq_chip wcd938x_regmap_irq_chip = { +static const struct regmap_irq_chip wcd938x_regmap_irq_chip = { .name = "wcd938x", .irqs = wcd938x_irqs, .num_irqs = ARRAY_SIZE(wcd938x_irqs), @@ -3043,6 +3044,7 @@ static int wcd938x_soc_codec_probe(struct snd_soc_component *component) struct sdw_slave *tx_sdw_dev = wcd938x->tx_sdw_dev; struct device *dev = component->dev; unsigned long time_left; + unsigned int variant; int ret, i; time_left = wait_for_completion_timeout(&tx_sdw_dev->initialization_complete, @@ -3058,9 +3060,9 @@ static int wcd938x_soc_codec_probe(struct snd_soc_component *component) if (ret < 0) return ret; - wcd938x->variant = snd_soc_component_read_field(component, - WCD938X_DIGITAL_EFUSE_REG_0, - WCD938X_ID_MASK); + variant = snd_soc_component_read_field(component, + WCD938X_DIGITAL_EFUSE_REG_0, + WCD938X_ID_MASK); wcd938x->clsh_info = wcd_clsh_ctrl_alloc(component, WCD938X); if (IS_ERR(wcd938x->clsh_info)) { @@ -3114,24 +3116,24 @@ static int wcd938x_soc_codec_probe(struct snd_soc_component *component) disable_irq_nosync(wcd938x->hphl_pdm_wd_int); disable_irq_nosync(wcd938x->aux_pdm_wd_int); - switch (wcd938x->variant) { - case WCD9380: + switch (variant) { + case CHIPID_WCD9380: ret = snd_soc_add_component_controls(component, wcd9380_snd_controls, ARRAY_SIZE(wcd9380_snd_controls)); if (ret < 0) { dev_err(component->dev, "%s: Failed to add snd ctrls for variant: %d\n", - __func__, wcd938x->variant); + __func__, variant); goto err_free_aux_pdm_wd_int; } break; - case WCD9385: + case CHIPID_WCD9385: ret = snd_soc_add_component_controls(component, wcd9385_snd_controls, ARRAY_SIZE(wcd9385_snd_controls)); if (ret < 0) { dev_err(component->dev, "%s: Failed to add snd ctrls for variant: %d\n", - __func__, wcd938x->variant); + __func__, variant); goto err_free_aux_pdm_wd_int; } break; @@ -3230,17 +3232,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; + struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component); + struct device *dev = component->dev; + int ret; - wcd938x = snd_soc_component_get_drvdata(component); + if (wcd938x->us_euro_mux) { + if (wcd938x->mux_setup_done) + mux_control_deselect(wcd938x->us_euro_mux); - value = gpiod_get_value(wcd938x->us_euro_gpio); + 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); + } - gpiod_set_value(wcd938x->us_euro_gpio, !value); + wcd938x->mux_state = !wcd938x->mux_state; return true; } @@ -3251,33 +3264,37 @@ static int wcd938x_populate_dt_data(struct wcd938x_priv *wcd938x, struct device struct wcd_mbhc_config *cfg = &wcd938x->mbhc_cfg; int ret; - wcd938x->reset_gpio = of_get_named_gpio(dev->of_node, "reset-gpios", 0); - if (wcd938x->reset_gpio < 0) - return dev_err_probe(dev, wcd938x->reset_gpio, + wcd938x->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); + if (IS_ERR(wcd938x->reset_gpio)) + 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"); + if (of_property_present(dev->of_node, "mux-controls")) { + wcd938x->us_euro_mux = devm_mux_control_get(dev, NULL); + if (IS_ERR(wcd938x->us_euro_mux)) { + ret = PTR_ERR(wcd938x->us_euro_mux); + return dev_err_probe(dev, ret, "failed to get mux control\n"); + } - cfg->swap_gnd_mic = wcd938x_swap_gnd_mic; + 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); + return ret; + } + wcd938x->mux_setup_done = true; + } else { + 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->supplies[0].supply = "vdd-rxtx"; - wcd938x->supplies[1].supply = "vdd-io"; - wcd938x->supplies[2].supply = "vdd-buck"; - wcd938x->supplies[3].supply = "vdd-mic-bias"; + cfg->swap_gnd_mic = wcd938x_swap_gnd_mic; - ret = regulator_bulk_get(dev, WCD938X_MAX_SUPPLY, wcd938x->supplies); + ret = devm_regulator_bulk_get_enable(dev, ARRAY_SIZE(wcd938x_supplies), + wcd938x_supplies); if (ret) - return dev_err_probe(dev, ret, "Failed to get supplies\n"); - - ret = regulator_bulk_enable(WCD938X_MAX_SUPPLY, wcd938x->supplies); - if (ret) { - regulator_bulk_free(WCD938X_MAX_SUPPLY, wcd938x->supplies); - return dev_err_probe(dev, ret, "Failed to enable supplies\n"); - } + return dev_err_probe(dev, ret, "Failed to get and enable supplies\n"); wcd938x_dt_parse_micbias_info(dev, wcd938x); @@ -3297,10 +3314,10 @@ static int wcd938x_populate_dt_data(struct wcd938x_priv *wcd938x, struct device static int wcd938x_reset(struct wcd938x_priv *wcd938x) { - gpio_direction_output(wcd938x->reset_gpio, 0); + gpiod_set_value(wcd938x->reset_gpio, 1); /* 20us sleep required after pulling the reset gpio to LOW */ usleep_range(20, 30); - gpio_set_value(wcd938x->reset_gpio, 1); + gpiod_set_value(wcd938x->reset_gpio, 0); /* 20us sleep required after pulling the reset gpio to HIGH */ usleep_range(20, 30); @@ -3541,13 +3558,13 @@ static int wcd938x_probe(struct platform_device *pdev) ret = wcd938x_add_slave_components(wcd938x, dev, &match); if (ret) - goto err_disable_regulators; + return ret; wcd938x_reset(wcd938x); ret = component_master_add_with_match(dev, &wcd938x_comp_ops, match); if (ret) - goto err_disable_regulators; + return ret; pm_runtime_set_autosuspend_delay(dev, 1000); pm_runtime_use_autosuspend(dev); @@ -3557,12 +3574,6 @@ static int wcd938x_probe(struct platform_device *pdev) pm_runtime_idle(dev); return 0; - -err_disable_regulators: - regulator_bulk_disable(WCD938X_MAX_SUPPLY, wcd938x->supplies); - regulator_bulk_free(WCD938X_MAX_SUPPLY, wcd938x->supplies); - - return ret; } static void wcd938x_remove(struct platform_device *pdev) @@ -3576,8 +3587,8 @@ static void wcd938x_remove(struct platform_device *pdev) pm_runtime_set_suspended(dev); pm_runtime_dont_use_autosuspend(dev); - regulator_bulk_disable(WCD938X_MAX_SUPPLY, wcd938x->supplies); - regulator_bulk_free(WCD938X_MAX_SUPPLY, wcd938x->supplies); + if (wcd938x->us_euro_mux && wcd938x->mux_setup_done) + mux_control_deselect(wcd938x->us_euro_mux); } #if defined(CONFIG_OF) |