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