summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAmaury Pouly <amaury.pouly@gmail.com>2013-06-18 15:43:43 +0200
committerAmaury Pouly <amaury.pouly@gmail.com>2013-06-18 15:43:43 +0200
commitac4e76d0720eeca0dd00ec3bf1fcd80f76d543c0 (patch)
tree44ecd9aac360a15043e62ca2e49a58525fd040c1
parent57bb7b2d2704166b5d4dd307d3ae8d8ae99afbbd (diff)
downloadrockbox-ac4e76d0720eeca0dd00ec3bf1fcd80f76d543c0.tar.gz
rockbox-ac4e76d0720eeca0dd00ec3bf1fcd80f76d543c0.zip
imx233: implement audioin
Change-Id: I0cf896f59fd2176217d0dd1f6032c3463b936669
-rw-r--r--firmware/target/arm/imx233/audioin-imx233.c158
-rw-r--r--firmware/target/arm/imx233/audioin-imx233.h16
2 files changed, 168 insertions, 6 deletions
diff --git a/firmware/target/arm/imx233/audioin-imx233.c b/firmware/target/arm/imx233/audioin-imx233.c
index d3df627037..6c2a212c4d 100644
--- a/firmware/target/arm/imx233/audioin-imx233.c
+++ b/firmware/target/arm/imx233/audioin-imx233.c
@@ -19,26 +19,172 @@
19 * 19 *
20 ****************************************************************************/ 20 ****************************************************************************/
21#include "audioin-imx233.h" 21#include "audioin-imx233.h"
22#include "pcm_sampr.h"
23
24/* values in half-dB, one for each setting */
25static int audioin_vol[2][4]; /* 0=left, 1=right */
26static int audioin_select[2]; /* idem */
22 27
23void imx233_audioin_preinit(void) 28void imx233_audioin_preinit(void)
24{ 29{
25 /* Enable AUDIOIN block */ 30 /* Enable AUDIOIN block */
26 imx233_reset_block(&HW_AUDIOIN_CTRL); 31 imx233_reset_block(&HW_AUDIOIN_CTRL);
27 /* Enable ADC */
28 BF_SET(AUDIOIN_CTRL, CLKGATE);
29 /* Set word-length to 16-bit */ 32 /* Set word-length to 16-bit */
30 BF_SET(AUDIOIN_CTRL, WORD_LENGTH); 33 BF_SET(AUDIOIN_CTRL, WORD_LENGTH);
34 /* Gate Off */
35 BF_SET(AUDIOIN_CTRL, CLKGATE);
31} 36}
32 37
33void imx233_audioin_postinit(void) 38void imx233_audioin_postinit(void)
34{ 39{
35} 40}
36 41
42void imx233_audioin_open(void)
43{
44 /* Gate On */
45 BF_CLR(AUDIOIN_CTRL, CLKGATE);
46 /* Enable ADC clock */
47 BF_CLR(AUDIOIN_ANACLKCTRL, CLKGATE);
48 /* Power up ADC (WARNING audioout register) */
49 BF_CLR(AUDIOOUT_PWRDN, ADC);
50 /* Start ADC */
51 BF_SET(AUDIOIN_CTRL, RUN);
52}
53
37void imx233_audioin_close(void) 54void imx233_audioin_close(void)
38{ 55{
39 /* TODO mute */ 56 /* Stop ADC (doc says it gate off the module but that's not the case) */
40 /* Gate off ADC */
41 BF_SET(AUDIOIN_ANACLKCTRL, CLKGATE);
42 /* will also gate off the module */
43 BF_CLR(AUDIOIN_CTRL, RUN); 57 BF_CLR(AUDIOIN_CTRL, RUN);
58 /* Disable ADC clock */
59 BF_SET(AUDIOIN_ANACLKCTRL, CLKGATE);
60 /* Power down ADC (WARNING audioout register) */
61 BF_SET(AUDIOOUT_PWRDN, ADC);
62 /* Gate Off */
63 BF_SET(AUDIOIN_CTRL, CLKGATE);
64}
65
66static void apply_config(void)
67{
68 int select_l = audioin_select[0];
69 int select_r = audioin_select[1];
70 int vol_l = audioin_vol[0][select_l];
71 int vol_r = audioin_vol[1][select_r];
72 /* Depending on the input, we have three available volumes to tweak:
73 * - adc volume: -100dB -> -0.5dB in 0.5dB steps
74 * - mux gain: 0dB -> 22.5dB in 1.5dB steps
75 * - mic gain: 0dB -> 40dB in 10dB steps (except for 10)
76 *
77 * This means two available volume ranges:
78 * - line1/line2/hp: -100dB -> 22dB in 0.5dB steps
79 * - microphone: -100dB -> 62dB in 0.5dB steps
80 */
81
82 /* First apply mic gain of possible and necessary
83 * Only left volume is relevant with microphone
84 * If gain is > 22dB, use mic gain */
85 if(select_l == AUDIOIN_SELECT_MICROPHONE && vol_l > 22 * 2)
86 {
87 /* take lowest microphone gain to get back into the -100..22 range
88 * achievable with mux+adc.*/
89
90 /* from 52.5 dB and beyond: 40dB gain */
91 if(vol_l > 52 * 2)
92 {
93 BF_WR_V(AUDIOIN_MICLINE, MIC_GAIN, 40dB);
94 vol_l -= 40 * 2;
95 }
96 /* from 42.5 dB to 52dB: 30dB gain */
97 else if(vol_l > 42 * 2)
98 {
99 BF_WR_V(AUDIOIN_MICLINE, MIC_GAIN, 30dB);
100 vol_l -= 30 * 2;
101 }
102 /* from 22.5 dB to 42dB: 20dB gain */
103 else if(vol_l > 22 * 2)
104 {
105 BF_WR_V(AUDIOIN_MICLINE, MIC_GAIN, 20dB);
106 vol_l -= 20 * 2;
107 }
108 /* otherwise 0dB gain */
109 else
110 BF_WR_V(AUDIOIN_MICLINE, MIC_GAIN, 0dB);
111 }
112 /* max is 22dB */
113 vol_l = MIN(vol_l, 44);
114 vol_r = MIN(vol_r, 44);
115 /* we use the mux volume to reach the volume or higher with 1.5dB steps
116 * and then we use the ADC to go below 0dB or to obtain 0.5dB accuracy */
117
118 int mux_vol_l = MAX(0, (vol_l + 2) / 3); /* 1.5dB = 3 * 0.5dB */
119 int mux_vol_r = MAX(0, (vol_r + 2) / 3);
120#if IMX233_SUBTARGET >= 3700
121 unsigned adc_zcd = BM_AUDIOIN_ADCVOL_EN_ADC_ZCD;
122#else
123 unsigned adc_zcd = 0;
124#endif
125 HW_AUDIOIN_ADCVOL = adc_zcd | BF_OR4(AUDIOIN_ADCVOL, SELECT_LEFT(select_l),
126 SELECT_RIGHT(select_r), GAIN_LEFT(mux_vol_l), GAIN_RIGHT(mux_vol_r));
127
128 vol_l -= mux_vol_l * 3; /* mux vol is in 1.5dB = 3 * 0.5dB steps */
129 vol_r -= mux_vol_l * 3;
130 vol_l = MIN(MAX(-200, vol_l), -1);
131 vol_r = MIN(MAX(-200, vol_r), -1);
132
133 /* unmute, enable zero cross and set volume.
134 * 0xfe is -0.5dB */
135 HW_AUDIOIN_ADCVOLUME = BF_OR3(AUDIOIN_ADCVOLUME, EN_ZCD(1),
136 VOLUME_LEFT(0xff + vol_l), VOLUME_RIGHT(0xff + vol_r));
137}
138
139void imx233_audioin_select_mux_input(bool right, int select)
140{
141 audioin_select[right] = select;
142 apply_config();
143}
144
145void imx233_audioin_set_vol(bool right, int vol, int select)
146{
147 audioin_vol[right][select] = vol;
148 apply_config();
149}
150
151void imx233_audioin_enable_mic(bool enable)
152{
153 if(enable)
154 {
155 BF_WR_V(AUDIOIN_MICLINE, MIC_RESISTOR, 2KOhm);
156 BF_WR(AUDIOIN_MICLINE, MIC_BIAS, 4);
157 BF_WR(AUDIOIN_MICLINE, MIC_SELECT, 1);
158 }
159 else
160 BF_WR_V(AUDIOIN_MICLINE, MIC_RESISTOR, Off);
161}
162
163void imx233_audioin_set_freq(int fsel)
164{
165 static struct
166 {
167 int base_mult;
168 int src_hold;
169 int src_int;
170 int src_frac;
171 }dacssr[HW_NUM_FREQ] =
172 {
173 HW_HAVE_8_([HW_FREQ_8] = { 0x1, 0x3, 0x17, 0xe00 } ,)
174 HW_HAVE_11_([HW_FREQ_11] = { 0x1, 0x3, 0x11, 0x37 } ,)
175 HW_HAVE_12_([HW_FREQ_12] = { 0x1, 0x3, 0xf, 0x13ff },)
176 HW_HAVE_16_([HW_FREQ_16] = { 0x1, 0x1, 0x17, 0xe00},)
177 HW_HAVE_22_([HW_FREQ_22] = { 0x1, 0x1, 0x11, 0x37 },)
178 HW_HAVE_24_([HW_FREQ_24] = { 0x1, 0x1, 0xf, 0x13ff },)
179 HW_HAVE_32_([HW_FREQ_32] = { 0x1, 0x0, 0x17, 0xe00},)
180 HW_HAVE_44_([HW_FREQ_44] = { 0x1, 0x0, 0x11, 0x37 },)
181 HW_HAVE_48_([HW_FREQ_48] = { 0x1, 0x0, 0xf, 0x13ff },)
182 HW_HAVE_64_([HW_FREQ_64] = { 0x2, 0x0, 0x17, 0xe00},)
183 HW_HAVE_88_([HW_FREQ_88] = { 0x2, 0x0, 0x11, 0x37 },)
184 HW_HAVE_96_([HW_FREQ_96] = { 0x2, 0x0, 0xf, 0x13ff },)
185 };
186
187 HW_AUDIOIN_ADCSRR = BF_OR4(AUDIOIN_ADCSRR,
188 SRC_FRAC(dacssr[fsel].src_frac), SRC_INT(dacssr[fsel].src_int),
189 SRC_HOLD(dacssr[fsel].src_hold), BASEMULT(dacssr[fsel].base_mult));
44} 190}
diff --git a/firmware/target/arm/imx233/audioin-imx233.h b/firmware/target/arm/imx233/audioin-imx233.h
index e8c5b36d6d..a36cbf6e1a 100644
--- a/firmware/target/arm/imx233/audioin-imx233.h
+++ b/firmware/target/arm/imx233/audioin-imx233.h
@@ -26,9 +26,25 @@
26#include "system.h" 26#include "system.h"
27 27
28#include "regs/regs-audioin.h" 28#include "regs/regs-audioin.h"
29/* some audioout registers impact audioin */
30#include "regs/regs-audioout.h"
31
32#define AUDIOIN_SELECT_MICROPHONE 0
33#define AUDIOIN_SELECT_LINE1 1
34#define AUDIOIN_SELECT_HEADPHONE 2
35#define AUDIOIN_SELECT_LINE2 3
29 36
30void imx233_audioin_preinit(void); 37void imx233_audioin_preinit(void);
31void imx233_audioin_postinit(void); 38void imx233_audioin_postinit(void);
39void imx233_audioin_open(void);
32void imx233_audioin_close(void); 40void imx233_audioin_close(void);
41/* use AUDIONIN_SELECT_* values */
42void imx233_audioin_select_mux_input(bool right, int select);
43/* volume in half dB */
44void imx233_audioin_set_vol(bool right, int vol, int select);
45/* frequency index, NOT the frequency itself */
46void imx233_audioin_set_freq(int fsel);
47/* enable microphone */
48void imx233_audioin_enable_mic(bool enable);
33 49
34#endif /* __audioin_imx233__ */ 50#endif /* __audioin_imx233__ */