aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/wm_hubs.c
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2010-03-29 12:09:45 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2010-04-05 11:19:09 -0400
commit8437f7006b9cfa249791e2fd57596683d4561843 (patch)
treec1701c27b37b21c53daec55f730162757511e041 /sound/soc/codecs/wm_hubs.c
parent3fa49e3ad9ac20b15edfb0c51bbad36e45a84b17 (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.c41
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)
86static void calibrate_dc_servo(struct snd_soc_codec *codec) 86static 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);