diff options
Diffstat (limited to 'sound/soc/codecs/da7219.c')
| -rw-r--r-- | sound/soc/codecs/da7219.c | 668 |
1 files changed, 373 insertions, 295 deletions
diff --git a/sound/soc/codecs/da7219.c b/sound/soc/codecs/da7219.c index f83a6eaba12c..298a626df3ad 100644 --- a/sound/soc/codecs/da7219.c +++ b/sound/soc/codecs/da7219.c @@ -12,7 +12,7 @@ #include <linux/clkdev.h> #include <linux/clk-provider.h> #include <linux/i2c.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/property.h> #include <linux/regmap.h> #include <linux/slab.h> @@ -254,7 +254,7 @@ static const struct soc_enum da7219_cp_track_mode = static int da7219_volsw_locked_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); struct da7219_priv *da7219 = snd_soc_component_get_drvdata(component); int ret; @@ -268,7 +268,7 @@ static int da7219_volsw_locked_get(struct snd_kcontrol *kcontrol, static int da7219_volsw_locked_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); struct da7219_priv *da7219 = snd_soc_component_get_drvdata(component); int ret; @@ -282,7 +282,7 @@ static int da7219_volsw_locked_put(struct snd_kcontrol *kcontrol, static int da7219_enum_locked_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); struct da7219_priv *da7219 = snd_soc_component_get_drvdata(component); int ret; @@ -296,7 +296,7 @@ static int da7219_enum_locked_get(struct snd_kcontrol *kcontrol, static int da7219_enum_locked_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); struct da7219_priv *da7219 = snd_soc_component_get_drvdata(component); int ret; @@ -313,13 +313,13 @@ static void da7219_alc_calib(struct snd_soc_component *component) u8 mic_ctrl, mixin_ctrl, adc_ctrl, calib_ctrl; /* Save current state of mic control register */ - mic_ctrl = snd_soc_component_read32(component, DA7219_MIC_1_CTRL); + mic_ctrl = snd_soc_component_read(component, DA7219_MIC_1_CTRL); /* Save current state of input mixer control register */ - mixin_ctrl = snd_soc_component_read32(component, DA7219_MIXIN_L_CTRL); + mixin_ctrl = snd_soc_component_read(component, DA7219_MIXIN_L_CTRL); /* Save current state of input ADC control register */ - adc_ctrl = snd_soc_component_read32(component, DA7219_ADC_L_CTRL); + adc_ctrl = snd_soc_component_read(component, DA7219_ADC_L_CTRL); /* Enable then Mute MIC PGAs */ snd_soc_component_update_bits(component, DA7219_MIC_1_CTRL, DA7219_MIC_1_AMP_EN_MASK, @@ -344,7 +344,7 @@ static void da7219_alc_calib(struct snd_soc_component *component) DA7219_ALC_AUTO_CALIB_EN_MASK, DA7219_ALC_AUTO_CALIB_EN_MASK); do { - calib_ctrl = snd_soc_component_read32(component, DA7219_ALC_CTRL1); + calib_ctrl = snd_soc_component_read(component, DA7219_ALC_CTRL1); } while (calib_ctrl & DA7219_ALC_AUTO_CALIB_EN_MASK); /* If auto calibration fails, disable DC offset, hybrid ALC */ @@ -376,7 +376,7 @@ static void da7219_alc_calib(struct snd_soc_component *component) static int da7219_mixin_gain_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); struct da7219_priv *da7219 = snd_soc_component_get_drvdata(component); int ret; @@ -395,7 +395,7 @@ static int da7219_mixin_gain_put(struct snd_kcontrol *kcontrol, static int da7219_alc_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); struct da7219_priv *da7219 = snd_soc_component_get_drvdata(component); @@ -414,7 +414,7 @@ static int da7219_alc_sw_put(struct snd_kcontrol *kcontrol, static int da7219_tonegen_freq_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); struct da7219_priv *da7219 = snd_soc_component_get_drvdata(component); struct soc_mixer_control *mixer_ctrl = (struct soc_mixer_control *) kcontrol->private_value; @@ -441,12 +441,12 @@ static int da7219_tonegen_freq_get(struct snd_kcontrol *kcontrol, static int da7219_tonegen_freq_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); struct da7219_priv *da7219 = snd_soc_component_get_drvdata(component); struct soc_mixer_control *mixer_ctrl = (struct soc_mixer_control *) kcontrol->private_value; unsigned int reg = mixer_ctrl->reg; - __le16 val; + __le16 val_new, val_old; int ret; /* @@ -454,13 +454,19 @@ static int da7219_tonegen_freq_put(struct snd_kcontrol *kcontrol, * Therefore we need to convert to little endian here to align with * HW registers. */ - val = cpu_to_le16(ucontrol->value.integer.value[0]); + val_new = cpu_to_le16(ucontrol->value.integer.value[0]); mutex_lock(&da7219->ctrl_lock); - ret = regmap_raw_write(da7219->regmap, reg, &val, sizeof(val)); + ret = regmap_raw_read(da7219->regmap, reg, &val_old, sizeof(val_old)); + if (ret == 0 && (val_old != val_new)) + ret = regmap_raw_write(da7219->regmap, reg, + &val_new, sizeof(val_new)); mutex_unlock(&da7219->ctrl_lock); - return ret; + if (ret < 0) + return ret; + + return val_old != val_new; } @@ -822,13 +828,13 @@ static int da7219_dai_event(struct snd_soc_dapm_widget *w, DA7219_PC_FREERUN_MASK, 0); /* Slave mode, if SRM not enabled no need for status checks */ - pll_ctrl = snd_soc_component_read32(component, DA7219_PLL_CTRL); + pll_ctrl = snd_soc_component_read(component, DA7219_PLL_CTRL); if ((pll_ctrl & DA7219_PLL_MODE_MASK) != DA7219_PLL_MODE_SRM) return 0; /* Check SRM has locked */ do { - pll_status = snd_soc_component_read32(component, DA7219_PLL_SRM_STS); + pll_status = snd_soc_component_read(component, DA7219_PLL_SRM_STS); if (pll_status & DA7219_PLL_SRM_STS_SRM_LOCK) { srm_lock = true; } else { @@ -928,7 +934,7 @@ static int da7219_gain_ramp_event(struct snd_soc_dapm_widget *w, case SND_SOC_DAPM_PRE_PMD: /* Ensure nominal gain ramping for DAPM sequence */ da7219->gain_ramp_ctrl = - snd_soc_component_read32(component, DA7219_GAIN_RAMP_CTRL); + snd_soc_component_read(component, DA7219_GAIN_RAMP_CTRL); snd_soc_component_write(component, DA7219_GAIN_RAMP_CTRL, DA7219_GAIN_RAMP_RATE_NOMINAL); break; @@ -1161,17 +1167,20 @@ static int da7219_set_dai_sysclk(struct snd_soc_dai *codec_dai, struct da7219_priv *da7219 = snd_soc_component_get_drvdata(component); int ret = 0; - if ((da7219->clk_src == clk_id) && (da7219->mclk_rate == freq)) + mutex_lock(&da7219->pll_lock); + + if ((da7219->clk_src == clk_id) && (da7219->mclk_rate == freq)) { + mutex_unlock(&da7219->pll_lock); return 0; + } if ((freq < 2000000) || (freq > 54000000)) { + mutex_unlock(&da7219->pll_lock); dev_err(codec_dai->dev, "Unsupported MCLK value %d\n", freq); return -EINVAL; } - mutex_lock(&da7219->pll_lock); - switch (clk_id) { case DA7219_CLKSRC_MCLK_SQR: snd_soc_component_update_bits(component, DA7219_PLL_CTRL, @@ -1303,10 +1312,10 @@ static int da7219_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) u8 dai_clk_mode = 0, dai_ctrl = 0; switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: da7219->master = true; break; - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: da7219->master = false; break; default: @@ -1692,9 +1701,9 @@ static struct snd_soc_dai_driver da7219_dai = { .formats = DA7219_FORMATS, }, .ops = &da7219_dai_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, .symmetric_channels = 1, - .symmetric_samplebits = 1, + .symmetric_sample_bits = 1, }; @@ -1702,17 +1711,21 @@ static struct snd_soc_dai_driver da7219_dai = { * DT/ACPI */ +#ifdef CONFIG_OF static const struct of_device_id da7219_of_match[] = { { .compatible = "dlg,da7219", }, { } }; MODULE_DEVICE_TABLE(of, da7219_of_match); +#endif +#ifdef CONFIG_ACPI static const struct acpi_device_id da7219_acpi_match[] = { { .id = "DLGS7219", }, { } }; MODULE_DEVICE_TABLE(acpi, da7219_acpi_match); +#endif static enum da7219_micbias_voltage da7219_fw_micbias_lvl(struct device *dev, u32 val) @@ -1751,9 +1764,8 @@ static enum da7219_mic_amp_in_sel } } -static struct da7219_pdata *da7219_fw_to_pdata(struct snd_soc_component *component) +static struct da7219_pdata *da7219_fw_to_pdata(struct device *dev) { - struct device *dev = component->dev; struct da7219_pdata *pdata; const char *of_str; u32 of_val32; @@ -1795,6 +1807,7 @@ static int da7219_set_bias_level(struct snd_soc_component *component, enum snd_soc_bias_level level) { struct da7219_priv *da7219 = snd_soc_component_get_drvdata(component); + struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(component); int ret; switch (level) { @@ -1802,7 +1815,7 @@ static int da7219_set_bias_level(struct snd_soc_component *component, break; case SND_SOC_BIAS_PREPARE: /* Enable MCLK for transition to ON state */ - if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_STANDBY) { + if (snd_soc_dapm_get_bias_level(dapm) == SND_SOC_BIAS_STANDBY) { if (da7219->mclk) { ret = clk_prepare_enable(da7219->mclk); if (ret) { @@ -1815,13 +1828,13 @@ static int da7219_set_bias_level(struct snd_soc_component *component, break; case SND_SOC_BIAS_STANDBY: - if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF) + if (snd_soc_dapm_get_bias_level(dapm) == SND_SOC_BIAS_OFF) /* Master bias */ snd_soc_component_update_bits(component, DA7219_REFERENCES, DA7219_BIAS_EN_MASK, DA7219_BIAS_EN_MASK); - if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_PREPARE) { + if (snd_soc_dapm_get_bias_level(dapm) == SND_SOC_BIAS_PREPARE) { /* Remove MCLK */ if (da7219->mclk) clk_disable_unprepare(da7219->mclk); @@ -1845,45 +1858,43 @@ static const char *da7219_supply_names[DA7219_NUM_SUPPLIES] = { [DA7219_SUPPLY_VDDIO] = "VDDIO", }; -static int da7219_handle_supplies(struct snd_soc_component *component) +static int da7219_handle_supplies(struct snd_soc_component *component, + u8 *io_voltage_lvl) { struct da7219_priv *da7219 = snd_soc_component_get_drvdata(component); struct regulator *vddio; - u8 io_voltage_lvl = DA7219_IO_VOLTAGE_LEVEL_2_5V_3_6V; int i, ret; /* Get required supplies */ for (i = 0; i < DA7219_NUM_SUPPLIES; ++i) da7219->supplies[i].supply = da7219_supply_names[i]; - ret = devm_regulator_bulk_get(component->dev, DA7219_NUM_SUPPLIES, - da7219->supplies); + ret = regulator_bulk_get(component->dev, DA7219_NUM_SUPPLIES, + da7219->supplies); if (ret) { dev_err(component->dev, "Failed to get supplies"); return ret; } + /* Default to upper range */ + *io_voltage_lvl = DA7219_IO_VOLTAGE_LEVEL_2_5V_3_6V; + /* Determine VDDIO voltage provided */ vddio = da7219->supplies[DA7219_SUPPLY_VDDIO].consumer; ret = regulator_get_voltage(vddio); if (ret < 1200000) dev_warn(component->dev, "Invalid VDDIO voltage\n"); else if (ret < 2800000) - io_voltage_lvl = DA7219_IO_VOLTAGE_LEVEL_1_2V_2_8V; + *io_voltage_lvl = DA7219_IO_VOLTAGE_LEVEL_1_2V_2_8V; /* Enable main supplies */ ret = regulator_bulk_enable(DA7219_NUM_SUPPLIES, da7219->supplies); if (ret) { dev_err(component->dev, "Failed to enable supplies"); + regulator_bulk_free(DA7219_NUM_SUPPLIES, da7219->supplies); return ret; } - /* Ensure device in active mode */ - snd_soc_component_write(component, DA7219_SYSTEM_ACTIVE, DA7219_SYSTEM_ACTIVE_MASK); - - /* Update IO voltage level range */ - snd_soc_component_write(component, DA7219_IO_CTRL, io_voltage_lvl); - return 0; } @@ -1930,7 +1941,7 @@ static int da7219_wclk_is_prepared(struct clk_hw *hw) if (!da7219->master) return -EINVAL; - clk_reg = snd_soc_component_read32(component, DA7219_DAI_CLK_MODE); + clk_reg = snd_soc_component_read(component, DA7219_DAI_CLK_MODE); return !!(clk_reg & DA7219_DAI_CLK_EN_MASK); } @@ -1942,7 +1953,7 @@ static unsigned long da7219_wclk_recalc_rate(struct clk_hw *hw, container_of(hw, struct da7219_priv, dai_clks_hw[DA7219_DAI_WCLK_IDX]); struct snd_soc_component *component = da7219->component; - u8 fs = snd_soc_component_read32(component, DA7219_SR); + u8 fs = snd_soc_component_read(component, DA7219_SR); switch (fs & DA7219_SR_MASK) { case DA7219_SR_8000: @@ -1972,8 +1983,8 @@ static unsigned long da7219_wclk_recalc_rate(struct clk_hw *hw, } } -static long da7219_wclk_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *parent_rate) +static int da7219_wclk_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) { struct da7219_priv *da7219 = container_of(hw, struct da7219_priv, @@ -1982,28 +1993,30 @@ static long da7219_wclk_round_rate(struct clk_hw *hw, unsigned long rate, if (!da7219->master) return -EINVAL; - if (rate < 11025) - return 8000; - else if (rate < 12000) - return 11025; - else if (rate < 16000) - return 12000; - else if (rate < 22050) - return 16000; - else if (rate < 24000) - return 22050; - else if (rate < 32000) - return 24000; - else if (rate < 44100) - return 32000; - else if (rate < 48000) - return 44100; - else if (rate < 88200) - return 48000; - else if (rate < 96000) - return 88200; + if (req->rate < 11025) + req->rate = 8000; + else if (req->rate < 12000) + req->rate = 11025; + else if (req->rate < 16000) + req->rate = 12000; + else if (req->rate < 22050) + req->rate = 16000; + else if (req->rate < 24000) + req->rate = 22050; + else if (req->rate < 32000) + req->rate = 24000; + else if (req->rate < 44100) + req->rate = 32000; + else if (req->rate < 48000) + req->rate = 44100; + else if (req->rate < 88200) + req->rate = 48000; + else if (req->rate < 96000) + req->rate = 88200; else - return 96000; + req->rate = 96000; + + return 0; } static int da7219_wclk_set_rate(struct clk_hw *hw, unsigned long rate, @@ -2027,7 +2040,7 @@ static unsigned long da7219_bclk_recalc_rate(struct clk_hw *hw, container_of(hw, struct da7219_priv, dai_clks_hw[DA7219_DAI_BCLK_IDX]); struct snd_soc_component *component = da7219->component; - u8 bclks_per_wclk = snd_soc_component_read32(component, + u8 bclks_per_wclk = snd_soc_component_read(component, DA7219_DAI_CLK_MODE); switch (bclks_per_wclk & DA7219_DAI_BCLKS_PER_WCLK_MASK) { @@ -2060,15 +2073,15 @@ static unsigned long da7219_bclk_get_factor(unsigned long rate, return 256; } -static long da7219_bclk_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *parent_rate) +static int da7219_bclk_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) { struct da7219_priv *da7219 = container_of(hw, struct da7219_priv, dai_clks_hw[DA7219_DAI_BCLK_IDX]); unsigned long factor; - if (!*parent_rate || !da7219->master) + if (!req->best_parent_rate || !da7219->master) return -EINVAL; /* @@ -2078,9 +2091,11 @@ static long da7219_bclk_round_rate(struct clk_hw *hw, unsigned long rate, * parent WCLK rate set and find the appropriate multiplier of BCLK to * get the rounded down BCLK value. */ - factor = da7219_bclk_get_factor(rate, *parent_rate); + factor = da7219_bclk_get_factor(req->rate, req->best_parent_rate); - return *parent_rate * factor; + req->rate = req->best_parent_rate * factor; + + return 0; } static int da7219_bclk_set_rate(struct clk_hw *hw, unsigned long rate, @@ -2106,12 +2121,12 @@ static const struct clk_ops da7219_dai_clk_ops[DA7219_DAI_NUM_CLKS] = { .unprepare = da7219_wclk_unprepare, .is_prepared = da7219_wclk_is_prepared, .recalc_rate = da7219_wclk_recalc_rate, - .round_rate = da7219_wclk_round_rate, + .determine_rate = da7219_wclk_determine_rate, .set_rate = da7219_wclk_set_rate, }, [DA7219_DAI_BCLK_IDX] = { .recalc_rate = da7219_bclk_recalc_rate, - .round_rate = da7219_bclk_round_rate, + .determine_rate = da7219_bclk_determine_rate, .set_rate = da7219_bclk_set_rate, }, }; @@ -2119,14 +2134,26 @@ static const struct clk_ops da7219_dai_clk_ops[DA7219_DAI_NUM_CLKS] = { static int da7219_register_dai_clks(struct snd_soc_component *component) { struct device *dev = component->dev; + struct device_node *np = dev->of_node; struct da7219_priv *da7219 = snd_soc_component_get_drvdata(component); struct da7219_pdata *pdata = da7219->pdata; const char *parent_name; + struct clk_hw_onecell_data *clk_data; int i, ret; + /* For DT platforms allocate onecell data for clock registration */ + if (np) { + clk_data = kzalloc(struct_size(clk_data, hws, DA7219_DAI_NUM_CLKS), + GFP_KERNEL); + if (!clk_data) + return -ENOMEM; + + clk_data->num = DA7219_DAI_NUM_CLKS; + da7219->clk_hw_data = clk_data; + } + for (i = 0; i < DA7219_DAI_NUM_CLKS; ++i) { struct clk_init_data init = {}; - struct clk *dai_clk; struct clk_lookup *dai_clk_lookup; struct clk_hw *dai_clk_hw = &da7219->dai_clks_hw[i]; @@ -2162,23 +2189,22 @@ static int da7219_register_dai_clks(struct snd_soc_component *component) init.flags = CLK_GET_RATE_NOCACHE | CLK_SET_RATE_GATE; dai_clk_hw->init = &init; - dai_clk = devm_clk_register(dev, dai_clk_hw); - if (IS_ERR(dai_clk)) { - dev_warn(dev, "Failed to register %s: %ld\n", - init.name, PTR_ERR(dai_clk)); - ret = PTR_ERR(dai_clk); + ret = clk_hw_register(dev, dai_clk_hw); + if (ret) { + dev_warn(dev, "Failed to register %s: %d\n", init.name, + ret); goto err; } - da7219->dai_clks[i] = dai_clk; + da7219->dai_clks[i] = dai_clk_hw->clk; - /* If we're using DT, then register as provider accordingly */ - if (dev->of_node) { - devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, - dai_clk_hw); + /* For DT setup onecell data, otherwise create lookup */ + if (np) { + da7219->clk_hw_data->hws[i] = dai_clk_hw; } else { - dai_clk_lookup = clkdev_create(dai_clk, init.name, - "%s", dev_name(dev)); + dai_clk_lookup = clkdev_hw_create(dai_clk_hw, init.name, + "%s", dev_name(dev)); if (!dai_clk_lookup) { + clk_hw_unregister(dai_clk_hw); ret = -ENOMEM; goto err; } else { @@ -2187,21 +2213,58 @@ static int da7219_register_dai_clks(struct snd_soc_component *component) } } + /* If we're using DT, then register as provider accordingly */ + if (np) { + ret = of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get, + da7219->clk_hw_data); + if (ret) { + dev_err(dev, "Failed to register clock provider\n"); + goto err; + } + } + return 0; err: - do { + while (--i >= 0) { if (da7219->dai_clks_lookup[i]) clkdev_drop(da7219->dai_clks_lookup[i]); - } while (i-- > 0); + + clk_hw_unregister(&da7219->dai_clks_hw[i]); + } + + if (np) + kfree(da7219->clk_hw_data); return ret; } + +static void da7219_free_dai_clks(struct snd_soc_component *component) +{ + struct da7219_priv *da7219 = snd_soc_component_get_drvdata(component); + struct device_node *np = component->dev->of_node; + int i; + + if (np) + of_clk_del_provider(np); + + for (i = DA7219_DAI_NUM_CLKS - 1; i >= 0; --i) { + if (da7219->dai_clks_lookup[i]) + clkdev_drop(da7219->dai_clks_lookup[i]); + + clk_hw_unregister(&da7219->dai_clks_hw[i]); + } + + if (np) + kfree(da7219->clk_hw_data); +} #else static inline int da7219_register_dai_clks(struct snd_soc_component *component) { return 0; } + +static void da7219_free_dai_clks(struct snd_soc_component *component) {} #endif /* CONFIG_COMMON_CLK */ static void da7219_handle_pdata(struct snd_soc_component *component) @@ -2249,188 +2312,12 @@ static void da7219_handle_pdata(struct snd_soc_component *component) } } -static struct reg_sequence da7219_rev_aa_patch[] = { - { DA7219_REFERENCES, 0x08 }, -}; - -static int da7219_probe(struct snd_soc_component *component) -{ - struct da7219_priv *da7219 = snd_soc_component_get_drvdata(component); - unsigned int rev; - int ret; - - da7219->component = component; - mutex_init(&da7219->ctrl_lock); - mutex_init(&da7219->pll_lock); - - /* Regulator configuration */ - ret = da7219_handle_supplies(component); - if (ret) - return ret; - - ret = regmap_read(da7219->regmap, DA7219_CHIP_REVISION, &rev); - if (ret) { - dev_err(component->dev, "Failed to read chip revision: %d\n", ret); - goto err_disable_reg; - } - - switch (rev & DA7219_CHIP_MINOR_MASK) { - case 0: - ret = regmap_register_patch(da7219->regmap, da7219_rev_aa_patch, - ARRAY_SIZE(da7219_rev_aa_patch)); - if (ret) { - dev_err(component->dev, "Failed to register AA patch: %d\n", - ret); - goto err_disable_reg; - } - break; - default: - break; - } - - /* Handle DT/ACPI/Platform data */ - da7219->pdata = dev_get_platdata(component->dev); - if (!da7219->pdata) - da7219->pdata = da7219_fw_to_pdata(component); - - da7219_handle_pdata(component); - - /* Check if MCLK provided */ - da7219->mclk = devm_clk_get(component->dev, "mclk"); - if (IS_ERR(da7219->mclk)) { - if (PTR_ERR(da7219->mclk) != -ENOENT) { - ret = PTR_ERR(da7219->mclk); - goto err_disable_reg; - } else { - da7219->mclk = NULL; - } - } - - /* Register CCF DAI clock control */ - ret = da7219_register_dai_clks(component); - if (ret) - return ret; - - /* Default PC counter to free-running */ - snd_soc_component_update_bits(component, DA7219_PC_COUNT, DA7219_PC_FREERUN_MASK, - DA7219_PC_FREERUN_MASK); - - /* Default gain ramping */ - snd_soc_component_update_bits(component, DA7219_MIXIN_L_CTRL, - DA7219_MIXIN_L_AMP_RAMP_EN_MASK, - DA7219_MIXIN_L_AMP_RAMP_EN_MASK); - snd_soc_component_update_bits(component, DA7219_ADC_L_CTRL, DA7219_ADC_L_RAMP_EN_MASK, - DA7219_ADC_L_RAMP_EN_MASK); - snd_soc_component_update_bits(component, DA7219_DAC_L_CTRL, DA7219_DAC_L_RAMP_EN_MASK, - DA7219_DAC_L_RAMP_EN_MASK); - snd_soc_component_update_bits(component, DA7219_DAC_R_CTRL, DA7219_DAC_R_RAMP_EN_MASK, - DA7219_DAC_R_RAMP_EN_MASK); - snd_soc_component_update_bits(component, DA7219_HP_L_CTRL, - DA7219_HP_L_AMP_RAMP_EN_MASK, - DA7219_HP_L_AMP_RAMP_EN_MASK); - snd_soc_component_update_bits(component, DA7219_HP_R_CTRL, - DA7219_HP_R_AMP_RAMP_EN_MASK, - DA7219_HP_R_AMP_RAMP_EN_MASK); - - /* Default minimum gain on HP to avoid pops during DAPM sequencing */ - snd_soc_component_update_bits(component, DA7219_HP_L_CTRL, - DA7219_HP_L_AMP_MIN_GAIN_EN_MASK, - DA7219_HP_L_AMP_MIN_GAIN_EN_MASK); - snd_soc_component_update_bits(component, DA7219_HP_R_CTRL, - DA7219_HP_R_AMP_MIN_GAIN_EN_MASK, - DA7219_HP_R_AMP_MIN_GAIN_EN_MASK); - - /* Default infinite tone gen, start/stop by Kcontrol */ - snd_soc_component_write(component, DA7219_TONE_GEN_CYCLES, DA7219_BEEP_CYCLES_MASK); - - /* Initialise AAD block */ - ret = da7219_aad_init(component); - if (ret) - goto err_disable_reg; - - return 0; - -err_disable_reg: - regulator_bulk_disable(DA7219_NUM_SUPPLIES, da7219->supplies); - - return ret; -} - -static void da7219_remove(struct snd_soc_component *component) -{ - struct da7219_priv *da7219 = snd_soc_component_get_drvdata(component); -#ifdef CONFIG_COMMON_CLK - int i; -#endif - - da7219_aad_exit(component); - -#ifdef CONFIG_COMMON_CLK - for (i = DA7219_DAI_NUM_CLKS - 1; i >= 0; --i) { - if (da7219->dai_clks_lookup[i]) - clkdev_drop(da7219->dai_clks_lookup[i]); - } -#endif - - /* Supplies */ - regulator_bulk_disable(DA7219_NUM_SUPPLIES, da7219->supplies); -} - -#ifdef CONFIG_PM -static int da7219_suspend(struct snd_soc_component *component) -{ - struct da7219_priv *da7219 = snd_soc_component_get_drvdata(component); - - /* Suspend AAD if we're not a wake-up source */ - if (!da7219->wakeup_source) - da7219_aad_suspend(component); - - snd_soc_component_force_bias_level(component, SND_SOC_BIAS_OFF); - - return 0; -} - -static int da7219_resume(struct snd_soc_component *component) -{ - struct da7219_priv *da7219 = snd_soc_component_get_drvdata(component); - - snd_soc_component_force_bias_level(component, SND_SOC_BIAS_STANDBY); - - /* Resume AAD if previously suspended */ - if (!da7219->wakeup_source) - da7219_aad_resume(component); - - return 0; -} -#else -#define da7219_suspend NULL -#define da7219_resume NULL -#endif - -static const struct snd_soc_component_driver soc_component_dev_da7219 = { - .probe = da7219_probe, - .remove = da7219_remove, - .suspend = da7219_suspend, - .resume = da7219_resume, - .set_bias_level = da7219_set_bias_level, - .controls = da7219_snd_controls, - .num_controls = ARRAY_SIZE(da7219_snd_controls), - .dapm_widgets = da7219_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(da7219_dapm_widgets), - .dapm_routes = da7219_audio_map, - .num_dapm_routes = ARRAY_SIZE(da7219_audio_map), - .idle_bias_on = 1, - .use_pmdown_time = 1, - .endianness = 1, - .non_legacy_dai_naming = 1, -}; - /* * Regmap configs */ -static struct reg_default da7219_reg_defaults[] = { +static const struct reg_default da7219_reg_defaults[] = { { DA7219_MIC_1_SELECT, 0x00 }, { DA7219_CIF_TIMEOUT_CTRL, 0x01 }, { DA7219_SR_24_48, 0x00 }, @@ -2561,31 +2448,25 @@ static const struct regmap_config da7219_regmap_config = { .cache_type = REGCACHE_RBTREE, }; +static const struct reg_sequence da7219_rev_aa_patch[] = { + { DA7219_REFERENCES, 0x08 }, +}; -/* - * I2C layer - */ - -static int da7219_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) +static int da7219_probe(struct snd_soc_component *component) { - struct da7219_priv *da7219; - unsigned int system_active, system_status; + struct da7219_priv *da7219 = snd_soc_component_get_drvdata(component); + unsigned int system_active, system_status, rev; + u8 io_voltage_lvl; int i, ret; - da7219 = devm_kzalloc(&i2c->dev, sizeof(struct da7219_priv), - GFP_KERNEL); - if (!da7219) - return -ENOMEM; - - i2c_set_clientdata(i2c, da7219); + da7219->component = component; + mutex_init(&da7219->ctrl_lock); + mutex_init(&da7219->pll_lock); - da7219->regmap = devm_regmap_init_i2c(i2c, &da7219_regmap_config); - if (IS_ERR(da7219->regmap)) { - ret = PTR_ERR(da7219->regmap); - dev_err(&i2c->dev, "regmap_init() failed: %d\n", ret); + /* Regulator configuration */ + ret = da7219_handle_supplies(component, &io_voltage_lvl); + if (ret) return ret; - } regcache_cache_bypass(da7219->regmap, true); @@ -2615,23 +2496,221 @@ static int da7219_i2c_probe(struct i2c_client *i2c, DA7219_CIF_REG_SOFT_RESET_MASK); regmap_write_bits(da7219->regmap, DA7219_SYSTEM_ACTIVE, DA7219_SYSTEM_ACTIVE_MASK, 0); + regmap_write_bits(da7219->regmap, DA7219_SYSTEM_ACTIVE, + DA7219_SYSTEM_ACTIVE_MASK, 1); regcache_cache_bypass(da7219->regmap, false); + regmap_reinit_cache(da7219->regmap, &da7219_regmap_config); - ret = devm_snd_soc_register_component(&i2c->dev, - &soc_component_dev_da7219, - &da7219_dai, 1); - if (ret < 0) { - dev_err(&i2c->dev, "Failed to register da7219 component: %d\n", - ret); + /* Update IO voltage level range based on supply level */ + snd_soc_component_write(component, DA7219_IO_CTRL, io_voltage_lvl); + + ret = regmap_read(da7219->regmap, DA7219_CHIP_REVISION, &rev); + if (ret) { + dev_err(component->dev, "Failed to read chip revision: %d\n", ret); + goto err_disable_reg; + } + + switch (rev & DA7219_CHIP_MINOR_MASK) { + case 0: + ret = regmap_register_patch(da7219->regmap, da7219_rev_aa_patch, + ARRAY_SIZE(da7219_rev_aa_patch)); + if (ret) { + dev_err(component->dev, "Failed to register AA patch: %d\n", + ret); + goto err_disable_reg; + } + break; + default: + break; } + + /* Handle DT/ACPI/Platform data */ + da7219_handle_pdata(component); + + /* Check if MCLK provided */ + da7219->mclk = clk_get(component->dev, "mclk"); + if (IS_ERR(da7219->mclk)) { + if (PTR_ERR(da7219->mclk) != -ENOENT) { + ret = PTR_ERR(da7219->mclk); + goto err_disable_reg; + } else { + da7219->mclk = NULL; + } + } + + /* Register CCF DAI clock control */ + ret = da7219_register_dai_clks(component); + if (ret) + goto err_put_clk; + + /* Default PC counter to free-running */ + snd_soc_component_update_bits(component, DA7219_PC_COUNT, DA7219_PC_FREERUN_MASK, + DA7219_PC_FREERUN_MASK); + + /* Default gain ramping */ + snd_soc_component_update_bits(component, DA7219_MIXIN_L_CTRL, + DA7219_MIXIN_L_AMP_RAMP_EN_MASK, + DA7219_MIXIN_L_AMP_RAMP_EN_MASK); + snd_soc_component_update_bits(component, DA7219_ADC_L_CTRL, DA7219_ADC_L_RAMP_EN_MASK, + DA7219_ADC_L_RAMP_EN_MASK); + snd_soc_component_update_bits(component, DA7219_DAC_L_CTRL, DA7219_DAC_L_RAMP_EN_MASK, + DA7219_DAC_L_RAMP_EN_MASK); + snd_soc_component_update_bits(component, DA7219_DAC_R_CTRL, DA7219_DAC_R_RAMP_EN_MASK, + DA7219_DAC_R_RAMP_EN_MASK); + snd_soc_component_update_bits(component, DA7219_HP_L_CTRL, + DA7219_HP_L_AMP_RAMP_EN_MASK, + DA7219_HP_L_AMP_RAMP_EN_MASK); + snd_soc_component_update_bits(component, DA7219_HP_R_CTRL, + DA7219_HP_R_AMP_RAMP_EN_MASK, + DA7219_HP_R_AMP_RAMP_EN_MASK); + + /* Default minimum gain on HP to avoid pops during DAPM sequencing */ + snd_soc_component_update_bits(component, DA7219_HP_L_CTRL, + DA7219_HP_L_AMP_MIN_GAIN_EN_MASK, + DA7219_HP_L_AMP_MIN_GAIN_EN_MASK); + snd_soc_component_update_bits(component, DA7219_HP_R_CTRL, + DA7219_HP_R_AMP_MIN_GAIN_EN_MASK, + DA7219_HP_R_AMP_MIN_GAIN_EN_MASK); + + /* Default infinite tone gen, start/stop by Kcontrol */ + snd_soc_component_write(component, DA7219_TONE_GEN_CYCLES, DA7219_BEEP_CYCLES_MASK); + + /* Initialise AAD block */ + ret = da7219_aad_init(component); + if (ret) + goto err_free_dai_clks; + + return 0; + +err_free_dai_clks: + da7219_free_dai_clks(component); + +err_put_clk: + clk_put(da7219->mclk); + +err_disable_reg: + regulator_bulk_disable(DA7219_NUM_SUPPLIES, da7219->supplies); + regulator_bulk_free(DA7219_NUM_SUPPLIES, da7219->supplies); + return ret; } -static int da7219_i2c_remove(struct i2c_client *client) +static void da7219_remove(struct snd_soc_component *component) { + struct da7219_priv *da7219 = snd_soc_component_get_drvdata(component); + + da7219_aad_exit(component); + + da7219_free_dai_clks(component); + clk_put(da7219->mclk); + + /* Supplies */ + regulator_bulk_disable(DA7219_NUM_SUPPLIES, da7219->supplies); + regulator_bulk_free(DA7219_NUM_SUPPLIES, da7219->supplies); +} + +#ifdef CONFIG_PM +static int da7219_suspend(struct snd_soc_component *component) +{ + struct da7219_priv *da7219 = snd_soc_component_get_drvdata(component); + struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(component); + + /* Suspend AAD if we're not a wake-up source */ + if (!da7219->wakeup_source) + da7219_aad_suspend(component); + + snd_soc_dapm_force_bias_level(dapm, SND_SOC_BIAS_OFF); + + return 0; +} + +static int da7219_resume(struct snd_soc_component *component) +{ + struct da7219_priv *da7219 = snd_soc_component_get_drvdata(component); + struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(component); + + snd_soc_dapm_force_bias_level(dapm, SND_SOC_BIAS_STANDBY); + + /* Resume AAD if previously suspended */ + if (!da7219->wakeup_source) + da7219_aad_resume(component); + return 0; } +#else +#define da7219_suspend NULL +#define da7219_resume NULL +#endif + +static int da7219_set_jack(struct snd_soc_component *component, struct snd_soc_jack *jack, + void *data) +{ + da7219_aad_jack_det(component, jack); + + return 0; +} + +static const struct snd_soc_component_driver soc_component_dev_da7219 = { + .probe = da7219_probe, + .remove = da7219_remove, + .suspend = da7219_suspend, + .resume = da7219_resume, + .set_jack = da7219_set_jack, + .set_bias_level = da7219_set_bias_level, + .controls = da7219_snd_controls, + .num_controls = ARRAY_SIZE(da7219_snd_controls), + .dapm_widgets = da7219_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(da7219_dapm_widgets), + .dapm_routes = da7219_audio_map, + .num_dapm_routes = ARRAY_SIZE(da7219_audio_map), + .idle_bias_on = 1, + .use_pmdown_time = 1, + .endianness = 1, +}; + + +/* + * I2C layer + */ + +static int da7219_i2c_probe(struct i2c_client *i2c) +{ + struct device *dev = &i2c->dev; + struct da7219_priv *da7219; + int ret; + + da7219 = devm_kzalloc(dev, sizeof(struct da7219_priv), + GFP_KERNEL); + if (!da7219) + return -ENOMEM; + + i2c_set_clientdata(i2c, da7219); + + da7219->regmap = devm_regmap_init_i2c(i2c, &da7219_regmap_config); + if (IS_ERR(da7219->regmap)) { + ret = PTR_ERR(da7219->regmap); + dev_err(dev, "regmap_init() failed: %d\n", ret); + return ret; + } + + /* Retrieve DT/ACPI/Platform data */ + da7219->pdata = dev_get_platdata(dev); + if (!da7219->pdata) + da7219->pdata = da7219_fw_to_pdata(dev); + + /* AAD */ + ret = da7219_aad_probe(i2c); + if (ret) + return ret; + + ret = devm_snd_soc_register_component(dev, &soc_component_dev_da7219, + &da7219_dai, 1); + if (ret < 0) { + dev_err(dev, "Failed to register da7219 component: %d\n", ret); + } + return ret; +} static const struct i2c_device_id da7219_i2c_id[] = { { "da7219", }, @@ -2646,7 +2725,6 @@ static struct i2c_driver da7219_i2c_driver = { .acpi_match_table = ACPI_PTR(da7219_acpi_match), }, .probe = da7219_i2c_probe, - .remove = da7219_i2c_remove, .id_table = da7219_i2c_id, }; |
