1 /* 2 * wm_hubs.c -- WM8993/4 common code 3 * 4 * Copyright 2009 Wolfson Microelectronics plc 5 * 6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> 7 * 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License version 2 as 11 * published by the Free Software Foundation. 12 */ 13 14 #include <linux/module.h> 15 #include <linux/moduleparam.h> 16 #include <linux/init.h> 17 #include <linux/delay.h> 18 #include <linux/pm.h> 19 #include <linux/i2c.h> 20 #include <linux/platform_device.h> 21 #include <sound/core.h> 22 #include <sound/pcm.h> 23 #include <sound/pcm_params.h> 24 #include <sound/soc.h> 25 #include <sound/soc-dapm.h> 26 #include <sound/initval.h> 27 #include <sound/tlv.h> 28 29 #include "wm8993.h" 30 #include "wm_hubs.h" 31 32 const DECLARE_TLV_DB_SCALE(wm_hubs_spkmix_tlv, -300, 300, 0); 33 EXPORT_SYMBOL_GPL(wm_hubs_spkmix_tlv); 34 35 static const DECLARE_TLV_DB_SCALE(inpga_tlv, -1650, 150, 0); 36 static const DECLARE_TLV_DB_SCALE(inmix_sw_tlv, 0, 3000, 0); 37 static const DECLARE_TLV_DB_SCALE(inmix_tlv, -1500, 300, 1); 38 static const DECLARE_TLV_DB_SCALE(earpiece_tlv, -600, 600, 0); 39 static const DECLARE_TLV_DB_SCALE(outmix_tlv, -2100, 300, 0); 40 static const DECLARE_TLV_DB_SCALE(spkmixout_tlv, -1800, 600, 1); 41 static const DECLARE_TLV_DB_SCALE(outpga_tlv, -5700, 100, 0); 42 static const unsigned int spkboost_tlv[] = { 43 TLV_DB_RANGE_HEAD(7), 44 0, 6, TLV_DB_SCALE_ITEM(0, 150, 0), 45 7, 7, TLV_DB_SCALE_ITEM(1200, 0, 0), 46 }; 47 static const DECLARE_TLV_DB_SCALE(line_tlv, -600, 600, 0); 48 49 static const char *speaker_ref_text[] = { 50 "SPKVDD/2", 51 "VMID", 52 }; 53 54 static const struct soc_enum speaker_ref = 55 SOC_ENUM_SINGLE(WM8993_SPEAKER_MIXER, 8, 2, speaker_ref_text); 56 57 static const char *speaker_mode_text[] = { 58 "Class D", 59 "Class AB", 60 }; 61 62 static const struct soc_enum speaker_mode = 63 SOC_ENUM_SINGLE(WM8993_SPKMIXR_ATTENUATION, 8, 2, speaker_mode_text); 64 65 static void wait_for_dc_servo(struct snd_soc_codec *codec) 66 { 67 unsigned int reg; 68 int count = 0; 69 70 dev_dbg(codec->dev, "Waiting for DC servo...\n"); 71 do { 72 count++; 73 msleep(1); 74 reg = snd_soc_read(codec, WM8993_DC_SERVO_READBACK_0); 75 dev_dbg(codec->dev, "DC servo status: %x\n", reg); 76 } while ((reg & WM8993_DCS_CAL_COMPLETE_MASK) 77 != WM8993_DCS_CAL_COMPLETE_MASK && count < 1000); 78 79 if ((reg & WM8993_DCS_CAL_COMPLETE_MASK) 80 != WM8993_DCS_CAL_COMPLETE_MASK) 81 dev_err(codec->dev, "Timed out waiting for DC Servo\n"); 82 } 83 84 /* 85 * Update the DC servo calibration on gain changes 86 */ 87 static int wm8993_put_dc_servo(struct snd_kcontrol *kcontrol, 88 struct snd_ctl_elem_value *ucontrol) 89 { 90 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); 91 int ret; 92 93 ret = snd_soc_put_volsw_2r(kcontrol, ucontrol); 94 95 /* Only need to do this if the outputs are active */ 96 if (snd_soc_read(codec, WM8993_POWER_MANAGEMENT_1) 97 & (WM8993_HPOUT1L_ENA | WM8993_HPOUT1R_ENA)) 98 snd_soc_update_bits(codec, 99 WM8993_DC_SERVO_0, 100 WM8993_DCS_TRIG_SINGLE_0 | 101 WM8993_DCS_TRIG_SINGLE_1, 102 WM8993_DCS_TRIG_SINGLE_0 | 103 WM8993_DCS_TRIG_SINGLE_1); 104 105 return ret; 106 } 107 108 static const struct snd_kcontrol_new analogue_snd_controls[] = { 109 SOC_SINGLE_TLV("IN1L Volume", WM8993_LEFT_LINE_INPUT_1_2_VOLUME, 0, 31, 0, 110 inpga_tlv), 111 SOC_SINGLE("IN1L Switch", WM8993_LEFT_LINE_INPUT_1_2_VOLUME, 7, 1, 1), 112 SOC_SINGLE("IN1L ZC Switch", WM8993_LEFT_LINE_INPUT_1_2_VOLUME, 7, 1, 0), 113 114 SOC_SINGLE_TLV("IN1R Volume", WM8993_RIGHT_LINE_INPUT_1_2_VOLUME, 0, 31, 0, 115 inpga_tlv), 116 SOC_SINGLE("IN1R Switch", WM8993_RIGHT_LINE_INPUT_1_2_VOLUME, 7, 1, 1), 117 SOC_SINGLE("IN1R ZC Switch", WM8993_RIGHT_LINE_INPUT_1_2_VOLUME, 7, 1, 0), 118 119 120 SOC_SINGLE_TLV("IN2L Volume", WM8993_LEFT_LINE_INPUT_3_4_VOLUME, 0, 31, 0, 121 inpga_tlv), 122 SOC_SINGLE("IN2L Switch", WM8993_LEFT_LINE_INPUT_3_4_VOLUME, 7, 1, 1), 123 SOC_SINGLE("IN2L ZC Switch", WM8993_LEFT_LINE_INPUT_3_4_VOLUME, 7, 1, 0), 124 125 SOC_SINGLE_TLV("IN2R Volume", WM8993_RIGHT_LINE_INPUT_3_4_VOLUME, 0, 31, 0, 126 inpga_tlv), 127 SOC_SINGLE("IN2R Switch", WM8993_RIGHT_LINE_INPUT_3_4_VOLUME, 7, 1, 1), 128 SOC_SINGLE("IN2R ZC Switch", WM8993_RIGHT_LINE_INPUT_3_4_VOLUME, 7, 1, 0), 129 130 SOC_SINGLE_TLV("MIXINL IN2L Volume", WM8993_INPUT_MIXER3, 7, 1, 0, 131 inmix_sw_tlv), 132 SOC_SINGLE_TLV("MIXINL IN1L Volume", WM8993_INPUT_MIXER3, 4, 1, 0, 133 inmix_sw_tlv), 134 SOC_SINGLE_TLV("MIXINL Output Record Volume", WM8993_INPUT_MIXER3, 0, 7, 0, 135 inmix_tlv), 136 SOC_SINGLE_TLV("MIXINL IN1LP Volume", WM8993_INPUT_MIXER5, 6, 7, 0, inmix_tlv), 137 SOC_SINGLE_TLV("MIXINL Direct Voice Volume", WM8993_INPUT_MIXER5, 0, 6, 0, 138 inmix_tlv), 139 140 SOC_SINGLE_TLV("MIXINR IN2R Volume", WM8993_INPUT_MIXER4, 7, 1, 0, 141 inmix_sw_tlv), 142 SOC_SINGLE_TLV("MIXINR IN1R Volume", WM8993_INPUT_MIXER4, 4, 1, 0, 143 inmix_sw_tlv), 144 SOC_SINGLE_TLV("MIXINR Output Record Volume", WM8993_INPUT_MIXER4, 0, 7, 0, 145 inmix_tlv), 146 SOC_SINGLE_TLV("MIXINR IN1RP Volume", WM8993_INPUT_MIXER6, 6, 7, 0, inmix_tlv), 147 SOC_SINGLE_TLV("MIXINR Direct Voice Volume", WM8993_INPUT_MIXER6, 0, 6, 0, 148 inmix_tlv), 149 150 SOC_SINGLE_TLV("Left Output Mixer IN2RN Volume", WM8993_OUTPUT_MIXER5, 6, 7, 1, 151 outmix_tlv), 152 SOC_SINGLE_TLV("Left Output Mixer IN2LN Volume", WM8993_OUTPUT_MIXER3, 6, 7, 1, 153 outmix_tlv), 154 SOC_SINGLE_TLV("Left Output Mixer IN2LP Volume", WM8993_OUTPUT_MIXER3, 9, 7, 1, 155 outmix_tlv), 156 SOC_SINGLE_TLV("Left Output Mixer IN1L Volume", WM8993_OUTPUT_MIXER3, 0, 7, 1, 157 outmix_tlv), 158 SOC_SINGLE_TLV("Left Output Mixer IN1R Volume", WM8993_OUTPUT_MIXER3, 3, 7, 1, 159 outmix_tlv), 160 SOC_SINGLE_TLV("Left Output Mixer Right Input Volume", 161 WM8993_OUTPUT_MIXER5, 3, 7, 1, outmix_tlv), 162 SOC_SINGLE_TLV("Left Output Mixer Left Input Volume", 163 WM8993_OUTPUT_MIXER5, 0, 7, 1, outmix_tlv), 164 SOC_SINGLE_TLV("Left Output Mixer DAC Volume", WM8993_OUTPUT_MIXER5, 9, 7, 1, 165 outmix_tlv), 166 167 SOC_SINGLE_TLV("Right Output Mixer IN2LN Volume", 168 WM8993_OUTPUT_MIXER6, 6, 7, 1, outmix_tlv), 169 SOC_SINGLE_TLV("Right Output Mixer IN2RN Volume", 170 WM8993_OUTPUT_MIXER4, 6, 7, 1, outmix_tlv), 171 SOC_SINGLE_TLV("Right Output Mixer IN1L Volume", 172 WM8993_OUTPUT_MIXER4, 3, 7, 1, outmix_tlv), 173 SOC_SINGLE_TLV("Right Output Mixer IN1R Volume", 174 WM8993_OUTPUT_MIXER4, 0, 7, 1, outmix_tlv), 175 SOC_SINGLE_TLV("Right Output Mixer IN2RP Volume", 176 WM8993_OUTPUT_MIXER4, 9, 7, 1, outmix_tlv), 177 SOC_SINGLE_TLV("Right Output Mixer Left Input Volume", 178 WM8993_OUTPUT_MIXER6, 3, 7, 1, outmix_tlv), 179 SOC_SINGLE_TLV("Right Output Mixer Right Input Volume", 180 WM8993_OUTPUT_MIXER6, 6, 7, 1, outmix_tlv), 181 SOC_SINGLE_TLV("Right Output Mixer DAC Volume", 182 WM8993_OUTPUT_MIXER6, 9, 7, 1, outmix_tlv), 183 184 SOC_DOUBLE_R_TLV("Output Volume", WM8993_LEFT_OPGA_VOLUME, 185 WM8993_RIGHT_OPGA_VOLUME, 0, 63, 0, outpga_tlv), 186 SOC_DOUBLE_R("Output Switch", WM8993_LEFT_OPGA_VOLUME, 187 WM8993_RIGHT_OPGA_VOLUME, 6, 1, 0), 188 SOC_DOUBLE_R("Output ZC Switch", WM8993_LEFT_OPGA_VOLUME, 189 WM8993_RIGHT_OPGA_VOLUME, 7, 1, 0), 190 191 SOC_SINGLE("Earpiece Switch", WM8993_HPOUT2_VOLUME, 5, 1, 1), 192 SOC_SINGLE_TLV("Earpiece Volume", WM8993_HPOUT2_VOLUME, 4, 1, 1, earpiece_tlv), 193 194 SOC_SINGLE_TLV("SPKL Input Volume", WM8993_SPKMIXL_ATTENUATION, 195 5, 1, 1, wm_hubs_spkmix_tlv), 196 SOC_SINGLE_TLV("SPKL IN1LP Volume", WM8993_SPKMIXL_ATTENUATION, 197 4, 1, 1, wm_hubs_spkmix_tlv), 198 SOC_SINGLE_TLV("SPKL Output Volume", WM8993_SPKMIXL_ATTENUATION, 199 3, 1, 1, wm_hubs_spkmix_tlv), 200 201 SOC_SINGLE_TLV("SPKR Input Volume", WM8993_SPKMIXR_ATTENUATION, 202 5, 1, 1, wm_hubs_spkmix_tlv), 203 SOC_SINGLE_TLV("SPKR IN1RP Volume", WM8993_SPKMIXR_ATTENUATION, 204 4, 1, 1, wm_hubs_spkmix_tlv), 205 SOC_SINGLE_TLV("SPKR Output Volume", WM8993_SPKMIXR_ATTENUATION, 206 3, 1, 1, wm_hubs_spkmix_tlv), 207 208 SOC_DOUBLE_R_TLV("Speaker Mixer Volume", 209 WM8993_SPKMIXL_ATTENUATION, WM8993_SPKMIXR_ATTENUATION, 210 0, 3, 1, spkmixout_tlv), 211 SOC_DOUBLE_R_TLV("Speaker Volume", 212 WM8993_SPEAKER_VOLUME_LEFT, WM8993_SPEAKER_VOLUME_RIGHT, 213 0, 63, 0, outpga_tlv), 214 SOC_DOUBLE_R("Speaker Switch", 215 WM8993_SPEAKER_VOLUME_LEFT, WM8993_SPEAKER_VOLUME_RIGHT, 216 6, 1, 0), 217 SOC_DOUBLE_R("Speaker ZC Switch", 218 WM8993_SPEAKER_VOLUME_LEFT, WM8993_SPEAKER_VOLUME_RIGHT, 219 7, 1, 0), 220 SOC_DOUBLE_TLV("Speaker Boost Volume", WM8993_SPKOUT_BOOST, 0, 3, 7, 0, 221 spkboost_tlv), 222 SOC_ENUM("Speaker Reference", speaker_ref), 223 SOC_ENUM("Speaker Mode", speaker_mode), 224 225 { 226 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Headphone Volume", 227 .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | 228 SNDRV_CTL_ELEM_ACCESS_READWRITE, 229 .tlv.p = outpga_tlv, 230 .info = snd_soc_info_volsw_2r, 231 .get = snd_soc_get_volsw_2r, .put = wm8993_put_dc_servo, 232 .private_value = (unsigned long)&(struct soc_mixer_control) { 233 .reg = WM8993_LEFT_OUTPUT_VOLUME, 234 .rreg = WM8993_RIGHT_OUTPUT_VOLUME, 235 .shift = 0, .max = 63 236 }, 237 }, 238 SOC_DOUBLE_R("Headphone Switch", WM8993_LEFT_OUTPUT_VOLUME, 239 WM8993_RIGHT_OUTPUT_VOLUME, 6, 1, 0), 240 SOC_DOUBLE_R("Headphone ZC Switch", WM8993_LEFT_OUTPUT_VOLUME, 241 WM8993_RIGHT_OUTPUT_VOLUME, 7, 1, 0), 242 243 SOC_SINGLE("LINEOUT1N Switch", WM8993_LINE_OUTPUTS_VOLUME, 6, 1, 1), 244 SOC_SINGLE("LINEOUT1P Switch", WM8993_LINE_OUTPUTS_VOLUME, 5, 1, 1), 245 SOC_SINGLE_TLV("LINEOUT1 Volume", WM8993_LINE_OUTPUTS_VOLUME, 4, 1, 1, 246 line_tlv), 247 248 SOC_SINGLE("LINEOUT2N Switch", WM8993_LINE_OUTPUTS_VOLUME, 2, 1, 1), 249 SOC_SINGLE("LINEOUT2P Switch", WM8993_LINE_OUTPUTS_VOLUME, 1, 1, 1), 250 SOC_SINGLE_TLV("LINEOUT2 Volume", WM8993_LINE_OUTPUTS_VOLUME, 0, 1, 1, 251 line_tlv), 252 }; 253 254 static int hp_event(struct snd_soc_dapm_widget *w, 255 struct snd_kcontrol *kcontrol, int event) 256 { 257 struct snd_soc_codec *codec = w->codec; 258 unsigned int reg = snd_soc_read(codec, WM8993_ANALOGUE_HP_0); 259 260 switch (event) { 261 case SND_SOC_DAPM_POST_PMU: 262 snd_soc_update_bits(codec, WM8993_CHARGE_PUMP_1, 263 WM8993_CP_ENA, WM8993_CP_ENA); 264 265 msleep(5); 266 267 snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_1, 268 WM8993_HPOUT1L_ENA | WM8993_HPOUT1R_ENA, 269 WM8993_HPOUT1L_ENA | WM8993_HPOUT1R_ENA); 270 271 reg |= WM8993_HPOUT1L_DLY | WM8993_HPOUT1R_DLY; 272 snd_soc_write(codec, WM8993_ANALOGUE_HP_0, reg); 273 274 /* Start the DC servo */ 275 snd_soc_update_bits(codec, WM8993_DC_SERVO_0, 276 0xFFFF, 277 WM8993_DCS_ENA_CHAN_0 | 278 WM8993_DCS_ENA_CHAN_1 | 279 WM8993_DCS_TRIG_STARTUP_1 | 280 WM8993_DCS_TRIG_STARTUP_0); 281 wait_for_dc_servo(codec); 282 283 reg |= WM8993_HPOUT1R_OUTP | WM8993_HPOUT1R_RMV_SHORT | 284 WM8993_HPOUT1L_OUTP | WM8993_HPOUT1L_RMV_SHORT; 285 snd_soc_write(codec, WM8993_ANALOGUE_HP_0, reg); 286 break; 287 288 case SND_SOC_DAPM_PRE_PMD: 289 reg &= ~(WM8993_HPOUT1L_RMV_SHORT | 290 WM8993_HPOUT1L_DLY | 291 WM8993_HPOUT1L_OUTP | 292 WM8993_HPOUT1R_RMV_SHORT | 293 WM8993_HPOUT1R_DLY | 294 WM8993_HPOUT1R_OUTP); 295 296 snd_soc_update_bits(codec, WM8993_DC_SERVO_0, 297 0xffff, 0); 298 299 snd_soc_write(codec, WM8993_ANALOGUE_HP_0, reg); 300 snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_1, 301 WM8993_HPOUT1L_ENA | WM8993_HPOUT1R_ENA, 302 0); 303 304 snd_soc_update_bits(codec, WM8993_CHARGE_PUMP_1, 305 WM8993_CP_ENA, 0); 306 break; 307 } 308 309 return 0; 310 } 311 312 static int earpiece_event(struct snd_soc_dapm_widget *w, 313 struct snd_kcontrol *control, int event) 314 { 315 struct snd_soc_codec *codec = w->codec; 316 u16 reg = snd_soc_read(codec, WM8993_ANTIPOP1) & ~WM8993_HPOUT2_IN_ENA; 317 318 switch (event) { 319 case SND_SOC_DAPM_PRE_PMU: 320 reg |= WM8993_HPOUT2_IN_ENA; 321 snd_soc_write(codec, WM8993_ANTIPOP1, reg); 322 udelay(50); 323 break; 324 325 case SND_SOC_DAPM_POST_PMD: 326 snd_soc_write(codec, WM8993_ANTIPOP1, reg); 327 break; 328 329 default: 330 BUG(); 331 break; 332 } 333 334 return 0; 335 } 336 337 static const struct snd_kcontrol_new in1l_pga[] = { 338 SOC_DAPM_SINGLE("IN1LP Switch", WM8993_INPUT_MIXER2, 5, 1, 0), 339 SOC_DAPM_SINGLE("IN1LN Switch", WM8993_INPUT_MIXER2, 4, 1, 0), 340 }; 341 342 static const struct snd_kcontrol_new in1r_pga[] = { 343 SOC_DAPM_SINGLE("IN1RP Switch", WM8993_INPUT_MIXER2, 1, 1, 0), 344 SOC_DAPM_SINGLE("IN1RN Switch", WM8993_INPUT_MIXER2, 0, 1, 0), 345 }; 346 347 static const struct snd_kcontrol_new in2l_pga[] = { 348 SOC_DAPM_SINGLE("IN2LP Switch", WM8993_INPUT_MIXER2, 7, 1, 0), 349 SOC_DAPM_SINGLE("IN2LN Switch", WM8993_INPUT_MIXER2, 6, 1, 0), 350 }; 351 352 static const struct snd_kcontrol_new in2r_pga[] = { 353 SOC_DAPM_SINGLE("IN2RP Switch", WM8993_INPUT_MIXER2, 3, 1, 0), 354 SOC_DAPM_SINGLE("IN2RN Switch", WM8993_INPUT_MIXER2, 2, 1, 0), 355 }; 356 357 static const struct snd_kcontrol_new mixinl[] = { 358 SOC_DAPM_SINGLE("IN2L Switch", WM8993_INPUT_MIXER3, 8, 1, 0), 359 SOC_DAPM_SINGLE("IN1L Switch", WM8993_INPUT_MIXER3, 5, 1, 0), 360 }; 361 362 static const struct snd_kcontrol_new mixinr[] = { 363 SOC_DAPM_SINGLE("IN2R Switch", WM8993_INPUT_MIXER4, 8, 1, 0), 364 SOC_DAPM_SINGLE("IN1R Switch", WM8993_INPUT_MIXER4, 5, 1, 0), 365 }; 366 367 static const struct snd_kcontrol_new left_output_mixer[] = { 368 SOC_DAPM_SINGLE("Right Input Switch", WM8993_OUTPUT_MIXER1, 7, 1, 0), 369 SOC_DAPM_SINGLE("Left Input Switch", WM8993_OUTPUT_MIXER1, 6, 1, 0), 370 SOC_DAPM_SINGLE("IN2RN Switch", WM8993_OUTPUT_MIXER1, 5, 1, 0), 371 SOC_DAPM_SINGLE("IN2LN Switch", WM8993_OUTPUT_MIXER1, 4, 1, 0), 372 SOC_DAPM_SINGLE("IN2LP Switch", WM8993_OUTPUT_MIXER1, 1, 1, 0), 373 SOC_DAPM_SINGLE("IN1R Switch", WM8993_OUTPUT_MIXER1, 3, 1, 0), 374 SOC_DAPM_SINGLE("IN1L Switch", WM8993_OUTPUT_MIXER1, 2, 1, 0), 375 SOC_DAPM_SINGLE("DAC Switch", WM8993_OUTPUT_MIXER1, 0, 1, 0), 376 }; 377 378 static const struct snd_kcontrol_new right_output_mixer[] = { 379 SOC_DAPM_SINGLE("Left Input Switch", WM8993_OUTPUT_MIXER2, 7, 1, 0), 380 SOC_DAPM_SINGLE("Right Input Switch", WM8993_OUTPUT_MIXER2, 6, 1, 0), 381 SOC_DAPM_SINGLE("IN2LN Switch", WM8993_OUTPUT_MIXER2, 5, 1, 0), 382 SOC_DAPM_SINGLE("IN2RN Switch", WM8993_OUTPUT_MIXER2, 4, 1, 0), 383 SOC_DAPM_SINGLE("IN1L Switch", WM8993_OUTPUT_MIXER2, 3, 1, 0), 384 SOC_DAPM_SINGLE("IN1R Switch", WM8993_OUTPUT_MIXER2, 2, 1, 0), 385 SOC_DAPM_SINGLE("IN2RP Switch", WM8993_OUTPUT_MIXER2, 1, 1, 0), 386 SOC_DAPM_SINGLE("DAC Switch", WM8993_OUTPUT_MIXER2, 0, 1, 0), 387 }; 388 389 static const struct snd_kcontrol_new earpiece_mixer[] = { 390 SOC_DAPM_SINGLE("Direct Voice Switch", WM8993_HPOUT2_MIXER, 5, 1, 0), 391 SOC_DAPM_SINGLE("Left Output Switch", WM8993_HPOUT2_MIXER, 4, 1, 0), 392 SOC_DAPM_SINGLE("Right Output Switch", WM8993_HPOUT2_MIXER, 3, 1, 0), 393 }; 394 395 static const struct snd_kcontrol_new left_speaker_boost[] = { 396 SOC_DAPM_SINGLE("Direct Voice Switch", WM8993_SPKOUT_MIXERS, 5, 1, 0), 397 SOC_DAPM_SINGLE("SPKL Switch", WM8993_SPKOUT_MIXERS, 4, 1, 0), 398 SOC_DAPM_SINGLE("SPKR Switch", WM8993_SPKOUT_MIXERS, 3, 1, 0), 399 }; 400 401 static const struct snd_kcontrol_new right_speaker_boost[] = { 402 SOC_DAPM_SINGLE("Direct Voice Switch", WM8993_SPKOUT_MIXERS, 2, 1, 0), 403 SOC_DAPM_SINGLE("SPKL Switch", WM8993_SPKOUT_MIXERS, 1, 1, 0), 404 SOC_DAPM_SINGLE("SPKR Switch", WM8993_SPKOUT_MIXERS, 0, 1, 0), 405 }; 406 407 static const struct snd_kcontrol_new line1_mix[] = { 408 SOC_DAPM_SINGLE("IN1R Switch", WM8993_LINE_MIXER1, 2, 1, 0), 409 SOC_DAPM_SINGLE("IN1L Switch", WM8993_LINE_MIXER1, 1, 1, 0), 410 SOC_DAPM_SINGLE("Output Switch", WM8993_LINE_MIXER1, 0, 1, 0), 411 }; 412 413 static const struct snd_kcontrol_new line1n_mix[] = { 414 SOC_DAPM_SINGLE("Left Output Switch", WM8993_LINE_MIXER1, 6, 1, 0), 415 SOC_DAPM_SINGLE("Right Output Switch", WM8993_LINE_MIXER1, 5, 1, 0), 416 }; 417 418 static const struct snd_kcontrol_new line1p_mix[] = { 419 SOC_DAPM_SINGLE("Left Output Switch", WM8993_LINE_MIXER1, 0, 1, 0), 420 }; 421 422 static const struct snd_kcontrol_new line2_mix[] = { 423 SOC_DAPM_SINGLE("IN2R Switch", WM8993_LINE_MIXER2, 2, 1, 0), 424 SOC_DAPM_SINGLE("IN2L Switch", WM8993_LINE_MIXER2, 1, 1, 0), 425 SOC_DAPM_SINGLE("Output Switch", WM8993_LINE_MIXER2, 0, 1, 0), 426 }; 427 428 static const struct snd_kcontrol_new line2n_mix[] = { 429 SOC_DAPM_SINGLE("Left Output Switch", WM8993_LINE_MIXER2, 6, 1, 0), 430 SOC_DAPM_SINGLE("Right Output Switch", WM8993_LINE_MIXER2, 5, 1, 0), 431 }; 432 433 static const struct snd_kcontrol_new line2p_mix[] = { 434 SOC_DAPM_SINGLE("Right Output Switch", WM8993_LINE_MIXER2, 0, 1, 0), 435 }; 436 437 static const struct snd_soc_dapm_widget analogue_dapm_widgets[] = { 438 SND_SOC_DAPM_INPUT("IN1LN"), 439 SND_SOC_DAPM_INPUT("IN1LP"), 440 SND_SOC_DAPM_INPUT("IN2LN"), 441 SND_SOC_DAPM_INPUT("IN2LP/VXRN"), 442 SND_SOC_DAPM_INPUT("IN1RN"), 443 SND_SOC_DAPM_INPUT("IN1RP"), 444 SND_SOC_DAPM_INPUT("IN2RN"), 445 SND_SOC_DAPM_INPUT("IN2RP/VXRP"), 446 447 SND_SOC_DAPM_MICBIAS("MICBIAS2", WM8993_POWER_MANAGEMENT_1, 5, 0), 448 SND_SOC_DAPM_MICBIAS("MICBIAS1", WM8993_POWER_MANAGEMENT_1, 4, 0), 449 450 SND_SOC_DAPM_MIXER("IN1L PGA", WM8993_POWER_MANAGEMENT_2, 6, 0, 451 in1l_pga, ARRAY_SIZE(in1l_pga)), 452 SND_SOC_DAPM_MIXER("IN1R PGA", WM8993_POWER_MANAGEMENT_2, 4, 0, 453 in1r_pga, ARRAY_SIZE(in1r_pga)), 454 455 SND_SOC_DAPM_MIXER("IN2L PGA", WM8993_POWER_MANAGEMENT_2, 7, 0, 456 in2l_pga, ARRAY_SIZE(in2l_pga)), 457 SND_SOC_DAPM_MIXER("IN2R PGA", WM8993_POWER_MANAGEMENT_2, 5, 0, 458 in2r_pga, ARRAY_SIZE(in2r_pga)), 459 460 /* Dummy widgets to represent differential paths */ 461 SND_SOC_DAPM_PGA("Direct Voice", SND_SOC_NOPM, 0, 0, NULL, 0), 462 463 SND_SOC_DAPM_MIXER("MIXINL", WM8993_POWER_MANAGEMENT_2, 9, 0, 464 mixinl, ARRAY_SIZE(mixinl)), 465 SND_SOC_DAPM_MIXER("MIXINR", WM8993_POWER_MANAGEMENT_2, 8, 0, 466 mixinr, ARRAY_SIZE(mixinr)), 467 468 SND_SOC_DAPM_MIXER("Left Output Mixer", WM8993_POWER_MANAGEMENT_3, 5, 0, 469 left_output_mixer, ARRAY_SIZE(left_output_mixer)), 470 SND_SOC_DAPM_MIXER("Right Output Mixer", WM8993_POWER_MANAGEMENT_3, 4, 0, 471 right_output_mixer, ARRAY_SIZE(right_output_mixer)), 472 473 SND_SOC_DAPM_PGA("Left Output PGA", WM8993_POWER_MANAGEMENT_3, 7, 0, NULL, 0), 474 SND_SOC_DAPM_PGA("Right Output PGA", WM8993_POWER_MANAGEMENT_3, 6, 0, NULL, 0), 475 476 SND_SOC_DAPM_PGA_E("Headphone PGA", SND_SOC_NOPM, 0, 0, 477 NULL, 0, 478 hp_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), 479 480 SND_SOC_DAPM_MIXER("Earpiece Mixer", SND_SOC_NOPM, 0, 0, 481 earpiece_mixer, ARRAY_SIZE(earpiece_mixer)), 482 SND_SOC_DAPM_PGA_E("Earpiece Driver", WM8993_POWER_MANAGEMENT_1, 11, 0, 483 NULL, 0, earpiece_event, 484 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), 485 486 SND_SOC_DAPM_MIXER("SPKL Boost", SND_SOC_NOPM, 0, 0, 487 left_speaker_boost, ARRAY_SIZE(left_speaker_boost)), 488 SND_SOC_DAPM_MIXER("SPKR Boost", SND_SOC_NOPM, 0, 0, 489 right_speaker_boost, ARRAY_SIZE(right_speaker_boost)), 490 491 SND_SOC_DAPM_PGA("SPKL Driver", WM8993_POWER_MANAGEMENT_1, 12, 0, 492 NULL, 0), 493 SND_SOC_DAPM_PGA("SPKR Driver", WM8993_POWER_MANAGEMENT_1, 13, 0, 494 NULL, 0), 495 496 SND_SOC_DAPM_MIXER("LINEOUT1 Mixer", SND_SOC_NOPM, 0, 0, 497 line1_mix, ARRAY_SIZE(line1_mix)), 498 SND_SOC_DAPM_MIXER("LINEOUT2 Mixer", SND_SOC_NOPM, 0, 0, 499 line2_mix, ARRAY_SIZE(line2_mix)), 500 501 SND_SOC_DAPM_MIXER("LINEOUT1N Mixer", SND_SOC_NOPM, 0, 0, 502 line1n_mix, ARRAY_SIZE(line1n_mix)), 503 SND_SOC_DAPM_MIXER("LINEOUT1P Mixer", SND_SOC_NOPM, 0, 0, 504 line1p_mix, ARRAY_SIZE(line1p_mix)), 505 SND_SOC_DAPM_MIXER("LINEOUT2N Mixer", SND_SOC_NOPM, 0, 0, 506 line2n_mix, ARRAY_SIZE(line2n_mix)), 507 SND_SOC_DAPM_MIXER("LINEOUT2P Mixer", SND_SOC_NOPM, 0, 0, 508 line2p_mix, ARRAY_SIZE(line2p_mix)), 509 510 SND_SOC_DAPM_PGA("LINEOUT1N Driver", WM8993_POWER_MANAGEMENT_3, 13, 0, 511 NULL, 0), 512 SND_SOC_DAPM_PGA("LINEOUT1P Driver", WM8993_POWER_MANAGEMENT_3, 12, 0, 513 NULL, 0), 514 SND_SOC_DAPM_PGA("LINEOUT2N Driver", WM8993_POWER_MANAGEMENT_3, 11, 0, 515 NULL, 0), 516 SND_SOC_DAPM_PGA("LINEOUT2P Driver", WM8993_POWER_MANAGEMENT_3, 10, 0, 517 NULL, 0), 518 519 SND_SOC_DAPM_OUTPUT("SPKOUTLP"), 520 SND_SOC_DAPM_OUTPUT("SPKOUTLN"), 521 SND_SOC_DAPM_OUTPUT("SPKOUTRP"), 522 SND_SOC_DAPM_OUTPUT("SPKOUTRN"), 523 SND_SOC_DAPM_OUTPUT("HPOUT1L"), 524 SND_SOC_DAPM_OUTPUT("HPOUT1R"), 525 SND_SOC_DAPM_OUTPUT("HPOUT2P"), 526 SND_SOC_DAPM_OUTPUT("HPOUT2N"), 527 SND_SOC_DAPM_OUTPUT("LINEOUT1P"), 528 SND_SOC_DAPM_OUTPUT("LINEOUT1N"), 529 SND_SOC_DAPM_OUTPUT("LINEOUT2P"), 530 SND_SOC_DAPM_OUTPUT("LINEOUT2N"), 531 }; 532 533 static const struct snd_soc_dapm_route analogue_routes[] = { 534 { "IN1L PGA", "IN1LP Switch", "IN1LP" }, 535 { "IN1L PGA", "IN1LN Switch", "IN1LN" }, 536 537 { "IN1R PGA", "IN1RP Switch", "IN1RP" }, 538 { "IN1R PGA", "IN1RN Switch", "IN1RN" }, 539 540 { "IN2L PGA", "IN2LP Switch", "IN2LP/VXRN" }, 541 { "IN2L PGA", "IN2LN Switch", "IN2LN" }, 542 543 { "IN2R PGA", "IN2RP Switch", "IN2RP/VXRP" }, 544 { "IN2R PGA", "IN2RN Switch", "IN2RN" }, 545 546 { "Direct Voice", NULL, "IN2LP/VXRN" }, 547 { "Direct Voice", NULL, "IN2RP/VXRP" }, 548 549 { "MIXINL", "IN1L Switch", "IN1L PGA" }, 550 { "MIXINL", "IN2L Switch", "IN2L PGA" }, 551 { "MIXINL", NULL, "Direct Voice" }, 552 { "MIXINL", NULL, "IN1LP" }, 553 { "MIXINL", NULL, "Left Output Mixer" }, 554 555 { "MIXINR", "IN1R Switch", "IN1R PGA" }, 556 { "MIXINR", "IN2R Switch", "IN2R PGA" }, 557 { "MIXINR", NULL, "Direct Voice" }, 558 { "MIXINR", NULL, "IN1RP" }, 559 { "MIXINR", NULL, "Right Output Mixer" }, 560 561 { "ADCL", NULL, "MIXINL" }, 562 { "ADCR", NULL, "MIXINR" }, 563 564 { "Left Output Mixer", "Left Input Switch", "MIXINL" }, 565 { "Left Output Mixer", "Right Input Switch", "MIXINR" }, 566 { "Left Output Mixer", "IN2RN Switch", "IN2RN" }, 567 { "Left Output Mixer", "IN2LN Switch", "IN2LN" }, 568 { "Left Output Mixer", "IN2LP Switch", "IN2LP/VXRN" }, 569 { "Left Output Mixer", "IN1L Switch", "IN1L PGA" }, 570 { "Left Output Mixer", "IN1R Switch", "IN1R PGA" }, 571 572 { "Right Output Mixer", "Left Input Switch", "MIXINL" }, 573 { "Right Output Mixer", "Right Input Switch", "MIXINR" }, 574 { "Right Output Mixer", "IN2LN Switch", "IN2LN" }, 575 { "Right Output Mixer", "IN2RN Switch", "IN2RN" }, 576 { "Right Output Mixer", "IN2RP Switch", "IN2RP/VXRP" }, 577 { "Right Output Mixer", "IN1L Switch", "IN1L PGA" }, 578 { "Right Output Mixer", "IN1R Switch", "IN1R PGA" }, 579 580 { "Left Output PGA", NULL, "Left Output Mixer" }, 581 { "Left Output PGA", NULL, "TOCLK" }, 582 583 { "Right Output PGA", NULL, "Right Output Mixer" }, 584 { "Right Output PGA", NULL, "TOCLK" }, 585 586 { "Earpiece Mixer", "Direct Voice Switch", "Direct Voice" }, 587 { "Earpiece Mixer", "Left Output Switch", "Left Output PGA" }, 588 { "Earpiece Mixer", "Right Output Switch", "Right Output PGA" }, 589 590 { "Earpiece Driver", NULL, "Earpiece Mixer" }, 591 { "HPOUT2N", NULL, "Earpiece Driver" }, 592 { "HPOUT2P", NULL, "Earpiece Driver" }, 593 594 { "SPKL", "Input Switch", "MIXINL" }, 595 { "SPKL", "IN1LP Switch", "IN1LP" }, 596 { "SPKL", "Output Switch", "Left Output Mixer" }, 597 { "SPKL", NULL, "TOCLK" }, 598 599 { "SPKR", "Input Switch", "MIXINR" }, 600 { "SPKR", "IN1RP Switch", "IN1RP" }, 601 { "SPKR", "Output Switch", "Right Output Mixer" }, 602 { "SPKR", NULL, "TOCLK" }, 603 604 { "SPKL Boost", "Direct Voice Switch", "Direct Voice" }, 605 { "SPKL Boost", "SPKL Switch", "SPKL" }, 606 { "SPKL Boost", "SPKR Switch", "SPKR" }, 607 608 { "SPKR Boost", "Direct Voice Switch", "Direct Voice" }, 609 { "SPKR Boost", "SPKR Switch", "SPKR" }, 610 { "SPKR Boost", "SPKL Switch", "SPKL" }, 611 612 { "SPKL Driver", NULL, "SPKL Boost" }, 613 { "SPKL Driver", NULL, "CLK_SYS" }, 614 615 { "SPKR Driver", NULL, "SPKR Boost" }, 616 { "SPKR Driver", NULL, "CLK_SYS" }, 617 618 { "SPKOUTLP", NULL, "SPKL Driver" }, 619 { "SPKOUTLN", NULL, "SPKL Driver" }, 620 { "SPKOUTRP", NULL, "SPKR Driver" }, 621 { "SPKOUTRN", NULL, "SPKR Driver" }, 622 623 { "Left Headphone Mux", "Mixer", "Left Output Mixer" }, 624 { "Right Headphone Mux", "Mixer", "Right Output Mixer" }, 625 626 { "Headphone PGA", NULL, "Left Headphone Mux" }, 627 { "Headphone PGA", NULL, "Right Headphone Mux" }, 628 { "Headphone PGA", NULL, "CLK_SYS" }, 629 630 { "HPOUT1L", NULL, "Headphone PGA" }, 631 { "HPOUT1R", NULL, "Headphone PGA" }, 632 633 { "LINEOUT1N", NULL, "LINEOUT1N Driver" }, 634 { "LINEOUT1P", NULL, "LINEOUT1P Driver" }, 635 { "LINEOUT2N", NULL, "LINEOUT2N Driver" }, 636 { "LINEOUT2P", NULL, "LINEOUT2P Driver" }, 637 }; 638 639 static const struct snd_soc_dapm_route lineout1_diff_routes[] = { 640 { "LINEOUT1 Mixer", "IN1L Switch", "IN1L PGA" }, 641 { "LINEOUT1 Mixer", "IN1R Switch", "IN1R PGA" }, 642 { "LINEOUT1 Mixer", "Output Switch", "Left Output Mixer" }, 643 644 { "LINEOUT1N Driver", NULL, "LINEOUT1 Mixer" }, 645 { "LINEOUT1P Driver", NULL, "LINEOUT1 Mixer" }, 646 }; 647 648 static const struct snd_soc_dapm_route lineout1_se_routes[] = { 649 { "LINEOUT1N Mixer", "Left Output Switch", "Left Output Mixer" }, 650 { "LINEOUT1N Mixer", "Right Output Switch", "Left Output Mixer" }, 651 652 { "LINEOUT1P Mixer", "Left Output Switch", "Left Output Mixer" }, 653 654 { "LINEOUT1N Driver", NULL, "LINEOUT1N Mixer" }, 655 { "LINEOUT1P Driver", NULL, "LINEOUT1P Mixer" }, 656 }; 657 658 static const struct snd_soc_dapm_route lineout2_diff_routes[] = { 659 { "LINEOUT2 Mixer", "IN2L Switch", "IN2L PGA" }, 660 { "LINEOUT2 Mixer", "IN2R Switch", "IN2R PGA" }, 661 { "LINEOUT2 Mixer", "Output Switch", "Right Output Mixer" }, 662 663 { "LINEOUT2N Driver", NULL, "LINEOUT2 Mixer" }, 664 { "LINEOUT2P Driver", NULL, "LINEOUT2 Mixer" }, 665 }; 666 667 static const struct snd_soc_dapm_route lineout2_se_routes[] = { 668 { "LINEOUT2N Mixer", "Left Output Switch", "Left Output Mixer" }, 669 { "LINEOUT2N Mixer", "Right Output Switch", "Left Output Mixer" }, 670 671 { "LINEOUT2P Mixer", "Right Output Switch", "Right Output Mixer" }, 672 673 { "LINEOUT2N Driver", NULL, "LINEOUT2N Mixer" }, 674 { "LINEOUT2P Driver", NULL, "LINEOUT2P Mixer" }, 675 }; 676 677 int wm_hubs_add_analogue_controls(struct snd_soc_codec *codec) 678 { 679 /* Latch volume update bits & default ZC on */ 680 snd_soc_update_bits(codec, WM8993_LEFT_LINE_INPUT_1_2_VOLUME, 681 WM8993_IN1_VU, WM8993_IN1_VU); 682 snd_soc_update_bits(codec, WM8993_RIGHT_LINE_INPUT_1_2_VOLUME, 683 WM8993_IN1_VU, WM8993_IN1_VU); 684 snd_soc_update_bits(codec, WM8993_LEFT_LINE_INPUT_3_4_VOLUME, 685 WM8993_IN2_VU, WM8993_IN2_VU); 686 snd_soc_update_bits(codec, WM8993_RIGHT_LINE_INPUT_3_4_VOLUME, 687 WM8993_IN2_VU, WM8993_IN2_VU); 688 689 snd_soc_update_bits(codec, WM8993_SPEAKER_VOLUME_RIGHT, 690 WM8993_SPKOUT_VU, WM8993_SPKOUT_VU); 691 692 snd_soc_update_bits(codec, WM8993_LEFT_OUTPUT_VOLUME, 693 WM8993_HPOUT1L_ZC, WM8993_HPOUT1L_ZC); 694 snd_soc_update_bits(codec, WM8993_RIGHT_OUTPUT_VOLUME, 695 WM8993_HPOUT1_VU | WM8993_HPOUT1R_ZC, 696 WM8993_HPOUT1_VU | WM8993_HPOUT1R_ZC); 697 698 snd_soc_update_bits(codec, WM8993_LEFT_OPGA_VOLUME, 699 WM8993_MIXOUTL_ZC, WM8993_MIXOUTL_ZC); 700 snd_soc_update_bits(codec, WM8993_RIGHT_OPGA_VOLUME, 701 WM8993_MIXOUTR_ZC | WM8993_MIXOUT_VU, 702 WM8993_MIXOUTR_ZC | WM8993_MIXOUT_VU); 703 704 snd_soc_add_controls(codec, analogue_snd_controls, 705 ARRAY_SIZE(analogue_snd_controls)); 706 707 snd_soc_dapm_new_controls(codec, analogue_dapm_widgets, 708 ARRAY_SIZE(analogue_dapm_widgets)); 709 return 0; 710 } 711 EXPORT_SYMBOL_GPL(wm_hubs_add_analogue_controls); 712 713 int wm_hubs_add_analogue_routes(struct snd_soc_codec *codec, 714 int lineout1_diff, int lineout2_diff) 715 { 716 snd_soc_dapm_add_routes(codec, analogue_routes, 717 ARRAY_SIZE(analogue_routes)); 718 719 if (lineout1_diff) 720 snd_soc_dapm_add_routes(codec, 721 lineout1_diff_routes, 722 ARRAY_SIZE(lineout1_diff_routes)); 723 else 724 snd_soc_dapm_add_routes(codec, 725 lineout1_se_routes, 726 ARRAY_SIZE(lineout1_se_routes)); 727 728 if (lineout2_diff) 729 snd_soc_dapm_add_routes(codec, 730 lineout2_diff_routes, 731 ARRAY_SIZE(lineout2_diff_routes)); 732 else 733 snd_soc_dapm_add_routes(codec, 734 lineout2_se_routes, 735 ARRAY_SIZE(lineout2_se_routes)); 736 737 return 0; 738 } 739 EXPORT_SYMBOL_GPL(wm_hubs_add_analogue_routes); 740 741 MODULE_DESCRIPTION("Shared support for Wolfson hubs products"); 742 MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); 743 MODULE_LICENSE("GPL"); 744