1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
27 /* Register addresses as per datasheet Rev.4.4 */
35 #define SRATECTRL 0x07
37 #define JACKDETECT0 0x09
41 #define JACKDETECT1 0x0d
51 #define EQ_GAIN_MASK 0x001f
52 #define EQ_CUTOFF_MASK 0x0060
53 #define EQ_GAIN_VALUE(x) (((-x) + 12) & 0x1f)
54 #define EQ_CUTOFF_VALUE(x) ((((x) - 1) & 0x03) << 5)
56 #define CLASSDCTL 0x17
57 #define DACLIMIT1 0x18
58 #define DACLIMIT2 0x19
66 #define NOISEGATE 0x23
71 #define THREEDCTL 0x29
75 #define LINPGAGAIN 0x2d
76 #define RINPGAGAIN 0x2e
77 #define LADCBOOST 0x2f
78 #define RADCBOOST 0x30
90 const struct sound_settings_info audiohw_settings
[] = {
91 [SOUND_VOLUME
] = {"dB", 0, 1, -58, 6, -25},
92 [SOUND_BASS
] = {"dB", 0, 1, -12, 12, 0},
93 [SOUND_TREBLE
] = {"dB", 0, 1, -12, 12, 0},
94 [SOUND_BALANCE
] = {"%", 0, 1,-100, 100, 0},
95 [SOUND_CHANNELS
] = {"", 0, 1, 0, 5, 0},
96 [SOUND_STEREO_WIDTH
] = {"%", 0, 5, 0, 250, 100},
98 [SOUND_LEFT_GAIN
] = {"dB", 1, 1,-128, 96, 0},
99 [SOUND_RIGHT_GAIN
] = {"dB", 1, 1,-128, 96, 0},
100 [SOUND_MIC_GAIN
] = {"dB", 1, 1,-128, 108, 16},
102 #ifdef AUDIOHW_HAVE_BASS_CUTOFF
103 [SOUND_BASS_CUTOFF
] = {"", 0, 1, 1, 4, 1},
105 #ifdef AUDIOHW_HAVE_TREBLE_CUTOFF
106 [SOUND_TREBLE_CUTOFF
] = {"", 0, 1, 1, 4, 1},
110 /* shadow registers */
111 unsigned int eq1_reg
;
112 unsigned int eq5_reg
;
114 /* convert tenth of dB volume (-57..6) to master volume register value */
115 int tenthdb2master(int db
)
117 /* +6 to -57dB in 1dB steps == 64 levels = 6 bits */
118 /* 0111111 == +6dB (0x3f) = 63) */
119 /* 0111001 == 0dB (0x39) = 57) */
120 /* 0000001 == -56dB (0x01) = */
121 /* 0000000 == -57dB (0x00) */
123 /* 1000000 == Mute (0x40) */
125 if (db
< VOLUME_MIN
) {
132 /* Silently enable / disable audio output */
133 void audiohw_preinit(void)
135 wmcodec_write(RESET
, 0x1ff); /* Reset */
137 wmcodec_write(BIASCTL
, 0x100); /* BIASCUT = 1 */
138 wmcodec_write(OUTCTRL
, 0x6); /* Thermal shutdown */
140 wmcodec_write(PWRMGMT1
, 0x8); /* BIASEN = 1 */
142 /* Volume zero, mute all outputs */
143 wmcodec_write(LOUT1VOL
, 0x140);
144 wmcodec_write(ROUT1VOL
, 0x140);
145 wmcodec_write(LOUT2VOL
, 0x140);
146 wmcodec_write(ROUT2VOL
, 0x140);
147 wmcodec_write(OUT3MIX
, 0x40);
148 wmcodec_write(OUT4MIX
, 0x40);
150 /* DAC softmute, automute, 128OSR */
151 wmcodec_write(DACCTRL
, 0x4c);
153 wmcodec_write(OUT4ADC
, 0x2); /* POBCTRL = 1 */
155 /* Enable output, DAC and mixer */
156 wmcodec_write(PWRMGMT3
, 0x6f);
157 wmcodec_write(PWRMGMT2
, 0x180);
158 wmcodec_write(PWRMGMT1
, 0xd);
159 wmcodec_write(LOUTMIX
, 0x1);
160 wmcodec_write(ROUTMIX
, 0x1);
162 /* Disable clock since we're acting as slave to the SoC */
163 wmcodec_write(CLKGEN
, 0x0);
164 wmcodec_write(AINTFCE
, 0x10); /* 16-bit, I2S format */
166 wmcodec_write(LDACVOL
, 0x1ff); /* Full DAC digital vol */
167 wmcodec_write(RDACVOL
, 0x1ff);
169 wmcodec_write(OUT4ADC
, 0x0); /* POBCTRL = 0 */
172 static void audiohw_mute(bool mute
)
176 /* Set DACMU = 1 to soft-mute the audio DACs. */
177 wmcodec_write(DACCTRL
, 0x4c);
179 /* Set DACMU = 0 to soft-un-mute the audio DACs. */
180 wmcodec_write(DACCTRL
, 0xc);
184 void audiohw_postinit(void)
191 void audiohw_set_headphone_vol(int vol_l
, int vol_r
)
194 wmcodec_write(LOUT1VOL
, 0x080 | vol_l
);
195 wmcodec_write(ROUT1VOL
, 0x180 | vol_r
);
198 void audiohw_set_lineout_vol(int vol_l
, int vol_r
)
201 wmcodec_write(LOUT2VOL
, vol_l
);
202 wmcodec_write(ROUT2VOL
, 0x100 | vol_r
);
205 void audiohw_set_aux_vol(int vol_l
, int vol_r
)
208 wmcodec_write(LOUTMIX
, 0x111 | (vol_l
<< 5) );
209 wmcodec_write(ROUTMIX
, 0x111 | (vol_r
<< 5) );
212 void audiohw_set_bass(int value
)
214 eq1_reg
= (eq1_reg
& ~EQ_GAIN_MASK
) | EQ_GAIN_VALUE(value
);
215 wmcodec_write(EQ1
, 0x100 | eq1_reg
);
218 void audiohw_set_bass_cutoff(int value
)
220 eq1_reg
= (eq1_reg
& ~EQ_CUTOFF_MASK
) | EQ_CUTOFF_VALUE(value
);
221 wmcodec_write(EQ1
, 0x100 | eq1_reg
);
224 void audiohw_set_treble(int value
)
226 eq5_reg
= (eq5_reg
& ~EQ_GAIN_MASK
) | EQ_GAIN_VALUE(value
);
227 wmcodec_write(EQ5
, eq5_reg
);
230 void audiohw_set_treble_cutoff(int value
)
232 eq5_reg
= (eq5_reg
& ~EQ_CUTOFF_MASK
) | EQ_CUTOFF_VALUE(value
);
233 wmcodec_write(EQ5
, eq5_reg
);
236 /* Nice shutdown of WM8985 codec */
237 void audiohw_close(void)
241 wmcodec_write(PWRMGMT3
, 0x0);
243 wmcodec_write(PWRMGMT1
, 0x0);
245 wmcodec_write(PWRMGMT2
, 0x40);
248 /* Note: Disable output before calling this function */
249 void audiohw_set_sample_rate(int fsel
)
251 /* Currently the WM8985 acts as slave to the SoC I2S controller, so no
252 setup is needed here. This seems to be in contrast to every other WM
253 driver in Rockbox, so this may need to change in the future. */
257 #ifdef HAVE_RECORDING
258 void audiohw_enable_recording(bool source_mic
)
260 (void)source_mic
; /* We only have a line-in (I think) */
262 wmcodec_write(RESET
, 0x1ff); /*Reset*/
264 wmcodec_write(PWRMGMT1
, 0x2b);
265 wmcodec_write(PWRMGMT2
, 0x18f); /* Enable ADC - 0x0c enables left/right PGA input, and 0x03 turns on power to the ADCs */
266 wmcodec_write(PWRMGMT3
, 0x6f);
268 wmcodec_write(AINTFCE
, 0x10);
269 wmcodec_write(CLKCTRL
, 0x49);
271 wmcodec_write(OUTCTRL
, 1);
273 /* The iPod can handle multiple frequencies, but fix at 44.1KHz
275 audiohw_set_frequency(HW_FREQ_DEFAULT
);
277 wmcodec_write(INCTRL
,0x44); /* Connect L2 and R2 inputs */
279 /* Set L2/R2_2BOOSTVOL to 0db (bits 4-6) */
289 wmcodec_write(LADCBOOST
,0x50);
290 wmcodec_write(RADCBOOST
,0x50);
292 /* Set L/R input PGA Volume to 0db */
293 // wm8758_write(LINPGAVOL,0x3f);
294 // wm8758_write(RINPGAVOL,0x13f);
296 /* Enable monitoring */
297 wmcodec_write(LOUTMIX
,0x17); /* Enable output mixer - BYPL2LMIX @ 0db*/
298 wmcodec_write(ROUTMIX
,0x17); /* Enable output mixer - BYPR2RMIX @ 0db*/
303 void audiohw_disable_recording(void) {
306 wmcodec_write(PWRMGMT3
, 0x0);
308 wmcodec_write(PWRMGMT1
, 0x0);
310 wmcodec_write(PWRMGMT2
, 0x40);
313 void audiohw_set_recvol(int left
, int right
, int type
) {
320 void audiohw_set_monitor(bool enable
) {
324 #endif /* HAVE_RECORDING */