summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--firmware/SOURCES2
-rw-r--r--firmware/drivers/wm8758.c276
-rw-r--r--firmware/drivers/wm8975.c36
-rw-r--r--firmware/export/config-ipodvideo.h4
-rw-r--r--firmware/export/wm8758.h74
-rw-r--r--firmware/export/wm8975.h31
-rw-r--r--firmware/pcm_playback.c14
-rw-r--r--firmware/sound.c72
8 files changed, 453 insertions, 56 deletions
diff --git a/firmware/SOURCES b/firmware/SOURCES
index 53923b3c35..15a5de8b7c 100644
--- a/firmware/SOURCES
+++ b/firmware/SOURCES
@@ -165,6 +165,8 @@ drivers/lcd-h100-remote.c
165drivers/uda1380.c 165drivers/uda1380.c
166#elif defined(HAVE_WM8975) && !defined(SIMULATOR) 166#elif defined(HAVE_WM8975) && !defined(SIMULATOR)
167drivers/wm8975.c 167drivers/wm8975.c
168#elif defined(HAVE_WM8758) && !defined(SIMULATOR)
169drivers/wm8758.c
168#elif defined(HAVE_WM8731L) && !defined(SIMULATOR) 170#elif defined(HAVE_WM8731L) && !defined(SIMULATOR)
169drivers/wm8731l.c 171drivers/wm8731l.c
170#elif defined(HAVE_TLV320) && !defined(SIMULATOR) 172#elif defined(HAVE_TLV320) && !defined(SIMULATOR)
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}
diff --git a/firmware/export/config-ipodvideo.h b/firmware/export/config-ipodvideo.h
index 160a2db383..2bf0396a21 100644
--- a/firmware/export/config-ipodvideo.h
+++ b/firmware/export/config-ipodvideo.h
@@ -42,8 +42,8 @@
42/* The number of bytes reserved for loadable plugins */ 42/* The number of bytes reserved for loadable plugins */
43#define PLUGIN_BUFFER_SIZE 0x80000 43#define PLUGIN_BUFFER_SIZE 0x80000
44 44
45/* Define this if you have the WM8975 audio codec */ 45/* Define this if you have the WM8758 audio codec */
46#define HAVE_WM8975 46#define HAVE_WM8758
47 47
48/* Define this for LCD backlight available */ 48/* Define this for LCD backlight available */
49#define CONFIG_BACKLIGHT BL_IPODNANO /* port controlled */ 49#define CONFIG_BACKLIGHT BL_IPODNANO /* port controlled */
diff --git a/firmware/export/wm8758.h b/firmware/export/wm8758.h
new file mode 100644
index 0000000000..adc17f86d7
--- /dev/null
+++ b/firmware/export/wm8758.h
@@ -0,0 +1,74 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2005 by Dave Chapman
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19
20#ifndef _WM8758_H
21#define _WM8758_H
22
23extern void wmcodec_reset(void);
24extern int wmcodec_init(void);
25extern void wmcodec_enable_output(bool enable);
26extern int wmcodec_set_master_vol(int vol_l, int vol_r);
27extern int wmcodec_set_mixer_vol(int channel1, int channel2);
28extern void wmcodec_set_bass(int value);
29extern void wmcodec_set_treble(int value);
30extern int wmcodec_mute(int mute);
31extern void wmcodec_close(void);
32extern void wmcodec_set_nsorder(int order);
33extern void wmcodec_set_sample_rate(int sampling_control);
34
35extern void wmcodec_enable_recording(bool source_mic);
36extern void wmcodec_disable_recording(void);
37extern void wmcodec_set_recvol(int left, int right, int type);
38extern void wmcodec_set_monitor(int enable);
39
40#define RESET 0x00
41#define PWRMGMT1 0x01
42#define PWRMGMT2 0x02
43#define PWRMGMT3 0x03
44#define AINTFCE 0x04
45#define CLKCTRL 0x06
46#define SRATECTRL 0x07
47#define DACCTRL 0x0a
48#define OUTCTRL 0x31
49#define LOUTMIX 0x32
50#define ROUTMIX 0x33
51
52#define LOUT1VOL 0x34
53#define ROUT1VOL 0x35
54#define LOUT2VOL 0x36
55#define ROUT2VOL 0x37
56
57#define PLLN 0x24
58#define PLLK1 0x25
59#define PLLK2 0x26
60#define PLLK3 0x27
61
62/* Register settings for the supported samplerates: */
63#define WM8758_8000HZ 0x4d
64#define WM8758_12000HZ 0x61
65#define WM8758_16000HZ 0x55
66#define WM8758_22050HZ 0x77
67#define WM8758_24000HZ 0x79
68#define WM8758_32000HZ 0x59
69#define WM8758_44100HZ 0x63
70#define WM8758_48000HZ 0x41
71#define WM8758_88200HZ 0x7f
72#define WM8758_96000HZ 0x5d
73
74#endif /* _WM8758_H */
diff --git a/firmware/export/wm8975.h b/firmware/export/wm8975.h
index 1d63159748..4d575c3d90 100644
--- a/firmware/export/wm8975.h
+++ b/firmware/export/wm8975.h
@@ -20,22 +20,22 @@
20#ifndef _WM8975_H 20#ifndef _WM8975_H
21#define _WM8975_H 21#define _WM8975_H
22 22
23extern void wm8975_reset(void); 23extern void wmcodec_reset(void);
24extern int wm8975_init(void); 24extern int wmcodec_init(void);
25extern void wm8975_enable_output(bool enable); 25extern void wmcodec_enable_output(bool enable);
26extern int wm8975_set_master_vol(int vol_l, int vol_r); 26extern int wmcodec_set_master_vol(int vol_l, int vol_r);
27extern int wm8975_set_mixer_vol(int channel1, int channel2); 27extern int wmcodec_set_mixer_vol(int channel1, int channel2);
28extern void wm8975_set_bass(int value); 28extern void wmcodec_set_bass(int value);
29extern void wm8975_set_treble(int value); 29extern void wmcodec_set_treble(int value);
30extern int wm8975_mute(int mute); 30extern int wmcodec_mute(int mute);
31extern void wm8975_close(void); 31extern void wmcodec_close(void);
32extern void wm8975_set_nsorder(int order); 32extern void wmcodec_set_nsorder(int order);
33extern void wm8975_set_sample_rate(int sampling_control); 33extern void wmcodec_set_sample_rate(int sampling_control);
34 34
35extern void wm8975_enable_recording(bool source_mic); 35extern void wmcodec_enable_recording(bool source_mic);
36extern void wm8975_disable_recording(void); 36extern void wmcodec_disable_recording(void);
37extern void wm8975_set_recvol(int left, int right, int type); 37extern void wmcodec_set_recvol(int left, int right, int type);
38extern void wm8975_set_monitor(int enable); 38extern void wmcodec_set_monitor(int enable);
39 39
40/* Register addresses */ 40/* Register addresses */
41#define LOUT1VOL 0x02 41#define LOUT1VOL 0x02
@@ -56,7 +56,6 @@ extern void wm8975_set_monitor(int enable);
56#define LOUT2VOL 0x28 56#define LOUT2VOL 0x28
57#define ROUT2VOL 0x29 57#define ROUT2VOL 0x29
58 58
59
60/* Register settings for the supported samplerates: */ 59/* Register settings for the supported samplerates: */
61#define WM8975_8000HZ 0x4d 60#define WM8975_8000HZ 0x4d
62#define WM8975_12000HZ 0x61 61#define WM8975_12000HZ 0x61
diff --git a/firmware/pcm_playback.c b/firmware/pcm_playback.c
index c55b48699b..1e9cac31f5 100644
--- a/firmware/pcm_playback.c
+++ b/firmware/pcm_playback.c
@@ -28,6 +28,8 @@
28#include "uda1380.h" 28#include "uda1380.h"
29#elif defined(HAVE_WM8975) 29#elif defined(HAVE_WM8975)
30#include "wm8975.h" 30#include "wm8975.h"
31#elif defined(HAVE_WM8758)
32#include "wm8758.h"
31#elif defined(HAVE_TLV320) 33#elif defined(HAVE_TLV320)
32#include "tlv320.h" 34#include "tlv320.h"
33#elif defined(HAVE_WM8731L) 35#elif defined(HAVE_WM8731L)
@@ -314,7 +316,7 @@ void pcm_init(void)
314 dma_stop(); 316 dma_stop();
315} 317}
316 318
317#elif defined(HAVE_WM8975) 319#elif defined(HAVE_WM8975) || defined(HAVE_WM8758)
318 320
319/* We need to unify this code with the uda1380 code as much as possible, but 321/* We need to unify this code with the uda1380 code as much as possible, but
320 we will keep it separate during early development. 322 we will keep it separate during early development.
@@ -408,7 +410,7 @@ size_t pcm_get_bytes_waiting(void)
408 410
409void pcm_mute(bool mute) 411void pcm_mute(bool mute)
410{ 412{
411 wm8975_mute(mute); 413 wmcodec_mute(mute);
412 if (mute) 414 if (mute)
413 sleep(HZ/16); 415 sleep(HZ/16);
414} 416}
@@ -532,15 +534,15 @@ void pcm_init(void)
532 pcm_paused = false; 534 pcm_paused = false;
533 535
534 /* Initialize default register values. */ 536 /* Initialize default register values. */
535 wm8975_init(); 537 wmcodec_init();
536 538
537 /* The uda1380 needs a sleep(HZ) here - do we need one? */ 539 /* The uda1380 needs a sleep(HZ) here - do we need one? */
538 540
539 /* Power on */ 541 /* Power on */
540 wm8975_enable_output(true); 542 wmcodec_enable_output(true);
541 543
542 /* Unmute the master channel (DAC should be at zero point now). */ 544 /* Unmute the master channel (DAC should be at zero point now). */
543 wm8975_mute(false); 545 wmcodec_mute(false);
544 546
545 /* Call dma_stop to initialize everything. */ 547 /* Call dma_stop to initialize everything. */
546 dma_stop(); 548 dma_stop();
@@ -625,7 +627,7 @@ void pcm_calculate_peaks(int *left, int *right)
625#ifdef HAVE_UDA1380 627#ifdef HAVE_UDA1380
626 long samples = (BCR0 & 0xffffff) / 4; 628 long samples = (BCR0 & 0xffffff) / 4;
627 short *addr = (short *) (SAR0 & ~3); 629 short *addr = (short *) (SAR0 & ~3);
628#elif defined(HAVE_WM8975) 630#elif defined(HAVE_WM8975) || defined(HAVE_WM8758)
629 long samples = p_size / 4; 631 long samples = p_size / 4;
630 short *addr = p; 632 short *addr = p;
631#elif defined(HAVE_WM8731L) 633#elif defined(HAVE_WM8731L)
diff --git a/firmware/sound.c b/firmware/sound.c
index 110c2c91b8..a039cca609 100644
--- a/firmware/sound.c
+++ b/firmware/sound.c
@@ -28,6 +28,8 @@
28#include "uda1380.h" 28#include "uda1380.h"
29#elif defined(HAVE_WM8975) 29#elif defined(HAVE_WM8975)
30#include "wm8975.h" 30#include "wm8975.h"
31#elif defined(HAVE_WM8758)
32#include "wm8758.h"
31#elif defined(HAVE_TLV320) 33#elif defined(HAVE_TLV320)
32#include "tlv320.h" 34#include "tlv320.h"
33#endif 35#endif
@@ -71,6 +73,10 @@ static const struct sound_settings_info sound_settings_table[] = {
71 [SOUND_VOLUME] = {"dB", 0, 1, -73, 6, -25, sound_set_volume}, 73 [SOUND_VOLUME] = {"dB", 0, 1, -73, 6, -25, sound_set_volume},
72 [SOUND_BASS] = {"dB", 0, 1, -6, 9, 0, sound_set_bass}, 74 [SOUND_BASS] = {"dB", 0, 1, -6, 9, 0, sound_set_bass},
73 [SOUND_TREBLE] = {"dB", 0, 1, -6, 9, 0, sound_set_treble}, 75 [SOUND_TREBLE] = {"dB", 0, 1, -6, 9, 0, sound_set_treble},
76#elif defined(HAVE_WM8758)
77 [SOUND_VOLUME] = {"dB", 0, 1, -57, 6, -25, sound_set_volume},
78 [SOUND_BASS] = {"dB", 0, 1, -6, 9, 0, sound_set_bass},
79 [SOUND_TREBLE] = {"dB", 0, 1, -6, 9, 0, sound_set_treble},
74#else /* MAS3507D */ 80#else /* MAS3507D */
75 [SOUND_VOLUME] = {"dB", 0, 1, -78, 18, -18, sound_set_volume}, 81 [SOUND_VOLUME] = {"dB", 0, 1, -78, 18, -18, sound_set_volume},
76 [SOUND_BASS] = {"dB", 0, 1, -15, 15, 7, sound_set_bass}, 82 [SOUND_BASS] = {"dB", 0, 1, -15, 15, 7, sound_set_bass},
@@ -276,7 +282,8 @@ static int tenthdb2mixer(int db)
276 return -db * 2 / 5; 282 return -db * 2 / 5;
277} 283}
278 284
279#elif defined(HAVE_WM8975) /* volume/balance/treble/bass interdependency */ 285#elif defined(HAVE_WM8975)
286/* volume/balance/treble/bass interdependency */
280#define VOLUME_MIN -730 287#define VOLUME_MIN -730
281#define VOLUME_MAX 60 288#define VOLUME_MAX 60
282 289
@@ -290,9 +297,43 @@ static int tenthdb2master(int db)
290 /* 0101111 == mute (0x2f) */ 297 /* 0101111 == mute (0x2f) */
291 298
292 if (db <= -730) { 299 if (db <= -730) {
293 return 0x2f; 300 return 0x0;
294 } else { 301 } else {
295 return((db/10)+74+0x2f); 302 return((db/10)+73+0x2f);
303 }
304}
305
306/* convert tenth of dB volume (-780..0) to mixer volume register value */
307static int tenthdb2mixer(int db)
308{
309 if (db < -660) /* 1.5 dB steps */
310 return (2640 - db) / 15;
311 else if (db < -600) /* 0.75 dB steps */
312 return (990 - db) * 2 / 15;
313 else if (db < -460) /* 0.5 dB steps */
314 return (460 - db) / 5;
315 else /* 0.25 dB steps */
316 return -db * 2 / 5;
317}
318
319#elif defined(HAVE_WM8758)
320/* volume/balance/treble/bass interdependency */
321#define VOLUME_MIN -730
322#define VOLUME_MAX 60
323
324/* convert tenth of dB volume (-730..60) to master volume register value */
325static int tenthdb2master(int db)
326{
327 /* +6 to -73dB 1dB steps (plus mute == 80levels) 7bits */
328 /* 1111111 == +6dB (0x7f) */
329 /* 1111001 == 0dB (0x79) */
330 /* 0110000 == -73dB (0x30 */
331 /* 0101111 == mute (0x2f) */
332
333 if (db <= -570) {
334 return 0x0;
335 } else {
336 return((db/10)+57);
296 } 337 }
297} 338}
298 339
@@ -311,7 +352,8 @@ static int tenthdb2mixer(int db)
311 352
312#endif 353#endif
313 354
314#if (CONFIG_CODEC == MAS3507D) || defined HAVE_UDA1380 || defined HAVE_WM8975 355#if (CONFIG_CODEC == MAS3507D) || defined HAVE_UDA1380 || \
356 defined HAVE_WM8975 || defined HAVE_WM8758
315 /* volume/balance/treble/bass interdependency main part */ 357 /* volume/balance/treble/bass interdependency main part */
316#define VOLUME_RANGE (VOLUME_MAX - VOLUME_MIN) 358#define VOLUME_RANGE (VOLUME_MAX - VOLUME_MIN)
317 359
@@ -341,8 +383,8 @@ static void set_prescaled_volume(void)
341 mas_writereg(MAS_REG_KPRESCALE, prescale_table[prescale/10]); 383 mas_writereg(MAS_REG_KPRESCALE, prescale_table[prescale/10]);
342#elif defined(HAVE_UDA1380) 384#elif defined(HAVE_UDA1380)
343 uda1380_set_mixer_vol(tenthdb2mixer(-prescale), tenthdb2mixer(-prescale)); 385 uda1380_set_mixer_vol(tenthdb2mixer(-prescale), tenthdb2mixer(-prescale));
344#elif defined(HAVE_WM8975) 386#elif defined(HAVE_WM8975) || defined(HAVE_WM8758)
345 wm8975_set_mixer_vol(tenthdb2mixer(-prescale), tenthdb2mixer(-prescale)); 387 wmcodec_set_mixer_vol(tenthdb2mixer(-prescale), tenthdb2mixer(-prescale));
346#endif 388#endif
347 389
348 if (current_volume == VOLUME_MIN) 390 if (current_volume == VOLUME_MIN)
@@ -367,8 +409,8 @@ static void set_prescaled_volume(void)
367 dac_volume(tenthdb2reg(l), tenthdb2reg(r), false); 409 dac_volume(tenthdb2reg(l), tenthdb2reg(r), false);
368#elif defined(HAVE_UDA1380) 410#elif defined(HAVE_UDA1380)
369 uda1380_set_master_vol(tenthdb2master(l), tenthdb2master(r)); 411 uda1380_set_master_vol(tenthdb2master(l), tenthdb2master(r));
370#elif defined(HAVE_WM8975) 412#elif defined(HAVE_WM8975) || defined(HAVE_WM8758)
371 wm8975_set_master_vol(tenthdb2master(l), tenthdb2master(r)); 413 wmcodec_set_master_vol(tenthdb2master(l), tenthdb2master(r));
372#endif 414#endif
373} 415}
374#endif /* (CONFIG_CODEC == MAS3507D) || defined HAVE_UDA1380 */ 416#endif /* (CONFIG_CODEC == MAS3507D) || defined HAVE_UDA1380 */
@@ -468,7 +510,8 @@ void sound_set_volume(int value)
468#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) 510#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
469 unsigned tmp = ((unsigned)(value + 115) & 0xff) << 8; 511 unsigned tmp = ((unsigned)(value + 115) & 0xff) << 8;
470 mas_codec_writereg(0x10, tmp); 512 mas_codec_writereg(0x10, tmp);
471#elif (CONFIG_CODEC == MAS3507D) || defined HAVE_UDA1380 || defined HAVE_WM8975 513#elif (CONFIG_CODEC == MAS3507D) || defined HAVE_UDA1380 || \
514 defined HAVE_WM8975 || defined HAVE_WM8758
472 current_volume = value * 10; /* tenth of dB */ 515 current_volume = value * 10; /* tenth of dB */
473 set_prescaled_volume(); 516 set_prescaled_volume();
474#elif CONFIG_CPU == PNX0101 517#elif CONFIG_CPU == PNX0101
@@ -484,7 +527,8 @@ void sound_set_balance(int value)
484#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) 527#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
485 unsigned tmp = ((unsigned)(value * 127 / 100) & 0xff) << 8; 528 unsigned tmp = ((unsigned)(value * 127 / 100) & 0xff) << 8;
486 mas_codec_writereg(0x11, tmp); 529 mas_codec_writereg(0x11, tmp);
487#elif CONFIG_CODEC == MAS3507D || defined HAVE_UDA1380 || defined HAVE_WM8975 530#elif CONFIG_CODEC == MAS3507D || defined HAVE_UDA1380 || \
531 defined HAVE_WM8975 || defined HAVE_WM8758
488 current_balance = value * VOLUME_RANGE / 100; /* tenth of dB */ 532 current_balance = value * VOLUME_RANGE / 100; /* tenth of dB */
489 set_prescaled_volume(); 533 set_prescaled_volume();
490#elif CONFIG_CPU == PNX0101 534#elif CONFIG_CPU == PNX0101
@@ -508,9 +552,9 @@ void sound_set_bass(int value)
508 uda1380_set_bass(value >> 1); 552 uda1380_set_bass(value >> 1);
509 current_bass = value * 10; 553 current_bass = value * 10;
510 set_prescaled_volume(); 554 set_prescaled_volume();
511#elif defined(HAVE_WM8975) 555#elif defined HAVE_WM8975 || defined HAVE_WM8758
512 current_bass = value * 10; 556 current_bass = value * 10;
513 wm8975_set_bass(value); 557 wmcodec_set_bass(value);
514 set_prescaled_volume(); 558 set_prescaled_volume();
515#elif CONFIG_CPU == PNX0101 559#elif CONFIG_CPU == PNX0101
516 /* TODO: implement for iFP */ 560 /* TODO: implement for iFP */
@@ -533,8 +577,8 @@ void sound_set_treble(int value)
533 uda1380_set_treble(value >> 1); 577 uda1380_set_treble(value >> 1);
534 current_treble = value * 10; 578 current_treble = value * 10;
535 set_prescaled_volume(); 579 set_prescaled_volume();
536#elif defined(HAVE_WM8975) 580#elif defined(HAVE_WM8975) || defined(HAVE_WM8758)
537 wm8975_set_treble(value); 581 wmcodec_set_treble(value);
538 current_treble = value * 10; 582 current_treble = value * 10;
539 set_prescaled_volume(); 583 set_prescaled_volume();
540#elif CONFIG_CPU == PNX0101 584#elif CONFIG_CPU == PNX0101