This source file includes following definitions.
- ym_intr
- ym_attach
- ym_read
- ym_write
- ym_getdev
- ym_mute
- ym_set_master_gain
- ym_set_mic_gain
- ym_set_3d
- ym_mixer_set_port
- ym_mixer_get_port
- ym_query_devinfo
- ym_mpu401_open
- ym_mpu401_output
- ym_mpu401_close
- ym_mpu401_getinfo
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 #include "midi.h"
31
32 #include <sys/param.h>
33 #include <sys/systm.h>
34 #include <sys/errno.h>
35 #include <sys/ioctl.h>
36 #include <sys/syslog.h>
37 #include <sys/device.h>
38 #include <sys/proc.h>
39 #include <sys/buf.h>
40
41 #include <machine/cpu.h>
42 #include <machine/intr.h>
43 #include <machine/bus.h>
44
45 #include <sys/audioio.h>
46 #include <dev/audio_if.h>
47 #include <dev/midi_if.h>
48
49 #include <dev/isa/isavar.h>
50 #include <dev/isa/isadmavar.h>
51
52 #include <dev/ic/ad1848reg.h>
53 #include <dev/isa/ad1848var.h>
54 #include <dev/ic/opl3sa3reg.h>
55 #include <dev/ic/mpuvar.h>
56 #include <dev/isa/ymvar.h>
57
58 int ym_getdev(void *, struct audio_device *);
59 int ym_mixer_set_port(void *, mixer_ctrl_t *);
60 int ym_mixer_get_port(void *, mixer_ctrl_t *);
61 int ym_query_devinfo(void *, mixer_devinfo_t *);
62 int ym_intr(void *);
63
64 static void ym_mute(struct ym_softc *, int, int);
65 static void ym_set_master_gain(struct ym_softc *, struct ad1848_volume *);
66 static void ym_set_mic_gain(struct ym_softc *, int);
67 static void ym_set_3d(struct ym_softc *, mixer_ctrl_t *,
68 struct ad1848_volume *, int);
69
70 struct audio_hw_if ym_hw_if = {
71 ad1848_open,
72 ad1848_close,
73 NULL,
74 ad1848_query_encoding,
75 ad1848_set_params,
76 ad1848_round_blocksize,
77 ad1848_commit_settings,
78 ad1848_dma_init_output,
79 ad1848_dma_init_input,
80 ad1848_dma_output,
81 ad1848_dma_input,
82 ad1848_halt_out_dma,
83 ad1848_halt_in_dma,
84 NULL,
85 ym_getdev,
86 NULL,
87 ym_mixer_set_port,
88 ym_mixer_get_port,
89 ym_query_devinfo,
90 ad1848_malloc,
91 ad1848_free,
92 ad1848_round,
93 ad1848_mappage,
94 ad1848_get_props,
95 NULL,
96 NULL
97 };
98
99
100 struct cfdriver ym_cd = {
101 NULL, "ym", DV_DULL
102 };
103
104 struct audio_device ym_device = {
105 "ym,ad1848",
106 "",
107 "ym"
108 };
109
110 static __inline int ym_read(struct ym_softc *, int);
111 static __inline void ym_write(struct ym_softc *, int, int);
112
113 #if NMIDI > 0
114 int ym_mpu401_open(void *, int, void (*iintr)(void *, int),
115 void (*ointr)(void *), void *arg);
116 void ym_mpu401_close(void *);
117 int ym_mpu401_output(void *, int);
118 void ym_mpu401_getinfo(void *, struct midi_info *);
119
120 struct midi_hw_if ym_mpu401_hw_if = {
121 ym_mpu401_open,
122 ym_mpu401_close,
123 ym_mpu401_output,
124 0,
125 ym_mpu401_getinfo,
126 0,
127 };
128 #endif
129
130 int
131 ym_intr(v)
132 void *v;
133 {
134 #if NMIDI > 0
135 struct ym_softc *sc = v;
136
137 if ( sc->sc_hasmpu)
138 mpu_intr(&sc->sc_mpu_sc);
139 #endif
140 return ad1848_intr(v);
141 }
142
143 void
144 ym_attach(sc)
145 struct ym_softc *sc;
146
147 {
148 struct ad1848_volume vol_mid = {220, 220};
149 #if NMIDI > 0
150 struct midi_hw_if *mhw = &ym_mpu401_hw_if;
151 #endif
152
153 sc->sc_ih = isa_intr_establish(sc->sc_ic, sc->ym_irq, IST_EDGE,
154 IPL_AUDIO, ym_intr, &sc->sc_ad1848, sc->sc_dev.dv_xname);
155
156 ad1848_attach(&sc->sc_ad1848);
157 printf("\n");
158 sc->sc_ad1848.parent = sc;
159
160
161 ym_set_master_gain(sc, &vol_mid);
162 ym_set_mic_gain(sc, 0);
163 sc->master_mute = 0;
164 ym_mute(sc, SA3_VOL_L, sc->master_mute);
165 ym_mute(sc, SA3_VOL_R, sc->master_mute);
166
167 sc->mic_mute = 1;
168 ym_mute(sc, SA3_MIC_VOL, sc->mic_mute);
169
170 #if NMIDI > 0
171 sc->sc_hasmpu = 0;
172 if (sc->sc_mpu_sc.iobase) {
173 sc->sc_mpu_sc.iot = sc->sc_iot;
174 if (mpu_find(&sc->sc_mpu_sc)) {
175 sc->sc_hasmpu = 1;
176 mhw = &ym_mpu401_hw_if;
177 }
178 }
179 midi_attach_mi(mhw, sc, &sc->sc_dev);
180 #endif
181
182 audio_attach_mi(&ym_hw_if, &sc->sc_ad1848, &sc->sc_dev);
183 }
184
185 static __inline int
186 ym_read(sc, reg)
187 struct ym_softc *sc;
188 int reg;
189 {
190 bus_space_write_1(sc->sc_iot, sc->sc_controlioh, SA3_CTL_INDEX,
191 (reg & 0xff));
192 return (bus_space_read_1(sc->sc_iot, sc->sc_controlioh, SA3_CTL_DATA));
193 }
194
195 static __inline void
196 ym_write(sc, reg, data)
197 struct ym_softc *sc;
198 int reg;
199 int data;
200 {
201 bus_space_write_1(sc->sc_iot, sc->sc_controlioh, SA3_CTL_INDEX,
202 (reg & 0xff));
203 bus_space_write_1(sc->sc_iot, sc->sc_controlioh, SA3_CTL_DATA,
204 (data & 0xff));
205 }
206
207
208
209 int
210 ym_getdev(addr, retp)
211 void *addr;
212 struct audio_device *retp;
213 {
214 *retp = ym_device;
215 return 0;
216 }
217
218
219 static ad1848_devmap_t mappings[] = {
220 { YM_MIDI_LVL, AD1848_KIND_LVL, AD1848_AUX2_CHANNEL },
221 { YM_CD_LVL, AD1848_KIND_LVL, AD1848_AUX1_CHANNEL },
222 { YM_DAC_LVL, AD1848_KIND_LVL, AD1848_DAC_CHANNEL },
223 { YM_LINE_LVL, AD1848_KIND_LVL, AD1848_LINE_CHANNEL },
224 { YM_SPEAKER_LVL, AD1848_KIND_LVL, AD1848_MONO_CHANNEL },
225 { YM_MONITOR_LVL, AD1848_KIND_LVL, AD1848_MONITOR_CHANNEL },
226 { YM_MIDI_MUTE, AD1848_KIND_MUTE, AD1848_AUX2_CHANNEL },
227 { YM_CD_MUTE, AD1848_KIND_MUTE, AD1848_AUX1_CHANNEL },
228 { YM_DAC_MUTE, AD1848_KIND_MUTE, AD1848_DAC_CHANNEL },
229 { YM_LINE_MUTE, AD1848_KIND_MUTE, AD1848_LINE_CHANNEL },
230 { YM_SPEAKER_MUTE, AD1848_KIND_MUTE, AD1848_MONO_CHANNEL },
231 { YM_MONITOR_MUTE, AD1848_KIND_MUTE, AD1848_MONITOR_CHANNEL },
232 { YM_REC_LVL, AD1848_KIND_RECORDGAIN, -1 },
233 { YM_RECORD_SOURCE, AD1848_KIND_RECORDSOURCE, -1 }
234 };
235
236 #define NUMMAP (sizeof(mappings) / sizeof(mappings[0]))
237
238
239 static void
240 ym_mute(sc, left_reg, mute)
241 struct ym_softc *sc;
242 int left_reg;
243 int mute;
244 {
245 u_int8_t reg;
246
247 reg = ym_read(sc, left_reg);
248 if (mute)
249 ym_write(sc, left_reg, reg | 0x80);
250 else
251 ym_write(sc, left_reg, reg & ~0x80);
252 }
253
254 static void
255 ym_set_master_gain(sc, vol)
256 struct ym_softc *sc;
257 struct ad1848_volume *vol;
258 {
259 u_int atten;
260
261 sc->master_gain = *vol;
262
263 atten = ((AUDIO_MAX_GAIN - vol->left) * (SA3_VOL_MV + 1)) /
264 (AUDIO_MAX_GAIN + 1);
265
266 ym_write(sc, SA3_VOL_L, (ym_read(sc, SA3_VOL_L) & ~SA3_VOL_MV) | atten);
267
268 atten = ((AUDIO_MAX_GAIN - vol->right) * (SA3_VOL_MV + 1)) /
269 (AUDIO_MAX_GAIN + 1);
270
271 ym_write(sc, SA3_VOL_R, (ym_read(sc, SA3_VOL_R) & ~SA3_VOL_MV) | atten);
272 }
273
274 static void
275 ym_set_mic_gain(sc, vol)
276 struct ym_softc *sc;
277 int vol;
278 {
279 u_int atten;
280
281 sc->mic_gain = vol;
282
283 atten = ((AUDIO_MAX_GAIN - vol) * (SA3_MIC_MCV + 1)) /
284 (AUDIO_MAX_GAIN + 1);
285
286 ym_write(sc, SA3_MIC_VOL,
287 (ym_read(sc, SA3_MIC_VOL) & ~SA3_MIC_MCV) | atten);
288 }
289
290 static void
291 ym_set_3d(sc, cp, val, reg)
292 struct ym_softc *sc;
293 mixer_ctrl_t *cp;
294 struct ad1848_volume *val;
295 int reg;
296 {
297 u_int8_t e;
298
299 ad1848_to_vol(cp, val);
300
301 e = (val->left * (SA3_3D_BITS + 1) + (SA3_3D_BITS + 1) / 2) /
302 (AUDIO_MAX_GAIN + 1) << SA3_3D_LSHIFT |
303 (val->right * (SA3_3D_BITS + 1) + (SA3_3D_BITS + 1) / 2) /
304 (AUDIO_MAX_GAIN + 1) << SA3_3D_RSHIFT;
305
306 ym_write(sc, reg, e);
307 }
308
309 int
310 ym_mixer_set_port(addr, cp)
311 void *addr;
312 mixer_ctrl_t *cp;
313 {
314 struct ad1848_softc *ac = addr;
315 struct ym_softc *sc = ac->parent;
316 struct ad1848_volume vol;
317 int error = ad1848_mixer_set_port(ac, mappings, NUMMAP, cp);
318
319 if (error != ENXIO)
320 return (error);
321
322 error = 0;
323
324 switch (cp->dev) {
325 case YM_OUTPUT_LVL:
326 ad1848_to_vol(cp, &vol);
327 ym_set_master_gain(sc, &vol);
328 break;
329
330 case YM_OUTPUT_MUTE:
331 sc->master_mute = (cp->un.ord != 0);
332 ym_mute(sc, SA3_VOL_L, sc->master_mute);
333 ym_mute(sc, SA3_VOL_R, sc->master_mute);
334 break;
335
336 case YM_MIC_LVL:
337 if (cp->un.value.num_channels != 1)
338 error = EINVAL;
339 else
340 ym_set_mic_gain(sc,
341 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]);
342 break;
343
344 case YM_MASTER_EQMODE:
345 sc->sc_eqmode = cp->un.ord & SA3_SYS_CTL_YMODE;
346 ym_write(sc, SA3_SYS_CTL, (ym_read(sc, SA3_SYS_CTL) &
347 ~SA3_SYS_CTL_YMODE) | sc->sc_eqmode);
348 break;
349
350 case YM_MASTER_TREBLE:
351 ym_set_3d(sc, cp, &sc->sc_treble, SA3_3D_TREBLE);
352 break;
353
354 case YM_MASTER_BASS:
355 ym_set_3d(sc, cp, &sc->sc_bass, SA3_3D_BASS);
356 break;
357
358 case YM_MASTER_WIDE:
359 ym_set_3d(sc, cp, &sc->sc_wide, SA3_3D_WIDE);
360 break;
361
362 case YM_MIC_MUTE:
363 sc->mic_mute = (cp->un.ord != 0);
364 ym_mute(sc, SA3_MIC_VOL, sc->mic_mute);
365 break;
366
367 default:
368 return ENXIO;
369
370 }
371
372 return (error);
373 }
374
375 int
376 ym_mixer_get_port(addr, cp)
377 void *addr;
378 mixer_ctrl_t *cp;
379 {
380 struct ad1848_softc *ac = addr;
381 struct ym_softc *sc = ac->parent;
382
383 int error = ad1848_mixer_get_port(ac, mappings, NUMMAP, cp);
384
385 if (error != ENXIO)
386 return (error);
387
388 error = 0;
389
390 switch (cp->dev) {
391 case YM_OUTPUT_LVL:
392 ad1848_from_vol(cp, &sc->master_gain);
393 break;
394
395 case YM_OUTPUT_MUTE:
396 cp->un.ord = sc->master_mute;
397 break;
398
399 case YM_MIC_LVL:
400 if (cp->un.value.num_channels != 1)
401 error = EINVAL;
402 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = sc->mic_gain;
403 break;
404
405 case YM_MASTER_EQMODE:
406 cp->un.ord = sc->sc_eqmode;
407 break;
408
409 case YM_MASTER_TREBLE:
410 ad1848_from_vol(cp, &sc->sc_treble);
411 break;
412
413 case YM_MASTER_BASS:
414 ad1848_from_vol(cp, &sc->sc_bass);
415 break;
416
417 case YM_MASTER_WIDE:
418 ad1848_from_vol(cp, &sc->sc_wide);
419 break;
420
421 case YM_MIC_MUTE:
422 cp->un.ord = sc->mic_mute;
423 break;
424
425 default:
426 error = ENXIO;
427 break;
428 }
429
430 return (error);
431 }
432
433 static char *mixer_classes[] = {
434 AudioCinputs, AudioCrecord, AudioCoutputs, AudioCmonitor,
435 AudioCequalization
436 };
437
438 int
439 ym_query_devinfo(addr, dip)
440 void *addr;
441 mixer_devinfo_t *dip;
442 {
443 static char *mixer_port_names[] = { AudioNmidi, AudioNcd, AudioNdac,
444 AudioNline, AudioNspeaker, AudioNmicrophone, AudioNmonitor
445 };
446
447 dip->next = dip->prev = AUDIO_MIXER_LAST;
448
449 switch (dip->index) {
450 case YM_INPUT_CLASS:
451 case YM_OUTPUT_CLASS:
452 case YM_MONITOR_CLASS:
453 case YM_RECORD_CLASS:
454 case YM_EQ_CLASS:
455 dip->type = AUDIO_MIXER_CLASS;
456 dip->mixer_class = dip->index;
457 strlcpy(dip->label.name,
458 mixer_classes[dip->index - YM_INPUT_CLASS],
459 sizeof dip->label.name);
460 break;
461
462 case YM_MIDI_LVL:
463 case YM_CD_LVL:
464 case YM_DAC_LVL:
465 case YM_LINE_LVL:
466 case YM_SPEAKER_LVL:
467 case YM_MIC_LVL:
468 case YM_MONITOR_LVL:
469 dip->type = AUDIO_MIXER_VALUE;
470 if (dip->index == YM_MONITOR_LVL)
471 dip->mixer_class = YM_MONITOR_CLASS;
472 else
473 dip->mixer_class = YM_INPUT_CLASS;
474
475 dip->next = dip->index + 7;
476
477 strlcpy(dip->label.name,
478 mixer_port_names[dip->index - YM_MIDI_LVL],
479 sizeof dip->label.name);
480
481 if (dip->index == YM_SPEAKER_LVL ||
482 dip->index == YM_MIC_LVL)
483 dip->un.v.num_channels = 1;
484 else
485 dip->un.v.num_channels = 2;
486
487 strlcpy(dip->un.v.units.name, AudioNvolume,
488 sizeof dip->un.v.units.name);
489 break;
490
491 case YM_MIDI_MUTE:
492 case YM_CD_MUTE:
493 case YM_DAC_MUTE:
494 case YM_LINE_MUTE:
495 case YM_SPEAKER_MUTE:
496 case YM_MIC_MUTE:
497 case YM_MONITOR_MUTE:
498 if (dip->index == YM_MONITOR_MUTE)
499 dip->mixer_class = YM_MONITOR_CLASS;
500 else
501 dip->mixer_class = YM_INPUT_CLASS;
502 dip->type = AUDIO_MIXER_ENUM;
503 dip->prev = dip->index - 7;
504 mute:
505 strlcpy(dip->label.name, AudioNmute, sizeof dip->label.name);
506 dip->un.e.num_mem = 2;
507 strlcpy(dip->un.e.member[0].label.name, AudioNoff,
508 sizeof dip->un.e.member[0].label.name);
509 dip->un.e.member[0].ord = 0;
510 strlcpy(dip->un.e.member[1].label.name, AudioNon,
511 sizeof dip->un.e.member[1].label.name);
512 dip->un.e.member[1].ord = 1;
513 break;
514
515
516 case YM_OUTPUT_LVL:
517 dip->type = AUDIO_MIXER_VALUE;
518 dip->mixer_class = YM_OUTPUT_CLASS;
519 dip->next = YM_OUTPUT_MUTE;
520 strlcpy(dip->label.name, AudioNmaster, sizeof dip->label.name);
521 dip->un.v.num_channels = 2;
522 strlcpy(dip->un.v.units.name, AudioNvolume,
523 sizeof dip->un.v.units.name);
524 break;
525
526 case YM_OUTPUT_MUTE:
527 dip->mixer_class = YM_OUTPUT_CLASS;
528 dip->type = AUDIO_MIXER_ENUM;
529 dip->prev = YM_OUTPUT_LVL;
530 goto mute;
531
532 case YM_REC_LVL:
533 dip->type = AUDIO_MIXER_VALUE;
534 dip->mixer_class = YM_RECORD_CLASS;
535 dip->next = YM_RECORD_SOURCE;
536 strlcpy(dip->label.name, AudioNrecord, sizeof dip->label.name);
537 dip->un.v.num_channels = 2;
538 strlcpy(dip->un.v.units.name, AudioNvolume,
539 sizeof dip->un.v.units.name);
540 break;
541
542
543 case YM_RECORD_SOURCE:
544 dip->mixer_class = YM_RECORD_CLASS;
545 dip->type = AUDIO_MIXER_ENUM;
546 dip->prev = YM_REC_LVL;
547 strlcpy(dip->label.name, AudioNsource, sizeof dip->label.name);
548 dip->un.e.num_mem = 4;
549 strlcpy(dip->un.e.member[0].label.name, AudioNmicrophone,
550 sizeof dip->un.e.member[0].label.name);
551 dip->un.e.member[0].ord = MIC_IN_PORT;
552 strlcpy(dip->un.e.member[1].label.name, AudioNline,
553 sizeof dip->un.e.member[1].label.name);
554 dip->un.e.member[1].ord = LINE_IN_PORT;
555 strlcpy(dip->un.e.member[2].label.name, AudioNdac,
556 sizeof dip->un.e.member[2].label.name);
557 dip->un.e.member[2].ord = DAC_IN_PORT;
558 strlcpy(dip->un.e.member[3].label.name, AudioNcd,
559 sizeof dip->un.e.member[3].label.name);
560 dip->un.e.member[3].ord = AUX1_IN_PORT;
561 break;
562
563 case YM_MASTER_EQMODE:
564 dip->type = AUDIO_MIXER_ENUM;
565 dip->mixer_class = YM_EQ_CLASS;
566 strlcpy(dip->label.name, AudioNmode, sizeof dip->label.name);
567 strlcpy(dip->un.v.units.name, AudioNmode,
568 sizeof dip->un.v.units.name);
569 dip->un.e.num_mem = 4;
570 strlcpy(dip->un.e.member[0].label.name, AudioNdesktop,
571 sizeof dip->un.e.member[0].label.name);
572 dip->un.e.member[0].ord = SA3_SYS_CTL_YMODE0;
573 strlcpy(dip->un.e.member[1].label.name, AudioNlaptop,
574 sizeof dip->un.e.member[1].label.name);
575 dip->un.e.member[1].ord = SA3_SYS_CTL_YMODE1;
576 strlcpy(dip->un.e.member[2].label.name, AudioNsubnote,
577 sizeof dip->un.e.member[2].label.name);
578 dip->un.e.member[2].ord = SA3_SYS_CTL_YMODE2;
579 strlcpy(dip->un.e.member[3].label.name, AudioNhifi,
580 sizeof dip->un.e.member[3].label.name);
581 dip->un.e.member[3].ord = SA3_SYS_CTL_YMODE3;
582 break;
583
584 case YM_MASTER_TREBLE:
585 dip->type = AUDIO_MIXER_VALUE;
586 dip->mixer_class = YM_EQ_CLASS;
587 strlcpy(dip->label.name, AudioNtreble, sizeof dip->label.name);
588 dip->un.v.num_channels = 2;
589 strlcpy(dip->un.v.units.name, AudioNtreble,
590 sizeof dip->un.v.units.name);
591 break;
592
593 case YM_MASTER_BASS:
594 dip->type = AUDIO_MIXER_VALUE;
595 dip->mixer_class = YM_EQ_CLASS;
596 strlcpy(dip->label.name, AudioNbass, sizeof dip->label.name);
597 dip->un.v.num_channels = 2;
598 strlcpy(dip->un.v.units.name, AudioNbass,
599 sizeof dip->un.v.units.name);
600 break;
601
602 case YM_MASTER_WIDE:
603 dip->type = AUDIO_MIXER_VALUE;
604 dip->mixer_class = YM_EQ_CLASS;
605 strlcpy(dip->label.name, AudioNsurround,
606 sizeof dip->label.name);
607 dip->un.v.num_channels = 2;
608 strlcpy(dip->un.v.units.name, AudioNsurround,
609 sizeof dip->un.v.units.name);
610 break;
611
612 default:
613 return ENXIO;
614
615 }
616
617 return 0;
618 }
619 #if NMIDI > 0
620
621 #define YMMPU(a) (&((struct ym_softc *)addr)->sc_mpu_sc)
622
623 int
624 ym_mpu401_open(addr, flags, iintr, ointr, arg)
625 void *addr;
626 int flags;
627 void (*iintr)(void *, int);
628 void (*ointr)(void *);
629 void *arg;
630 {
631 return mpu_open(YMMPU(addr), flags, iintr, ointr, arg);
632 }
633
634 int
635 ym_mpu401_output(addr, d)
636 void *addr;
637 int d;
638 {
639 return mpu_output(YMMPU(addr), d);
640 }
641
642 void
643 ym_mpu401_close(addr)
644 void *addr;
645 {
646 mpu_close(YMMPU(addr));
647 }
648
649 void
650 ym_mpu401_getinfo(addr, mi)
651 void *addr;
652 struct midi_info *mi;
653 {
654 mi->name = "YM MPU-401 UART";
655 mi->props = 0;
656 }
657 #endif