linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/3] ASoC: da7219: Reorganise device/codec level probe/remove
@ 2020-08-11 16:57 Adam Thomson
  2020-08-11 16:57 ` [PATCH 1/3] ASoC: da7219: Move required devm_* allocations to device level code Adam Thomson
                   ` (4 more replies)
  0 siblings, 5 replies; 7+ messages in thread
From: Adam Thomson @ 2020-08-11 16:57 UTC (permalink / raw)
  To: Mark Brown, Takashi Iwai, Liam Girdwood, Jaroslav Kysela
  Cc: Yong Zhi, Pierre-Louis Bossart, alsa-devel, linux-kernel,
	Support Opensource

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


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 1/3] ASoC: da7219: Move required devm_* allocations to device level code
  2020-08-11 16:57 [PATCH 0/3] ASoC: da7219: Reorganise device/codec level probe/remove Adam Thomson
@ 2020-08-11 16:57 ` Adam Thomson
  2020-08-11 16:57 ` [PATCH 2/3] ASoC: da7219: Move soft reset handling to codec level probe Adam Thomson
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 7+ messages in thread
From: Adam Thomson @ 2020-08-11 16:57 UTC (permalink / raw)
  To: Mark Brown, Takashi Iwai, Liam Girdwood, Jaroslav Kysela
  Cc: Yong Zhi, Pierre-Louis Bossart, alsa-devel, linux-kernel,
	Support Opensource

In preparation for cleanup of device level and codec level probe
funcitonality, all necessary devm_* allocations and fw retrieval
functions are moved to the I2C probe level code.

Signed-off-by: Adam Thomson <Adam.Thomson.Opensource@diasemi.com>
---
 sound/soc/codecs/da7219-aad.c | 85 +++++++++++++++++++++++++------------------
 sound/soc/codecs/da7219-aad.h |  3 ++
 sound/soc/codecs/da7219.c     | 30 ++++++++-------
 3 files changed, 70 insertions(+), 48 deletions(-)

diff --git a/sound/soc/codecs/da7219-aad.c b/sound/soc/codecs/da7219-aad.c
index 4f2a96e..3827734 100644
--- a/sound/soc/codecs/da7219-aad.c
+++ b/sound/soc/codecs/da7219-aad.c
@@ -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 irqreturn_t da7219_aad_irq_thread(int irq, void *data)
 	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 irqreturn_t da7219_aad_irq_thread(int irq, void *data)
 	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 irqreturn_t da7219_aad_irq_thread(int irq, void *data)
 	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 irqreturn_t da7219_aad_irq_thread(int irq, void *data)
 	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 irqreturn_t da7219_aad_irq_thread(int irq, void *data)
 	} 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 irqreturn_t da7219_aad_irq_thread(int irq, void *data)
 	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 irqreturn_t da7219_aad_irq_thread(int irq, void *data)
 	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 irqreturn_t da7219_aad_irq_thread(int irq, void *data)
 	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");
diff --git a/sound/soc/codecs/da7219-aad.h b/sound/soc/codecs/da7219-aad.h
index cfa46fb..f48a120 100644
--- a/sound/soc/codecs/da7219-aad.h
+++ b/sound/soc/codecs/da7219-aad.h
@@ -212,4 +212,7 @@ struct da7219_aad_priv {
 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 */
diff --git a/sound/soc/codecs/da7219.c b/sound/soc/codecs/da7219.c
index f83a6ea..82d35bc 100644
--- a/sound/soc/codecs/da7219.c
+++ b/sound/soc/codecs/da7219.c
@@ -1751,9 +1751,8 @@ static int da7219_hw_params(struct snd_pcm_substream *substream,
 	}
 }
 
-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;
@@ -2289,10 +2288,6 @@ 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 */
@@ -2569,11 +2564,12 @@ static bool da7219_volatile_register(struct device *dev, unsigned int reg)
 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;
 
-	da7219 = devm_kzalloc(&i2c->dev, sizeof(struct da7219_priv),
+	da7219 = devm_kzalloc(dev, sizeof(struct da7219_priv),
 			      GFP_KERNEL);
 	if (!da7219)
 		return -ENOMEM;
@@ -2583,7 +2579,7 @@ 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;
 	}
 
@@ -2618,12 +2614,20 @@ static int da7219_i2c_probe(struct i2c_client *i2c,
 
 	regcache_cache_bypass(da7219->regmap, false);
 
-	ret = devm_snd_soc_register_component(&i2c->dev,
-				     &soc_component_dev_da7219,
-				     &da7219_dai, 1);
+	/* 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;
 }
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 2/3] ASoC: da7219: Move soft reset handling to codec level probe
  2020-08-11 16:57 [PATCH 0/3] ASoC: da7219: Reorganise device/codec level probe/remove Adam Thomson
  2020-08-11 16:57 ` [PATCH 1/3] ASoC: da7219: Move required devm_* allocations to device level code Adam Thomson
@ 2020-08-11 16:57 ` Adam Thomson
  2020-08-11 16:57 ` [PATCH 3/3] ASoC: da7219: Fix clock handling around " Adam Thomson
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 7+ messages in thread
From: Adam Thomson @ 2020-08-11 16:57 UTC (permalink / raw)
  To: Mark Brown, Takashi Iwai, Liam Girdwood, Jaroslav Kysela
  Cc: Yong Zhi, Pierre-Louis Bossart, alsa-devel, linux-kernel,
	Support Opensource

As part of the reorganisation of the device level and codec
level probe functionlity, the soft reset handling should really
reside at the codec level and after the instantiation of supplies.
This commit makes the relevant changes to support this change of
scope including the remove of devm_* functions being called for
regulator instantiation at the codec level.

Signed-off-by: Adam Thomson <Adam.Thomson.Opensource@diasemi.com>
---
 sound/soc/codecs/da7219.c | 371 +++++++++++++++++++++++-----------------------
 1 file changed, 188 insertions(+), 183 deletions(-)

diff --git a/sound/soc/codecs/da7219.c b/sound/soc/codecs/da7219.c
index 82d35bc..0d1c70f8 100644
--- a/sound/soc/codecs/da7219.c
+++ b/sound/soc/codecs/da7219.c
@@ -1844,19 +1844,19 @@ static int da7219_set_bias_level(struct snd_soc_component *component,
 	[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;
@@ -1868,21 +1868,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;
 }
 
@@ -2248,6 +2245,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 },
 };
@@ -2255,18 +2388,56 @@ static void da7219_handle_pdata(struct snd_soc_component *component)
 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);
@@ -2347,6 +2518,7 @@ static int da7219_probe(struct snd_soc_component *component)
 
 err_disable_reg:
 	regulator_bulk_disable(DA7219_NUM_SUPPLIES, da7219->supplies);
+	regulator_bulk_free(DA7219_NUM_SUPPLIES, da7219->supplies);
 
 	return ret;
 }
@@ -2369,6 +2541,7 @@ static void da7219_remove(struct snd_soc_component *component)
 
 	/* Supplies */
 	regulator_bulk_disable(DA7219_NUM_SUPPLIES, da7219->supplies);
+	regulator_bulk_free(DA7219_NUM_SUPPLIES, da7219->supplies);
 }
 
 #ifdef CONFIG_PM
@@ -2422,142 +2595,6 @@ static int da7219_resume(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,
-};
-
-
-/*
  * I2C layer
  */
 
@@ -2566,8 +2603,7 @@ static int da7219_i2c_probe(struct i2c_client *i2c,
 {
 	struct device *dev = &i2c->dev;
 	struct da7219_priv *da7219;
-	unsigned int system_active, system_status;
-	int i, ret;
+	int ret;
 
 	da7219 = devm_kzalloc(dev, sizeof(struct da7219_priv),
 			      GFP_KERNEL);
@@ -2583,37 +2619,6 @@ static int da7219_i2c_probe(struct i2c_client *i2c,
 		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);
-
-	regcache_cache_bypass(da7219->regmap, false);
-
 	/* Retrieve DT/ACPI/Platform data */
 	da7219->pdata = dev_get_platdata(dev);
 	if (!da7219->pdata)
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 3/3] ASoC: da7219: Fix clock handling around codec level probe
  2020-08-11 16:57 [PATCH 0/3] ASoC: da7219: Reorganise device/codec level probe/remove Adam Thomson
  2020-08-11 16:57 ` [PATCH 1/3] ASoC: da7219: Move required devm_* allocations to device level code Adam Thomson
  2020-08-11 16:57 ` [PATCH 2/3] ASoC: da7219: Move soft reset handling to codec level probe Adam Thomson
@ 2020-08-11 16:57 ` Adam Thomson
  2020-08-18 16:38 ` [PATCH 0/3] ASoC: da7219: Reorganise device/codec level probe/remove Zhi, Yong
  2020-08-18 16:55 ` Mark Brown
  4 siblings, 0 replies; 7+ messages in thread
From: Adam Thomson @ 2020-08-11 16:57 UTC (permalink / raw)
  To: Mark Brown, Takashi Iwai, Liam Girdwood, Jaroslav Kysela
  Cc: Yong Zhi, Pierre-Louis Bossart, alsa-devel, linux-kernel,
	Support Opensource

Previously the driver would use devm_* related functions at
the codec level probe() to allocate clock resources for MCLK
and the DAI clocks exposed by the device. This caused issues
when registering clocks on a re-probe (no device level
remove/prove involved) as the devm_* resources were never
freed up so the clocks were still registered from the previous
codec level probe().

This commit updates the clock handling for MCLK usage and DAI
clock provision to fix this discrepancy and allow the codec level
probe/remove functionality to operate as intended.

Signed-off-by: Adam Thomson <Adam.Thomson.Opensource@diasemi.com>
---
 sound/soc/codecs/da7219.c | 96 +++++++++++++++++++++++++++++++++++------------
 sound/soc/codecs/da7219.h |  1 +
 2 files changed, 72 insertions(+), 25 deletions(-)

diff --git a/sound/soc/codecs/da7219.c b/sound/soc/codecs/da7219.c
index 0d1c70f8..ddd422c 100644
--- a/sound/soc/codecs/da7219.c
+++ b/sound/soc/codecs/da7219.c
@@ -2115,14 +2115,26 @@ static int da7219_bclk_set_rate(struct clk_hw *hw, unsigned long rate,
 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];
 
@@ -2158,22 +2170,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;
@@ -2183,21 +2193,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)
@@ -2462,7 +2509,7 @@ static int da7219_probe(struct snd_soc_component *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);
@@ -2475,7 +2522,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,
@@ -2512,10 +2559,16 @@ 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);
@@ -2526,18 +2579,11 @@ 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);
diff --git a/sound/soc/codecs/da7219.h b/sound/soc/codecs/da7219.h
index 88b67fe..94af88f 100644
--- a/sound/soc/codecs/da7219.h
+++ b/sound/soc/codecs/da7219.h
@@ -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];
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* RE: [PATCH 0/3] ASoC: da7219: Reorganise device/codec level probe/remove
  2020-08-11 16:57 [PATCH 0/3] ASoC: da7219: Reorganise device/codec level probe/remove Adam Thomson
                   ` (2 preceding siblings ...)
  2020-08-11 16:57 ` [PATCH 3/3] ASoC: da7219: Fix clock handling around " Adam Thomson
@ 2020-08-18 16:38 ` Zhi, Yong
  2020-08-18 17:16   ` Adam Thomson
  2020-08-18 16:55 ` Mark Brown
  4 siblings, 1 reply; 7+ messages in thread
From: Zhi, Yong @ 2020-08-18 16:38 UTC (permalink / raw)
  To: Adam Thomson, Mark Brown, Takashi Iwai, Liam Girdwood, Jaroslav Kysela
  Cc: Pierre-Louis Bossart, alsa-devel, linux-kernel, Support Opensource

Hi, Adam,

> -----Original Message-----
> From: Adam Thomson <Adam.Thomson.Opensource@diasemi.com>
> Sent: Tuesday, August 11, 2020 11:57 AM
> To: Mark Brown <broonie@kernel.org>; Takashi Iwai <tiwai@suse.com>; Liam
> Girdwood <lgirdwood@gmail.com>; Jaroslav Kysela <perex@perex.cz>
> Cc: Zhi, Yong <yong.zhi@intel.com>; Pierre-Louis Bossart <pierre-
> louis.bossart@linux.intel.com>; alsa-devel@alsa-project.org; linux-
> kernel@vger.kernel.org; Support Opensource
> <support.opensource@diasemi.com>
> Subject: [PATCH 0/3] ASoC: da7219: Reorganise device/codec level
> probe/remove
> 
> 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.
> 

Just to let you know that I tested this series on the JSL platform, the original issue was resolved, also sanity checked basic use case like plug/unplug and
suspend/resume, no regression found.

thanks,
yong
> 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


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 0/3] ASoC: da7219: Reorganise device/codec level probe/remove
  2020-08-11 16:57 [PATCH 0/3] ASoC: da7219: Reorganise device/codec level probe/remove Adam Thomson
                   ` (3 preceding siblings ...)
  2020-08-18 16:38 ` [PATCH 0/3] ASoC: da7219: Reorganise device/codec level probe/remove Zhi, Yong
@ 2020-08-18 16:55 ` Mark Brown
  4 siblings, 0 replies; 7+ messages in thread
From: Mark Brown @ 2020-08-18 16:55 UTC (permalink / raw)
  To: Jaroslav Kysela, Liam Girdwood, Adam Thomson, Takashi Iwai
  Cc: Pierre-Louis Bossart, linux-kernel, Yong Zhi, Support Opensource,
	alsa-devel

On Tue, 11 Aug 2020 17:57:22 +0100, Adam Thomson wrote:
> 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.
> 
> [...]

Applied to

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next

Thanks!

[1/3] ASoC: da7219: Move required devm_* allocations to device level code
      commit: 21f279f34c212e82f0330697394840898908f7a6
[2/3] ASoC: da7219: Move soft reset handling to codec level probe
      commit: aa5b18d1c29023b315073661b74c67f91bf2f27c
[3/3] ASoC: da7219: Fix clock handling around codec level probe
      commit: 78013a1cf2971684775f6956d5666237ac53a1aa

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

^ permalink raw reply	[flat|nested] 7+ messages in thread

* RE: [PATCH 0/3] ASoC: da7219: Reorganise device/codec level probe/remove
  2020-08-18 16:38 ` [PATCH 0/3] ASoC: da7219: Reorganise device/codec level probe/remove Zhi, Yong
@ 2020-08-18 17:16   ` Adam Thomson
  0 siblings, 0 replies; 7+ messages in thread
From: Adam Thomson @ 2020-08-18 17:16 UTC (permalink / raw)
  To: Zhi, Yong, Adam Thomson, Mark Brown, Takashi Iwai, Liam Girdwood,
	Jaroslav Kysela
  Cc: Pierre-Louis Bossart, alsa-devel, linux-kernel, Support Opensource

On 18 August 2020 17:39, Zhi, Yong wrote:

> > 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.
> >
> 
> Just to let you know that I tested this series on the JSL platform, the original issue
> was resolved, also sanity checked basic use case like plug/unplug and
> suspend/resume, no regression found.
> 
> thanks,
> yong

That's great. Many thanks for verifying your side.

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2020-08-18 17:17 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-08-11 16:57 [PATCH 0/3] ASoC: da7219: Reorganise device/codec level probe/remove Adam Thomson
2020-08-11 16:57 ` [PATCH 1/3] ASoC: da7219: Move required devm_* allocations to device level code Adam Thomson
2020-08-11 16:57 ` [PATCH 2/3] ASoC: da7219: Move soft reset handling to codec level probe Adam Thomson
2020-08-11 16:57 ` [PATCH 3/3] ASoC: da7219: Fix clock handling around " Adam Thomson
2020-08-18 16:38 ` [PATCH 0/3] ASoC: da7219: Reorganise device/codec level probe/remove Zhi, Yong
2020-08-18 17:16   ` Adam Thomson
2020-08-18 16:55 ` Mark Brown

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).