| Mark Brown | f1c0a02 | 2008-08-26 13:05:27 +0100 | [diff] [blame] | 1 | /* | 
|  | 2 | * wm8903.c  --  WM8903 ALSA SoC Audio driver | 
|  | 3 | * | 
|  | 4 | * Copyright 2008 Wolfson Microelectronics | 
|  | 5 | * | 
|  | 6 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> | 
|  | 7 | * | 
|  | 8 | * This program is free software; you can redistribute it and/or modify | 
|  | 9 | * it under the terms of the GNU General Public License version 2 as | 
|  | 10 | * published by the Free Software Foundation. | 
|  | 11 | * | 
|  | 12 | * TODO: | 
|  | 13 | *  - TDM mode configuration. | 
|  | 14 | *  - Mic detect. | 
|  | 15 | *  - Digital microphone support. | 
|  | 16 | *  - Interrupt support (mic detect and sequencer). | 
|  | 17 | */ | 
|  | 18 |  | 
|  | 19 | #include <linux/module.h> | 
|  | 20 | #include <linux/moduleparam.h> | 
|  | 21 | #include <linux/init.h> | 
|  | 22 | #include <linux/delay.h> | 
|  | 23 | #include <linux/pm.h> | 
|  | 24 | #include <linux/i2c.h> | 
|  | 25 | #include <linux/platform_device.h> | 
|  | 26 | #include <sound/core.h> | 
|  | 27 | #include <sound/pcm.h> | 
|  | 28 | #include <sound/pcm_params.h> | 
|  | 29 | #include <sound/tlv.h> | 
|  | 30 | #include <sound/soc.h> | 
|  | 31 | #include <sound/soc-dapm.h> | 
|  | 32 | #include <sound/initval.h> | 
|  | 33 |  | 
|  | 34 | #include "wm8903.h" | 
|  | 35 |  | 
|  | 36 | struct wm8903_priv { | 
|  | 37 | int sysclk; | 
|  | 38 |  | 
|  | 39 | /* Reference counts */ | 
|  | 40 | int charge_pump_users; | 
|  | 41 | int class_w_users; | 
|  | 42 | int playback_active; | 
|  | 43 | int capture_active; | 
|  | 44 |  | 
|  | 45 | struct snd_pcm_substream *master_substream; | 
|  | 46 | struct snd_pcm_substream *slave_substream; | 
|  | 47 | }; | 
|  | 48 |  | 
|  | 49 | /* Register defaults at reset */ | 
|  | 50 | static u16 wm8903_reg_defaults[] = { | 
|  | 51 | 0x8903,     /* R0   - SW Reset and ID */ | 
|  | 52 | 0x0000,     /* R1   - Revision Number */ | 
|  | 53 | 0x0000,     /* R2 */ | 
|  | 54 | 0x0000,     /* R3 */ | 
|  | 55 | 0x0018,     /* R4   - Bias Control 0 */ | 
|  | 56 | 0x0000,     /* R5   - VMID Control 0 */ | 
|  | 57 | 0x0000,     /* R6   - Mic Bias Control 0 */ | 
|  | 58 | 0x0000,     /* R7 */ | 
|  | 59 | 0x0001,     /* R8   - Analogue DAC 0 */ | 
|  | 60 | 0x0000,     /* R9 */ | 
|  | 61 | 0x0001,     /* R10  - Analogue ADC 0 */ | 
|  | 62 | 0x0000,     /* R11 */ | 
|  | 63 | 0x0000,     /* R12  - Power Management 0 */ | 
|  | 64 | 0x0000,     /* R13  - Power Management 1 */ | 
|  | 65 | 0x0000,     /* R14  - Power Management 2 */ | 
|  | 66 | 0x0000,     /* R15  - Power Management 3 */ | 
|  | 67 | 0x0000,     /* R16  - Power Management 4 */ | 
|  | 68 | 0x0000,     /* R17  - Power Management 5 */ | 
|  | 69 | 0x0000,     /* R18  - Power Management 6 */ | 
|  | 70 | 0x0000,     /* R19 */ | 
|  | 71 | 0x0400,     /* R20  - Clock Rates 0 */ | 
|  | 72 | 0x0D07,     /* R21  - Clock Rates 1 */ | 
|  | 73 | 0x0000,     /* R22  - Clock Rates 2 */ | 
|  | 74 | 0x0000,     /* R23 */ | 
|  | 75 | 0x0050,     /* R24  - Audio Interface 0 */ | 
|  | 76 | 0x0242,     /* R25  - Audio Interface 1 */ | 
|  | 77 | 0x0008,     /* R26  - Audio Interface 2 */ | 
|  | 78 | 0x0022,     /* R27  - Audio Interface 3 */ | 
|  | 79 | 0x0000,     /* R28 */ | 
|  | 80 | 0x0000,     /* R29 */ | 
|  | 81 | 0x00C0,     /* R30  - DAC Digital Volume Left */ | 
|  | 82 | 0x00C0,     /* R31  - DAC Digital Volume Right */ | 
|  | 83 | 0x0000,     /* R32  - DAC Digital 0 */ | 
|  | 84 | 0x0000,     /* R33  - DAC Digital 1 */ | 
|  | 85 | 0x0000,     /* R34 */ | 
|  | 86 | 0x0000,     /* R35 */ | 
|  | 87 | 0x00C0,     /* R36  - ADC Digital Volume Left */ | 
|  | 88 | 0x00C0,     /* R37  - ADC Digital Volume Right */ | 
|  | 89 | 0x0000,     /* R38  - ADC Digital 0 */ | 
|  | 90 | 0x0073,     /* R39  - Digital Microphone 0 */ | 
|  | 91 | 0x09BF,     /* R40  - DRC 0 */ | 
|  | 92 | 0x3241,     /* R41  - DRC 1 */ | 
|  | 93 | 0x0020,     /* R42  - DRC 2 */ | 
|  | 94 | 0x0000,     /* R43  - DRC 3 */ | 
|  | 95 | 0x0085,     /* R44  - Analogue Left Input 0 */ | 
|  | 96 | 0x0085,     /* R45  - Analogue Right Input 0 */ | 
|  | 97 | 0x0044,     /* R46  - Analogue Left Input 1 */ | 
|  | 98 | 0x0044,     /* R47  - Analogue Right Input 1 */ | 
|  | 99 | 0x0000,     /* R48 */ | 
|  | 100 | 0x0000,     /* R49 */ | 
|  | 101 | 0x0008,     /* R50  - Analogue Left Mix 0 */ | 
|  | 102 | 0x0004,     /* R51  - Analogue Right Mix 0 */ | 
|  | 103 | 0x0000,     /* R52  - Analogue Spk Mix Left 0 */ | 
|  | 104 | 0x0000,     /* R53  - Analogue Spk Mix Left 1 */ | 
|  | 105 | 0x0000,     /* R54  - Analogue Spk Mix Right 0 */ | 
|  | 106 | 0x0000,     /* R55  - Analogue Spk Mix Right 1 */ | 
|  | 107 | 0x0000,     /* R56 */ | 
|  | 108 | 0x002D,     /* R57  - Analogue OUT1 Left */ | 
|  | 109 | 0x002D,     /* R58  - Analogue OUT1 Right */ | 
|  | 110 | 0x0039,     /* R59  - Analogue OUT2 Left */ | 
|  | 111 | 0x0039,     /* R60  - Analogue OUT2 Right */ | 
|  | 112 | 0x0100,     /* R61 */ | 
|  | 113 | 0x0139,     /* R62  - Analogue OUT3 Left */ | 
|  | 114 | 0x0139,     /* R63  - Analogue OUT3 Right */ | 
|  | 115 | 0x0000,     /* R64 */ | 
|  | 116 | 0x0000,     /* R65  - Analogue SPK Output Control 0 */ | 
|  | 117 | 0x0000,     /* R66 */ | 
|  | 118 | 0x0010,     /* R67  - DC Servo 0 */ | 
|  | 119 | 0x0100,     /* R68 */ | 
|  | 120 | 0x00A4,     /* R69  - DC Servo 2 */ | 
|  | 121 | 0x0807,     /* R70 */ | 
|  | 122 | 0x0000,     /* R71 */ | 
|  | 123 | 0x0000,     /* R72 */ | 
|  | 124 | 0x0000,     /* R73 */ | 
|  | 125 | 0x0000,     /* R74 */ | 
|  | 126 | 0x0000,     /* R75 */ | 
|  | 127 | 0x0000,     /* R76 */ | 
|  | 128 | 0x0000,     /* R77 */ | 
|  | 129 | 0x0000,     /* R78 */ | 
|  | 130 | 0x000E,     /* R79 */ | 
|  | 131 | 0x0000,     /* R80 */ | 
|  | 132 | 0x0000,     /* R81 */ | 
|  | 133 | 0x0000,     /* R82 */ | 
|  | 134 | 0x0000,     /* R83 */ | 
|  | 135 | 0x0000,     /* R84 */ | 
|  | 136 | 0x0000,     /* R85 */ | 
|  | 137 | 0x0000,     /* R86 */ | 
|  | 138 | 0x0006,     /* R87 */ | 
|  | 139 | 0x0000,     /* R88 */ | 
|  | 140 | 0x0000,     /* R89 */ | 
|  | 141 | 0x0000,     /* R90  - Analogue HP 0 */ | 
|  | 142 | 0x0060,     /* R91 */ | 
|  | 143 | 0x0000,     /* R92 */ | 
|  | 144 | 0x0000,     /* R93 */ | 
|  | 145 | 0x0000,     /* R94  - Analogue Lineout 0 */ | 
|  | 146 | 0x0060,     /* R95 */ | 
|  | 147 | 0x0000,     /* R96 */ | 
|  | 148 | 0x0000,     /* R97 */ | 
|  | 149 | 0x0000,     /* R98  - Charge Pump 0 */ | 
|  | 150 | 0x1F25,     /* R99 */ | 
|  | 151 | 0x2B19,     /* R100 */ | 
|  | 152 | 0x01C0,     /* R101 */ | 
|  | 153 | 0x01EF,     /* R102 */ | 
|  | 154 | 0x2B00,     /* R103 */ | 
|  | 155 | 0x0000,     /* R104 - Class W 0 */ | 
|  | 156 | 0x01C0,     /* R105 */ | 
|  | 157 | 0x1C10,     /* R106 */ | 
|  | 158 | 0x0000,     /* R107 */ | 
|  | 159 | 0x0000,     /* R108 - Write Sequencer 0 */ | 
|  | 160 | 0x0000,     /* R109 - Write Sequencer 1 */ | 
|  | 161 | 0x0000,     /* R110 - Write Sequencer 2 */ | 
|  | 162 | 0x0000,     /* R111 - Write Sequencer 3 */ | 
|  | 163 | 0x0000,     /* R112 - Write Sequencer 4 */ | 
|  | 164 | 0x0000,     /* R113 */ | 
|  | 165 | 0x0000,     /* R114 - Control Interface */ | 
|  | 166 | 0x0000,     /* R115 */ | 
|  | 167 | 0x00A8,     /* R116 - GPIO Control 1 */ | 
|  | 168 | 0x00A8,     /* R117 - GPIO Control 2 */ | 
|  | 169 | 0x00A8,     /* R118 - GPIO Control 3 */ | 
|  | 170 | 0x0220,     /* R119 - GPIO Control 4 */ | 
|  | 171 | 0x01A0,     /* R120 - GPIO Control 5 */ | 
|  | 172 | 0x0000,     /* R121 - Interrupt Status 1 */ | 
|  | 173 | 0xFFFF,     /* R122 - Interrupt Status 1 Mask */ | 
|  | 174 | 0x0000,     /* R123 - Interrupt Polarity 1 */ | 
|  | 175 | 0x0000,     /* R124 */ | 
|  | 176 | 0x0003,     /* R125 */ | 
|  | 177 | 0x0000,     /* R126 - Interrupt Control */ | 
|  | 178 | 0x0000,     /* R127 */ | 
|  | 179 | 0x0005,     /* R128 */ | 
|  | 180 | 0x0000,     /* R129 - Control Interface Test 1 */ | 
|  | 181 | 0x0000,     /* R130 */ | 
|  | 182 | 0x0000,     /* R131 */ | 
|  | 183 | 0x0000,     /* R132 */ | 
|  | 184 | 0x0000,     /* R133 */ | 
|  | 185 | 0x0000,     /* R134 */ | 
|  | 186 | 0x03FF,     /* R135 */ | 
|  | 187 | 0x0007,     /* R136 */ | 
|  | 188 | 0x0040,     /* R137 */ | 
|  | 189 | 0x0000,     /* R138 */ | 
|  | 190 | 0x0000,     /* R139 */ | 
|  | 191 | 0x0000,     /* R140 */ | 
|  | 192 | 0x0000,     /* R141 */ | 
|  | 193 | 0x0000,     /* R142 */ | 
|  | 194 | 0x0000,     /* R143 */ | 
|  | 195 | 0x0000,     /* R144 */ | 
|  | 196 | 0x0000,     /* R145 */ | 
|  | 197 | 0x0000,     /* R146 */ | 
|  | 198 | 0x0000,     /* R147 */ | 
|  | 199 | 0x4000,     /* R148 */ | 
|  | 200 | 0x6810,     /* R149 - Charge Pump Test 1 */ | 
|  | 201 | 0x0004,     /* R150 */ | 
|  | 202 | 0x0000,     /* R151 */ | 
|  | 203 | 0x0000,     /* R152 */ | 
|  | 204 | 0x0000,     /* R153 */ | 
|  | 205 | 0x0000,     /* R154 */ | 
|  | 206 | 0x0000,     /* R155 */ | 
|  | 207 | 0x0000,     /* R156 */ | 
|  | 208 | 0x0000,     /* R157 */ | 
|  | 209 | 0x0000,     /* R158 */ | 
|  | 210 | 0x0000,     /* R159 */ | 
|  | 211 | 0x0000,     /* R160 */ | 
|  | 212 | 0x0000,     /* R161 */ | 
|  | 213 | 0x0000,     /* R162 */ | 
|  | 214 | 0x0000,     /* R163 */ | 
|  | 215 | 0x0028,     /* R164 - Clock Rate Test 4 */ | 
|  | 216 | 0x0004,     /* R165 */ | 
|  | 217 | 0x0000,     /* R166 */ | 
|  | 218 | 0x0060,     /* R167 */ | 
|  | 219 | 0x0000,     /* R168 */ | 
|  | 220 | 0x0000,     /* R169 */ | 
|  | 221 | 0x0000,     /* R170 */ | 
|  | 222 | 0x0000,     /* R171 */ | 
|  | 223 | 0x0000,     /* R172 - Analogue Output Bias 0 */ | 
|  | 224 | }; | 
|  | 225 |  | 
|  | 226 | static unsigned int wm8903_read_reg_cache(struct snd_soc_codec *codec, | 
|  | 227 | unsigned int reg) | 
|  | 228 | { | 
|  | 229 | u16 *cache = codec->reg_cache; | 
|  | 230 |  | 
|  | 231 | BUG_ON(reg >= ARRAY_SIZE(wm8903_reg_defaults)); | 
|  | 232 |  | 
|  | 233 | return cache[reg]; | 
|  | 234 | } | 
|  | 235 |  | 
|  | 236 | static unsigned int wm8903_hw_read(struct snd_soc_codec *codec, u8 reg) | 
|  | 237 | { | 
|  | 238 | struct i2c_msg xfer[2]; | 
|  | 239 | u16 data; | 
|  | 240 | int ret; | 
|  | 241 | struct i2c_client *client = codec->control_data; | 
|  | 242 |  | 
|  | 243 | /* Write register */ | 
|  | 244 | xfer[0].addr = client->addr; | 
|  | 245 | xfer[0].flags = 0; | 
|  | 246 | xfer[0].len = 1; | 
|  | 247 | xfer[0].buf = ® | 
|  | 248 |  | 
|  | 249 | /* Read data */ | 
|  | 250 | xfer[1].addr = client->addr; | 
|  | 251 | xfer[1].flags = I2C_M_RD; | 
|  | 252 | xfer[1].len = 2; | 
|  | 253 | xfer[1].buf = (u8 *)&data; | 
|  | 254 |  | 
|  | 255 | ret = i2c_transfer(client->adapter, xfer, 2); | 
|  | 256 | if (ret != 2) { | 
|  | 257 | pr_err("i2c_transfer returned %d\n", ret); | 
|  | 258 | return 0; | 
|  | 259 | } | 
|  | 260 |  | 
|  | 261 | return (data >> 8) | ((data & 0xff) << 8); | 
|  | 262 | } | 
|  | 263 |  | 
|  | 264 | static unsigned int wm8903_read(struct snd_soc_codec *codec, | 
|  | 265 | unsigned int reg) | 
|  | 266 | { | 
|  | 267 | switch (reg) { | 
|  | 268 | case WM8903_SW_RESET_AND_ID: | 
|  | 269 | case WM8903_REVISION_NUMBER: | 
|  | 270 | case WM8903_INTERRUPT_STATUS_1: | 
|  | 271 | case WM8903_WRITE_SEQUENCER_4: | 
|  | 272 | return wm8903_hw_read(codec, reg); | 
|  | 273 |  | 
|  | 274 | default: | 
|  | 275 | return wm8903_read_reg_cache(codec, reg); | 
|  | 276 | } | 
|  | 277 | } | 
|  | 278 |  | 
|  | 279 | static void wm8903_write_reg_cache(struct snd_soc_codec *codec, | 
|  | 280 | u16 reg, unsigned int value) | 
|  | 281 | { | 
|  | 282 | u16 *cache = codec->reg_cache; | 
|  | 283 |  | 
|  | 284 | BUG_ON(reg >= ARRAY_SIZE(wm8903_reg_defaults)); | 
|  | 285 |  | 
|  | 286 | switch (reg) { | 
|  | 287 | case WM8903_SW_RESET_AND_ID: | 
|  | 288 | case WM8903_REVISION_NUMBER: | 
|  | 289 | break; | 
|  | 290 |  | 
|  | 291 | default: | 
|  | 292 | cache[reg] = value; | 
|  | 293 | break; | 
|  | 294 | } | 
|  | 295 | } | 
|  | 296 |  | 
|  | 297 | static int wm8903_write(struct snd_soc_codec *codec, unsigned int reg, | 
|  | 298 | unsigned int value) | 
|  | 299 | { | 
|  | 300 | u8 data[3]; | 
|  | 301 |  | 
|  | 302 | wm8903_write_reg_cache(codec, reg, value); | 
|  | 303 |  | 
|  | 304 | /* Data format is 1 byte of address followed by 2 bytes of data */ | 
|  | 305 | data[0] = reg; | 
|  | 306 | data[1] = (value >> 8) & 0xff; | 
|  | 307 | data[2] = value & 0xff; | 
|  | 308 |  | 
|  | 309 | if (codec->hw_write(codec->control_data, data, 3) == 2) | 
|  | 310 | return 0; | 
|  | 311 | else | 
|  | 312 | return -EIO; | 
|  | 313 | } | 
|  | 314 |  | 
|  | 315 | static int wm8903_run_sequence(struct snd_soc_codec *codec, unsigned int start) | 
|  | 316 | { | 
|  | 317 | u16 reg[5]; | 
|  | 318 | struct i2c_client *i2c = codec->control_data; | 
|  | 319 |  | 
|  | 320 | BUG_ON(start > 48); | 
|  | 321 |  | 
|  | 322 | /* Enable the sequencer */ | 
|  | 323 | reg[0] = wm8903_read(codec, WM8903_WRITE_SEQUENCER_0); | 
|  | 324 | reg[0] |= WM8903_WSEQ_ENA; | 
|  | 325 | wm8903_write(codec, WM8903_WRITE_SEQUENCER_0, reg[0]); | 
|  | 326 |  | 
|  | 327 | dev_dbg(&i2c->dev, "Starting sequence at %d\n", start); | 
|  | 328 |  | 
|  | 329 | wm8903_write(codec, WM8903_WRITE_SEQUENCER_3, | 
|  | 330 | start | WM8903_WSEQ_START); | 
|  | 331 |  | 
|  | 332 | /* Wait for it to complete.  If we have the interrupt wired up then | 
|  | 333 | * we could block waiting for an interrupt, though polling may still | 
|  | 334 | * be desirable for diagnostic purposes. | 
|  | 335 | */ | 
|  | 336 | do { | 
|  | 337 | msleep(10); | 
|  | 338 |  | 
|  | 339 | reg[4] = wm8903_read(codec, WM8903_WRITE_SEQUENCER_4); | 
|  | 340 | } while (reg[4] & WM8903_WSEQ_BUSY); | 
|  | 341 |  | 
|  | 342 | dev_dbg(&i2c->dev, "Sequence complete\n"); | 
|  | 343 |  | 
|  | 344 | /* Disable the sequencer again */ | 
|  | 345 | wm8903_write(codec, WM8903_WRITE_SEQUENCER_0, | 
|  | 346 | reg[0] & ~WM8903_WSEQ_ENA); | 
|  | 347 |  | 
|  | 348 | return 0; | 
|  | 349 | } | 
|  | 350 |  | 
|  | 351 | static void wm8903_sync_reg_cache(struct snd_soc_codec *codec, u16 *cache) | 
|  | 352 | { | 
|  | 353 | int i; | 
|  | 354 |  | 
|  | 355 | /* There really ought to be something better we can do here :/ */ | 
|  | 356 | for (i = 0; i < ARRAY_SIZE(wm8903_reg_defaults); i++) | 
|  | 357 | cache[i] = wm8903_hw_read(codec, i); | 
|  | 358 | } | 
|  | 359 |  | 
|  | 360 | static void wm8903_reset(struct snd_soc_codec *codec) | 
|  | 361 | { | 
|  | 362 | wm8903_write(codec, WM8903_SW_RESET_AND_ID, 0); | 
|  | 363 | } | 
|  | 364 |  | 
|  | 365 | #define WM8903_OUTPUT_SHORT 0x8 | 
|  | 366 | #define WM8903_OUTPUT_OUT   0x4 | 
|  | 367 | #define WM8903_OUTPUT_INT   0x2 | 
|  | 368 | #define WM8903_OUTPUT_IN    0x1 | 
|  | 369 |  | 
|  | 370 | /* | 
|  | 371 | * Event for headphone and line out amplifier power changes.  Special | 
|  | 372 | * power up/down sequences are required in order to maximise pop/click | 
|  | 373 | * performance. | 
|  | 374 | */ | 
|  | 375 | static int wm8903_output_event(struct snd_soc_dapm_widget *w, | 
|  | 376 | struct snd_kcontrol *kcontrol, int event) | 
|  | 377 | { | 
|  | 378 | struct snd_soc_codec *codec = w->codec; | 
|  | 379 | struct wm8903_priv *wm8903 = codec->private_data; | 
|  | 380 | struct i2c_client *i2c = codec->control_data; | 
|  | 381 | u16 val; | 
|  | 382 | u16 reg; | 
|  | 383 | int shift; | 
|  | 384 | u16 cp_reg = wm8903_read(codec, WM8903_CHARGE_PUMP_0); | 
|  | 385 |  | 
|  | 386 | switch (w->reg) { | 
|  | 387 | case WM8903_POWER_MANAGEMENT_2: | 
|  | 388 | reg = WM8903_ANALOGUE_HP_0; | 
|  | 389 | break; | 
|  | 390 | case WM8903_POWER_MANAGEMENT_3: | 
|  | 391 | reg = WM8903_ANALOGUE_LINEOUT_0; | 
|  | 392 | break; | 
|  | 393 | default: | 
|  | 394 | BUG(); | 
|  | 395 | } | 
|  | 396 |  | 
|  | 397 | switch (w->shift) { | 
|  | 398 | case 0: | 
|  | 399 | shift = 0; | 
|  | 400 | break; | 
|  | 401 | case 1: | 
|  | 402 | shift = 4; | 
|  | 403 | break; | 
|  | 404 | default: | 
|  | 405 | BUG(); | 
|  | 406 | } | 
|  | 407 |  | 
|  | 408 | if (event & SND_SOC_DAPM_PRE_PMU) { | 
|  | 409 | val = wm8903_read(codec, reg); | 
|  | 410 |  | 
|  | 411 | /* Short the output */ | 
|  | 412 | val &= ~(WM8903_OUTPUT_SHORT << shift); | 
|  | 413 | wm8903_write(codec, reg, val); | 
|  | 414 |  | 
|  | 415 | wm8903->charge_pump_users++; | 
|  | 416 |  | 
|  | 417 | dev_dbg(&i2c->dev, "Charge pump use count now %d\n", | 
|  | 418 | wm8903->charge_pump_users); | 
|  | 419 |  | 
|  | 420 | if (wm8903->charge_pump_users == 1) { | 
|  | 421 | dev_dbg(&i2c->dev, "Enabling charge pump\n"); | 
|  | 422 | wm8903_write(codec, WM8903_CHARGE_PUMP_0, | 
|  | 423 | cp_reg | WM8903_CP_ENA); | 
|  | 424 | mdelay(4); | 
|  | 425 | } | 
|  | 426 | } | 
|  | 427 |  | 
|  | 428 | if (event & SND_SOC_DAPM_POST_PMU) { | 
|  | 429 | val = wm8903_read(codec, reg); | 
|  | 430 |  | 
|  | 431 | val |= (WM8903_OUTPUT_IN << shift); | 
|  | 432 | wm8903_write(codec, reg, val); | 
|  | 433 |  | 
|  | 434 | val |= (WM8903_OUTPUT_INT << shift); | 
|  | 435 | wm8903_write(codec, reg, val); | 
|  | 436 |  | 
|  | 437 | /* Turn on the output ENA_OUTP */ | 
|  | 438 | val |= (WM8903_OUTPUT_OUT << shift); | 
|  | 439 | wm8903_write(codec, reg, val); | 
|  | 440 |  | 
|  | 441 | /* Remove the short */ | 
|  | 442 | val |= (WM8903_OUTPUT_SHORT << shift); | 
|  | 443 | wm8903_write(codec, reg, val); | 
|  | 444 | } | 
|  | 445 |  | 
|  | 446 | if (event & SND_SOC_DAPM_PRE_PMD) { | 
|  | 447 | val = wm8903_read(codec, reg); | 
|  | 448 |  | 
|  | 449 | /* Short the output */ | 
|  | 450 | val &= ~(WM8903_OUTPUT_SHORT << shift); | 
|  | 451 | wm8903_write(codec, reg, val); | 
|  | 452 |  | 
|  | 453 | /* Then disable the intermediate and output stages */ | 
|  | 454 | val &= ~((WM8903_OUTPUT_OUT | WM8903_OUTPUT_INT | | 
|  | 455 | WM8903_OUTPUT_IN) << shift); | 
|  | 456 | wm8903_write(codec, reg, val); | 
|  | 457 | } | 
|  | 458 |  | 
|  | 459 | if (event & SND_SOC_DAPM_POST_PMD) { | 
|  | 460 | wm8903->charge_pump_users--; | 
|  | 461 |  | 
|  | 462 | dev_dbg(&i2c->dev, "Charge pump use count now %d\n", | 
|  | 463 | wm8903->charge_pump_users); | 
|  | 464 |  | 
|  | 465 | if (wm8903->charge_pump_users == 0) { | 
|  | 466 | dev_dbg(&i2c->dev, "Disabling charge pump\n"); | 
|  | 467 | wm8903_write(codec, WM8903_CHARGE_PUMP_0, | 
|  | 468 | cp_reg & ~WM8903_CP_ENA); | 
|  | 469 | } | 
|  | 470 | } | 
|  | 471 |  | 
|  | 472 | return 0; | 
|  | 473 | } | 
|  | 474 |  | 
|  | 475 | /* | 
|  | 476 | * When used with DAC outputs only the WM8903 charge pump supports | 
|  | 477 | * operation in class W mode, providing very low power consumption | 
|  | 478 | * when used with digital sources.  Enable and disable this mode | 
|  | 479 | * automatically depending on the mixer configuration. | 
|  | 480 | * | 
|  | 481 | * All the relevant controls are simple switches. | 
|  | 482 | */ | 
|  | 483 | static int wm8903_class_w_put(struct snd_kcontrol *kcontrol, | 
|  | 484 | struct snd_ctl_elem_value *ucontrol) | 
|  | 485 | { | 
|  | 486 | struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol); | 
|  | 487 | struct snd_soc_codec *codec = widget->codec; | 
|  | 488 | struct wm8903_priv *wm8903 = codec->private_data; | 
|  | 489 | struct i2c_client *i2c = codec->control_data; | 
|  | 490 | u16 reg; | 
|  | 491 | int ret; | 
|  | 492 |  | 
|  | 493 | reg = wm8903_read(codec, WM8903_CLASS_W_0); | 
|  | 494 |  | 
|  | 495 | /* Turn it off if we're about to enable bypass */ | 
|  | 496 | if (ucontrol->value.integer.value[0]) { | 
|  | 497 | if (wm8903->class_w_users == 0) { | 
|  | 498 | dev_dbg(&i2c->dev, "Disabling Class W\n"); | 
|  | 499 | wm8903_write(codec, WM8903_CLASS_W_0, reg & | 
|  | 500 | ~(WM8903_CP_DYN_FREQ | WM8903_CP_DYN_V)); | 
|  | 501 | } | 
|  | 502 | wm8903->class_w_users++; | 
|  | 503 | } | 
|  | 504 |  | 
|  | 505 | /* Implement the change */ | 
|  | 506 | ret = snd_soc_dapm_put_volsw(kcontrol, ucontrol); | 
|  | 507 |  | 
|  | 508 | /* If we've just disabled the last bypass path turn Class W on */ | 
|  | 509 | if (!ucontrol->value.integer.value[0]) { | 
|  | 510 | if (wm8903->class_w_users == 1) { | 
|  | 511 | dev_dbg(&i2c->dev, "Enabling Class W\n"); | 
|  | 512 | wm8903_write(codec, WM8903_CLASS_W_0, reg | | 
|  | 513 | WM8903_CP_DYN_FREQ | WM8903_CP_DYN_V); | 
|  | 514 | } | 
|  | 515 | wm8903->class_w_users--; | 
|  | 516 | } | 
|  | 517 |  | 
|  | 518 | dev_dbg(&i2c->dev, "Bypass use count now %d\n", | 
|  | 519 | wm8903->class_w_users); | 
|  | 520 |  | 
|  | 521 | return ret; | 
|  | 522 | } | 
|  | 523 |  | 
|  | 524 | #define SOC_DAPM_SINGLE_W(xname, reg, shift, max, invert) \ | 
|  | 525 | {	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ | 
|  | 526 | .info = snd_soc_info_volsw, \ | 
|  | 527 | .get = snd_soc_dapm_get_volsw, .put = wm8903_class_w_put, \ | 
|  | 528 | .private_value =  SOC_SINGLE_VALUE(reg, shift, max, invert) } | 
|  | 529 |  | 
|  | 530 |  | 
|  | 531 | /* ALSA can only do steps of .01dB */ | 
|  | 532 | static const DECLARE_TLV_DB_SCALE(digital_tlv, -7200, 75, 1); | 
|  | 533 |  | 
|  | 534 | static const DECLARE_TLV_DB_SCALE(out_tlv, -5700, 100, 0); | 
|  | 535 |  | 
|  | 536 | static const DECLARE_TLV_DB_SCALE(drc_tlv_thresh, 0, 75, 0); | 
|  | 537 | static const DECLARE_TLV_DB_SCALE(drc_tlv_amp, -2250, 75, 0); | 
|  | 538 | static const DECLARE_TLV_DB_SCALE(drc_tlv_min, 0, 600, 0); | 
|  | 539 | static const DECLARE_TLV_DB_SCALE(drc_tlv_max, 1200, 600, 0); | 
|  | 540 | static const DECLARE_TLV_DB_SCALE(drc_tlv_startup, -300, 50, 0); | 
|  | 541 |  | 
|  | 542 | static const char *drc_slope_text[] = { | 
|  | 543 | "1", "1/2", "1/4", "1/8", "1/16", "0" | 
|  | 544 | }; | 
|  | 545 |  | 
|  | 546 | static const struct soc_enum drc_slope_r0 = | 
|  | 547 | SOC_ENUM_SINGLE(WM8903_DRC_2, 3, 6, drc_slope_text); | 
|  | 548 |  | 
|  | 549 | static const struct soc_enum drc_slope_r1 = | 
|  | 550 | SOC_ENUM_SINGLE(WM8903_DRC_2, 0, 6, drc_slope_text); | 
|  | 551 |  | 
|  | 552 | static const char *drc_attack_text[] = { | 
|  | 553 | "instantaneous", | 
|  | 554 | "363us", "762us", "1.45ms", "2.9ms", "5.8ms", "11.6ms", "23.2ms", | 
|  | 555 | "46.4ms", "92.8ms", "185.6ms" | 
|  | 556 | }; | 
|  | 557 |  | 
|  | 558 | static const struct soc_enum drc_attack = | 
|  | 559 | SOC_ENUM_SINGLE(WM8903_DRC_1, 12, 11, drc_attack_text); | 
|  | 560 |  | 
|  | 561 | static const char *drc_decay_text[] = { | 
|  | 562 | "186ms", "372ms", "743ms", "1.49s", "2.97s", "5.94s", "11.89s", | 
|  | 563 | "23.87s", "47.56s" | 
|  | 564 | }; | 
|  | 565 |  | 
|  | 566 | static const struct soc_enum drc_decay = | 
|  | 567 | SOC_ENUM_SINGLE(WM8903_DRC_1, 8, 9, drc_decay_text); | 
|  | 568 |  | 
|  | 569 | static const char *drc_ff_delay_text[] = { | 
|  | 570 | "5 samples", "9 samples" | 
|  | 571 | }; | 
|  | 572 |  | 
|  | 573 | static const struct soc_enum drc_ff_delay = | 
|  | 574 | SOC_ENUM_SINGLE(WM8903_DRC_0, 5, 2, drc_ff_delay_text); | 
|  | 575 |  | 
|  | 576 | static const char *drc_qr_decay_text[] = { | 
|  | 577 | "0.725ms", "1.45ms", "5.8ms" | 
|  | 578 | }; | 
|  | 579 |  | 
|  | 580 | static const struct soc_enum drc_qr_decay = | 
|  | 581 | SOC_ENUM_SINGLE(WM8903_DRC_1, 4, 3, drc_qr_decay_text); | 
|  | 582 |  | 
|  | 583 | static const char *drc_smoothing_text[] = { | 
|  | 584 | "Low", "Medium", "High" | 
|  | 585 | }; | 
|  | 586 |  | 
|  | 587 | static const struct soc_enum drc_smoothing = | 
|  | 588 | SOC_ENUM_SINGLE(WM8903_DRC_0, 11, 3, drc_smoothing_text); | 
|  | 589 |  | 
|  | 590 | static const char *soft_mute_text[] = { | 
|  | 591 | "Fast (fs/2)", "Slow (fs/32)" | 
|  | 592 | }; | 
|  | 593 |  | 
|  | 594 | static const struct soc_enum soft_mute = | 
|  | 595 | SOC_ENUM_SINGLE(WM8903_DAC_DIGITAL_1, 10, 2, soft_mute_text); | 
|  | 596 |  | 
|  | 597 | static const char *mute_mode_text[] = { | 
|  | 598 | "Hard", "Soft" | 
|  | 599 | }; | 
|  | 600 |  | 
|  | 601 | static const struct soc_enum mute_mode = | 
|  | 602 | SOC_ENUM_SINGLE(WM8903_DAC_DIGITAL_1, 9, 2, mute_mode_text); | 
|  | 603 |  | 
|  | 604 | static const char *dac_deemphasis_text[] = { | 
|  | 605 | "Disabled", "32kHz", "44.1kHz", "48kHz" | 
|  | 606 | }; | 
|  | 607 |  | 
|  | 608 | static const struct soc_enum dac_deemphasis = | 
|  | 609 | SOC_ENUM_SINGLE(WM8903_DAC_DIGITAL_1, 1, 4, dac_deemphasis_text); | 
|  | 610 |  | 
|  | 611 | static const char *companding_text[] = { | 
|  | 612 | "ulaw", "alaw" | 
|  | 613 | }; | 
|  | 614 |  | 
|  | 615 | static const struct soc_enum dac_companding = | 
|  | 616 | SOC_ENUM_SINGLE(WM8903_AUDIO_INTERFACE_0, 0, 2, companding_text); | 
|  | 617 |  | 
|  | 618 | static const struct soc_enum adc_companding = | 
|  | 619 | SOC_ENUM_SINGLE(WM8903_AUDIO_INTERFACE_0, 2, 2, companding_text); | 
|  | 620 |  | 
|  | 621 | static const char *input_mode_text[] = { | 
|  | 622 | "Single-Ended", "Differential Line", "Differential Mic" | 
|  | 623 | }; | 
|  | 624 |  | 
|  | 625 | static const struct soc_enum linput_mode_enum = | 
|  | 626 | SOC_ENUM_SINGLE(WM8903_ANALOGUE_LEFT_INPUT_1, 0, 3, input_mode_text); | 
|  | 627 |  | 
|  | 628 | static const struct soc_enum rinput_mode_enum = | 
|  | 629 | SOC_ENUM_SINGLE(WM8903_ANALOGUE_RIGHT_INPUT_1, 0, 3, input_mode_text); | 
|  | 630 |  | 
|  | 631 | static const char *linput_mux_text[] = { | 
|  | 632 | "IN1L", "IN2L", "IN3L" | 
|  | 633 | }; | 
|  | 634 |  | 
|  | 635 | static const struct soc_enum linput_enum = | 
|  | 636 | SOC_ENUM_SINGLE(WM8903_ANALOGUE_LEFT_INPUT_1, 2, 3, linput_mux_text); | 
|  | 637 |  | 
|  | 638 | static const struct soc_enum linput_inv_enum = | 
|  | 639 | SOC_ENUM_SINGLE(WM8903_ANALOGUE_LEFT_INPUT_1, 4, 3, linput_mux_text); | 
|  | 640 |  | 
|  | 641 | static const char *rinput_mux_text[] = { | 
|  | 642 | "IN1R", "IN2R", "IN3R" | 
|  | 643 | }; | 
|  | 644 |  | 
|  | 645 | static const struct soc_enum rinput_enum = | 
|  | 646 | SOC_ENUM_SINGLE(WM8903_ANALOGUE_RIGHT_INPUT_1, 2, 3, rinput_mux_text); | 
|  | 647 |  | 
|  | 648 | static const struct soc_enum rinput_inv_enum = | 
|  | 649 | SOC_ENUM_SINGLE(WM8903_ANALOGUE_RIGHT_INPUT_1, 4, 3, rinput_mux_text); | 
|  | 650 |  | 
|  | 651 |  | 
|  | 652 | static const struct snd_kcontrol_new wm8903_snd_controls[] = { | 
|  | 653 |  | 
|  | 654 | /* Input PGAs - No TLV since the scale depends on PGA mode */ | 
|  | 655 | SOC_SINGLE("Left Input PGA Switch", WM8903_ANALOGUE_LEFT_INPUT_0, | 
| Mark Brown | 5715952 | 2008-09-24 10:47:02 +0100 | [diff] [blame] | 656 | 7, 1, 1), | 
| Mark Brown | f1c0a02 | 2008-08-26 13:05:27 +0100 | [diff] [blame] | 657 | SOC_SINGLE("Left Input PGA Volume", WM8903_ANALOGUE_LEFT_INPUT_0, | 
|  | 658 | 0, 31, 0), | 
|  | 659 | SOC_SINGLE("Left Input PGA Common Mode Switch", WM8903_ANALOGUE_LEFT_INPUT_1, | 
|  | 660 | 6, 1, 0), | 
|  | 661 |  | 
|  | 662 | SOC_SINGLE("Right Input PGA Switch", WM8903_ANALOGUE_RIGHT_INPUT_0, | 
| Mark Brown | 5715952 | 2008-09-24 10:47:02 +0100 | [diff] [blame] | 663 | 7, 1, 1), | 
| Mark Brown | f1c0a02 | 2008-08-26 13:05:27 +0100 | [diff] [blame] | 664 | SOC_SINGLE("Right Input PGA Volume", WM8903_ANALOGUE_RIGHT_INPUT_0, | 
|  | 665 | 0, 31, 0), | 
|  | 666 | SOC_SINGLE("Right Input PGA Common Mode Switch", WM8903_ANALOGUE_RIGHT_INPUT_1, | 
|  | 667 | 6, 1, 0), | 
|  | 668 |  | 
|  | 669 | /* ADCs */ | 
|  | 670 | SOC_SINGLE("DRC Switch", WM8903_DRC_0, 15, 1, 0), | 
|  | 671 | SOC_ENUM("DRC Compressor Slope R0", drc_slope_r0), | 
|  | 672 | SOC_ENUM("DRC Compressor Slope R1", drc_slope_r1), | 
|  | 673 | SOC_SINGLE_TLV("DRC Compressor Threashold Volume", WM8903_DRC_3, 5, 124, 1, | 
|  | 674 | drc_tlv_thresh), | 
|  | 675 | SOC_SINGLE_TLV("DRC Volume", WM8903_DRC_3, 0, 30, 1, drc_tlv_amp), | 
|  | 676 | SOC_SINGLE_TLV("DRC Minimum Gain Volume", WM8903_DRC_1, 2, 3, 1, drc_tlv_min), | 
|  | 677 | SOC_SINGLE_TLV("DRC Maximum Gain Volume", WM8903_DRC_1, 0, 3, 0, drc_tlv_max), | 
|  | 678 | SOC_ENUM("DRC Attack Rate", drc_attack), | 
|  | 679 | SOC_ENUM("DRC Decay Rate", drc_decay), | 
|  | 680 | SOC_ENUM("DRC FF Delay", drc_ff_delay), | 
|  | 681 | SOC_SINGLE("DRC Anticlip Switch", WM8903_DRC_0, 1, 1, 0), | 
|  | 682 | SOC_SINGLE("DRC QR Switch", WM8903_DRC_0, 2, 1, 0), | 
|  | 683 | SOC_SINGLE_TLV("DRC QR Threashold Volume", WM8903_DRC_0, 6, 3, 0, drc_tlv_max), | 
|  | 684 | SOC_ENUM("DRC QR Decay Rate", drc_qr_decay), | 
|  | 685 | SOC_SINGLE("DRC Smoothing Switch", WM8903_DRC_0, 3, 1, 0), | 
|  | 686 | SOC_SINGLE("DRC Smoothing Hysteresis Switch", WM8903_DRC_0, 0, 1, 0), | 
|  | 687 | SOC_ENUM("DRC Smoothing Threashold", drc_smoothing), | 
|  | 688 | SOC_SINGLE_TLV("DRC Startup Volume", WM8903_DRC_0, 6, 18, 0, drc_tlv_startup), | 
|  | 689 |  | 
|  | 690 | SOC_DOUBLE_R_TLV("Digital Capture Volume", WM8903_ADC_DIGITAL_VOLUME_LEFT, | 
|  | 691 | WM8903_ADC_DIGITAL_VOLUME_RIGHT, 1, 96, 0, digital_tlv), | 
|  | 692 | SOC_ENUM("ADC Companding Mode", adc_companding), | 
|  | 693 | SOC_SINGLE("ADC Companding Switch", WM8903_AUDIO_INTERFACE_0, 3, 1, 0), | 
|  | 694 |  | 
|  | 695 | /* DAC */ | 
|  | 696 | SOC_DOUBLE_R_TLV("Digital Playback Volume", WM8903_DAC_DIGITAL_VOLUME_LEFT, | 
|  | 697 | WM8903_DAC_DIGITAL_VOLUME_RIGHT, 1, 120, 0, digital_tlv), | 
|  | 698 | SOC_ENUM("DAC Soft Mute Rate", soft_mute), | 
|  | 699 | SOC_ENUM("DAC Mute Mode", mute_mode), | 
|  | 700 | SOC_SINGLE("DAC Mono Switch", WM8903_DAC_DIGITAL_1, 12, 1, 0), | 
|  | 701 | SOC_ENUM("DAC De-emphasis", dac_deemphasis), | 
|  | 702 | SOC_SINGLE("DAC Sloping Stopband Filter Switch", | 
|  | 703 | WM8903_DAC_DIGITAL_1, 11, 1, 0), | 
|  | 704 | SOC_ENUM("DAC Companding Mode", dac_companding), | 
|  | 705 | SOC_SINGLE("DAC Companding Switch", WM8903_AUDIO_INTERFACE_0, 1, 1, 0), | 
|  | 706 |  | 
|  | 707 | /* Headphones */ | 
|  | 708 | SOC_DOUBLE_R("Headphone Switch", | 
|  | 709 | WM8903_ANALOGUE_OUT1_LEFT, WM8903_ANALOGUE_OUT1_RIGHT, | 
|  | 710 | 8, 1, 1), | 
|  | 711 | SOC_DOUBLE_R("Headphone ZC Switch", | 
|  | 712 | WM8903_ANALOGUE_OUT1_LEFT, WM8903_ANALOGUE_OUT1_RIGHT, | 
|  | 713 | 6, 1, 0), | 
|  | 714 | SOC_DOUBLE_R_TLV("Headphone Volume", | 
|  | 715 | WM8903_ANALOGUE_OUT1_LEFT, WM8903_ANALOGUE_OUT1_RIGHT, | 
|  | 716 | 0, 63, 0, out_tlv), | 
|  | 717 |  | 
|  | 718 | /* Line out */ | 
|  | 719 | SOC_DOUBLE_R("Line Out Switch", | 
|  | 720 | WM8903_ANALOGUE_OUT2_LEFT, WM8903_ANALOGUE_OUT2_RIGHT, | 
|  | 721 | 8, 1, 1), | 
|  | 722 | SOC_DOUBLE_R("Line Out ZC Switch", | 
|  | 723 | WM8903_ANALOGUE_OUT2_LEFT, WM8903_ANALOGUE_OUT2_RIGHT, | 
|  | 724 | 6, 1, 0), | 
|  | 725 | SOC_DOUBLE_R_TLV("Line Out Volume", | 
|  | 726 | WM8903_ANALOGUE_OUT2_LEFT, WM8903_ANALOGUE_OUT2_RIGHT, | 
|  | 727 | 0, 63, 0, out_tlv), | 
|  | 728 |  | 
|  | 729 | /* Speaker */ | 
|  | 730 | SOC_DOUBLE_R("Speaker Switch", | 
|  | 731 | WM8903_ANALOGUE_OUT3_LEFT, WM8903_ANALOGUE_OUT3_RIGHT, 8, 1, 1), | 
|  | 732 | SOC_DOUBLE_R("Speaker ZC Switch", | 
|  | 733 | WM8903_ANALOGUE_OUT3_LEFT, WM8903_ANALOGUE_OUT3_RIGHT, 6, 1, 0), | 
|  | 734 | SOC_DOUBLE_R_TLV("Speaker Volume", | 
|  | 735 | WM8903_ANALOGUE_OUT3_LEFT, WM8903_ANALOGUE_OUT3_RIGHT, | 
|  | 736 | 0, 63, 0, out_tlv), | 
|  | 737 | }; | 
|  | 738 |  | 
|  | 739 | static int wm8903_add_controls(struct snd_soc_codec *codec) | 
|  | 740 | { | 
|  | 741 | int err, i; | 
|  | 742 |  | 
|  | 743 | for (i = 0; i < ARRAY_SIZE(wm8903_snd_controls); i++) { | 
|  | 744 | err = snd_ctl_add(codec->card, | 
|  | 745 | snd_soc_cnew(&wm8903_snd_controls[i], | 
|  | 746 | codec, NULL)); | 
|  | 747 | if (err < 0) | 
|  | 748 | return err; | 
|  | 749 | } | 
|  | 750 |  | 
|  | 751 | return 0; | 
|  | 752 | } | 
|  | 753 |  | 
|  | 754 | static const struct snd_kcontrol_new linput_mode_mux = | 
|  | 755 | SOC_DAPM_ENUM("Left Input Mode Mux", linput_mode_enum); | 
|  | 756 |  | 
|  | 757 | static const struct snd_kcontrol_new rinput_mode_mux = | 
|  | 758 | SOC_DAPM_ENUM("Right Input Mode Mux", rinput_mode_enum); | 
|  | 759 |  | 
|  | 760 | static const struct snd_kcontrol_new linput_mux = | 
|  | 761 | SOC_DAPM_ENUM("Left Input Mux", linput_enum); | 
|  | 762 |  | 
|  | 763 | static const struct snd_kcontrol_new linput_inv_mux = | 
|  | 764 | SOC_DAPM_ENUM("Left Inverting Input Mux", linput_inv_enum); | 
|  | 765 |  | 
|  | 766 | static const struct snd_kcontrol_new rinput_mux = | 
|  | 767 | SOC_DAPM_ENUM("Right Input Mux", rinput_enum); | 
|  | 768 |  | 
|  | 769 | static const struct snd_kcontrol_new rinput_inv_mux = | 
|  | 770 | SOC_DAPM_ENUM("Right Inverting Input Mux", rinput_inv_enum); | 
|  | 771 |  | 
|  | 772 | static const struct snd_kcontrol_new left_output_mixer[] = { | 
|  | 773 | SOC_DAPM_SINGLE("DACL Switch", WM8903_ANALOGUE_LEFT_MIX_0, 3, 1, 0), | 
|  | 774 | SOC_DAPM_SINGLE("DACR Switch", WM8903_ANALOGUE_LEFT_MIX_0, 2, 1, 0), | 
|  | 775 | SOC_DAPM_SINGLE_W("Left Bypass Switch", WM8903_ANALOGUE_LEFT_MIX_0, 1, 1, 0), | 
|  | 776 | SOC_DAPM_SINGLE_W("Right Bypass Switch", WM8903_ANALOGUE_LEFT_MIX_0, 1, 1, 0), | 
|  | 777 | }; | 
|  | 778 |  | 
|  | 779 | static const struct snd_kcontrol_new right_output_mixer[] = { | 
|  | 780 | SOC_DAPM_SINGLE("DACL Switch", WM8903_ANALOGUE_RIGHT_MIX_0, 3, 1, 0), | 
|  | 781 | SOC_DAPM_SINGLE("DACR Switch", WM8903_ANALOGUE_RIGHT_MIX_0, 2, 1, 0), | 
|  | 782 | SOC_DAPM_SINGLE_W("Left Bypass Switch", WM8903_ANALOGUE_RIGHT_MIX_0, 1, 1, 0), | 
|  | 783 | SOC_DAPM_SINGLE_W("Right Bypass Switch", WM8903_ANALOGUE_RIGHT_MIX_0, 1, 1, 0), | 
|  | 784 | }; | 
|  | 785 |  | 
|  | 786 | static const struct snd_kcontrol_new left_speaker_mixer[] = { | 
|  | 787 | SOC_DAPM_SINGLE("DACL Switch", WM8903_ANALOGUE_SPK_MIX_LEFT_0, 3, 1, 0), | 
|  | 788 | SOC_DAPM_SINGLE("DACR Switch", WM8903_ANALOGUE_SPK_MIX_LEFT_0, 2, 1, 0), | 
|  | 789 | SOC_DAPM_SINGLE("Left Bypass Switch", WM8903_ANALOGUE_SPK_MIX_LEFT_0, 1, 1, 0), | 
|  | 790 | SOC_DAPM_SINGLE("Right Bypass Switch", WM8903_ANALOGUE_SPK_MIX_LEFT_0, | 
|  | 791 | 1, 1, 0), | 
|  | 792 | }; | 
|  | 793 |  | 
|  | 794 | static const struct snd_kcontrol_new right_speaker_mixer[] = { | 
|  | 795 | SOC_DAPM_SINGLE("DACL Switch", WM8903_ANALOGUE_SPK_MIX_RIGHT_0, 3, 1, 0), | 
|  | 796 | SOC_DAPM_SINGLE("DACR Switch", WM8903_ANALOGUE_SPK_MIX_RIGHT_0, 2, 1, 0), | 
|  | 797 | SOC_DAPM_SINGLE("Left Bypass Switch", WM8903_ANALOGUE_SPK_MIX_RIGHT_0, | 
|  | 798 | 1, 1, 0), | 
|  | 799 | SOC_DAPM_SINGLE("Right Bypass Switch", WM8903_ANALOGUE_SPK_MIX_RIGHT_0, | 
|  | 800 | 1, 1, 0), | 
|  | 801 | }; | 
|  | 802 |  | 
|  | 803 | static const struct snd_soc_dapm_widget wm8903_dapm_widgets[] = { | 
|  | 804 | SND_SOC_DAPM_INPUT("IN1L"), | 
|  | 805 | SND_SOC_DAPM_INPUT("IN1R"), | 
|  | 806 | SND_SOC_DAPM_INPUT("IN2L"), | 
|  | 807 | SND_SOC_DAPM_INPUT("IN2R"), | 
|  | 808 | SND_SOC_DAPM_INPUT("IN3L"), | 
|  | 809 | SND_SOC_DAPM_INPUT("IN3R"), | 
|  | 810 |  | 
|  | 811 | SND_SOC_DAPM_OUTPUT("HPOUTL"), | 
|  | 812 | SND_SOC_DAPM_OUTPUT("HPOUTR"), | 
|  | 813 | SND_SOC_DAPM_OUTPUT("LINEOUTL"), | 
|  | 814 | SND_SOC_DAPM_OUTPUT("LINEOUTR"), | 
|  | 815 | SND_SOC_DAPM_OUTPUT("LOP"), | 
|  | 816 | SND_SOC_DAPM_OUTPUT("LON"), | 
|  | 817 | SND_SOC_DAPM_OUTPUT("ROP"), | 
|  | 818 | SND_SOC_DAPM_OUTPUT("RON"), | 
|  | 819 |  | 
|  | 820 | SND_SOC_DAPM_MICBIAS("Mic Bias", WM8903_MIC_BIAS_CONTROL_0, 0, 0), | 
|  | 821 |  | 
|  | 822 | SND_SOC_DAPM_MUX("Left Input Mux", SND_SOC_NOPM, 0, 0, &linput_mux), | 
|  | 823 | SND_SOC_DAPM_MUX("Left Input Inverting Mux", SND_SOC_NOPM, 0, 0, | 
|  | 824 | &linput_inv_mux), | 
|  | 825 | SND_SOC_DAPM_MUX("Left Input Mode Mux", SND_SOC_NOPM, 0, 0, &linput_mode_mux), | 
|  | 826 |  | 
|  | 827 | SND_SOC_DAPM_MUX("Right Input Mux", SND_SOC_NOPM, 0, 0, &rinput_mux), | 
|  | 828 | SND_SOC_DAPM_MUX("Right Input Inverting Mux", SND_SOC_NOPM, 0, 0, | 
|  | 829 | &rinput_inv_mux), | 
|  | 830 | SND_SOC_DAPM_MUX("Right Input Mode Mux", SND_SOC_NOPM, 0, 0, &rinput_mode_mux), | 
|  | 831 |  | 
|  | 832 | SND_SOC_DAPM_PGA("Left Input PGA", WM8903_POWER_MANAGEMENT_0, 1, 0, NULL, 0), | 
|  | 833 | SND_SOC_DAPM_PGA("Right Input PGA", WM8903_POWER_MANAGEMENT_0, 0, 0, NULL, 0), | 
|  | 834 |  | 
|  | 835 | SND_SOC_DAPM_ADC("ADCL", "Left HiFi Capture", WM8903_POWER_MANAGEMENT_6, 1, 0), | 
|  | 836 | SND_SOC_DAPM_ADC("ADCR", "Right HiFi Capture", WM8903_POWER_MANAGEMENT_6, 0, 0), | 
|  | 837 |  | 
|  | 838 | SND_SOC_DAPM_DAC("DACL", "Left Playback", WM8903_POWER_MANAGEMENT_6, 3, 0), | 
|  | 839 | SND_SOC_DAPM_DAC("DACR", "Right Playback", WM8903_POWER_MANAGEMENT_6, 2, 0), | 
|  | 840 |  | 
|  | 841 | SND_SOC_DAPM_MIXER("Left Output Mixer", WM8903_POWER_MANAGEMENT_1, 1, 0, | 
|  | 842 | left_output_mixer, ARRAY_SIZE(left_output_mixer)), | 
|  | 843 | SND_SOC_DAPM_MIXER("Right Output Mixer", WM8903_POWER_MANAGEMENT_1, 0, 0, | 
|  | 844 | right_output_mixer, ARRAY_SIZE(right_output_mixer)), | 
|  | 845 |  | 
|  | 846 | SND_SOC_DAPM_MIXER("Left Speaker Mixer", WM8903_POWER_MANAGEMENT_4, 1, 0, | 
|  | 847 | left_speaker_mixer, ARRAY_SIZE(left_speaker_mixer)), | 
|  | 848 | SND_SOC_DAPM_MIXER("Right Speaker Mixer", WM8903_POWER_MANAGEMENT_4, 0, 0, | 
|  | 849 | right_speaker_mixer, ARRAY_SIZE(right_speaker_mixer)), | 
|  | 850 |  | 
|  | 851 | SND_SOC_DAPM_PGA_E("Left Headphone Output PGA", WM8903_POWER_MANAGEMENT_2, | 
|  | 852 | 1, 0, NULL, 0, wm8903_output_event, | 
|  | 853 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | | 
|  | 854 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), | 
|  | 855 | SND_SOC_DAPM_PGA_E("Right Headphone Output PGA", WM8903_POWER_MANAGEMENT_2, | 
|  | 856 | 0, 0, NULL, 0, wm8903_output_event, | 
|  | 857 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | | 
|  | 858 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), | 
|  | 859 |  | 
|  | 860 | SND_SOC_DAPM_PGA_E("Left Line Output PGA", WM8903_POWER_MANAGEMENT_3, 1, 0, | 
|  | 861 | NULL, 0, wm8903_output_event, | 
|  | 862 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | | 
|  | 863 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), | 
|  | 864 | SND_SOC_DAPM_PGA_E("Right Line Output PGA", WM8903_POWER_MANAGEMENT_3, 0, 0, | 
|  | 865 | NULL, 0, wm8903_output_event, | 
|  | 866 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | | 
|  | 867 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), | 
|  | 868 |  | 
|  | 869 | SND_SOC_DAPM_PGA("Left Speaker PGA", WM8903_POWER_MANAGEMENT_5, 1, 0, | 
|  | 870 | NULL, 0), | 
|  | 871 | SND_SOC_DAPM_PGA("Right Speaker PGA", WM8903_POWER_MANAGEMENT_5, 0, 0, | 
|  | 872 | NULL, 0), | 
|  | 873 |  | 
|  | 874 | }; | 
|  | 875 |  | 
|  | 876 | static const struct snd_soc_dapm_route intercon[] = { | 
|  | 877 |  | 
|  | 878 | { "Left Input Mux", "IN1L", "IN1L" }, | 
|  | 879 | { "Left Input Mux", "IN2L", "IN2L" }, | 
|  | 880 | { "Left Input Mux", "IN3L", "IN3L" }, | 
|  | 881 |  | 
|  | 882 | { "Left Input Inverting Mux", "IN1L", "IN1L" }, | 
|  | 883 | { "Left Input Inverting Mux", "IN2L", "IN2L" }, | 
|  | 884 | { "Left Input Inverting Mux", "IN3L", "IN3L" }, | 
|  | 885 |  | 
|  | 886 | { "Right Input Mux", "IN1R", "IN1R" }, | 
|  | 887 | { "Right Input Mux", "IN2R", "IN2R" }, | 
|  | 888 | { "Right Input Mux", "IN3R", "IN3R" }, | 
|  | 889 |  | 
|  | 890 | { "Right Input Inverting Mux", "IN1R", "IN1R" }, | 
|  | 891 | { "Right Input Inverting Mux", "IN2R", "IN2R" }, | 
|  | 892 | { "Right Input Inverting Mux", "IN3R", "IN3R" }, | 
|  | 893 |  | 
|  | 894 | { "Left Input Mode Mux", "Single-Ended", "Left Input Inverting Mux" }, | 
|  | 895 | { "Left Input Mode Mux", "Differential Line", | 
|  | 896 | "Left Input Mux" }, | 
|  | 897 | { "Left Input Mode Mux", "Differential Line", | 
|  | 898 | "Left Input Inverting Mux" }, | 
|  | 899 | { "Left Input Mode Mux", "Differential Mic", | 
|  | 900 | "Left Input Mux" }, | 
|  | 901 | { "Left Input Mode Mux", "Differential Mic", | 
|  | 902 | "Left Input Inverting Mux" }, | 
|  | 903 |  | 
|  | 904 | { "Right Input Mode Mux", "Single-Ended", | 
|  | 905 | "Right Input Inverting Mux" }, | 
|  | 906 | { "Right Input Mode Mux", "Differential Line", | 
|  | 907 | "Right Input Mux" }, | 
|  | 908 | { "Right Input Mode Mux", "Differential Line", | 
|  | 909 | "Right Input Inverting Mux" }, | 
|  | 910 | { "Right Input Mode Mux", "Differential Mic", | 
|  | 911 | "Right Input Mux" }, | 
|  | 912 | { "Right Input Mode Mux", "Differential Mic", | 
|  | 913 | "Right Input Inverting Mux" }, | 
|  | 914 |  | 
|  | 915 | { "Left Input PGA", NULL, "Left Input Mode Mux" }, | 
|  | 916 | { "Right Input PGA", NULL, "Right Input Mode Mux" }, | 
|  | 917 |  | 
|  | 918 | { "ADCL", NULL, "Left Input PGA" }, | 
|  | 919 | { "ADCR", NULL, "Right Input PGA" }, | 
|  | 920 |  | 
|  | 921 | { "Left Output Mixer", "Left Bypass Switch", "Left Input PGA" }, | 
|  | 922 | { "Left Output Mixer", "Right Bypass Switch", "Right Input PGA" }, | 
|  | 923 | { "Left Output Mixer", "DACL Switch", "DACL" }, | 
|  | 924 | { "Left Output Mixer", "DACR Switch", "DACR" }, | 
|  | 925 |  | 
|  | 926 | { "Right Output Mixer", "Left Bypass Switch", "Left Input PGA" }, | 
|  | 927 | { "Right Output Mixer", "Right Bypass Switch", "Right Input PGA" }, | 
|  | 928 | { "Right Output Mixer", "DACL Switch", "DACL" }, | 
|  | 929 | { "Right Output Mixer", "DACR Switch", "DACR" }, | 
|  | 930 |  | 
|  | 931 | { "Left Speaker Mixer", "Left Bypass Switch", "Left Input PGA" }, | 
|  | 932 | { "Left Speaker Mixer", "Right Bypass Switch", "Right Input PGA" }, | 
|  | 933 | { "Left Speaker Mixer", "DACL Switch", "DACL" }, | 
|  | 934 | { "Left Speaker Mixer", "DACR Switch", "DACR" }, | 
|  | 935 |  | 
|  | 936 | { "Right Speaker Mixer", "Left Bypass Switch", "Left Input PGA" }, | 
|  | 937 | { "Right Speaker Mixer", "Right Bypass Switch", "Right Input PGA" }, | 
|  | 938 | { "Right Speaker Mixer", "DACL Switch", "DACL" }, | 
|  | 939 | { "Right Speaker Mixer", "DACR Switch", "DACR" }, | 
|  | 940 |  | 
|  | 941 | { "Left Line Output PGA", NULL, "Left Output Mixer" }, | 
|  | 942 | { "Right Line Output PGA", NULL, "Right Output Mixer" }, | 
|  | 943 |  | 
|  | 944 | { "Left Headphone Output PGA", NULL, "Left Output Mixer" }, | 
|  | 945 | { "Right Headphone Output PGA", NULL, "Right Output Mixer" }, | 
|  | 946 |  | 
|  | 947 | { "Left Speaker PGA", NULL, "Left Speaker Mixer" }, | 
|  | 948 | { "Right Speaker PGA", NULL, "Right Speaker Mixer" }, | 
|  | 949 |  | 
|  | 950 | { "HPOUTL", NULL, "Left Headphone Output PGA" }, | 
|  | 951 | { "HPOUTR", NULL, "Right Headphone Output PGA" }, | 
|  | 952 |  | 
|  | 953 | { "LINEOUTL", NULL, "Left Line Output PGA" }, | 
|  | 954 | { "LINEOUTR", NULL, "Right Line Output PGA" }, | 
|  | 955 |  | 
|  | 956 | { "LOP", NULL, "Left Speaker PGA" }, | 
|  | 957 | { "LON", NULL, "Left Speaker PGA" }, | 
|  | 958 |  | 
|  | 959 | { "ROP", NULL, "Right Speaker PGA" }, | 
|  | 960 | { "RON", NULL, "Right Speaker PGA" }, | 
|  | 961 | }; | 
|  | 962 |  | 
|  | 963 | static int wm8903_add_widgets(struct snd_soc_codec *codec) | 
|  | 964 | { | 
|  | 965 | snd_soc_dapm_new_controls(codec, wm8903_dapm_widgets, | 
|  | 966 | ARRAY_SIZE(wm8903_dapm_widgets)); | 
|  | 967 |  | 
|  | 968 | snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon)); | 
|  | 969 |  | 
|  | 970 | snd_soc_dapm_new_widgets(codec); | 
|  | 971 |  | 
|  | 972 | return 0; | 
|  | 973 | } | 
|  | 974 |  | 
|  | 975 | static int wm8903_set_bias_level(struct snd_soc_codec *codec, | 
|  | 976 | enum snd_soc_bias_level level) | 
|  | 977 | { | 
|  | 978 | struct i2c_client *i2c = codec->control_data; | 
|  | 979 | u16 reg, reg2; | 
|  | 980 |  | 
|  | 981 | switch (level) { | 
|  | 982 | case SND_SOC_BIAS_ON: | 
|  | 983 | case SND_SOC_BIAS_PREPARE: | 
|  | 984 | reg = wm8903_read(codec, WM8903_VMID_CONTROL_0); | 
|  | 985 | reg &= ~(WM8903_VMID_RES_MASK); | 
|  | 986 | reg |= WM8903_VMID_RES_50K; | 
|  | 987 | wm8903_write(codec, WM8903_VMID_CONTROL_0, reg); | 
|  | 988 | break; | 
|  | 989 |  | 
|  | 990 | case SND_SOC_BIAS_STANDBY: | 
|  | 991 | if (codec->bias_level == SND_SOC_BIAS_OFF) { | 
|  | 992 | wm8903_run_sequence(codec, 0); | 
|  | 993 | wm8903_sync_reg_cache(codec, codec->reg_cache); | 
|  | 994 |  | 
|  | 995 | /* Enable low impedence charge pump output */ | 
|  | 996 | reg = wm8903_read(codec, | 
|  | 997 | WM8903_CONTROL_INTERFACE_TEST_1); | 
|  | 998 | wm8903_write(codec, WM8903_CONTROL_INTERFACE_TEST_1, | 
|  | 999 | reg | WM8903_TEST_KEY); | 
|  | 1000 | reg2 = wm8903_read(codec, WM8903_CHARGE_PUMP_TEST_1); | 
|  | 1001 | wm8903_write(codec, WM8903_CHARGE_PUMP_TEST_1, | 
|  | 1002 | reg2 | WM8903_CP_SW_KELVIN_MODE_MASK); | 
|  | 1003 | wm8903_write(codec, WM8903_CONTROL_INTERFACE_TEST_1, | 
|  | 1004 | reg); | 
|  | 1005 |  | 
|  | 1006 | /* By default no bypass paths are enabled so | 
|  | 1007 | * enable Class W support. | 
|  | 1008 | */ | 
|  | 1009 | dev_dbg(&i2c->dev, "Enabling Class W\n"); | 
|  | 1010 | wm8903_write(codec, WM8903_CLASS_W_0, reg | | 
|  | 1011 | WM8903_CP_DYN_FREQ | WM8903_CP_DYN_V); | 
|  | 1012 | } | 
|  | 1013 |  | 
|  | 1014 | reg = wm8903_read(codec, WM8903_VMID_CONTROL_0); | 
|  | 1015 | reg &= ~(WM8903_VMID_RES_MASK); | 
|  | 1016 | reg |= WM8903_VMID_RES_250K; | 
|  | 1017 | wm8903_write(codec, WM8903_VMID_CONTROL_0, reg); | 
|  | 1018 | break; | 
|  | 1019 |  | 
|  | 1020 | case SND_SOC_BIAS_OFF: | 
|  | 1021 | wm8903_run_sequence(codec, 32); | 
|  | 1022 | break; | 
|  | 1023 | } | 
|  | 1024 |  | 
|  | 1025 | codec->bias_level = level; | 
|  | 1026 |  | 
|  | 1027 | return 0; | 
|  | 1028 | } | 
|  | 1029 |  | 
|  | 1030 | static int wm8903_set_dai_sysclk(struct snd_soc_dai *codec_dai, | 
|  | 1031 | int clk_id, unsigned int freq, int dir) | 
|  | 1032 | { | 
|  | 1033 | struct snd_soc_codec *codec = codec_dai->codec; | 
|  | 1034 | struct wm8903_priv *wm8903 = codec->private_data; | 
|  | 1035 |  | 
|  | 1036 | wm8903->sysclk = freq; | 
|  | 1037 |  | 
|  | 1038 | return 0; | 
|  | 1039 | } | 
|  | 1040 |  | 
|  | 1041 | static int wm8903_set_dai_fmt(struct snd_soc_dai *codec_dai, | 
|  | 1042 | unsigned int fmt) | 
|  | 1043 | { | 
|  | 1044 | struct snd_soc_codec *codec = codec_dai->codec; | 
|  | 1045 | u16 aif1 = wm8903_read(codec, WM8903_AUDIO_INTERFACE_1); | 
|  | 1046 |  | 
|  | 1047 | aif1 &= ~(WM8903_LRCLK_DIR | WM8903_BCLK_DIR | WM8903_AIF_FMT_MASK | | 
|  | 1048 | WM8903_AIF_LRCLK_INV | WM8903_AIF_BCLK_INV); | 
|  | 1049 |  | 
|  | 1050 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | 
|  | 1051 | case SND_SOC_DAIFMT_CBS_CFS: | 
|  | 1052 | break; | 
|  | 1053 | case SND_SOC_DAIFMT_CBS_CFM: | 
|  | 1054 | aif1 |= WM8903_LRCLK_DIR; | 
|  | 1055 | break; | 
|  | 1056 | case SND_SOC_DAIFMT_CBM_CFM: | 
|  | 1057 | aif1 |= WM8903_LRCLK_DIR | WM8903_BCLK_DIR; | 
|  | 1058 | break; | 
|  | 1059 | case SND_SOC_DAIFMT_CBM_CFS: | 
|  | 1060 | aif1 |= WM8903_BCLK_DIR; | 
|  | 1061 | break; | 
|  | 1062 | default: | 
|  | 1063 | return -EINVAL; | 
|  | 1064 | } | 
|  | 1065 |  | 
|  | 1066 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | 
|  | 1067 | case SND_SOC_DAIFMT_DSP_A: | 
|  | 1068 | aif1 |= 0x3; | 
|  | 1069 | break; | 
|  | 1070 | case SND_SOC_DAIFMT_DSP_B: | 
|  | 1071 | aif1 |= 0x3 | WM8903_AIF_LRCLK_INV; | 
|  | 1072 | break; | 
|  | 1073 | case SND_SOC_DAIFMT_I2S: | 
|  | 1074 | aif1 |= 0x2; | 
|  | 1075 | break; | 
|  | 1076 | case SND_SOC_DAIFMT_RIGHT_J: | 
|  | 1077 | aif1 |= 0x1; | 
|  | 1078 | break; | 
|  | 1079 | case SND_SOC_DAIFMT_LEFT_J: | 
|  | 1080 | break; | 
|  | 1081 | default: | 
|  | 1082 | return -EINVAL; | 
|  | 1083 | } | 
|  | 1084 |  | 
|  | 1085 | /* Clock inversion */ | 
|  | 1086 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | 
|  | 1087 | case SND_SOC_DAIFMT_DSP_A: | 
|  | 1088 | case SND_SOC_DAIFMT_DSP_B: | 
|  | 1089 | /* frame inversion not valid for DSP modes */ | 
|  | 1090 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | 
|  | 1091 | case SND_SOC_DAIFMT_NB_NF: | 
|  | 1092 | break; | 
|  | 1093 | case SND_SOC_DAIFMT_IB_NF: | 
|  | 1094 | aif1 |= WM8903_AIF_BCLK_INV; | 
|  | 1095 | break; | 
|  | 1096 | default: | 
|  | 1097 | return -EINVAL; | 
|  | 1098 | } | 
|  | 1099 | break; | 
|  | 1100 | case SND_SOC_DAIFMT_I2S: | 
|  | 1101 | case SND_SOC_DAIFMT_RIGHT_J: | 
|  | 1102 | case SND_SOC_DAIFMT_LEFT_J: | 
|  | 1103 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | 
|  | 1104 | case SND_SOC_DAIFMT_NB_NF: | 
|  | 1105 | break; | 
|  | 1106 | case SND_SOC_DAIFMT_IB_IF: | 
|  | 1107 | aif1 |= WM8903_AIF_BCLK_INV | WM8903_AIF_LRCLK_INV; | 
|  | 1108 | break; | 
|  | 1109 | case SND_SOC_DAIFMT_IB_NF: | 
|  | 1110 | aif1 |= WM8903_AIF_BCLK_INV; | 
|  | 1111 | break; | 
|  | 1112 | case SND_SOC_DAIFMT_NB_IF: | 
|  | 1113 | aif1 |= WM8903_AIF_LRCLK_INV; | 
|  | 1114 | break; | 
|  | 1115 | default: | 
|  | 1116 | return -EINVAL; | 
|  | 1117 | } | 
|  | 1118 | break; | 
|  | 1119 | default: | 
|  | 1120 | return -EINVAL; | 
|  | 1121 | } | 
|  | 1122 |  | 
|  | 1123 | wm8903_write(codec, WM8903_AUDIO_INTERFACE_1, aif1); | 
|  | 1124 |  | 
|  | 1125 | return 0; | 
|  | 1126 | } | 
|  | 1127 |  | 
|  | 1128 | static int wm8903_digital_mute(struct snd_soc_dai *codec_dai, int mute) | 
|  | 1129 | { | 
|  | 1130 | struct snd_soc_codec *codec = codec_dai->codec; | 
|  | 1131 | u16 reg; | 
|  | 1132 |  | 
|  | 1133 | reg = wm8903_read(codec, WM8903_DAC_DIGITAL_1); | 
|  | 1134 |  | 
|  | 1135 | if (mute) | 
|  | 1136 | reg |= WM8903_DAC_MUTE; | 
|  | 1137 | else | 
|  | 1138 | reg &= ~WM8903_DAC_MUTE; | 
|  | 1139 |  | 
|  | 1140 | wm8903_write(codec, WM8903_DAC_DIGITAL_1, reg); | 
|  | 1141 |  | 
|  | 1142 | return 0; | 
|  | 1143 | } | 
|  | 1144 |  | 
|  | 1145 | /* Lookup table for CLK_SYS/fs ratio.  256fs or more is recommended | 
|  | 1146 | * for optimal performance so we list the lower rates first and match | 
|  | 1147 | * on the last match we find. */ | 
|  | 1148 | static struct { | 
|  | 1149 | int div; | 
|  | 1150 | int rate; | 
|  | 1151 | int mode; | 
|  | 1152 | int mclk_div; | 
|  | 1153 | } clk_sys_ratios[] = { | 
|  | 1154 | {   64, 0x0, 0x0, 1 }, | 
|  | 1155 | {   68, 0x0, 0x1, 1 }, | 
|  | 1156 | {  125, 0x0, 0x2, 1 }, | 
|  | 1157 | {  128, 0x1, 0x0, 1 }, | 
|  | 1158 | {  136, 0x1, 0x1, 1 }, | 
|  | 1159 | {  192, 0x2, 0x0, 1 }, | 
|  | 1160 | {  204, 0x2, 0x1, 1 }, | 
|  | 1161 |  | 
|  | 1162 | {   64, 0x0, 0x0, 2 }, | 
|  | 1163 | {   68, 0x0, 0x1, 2 }, | 
|  | 1164 | {  125, 0x0, 0x2, 2 }, | 
|  | 1165 | {  128, 0x1, 0x0, 2 }, | 
|  | 1166 | {  136, 0x1, 0x1, 2 }, | 
|  | 1167 | {  192, 0x2, 0x0, 2 }, | 
|  | 1168 | {  204, 0x2, 0x1, 2 }, | 
|  | 1169 |  | 
|  | 1170 | {  250, 0x2, 0x2, 1 }, | 
|  | 1171 | {  256, 0x3, 0x0, 1 }, | 
|  | 1172 | {  272, 0x3, 0x1, 1 }, | 
|  | 1173 | {  384, 0x4, 0x0, 1 }, | 
|  | 1174 | {  408, 0x4, 0x1, 1 }, | 
|  | 1175 | {  375, 0x4, 0x2, 1 }, | 
|  | 1176 | {  512, 0x5, 0x0, 1 }, | 
|  | 1177 | {  544, 0x5, 0x1, 1 }, | 
|  | 1178 | {  500, 0x5, 0x2, 1 }, | 
|  | 1179 | {  768, 0x6, 0x0, 1 }, | 
|  | 1180 | {  816, 0x6, 0x1, 1 }, | 
|  | 1181 | {  750, 0x6, 0x2, 1 }, | 
|  | 1182 | { 1024, 0x7, 0x0, 1 }, | 
|  | 1183 | { 1088, 0x7, 0x1, 1 }, | 
|  | 1184 | { 1000, 0x7, 0x2, 1 }, | 
|  | 1185 | { 1408, 0x8, 0x0, 1 }, | 
|  | 1186 | { 1496, 0x8, 0x1, 1 }, | 
|  | 1187 | { 1536, 0x9, 0x0, 1 }, | 
|  | 1188 | { 1632, 0x9, 0x1, 1 }, | 
|  | 1189 | { 1500, 0x9, 0x2, 1 }, | 
|  | 1190 |  | 
|  | 1191 | {  250, 0x2, 0x2, 2 }, | 
|  | 1192 | {  256, 0x3, 0x0, 2 }, | 
|  | 1193 | {  272, 0x3, 0x1, 2 }, | 
|  | 1194 | {  384, 0x4, 0x0, 2 }, | 
|  | 1195 | {  408, 0x4, 0x1, 2 }, | 
|  | 1196 | {  375, 0x4, 0x2, 2 }, | 
|  | 1197 | {  512, 0x5, 0x0, 2 }, | 
|  | 1198 | {  544, 0x5, 0x1, 2 }, | 
|  | 1199 | {  500, 0x5, 0x2, 2 }, | 
|  | 1200 | {  768, 0x6, 0x0, 2 }, | 
|  | 1201 | {  816, 0x6, 0x1, 2 }, | 
|  | 1202 | {  750, 0x6, 0x2, 2 }, | 
|  | 1203 | { 1024, 0x7, 0x0, 2 }, | 
|  | 1204 | { 1088, 0x7, 0x1, 2 }, | 
|  | 1205 | { 1000, 0x7, 0x2, 2 }, | 
|  | 1206 | { 1408, 0x8, 0x0, 2 }, | 
|  | 1207 | { 1496, 0x8, 0x1, 2 }, | 
|  | 1208 | { 1536, 0x9, 0x0, 2 }, | 
|  | 1209 | { 1632, 0x9, 0x1, 2 }, | 
|  | 1210 | { 1500, 0x9, 0x2, 2 }, | 
|  | 1211 | }; | 
|  | 1212 |  | 
|  | 1213 | /* CLK_SYS/BCLK ratios - multiplied by 10 due to .5s */ | 
|  | 1214 | static struct { | 
|  | 1215 | int ratio; | 
|  | 1216 | int div; | 
|  | 1217 | } bclk_divs[] = { | 
|  | 1218 | {  10,  0 }, | 
|  | 1219 | {  15,  1 }, | 
|  | 1220 | {  20,  2 }, | 
|  | 1221 | {  30,  3 }, | 
|  | 1222 | {  40,  4 }, | 
|  | 1223 | {  50,  5 }, | 
|  | 1224 | {  55,  6 }, | 
|  | 1225 | {  60,  7 }, | 
|  | 1226 | {  80,  8 }, | 
|  | 1227 | { 100,  9 }, | 
|  | 1228 | { 110, 10 }, | 
|  | 1229 | { 120, 11 }, | 
|  | 1230 | { 160, 12 }, | 
|  | 1231 | { 200, 13 }, | 
|  | 1232 | { 220, 14 }, | 
|  | 1233 | { 240, 15 }, | 
|  | 1234 | { 250, 16 }, | 
|  | 1235 | { 300, 17 }, | 
|  | 1236 | { 320, 18 }, | 
|  | 1237 | { 440, 19 }, | 
|  | 1238 | { 480, 20 }, | 
|  | 1239 | }; | 
|  | 1240 |  | 
|  | 1241 | /* Sample rates for DSP */ | 
|  | 1242 | static struct { | 
|  | 1243 | int rate; | 
|  | 1244 | int value; | 
|  | 1245 | } sample_rates[] = { | 
|  | 1246 | {  8000,  0 }, | 
|  | 1247 | { 11025,  1 }, | 
|  | 1248 | { 12000,  2 }, | 
|  | 1249 | { 16000,  3 }, | 
|  | 1250 | { 22050,  4 }, | 
|  | 1251 | { 24000,  5 }, | 
|  | 1252 | { 32000,  6 }, | 
|  | 1253 | { 44100,  7 }, | 
|  | 1254 | { 48000,  8 }, | 
|  | 1255 | { 88200,  9 }, | 
|  | 1256 | { 96000, 10 }, | 
|  | 1257 | { 0,      0 }, | 
|  | 1258 | }; | 
|  | 1259 |  | 
|  | 1260 | static int wm8903_startup(struct snd_pcm_substream *substream) | 
|  | 1261 | { | 
|  | 1262 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 
|  | 1263 | struct snd_soc_device *socdev = rtd->socdev; | 
|  | 1264 | struct snd_soc_codec *codec = socdev->codec; | 
|  | 1265 | struct wm8903_priv *wm8903 = codec->private_data; | 
|  | 1266 | struct i2c_client *i2c = codec->control_data; | 
|  | 1267 | struct snd_pcm_runtime *master_runtime; | 
|  | 1268 |  | 
|  | 1269 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 
|  | 1270 | wm8903->playback_active++; | 
|  | 1271 | else | 
|  | 1272 | wm8903->capture_active++; | 
|  | 1273 |  | 
|  | 1274 | /* The DAI has shared clocks so if we already have a playback or | 
|  | 1275 | * capture going then constrain this substream to match it. | 
|  | 1276 | */ | 
|  | 1277 | if (wm8903->master_substream) { | 
|  | 1278 | master_runtime = wm8903->master_substream->runtime; | 
|  | 1279 |  | 
|  | 1280 | dev_dbg(&i2c->dev, "Constraining to %d bits at %dHz\n", | 
|  | 1281 | master_runtime->sample_bits, | 
|  | 1282 | master_runtime->rate); | 
|  | 1283 |  | 
|  | 1284 | snd_pcm_hw_constraint_minmax(substream->runtime, | 
|  | 1285 | SNDRV_PCM_HW_PARAM_RATE, | 
|  | 1286 | master_runtime->rate, | 
|  | 1287 | master_runtime->rate); | 
|  | 1288 |  | 
|  | 1289 | snd_pcm_hw_constraint_minmax(substream->runtime, | 
|  | 1290 | SNDRV_PCM_HW_PARAM_SAMPLE_BITS, | 
|  | 1291 | master_runtime->sample_bits, | 
|  | 1292 | master_runtime->sample_bits); | 
|  | 1293 |  | 
|  | 1294 | wm8903->slave_substream = substream; | 
|  | 1295 | } else | 
|  | 1296 | wm8903->master_substream = substream; | 
|  | 1297 |  | 
|  | 1298 | return 0; | 
|  | 1299 | } | 
|  | 1300 |  | 
|  | 1301 | static void wm8903_shutdown(struct snd_pcm_substream *substream) | 
|  | 1302 | { | 
|  | 1303 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 
|  | 1304 | struct snd_soc_device *socdev = rtd->socdev; | 
|  | 1305 | struct snd_soc_codec *codec = socdev->codec; | 
|  | 1306 | struct wm8903_priv *wm8903 = codec->private_data; | 
|  | 1307 |  | 
|  | 1308 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 
|  | 1309 | wm8903->playback_active--; | 
|  | 1310 | else | 
|  | 1311 | wm8903->capture_active--; | 
|  | 1312 |  | 
|  | 1313 | if (wm8903->master_substream == substream) | 
|  | 1314 | wm8903->master_substream = wm8903->slave_substream; | 
|  | 1315 |  | 
|  | 1316 | wm8903->slave_substream = NULL; | 
|  | 1317 | } | 
|  | 1318 |  | 
|  | 1319 | static int wm8903_hw_params(struct snd_pcm_substream *substream, | 
|  | 1320 | struct snd_pcm_hw_params *params) | 
|  | 1321 | { | 
|  | 1322 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 
|  | 1323 | struct snd_soc_device *socdev = rtd->socdev; | 
|  | 1324 | struct snd_soc_codec *codec = socdev->codec; | 
|  | 1325 | struct wm8903_priv *wm8903 = codec->private_data; | 
|  | 1326 | struct i2c_client *i2c = codec->control_data; | 
|  | 1327 | int fs = params_rate(params); | 
|  | 1328 | int bclk; | 
|  | 1329 | int bclk_div; | 
|  | 1330 | int i; | 
|  | 1331 | int dsp_config; | 
|  | 1332 | int clk_config; | 
|  | 1333 | int best_val; | 
|  | 1334 | int cur_val; | 
|  | 1335 | int clk_sys; | 
|  | 1336 |  | 
|  | 1337 | u16 aif1 = wm8903_read(codec, WM8903_AUDIO_INTERFACE_1); | 
|  | 1338 | u16 aif2 = wm8903_read(codec, WM8903_AUDIO_INTERFACE_2); | 
|  | 1339 | u16 aif3 = wm8903_read(codec, WM8903_AUDIO_INTERFACE_3); | 
|  | 1340 | u16 clock0 = wm8903_read(codec, WM8903_CLOCK_RATES_0); | 
|  | 1341 | u16 clock1 = wm8903_read(codec, WM8903_CLOCK_RATES_1); | 
|  | 1342 |  | 
|  | 1343 | if (substream == wm8903->slave_substream) { | 
|  | 1344 | dev_dbg(&i2c->dev, "Ignoring hw_params for slave substream\n"); | 
|  | 1345 | return 0; | 
|  | 1346 | } | 
|  | 1347 |  | 
|  | 1348 | /* Configure sample rate logic for DSP - choose nearest rate */ | 
|  | 1349 | dsp_config = 0; | 
|  | 1350 | best_val = abs(sample_rates[dsp_config].rate - fs); | 
|  | 1351 | for (i = 1; i < ARRAY_SIZE(sample_rates); i++) { | 
|  | 1352 | cur_val = abs(sample_rates[i].rate - fs); | 
|  | 1353 | if (cur_val <= best_val) { | 
|  | 1354 | dsp_config = i; | 
|  | 1355 | best_val = cur_val; | 
|  | 1356 | } | 
|  | 1357 | } | 
|  | 1358 |  | 
|  | 1359 | /* Constraints should stop us hitting this but let's make sure */ | 
|  | 1360 | if (wm8903->capture_active) | 
|  | 1361 | switch (sample_rates[dsp_config].rate) { | 
|  | 1362 | case 88200: | 
|  | 1363 | case 96000: | 
|  | 1364 | dev_err(&i2c->dev, "%dHz unsupported by ADC\n", | 
|  | 1365 | fs); | 
|  | 1366 | return -EINVAL; | 
|  | 1367 |  | 
|  | 1368 | default: | 
|  | 1369 | break; | 
|  | 1370 | } | 
|  | 1371 |  | 
|  | 1372 | dev_dbg(&i2c->dev, "DSP fs = %dHz\n", sample_rates[dsp_config].rate); | 
|  | 1373 | clock1 &= ~WM8903_SAMPLE_RATE_MASK; | 
|  | 1374 | clock1 |= sample_rates[dsp_config].value; | 
|  | 1375 |  | 
|  | 1376 | aif1 &= ~WM8903_AIF_WL_MASK; | 
|  | 1377 | bclk = 2 * fs; | 
|  | 1378 | switch (params_format(params)) { | 
|  | 1379 | case SNDRV_PCM_FORMAT_S16_LE: | 
|  | 1380 | bclk *= 16; | 
|  | 1381 | break; | 
|  | 1382 | case SNDRV_PCM_FORMAT_S20_3LE: | 
|  | 1383 | bclk *= 20; | 
|  | 1384 | aif1 |= 0x4; | 
|  | 1385 | break; | 
|  | 1386 | case SNDRV_PCM_FORMAT_S24_LE: | 
|  | 1387 | bclk *= 24; | 
|  | 1388 | aif1 |= 0x8; | 
|  | 1389 | break; | 
|  | 1390 | case SNDRV_PCM_FORMAT_S32_LE: | 
|  | 1391 | bclk *= 32; | 
|  | 1392 | aif1 |= 0xc; | 
|  | 1393 | break; | 
|  | 1394 | default: | 
|  | 1395 | return -EINVAL; | 
|  | 1396 | } | 
|  | 1397 |  | 
|  | 1398 | dev_dbg(&i2c->dev, "MCLK = %dHz, target sample rate = %dHz\n", | 
|  | 1399 | wm8903->sysclk, fs); | 
|  | 1400 |  | 
|  | 1401 | /* We may not have an MCLK which allows us to generate exactly | 
|  | 1402 | * the clock we want, particularly with USB derived inputs, so | 
|  | 1403 | * approximate. | 
|  | 1404 | */ | 
|  | 1405 | clk_config = 0; | 
|  | 1406 | best_val = abs((wm8903->sysclk / | 
|  | 1407 | (clk_sys_ratios[0].mclk_div * | 
|  | 1408 | clk_sys_ratios[0].div)) - fs); | 
|  | 1409 | for (i = 1; i < ARRAY_SIZE(clk_sys_ratios); i++) { | 
|  | 1410 | cur_val = abs((wm8903->sysclk / | 
|  | 1411 | (clk_sys_ratios[i].mclk_div * | 
|  | 1412 | clk_sys_ratios[i].div)) - fs); | 
|  | 1413 |  | 
|  | 1414 | if (cur_val <= best_val) { | 
|  | 1415 | clk_config = i; | 
|  | 1416 | best_val = cur_val; | 
|  | 1417 | } | 
|  | 1418 | } | 
|  | 1419 |  | 
|  | 1420 | if (clk_sys_ratios[clk_config].mclk_div == 2) { | 
|  | 1421 | clock0 |= WM8903_MCLKDIV2; | 
|  | 1422 | clk_sys = wm8903->sysclk / 2; | 
|  | 1423 | } else { | 
|  | 1424 | clock0 &= ~WM8903_MCLKDIV2; | 
|  | 1425 | clk_sys = wm8903->sysclk; | 
|  | 1426 | } | 
|  | 1427 |  | 
|  | 1428 | clock1 &= ~(WM8903_CLK_SYS_RATE_MASK | | 
|  | 1429 | WM8903_CLK_SYS_MODE_MASK); | 
|  | 1430 | clock1 |= clk_sys_ratios[clk_config].rate << WM8903_CLK_SYS_RATE_SHIFT; | 
|  | 1431 | clock1 |= clk_sys_ratios[clk_config].mode << WM8903_CLK_SYS_MODE_SHIFT; | 
|  | 1432 |  | 
|  | 1433 | dev_dbg(&i2c->dev, "CLK_SYS_RATE=%x, CLK_SYS_MODE=%x div=%d\n", | 
|  | 1434 | clk_sys_ratios[clk_config].rate, | 
|  | 1435 | clk_sys_ratios[clk_config].mode, | 
|  | 1436 | clk_sys_ratios[clk_config].div); | 
|  | 1437 |  | 
|  | 1438 | dev_dbg(&i2c->dev, "Actual CLK_SYS = %dHz\n", clk_sys); | 
|  | 1439 |  | 
|  | 1440 | /* We may not get quite the right frequency if using | 
|  | 1441 | * approximate clocks so look for the closest match that is | 
|  | 1442 | * higher than the target (we need to ensure that there enough | 
|  | 1443 | * BCLKs to clock out the samples). | 
|  | 1444 | */ | 
|  | 1445 | bclk_div = 0; | 
|  | 1446 | best_val = ((clk_sys * 10) / bclk_divs[0].ratio) - bclk; | 
|  | 1447 | i = 1; | 
|  | 1448 | while (i < ARRAY_SIZE(bclk_divs)) { | 
|  | 1449 | cur_val = ((clk_sys * 10) / bclk_divs[i].ratio) - bclk; | 
|  | 1450 | if (cur_val < 0) /* BCLK table is sorted */ | 
|  | 1451 | break; | 
|  | 1452 | bclk_div = i; | 
|  | 1453 | best_val = cur_val; | 
|  | 1454 | i++; | 
|  | 1455 | } | 
|  | 1456 |  | 
|  | 1457 | aif2 &= ~WM8903_BCLK_DIV_MASK; | 
|  | 1458 | aif3 &= ~WM8903_LRCLK_RATE_MASK; | 
|  | 1459 |  | 
|  | 1460 | dev_dbg(&i2c->dev, "BCLK ratio %d for %dHz - actual BCLK = %dHz\n", | 
|  | 1461 | bclk_divs[bclk_div].ratio / 10, bclk, | 
|  | 1462 | (clk_sys * 10) / bclk_divs[bclk_div].ratio); | 
|  | 1463 |  | 
|  | 1464 | aif2 |= bclk_divs[bclk_div].div; | 
|  | 1465 | aif3 |= bclk / fs; | 
|  | 1466 |  | 
|  | 1467 | wm8903_write(codec, WM8903_CLOCK_RATES_0, clock0); | 
|  | 1468 | wm8903_write(codec, WM8903_CLOCK_RATES_1, clock1); | 
|  | 1469 | wm8903_write(codec, WM8903_AUDIO_INTERFACE_1, aif1); | 
|  | 1470 | wm8903_write(codec, WM8903_AUDIO_INTERFACE_2, aif2); | 
|  | 1471 | wm8903_write(codec, WM8903_AUDIO_INTERFACE_3, aif3); | 
|  | 1472 |  | 
|  | 1473 | return 0; | 
|  | 1474 | } | 
|  | 1475 |  | 
|  | 1476 | #define WM8903_PLAYBACK_RATES (SNDRV_PCM_RATE_8000 |\ | 
|  | 1477 | SNDRV_PCM_RATE_11025 |	\ | 
|  | 1478 | SNDRV_PCM_RATE_16000 |	\ | 
|  | 1479 | SNDRV_PCM_RATE_22050 |	\ | 
|  | 1480 | SNDRV_PCM_RATE_32000 |	\ | 
|  | 1481 | SNDRV_PCM_RATE_44100 |	\ | 
|  | 1482 | SNDRV_PCM_RATE_48000 |	\ | 
|  | 1483 | SNDRV_PCM_RATE_88200 |	\ | 
|  | 1484 | SNDRV_PCM_RATE_96000) | 
|  | 1485 |  | 
|  | 1486 | #define WM8903_CAPTURE_RATES (SNDRV_PCM_RATE_8000 |\ | 
|  | 1487 | SNDRV_PCM_RATE_11025 |	\ | 
|  | 1488 | SNDRV_PCM_RATE_16000 |	\ | 
|  | 1489 | SNDRV_PCM_RATE_22050 |	\ | 
|  | 1490 | SNDRV_PCM_RATE_32000 |	\ | 
|  | 1491 | SNDRV_PCM_RATE_44100 |	\ | 
|  | 1492 | SNDRV_PCM_RATE_48000) | 
|  | 1493 |  | 
|  | 1494 | #define WM8903_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ | 
|  | 1495 | SNDRV_PCM_FMTBIT_S20_3LE |\ | 
|  | 1496 | SNDRV_PCM_FMTBIT_S24_LE) | 
|  | 1497 |  | 
|  | 1498 | struct snd_soc_dai wm8903_dai = { | 
|  | 1499 | .name = "WM8903", | 
|  | 1500 | .playback = { | 
|  | 1501 | .stream_name = "Playback", | 
|  | 1502 | .channels_min = 2, | 
|  | 1503 | .channels_max = 2, | 
|  | 1504 | .rates = WM8903_PLAYBACK_RATES, | 
|  | 1505 | .formats = WM8903_FORMATS, | 
|  | 1506 | }, | 
|  | 1507 | .capture = { | 
|  | 1508 | .stream_name = "Capture", | 
|  | 1509 | .channels_min = 2, | 
|  | 1510 | .channels_max = 2, | 
|  | 1511 | .rates = WM8903_CAPTURE_RATES, | 
|  | 1512 | .formats = WM8903_FORMATS, | 
|  | 1513 | }, | 
|  | 1514 | .ops = { | 
|  | 1515 | .startup = wm8903_startup, | 
|  | 1516 | .shutdown = wm8903_shutdown, | 
|  | 1517 | .hw_params = wm8903_hw_params, | 
|  | 1518 | }, | 
|  | 1519 | .dai_ops = { | 
|  | 1520 | .digital_mute = wm8903_digital_mute, | 
|  | 1521 | .set_fmt = wm8903_set_dai_fmt, | 
|  | 1522 | .set_sysclk = wm8903_set_dai_sysclk | 
|  | 1523 | } | 
|  | 1524 | }; | 
|  | 1525 | EXPORT_SYMBOL_GPL(wm8903_dai); | 
|  | 1526 |  | 
|  | 1527 | static int wm8903_suspend(struct platform_device *pdev, pm_message_t state) | 
|  | 1528 | { | 
|  | 1529 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 
|  | 1530 | struct snd_soc_codec *codec = socdev->codec; | 
|  | 1531 |  | 
|  | 1532 | wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF); | 
|  | 1533 |  | 
|  | 1534 | return 0; | 
|  | 1535 | } | 
|  | 1536 |  | 
|  | 1537 | static int wm8903_resume(struct platform_device *pdev) | 
|  | 1538 | { | 
|  | 1539 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 
|  | 1540 | struct snd_soc_codec *codec = socdev->codec; | 
|  | 1541 | struct i2c_client *i2c = codec->control_data; | 
|  | 1542 | int i; | 
|  | 1543 | u16 *reg_cache = codec->reg_cache; | 
|  | 1544 | u16 *tmp_cache = kmemdup(codec->reg_cache, sizeof(wm8903_reg_defaults), | 
|  | 1545 | GFP_KERNEL); | 
|  | 1546 |  | 
|  | 1547 | /* Bring the codec back up to standby first to minimise pop/clicks */ | 
|  | 1548 | wm8903_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 
|  | 1549 | wm8903_set_bias_level(codec, codec->suspend_bias_level); | 
|  | 1550 |  | 
|  | 1551 | /* Sync back everything else */ | 
|  | 1552 | if (tmp_cache) { | 
|  | 1553 | for (i = 2; i < ARRAY_SIZE(wm8903_reg_defaults); i++) | 
|  | 1554 | if (tmp_cache[i] != reg_cache[i]) | 
|  | 1555 | wm8903_write(codec, i, tmp_cache[i]); | 
|  | 1556 | } else { | 
|  | 1557 | dev_err(&i2c->dev, "Failed to allocate temporary cache\n"); | 
|  | 1558 | } | 
|  | 1559 |  | 
|  | 1560 | return 0; | 
|  | 1561 | } | 
|  | 1562 |  | 
|  | 1563 | /* | 
|  | 1564 | * initialise the WM8903 driver | 
|  | 1565 | * register the mixer and dsp interfaces with the kernel | 
|  | 1566 | */ | 
|  | 1567 | static int wm8903_init(struct snd_soc_device *socdev) | 
|  | 1568 | { | 
|  | 1569 | struct snd_soc_codec *codec = socdev->codec; | 
|  | 1570 | struct i2c_client *i2c = codec->control_data; | 
|  | 1571 | int ret = 0; | 
|  | 1572 | u16 val; | 
|  | 1573 |  | 
|  | 1574 | val = wm8903_hw_read(codec, WM8903_SW_RESET_AND_ID); | 
|  | 1575 | if (val != wm8903_reg_defaults[WM8903_SW_RESET_AND_ID]) { | 
|  | 1576 | dev_err(&i2c->dev, | 
|  | 1577 | "Device with ID register %x is not a WM8903\n", val); | 
|  | 1578 | return -ENODEV; | 
|  | 1579 | } | 
|  | 1580 |  | 
|  | 1581 | codec->name = "WM8903"; | 
|  | 1582 | codec->owner = THIS_MODULE; | 
|  | 1583 | codec->read = wm8903_read; | 
|  | 1584 | codec->write = wm8903_write; | 
|  | 1585 | codec->bias_level = SND_SOC_BIAS_OFF; | 
|  | 1586 | codec->set_bias_level = wm8903_set_bias_level; | 
|  | 1587 | codec->dai = &wm8903_dai; | 
|  | 1588 | codec->num_dai = 1; | 
|  | 1589 | codec->reg_cache_size = ARRAY_SIZE(wm8903_reg_defaults); | 
|  | 1590 | codec->reg_cache = kmemdup(wm8903_reg_defaults, | 
|  | 1591 | sizeof(wm8903_reg_defaults), | 
|  | 1592 | GFP_KERNEL); | 
|  | 1593 | if (codec->reg_cache == NULL) { | 
|  | 1594 | dev_err(&i2c->dev, "Failed to allocate register cache\n"); | 
|  | 1595 | return -ENOMEM; | 
|  | 1596 | } | 
|  | 1597 |  | 
|  | 1598 | val = wm8903_read(codec, WM8903_REVISION_NUMBER); | 
|  | 1599 | dev_info(&i2c->dev, "WM8903 revision %d\n", | 
|  | 1600 | val & WM8903_CHIP_REV_MASK); | 
|  | 1601 |  | 
|  | 1602 | wm8903_reset(codec); | 
|  | 1603 |  | 
|  | 1604 | /* register pcms */ | 
|  | 1605 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | 
|  | 1606 | if (ret < 0) { | 
|  | 1607 | dev_err(&i2c->dev, "failed to create pcms\n"); | 
|  | 1608 | goto pcm_err; | 
|  | 1609 | } | 
|  | 1610 |  | 
|  | 1611 | /* SYSCLK is required for pretty much anything */ | 
|  | 1612 | wm8903_write(codec, WM8903_CLOCK_RATES_2, WM8903_CLK_SYS_ENA); | 
|  | 1613 |  | 
|  | 1614 | /* power on device */ | 
|  | 1615 | wm8903_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 
|  | 1616 |  | 
|  | 1617 | /* Latch volume update bits */ | 
|  | 1618 | val = wm8903_read(codec, WM8903_ADC_DIGITAL_VOLUME_LEFT); | 
|  | 1619 | val |= WM8903_ADCVU; | 
|  | 1620 | wm8903_write(codec, WM8903_ADC_DIGITAL_VOLUME_LEFT, val); | 
|  | 1621 | wm8903_write(codec, WM8903_ADC_DIGITAL_VOLUME_RIGHT, val); | 
|  | 1622 |  | 
|  | 1623 | val = wm8903_read(codec, WM8903_DAC_DIGITAL_VOLUME_LEFT); | 
|  | 1624 | val |= WM8903_DACVU; | 
|  | 1625 | wm8903_write(codec, WM8903_DAC_DIGITAL_VOLUME_LEFT, val); | 
|  | 1626 | wm8903_write(codec, WM8903_DAC_DIGITAL_VOLUME_RIGHT, val); | 
|  | 1627 |  | 
|  | 1628 | val = wm8903_read(codec, WM8903_ANALOGUE_OUT1_LEFT); | 
|  | 1629 | val |= WM8903_HPOUTVU; | 
|  | 1630 | wm8903_write(codec, WM8903_ANALOGUE_OUT1_LEFT, val); | 
|  | 1631 | wm8903_write(codec, WM8903_ANALOGUE_OUT1_RIGHT, val); | 
|  | 1632 |  | 
|  | 1633 | val = wm8903_read(codec, WM8903_ANALOGUE_OUT2_LEFT); | 
|  | 1634 | val |= WM8903_LINEOUTVU; | 
|  | 1635 | wm8903_write(codec, WM8903_ANALOGUE_OUT2_LEFT, val); | 
|  | 1636 | wm8903_write(codec, WM8903_ANALOGUE_OUT2_RIGHT, val); | 
|  | 1637 |  | 
|  | 1638 | val = wm8903_read(codec, WM8903_ANALOGUE_OUT3_LEFT); | 
|  | 1639 | val |= WM8903_SPKVU; | 
|  | 1640 | wm8903_write(codec, WM8903_ANALOGUE_OUT3_LEFT, val); | 
|  | 1641 | wm8903_write(codec, WM8903_ANALOGUE_OUT3_RIGHT, val); | 
|  | 1642 |  | 
|  | 1643 | /* Enable DAC soft mute by default */ | 
|  | 1644 | val = wm8903_read(codec, WM8903_DAC_DIGITAL_1); | 
|  | 1645 | val |= WM8903_DAC_MUTEMODE; | 
|  | 1646 | wm8903_write(codec, WM8903_DAC_DIGITAL_1, val); | 
|  | 1647 |  | 
|  | 1648 | wm8903_add_controls(codec); | 
|  | 1649 | wm8903_add_widgets(codec); | 
|  | 1650 | ret = snd_soc_register_card(socdev); | 
|  | 1651 | if (ret < 0) { | 
|  | 1652 | dev_err(&i2c->dev, "wm8903: failed to register card\n"); | 
|  | 1653 | goto card_err; | 
|  | 1654 | } | 
|  | 1655 |  | 
|  | 1656 | return ret; | 
|  | 1657 |  | 
|  | 1658 | card_err: | 
|  | 1659 | snd_soc_free_pcms(socdev); | 
|  | 1660 | snd_soc_dapm_free(socdev); | 
|  | 1661 | pcm_err: | 
|  | 1662 | kfree(codec->reg_cache); | 
|  | 1663 | return ret; | 
|  | 1664 | } | 
|  | 1665 |  | 
|  | 1666 | static struct snd_soc_device *wm8903_socdev; | 
|  | 1667 |  | 
|  | 1668 | static int wm8903_i2c_probe(struct i2c_client *i2c, | 
|  | 1669 | const struct i2c_device_id *id) | 
|  | 1670 | { | 
|  | 1671 | struct snd_soc_device *socdev = wm8903_socdev; | 
|  | 1672 | struct snd_soc_codec *codec = socdev->codec; | 
|  | 1673 | int ret; | 
|  | 1674 |  | 
|  | 1675 | i2c_set_clientdata(i2c, codec); | 
|  | 1676 | codec->control_data = i2c; | 
|  | 1677 |  | 
|  | 1678 | ret = wm8903_init(socdev); | 
|  | 1679 | if (ret < 0) | 
|  | 1680 | dev_err(&i2c->dev, "Device initialisation failed\n"); | 
|  | 1681 |  | 
|  | 1682 | return ret; | 
|  | 1683 | } | 
|  | 1684 |  | 
|  | 1685 | static int wm8903_i2c_remove(struct i2c_client *client) | 
|  | 1686 | { | 
|  | 1687 | struct snd_soc_codec *codec = i2c_get_clientdata(client); | 
|  | 1688 | kfree(codec->reg_cache); | 
|  | 1689 | return 0; | 
|  | 1690 | } | 
|  | 1691 |  | 
|  | 1692 | /* i2c codec control layer */ | 
|  | 1693 | static const struct i2c_device_id wm8903_i2c_id[] = { | 
|  | 1694 | { "wm8903", 0 }, | 
|  | 1695 | { } | 
|  | 1696 | }; | 
|  | 1697 | MODULE_DEVICE_TABLE(i2c, wm8903_i2c_id); | 
|  | 1698 |  | 
|  | 1699 | static struct i2c_driver wm8903_i2c_driver = { | 
|  | 1700 | .driver = { | 
|  | 1701 | .name = "WM8903", | 
|  | 1702 | .owner = THIS_MODULE, | 
|  | 1703 | }, | 
|  | 1704 | .probe    = wm8903_i2c_probe, | 
|  | 1705 | .remove   = wm8903_i2c_remove, | 
|  | 1706 | .id_table = wm8903_i2c_id, | 
|  | 1707 | }; | 
|  | 1708 |  | 
| Mark Brown | f1c0a02 | 2008-08-26 13:05:27 +0100 | [diff] [blame] | 1709 | static int wm8903_probe(struct platform_device *pdev) | 
|  | 1710 | { | 
|  | 1711 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 
|  | 1712 | struct wm8903_setup_data *setup; | 
|  | 1713 | struct snd_soc_codec *codec; | 
|  | 1714 | struct wm8903_priv *wm8903; | 
|  | 1715 | struct i2c_board_info board_info; | 
|  | 1716 | struct i2c_adapter *adapter; | 
| Mark Brown | acdfc9e | 2008-08-26 15:29:11 +0100 | [diff] [blame] | 1717 | struct i2c_client *i2c_client; | 
| Mark Brown | f1c0a02 | 2008-08-26 13:05:27 +0100 | [diff] [blame] | 1718 | int ret = 0; | 
|  | 1719 |  | 
|  | 1720 | setup = socdev->codec_data; | 
|  | 1721 |  | 
|  | 1722 | if (!setup->i2c_address) { | 
|  | 1723 | dev_err(&pdev->dev, "No codec address provided\n"); | 
|  | 1724 | return -ENODEV; | 
|  | 1725 | } | 
|  | 1726 |  | 
|  | 1727 | codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); | 
|  | 1728 | if (codec == NULL) | 
|  | 1729 | return -ENOMEM; | 
|  | 1730 |  | 
|  | 1731 | wm8903 = kzalloc(sizeof(struct wm8903_priv), GFP_KERNEL); | 
|  | 1732 | if (wm8903 == NULL) { | 
|  | 1733 | ret = -ENOMEM; | 
|  | 1734 | goto err_codec; | 
|  | 1735 | } | 
|  | 1736 |  | 
|  | 1737 | codec->private_data = wm8903; | 
|  | 1738 | socdev->codec = codec; | 
|  | 1739 | mutex_init(&codec->mutex); | 
|  | 1740 | INIT_LIST_HEAD(&codec->dapm_widgets); | 
|  | 1741 | INIT_LIST_HEAD(&codec->dapm_paths); | 
|  | 1742 |  | 
|  | 1743 | wm8903_socdev = socdev; | 
|  | 1744 |  | 
|  | 1745 | codec->hw_write = (hw_write_t)i2c_master_send; | 
|  | 1746 | ret = i2c_add_driver(&wm8903_i2c_driver); | 
|  | 1747 | if (ret != 0) { | 
| Mark Brown | acdfc9e | 2008-08-26 15:29:11 +0100 | [diff] [blame] | 1748 | dev_err(&pdev->dev, "can't add i2c driver\n"); | 
| Mark Brown | f1c0a02 | 2008-08-26 13:05:27 +0100 | [diff] [blame] | 1749 | goto err_priv; | 
|  | 1750 | } else { | 
|  | 1751 | memset(&board_info, 0, sizeof(board_info)); | 
|  | 1752 | strlcpy(board_info.type, "wm8903", I2C_NAME_SIZE); | 
|  | 1753 | board_info.addr = setup->i2c_address; | 
|  | 1754 |  | 
|  | 1755 | adapter = i2c_get_adapter(setup->i2c_bus); | 
|  | 1756 | if (!adapter) { | 
|  | 1757 | dev_err(&pdev->dev, "Can't get I2C bus %d\n", | 
|  | 1758 | setup->i2c_bus); | 
| Mark Brown | acdfc9e | 2008-08-26 15:29:11 +0100 | [diff] [blame] | 1759 | ret = -ENODEV; | 
| Mark Brown | f1c0a02 | 2008-08-26 13:05:27 +0100 | [diff] [blame] | 1760 | goto err_adapter; | 
|  | 1761 | } | 
|  | 1762 |  | 
| Mark Brown | acdfc9e | 2008-08-26 15:29:11 +0100 | [diff] [blame] | 1763 | i2c_client = i2c_new_device(adapter, &board_info); | 
| Mark Brown | f1c0a02 | 2008-08-26 13:05:27 +0100 | [diff] [blame] | 1764 | i2c_put_adapter(adapter); | 
| Mark Brown | acdfc9e | 2008-08-26 15:29:11 +0100 | [diff] [blame] | 1765 | if (i2c_client == NULL) { | 
| Mark Brown | f1c0a02 | 2008-08-26 13:05:27 +0100 | [diff] [blame] | 1766 | dev_err(&pdev->dev, | 
|  | 1767 | "I2C driver registration failed\n"); | 
|  | 1768 | ret = -ENODEV; | 
|  | 1769 | goto err_adapter; | 
|  | 1770 | } | 
|  | 1771 | } | 
|  | 1772 |  | 
|  | 1773 | return ret; | 
|  | 1774 |  | 
|  | 1775 | err_adapter: | 
|  | 1776 | i2c_del_driver(&wm8903_i2c_driver); | 
|  | 1777 | err_priv: | 
|  | 1778 | kfree(codec->private_data); | 
|  | 1779 | err_codec: | 
|  | 1780 | kfree(codec); | 
|  | 1781 | return ret; | 
|  | 1782 | } | 
|  | 1783 |  | 
|  | 1784 | /* power down chip */ | 
|  | 1785 | static int wm8903_remove(struct platform_device *pdev) | 
|  | 1786 | { | 
|  | 1787 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 
|  | 1788 | struct snd_soc_codec *codec = socdev->codec; | 
|  | 1789 |  | 
|  | 1790 | if (codec->control_data) | 
|  | 1791 | wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF); | 
|  | 1792 |  | 
|  | 1793 | snd_soc_free_pcms(socdev); | 
|  | 1794 | snd_soc_dapm_free(socdev); | 
| Mark Brown | acdfc9e | 2008-08-26 15:29:11 +0100 | [diff] [blame] | 1795 | i2c_unregister_device(socdev->codec->control_data); | 
| Mark Brown | f1c0a02 | 2008-08-26 13:05:27 +0100 | [diff] [blame] | 1796 | i2c_del_driver(&wm8903_i2c_driver); | 
|  | 1797 | kfree(codec->private_data); | 
|  | 1798 | kfree(codec); | 
|  | 1799 |  | 
|  | 1800 | return 0; | 
|  | 1801 | } | 
|  | 1802 |  | 
|  | 1803 | struct snd_soc_codec_device soc_codec_dev_wm8903 = { | 
|  | 1804 | .probe = 	wm8903_probe, | 
|  | 1805 | .remove = 	wm8903_remove, | 
|  | 1806 | .suspend = 	wm8903_suspend, | 
|  | 1807 | .resume =	wm8903_resume, | 
|  | 1808 | }; | 
|  | 1809 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8903); | 
|  | 1810 |  | 
|  | 1811 | MODULE_DESCRIPTION("ASoC WM8903 driver"); | 
|  | 1812 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.cm>"); | 
|  | 1813 | MODULE_LICENSE("GPL"); |