Merge series "ASoC: da7219: Reorganise device/codec level probe/remove" from Adam Thomson <Adam.Thomson.Opensource@diasemi.com>:

This patch set reorganises and fixes device and codec level probe/remove
handling within the driver, to allow clean probe and remove at the codec level.

This set relates to an issue raised by Yong Zhi where a codec level re-probe
would fail due to clks still being registered from the previous instantiation.
In addition some improvements around regulator handling and soft reset have
also been included.

Adam Thomson (3):
  ASoC: da7219: Move required devm_* allocations to device level code
  ASoC: da7219: Move soft reset handling to codec level probe
  ASoC: da7219: Fix clock handling around codec level probe

 sound/soc/codecs/da7219-aad.c |  85 +++++---
 sound/soc/codecs/da7219-aad.h |   3 +
 sound/soc/codecs/da7219.c     | 493 +++++++++++++++++++++++-------------------
 sound/soc/codecs/da7219.h     |   1 +
 4 files changed, 328 insertions(+), 254 deletions(-)

--
1.9.1
This commit is contained in:
Mark Brown 2020-08-18 14:53:01 +01:00
commit ba3e069fc1
No known key found for this signature in database
GPG Key ID: 24D68B725D5487D0
4 changed files with 335 additions and 261 deletions

View File

@ -460,7 +460,7 @@ static irqreturn_t da7219_aad_irq_thread(int irq, void *data)
*/
static enum da7219_aad_micbias_pulse_lvl
da7219_aad_fw_micbias_pulse_lvl(struct snd_soc_component *component, u32 val)
da7219_aad_fw_micbias_pulse_lvl(struct device *dev, u32 val)
{
switch (val) {
case 2800:
@ -468,13 +468,13 @@ static enum da7219_aad_micbias_pulse_lvl
case 2900:
return DA7219_AAD_MICBIAS_PULSE_LVL_2_9V;
default:
dev_warn(component->dev, "Invalid micbias pulse level");
dev_warn(dev, "Invalid micbias pulse level");
return DA7219_AAD_MICBIAS_PULSE_LVL_OFF;
}
}
static enum da7219_aad_btn_cfg
da7219_aad_fw_btn_cfg(struct snd_soc_component *component, u32 val)
da7219_aad_fw_btn_cfg(struct device *dev, u32 val)
{
switch (val) {
case 2:
@ -492,13 +492,13 @@ static enum da7219_aad_btn_cfg
case 500:
return DA7219_AAD_BTN_CFG_500MS;
default:
dev_warn(component->dev, "Invalid button config");
dev_warn(dev, "Invalid button config");
return DA7219_AAD_BTN_CFG_10MS;
}
}
static enum da7219_aad_mic_det_thr
da7219_aad_fw_mic_det_thr(struct snd_soc_component *component, u32 val)
da7219_aad_fw_mic_det_thr(struct device *dev, u32 val)
{
switch (val) {
case 200:
@ -510,13 +510,13 @@ static enum da7219_aad_mic_det_thr
case 1000:
return DA7219_AAD_MIC_DET_THR_1000_OHMS;
default:
dev_warn(component->dev, "Invalid mic detect threshold");
dev_warn(dev, "Invalid mic detect threshold");
return DA7219_AAD_MIC_DET_THR_500_OHMS;
}
}
static enum da7219_aad_jack_ins_deb
da7219_aad_fw_jack_ins_deb(struct snd_soc_component *component, u32 val)
da7219_aad_fw_jack_ins_deb(struct device *dev, u32 val)
{
switch (val) {
case 5:
@ -536,13 +536,13 @@ static enum da7219_aad_jack_ins_deb
case 1000:
return DA7219_AAD_JACK_INS_DEB_1S;
default:
dev_warn(component->dev, "Invalid jack insert debounce");
dev_warn(dev, "Invalid jack insert debounce");
return DA7219_AAD_JACK_INS_DEB_20MS;
}
}
static enum da7219_aad_jack_det_rate
da7219_aad_fw_jack_det_rate(struct snd_soc_component *component, const char *str)
da7219_aad_fw_jack_det_rate(struct device *dev, const char *str)
{
if (!strcmp(str, "32ms_64ms")) {
return DA7219_AAD_JACK_DET_RATE_32_64MS;
@ -553,13 +553,13 @@ static enum da7219_aad_jack_det_rate
} else if (!strcmp(str, "256ms_512ms")) {
return DA7219_AAD_JACK_DET_RATE_256_512MS;
} else {
dev_warn(component->dev, "Invalid jack detect rate");
dev_warn(dev, "Invalid jack detect rate");
return DA7219_AAD_JACK_DET_RATE_256_512MS;
}
}
static enum da7219_aad_jack_rem_deb
da7219_aad_fw_jack_rem_deb(struct snd_soc_component *component, u32 val)
da7219_aad_fw_jack_rem_deb(struct device *dev, u32 val)
{
switch (val) {
case 1:
@ -571,13 +571,13 @@ static enum da7219_aad_jack_rem_deb
case 20:
return DA7219_AAD_JACK_REM_DEB_20MS;
default:
dev_warn(component->dev, "Invalid jack removal debounce");
dev_warn(dev, "Invalid jack removal debounce");
return DA7219_AAD_JACK_REM_DEB_1MS;
}
}
static enum da7219_aad_btn_avg
da7219_aad_fw_btn_avg(struct snd_soc_component *component, u32 val)
da7219_aad_fw_btn_avg(struct device *dev, u32 val)
{
switch (val) {
case 1:
@ -589,13 +589,13 @@ static enum da7219_aad_btn_avg
case 8:
return DA7219_AAD_BTN_AVG_8;
default:
dev_warn(component->dev, "Invalid button average value");
dev_warn(dev, "Invalid button average value");
return DA7219_AAD_BTN_AVG_2;
}
}
static enum da7219_aad_adc_1bit_rpt
da7219_aad_fw_adc_1bit_rpt(struct snd_soc_component *component, u32 val)
da7219_aad_fw_adc_1bit_rpt(struct device *dev, u32 val)
{
switch (val) {
case 1:
@ -607,14 +607,13 @@ static enum da7219_aad_adc_1bit_rpt
case 8:
return DA7219_AAD_ADC_1BIT_RPT_8;
default:
dev_warn(component->dev, "Invalid ADC 1-bit repeat value");
dev_warn(dev, "Invalid ADC 1-bit repeat value");
return DA7219_AAD_ADC_1BIT_RPT_1;
}
}
static struct da7219_aad_pdata *da7219_aad_fw_to_pdata(struct snd_soc_component *component)
static struct da7219_aad_pdata *da7219_aad_fw_to_pdata(struct device *dev)
{
struct device *dev = component->dev;
struct i2c_client *i2c = to_i2c_client(dev);
struct fwnode_handle *aad_np;
struct da7219_aad_pdata *aad_pdata;
@ -634,7 +633,7 @@ static struct da7219_aad_pdata *da7219_aad_fw_to_pdata(struct snd_soc_component
if (fwnode_property_read_u32(aad_np, "dlg,micbias-pulse-lvl",
&fw_val32) >= 0)
aad_pdata->micbias_pulse_lvl =
da7219_aad_fw_micbias_pulse_lvl(component, fw_val32);
da7219_aad_fw_micbias_pulse_lvl(dev, fw_val32);
else
aad_pdata->micbias_pulse_lvl = DA7219_AAD_MICBIAS_PULSE_LVL_OFF;
@ -643,31 +642,31 @@ static struct da7219_aad_pdata *da7219_aad_fw_to_pdata(struct snd_soc_component
aad_pdata->micbias_pulse_time = fw_val32;
if (fwnode_property_read_u32(aad_np, "dlg,btn-cfg", &fw_val32) >= 0)
aad_pdata->btn_cfg = da7219_aad_fw_btn_cfg(component, fw_val32);
aad_pdata->btn_cfg = da7219_aad_fw_btn_cfg(dev, fw_val32);
else
aad_pdata->btn_cfg = DA7219_AAD_BTN_CFG_10MS;
if (fwnode_property_read_u32(aad_np, "dlg,mic-det-thr", &fw_val32) >= 0)
aad_pdata->mic_det_thr =
da7219_aad_fw_mic_det_thr(component, fw_val32);
da7219_aad_fw_mic_det_thr(dev, fw_val32);
else
aad_pdata->mic_det_thr = DA7219_AAD_MIC_DET_THR_500_OHMS;
if (fwnode_property_read_u32(aad_np, "dlg,jack-ins-deb", &fw_val32) >= 0)
aad_pdata->jack_ins_deb =
da7219_aad_fw_jack_ins_deb(component, fw_val32);
da7219_aad_fw_jack_ins_deb(dev, fw_val32);
else
aad_pdata->jack_ins_deb = DA7219_AAD_JACK_INS_DEB_20MS;
if (!fwnode_property_read_string(aad_np, "dlg,jack-det-rate", &fw_str))
aad_pdata->jack_det_rate =
da7219_aad_fw_jack_det_rate(component, fw_str);
da7219_aad_fw_jack_det_rate(dev, fw_str);
else
aad_pdata->jack_det_rate = DA7219_AAD_JACK_DET_RATE_256_512MS;
if (fwnode_property_read_u32(aad_np, "dlg,jack-rem-deb", &fw_val32) >= 0)
aad_pdata->jack_rem_deb =
da7219_aad_fw_jack_rem_deb(component, fw_val32);
da7219_aad_fw_jack_rem_deb(dev, fw_val32);
else
aad_pdata->jack_rem_deb = DA7219_AAD_JACK_REM_DEB_1MS;
@ -692,13 +691,13 @@ static struct da7219_aad_pdata *da7219_aad_fw_to_pdata(struct snd_soc_component
aad_pdata->c_mic_btn_thr = 0x3E;
if (fwnode_property_read_u32(aad_np, "dlg,btn-avg", &fw_val32) >= 0)
aad_pdata->btn_avg = da7219_aad_fw_btn_avg(component, fw_val32);
aad_pdata->btn_avg = da7219_aad_fw_btn_avg(dev, fw_val32);
else
aad_pdata->btn_avg = DA7219_AAD_BTN_AVG_2;
if (fwnode_property_read_u32(aad_np, "dlg,adc-1bit-rpt", &fw_val32) >= 0)
aad_pdata->adc_1bit_rpt =
da7219_aad_fw_adc_1bit_rpt(component, fw_val32);
da7219_aad_fw_adc_1bit_rpt(dev, fw_val32);
else
aad_pdata->adc_1bit_rpt = DA7219_AAD_ADC_1BIT_RPT_1;
@ -887,21 +886,13 @@ void da7219_aad_resume(struct snd_soc_component *component)
int da7219_aad_init(struct snd_soc_component *component)
{
struct da7219_priv *da7219 = snd_soc_component_get_drvdata(component);
struct da7219_aad_priv *da7219_aad;
struct da7219_aad_priv *da7219_aad = da7219->aad;
u8 mask[DA7219_AAD_IRQ_REG_MAX];
int ret;
da7219_aad = devm_kzalloc(component->dev, sizeof(*da7219_aad), GFP_KERNEL);
if (!da7219_aad)
return -ENOMEM;
da7219->aad = da7219_aad;
da7219_aad->component = component;
/* Handle any DT/ACPI/platform data */
if (da7219->pdata && !da7219->pdata->aad_pdata)
da7219->pdata->aad_pdata = da7219_aad_fw_to_pdata(component);
da7219_aad_handle_pdata(component);
/* Disable button detection */
@ -947,6 +938,30 @@ void da7219_aad_exit(struct snd_soc_component *component)
}
EXPORT_SYMBOL_GPL(da7219_aad_exit);
/*
* AAD related I2C probe handling
*/
int da7219_aad_probe(struct i2c_client *i2c)
{
struct da7219_priv *da7219 = i2c_get_clientdata(i2c);
struct device *dev = &i2c->dev;
struct da7219_aad_priv *da7219_aad;
da7219_aad = devm_kzalloc(dev, sizeof(*da7219_aad), GFP_KERNEL);
if (!da7219_aad)
return -ENOMEM;
da7219->aad = da7219_aad;
/* Retrieve any DT/ACPI/platform data */
if (da7219->pdata && !da7219->pdata->aad_pdata)
da7219->pdata->aad_pdata = da7219_aad_fw_to_pdata(dev);
return 0;
}
EXPORT_SYMBOL_GPL(da7219_aad_probe);
MODULE_DESCRIPTION("ASoC DA7219 AAD Driver");
MODULE_AUTHOR("Adam Thomson <Adam.Thomson.Opensource@diasemi.com>");
MODULE_LICENSE("GPL");

View File

@ -212,4 +212,7 @@ void da7219_aad_resume(struct snd_soc_component *component);
int da7219_aad_init(struct snd_soc_component *component);
void da7219_aad_exit(struct snd_soc_component *component);
/* I2C Probe */
int da7219_aad_probe(struct i2c_client *i2c);
#endif /* __DA7219_AAD_H */

View File

@ -1753,9 +1753,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;
@ -1847,19 +1846,19 @@ 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;
@ -1871,21 +1870,18 @@ static int da7219_handle_supplies(struct snd_soc_component *component)
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;
else
*io_voltage_lvl = DA7219_IO_VOLTAGE_LEVEL_2_5V_3_6V;
/* 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;
}
@ -2121,14 +2117,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];
@ -2164,22 +2172,20 @@ 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) {
ret = -ENOMEM;
goto err;
@ -2189,21 +2195,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 {
if (da7219->dai_clks_lookup[i])
clkdev_drop(da7219->dai_clks_lookup[i]);
clk_hw_unregister(&da7219->dai_clks_hw[i]);
} while (i-- > 0);
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)
@ -2251,182 +2294,6 @@ 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
@ -2563,31 +2430,25 @@ static const struct regmap_config da7219_regmap_config = {
.cache_type = REGCACHE_RBTREE,
};
static 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;
da7219->component = component;
mutex_init(&da7219->ctrl_lock);
mutex_init(&da7219->pll_lock);
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(&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);
@ -2617,15 +2478,209 @@ 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);
/* 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 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);
/* 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,
};
/*
* I2C layer
*/
static int da7219_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
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(&i2c->dev, "Failed to register da7219 component: %d\n",
ret);
dev_err(dev, "Failed to register da7219 component: %d\n", ret);
}
return ret;
}

View File

@ -817,6 +817,7 @@ struct da7219_priv {
#ifdef CONFIG_COMMON_CLK
struct clk_hw dai_clks_hw[DA7219_DAI_NUM_CLKS];
struct clk_hw_onecell_data *clk_hw_data;
#endif
struct clk_lookup *dai_clks_lookup[DA7219_DAI_NUM_CLKS];
struct clk *dai_clks[DA7219_DAI_NUM_CLKS];