diff options
author | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2010-03-29 12:09:45 -0400 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2010-04-05 11:19:09 -0400 |
commit | 8437f7006b9cfa249791e2fd57596683d4561843 (patch) | |
tree | c1701c27b37b21c53daec55f730162757511e041 /sound/soc/codecs/wm_hubs.c | |
parent | 3fa49e3ad9ac20b15edfb0c51bbad36e45a84b17 (diff) |
ASoC: Support second DC servo readback method for wm_hubs
More recent Wolfson hubs devices add the ability to read back the DC
servo calibration information from the register used to write offsets,
and later still ones remove the old readback registers. Add support
for the new scheme, and use it for WM8994 device revisions that
support it.
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Acked-by: Liam Girdwood <lrg@slimlogic.co.uk>
Diffstat (limited to 'sound/soc/codecs/wm_hubs.c')
-rw-r--r-- | sound/soc/codecs/wm_hubs.c | 41 |
1 files changed, 30 insertions, 11 deletions
diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c index 3729a12b151f..2b5c0924f615 100644 --- a/sound/soc/codecs/wm_hubs.c +++ b/sound/soc/codecs/wm_hubs.c | |||
@@ -86,7 +86,7 @@ static void wait_for_dc_servo(struct snd_soc_codec *codec) | |||
86 | static void calibrate_dc_servo(struct snd_soc_codec *codec) | 86 | static void calibrate_dc_servo(struct snd_soc_codec *codec) |
87 | { | 87 | { |
88 | struct wm_hubs_data *hubs = codec->private_data; | 88 | struct wm_hubs_data *hubs = codec->private_data; |
89 | u16 reg, dcs_cfg; | 89 | u16 reg, reg_l, reg_r, dcs_cfg; |
90 | 90 | ||
91 | /* Set for 32 series updates */ | 91 | /* Set for 32 series updates */ |
92 | snd_soc_update_bits(codec, WM8993_DC_SERVO_1, | 92 | snd_soc_update_bits(codec, WM8993_DC_SERVO_1, |
@@ -110,19 +110,38 @@ static void calibrate_dc_servo(struct snd_soc_codec *codec) | |||
110 | dev_dbg(codec->dev, "Applying %d code DC servo correction\n", | 110 | dev_dbg(codec->dev, "Applying %d code DC servo correction\n", |
111 | hubs->dcs_codes); | 111 | hubs->dcs_codes); |
112 | 112 | ||
113 | /* Different chips in the family support different | ||
114 | * readback methods. | ||
115 | */ | ||
116 | switch (hubs->dcs_readback_mode) { | ||
117 | case 0: | ||
118 | reg_l = snd_soc_read(codec, WM8993_DC_SERVO_READBACK_1) | ||
119 | & WM8993_DCS_INTEG_CHAN_0_MASK;; | ||
120 | reg_r = snd_soc_read(codec, WM8993_DC_SERVO_READBACK_2) | ||
121 | & WM8993_DCS_INTEG_CHAN_1_MASK; | ||
122 | break; | ||
123 | case 1: | ||
124 | reg = snd_soc_read(codec, WM8993_DC_SERVO_3); | ||
125 | reg_l = (reg & WM8993_DCS_DAC_WR_VAL_1_MASK) | ||
126 | >> WM8993_DCS_DAC_WR_VAL_1_SHIFT; | ||
127 | reg_r = reg & WM8993_DCS_DAC_WR_VAL_0_MASK; | ||
128 | break; | ||
129 | default: | ||
130 | WARN(1, "Unknown DCS readback method"); | ||
131 | break; | ||
132 | } | ||
133 | |||
113 | /* HPOUT1L */ | 134 | /* HPOUT1L */ |
114 | reg = snd_soc_read(codec, WM8993_DC_SERVO_READBACK_1) & | 135 | if (reg_l + hubs->dcs_codes > 0 && |
115 | WM8993_DCS_INTEG_CHAN_0_MASK;; | 136 | reg_l + hubs->dcs_codes < 0xff) |
116 | if (reg + hubs->dcs_codes > 0 && reg + hubs->dcs_codes < 0xff) | 137 | reg_l += hubs->dcs_codes; |
117 | reg += hubs->dcs_codes; | 138 | dcs_cfg = reg_l << WM8993_DCS_DAC_WR_VAL_1_SHIFT; |
118 | dcs_cfg = reg << WM8993_DCS_DAC_WR_VAL_1_SHIFT; | ||
119 | 139 | ||
120 | /* HPOUT1R */ | 140 | /* HPOUT1R */ |
121 | reg = snd_soc_read(codec, WM8993_DC_SERVO_READBACK_2) & | 141 | if (reg_r + hubs->dcs_codes > 0 && |
122 | WM8993_DCS_INTEG_CHAN_1_MASK; | 142 | reg_r + hubs->dcs_codes < 0xff) |
123 | if (reg + hubs->dcs_codes > 0 && reg + hubs->dcs_codes < 0xff) | 143 | reg_r += hubs->dcs_codes; |
124 | reg += hubs->dcs_codes; | 144 | dcs_cfg |= reg_r; |
125 | dcs_cfg |= reg; | ||
126 | 145 | ||
127 | /* Do it */ | 146 | /* Do it */ |
128 | snd_soc_write(codec, WM8993_DC_SERVO_3, dcs_cfg); | 147 | snd_soc_write(codec, WM8993_DC_SERVO_3, dcs_cfg); |