ym.c revision 1.3 1 /* $NetBSD: ym.c,v 1.3 1998/06/17 08:17:25 augustss Exp $ */
2
3
4 /*
5 * Copyright (c) 1998 Constantine Sapuntzakis. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30 /*
31 * Original code from OpenBSD.
32 */
33
34
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/errno.h>
38 #include <sys/ioctl.h>
39 #include <sys/syslog.h>
40 #include <sys/device.h>
41 #include <sys/proc.h>
42 #include <sys/buf.h>
43
44 #include <machine/cpu.h>
45 #include <machine/intr.h>
46 #include <machine/bus.h>
47
48 #include <sys/audioio.h>
49 #include <dev/audio_if.h>
50
51 #include <dev/isa/isavar.h>
52 #include <dev/isa/isadmavar.h>
53
54 #include <dev/ic/ad1848reg.h>
55 #include <dev/isa/ad1848var.h>
56 #include <dev/ic/opl3sa3.h>
57 #include <dev/isa/ymvar.h>
58
59
60 int ym_getdev __P((void *, struct audio_device *));
61 int ym_mixer_set_port __P((void *, mixer_ctrl_t *));
62 int ym_mixer_get_port __P((void *, mixer_ctrl_t *));
63 int ym_query_devinfo __P((void *, mixer_devinfo_t *));
64
65 static void ym_mute __P((struct ym_softc *, int, int));
66 static void ym_set_master_gain __P((struct ym_softc *, struct ad1848_volume*));
67 static void ym_set_mic_gain __P((struct ym_softc *, struct ad1848_volume *));
68
69
70
71 struct audio_hw_if ym_hw_if = {
72 ad1848_open,
73 ad1848_close,
74 NULL,
75 ad1848_query_encoding,
76 ad1848_set_params,
77 ad1848_round_blocksize,
78 ad1848_commit_settings,
79 ad1848_dma_init_output,
80 ad1848_dma_init_input,
81 ad1848_dma_output,
82 ad1848_dma_input,
83 ad1848_halt_out_dma,
84 ad1848_halt_in_dma,
85 NULL,
86 ym_getdev,
87 NULL,
88 ym_mixer_set_port,
89 ym_mixer_get_port,
90 ym_query_devinfo,
91 ad1848_malloc,
92 ad1848_free,
93 ad1848_round,
94 ad1848_mappage,
95 ad1848_get_props,
96 };
97
98
99 struct audio_device ym_device = {
100 "ym,ad1848",
101 "",
102 "ym"
103 };
104
105 static __inline int ym_read __P((struct ym_softc *, int));
106 static __inline void ym_write __P((struct ym_softc *, int, int));
107
108 void
109 ym_attach(sc)
110 struct ym_softc *sc;
111 {
112 struct ad1848_volume vol_mid = {220, 220};
113 struct ad1848_volume vol_0 = {0, 0};
114
115 sc->sc_ih = isa_intr_establish(sc->sc_ic, sc->ym_irq, IST_EDGE,
116 IPL_AUDIO, ad1848_intr, &sc->sc_ad1848);
117
118 ad1848_attach(&sc->sc_ad1848);
119 printf("\n");
120 sc->sc_ad1848.parent = sc;
121
122 /* Establish chip in well known mode */
123 ym_set_master_gain(sc, &vol_mid);
124 ym_set_mic_gain(sc, &vol_0);
125 sc->master_mute = 0;
126 ym_mute(sc, SA3_LCH, sc->master_mute);
127 ym_mute(sc, SA3_RCH, sc->master_mute);
128
129 sc->mic_mute = 1;
130 ym_mute(sc, SA3_MIC, sc->mic_mute);
131
132 audio_attach_mi(&ym_hw_if, 0, &sc->sc_ad1848, &sc->sc_dev);
133 }
134
135 static __inline int
136 ym_read(sc, reg)
137 struct ym_softc *sc;
138 int reg;
139 {
140 bus_space_write_1(sc->sc_iot, sc->sc_controlioh, 0, 0x1d);
141 bus_space_write_1(sc->sc_iot, sc->sc_controlioh, 0, (reg & 0xff));
142 return (bus_space_read_1(sc->sc_iot, sc->sc_controlioh, 1));
143 }
144
145 static __inline void
146 ym_write(sc, reg, data)
147 struct ym_softc *sc;
148 int reg;
149 int data;
150 {
151 bus_space_write_1(sc->sc_iot, sc->sc_controlioh, 0, 0x1d);
152 bus_space_write_1(sc->sc_iot, sc->sc_controlioh, 0, (reg & 0xff));
153 bus_space_write_1(sc->sc_iot, sc->sc_controlioh, 1, (data & 0xff));
154 }
155
156
157
158 int
159 ym_getdev(addr, retp)
160 void *addr;
161 struct audio_device *retp;
162 {
163 *retp = ym_device;
164 return 0;
165 }
166
167
168 static ad1848_devmap_t mappings[] = {
169 { YM_MIDI_LVL, AD1848_KIND_LVL, AD1848_AUX2_CHANNEL },
170 { YM_CD_LVL, AD1848_KIND_LVL, AD1848_AUX1_CHANNEL },
171 { YM_DAC_LVL, AD1848_KIND_LVL, AD1848_DAC_CHANNEL },
172 { YM_LINE_LVL, AD1848_KIND_LVL, AD1848_LINE_CHANNEL },
173 { YM_SPEAKER_LVL, AD1848_KIND_LVL, AD1848_MONO_CHANNEL },
174 { YM_MONITOR_LVL, AD1848_KIND_LVL, AD1848_MONITOR_CHANNEL },
175 { YM_MIDI_MUTE, AD1848_KIND_MUTE, AD1848_AUX2_CHANNEL },
176 { YM_CD_MUTE, AD1848_KIND_MUTE, AD1848_AUX1_CHANNEL },
177 { YM_DAC_MUTE, AD1848_KIND_MUTE, AD1848_DAC_CHANNEL },
178 { YM_LINE_MUTE, AD1848_KIND_MUTE, AD1848_LINE_CHANNEL },
179 { YM_SPEAKER_MUTE, AD1848_KIND_MUTE, AD1848_MONO_CHANNEL },
180 { YM_MONITOR_MUTE, AD1848_KIND_MUTE, AD1848_MONITOR_CHANNEL },
181 { YM_REC_LVL, AD1848_KIND_RECORDGAIN, -1 },
182 { YM_RECORD_SOURCE, AD1848_KIND_RECORDSOURCE, -1}
183 };
184
185 static int nummap = sizeof(mappings) / sizeof(mappings[0]);
186
187
188 static void
189 ym_mute(sc, left_reg, mute)
190 struct ym_softc *sc;
191 int left_reg;
192 int mute;
193
194 {
195 u_char reg;
196
197 if (mute) {
198 reg = ym_read(sc, left_reg);
199 ym_write (sc, left_reg, reg | 0x80);
200 } else {
201 reg = ym_read(sc, left_reg);
202 ym_write (sc, left_reg, reg & ~0x80);
203 }
204 }
205
206 #define MIC_ATTEN_BITS 0x1f
207 #define MASTER_ATTEN_BITS 0x0f
208
209
210 static void
211 ym_set_master_gain(sc, vol)
212 struct ym_softc *sc;
213 struct ad1848_volume *vol;
214 {
215 u_char reg;
216 u_int atten;
217
218 sc->master_gain = *vol;
219
220 atten = ((AUDIO_MAX_GAIN - vol->left) * MASTER_ATTEN_BITS) /
221 AUDIO_MAX_GAIN;
222
223 reg = ym_read(sc, SA3_LCH);
224
225 reg &= ~(MASTER_ATTEN_BITS);
226 reg |= atten;
227
228 ym_write (sc, SA3_LCH, reg);
229
230 atten = ((AUDIO_MAX_GAIN - vol->right) * MASTER_ATTEN_BITS) /
231 AUDIO_MAX_GAIN;
232
233 reg = ym_read(sc, SA3_RCH) & ~(MASTER_ATTEN_BITS);
234 reg |= atten;
235
236 ym_write (sc, SA3_RCH, reg);
237 }
238
239 static void
240 ym_set_mic_gain(sc, vol)
241 struct ym_softc *sc;
242 struct ad1848_volume *vol;
243 {
244 u_char reg;
245 u_int atten;
246
247 sc->mic_gain = *vol;
248
249 atten = ((AUDIO_MAX_GAIN - vol->left) * MIC_ATTEN_BITS)/AUDIO_MAX_GAIN;
250
251 reg = ym_read(sc, SA3_MIC) & ~(MIC_ATTEN_BITS);
252 reg |= atten;
253
254 ym_write (sc, SA3_MIC, reg);
255 }
256
257 int
258 ym_mixer_set_port(addr, cp)
259 void *addr;
260 mixer_ctrl_t *cp;
261 {
262 struct ad1848_softc *ac = addr;
263 struct ym_softc *sc = ac->parent;
264 struct ad1848_volume vol;
265 int error = ad1848_mixer_set_port(ac, mappings, nummap, cp);
266
267 if (error != ENXIO)
268 return (error);
269
270 error = 0;
271
272 switch (cp->dev) {
273 case YM_OUTPUT_LVL:
274 ad1848_to_vol(cp, &vol);
275 ym_set_master_gain(sc, &vol);
276 break;
277
278 case YM_OUTPUT_MUTE:
279 sc->master_mute = (cp->un.ord != 0);
280 ym_mute(sc, SA3_LCH, sc->master_mute);
281 ym_mute(sc, SA3_RCH, sc->master_mute);
282 break;
283
284 case YM_MIC_LVL:
285 if (cp->un.value.num_channels != 1)
286 error = EINVAL;
287
288 ad1848_to_vol(cp, &vol);
289 ym_set_mic_gain(sc, &vol);
290 break;
291
292 case YM_MIC_MUTE:
293 sc->mic_mute = (cp->un.ord != 0);
294 ym_mute(sc, SA3_MIC, sc->mic_mute);
295 break;
296
297 default:
298 return ENXIO;
299 /*NOTREACHED*/
300 }
301
302 return (error);
303 }
304
305 int
306 ym_mixer_get_port(addr, cp)
307 void *addr;
308 mixer_ctrl_t *cp;
309 {
310 struct ad1848_softc *ac = addr;
311 struct ym_softc *sc = ac->parent;
312
313 int error = ad1848_mixer_get_port(ac, mappings, nummap, cp);
314
315 if (error != ENXIO)
316 return (error);
317
318 error = 0;
319
320 switch (cp->dev) {
321 case YM_OUTPUT_LVL:
322 ad1848_from_vol(cp, &sc->master_gain);
323 break;
324
325 case YM_OUTPUT_MUTE:
326 cp->un.ord = sc->master_mute;
327 break;
328
329 case YM_MIC_LVL:
330 if (cp->un.value.num_channels != 1)
331 error = EINVAL;
332 ad1848_from_vol(cp, &sc->mic_gain);
333 break;
334
335 case YM_MIC_MUTE:
336 cp->un.ord = sc->mic_mute;
337 break;
338
339 default:
340 error = ENXIO;
341 break;
342 }
343
344 return(error);
345 }
346
347 static char *mixer_classes[] =
348 { AudioCinputs, AudioCrecord, AudioCoutputs, AudioCmonitor };
349
350 int
351 ym_query_devinfo(addr, dip)
352 void *addr;
353 mixer_devinfo_t *dip;
354 {
355 static char *mixer_port_names[] =
356 { AudioNmidi, AudioNcd, AudioNdac, AudioNline, AudioNspeaker,
357 AudioNmicrophone, AudioNmonitor};
358
359 dip->next = dip->prev = AUDIO_MIXER_LAST;
360
361 switch(dip->index) {
362 case YM_INPUT_CLASS: /* input class descriptor */
363 case YM_OUTPUT_CLASS:
364 case YM_MONITOR_CLASS:
365 case YM_RECORD_CLASS:
366 dip->type = AUDIO_MIXER_CLASS;
367 dip->mixer_class = dip->index;
368 strcpy(dip->label.name,
369 mixer_classes[dip->index - YM_INPUT_CLASS]);
370 break;
371
372 case YM_MIDI_LVL:
373 case YM_CD_LVL:
374 case YM_DAC_LVL:
375 case YM_LINE_LVL:
376 case YM_SPEAKER_LVL:
377 case YM_MIC_LVL:
378 case YM_MONITOR_LVL:
379 dip->type = AUDIO_MIXER_VALUE;
380 if (dip->index == YM_MONITOR_LVL)
381 dip->mixer_class = YM_MONITOR_CLASS;
382 else
383 dip->mixer_class = YM_INPUT_CLASS;
384
385 dip->next = dip->index + 7;
386
387 strcpy(dip->label.name,
388 mixer_port_names[dip->index - YM_MIDI_LVL]);
389
390 if (dip->index == YM_SPEAKER_LVL ||
391 dip->index == YM_MIC_LVL)
392 dip->un.v.num_channels = 1;
393 else
394 dip->un.v.num_channels = 2;
395
396 strcpy(dip->un.v.units.name, AudioNvolume);
397 break;
398
399 case YM_MIDI_MUTE:
400 case YM_CD_MUTE:
401 case YM_DAC_MUTE:
402 case YM_LINE_MUTE:
403 case YM_SPEAKER_MUTE:
404 case YM_MIC_MUTE:
405 case YM_MONITOR_MUTE:
406 if (dip->index == YM_MONITOR_MUTE)
407 dip->mixer_class = YM_MONITOR_CLASS;
408 else
409 dip->mixer_class = YM_INPUT_CLASS;
410 dip->type = AUDIO_MIXER_ENUM;
411 dip->prev = dip->index - 7;
412 mute:
413 strcpy(dip->label.name, AudioNmute);
414 dip->un.e.num_mem = 2;
415 strcpy(dip->un.e.member[0].label.name, AudioNoff);
416 dip->un.e.member[0].ord = 0;
417 strcpy(dip->un.e.member[1].label.name, AudioNon);
418 dip->un.e.member[1].ord = 1;
419 break;
420
421
422 case YM_OUTPUT_LVL:
423 dip->type = AUDIO_MIXER_VALUE;
424 dip->mixer_class = YM_OUTPUT_CLASS;
425 dip->next = YM_OUTPUT_MUTE;
426 strcpy(dip->label.name, AudioNmaster);
427 dip->un.v.num_channels = 2;
428 strcpy(dip->un.v.units.name, AudioNvolume);
429 break;
430
431 case YM_OUTPUT_MUTE:
432 dip->mixer_class = YM_OUTPUT_CLASS;
433 dip->type = AUDIO_MIXER_ENUM;
434 dip->prev = YM_OUTPUT_LVL;
435 goto mute;
436
437 case YM_REC_LVL: /* record level */
438 dip->type = AUDIO_MIXER_VALUE;
439 dip->mixer_class = YM_RECORD_CLASS;
440 dip->next = YM_RECORD_SOURCE;
441 strcpy(dip->label.name, AudioNrecord);
442 dip->un.v.num_channels = 2;
443 strcpy(dip->un.v.units.name, AudioNvolume);
444 break;
445
446
447 case YM_RECORD_SOURCE:
448 dip->mixer_class = YM_RECORD_CLASS;
449 dip->type = AUDIO_MIXER_ENUM;
450 dip->prev = YM_REC_LVL;
451 strcpy(dip->label.name, AudioNsource);
452 dip->un.e.num_mem = 4;
453 strcpy(dip->un.e.member[0].label.name, AudioNmicrophone);
454 dip->un.e.member[0].ord = MIC_IN_PORT;
455 strcpy(dip->un.e.member[1].label.name, AudioNline);
456 dip->un.e.member[1].ord = LINE_IN_PORT;
457 strcpy(dip->un.e.member[2].label.name, AudioNdac);
458 dip->un.e.member[2].ord = DAC_IN_PORT;
459 strcpy(dip->un.e.member[3].label.name, AudioNcd);
460 dip->un.e.member[3].ord = AUX1_IN_PORT;
461 break;
462
463 default:
464 return ENXIO;
465 /*NOTREACHED*/
466 }
467
468 return 0;
469 }
470