0001
0002
0003
0004
0005
0006
0007
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
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
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
0215
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
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
0258
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
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, ®_l, ®_r) < 0)
0285 return;
0286
0287 dev_dbg(component->dev, "DCS input: %x %x\n", reg_l, reg_r);
0288
0289
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
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
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
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
0322
0323 if (wm_hubs_dac_hp_direct(component))
0324 wm_hubs_dcs_cache_set(component, dcs_cfg);
0325 }
0326
0327
0328
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
0340
0341 if (hubs->dcs_codes_l || hubs->dcs_codes_r || hubs->no_series_update)
0342 return ret;
0343
0344
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
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
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
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
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
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
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
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");