ASoC: Support second DC servo readback method for wm_hubs
authorMark Brown <broonie@opensource.wolfsonmicro.com>
Mon, 29 Mar 2010 16:09:45 +0000 (17:09 +0100)
committerMark Brown <broonie@opensource.wolfsonmicro.com>
Mon, 5 Apr 2010 15:19:09 +0000 (16:19 +0100)
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>
sound/soc/codecs/wm8994.c
sound/soc/codecs/wm_hubs.c
sound/soc/codecs/wm_hubs.h

index d10d65191fd279e8d247c5e1cf8d535bff387427..c80218f23bb90cbbc398c5f69af270a219f47ec3 100644 (file)
@@ -3730,11 +3730,12 @@ static int wm8994_codec_probe(struct platform_device *pdev)
        case 3:
                wm8994->hubs.dcs_codes = -5;
                wm8994->hubs.hp_startup_mode = 1;
+               wm8994->hubs.dcs_readback_mode = 1;
                break;
        default:
+               wm8994->hubs.dcs_readback_mode = 1;
                break;
        }
-                          
 
        /* Remember if AIFnLRCLK is configured as a GPIO.  This should be
         * configured on init - if a system wants to do this dynamically
index 3729a12b151ff4dbd2c3ad2a94016243eae9025b..2b5c0924f6153539f449e5227dad5d19157c4141 100644 (file)
@@ -86,7 +86,7 @@ static void wait_for_dc_servo(struct snd_soc_codec *codec)
 static void calibrate_dc_servo(struct snd_soc_codec *codec)
 {
        struct wm_hubs_data *hubs = codec->private_data;
-       u16 reg, dcs_cfg;
+       u16 reg, reg_l, reg_r, dcs_cfg;
 
        /* Set for 32 series updates */
        snd_soc_update_bits(codec, WM8993_DC_SERVO_1,
@@ -110,19 +110,38 @@ static void calibrate_dc_servo(struct snd_soc_codec *codec)
                dev_dbg(codec->dev, "Applying %d code DC servo correction\n",
                        hubs->dcs_codes);
 
+               /* Different chips in the family support different
+                * readback methods.
+                */
+               switch (hubs->dcs_readback_mode) {
+               case 0:
+                       reg_l = snd_soc_read(codec, WM8993_DC_SERVO_READBACK_1)
+                               & WM8993_DCS_INTEG_CHAN_0_MASK;;
+                       reg_r = snd_soc_read(codec, WM8993_DC_SERVO_READBACK_2)
+                               & WM8993_DCS_INTEG_CHAN_1_MASK;
+                       break;
+               case 1:
+                       reg = snd_soc_read(codec, WM8993_DC_SERVO_3);
+                       reg_l = (reg & WM8993_DCS_DAC_WR_VAL_1_MASK)
+                               >> WM8993_DCS_DAC_WR_VAL_1_SHIFT;
+                       reg_r = reg & WM8993_DCS_DAC_WR_VAL_0_MASK;
+                       break;
+               default:
+                       WARN(1, "Unknown DCS readback method");
+                       break;
+               }
+
                /* HPOUT1L */
-               reg = snd_soc_read(codec, WM8993_DC_SERVO_READBACK_1) &
-                       WM8993_DCS_INTEG_CHAN_0_MASK;;
-               if (reg + hubs->dcs_codes > 0 && reg + hubs->dcs_codes < 0xff)
-                       reg += hubs->dcs_codes;
-               dcs_cfg = reg << WM8993_DCS_DAC_WR_VAL_1_SHIFT;
+               if (reg_l + hubs->dcs_codes > 0 &&
+                   reg_l + hubs->dcs_codes < 0xff)
+                       reg_l += hubs->dcs_codes;
+               dcs_cfg = reg_l << WM8993_DCS_DAC_WR_VAL_1_SHIFT;
 
                /* HPOUT1R */
-               reg = snd_soc_read(codec, WM8993_DC_SERVO_READBACK_2) &
-                       WM8993_DCS_INTEG_CHAN_1_MASK;
-               if (reg + hubs->dcs_codes > 0 && reg + hubs->dcs_codes < 0xff)
-                       reg += hubs->dcs_codes;
-               dcs_cfg |= reg;
+               if (reg_r + hubs->dcs_codes > 0 &&
+                   reg_r + hubs->dcs_codes < 0xff)
+                       reg_r += hubs->dcs_codes;
+               dcs_cfg |= reg_r;
 
                /* Do it */
                snd_soc_write(codec, WM8993_DC_SERVO_3, dcs_cfg);
index 420104fe9c90467a1c9027c3e9bc234cab28ecc8..e51c16683589ffb612f3ec58761f01ea24c7223e 100644 (file)
@@ -21,6 +21,7 @@ extern const unsigned int wm_hubs_spkmix_tlv[];
 /* This *must* be the first element of the codec->private_data struct */
 struct wm_hubs_data {
        int dcs_codes;
+       int dcs_readback_mode;
        int hp_startup_mode;
 };