summaryrefslogtreecommitdiff
path: root/firmware/drivers/audio/wm8985.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/drivers/audio/wm8985.c')
-rw-r--r--firmware/drivers/audio/wm8985.c111
1 files changed, 41 insertions, 70 deletions
diff --git a/firmware/drivers/audio/wm8985.c b/firmware/drivers/audio/wm8985.c
index 6f8d65998b..411bd97c59 100644
--- a/firmware/drivers/audio/wm8985.c
+++ b/firmware/drivers/audio/wm8985.c
@@ -86,18 +86,6 @@
86#define OUT4MIX 0x39 86#define OUT4MIX 0x39
87#define BIASCTL 0x3d 87#define BIASCTL 0x3d
88 88
89/* Register settings for the supported samplerates: */
90#define WM8985_8000HZ 0x4d
91#define WM8985_12000HZ 0x61
92#define WM8985_16000HZ 0x55
93#define WM8985_22050HZ 0x77
94#define WM8985_24000HZ 0x79
95#define WM8985_32000HZ 0x59
96#define WM8985_44100HZ 0x63
97#define WM8985_48000HZ 0x41
98#define WM8985_88200HZ 0x7f
99#define WM8985_96000HZ 0x5d
100
101const struct sound_settings_info audiohw_settings[] = { 89const struct sound_settings_info audiohw_settings[] = {
102 [SOUND_VOLUME] = {"dB", 0, 1, -58, 6, -25}, 90 [SOUND_VOLUME] = {"dB", 0, 1, -58, 6, -25},
103 [SOUND_BASS] = {"dB", 0, 1, -12, 12, 0}, 91 [SOUND_BASS] = {"dB", 0, 1, -12, 12, 0},
@@ -136,19 +124,6 @@ int tenthdb2master(int db)
136 } 124 }
137} 125}
138 126
139/* convert tenth of dB volume (-780..0) to mixer volume register value */
140int tenthdb2mixer(int db)
141{
142 if (db < -660) /* 1.5 dB steps */
143 return (2640 - db) / 15;
144 else if (db < -600) /* 0.75 dB steps */
145 return (990 - db) * 2 / 15;
146 else if (db < -460) /* 0.5 dB steps */
147 return (460 - db) / 5;
148 else /* 0.25 dB steps */
149 return -db * 2 / 5;
150}
151
152/* Silently enable / disable audio output */ 127/* Silently enable / disable audio output */
153void audiohw_enable_output(bool enable) 128void audiohw_enable_output(bool enable)
154{ 129{
@@ -157,32 +132,53 @@ void audiohw_enable_output(bool enable)
157 /* TODO: reset the I2S controller into known state */ 132 /* TODO: reset the I2S controller into known state */
158 //i2s_reset(); 133 //i2s_reset();
159 134
160 /* TODO: Review the power-up sequence to prevent pops (see datasheet) */ 135 wmcodec_write(RESET, 0x1ff); /* Reset */
161 136
162 wmcodec_write(RESET, 0x1ff); /*Reset*/ 137 wmcodec_write(BIASCTL, 0x100); /* BIASCUT = 1 */
138 wmcodec_write(OUTCTRL, 0x6); /* Thermal shutdown */
163 139
164 wmcodec_write(PWRMGMT1, 0x2b); 140 wmcodec_write(PWRMGMT1, 0x8); /* BIASEN = 1 */
165 wmcodec_write(PWRMGMT2, 0x180); 141
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);
149
150 /* DAC softmute, automute, 128OSR */
151 wmcodec_write(DACCTRL, 0x4c);
152
153 wmcodec_write(OUT4ADC, 0x2); /* POBCTRL = 1 */
154
155 /* Enable output, DAC and mixer */
166 wmcodec_write(PWRMGMT3, 0x6f); 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);
167 161
168 wmcodec_write(AINTFCE, 0x10); 162 /* Disable clock since we're acting as slave to the SoC */
169 wmcodec_write(CLKCTRL, 0x49); 163 wmcodec_write(CLKGEN, 0x0);
164 wmcodec_write(AINTFCE, 0x10); /* 16-bit, I2S format */
170 165
171 wmcodec_write(OUTCTRL, 1); 166 wmcodec_write(LDACVOL, 0x1ff); /* Full DAC digital vol */
167 wmcodec_write(RDACVOL, 0x1ff);
172 168
173 /* The iPod can handle multiple frequencies, but fix at 44.1KHz 169 wmcodec_write(OUT4ADC, 0x0); /* POBCTRL = 0 */
174 for now */ 170
175 audiohw_set_sample_rate(WM8985_44100HZ); 171 sleep(HZ/2);
176 172
177 wmcodec_write(LOUTMIX,0x1); /* Enable mixer */
178 wmcodec_write(ROUTMIX,0x1); /* Enable mixer */
179 audiohw_mute(0); 173 audiohw_mute(0);
180 } else { 174 }
175 else
176 {
181 audiohw_mute(1); 177 audiohw_mute(1);
182 } 178 }
183} 179}
184 180
185void audiohw_set_master_vol(int vol_l, int vol_r) 181void audiohw_set_headphone_vol(int vol_l, int vol_r)
186{ 182{
187 /* OUT1 */ 183 /* OUT1 */
188 wmcodec_write(LOUT1VOL, 0x080 | vol_l); 184 wmcodec_write(LOUT1VOL, 0x080 | vol_l);
@@ -196,12 +192,6 @@ void audiohw_set_lineout_vol(int vol_l, int vol_r)
196 wmcodec_write(ROUT2VOL, 0x100 | vol_r); 192 wmcodec_write(ROUT2VOL, 0x100 | vol_r);
197} 193}
198 194
199void audiohw_set_mixer_vol(int channel1, int channel2)
200{
201 (void)channel1;
202 (void)channel2;
203}
204
205void audiohw_set_bass(int value) 195void audiohw_set_bass(int value)
206{ 196{
207 eq1_reg = (eq1_reg & ~EQ_GAIN_MASK) | EQ_GAIN_VALUE(value); 197 eq1_reg = (eq1_reg & ~EQ_GAIN_MASK) | EQ_GAIN_VALUE(value);
@@ -231,14 +221,14 @@ void audiohw_mute(bool mute)
231 if (mute) 221 if (mute)
232 { 222 {
233 /* Set DACMU = 1 to soft-mute the audio DACs. */ 223 /* Set DACMU = 1 to soft-mute the audio DACs. */
234 wmcodec_write(DACCTRL, 0x40); 224 wmcodec_write(DACCTRL, 0x4c);
235 } else { 225 } else {
236 /* Set DACMU = 0 to soft-un-mute the audio DACs. */ 226 /* Set DACMU = 0 to soft-un-mute the audio DACs. */
237 wmcodec_write(DACCTRL, 0x0); 227 wmcodec_write(DACCTRL, 0xc);
238 } 228 }
239} 229}
240 230
241/* Nice shutdown of WM8758 codec */ 231/* Nice shutdown of WM8985 codec */
242void audiohw_close(void) 232void audiohw_close(void)
243{ 233{
244 audiohw_mute(1); 234 audiohw_mute(1);
@@ -250,32 +240,13 @@ void audiohw_close(void)
250 wmcodec_write(PWRMGMT2, 0x40); 240 wmcodec_write(PWRMGMT2, 0x40);
251} 241}
252 242
253/* Change the order of the noise shaper, 5th order is recommended above 32kHz */
254void audiohw_set_nsorder(int order)
255{
256 (void)order;
257}
258
259/* Note: Disable output before calling this function */ 243/* Note: Disable output before calling this function */
260void audiohw_set_sample_rate(int sampling_control) 244void audiohw_set_sample_rate(int sampling_control)
261{ 245{
262 /**** We force 44.1KHz for now. ****/ 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. */
263 (void)sampling_control; 249 (void)sampling_control;
264
265 /* set clock div */
266 wmcodec_write(CLKCTRL, 1 | (0 << 2) | (2 << 5));
267
268 /* setup PLL for MHZ=11.2896 */
269 wmcodec_write(PLLN, (1 << 4) | 0x7);
270 wmcodec_write(PLLK1, 0x21);
271 wmcodec_write(PLLK2, 0x161);
272 wmcodec_write(PLLK3, 0x26);
273
274 /* set clock div */
275 wmcodec_write(CLKCTRL, 1 | (1 << 2) | (2 << 5) | (1 << 8));
276
277 /* set srate */
278 wmcodec_write(SRATECTRL, (0 << 1));
279} 250}
280 251
281#ifdef HAVE_RECORDING 252#ifdef HAVE_RECORDING