ASoC: wm8994: Prevent access to invalid VU register bits on WM1811
diff mbox series

Message ID 20200804141043.11425-1-s.nawrocki@samsung.com
State New
Headers show
Series
  • ASoC: wm8994: Prevent access to invalid VU register bits on WM1811
Related show

Commit Message

Sylwester Nawrocki Aug. 4, 2020, 2:10 p.m. UTC
The ADC2 and DAC2 are not available on WM1811 device. This patch moves
the ADC2, DAC2 VU bitfields to a separate array so we can skip accessing
them and avoid unreadable register access on WM1811.

This allows to get rid of warnings during boot like:
wm8994-codec: ASoC: error at soc_component_read_no_lock on wm8994-codec: -5

Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
---
 sound/soc/codecs/wm8994.c | 60 ++++++++++++++++++++++++++++-----------
 1 file changed, 44 insertions(+), 16 deletions(-)

--
2.17.1

Comments

Charles Keepax Aug. 17, 2020, 9:45 a.m. UTC | #1
On Tue, Aug 04, 2020 at 04:10:43PM +0200, Sylwester Nawrocki wrote:
> The ADC2 and DAC2 are not available on WM1811 device. This patch moves
> the ADC2, DAC2 VU bitfields to a separate array so we can skip accessing
> them and avoid unreadable register access on WM1811.
> 
> This allows to get rid of warnings during boot like:
> wm8994-codec: ASoC: error at soc_component_read_no_lock on wm8994-codec: -5
> 
> Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
> ---
> +static void wm8994_update_vu_bits(struct snd_soc_component *component)
> +{
> +	struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
> +	struct wm8994 *control = wm8994->wm8994;
> +	int i;
> +
> +	for (i = 0; i < ARRAY_SIZE(wm8994_vu_bits); i++)
> +		snd_soc_component_write(component, wm8994_vu_bits[i].reg,
> +					snd_soc_component_read(component,
> +						       wm8994_vu_bits[i].reg));

Is there a reason to not be using snd_soc_component_update_bits
here?

I think otherwise this looks ok.

Thanks,
Charles
Mark Brown Aug. 18, 2020, 4:55 p.m. UTC | #2
On Tue, 4 Aug 2020 16:10:43 +0200, Sylwester Nawrocki wrote:
> The ADC2 and DAC2 are not available on WM1811 device. This patch moves
> the ADC2, DAC2 VU bitfields to a separate array so we can skip accessing
> them and avoid unreadable register access on WM1811.
> 
> This allows to get rid of warnings during boot like:
> wm8994-codec: ASoC: error at soc_component_read_no_lock on wm8994-codec: -5

Applied to

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

Thanks!

[1/1] ASoC: wm8994: Prevent access to invalid VU register bits on WM1811
      commit: 314213c15702f7598c486cf8c94f617719dfe339

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

Patch
diff mbox series

diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c
index a84ae879d37e..038be667c1a6 100644
--- a/sound/soc/codecs/wm8994.c
+++ b/sound/soc/codecs/wm8994.c
@@ -43,10 +43,12 @@ 
 #define WM8994_NUM_DRC 3
 #define WM8994_NUM_EQ  3

-static struct {
+struct wm8994_reg_mask {
 	unsigned int reg;
 	unsigned int mask;
-} wm8994_vu_bits[] = {
+};
+
+static struct wm8994_reg_mask wm8994_vu_bits[] = {
 	{ WM8994_LEFT_LINE_INPUT_1_2_VOLUME, WM8994_IN1_VU },
 	{ WM8994_RIGHT_LINE_INPUT_1_2_VOLUME, WM8994_IN1_VU },
 	{ WM8994_LEFT_LINE_INPUT_3_4_VOLUME, WM8994_IN2_VU },
@@ -60,14 +62,10 @@  static struct {

 	{ WM8994_AIF1_DAC1_LEFT_VOLUME, WM8994_AIF1DAC1_VU },
 	{ WM8994_AIF1_DAC1_RIGHT_VOLUME, WM8994_AIF1DAC1_VU },
-	{ WM8994_AIF1_DAC2_LEFT_VOLUME, WM8994_AIF1DAC2_VU },
-	{ WM8994_AIF1_DAC2_RIGHT_VOLUME, WM8994_AIF1DAC2_VU },
 	{ WM8994_AIF2_DAC_LEFT_VOLUME, WM8994_AIF2DAC_VU },
 	{ WM8994_AIF2_DAC_RIGHT_VOLUME, WM8994_AIF2DAC_VU },
 	{ WM8994_AIF1_ADC1_LEFT_VOLUME, WM8994_AIF1ADC1_VU },
 	{ WM8994_AIF1_ADC1_RIGHT_VOLUME, WM8994_AIF1ADC1_VU },
-	{ WM8994_AIF1_ADC2_LEFT_VOLUME, WM8994_AIF1ADC2_VU },
-	{ WM8994_AIF1_ADC2_RIGHT_VOLUME, WM8994_AIF1ADC2_VU },
 	{ WM8994_AIF2_ADC_LEFT_VOLUME, WM8994_AIF2ADC_VU },
 	{ WM8994_AIF2_ADC_RIGHT_VOLUME, WM8994_AIF1ADC2_VU },
 	{ WM8994_DAC1_LEFT_VOLUME, WM8994_DAC1_VU },
@@ -76,6 +74,14 @@  static struct {
 	{ WM8994_DAC2_RIGHT_VOLUME, WM8994_DAC2_VU },
 };

+/* VU bitfields for ADC2, DAC2 not available on WM1811 */
+static struct wm8994_reg_mask wm8994_adc2_dac2_vu_bits[] = {
+	{ WM8994_AIF1_DAC2_LEFT_VOLUME, WM8994_AIF1DAC2_VU },
+	{ WM8994_AIF1_DAC2_RIGHT_VOLUME, WM8994_AIF1DAC2_VU },
+	{ WM8994_AIF1_ADC2_LEFT_VOLUME, WM8994_AIF1ADC2_VU },
+	{ WM8994_AIF1_ADC2_RIGHT_VOLUME, WM8994_AIF1ADC2_VU },
+};
+
 static int wm8994_drc_base[] = {
 	WM8994_AIF1_DRC1_1,
 	WM8994_AIF1_DRC2_1,
@@ -1030,6 +1036,26 @@  static bool wm8994_check_class_w_digital(struct snd_soc_component *component)
 	return true;
 }

+static void wm8994_update_vu_bits(struct snd_soc_component *component)
+{
+	struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
+	struct wm8994 *control = wm8994->wm8994;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(wm8994_vu_bits); i++)
+		snd_soc_component_write(component, wm8994_vu_bits[i].reg,
+					snd_soc_component_read(component,
+						       wm8994_vu_bits[i].reg));
+	if (control->type == WM1811)
+		return;
+
+	for (i = 0; i < ARRAY_SIZE(wm8994_adc2_dac2_vu_bits); i++)
+		snd_soc_component_write(component,
+				wm8994_adc2_dac2_vu_bits[i].reg,
+				snd_soc_component_read(component,
+					wm8994_adc2_dac2_vu_bits[i].reg));
+}
+
 static int aif_mclk_set(struct snd_soc_component *component, int aif, bool enable)
 {
 	struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
@@ -1076,7 +1102,7 @@  static int aif1clk_ev(struct snd_soc_dapm_widget *w,
 	struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
 	struct wm8994 *control = wm8994->wm8994;
 	int mask = WM8994_AIF1DAC1L_ENA | WM8994_AIF1DAC1R_ENA;
-	int ret, i;
+	int ret;
 	int dac;
 	int adc;
 	int val;
@@ -1144,10 +1170,7 @@  static int aif1clk_ev(struct snd_soc_dapm_widget *w,
 		break;

 	case SND_SOC_DAPM_POST_PMU:
-		for (i = 0; i < ARRAY_SIZE(wm8994_vu_bits); i++)
-			snd_soc_component_write(component, wm8994_vu_bits[i].reg,
-				      snd_soc_component_read(component,
-						   wm8994_vu_bits[i].reg));
+		wm8994_update_vu_bits(component);
 		break;

 	case SND_SOC_DAPM_PRE_PMD:
@@ -1181,7 +1204,7 @@  static int aif2clk_ev(struct snd_soc_dapm_widget *w,
 		      struct snd_kcontrol *kcontrol, int event)
 {
 	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
-	int ret, i;
+	int ret;
 	int dac;
 	int adc;
 	int val;
@@ -1237,10 +1260,7 @@  static int aif2clk_ev(struct snd_soc_dapm_widget *w,
 		break;

 	case SND_SOC_DAPM_POST_PMU:
-		for (i = 0; i < ARRAY_SIZE(wm8994_vu_bits); i++)
-			snd_soc_component_write(component, wm8994_vu_bits[i].reg,
-				      snd_soc_component_read(component,
-						   wm8994_vu_bits[i].reg));
+		wm8994_update_vu_bits(component);
 		break;

 	case SND_SOC_DAPM_PRE_PMD:
@@ -4346,6 +4366,14 @@  static int wm8994_component_probe(struct snd_soc_component *component)
 				    wm8994_vu_bits[i].mask,
 				    wm8994_vu_bits[i].mask);

+	if (control->type != WM1811) {
+		for (i = 0; i < ARRAY_SIZE(wm8994_adc2_dac2_vu_bits); i++)
+			snd_soc_component_update_bits(component,
+					wm8994_adc2_dac2_vu_bits[i].reg,
+					wm8994_adc2_dac2_vu_bits[i].mask,
+					wm8994_adc2_dac2_vu_bits[i].mask);
+	}
+
 	/* Set the low bit of the 3D stereo depth so TLV matches */
 	snd_soc_component_update_bits(component, WM8994_AIF1_DAC1_FILTERS_2,
 			    1 << WM8994_AIF1DAC1_3D_GAIN_SHIFT,