This source file includes following definitions.
- wssattach
- wss_getdev
- wss_mixer_set_port
- wss_mixer_get_port
- wss_query_devinfo
- mad_read
- mad_write
- madattach
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39 #include <sys/param.h>
40 #include <sys/systm.h>
41 #include <sys/errno.h>
42 #include <sys/ioctl.h>
43 #include <sys/syslog.h>
44 #include <sys/device.h>
45 #include <sys/proc.h>
46 #include <sys/buf.h>
47
48 #include <machine/cpu.h>
49 #include <machine/intr.h>
50 #include <machine/bus.h>
51
52 #include <sys/audioio.h>
53 #include <dev/audio_if.h>
54
55 #include <dev/isa/isavar.h>
56 #include <dev/isa/isadmavar.h>
57
58 #include <dev/ic/ad1848reg.h>
59 #include <dev/isa/ad1848var.h>
60 #include <dev/isa/wssreg.h>
61 #include <dev/isa/wssvar.h>
62 #include <dev/isa/madreg.h>
63
64 #ifdef AUDIO_DEBUG
65 #define DPRINTF(x) if (wssdebug) printf x
66 int wssdebug = 0;
67 #else
68 #define DPRINTF(x)
69 #endif
70
71 struct audio_device wss_device = {
72 "wss,ad1848",
73 "",
74 "WSS"
75 };
76
77 int wss_getdev(void *, struct audio_device *);
78
79 int wss_mixer_set_port(void *, mixer_ctrl_t *);
80 int wss_mixer_get_port(void *, mixer_ctrl_t *);
81 int wss_query_devinfo(void *, mixer_devinfo_t *);
82
83
84
85
86
87 struct audio_hw_if wss_hw_if = {
88 ad1848_open,
89 ad1848_close,
90 NULL,
91 ad1848_query_encoding,
92 ad1848_set_params,
93 ad1848_round_blocksize,
94 ad1848_commit_settings,
95 ad1848_dma_init_output,
96 ad1848_dma_init_input,
97 ad1848_dma_output,
98 ad1848_dma_input,
99 ad1848_halt_out_dma,
100 ad1848_halt_in_dma,
101 NULL,
102 wss_getdev,
103 NULL,
104 wss_mixer_set_port,
105 wss_mixer_get_port,
106 wss_query_devinfo,
107 ad1848_malloc,
108 ad1848_free,
109 ad1848_round,
110 ad1848_mappage,
111 ad1848_get_props,
112 NULL,
113 NULL
114 };
115
116
117
118
119
120 void
121 wssattach(sc)
122 struct wss_softc *sc;
123 {
124 int version;
125
126 madattach(sc);
127
128 sc->sc_ih = isa_intr_establish(sc->sc_ic, sc->wss_irq, IST_EDGE, IPL_AUDIO,
129 ad1848_intr, &sc->sc_ad1848, sc->sc_dev.dv_xname);
130
131 ad1848_attach(&sc->sc_ad1848);
132
133 version = bus_space_read_1(sc->sc_iot, sc->sc_ioh, WSS_STATUS) & WSS_VERSMASK;
134 printf(" (vers %d)", version);
135 switch(sc->mad_chip_type) {
136 case MAD_82C928:
137 printf(", 82C928");
138 break;
139 case MAD_OTI601D:
140 printf(", OTI-601D");
141 break;
142 case MAD_82C929:
143 printf(", 82C929");
144 break;
145 case MAD_82C931:
146 printf(", 82C931");
147 break;
148 default:
149 break;
150 }
151 printf("\n");
152
153 sc->sc_ad1848.parent = sc;
154
155 audio_attach_mi(&wss_hw_if, &sc->sc_ad1848, &sc->sc_dev);
156 }
157
158 int
159 wss_getdev(addr, retp)
160 void *addr;
161 struct audio_device *retp;
162 {
163 *retp = wss_device;
164 return 0;
165 }
166
167 static ad1848_devmap_t mappings[] = {
168 { WSS_MIC_IN_LVL, AD1848_KIND_LVL, AD1848_AUX2_CHANNEL },
169 { WSS_LINE_IN_LVL, AD1848_KIND_LVL, AD1848_AUX1_CHANNEL },
170 { WSS_DAC_LVL, AD1848_KIND_LVL, AD1848_DAC_CHANNEL },
171 { WSS_MON_LVL, AD1848_KIND_LVL, AD1848_MONO_CHANNEL },
172 { WSS_MIC_IN_MUTE, AD1848_KIND_MUTE, AD1848_AUX2_CHANNEL },
173 { WSS_LINE_IN_MUTE, AD1848_KIND_MUTE, AD1848_AUX1_CHANNEL },
174 { WSS_DAC_MUTE, AD1848_KIND_MUTE, AD1848_DAC_CHANNEL },
175 { WSS_REC_LVL, AD1848_KIND_RECORDGAIN, -1 },
176 { WSS_RECORD_SOURCE, AD1848_KIND_RECORDSOURCE, -1}
177 };
178
179 static int nummap = sizeof(mappings) / sizeof(mappings[0]);
180
181 int
182 wss_mixer_set_port(addr, cp)
183 void *addr;
184 mixer_ctrl_t *cp;
185 {
186 struct ad1848_softc *ac = addr;
187
188 return (ad1848_mixer_set_port(ac, mappings, nummap, cp));
189 }
190
191 int
192 wss_mixer_get_port(addr, cp)
193 void *addr;
194 mixer_ctrl_t *cp;
195 {
196 struct ad1848_softc *ac = addr;
197
198 return (ad1848_mixer_get_port(ac, mappings, nummap, cp));
199 }
200
201 int
202 wss_query_devinfo(addr, dip)
203 void *addr;
204 mixer_devinfo_t *dip;
205 {
206 DPRINTF(("wss_query_devinfo: index=%d\n", dip->index));
207
208 switch(dip->index) {
209 case WSS_MIC_IN_LVL:
210 dip->type = AUDIO_MIXER_VALUE;
211 dip->mixer_class = WSS_INPUT_CLASS;
212 dip->prev = AUDIO_MIXER_LAST;
213 dip->next = WSS_MIC_IN_MUTE;
214 strlcpy(dip->label.name, AudioNmicrophone, sizeof dip->label.name);
215 dip->un.v.num_channels = 2;
216 strlcpy(dip->un.v.units.name, AudioNvolume, sizeof dip->un.v.units.name);
217 break;
218
219 case WSS_LINE_IN_LVL:
220 dip->type = AUDIO_MIXER_VALUE;
221 dip->mixer_class = WSS_INPUT_CLASS;
222 dip->prev = AUDIO_MIXER_LAST;
223 dip->next = WSS_LINE_IN_MUTE;
224 strlcpy(dip->label.name, AudioNcd, sizeof dip->label.name);
225 dip->un.v.num_channels = 2;
226 strlcpy(dip->un.v.units.name, AudioNvolume, sizeof dip->un.v.units.name);
227 break;
228
229 case WSS_DAC_LVL:
230 dip->type = AUDIO_MIXER_VALUE;
231 dip->mixer_class = WSS_INPUT_CLASS;
232 dip->prev = AUDIO_MIXER_LAST;
233 dip->next = WSS_DAC_MUTE;
234 strlcpy(dip->label.name, AudioNdac, sizeof dip->label.name);
235 dip->un.v.num_channels = 2;
236 strlcpy(dip->un.v.units.name, AudioNvolume, sizeof dip->un.v.units.name);
237 break;
238
239 case WSS_REC_LVL:
240 dip->type = AUDIO_MIXER_VALUE;
241 dip->mixer_class = WSS_RECORD_CLASS;
242 dip->prev = AUDIO_MIXER_LAST;
243 dip->next = WSS_RECORD_SOURCE;
244 strlcpy(dip->label.name, AudioNrecord, sizeof dip->label.name);
245 dip->un.v.num_channels = 2;
246 strlcpy(dip->un.v.units.name, AudioNvolume, sizeof dip->un.v.units.name);
247 break;
248
249 case WSS_MON_LVL:
250 dip->type = AUDIO_MIXER_VALUE;
251 dip->mixer_class = WSS_MONITOR_CLASS;
252 dip->next = dip->prev = AUDIO_MIXER_LAST;
253 strlcpy(dip->label.name, AudioNmonitor, sizeof dip->label.name);
254 dip->un.v.num_channels = 1;
255 strlcpy(dip->un.v.units.name, AudioNvolume, sizeof dip->un.v.units.name);
256 break;
257
258 case WSS_INPUT_CLASS:
259 dip->type = AUDIO_MIXER_CLASS;
260 dip->mixer_class = WSS_INPUT_CLASS;
261 dip->next = dip->prev = AUDIO_MIXER_LAST;
262 strlcpy(dip->label.name, AudioCinputs, sizeof dip->label.name);
263 break;
264
265 case WSS_MONITOR_CLASS:
266 dip->type = AUDIO_MIXER_CLASS;
267 dip->mixer_class = WSS_MONITOR_CLASS;
268 dip->next = dip->prev = AUDIO_MIXER_LAST;
269 strlcpy(dip->label.name, AudioCmonitor, sizeof dip->label.name);
270 break;
271
272 case WSS_RECORD_CLASS:
273 dip->type = AUDIO_MIXER_CLASS;
274 dip->mixer_class = WSS_RECORD_CLASS;
275 dip->next = dip->prev = AUDIO_MIXER_LAST;
276 strlcpy(dip->label.name, AudioCrecord, sizeof dip->label.name);
277 break;
278
279 case WSS_MIC_IN_MUTE:
280 dip->mixer_class = WSS_INPUT_CLASS;
281 dip->type = AUDIO_MIXER_ENUM;
282 dip->prev = WSS_MIC_IN_LVL;
283 dip->next = AUDIO_MIXER_LAST;
284 goto mute;
285
286 case WSS_LINE_IN_MUTE:
287 dip->mixer_class = WSS_INPUT_CLASS;
288 dip->type = AUDIO_MIXER_ENUM;
289 dip->prev = WSS_LINE_IN_LVL;
290 dip->next = AUDIO_MIXER_LAST;
291 goto mute;
292
293 case WSS_DAC_MUTE:
294 dip->mixer_class = WSS_INPUT_CLASS;
295 dip->type = AUDIO_MIXER_ENUM;
296 dip->prev = WSS_DAC_LVL;
297 dip->next = AUDIO_MIXER_LAST;
298 mute:
299 strlcpy(dip->label.name, AudioNmute, sizeof dip->label.name);
300 dip->un.e.num_mem = 2;
301 strlcpy(dip->un.e.member[0].label.name, AudioNoff,
302 sizeof dip->un.e.member[0].label.name);
303 dip->un.e.member[0].ord = 0;
304 strlcpy(dip->un.e.member[1].label.name, AudioNon,
305 sizeof dip->un.e.member[1].label.name);
306 dip->un.e.member[1].ord = 1;
307 break;
308
309 case WSS_RECORD_SOURCE:
310 dip->mixer_class = WSS_RECORD_CLASS;
311 dip->type = AUDIO_MIXER_ENUM;
312 dip->prev = WSS_REC_LVL;
313 dip->next = AUDIO_MIXER_LAST;
314 strlcpy(dip->label.name, AudioNsource, sizeof dip->label.name);
315 dip->un.e.num_mem = 3;
316 strlcpy(dip->un.e.member[0].label.name, AudioNmicrophone,
317 sizeof dip->un.e.member[0].label.name);
318 dip->un.e.member[0].ord = WSS_MIC_IN_LVL;
319 strlcpy(dip->un.e.member[1].label.name, AudioNcd,
320 sizeof dip->un.e.member[1].label.name);
321 dip->un.e.member[1].ord = WSS_LINE_IN_LVL;
322 strlcpy(dip->un.e.member[2].label.name, AudioNdac,
323 sizeof dip->un.e.member[2].label.name);
324 dip->un.e.member[2].ord = WSS_DAC_LVL;
325 break;
326
327 default:
328 return ENXIO;
329
330 }
331 DPRINTF(("AUDIO_MIXER_DEVINFO: name=%s\n", dip->label.name));
332
333 return 0;
334 }
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370 u_int
371 mad_read(sc, port)
372 struct wss_softc *sc;
373 int port;
374 {
375 u_int tmp;
376 int pwd;
377 int s;
378
379 switch (sc->mad_chip_type) {
380 case MAD_82C928:
381 case MAD_OTI601D:
382 pwd = M_PASSWD_928;
383 break;
384 case MAD_82C929:
385 pwd = M_PASSWD_929;
386 break;
387 case MAD_82C931:
388 pwd = M_PASSWD_931;
389 break;
390 default:
391 panic("mad_read: Bad chip type=%d", sc->mad_chip_type);
392 }
393 s = splaudio();
394 bus_space_write_1(sc->sc_iot, sc->mad_ioh, MC_PASSWD_REG, pwd);
395 tmp = bus_space_read_1(sc->sc_iot, sc->mad_ioh, port);
396 splx(s);
397 return tmp;
398 }
399
400 void
401 mad_write(sc, port, value)
402 struct wss_softc *sc;
403 int port;
404 int value;
405 {
406 int pwd;
407 int s;
408
409 switch (sc->mad_chip_type) {
410 case MAD_82C928:
411 case MAD_OTI601D:
412 pwd = M_PASSWD_928;
413 break;
414 case MAD_82C929:
415 pwd = M_PASSWD_929;
416 break;
417 case MAD_82C931:
418 pwd = M_PASSWD_931;
419 break;
420 default:
421 panic("mad_write: Bad chip type=%d", sc->mad_chip_type);
422 }
423 s = splaudio();
424 bus_space_write_1(sc->sc_iot, sc->mad_ioh, MC_PASSWD_REG, pwd);
425 bus_space_write_1(sc->sc_iot, sc->mad_ioh, port, value & 0xff);
426 splx(s);
427 }
428
429 void
430 madattach(sc)
431 struct wss_softc *sc;
432 {
433 unsigned char cs4231_mode;
434 int joy;
435
436 if (sc->mad_chip_type == MAD_NONE)
437 return;
438
439
440 joy = sc->sc_dev.dv_cfdata->cf_flags & 2 ? MC1_JOYDISABLE : 0;
441
442
443 mad_write(sc, MC1_PORT, M_WSS_PORT_SELECT(sc->mad_ioindex) | joy);
444 mad_write(sc, MC2_PORT, 0x03);
445 mad_write(sc, MC3_PORT, 0xf0);
446
447 cs4231_mode =
448 strncmp(sc->sc_ad1848.chip_name, "CS4248", 6) == 0 ||
449 strncmp(sc->sc_ad1848.chip_name, "CS4231", 6) == 0 ? 0x02 : 0;
450
451 if (sc->mad_chip_type == MAD_82C929) {
452 mad_write(sc, MC4_PORT, 0x92);
453 mad_write(sc, MC5_PORT, 0xA5 | cs4231_mode);
454 mad_write(sc, MC6_PORT, 0x03);
455 } else {
456 mad_write(sc, MC4_PORT, 0x02);
457 mad_write(sc, MC5_PORT, 0x30 | cs4231_mode);
458 }
459
460 #ifdef AUDIO_DEBUG
461 if (wssdebug) {
462 int i;
463 for (i = MC1_PORT; i <= MC7_PORT; i++)
464 DPRINTF(("port %03x after init = %02x\n", i, mad_read(sc, i)));
465 }
466 #endif
467 }