Home | History | Annotate | Line # | Download | only in mini2440
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