diff options
author | Bard Liao <bardliao@realtek.com> | 2015-06-25 22:59:49 -0400 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2015-07-09 07:00:11 -0400 |
commit | 6adcafae6ed20fe380addc8e7c628e529751ade3 (patch) | |
tree | 700e3b0f1aec8a5160d9f19c0ab627cfa7cdb9d0 | |
parent | d770e558e21961ad6cfdf0ff7df0eb5d7d4f0754 (diff) |
ASoC: add rt298 codec driver
It is the initial version of ALC298 codec driver.
Signed-off-by: Bard Liao <bardliao@realtek.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r-- | include/sound/rt298.h | 20 | ||||
-rw-r--r-- | sound/soc/codecs/Kconfig | 7 | ||||
-rw-r--r-- | sound/soc/codecs/Makefile | 2 | ||||
-rw-r--r-- | sound/soc/codecs/rt298.c | 1274 | ||||
-rw-r--r-- | sound/soc/codecs/rt298.h | 206 |
5 files changed, 1509 insertions, 0 deletions
diff --git a/include/sound/rt298.h b/include/sound/rt298.h new file mode 100644 index 000000000000..7fffeaa84f64 --- /dev/null +++ b/include/sound/rt298.h | |||
@@ -0,0 +1,20 @@ | |||
1 | /* | ||
2 | * linux/sound/rt286.h -- Platform data for RT286 | ||
3 | * | ||
4 | * Copyright 2013 Realtek Microelectronics | ||
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 __LINUX_SND_RT298_H | ||
12 | #define __LINUX_SND_RT298_H | ||
13 | |||
14 | struct rt298_platform_data { | ||
15 | bool cbj_en; /*combo jack enable*/ | ||
16 | bool gpio2_en; /*GPIO2 enable*/ | ||
17 | bool suspend_power_off; /* power is off during suspend */ | ||
18 | }; | ||
19 | |||
20 | #endif | ||
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index efaafce8ba38..76125a281557 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig | |||
@@ -83,6 +83,7 @@ config SND_SOC_ALL_CODECS | |||
83 | select SND_SOC_PCM512x_I2C if I2C | 83 | select SND_SOC_PCM512x_I2C if I2C |
84 | select SND_SOC_PCM512x_SPI if SPI_MASTER | 84 | select SND_SOC_PCM512x_SPI if SPI_MASTER |
85 | select SND_SOC_RT286 if I2C | 85 | select SND_SOC_RT286 if I2C |
86 | select SND_SOC_RT298 if I2C | ||
86 | select SND_SOC_RT5631 if I2C | 87 | select SND_SOC_RT5631 if I2C |
87 | select SND_SOC_RT5640 if I2C | 88 | select SND_SOC_RT5640 if I2C |
88 | select SND_SOC_RT5645 if I2C | 89 | select SND_SOC_RT5645 if I2C |
@@ -512,12 +513,18 @@ config SND_SOC_RL6231 | |||
512 | config SND_SOC_RL6347A | 513 | config SND_SOC_RL6347A |
513 | tristate | 514 | tristate |
514 | default y if SND_SOC_RT286=y | 515 | default y if SND_SOC_RT286=y |
516 | default y if SND_SOC_RT298=y | ||
515 | default m if SND_SOC_RT286=m | 517 | default m if SND_SOC_RT286=m |
518 | default m if SND_SOC_RT298=m | ||
516 | 519 | ||
517 | config SND_SOC_RT286 | 520 | config SND_SOC_RT286 |
518 | tristate | 521 | tristate |
519 | depends on I2C | 522 | depends on I2C |
520 | 523 | ||
524 | config SND_SOC_RT298 | ||
525 | tristate | ||
526 | depends on I2C | ||
527 | |||
521 | config SND_SOC_RT5631 | 528 | config SND_SOC_RT5631 |
522 | tristate "Realtek ALC5631/RT5631 CODEC" | 529 | tristate "Realtek ALC5631/RT5631 CODEC" |
523 | depends on I2C | 530 | depends on I2C |
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index cf160d972cb3..3b58c4571859 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile | |||
@@ -79,6 +79,7 @@ snd-soc-pcm512x-spi-objs := pcm512x-spi.o | |||
79 | snd-soc-rl6231-objs := rl6231.o | 79 | snd-soc-rl6231-objs := rl6231.o |
80 | snd-soc-rl6347a-objs := rl6347a.o | 80 | snd-soc-rl6347a-objs := rl6347a.o |
81 | snd-soc-rt286-objs := rt286.o | 81 | snd-soc-rt286-objs := rt286.o |
82 | snd-soc-rt298-objs := rt298.o | ||
82 | snd-soc-rt5631-objs := rt5631.o | 83 | snd-soc-rt5631-objs := rt5631.o |
83 | snd-soc-rt5640-objs := rt5640.o | 84 | snd-soc-rt5640-objs := rt5640.o |
84 | snd-soc-rt5645-objs := rt5645.o | 85 | snd-soc-rt5645-objs := rt5645.o |
@@ -266,6 +267,7 @@ obj-$(CONFIG_SND_SOC_PCM512x_SPI) += snd-soc-pcm512x-spi.o | |||
266 | obj-$(CONFIG_SND_SOC_RL6231) += snd-soc-rl6231.o | 267 | obj-$(CONFIG_SND_SOC_RL6231) += snd-soc-rl6231.o |
267 | obj-$(CONFIG_SND_SOC_RL6347A) += snd-soc-rl6347a.o | 268 | obj-$(CONFIG_SND_SOC_RL6347A) += snd-soc-rl6347a.o |
268 | obj-$(CONFIG_SND_SOC_RT286) += snd-soc-rt286.o | 269 | obj-$(CONFIG_SND_SOC_RT286) += snd-soc-rt286.o |
270 | obj-$(CONFIG_SND_SOC_RT298) += snd-soc-rt298.o | ||
269 | obj-$(CONFIG_SND_SOC_RT5631) += snd-soc-rt5631.o | 271 | obj-$(CONFIG_SND_SOC_RT5631) += snd-soc-rt5631.o |
270 | obj-$(CONFIG_SND_SOC_RT5640) += snd-soc-rt5640.o | 272 | obj-$(CONFIG_SND_SOC_RT5640) += snd-soc-rt5640.o |
271 | obj-$(CONFIG_SND_SOC_RT5645) += snd-soc-rt5645.o | 273 | obj-$(CONFIG_SND_SOC_RT5645) += snd-soc-rt5645.o |
diff --git a/sound/soc/codecs/rt298.c b/sound/soc/codecs/rt298.c new file mode 100644 index 000000000000..7c4bcb65ef2c --- /dev/null +++ b/sound/soc/codecs/rt298.c | |||
@@ -0,0 +1,1274 @@ | |||
1 | /* | ||
2 | * rt298.c -- RT298 ALSA SoC audio codec driver | ||
3 | * | ||
4 | * Copyright 2015 Realtek Semiconductor Corp. | ||
5 | * Author: Bard Liao <bardliao@realtek.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #include <linux/module.h> | ||
13 | #include <linux/moduleparam.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 <linux/spi/spi.h> | ||
20 | #include <linux/acpi.h> | ||
21 | #include <sound/core.h> | ||
22 | #include <sound/pcm.h> | ||
23 | #include <sound/pcm_params.h> | ||
24 | #include <sound/soc.h> | ||
25 | #include <sound/soc-dapm.h> | ||
26 | #include <sound/initval.h> | ||
27 | #include <sound/tlv.h> | ||
28 | #include <sound/jack.h> | ||
29 | #include <linux/workqueue.h> | ||
30 | #include <sound/rt298.h> | ||
31 | #include <sound/hda_verbs.h> | ||
32 | |||
33 | #include "rl6347a.h" | ||
34 | #include "rt298.h" | ||
35 | |||
36 | #define RT298_VENDOR_ID 0x10ec0298 | ||
37 | |||
38 | struct rt298_priv { | ||
39 | struct reg_default *index_cache; | ||
40 | int index_cache_size; | ||
41 | struct regmap *regmap; | ||
42 | struct snd_soc_codec *codec; | ||
43 | struct rt298_platform_data pdata; | ||
44 | struct i2c_client *i2c; | ||
45 | struct snd_soc_jack *jack; | ||
46 | struct delayed_work jack_detect_work; | ||
47 | int sys_clk; | ||
48 | int clk_id; | ||
49 | int is_hp_in; | ||
50 | }; | ||
51 | |||
52 | static struct reg_default rt298_index_def[] = { | ||
53 | { 0x01, 0xaaaa }, | ||
54 | { 0x02, 0x8aaa }, | ||
55 | { 0x03, 0x0002 }, | ||
56 | { 0x04, 0xaf01 }, | ||
57 | { 0x08, 0x000d }, | ||
58 | { 0x09, 0xd810 }, | ||
59 | { 0x0a, 0x0120 }, | ||
60 | { 0x0b, 0x0000 }, | ||
61 | { 0x0d, 0x2800 }, | ||
62 | { 0x0f, 0x0000 }, | ||
63 | { 0x19, 0x0a17 }, | ||
64 | { 0x20, 0x0020 }, | ||
65 | { 0x33, 0x0208 }, | ||
66 | { 0x46, 0x0300 }, | ||
67 | { 0x49, 0x0004 }, | ||
68 | { 0x4f, 0x50e9 }, | ||
69 | { 0x50, 0x2000 }, | ||
70 | { 0x63, 0x2902 }, | ||
71 | { 0x67, 0x1111 }, | ||
72 | { 0x68, 0x1016 }, | ||
73 | { 0x69, 0x273f }, | ||
74 | }; | ||
75 | #define INDEX_CACHE_SIZE ARRAY_SIZE(rt298_index_def) | ||
76 | |||
77 | static const struct reg_default rt298_reg[] = { | ||
78 | { 0x00170500, 0x00000400 }, | ||
79 | { 0x00220000, 0x00000031 }, | ||
80 | { 0x00239000, 0x0000007f }, | ||
81 | { 0x0023a000, 0x0000007f }, | ||
82 | { 0x00270500, 0x00000400 }, | ||
83 | { 0x00370500, 0x00000400 }, | ||
84 | { 0x00870500, 0x00000400 }, | ||
85 | { 0x00920000, 0x00000031 }, | ||
86 | { 0x00935000, 0x000000c3 }, | ||
87 | { 0x00936000, 0x000000c3 }, | ||
88 | { 0x00970500, 0x00000400 }, | ||
89 | { 0x00b37000, 0x00000097 }, | ||
90 | { 0x00b37200, 0x00000097 }, | ||
91 | { 0x00b37300, 0x00000097 }, | ||
92 | { 0x00c37000, 0x00000000 }, | ||
93 | { 0x00c37100, 0x00000080 }, | ||
94 | { 0x01270500, 0x00000400 }, | ||
95 | { 0x01370500, 0x00000400 }, | ||
96 | { 0x01371f00, 0x411111f0 }, | ||
97 | { 0x01439000, 0x00000080 }, | ||
98 | { 0x0143a000, 0x00000080 }, | ||
99 | { 0x01470700, 0x00000000 }, | ||
100 | { 0x01470500, 0x00000400 }, | ||
101 | { 0x01470c00, 0x00000000 }, | ||
102 | { 0x01470100, 0x00000000 }, | ||
103 | { 0x01837000, 0x00000000 }, | ||
104 | { 0x01870500, 0x00000400 }, | ||
105 | { 0x02050000, 0x00000000 }, | ||
106 | { 0x02139000, 0x00000080 }, | ||
107 | { 0x0213a000, 0x00000080 }, | ||
108 | { 0x02170100, 0x00000000 }, | ||
109 | { 0x02170500, 0x00000400 }, | ||
110 | { 0x02170700, 0x00000000 }, | ||
111 | { 0x02270100, 0x00000000 }, | ||
112 | { 0x02370100, 0x00000000 }, | ||
113 | { 0x01870700, 0x00000020 }, | ||
114 | { 0x00830000, 0x000000c3 }, | ||
115 | { 0x00930000, 0x000000c3 }, | ||
116 | { 0x01270700, 0x00000000 }, | ||
117 | }; | ||
118 | |||
119 | static bool rt298_volatile_register(struct device *dev, unsigned int reg) | ||
120 | { | ||
121 | switch (reg) { | ||
122 | case 0 ... 0xff: | ||
123 | case RT298_GET_PARAM(AC_NODE_ROOT, AC_PAR_VENDOR_ID): | ||
124 | case RT298_GET_HP_SENSE: | ||
125 | case RT298_GET_MIC1_SENSE: | ||
126 | case RT298_PROC_COEF: | ||
127 | case VERB_CMD(AC_VERB_GET_EAPD_BTLENABLE, RT298_MIC1, 0): | ||
128 | case VERB_CMD(AC_VERB_GET_EAPD_BTLENABLE, RT298_SPK_OUT, 0): | ||
129 | case VERB_CMD(AC_VERB_GET_EAPD_BTLENABLE, RT298_HP_OUT, 0): | ||
130 | return true; | ||
131 | default: | ||
132 | return true; | ||
133 | } | ||
134 | |||
135 | |||
136 | } | ||
137 | |||
138 | static bool rt298_readable_register(struct device *dev, unsigned int reg) | ||
139 | { | ||
140 | switch (reg) { | ||
141 | case 0 ... 0xff: | ||
142 | case RT298_GET_PARAM(AC_NODE_ROOT, AC_PAR_VENDOR_ID): | ||
143 | case RT298_GET_HP_SENSE: | ||
144 | case RT298_GET_MIC1_SENSE: | ||
145 | case RT298_SET_AUDIO_POWER: | ||
146 | case RT298_SET_HPO_POWER: | ||
147 | case RT298_SET_SPK_POWER: | ||
148 | case RT298_SET_DMIC1_POWER: | ||
149 | case RT298_SPK_MUX: | ||
150 | case RT298_HPO_MUX: | ||
151 | case RT298_ADC0_MUX: | ||
152 | case RT298_ADC1_MUX: | ||
153 | case RT298_SET_MIC1: | ||
154 | case RT298_SET_PIN_HPO: | ||
155 | case RT298_SET_PIN_SPK: | ||
156 | case RT298_SET_PIN_DMIC1: | ||
157 | case RT298_SPK_EAPD: | ||
158 | case RT298_SET_AMP_GAIN_HPO: | ||
159 | case RT298_SET_DMIC2_DEFAULT: | ||
160 | case RT298_DACL_GAIN: | ||
161 | case RT298_DACR_GAIN: | ||
162 | case RT298_ADCL_GAIN: | ||
163 | case RT298_ADCR_GAIN: | ||
164 | case RT298_MIC_GAIN: | ||
165 | case RT298_SPOL_GAIN: | ||
166 | case RT298_SPOR_GAIN: | ||
167 | case RT298_HPOL_GAIN: | ||
168 | case RT298_HPOR_GAIN: | ||
169 | case RT298_F_DAC_SWITCH: | ||
170 | case RT298_F_RECMIX_SWITCH: | ||
171 | case RT298_REC_MIC_SWITCH: | ||
172 | case RT298_REC_I2S_SWITCH: | ||
173 | case RT298_REC_LINE_SWITCH: | ||
174 | case RT298_REC_BEEP_SWITCH: | ||
175 | case RT298_DAC_FORMAT: | ||
176 | case RT298_ADC_FORMAT: | ||
177 | case RT298_COEF_INDEX: | ||
178 | case RT298_PROC_COEF: | ||
179 | case RT298_SET_AMP_GAIN_ADC_IN1: | ||
180 | case RT298_SET_AMP_GAIN_ADC_IN2: | ||
181 | case RT298_SET_POWER(RT298_DAC_OUT1): | ||
182 | case RT298_SET_POWER(RT298_DAC_OUT2): | ||
183 | case RT298_SET_POWER(RT298_ADC_IN1): | ||
184 | case RT298_SET_POWER(RT298_ADC_IN2): | ||
185 | case RT298_SET_POWER(RT298_DMIC2): | ||
186 | case RT298_SET_POWER(RT298_MIC1): | ||
187 | case VERB_CMD(AC_VERB_GET_EAPD_BTLENABLE, RT298_MIC1, 0): | ||
188 | case VERB_CMD(AC_VERB_GET_EAPD_BTLENABLE, RT298_SPK_OUT, 0): | ||
189 | case VERB_CMD(AC_VERB_GET_EAPD_BTLENABLE, RT298_HP_OUT, 0): | ||
190 | return true; | ||
191 | default: | ||
192 | return false; | ||
193 | } | ||
194 | } | ||
195 | |||
196 | #ifdef CONFIG_PM | ||
197 | static void rt298_index_sync(struct snd_soc_codec *codec) | ||
198 | { | ||
199 | struct rt298_priv *rt298 = snd_soc_codec_get_drvdata(codec); | ||
200 | int i; | ||
201 | |||
202 | for (i = 0; i < INDEX_CACHE_SIZE; i++) { | ||
203 | snd_soc_write(codec, rt298->index_cache[i].reg, | ||
204 | rt298->index_cache[i].def); | ||
205 | } | ||
206 | } | ||
207 | #endif | ||
208 | |||
209 | static int rt298_support_power_controls[] = { | ||
210 | RT298_DAC_OUT1, | ||
211 | RT298_DAC_OUT2, | ||
212 | RT298_ADC_IN1, | ||
213 | RT298_ADC_IN2, | ||
214 | RT298_MIC1, | ||
215 | RT298_DMIC1, | ||
216 | RT298_DMIC2, | ||
217 | RT298_SPK_OUT, | ||
218 | RT298_HP_OUT, | ||
219 | }; | ||
220 | #define RT298_POWER_REG_LEN ARRAY_SIZE(rt298_support_power_controls) | ||
221 | |||
222 | static int rt298_jack_detect(struct rt298_priv *rt298, bool *hp, bool *mic) | ||
223 | { | ||
224 | struct snd_soc_dapm_context *dapm; | ||
225 | unsigned int val, buf; | ||
226 | |||
227 | *hp = false; | ||
228 | *mic = false; | ||
229 | |||
230 | if (!rt298->codec) | ||
231 | return -EINVAL; | ||
232 | |||
233 | dapm = snd_soc_codec_get_dapm(rt298->codec); | ||
234 | |||
235 | if (rt298->pdata.cbj_en) { | ||
236 | regmap_read(rt298->regmap, RT298_GET_HP_SENSE, &buf); | ||
237 | *hp = buf & 0x80000000; | ||
238 | if (*hp == rt298->is_hp_in) | ||
239 | return -1; | ||
240 | rt298->is_hp_in = *hp; | ||
241 | if (*hp) { | ||
242 | /* power on HV,VERF */ | ||
243 | regmap_update_bits(rt298->regmap, | ||
244 | RT298_DC_GAIN, 0x200, 0x200); | ||
245 | |||
246 | snd_soc_dapm_force_enable_pin(dapm, "HV"); | ||
247 | snd_soc_dapm_force_enable_pin(dapm, "VREF"); | ||
248 | /* power LDO1 */ | ||
249 | snd_soc_dapm_force_enable_pin(dapm, "LDO1"); | ||
250 | snd_soc_dapm_sync(dapm); | ||
251 | |||
252 | regmap_write(rt298->regmap, RT298_SET_MIC1, 0x24); | ||
253 | msleep(50); | ||
254 | |||
255 | regmap_update_bits(rt298->regmap, | ||
256 | RT298_CBJ_CTRL1, 0xfcc0, 0xd400); | ||
257 | msleep(300); | ||
258 | regmap_read(rt298->regmap, RT298_CBJ_CTRL2, &val); | ||
259 | |||
260 | if (0x0070 == (val & 0x0070)) { | ||
261 | *mic = true; | ||
262 | } else { | ||
263 | regmap_update_bits(rt298->regmap, | ||
264 | RT298_CBJ_CTRL1, 0xfcc0, 0xe400); | ||
265 | msleep(300); | ||
266 | regmap_read(rt298->regmap, | ||
267 | RT298_CBJ_CTRL2, &val); | ||
268 | if (0x0070 == (val & 0x0070)) | ||
269 | *mic = true; | ||
270 | else | ||
271 | *mic = false; | ||
272 | } | ||
273 | regmap_update_bits(rt298->regmap, | ||
274 | RT298_DC_GAIN, 0x200, 0x0); | ||
275 | |||
276 | } else { | ||
277 | *mic = false; | ||
278 | regmap_write(rt298->regmap, RT298_SET_MIC1, 0x20); | ||
279 | } | ||
280 | } else { | ||
281 | regmap_read(rt298->regmap, RT298_GET_HP_SENSE, &buf); | ||
282 | *hp = buf & 0x80000000; | ||
283 | regmap_read(rt298->regmap, RT298_GET_MIC1_SENSE, &buf); | ||
284 | *mic = buf & 0x80000000; | ||
285 | } | ||
286 | |||
287 | snd_soc_dapm_disable_pin(dapm, "HV"); | ||
288 | snd_soc_dapm_disable_pin(dapm, "VREF"); | ||
289 | if (!*hp) | ||
290 | snd_soc_dapm_disable_pin(dapm, "LDO1"); | ||
291 | snd_soc_dapm_sync(dapm); | ||
292 | |||
293 | pr_debug("*hp = %d *mic = %d\n", *hp, *mic); | ||
294 | |||
295 | return 0; | ||
296 | } | ||
297 | |||
298 | static void rt298_jack_detect_work(struct work_struct *work) | ||
299 | { | ||
300 | struct rt298_priv *rt298 = | ||
301 | container_of(work, struct rt298_priv, jack_detect_work.work); | ||
302 | int status = 0; | ||
303 | bool hp = false; | ||
304 | bool mic = false; | ||
305 | |||
306 | if (rt298_jack_detect(rt298, &hp, &mic) < 0) | ||
307 | return; | ||
308 | |||
309 | if (hp == true) | ||
310 | status |= SND_JACK_HEADPHONE; | ||
311 | |||
312 | if (mic == true) | ||
313 | status |= SND_JACK_MICROPHONE; | ||
314 | |||
315 | snd_soc_jack_report(rt298->jack, status, | ||
316 | SND_JACK_MICROPHONE | SND_JACK_HEADPHONE); | ||
317 | } | ||
318 | |||
319 | int rt298_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack) | ||
320 | { | ||
321 | struct rt298_priv *rt298 = snd_soc_codec_get_drvdata(codec); | ||
322 | |||
323 | rt298->jack = jack; | ||
324 | |||
325 | /* Send an initial empty report */ | ||
326 | snd_soc_jack_report(rt298->jack, 0, | ||
327 | SND_JACK_MICROPHONE | SND_JACK_HEADPHONE); | ||
328 | |||
329 | return 0; | ||
330 | } | ||
331 | EXPORT_SYMBOL_GPL(rt298_mic_detect); | ||
332 | |||
333 | static int is_mclk_mode(struct snd_soc_dapm_widget *source, | ||
334 | struct snd_soc_dapm_widget *sink) | ||
335 | { | ||
336 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(source->dapm); | ||
337 | struct rt298_priv *rt298 = snd_soc_codec_get_drvdata(codec); | ||
338 | |||
339 | if (rt298->clk_id == RT298_SCLK_S_MCLK) | ||
340 | return 1; | ||
341 | else | ||
342 | return 0; | ||
343 | } | ||
344 | |||
345 | static const DECLARE_TLV_DB_SCALE(out_vol_tlv, -6350, 50, 0); | ||
346 | static const DECLARE_TLV_DB_SCALE(mic_vol_tlv, 0, 1000, 0); | ||
347 | |||
348 | static const struct snd_kcontrol_new rt298_snd_controls[] = { | ||
349 | SOC_DOUBLE_R_TLV("DAC0 Playback Volume", RT298_DACL_GAIN, | ||
350 | RT298_DACR_GAIN, 0, 0x7f, 0, out_vol_tlv), | ||
351 | SOC_DOUBLE_R_TLV("ADC0 Capture Volume", RT298_ADCL_GAIN, | ||
352 | RT298_ADCR_GAIN, 0, 0x7f, 0, out_vol_tlv), | ||
353 | SOC_SINGLE_TLV("AMIC Volume", RT298_MIC_GAIN, | ||
354 | 0, 0x3, 0, mic_vol_tlv), | ||
355 | SOC_DOUBLE_R("Speaker Playback Switch", RT298_SPOL_GAIN, | ||
356 | RT298_SPOR_GAIN, RT298_MUTE_SFT, 1, 1), | ||
357 | }; | ||
358 | |||
359 | /* Digital Mixer */ | ||
360 | static const struct snd_kcontrol_new rt298_front_mix[] = { | ||
361 | SOC_DAPM_SINGLE("DAC Switch", RT298_F_DAC_SWITCH, | ||
362 | RT298_MUTE_SFT, 1, 1), | ||
363 | SOC_DAPM_SINGLE("RECMIX Switch", RT298_F_RECMIX_SWITCH, | ||
364 | RT298_MUTE_SFT, 1, 1), | ||
365 | }; | ||
366 | |||
367 | /* Analog Input Mixer */ | ||
368 | static const struct snd_kcontrol_new rt298_rec_mix[] = { | ||
369 | SOC_DAPM_SINGLE("Mic1 Switch", RT298_REC_MIC_SWITCH, | ||
370 | RT298_MUTE_SFT, 1, 1), | ||
371 | SOC_DAPM_SINGLE("I2S Switch", RT298_REC_I2S_SWITCH, | ||
372 | RT298_MUTE_SFT, 1, 1), | ||
373 | SOC_DAPM_SINGLE("Line1 Switch", RT298_REC_LINE_SWITCH, | ||
374 | RT298_MUTE_SFT, 1, 1), | ||
375 | SOC_DAPM_SINGLE("Beep Switch", RT298_REC_BEEP_SWITCH, | ||
376 | RT298_MUTE_SFT, 1, 1), | ||
377 | }; | ||
378 | |||
379 | static const struct snd_kcontrol_new spo_enable_control = | ||
380 | SOC_DAPM_SINGLE("Switch", RT298_SET_PIN_SPK, | ||
381 | RT298_SET_PIN_SFT, 1, 0); | ||
382 | |||
383 | static const struct snd_kcontrol_new hpol_enable_control = | ||
384 | SOC_DAPM_SINGLE_AUTODISABLE("Switch", RT298_HPOL_GAIN, | ||
385 | RT298_MUTE_SFT, 1, 1); | ||
386 | |||
387 | static const struct snd_kcontrol_new hpor_enable_control = | ||
388 | SOC_DAPM_SINGLE_AUTODISABLE("Switch", RT298_HPOR_GAIN, | ||
389 | RT298_MUTE_SFT, 1, 1); | ||
390 | |||
391 | /* ADC0 source */ | ||
392 | static const char * const rt298_adc_src[] = { | ||
393 | "Mic", "RECMIX", "Dmic" | ||
394 | }; | ||
395 | |||
396 | static const int rt298_adc_values[] = { | ||
397 | 0, 4, 5, | ||
398 | }; | ||
399 | |||
400 | static SOC_VALUE_ENUM_SINGLE_DECL( | ||
401 | rt298_adc0_enum, RT298_ADC0_MUX, RT298_ADC_SEL_SFT, | ||
402 | RT298_ADC_SEL_MASK, rt298_adc_src, rt298_adc_values); | ||
403 | |||
404 | static const struct snd_kcontrol_new rt298_adc0_mux = | ||
405 | SOC_DAPM_ENUM("ADC 0 source", rt298_adc0_enum); | ||
406 | |||
407 | static SOC_VALUE_ENUM_SINGLE_DECL( | ||
408 | rt298_adc1_enum, RT298_ADC1_MUX, RT298_ADC_SEL_SFT, | ||
409 | RT298_ADC_SEL_MASK, rt298_adc_src, rt298_adc_values); | ||
410 | |||
411 | static const struct snd_kcontrol_new rt298_adc1_mux = | ||
412 | SOC_DAPM_ENUM("ADC 1 source", rt298_adc1_enum); | ||
413 | |||
414 | static const char * const rt298_dac_src[] = { | ||
415 | "Front", "Surround" | ||
416 | }; | ||
417 | /* HP-OUT source */ | ||
418 | static SOC_ENUM_SINGLE_DECL(rt298_hpo_enum, RT298_HPO_MUX, | ||
419 | 0, rt298_dac_src); | ||
420 | |||
421 | static const struct snd_kcontrol_new rt298_hpo_mux = | ||
422 | SOC_DAPM_ENUM("HPO source", rt298_hpo_enum); | ||
423 | |||
424 | /* SPK-OUT source */ | ||
425 | static SOC_ENUM_SINGLE_DECL(rt298_spo_enum, RT298_SPK_MUX, | ||
426 | 0, rt298_dac_src); | ||
427 | |||
428 | static const struct snd_kcontrol_new rt298_spo_mux = | ||
429 | SOC_DAPM_ENUM("SPO source", rt298_spo_enum); | ||
430 | |||
431 | static int rt298_spk_event(struct snd_soc_dapm_widget *w, | ||
432 | struct snd_kcontrol *kcontrol, int event) | ||
433 | { | ||
434 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); | ||
435 | |||
436 | switch (event) { | ||
437 | case SND_SOC_DAPM_POST_PMU: | ||
438 | snd_soc_write(codec, | ||
439 | RT298_SPK_EAPD, RT298_SET_EAPD_HIGH); | ||
440 | break; | ||
441 | case SND_SOC_DAPM_PRE_PMD: | ||
442 | snd_soc_write(codec, | ||
443 | RT298_SPK_EAPD, RT298_SET_EAPD_LOW); | ||
444 | break; | ||
445 | |||
446 | default: | ||
447 | return 0; | ||
448 | } | ||
449 | |||
450 | return 0; | ||
451 | } | ||
452 | |||
453 | static int rt298_set_dmic1_event(struct snd_soc_dapm_widget *w, | ||
454 | struct snd_kcontrol *kcontrol, int event) | ||
455 | { | ||
456 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); | ||
457 | |||
458 | switch (event) { | ||
459 | case SND_SOC_DAPM_POST_PMU: | ||
460 | snd_soc_write(codec, RT298_SET_PIN_DMIC1, 0x20); | ||
461 | break; | ||
462 | case SND_SOC_DAPM_PRE_PMD: | ||
463 | snd_soc_write(codec, RT298_SET_PIN_DMIC1, 0); | ||
464 | break; | ||
465 | default: | ||
466 | return 0; | ||
467 | } | ||
468 | |||
469 | return 0; | ||
470 | } | ||
471 | |||
472 | static int rt298_adc_event(struct snd_soc_dapm_widget *w, | ||
473 | struct snd_kcontrol *kcontrol, int event) | ||
474 | { | ||
475 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); | ||
476 | unsigned int nid; | ||
477 | |||
478 | nid = (w->reg >> 20) & 0xff; | ||
479 | |||
480 | switch (event) { | ||
481 | case SND_SOC_DAPM_POST_PMU: | ||
482 | snd_soc_update_bits(codec, | ||
483 | VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, nid, 0), | ||
484 | 0x7080, 0x7000); | ||
485 | break; | ||
486 | case SND_SOC_DAPM_PRE_PMD: | ||
487 | snd_soc_update_bits(codec, | ||
488 | VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, nid, 0), | ||
489 | 0x7080, 0x7080); | ||
490 | break; | ||
491 | default: | ||
492 | return 0; | ||
493 | } | ||
494 | |||
495 | return 0; | ||
496 | } | ||
497 | |||
498 | static int rt298_mic1_event(struct snd_soc_dapm_widget *w, | ||
499 | struct snd_kcontrol *kcontrol, int event) | ||
500 | { | ||
501 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); | ||
502 | |||
503 | switch (event) { | ||
504 | case SND_SOC_DAPM_PRE_PMU: | ||
505 | snd_soc_update_bits(codec, | ||
506 | RT298_A_BIAS_CTRL3, 0xc000, 0x8000); | ||
507 | snd_soc_update_bits(codec, | ||
508 | RT298_A_BIAS_CTRL2, 0xc000, 0x8000); | ||
509 | break; | ||
510 | case SND_SOC_DAPM_POST_PMD: | ||
511 | snd_soc_update_bits(codec, | ||
512 | RT298_A_BIAS_CTRL3, 0xc000, 0x0000); | ||
513 | snd_soc_update_bits(codec, | ||
514 | RT298_A_BIAS_CTRL2, 0xc000, 0x0000); | ||
515 | break; | ||
516 | default: | ||
517 | return 0; | ||
518 | } | ||
519 | |||
520 | return 0; | ||
521 | } | ||
522 | |||
523 | static int rt298_vref_event(struct snd_soc_dapm_widget *w, | ||
524 | struct snd_kcontrol *kcontrol, int event) | ||
525 | { | ||
526 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); | ||
527 | |||
528 | switch (event) { | ||
529 | case SND_SOC_DAPM_PRE_PMU: | ||
530 | snd_soc_update_bits(codec, | ||
531 | RT298_CBJ_CTRL1, 0x0400, 0x0000); | ||
532 | mdelay(50); | ||
533 | break; | ||
534 | default: | ||
535 | return 0; | ||
536 | } | ||
537 | |||
538 | return 0; | ||
539 | } | ||
540 | |||
541 | static const struct snd_soc_dapm_widget rt298_dapm_widgets[] = { | ||
542 | |||
543 | SND_SOC_DAPM_SUPPLY_S("HV", 1, RT298_POWER_CTRL1, | ||
544 | 12, 1, NULL, 0), | ||
545 | SND_SOC_DAPM_SUPPLY("VREF", RT298_POWER_CTRL1, | ||
546 | 0, 1, rt298_vref_event, SND_SOC_DAPM_PRE_PMU), | ||
547 | SND_SOC_DAPM_SUPPLY_S("BG_MBIAS", 1, RT298_POWER_CTRL2, | ||
548 | 1, 0, NULL, 0), | ||
549 | SND_SOC_DAPM_SUPPLY_S("LDO1", 1, RT298_POWER_CTRL2, | ||
550 | 2, 0, NULL, 0), | ||
551 | SND_SOC_DAPM_SUPPLY_S("LDO2", 1, RT298_POWER_CTRL2, | ||
552 | 3, 0, NULL, 0), | ||
553 | SND_SOC_DAPM_SUPPLY_S("VREF1", 1, RT298_POWER_CTRL2, | ||
554 | 4, 1, NULL, 0), | ||
555 | SND_SOC_DAPM_SUPPLY_S("LV", 2, RT298_POWER_CTRL1, | ||
556 | 13, 1, NULL, 0), | ||
557 | |||
558 | |||
559 | SND_SOC_DAPM_SUPPLY("MCLK MODE", RT298_PLL_CTRL1, | ||
560 | 5, 0, NULL, 0), | ||
561 | SND_SOC_DAPM_SUPPLY("MIC1 Input Buffer", SND_SOC_NOPM, | ||
562 | 0, 0, rt298_mic1_event, SND_SOC_DAPM_PRE_PMU | | ||
563 | SND_SOC_DAPM_POST_PMD), | ||
564 | |||
565 | /* Input Lines */ | ||
566 | SND_SOC_DAPM_INPUT("DMIC1 Pin"), | ||
567 | SND_SOC_DAPM_INPUT("DMIC2 Pin"), | ||
568 | SND_SOC_DAPM_INPUT("MIC1"), | ||
569 | SND_SOC_DAPM_INPUT("LINE1"), | ||
570 | SND_SOC_DAPM_INPUT("Beep"), | ||
571 | |||
572 | /* DMIC */ | ||
573 | SND_SOC_DAPM_PGA_E("DMIC1", RT298_SET_POWER(RT298_DMIC1), 0, 1, | ||
574 | NULL, 0, rt298_set_dmic1_event, | ||
575 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | ||
576 | SND_SOC_DAPM_PGA("DMIC2", RT298_SET_POWER(RT298_DMIC2), 0, 1, | ||
577 | NULL, 0), | ||
578 | SND_SOC_DAPM_SUPPLY("DMIC Receiver", SND_SOC_NOPM, | ||
579 | 0, 0, NULL, 0), | ||
580 | |||
581 | /* REC Mixer */ | ||
582 | SND_SOC_DAPM_MIXER("RECMIX", SND_SOC_NOPM, 0, 0, | ||
583 | rt298_rec_mix, ARRAY_SIZE(rt298_rec_mix)), | ||
584 | |||
585 | /* ADCs */ | ||
586 | SND_SOC_DAPM_ADC("ADC 0", NULL, SND_SOC_NOPM, 0, 0), | ||
587 | SND_SOC_DAPM_ADC("ADC 1", NULL, SND_SOC_NOPM, 0, 0), | ||
588 | |||
589 | /* ADC Mux */ | ||
590 | SND_SOC_DAPM_MUX_E("ADC 0 Mux", RT298_SET_POWER(RT298_ADC_IN1), 0, 1, | ||
591 | &rt298_adc0_mux, rt298_adc_event, SND_SOC_DAPM_PRE_PMD | | ||
592 | SND_SOC_DAPM_POST_PMU), | ||
593 | SND_SOC_DAPM_MUX_E("ADC 1 Mux", RT298_SET_POWER(RT298_ADC_IN2), 0, 1, | ||
594 | &rt298_adc1_mux, rt298_adc_event, SND_SOC_DAPM_PRE_PMD | | ||
595 | SND_SOC_DAPM_POST_PMU), | ||
596 | |||
597 | /* Audio Interface */ | ||
598 | SND_SOC_DAPM_AIF_IN("AIF1RX", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0), | ||
599 | SND_SOC_DAPM_AIF_OUT("AIF1TX", "AIF1 Capture", 0, SND_SOC_NOPM, 0, 0), | ||
600 | SND_SOC_DAPM_AIF_IN("AIF2RX", "AIF2 Playback", 0, SND_SOC_NOPM, 0, 0), | ||
601 | SND_SOC_DAPM_AIF_OUT("AIF2TX", "AIF2 Capture", 0, SND_SOC_NOPM, 0, 0), | ||
602 | |||
603 | /* Output Side */ | ||
604 | /* DACs */ | ||
605 | SND_SOC_DAPM_DAC("DAC 0", NULL, SND_SOC_NOPM, 0, 0), | ||
606 | SND_SOC_DAPM_DAC("DAC 1", NULL, SND_SOC_NOPM, 0, 0), | ||
607 | |||
608 | /* Output Mux */ | ||
609 | SND_SOC_DAPM_MUX("SPK Mux", SND_SOC_NOPM, 0, 0, &rt298_spo_mux), | ||
610 | SND_SOC_DAPM_MUX("HPO Mux", SND_SOC_NOPM, 0, 0, &rt298_hpo_mux), | ||
611 | |||
612 | SND_SOC_DAPM_SUPPLY("HP Power", RT298_SET_PIN_HPO, | ||
613 | RT298_SET_PIN_SFT, 0, NULL, 0), | ||
614 | |||
615 | /* Output Mixer */ | ||
616 | SND_SOC_DAPM_MIXER("Front", RT298_SET_POWER(RT298_DAC_OUT1), 0, 1, | ||
617 | rt298_front_mix, ARRAY_SIZE(rt298_front_mix)), | ||
618 | SND_SOC_DAPM_PGA("Surround", RT298_SET_POWER(RT298_DAC_OUT2), 0, 1, | ||
619 | NULL, 0), | ||
620 | |||
621 | /* Output Pga */ | ||
622 | SND_SOC_DAPM_SWITCH_E("SPO", SND_SOC_NOPM, 0, 0, | ||
623 | &spo_enable_control, rt298_spk_event, | ||
624 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | ||
625 | SND_SOC_DAPM_SWITCH("HPO L", SND_SOC_NOPM, 0, 0, | ||
626 | &hpol_enable_control), | ||
627 | SND_SOC_DAPM_SWITCH("HPO R", SND_SOC_NOPM, 0, 0, | ||
628 | &hpor_enable_control), | ||
629 | |||
630 | /* Output Lines */ | ||
631 | SND_SOC_DAPM_OUTPUT("SPOL"), | ||
632 | SND_SOC_DAPM_OUTPUT("SPOR"), | ||
633 | SND_SOC_DAPM_OUTPUT("HPO Pin"), | ||
634 | SND_SOC_DAPM_OUTPUT("SPDIF"), | ||
635 | }; | ||
636 | |||
637 | static const struct snd_soc_dapm_route rt298_dapm_routes[] = { | ||
638 | |||
639 | {"ADC 0", NULL, "MCLK MODE", is_mclk_mode}, | ||
640 | {"ADC 1", NULL, "MCLK MODE", is_mclk_mode}, | ||
641 | {"Front", NULL, "MCLK MODE", is_mclk_mode}, | ||
642 | {"Surround", NULL, "MCLK MODE", is_mclk_mode}, | ||
643 | |||
644 | {"HP Power", NULL, "LDO1"}, | ||
645 | {"HP Power", NULL, "LDO2"}, | ||
646 | {"HP Power", NULL, "LV"}, | ||
647 | {"HP Power", NULL, "VREF1"}, | ||
648 | {"HP Power", NULL, "BG_MBIAS"}, | ||
649 | |||
650 | {"MIC1", NULL, "LDO1"}, | ||
651 | {"MIC1", NULL, "LDO2"}, | ||
652 | {"MIC1", NULL, "HV"}, | ||
653 | {"MIC1", NULL, "LV"}, | ||
654 | {"MIC1", NULL, "VREF"}, | ||
655 | {"MIC1", NULL, "VREF1"}, | ||
656 | {"MIC1", NULL, "BG_MBIAS"}, | ||
657 | {"MIC1", NULL, "MIC1 Input Buffer"}, | ||
658 | |||
659 | {"SPO", NULL, "LDO1"}, | ||
660 | {"SPO", NULL, "LDO2"}, | ||
661 | {"SPO", NULL, "HV"}, | ||
662 | {"SPO", NULL, "LV"}, | ||
663 | {"SPO", NULL, "VREF"}, | ||
664 | {"SPO", NULL, "VREF1"}, | ||
665 | {"SPO", NULL, "BG_MBIAS"}, | ||
666 | |||
667 | {"DMIC1", NULL, "DMIC1 Pin"}, | ||
668 | {"DMIC2", NULL, "DMIC2 Pin"}, | ||
669 | {"DMIC1", NULL, "DMIC Receiver"}, | ||
670 | {"DMIC2", NULL, "DMIC Receiver"}, | ||
671 | |||
672 | {"RECMIX", "Beep Switch", "Beep"}, | ||
673 | {"RECMIX", "Line1 Switch", "LINE1"}, | ||
674 | {"RECMIX", "Mic1 Switch", "MIC1"}, | ||
675 | |||
676 | {"ADC 0 Mux", "Dmic", "DMIC1"}, | ||
677 | {"ADC 0 Mux", "RECMIX", "RECMIX"}, | ||
678 | {"ADC 0 Mux", "Mic", "MIC1"}, | ||
679 | {"ADC 1 Mux", "Dmic", "DMIC2"}, | ||
680 | {"ADC 1 Mux", "RECMIX", "RECMIX"}, | ||
681 | {"ADC 1 Mux", "Mic", "MIC1"}, | ||
682 | |||
683 | {"ADC 0", NULL, "ADC 0 Mux"}, | ||
684 | {"ADC 1", NULL, "ADC 1 Mux"}, | ||
685 | |||
686 | {"AIF1TX", NULL, "ADC 0"}, | ||
687 | {"AIF2TX", NULL, "ADC 1"}, | ||
688 | |||
689 | {"DAC 0", NULL, "AIF1RX"}, | ||
690 | {"DAC 1", NULL, "AIF2RX"}, | ||
691 | |||
692 | {"Front", "DAC Switch", "DAC 0"}, | ||
693 | {"Front", "RECMIX Switch", "RECMIX"}, | ||
694 | |||
695 | {"Surround", NULL, "DAC 1"}, | ||
696 | |||
697 | {"SPK Mux", "Front", "Front"}, | ||
698 | {"SPK Mux", "Surround", "Surround"}, | ||
699 | |||
700 | {"HPO Mux", "Front", "Front"}, | ||
701 | {"HPO Mux", "Surround", "Surround"}, | ||
702 | |||
703 | {"SPO", "Switch", "SPK Mux"}, | ||
704 | {"HPO L", "Switch", "HPO Mux"}, | ||
705 | {"HPO R", "Switch", "HPO Mux"}, | ||
706 | {"HPO L", NULL, "HP Power"}, | ||
707 | {"HPO R", NULL, "HP Power"}, | ||
708 | |||
709 | {"SPOL", NULL, "SPO"}, | ||
710 | {"SPOR", NULL, "SPO"}, | ||
711 | {"HPO Pin", NULL, "HPO L"}, | ||
712 | {"HPO Pin", NULL, "HPO R"}, | ||
713 | }; | ||
714 | |||
715 | static int rt298_hw_params(struct snd_pcm_substream *substream, | ||
716 | struct snd_pcm_hw_params *params, | ||
717 | struct snd_soc_dai *dai) | ||
718 | { | ||
719 | struct snd_soc_codec *codec = dai->codec; | ||
720 | struct rt298_priv *rt298 = snd_soc_codec_get_drvdata(codec); | ||
721 | unsigned int val = 0; | ||
722 | int d_len_code; | ||
723 | |||
724 | switch (params_rate(params)) { | ||
725 | /* bit 14 0:48K 1:44.1K */ | ||
726 | case 44100: | ||
727 | case 48000: | ||
728 | break; | ||
729 | default: | ||
730 | dev_err(codec->dev, "Unsupported sample rate %d\n", | ||
731 | params_rate(params)); | ||
732 | return -EINVAL; | ||
733 | } | ||
734 | switch (rt298->sys_clk) { | ||
735 | case 12288000: | ||
736 | case 24576000: | ||
737 | if (params_rate(params) != 48000) { | ||
738 | dev_err(codec->dev, "Sys_clk is not matched (%d %d)\n", | ||
739 | params_rate(params), rt298->sys_clk); | ||
740 | return -EINVAL; | ||
741 | } | ||
742 | break; | ||
743 | case 11289600: | ||
744 | case 22579200: | ||
745 | if (params_rate(params) != 44100) { | ||
746 | dev_err(codec->dev, "Sys_clk is not matched (%d %d)\n", | ||
747 | params_rate(params), rt298->sys_clk); | ||
748 | return -EINVAL; | ||
749 | } | ||
750 | break; | ||
751 | } | ||
752 | |||
753 | if (params_channels(params) <= 16) { | ||
754 | /* bit 3:0 Number of Channel */ | ||
755 | val |= (params_channels(params) - 1); | ||
756 | } else { | ||
757 | dev_err(codec->dev, "Unsupported channels %d\n", | ||
758 | params_channels(params)); | ||
759 | return -EINVAL; | ||
760 | } | ||
761 | |||
762 | d_len_code = 0; | ||
763 | switch (params_width(params)) { | ||
764 | /* bit 6:4 Bits per Sample */ | ||
765 | case 16: | ||
766 | d_len_code = 0; | ||
767 | val |= (0x1 << 4); | ||
768 | break; | ||
769 | case 32: | ||
770 | d_len_code = 2; | ||
771 | val |= (0x4 << 4); | ||
772 | break; | ||
773 | case 20: | ||
774 | d_len_code = 1; | ||
775 | val |= (0x2 << 4); | ||
776 | break; | ||
777 | case 24: | ||
778 | d_len_code = 2; | ||
779 | val |= (0x3 << 4); | ||
780 | break; | ||
781 | case 8: | ||
782 | d_len_code = 3; | ||
783 | break; | ||
784 | default: | ||
785 | return -EINVAL; | ||
786 | } | ||
787 | |||
788 | snd_soc_update_bits(codec, | ||
789 | RT298_I2S_CTRL1, 0x0018, d_len_code << 3); | ||
790 | dev_dbg(codec->dev, "format val = 0x%x\n", val); | ||
791 | |||
792 | snd_soc_update_bits(codec, RT298_DAC_FORMAT, 0x407f, val); | ||
793 | snd_soc_update_bits(codec, RT298_ADC_FORMAT, 0x407f, val); | ||
794 | |||
795 | return 0; | ||
796 | } | ||
797 | |||
798 | static int rt298_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) | ||
799 | { | ||
800 | struct snd_soc_codec *codec = dai->codec; | ||
801 | |||
802 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
803 | case SND_SOC_DAIFMT_CBM_CFM: | ||
804 | snd_soc_update_bits(codec, | ||
805 | RT298_I2S_CTRL1, 0x800, 0x800); | ||
806 | break; | ||
807 | case SND_SOC_DAIFMT_CBS_CFS: | ||
808 | snd_soc_update_bits(codec, | ||
809 | RT298_I2S_CTRL1, 0x800, 0x0); | ||
810 | break; | ||
811 | default: | ||
812 | return -EINVAL; | ||
813 | } | ||
814 | |||
815 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
816 | case SND_SOC_DAIFMT_I2S: | ||
817 | snd_soc_update_bits(codec, | ||
818 | RT298_I2S_CTRL1, 0x300, 0x0); | ||
819 | break; | ||
820 | case SND_SOC_DAIFMT_LEFT_J: | ||
821 | snd_soc_update_bits(codec, | ||
822 | RT298_I2S_CTRL1, 0x300, 0x1 << 8); | ||
823 | break; | ||
824 | case SND_SOC_DAIFMT_DSP_A: | ||
825 | snd_soc_update_bits(codec, | ||
826 | RT298_I2S_CTRL1, 0x300, 0x2 << 8); | ||
827 | break; | ||
828 | case SND_SOC_DAIFMT_DSP_B: | ||
829 | snd_soc_update_bits(codec, | ||
830 | RT298_I2S_CTRL1, 0x300, 0x3 << 8); | ||
831 | break; | ||
832 | default: | ||
833 | return -EINVAL; | ||
834 | } | ||
835 | /* bit 15 Stream Type 0:PCM 1:Non-PCM */ | ||
836 | snd_soc_update_bits(codec, RT298_DAC_FORMAT, 0x8000, 0); | ||
837 | snd_soc_update_bits(codec, RT298_ADC_FORMAT, 0x8000, 0); | ||
838 | |||
839 | return 0; | ||
840 | } | ||
841 | |||
842 | static int rt298_set_dai_sysclk(struct snd_soc_dai *dai, | ||
843 | int clk_id, unsigned int freq, int dir) | ||
844 | { | ||
845 | struct snd_soc_codec *codec = dai->codec; | ||
846 | struct rt298_priv *rt298 = snd_soc_codec_get_drvdata(codec); | ||
847 | |||
848 | dev_dbg(codec->dev, "%s freq=%d\n", __func__, freq); | ||
849 | |||
850 | if (RT298_SCLK_S_MCLK == clk_id) { | ||
851 | snd_soc_update_bits(codec, | ||
852 | RT298_I2S_CTRL2, 0x0100, 0x0); | ||
853 | snd_soc_update_bits(codec, | ||
854 | RT298_PLL_CTRL1, 0x20, 0x20); | ||
855 | } else { | ||
856 | snd_soc_update_bits(codec, | ||
857 | RT298_I2S_CTRL2, 0x0100, 0x0100); | ||
858 | snd_soc_update_bits(codec, | ||
859 | RT298_PLL_CTRL, 0x4, 0x4); | ||
860 | snd_soc_update_bits(codec, | ||
861 | RT298_PLL_CTRL1, 0x20, 0x0); | ||
862 | } | ||
863 | |||
864 | switch (freq) { | ||
865 | case 19200000: | ||
866 | if (RT298_SCLK_S_MCLK == clk_id) { | ||
867 | dev_err(codec->dev, "Should not use MCLK\n"); | ||
868 | return -EINVAL; | ||
869 | } | ||
870 | snd_soc_update_bits(codec, | ||
871 | RT298_I2S_CTRL2, 0x40, 0x40); | ||
872 | break; | ||
873 | case 24000000: | ||
874 | if (RT298_SCLK_S_MCLK == clk_id) { | ||
875 | dev_err(codec->dev, "Should not use MCLK\n"); | ||
876 | return -EINVAL; | ||
877 | } | ||
878 | snd_soc_update_bits(codec, | ||
879 | RT298_I2S_CTRL2, 0x40, 0x0); | ||
880 | break; | ||
881 | case 12288000: | ||
882 | case 11289600: | ||
883 | snd_soc_update_bits(codec, | ||
884 | RT298_I2S_CTRL2, 0x8, 0x0); | ||
885 | snd_soc_update_bits(codec, | ||
886 | RT298_CLK_DIV, 0xfc1e, 0x0004); | ||
887 | break; | ||
888 | case 24576000: | ||
889 | case 22579200: | ||
890 | snd_soc_update_bits(codec, | ||
891 | RT298_I2S_CTRL2, 0x8, 0x8); | ||
892 | snd_soc_update_bits(codec, | ||
893 | RT298_CLK_DIV, 0xfc1e, 0x5406); | ||
894 | break; | ||
895 | default: | ||
896 | dev_err(codec->dev, "Unsupported system clock\n"); | ||
897 | return -EINVAL; | ||
898 | } | ||
899 | |||
900 | rt298->sys_clk = freq; | ||
901 | rt298->clk_id = clk_id; | ||
902 | |||
903 | return 0; | ||
904 | } | ||
905 | |||
906 | static int rt298_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio) | ||
907 | { | ||
908 | struct snd_soc_codec *codec = dai->codec; | ||
909 | |||
910 | dev_dbg(codec->dev, "%s ratio=%d\n", __func__, ratio); | ||
911 | if (50 == ratio) | ||
912 | snd_soc_update_bits(codec, | ||
913 | RT298_I2S_CTRL1, 0x1000, 0x1000); | ||
914 | else | ||
915 | snd_soc_update_bits(codec, | ||
916 | RT298_I2S_CTRL1, 0x1000, 0x0); | ||
917 | |||
918 | |||
919 | return 0; | ||
920 | } | ||
921 | |||
922 | static int rt298_set_bias_level(struct snd_soc_codec *codec, | ||
923 | enum snd_soc_bias_level level) | ||
924 | { | ||
925 | switch (level) { | ||
926 | case SND_SOC_BIAS_PREPARE: | ||
927 | if (SND_SOC_BIAS_STANDBY == | ||
928 | snd_soc_codec_get_bias_level(codec)) { | ||
929 | snd_soc_write(codec, | ||
930 | RT298_SET_AUDIO_POWER, AC_PWRST_D0); | ||
931 | snd_soc_update_bits(codec, 0x0d, 0x200, 0x200); | ||
932 | snd_soc_update_bits(codec, 0x52, 0x80, 0x0); | ||
933 | mdelay(20); | ||
934 | snd_soc_update_bits(codec, 0x0d, 0x200, 0x0); | ||
935 | snd_soc_update_bits(codec, 0x52, 0x80, 0x80); | ||
936 | } | ||
937 | break; | ||
938 | |||
939 | case SND_SOC_BIAS_ON: | ||
940 | mdelay(30); | ||
941 | snd_soc_update_bits(codec, | ||
942 | RT298_CBJ_CTRL1, 0x0400, 0x0400); | ||
943 | |||
944 | break; | ||
945 | |||
946 | case SND_SOC_BIAS_STANDBY: | ||
947 | snd_soc_write(codec, | ||
948 | RT298_SET_AUDIO_POWER, AC_PWRST_D3); | ||
949 | snd_soc_update_bits(codec, | ||
950 | RT298_CBJ_CTRL1, 0x0400, 0x0000); | ||
951 | break; | ||
952 | |||
953 | default: | ||
954 | break; | ||
955 | } | ||
956 | |||
957 | return 0; | ||
958 | } | ||
959 | |||
960 | static irqreturn_t rt298_irq(int irq, void *data) | ||
961 | { | ||
962 | struct rt298_priv *rt298 = data; | ||
963 | bool hp = false; | ||
964 | bool mic = false; | ||
965 | int ret, status = 0; | ||
966 | |||
967 | ret = rt298_jack_detect(rt298, &hp, &mic); | ||
968 | |||
969 | /* Clear IRQ */ | ||
970 | regmap_update_bits(rt298->regmap, RT298_IRQ_CTRL, 0x1, 0x1); | ||
971 | |||
972 | if (ret == 0) { | ||
973 | if (hp == true) | ||
974 | status |= SND_JACK_HEADPHONE; | ||
975 | |||
976 | if (mic == true) | ||
977 | status |= SND_JACK_MICROPHONE; | ||
978 | |||
979 | snd_soc_jack_report(rt298->jack, status, | ||
980 | SND_JACK_MICROPHONE | SND_JACK_HEADPHONE); | ||
981 | |||
982 | pm_wakeup_event(&rt298->i2c->dev, 300); | ||
983 | } | ||
984 | |||
985 | return IRQ_HANDLED; | ||
986 | } | ||
987 | |||
988 | static int rt298_probe(struct snd_soc_codec *codec) | ||
989 | { | ||
990 | struct rt298_priv *rt298 = snd_soc_codec_get_drvdata(codec); | ||
991 | |||
992 | rt298->codec = codec; | ||
993 | |||
994 | if (rt298->i2c->irq) { | ||
995 | regmap_update_bits(rt298->regmap, | ||
996 | RT298_IRQ_CTRL, 0x2, 0x2); | ||
997 | |||
998 | INIT_DELAYED_WORK(&rt298->jack_detect_work, | ||
999 | rt298_jack_detect_work); | ||
1000 | schedule_delayed_work(&rt298->jack_detect_work, | ||
1001 | msecs_to_jiffies(1250)); | ||
1002 | } | ||
1003 | |||
1004 | return 0; | ||
1005 | } | ||
1006 | |||
1007 | static int rt298_remove(struct snd_soc_codec *codec) | ||
1008 | { | ||
1009 | struct rt298_priv *rt298 = snd_soc_codec_get_drvdata(codec); | ||
1010 | |||
1011 | cancel_delayed_work_sync(&rt298->jack_detect_work); | ||
1012 | |||
1013 | return 0; | ||
1014 | } | ||
1015 | |||
1016 | #ifdef CONFIG_PM | ||
1017 | static int rt298_suspend(struct snd_soc_codec *codec) | ||
1018 | { | ||
1019 | struct rt298_priv *rt298 = snd_soc_codec_get_drvdata(codec); | ||
1020 | |||
1021 | rt298->is_hp_in = -1; | ||
1022 | regcache_cache_only(rt298->regmap, true); | ||
1023 | regcache_mark_dirty(rt298->regmap); | ||
1024 | |||
1025 | return 0; | ||
1026 | } | ||
1027 | |||
1028 | static int rt298_resume(struct snd_soc_codec *codec) | ||
1029 | { | ||
1030 | struct rt298_priv *rt298 = snd_soc_codec_get_drvdata(codec); | ||
1031 | |||
1032 | regcache_cache_only(rt298->regmap, false); | ||
1033 | rt298_index_sync(codec); | ||
1034 | regcache_sync(rt298->regmap); | ||
1035 | |||
1036 | return 0; | ||
1037 | } | ||
1038 | #else | ||
1039 | #define rt298_suspend NULL | ||
1040 | #define rt298_resume NULL | ||
1041 | #endif | ||
1042 | |||
1043 | #define RT298_STEREO_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000) | ||
1044 | #define RT298_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ | ||
1045 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8) | ||
1046 | |||
1047 | static const struct snd_soc_dai_ops rt298_aif_dai_ops = { | ||
1048 | .hw_params = rt298_hw_params, | ||
1049 | .set_fmt = rt298_set_dai_fmt, | ||
1050 | .set_sysclk = rt298_set_dai_sysclk, | ||
1051 | .set_bclk_ratio = rt298_set_bclk_ratio, | ||
1052 | }; | ||
1053 | |||
1054 | static struct snd_soc_dai_driver rt298_dai[] = { | ||
1055 | { | ||
1056 | .name = "rt298-aif1", | ||
1057 | .id = RT298_AIF1, | ||
1058 | .playback = { | ||
1059 | .stream_name = "AIF1 Playback", | ||
1060 | .channels_min = 1, | ||
1061 | .channels_max = 2, | ||
1062 | .rates = RT298_STEREO_RATES, | ||
1063 | .formats = RT298_FORMATS, | ||
1064 | }, | ||
1065 | .capture = { | ||
1066 | .stream_name = "AIF1 Capture", | ||
1067 | .channels_min = 1, | ||
1068 | .channels_max = 2, | ||
1069 | .rates = RT298_STEREO_RATES, | ||
1070 | .formats = RT298_FORMATS, | ||
1071 | }, | ||
1072 | .ops = &rt298_aif_dai_ops, | ||
1073 | .symmetric_rates = 1, | ||
1074 | }, | ||
1075 | { | ||
1076 | .name = "rt298-aif2", | ||
1077 | .id = RT298_AIF2, | ||
1078 | .playback = { | ||
1079 | .stream_name = "AIF2 Playback", | ||
1080 | .channels_min = 1, | ||
1081 | .channels_max = 2, | ||
1082 | .rates = RT298_STEREO_RATES, | ||
1083 | .formats = RT298_FORMATS, | ||
1084 | }, | ||
1085 | .capture = { | ||
1086 | .stream_name = "AIF2 Capture", | ||
1087 | .channels_min = 1, | ||
1088 | .channels_max = 2, | ||
1089 | .rates = RT298_STEREO_RATES, | ||
1090 | .formats = RT298_FORMATS, | ||
1091 | }, | ||
1092 | .ops = &rt298_aif_dai_ops, | ||
1093 | .symmetric_rates = 1, | ||
1094 | }, | ||
1095 | |||
1096 | }; | ||
1097 | |||
1098 | static struct snd_soc_codec_driver soc_codec_dev_rt298 = { | ||
1099 | .probe = rt298_probe, | ||
1100 | .remove = rt298_remove, | ||
1101 | .suspend = rt298_suspend, | ||
1102 | .resume = rt298_resume, | ||
1103 | .set_bias_level = rt298_set_bias_level, | ||
1104 | .idle_bias_off = true, | ||
1105 | .controls = rt298_snd_controls, | ||
1106 | .num_controls = ARRAY_SIZE(rt298_snd_controls), | ||
1107 | .dapm_widgets = rt298_dapm_widgets, | ||
1108 | .num_dapm_widgets = ARRAY_SIZE(rt298_dapm_widgets), | ||
1109 | .dapm_routes = rt298_dapm_routes, | ||
1110 | .num_dapm_routes = ARRAY_SIZE(rt298_dapm_routes), | ||
1111 | }; | ||
1112 | |||
1113 | static const struct regmap_config rt298_regmap = { | ||
1114 | .reg_bits = 32, | ||
1115 | .val_bits = 32, | ||
1116 | .max_register = 0x02370100, | ||
1117 | .volatile_reg = rt298_volatile_register, | ||
1118 | .readable_reg = rt298_readable_register, | ||
1119 | .reg_write = rl6347a_hw_write, | ||
1120 | .reg_read = rl6347a_hw_read, | ||
1121 | .cache_type = REGCACHE_RBTREE, | ||
1122 | .reg_defaults = rt298_reg, | ||
1123 | .num_reg_defaults = ARRAY_SIZE(rt298_reg), | ||
1124 | }; | ||
1125 | |||
1126 | static const struct i2c_device_id rt298_i2c_id[] = { | ||
1127 | {"rt298", 0}, | ||
1128 | {} | ||
1129 | }; | ||
1130 | MODULE_DEVICE_TABLE(i2c, rt298_i2c_id); | ||
1131 | |||
1132 | static const struct acpi_device_id rt298_acpi_match[] = { | ||
1133 | { "INT343A", 0 }, | ||
1134 | {}, | ||
1135 | }; | ||
1136 | MODULE_DEVICE_TABLE(acpi, rt298_acpi_match); | ||
1137 | |||
1138 | static int rt298_i2c_probe(struct i2c_client *i2c, | ||
1139 | const struct i2c_device_id *id) | ||
1140 | { | ||
1141 | struct rt298_platform_data *pdata = dev_get_platdata(&i2c->dev); | ||
1142 | struct rt298_priv *rt298; | ||
1143 | struct device *dev = &i2c->dev; | ||
1144 | const struct acpi_device_id *acpiid; | ||
1145 | int i, ret; | ||
1146 | |||
1147 | pr_info("%s\n", __func__); | ||
1148 | |||
1149 | rt298 = devm_kzalloc(&i2c->dev, sizeof(*rt298), | ||
1150 | GFP_KERNEL); | ||
1151 | if (NULL == rt298) | ||
1152 | return -ENOMEM; | ||
1153 | |||
1154 | rt298->regmap = devm_regmap_init(&i2c->dev, NULL, i2c, &rt298_regmap); | ||
1155 | if (IS_ERR(rt298->regmap)) { | ||
1156 | ret = PTR_ERR(rt298->regmap); | ||
1157 | dev_err(&i2c->dev, "Failed to allocate register map: %d\n", | ||
1158 | ret); | ||
1159 | return ret; | ||
1160 | } | ||
1161 | |||
1162 | regmap_read(rt298->regmap, | ||
1163 | RT298_GET_PARAM(AC_NODE_ROOT, AC_PAR_VENDOR_ID), &ret); | ||
1164 | if (ret != RT298_VENDOR_ID) { | ||
1165 | dev_err(&i2c->dev, | ||
1166 | "Device with ID register %#x is not rt298\n", ret); | ||
1167 | return -ENODEV; | ||
1168 | } | ||
1169 | |||
1170 | rt298->index_cache = rt298_index_def; | ||
1171 | rt298->index_cache_size = INDEX_CACHE_SIZE; | ||
1172 | rt298->i2c = i2c; | ||
1173 | i2c_set_clientdata(i2c, rt298); | ||
1174 | |||
1175 | /* restore codec default */ | ||
1176 | for (i = 0; i < INDEX_CACHE_SIZE; i++) | ||
1177 | regmap_write(rt298->regmap, rt298->index_cache[i].reg, | ||
1178 | rt298->index_cache[i].def); | ||
1179 | for (i = 0; i < ARRAY_SIZE(rt298_reg); i++) | ||
1180 | regmap_write(rt298->regmap, rt298_reg[i].reg, | ||
1181 | rt298_reg[i].def); | ||
1182 | |||
1183 | if (pdata) | ||
1184 | rt298->pdata = *pdata; | ||
1185 | |||
1186 | /* enable jack combo mode on supported devices */ | ||
1187 | acpiid = acpi_match_device(dev->driver->acpi_match_table, dev); | ||
1188 | if (acpiid) { | ||
1189 | rt298->pdata = *(struct rt298_platform_data *) | ||
1190 | acpiid->driver_data; | ||
1191 | } | ||
1192 | |||
1193 | /* VREF Charging */ | ||
1194 | regmap_update_bits(rt298->regmap, 0x04, 0x80, 0x80); | ||
1195 | regmap_update_bits(rt298->regmap, 0x1b, 0x860, 0x860); | ||
1196 | /* Vref2 */ | ||
1197 | regmap_update_bits(rt298->regmap, 0x08, 0x20, 0x20); | ||
1198 | |||
1199 | regmap_write(rt298->regmap, RT298_SET_AUDIO_POWER, AC_PWRST_D3); | ||
1200 | |||
1201 | for (i = 0; i < RT298_POWER_REG_LEN; i++) | ||
1202 | regmap_write(rt298->regmap, | ||
1203 | RT298_SET_POWER(rt298_support_power_controls[i]), | ||
1204 | AC_PWRST_D1); | ||
1205 | |||
1206 | if (!rt298->pdata.cbj_en) { | ||
1207 | regmap_write(rt298->regmap, RT298_CBJ_CTRL2, 0x0000); | ||
1208 | regmap_write(rt298->regmap, RT298_MIC1_DET_CTRL, 0x0816); | ||
1209 | regmap_update_bits(rt298->regmap, | ||
1210 | RT298_CBJ_CTRL1, 0xf000, 0xb000); | ||
1211 | } else { | ||
1212 | regmap_update_bits(rt298->regmap, | ||
1213 | RT298_CBJ_CTRL1, 0xf000, 0x5000); | ||
1214 | } | ||
1215 | |||
1216 | mdelay(10); | ||
1217 | |||
1218 | if (!rt298->pdata.gpio2_en) | ||
1219 | regmap_write(rt298->regmap, RT298_SET_DMIC2_DEFAULT, 0x4000); | ||
1220 | else | ||
1221 | regmap_write(rt298->regmap, RT298_SET_DMIC2_DEFAULT, 0); | ||
1222 | |||
1223 | mdelay(10); | ||
1224 | |||
1225 | regmap_write(rt298->regmap, RT298_MISC_CTRL1, 0x0000); | ||
1226 | regmap_update_bits(rt298->regmap, | ||
1227 | RT298_WIND_FILTER_CTRL, 0x0082, 0x0082); | ||
1228 | regmap_update_bits(rt298->regmap, RT298_IRQ_CTRL, 0x2, 0x2); | ||
1229 | rt298->is_hp_in = -1; | ||
1230 | |||
1231 | if (rt298->i2c->irq) { | ||
1232 | ret = request_threaded_irq(rt298->i2c->irq, NULL, rt298_irq, | ||
1233 | IRQF_TRIGGER_HIGH | IRQF_ONESHOT, "rt298", rt298); | ||
1234 | if (ret != 0) { | ||
1235 | dev_err(&i2c->dev, | ||
1236 | "Failed to reguest IRQ: %d\n", ret); | ||
1237 | return ret; | ||
1238 | } | ||
1239 | } | ||
1240 | |||
1241 | ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt298, | ||
1242 | rt298_dai, ARRAY_SIZE(rt298_dai)); | ||
1243 | |||
1244 | return ret; | ||
1245 | } | ||
1246 | |||
1247 | static int rt298_i2c_remove(struct i2c_client *i2c) | ||
1248 | { | ||
1249 | struct rt298_priv *rt298 = i2c_get_clientdata(i2c); | ||
1250 | |||
1251 | if (i2c->irq) | ||
1252 | free_irq(i2c->irq, rt298); | ||
1253 | snd_soc_unregister_codec(&i2c->dev); | ||
1254 | |||
1255 | return 0; | ||
1256 | } | ||
1257 | |||
1258 | |||
1259 | static struct i2c_driver rt298_i2c_driver = { | ||
1260 | .driver = { | ||
1261 | .name = "rt298", | ||
1262 | .owner = THIS_MODULE, | ||
1263 | .acpi_match_table = ACPI_PTR(rt298_acpi_match), | ||
1264 | }, | ||
1265 | .probe = rt298_i2c_probe, | ||
1266 | .remove = rt298_i2c_remove, | ||
1267 | .id_table = rt298_i2c_id, | ||
1268 | }; | ||
1269 | |||
1270 | module_i2c_driver(rt298_i2c_driver); | ||
1271 | |||
1272 | MODULE_DESCRIPTION("ASoC RT298 driver"); | ||
1273 | MODULE_AUTHOR("Bard Liao <bardliao@realtek.com>"); | ||
1274 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/rt298.h b/sound/soc/codecs/rt298.h new file mode 100644 index 000000000000..31da16265f2b --- /dev/null +++ b/sound/soc/codecs/rt298.h | |||
@@ -0,0 +1,206 @@ | |||
1 | /* | ||
2 | * rt298.h -- RT298 ALSA SoC audio driver | ||
3 | * | ||
4 | * Copyright 2011 Realtek Microelectronics | ||
5 | * Author: Johnny Hsu <johnnyhsu@realtek.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #ifndef __RT298_H__ | ||
13 | #define __RT298_H__ | ||
14 | |||
15 | #define VERB_CMD(V, N, D) ((N << 20) | (V << 8) | D) | ||
16 | |||
17 | #define RT298_AUDIO_FUNCTION_GROUP 0x01 | ||
18 | #define RT298_DAC_OUT1 0x02 | ||
19 | #define RT298_DAC_OUT2 0x03 | ||
20 | #define RT298_DIG_CVT 0x06 | ||
21 | #define RT298_ADC_IN1 0x09 | ||
22 | #define RT298_ADC_IN2 0x08 | ||
23 | #define RT298_MIXER_IN 0x0b | ||
24 | #define RT298_MIXER_OUT1 0x0c | ||
25 | #define RT298_MIXER_OUT2 0x0d | ||
26 | #define RT298_DMIC1 0x12 | ||
27 | #define RT298_DMIC2 0x13 | ||
28 | #define RT298_SPK_OUT 0x14 | ||
29 | #define RT298_MIC1 0x18 | ||
30 | #define RT298_LINE1 0x1a | ||
31 | #define RT298_BEEP 0x1d | ||
32 | #define RT298_SPDIF 0x1e | ||
33 | #define RT298_VENDOR_REGISTERS 0x20 | ||
34 | #define RT298_HP_OUT 0x21 | ||
35 | #define RT298_MIXER_IN1 0x22 | ||
36 | #define RT298_MIXER_IN2 0x23 | ||
37 | |||
38 | #define RT298_SET_PIN_SFT 6 | ||
39 | #define RT298_SET_PIN_ENABLE 0x40 | ||
40 | #define RT298_SET_PIN_DISABLE 0 | ||
41 | #define RT298_SET_EAPD_HIGH 0x2 | ||
42 | #define RT298_SET_EAPD_LOW 0 | ||
43 | |||
44 | #define RT298_MUTE_SFT 7 | ||
45 | |||
46 | /* Verb commands */ | ||
47 | #define RT298_GET_PARAM(NID, PARAM) VERB_CMD(AC_VERB_PARAMETERS, NID, PARAM) | ||
48 | #define RT298_SET_POWER(NID) VERB_CMD(AC_VERB_SET_POWER_STATE, NID, 0) | ||
49 | #define RT298_SET_AUDIO_POWER RT298_SET_POWER(RT298_AUDIO_FUNCTION_GROUP) | ||
50 | #define RT298_SET_HPO_POWER RT298_SET_POWER(RT298_HP_OUT) | ||
51 | #define RT298_SET_SPK_POWER RT298_SET_POWER(RT298_SPK_OUT) | ||
52 | #define RT298_SET_DMIC1_POWER RT298_SET_POWER(RT298_DMIC1) | ||
53 | #define RT298_SPK_MUX\ | ||
54 | VERB_CMD(AC_VERB_SET_CONNECT_SEL, RT298_SPK_OUT, 0) | ||
55 | #define RT298_HPO_MUX\ | ||
56 | VERB_CMD(AC_VERB_SET_CONNECT_SEL, RT298_HP_OUT, 0) | ||
57 | #define RT298_ADC0_MUX\ | ||
58 | VERB_CMD(AC_VERB_SET_CONNECT_SEL, RT298_MIXER_IN1, 0) | ||
59 | #define RT298_ADC1_MUX\ | ||
60 | VERB_CMD(AC_VERB_SET_CONNECT_SEL, RT298_MIXER_IN2, 0) | ||
61 | #define RT298_SET_MIC1\ | ||
62 | VERB_CMD(AC_VERB_SET_PIN_WIDGET_CONTROL, RT298_MIC1, 0) | ||
63 | #define RT298_SET_PIN_HPO\ | ||
64 | VERB_CMD(AC_VERB_SET_PIN_WIDGET_CONTROL, RT298_HP_OUT, 0) | ||
65 | #define RT298_SET_PIN_SPK\ | ||
66 | VERB_CMD(AC_VERB_SET_PIN_WIDGET_CONTROL, RT298_SPK_OUT, 0) | ||
67 | #define RT298_SET_PIN_DMIC1\ | ||
68 | VERB_CMD(AC_VERB_SET_PIN_WIDGET_CONTROL, RT298_DMIC1, 0) | ||
69 | #define RT298_SET_PIN_SPDIF\ | ||
70 | VERB_CMD(AC_VERB_SET_PIN_WIDGET_CONTROL, RT298_SPDIF, 0) | ||
71 | #define RT298_SET_PIN_DIG_CVT\ | ||
72 | VERB_CMD(AC_VERB_SET_DIGI_CONVERT_1, RT298_DIG_CVT, 0) | ||
73 | #define RT298_SPK_EAPD\ | ||
74 | VERB_CMD(AC_VERB_SET_EAPD_BTLENABLE, RT298_SPK_OUT, 0) | ||
75 | #define RT298_SET_AMP_GAIN_HPO\ | ||
76 | VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT298_HP_OUT, 0) | ||
77 | #define RT298_SET_AMP_GAIN_ADC_IN1\ | ||
78 | VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT298_ADC_IN1, 0) | ||
79 | #define RT298_SET_AMP_GAIN_ADC_IN2\ | ||
80 | VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT298_ADC_IN2, 0) | ||
81 | #define RT298_GET_HP_SENSE\ | ||
82 | VERB_CMD(AC_VERB_GET_PIN_SENSE, RT298_HP_OUT, 0) | ||
83 | #define RT298_GET_MIC1_SENSE\ | ||
84 | VERB_CMD(AC_VERB_GET_PIN_SENSE, RT298_MIC1, 0) | ||
85 | #define RT298_SET_DMIC2_DEFAULT\ | ||
86 | VERB_CMD(AC_VERB_SET_CONFIG_DEFAULT_BYTES_3, RT298_DMIC2, 0) | ||
87 | #define RT298_SET_SPDIF_DEFAULT\ | ||
88 | VERB_CMD(AC_VERB_SET_CONFIG_DEFAULT_BYTES_3, RT298_SPDIF, 0) | ||
89 | #define RT298_DACL_GAIN\ | ||
90 | VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT298_DAC_OUT1, 0xa000) | ||
91 | #define RT298_DACR_GAIN\ | ||
92 | VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT298_DAC_OUT1, 0x9000) | ||
93 | #define RT298_ADCL_GAIN\ | ||
94 | VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT298_ADC_IN1, 0x6000) | ||
95 | #define RT298_ADCR_GAIN\ | ||
96 | VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT298_ADC_IN1, 0x5000) | ||
97 | #define RT298_MIC_GAIN\ | ||
98 | VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT298_MIC1, 0x7000) | ||
99 | #define RT298_SPOL_GAIN\ | ||
100 | VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT298_SPK_OUT, 0xa000) | ||
101 | #define RT298_SPOR_GAIN\ | ||
102 | VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT298_SPK_OUT, 0x9000) | ||
103 | #define RT298_HPOL_GAIN\ | ||
104 | VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT298_HP_OUT, 0xa000) | ||
105 | #define RT298_HPOR_GAIN\ | ||
106 | VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT298_HP_OUT, 0x9000) | ||
107 | #define RT298_F_DAC_SWITCH\ | ||
108 | VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT298_MIXER_OUT1, 0x7000) | ||
109 | #define RT298_F_RECMIX_SWITCH\ | ||
110 | VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT298_MIXER_OUT1, 0x7100) | ||
111 | #define RT298_REC_MIC_SWITCH\ | ||
112 | VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT298_MIXER_IN, 0x7000) | ||
113 | #define RT298_REC_I2S_SWITCH\ | ||
114 | VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT298_MIXER_IN, 0x7100) | ||
115 | #define RT298_REC_LINE_SWITCH\ | ||
116 | VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT298_MIXER_IN, 0x7200) | ||
117 | #define RT298_REC_BEEP_SWITCH\ | ||
118 | VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT298_MIXER_IN, 0x7300) | ||
119 | #define RT298_DAC_FORMAT\ | ||
120 | VERB_CMD(AC_VERB_SET_STREAM_FORMAT, RT298_DAC_OUT1, 0) | ||
121 | #define RT298_ADC_FORMAT\ | ||
122 | VERB_CMD(AC_VERB_SET_STREAM_FORMAT, RT298_ADC_IN1, 0) | ||
123 | #define RT298_COEF_INDEX\ | ||
124 | VERB_CMD(AC_VERB_SET_COEF_INDEX, RT298_VENDOR_REGISTERS, 0) | ||
125 | #define RT298_PROC_COEF\ | ||
126 | VERB_CMD(AC_VERB_SET_PROC_COEF, RT298_VENDOR_REGISTERS, 0) | ||
127 | |||
128 | /* Index registers */ | ||
129 | #define RT298_A_BIAS_CTRL1 0x01 | ||
130 | #define RT298_A_BIAS_CTRL2 0x02 | ||
131 | #define RT298_POWER_CTRL1 0x03 | ||
132 | #define RT298_A_BIAS_CTRL3 0x04 | ||
133 | #define RT298_POWER_CTRL2 0x08 | ||
134 | #define RT298_I2S_CTRL1 0x09 | ||
135 | #define RT298_I2S_CTRL2 0x0a | ||
136 | #define RT298_CLK_DIV 0x0b | ||
137 | #define RT298_DC_GAIN 0x0d | ||
138 | #define RT298_POWER_CTRL3 0x0f | ||
139 | #define RT298_MIC1_DET_CTRL 0x19 | ||
140 | #define RT298_MISC_CTRL1 0x20 | ||
141 | #define RT298_IRQ_CTRL 0x33 | ||
142 | #define RT298_WIND_FILTER_CTRL 0x46 | ||
143 | #define RT298_PLL_CTRL1 0x49 | ||
144 | #define RT298_CBJ_CTRL1 0x4f | ||
145 | #define RT298_CBJ_CTRL2 0x50 | ||
146 | #define RT298_PLL_CTRL 0x63 | ||
147 | #define RT298_DEPOP_CTRL1 0x66 | ||
148 | #define RT298_DEPOP_CTRL2 0x67 | ||
149 | #define RT298_DEPOP_CTRL3 0x68 | ||
150 | #define RT298_DEPOP_CTRL4 0x69 | ||
151 | |||
152 | /* SPDIF (0x06) */ | ||
153 | #define RT298_SPDIF_SEL_SFT 0 | ||
154 | #define RT298_SPDIF_SEL_PCM0 0 | ||
155 | #define RT298_SPDIF_SEL_PCM1 1 | ||
156 | #define RT298_SPDIF_SEL_SPOUT 2 | ||
157 | #define RT298_SPDIF_SEL_PP 3 | ||
158 | |||
159 | /* RECMIX (0x0b) */ | ||
160 | #define RT298_M_REC_BEEP_SFT 0 | ||
161 | #define RT298_M_REC_LINE1_SFT 1 | ||
162 | #define RT298_M_REC_MIC1_SFT 2 | ||
163 | #define RT298_M_REC_I2S_SFT 3 | ||
164 | |||
165 | /* Front (0x0c) */ | ||
166 | #define RT298_M_FRONT_DAC_SFT 0 | ||
167 | #define RT298_M_FRONT_REC_SFT 1 | ||
168 | |||
169 | /* SPK-OUT (0x14) */ | ||
170 | #define RT298_M_SPK_MUX_SFT 14 | ||
171 | #define RT298_SPK_SEL_MASK 0x1 | ||
172 | #define RT298_SPK_SEL_SFT 0 | ||
173 | #define RT298_SPK_SEL_F 0 | ||
174 | #define RT298_SPK_SEL_S 1 | ||
175 | |||
176 | /* HP-OUT (0x21) */ | ||
177 | #define RT298_M_HP_MUX_SFT 14 | ||
178 | #define RT298_HP_SEL_MASK 0x1 | ||
179 | #define RT298_HP_SEL_SFT 0 | ||
180 | #define RT298_HP_SEL_F 0 | ||
181 | #define RT298_HP_SEL_S 1 | ||
182 | |||
183 | /* ADC (0x22) (0x23) */ | ||
184 | #define RT298_ADC_SEL_MASK 0x7 | ||
185 | #define RT298_ADC_SEL_SFT 0 | ||
186 | #define RT298_ADC_SEL_SURR 0 | ||
187 | #define RT298_ADC_SEL_FRONT 1 | ||
188 | #define RT298_ADC_SEL_DMIC 2 | ||
189 | #define RT298_ADC_SEL_BEEP 4 | ||
190 | #define RT298_ADC_SEL_LINE1 5 | ||
191 | #define RT298_ADC_SEL_I2S 6 | ||
192 | #define RT298_ADC_SEL_MIC1 7 | ||
193 | |||
194 | #define RT298_SCLK_S_MCLK 0 | ||
195 | #define RT298_SCLK_S_PLL 1 | ||
196 | |||
197 | enum { | ||
198 | RT298_AIF1, | ||
199 | RT298_AIF2, | ||
200 | RT298_AIFS, | ||
201 | }; | ||
202 | |||
203 | int rt298_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack); | ||
204 | |||
205 | #endif /* __RT298_H__ */ | ||
206 | |||