Remove pcm_mute() which has been unused since r19308
[kugel-rb.git] / firmware / drivers / audio / wm8731.c
blobe50079a18d3a8d65ab44ac0b588295c4f05bf85f
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Driver for WM8711/WM8721/WM8731 audio codecs
12 * Based on code from the ipodlinux project - http://ipodlinux.org/
13 * Adapted for Rockbox in January 2006
15 * Original file: linux/arch/armnommu/mach-ipod/audio.c
17 * Copyright (c) 2003-2005 Bernard Leach (leachbj@bouncycastle.org)
19 * This program is free software; you can redistribute it and/or
20 * modify it under the terms of the GNU General Public License
21 * as published by the Free Software Foundation; either version 2
22 * of the License, or (at your option) any later version.
24 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
25 * KIND, either express or implied.
27 ****************************************************************************/
28 #include "config.h"
29 #include "logf.h"
30 #include "system.h"
31 #include "string.h"
33 #include "pcm_sampr.h"
35 #include "audio.h"
37 #include "wmcodec.h"
38 #include "audiohw.h"
39 #include "sound.h"
42 const struct sound_settings_info audiohw_settings[] = {
43 [SOUND_VOLUME] = {"dB", 0, 1, -74, 6, -25},
44 /* HAVE_SW_TONE_CONTROLS */
45 [SOUND_BASS] = {"dB", 0, 1, -24, 24, 0},
46 [SOUND_TREBLE] = {"dB", 0, 1, -24, 24, 0},
47 [SOUND_BALANCE] = {"%", 0, 1,-100, 100, 0},
48 [SOUND_CHANNELS] = {"", 0, 1, 0, 5, 0},
49 [SOUND_STEREO_WIDTH] = {"%", 0, 5, 0, 250, 100},
50 #if defined(HAVE_WM8731) && defined(HAVE_RECORDING)
51 [SOUND_LEFT_GAIN] = {"dB", 1, 1, 0, 31, 23},
52 [SOUND_RIGHT_GAIN] = {"dB", 1, 1, 0, 31, 23},
53 [SOUND_MIC_GAIN] = {"dB", 1, 1, 0, 1, 0},
54 #endif
57 /* Init values/shadows
58 * Ignore bit 8 since that only specifies "both" for updating
59 * gains - "RESET" (15h) not included */
60 static unsigned char wmc_regs[WMC_NUM_REGS] =
62 #ifdef HAVE_WM8731
63 [LINVOL] = LINVOL_DEFAULT,
64 [RINVOL] = RINVOL_DEFAULT,
65 #endif
66 [LOUTVOL] = LOUTVOL_DEFAULT | WMC_OUT_ZCEN,
67 [ROUTVOL] = LOUTVOL_DEFAULT | WMC_OUT_ZCEN,
68 #if defined(HAVE_WM8711) || defined(HAVE_WM8731)
69 /* BYPASS on by default - OFF until needed */
70 [AAPCTRL] = AAPCTRL_DEFAULT & ~AAPCTRL_BYPASS,
71 /* CLKOUT and OSC on by default - OFF unless needed by a target */
72 [PDCTRL] = PDCTRL_DEFAULT | PDCTRL_CLKOUTPD | PDCTRL_OSCPD,
73 #elif defined(HAVE_WM8721)
74 /* No BYPASS */
75 [AAPCTRL] = AAPCTRL_DEFAULT,
76 /* No CLKOUT or OSC */
77 [PDCTRL] = PDCTRL_DEFAULT,
78 #endif
79 [DAPCTRL] = DAPCTRL_DEFAULT,
80 #ifndef CODEC_SLAVE
81 [AINTFCE] = AINTFCE_FORMAT_I2S | AINTFCE_IWL_16BIT | AINTFCE_MS,
82 #else
83 [AINTFCE] = AINTFCE_FORMAT_I2S | AINTFCE_IWL_16BIT,
84 #endif
85 [SAMPCTRL] = SAMPCTRL_DEFAULT,
86 [ACTIVECTRL] = ACTIVECTRL_DEFAULT,
89 static void wmc_write(int reg, unsigned val)
91 if ((unsigned)reg >= WMC_NUM_REGS)
92 return;
94 wmc_regs[reg] = (unsigned char)val;
95 wmcodec_write(reg, val);
98 static void wmc_set(int reg, unsigned bits)
100 wmc_write(reg, wmc_regs[reg] | bits);
103 static void wmc_clear(int reg, unsigned bits)
105 wmc_write(reg, wmc_regs[reg] & ~bits);
108 static void wmc_write_masked(int reg, unsigned bits, unsigned mask)
110 wmc_write(reg, (wmc_regs[reg] & ~mask) | (bits & mask));
113 /* convert tenth of dB volume (-730..60) to master volume register value */
114 int tenthdb2master(int db)
116 /* +6 to -73dB 1dB steps (plus mute == 80levels) 7bits */
117 /* 1111111 == +6dB (0x7f) */
118 /* 1111001 == 0dB (0x79) */
119 /* 0110000 == -73dB (0x30 */
120 /* 0101111 == mute (0x2f) */
122 if (db < VOLUME_MIN) {
123 return 0x2f;
124 } else {
125 return((db/10)+0x30+73);
129 int sound_val2phys(int setting, int value)
131 int result;
133 switch(setting)
135 #ifdef HAVE_RECORDING
136 case SOUND_LEFT_GAIN:
137 case SOUND_RIGHT_GAIN:
138 result = (value - 23) * 15;
139 break;
140 case SOUND_MIC_GAIN:
141 result = value * 200;
142 break;
143 #endif
144 default:
145 result = value;
146 break;
149 return result;
152 static void audiohw_mute(bool mute)
154 if (mute) {
155 /* Set DACMU = 1 to soft-mute the audio DACs. */
156 wmc_set(DAPCTRL, DAPCTRL_DACMU);
157 } else {
158 /* Set DACMU = 0 to soft-un-mute the audio DACs. */
159 wmc_clear(DAPCTRL, DAPCTRL_DACMU);
163 static void codec_set_active(int active)
165 /* set active to 0x0 or 0x1 */
166 wmc_write(ACTIVECTRL, active ? ACTIVECTRL_ACTIVE : 0);
169 void audiohw_preinit(void)
171 /* POWER UP SEQUENCE */
172 /* 1) Switch on power supplies. By default the WM codec is in Standby Mode,
173 * the DAC is digitally muted and the Audio Interface and Outputs are
174 * all OFF. */
175 wmcodec_write(RESET, RESET_RESET);
177 /* 2) Set all required bits in the Power Down register (0Ch) to '0';
178 * EXCEPT the OUTPD bit, this should be set to '1' (Default). */
179 wmc_clear(PDCTRL, PDCTRL_DACPD | PDCTRL_POWEROFF);
181 /* 3) Set required values in all other registers except 12h (Active). */
182 wmc_set(AINTFCE, 0); /* Set no bits - write init/shadow value */
184 wmc_set(AAPCTRL, AAPCTRL_DACSEL);
185 wmc_write(SAMPCTRL, WMC_USB24_44100HZ);
187 /* 4) Set the 'Active' bit in register 12h. */
188 codec_set_active(true);
190 /* 5) The last write of the sequence should be setting OUTPD to '0'
191 * (active) in register 0Ch, enabling the DAC signal path, free
192 * of any significant power-up noise. */
193 wmc_clear(PDCTRL, PDCTRL_OUTPD);
196 void audiohw_postinit(void)
198 sleep(HZ);
200 audiohw_mute(false);
202 #if defined(IRIVER_H10) || defined(IRIVER_H10_5GB)
203 /* We need to enable bit 4 of GPIOL for output for sound on H10 */
204 GPIO_SET_BITWISE(GPIOL_OUTPUT_VAL, 0x10);
205 #elif defined(PHILIPS_HDD1630)
206 GPO32_ENABLE |= 0x2;
207 GPO32_VAL &= ~0x2;
208 #endif
211 void audiohw_set_master_vol(int vol_l, int vol_r)
213 /* +6 to -73dB 1dB steps (plus mute == 80levels) 7bits */
214 /* 1111111 == +6dB */
215 /* 1111001 == 0dB */
216 /* 0110000 == -73dB */
217 /* 0101111 == mute (0x2f) */
218 wmc_write_masked(LOUTVOL, vol_l, WMC_OUT_VOL_MASK);
219 wmc_write_masked(ROUTVOL, vol_r, WMC_OUT_VOL_MASK);
222 /* Nice shutdown of WM codec */
223 void audiohw_close(void)
225 /* POWER DOWN SEQUENCE */
226 /* 1) Set the OUTPD bit to '1' (power down). */
227 wmc_set(PDCTRL, PDCTRL_OUTPD);
228 /* 2) Remove the WM codec supplies. */
231 void audiohw_set_frequency(int fsel)
233 /* For 24MHz MCLK */
234 static const unsigned char srctrl_table[HW_NUM_FREQ] =
236 HW_HAVE_8_([HW_FREQ_8] = WMC_USB24_8000HZ,)
237 HW_HAVE_32_([HW_FREQ_32] = WMC_USB24_32000HZ,)
238 HW_HAVE_44_([HW_FREQ_44] = WMC_USB24_44100HZ,)
239 HW_HAVE_48_([HW_FREQ_48] = WMC_USB24_48000HZ,)
240 HW_HAVE_88_([HW_FREQ_88] = WMC_USB24_88200HZ,)
241 HW_HAVE_96_([HW_FREQ_96] = WMC_USB24_96000HZ,)
244 if ((unsigned)fsel >= HW_NUM_FREQ)
245 fsel = HW_FREQ_DEFAULT;
247 codec_set_active(false);
248 wmc_write(SAMPCTRL, srctrl_table[fsel]);
249 codec_set_active(true);
252 #if defined(HAVE_WM8731) && defined(HAVE_RECORDING)
253 /* WM8731 only */
254 void audiohw_enable_recording(bool source_mic)
256 /* NOTE: When switching to digital monitoring we will not want
257 * the DAC disabled. */
259 codec_set_active(false);
261 if (source_mic) {
262 wmc_set(LINVOL, WMC_IN_MUTE);
263 wmc_set(RINVOL, WMC_IN_MUTE);
265 wmc_write_masked(PDCTRL, PDCTRL_LINEINPD | PDCTRL_DACPD,
266 PDCTRL_LINEINPD | PDCTRL_MICPD |
267 PDCTRL_ADCPD | PDCTRL_DACPD);
268 wmc_write_masked(AAPCTRL, AAPCTRL_INSEL | AAPCTRL_SIDETONE,
269 AAPCTRL_MUTEMIC | AAPCTRL_INSEL |
270 AAPCTRL_BYPASS | AAPCTRL_DACSEL |
271 AAPCTRL_SIDETONE);
272 } else {
273 wmc_write_masked(PDCTRL, PDCTRL_MICPD | PDCTRL_DACPD,
274 PDCTRL_LINEINPD | PDCTRL_MICPD |
275 PDCTRL_ADCPD | PDCTRL_DACPD);
276 wmc_write_masked(AAPCTRL, AAPCTRL_MUTEMIC | AAPCTRL_BYPASS,
277 AAPCTRL_MUTEMIC | AAPCTRL_INSEL |
278 AAPCTRL_BYPASS | AAPCTRL_DACSEL |
279 AAPCTRL_SIDETONE);
281 wmc_clear(LINVOL, WMC_IN_MUTE);
282 wmc_clear(RINVOL, WMC_IN_MUTE);
285 codec_set_active(true);
288 void audiohw_disable_recording(void)
290 codec_set_active(false);
292 /* Mute line inputs */
293 wmc_set(LINVOL, WMC_IN_MUTE);
294 wmc_set(RINVOL, WMC_IN_MUTE);
295 wmc_set(AAPCTRL, AAPCTRL_MUTEMIC);
297 /* Turn off input analog audio paths */
298 wmc_clear(AAPCTRL, AAPCTRL_BYPASS | AAPCTRL_SIDETONE);
300 /* Set power config */
301 wmc_write_masked(PDCTRL,
302 PDCTRL_LINEINPD | PDCTRL_MICPD | PDCTRL_ADCPD,
303 PDCTRL_LINEINPD | PDCTRL_MICPD | PDCTRL_DACPD |
304 PDCTRL_ADCPD);
306 /* Select DAC */
307 wmc_set(AAPCTRL, AAPCTRL_DACSEL);
309 codec_set_active(true);
312 void audiohw_set_recvol(int left, int right, int type)
314 switch (type)
316 case AUDIO_GAIN_MIC:
317 if (left > 0) {
318 wmc_set(AAPCTRL, AAPCTRL_MIC_BOOST);
320 else {
321 wmc_clear(AAPCTRL, AAPCTRL_MIC_BOOST);
323 break;
324 case AUDIO_GAIN_LINEIN:
325 wmc_write_masked(LINVOL, left, WMC_IN_VOL_MASK);
326 wmc_write_masked(RINVOL, right, WMC_IN_VOL_MASK);
327 break;
328 default:
329 return;
333 void audiohw_set_monitor(bool enable)
335 if(enable) {
336 wmc_clear(PDCTRL, PDCTRL_LINEINPD);
337 wmc_set(AAPCTRL, AAPCTRL_BYPASS);
339 else {
340 wmc_clear(AAPCTRL, AAPCTRL_BYPASS);
341 wmc_set(PDCTRL, PDCTRL_LINEINPD);
344 #endif /* HAVE_WM8731 && HAVE_RECORDING */