| Mark Brown | e86e124 | 2010-10-18 16:45:24 -0700 | [diff] [blame] | 1 | /* | 
 | 2 |  * max98088.c -- MAX98088 ALSA SoC Audio driver | 
 | 3 |  * | 
 | 4 |  * Copyright 2010 Maxim Integrated Products | 
 | 5 |  * | 
 | 6 |  * This program is free software; you can redistribute it and/or modify | 
 | 7 |  * it under the terms of the GNU General Public License version 2 as | 
 | 8 |  * published by the Free Software Foundation. | 
 | 9 |  */ | 
 | 10 |  | 
 | 11 | #include <linux/module.h> | 
 | 12 | #include <linux/moduleparam.h> | 
 | 13 | #include <linux/kernel.h> | 
 | 14 | #include <linux/init.h> | 
 | 15 | #include <linux/delay.h> | 
 | 16 | #include <linux/pm.h> | 
 | 17 | #include <linux/i2c.h> | 
 | 18 | #include <linux/platform_device.h> | 
 | 19 | #include <sound/core.h> | 
 | 20 | #include <sound/pcm.h> | 
 | 21 | #include <sound/pcm_params.h> | 
 | 22 | #include <sound/soc.h> | 
| Mark Brown | e86e124 | 2010-10-18 16:45:24 -0700 | [diff] [blame] | 23 | #include <sound/initval.h> | 
 | 24 | #include <sound/tlv.h> | 
 | 25 | #include <linux/slab.h> | 
 | 26 | #include <asm/div64.h> | 
 | 27 | #include <sound/max98088.h> | 
 | 28 | #include "max98088.h" | 
 | 29 |  | 
| Jesse Marroquin | fb762a5 | 2010-11-17 14:26:40 -0600 | [diff] [blame] | 30 | enum max98088_type { | 
 | 31 |        MAX98088, | 
 | 32 |        MAX98089, | 
 | 33 | }; | 
 | 34 |  | 
| Mark Brown | e86e124 | 2010-10-18 16:45:24 -0700 | [diff] [blame] | 35 | struct max98088_cdata { | 
 | 36 |        unsigned int rate; | 
 | 37 |        unsigned int fmt; | 
 | 38 |        int eq_sel; | 
 | 39 | }; | 
 | 40 |  | 
 | 41 | struct max98088_priv { | 
| Jesse Marroquin | fb762a5 | 2010-11-17 14:26:40 -0600 | [diff] [blame] | 42 |        enum max98088_type devtype; | 
| Mark Brown | e86e124 | 2010-10-18 16:45:24 -0700 | [diff] [blame] | 43 |        void *control_data; | 
 | 44 |        struct max98088_pdata *pdata; | 
 | 45 |        unsigned int sysclk; | 
 | 46 |        struct max98088_cdata dai[2]; | 
 | 47 |        int eq_textcnt; | 
 | 48 |        const char **eq_texts; | 
 | 49 |        struct soc_enum eq_enum; | 
 | 50 |        u8 ina_state; | 
 | 51 |        u8 inb_state; | 
 | 52 |        unsigned int ex_mode; | 
 | 53 |        unsigned int digmic; | 
 | 54 |        unsigned int mic1pre; | 
 | 55 |        unsigned int mic2pre; | 
 | 56 |        unsigned int extmic_mode; | 
 | 57 | }; | 
 | 58 |  | 
 | 59 | static const u8 max98088_reg[M98088_REG_CNT] = { | 
 | 60 |        0x00, /* 00 IRQ status */ | 
 | 61 |        0x00, /* 01 MIC status */ | 
 | 62 |        0x00, /* 02 jack status */ | 
 | 63 |        0x00, /* 03 battery voltage */ | 
 | 64 |        0x00, /* 04 */ | 
 | 65 |        0x00, /* 05 */ | 
 | 66 |        0x00, /* 06 */ | 
 | 67 |        0x00, /* 07 */ | 
 | 68 |        0x00, /* 08 */ | 
 | 69 |        0x00, /* 09 */ | 
 | 70 |        0x00, /* 0A */ | 
 | 71 |        0x00, /* 0B */ | 
 | 72 |        0x00, /* 0C */ | 
 | 73 |        0x00, /* 0D */ | 
 | 74 |        0x00, /* 0E */ | 
 | 75 |        0x00, /* 0F interrupt enable */ | 
 | 76 |  | 
 | 77 |        0x00, /* 10 master clock */ | 
 | 78 |        0x00, /* 11 DAI1 clock mode */ | 
 | 79 |        0x00, /* 12 DAI1 clock control */ | 
 | 80 |        0x00, /* 13 DAI1 clock control */ | 
 | 81 |        0x00, /* 14 DAI1 format */ | 
 | 82 |        0x00, /* 15 DAI1 clock */ | 
 | 83 |        0x00, /* 16 DAI1 config */ | 
 | 84 |        0x00, /* 17 DAI1 TDM */ | 
 | 85 |        0x00, /* 18 DAI1 filters */ | 
 | 86 |        0x00, /* 19 DAI2 clock mode */ | 
 | 87 |        0x00, /* 1A DAI2 clock control */ | 
 | 88 |        0x00, /* 1B DAI2 clock control */ | 
 | 89 |        0x00, /* 1C DAI2 format */ | 
 | 90 |        0x00, /* 1D DAI2 clock */ | 
 | 91 |        0x00, /* 1E DAI2 config */ | 
 | 92 |        0x00, /* 1F DAI2 TDM */ | 
 | 93 |  | 
 | 94 |        0x00, /* 20 DAI2 filters */ | 
 | 95 |        0x00, /* 21 data config */ | 
 | 96 |        0x00, /* 22 DAC mixer */ | 
 | 97 |        0x00, /* 23 left ADC mixer */ | 
 | 98 |        0x00, /* 24 right ADC mixer */ | 
 | 99 |        0x00, /* 25 left HP mixer */ | 
 | 100 |        0x00, /* 26 right HP mixer */ | 
 | 101 |        0x00, /* 27 HP control */ | 
 | 102 |        0x00, /* 28 left REC mixer */ | 
 | 103 |        0x00, /* 29 right REC mixer */ | 
 | 104 |        0x00, /* 2A REC control */ | 
 | 105 |        0x00, /* 2B left SPK mixer */ | 
 | 106 |        0x00, /* 2C right SPK mixer */ | 
 | 107 |        0x00, /* 2D SPK control */ | 
 | 108 |        0x00, /* 2E sidetone */ | 
 | 109 |        0x00, /* 2F DAI1 playback level */ | 
 | 110 |  | 
 | 111 |        0x00, /* 30 DAI1 playback level */ | 
 | 112 |        0x00, /* 31 DAI2 playback level */ | 
 | 113 |        0x00, /* 32 DAI2 playbakc level */ | 
 | 114 |        0x00, /* 33 left ADC level */ | 
 | 115 |        0x00, /* 34 right ADC level */ | 
 | 116 |        0x00, /* 35 MIC1 level */ | 
 | 117 |        0x00, /* 36 MIC2 level */ | 
 | 118 |        0x00, /* 37 INA level */ | 
 | 119 |        0x00, /* 38 INB level */ | 
 | 120 |        0x00, /* 39 left HP volume */ | 
 | 121 |        0x00, /* 3A right HP volume */ | 
 | 122 |        0x00, /* 3B left REC volume */ | 
 | 123 |        0x00, /* 3C right REC volume */ | 
 | 124 |        0x00, /* 3D left SPK volume */ | 
 | 125 |        0x00, /* 3E right SPK volume */ | 
 | 126 |        0x00, /* 3F MIC config */ | 
 | 127 |  | 
 | 128 |        0x00, /* 40 MIC threshold */ | 
 | 129 |        0x00, /* 41 excursion limiter filter */ | 
 | 130 |        0x00, /* 42 excursion limiter threshold */ | 
 | 131 |        0x00, /* 43 ALC */ | 
 | 132 |        0x00, /* 44 power limiter threshold */ | 
 | 133 |        0x00, /* 45 power limiter config */ | 
 | 134 |        0x00, /* 46 distortion limiter config */ | 
 | 135 |        0x00, /* 47 audio input */ | 
 | 136 |        0x00, /* 48 microphone */ | 
 | 137 |        0x00, /* 49 level control */ | 
 | 138 |        0x00, /* 4A bypass switches */ | 
 | 139 |        0x00, /* 4B jack detect */ | 
 | 140 |        0x00, /* 4C input enable */ | 
 | 141 |        0x00, /* 4D output enable */ | 
 | 142 |        0xF0, /* 4E bias control */ | 
 | 143 |        0x00, /* 4F DAC power */ | 
 | 144 |  | 
 | 145 |        0x0F, /* 50 DAC power */ | 
 | 146 |        0x00, /* 51 system */ | 
 | 147 |        0x00, /* 52 DAI1 EQ1 */ | 
 | 148 |        0x00, /* 53 DAI1 EQ1 */ | 
 | 149 |        0x00, /* 54 DAI1 EQ1 */ | 
 | 150 |        0x00, /* 55 DAI1 EQ1 */ | 
 | 151 |        0x00, /* 56 DAI1 EQ1 */ | 
 | 152 |        0x00, /* 57 DAI1 EQ1 */ | 
 | 153 |        0x00, /* 58 DAI1 EQ1 */ | 
 | 154 |        0x00, /* 59 DAI1 EQ1 */ | 
 | 155 |        0x00, /* 5A DAI1 EQ1 */ | 
 | 156 |        0x00, /* 5B DAI1 EQ1 */ | 
 | 157 |        0x00, /* 5C DAI1 EQ2 */ | 
 | 158 |        0x00, /* 5D DAI1 EQ2 */ | 
 | 159 |        0x00, /* 5E DAI1 EQ2 */ | 
 | 160 |        0x00, /* 5F DAI1 EQ2 */ | 
 | 161 |  | 
 | 162 |        0x00, /* 60 DAI1 EQ2 */ | 
 | 163 |        0x00, /* 61 DAI1 EQ2 */ | 
 | 164 |        0x00, /* 62 DAI1 EQ2 */ | 
 | 165 |        0x00, /* 63 DAI1 EQ2 */ | 
 | 166 |        0x00, /* 64 DAI1 EQ2 */ | 
 | 167 |        0x00, /* 65 DAI1 EQ2 */ | 
 | 168 |        0x00, /* 66 DAI1 EQ3 */ | 
 | 169 |        0x00, /* 67 DAI1 EQ3 */ | 
 | 170 |        0x00, /* 68 DAI1 EQ3 */ | 
 | 171 |        0x00, /* 69 DAI1 EQ3 */ | 
 | 172 |        0x00, /* 6A DAI1 EQ3 */ | 
 | 173 |        0x00, /* 6B DAI1 EQ3 */ | 
 | 174 |        0x00, /* 6C DAI1 EQ3 */ | 
 | 175 |        0x00, /* 6D DAI1 EQ3 */ | 
 | 176 |        0x00, /* 6E DAI1 EQ3 */ | 
 | 177 |        0x00, /* 6F DAI1 EQ3 */ | 
 | 178 |  | 
 | 179 |        0x00, /* 70 DAI1 EQ4 */ | 
 | 180 |        0x00, /* 71 DAI1 EQ4 */ | 
 | 181 |        0x00, /* 72 DAI1 EQ4 */ | 
 | 182 |        0x00, /* 73 DAI1 EQ4 */ | 
 | 183 |        0x00, /* 74 DAI1 EQ4 */ | 
 | 184 |        0x00, /* 75 DAI1 EQ4 */ | 
 | 185 |        0x00, /* 76 DAI1 EQ4 */ | 
 | 186 |        0x00, /* 77 DAI1 EQ4 */ | 
 | 187 |        0x00, /* 78 DAI1 EQ4 */ | 
 | 188 |        0x00, /* 79 DAI1 EQ4 */ | 
 | 189 |        0x00, /* 7A DAI1 EQ5 */ | 
 | 190 |        0x00, /* 7B DAI1 EQ5 */ | 
 | 191 |        0x00, /* 7C DAI1 EQ5 */ | 
 | 192 |        0x00, /* 7D DAI1 EQ5 */ | 
 | 193 |        0x00, /* 7E DAI1 EQ5 */ | 
 | 194 |        0x00, /* 7F DAI1 EQ5 */ | 
 | 195 |  | 
 | 196 |        0x00, /* 80 DAI1 EQ5 */ | 
 | 197 |        0x00, /* 81 DAI1 EQ5 */ | 
 | 198 |        0x00, /* 82 DAI1 EQ5 */ | 
 | 199 |        0x00, /* 83 DAI1 EQ5 */ | 
 | 200 |        0x00, /* 84 DAI2 EQ1 */ | 
 | 201 |        0x00, /* 85 DAI2 EQ1 */ | 
 | 202 |        0x00, /* 86 DAI2 EQ1 */ | 
 | 203 |        0x00, /* 87 DAI2 EQ1 */ | 
 | 204 |        0x00, /* 88 DAI2 EQ1 */ | 
 | 205 |        0x00, /* 89 DAI2 EQ1 */ | 
 | 206 |        0x00, /* 8A DAI2 EQ1 */ | 
 | 207 |        0x00, /* 8B DAI2 EQ1 */ | 
 | 208 |        0x00, /* 8C DAI2 EQ1 */ | 
 | 209 |        0x00, /* 8D DAI2 EQ1 */ | 
 | 210 |        0x00, /* 8E DAI2 EQ2 */ | 
 | 211 |        0x00, /* 8F DAI2 EQ2 */ | 
 | 212 |  | 
 | 213 |        0x00, /* 90 DAI2 EQ2 */ | 
 | 214 |        0x00, /* 91 DAI2 EQ2 */ | 
 | 215 |        0x00, /* 92 DAI2 EQ2 */ | 
 | 216 |        0x00, /* 93 DAI2 EQ2 */ | 
 | 217 |        0x00, /* 94 DAI2 EQ2 */ | 
 | 218 |        0x00, /* 95 DAI2 EQ2 */ | 
 | 219 |        0x00, /* 96 DAI2 EQ2 */ | 
 | 220 |        0x00, /* 97 DAI2 EQ2 */ | 
 | 221 |        0x00, /* 98 DAI2 EQ3 */ | 
 | 222 |        0x00, /* 99 DAI2 EQ3 */ | 
 | 223 |        0x00, /* 9A DAI2 EQ3 */ | 
 | 224 |        0x00, /* 9B DAI2 EQ3 */ | 
 | 225 |        0x00, /* 9C DAI2 EQ3 */ | 
 | 226 |        0x00, /* 9D DAI2 EQ3 */ | 
 | 227 |        0x00, /* 9E DAI2 EQ3 */ | 
 | 228 |        0x00, /* 9F DAI2 EQ3 */ | 
 | 229 |  | 
 | 230 |        0x00, /* A0 DAI2 EQ3 */ | 
 | 231 |        0x00, /* A1 DAI2 EQ3 */ | 
 | 232 |        0x00, /* A2 DAI2 EQ4 */ | 
 | 233 |        0x00, /* A3 DAI2 EQ4 */ | 
 | 234 |        0x00, /* A4 DAI2 EQ4 */ | 
 | 235 |        0x00, /* A5 DAI2 EQ4 */ | 
 | 236 |        0x00, /* A6 DAI2 EQ4 */ | 
 | 237 |        0x00, /* A7 DAI2 EQ4 */ | 
 | 238 |        0x00, /* A8 DAI2 EQ4 */ | 
 | 239 |        0x00, /* A9 DAI2 EQ4 */ | 
 | 240 |        0x00, /* AA DAI2 EQ4 */ | 
 | 241 |        0x00, /* AB DAI2 EQ4 */ | 
 | 242 |        0x00, /* AC DAI2 EQ5 */ | 
 | 243 |        0x00, /* AD DAI2 EQ5 */ | 
 | 244 |        0x00, /* AE DAI2 EQ5 */ | 
 | 245 |        0x00, /* AF DAI2 EQ5 */ | 
 | 246 |  | 
 | 247 |        0x00, /* B0 DAI2 EQ5 */ | 
 | 248 |        0x00, /* B1 DAI2 EQ5 */ | 
 | 249 |        0x00, /* B2 DAI2 EQ5 */ | 
 | 250 |        0x00, /* B3 DAI2 EQ5 */ | 
 | 251 |        0x00, /* B4 DAI2 EQ5 */ | 
 | 252 |        0x00, /* B5 DAI2 EQ5 */ | 
 | 253 |        0x00, /* B6 DAI1 biquad */ | 
 | 254 |        0x00, /* B7 DAI1 biquad */ | 
 | 255 |        0x00, /* B8 DAI1 biquad */ | 
 | 256 |        0x00, /* B9 DAI1 biquad */ | 
 | 257 |        0x00, /* BA DAI1 biquad */ | 
 | 258 |        0x00, /* BB DAI1 biquad */ | 
 | 259 |        0x00, /* BC DAI1 biquad */ | 
 | 260 |        0x00, /* BD DAI1 biquad */ | 
 | 261 |        0x00, /* BE DAI1 biquad */ | 
 | 262 |        0x00, /* BF DAI1 biquad */ | 
 | 263 |  | 
 | 264 |        0x00, /* C0 DAI2 biquad */ | 
 | 265 |        0x00, /* C1 DAI2 biquad */ | 
 | 266 |        0x00, /* C2 DAI2 biquad */ | 
 | 267 |        0x00, /* C3 DAI2 biquad */ | 
 | 268 |        0x00, /* C4 DAI2 biquad */ | 
 | 269 |        0x00, /* C5 DAI2 biquad */ | 
 | 270 |        0x00, /* C6 DAI2 biquad */ | 
 | 271 |        0x00, /* C7 DAI2 biquad */ | 
 | 272 |        0x00, /* C8 DAI2 biquad */ | 
 | 273 |        0x00, /* C9 DAI2 biquad */ | 
 | 274 |        0x00, /* CA */ | 
 | 275 |        0x00, /* CB */ | 
 | 276 |        0x00, /* CC */ | 
 | 277 |        0x00, /* CD */ | 
 | 278 |        0x00, /* CE */ | 
 | 279 |        0x00, /* CF */ | 
 | 280 |  | 
 | 281 |        0x00, /* D0 */ | 
 | 282 |        0x00, /* D1 */ | 
 | 283 |        0x00, /* D2 */ | 
 | 284 |        0x00, /* D3 */ | 
 | 285 |        0x00, /* D4 */ | 
 | 286 |        0x00, /* D5 */ | 
 | 287 |        0x00, /* D6 */ | 
 | 288 |        0x00, /* D7 */ | 
 | 289 |        0x00, /* D8 */ | 
 | 290 |        0x00, /* D9 */ | 
 | 291 |        0x00, /* DA */ | 
 | 292 |        0x70, /* DB */ | 
 | 293 |        0x00, /* DC */ | 
 | 294 |        0x00, /* DD */ | 
 | 295 |        0x00, /* DE */ | 
 | 296 |        0x00, /* DF */ | 
 | 297 |  | 
 | 298 |        0x00, /* E0 */ | 
 | 299 |        0x00, /* E1 */ | 
 | 300 |        0x00, /* E2 */ | 
 | 301 |        0x00, /* E3 */ | 
 | 302 |        0x00, /* E4 */ | 
 | 303 |        0x00, /* E5 */ | 
 | 304 |        0x00, /* E6 */ | 
 | 305 |        0x00, /* E7 */ | 
 | 306 |        0x00, /* E8 */ | 
 | 307 |        0x00, /* E9 */ | 
 | 308 |        0x00, /* EA */ | 
 | 309 |        0x00, /* EB */ | 
 | 310 |        0x00, /* EC */ | 
 | 311 |        0x00, /* ED */ | 
 | 312 |        0x00, /* EE */ | 
 | 313 |        0x00, /* EF */ | 
 | 314 |  | 
 | 315 |        0x00, /* F0 */ | 
 | 316 |        0x00, /* F1 */ | 
 | 317 |        0x00, /* F2 */ | 
 | 318 |        0x00, /* F3 */ | 
 | 319 |        0x00, /* F4 */ | 
 | 320 |        0x00, /* F5 */ | 
 | 321 |        0x00, /* F6 */ | 
 | 322 |        0x00, /* F7 */ | 
 | 323 |        0x00, /* F8 */ | 
 | 324 |        0x00, /* F9 */ | 
 | 325 |        0x00, /* FA */ | 
 | 326 |        0x00, /* FB */ | 
 | 327 |        0x00, /* FC */ | 
 | 328 |        0x00, /* FD */ | 
 | 329 |        0x00, /* FE */ | 
 | 330 |        0x00, /* FF */ | 
 | 331 | }; | 
 | 332 |  | 
 | 333 | static struct { | 
 | 334 |        int readable; | 
 | 335 |        int writable; | 
 | 336 |        int vol; | 
 | 337 | } max98088_access[M98088_REG_CNT] = { | 
 | 338 |        { 0xFF, 0xFF, 1 }, /* 00 IRQ status */ | 
 | 339 |        { 0xFF, 0x00, 1 }, /* 01 MIC status */ | 
 | 340 |        { 0xFF, 0x00, 1 }, /* 02 jack status */ | 
 | 341 |        { 0x1F, 0x1F, 1 }, /* 03 battery voltage */ | 
 | 342 |        { 0xFF, 0xFF, 0 }, /* 04 */ | 
 | 343 |        { 0xFF, 0xFF, 0 }, /* 05 */ | 
 | 344 |        { 0xFF, 0xFF, 0 }, /* 06 */ | 
 | 345 |        { 0xFF, 0xFF, 0 }, /* 07 */ | 
 | 346 |        { 0xFF, 0xFF, 0 }, /* 08 */ | 
 | 347 |        { 0xFF, 0xFF, 0 }, /* 09 */ | 
 | 348 |        { 0xFF, 0xFF, 0 }, /* 0A */ | 
 | 349 |        { 0xFF, 0xFF, 0 }, /* 0B */ | 
 | 350 |        { 0xFF, 0xFF, 0 }, /* 0C */ | 
 | 351 |        { 0xFF, 0xFF, 0 }, /* 0D */ | 
 | 352 |        { 0xFF, 0xFF, 0 }, /* 0E */ | 
 | 353 |        { 0xFF, 0xFF, 0 }, /* 0F interrupt enable */ | 
 | 354 |  | 
 | 355 |        { 0xFF, 0xFF, 0 }, /* 10 master clock */ | 
 | 356 |        { 0xFF, 0xFF, 0 }, /* 11 DAI1 clock mode */ | 
 | 357 |        { 0xFF, 0xFF, 0 }, /* 12 DAI1 clock control */ | 
 | 358 |        { 0xFF, 0xFF, 0 }, /* 13 DAI1 clock control */ | 
 | 359 |        { 0xFF, 0xFF, 0 }, /* 14 DAI1 format */ | 
 | 360 |        { 0xFF, 0xFF, 0 }, /* 15 DAI1 clock */ | 
 | 361 |        { 0xFF, 0xFF, 0 }, /* 16 DAI1 config */ | 
 | 362 |        { 0xFF, 0xFF, 0 }, /* 17 DAI1 TDM */ | 
 | 363 |        { 0xFF, 0xFF, 0 }, /* 18 DAI1 filters */ | 
 | 364 |        { 0xFF, 0xFF, 0 }, /* 19 DAI2 clock mode */ | 
 | 365 |        { 0xFF, 0xFF, 0 }, /* 1A DAI2 clock control */ | 
 | 366 |        { 0xFF, 0xFF, 0 }, /* 1B DAI2 clock control */ | 
 | 367 |        { 0xFF, 0xFF, 0 }, /* 1C DAI2 format */ | 
 | 368 |        { 0xFF, 0xFF, 0 }, /* 1D DAI2 clock */ | 
 | 369 |        { 0xFF, 0xFF, 0 }, /* 1E DAI2 config */ | 
 | 370 |        { 0xFF, 0xFF, 0 }, /* 1F DAI2 TDM */ | 
 | 371 |  | 
 | 372 |        { 0xFF, 0xFF, 0 }, /* 20 DAI2 filters */ | 
 | 373 |        { 0xFF, 0xFF, 0 }, /* 21 data config */ | 
 | 374 |        { 0xFF, 0xFF, 0 }, /* 22 DAC mixer */ | 
 | 375 |        { 0xFF, 0xFF, 0 }, /* 23 left ADC mixer */ | 
 | 376 |        { 0xFF, 0xFF, 0 }, /* 24 right ADC mixer */ | 
 | 377 |        { 0xFF, 0xFF, 0 }, /* 25 left HP mixer */ | 
 | 378 |        { 0xFF, 0xFF, 0 }, /* 26 right HP mixer */ | 
 | 379 |        { 0xFF, 0xFF, 0 }, /* 27 HP control */ | 
 | 380 |        { 0xFF, 0xFF, 0 }, /* 28 left REC mixer */ | 
 | 381 |        { 0xFF, 0xFF, 0 }, /* 29 right REC mixer */ | 
 | 382 |        { 0xFF, 0xFF, 0 }, /* 2A REC control */ | 
 | 383 |        { 0xFF, 0xFF, 0 }, /* 2B left SPK mixer */ | 
 | 384 |        { 0xFF, 0xFF, 0 }, /* 2C right SPK mixer */ | 
 | 385 |        { 0xFF, 0xFF, 0 }, /* 2D SPK control */ | 
 | 386 |        { 0xFF, 0xFF, 0 }, /* 2E sidetone */ | 
 | 387 |        { 0xFF, 0xFF, 0 }, /* 2F DAI1 playback level */ | 
 | 388 |  | 
 | 389 |        { 0xFF, 0xFF, 0 }, /* 30 DAI1 playback level */ | 
 | 390 |        { 0xFF, 0xFF, 0 }, /* 31 DAI2 playback level */ | 
 | 391 |        { 0xFF, 0xFF, 0 }, /* 32 DAI2 playbakc level */ | 
 | 392 |        { 0xFF, 0xFF, 0 }, /* 33 left ADC level */ | 
 | 393 |        { 0xFF, 0xFF, 0 }, /* 34 right ADC level */ | 
 | 394 |        { 0xFF, 0xFF, 0 }, /* 35 MIC1 level */ | 
 | 395 |        { 0xFF, 0xFF, 0 }, /* 36 MIC2 level */ | 
 | 396 |        { 0xFF, 0xFF, 0 }, /* 37 INA level */ | 
 | 397 |        { 0xFF, 0xFF, 0 }, /* 38 INB level */ | 
 | 398 |        { 0xFF, 0xFF, 0 }, /* 39 left HP volume */ | 
 | 399 |        { 0xFF, 0xFF, 0 }, /* 3A right HP volume */ | 
 | 400 |        { 0xFF, 0xFF, 0 }, /* 3B left REC volume */ | 
 | 401 |        { 0xFF, 0xFF, 0 }, /* 3C right REC volume */ | 
 | 402 |        { 0xFF, 0xFF, 0 }, /* 3D left SPK volume */ | 
 | 403 |        { 0xFF, 0xFF, 0 }, /* 3E right SPK volume */ | 
 | 404 |        { 0xFF, 0xFF, 0 }, /* 3F MIC config */ | 
 | 405 |  | 
 | 406 |        { 0xFF, 0xFF, 0 }, /* 40 MIC threshold */ | 
 | 407 |        { 0xFF, 0xFF, 0 }, /* 41 excursion limiter filter */ | 
 | 408 |        { 0xFF, 0xFF, 0 }, /* 42 excursion limiter threshold */ | 
 | 409 |        { 0xFF, 0xFF, 0 }, /* 43 ALC */ | 
 | 410 |        { 0xFF, 0xFF, 0 }, /* 44 power limiter threshold */ | 
 | 411 |        { 0xFF, 0xFF, 0 }, /* 45 power limiter config */ | 
 | 412 |        { 0xFF, 0xFF, 0 }, /* 46 distortion limiter config */ | 
 | 413 |        { 0xFF, 0xFF, 0 }, /* 47 audio input */ | 
 | 414 |        { 0xFF, 0xFF, 0 }, /* 48 microphone */ | 
 | 415 |        { 0xFF, 0xFF, 0 }, /* 49 level control */ | 
 | 416 |        { 0xFF, 0xFF, 0 }, /* 4A bypass switches */ | 
 | 417 |        { 0xFF, 0xFF, 0 }, /* 4B jack detect */ | 
 | 418 |        { 0xFF, 0xFF, 0 }, /* 4C input enable */ | 
 | 419 |        { 0xFF, 0xFF, 0 }, /* 4D output enable */ | 
 | 420 |        { 0xFF, 0xFF, 0 }, /* 4E bias control */ | 
 | 421 |        { 0xFF, 0xFF, 0 }, /* 4F DAC power */ | 
 | 422 |  | 
 | 423 |        { 0xFF, 0xFF, 0 }, /* 50 DAC power */ | 
 | 424 |        { 0xFF, 0xFF, 0 }, /* 51 system */ | 
 | 425 |        { 0xFF, 0xFF, 0 }, /* 52 DAI1 EQ1 */ | 
 | 426 |        { 0xFF, 0xFF, 0 }, /* 53 DAI1 EQ1 */ | 
 | 427 |        { 0xFF, 0xFF, 0 }, /* 54 DAI1 EQ1 */ | 
 | 428 |        { 0xFF, 0xFF, 0 }, /* 55 DAI1 EQ1 */ | 
 | 429 |        { 0xFF, 0xFF, 0 }, /* 56 DAI1 EQ1 */ | 
 | 430 |        { 0xFF, 0xFF, 0 }, /* 57 DAI1 EQ1 */ | 
 | 431 |        { 0xFF, 0xFF, 0 }, /* 58 DAI1 EQ1 */ | 
 | 432 |        { 0xFF, 0xFF, 0 }, /* 59 DAI1 EQ1 */ | 
 | 433 |        { 0xFF, 0xFF, 0 }, /* 5A DAI1 EQ1 */ | 
 | 434 |        { 0xFF, 0xFF, 0 }, /* 5B DAI1 EQ1 */ | 
 | 435 |        { 0xFF, 0xFF, 0 }, /* 5C DAI1 EQ2 */ | 
 | 436 |        { 0xFF, 0xFF, 0 }, /* 5D DAI1 EQ2 */ | 
 | 437 |        { 0xFF, 0xFF, 0 }, /* 5E DAI1 EQ2 */ | 
 | 438 |        { 0xFF, 0xFF, 0 }, /* 5F DAI1 EQ2 */ | 
 | 439 |  | 
 | 440 |        { 0xFF, 0xFF, 0 }, /* 60 DAI1 EQ2 */ | 
 | 441 |        { 0xFF, 0xFF, 0 }, /* 61 DAI1 EQ2 */ | 
 | 442 |        { 0xFF, 0xFF, 0 }, /* 62 DAI1 EQ2 */ | 
 | 443 |        { 0xFF, 0xFF, 0 }, /* 63 DAI1 EQ2 */ | 
 | 444 |        { 0xFF, 0xFF, 0 }, /* 64 DAI1 EQ2 */ | 
 | 445 |        { 0xFF, 0xFF, 0 }, /* 65 DAI1 EQ2 */ | 
 | 446 |        { 0xFF, 0xFF, 0 }, /* 66 DAI1 EQ3 */ | 
 | 447 |        { 0xFF, 0xFF, 0 }, /* 67 DAI1 EQ3 */ | 
 | 448 |        { 0xFF, 0xFF, 0 }, /* 68 DAI1 EQ3 */ | 
 | 449 |        { 0xFF, 0xFF, 0 }, /* 69 DAI1 EQ3 */ | 
 | 450 |        { 0xFF, 0xFF, 0 }, /* 6A DAI1 EQ3 */ | 
 | 451 |        { 0xFF, 0xFF, 0 }, /* 6B DAI1 EQ3 */ | 
 | 452 |        { 0xFF, 0xFF, 0 }, /* 6C DAI1 EQ3 */ | 
 | 453 |        { 0xFF, 0xFF, 0 }, /* 6D DAI1 EQ3 */ | 
 | 454 |        { 0xFF, 0xFF, 0 }, /* 6E DAI1 EQ3 */ | 
 | 455 |        { 0xFF, 0xFF, 0 }, /* 6F DAI1 EQ3 */ | 
 | 456 |  | 
 | 457 |        { 0xFF, 0xFF, 0 }, /* 70 DAI1 EQ4 */ | 
 | 458 |        { 0xFF, 0xFF, 0 }, /* 71 DAI1 EQ4 */ | 
 | 459 |        { 0xFF, 0xFF, 0 }, /* 72 DAI1 EQ4 */ | 
 | 460 |        { 0xFF, 0xFF, 0 }, /* 73 DAI1 EQ4 */ | 
 | 461 |        { 0xFF, 0xFF, 0 }, /* 74 DAI1 EQ4 */ | 
 | 462 |        { 0xFF, 0xFF, 0 }, /* 75 DAI1 EQ4 */ | 
 | 463 |        { 0xFF, 0xFF, 0 }, /* 76 DAI1 EQ4 */ | 
 | 464 |        { 0xFF, 0xFF, 0 }, /* 77 DAI1 EQ4 */ | 
 | 465 |        { 0xFF, 0xFF, 0 }, /* 78 DAI1 EQ4 */ | 
 | 466 |        { 0xFF, 0xFF, 0 }, /* 79 DAI1 EQ4 */ | 
 | 467 |        { 0xFF, 0xFF, 0 }, /* 7A DAI1 EQ5 */ | 
 | 468 |        { 0xFF, 0xFF, 0 }, /* 7B DAI1 EQ5 */ | 
 | 469 |        { 0xFF, 0xFF, 0 }, /* 7C DAI1 EQ5 */ | 
 | 470 |        { 0xFF, 0xFF, 0 }, /* 7D DAI1 EQ5 */ | 
 | 471 |        { 0xFF, 0xFF, 0 }, /* 7E DAI1 EQ5 */ | 
 | 472 |        { 0xFF, 0xFF, 0 }, /* 7F DAI1 EQ5 */ | 
 | 473 |  | 
 | 474 |        { 0xFF, 0xFF, 0 }, /* 80 DAI1 EQ5 */ | 
 | 475 |        { 0xFF, 0xFF, 0 }, /* 81 DAI1 EQ5 */ | 
 | 476 |        { 0xFF, 0xFF, 0 }, /* 82 DAI1 EQ5 */ | 
 | 477 |        { 0xFF, 0xFF, 0 }, /* 83 DAI1 EQ5 */ | 
 | 478 |        { 0xFF, 0xFF, 0 }, /* 84 DAI2 EQ1 */ | 
 | 479 |        { 0xFF, 0xFF, 0 }, /* 85 DAI2 EQ1 */ | 
 | 480 |        { 0xFF, 0xFF, 0 }, /* 86 DAI2 EQ1 */ | 
 | 481 |        { 0xFF, 0xFF, 0 }, /* 87 DAI2 EQ1 */ | 
 | 482 |        { 0xFF, 0xFF, 0 }, /* 88 DAI2 EQ1 */ | 
 | 483 |        { 0xFF, 0xFF, 0 }, /* 89 DAI2 EQ1 */ | 
 | 484 |        { 0xFF, 0xFF, 0 }, /* 8A DAI2 EQ1 */ | 
 | 485 |        { 0xFF, 0xFF, 0 }, /* 8B DAI2 EQ1 */ | 
 | 486 |        { 0xFF, 0xFF, 0 }, /* 8C DAI2 EQ1 */ | 
 | 487 |        { 0xFF, 0xFF, 0 }, /* 8D DAI2 EQ1 */ | 
 | 488 |        { 0xFF, 0xFF, 0 }, /* 8E DAI2 EQ2 */ | 
 | 489 |        { 0xFF, 0xFF, 0 }, /* 8F DAI2 EQ2 */ | 
 | 490 |  | 
 | 491 |        { 0xFF, 0xFF, 0 }, /* 90 DAI2 EQ2 */ | 
 | 492 |        { 0xFF, 0xFF, 0 }, /* 91 DAI2 EQ2 */ | 
 | 493 |        { 0xFF, 0xFF, 0 }, /* 92 DAI2 EQ2 */ | 
 | 494 |        { 0xFF, 0xFF, 0 }, /* 93 DAI2 EQ2 */ | 
 | 495 |        { 0xFF, 0xFF, 0 }, /* 94 DAI2 EQ2 */ | 
 | 496 |        { 0xFF, 0xFF, 0 }, /* 95 DAI2 EQ2 */ | 
 | 497 |        { 0xFF, 0xFF, 0 }, /* 96 DAI2 EQ2 */ | 
 | 498 |        { 0xFF, 0xFF, 0 }, /* 97 DAI2 EQ2 */ | 
 | 499 |        { 0xFF, 0xFF, 0 }, /* 98 DAI2 EQ3 */ | 
 | 500 |        { 0xFF, 0xFF, 0 }, /* 99 DAI2 EQ3 */ | 
 | 501 |        { 0xFF, 0xFF, 0 }, /* 9A DAI2 EQ3 */ | 
 | 502 |        { 0xFF, 0xFF, 0 }, /* 9B DAI2 EQ3 */ | 
 | 503 |        { 0xFF, 0xFF, 0 }, /* 9C DAI2 EQ3 */ | 
 | 504 |        { 0xFF, 0xFF, 0 }, /* 9D DAI2 EQ3 */ | 
 | 505 |        { 0xFF, 0xFF, 0 }, /* 9E DAI2 EQ3 */ | 
 | 506 |        { 0xFF, 0xFF, 0 }, /* 9F DAI2 EQ3 */ | 
 | 507 |  | 
 | 508 |        { 0xFF, 0xFF, 0 }, /* A0 DAI2 EQ3 */ | 
 | 509 |        { 0xFF, 0xFF, 0 }, /* A1 DAI2 EQ3 */ | 
 | 510 |        { 0xFF, 0xFF, 0 }, /* A2 DAI2 EQ4 */ | 
 | 511 |        { 0xFF, 0xFF, 0 }, /* A3 DAI2 EQ4 */ | 
 | 512 |        { 0xFF, 0xFF, 0 }, /* A4 DAI2 EQ4 */ | 
 | 513 |        { 0xFF, 0xFF, 0 }, /* A5 DAI2 EQ4 */ | 
 | 514 |        { 0xFF, 0xFF, 0 }, /* A6 DAI2 EQ4 */ | 
 | 515 |        { 0xFF, 0xFF, 0 }, /* A7 DAI2 EQ4 */ | 
 | 516 |        { 0xFF, 0xFF, 0 }, /* A8 DAI2 EQ4 */ | 
 | 517 |        { 0xFF, 0xFF, 0 }, /* A9 DAI2 EQ4 */ | 
 | 518 |        { 0xFF, 0xFF, 0 }, /* AA DAI2 EQ4 */ | 
 | 519 |        { 0xFF, 0xFF, 0 }, /* AB DAI2 EQ4 */ | 
 | 520 |        { 0xFF, 0xFF, 0 }, /* AC DAI2 EQ5 */ | 
 | 521 |        { 0xFF, 0xFF, 0 }, /* AD DAI2 EQ5 */ | 
 | 522 |        { 0xFF, 0xFF, 0 }, /* AE DAI2 EQ5 */ | 
 | 523 |        { 0xFF, 0xFF, 0 }, /* AF DAI2 EQ5 */ | 
 | 524 |  | 
 | 525 |        { 0xFF, 0xFF, 0 }, /* B0 DAI2 EQ5 */ | 
 | 526 |        { 0xFF, 0xFF, 0 }, /* B1 DAI2 EQ5 */ | 
 | 527 |        { 0xFF, 0xFF, 0 }, /* B2 DAI2 EQ5 */ | 
 | 528 |        { 0xFF, 0xFF, 0 }, /* B3 DAI2 EQ5 */ | 
 | 529 |        { 0xFF, 0xFF, 0 }, /* B4 DAI2 EQ5 */ | 
 | 530 |        { 0xFF, 0xFF, 0 }, /* B5 DAI2 EQ5 */ | 
 | 531 |        { 0xFF, 0xFF, 0 }, /* B6 DAI1 biquad */ | 
 | 532 |        { 0xFF, 0xFF, 0 }, /* B7 DAI1 biquad */ | 
 | 533 |        { 0xFF, 0xFF, 0 }, /* B8 DAI1 biquad */ | 
 | 534 |        { 0xFF, 0xFF, 0 }, /* B9 DAI1 biquad */ | 
 | 535 |        { 0xFF, 0xFF, 0 }, /* BA DAI1 biquad */ | 
 | 536 |        { 0xFF, 0xFF, 0 }, /* BB DAI1 biquad */ | 
 | 537 |        { 0xFF, 0xFF, 0 }, /* BC DAI1 biquad */ | 
 | 538 |        { 0xFF, 0xFF, 0 }, /* BD DAI1 biquad */ | 
 | 539 |        { 0xFF, 0xFF, 0 }, /* BE DAI1 biquad */ | 
 | 540 |        { 0xFF, 0xFF, 0 }, /* BF DAI1 biquad */ | 
 | 541 |  | 
 | 542 |        { 0xFF, 0xFF, 0 }, /* C0 DAI2 biquad */ | 
 | 543 |        { 0xFF, 0xFF, 0 }, /* C1 DAI2 biquad */ | 
 | 544 |        { 0xFF, 0xFF, 0 }, /* C2 DAI2 biquad */ | 
 | 545 |        { 0xFF, 0xFF, 0 }, /* C3 DAI2 biquad */ | 
 | 546 |        { 0xFF, 0xFF, 0 }, /* C4 DAI2 biquad */ | 
 | 547 |        { 0xFF, 0xFF, 0 }, /* C5 DAI2 biquad */ | 
 | 548 |        { 0xFF, 0xFF, 0 }, /* C6 DAI2 biquad */ | 
 | 549 |        { 0xFF, 0xFF, 0 }, /* C7 DAI2 biquad */ | 
 | 550 |        { 0xFF, 0xFF, 0 }, /* C8 DAI2 biquad */ | 
 | 551 |        { 0xFF, 0xFF, 0 }, /* C9 DAI2 biquad */ | 
 | 552 |        { 0x00, 0x00, 0 }, /* CA */ | 
 | 553 |        { 0x00, 0x00, 0 }, /* CB */ | 
 | 554 |        { 0x00, 0x00, 0 }, /* CC */ | 
 | 555 |        { 0x00, 0x00, 0 }, /* CD */ | 
 | 556 |        { 0x00, 0x00, 0 }, /* CE */ | 
 | 557 |        { 0x00, 0x00, 0 }, /* CF */ | 
 | 558 |  | 
 | 559 |        { 0x00, 0x00, 0 }, /* D0 */ | 
 | 560 |        { 0x00, 0x00, 0 }, /* D1 */ | 
 | 561 |        { 0x00, 0x00, 0 }, /* D2 */ | 
 | 562 |        { 0x00, 0x00, 0 }, /* D3 */ | 
 | 563 |        { 0x00, 0x00, 0 }, /* D4 */ | 
 | 564 |        { 0x00, 0x00, 0 }, /* D5 */ | 
 | 565 |        { 0x00, 0x00, 0 }, /* D6 */ | 
 | 566 |        { 0x00, 0x00, 0 }, /* D7 */ | 
 | 567 |        { 0x00, 0x00, 0 }, /* D8 */ | 
 | 568 |        { 0x00, 0x00, 0 }, /* D9 */ | 
 | 569 |        { 0x00, 0x00, 0 }, /* DA */ | 
 | 570 |        { 0x00, 0x00, 0 }, /* DB */ | 
 | 571 |        { 0x00, 0x00, 0 }, /* DC */ | 
 | 572 |        { 0x00, 0x00, 0 }, /* DD */ | 
 | 573 |        { 0x00, 0x00, 0 }, /* DE */ | 
 | 574 |        { 0x00, 0x00, 0 }, /* DF */ | 
 | 575 |  | 
 | 576 |        { 0x00, 0x00, 0 }, /* E0 */ | 
 | 577 |        { 0x00, 0x00, 0 }, /* E1 */ | 
 | 578 |        { 0x00, 0x00, 0 }, /* E2 */ | 
 | 579 |        { 0x00, 0x00, 0 }, /* E3 */ | 
 | 580 |        { 0x00, 0x00, 0 }, /* E4 */ | 
 | 581 |        { 0x00, 0x00, 0 }, /* E5 */ | 
 | 582 |        { 0x00, 0x00, 0 }, /* E6 */ | 
 | 583 |        { 0x00, 0x00, 0 }, /* E7 */ | 
 | 584 |        { 0x00, 0x00, 0 }, /* E8 */ | 
 | 585 |        { 0x00, 0x00, 0 }, /* E9 */ | 
 | 586 |        { 0x00, 0x00, 0 }, /* EA */ | 
 | 587 |        { 0x00, 0x00, 0 }, /* EB */ | 
 | 588 |        { 0x00, 0x00, 0 }, /* EC */ | 
 | 589 |        { 0x00, 0x00, 0 }, /* ED */ | 
 | 590 |        { 0x00, 0x00, 0 }, /* EE */ | 
 | 591 |        { 0x00, 0x00, 0 }, /* EF */ | 
 | 592 |  | 
 | 593 |        { 0x00, 0x00, 0 }, /* F0 */ | 
 | 594 |        { 0x00, 0x00, 0 }, /* F1 */ | 
 | 595 |        { 0x00, 0x00, 0 }, /* F2 */ | 
 | 596 |        { 0x00, 0x00, 0 }, /* F3 */ | 
 | 597 |        { 0x00, 0x00, 0 }, /* F4 */ | 
 | 598 |        { 0x00, 0x00, 0 }, /* F5 */ | 
 | 599 |        { 0x00, 0x00, 0 }, /* F6 */ | 
 | 600 |        { 0x00, 0x00, 0 }, /* F7 */ | 
 | 601 |        { 0x00, 0x00, 0 }, /* F8 */ | 
 | 602 |        { 0x00, 0x00, 0 }, /* F9 */ | 
 | 603 |        { 0x00, 0x00, 0 }, /* FA */ | 
 | 604 |        { 0x00, 0x00, 0 }, /* FB */ | 
 | 605 |        { 0x00, 0x00, 0 }, /* FC */ | 
 | 606 |        { 0x00, 0x00, 0 }, /* FD */ | 
 | 607 |        { 0x00, 0x00, 0 }, /* FE */ | 
 | 608 |        { 0xFF, 0x00, 1 }, /* FF */ | 
 | 609 | }; | 
 | 610 |  | 
| Dimitris Papastamos | d4754ec | 2011-01-13 12:20:37 +0000 | [diff] [blame] | 611 | static int max98088_volatile_register(struct snd_soc_codec *codec, unsigned int reg) | 
| Mark Brown | e86e124 | 2010-10-18 16:45:24 -0700 | [diff] [blame] | 612 | { | 
 | 613 |        return max98088_access[reg].vol; | 
 | 614 | } | 
 | 615 |  | 
 | 616 |  | 
 | 617 | /* | 
 | 618 |  * Load equalizer DSP coefficient configurations registers | 
 | 619 |  */ | 
| Dimitris Papastamos | 4428bc0 | 2010-10-21 12:15:56 +0100 | [diff] [blame] | 620 | static void m98088_eq_band(struct snd_soc_codec *codec, unsigned int dai, | 
| Mark Brown | e86e124 | 2010-10-18 16:45:24 -0700 | [diff] [blame] | 621 |                    unsigned int band, u16 *coefs) | 
 | 622 | { | 
 | 623 |        unsigned int eq_reg; | 
 | 624 |        unsigned int i; | 
 | 625 |  | 
 | 626 |        BUG_ON(band > 4); | 
 | 627 |        BUG_ON(dai > 1); | 
 | 628 |  | 
 | 629 |        /* Load the base register address */ | 
 | 630 |        eq_reg = dai ? M98088_REG_84_DAI2_EQ_BASE : M98088_REG_52_DAI1_EQ_BASE; | 
 | 631 |  | 
 | 632 |        /* Add the band address offset, note adjustment for word address */ | 
 | 633 |        eq_reg += band * (M98088_COEFS_PER_BAND << 1); | 
 | 634 |  | 
 | 635 |        /* Step through the registers and coefs */ | 
 | 636 |        for (i = 0; i < M98088_COEFS_PER_BAND; i++) { | 
 | 637 |                snd_soc_write(codec, eq_reg++, M98088_BYTE1(coefs[i])); | 
 | 638 |                snd_soc_write(codec, eq_reg++, M98088_BYTE0(coefs[i])); | 
 | 639 |        } | 
 | 640 | } | 
 | 641 |  | 
 | 642 | /* | 
 | 643 |  * Excursion limiter modes | 
 | 644 |  */ | 
 | 645 | static const char *max98088_exmode_texts[] = { | 
 | 646 |        "Off", "100Hz", "400Hz", "600Hz", "800Hz", "1000Hz", "200-400Hz", | 
 | 647 |        "400-600Hz", "400-800Hz", | 
 | 648 | }; | 
 | 649 |  | 
 | 650 | static const unsigned int max98088_exmode_values[] = { | 
 | 651 |        0x00, 0x43, 0x10, 0x20, 0x30, 0x40, 0x11, 0x22, 0x32 | 
 | 652 | }; | 
 | 653 |  | 
 | 654 | static const struct soc_enum max98088_exmode_enum = | 
 | 655 |        SOC_VALUE_ENUM_SINGLE(M98088_REG_41_SPKDHP, 0, 127, | 
 | 656 |                              ARRAY_SIZE(max98088_exmode_texts), | 
 | 657 |                              max98088_exmode_texts, | 
 | 658 |                              max98088_exmode_values); | 
| Mark Brown | e86e124 | 2010-10-18 16:45:24 -0700 | [diff] [blame] | 659 |  | 
 | 660 | static const char *max98088_ex_thresh[] = { /* volts PP */ | 
 | 661 |        "0.6", "1.2", "1.8", "2.4", "3.0", "3.6", "4.2", "4.8"}; | 
 | 662 | static const struct soc_enum max98088_ex_thresh_enum[] = { | 
 | 663 |        SOC_ENUM_SINGLE(M98088_REG_42_SPKDHP_THRESH, 0, 8, | 
 | 664 |                max98088_ex_thresh), | 
 | 665 | }; | 
 | 666 |  | 
 | 667 | static const char *max98088_fltr_mode[] = {"Voice", "Music" }; | 
 | 668 | static const struct soc_enum max98088_filter_mode_enum[] = { | 
 | 669 |        SOC_ENUM_SINGLE(M98088_REG_18_DAI1_FILTERS, 7, 2, max98088_fltr_mode), | 
 | 670 | }; | 
 | 671 |  | 
 | 672 | static const char *max98088_extmic_text[] = { "None", "MIC1", "MIC2" }; | 
 | 673 |  | 
 | 674 | static const struct soc_enum max98088_extmic_enum = | 
 | 675 |        SOC_ENUM_SINGLE(M98088_REG_48_CFG_MIC, 0, 3, max98088_extmic_text); | 
 | 676 |  | 
 | 677 | static const struct snd_kcontrol_new max98088_extmic_mux = | 
 | 678 |        SOC_DAPM_ENUM("External MIC Mux", max98088_extmic_enum); | 
 | 679 |  | 
 | 680 | static const char *max98088_dai1_fltr[] = { | 
 | 681 |        "Off", "fc=258/fs=16k", "fc=500/fs=16k", | 
 | 682 |        "fc=258/fs=8k", "fc=500/fs=8k", "fc=200"}; | 
 | 683 | static const struct soc_enum max98088_dai1_dac_filter_enum[] = { | 
 | 684 |        SOC_ENUM_SINGLE(M98088_REG_18_DAI1_FILTERS, 0, 6, max98088_dai1_fltr), | 
 | 685 | }; | 
 | 686 | static const struct soc_enum max98088_dai1_adc_filter_enum[] = { | 
 | 687 |        SOC_ENUM_SINGLE(M98088_REG_18_DAI1_FILTERS, 4, 6, max98088_dai1_fltr), | 
 | 688 | }; | 
 | 689 |  | 
 | 690 | static int max98088_mic1pre_set(struct snd_kcontrol *kcontrol, | 
 | 691 |                                struct snd_ctl_elem_value *ucontrol) | 
 | 692 | { | 
 | 693 |        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | 
 | 694 |        struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); | 
 | 695 |        unsigned int sel = ucontrol->value.integer.value[0]; | 
 | 696 |  | 
 | 697 |        max98088->mic1pre = sel; | 
 | 698 |        snd_soc_update_bits(codec, M98088_REG_35_LVL_MIC1, M98088_MICPRE_MASK, | 
 | 699 |                (1+sel)<<M98088_MICPRE_SHIFT); | 
 | 700 |  | 
 | 701 |        return 0; | 
 | 702 | } | 
 | 703 |  | 
 | 704 | static int max98088_mic1pre_get(struct snd_kcontrol *kcontrol, | 
 | 705 |                                struct snd_ctl_elem_value *ucontrol) | 
 | 706 | { | 
 | 707 |        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | 
 | 708 |        struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); | 
 | 709 |  | 
 | 710 |        ucontrol->value.integer.value[0] = max98088->mic1pre; | 
 | 711 |        return 0; | 
 | 712 | } | 
 | 713 |  | 
 | 714 | static int max98088_mic2pre_set(struct snd_kcontrol *kcontrol, | 
 | 715 |                                struct snd_ctl_elem_value *ucontrol) | 
 | 716 | { | 
 | 717 |        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | 
 | 718 |        struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); | 
 | 719 |        unsigned int sel = ucontrol->value.integer.value[0]; | 
 | 720 |  | 
 | 721 |        max98088->mic2pre = sel; | 
 | 722 |        snd_soc_update_bits(codec, M98088_REG_36_LVL_MIC2, M98088_MICPRE_MASK, | 
 | 723 |                (1+sel)<<M98088_MICPRE_SHIFT); | 
 | 724 |  | 
 | 725 |        return 0; | 
 | 726 | } | 
 | 727 |  | 
 | 728 | static int max98088_mic2pre_get(struct snd_kcontrol *kcontrol, | 
 | 729 |                                struct snd_ctl_elem_value *ucontrol) | 
 | 730 | { | 
 | 731 |        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | 
 | 732 |        struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); | 
 | 733 |  | 
 | 734 |        ucontrol->value.integer.value[0] = max98088->mic2pre; | 
 | 735 |        return 0; | 
 | 736 | } | 
 | 737 |  | 
 | 738 | static const unsigned int max98088_micboost_tlv[] = { | 
 | 739 |        TLV_DB_RANGE_HEAD(2), | 
 | 740 |        0, 1, TLV_DB_SCALE_ITEM(0, 2000, 0), | 
 | 741 |        2, 2, TLV_DB_SCALE_ITEM(3000, 0, 0), | 
 | 742 | }; | 
 | 743 |  | 
 | 744 | static const struct snd_kcontrol_new max98088_snd_controls[] = { | 
 | 745 |  | 
 | 746 |        SOC_DOUBLE_R("Headphone Volume", M98088_REG_39_LVL_HP_L, | 
 | 747 |                M98088_REG_3A_LVL_HP_R, 0, 31, 0), | 
 | 748 |        SOC_DOUBLE_R("Speaker Volume", M98088_REG_3D_LVL_SPK_L, | 
 | 749 |                M98088_REG_3E_LVL_SPK_R, 0, 31, 0), | 
 | 750 |        SOC_DOUBLE_R("Receiver Volume", M98088_REG_3B_LVL_REC_L, | 
 | 751 |                M98088_REG_3C_LVL_REC_R, 0, 31, 0), | 
 | 752 |  | 
 | 753 |        SOC_DOUBLE_R("Headphone Switch", M98088_REG_39_LVL_HP_L, | 
 | 754 |                M98088_REG_3A_LVL_HP_R, 7, 1, 1), | 
 | 755 |        SOC_DOUBLE_R("Speaker Switch", M98088_REG_3D_LVL_SPK_L, | 
 | 756 |                M98088_REG_3E_LVL_SPK_R, 7, 1, 1), | 
 | 757 |        SOC_DOUBLE_R("Receiver Switch", M98088_REG_3B_LVL_REC_L, | 
 | 758 |                M98088_REG_3C_LVL_REC_R, 7, 1, 1), | 
 | 759 |  | 
 | 760 |        SOC_SINGLE("MIC1 Volume", M98088_REG_35_LVL_MIC1, 0, 31, 1), | 
 | 761 |        SOC_SINGLE("MIC2 Volume", M98088_REG_36_LVL_MIC2, 0, 31, 1), | 
 | 762 |  | 
 | 763 |        SOC_SINGLE_EXT_TLV("MIC1 Boost Volume", | 
 | 764 |                        M98088_REG_35_LVL_MIC1, 5, 2, 0, | 
 | 765 |                        max98088_mic1pre_get, max98088_mic1pre_set, | 
 | 766 |                        max98088_micboost_tlv), | 
 | 767 |        SOC_SINGLE_EXT_TLV("MIC2 Boost Volume", | 
 | 768 |                        M98088_REG_36_LVL_MIC2, 5, 2, 0, | 
 | 769 |                        max98088_mic2pre_get, max98088_mic2pre_set, | 
 | 770 |                        max98088_micboost_tlv), | 
 | 771 |  | 
 | 772 |        SOC_SINGLE("INA Volume", M98088_REG_37_LVL_INA, 0, 7, 1), | 
 | 773 |        SOC_SINGLE("INB Volume", M98088_REG_38_LVL_INB, 0, 7, 1), | 
 | 774 |  | 
 | 775 |        SOC_SINGLE("ADCL Volume", M98088_REG_33_LVL_ADC_L, 0, 15, 0), | 
 | 776 |        SOC_SINGLE("ADCR Volume", M98088_REG_34_LVL_ADC_R, 0, 15, 0), | 
 | 777 |  | 
 | 778 |        SOC_SINGLE("ADCL Boost Volume", M98088_REG_33_LVL_ADC_L, 4, 3, 0), | 
 | 779 |        SOC_SINGLE("ADCR Boost Volume", M98088_REG_34_LVL_ADC_R, 4, 3, 0), | 
 | 780 |  | 
 | 781 |        SOC_SINGLE("EQ1 Switch", M98088_REG_49_CFG_LEVEL, 0, 1, 0), | 
 | 782 |        SOC_SINGLE("EQ2 Switch", M98088_REG_49_CFG_LEVEL, 1, 1, 0), | 
 | 783 |  | 
| Jin Park | 938b4fb | 2011-05-12 14:58:37 +0900 | [diff] [blame] | 784 |        SOC_ENUM("EX Limiter Mode", max98088_exmode_enum), | 
| Mark Brown | e86e124 | 2010-10-18 16:45:24 -0700 | [diff] [blame] | 785 |        SOC_ENUM("EX Limiter Threshold", max98088_ex_thresh_enum), | 
 | 786 |  | 
 | 787 |        SOC_ENUM("DAI1 Filter Mode", max98088_filter_mode_enum), | 
 | 788 |        SOC_ENUM("DAI1 DAC Filter", max98088_dai1_dac_filter_enum), | 
 | 789 |        SOC_ENUM("DAI1 ADC Filter", max98088_dai1_adc_filter_enum), | 
 | 790 |        SOC_SINGLE("DAI2 DC Block Switch", M98088_REG_20_DAI2_FILTERS, | 
 | 791 |                0, 1, 0), | 
 | 792 |  | 
 | 793 |        SOC_SINGLE("ALC Switch", M98088_REG_43_SPKALC_COMP, 7, 1, 0), | 
 | 794 |        SOC_SINGLE("ALC Threshold", M98088_REG_43_SPKALC_COMP, 0, 7, 0), | 
 | 795 |        SOC_SINGLE("ALC Multiband", M98088_REG_43_SPKALC_COMP, 3, 1, 0), | 
 | 796 |        SOC_SINGLE("ALC Release Time", M98088_REG_43_SPKALC_COMP, 4, 7, 0), | 
 | 797 |  | 
 | 798 |        SOC_SINGLE("PWR Limiter Threshold", M98088_REG_44_PWRLMT_CFG, | 
 | 799 |                4, 15, 0), | 
 | 800 |        SOC_SINGLE("PWR Limiter Weight", M98088_REG_44_PWRLMT_CFG, 0, 7, 0), | 
 | 801 |        SOC_SINGLE("PWR Limiter Time1", M98088_REG_45_PWRLMT_TIME, 0, 15, 0), | 
 | 802 |        SOC_SINGLE("PWR Limiter Time2", M98088_REG_45_PWRLMT_TIME, 4, 15, 0), | 
 | 803 |  | 
 | 804 |        SOC_SINGLE("THD Limiter Threshold", M98088_REG_46_THDLMT_CFG, 4, 15, 0), | 
 | 805 |        SOC_SINGLE("THD Limiter Time", M98088_REG_46_THDLMT_CFG, 0, 7, 0), | 
 | 806 | }; | 
 | 807 |  | 
 | 808 | /* Left speaker mixer switch */ | 
 | 809 | static const struct snd_kcontrol_new max98088_left_speaker_mixer_controls[] = { | 
| Jin Park | 770939c | 2011-05-12 14:58:36 +0900 | [diff] [blame] | 810 |        SOC_DAPM_SINGLE("Left DAC1 Switch", M98088_REG_2B_MIX_SPK_LEFT, 0, 1, 0), | 
 | 811 |        SOC_DAPM_SINGLE("Right DAC1 Switch", M98088_REG_2B_MIX_SPK_LEFT, 7, 1, 0), | 
 | 812 |        SOC_DAPM_SINGLE("Left DAC2 Switch", M98088_REG_2B_MIX_SPK_LEFT, 0, 1, 0), | 
 | 813 |        SOC_DAPM_SINGLE("Right DAC2 Switch", M98088_REG_2B_MIX_SPK_LEFT, 7, 1, 0), | 
| Mark Brown | e86e124 | 2010-10-18 16:45:24 -0700 | [diff] [blame] | 814 |        SOC_DAPM_SINGLE("MIC1 Switch", M98088_REG_2B_MIX_SPK_LEFT, 5, 1, 0), | 
 | 815 |        SOC_DAPM_SINGLE("MIC2 Switch", M98088_REG_2B_MIX_SPK_LEFT, 6, 1, 0), | 
 | 816 |        SOC_DAPM_SINGLE("INA1 Switch", M98088_REG_2B_MIX_SPK_LEFT, 1, 1, 0), | 
 | 817 |        SOC_DAPM_SINGLE("INA2 Switch", M98088_REG_2B_MIX_SPK_LEFT, 2, 1, 0), | 
 | 818 |        SOC_DAPM_SINGLE("INB1 Switch", M98088_REG_2B_MIX_SPK_LEFT, 3, 1, 0), | 
 | 819 |        SOC_DAPM_SINGLE("INB2 Switch", M98088_REG_2B_MIX_SPK_LEFT, 4, 1, 0), | 
 | 820 | }; | 
 | 821 |  | 
 | 822 | /* Right speaker mixer switch */ | 
 | 823 | static const struct snd_kcontrol_new max98088_right_speaker_mixer_controls[] = { | 
 | 824 |        SOC_DAPM_SINGLE("Left DAC1 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 7, 1, 0), | 
 | 825 |        SOC_DAPM_SINGLE("Right DAC1 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 0, 1, 0), | 
 | 826 |        SOC_DAPM_SINGLE("Left DAC2 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 7, 1, 0), | 
 | 827 |        SOC_DAPM_SINGLE("Right DAC2 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 0, 1, 0), | 
 | 828 |        SOC_DAPM_SINGLE("MIC1 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 5, 1, 0), | 
 | 829 |        SOC_DAPM_SINGLE("MIC2 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 6, 1, 0), | 
 | 830 |        SOC_DAPM_SINGLE("INA1 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 1, 1, 0), | 
 | 831 |        SOC_DAPM_SINGLE("INA2 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 2, 1, 0), | 
 | 832 |        SOC_DAPM_SINGLE("INB1 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 3, 1, 0), | 
 | 833 |        SOC_DAPM_SINGLE("INB2 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 4, 1, 0), | 
 | 834 | }; | 
 | 835 |  | 
 | 836 | /* Left headphone mixer switch */ | 
 | 837 | static const struct snd_kcontrol_new max98088_left_hp_mixer_controls[] = { | 
| Jin Park | 770939c | 2011-05-12 14:58:36 +0900 | [diff] [blame] | 838 |        SOC_DAPM_SINGLE("Left DAC1 Switch", M98088_REG_25_MIX_HP_LEFT, 0, 1, 0), | 
 | 839 |        SOC_DAPM_SINGLE("Right DAC1 Switch", M98088_REG_25_MIX_HP_LEFT, 7, 1, 0), | 
 | 840 |        SOC_DAPM_SINGLE("Left DAC2 Switch", M98088_REG_25_MIX_HP_LEFT, 0, 1, 0), | 
 | 841 |        SOC_DAPM_SINGLE("Right DAC2 Switch", M98088_REG_25_MIX_HP_LEFT, 7, 1, 0), | 
| Mark Brown | e86e124 | 2010-10-18 16:45:24 -0700 | [diff] [blame] | 842 |        SOC_DAPM_SINGLE("MIC1 Switch", M98088_REG_25_MIX_HP_LEFT, 5, 1, 0), | 
 | 843 |        SOC_DAPM_SINGLE("MIC2 Switch", M98088_REG_25_MIX_HP_LEFT, 6, 1, 0), | 
 | 844 |        SOC_DAPM_SINGLE("INA1 Switch", M98088_REG_25_MIX_HP_LEFT, 1, 1, 0), | 
 | 845 |        SOC_DAPM_SINGLE("INA2 Switch", M98088_REG_25_MIX_HP_LEFT, 2, 1, 0), | 
 | 846 |        SOC_DAPM_SINGLE("INB1 Switch", M98088_REG_25_MIX_HP_LEFT, 3, 1, 0), | 
 | 847 |        SOC_DAPM_SINGLE("INB2 Switch", M98088_REG_25_MIX_HP_LEFT, 4, 1, 0), | 
 | 848 | }; | 
 | 849 |  | 
 | 850 | /* Right headphone mixer switch */ | 
 | 851 | static const struct snd_kcontrol_new max98088_right_hp_mixer_controls[] = { | 
 | 852 |        SOC_DAPM_SINGLE("Left DAC1 Switch", M98088_REG_26_MIX_HP_RIGHT, 7, 1, 0), | 
 | 853 |        SOC_DAPM_SINGLE("Right DAC1 Switch", M98088_REG_26_MIX_HP_RIGHT, 0, 1, 0), | 
 | 854 |        SOC_DAPM_SINGLE("Left DAC2 Switch", M98088_REG_26_MIX_HP_RIGHT, 7, 1, 0), | 
 | 855 |        SOC_DAPM_SINGLE("Right DAC2 Switch", M98088_REG_26_MIX_HP_RIGHT, 0, 1, 0), | 
 | 856 |        SOC_DAPM_SINGLE("MIC1 Switch", M98088_REG_26_MIX_HP_RIGHT, 5, 1, 0), | 
 | 857 |        SOC_DAPM_SINGLE("MIC2 Switch", M98088_REG_26_MIX_HP_RIGHT, 6, 1, 0), | 
 | 858 |        SOC_DAPM_SINGLE("INA1 Switch", M98088_REG_26_MIX_HP_RIGHT, 1, 1, 0), | 
 | 859 |        SOC_DAPM_SINGLE("INA2 Switch", M98088_REG_26_MIX_HP_RIGHT, 2, 1, 0), | 
 | 860 |        SOC_DAPM_SINGLE("INB1 Switch", M98088_REG_26_MIX_HP_RIGHT, 3, 1, 0), | 
 | 861 |        SOC_DAPM_SINGLE("INB2 Switch", M98088_REG_26_MIX_HP_RIGHT, 4, 1, 0), | 
 | 862 | }; | 
 | 863 |  | 
 | 864 | /* Left earpiece/receiver mixer switch */ | 
 | 865 | static const struct snd_kcontrol_new max98088_left_rec_mixer_controls[] = { | 
| Jin Park | 770939c | 2011-05-12 14:58:36 +0900 | [diff] [blame] | 866 |        SOC_DAPM_SINGLE("Left DAC1 Switch", M98088_REG_28_MIX_REC_LEFT, 0, 1, 0), | 
 | 867 |        SOC_DAPM_SINGLE("Right DAC1 Switch", M98088_REG_28_MIX_REC_LEFT, 7, 1, 0), | 
 | 868 |        SOC_DAPM_SINGLE("Left DAC2 Switch", M98088_REG_28_MIX_REC_LEFT, 0, 1, 0), | 
 | 869 |        SOC_DAPM_SINGLE("Right DAC2 Switch", M98088_REG_28_MIX_REC_LEFT, 7, 1, 0), | 
| Mark Brown | e86e124 | 2010-10-18 16:45:24 -0700 | [diff] [blame] | 870 |        SOC_DAPM_SINGLE("MIC1 Switch", M98088_REG_28_MIX_REC_LEFT, 5, 1, 0), | 
 | 871 |        SOC_DAPM_SINGLE("MIC2 Switch", M98088_REG_28_MIX_REC_LEFT, 6, 1, 0), | 
 | 872 |        SOC_DAPM_SINGLE("INA1 Switch", M98088_REG_28_MIX_REC_LEFT, 1, 1, 0), | 
 | 873 |        SOC_DAPM_SINGLE("INA2 Switch", M98088_REG_28_MIX_REC_LEFT, 2, 1, 0), | 
 | 874 |        SOC_DAPM_SINGLE("INB1 Switch", M98088_REG_28_MIX_REC_LEFT, 3, 1, 0), | 
 | 875 |        SOC_DAPM_SINGLE("INB2 Switch", M98088_REG_28_MIX_REC_LEFT, 4, 1, 0), | 
 | 876 | }; | 
 | 877 |  | 
 | 878 | /* Right earpiece/receiver mixer switch */ | 
 | 879 | static const struct snd_kcontrol_new max98088_right_rec_mixer_controls[] = { | 
 | 880 |        SOC_DAPM_SINGLE("Left DAC1 Switch", M98088_REG_29_MIX_REC_RIGHT, 7, 1, 0), | 
 | 881 |        SOC_DAPM_SINGLE("Right DAC1 Switch", M98088_REG_29_MIX_REC_RIGHT, 0, 1, 0), | 
 | 882 |        SOC_DAPM_SINGLE("Left DAC2 Switch", M98088_REG_29_MIX_REC_RIGHT, 7, 1, 0), | 
 | 883 |        SOC_DAPM_SINGLE("Right DAC2 Switch", M98088_REG_29_MIX_REC_RIGHT, 0, 1, 0), | 
 | 884 |        SOC_DAPM_SINGLE("MIC1 Switch", M98088_REG_29_MIX_REC_RIGHT, 5, 1, 0), | 
 | 885 |        SOC_DAPM_SINGLE("MIC2 Switch", M98088_REG_29_MIX_REC_RIGHT, 6, 1, 0), | 
 | 886 |        SOC_DAPM_SINGLE("INA1 Switch", M98088_REG_29_MIX_REC_RIGHT, 1, 1, 0), | 
 | 887 |        SOC_DAPM_SINGLE("INA2 Switch", M98088_REG_29_MIX_REC_RIGHT, 2, 1, 0), | 
 | 888 |        SOC_DAPM_SINGLE("INB1 Switch", M98088_REG_29_MIX_REC_RIGHT, 3, 1, 0), | 
 | 889 |        SOC_DAPM_SINGLE("INB2 Switch", M98088_REG_29_MIX_REC_RIGHT, 4, 1, 0), | 
 | 890 | }; | 
 | 891 |  | 
 | 892 | /* Left ADC mixer switch */ | 
 | 893 | static const struct snd_kcontrol_new max98088_left_ADC_mixer_controls[] = { | 
 | 894 |        SOC_DAPM_SINGLE("MIC1 Switch", M98088_REG_23_MIX_ADC_LEFT, 7, 1, 0), | 
 | 895 |        SOC_DAPM_SINGLE("MIC2 Switch", M98088_REG_23_MIX_ADC_LEFT, 6, 1, 0), | 
 | 896 |        SOC_DAPM_SINGLE("INA1 Switch", M98088_REG_23_MIX_ADC_LEFT, 3, 1, 0), | 
 | 897 |        SOC_DAPM_SINGLE("INA2 Switch", M98088_REG_23_MIX_ADC_LEFT, 2, 1, 0), | 
 | 898 |        SOC_DAPM_SINGLE("INB1 Switch", M98088_REG_23_MIX_ADC_LEFT, 1, 1, 0), | 
 | 899 |        SOC_DAPM_SINGLE("INB2 Switch", M98088_REG_23_MIX_ADC_LEFT, 0, 1, 0), | 
 | 900 | }; | 
 | 901 |  | 
 | 902 | /* Right ADC mixer switch */ | 
 | 903 | static const struct snd_kcontrol_new max98088_right_ADC_mixer_controls[] = { | 
 | 904 |        SOC_DAPM_SINGLE("MIC1 Switch", M98088_REG_24_MIX_ADC_RIGHT, 7, 1, 0), | 
 | 905 |        SOC_DAPM_SINGLE("MIC2 Switch", M98088_REG_24_MIX_ADC_RIGHT, 6, 1, 0), | 
 | 906 |        SOC_DAPM_SINGLE("INA1 Switch", M98088_REG_24_MIX_ADC_RIGHT, 3, 1, 0), | 
 | 907 |        SOC_DAPM_SINGLE("INA2 Switch", M98088_REG_24_MIX_ADC_RIGHT, 2, 1, 0), | 
 | 908 |        SOC_DAPM_SINGLE("INB1 Switch", M98088_REG_24_MIX_ADC_RIGHT, 1, 1, 0), | 
 | 909 |        SOC_DAPM_SINGLE("INB2 Switch", M98088_REG_24_MIX_ADC_RIGHT, 0, 1, 0), | 
 | 910 | }; | 
 | 911 |  | 
 | 912 | static int max98088_mic_event(struct snd_soc_dapm_widget *w, | 
 | 913 |                             struct snd_kcontrol *kcontrol, int event) | 
 | 914 | { | 
 | 915 |        struct snd_soc_codec *codec = w->codec; | 
 | 916 |        struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); | 
 | 917 |  | 
 | 918 |        switch (event) { | 
 | 919 |        case SND_SOC_DAPM_POST_PMU: | 
 | 920 |                if (w->reg == M98088_REG_35_LVL_MIC1) { | 
 | 921 |                        snd_soc_update_bits(codec, w->reg, M98088_MICPRE_MASK, | 
 | 922 |                                (1+max98088->mic1pre)<<M98088_MICPRE_SHIFT); | 
 | 923 |                } else { | 
 | 924 |                        snd_soc_update_bits(codec, w->reg, M98088_MICPRE_MASK, | 
 | 925 |                                (1+max98088->mic2pre)<<M98088_MICPRE_SHIFT); | 
 | 926 |                } | 
 | 927 |                break; | 
 | 928 |        case SND_SOC_DAPM_POST_PMD: | 
 | 929 |                snd_soc_update_bits(codec, w->reg, M98088_MICPRE_MASK, 0); | 
 | 930 |                break; | 
 | 931 |        default: | 
 | 932 |                return -EINVAL; | 
 | 933 |        } | 
 | 934 |  | 
 | 935 |        return 0; | 
 | 936 | } | 
 | 937 |  | 
 | 938 | /* | 
 | 939 |  * The line inputs are 2-channel stereo inputs with the left | 
 | 940 |  * and right channels sharing a common PGA power control signal. | 
 | 941 |  */ | 
 | 942 | static int max98088_line_pga(struct snd_soc_dapm_widget *w, | 
 | 943 |                             int event, int line, u8 channel) | 
 | 944 | { | 
 | 945 |        struct snd_soc_codec *codec = w->codec; | 
 | 946 |        struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); | 
 | 947 |        u8 *state; | 
 | 948 |  | 
 | 949 |        BUG_ON(!((channel == 1) || (channel == 2))); | 
 | 950 |  | 
 | 951 |        switch (line) { | 
 | 952 |        case LINE_INA: | 
 | 953 |                state = &max98088->ina_state; | 
 | 954 |                break; | 
 | 955 |        case LINE_INB: | 
 | 956 |                state = &max98088->inb_state; | 
 | 957 |                break; | 
 | 958 |        default: | 
 | 959 |                return -EINVAL; | 
 | 960 |        } | 
 | 961 |  | 
 | 962 |        switch (event) { | 
 | 963 |        case SND_SOC_DAPM_POST_PMU: | 
 | 964 |                *state |= channel; | 
 | 965 |                snd_soc_update_bits(codec, w->reg, | 
 | 966 |                        (1 << w->shift), (1 << w->shift)); | 
 | 967 |                break; | 
 | 968 |        case SND_SOC_DAPM_POST_PMD: | 
 | 969 |                *state &= ~channel; | 
 | 970 |                if (*state == 0) { | 
 | 971 |                        snd_soc_update_bits(codec, w->reg, | 
 | 972 |                                (1 << w->shift), 0); | 
 | 973 |                } | 
 | 974 |                break; | 
 | 975 |        default: | 
 | 976 |                return -EINVAL; | 
 | 977 |        } | 
 | 978 |  | 
 | 979 |        return 0; | 
 | 980 | } | 
 | 981 |  | 
 | 982 | static int max98088_pga_ina1_event(struct snd_soc_dapm_widget *w, | 
 | 983 |                                   struct snd_kcontrol *k, int event) | 
 | 984 | { | 
 | 985 |        return max98088_line_pga(w, event, LINE_INA, 1); | 
 | 986 | } | 
 | 987 |  | 
 | 988 | static int max98088_pga_ina2_event(struct snd_soc_dapm_widget *w, | 
 | 989 |                                   struct snd_kcontrol *k, int event) | 
 | 990 | { | 
 | 991 |        return max98088_line_pga(w, event, LINE_INA, 2); | 
 | 992 | } | 
 | 993 |  | 
 | 994 | static int max98088_pga_inb1_event(struct snd_soc_dapm_widget *w, | 
 | 995 |                                   struct snd_kcontrol *k, int event) | 
 | 996 | { | 
 | 997 |        return max98088_line_pga(w, event, LINE_INB, 1); | 
 | 998 | } | 
 | 999 |  | 
 | 1000 | static int max98088_pga_inb2_event(struct snd_soc_dapm_widget *w, | 
 | 1001 |                                   struct snd_kcontrol *k, int event) | 
 | 1002 | { | 
 | 1003 |        return max98088_line_pga(w, event, LINE_INB, 2); | 
 | 1004 | } | 
 | 1005 |  | 
 | 1006 | static const struct snd_soc_dapm_widget max98088_dapm_widgets[] = { | 
 | 1007 |  | 
 | 1008 |        SND_SOC_DAPM_ADC("ADCL", "HiFi Capture", M98088_REG_4C_PWR_EN_IN, 1, 0), | 
 | 1009 |        SND_SOC_DAPM_ADC("ADCR", "HiFi Capture", M98088_REG_4C_PWR_EN_IN, 0, 0), | 
 | 1010 |  | 
 | 1011 |        SND_SOC_DAPM_DAC("DACL1", "HiFi Playback", | 
 | 1012 |                M98088_REG_4D_PWR_EN_OUT, 1, 0), | 
 | 1013 |        SND_SOC_DAPM_DAC("DACR1", "HiFi Playback", | 
 | 1014 |                M98088_REG_4D_PWR_EN_OUT, 0, 0), | 
 | 1015 |        SND_SOC_DAPM_DAC("DACL2", "Aux Playback", | 
 | 1016 |                M98088_REG_4D_PWR_EN_OUT, 1, 0), | 
 | 1017 |        SND_SOC_DAPM_DAC("DACR2", "Aux Playback", | 
 | 1018 |                M98088_REG_4D_PWR_EN_OUT, 0, 0), | 
 | 1019 |  | 
 | 1020 |        SND_SOC_DAPM_PGA("HP Left Out", M98088_REG_4D_PWR_EN_OUT, | 
 | 1021 |                7, 0, NULL, 0), | 
 | 1022 |        SND_SOC_DAPM_PGA("HP Right Out", M98088_REG_4D_PWR_EN_OUT, | 
 | 1023 |                6, 0, NULL, 0), | 
 | 1024 |  | 
 | 1025 |        SND_SOC_DAPM_PGA("SPK Left Out", M98088_REG_4D_PWR_EN_OUT, | 
 | 1026 |                5, 0, NULL, 0), | 
 | 1027 |        SND_SOC_DAPM_PGA("SPK Right Out", M98088_REG_4D_PWR_EN_OUT, | 
 | 1028 |                4, 0, NULL, 0), | 
 | 1029 |  | 
 | 1030 |        SND_SOC_DAPM_PGA("REC Left Out", M98088_REG_4D_PWR_EN_OUT, | 
 | 1031 |                3, 0, NULL, 0), | 
 | 1032 |        SND_SOC_DAPM_PGA("REC Right Out", M98088_REG_4D_PWR_EN_OUT, | 
 | 1033 |                2, 0, NULL, 0), | 
 | 1034 |  | 
 | 1035 |        SND_SOC_DAPM_MUX("External MIC", SND_SOC_NOPM, 0, 0, | 
 | 1036 |                &max98088_extmic_mux), | 
 | 1037 |  | 
 | 1038 |        SND_SOC_DAPM_MIXER("Left HP Mixer", SND_SOC_NOPM, 0, 0, | 
 | 1039 |                &max98088_left_hp_mixer_controls[0], | 
 | 1040 |                ARRAY_SIZE(max98088_left_hp_mixer_controls)), | 
 | 1041 |  | 
 | 1042 |        SND_SOC_DAPM_MIXER("Right HP Mixer", SND_SOC_NOPM, 0, 0, | 
 | 1043 |                &max98088_right_hp_mixer_controls[0], | 
 | 1044 |                ARRAY_SIZE(max98088_right_hp_mixer_controls)), | 
 | 1045 |  | 
 | 1046 |        SND_SOC_DAPM_MIXER("Left SPK Mixer", SND_SOC_NOPM, 0, 0, | 
 | 1047 |                &max98088_left_speaker_mixer_controls[0], | 
 | 1048 |                ARRAY_SIZE(max98088_left_speaker_mixer_controls)), | 
 | 1049 |  | 
 | 1050 |        SND_SOC_DAPM_MIXER("Right SPK Mixer", SND_SOC_NOPM, 0, 0, | 
 | 1051 |                &max98088_right_speaker_mixer_controls[0], | 
 | 1052 |                ARRAY_SIZE(max98088_right_speaker_mixer_controls)), | 
 | 1053 |  | 
 | 1054 |        SND_SOC_DAPM_MIXER("Left REC Mixer", SND_SOC_NOPM, 0, 0, | 
 | 1055 |          &max98088_left_rec_mixer_controls[0], | 
 | 1056 |                ARRAY_SIZE(max98088_left_rec_mixer_controls)), | 
 | 1057 |  | 
 | 1058 |        SND_SOC_DAPM_MIXER("Right REC Mixer", SND_SOC_NOPM, 0, 0, | 
 | 1059 |          &max98088_right_rec_mixer_controls[0], | 
 | 1060 |                ARRAY_SIZE(max98088_right_rec_mixer_controls)), | 
 | 1061 |  | 
 | 1062 |        SND_SOC_DAPM_MIXER("Left ADC Mixer", SND_SOC_NOPM, 0, 0, | 
 | 1063 |                &max98088_left_ADC_mixer_controls[0], | 
 | 1064 |                ARRAY_SIZE(max98088_left_ADC_mixer_controls)), | 
 | 1065 |  | 
 | 1066 |        SND_SOC_DAPM_MIXER("Right ADC Mixer", SND_SOC_NOPM, 0, 0, | 
 | 1067 |                &max98088_right_ADC_mixer_controls[0], | 
 | 1068 |                ARRAY_SIZE(max98088_right_ADC_mixer_controls)), | 
 | 1069 |  | 
 | 1070 |        SND_SOC_DAPM_PGA_E("MIC1 Input", M98088_REG_35_LVL_MIC1, | 
 | 1071 |                5, 0, NULL, 0, max98088_mic_event, | 
 | 1072 |                SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), | 
 | 1073 |  | 
 | 1074 |        SND_SOC_DAPM_PGA_E("MIC2 Input", M98088_REG_36_LVL_MIC2, | 
 | 1075 |                5, 0, NULL, 0, max98088_mic_event, | 
 | 1076 |                SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), | 
 | 1077 |  | 
 | 1078 |        SND_SOC_DAPM_PGA_E("INA1 Input", M98088_REG_4C_PWR_EN_IN, | 
 | 1079 |                7, 0, NULL, 0, max98088_pga_ina1_event, | 
 | 1080 |                SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), | 
 | 1081 |  | 
 | 1082 |        SND_SOC_DAPM_PGA_E("INA2 Input", M98088_REG_4C_PWR_EN_IN, | 
 | 1083 |                7, 0, NULL, 0, max98088_pga_ina2_event, | 
 | 1084 |                SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), | 
 | 1085 |  | 
 | 1086 |        SND_SOC_DAPM_PGA_E("INB1 Input", M98088_REG_4C_PWR_EN_IN, | 
 | 1087 |                6, 0, NULL, 0, max98088_pga_inb1_event, | 
 | 1088 |                SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), | 
 | 1089 |  | 
 | 1090 |        SND_SOC_DAPM_PGA_E("INB2 Input", M98088_REG_4C_PWR_EN_IN, | 
 | 1091 |                6, 0, NULL, 0, max98088_pga_inb2_event, | 
 | 1092 |                SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), | 
 | 1093 |  | 
 | 1094 |        SND_SOC_DAPM_MICBIAS("MICBIAS", M98088_REG_4C_PWR_EN_IN, 3, 0), | 
 | 1095 |  | 
| Mark Brown | e86e124 | 2010-10-18 16:45:24 -0700 | [diff] [blame] | 1096 |        SND_SOC_DAPM_OUTPUT("HPL"), | 
 | 1097 |        SND_SOC_DAPM_OUTPUT("HPR"), | 
 | 1098 |        SND_SOC_DAPM_OUTPUT("SPKL"), | 
 | 1099 |        SND_SOC_DAPM_OUTPUT("SPKR"), | 
 | 1100 |        SND_SOC_DAPM_OUTPUT("RECL"), | 
 | 1101 |        SND_SOC_DAPM_OUTPUT("RECR"), | 
 | 1102 |  | 
 | 1103 |        SND_SOC_DAPM_INPUT("MIC1"), | 
 | 1104 |        SND_SOC_DAPM_INPUT("MIC2"), | 
 | 1105 |        SND_SOC_DAPM_INPUT("INA1"), | 
 | 1106 |        SND_SOC_DAPM_INPUT("INA2"), | 
 | 1107 |        SND_SOC_DAPM_INPUT("INB1"), | 
 | 1108 |        SND_SOC_DAPM_INPUT("INB2"), | 
 | 1109 | }; | 
 | 1110 |  | 
| Lu Guanqun | dc6fc49 | 2011-03-30 21:53:10 +0800 | [diff] [blame] | 1111 | static const struct snd_soc_dapm_route max98088_audio_map[] = { | 
| Mark Brown | e86e124 | 2010-10-18 16:45:24 -0700 | [diff] [blame] | 1112 |        /* Left headphone output mixer */ | 
 | 1113 |        {"Left HP Mixer", "Left DAC1 Switch", "DACL1"}, | 
 | 1114 |        {"Left HP Mixer", "Left DAC2 Switch", "DACL2"}, | 
 | 1115 |        {"Left HP Mixer", "Right DAC1 Switch", "DACR1"}, | 
 | 1116 |        {"Left HP Mixer", "Right DAC2 Switch", "DACR2"}, | 
 | 1117 |        {"Left HP Mixer", "MIC1 Switch", "MIC1 Input"}, | 
 | 1118 |        {"Left HP Mixer", "MIC2 Switch", "MIC2 Input"}, | 
 | 1119 |        {"Left HP Mixer", "INA1 Switch", "INA1 Input"}, | 
 | 1120 |        {"Left HP Mixer", "INA2 Switch", "INA2 Input"}, | 
 | 1121 |        {"Left HP Mixer", "INB1 Switch", "INB1 Input"}, | 
 | 1122 |        {"Left HP Mixer", "INB2 Switch", "INB2 Input"}, | 
 | 1123 |  | 
 | 1124 |        /* Right headphone output mixer */ | 
 | 1125 |        {"Right HP Mixer", "Left DAC1 Switch", "DACL1"}, | 
 | 1126 |        {"Right HP Mixer", "Left DAC2 Switch", "DACL2"  }, | 
 | 1127 |        {"Right HP Mixer", "Right DAC1 Switch", "DACR1"}, | 
 | 1128 |        {"Right HP Mixer", "Right DAC2 Switch", "DACR2"}, | 
 | 1129 |        {"Right HP Mixer", "MIC1 Switch", "MIC1 Input"}, | 
 | 1130 |        {"Right HP Mixer", "MIC2 Switch", "MIC2 Input"}, | 
 | 1131 |        {"Right HP Mixer", "INA1 Switch", "INA1 Input"}, | 
 | 1132 |        {"Right HP Mixer", "INA2 Switch", "INA2 Input"}, | 
 | 1133 |        {"Right HP Mixer", "INB1 Switch", "INB1 Input"}, | 
 | 1134 |        {"Right HP Mixer", "INB2 Switch", "INB2 Input"}, | 
 | 1135 |  | 
 | 1136 |        /* Left speaker output mixer */ | 
 | 1137 |        {"Left SPK Mixer", "Left DAC1 Switch", "DACL1"}, | 
 | 1138 |        {"Left SPK Mixer", "Left DAC2 Switch", "DACL2"}, | 
 | 1139 |        {"Left SPK Mixer", "Right DAC1 Switch", "DACR1"}, | 
 | 1140 |        {"Left SPK Mixer", "Right DAC2 Switch", "DACR2"}, | 
 | 1141 |        {"Left SPK Mixer", "MIC1 Switch", "MIC1 Input"}, | 
 | 1142 |        {"Left SPK Mixer", "MIC2 Switch", "MIC2 Input"}, | 
 | 1143 |        {"Left SPK Mixer", "INA1 Switch", "INA1 Input"}, | 
 | 1144 |        {"Left SPK Mixer", "INA2 Switch", "INA2 Input"}, | 
 | 1145 |        {"Left SPK Mixer", "INB1 Switch", "INB1 Input"}, | 
 | 1146 |        {"Left SPK Mixer", "INB2 Switch", "INB2 Input"}, | 
 | 1147 |  | 
 | 1148 |        /* Right speaker output mixer */ | 
 | 1149 |        {"Right SPK Mixer", "Left DAC1 Switch", "DACL1"}, | 
 | 1150 |        {"Right SPK Mixer", "Left DAC2 Switch", "DACL2"}, | 
 | 1151 |        {"Right SPK Mixer", "Right DAC1 Switch", "DACR1"}, | 
 | 1152 |        {"Right SPK Mixer", "Right DAC2 Switch", "DACR2"}, | 
 | 1153 |        {"Right SPK Mixer", "MIC1 Switch", "MIC1 Input"}, | 
 | 1154 |        {"Right SPK Mixer", "MIC2 Switch", "MIC2 Input"}, | 
 | 1155 |        {"Right SPK Mixer", "INA1 Switch", "INA1 Input"}, | 
 | 1156 |        {"Right SPK Mixer", "INA2 Switch", "INA2 Input"}, | 
 | 1157 |        {"Right SPK Mixer", "INB1 Switch", "INB1 Input"}, | 
 | 1158 |        {"Right SPK Mixer", "INB2 Switch", "INB2 Input"}, | 
 | 1159 |  | 
 | 1160 |        /* Earpiece/Receiver output mixer */ | 
 | 1161 |        {"Left REC Mixer", "Left DAC1 Switch", "DACL1"}, | 
 | 1162 |        {"Left REC Mixer", "Left DAC2 Switch", "DACL2"}, | 
 | 1163 |        {"Left REC Mixer", "Right DAC1 Switch", "DACR1"}, | 
 | 1164 |        {"Left REC Mixer", "Right DAC2 Switch", "DACR2"}, | 
 | 1165 |        {"Left REC Mixer", "MIC1 Switch", "MIC1 Input"}, | 
 | 1166 |        {"Left REC Mixer", "MIC2 Switch", "MIC2 Input"}, | 
 | 1167 |        {"Left REC Mixer", "INA1 Switch", "INA1 Input"}, | 
 | 1168 |        {"Left REC Mixer", "INA2 Switch", "INA2 Input"}, | 
 | 1169 |        {"Left REC Mixer", "INB1 Switch", "INB1 Input"}, | 
 | 1170 |        {"Left REC Mixer", "INB2 Switch", "INB2 Input"}, | 
 | 1171 |  | 
 | 1172 |        /* Earpiece/Receiver output mixer */ | 
 | 1173 |        {"Right REC Mixer", "Left DAC1 Switch", "DACL1"}, | 
 | 1174 |        {"Right REC Mixer", "Left DAC2 Switch", "DACL2"}, | 
 | 1175 |        {"Right REC Mixer", "Right DAC1 Switch", "DACR1"}, | 
 | 1176 |        {"Right REC Mixer", "Right DAC2 Switch", "DACR2"}, | 
 | 1177 |        {"Right REC Mixer", "MIC1 Switch", "MIC1 Input"}, | 
 | 1178 |        {"Right REC Mixer", "MIC2 Switch", "MIC2 Input"}, | 
 | 1179 |        {"Right REC Mixer", "INA1 Switch", "INA1 Input"}, | 
 | 1180 |        {"Right REC Mixer", "INA2 Switch", "INA2 Input"}, | 
 | 1181 |        {"Right REC Mixer", "INB1 Switch", "INB1 Input"}, | 
 | 1182 |        {"Right REC Mixer", "INB2 Switch", "INB2 Input"}, | 
 | 1183 |  | 
 | 1184 |        {"HP Left Out", NULL, "Left HP Mixer"}, | 
 | 1185 |        {"HP Right Out", NULL, "Right HP Mixer"}, | 
 | 1186 |        {"SPK Left Out", NULL, "Left SPK Mixer"}, | 
 | 1187 |        {"SPK Right Out", NULL, "Right SPK Mixer"}, | 
 | 1188 |        {"REC Left Out", NULL, "Left REC Mixer"}, | 
 | 1189 |        {"REC Right Out", NULL, "Right REC Mixer"}, | 
 | 1190 |  | 
 | 1191 |        {"HPL", NULL, "HP Left Out"}, | 
 | 1192 |        {"HPR", NULL, "HP Right Out"}, | 
 | 1193 |        {"SPKL", NULL, "SPK Left Out"}, | 
 | 1194 |        {"SPKR", NULL, "SPK Right Out"}, | 
 | 1195 |        {"RECL", NULL, "REC Left Out"}, | 
 | 1196 |        {"RECR", NULL, "REC Right Out"}, | 
 | 1197 |  | 
 | 1198 |        /* Left ADC input mixer */ | 
 | 1199 |        {"Left ADC Mixer", "MIC1 Switch", "MIC1 Input"}, | 
 | 1200 |        {"Left ADC Mixer", "MIC2 Switch", "MIC2 Input"}, | 
 | 1201 |        {"Left ADC Mixer", "INA1 Switch", "INA1 Input"}, | 
 | 1202 |        {"Left ADC Mixer", "INA2 Switch", "INA2 Input"}, | 
 | 1203 |        {"Left ADC Mixer", "INB1 Switch", "INB1 Input"}, | 
 | 1204 |        {"Left ADC Mixer", "INB2 Switch", "INB2 Input"}, | 
 | 1205 |  | 
 | 1206 |        /* Right ADC input mixer */ | 
 | 1207 |        {"Right ADC Mixer", "MIC1 Switch", "MIC1 Input"}, | 
 | 1208 |        {"Right ADC Mixer", "MIC2 Switch", "MIC2 Input"}, | 
 | 1209 |        {"Right ADC Mixer", "INA1 Switch", "INA1 Input"}, | 
 | 1210 |        {"Right ADC Mixer", "INA2 Switch", "INA2 Input"}, | 
 | 1211 |        {"Right ADC Mixer", "INB1 Switch", "INB1 Input"}, | 
 | 1212 |        {"Right ADC Mixer", "INB2 Switch", "INB2 Input"}, | 
 | 1213 |  | 
 | 1214 |        /* Inputs */ | 
 | 1215 |        {"ADCL", NULL, "Left ADC Mixer"}, | 
 | 1216 |        {"ADCR", NULL, "Right ADC Mixer"}, | 
 | 1217 |        {"INA1 Input", NULL, "INA1"}, | 
 | 1218 |        {"INA2 Input", NULL, "INA2"}, | 
 | 1219 |        {"INB1 Input", NULL, "INB1"}, | 
 | 1220 |        {"INB2 Input", NULL, "INB2"}, | 
 | 1221 |        {"MIC1 Input", NULL, "MIC1"}, | 
 | 1222 |        {"MIC2 Input", NULL, "MIC2"}, | 
 | 1223 | }; | 
 | 1224 |  | 
| Mark Brown | e86e124 | 2010-10-18 16:45:24 -0700 | [diff] [blame] | 1225 | /* codec mclk clock divider coefficients */ | 
 | 1226 | static const struct { | 
 | 1227 |        u32 rate; | 
 | 1228 |        u8  sr; | 
 | 1229 | } rate_table[] = { | 
 | 1230 |        {8000,  0x10}, | 
 | 1231 |        {11025, 0x20}, | 
 | 1232 |        {16000, 0x30}, | 
 | 1233 |        {22050, 0x40}, | 
 | 1234 |        {24000, 0x50}, | 
 | 1235 |        {32000, 0x60}, | 
 | 1236 |        {44100, 0x70}, | 
 | 1237 |        {48000, 0x80}, | 
 | 1238 |        {88200, 0x90}, | 
 | 1239 |        {96000, 0xA0}, | 
 | 1240 | }; | 
 | 1241 |  | 
 | 1242 | static inline int rate_value(int rate, u8 *value) | 
 | 1243 | { | 
 | 1244 |        int i; | 
 | 1245 |  | 
 | 1246 |        for (i = 0; i < ARRAY_SIZE(rate_table); i++) { | 
 | 1247 |                if (rate_table[i].rate >= rate) { | 
 | 1248 |                        *value = rate_table[i].sr; | 
 | 1249 |                        return 0; | 
 | 1250 |                } | 
 | 1251 |        } | 
 | 1252 |        *value = rate_table[0].sr; | 
 | 1253 |        return -EINVAL; | 
 | 1254 | } | 
 | 1255 |  | 
 | 1256 | static int max98088_dai1_hw_params(struct snd_pcm_substream *substream, | 
 | 1257 |                                   struct snd_pcm_hw_params *params, | 
 | 1258 |                                   struct snd_soc_dai *dai) | 
 | 1259 | { | 
 | 1260 |        struct snd_soc_codec *codec = dai->codec; | 
 | 1261 |        struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); | 
 | 1262 |        struct max98088_cdata *cdata; | 
 | 1263 |        unsigned long long ni; | 
 | 1264 |        unsigned int rate; | 
 | 1265 |        u8 regval; | 
 | 1266 |  | 
 | 1267 |        cdata = &max98088->dai[0]; | 
 | 1268 |  | 
 | 1269 |        rate = params_rate(params); | 
 | 1270 |  | 
 | 1271 |        switch (params_format(params)) { | 
 | 1272 |        case SNDRV_PCM_FORMAT_S16_LE: | 
 | 1273 |                snd_soc_update_bits(codec, M98088_REG_14_DAI1_FORMAT, | 
 | 1274 |                        M98088_DAI_WS, 0); | 
 | 1275 |                break; | 
 | 1276 |        case SNDRV_PCM_FORMAT_S24_LE: | 
 | 1277 |                snd_soc_update_bits(codec, M98088_REG_14_DAI1_FORMAT, | 
 | 1278 |                        M98088_DAI_WS, M98088_DAI_WS); | 
 | 1279 |                break; | 
 | 1280 |        default: | 
 | 1281 |                return -EINVAL; | 
 | 1282 |        } | 
 | 1283 |  | 
 | 1284 |        snd_soc_update_bits(codec, M98088_REG_51_PWR_SYS, M98088_SHDNRUN, 0); | 
 | 1285 |  | 
 | 1286 |        if (rate_value(rate, ®val)) | 
 | 1287 |                return -EINVAL; | 
 | 1288 |  | 
 | 1289 |        snd_soc_update_bits(codec, M98088_REG_11_DAI1_CLKMODE, | 
 | 1290 |                M98088_CLKMODE_MASK, regval); | 
 | 1291 |        cdata->rate = rate; | 
 | 1292 |  | 
 | 1293 |        /* Configure NI when operating as master */ | 
 | 1294 |        if (snd_soc_read(codec, M98088_REG_14_DAI1_FORMAT) | 
 | 1295 |                & M98088_DAI_MAS) { | 
 | 1296 |                if (max98088->sysclk == 0) { | 
 | 1297 |                        dev_err(codec->dev, "Invalid system clock frequency\n"); | 
 | 1298 |                        return -EINVAL; | 
 | 1299 |                } | 
 | 1300 |                ni = 65536ULL * (rate < 50000 ? 96ULL : 48ULL) | 
 | 1301 |                                * (unsigned long long int)rate; | 
 | 1302 |                do_div(ni, (unsigned long long int)max98088->sysclk); | 
 | 1303 |                snd_soc_write(codec, M98088_REG_12_DAI1_CLKCFG_HI, | 
 | 1304 |                        (ni >> 8) & 0x7F); | 
 | 1305 |                snd_soc_write(codec, M98088_REG_13_DAI1_CLKCFG_LO, | 
 | 1306 |                        ni & 0xFF); | 
 | 1307 |        } | 
 | 1308 |  | 
 | 1309 |        /* Update sample rate mode */ | 
 | 1310 |        if (rate < 50000) | 
 | 1311 |                snd_soc_update_bits(codec, M98088_REG_18_DAI1_FILTERS, | 
 | 1312 |                        M98088_DAI_DHF, 0); | 
 | 1313 |        else | 
 | 1314 |                snd_soc_update_bits(codec, M98088_REG_18_DAI1_FILTERS, | 
 | 1315 |                        M98088_DAI_DHF, M98088_DAI_DHF); | 
 | 1316 |  | 
 | 1317 |        snd_soc_update_bits(codec, M98088_REG_51_PWR_SYS, M98088_SHDNRUN, | 
 | 1318 |                M98088_SHDNRUN); | 
 | 1319 |  | 
 | 1320 |        return 0; | 
 | 1321 | } | 
 | 1322 |  | 
 | 1323 | static int max98088_dai2_hw_params(struct snd_pcm_substream *substream, | 
 | 1324 |                                   struct snd_pcm_hw_params *params, | 
 | 1325 |                                   struct snd_soc_dai *dai) | 
 | 1326 | { | 
 | 1327 |        struct snd_soc_codec *codec = dai->codec; | 
 | 1328 |        struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); | 
 | 1329 |        struct max98088_cdata *cdata; | 
 | 1330 |        unsigned long long ni; | 
 | 1331 |        unsigned int rate; | 
 | 1332 |        u8 regval; | 
 | 1333 |  | 
 | 1334 |        cdata = &max98088->dai[1]; | 
 | 1335 |  | 
 | 1336 |        rate = params_rate(params); | 
 | 1337 |  | 
 | 1338 |        switch (params_format(params)) { | 
 | 1339 |        case SNDRV_PCM_FORMAT_S16_LE: | 
 | 1340 |                snd_soc_update_bits(codec, M98088_REG_1C_DAI2_FORMAT, | 
 | 1341 |                        M98088_DAI_WS, 0); | 
 | 1342 |                break; | 
 | 1343 |        case SNDRV_PCM_FORMAT_S24_LE: | 
 | 1344 |                snd_soc_update_bits(codec, M98088_REG_1C_DAI2_FORMAT, | 
 | 1345 |                        M98088_DAI_WS, M98088_DAI_WS); | 
 | 1346 |                break; | 
 | 1347 |        default: | 
 | 1348 |                return -EINVAL; | 
 | 1349 |        } | 
 | 1350 |  | 
 | 1351 |        snd_soc_update_bits(codec, M98088_REG_51_PWR_SYS, M98088_SHDNRUN, 0); | 
 | 1352 |  | 
 | 1353 |        if (rate_value(rate, ®val)) | 
 | 1354 |                return -EINVAL; | 
 | 1355 |  | 
 | 1356 |        snd_soc_update_bits(codec, M98088_REG_19_DAI2_CLKMODE, | 
 | 1357 |                M98088_CLKMODE_MASK, regval); | 
 | 1358 |        cdata->rate = rate; | 
 | 1359 |  | 
 | 1360 |        /* Configure NI when operating as master */ | 
 | 1361 |        if (snd_soc_read(codec, M98088_REG_1C_DAI2_FORMAT) | 
 | 1362 |                & M98088_DAI_MAS) { | 
 | 1363 |                if (max98088->sysclk == 0) { | 
 | 1364 |                        dev_err(codec->dev, "Invalid system clock frequency\n"); | 
 | 1365 |                        return -EINVAL; | 
 | 1366 |                } | 
 | 1367 |                ni = 65536ULL * (rate < 50000 ? 96ULL : 48ULL) | 
 | 1368 |                                * (unsigned long long int)rate; | 
 | 1369 |                do_div(ni, (unsigned long long int)max98088->sysclk); | 
 | 1370 |                snd_soc_write(codec, M98088_REG_1A_DAI2_CLKCFG_HI, | 
 | 1371 |                        (ni >> 8) & 0x7F); | 
 | 1372 |                snd_soc_write(codec, M98088_REG_1B_DAI2_CLKCFG_LO, | 
 | 1373 |                        ni & 0xFF); | 
 | 1374 |        } | 
 | 1375 |  | 
 | 1376 |        /* Update sample rate mode */ | 
 | 1377 |        if (rate < 50000) | 
 | 1378 |                snd_soc_update_bits(codec, M98088_REG_20_DAI2_FILTERS, | 
 | 1379 |                        M98088_DAI_DHF, 0); | 
 | 1380 |        else | 
 | 1381 |                snd_soc_update_bits(codec, M98088_REG_20_DAI2_FILTERS, | 
 | 1382 |                        M98088_DAI_DHF, M98088_DAI_DHF); | 
 | 1383 |  | 
 | 1384 |        snd_soc_update_bits(codec, M98088_REG_51_PWR_SYS, M98088_SHDNRUN, | 
 | 1385 |                M98088_SHDNRUN); | 
 | 1386 |  | 
 | 1387 |        return 0; | 
 | 1388 | } | 
 | 1389 |  | 
 | 1390 | static int max98088_dai_set_sysclk(struct snd_soc_dai *dai, | 
 | 1391 |                                   int clk_id, unsigned int freq, int dir) | 
 | 1392 | { | 
 | 1393 |        struct snd_soc_codec *codec = dai->codec; | 
 | 1394 |        struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); | 
 | 1395 |  | 
 | 1396 |        /* Requested clock frequency is already setup */ | 
 | 1397 |        if (freq == max98088->sysclk) | 
 | 1398 |                return 0; | 
 | 1399 |  | 
 | 1400 |        max98088->sysclk = freq; /* remember current sysclk */ | 
 | 1401 |  | 
 | 1402 |        /* Setup clocks for slave mode, and using the PLL | 
 | 1403 |         * PSCLK = 0x01 (when master clk is 10MHz to 20MHz) | 
 | 1404 |         *         0x02 (when master clk is 20MHz to 30MHz).. | 
 | 1405 |         */ | 
 | 1406 |        if ((freq >= 10000000) && (freq < 20000000)) { | 
 | 1407 |                snd_soc_write(codec, M98088_REG_10_SYS_CLK, 0x10); | 
 | 1408 |        } else if ((freq >= 20000000) && (freq < 30000000)) { | 
 | 1409 |                snd_soc_write(codec, M98088_REG_10_SYS_CLK, 0x20); | 
 | 1410 |        } else { | 
 | 1411 |                dev_err(codec->dev, "Invalid master clock frequency\n"); | 
 | 1412 |                return -EINVAL; | 
 | 1413 |        } | 
 | 1414 |  | 
 | 1415 |        if (snd_soc_read(codec, M98088_REG_51_PWR_SYS)  & M98088_SHDNRUN) { | 
 | 1416 |                snd_soc_update_bits(codec, M98088_REG_51_PWR_SYS, | 
 | 1417 |                        M98088_SHDNRUN, 0); | 
 | 1418 |                snd_soc_update_bits(codec, M98088_REG_51_PWR_SYS, | 
 | 1419 |                        M98088_SHDNRUN, M98088_SHDNRUN); | 
 | 1420 |        } | 
 | 1421 |  | 
 | 1422 |        dev_dbg(dai->dev, "Clock source is %d at %uHz\n", clk_id, freq); | 
 | 1423 |  | 
 | 1424 |        max98088->sysclk = freq; | 
 | 1425 |        return 0; | 
 | 1426 | } | 
 | 1427 |  | 
 | 1428 | static int max98088_dai1_set_fmt(struct snd_soc_dai *codec_dai, | 
 | 1429 |                                 unsigned int fmt) | 
 | 1430 | { | 
 | 1431 |        struct snd_soc_codec *codec = codec_dai->codec; | 
 | 1432 |        struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); | 
 | 1433 |        struct max98088_cdata *cdata; | 
 | 1434 |        u8 reg15val; | 
 | 1435 |        u8 reg14val = 0; | 
 | 1436 |  | 
 | 1437 |        cdata = &max98088->dai[0]; | 
 | 1438 |  | 
 | 1439 |        if (fmt != cdata->fmt) { | 
 | 1440 |                cdata->fmt = fmt; | 
 | 1441 |  | 
 | 1442 |                switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | 
 | 1443 |                case SND_SOC_DAIFMT_CBS_CFS: | 
 | 1444 |                        /* Slave mode PLL */ | 
 | 1445 |                        snd_soc_write(codec, M98088_REG_12_DAI1_CLKCFG_HI, | 
 | 1446 |                                0x80); | 
 | 1447 |                        snd_soc_write(codec, M98088_REG_13_DAI1_CLKCFG_LO, | 
 | 1448 |                                0x00); | 
 | 1449 |                        break; | 
 | 1450 |                case SND_SOC_DAIFMT_CBM_CFM: | 
 | 1451 |                        /* Set to master mode */ | 
 | 1452 |                        reg14val |= M98088_DAI_MAS; | 
 | 1453 |                        break; | 
 | 1454 |                case SND_SOC_DAIFMT_CBS_CFM: | 
 | 1455 |                case SND_SOC_DAIFMT_CBM_CFS: | 
 | 1456 |                default: | 
 | 1457 |                        dev_err(codec->dev, "Clock mode unsupported"); | 
 | 1458 |                        return -EINVAL; | 
 | 1459 |                } | 
 | 1460 |  | 
 | 1461 |                switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | 
 | 1462 |                case SND_SOC_DAIFMT_I2S: | 
 | 1463 |                        reg14val |= M98088_DAI_DLY; | 
 | 1464 |                        break; | 
 | 1465 |                case SND_SOC_DAIFMT_LEFT_J: | 
 | 1466 |                        break; | 
 | 1467 |                default: | 
 | 1468 |                        return -EINVAL; | 
 | 1469 |                } | 
 | 1470 |  | 
 | 1471 |                switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | 
 | 1472 |                case SND_SOC_DAIFMT_NB_NF: | 
 | 1473 |                        break; | 
 | 1474 |                case SND_SOC_DAIFMT_NB_IF: | 
 | 1475 |                        reg14val |= M98088_DAI_WCI; | 
 | 1476 |                        break; | 
 | 1477 |                case SND_SOC_DAIFMT_IB_NF: | 
 | 1478 |                        reg14val |= M98088_DAI_BCI; | 
 | 1479 |                        break; | 
 | 1480 |                case SND_SOC_DAIFMT_IB_IF: | 
 | 1481 |                        reg14val |= M98088_DAI_BCI|M98088_DAI_WCI; | 
 | 1482 |                        break; | 
 | 1483 |                default: | 
 | 1484 |                        return -EINVAL; | 
 | 1485 |                } | 
 | 1486 |  | 
 | 1487 |                snd_soc_update_bits(codec, M98088_REG_14_DAI1_FORMAT, | 
 | 1488 |                        M98088_DAI_MAS | M98088_DAI_DLY | M98088_DAI_BCI | | 
 | 1489 |                        M98088_DAI_WCI, reg14val); | 
 | 1490 |  | 
 | 1491 |                reg15val = M98088_DAI_BSEL64; | 
 | 1492 |                if (max98088->digmic) | 
 | 1493 |                        reg15val |= M98088_DAI_OSR64; | 
 | 1494 |                snd_soc_write(codec, M98088_REG_15_DAI1_CLOCK, reg15val); | 
 | 1495 |        } | 
 | 1496 |  | 
 | 1497 |        return 0; | 
 | 1498 | } | 
 | 1499 |  | 
 | 1500 | static int max98088_dai2_set_fmt(struct snd_soc_dai *codec_dai, | 
 | 1501 |                                 unsigned int fmt) | 
 | 1502 | { | 
 | 1503 |        struct snd_soc_codec *codec = codec_dai->codec; | 
 | 1504 |        struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); | 
 | 1505 |        struct max98088_cdata *cdata; | 
 | 1506 |        u8 reg1Cval = 0; | 
 | 1507 |  | 
 | 1508 |        cdata = &max98088->dai[1]; | 
 | 1509 |  | 
 | 1510 |        if (fmt != cdata->fmt) { | 
 | 1511 |                cdata->fmt = fmt; | 
 | 1512 |  | 
 | 1513 |                switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | 
 | 1514 |                case SND_SOC_DAIFMT_CBS_CFS: | 
 | 1515 |                        /* Slave mode PLL */ | 
 | 1516 |                        snd_soc_write(codec, M98088_REG_1A_DAI2_CLKCFG_HI, | 
 | 1517 |                                0x80); | 
 | 1518 |                        snd_soc_write(codec, M98088_REG_1B_DAI2_CLKCFG_LO, | 
 | 1519 |                                0x00); | 
 | 1520 |                        break; | 
 | 1521 |                case SND_SOC_DAIFMT_CBM_CFM: | 
 | 1522 |                        /* Set to master mode */ | 
 | 1523 |                        reg1Cval |= M98088_DAI_MAS; | 
 | 1524 |                        break; | 
 | 1525 |                case SND_SOC_DAIFMT_CBS_CFM: | 
 | 1526 |                case SND_SOC_DAIFMT_CBM_CFS: | 
 | 1527 |                default: | 
 | 1528 |                        dev_err(codec->dev, "Clock mode unsupported"); | 
 | 1529 |                        return -EINVAL; | 
 | 1530 |                } | 
 | 1531 |  | 
 | 1532 |                switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | 
 | 1533 |                case SND_SOC_DAIFMT_I2S: | 
 | 1534 |                        reg1Cval |= M98088_DAI_DLY; | 
 | 1535 |                        break; | 
 | 1536 |                case SND_SOC_DAIFMT_LEFT_J: | 
 | 1537 |                        break; | 
 | 1538 |                default: | 
 | 1539 |                        return -EINVAL; | 
 | 1540 |                } | 
 | 1541 |  | 
 | 1542 |                switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | 
 | 1543 |                case SND_SOC_DAIFMT_NB_NF: | 
 | 1544 |                        break; | 
 | 1545 |                case SND_SOC_DAIFMT_NB_IF: | 
 | 1546 |                        reg1Cval |= M98088_DAI_WCI; | 
 | 1547 |                        break; | 
 | 1548 |                case SND_SOC_DAIFMT_IB_NF: | 
 | 1549 |                        reg1Cval |= M98088_DAI_BCI; | 
 | 1550 |                        break; | 
 | 1551 |                case SND_SOC_DAIFMT_IB_IF: | 
 | 1552 |                        reg1Cval |= M98088_DAI_BCI|M98088_DAI_WCI; | 
 | 1553 |                        break; | 
 | 1554 |                default: | 
 | 1555 |                        return -EINVAL; | 
 | 1556 |                } | 
 | 1557 |  | 
 | 1558 |                snd_soc_update_bits(codec, M98088_REG_1C_DAI2_FORMAT, | 
 | 1559 |                        M98088_DAI_MAS | M98088_DAI_DLY | M98088_DAI_BCI | | 
 | 1560 |                        M98088_DAI_WCI, reg1Cval); | 
 | 1561 |  | 
 | 1562 |                snd_soc_write(codec, M98088_REG_1D_DAI2_CLOCK, | 
 | 1563 |                        M98088_DAI_BSEL64); | 
 | 1564 |        } | 
 | 1565 |  | 
 | 1566 |        return 0; | 
 | 1567 | } | 
 | 1568 |  | 
| Jin Park | 25709f6 | 2011-05-12 14:58:38 +0900 | [diff] [blame] | 1569 | static int max98088_dai1_digital_mute(struct snd_soc_dai *codec_dai, int mute) | 
 | 1570 | { | 
 | 1571 |        struct snd_soc_codec *codec = codec_dai->codec; | 
 | 1572 |        int reg; | 
 | 1573 |  | 
 | 1574 |        if (mute) | 
 | 1575 |                reg = M98088_DAI_MUTE; | 
 | 1576 |        else | 
 | 1577 |                reg = 0; | 
 | 1578 |  | 
 | 1579 |        snd_soc_update_bits(codec, M98088_REG_2F_LVL_DAI1_PLAY, | 
 | 1580 |                            M98088_DAI_MUTE_MASK, reg); | 
 | 1581 |        return 0; | 
 | 1582 | } | 
 | 1583 |  | 
 | 1584 | static int max98088_dai2_digital_mute(struct snd_soc_dai *codec_dai, int mute) | 
 | 1585 | { | 
 | 1586 |        struct snd_soc_codec *codec = codec_dai->codec; | 
 | 1587 |        int reg; | 
 | 1588 |  | 
 | 1589 |        if (mute) | 
 | 1590 |                reg = M98088_DAI_MUTE; | 
 | 1591 |        else | 
 | 1592 |                reg = 0; | 
 | 1593 |  | 
 | 1594 |        snd_soc_update_bits(codec, M98088_REG_31_LVL_DAI2_PLAY, | 
 | 1595 |                            M98088_DAI_MUTE_MASK, reg); | 
 | 1596 |        return 0; | 
 | 1597 | } | 
 | 1598 |  | 
| Mark Brown | e86e124 | 2010-10-18 16:45:24 -0700 | [diff] [blame] | 1599 | static void max98088_sync_cache(struct snd_soc_codec *codec) | 
 | 1600 | { | 
| Lars-Peter Clausen | d24eb0d | 2010-12-28 21:37:56 +0100 | [diff] [blame] | 1601 |        u16 *reg_cache = codec->reg_cache; | 
| Mark Brown | e86e124 | 2010-10-18 16:45:24 -0700 | [diff] [blame] | 1602 |        int i; | 
 | 1603 |  | 
 | 1604 |        if (!codec->cache_sync) | 
 | 1605 |                return; | 
 | 1606 |  | 
 | 1607 |        codec->cache_only = 0; | 
 | 1608 |  | 
 | 1609 |        /* write back cached values if they're writeable and | 
 | 1610 |         * different from the hardware default. | 
 | 1611 |         */ | 
| Lars-Peter Clausen | d24eb0d | 2010-12-28 21:37:56 +0100 | [diff] [blame] | 1612 |        for (i = 1; i < codec->driver->reg_cache_size; i++) { | 
| Mark Brown | e86e124 | 2010-10-18 16:45:24 -0700 | [diff] [blame] | 1613 |                if (!max98088_access[i].writable) | 
 | 1614 |                        continue; | 
 | 1615 |  | 
| Lars-Peter Clausen | d24eb0d | 2010-12-28 21:37:56 +0100 | [diff] [blame] | 1616 |                if (reg_cache[i] == max98088_reg[i]) | 
| Mark Brown | e86e124 | 2010-10-18 16:45:24 -0700 | [diff] [blame] | 1617 |                        continue; | 
 | 1618 |  | 
| Lars-Peter Clausen | d24eb0d | 2010-12-28 21:37:56 +0100 | [diff] [blame] | 1619 |                snd_soc_write(codec, i, reg_cache[i]); | 
| Mark Brown | e86e124 | 2010-10-18 16:45:24 -0700 | [diff] [blame] | 1620 |        } | 
 | 1621 |  | 
 | 1622 |        codec->cache_sync = 0; | 
 | 1623 | } | 
 | 1624 |  | 
 | 1625 | static int max98088_set_bias_level(struct snd_soc_codec *codec, | 
 | 1626 |                                   enum snd_soc_bias_level level) | 
 | 1627 | { | 
 | 1628 |        switch (level) { | 
 | 1629 |        case SND_SOC_BIAS_ON: | 
 | 1630 |                break; | 
 | 1631 |  | 
 | 1632 |        case SND_SOC_BIAS_PREPARE: | 
 | 1633 |                break; | 
 | 1634 |  | 
 | 1635 |        case SND_SOC_BIAS_STANDBY: | 
| Liam Girdwood | ce6120c | 2010-11-05 15:53:46 +0200 | [diff] [blame] | 1636 |                if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) | 
| Mark Brown | e86e124 | 2010-10-18 16:45:24 -0700 | [diff] [blame] | 1637 |                        max98088_sync_cache(codec); | 
 | 1638 |  | 
 | 1639 |                snd_soc_update_bits(codec, M98088_REG_4C_PWR_EN_IN, | 
 | 1640 |                                M98088_MBEN, M98088_MBEN); | 
 | 1641 |                break; | 
 | 1642 |  | 
 | 1643 |        case SND_SOC_BIAS_OFF: | 
 | 1644 |                snd_soc_update_bits(codec, M98088_REG_4C_PWR_EN_IN, | 
 | 1645 |                                M98088_MBEN, 0); | 
 | 1646 |                codec->cache_sync = 1; | 
 | 1647 |                break; | 
 | 1648 |        } | 
| Liam Girdwood | ce6120c | 2010-11-05 15:53:46 +0200 | [diff] [blame] | 1649 |        codec->dapm.bias_level = level; | 
| Mark Brown | e86e124 | 2010-10-18 16:45:24 -0700 | [diff] [blame] | 1650 |        return 0; | 
 | 1651 | } | 
 | 1652 |  | 
 | 1653 | #define MAX98088_RATES SNDRV_PCM_RATE_8000_96000 | 
 | 1654 | #define MAX98088_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE) | 
 | 1655 |  | 
 | 1656 | static struct snd_soc_dai_ops max98088_dai1_ops = { | 
 | 1657 |        .set_sysclk = max98088_dai_set_sysclk, | 
 | 1658 |        .set_fmt = max98088_dai1_set_fmt, | 
 | 1659 |        .hw_params = max98088_dai1_hw_params, | 
| Jin Park | 25709f6 | 2011-05-12 14:58:38 +0900 | [diff] [blame] | 1660 |        .digital_mute = max98088_dai1_digital_mute, | 
| Mark Brown | e86e124 | 2010-10-18 16:45:24 -0700 | [diff] [blame] | 1661 | }; | 
 | 1662 |  | 
 | 1663 | static struct snd_soc_dai_ops max98088_dai2_ops = { | 
 | 1664 |        .set_sysclk = max98088_dai_set_sysclk, | 
 | 1665 |        .set_fmt = max98088_dai2_set_fmt, | 
 | 1666 |        .hw_params = max98088_dai2_hw_params, | 
| Jin Park | 25709f6 | 2011-05-12 14:58:38 +0900 | [diff] [blame] | 1667 |        .digital_mute = max98088_dai2_digital_mute, | 
| Mark Brown | e86e124 | 2010-10-18 16:45:24 -0700 | [diff] [blame] | 1668 | }; | 
 | 1669 |  | 
 | 1670 | static struct snd_soc_dai_driver max98088_dai[] = { | 
 | 1671 | { | 
 | 1672 |        .name = "HiFi", | 
 | 1673 |        .playback = { | 
 | 1674 |                .stream_name = "HiFi Playback", | 
 | 1675 |                .channels_min = 1, | 
 | 1676 |                .channels_max = 2, | 
 | 1677 |                .rates = MAX98088_RATES, | 
 | 1678 |                .formats = MAX98088_FORMATS, | 
 | 1679 |        }, | 
 | 1680 |        .capture = { | 
 | 1681 |                .stream_name = "HiFi Capture", | 
 | 1682 |                .channels_min = 1, | 
 | 1683 |                .channels_max = 2, | 
 | 1684 |                .rates = MAX98088_RATES, | 
 | 1685 |                .formats = MAX98088_FORMATS, | 
 | 1686 |        }, | 
 | 1687 |         .ops = &max98088_dai1_ops, | 
 | 1688 | }, | 
 | 1689 | { | 
 | 1690 |        .name = "Aux", | 
 | 1691 |        .playback = { | 
 | 1692 |                .stream_name = "Aux Playback", | 
 | 1693 |                .channels_min = 1, | 
 | 1694 |                .channels_max = 2, | 
 | 1695 |                .rates = MAX98088_RATES, | 
 | 1696 |                .formats = MAX98088_FORMATS, | 
 | 1697 |        }, | 
 | 1698 |        .ops = &max98088_dai2_ops, | 
 | 1699 | } | 
 | 1700 | }; | 
 | 1701 |  | 
 | 1702 | static int max98088_get_channel(const char *name) | 
 | 1703 | { | 
 | 1704 |        if (strcmp(name, "EQ1 Mode") == 0) | 
 | 1705 |                return 0; | 
 | 1706 |        if (strcmp(name, "EQ2 Mode") == 0) | 
 | 1707 |                return 1; | 
 | 1708 |        return -EINVAL; | 
 | 1709 | } | 
 | 1710 |  | 
 | 1711 | static void max98088_setup_eq1(struct snd_soc_codec *codec) | 
 | 1712 | { | 
 | 1713 |        struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); | 
 | 1714 |        struct max98088_pdata *pdata = max98088->pdata; | 
 | 1715 |        struct max98088_eq_cfg *coef_set; | 
 | 1716 |        int best, best_val, save, i, sel, fs; | 
 | 1717 |        struct max98088_cdata *cdata; | 
 | 1718 |  | 
 | 1719 |        cdata = &max98088->dai[0]; | 
 | 1720 |  | 
 | 1721 |        if (!pdata || !max98088->eq_textcnt) | 
 | 1722 |                return; | 
 | 1723 |  | 
 | 1724 |        /* Find the selected configuration with nearest sample rate */ | 
 | 1725 |        fs = cdata->rate; | 
 | 1726 |        sel = cdata->eq_sel; | 
 | 1727 |  | 
 | 1728 |        best = 0; | 
 | 1729 |        best_val = INT_MAX; | 
 | 1730 |        for (i = 0; i < pdata->eq_cfgcnt; i++) { | 
 | 1731 |                if (strcmp(pdata->eq_cfg[i].name, max98088->eq_texts[sel]) == 0 && | 
 | 1732 |                    abs(pdata->eq_cfg[i].rate - fs) < best_val) { | 
 | 1733 |                        best = i; | 
 | 1734 |                        best_val = abs(pdata->eq_cfg[i].rate - fs); | 
 | 1735 |                } | 
 | 1736 |        } | 
 | 1737 |  | 
 | 1738 |        dev_dbg(codec->dev, "Selected %s/%dHz for %dHz sample rate\n", | 
 | 1739 |                pdata->eq_cfg[best].name, | 
 | 1740 |                pdata->eq_cfg[best].rate, fs); | 
 | 1741 |  | 
 | 1742 |        /* Disable EQ while configuring, and save current on/off state */ | 
 | 1743 |        save = snd_soc_read(codec, M98088_REG_49_CFG_LEVEL); | 
 | 1744 |        snd_soc_update_bits(codec, M98088_REG_49_CFG_LEVEL, M98088_EQ1EN, 0); | 
 | 1745 |  | 
 | 1746 |        coef_set = &pdata->eq_cfg[sel]; | 
 | 1747 |  | 
 | 1748 |        m98088_eq_band(codec, 0, 0, coef_set->band1); | 
 | 1749 |        m98088_eq_band(codec, 0, 1, coef_set->band2); | 
 | 1750 |        m98088_eq_band(codec, 0, 2, coef_set->band3); | 
 | 1751 |        m98088_eq_band(codec, 0, 3, coef_set->band4); | 
 | 1752 |        m98088_eq_band(codec, 0, 4, coef_set->band5); | 
 | 1753 |  | 
 | 1754 |        /* Restore the original on/off state */ | 
 | 1755 |        snd_soc_update_bits(codec, M98088_REG_49_CFG_LEVEL, M98088_EQ1EN, save); | 
 | 1756 | } | 
 | 1757 |  | 
 | 1758 | static void max98088_setup_eq2(struct snd_soc_codec *codec) | 
 | 1759 | { | 
 | 1760 |        struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); | 
 | 1761 |        struct max98088_pdata *pdata = max98088->pdata; | 
 | 1762 |        struct max98088_eq_cfg *coef_set; | 
 | 1763 |        int best, best_val, save, i, sel, fs; | 
 | 1764 |        struct max98088_cdata *cdata; | 
 | 1765 |  | 
 | 1766 |        cdata = &max98088->dai[1]; | 
 | 1767 |  | 
 | 1768 |        if (!pdata || !max98088->eq_textcnt) | 
 | 1769 |                return; | 
 | 1770 |  | 
 | 1771 |        /* Find the selected configuration with nearest sample rate */ | 
 | 1772 |        fs = cdata->rate; | 
 | 1773 |  | 
 | 1774 |        sel = cdata->eq_sel; | 
 | 1775 |        best = 0; | 
 | 1776 |        best_val = INT_MAX; | 
 | 1777 |        for (i = 0; i < pdata->eq_cfgcnt; i++) { | 
 | 1778 |                if (strcmp(pdata->eq_cfg[i].name, max98088->eq_texts[sel]) == 0 && | 
 | 1779 |                    abs(pdata->eq_cfg[i].rate - fs) < best_val) { | 
 | 1780 |                        best = i; | 
 | 1781 |                        best_val = abs(pdata->eq_cfg[i].rate - fs); | 
 | 1782 |                } | 
 | 1783 |        } | 
 | 1784 |  | 
 | 1785 |        dev_dbg(codec->dev, "Selected %s/%dHz for %dHz sample rate\n", | 
 | 1786 |                pdata->eq_cfg[best].name, | 
 | 1787 |                pdata->eq_cfg[best].rate, fs); | 
 | 1788 |  | 
 | 1789 |        /* Disable EQ while configuring, and save current on/off state */ | 
 | 1790 |        save = snd_soc_read(codec, M98088_REG_49_CFG_LEVEL); | 
 | 1791 |        snd_soc_update_bits(codec, M98088_REG_49_CFG_LEVEL, M98088_EQ2EN, 0); | 
 | 1792 |  | 
 | 1793 |        coef_set = &pdata->eq_cfg[sel]; | 
 | 1794 |  | 
 | 1795 |        m98088_eq_band(codec, 1, 0, coef_set->band1); | 
 | 1796 |        m98088_eq_band(codec, 1, 1, coef_set->band2); | 
 | 1797 |        m98088_eq_band(codec, 1, 2, coef_set->band3); | 
 | 1798 |        m98088_eq_band(codec, 1, 3, coef_set->band4); | 
 | 1799 |        m98088_eq_band(codec, 1, 4, coef_set->band5); | 
 | 1800 |  | 
 | 1801 |        /* Restore the original on/off state */ | 
 | 1802 |        snd_soc_update_bits(codec, M98088_REG_49_CFG_LEVEL, M98088_EQ2EN, | 
 | 1803 |                save); | 
 | 1804 | } | 
 | 1805 |  | 
 | 1806 | static int max98088_put_eq_enum(struct snd_kcontrol *kcontrol, | 
 | 1807 |                                 struct snd_ctl_elem_value *ucontrol) | 
 | 1808 | { | 
 | 1809 |        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | 
 | 1810 |        struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); | 
 | 1811 |        struct max98088_pdata *pdata = max98088->pdata; | 
 | 1812 |        int channel = max98088_get_channel(kcontrol->id.name); | 
 | 1813 |        struct max98088_cdata *cdata; | 
 | 1814 |        int sel = ucontrol->value.integer.value[0]; | 
 | 1815 |  | 
 | 1816 |        cdata = &max98088->dai[channel]; | 
 | 1817 |  | 
 | 1818 |        if (sel >= pdata->eq_cfgcnt) | 
 | 1819 |                return -EINVAL; | 
 | 1820 |  | 
 | 1821 |        cdata->eq_sel = sel; | 
 | 1822 |  | 
 | 1823 |        switch (channel) { | 
 | 1824 |        case 0: | 
 | 1825 |                max98088_setup_eq1(codec); | 
 | 1826 |                break; | 
 | 1827 |        case 1: | 
 | 1828 |                max98088_setup_eq2(codec); | 
 | 1829 |                break; | 
 | 1830 |        } | 
 | 1831 |  | 
 | 1832 |        return 0; | 
 | 1833 | } | 
 | 1834 |  | 
 | 1835 | static int max98088_get_eq_enum(struct snd_kcontrol *kcontrol, | 
 | 1836 |                                 struct snd_ctl_elem_value *ucontrol) | 
 | 1837 | { | 
 | 1838 |        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | 
 | 1839 |        struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); | 
 | 1840 |        int channel = max98088_get_channel(kcontrol->id.name); | 
 | 1841 |        struct max98088_cdata *cdata; | 
 | 1842 |  | 
 | 1843 |        cdata = &max98088->dai[channel]; | 
 | 1844 |        ucontrol->value.enumerated.item[0] = cdata->eq_sel; | 
 | 1845 |        return 0; | 
 | 1846 | } | 
 | 1847 |  | 
 | 1848 | static void max98088_handle_eq_pdata(struct snd_soc_codec *codec) | 
 | 1849 | { | 
 | 1850 |        struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); | 
 | 1851 |        struct max98088_pdata *pdata = max98088->pdata; | 
 | 1852 |        struct max98088_eq_cfg *cfg; | 
 | 1853 |        unsigned int cfgcnt; | 
 | 1854 |        int i, j; | 
 | 1855 |        const char **t; | 
 | 1856 |        int ret; | 
 | 1857 |  | 
 | 1858 |        struct snd_kcontrol_new controls[] = { | 
 | 1859 |                SOC_ENUM_EXT("EQ1 Mode", | 
 | 1860 |                        max98088->eq_enum, | 
 | 1861 |                        max98088_get_eq_enum, | 
 | 1862 |                        max98088_put_eq_enum), | 
 | 1863 |                SOC_ENUM_EXT("EQ2 Mode", | 
 | 1864 |                        max98088->eq_enum, | 
 | 1865 |                        max98088_get_eq_enum, | 
 | 1866 |                        max98088_put_eq_enum), | 
 | 1867 |        }; | 
 | 1868 |  | 
 | 1869 |        cfg = pdata->eq_cfg; | 
 | 1870 |        cfgcnt = pdata->eq_cfgcnt; | 
 | 1871 |  | 
 | 1872 |        /* Setup an array of texts for the equalizer enum. | 
 | 1873 |         * This is based on Mark Brown's equalizer driver code. | 
 | 1874 |         */ | 
 | 1875 |        max98088->eq_textcnt = 0; | 
 | 1876 |        max98088->eq_texts = NULL; | 
 | 1877 |        for (i = 0; i < cfgcnt; i++) { | 
 | 1878 |                for (j = 0; j < max98088->eq_textcnt; j++) { | 
 | 1879 |                        if (strcmp(cfg[i].name, max98088->eq_texts[j]) == 0) | 
 | 1880 |                                break; | 
 | 1881 |                } | 
 | 1882 |  | 
 | 1883 |                if (j != max98088->eq_textcnt) | 
 | 1884 |                        continue; | 
 | 1885 |  | 
 | 1886 |                /* Expand the array */ | 
 | 1887 |                t = krealloc(max98088->eq_texts, | 
 | 1888 |                             sizeof(char *) * (max98088->eq_textcnt + 1), | 
 | 1889 |                             GFP_KERNEL); | 
 | 1890 |                if (t == NULL) | 
 | 1891 |                        continue; | 
 | 1892 |  | 
 | 1893 |                /* Store the new entry */ | 
 | 1894 |                t[max98088->eq_textcnt] = cfg[i].name; | 
 | 1895 |                max98088->eq_textcnt++; | 
 | 1896 |                max98088->eq_texts = t; | 
 | 1897 |        } | 
 | 1898 |  | 
 | 1899 |        /* Now point the soc_enum to .texts array items */ | 
 | 1900 |        max98088->eq_enum.texts = max98088->eq_texts; | 
 | 1901 |        max98088->eq_enum.max = max98088->eq_textcnt; | 
 | 1902 |  | 
 | 1903 |        ret = snd_soc_add_controls(codec, controls, ARRAY_SIZE(controls)); | 
 | 1904 |        if (ret != 0) | 
 | 1905 |                dev_err(codec->dev, "Failed to add EQ control: %d\n", ret); | 
 | 1906 | } | 
 | 1907 |  | 
 | 1908 | static void max98088_handle_pdata(struct snd_soc_codec *codec) | 
 | 1909 | { | 
 | 1910 |        struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); | 
 | 1911 |        struct max98088_pdata *pdata = max98088->pdata; | 
 | 1912 |        u8 regval = 0; | 
 | 1913 |  | 
 | 1914 |        if (!pdata) { | 
 | 1915 |                dev_dbg(codec->dev, "No platform data\n"); | 
 | 1916 |                return; | 
 | 1917 |        } | 
 | 1918 |  | 
 | 1919 |        /* Configure mic for analog/digital mic mode */ | 
 | 1920 |        if (pdata->digmic_left_mode) | 
 | 1921 |                regval |= M98088_DIGMIC_L; | 
 | 1922 |  | 
 | 1923 |        if (pdata->digmic_right_mode) | 
 | 1924 |                regval |= M98088_DIGMIC_R; | 
 | 1925 |  | 
 | 1926 |        max98088->digmic = (regval ? 1 : 0); | 
 | 1927 |  | 
 | 1928 |        snd_soc_write(codec, M98088_REG_48_CFG_MIC, regval); | 
 | 1929 |  | 
 | 1930 |        /* Configure receiver output */ | 
 | 1931 |        regval = ((pdata->receiver_mode) ? M98088_REC_LINEMODE : 0); | 
 | 1932 |        snd_soc_update_bits(codec, M98088_REG_2A_MIC_REC_CNTL, | 
 | 1933 |                M98088_REC_LINEMODE_MASK, regval); | 
 | 1934 |  | 
 | 1935 |        /* Configure equalizers */ | 
 | 1936 |        if (pdata->eq_cfgcnt) | 
 | 1937 |                max98088_handle_eq_pdata(codec); | 
 | 1938 | } | 
 | 1939 |  | 
 | 1940 | #ifdef CONFIG_PM | 
 | 1941 | static int max98088_suspend(struct snd_soc_codec *codec, pm_message_t state) | 
 | 1942 | { | 
 | 1943 |        max98088_set_bias_level(codec, SND_SOC_BIAS_OFF); | 
 | 1944 |  | 
 | 1945 |        return 0; | 
 | 1946 | } | 
 | 1947 |  | 
 | 1948 | static int max98088_resume(struct snd_soc_codec *codec) | 
 | 1949 | { | 
 | 1950 |        max98088_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 
 | 1951 |  | 
 | 1952 |        return 0; | 
 | 1953 | } | 
 | 1954 | #else | 
 | 1955 | #define max98088_suspend NULL | 
 | 1956 | #define max98088_resume NULL | 
 | 1957 | #endif | 
 | 1958 |  | 
 | 1959 | static int max98088_probe(struct snd_soc_codec *codec) | 
 | 1960 | { | 
 | 1961 |        struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); | 
 | 1962 |        struct max98088_cdata *cdata; | 
 | 1963 |        int ret = 0; | 
 | 1964 |  | 
 | 1965 |        codec->cache_sync = 1; | 
| Mark Brown | e86e124 | 2010-10-18 16:45:24 -0700 | [diff] [blame] | 1966 |  | 
 | 1967 |        ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C); | 
 | 1968 |        if (ret != 0) { | 
 | 1969 |                dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | 
 | 1970 |                return ret; | 
 | 1971 |        } | 
 | 1972 |  | 
| Uwe Kleine-König | b595076 | 2010-11-01 15:38:34 -0400 | [diff] [blame] | 1973 |        /* initialize private data */ | 
| Mark Brown | e86e124 | 2010-10-18 16:45:24 -0700 | [diff] [blame] | 1974 |  | 
 | 1975 |        max98088->sysclk = (unsigned)-1; | 
 | 1976 |        max98088->eq_textcnt = 0; | 
 | 1977 |  | 
 | 1978 |        cdata = &max98088->dai[0]; | 
 | 1979 |        cdata->rate = (unsigned)-1; | 
 | 1980 |        cdata->fmt  = (unsigned)-1; | 
 | 1981 |        cdata->eq_sel = 0; | 
 | 1982 |  | 
 | 1983 |        cdata = &max98088->dai[1]; | 
 | 1984 |        cdata->rate = (unsigned)-1; | 
 | 1985 |        cdata->fmt  = (unsigned)-1; | 
 | 1986 |        cdata->eq_sel = 0; | 
 | 1987 |  | 
 | 1988 |        max98088->ina_state = 0; | 
 | 1989 |        max98088->inb_state = 0; | 
 | 1990 |        max98088->ex_mode = 0; | 
 | 1991 |        max98088->digmic = 0; | 
 | 1992 |        max98088->mic1pre = 0; | 
 | 1993 |        max98088->mic2pre = 0; | 
 | 1994 |  | 
 | 1995 |        ret = snd_soc_read(codec, M98088_REG_FF_REV_ID); | 
 | 1996 |        if (ret < 0) { | 
 | 1997 |                dev_err(codec->dev, "Failed to read device revision: %d\n", | 
 | 1998 |                        ret); | 
 | 1999 |                goto err_access; | 
 | 2000 |        } | 
 | 2001 |        dev_info(codec->dev, "revision %c\n", ret + 'A'); | 
 | 2002 |  | 
 | 2003 |        snd_soc_write(codec, M98088_REG_51_PWR_SYS, M98088_PWRSV); | 
 | 2004 |  | 
 | 2005 |        /* initialize registers cache to hardware default */ | 
 | 2006 |        max98088_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 
 | 2007 |  | 
 | 2008 |        snd_soc_write(codec, M98088_REG_0F_IRQ_ENABLE, 0x00); | 
 | 2009 |  | 
 | 2010 |        snd_soc_write(codec, M98088_REG_22_MIX_DAC, | 
 | 2011 |                M98088_DAI1L_TO_DACL|M98088_DAI2L_TO_DACL| | 
 | 2012 |                M98088_DAI1R_TO_DACR|M98088_DAI2R_TO_DACR); | 
 | 2013 |  | 
 | 2014 |        snd_soc_write(codec, M98088_REG_4E_BIAS_CNTL, 0xF0); | 
 | 2015 |        snd_soc_write(codec, M98088_REG_50_DAC_BIAS2, 0x0F); | 
 | 2016 |  | 
 | 2017 |        snd_soc_write(codec, M98088_REG_16_DAI1_IOCFG, | 
 | 2018 |                M98088_S1NORMAL|M98088_SDATA); | 
 | 2019 |  | 
 | 2020 |        snd_soc_write(codec, M98088_REG_1E_DAI2_IOCFG, | 
 | 2021 |                M98088_S2NORMAL|M98088_SDATA); | 
 | 2022 |  | 
 | 2023 |        max98088_handle_pdata(codec); | 
 | 2024 |  | 
| Lu Guanqun | dc6fc49 | 2011-03-30 21:53:10 +0800 | [diff] [blame] | 2025 |        snd_soc_add_controls(codec, max98088_snd_controls, | 
 | 2026 |                             ARRAY_SIZE(max98088_snd_controls)); | 
| Mark Brown | e86e124 | 2010-10-18 16:45:24 -0700 | [diff] [blame] | 2027 |  | 
 | 2028 | err_access: | 
 | 2029 |        return ret; | 
 | 2030 | } | 
 | 2031 |  | 
 | 2032 | static int max98088_remove(struct snd_soc_codec *codec) | 
 | 2033 | { | 
| Axel Lin | bc5954f | 2010-11-23 15:56:21 +0800 | [diff] [blame] | 2034 |        struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); | 
 | 2035 |  | 
| Mark Brown | e86e124 | 2010-10-18 16:45:24 -0700 | [diff] [blame] | 2036 |        max98088_set_bias_level(codec, SND_SOC_BIAS_OFF); | 
| Axel Lin | bc5954f | 2010-11-23 15:56:21 +0800 | [diff] [blame] | 2037 |        kfree(max98088->eq_texts); | 
| Mark Brown | e86e124 | 2010-10-18 16:45:24 -0700 | [diff] [blame] | 2038 |  | 
 | 2039 |        return 0; | 
 | 2040 | } | 
 | 2041 |  | 
 | 2042 | static struct snd_soc_codec_driver soc_codec_dev_max98088 = { | 
 | 2043 |        .probe   = max98088_probe, | 
 | 2044 |        .remove  = max98088_remove, | 
 | 2045 |        .suspend = max98088_suspend, | 
 | 2046 |        .resume  = max98088_resume, | 
 | 2047 |        .set_bias_level = max98088_set_bias_level, | 
 | 2048 |        .reg_cache_size = ARRAY_SIZE(max98088_reg), | 
 | 2049 |        .reg_word_size = sizeof(u8), | 
 | 2050 |        .reg_cache_default = max98088_reg, | 
 | 2051 |        .volatile_register = max98088_volatile_register, | 
| Lu Guanqun | dc6fc49 | 2011-03-30 21:53:10 +0800 | [diff] [blame] | 2052 | 	.dapm_widgets = max98088_dapm_widgets, | 
 | 2053 | 	.num_dapm_widgets = ARRAY_SIZE(max98088_dapm_widgets), | 
 | 2054 | 	.dapm_routes = max98088_audio_map, | 
 | 2055 | 	.num_dapm_routes = ARRAY_SIZE(max98088_audio_map), | 
| Mark Brown | e86e124 | 2010-10-18 16:45:24 -0700 | [diff] [blame] | 2056 | }; | 
 | 2057 |  | 
 | 2058 | static int max98088_i2c_probe(struct i2c_client *i2c, | 
 | 2059 |                             const struct i2c_device_id *id) | 
 | 2060 | { | 
 | 2061 |        struct max98088_priv *max98088; | 
 | 2062 |        int ret; | 
 | 2063 |  | 
 | 2064 |        max98088 = kzalloc(sizeof(struct max98088_priv), GFP_KERNEL); | 
 | 2065 |        if (max98088 == NULL) | 
 | 2066 |                return -ENOMEM; | 
 | 2067 |  | 
| Jesse Marroquin | fb762a5 | 2010-11-17 14:26:40 -0600 | [diff] [blame] | 2068 |        max98088->devtype = id->driver_data; | 
 | 2069 |  | 
| Mark Brown | e86e124 | 2010-10-18 16:45:24 -0700 | [diff] [blame] | 2070 |        i2c_set_clientdata(i2c, max98088); | 
 | 2071 |        max98088->control_data = i2c; | 
 | 2072 |        max98088->pdata = i2c->dev.platform_data; | 
 | 2073 |  | 
 | 2074 |        ret = snd_soc_register_codec(&i2c->dev, | 
 | 2075 |                        &soc_codec_dev_max98088, &max98088_dai[0], 2); | 
 | 2076 |        if (ret < 0) | 
 | 2077 |                kfree(max98088); | 
 | 2078 |        return ret; | 
 | 2079 | } | 
 | 2080 |  | 
| Arnaud Lacombe | f3607ae | 2010-10-26 16:04:35 -0400 | [diff] [blame] | 2081 | static int __devexit max98088_i2c_remove(struct i2c_client *client) | 
| Mark Brown | e86e124 | 2010-10-18 16:45:24 -0700 | [diff] [blame] | 2082 | { | 
 | 2083 |        snd_soc_unregister_codec(&client->dev); | 
 | 2084 |        kfree(i2c_get_clientdata(client)); | 
 | 2085 |        return 0; | 
 | 2086 | } | 
 | 2087 |  | 
 | 2088 | static const struct i2c_device_id max98088_i2c_id[] = { | 
| Jesse Marroquin | fb762a5 | 2010-11-17 14:26:40 -0600 | [diff] [blame] | 2089 |        { "max98088", MAX98088 }, | 
 | 2090 |        { "max98089", MAX98089 }, | 
| Mark Brown | e86e124 | 2010-10-18 16:45:24 -0700 | [diff] [blame] | 2091 |        { } | 
 | 2092 | }; | 
 | 2093 | MODULE_DEVICE_TABLE(i2c, max98088_i2c_id); | 
 | 2094 |  | 
 | 2095 | static struct i2c_driver max98088_i2c_driver = { | 
 | 2096 |        .driver = { | 
 | 2097 |                .name = "max98088", | 
 | 2098 |                .owner = THIS_MODULE, | 
 | 2099 |        }, | 
 | 2100 |        .probe  = max98088_i2c_probe, | 
 | 2101 |        .remove = __devexit_p(max98088_i2c_remove), | 
 | 2102 |        .id_table = max98088_i2c_id, | 
 | 2103 | }; | 
 | 2104 |  | 
 | 2105 | static int __init max98088_init(void) | 
 | 2106 | { | 
 | 2107 |        int ret; | 
 | 2108 |  | 
 | 2109 |        ret = i2c_add_driver(&max98088_i2c_driver); | 
 | 2110 |        if (ret) | 
 | 2111 |                pr_err("Failed to register max98088 I2C driver: %d\n", ret); | 
 | 2112 |  | 
 | 2113 |        return ret; | 
 | 2114 | } | 
 | 2115 | module_init(max98088_init); | 
 | 2116 |  | 
 | 2117 | static void __exit max98088_exit(void) | 
 | 2118 | { | 
 | 2119 |        i2c_del_driver(&max98088_i2c_driver); | 
 | 2120 | } | 
 | 2121 | module_exit(max98088_exit); | 
 | 2122 |  | 
 | 2123 | MODULE_DESCRIPTION("ALSA SoC MAX98088 driver"); | 
 | 2124 | MODULE_AUTHOR("Peter Hsiang, Jesse Marroquin"); | 
 | 2125 | MODULE_LICENSE("GPL"); |