summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2011-12-15 03:30:03 +0000
committerMichael Sevakis <jethead71@rockbox.org>2011-12-15 03:30:03 +0000
commit2026c9506cf090b3d0a59f140e0fc4756a792555 (patch)
treec34f986e8fd2ced2b0e2981a4e7c62e0cfb611ee
parent47bade1437d5281a5aca0ec8b2b9a3956f88f685 (diff)
downloadrockbox-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.c43
-rw-r--r--firmware/target/arm/as3525/ascodec-target.h24
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
116static struct mutex as_mtx; 116static struct mutex as_mtx;
117 117
118static int ascodec_enrd0_shadow = 0; 118static unsigned long ascodec_enrd0_shadow = 0;
119 119
120static unsigned char *req_data_ptr = NULL; 120static unsigned char *req_data_ptr = NULL;
121static struct ascodec_request *req_head = NULL; 121static 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
438void 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
454int 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
437static void ascodec_read_cb(unsigned const char *data, unsigned int len) 472static 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)
492bool ascodec_endofch(void) 527bool 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);
67bool ascodec_chg_status(void); 67bool ascodec_chg_status(void);
68 68
69#if CONFIG_CPU == AS3525v2 69#if CONFIG_CPU == AS3525v2
70static inline void ascodec_write_pmu(unsigned int index, unsigned int subreg, 70void ascodec_write_pmu(unsigned int index, unsigned int subreg,
71 unsigned int value) 71 unsigned int value);
72{ 72int 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
81static 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
93static inline void ascodec_write_charger(int value) 75static inline void ascodec_write_charger(int value)