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.zip
rockbox-2026c9506cf090b3d0a59f140e0fc4756a792555.tar.gz
rockbox-2026c9506cf090b3d0a59f140e0fc4756a792555.tar.bz2
rockbox-2026c9506cf090b3d0a59f140e0fc4756a792555.tar.xz
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 405acf3..1d03e35 100644
--- a/firmware/target/arm/as3525/ascodec-as3525.c
+++ b/firmware/target/arm/as3525/ascodec-as3525.c
@@ -115,7 +115,7 @@ struct ascodec_request {
static struct mutex as_mtx;
-static int ascodec_enrd0_shadow = 0;
+static unsigned long ascodec_enrd0_shadow = 0;
static unsigned char *req_data_ptr = NULL;
static struct ascodec_request *req_head = NULL;
@@ -160,8 +160,8 @@ static void ascodec_finish_req(struct ascodec_request *req)
*/
while (i2c_busy());
- /* disable clock - already in IRQ context */
- CGU_PERI &= ~CGU_I2C_AUDIO_MASTER_CLOCK_ENABLE;
+ /* disable clock */
+ bitclr32(&CGU_PERI, CGU_I2C_AUDIO_MASTER_CLOCK_ENABLE);
req->status = 1;
@@ -434,6 +434,41 @@ int ascodec_readbytes(unsigned int index, unsigned int len, unsigned char *data)
return i;
}
+#if CONFIG_CPU == AS3525v2
+void ascodec_write_pmu(unsigned int index, unsigned int subreg,
+ unsigned int value)
+{
+ struct ascodec_request reqs[2];
+
+ int oldstatus = disable_irq_save();
+ /* we submit consecutive requests to make sure no operations happen on the
+ * i2c bus between selecting the sub register and writing to it */
+ ascodec_async_write(AS3543_PMU_ENABLE, 8 | subreg, &reqs[0]);
+ ascodec_async_write(index, value, &reqs[1]);
+ restore_irq(oldstatus);
+
+ /* Wait for second request to finish */
+ ascodec_wait(&reqs[1]);
+}
+
+int ascodec_read_pmu(unsigned int index, unsigned int subreg)
+{
+ struct ascodec_request reqs[2];
+
+ int oldstatus = disable_irq_save();
+ /* we submit consecutive requests to make sure no operations happen on the
+ * i2c bus between selecting the sub register and reading it */
+ ascodec_async_write(AS3543_PMU_ENABLE, subreg, &reqs[0]);
+ ascodec_async_read(index, 1, &reqs[1], NULL);
+ restore_irq(oldstatus);
+
+ /* Wait for second request to finish */
+ ascodec_wait(&reqs[1]);
+
+ return reqs[1].data[0];
+}
+#endif /* CONFIG_CPU == AS3525v2 */
+
static void ascodec_read_cb(unsigned const char *data, unsigned int len)
{
if (UNLIKELY(len != 3)) /* some error happened? */
@@ -492,7 +527,7 @@ void ascodec_wait_adc_finished(void)
bool ascodec_endofch(void)
{
bool ret = ascodec_enrd0_shadow & CHG_ENDOFCH;
- ascodec_enrd0_shadow &= ~CHG_ENDOFCH; // clear interrupt
+ bitclr32(&ascodec_enrd0_shadow, CHG_ENDOFCH); /* clear interrupt */
return ret;
}
diff --git a/firmware/target/arm/as3525/ascodec-target.h b/firmware/target/arm/as3525/ascodec-target.h
index 85c3d1c..7e1a3b7 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);
bool ascodec_chg_status(void);
#if CONFIG_CPU == AS3525v2
-static inline void ascodec_write_pmu(unsigned int index, unsigned int subreg,
- unsigned int value)
-{
- /* we disable interrupts to make sure no operation happen on the i2c bus
- * between selecting the sub register and writing to it */
- int oldstatus = disable_irq_save();
- ascodec_write(AS3543_PMU_ENABLE, 8|subreg);
- ascodec_write(index, value);
- restore_irq(oldstatus);
-}
-
-static inline int ascodec_read_pmu(unsigned int index, unsigned int subreg)
-{
- /* we disable interrupts to make sure no operation happen on the i2c bus
- * between selecting the sub register and reading it */
- int oldstatus = disable_irq_save();
- ascodec_write(AS3543_PMU_ENABLE, subreg);
- int ret = ascodec_read(index);
- restore_irq(oldstatus);
- return ret;
-}
+void ascodec_write_pmu(unsigned int index, unsigned int subreg,
+ unsigned int value);
+int ascodec_read_pmu(unsigned int index, unsigned int subreg);
#endif /* CONFIG_CPU == AS3525v2 */
static inline void ascodec_write_charger(int value)