mirror of
https://github.com/Rockbox/rockbox.git
synced 2025-12-08 20:55:17 -05:00
as3525 ascodec: make internal functions statics and remove some details for ascodec-target.h header
reorder static functions to avoid the need for early prototypes panic if the INT_AUDIO callback could not read the 3 IRQ_ENRD registers git-svn-id: svn://svn.rockbox.org/rockbox/trunk@26445 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
dc32a5b14c
commit
df34a4767f
2 changed files with 125 additions and 156 deletions
|
|
@ -88,6 +88,31 @@
|
||||||
#define IFDEBUG(x)
|
#define IFDEBUG(x)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define ASCODEC_REQ_READ 0
|
||||||
|
#define ASCODEC_REQ_WRITE 1
|
||||||
|
|
||||||
|
/*
|
||||||
|
* How many bytes we using in struct ascodec_request for the data buffer.
|
||||||
|
* 4 fits the alignment best right now.
|
||||||
|
* We don't actually use more than 3 at the moment (when reading interrupts)
|
||||||
|
* Upper limit would be 255 since DACNT is 8 bits!
|
||||||
|
*/
|
||||||
|
#define ASCODEC_REQ_MAXLEN 4
|
||||||
|
|
||||||
|
typedef void (ascodec_cb_fn)(unsigned const char *data, unsigned cnt);
|
||||||
|
|
||||||
|
struct ascodec_request {
|
||||||
|
unsigned char type;
|
||||||
|
unsigned char index;
|
||||||
|
unsigned char status;
|
||||||
|
unsigned char cnt;
|
||||||
|
unsigned char data[ASCODEC_REQ_MAXLEN];
|
||||||
|
struct wakeup wkup;
|
||||||
|
ascodec_cb_fn *callback;
|
||||||
|
struct ascodec_request *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
static struct mutex as_mtx;
|
static struct mutex as_mtx;
|
||||||
|
|
||||||
static int ascodec_enrd0_shadow = 0;
|
static int ascodec_enrd0_shadow = 0;
|
||||||
|
|
@ -110,18 +135,94 @@ static int int_rtc = 0;
|
||||||
static int int_adc = 0;
|
static int int_adc = 0;
|
||||||
#endif /* DEBUG */
|
#endif /* DEBUG */
|
||||||
|
|
||||||
static void ascodec_read_cb(unsigned const char *data, unsigned int len);
|
/* returns != 0 when busy */
|
||||||
|
static inline int i2c_busy(void)
|
||||||
static void ascodec_start_req(struct ascodec_request *req);
|
|
||||||
static int ascodec_continue_req(struct ascodec_request *req, int irq_status);
|
|
||||||
static void ascodec_finish_req(struct ascodec_request *req);
|
|
||||||
|
|
||||||
void INT_AUDIO(void)
|
|
||||||
{
|
{
|
||||||
VIC_INT_EN_CLEAR = INTERRUPT_AUDIO;
|
return (I2C2_SR & 1);
|
||||||
IFDEBUG(int_audio_ctr++);
|
}
|
||||||
|
|
||||||
ascodec_async_read(AS3514_IRQ_ENRD0, 3, &as_audio_req, ascodec_read_cb);
|
static void ascodec_finish_req(struct ascodec_request *req)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Wait if still busy, unfortunately this happens since
|
||||||
|
* the controller is running at a low divisor, so it's
|
||||||
|
* still busy when we serviced the interrupt.
|
||||||
|
* I tried upping the i2c speed to 4MHz which
|
||||||
|
* made the number of busywait cycles much smaller
|
||||||
|
* (none for reads and only a few for writes),
|
||||||
|
* but who knows if it's reliable at that frequency. ;)
|
||||||
|
* For one thing, 8MHz doesn't work, so 4MHz is likely
|
||||||
|
* borderline.
|
||||||
|
* In general writes need much more wait cycles than reads
|
||||||
|
* for some reason, possibly because we read the data register
|
||||||
|
* for reads, which will likely block the processor while
|
||||||
|
* the i2c controller responds to the register read.
|
||||||
|
*/
|
||||||
|
while (i2c_busy());
|
||||||
|
|
||||||
|
/* disable clock */
|
||||||
|
CGU_PERI &= ~CGU_I2C_AUDIO_MASTER_CLOCK_ENABLE;
|
||||||
|
|
||||||
|
req->status = 1;
|
||||||
|
|
||||||
|
if (req->callback) {
|
||||||
|
req->callback(req->data, req_data_ptr - req->data);
|
||||||
|
}
|
||||||
|
wakeup_signal(&req->wkup);
|
||||||
|
|
||||||
|
req_head = req->next;
|
||||||
|
req->next = NULL;
|
||||||
|
if (req_head == NULL)
|
||||||
|
req_tail = NULL;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ascodec_continue_req(struct ascodec_request *req, int irq_status)
|
||||||
|
{
|
||||||
|
if ((irq_status & (I2C2_IRQ_RXOVER|I2C2_IRQ_ACKTIMEO)) > 0) {
|
||||||
|
/* some error occured, restart the request */
|
||||||
|
return REQ_RETRY;
|
||||||
|
}
|
||||||
|
if (req->type == ASCODEC_REQ_READ &&
|
||||||
|
(irq_status & I2C2_IRQ_RXFULL) > 0) {
|
||||||
|
*(req_data_ptr++) = I2C2_DATA;
|
||||||
|
} else {
|
||||||
|
if (req->cnt > 1 &&
|
||||||
|
(irq_status & I2C2_IRQ_TXEMPTY) > 0) {
|
||||||
|
I2C2_DATA = *(req_data_ptr++);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
req->index++;
|
||||||
|
if (--req->cnt > 0)
|
||||||
|
return REQ_UNFINISHED;
|
||||||
|
|
||||||
|
return REQ_FINISHED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ascodec_start_req(struct ascodec_request *req)
|
||||||
|
{
|
||||||
|
int unmask = 0;
|
||||||
|
|
||||||
|
/* enable clock */
|
||||||
|
CGU_PERI |= CGU_I2C_AUDIO_MASTER_CLOCK_ENABLE;
|
||||||
|
|
||||||
|
/* start transfer */
|
||||||
|
I2C2_SADDR = req->index;
|
||||||
|
if (req->type == ASCODEC_REQ_READ) {
|
||||||
|
req_data_ptr = req->data;
|
||||||
|
/* start transfer */
|
||||||
|
I2C2_CNTRL = I2C2_CNTRL_DEFAULT | I2C2_CNTRL_READ;
|
||||||
|
unmask = I2C2_IRQ_RXFULL|I2C2_IRQ_RXOVER;
|
||||||
|
} else {
|
||||||
|
req_data_ptr = &req->data[1];
|
||||||
|
I2C2_CNTRL = I2C2_CNTRL_DEFAULT | I2C2_CNTRL_WRITE;
|
||||||
|
I2C2_DATA = req->data[0];
|
||||||
|
unmask = I2C2_IRQ_TXEMPTY|I2C2_IRQ_ACKTIMEO;
|
||||||
|
}
|
||||||
|
|
||||||
|
I2C2_DACNT = req->cnt;
|
||||||
|
I2C2_IMR |= unmask; /* enable interrupts */
|
||||||
}
|
}
|
||||||
|
|
||||||
void INT_I2C_AUDIO(void)
|
void INT_I2C_AUDIO(void)
|
||||||
|
|
@ -207,13 +308,7 @@ void ascodec_init(void)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* returns != 0 when busy */
|
static void ascodec_req_init(struct ascodec_request *req, int type,
|
||||||
static int i2c_busy(void)
|
|
||||||
{
|
|
||||||
return (I2C2_SR & 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ascodec_req_init(struct ascodec_request *req, int type,
|
|
||||||
unsigned int index, unsigned int cnt)
|
unsigned int index, unsigned int cnt)
|
||||||
{
|
{
|
||||||
wakeup_init(&req->wkup);
|
wakeup_init(&req->wkup);
|
||||||
|
|
@ -224,7 +319,7 @@ void ascodec_req_init(struct ascodec_request *req, int type,
|
||||||
req->cnt = cnt;
|
req->cnt = cnt;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ascodec_submit(struct ascodec_request *req)
|
static void ascodec_submit(struct ascodec_request *req)
|
||||||
{
|
{
|
||||||
int oldlevel = disable_irq_save();
|
int oldlevel = disable_irq_save();
|
||||||
|
|
||||||
|
|
@ -241,90 +336,6 @@ void ascodec_submit(struct ascodec_request *req)
|
||||||
restore_irq(oldlevel);
|
restore_irq(oldlevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ascodec_start_req(struct ascodec_request *req)
|
|
||||||
{
|
|
||||||
int unmask = 0;
|
|
||||||
|
|
||||||
/* enable clock */
|
|
||||||
CGU_PERI |= CGU_I2C_AUDIO_MASTER_CLOCK_ENABLE;
|
|
||||||
|
|
||||||
/* start transfer */
|
|
||||||
I2C2_SADDR = req->index;
|
|
||||||
if (req->type == ASCODEC_REQ_READ) {
|
|
||||||
req_data_ptr = req->data;
|
|
||||||
/* start transfer */
|
|
||||||
I2C2_CNTRL = I2C2_CNTRL_DEFAULT | I2C2_CNTRL_READ;
|
|
||||||
unmask = I2C2_IRQ_RXFULL|I2C2_IRQ_RXOVER;
|
|
||||||
} else {
|
|
||||||
req_data_ptr = &req->data[1];
|
|
||||||
I2C2_CNTRL = I2C2_CNTRL_DEFAULT | I2C2_CNTRL_WRITE;
|
|
||||||
I2C2_DATA = req->data[0];
|
|
||||||
unmask = I2C2_IRQ_TXEMPTY|I2C2_IRQ_ACKTIMEO;
|
|
||||||
}
|
|
||||||
|
|
||||||
I2C2_DACNT = req->cnt;
|
|
||||||
I2C2_IMR |= unmask; /* enable interrupts */
|
|
||||||
}
|
|
||||||
|
|
||||||
static int ascodec_continue_req(struct ascodec_request *req, int irq_status)
|
|
||||||
{
|
|
||||||
if ((irq_status & (I2C2_IRQ_RXOVER|I2C2_IRQ_ACKTIMEO)) > 0) {
|
|
||||||
/* some error occured, restart the request */
|
|
||||||
return REQ_RETRY;
|
|
||||||
}
|
|
||||||
if (req->type == ASCODEC_REQ_READ &&
|
|
||||||
(irq_status & I2C2_IRQ_RXFULL) > 0) {
|
|
||||||
*(req_data_ptr++) = I2C2_DATA;
|
|
||||||
} else {
|
|
||||||
if (req->cnt > 1 &&
|
|
||||||
(irq_status & I2C2_IRQ_TXEMPTY) > 0) {
|
|
||||||
I2C2_DATA = *(req_data_ptr++);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
req->index++;
|
|
||||||
if (--req->cnt > 0)
|
|
||||||
return REQ_UNFINISHED;
|
|
||||||
|
|
||||||
return REQ_FINISHED;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ascodec_finish_req(struct ascodec_request *req)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Wait if still busy, unfortunately this happens since
|
|
||||||
* the controller is running at a low divisor, so it's
|
|
||||||
* still busy when we serviced the interrupt.
|
|
||||||
* I tried upping the i2c speed to 4MHz which
|
|
||||||
* made the number of busywait cycles much smaller
|
|
||||||
* (none for reads and only a few for writes),
|
|
||||||
* but who knows if it's reliable at that frequency. ;)
|
|
||||||
* For one thing, 8MHz doesn't work, so 4MHz is likely
|
|
||||||
* borderline.
|
|
||||||
* In general writes need much more wait cycles than reads
|
|
||||||
* for some reason, possibly because we read the data register
|
|
||||||
* for reads, which will likely block the processor while
|
|
||||||
* the i2c controller responds to the register read.
|
|
||||||
*/
|
|
||||||
while (i2c_busy());
|
|
||||||
|
|
||||||
/* disable clock */
|
|
||||||
CGU_PERI &= ~CGU_I2C_AUDIO_MASTER_CLOCK_ENABLE;
|
|
||||||
|
|
||||||
req->status = 1;
|
|
||||||
|
|
||||||
if (req->callback) {
|
|
||||||
req->callback(req->data, req_data_ptr - req->data);
|
|
||||||
}
|
|
||||||
wakeup_signal(&req->wkup);
|
|
||||||
|
|
||||||
req_head = req->next;
|
|
||||||
req->next = NULL;
|
|
||||||
if (req_head == NULL)
|
|
||||||
req_tail = NULL;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static int irq_disabled(void)
|
static int irq_disabled(void)
|
||||||
{
|
{
|
||||||
unsigned long cpsr;
|
unsigned long cpsr;
|
||||||
|
|
@ -350,9 +361,8 @@ static void ascodec_wait(struct ascodec_request *req)
|
||||||
* The request struct passed in must be allocated statically.
|
* The request struct passed in must be allocated statically.
|
||||||
* If you call ascodec_async_write from different places, each
|
* If you call ascodec_async_write from different places, each
|
||||||
* call needs it's own request struct.
|
* call needs it's own request struct.
|
||||||
* This comment is duplicated in .c and .h for your convenience.
|
|
||||||
*/
|
*/
|
||||||
void ascodec_async_write(unsigned int index, unsigned int value,
|
static void ascodec_async_write(unsigned int index, unsigned int value,
|
||||||
struct ascodec_request *req)
|
struct ascodec_request *req)
|
||||||
{
|
{
|
||||||
if (index == AS3514_CVDD_DCDC3) /* prevent setting of the LREG_CP_not bit */
|
if (index == AS3514_CVDD_DCDC3) /* prevent setting of the LREG_CP_not bit */
|
||||||
|
|
@ -380,9 +390,8 @@ int ascodec_write(unsigned int index, unsigned int value)
|
||||||
* call needs it's own request struct.
|
* call needs it's own request struct.
|
||||||
* If len is bigger than ASCODEC_REQ_MAXLEN it will be
|
* If len is bigger than ASCODEC_REQ_MAXLEN it will be
|
||||||
* set to ASCODEC_REQ_MAXLEN.
|
* set to ASCODEC_REQ_MAXLEN.
|
||||||
* This comment is duplicated in .c and .h for your convenience.
|
|
||||||
*/
|
*/
|
||||||
void ascodec_async_read(unsigned int index, unsigned int len,
|
static void ascodec_async_read(unsigned int index, unsigned int len,
|
||||||
struct ascodec_request *req, ascodec_cb_fn *cb)
|
struct ascodec_request *req, ascodec_cb_fn *cb)
|
||||||
{
|
{
|
||||||
if (len > ASCODEC_REQ_MAXLEN)
|
if (len > ASCODEC_REQ_MAXLEN)
|
||||||
|
|
@ -433,8 +442,8 @@ int ascodec_readbytes(unsigned int index, unsigned int len, unsigned char *data)
|
||||||
|
|
||||||
static void ascodec_read_cb(unsigned const char *data, unsigned int len)
|
static void ascodec_read_cb(unsigned const char *data, unsigned int len)
|
||||||
{
|
{
|
||||||
if (len != 3) /* some error happened? */
|
if (UNLIKELY(len != 3)) /* some error happened? */
|
||||||
return;
|
panicf("INT_AUDIO callback got %d regs", len);
|
||||||
|
|
||||||
if (data[0] & CHG_ENDOFCH) { /* chg finished */
|
if (data[0] & CHG_ENDOFCH) { /* chg finished */
|
||||||
ascodec_enrd0_shadow |= CHG_ENDOFCH;
|
ascodec_enrd0_shadow |= CHG_ENDOFCH;
|
||||||
|
|
@ -472,6 +481,14 @@ static void ascodec_read_cb(unsigned const char *data, unsigned int len)
|
||||||
VIC_INT_ENABLE = INTERRUPT_AUDIO;
|
VIC_INT_ENABLE = INTERRUPT_AUDIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void INT_AUDIO(void)
|
||||||
|
{
|
||||||
|
VIC_INT_EN_CLEAR = INTERRUPT_AUDIO;
|
||||||
|
IFDEBUG(int_audio_ctr++);
|
||||||
|
|
||||||
|
ascodec_async_read(AS3514_IRQ_ENRD0, 3, &as_audio_req, ascodec_read_cb);
|
||||||
|
}
|
||||||
|
|
||||||
void ascodec_wait_adc_finished(void)
|
void ascodec_wait_adc_finished(void)
|
||||||
{
|
{
|
||||||
wakeup_wait(&adc_wkup, TIMEOUT_BLOCK);
|
wakeup_wait(&adc_wkup, TIMEOUT_BLOCK);
|
||||||
|
|
|
||||||
|
|
@ -46,30 +46,6 @@
|
||||||
#define CVDD_1_10 2
|
#define CVDD_1_10 2
|
||||||
#define CVDD_1_05 3
|
#define CVDD_1_05 3
|
||||||
|
|
||||||
#define ASCODEC_REQ_READ 0
|
|
||||||
#define ASCODEC_REQ_WRITE 1
|
|
||||||
|
|
||||||
/*
|
|
||||||
* How many bytes we using in struct ascodec_request for the data buffer.
|
|
||||||
* 4 fits the alignment best right now.
|
|
||||||
* We don't actually use more than 3 at the moment (when reading interrupts)
|
|
||||||
* Upper limit would be 255 since DACNT is 8 bits!
|
|
||||||
*/
|
|
||||||
#define ASCODEC_REQ_MAXLEN 4
|
|
||||||
|
|
||||||
typedef void (ascodec_cb_fn)(unsigned const char *data, unsigned cnt);
|
|
||||||
|
|
||||||
struct ascodec_request {
|
|
||||||
unsigned char type;
|
|
||||||
unsigned char index;
|
|
||||||
unsigned char status;
|
|
||||||
unsigned char cnt;
|
|
||||||
unsigned char data[ASCODEC_REQ_MAXLEN];
|
|
||||||
struct wakeup wkup;
|
|
||||||
ascodec_cb_fn *callback;
|
|
||||||
struct ascodec_request *next;
|
|
||||||
};
|
|
||||||
|
|
||||||
void ascodec_init(void) INIT_ATTR;
|
void ascodec_init(void) INIT_ATTR;
|
||||||
|
|
||||||
int ascodec_write(unsigned int index, unsigned int value);
|
int ascodec_write(unsigned int index, unsigned int value);
|
||||||
|
|
@ -78,30 +54,6 @@ int ascodec_read(unsigned int index);
|
||||||
|
|
||||||
int ascodec_readbytes(unsigned int index, unsigned int len, unsigned char *data);
|
int ascodec_readbytes(unsigned int index, unsigned int len, unsigned char *data);
|
||||||
|
|
||||||
/*
|
|
||||||
* The request struct passed in must be allocated statically.
|
|
||||||
* If you call ascodec_async_write from different places, each
|
|
||||||
* call needs it's own request struct.
|
|
||||||
* This comment is duplicated in .c and .h for your convenience.
|
|
||||||
*/
|
|
||||||
void ascodec_async_write(unsigned index, unsigned int value, struct ascodec_request *req);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The request struct passed in must be allocated statically.
|
|
||||||
* If you call ascodec_async_read from different places, each
|
|
||||||
* call needs it's own request struct.
|
|
||||||
* If len is bigger than ASCODEC_REQ_MAXLEN it will be
|
|
||||||
* set to ASCODEC_REQ_MAXLEN.
|
|
||||||
* This comment is duplicated in .c and .h for your convenience.
|
|
||||||
*/
|
|
||||||
void ascodec_async_read(unsigned index, unsigned int len,
|
|
||||||
struct ascodec_request *req, ascodec_cb_fn *cb);
|
|
||||||
|
|
||||||
void ascodec_req_init(struct ascodec_request *req, int type,
|
|
||||||
unsigned int index, unsigned int cnt);
|
|
||||||
|
|
||||||
void ascodec_submit(struct ascodec_request *req);
|
|
||||||
|
|
||||||
void ascodec_lock(void);
|
void ascodec_lock(void);
|
||||||
|
|
||||||
void ascodec_unlock(void);
|
void ascodec_unlock(void);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue