diff options
Diffstat (limited to 'firmware/target')
-rw-r--r-- | firmware/target/arm/as3525/ascodec-as3525.c | 42 |
1 files changed, 25 insertions, 17 deletions
diff --git a/firmware/target/arm/as3525/ascodec-as3525.c b/firmware/target/arm/as3525/ascodec-as3525.c index be81178859..634648afe4 100644 --- a/firmware/target/arm/as3525/ascodec-as3525.c +++ b/firmware/target/arm/as3525/ascodec-as3525.c | |||
@@ -159,21 +159,12 @@ static void ascodec_finish_req(struct ascodec_request *req) | |||
159 | */ | 159 | */ |
160 | while (i2c_busy()); | 160 | while (i2c_busy()); |
161 | 161 | ||
162 | /* disable clock */ | ||
163 | bitclr32(&CGU_PERI, CGU_I2C_AUDIO_MASTER_CLOCK_ENABLE); | ||
164 | |||
165 | req->status = 1; | 162 | req->status = 1; |
166 | 163 | ||
167 | if (req->callback) { | 164 | if (req->callback) { |
168 | req->callback(req->data, req_data_ptr - req->data); | 165 | req->callback(req->data, req_data_ptr - req->data); |
169 | } | 166 | } |
170 | semaphore_release(&req->complete); | 167 | semaphore_release(&req->complete); |
171 | |||
172 | req_head = req->next; | ||
173 | req->next = NULL; | ||
174 | if (req_head == NULL) | ||
175 | req_tail = NULL; | ||
176 | |||
177 | } | 168 | } |
178 | 169 | ||
179 | static int ascodec_continue_req(struct ascodec_request *req, int irq_status) | 170 | static int ascodec_continue_req(struct ascodec_request *req, int irq_status) |
@@ -226,13 +217,12 @@ static void ascodec_start_req(struct ascodec_request *req) | |||
226 | 217 | ||
227 | void INT_I2C_AUDIO(void) | 218 | void INT_I2C_AUDIO(void) |
228 | { | 219 | { |
229 | int irq_status = I2C2_MIS; | 220 | struct ascodec_request *req = req_head; |
230 | int status = REQ_FINISHED; | ||
231 | 221 | ||
232 | if (req_head != NULL) | 222 | int irq_status = I2C2_MIS; |
233 | status = ascodec_continue_req(req_head, irq_status); | 223 | int status = ascodec_continue_req(req, irq_status); |
234 | 224 | ||
235 | I2C2_INT_CLR |= irq_status; /* clear interrupt status */ | 225 | I2C2_INT_CLR = irq_status; /* clear interrupt status */ |
236 | 226 | ||
237 | if (status != REQ_UNFINISHED) { | 227 | if (status != REQ_UNFINISHED) { |
238 | /* mask rx/tx interrupts */ | 228 | /* mask rx/tx interrupts */ |
@@ -240,15 +230,31 @@ void INT_I2C_AUDIO(void) | |||
240 | I2C2_IRQ_RXOVER|I2C2_IRQ_ACKTIMEO); | 230 | I2C2_IRQ_RXOVER|I2C2_IRQ_ACKTIMEO); |
241 | 231 | ||
242 | if (status == REQ_FINISHED) | 232 | if (status == REQ_FINISHED) |
243 | ascodec_finish_req(req_head); | 233 | ascodec_finish_req(req); |
234 | |||
235 | int oldlevel = disable_irq_save(); /* IRQs are stacked */ | ||
244 | 236 | ||
245 | /* | 237 | /* |
246 | * If status == REQ_RETRY, this will restart | 238 | * If status == REQ_RETRY, this will restart |
247 | * the request because we didn't remove it from | 239 | * the request because we didn't remove it from |
248 | * the request list | 240 | * the request list |
249 | */ | 241 | */ |
250 | if (req_head) | 242 | |
243 | if (status == REQ_FINISHED) { | ||
244 | req_head = req->next; | ||
245 | req->next = NULL; | ||
246 | } | ||
247 | |||
248 | if (req_head == NULL) { | ||
249 | req_tail = NULL; | ||
250 | |||
251 | /* disable clock */ | ||
252 | bitclr32(&CGU_PERI, CGU_I2C_AUDIO_MASTER_CLOCK_ENABLE); | ||
253 | } else { | ||
251 | ascodec_start_req(req_head); | 254 | ascodec_start_req(req_head); |
255 | } | ||
256 | |||
257 | restore_irq(oldlevel); | ||
252 | } | 258 | } |
253 | } | 259 | } |
254 | 260 | ||
@@ -278,7 +284,7 @@ void ascodec_init(void) | |||
278 | I2C2_CNTRL = I2C2_CNTRL_DEFAULT; | 284 | I2C2_CNTRL = I2C2_CNTRL_DEFAULT; |
279 | 285 | ||
280 | I2C2_IMR = 0x00; /* disable interrupts */ | 286 | I2C2_IMR = 0x00; /* disable interrupts */ |
281 | I2C2_INT_CLR |= I2C2_RIS; /* clear interrupt status */ | 287 | I2C2_INT_CLR = I2C2_RIS; /* clear interrupt status */ |
282 | VIC_INT_ENABLE = INTERRUPT_I2C_AUDIO; | 288 | VIC_INT_ENABLE = INTERRUPT_I2C_AUDIO; |
283 | VIC_INT_ENABLE = INTERRUPT_AUDIO; | 289 | VIC_INT_ENABLE = INTERRUPT_AUDIO; |
284 | 290 | ||
@@ -338,6 +344,8 @@ static void ascodec_submit(struct ascodec_request *req) | |||
338 | 344 | ||
339 | static void ascodec_wait(struct ascodec_request *req) | 345 | static void ascodec_wait(struct ascodec_request *req) |
340 | { | 346 | { |
347 | /* NOTE: Only safe from thread context */ | ||
348 | |||
341 | if (irq_enabled()) { | 349 | if (irq_enabled()) { |
342 | semaphore_wait(&req->complete, TIMEOUT_BLOCK); | 350 | semaphore_wait(&req->complete, TIMEOUT_BLOCK); |
343 | return; | 351 | return; |