diff options
| author | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2010-10-18 19:45:24 -0400 |
|---|---|---|
| committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2010-10-18 19:46:27 -0400 |
| commit | e86e1244a41352d1b78d32c10316fc4df2c86a8a (patch) | |
| tree | 766af885db3341cf049f586dfab528d1c0d9c428 | |
| parent | 02ffc5f3f91c265e110ddd1fdd7019a18426ebe5 (diff) | |
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>
| -rw-r--r-- | include/sound/max98088.h | 50 | ||||
| -rw-r--r-- | sound/soc/codecs/Kconfig | 4 | ||||
| -rw-r--r-- | sound/soc/codecs/Makefile | 2 | ||||
| -rw-r--r-- | sound/soc/codecs/max98088.c | 2097 | ||||
| -rw-r--r-- | sound/soc/codecs/max98088.h | 193 |
5 files changed, 2346 insertions, 0 deletions
diff --git a/include/sound/max98088.h b/include/sound/max98088.h new file mode 100644 index 000000000000..c3ba8239182d --- /dev/null +++ b/include/sound/max98088.h | |||
| @@ -0,0 +1,50 @@ | |||
| 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 | ||
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index ff7b922a0f41..94a9d06b9027 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig | |||
| @@ -27,6 +27,7 @@ config SND_SOC_ALL_CODECS | |||
| 27 | select SND_SOC_CS4270 if I2C | 27 | select SND_SOC_CS4270 if I2C |
| 28 | select SND_SOC_DA7210 if I2C | 28 | select SND_SOC_DA7210 if I2C |
| 29 | select SND_SOC_JZ4740 if SOC_JZ4740 | 29 | select SND_SOC_JZ4740 if SOC_JZ4740 |
| 30 | select SND_SOC_MAX98088 if I2C | ||
| 30 | select SND_SOC_MAX9877 if I2C | 31 | select SND_SOC_MAX9877 if I2C |
| 31 | select SND_SOC_PCM3008 | 32 | select SND_SOC_PCM3008 |
| 32 | select SND_SOC_SPDIF | 33 | select SND_SOC_SPDIF |
| @@ -158,6 +159,9 @@ config SND_SOC_L3 | |||
| 158 | config SND_SOC_DA7210 | 159 | config SND_SOC_DA7210 |
| 159 | tristate | 160 | tristate |
| 160 | 161 | ||
| 162 | config SND_SOC_MAX98088 | ||
| 163 | tristate | ||
| 164 | |||
| 161 | config SND_SOC_PCM3008 | 165 | config SND_SOC_PCM3008 |
| 162 | tristate | 166 | tristate |
| 163 | 167 | ||
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index af4d4c4e17b4..f67a2d6f7a46 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile | |||
| @@ -15,6 +15,7 @@ snd-soc-cs4270-objs := cs4270.o | |||
| 15 | snd-soc-cx20442-objs := cx20442.o | 15 | snd-soc-cx20442-objs := cx20442.o |
| 16 | snd-soc-da7210-objs := da7210.o | 16 | snd-soc-da7210-objs := da7210.o |
| 17 | snd-soc-l3-objs := l3.o | 17 | snd-soc-l3-objs := l3.o |
| 18 | snd-soc-max98088-objs := max98088.o | ||
| 18 | snd-soc-pcm3008-objs := pcm3008.o | 19 | snd-soc-pcm3008-objs := pcm3008.o |
| 19 | snd-soc-spdif-objs := spdif_transciever.o | 20 | snd-soc-spdif-objs := spdif_transciever.o |
| 20 | snd-soc-ssm2602-objs := ssm2602.o | 21 | snd-soc-ssm2602-objs := ssm2602.o |
| @@ -89,6 +90,7 @@ obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o | |||
| 89 | obj-$(CONFIG_SND_SOC_DA7210) += snd-soc-da7210.o | 90 | obj-$(CONFIG_SND_SOC_DA7210) += snd-soc-da7210.o |
| 90 | obj-$(CONFIG_SND_SOC_L3) += snd-soc-l3.o | 91 | obj-$(CONFIG_SND_SOC_L3) += snd-soc-l3.o |
| 91 | obj-$(CONFIG_SND_SOC_JZ4740_CODEC) += snd-soc-jz4740-codec.o | 92 | obj-$(CONFIG_SND_SOC_JZ4740_CODEC) += snd-soc-jz4740-codec.o |
| 93 | obj-$(CONFIG_SND_SOC_MAX98088) += snd-soc-max98088.o | ||
| 92 | obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o | 94 | obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o |
| 93 | obj-$(CONFIG_SND_SOC_SPDIF) += snd-soc-spdif.o | 95 | obj-$(CONFIG_SND_SOC_SPDIF) += snd-soc-spdif.o |
| 94 | obj-$(CONFIG_SND_SOC_SSM2602) += snd-soc-ssm2602.o | 96 | obj-$(CONFIG_SND_SOC_SSM2602) += snd-soc-ssm2602.o |
diff --git a/sound/soc/codecs/max98088.c b/sound/soc/codecs/max98088.c new file mode 100644 index 000000000000..4186b2755a58 --- /dev/null +++ b/sound/soc/codecs/max98088.c | |||
| @@ -0,0 +1,2097 @@ | |||
| 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, ®val)) | ||
| 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, ®val)) | ||
| 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"); | ||
diff --git a/sound/soc/codecs/max98088.h b/sound/soc/codecs/max98088.h new file mode 100644 index 000000000000..56554c797fef --- /dev/null +++ b/sound/soc/codecs/max98088.h | |||
| @@ -0,0 +1,193 @@ | |||
| 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 | ||
