Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * wm_hubs.c  --  WM8993/4 common code
0004  *
0005  * Copyright 2009-12 Wolfson Microelectronics plc
0006  *
0007  * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
0008  */
0009 
0010 #include <linux/module.h>
0011 #include <linux/moduleparam.h>
0012 #include <linux/init.h>
0013 #include <linux/delay.h>
0014 #include <linux/pm.h>
0015 #include <linux/i2c.h>
0016 #include <linux/mfd/wm8994/registers.h>
0017 #include <sound/core.h>
0018 #include <sound/pcm.h>
0019 #include <sound/pcm_params.h>
0020 #include <sound/soc.h>
0021 #include <sound/initval.h>
0022 #include <sound/tlv.h>
0023 
0024 #include "wm8993.h"
0025 #include "wm_hubs.h"
0026 
0027 const DECLARE_TLV_DB_SCALE(wm_hubs_spkmix_tlv, -300, 300, 0);
0028 EXPORT_SYMBOL_GPL(wm_hubs_spkmix_tlv);
0029 
0030 static const DECLARE_TLV_DB_SCALE(inpga_tlv, -1650, 150, 0);
0031 static const DECLARE_TLV_DB_SCALE(inmix_sw_tlv, 0, 3000, 0);
0032 static const DECLARE_TLV_DB_SCALE(inmix_tlv, -1500, 300, 1);
0033 static const DECLARE_TLV_DB_SCALE(earpiece_tlv, -600, 600, 0);
0034 static const DECLARE_TLV_DB_SCALE(outmix_tlv, -2100, 300, 0);
0035 static const DECLARE_TLV_DB_SCALE(spkmixout_tlv, -1800, 600, 1);
0036 static const DECLARE_TLV_DB_SCALE(outpga_tlv, -5700, 100, 0);
0037 static const DECLARE_TLV_DB_RANGE(spkboost_tlv,
0038     0, 6, TLV_DB_SCALE_ITEM(0, 150, 0),
0039     7, 7, TLV_DB_SCALE_ITEM(1200, 0, 0)
0040 );
0041 static const DECLARE_TLV_DB_SCALE(line_tlv, -600, 600, 0);
0042 
0043 static const char *speaker_ref_text[] = {
0044     "SPKVDD/2",
0045     "VMID",
0046 };
0047 
0048 static SOC_ENUM_SINGLE_DECL(speaker_ref,
0049                 WM8993_SPEAKER_MIXER, 8, speaker_ref_text);
0050 
0051 static const char *speaker_mode_text[] = {
0052     "Class D",
0053     "Class AB",
0054 };
0055 
0056 static SOC_ENUM_SINGLE_DECL(speaker_mode,
0057                 WM8993_SPKMIXR_ATTENUATION, 8, speaker_mode_text);
0058 
0059 static void wait_for_dc_servo(struct snd_soc_component *component, unsigned int op)
0060 {
0061     struct wm_hubs_data *hubs = snd_soc_component_get_drvdata(component);
0062     unsigned int reg;
0063     int count = 0;
0064     int timeout;
0065     unsigned int val;
0066 
0067     val = op | WM8993_DCS_ENA_CHAN_0 | WM8993_DCS_ENA_CHAN_1;
0068 
0069     /* Trigger the command */
0070     snd_soc_component_write(component, WM8993_DC_SERVO_0, val);
0071 
0072     dev_dbg(component->dev, "Waiting for DC servo...\n");
0073 
0074     if (hubs->dcs_done_irq)
0075         timeout = 4;
0076     else
0077         timeout = 400;
0078 
0079     do {
0080         count++;
0081 
0082         if (hubs->dcs_done_irq)
0083             wait_for_completion_timeout(&hubs->dcs_done,
0084                             msecs_to_jiffies(250));
0085         else
0086             msleep(1);
0087 
0088         reg = snd_soc_component_read(component, WM8993_DC_SERVO_0);
0089         dev_dbg(component->dev, "DC servo: %x\n", reg);
0090     } while (reg & op && count < timeout);
0091 
0092     if (reg & op)
0093         dev_err(component->dev, "Timed out waiting for DC Servo %x\n",
0094             op);
0095 }
0096 
0097 irqreturn_t wm_hubs_dcs_done(int irq, void *data)
0098 {
0099     struct wm_hubs_data *hubs = data;
0100 
0101     complete(&hubs->dcs_done);
0102 
0103     return IRQ_HANDLED;
0104 }
0105 EXPORT_SYMBOL_GPL(wm_hubs_dcs_done);
0106 
0107 static bool wm_hubs_dac_hp_direct(struct snd_soc_component *component)
0108 {
0109     int reg;
0110 
0111     /* If we're going via the mixer we'll need to do additional checks */
0112     reg = snd_soc_component_read(component, WM8993_OUTPUT_MIXER1);
0113     if (!(reg & WM8993_DACL_TO_HPOUT1L)) {
0114         if (reg & ~WM8993_DACL_TO_MIXOUTL) {
0115             dev_vdbg(component->dev, "Analogue paths connected: %x\n",
0116                  reg & ~WM8993_DACL_TO_HPOUT1L);
0117             return false;
0118         } else {
0119             dev_vdbg(component->dev, "HPL connected to mixer\n");
0120         }
0121     } else {
0122         dev_vdbg(component->dev, "HPL connected to DAC\n");
0123     }
0124 
0125     reg = snd_soc_component_read(component, WM8993_OUTPUT_MIXER2);
0126     if (!(reg & WM8993_DACR_TO_HPOUT1R)) {
0127         if (reg & ~WM8993_DACR_TO_MIXOUTR) {
0128             dev_vdbg(component->dev, "Analogue paths connected: %x\n",
0129                  reg & ~WM8993_DACR_TO_HPOUT1R);
0130             return false;
0131         } else {
0132             dev_vdbg(component->dev, "HPR connected to mixer\n");
0133         }
0134     } else {
0135         dev_vdbg(component->dev, "HPR connected to DAC\n");
0136     }
0137 
0138     return true;
0139 }
0140 
0141 struct wm_hubs_dcs_cache {
0142     struct list_head list;
0143     unsigned int left;
0144     unsigned int right;
0145     u16 dcs_cfg;
0146 };
0147 
0148 static bool wm_hubs_dcs_cache_get(struct snd_soc_component *component,
0149                   struct wm_hubs_dcs_cache **entry)
0150 {
0151     struct wm_hubs_data *hubs = snd_soc_component_get_drvdata(component);
0152     struct wm_hubs_dcs_cache *cache;
0153     unsigned int left, right;
0154 
0155     left = snd_soc_component_read(component, WM8993_LEFT_OUTPUT_VOLUME);
0156     left &= WM8993_HPOUT1L_VOL_MASK;
0157 
0158     right = snd_soc_component_read(component, WM8993_RIGHT_OUTPUT_VOLUME);
0159     right &= WM8993_HPOUT1R_VOL_MASK;
0160 
0161     list_for_each_entry(cache, &hubs->dcs_cache, list) {
0162         if (cache->left != left || cache->right != right)
0163             continue;
0164 
0165         *entry = cache;
0166         return true;
0167     }
0168 
0169     return false;
0170 }
0171 
0172 static void wm_hubs_dcs_cache_set(struct snd_soc_component *component, u16 dcs_cfg)
0173 {
0174     struct wm_hubs_data *hubs = snd_soc_component_get_drvdata(component);
0175     struct wm_hubs_dcs_cache *cache;
0176 
0177     if (hubs->no_cache_dac_hp_direct)
0178         return;
0179 
0180     cache = devm_kzalloc(component->dev, sizeof(*cache), GFP_KERNEL);
0181     if (!cache)
0182         return;
0183 
0184     cache->left = snd_soc_component_read(component, WM8993_LEFT_OUTPUT_VOLUME);
0185     cache->left &= WM8993_HPOUT1L_VOL_MASK;
0186 
0187     cache->right = snd_soc_component_read(component, WM8993_RIGHT_OUTPUT_VOLUME);
0188     cache->right &= WM8993_HPOUT1R_VOL_MASK;
0189 
0190     cache->dcs_cfg = dcs_cfg;
0191 
0192     list_add_tail(&cache->list, &hubs->dcs_cache);
0193 }
0194 
0195 static int wm_hubs_read_dc_servo(struct snd_soc_component *component,
0196                   u16 *reg_l, u16 *reg_r)
0197 {
0198     struct wm_hubs_data *hubs = snd_soc_component_get_drvdata(component);
0199     u16 dcs_reg, reg;
0200     int ret = 0;
0201 
0202     switch (hubs->dcs_readback_mode) {
0203     case 2:
0204         dcs_reg = WM8994_DC_SERVO_4E;
0205         break;
0206     case 1:
0207         dcs_reg = WM8994_DC_SERVO_READBACK;
0208         break;
0209     default:
0210         dcs_reg = WM8993_DC_SERVO_3;
0211         break;
0212     }
0213 
0214     /* Different chips in the family support different readback
0215      * methods.
0216      */
0217     switch (hubs->dcs_readback_mode) {
0218     case 0:
0219         *reg_l = snd_soc_component_read(component, WM8993_DC_SERVO_READBACK_1)
0220             & WM8993_DCS_INTEG_CHAN_0_MASK;
0221         *reg_r = snd_soc_component_read(component, WM8993_DC_SERVO_READBACK_2)
0222             & WM8993_DCS_INTEG_CHAN_1_MASK;
0223         break;
0224     case 2:
0225     case 1:
0226         reg = snd_soc_component_read(component, dcs_reg);
0227         *reg_r = (reg & WM8993_DCS_DAC_WR_VAL_1_MASK)
0228             >> WM8993_DCS_DAC_WR_VAL_1_SHIFT;
0229         *reg_l = reg & WM8993_DCS_DAC_WR_VAL_0_MASK;
0230         break;
0231     default:
0232         WARN(1, "Unknown DCS readback method\n");
0233         ret = -1;
0234     }
0235     return ret;
0236 }
0237 
0238 /*
0239  * Startup calibration of the DC servo
0240  */
0241 static void enable_dc_servo(struct snd_soc_component *component)
0242 {
0243     struct wm_hubs_data *hubs = snd_soc_component_get_drvdata(component);
0244     struct wm_hubs_dcs_cache *cache;
0245     s8 offset;
0246     u16 reg_l, reg_r, dcs_cfg, dcs_reg;
0247 
0248     switch (hubs->dcs_readback_mode) {
0249     case 2:
0250         dcs_reg = WM8994_DC_SERVO_4E;
0251         break;
0252     default:
0253         dcs_reg = WM8993_DC_SERVO_3;
0254         break;
0255     }
0256 
0257     /* If we're using a digital only path and have a previously
0258      * callibrated DC servo offset stored then use that. */
0259     if (wm_hubs_dac_hp_direct(component) &&
0260         wm_hubs_dcs_cache_get(component, &cache)) {
0261         dev_dbg(component->dev, "Using cached DCS offset %x for %d,%d\n",
0262             cache->dcs_cfg, cache->left, cache->right);
0263         snd_soc_component_write(component, dcs_reg, cache->dcs_cfg);
0264         wait_for_dc_servo(component,
0265                   WM8993_DCS_TRIG_DAC_WR_0 |
0266                   WM8993_DCS_TRIG_DAC_WR_1);
0267         return;
0268     }
0269 
0270     if (hubs->series_startup) {
0271         /* Set for 32 series updates */
0272         snd_soc_component_update_bits(component, WM8993_DC_SERVO_1,
0273                     WM8993_DCS_SERIES_NO_01_MASK,
0274                     32 << WM8993_DCS_SERIES_NO_01_SHIFT);
0275         wait_for_dc_servo(component,
0276                   WM8993_DCS_TRIG_SERIES_0 |
0277                   WM8993_DCS_TRIG_SERIES_1);
0278     } else {
0279         wait_for_dc_servo(component,
0280                   WM8993_DCS_TRIG_STARTUP_0 |
0281                   WM8993_DCS_TRIG_STARTUP_1);
0282     }
0283 
0284     if (wm_hubs_read_dc_servo(component, &reg_l, &reg_r) < 0)
0285         return;
0286 
0287     dev_dbg(component->dev, "DCS input: %x %x\n", reg_l, reg_r);
0288 
0289     /* Apply correction to DC servo result */
0290     if (hubs->dcs_codes_l || hubs->dcs_codes_r) {
0291         dev_dbg(component->dev,
0292             "Applying %d/%d code DC servo correction\n",
0293             hubs->dcs_codes_l, hubs->dcs_codes_r);
0294 
0295         /* HPOUT1R */
0296         offset = (s8)reg_r;
0297         dev_dbg(component->dev, "DCS right %d->%d\n", offset,
0298             offset + hubs->dcs_codes_r);
0299         offset += hubs->dcs_codes_r;
0300         dcs_cfg = (u8)offset << WM8993_DCS_DAC_WR_VAL_1_SHIFT;
0301 
0302         /* HPOUT1L */
0303         offset = (s8)reg_l;
0304         dev_dbg(component->dev, "DCS left %d->%d\n", offset,
0305             offset + hubs->dcs_codes_l);
0306         offset += hubs->dcs_codes_l;
0307         dcs_cfg |= (u8)offset;
0308 
0309         dev_dbg(component->dev, "DCS result: %x\n", dcs_cfg);
0310 
0311         /* Do it */
0312         snd_soc_component_write(component, dcs_reg, dcs_cfg);
0313         wait_for_dc_servo(component,
0314                   WM8993_DCS_TRIG_DAC_WR_0 |
0315                   WM8993_DCS_TRIG_DAC_WR_1);
0316     } else {
0317         dcs_cfg = reg_r << WM8993_DCS_DAC_WR_VAL_1_SHIFT;
0318         dcs_cfg |= reg_l;
0319     }
0320 
0321     /* Save the callibrated offset if we're in class W mode and
0322      * therefore don't have any analogue signal mixed in. */
0323     if (wm_hubs_dac_hp_direct(component))
0324         wm_hubs_dcs_cache_set(component, dcs_cfg);
0325 }
0326 
0327 /*
0328  * Update the DC servo calibration on gain changes
0329  */
0330 static int wm8993_put_dc_servo(struct snd_kcontrol *kcontrol,
0331                    struct snd_ctl_elem_value *ucontrol)
0332 {
0333     struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
0334     struct wm_hubs_data *hubs = snd_soc_component_get_drvdata(component);
0335     int ret;
0336 
0337     ret = snd_soc_put_volsw(kcontrol, ucontrol);
0338 
0339     /* If we're applying an offset correction then updating the
0340      * callibration would be likely to introduce further offsets. */
0341     if (hubs->dcs_codes_l || hubs->dcs_codes_r || hubs->no_series_update)
0342         return ret;
0343 
0344     /* Only need to do this if the outputs are active */
0345     if (snd_soc_component_read(component, WM8993_POWER_MANAGEMENT_1)
0346         & (WM8993_HPOUT1L_ENA | WM8993_HPOUT1R_ENA))
0347         snd_soc_component_update_bits(component,
0348                     WM8993_DC_SERVO_0,
0349                     WM8993_DCS_TRIG_SINGLE_0 |
0350                     WM8993_DCS_TRIG_SINGLE_1,
0351                     WM8993_DCS_TRIG_SINGLE_0 |
0352                     WM8993_DCS_TRIG_SINGLE_1);
0353 
0354     return ret;
0355 }
0356 
0357 static const struct snd_kcontrol_new analogue_snd_controls[] = {
0358 SOC_SINGLE_TLV("IN1L Volume", WM8993_LEFT_LINE_INPUT_1_2_VOLUME, 0, 31, 0,
0359            inpga_tlv),
0360 SOC_SINGLE("IN1L Switch", WM8993_LEFT_LINE_INPUT_1_2_VOLUME, 7, 1, 1),
0361 SOC_SINGLE("IN1L ZC Switch", WM8993_LEFT_LINE_INPUT_1_2_VOLUME, 6, 1, 0),
0362 
0363 SOC_SINGLE_TLV("IN1R Volume", WM8993_RIGHT_LINE_INPUT_1_2_VOLUME, 0, 31, 0,
0364            inpga_tlv),
0365 SOC_SINGLE("IN1R Switch", WM8993_RIGHT_LINE_INPUT_1_2_VOLUME, 7, 1, 1),
0366 SOC_SINGLE("IN1R ZC Switch", WM8993_RIGHT_LINE_INPUT_1_2_VOLUME, 6, 1, 0),
0367 
0368 
0369 SOC_SINGLE_TLV("IN2L Volume", WM8993_LEFT_LINE_INPUT_3_4_VOLUME, 0, 31, 0,
0370            inpga_tlv),
0371 SOC_SINGLE("IN2L Switch", WM8993_LEFT_LINE_INPUT_3_4_VOLUME, 7, 1, 1),
0372 SOC_SINGLE("IN2L ZC Switch", WM8993_LEFT_LINE_INPUT_3_4_VOLUME, 6, 1, 0),
0373 
0374 SOC_SINGLE_TLV("IN2R Volume", WM8993_RIGHT_LINE_INPUT_3_4_VOLUME, 0, 31, 0,
0375            inpga_tlv),
0376 SOC_SINGLE("IN2R Switch", WM8993_RIGHT_LINE_INPUT_3_4_VOLUME, 7, 1, 1),
0377 SOC_SINGLE("IN2R ZC Switch", WM8993_RIGHT_LINE_INPUT_3_4_VOLUME, 6, 1, 0),
0378 
0379 SOC_SINGLE_TLV("MIXINL IN2L Volume", WM8993_INPUT_MIXER3, 7, 1, 0,
0380            inmix_sw_tlv),
0381 SOC_SINGLE_TLV("MIXINL IN1L Volume", WM8993_INPUT_MIXER3, 4, 1, 0,
0382            inmix_sw_tlv),
0383 SOC_SINGLE_TLV("MIXINL Output Record Volume", WM8993_INPUT_MIXER3, 0, 7, 0,
0384            inmix_tlv),
0385 SOC_SINGLE_TLV("MIXINL IN1LP Volume", WM8993_INPUT_MIXER5, 6, 7, 0, inmix_tlv),
0386 SOC_SINGLE_TLV("MIXINL Direct Voice Volume", WM8993_INPUT_MIXER5, 0, 6, 0,
0387            inmix_tlv),
0388 
0389 SOC_SINGLE_TLV("MIXINR IN2R Volume", WM8993_INPUT_MIXER4, 7, 1, 0,
0390            inmix_sw_tlv),
0391 SOC_SINGLE_TLV("MIXINR IN1R Volume", WM8993_INPUT_MIXER4, 4, 1, 0,
0392            inmix_sw_tlv),
0393 SOC_SINGLE_TLV("MIXINR Output Record Volume", WM8993_INPUT_MIXER4, 0, 7, 0,
0394            inmix_tlv),
0395 SOC_SINGLE_TLV("MIXINR IN1RP Volume", WM8993_INPUT_MIXER6, 6, 7, 0, inmix_tlv),
0396 SOC_SINGLE_TLV("MIXINR Direct Voice Volume", WM8993_INPUT_MIXER6, 0, 6, 0,
0397            inmix_tlv),
0398 
0399 SOC_SINGLE_TLV("Left Output Mixer IN2RN Volume", WM8993_OUTPUT_MIXER5, 6, 7, 1,
0400            outmix_tlv),
0401 SOC_SINGLE_TLV("Left Output Mixer IN2LN Volume", WM8993_OUTPUT_MIXER3, 6, 7, 1,
0402            outmix_tlv),
0403 SOC_SINGLE_TLV("Left Output Mixer IN2LP Volume", WM8993_OUTPUT_MIXER3, 9, 7, 1,
0404            outmix_tlv),
0405 SOC_SINGLE_TLV("Left Output Mixer IN1L Volume", WM8993_OUTPUT_MIXER3, 0, 7, 1,
0406            outmix_tlv),
0407 SOC_SINGLE_TLV("Left Output Mixer IN1R Volume", WM8993_OUTPUT_MIXER3, 3, 7, 1,
0408            outmix_tlv),
0409 SOC_SINGLE_TLV("Left Output Mixer Right Input Volume",
0410            WM8993_OUTPUT_MIXER5, 3, 7, 1, outmix_tlv),
0411 SOC_SINGLE_TLV("Left Output Mixer Left Input Volume",
0412            WM8993_OUTPUT_MIXER5, 0, 7, 1, outmix_tlv),
0413 SOC_SINGLE_TLV("Left Output Mixer DAC Volume", WM8993_OUTPUT_MIXER5, 9, 7, 1,
0414            outmix_tlv),
0415 
0416 SOC_SINGLE_TLV("Right Output Mixer IN2LN Volume",
0417            WM8993_OUTPUT_MIXER6, 6, 7, 1, outmix_tlv),
0418 SOC_SINGLE_TLV("Right Output Mixer IN2RN Volume",
0419            WM8993_OUTPUT_MIXER4, 6, 7, 1, outmix_tlv),
0420 SOC_SINGLE_TLV("Right Output Mixer IN1L Volume",
0421            WM8993_OUTPUT_MIXER4, 3, 7, 1, outmix_tlv),
0422 SOC_SINGLE_TLV("Right Output Mixer IN1R Volume",
0423            WM8993_OUTPUT_MIXER4, 0, 7, 1, outmix_tlv),
0424 SOC_SINGLE_TLV("Right Output Mixer IN2RP Volume",
0425            WM8993_OUTPUT_MIXER4, 9, 7, 1, outmix_tlv),
0426 SOC_SINGLE_TLV("Right Output Mixer Left Input Volume",
0427            WM8993_OUTPUT_MIXER6, 3, 7, 1, outmix_tlv),
0428 SOC_SINGLE_TLV("Right Output Mixer Right Input Volume",
0429            WM8993_OUTPUT_MIXER6, 6, 7, 1, outmix_tlv),
0430 SOC_SINGLE_TLV("Right Output Mixer DAC Volume",
0431            WM8993_OUTPUT_MIXER6, 9, 7, 1, outmix_tlv),
0432 
0433 SOC_DOUBLE_R_TLV("Output Volume", WM8993_LEFT_OPGA_VOLUME,
0434          WM8993_RIGHT_OPGA_VOLUME, 0, 63, 0, outpga_tlv),
0435 SOC_DOUBLE_R("Output Switch", WM8993_LEFT_OPGA_VOLUME,
0436          WM8993_RIGHT_OPGA_VOLUME, 6, 1, 0),
0437 SOC_DOUBLE_R("Output ZC Switch", WM8993_LEFT_OPGA_VOLUME,
0438          WM8993_RIGHT_OPGA_VOLUME, 7, 1, 0),
0439 
0440 SOC_SINGLE("Earpiece Switch", WM8993_HPOUT2_VOLUME, 5, 1, 1),
0441 SOC_SINGLE_TLV("Earpiece Volume", WM8993_HPOUT2_VOLUME, 4, 1, 1, earpiece_tlv),
0442 
0443 SOC_SINGLE_TLV("SPKL Input Volume", WM8993_SPKMIXL_ATTENUATION,
0444            5, 1, 1, wm_hubs_spkmix_tlv),
0445 SOC_SINGLE_TLV("SPKL IN1LP Volume", WM8993_SPKMIXL_ATTENUATION,
0446            4, 1, 1, wm_hubs_spkmix_tlv),
0447 SOC_SINGLE_TLV("SPKL Output Volume", WM8993_SPKMIXL_ATTENUATION,
0448            3, 1, 1, wm_hubs_spkmix_tlv),
0449 
0450 SOC_SINGLE_TLV("SPKR Input Volume", WM8993_SPKMIXR_ATTENUATION,
0451            5, 1, 1, wm_hubs_spkmix_tlv),
0452 SOC_SINGLE_TLV("SPKR IN1RP Volume", WM8993_SPKMIXR_ATTENUATION,
0453            4, 1, 1, wm_hubs_spkmix_tlv),
0454 SOC_SINGLE_TLV("SPKR Output Volume", WM8993_SPKMIXR_ATTENUATION,
0455            3, 1, 1, wm_hubs_spkmix_tlv),
0456 
0457 SOC_DOUBLE_R_TLV("Speaker Mixer Volume",
0458          WM8993_SPKMIXL_ATTENUATION, WM8993_SPKMIXR_ATTENUATION,
0459          0, 3, 1, spkmixout_tlv),
0460 SOC_DOUBLE_R_TLV("Speaker Volume",
0461          WM8993_SPEAKER_VOLUME_LEFT, WM8993_SPEAKER_VOLUME_RIGHT,
0462          0, 63, 0, outpga_tlv),
0463 SOC_DOUBLE_R("Speaker Switch",
0464          WM8993_SPEAKER_VOLUME_LEFT, WM8993_SPEAKER_VOLUME_RIGHT,
0465          6, 1, 0),
0466 SOC_DOUBLE_R("Speaker ZC Switch",
0467          WM8993_SPEAKER_VOLUME_LEFT, WM8993_SPEAKER_VOLUME_RIGHT,
0468          7, 1, 0),
0469 SOC_DOUBLE_TLV("Speaker Boost Volume", WM8993_SPKOUT_BOOST, 3, 0, 7, 0,
0470            spkboost_tlv),
0471 SOC_ENUM("Speaker Reference", speaker_ref),
0472 SOC_ENUM("Speaker Mode", speaker_mode),
0473 
0474 SOC_DOUBLE_R_EXT_TLV("Headphone Volume",
0475              WM8993_LEFT_OUTPUT_VOLUME, WM8993_RIGHT_OUTPUT_VOLUME,
0476              0, 63, 0, snd_soc_get_volsw, wm8993_put_dc_servo,
0477              outpga_tlv),
0478 
0479 SOC_DOUBLE_R("Headphone Switch", WM8993_LEFT_OUTPUT_VOLUME,
0480          WM8993_RIGHT_OUTPUT_VOLUME, 6, 1, 0),
0481 SOC_DOUBLE_R("Headphone ZC Switch", WM8993_LEFT_OUTPUT_VOLUME,
0482          WM8993_RIGHT_OUTPUT_VOLUME, 7, 1, 0),
0483 
0484 SOC_SINGLE("LINEOUT1N Switch", WM8993_LINE_OUTPUTS_VOLUME, 6, 1, 1),
0485 SOC_SINGLE("LINEOUT1P Switch", WM8993_LINE_OUTPUTS_VOLUME, 5, 1, 1),
0486 SOC_SINGLE_TLV("LINEOUT1 Volume", WM8993_LINE_OUTPUTS_VOLUME, 4, 1, 1,
0487            line_tlv),
0488 
0489 SOC_SINGLE("LINEOUT2N Switch", WM8993_LINE_OUTPUTS_VOLUME, 2, 1, 1),
0490 SOC_SINGLE("LINEOUT2P Switch", WM8993_LINE_OUTPUTS_VOLUME, 1, 1, 1),
0491 SOC_SINGLE_TLV("LINEOUT2 Volume", WM8993_LINE_OUTPUTS_VOLUME, 0, 1, 1,
0492            line_tlv),
0493 };
0494 
0495 static int hp_supply_event(struct snd_soc_dapm_widget *w,
0496                struct snd_kcontrol *kcontrol, int event)
0497 {
0498     struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
0499     struct wm_hubs_data *hubs = snd_soc_component_get_drvdata(component);
0500 
0501     switch (event) {
0502     case SND_SOC_DAPM_PRE_PMU:
0503         switch (hubs->hp_startup_mode) {
0504         case 0:
0505             break;
0506         case 1:
0507             /* Enable the headphone amp */
0508             snd_soc_component_update_bits(component, WM8993_POWER_MANAGEMENT_1,
0509                         WM8993_HPOUT1L_ENA |
0510                         WM8993_HPOUT1R_ENA,
0511                         WM8993_HPOUT1L_ENA |
0512                         WM8993_HPOUT1R_ENA);
0513 
0514             /* Enable the second stage */
0515             snd_soc_component_update_bits(component, WM8993_ANALOGUE_HP_0,
0516                         WM8993_HPOUT1L_DLY |
0517                         WM8993_HPOUT1R_DLY,
0518                         WM8993_HPOUT1L_DLY |
0519                         WM8993_HPOUT1R_DLY);
0520             break;
0521         default:
0522             dev_err(component->dev, "Unknown HP startup mode %d\n",
0523                 hubs->hp_startup_mode);
0524             break;
0525         }
0526         break;
0527 
0528     case SND_SOC_DAPM_PRE_PMD:
0529         snd_soc_component_update_bits(component, WM8993_CHARGE_PUMP_1,
0530                     WM8993_CP_ENA, 0);
0531         break;
0532     }
0533 
0534     return 0;
0535 }
0536 
0537 static int hp_event(struct snd_soc_dapm_widget *w,
0538             struct snd_kcontrol *kcontrol, int event)
0539 {
0540     struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
0541     unsigned int reg = snd_soc_component_read(component, WM8993_ANALOGUE_HP_0);
0542 
0543     switch (event) {
0544     case SND_SOC_DAPM_POST_PMU:
0545         snd_soc_component_update_bits(component, WM8993_CHARGE_PUMP_1,
0546                     WM8993_CP_ENA, WM8993_CP_ENA);
0547 
0548         msleep(5);
0549 
0550         snd_soc_component_update_bits(component, WM8993_POWER_MANAGEMENT_1,
0551                     WM8993_HPOUT1L_ENA | WM8993_HPOUT1R_ENA,
0552                     WM8993_HPOUT1L_ENA | WM8993_HPOUT1R_ENA);
0553 
0554         reg |= WM8993_HPOUT1L_DLY | WM8993_HPOUT1R_DLY;
0555         snd_soc_component_write(component, WM8993_ANALOGUE_HP_0, reg);
0556 
0557         snd_soc_component_update_bits(component, WM8993_DC_SERVO_1,
0558                     WM8993_DCS_TIMER_PERIOD_01_MASK, 0);
0559 
0560         enable_dc_servo(component);
0561 
0562         reg |= WM8993_HPOUT1R_OUTP | WM8993_HPOUT1R_RMV_SHORT |
0563             WM8993_HPOUT1L_OUTP | WM8993_HPOUT1L_RMV_SHORT;
0564         snd_soc_component_write(component, WM8993_ANALOGUE_HP_0, reg);
0565         break;
0566 
0567     case SND_SOC_DAPM_PRE_PMD:
0568         snd_soc_component_update_bits(component, WM8993_ANALOGUE_HP_0,
0569                     WM8993_HPOUT1L_OUTP |
0570                     WM8993_HPOUT1R_OUTP |
0571                     WM8993_HPOUT1L_RMV_SHORT |
0572                     WM8993_HPOUT1R_RMV_SHORT, 0);
0573 
0574         snd_soc_component_update_bits(component, WM8993_ANALOGUE_HP_0,
0575                     WM8993_HPOUT1L_DLY |
0576                     WM8993_HPOUT1R_DLY, 0);
0577 
0578         snd_soc_component_write(component, WM8993_DC_SERVO_0, 0);
0579 
0580         snd_soc_component_update_bits(component, WM8993_POWER_MANAGEMENT_1,
0581                     WM8993_HPOUT1L_ENA | WM8993_HPOUT1R_ENA,
0582                     0);
0583         break;
0584     }
0585 
0586     return 0;
0587 }
0588 
0589 static int earpiece_event(struct snd_soc_dapm_widget *w,
0590               struct snd_kcontrol *control, int event)
0591 {
0592     struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
0593     u16 reg = snd_soc_component_read(component, WM8993_ANTIPOP1) & ~WM8993_HPOUT2_IN_ENA;
0594 
0595     switch (event) {
0596     case SND_SOC_DAPM_PRE_PMU:
0597         reg |= WM8993_HPOUT2_IN_ENA;
0598         snd_soc_component_write(component, WM8993_ANTIPOP1, reg);
0599         udelay(50);
0600         break;
0601 
0602     case SND_SOC_DAPM_POST_PMD:
0603         snd_soc_component_write(component, WM8993_ANTIPOP1, reg);
0604         break;
0605 
0606     default:
0607         WARN(1, "Invalid event %d\n", event);
0608         break;
0609     }
0610 
0611     return 0;
0612 }
0613 
0614 static int lineout_event(struct snd_soc_dapm_widget *w,
0615              struct snd_kcontrol *control, int event)
0616 {
0617     struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
0618     struct wm_hubs_data *hubs = snd_soc_component_get_drvdata(component);
0619     bool *flag;
0620 
0621     switch (w->shift) {
0622     case WM8993_LINEOUT1N_ENA_SHIFT:
0623         flag = &hubs->lineout1n_ena;
0624         break;
0625     case WM8993_LINEOUT1P_ENA_SHIFT:
0626         flag = &hubs->lineout1p_ena;
0627         break;
0628     case WM8993_LINEOUT2N_ENA_SHIFT:
0629         flag = &hubs->lineout2n_ena;
0630         break;
0631     case WM8993_LINEOUT2P_ENA_SHIFT:
0632         flag = &hubs->lineout2p_ena;
0633         break;
0634     default:
0635         WARN(1, "Unknown line output");
0636         return -EINVAL;
0637     }
0638 
0639     *flag = SND_SOC_DAPM_EVENT_ON(event);
0640 
0641     return 0;
0642 }
0643 
0644 static int micbias_event(struct snd_soc_dapm_widget *w,
0645              struct snd_kcontrol *kcontrol, int event)
0646 {
0647     struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
0648     struct wm_hubs_data *hubs = snd_soc_component_get_drvdata(component);
0649 
0650     switch (w->shift) {
0651     case WM8993_MICB1_ENA_SHIFT:
0652         if (hubs->micb1_delay)
0653             msleep(hubs->micb1_delay);
0654         break;
0655     case WM8993_MICB2_ENA_SHIFT:
0656         if (hubs->micb2_delay)
0657             msleep(hubs->micb2_delay);
0658         break;
0659     default:
0660         return -EINVAL;
0661     }
0662 
0663     return 0;
0664 }
0665 
0666 void wm_hubs_update_class_w(struct snd_soc_component *component)
0667 {
0668     struct wm_hubs_data *hubs = snd_soc_component_get_drvdata(component);
0669     int enable = WM8993_CP_DYN_V | WM8993_CP_DYN_FREQ;
0670 
0671     if (!wm_hubs_dac_hp_direct(component))
0672         enable = false;
0673 
0674     if (hubs->check_class_w_digital && !hubs->check_class_w_digital(component))
0675         enable = false;
0676 
0677     dev_vdbg(component->dev, "Class W %s\n", enable ? "enabled" : "disabled");
0678 
0679     snd_soc_component_update_bits(component, WM8993_CLASS_W_0,
0680                 WM8993_CP_DYN_V | WM8993_CP_DYN_FREQ, enable);
0681 
0682     snd_soc_component_write(component, WM8993_LEFT_OUTPUT_VOLUME,
0683               snd_soc_component_read(component, WM8993_LEFT_OUTPUT_VOLUME));
0684     snd_soc_component_write(component, WM8993_RIGHT_OUTPUT_VOLUME,
0685               snd_soc_component_read(component, WM8993_RIGHT_OUTPUT_VOLUME));
0686 }
0687 EXPORT_SYMBOL_GPL(wm_hubs_update_class_w);
0688 
0689 #define WM_HUBS_SINGLE_W(xname, reg, shift, max, invert) \
0690     SOC_SINGLE_EXT(xname, reg, shift, max, invert, \
0691         snd_soc_dapm_get_volsw, class_w_put_volsw)
0692 
0693 static int class_w_put_volsw(struct snd_kcontrol *kcontrol,
0694                   struct snd_ctl_elem_value *ucontrol)
0695 {
0696     struct snd_soc_component *component = snd_soc_dapm_kcontrol_component(kcontrol);
0697     int ret;
0698 
0699     ret = snd_soc_dapm_put_volsw(kcontrol, ucontrol);
0700 
0701     wm_hubs_update_class_w(component);
0702 
0703     return ret;
0704 }
0705 
0706 #define WM_HUBS_ENUM_W(xname, xenum) \
0707 {   .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
0708     .info = snd_soc_info_enum_double, \
0709     .get = snd_soc_dapm_get_enum_double, \
0710     .put = class_w_put_double, \
0711     .private_value = (unsigned long)&xenum }
0712 
0713 static int class_w_put_double(struct snd_kcontrol *kcontrol,
0714                   struct snd_ctl_elem_value *ucontrol)
0715 {
0716     struct snd_soc_component *component = snd_soc_dapm_kcontrol_component(kcontrol);
0717     int ret;
0718 
0719     ret = snd_soc_dapm_put_enum_double(kcontrol, ucontrol);
0720 
0721     wm_hubs_update_class_w(component);
0722 
0723     return ret;
0724 }
0725 
0726 static const char *hp_mux_text[] = {
0727     "Mixer",
0728     "DAC",
0729 };
0730 
0731 static SOC_ENUM_SINGLE_DECL(hpl_enum,
0732                 WM8993_OUTPUT_MIXER1, 8, hp_mux_text);
0733 
0734 const struct snd_kcontrol_new wm_hubs_hpl_mux =
0735     WM_HUBS_ENUM_W("Left Headphone Mux", hpl_enum);
0736 EXPORT_SYMBOL_GPL(wm_hubs_hpl_mux);
0737 
0738 static SOC_ENUM_SINGLE_DECL(hpr_enum,
0739                 WM8993_OUTPUT_MIXER2, 8, hp_mux_text);
0740 
0741 const struct snd_kcontrol_new wm_hubs_hpr_mux =
0742     WM_HUBS_ENUM_W("Right Headphone Mux", hpr_enum);
0743 EXPORT_SYMBOL_GPL(wm_hubs_hpr_mux);
0744 
0745 static const struct snd_kcontrol_new in1l_pga[] = {
0746 SOC_DAPM_SINGLE("IN1LP Switch", WM8993_INPUT_MIXER2, 5, 1, 0),
0747 SOC_DAPM_SINGLE("IN1LN Switch", WM8993_INPUT_MIXER2, 4, 1, 0),
0748 };
0749 
0750 static const struct snd_kcontrol_new in1r_pga[] = {
0751 SOC_DAPM_SINGLE("IN1RP Switch", WM8993_INPUT_MIXER2, 1, 1, 0),
0752 SOC_DAPM_SINGLE("IN1RN Switch", WM8993_INPUT_MIXER2, 0, 1, 0),
0753 };
0754 
0755 static const struct snd_kcontrol_new in2l_pga[] = {
0756 SOC_DAPM_SINGLE("IN2LP Switch", WM8993_INPUT_MIXER2, 7, 1, 0),
0757 SOC_DAPM_SINGLE("IN2LN Switch", WM8993_INPUT_MIXER2, 6, 1, 0),
0758 };
0759 
0760 static const struct snd_kcontrol_new in2r_pga[] = {
0761 SOC_DAPM_SINGLE("IN2RP Switch", WM8993_INPUT_MIXER2, 3, 1, 0),
0762 SOC_DAPM_SINGLE("IN2RN Switch", WM8993_INPUT_MIXER2, 2, 1, 0),
0763 };
0764 
0765 static const struct snd_kcontrol_new mixinl[] = {
0766 SOC_DAPM_SINGLE("IN2L Switch", WM8993_INPUT_MIXER3, 8, 1, 0),
0767 SOC_DAPM_SINGLE("IN1L Switch", WM8993_INPUT_MIXER3, 5, 1, 0),
0768 };
0769 
0770 static const struct snd_kcontrol_new mixinr[] = {
0771 SOC_DAPM_SINGLE("IN2R Switch", WM8993_INPUT_MIXER4, 8, 1, 0),
0772 SOC_DAPM_SINGLE("IN1R Switch", WM8993_INPUT_MIXER4, 5, 1, 0),
0773 };
0774 
0775 static const struct snd_kcontrol_new left_output_mixer[] = {
0776 WM_HUBS_SINGLE_W("Right Input Switch", WM8993_OUTPUT_MIXER1, 7, 1, 0),
0777 WM_HUBS_SINGLE_W("Left Input Switch", WM8993_OUTPUT_MIXER1, 6, 1, 0),
0778 WM_HUBS_SINGLE_W("IN2RN Switch", WM8993_OUTPUT_MIXER1, 5, 1, 0),
0779 WM_HUBS_SINGLE_W("IN2LN Switch", WM8993_OUTPUT_MIXER1, 4, 1, 0),
0780 WM_HUBS_SINGLE_W("IN2LP Switch", WM8993_OUTPUT_MIXER1, 1, 1, 0),
0781 WM_HUBS_SINGLE_W("IN1R Switch", WM8993_OUTPUT_MIXER1, 3, 1, 0),
0782 WM_HUBS_SINGLE_W("IN1L Switch", WM8993_OUTPUT_MIXER1, 2, 1, 0),
0783 WM_HUBS_SINGLE_W("DAC Switch", WM8993_OUTPUT_MIXER1, 0, 1, 0),
0784 };
0785 
0786 static const struct snd_kcontrol_new right_output_mixer[] = {
0787 WM_HUBS_SINGLE_W("Left Input Switch", WM8993_OUTPUT_MIXER2, 7, 1, 0),
0788 WM_HUBS_SINGLE_W("Right Input Switch", WM8993_OUTPUT_MIXER2, 6, 1, 0),
0789 WM_HUBS_SINGLE_W("IN2LN Switch", WM8993_OUTPUT_MIXER2, 5, 1, 0),
0790 WM_HUBS_SINGLE_W("IN2RN Switch", WM8993_OUTPUT_MIXER2, 4, 1, 0),
0791 WM_HUBS_SINGLE_W("IN1L Switch", WM8993_OUTPUT_MIXER2, 3, 1, 0),
0792 WM_HUBS_SINGLE_W("IN1R Switch", WM8993_OUTPUT_MIXER2, 2, 1, 0),
0793 WM_HUBS_SINGLE_W("IN2RP Switch", WM8993_OUTPUT_MIXER2, 1, 1, 0),
0794 WM_HUBS_SINGLE_W("DAC Switch", WM8993_OUTPUT_MIXER2, 0, 1, 0),
0795 };
0796 
0797 static const struct snd_kcontrol_new earpiece_mixer[] = {
0798 SOC_DAPM_SINGLE("Direct Voice Switch", WM8993_HPOUT2_MIXER, 5, 1, 0),
0799 SOC_DAPM_SINGLE("Left Output Switch", WM8993_HPOUT2_MIXER, 4, 1, 0),
0800 SOC_DAPM_SINGLE("Right Output Switch", WM8993_HPOUT2_MIXER, 3, 1, 0),
0801 };
0802 
0803 static const struct snd_kcontrol_new left_speaker_boost[] = {
0804 SOC_DAPM_SINGLE("Direct Voice Switch", WM8993_SPKOUT_MIXERS, 5, 1, 0),
0805 SOC_DAPM_SINGLE("SPKL Switch", WM8993_SPKOUT_MIXERS, 4, 1, 0),
0806 SOC_DAPM_SINGLE("SPKR Switch", WM8993_SPKOUT_MIXERS, 3, 1, 0),
0807 };
0808 
0809 static const struct snd_kcontrol_new right_speaker_boost[] = {
0810 SOC_DAPM_SINGLE("Direct Voice Switch", WM8993_SPKOUT_MIXERS, 2, 1, 0),
0811 SOC_DAPM_SINGLE("SPKL Switch", WM8993_SPKOUT_MIXERS, 1, 1, 0),
0812 SOC_DAPM_SINGLE("SPKR Switch", WM8993_SPKOUT_MIXERS, 0, 1, 0),
0813 };
0814 
0815 static const struct snd_kcontrol_new line1_mix[] = {
0816 SOC_DAPM_SINGLE("IN1R Switch", WM8993_LINE_MIXER1, 2, 1, 0),
0817 SOC_DAPM_SINGLE("IN1L Switch", WM8993_LINE_MIXER1, 1, 1, 0),
0818 SOC_DAPM_SINGLE("Output Switch", WM8993_LINE_MIXER1, 0, 1, 0),
0819 };
0820 
0821 static const struct snd_kcontrol_new line1n_mix[] = {
0822 SOC_DAPM_SINGLE("Left Output Switch", WM8993_LINE_MIXER1, 6, 1, 0),
0823 SOC_DAPM_SINGLE("Right Output Switch", WM8993_LINE_MIXER1, 5, 1, 0),
0824 };
0825 
0826 static const struct snd_kcontrol_new line1p_mix[] = {
0827 SOC_DAPM_SINGLE("Left Output Switch", WM8993_LINE_MIXER1, 0, 1, 0),
0828 };
0829 
0830 static const struct snd_kcontrol_new line2_mix[] = {
0831 SOC_DAPM_SINGLE("IN1L Switch", WM8993_LINE_MIXER2, 2, 1, 0),
0832 SOC_DAPM_SINGLE("IN1R Switch", WM8993_LINE_MIXER2, 1, 1, 0),
0833 SOC_DAPM_SINGLE("Output Switch", WM8993_LINE_MIXER2, 0, 1, 0),
0834 };
0835 
0836 static const struct snd_kcontrol_new line2n_mix[] = {
0837 SOC_DAPM_SINGLE("Left Output Switch", WM8993_LINE_MIXER2, 5, 1, 0),
0838 SOC_DAPM_SINGLE("Right Output Switch", WM8993_LINE_MIXER2, 6, 1, 0),
0839 };
0840 
0841 static const struct snd_kcontrol_new line2p_mix[] = {
0842 SOC_DAPM_SINGLE("Right Output Switch", WM8993_LINE_MIXER2, 0, 1, 0),
0843 };
0844 
0845 static const struct snd_soc_dapm_widget analogue_dapm_widgets[] = {
0846 SND_SOC_DAPM_INPUT("IN1LN"),
0847 SND_SOC_DAPM_INPUT("IN1LP"),
0848 SND_SOC_DAPM_INPUT("IN2LN"),
0849 SND_SOC_DAPM_INPUT("IN2LP:VXRN"),
0850 SND_SOC_DAPM_INPUT("IN1RN"),
0851 SND_SOC_DAPM_INPUT("IN1RP"),
0852 SND_SOC_DAPM_INPUT("IN2RN"),
0853 SND_SOC_DAPM_INPUT("IN2RP:VXRP"),
0854 
0855 SND_SOC_DAPM_SUPPLY("MICBIAS2", WM8993_POWER_MANAGEMENT_1, 5, 0,
0856             micbias_event, SND_SOC_DAPM_POST_PMU),
0857 SND_SOC_DAPM_SUPPLY("MICBIAS1", WM8993_POWER_MANAGEMENT_1, 4, 0,
0858             micbias_event, SND_SOC_DAPM_POST_PMU),
0859 
0860 SND_SOC_DAPM_MIXER("IN1L PGA", WM8993_POWER_MANAGEMENT_2, 6, 0,
0861            in1l_pga, ARRAY_SIZE(in1l_pga)),
0862 SND_SOC_DAPM_MIXER("IN1R PGA", WM8993_POWER_MANAGEMENT_2, 4, 0,
0863            in1r_pga, ARRAY_SIZE(in1r_pga)),
0864 
0865 SND_SOC_DAPM_MIXER("IN2L PGA", WM8993_POWER_MANAGEMENT_2, 7, 0,
0866            in2l_pga, ARRAY_SIZE(in2l_pga)),
0867 SND_SOC_DAPM_MIXER("IN2R PGA", WM8993_POWER_MANAGEMENT_2, 5, 0,
0868            in2r_pga, ARRAY_SIZE(in2r_pga)),
0869 
0870 SND_SOC_DAPM_MIXER("MIXINL", WM8993_POWER_MANAGEMENT_2, 9, 0,
0871            mixinl, ARRAY_SIZE(mixinl)),
0872 SND_SOC_DAPM_MIXER("MIXINR", WM8993_POWER_MANAGEMENT_2, 8, 0,
0873            mixinr, ARRAY_SIZE(mixinr)),
0874 
0875 SND_SOC_DAPM_MIXER("Left Output Mixer", WM8993_POWER_MANAGEMENT_3, 5, 0,
0876            left_output_mixer, ARRAY_SIZE(left_output_mixer)),
0877 SND_SOC_DAPM_MIXER("Right Output Mixer", WM8993_POWER_MANAGEMENT_3, 4, 0,
0878            right_output_mixer, ARRAY_SIZE(right_output_mixer)),
0879 
0880 SND_SOC_DAPM_PGA("Left Output PGA", WM8993_POWER_MANAGEMENT_3, 7, 0, NULL, 0),
0881 SND_SOC_DAPM_PGA("Right Output PGA", WM8993_POWER_MANAGEMENT_3, 6, 0, NULL, 0),
0882 
0883 SND_SOC_DAPM_SUPPLY("Headphone Supply", SND_SOC_NOPM, 0, 0, hp_supply_event, 
0884             SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
0885 SND_SOC_DAPM_OUT_DRV_E("Headphone PGA", SND_SOC_NOPM, 0, 0, NULL, 0,
0886                hp_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
0887 
0888 SND_SOC_DAPM_MIXER("Earpiece Mixer", SND_SOC_NOPM, 0, 0,
0889            earpiece_mixer, ARRAY_SIZE(earpiece_mixer)),
0890 SND_SOC_DAPM_PGA_E("Earpiece Driver", WM8993_POWER_MANAGEMENT_1, 11, 0,
0891            NULL, 0, earpiece_event,
0892            SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
0893 
0894 SND_SOC_DAPM_MIXER("SPKL Boost", SND_SOC_NOPM, 0, 0,
0895            left_speaker_boost, ARRAY_SIZE(left_speaker_boost)),
0896 SND_SOC_DAPM_MIXER("SPKR Boost", SND_SOC_NOPM, 0, 0,
0897            right_speaker_boost, ARRAY_SIZE(right_speaker_boost)),
0898 
0899 SND_SOC_DAPM_SUPPLY("TSHUT", WM8993_POWER_MANAGEMENT_2, 14, 0, NULL, 0),
0900 SND_SOC_DAPM_OUT_DRV("SPKL Driver", WM8993_POWER_MANAGEMENT_1, 12, 0,
0901              NULL, 0),
0902 SND_SOC_DAPM_OUT_DRV("SPKR Driver", WM8993_POWER_MANAGEMENT_1, 13, 0,
0903              NULL, 0),
0904 
0905 SND_SOC_DAPM_MIXER("LINEOUT1 Mixer", SND_SOC_NOPM, 0, 0,
0906            line1_mix, ARRAY_SIZE(line1_mix)),
0907 SND_SOC_DAPM_MIXER("LINEOUT2 Mixer", SND_SOC_NOPM, 0, 0,
0908            line2_mix, ARRAY_SIZE(line2_mix)),
0909 
0910 SND_SOC_DAPM_MIXER("LINEOUT1N Mixer", SND_SOC_NOPM, 0, 0,
0911            line1n_mix, ARRAY_SIZE(line1n_mix)),
0912 SND_SOC_DAPM_MIXER("LINEOUT1P Mixer", SND_SOC_NOPM, 0, 0,
0913            line1p_mix, ARRAY_SIZE(line1p_mix)),
0914 SND_SOC_DAPM_MIXER("LINEOUT2N Mixer", SND_SOC_NOPM, 0, 0,
0915            line2n_mix, ARRAY_SIZE(line2n_mix)),
0916 SND_SOC_DAPM_MIXER("LINEOUT2P Mixer", SND_SOC_NOPM, 0, 0,
0917            line2p_mix, ARRAY_SIZE(line2p_mix)),
0918 
0919 SND_SOC_DAPM_OUT_DRV_E("LINEOUT1N Driver", WM8993_POWER_MANAGEMENT_3, 13, 0,
0920                NULL, 0, lineout_event,
0921              SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
0922 SND_SOC_DAPM_OUT_DRV_E("LINEOUT1P Driver", WM8993_POWER_MANAGEMENT_3, 12, 0,
0923                NULL, 0, lineout_event,
0924                SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
0925 SND_SOC_DAPM_OUT_DRV_E("LINEOUT2N Driver", WM8993_POWER_MANAGEMENT_3, 11, 0,
0926                NULL, 0, lineout_event,
0927                SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
0928 SND_SOC_DAPM_OUT_DRV_E("LINEOUT2P Driver", WM8993_POWER_MANAGEMENT_3, 10, 0,
0929                NULL, 0, lineout_event,
0930                SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
0931 
0932 SND_SOC_DAPM_OUTPUT("SPKOUTLP"),
0933 SND_SOC_DAPM_OUTPUT("SPKOUTLN"),
0934 SND_SOC_DAPM_OUTPUT("SPKOUTRP"),
0935 SND_SOC_DAPM_OUTPUT("SPKOUTRN"),
0936 SND_SOC_DAPM_OUTPUT("HPOUT1L"),
0937 SND_SOC_DAPM_OUTPUT("HPOUT1R"),
0938 SND_SOC_DAPM_OUTPUT("HPOUT2P"),
0939 SND_SOC_DAPM_OUTPUT("HPOUT2N"),
0940 SND_SOC_DAPM_OUTPUT("LINEOUT1P"),
0941 SND_SOC_DAPM_OUTPUT("LINEOUT1N"),
0942 SND_SOC_DAPM_OUTPUT("LINEOUT2P"),
0943 SND_SOC_DAPM_OUTPUT("LINEOUT2N"),
0944 };
0945 
0946 static const struct snd_soc_dapm_route analogue_routes[] = {
0947     { "MICBIAS1", NULL, "CLK_SYS" },
0948     { "MICBIAS2", NULL, "CLK_SYS" },
0949 
0950     { "IN1L PGA", "IN1LP Switch", "IN1LP" },
0951     { "IN1L PGA", "IN1LN Switch", "IN1LN" },
0952 
0953     { "IN1L PGA", NULL, "VMID" },
0954     { "IN1R PGA", NULL, "VMID" },
0955     { "IN2L PGA", NULL, "VMID" },
0956     { "IN2R PGA", NULL, "VMID" },
0957 
0958     { "IN1R PGA", "IN1RP Switch", "IN1RP" },
0959     { "IN1R PGA", "IN1RN Switch", "IN1RN" },
0960 
0961     { "IN2L PGA", "IN2LP Switch", "IN2LP:VXRN" },
0962     { "IN2L PGA", "IN2LN Switch", "IN2LN" },
0963 
0964     { "IN2R PGA", "IN2RP Switch", "IN2RP:VXRP" },
0965     { "IN2R PGA", "IN2RN Switch", "IN2RN" },
0966 
0967     { "Direct Voice", NULL, "IN2LP:VXRN" },
0968     { "Direct Voice", NULL, "IN2RP:VXRP" },
0969 
0970     { "MIXINL", "IN1L Switch", "IN1L PGA" },
0971     { "MIXINL", "IN2L Switch", "IN2L PGA" },
0972     { "MIXINL", NULL, "Direct Voice" },
0973     { "MIXINL", NULL, "IN1LP" },
0974     { "MIXINL", NULL, "Left Output Mixer" },
0975     { "MIXINL", NULL, "VMID" },
0976 
0977     { "MIXINR", "IN1R Switch", "IN1R PGA" },
0978     { "MIXINR", "IN2R Switch", "IN2R PGA" },
0979     { "MIXINR", NULL, "Direct Voice" },
0980     { "MIXINR", NULL, "IN1RP" },
0981     { "MIXINR", NULL, "Right Output Mixer" },
0982     { "MIXINR", NULL, "VMID" },
0983 
0984     { "ADCL", NULL, "MIXINL" },
0985     { "ADCR", NULL, "MIXINR" },
0986 
0987     { "Left Output Mixer", "Left Input Switch", "MIXINL" },
0988     { "Left Output Mixer", "Right Input Switch", "MIXINR" },
0989     { "Left Output Mixer", "IN2RN Switch", "IN2RN" },
0990     { "Left Output Mixer", "IN2LN Switch", "IN2LN" },
0991     { "Left Output Mixer", "IN2LP Switch", "IN2LP:VXRN" },
0992     { "Left Output Mixer", "IN1L Switch", "IN1L PGA" },
0993     { "Left Output Mixer", "IN1R Switch", "IN1R PGA" },
0994 
0995     { "Right Output Mixer", "Left Input Switch", "MIXINL" },
0996     { "Right Output Mixer", "Right Input Switch", "MIXINR" },
0997     { "Right Output Mixer", "IN2LN Switch", "IN2LN" },
0998     { "Right Output Mixer", "IN2RN Switch", "IN2RN" },
0999     { "Right Output Mixer", "IN2RP Switch", "IN2RP:VXRP" },
1000     { "Right Output Mixer", "IN1L Switch", "IN1L PGA" },
1001     { "Right Output Mixer", "IN1R Switch", "IN1R PGA" },
1002 
1003     { "Left Output PGA", NULL, "Left Output Mixer" },
1004     { "Left Output PGA", NULL, "TOCLK" },
1005 
1006     { "Right Output PGA", NULL, "Right Output Mixer" },
1007     { "Right Output PGA", NULL, "TOCLK" },
1008 
1009     { "Earpiece Mixer", "Direct Voice Switch", "Direct Voice" },
1010     { "Earpiece Mixer", "Left Output Switch", "Left Output PGA" },
1011     { "Earpiece Mixer", "Right Output Switch", "Right Output PGA" },
1012 
1013     { "Earpiece Driver", NULL, "VMID" },
1014     { "Earpiece Driver", NULL, "Earpiece Mixer" },
1015     { "HPOUT2N", NULL, "Earpiece Driver" },
1016     { "HPOUT2P", NULL, "Earpiece Driver" },
1017 
1018     { "SPKL", "Input Switch", "MIXINL" },
1019     { "SPKL", "IN1LP Switch", "IN1LP" },
1020     { "SPKL", "Output Switch", "Left Output PGA" },
1021     { "SPKL", NULL, "TOCLK" },
1022 
1023     { "SPKR", "Input Switch", "MIXINR" },
1024     { "SPKR", "IN1RP Switch", "IN1RP" },
1025     { "SPKR", "Output Switch", "Right Output PGA" },
1026     { "SPKR", NULL, "TOCLK" },
1027 
1028     { "SPKL Boost", "Direct Voice Switch", "Direct Voice" },
1029     { "SPKL Boost", "SPKL Switch", "SPKL" },
1030     { "SPKL Boost", "SPKR Switch", "SPKR" },
1031 
1032     { "SPKR Boost", "Direct Voice Switch", "Direct Voice" },
1033     { "SPKR Boost", "SPKR Switch", "SPKR" },
1034     { "SPKR Boost", "SPKL Switch", "SPKL" },
1035 
1036     { "SPKL Driver", NULL, "VMID" },
1037     { "SPKL Driver", NULL, "SPKL Boost" },
1038     { "SPKL Driver", NULL, "CLK_SYS" },
1039     { "SPKL Driver", NULL, "TSHUT" },
1040 
1041     { "SPKR Driver", NULL, "VMID" },
1042     { "SPKR Driver", NULL, "SPKR Boost" },
1043     { "SPKR Driver", NULL, "CLK_SYS" },
1044     { "SPKR Driver", NULL, "TSHUT" },
1045 
1046     { "SPKOUTLP", NULL, "SPKL Driver" },
1047     { "SPKOUTLN", NULL, "SPKL Driver" },
1048     { "SPKOUTRP", NULL, "SPKR Driver" },
1049     { "SPKOUTRN", NULL, "SPKR Driver" },
1050 
1051     { "Left Headphone Mux", "Mixer", "Left Output PGA" },
1052     { "Right Headphone Mux", "Mixer", "Right Output PGA" },
1053 
1054     { "Headphone PGA", NULL, "Left Headphone Mux" },
1055     { "Headphone PGA", NULL, "Right Headphone Mux" },
1056     { "Headphone PGA", NULL, "VMID" },
1057     { "Headphone PGA", NULL, "CLK_SYS" },
1058     { "Headphone PGA", NULL, "Headphone Supply" },
1059 
1060     { "HPOUT1L", NULL, "Headphone PGA" },
1061     { "HPOUT1R", NULL, "Headphone PGA" },
1062 
1063     { "LINEOUT1N Driver", NULL, "VMID" },
1064     { "LINEOUT1P Driver", NULL, "VMID" },
1065     { "LINEOUT2N Driver", NULL, "VMID" },
1066     { "LINEOUT2P Driver", NULL, "VMID" },
1067 
1068     { "LINEOUT1N", NULL, "LINEOUT1N Driver" },
1069     { "LINEOUT1P", NULL, "LINEOUT1P Driver" },
1070     { "LINEOUT2N", NULL, "LINEOUT2N Driver" },
1071     { "LINEOUT2P", NULL, "LINEOUT2P Driver" },
1072 };
1073 
1074 static const struct snd_soc_dapm_route lineout1_diff_routes[] = {
1075     { "LINEOUT1 Mixer", "IN1L Switch", "IN1L PGA" },
1076     { "LINEOUT1 Mixer", "IN1R Switch", "IN1R PGA" },
1077     { "LINEOUT1 Mixer", "Output Switch", "Left Output PGA" },
1078 
1079     { "LINEOUT1N Driver", NULL, "LINEOUT1 Mixer" },
1080     { "LINEOUT1P Driver", NULL, "LINEOUT1 Mixer" },
1081 };
1082 
1083 static const struct snd_soc_dapm_route lineout1_se_routes[] = {
1084     { "LINEOUT1N Mixer", "Left Output Switch", "Left Output PGA" },
1085     { "LINEOUT1N Mixer", "Right Output Switch", "Right Output PGA" },
1086 
1087     { "LINEOUT1P Mixer", "Left Output Switch", "Left Output PGA" },
1088 
1089     { "LINEOUT1N Driver", NULL, "LINEOUT1N Mixer" },
1090     { "LINEOUT1P Driver", NULL, "LINEOUT1P Mixer" },
1091 };
1092 
1093 static const struct snd_soc_dapm_route lineout2_diff_routes[] = {
1094     { "LINEOUT2 Mixer", "IN1L Switch", "IN1L PGA" },
1095     { "LINEOUT2 Mixer", "IN1R Switch", "IN1R PGA" },
1096     { "LINEOUT2 Mixer", "Output Switch", "Right Output PGA" },
1097 
1098     { "LINEOUT2N Driver", NULL, "LINEOUT2 Mixer" },
1099     { "LINEOUT2P Driver", NULL, "LINEOUT2 Mixer" },
1100 };
1101 
1102 static const struct snd_soc_dapm_route lineout2_se_routes[] = {
1103     { "LINEOUT2N Mixer", "Left Output Switch", "Left Output PGA" },
1104     { "LINEOUT2N Mixer", "Right Output Switch", "Right Output PGA" },
1105 
1106     { "LINEOUT2P Mixer", "Right Output Switch", "Right Output PGA" },
1107 
1108     { "LINEOUT2N Driver", NULL, "LINEOUT2N Mixer" },
1109     { "LINEOUT2P Driver", NULL, "LINEOUT2P Mixer" },
1110 };
1111 
1112 int wm_hubs_add_analogue_controls(struct snd_soc_component *component)
1113 {
1114     struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
1115 
1116     /* Latch volume update bits & default ZC on */
1117     snd_soc_component_update_bits(component, WM8993_LEFT_LINE_INPUT_1_2_VOLUME,
1118                 WM8993_IN1_VU, WM8993_IN1_VU);
1119     snd_soc_component_update_bits(component, WM8993_RIGHT_LINE_INPUT_1_2_VOLUME,
1120                 WM8993_IN1_VU, WM8993_IN1_VU);
1121     snd_soc_component_update_bits(component, WM8993_LEFT_LINE_INPUT_3_4_VOLUME,
1122                 WM8993_IN2_VU, WM8993_IN2_VU);
1123     snd_soc_component_update_bits(component, WM8993_RIGHT_LINE_INPUT_3_4_VOLUME,
1124                 WM8993_IN2_VU, WM8993_IN2_VU);
1125 
1126     snd_soc_component_update_bits(component, WM8993_SPEAKER_VOLUME_LEFT,
1127                 WM8993_SPKOUT_VU, WM8993_SPKOUT_VU);
1128     snd_soc_component_update_bits(component, WM8993_SPEAKER_VOLUME_RIGHT,
1129                 WM8993_SPKOUT_VU, WM8993_SPKOUT_VU);
1130 
1131     snd_soc_component_update_bits(component, WM8993_LEFT_OUTPUT_VOLUME,
1132                 WM8993_HPOUT1_VU | WM8993_HPOUT1L_ZC,
1133                 WM8993_HPOUT1_VU | WM8993_HPOUT1L_ZC);
1134     snd_soc_component_update_bits(component, WM8993_RIGHT_OUTPUT_VOLUME,
1135                 WM8993_HPOUT1_VU | WM8993_HPOUT1R_ZC,
1136                 WM8993_HPOUT1_VU | WM8993_HPOUT1R_ZC);
1137 
1138     snd_soc_component_update_bits(component, WM8993_LEFT_OPGA_VOLUME,
1139                 WM8993_MIXOUTL_ZC | WM8993_MIXOUT_VU,
1140                 WM8993_MIXOUTL_ZC | WM8993_MIXOUT_VU);
1141     snd_soc_component_update_bits(component, WM8993_RIGHT_OPGA_VOLUME,
1142                 WM8993_MIXOUTR_ZC | WM8993_MIXOUT_VU,
1143                 WM8993_MIXOUTR_ZC | WM8993_MIXOUT_VU);
1144 
1145     snd_soc_add_component_controls(component, analogue_snd_controls,
1146                  ARRAY_SIZE(analogue_snd_controls));
1147 
1148     snd_soc_dapm_new_controls(dapm, analogue_dapm_widgets,
1149                   ARRAY_SIZE(analogue_dapm_widgets));
1150     return 0;
1151 }
1152 EXPORT_SYMBOL_GPL(wm_hubs_add_analogue_controls);
1153 
1154 int wm_hubs_add_analogue_routes(struct snd_soc_component *component,
1155                 int lineout1_diff, int lineout2_diff)
1156 {
1157     struct wm_hubs_data *hubs = snd_soc_component_get_drvdata(component);
1158     struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
1159 
1160     hubs->component = component;
1161 
1162     INIT_LIST_HEAD(&hubs->dcs_cache);
1163     init_completion(&hubs->dcs_done);
1164 
1165     snd_soc_dapm_add_routes(dapm, analogue_routes,
1166                 ARRAY_SIZE(analogue_routes));
1167 
1168     if (lineout1_diff)
1169         snd_soc_dapm_add_routes(dapm,
1170                     lineout1_diff_routes,
1171                     ARRAY_SIZE(lineout1_diff_routes));
1172     else
1173         snd_soc_dapm_add_routes(dapm,
1174                     lineout1_se_routes,
1175                     ARRAY_SIZE(lineout1_se_routes));
1176 
1177     if (lineout2_diff)
1178         snd_soc_dapm_add_routes(dapm,
1179                     lineout2_diff_routes,
1180                     ARRAY_SIZE(lineout2_diff_routes));
1181     else
1182         snd_soc_dapm_add_routes(dapm,
1183                     lineout2_se_routes,
1184                     ARRAY_SIZE(lineout2_se_routes));
1185 
1186     return 0;
1187 }
1188 EXPORT_SYMBOL_GPL(wm_hubs_add_analogue_routes);
1189 
1190 int wm_hubs_handle_analogue_pdata(struct snd_soc_component *component,
1191                   int lineout1_diff, int lineout2_diff,
1192                   int lineout1fb, int lineout2fb,
1193                   int jd_scthr, int jd_thr,
1194                   int micbias1_delay, int micbias2_delay,
1195                   int micbias1_lvl, int micbias2_lvl)
1196 {
1197     struct wm_hubs_data *hubs = snd_soc_component_get_drvdata(component);
1198 
1199     hubs->lineout1_se = !lineout1_diff;
1200     hubs->lineout2_se = !lineout2_diff;
1201     hubs->micb1_delay = micbias1_delay;
1202     hubs->micb2_delay = micbias2_delay;
1203 
1204     if (!lineout1_diff)
1205         snd_soc_component_update_bits(component, WM8993_LINE_MIXER1,
1206                     WM8993_LINEOUT1_MODE,
1207                     WM8993_LINEOUT1_MODE);
1208     if (!lineout2_diff)
1209         snd_soc_component_update_bits(component, WM8993_LINE_MIXER2,
1210                     WM8993_LINEOUT2_MODE,
1211                     WM8993_LINEOUT2_MODE);
1212 
1213     if (!lineout1_diff && !lineout2_diff)
1214         snd_soc_component_update_bits(component, WM8993_ANTIPOP1,
1215                     WM8993_LINEOUT_VMID_BUF_ENA,
1216                     WM8993_LINEOUT_VMID_BUF_ENA);
1217 
1218     if (lineout1fb)
1219         snd_soc_component_update_bits(component, WM8993_ADDITIONAL_CONTROL,
1220                     WM8993_LINEOUT1_FB, WM8993_LINEOUT1_FB);
1221 
1222     if (lineout2fb)
1223         snd_soc_component_update_bits(component, WM8993_ADDITIONAL_CONTROL,
1224                     WM8993_LINEOUT2_FB, WM8993_LINEOUT2_FB);
1225 
1226     if (!hubs->micd_scthr)
1227         return 0;
1228 
1229     snd_soc_component_update_bits(component, WM8993_MICBIAS,
1230                 WM8993_JD_SCTHR_MASK | WM8993_JD_THR_MASK |
1231                 WM8993_MICB1_LVL | WM8993_MICB2_LVL,
1232                 jd_scthr << WM8993_JD_SCTHR_SHIFT |
1233                 jd_thr << WM8993_JD_THR_SHIFT |
1234                 micbias1_lvl |
1235                 micbias2_lvl << WM8993_MICB2_LVL_SHIFT);
1236 
1237     return 0;
1238 }
1239 EXPORT_SYMBOL_GPL(wm_hubs_handle_analogue_pdata);
1240 
1241 void wm_hubs_vmid_ena(struct snd_soc_component *component)
1242 {
1243     struct wm_hubs_data *hubs = snd_soc_component_get_drvdata(component);
1244     int val = 0;
1245 
1246     if (hubs->lineout1_se)
1247         val |= WM8993_LINEOUT1N_ENA | WM8993_LINEOUT1P_ENA;
1248 
1249     if (hubs->lineout2_se)
1250         val |= WM8993_LINEOUT2N_ENA | WM8993_LINEOUT2P_ENA;
1251 
1252     /* Enable the line outputs while we power up */
1253     snd_soc_component_update_bits(component, WM8993_POWER_MANAGEMENT_3, val, val);
1254 }
1255 EXPORT_SYMBOL_GPL(wm_hubs_vmid_ena);
1256 
1257 void wm_hubs_set_bias_level(struct snd_soc_component *component,
1258                 enum snd_soc_bias_level level)
1259 {
1260     struct wm_hubs_data *hubs = snd_soc_component_get_drvdata(component);
1261     int mask, val;
1262 
1263     switch (level) {
1264     case SND_SOC_BIAS_STANDBY:
1265         /* Clamp the inputs to VMID while we ramp to charge caps */
1266         snd_soc_component_update_bits(component, WM8993_INPUTS_CLAMP_REG,
1267                     WM8993_INPUTS_CLAMP, WM8993_INPUTS_CLAMP);
1268         break;
1269 
1270     case SND_SOC_BIAS_ON:
1271         /* Turn off any unneeded single ended outputs */
1272         val = 0;
1273         mask = 0;
1274 
1275         if (hubs->lineout1_se)
1276             mask |= WM8993_LINEOUT1N_ENA | WM8993_LINEOUT1P_ENA;
1277 
1278         if (hubs->lineout2_se)
1279             mask |= WM8993_LINEOUT2N_ENA | WM8993_LINEOUT2P_ENA;
1280 
1281         if (hubs->lineout1_se && hubs->lineout1n_ena)
1282             val |= WM8993_LINEOUT1N_ENA;
1283 
1284         if (hubs->lineout1_se && hubs->lineout1p_ena)
1285             val |= WM8993_LINEOUT1P_ENA;
1286 
1287         if (hubs->lineout2_se && hubs->lineout2n_ena)
1288             val |= WM8993_LINEOUT2N_ENA;
1289 
1290         if (hubs->lineout2_se && hubs->lineout2p_ena)
1291             val |= WM8993_LINEOUT2P_ENA;
1292 
1293         snd_soc_component_update_bits(component, WM8993_POWER_MANAGEMENT_3,
1294                     mask, val);
1295 
1296         /* Remove the input clamps */
1297         snd_soc_component_update_bits(component, WM8993_INPUTS_CLAMP_REG,
1298                     WM8993_INPUTS_CLAMP, 0);
1299         break;
1300 
1301     default:
1302         break;
1303     }
1304 }
1305 EXPORT_SYMBOL_GPL(wm_hubs_set_bias_level);
1306 
1307 MODULE_DESCRIPTION("Shared support for Wolfson hubs products");
1308 MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
1309 MODULE_LICENSE("GPL");