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/fcntl.h> 34 #include <sys/audioio.h> 35 36 #include <sys/bus.h> 37 38 #include <dev/audio/audio_if.h> 39 40 41 #include <dev/ic/uda1341var.h> 42 43 #include <arch/arm/s3c2xx0/s3c2440reg.h> 44 #include <arch/arm/s3c2xx0/s3c2440var.h> 45 46 #include <arch/arm/s3c2xx0/s3c2440_dma.h> 47 #include <arch/arm/s3c2xx0/s3c2440_i2s.h> 48 49 /*#define AUDIO_MINI2440_DEBUG*/ 50 51 #ifdef AUDIO_MINI2440_DEBUG 52 #define DPRINTF(x) do {printf x; } while (/*CONSTCOND*/0) 53 #else 54 #define DPRINTF(s) do {} while (/*CONSTCOND*/0) 55 #endif 56 57 struct uda_softc { 58 device_t sc_dev; 59 kmutex_t sc_lock; 60 kmutex_t sc_intr_lock; 61 62 struct uda1341_softc sc_uda1341; 63 64 s3c2440_i2s_buf_t sc_play_buf; 65 s3c2440_i2s_buf_t sc_rec_buf; 66 67 void *sc_i2s_handle; 68 }; 69 70 int uda_ssio_open(void *, int); 71 void uda_ssio_close(void *); 72 int uda_ssio_query_format(void *, audio_format_query_t *); 73 int uda_ssio_set_format(void *, int, 74 const audio_params_t *, const audio_params_t *, 75 audio_filter_reg_t *, audio_filter_reg_t *); 76 int uda_ssio_start_output(void *, void *, int, void (*)(void *), 77 void *); 78 int uda_ssio_start_input(void *, void *, int, void (*)(void *), 79 void *); 80 int uda_ssio_halt_output(void *); 81 int uda_ssio_halt_input(void *); 82 int uda_ssio_getdev(void *, struct audio_device *ret); 83 void* uda_ssio_allocm(void *, int, size_t); 84 void uda_ssio_freem(void *, void *, size_t); 85 size_t uda_ssio_round_buffersize(void *, int, size_t); 86 int uda_ssio_get_props(void *); 87 void uda_ssio_get_locks(void *, kmutex_t**, kmutex_t**); 88 89 struct audio_hw_if uda1341_hw_if = { 90 .open = uda_ssio_open, 91 .close = uda_ssio_close, 92 .query_format = uda_ssio_query_format, 93 .set_format = uda_ssio_set_format, 94 .start_output = uda_ssio_start_output, 95 .start_input = uda_ssio_start_input, 96 .halt_output = uda_ssio_halt_output, 97 .halt_input = uda_ssio_halt_input, 98 .getdev = uda_ssio_getdev, 99 .set_port = uda1341_set_port, 100 .get_port = uda1341_get_port, 101 .query_devinfo = uda1341_query_devinfo, 102 .allocm = uda_ssio_allocm, 103 .freem = uda_ssio_freem, 104 .round_buffersize = uda_ssio_round_buffersize, 105 .get_props = uda_ssio_get_props, 106 .get_locks = uda_ssio_get_locks 107 }; 108 109 static struct audio_device uda1341_device = { 110 "MINI2240-UDA1341", 111 "0.1", 112 "uda_ssio" 113 }; 114 115 static const struct audio_format uda_ssio_formats[] = 116 { 117 { 118 .mode = AUMODE_PLAY | AUMODE_RECORD, 119 .encoding = AUDIO_ENCODING_SLINEAR_LE, 120 .validbits = 16, 121 .precision = 16, 122 .channels = 2, 123 .channel_mask = AUFMT_STEREO, 124 .frequency_type = 6, 125 .frequency = { 8000, 11025, 22050, 32000, 44100, 48000 }, 126 } 127 }; 128 #define UDA_SSIO_NFORMATS __arraycount(uda_ssio_formats) 129 130 void uda_ssio_l3_write(void *,int mode, int value); 131 132 int uda_ssio_match(device_t, cfdata_t, void*); 133 void uda_ssio_attach(device_t, device_t, void*); 134 135 CFATTACH_DECL_NEW(udassio, sizeof(struct uda_softc), 136 uda_ssio_match, uda_ssio_attach, NULL, NULL); 137 138 int 139 uda_ssio_match(device_t parent, cfdata_t match, void *aux) 140 { 141 DPRINTF(("%s\n", __func__)); 142 /* Not quite sure how we can detect the UDA1341 chip */ 143 return 1; 144 } 145 146 void 147 uda_ssio_attach(device_t parent, device_t self, void *aux) 148 { 149 /* struct s3c2xx0_attach_args *sa = aux;*/ 150 struct uda_softc *sc = device_private(self); 151 struct s3c2xx0_softc *s3sc = s3c2xx0_softc; /* Shortcut */ 152 struct s3c2440_i2s_attach_args *aa = aux; 153 uint32_t reg; 154 155 sc->sc_dev = self; 156 157 sc->sc_play_buf = NULL; 158 sc->sc_i2s_handle = aa->i2sa_handle; 159 160 mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE); 161 mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_SCHED); 162 163 s3c2440_i2s_set_intr_lock(aa->i2sa_handle, &sc->sc_intr_lock); 164 165 /* arch/arm/s3c2xx0/s3c2440.c initializes the I2S subsystem for us */ 166 167 /* Setup GPIO pins to output for L3 communication. 168 GPB3 (L3DATA) will have to be switched to input when reading 169 from the L3 bus. 170 171 GPB2 - L3MODE 172 GPB3 - L3DATA 173 GPB4 - L3CLOCK 174 TODO: Make this configurable 175 */ 176 reg = bus_space_read_4(s3sc->sc_iot, s3sc->sc_gpio_ioh, GPIO_PBCON); 177 reg = GPIO_SET_FUNC(reg, 2, 1); 178 reg = GPIO_SET_FUNC(reg, 3, 1); 179 reg = GPIO_SET_FUNC(reg, 4, 1); 180 bus_space_write_4(s3sc->sc_iot, s3sc->sc_gpio_ioh, GPIO_PBCON, reg); 181 182 reg = bus_space_read_4(s3sc->sc_iot, s3sc->sc_gpio_ioh, GPIO_PBDAT); 183 reg = GPIO_SET_DATA(reg, 4, 1); 184 reg = GPIO_SET_DATA(reg, 3, 0); 185 reg = GPIO_SET_DATA(reg, 2, 1); 186 bus_space_write_4(s3sc->sc_iot, s3sc->sc_gpio_ioh, GPIO_PBDAT, reg); 187 188 printf("\n"); 189 190 /* uda1341_attach resets the uda1341 sc, so it has to be called before 191 attributes are set on the sc.*/ 192 uda1341_attach(&sc->sc_uda1341); 193 194 /* Configure the UDA1341 Codec */ 195 sc->sc_uda1341.parent = sc; 196 sc->sc_uda1341.sc_l3_write = uda_ssio_l3_write; 197 sc->sc_uda1341.sc_bus_format = UDA1341_BUS_MSB; 198 199 /* Configure I2S controller */ 200 s3c2440_i2s_set_bus_format(sc->sc_i2s_handle, S3C2440_I2S_BUS_MSB); 201 // Attach 202 audio_attach_mi(&uda1341_hw_if, &sc->sc_uda1341, self); 203 } 204 205 int 206 uda_ssio_open(void *handle, int flags) 207 { 208 int retval; 209 210 DPRINTF(("%s\n", __func__)); 211 212 /* We only support write operations */ 213 if (!(flags & FREAD) && !(flags & FWRITE)) 214 return EINVAL; 215 216 /* We can't do much more at this point than to 217 ask the UDA1341 codec to initialize itself 218 (for an unknown system clock) 219 */ 220 retval = uda1341_open(handle, flags); 221 if (retval != 0) { 222 return retval; 223 } 224 225 return 0; /* SUCCESS */ 226 } 227 228 void 229 uda_ssio_close(void *handle) 230 { 231 232 DPRINTF(("%s\n", __func__)); 233 234 uda1341_close(handle); 235 } 236 237 int 238 uda_ssio_query_format(void *handle, audio_format_query_t *afp) 239 { 240 241 return audio_query_format(uda_ssio_formats, UDA_SSIO_NFORMATS, afp); 242 } 243 244 int 245 uda_ssio_set_format(void *handle, int setmode, 246 const audio_params_t *play, const audio_params_t *rec, 247 audio_filter_reg_t *pfil, audio_filter_reg_t *rfil) 248 { 249 struct uda1341_softc *uc = handle; 250 struct uda_softc *sc = uc->parent; 251 int retval; 252 253 DPRINTF(("%s: setmode: %d\n", __func__, setmode)); 254 255 /* *play and *rec are the identical because !AUDIO_PROP_INDEPENDENT. */ 256 257 DPRINTF(("%s: %dHz, encoding: %d, precision: %d, channels: %d\n", 258 __func__, play->sample_rate, play->encoding, play->precision, 259 play->channels)); 260 261 if (setmode == AUMODE_PLAY) { 262 s3c2440_i2s_set_direction(sc->sc_i2s_handle, 263 S3C2440_I2S_TRANSMIT); 264 } else { 265 s3c2440_i2s_set_direction(sc->sc_i2s_handle, 266 S3C2440_I2S_RECEIVE); 267 } 268 269 s3c2440_i2s_set_sample_rate(sc->sc_i2s_handle, play->sample_rate); 270 s3c2440_i2s_set_sample_width(sc->sc_i2s_handle, 16); 271 272 /* It is vital that sc_system_clock is set PRIOR to calling 273 uda1341_set_format. */ 274 switch (s3c2440_i2s_get_master_clock(sc->sc_i2s_handle)) { 275 case 384: 276 uc->sc_system_clock = UDA1341_CLOCK_384; 277 break; 278 case 256: 279 uc->sc_system_clock = UDA1341_CLOCK_256; 280 break; 281 default: 282 return EINVAL; 283 } 284 285 retval = uda1341_set_format(handle, setmode, play, rec, pfil, rfil); 286 if (retval != 0) { 287 return retval; 288 } 289 290 /* Setup and enable I2S controller */ 291 retval = s3c2440_i2s_commit(sc->sc_i2s_handle); 292 if (retval != 0) { 293 printf("Failed to setup I2S controller\n"); 294 return retval; 295 } 296 297 return 0; 298 } 299 300 int 301 uda_ssio_start_output(void *handle, void *block, int bsize, 302 void (*intr)(void *), void *intrarg) 303 { 304 struct uda1341_softc *uc = handle; 305 struct uda_softc *sc = uc->parent; 306 307 return s3c2440_i2s_output(sc->sc_play_buf, block, bsize, intr, intrarg); 308 } 309 310 int 311 uda_ssio_start_input(void *handle, void *block, int bsize, 312 void (*intr)(void *), void *intrarg) 313 { 314 struct uda1341_softc *uc = handle; 315 struct uda_softc *sc = uc->parent; 316 317 return s3c2440_i2s_input(sc->sc_rec_buf, block, bsize, intr, intrarg); 318 } 319 320 int 321 uda_ssio_halt_output(void *handle) 322 { 323 struct uda1341_softc *uc = handle; 324 struct uda_softc *sc = uc->parent; 325 326 return s3c2440_i2s_halt_output(sc->sc_play_buf); 327 } 328 329 int 330 uda_ssio_halt_input(void *handle) 331 { 332 DPRINTF(("%s\n", __func__)); 333 return 0; 334 } 335 336 int 337 uda_ssio_getdev(void *handle, struct audio_device *ret) 338 { 339 *ret = uda1341_device; 340 return 0; 341 } 342 343 void * 344 uda_ssio_allocm(void *handle, int direction, size_t size) 345 { 346 struct uda1341_softc *uc = handle; 347 struct uda_softc *sc = uc->parent; 348 void *retval = NULL; 349 350 DPRINTF(("%s\n", __func__)); 351 352 if (direction == AUMODE_PLAY ) { 353 if (sc->sc_play_buf != NULL) 354 return NULL; 355 356 s3c2440_i2s_alloc(sc->sc_i2s_handle, direction, size, 0x00, &sc->sc_play_buf); 357 DPRINTF(("%s: addr of ring buffer: %p\n", __func__, sc->sc_play_buf->i2b_addr)); 358 retval = sc->sc_play_buf->i2b_addr; 359 } else if (direction == AUMODE_RECORD) { 360 if (sc->sc_rec_buf != NULL) 361 return NULL; 362 363 s3c2440_i2s_alloc(sc->sc_i2s_handle, direction, size, 0x00, &sc->sc_rec_buf); 364 DPRINTF(("%s: addr of ring buffer: %p\n", __func__, sc->sc_rec_buf->i2b_addr)); 365 retval = sc->sc_rec_buf->i2b_addr; 366 } 367 368 DPRINTF(("buffer: %p", retval)); 369 370 return retval; 371 } 372 373 void 374 uda_ssio_freem(void *handle, void *ptr, size_t size) 375 { 376 struct uda1341_softc *uc = handle; 377 struct uda_softc *sc = uc->parent; 378 DPRINTF(("%s\n", __func__)); 379 380 if (ptr == sc->sc_play_buf->i2b_addr) 381 s3c2440_i2s_free(sc->sc_play_buf); 382 else if (ptr == sc->sc_rec_buf->i2b_addr) 383 s3c2440_i2s_free(sc->sc_rec_buf); 384 } 385 386 size_t 387 uda_ssio_round_buffersize(void *handle, int direction, size_t bufsize) 388 { 389 DPRINTF(("%s: %d\n", __func__, (int)bufsize)); 390 return bufsize; 391 } 392 393 int 394 uda_ssio_get_props(void *handle) 395 { 396 return AUDIO_PROP_PLAYBACK | AUDIO_PROP_CAPTURE; 397 } 398 399 void 400 uda_ssio_get_locks(void *handle, kmutex_t **intr, kmutex_t **thread) 401 { 402 struct uda1341_softc *uc = handle; 403 struct uda_softc *sc = uc->parent; 404 //struct uda_softc *sc = handle; 405 406 *intr = &sc->sc_intr_lock; 407 *thread = &sc->sc_lock; 408 } 409 410 void 411 uda_ssio_l3_write(void *cookie, int mode, int value) 412 { 413 struct s3c2xx0_softc *s3sc = s3c2xx0_softc; /* Shortcut */ 414 uint32_t reg; 415 416 /* GPB2: L3MODE 417 GPB3: L2DATA 418 GPB4: L3CLOCK */ 419 #define L3MODE 2 420 #define L3DATA 3 421 #define L3CLOCK 4 422 #define READ_GPIO() bus_space_read_4(s3sc->sc_iot, s3sc->sc_gpio_ioh, GPIO_PBDAT) 423 #define WRITE_GPIO(val) bus_space_write_4(s3sc->sc_iot, s3sc->sc_gpio_ioh, GPIO_PBDAT, val) 424 425 #define DELAY_TIME 1 426 427 reg = READ_GPIO(); 428 reg = GPIO_SET_DATA(reg, L3CLOCK, 1); 429 reg = GPIO_SET_DATA(reg, L3MODE, mode); 430 reg = GPIO_SET_DATA(reg, L3DATA, 0); 431 WRITE_GPIO(reg); 432 433 if (mode == 1 ) { 434 reg = READ_GPIO(); 435 reg = GPIO_SET_DATA(reg, L3MODE, 1); 436 WRITE_GPIO(reg); 437 } 438 439 DELAY(1); /* L3MODE setup time: min 190ns */ 440 441 for(int i = 0; i<8; i++) { 442 char bval = (value >> i) & 0x1; 443 444 reg = READ_GPIO(); 445 reg = GPIO_SET_DATA(reg, L3CLOCK, 0); 446 reg = GPIO_SET_DATA(reg, L3DATA, bval); 447 WRITE_GPIO(reg); 448 449 DELAY(DELAY_TIME); 450 451 reg = READ_GPIO(); 452 reg = GPIO_SET_DATA(reg, L3CLOCK, 1); 453 reg = GPIO_SET_DATA(reg, L3DATA, bval); 454 WRITE_GPIO(reg); 455 456 DELAY(DELAY_TIME); 457 } 458 459 reg = READ_GPIO(); 460 reg = GPIO_SET_DATA(reg, L3MODE, 1); 461 reg = GPIO_SET_DATA(reg, L3CLOCK, 1); 462 reg = GPIO_SET_DATA(reg, L3DATA, 0); 463 WRITE_GPIO(reg); 464 465 #undef L3MODE 466 #undef L3DATA 467 #undef L3CLOCK 468 #undef DELAY_TIME 469 #undef READ_GPIO 470 #undef WRITE_GPIO 471 } 472