diff options
Diffstat (limited to 'sound/soc/codecs/wcd937x.c')
-rw-r--r-- | sound/soc/codecs/wcd937x.c | 102 |
1 files changed, 66 insertions, 36 deletions
diff --git a/sound/soc/codecs/wcd937x.c b/sound/soc/codecs/wcd937x.c index c9d5e67bf66e..3b0a8cc314e0 100644 --- a/sound/soc/codecs/wcd937x.c +++ b/sound/soc/codecs/wcd937x.c @@ -24,10 +24,8 @@ #include "wcd-mbhc-v2.h" #include "wcd937x.h" -enum { - CHIPID_WCD9370 = 0, - CHIPID_WCD9375 = 5, -}; +#define CHIPID_WCD9370 0x0 +#define CHIPID_WCD9375 0x5 /* Z value defined in milliohm */ #define WCD937X_ZDET_VAL_32 (32000) @@ -88,10 +86,7 @@ struct wcd937x_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[WCD937X_MAX_BULK_SUPPLY]; - struct regulator *buck_supply; struct snd_soc_jack *jack; unsigned long status_mask; s32 micb_ref[WCD937X_MAX_MICBIAS]; @@ -114,6 +109,10 @@ struct wcd937x_priv { atomic_t ana_clk_count; }; +static const char * const wcd937x_supplies[] = { + "vdd-rxtx", "vdd-px", "vdd-mic-bias", "vdd-buck", +}; + static const SNDRV_CTL_TLVD_DECLARE_DB_MINMAX(ear_pa_gain, 600, -1800); static const DECLARE_TLV_DB_SCALE(line_gain, 0, 7, 1); static const DECLARE_TLV_DB_SCALE(analog_gain, 0, 25, 1); @@ -1197,13 +1196,21 @@ static int wcd937x_connect_port(struct wcd937x_sdw_priv *wcd, u8 port_idx, u8 ch const struct wcd937x_sdw_ch_info *ch_info = &wcd->ch_info[ch_id]; u8 port_num = ch_info->port_num; u8 ch_mask = ch_info->ch_mask; + u8 mstr_port_num, mstr_ch_mask; + struct sdw_slave *sdev = wcd->sdev; port_config->num = port_num; - if (enable) + mstr_port_num = sdev->m_port_map[port_num]; + mstr_ch_mask = ch_info->master_ch_mask; + + if (enable) { port_config->ch_mask |= ch_mask; - else + wcd->master_channel_map[mstr_port_num] |= mstr_ch_mask; + } else { port_config->ch_mask &= ~ch_mask; + wcd->master_channel_map[mstr_port_num] &= ~mstr_ch_mask; + } return 0; } @@ -2472,7 +2479,7 @@ static const struct irq_domain_ops wcd_domain_ops = { static int wcd937x_irq_init(struct wcd937x_priv *wcd, struct device *dev) { - wcd->virq = irq_domain_add_linear(NULL, 1, &wcd_domain_ops, NULL); + wcd->virq = irq_domain_create_linear(NULL, 1, &wcd_domain_ops, NULL); if (!(wcd->virq)) { dev_err(dev, "%s: Failed to add IRQ domain\n", __func__); return -EINVAL; @@ -2563,6 +2570,7 @@ static int wcd937x_soc_codec_probe(struct snd_soc_component *component) ARRAY_SIZE(wcd9375_dapm_widgets)); if (ret < 0) { dev_err(component->dev, "Failed to add snd_ctls\n"); + wcd_clsh_ctrl_free(wcd937x->clsh_info); return ret; } @@ -2570,6 +2578,7 @@ static int wcd937x_soc_codec_probe(struct snd_soc_component *component) ARRAY_SIZE(wcd9375_audio_map)); if (ret < 0) { dev_err(component->dev, "Failed to add routes\n"); + wcd_clsh_ctrl_free(wcd937x->clsh_info); return ret; } } @@ -2646,7 +2655,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; @@ -2689,10 +2698,51 @@ static int wcd937x_codec_set_sdw_stream(struct snd_soc_dai *dai, return 0; } +static int wcd937x_get_channel_map(const struct snd_soc_dai *dai, + unsigned int *tx_num, unsigned int *tx_slot, + unsigned int *rx_num, unsigned int *rx_slot) +{ + struct wcd937x_priv *wcd937x = dev_get_drvdata(dai->dev); + struct wcd937x_sdw_priv *wcd = wcd937x->sdw_priv[dai->id]; + int i; + + switch (dai->id) { + case AIF1_PB: + if (!rx_slot || !rx_num) { + dev_err(dai->dev, "Invalid rx_slot %p or rx_num %p\n", + rx_slot, rx_num); + return -EINVAL; + } + + for (i = 0; i < SDW_MAX_PORTS; i++) + rx_slot[i] = wcd->master_channel_map[i]; + + *rx_num = i; + break; + case AIF1_CAP: + if (!tx_slot || !tx_num) { + dev_err(dai->dev, "Invalid tx_slot %p or tx_num %p\n", + tx_slot, tx_num); + return -EINVAL; + } + + for (i = 0; i < SDW_MAX_PORTS; i++) + tx_slot[i] = wcd->master_channel_map[i]; + + *tx_num = i; + break; + default: + break; + } + + return 0; +} + static const struct snd_soc_dai_ops wcd937x_sdw_dai_ops = { .hw_params = wcd937x_codec_hw_params, .hw_free = wcd937x_codec_free, .set_stream = wcd937x_codec_set_sdw_stream, + .get_channel_map = wcd937x_get_channel_map, }; static struct snd_soc_dai_driver wcd937x_dais[] = { @@ -2884,20 +2934,10 @@ static int wcd937x_probe(struct platform_device *pdev) cfg = &wcd937x->mbhc_cfg; cfg->swap_gnd_mic = wcd937x_swap_gnd_mic; - wcd937x->supplies[0].supply = "vdd-rxtx"; - wcd937x->supplies[1].supply = "vdd-px"; - wcd937x->supplies[2].supply = "vdd-mic-bias"; - wcd937x->supplies[3].supply = "vdd-buck"; - - ret = devm_regulator_bulk_get(dev, WCD937X_MAX_BULK_SUPPLY, wcd937x->supplies); + ret = devm_regulator_bulk_get_enable(dev, ARRAY_SIZE(wcd937x_supplies), + wcd937x_supplies); if (ret) - return dev_err_probe(dev, ret, "Failed to get supplies\n"); - - ret = regulator_bulk_enable(WCD937X_MAX_BULK_SUPPLY, wcd937x->supplies); - if (ret) { - regulator_bulk_free(WCD937X_MAX_BULK_SUPPLY, wcd937x->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"); wcd937x_dt_parse_micbias_info(dev, wcd937x); @@ -2914,13 +2954,13 @@ static int wcd937x_probe(struct platform_device *pdev) ret = wcd937x_add_slave_components(wcd937x, dev, &match); if (ret) - goto err_disable_regulators; + return ret; wcd937x_reset(wcd937x); ret = component_master_add_with_match(dev, &wcd937x_comp_ops, match); if (ret) - goto err_disable_regulators; + return ret; pm_runtime_set_autosuspend_delay(dev, 1000); pm_runtime_use_autosuspend(dev); @@ -2930,27 +2970,17 @@ static int wcd937x_probe(struct platform_device *pdev) pm_runtime_idle(dev); return 0; - -err_disable_regulators: - regulator_bulk_disable(WCD937X_MAX_BULK_SUPPLY, wcd937x->supplies); - regulator_bulk_free(WCD937X_MAX_BULK_SUPPLY, wcd937x->supplies); - - return ret; } static void wcd937x_remove(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct wcd937x_priv *wcd937x = dev_get_drvdata(dev); component_master_del(&pdev->dev, &wcd937x_comp_ops); pm_runtime_disable(dev); pm_runtime_set_suspended(dev); pm_runtime_dont_use_autosuspend(dev); - - regulator_bulk_disable(WCD937X_MAX_BULK_SUPPLY, wcd937x->supplies); - regulator_bulk_free(WCD937X_MAX_BULK_SUPPLY, wcd937x->supplies); } #if defined(CONFIG_OF) |