Commit 79ef0abc authored by Mark Brown's avatar Mark Brown

ASoC: Implement new DC servo readback mode for late WM8994 revisions

Later WM8994 devices implement a new DC servo readback mode with the
register used to access the offset moved to register 0x59. Implement
support for this and enable it on the appropriate devices.
Signed-off-by: default avatarMark Brown <broonie@opensource.wolfsonmicro.com>
Acked-by: default avatarLiam Girdwood <lrg@ti.com>
parent 25032c11
...@@ -72,6 +72,7 @@ ...@@ -72,6 +72,7 @@
#define WM8994_DC_SERVO_2 0x55 #define WM8994_DC_SERVO_2 0x55
#define WM8994_DC_SERVO_4 0x57 #define WM8994_DC_SERVO_4 0x57
#define WM8994_DC_SERVO_READBACK 0x58 #define WM8994_DC_SERVO_READBACK 0x58
#define WM8994_DC_SERVO_4E 0x59
#define WM8994_ANALOGUE_HP_1 0x60 #define WM8994_ANALOGUE_HP_1 0x60
#define WM8958_MIC_DETECT_1 0xD0 #define WM8958_MIC_DETECT_1 0xD0
#define WM8958_MIC_DETECT_2 0xD1 #define WM8958_MIC_DETECT_2 0xD1
......
...@@ -107,6 +107,7 @@ static int wm8994_volatile(struct snd_soc_codec *codec, unsigned int reg) ...@@ -107,6 +107,7 @@ static int wm8994_volatile(struct snd_soc_codec *codec, unsigned int reg)
case WM8994_LDO_2: case WM8994_LDO_2:
case WM8958_DSP2_EXECCONTROL: case WM8958_DSP2_EXECCONTROL:
case WM8958_MIC_DETECT_3: case WM8958_MIC_DETECT_3:
case WM8994_DC_SERVO_4E:
return 1; return 1;
default: default:
return 0; return 0;
...@@ -2978,7 +2979,7 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) ...@@ -2978,7 +2979,7 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
wm8994->hubs.series_startup = 1; wm8994->hubs.series_startup = 1;
break; break;
default: default:
wm8994->hubs.dcs_readback_mode = 1; wm8994->hubs.dcs_readback_mode = 2;
break; break;
} }
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <linux/pm.h> #include <linux/pm.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/mfd/wm8994/registers.h>
#include <sound/core.h> #include <sound/core.h>
#include <sound/pcm.h> #include <sound/pcm.h>
#include <sound/pcm_params.h> #include <sound/pcm_params.h>
...@@ -116,14 +117,23 @@ static void calibrate_dc_servo(struct snd_soc_codec *codec) ...@@ -116,14 +117,23 @@ static void calibrate_dc_servo(struct snd_soc_codec *codec)
{ {
struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec); struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec);
s8 offset; s8 offset;
u16 reg, reg_l, reg_r, dcs_cfg; u16 reg, reg_l, reg_r, dcs_cfg, dcs_reg;
switch (hubs->dcs_readback_mode) {
case 2:
dcs_reg = WM8994_DC_SERVO_4E;
break;
default:
dcs_reg = WM8993_DC_SERVO_3;
break;
}
/* If we're using a digital only path and have a previously /* If we're using a digital only path and have a previously
* callibrated DC servo offset stored then use that. */ * callibrated DC servo offset stored then use that. */
if (hubs->class_w && hubs->class_w_dcs) { if (hubs->class_w && hubs->class_w_dcs) {
dev_dbg(codec->dev, "Using cached DC servo offset %x\n", dev_dbg(codec->dev, "Using cached DC servo offset %x\n",
hubs->class_w_dcs); hubs->class_w_dcs);
snd_soc_write(codec, WM8993_DC_SERVO_3, hubs->class_w_dcs); snd_soc_write(codec, dcs_reg, hubs->class_w_dcs);
wait_for_dc_servo(codec, wait_for_dc_servo(codec,
WM8993_DCS_TRIG_DAC_WR_0 | WM8993_DCS_TRIG_DAC_WR_0 |
WM8993_DCS_TRIG_DAC_WR_1); WM8993_DCS_TRIG_DAC_WR_1);
...@@ -154,8 +164,9 @@ static void calibrate_dc_servo(struct snd_soc_codec *codec) ...@@ -154,8 +164,9 @@ static void calibrate_dc_servo(struct snd_soc_codec *codec)
reg_r = snd_soc_read(codec, WM8993_DC_SERVO_READBACK_2) reg_r = snd_soc_read(codec, WM8993_DC_SERVO_READBACK_2)
& WM8993_DCS_INTEG_CHAN_1_MASK; & WM8993_DCS_INTEG_CHAN_1_MASK;
break; break;
case 2:
case 1: case 1:
reg = snd_soc_read(codec, WM8993_DC_SERVO_3); reg = snd_soc_read(codec, dcs_reg);
reg_r = (reg & WM8993_DCS_DAC_WR_VAL_1_MASK) reg_r = (reg & WM8993_DCS_DAC_WR_VAL_1_MASK)
>> WM8993_DCS_DAC_WR_VAL_1_SHIFT; >> WM8993_DCS_DAC_WR_VAL_1_SHIFT;
reg_l = reg & WM8993_DCS_DAC_WR_VAL_0_MASK; reg_l = reg & WM8993_DCS_DAC_WR_VAL_0_MASK;
...@@ -185,7 +196,7 @@ static void calibrate_dc_servo(struct snd_soc_codec *codec) ...@@ -185,7 +196,7 @@ static void calibrate_dc_servo(struct snd_soc_codec *codec)
dev_dbg(codec->dev, "DCS result: %x\n", dcs_cfg); dev_dbg(codec->dev, "DCS result: %x\n", dcs_cfg);
/* Do it */ /* Do it */
snd_soc_write(codec, WM8993_DC_SERVO_3, dcs_cfg); snd_soc_write(codec, dcs_reg, dcs_cfg);
wait_for_dc_servo(codec, wait_for_dc_servo(codec,
WM8993_DCS_TRIG_DAC_WR_0 | WM8993_DCS_TRIG_DAC_WR_0 |
WM8993_DCS_TRIG_DAC_WR_1); WM8993_DCS_TRIG_DAC_WR_1);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment