Home | History | Annotate | Line # | Download | only in dev
      1 /*	$NetBSD: audioamd.c,v 1.30 2020/09/12 05:19:16 isaki Exp $	*/
      2 /*	NetBSD: am7930_sparc.c,v 1.44 1999/03/14 22:29:00 jonathan Exp 	*/
      3 
      4 /*
      5  * Copyright (c) 1995 Rolf Grossmann
      6  * All rights reserved.
      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  * 3. All advertising materials mentioning features or use of this software
     17  *    must display the following acknowledgement:
     18  *      This product includes software developed by Rolf Grossmann.
     19  * 4. The name of the author may not be used to endorse or promote products
     20  *    derived from this software without specific prior written permission
     21  *
     22  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     23  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     24  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     25  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     27  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     28  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     29  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     30  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     31  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     32  */
     33 
     34 #include <sys/cdefs.h>
     35 __KERNEL_RCSID(0, "$NetBSD: audioamd.c,v 1.30 2020/09/12 05:19:16 isaki Exp $");
     36 
     37 #include "audio.h"
     38 #if NAUDIO > 0
     39 
     40 #include <sys/param.h>
     41 #include <sys/systm.h>
     42 #include <sys/errno.h>
     43 #include <sys/device.h>
     44 #include <sys/bus.h>
     45 #include <sys/intr.h>
     46 #include <sys/mutex.h>
     47 
     48 #include <machine/autoconf.h>
     49 
     50 #include <sys/audioio.h>
     51 #include <dev/audio/audio_if.h>
     52 
     53 #include <dev/ic/am7930reg.h>
     54 #include <dev/ic/am7930var.h>
     55 
     56 #define AUDIO_ROM_NAME "audio"
     57 
     58 struct audioamd_softc {
     59 	struct am7930_softc sc_am7930;	/* glue to MI code */
     60 
     61 	bus_space_tag_t sc_bt;		/* bus cookie */
     62 	bus_space_handle_t sc_bh;	/* device registers */
     63 };
     64 
     65 int	audioamd_mainbus_match(device_t, cfdata_t, void *);
     66 void	audioamd_mainbus_attach(device_t, device_t, void *);
     67 int	audioamd_obio_match(device_t, cfdata_t, void *);
     68 void	audioamd_obio_attach(device_t, device_t, void *);
     69 int	audioamd_sbus_match(device_t, cfdata_t, void *);
     70 void	audioamd_sbus_attach(device_t, device_t, void *);
     71 void	audioamd_attach(struct audioamd_softc *, int);
     72 
     73 CFATTACH_DECL_NEW(audioamd_mainbus, sizeof(struct audioamd_softc),
     74     audioamd_mainbus_match, audioamd_mainbus_attach, NULL, NULL);
     75 
     76 CFATTACH_DECL_NEW(audioamd_obio, sizeof(struct audioamd_softc),
     77     audioamd_obio_match, audioamd_obio_attach, NULL, NULL);
     78 
     79 CFATTACH_DECL_NEW(audioamd_sbus, sizeof(struct audioamd_softc),
     80     audioamd_sbus_match, audioamd_sbus_attach, NULL, NULL);
     81 
     82 /*
     83  * Define our interface into the am7930 MI driver.
     84  */
     85 
     86 uint8_t	audioamd_codec_dread(struct am7930_softc *, int);
     87 void	audioamd_codec_dwrite(struct am7930_softc *, int, uint8_t);
     88 
     89 struct am7930_glue audioamd_glue = {
     90 	audioamd_codec_dread,
     91 	audioamd_codec_dwrite,
     92 };
     93 
     94 /*
     95  * Define our interface to the higher level audio driver.
     96  */
     97 int	audioamd_getdev(void *, struct audio_device *);
     98 
     99 const struct audio_hw_if sa_hw_if = {
    100 	.query_format		= am7930_query_format,
    101 	.set_format		= am7930_set_format,
    102 	.commit_settings	= am7930_commit_settings,
    103 	.trigger_output		= am7930_trigger_output,
    104 	.trigger_input		= am7930_trigger_input,
    105 	.halt_output		= am7930_halt_output,
    106 	.halt_input		= am7930_halt_input,
    107 	.getdev			= audioamd_getdev,
    108 	.set_port		= am7930_set_port,
    109 	.get_port		= am7930_get_port,
    110 	.query_devinfo		= am7930_query_devinfo,
    111 	.get_props		= am7930_get_props,
    112 	.get_locks		= am7930_get_locks,
    113 };
    114 
    115 struct audio_device audioamd_device = {
    116 	"am7930",
    117 	"x",
    118 	"audioamd"
    119 };
    120 
    121 
    122 int
    123 audioamd_mainbus_match(device_t parent, cfdata_t cf, void *aux)
    124 {
    125 	struct mainbus_attach_args *ma;
    126 
    127 	ma = aux;
    128 	if (CPU_ISSUN4)
    129 		return 0;
    130 	return strcmp(AUDIO_ROM_NAME, ma->ma_name) == 0;
    131 }
    132 
    133 int
    134 audioamd_obio_match(device_t parent, cfdata_t cf, void *aux)
    135 {
    136 	union obio_attach_args *uoba;
    137 
    138 	uoba = aux;
    139 	if (uoba->uoba_isobio4 != 0)
    140 		return 0;
    141 
    142 	return strcmp("audio", uoba->uoba_sbus.sa_name) == 0;
    143 }
    144 
    145 int
    146 audioamd_sbus_match(device_t parent, cfdata_t cf, void *aux)
    147 {
    148 	struct sbus_attach_args *sa;
    149 
    150 	sa = aux;
    151 	return strcmp(AUDIO_ROM_NAME, sa->sa_name) == 0;
    152 }
    153 
    154 void
    155 audioamd_mainbus_attach(device_t parent, device_t self, void *aux)
    156 {
    157 	struct mainbus_attach_args *ma;
    158 	struct audioamd_softc *sc;
    159 	bus_space_handle_t bh;
    160 
    161 	ma = aux;
    162 	sc = device_private(self);
    163 	sc->sc_am7930.sc_dev = self;
    164 	sc->sc_bt = ma->ma_bustag;
    165 
    166 	if (bus_space_map(
    167 			ma->ma_bustag,
    168 			ma->ma_paddr,
    169 			AM7930_DREG_SIZE,
    170 			BUS_SPACE_MAP_LINEAR,
    171 			&bh) != 0) {
    172 		printf("%s: cannot map registers\n", device_xname(self));
    173 		return;
    174 	}
    175 	sc->sc_bh = bh;
    176 	audioamd_attach(sc, ma->ma_pri);
    177 }
    178 
    179 void
    180 audioamd_obio_attach(device_t parent, device_t self, void *aux)
    181 {
    182 	union obio_attach_args *uoba;
    183 	struct sbus_attach_args *sa;
    184 	struct audioamd_softc *sc;
    185 	bus_space_handle_t bh;
    186 
    187 	uoba = aux;
    188 	sa = &uoba->uoba_sbus;
    189 	sc = device_private(self);
    190 	sc->sc_am7930.sc_dev = self;
    191 	sc->sc_bt = sa->sa_bustag;
    192 
    193 	if (sbus_bus_map(sa->sa_bustag,
    194 			 sa->sa_slot, sa->sa_offset,
    195 			 AM7930_DREG_SIZE,
    196 			 0, &bh) != 0) {
    197 		printf("%s: cannot map registers\n", device_xname(self));
    198 		return;
    199 	}
    200 	sc->sc_bh = bh;
    201 	audioamd_attach(sc, sa->sa_pri);
    202 }
    203 
    204 void
    205 audioamd_sbus_attach(device_t parent, device_t self, void *aux)
    206 {
    207 	struct sbus_attach_args *sa;
    208 	struct audioamd_softc *sc;
    209 	bus_space_handle_t bh;
    210 
    211 	sa = aux;
    212 	sc = device_private(self);
    213 	sc->sc_am7930.sc_dev = self;
    214 	sc->sc_bt = sa->sa_bustag;
    215 
    216 	if (sbus_bus_map(sa->sa_bustag,
    217 			 sa->sa_slot, sa->sa_offset,
    218 			 AM7930_DREG_SIZE,
    219 			 0, &bh) != 0) {
    220 		printf("%s: cannot map registers\n", device_xname(self));
    221 		return;
    222 	}
    223 	sc->sc_bh = bh;
    224 	audioamd_attach(sc, sa->sa_pri);
    225 }
    226 
    227 void
    228 audioamd_attach(struct audioamd_softc *sc, int pri)
    229 {
    230 	struct am7930_softc *amsc = &sc->sc_am7930;
    231 	device_t self;
    232 
    233 	/*
    234 	 * Set up glue for MI code early; we use some of it here.
    235 	 */
    236 	amsc->sc_glue = &audioamd_glue;
    237 	am7930_init(amsc, AUDIOAMD_POLL_MODE);
    238 
    239 	(void)bus_intr_establish2(sc->sc_bt, pri, IPL_HIGH,
    240 				  am7930_hwintr, sc, NULL);
    241 
    242 	printf("\n");
    243 
    244 	self = amsc->sc_dev;
    245 	evcnt_attach_dynamic(&amsc->sc_intrcnt, EVCNT_TYPE_INTR, NULL,
    246 	    device_xname(self), "intr");
    247 
    248 	audio_attach_mi(&sa_hw_if, sc, self);
    249 }
    250 
    251 
    252 /* direct read */
    253 uint8_t
    254 audioamd_codec_dread(struct am7930_softc *amsc, int reg)
    255 {
    256 	struct audioamd_softc *sc = (struct audioamd_softc *)amsc;
    257 
    258 	return bus_space_read_1(sc->sc_bt, sc->sc_bh, reg);
    259 }
    260 
    261 /* direct write */
    262 void
    263 audioamd_codec_dwrite(struct am7930_softc *amsc, int reg, uint8_t val)
    264 {
    265 	struct audioamd_softc *sc = (struct audioamd_softc *)amsc;
    266 
    267 	bus_space_write_1(sc->sc_bt, sc->sc_bh, reg, val);
    268 }
    269 
    270 int
    271 audioamd_getdev(void *addr, struct audio_device *retp)
    272 {
    273 
    274 	*retp = audioamd_device;
    275 	return 0;
    276 }
    277 
    278 #endif /* NAUDIO > 0 */
    279