ASoC: wm8962: Update register CLASS_D_CONTROL_1 to be non-volatile
Subsystems (3)
PATCH 1/1 ASoC: wm8962: Update register CLASS_D_CONTROL_1 to be non-volatile
The register CLASS_D_CONTROL_1 is marked as volatile because it contains a bit, DAC_MUTE, which is also mirrored in the ADC_DAC_CONTROL_1 register. This causes problems for the "Speaker Switch" control, which will report an error if the CODEC is suspended because it relies on a volatile register.
To resolve this issue mark CLASS_D_CONTROL_1 as non-volatile and manually keep the register cache in sync by updating both bits when changing the mute status.
---
Hi Shawn,
I am afraid I don't have access to hardware for 8962 at the moment, so have only build tested this, but I believe it should fix your issue.
Please let me know how you get on.
Thanks,
Charles
sound/soc/codecs/wm8962.c | 15 ++++++++++++--- sound/soc/codecs/wm8962.h | 4 ++++ 2 files changed, 16 insertions(+), 3 deletions(-)
sound/soc/codecs/wm8962.c +12 -3
@@ -154,6 +154,7 @@ static struct reg_default wm8962_reg[] = { { 40, 0x0000 }, /* R40 - SPKOUTL volume */ { 41, 0x0000 }, /* R41 - SPKOUTR volume */ + { 49, 0x0010 }, /* R49 - Class D Control 1 */ { 51, 0x0003 }, /* R51 - Class D Control 2 */ { 56, 0x0506 }, /* R56 - Clocking 4 */
@@ -795,7 +796,6 @@ static bool wm8962_volatile_register(struct device *dev, unsigned int reg)case WM8962_ALC2 :case WM8962_THERMAL_SHUTDOWN_STATUS :case WM8962_ADDITIONAL_CONTROL_4 : -case WM8962_CLASS_D_CONTROL_1 :case WM8962_DC_SERVO_6 :case WM8962_INTERRUPT_STATUS_1 :case WM8962_INTERRUPT_STATUS_2 :
@@ -2929,13 +2929,22 @@ static int wm8962_set_fll(struct snd_soc_codec *codec, int fll_id, int source,static int wm8962_mute (struct snd_soc_dai *dai,int mute) {struct snd_soc_codec *codec = dai->codec; -int val; +int val, ret;if (mute) - val =WM8962_DAC_MUTE ; + val =WM8962_DAC_MUTE |WM8962_DAC_MUTE_ALT ;else val =0 ; +/** +* The DAC mute bit is mirrored in two registers, update both to keep +* the register cache consistent. +*/ + ret =snd_soc_update_bits (codec,WM8962_CLASS_D_CONTROL_1 , +WM8962_DAC_MUTE_ALT , val); +if (ret <0 ) +return ret; +return snd_soc_update_bits (codec,WM8962_ADC_DAC_CONTROL_1 ,WM8962_DAC_MUTE , val); }
sound/soc/codecs/wm8962.h +4 -0
@@ -1954,6 +1954,10 @@#define WM8962_SPKOUTL_ENA_MASK 0x0040/* SPKOUTL_ENA */ #define WM8962_SPKOUTL_ENA_SHIFT 6/* SPKOUTL_ENA */ #define WM8962_SPKOUTL_ENA_WIDTH 1/* SPKOUTL_ENA */ +#define WM8962_DAC_MUTE_ALT 0x0010/* DAC_MUTE */ +#define WM8962_DAC_MUTE_ALT_MASK 0x0010/* DAC_MUTE */ +#define WM8962_DAC_MUTE_ALT_SHIFT 4/* DAC_MUTE */ +#define WM8962_DAC_MUTE_ALT_WIDTH 1/* DAC_MUTE */ #define WM8962_SPKOUTL_PGA_MUTE 0x0002/* SPKOUTL_PGA_MUTE */ #define WM8962_SPKOUTL_PGA_MUTE_MASK 0x0002/* SPKOUTL_PGA_MUTE */ #define WM8962_SPKOUTL_PGA_MUTE_SHIFT 1/* SPKOUTL_PGA_MUTE */
Signature · 1 line
1.7.2.5
Quoted 10 lines · Charles Keepax
The register
CLASS_D_CONTROL_1is marked as volatile because it contains a bit,DAC_MUTE, which is also mirrored in theADC_DAC_CONTROL_1register. This causes problems for the "Speaker Switch" control, which will report an error if the CODEC is suspended because it relies on a volatile register.To resolve this issue mark
CLASS_D_CONTROL_1as non-volatile and manually keep the register cache in sync by updating both bits when changing the mute status.
Quoted 8 lines
Reported-by Shawn Guo <[email protected]>Signed-off-by Charles Keepax <[email protected]>---
Hi Shawn,I am afraid I don't have access to hardware for 8962 at the moment, so have only build tested this, but I believe it should fix your issue.
Yes, it fixes my issue. Thanks, Charles.
Quoted 5 lines · Charles Keepax
The register
CLASS_D_CONTROL_1is marked as volatile because it contains a bit,DAC_MUTE, which is also mirrored in theADC_DAC_CONTROL_1register. This causes problems for the "Speaker Switch" control, which will report an error if the CODEC is suspended because it relies on a volatile register.
Applied, thanks. I had thought there was one of the user visible controls affected too but I guess not.