FreeBSD/Linux Kernel Cross Reference
sys/dev/ic/ad1848.c
1 /* $NetBSD: ad1848.c,v 1.25 2006/11/16 01:32:50 christos Exp $ */
2
3 /*-
4 * Copyright (c) 1999 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Ken Hornstein and John Kohl.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the NetBSD
21 * Foundation, Inc. and its contributors.
22 * 4. Neither the name of The NetBSD Foundation nor the names of its
23 * contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 */
38 /*
39 * Copyright (c) 1994 John Brezak
40 * Copyright (c) 1991-1993 Regents of the University of California.
41 * All rights reserved.
42 *
43 * Redistribution and use in source and binary forms, with or without
44 * modification, are permitted provided that the following conditions
45 * are met:
46 * 1. Redistributions of source code must retain the above copyright
47 * notice, this list of conditions and the following disclaimer.
48 * 2. Redistributions in binary form must reproduce the above copyright
49 * notice, this list of conditions and the following disclaimer in the
50 * documentation and/or other materials provided with the distribution.
51 * 3. All advertising materials mentioning features or use of this software
52 * must display the following acknowledgement:
53 * This product includes software developed by the Computer Systems
54 * Engineering Group at Lawrence Berkeley Laboratory.
55 * 4. Neither the name of the University nor of the Laboratory may be used
56 * to endorse or promote products derived from this software without
57 * specific prior written permission.
58 *
59 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
60 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
61 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
62 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
63 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
64 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
65 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
66 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
67 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
68 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
69 * SUCH DAMAGE.
70 *
71 */
72
73 /*
74 * Copyright by Hannu Savolainen 1994
75 *
76 * Redistribution and use in source and binary forms, with or without
77 * modification, are permitted provided that the following conditions are
78 * met: 1. Redistributions of source code must retain the above copyright
79 * notice, this list of conditions and the following disclaimer. 2.
80 * Redistributions in binary form must reproduce the above copyright notice,
81 * this list of conditions and the following disclaimer in the documentation
82 * and/or other materials provided with the distribution.
83 *
84 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
85 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
86 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
87 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
88 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
89 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
90 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
91 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
92 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
93 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
94 * SUCH DAMAGE.
95 *
96 */
97 /*
98 * Portions of this code are from the VOXware support for the ad1848
99 * by Hannu Savolainen <hannu@voxware.pp.fi>
100 *
101 * Portions also supplied from the SoundBlaster driver for NetBSD.
102 */
103
104 #include <sys/cdefs.h>
105 __KERNEL_RCSID(0, "$NetBSD: ad1848.c,v 1.25 2006/11/16 01:32:50 christos Exp $");
106
107 #include <sys/param.h>
108 #include <sys/systm.h>
109 #include <sys/errno.h>
110 #include <sys/ioctl.h>
111 #include <sys/device.h>
112 #include <sys/fcntl.h>
113 /*#include <sys/syslog.h>*/
114 /*#include <sys/proc.h>*/
115
116 #include <machine/cpu.h>
117 #include <machine/bus.h>
118
119 #include <sys/audioio.h>
120
121 #include <dev/audio_if.h>
122 #include <dev/auconv.h>
123
124 #include <dev/ic/ad1848reg.h>
125 #include <dev/ic/cs4231reg.h>
126 #include <dev/ic/cs4237reg.h>
127 #include <dev/ic/ad1848var.h>
128 #if 0
129 #include <dev/isa/cs4231var.h>
130 #endif
131
132 /*
133 * AD1845 on some machines don't match the AD1845 doc
134 * and defining AD1845_HACK to 1 works around the problems.
135 * options AD1845_HACK=0 should work if you have ``correct'' one.
136 */
137 #ifndef AD1845_HACK
138 #define AD1845_HACK 1 /* weird mixer, can't play slinear_be */
139 #endif
140
141 #ifdef AUDIO_DEBUG
142 #define DPRINTF(x) if (ad1848debug) printf x
143 int ad1848debug = 0;
144 #else
145 #define DPRINTF(x)
146 #endif
147
148 /*
149 * Initial values for the indirect registers of CS4248/AD1848.
150 */
151 static const int ad1848_init_values[] = {
152 GAIN_12|INPUT_MIC_GAIN_ENABLE, /* Left Input Control */
153 GAIN_12|INPUT_MIC_GAIN_ENABLE, /* Right Input Control */
154 ATTEN_12, /* Left Aux #1 Input Control */
155 ATTEN_12, /* Right Aux #1 Input Control */
156 ATTEN_12, /* Left Aux #2 Input Control */
157 ATTEN_12, /* Right Aux #2 Input Control */
158 /* bits 5-0 are attenuation select */
159 ATTEN_12, /* Left DAC output Control */
160 ATTEN_12, /* Right DAC output Control */
161 CLOCK_XTAL1|FMT_PCM8, /* Clock and Data Format */
162 SINGLE_DMA|AUTO_CAL_ENABLE, /* Interface Config */
163 INTERRUPT_ENABLE, /* Pin control */
164 0x00, /* Test and Init */
165 MODE2, /* Misc control */
166 ATTEN_0<<2, /* Digital Mix Control */
167 0, /* Upper base Count */
168 0, /* Lower base Count */
169
170 /* These are for CS4231 &c. only (additional registers): */
171 0, /* Alt feature 1 */
172 0, /* Alt feature 2 */
173 ATTEN_12, /* Left line in */
174 ATTEN_12, /* Right line in */
175 0, /* Timer low */
176 0, /* Timer high */
177 0, /* unused */
178 0, /* unused */
179 0, /* IRQ status */
180 0, /* unused */
181 /* Mono input (a.k.a speaker) (mic) Control */
182 MONO_INPUT_MUTE|ATTEN_6, /* mute speaker by default */
183 0, /* unused */
184 0, /* record format */
185 0, /* Crystal Clock Select */
186 0, /* upper record count */
187 0 /* lower record count */
188 };
189
190
191 int
192 ad1848_to_vol(mixer_ctrl_t *cp, struct ad1848_volume *vol)
193 {
194
195 if (cp->un.value.num_channels == 1) {
196 vol->left =
197 vol->right = cp->un.value.level[AUDIO_MIXER_LEVEL_MONO];
198 return 1;
199 }
200 else if (cp->un.value.num_channels == 2) {
201 vol->left = cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT];
202 vol->right = cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
203 return 1;
204 }
205 return 0;
206 }
207
208 int
209 ad1848_from_vol(mixer_ctrl_t *cp, struct ad1848_volume *vol)
210 {
211
212 if (cp->un.value.num_channels == 1) {
213 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = vol->left;
214 return 1;
215 }
216 else if (cp->un.value.num_channels == 2) {
217 cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = vol->left;
218 cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = vol->right;
219 return 1;
220 }
221 return 0;
222 }
223
224
225 inline int
226 ad_read(struct ad1848_softc *sc, int reg)
227 {
228 int x;
229
230 ADWRITE(sc, AD1848_IADDR, (reg & 0xff) | sc->MCE_bit);
231 x = ADREAD(sc, AD1848_IDATA);
232 /* printf("(%02x<-%02x) ", reg|sc->MCE_bit, x); */
233 return x;
234 }
235
236 inline void
237 ad_write(struct ad1848_softc *sc, int reg, int data)
238 {
239
240 ADWRITE(sc, AD1848_IADDR, (reg & 0xff) | sc->MCE_bit);
241 ADWRITE(sc, AD1848_IDATA, data & 0xff);
242 /* printf("(%02x->%02x) ", reg|sc->MCE_bit, data); */
243 }
244
245 /*
246 * extended registers (mode 3) require an additional level of
247 * indirection through CS_XREG (I23).
248 */
249
250 inline int
251 ad_xread(struct ad1848_softc *sc, int reg)
252 {
253 int x;
254
255 ADWRITE(sc, AD1848_IADDR, CS_XREG | sc->MCE_bit);
256 ADWRITE(sc, AD1848_IDATA, (reg | ALT_F3_XRAE) & 0xff);
257 x = ADREAD(sc, AD1848_IDATA);
258
259 return x;
260 }
261
262 inline void
263 ad_xwrite(struct ad1848_softc *sc, int reg, int val)
264 {
265
266 ADWRITE(sc, AD1848_IADDR, CS_XREG | sc->MCE_bit);
267 ADWRITE(sc, AD1848_IDATA, (reg | ALT_F3_XRAE) & 0xff);
268 ADWRITE(sc, AD1848_IDATA, val & 0xff);
269 }
270
271 static void
272 ad_set_MCE(struct ad1848_softc *sc, int state)
273 {
274
275 if (state)
276 sc->MCE_bit = MODE_CHANGE_ENABLE;
277 else
278 sc->MCE_bit = 0;
279 ADWRITE(sc, AD1848_IADDR, sc->MCE_bit);
280 }
281
282 static void
283 wait_for_calibration(struct ad1848_softc *sc)
284 {
285 int timeout;
286
287 DPRINTF(("ad1848: Auto calibration started.\n"));
288 /*
289 * Wait until the auto calibration process has finished.
290 *
291 * 1) Wait until the chip becomes ready (reads don't return 0x80).
292 * 2) Wait until the ACI bit of I11 gets on and then off.
293 * Because newer chips are fast we may never see the ACI
294 * bit go on. Just delay a little instead.
295 */
296 timeout = 10000;
297 while (timeout > 0 && ADREAD(sc, AD1848_IADDR) == SP_IN_INIT) {
298 delay(10);
299 timeout--;
300 }
301 if (timeout <= 0) {
302 DPRINTF(("ad1848: Auto calibration timed out(1).\n"));
303 }
304
305 /* Set register addr */
306 ADWRITE(sc, AD1848_IADDR, SP_TEST_AND_INIT);
307 /* Wait for address to appear when read back. */
308 timeout = 100000;
309 while (timeout > 0 &&
310 (ADREAD(sc, AD1848_IADDR)&SP_IADDR_MASK) != SP_TEST_AND_INIT) {
311 delay(10);
312 timeout--;
313 }
314 if (timeout <= 0) {
315 DPRINTF(("ad1848: Auto calibration timed out(1.5).\n"));
316 }
317
318 if (!(ad_read(sc, SP_TEST_AND_INIT) & AUTO_CAL_IN_PROG)) {
319 if (sc->mode > 1) {
320 /* A new chip, just delay a little. */
321 delay(100); /* XXX what should it be? */
322 } else {
323 timeout = 10000;
324 while (timeout > 0 &&
325 !(ad_read(sc, SP_TEST_AND_INIT) &
326 AUTO_CAL_IN_PROG)) {
327 delay(10);
328 timeout--;
329 }
330 if (timeout <= 0) {
331 DPRINTF(("ad1848: Auto calibration timed out(2).\n"));
332 }
333 }
334 }
335
336 timeout = 10000;
337 while (timeout > 0 &&
338 ad_read(sc, SP_TEST_AND_INIT) & AUTO_CAL_IN_PROG) {
339 delay(10);
340 timeout--;
341 }
342 if (timeout <= 0) {
343 DPRINTF(("ad1848: Auto calibration timed out(3).\n"));
344 }
345 }
346
347 #ifdef AUDIO_DEBUG
348 void
349 ad1848_dump_regs(struct ad1848_softc *sc)
350 {
351 int i;
352 u_char r;
353
354 printf("ad1848 status=%02x", ADREAD(sc, AD1848_STATUS));
355 printf(" regs: ");
356 for (i = 0; i < 16; i++) {
357 r = ad_read(sc, i);
358 printf("%02x ", r);
359 }
360 if (sc->mode >= 2) {
361 for (i = 16; i < 32; i++) {
362 r = ad_read(sc, i);
363 printf("%02x ", r);
364 }
365 }
366 printf("\n");
367 }
368 #endif /* AUDIO_DEBUG */
369
370
371 /*
372 * Attach hardware to driver, attach hardware driver to audio
373 * pseudo-device driver .
374 */
375 void
376 ad1848_attach(struct ad1848_softc *sc)
377 {
378 static struct ad1848_volume vol_mid = {220, 220};
379 static struct ad1848_volume vol_0 = {0, 0};
380 int i;
381 int timeout;
382
383 /* Initialize the ad1848... */
384 for (i = 0; i < 0x10; i++) {
385 ad_write(sc, i, ad1848_init_values[i]);
386 timeout = 100000;
387 while (timeout > 0 && ADREAD(sc, AD1848_IADDR) & SP_IN_INIT)
388 timeout--;
389 }
390 /* ...and additional CS4231 stuff too */
391 if (sc->mode >= 2) {
392 ad_write(sc, SP_INTERFACE_CONFIG, 0); /* disable SINGLE_DMA */
393 for (i = 0x10; i < 0x20; i++)
394 if (ad1848_init_values[i] != 0) {
395 ad_write(sc, i, ad1848_init_values[i]);
396 timeout = 100000;
397 while (timeout > 0 &&
398 ADREAD(sc, AD1848_IADDR) & SP_IN_INIT)
399 timeout--;
400 }
401 }
402 ad1848_reset(sc);
403
404 /* Set default gains */
405 ad1848_set_rec_gain(sc, &vol_mid);
406 ad1848_set_channel_gain(sc, AD1848_DAC_CHANNEL, &vol_mid);
407 ad1848_set_channel_gain(sc, AD1848_MONITOR_CHANNEL, &vol_0);
408 ad1848_set_channel_gain(sc, AD1848_AUX1_CHANNEL, &vol_mid); /* CD volume */
409 sc->mute[AD1848_MONITOR_CHANNEL] = MUTE_ALL;
410 if (sc->mode >= 2
411 #if AD1845_HACK
412 && sc->is_ad1845 == 0
413 #endif
414 ) {
415 ad1848_set_channel_gain(sc, AD1848_AUX2_CHANNEL, &vol_mid); /* CD volume */
416 ad1848_set_channel_gain(sc, AD1848_LINE_CHANNEL, &vol_mid);
417 ad1848_set_channel_gain(sc, AD1848_MONO_CHANNEL, &vol_0);
418 sc->mute[AD1848_MONO_CHANNEL] = MUTE_ALL;
419 } else
420 ad1848_set_channel_gain(sc, AD1848_AUX2_CHANNEL, &vol_0);
421
422 /* Set default port */
423 ad1848_set_rec_port(sc, MIC_IN_PORT);
424
425 printf(": %s", sc->chip_name);
426 }
427
428 /*
429 * Various routines to interface to higher level audio driver
430 */
431 static const struct ad1848_mixerinfo {
432 int left_reg;
433 int right_reg;
434 int atten_bits;
435 int atten_mask;
436 } mixer_channel_info[] =
437 {
438 { SP_LEFT_AUX2_CONTROL, SP_RIGHT_AUX2_CONTROL, AUX_INPUT_ATTEN_BITS,
439 AUX_INPUT_ATTEN_MASK },
440 { SP_LEFT_AUX1_CONTROL, SP_RIGHT_AUX1_CONTROL, AUX_INPUT_ATTEN_BITS,
441 AUX_INPUT_ATTEN_MASK },
442 { SP_LEFT_OUTPUT_CONTROL, SP_RIGHT_OUTPUT_CONTROL,
443 OUTPUT_ATTEN_BITS, OUTPUT_ATTEN_MASK },
444 { CS_LEFT_LINE_CONTROL, CS_RIGHT_LINE_CONTROL, LINE_INPUT_ATTEN_BITS,
445 LINE_INPUT_ATTEN_MASK },
446 { CS_MONO_IO_CONTROL, 0, MONO_INPUT_ATTEN_BITS, MONO_INPUT_ATTEN_MASK },
447 { CS_MONO_IO_CONTROL, 0, 0, 0 },
448 { SP_DIGITAL_MIX, 0, OUTPUT_ATTEN_BITS, MIX_ATTEN_MASK }
449 };
450
451 /*
452 * This function doesn't set the mute flags but does use them.
453 * The mute flags reflect the mutes that have been applied by the user.
454 * However, the driver occasionally wants to mute devices (e.g. when chaing
455 * sampling rate). These operations should not affect the mute flags.
456 */
457
458 void
459 ad1848_mute_channel(struct ad1848_softc *sc, int device, int mute)
460 {
461 u_char reg;
462
463 reg = ad_read(sc, mixer_channel_info[device].left_reg);
464
465 if (mute & MUTE_LEFT) {
466 if (device == AD1848_MONITOR_CHANNEL) {
467 if (sc->open_mode & FREAD)
468 ad1848_mute_wave_output(sc, WAVE_UNMUTE1, 0);
469 ad_write(sc, mixer_channel_info[device].left_reg,
470 reg & ~DIGITAL_MIX1_ENABLE);
471 } else if (device == AD1848_OUT_CHANNEL)
472 ad_write(sc, mixer_channel_info[device].left_reg,
473 reg | MONO_OUTPUT_MUTE);
474 else
475 ad_write(sc, mixer_channel_info[device].left_reg,
476 reg | 0x80);
477 } else if (!(sc->mute[device] & MUTE_LEFT)) {
478 if (device == AD1848_MONITOR_CHANNEL) {
479 ad_write(sc, mixer_channel_info[device].left_reg,
480 reg | DIGITAL_MIX1_ENABLE);
481 if (sc->open_mode & FREAD)
482 ad1848_mute_wave_output(sc, WAVE_UNMUTE1, 1);
483 } else if (device == AD1848_OUT_CHANNEL)
484 ad_write(sc, mixer_channel_info[device].left_reg,
485 reg & ~MONO_OUTPUT_MUTE);
486 else
487 ad_write(sc, mixer_channel_info[device].left_reg,
488 reg & ~0x80);
489 }
490
491 if (!mixer_channel_info[device].right_reg)
492 return;
493
494 reg = ad_read(sc, mixer_channel_info[device].right_reg);
495
496 if (mute & MUTE_RIGHT) {
497 ad_write(sc, mixer_channel_info[device].right_reg, reg | 0x80);
498 } else if (!(sc->mute[device] & MUTE_RIGHT)) {
499 ad_write(sc, mixer_channel_info[device].right_reg, reg &~0x80);
500 }
501 }
502
503 int
504 ad1848_set_channel_gain(struct ad1848_softc *sc, int device,
505 struct ad1848_volume *gp)
506 {
507 const struct ad1848_mixerinfo *info;
508 u_char reg;
509 u_int atten;
510
511 info = &mixer_channel_info[device];
512 sc->gains[device] = *gp;
513
514 atten = (AUDIO_MAX_GAIN - gp->left) * (info->atten_bits + 1) /
515 (AUDIO_MAX_GAIN + 1);
516
517 reg = ad_read(sc, info->left_reg) & (info->atten_mask);
518 if (device == AD1848_MONITOR_CHANNEL)
519 reg |= ((atten & info->atten_bits) << 2);
520 else
521 reg |= ((atten & info->atten_bits));
522
523 ad_write(sc, info->left_reg, reg);
524
525 if (!info->right_reg)
526 return 0;
527
528 atten = (AUDIO_MAX_GAIN - gp->right) * (info->atten_bits + 1) /
529 (AUDIO_MAX_GAIN + 1);
530 reg = ad_read(sc, info->right_reg);
531 reg &= info->atten_mask;
532 ad_write(sc, info->right_reg, (atten & info->atten_bits) | reg);
533
534 return 0;
535 }
536
537 int
538 ad1848_get_device_gain(struct ad1848_softc *sc, int device,
539 struct ad1848_volume *gp)
540 {
541
542 *gp = sc->gains[device];
543 return 0;
544 }
545
546 int
547 ad1848_get_rec_gain(struct ad1848_softc *sc, struct ad1848_volume *gp)
548 {
549
550 *gp = sc->rec_gain;
551 return 0;
552 }
553
554 int
555 ad1848_set_rec_gain(struct ad1848_softc *sc, struct ad1848_volume *gp)
556 {
557 u_char reg, gain;
558
559 DPRINTF(("ad1848_set_rec_gain: %d:%d\n", gp->left, gp->right));
560
561 sc->rec_gain = *gp;
562
563 gain = (gp->left * (GAIN_22_5 + 1)) / (AUDIO_MAX_GAIN + 1);
564 reg = ad_read(sc, SP_LEFT_INPUT_CONTROL);
565 reg &= INPUT_GAIN_MASK;
566 ad_write(sc, SP_LEFT_INPUT_CONTROL, (gain & 0x0f) | reg);
567
568 gain = (gp->right * (GAIN_22_5 + 1)) / (AUDIO_MAX_GAIN + 1);
569 reg = ad_read(sc, SP_RIGHT_INPUT_CONTROL);
570 reg &= INPUT_GAIN_MASK;
571 ad_write(sc, SP_RIGHT_INPUT_CONTROL, (gain & 0x0f) | reg);
572
573 return 0;
574 }
575
576 void
577 ad1848_mute_wave_output(struct ad1848_softc *sc, int mute, int set)
578 {
579 int m;
580
581 DPRINTF(("ad1848_mute_wave_output: %d, %d\n", mute, set));
582
583 if (mute == WAVE_MUTE2_INIT) {
584 sc->wave_mute_status = 0;
585 mute = WAVE_MUTE2;
586 }
587 if (set)
588 m = sc->wave_mute_status |= mute;
589 else
590 m = sc->wave_mute_status &= ~mute;
591
592 if (m & WAVE_MUTE0 || ((m & WAVE_UNMUTE1) == 0 && m & WAVE_MUTE2))
593 ad1848_mute_channel(sc, AD1848_DAC_CHANNEL, MUTE_ALL);
594 else
595 ad1848_mute_channel(sc, AD1848_DAC_CHANNEL,
596 sc->mute[AD1848_DAC_CHANNEL]);
597 }
598
599 int
600 ad1848_set_mic_gain(struct ad1848_softc *sc, struct ad1848_volume *gp)
601 {
602 u_char reg;
603
604 DPRINTF(("cs4231_set_mic_gain: %d\n", gp->left));
605
606 if (gp->left > AUDIO_MAX_GAIN/2) {
607 sc->mic_gain_on = 1;
608 reg = ad_read(sc, SP_LEFT_INPUT_CONTROL);
609 ad_write(sc, SP_LEFT_INPUT_CONTROL,
610 reg | INPUT_MIC_GAIN_ENABLE);
611 } else {
612 sc->mic_gain_on = 0;
613 reg = ad_read(sc, SP_LEFT_INPUT_CONTROL);
614 ad_write(sc, SP_LEFT_INPUT_CONTROL,
615 reg & ~INPUT_MIC_GAIN_ENABLE);
616 }
617
618 return 0;
619 }
620
621 int
622 ad1848_get_mic_gain(struct ad1848_softc *sc, struct ad1848_volume *gp)
623 {
624 if (sc->mic_gain_on)
625 gp->left = gp->right = AUDIO_MAX_GAIN;
626 else
627 gp->left = gp->right = AUDIO_MIN_GAIN;
628 return 0;
629 }
630
631 static ad1848_devmap_t *
632 ad1848_mixer_find_dev(ad1848_devmap_t *map, int cnt, mixer_ctrl_t *cp)
633 {
634 int i;
635
636 for (i = 0; i < cnt; i++) {
637 if (map[i].id == cp->dev) {
638 return (&map[i]);
639 }
640 }
641 return 0;
642 }
643
644 int
645 ad1848_mixer_get_port(struct ad1848_softc *ac, struct ad1848_devmap *map,
646 int cnt, mixer_ctrl_t *cp)
647 {
648 ad1848_devmap_t *entry;
649 struct ad1848_volume vol;
650 int error;
651 int dev;
652
653 error = EINVAL;
654 if (!(entry = ad1848_mixer_find_dev(map, cnt, cp)))
655 return ENXIO;
656
657 dev = entry->dev;
658
659 switch (entry->kind) {
660 case AD1848_KIND_LVL:
661 if (cp->type != AUDIO_MIXER_VALUE)
662 break;
663
664 if (dev < AD1848_AUX2_CHANNEL ||
665 dev > AD1848_MONITOR_CHANNEL)
666 break;
667
668 if (cp->un.value.num_channels != 1 &&
669 mixer_channel_info[dev].right_reg == 0)
670 break;
671
672 error = ad1848_get_device_gain(ac, dev, &vol);
673 if (!error)
674 ad1848_from_vol(cp, &vol);
675
676 break;
677
678 case AD1848_KIND_MUTE:
679 if (cp->type != AUDIO_MIXER_ENUM) break;
680
681 cp->un.ord = ac->mute[dev] ? 1 : 0;
682 error = 0;
683 break;
684
685 case AD1848_KIND_RECORDGAIN:
686 if (cp->type != AUDIO_MIXER_VALUE) break;
687
688 error = ad1848_get_rec_gain(ac, &vol);
689 if (!error)
690 ad1848_from_vol(cp, &vol);
691
692 break;
693
694 case AD1848_KIND_MICGAIN:
695 if (cp->type != AUDIO_MIXER_VALUE) break;
696
697 error = ad1848_get_mic_gain(ac, &vol);
698 if (!error)
699 ad1848_from_vol(cp, &vol);
700
701 break;
702
703 case AD1848_KIND_RECORDSOURCE:
704 if (cp->type != AUDIO_MIXER_ENUM) break;
705 cp->un.ord = ad1848_get_rec_port(ac);
706 error = 0;
707 break;
708
709 default:
710 printf ("Invalid kind\n");
711 break;
712 }
713
714 return error;
715 }
716
717 int
718 ad1848_mixer_set_port(struct ad1848_softc *ac, struct ad1848_devmap *map,
719 int cnt, mixer_ctrl_t *cp)
720 {
721 ad1848_devmap_t *entry;
722 struct ad1848_volume vol;
723 int error;
724 int dev;
725
726 error = EINVAL;
727 if (!(entry = ad1848_mixer_find_dev(map, cnt, cp)))
728 return ENXIO;
729
730 dev = entry->dev;
731
732 switch (entry->kind) {
733 case AD1848_KIND_LVL:
734 if (cp->type != AUDIO_MIXER_VALUE)
735 break;
736
737 if (dev < AD1848_AUX2_CHANNEL ||
738 dev > AD1848_MONITOR_CHANNEL)
739 break;
740
741 if (cp->un.value.num_channels != 1 &&
742 mixer_channel_info[dev].right_reg == 0)
743 break;
744
745 ad1848_to_vol(cp, &vol);
746 error = ad1848_set_channel_gain(ac, dev, &vol);
747 break;
748
749 case AD1848_KIND_MUTE:
750 if (cp->type != AUDIO_MIXER_ENUM) break;
751
752 ac->mute[dev] = (cp->un.ord ? MUTE_ALL : 0);
753 ad1848_mute_channel(ac, dev, ac->mute[dev]);
754 error = 0;
755 break;
756
757 case AD1848_KIND_RECORDGAIN:
758 if (cp->type != AUDIO_MIXER_VALUE) break;
759
760 ad1848_to_vol(cp, &vol);
761 error = ad1848_set_rec_gain(ac, &vol);
762 break;
763
764 case AD1848_KIND_MICGAIN:
765 if (cp->type != AUDIO_MIXER_VALUE) break;
766
767 ad1848_to_vol(cp, &vol);
768 error = ad1848_set_mic_gain(ac, &vol);
769 break;
770
771 case AD1848_KIND_RECORDSOURCE:
772 if (cp->type != AUDIO_MIXER_ENUM) break;
773
774 error = ad1848_set_rec_port(ac, cp->un.ord);
775 break;
776
777 default:
778 printf ("Invalid kind\n");
779 break;
780 }
781
782 return error;
783 }
784
785 int
786 ad1848_query_encoding(void *addr, struct audio_encoding *fp)
787 {
788 struct ad1848_softc *sc;
789
790 sc = addr;
791 switch (fp->index) {
792 case 0:
793 strcpy(fp->name, AudioEmulaw);
794 fp->encoding = AUDIO_ENCODING_ULAW;
795 fp->precision = 8;
796 fp->flags = 0;
797 break;
798 case 1:
799 strcpy(fp->name, AudioEalaw);
800 fp->encoding = AUDIO_ENCODING_ALAW;
801 fp->precision = 8;
802 fp->flags = 0;
803 break;
804 case 2:
805 strcpy(fp->name, AudioEslinear_le);
806 fp->encoding = AUDIO_ENCODING_SLINEAR_LE;
807 fp->precision = 16;
808 fp->flags = 0;
809 break;
810 case 3:
811 strcpy(fp->name, AudioEulinear);
812 fp->encoding = AUDIO_ENCODING_ULINEAR;
813 fp->precision = 8;
814 fp->flags = 0;
815 break;
816
817 case 4: /* only on CS4231 */
818 strcpy(fp->name, AudioEslinear_be);
819 fp->encoding = AUDIO_ENCODING_SLINEAR_BE;
820 fp->precision = 16;
821 fp->flags = sc->mode == 1
822 #if AD1845_HACK
823 || sc->is_ad1845
824 #endif
825 ? AUDIO_ENCODINGFLAG_EMULATED : 0;
826 break;
827
828 /* emulate some modes */
829 case 5:
830 strcpy(fp->name, AudioEslinear);
831 fp->encoding = AUDIO_ENCODING_SLINEAR;
832 fp->precision = 8;
833 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
834 break;
835 case 6:
836 strcpy(fp->name, AudioEulinear_le);
837 fp->encoding = AUDIO_ENCODING_ULINEAR_LE;
838 fp->precision = 16;
839 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
840 break;
841 case 7:
842 strcpy(fp->name, AudioEulinear_be);
843 fp->encoding = AUDIO_ENCODING_ULINEAR_BE;
844 fp->precision = 16;
845 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
846 break;
847
848 case 8: /* only on CS4231 */
849 if (sc->mode == 1 || sc->is_ad1845)
850 return EINVAL;
851 strcpy(fp->name, AudioEadpcm);
852 fp->encoding = AUDIO_ENCODING_ADPCM;
853 fp->precision = 4;
854 fp->flags = 0;
855 break;
856 default:
857 return EINVAL;
858 /*NOTREACHED*/
859 }
860 return 0;
861 }
862
863 int
864 ad1848_set_params(void *addr, int setmode, int usemode,
865 audio_params_t *p, audio_params_t *r, stream_filter_list_t *pfil,
866 stream_filter_list_t *rfil)
867 {
868 audio_params_t phw, rhw;
869 struct ad1848_softc *sc;
870 int error, bits, enc;
871 stream_filter_factory_t *pswcode;
872 stream_filter_factory_t *rswcode;
873
874 DPRINTF(("ad1848_set_params: %u %u %u %u\n",
875 p->encoding, p->precision, p->channels, p->sample_rate));
876
877 sc = addr;
878 enc = p->encoding;
879 pswcode = rswcode = 0;
880 phw = *p;
881 rhw = *r;
882 switch (enc) {
883 case AUDIO_ENCODING_SLINEAR_LE:
884 if (p->precision == 8) {
885 enc = AUDIO_ENCODING_ULINEAR_LE;
886 phw.encoding = AUDIO_ENCODING_ULINEAR_LE;
887 rhw.encoding = AUDIO_ENCODING_ULINEAR_LE;
888 pswcode = rswcode = change_sign8;
889 }
890 break;
891 case AUDIO_ENCODING_SLINEAR_BE:
892 if (p->precision == 16 && (sc->mode == 1
893 #if AD1845_HACK
894 || sc->is_ad1845
895 #endif
896 )) {
897 enc = AUDIO_ENCODING_SLINEAR_LE;
898 phw.encoding = AUDIO_ENCODING_SLINEAR_LE;
899 rhw.encoding = AUDIO_ENCODING_SLINEAR_LE;
900 pswcode = rswcode = swap_bytes;
901 }
902 break;
903 case AUDIO_ENCODING_ULINEAR_LE:
904 if (p->precision == 16) {
905 enc = AUDIO_ENCODING_SLINEAR_LE;
906 phw.encoding = AUDIO_ENCODING_SLINEAR_LE;
907 rhw.encoding = AUDIO_ENCODING_SLINEAR_LE;
908 pswcode = rswcode = change_sign16;
909 }
910 break;
911 case AUDIO_ENCODING_ULINEAR_BE:
912 if (p->precision == 16) {
913 if (sc->mode == 1
914 #if AD1845_HACK
915 || sc->is_ad1845
916 #endif
917 ) {
918 enc = AUDIO_ENCODING_SLINEAR_LE;
919 phw.encoding = AUDIO_ENCODING_SLINEAR_LE;
920 rhw.encoding = AUDIO_ENCODING_SLINEAR_LE;
921 pswcode = swap_bytes_change_sign16;
922 rswcode = swap_bytes_change_sign16;
923 } else {
924 enc = AUDIO_ENCODING_SLINEAR_BE;
925 phw.encoding = AUDIO_ENCODING_SLINEAR_BE;
926 rhw.encoding = AUDIO_ENCODING_SLINEAR_BE;
927 pswcode = rswcode = change_sign16;
928 }
929 }
930 break;
931 }
932 switch (enc) {
933 case AUDIO_ENCODING_ULAW:
934 bits = FMT_ULAW >> 5;
935 break;
936 case AUDIO_ENCODING_ALAW:
937 bits = FMT_ALAW >> 5;
938 break;
939 case AUDIO_ENCODING_ADPCM:
940 bits = FMT_ADPCM >> 5;
941 break;
942 case AUDIO_ENCODING_SLINEAR_LE:
943 if (p->precision == 16)
944 bits = FMT_TWOS_COMP >> 5;
945 else
946 return EINVAL;
947 break;
948 case AUDIO_ENCODING_SLINEAR_BE:
949 if (p->precision == 16)
950 bits = FMT_TWOS_COMP_BE >> 5;
951 else
952 return EINVAL;
953 break;
954 case AUDIO_ENCODING_ULINEAR_LE:
955 if (p->precision == 8)
956 bits = FMT_PCM8 >> 5;
957 else
958 return EINVAL;
959 break;
960 default:
961 return EINVAL;
962 }
963
964 if (p->channels < 1 || p->channels > 2)
965 return EINVAL;
966
967 error = ad1848_set_speed(sc, &p->sample_rate);
968 if (error)
969 return error;
970 phw.sample_rate = p->sample_rate;
971
972 if (pswcode != NULL)
973 pfil->append(pfil, pswcode, &phw);
974 if (rswcode != NULL)
975 rfil->append(rfil, rswcode, &rhw);
976
977 sc->format_bits = bits;
978 sc->channels = p->channels;
979 sc->precision = p->precision;
980 sc->need_commit = 1;
981
982 DPRINTF(("ad1848_set_params succeeded, bits=%x\n", bits));
983 return 0;
984 }
985
986 int
987 ad1848_set_rec_port(struct ad1848_softc *sc, int port)
988 {
989 u_char inp, reg;
990
991 DPRINTF(("ad1848_set_rec_port: 0x%x\n", port));
992
993 if (port == MIC_IN_PORT)
994 inp = MIC_INPUT;
995 else if (port == LINE_IN_PORT)
996 inp = LINE_INPUT;
997 else if (port == DAC_IN_PORT)
998 inp = MIXED_DAC_INPUT;
999 else if (sc->mode >= 2 && port == AUX1_IN_PORT)
1000 inp = AUX_INPUT;
1001 else
1002 return EINVAL;
1003
1004 reg = ad_read(sc, SP_LEFT_INPUT_CONTROL);
1005 reg &= INPUT_SOURCE_MASK;
1006 ad_write(sc, SP_LEFT_INPUT_CONTROL, (inp|reg));
1007
1008 reg = ad_read(sc, SP_RIGHT_INPUT_CONTROL);
1009 reg &= INPUT_SOURCE_MASK;
1010 ad_write(sc, SP_RIGHT_INPUT_CONTROL, (inp|reg));
1011
1012 sc->rec_port = port;
1013
1014 return 0;
1015 }
1016
1017 int
1018 ad1848_get_rec_port(struct ad1848_softc *sc)
1019 {
1020 return sc->rec_port;
1021 }
1022
1023 int
1024 ad1848_round_blocksize(void *addr, int blk,
1025 int mode, const audio_params_t *param)
1026 {
1027
1028 /* Round to a multiple of the biggest sample size. */
1029 return blk &= -4;
1030 }
1031
1032 int
1033 ad1848_open(void *addr, int flags)
1034 {
1035 struct ad1848_softc *sc;
1036 u_char reg;
1037
1038 sc = addr;
1039 DPRINTF(("ad1848_open: sc=%p\n", sc));
1040
1041 sc->open_mode = flags;
1042
1043 /* Enable interrupts */
1044 DPRINTF(("ad1848_open: enable intrs\n"));
1045 reg = ad_read(sc, SP_PIN_CONTROL);
1046 ad_write(sc, SP_PIN_CONTROL, reg | INTERRUPT_ENABLE);
1047
1048 /* If recording && monitoring, the playback part is also used. */
1049 if (flags & FREAD && sc->mute[AD1848_MONITOR_CHANNEL] == 0)
1050 ad1848_mute_wave_output(sc, WAVE_UNMUTE1, 1);
1051
1052 #ifdef AUDIO_DEBUG
1053 if (ad1848debug)
1054 ad1848_dump_regs(sc);
1055 #endif
1056
1057 return 0;
1058 }
1059
1060 /*
1061 * Close function is called at splaudio().
1062 */
1063 void
1064 ad1848_close(void *addr)
1065 {
1066 struct ad1848_softc *sc;
1067 u_char reg;
1068
1069 sc = addr;
1070 sc->open_mode = 0;
1071
1072 ad1848_mute_wave_output(sc, WAVE_UNMUTE1, 0);
1073
1074 /* Disable interrupts */
1075 DPRINTF(("ad1848_close: disable intrs\n"));
1076 reg = ad_read(sc, SP_PIN_CONTROL);
1077 ad_write(sc, SP_PIN_CONTROL, reg & ~INTERRUPT_ENABLE);
1078
1079 #ifdef AUDIO_DEBUG
1080 if (ad1848debug)
1081 ad1848_dump_regs(sc);
1082 #endif
1083 }
1084
1085 /*
1086 * Lower-level routines
1087 */
1088 int
1089 ad1848_commit_settings(void *addr)
1090 {
1091 struct ad1848_softc *sc;
1092 int timeout;
1093 u_char fs;
1094 int s;
1095
1096 sc = addr;
1097 if (!sc->need_commit)
1098 return 0;
1099
1100 s = splaudio();
1101
1102 ad1848_mute_wave_output(sc, WAVE_MUTE0, 1);
1103
1104 ad_set_MCE(sc, 1); /* Enables changes to the format select reg */
1105
1106 fs = sc->speed_bits | (sc->format_bits << 5);
1107
1108 if (sc->channels == 2)
1109 fs |= FMT_STEREO;
1110
1111 /*
1112 * OPL3-SA2 (YMF711) is sometimes busy here.
1113 * Wait until it becomes ready.
1114 */
1115 for (timeout = 0;
1116 timeout < 1000 && ADREAD(sc, AD1848_IADDR) & SP_IN_INIT; timeout++)
1117 delay(10);
1118
1119 ad_write(sc, SP_CLOCK_DATA_FORMAT, fs);
1120
1121 /*
1122 * If mode >= 2 (CS4231), set I28 also.
1123 * It's the capture format register.
1124 */
1125 if (sc->mode >= 2) {
1126 /*
1127 * Gravis Ultrasound MAX SDK sources says something about
1128 * errata sheets, with the implication that these inb()s
1129 * are necessary.
1130 */
1131 (void)ADREAD(sc, AD1848_IDATA);
1132 (void)ADREAD(sc, AD1848_IDATA);
1133 /* Write to I8 starts resynchronization. Wait for completion. */
1134 timeout = 100000;
1135 while (timeout > 0 && ADREAD(sc, AD1848_IADDR) == SP_IN_INIT)
1136 timeout--;
1137
1138 ad_write(sc, CS_REC_FORMAT, fs);
1139 (void)ADREAD(sc, AD1848_IDATA);
1140 (void)ADREAD(sc, AD1848_IDATA);
1141 /* Now wait for resync for capture side of the house */
1142 }
1143 /*
1144 * Write to I8 starts resynchronization. Wait until it completes.
1145 */
1146 timeout = 100000;
1147 while (timeout > 0 && ADREAD(sc, AD1848_IADDR) == SP_IN_INIT) {
1148 delay(10);
1149 timeout--;
1150 }
1151
1152 if (ADREAD(sc, AD1848_IADDR) == SP_IN_INIT)
1153 printf("ad1848_commit: Auto calibration timed out\n");
1154
1155 /*
1156 * Starts the calibration process and
1157 * enters playback mode after it.
1158 */
1159 ad_set_MCE(sc, 0);
1160 wait_for_calibration(sc);
1161
1162 ad1848_mute_wave_output(sc, WAVE_MUTE0, 0);
1163
1164 splx(s);
1165
1166 sc->need_commit = 0;
1167 return 0;
1168 }
1169
1170 void
1171 ad1848_reset(struct ad1848_softc *sc)
1172 {
1173 u_char r;
1174
1175 DPRINTF(("ad1848_reset\n"));
1176
1177 /* Clear the PEN and CEN bits */
1178 r = ad_read(sc, SP_INTERFACE_CONFIG);
1179 r &= ~(CAPTURE_ENABLE | PLAYBACK_ENABLE);
1180 ad_write(sc, SP_INTERFACE_CONFIG, r);
1181
1182 if (sc->mode >= 2) {
1183 ADWRITE(sc, AD1848_IADDR, CS_IRQ_STATUS);
1184 ADWRITE(sc, AD1848_IDATA, 0);
1185 }
1186 /* Clear interrupt status */
1187 ADWRITE(sc, AD1848_STATUS, 0);
1188 #ifdef AUDIO_DEBUG
1189 if (ad1848debug)
1190 ad1848_dump_regs(sc);
1191 #endif
1192 }
1193
1194 int
1195 ad1848_set_speed(struct ad1848_softc *sc, u_int *argp)
1196 {
1197 /*
1198 * The sampling speed is encoded in the least significant nible of I8.
1199 * The LSB selects the clock source (0=24.576 MHz, 1=16.9344 MHz) and
1200 * other three bits select the divisor (indirectly):
1201 *
1202 * The available speeds are in the following table. Keep the speeds in
1203 * the increasing order.
1204 */
1205 typedef struct {
1206 int speed;
1207 u_char bits;
1208 } speed_struct;
1209 u_long arg;
1210
1211 static const speed_struct speed_table[] = {
1212 {5510, (0 << 1) | 1},
1213 {5510, (0 << 1) | 1},
1214 {6620, (7 << 1) | 1},
1215 {8000, (0 << 1) | 0},
1216 {9600, (7 << 1) | 0},
1217 {11025, (1 << 1) | 1},
1218 {16000, (1 << 1) | 0},
1219 {18900, (2 << 1) | 1},
1220 {22050, (3 << 1) | 1},
1221 {27420, (2 << 1) | 0},
1222 {32000, (3 << 1) | 0},
1223 {33075, (6 << 1) | 1},
1224 {37800, (4 << 1) | 1},
1225 {44100, (5 << 1) | 1},
1226 {48000, (6 << 1) | 0}
1227 };
1228
1229 int i, n, selected;
1230
1231 arg = *argp;
1232 selected = -1;
1233 n = sizeof(speed_table) / sizeof(speed_struct);
1234
1235 if (arg < speed_table[0].speed)
1236 selected = 0;
1237 if (arg > speed_table[n - 1].speed)
1238 selected = n - 1;
1239
1240 for (i = 1 /*really*/ ; selected == -1 && i < n; i++)
1241 if (speed_table[i].speed == arg)
1242 selected = i;
1243 else if (speed_table[i].speed > arg) {
1244 int diff1, diff2;
1245
1246 diff1 = arg - speed_table[i - 1].speed;
1247 diff2 = speed_table[i].speed - arg;
1248
1249 if (diff1 < diff2)
1250 selected = i - 1;
1251 else
1252 selected = i;
1253 }
1254
1255 if (selected == -1) {
1256 printf("ad1848: Can't find speed???\n");
1257 selected = 3;
1258 }
1259
1260 sc->speed_bits = speed_table[selected].bits;
1261 sc->need_commit = 1;
1262 *argp = speed_table[selected].speed;
1263
1264 return 0;
1265 }
1266
1267 /*
1268 * Halt I/O
1269 */
1270 int
1271 ad1848_halt_output(void *addr)
1272 {
1273 struct ad1848_softc *sc;
1274 u_char reg;
1275
1276 DPRINTF(("ad1848: ad1848_halt_output\n"));
1277 sc = addr;
1278 reg = ad_read(sc, SP_INTERFACE_CONFIG);
1279 ad_write(sc, SP_INTERFACE_CONFIG, reg & ~PLAYBACK_ENABLE);
1280
1281 return 0;
1282 }
1283
1284 int
1285 ad1848_halt_input(void *addr)
1286 {
1287 struct ad1848_softc *sc;
1288 u_char reg;
1289
1290 DPRINTF(("ad1848: ad1848_halt_input\n"));
1291 sc = addr;
1292 reg = ad_read(sc, SP_INTERFACE_CONFIG);
1293 ad_write(sc, SP_INTERFACE_CONFIG, reg & ~CAPTURE_ENABLE);
1294
1295 return 0;
1296 }
Cache object: b33b062e44b7e91976282fb0c7c797ca
|