aboutsummaryrefslogtreecommitdiffstats
path: root/sound
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
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')
-rw-r--r--sound/soc/codecs/wm8994.c3
-rw-r--r--sound/soc/codecs/wm_hubs.c41
-rw-r--r--sound/soc/codecs/wm_hubs.h1
3 files changed, 33 insertions, 12 deletions
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c
index d10d65191fd2..c80218f23bb9 100644
--- a/sound/soc/codecs/wm8994.c
+++ b/sound/soc/codecs/wm8994.c
@@ -3730,11 +3730,12 @@ static int wm8994_codec_probe(struct platform_device *pdev)
3730 case 3: 3730 case 3:
3731 wm8994->hubs.dcs_codes = -5; 3731 wm8994->hubs.dcs_codes = -5;
3732 wm8994->hubs.hp_startup_mode = 1; 3732 wm8994->hubs.hp_startup_mode = 1;
3733 wm8994->hubs.dcs_readback_mode = 1;
3733 break; 3734 break;
3734 default: 3735 default:
3736 wm8994->hubs.dcs_readback_mode = 1;
3735 break; 3737 break;
3736 } 3738 }
3737
3738 3739
3739 /* Remember if AIFnLRCLK is configured as a GPIO. This should be 3740 /* Remember if AIFnLRCLK is configured as a GPIO. This should be
3740 * configured on init - if a system wants to do this dynamically 3741 * configured on init - if a system wants to do this dynamically
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);
diff --git a/sound/soc/codecs/wm_hubs.h b/sound/soc/codecs/wm_hubs.h
index 420104fe9c90..e51c16683589 100644
--- a/sound/soc/codecs/wm_hubs.h
+++ b/sound/soc/codecs/wm_hubs.h
@@ -21,6 +21,7 @@ extern const unsigned int wm_hubs_spkmix_tlv[];
21/* This *must* be the first element of the codec->private_data struct */ 21/* This *must* be the first element of the codec->private_data struct */
22struct wm_hubs_data { 22struct wm_hubs_data {
23 int dcs_codes; 23 int dcs_codes;
24 int dcs_readback_mode;
24 int hp_startup_mode; 25 int hp_startup_mode;
25}; 26};
26 27