All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 1/2] ASoC: tas5805m: rework to avoid scheduling while atomic.
  2023-02-04  7:55 ` Daniel Beer
@ 2022-10-27  8:28   ` Daniel Beer
  -1 siblings, 0 replies; 14+ messages in thread
From: Daniel Beer @ 2022-10-27  8:28 UTC (permalink / raw)
  To: alsa-devel; +Cc: linux-kernel, Daniel Beer, Andy Liu, Mark Brown

There's some setup we need to do in order to get the DSP initialized,
and this can't be done until a bit-clock is ready. In an earlier version
of this driver, this work was done in a DAPM callback.

The DAPM callback doesn't guarantee that the bit-clock is running, so
the work was moved instead to the trigger callback. Unfortunately this
callback runs in atomic context, and the setup code needs to do I2C
transactions.

Here we use a work_struct to kick off the setup in a thread instead.

Fixes: ec45268467f4 ("ASoC: add support for TAS5805M digital amplifier")
Signed-off-by: Daniel Beer <daniel.beer@igorinstitute.com>
---
 sound/soc/codecs/tas5805m.c | 128 ++++++++++++++++++++++++------------
 1 file changed, 87 insertions(+), 41 deletions(-)

diff --git a/sound/soc/codecs/tas5805m.c b/sound/soc/codecs/tas5805m.c
index beb4ec629a03..6e2edf045446 100644
--- a/sound/soc/codecs/tas5805m.c
+++ b/sound/soc/codecs/tas5805m.c
@@ -154,6 +154,7 @@ static const uint32_t tas5805m_volume[] = {
 #define TAS5805M_VOLUME_MIN	0
 
 struct tas5805m_priv {
+	struct i2c_client		*i2c;
 	struct regulator		*pvdd;
 	struct gpio_desc		*gpio_pdn_n;
 
@@ -165,6 +166,9 @@ struct tas5805m_priv {
 	int				vol[2];
 	bool				is_powered;
 	bool				is_muted;
+
+	struct work_struct		work;
+	struct mutex			lock;
 };
 
 static void set_dsp_scale(struct regmap *rm, int offset, int vol)
@@ -181,13 +185,11 @@ static void set_dsp_scale(struct regmap *rm, int offset, int vol)
 	regmap_bulk_write(rm, offset, v, ARRAY_SIZE(v));
 }
 
-static void tas5805m_refresh(struct snd_soc_component *component)
+static void tas5805m_refresh(struct tas5805m_priv *tas5805m)
 {
-	struct tas5805m_priv *tas5805m =
-		snd_soc_component_get_drvdata(component);
 	struct regmap *rm = tas5805m->regmap;
 
-	dev_dbg(component->dev, "refresh: is_muted=%d, vol=%d/%d\n",
+	dev_dbg(&tas5805m->i2c->dev, "refresh: is_muted=%d, vol=%d/%d\n",
 		tas5805m->is_muted, tas5805m->vol[0], tas5805m->vol[1]);
 
 	regmap_write(rm, REG_PAGE, 0x00);
@@ -226,8 +228,11 @@ static int tas5805m_vol_get(struct snd_kcontrol *kcontrol,
 	struct tas5805m_priv *tas5805m =
 		snd_soc_component_get_drvdata(component);
 
+	mutex_lock(&tas5805m->lock);
 	ucontrol->value.integer.value[0] = tas5805m->vol[0];
 	ucontrol->value.integer.value[1] = tas5805m->vol[1];
+	mutex_unlock(&tas5805m->lock);
+
 	return 0;
 }
 
@@ -243,11 +248,13 @@ static int tas5805m_vol_put(struct snd_kcontrol *kcontrol,
 		snd_soc_kcontrol_component(kcontrol);
 	struct tas5805m_priv *tas5805m =
 		snd_soc_component_get_drvdata(component);
+	int ret = 0;
 
 	if (!(volume_is_valid(ucontrol->value.integer.value[0]) &&
 	      volume_is_valid(ucontrol->value.integer.value[1])))
 		return -EINVAL;
 
+	mutex_lock(&tas5805m->lock);
 	if (tas5805m->vol[0] != ucontrol->value.integer.value[0] ||
 	    tas5805m->vol[1] != ucontrol->value.integer.value[1]) {
 		tas5805m->vol[0] = ucontrol->value.integer.value[0];
@@ -256,11 +263,12 @@ static int tas5805m_vol_put(struct snd_kcontrol *kcontrol,
 			tas5805m->vol[0], tas5805m->vol[1],
 			tas5805m->is_powered);
 		if (tas5805m->is_powered)
-			tas5805m_refresh(component);
-		return 1;
+			tas5805m_refresh(tas5805m);
+		ret = 1;
 	}
+	mutex_unlock(&tas5805m->lock);
 
-	return 0;
+	return ret;
 }
 
 static const struct snd_kcontrol_new tas5805m_snd_controls[] = {
@@ -294,54 +302,83 @@ static int tas5805m_trigger(struct snd_pcm_substream *substream, int cmd,
 	struct snd_soc_component *component = dai->component;
 	struct tas5805m_priv *tas5805m =
 		snd_soc_component_get_drvdata(component);
-	struct regmap *rm = tas5805m->regmap;
-	unsigned int chan, global1, global2;
 
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_START:
 	case SNDRV_PCM_TRIGGER_RESUME:
 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-		dev_dbg(component->dev, "DSP startup\n");
-
-		/* We mustn't issue any I2C transactions until the I2S
-		 * clock is stable. Furthermore, we must allow a 5ms
-		 * delay after the first set of register writes to
-		 * allow the DSP to boot before configuring it.
-		 */
-		usleep_range(5000, 10000);
-		send_cfg(rm, dsp_cfg_preboot,
-			ARRAY_SIZE(dsp_cfg_preboot));
-		usleep_range(5000, 15000);
-		send_cfg(rm, tas5805m->dsp_cfg_data,
-			tas5805m->dsp_cfg_len);
-
-		tas5805m->is_powered = true;
-		tas5805m_refresh(component);
+		dev_dbg(component->dev, "clock start\n");
+		schedule_work(&tas5805m->work);
 		break;
 
 	case SNDRV_PCM_TRIGGER_STOP:
 	case SNDRV_PCM_TRIGGER_SUSPEND:
 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-		dev_dbg(component->dev, "DSP shutdown\n");
+		break;
 
-		tas5805m->is_powered = false;
+	default:
+		return -EINVAL;
+	}
 
-		regmap_write(rm, REG_PAGE, 0x00);
-		regmap_write(rm, REG_BOOK, 0x00);
+	return 0;
+}
 
-		regmap_read(rm, REG_CHAN_FAULT, &chan);
-		regmap_read(rm, REG_GLOBAL_FAULT1, &global1);
-		regmap_read(rm, REG_GLOBAL_FAULT2, &global2);
+static void do_work(struct work_struct *work)
+{
+	struct tas5805m_priv *tas5805m =
+	       container_of(work, struct tas5805m_priv, work);
+	struct regmap *rm = tas5805m->regmap;
 
-		dev_dbg(component->dev,
-			"fault regs: CHAN=%02x, GLOBAL1=%02x, GLOBAL2=%02x\n",
-			chan, global1, global2);
+	dev_dbg(&tas5805m->i2c->dev, "DSP startup\n");
 
-		regmap_write(rm, REG_DEVICE_CTRL_2, DCTRL2_MODE_HIZ);
-		break;
+	mutex_lock(&tas5805m->lock);
+	/* We mustn't issue any I2C transactions until the I2S
+	 * clock is stable. Furthermore, we must allow a 5ms
+	 * delay after the first set of register writes to
+	 * allow the DSP to boot before configuring it.
+	 */
+	usleep_range(5000, 10000);
+	send_cfg(rm, dsp_cfg_preboot, ARRAY_SIZE(dsp_cfg_preboot));
+	usleep_range(5000, 15000);
+	send_cfg(rm, tas5805m->dsp_cfg_data, tas5805m->dsp_cfg_len);
+
+	tas5805m->is_powered = true;
+	tas5805m_refresh(tas5805m);
+	mutex_unlock(&tas5805m->lock);
+}
 
-	default:
-		return -EINVAL;
+static int tas5805m_dac_event(struct snd_soc_dapm_widget *w,
+			      struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
+	struct tas5805m_priv *tas5805m =
+		snd_soc_component_get_drvdata(component);
+	struct regmap *rm = tas5805m->regmap;
+
+	if (event & SND_SOC_DAPM_PRE_PMD) {
+		unsigned int chan, global1, global2;
+
+		dev_dbg(component->dev, "DSP shutdown\n");
+		cancel_work_sync(&tas5805m->work);
+
+		mutex_lock(&tas5805m->lock);
+		if (tas5805m->is_powered) {
+			tas5805m->is_powered = false;
+
+			regmap_write(rm, REG_PAGE, 0x00);
+			regmap_write(rm, REG_BOOK, 0x00);
+
+			regmap_read(rm, REG_CHAN_FAULT, &chan);
+			regmap_read(rm, REG_GLOBAL_FAULT1, &global1);
+			regmap_read(rm, REG_GLOBAL_FAULT2, &global2);
+
+			dev_dbg(component->dev, "fault regs: CHAN=%02x, "
+				"GLOBAL1=%02x, GLOBAL2=%02x\n",
+				chan, global1, global2);
+
+			regmap_write(rm, REG_DEVICE_CTRL_2, DCTRL2_MODE_HIZ);
+		}
+		mutex_unlock(&tas5805m->lock);
 	}
 
 	return 0;
@@ -354,7 +391,8 @@ static const struct snd_soc_dapm_route tas5805m_audio_map[] = {
 
 static const struct snd_soc_dapm_widget tas5805m_dapm_widgets[] = {
 	SND_SOC_DAPM_AIF_IN("DAC IN", "Playback", 0, SND_SOC_NOPM, 0, 0),
-	SND_SOC_DAPM_DAC("DAC", NULL, SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_DAC_E("DAC", NULL, SND_SOC_NOPM, 0, 0,
+		tas5805m_dac_event, SND_SOC_DAPM_PRE_PMD),
 	SND_SOC_DAPM_OUTPUT("OUT")
 };
 
@@ -375,11 +413,14 @@ static int tas5805m_mute(struct snd_soc_dai *dai, int mute, int direction)
 	struct tas5805m_priv *tas5805m =
 		snd_soc_component_get_drvdata(component);
 
+	mutex_lock(&tas5805m->lock);
 	dev_dbg(component->dev, "set mute=%d (is_powered=%d)\n",
 		mute, tas5805m->is_powered);
+
 	tas5805m->is_muted = mute;
 	if (tas5805m->is_powered)
-		tas5805m_refresh(component);
+		tas5805m_refresh(tas5805m);
+	mutex_unlock(&tas5805m->lock);
 
 	return 0;
 }
@@ -434,6 +475,7 @@ static int tas5805m_i2c_probe(struct i2c_client *i2c)
 	if (!tas5805m)
 		return -ENOMEM;
 
+	tas5805m->i2c = i2c;
 	tas5805m->pvdd = devm_regulator_get(dev, "pvdd");
 	if (IS_ERR(tas5805m->pvdd)) {
 		dev_err(dev, "failed to get pvdd supply: %ld\n",
@@ -507,6 +549,9 @@ static int tas5805m_i2c_probe(struct i2c_client *i2c)
 	gpiod_set_value(tas5805m->gpio_pdn_n, 1);
 	usleep_range(10000, 15000);
 
+	INIT_WORK(&tas5805m->work, do_work);
+	mutex_init(&tas5805m->lock);
+
 	/* Don't register through devm. We need to be able to unregister
 	 * the component prior to deasserting PDN#
 	 */
@@ -527,6 +572,7 @@ static void tas5805m_i2c_remove(struct i2c_client *i2c)
 	struct device *dev = &i2c->dev;
 	struct tas5805m_priv *tas5805m = dev_get_drvdata(dev);
 
+	cancel_work_sync(&tas5805m->work);
 	snd_soc_unregister_component(dev);
 	gpiod_set_value(tas5805m->gpio_pdn_n, 0);
 	usleep_range(10000, 15000);
-- 
2.38.1


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

* [PATCH v3 1/2] ASoC: tas5805m: rework to avoid scheduling while atomic.
@ 2022-10-27  8:28   ` Daniel Beer
  0 siblings, 0 replies; 14+ messages in thread
From: Daniel Beer @ 2022-10-27  8:28 UTC (permalink / raw)
  To: alsa-devel; +Cc: Andy Liu, Mark Brown, Daniel Beer, linux-kernel

There's some setup we need to do in order to get the DSP initialized,
and this can't be done until a bit-clock is ready. In an earlier version
of this driver, this work was done in a DAPM callback.

The DAPM callback doesn't guarantee that the bit-clock is running, so
the work was moved instead to the trigger callback. Unfortunately this
callback runs in atomic context, and the setup code needs to do I2C
transactions.

Here we use a work_struct to kick off the setup in a thread instead.

Fixes: ec45268467f4 ("ASoC: add support for TAS5805M digital amplifier")
Signed-off-by: Daniel Beer <daniel.beer@igorinstitute.com>
---
 sound/soc/codecs/tas5805m.c | 128 ++++++++++++++++++++++++------------
 1 file changed, 87 insertions(+), 41 deletions(-)

diff --git a/sound/soc/codecs/tas5805m.c b/sound/soc/codecs/tas5805m.c
index beb4ec629a03..6e2edf045446 100644
--- a/sound/soc/codecs/tas5805m.c
+++ b/sound/soc/codecs/tas5805m.c
@@ -154,6 +154,7 @@ static const uint32_t tas5805m_volume[] = {
 #define TAS5805M_VOLUME_MIN	0
 
 struct tas5805m_priv {
+	struct i2c_client		*i2c;
 	struct regulator		*pvdd;
 	struct gpio_desc		*gpio_pdn_n;
 
@@ -165,6 +166,9 @@ struct tas5805m_priv {
 	int				vol[2];
 	bool				is_powered;
 	bool				is_muted;
+
+	struct work_struct		work;
+	struct mutex			lock;
 };
 
 static void set_dsp_scale(struct regmap *rm, int offset, int vol)
@@ -181,13 +185,11 @@ static void set_dsp_scale(struct regmap *rm, int offset, int vol)
 	regmap_bulk_write(rm, offset, v, ARRAY_SIZE(v));
 }
 
-static void tas5805m_refresh(struct snd_soc_component *component)
+static void tas5805m_refresh(struct tas5805m_priv *tas5805m)
 {
-	struct tas5805m_priv *tas5805m =
-		snd_soc_component_get_drvdata(component);
 	struct regmap *rm = tas5805m->regmap;
 
-	dev_dbg(component->dev, "refresh: is_muted=%d, vol=%d/%d\n",
+	dev_dbg(&tas5805m->i2c->dev, "refresh: is_muted=%d, vol=%d/%d\n",
 		tas5805m->is_muted, tas5805m->vol[0], tas5805m->vol[1]);
 
 	regmap_write(rm, REG_PAGE, 0x00);
@@ -226,8 +228,11 @@ static int tas5805m_vol_get(struct snd_kcontrol *kcontrol,
 	struct tas5805m_priv *tas5805m =
 		snd_soc_component_get_drvdata(component);
 
+	mutex_lock(&tas5805m->lock);
 	ucontrol->value.integer.value[0] = tas5805m->vol[0];
 	ucontrol->value.integer.value[1] = tas5805m->vol[1];
+	mutex_unlock(&tas5805m->lock);
+
 	return 0;
 }
 
@@ -243,11 +248,13 @@ static int tas5805m_vol_put(struct snd_kcontrol *kcontrol,
 		snd_soc_kcontrol_component(kcontrol);
 	struct tas5805m_priv *tas5805m =
 		snd_soc_component_get_drvdata(component);
+	int ret = 0;
 
 	if (!(volume_is_valid(ucontrol->value.integer.value[0]) &&
 	      volume_is_valid(ucontrol->value.integer.value[1])))
 		return -EINVAL;
 
+	mutex_lock(&tas5805m->lock);
 	if (tas5805m->vol[0] != ucontrol->value.integer.value[0] ||
 	    tas5805m->vol[1] != ucontrol->value.integer.value[1]) {
 		tas5805m->vol[0] = ucontrol->value.integer.value[0];
@@ -256,11 +263,12 @@ static int tas5805m_vol_put(struct snd_kcontrol *kcontrol,
 			tas5805m->vol[0], tas5805m->vol[1],
 			tas5805m->is_powered);
 		if (tas5805m->is_powered)
-			tas5805m_refresh(component);
-		return 1;
+			tas5805m_refresh(tas5805m);
+		ret = 1;
 	}
+	mutex_unlock(&tas5805m->lock);
 
-	return 0;
+	return ret;
 }
 
 static const struct snd_kcontrol_new tas5805m_snd_controls[] = {
@@ -294,54 +302,83 @@ static int tas5805m_trigger(struct snd_pcm_substream *substream, int cmd,
 	struct snd_soc_component *component = dai->component;
 	struct tas5805m_priv *tas5805m =
 		snd_soc_component_get_drvdata(component);
-	struct regmap *rm = tas5805m->regmap;
-	unsigned int chan, global1, global2;
 
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_START:
 	case SNDRV_PCM_TRIGGER_RESUME:
 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-		dev_dbg(component->dev, "DSP startup\n");
-
-		/* We mustn't issue any I2C transactions until the I2S
-		 * clock is stable. Furthermore, we must allow a 5ms
-		 * delay after the first set of register writes to
-		 * allow the DSP to boot before configuring it.
-		 */
-		usleep_range(5000, 10000);
-		send_cfg(rm, dsp_cfg_preboot,
-			ARRAY_SIZE(dsp_cfg_preboot));
-		usleep_range(5000, 15000);
-		send_cfg(rm, tas5805m->dsp_cfg_data,
-			tas5805m->dsp_cfg_len);
-
-		tas5805m->is_powered = true;
-		tas5805m_refresh(component);
+		dev_dbg(component->dev, "clock start\n");
+		schedule_work(&tas5805m->work);
 		break;
 
 	case SNDRV_PCM_TRIGGER_STOP:
 	case SNDRV_PCM_TRIGGER_SUSPEND:
 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-		dev_dbg(component->dev, "DSP shutdown\n");
+		break;
 
-		tas5805m->is_powered = false;
+	default:
+		return -EINVAL;
+	}
 
-		regmap_write(rm, REG_PAGE, 0x00);
-		regmap_write(rm, REG_BOOK, 0x00);
+	return 0;
+}
 
-		regmap_read(rm, REG_CHAN_FAULT, &chan);
-		regmap_read(rm, REG_GLOBAL_FAULT1, &global1);
-		regmap_read(rm, REG_GLOBAL_FAULT2, &global2);
+static void do_work(struct work_struct *work)
+{
+	struct tas5805m_priv *tas5805m =
+	       container_of(work, struct tas5805m_priv, work);
+	struct regmap *rm = tas5805m->regmap;
 
-		dev_dbg(component->dev,
-			"fault regs: CHAN=%02x, GLOBAL1=%02x, GLOBAL2=%02x\n",
-			chan, global1, global2);
+	dev_dbg(&tas5805m->i2c->dev, "DSP startup\n");
 
-		regmap_write(rm, REG_DEVICE_CTRL_2, DCTRL2_MODE_HIZ);
-		break;
+	mutex_lock(&tas5805m->lock);
+	/* We mustn't issue any I2C transactions until the I2S
+	 * clock is stable. Furthermore, we must allow a 5ms
+	 * delay after the first set of register writes to
+	 * allow the DSP to boot before configuring it.
+	 */
+	usleep_range(5000, 10000);
+	send_cfg(rm, dsp_cfg_preboot, ARRAY_SIZE(dsp_cfg_preboot));
+	usleep_range(5000, 15000);
+	send_cfg(rm, tas5805m->dsp_cfg_data, tas5805m->dsp_cfg_len);
+
+	tas5805m->is_powered = true;
+	tas5805m_refresh(tas5805m);
+	mutex_unlock(&tas5805m->lock);
+}
 
-	default:
-		return -EINVAL;
+static int tas5805m_dac_event(struct snd_soc_dapm_widget *w,
+			      struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
+	struct tas5805m_priv *tas5805m =
+		snd_soc_component_get_drvdata(component);
+	struct regmap *rm = tas5805m->regmap;
+
+	if (event & SND_SOC_DAPM_PRE_PMD) {
+		unsigned int chan, global1, global2;
+
+		dev_dbg(component->dev, "DSP shutdown\n");
+		cancel_work_sync(&tas5805m->work);
+
+		mutex_lock(&tas5805m->lock);
+		if (tas5805m->is_powered) {
+			tas5805m->is_powered = false;
+
+			regmap_write(rm, REG_PAGE, 0x00);
+			regmap_write(rm, REG_BOOK, 0x00);
+
+			regmap_read(rm, REG_CHAN_FAULT, &chan);
+			regmap_read(rm, REG_GLOBAL_FAULT1, &global1);
+			regmap_read(rm, REG_GLOBAL_FAULT2, &global2);
+
+			dev_dbg(component->dev, "fault regs: CHAN=%02x, "
+				"GLOBAL1=%02x, GLOBAL2=%02x\n",
+				chan, global1, global2);
+
+			regmap_write(rm, REG_DEVICE_CTRL_2, DCTRL2_MODE_HIZ);
+		}
+		mutex_unlock(&tas5805m->lock);
 	}
 
 	return 0;
@@ -354,7 +391,8 @@ static const struct snd_soc_dapm_route tas5805m_audio_map[] = {
 
 static const struct snd_soc_dapm_widget tas5805m_dapm_widgets[] = {
 	SND_SOC_DAPM_AIF_IN("DAC IN", "Playback", 0, SND_SOC_NOPM, 0, 0),
-	SND_SOC_DAPM_DAC("DAC", NULL, SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_DAC_E("DAC", NULL, SND_SOC_NOPM, 0, 0,
+		tas5805m_dac_event, SND_SOC_DAPM_PRE_PMD),
 	SND_SOC_DAPM_OUTPUT("OUT")
 };
 
@@ -375,11 +413,14 @@ static int tas5805m_mute(struct snd_soc_dai *dai, int mute, int direction)
 	struct tas5805m_priv *tas5805m =
 		snd_soc_component_get_drvdata(component);
 
+	mutex_lock(&tas5805m->lock);
 	dev_dbg(component->dev, "set mute=%d (is_powered=%d)\n",
 		mute, tas5805m->is_powered);
+
 	tas5805m->is_muted = mute;
 	if (tas5805m->is_powered)
-		tas5805m_refresh(component);
+		tas5805m_refresh(tas5805m);
+	mutex_unlock(&tas5805m->lock);
 
 	return 0;
 }
@@ -434,6 +475,7 @@ static int tas5805m_i2c_probe(struct i2c_client *i2c)
 	if (!tas5805m)
 		return -ENOMEM;
 
+	tas5805m->i2c = i2c;
 	tas5805m->pvdd = devm_regulator_get(dev, "pvdd");
 	if (IS_ERR(tas5805m->pvdd)) {
 		dev_err(dev, "failed to get pvdd supply: %ld\n",
@@ -507,6 +549,9 @@ static int tas5805m_i2c_probe(struct i2c_client *i2c)
 	gpiod_set_value(tas5805m->gpio_pdn_n, 1);
 	usleep_range(10000, 15000);
 
+	INIT_WORK(&tas5805m->work, do_work);
+	mutex_init(&tas5805m->lock);
+
 	/* Don't register through devm. We need to be able to unregister
 	 * the component prior to deasserting PDN#
 	 */
@@ -527,6 +572,7 @@ static void tas5805m_i2c_remove(struct i2c_client *i2c)
 	struct device *dev = &i2c->dev;
 	struct tas5805m_priv *tas5805m = dev_get_drvdata(dev);
 
+	cancel_work_sync(&tas5805m->work);
 	snd_soc_unregister_component(dev);
 	gpiod_set_value(tas5805m->gpio_pdn_n, 0);
 	usleep_range(10000, 15000);
-- 
2.38.1


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

* [PATCH v3 2/2] ASoC: tas5805m: add missing page switch.
  2023-02-04  7:55 ` Daniel Beer
@ 2022-10-27  8:38   ` Daniel Beer
  -1 siblings, 0 replies; 14+ messages in thread
From: Daniel Beer @ 2022-10-27  8:38 UTC (permalink / raw)
  To: alsa-devel; +Cc: linux-kernel, Daniel Beer, Andy Liu, Mark Brown

In tas5805m_refresh, we switch pages to update the DSP volume control,
but we need to switch back to page 0 before trying to alter the
soft-mute control. This latter page-switch was missing.

Fixes: ec45268467f4 ("ASoC: add support for TAS5805M digital amplifier")
Signed-off-by: Daniel Beer <daniel.beer@igorinstitute.com>
---
 sound/soc/codecs/tas5805m.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/sound/soc/codecs/tas5805m.c b/sound/soc/codecs/tas5805m.c
index 6e2edf045446..4e38eb7acea1 100644
--- a/sound/soc/codecs/tas5805m.c
+++ b/sound/soc/codecs/tas5805m.c
@@ -203,6 +203,9 @@ static void tas5805m_refresh(struct tas5805m_priv *tas5805m)
 	set_dsp_scale(rm, 0x24, tas5805m->vol[0]);
 	set_dsp_scale(rm, 0x28, tas5805m->vol[1]);
 
+	regmap_write(rm, REG_PAGE, 0x00);
+	regmap_write(rm, REG_BOOK, 0x00);
+
 	/* Set/clear digital soft-mute */
 	regmap_write(rm, REG_DEVICE_CTRL_2,
 		(tas5805m->is_muted ? DCTRL2_MUTE : 0) |
-- 
2.38.1


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

* [PATCH v3 2/2] ASoC: tas5805m: add missing page switch.
@ 2022-10-27  8:38   ` Daniel Beer
  0 siblings, 0 replies; 14+ messages in thread
From: Daniel Beer @ 2022-10-27  8:38 UTC (permalink / raw)
  To: alsa-devel; +Cc: Andy Liu, Mark Brown, Daniel Beer, linux-kernel

In tas5805m_refresh, we switch pages to update the DSP volume control,
but we need to switch back to page 0 before trying to alter the
soft-mute control. This latter page-switch was missing.

Fixes: ec45268467f4 ("ASoC: add support for TAS5805M digital amplifier")
Signed-off-by: Daniel Beer <daniel.beer@igorinstitute.com>
---
 sound/soc/codecs/tas5805m.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/sound/soc/codecs/tas5805m.c b/sound/soc/codecs/tas5805m.c
index 6e2edf045446..4e38eb7acea1 100644
--- a/sound/soc/codecs/tas5805m.c
+++ b/sound/soc/codecs/tas5805m.c
@@ -203,6 +203,9 @@ static void tas5805m_refresh(struct tas5805m_priv *tas5805m)
 	set_dsp_scale(rm, 0x24, tas5805m->vol[0]);
 	set_dsp_scale(rm, 0x28, tas5805m->vol[1]);
 
+	regmap_write(rm, REG_PAGE, 0x00);
+	regmap_write(rm, REG_BOOK, 0x00);
+
 	/* Set/clear digital soft-mute */
 	regmap_write(rm, REG_DEVICE_CTRL_2,
 		(tas5805m->is_muted ? DCTRL2_MUTE : 0) |
-- 
2.38.1


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

* [PATCH v3 0/2] Two bug fixes for tas5805m codec driver
@ 2023-02-04  7:55 ` Daniel Beer
  0 siblings, 0 replies; 14+ messages in thread
From: Daniel Beer @ 2023-02-04  7:55 UTC (permalink / raw)
  To: alsa-devel; +Cc: linux-kernel, Daniel Beer, Andy Liu, Mark Brown

This pair of patches fixes two issues which crept in while revising the
original submission, at a time when I no longer had access to test
hardware.

The fixes here have been tested and verified on hardware.

Changes v2 -> v3:
  - Resubmit with cover letter

Changes v1 -> v2:
  - Fix issue reported by kernel test robot

Daniel Beer (2):
  ASoC: tas5805m: rework to avoid scheduling while atomic.
  ASoC: tas5805m: add missing page switch.

 sound/soc/codecs/tas5805m.c | 131 +++++++++++++++++++++++++-----------
 1 file changed, 90 insertions(+), 41 deletions(-)

-- 
2.38.1


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

* [PATCH v3 0/2] Two bug fixes for tas5805m codec driver
@ 2023-02-04  7:55 ` Daniel Beer
  0 siblings, 0 replies; 14+ messages in thread
From: Daniel Beer @ 2023-02-04  7:55 UTC (permalink / raw)
  To: alsa-devel; +Cc: Andy Liu, Mark Brown, Daniel Beer, linux-kernel

This pair of patches fixes two issues which crept in while revising the
original submission, at a time when I no longer had access to test
hardware.

The fixes here have been tested and verified on hardware.

Changes v2 -> v3:
  - Resubmit with cover letter

Changes v1 -> v2:
  - Fix issue reported by kernel test robot

Daniel Beer (2):
  ASoC: tas5805m: rework to avoid scheduling while atomic.
  ASoC: tas5805m: add missing page switch.

 sound/soc/codecs/tas5805m.c | 131 +++++++++++++++++++++++++-----------
 1 file changed, 90 insertions(+), 41 deletions(-)

-- 
2.38.1


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

* Re: [PATCH v3 2/2] ASoC: tas5805m: add missing page switch.
  2022-10-27  8:38   ` Daniel Beer
@ 2023-02-06 13:11     ` Mark Brown
  -1 siblings, 0 replies; 14+ messages in thread
From: Mark Brown @ 2023-02-06 13:11 UTC (permalink / raw)
  To: Daniel Beer; +Cc: alsa-devel, linux-kernel, Andy Liu

[-- Attachment #1: Type: text/plain, Size: 393 bytes --]

On Thu, Oct 27, 2022 at 09:38:38PM +1300, Daniel Beer wrote:
> In tas5805m_refresh, we switch pages to update the DSP volume control,
> but we need to switch back to page 0 before trying to alter the
> soft-mute control. This latter page-switch was missing.

You should just use the register windowing support in regmap, it will
take care of this for you, avoiding any further similar errors.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

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

* Re: [PATCH v3 2/2] ASoC: tas5805m: add missing page switch.
@ 2023-02-06 13:11     ` Mark Brown
  0 siblings, 0 replies; 14+ messages in thread
From: Mark Brown @ 2023-02-06 13:11 UTC (permalink / raw)
  To: Daniel Beer; +Cc: Andy Liu, alsa-devel, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 393 bytes --]

On Thu, Oct 27, 2022 at 09:38:38PM +1300, Daniel Beer wrote:
> In tas5805m_refresh, we switch pages to update the DSP volume control,
> but we need to switch back to page 0 before trying to alter the
> soft-mute control. This latter page-switch was missing.

You should just use the register windowing support in regmap, it will
take care of this for you, avoiding any further similar errors.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

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

* Re: [PATCH v3 2/2] ASoC: tas5805m: add missing page switch.
  2023-02-06 13:11     ` Mark Brown
@ 2023-02-06 20:45       ` Daniel Beer
  -1 siblings, 0 replies; 14+ messages in thread
From: Daniel Beer @ 2023-02-06 20:45 UTC (permalink / raw)
  To: Mark Brown; +Cc: alsa-devel, linux-kernel, Andy Liu

On Mon, Feb 06, 2023 at 01:11:09PM +0000, Mark Brown wrote:
> On Thu, Oct 27, 2022 at 09:38:38PM +1300, Daniel Beer wrote:
> > In tas5805m_refresh, we switch pages to update the DSP volume control,
> > but we need to switch back to page 0 before trying to alter the
> > soft-mute control. This latter page-switch was missing.
> 
> You should just use the register windowing support in regmap, it will
> take care of this for you, avoiding any further similar errors.

Hi Mark,

Thanks for reviewing.

We did discuss this a while back when the driver first went in.
Unfortunately the vendor software tools provide configuration for the
part in the form of a sequence of raw register writes, including
explicit page changes:

    https://lore.kernel.org/lkml/Yd85bjKEX9JnoOlI@sirena.org.uk/

Aside from this, I have two other practical issues.

The first is that I'm not sure how exactly to implement the paging
scheme in terms of regmap_range_cfg (assuming this is what you're
referring to). This chip has multi-level paging (books/pages), with the
book selection register itself requiring paging to access. A sequence of
three register writes is therefore required in the general case to
select the correct page. I had a quick look at a random assortment of
existing regmap_range_cfg uses, but didn't find anything that looked
like the same problem.

Secondly, the patches as submitted here have been tested, but I don't
currently have access to hardware. I'm very hesitant to make a
significant change without retesting and leave the driver in a broken
state again.

Cheers,
Daniel

-- 
Daniel Beer
Firmware Engineer at Igor Institute
daniel.beer@igorinstitute.com or +64-27-420-8101
Offices in Seattle, San Francisco, and Vancouver BC or (206) 494-3312

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

* Re: [PATCH v3 2/2] ASoC: tas5805m: add missing page switch.
@ 2023-02-06 20:45       ` Daniel Beer
  0 siblings, 0 replies; 14+ messages in thread
From: Daniel Beer @ 2023-02-06 20:45 UTC (permalink / raw)
  To: Mark Brown; +Cc: Andy Liu, alsa-devel, linux-kernel

On Mon, Feb 06, 2023 at 01:11:09PM +0000, Mark Brown wrote:
> On Thu, Oct 27, 2022 at 09:38:38PM +1300, Daniel Beer wrote:
> > In tas5805m_refresh, we switch pages to update the DSP volume control,
> > but we need to switch back to page 0 before trying to alter the
> > soft-mute control. This latter page-switch was missing.
> 
> You should just use the register windowing support in regmap, it will
> take care of this for you, avoiding any further similar errors.

Hi Mark,

Thanks for reviewing.

We did discuss this a while back when the driver first went in.
Unfortunately the vendor software tools provide configuration for the
part in the form of a sequence of raw register writes, including
explicit page changes:

    https://lore.kernel.org/lkml/Yd85bjKEX9JnoOlI@sirena.org.uk/

Aside from this, I have two other practical issues.

The first is that I'm not sure how exactly to implement the paging
scheme in terms of regmap_range_cfg (assuming this is what you're
referring to). This chip has multi-level paging (books/pages), with the
book selection register itself requiring paging to access. A sequence of
three register writes is therefore required in the general case to
select the correct page. I had a quick look at a random assortment of
existing regmap_range_cfg uses, but didn't find anything that looked
like the same problem.

Secondly, the patches as submitted here have been tested, but I don't
currently have access to hardware. I'm very hesitant to make a
significant change without retesting and leave the driver in a broken
state again.

Cheers,
Daniel

-- 
Daniel Beer
Firmware Engineer at Igor Institute
daniel.beer@igorinstitute.com or +64-27-420-8101
Offices in Seattle, San Francisco, and Vancouver BC or (206) 494-3312

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

* Re: [PATCH v3 2/2] ASoC: tas5805m: add missing page switch.
  2023-02-06 20:45       ` Daniel Beer
@ 2023-02-06 21:14         ` Mark Brown
  -1 siblings, 0 replies; 14+ messages in thread
From: Mark Brown @ 2023-02-06 21:14 UTC (permalink / raw)
  To: Daniel Beer; +Cc: alsa-devel, linux-kernel, Andy Liu

[-- Attachment #1: Type: text/plain, Size: 1192 bytes --]

On Tue, Feb 07, 2023 at 09:45:46AM +1300, Daniel Beer wrote:

> We did discuss this a while back when the driver first went in.
> Unfortunately the vendor software tools provide configuration for the
> part in the form of a sequence of raw register writes, including
> explicit page changes:

>     https://lore.kernel.org/lkml/Yd85bjKEX9JnoOlI@sirena.org.uk/

That seems surmountable, either bypassing regmap or parsing the
configuration files.

> Aside from this, I have two other practical issues.

> The first is that I'm not sure how exactly to implement the paging
> scheme in terms of regmap_range_cfg (assuming this is what you're
> referring to). This chip has multi-level paging (books/pages), with the
> book selection register itself requiring paging to access. A sequence of

That's absolutely fine, this isn't the first device which has such a
setup and the code handles nested windows fine.

> Secondly, the patches as submitted here have been tested, but I don't
> currently have access to hardware. I'm very hesitant to make a
> significant change without retesting and leave the driver in a broken
> state again.

Presumably someone does given that the problem was noticed?

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

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

* Re: [PATCH v3 2/2] ASoC: tas5805m: add missing page switch.
@ 2023-02-06 21:14         ` Mark Brown
  0 siblings, 0 replies; 14+ messages in thread
From: Mark Brown @ 2023-02-06 21:14 UTC (permalink / raw)
  To: Daniel Beer; +Cc: Andy Liu, alsa-devel, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 1192 bytes --]

On Tue, Feb 07, 2023 at 09:45:46AM +1300, Daniel Beer wrote:

> We did discuss this a while back when the driver first went in.
> Unfortunately the vendor software tools provide configuration for the
> part in the form of a sequence of raw register writes, including
> explicit page changes:

>     https://lore.kernel.org/lkml/Yd85bjKEX9JnoOlI@sirena.org.uk/

That seems surmountable, either bypassing regmap or parsing the
configuration files.

> Aside from this, I have two other practical issues.

> The first is that I'm not sure how exactly to implement the paging
> scheme in terms of regmap_range_cfg (assuming this is what you're
> referring to). This chip has multi-level paging (books/pages), with the
> book selection register itself requiring paging to access. A sequence of

That's absolutely fine, this isn't the first device which has such a
setup and the code handles nested windows fine.

> Secondly, the patches as submitted here have been tested, but I don't
> currently have access to hardware. I'm very hesitant to make a
> significant change without retesting and leave the driver in a broken
> state again.

Presumably someone does given that the problem was noticed?

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

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

* Re: [PATCH v3 0/2] Two bug fixes for tas5805m codec driver
  2023-02-04  7:55 ` Daniel Beer
@ 2023-02-06 21:37   ` Mark Brown
  -1 siblings, 0 replies; 14+ messages in thread
From: Mark Brown @ 2023-02-06 21:37 UTC (permalink / raw)
  To: alsa-devel, Daniel Beer; +Cc: linux-kernel, Andy Liu

On Sat, 04 Feb 2023 20:55:26 +1300, Daniel Beer wrote:
> This pair of patches fixes two issues which crept in while revising the
> original submission, at a time when I no longer had access to test
> hardware.
> 
> The fixes here have been tested and verified on hardware.
> 
> Changes v2 -> v3:
>   - Resubmit with cover letter
> 
> [...]

Applied to

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

Thanks!

[1/2] ASoC: tas5805m: rework to avoid scheduling while atomic.
      commit: 147323792693bf013f60dca160be1d32bd4d180a
[2/2] ASoC: tas5805m: add missing page switch.
      commit: e0576cd642ced1ac65370b4516b7be9f536a0498

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] 14+ messages in thread

* Re: [PATCH v3 0/2] Two bug fixes for tas5805m codec driver
@ 2023-02-06 21:37   ` Mark Brown
  0 siblings, 0 replies; 14+ messages in thread
From: Mark Brown @ 2023-02-06 21:37 UTC (permalink / raw)
  To: alsa-devel, Daniel Beer; +Cc: Andy Liu, linux-kernel

On Sat, 04 Feb 2023 20:55:26 +1300, Daniel Beer wrote:
> This pair of patches fixes two issues which crept in while revising the
> original submission, at a time when I no longer had access to test
> hardware.
> 
> The fixes here have been tested and verified on hardware.
> 
> Changes v2 -> v3:
>   - Resubmit with cover letter
> 
> [...]

Applied to

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

Thanks!

[1/2] ASoC: tas5805m: rework to avoid scheduling while atomic.
      commit: 147323792693bf013f60dca160be1d32bd4d180a
[2/2] ASoC: tas5805m: add missing page switch.
      commit: e0576cd642ced1ac65370b4516b7be9f536a0498

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] 14+ messages in thread

end of thread, other threads:[~2023-02-06 21:39 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-02-04  7:55 [PATCH v3 0/2] Two bug fixes for tas5805m codec driver Daniel Beer
2023-02-04  7:55 ` Daniel Beer
2022-10-27  8:28 ` [PATCH v3 1/2] ASoC: tas5805m: rework to avoid scheduling while atomic Daniel Beer
2022-10-27  8:28   ` Daniel Beer
2022-10-27  8:38 ` [PATCH v3 2/2] ASoC: tas5805m: add missing page switch Daniel Beer
2022-10-27  8:38   ` Daniel Beer
2023-02-06 13:11   ` Mark Brown
2023-02-06 13:11     ` Mark Brown
2023-02-06 20:45     ` Daniel Beer
2023-02-06 20:45       ` Daniel Beer
2023-02-06 21:14       ` Mark Brown
2023-02-06 21:14         ` Mark Brown
2023-02-06 21:37 ` [PATCH v3 0/2] Two bug fixes for tas5805m codec driver Mark Brown
2023-02-06 21:37   ` Mark Brown

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.