summaryrefslogtreecommitdiff
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.c206
1 files changed, 206 insertions, 0 deletions
diff --git a/firmware/target/hosted/ypr0/ascodec-ypr0.c b/firmware/target/hosted/ypr0/ascodec-ypr0.c
new file mode 100644
index 0000000000..a4e92e6f6b
--- /dev/null
+++ b/firmware/target/hosted/ypr0/ascodec-ypr0.c
@@ -0,0 +1,206 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id: ascodec-target.h 26116 2010-05-17 20:53:25Z funman $
9 *
10 * Module wrapper for AS3543 audio codec, using /dev/afe (afe.ko) of Samsung YP-R0
11 *
12 * Copyright (c) 2011 Lorenzo Miori
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
18 *
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
21 *
22 ****************************************************************************/
23
24#include "fcntl.h"
25#include "unistd.h"
26#include "stdio.h"
27#include "string.h"
28#include "sys/ioctl.h"
29#include "stdlib.h"
30
31#include "ascodec-target.h"
32
33int afe_dev = -1;
34
35/* Write to a normal register */
36#define IOCTL_REG_WRITE 0x40034101
37/* Write to a PMU register */
38#define IOCTL_SUBREG_WRITE 0x40034103
39/* Read from a normal register */
40#define IOCTL_REG_READ 0x80034102
41/* Read from a PMU register */
42#define IOCTL_SUBREG_READ 0x80034103
43
44static struct mutex as_mtx;
45
46int ascodec_init(void) {
47
48 afe_dev = open("/dev/afe", O_RDWR);
49
50 mutex_init(&as_mtx);
51
52 return afe_dev;
53
54}
55
56void ascodec_close(void) {
57
58 if (afe_dev >= 0) {
59 close(afe_dev);
60 }
61
62}
63
64/* Read functions returns -1 if fail, otherwise the register's value if success */
65/* Write functions return >= 0 if success, otherwise -1 if fail */
66
67int ascodec_write(unsigned int reg, unsigned int value)
68{
69 struct codec_req_struct y;
70 struct codec_req_struct *p;
71 p = &y;
72 p->reg = reg;
73 p->value = value;
74 return ioctl(afe_dev, IOCTL_REG_WRITE, p);
75}
76
77int ascodec_read(unsigned int reg)
78{
79 int retval = -1;
80 struct codec_req_struct y;
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)
86 return p->value;
87 else
88 return retval;
89}
90
91void ascodec_write_pmu(unsigned int index, unsigned int subreg,
92 unsigned int value)
93{
94 struct codec_req_struct y;
95 struct codec_req_struct *p;
96 p = &y;
97 p->reg = index;
98 p->subreg = subreg;
99 p->value = value;
100 ioctl(afe_dev, IOCTL_SUBREG_WRITE, p);
101}
102
103int ascodec_read_pmu(unsigned int index, unsigned int subreg)
104{
105 int retval = -1;
106 struct codec_req_struct y;
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)
113 return p->value;
114 else
115 return retval;
116}
117
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)
137{
138 unsigned int i;
139
140 for (i=index; i<len; i++) {
141 data[i] = ascodec_read(i);
142 printf("Register %i: value=%i\n",index,data[i]);
143 }
144
145 printf("TOTAL: %i\n", i);
146
147 return i;
148}
149
150/*
151 * NOTE:
152 * 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
154 * the ADC at the same time.
155 *
156 * Concurrent ascodec_(async_)?(read|write) calls are instead protected
157 * by the R0's Kernel I2C driver for ascodec (mutexed), so it's automatically safe
158 */
159
160void ascodec_lock(void)
161{
162 mutex_lock(&as_mtx);
163}
164
165void ascodec_unlock(void)
166{
167 mutex_unlock(&as_mtx);
168}
169
170/* Read 10-bit channel data */
171unsigned short adc_read(int channel)
172{
173 unsigned short data = 0;
174
175 if ((unsigned)channel >= NUM_ADC_CHANNELS)
176 return 0;
177
178 ascodec_lock();
179
180 /* Select channel */
181 ascodec_write(AS3514_ADC_0, (channel << 4));
182 unsigned char buf[2];
183
184 /*
185 * The AS3514 ADC will trigger an interrupt when the conversion
186 * is finished, if the corresponding enable bit in IRQ_ENRD2
187 * is set.
188 * Previously the code did not wait and this apparently did
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}
203
204void adc_init(void)
205{
206}