audio_mini2440.c revision 1.1 1 1.1 nisimura /*-
2 1.1 nisimura * Copyright (c) 2012 The NetBSD Foundation, Inc.
3 1.1 nisimura * All rights reserved.
4 1.1 nisimura *
5 1.1 nisimura * This code is derived from software contributed to The NetBSD Foundation
6 1.1 nisimura * by Paul Fleischer <paul (at) xpg.dk>
7 1.1 nisimura *
8 1.1 nisimura * Redistribution and use in source and binary forms, with or without
9 1.1 nisimura * modification, are permitted provided that the following conditions
10 1.1 nisimura * are met:
11 1.1 nisimura * 1. Redistributions of source code must retain the above copyright
12 1.1 nisimura * notice, this list of conditions and the following disclaimer.
13 1.1 nisimura * 2. Redistributions in binary form must reproduce the above copyright
14 1.1 nisimura * notice, this list of conditions and the following disclaimer in the
15 1.1 nisimura * documentation and/or other materials provided with the distribution.
16 1.1 nisimura *
17 1.1 nisimura * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
18 1.1 nisimura * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 1.1 nisimura * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20 1.1 nisimura * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
21 1.1 nisimura * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 1.1 nisimura * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 1.1 nisimura * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 1.1 nisimura * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 1.1 nisimura * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 1.1 nisimura * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 1.1 nisimura * POSSIBILITY OF SUCH DAMAGE.
28 1.1 nisimura */
29 1.1 nisimura
30 1.1 nisimura #include <sys/cdefs.h>
31 1.1 nisimura #include <sys/param.h>
32 1.1 nisimura #include <sys/device.h>
33 1.1 nisimura #include <sys/malloc.h>
34 1.1 nisimura #include <sys/fcntl.h>
35 1.1 nisimura #include <sys/audioio.h>
36 1.1 nisimura
37 1.1 nisimura #include <sys/bus.h>
38 1.1 nisimura
39 1.1 nisimura #include <dev/audio_if.h>
40 1.1 nisimura
41 1.1 nisimura
42 1.1 nisimura #include <dev/ic/uda1341var.h>
43 1.1 nisimura
44 1.1 nisimura #include <arch/arm/s3c2xx0/s3c2440reg.h>
45 1.1 nisimura #include <arch/arm/s3c2xx0/s3c2440var.h>
46 1.1 nisimura
47 1.1 nisimura #include <arch/arm/s3c2xx0/s3c2440_dma.h>
48 1.1 nisimura #include <arch/arm/s3c2xx0/s3c2440_i2s.h>
49 1.1 nisimura
50 1.1 nisimura /*#define AUDIO_MINI2440_DEBUG*/
51 1.1 nisimura
52 1.1 nisimura #ifdef AUDIO_MINI2440_DEBUG
53 1.1 nisimura #define DPRINTF(x) do {printf x; } while (/*CONSTCOND*/0)
54 1.1 nisimura #else
55 1.1 nisimura #define DPRINTF(s) do {} while (/*CONSTCOND*/0)
56 1.1 nisimura #endif
57 1.1 nisimura
58 1.1 nisimura struct uda_softc {
59 1.1 nisimura device_t sc_dev;
60 1.1 nisimura kmutex_t sc_lock;
61 1.1 nisimura kmutex_t sc_intr_lock;
62 1.1 nisimura
63 1.1 nisimura struct uda1341_softc sc_uda1341;
64 1.1 nisimura
65 1.1 nisimura s3c2440_i2s_buf_t sc_play_buf;
66 1.1 nisimura s3c2440_i2s_buf_t sc_rec_buf;
67 1.1 nisimura
68 1.1 nisimura void *sc_i2s_handle;
69 1.1 nisimura
70 1.1 nisimura bool sc_open;
71 1.1 nisimura };
72 1.1 nisimura
73 1.1 nisimura int uda_ssio_open(void *, int);
74 1.1 nisimura void uda_ssio_close(void *);
75 1.1 nisimura int uda_ssio_set_params(void *, int, int, audio_params_t *, audio_params_t *,
76 1.1 nisimura stream_filter_list_t *, stream_filter_list_t *);
77 1.1 nisimura int uda_ssio_round_blocksize(void *, int, int, const audio_params_t *);
78 1.1 nisimura int uda_ssio_start_output(void *, void *, int, void (*)(void *),
79 1.1 nisimura void *);
80 1.1 nisimura int uda_ssio_start_input(void *, void *, int, void (*)(void *),
81 1.1 nisimura void *);
82 1.1 nisimura int uda_ssio_halt_output(void *);
83 1.1 nisimura int uda_ssio_halt_input(void *);
84 1.1 nisimura int uda_ssio_getdev(void *, struct audio_device *ret);
85 1.1 nisimura void* uda_ssio_allocm(void *, int, size_t);
86 1.1 nisimura void uda_ssio_freem(void *, void *, size_t);
87 1.1 nisimura size_t uda_ssio_round_buffersize(void *, int, size_t);
88 1.1 nisimura int uda_ssio_getprops(void *);
89 1.1 nisimura void uda_ssio_get_locks(void *, kmutex_t**, kmutex_t**);
90 1.1 nisimura
91 1.1 nisimura struct audio_hw_if uda1341_hw_if = {
92 1.1 nisimura uda_ssio_open,
93 1.1 nisimura uda_ssio_close,
94 1.1 nisimura NULL,
95 1.1 nisimura uda1341_query_encodings,
96 1.1 nisimura uda_ssio_set_params,
97 1.1 nisimura uda_ssio_round_blocksize,
98 1.1 nisimura NULL, /* commit_settings*/
99 1.1 nisimura NULL,
100 1.1 nisimura NULL,
101 1.1 nisimura uda_ssio_start_output,
102 1.1 nisimura uda_ssio_start_input,
103 1.1 nisimura uda_ssio_halt_output,
104 1.1 nisimura uda_ssio_halt_input,
105 1.1 nisimura NULL,
106 1.1 nisimura uda_ssio_getdev,
107 1.1 nisimura NULL,
108 1.1 nisimura uda1341_set_port,
109 1.1 nisimura uda1341_get_port,
110 1.1 nisimura uda1341_query_devinfo,
111 1.1 nisimura uda_ssio_allocm,
112 1.1 nisimura uda_ssio_freem,
113 1.1 nisimura uda_ssio_round_buffersize,
114 1.1 nisimura NULL, /* mappage */
115 1.1 nisimura uda_ssio_getprops,
116 1.1 nisimura NULL,
117 1.1 nisimura NULL,
118 1.1 nisimura NULL,
119 1.1 nisimura uda_ssio_get_locks
120 1.1 nisimura };
121 1.1 nisimura
122 1.1 nisimura static struct audio_device uda1341_device = {
123 1.1 nisimura "MINI2240-UDA1341",
124 1.1 nisimura "0.1",
125 1.1 nisimura "uda_ssio"
126 1.1 nisimura };
127 1.1 nisimura
128 1.1 nisimura void uda_ssio_l3_write(void *,int mode, int value);
129 1.1 nisimura
130 1.1 nisimura int uda_ssio_match(device_t, cfdata_t, void*);
131 1.1 nisimura void uda_ssio_attach(device_t, device_t, void*);
132 1.1 nisimura
133 1.1 nisimura CFATTACH_DECL_NEW(udassio, sizeof(struct uda_softc),
134 1.1 nisimura uda_ssio_match, uda_ssio_attach, NULL, NULL);
135 1.1 nisimura
136 1.1 nisimura int
137 1.1 nisimura uda_ssio_match(device_t parent, cfdata_t match, void *aux)
138 1.1 nisimura {
139 1.1 nisimura DPRINTF(("%s\n", __func__));
140 1.1 nisimura /* Not quite sure how we can detect the UDA1341 chip */
141 1.1 nisimura return 1;
142 1.1 nisimura }
143 1.1 nisimura
144 1.1 nisimura void
145 1.1 nisimura uda_ssio_attach(device_t parent, device_t self, void *aux)
146 1.1 nisimura {
147 1.1 nisimura /* struct s3c2xx0_attach_args *sa = aux;*/
148 1.1 nisimura struct uda_softc *sc = device_private(self);
149 1.1 nisimura struct s3c2xx0_softc *s3sc = s3c2xx0_softc; /* Shortcut */
150 1.1 nisimura struct s3c2440_i2s_attach_args *aa = aux;
151 1.1 nisimura uint32_t reg;
152 1.1 nisimura
153 1.1 nisimura sc->sc_dev = self;
154 1.1 nisimura
155 1.1 nisimura sc->sc_play_buf = NULL;
156 1.1 nisimura sc->sc_i2s_handle = aa->i2sa_handle;
157 1.1 nisimura sc->sc_open = false;
158 1.1 nisimura
159 1.1 nisimura mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE);
160 1.1 nisimura mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_SCHED);
161 1.1 nisimura
162 1.1 nisimura s3c2440_i2s_set_intr_lock(aa->i2sa_handle, &sc->sc_intr_lock);
163 1.1 nisimura
164 1.1 nisimura /* arch/arm/s3c2xx0/s3c2440.c initializes the I2S subsystem for us */
165 1.1 nisimura
166 1.1 nisimura /* Setup GPIO pins to output for L3 communication.
167 1.1 nisimura GPB3 (L3DATA) will have to be switched to input when reading
168 1.1 nisimura from the L3 bus.
169 1.1 nisimura
170 1.1 nisimura GPB2 - L3MODE
171 1.1 nisimura GPB3 - L3DATA
172 1.1 nisimura GPB4 - L3CLOCK
173 1.1 nisimura TODO: Make this configurable
174 1.1 nisimura */
175 1.1 nisimura reg = bus_space_read_4(s3sc->sc_iot, s3sc->sc_gpio_ioh, GPIO_PBCON);
176 1.1 nisimura reg = GPIO_SET_FUNC(reg, 2, 1);
177 1.1 nisimura reg = GPIO_SET_FUNC(reg, 3, 1);
178 1.1 nisimura reg = GPIO_SET_FUNC(reg, 4, 1);
179 1.1 nisimura bus_space_write_4(s3sc->sc_iot, s3sc->sc_gpio_ioh, GPIO_PBCON, reg);
180 1.1 nisimura
181 1.1 nisimura reg = bus_space_read_4(s3sc->sc_iot, s3sc->sc_gpio_ioh, GPIO_PBDAT);
182 1.1 nisimura reg = GPIO_SET_DATA(reg, 4, 1);
183 1.1 nisimura reg = GPIO_SET_DATA(reg, 3, 0);
184 1.1 nisimura reg = GPIO_SET_DATA(reg, 2, 1);
185 1.1 nisimura bus_space_write_4(s3sc->sc_iot, s3sc->sc_gpio_ioh, GPIO_PBDAT, reg);
186 1.1 nisimura
187 1.1 nisimura printf("\n");
188 1.1 nisimura
189 1.1 nisimura /* uda1341_attach resets the uda1341 sc, so it has to be called before
190 1.1 nisimura attributes are set on the sc.*/
191 1.1 nisimura uda1341_attach(&sc->sc_uda1341);
192 1.1 nisimura
193 1.1 nisimura /* Configure the UDA1341 Codec */
194 1.1 nisimura sc->sc_uda1341.parent = sc;
195 1.1 nisimura sc->sc_uda1341.sc_l3_write = uda_ssio_l3_write;
196 1.1 nisimura sc->sc_uda1341.sc_bus_format = UDA1341_BUS_MSB;
197 1.1 nisimura
198 1.1 nisimura /* Configure I2S controller */
199 1.1 nisimura s3c2440_i2s_set_bus_format(sc->sc_i2s_handle, S3C2440_I2S_BUS_MSB);
200 1.1 nisimura // Attach
201 1.1 nisimura audio_attach_mi(&uda1341_hw_if, &sc->sc_uda1341, self);
202 1.1 nisimura }
203 1.1 nisimura
204 1.1 nisimura int
205 1.1 nisimura uda_ssio_open(void *handle, int flags)
206 1.1 nisimura {
207 1.1 nisimura struct uda1341_softc *uc = handle;
208 1.1 nisimura struct uda_softc *sc = uc->parent;
209 1.1 nisimura int retval;
210 1.1 nisimura
211 1.1 nisimura DPRINTF(("%s\n", __func__));
212 1.1 nisimura
213 1.1 nisimura if (sc->sc_open)
214 1.1 nisimura return EBUSY;
215 1.1 nisimura
216 1.1 nisimura /* We only support write operations */
217 1.1 nisimura if (!(flags & FREAD) && !(flags & FWRITE))
218 1.1 nisimura return EINVAL;
219 1.1 nisimura
220 1.1 nisimura /* We can't do much more at this point than to
221 1.1 nisimura ask the UDA1341 codec to initialize itself
222 1.1 nisimura (for an unknown system clock)
223 1.1 nisimura */
224 1.1 nisimura retval = uda1341_open(handle, flags);
225 1.1 nisimura if (retval != 0) {
226 1.1 nisimura return retval;
227 1.1 nisimura }
228 1.1 nisimura
229 1.1 nisimura sc->sc_open = true;
230 1.1 nisimura
231 1.1 nisimura return 0; /* SUCCESS */
232 1.1 nisimura }
233 1.1 nisimura
234 1.1 nisimura void
235 1.1 nisimura uda_ssio_close(void *handle)
236 1.1 nisimura {
237 1.1 nisimura struct uda1341_softc *uc = handle;
238 1.1 nisimura struct uda_softc *sc = uc->parent;
239 1.1 nisimura DPRINTF(("%s\n", __func__));
240 1.1 nisimura
241 1.1 nisimura uda1341_close(handle);
242 1.1 nisimura sc->sc_open = false;
243 1.1 nisimura }
244 1.1 nisimura
245 1.1 nisimura int
246 1.1 nisimura uda_ssio_set_params(void *handle, int setmode, int usemode,
247 1.1 nisimura audio_params_t *play, audio_params_t *rec,
248 1.1 nisimura stream_filter_list_t *pfil, stream_filter_list_t *rfil)
249 1.1 nisimura {
250 1.1 nisimura struct uda1341_softc *uc = handle;
251 1.1 nisimura struct uda_softc *sc = uc->parent;
252 1.1 nisimura const struct audio_format *selected_format;
253 1.1 nisimura audio_params_t *params;
254 1.1 nisimura stream_filter_list_t *fil;
255 1.1 nisimura int retval;
256 1.1 nisimura
257 1.1 nisimura DPRINTF(("%s: setmode: %d\n", __func__, setmode));
258 1.1 nisimura DPRINTF(("%s: usemode: %d\n", __func__, usemode));
259 1.1 nisimura
260 1.1 nisimura if (setmode == 0)
261 1.1 nisimura setmode = usemode;
262 1.1 nisimura
263 1.1 nisimura if (setmode & AUMODE_PLAY) {
264 1.1 nisimura params = play;
265 1.1 nisimura fil = pfil;
266 1.1 nisimura } else if (setmode == AUMODE_RECORD) {
267 1.1 nisimura params = rec;
268 1.1 nisimura fil = rfil;
269 1.1 nisimura } else {
270 1.1 nisimura return EINVAL;
271 1.1 nisimura }
272 1.1 nisimura
273 1.1 nisimura DPRINTF(("%s: %dHz, encoding: %d, precision: %d, channels: %d\n",
274 1.1 nisimura __func__, params->sample_rate, params->encoding, play->precision,
275 1.1 nisimura params->channels));
276 1.1 nisimura
277 1.1 nisimura if (params->sample_rate != 8000 &&
278 1.1 nisimura params->sample_rate != 11025 &&
279 1.1 nisimura params->sample_rate != 22050 &&
280 1.1 nisimura params->sample_rate != 32000 &&
281 1.1 nisimura params->sample_rate != 44100 &&
282 1.1 nisimura params->sample_rate != 48000) {
283 1.1 nisimura return EINVAL;
284 1.1 nisimura }
285 1.1 nisimura
286 1.1 nisimura retval = auconv_set_converter(uda1341_formats, UDA1341_NFORMATS,
287 1.1 nisimura setmode, params, true, fil);
288 1.1 nisimura if (retval < 0) {
289 1.1 nisimura printf("Could not find valid format\n");
290 1.1 nisimura return EINVAL;
291 1.1 nisimura }
292 1.1 nisimura
293 1.1 nisimura selected_format = &uda1341_formats[retval];
294 1.1 nisimura
295 1.1 nisimura if (setmode == AUMODE_PLAY) {
296 1.1 nisimura s3c2440_i2s_set_direction(sc->sc_i2s_handle,
297 1.1 nisimura S3C2440_I2S_TRANSMIT);
298 1.1 nisimura } else {
299 1.1 nisimura s3c2440_i2s_set_direction(sc->sc_i2s_handle,
300 1.1 nisimura S3C2440_I2S_RECEIVE);
301 1.1 nisimura }
302 1.1 nisimura
303 1.1 nisimura s3c2440_i2s_set_sample_rate(sc->sc_i2s_handle, params->sample_rate);
304 1.1 nisimura s3c2440_i2s_set_sample_width(sc->sc_i2s_handle,
305 1.1 nisimura selected_format->precision);
306 1.1 nisimura
307 1.1 nisimura /* It is vital that sc_system_clock is set PRIOR to calling
308 1.1 nisimura uda1341_set_params. */
309 1.1 nisimura switch (s3c2440_i2s_get_master_clock(sc->sc_i2s_handle)) {
310 1.1 nisimura case 384:
311 1.1 nisimura uc->sc_system_clock = UDA1341_CLOCK_384;
312 1.1 nisimura break;
313 1.1 nisimura case 256:
314 1.1 nisimura uc->sc_system_clock = UDA1341_CLOCK_256;
315 1.1 nisimura break;
316 1.1 nisimura default:
317 1.1 nisimura return EINVAL;
318 1.1 nisimura }
319 1.1 nisimura
320 1.1 nisimura retval = uda1341_set_params(handle, setmode, usemode,
321 1.1 nisimura play, rec, pfil, rfil);
322 1.1 nisimura if (retval != 0) {
323 1.1 nisimura return retval;
324 1.1 nisimura }
325 1.1 nisimura
326 1.1 nisimura /* Setup and enable I2S controller */
327 1.1 nisimura retval = s3c2440_i2s_commit(sc->sc_i2s_handle);
328 1.1 nisimura if (retval != 0) {
329 1.1 nisimura printf("Failed to setup I2S controller\n");
330 1.1 nisimura return retval;
331 1.1 nisimura }
332 1.1 nisimura
333 1.1 nisimura return 0;
334 1.1 nisimura }
335 1.1 nisimura
336 1.1 nisimura int
337 1.1 nisimura uda_ssio_round_blocksize(void *handle, int bs, int mode,
338 1.1 nisimura const audio_params_t *param)
339 1.1 nisimura {
340 1.1 nisimura int out_bs;
341 1.1 nisimura DPRINTF(("%s: %d\n", __func__, bs));
342 1.1 nisimura
343 1.1 nisimura out_bs = (bs + 0x03) & ~0x03;
344 1.1 nisimura DPRINTF(("%s: out_bs: %d\n", __func__, out_bs));
345 1.1 nisimura return out_bs;
346 1.1 nisimura }
347 1.1 nisimura
348 1.1 nisimura int
349 1.1 nisimura uda_ssio_start_output(void *handle, void *block, int bsize,
350 1.1 nisimura void (*intr)(void *), void *intrarg)
351 1.1 nisimura {
352 1.1 nisimura struct uda1341_softc *uc = handle;
353 1.1 nisimura struct uda_softc *sc = uc->parent;
354 1.1 nisimura
355 1.1 nisimura return s3c2440_i2s_output(sc->sc_play_buf, block, bsize, intr, intrarg);
356 1.1 nisimura }
357 1.1 nisimura
358 1.1 nisimura int
359 1.1 nisimura uda_ssio_start_input(void *handle, void *block, int bsize,
360 1.1 nisimura void (*intr)(void *), void *intrarg)
361 1.1 nisimura {
362 1.1 nisimura struct uda1341_softc *uc = handle;
363 1.1 nisimura struct uda_softc *sc = uc->parent;
364 1.1 nisimura
365 1.1 nisimura return s3c2440_i2s_input(sc->sc_rec_buf, block, bsize, intr, intrarg);
366 1.1 nisimura }
367 1.1 nisimura
368 1.1 nisimura int
369 1.1 nisimura uda_ssio_halt_output(void *handle)
370 1.1 nisimura {
371 1.1 nisimura struct uda1341_softc *uc = handle;
372 1.1 nisimura struct uda_softc *sc = uc->parent;
373 1.1 nisimura
374 1.1 nisimura return s3c2440_i2s_halt_output(sc->sc_play_buf);
375 1.1 nisimura }
376 1.1 nisimura
377 1.1 nisimura int
378 1.1 nisimura uda_ssio_halt_input(void *handle)
379 1.1 nisimura {
380 1.1 nisimura DPRINTF(("%s\n", __func__));
381 1.1 nisimura return 0;
382 1.1 nisimura }
383 1.1 nisimura
384 1.1 nisimura int
385 1.1 nisimura uda_ssio_getdev(void *handle, struct audio_device *ret)
386 1.1 nisimura {
387 1.1 nisimura *ret = uda1341_device;
388 1.1 nisimura return 0;
389 1.1 nisimura }
390 1.1 nisimura
391 1.1 nisimura void *
392 1.1 nisimura uda_ssio_allocm(void *handle, int direction, size_t size)
393 1.1 nisimura {
394 1.1 nisimura struct uda1341_softc *uc = handle;
395 1.1 nisimura struct uda_softc *sc = uc->parent;
396 1.1 nisimura void *retval = NULL;
397 1.1 nisimura
398 1.1 nisimura DPRINTF(("%s\n", __func__));
399 1.1 nisimura
400 1.1 nisimura if (direction == AUMODE_PLAY ) {
401 1.1 nisimura if (sc->sc_play_buf != NULL)
402 1.1 nisimura return NULL;
403 1.1 nisimura
404 1.1 nisimura s3c2440_i2s_alloc(sc->sc_i2s_handle, direction, size, 0x00, &sc->sc_play_buf);
405 1.1 nisimura DPRINTF(("%s: addr of ring buffer: %p\n", __func__, sc->sc_play_buf->i2b_addr));
406 1.1 nisimura retval = sc->sc_play_buf->i2b_addr;
407 1.1 nisimura } else if (direction == AUMODE_RECORD) {
408 1.1 nisimura if (sc->sc_rec_buf != NULL)
409 1.1 nisimura return NULL;
410 1.1 nisimura
411 1.1 nisimura s3c2440_i2s_alloc(sc->sc_i2s_handle, direction, size, 0x00, &sc->sc_rec_buf);
412 1.1 nisimura DPRINTF(("%s: addr of ring buffer: %p\n", __func__, sc->sc_rec_buf->i2b_addr));
413 1.1 nisimura retval = sc->sc_rec_buf->i2b_addr;
414 1.1 nisimura }
415 1.1 nisimura
416 1.1 nisimura DPRINTF(("buffer: %p", retval));
417 1.1 nisimura
418 1.1 nisimura return retval;
419 1.1 nisimura }
420 1.1 nisimura
421 1.1 nisimura void
422 1.1 nisimura uda_ssio_freem(void *handle, void *ptr, size_t size)
423 1.1 nisimura {
424 1.1 nisimura struct uda1341_softc *uc = handle;
425 1.1 nisimura struct uda_softc *sc = uc->parent;
426 1.1 nisimura DPRINTF(("%s\n", __func__));
427 1.1 nisimura
428 1.1 nisimura if (ptr == sc->sc_play_buf->i2b_addr)
429 1.1 nisimura s3c2440_i2s_free(sc->sc_play_buf);
430 1.1 nisimura else if (ptr == sc->sc_rec_buf->i2b_addr)
431 1.1 nisimura s3c2440_i2s_free(sc->sc_rec_buf);
432 1.1 nisimura }
433 1.1 nisimura
434 1.1 nisimura size_t
435 1.1 nisimura uda_ssio_round_buffersize(void *handle, int direction, size_t bufsize)
436 1.1 nisimura {
437 1.1 nisimura DPRINTF(("%s: %d\n", __func__, (int)bufsize));
438 1.1 nisimura return bufsize;
439 1.1 nisimura }
440 1.1 nisimura
441 1.1 nisimura int
442 1.1 nisimura uda_ssio_getprops(void *handle)
443 1.1 nisimura {
444 1.1 nisimura return AUDIO_PROP_PLAYBACK | AUDIO_PROP_CAPTURE;
445 1.1 nisimura }
446 1.1 nisimura
447 1.1 nisimura void
448 1.1 nisimura uda_ssio_get_locks(void *handle, kmutex_t **intr, kmutex_t **thread)
449 1.1 nisimura {
450 1.1 nisimura struct uda1341_softc *uc = handle;
451 1.1 nisimura struct uda_softc *sc = uc->parent;
452 1.1 nisimura //struct uda_softc *sc = handle;
453 1.1 nisimura
454 1.1 nisimura *intr = &sc->sc_intr_lock;
455 1.1 nisimura *thread = &sc->sc_lock;
456 1.1 nisimura }
457 1.1 nisimura
458 1.1 nisimura void
459 1.1 nisimura uda_ssio_l3_write(void *cookie, int mode, int value)
460 1.1 nisimura {
461 1.1 nisimura struct s3c2xx0_softc *s3sc = s3c2xx0_softc; /* Shortcut */
462 1.1 nisimura uint32_t reg;
463 1.1 nisimura
464 1.1 nisimura /* GPB2: L3MODE
465 1.1 nisimura GPB3: L2DATA
466 1.1 nisimura GPB4: L3CLOCK */
467 1.1 nisimura #define L3MODE 2
468 1.1 nisimura #define L3DATA 3
469 1.1 nisimura #define L3CLOCK 4
470 1.1 nisimura #define READ_GPIO() bus_space_read_4(s3sc->sc_iot, s3sc->sc_gpio_ioh, GPIO_PBDAT)
471 1.1 nisimura #define WRITE_GPIO(val) bus_space_write_4(s3sc->sc_iot, s3sc->sc_gpio_ioh, GPIO_PBDAT, val)
472 1.1 nisimura
473 1.1 nisimura #define DELAY_TIME 1
474 1.1 nisimura
475 1.1 nisimura reg = READ_GPIO();
476 1.1 nisimura reg = GPIO_SET_DATA(reg, L3CLOCK, 1);
477 1.1 nisimura reg = GPIO_SET_DATA(reg, L3MODE, mode);
478 1.1 nisimura reg = GPIO_SET_DATA(reg, L3DATA, 0);
479 1.1 nisimura WRITE_GPIO(reg);
480 1.1 nisimura
481 1.1 nisimura if (mode == 1 ) {
482 1.1 nisimura reg = READ_GPIO();
483 1.1 nisimura reg = GPIO_SET_DATA(reg, L3MODE, 1);
484 1.1 nisimura WRITE_GPIO(reg);
485 1.1 nisimura }
486 1.1 nisimura
487 1.1 nisimura DELAY(1); /* L3MODE setup time: min 190ns */
488 1.1 nisimura
489 1.1 nisimura for(int i = 0; i<8; i++) {
490 1.1 nisimura char bval = (value >> i) & 0x1;
491 1.1 nisimura
492 1.1 nisimura reg = READ_GPIO();
493 1.1 nisimura reg = GPIO_SET_DATA(reg, L3CLOCK, 0);
494 1.1 nisimura reg = GPIO_SET_DATA(reg, L3DATA, bval);
495 1.1 nisimura WRITE_GPIO(reg);
496 1.1 nisimura
497 1.1 nisimura DELAY(DELAY_TIME);
498 1.1 nisimura
499 1.1 nisimura reg = READ_GPIO();
500 1.1 nisimura reg = GPIO_SET_DATA(reg, L3CLOCK, 1);
501 1.1 nisimura reg = GPIO_SET_DATA(reg, L3DATA, bval);
502 1.1 nisimura WRITE_GPIO(reg);
503 1.1 nisimura
504 1.1 nisimura DELAY(DELAY_TIME);
505 1.1 nisimura }
506 1.1 nisimura
507 1.1 nisimura reg = READ_GPIO();
508 1.1 nisimura reg = GPIO_SET_DATA(reg, L3MODE, 1);
509 1.1 nisimura reg = GPIO_SET_DATA(reg, L3CLOCK, 1);
510 1.1 nisimura reg = GPIO_SET_DATA(reg, L3DATA, 0);
511 1.1 nisimura WRITE_GPIO(reg);
512 1.1 nisimura
513 1.1 nisimura #undef L3MODE
514 1.1 nisimura #undef L3DATA
515 1.1 nisimura #undef L3CLOCK
516 1.1 nisimura #undef DELAY_TIME
517 1.1 nisimura #undef READ_GPIO
518 1.1 nisimura #undef WRITE_GPIO
519 1.1 nisimura }
520