summaryrefslogtreecommitdiffstats
path: root/firmware/target/hosted/ypr0/ascodec-ypr0.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/hosted/ypr0/ascodec-ypr0.c')
-rw-r--r--firmware/target/hosted/ypr0/ascodec-ypr0.c137
1 files changed, 43 insertions, 94 deletions
diff --git a/firmware/target/hosted/ypr0/ascodec-ypr0.c b/firmware/target/hosted/ypr0/ascodec-ypr0.c
index a4e92e6f6b..b3bc48290f 100644
--- a/firmware/target/hosted/ypr0/ascodec-ypr0.c
+++ b/firmware/target/hosted/ypr0/ascodec-ypr0.c
@@ -32,33 +32,36 @@
int afe_dev = -1;
+/* ioctl parameter struct */
+struct codec_req_struct {
+/* This works for every kind of afe.ko module requests */
+ unsigned char reg; /* Main register address */
+ unsigned char subreg; /* Set this only if you are reading/writing a PMU register*/
+ unsigned char value; /* To be read if reading a register; to be set if writing to a register */
+} __attribute__((packed));
+
+
/* Write to a normal register */
-#define IOCTL_REG_WRITE 0x40034101
+#define IOCTL_REG_WRITE 0x40034101
/* Write to a PMU register */
-#define IOCTL_SUBREG_WRITE 0x40034103
+#define IOCTL_SUBREG_WRITE 0x40034103
/* Read from a normal register */
-#define IOCTL_REG_READ 0x80034102
+#define IOCTL_REG_READ 0x80034102
/* Read from a PMU register */
-#define IOCTL_SUBREG_READ 0x80034103
-
-static struct mutex as_mtx;
+#define IOCTL_SUBREG_READ 0x80034103
-int ascodec_init(void) {
+int ascodec_init(void)
+{
afe_dev = open("/dev/afe", O_RDWR);
-
- mutex_init(&as_mtx);
-
return afe_dev;
-
}
-void ascodec_close(void) {
-
+void ascodec_close(void)
+{
if (afe_dev >= 0) {
close(afe_dev);
}
-
}
/* Read functions returns -1 if fail, otherwise the register's value if success */
@@ -66,24 +69,16 @@ void ascodec_close(void) {
int ascodec_write(unsigned int reg, unsigned int value)
{
- struct codec_req_struct y;
- struct codec_req_struct *p;
- p = &y;
- p->reg = reg;
- p->value = value;
- return ioctl(afe_dev, IOCTL_REG_WRITE, p);
+ struct codec_req_struct r = { .reg = reg, .value = value };
+ return ioctl(afe_dev, IOCTL_REG_WRITE, &r);
}
int ascodec_read(unsigned int reg)
{
- int retval = -1;
- struct codec_req_struct y;
- struct codec_req_struct *p;
- p = &y;
- p->reg = reg;
- retval = ioctl(afe_dev, IOCTL_REG_READ, p);
+ struct codec_req_struct r = { .reg = reg };
+ int retval = ioctl(afe_dev, IOCTL_REG_READ, &r);
if (retval >= 0)
- return p->value;
+ return r.value;
else
return retval;
}
@@ -91,114 +86,68 @@ int ascodec_read(unsigned int reg)
void ascodec_write_pmu(unsigned int index, unsigned int subreg,
unsigned int value)
{
- struct codec_req_struct y;
- struct codec_req_struct *p;
- p = &y;
- p->reg = index;
- p->subreg = subreg;
- p->value = value;
- ioctl(afe_dev, IOCTL_SUBREG_WRITE, p);
+ struct codec_req_struct r = {.reg = index, .subreg = subreg, .value = value};
+ ioctl(afe_dev, IOCTL_SUBREG_WRITE, &r);
}
int ascodec_read_pmu(unsigned int index, unsigned int subreg)
{
- int retval = -1;
- struct codec_req_struct y;
- struct codec_req_struct *p;
- p = &y;
- p->reg = index;
- p->subreg = subreg;
- retval = ioctl(afe_dev, IOCTL_SUBREG_READ, p);
+ struct codec_req_struct r = { .reg = index, .subreg = subreg, };
+ int retval = ioctl(afe_dev, IOCTL_SUBREG_READ, &r);
if (retval >= 0)
- return p->value;
+ return r.value;
else
return retval;
}
-/* Helpers to set/clear bits */
-void ascodec_set(unsigned int reg, unsigned int bits)
-{
- ascodec_write(reg, ascodec_read(reg) | bits);
-}
-
-void ascodec_clear(unsigned int reg, unsigned int bits)
-{
- ascodec_write(reg, ascodec_read(reg) & ~bits);
-}
-
-void ascodec_write_masked(unsigned int reg, unsigned int bits,
- unsigned int mask)
-{
- ascodec_write(reg, (ascodec_read(reg) & ~mask) | (bits & mask));
-}
-
-/*FIXME: doesn't work */
int ascodec_readbytes(unsigned int index, unsigned int len, unsigned char *data)
{
- unsigned int i;
+ int i, val, ret = 0;
- for (i=index; i<len; i++) {
- data[i] = ascodec_read(i);
- printf("Register %i: value=%i\n",index,data[i]);
+ for (i = index; i < (int)len; i++) {
+ val = ascodec_read(i);
+ if (val >= 0) data[i] = val;
+ else ret = -1;
}
- printf("TOTAL: %i\n", i);
-
- return i;
+ return ret ?: i; /* i means success */
}
/*
* NOTE:
* After the conversion to interrupts, ascodec_(lock|unlock) are only used by
* adc-as3514.c to protect against other threads corrupting the result by using
- * the ADC at the same time.
+ * the ADC at the same time. this adc_read() doesn't yield but blocks, so
+ * lock/unlock is not needed
*
- * Concurrent ascodec_(async_)?(read|write) calls are instead protected
- * by the R0's Kernel I2C driver for ascodec (mutexed), so it's automatically safe
+ * Additionally, concurrent ascodec_?(read|write) calls are instead protected
+ * by the R0's Kernel I2C driver for ascodec (mutexed), so it's automatically
+ * safe
*/
void ascodec_lock(void)
{
- mutex_lock(&as_mtx);
}
void ascodec_unlock(void)
{
- mutex_unlock(&as_mtx);
}
/* Read 10-bit channel data */
unsigned short adc_read(int channel)
{
- unsigned short data = 0;
-
if ((unsigned)channel >= NUM_ADC_CHANNELS)
return 0;
- ascodec_lock();
-
/* Select channel */
ascodec_write(AS3514_ADC_0, (channel << 4));
unsigned char buf[2];
- /*
- * The AS3514 ADC will trigger an interrupt when the conversion
- * is finished, if the corresponding enable bit in IRQ_ENRD2
- * is set.
- * Previously the code did not wait and this apparently did
- * not pose any problems, but this should be more correct.
- * Without the wait the data read back may be completely or
- * partially (first one of the two bytes) stale.
- */
- /*FIXME: not implemented*/
- ascodec_wait_adc_finished();
-
- /* Read data */
- ascodec_readbytes(AS3514_ADC_0, 2, buf);
- data = (((buf[0] & 0x3) << 8) | buf[1]);
-
- ascodec_unlock();
- return data;
+ /* Read data */
+ ascodec_readbytes(AS3514_ADC_0, sizeof(buf), buf);
+
+ /* decode to 10-bit and return */
+ return (((buf[0] & 0x3) << 8) | buf[1]);
}
void adc_init(void)