This source file includes following definitions.
- cs4231_match
- cs4231_attach
- cs4231_write
- cs4231_read
- cs4231_set_speed
- speed_struct
- cs4231_open
- cs4231_setup_output
- cs4231_close
- cs4231_query_encoding
- cs4231_set_params
- cs4231_round_blocksize
- cs4231_commit_settings
- cs4231_halt_output
- cs4231_halt_input
- cs4231_getdev
- cs4231_set_port
- cs4231_get_port
- cs4231_query_devinfo
- cs4231_get_props
- cs4231_intr
- cs4231_alloc
- cs4231_free
- cs4231_trigger_output
- cs4231_trigger_input
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/device.h>
44 #include <sys/proc.h>
45 #include <sys/malloc.h>
46
47 #include <machine/bus.h>
48 #include <machine/intr.h>
49 #include <machine/autoconf.h>
50
51 #include <sys/audioio.h>
52 #include <dev/audio_if.h>
53 #include <dev/auconv.h>
54
55 #include <dev/ic/ad1848reg.h>
56 #include <dev/ic/cs4231reg.h>
57 #include <dev/ic/apcdmareg.h>
58 #include <dev/sbus/sbusvar.h>
59 #include <dev/sbus/cs4231var.h>
60
61 #define CSAUDIO_DAC_LVL 0
62 #define CSAUDIO_LINE_IN_LVL 1
63 #define CSAUDIO_MIC_LVL 2
64 #define CSAUDIO_CD_LVL 3
65 #define CSAUDIO_MONITOR_LVL 4
66 #define CSAUDIO_OUTPUT_LVL 5
67 #define CSAUDIO_LINE_IN_MUTE 6
68 #define CSAUDIO_DAC_MUTE 7
69 #define CSAUDIO_CD_MUTE 8
70 #define CSAUDIO_MIC_MUTE 9
71 #define CSAUDIO_MONITOR_MUTE 10
72 #define CSAUDIO_OUTPUT_MUTE 11
73 #define CSAUDIO_REC_LVL 12
74 #define CSAUDIO_RECORD_SOURCE 13
75 #define CSAUDIO_OUTPUT 14
76 #define CSAUDIO_INPUT_CLASS 15
77 #define CSAUDIO_OUTPUT_CLASS 16
78 #define CSAUDIO_RECORD_CLASS 17
79 #define CSAUDIO_MONITOR_CLASS 18
80
81 #define CSPORT_AUX2 0
82 #define CSPORT_AUX1 1
83 #define CSPORT_DAC 2
84 #define CSPORT_LINEIN 3
85 #define CSPORT_MONO 4
86 #define CSPORT_MONITOR 5
87 #define CSPORT_SPEAKER 6
88 #define CSPORT_LINEOUT 7
89 #define CSPORT_HEADPHONE 8
90 #define CSPORT_MICROPHONE 9
91
92 #define MIC_IN_PORT 0
93 #define LINE_IN_PORT 1
94 #define AUX1_IN_PORT 2
95 #define DAC_IN_PORT 3
96
97 #ifdef AUDIO_DEBUG
98 #define DPRINTF(x) printf x
99 #else
100 #define DPRINTF(x)
101 #endif
102
103 #define CS_TIMEOUT 90000
104
105 #define CS_PC_LINEMUTE XCTL0_ENABLE
106 #define CS_PC_HDPHMUTE XCTL1_ENABLE
107 #define CS_AFS_TI 0x40
108 #define CS_AFS_CI 0x20
109 #define CS_AFS_PI 0x10
110 #define CS_AFS_CU 0x08
111 #define CS_AFS_CO 0x04
112 #define CS_AFS_PO 0x02
113 #define CS_AFS_PU 0x01
114
115 #define CS_WRITE(sc,r,v) \
116 bus_space_write_1((sc)->sc_bustag, (sc)->sc_regs, (r) << 2, (v))
117 #define CS_READ(sc,r) \
118 bus_space_read_1((sc)->sc_bustag, (sc)->sc_regs, (r) << 2)
119
120 #define APC_WRITE(sc,r,v) \
121 bus_space_write_4(sc->sc_bustag, sc->sc_regs, r, v)
122 #define APC_READ(sc,r) \
123 bus_space_read_4(sc->sc_bustag, sc->sc_regs, r)
124
125 int cs4231_match(struct device *, void *, void *);
126 void cs4231_attach(struct device *, struct device *, void *);
127 int cs4231_intr(void *);
128
129 int cs4231_set_speed(struct cs4231_softc *, u_long *);
130 void cs4231_setup_output(struct cs4231_softc *sc);
131
132 void cs4231_write(struct cs4231_softc *, u_int8_t, u_int8_t);
133 u_int8_t cs4231_read(struct cs4231_softc *, u_int8_t);
134
135
136 int cs4231_open(void *, int);
137 void cs4231_close(void *);
138 int cs4231_query_encoding(void *, struct audio_encoding *);
139 int cs4231_set_params(void *, int, int, struct audio_params *,
140 struct audio_params *);
141 int cs4231_round_blocksize(void *, int);
142 int cs4231_commit_settings(void *);
143 int cs4231_halt_output(void *);
144 int cs4231_halt_input(void *);
145 int cs4231_getdev(void *, struct audio_device *);
146 int cs4231_set_port(void *, mixer_ctrl_t *);
147 int cs4231_get_port(void *, mixer_ctrl_t *);
148 int cs4231_query_devinfo(void *, mixer_devinfo_t *);
149 void * cs4231_alloc(void *, int, size_t, int, int);
150 void cs4231_free(void *, void *, int);
151 int cs4231_get_props(void *);
152 int cs4231_trigger_output(void *, void *, void *, int,
153 void (*)(void *), void *, struct audio_params *);
154 int cs4231_trigger_input(void *, void *, void *, int,
155 void (*)(void *), void *, struct audio_params *);
156
157 struct audio_hw_if cs4231_sa_hw_if = {
158 cs4231_open,
159 cs4231_close,
160 0,
161 cs4231_query_encoding,
162 cs4231_set_params,
163 cs4231_round_blocksize,
164 cs4231_commit_settings,
165 0,
166 0,
167 0,
168 0,
169 cs4231_halt_output,
170 cs4231_halt_input,
171 0,
172 cs4231_getdev,
173 0,
174 cs4231_set_port,
175 cs4231_get_port,
176 cs4231_query_devinfo,
177 cs4231_alloc,
178 cs4231_free,
179 0,
180 0,
181 cs4231_get_props,
182 cs4231_trigger_output,
183 cs4231_trigger_input
184 };
185
186 struct cfattach audiocs_ca = {
187 sizeof (struct cs4231_softc), cs4231_match, cs4231_attach
188 };
189
190 struct cfdriver audiocs_cd = {
191 NULL, "audiocs", DV_DULL
192 };
193
194 struct audio_device cs4231_device = {
195 "SUNW,CS4231",
196 "b",
197 "onboard1",
198 };
199
200 int
201 cs4231_match(struct device *parent, void *vcf, void *aux)
202 {
203 struct sbus_attach_args *sa = aux;
204
205 return (strcmp("SUNW,CS4231", sa->sa_name) == 0);
206 }
207
208 void
209 cs4231_attach(struct device *parent, struct device *self, void *aux)
210 {
211 struct sbus_attach_args *sa = aux;
212 struct cs4231_softc *sc = (struct cs4231_softc *)self;
213 int node;
214 u_int32_t sbusburst, burst;
215
216 node = sa->sa_node;
217
218
219 sc->sc_bustag = sa->sa_bustag;
220 sc->sc_dmatag = sa->sa_dmatag;
221
222
223 if (sa->sa_nintr != 1) {
224 printf(": expected 1 interrupt, got %d\n", sa->sa_nintr);
225 return;
226 }
227 if (sa->sa_nreg != 1) {
228 printf(": expected 1 register set, got %d\n",
229 sa->sa_nreg);
230 return;
231 }
232
233 if (bus_intr_establish(sa->sa_bustag, sa->sa_pri, IPL_AUDIO, 0,
234 cs4231_intr, sc, self->dv_xname) == NULL) {
235 printf(": couldn't establish interrupt, pri %d\n",
236 INTLEV(sa->sa_pri));
237 return;
238 }
239
240 if (sbus_bus_map(sa->sa_bustag,
241 sa->sa_reg[0].sbr_slot,
242 (bus_addr_t)sa->sa_reg[0].sbr_offset,
243 (bus_size_t)sa->sa_reg[0].sbr_size,
244 BUS_SPACE_MAP_LINEAR, 0, &sc->sc_regs) != 0) {
245 printf(": couldn't map registers\n");
246 return;
247 }
248
249 sbusburst = ((struct sbus_softc *)parent)->sc_burst;
250 if (sbusburst == 0)
251 sbusburst = SBUS_BURST_32 - 1;
252 burst = getpropint(node, "burst-sizes", -1);
253 if (burst == -1)
254 burst = sbusburst;
255 sc->sc_burst = burst & sbusburst;
256
257 printf("\n");
258
259 audio_attach_mi(&cs4231_sa_hw_if, sc, &sc->sc_dev);
260
261
262 sc->sc_out_port = CSPORT_SPEAKER;
263 sc->sc_in_port = CSPORT_MICROPHONE;
264 sc->sc_mute[CSPORT_SPEAKER] = 1;
265 sc->sc_mute[CSPORT_MONITOR] = 1;
266 sc->sc_volume[CSPORT_SPEAKER].left = 192;
267 sc->sc_volume[CSPORT_SPEAKER].right = 192;
268 }
269
270
271
272
273 void
274 cs4231_write(struct cs4231_softc *sc, u_int8_t r, u_int8_t v)
275 {
276 CS_WRITE(sc, AD1848_IADDR, r);
277 CS_WRITE(sc, AD1848_IDATA, v);
278 }
279
280
281
282
283 u_int8_t
284 cs4231_read(struct cs4231_softc *sc, u_int8_t r)
285 {
286 CS_WRITE(sc, AD1848_IADDR, r);
287 return (CS_READ(sc, AD1848_IDATA));
288 }
289
290 int
291 cs4231_set_speed(struct cs4231_softc *sc, u_long *argp)
292 {
293
294
295
296
297 typedef struct {
298 int speed;
299 u_char bits;
300 } speed_struct;
301 u_long arg = *argp;
302
303 const static speed_struct speed_table[] = {
304 {5510, (0 << 1) | CLOCK_XTAL2},
305 {5510, (0 << 1) | CLOCK_XTAL2},
306 {6620, (7 << 1) | CLOCK_XTAL2},
307 {8000, (0 << 1) | CLOCK_XTAL1},
308 {9600, (7 << 1) | CLOCK_XTAL1},
309 {11025, (1 << 1) | CLOCK_XTAL2},
310 {16000, (1 << 1) | CLOCK_XTAL1},
311 {18900, (2 << 1) | CLOCK_XTAL2},
312 {22050, (3 << 1) | CLOCK_XTAL2},
313 {27420, (2 << 1) | CLOCK_XTAL1},
314 {32000, (3 << 1) | CLOCK_XTAL1},
315 {33075, (6 << 1) | CLOCK_XTAL2},
316 {33075, (4 << 1) | CLOCK_XTAL2},
317 {44100, (5 << 1) | CLOCK_XTAL2},
318 {48000, (6 << 1) | CLOCK_XTAL1},
319 };
320
321 int i, n, selected = -1;
322
323 n = sizeof(speed_table) / sizeof(speed_struct);
324
325 if (arg < speed_table[0].speed)
326 selected = 0;
327 if (arg > speed_table[n - 1].speed)
328 selected = n - 1;
329
330 for (i = 1; selected == -1 && i < n; i++) {
331 if (speed_table[i].speed == arg)
332 selected = i;
333 else if (speed_table[i].speed > arg) {
334 int diff1, diff2;
335
336 diff1 = arg - speed_table[i - 1].speed;
337 diff2 = speed_table[i].speed - arg;
338 if (diff1 < diff2)
339 selected = i - 1;
340 else
341 selected = i;
342 }
343 }
344
345 if (selected == -1)
346 selected = 3;
347
348 sc->sc_speed_bits = speed_table[selected].bits;
349 sc->sc_need_commit = 1;
350 *argp = speed_table[selected].speed;
351
352 return (0);
353 }
354
355
356
357
358 int
359 cs4231_open(void *vsc, int flags)
360 {
361 struct cs4231_softc *sc = vsc;
362 int tries;
363
364 if (sc->sc_open)
365 return (EBUSY);
366 sc->sc_open = 1;
367
368 sc->sc_capture.cs_intr = NULL;
369 sc->sc_capture.cs_arg = NULL;
370 sc->sc_capture.cs_locked = 0;
371
372 sc->sc_playback.cs_intr = NULL;
373 sc->sc_playback.cs_arg = NULL;
374 sc->sc_playback.cs_locked = 0;
375
376 APC_WRITE(sc, APC_CSR, APC_CSR_RESET);
377 DELAY(10);
378 APC_WRITE(sc, APC_CSR, 0);
379 DELAY(10);
380 APC_WRITE(sc, APC_CSR, APC_READ(sc, APC_CSR) | APC_CSR_CODEC_RESET);
381
382 DELAY(20);
383
384 APC_WRITE(sc, APC_CSR, APC_READ(sc, APC_CSR) & (~APC_CSR_CODEC_RESET));
385
386 for (tries = CS_TIMEOUT;
387 tries && CS_READ(sc, AD1848_IADDR) == SP_IN_INIT; tries--)
388 DELAY(10);
389 if (tries == 0)
390 printf("%s: timeout waiting for reset\n", sc->sc_dev.dv_xname);
391
392
393 cs4231_write(sc, SP_MISC_INFO,
394 cs4231_read(sc, SP_MISC_INFO) | MODE2);
395
396 cs4231_setup_output(sc);
397
398 cs4231_write(sc, SP_PIN_CONTROL,
399 cs4231_read(sc, SP_PIN_CONTROL) | INTERRUPT_ENABLE);
400
401 return (0);
402 }
403
404 void
405 cs4231_setup_output(struct cs4231_softc *sc)
406 {
407 u_int8_t pc, mi, rm, lm;
408
409 pc = cs4231_read(sc, SP_PIN_CONTROL) | CS_PC_HDPHMUTE | CS_PC_LINEMUTE;
410
411 mi = cs4231_read(sc, CS_MONO_IO_CONTROL) | MONO_OUTPUT_MUTE;
412
413 lm = cs4231_read(sc, SP_LEFT_OUTPUT_CONTROL);
414 lm &= ~OUTPUT_ATTEN_BITS;
415 lm |= ((~(sc->sc_volume[CSPORT_SPEAKER].left >> 2)) &
416 OUTPUT_ATTEN_BITS) | OUTPUT_MUTE;
417
418 rm = cs4231_read(sc, SP_RIGHT_OUTPUT_CONTROL);
419 rm &= ~OUTPUT_ATTEN_BITS;
420 rm |= ((~(sc->sc_volume[CSPORT_SPEAKER].right >> 2)) &
421 OUTPUT_ATTEN_BITS) | OUTPUT_MUTE;
422
423 if (sc->sc_mute[CSPORT_MONITOR]) {
424 lm &= ~OUTPUT_MUTE;
425 rm &= ~OUTPUT_MUTE;
426 }
427
428 switch (sc->sc_out_port) {
429 case CSPORT_HEADPHONE:
430 if (sc->sc_mute[CSPORT_SPEAKER])
431 pc &= ~CS_PC_HDPHMUTE;
432 break;
433 case CSPORT_SPEAKER:
434 if (sc->sc_mute[CSPORT_SPEAKER])
435 mi &= ~MONO_OUTPUT_MUTE;
436 break;
437 case CSPORT_LINEOUT:
438 if (sc->sc_mute[CSPORT_SPEAKER])
439 pc &= ~CS_PC_LINEMUTE;
440 break;
441 }
442
443 cs4231_write(sc, SP_LEFT_OUTPUT_CONTROL, lm);
444 cs4231_write(sc, SP_RIGHT_OUTPUT_CONTROL, rm);
445 cs4231_write(sc, SP_PIN_CONTROL, pc);
446 cs4231_write(sc, CS_MONO_IO_CONTROL, mi);
447
448
449 switch (sc->sc_in_port) {
450 case CSPORT_LINEIN:
451 pc = LINE_INPUT;
452 break;
453 case CSPORT_AUX1:
454 pc = AUX_INPUT;
455 break;
456 case CSPORT_DAC:
457 pc = MIXED_DAC_INPUT;
458 break;
459 case CSPORT_MICROPHONE:
460 default:
461 pc = MIC_INPUT;
462 break;
463 }
464 lm = cs4231_read(sc, SP_LEFT_INPUT_CONTROL);
465 rm = cs4231_read(sc, SP_RIGHT_INPUT_CONTROL);
466 lm &= ~(MIXED_DAC_INPUT | ATTEN_22_5);
467 rm &= ~(MIXED_DAC_INPUT | ATTEN_22_5);
468 lm |= pc | (sc->sc_adc.left >> 4);
469 rm |= pc | (sc->sc_adc.right >> 4);
470 cs4231_write(sc, SP_LEFT_INPUT_CONTROL, lm);
471 cs4231_write(sc, SP_RIGHT_INPUT_CONTROL, rm);
472 }
473
474 void
475 cs4231_close(void *vsc)
476 {
477 struct cs4231_softc *sc = vsc;
478
479 cs4231_halt_input(sc);
480 cs4231_halt_output(sc);
481 cs4231_write(sc, SP_PIN_CONTROL,
482 cs4231_read(sc, SP_PIN_CONTROL) & (~INTERRUPT_ENABLE));
483 sc->sc_open = 0;
484 }
485
486 int
487 cs4231_query_encoding(void *vsc, struct audio_encoding *fp)
488 {
489 int err = 0;
490
491 switch (fp->index) {
492 case 0:
493 strlcpy(fp->name, AudioEmulaw, sizeof fp->name);
494 fp->encoding = AUDIO_ENCODING_ULAW;
495 fp->precision = 8;
496 fp->flags = 0;
497 break;
498 case 1:
499 strlcpy(fp->name, AudioEalaw, sizeof fp->name);
500 fp->encoding = AUDIO_ENCODING_ALAW;
501 fp->precision = 8;
502 fp->flags = 0;
503 break;
504 case 2:
505 strlcpy(fp->name, AudioEslinear_le, sizeof fp->name);
506 fp->encoding = AUDIO_ENCODING_SLINEAR_LE;
507 fp->precision = 16;
508 fp->flags = 0;
509 break;
510 case 3:
511 strlcpy(fp->name, AudioEulinear, sizeof fp->name);
512 fp->encoding = AUDIO_ENCODING_ULINEAR;
513 fp->precision = 8;
514 fp->flags = 0;
515 break;
516 case 4:
517 strlcpy(fp->name, AudioEslinear_be, sizeof fp->name);
518 fp->encoding = AUDIO_ENCODING_SLINEAR_BE;
519 fp->precision = 16;
520 fp->flags = 0;
521 break;
522 case 5:
523 strlcpy(fp->name, AudioEslinear, sizeof fp->name);
524 fp->encoding = AUDIO_ENCODING_SLINEAR;
525 fp->precision = 8;
526 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
527 break;
528 case 6:
529 strlcpy(fp->name, AudioEulinear_le, sizeof fp->name);
530 fp->encoding = AUDIO_ENCODING_ULINEAR_LE;
531 fp->precision = 16;
532 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
533 break;
534 case 7:
535 strlcpy(fp->name, AudioEulinear_be, sizeof fp->name);
536 fp->encoding = AUDIO_ENCODING_ULINEAR_BE;
537 fp->precision = 16;
538 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
539 break;
540 case 8:
541 strlcpy(fp->name, AudioEadpcm, sizeof fp->name);
542 fp->encoding = AUDIO_ENCODING_ADPCM;
543 fp->precision = 8;
544 fp->flags = 0;
545 break;
546 default:
547 err = EINVAL;
548 }
549 return (err);
550 }
551
552 int
553 cs4231_set_params(void *vsc, int setmode, int usemode,
554 struct audio_params *p, struct audio_params *r)
555 {
556 struct cs4231_softc *sc = (struct cs4231_softc *)vsc;
557 int err, bits, enc = p->encoding;
558 void (*pswcode)(void *, u_char *, int cnt) = NULL;
559 void (*rswcode)(void *, u_char *, int cnt) = NULL;
560
561 switch (enc) {
562 case AUDIO_ENCODING_ULAW:
563 if (p->precision != 8)
564 return (EINVAL);
565 bits = FMT_ULAW >> 5;
566 break;
567 case AUDIO_ENCODING_ALAW:
568 if (p->precision != 8)
569 return (EINVAL);
570 bits = FMT_ALAW >> 5;
571 break;
572 case AUDIO_ENCODING_SLINEAR_LE:
573 if (p->precision == 8) {
574 bits = FMT_PCM8 >> 5;
575 pswcode = rswcode = change_sign8;
576 } else if (p->precision == 16)
577 bits = FMT_TWOS_COMP >> 5;
578 else
579 return (EINVAL);
580 break;
581 case AUDIO_ENCODING_ULINEAR:
582 if (p->precision != 8)
583 return (EINVAL);
584 bits = FMT_PCM8 >> 5;
585 break;
586 case AUDIO_ENCODING_SLINEAR_BE:
587 if (p->precision == 8) {
588 bits = FMT_PCM8 >> 5;
589 pswcode = rswcode = change_sign8;
590 } else if (p->precision == 16)
591 bits = FMT_TWOS_COMP_BE >> 5;
592 else
593 return (EINVAL);
594 break;
595 case AUDIO_ENCODING_SLINEAR:
596 if (p->precision != 8)
597 return (EINVAL);
598 bits = FMT_PCM8 >> 5;
599 pswcode = rswcode = change_sign8;
600 break;
601 case AUDIO_ENCODING_ULINEAR_LE:
602 if (p->precision == 8)
603 bits = FMT_PCM8 >> 5;
604 else if (p->precision == 16) {
605 bits = FMT_TWOS_COMP >> 5;
606 pswcode = rswcode = change_sign16_le;
607 } else
608 return (EINVAL);
609 break;
610 case AUDIO_ENCODING_ULINEAR_BE:
611 if (p->precision == 8)
612 bits = FMT_PCM8 >> 5;
613 else if (p->precision == 16) {
614 bits = FMT_TWOS_COMP_BE >> 5;
615 pswcode = rswcode = change_sign16_be;
616 } else
617 return (EINVAL);
618 break;
619 case AUDIO_ENCODING_ADPCM:
620 if (p->precision != 8)
621 return (EINVAL);
622 bits = FMT_ADPCM >> 5;
623 break;
624 default:
625 return (EINVAL);
626 }
627
628 if (p->channels != 1 && p->channels != 2)
629 return (EINVAL);
630
631 err = cs4231_set_speed(sc, &p->sample_rate);
632 if (err)
633 return (err);
634
635 p->sw_code = pswcode;
636 r->sw_code = rswcode;
637
638 sc->sc_format_bits = bits;
639 sc->sc_channels = p->channels;
640 sc->sc_precision = p->precision;
641 sc->sc_need_commit = 1;
642 return (0);
643 }
644
645 int
646 cs4231_round_blocksize(void *vsc, int blk)
647 {
648 return ((blk + 3) & (-4));
649 }
650
651 int
652 cs4231_commit_settings(void *vsc)
653 {
654 struct cs4231_softc *sc = (struct cs4231_softc *)vsc;
655 int s, tries;
656 u_int8_t r, fs;
657
658 if (sc->sc_need_commit == 0)
659 return (0);
660
661 fs = sc->sc_speed_bits | (sc->sc_format_bits << 5);
662 if (sc->sc_channels == 2)
663 fs |= FMT_STEREO;
664
665 s = splaudio();
666
667 r = cs4231_read(sc, SP_INTERFACE_CONFIG) | AUTO_CAL_ENABLE;
668 CS_WRITE(sc, AD1848_IADDR, MODE_CHANGE_ENABLE);
669 CS_WRITE(sc, AD1848_IADDR, MODE_CHANGE_ENABLE | SP_INTERFACE_CONFIG);
670 CS_WRITE(sc, AD1848_IDATA, r);
671
672 CS_WRITE(sc, AD1848_IADDR, MODE_CHANGE_ENABLE | SP_CLOCK_DATA_FORMAT);
673 CS_WRITE(sc, AD1848_IDATA, fs);
674 CS_READ(sc, AD1848_IDATA);
675 CS_READ(sc, AD1848_IDATA);
676 tries = CS_TIMEOUT;
677 for (tries = CS_TIMEOUT;
678 tries && CS_READ(sc, AD1848_IADDR) == SP_IN_INIT; tries--)
679 DELAY(10);
680 if (tries == 0)
681 printf("%s: timeout committing fspb\n", sc->sc_dev.dv_xname);
682
683 CS_WRITE(sc, AD1848_IADDR, MODE_CHANGE_ENABLE | CS_REC_FORMAT);
684 CS_WRITE(sc, AD1848_IDATA, fs);
685 CS_READ(sc, AD1848_IDATA);
686 CS_READ(sc, AD1848_IDATA);
687 for (tries = CS_TIMEOUT;
688 tries && CS_READ(sc, AD1848_IADDR) == SP_IN_INIT; tries--)
689 DELAY(10);
690 if (tries == 0)
691 printf("%s: timeout committing cdf\n", sc->sc_dev.dv_xname);
692
693 CS_WRITE(sc, AD1848_IADDR, 0);
694 for (tries = CS_TIMEOUT;
695 tries && CS_READ(sc, AD1848_IADDR) == SP_IN_INIT; tries--)
696 DELAY(10);
697 if (tries == 0)
698 printf("%s: timeout waiting for !mce\n", sc->sc_dev.dv_xname);
699
700 CS_WRITE(sc, AD1848_IADDR, SP_TEST_AND_INIT);
701 for (tries = CS_TIMEOUT;
702 tries && CS_READ(sc, AD1848_IDATA) & AUTO_CAL_IN_PROG; tries--)
703 DELAY(10);
704 if (tries == 0)
705 printf("%s: timeout waiting for autocalibration\n",
706 sc->sc_dev.dv_xname);
707
708 splx(s);
709
710 sc->sc_need_commit = 0;
711 return (0);
712 }
713
714 int
715 cs4231_halt_output(void *vsc)
716 {
717 struct cs4231_softc *sc = (struct cs4231_softc *)vsc;
718
719
720 APC_WRITE(sc, APC_CSR, APC_READ(sc, APC_CSR) &
721 ~(APC_CSR_EI | APC_CSR_GIE | APC_CSR_PIE |
722 APC_CSR_EIE | APC_CSR_PDMA_GO | APC_CSR_PMIE));
723 cs4231_write(sc, SP_INTERFACE_CONFIG,
724 cs4231_read(sc, SP_INTERFACE_CONFIG) & (~PLAYBACK_ENABLE));
725 sc->sc_playback.cs_locked = 0;
726 return (0);
727 }
728
729 int
730 cs4231_halt_input(void *vsc)
731 {
732 struct cs4231_softc *sc = (struct cs4231_softc *)vsc;
733
734
735 APC_WRITE(sc, APC_CSR, APC_CSR_CAPTURE_PAUSE);
736 cs4231_write(sc, SP_INTERFACE_CONFIG,
737 cs4231_read(sc, SP_INTERFACE_CONFIG) & (~CAPTURE_ENABLE));
738 sc->sc_capture.cs_locked = 0;
739 return (0);
740 }
741
742 int
743 cs4231_getdev(void *vsc, struct audio_device *retp)
744 {
745 *retp = cs4231_device;
746 return (0);
747 }
748
749 int
750 cs4231_set_port(void *vsc, mixer_ctrl_t *cp)
751 {
752 struct cs4231_softc *sc = (struct cs4231_softc *)vsc;
753 int error = EINVAL;
754
755 DPRINTF(("cs4231_set_port: port=%d type=%d\n", cp->dev, cp->type));
756
757 switch (cp->dev) {
758 case CSAUDIO_DAC_LVL:
759 if (cp->type != AUDIO_MIXER_VALUE)
760 break;
761 if (cp->un.value.num_channels == 1)
762 cs4231_write(sc, SP_LEFT_AUX1_CONTROL,
763 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] &
764 LINE_INPUT_ATTEN_BITS);
765 else if (cp->un.value.num_channels == 2) {
766 cs4231_write(sc, SP_LEFT_AUX1_CONTROL,
767 cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] &
768 LINE_INPUT_ATTEN_BITS);
769 cs4231_write(sc, SP_RIGHT_AUX1_CONTROL,
770 cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] &
771 LINE_INPUT_ATTEN_BITS);
772 } else
773 break;
774 error = 0;
775 break;
776 case CSAUDIO_LINE_IN_LVL:
777 if (cp->type != AUDIO_MIXER_VALUE)
778 break;
779 if (cp->un.value.num_channels == 1)
780 cs4231_write(sc, CS_LEFT_LINE_CONTROL,
781 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] &
782 AUX_INPUT_ATTEN_BITS);
783 else if (cp->un.value.num_channels == 2) {
784 cs4231_write(sc, CS_LEFT_LINE_CONTROL,
785 cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] &
786 AUX_INPUT_ATTEN_BITS);
787 cs4231_write(sc, CS_RIGHT_LINE_CONTROL,
788 cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] &
789 AUX_INPUT_ATTEN_BITS);
790 } else
791 break;
792 error = 0;
793 break;
794 case CSAUDIO_MIC_LVL:
795 if (cp->type != AUDIO_MIXER_VALUE)
796 break;
797 if (cp->un.value.num_channels == 1) {
798 #if 0
799 cs4231_write(sc, CS_MONO_IO_CONTROL,
800 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] &
801 MONO_INPUT_ATTEN_BITS);
802 #endif
803 } else
804 break;
805 error = 0;
806 break;
807 case CSAUDIO_CD_LVL:
808 if (cp->type != AUDIO_MIXER_VALUE)
809 break;
810 if (cp->un.value.num_channels == 1) {
811 cs4231_write(sc, SP_LEFT_AUX2_CONTROL,
812 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] &
813 LINE_INPUT_ATTEN_BITS);
814 } else if (cp->un.value.num_channels == 2) {
815 cs4231_write(sc, SP_LEFT_AUX2_CONTROL,
816 cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] &
817 LINE_INPUT_ATTEN_BITS);
818 cs4231_write(sc, SP_RIGHT_AUX2_CONTROL,
819 cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] &
820 LINE_INPUT_ATTEN_BITS);
821 } else
822 break;
823 error = 0;
824 break;
825 case CSAUDIO_MONITOR_LVL:
826 if (cp->type != AUDIO_MIXER_VALUE)
827 break;
828 if (cp->un.value.num_channels == 1)
829 cs4231_write(sc, SP_DIGITAL_MIX,
830 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] << 2);
831 else
832 break;
833 error = 0;
834 break;
835 case CSAUDIO_OUTPUT_LVL:
836 if (cp->type != AUDIO_MIXER_VALUE)
837 break;
838 if (cp->un.value.num_channels == 1) {
839 sc->sc_volume[CSPORT_SPEAKER].left =
840 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO];
841 sc->sc_volume[CSPORT_SPEAKER].right =
842 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO];
843 }
844 else if (cp->un.value.num_channels == 2) {
845 sc->sc_volume[CSPORT_SPEAKER].left =
846 cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT];
847 sc->sc_volume[CSPORT_SPEAKER].right =
848 cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
849 }
850 else
851 break;
852
853 cs4231_setup_output(sc);
854 error = 0;
855 break;
856 case CSAUDIO_OUTPUT:
857 if (cp->type != AUDIO_MIXER_ENUM)
858 break;
859 if (cp->un.ord != CSPORT_LINEOUT &&
860 cp->un.ord != CSPORT_SPEAKER &&
861 cp->un.ord != CSPORT_HEADPHONE)
862 return (EINVAL);
863 sc->sc_out_port = cp->un.ord;
864 cs4231_setup_output(sc);
865 error = 0;
866 break;
867 case CSAUDIO_LINE_IN_MUTE:
868 if (cp->type != AUDIO_MIXER_ENUM)
869 break;
870 sc->sc_mute[CSPORT_LINEIN] = cp->un.ord ? 1 : 0;
871 error = 0;
872 break;
873 case CSAUDIO_DAC_MUTE:
874 if (cp->type != AUDIO_MIXER_ENUM)
875 break;
876 sc->sc_mute[CSPORT_AUX1] = cp->un.ord ? 1 : 0;
877 error = 0;
878 break;
879 case CSAUDIO_CD_MUTE:
880 if (cp->type != AUDIO_MIXER_ENUM)
881 break;
882 sc->sc_mute[CSPORT_AUX2] = cp->un.ord ? 1 : 0;
883 error = 0;
884 break;
885 case CSAUDIO_MIC_MUTE:
886 if (cp->type != AUDIO_MIXER_ENUM)
887 break;
888 sc->sc_mute[CSPORT_MONO] = cp->un.ord ? 1 : 0;
889 error = 0;
890 break;
891 case CSAUDIO_MONITOR_MUTE:
892 if (cp->type != AUDIO_MIXER_ENUM)
893 break;
894 sc->sc_mute[CSPORT_MONITOR] = cp->un.ord ? 1 : 0;
895 error = 0;
896 break;
897 case CSAUDIO_OUTPUT_MUTE:
898 if (cp->type != AUDIO_MIXER_ENUM)
899 break;
900 sc->sc_mute[CSPORT_SPEAKER] = cp->un.ord ? 1 : 0;
901 cs4231_setup_output(sc);
902 error = 0;
903 break;
904 case CSAUDIO_REC_LVL:
905 if (cp->type != AUDIO_MIXER_VALUE)
906 break;
907 if (cp->un.value.num_channels == 1) {
908 sc->sc_adc.left =
909 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO];
910 sc->sc_adc.right =
911 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO];
912 } else if (cp->un.value.num_channels == 2) {
913 sc->sc_adc.left =
914 cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT];
915 sc->sc_adc.right =
916 cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
917 } else
918 break;
919 cs4231_setup_output(sc);
920 error = 0;
921 break;
922 case CSAUDIO_RECORD_SOURCE:
923 if (cp->type != AUDIO_MIXER_ENUM)
924 break;
925 if (cp->un.ord == CSPORT_MICROPHONE ||
926 cp->un.ord == CSPORT_LINEIN ||
927 cp->un.ord == CSPORT_AUX1 ||
928 cp->un.ord == CSPORT_DAC) {
929 sc->sc_in_port = cp->un.ord;
930 error = 0;
931 cs4231_setup_output(sc);
932 }
933 break;
934 }
935
936 return (error);
937 }
938
939 int
940 cs4231_get_port(void *vsc, mixer_ctrl_t *cp)
941 {
942 struct cs4231_softc *sc = (struct cs4231_softc *)vsc;
943 int error = EINVAL;
944
945 DPRINTF(("cs4231_get_port: port=%d type=%d\n", cp->dev, cp->type));
946
947 switch (cp->dev) {
948 case CSAUDIO_DAC_LVL:
949 if (cp->type != AUDIO_MIXER_VALUE)
950 break;
951 if (cp->un.value.num_channels == 1)
952 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]=
953 cs4231_read(sc, SP_LEFT_AUX1_CONTROL) &
954 LINE_INPUT_ATTEN_BITS;
955 else if (cp->un.value.num_channels == 2) {
956 cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] =
957 cs4231_read(sc, SP_LEFT_AUX1_CONTROL) &
958 LINE_INPUT_ATTEN_BITS;
959 cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] =
960 cs4231_read(sc, SP_RIGHT_AUX1_CONTROL) &
961 LINE_INPUT_ATTEN_BITS;
962 } else
963 break;
964 error = 0;
965 break;
966 case CSAUDIO_LINE_IN_LVL:
967 if (cp->type != AUDIO_MIXER_VALUE)
968 break;
969 if (cp->un.value.num_channels == 1)
970 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
971 cs4231_read(sc, CS_LEFT_LINE_CONTROL) & AUX_INPUT_ATTEN_BITS;
972 else if (cp->un.value.num_channels == 2) {
973 cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] =
974 cs4231_read(sc, CS_LEFT_LINE_CONTROL) & AUX_INPUT_ATTEN_BITS;
975 cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] =
976 cs4231_read(sc, CS_RIGHT_LINE_CONTROL) & AUX_INPUT_ATTEN_BITS;
977 } else
978 break;
979 error = 0;
980 break;
981 case CSAUDIO_MIC_LVL:
982 if (cp->type != AUDIO_MIXER_VALUE)
983 break;
984 if (cp->un.value.num_channels == 1) {
985 #if 0
986 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
987 cs4231_read(sc, CS_MONO_IO_CONTROL) &
988 MONO_INPUT_ATTEN_BITS;
989 #endif
990 } else
991 break;
992 error = 0;
993 break;
994 case CSAUDIO_CD_LVL:
995 if (cp->type != AUDIO_MIXER_VALUE)
996 break;
997 if (cp->un.value.num_channels == 1)
998 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
999 cs4231_read(sc, SP_LEFT_AUX2_CONTROL) &
1000 LINE_INPUT_ATTEN_BITS;
1001 else if (cp->un.value.num_channels == 2) {
1002 cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] =
1003 cs4231_read(sc, SP_LEFT_AUX2_CONTROL) &
1004 LINE_INPUT_ATTEN_BITS;
1005 cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] =
1006 cs4231_read(sc, SP_RIGHT_AUX2_CONTROL) &
1007 LINE_INPUT_ATTEN_BITS;
1008 }
1009 else
1010 break;
1011 error = 0;
1012 break;
1013 case CSAUDIO_MONITOR_LVL:
1014 if (cp->type != AUDIO_MIXER_VALUE)
1015 break;
1016 if (cp->un.value.num_channels != 1)
1017 break;
1018 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
1019 cs4231_read(sc, SP_DIGITAL_MIX) >> 2;
1020 error = 0;
1021 break;
1022 case CSAUDIO_OUTPUT_LVL:
1023 if (cp->type != AUDIO_MIXER_VALUE)
1024 break;
1025 if (cp->un.value.num_channels == 1)
1026 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
1027 sc->sc_volume[CSPORT_SPEAKER].left;
1028 else if (cp->un.value.num_channels == 2) {
1029 cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] =
1030 sc->sc_volume[CSPORT_SPEAKER].left;
1031 cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] =
1032 sc->sc_volume[CSPORT_SPEAKER].right;
1033 }
1034 else
1035 break;
1036 error = 0;
1037 break;
1038 case CSAUDIO_LINE_IN_MUTE:
1039 if (cp->type != AUDIO_MIXER_ENUM)
1040 break;
1041 cp->un.ord = sc->sc_mute[CSPORT_LINEIN] ? 1 : 0;
1042 error = 0;
1043 break;
1044 case CSAUDIO_DAC_MUTE:
1045 if (cp->type != AUDIO_MIXER_ENUM)
1046 break;
1047 cp->un.ord = sc->sc_mute[CSPORT_AUX1] ? 1 : 0;
1048 error = 0;
1049 break;
1050 case CSAUDIO_CD_MUTE:
1051 if (cp->type != AUDIO_MIXER_ENUM)
1052 break;
1053 cp->un.ord = sc->sc_mute[CSPORT_AUX2] ? 1 : 0;
1054 error = 0;
1055 break;
1056 case CSAUDIO_MIC_MUTE:
1057 if (cp->type != AUDIO_MIXER_ENUM)
1058 break;
1059 cp->un.ord = sc->sc_mute[CSPORT_MONO] ? 1 : 0;
1060 error = 0;
1061 break;
1062 case CSAUDIO_MONITOR_MUTE:
1063 if (cp->type != AUDIO_MIXER_ENUM)
1064 break;
1065 cp->un.ord = sc->sc_mute[CSPORT_MONITOR] ? 1 : 0;
1066 error = 0;
1067 break;
1068 case CSAUDIO_OUTPUT_MUTE:
1069 if (cp->type != AUDIO_MIXER_ENUM)
1070 break;
1071 cp->un.ord = sc->sc_mute[CSPORT_SPEAKER] ? 1 : 0;
1072 error = 0;
1073 break;
1074 case CSAUDIO_REC_LVL:
1075 if (cp->type != AUDIO_MIXER_VALUE)
1076 break;
1077 if (cp->un.value.num_channels == 1) {
1078 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
1079 sc->sc_adc.left;
1080 } else if (cp->un.value.num_channels == 2) {
1081 cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] =
1082 sc->sc_adc.left;
1083 cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] =
1084 sc->sc_adc.right;
1085 } else
1086 break;
1087 error = 0;
1088 break;
1089 case CSAUDIO_RECORD_SOURCE:
1090 if (cp->type != AUDIO_MIXER_ENUM)
1091 break;
1092 cp->un.ord = sc->sc_in_port;
1093 error = 0;
1094 break;
1095 case CSAUDIO_OUTPUT:
1096 if (cp->type != AUDIO_MIXER_ENUM)
1097 break;
1098 cp->un.ord = sc->sc_out_port;
1099 error = 0;
1100 break;
1101 }
1102 return (error);
1103 }
1104
1105 int
1106 cs4231_query_devinfo(void *vsc, mixer_devinfo_t *dip)
1107 {
1108 int err = 0;
1109
1110 switch (dip->index) {
1111 case CSAUDIO_MIC_LVL:
1112 dip->type = AUDIO_MIXER_VALUE;
1113 dip->mixer_class = CSAUDIO_INPUT_CLASS;
1114 dip->prev = AUDIO_MIXER_LAST;
1115 dip->next = CSAUDIO_MIC_MUTE;
1116 strlcpy(dip->label.name, AudioNmicrophone,
1117 sizeof dip->label.name);
1118 dip->un.v.num_channels = 1;
1119 strlcpy(dip->un.v.units.name, AudioNvolume,
1120 sizeof dip->un.v.units.name);
1121 break;
1122 case CSAUDIO_DAC_LVL:
1123 dip->type = AUDIO_MIXER_VALUE;
1124 dip->mixer_class = CSAUDIO_INPUT_CLASS;
1125 dip->prev = AUDIO_MIXER_LAST;
1126 dip->next = CSAUDIO_DAC_MUTE;
1127 strlcpy(dip->label.name, AudioNdac,
1128 sizeof dip->label.name);
1129 dip->un.v.num_channels = 2;
1130 strlcpy(dip->un.v.units.name, AudioNvolume,
1131 sizeof dip->un.v.units.name);
1132 break;
1133 case CSAUDIO_LINE_IN_LVL:
1134 dip->type = AUDIO_MIXER_VALUE;
1135 dip->mixer_class = CSAUDIO_INPUT_CLASS;
1136 dip->prev = AUDIO_MIXER_LAST;
1137 dip->next = CSAUDIO_LINE_IN_MUTE;
1138 strlcpy(dip->label.name, AudioNline, sizeof dip->label.name);
1139 dip->un.v.num_channels = 2;
1140 strlcpy(dip->un.v.units.name, AudioNvolume,
1141 sizeof dip->un.v.units.name);
1142 break;
1143 case CSAUDIO_CD_LVL:
1144 dip->type = AUDIO_MIXER_VALUE;
1145 dip->mixer_class = CSAUDIO_INPUT_CLASS;
1146 dip->prev = AUDIO_MIXER_LAST;
1147 dip->next = CSAUDIO_CD_MUTE;
1148 strlcpy(dip->label.name, AudioNcd, sizeof dip->label.name);
1149 dip->un.v.num_channels = 2;
1150 strlcpy(dip->un.v.units.name, AudioNvolume,
1151 sizeof dip->un.v.units.name);
1152 break;
1153 case CSAUDIO_MONITOR_LVL:
1154 dip->type = AUDIO_MIXER_VALUE;
1155 dip->mixer_class = CSAUDIO_MONITOR_CLASS;
1156 dip->prev = AUDIO_MIXER_LAST;
1157 dip->next = CSAUDIO_MONITOR_MUTE;
1158 strlcpy(dip->label.name, AudioNmonitor,
1159 sizeof dip->label.name);
1160 dip->un.v.num_channels = 1;
1161 strlcpy(dip->un.v.units.name, AudioNvolume,
1162 sizeof dip->un.v.units.name);
1163 break;
1164 case CSAUDIO_OUTPUT_LVL:
1165 dip->type = AUDIO_MIXER_VALUE;
1166 dip->mixer_class = CSAUDIO_OUTPUT_CLASS;
1167 dip->prev = AUDIO_MIXER_LAST;
1168 dip->next = CSAUDIO_OUTPUT_MUTE;
1169 strlcpy(dip->label.name, AudioNoutput, sizeof dip->label.name);
1170 dip->un.v.num_channels = 2;
1171 strlcpy(dip->un.v.units.name, AudioNvolume,
1172 sizeof dip->un.v.units.name);
1173 break;
1174 case CSAUDIO_LINE_IN_MUTE:
1175 dip->type = AUDIO_MIXER_ENUM;
1176 dip->mixer_class = CSAUDIO_INPUT_CLASS;
1177 dip->prev = CSAUDIO_LINE_IN_LVL;
1178 dip->next = AUDIO_MIXER_LAST;
1179 goto mute;
1180 case CSAUDIO_DAC_MUTE:
1181 dip->type = AUDIO_MIXER_ENUM;
1182 dip->mixer_class = CSAUDIO_INPUT_CLASS;
1183 dip->prev = CSAUDIO_DAC_LVL;
1184 dip->next = AUDIO_MIXER_LAST;
1185 goto mute;
1186 case CSAUDIO_CD_MUTE:
1187 dip->type = AUDIO_MIXER_ENUM;
1188 dip->mixer_class = CSAUDIO_INPUT_CLASS;
1189 dip->prev = CSAUDIO_CD_LVL;
1190 dip->next = AUDIO_MIXER_LAST;
1191 goto mute;
1192 case CSAUDIO_MIC_MUTE:
1193 dip->type = AUDIO_MIXER_ENUM;
1194 dip->mixer_class = CSAUDIO_INPUT_CLASS;
1195 dip->prev = CSAUDIO_MIC_LVL;
1196 dip->next = AUDIO_MIXER_LAST;
1197 goto mute;
1198 case CSAUDIO_MONITOR_MUTE:
1199 dip->type = AUDIO_MIXER_ENUM;
1200 dip->mixer_class = CSAUDIO_OUTPUT_CLASS;
1201 dip->prev = CSAUDIO_MONITOR_LVL;
1202 dip->next = AUDIO_MIXER_LAST;
1203 goto mute;
1204 case CSAUDIO_OUTPUT_MUTE:
1205 dip->type = AUDIO_MIXER_ENUM;
1206 dip->mixer_class = CSAUDIO_OUTPUT_CLASS;
1207 dip->prev = CSAUDIO_OUTPUT_LVL;
1208 dip->next = AUDIO_MIXER_LAST;
1209 goto mute;
1210
1211 mute:
1212 strlcpy(dip->label.name, AudioNmute, sizeof dip->label.name);
1213 dip->un.e.num_mem = 2;
1214 strlcpy(dip->un.e.member[0].label.name, AudioNon,
1215 sizeof dip->un.e.member[0].label.name);
1216 dip->un.e.member[0].ord = 0;
1217 strlcpy(dip->un.e.member[1].label.name, AudioNoff,
1218 sizeof dip->un.e.member[1].label.name);
1219 dip->un.e.member[1].ord = 1;
1220 break;
1221 case CSAUDIO_REC_LVL:
1222 dip->type = AUDIO_MIXER_VALUE;
1223 dip->mixer_class = CSAUDIO_RECORD_CLASS;
1224 dip->prev = AUDIO_MIXER_LAST;
1225 dip->next = CSAUDIO_RECORD_SOURCE;
1226 strlcpy(dip->label.name, AudioNrecord, sizeof dip->label.name);
1227 dip->un.v.num_channels = 2;
1228 strlcpy(dip->un.v.units.name, AudioNvolume,
1229 sizeof dip->un.v.units.name);
1230 break;
1231 case CSAUDIO_RECORD_SOURCE:
1232 dip->type = AUDIO_MIXER_ENUM;
1233 dip->mixer_class = CSAUDIO_RECORD_CLASS;
1234 dip->prev = CSAUDIO_REC_LVL;
1235 dip->next = AUDIO_MIXER_LAST;
1236 strlcpy(dip->label.name, AudioNsource, sizeof dip->label.name);
1237 dip->un.e.num_mem = 4;
1238 strlcpy(dip->un.e.member[0].label.name, AudioNmicrophone,
1239 sizeof dip->un.e.member[0].label.name);
1240 dip->un.e.member[0].ord = CSPORT_MICROPHONE;
1241 strlcpy(dip->un.e.member[1].label.name, AudioNline,
1242 sizeof dip->un.e.member[1].label.name);
1243 dip->un.e.member[1].ord = CSPORT_LINEIN;
1244 strlcpy(dip->un.e.member[2].label.name, AudioNcd,
1245 sizeof dip->un.e.member[2].label.name);
1246 dip->un.e.member[2].ord = CSPORT_AUX1;
1247 strlcpy(dip->un.e.member[3].label.name, AudioNdac,
1248 sizeof dip->un.e.member[3].label.name);
1249 dip->un.e.member[3].ord = CSPORT_DAC;
1250 break;
1251 case CSAUDIO_OUTPUT:
1252 dip->type = AUDIO_MIXER_ENUM;
1253 dip->mixer_class = CSAUDIO_MONITOR_CLASS;
1254 dip->prev = dip->next = AUDIO_MIXER_LAST;
1255 strlcpy(dip->label.name, AudioNoutput, sizeof dip->label.name);
1256 dip->un.e.num_mem = 3;
1257 strlcpy(dip->un.e.member[0].label.name, AudioNspeaker,
1258 sizeof dip->un.e.member[0].label.name);
1259 dip->un.e.member[0].ord = CSPORT_SPEAKER;
1260 strlcpy(dip->un.e.member[1].label.name, AudioNline,
1261 sizeof dip->un.e.member[1].label.name);
1262 dip->un.e.member[1].ord = CSPORT_LINEOUT;
1263 strlcpy(dip->un.e.member[2].label.name, AudioNheadphone,
1264 sizeof dip->un.e.member[2].label.name);
1265 dip->un.e.member[2].ord = CSPORT_HEADPHONE;
1266 break;
1267 case CSAUDIO_INPUT_CLASS:
1268 dip->type = AUDIO_MIXER_CLASS;
1269 dip->mixer_class = CSAUDIO_INPUT_CLASS;
1270 dip->prev = AUDIO_MIXER_LAST;
1271 dip->next = AUDIO_MIXER_LAST;
1272 strlcpy(dip->label.name, AudioCinputs, sizeof dip->label.name);
1273 break;
1274 case CSAUDIO_OUTPUT_CLASS:
1275 dip->type = AUDIO_MIXER_CLASS;
1276 dip->mixer_class = CSAUDIO_OUTPUT_CLASS;
1277 dip->prev = AUDIO_MIXER_LAST;
1278 dip->next = AUDIO_MIXER_LAST;
1279 strlcpy(dip->label.name, AudioCoutputs,
1280 sizeof dip->label.name);
1281 break;
1282 case CSAUDIO_MONITOR_CLASS:
1283 dip->type = AUDIO_MIXER_CLASS;
1284 dip->mixer_class = CSAUDIO_MONITOR_CLASS;
1285 dip->prev = AUDIO_MIXER_LAST;
1286 dip->next = AUDIO_MIXER_LAST;
1287 strlcpy(dip->label.name, AudioCmonitor,
1288 sizeof dip->label.name);
1289 break;
1290 case CSAUDIO_RECORD_CLASS:
1291 dip->type = AUDIO_MIXER_CLASS;
1292 dip->mixer_class = CSAUDIO_RECORD_CLASS;
1293 dip->prev = AUDIO_MIXER_LAST;
1294 dip->next = AUDIO_MIXER_LAST;
1295 strlcpy(dip->label.name, AudioCrecord, sizeof dip->label.name);
1296 break;
1297 default:
1298 err = ENXIO;
1299 }
1300
1301 return (err);
1302 }
1303
1304 int
1305 cs4231_get_props(void *vsc)
1306 {
1307 return (AUDIO_PROP_FULLDUPLEX);
1308 }
1309
1310
1311
1312
1313 int
1314 cs4231_intr(void *vsc)
1315 {
1316 struct cs4231_softc *sc = (struct cs4231_softc *)vsc;
1317 u_int32_t csr;
1318 u_int8_t reg, status;
1319 struct cs_dma *p;
1320 int r = 0;
1321
1322 csr = APC_READ(sc, APC_CSR);
1323 APC_WRITE(sc, APC_CSR, csr);
1324
1325 if ((csr & APC_CSR_EIE) && (csr & APC_CSR_EI)) {
1326 printf("%s: error interrupt\n", sc->sc_dev.dv_xname);
1327 r = 1;
1328 }
1329
1330 if ((csr & APC_CSR_PIE) && (csr & APC_CSR_PI)) {
1331
1332 r = 1;
1333 }
1334
1335 if ((csr & APC_CSR_GIE) && (csr & APC_CSR_GI)) {
1336
1337 status = CS_READ(sc, AD1848_STATUS);
1338 if (status & (INTERRUPT_STATUS | SAMPLE_ERROR)) {
1339 reg = cs4231_read(sc, CS_IRQ_STATUS);
1340 if (reg & CS_AFS_PI) {
1341 cs4231_write(sc, SP_LOWER_BASE_COUNT, 0xff);
1342 cs4231_write(sc, SP_UPPER_BASE_COUNT, 0xff);
1343 }
1344 if (reg & CS_AFS_CI) {
1345 cs4231_write(sc, CS_LOWER_REC_CNT, 0xff);
1346 cs4231_write(sc, CS_UPPER_REC_CNT, 0xff);
1347 }
1348 CS_WRITE(sc, AD1848_STATUS, 0);
1349 }
1350 r = 1;
1351 }
1352
1353
1354 if (csr & (APC_CSR_PI|APC_CSR_PMI|APC_CSR_PIE|APC_CSR_PD))
1355 r = 1;
1356
1357 if ((csr & APC_CSR_PMIE) && (csr & APC_CSR_PMI)) {
1358 struct cs_channel *chan = &sc->sc_playback;
1359 u_long nextaddr, togo;
1360
1361 p = chan->cs_curdma;
1362 togo = chan->cs_segsz - chan->cs_cnt;
1363 if (togo == 0) {
1364 nextaddr = (u_int32_t)p->dmamap->dm_segs[0].ds_addr;
1365 chan->cs_cnt = togo = chan->cs_blksz;
1366 } else {
1367 nextaddr = APC_READ(sc, APC_PNVA) + chan->cs_blksz;
1368 if (togo > chan->cs_blksz)
1369 togo = chan->cs_blksz;
1370 chan->cs_cnt += togo;
1371 }
1372
1373 APC_WRITE(sc, APC_PNVA, nextaddr);
1374 APC_WRITE(sc, APC_PNC, togo);
1375
1376 if (chan->cs_intr != NULL)
1377 (*chan->cs_intr)(chan->cs_arg);
1378 r = 1;
1379 }
1380
1381 if ((csr & APC_CSR_CIE) && (csr & APC_CSR_CI)) {
1382 if (csr & APC_CSR_CD) {
1383 struct cs_channel *chan = &sc->sc_capture;
1384 u_long nextaddr, togo;
1385
1386 p = chan->cs_curdma;
1387 togo = chan->cs_segsz - chan->cs_cnt;
1388 if (togo == 0) {
1389 nextaddr =
1390 (u_int32_t)p->dmamap->dm_segs[0].ds_addr;
1391 chan->cs_cnt = togo = chan->cs_blksz;
1392 } else {
1393 nextaddr = APC_READ(sc, APC_CNVA) +
1394 chan->cs_blksz;
1395 if (togo > chan->cs_blksz)
1396 togo = chan->cs_blksz;
1397 chan->cs_cnt += togo;
1398 }
1399
1400 APC_WRITE(sc, APC_CNVA, nextaddr);
1401 APC_WRITE(sc, APC_CNC, togo);
1402
1403 if (chan->cs_intr != NULL)
1404 (*chan->cs_intr)(chan->cs_arg);
1405 }
1406 r = 1;
1407 }
1408
1409 if ((csr & APC_CSR_CMIE) && (csr & APC_CSR_CMI)) {
1410
1411 r = 1;
1412 }
1413
1414 return (r);
1415 }
1416
1417 void *
1418 cs4231_alloc(void *vsc, int direction, size_t size, int pool, int flags)
1419 {
1420 struct cs4231_softc *sc = (struct cs4231_softc *)vsc;
1421 bus_dma_tag_t dmat = sc->sc_dmatag;
1422 struct cs_dma *p;
1423
1424 p = (struct cs_dma *)malloc(sizeof(struct cs_dma), pool, flags);
1425 if (p == NULL)
1426 return (NULL);
1427
1428 if (bus_dmamap_create(dmat, size, 1, size, 0,
1429 BUS_DMA_NOWAIT, &p->dmamap) != 0)
1430 goto fail;
1431
1432 p->size = size;
1433
1434 if (bus_dmamem_alloc(dmat, size, 64*1024, 0, p->segs,
1435 sizeof(p->segs)/sizeof(p->segs[0]), &p->nsegs,
1436 BUS_DMA_NOWAIT) != 0)
1437 goto fail1;
1438
1439 if (bus_dmamem_map(dmat, p->segs, p->nsegs, p->size,
1440 &p->addr, BUS_DMA_NOWAIT | BUS_DMA_COHERENT) != 0)
1441 goto fail2;
1442
1443 if (bus_dmamap_load(dmat, p->dmamap, p->addr, size, NULL,
1444 BUS_DMA_NOWAIT) != 0)
1445 goto fail3;
1446
1447 p->next = sc->sc_dmas;
1448 sc->sc_dmas = p;
1449 return (p->addr);
1450
1451 fail3:
1452 bus_dmamem_unmap(dmat, p->addr, p->size);
1453 fail2:
1454 bus_dmamem_free(dmat, p->segs, p->nsegs);
1455 fail1:
1456 bus_dmamap_destroy(dmat, p->dmamap);
1457 fail:
1458 free(p, pool);
1459 return (NULL);
1460 }
1461
1462 void
1463 cs4231_free(void *vsc, void *ptr, int pool)
1464 {
1465 struct cs4231_softc *sc = vsc;
1466 bus_dma_tag_t dmat = sc->sc_dmatag;
1467 struct cs_dma *p, **pp;
1468
1469 for (pp = &sc->sc_dmas; (p = *pp) != NULL; pp = &(*pp)->next) {
1470 if (p->addr != ptr)
1471 continue;
1472 bus_dmamap_unload(dmat, p->dmamap);
1473 bus_dmamem_unmap(dmat, p->addr, p->size);
1474 bus_dmamem_free(dmat, p->segs, p->nsegs);
1475 bus_dmamap_destroy(dmat, p->dmamap);
1476 *pp = p->next;
1477 free(p, pool);
1478 return;
1479 }
1480 printf("%s: attempt to free rogue pointer\n", sc->sc_dev.dv_xname);
1481 }
1482
1483 int
1484 cs4231_trigger_output(void *vsc, void *start, void *end, int blksize,
1485 void (*intr)(void *), void *arg, struct audio_params *param)
1486 {
1487 struct cs4231_softc *sc = vsc;
1488 struct cs_channel *chan = &sc->sc_playback;
1489 struct cs_dma *p;
1490 u_int32_t csr;
1491 u_long n;
1492
1493 if (chan->cs_locked != 0) {
1494 printf("%s: trigger_output: already running\n",
1495 sc->sc_dev.dv_xname);
1496 return (EINVAL);
1497 }
1498
1499 chan->cs_locked = 1;
1500 chan->cs_intr = intr;
1501 chan->cs_arg = arg;
1502
1503 for (p = sc->sc_dmas; p->addr != start; p = p->next)
1504 ;
1505 if (p == NULL) {
1506 printf("%s: trigger_output: bad addr: %p\n",
1507 sc->sc_dev.dv_xname, start);
1508 return (EINVAL);
1509 }
1510
1511 n = (char *)end - (char *)start;
1512
1513
1514
1515
1516
1517 chan->cs_blksz = blksize;
1518 chan->cs_curdma = p;
1519 chan->cs_segsz = n;
1520
1521 if (n > chan->cs_blksz)
1522 n = chan->cs_blksz;
1523
1524 chan->cs_cnt = n;
1525
1526 csr = APC_READ(sc, APC_CSR);
1527
1528 APC_WRITE(sc, APC_PNVA, (u_long)p->dmamap->dm_segs[0].ds_addr);
1529 APC_WRITE(sc, APC_PNC, (u_long)n);
1530
1531 if ((csr & APC_CSR_PDMA_GO) == 0 || (csr & APC_CSR_PPAUSE) != 0) {
1532 APC_WRITE(sc, APC_CSR,
1533 APC_READ(sc, APC_CSR) & ~(APC_CSR_PIE | APC_CSR_PPAUSE));
1534 APC_WRITE(sc, APC_CSR, APC_READ(sc, APC_CSR) |
1535 APC_CSR_EI | APC_CSR_GIE | APC_CSR_PIE | APC_CSR_EIE |
1536 APC_CSR_PMIE | APC_CSR_PDMA_GO);
1537 cs4231_write(sc, SP_LOWER_BASE_COUNT, 0xff);
1538 cs4231_write(sc, SP_UPPER_BASE_COUNT, 0xff);
1539 cs4231_write(sc, SP_INTERFACE_CONFIG,
1540 cs4231_read(sc, SP_INTERFACE_CONFIG) | PLAYBACK_ENABLE);
1541 }
1542 return (0);
1543 }
1544
1545 int
1546 cs4231_trigger_input(void *vsc, void *start, void *end, int blksize,
1547 void (*intr)(void *), void *arg, struct audio_params *param)
1548 {
1549 struct cs4231_softc *sc = vsc;
1550 struct cs_channel *chan = &sc->sc_capture;
1551 struct cs_dma *p;
1552 u_int32_t csr;
1553 u_long n;
1554
1555 if (chan->cs_locked != 0) {
1556 printf("%s: trigger_input: already running\n",
1557 sc->sc_dev.dv_xname);
1558 return (EINVAL);
1559 }
1560 chan->cs_locked = 1;
1561 chan->cs_intr = intr;
1562 chan->cs_arg = arg;
1563
1564 for (p = sc->sc_dmas; p->addr != start; p = p->next)
1565 ;
1566 if (p == NULL) {
1567 printf("%s: trigger_input: bad addr: %p\n",
1568 sc->sc_dev.dv_xname, start);
1569 return (EINVAL);
1570 }
1571
1572 n = (char *)end - (char *)start;
1573
1574
1575
1576
1577
1578 chan->cs_blksz = blksize;
1579 chan->cs_curdma = p;
1580 chan->cs_segsz = n;
1581
1582 if (n > chan->cs_blksz)
1583 n = chan->cs_blksz;
1584 chan->cs_cnt = n;
1585
1586 APC_WRITE(sc, APC_CNVA, p->dmamap->dm_segs[0].ds_addr);
1587 APC_WRITE(sc, APC_CNC, (u_long)n);
1588
1589 csr = APC_READ(sc, APC_CSR);
1590 if ((csr & APC_CSR_CDMA_GO) == 0 || (csr & APC_CSR_CPAUSE) != 0) {
1591 csr &= APC_CSR_CPAUSE;
1592 csr |= APC_CSR_GIE | APC_CSR_CMIE | APC_CSR_CIE | APC_CSR_EI |
1593 APC_CSR_CDMA_GO;
1594 APC_WRITE(sc, APC_CSR, csr);
1595 cs4231_write(sc, CS_LOWER_REC_CNT, 0xff);
1596 cs4231_write(sc, CS_UPPER_REC_CNT, 0xff);
1597 cs4231_write(sc, SP_INTERFACE_CONFIG,
1598 cs4231_read(sc, SP_INTERFACE_CONFIG) | CAPTURE_ENABLE);
1599 }
1600
1601 if (APC_READ(sc, APC_CSR) & APC_CSR_CD) {
1602 u_long nextaddr, togo;
1603
1604 p = chan->cs_curdma;
1605 togo = chan->cs_segsz - chan->cs_cnt;
1606 if (togo == 0) {
1607 nextaddr = (u_int32_t)p->dmamap->dm_segs[0].ds_addr;
1608 chan->cs_cnt = togo = chan->cs_blksz;
1609 } else {
1610 nextaddr = APC_READ(sc, APC_CNVA) + chan->cs_blksz;
1611 if (togo > chan->cs_blksz)
1612 togo = chan->cs_blksz;
1613 chan->cs_cnt += togo;
1614 }
1615
1616 APC_WRITE(sc, APC_CNVA, nextaddr);
1617 APC_WRITE(sc, APC_CNC, togo);
1618 }
1619
1620 return (0);
1621 }