summaryrefslogtreecommitdiff
path: root/firmware/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/drivers')
-rw-r--r--firmware/drivers/wm8758.c276
-rw-r--r--firmware/drivers/wm8975.c36
2 files changed, 294 insertions, 18 deletions
diff --git a/firmware/drivers/wm8758.c b/firmware/drivers/wm8758.c
new file mode 100644
index 0000000000..3069b3cba7
--- /dev/null
+++ b/firmware/drivers/wm8758.c
@@ -0,0 +1,276 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Driver for WM8758 audio codec
11 *
12 * Based on code from the ipodlinux project - http://ipodlinux.org/
13 * Adapted for Rockbox in December 2005
14 *
15 * Original file: linux/arch/armnommu/mach-ipod/audio.c
16 *
17 * Copyright (c) 2003-2005 Bernard Leach (leachbj@bouncycastle.org)
18 *
19 * All files in this archive are subject to the GNU General Public License.
20 * See the file COPYING in the source tree root for full license agreement.
21 *
22 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
23 * KIND, either express or implied.
24 *
25 ****************************************************************************/
26#include "lcd.h"
27#include "cpu.h"
28#include "kernel.h"
29#include "thread.h"
30#include "power.h"
31#include "debug.h"
32#include "system.h"
33#include "sprintf.h"
34#include "button.h"
35#include "string.h"
36#include "file.h"
37#include "buffer.h"
38#include "audio.h"
39
40#include "i2c-pp5020.h"
41#include "wm8758.h"
42#include "pcf50605.h"
43
44void wmcodec_reset(void);
45
46#define IPOD_PCM_LEVEL 0x65 /* -6dB */
47
48//#define BASSCTRL 0x
49//#define TREBCTRL 0x0b
50
51/*
52 * Reset the I2S BIT.FORMAT I2S, 16bit, FIFO.FORMAT 32bit
53 */
54static void i2s_reset(void)
55{
56 /* PP502x */
57
58 /* I2S soft reset */
59 outl(inl(0x70002800) | 0x80000000, 0x70002800);
60 outl(inl(0x70002800) & ~0x80000000, 0x70002800);
61
62 /* BIT.FORMAT [11:10] = I2S (default) */
63 outl(inl(0x70002800) & ~0xc00, 0x70002800);
64 /* BIT.SIZE [9:8] = 16bit (default) */
65 outl(inl(0x70002800) & ~0x300, 0x70002800);
66
67 /* FIFO.FORMAT [6:4] = 32 bit LSB */
68 /* since BIT.SIZ < FIFO.FORMAT low 16 bits will be 0 */
69 outl(inl(0x70002800) | 0x30, 0x70002800);
70
71 /* RX_ATN_LVL=1 == when 12 slots full */
72 /* TX_ATN_LVL=1 == when 12 slots empty */
73 outl(inl(0x7000280c) | 0x33, 0x7000280c);
74
75 /* Rx.CLR = 1, TX.CLR = 1 */
76 outl(inl(0x7000280c) | 0x1100, 0x7000280c);
77}
78
79void wm8758_write(int reg, int data)
80{
81 ipod_i2c_send(0x1a, (reg<<1) | ((data&0x100)>>8),data&0xff);
82}
83
84/*
85 * Initialise the WM8758 for playback via headphone and line out.
86 * Note, I'm using the WM8750 datasheet as its apparently close.
87 */
88int wmcodec_init(void) {
89 /* reset I2C */
90 i2c_init();
91
92 /* normal outputs for CDI and I2S pin groups */
93 outl(inl(0x70000020) & ~0x300, 0x70000020);
94
95 /*mini2?*/
96 outl(inl(0x70000010) & ~0x3000000, 0x70000010);
97 /*mini2?*/
98
99 /* device reset */
100 outl(inl(0x60006004) | 0x800, 0x60006004);
101 outl(inl(0x60006004) & ~0x800, 0x60006004);
102
103 /* device enable */
104 outl(inl(0x6000600C) | 0x807, 0x6000600C);
105
106 /* enable external dev clock clocks */
107 outl(inl(0x6000600c) | 0x2, 0x6000600c);
108
109 /* external dev clock to 24MHz */
110 outl(inl(0x70000018) & ~0xc, 0x70000018);
111
112 return 0;
113}
114
115/* Silently enable / disable audio output */
116void wmcodec_enable_output(bool enable)
117{
118 if (enable)
119 {
120 /* reset the I2S controller into known state */
121 i2s_reset();
122
123 wm8758_write(RESET, 0x1ff); /*Reset*/
124
125 wm8758_write(PWRMGMT1, 0x2b);
126 wm8758_write(PWRMGMT2, 0x180);
127 wm8758_write(PWRMGMT3, 0x6f);
128
129 wm8758_write(AINTFCE, 0x10);
130 wm8758_write(CLKCTRL, 0x49);
131
132 wm8758_write(OUTCTRL, 1 | (0x3 << 5));
133
134 /* The iPod can handle multiple frequencies, but fix at 44.1KHz
135 for now */
136 wmcodec_set_sample_rate(WM8758_44100HZ);
137
138 wm8758_write(LOUTMIX,0x1); /* Enable mixer */
139 wm8758_write(ROUTMIX,0x1); /* Enable mixer */
140 wmcodec_mute(0);
141 } else {
142 wmcodec_mute(1);
143 }
144}
145
146int wmcodec_set_master_vol(int vol_l, int vol_r)
147{
148 /* +6 to -73dB 1dB steps (plus mute == 80levels) 7bits */
149 /* 1111111 == +6dB */
150 /* 1111001 == 0dB */
151 /* 0110000 == -73dB */
152 /* 0101111 == mute (0x2f) */
153
154 /* OUT1 */
155 wm8758_write(LOUT1VOL, vol_l);
156 wm8758_write(ROUT1VOL, 0x100 | vol_r);
157
158 /* OUT2 */
159 wm8758_write(LOUT2VOL, vol_l);
160 wm8758_write(ROUT2VOL, 0x100 | vol_r);
161
162 return 0;
163}
164
165int wmcodec_set_mixer_vol(int channel1, int channel2)
166{
167 (void)channel1;
168 (void)channel2;
169
170 return 0;
171}
172
173/* We are using Linear bass control */
174void wmcodec_set_bass(int value)
175{
176 (void)value;
177#if 0
178 /* Not yet implemented - this is the wm8975 code*/
179 int regvalues[]={11, 10, 10, 9, 8, 8, 0xf , 6, 6, 5, 4, 4, 3, 2, 1, 0};
180
181 if ((value >= -6) && (value <= 9)) {
182 /* We use linear bass control with 130Hz cutoff */
183 wm8758_write(BASSCTRL, regvalues[value+6]);
184 }
185#endif
186}
187
188void wmcodec_set_treble(int value)
189{
190 (void)value;
191#if 0
192 /* Not yet implemented - this is the wm8975 code*/
193 int regvalues[]={11, 10, 10, 9, 8, 8, 0xf , 6, 6, 5, 4, 4, 3, 2, 1, 0};
194
195 if ((value >= -6) && (value <= 9)) {
196 /* We use a 8Khz cutoff */
197 wm8758_write(TREBCTRL, regvalues[value+6]);
198 }
199#endif
200
201}
202
203int wmcodec_mute(int mute)
204{
205 if (mute)
206 {
207 /* Set DACMU = 1 to soft-mute the audio DACs. */
208 wm8758_write(DACCTRL, 0x40);
209 } else {
210 /* Set DACMU = 0 to soft-un-mute the audio DACs. */
211 wm8758_write(DACCTRL, 0x0);
212 }
213
214 return 0;
215}
216
217/* Nice shutdown of WM8758 codec */
218void wmcodec_close(void)
219{
220 wmcodec_mute(1);
221
222 wm8758_write(PWRMGMT3, 0x0);
223
224 wm8758_write(PWRMGMT1, 0x0);
225
226 wm8758_write(PWRMGMT2, 0x40);
227}
228
229/* Change the order of the noise shaper, 5th order is recommended above 32kHz */
230void wmcodec_set_nsorder(int order)
231{
232 (void)order;
233}
234
235/* Note: Disable output before calling this function */
236void wmcodec_set_sample_rate(int sampling_control)
237{
238 /**** We force 44.1KHz for now. ****/
239 (void)sampling_control;
240
241 /* set clock div */
242 wm8758_write(CLKCTRL, 1 | (0 << 2) | (2 << 5));
243
244 /* setup PLL for MHZ=11.2896 */
245 wm8758_write(PLLN, (1 << 4) | 0x7);
246 wm8758_write(PLLK1, 0x21);
247 wm8758_write(PLLK2, 0x161);
248 wm8758_write(PLLK3, 0x26);
249
250 /* set clock div */
251 wm8758_write(CLKCTRL, 1 | (0 << 2) | (2 << 5) | (1 << 8));
252
253 /* set srate */
254 wm8758_write(SRATECTRL, (0 << 1));
255}
256
257void wmcodec_enable_recording(bool source_mic)
258{
259 (void)source_mic;
260}
261
262void wmcodec_disable_recording(void) {
263
264}
265
266void wmcodec_set_recvol(int left, int right, int type) {
267
268 (void)left;
269 (void)right;
270 (void)type;
271}
272
273void wmcodec_set_monitor(int enable) {
274
275 (void)enable;
276}
diff --git a/firmware/drivers/wm8975.c b/firmware/drivers/wm8975.c
index 54e245b61a..51c12f1505 100644
--- a/firmware/drivers/wm8975.c
+++ b/firmware/drivers/wm8975.c
@@ -41,7 +41,7 @@
41#include "wm8975.h" 41#include "wm8975.h"
42#include "pcf50605.h" 42#include "pcf50605.h"
43 43
44void wm8975_reset(void); 44void wmcodec_reset(void);
45 45
46#define IPOD_PCM_LEVEL 0x65 /* -6dB */ 46#define IPOD_PCM_LEVEL 0x65 /* -6dB */
47 47
@@ -82,7 +82,7 @@ void wm8975_write(int reg, int data)
82 * Initialise the WM8975 for playback via headphone and line out. 82 * Initialise the WM8975 for playback via headphone and line out.
83 * Note, I'm using the WM8750 datasheet as its apparently close. 83 * Note, I'm using the WM8750 datasheet as its apparently close.
84 */ 84 */
85int wm8975_init(void) { 85int wmcodec_init(void) {
86 /* reset I2C */ 86 /* reset I2C */
87 i2c_init(); 87 i2c_init();
88 88
@@ -110,7 +110,7 @@ int wm8975_init(void) {
110} 110}
111 111
112/* Silently enable / disable audio output */ 112/* Silently enable / disable audio output */
113void wm8975_enable_output(bool enable) 113void wmcodec_enable_output(bool enable)
114{ 114{
115 if (enable) 115 if (enable)
116 { 116 {
@@ -141,7 +141,7 @@ void wm8975_enable_output(bool enable)
141 wm8975_write(AINTFCE, 0x42); 141 wm8975_write(AINTFCE, 0x42);
142 142
143 /* The iPod can handle multiple frequencies, but fix at 44.1KHz for now */ 143 /* The iPod can handle multiple frequencies, but fix at 44.1KHz for now */
144 wm8975_set_sample_rate(WM8975_44100HZ); 144 wmcodec_set_sample_rate(WM8975_44100HZ);
145 145
146 /* set the volume to -6dB */ 146 /* set the volume to -6dB */
147 wm8975_write(LOUT1VOL, IPOD_PCM_LEVEL); 147 wm8975_write(LOUT1VOL, IPOD_PCM_LEVEL);
@@ -158,13 +158,13 @@ void wm8975_enable_output(bool enable)
158 wm8975_write(MOUTMIX1, 0x0); /* Mono out Mix */ 158 wm8975_write(MOUTMIX1, 0x0); /* Mono out Mix */
159 wm8975_write(MOUTMIX2, 0x0); 159 wm8975_write(MOUTMIX2, 0x0);
160 160
161 wm8975_mute(0); 161 wmcodec_mute(0);
162 } else { 162 } else {
163 wm8975_mute(1); 163 wmcodec_mute(1);
164 } 164 }
165} 165}
166 166
167int wm8975_set_master_vol(int vol_l, int vol_r) 167int wmcodec_set_master_vol(int vol_l, int vol_r)
168{ 168{
169 /* +6 to -73dB 1dB steps (plus mute == 80levels) 7bits */ 169 /* +6 to -73dB 1dB steps (plus mute == 80levels) 7bits */
170 /* 1111111 == +6dB */ 170 /* 1111111 == +6dB */
@@ -183,7 +183,7 @@ int wm8975_set_master_vol(int vol_l, int vol_r)
183 return 0; 183 return 0;
184} 184}
185 185
186int wm8975_set_mixer_vol(int channel1, int channel2) 186int wmcodec_set_mixer_vol(int channel1, int channel2)
187{ 187{
188 (void)channel1; 188 (void)channel1;
189 (void)channel2; 189 (void)channel2;
@@ -192,7 +192,7 @@ int wm8975_set_mixer_vol(int channel1, int channel2)
192} 192}
193 193
194/* We are using Linear bass control */ 194/* We are using Linear bass control */
195void wm8975_set_bass(int value) 195void wmcodec_set_bass(int value)
196{ 196{
197 int regvalues[]={11, 10, 10, 9, 8, 8, 0xf , 6, 6, 5, 4, 4, 3, 2, 1, 0}; 197 int regvalues[]={11, 10, 10, 9, 8, 8, 0xf , 6, 6, 5, 4, 4, 3, 2, 1, 0};
198 198
@@ -202,7 +202,7 @@ void wm8975_set_bass(int value)
202 } 202 }
203} 203}
204 204
205void wm8975_set_treble(int value) 205void wmcodec_set_treble(int value)
206{ 206{
207 int regvalues[]={11, 10, 10, 9, 8, 8, 0xf , 6, 6, 5, 4, 4, 3, 2, 1, 0}; 207 int regvalues[]={11, 10, 10, 9, 8, 8, 0xf , 6, 6, 5, 4, 4, 3, 2, 1, 0};
208 208
@@ -212,7 +212,7 @@ void wm8975_set_treble(int value)
212 } 212 }
213} 213}
214 214
215int wm8975_mute(int mute) 215int wmcodec_mute(int mute)
216{ 216{
217 if (mute) 217 if (mute)
218 { 218 {
@@ -227,7 +227,7 @@ int wm8975_mute(int mute)
227} 227}
228 228
229/* Nice shutdown of WM8975 codec */ 229/* Nice shutdown of WM8975 codec */
230void wm8975_close(void) 230void wmcodec_close(void)
231{ 231{
232 /* 1. Set DACMU = 1 to soft-mute the audio DACs. */ 232 /* 1. Set DACMU = 1 to soft-mute the audio DACs. */
233 wm8975_write(DACCTRL, 0x8); 233 wm8975_write(DACCTRL, 0x8);
@@ -240,35 +240,35 @@ void wm8975_close(void)
240} 240}
241 241
242/* Change the order of the noise shaper, 5th order is recommended above 32kHz */ 242/* Change the order of the noise shaper, 5th order is recommended above 32kHz */
243void wm8975_set_nsorder(int order) 243void wmcodec_set_nsorder(int order)
244{ 244{
245 (void)order; 245 (void)order;
246} 246}
247 247
248/* Note: Disable output before calling this function */ 248/* Note: Disable output before calling this function */
249void wm8975_set_sample_rate(int sampling_control) { 249void wmcodec_set_sample_rate(int sampling_control) {
250 250
251 wm8975_write(0x08, sampling_control); 251 wm8975_write(0x08, sampling_control);
252 252
253} 253}
254 254
255void wm8975_enable_recording(bool source_mic) { 255void wmcodec_enable_recording(bool source_mic) {
256 256
257 (void)source_mic; 257 (void)source_mic;
258} 258}
259 259
260void wm8975_disable_recording(void) { 260void wmcodec_disable_recording(void) {
261 261
262} 262}
263 263
264void wm8975_set_recvol(int left, int right, int type) { 264void wmcodec_set_recvol(int left, int right, int type) {
265 265
266 (void)left; 266 (void)left;
267 (void)right; 267 (void)right;
268 (void)type; 268 (void)type;
269} 269}
270 270
271void wm8975_set_monitor(int enable) { 271void wmcodec_set_monitor(int enable) {
272 272
273 (void)enable; 273 (void)enable;
274} 274}