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 [SOUND_BASS_CUTOFF
] = {"", 0, 1, 1, 4, 1},
103 [SOUND_TREBLE_CUTOFF
] = {"", 0, 1, 1, 4, 1},
106 /* shadow registers */
107 unsigned int eq1_reg
;
108 unsigned int eq5_reg
;
110 /* convert tenth of dB volume (-57..6) to master volume register value */
111 int tenthdb2master(int db
)
113 /* +6 to -57dB in 1dB steps == 64 levels = 6 bits */
114 /* 0111111 == +6dB (0x3f) = 63) */
115 /* 0111001 == 0dB (0x39) = 57) */
116 /* 0000001 == -56dB (0x01) = */
117 /* 0000000 == -57dB (0x00) */
119 /* 1000000 == Mute (0x40) */
121 if (db
< VOLUME_MIN
) {
128 /* Silently enable / disable audio output */
129 void audiohw_preinit(void)
131 wmcodec_write(RESET
, 0x1ff); /* Reset */
133 wmcodec_write(BIASCTL
, 0x100); /* BIASCUT = 1 */
134 wmcodec_write(OUTCTRL
, 0x6); /* Thermal shutdown */
136 wmcodec_write(PWRMGMT1
, 0x8); /* BIASEN = 1 */
138 /* Volume zero, mute all outputs */
139 wmcodec_write(LOUT1VOL
, 0x140);
140 wmcodec_write(ROUT1VOL
, 0x140);
141 wmcodec_write(LOUT2VOL
, 0x140);
142 wmcodec_write(ROUT2VOL
, 0x140);
143 wmcodec_write(OUT3MIX
, 0x40);
144 wmcodec_write(OUT4MIX
, 0x40);
146 /* DAC softmute, automute, 128OSR */
147 wmcodec_write(DACCTRL
, 0x4c);
149 wmcodec_write(OUT4ADC
, 0x2); /* POBCTRL = 1 */
151 /* Enable output, DAC and mixer */
152 wmcodec_write(PWRMGMT3
, 0x6f);
153 wmcodec_write(PWRMGMT2
, 0x180);
154 wmcodec_write(PWRMGMT1
, 0xd);
155 wmcodec_write(LOUTMIX
, 0x1);
156 wmcodec_write(ROUTMIX
, 0x1);
158 /* Disable clock since we're acting as slave to the SoC */
159 wmcodec_write(CLKGEN
, 0x0);
160 wmcodec_write(AINTFCE
, 0x10); /* 16-bit, I2S format */
162 wmcodec_write(LDACVOL
, 0x1ff); /* Full DAC digital vol */
163 wmcodec_write(RDACVOL
, 0x1ff);
165 wmcodec_write(OUT4ADC
, 0x0); /* POBCTRL = 0 */
168 void audiohw_postinit(void)
175 void audiohw_set_headphone_vol(int vol_l
, int vol_r
)
178 wmcodec_write(LOUT1VOL
, 0x080 | vol_l
);
179 wmcodec_write(ROUT1VOL
, 0x180 | vol_r
);
182 void audiohw_set_lineout_vol(int vol_l
, int vol_r
)
185 wmcodec_write(LOUT2VOL
, vol_l
);
186 wmcodec_write(ROUT2VOL
, 0x100 | vol_r
);
189 void audiohw_set_aux_vol(int vol_l
, int vol_r
)
192 wmcodec_write(LOUTMIX
, 0x111 | (vol_l
<< 5) );
193 wmcodec_write(ROUTMIX
, 0x111 | (vol_r
<< 5) );
196 void audiohw_set_bass(int value
)
198 eq1_reg
= (eq1_reg
& ~EQ_GAIN_MASK
) | EQ_GAIN_VALUE(value
);
199 wmcodec_write(EQ1
, 0x100 | eq1_reg
);
202 void audiohw_set_bass_cutoff(int value
)
204 eq1_reg
= (eq1_reg
& ~EQ_CUTOFF_MASK
) | EQ_CUTOFF_VALUE(value
);
205 wmcodec_write(EQ1
, 0x100 | eq1_reg
);
208 void audiohw_set_treble(int value
)
210 eq5_reg
= (eq5_reg
& ~EQ_GAIN_MASK
) | EQ_GAIN_VALUE(value
);
211 wmcodec_write(EQ5
, eq5_reg
);
214 void audiohw_set_treble_cutoff(int value
)
216 eq5_reg
= (eq5_reg
& ~EQ_CUTOFF_MASK
) | EQ_CUTOFF_VALUE(value
);
217 wmcodec_write(EQ5
, eq5_reg
);
220 void audiohw_mute(bool mute
)
224 /* Set DACMU = 1 to soft-mute the audio DACs. */
225 wmcodec_write(DACCTRL
, 0x4c);
227 /* Set DACMU = 0 to soft-un-mute the audio DACs. */
228 wmcodec_write(DACCTRL
, 0xc);
232 /* Nice shutdown of WM8985 codec */
233 void audiohw_close(void)
237 wmcodec_write(PWRMGMT3
, 0x0);
239 wmcodec_write(PWRMGMT1
, 0x0);
241 wmcodec_write(PWRMGMT2
, 0x40);
244 /* Note: Disable output before calling this function */
245 void audiohw_set_sample_rate(int fsel
)
247 /* Currently the WM8985 acts as slave to the SoC I2S controller, so no
248 setup is needed here. This seems to be in contrast to every other WM
249 driver in Rockbox, so this may need to change in the future. */
253 #ifdef HAVE_RECORDING
254 void audiohw_enable_recording(bool source_mic
)
256 (void)source_mic
; /* We only have a line-in (I think) */
258 wmcodec_write(RESET
, 0x1ff); /*Reset*/
260 wmcodec_write(PWRMGMT1
, 0x2b);
261 wmcodec_write(PWRMGMT2
, 0x18f); /* Enable ADC - 0x0c enables left/right PGA input, and 0x03 turns on power to the ADCs */
262 wmcodec_write(PWRMGMT3
, 0x6f);
264 wmcodec_write(AINTFCE
, 0x10);
265 wmcodec_write(CLKCTRL
, 0x49);
267 wmcodec_write(OUTCTRL
, 1);
269 /* The iPod can handle multiple frequencies, but fix at 44.1KHz
271 audiohw_set_frequency(HW_FREQ_DEFAULT
);
273 wmcodec_write(INCTRL
,0x44); /* Connect L2 and R2 inputs */
275 /* Set L2/R2_2BOOSTVOL to 0db (bits 4-6) */
285 wmcodec_write(LADCBOOST
,0x50);
286 wmcodec_write(RADCBOOST
,0x50);
288 /* Set L/R input PGA Volume to 0db */
289 // wm8758_write(LINPGAVOL,0x3f);
290 // wm8758_write(RINPGAVOL,0x13f);
292 /* Enable monitoring */
293 wmcodec_write(LOUTMIX
,0x17); /* Enable output mixer - BYPL2LMIX @ 0db*/
294 wmcodec_write(ROUTMIX
,0x17); /* Enable output mixer - BYPR2RMIX @ 0db*/
299 void audiohw_disable_recording(void) {
302 wmcodec_write(PWRMGMT3
, 0x0);
304 wmcodec_write(PWRMGMT1
, 0x0);
306 wmcodec_write(PWRMGMT2
, 0x40);
309 void audiohw_set_recvol(int left
, int right
, int type
) {
316 void audiohw_set_monitor(bool enable
) {
320 #endif /* HAVE_RECORDING */