1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * All files in this archive are subject to the GNU General Public License.
11 * See the file COPYING in the source tree root for full license agreement.
13 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
14 * KIND, either express or implied.
16 ****************************************************************************/
26 /* Register addresses as per datasheet Rev.4.4 */
34 #define SRATECTRL 0x07
36 #define JACKDETECT0 0x09
40 #define JACKDETECT1 0x0d
50 #define EQ_GAIN_MASK 0x001f
51 #define EQ_CUTOFF_MASK 0x0060
52 #define EQ_GAIN_VALUE(x) (((-x) + 12) & 0x1f)
53 #define EQ_CUTOFF_VALUE(x) ((((x) - 1) & 0x03) << 5)
55 #define CLASSDCTL 0x17
56 #define DACLIMIT1 0x18
57 #define DACLIMIT2 0x19
65 #define NOISEGATE 0x23
70 #define THREEDCTL 0x29
74 #define LINPGAGAIN 0x2d
75 #define RINPGAGAIN 0x2e
76 #define LADCBOOST 0x2f
77 #define RADCBOOST 0x30
89 const struct sound_settings_info audiohw_settings
[] = {
90 [SOUND_VOLUME
] = {"dB", 0, 1, -58, 6, -25},
91 [SOUND_BASS
] = {"dB", 0, 1, -12, 12, 0},
92 [SOUND_TREBLE
] = {"dB", 0, 1, -12, 12, 0},
93 [SOUND_BALANCE
] = {"%", 0, 1,-100, 100, 0},
94 [SOUND_CHANNELS
] = {"", 0, 1, 0, 5, 0},
95 [SOUND_STEREO_WIDTH
] = {"%", 0, 5, 0, 250, 100},
97 [SOUND_LEFT_GAIN
] = {"dB", 1, 1,-128, 96, 0},
98 [SOUND_RIGHT_GAIN
] = {"dB", 1, 1,-128, 96, 0},
99 [SOUND_MIC_GAIN
] = {"dB", 1, 1,-128, 108, 16},
101 [SOUND_BASS_CUTOFF
] = {"", 0, 1, 1, 4, 1},
102 [SOUND_TREBLE_CUTOFF
] = {"", 0, 1, 1, 4, 1},
105 /* shadow registers */
106 unsigned int eq1_reg
;
107 unsigned int eq5_reg
;
109 /* convert tenth of dB volume (-57..6) to master volume register value */
110 int tenthdb2master(int db
)
112 /* +6 to -57dB in 1dB steps == 64 levels = 6 bits */
113 /* 0111111 == +6dB (0x3f) = 63) */
114 /* 0111001 == 0dB (0x39) = 57) */
115 /* 0000001 == -56dB (0x01) = */
116 /* 0000000 == -57dB (0x00) */
118 /* 1000000 == Mute (0x40) */
120 if (db
< VOLUME_MIN
) {
127 /* Silently enable / disable audio output */
128 void audiohw_enable_output(bool enable
)
132 /* TODO: reset the I2S controller into known state */
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 */
181 void audiohw_set_headphone_vol(int vol_l
, int vol_r
)
184 wmcodec_write(LOUT1VOL
, 0x080 | vol_l
);
185 wmcodec_write(ROUT1VOL
, 0x180 | vol_r
);
188 void audiohw_set_lineout_vol(int vol_l
, int vol_r
)
191 wmcodec_write(LOUT2VOL
, vol_l
);
192 wmcodec_write(ROUT2VOL
, 0x100 | vol_r
);
195 void audiohw_set_bass(int value
)
197 eq1_reg
= (eq1_reg
& ~EQ_GAIN_MASK
) | EQ_GAIN_VALUE(value
);
198 wmcodec_write(EQ1
, 0x100 | eq1_reg
);
201 void audiohw_set_bass_cutoff(int value
)
203 eq1_reg
= (eq1_reg
& ~EQ_CUTOFF_MASK
) | EQ_CUTOFF_VALUE(value
);
204 wmcodec_write(EQ1
, 0x100 | eq1_reg
);
207 void audiohw_set_treble(int value
)
209 eq5_reg
= (eq5_reg
& ~EQ_GAIN_MASK
) | EQ_GAIN_VALUE(value
);
210 wmcodec_write(EQ5
, eq5_reg
);
213 void audiohw_set_treble_cutoff(int value
)
215 eq5_reg
= (eq5_reg
& ~EQ_CUTOFF_MASK
) | EQ_CUTOFF_VALUE(value
);
216 wmcodec_write(EQ5
, eq5_reg
);
219 void audiohw_mute(bool mute
)
223 /* Set DACMU = 1 to soft-mute the audio DACs. */
224 wmcodec_write(DACCTRL
, 0x4c);
226 /* Set DACMU = 0 to soft-un-mute the audio DACs. */
227 wmcodec_write(DACCTRL
, 0xc);
231 /* Nice shutdown of WM8985 codec */
232 void audiohw_close(void)
236 wmcodec_write(PWRMGMT3
, 0x0);
238 wmcodec_write(PWRMGMT1
, 0x0);
240 wmcodec_write(PWRMGMT2
, 0x40);
243 /* Note: Disable output before calling this function */
244 void audiohw_set_sample_rate(int sampling_control
)
246 /* Currently the WM8985 acts as slave to the SoC I2S controller, so no
247 setup is needed here. This seems to be in contrast to every other WM
248 driver in Rockbox, so this may need to change in the future. */
249 (void)sampling_control
;
252 #ifdef HAVE_RECORDING
253 void audiohw_enable_recording(bool source_mic
)
255 (void)source_mic
; /* We only have a line-in (I think) */
257 /* TODO: reset the I2S controller into known state */
260 wmcodec_write(RESET
, 0x1ff); /*Reset*/
262 wmcodec_write(PWRMGMT1
, 0x2b);
263 wmcodec_write(PWRMGMT2
, 0x18f); /* Enable ADC - 0x0c enables left/right PGA input, and 0x03 turns on power to the ADCs */
264 wmcodec_write(PWRMGMT3
, 0x6f);
266 wmcodec_write(AINTFCE
, 0x10);
267 wmcodec_write(CLKCTRL
, 0x49);
269 wmcodec_write(OUTCTRL
, 1);
271 /* The iPod can handle multiple frequencies, but fix at 44.1KHz
273 audiohw_set_sample_rate(WM8985_44100HZ
);
275 wmcodec_write(INCTRL
,0x44); /* Connect L2 and R2 inputs */
277 /* Set L2/R2_2BOOSTVOL to 0db (bits 4-6) */
287 wmcodec_write(LADCBOOST
,0x50);
288 wmcodec_write(RADCBOOST
,0x50);
290 /* Set L/R input PGA Volume to 0db */
291 // wm8758_write(LINPGAVOL,0x3f);
292 // wm8758_write(RINPGAVOL,0x13f);
294 /* Enable monitoring */
295 wmcodec_write(LOUTMIX
,0x17); /* Enable output mixer - BYPL2LMIX @ 0db*/
296 wmcodec_write(ROUTMIX
,0x17); /* Enable output mixer - BYPR2RMIX @ 0db*/
301 void audiohw_disable_recording(void) {
304 wmcodec_write(PWRMGMT3
, 0x0);
306 wmcodec_write(PWRMGMT1
, 0x0);
308 wmcodec_write(PWRMGMT2
, 0x40);
311 void audiohw_set_recvol(int left
, int right
, int type
) {
318 void audiohw_set_monitor(bool enable
) {
322 #endif /* HAVE_RECORDING */