summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
Diffstat (limited to 'firmware')
-rw-r--r--firmware/drivers/adc.c3
-rw-r--r--firmware/drivers/i2c-pp5020.c80
-rw-r--r--firmware/drivers/rtc.c12
-rw-r--r--firmware/drivers/wm8758.c21
4 files changed, 53 insertions, 63 deletions
diff --git a/firmware/drivers/adc.c b/firmware/drivers/adc.c
index f4bdb7a54f..f1a6d7e667 100644
--- a/firmware/drivers/adc.c
+++ b/firmware/drivers/adc.c
@@ -294,10 +294,7 @@ static struct adc_struct adcdata[NUM_ADC_CHANNELS];
294 294
295static unsigned short adc_scan(struct adc_struct *adc) 295static unsigned short adc_scan(struct adc_struct *adc)
296{ 296{
297 /* Disable interrupts during the I2C transaction */
298 int old_irq_level = set_irq_level(HIGHEST_IRQ_LEVEL);
299 unsigned short data = pcf50605_a2d_read(adc->channelnum); 297 unsigned short data = pcf50605_a2d_read(adc->channelnum);
300 set_irq_level(old_irq_level);
301 /* This gives us a 13 bit value corresponding to 0-5.4 volts 298 /* This gives us a 13 bit value corresponding to 0-5.4 volts
302 * The range of the value is 13FB-17FA */ 299 * The range of the value is 13FB-17FA */
303 data = (data<<2)+0x13FB; 300 data = (data<<2)+0x13FB;
diff --git a/firmware/drivers/i2c-pp5020.c b/firmware/drivers/i2c-pp5020.c
index 522ddbed77..77671e79d8 100644
--- a/firmware/drivers/i2c-pp5020.c
+++ b/firmware/drivers/i2c-pp5020.c
@@ -57,42 +57,48 @@ static int ipod_i2c_wait_not_busy(void)
57 if (!(inb(IPOD_I2C_STATUS) & IPOD_I2C_BUSY)) { 57 if (!(inb(IPOD_I2C_STATUS) & IPOD_I2C_BUSY)) {
58 return 0; 58 return 0;
59 } 59 }
60 yield();
60 } 61 }
61 62
62 return -1; 63 return -1;
63} 64}
64 65
65 66
66/* Public functions */ 67static int ipod_i2c_read_byte(unsigned int addr, unsigned int *data)
67
68int ipod_i2c_read_byte(unsigned int addr, unsigned int *data)
69{ 68{
70 if (ipod_i2c_wait_not_busy() < 0) 69 if (ipod_i2c_wait_not_busy() < 0)
71 { 70 {
72 return -1; 71 return -1;
73 } 72 }
74 73
75 /* clear top 15 bits, left shift 1, or in 0x1 for a read */ 74 {
76 outb(((addr << 17) >> 16) | 0x1, IPOD_I2C_ADDR); 75 int old_irq_level = set_irq_level(HIGHEST_IRQ_LEVEL);
77 76
78 outb(inb(IPOD_I2C_CTRL) | 0x20, IPOD_I2C_CTRL); 77 /* clear top 15 bits, left shift 1, or in 0x1 for a read */
78 outb(((addr << 17) >> 16) | 0x1, IPOD_I2C_ADDR);
79 79
80 outb(inb(IPOD_I2C_CTRL) | IPOD_I2C_SEND, IPOD_I2C_CTRL); 80 outb(inb(IPOD_I2C_CTRL) | 0x20, IPOD_I2C_CTRL);
81 81
82 if (ipod_i2c_wait_not_busy() < 0) 82 outb(inb(IPOD_I2C_CTRL) | IPOD_I2C_SEND, IPOD_I2C_CTRL);
83 {
84 return -1;
85 }
86 83
87 if (data) 84 set_irq_level(old_irq_level);
88 { 85
89 *data = inb(IPOD_I2C_DATA0); 86 if (data)
87 {
88 if (ipod_i2c_wait_not_busy() < 0)
89 {
90 return -1;
91 }
92 old_irq_level = set_irq_level(HIGHEST_IRQ_LEVEL);
93 *data = inb(IPOD_I2C_DATA0);
94 set_irq_level(old_irq_level);
95 }
90 } 96 }
91 97
92 return 0; 98 return 0;
93} 99}
94 100
95int ipod_i2c_send_bytes(unsigned int addr, unsigned int len, unsigned char *data) 101static int ipod_i2c_send_bytes(unsigned int addr, unsigned int len, unsigned char *data)
96{ 102{
97 int data_addr; 103 int data_addr;
98 unsigned int i; 104 unsigned int i;
@@ -107,26 +113,32 @@ int ipod_i2c_send_bytes(unsigned int addr, unsigned int len, unsigned char *data
107 return -2; 113 return -2;
108 } 114 }
109 115
110 /* clear top 15 bits, left shift 1 */ 116 {
111 outb((addr << 17) >> 16, IPOD_I2C_ADDR); 117 int old_irq_level = set_irq_level(HIGHEST_IRQ_LEVEL);
112 118
113 outb(inb(IPOD_I2C_CTRL) & ~0x20, IPOD_I2C_CTRL); 119 /* clear top 15 bits, left shift 1 */
120 outb((addr << 17) >> 16, IPOD_I2C_ADDR);
114 121
115 data_addr = IPOD_I2C_DATA0; 122 outb(inb(IPOD_I2C_CTRL) & ~0x20, IPOD_I2C_CTRL);
116 for ( i = 0; i < len; i++ ) 123
117 { 124 data_addr = IPOD_I2C_DATA0;
118 outb(*data++, data_addr); 125 for ( i = 0; i < len; i++ )
119 data_addr += 4; 126 {
120 } 127 outb(*data++, data_addr);
128 data_addr += 4;
129 }
121 130
122 outb((inb(IPOD_I2C_CTRL) & ~0x26) | ((len-1) << 1), IPOD_I2C_CTRL); 131 outb((inb(IPOD_I2C_CTRL) & ~0x26) | ((len-1) << 1), IPOD_I2C_CTRL);
123 132
124 outb(inb(IPOD_I2C_CTRL) | IPOD_I2C_SEND, IPOD_I2C_CTRL); 133 outb(inb(IPOD_I2C_CTRL) | IPOD_I2C_SEND, IPOD_I2C_CTRL);
134
135 set_irq_level(old_irq_level);
136 }
125 137
126 return 0x0; 138 return 0x0;
127} 139}
128 140
129int ipod_i2c_send_byte(unsigned int addr, int data0) 141static int ipod_i2c_send_byte(unsigned int addr, int data0)
130{ 142{
131 unsigned char data[1]; 143 unsigned char data[1];
132 144
@@ -135,25 +147,35 @@ int ipod_i2c_send_byte(unsigned int addr, int data0)
135 return ipod_i2c_send_bytes(addr, 1, data); 147 return ipod_i2c_send_bytes(addr, 1, data);
136} 148}
137 149
150/* Public functions */
151static struct mutex i2c_mutex;
138 152
139int i2c_readbyte(unsigned int dev_addr, int addr) 153int i2c_readbyte(unsigned int dev_addr, int addr)
140{ 154{
155 int retval;
141 int data; 156 int data;
142 157
158 mutex_lock(&i2c_mutex);
143 ipod_i2c_send_byte(dev_addr, addr); 159 ipod_i2c_send_byte(dev_addr, addr);
144 ipod_i2c_read_byte(dev_addr, &data); 160 ipod_i2c_read_byte(dev_addr, &data);
161 mutex_unlock(&i2c_mutex);
145 162
146 return data; 163 return data;
147} 164}
148 165
149int ipod_i2c_send(unsigned int addr, int data0, int data1) 166int ipod_i2c_send(unsigned int addr, int data0, int data1)
150{ 167{
168 int retval;
151 unsigned char data[2]; 169 unsigned char data[2];
152 170
153 data[0] = data0; 171 data[0] = data0;
154 data[1] = data1; 172 data[1] = data1;
155 173
156 return ipod_i2c_send_bytes(addr, 2, data); 174 mutex_lock(&i2c_mutex);
175 retval = ipod_i2c_send_bytes(addr, 2, data);
176 mutex_unlock(&i2c_mutex);
177
178 return retval;
157} 179}
158 180
159void i2c_init(void) 181void i2c_init(void)
@@ -175,5 +197,7 @@ void i2c_init(void)
175 outl(0x0, 0x600060a4); 197 outl(0x0, 0x600060a4);
176 outl(0x80 | (0 << 8), 0x600060a4); 198 outl(0x80 | (0 << 8), 0x600060a4);
177 199
200 mutex_init(&i2c_mutex);
201
178 i2c_readbyte(0x8, 0); 202 i2c_readbyte(0x8, 0);
179} 203}
diff --git a/firmware/drivers/rtc.c b/firmware/drivers/rtc.c
index ecfd2ac6ba..4b4b45826f 100644
--- a/firmware/drivers/rtc.c
+++ b/firmware/drivers/rtc.c
@@ -36,28 +36,18 @@ void rtc_init(void)
36} 36}
37int rtc_read_datetime(unsigned char* buf) 37int rtc_read_datetime(unsigned char* buf)
38{ 38{
39 int rc; 39 return pcf50605_read_multiple(0x0a, buf, 7);
40 int old_irq_level = set_irq_level(HIGHEST_IRQ_LEVEL);
41
42 rc = pcf50605_read_multiple(0x0a, buf, 7);
43
44 set_irq_level(old_irq_level);
45
46 return rc;
47} 40}
48 41
49 42
50int rtc_write_datetime(unsigned char* buf) 43int rtc_write_datetime(unsigned char* buf)
51{ 44{
52 int i; 45 int i;
53 int old_irq_level = set_irq_level(HIGHEST_IRQ_LEVEL);
54 46
55 for (i=0;i<7;i++) { 47 for (i=0;i<7;i++) {
56 pcf50605_write(0x0a+i, buf[i]); 48 pcf50605_write(0x0a+i, buf[i]);
57 } 49 }
58 50
59 set_irq_level(old_irq_level);
60
61 return 1; 51 return 1;
62} 52}
63#elif CONFIG_RTC == RTC_PCF50606 53#elif CONFIG_RTC == RTC_PCF50606
diff --git a/firmware/drivers/wm8758.c b/firmware/drivers/wm8758.c
index 7c9ac77395..3867748417 100644
--- a/firmware/drivers/wm8758.c
+++ b/firmware/drivers/wm8758.c
@@ -86,8 +86,6 @@ void wm8758_write(int reg, int data)
86 * Note, I'm using the WM8750 datasheet as its apparently close. 86 * Note, I'm using the WM8750 datasheet as its apparently close.
87 */ 87 */
88int wmcodec_init(void) { 88int wmcodec_init(void) {
89 int old_irq_level = set_irq_level(HIGHEST_IRQ_LEVEL);
90
91 /* normal outputs for CDI and I2S pin groups */ 89 /* normal outputs for CDI and I2S pin groups */
92 outl(inl(0x70000020) & ~0x300, 0x70000020); 90 outl(inl(0x70000020) & ~0x300, 0x70000020);
93 91
@@ -108,7 +106,6 @@ int wmcodec_init(void) {
108 /* external dev clock to 24MHz */ 106 /* external dev clock to 24MHz */
109 outl(inl(0x70000018) & ~0xc, 0x70000018); 107 outl(inl(0x70000018) & ~0xc, 0x70000018);
110 108
111 set_irq_level(old_irq_level);
112 return 0; 109 return 0;
113} 110}
114 111
@@ -117,8 +114,6 @@ void wmcodec_enable_output(bool enable)
117{ 114{
118 if (enable) 115 if (enable)
119 { 116 {
120 int old_irq_level = set_irq_level(HIGHEST_IRQ_LEVEL);
121
122 /* reset the I2S controller into known state */ 117 /* reset the I2S controller into known state */
123 i2s_reset(); 118 i2s_reset();
124 119
@@ -142,7 +137,6 @@ void wmcodec_enable_output(bool enable)
142 wm8758_write(LOUTMIX,0x1); /* Enable mixer */ 137 wm8758_write(LOUTMIX,0x1); /* Enable mixer */
143 wm8758_write(ROUTMIX,0x1); /* Enable mixer */ 138 wm8758_write(ROUTMIX,0x1); /* Enable mixer */
144 wmcodec_mute(0); 139 wmcodec_mute(0);
145 set_irq_level(old_irq_level);
146 } else { 140 } else {
147 wmcodec_mute(1); 141 wmcodec_mute(1);
148 } 142 }
@@ -150,7 +144,6 @@ void wmcodec_enable_output(bool enable)
150 144
151int wmcodec_set_master_vol(int vol_l, int vol_r) 145int wmcodec_set_master_vol(int vol_l, int vol_r)
152{ 146{
153 int old_irq_level = set_irq_level(HIGHEST_IRQ_LEVEL);
154 /* OUT1 */ 147 /* OUT1 */
155 wm8758_write(LOUT1VOL, vol_l); 148 wm8758_write(LOUT1VOL, vol_l);
156 wm8758_write(ROUT1VOL, 0x100 | vol_r); 149 wm8758_write(ROUT1VOL, 0x100 | vol_r);
@@ -159,8 +152,6 @@ int wmcodec_set_master_vol(int vol_l, int vol_r)
159 wm8758_write(LOUT2VOL, vol_l); 152 wm8758_write(LOUT2VOL, vol_l);
160 wm8758_write(ROUT2VOL, 0x100 | vol_r); 153 wm8758_write(ROUT2VOL, 0x100 | vol_r);
161 154
162 set_irq_level(old_irq_level);
163
164 return 0; 155 return 0;
165} 156}
166 157
@@ -204,8 +195,6 @@ void wmcodec_set_treble(int value)
204 195
205int wmcodec_mute(int mute) 196int wmcodec_mute(int mute)
206{ 197{
207 int old_irq_level = set_irq_level(HIGHEST_IRQ_LEVEL);
208
209 if (mute) 198 if (mute)
210 { 199 {
211 /* Set DACMU = 1 to soft-mute the audio DACs. */ 200 /* Set DACMU = 1 to soft-mute the audio DACs. */
@@ -215,16 +204,12 @@ int wmcodec_mute(int mute)
215 wm8758_write(DACCTRL, 0x0); 204 wm8758_write(DACCTRL, 0x0);
216 } 205 }
217 206
218 set_irq_level(old_irq_level);
219
220 return 0; 207 return 0;
221} 208}
222 209
223/* Nice shutdown of WM8758 codec */ 210/* Nice shutdown of WM8758 codec */
224void wmcodec_close(void) 211void wmcodec_close(void)
225{ 212{
226 int old_irq_level = set_irq_level(HIGHEST_IRQ_LEVEL);
227
228 wmcodec_mute(1); 213 wmcodec_mute(1);
229 214
230 wm8758_write(PWRMGMT3, 0x0); 215 wm8758_write(PWRMGMT3, 0x0);
@@ -232,8 +217,6 @@ void wmcodec_close(void)
232 wm8758_write(PWRMGMT1, 0x0); 217 wm8758_write(PWRMGMT1, 0x0);
233 218
234 wm8758_write(PWRMGMT2, 0x40); 219 wm8758_write(PWRMGMT2, 0x40);
235
236 set_irq_level(old_irq_level);
237} 220}
238 221
239/* Change the order of the noise shaper, 5th order is recommended above 32kHz */ 222/* Change the order of the noise shaper, 5th order is recommended above 32kHz */
@@ -245,8 +228,6 @@ void wmcodec_set_nsorder(int order)
245/* Note: Disable output before calling this function */ 228/* Note: Disable output before calling this function */
246void wmcodec_set_sample_rate(int sampling_control) 229void wmcodec_set_sample_rate(int sampling_control)
247{ 230{
248 int old_irq_level = set_irq_level(HIGHEST_IRQ_LEVEL);
249
250 /**** We force 44.1KHz for now. ****/ 231 /**** We force 44.1KHz for now. ****/
251 (void)sampling_control; 232 (void)sampling_control;
252 233
@@ -264,8 +245,6 @@ void wmcodec_set_sample_rate(int sampling_control)
264 245
265 /* set srate */ 246 /* set srate */
266 wm8758_write(SRATECTRL, (0 << 1)); 247 wm8758_write(SRATECTRL, (0 << 1));
267
268 set_irq_level(old_irq_level);
269} 248}
270 249
271void wmcodec_enable_recording(bool source_mic) 250void wmcodec_enable_recording(bool source_mic)