Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ASoC: Restore MAX98088 CODEC driver

This reverts commit f6765502f8daae3d237a394889276c8987f3e299 and adds
the missing include file.

Signed-off-by: Peter Hsiang <Peter.Hsiang@maxim-ic.com>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>

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