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