forked from luck/tmp_suning_uos_patched
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:
commit
ba3e069fc1
|
@ -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,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;
|
||||
}
|
||||
|
|
|
@ -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];
|
||||
|
|
Loading…
Reference in New Issue
Block a user