am7930.c revision 1.43 1 1.43 augustss /* $NetBSD: am7930.c,v 1.43 2000/05/02 06:30:51 augustss Exp $ */
2 1.3 cgd
3 1.1 pk /*
4 1.1 pk * Copyright (c) 1995 Rolf Grossmann
5 1.1 pk * All rights reserved.
6 1.1 pk *
7 1.1 pk * Redistribution and use in source and binary forms, with or without
8 1.1 pk * modification, are permitted provided that the following conditions
9 1.1 pk * are met:
10 1.1 pk * 1. Redistributions of source code must retain the above copyright
11 1.1 pk * notice, this list of conditions and the following disclaimer.
12 1.1 pk * 2. Redistributions in binary form must reproduce the above copyright
13 1.1 pk * notice, this list of conditions and the following disclaimer in the
14 1.1 pk * documentation and/or other materials provided with the distribution.
15 1.1 pk * 3. All advertising materials mentioning features or use of this software
16 1.1 pk * must display the following acknowledgement:
17 1.1 pk * This product includes software developed by Rolf Grossmann.
18 1.1 pk * 4. The name of the author may not be used to endorse or promote products
19 1.1 pk * derived from this software without specific prior written permission
20 1.1 pk *
21 1.1 pk * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 1.1 pk * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 1.1 pk * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 1.1 pk * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 1.1 pk * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 1.1 pk * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 1.1 pk * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 1.1 pk * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 1.1 pk * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 1.1 pk * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 1.1 pk */
32 1.1 pk
33 1.39 jonathan /*
34 1.39 jonathan * Front-end attachment independent layer for AMD 79c30
35 1.43 augustss * audio driver. No ISDN support.
36 1.39 jonathan */
37 1.39 jonathan
38 1.1 pk #include "audio.h"
39 1.1 pk #if NAUDIO > 0
40 1.1 pk
41 1.1 pk #include <sys/param.h>
42 1.1 pk #include <sys/systm.h>
43 1.1 pk #include <sys/errno.h>
44 1.1 pk #include <sys/ioctl.h>
45 1.1 pk #include <sys/device.h>
46 1.1 pk #include <sys/proc.h>
47 1.1 pk
48 1.36 pk #include <machine/bus.h>
49 1.1 pk #include <machine/autoconf.h>
50 1.1 pk #include <machine/cpu.h>
51 1.1 pk
52 1.1 pk #include <sys/audioio.h>
53 1.1 pk #include <dev/audio_if.h>
54 1.1 pk
55 1.3 cgd #include <dev/ic/am7930reg.h>
56 1.39 jonathan #include <dev/ic/am7930var.h>
57 1.1 pk
58 1.4 brezak #ifdef AUDIO_DEBUG
59 1.39 jonathan int am7930debug = 0;
60 1.40 pk #define DPRINTF(x) if (am7930debug) printf x
61 1.1 pk #else
62 1.1 pk #define DPRINTF(x)
63 1.1 pk #endif
64 1.1 pk
65 1.1 pk
66 1.1 pk /* The following tables stolen from former (4.4Lite's) sys/sparc/bsd_audio.c */
67 1.1 pk
68 1.1 pk /*
69 1.1 pk * gx, gr & stg gains. this table must contain 256 elements with
70 1.1 pk * the 0th being "infinity" (the magic value 9008). The remaining
71 1.1 pk * elements match sun's gain curve (but with higher resolution):
72 1.1 pk * -18 to 0dB in .16dB steps then 0 to 12dB in .08dB steps.
73 1.1 pk */
74 1.1 pk static const u_short gx_coeff[256] = {
75 1.21 pk 0x9008, 0x8e7c, 0x8e51, 0x8e45, 0x8d42, 0x8d3b, 0x8c36, 0x8c33,
76 1.1 pk 0x8b32, 0x8b2a, 0x8b2b, 0x8b2c, 0x8b25, 0x8b23, 0x8b22, 0x8b22,
77 1.1 pk 0x9122, 0x8b1a, 0x8aa3, 0x8aa3, 0x8b1c, 0x8aa6, 0x912d, 0x912b,
78 1.1 pk 0x8aab, 0x8b12, 0x8aaa, 0x8ab2, 0x9132, 0x8ab4, 0x913c, 0x8abb,
79 1.1 pk 0x9142, 0x9144, 0x9151, 0x8ad5, 0x8aeb, 0x8a79, 0x8a5a, 0x8a4a,
80 1.1 pk 0x8b03, 0x91c2, 0x91bb, 0x8a3f, 0x8a33, 0x91b2, 0x9212, 0x9213,
81 1.1 pk 0x8a2c, 0x921d, 0x8a23, 0x921a, 0x9222, 0x9223, 0x922d, 0x9231,
82 1.1 pk 0x9234, 0x9242, 0x925b, 0x92dd, 0x92c1, 0x92b3, 0x92ab, 0x92a4,
83 1.1 pk 0x92a2, 0x932b, 0x9341, 0x93d3, 0x93b2, 0x93a2, 0x943c, 0x94b2,
84 1.1 pk 0x953a, 0x9653, 0x9782, 0x9e21, 0x9d23, 0x9cd2, 0x9c23, 0x9baa,
85 1.1 pk 0x9bde, 0x9b33, 0x9b22, 0x9b1d, 0x9ab2, 0xa142, 0xa1e5, 0x9a3b,
86 1.1 pk 0xa213, 0xa1a2, 0xa231, 0xa2eb, 0xa313, 0xa334, 0xa421, 0xa54b,
87 1.1 pk 0xada4, 0xac23, 0xab3b, 0xaaab, 0xaa5c, 0xb1a3, 0xb2ca, 0xb3bd,
88 1.1 pk 0xbe24, 0xbb2b, 0xba33, 0xc32b, 0xcb5a, 0xd2a2, 0xe31d, 0x0808,
89 1.1 pk 0x72ba, 0x62c2, 0x5c32, 0x52db, 0x513e, 0x4cce, 0x43b2, 0x4243,
90 1.1 pk 0x41b4, 0x3b12, 0x3bc3, 0x3df2, 0x34bd, 0x3334, 0x32c2, 0x3224,
91 1.1 pk 0x31aa, 0x2a7b, 0x2aaa, 0x2b23, 0x2bba, 0x2c42, 0x2e23, 0x25bb,
92 1.1 pk 0x242b, 0x240f, 0x231a, 0x22bb, 0x2241, 0x2223, 0x221f, 0x1a33,
93 1.1 pk 0x1a4a, 0x1acd, 0x2132, 0x1b1b, 0x1b2c, 0x1b62, 0x1c12, 0x1c32,
94 1.1 pk 0x1d1b, 0x1e71, 0x16b1, 0x1522, 0x1434, 0x1412, 0x1352, 0x1323,
95 1.1 pk 0x1315, 0x12bc, 0x127a, 0x1235, 0x1226, 0x11a2, 0x1216, 0x0a2a,
96 1.1 pk 0x11bc, 0x11d1, 0x1163, 0x0ac2, 0x0ab2, 0x0aab, 0x0b1b, 0x0b23,
97 1.1 pk 0x0b33, 0x0c0f, 0x0bb3, 0x0c1b, 0x0c3e, 0x0cb1, 0x0d4c, 0x0ec1,
98 1.1 pk 0x079a, 0x0614, 0x0521, 0x047c, 0x0422, 0x03b1, 0x03e3, 0x0333,
99 1.1 pk 0x0322, 0x031c, 0x02aa, 0x02ba, 0x02f2, 0x0242, 0x0232, 0x0227,
100 1.1 pk 0x0222, 0x021b, 0x01ad, 0x0212, 0x01b2, 0x01bb, 0x01cb, 0x01f6,
101 1.1 pk 0x0152, 0x013a, 0x0133, 0x0131, 0x012c, 0x0123, 0x0122, 0x00a2,
102 1.1 pk 0x011b, 0x011e, 0x0114, 0x00b1, 0x00aa, 0x00b3, 0x00bd, 0x00ba,
103 1.1 pk 0x00c5, 0x00d3, 0x00f3, 0x0062, 0x0051, 0x0042, 0x003b, 0x0033,
104 1.1 pk 0x0032, 0x002a, 0x002c, 0x0025, 0x0023, 0x0022, 0x001a, 0x0021,
105 1.1 pk 0x001b, 0x001b, 0x001d, 0x0015, 0x0013, 0x0013, 0x0012, 0x0012,
106 1.1 pk 0x000a, 0x000a, 0x0011, 0x0011, 0x000b, 0x000b, 0x000c, 0x000e,
107 1.1 pk };
108 1.1 pk
109 1.1 pk /*
110 1.1 pk * second stage play gain.
111 1.1 pk */
112 1.1 pk static const u_short ger_coeff[] = {
113 1.1 pk 0x431f, /* 5. dB */
114 1.1 pk 0x331f, /* 5.5 dB */
115 1.1 pk 0x40dd, /* 6. dB */
116 1.1 pk 0x11dd, /* 6.5 dB */
117 1.1 pk 0x440f, /* 7. dB */
118 1.1 pk 0x411f, /* 7.5 dB */
119 1.1 pk 0x311f, /* 8. dB */
120 1.1 pk 0x5520, /* 8.5 dB */
121 1.1 pk 0x10dd, /* 9. dB */
122 1.1 pk 0x4211, /* 9.5 dB */
123 1.1 pk 0x410f, /* 10. dB */
124 1.1 pk 0x111f, /* 10.5 dB */
125 1.1 pk 0x600b, /* 11. dB */
126 1.1 pk 0x00dd, /* 11.5 dB */
127 1.1 pk 0x4210, /* 12. dB */
128 1.1 pk 0x110f, /* 13. dB */
129 1.1 pk 0x7200, /* 14. dB */
130 1.1 pk 0x2110, /* 15. dB */
131 1.1 pk 0x2200, /* 15.9 dB */
132 1.1 pk 0x000b, /* 16.9 dB */
133 1.1 pk 0x000f /* 18. dB */
134 1.1 pk #define NGER (sizeof(ger_coeff) / sizeof(ger_coeff[0]))
135 1.1 pk };
136 1.1 pk
137 1.1 pk
138 1.1 pk /*
139 1.39 jonathan * Reset chip and set boot-time softc defaults.
140 1.1 pk */
141 1.1 pk void
142 1.43 augustss am7930_init(sc, flag)
143 1.39 jonathan struct am7930_softc *sc;
144 1.43 augustss int flag;
145 1.36 pk {
146 1.41 jonathan
147 1.43 augustss DPRINTF(("am7930_init()\n"));
148 1.39 jonathan
149 1.1 pk /* set boot defaults */
150 1.1 pk sc->sc_rlevel = 128;
151 1.1 pk sc->sc_plevel = 128;
152 1.1 pk sc->sc_mlevel = 0;
153 1.43 augustss sc->sc_out_port = AUDIOAMD_SPEAKER_VOL;
154 1.43 augustss sc->sc_mic_mute = 0;
155 1.43 augustss
156 1.43 augustss /* disable sample interrupts */
157 1.43 augustss AM7930_IWRITE(sc, AM7930_IREG_MUX_MCR4, 0);
158 1.43 augustss
159 1.43 augustss /* initialise voice and data, and disable interrupts */
160 1.43 augustss AM7930_IWRITE(sc, AM7930_IREG_INIT,
161 1.43 augustss AM7930_INIT_PMS_ACTIVE | AM7930_INIT_INT_DISABLE);
162 1.43 augustss
163 1.43 augustss if (flag == AUDIOAMD_DMA_MODE) {
164 1.43 augustss
165 1.43 augustss /* configure PP for serial (SBP) mode */
166 1.43 augustss AM7930_IWRITE(sc, AM7930_IREG_PP_PPCR1, AM7930_PPCR1_SBP);
167 1.43 augustss
168 1.43 augustss /*
169 1.43 augustss * Initialise the MUX unit - route the MAP to the PP
170 1.43 augustss */
171 1.43 augustss AM7930_IWRITE(sc, AM7930_IREG_MUX_MCR1,
172 1.43 augustss (AM7930_MCRCHAN_BA << 4) | AM7930_MCRCHAN_BD);
173 1.43 augustss AM7930_IWRITE(sc, AM7930_IREG_MUX_MCR2, AM7930_MCRCHAN_NC);
174 1.43 augustss AM7930_IWRITE(sc, AM7930_IREG_MUX_MCR3, AM7930_MCRCHAN_NC);
175 1.43 augustss
176 1.43 augustss } else {
177 1.43 augustss
178 1.43 augustss /*
179 1.43 augustss * Initialize the MUX unit. We use MCR3 to route the MAP
180 1.43 augustss * through channel Bb. MCR1 and MCR2 are unused.
181 1.43 augustss * Setting the INT enable bit in MCR4 will generate an
182 1.43 augustss * interrupt on each converted audio sample.
183 1.43 augustss */
184 1.43 augustss AM7930_IWRITE(sc, AM7930_IREG_MUX_MCR1, 0);
185 1.43 augustss AM7930_IWRITE(sc, AM7930_IREG_MUX_MCR2, 0);
186 1.43 augustss AM7930_IWRITE(sc, AM7930_IREG_MUX_MCR3,
187 1.43 augustss (AM7930_MCRCHAN_BB << 4) | AM7930_MCRCHAN_BA);
188 1.43 augustss AM7930_IWRITE(sc, AM7930_IREG_MUX_MCR4,
189 1.43 augustss AM7930_MCR4_INT_ENABLE);
190 1.43 augustss }
191 1.43 augustss
192 1.1 pk }
193 1.1 pk
194 1.1 pk
195 1.1 pk int
196 1.39 jonathan am7930_open(addr, flags)
197 1.26 augustss void *addr;
198 1.1 pk int flags;
199 1.1 pk {
200 1.39 jonathan struct am7930_softc *sc = addr;
201 1.1 pk
202 1.26 augustss DPRINTF(("sa_open: unit %p\n", sc));
203 1.1 pk
204 1.1 pk if (sc->sc_open)
205 1.1 pk return (EBUSY);
206 1.1 pk sc->sc_open = 1;
207 1.1 pk sc->sc_locked = 0;
208 1.1 pk
209 1.43 augustss sc->sc_glue->onopen(sc);
210 1.1 pk
211 1.41 jonathan DPRINTF(("saopen: ok -> sc=0x%p\n",sc));
212 1.1 pk
213 1.1 pk return (0);
214 1.1 pk }
215 1.1 pk
216 1.1 pk void
217 1.39 jonathan am7930_close(addr)
218 1.1 pk void *addr;
219 1.1 pk {
220 1.42 augustss struct am7930_softc *sc = addr;
221 1.1 pk
222 1.40 pk DPRINTF(("sa_close: sc=%p\n", sc));
223 1.43 augustss
224 1.43 augustss sc->sc_glue->onclose(sc);
225 1.1 pk sc->sc_open = 0;
226 1.1 pk
227 1.1 pk DPRINTF(("sa_close: closed.\n"));
228 1.1 pk }
229 1.1 pk
230 1.43 augustss
231 1.43 augustss /*
232 1.43 augustss * XXX should be extended to handle a few of the more common formats.
233 1.43 augustss */
234 1.1 pk int
235 1.39 jonathan am7930_set_params(addr, setmode, usemode, p, r)
236 1.1 pk void *addr;
237 1.28 augustss int setmode, usemode;
238 1.28 augustss struct audio_params *p, *r;
239 1.1 pk {
240 1.43 augustss struct am7930_softc *sc = addr;
241 1.43 augustss
242 1.43 augustss if ((usemode & AUMODE_PLAY) == AUMODE_PLAY) {
243 1.43 augustss if (p->sample_rate < 7500 || p->sample_rate > 8500 ||
244 1.43 augustss p->encoding != AUDIO_ENCODING_ULAW ||
245 1.43 augustss p->precision != 8 ||
246 1.43 augustss p->channels != 1)
247 1.43 augustss return EINVAL;
248 1.43 augustss p->sample_rate = 8000;
249 1.43 augustss if (sc->sc_glue->factor > 1) {
250 1.43 augustss p->factor = sc->sc_glue->factor;
251 1.43 augustss p->sw_code = sc->sc_glue->output_conv;
252 1.43 augustss }
253 1.43 augustss }
254 1.43 augustss if ((usemode & AUMODE_RECORD) == AUMODE_RECORD) {
255 1.43 augustss if (r->sample_rate < 7500 || r->sample_rate > 8500 ||
256 1.43 augustss r->encoding != AUDIO_ENCODING_ULAW ||
257 1.43 augustss r->precision != 8 ||
258 1.43 augustss r->channels != 1)
259 1.43 augustss return EINVAL;
260 1.43 augustss r->sample_rate = 8000;
261 1.43 augustss if (sc->sc_glue->factor > 1) {
262 1.43 augustss r->factor = sc->sc_glue->factor;
263 1.43 augustss r->sw_code = sc->sc_glue->input_conv;
264 1.43 augustss }
265 1.43 augustss }
266 1.20 augustss
267 1.20 augustss return 0;
268 1.1 pk }
269 1.1 pk
270 1.1 pk int
271 1.39 jonathan am7930_query_encoding(addr, fp)
272 1.1 pk void *addr;
273 1.1 pk struct audio_encoding *fp;
274 1.1 pk {
275 1.1 pk switch (fp->index) { /* ??? */
276 1.1 pk case 0:
277 1.19 augustss strcpy(fp->name, AudioEmulaw);
278 1.19 augustss fp->encoding = AUDIO_ENCODING_ULAW;
279 1.19 augustss fp->precision = 8;
280 1.19 augustss fp->flags = 0;
281 1.1 pk break;
282 1.1 pk default:
283 1.1 pk return(EINVAL);
284 1.1 pk /*NOTREACHED*/
285 1.1 pk }
286 1.1 pk return(0);
287 1.1 pk }
288 1.1 pk
289 1.39 jonathan
290 1.1 pk int
291 1.39 jonathan am7930_round_blocksize(addr, blk)
292 1.1 pk void *addr;
293 1.1 pk int blk;
294 1.1 pk {
295 1.1 pk return(blk);
296 1.1 pk }
297 1.1 pk
298 1.43 augustss
299 1.1 pk int
300 1.39 jonathan am7930_commit_settings(addr)
301 1.1 pk void *addr;
302 1.1 pk {
303 1.42 augustss struct am7930_softc *sc = addr;
304 1.43 augustss u_int16_t ger, gr, gx, stgr;
305 1.43 augustss u_int8_t mmr2, mmr3;
306 1.42 augustss int s, level;
307 1.10 pk
308 1.1 pk DPRINTF(("sa_commit.\n"));
309 1.1 pk
310 1.43 augustss gx = gx_coeff[sc->sc_rlevel];
311 1.43 augustss stgr = gx_coeff[sc->sc_mlevel];
312 1.10 pk
313 1.1 pk level = (sc->sc_plevel * (256 + NGER)) >> 8;
314 1.1 pk if (level >= 256) {
315 1.43 augustss ger = ger_coeff[level - 256];
316 1.43 augustss gr = gx_coeff[255];
317 1.1 pk } else {
318 1.43 augustss ger = ger_coeff[0];
319 1.43 augustss gr = gx_coeff[level];
320 1.1 pk }
321 1.1 pk
322 1.1 pk s = splaudio();
323 1.10 pk
324 1.43 augustss mmr2 = AM7930_IREAD(sc, AM7930_IREG_MAP_MMR2);
325 1.43 augustss if (sc->sc_out_port == AUDIOAMD_SPEAKER_VOL)
326 1.43 augustss mmr2 |= AM7930_MMR2_LS;
327 1.43 augustss else
328 1.43 augustss mmr2 &= ~AM7930_MMR2_LS;
329 1.43 augustss AM7930_IWRITE(sc, AM7930_IREG_MAP_MMR2, mmr2);
330 1.41 jonathan
331 1.43 augustss mmr3 = AM7930_IREAD(sc, AM7930_IREG_MAP_MMR3);
332 1.43 augustss if (sc->sc_mic_mute)
333 1.43 augustss mmr3 |= AM7930_MMR3_MUTE;
334 1.43 augustss else
335 1.43 augustss mmr3 &= ~AM7930_MMR3_MUTE;
336 1.43 augustss AM7930_IWRITE(sc, AM7930_IREG_MAP_MMR3, mmr3);
337 1.41 jonathan
338 1.43 augustss AM7930_IWRITE(sc, AM7930_IREG_MAP_MMR1,
339 1.43 augustss AM7930_MMR1_GX | AM7930_MMR1_GER |
340 1.43 augustss AM7930_MMR1_GR | AM7930_MMR1_STG);
341 1.43 augustss
342 1.43 augustss AM7930_IWRITE16(sc, AM7930_IREG_MAP_GX, gx);
343 1.43 augustss AM7930_IWRITE16(sc, AM7930_IREG_MAP_STG, stgr);
344 1.43 augustss AM7930_IWRITE16(sc, AM7930_IREG_MAP_GR, gr);
345 1.43 augustss AM7930_IWRITE16(sc, AM7930_IREG_MAP_GER, ger);
346 1.41 jonathan
347 1.43 augustss splx(s);
348 1.1 pk
349 1.1 pk return(0);
350 1.1 pk }
351 1.1 pk
352 1.43 augustss
353 1.1 pk int
354 1.39 jonathan am7930_halt_output(addr)
355 1.1 pk void *addr;
356 1.1 pk {
357 1.42 augustss struct am7930_softc *sc = addr;
358 1.1 pk
359 1.1 pk /* XXX only halt, if input is also halted ?? */
360 1.43 augustss AM7930_IWRITE(sc, AM7930_IREG_INIT,
361 1.43 augustss AM7930_INIT_PMS_ACTIVE | AM7930_INIT_INT_DISABLE);
362 1.1 pk sc->sc_locked = 0;
363 1.1 pk
364 1.1 pk return(0);
365 1.1 pk }
366 1.1 pk
367 1.43 augustss
368 1.1 pk int
369 1.39 jonathan am7930_halt_input(addr)
370 1.1 pk void *addr;
371 1.1 pk {
372 1.42 augustss struct am7930_softc *sc = addr;
373 1.1 pk
374 1.1 pk /* XXX only halt, if output is also halted ?? */
375 1.43 augustss AM7930_IWRITE(sc, AM7930_IREG_INIT,
376 1.43 augustss AM7930_INIT_PMS_ACTIVE | AM7930_INIT_INT_DISABLE);
377 1.1 pk sc->sc_locked = 0;
378 1.1 pk
379 1.1 pk return(0);
380 1.1 pk }
381 1.1 pk
382 1.43 augustss
383 1.43 augustss /*
384 1.43 augustss * XXX chip is full-duplex, but really attach-dependent.
385 1.43 augustss * For now we know of no half-duplex attachments.
386 1.43 augustss */
387 1.1 pk int
388 1.43 augustss am7930_get_props(addr)
389 1.43 augustss void *addr;
390 1.1 pk {
391 1.43 augustss return AUDIO_PROP_FULLDUPLEX;
392 1.43 augustss }
393 1.43 augustss
394 1.43 augustss /*
395 1.43 augustss * Attach-dependent channel set/query
396 1.43 augustss */
397 1.43 augustss int
398 1.43 augustss am7930_set_port(addr, cp)
399 1.43 augustss void *addr;
400 1.43 augustss mixer_ctrl_t *cp;
401 1.43 augustss {
402 1.43 augustss struct am7930_softc *sc = addr;
403 1.43 augustss
404 1.43 augustss DPRINTF(("am7930_set_port: port=%d", cp->dev));
405 1.43 augustss
406 1.43 augustss if (cp->dev == AUDIOAMD_RECORD_SOURCE ||
407 1.43 augustss cp->dev == AUDIOAMD_MONITOR_OUTPUT ||
408 1.43 augustss cp->dev == AUDIOAMD_MIC_MUTE) {
409 1.43 augustss if (cp->type != AUDIO_MIXER_ENUM)
410 1.43 augustss return(EINVAL);
411 1.43 augustss } else if (cp->type != AUDIO_MIXER_VALUE ||
412 1.43 augustss cp->un.value.num_channels != 1) {
413 1.43 augustss return(EINVAL);
414 1.43 augustss }
415 1.43 augustss
416 1.43 augustss switch(cp->dev) {
417 1.43 augustss case AUDIOAMD_MIC_VOL:
418 1.43 augustss sc->sc_rlevel = cp->un.value.level[AUDIO_MIXER_LEVEL_MONO];
419 1.43 augustss break;
420 1.43 augustss case AUDIOAMD_SPEAKER_VOL:
421 1.43 augustss case AUDIOAMD_HEADPHONES_VOL:
422 1.43 augustss sc->sc_plevel = cp->un.value.level[AUDIO_MIXER_LEVEL_MONO];
423 1.43 augustss break;
424 1.43 augustss case AUDIOAMD_MONITOR_VOL:
425 1.43 augustss sc->sc_mlevel = cp->un.value.level[AUDIO_MIXER_LEVEL_MONO];
426 1.43 augustss break;
427 1.43 augustss case AUDIOAMD_RECORD_SOURCE:
428 1.43 augustss if (cp->un.ord != AUDIOAMD_MIC_VOL)
429 1.43 augustss return EINVAL;
430 1.43 augustss break;
431 1.43 augustss case AUDIOAMD_MIC_MUTE:
432 1.43 augustss sc->sc_mic_mute = cp->un.ord;
433 1.43 augustss break;
434 1.43 augustss case AUDIOAMD_MONITOR_OUTPUT:
435 1.43 augustss if (cp->un.ord != AUDIOAMD_SPEAKER_VOL &&
436 1.43 augustss cp->un.ord != AUDIOAMD_HEADPHONES_VOL)
437 1.43 augustss return EINVAL;
438 1.43 augustss sc->sc_out_port = cp->un.ord;
439 1.43 augustss break;
440 1.43 augustss default:
441 1.43 augustss return(EINVAL);
442 1.43 augustss /* NOTREACHED */
443 1.43 augustss }
444 1.43 augustss return 0;
445 1.43 augustss }
446 1.43 augustss
447 1.43 augustss int
448 1.43 augustss am7930_get_port(addr, cp)
449 1.43 augustss void *addr;
450 1.43 augustss mixer_ctrl_t *cp;
451 1.43 augustss {
452 1.43 augustss struct am7930_softc *sc = addr;
453 1.43 augustss
454 1.43 augustss DPRINTF(("am7930_get_port: port=%d\n", cp->dev));
455 1.43 augustss
456 1.43 augustss if (cp->dev == AUDIOAMD_RECORD_SOURCE ||
457 1.43 augustss cp->dev == AUDIOAMD_MONITOR_OUTPUT ||
458 1.43 augustss cp->dev == AUDIOAMD_MIC_MUTE) {
459 1.43 augustss if (cp->type != AUDIO_MIXER_ENUM)
460 1.43 augustss return(EINVAL);
461 1.43 augustss } else if (cp->type != AUDIO_MIXER_VALUE ||
462 1.43 augustss cp->un.value.num_channels != 1) {
463 1.43 augustss return(EINVAL);
464 1.43 augustss }
465 1.43 augustss
466 1.43 augustss switch(cp->dev) {
467 1.43 augustss case AUDIOAMD_MIC_VOL:
468 1.43 augustss cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = sc->sc_rlevel;
469 1.43 augustss break;
470 1.43 augustss case AUDIOAMD_SPEAKER_VOL:
471 1.43 augustss case AUDIOAMD_HEADPHONES_VOL:
472 1.43 augustss cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = sc->sc_plevel;
473 1.43 augustss break;
474 1.43 augustss case AUDIOAMD_MONITOR_VOL:
475 1.43 augustss cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = sc->sc_mlevel;
476 1.43 augustss break;
477 1.43 augustss case AUDIOAMD_RECORD_SOURCE:
478 1.43 augustss cp->un.ord = AUDIOAMD_MIC_VOL;
479 1.43 augustss break;
480 1.43 augustss case AUDIOAMD_MIC_MUTE:
481 1.43 augustss cp->un.ord = sc->sc_mic_mute;
482 1.43 augustss break;
483 1.43 augustss case AUDIOAMD_MONITOR_OUTPUT:
484 1.43 augustss cp->un.ord = sc->sc_out_port;
485 1.43 augustss break;
486 1.43 augustss default:
487 1.43 augustss return(EINVAL);
488 1.43 augustss /* NOTREACHED */
489 1.43 augustss }
490 1.43 augustss return 0;
491 1.1 pk }
492 1.1 pk
493 1.26 augustss
494 1.39 jonathan /*
495 1.43 augustss * Define mixer control facilities.
496 1.39 jonathan */
497 1.26 augustss int
498 1.43 augustss am7930_query_devinfo(addr, dip)
499 1.26 augustss void *addr;
500 1.43 augustss mixer_devinfo_t *dip;
501 1.26 augustss {
502 1.43 augustss
503 1.43 augustss DPRINTF(("am7930_query_devinfo()\n"));
504 1.43 augustss
505 1.43 augustss switch(dip->index) {
506 1.43 augustss case AUDIOAMD_MIC_VOL:
507 1.43 augustss dip->type = AUDIO_MIXER_VALUE;
508 1.43 augustss dip->mixer_class = AUDIOAMD_INPUT_CLASS;
509 1.43 augustss dip->prev = AUDIO_MIXER_LAST;
510 1.43 augustss dip->next = AUDIOAMD_MIC_MUTE;
511 1.43 augustss strcpy(dip->label.name, AudioNmicrophone);
512 1.43 augustss dip->un.v.num_channels = 1;
513 1.43 augustss strcpy(dip->un.v.units.name, AudioNvolume);
514 1.43 augustss break;
515 1.43 augustss case AUDIOAMD_SPEAKER_VOL:
516 1.43 augustss dip->type = AUDIO_MIXER_VALUE;
517 1.43 augustss dip->mixer_class = AUDIOAMD_OUTPUT_CLASS;
518 1.43 augustss dip->prev = dip->next = AUDIO_MIXER_LAST;
519 1.43 augustss strcpy(dip->label.name, AudioNspeaker);
520 1.43 augustss dip->un.v.num_channels = 1;
521 1.43 augustss strcpy(dip->un.v.units.name, AudioNvolume);
522 1.43 augustss break;
523 1.43 augustss case AUDIOAMD_HEADPHONES_VOL:
524 1.43 augustss dip->type = AUDIO_MIXER_VALUE;
525 1.43 augustss dip->mixer_class = AUDIOAMD_OUTPUT_CLASS;
526 1.43 augustss dip->prev = dip->next = AUDIO_MIXER_LAST;
527 1.43 augustss strcpy(dip->label.name, AudioNheadphone);
528 1.43 augustss dip->un.v.num_channels = 1;
529 1.43 augustss strcpy(dip->un.v.units.name, AudioNvolume);
530 1.43 augustss break;
531 1.43 augustss case AUDIOAMD_MONITOR_VOL:
532 1.43 augustss dip->type = AUDIO_MIXER_VALUE;
533 1.43 augustss dip->mixer_class = AUDIOAMD_MONITOR_CLASS;
534 1.43 augustss dip->prev = dip->next = AUDIO_MIXER_LAST;
535 1.43 augustss strcpy(dip->label.name, AudioNmonitor);
536 1.43 augustss dip->un.v.num_channels = 1;
537 1.43 augustss strcpy(dip->un.v.units.name, AudioNvolume);
538 1.43 augustss break;
539 1.43 augustss case AUDIOAMD_RECORD_SOURCE:
540 1.43 augustss dip->type = AUDIO_MIXER_ENUM;
541 1.43 augustss dip->mixer_class = AUDIOAMD_RECORD_CLASS;
542 1.43 augustss dip->next = dip->prev = AUDIO_MIXER_LAST;
543 1.43 augustss strcpy(dip->label.name, AudioNsource);
544 1.43 augustss dip->un.e.num_mem = 1;
545 1.43 augustss strcpy(dip->un.e.member[0].label.name, AudioNmicrophone);
546 1.43 augustss dip->un.e.member[0].ord = AUDIOAMD_MIC_VOL;
547 1.43 augustss break;
548 1.43 augustss case AUDIOAMD_MONITOR_OUTPUT:
549 1.43 augustss dip->type = AUDIO_MIXER_ENUM;
550 1.43 augustss dip->mixer_class = AUDIOAMD_MONITOR_CLASS;
551 1.43 augustss dip->next = dip->prev = AUDIO_MIXER_LAST;
552 1.43 augustss strcpy(dip->label.name, AudioNoutput);
553 1.43 augustss dip->un.e.num_mem = 2;
554 1.43 augustss strcpy(dip->un.e.member[0].label.name, AudioNspeaker);
555 1.43 augustss dip->un.e.member[0].ord = AUDIOAMD_SPEAKER_VOL;
556 1.43 augustss strcpy(dip->un.e.member[1].label.name, AudioNheadphone);
557 1.43 augustss dip->un.e.member[1].ord = AUDIOAMD_HEADPHONES_VOL;
558 1.43 augustss break;
559 1.43 augustss case AUDIOAMD_MIC_MUTE:
560 1.43 augustss dip->type = AUDIO_MIXER_ENUM;
561 1.43 augustss dip->mixer_class = AUDIOAMD_INPUT_CLASS;
562 1.43 augustss dip->prev = AUDIOAMD_MIC_VOL;
563 1.43 augustss dip->next = AUDIO_MIXER_LAST;
564 1.43 augustss strcpy(dip->label.name, AudioNmute);
565 1.43 augustss dip->un.e.num_mem = 2;
566 1.43 augustss strcpy(dip->un.e.member[0].label.name, AudioNoff);
567 1.43 augustss dip->un.e.member[0].ord = 0;
568 1.43 augustss strcpy(dip->un.e.member[1].label.name, AudioNon);
569 1.43 augustss dip->un.e.member[1].ord = 1;
570 1.43 augustss break;
571 1.43 augustss case AUDIOAMD_INPUT_CLASS:
572 1.43 augustss dip->type = AUDIO_MIXER_CLASS;
573 1.43 augustss dip->mixer_class = AUDIOAMD_INPUT_CLASS;
574 1.43 augustss dip->next = dip->prev = AUDIO_MIXER_LAST;
575 1.43 augustss strcpy(dip->label.name, AudioCinputs);
576 1.43 augustss break;
577 1.43 augustss case AUDIOAMD_OUTPUT_CLASS:
578 1.43 augustss dip->type = AUDIO_MIXER_CLASS;
579 1.43 augustss dip->mixer_class = AUDIOAMD_OUTPUT_CLASS;
580 1.43 augustss dip->next = dip->prev = AUDIO_MIXER_LAST;
581 1.43 augustss strcpy(dip->label.name, AudioCoutputs);
582 1.43 augustss break;
583 1.43 augustss case AUDIOAMD_RECORD_CLASS:
584 1.43 augustss dip->type = AUDIO_MIXER_CLASS;
585 1.43 augustss dip->mixer_class = AUDIOAMD_RECORD_CLASS;
586 1.43 augustss dip->next = dip->prev = AUDIO_MIXER_LAST;
587 1.43 augustss strcpy(dip->label.name, AudioCrecord);
588 1.43 augustss break;
589 1.43 augustss case AUDIOAMD_MONITOR_CLASS:
590 1.43 augustss dip->type = AUDIO_MIXER_CLASS;
591 1.43 augustss dip->mixer_class = AUDIOAMD_MONITOR_CLASS;
592 1.43 augustss dip->next = dip->prev = AUDIO_MIXER_LAST;
593 1.43 augustss strcpy(dip->label.name, AudioCmonitor);
594 1.43 augustss break;
595 1.43 augustss default:
596 1.43 augustss return ENXIO;
597 1.43 augustss /*NOTREACHED*/
598 1.43 augustss }
599 1.43 augustss
600 1.43 augustss DPRINTF(("AUDIO_MIXER_DEVINFO: name=%s\n", dip->label.name));
601 1.43 augustss
602 1.43 augustss return(0);
603 1.1 pk }
604 1.43 augustss
605 1.39 jonathan #endif /* NAUDIO */
606