diff options
author | Mark Brown <broonie@kernel.org> | 2015-10-25 22:16:02 -0400 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2015-10-25 22:16:02 -0400 |
commit | 1c9d000c5b3c73d1ae79fe0f332a79a166a8131c (patch) | |
tree | 7ddfb50c8021c2f024bfeb3985d313d77ce2d39a | |
parent | 7034ef5f604a9e92dd80d042cb3f64d4b1f22375 (diff) | |
parent | c5cff89b5f64b4fc7f6fd9be44b1aa7e766a94e4 (diff) |
Merge remote-tracking branch 'asoc/topic/da7219' into asoc-next
-rw-r--r-- | Documentation/devicetree/bindings/sound/da7219.txt | 106 | ||||
-rw-r--r-- | MAINTAINERS | 1 | ||||
-rw-r--r-- | include/sound/da7219-aad.h | 99 | ||||
-rw-r--r-- | include/sound/da7219.h | 55 | ||||
-rw-r--r-- | include/sound/soc.h | 7 | ||||
-rw-r--r-- | sound/soc/codecs/Kconfig | 4 | ||||
-rw-r--r-- | sound/soc/codecs/Makefile | 2 | ||||
-rw-r--r-- | sound/soc/codecs/da7219-aad.c | 823 | ||||
-rw-r--r-- | sound/soc/codecs/da7219-aad.h | 212 | ||||
-rw-r--r-- | sound/soc/codecs/da7219.c | 1955 | ||||
-rw-r--r-- | sound/soc/codecs/da7219.h | 820 |
11 files changed, 4084 insertions, 0 deletions
diff --git a/Documentation/devicetree/bindings/sound/da7219.txt b/Documentation/devicetree/bindings/sound/da7219.txt new file mode 100644 index 000000000000..1b7030911a3b --- /dev/null +++ b/Documentation/devicetree/bindings/sound/da7219.txt | |||
@@ -0,0 +1,106 @@ | |||
1 | Dialog Semiconductor DA7219 Audio Codec bindings | ||
2 | |||
3 | DA7219 is an audio codec with advanced accessory detect features. | ||
4 | |||
5 | ====== | ||
6 | |||
7 | Required properties: | ||
8 | - compatible : Should be "dlg,da7219" | ||
9 | - reg: Specifies the I2C slave address | ||
10 | |||
11 | - interrupt-parent : Specifies the phandle of the interrupt controller to which | ||
12 | the IRQs from DA7219 are delivered to. | ||
13 | - interrupts : IRQ line info for DA7219. | ||
14 | (See Documentation/devicetree/bindings/interrupt-controller/interrupts.txt for | ||
15 | further information relating to interrupt properties) | ||
16 | |||
17 | - VDD-supply: VDD power supply for the device | ||
18 | - VDDMIC-supply: VDDMIC power supply for the device | ||
19 | - VDDIO-supply: VDDIO power supply for the device | ||
20 | (See Documentation/devicetree/bindings/regulator/regulator.txt for further | ||
21 | information relating to regulators) | ||
22 | |||
23 | Optional properties: | ||
24 | - interrupt-names : Name associated with interrupt line. Should be "wakeup" if | ||
25 | interrupt is to be used to wake system, otherwise "irq" should be used. | ||
26 | - wakeup-source: Flag to indicate this device can wake system (suspend/resume). | ||
27 | |||
28 | - clocks : phandle and clock specifier for codec MCLK. | ||
29 | - clock-names : Clock name string for 'clocks' attribute, should be "mclk". | ||
30 | |||
31 | - dlg,ldo-lvl : Required internal LDO voltage (mV) level for digital engine | ||
32 | [<1050>, <1100>, <1200>, <1400>] | ||
33 | - dlg,micbias-lvl : Voltage (mV) for Mic Bias | ||
34 | [<1800>, <2000>, <2200>, <2400>, <2600>] | ||
35 | - dlg,mic-amp-in-sel : Mic input source type | ||
36 | ["diff", "se_p", "se_n"] | ||
37 | |||
38 | ====== | ||
39 | |||
40 | Child node - 'da7219_aad': | ||
41 | |||
42 | Optional properties: | ||
43 | - dlg,micbias-pulse-lvl : Mic bias higher voltage pulse level (mV). | ||
44 | [<2800>, <2900>] | ||
45 | - dlg,micbias-pulse-time : Mic bias higher voltage pulse duration (ms) | ||
46 | - dlg,btn-cfg : Periodic button press measurements for 4-pole jack (ms) | ||
47 | [<2>, <5>, <10>, <50>, <100>, <200>, <500>] | ||
48 | - dlg,mic-det-thr : Impedance threshold for mic detection measurement (Ohms) | ||
49 | [<200>, <500>, <750>, <1000>] | ||
50 | - dlg,jack-ins-deb : Debounce time for jack insertion (ms) | ||
51 | [<5>, <10>, <20>, <50>, <100>, <200>, <500>, <1000>] | ||
52 | - dlg,jack-det-rate: Jack type detection latency (3/4 pole) | ||
53 | ["32ms_64ms", "64ms_128ms", "128ms_256ms", "256ms_512ms"] | ||
54 | - dlg,jack-rem-deb : Debounce time for jack removal (ms) | ||
55 | [<1>, <5>, <10>, <20>] | ||
56 | - dlg,a-d-btn-thr : Impedance threshold between buttons A and D | ||
57 | [0x0 - 0xFF] | ||
58 | - dlg,d-b-btn-thr : Impedance threshold between buttons D and B | ||
59 | [0x0 - 0xFF] | ||
60 | - dlg,b-c-btn-thr : Impedance threshold between buttons B and C | ||
61 | [0x0 - 0xFF] | ||
62 | - dlg,c-mic-btn-thr : Impedance threshold between button C and Mic | ||
63 | [0x0 - 0xFF] | ||
64 | - dlg,btn-avg : Number of 8-bit readings for averaged button measurement | ||
65 | [<1>, <2>, <4>, <8>] | ||
66 | - dlg,adc-1bit-rpt : Repeat count for 1-bit button measurement | ||
67 | [<1>, <2>, <4>, <8>] | ||
68 | |||
69 | ====== | ||
70 | |||
71 | Example: | ||
72 | |||
73 | codec: da7219@1a { | ||
74 | compatible = "dlg,da7219"; | ||
75 | reg = <0x1a>; | ||
76 | |||
77 | interrupt-parent = <&gpio6>; | ||
78 | interrupts = <11 IRQ_TYPE_LEVEL_HIGH>; | ||
79 | |||
80 | VDD-supply = <®_audio>; | ||
81 | VDDMIC-supply = <®_audio>; | ||
82 | VDDIO-supply = <®_audio>; | ||
83 | |||
84 | clocks = <&clks 201>; | ||
85 | clock-names = "mclk"; | ||
86 | |||
87 | dlg,ldo-lvl = <1200>; | ||
88 | dlg,micbias-lvl = <2600>; | ||
89 | dlg,mic-amp-in-sel = "diff"; | ||
90 | |||
91 | da7219_aad { | ||
92 | dlg,btn-cfg = <50>; | ||
93 | dlg,mic-det-thr = <500>; | ||
94 | dlg,jack-ins-deb = <20>; | ||
95 | dlg,jack-det-rate = "32ms_64ms"; | ||
96 | dlg,jack-rem-deb = <1>; | ||
97 | |||
98 | dlg,a-d-btn-thr = <0xa>; | ||
99 | dlg,d-b-btn-thr = <0x16>; | ||
100 | dlg,b-c-btn-thr = <0x21>; | ||
101 | dlg,c-mic-btn-thr = <0x3E>; | ||
102 | |||
103 | dlg,btn-avg = <4>; | ||
104 | dlg,adc-1bit-rpt = <1>; | ||
105 | }; | ||
106 | }; | ||
diff --git a/MAINTAINERS b/MAINTAINERS index 9de185da5f5b..cb1a432a4081 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -3368,6 +3368,7 @@ M: Support Opensource <support.opensource@diasemi.com> | |||
3368 | W: http://www.dialog-semiconductor.com/products | 3368 | W: http://www.dialog-semiconductor.com/products |
3369 | S: Supported | 3369 | S: Supported |
3370 | F: Documentation/hwmon/da90?? | 3370 | F: Documentation/hwmon/da90?? |
3371 | F: Documentation/devicetree/bindings/sound/da[79]*.txt | ||
3371 | F: drivers/gpio/gpio-da90??.c | 3372 | F: drivers/gpio/gpio-da90??.c |
3372 | F: drivers/hwmon/da90??-hwmon.c | 3373 | F: drivers/hwmon/da90??-hwmon.c |
3373 | F: drivers/iio/adc/da91??-*.c | 3374 | F: drivers/iio/adc/da91??-*.c |
diff --git a/include/sound/da7219-aad.h b/include/sound/da7219-aad.h new file mode 100644 index 000000000000..17802fb86ec4 --- /dev/null +++ b/include/sound/da7219-aad.h | |||
@@ -0,0 +1,99 @@ | |||
1 | /* | ||
2 | * da7219-aad.h - DA7322 ASoC Codec AAD Driver Platform Data | ||
3 | * | ||
4 | * Copyright (c) 2015 Dialog Semiconductor Ltd. | ||
5 | * | ||
6 | * Author: Adam Thomson <Adam.Thomson.Opensource@diasemi.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | */ | ||
13 | |||
14 | #ifndef __DA7219_AAD_PDATA_H | ||
15 | #define __DA7219_AAD_PDATA_H | ||
16 | |||
17 | enum da7219_aad_micbias_pulse_lvl { | ||
18 | DA7219_AAD_MICBIAS_PULSE_LVL_OFF = 0, | ||
19 | DA7219_AAD_MICBIAS_PULSE_LVL_2_8V = 6, | ||
20 | DA7219_AAD_MICBIAS_PULSE_LVL_2_9V, | ||
21 | }; | ||
22 | |||
23 | enum da7219_aad_btn_cfg { | ||
24 | DA7219_AAD_BTN_CFG_2MS = 1, | ||
25 | DA7219_AAD_BTN_CFG_5MS, | ||
26 | DA7219_AAD_BTN_CFG_10MS, | ||
27 | DA7219_AAD_BTN_CFG_50MS, | ||
28 | DA7219_AAD_BTN_CFG_100MS, | ||
29 | DA7219_AAD_BTN_CFG_200MS, | ||
30 | DA7219_AAD_BTN_CFG_500MS, | ||
31 | }; | ||
32 | |||
33 | enum da7219_aad_mic_det_thr { | ||
34 | DA7219_AAD_MIC_DET_THR_200_OHMS = 0, | ||
35 | DA7219_AAD_MIC_DET_THR_500_OHMS, | ||
36 | DA7219_AAD_MIC_DET_THR_750_OHMS, | ||
37 | DA7219_AAD_MIC_DET_THR_1000_OHMS, | ||
38 | }; | ||
39 | |||
40 | enum da7219_aad_jack_ins_deb { | ||
41 | DA7219_AAD_JACK_INS_DEB_5MS = 0, | ||
42 | DA7219_AAD_JACK_INS_DEB_10MS, | ||
43 | DA7219_AAD_JACK_INS_DEB_20MS, | ||
44 | DA7219_AAD_JACK_INS_DEB_50MS, | ||
45 | DA7219_AAD_JACK_INS_DEB_100MS, | ||
46 | DA7219_AAD_JACK_INS_DEB_200MS, | ||
47 | DA7219_AAD_JACK_INS_DEB_500MS, | ||
48 | DA7219_AAD_JACK_INS_DEB_1S, | ||
49 | }; | ||
50 | |||
51 | enum da7219_aad_jack_det_rate { | ||
52 | DA7219_AAD_JACK_DET_RATE_32_64MS = 0, | ||
53 | DA7219_AAD_JACK_DET_RATE_64_128MS, | ||
54 | DA7219_AAD_JACK_DET_RATE_128_256MS, | ||
55 | DA7219_AAD_JACK_DET_RATE_256_512MS, | ||
56 | }; | ||
57 | |||
58 | enum da7219_aad_jack_rem_deb { | ||
59 | DA7219_AAD_JACK_REM_DEB_1MS = 0, | ||
60 | DA7219_AAD_JACK_REM_DEB_5MS, | ||
61 | DA7219_AAD_JACK_REM_DEB_10MS, | ||
62 | DA7219_AAD_JACK_REM_DEB_20MS, | ||
63 | }; | ||
64 | |||
65 | enum da7219_aad_btn_avg { | ||
66 | DA7219_AAD_BTN_AVG_1 = 0, | ||
67 | DA7219_AAD_BTN_AVG_2, | ||
68 | DA7219_AAD_BTN_AVG_4, | ||
69 | DA7219_AAD_BTN_AVG_8, | ||
70 | }; | ||
71 | |||
72 | enum da7219_aad_adc_1bit_rpt { | ||
73 | DA7219_AAD_ADC_1BIT_RPT_1 = 0, | ||
74 | DA7219_AAD_ADC_1BIT_RPT_2, | ||
75 | DA7219_AAD_ADC_1BIT_RPT_4, | ||
76 | DA7219_AAD_ADC_1BIT_RPT_8, | ||
77 | }; | ||
78 | |||
79 | struct da7219_aad_pdata { | ||
80 | int irq; | ||
81 | |||
82 | enum da7219_aad_micbias_pulse_lvl micbias_pulse_lvl; | ||
83 | u32 micbias_pulse_time; | ||
84 | enum da7219_aad_btn_cfg btn_cfg; | ||
85 | enum da7219_aad_mic_det_thr mic_det_thr; | ||
86 | enum da7219_aad_jack_ins_deb jack_ins_deb; | ||
87 | enum da7219_aad_jack_det_rate jack_det_rate; | ||
88 | enum da7219_aad_jack_rem_deb jack_rem_deb; | ||
89 | |||
90 | u8 a_d_btn_thr; | ||
91 | u8 d_b_btn_thr; | ||
92 | u8 b_c_btn_thr; | ||
93 | u8 c_mic_btn_thr; | ||
94 | |||
95 | enum da7219_aad_btn_avg btn_avg; | ||
96 | enum da7219_aad_adc_1bit_rpt adc_1bit_rpt; | ||
97 | }; | ||
98 | |||
99 | #endif /* __DA7219_AAD_PDATA_H */ | ||
diff --git a/include/sound/da7219.h b/include/sound/da7219.h new file mode 100644 index 000000000000..3f39e135312d --- /dev/null +++ b/include/sound/da7219.h | |||
@@ -0,0 +1,55 @@ | |||
1 | /* | ||
2 | * da7219.h - DA7219 ASoC Codec Driver Platform Data | ||
3 | * | ||
4 | * Copyright (c) 2015 Dialog Semiconductor | ||
5 | * | ||
6 | * Author: Adam Thomson <Adam.Thomson.Opensource@diasemi.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | */ | ||
13 | |||
14 | #ifndef __DA7219_PDATA_H | ||
15 | #define __DA7219_PDATA_H | ||
16 | |||
17 | /* LDO */ | ||
18 | enum da7219_ldo_lvl_sel { | ||
19 | DA7219_LDO_LVL_SEL_1_05V = 0, | ||
20 | DA7219_LDO_LVL_SEL_1_10V, | ||
21 | DA7219_LDO_LVL_SEL_1_20V, | ||
22 | DA7219_LDO_LVL_SEL_1_40V, | ||
23 | }; | ||
24 | |||
25 | /* Mic Bias */ | ||
26 | enum da7219_micbias_voltage { | ||
27 | DA7219_MICBIAS_1_8V = 1, | ||
28 | DA7219_MICBIAS_2_0V, | ||
29 | DA7219_MICBIAS_2_2V, | ||
30 | DA7219_MICBIAS_2_4V, | ||
31 | DA7219_MICBIAS_2_6V, | ||
32 | }; | ||
33 | |||
34 | /* Mic input type */ | ||
35 | enum da7219_mic_amp_in_sel { | ||
36 | DA7219_MIC_AMP_IN_SEL_DIFF = 0, | ||
37 | DA7219_MIC_AMP_IN_SEL_SE_P, | ||
38 | DA7219_MIC_AMP_IN_SEL_SE_N, | ||
39 | }; | ||
40 | |||
41 | struct da7219_aad_pdata; | ||
42 | |||
43 | struct da7219_pdata { | ||
44 | /* Internal LDO */ | ||
45 | enum da7219_ldo_lvl_sel ldo_lvl_sel; | ||
46 | |||
47 | /* Mic */ | ||
48 | enum da7219_micbias_voltage micbias_lvl; | ||
49 | enum da7219_mic_amp_in_sel mic_amp_in_sel; | ||
50 | |||
51 | /* AAD */ | ||
52 | struct da7219_aad_pdata *aad_pdata; | ||
53 | }; | ||
54 | |||
55 | #endif /* __DA7219_PDATA_H */ | ||
diff --git a/include/sound/soc.h b/include/sound/soc.h index 904d69429087..a8b4b9c8b1d2 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h | |||
@@ -217,6 +217,13 @@ | |||
217 | .get = xhandler_get, .put = xhandler_put, \ | 217 | .get = xhandler_get, .put = xhandler_put, \ |
218 | .private_value = \ | 218 | .private_value = \ |
219 | SOC_DOUBLE_VALUE(reg, shift_left, shift_right, max, invert, 0) } | 219 | SOC_DOUBLE_VALUE(reg, shift_left, shift_right, max, invert, 0) } |
220 | #define SOC_DOUBLE_R_EXT(xname, reg_left, reg_right, xshift, xmax, xinvert,\ | ||
221 | xhandler_get, xhandler_put) \ | ||
222 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ | ||
223 | .info = snd_soc_info_volsw, \ | ||
224 | .get = xhandler_get, .put = xhandler_put, \ | ||
225 | .private_value = SOC_DOUBLE_R_VALUE(reg_left, reg_right, xshift, \ | ||
226 | xmax, xinvert) } | ||
220 | #define SOC_SINGLE_EXT_TLV(xname, xreg, xshift, xmax, xinvert,\ | 227 | #define SOC_SINGLE_EXT_TLV(xname, xreg, xshift, xmax, xinvert,\ |
221 | xhandler_get, xhandler_put, tlv_array) \ | 228 | xhandler_get, xhandler_put, tlv_array) \ |
222 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ | 229 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ |
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index b77c6b06c87f..cce4e96b625b 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig | |||
@@ -58,6 +58,7 @@ config SND_SOC_ALL_CODECS | |||
58 | select SND_SOC_CX20442 if TTY | 58 | select SND_SOC_CX20442 if TTY |
59 | select SND_SOC_DA7210 if SND_SOC_I2C_AND_SPI | 59 | select SND_SOC_DA7210 if SND_SOC_I2C_AND_SPI |
60 | select SND_SOC_DA7213 if I2C | 60 | select SND_SOC_DA7213 if I2C |
61 | select SND_SOC_DA7219 if I2C | ||
61 | select SND_SOC_DA732X if I2C | 62 | select SND_SOC_DA732X if I2C |
62 | select SND_SOC_DA9055 if I2C | 63 | select SND_SOC_DA9055 if I2C |
63 | select SND_SOC_DMIC | 64 | select SND_SOC_DMIC |
@@ -437,6 +438,9 @@ config SND_SOC_DA7210 | |||
437 | config SND_SOC_DA7213 | 438 | config SND_SOC_DA7213 |
438 | tristate | 439 | tristate |
439 | 440 | ||
441 | config SND_SOC_DA7219 | ||
442 | tristate | ||
443 | |||
440 | config SND_SOC_DA732X | 444 | config SND_SOC_DA732X |
441 | tristate | 445 | tristate |
442 | 446 | ||
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 8d0f9d8bd9fe..783300aa1193 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile | |||
@@ -50,6 +50,7 @@ snd-soc-cs4349-objs := cs4349.o | |||
50 | snd-soc-cx20442-objs := cx20442.o | 50 | snd-soc-cx20442-objs := cx20442.o |
51 | snd-soc-da7210-objs := da7210.o | 51 | snd-soc-da7210-objs := da7210.o |
52 | snd-soc-da7213-objs := da7213.o | 52 | snd-soc-da7213-objs := da7213.o |
53 | snd-soc-da7219-objs := da7219.o da7219-aad.o | ||
53 | snd-soc-da732x-objs := da732x.o | 54 | snd-soc-da732x-objs := da732x.o |
54 | snd-soc-da9055-objs := da9055.o | 55 | snd-soc-da9055-objs := da9055.o |
55 | snd-soc-bt-sco-objs := bt-sco.o | 56 | snd-soc-bt-sco-objs := bt-sco.o |
@@ -243,6 +244,7 @@ obj-$(CONFIG_SND_SOC_CS4349) += snd-soc-cs4349.o | |||
243 | obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o | 244 | obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o |
244 | obj-$(CONFIG_SND_SOC_DA7210) += snd-soc-da7210.o | 245 | obj-$(CONFIG_SND_SOC_DA7210) += snd-soc-da7210.o |
245 | obj-$(CONFIG_SND_SOC_DA7213) += snd-soc-da7213.o | 246 | obj-$(CONFIG_SND_SOC_DA7213) += snd-soc-da7213.o |
247 | obj-$(CONFIG_SND_SOC_DA7219) += snd-soc-da7219.o | ||
246 | obj-$(CONFIG_SND_SOC_DA732X) += snd-soc-da732x.o | 248 | obj-$(CONFIG_SND_SOC_DA732X) += snd-soc-da732x.o |
247 | obj-$(CONFIG_SND_SOC_DA9055) += snd-soc-da9055.o | 249 | obj-$(CONFIG_SND_SOC_DA9055) += snd-soc-da9055.o |
248 | obj-$(CONFIG_SND_SOC_BT_SCO) += snd-soc-bt-sco.o | 250 | obj-$(CONFIG_SND_SOC_BT_SCO) += snd-soc-bt-sco.o |
diff --git a/sound/soc/codecs/da7219-aad.c b/sound/soc/codecs/da7219-aad.c new file mode 100644 index 000000000000..9459593eef13 --- /dev/null +++ b/sound/soc/codecs/da7219-aad.c | |||
@@ -0,0 +1,823 @@ | |||
1 | /* | ||
2 | * da7219-aad.c - Dialog DA7219 ALSA SoC AAD Driver | ||
3 | * | ||
4 | * Copyright (c) 2015 Dialog Semiconductor Ltd. | ||
5 | * | ||
6 | * Author: Adam Thomson <Adam.Thomson.Opensource@diasemi.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | */ | ||
13 | |||
14 | #include <linux/module.h> | ||
15 | #include <linux/platform_device.h> | ||
16 | #include <linux/of_device.h> | ||
17 | #include <linux/of_irq.h> | ||
18 | #include <linux/pm_wakeirq.h> | ||
19 | #include <linux/slab.h> | ||
20 | #include <linux/delay.h> | ||
21 | #include <linux/workqueue.h> | ||
22 | #include <sound/soc.h> | ||
23 | #include <sound/jack.h> | ||
24 | #include <sound/da7219.h> | ||
25 | |||
26 | #include "da7219.h" | ||
27 | #include "da7219-aad.h" | ||
28 | |||
29 | |||
30 | /* | ||
31 | * Detection control | ||
32 | */ | ||
33 | |||
34 | void da7219_aad_jack_det(struct snd_soc_codec *codec, struct snd_soc_jack *jack) | ||
35 | { | ||
36 | struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); | ||
37 | |||
38 | da7219->aad->jack = jack; | ||
39 | da7219->aad->jack_inserted = false; | ||
40 | |||
41 | /* Send an initial empty report */ | ||
42 | snd_soc_jack_report(jack, 0, DA7219_AAD_REPORT_ALL_MASK); | ||
43 | |||
44 | /* Enable/Disable jack detection */ | ||
45 | snd_soc_update_bits(codec, DA7219_ACCDET_CONFIG_1, | ||
46 | DA7219_ACCDET_EN_MASK, | ||
47 | (jack ? DA7219_ACCDET_EN_MASK : 0)); | ||
48 | } | ||
49 | EXPORT_SYMBOL_GPL(da7219_aad_jack_det); | ||
50 | |||
51 | /* | ||
52 | * Button/HPTest work | ||
53 | */ | ||
54 | |||
55 | static void da7219_aad_btn_det_work(struct work_struct *work) | ||
56 | { | ||
57 | struct da7219_aad_priv *da7219_aad = | ||
58 | container_of(work, struct da7219_aad_priv, btn_det_work); | ||
59 | struct snd_soc_codec *codec = da7219_aad->codec; | ||
60 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); | ||
61 | u8 statusa, micbias_ctrl; | ||
62 | bool micbias_up = false; | ||
63 | int retries = 0; | ||
64 | |||
65 | /* Drive headphones/lineout */ | ||
66 | snd_soc_update_bits(codec, DA7219_HP_L_CTRL, | ||
67 | DA7219_HP_L_AMP_OE_MASK, | ||
68 | DA7219_HP_L_AMP_OE_MASK); | ||
69 | snd_soc_update_bits(codec, DA7219_HP_R_CTRL, | ||
70 | DA7219_HP_R_AMP_OE_MASK, | ||
71 | DA7219_HP_R_AMP_OE_MASK); | ||
72 | |||
73 | /* Make sure mic bias is up */ | ||
74 | snd_soc_dapm_force_enable_pin(dapm, "Mic Bias"); | ||
75 | snd_soc_dapm_sync(dapm); | ||
76 | |||
77 | do { | ||
78 | statusa = snd_soc_read(codec, DA7219_ACCDET_STATUS_A); | ||
79 | if (statusa & DA7219_MICBIAS_UP_STS_MASK) | ||
80 | micbias_up = true; | ||
81 | else if (retries++ < DA7219_AAD_MICBIAS_CHK_RETRIES) | ||
82 | msleep(DA7219_AAD_MICBIAS_CHK_DELAY); | ||
83 | } while ((!micbias_up) && (retries < DA7219_AAD_MICBIAS_CHK_RETRIES)); | ||
84 | |||
85 | if (retries >= DA7219_AAD_MICBIAS_CHK_RETRIES) | ||
86 | dev_warn(codec->dev, "Mic bias status check timed out"); | ||
87 | |||
88 | /* | ||
89 | * Mic bias pulse required to enable mic, must be done before enabling | ||
90 | * button detection to prevent erroneous button readings. | ||
91 | */ | ||
92 | if (da7219_aad->micbias_pulse_lvl && da7219_aad->micbias_pulse_time) { | ||
93 | /* Pulse higher level voltage */ | ||
94 | micbias_ctrl = snd_soc_read(codec, DA7219_MICBIAS_CTRL); | ||
95 | snd_soc_update_bits(codec, DA7219_MICBIAS_CTRL, | ||
96 | DA7219_MICBIAS1_LEVEL_MASK, | ||
97 | da7219_aad->micbias_pulse_lvl); | ||
98 | msleep(da7219_aad->micbias_pulse_time); | ||
99 | snd_soc_write(codec, DA7219_MICBIAS_CTRL, micbias_ctrl); | ||
100 | |||
101 | } | ||
102 | |||
103 | snd_soc_update_bits(codec, DA7219_ACCDET_CONFIG_1, | ||
104 | DA7219_BUTTON_CONFIG_MASK, | ||
105 | da7219_aad->btn_cfg); | ||
106 | } | ||
107 | |||
108 | static void da7219_aad_hptest_work(struct work_struct *work) | ||
109 | { | ||
110 | struct da7219_aad_priv *da7219_aad = | ||
111 | container_of(work, struct da7219_aad_priv, hptest_work); | ||
112 | struct snd_soc_codec *codec = da7219_aad->codec; | ||
113 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); | ||
114 | struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); | ||
115 | |||
116 | u16 tonegen_freq_hptest; | ||
117 | u8 accdet_cfg8; | ||
118 | int report = 0; | ||
119 | |||
120 | /* Lock DAPM and any Kcontrols that are affected by this test */ | ||
121 | snd_soc_dapm_mutex_lock(dapm); | ||
122 | mutex_lock(&da7219->lock); | ||
123 | |||
124 | /* Bypass cache so it saves current settings */ | ||
125 | regcache_cache_bypass(da7219->regmap, true); | ||
126 | |||
127 | /* Make sure Tone Generator is disabled */ | ||
128 | snd_soc_write(codec, DA7219_TONE_GEN_CFG1, 0); | ||
129 | |||
130 | /* Enable HPTest block, 1KOhms check */ | ||
131 | snd_soc_update_bits(codec, DA7219_ACCDET_CONFIG_8, | ||
132 | DA7219_HPTEST_EN_MASK | DA7219_HPTEST_RES_SEL_MASK, | ||
133 | DA7219_HPTEST_EN_MASK | | ||
134 | DA7219_HPTEST_RES_SEL_1KOHMS); | ||
135 | |||
136 | /* Set gains to 0db */ | ||
137 | snd_soc_write(codec, DA7219_DAC_L_GAIN, DA7219_DAC_DIGITAL_GAIN_0DB); | ||
138 | snd_soc_write(codec, DA7219_DAC_R_GAIN, DA7219_DAC_DIGITAL_GAIN_0DB); | ||
139 | snd_soc_write(codec, DA7219_HP_L_GAIN, DA7219_HP_AMP_GAIN_0DB); | ||
140 | snd_soc_write(codec, DA7219_HP_R_GAIN, DA7219_HP_AMP_GAIN_0DB); | ||
141 | |||
142 | /* Disable DAC filters, EQs and soft mute */ | ||
143 | snd_soc_update_bits(codec, DA7219_DAC_FILTERS1, DA7219_HPF_MODE_MASK, | ||
144 | 0); | ||
145 | snd_soc_update_bits(codec, DA7219_DAC_FILTERS4, DA7219_DAC_EQ_EN_MASK, | ||
146 | 0); | ||
147 | snd_soc_update_bits(codec, DA7219_DAC_FILTERS5, | ||
148 | DA7219_DAC_SOFTMUTE_EN_MASK, 0); | ||
149 | |||
150 | /* Enable HP left & right paths */ | ||
151 | snd_soc_update_bits(codec, DA7219_CP_CTRL, DA7219_CP_EN_MASK, | ||
152 | DA7219_CP_EN_MASK); | ||
153 | snd_soc_update_bits(codec, DA7219_DIG_ROUTING_DAC, | ||
154 | DA7219_DAC_L_SRC_MASK | DA7219_DAC_R_SRC_MASK, | ||
155 | DA7219_DAC_L_SRC_TONEGEN | | ||
156 | DA7219_DAC_R_SRC_TONEGEN); | ||
157 | snd_soc_update_bits(codec, DA7219_DAC_L_CTRL, | ||
158 | DA7219_DAC_L_EN_MASK | DA7219_DAC_L_MUTE_EN_MASK, | ||
159 | DA7219_DAC_L_EN_MASK); | ||
160 | snd_soc_update_bits(codec, DA7219_DAC_R_CTRL, | ||
161 | DA7219_DAC_R_EN_MASK | DA7219_DAC_R_MUTE_EN_MASK, | ||
162 | DA7219_DAC_R_EN_MASK); | ||
163 | snd_soc_update_bits(codec, DA7219_MIXOUT_L_SELECT, | ||
164 | DA7219_MIXOUT_L_MIX_SELECT_MASK, | ||
165 | DA7219_MIXOUT_L_MIX_SELECT_MASK); | ||
166 | snd_soc_update_bits(codec, DA7219_MIXOUT_R_SELECT, | ||
167 | DA7219_MIXOUT_R_MIX_SELECT_MASK, | ||
168 | DA7219_MIXOUT_R_MIX_SELECT_MASK); | ||
169 | snd_soc_update_bits(codec, DA7219_DROUTING_ST_OUTFILT_1L, | ||
170 | DA7219_OUTFILT_ST_1L_SRC_MASK, | ||
171 | DA7219_DMIX_ST_SRC_OUTFILT1L); | ||
172 | snd_soc_update_bits(codec, DA7219_DROUTING_ST_OUTFILT_1R, | ||
173 | DA7219_OUTFILT_ST_1R_SRC_MASK, | ||
174 | DA7219_DMIX_ST_SRC_OUTFILT1R); | ||
175 | snd_soc_update_bits(codec, DA7219_MIXOUT_L_CTRL, | ||
176 | DA7219_MIXOUT_L_AMP_EN_MASK, | ||
177 | DA7219_MIXOUT_L_AMP_EN_MASK); | ||
178 | snd_soc_update_bits(codec, DA7219_MIXOUT_R_CTRL, | ||
179 | DA7219_MIXOUT_R_AMP_EN_MASK, | ||
180 | DA7219_MIXOUT_R_AMP_EN_MASK); | ||
181 | snd_soc_write(codec, DA7219_HP_L_CTRL, | ||
182 | DA7219_HP_L_AMP_OE_MASK | DA7219_HP_L_AMP_EN_MASK); | ||
183 | snd_soc_write(codec, DA7219_HP_R_CTRL, | ||
184 | DA7219_HP_R_AMP_OE_MASK | DA7219_HP_R_AMP_EN_MASK); | ||
185 | |||
186 | /* Configure & start Tone Generator */ | ||
187 | snd_soc_write(codec, DA7219_TONE_GEN_ON_PER, DA7219_BEEP_ON_PER_MASK); | ||
188 | tonegen_freq_hptest = cpu_to_le16(DA7219_AAD_HPTEST_RAMP_FREQ); | ||
189 | regmap_raw_write(da7219->regmap, DA7219_TONE_GEN_FREQ1_L, | ||
190 | &tonegen_freq_hptest, sizeof(tonegen_freq_hptest)); | ||
191 | snd_soc_update_bits(codec, DA7219_TONE_GEN_CFG2, | ||
192 | DA7219_SWG_SEL_MASK | DA7219_TONE_GEN_GAIN_MASK, | ||
193 | DA7219_SWG_SEL_SRAMP | | ||
194 | DA7219_TONE_GEN_GAIN_MINUS_15DB); | ||
195 | snd_soc_write(codec, DA7219_TONE_GEN_CFG1, DA7219_START_STOPN_MASK); | ||
196 | |||
197 | msleep(DA7219_AAD_HPTEST_PERIOD); | ||
198 | |||
199 | /* Grab comparator reading */ | ||
200 | accdet_cfg8 = snd_soc_read(codec, DA7219_ACCDET_CONFIG_8); | ||
201 | if (accdet_cfg8 & DA7219_HPTEST_COMP_MASK) | ||
202 | report |= SND_JACK_HEADPHONE; | ||
203 | else | ||
204 | report |= SND_JACK_LINEOUT; | ||
205 | |||
206 | /* Stop tone generator */ | ||
207 | snd_soc_write(codec, DA7219_TONE_GEN_CFG1, 0); | ||
208 | |||
209 | msleep(DA7219_AAD_HPTEST_PERIOD); | ||
210 | |||
211 | /* Restore original settings from cache */ | ||
212 | regcache_mark_dirty(da7219->regmap); | ||
213 | regcache_sync_region(da7219->regmap, DA7219_HP_L_CTRL, | ||
214 | DA7219_HP_R_CTRL); | ||
215 | regcache_sync_region(da7219->regmap, DA7219_MIXOUT_L_CTRL, | ||
216 | DA7219_MIXOUT_R_CTRL); | ||
217 | regcache_sync_region(da7219->regmap, DA7219_DROUTING_ST_OUTFILT_1L, | ||
218 | DA7219_DROUTING_ST_OUTFILT_1R); | ||
219 | regcache_sync_region(da7219->regmap, DA7219_MIXOUT_L_SELECT, | ||
220 | DA7219_MIXOUT_R_SELECT); | ||
221 | regcache_sync_region(da7219->regmap, DA7219_DAC_L_CTRL, | ||
222 | DA7219_DAC_R_CTRL); | ||
223 | regcache_sync_region(da7219->regmap, DA7219_DIG_ROUTING_DAC, | ||
224 | DA7219_DIG_ROUTING_DAC); | ||
225 | regcache_sync_region(da7219->regmap, DA7219_CP_CTRL, DA7219_CP_CTRL); | ||
226 | regcache_sync_region(da7219->regmap, DA7219_DAC_FILTERS5, | ||
227 | DA7219_DAC_FILTERS5); | ||
228 | regcache_sync_region(da7219->regmap, DA7219_DAC_FILTERS4, | ||
229 | DA7219_DAC_FILTERS1); | ||
230 | regcache_sync_region(da7219->regmap, DA7219_HP_L_GAIN, | ||
231 | DA7219_HP_R_GAIN); | ||
232 | regcache_sync_region(da7219->regmap, DA7219_DAC_L_GAIN, | ||
233 | DA7219_DAC_R_GAIN); | ||
234 | regcache_sync_region(da7219->regmap, DA7219_TONE_GEN_ON_PER, | ||
235 | DA7219_TONE_GEN_ON_PER); | ||
236 | regcache_sync_region(da7219->regmap, DA7219_TONE_GEN_FREQ1_L, | ||
237 | DA7219_TONE_GEN_FREQ1_U); | ||
238 | regcache_sync_region(da7219->regmap, DA7219_TONE_GEN_CFG1, | ||
239 | DA7219_TONE_GEN_CFG2); | ||
240 | |||
241 | regcache_cache_bypass(da7219->regmap, false); | ||
242 | |||
243 | /* Disable HPTest block */ | ||
244 | snd_soc_update_bits(codec, DA7219_ACCDET_CONFIG_8, | ||
245 | DA7219_HPTEST_EN_MASK, 0); | ||
246 | |||
247 | /* Drive Headphones/lineout */ | ||
248 | snd_soc_update_bits(codec, DA7219_HP_L_CTRL, DA7219_HP_L_AMP_OE_MASK, | ||
249 | DA7219_HP_L_AMP_OE_MASK); | ||
250 | snd_soc_update_bits(codec, DA7219_HP_R_CTRL, DA7219_HP_R_AMP_OE_MASK, | ||
251 | DA7219_HP_R_AMP_OE_MASK); | ||
252 | |||
253 | mutex_unlock(&da7219->lock); | ||
254 | snd_soc_dapm_mutex_unlock(dapm); | ||
255 | |||
256 | /* | ||
257 | * Only send report if jack hasn't been removed during process, | ||
258 | * otherwise it's invalid and we drop it. | ||
259 | */ | ||
260 | if (da7219_aad->jack_inserted) | ||
261 | snd_soc_jack_report(da7219_aad->jack, report, | ||
262 | SND_JACK_HEADSET | SND_JACK_LINEOUT); | ||
263 | } | ||
264 | |||
265 | |||
266 | /* | ||
267 | * IRQ | ||
268 | */ | ||
269 | |||
270 | static irqreturn_t da7219_aad_irq_thread(int irq, void *data) | ||
271 | { | ||
272 | struct da7219_aad_priv *da7219_aad = data; | ||
273 | struct snd_soc_codec *codec = da7219_aad->codec; | ||
274 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); | ||
275 | struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); | ||
276 | u8 events[DA7219_AAD_IRQ_REG_MAX]; | ||
277 | u8 statusa; | ||
278 | int i, report = 0, mask = 0; | ||
279 | |||
280 | /* Read current IRQ events */ | ||
281 | regmap_bulk_read(da7219->regmap, DA7219_ACCDET_IRQ_EVENT_A, | ||
282 | events, DA7219_AAD_IRQ_REG_MAX); | ||
283 | |||
284 | if (!events[DA7219_AAD_IRQ_REG_A] && !events[DA7219_AAD_IRQ_REG_B]) | ||
285 | return IRQ_NONE; | ||
286 | |||
287 | /* Read status register for jack insertion & type status */ | ||
288 | statusa = snd_soc_read(codec, DA7219_ACCDET_STATUS_A); | ||
289 | |||
290 | /* Clear events */ | ||
291 | regmap_bulk_write(da7219->regmap, DA7219_ACCDET_IRQ_EVENT_A, | ||
292 | events, DA7219_AAD_IRQ_REG_MAX); | ||
293 | |||
294 | dev_dbg(codec->dev, "IRQ events = 0x%x|0x%x, status = 0x%x\n", | ||
295 | events[DA7219_AAD_IRQ_REG_A], events[DA7219_AAD_IRQ_REG_B], | ||
296 | statusa); | ||
297 | |||
298 | if (statusa & DA7219_JACK_INSERTION_STS_MASK) { | ||
299 | /* Jack Insertion */ | ||
300 | if (events[DA7219_AAD_IRQ_REG_A] & | ||
301 | DA7219_E_JACK_INSERTED_MASK) { | ||
302 | report |= SND_JACK_MECHANICAL; | ||
303 | mask |= SND_JACK_MECHANICAL; | ||
304 | da7219_aad->jack_inserted = true; | ||
305 | } | ||
306 | |||
307 | /* Jack type detection */ | ||
308 | if (events[DA7219_AAD_IRQ_REG_A] & | ||
309 | DA7219_E_JACK_DETECT_COMPLETE_MASK) { | ||
310 | /* | ||
311 | * If 4-pole, then enable button detection, else perform | ||
312 | * HP impedance test to determine output type to report. | ||
313 | * | ||
314 | * We schedule work here as the tasks themselves can | ||
315 | * take time to complete, and in particular for hptest | ||
316 | * we want to be able to check if the jack was removed | ||
317 | * during the procedure as this will invalidate the | ||
318 | * result. By doing this as work, the IRQ thread can | ||
319 | * handle a removal, and we can check at the end of | ||
320 | * hptest if we have a valid result or not. | ||
321 | */ | ||
322 | if (statusa & DA7219_JACK_TYPE_STS_MASK) { | ||
323 | report |= SND_JACK_HEADSET; | ||
324 | mask |= SND_JACK_HEADSET | SND_JACK_LINEOUT; | ||
325 | schedule_work(&da7219_aad->btn_det_work); | ||
326 | } else { | ||
327 | schedule_work(&da7219_aad->hptest_work); | ||
328 | } | ||
329 | } | ||
330 | |||
331 | /* Button support for 4-pole jack */ | ||
332 | if (statusa & DA7219_JACK_TYPE_STS_MASK) { | ||
333 | for (i = 0; i < DA7219_AAD_MAX_BUTTONS; ++i) { | ||
334 | /* Button Press */ | ||
335 | if (events[DA7219_AAD_IRQ_REG_B] & | ||
336 | (DA7219_E_BUTTON_A_PRESSED_MASK << i)) { | ||
337 | report |= SND_JACK_BTN_0 >> i; | ||
338 | mask |= SND_JACK_BTN_0 >> i; | ||
339 | } | ||
340 | } | ||
341 | snd_soc_jack_report(da7219_aad->jack, report, mask); | ||
342 | |||
343 | for (i = 0; i < DA7219_AAD_MAX_BUTTONS; ++i) { | ||
344 | /* Button Release */ | ||
345 | if (events[DA7219_AAD_IRQ_REG_B] & | ||
346 | (DA7219_E_BUTTON_A_RELEASED_MASK >> i)) { | ||
347 | report &= ~(SND_JACK_BTN_0 >> i); | ||
348 | mask |= SND_JACK_BTN_0 >> i; | ||
349 | } | ||
350 | } | ||
351 | } | ||
352 | } else { | ||
353 | /* Jack removal */ | ||
354 | if (events[DA7219_AAD_IRQ_REG_A] & DA7219_E_JACK_REMOVED_MASK) { | ||
355 | report = 0; | ||
356 | mask |= DA7219_AAD_REPORT_ALL_MASK; | ||
357 | da7219_aad->jack_inserted = false; | ||
358 | |||
359 | /* Un-drive headphones/lineout */ | ||
360 | snd_soc_update_bits(codec, DA7219_HP_R_CTRL, | ||
361 | DA7219_HP_R_AMP_OE_MASK, 0); | ||
362 | snd_soc_update_bits(codec, DA7219_HP_L_CTRL, | ||
363 | DA7219_HP_L_AMP_OE_MASK, 0); | ||
364 | |||
365 | /* Ensure button detection disabled */ | ||
366 | snd_soc_update_bits(codec, DA7219_ACCDET_CONFIG_1, | ||
367 | DA7219_BUTTON_CONFIG_MASK, 0); | ||
368 | |||
369 | /* Disable mic bias */ | ||
370 | snd_soc_dapm_disable_pin(dapm, "Mic Bias"); | ||
371 | snd_soc_dapm_sync(dapm); | ||
372 | |||
373 | /* Cancel any pending work */ | ||
374 | cancel_work_sync(&da7219_aad->btn_det_work); | ||
375 | cancel_work_sync(&da7219_aad->hptest_work); | ||
376 | } | ||
377 | } | ||
378 | |||
379 | snd_soc_jack_report(da7219_aad->jack, report, mask); | ||
380 | |||
381 | return IRQ_HANDLED; | ||
382 | } | ||
383 | |||
384 | /* | ||
385 | * DT to pdata conversion | ||
386 | */ | ||
387 | |||
388 | static enum da7219_aad_micbias_pulse_lvl | ||
389 | da7219_aad_of_micbias_pulse_lvl(struct snd_soc_codec *codec, u32 val) | ||
390 | { | ||
391 | switch (val) { | ||
392 | case 2800: | ||
393 | return DA7219_AAD_MICBIAS_PULSE_LVL_2_8V; | ||
394 | case 2900: | ||
395 | return DA7219_AAD_MICBIAS_PULSE_LVL_2_9V; | ||
396 | default: | ||
397 | dev_warn(codec->dev, "Invalid micbias pulse level"); | ||
398 | return DA7219_AAD_MICBIAS_PULSE_LVL_OFF; | ||
399 | } | ||
400 | } | ||
401 | |||
402 | static enum da7219_aad_btn_cfg | ||
403 | da7219_aad_of_btn_cfg(struct snd_soc_codec *codec, u32 val) | ||
404 | { | ||
405 | switch (val) { | ||
406 | case 2: | ||
407 | return DA7219_AAD_BTN_CFG_2MS; | ||
408 | case 5: | ||
409 | return DA7219_AAD_BTN_CFG_5MS; | ||
410 | case 10: | ||
411 | return DA7219_AAD_BTN_CFG_10MS; | ||
412 | case 50: | ||
413 | return DA7219_AAD_BTN_CFG_50MS; | ||
414 | case 100: | ||
415 | return DA7219_AAD_BTN_CFG_100MS; | ||
416 | case 200: | ||
417 | return DA7219_AAD_BTN_CFG_200MS; | ||
418 | case 500: | ||
419 | return DA7219_AAD_BTN_CFG_500MS; | ||
420 | default: | ||
421 | dev_warn(codec->dev, "Invalid button config"); | ||
422 | return DA7219_AAD_BTN_CFG_10MS; | ||
423 | } | ||
424 | } | ||
425 | |||
426 | static enum da7219_aad_mic_det_thr | ||
427 | da7219_aad_of_mic_det_thr(struct snd_soc_codec *codec, u32 val) | ||
428 | { | ||
429 | switch (val) { | ||
430 | case 200: | ||
431 | return DA7219_AAD_MIC_DET_THR_200_OHMS; | ||
432 | case 500: | ||
433 | return DA7219_AAD_MIC_DET_THR_500_OHMS; | ||
434 | case 750: | ||
435 | return DA7219_AAD_MIC_DET_THR_750_OHMS; | ||
436 | case 1000: | ||
437 | return DA7219_AAD_MIC_DET_THR_1000_OHMS; | ||
438 | default: | ||
439 | dev_warn(codec->dev, "Invalid mic detect threshold"); | ||
440 | return DA7219_AAD_MIC_DET_THR_500_OHMS; | ||
441 | } | ||
442 | } | ||
443 | |||
444 | static enum da7219_aad_jack_ins_deb | ||
445 | da7219_aad_of_jack_ins_deb(struct snd_soc_codec *codec, u32 val) | ||
446 | { | ||
447 | switch (val) { | ||
448 | case 5: | ||
449 | return DA7219_AAD_JACK_INS_DEB_5MS; | ||
450 | case 10: | ||
451 | return DA7219_AAD_JACK_INS_DEB_10MS; | ||
452 | case 20: | ||
453 | return DA7219_AAD_JACK_INS_DEB_20MS; | ||
454 | case 50: | ||
455 | return DA7219_AAD_JACK_INS_DEB_50MS; | ||
456 | case 100: | ||
457 | return DA7219_AAD_JACK_INS_DEB_100MS; | ||
458 | case 200: | ||
459 | return DA7219_AAD_JACK_INS_DEB_200MS; | ||
460 | case 500: | ||
461 | return DA7219_AAD_JACK_INS_DEB_500MS; | ||
462 | case 1000: | ||
463 | return DA7219_AAD_JACK_INS_DEB_1S; | ||
464 | default: | ||
465 | dev_warn(codec->dev, "Invalid jack insert debounce"); | ||
466 | return DA7219_AAD_JACK_INS_DEB_20MS; | ||
467 | } | ||
468 | } | ||
469 | |||
470 | static enum da7219_aad_jack_det_rate | ||
471 | da7219_aad_of_jack_det_rate(struct snd_soc_codec *codec, const char *str) | ||
472 | { | ||
473 | if (!strcmp(str, "32ms_64ms")) { | ||
474 | return DA7219_AAD_JACK_DET_RATE_32_64MS; | ||
475 | } else if (!strcmp(str, "64ms_128ms")) { | ||
476 | return DA7219_AAD_JACK_DET_RATE_64_128MS; | ||
477 | } else if (!strcmp(str, "128ms_256ms")) { | ||
478 | return DA7219_AAD_JACK_DET_RATE_128_256MS; | ||
479 | } else if (!strcmp(str, "256ms_512ms")) { | ||
480 | return DA7219_AAD_JACK_DET_RATE_256_512MS; | ||
481 | } else { | ||
482 | dev_warn(codec->dev, "Invalid jack detect rate"); | ||
483 | return DA7219_AAD_JACK_DET_RATE_256_512MS; | ||
484 | } | ||
485 | } | ||
486 | |||
487 | static enum da7219_aad_jack_rem_deb | ||
488 | da7219_aad_of_jack_rem_deb(struct snd_soc_codec *codec, u32 val) | ||
489 | { | ||
490 | switch (val) { | ||
491 | case 1: | ||
492 | return DA7219_AAD_JACK_REM_DEB_1MS; | ||
493 | case 5: | ||
494 | return DA7219_AAD_JACK_REM_DEB_5MS; | ||
495 | case 10: | ||
496 | return DA7219_AAD_JACK_REM_DEB_10MS; | ||
497 | case 20: | ||
498 | return DA7219_AAD_JACK_REM_DEB_20MS; | ||
499 | default: | ||
500 | dev_warn(codec->dev, "Invalid jack removal debounce"); | ||
501 | return DA7219_AAD_JACK_REM_DEB_1MS; | ||
502 | } | ||
503 | } | ||
504 | |||
505 | static enum da7219_aad_btn_avg | ||
506 | da7219_aad_of_btn_avg(struct snd_soc_codec *codec, u32 val) | ||
507 | { | ||
508 | switch (val) { | ||
509 | case 1: | ||
510 | return DA7219_AAD_BTN_AVG_1; | ||
511 | case 2: | ||
512 | return DA7219_AAD_BTN_AVG_2; | ||
513 | case 4: | ||
514 | return DA7219_AAD_BTN_AVG_4; | ||
515 | case 8: | ||
516 | return DA7219_AAD_BTN_AVG_8; | ||
517 | default: | ||
518 | dev_warn(codec->dev, "Invalid button average value"); | ||
519 | return DA7219_AAD_BTN_AVG_2; | ||
520 | } | ||
521 | } | ||
522 | |||
523 | static enum da7219_aad_adc_1bit_rpt | ||
524 | da7219_aad_of_adc_1bit_rpt(struct snd_soc_codec *codec, u32 val) | ||
525 | { | ||
526 | switch (val) { | ||
527 | case 1: | ||
528 | return DA7219_AAD_ADC_1BIT_RPT_1; | ||
529 | case 2: | ||
530 | return DA7219_AAD_ADC_1BIT_RPT_2; | ||
531 | case 4: | ||
532 | return DA7219_AAD_ADC_1BIT_RPT_4; | ||
533 | case 8: | ||
534 | return DA7219_AAD_ADC_1BIT_RPT_8; | ||
535 | default: | ||
536 | dev_warn(codec->dev, "Invalid ADC 1-bit repeat value"); | ||
537 | return DA7219_AAD_ADC_1BIT_RPT_1; | ||
538 | } | ||
539 | } | ||
540 | |||
541 | static struct da7219_aad_pdata *da7219_aad_of_to_pdata(struct snd_soc_codec *codec) | ||
542 | { | ||
543 | struct device_node *np = codec->dev->of_node; | ||
544 | struct device_node *aad_np = of_find_node_by_name(np, "da7219_aad"); | ||
545 | struct da7219_aad_pdata *aad_pdata; | ||
546 | const char *of_str; | ||
547 | u32 of_val32; | ||
548 | |||
549 | if (!aad_np) | ||
550 | return NULL; | ||
551 | |||
552 | aad_pdata = devm_kzalloc(codec->dev, sizeof(*aad_pdata), GFP_KERNEL); | ||
553 | if (!aad_pdata) | ||
554 | goto out; | ||
555 | |||
556 | aad_pdata->irq = irq_of_parse_and_map(np, 0); | ||
557 | |||
558 | if (of_property_read_u32(aad_np, "dlg,micbias-pulse-lvl", | ||
559 | &of_val32) >= 0) | ||
560 | aad_pdata->micbias_pulse_lvl = | ||
561 | da7219_aad_of_micbias_pulse_lvl(codec, of_val32); | ||
562 | else | ||
563 | aad_pdata->micbias_pulse_lvl = DA7219_AAD_MICBIAS_PULSE_LVL_OFF; | ||
564 | |||
565 | if (of_property_read_u32(aad_np, "dlg,micbias-pulse-time", | ||
566 | &of_val32) >= 0) | ||
567 | aad_pdata->micbias_pulse_time = of_val32; | ||
568 | |||
569 | if (of_property_read_u32(aad_np, "dlg,btn-cfg", &of_val32) >= 0) | ||
570 | aad_pdata->btn_cfg = da7219_aad_of_btn_cfg(codec, of_val32); | ||
571 | else | ||
572 | aad_pdata->btn_cfg = DA7219_AAD_BTN_CFG_10MS; | ||
573 | |||
574 | if (of_property_read_u32(aad_np, "dlg,mic-det-thr", &of_val32) >= 0) | ||
575 | aad_pdata->mic_det_thr = | ||
576 | da7219_aad_of_mic_det_thr(codec, of_val32); | ||
577 | else | ||
578 | aad_pdata->mic_det_thr = DA7219_AAD_MIC_DET_THR_500_OHMS; | ||
579 | |||
580 | if (of_property_read_u32(aad_np, "dlg,jack-ins-deb", &of_val32) >= 0) | ||
581 | aad_pdata->jack_ins_deb = | ||
582 | da7219_aad_of_jack_ins_deb(codec, of_val32); | ||
583 | else | ||
584 | aad_pdata->jack_ins_deb = DA7219_AAD_JACK_INS_DEB_20MS; | ||
585 | |||
586 | if (!of_property_read_string(aad_np, "dlg,jack-det-rate", &of_str)) | ||
587 | aad_pdata->jack_det_rate = | ||
588 | da7219_aad_of_jack_det_rate(codec, of_str); | ||
589 | else | ||
590 | aad_pdata->jack_det_rate = DA7219_AAD_JACK_DET_RATE_256_512MS; | ||
591 | |||
592 | if (of_property_read_u32(aad_np, "dlg,jack-rem-deb", &of_val32) >= 0) | ||
593 | aad_pdata->jack_rem_deb = | ||
594 | da7219_aad_of_jack_rem_deb(codec, of_val32); | ||
595 | else | ||
596 | aad_pdata->jack_rem_deb = DA7219_AAD_JACK_REM_DEB_1MS; | ||
597 | |||
598 | if (of_property_read_u32(aad_np, "dlg,a-d-btn-thr", &of_val32) >= 0) | ||
599 | aad_pdata->a_d_btn_thr = (u8) of_val32; | ||
600 | else | ||
601 | aad_pdata->a_d_btn_thr = 0xA; | ||
602 | |||
603 | if (of_property_read_u32(aad_np, "dlg,d-b-btn-thr", &of_val32) >= 0) | ||
604 | aad_pdata->d_b_btn_thr = (u8) of_val32; | ||
605 | else | ||
606 | aad_pdata->d_b_btn_thr = 0x16; | ||
607 | |||
608 | if (of_property_read_u32(aad_np, "dlg,b-c-btn-thr", &of_val32) >= 0) | ||
609 | aad_pdata->b_c_btn_thr = (u8) of_val32; | ||
610 | else | ||
611 | aad_pdata->b_c_btn_thr = 0x21; | ||
612 | |||
613 | if (of_property_read_u32(aad_np, "dlg,c-mic-btn-thr", &of_val32) >= 0) | ||
614 | aad_pdata->c_mic_btn_thr = (u8) of_val32; | ||
615 | else | ||
616 | aad_pdata->c_mic_btn_thr = 0x3E; | ||
617 | |||
618 | if (of_property_read_u32(aad_np, "dlg,btn-avg", &of_val32) >= 0) | ||
619 | aad_pdata->btn_avg = da7219_aad_of_btn_avg(codec, of_val32); | ||
620 | else | ||
621 | aad_pdata->btn_avg = DA7219_AAD_BTN_AVG_2; | ||
622 | |||
623 | if (of_property_read_u32(aad_np, "dlg,adc-1bit-rpt", &of_val32) >= 0) | ||
624 | aad_pdata->adc_1bit_rpt = | ||
625 | da7219_aad_of_adc_1bit_rpt(codec, of_val32); | ||
626 | else | ||
627 | aad_pdata->adc_1bit_rpt = DA7219_AAD_ADC_1BIT_RPT_1; | ||
628 | |||
629 | out: | ||
630 | of_node_put(aad_np); | ||
631 | |||
632 | return aad_pdata; | ||
633 | } | ||
634 | |||
635 | static void da7219_aad_handle_pdata(struct snd_soc_codec *codec) | ||
636 | { | ||
637 | struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); | ||
638 | struct da7219_aad_priv *da7219_aad = da7219->aad; | ||
639 | struct da7219_pdata *pdata = da7219->pdata; | ||
640 | |||
641 | if ((pdata) && (pdata->aad_pdata)) { | ||
642 | struct da7219_aad_pdata *aad_pdata = pdata->aad_pdata; | ||
643 | u8 cfg, mask; | ||
644 | |||
645 | da7219_aad->irq = aad_pdata->irq; | ||
646 | |||
647 | switch (aad_pdata->micbias_pulse_lvl) { | ||
648 | case DA7219_AAD_MICBIAS_PULSE_LVL_2_8V: | ||
649 | case DA7219_AAD_MICBIAS_PULSE_LVL_2_9V: | ||
650 | da7219_aad->micbias_pulse_lvl = | ||
651 | (aad_pdata->micbias_pulse_lvl << | ||
652 | DA7219_MICBIAS1_LEVEL_SHIFT); | ||
653 | break; | ||
654 | default: | ||
655 | break; | ||
656 | } | ||
657 | |||
658 | da7219_aad->micbias_pulse_time = aad_pdata->micbias_pulse_time; | ||
659 | |||
660 | switch (aad_pdata->btn_cfg) { | ||
661 | case DA7219_AAD_BTN_CFG_2MS: | ||
662 | case DA7219_AAD_BTN_CFG_5MS: | ||
663 | case DA7219_AAD_BTN_CFG_10MS: | ||
664 | case DA7219_AAD_BTN_CFG_50MS: | ||
665 | case DA7219_AAD_BTN_CFG_100MS: | ||
666 | case DA7219_AAD_BTN_CFG_200MS: | ||
667 | case DA7219_AAD_BTN_CFG_500MS: | ||
668 | da7219_aad->btn_cfg = (aad_pdata->btn_cfg << | ||
669 | DA7219_BUTTON_CONFIG_SHIFT); | ||
670 | } | ||
671 | |||
672 | cfg = 0; | ||
673 | mask = 0; | ||
674 | switch (aad_pdata->mic_det_thr) { | ||
675 | case DA7219_AAD_MIC_DET_THR_200_OHMS: | ||
676 | case DA7219_AAD_MIC_DET_THR_500_OHMS: | ||
677 | case DA7219_AAD_MIC_DET_THR_750_OHMS: | ||
678 | case DA7219_AAD_MIC_DET_THR_1000_OHMS: | ||
679 | cfg |= (aad_pdata->mic_det_thr << | ||
680 | DA7219_MIC_DET_THRESH_SHIFT); | ||
681 | mask |= DA7219_MIC_DET_THRESH_MASK; | ||
682 | } | ||
683 | snd_soc_update_bits(codec, DA7219_ACCDET_CONFIG_1, mask, cfg); | ||
684 | |||
685 | cfg = 0; | ||
686 | mask = 0; | ||
687 | switch (aad_pdata->jack_ins_deb) { | ||
688 | case DA7219_AAD_JACK_INS_DEB_5MS: | ||
689 | case DA7219_AAD_JACK_INS_DEB_10MS: | ||
690 | case DA7219_AAD_JACK_INS_DEB_20MS: | ||
691 | case DA7219_AAD_JACK_INS_DEB_50MS: | ||
692 | case DA7219_AAD_JACK_INS_DEB_100MS: | ||
693 | case DA7219_AAD_JACK_INS_DEB_200MS: | ||
694 | case DA7219_AAD_JACK_INS_DEB_500MS: | ||
695 | case DA7219_AAD_JACK_INS_DEB_1S: | ||
696 | cfg |= (aad_pdata->jack_ins_deb << | ||
697 | DA7219_JACKDET_DEBOUNCE_SHIFT); | ||
698 | mask |= DA7219_JACKDET_DEBOUNCE_MASK; | ||
699 | } | ||
700 | switch (aad_pdata->jack_det_rate) { | ||
701 | case DA7219_AAD_JACK_DET_RATE_32_64MS: | ||
702 | case DA7219_AAD_JACK_DET_RATE_64_128MS: | ||
703 | case DA7219_AAD_JACK_DET_RATE_128_256MS: | ||
704 | case DA7219_AAD_JACK_DET_RATE_256_512MS: | ||
705 | cfg |= (aad_pdata->jack_det_rate << | ||
706 | DA7219_JACK_DETECT_RATE_SHIFT); | ||
707 | mask |= DA7219_JACK_DETECT_RATE_MASK; | ||
708 | } | ||
709 | switch (aad_pdata->jack_rem_deb) { | ||
710 | case DA7219_AAD_JACK_REM_DEB_1MS: | ||
711 | case DA7219_AAD_JACK_REM_DEB_5MS: | ||
712 | case DA7219_AAD_JACK_REM_DEB_10MS: | ||
713 | case DA7219_AAD_JACK_REM_DEB_20MS: | ||
714 | cfg |= (aad_pdata->jack_rem_deb << | ||
715 | DA7219_JACKDET_REM_DEB_SHIFT); | ||
716 | mask |= DA7219_JACKDET_REM_DEB_MASK; | ||
717 | } | ||
718 | snd_soc_update_bits(codec, DA7219_ACCDET_CONFIG_2, mask, cfg); | ||
719 | |||
720 | snd_soc_write(codec, DA7219_ACCDET_CONFIG_3, | ||
721 | aad_pdata->a_d_btn_thr); | ||
722 | snd_soc_write(codec, DA7219_ACCDET_CONFIG_4, | ||
723 | aad_pdata->d_b_btn_thr); | ||
724 | snd_soc_write(codec, DA7219_ACCDET_CONFIG_5, | ||
725 | aad_pdata->b_c_btn_thr); | ||
726 | snd_soc_write(codec, DA7219_ACCDET_CONFIG_6, | ||
727 | aad_pdata->c_mic_btn_thr); | ||
728 | |||
729 | cfg = 0; | ||
730 | mask = 0; | ||
731 | switch (aad_pdata->btn_avg) { | ||
732 | case DA7219_AAD_BTN_AVG_1: | ||
733 | case DA7219_AAD_BTN_AVG_2: | ||
734 | case DA7219_AAD_BTN_AVG_4: | ||
735 | case DA7219_AAD_BTN_AVG_8: | ||
736 | cfg |= (aad_pdata->btn_avg << | ||
737 | DA7219_BUTTON_AVERAGE_SHIFT); | ||
738 | mask |= DA7219_BUTTON_AVERAGE_MASK; | ||
739 | } | ||
740 | switch (aad_pdata->adc_1bit_rpt) { | ||
741 | case DA7219_AAD_ADC_1BIT_RPT_1: | ||
742 | case DA7219_AAD_ADC_1BIT_RPT_2: | ||
743 | case DA7219_AAD_ADC_1BIT_RPT_4: | ||
744 | case DA7219_AAD_ADC_1BIT_RPT_8: | ||
745 | cfg |= (aad_pdata->adc_1bit_rpt << | ||
746 | DA7219_ADC_1_BIT_REPEAT_SHIFT); | ||
747 | mask |= DA7219_ADC_1_BIT_REPEAT_MASK; | ||
748 | } | ||
749 | snd_soc_update_bits(codec, DA7219_ACCDET_CONFIG_7, mask, cfg); | ||
750 | } | ||
751 | } | ||
752 | |||
753 | |||
754 | /* | ||
755 | * Init/Exit | ||
756 | */ | ||
757 | |||
758 | int da7219_aad_init(struct snd_soc_codec *codec) | ||
759 | { | ||
760 | struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); | ||
761 | struct da7219_aad_priv *da7219_aad; | ||
762 | u8 mask[DA7219_AAD_IRQ_REG_MAX]; | ||
763 | int ret; | ||
764 | |||
765 | da7219_aad = devm_kzalloc(codec->dev, sizeof(*da7219_aad), GFP_KERNEL); | ||
766 | if (!da7219_aad) | ||
767 | return -ENOMEM; | ||
768 | |||
769 | da7219->aad = da7219_aad; | ||
770 | da7219_aad->codec = codec; | ||
771 | |||
772 | /* Handle any DT/platform data */ | ||
773 | if ((codec->dev->of_node) && (da7219->pdata)) | ||
774 | da7219->pdata->aad_pdata = da7219_aad_of_to_pdata(codec); | ||
775 | |||
776 | da7219_aad_handle_pdata(codec); | ||
777 | |||
778 | /* Disable button detection */ | ||
779 | snd_soc_update_bits(codec, DA7219_ACCDET_CONFIG_1, | ||
780 | DA7219_BUTTON_CONFIG_MASK, 0); | ||
781 | |||
782 | INIT_WORK(&da7219_aad->btn_det_work, da7219_aad_btn_det_work); | ||
783 | INIT_WORK(&da7219_aad->hptest_work, da7219_aad_hptest_work); | ||
784 | |||
785 | ret = request_threaded_irq(da7219_aad->irq, NULL, | ||
786 | da7219_aad_irq_thread, | ||
787 | IRQF_TRIGGER_LOW | IRQF_ONESHOT, | ||
788 | "da7219-aad", da7219_aad); | ||
789 | if (ret) { | ||
790 | dev_err(codec->dev, "Failed to request IRQ: %d\n", ret); | ||
791 | return ret; | ||
792 | } | ||
793 | |||
794 | /* Unmask AAD IRQs */ | ||
795 | memset(mask, 0, DA7219_AAD_IRQ_REG_MAX); | ||
796 | regmap_bulk_write(da7219->regmap, DA7219_ACCDET_IRQ_MASK_A, | ||
797 | &mask, DA7219_AAD_IRQ_REG_MAX); | ||
798 | |||
799 | return 0; | ||
800 | } | ||
801 | EXPORT_SYMBOL_GPL(da7219_aad_init); | ||
802 | |||
803 | void da7219_aad_exit(struct snd_soc_codec *codec) | ||
804 | { | ||
805 | struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); | ||
806 | struct da7219_aad_priv *da7219_aad = da7219->aad; | ||
807 | u8 mask[DA7219_AAD_IRQ_REG_MAX]; | ||
808 | |||
809 | /* Mask off AAD IRQs */ | ||
810 | memset(mask, DA7219_BYTE_MASK, DA7219_AAD_IRQ_REG_MAX); | ||
811 | regmap_bulk_write(da7219->regmap, DA7219_ACCDET_IRQ_MASK_A, | ||
812 | mask, DA7219_AAD_IRQ_REG_MAX); | ||
813 | |||
814 | free_irq(da7219_aad->irq, da7219_aad); | ||
815 | |||
816 | cancel_work_sync(&da7219_aad->btn_det_work); | ||
817 | cancel_work_sync(&da7219_aad->hptest_work); | ||
818 | } | ||
819 | EXPORT_SYMBOL_GPL(da7219_aad_exit); | ||
820 | |||
821 | MODULE_DESCRIPTION("ASoC DA7219 AAD Driver"); | ||
822 | MODULE_AUTHOR("Adam Thomson <Adam.Thomson.Opensource@diasemi.com>"); | ||
823 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/da7219-aad.h b/sound/soc/codecs/da7219-aad.h new file mode 100644 index 000000000000..4fccf677cd06 --- /dev/null +++ b/sound/soc/codecs/da7219-aad.h | |||
@@ -0,0 +1,212 @@ | |||
1 | /* | ||
2 | * da7219-aad.h - DA7322 ASoC AAD Driver | ||
3 | * | ||
4 | * Copyright (c) 2015 Dialog Semiconductor Ltd. | ||
5 | * | ||
6 | * Author: Adam Thomson <Adam.Thomson.Opensource@diasemi.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | */ | ||
13 | |||
14 | #ifndef __DA7219_AAD_H | ||
15 | #define __DA7219_AAD_H | ||
16 | |||
17 | #include <linux/timer.h> | ||
18 | #include <sound/soc.h> | ||
19 | #include <sound/jack.h> | ||
20 | #include <sound/da7219-aad.h> | ||
21 | |||
22 | /* | ||
23 | * Registers | ||
24 | */ | ||
25 | |||
26 | #define DA7219_ACCDET_STATUS_A 0xC0 | ||
27 | #define DA7219_ACCDET_STATUS_B 0xC1 | ||
28 | #define DA7219_ACCDET_IRQ_EVENT_A 0xC2 | ||
29 | #define DA7219_ACCDET_IRQ_EVENT_B 0xC3 | ||
30 | #define DA7219_ACCDET_IRQ_MASK_A 0xC4 | ||
31 | #define DA7219_ACCDET_IRQ_MASK_B 0xC5 | ||
32 | #define DA7219_ACCDET_CONFIG_1 0xC6 | ||
33 | #define DA7219_ACCDET_CONFIG_2 0xC7 | ||
34 | #define DA7219_ACCDET_CONFIG_3 0xC8 | ||
35 | #define DA7219_ACCDET_CONFIG_4 0xC9 | ||
36 | #define DA7219_ACCDET_CONFIG_5 0xCA | ||
37 | #define DA7219_ACCDET_CONFIG_6 0xCB | ||
38 | #define DA7219_ACCDET_CONFIG_7 0xCC | ||
39 | #define DA7219_ACCDET_CONFIG_8 0xCD | ||
40 | |||
41 | |||
42 | /* | ||
43 | * Bit Fields | ||
44 | */ | ||
45 | |||
46 | /* DA7219_ACCDET_STATUS_A = 0xC0 */ | ||
47 | #define DA7219_JACK_INSERTION_STS_SHIFT 0 | ||
48 | #define DA7219_JACK_INSERTION_STS_MASK (0x1 << 0) | ||
49 | #define DA7219_JACK_TYPE_STS_SHIFT 1 | ||
50 | #define DA7219_JACK_TYPE_STS_MASK (0x1 << 1) | ||
51 | #define DA7219_JACK_PIN_ORDER_STS_SHIFT 2 | ||
52 | #define DA7219_JACK_PIN_ORDER_STS_MASK (0x1 << 2) | ||
53 | #define DA7219_MICBIAS_UP_STS_SHIFT 3 | ||
54 | #define DA7219_MICBIAS_UP_STS_MASK (0x1 << 3) | ||
55 | |||
56 | /* DA7219_ACCDET_STATUS_B = 0xC1 */ | ||
57 | #define DA7219_BUTTON_TYPE_STS_SHIFT 0 | ||
58 | #define DA7219_BUTTON_TYPE_STS_MASK (0xFF << 0) | ||
59 | |||
60 | /* DA7219_ACCDET_IRQ_EVENT_A = 0xC2 */ | ||
61 | #define DA7219_E_JACK_INSERTED_SHIFT 0 | ||
62 | #define DA7219_E_JACK_INSERTED_MASK (0x1 << 0) | ||
63 | #define DA7219_E_JACK_REMOVED_SHIFT 1 | ||
64 | #define DA7219_E_JACK_REMOVED_MASK (0x1 << 1) | ||
65 | #define DA7219_E_JACK_DETECT_COMPLETE_SHIFT 2 | ||
66 | #define DA7219_E_JACK_DETECT_COMPLETE_MASK (0x1 << 2) | ||
67 | |||
68 | /* DA7219_ACCDET_IRQ_EVENT_B = 0xC3 */ | ||
69 | #define DA7219_E_BUTTON_A_PRESSED_SHIFT 0 | ||
70 | #define DA7219_E_BUTTON_A_PRESSED_MASK (0x1 << 0) | ||
71 | #define DA7219_E_BUTTON_B_PRESSED_SHIFT 1 | ||
72 | #define DA7219_E_BUTTON_B_PRESSED_MASK (0x1 << 1) | ||
73 | #define DA7219_E_BUTTON_C_PRESSED_SHIFT 2 | ||
74 | #define DA7219_E_BUTTON_C_PRESSED_MASK (0x1 << 2) | ||
75 | #define DA7219_E_BUTTON_D_PRESSED_SHIFT 3 | ||
76 | #define DA7219_E_BUTTON_D_PRESSED_MASK (0x1 << 3) | ||
77 | #define DA7219_E_BUTTON_D_RELEASED_SHIFT 4 | ||
78 | #define DA7219_E_BUTTON_D_RELEASED_MASK (0x1 << 4) | ||
79 | #define DA7219_E_BUTTON_C_RELEASED_SHIFT 5 | ||
80 | #define DA7219_E_BUTTON_C_RELEASED_MASK (0x1 << 5) | ||
81 | #define DA7219_E_BUTTON_B_RELEASED_SHIFT 6 | ||
82 | #define DA7219_E_BUTTON_B_RELEASED_MASK (0x1 << 6) | ||
83 | #define DA7219_E_BUTTON_A_RELEASED_SHIFT 7 | ||
84 | #define DA7219_E_BUTTON_A_RELEASED_MASK (0x1 << 7) | ||
85 | |||
86 | /* DA7219_ACCDET_IRQ_MASK_A = 0xC4 */ | ||
87 | #define DA7219_M_JACK_INSERTED_SHIFT 0 | ||
88 | #define DA7219_M_JACK_INSERTED_MASK (0x1 << 0) | ||
89 | #define DA7219_M_JACK_REMOVED_SHIFT 1 | ||
90 | #define DA7219_M_JACK_REMOVED_MASK (0x1 << 1) | ||
91 | #define DA7219_M_JACK_DETECT_COMPLETE_SHIFT 2 | ||
92 | #define DA7219_M_JACK_DETECT_COMPLETE_MASK (0x1 << 2) | ||
93 | |||
94 | /* DA7219_ACCDET_IRQ_MASK_B = 0xC5 */ | ||
95 | #define DA7219_M_BUTTON_A_PRESSED_SHIFT 0 | ||
96 | #define DA7219_M_BUTTON_A_PRESSED_MASK (0x1 << 0) | ||
97 | #define DA7219_M_BUTTON_B_PRESSED_SHIFT 1 | ||
98 | #define DA7219_M_BUTTON_B_PRESSED_MASK (0x1 << 1) | ||
99 | #define DA7219_M_BUTTON_C_PRESSED_SHIFT 2 | ||
100 | #define DA7219_M_BUTTON_C_PRESSED_MASK (0x1 << 2) | ||
101 | #define DA7219_M_BUTTON_D_PRESSED_SHIFT 3 | ||
102 | #define DA7219_M_BUTTON_D_PRESSED_MASK (0x1 << 3) | ||
103 | #define DA7219_M_BUTTON_D_RELEASED_SHIFT 4 | ||
104 | #define DA7219_M_BUTTON_D_RELEASED_MASK (0x1 << 4) | ||
105 | #define DA7219_M_BUTTON_C_RELEASED_SHIFT 5 | ||
106 | #define DA7219_M_BUTTON_C_RELEASED_MASK (0x1 << 5) | ||
107 | #define DA7219_M_BUTTON_B_RELEASED_SHIFT 6 | ||
108 | #define DA7219_M_BUTTON_B_RELEASED_MASK (0x1 << 6) | ||
109 | #define DA7219_M_BUTTON_A_RELEASED_SHIFT 7 | ||
110 | #define DA7219_M_BUTTON_A_RELEASED_MASK (0x1 << 7) | ||
111 | |||
112 | /* DA7219_ACCDET_CONFIG_1 = 0xC6 */ | ||
113 | #define DA7219_ACCDET_EN_SHIFT 0 | ||
114 | #define DA7219_ACCDET_EN_MASK (0x1 << 0) | ||
115 | #define DA7219_BUTTON_CONFIG_SHIFT 1 | ||
116 | #define DA7219_BUTTON_CONFIG_MASK (0x7 << 1) | ||
117 | #define DA7219_MIC_DET_THRESH_SHIFT 4 | ||
118 | #define DA7219_MIC_DET_THRESH_MASK (0x3 << 4) | ||
119 | #define DA7219_JACK_TYPE_DET_EN_SHIFT 6 | ||
120 | #define DA7219_JACK_TYPE_DET_EN_MASK (0x1 << 6) | ||
121 | #define DA7219_PIN_ORDER_DET_EN_SHIFT 7 | ||
122 | #define DA7219_PIN_ORDER_DET_EN_MASK (0x1 << 7) | ||
123 | |||
124 | /* DA7219_ACCDET_CONFIG_2 = 0xC7 */ | ||
125 | #define DA7219_ACCDET_PAUSE_SHIFT 0 | ||
126 | #define DA7219_ACCDET_PAUSE_MASK (0x1 << 0) | ||
127 | #define DA7219_JACKDET_DEBOUNCE_SHIFT 1 | ||
128 | #define DA7219_JACKDET_DEBOUNCE_MASK (0x7 << 1) | ||
129 | #define DA7219_JACK_DETECT_RATE_SHIFT 4 | ||
130 | #define DA7219_JACK_DETECT_RATE_MASK (0x3 << 4) | ||
131 | #define DA7219_JACKDET_REM_DEB_SHIFT 6 | ||
132 | #define DA7219_JACKDET_REM_DEB_MASK (0x3 << 6) | ||
133 | |||
134 | /* DA7219_ACCDET_CONFIG_3 = 0xC8 */ | ||
135 | #define DA7219_A_D_BUTTON_THRESH_SHIFT 0 | ||
136 | #define DA7219_A_D_BUTTON_THRESH_MASK (0xFF << 0) | ||
137 | |||
138 | /* DA7219_ACCDET_CONFIG_4 = 0xC9 */ | ||
139 | #define DA7219_D_B_BUTTON_THRESH_SHIFT 0 | ||
140 | #define DA7219_D_B_BUTTON_THRESH_MASK (0xFF << 0) | ||
141 | |||
142 | /* DA7219_ACCDET_CONFIG_5 = 0xCA */ | ||
143 | #define DA7219_B_C_BUTTON_THRESH_SHIFT 0 | ||
144 | #define DA7219_B_C_BUTTON_THRESH_MASK (0xFF << 0) | ||
145 | |||
146 | /* DA7219_ACCDET_CONFIG_6 = 0xCB */ | ||
147 | #define DA7219_C_MIC_BUTTON_THRESH_SHIFT 0 | ||
148 | #define DA7219_C_MIC_BUTTON_THRESH_MASK (0xFF << 0) | ||
149 | |||
150 | /* DA7219_ACCDET_CONFIG_7 = 0xCC */ | ||
151 | #define DA7219_BUTTON_AVERAGE_SHIFT 0 | ||
152 | #define DA7219_BUTTON_AVERAGE_MASK (0x3 << 0) | ||
153 | #define DA7219_ADC_1_BIT_REPEAT_SHIFT 2 | ||
154 | #define DA7219_ADC_1_BIT_REPEAT_MASK (0x3 << 2) | ||
155 | #define DA7219_PIN_ORDER_FORCE_SHIFT 4 | ||
156 | #define DA7219_PIN_ORDER_FORCE_MASK (0x1 << 4) | ||
157 | #define DA7219_JACK_TYPE_FORCE_SHIFT 5 | ||
158 | #define DA7219_JACK_TYPE_FORCE_MASK (0x1 << 5) | ||
159 | |||
160 | /* DA7219_ACCDET_CONFIG_8 = 0xCD */ | ||
161 | #define DA7219_HPTEST_EN_SHIFT 0 | ||
162 | #define DA7219_HPTEST_EN_MASK (0x1 << 0) | ||
163 | #define DA7219_HPTEST_RES_SEL_SHIFT 1 | ||
164 | #define DA7219_HPTEST_RES_SEL_MASK (0x3 << 1) | ||
165 | #define DA7219_HPTEST_RES_SEL_1KOHMS (0x0 << 1) | ||
166 | #define DA7219_HPTEST_COMP_SHIFT 4 | ||
167 | #define DA7219_HPTEST_COMP_MASK (0x1 << 4) | ||
168 | |||
169 | |||
170 | #define DA7219_AAD_MAX_BUTTONS 4 | ||
171 | #define DA7219_AAD_REPORT_ALL_MASK (SND_JACK_MECHANICAL | \ | ||
172 | SND_JACK_HEADSET | SND_JACK_LINEOUT | \ | ||
173 | SND_JACK_BTN_0 | SND_JACK_BTN_1 | \ | ||
174 | SND_JACK_BTN_2 | SND_JACK_BTN_3) | ||
175 | |||
176 | #define DA7219_AAD_MICBIAS_CHK_DELAY 10 | ||
177 | #define DA7219_AAD_MICBIAS_CHK_RETRIES 5 | ||
178 | |||
179 | #define DA7219_AAD_HPTEST_RAMP_FREQ 0x28 | ||
180 | #define DA7219_AAD_HPTEST_PERIOD 65 | ||
181 | |||
182 | enum da7219_aad_event_regs { | ||
183 | DA7219_AAD_IRQ_REG_A = 0, | ||
184 | DA7219_AAD_IRQ_REG_B, | ||
185 | DA7219_AAD_IRQ_REG_MAX, | ||
186 | }; | ||
187 | |||
188 | /* Private data */ | ||
189 | struct da7219_aad_priv { | ||
190 | struct snd_soc_codec *codec; | ||
191 | int irq; | ||
192 | |||
193 | u8 micbias_pulse_lvl; | ||
194 | u32 micbias_pulse_time; | ||
195 | |||
196 | u8 btn_cfg; | ||
197 | |||
198 | struct work_struct btn_det_work; | ||
199 | struct work_struct hptest_work; | ||
200 | |||
201 | struct snd_soc_jack *jack; | ||
202 | bool jack_inserted; | ||
203 | }; | ||
204 | |||
205 | /* AAD control */ | ||
206 | void da7219_aad_jack_det(struct snd_soc_codec *codec, struct snd_soc_jack *jack); | ||
207 | |||
208 | /* Init/Exit */ | ||
209 | int da7219_aad_init(struct snd_soc_codec *codec); | ||
210 | void da7219_aad_exit(struct snd_soc_codec *codec); | ||
211 | |||
212 | #endif /* __DA7219_AAD_H */ | ||
diff --git a/sound/soc/codecs/da7219.c b/sound/soc/codecs/da7219.c new file mode 100644 index 000000000000..f238c1e8a69c --- /dev/null +++ b/sound/soc/codecs/da7219.c | |||
@@ -0,0 +1,1955 @@ | |||
1 | /* | ||
2 | * da7219.c - DA7219 ALSA SoC Codec Driver | ||
3 | * | ||
4 | * Copyright (c) 2015 Dialog Semiconductor | ||
5 | * | ||
6 | * Author: Adam Thomson <Adam.Thomson.Opensource@diasemi.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | */ | ||
13 | |||
14 | #include <linux/clk.h> | ||
15 | #include <linux/i2c.h> | ||
16 | #include <linux/of_device.h> | ||
17 | #include <linux/regmap.h> | ||
18 | #include <linux/slab.h> | ||
19 | #include <linux/pm.h> | ||
20 | #include <linux/module.h> | ||
21 | #include <linux/delay.h> | ||
22 | #include <linux/regulator/consumer.h> | ||
23 | #include <sound/pcm.h> | ||
24 | #include <sound/pcm_params.h> | ||
25 | #include <sound/soc.h> | ||
26 | #include <sound/soc-dapm.h> | ||
27 | #include <sound/initval.h> | ||
28 | #include <sound/tlv.h> | ||
29 | #include <asm/div64.h> | ||
30 | |||
31 | #include <sound/da7219.h> | ||
32 | #include "da7219.h" | ||
33 | #include "da7219-aad.h" | ||
34 | |||
35 | |||
36 | /* | ||
37 | * TLVs and Enums | ||
38 | */ | ||
39 | |||
40 | /* Input TLVs */ | ||
41 | static const DECLARE_TLV_DB_SCALE(da7219_mic_gain_tlv, -600, 600, 0); | ||
42 | static const DECLARE_TLV_DB_SCALE(da7219_mixin_gain_tlv, -450, 150, 0); | ||
43 | static const DECLARE_TLV_DB_SCALE(da7219_adc_dig_gain_tlv, -8325, 75, 0); | ||
44 | static const DECLARE_TLV_DB_SCALE(da7219_alc_threshold_tlv, -9450, 150, 0); | ||
45 | static const DECLARE_TLV_DB_SCALE(da7219_alc_gain_tlv, 0, 600, 0); | ||
46 | static const DECLARE_TLV_DB_SCALE(da7219_alc_ana_gain_tlv, 0, 600, 0); | ||
47 | static const DECLARE_TLV_DB_SCALE(da7219_sidetone_gain_tlv, -4200, 300, 0); | ||
48 | static const DECLARE_TLV_DB_SCALE(da7219_tonegen_gain_tlv, -4500, 300, 0); | ||
49 | |||
50 | /* Output TLVs */ | ||
51 | static const DECLARE_TLV_DB_SCALE(da7219_dac_eq_band_tlv, -1050, 150, 0); | ||
52 | |||
53 | static const DECLARE_TLV_DB_RANGE(da7219_dac_dig_gain_tlv, | ||
54 | 0x0, 0x07, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 1), | ||
55 | /* -77.25dB to 12dB */ | ||
56 | 0x08, 0x7f, TLV_DB_SCALE_ITEM(-7725, 75, 0) | ||
57 | ); | ||
58 | |||
59 | static const DECLARE_TLV_DB_SCALE(da7219_dac_ng_threshold_tlv, -10200, 600, 0); | ||
60 | static const DECLARE_TLV_DB_SCALE(da7219_hp_gain_tlv, -5700, 100, 0); | ||
61 | |||
62 | /* Input Enums */ | ||
63 | static const char * const da7219_alc_attack_rate_txt[] = { | ||
64 | "7.33/fs", "14.66/fs", "29.32/fs", "58.64/fs", "117.3/fs", "234.6/fs", | ||
65 | "469.1/fs", "938.2/fs", "1876/fs", "3753/fs", "7506/fs", "15012/fs", | ||
66 | "30024/fs" | ||
67 | }; | ||
68 | |||
69 | static const struct soc_enum da7219_alc_attack_rate = | ||
70 | SOC_ENUM_SINGLE(DA7219_ALC_CTRL2, DA7219_ALC_ATTACK_SHIFT, | ||
71 | DA7219_ALC_ATTACK_MAX, da7219_alc_attack_rate_txt); | ||
72 | |||
73 | static const char * const da7219_alc_release_rate_txt[] = { | ||
74 | "28.66/fs", "57.33/fs", "114.6/fs", "229.3/fs", "458.6/fs", "917.1/fs", | ||
75 | "1834/fs", "3668/fs", "7337/fs", "14674/fs", "29348/fs" | ||
76 | }; | ||
77 | |||
78 | static const struct soc_enum da7219_alc_release_rate = | ||
79 | SOC_ENUM_SINGLE(DA7219_ALC_CTRL2, DA7219_ALC_RELEASE_SHIFT, | ||
80 | DA7219_ALC_RELEASE_MAX, da7219_alc_release_rate_txt); | ||
81 | |||
82 | static const char * const da7219_alc_hold_time_txt[] = { | ||
83 | "62/fs", "124/fs", "248/fs", "496/fs", "992/fs", "1984/fs", "3968/fs", | ||
84 | "7936/fs", "15872/fs", "31744/fs", "63488/fs", "126976/fs", | ||
85 | "253952/fs", "507904/fs", "1015808/fs", "2031616/fs" | ||
86 | }; | ||
87 | |||
88 | static const struct soc_enum da7219_alc_hold_time = | ||
89 | SOC_ENUM_SINGLE(DA7219_ALC_CTRL3, DA7219_ALC_HOLD_SHIFT, | ||
90 | DA7219_ALC_HOLD_MAX, da7219_alc_hold_time_txt); | ||
91 | |||
92 | static const char * const da7219_alc_env_rate_txt[] = { | ||
93 | "1/4", "1/16", "1/256", "1/65536" | ||
94 | }; | ||
95 | |||
96 | static const struct soc_enum da7219_alc_env_attack_rate = | ||
97 | SOC_ENUM_SINGLE(DA7219_ALC_CTRL3, DA7219_ALC_INTEG_ATTACK_SHIFT, | ||
98 | DA7219_ALC_INTEG_MAX, da7219_alc_env_rate_txt); | ||
99 | |||
100 | static const struct soc_enum da7219_alc_env_release_rate = | ||
101 | SOC_ENUM_SINGLE(DA7219_ALC_CTRL3, DA7219_ALC_INTEG_RELEASE_SHIFT, | ||
102 | DA7219_ALC_INTEG_MAX, da7219_alc_env_rate_txt); | ||
103 | |||
104 | static const char * const da7219_alc_anticlip_step_txt[] = { | ||
105 | "0.034dB/fs", "0.068dB/fs", "0.136dB/fs", "0.272dB/fs" | ||
106 | }; | ||
107 | |||
108 | static const struct soc_enum da7219_alc_anticlip_step = | ||
109 | SOC_ENUM_SINGLE(DA7219_ALC_ANTICLIP_CTRL, | ||
110 | DA7219_ALC_ANTICLIP_STEP_SHIFT, | ||
111 | DA7219_ALC_ANTICLIP_STEP_MAX, | ||
112 | da7219_alc_anticlip_step_txt); | ||
113 | |||
114 | /* Input/Output Enums */ | ||
115 | static const char * const da7219_gain_ramp_rate_txt[] = { | ||
116 | "Nominal Rate * 8", "Nominal Rate", "Nominal Rate / 8", | ||
117 | "Nominal Rate / 16" | ||
118 | }; | ||
119 | |||
120 | static const struct soc_enum da7219_gain_ramp_rate = | ||
121 | SOC_ENUM_SINGLE(DA7219_GAIN_RAMP_CTRL, DA7219_GAIN_RAMP_RATE_SHIFT, | ||
122 | DA7219_GAIN_RAMP_RATE_MAX, da7219_gain_ramp_rate_txt); | ||
123 | |||
124 | static const char * const da7219_hpf_mode_txt[] = { | ||
125 | "Disabled", "Audio", "Voice" | ||
126 | }; | ||
127 | |||
128 | static const unsigned int da7219_hpf_mode_val[] = { | ||
129 | DA7219_HPF_DISABLED, DA7219_HPF_AUDIO_EN, DA7219_HPF_VOICE_EN, | ||
130 | }; | ||
131 | |||
132 | static const struct soc_enum da7219_adc_hpf_mode = | ||
133 | SOC_VALUE_ENUM_SINGLE(DA7219_ADC_FILTERS1, DA7219_HPF_MODE_SHIFT, | ||
134 | DA7219_HPF_MODE_MASK, DA7219_HPF_MODE_MAX, | ||
135 | da7219_hpf_mode_txt, da7219_hpf_mode_val); | ||
136 | |||
137 | static const struct soc_enum da7219_dac_hpf_mode = | ||
138 | SOC_VALUE_ENUM_SINGLE(DA7219_DAC_FILTERS1, DA7219_HPF_MODE_SHIFT, | ||
139 | DA7219_HPF_MODE_MASK, DA7219_HPF_MODE_MAX, | ||
140 | da7219_hpf_mode_txt, da7219_hpf_mode_val); | ||
141 | |||
142 | static const char * const da7219_audio_hpf_corner_txt[] = { | ||
143 | "2Hz", "4Hz", "8Hz", "16Hz" | ||
144 | }; | ||
145 | |||
146 | static const struct soc_enum da7219_adc_audio_hpf_corner = | ||
147 | SOC_ENUM_SINGLE(DA7219_ADC_FILTERS1, | ||
148 | DA7219_ADC_AUDIO_HPF_CORNER_SHIFT, | ||
149 | DA7219_AUDIO_HPF_CORNER_MAX, | ||
150 | da7219_audio_hpf_corner_txt); | ||
151 | |||
152 | static const struct soc_enum da7219_dac_audio_hpf_corner = | ||
153 | SOC_ENUM_SINGLE(DA7219_DAC_FILTERS1, | ||
154 | DA7219_DAC_AUDIO_HPF_CORNER_SHIFT, | ||
155 | DA7219_AUDIO_HPF_CORNER_MAX, | ||
156 | da7219_audio_hpf_corner_txt); | ||
157 | |||
158 | static const char * const da7219_voice_hpf_corner_txt[] = { | ||
159 | "2.5Hz", "25Hz", "50Hz", "100Hz", "150Hz", "200Hz", "300Hz", "400Hz" | ||
160 | }; | ||
161 | |||
162 | static const struct soc_enum da7219_adc_voice_hpf_corner = | ||
163 | SOC_ENUM_SINGLE(DA7219_ADC_FILTERS1, | ||
164 | DA7219_ADC_VOICE_HPF_CORNER_SHIFT, | ||
165 | DA7219_VOICE_HPF_CORNER_MAX, | ||
166 | da7219_voice_hpf_corner_txt); | ||
167 | |||
168 | static const struct soc_enum da7219_dac_voice_hpf_corner = | ||
169 | SOC_ENUM_SINGLE(DA7219_DAC_FILTERS1, | ||
170 | DA7219_DAC_VOICE_HPF_CORNER_SHIFT, | ||
171 | DA7219_VOICE_HPF_CORNER_MAX, | ||
172 | da7219_voice_hpf_corner_txt); | ||
173 | |||
174 | static const char * const da7219_tonegen_dtmf_key_txt[] = { | ||
175 | "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", | ||
176 | "*", "#" | ||
177 | }; | ||
178 | |||
179 | static const struct soc_enum da7219_tonegen_dtmf_key = | ||
180 | SOC_ENUM_SINGLE(DA7219_TONE_GEN_CFG1, DA7219_DTMF_REG_SHIFT, | ||
181 | DA7219_DTMF_REG_MAX, da7219_tonegen_dtmf_key_txt); | ||
182 | |||
183 | static const char * const da7219_tonegen_swg_sel_txt[] = { | ||
184 | "Sum", "SWG1", "SWG2", "SWG1_1-Cos" | ||
185 | }; | ||
186 | |||
187 | static const struct soc_enum da7219_tonegen_swg_sel = | ||
188 | SOC_ENUM_SINGLE(DA7219_TONE_GEN_CFG2, DA7219_SWG_SEL_SHIFT, | ||
189 | DA7219_SWG_SEL_MAX, da7219_tonegen_swg_sel_txt); | ||
190 | |||
191 | /* Output Enums */ | ||
192 | static const char * const da7219_dac_softmute_rate_txt[] = { | ||
193 | "1 Sample", "2 Samples", "4 Samples", "8 Samples", "16 Samples", | ||
194 | "32 Samples", "64 Samples" | ||
195 | }; | ||
196 | |||
197 | static const struct soc_enum da7219_dac_softmute_rate = | ||
198 | SOC_ENUM_SINGLE(DA7219_DAC_FILTERS5, DA7219_DAC_SOFTMUTE_RATE_SHIFT, | ||
199 | DA7219_DAC_SOFTMUTE_RATE_MAX, | ||
200 | da7219_dac_softmute_rate_txt); | ||
201 | |||
202 | static const char * const da7219_dac_ng_setup_time_txt[] = { | ||
203 | "256 Samples", "512 Samples", "1024 Samples", "2048 Samples" | ||
204 | }; | ||
205 | |||
206 | static const struct soc_enum da7219_dac_ng_setup_time = | ||
207 | SOC_ENUM_SINGLE(DA7219_DAC_NG_SETUP_TIME, | ||
208 | DA7219_DAC_NG_SETUP_TIME_SHIFT, | ||
209 | DA7219_DAC_NG_SETUP_TIME_MAX, | ||
210 | da7219_dac_ng_setup_time_txt); | ||
211 | |||
212 | static const char * const da7219_dac_ng_rampup_txt[] = { | ||
213 | "0.22ms/dB", "0.0138ms/dB" | ||
214 | }; | ||
215 | |||
216 | static const struct soc_enum da7219_dac_ng_rampup_rate = | ||
217 | SOC_ENUM_SINGLE(DA7219_DAC_NG_SETUP_TIME, | ||
218 | DA7219_DAC_NG_RAMPUP_RATE_SHIFT, | ||
219 | DA7219_DAC_NG_RAMP_RATE_MAX, | ||
220 | da7219_dac_ng_rampup_txt); | ||
221 | |||
222 | static const char * const da7219_dac_ng_rampdown_txt[] = { | ||
223 | "0.88ms/dB", "14.08ms/dB" | ||
224 | }; | ||
225 | |||
226 | static const struct soc_enum da7219_dac_ng_rampdown_rate = | ||
227 | SOC_ENUM_SINGLE(DA7219_DAC_NG_SETUP_TIME, | ||
228 | DA7219_DAC_NG_RAMPDN_RATE_SHIFT, | ||
229 | DA7219_DAC_NG_RAMP_RATE_MAX, | ||
230 | da7219_dac_ng_rampdown_txt); | ||
231 | |||
232 | |||
233 | static const char * const da7219_cp_track_mode_txt[] = { | ||
234 | "Largest Volume", "DAC Volume", "Signal Magnitude" | ||
235 | }; | ||
236 | |||
237 | static const unsigned int da7219_cp_track_mode_val[] = { | ||
238 | DA7219_CP_MCHANGE_LARGEST_VOL, DA7219_CP_MCHANGE_DAC_VOL, | ||
239 | DA7219_CP_MCHANGE_SIG_MAG | ||
240 | }; | ||
241 | |||
242 | static const struct soc_enum da7219_cp_track_mode = | ||
243 | SOC_VALUE_ENUM_SINGLE(DA7219_CP_CTRL, DA7219_CP_MCHANGE_SHIFT, | ||
244 | DA7219_CP_MCHANGE_REL_MASK, DA7219_CP_MCHANGE_MAX, | ||
245 | da7219_cp_track_mode_txt, | ||
246 | da7219_cp_track_mode_val); | ||
247 | |||
248 | |||
249 | /* | ||
250 | * Control Functions | ||
251 | */ | ||
252 | |||
253 | /* Locked Kcontrol calls */ | ||
254 | static int da7219_volsw_locked_get(struct snd_kcontrol *kcontrol, | ||
255 | struct snd_ctl_elem_value *ucontrol) | ||
256 | { | ||
257 | struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); | ||
258 | struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); | ||
259 | int ret; | ||
260 | |||
261 | mutex_lock(&da7219->lock); | ||
262 | ret = snd_soc_get_volsw(kcontrol, ucontrol); | ||
263 | mutex_unlock(&da7219->lock); | ||
264 | |||
265 | return ret; | ||
266 | } | ||
267 | |||
268 | static int da7219_volsw_locked_put(struct snd_kcontrol *kcontrol, | ||
269 | struct snd_ctl_elem_value *ucontrol) | ||
270 | { | ||
271 | struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); | ||
272 | struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); | ||
273 | int ret; | ||
274 | |||
275 | mutex_lock(&da7219->lock); | ||
276 | ret = snd_soc_put_volsw(kcontrol, ucontrol); | ||
277 | mutex_unlock(&da7219->lock); | ||
278 | |||
279 | return ret; | ||
280 | } | ||
281 | |||
282 | static int da7219_enum_locked_get(struct snd_kcontrol *kcontrol, | ||
283 | struct snd_ctl_elem_value *ucontrol) | ||
284 | { | ||
285 | struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); | ||
286 | struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); | ||
287 | int ret; | ||
288 | |||
289 | mutex_lock(&da7219->lock); | ||
290 | ret = snd_soc_get_enum_double(kcontrol, ucontrol); | ||
291 | mutex_unlock(&da7219->lock); | ||
292 | |||
293 | return ret; | ||
294 | } | ||
295 | |||
296 | static int da7219_enum_locked_put(struct snd_kcontrol *kcontrol, | ||
297 | struct snd_ctl_elem_value *ucontrol) | ||
298 | { | ||
299 | struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); | ||
300 | struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); | ||
301 | int ret; | ||
302 | |||
303 | mutex_lock(&da7219->lock); | ||
304 | ret = snd_soc_put_enum_double(kcontrol, ucontrol); | ||
305 | mutex_unlock(&da7219->lock); | ||
306 | |||
307 | return ret; | ||
308 | } | ||
309 | |||
310 | /* ALC */ | ||
311 | static void da7219_alc_calib(struct snd_soc_codec *codec) | ||
312 | { | ||
313 | u8 mic_ctrl, mixin_ctrl, adc_ctrl, calib_ctrl; | ||
314 | |||
315 | /* Save current state of mic control register */ | ||
316 | mic_ctrl = snd_soc_read(codec, DA7219_MIC_1_CTRL); | ||
317 | |||
318 | /* Save current state of input mixer control register */ | ||
319 | mixin_ctrl = snd_soc_read(codec, DA7219_MIXIN_L_CTRL); | ||
320 | |||
321 | /* Save current state of input ADC control register */ | ||
322 | adc_ctrl = snd_soc_read(codec, DA7219_ADC_L_CTRL); | ||
323 | |||
324 | /* Enable then Mute MIC PGAs */ | ||
325 | snd_soc_update_bits(codec, DA7219_MIC_1_CTRL, DA7219_MIC_1_AMP_EN_MASK, | ||
326 | DA7219_MIC_1_AMP_EN_MASK); | ||
327 | snd_soc_update_bits(codec, DA7219_MIC_1_CTRL, | ||
328 | DA7219_MIC_1_AMP_MUTE_EN_MASK, | ||
329 | DA7219_MIC_1_AMP_MUTE_EN_MASK); | ||
330 | |||
331 | /* Enable input mixers unmuted */ | ||
332 | snd_soc_update_bits(codec, DA7219_MIXIN_L_CTRL, | ||
333 | DA7219_MIXIN_L_AMP_EN_MASK | | ||
334 | DA7219_MIXIN_L_AMP_MUTE_EN_MASK, | ||
335 | DA7219_MIXIN_L_AMP_EN_MASK); | ||
336 | |||
337 | /* Enable input filters unmuted */ | ||
338 | snd_soc_update_bits(codec, DA7219_ADC_L_CTRL, | ||
339 | DA7219_ADC_L_MUTE_EN_MASK | DA7219_ADC_L_EN_MASK, | ||
340 | DA7219_ADC_L_EN_MASK); | ||
341 | |||
342 | /* Perform auto calibration */ | ||
343 | snd_soc_update_bits(codec, DA7219_ALC_CTRL1, | ||
344 | DA7219_ALC_AUTO_CALIB_EN_MASK, | ||
345 | DA7219_ALC_AUTO_CALIB_EN_MASK); | ||
346 | do { | ||
347 | calib_ctrl = snd_soc_read(codec, DA7219_ALC_CTRL1); | ||
348 | } while (calib_ctrl & DA7219_ALC_AUTO_CALIB_EN_MASK); | ||
349 | |||
350 | /* If auto calibration fails, disable DC offset, hybrid ALC */ | ||
351 | if (calib_ctrl & DA7219_ALC_CALIB_OVERFLOW_MASK) { | ||
352 | dev_warn(codec->dev, | ||
353 | "ALC auto calibration failed with overflow\n"); | ||
354 | snd_soc_update_bits(codec, DA7219_ALC_CTRL1, | ||
355 | DA7219_ALC_OFFSET_EN_MASK | | ||
356 | DA7219_ALC_SYNC_MODE_MASK, 0); | ||
357 | } else { | ||
358 | /* Enable DC offset cancellation, hybrid mode */ | ||
359 | snd_soc_update_bits(codec, DA7219_ALC_CTRL1, | ||
360 | DA7219_ALC_OFFSET_EN_MASK | | ||
361 | DA7219_ALC_SYNC_MODE_MASK, | ||
362 | DA7219_ALC_OFFSET_EN_MASK | | ||
363 | DA7219_ALC_SYNC_MODE_MASK); | ||
364 | } | ||
365 | |||
366 | /* Restore input filter control register to original state */ | ||
367 | snd_soc_write(codec, DA7219_ADC_L_CTRL, adc_ctrl); | ||
368 | |||
369 | /* Restore input mixer control registers to original state */ | ||
370 | snd_soc_write(codec, DA7219_MIXIN_L_CTRL, mixin_ctrl); | ||
371 | |||
372 | /* Restore MIC control registers to original states */ | ||
373 | snd_soc_write(codec, DA7219_MIC_1_CTRL, mic_ctrl); | ||
374 | } | ||
375 | |||
376 | static int da7219_mixin_gain_put(struct snd_kcontrol *kcontrol, | ||
377 | struct snd_ctl_elem_value *ucontrol) | ||
378 | { | ||
379 | struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); | ||
380 | struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); | ||
381 | int ret; | ||
382 | |||
383 | ret = snd_soc_put_volsw(kcontrol, ucontrol); | ||
384 | |||
385 | /* | ||
386 | * If ALC in operation and value of control has been updated, | ||
387 | * make sure calibrated offsets are updated. | ||
388 | */ | ||
389 | if ((ret == 1) && (da7219->alc_en)) | ||
390 | da7219_alc_calib(codec); | ||
391 | |||
392 | return ret; | ||
393 | } | ||
394 | |||
395 | static int da7219_alc_sw_put(struct snd_kcontrol *kcontrol, | ||
396 | struct snd_ctl_elem_value *ucontrol) | ||
397 | { | ||
398 | struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); | ||
399 | struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); | ||
400 | |||
401 | |||
402 | /* Force ALC offset calibration if enabling ALC */ | ||
403 | if ((ucontrol->value.integer.value[0]) && (!da7219->alc_en)) { | ||
404 | da7219_alc_calib(codec); | ||
405 | da7219->alc_en = true; | ||
406 | } else { | ||
407 | da7219->alc_en = false; | ||
408 | } | ||
409 | |||
410 | return snd_soc_put_volsw(kcontrol, ucontrol); | ||
411 | } | ||
412 | |||
413 | /* ToneGen */ | ||
414 | static int da7219_tonegen_freq_get(struct snd_kcontrol *kcontrol, | ||
415 | struct snd_ctl_elem_value *ucontrol) | ||
416 | { | ||
417 | struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); | ||
418 | struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); | ||
419 | struct soc_mixer_control *mixer_ctrl = | ||
420 | (struct soc_mixer_control *) kcontrol->private_value; | ||
421 | unsigned int reg = mixer_ctrl->reg; | ||
422 | u16 val; | ||
423 | int ret; | ||
424 | |||
425 | mutex_lock(&da7219->lock); | ||
426 | ret = regmap_raw_read(da7219->regmap, reg, &val, sizeof(val)); | ||
427 | mutex_unlock(&da7219->lock); | ||
428 | |||
429 | if (ret) | ||
430 | return ret; | ||
431 | |||
432 | /* | ||
433 | * Frequency value spans two 8-bit registers, lower then upper byte. | ||
434 | * Therefore we need to convert to host endianness here. | ||
435 | */ | ||
436 | ucontrol->value.integer.value[0] = le16_to_cpu(val); | ||
437 | |||
438 | return 0; | ||
439 | } | ||
440 | |||
441 | static int da7219_tonegen_freq_put(struct snd_kcontrol *kcontrol, | ||
442 | struct snd_ctl_elem_value *ucontrol) | ||
443 | { | ||
444 | struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); | ||
445 | struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); | ||
446 | struct soc_mixer_control *mixer_ctrl = | ||
447 | (struct soc_mixer_control *) kcontrol->private_value; | ||
448 | unsigned int reg = mixer_ctrl->reg; | ||
449 | u16 val; | ||
450 | int ret; | ||
451 | |||
452 | /* | ||
453 | * Frequency value spans two 8-bit registers, lower then upper byte. | ||
454 | * Therefore we need to convert to little endian here to align with | ||
455 | * HW registers. | ||
456 | */ | ||
457 | val = cpu_to_le16(ucontrol->value.integer.value[0]); | ||
458 | |||
459 | mutex_lock(&da7219->lock); | ||
460 | ret = regmap_raw_write(da7219->regmap, reg, &val, sizeof(val)); | ||
461 | mutex_unlock(&da7219->lock); | ||
462 | |||
463 | return ret; | ||
464 | } | ||
465 | |||
466 | |||
467 | /* | ||
468 | * KControls | ||
469 | */ | ||
470 | |||
471 | static const struct snd_kcontrol_new da7219_snd_controls[] = { | ||
472 | /* Mics */ | ||
473 | SOC_SINGLE_TLV("Mic Volume", DA7219_MIC_1_GAIN, | ||
474 | DA7219_MIC_1_AMP_GAIN_SHIFT, DA7219_MIC_1_AMP_GAIN_MAX, | ||
475 | DA7219_NO_INVERT, da7219_mic_gain_tlv), | ||
476 | SOC_SINGLE("Mic Switch", DA7219_MIC_1_CTRL, | ||
477 | DA7219_MIC_1_AMP_MUTE_EN_SHIFT, DA7219_SWITCH_EN_MAX, | ||
478 | DA7219_INVERT), | ||
479 | |||
480 | /* Mixer Input */ | ||
481 | SOC_SINGLE_EXT_TLV("Mixin Volume", DA7219_MIXIN_L_GAIN, | ||
482 | DA7219_MIXIN_L_AMP_GAIN_SHIFT, | ||
483 | DA7219_MIXIN_L_AMP_GAIN_MAX, DA7219_NO_INVERT, | ||
484 | snd_soc_get_volsw, da7219_mixin_gain_put, | ||
485 | da7219_mixin_gain_tlv), | ||
486 | SOC_SINGLE("Mixin Switch", DA7219_MIXIN_L_CTRL, | ||
487 | DA7219_MIXIN_L_AMP_MUTE_EN_SHIFT, DA7219_SWITCH_EN_MAX, | ||
488 | DA7219_INVERT), | ||
489 | SOC_SINGLE("Mixin Gain Ramp Switch", DA7219_MIXIN_L_CTRL, | ||
490 | DA7219_MIXIN_L_AMP_RAMP_EN_SHIFT, DA7219_SWITCH_EN_MAX, | ||
491 | DA7219_NO_INVERT), | ||
492 | SOC_SINGLE("Mixin ZC Gain Switch", DA7219_MIXIN_L_CTRL, | ||
493 | DA7219_MIXIN_L_AMP_ZC_EN_SHIFT, DA7219_SWITCH_EN_MAX, | ||
494 | DA7219_NO_INVERT), | ||
495 | |||
496 | /* ADC */ | ||
497 | SOC_SINGLE_TLV("Capture Digital Volume", DA7219_ADC_L_GAIN, | ||
498 | DA7219_ADC_L_DIGITAL_GAIN_SHIFT, | ||
499 | DA7219_ADC_L_DIGITAL_GAIN_MAX, DA7219_NO_INVERT, | ||
500 | da7219_adc_dig_gain_tlv), | ||
501 | SOC_SINGLE("Capture Digital Switch", DA7219_ADC_L_CTRL, | ||
502 | DA7219_ADC_L_MUTE_EN_SHIFT, DA7219_SWITCH_EN_MAX, | ||
503 | DA7219_INVERT), | ||
504 | SOC_SINGLE("Capture Digital Gain Ramp Switch", DA7219_ADC_L_CTRL, | ||
505 | DA7219_ADC_L_RAMP_EN_SHIFT, DA7219_SWITCH_EN_MAX, | ||
506 | DA7219_NO_INVERT), | ||
507 | |||
508 | /* ALC */ | ||
509 | SOC_ENUM("ALC Attack Rate", da7219_alc_attack_rate), | ||
510 | SOC_ENUM("ALC Release Rate", da7219_alc_release_rate), | ||
511 | SOC_ENUM("ALC Hold Time", da7219_alc_hold_time), | ||
512 | SOC_ENUM("ALC Envelope Attack Rate", da7219_alc_env_attack_rate), | ||
513 | SOC_ENUM("ALC Envelope Release Rate", da7219_alc_env_release_rate), | ||
514 | SOC_SINGLE_TLV("ALC Noise Threshold", DA7219_ALC_NOISE, | ||
515 | DA7219_ALC_NOISE_SHIFT, DA7219_ALC_THRESHOLD_MAX, | ||
516 | DA7219_INVERT, da7219_alc_threshold_tlv), | ||
517 | SOC_SINGLE_TLV("ALC Min Threshold", DA7219_ALC_TARGET_MIN, | ||
518 | DA7219_ALC_THRESHOLD_MIN_SHIFT, DA7219_ALC_THRESHOLD_MAX, | ||
519 | DA7219_INVERT, da7219_alc_threshold_tlv), | ||
520 | SOC_SINGLE_TLV("ALC Max Threshold", DA7219_ALC_TARGET_MAX, | ||
521 | DA7219_ALC_THRESHOLD_MAX_SHIFT, DA7219_ALC_THRESHOLD_MAX, | ||
522 | DA7219_INVERT, da7219_alc_threshold_tlv), | ||
523 | SOC_SINGLE_TLV("ALC Max Attenuation", DA7219_ALC_GAIN_LIMITS, | ||
524 | DA7219_ALC_ATTEN_MAX_SHIFT, DA7219_ALC_ATTEN_GAIN_MAX, | ||
525 | DA7219_NO_INVERT, da7219_alc_gain_tlv), | ||
526 | SOC_SINGLE_TLV("ALC Max Volume", DA7219_ALC_GAIN_LIMITS, | ||
527 | DA7219_ALC_GAIN_MAX_SHIFT, DA7219_ALC_ATTEN_GAIN_MAX, | ||
528 | DA7219_NO_INVERT, da7219_alc_gain_tlv), | ||
529 | SOC_SINGLE_RANGE_TLV("ALC Min Analog Volume", DA7219_ALC_ANA_GAIN_LIMITS, | ||
530 | DA7219_ALC_ANA_GAIN_MIN_SHIFT, | ||
531 | DA7219_ALC_ANA_GAIN_MIN, DA7219_ALC_ANA_GAIN_MAX, | ||
532 | DA7219_NO_INVERT, da7219_alc_ana_gain_tlv), | ||
533 | SOC_SINGLE_RANGE_TLV("ALC Max Analog Volume", DA7219_ALC_ANA_GAIN_LIMITS, | ||
534 | DA7219_ALC_ANA_GAIN_MAX_SHIFT, | ||
535 | DA7219_ALC_ANA_GAIN_MIN, DA7219_ALC_ANA_GAIN_MAX, | ||
536 | DA7219_NO_INVERT, da7219_alc_ana_gain_tlv), | ||
537 | SOC_ENUM("ALC Anticlip Step", da7219_alc_anticlip_step), | ||
538 | SOC_SINGLE("ALC Anticlip Switch", DA7219_ALC_ANTICLIP_CTRL, | ||
539 | DA7219_ALC_ANTIPCLIP_EN_SHIFT, DA7219_SWITCH_EN_MAX, | ||
540 | DA7219_NO_INVERT), | ||
541 | SOC_SINGLE_EXT("ALC Switch", DA7219_ALC_CTRL1, DA7219_ALC_EN_SHIFT, | ||
542 | DA7219_SWITCH_EN_MAX, DA7219_NO_INVERT, | ||
543 | snd_soc_get_volsw, da7219_alc_sw_put), | ||
544 | |||
545 | /* Input High-Pass Filters */ | ||
546 | SOC_ENUM("ADC HPF Mode", da7219_adc_hpf_mode), | ||
547 | SOC_ENUM("ADC HPF Corner Audio", da7219_adc_audio_hpf_corner), | ||
548 | SOC_ENUM("ADC HPF Corner Voice", da7219_adc_voice_hpf_corner), | ||
549 | |||
550 | /* Sidetone Filter */ | ||
551 | SOC_SINGLE_TLV("Sidetone Volume", DA7219_SIDETONE_GAIN, | ||
552 | DA7219_SIDETONE_GAIN_SHIFT, DA7219_SIDETONE_GAIN_MAX, | ||
553 | DA7219_NO_INVERT, da7219_sidetone_gain_tlv), | ||
554 | SOC_SINGLE("Sidetone Switch", DA7219_SIDETONE_CTRL, | ||
555 | DA7219_SIDETONE_MUTE_EN_SHIFT, DA7219_SWITCH_EN_MAX, | ||
556 | DA7219_INVERT), | ||
557 | |||
558 | /* Tone Generator */ | ||
559 | SOC_SINGLE_EXT_TLV("ToneGen Volume", DA7219_TONE_GEN_CFG2, | ||
560 | DA7219_TONE_GEN_GAIN_SHIFT, DA7219_TONE_GEN_GAIN_MAX, | ||
561 | DA7219_NO_INVERT, da7219_volsw_locked_get, | ||
562 | da7219_volsw_locked_put, da7219_tonegen_gain_tlv), | ||
563 | SOC_ENUM_EXT("ToneGen DTMF Key", da7219_tonegen_dtmf_key, | ||
564 | da7219_enum_locked_get, da7219_enum_locked_put), | ||
565 | SOC_SINGLE_EXT("ToneGen DTMF Switch", DA7219_TONE_GEN_CFG1, | ||
566 | DA7219_DTMF_EN_SHIFT, DA7219_SWITCH_EN_MAX, | ||
567 | DA7219_NO_INVERT, da7219_volsw_locked_get, | ||
568 | da7219_volsw_locked_put), | ||
569 | SOC_ENUM_EXT("ToneGen Sinewave Gen Type", da7219_tonegen_swg_sel, | ||
570 | da7219_enum_locked_get, da7219_enum_locked_put), | ||
571 | SOC_SINGLE_EXT("ToneGen Sinewave1 Freq", DA7219_TONE_GEN_FREQ1_L, | ||
572 | DA7219_FREQ1_L_SHIFT, DA7219_FREQ_MAX, DA7219_NO_INVERT, | ||
573 | da7219_tonegen_freq_get, da7219_tonegen_freq_put), | ||
574 | SOC_SINGLE_EXT("ToneGen Sinewave2 Freq", DA7219_TONE_GEN_FREQ2_L, | ||
575 | DA7219_FREQ2_L_SHIFT, DA7219_FREQ_MAX, DA7219_NO_INVERT, | ||
576 | da7219_tonegen_freq_get, da7219_tonegen_freq_put), | ||
577 | SOC_SINGLE_EXT("ToneGen On Time", DA7219_TONE_GEN_ON_PER, | ||
578 | DA7219_BEEP_ON_PER_SHIFT, DA7219_BEEP_ON_OFF_MAX, | ||
579 | DA7219_NO_INVERT, da7219_volsw_locked_get, | ||
580 | da7219_volsw_locked_put), | ||
581 | SOC_SINGLE("ToneGen Off Time", DA7219_TONE_GEN_OFF_PER, | ||
582 | DA7219_BEEP_OFF_PER_SHIFT, DA7219_BEEP_ON_OFF_MAX, | ||
583 | DA7219_NO_INVERT), | ||
584 | |||
585 | /* Gain ramping */ | ||
586 | SOC_ENUM("Gain Ramp Rate", da7219_gain_ramp_rate), | ||
587 | |||
588 | /* DAC High-Pass Filter */ | ||
589 | SOC_ENUM_EXT("DAC HPF Mode", da7219_dac_hpf_mode, | ||
590 | da7219_enum_locked_get, da7219_enum_locked_put), | ||
591 | SOC_ENUM("DAC HPF Corner Audio", da7219_dac_audio_hpf_corner), | ||
592 | SOC_ENUM("DAC HPF Corner Voice", da7219_dac_voice_hpf_corner), | ||
593 | |||
594 | /* DAC 5-Band Equaliser */ | ||
595 | SOC_SINGLE_TLV("DAC EQ Band1 Volume", DA7219_DAC_FILTERS2, | ||
596 | DA7219_DAC_EQ_BAND1_SHIFT, DA7219_DAC_EQ_BAND_MAX, | ||
597 | DA7219_NO_INVERT, da7219_dac_eq_band_tlv), | ||
598 | SOC_SINGLE_TLV("DAC EQ Band2 Volume", DA7219_DAC_FILTERS2, | ||
599 | DA7219_DAC_EQ_BAND2_SHIFT, DA7219_DAC_EQ_BAND_MAX, | ||
600 | DA7219_NO_INVERT, da7219_dac_eq_band_tlv), | ||
601 | SOC_SINGLE_TLV("DAC EQ Band3 Volume", DA7219_DAC_FILTERS3, | ||
602 | DA7219_DAC_EQ_BAND3_SHIFT, DA7219_DAC_EQ_BAND_MAX, | ||
603 | DA7219_NO_INVERT, da7219_dac_eq_band_tlv), | ||
604 | SOC_SINGLE_TLV("DAC EQ Band4 Volume", DA7219_DAC_FILTERS3, | ||
605 | DA7219_DAC_EQ_BAND4_SHIFT, DA7219_DAC_EQ_BAND_MAX, | ||
606 | DA7219_NO_INVERT, da7219_dac_eq_band_tlv), | ||
607 | SOC_SINGLE_TLV("DAC EQ Band5 Volume", DA7219_DAC_FILTERS4, | ||
608 | DA7219_DAC_EQ_BAND5_SHIFT, DA7219_DAC_EQ_BAND_MAX, | ||
609 | DA7219_NO_INVERT, da7219_dac_eq_band_tlv), | ||
610 | SOC_SINGLE_EXT("DAC EQ Switch", DA7219_DAC_FILTERS4, | ||
611 | DA7219_DAC_EQ_EN_SHIFT, DA7219_SWITCH_EN_MAX, | ||
612 | DA7219_NO_INVERT, da7219_volsw_locked_get, | ||
613 | da7219_volsw_locked_put), | ||
614 | |||
615 | /* DAC Softmute */ | ||
616 | SOC_ENUM("DAC Soft Mute Rate", da7219_dac_softmute_rate), | ||
617 | SOC_SINGLE_EXT("DAC Soft Mute Switch", DA7219_DAC_FILTERS5, | ||
618 | DA7219_DAC_SOFTMUTE_EN_SHIFT, DA7219_SWITCH_EN_MAX, | ||
619 | DA7219_NO_INVERT, da7219_volsw_locked_get, | ||
620 | da7219_volsw_locked_put), | ||
621 | |||
622 | /* DAC Noise Gate */ | ||
623 | SOC_ENUM("DAC NG Setup Time", da7219_dac_ng_setup_time), | ||
624 | SOC_ENUM("DAC NG Rampup Rate", da7219_dac_ng_rampup_rate), | ||
625 | SOC_ENUM("DAC NG Rampdown Rate", da7219_dac_ng_rampdown_rate), | ||
626 | SOC_SINGLE_TLV("DAC NG Off Threshold", DA7219_DAC_NG_OFF_THRESH, | ||
627 | DA7219_DAC_NG_OFF_THRESHOLD_SHIFT, | ||
628 | DA7219_DAC_NG_THRESHOLD_MAX, DA7219_NO_INVERT, | ||
629 | da7219_dac_ng_threshold_tlv), | ||
630 | SOC_SINGLE_TLV("DAC NG On Threshold", DA7219_DAC_NG_ON_THRESH, | ||
631 | DA7219_DAC_NG_ON_THRESHOLD_SHIFT, | ||
632 | DA7219_DAC_NG_THRESHOLD_MAX, DA7219_NO_INVERT, | ||
633 | da7219_dac_ng_threshold_tlv), | ||
634 | SOC_SINGLE("DAC NG Switch", DA7219_DAC_NG_CTRL, DA7219_DAC_NG_EN_SHIFT, | ||
635 | DA7219_SWITCH_EN_MAX, DA7219_NO_INVERT), | ||
636 | |||
637 | /* DACs */ | ||
638 | SOC_DOUBLE_R_EXT_TLV("Playback Digital Volume", DA7219_DAC_L_GAIN, | ||
639 | DA7219_DAC_R_GAIN, DA7219_DAC_L_DIGITAL_GAIN_SHIFT, | ||
640 | DA7219_DAC_DIGITAL_GAIN_MAX, DA7219_NO_INVERT, | ||
641 | da7219_volsw_locked_get, da7219_volsw_locked_put, | ||
642 | da7219_dac_dig_gain_tlv), | ||
643 | SOC_DOUBLE_R_EXT("Playback Digital Switch", DA7219_DAC_L_CTRL, | ||
644 | DA7219_DAC_R_CTRL, DA7219_DAC_L_MUTE_EN_SHIFT, | ||
645 | DA7219_SWITCH_EN_MAX, DA7219_INVERT, | ||
646 | da7219_volsw_locked_get, da7219_volsw_locked_put), | ||
647 | SOC_DOUBLE_R("Playback Digital Gain Ramp Switch", DA7219_DAC_L_CTRL, | ||
648 | DA7219_DAC_R_CTRL, DA7219_DAC_L_RAMP_EN_SHIFT, | ||
649 | DA7219_SWITCH_EN_MAX, DA7219_NO_INVERT), | ||
650 | |||
651 | /* CP */ | ||
652 | SOC_ENUM("Charge Pump Track Mode", da7219_cp_track_mode), | ||
653 | SOC_SINGLE("Charge Pump Threshold", DA7219_CP_VOL_THRESHOLD1, | ||
654 | DA7219_CP_THRESH_VDD2_SHIFT, DA7219_CP_THRESH_VDD2_MAX, | ||
655 | DA7219_NO_INVERT), | ||
656 | |||
657 | /* Headphones */ | ||
658 | SOC_DOUBLE_R_EXT_TLV("Headphone Volume", DA7219_HP_L_GAIN, | ||
659 | DA7219_HP_R_GAIN, DA7219_HP_L_AMP_GAIN_SHIFT, | ||
660 | DA7219_HP_AMP_GAIN_MAX, DA7219_NO_INVERT, | ||
661 | da7219_volsw_locked_get, da7219_volsw_locked_put, | ||
662 | da7219_hp_gain_tlv), | ||
663 | SOC_DOUBLE_R_EXT("Headphone Switch", DA7219_HP_L_CTRL, DA7219_HP_R_CTRL, | ||
664 | DA7219_HP_L_AMP_MUTE_EN_SHIFT, DA7219_SWITCH_EN_MAX, | ||
665 | DA7219_INVERT, da7219_volsw_locked_get, | ||
666 | da7219_volsw_locked_put), | ||
667 | SOC_DOUBLE_R("Headphone Gain Ramp Switch", DA7219_HP_L_CTRL, | ||
668 | DA7219_HP_R_CTRL, DA7219_HP_L_AMP_RAMP_EN_SHIFT, | ||
669 | DA7219_SWITCH_EN_MAX, DA7219_NO_INVERT), | ||
670 | SOC_DOUBLE_R("Headphone ZC Gain Switch", DA7219_HP_L_CTRL, | ||
671 | DA7219_HP_R_CTRL, DA7219_HP_L_AMP_ZC_EN_SHIFT, | ||
672 | DA7219_SWITCH_EN_MAX, DA7219_NO_INVERT), | ||
673 | }; | ||
674 | |||
675 | |||
676 | /* | ||
677 | * DAPM Mux Controls | ||
678 | */ | ||
679 | |||
680 | static const char * const da7219_out_sel_txt[] = { | ||
681 | "ADC", "Tone Generator", "DAIL", "DAIR" | ||
682 | }; | ||
683 | |||
684 | static const struct soc_enum da7219_out_dail_sel = | ||
685 | SOC_ENUM_SINGLE(DA7219_DIG_ROUTING_DAI, | ||
686 | DA7219_DAI_L_SRC_SHIFT, | ||
687 | DA7219_OUT_SRC_MAX, | ||
688 | da7219_out_sel_txt); | ||
689 | |||
690 | static const struct snd_kcontrol_new da7219_out_dail_sel_mux = | ||
691 | SOC_DAPM_ENUM("Out DAIL Mux", da7219_out_dail_sel); | ||
692 | |||
693 | static const struct soc_enum da7219_out_dair_sel = | ||
694 | SOC_ENUM_SINGLE(DA7219_DIG_ROUTING_DAI, | ||
695 | DA7219_DAI_R_SRC_SHIFT, | ||
696 | DA7219_OUT_SRC_MAX, | ||
697 | da7219_out_sel_txt); | ||
698 | |||
699 | static const struct snd_kcontrol_new da7219_out_dair_sel_mux = | ||
700 | SOC_DAPM_ENUM("Out DAIR Mux", da7219_out_dair_sel); | ||
701 | |||
702 | static const struct soc_enum da7219_out_dacl_sel = | ||
703 | SOC_ENUM_SINGLE(DA7219_DIG_ROUTING_DAC, | ||
704 | DA7219_DAC_L_SRC_SHIFT, | ||
705 | DA7219_OUT_SRC_MAX, | ||
706 | da7219_out_sel_txt); | ||
707 | |||
708 | static const struct snd_kcontrol_new da7219_out_dacl_sel_mux = | ||
709 | SOC_DAPM_ENUM("Out DACL Mux", da7219_out_dacl_sel); | ||
710 | |||
711 | static const struct soc_enum da7219_out_dacr_sel = | ||
712 | SOC_ENUM_SINGLE(DA7219_DIG_ROUTING_DAC, | ||
713 | DA7219_DAC_R_SRC_SHIFT, | ||
714 | DA7219_OUT_SRC_MAX, | ||
715 | da7219_out_sel_txt); | ||
716 | |||
717 | static const struct snd_kcontrol_new da7219_out_dacr_sel_mux = | ||
718 | SOC_DAPM_ENUM("Out DACR Mux", da7219_out_dacr_sel); | ||
719 | |||
720 | |||
721 | /* | ||
722 | * DAPM Mixer Controls | ||
723 | */ | ||
724 | |||
725 | static const struct snd_kcontrol_new da7219_mixin_controls[] = { | ||
726 | SOC_DAPM_SINGLE("Mic Switch", DA7219_MIXIN_L_SELECT, | ||
727 | DA7219_MIXIN_L_MIX_SELECT_SHIFT, | ||
728 | DA7219_SWITCH_EN_MAX, DA7219_NO_INVERT), | ||
729 | }; | ||
730 | |||
731 | static const struct snd_kcontrol_new da7219_mixout_l_controls[] = { | ||
732 | SOC_DAPM_SINGLE("DACL Switch", DA7219_MIXOUT_L_SELECT, | ||
733 | DA7219_MIXOUT_L_MIX_SELECT_SHIFT, | ||
734 | DA7219_SWITCH_EN_MAX, DA7219_NO_INVERT), | ||
735 | }; | ||
736 | |||
737 | static const struct snd_kcontrol_new da7219_mixout_r_controls[] = { | ||
738 | SOC_DAPM_SINGLE("DACR Switch", DA7219_MIXOUT_R_SELECT, | ||
739 | DA7219_MIXOUT_R_MIX_SELECT_SHIFT, | ||
740 | DA7219_SWITCH_EN_MAX, DA7219_NO_INVERT), | ||
741 | }; | ||
742 | |||
743 | #define DA7219_DMIX_ST_CTRLS(reg) \ | ||
744 | SOC_DAPM_SINGLE("Out FilterL Switch", reg, \ | ||
745 | DA7219_DMIX_ST_SRC_OUTFILT1L_SHIFT, \ | ||
746 | DA7219_SWITCH_EN_MAX, DA7219_NO_INVERT), \ | ||
747 | SOC_DAPM_SINGLE("Out FilterR Switch", reg, \ | ||
748 | DA7219_DMIX_ST_SRC_OUTFILT1R_SHIFT, \ | ||
749 | DA7219_SWITCH_EN_MAX, DA7219_NO_INVERT), \ | ||
750 | SOC_DAPM_SINGLE("Sidetone Switch", reg, \ | ||
751 | DA7219_DMIX_ST_SRC_SIDETONE_SHIFT, \ | ||
752 | DA7219_SWITCH_EN_MAX, DA7219_NO_INVERT) \ | ||
753 | |||
754 | static const struct snd_kcontrol_new da7219_st_out_filtl_mix_controls[] = { | ||
755 | DA7219_DMIX_ST_CTRLS(DA7219_DROUTING_ST_OUTFILT_1L), | ||
756 | }; | ||
757 | |||
758 | static const struct snd_kcontrol_new da7219_st_out_filtr_mix_controls[] = { | ||
759 | DA7219_DMIX_ST_CTRLS(DA7219_DROUTING_ST_OUTFILT_1R), | ||
760 | }; | ||
761 | |||
762 | |||
763 | /* | ||
764 | * DAPM Events | ||
765 | */ | ||
766 | |||
767 | static int da7219_dai_event(struct snd_soc_dapm_widget *w, | ||
768 | struct snd_kcontrol *kcontrol, int event) | ||
769 | { | ||
770 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); | ||
771 | struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); | ||
772 | u8 pll_ctrl, pll_status; | ||
773 | int i = 0; | ||
774 | bool srm_lock = false; | ||
775 | |||
776 | switch (event) { | ||
777 | case SND_SOC_DAPM_PRE_PMU: | ||
778 | if (da7219->master) | ||
779 | /* Enable DAI clks for master mode */ | ||
780 | snd_soc_update_bits(codec, DA7219_DAI_CLK_MODE, | ||
781 | DA7219_DAI_CLK_EN_MASK, | ||
782 | DA7219_DAI_CLK_EN_MASK); | ||
783 | |||
784 | /* PC synchronised to DAI */ | ||
785 | snd_soc_update_bits(codec, DA7219_PC_COUNT, | ||
786 | DA7219_PC_FREERUN_MASK, 0); | ||
787 | |||
788 | /* Slave mode, if SRM not enabled no need for status checks */ | ||
789 | pll_ctrl = snd_soc_read(codec, DA7219_PLL_CTRL); | ||
790 | if ((pll_ctrl & DA7219_PLL_MODE_MASK) != DA7219_PLL_MODE_SRM) | ||
791 | return 0; | ||
792 | |||
793 | /* Check SRM has locked */ | ||
794 | do { | ||
795 | pll_status = snd_soc_read(codec, DA7219_PLL_SRM_STS); | ||
796 | if (pll_status & DA7219_PLL_SRM_STS_SRM_LOCK) { | ||
797 | srm_lock = true; | ||
798 | } else { | ||
799 | ++i; | ||
800 | msleep(50); | ||
801 | } | ||
802 | } while ((i < DA7219_SRM_CHECK_RETRIES) & (!srm_lock)); | ||
803 | |||
804 | if (!srm_lock) | ||
805 | dev_warn(codec->dev, "SRM failed to lock\n"); | ||
806 | |||
807 | return 0; | ||
808 | case SND_SOC_DAPM_POST_PMD: | ||
809 | /* PC free-running */ | ||
810 | snd_soc_update_bits(codec, DA7219_PC_COUNT, | ||
811 | DA7219_PC_FREERUN_MASK, | ||
812 | DA7219_PC_FREERUN_MASK); | ||
813 | |||
814 | /* Disable DAI clks if in master mode */ | ||
815 | if (da7219->master) | ||
816 | snd_soc_update_bits(codec, DA7219_DAI_CLK_MODE, | ||
817 | DA7219_DAI_CLK_EN_MASK, 0); | ||
818 | return 0; | ||
819 | default: | ||
820 | return -EINVAL; | ||
821 | } | ||
822 | } | ||
823 | |||
824 | |||
825 | /* | ||
826 | * DAPM Widgets | ||
827 | */ | ||
828 | |||
829 | static const struct snd_soc_dapm_widget da7219_dapm_widgets[] = { | ||
830 | /* Input Supplies */ | ||
831 | SND_SOC_DAPM_SUPPLY("Mic Bias", DA7219_MICBIAS_CTRL, | ||
832 | DA7219_MICBIAS1_EN_SHIFT, DA7219_NO_INVERT, | ||
833 | NULL, 0), | ||
834 | |||
835 | /* Inputs */ | ||
836 | SND_SOC_DAPM_INPUT("MIC"), | ||
837 | |||
838 | /* Input PGAs */ | ||
839 | SND_SOC_DAPM_PGA("Mic PGA", DA7219_MIC_1_CTRL, | ||
840 | DA7219_MIC_1_AMP_EN_SHIFT, DA7219_NO_INVERT, | ||
841 | NULL, 0), | ||
842 | SND_SOC_DAPM_PGA("Mixin PGA", DA7219_MIXIN_L_CTRL, | ||
843 | DA7219_MIXIN_L_AMP_EN_SHIFT, DA7219_NO_INVERT, | ||
844 | NULL, 0), | ||
845 | |||
846 | /* Input Filters */ | ||
847 | SND_SOC_DAPM_ADC("ADC", NULL, DA7219_ADC_L_CTRL, DA7219_ADC_L_EN_SHIFT, | ||
848 | DA7219_NO_INVERT), | ||
849 | |||
850 | /* Tone Generator */ | ||
851 | SND_SOC_DAPM_SIGGEN("TONE"), | ||
852 | SND_SOC_DAPM_PGA("Tone Generator", DA7219_TONE_GEN_CFG1, | ||
853 | DA7219_START_STOPN_SHIFT, DA7219_NO_INVERT, NULL, 0), | ||
854 | |||
855 | /* Sidetone Input */ | ||
856 | SND_SOC_DAPM_ADC("Sidetone Filter", NULL, DA7219_SIDETONE_CTRL, | ||
857 | DA7219_SIDETONE_EN_SHIFT, DA7219_NO_INVERT), | ||
858 | |||
859 | /* Input Mixer Supply */ | ||
860 | SND_SOC_DAPM_SUPPLY("Mixer In Supply", DA7219_MIXIN_L_CTRL, | ||
861 | DA7219_MIXIN_L_MIX_EN_SHIFT, DA7219_NO_INVERT, | ||
862 | NULL, 0), | ||
863 | |||
864 | /* Input Mixer */ | ||
865 | SND_SOC_DAPM_MIXER("Mixer In", SND_SOC_NOPM, 0, 0, | ||
866 | da7219_mixin_controls, | ||
867 | ARRAY_SIZE(da7219_mixin_controls)), | ||
868 | |||
869 | /* Input Muxes */ | ||
870 | SND_SOC_DAPM_MUX("Out DAIL Mux", SND_SOC_NOPM, 0, 0, | ||
871 | &da7219_out_dail_sel_mux), | ||
872 | SND_SOC_DAPM_MUX("Out DAIR Mux", SND_SOC_NOPM, 0, 0, | ||
873 | &da7219_out_dair_sel_mux), | ||
874 | |||
875 | /* DAI Supply */ | ||
876 | SND_SOC_DAPM_SUPPLY("DAI", DA7219_DAI_CTRL, DA7219_DAI_EN_SHIFT, | ||
877 | DA7219_NO_INVERT, da7219_dai_event, | ||
878 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), | ||
879 | |||
880 | /* DAI */ | ||
881 | SND_SOC_DAPM_AIF_OUT("DAIOUT", "Capture", 0, SND_SOC_NOPM, 0, 0), | ||
882 | SND_SOC_DAPM_AIF_IN("DAIIN", "Playback", 0, SND_SOC_NOPM, 0, 0), | ||
883 | |||
884 | /* Output Muxes */ | ||
885 | SND_SOC_DAPM_MUX("Out DACL Mux", SND_SOC_NOPM, 0, 0, | ||
886 | &da7219_out_dacl_sel_mux), | ||
887 | SND_SOC_DAPM_MUX("Out DACR Mux", SND_SOC_NOPM, 0, 0, | ||
888 | &da7219_out_dacr_sel_mux), | ||
889 | |||
890 | /* Output Mixers */ | ||
891 | SND_SOC_DAPM_MIXER("Mixer Out FilterL", SND_SOC_NOPM, 0, 0, | ||
892 | da7219_mixout_l_controls, | ||
893 | ARRAY_SIZE(da7219_mixout_l_controls)), | ||
894 | SND_SOC_DAPM_MIXER("Mixer Out FilterR", SND_SOC_NOPM, 0, 0, | ||
895 | da7219_mixout_r_controls, | ||
896 | ARRAY_SIZE(da7219_mixout_r_controls)), | ||
897 | |||
898 | /* Sidetone Mixers */ | ||
899 | SND_SOC_DAPM_MIXER("ST Mixer Out FilterL", SND_SOC_NOPM, 0, 0, | ||
900 | da7219_st_out_filtl_mix_controls, | ||
901 | ARRAY_SIZE(da7219_st_out_filtl_mix_controls)), | ||
902 | SND_SOC_DAPM_MIXER("ST Mixer Out FilterR", SND_SOC_NOPM, 0, | ||
903 | 0, da7219_st_out_filtr_mix_controls, | ||
904 | ARRAY_SIZE(da7219_st_out_filtr_mix_controls)), | ||
905 | |||
906 | /* DACs */ | ||
907 | SND_SOC_DAPM_DAC("DACL", NULL, DA7219_DAC_L_CTRL, DA7219_DAC_L_EN_SHIFT, | ||
908 | DA7219_NO_INVERT), | ||
909 | SND_SOC_DAPM_DAC("DACR", NULL, DA7219_DAC_R_CTRL, DA7219_DAC_R_EN_SHIFT, | ||
910 | DA7219_NO_INVERT), | ||
911 | |||
912 | /* Output PGAs */ | ||
913 | SND_SOC_DAPM_PGA("Mixout Left PGA", DA7219_MIXOUT_L_CTRL, | ||
914 | DA7219_MIXOUT_L_AMP_EN_SHIFT, DA7219_NO_INVERT, | ||
915 | NULL, 0), | ||
916 | SND_SOC_DAPM_PGA("Mixout Right PGA", DA7219_MIXOUT_R_CTRL, | ||
917 | DA7219_MIXOUT_R_AMP_EN_SHIFT, DA7219_NO_INVERT, | ||
918 | NULL, 0), | ||
919 | SND_SOC_DAPM_PGA("Headphone Left PGA", DA7219_HP_L_CTRL, | ||
920 | DA7219_HP_L_AMP_EN_SHIFT, DA7219_NO_INVERT, NULL, 0), | ||
921 | SND_SOC_DAPM_PGA("Headphone Right PGA", DA7219_HP_R_CTRL, | ||
922 | DA7219_HP_R_AMP_EN_SHIFT, DA7219_NO_INVERT, NULL, 0), | ||
923 | |||
924 | /* Output Supplies */ | ||
925 | SND_SOC_DAPM_SUPPLY("Charge Pump", DA7219_CP_CTRL, DA7219_CP_EN_SHIFT, | ||
926 | DA7219_NO_INVERT, NULL, 0), | ||
927 | |||
928 | /* Outputs */ | ||
929 | SND_SOC_DAPM_OUTPUT("HPL"), | ||
930 | SND_SOC_DAPM_OUTPUT("HPR"), | ||
931 | }; | ||
932 | |||
933 | |||
934 | /* | ||
935 | * DAPM Mux Routes | ||
936 | */ | ||
937 | |||
938 | #define DA7219_OUT_DAI_MUX_ROUTES(name) \ | ||
939 | {name, "ADC", "Mixer In"}, \ | ||
940 | {name, "Tone Generator", "Tone Generator"}, \ | ||
941 | {name, "DAIL", "DAIOUT"}, \ | ||
942 | {name, "DAIR", "DAIOUT"} | ||
943 | |||
944 | #define DA7219_OUT_DAC_MUX_ROUTES(name) \ | ||
945 | {name, "ADC", "Mixer In"}, \ | ||
946 | {name, "Tone Generator", "Tone Generator"}, \ | ||
947 | {name, "DAIL", "DAIIN"}, \ | ||
948 | {name, "DAIR", "DAIIN"} | ||
949 | |||
950 | /* | ||
951 | * DAPM Mixer Routes | ||
952 | */ | ||
953 | |||
954 | #define DA7219_DMIX_ST_ROUTES(name) \ | ||
955 | {name, "Out FilterL Switch", "Mixer Out FilterL"}, \ | ||
956 | {name, "Out FilterR Switch", "Mixer Out FilterR"}, \ | ||
957 | {name, "Sidetone Switch", "Sidetone Filter"} | ||
958 | |||
959 | |||
960 | /* | ||
961 | * DAPM audio route definition | ||
962 | */ | ||
963 | |||
964 | static const struct snd_soc_dapm_route da7219_audio_map[] = { | ||
965 | /* Input paths */ | ||
966 | {"MIC", NULL, "Mic Bias"}, | ||
967 | {"Mic PGA", NULL, "MIC"}, | ||
968 | {"Mixin PGA", NULL, "Mic PGA"}, | ||
969 | {"ADC", NULL, "Mixin PGA"}, | ||
970 | |||
971 | {"Sidetone Filter", NULL, "ADC"}, | ||
972 | {"Mixer In", NULL, "Mixer In Supply"}, | ||
973 | {"Mixer In", "Mic Switch", "ADC"}, | ||
974 | |||
975 | {"Tone Generator", NULL, "TONE"}, | ||
976 | |||
977 | DA7219_OUT_DAI_MUX_ROUTES("Out DAIL Mux"), | ||
978 | DA7219_OUT_DAI_MUX_ROUTES("Out DAIR Mux"), | ||
979 | |||
980 | {"DAIOUT", NULL, "Out DAIL Mux"}, | ||
981 | {"DAIOUT", NULL, "Out DAIR Mux"}, | ||
982 | {"DAIOUT", NULL, "DAI"}, | ||
983 | |||
984 | /* Output paths */ | ||
985 | {"DAIIN", NULL, "DAI"}, | ||
986 | |||
987 | DA7219_OUT_DAC_MUX_ROUTES("Out DACL Mux"), | ||
988 | DA7219_OUT_DAC_MUX_ROUTES("Out DACR Mux"), | ||
989 | |||
990 | {"Mixer Out FilterL", "DACL Switch", "Out DACL Mux"}, | ||
991 | {"Mixer Out FilterR", "DACR Switch", "Out DACR Mux"}, | ||
992 | |||
993 | DA7219_DMIX_ST_ROUTES("ST Mixer Out FilterL"), | ||
994 | DA7219_DMIX_ST_ROUTES("ST Mixer Out FilterR"), | ||
995 | |||
996 | {"DACL", NULL, "ST Mixer Out FilterL"}, | ||
997 | {"DACR", NULL, "ST Mixer Out FilterR"}, | ||
998 | |||
999 | {"Mixout Left PGA", NULL, "DACL"}, | ||
1000 | {"Mixout Right PGA", NULL, "DACR"}, | ||
1001 | |||
1002 | {"Headphone Left PGA", NULL, "Mixout Left PGA"}, | ||
1003 | {"Headphone Right PGA", NULL, "Mixout Right PGA"}, | ||
1004 | |||
1005 | {"HPL", NULL, "Headphone Left PGA"}, | ||
1006 | {"HPR", NULL, "Headphone Right PGA"}, | ||
1007 | |||
1008 | {"HPL", NULL, "Charge Pump"}, | ||
1009 | {"HPR", NULL, "Charge Pump"}, | ||
1010 | }; | ||
1011 | |||
1012 | |||
1013 | /* | ||
1014 | * DAI operations | ||
1015 | */ | ||
1016 | |||
1017 | static int da7219_set_dai_sysclk(struct snd_soc_dai *codec_dai, | ||
1018 | int clk_id, unsigned int freq, int dir) | ||
1019 | { | ||
1020 | struct snd_soc_codec *codec = codec_dai->codec; | ||
1021 | struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); | ||
1022 | int ret = 0; | ||
1023 | |||
1024 | if ((da7219->clk_src == clk_id) && (da7219->mclk_rate == freq)) | ||
1025 | return 0; | ||
1026 | |||
1027 | if (((freq < 2000000) && (freq != 32768)) || (freq > 54000000)) { | ||
1028 | dev_err(codec_dai->dev, "Unsupported MCLK value %d\n", | ||
1029 | freq); | ||
1030 | return -EINVAL; | ||
1031 | } | ||
1032 | |||
1033 | switch (clk_id) { | ||
1034 | case DA7219_CLKSRC_MCLK_SQR: | ||
1035 | snd_soc_update_bits(codec, DA7219_PLL_CTRL, | ||
1036 | DA7219_PLL_MCLK_SQR_EN_MASK, | ||
1037 | DA7219_PLL_MCLK_SQR_EN_MASK); | ||
1038 | break; | ||
1039 | case DA7219_CLKSRC_MCLK: | ||
1040 | snd_soc_update_bits(codec, DA7219_PLL_CTRL, | ||
1041 | DA7219_PLL_MCLK_SQR_EN_MASK, 0); | ||
1042 | break; | ||
1043 | default: | ||
1044 | dev_err(codec_dai->dev, "Unknown clock source %d\n", clk_id); | ||
1045 | return -EINVAL; | ||
1046 | } | ||
1047 | |||
1048 | da7219->clk_src = clk_id; | ||
1049 | |||
1050 | if (da7219->mclk) { | ||
1051 | freq = clk_round_rate(da7219->mclk, freq); | ||
1052 | ret = clk_set_rate(da7219->mclk, freq); | ||
1053 | if (ret) { | ||
1054 | dev_err(codec_dai->dev, "Failed to set clock rate %d\n", | ||
1055 | freq); | ||
1056 | return ret; | ||
1057 | } | ||
1058 | } | ||
1059 | |||
1060 | da7219->mclk_rate = freq; | ||
1061 | |||
1062 | return 0; | ||
1063 | } | ||
1064 | |||
1065 | static int da7219_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, | ||
1066 | int source, unsigned int fref, unsigned int fout) | ||
1067 | { | ||
1068 | struct snd_soc_codec *codec = codec_dai->codec; | ||
1069 | struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); | ||
1070 | |||
1071 | u8 pll_ctrl, indiv_bits, indiv; | ||
1072 | u8 pll_frac_top, pll_frac_bot, pll_integer; | ||
1073 | u32 freq_ref; | ||
1074 | u64 frac_div; | ||
1075 | |||
1076 | /* Verify 32KHz, 2MHz - 54MHz MCLK provided, and set input divider */ | ||
1077 | if (da7219->mclk_rate == 32768) { | ||
1078 | indiv_bits = DA7219_PLL_INDIV_2_5_MHZ; | ||
1079 | indiv = DA7219_PLL_INDIV_2_5_MHZ_VAL; | ||
1080 | } else if (da7219->mclk_rate < 2000000) { | ||
1081 | dev_err(codec->dev, "PLL input clock %d below valid range\n", | ||
1082 | da7219->mclk_rate); | ||
1083 | return -EINVAL; | ||
1084 | } else if (da7219->mclk_rate <= 5000000) { | ||
1085 | indiv_bits = DA7219_PLL_INDIV_2_5_MHZ; | ||
1086 | indiv = DA7219_PLL_INDIV_2_5_MHZ_VAL; | ||
1087 | } else if (da7219->mclk_rate <= 10000000) { | ||
1088 | indiv_bits = DA7219_PLL_INDIV_5_10_MHZ; | ||
1089 | indiv = DA7219_PLL_INDIV_5_10_MHZ_VAL; | ||
1090 | } else if (da7219->mclk_rate <= 20000000) { | ||
1091 | indiv_bits = DA7219_PLL_INDIV_10_20_MHZ; | ||
1092 | indiv = DA7219_PLL_INDIV_10_20_MHZ_VAL; | ||
1093 | } else if (da7219->mclk_rate <= 40000000) { | ||
1094 | indiv_bits = DA7219_PLL_INDIV_20_40_MHZ; | ||
1095 | indiv = DA7219_PLL_INDIV_20_40_MHZ_VAL; | ||
1096 | } else if (da7219->mclk_rate <= 54000000) { | ||
1097 | indiv_bits = DA7219_PLL_INDIV_40_54_MHZ; | ||
1098 | indiv = DA7219_PLL_INDIV_40_54_MHZ_VAL; | ||
1099 | } else { | ||
1100 | dev_err(codec->dev, "PLL input clock %d above valid range\n", | ||
1101 | da7219->mclk_rate); | ||
1102 | return -EINVAL; | ||
1103 | } | ||
1104 | freq_ref = (da7219->mclk_rate / indiv); | ||
1105 | pll_ctrl = indiv_bits; | ||
1106 | |||
1107 | /* Configure PLL */ | ||
1108 | switch (source) { | ||
1109 | case DA7219_SYSCLK_MCLK: | ||
1110 | pll_ctrl |= DA7219_PLL_MODE_BYPASS; | ||
1111 | snd_soc_update_bits(codec, DA7219_PLL_CTRL, | ||
1112 | DA7219_PLL_INDIV_MASK | | ||
1113 | DA7219_PLL_MODE_MASK, pll_ctrl); | ||
1114 | return 0; | ||
1115 | case DA7219_SYSCLK_PLL: | ||
1116 | pll_ctrl |= DA7219_PLL_MODE_NORMAL; | ||
1117 | break; | ||
1118 | case DA7219_SYSCLK_PLL_SRM: | ||
1119 | pll_ctrl |= DA7219_PLL_MODE_SRM; | ||
1120 | break; | ||
1121 | case DA7219_SYSCLK_PLL_32KHZ: | ||
1122 | pll_ctrl |= DA7219_PLL_MODE_32KHZ; | ||
1123 | break; | ||
1124 | default: | ||
1125 | dev_err(codec->dev, "Invalid PLL config\n"); | ||
1126 | return -EINVAL; | ||
1127 | } | ||
1128 | |||
1129 | /* Calculate dividers for PLL */ | ||
1130 | pll_integer = fout / freq_ref; | ||
1131 | frac_div = (u64)(fout % freq_ref) * 8192ULL; | ||
1132 | do_div(frac_div, freq_ref); | ||
1133 | pll_frac_top = (frac_div >> DA7219_BYTE_SHIFT) & DA7219_BYTE_MASK; | ||
1134 | pll_frac_bot = (frac_div) & DA7219_BYTE_MASK; | ||
1135 | |||
1136 | /* Write PLL config & dividers */ | ||
1137 | snd_soc_write(codec, DA7219_PLL_FRAC_TOP, pll_frac_top); | ||
1138 | snd_soc_write(codec, DA7219_PLL_FRAC_BOT, pll_frac_bot); | ||
1139 | snd_soc_write(codec, DA7219_PLL_INTEGER, pll_integer); | ||
1140 | snd_soc_update_bits(codec, DA7219_PLL_CTRL, | ||
1141 | DA7219_PLL_INDIV_MASK | DA7219_PLL_MODE_MASK, | ||
1142 | pll_ctrl); | ||
1143 | |||
1144 | return 0; | ||
1145 | } | ||
1146 | |||
1147 | static int da7219_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) | ||
1148 | { | ||
1149 | struct snd_soc_codec *codec = codec_dai->codec; | ||
1150 | struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); | ||
1151 | u8 dai_clk_mode = 0, dai_ctrl = 0; | ||
1152 | |||
1153 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
1154 | case SND_SOC_DAIFMT_CBM_CFM: | ||
1155 | da7219->master = true; | ||
1156 | break; | ||
1157 | case SND_SOC_DAIFMT_CBS_CFS: | ||
1158 | da7219->master = false; | ||
1159 | break; | ||
1160 | default: | ||
1161 | return -EINVAL; | ||
1162 | } | ||
1163 | |||
1164 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | ||
1165 | case SND_SOC_DAIFMT_NB_NF: | ||
1166 | break; | ||
1167 | case SND_SOC_DAIFMT_NB_IF: | ||
1168 | dai_clk_mode |= DA7219_DAI_WCLK_POL_INV; | ||
1169 | break; | ||
1170 | case SND_SOC_DAIFMT_IB_NF: | ||
1171 | dai_clk_mode |= DA7219_DAI_CLK_POL_INV; | ||
1172 | break; | ||
1173 | case SND_SOC_DAIFMT_IB_IF: | ||
1174 | dai_clk_mode |= DA7219_DAI_WCLK_POL_INV | | ||
1175 | DA7219_DAI_CLK_POL_INV; | ||
1176 | break; | ||
1177 | default: | ||
1178 | return -EINVAL; | ||
1179 | } | ||
1180 | |||
1181 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
1182 | case SND_SOC_DAIFMT_I2S: | ||
1183 | dai_ctrl |= DA7219_DAI_FORMAT_I2S; | ||
1184 | break; | ||
1185 | case SND_SOC_DAIFMT_LEFT_J: | ||
1186 | dai_ctrl |= DA7219_DAI_FORMAT_LEFT_J; | ||
1187 | break; | ||
1188 | case SND_SOC_DAIFMT_RIGHT_J: | ||
1189 | dai_ctrl |= DA7219_DAI_FORMAT_RIGHT_J; | ||
1190 | break; | ||
1191 | case SND_SOC_DAIFMT_DSP_B: | ||
1192 | dai_ctrl |= DA7219_DAI_FORMAT_DSP; | ||
1193 | break; | ||
1194 | default: | ||
1195 | return -EINVAL; | ||
1196 | } | ||
1197 | |||
1198 | /* By default 64 BCLKs per WCLK is supported */ | ||
1199 | dai_clk_mode |= DA7219_DAI_BCLKS_PER_WCLK_64; | ||
1200 | |||
1201 | snd_soc_update_bits(codec, DA7219_DAI_CLK_MODE, | ||
1202 | DA7219_DAI_BCLKS_PER_WCLK_MASK | | ||
1203 | DA7219_DAI_CLK_POL_MASK | DA7219_DAI_WCLK_POL_MASK, | ||
1204 | dai_clk_mode); | ||
1205 | snd_soc_update_bits(codec, DA7219_DAI_CTRL, DA7219_DAI_FORMAT_MASK, | ||
1206 | dai_ctrl); | ||
1207 | |||
1208 | return 0; | ||
1209 | } | ||
1210 | |||
1211 | static int da7219_set_dai_tdm_slot(struct snd_soc_dai *dai, | ||
1212 | unsigned int tx_mask, unsigned int rx_mask, | ||
1213 | int slots, int slot_width) | ||
1214 | { | ||
1215 | struct snd_soc_codec *codec = dai->codec; | ||
1216 | struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); | ||
1217 | u8 dai_bclks_per_wclk; | ||
1218 | u16 offset; | ||
1219 | u32 frame_size; | ||
1220 | |||
1221 | /* No channels enabled so disable TDM, revert to 64-bit frames */ | ||
1222 | if (!tx_mask) { | ||
1223 | snd_soc_update_bits(codec, DA7219_DAI_TDM_CTRL, | ||
1224 | DA7219_DAI_TDM_CH_EN_MASK | | ||
1225 | DA7219_DAI_TDM_MODE_EN_MASK, 0); | ||
1226 | snd_soc_update_bits(codec, DA7219_DAI_CLK_MODE, | ||
1227 | DA7219_DAI_BCLKS_PER_WCLK_MASK, | ||
1228 | DA7219_DAI_BCLKS_PER_WCLK_64); | ||
1229 | return 0; | ||
1230 | } | ||
1231 | |||
1232 | /* Check we have valid slots */ | ||
1233 | if (fls(tx_mask) > DA7219_DAI_TDM_MAX_SLOTS) { | ||
1234 | dev_err(codec->dev, "Invalid number of slots, max = %d\n", | ||
1235 | DA7219_DAI_TDM_MAX_SLOTS); | ||
1236 | return -EINVAL; | ||
1237 | } | ||
1238 | |||
1239 | /* Check we have a valid offset given */ | ||
1240 | if (rx_mask > DA7219_DAI_OFFSET_MAX) { | ||
1241 | dev_err(codec->dev, "Invalid slot offset, max = %d\n", | ||
1242 | DA7219_DAI_OFFSET_MAX); | ||
1243 | return -EINVAL; | ||
1244 | } | ||
1245 | |||
1246 | /* Calculate & validate frame size based on slot info provided. */ | ||
1247 | frame_size = slots * slot_width; | ||
1248 | switch (frame_size) { | ||
1249 | case 32: | ||
1250 | dai_bclks_per_wclk = DA7219_DAI_BCLKS_PER_WCLK_32; | ||
1251 | break; | ||
1252 | case 64: | ||
1253 | dai_bclks_per_wclk = DA7219_DAI_BCLKS_PER_WCLK_64; | ||
1254 | break; | ||
1255 | case 128: | ||
1256 | dai_bclks_per_wclk = DA7219_DAI_BCLKS_PER_WCLK_128; | ||
1257 | break; | ||
1258 | case 256: | ||
1259 | dai_bclks_per_wclk = DA7219_DAI_BCLKS_PER_WCLK_256; | ||
1260 | break; | ||
1261 | default: | ||
1262 | dev_err(codec->dev, "Invalid frame size %d\n", frame_size); | ||
1263 | return -EINVAL; | ||
1264 | } | ||
1265 | |||
1266 | snd_soc_update_bits(codec, DA7219_DAI_CLK_MODE, | ||
1267 | DA7219_DAI_BCLKS_PER_WCLK_MASK, | ||
1268 | dai_bclks_per_wclk); | ||
1269 | |||
1270 | offset = cpu_to_le16(rx_mask); | ||
1271 | regmap_bulk_write(da7219->regmap, DA7219_DAI_OFFSET_LOWER, | ||
1272 | &offset, sizeof(offset)); | ||
1273 | |||
1274 | snd_soc_update_bits(codec, DA7219_DAI_TDM_CTRL, | ||
1275 | DA7219_DAI_TDM_CH_EN_MASK | | ||
1276 | DA7219_DAI_TDM_MODE_EN_MASK, | ||
1277 | (tx_mask << DA7219_DAI_TDM_CH_EN_SHIFT) | | ||
1278 | DA7219_DAI_TDM_MODE_EN_MASK); | ||
1279 | |||
1280 | return 0; | ||
1281 | } | ||
1282 | |||
1283 | static int da7219_hw_params(struct snd_pcm_substream *substream, | ||
1284 | struct snd_pcm_hw_params *params, | ||
1285 | struct snd_soc_dai *dai) | ||
1286 | { | ||
1287 | struct snd_soc_codec *codec = dai->codec; | ||
1288 | u8 dai_ctrl = 0, fs; | ||
1289 | unsigned int channels; | ||
1290 | |||
1291 | switch (params_width(params)) { | ||
1292 | case 16: | ||
1293 | dai_ctrl |= DA7219_DAI_WORD_LENGTH_S16_LE; | ||
1294 | break; | ||
1295 | case 20: | ||
1296 | dai_ctrl |= DA7219_DAI_WORD_LENGTH_S20_LE; | ||
1297 | break; | ||
1298 | case 24: | ||
1299 | dai_ctrl |= DA7219_DAI_WORD_LENGTH_S24_LE; | ||
1300 | break; | ||
1301 | case 32: | ||
1302 | dai_ctrl |= DA7219_DAI_WORD_LENGTH_S32_LE; | ||
1303 | break; | ||
1304 | default: | ||
1305 | return -EINVAL; | ||
1306 | } | ||
1307 | |||
1308 | channels = params_channels(params); | ||
1309 | if ((channels < 1) | (channels > DA7219_DAI_CH_NUM_MAX)) { | ||
1310 | dev_err(codec->dev, | ||
1311 | "Invalid number of channels, only 1 to %d supported\n", | ||
1312 | DA7219_DAI_CH_NUM_MAX); | ||
1313 | return -EINVAL; | ||
1314 | } | ||
1315 | dai_ctrl |= channels << DA7219_DAI_CH_NUM_SHIFT; | ||
1316 | |||
1317 | switch (params_rate(params)) { | ||
1318 | case 8000: | ||
1319 | fs = DA7219_SR_8000; | ||
1320 | break; | ||
1321 | case 11025: | ||
1322 | fs = DA7219_SR_11025; | ||
1323 | break; | ||
1324 | case 12000: | ||
1325 | fs = DA7219_SR_12000; | ||
1326 | break; | ||
1327 | case 16000: | ||
1328 | fs = DA7219_SR_16000; | ||
1329 | break; | ||
1330 | case 22050: | ||
1331 | fs = DA7219_SR_22050; | ||
1332 | break; | ||
1333 | case 24000: | ||
1334 | fs = DA7219_SR_24000; | ||
1335 | break; | ||
1336 | case 32000: | ||
1337 | fs = DA7219_SR_32000; | ||
1338 | break; | ||
1339 | case 44100: | ||
1340 | fs = DA7219_SR_44100; | ||
1341 | break; | ||
1342 | case 48000: | ||
1343 | fs = DA7219_SR_48000; | ||
1344 | break; | ||
1345 | case 88200: | ||
1346 | fs = DA7219_SR_88200; | ||
1347 | break; | ||
1348 | case 96000: | ||
1349 | fs = DA7219_SR_96000; | ||
1350 | break; | ||
1351 | default: | ||
1352 | return -EINVAL; | ||
1353 | } | ||
1354 | |||
1355 | snd_soc_update_bits(codec, DA7219_DAI_CTRL, | ||
1356 | DA7219_DAI_WORD_LENGTH_MASK | | ||
1357 | DA7219_DAI_CH_NUM_MASK, | ||
1358 | dai_ctrl); | ||
1359 | snd_soc_write(codec, DA7219_SR, fs); | ||
1360 | |||
1361 | return 0; | ||
1362 | } | ||
1363 | |||
1364 | static const struct snd_soc_dai_ops da7219_dai_ops = { | ||
1365 | .hw_params = da7219_hw_params, | ||
1366 | .set_sysclk = da7219_set_dai_sysclk, | ||
1367 | .set_pll = da7219_set_dai_pll, | ||
1368 | .set_fmt = da7219_set_dai_fmt, | ||
1369 | .set_tdm_slot = da7219_set_dai_tdm_slot, | ||
1370 | }; | ||
1371 | |||
1372 | #define DA7219_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ | ||
1373 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) | ||
1374 | |||
1375 | static struct snd_soc_dai_driver da7219_dai = { | ||
1376 | .name = "da7219-hifi", | ||
1377 | .playback = { | ||
1378 | .stream_name = "Playback", | ||
1379 | .channels_min = 1, | ||
1380 | .channels_max = DA7219_DAI_CH_NUM_MAX, | ||
1381 | .rates = SNDRV_PCM_RATE_8000_96000, | ||
1382 | .formats = DA7219_FORMATS, | ||
1383 | }, | ||
1384 | .capture = { | ||
1385 | .stream_name = "Capture", | ||
1386 | .channels_min = 1, | ||
1387 | .channels_max = DA7219_DAI_CH_NUM_MAX, | ||
1388 | .rates = SNDRV_PCM_RATE_8000_96000, | ||
1389 | .formats = DA7219_FORMATS, | ||
1390 | }, | ||
1391 | .ops = &da7219_dai_ops, | ||
1392 | .symmetric_rates = 1, | ||
1393 | .symmetric_channels = 1, | ||
1394 | .symmetric_samplebits = 1, | ||
1395 | }; | ||
1396 | |||
1397 | |||
1398 | /* | ||
1399 | * DT | ||
1400 | */ | ||
1401 | |||
1402 | static const struct of_device_id da7219_of_match[] = { | ||
1403 | { .compatible = "dlg,da7219", }, | ||
1404 | { } | ||
1405 | }; | ||
1406 | MODULE_DEVICE_TABLE(of, da7219_of_match); | ||
1407 | |||
1408 | static enum da7219_ldo_lvl_sel da7219_of_ldo_lvl(struct snd_soc_codec *codec, | ||
1409 | u32 val) | ||
1410 | { | ||
1411 | switch (val) { | ||
1412 | case 1050: | ||
1413 | return DA7219_LDO_LVL_SEL_1_05V; | ||
1414 | case 1100: | ||
1415 | return DA7219_LDO_LVL_SEL_1_10V; | ||
1416 | case 1200: | ||
1417 | return DA7219_LDO_LVL_SEL_1_20V; | ||
1418 | case 1400: | ||
1419 | return DA7219_LDO_LVL_SEL_1_40V; | ||
1420 | default: | ||
1421 | dev_warn(codec->dev, "Invalid LDO level"); | ||
1422 | return DA7219_LDO_LVL_SEL_1_05V; | ||
1423 | } | ||
1424 | } | ||
1425 | |||
1426 | static enum da7219_micbias_voltage | ||
1427 | da7219_of_micbias_lvl(struct snd_soc_codec *codec, u32 val) | ||
1428 | { | ||
1429 | switch (val) { | ||
1430 | case 1800: | ||
1431 | return DA7219_MICBIAS_1_8V; | ||
1432 | case 2000: | ||
1433 | return DA7219_MICBIAS_2_0V; | ||
1434 | case 2200: | ||
1435 | return DA7219_MICBIAS_2_2V; | ||
1436 | case 2400: | ||
1437 | return DA7219_MICBIAS_2_4V; | ||
1438 | case 2600: | ||
1439 | return DA7219_MICBIAS_2_6V; | ||
1440 | default: | ||
1441 | dev_warn(codec->dev, "Invalid micbias level"); | ||
1442 | return DA7219_MICBIAS_2_2V; | ||
1443 | } | ||
1444 | } | ||
1445 | |||
1446 | static enum da7219_mic_amp_in_sel | ||
1447 | da7219_of_mic_amp_in_sel(struct snd_soc_codec *codec, const char *str) | ||
1448 | { | ||
1449 | if (!strcmp(str, "diff")) { | ||
1450 | return DA7219_MIC_AMP_IN_SEL_DIFF; | ||
1451 | } else if (!strcmp(str, "se_p")) { | ||
1452 | return DA7219_MIC_AMP_IN_SEL_SE_P; | ||
1453 | } else if (!strcmp(str, "se_n")) { | ||
1454 | return DA7219_MIC_AMP_IN_SEL_SE_N; | ||
1455 | } else { | ||
1456 | dev_warn(codec->dev, "Invalid mic input type selection"); | ||
1457 | return DA7219_MIC_AMP_IN_SEL_DIFF; | ||
1458 | } | ||
1459 | } | ||
1460 | |||
1461 | static struct da7219_pdata *da7219_of_to_pdata(struct snd_soc_codec *codec) | ||
1462 | { | ||
1463 | struct device_node *np = codec->dev->of_node; | ||
1464 | struct da7219_pdata *pdata; | ||
1465 | const char *of_str; | ||
1466 | u32 of_val32; | ||
1467 | |||
1468 | pdata = devm_kzalloc(codec->dev, sizeof(*pdata), GFP_KERNEL); | ||
1469 | if (!pdata) | ||
1470 | return NULL; | ||
1471 | |||
1472 | if (of_property_read_u32(np, "dlg,ldo-lvl", &of_val32) >= 0) | ||
1473 | pdata->ldo_lvl_sel = da7219_of_ldo_lvl(codec, of_val32); | ||
1474 | |||
1475 | if (of_property_read_u32(np, "dlg,micbias-lvl", &of_val32) >= 0) | ||
1476 | pdata->micbias_lvl = da7219_of_micbias_lvl(codec, of_val32); | ||
1477 | else | ||
1478 | pdata->micbias_lvl = DA7219_MICBIAS_2_2V; | ||
1479 | |||
1480 | if (!of_property_read_string(np, "dlg,mic-amp-in-sel", &of_str)) | ||
1481 | pdata->mic_amp_in_sel = da7219_of_mic_amp_in_sel(codec, of_str); | ||
1482 | else | ||
1483 | pdata->mic_amp_in_sel = DA7219_MIC_AMP_IN_SEL_DIFF; | ||
1484 | |||
1485 | return pdata; | ||
1486 | } | ||
1487 | |||
1488 | |||
1489 | /* | ||
1490 | * Codec driver functions | ||
1491 | */ | ||
1492 | |||
1493 | static int da7219_set_bias_level(struct snd_soc_codec *codec, | ||
1494 | enum snd_soc_bias_level level) | ||
1495 | { | ||
1496 | struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); | ||
1497 | int ret; | ||
1498 | |||
1499 | switch (level) { | ||
1500 | case SND_SOC_BIAS_ON: | ||
1501 | case SND_SOC_BIAS_PREPARE: | ||
1502 | break; | ||
1503 | case SND_SOC_BIAS_STANDBY: | ||
1504 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { | ||
1505 | /* MCLK */ | ||
1506 | if (da7219->mclk) { | ||
1507 | ret = clk_prepare_enable(da7219->mclk); | ||
1508 | if (ret) { | ||
1509 | dev_err(codec->dev, | ||
1510 | "Failed to enable mclk\n"); | ||
1511 | return ret; | ||
1512 | } | ||
1513 | } | ||
1514 | |||
1515 | /* Master bias */ | ||
1516 | snd_soc_update_bits(codec, DA7219_REFERENCES, | ||
1517 | DA7219_BIAS_EN_MASK, | ||
1518 | DA7219_BIAS_EN_MASK); | ||
1519 | |||
1520 | /* Enable Internal Digital LDO */ | ||
1521 | snd_soc_update_bits(codec, DA7219_LDO_CTRL, | ||
1522 | DA7219_LDO_EN_MASK, | ||
1523 | DA7219_LDO_EN_MASK); | ||
1524 | } | ||
1525 | break; | ||
1526 | case SND_SOC_BIAS_OFF: | ||
1527 | /* Only disable if jack detection not active */ | ||
1528 | if (!da7219->aad->jack) { | ||
1529 | /* Bypass Internal Digital LDO */ | ||
1530 | snd_soc_update_bits(codec, DA7219_LDO_CTRL, | ||
1531 | DA7219_LDO_EN_MASK, 0); | ||
1532 | |||
1533 | /* Master bias */ | ||
1534 | snd_soc_update_bits(codec, DA7219_REFERENCES, | ||
1535 | DA7219_BIAS_EN_MASK, 0); | ||
1536 | } | ||
1537 | |||
1538 | /* MCLK */ | ||
1539 | if (da7219->mclk) | ||
1540 | clk_disable_unprepare(da7219->mclk); | ||
1541 | break; | ||
1542 | } | ||
1543 | |||
1544 | return 0; | ||
1545 | } | ||
1546 | |||
1547 | static const char *da7219_supply_names[DA7219_NUM_SUPPLIES] = { | ||
1548 | [DA7219_SUPPLY_VDD] = "VDD", | ||
1549 | [DA7219_SUPPLY_VDDMIC] = "VDDMIC", | ||
1550 | [DA7219_SUPPLY_VDDIO] = "VDDIO", | ||
1551 | }; | ||
1552 | |||
1553 | static int da7219_handle_supplies(struct snd_soc_codec *codec) | ||
1554 | { | ||
1555 | struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); | ||
1556 | struct regulator *vddio; | ||
1557 | u8 io_voltage_lvl = DA7219_IO_VOLTAGE_LEVEL_2_5V_3_6V; | ||
1558 | int i, ret; | ||
1559 | |||
1560 | /* Get required supplies */ | ||
1561 | for (i = 0; i < DA7219_NUM_SUPPLIES; ++i) | ||
1562 | da7219->supplies[i].supply = da7219_supply_names[i]; | ||
1563 | |||
1564 | ret = devm_regulator_bulk_get(codec->dev, DA7219_NUM_SUPPLIES, | ||
1565 | da7219->supplies); | ||
1566 | if (ret) { | ||
1567 | dev_err(codec->dev, "Failed to get supplies"); | ||
1568 | return ret; | ||
1569 | } | ||
1570 | |||
1571 | /* Determine VDDIO voltage provided */ | ||
1572 | vddio = da7219->supplies[DA7219_SUPPLY_VDDIO].consumer; | ||
1573 | ret = regulator_get_voltage(vddio); | ||
1574 | if (ret < 1200000) | ||
1575 | dev_warn(codec->dev, "Invalid VDDIO voltage\n"); | ||
1576 | else if (ret < 2800000) | ||
1577 | io_voltage_lvl = DA7219_IO_VOLTAGE_LEVEL_1_2V_2_8V; | ||
1578 | |||
1579 | /* Enable main supplies */ | ||
1580 | ret = regulator_bulk_enable(DA7219_NUM_SUPPLIES, da7219->supplies); | ||
1581 | if (ret) { | ||
1582 | dev_err(codec->dev, "Failed to enable supplies"); | ||
1583 | return ret; | ||
1584 | } | ||
1585 | |||
1586 | /* Ensure device in active mode */ | ||
1587 | snd_soc_write(codec, DA7219_SYSTEM_ACTIVE, DA7219_SYSTEM_ACTIVE_MASK); | ||
1588 | |||
1589 | /* Update IO voltage level range */ | ||
1590 | snd_soc_write(codec, DA7219_IO_CTRL, io_voltage_lvl); | ||
1591 | |||
1592 | return 0; | ||
1593 | } | ||
1594 | |||
1595 | static void da7219_handle_pdata(struct snd_soc_codec *codec) | ||
1596 | { | ||
1597 | struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); | ||
1598 | struct da7219_pdata *pdata = da7219->pdata; | ||
1599 | |||
1600 | if (pdata) { | ||
1601 | u8 micbias_lvl = 0; | ||
1602 | |||
1603 | /* Internal LDO */ | ||
1604 | switch (pdata->ldo_lvl_sel) { | ||
1605 | case DA7219_LDO_LVL_SEL_1_05V: | ||
1606 | case DA7219_LDO_LVL_SEL_1_10V: | ||
1607 | case DA7219_LDO_LVL_SEL_1_20V: | ||
1608 | case DA7219_LDO_LVL_SEL_1_40V: | ||
1609 | snd_soc_update_bits(codec, DA7219_LDO_CTRL, | ||
1610 | DA7219_LDO_LEVEL_SELECT_MASK, | ||
1611 | (pdata->ldo_lvl_sel << | ||
1612 | DA7219_LDO_LEVEL_SELECT_SHIFT)); | ||
1613 | break; | ||
1614 | } | ||
1615 | |||
1616 | /* Mic Bias voltages */ | ||
1617 | switch (pdata->micbias_lvl) { | ||
1618 | case DA7219_MICBIAS_1_8V: | ||
1619 | case DA7219_MICBIAS_2_0V: | ||
1620 | case DA7219_MICBIAS_2_2V: | ||
1621 | case DA7219_MICBIAS_2_4V: | ||
1622 | case DA7219_MICBIAS_2_6V: | ||
1623 | micbias_lvl |= (pdata->micbias_lvl << | ||
1624 | DA7219_MICBIAS1_LEVEL_SHIFT); | ||
1625 | break; | ||
1626 | } | ||
1627 | |||
1628 | snd_soc_write(codec, DA7219_MICBIAS_CTRL, micbias_lvl); | ||
1629 | |||
1630 | /* Mic */ | ||
1631 | switch (pdata->mic_amp_in_sel) { | ||
1632 | case DA7219_MIC_AMP_IN_SEL_DIFF: | ||
1633 | case DA7219_MIC_AMP_IN_SEL_SE_P: | ||
1634 | case DA7219_MIC_AMP_IN_SEL_SE_N: | ||
1635 | snd_soc_write(codec, DA7219_MIC_1_SELECT, | ||
1636 | pdata->mic_amp_in_sel); | ||
1637 | break; | ||
1638 | } | ||
1639 | } | ||
1640 | } | ||
1641 | |||
1642 | static int da7219_probe(struct snd_soc_codec *codec) | ||
1643 | { | ||
1644 | struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); | ||
1645 | int ret; | ||
1646 | |||
1647 | mutex_init(&da7219->lock); | ||
1648 | |||
1649 | /* Regulator configuration */ | ||
1650 | ret = da7219_handle_supplies(codec); | ||
1651 | if (ret) | ||
1652 | return ret; | ||
1653 | |||
1654 | /* Handle DT/Platform data */ | ||
1655 | if (codec->dev->of_node) | ||
1656 | da7219->pdata = da7219_of_to_pdata(codec); | ||
1657 | else | ||
1658 | da7219->pdata = dev_get_platdata(codec->dev); | ||
1659 | |||
1660 | da7219_handle_pdata(codec); | ||
1661 | |||
1662 | /* Check if MCLK provided */ | ||
1663 | da7219->mclk = devm_clk_get(codec->dev, "mclk"); | ||
1664 | if (IS_ERR(da7219->mclk)) { | ||
1665 | if (PTR_ERR(da7219->mclk) != -ENOENT) | ||
1666 | return PTR_ERR(da7219->mclk); | ||
1667 | else | ||
1668 | da7219->mclk = NULL; | ||
1669 | } | ||
1670 | |||
1671 | /* Default PC counter to free-running */ | ||
1672 | snd_soc_update_bits(codec, DA7219_PC_COUNT, DA7219_PC_FREERUN_MASK, | ||
1673 | DA7219_PC_FREERUN_MASK); | ||
1674 | |||
1675 | /* Default gain ramping */ | ||
1676 | snd_soc_update_bits(codec, DA7219_MIXIN_L_CTRL, | ||
1677 | DA7219_MIXIN_L_AMP_RAMP_EN_MASK, | ||
1678 | DA7219_MIXIN_L_AMP_RAMP_EN_MASK); | ||
1679 | snd_soc_update_bits(codec, DA7219_ADC_L_CTRL, DA7219_ADC_L_RAMP_EN_MASK, | ||
1680 | DA7219_ADC_L_RAMP_EN_MASK); | ||
1681 | snd_soc_update_bits(codec, DA7219_DAC_L_CTRL, DA7219_DAC_L_RAMP_EN_MASK, | ||
1682 | DA7219_DAC_L_RAMP_EN_MASK); | ||
1683 | snd_soc_update_bits(codec, DA7219_DAC_R_CTRL, DA7219_DAC_R_RAMP_EN_MASK, | ||
1684 | DA7219_DAC_R_RAMP_EN_MASK); | ||
1685 | snd_soc_update_bits(codec, DA7219_HP_L_CTRL, | ||
1686 | DA7219_HP_L_AMP_RAMP_EN_MASK, | ||
1687 | DA7219_HP_L_AMP_RAMP_EN_MASK); | ||
1688 | snd_soc_update_bits(codec, DA7219_HP_R_CTRL, | ||
1689 | DA7219_HP_R_AMP_RAMP_EN_MASK, | ||
1690 | DA7219_HP_R_AMP_RAMP_EN_MASK); | ||
1691 | |||
1692 | /* Default infinite tone gen, start/stop by Kcontrol */ | ||
1693 | snd_soc_write(codec, DA7219_TONE_GEN_CYCLES, DA7219_BEEP_CYCLES_MASK); | ||
1694 | |||
1695 | /* Initialise AAD block */ | ||
1696 | return da7219_aad_init(codec); | ||
1697 | } | ||
1698 | |||
1699 | static int da7219_remove(struct snd_soc_codec *codec) | ||
1700 | { | ||
1701 | struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); | ||
1702 | |||
1703 | da7219_aad_exit(codec); | ||
1704 | |||
1705 | /* Supplies */ | ||
1706 | return regulator_bulk_disable(DA7219_NUM_SUPPLIES, da7219->supplies); | ||
1707 | } | ||
1708 | |||
1709 | #ifdef CONFIG_PM | ||
1710 | static int da7219_suspend(struct snd_soc_codec *codec) | ||
1711 | { | ||
1712 | struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); | ||
1713 | |||
1714 | snd_soc_codec_force_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1715 | |||
1716 | /* Put device into standby mode if jack detection disabled */ | ||
1717 | if (!da7219->aad->jack) | ||
1718 | snd_soc_write(codec, DA7219_SYSTEM_ACTIVE, 0); | ||
1719 | |||
1720 | return 0; | ||
1721 | } | ||
1722 | |||
1723 | static int da7219_resume(struct snd_soc_codec *codec) | ||
1724 | { | ||
1725 | struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); | ||
1726 | |||
1727 | /* Put device into active mode if previously pushed to standby */ | ||
1728 | if (!da7219->aad->jack) | ||
1729 | snd_soc_write(codec, DA7219_SYSTEM_ACTIVE, | ||
1730 | DA7219_SYSTEM_ACTIVE_MASK); | ||
1731 | |||
1732 | snd_soc_codec_force_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1733 | |||
1734 | return 0; | ||
1735 | } | ||
1736 | #else | ||
1737 | #define da7219_suspend NULL | ||
1738 | #define da7219_resume NULL | ||
1739 | #endif | ||
1740 | |||
1741 | static struct snd_soc_codec_driver soc_codec_dev_da7219 = { | ||
1742 | .probe = da7219_probe, | ||
1743 | .remove = da7219_remove, | ||
1744 | .suspend = da7219_suspend, | ||
1745 | .resume = da7219_resume, | ||
1746 | .set_bias_level = da7219_set_bias_level, | ||
1747 | |||
1748 | .controls = da7219_snd_controls, | ||
1749 | .num_controls = ARRAY_SIZE(da7219_snd_controls), | ||
1750 | |||
1751 | .dapm_widgets = da7219_dapm_widgets, | ||
1752 | .num_dapm_widgets = ARRAY_SIZE(da7219_dapm_widgets), | ||
1753 | .dapm_routes = da7219_audio_map, | ||
1754 | .num_dapm_routes = ARRAY_SIZE(da7219_audio_map), | ||
1755 | }; | ||
1756 | |||
1757 | |||
1758 | /* | ||
1759 | * Regmap configs | ||
1760 | */ | ||
1761 | |||
1762 | static struct reg_default da7219_reg_defaults[] = { | ||
1763 | { DA7219_MIC_1_SELECT, 0x00 }, | ||
1764 | { DA7219_CIF_TIMEOUT_CTRL, 0x01 }, | ||
1765 | { DA7219_SR_24_48, 0x00 }, | ||
1766 | { DA7219_SR, 0x0A }, | ||
1767 | { DA7219_CIF_I2C_ADDR_CFG, 0x02 }, | ||
1768 | { DA7219_PLL_CTRL, 0x10 }, | ||
1769 | { DA7219_PLL_FRAC_TOP, 0x00 }, | ||
1770 | { DA7219_PLL_FRAC_BOT, 0x00 }, | ||
1771 | { DA7219_PLL_INTEGER, 0x20 }, | ||
1772 | { DA7219_DIG_ROUTING_DAI, 0x10 }, | ||
1773 | { DA7219_DAI_CLK_MODE, 0x01 }, | ||
1774 | { DA7219_DAI_CTRL, 0x28 }, | ||
1775 | { DA7219_DAI_TDM_CTRL, 0x40 }, | ||
1776 | { DA7219_DIG_ROUTING_DAC, 0x32 }, | ||
1777 | { DA7219_DAI_OFFSET_LOWER, 0x00 }, | ||
1778 | { DA7219_DAI_OFFSET_UPPER, 0x00 }, | ||
1779 | { DA7219_REFERENCES, 0x00 }, | ||
1780 | { DA7219_MIXIN_L_SELECT, 0x00 }, | ||
1781 | { DA7219_MIXIN_L_GAIN, 0x03 }, | ||
1782 | { DA7219_ADC_L_GAIN, 0x6F }, | ||
1783 | { DA7219_ADC_FILTERS1, 0x80 }, | ||
1784 | { DA7219_MIC_1_GAIN, 0x01 }, | ||
1785 | { DA7219_SIDETONE_CTRL, 0x40 }, | ||
1786 | { DA7219_SIDETONE_GAIN, 0x0E }, | ||
1787 | { DA7219_DROUTING_ST_OUTFILT_1L, 0x01 }, | ||
1788 | { DA7219_DROUTING_ST_OUTFILT_1R, 0x02 }, | ||
1789 | { DA7219_DAC_FILTERS5, 0x00 }, | ||
1790 | { DA7219_DAC_FILTERS2, 0x88 }, | ||
1791 | { DA7219_DAC_FILTERS3, 0x88 }, | ||
1792 | { DA7219_DAC_FILTERS4, 0x08 }, | ||
1793 | { DA7219_DAC_FILTERS1, 0x80 }, | ||
1794 | { DA7219_DAC_L_GAIN, 0x6F }, | ||
1795 | { DA7219_DAC_R_GAIN, 0x6F }, | ||
1796 | { DA7219_CP_CTRL, 0x20 }, | ||
1797 | { DA7219_HP_L_GAIN, 0x39 }, | ||
1798 | { DA7219_HP_R_GAIN, 0x39 }, | ||
1799 | { DA7219_MIXOUT_L_SELECT, 0x00 }, | ||
1800 | { DA7219_MIXOUT_R_SELECT, 0x00 }, | ||
1801 | { DA7219_MICBIAS_CTRL, 0x03 }, | ||
1802 | { DA7219_MIC_1_CTRL, 0x40 }, | ||
1803 | { DA7219_MIXIN_L_CTRL, 0x40 }, | ||
1804 | { DA7219_ADC_L_CTRL, 0x40 }, | ||
1805 | { DA7219_DAC_L_CTRL, 0x40 }, | ||
1806 | { DA7219_DAC_R_CTRL, 0x40 }, | ||
1807 | { DA7219_HP_L_CTRL, 0x40 }, | ||
1808 | { DA7219_HP_R_CTRL, 0x40 }, | ||
1809 | { DA7219_MIXOUT_L_CTRL, 0x10 }, | ||
1810 | { DA7219_MIXOUT_R_CTRL, 0x10 }, | ||
1811 | { DA7219_CHIP_ID1, 0x23 }, | ||
1812 | { DA7219_CHIP_ID2, 0x93 }, | ||
1813 | { DA7219_CHIP_REVISION, 0x00 }, | ||
1814 | { DA7219_LDO_CTRL, 0x00 }, | ||
1815 | { DA7219_IO_CTRL, 0x00 }, | ||
1816 | { DA7219_GAIN_RAMP_CTRL, 0x00 }, | ||
1817 | { DA7219_PC_COUNT, 0x02 }, | ||
1818 | { DA7219_CP_VOL_THRESHOLD1, 0x0E }, | ||
1819 | { DA7219_DIG_CTRL, 0x00 }, | ||
1820 | { DA7219_ALC_CTRL2, 0x00 }, | ||
1821 | { DA7219_ALC_CTRL3, 0x00 }, | ||
1822 | { DA7219_ALC_NOISE, 0x3F }, | ||
1823 | { DA7219_ALC_TARGET_MIN, 0x3F }, | ||
1824 | { DA7219_ALC_TARGET_MAX, 0x00 }, | ||
1825 | { DA7219_ALC_GAIN_LIMITS, 0xFF }, | ||
1826 | { DA7219_ALC_ANA_GAIN_LIMITS, 0x71 }, | ||
1827 | { DA7219_ALC_ANTICLIP_CTRL, 0x00 }, | ||
1828 | { DA7219_ALC_ANTICLIP_LEVEL, 0x00 }, | ||
1829 | { DA7219_DAC_NG_SETUP_TIME, 0x00 }, | ||
1830 | { DA7219_DAC_NG_OFF_THRESH, 0x00 }, | ||
1831 | { DA7219_DAC_NG_ON_THRESH, 0x00 }, | ||
1832 | { DA7219_DAC_NG_CTRL, 0x00 }, | ||
1833 | { DA7219_TONE_GEN_CFG1, 0x00 }, | ||
1834 | { DA7219_TONE_GEN_CFG2, 0x00 }, | ||
1835 | { DA7219_TONE_GEN_CYCLES, 0x00 }, | ||
1836 | { DA7219_TONE_GEN_FREQ1_L, 0x55 }, | ||
1837 | { DA7219_TONE_GEN_FREQ1_U, 0x15 }, | ||
1838 | { DA7219_TONE_GEN_FREQ2_L, 0x00 }, | ||
1839 | { DA7219_TONE_GEN_FREQ2_U, 0x40 }, | ||
1840 | { DA7219_TONE_GEN_ON_PER, 0x02 }, | ||
1841 | { DA7219_TONE_GEN_OFF_PER, 0x01 }, | ||
1842 | { DA7219_ACCDET_IRQ_MASK_A, 0x00 }, | ||
1843 | { DA7219_ACCDET_IRQ_MASK_B, 0x00 }, | ||
1844 | { DA7219_ACCDET_CONFIG_1, 0xD6 }, | ||
1845 | { DA7219_ACCDET_CONFIG_2, 0x34 }, | ||
1846 | { DA7219_ACCDET_CONFIG_3, 0x0A }, | ||
1847 | { DA7219_ACCDET_CONFIG_4, 0x16 }, | ||
1848 | { DA7219_ACCDET_CONFIG_5, 0x21 }, | ||
1849 | { DA7219_ACCDET_CONFIG_6, 0x3E }, | ||
1850 | { DA7219_ACCDET_CONFIG_7, 0x01 }, | ||
1851 | { DA7219_SYSTEM_ACTIVE, 0x00 }, | ||
1852 | }; | ||
1853 | |||
1854 | static bool da7219_volatile_register(struct device *dev, unsigned int reg) | ||
1855 | { | ||
1856 | switch (reg) { | ||
1857 | case DA7219_MIC_1_GAIN_STATUS: | ||
1858 | case DA7219_MIXIN_L_GAIN_STATUS: | ||
1859 | case DA7219_ADC_L_GAIN_STATUS: | ||
1860 | case DA7219_DAC_L_GAIN_STATUS: | ||
1861 | case DA7219_DAC_R_GAIN_STATUS: | ||
1862 | case DA7219_HP_L_GAIN_STATUS: | ||
1863 | case DA7219_HP_R_GAIN_STATUS: | ||
1864 | case DA7219_CIF_CTRL: | ||
1865 | case DA7219_PLL_SRM_STS: | ||
1866 | case DA7219_ALC_CTRL1: | ||
1867 | case DA7219_SYSTEM_MODES_INPUT: | ||
1868 | case DA7219_SYSTEM_MODES_OUTPUT: | ||
1869 | case DA7219_ALC_OFFSET_AUTO_M_L: | ||
1870 | case DA7219_ALC_OFFSET_AUTO_U_L: | ||
1871 | case DA7219_TONE_GEN_CFG1: | ||
1872 | case DA7219_ACCDET_STATUS_A: | ||
1873 | case DA7219_ACCDET_STATUS_B: | ||
1874 | case DA7219_ACCDET_IRQ_EVENT_A: | ||
1875 | case DA7219_ACCDET_IRQ_EVENT_B: | ||
1876 | case DA7219_ACCDET_CONFIG_8: | ||
1877 | case DA7219_SYSTEM_STATUS: | ||
1878 | return 1; | ||
1879 | default: | ||
1880 | return 0; | ||
1881 | } | ||
1882 | } | ||
1883 | |||
1884 | static const struct regmap_config da7219_regmap_config = { | ||
1885 | .reg_bits = 8, | ||
1886 | .val_bits = 8, | ||
1887 | |||
1888 | .max_register = DA7219_SYSTEM_ACTIVE, | ||
1889 | .reg_defaults = da7219_reg_defaults, | ||
1890 | .num_reg_defaults = ARRAY_SIZE(da7219_reg_defaults), | ||
1891 | .volatile_reg = da7219_volatile_register, | ||
1892 | .cache_type = REGCACHE_RBTREE, | ||
1893 | }; | ||
1894 | |||
1895 | |||
1896 | /* | ||
1897 | * I2C layer | ||
1898 | */ | ||
1899 | |||
1900 | static int da7219_i2c_probe(struct i2c_client *i2c, | ||
1901 | const struct i2c_device_id *id) | ||
1902 | { | ||
1903 | struct da7219_priv *da7219; | ||
1904 | int ret; | ||
1905 | |||
1906 | da7219 = devm_kzalloc(&i2c->dev, sizeof(struct da7219_priv), | ||
1907 | GFP_KERNEL); | ||
1908 | if (!da7219) | ||
1909 | return -ENOMEM; | ||
1910 | |||
1911 | i2c_set_clientdata(i2c, da7219); | ||
1912 | |||
1913 | da7219->regmap = devm_regmap_init_i2c(i2c, &da7219_regmap_config); | ||
1914 | if (IS_ERR(da7219->regmap)) { | ||
1915 | ret = PTR_ERR(da7219->regmap); | ||
1916 | dev_err(&i2c->dev, "regmap_init() failed: %d\n", ret); | ||
1917 | return ret; | ||
1918 | } | ||
1919 | |||
1920 | ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_da7219, | ||
1921 | &da7219_dai, 1); | ||
1922 | if (ret < 0) { | ||
1923 | dev_err(&i2c->dev, "Failed to register da7219 codec: %d\n", | ||
1924 | ret); | ||
1925 | } | ||
1926 | return ret; | ||
1927 | } | ||
1928 | |||
1929 | static int da7219_i2c_remove(struct i2c_client *client) | ||
1930 | { | ||
1931 | snd_soc_unregister_codec(&client->dev); | ||
1932 | return 0; | ||
1933 | } | ||
1934 | |||
1935 | static const struct i2c_device_id da7219_i2c_id[] = { | ||
1936 | { "da7219", }, | ||
1937 | { } | ||
1938 | }; | ||
1939 | MODULE_DEVICE_TABLE(i2c, da7219_i2c_id); | ||
1940 | |||
1941 | static struct i2c_driver da7219_i2c_driver = { | ||
1942 | .driver = { | ||
1943 | .name = "da7219", | ||
1944 | .of_match_table = of_match_ptr(da7219_of_match), | ||
1945 | }, | ||
1946 | .probe = da7219_i2c_probe, | ||
1947 | .remove = da7219_i2c_remove, | ||
1948 | .id_table = da7219_i2c_id, | ||
1949 | }; | ||
1950 | |||
1951 | module_i2c_driver(da7219_i2c_driver); | ||
1952 | |||
1953 | MODULE_DESCRIPTION("ASoC DA7219 Codec Driver"); | ||
1954 | MODULE_AUTHOR("Adam Thomson <Adam.Thomson.Opensource@diasemi.com>"); | ||
1955 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/da7219.h b/sound/soc/codecs/da7219.h new file mode 100644 index 000000000000..b514268c6c56 --- /dev/null +++ b/sound/soc/codecs/da7219.h | |||
@@ -0,0 +1,820 @@ | |||
1 | /* | ||
2 | * da7219.h - DA7219 ALSA SoC Codec Driver | ||
3 | * | ||
4 | * Copyright (c) 2015 Dialog Semiconductor | ||
5 | * | ||
6 | * Author: Adam Thomson <Adam.Thomson.Opensource@diasemi.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | */ | ||
13 | |||
14 | #ifndef __DA7219_H | ||
15 | #define __DA7219_H | ||
16 | |||
17 | #include <linux/regmap.h> | ||
18 | #include <linux/regulator/consumer.h> | ||
19 | #include <sound/da7219.h> | ||
20 | |||
21 | /* | ||
22 | * Registers | ||
23 | */ | ||
24 | |||
25 | #define DA7219_MIC_1_GAIN_STATUS 0x6 | ||
26 | #define DA7219_MIXIN_L_GAIN_STATUS 0x8 | ||
27 | #define DA7219_ADC_L_GAIN_STATUS 0xA | ||
28 | #define DA7219_DAC_L_GAIN_STATUS 0xC | ||
29 | #define DA7219_DAC_R_GAIN_STATUS 0xD | ||
30 | #define DA7219_HP_L_GAIN_STATUS 0xE | ||
31 | #define DA7219_HP_R_GAIN_STATUS 0xF | ||
32 | #define DA7219_MIC_1_SELECT 0x10 | ||
33 | #define DA7219_CIF_TIMEOUT_CTRL 0x12 | ||
34 | #define DA7219_CIF_CTRL 0x13 | ||
35 | #define DA7219_SR_24_48 0x16 | ||
36 | #define DA7219_SR 0x17 | ||
37 | #define DA7219_CIF_I2C_ADDR_CFG 0x1B | ||
38 | #define DA7219_PLL_CTRL 0x20 | ||
39 | #define DA7219_PLL_FRAC_TOP 0x22 | ||
40 | #define DA7219_PLL_FRAC_BOT 0x23 | ||
41 | #define DA7219_PLL_INTEGER 0x24 | ||
42 | #define DA7219_PLL_SRM_STS 0x25 | ||
43 | #define DA7219_DIG_ROUTING_DAI 0x2A | ||
44 | #define DA7219_DAI_CLK_MODE 0x2B | ||
45 | #define DA7219_DAI_CTRL 0x2C | ||
46 | #define DA7219_DAI_TDM_CTRL 0x2D | ||
47 | #define DA7219_DIG_ROUTING_DAC 0x2E | ||
48 | #define DA7219_ALC_CTRL1 0x2F | ||
49 | #define DA7219_DAI_OFFSET_LOWER 0x30 | ||
50 | #define DA7219_DAI_OFFSET_UPPER 0x31 | ||
51 | #define DA7219_REFERENCES 0x32 | ||
52 | #define DA7219_MIXIN_L_SELECT 0x33 | ||
53 | #define DA7219_MIXIN_L_GAIN 0x34 | ||
54 | #define DA7219_ADC_L_GAIN 0x36 | ||
55 | #define DA7219_ADC_FILTERS1 0x38 | ||
56 | #define DA7219_MIC_1_GAIN 0x39 | ||
57 | #define DA7219_SIDETONE_CTRL 0x3A | ||
58 | #define DA7219_SIDETONE_GAIN 0x3B | ||
59 | #define DA7219_DROUTING_ST_OUTFILT_1L 0x3C | ||
60 | #define DA7219_DROUTING_ST_OUTFILT_1R 0x3D | ||
61 | #define DA7219_DAC_FILTERS5 0x40 | ||
62 | #define DA7219_DAC_FILTERS2 0x41 | ||
63 | #define DA7219_DAC_FILTERS3 0x42 | ||
64 | #define DA7219_DAC_FILTERS4 0x43 | ||
65 | #define DA7219_DAC_FILTERS1 0x44 | ||
66 | #define DA7219_DAC_L_GAIN 0x45 | ||
67 | #define DA7219_DAC_R_GAIN 0x46 | ||
68 | #define DA7219_CP_CTRL 0x47 | ||
69 | #define DA7219_HP_L_GAIN 0x48 | ||
70 | #define DA7219_HP_R_GAIN 0x49 | ||
71 | #define DA7219_MIXOUT_L_SELECT 0x4B | ||
72 | #define DA7219_MIXOUT_R_SELECT 0x4C | ||
73 | #define DA7219_SYSTEM_MODES_INPUT 0x50 | ||
74 | #define DA7219_SYSTEM_MODES_OUTPUT 0x51 | ||
75 | #define DA7219_MICBIAS_CTRL 0x62 | ||
76 | #define DA7219_MIC_1_CTRL 0x63 | ||
77 | #define DA7219_MIXIN_L_CTRL 0x65 | ||
78 | #define DA7219_ADC_L_CTRL 0x67 | ||
79 | #define DA7219_DAC_L_CTRL 0x69 | ||
80 | #define DA7219_DAC_R_CTRL 0x6A | ||
81 | #define DA7219_HP_L_CTRL 0x6B | ||
82 | #define DA7219_HP_R_CTRL 0x6C | ||
83 | #define DA7219_MIXOUT_L_CTRL 0x6E | ||
84 | #define DA7219_MIXOUT_R_CTRL 0x6F | ||
85 | #define DA7219_CHIP_ID1 0x81 | ||
86 | #define DA7219_CHIP_ID2 0x82 | ||
87 | #define DA7219_CHIP_REVISION 0x83 | ||
88 | #define DA7219_LDO_CTRL 0x90 | ||
89 | #define DA7219_IO_CTRL 0x91 | ||
90 | #define DA7219_GAIN_RAMP_CTRL 0x92 | ||
91 | #define DA7219_PC_COUNT 0x94 | ||
92 | #define DA7219_CP_VOL_THRESHOLD1 0x95 | ||
93 | #define DA7219_CP_DELAY 0x96 | ||
94 | #define DA7219_DIG_CTRL 0x99 | ||
95 | #define DA7219_ALC_CTRL2 0x9A | ||
96 | #define DA7219_ALC_CTRL3 0x9B | ||
97 | #define DA7219_ALC_NOISE 0x9C | ||
98 | #define DA7219_ALC_TARGET_MIN 0x9D | ||
99 | #define DA7219_ALC_TARGET_MAX 0x9E | ||
100 | #define DA7219_ALC_GAIN_LIMITS 0x9F | ||
101 | #define DA7219_ALC_ANA_GAIN_LIMITS 0xA0 | ||
102 | #define DA7219_ALC_ANTICLIP_CTRL 0xA1 | ||
103 | #define DA7219_ALC_ANTICLIP_LEVEL 0xA2 | ||
104 | #define DA7219_ALC_OFFSET_AUTO_M_L 0xA3 | ||
105 | #define DA7219_ALC_OFFSET_AUTO_U_L 0xA4 | ||
106 | #define DA7219_DAC_NG_SETUP_TIME 0xAF | ||
107 | #define DA7219_DAC_NG_OFF_THRESH 0xB0 | ||
108 | #define DA7219_DAC_NG_ON_THRESH 0xB1 | ||
109 | #define DA7219_DAC_NG_CTRL 0xB2 | ||
110 | #define DA7219_TONE_GEN_CFG1 0xB4 | ||
111 | #define DA7219_TONE_GEN_CFG2 0xB5 | ||
112 | #define DA7219_TONE_GEN_CYCLES 0xB6 | ||
113 | #define DA7219_TONE_GEN_FREQ1_L 0xB7 | ||
114 | #define DA7219_TONE_GEN_FREQ1_U 0xB8 | ||
115 | #define DA7219_TONE_GEN_FREQ2_L 0xB9 | ||
116 | #define DA7219_TONE_GEN_FREQ2_U 0xBA | ||
117 | #define DA7219_TONE_GEN_ON_PER 0xBB | ||
118 | #define DA7219_TONE_GEN_OFF_PER 0xBC | ||
119 | #define DA7219_SYSTEM_STATUS 0xE0 | ||
120 | #define DA7219_SYSTEM_ACTIVE 0xFD | ||
121 | |||
122 | |||
123 | /* | ||
124 | * Bit Fields | ||
125 | */ | ||
126 | |||
127 | #define DA7219_SWITCH_EN_MAX 0x1 | ||
128 | |||
129 | /* DA7219_MIC_1_GAIN_STATUS = 0x6 */ | ||
130 | #define DA7219_MIC_1_AMP_GAIN_STATUS_SHIFT 0 | ||
131 | #define DA7219_MIC_1_AMP_GAIN_STATUS_MASK (0x7 << 0) | ||
132 | #define DA7219_MIC_1_AMP_GAIN_MAX 0x7 | ||
133 | |||
134 | /* DA7219_MIXIN_L_GAIN_STATUS = 0x8 */ | ||
135 | #define DA7219_MIXIN_L_AMP_GAIN_STATUS_SHIFT 0 | ||
136 | #define DA7219_MIXIN_L_AMP_GAIN_STATUS_MASK (0xF << 0) | ||
137 | |||
138 | /* DA7219_ADC_L_GAIN_STATUS = 0xA */ | ||
139 | #define DA7219_ADC_L_DIGITAL_GAIN_STATUS_SHIFT 0 | ||
140 | #define DA7219_ADC_L_DIGITAL_GAIN_STATUS_MASK (0x7F << 0) | ||
141 | |||
142 | /* DA7219_DAC_L_GAIN_STATUS = 0xC */ | ||
143 | #define DA7219_DAC_L_DIGITAL_GAIN_STATUS_SHIFT 0 | ||
144 | #define DA7219_DAC_L_DIGITAL_GAIN_STATUS_MASK (0x7F << 0) | ||
145 | |||
146 | /* DA7219_DAC_R_GAIN_STATUS = 0xD */ | ||
147 | #define DA7219_DAC_R_DIGITAL_GAIN_STATUS_SHIFT 0 | ||
148 | #define DA7219_DAC_R_DIGITAL_GAIN_STATUS_MASK (0x7F << 0) | ||
149 | |||
150 | /* DA7219_HP_L_GAIN_STATUS = 0xE */ | ||
151 | #define DA7219_HP_L_AMP_GAIN_STATUS_SHIFT 0 | ||
152 | #define DA7219_HP_L_AMP_GAIN_STATUS_MASK (0x3F << 0) | ||
153 | |||
154 | /* DA7219_HP_R_GAIN_STATUS = 0xF */ | ||
155 | #define DA7219_HP_R_AMP_GAIN_STATUS_SHIFT 0 | ||
156 | #define DA7219_HP_R_AMP_GAIN_STATUS_MASK (0x3F << 0) | ||
157 | |||
158 | /* DA7219_MIC_1_SELECT = 0x10 */ | ||
159 | #define DA7219_MIC_1_AMP_IN_SEL_SHIFT 0 | ||
160 | #define DA7219_MIC_1_AMP_IN_SEL_MASK (0x3 << 0) | ||
161 | |||
162 | /* DA7219_CIF_TIMEOUT_CTRL = 0x12 */ | ||
163 | #define DA7219_I2C_TIMEOUT_EN_SHIFT 0 | ||
164 | #define DA7219_I2C_TIMEOUT_EN_MASK (0x1 << 0) | ||
165 | |||
166 | /* DA7219_CIF_CTRL = 0x13 */ | ||
167 | #define DA7219_CIF_I2C_WRITE_MODE_SHIFT 0 | ||
168 | #define DA7219_CIF_I2C_WRITE_MODE_MASK (0x1 << 0) | ||
169 | #define DA7219_CIF_REG_SOFT_RESET_SHIFT 7 | ||
170 | #define DA7219_CIF_REG_SOFT_RESET_MASK (0x1 << 7) | ||
171 | |||
172 | /* DA7219_SR_24_48 = 0x16 */ | ||
173 | #define DA7219_SR_24_48_SHIFT 0 | ||
174 | #define DA7219_SR_24_48_MASK (0x1 << 0) | ||
175 | |||
176 | /* DA7219_SR = 0x17 */ | ||
177 | #define DA7219_SR_SHIFT 0 | ||
178 | #define DA7219_SR_MASK (0xF << 0) | ||
179 | #define DA7219_SR_8000 (0x01 << 0) | ||
180 | #define DA7219_SR_11025 (0x02 << 0) | ||
181 | #define DA7219_SR_12000 (0x03 << 0) | ||
182 | #define DA7219_SR_16000 (0x05 << 0) | ||
183 | #define DA7219_SR_22050 (0x06 << 0) | ||
184 | #define DA7219_SR_24000 (0x07 << 0) | ||
185 | #define DA7219_SR_32000 (0x09 << 0) | ||
186 | #define DA7219_SR_44100 (0x0A << 0) | ||
187 | #define DA7219_SR_48000 (0x0B << 0) | ||
188 | #define DA7219_SR_88200 (0x0E << 0) | ||
189 | #define DA7219_SR_96000 (0x0F << 0) | ||
190 | |||
191 | /* DA7219_CIF_I2C_ADDR_CFG = 0x1B */ | ||
192 | #define DA7219_CIF_I2C_ADDR_CFG_SHIFT 0 | ||
193 | #define DA7219_CIF_I2C_ADDR_CFG_MASK (0x3 << 0) | ||
194 | |||
195 | /* DA7219_PLL_CTRL = 0x20 */ | ||
196 | #define DA7219_PLL_INDIV_SHIFT 2 | ||
197 | #define DA7219_PLL_INDIV_MASK (0x7 << 2) | ||
198 | #define DA7219_PLL_INDIV_2_5_MHZ (0x0 << 2) | ||
199 | #define DA7219_PLL_INDIV_5_10_MHZ (0x1 << 2) | ||
200 | #define DA7219_PLL_INDIV_10_20_MHZ (0x2 << 2) | ||
201 | #define DA7219_PLL_INDIV_20_40_MHZ (0x3 << 2) | ||
202 | #define DA7219_PLL_INDIV_40_54_MHZ (0x4 << 2) | ||
203 | #define DA7219_PLL_MCLK_SQR_EN_SHIFT 5 | ||
204 | #define DA7219_PLL_MCLK_SQR_EN_MASK (0x1 << 5) | ||
205 | #define DA7219_PLL_MODE_SHIFT 6 | ||
206 | #define DA7219_PLL_MODE_MASK (0x3 << 6) | ||
207 | #define DA7219_PLL_MODE_BYPASS (0x0 << 6) | ||
208 | #define DA7219_PLL_MODE_NORMAL (0x1 << 6) | ||
209 | #define DA7219_PLL_MODE_SRM (0x2 << 6) | ||
210 | #define DA7219_PLL_MODE_32KHZ (0x3 << 6) | ||
211 | |||
212 | /* DA7219_PLL_FRAC_TOP = 0x22 */ | ||
213 | #define DA7219_PLL_FBDIV_FRAC_TOP_SHIFT 0 | ||
214 | #define DA7219_PLL_FBDIV_FRAC_TOP_MASK (0x1F << 0) | ||
215 | |||
216 | /* DA7219_PLL_FRAC_BOT = 0x23 */ | ||
217 | #define DA7219_PLL_FBDIV_FRAC_BOT_SHIFT 0 | ||
218 | #define DA7219_PLL_FBDIV_FRAC_BOT_MASK (0xFF << 0) | ||
219 | |||
220 | /* DA7219_PLL_INTEGER = 0x24 */ | ||
221 | #define DA7219_PLL_FBDIV_INTEGER_SHIFT 0 | ||
222 | #define DA7219_PLL_FBDIV_INTEGER_MASK (0x7F << 0) | ||
223 | |||
224 | /* DA7219_PLL_SRM_STS = 0x25 */ | ||
225 | #define DA7219_PLL_SRM_STATE_SHIFT 0 | ||
226 | #define DA7219_PLL_SRM_STATE_MASK (0xF << 0) | ||
227 | #define DA7219_PLL_SRM_STATUS_SHIFT 4 | ||
228 | #define DA7219_PLL_SRM_STATUS_MASK (0xF << 4) | ||
229 | #define DA7219_PLL_SRM_STS_SRM_LOCK (0x1 << 7) | ||
230 | |||
231 | /* DA7219_DIG_ROUTING_DAI = 0x2A */ | ||
232 | #define DA7219_DAI_L_SRC_SHIFT 0 | ||
233 | #define DA7219_DAI_L_SRC_MASK (0x3 << 0) | ||
234 | #define DA7219_DAI_R_SRC_SHIFT 4 | ||
235 | #define DA7219_DAI_R_SRC_MASK (0x3 << 4) | ||
236 | #define DA7219_OUT_SRC_MAX 4 | ||
237 | |||
238 | /* DA7219_DAI_CLK_MODE = 0x2B */ | ||
239 | #define DA7219_DAI_BCLKS_PER_WCLK_SHIFT 0 | ||
240 | #define DA7219_DAI_BCLKS_PER_WCLK_MASK (0x3 << 0) | ||
241 | #define DA7219_DAI_BCLKS_PER_WCLK_32 (0x0 << 0) | ||
242 | #define DA7219_DAI_BCLKS_PER_WCLK_64 (0x1 << 0) | ||
243 | #define DA7219_DAI_BCLKS_PER_WCLK_128 (0x2 << 0) | ||
244 | #define DA7219_DAI_BCLKS_PER_WCLK_256 (0x3 << 0) | ||
245 | #define DA7219_DAI_CLK_POL_SHIFT 2 | ||
246 | #define DA7219_DAI_CLK_POL_MASK (0x1 << 2) | ||
247 | #define DA7219_DAI_CLK_POL_INV (0x1 << 2) | ||
248 | #define DA7219_DAI_WCLK_POL_SHIFT 3 | ||
249 | #define DA7219_DAI_WCLK_POL_MASK (0x1 << 3) | ||
250 | #define DA7219_DAI_WCLK_POL_INV (0x1 << 3) | ||
251 | #define DA7219_DAI_WCLK_TRI_STATE_SHIFT 4 | ||
252 | #define DA7219_DAI_WCLK_TRI_STATE_MASK (0x1 << 4) | ||
253 | #define DA7219_DAI_CLK_EN_SHIFT 7 | ||
254 | #define DA7219_DAI_CLK_EN_MASK (0x1 << 7) | ||
255 | |||
256 | /* DA7219_DAI_CTRL = 0x2C */ | ||
257 | #define DA7219_DAI_FORMAT_SHIFT 0 | ||
258 | #define DA7219_DAI_FORMAT_MASK (0x3 << 0) | ||
259 | #define DA7219_DAI_FORMAT_I2S (0x0 << 0) | ||
260 | #define DA7219_DAI_FORMAT_LEFT_J (0x1 << 0) | ||
261 | #define DA7219_DAI_FORMAT_RIGHT_J (0x2 << 0) | ||
262 | #define DA7219_DAI_FORMAT_DSP (0x3 << 0) | ||
263 | #define DA7219_DAI_WORD_LENGTH_SHIFT 2 | ||
264 | #define DA7219_DAI_WORD_LENGTH_MASK (0x3 << 2) | ||
265 | #define DA7219_DAI_WORD_LENGTH_S16_LE (0x0 << 2) | ||
266 | #define DA7219_DAI_WORD_LENGTH_S20_LE (0x1 << 2) | ||
267 | #define DA7219_DAI_WORD_LENGTH_S24_LE (0x2 << 2) | ||
268 | #define DA7219_DAI_WORD_LENGTH_S32_LE (0x3 << 2) | ||
269 | #define DA7219_DAI_CH_NUM_SHIFT 4 | ||
270 | #define DA7219_DAI_CH_NUM_MASK (0x3 << 4) | ||
271 | #define DA7219_DAI_CH_NUM_MAX 2 | ||
272 | #define DA7219_DAI_EN_SHIFT 7 | ||
273 | #define DA7219_DAI_EN_MASK (0x1 << 7) | ||
274 | |||
275 | /* DA7219_DAI_TDM_CTRL = 0x2D */ | ||
276 | #define DA7219_DAI_TDM_CH_EN_SHIFT 0 | ||
277 | #define DA7219_DAI_TDM_CH_EN_MASK (0x3 << 0) | ||
278 | #define DA7219_DAI_OE_SHIFT 6 | ||
279 | #define DA7219_DAI_OE_MASK (0x1 << 6) | ||
280 | #define DA7219_DAI_TDM_MODE_EN_SHIFT 7 | ||
281 | #define DA7219_DAI_TDM_MODE_EN_MASK (0x1 << 7) | ||
282 | #define DA7219_DAI_TDM_MAX_SLOTS 2 | ||
283 | |||
284 | /* DA7219_DIG_ROUTING_DAC = 0x2E */ | ||
285 | #define DA7219_DAC_L_SRC_SHIFT 0 | ||
286 | #define DA7219_DAC_L_SRC_MASK (0x3 << 0) | ||
287 | #define DA7219_DAC_L_SRC_TONEGEN (0x1 << 0) | ||
288 | #define DA7219_DAC_L_MONO_SHIFT 3 | ||
289 | #define DA7219_DAC_L_MONO_MASK (0x1 << 3) | ||
290 | #define DA7219_DAC_R_SRC_SHIFT 4 | ||
291 | #define DA7219_DAC_R_SRC_MASK (0x3 << 4) | ||
292 | #define DA7219_DAC_R_SRC_TONEGEN (0x1 << 4) | ||
293 | #define DA7219_DAC_R_MONO_SHIFT 7 | ||
294 | #define DA7219_DAC_R_MONO_MASK (0x1 << 7) | ||
295 | |||
296 | /* DA7219_ALC_CTRL1 = 0x2F */ | ||
297 | #define DA7219_ALC_OFFSET_EN_SHIFT 0 | ||
298 | #define DA7219_ALC_OFFSET_EN_MASK (0x1 << 0) | ||
299 | #define DA7219_ALC_SYNC_MODE_SHIFT 1 | ||
300 | #define DA7219_ALC_SYNC_MODE_MASK (0x1 << 1) | ||
301 | #define DA7219_ALC_EN_SHIFT 3 | ||
302 | #define DA7219_ALC_EN_MASK (0x1 << 3) | ||
303 | #define DA7219_ALC_AUTO_CALIB_EN_SHIFT 4 | ||
304 | #define DA7219_ALC_AUTO_CALIB_EN_MASK (0x1 << 4) | ||
305 | #define DA7219_ALC_CALIB_OVERFLOW_SHIFT 5 | ||
306 | #define DA7219_ALC_CALIB_OVERFLOW_MASK (0x1 << 5) | ||
307 | |||
308 | /* DA7219_DAI_OFFSET_LOWER = 0x30 */ | ||
309 | #define DA7219_DAI_OFFSET_LOWER_SHIFT 0 | ||
310 | #define DA7219_DAI_OFFSET_LOWER_MASK (0xFF << 0) | ||
311 | |||
312 | /* DA7219_DAI_OFFSET_UPPER = 0x31 */ | ||
313 | #define DA7219_DAI_OFFSET_UPPER_SHIFT 0 | ||
314 | #define DA7219_DAI_OFFSET_UPPER_MASK (0x7 << 0) | ||
315 | #define DA7219_DAI_OFFSET_MAX 0x2FF | ||
316 | |||
317 | /* DA7219_REFERENCES = 0x32 */ | ||
318 | #define DA7219_BIAS_EN_SHIFT 3 | ||
319 | #define DA7219_BIAS_EN_MASK (0x1 << 3) | ||
320 | #define DA7219_VMID_FAST_CHARGE_SHIFT 4 | ||
321 | #define DA7219_VMID_FAST_CHARGE_MASK (0x1 << 4) | ||
322 | |||
323 | /* DA7219_MIXIN_L_SELECT = 0x33 */ | ||
324 | #define DA7219_MIXIN_L_MIX_SELECT_SHIFT 0 | ||
325 | #define DA7219_MIXIN_L_MIX_SELECT_MASK (0x1 << 0) | ||
326 | |||
327 | /* DA7219_MIXIN_L_GAIN = 0x34 */ | ||
328 | #define DA7219_MIXIN_L_AMP_GAIN_SHIFT 0 | ||
329 | #define DA7219_MIXIN_L_AMP_GAIN_MASK (0xF << 0) | ||
330 | #define DA7219_MIXIN_L_AMP_GAIN_MAX 0xF | ||
331 | |||
332 | /* DA7219_ADC_L_GAIN = 0x36 */ | ||
333 | #define DA7219_ADC_L_DIGITAL_GAIN_SHIFT 0 | ||
334 | #define DA7219_ADC_L_DIGITAL_GAIN_MASK (0x7F << 0) | ||
335 | #define DA7219_ADC_L_DIGITAL_GAIN_MAX 0x7F | ||
336 | |||
337 | /* DA7219_ADC_FILTERS1 = 0x38 */ | ||
338 | #define DA7219_ADC_VOICE_HPF_CORNER_SHIFT 0 | ||
339 | #define DA7219_ADC_VOICE_HPF_CORNER_MASK (0x7 << 0) | ||
340 | #define DA7219_VOICE_HPF_CORNER_MAX 8 | ||
341 | #define DA7219_ADC_VOICE_EN_SHIFT 3 | ||
342 | #define DA7219_ADC_VOICE_EN_MASK (0x1 << 3) | ||
343 | #define DA7219_ADC_AUDIO_HPF_CORNER_SHIFT 4 | ||
344 | #define DA7219_ADC_AUDIO_HPF_CORNER_MASK (0x3 << 4) | ||
345 | #define DA7219_AUDIO_HPF_CORNER_MAX 4 | ||
346 | #define DA7219_ADC_HPF_EN_SHIFT 7 | ||
347 | #define DA7219_ADC_HPF_EN_MASK (0x1 << 7) | ||
348 | #define DA7219_HPF_MODE_SHIFT 0 | ||
349 | #define DA7219_HPF_DISABLED ((0x0 << 3) | (0x0 << 7)) | ||
350 | #define DA7219_HPF_AUDIO_EN ((0x0 << 3) | (0x1 << 7)) | ||
351 | #define DA7219_HPF_VOICE_EN ((0x1 << 3) | (0x1 << 7)) | ||
352 | #define DA7219_HPF_MODE_MASK ((0x1 << 3) | (0x1 << 7)) | ||
353 | #define DA7219_HPF_MODE_MAX 3 | ||
354 | |||
355 | /* DA7219_MIC_1_GAIN = 0x39 */ | ||
356 | #define DA7219_MIC_1_AMP_GAIN_SHIFT 0 | ||
357 | #define DA7219_MIC_1_AMP_GAIN_MASK (0x7 << 0) | ||
358 | |||
359 | /* DA7219_SIDETONE_CTRL = 0x3A */ | ||
360 | #define DA7219_SIDETONE_MUTE_EN_SHIFT 6 | ||
361 | #define DA7219_SIDETONE_MUTE_EN_MASK (0x1 << 6) | ||
362 | #define DA7219_SIDETONE_EN_SHIFT 7 | ||
363 | #define DA7219_SIDETONE_EN_MASK (0x1 << 7) | ||
364 | |||
365 | /* DA7219_SIDETONE_GAIN = 0x3B */ | ||
366 | #define DA7219_SIDETONE_GAIN_SHIFT 0 | ||
367 | #define DA7219_SIDETONE_GAIN_MASK (0xF << 0) | ||
368 | #define DA7219_SIDETONE_GAIN_MAX 0xE | ||
369 | |||
370 | /* DA7219_DROUTING_ST_OUTFILT_1L = 0x3C */ | ||
371 | #define DA7219_OUTFILT_ST_1L_SRC_SHIFT 0 | ||
372 | #define DA7219_OUTFILT_ST_1L_SRC_MASK (0x7 << 0) | ||
373 | #define DA7219_DMIX_ST_SRC_OUTFILT1L_SHIFT 0 | ||
374 | #define DA7219_DMIX_ST_SRC_OUTFILT1R_SHIFT 1 | ||
375 | #define DA7219_DMIX_ST_SRC_SIDETONE_SHIFT 2 | ||
376 | #define DA7219_DMIX_ST_SRC_OUTFILT1L (0x1 << 0) | ||
377 | #define DA7219_DMIX_ST_SRC_OUTFILT1R (0x1 << 1) | ||
378 | |||
379 | /* DA7219_DROUTING_ST_OUTFILT_1R = 0x3D */ | ||
380 | #define DA7219_OUTFILT_ST_1R_SRC_SHIFT 0 | ||
381 | #define DA7219_OUTFILT_ST_1R_SRC_MASK (0x7 << 0) | ||
382 | |||
383 | /* DA7219_DAC_FILTERS5 = 0x40 */ | ||
384 | #define DA7219_DAC_SOFTMUTE_RATE_SHIFT 4 | ||
385 | #define DA7219_DAC_SOFTMUTE_RATE_MASK (0x7 << 4) | ||
386 | #define DA7219_DAC_SOFTMUTE_RATE_MAX 7 | ||
387 | #define DA7219_DAC_SOFTMUTE_EN_SHIFT 7 | ||
388 | #define DA7219_DAC_SOFTMUTE_EN_MASK (0x1 << 7) | ||
389 | |||
390 | /* DA7219_DAC_FILTERS2 = 0x41 */ | ||
391 | #define DA7219_DAC_EQ_BAND1_SHIFT 0 | ||
392 | #define DA7219_DAC_EQ_BAND1_MASK (0xF << 0) | ||
393 | #define DA7219_DAC_EQ_BAND2_SHIFT 4 | ||
394 | #define DA7219_DAC_EQ_BAND2_MASK (0xF << 4) | ||
395 | #define DA7219_DAC_EQ_BAND_MAX 0xF | ||
396 | |||
397 | /* DA7219_DAC_FILTERS3 = 0x42 */ | ||
398 | #define DA7219_DAC_EQ_BAND3_SHIFT 0 | ||
399 | #define DA7219_DAC_EQ_BAND3_MASK (0xF << 0) | ||
400 | #define DA7219_DAC_EQ_BAND4_SHIFT 4 | ||
401 | #define DA7219_DAC_EQ_BAND4_MASK (0xF << 4) | ||
402 | |||
403 | /* DA7219_DAC_FILTERS4 = 0x43 */ | ||
404 | #define DA7219_DAC_EQ_BAND5_SHIFT 0 | ||
405 | #define DA7219_DAC_EQ_BAND5_MASK (0xF << 0) | ||
406 | #define DA7219_DAC_EQ_EN_SHIFT 7 | ||
407 | #define DA7219_DAC_EQ_EN_MASK (0x1 << 7) | ||
408 | |||
409 | /* DA7219_DAC_FILTERS1 = 0x44 */ | ||
410 | #define DA7219_DAC_VOICE_HPF_CORNER_SHIFT 0 | ||
411 | #define DA7219_DAC_VOICE_HPF_CORNER_MASK (0x7 << 0) | ||
412 | #define DA7219_DAC_VOICE_EN_SHIFT 3 | ||
413 | #define DA7219_DAC_VOICE_EN_MASK (0x1 << 3) | ||
414 | #define DA7219_DAC_AUDIO_HPF_CORNER_SHIFT 4 | ||
415 | #define DA7219_DAC_AUDIO_HPF_CORNER_MASK (0x3 << 4) | ||
416 | #define DA7219_DAC_HPF_EN_SHIFT 7 | ||
417 | #define DA7219_DAC_HPF_EN_MASK (0x1 << 7) | ||
418 | |||
419 | /* DA7219_DAC_L_GAIN = 0x45 */ | ||
420 | #define DA7219_DAC_L_DIGITAL_GAIN_SHIFT 0 | ||
421 | #define DA7219_DAC_L_DIGITAL_GAIN_MASK (0x7F << 0) | ||
422 | #define DA7219_DAC_DIGITAL_GAIN_MAX 0x7F | ||
423 | #define DA7219_DAC_DIGITAL_GAIN_0DB (0x6F << 0) | ||
424 | |||
425 | /* DA7219_DAC_R_GAIN = 0x46 */ | ||
426 | #define DA7219_DAC_R_DIGITAL_GAIN_SHIFT 0 | ||
427 | #define DA7219_DAC_R_DIGITAL_GAIN_MASK (0x7F << 0) | ||
428 | |||
429 | /* DA7219_CP_CTRL = 0x47 */ | ||
430 | #define DA7219_CP_MCHANGE_SHIFT 4 | ||
431 | #define DA7219_CP_MCHANGE_MASK (0x3 << 4) | ||
432 | #define DA7219_CP_MCHANGE_REL_MASK 0x3 | ||
433 | #define DA7219_CP_MCHANGE_MAX 3 | ||
434 | #define DA7219_CP_MCHANGE_LARGEST_VOL 0x1 | ||
435 | #define DA7219_CP_MCHANGE_DAC_VOL 0x2 | ||
436 | #define DA7219_CP_MCHANGE_SIG_MAG 0x3 | ||
437 | #define DA7219_CP_EN_SHIFT 7 | ||
438 | #define DA7219_CP_EN_MASK (0x1 << 7) | ||
439 | |||
440 | /* DA7219_HP_L_GAIN = 0x48 */ | ||
441 | #define DA7219_HP_L_AMP_GAIN_SHIFT 0 | ||
442 | #define DA7219_HP_L_AMP_GAIN_MASK (0x3F << 0) | ||
443 | #define DA7219_HP_AMP_GAIN_MAX 0x3F | ||
444 | #define DA7219_HP_AMP_GAIN_0DB (0x39 << 0) | ||
445 | |||
446 | /* DA7219_HP_R_GAIN = 0x49 */ | ||
447 | #define DA7219_HP_R_AMP_GAIN_SHIFT 0 | ||
448 | #define DA7219_HP_R_AMP_GAIN_MASK (0x3F << 0) | ||
449 | |||
450 | /* DA7219_MIXOUT_L_SELECT = 0x4B */ | ||
451 | #define DA7219_MIXOUT_L_MIX_SELECT_SHIFT 0 | ||
452 | #define DA7219_MIXOUT_L_MIX_SELECT_MASK (0x1 << 0) | ||
453 | |||
454 | /* DA7219_MIXOUT_R_SELECT = 0x4C */ | ||
455 | #define DA7219_MIXOUT_R_MIX_SELECT_SHIFT 0 | ||
456 | #define DA7219_MIXOUT_R_MIX_SELECT_MASK (0x1 << 0) | ||
457 | |||
458 | /* DA7219_SYSTEM_MODES_INPUT = 0x50 */ | ||
459 | #define DA7219_MODE_SUBMIT_SHIFT 0 | ||
460 | #define DA7219_MODE_SUBMIT_MASK (0x1 << 0) | ||
461 | #define DA7219_ADC_MODE_SHIFT 1 | ||
462 | #define DA7219_ADC_MODE_MASK (0x7F << 1) | ||
463 | |||
464 | /* DA7219_SYSTEM_MODES_OUTPUT = 0x51 */ | ||
465 | #define DA7219_MODE_SUBMIT_SHIFT 0 | ||
466 | #define DA7219_MODE_SUBMIT_MASK (0x1 << 0) | ||
467 | #define DA7219_DAC_MODE_SHIFT 1 | ||
468 | #define DA7219_DAC_MODE_MASK (0x7F << 1) | ||
469 | |||
470 | /* DA7219_MICBIAS_CTRL = 0x62 */ | ||
471 | #define DA7219_MICBIAS1_LEVEL_SHIFT 0 | ||
472 | #define DA7219_MICBIAS1_LEVEL_MASK (0x7 << 0) | ||
473 | #define DA7219_MICBIAS1_EN_SHIFT 3 | ||
474 | #define DA7219_MICBIAS1_EN_MASK (0x1 << 3) | ||
475 | |||
476 | /* DA7219_MIC_1_CTRL = 0x63 */ | ||
477 | #define DA7219_MIC_1_AMP_RAMP_EN_SHIFT 5 | ||
478 | #define DA7219_MIC_1_AMP_RAMP_EN_MASK (0x1 << 5) | ||
479 | #define DA7219_MIC_1_AMP_MUTE_EN_SHIFT 6 | ||
480 | #define DA7219_MIC_1_AMP_MUTE_EN_MASK (0x1 << 6) | ||
481 | #define DA7219_MIC_1_AMP_EN_SHIFT 7 | ||
482 | #define DA7219_MIC_1_AMP_EN_MASK (0x1 << 7) | ||
483 | |||
484 | /* DA7219_MIXIN_L_CTRL = 0x65 */ | ||
485 | #define DA7219_MIXIN_L_MIX_EN_SHIFT 3 | ||
486 | #define DA7219_MIXIN_L_MIX_EN_MASK (0x1 << 3) | ||
487 | #define DA7219_MIXIN_L_AMP_ZC_EN_SHIFT 4 | ||
488 | #define DA7219_MIXIN_L_AMP_ZC_EN_MASK (0x1 << 4) | ||
489 | #define DA7219_MIXIN_L_AMP_RAMP_EN_SHIFT 5 | ||
490 | #define DA7219_MIXIN_L_AMP_RAMP_EN_MASK (0x1 << 5) | ||
491 | #define DA7219_MIXIN_L_AMP_MUTE_EN_SHIFT 6 | ||
492 | #define DA7219_MIXIN_L_AMP_MUTE_EN_MASK (0x1 << 6) | ||
493 | #define DA7219_MIXIN_L_AMP_EN_SHIFT 7 | ||
494 | #define DA7219_MIXIN_L_AMP_EN_MASK (0x1 << 7) | ||
495 | |||
496 | /* DA7219_ADC_L_CTRL = 0x67 */ | ||
497 | #define DA7219_ADC_L_BIAS_SHIFT 0 | ||
498 | #define DA7219_ADC_L_BIAS_MASK (0x3 << 0) | ||
499 | #define DA7219_ADC_L_RAMP_EN_SHIFT 5 | ||
500 | #define DA7219_ADC_L_RAMP_EN_MASK (0x1 << 5) | ||
501 | #define DA7219_ADC_L_MUTE_EN_SHIFT 6 | ||
502 | #define DA7219_ADC_L_MUTE_EN_MASK (0x1 << 6) | ||
503 | #define DA7219_ADC_L_EN_SHIFT 7 | ||
504 | #define DA7219_ADC_L_EN_MASK (0x1 << 7) | ||
505 | |||
506 | /* DA7219_DAC_L_CTRL = 0x69 */ | ||
507 | #define DA7219_DAC_L_RAMP_EN_SHIFT 5 | ||
508 | #define DA7219_DAC_L_RAMP_EN_MASK (0x1 << 5) | ||
509 | #define DA7219_DAC_L_MUTE_EN_SHIFT 6 | ||
510 | #define DA7219_DAC_L_MUTE_EN_MASK (0x1 << 6) | ||
511 | #define DA7219_DAC_L_EN_SHIFT 7 | ||
512 | #define DA7219_DAC_L_EN_MASK (0x1 << 7) | ||
513 | |||
514 | /* DA7219_DAC_R_CTRL = 0x6A */ | ||
515 | #define DA7219_DAC_R_RAMP_EN_SHIFT 5 | ||
516 | #define DA7219_DAC_R_RAMP_EN_MASK (0x1 << 5) | ||
517 | #define DA7219_DAC_R_MUTE_EN_SHIFT 6 | ||
518 | #define DA7219_DAC_R_MUTE_EN_MASK (0x1 << 6) | ||
519 | #define DA7219_DAC_R_EN_SHIFT 7 | ||
520 | #define DA7219_DAC_R_EN_MASK (0x1 << 7) | ||
521 | |||
522 | /* DA7219_HP_L_CTRL = 0x6B */ | ||
523 | #define DA7219_HP_L_AMP_MIN_GAIN_EN_SHIFT 2 | ||
524 | #define DA7219_HP_L_AMP_MIN_GAIN_EN_MASK (0x1 << 2) | ||
525 | #define DA7219_HP_L_AMP_OE_SHIFT 3 | ||
526 | #define DA7219_HP_L_AMP_OE_MASK (0x1 << 3) | ||
527 | #define DA7219_HP_L_AMP_ZC_EN_SHIFT 4 | ||
528 | #define DA7219_HP_L_AMP_ZC_EN_MASK (0x1 << 4) | ||
529 | #define DA7219_HP_L_AMP_RAMP_EN_SHIFT 5 | ||
530 | #define DA7219_HP_L_AMP_RAMP_EN_MASK (0x1 << 5) | ||
531 | #define DA7219_HP_L_AMP_MUTE_EN_SHIFT 6 | ||
532 | #define DA7219_HP_L_AMP_MUTE_EN_MASK (0x1 << 6) | ||
533 | #define DA7219_HP_L_AMP_EN_SHIFT 7 | ||
534 | #define DA7219_HP_L_AMP_EN_MASK (0x1 << 7) | ||
535 | |||
536 | /* DA7219_HP_R_CTRL = 0x6C */ | ||
537 | #define DA7219_HP_R_AMP_MIN_GAIN_EN_SHIFT 2 | ||
538 | #define DA7219_HP_R_AMP_MIN_GAIN_EN_MASK (0x1 << 2) | ||
539 | #define DA7219_HP_R_AMP_OE_SHIFT 3 | ||
540 | #define DA7219_HP_R_AMP_OE_MASK (0x1 << 3) | ||
541 | #define DA7219_HP_R_AMP_ZC_EN_SHIFT 4 | ||
542 | #define DA7219_HP_R_AMP_ZC_EN_MASK (0x1 << 4) | ||
543 | #define DA7219_HP_R_AMP_RAMP_EN_SHIFT 5 | ||
544 | #define DA7219_HP_R_AMP_RAMP_EN_MASK (0x1 << 5) | ||
545 | #define DA7219_HP_R_AMP_MUTE_EN_SHIFT 6 | ||
546 | #define DA7219_HP_R_AMP_MUTE_EN_MASK (0x1 << 6) | ||
547 | #define DA7219_HP_R_AMP_EN_SHIFT 7 | ||
548 | #define DA7219_HP_R_AMP_EN_MASK (0x1 << 7) | ||
549 | |||
550 | /* DA7219_MIXOUT_L_CTRL = 0x6E */ | ||
551 | #define DA7219_MIXOUT_L_AMP_EN_SHIFT 7 | ||
552 | #define DA7219_MIXOUT_L_AMP_EN_MASK (0x1 << 7) | ||
553 | |||
554 | /* DA7219_MIXOUT_R_CTRL = 0x6F */ | ||
555 | #define DA7219_MIXOUT_R_AMP_EN_SHIFT 7 | ||
556 | #define DA7219_MIXOUT_R_AMP_EN_MASK (0x1 << 7) | ||
557 | |||
558 | /* DA7219_CHIP_ID1 = 0x81 */ | ||
559 | #define DA7219_CHIP_ID1_SHIFT 0 | ||
560 | #define DA7219_CHIP_ID1_MASK (0xFF << 0) | ||
561 | |||
562 | /* DA7219_CHIP_ID2 = 0x82 */ | ||
563 | #define DA7219_CHIP_ID2_SHIFT 0 | ||
564 | #define DA7219_CHIP_ID2_MASK (0xFF << 0) | ||
565 | |||
566 | /* DA7219_CHIP_REVISION = 0x83 */ | ||
567 | #define DA7219_CHIP_MINOR_SHIFT 0 | ||
568 | #define DA7219_CHIP_MINOR_MASK (0xF << 0) | ||
569 | #define DA7219_CHIP_MAJOR_SHIFT 4 | ||
570 | #define DA7219_CHIP_MAJOR_MASK (0xF << 4) | ||
571 | |||
572 | /* DA7219_LDO_CTRL = 0x90 */ | ||
573 | #define DA7219_LDO_LEVEL_SELECT_SHIFT 4 | ||
574 | #define DA7219_LDO_LEVEL_SELECT_MASK (0x3 << 4) | ||
575 | #define DA7219_LDO_EN_SHIFT 7 | ||
576 | #define DA7219_LDO_EN_MASK (0x1 << 7) | ||
577 | |||
578 | /* DA7219_IO_CTRL = 0x91 */ | ||
579 | #define DA7219_IO_VOLTAGE_LEVEL_SHIFT 0 | ||
580 | #define DA7219_IO_VOLTAGE_LEVEL_MASK (0x1 << 0) | ||
581 | #define DA7219_IO_VOLTAGE_LEVEL_2_5V_3_6V 0 | ||
582 | #define DA7219_IO_VOLTAGE_LEVEL_1_2V_2_8V 1 | ||
583 | |||
584 | /* DA7219_GAIN_RAMP_CTRL = 0x92 */ | ||
585 | #define DA7219_GAIN_RAMP_RATE_SHIFT 0 | ||
586 | #define DA7219_GAIN_RAMP_RATE_MASK (0x3 << 0) | ||
587 | #define DA7219_GAIN_RAMP_RATE_MAX 4 | ||
588 | |||
589 | /* DA7219_PC_COUNT = 0x94 */ | ||
590 | #define DA7219_PC_FREERUN_SHIFT 0 | ||
591 | #define DA7219_PC_FREERUN_MASK (0x1 << 0) | ||
592 | #define DA7219_PC_RESYNC_AUTO_SHIFT 1 | ||
593 | #define DA7219_PC_RESYNC_AUTO_MASK (0x1 << 1) | ||
594 | |||
595 | /* DA7219_CP_VOL_THRESHOLD1 = 0x95 */ | ||
596 | #define DA7219_CP_THRESH_VDD2_SHIFT 0 | ||
597 | #define DA7219_CP_THRESH_VDD2_MASK (0x3F << 0) | ||
598 | #define DA7219_CP_THRESH_VDD2_MAX 0x3F | ||
599 | |||
600 | /* DA7219_DIG_CTRL = 0x99 */ | ||
601 | #define DA7219_DAC_L_INV_SHIFT 3 | ||
602 | #define DA7219_DAC_L_INV_MASK (0x1 << 3) | ||
603 | #define DA7219_DAC_R_INV_SHIFT 7 | ||
604 | #define DA7219_DAC_R_INV_MASK (0x1 << 7) | ||
605 | |||
606 | /* DA7219_ALC_CTRL2 = 0x9A */ | ||
607 | #define DA7219_ALC_ATTACK_SHIFT 0 | ||
608 | #define DA7219_ALC_ATTACK_MASK (0xF << 0) | ||
609 | #define DA7219_ALC_ATTACK_MAX 13 | ||
610 | #define DA7219_ALC_RELEASE_SHIFT 4 | ||
611 | #define DA7219_ALC_RELEASE_MASK (0xF << 4) | ||
612 | #define DA7219_ALC_RELEASE_MAX 11 | ||
613 | |||
614 | /* DA7219_ALC_CTRL3 = 0x9B */ | ||
615 | #define DA7219_ALC_HOLD_SHIFT 0 | ||
616 | #define DA7219_ALC_HOLD_MASK (0xF << 0) | ||
617 | #define DA7219_ALC_HOLD_MAX 16 | ||
618 | #define DA7219_ALC_INTEG_ATTACK_SHIFT 4 | ||
619 | #define DA7219_ALC_INTEG_ATTACK_MASK (0x3 << 4) | ||
620 | #define DA7219_ALC_INTEG_RELEASE_SHIFT 6 | ||
621 | #define DA7219_ALC_INTEG_RELEASE_MASK (0x3 << 6) | ||
622 | #define DA7219_ALC_INTEG_MAX 4 | ||
623 | |||
624 | /* DA7219_ALC_NOISE = 0x9C */ | ||
625 | #define DA7219_ALC_NOISE_SHIFT 0 | ||
626 | #define DA7219_ALC_NOISE_MASK (0x3F << 0) | ||
627 | #define DA7219_ALC_THRESHOLD_MAX 0x3F | ||
628 | |||
629 | /* DA7219_ALC_TARGET_MIN = 0x9D */ | ||
630 | #define DA7219_ALC_THRESHOLD_MIN_SHIFT 0 | ||
631 | #define DA7219_ALC_THRESHOLD_MIN_MASK (0x3F << 0) | ||
632 | |||
633 | /* DA7219_ALC_TARGET_MAX = 0x9E */ | ||
634 | #define DA7219_ALC_THRESHOLD_MAX_SHIFT 0 | ||
635 | #define DA7219_ALC_THRESHOLD_MAX_MASK (0x3F << 0) | ||
636 | |||
637 | /* DA7219_ALC_GAIN_LIMITS = 0x9F */ | ||
638 | #define DA7219_ALC_ATTEN_MAX_SHIFT 0 | ||
639 | #define DA7219_ALC_ATTEN_MAX_MASK (0xF << 0) | ||
640 | #define DA7219_ALC_GAIN_MAX_SHIFT 4 | ||
641 | #define DA7219_ALC_GAIN_MAX_MASK (0xF << 4) | ||
642 | #define DA7219_ALC_ATTEN_GAIN_MAX 0xF | ||
643 | |||
644 | /* DA7219_ALC_ANA_GAIN_LIMITS = 0xA0 */ | ||
645 | #define DA7219_ALC_ANA_GAIN_MIN_SHIFT 0 | ||
646 | #define DA7219_ALC_ANA_GAIN_MIN_MASK (0x7 << 0) | ||
647 | #define DA7219_ALC_ANA_GAIN_MIN 0x1 | ||
648 | #define DA7219_ALC_ANA_GAIN_MAX_SHIFT 4 | ||
649 | #define DA7219_ALC_ANA_GAIN_MAX_MASK (0x7 << 4) | ||
650 | #define DA7219_ALC_ANA_GAIN_MAX 0x7 | ||
651 | |||
652 | /* DA7219_ALC_ANTICLIP_CTRL = 0xA1 */ | ||
653 | #define DA7219_ALC_ANTICLIP_STEP_SHIFT 0 | ||
654 | #define DA7219_ALC_ANTICLIP_STEP_MASK (0x3 << 0) | ||
655 | #define DA7219_ALC_ANTICLIP_STEP_MAX 4 | ||
656 | #define DA7219_ALC_ANTIPCLIP_EN_SHIFT 7 | ||
657 | #define DA7219_ALC_ANTIPCLIP_EN_MASK (0x1 << 7) | ||
658 | |||
659 | /* DA7219_ALC_ANTICLIP_LEVEL = 0xA2 */ | ||
660 | #define DA7219_ALC_ANTICLIP_LEVEL_SHIFT 0 | ||
661 | #define DA7219_ALC_ANTICLIP_LEVEL_MASK (0x7F << 0) | ||
662 | |||
663 | /* DA7219_ALC_OFFSET_AUTO_M_L = 0xA3 */ | ||
664 | #define DA7219_ALC_OFFSET_AUTO_M_L_SHIFT 0 | ||
665 | #define DA7219_ALC_OFFSET_AUTO_M_L_MASK (0xFF << 0) | ||
666 | |||
667 | /* DA7219_ALC_OFFSET_AUTO_U_L = 0xA4 */ | ||
668 | #define DA7219_ALC_OFFSET_AUTO_U_L_SHIFT 0 | ||
669 | #define DA7219_ALC_OFFSET_AUTO_U_L_MASK (0xF << 0) | ||
670 | |||
671 | /* DA7219_DAC_NG_SETUP_TIME = 0xAF */ | ||
672 | #define DA7219_DAC_NG_SETUP_TIME_SHIFT 0 | ||
673 | #define DA7219_DAC_NG_SETUP_TIME_MASK (0x3 << 0) | ||
674 | #define DA7219_DAC_NG_SETUP_TIME_MAX 4 | ||
675 | #define DA7219_DAC_NG_RAMPUP_RATE_SHIFT 2 | ||
676 | #define DA7219_DAC_NG_RAMPUP_RATE_MASK (0x1 << 2) | ||
677 | #define DA7219_DAC_NG_RAMPDN_RATE_SHIFT 3 | ||
678 | #define DA7219_DAC_NG_RAMPDN_RATE_MASK (0x1 << 3) | ||
679 | #define DA7219_DAC_NG_RAMP_RATE_MAX 2 | ||
680 | |||
681 | /* DA7219_DAC_NG_OFF_THRESH = 0xB0 */ | ||
682 | #define DA7219_DAC_NG_OFF_THRESHOLD_SHIFT 0 | ||
683 | #define DA7219_DAC_NG_OFF_THRESHOLD_MASK (0x7 << 0) | ||
684 | #define DA7219_DAC_NG_THRESHOLD_MAX 0x7 | ||
685 | |||
686 | /* DA7219_DAC_NG_ON_THRESH = 0xB1 */ | ||
687 | #define DA7219_DAC_NG_ON_THRESHOLD_SHIFT 0 | ||
688 | #define DA7219_DAC_NG_ON_THRESHOLD_MASK (0x7 << 0) | ||
689 | |||
690 | /* DA7219_DAC_NG_CTRL = 0xB2 */ | ||
691 | #define DA7219_DAC_NG_EN_SHIFT 7 | ||
692 | #define DA7219_DAC_NG_EN_MASK (0x1 << 7) | ||
693 | |||
694 | /* DA7219_TONE_GEN_CFG1 = 0xB4 */ | ||
695 | #define DA7219_DTMF_REG_SHIFT 0 | ||
696 | #define DA7219_DTMF_REG_MASK (0xF << 0) | ||
697 | #define DA7219_DTMF_REG_MAX 16 | ||
698 | #define DA7219_DTMF_EN_SHIFT 4 | ||
699 | #define DA7219_DTMF_EN_MASK (0x1 << 4) | ||
700 | #define DA7219_START_STOPN_SHIFT 7 | ||
701 | #define DA7219_START_STOPN_MASK (0x1 << 7) | ||
702 | |||
703 | /* DA7219_TONE_GEN_CFG2 = 0xB5 */ | ||
704 | #define DA7219_SWG_SEL_SHIFT 0 | ||
705 | #define DA7219_SWG_SEL_MASK (0x3 << 0) | ||
706 | #define DA7219_SWG_SEL_MAX 4 | ||
707 | #define DA7219_SWG_SEL_SRAMP (0x3 << 0) | ||
708 | #define DA7219_TONE_GEN_GAIN_SHIFT 4 | ||
709 | #define DA7219_TONE_GEN_GAIN_MASK (0xF << 4) | ||
710 | #define DA7219_TONE_GEN_GAIN_MAX 0xF | ||
711 | #define DA7219_TONE_GEN_GAIN_MINUS_9DB (0x3 << 4) | ||
712 | #define DA7219_TONE_GEN_GAIN_MINUS_15DB (0x5 << 4) | ||
713 | |||
714 | /* DA7219_TONE_GEN_CYCLES = 0xB6 */ | ||
715 | #define DA7219_BEEP_CYCLES_SHIFT 0 | ||
716 | #define DA7219_BEEP_CYCLES_MASK (0x7 << 0) | ||
717 | |||
718 | /* DA7219_TONE_GEN_FREQ1_L = 0xB7 */ | ||
719 | #define DA7219_FREQ1_L_SHIFT 0 | ||
720 | #define DA7219_FREQ1_L_MASK (0xFF << 0) | ||
721 | #define DA7219_FREQ_MAX 0xFFFF | ||
722 | |||
723 | /* DA7219_TONE_GEN_FREQ1_U = 0xB8 */ | ||
724 | #define DA7219_FREQ1_U_SHIFT 0 | ||
725 | #define DA7219_FREQ1_U_MASK (0xFF << 0) | ||
726 | |||
727 | /* DA7219_TONE_GEN_FREQ2_L = 0xB9 */ | ||
728 | #define DA7219_FREQ2_L_SHIFT 0 | ||
729 | #define DA7219_FREQ2_L_MASK (0xFF << 0) | ||
730 | |||
731 | /* DA7219_TONE_GEN_FREQ2_U = 0xBA */ | ||
732 | #define DA7219_FREQ2_U_SHIFT 0 | ||
733 | #define DA7219_FREQ2_U_MASK (0xFF << 0) | ||
734 | |||
735 | /* DA7219_TONE_GEN_ON_PER = 0xBB */ | ||
736 | #define DA7219_BEEP_ON_PER_SHIFT 0 | ||
737 | #define DA7219_BEEP_ON_PER_MASK (0x3F << 0) | ||
738 | #define DA7219_BEEP_ON_OFF_MAX 0x3F | ||
739 | |||
740 | /* DA7219_TONE_GEN_OFF_PER = 0xBC */ | ||
741 | #define DA7219_BEEP_OFF_PER_SHIFT 0 | ||
742 | #define DA7219_BEEP_OFF_PER_MASK (0x3F << 0) | ||
743 | |||
744 | /* DA7219_SYSTEM_STATUS = 0xE0 */ | ||
745 | #define DA7219_SC1_BUSY_SHIFT 0 | ||
746 | #define DA7219_SC1_BUSY_MASK (0x1 << 0) | ||
747 | #define DA7219_SC2_BUSY_SHIFT 1 | ||
748 | #define DA7219_SC2_BUSY_MASK (0x1 << 1) | ||
749 | |||
750 | /* DA7219_SYSTEM_ACTIVE = 0xFD */ | ||
751 | #define DA7219_SYSTEM_ACTIVE_SHIFT 0 | ||
752 | #define DA7219_SYSTEM_ACTIVE_MASK (0x1 << 0) | ||
753 | |||
754 | |||
755 | /* | ||
756 | * General defines & data | ||
757 | */ | ||
758 | |||
759 | /* Register inversion */ | ||
760 | #define DA7219_NO_INVERT 0 | ||
761 | #define DA7219_INVERT 1 | ||
762 | |||
763 | /* Byte related defines */ | ||
764 | #define DA7219_BYTE_SHIFT 8 | ||
765 | #define DA7219_BYTE_MASK 0xFF | ||
766 | |||
767 | /* PLL Output Frequencies */ | ||
768 | #define DA7219_PLL_FREQ_OUT_90316 90316800 | ||
769 | #define DA7219_PLL_FREQ_OUT_98304 98304000 | ||
770 | |||
771 | /* PLL Frequency Dividers */ | ||
772 | #define DA7219_PLL_INDIV_2_5_MHZ_VAL 1 | ||
773 | #define DA7219_PLL_INDIV_5_10_MHZ_VAL 2 | ||
774 | #define DA7219_PLL_INDIV_10_20_MHZ_VAL 4 | ||
775 | #define DA7219_PLL_INDIV_20_40_MHZ_VAL 8 | ||
776 | #define DA7219_PLL_INDIV_40_54_MHZ_VAL 16 | ||
777 | |||
778 | /* SRM */ | ||
779 | #define DA7219_SRM_CHECK_RETRIES 8 | ||
780 | |||
781 | enum da7219_clk_src { | ||
782 | DA7219_CLKSRC_MCLK = 0, | ||
783 | DA7219_CLKSRC_MCLK_SQR, | ||
784 | }; | ||
785 | |||
786 | enum da7219_sys_clk { | ||
787 | DA7219_SYSCLK_MCLK = 0, | ||
788 | DA7219_SYSCLK_PLL, | ||
789 | DA7219_SYSCLK_PLL_SRM, | ||
790 | DA7219_SYSCLK_PLL_32KHZ | ||
791 | }; | ||
792 | |||
793 | /* Regulators */ | ||
794 | enum da7219_supplies { | ||
795 | DA7219_SUPPLY_VDD = 0, | ||
796 | DA7219_SUPPLY_VDDMIC, | ||
797 | DA7219_SUPPLY_VDDIO, | ||
798 | DA7219_NUM_SUPPLIES, | ||
799 | }; | ||
800 | |||
801 | struct da7219_aad_priv; | ||
802 | |||
803 | /* Private data */ | ||
804 | struct da7219_priv { | ||
805 | struct da7219_aad_priv *aad; | ||
806 | struct da7219_pdata *pdata; | ||
807 | |||
808 | struct regulator_bulk_data supplies[DA7219_NUM_SUPPLIES]; | ||
809 | struct regmap *regmap; | ||
810 | struct mutex lock; | ||
811 | |||
812 | struct clk *mclk; | ||
813 | unsigned int mclk_rate; | ||
814 | int clk_src; | ||
815 | |||
816 | bool master; | ||
817 | bool alc_en; | ||
818 | }; | ||
819 | |||
820 | #endif /* __DA7219_H */ | ||