Commit ba3e069f authored by Mark Brown's avatar Mark Brown

Merge series "ASoC: da7219: Reorganise device/codec level probe/remove" from...

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
parents bf66f140 78013a1c
......@@ -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");
......@@ -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 */
......@@ -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,6 +2294,142 @@ static void da7219_handle_pdata(struct snd_soc_component *component)
}
}
/*
* Regmap configs
*/
static struct reg_default da7219_reg_defaults[] = {
{ DA7219_MIC_1_SELECT, 0x00 },
{ DA7219_CIF_TIMEOUT_CTRL, 0x01 },
{ DA7219_SR_24_48, 0x00 },
{ DA7219_SR, 0x0A },
{ DA7219_CIF_I2C_ADDR_CFG, 0x02 },
{ DA7219_PLL_CTRL, 0x10 },
{ DA7219_PLL_FRAC_TOP, 0x00 },
{ DA7219_PLL_FRAC_BOT, 0x00 },
{ DA7219_PLL_INTEGER, 0x20 },
{ DA7219_DIG_ROUTING_DAI, 0x10 },
{ DA7219_DAI_CLK_MODE, 0x01 },
{ DA7219_DAI_CTRL, 0x28 },
{ DA7219_DAI_TDM_CTRL, 0x40 },
{ DA7219_DIG_ROUTING_DAC, 0x32 },
{ DA7219_DAI_OFFSET_LOWER, 0x00 },
{ DA7219_DAI_OFFSET_UPPER, 0x00 },
{ DA7219_REFERENCES, 0x08 },
{ DA7219_MIXIN_L_SELECT, 0x00 },
{ DA7219_MIXIN_L_GAIN, 0x03 },
{ DA7219_ADC_L_GAIN, 0x6F },
{ DA7219_ADC_FILTERS1, 0x80 },
{ DA7219_MIC_1_GAIN, 0x01 },
{ DA7219_SIDETONE_CTRL, 0x40 },
{ DA7219_SIDETONE_GAIN, 0x0E },
{ DA7219_DROUTING_ST_OUTFILT_1L, 0x01 },
{ DA7219_DROUTING_ST_OUTFILT_1R, 0x02 },
{ DA7219_DAC_FILTERS5, 0x00 },
{ DA7219_DAC_FILTERS2, 0x88 },
{ DA7219_DAC_FILTERS3, 0x88 },
{ DA7219_DAC_FILTERS4, 0x08 },
{ DA7219_DAC_FILTERS1, 0x80 },
{ DA7219_DAC_L_GAIN, 0x6F },
{ DA7219_DAC_R_GAIN, 0x6F },
{ DA7219_CP_CTRL, 0x20 },
{ DA7219_HP_L_GAIN, 0x39 },
{ DA7219_HP_R_GAIN, 0x39 },
{ DA7219_MIXOUT_L_SELECT, 0x00 },
{ DA7219_MIXOUT_R_SELECT, 0x00 },
{ DA7219_MICBIAS_CTRL, 0x03 },
{ DA7219_MIC_1_CTRL, 0x40 },
{ DA7219_MIXIN_L_CTRL, 0x40 },
{ DA7219_ADC_L_CTRL, 0x40 },
{ DA7219_DAC_L_CTRL, 0x40 },
{ DA7219_DAC_R_CTRL, 0x40 },
{ DA7219_HP_L_CTRL, 0x40 },
{ DA7219_HP_R_CTRL, 0x40 },
{ DA7219_MIXOUT_L_CTRL, 0x10 },
{ DA7219_MIXOUT_R_CTRL, 0x10 },
{ DA7219_CHIP_ID1, 0x23 },
{ DA7219_CHIP_ID2, 0x93 },
{ DA7219_IO_CTRL, 0x00 },
{ DA7219_GAIN_RAMP_CTRL, 0x00 },
{ DA7219_PC_COUNT, 0x02 },
{ DA7219_CP_VOL_THRESHOLD1, 0x0E },
{ DA7219_DIG_CTRL, 0x00 },
{ DA7219_ALC_CTRL2, 0x00 },
{ DA7219_ALC_CTRL3, 0x00 },
{ DA7219_ALC_NOISE, 0x3F },
{ DA7219_ALC_TARGET_MIN, 0x3F },
{ DA7219_ALC_TARGET_MAX, 0x00 },
{ DA7219_ALC_GAIN_LIMITS, 0xFF },
{ DA7219_ALC_ANA_GAIN_LIMITS, 0x71 },
{ DA7219_ALC_ANTICLIP_CTRL, 0x00 },
{ DA7219_ALC_ANTICLIP_LEVEL, 0x00 },
{ DA7219_DAC_NG_SETUP_TIME, 0x00 },
{ DA7219_DAC_NG_OFF_THRESH, 0x00 },
{ DA7219_DAC_NG_ON_THRESH, 0x00 },
{ DA7219_DAC_NG_CTRL, 0x00 },
{ DA7219_TONE_GEN_CFG1, 0x00 },
{ DA7219_TONE_GEN_CFG2, 0x00 },
{ DA7219_TONE_GEN_CYCLES, 0x00 },
{ DA7219_TONE_GEN_FREQ1_L, 0x55 },
{ DA7219_TONE_GEN_FREQ1_U, 0x15 },
{ DA7219_TONE_GEN_FREQ2_L, 0x00 },
{ DA7219_TONE_GEN_FREQ2_U, 0x40 },
{ DA7219_TONE_GEN_ON_PER, 0x02 },
{ DA7219_TONE_GEN_OFF_PER, 0x01 },
{ DA7219_ACCDET_IRQ_MASK_A, 0x00 },
{ DA7219_ACCDET_IRQ_MASK_B, 0x00 },
{ DA7219_ACCDET_CONFIG_1, 0xD6 },
{ DA7219_ACCDET_CONFIG_2, 0x34 },
{ DA7219_ACCDET_CONFIG_3, 0x0A },
{ DA7219_ACCDET_CONFIG_4, 0x16 },
{ DA7219_ACCDET_CONFIG_5, 0x21 },
{ DA7219_ACCDET_CONFIG_6, 0x3E },
{ DA7219_ACCDET_CONFIG_7, 0x01 },
{ DA7219_SYSTEM_ACTIVE, 0x00 },
};
static bool da7219_volatile_register(struct device *dev, unsigned int reg)
{
switch (reg) {
case DA7219_MIC_1_GAIN_STATUS:
case DA7219_MIXIN_L_GAIN_STATUS:
case DA7219_ADC_L_GAIN_STATUS:
case DA7219_DAC_L_GAIN_STATUS:
case DA7219_DAC_R_GAIN_STATUS:
case DA7219_HP_L_GAIN_STATUS:
case DA7219_HP_R_GAIN_STATUS:
case DA7219_CIF_CTRL:
case DA7219_PLL_SRM_STS:
case DA7219_ALC_CTRL1:
case DA7219_SYSTEM_MODES_INPUT:
case DA7219_SYSTEM_MODES_OUTPUT:
case DA7219_ALC_OFFSET_AUTO_M_L:
case DA7219_ALC_OFFSET_AUTO_U_L:
case DA7219_TONE_GEN_CFG1:
case DA7219_ACCDET_STATUS_A:
case DA7219_ACCDET_STATUS_B:
case DA7219_ACCDET_IRQ_EVENT_A:
case DA7219_ACCDET_IRQ_EVENT_B:
case DA7219_ACCDET_CONFIG_8:
case DA7219_SYSTEM_STATUS:
return true;
default:
return false;
}
}
static const struct regmap_config da7219_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.max_register = DA7219_SYSTEM_ACTIVE,
.reg_defaults = da7219_reg_defaults,
.num_reg_defaults = ARRAY_SIZE(da7219_reg_defaults),
.volatile_reg = da7219_volatile_register,
.cache_type = REGCACHE_RBTREE,
};
static struct reg_sequence da7219_rev_aa_patch[] = {
{ DA7219_REFERENCES, 0x08 },
};
......@@ -2258,18 +2437,56 @@ static struct reg_sequence da7219_rev_aa_patch[] = {
static int da7219_probe(struct snd_soc_component *component)
{
struct da7219_priv *da7219 = snd_soc_component_get_drvdata(component);
unsigned int rev;
int ret;
unsigned int system_active, system_status, rev;
u8 io_voltage_lvl;
int i, ret;
da7219->component = component;
mutex_init(&da7219->ctrl_lock);
mutex_init(&da7219->pll_lock);
/* Regulator configuration */
ret = da7219_handle_supplies(component);
ret = da7219_handle_supplies(component, &io_voltage_lvl);
if (ret)
return ret;
regcache_cache_bypass(da7219->regmap, true);
/* Disable audio paths if still active from previous start */
regmap_read(da7219->regmap, DA7219_SYSTEM_ACTIVE, &system_active);
if (system_active) {
regmap_write(da7219->regmap, DA7219_GAIN_RAMP_CTRL,
DA7219_GAIN_RAMP_RATE_NOMINAL);
regmap_write(da7219->regmap, DA7219_SYSTEM_MODES_INPUT, 0x00);
regmap_write(da7219->regmap, DA7219_SYSTEM_MODES_OUTPUT, 0x01);
for (i = 0; i < DA7219_SYS_STAT_CHECK_RETRIES; ++i) {
regmap_read(da7219->regmap, DA7219_SYSTEM_STATUS,
&system_status);
if (!system_status)
break;
msleep(DA7219_SYS_STAT_CHECK_DELAY);
}
}
/* Soft reset component */
regmap_write_bits(da7219->regmap, DA7219_ACCDET_CONFIG_1,
DA7219_ACCDET_EN_MASK, 0);
regmap_write_bits(da7219->regmap, DA7219_CIF_CTRL,
DA7219_CIF_REG_SOFT_RESET_MASK,
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);
/* 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);
......@@ -2291,14 +2508,10 @@ static int da7219_probe(struct snd_soc_component *component)
}
/* 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");
da7219->mclk = clk_get(component->dev, "mclk");
if (IS_ERR(da7219->mclk)) {
if (PTR_ERR(da7219->mclk) != -ENOENT) {
ret = PTR_ERR(da7219->mclk);
......@@ -2311,7 +2524,7 @@ static int da7219_probe(struct snd_soc_component *component)
/* Register CCF DAI clock control */
ret = da7219_register_dai_clks(component);
if (ret)
return ret;
goto err_put_clk;
/* Default PC counter to free-running */
snd_soc_component_update_bits(component, DA7219_PC_COUNT, DA7219_PC_FREERUN_MASK,
......@@ -2348,12 +2561,19 @@ static int da7219_probe(struct snd_soc_component *component)
/* Initialise AAD block */
ret = da7219_aad_init(component);
if (ret)
goto err_disable_reg;
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;
}
......@@ -2361,21 +2581,15 @@ static int da7219_probe(struct snd_soc_component *component)
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
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
......@@ -2428,142 +2642,6 @@ static const struct snd_soc_component_driver soc_component_dev_da7219 = {
};
/*
* Regmap configs
*/
static struct reg_default da7219_reg_defaults[] = {
{ DA7219_MIC_1_SELECT, 0x00 },
{ DA7219_CIF_TIMEOUT_CTRL, 0x01 },
{ DA7219_SR_24_48, 0x00 },
{ DA7219_SR, 0x0A },
{ DA7219_CIF_I2C_ADDR_CFG, 0x02 },
{ DA7219_PLL_CTRL, 0x10 },
{ DA7219_PLL_FRAC_TOP, 0x00 },
{ DA7219_PLL_FRAC_BOT, 0x00 },
{ DA7219_PLL_INTEGER, 0x20 },
{ DA7219_DIG_ROUTING_DAI, 0x10 },
{ DA7219_DAI_CLK_MODE, 0x01 },
{ DA7219_DAI_CTRL, 0x28 },
{ DA7219_DAI_TDM_CTRL, 0x40 },
{ DA7219_DIG_ROUTING_DAC, 0x32 },
{ DA7219_DAI_OFFSET_LOWER, 0x00 },
{ DA7219_DAI_OFFSET_UPPER, 0x00 },
{ DA7219_REFERENCES, 0x08 },
{ DA7219_MIXIN_L_SELECT, 0x00 },
{ DA7219_MIXIN_L_GAIN, 0x03 },
{ DA7219_ADC_L_GAIN, 0x6F },
{ DA7219_ADC_FILTERS1, 0x80 },
{ DA7219_MIC_1_GAIN, 0x01 },
{ DA7219_SIDETONE_CTRL, 0x40 },
{ DA7219_SIDETONE_GAIN, 0x0E },
{ DA7219_DROUTING_ST_OUTFILT_1L, 0x01 },
{ DA7219_DROUTING_ST_OUTFILT_1R, 0x02 },
{ DA7219_DAC_FILTERS5, 0x00 },
{ DA7219_DAC_FILTERS2, 0x88 },
{ DA7219_DAC_FILTERS3, 0x88 },
{ DA7219_DAC_FILTERS4, 0x08 },
{ DA7219_DAC_FILTERS1, 0x80 },
{ DA7219_DAC_L_GAIN, 0x6F },
{ DA7219_DAC_R_GAIN, 0x6F },
{ DA7219_CP_CTRL, 0x20 },
{ DA7219_HP_L_GAIN, 0x39 },
{ DA7219_HP_R_GAIN, 0x39 },
{ DA7219_MIXOUT_L_SELECT, 0x00 },
{ DA7219_MIXOUT_R_SELECT, 0x00 },
{ DA7219_MICBIAS_CTRL, 0x03 },
{ DA7219_MIC_1_CTRL, 0x40 },
{ DA7219_MIXIN_L_CTRL, 0x40 },
{ DA7219_ADC_L_CTRL, 0x40 },
{ DA7219_DAC_L_CTRL, 0x40 },
{ DA7219_DAC_R_CTRL, 0x40 },
{ DA7219_HP_L_CTRL, 0x40 },
{ DA7219_HP_R_CTRL, 0x40 },
{ DA7219_MIXOUT_L_CTRL, 0x10 },
{ DA7219_MIXOUT_R_CTRL, 0x10 },
{ DA7219_CHIP_ID1, 0x23 },
{ DA7219_CHIP_ID2, 0x93 },
{ DA7219_IO_CTRL, 0x00 },
{ DA7219_GAIN_RAMP_CTRL, 0x00 },
{ DA7219_PC_COUNT, 0x02 },
{ DA7219_CP_VOL_THRESHOLD1, 0x0E },
{ DA7219_DIG_CTRL, 0x00 },
{ DA7219_ALC_CTRL2, 0x00 },
{ DA7219_ALC_CTRL3, 0x00 },
{ DA7219_ALC_NOISE, 0x3F },
{ DA7219_ALC_TARGET_MIN, 0x3F },
{ DA7219_ALC_TARGET_MAX, 0x00 },
{ DA7219_ALC_GAIN_LIMITS, 0xFF },
{ DA7219_ALC_ANA_GAIN_LIMITS, 0x71 },
{ DA7219_ALC_ANTICLIP_CTRL, 0x00 },
{ DA7219_ALC_ANTICLIP_LEVEL, 0x00 },
{ DA7219_DAC_NG_SETUP_TIME, 0x00 },
{ DA7219_DAC_NG_OFF_THRESH, 0x00 },
{ DA7219_DAC_NG_ON_THRESH, 0x00 },
{ DA7219_DAC_NG_CTRL, 0x00 },
{ DA7219_TONE_GEN_CFG1, 0x00 },
{ DA7219_TONE_GEN_CFG2, 0x00 },
{ DA7219_TONE_GEN_CYCLES, 0x00 },
{ DA7219_TONE_GEN_FREQ1_L, 0x55 },
{ DA7219_TONE_GEN_FREQ1_U, 0x15 },
{ DA7219_TONE_GEN_FREQ2_L, 0x00 },
{ DA7219_TONE_GEN_FREQ2_U, 0x40 },
{ DA7219_TONE_GEN_ON_PER, 0x02 },
{ DA7219_TONE_GEN_OFF_PER, 0x01 },
{ DA7219_ACCDET_IRQ_MASK_A, 0x00 },
{ DA7219_ACCDET_IRQ_MASK_B, 0x00 },
{ DA7219_ACCDET_CONFIG_1, 0xD6 },
{ DA7219_ACCDET_CONFIG_2, 0x34 },
{ DA7219_ACCDET_CONFIG_3, 0x0A },
{ DA7219_ACCDET_CONFIG_4, 0x16 },
{ DA7219_ACCDET_CONFIG_5, 0x21 },
{ DA7219_ACCDET_CONFIG_6, 0x3E },
{ DA7219_ACCDET_CONFIG_7, 0x01 },
{ DA7219_SYSTEM_ACTIVE, 0x00 },
};
static bool da7219_volatile_register(struct device *dev, unsigned int reg)
{
switch (reg) {
case DA7219_MIC_1_GAIN_STATUS:
case DA7219_MIXIN_L_GAIN_STATUS:
case DA7219_ADC_L_GAIN_STATUS:
case DA7219_DAC_L_GAIN_STATUS:
case DA7219_DAC_R_GAIN_STATUS:
case DA7219_HP_L_GAIN_STATUS:
case DA7219_HP_R_GAIN_STATUS:
case DA7219_CIF_CTRL:
case DA7219_PLL_SRM_STS:
case DA7219_ALC_CTRL1:
case DA7219_SYSTEM_MODES_INPUT:
case DA7219_SYSTEM_MODES_OUTPUT:
case DA7219_ALC_OFFSET_AUTO_M_L:
case DA7219_ALC_OFFSET_AUTO_U_L:
case DA7219_TONE_GEN_CFG1:
case DA7219_ACCDET_STATUS_A:
case DA7219_ACCDET_STATUS_B:
case DA7219_ACCDET_IRQ_EVENT_A:
case DA7219_ACCDET_IRQ_EVENT_B:
case DA7219_ACCDET_CONFIG_8:
case DA7219_SYSTEM_STATUS:
return true;
default:
return false;
}
}
static const struct regmap_config da7219_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.max_register = DA7219_SYSTEM_ACTIVE,
.reg_defaults = da7219_reg_defaults,
.num_reg_defaults = ARRAY_SIZE(da7219_reg_defaults),
.volatile_reg = da7219_volatile_register,
.cache_type = REGCACHE_RBTREE,
};
/*
* I2C layer
*/
......@@ -2571,11 +2649,11 @@ static const struct regmap_config da7219_regmap_config = {
static int da7219_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct device *dev = &i2c->dev;
struct da7219_priv *da7219;
unsigned int system_active, system_status;
int i, ret;
int ret;
da7219 = devm_kzalloc(&i2c->dev, sizeof(struct da7219_priv),
da7219 = devm_kzalloc(dev, sizeof(struct da7219_priv),
GFP_KERNEL);
if (!da7219)
return -ENOMEM;
......@@ -2585,47 +2663,24 @@ static int da7219_i2c_probe(struct i2c_client *i2c,
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);
dev_err(dev, "regmap_init() failed: %d\n", ret);
return ret;
}
regcache_cache_bypass(da7219->regmap, true);
/* Disable audio paths if still active from previous start */
regmap_read(da7219->regmap, DA7219_SYSTEM_ACTIVE, &system_active);
if (system_active) {
regmap_write(da7219->regmap, DA7219_GAIN_RAMP_CTRL,
DA7219_GAIN_RAMP_RATE_NOMINAL);
regmap_write(da7219->regmap, DA7219_SYSTEM_MODES_INPUT, 0x00);
regmap_write(da7219->regmap, DA7219_SYSTEM_MODES_OUTPUT, 0x01);
for (i = 0; i < DA7219_SYS_STAT_CHECK_RETRIES; ++i) {
regmap_read(da7219->regmap, DA7219_SYSTEM_STATUS,
&system_status);
if (!system_status)
break;
msleep(DA7219_SYS_STAT_CHECK_DELAY);
}
}
/* Soft reset component */
regmap_write_bits(da7219->regmap, DA7219_ACCDET_CONFIG_1,
DA7219_ACCDET_EN_MASK, 0);
regmap_write_bits(da7219->regmap, DA7219_CIF_CTRL,
DA7219_CIF_REG_SOFT_RESET_MASK,
DA7219_CIF_REG_SOFT_RESET_MASK);
regmap_write_bits(da7219->regmap, DA7219_SYSTEM_ACTIVE,
DA7219_SYSTEM_ACTIVE_MASK, 0);
/* Retrieve DT/ACPI/Platform data */
da7219->pdata = dev_get_platdata(dev);
if (!da7219->pdata)
da7219->pdata = da7219_fw_to_pdata(dev);
regcache_cache_bypass(da7219->regmap, false);
/* AAD */
ret = da7219_aad_probe(i2c);
if (ret)
return ret;
ret = devm_snd_soc_register_component(&i2c->dev,
&soc_component_dev_da7219,
&da7219_dai, 1);
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;
}
......
......@@ -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];
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment