1
0
Fork 0
forked from len0rd/rockbox

ypr0: Cleanup and simplify ascodec functions. Fix audiohw_{pre,post}init() not being called.

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@31423 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Thomas Martitz 2011-12-24 17:59:43 +00:00
parent 2ec443df12
commit a1d3ed2534
4 changed files with 48 additions and 134 deletions

View file

@ -78,13 +78,12 @@ const struct sound_settings_info audiohw_settings[] = {
#endif #endif
}; };
#ifndef SAMSUNG_YPR0
/* Shadow registers */ /* Shadow registers */
static uint8_t as3514_regs[AS3514_NUM_AUDIO_REGS]; /* 8-bit registers */ static uint8_t as3514_regs[AS3514_NUM_AUDIO_REGS]; /* 8-bit registers */
/* /*
* little helper method to set register values. * little helper method to set register values.
* With the help of as3514_regs, we minimize i2c * With the help of as3514_regs, we minimize i2c/syscall
* traffic. * traffic.
*/ */
static void as3514_write(unsigned int reg, unsigned int value) static void as3514_write(unsigned int reg, unsigned int value)
@ -111,29 +110,7 @@ static void as3514_write_masked(unsigned int reg, unsigned int bits,
{ {
as3514_write(reg, (as3514_regs[reg] & ~mask) | (bits & mask)); as3514_write(reg, (as3514_regs[reg] & ~mask) | (bits & mask));
} }
#else
static void as3514_write(unsigned int reg, unsigned int value)
{
ascodec_write(reg, value);
}
/* Helpers to set/clear bits */
static void as3514_set(unsigned int reg, unsigned int bits)
{
ascodec_write(reg, ascodec_read(reg) | bits);
}
static void as3514_clear(unsigned int reg, unsigned int bits)
{
ascodec_write(reg, ascodec_read(reg) & ~bits);
}
static void as3514_write_masked(unsigned int reg, unsigned int bits,
unsigned int mask)
{
ascodec_write(reg, (ascodec_read(reg) & ~mask) | (bits & mask));
}
#endif
/* convert tenth of dB volume to master volume register value */ /* convert tenth of dB volume to master volume register value */
int tenthdb2master(int db) int tenthdb2master(int db)
{ {
@ -168,11 +145,8 @@ int sound_val2phys(int setting, int value)
*/ */
void audiohw_preinit(void) void audiohw_preinit(void)
{ {
#ifndef SAMSUNG_YPR0
/* read all reg values */ /* read all reg values */
ascodec_readbytes(0x0, AS3514_NUM_AUDIO_REGS, as3514_regs); ascodec_readbytes(0x0, AS3514_NUM_AUDIO_REGS, as3514_regs);
#endif
#ifdef HAVE_AS3543 #ifdef HAVE_AS3543

View file

@ -50,6 +50,7 @@
#include "pcm-internal.h" #include "pcm-internal.h"
#include "pcm_mixer.h" #include "pcm_mixer.h"
#include "pcm_sampr.h" #include "pcm_sampr.h"
#include "audiohw.h"
#include <pthread.h> #include <pthread.h>
#include <signal.h> #include <signal.h>
@ -320,7 +321,7 @@ void cleanup(void)
void pcm_play_dma_init(void) void pcm_play_dma_init(void)
{ {
int err; int err;
audiohw_preinit();
if ((err = snd_pcm_open(&handle, device, SND_PCM_STREAM_PLAYBACK, 0)) < 0) if ((err = snd_pcm_open(&handle, device, SND_PCM_STREAM_PLAYBACK, 0)) < 0)
{ {
@ -343,6 +344,8 @@ void pcm_play_dma_init(void)
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
pcm_dma_apply_settings();
#ifdef USE_ASYNC_CALLBACK #ifdef USE_ASYNC_CALLBACK
pthread_mutexattr_t attr; pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr); pthread_mutexattr_init(&attr);
@ -352,7 +355,6 @@ void pcm_play_dma_init(void)
tick_add_task(pcm_tick); tick_add_task(pcm_tick);
#endif #endif
atexit(cleanup); atexit(cleanup);
return; return;
} }
@ -469,6 +471,7 @@ const void * pcm_play_dma_get_peak_buffer(int *count)
void pcm_play_dma_postinit(void) void pcm_play_dma_postinit(void)
{ {
audiohw_postinit();
} }

View file

@ -29,24 +29,12 @@
#include "adc.h" #include "adc.h"
#include "ascodec.h" #include "ascodec.h"
/* 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 */
};
int ascodec_init(void); int ascodec_init(void);
void ascodec_close(void); void ascodec_close(void);
int ascodec_write(unsigned int reg, unsigned int value); int ascodec_write(unsigned int reg, unsigned int value);
int ascodec_read(unsigned int reg); int ascodec_read(unsigned int reg);
void ascodec_write_pmu(unsigned int index, unsigned int subreg, unsigned int value); void ascodec_write_pmu(unsigned int index, unsigned int subreg, unsigned int value);
int ascodec_read_pmu(unsigned int index, unsigned int subreg); int ascodec_read_pmu(unsigned int index, unsigned int subreg);
void ascodec_set(unsigned int reg, unsigned int bits);
void ascodec_clear(unsigned int reg, unsigned int bits);
void ascodec_write_masked(unsigned int reg, unsigned int bits, unsigned int mask);
int ascodec_readbytes(unsigned int index, unsigned int len, unsigned char *data); int ascodec_readbytes(unsigned int index, unsigned int len, unsigned char *data);
unsigned short adc_read(int channel); unsigned short adc_read(int channel);
void ascodec_lock(void); void ascodec_lock(void);

View file

@ -32,6 +32,15 @@
int afe_dev = -1; 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 */ /* Write to a normal register */
#define IOCTL_REG_WRITE 0x40034101 #define IOCTL_REG_WRITE 0x40034101
/* Write to a PMU register */ /* Write to a PMU register */
@ -41,24 +50,18 @@ int afe_dev = -1;
/* Read from a PMU register */ /* Read from a PMU register */
#define IOCTL_SUBREG_READ 0x80034103 #define IOCTL_SUBREG_READ 0x80034103
static struct mutex as_mtx;
int ascodec_init(void) {
int ascodec_init(void)
{
afe_dev = open("/dev/afe", O_RDWR); afe_dev = open("/dev/afe", O_RDWR);
mutex_init(&as_mtx);
return afe_dev; return afe_dev;
} }
void ascodec_close(void) { void ascodec_close(void)
{
if (afe_dev >= 0) { if (afe_dev >= 0) {
close(afe_dev); close(afe_dev);
} }
} }
/* Read functions returns -1 if fail, otherwise the register's value if success */ /* 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) int ascodec_write(unsigned int reg, unsigned int value)
{ {
struct codec_req_struct y; struct codec_req_struct r = { .reg = reg, .value = value };
struct codec_req_struct *p; return ioctl(afe_dev, IOCTL_REG_WRITE, &r);
p = &y;
p->reg = reg;
p->value = value;
return ioctl(afe_dev, IOCTL_REG_WRITE, p);
} }
int ascodec_read(unsigned int reg) int ascodec_read(unsigned int reg)
{ {
int retval = -1; struct codec_req_struct r = { .reg = reg };
struct codec_req_struct y; int retval = ioctl(afe_dev, IOCTL_REG_READ, &r);
struct codec_req_struct *p;
p = &y;
p->reg = reg;
retval = ioctl(afe_dev, IOCTL_REG_READ, p);
if (retval >= 0) if (retval >= 0)
return p->value; return r.value;
else else
return retval; return retval;
} }
@ -91,114 +86,68 @@ int ascodec_read(unsigned int reg)
void ascodec_write_pmu(unsigned int index, unsigned int subreg, void ascodec_write_pmu(unsigned int index, unsigned int subreg,
unsigned int value) unsigned int value)
{ {
struct codec_req_struct y; struct codec_req_struct r = {.reg = index, .subreg = subreg, .value = value};
struct codec_req_struct *p; ioctl(afe_dev, IOCTL_SUBREG_WRITE, &r);
p = &y;
p->reg = index;
p->subreg = subreg;
p->value = value;
ioctl(afe_dev, IOCTL_SUBREG_WRITE, p);
} }
int ascodec_read_pmu(unsigned int index, unsigned int subreg) int ascodec_read_pmu(unsigned int index, unsigned int subreg)
{ {
int retval = -1; struct codec_req_struct r = { .reg = index, .subreg = subreg, };
struct codec_req_struct y; int retval = ioctl(afe_dev, IOCTL_SUBREG_READ, &r);
struct codec_req_struct *p;
p = &y;
p->reg = index;
p->subreg = subreg;
retval = ioctl(afe_dev, IOCTL_SUBREG_READ, p);
if (retval >= 0) if (retval >= 0)
return p->value; return r.value;
else else
return retval; 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) 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++) { for (i = index; i < (int)len; i++) {
data[i] = ascodec_read(i); val = ascodec_read(i);
printf("Register %i: value=%i\n",index,data[i]); if (val >= 0) data[i] = val;
else ret = -1;
} }
printf("TOTAL: %i\n", i); return ret ?: i; /* i means success */
return i;
} }
/* /*
* NOTE: * NOTE:
* After the conversion to interrupts, ascodec_(lock|unlock) are only used by * 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 * 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 * Additionally, concurrent ascodec_?(read|write) calls are instead protected
* by the R0's Kernel I2C driver for ascodec (mutexed), so it's automatically safe * by the R0's Kernel I2C driver for ascodec (mutexed), so it's automatically
* safe
*/ */
void ascodec_lock(void) void ascodec_lock(void)
{ {
mutex_lock(&as_mtx);
} }
void ascodec_unlock(void) void ascodec_unlock(void)
{ {
mutex_unlock(&as_mtx);
} }
/* Read 10-bit channel data */ /* Read 10-bit channel data */
unsigned short adc_read(int channel) unsigned short adc_read(int channel)
{ {
unsigned short data = 0;
if ((unsigned)channel >= NUM_ADC_CHANNELS) if ((unsigned)channel >= NUM_ADC_CHANNELS)
return 0; return 0;
ascodec_lock();
/* Select channel */ /* Select channel */
ascodec_write(AS3514_ADC_0, (channel << 4)); ascodec_write(AS3514_ADC_0, (channel << 4));
unsigned char buf[2]; 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 */ /* Read data */
ascodec_readbytes(AS3514_ADC_0, 2, buf); ascodec_readbytes(AS3514_ADC_0, sizeof(buf), buf);
data = (((buf[0] & 0x3) << 8) | buf[1]);
ascodec_unlock(); /* decode to 10-bit and return */
return data; return (((buf[0] & 0x3) << 8) | buf[1]);
} }
void adc_init(void) void adc_init(void)