diff options
author | Michael Sevakis <jethead71@rockbox.org> | 2011-12-15 03:30:03 +0000 |
---|---|---|
committer | Michael Sevakis <jethead71@rockbox.org> | 2011-12-15 03:30:03 +0000 |
commit | 2026c9506cf090b3d0a59f140e0fc4756a792555 (patch) | |
tree | c34f986e8fd2ced2b0e2981a4e7c62e0cfb611ee | |
parent | 47bade1437d5281a5aca0ec8b2b9a3956f88f685 (diff) | |
download | rockbox-2026c9506cf090b3d0a59f140e0fc4756a792555.tar.gz rockbox-2026c9506cf090b3d0a59f140e0fc4756a792555.zip |
Commit the ascodec-as3525.c/ascodec-target.h changes from FS#12452 that keep ascodec_read/write_pmu from keeping interrupts disabled for the full duration of two I2C transfers, which can contribute to I2S PUSH/POP FIFO under/over-flows. 'Tis peppered with a couple interrupt safety mods as well.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@31264 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r-- | firmware/target/arm/as3525/ascodec-as3525.c | 43 | ||||
-rw-r--r-- | firmware/target/arm/as3525/ascodec-target.h | 24 |
2 files changed, 42 insertions, 25 deletions
diff --git a/firmware/target/arm/as3525/ascodec-as3525.c b/firmware/target/arm/as3525/ascodec-as3525.c index 405acf3ca0..1d03e350c8 100644 --- a/firmware/target/arm/as3525/ascodec-as3525.c +++ b/firmware/target/arm/as3525/ascodec-as3525.c | |||
@@ -115,7 +115,7 @@ struct ascodec_request { | |||
115 | 115 | ||
116 | static struct mutex as_mtx; | 116 | static struct mutex as_mtx; |
117 | 117 | ||
118 | static int ascodec_enrd0_shadow = 0; | 118 | static unsigned long ascodec_enrd0_shadow = 0; |
119 | 119 | ||
120 | static unsigned char *req_data_ptr = NULL; | 120 | static unsigned char *req_data_ptr = NULL; |
121 | static struct ascodec_request *req_head = NULL; | 121 | static struct ascodec_request *req_head = NULL; |
@@ -160,8 +160,8 @@ static void ascodec_finish_req(struct ascodec_request *req) | |||
160 | */ | 160 | */ |
161 | while (i2c_busy()); | 161 | while (i2c_busy()); |
162 | 162 | ||
163 | /* disable clock - already in IRQ context */ | 163 | /* disable clock */ |
164 | CGU_PERI &= ~CGU_I2C_AUDIO_MASTER_CLOCK_ENABLE; | 164 | bitclr32(&CGU_PERI, CGU_I2C_AUDIO_MASTER_CLOCK_ENABLE); |
165 | 165 | ||
166 | req->status = 1; | 166 | req->status = 1; |
167 | 167 | ||
@@ -434,6 +434,41 @@ int ascodec_readbytes(unsigned int index, unsigned int len, unsigned char *data) | |||
434 | return i; | 434 | return i; |
435 | } | 435 | } |
436 | 436 | ||
437 | #if CONFIG_CPU == AS3525v2 | ||
438 | void ascodec_write_pmu(unsigned int index, unsigned int subreg, | ||
439 | unsigned int value) | ||
440 | { | ||
441 | struct ascodec_request reqs[2]; | ||
442 | |||
443 | int oldstatus = disable_irq_save(); | ||
444 | /* we submit consecutive requests to make sure no operations happen on the | ||
445 | * i2c bus between selecting the sub register and writing to it */ | ||
446 | ascodec_async_write(AS3543_PMU_ENABLE, 8 | subreg, &reqs[0]); | ||
447 | ascodec_async_write(index, value, &reqs[1]); | ||
448 | restore_irq(oldstatus); | ||
449 | |||
450 | /* Wait for second request to finish */ | ||
451 | ascodec_wait(&reqs[1]); | ||
452 | } | ||
453 | |||
454 | int ascodec_read_pmu(unsigned int index, unsigned int subreg) | ||
455 | { | ||
456 | struct ascodec_request reqs[2]; | ||
457 | |||
458 | int oldstatus = disable_irq_save(); | ||
459 | /* we submit consecutive requests to make sure no operations happen on the | ||
460 | * i2c bus between selecting the sub register and reading it */ | ||
461 | ascodec_async_write(AS3543_PMU_ENABLE, subreg, &reqs[0]); | ||
462 | ascodec_async_read(index, 1, &reqs[1], NULL); | ||
463 | restore_irq(oldstatus); | ||
464 | |||
465 | /* Wait for second request to finish */ | ||
466 | ascodec_wait(&reqs[1]); | ||
467 | |||
468 | return reqs[1].data[0]; | ||
469 | } | ||
470 | #endif /* CONFIG_CPU == AS3525v2 */ | ||
471 | |||
437 | static void ascodec_read_cb(unsigned const char *data, unsigned int len) | 472 | static void ascodec_read_cb(unsigned const char *data, unsigned int len) |
438 | { | 473 | { |
439 | if (UNLIKELY(len != 3)) /* some error happened? */ | 474 | if (UNLIKELY(len != 3)) /* some error happened? */ |
@@ -492,7 +527,7 @@ void ascodec_wait_adc_finished(void) | |||
492 | bool ascodec_endofch(void) | 527 | bool ascodec_endofch(void) |
493 | { | 528 | { |
494 | bool ret = ascodec_enrd0_shadow & CHG_ENDOFCH; | 529 | bool ret = ascodec_enrd0_shadow & CHG_ENDOFCH; |
495 | ascodec_enrd0_shadow &= ~CHG_ENDOFCH; // clear interrupt | 530 | bitclr32(&ascodec_enrd0_shadow, CHG_ENDOFCH); /* clear interrupt */ |
496 | return ret; | 531 | return ret; |
497 | } | 532 | } |
498 | 533 | ||
diff --git a/firmware/target/arm/as3525/ascodec-target.h b/firmware/target/arm/as3525/ascodec-target.h index 85c3d1c103..7e1a3b7424 100644 --- a/firmware/target/arm/as3525/ascodec-target.h +++ b/firmware/target/arm/as3525/ascodec-target.h | |||
@@ -67,27 +67,9 @@ bool ascodec_endofch(void); | |||
67 | bool ascodec_chg_status(void); | 67 | bool ascodec_chg_status(void); |
68 | 68 | ||
69 | #if CONFIG_CPU == AS3525v2 | 69 | #if CONFIG_CPU == AS3525v2 |
70 | static inline void ascodec_write_pmu(unsigned int index, unsigned int subreg, | 70 | void ascodec_write_pmu(unsigned int index, unsigned int subreg, |
71 | unsigned int value) | 71 | unsigned int value); |
72 | { | 72 | int ascodec_read_pmu(unsigned int index, unsigned int subreg); |
73 | /* we disable interrupts to make sure no operation happen on the i2c bus | ||
74 | * between selecting the sub register and writing to it */ | ||
75 | int oldstatus = disable_irq_save(); | ||
76 | ascodec_write(AS3543_PMU_ENABLE, 8|subreg); | ||
77 | ascodec_write(index, value); | ||
78 | restore_irq(oldstatus); | ||
79 | } | ||
80 | |||
81 | static inline int ascodec_read_pmu(unsigned int index, unsigned int subreg) | ||
82 | { | ||
83 | /* we disable interrupts to make sure no operation happen on the i2c bus | ||
84 | * between selecting the sub register and reading it */ | ||
85 | int oldstatus = disable_irq_save(); | ||
86 | ascodec_write(AS3543_PMU_ENABLE, subreg); | ||
87 | int ret = ascodec_read(index); | ||
88 | restore_irq(oldstatus); | ||
89 | return ret; | ||
90 | } | ||
91 | #endif /* CONFIG_CPU == AS3525v2 */ | 73 | #endif /* CONFIG_CPU == AS3525v2 */ |
92 | 74 | ||
93 | static inline void ascodec_write_charger(int value) | 75 | static inline void ascodec_write_charger(int value) |