summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--firmware/drivers/audio/as3514.c28
-rw-r--r--firmware/target/hosted/pcm-alsa.c7
-rw-r--r--firmware/target/hosted/ypr0/ascodec-target.h12
-rw-r--r--firmware/target/hosted/ypr0/ascodec-ypr0.c137
4 files changed, 49 insertions, 135 deletions
diff --git a/firmware/drivers/audio/as3514.c b/firmware/drivers/audio/as3514.c
index 0fe3070c19..a430afdf88 100644
--- a/firmware/drivers/audio/as3514.c
+++ b/firmware/drivers/audio/as3514.c
@@ -78,13 +78,12 @@ const struct sound_settings_info audiohw_settings[] = {
78#endif 78#endif
79}; 79};
80 80
81#ifndef SAMSUNG_YPR0
82/* Shadow registers */ 81/* Shadow registers */
83static uint8_t as3514_regs[AS3514_NUM_AUDIO_REGS]; /* 8-bit registers */ 82static uint8_t as3514_regs[AS3514_NUM_AUDIO_REGS]; /* 8-bit registers */
84 83
85/* 84/*
86 * little helper method to set register values. 85 * little helper method to set register values.
87 * With the help of as3514_regs, we minimize i2c 86 * With the help of as3514_regs, we minimize i2c/syscall
88 * traffic. 87 * traffic.
89 */ 88 */
90static void as3514_write(unsigned int reg, unsigned int value) 89static void as3514_write(unsigned int reg, unsigned int value)
@@ -111,29 +110,7 @@ static void as3514_write_masked(unsigned int reg, unsigned int bits,
111{ 110{
112 as3514_write(reg, (as3514_regs[reg] & ~mask) | (bits & mask)); 111 as3514_write(reg, (as3514_regs[reg] & ~mask) | (bits & mask));
113} 112}
114#else
115static void as3514_write(unsigned int reg, unsigned int value)
116{
117 ascodec_write(reg, value);
118}
119 113
120/* Helpers to set/clear bits */
121static void as3514_set(unsigned int reg, unsigned int bits)
122{
123 ascodec_write(reg, ascodec_read(reg) | bits);
124}
125
126static void as3514_clear(unsigned int reg, unsigned int bits)
127{
128 ascodec_write(reg, ascodec_read(reg) & ~bits);
129}
130
131static void as3514_write_masked(unsigned int reg, unsigned int bits,
132 unsigned int mask)
133{
134 ascodec_write(reg, (ascodec_read(reg) & ~mask) | (bits & mask));
135}
136#endif
137/* convert tenth of dB volume to master volume register value */ 114/* convert tenth of dB volume to master volume register value */
138int tenthdb2master(int db) 115int tenthdb2master(int db)
139{ 116{
@@ -168,11 +145,8 @@ int sound_val2phys(int setting, int value)
168 */ 145 */
169void audiohw_preinit(void) 146void audiohw_preinit(void)
170{ 147{
171
172#ifndef SAMSUNG_YPR0
173 /* read all reg values */ 148 /* read all reg values */
174 ascodec_readbytes(0x0, AS3514_NUM_AUDIO_REGS, as3514_regs); 149 ascodec_readbytes(0x0, AS3514_NUM_AUDIO_REGS, as3514_regs);
175#endif
176 150
177#ifdef HAVE_AS3543 151#ifdef HAVE_AS3543
178 152
diff --git a/firmware/target/hosted/pcm-alsa.c b/firmware/target/hosted/pcm-alsa.c
index 928187993e..7daf485f18 100644
--- a/firmware/target/hosted/pcm-alsa.c
+++ b/firmware/target/hosted/pcm-alsa.c
@@ -50,6 +50,7 @@
50#include "pcm-internal.h" 50#include "pcm-internal.h"
51#include "pcm_mixer.h" 51#include "pcm_mixer.h"
52#include "pcm_sampr.h" 52#include "pcm_sampr.h"
53#include "audiohw.h"
53 54
54#include <pthread.h> 55#include <pthread.h>
55#include <signal.h> 56#include <signal.h>
@@ -320,7 +321,7 @@ void cleanup(void)
320void pcm_play_dma_init(void) 321void pcm_play_dma_init(void)
321{ 322{
322 int err; 323 int err;
323 324 audiohw_preinit();
324 325
325 if ((err = snd_pcm_open(&handle, device, SND_PCM_STREAM_PLAYBACK, 0)) < 0) 326 if ((err = snd_pcm_open(&handle, device, SND_PCM_STREAM_PLAYBACK, 0)) < 0)
326 { 327 {
@@ -343,6 +344,8 @@ void pcm_play_dma_init(void)
343 exit(EXIT_FAILURE); 344 exit(EXIT_FAILURE);
344 } 345 }
345 346
347 pcm_dma_apply_settings();
348
346#ifdef USE_ASYNC_CALLBACK 349#ifdef USE_ASYNC_CALLBACK
347 pthread_mutexattr_t attr; 350 pthread_mutexattr_t attr;
348 pthread_mutexattr_init(&attr); 351 pthread_mutexattr_init(&attr);
@@ -352,7 +355,6 @@ void pcm_play_dma_init(void)
352 tick_add_task(pcm_tick); 355 tick_add_task(pcm_tick);
353#endif 356#endif
354 357
355
356 atexit(cleanup); 358 atexit(cleanup);
357 return; 359 return;
358} 360}
@@ -469,6 +471,7 @@ const void * pcm_play_dma_get_peak_buffer(int *count)
469 471
470void pcm_play_dma_postinit(void) 472void pcm_play_dma_postinit(void)
471{ 473{
474 audiohw_postinit();
472} 475}
473 476
474 477
diff --git a/firmware/target/hosted/ypr0/ascodec-target.h b/firmware/target/hosted/ypr0/ascodec-target.h
index f4ecf20a1b..2274d5f073 100644
--- a/firmware/target/hosted/ypr0/ascodec-target.h
+++ b/firmware/target/hosted/ypr0/ascodec-target.h
@@ -29,24 +29,12 @@
29#include "adc.h" 29#include "adc.h"
30#include "ascodec.h" 30#include "ascodec.h"
31 31
32/* ioctl parameter struct */
33
34struct codec_req_struct {
35/* This works for every kind of afe.ko module requests */
36 unsigned char reg; /* Main register address */
37 unsigned char subreg; /* Set this only if you are reading/writing a PMU register*/
38 unsigned char value; /* To be read if reading a register; to be set if writing to a register */
39};
40
41int ascodec_init(void); 32int ascodec_init(void);
42void ascodec_close(void); 33void ascodec_close(void);
43int ascodec_write(unsigned int reg, unsigned int value); 34int ascodec_write(unsigned int reg, unsigned int value);
44int ascodec_read(unsigned int reg); 35int ascodec_read(unsigned int reg);
45void ascodec_write_pmu(unsigned int index, unsigned int subreg, unsigned int value); 36void ascodec_write_pmu(unsigned int index, unsigned int subreg, unsigned int value);
46int ascodec_read_pmu(unsigned int index, unsigned int subreg); 37int ascodec_read_pmu(unsigned int index, unsigned int subreg);
47void ascodec_set(unsigned int reg, unsigned int bits);
48void ascodec_clear(unsigned int reg, unsigned int bits);
49void ascodec_write_masked(unsigned int reg, unsigned int bits, unsigned int mask);
50int ascodec_readbytes(unsigned int index, unsigned int len, unsigned char *data); 38int ascodec_readbytes(unsigned int index, unsigned int len, unsigned char *data);
51unsigned short adc_read(int channel); 39unsigned short adc_read(int channel);
52void ascodec_lock(void); 40void ascodec_lock(void);
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 @@
32 32
33int afe_dev = -1; 33int afe_dev = -1;
34 34
35/* ioctl parameter struct */
36struct codec_req_struct {
37/* This works for every kind of afe.ko module requests */
38 unsigned char reg; /* Main register address */
39 unsigned char subreg; /* Set this only if you are reading/writing a PMU register*/
40 unsigned char value; /* To be read if reading a register; to be set if writing to a register */
41} __attribute__((packed));
42
43
35/* Write to a normal register */ 44/* Write to a normal register */
36#define IOCTL_REG_WRITE 0x40034101 45#define IOCTL_REG_WRITE 0x40034101
37/* Write to a PMU register */ 46/* Write to a PMU register */
38#define IOCTL_SUBREG_WRITE 0x40034103 47#define IOCTL_SUBREG_WRITE 0x40034103
39/* Read from a normal register */ 48/* Read from a normal register */
40#define IOCTL_REG_READ 0x80034102 49#define IOCTL_REG_READ 0x80034102
41/* Read from a PMU register */ 50/* Read from a PMU register */
42#define IOCTL_SUBREG_READ 0x80034103 51#define IOCTL_SUBREG_READ 0x80034103
43
44static struct mutex as_mtx;
45 52
46int ascodec_init(void) {
47 53
54int ascodec_init(void)
55{
48 afe_dev = open("/dev/afe", O_RDWR); 56 afe_dev = open("/dev/afe", O_RDWR);
49
50 mutex_init(&as_mtx);
51
52 return afe_dev; 57 return afe_dev;
53
54} 58}
55 59
56void ascodec_close(void) { 60void ascodec_close(void)
57 61{
58 if (afe_dev >= 0) { 62 if (afe_dev >= 0) {
59 close(afe_dev); 63 close(afe_dev);
60 } 64 }
61
62} 65}
63 66
64/* Read functions returns -1 if fail, otherwise the register's value if success */ 67/* Read functions returns -1 if fail, otherwise the register's value if success */
@@ -66,24 +69,16 @@ void ascodec_close(void) {
66 69
67int ascodec_write(unsigned int reg, unsigned int value) 70int ascodec_write(unsigned int reg, unsigned int value)
68{ 71{
69 struct codec_req_struct y; 72 struct codec_req_struct r = { .reg = reg, .value = value };
70 struct codec_req_struct *p; 73 return ioctl(afe_dev, IOCTL_REG_WRITE, &r);
71 p = &y;
72 p->reg = reg;
73 p->value = value;
74 return ioctl(afe_dev, IOCTL_REG_WRITE, p);
75} 74}
76 75
77int ascodec_read(unsigned int reg) 76int ascodec_read(unsigned int reg)
78{ 77{
79 int retval = -1; 78 struct codec_req_struct r = { .reg = reg };
80 struct codec_req_struct y; 79 int retval = ioctl(afe_dev, IOCTL_REG_READ, &r);
81 struct codec_req_struct *p;
82 p = &y;
83 p->reg = reg;
84 retval = ioctl(afe_dev, IOCTL_REG_READ, p);
85 if (retval >= 0) 80 if (retval >= 0)
86 return p->value; 81 return r.value;
87 else 82 else
88 return retval; 83 return retval;
89} 84}
@@ -91,114 +86,68 @@ int ascodec_read(unsigned int reg)
91void ascodec_write_pmu(unsigned int index, unsigned int subreg, 86void ascodec_write_pmu(unsigned int index, unsigned int subreg,
92 unsigned int value) 87 unsigned int value)
93{ 88{
94 struct codec_req_struct y; 89 struct codec_req_struct r = {.reg = index, .subreg = subreg, .value = value};
95 struct codec_req_struct *p; 90 ioctl(afe_dev, IOCTL_SUBREG_WRITE, &r);
96 p = &y;
97 p->reg = index;
98 p->subreg = subreg;
99 p->value = value;
100 ioctl(afe_dev, IOCTL_SUBREG_WRITE, p);
101} 91}
102 92
103int ascodec_read_pmu(unsigned int index, unsigned int subreg) 93int ascodec_read_pmu(unsigned int index, unsigned int subreg)
104{ 94{
105 int retval = -1; 95 struct codec_req_struct r = { .reg = index, .subreg = subreg, };
106 struct codec_req_struct y; 96 int retval = ioctl(afe_dev, IOCTL_SUBREG_READ, &r);
107 struct codec_req_struct *p;
108 p = &y;
109 p->reg = index;
110 p->subreg = subreg;
111 retval = ioctl(afe_dev, IOCTL_SUBREG_READ, p);
112 if (retval >= 0) 97 if (retval >= 0)
113 return p->value; 98 return r.value;
114 else 99 else
115 return retval; 100 return retval;
116} 101}
117 102
118/* Helpers to set/clear bits */
119void ascodec_set(unsigned int reg, unsigned int bits)
120{
121 ascodec_write(reg, ascodec_read(reg) | bits);
122}
123
124void ascodec_clear(unsigned int reg, unsigned int bits)
125{
126 ascodec_write(reg, ascodec_read(reg) & ~bits);
127}
128
129void ascodec_write_masked(unsigned int reg, unsigned int bits,
130 unsigned int mask)
131{
132 ascodec_write(reg, (ascodec_read(reg) & ~mask) | (bits & mask));
133}
134
135/*FIXME: doesn't work */
136int ascodec_readbytes(unsigned int index, unsigned int len, unsigned char *data) 103int ascodec_readbytes(unsigned int index, unsigned int len, unsigned char *data)
137{ 104{
138 unsigned int i; 105 int i, val, ret = 0;
139 106
140 for (i=index; i<len; i++) { 107 for (i = index; i < (int)len; i++) {
141 data[i] = ascodec_read(i); 108 val = ascodec_read(i);
142 printf("Register %i: value=%i\n",index,data[i]); 109 if (val >= 0) data[i] = val;
110 else ret = -1;
143 } 111 }
144 112
145 printf("TOTAL: %i\n", i); 113 return ret ?: i; /* i means success */
146
147 return i;
148} 114}
149 115
150/* 116/*
151 * NOTE: 117 * NOTE:
152 * After the conversion to interrupts, ascodec_(lock|unlock) are only used by 118 * After the conversion to interrupts, ascodec_(lock|unlock) are only used by
153 * adc-as3514.c to protect against other threads corrupting the result by using 119 * adc-as3514.c to protect against other threads corrupting the result by using
154 * the ADC at the same time. 120 * the ADC at the same time. this adc_read() doesn't yield but blocks, so
121 * lock/unlock is not needed
155 * 122 *
156 * Concurrent ascodec_(async_)?(read|write) calls are instead protected 123 * Additionally, concurrent ascodec_?(read|write) calls are instead protected
157 * by the R0's Kernel I2C driver for ascodec (mutexed), so it's automatically safe 124 * by the R0's Kernel I2C driver for ascodec (mutexed), so it's automatically
125 * safe
158 */ 126 */
159 127
160void ascodec_lock(void) 128void ascodec_lock(void)
161{ 129{
162 mutex_lock(&as_mtx);
163} 130}
164 131
165void ascodec_unlock(void) 132void ascodec_unlock(void)
166{ 133{
167 mutex_unlock(&as_mtx);
168} 134}
169 135
170/* Read 10-bit channel data */ 136/* Read 10-bit channel data */
171unsigned short adc_read(int channel) 137unsigned short adc_read(int channel)
172{ 138{
173 unsigned short data = 0;
174
175 if ((unsigned)channel >= NUM_ADC_CHANNELS) 139 if ((unsigned)channel >= NUM_ADC_CHANNELS)
176 return 0; 140 return 0;
177 141
178 ascodec_lock();
179
180 /* Select channel */ 142 /* Select channel */
181 ascodec_write(AS3514_ADC_0, (channel << 4)); 143 ascodec_write(AS3514_ADC_0, (channel << 4));
182 unsigned char buf[2]; 144 unsigned char buf[2];
183 145
184 /* 146 /* Read data */
185 * The AS3514 ADC will trigger an interrupt when the conversion 147 ascodec_readbytes(AS3514_ADC_0, sizeof(buf), buf);
186 * is finished, if the corresponding enable bit in IRQ_ENRD2 148
187 * is set. 149 /* decode to 10-bit and return */
188 * Previously the code did not wait and this apparently did 150 return (((buf[0] & 0x3) << 8) | buf[1]);
189 * not pose any problems, but this should be more correct.
190 * Without the wait the data read back may be completely or
191 * partially (first one of the two bytes) stale.
192 */
193 /*FIXME: not implemented*/
194 ascodec_wait_adc_finished();
195
196 /* Read data */
197 ascodec_readbytes(AS3514_ADC_0, 2, buf);
198 data = (((buf[0] & 0x3) << 8) | buf[1]);
199
200 ascodec_unlock();
201 return data;
202} 151}
203 152
204void adc_init(void) 153void adc_init(void)