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
audioamd_mainbus_match(device_t parent,cfdata_t cf,void * aux)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
audioamd_obio_match(device_t parent,cfdata_t cf,void * aux)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
audioamd_sbus_match(device_t parent,cfdata_t cf,void * aux)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
audioamd_mainbus_attach(device_t parent,device_t self,void * aux)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
audioamd_obio_attach(device_t parent,device_t self,void * aux)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
audioamd_sbus_attach(device_t parent,device_t self,void * aux)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
audioamd_attach(struct audioamd_softc * sc,int pri)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
audioamd_codec_dread(struct am7930_softc * amsc,int reg)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
audioamd_codec_dwrite(struct am7930_softc * amsc,int reg,uint8_t val)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
audioamd_getdev(void * addr,struct audio_device * retp)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