This source file includes following definitions.
- cs4281_match
- cs4281_attach
- cs4281_intr
- cs4281_query_encoding
- cs4281_set_params
- cs4281_halt_output
- cs4281_halt_input
- cs4281_getdev
- cs4281_trigger_output
- cs4281_trigger_input
- cs4281_sr2regval
- cs4281_set_dac_rate
- cs4281_set_adc_rate
- cs4281_init
- cs4281_power
- cs4281_reset_codec
- cs4281_open
- cs4281_close
- cs4281_round_blocksize
- cs4281_mixer_set_port
- cs4281_mixer_get_port
- cs4281_query_devinfo
- cs4281_malloc
- cs4281_free
- cs4281_round_buffersize
- cs4281_mappage
- cs4281_get_props
- cs4281_attach_codec
- cs4281_read_codec
- cs4281_write_codec
- cs4281_allocmem
- cs4281_src_wait
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
40
41
42
43
44 #include <sys/param.h>
45 #include <sys/systm.h>
46 #include <sys/kernel.h>
47 #include <sys/malloc.h>
48 #include <sys/fcntl.h>
49 #include <sys/device.h>
50
51 #include <dev/pci/pcidevs.h>
52 #include <dev/pci/pcivar.h>
53 #include <dev/pci/cs4281reg.h>
54
55 #include <sys/audioio.h>
56 #include <dev/audio_if.h>
57 #include <dev/midi_if.h>
58 #include <dev/mulaw.h>
59 #include <dev/auconv.h>
60
61 #include <dev/ic/ac97.h>
62
63 #include <machine/bus.h>
64
65 #define CSCC_PCI_BA0 0x10
66 #define CSCC_PCI_BA1 0x14
67
68 struct cs4281_dma {
69 bus_dmamap_t map;
70 caddr_t addr;
71 caddr_t dum;
72 bus_dma_segment_t segs[1];
73 int nsegs;
74 size_t size;
75 struct cs4281_dma *next;
76 };
77 #define DMAADDR(p) ((p)->map->dm_segs[0].ds_addr)
78 #define BUFADDR(p) ((void *)((p)->dum))
79 #define KERNADDR(p) ((void *)((p)->addr))
80
81
82
83
84 struct cs4281_softc {
85 struct device sc_dev;
86
87 pci_intr_handle_t *sc_ih;
88
89
90 bus_space_tag_t ba0t;
91 bus_space_handle_t ba0h;
92
93
94 bus_space_tag_t ba1t;
95 bus_space_handle_t ba1h;
96
97
98 bus_dma_tag_t sc_dmatag;
99 struct cs4281_dma *sc_dmas;
100 size_t dma_size;
101 size_t dma_align;
102
103 int hw_blocksize;
104
105
106 void (*sc_pintr)(void *);
107 void *sc_parg;
108 char *sc_ps, *sc_pe, *sc_pn;
109 int sc_pcount;
110 int sc_pi;
111 struct cs4281_dma *sc_pdma;
112 char *sc_pbuf;
113 int (*halt_output)(void *);
114 #ifdef DIAGNOSTIC
115 char sc_prun;
116 #endif
117
118
119 void (*sc_rintr)(void *);
120 void *sc_rarg;
121 char *sc_rs, *sc_re, *sc_rn;
122 int sc_rcount;
123 int sc_ri;
124 struct cs4281_dma *sc_rdma;
125 char *sc_rbuf;
126 int sc_rparam;
127 int (*halt_input)(void *);
128 #ifdef DIAGNOSTIC
129 char sc_rrun;
130 #endif
131
132 #if NMIDI > 0
133 void (*sc_iintr)(void *, int);
134 void (*sc_ointr)(void *);
135 void *sc_arg;
136 #endif
137
138
139 struct ac97_codec_if *codec_if;
140 struct ac97_host_if host_if;
141
142
143 char sc_suspend;
144 void *sc_powerhook;
145 u_int16_t ac97_reg[CS4281_SAVE_REG_MAX + 1];
146 };
147
148 #define BA0READ4(sc, r) bus_space_read_4((sc)->ba0t, (sc)->ba0h, (r))
149 #define BA0WRITE4(sc, r, x) bus_space_write_4((sc)->ba0t, (sc)->ba0h, (r), (x))
150
151 #if defined(ENABLE_SECONDARY_CODEC)
152 #define MAX_CHANNELS (4)
153 #define MAX_FIFO_SIZE 32
154 #else
155 #define MAX_CHANNELS (2)
156 #define MAX_FIFO_SIZE 64
157 #endif
158
159 int cs4281_match(struct device *, void *, void *);
160 void cs4281_attach(struct device *, struct device *, void *);
161 int cs4281_intr(void *);
162 int cs4281_query_encoding(void *, struct audio_encoding *);
163 int cs4281_set_params(void *, int, int, struct audio_params *,
164 struct audio_params *);
165 int cs4281_halt_output(void *);
166 int cs4281_halt_input(void *);
167 int cs4281_getdev(void *, struct audio_device *);
168 int cs4281_trigger_output(void *, void *, void *, int, void (*)(void *),
169 void *, struct audio_params *);
170 int cs4281_trigger_input(void *, void *, void *, int, void (*)(void *),
171 void *, struct audio_params *);
172 u_int8_t cs4281_sr2regval(int);
173 void cs4281_set_dac_rate(struct cs4281_softc *, int);
174 void cs4281_set_adc_rate(struct cs4281_softc *, int);
175 int cs4281_init(struct cs4281_softc *);
176
177 int cs4281_open(void *, int);
178 void cs4281_close(void *);
179 int cs4281_round_blocksize(void *, int);
180 int cs4281_get_props(void *);
181 int cs4281_attach_codec(void *, struct ac97_codec_if *);
182 int cs4281_read_codec(void *, u_int8_t , u_int16_t *);
183 int cs4281_write_codec(void *, u_int8_t, u_int16_t);
184 void cs4281_reset_codec(void *);
185
186 void cs4281_power(int, void *);
187
188 int cs4281_mixer_set_port(void *, mixer_ctrl_t *);
189 int cs4281_mixer_get_port(void *, mixer_ctrl_t *);
190 int cs4281_query_devinfo(void *, mixer_devinfo_t *);
191 void *cs4281_malloc(void *, int, size_t, int, int);
192 size_t cs4281_round_buffersize(void *, int, size_t);
193 void cs4281_free(void *, void *, int);
194 paddr_t cs4281_mappage(void *, void *, off_t, int);
195
196 int cs4281_allocmem(struct cs4281_softc *, size_t, int, int,
197 struct cs4281_dma *);
198 int cs4281_src_wait(struct cs4281_softc *);
199
200 #if defined(CS4281_DEBUG)
201 #undef DPRINTF
202 #undef DPRINTFN
203 #define DPRINTF(x) if (cs4281_debug) printf x
204 #define DPRINTFN(n,x) if (cs4281_debug>(n)) printf x
205 int cs4281_debug = 5;
206 #else
207 #define DPRINTF(x)
208 #define DPRINTFN(n,x)
209 #endif
210
211 struct audio_hw_if cs4281_hw_if = {
212 cs4281_open,
213 cs4281_close,
214 NULL,
215 cs4281_query_encoding,
216 cs4281_set_params,
217 cs4281_round_blocksize,
218 NULL,
219 NULL,
220 NULL,
221 NULL,
222 NULL,
223 cs4281_halt_output,
224 cs4281_halt_input,
225 NULL,
226 cs4281_getdev,
227 NULL,
228 cs4281_mixer_set_port,
229 cs4281_mixer_get_port,
230 cs4281_query_devinfo,
231 cs4281_malloc,
232 cs4281_free,
233 cs4281_round_buffersize,
234 NULL,
235 cs4281_get_props,
236 cs4281_trigger_output,
237 cs4281_trigger_input,
238 };
239
240 #if NMIDI > 0
241
242 void cs4281_midi_close(void *);
243 void cs4281_midi_getinfo(void *, struct midi_info *);
244 int cs4281_midi_open(void *, int, void (*)(void *, int),
245 void (*)(void *), void *);
246 int cs4281_midi_output(void *, int);
247
248 struct midi_hw_if cs4281_midi_hw_if = {
249 cs4281_midi_open,
250 cs4281_midi_close,
251 cs4281_midi_output,
252 cs4281_midi_getinfo,
253 0,
254 };
255 #endif
256
257 struct cfattach clct_ca = {
258 sizeof(struct cs4281_softc), cs4281_match, cs4281_attach
259 };
260
261 struct cfdriver clct_cd = {
262 NULL, "clct", DV_DULL
263 };
264
265 struct audio_device cs4281_device = {
266 "CS4281",
267 "",
268 "cs4281"
269 };
270
271
272 int
273 cs4281_match(parent, match, aux)
274 struct device *parent;
275 void *match;
276 void *aux;
277 {
278 struct pci_attach_args *pa = (struct pci_attach_args *)aux;
279
280 if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_CIRRUS ||
281 PCI_PRODUCT(pa->pa_id) != PCI_PRODUCT_CIRRUS_CS4281)
282 return (0);
283
284 return (1);
285 }
286
287 void
288 cs4281_attach(parent, self, aux)
289 struct device *parent;
290 struct device *self;
291 void *aux;
292 {
293 struct cs4281_softc *sc = (struct cs4281_softc *)self;
294 struct pci_attach_args *pa = (struct pci_attach_args *)aux;
295 pci_chipset_tag_t pc = pa->pa_pc;
296 char const *intrstr;
297 pci_intr_handle_t ih;
298 int pci_pwrmgmt_cap_reg, pci_pwrmgmt_csr_reg;
299
300
301 if (pci_mapreg_map(pa, CSCC_PCI_BA0,
302 PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT, 0, &sc->ba0t,
303 &sc->ba0h, NULL, NULL, 0)) {
304 printf("%s: can't map BA0 space\n", sc->sc_dev.dv_xname);
305 return;
306 }
307 if (pci_mapreg_map(pa, CSCC_PCI_BA1,
308 PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT, 0, &sc->ba1t,
309 &sc->ba1h, NULL, NULL, 0)) {
310 printf("%s: can't map BA1 space\n", sc->sc_dev.dv_xname);
311 return;
312 }
313
314 sc->sc_dmatag = pa->pa_dmat;
315
316
317
318
319
320
321
322 if (pci_get_capability(pa->pa_pc, pa->pa_tag, PCI_CAP_PWRMGMT,
323 &pci_pwrmgmt_cap_reg, 0)) {
324 pcireg_t reg;
325
326 pci_pwrmgmt_csr_reg = pci_pwrmgmt_cap_reg + PCI_PMCSR;
327 reg = pci_conf_read(pa->pa_pc, pa->pa_tag, pci_pwrmgmt_csr_reg);
328 if ((reg & PCI_PMCSR_STATE_MASK) != PCI_PMCSR_STATE_D0) {
329 pci_conf_write(pc, pa->pa_tag, pci_pwrmgmt_csr_reg,
330 (reg & ~PCI_PMCSR_STATE_MASK) |
331 PCI_PMCSR_STATE_D0);
332 }
333 }
334
335
336 if (pci_intr_map(pa, &ih)) {
337 printf("%s: couldn't map interrupt\n", sc->sc_dev.dv_xname);
338 return;
339 }
340 intrstr = pci_intr_string(pc, ih);
341
342 sc->sc_ih = pci_intr_establish(pc, ih, IPL_AUDIO, cs4281_intr, sc,
343 sc->sc_dev.dv_xname);
344 if (sc->sc_ih == NULL) {
345 printf("%s: couldn't establish interrupt",sc->sc_dev.dv_xname);
346 if (intrstr != NULL)
347 printf(" at %s", intrstr);
348 printf("\n");
349 return;
350 }
351 printf(" %s\n", intrstr);
352
353
354
355
356 if (cs4281_init(sc) != 0)
357 return;
358
359 sc->halt_input = cs4281_halt_input;
360 sc->halt_output = cs4281_halt_output;
361
362 sc->dma_size = CS4281_BUFFER_SIZE / MAX_CHANNELS;
363 sc->dma_align = 0x10;
364 sc->hw_blocksize = sc->dma_size / 2;
365
366
367 sc->host_if.arg = sc;
368 sc->host_if.attach = cs4281_attach_codec;
369 sc->host_if.read = cs4281_read_codec;
370 sc->host_if.write = cs4281_write_codec;
371 sc->host_if.reset = cs4281_reset_codec;
372 if (ac97_attach(&sc->host_if) != 0) {
373 printf("%s: ac97_attach failed\n", sc->sc_dev.dv_xname);
374 return;
375 }
376 audio_attach_mi(&cs4281_hw_if, sc, &sc->sc_dev);
377
378 #if NMIDI > 0
379 midi_attach_mi(&cs4281_midi_hw_if, sc, &sc->sc_dev);
380 #endif
381
382 sc->sc_suspend = PWR_RESUME;
383 sc->sc_powerhook = powerhook_establish(cs4281_power, sc);
384 }
385
386
387 int
388 cs4281_intr(p)
389 void *p;
390 {
391 struct cs4281_softc *sc = p;
392 u_int32_t intr, val;
393 char *empty_dma;
394
395 intr = BA0READ4(sc, CS4281_HISR);
396 if (!(intr & (HISR_DMA0 | HISR_DMA1 | HISR_MIDI))) {
397 BA0WRITE4(sc, CS4281_HICR, HICR_IEV | HICR_CHGM);
398 return (0);
399 }
400 DPRINTF(("cs4281_intr:"));
401
402 if (intr & HISR_DMA0)
403 val = BA0READ4(sc, CS4281_HDSR0);
404 if (intr & HISR_DMA1)
405 val = BA0READ4(sc, CS4281_HDSR1);
406 BA0WRITE4(sc, CS4281_HICR, HICR_IEV | HICR_CHGM);
407
408
409 if (intr & HISR_DMA0) {
410 DPRINTF((" PB DMA 0x%x(%d)", (int)BA0READ4(sc, CS4281_DCA0),
411 (int)BA0READ4(sc, CS4281_DCC0)));
412 if (sc->sc_pintr) {
413 if ((sc->sc_pi%sc->sc_pcount) == 0)
414 sc->sc_pintr(sc->sc_parg);
415 } else {
416 printf("unexpected play intr\n");
417 }
418
419 ++sc->sc_pi;
420 empty_dma = sc->sc_pdma->addr;
421 if (sc->sc_pi&1)
422 empty_dma += sc->hw_blocksize;
423 memcpy(empty_dma, sc->sc_pn, sc->hw_blocksize);
424 sc->sc_pn += sc->hw_blocksize;
425 if (sc->sc_pn >= sc->sc_pe)
426 sc->sc_pn = sc->sc_ps;
427 }
428 if (intr & HISR_DMA1) {
429 val = BA0READ4(sc, CS4281_HDSR1);
430
431 DPRINTF((" CP DMA 0x%x(%d)", (int)BA0READ4(sc, CS4281_DCA1),
432 (int)BA0READ4(sc, CS4281_DCC1)));
433 ++sc->sc_ri;
434 empty_dma = sc->sc_rdma->addr;
435 if ((sc->sc_ri & 1) == 0)
436 empty_dma += sc->hw_blocksize;
437 memcpy(sc->sc_rn, empty_dma, sc->hw_blocksize);
438 if (sc->sc_rn >= sc->sc_re)
439 sc->sc_rn = sc->sc_rs;
440 if (sc->sc_rintr) {
441 if ((sc->sc_ri % sc->sc_rcount) == 0)
442 sc->sc_rintr(sc->sc_rarg);
443 } else {
444 printf("unexpected record intr\n");
445 }
446 }
447 DPRINTF(("\n"));
448 return (1);
449 }
450
451 int
452 cs4281_query_encoding(addr, fp)
453 void *addr;
454 struct audio_encoding *fp;
455 {
456 switch (fp->index) {
457 case 0:
458 strlcpy(fp->name, AudioEulinear, sizeof fp->name);
459 fp->encoding = AUDIO_ENCODING_ULINEAR;
460 fp->precision = 8;
461 fp->flags = 0;
462 break;
463 case 1:
464 strlcpy(fp->name, AudioEmulaw, sizeof fp->name);
465 fp->encoding = AUDIO_ENCODING_ULAW;
466 fp->precision = 8;
467 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
468 break;
469 case 2:
470 strlcpy(fp->name, AudioEalaw, sizeof fp->name);
471 fp->encoding = AUDIO_ENCODING_ALAW;
472 fp->precision = 8;
473 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
474 break;
475 case 3:
476 strlcpy(fp->name, AudioEslinear, sizeof fp->name);
477 fp->encoding = AUDIO_ENCODING_SLINEAR;
478 fp->precision = 8;
479 fp->flags = 0;
480 break;
481 case 4:
482 strlcpy(fp->name, AudioEslinear_le, sizeof fp->name);
483 fp->encoding = AUDIO_ENCODING_SLINEAR_LE;
484 fp->precision = 16;
485 fp->flags = 0;
486 break;
487 case 5:
488 strlcpy(fp->name, AudioEulinear_le, sizeof fp->name);
489 fp->encoding = AUDIO_ENCODING_ULINEAR_LE;
490 fp->precision = 16;
491 fp->flags = 0;
492 break;
493 case 6:
494 strlcpy(fp->name, AudioEslinear_be, sizeof fp->name);
495 fp->encoding = AUDIO_ENCODING_SLINEAR_BE;
496 fp->precision = 16;
497 fp->flags = 0;
498 break;
499 case 7:
500 strlcpy(fp->name, AudioEulinear_be, sizeof fp->name);
501 fp->encoding = AUDIO_ENCODING_ULINEAR_BE;
502 fp->precision = 16;
503 fp->flags = 0;
504 break;
505 default:
506 return EINVAL;
507 }
508 return (0);
509 }
510
511 int
512 cs4281_set_params(addr, setmode, usemode, play, rec)
513 void *addr;
514 int setmode, usemode;
515 struct audio_params *play, *rec;
516 {
517 struct cs4281_softc *sc = addr;
518 struct audio_params *p;
519 int mode;
520
521 for (mode = AUMODE_RECORD; mode != -1;
522 mode = mode == AUMODE_RECORD ? AUMODE_PLAY : -1) {
523 if ((setmode & mode) == 0)
524 continue;
525
526 p = mode == AUMODE_PLAY ? play : rec;
527
528 if (p == play) {
529 DPRINTFN(5,("play: samp=%ld precision=%d channels=%d\n",
530 p->sample_rate, p->precision, p->channels));
531 if (p->sample_rate < 6023 || p->sample_rate > 48000 ||
532 (p->precision != 8 && p->precision != 16) ||
533 (p->channels != 1 && p->channels != 2)) {
534 return (EINVAL);
535 }
536 } else {
537 DPRINTFN(5,("rec: samp=%ld precision=%d channels=%d\n",
538 p->sample_rate, p->precision, p->channels));
539 if (p->sample_rate < 6023 || p->sample_rate > 48000 ||
540 (p->precision != 8 && p->precision != 16) ||
541 (p->channels != 1 && p->channels != 2)) {
542 return (EINVAL);
543 }
544 }
545 p->factor = 1;
546 p->sw_code = 0;
547
548 switch (p->encoding) {
549 case AUDIO_ENCODING_SLINEAR_BE:
550 break;
551 case AUDIO_ENCODING_SLINEAR_LE:
552 break;
553 case AUDIO_ENCODING_ULINEAR_BE:
554 break;
555 case AUDIO_ENCODING_ULINEAR_LE:
556 break;
557 case AUDIO_ENCODING_ULAW:
558 if (mode == AUMODE_PLAY) {
559 p->sw_code = mulaw_to_slinear8;
560 } else {
561 p->sw_code = slinear8_to_mulaw;
562 }
563 break;
564 case AUDIO_ENCODING_ALAW:
565 if (mode == AUMODE_PLAY) {
566 p->sw_code = alaw_to_slinear8;
567 } else {
568 p->sw_code = slinear8_to_alaw;
569 }
570 break;
571 default:
572 return (EINVAL);
573 }
574 }
575
576
577 cs4281_set_dac_rate(sc, play->sample_rate);
578 cs4281_set_adc_rate(sc, rec->sample_rate);
579 return (0);
580 }
581
582 int
583 cs4281_halt_output(addr)
584 void *addr;
585 {
586 struct cs4281_softc *sc = addr;
587
588 BA0WRITE4(sc, CS4281_DCR0, BA0READ4(sc, CS4281_DCR0) | DCRn_MSK);
589 #ifdef DIAGNOSTIC
590 sc->sc_prun = 0;
591 #endif
592 return (0);
593 }
594
595 int
596 cs4281_halt_input(addr)
597 void *addr;
598 {
599 struct cs4281_softc *sc = addr;
600
601 BA0WRITE4(sc, CS4281_DCR1, BA0READ4(sc, CS4281_DCR1) | DCRn_MSK);
602 #ifdef DIAGNOSTIC
603 sc->sc_rrun = 0;
604 #endif
605 return (0);
606 }
607
608
609 int
610 cs4281_getdev(addr, retp)
611 void *addr;
612 struct audio_device *retp;
613 {
614 *retp = cs4281_device;
615 return (0);
616 }
617
618
619 int
620 cs4281_trigger_output(addr, start, end, blksize, intr, arg, param)
621 void *addr;
622 void *start, *end;
623 int blksize;
624 void (*intr)(void *);
625 void *arg;
626 struct audio_params *param;
627 {
628 struct cs4281_softc *sc = addr;
629 u_int32_t fmt=0;
630 struct cs4281_dma *p;
631 int dma_count;
632
633 #ifdef DIAGNOSTIC
634 if (sc->sc_prun)
635 printf("cs4281_trigger_output: already running\n");
636 sc->sc_prun = 1;
637 #endif
638
639 DPRINTF(("cs4281_trigger_output: sc=%p start=%p end=%p "
640 "blksize=%d intr=%p(%p)\n", addr, start, end, blksize, intr, arg));
641 sc->sc_pintr = intr;
642 sc->sc_parg = arg;
643
644
645 BA0WRITE4(sc, CS4281_DCR0, BA0READ4(sc, CS4281_DCR0) | DCRn_MSK);
646
647 DPRINTF(("param: precision=%d factor=%d channels=%d encoding=%d\n",
648 param->precision, param->factor, param->channels,
649 param->encoding));
650 for (p = sc->sc_dmas; p != NULL && BUFADDR(p) != start; p = p->next)
651 ;
652 if (p == NULL) {
653 printf("cs4281_trigger_output: bad addr %p\n", start);
654 return (EINVAL);
655 }
656
657 sc->sc_pcount = blksize / sc->hw_blocksize;
658 sc->sc_ps = (char *)start;
659 sc->sc_pe = (char *)end;
660 sc->sc_pdma = p;
661 sc->sc_pbuf = KERNADDR(p);
662 sc->sc_pi = 0;
663 sc->sc_pn = sc->sc_ps;
664 if (blksize >= sc->dma_size) {
665 sc->sc_pn = sc->sc_ps + sc->dma_size;
666 memcpy(sc->sc_pbuf, start, sc->dma_size);
667 ++sc->sc_pi;
668 } else {
669 sc->sc_pn = sc->sc_ps + sc->hw_blocksize;
670 memcpy(sc->sc_pbuf, start, sc->hw_blocksize);
671 }
672
673 dma_count = sc->dma_size;
674 if (param->precision * param->factor != 8)
675 dma_count /= 2;
676 if (param->channels > 1)
677 dma_count /= 2;
678
679 DPRINTF(("cs4281_trigger_output: DMAADDR(p)=0x%x count=%d\n",
680 (int)DMAADDR(p), dma_count));
681 BA0WRITE4(sc, CS4281_DBA0, DMAADDR(p));
682 BA0WRITE4(sc, CS4281_DBC0, dma_count-1);
683
684
685 fmt = BA0READ4(sc, CS4281_DMR0) & ~DMRn_FMTMSK;
686 if (param->precision * param->factor == 8)
687 fmt |= DMRn_SIZE8;
688 if (param->channels == 1)
689 fmt |= DMRn_MONO;
690 if (param->encoding == AUDIO_ENCODING_ULINEAR_BE ||
691 param->encoding == AUDIO_ENCODING_SLINEAR_BE)
692 fmt |= DMRn_BEND;
693 if (param->encoding == AUDIO_ENCODING_ULINEAR_BE ||
694 param->encoding == AUDIO_ENCODING_ULINEAR_LE)
695 fmt |= DMRn_USIGN;
696 BA0WRITE4(sc, CS4281_DMR0, fmt);
697
698
699 cs4281_set_dac_rate(sc, param->sample_rate);
700
701
702 BA0WRITE4(sc, CS4281_DCR0, BA0READ4(sc, CS4281_DCR0) & ~DCRn_MSK);
703
704 BA0WRITE4(sc, CS4281_HICR, HICR_IEV | HICR_CHGM);
705
706 BA0WRITE4(sc, CS4281_PPRVC, 7);
707 BA0WRITE4(sc, CS4281_PPLVC, 7);
708
709 DPRINTF(("HICR =0x%08x(expected 0x00000001)\n", BA0READ4(sc, CS4281_HICR)));
710 DPRINTF(("HIMR =0x%08x(expected 0x00f0fc3f)\n", BA0READ4(sc, CS4281_HIMR)));
711 DPRINTF(("DMR0 =0x%08x(expected 0x2???0018)\n", BA0READ4(sc, CS4281_DMR0)));
712 DPRINTF(("DCR0 =0x%08x(expected 0x00030000)\n", BA0READ4(sc, CS4281_DCR0)));
713 DPRINTF(("FCR0 =0x%08x(expected 0x81000f00)\n", BA0READ4(sc, CS4281_FCR0)));
714 DPRINTF(("DACSR=0x%08x(expected 1 for 44kHz 5 for 8kHz)\n",
715 BA0READ4(sc, CS4281_DACSR)));
716 DPRINTF(("SRCSA=0x%08x(expected 0x0b0a0100)\n", BA0READ4(sc, CS4281_SRCSA)));
717 DPRINTF(("SSPM&SSPM_PSRCEN =0x%08x(expected 0x00000010)\n",
718 BA0READ4(sc, CS4281_SSPM) & SSPM_PSRCEN));
719
720 return (0);
721 }
722
723 int
724 cs4281_trigger_input(addr, start, end, blksize, intr, arg, param)
725 void *addr;
726 void *start, *end;
727 int blksize;
728 void (*intr)(void *);
729 void *arg;
730 struct audio_params *param;
731 {
732 struct cs4281_softc *sc = addr;
733 struct cs4281_dma *p;
734 u_int32_t fmt=0;
735 int dma_count;
736
737 printf("cs4281_trigger_input: not implemented yet\n");
738 #ifdef DIAGNOSTIC
739 if (sc->sc_rrun)
740 printf("cs4281_trigger_input: already running\n");
741 sc->sc_rrun = 1;
742 #endif
743 DPRINTF(("cs4281_trigger_input: sc=%p start=%p end=%p "
744 "blksize=%d intr=%p(%p)\n", addr, start, end, blksize, intr, arg));
745 sc->sc_rintr = intr;
746 sc->sc_rarg = arg;
747
748
749 BA0WRITE4(sc, CS4281_DCR1, BA0READ4(sc, CS4281_DCR1) | DCRn_MSK);
750
751 for (p = sc->sc_dmas; p && BUFADDR(p) != start; p = p->next)
752 ;
753 if (!p) {
754 printf("cs4281_trigger_input: bad addr %p\n", start);
755 return (EINVAL);
756 }
757
758 sc->sc_rcount = blksize / sc->hw_blocksize;
759 sc->sc_rs = (char *)start;
760 sc->sc_re = (char *)end;
761 sc->sc_rdma = p;
762 sc->sc_rbuf = KERNADDR(p);
763 sc->sc_ri = 0;
764 sc->sc_rn = sc->sc_rs;
765
766 dma_count = sc->dma_size;
767 if (param->precision * param->factor == 8)
768 dma_count /= 2;
769 if (param->channels > 1)
770 dma_count /= 2;
771
772 DPRINTF(("cs4281_trigger_input: DMAADDR(p)=0x%x count=%d\n",
773 (int)DMAADDR(p), dma_count));
774 BA0WRITE4(sc, CS4281_DBA1, DMAADDR(p));
775 BA0WRITE4(sc, CS4281_DBC1, dma_count-1);
776
777
778 fmt = BA0READ4(sc, CS4281_DMR1) & ~DMRn_FMTMSK;
779 if (param->precision * param->factor == 8)
780 fmt |= DMRn_SIZE8;
781 if (param->channels == 1)
782 fmt |= DMRn_MONO;
783 if (param->encoding == AUDIO_ENCODING_ULINEAR_BE ||
784 param->encoding == AUDIO_ENCODING_SLINEAR_BE)
785 fmt |= DMRn_BEND;
786 if (param->encoding == AUDIO_ENCODING_ULINEAR_BE ||
787 param->encoding == AUDIO_ENCODING_ULINEAR_LE)
788 fmt |= DMRn_USIGN;
789 BA0WRITE4(sc, CS4281_DMR1, fmt);
790
791
792 cs4281_set_adc_rate(sc, param->sample_rate);
793
794
795 BA0WRITE4(sc, CS4281_DCR1, BA0READ4(sc, CS4281_DCR1) & ~DCRn_MSK);
796
797 BA0WRITE4(sc, CS4281_HICR, HICR_IEV | HICR_CHGM);
798
799 DPRINTF(("HICR=0x%08x\n", BA0READ4(sc, CS4281_HICR)));
800 DPRINTF(("HIMR=0x%08x\n", BA0READ4(sc, CS4281_HIMR)));
801 DPRINTF(("DMR1=0x%08x\n", BA0READ4(sc, CS4281_DMR1)));
802 DPRINTF(("DCR1=0x%08x\n", BA0READ4(sc, CS4281_DCR1)));
803
804 return (0);
805 }
806
807
808 u_int8_t
809 cs4281_sr2regval(rate)
810 int rate;
811 {
812 u_int8_t retval;
813
814
815 if (rate > 48000)
816 rate = 48000;
817 if (rate < 6023)
818 rate = 6023;
819
820 switch (rate) {
821 case 8000:
822 retval = 5;
823 break;
824 case 11025:
825 retval = 4;
826 break;
827 case 16000:
828 retval = 3;
829 break;
830 case 22050:
831 retval = 2;
832 break;
833 case 44100:
834 retval = 1;
835 break;
836 case 48000:
837 retval = 0;
838 break;
839 default:
840 retval = 1536000/rate;
841 }
842 return (retval);
843 }
844
845
846 void
847 cs4281_set_dac_rate(sc, rate)
848 struct cs4281_softc *sc;
849 int rate;
850 {
851 BA0WRITE4(sc, CS4281_DACSR, cs4281_sr2regval(rate));
852 }
853
854 void
855 cs4281_set_adc_rate(sc, rate)
856 struct cs4281_softc *sc;
857 int rate;
858 {
859 BA0WRITE4(sc, CS4281_ADCSR, cs4281_sr2regval(rate));
860 }
861
862 int
863 cs4281_init(sc)
864 struct cs4281_softc *sc;
865 {
866 int n;
867 u_int16_t data;
868 u_int32_t dat32;
869
870
871
872 BA0WRITE4(sc, CS4281_CWPR, 0x4281);
873
874
875
876
877
878 dat32 = BA0READ4(sc, CS4281_EPPMC);
879 if (dat32 & EPPMC_FPDN)
880 BA0WRITE4(sc, CS4281_EPPMC, dat32 & ~EPPMC_FPDN);
881
882
883 BA0WRITE4(sc, CS4281_CLKCR1, 0);
884
885 BA0WRITE4(sc, CS4281_SERMC, 0);
886
887
888 BA0WRITE4(sc, CS4281_ACCTL, 0);
889 delay(50);
890
891 BA0WRITE4(sc, CS4281_SPMC, 0);
892 delay(100);
893 BA0WRITE4(sc, CS4281_SPMC, SPMC_RSTN);
894 #if defined(ENABLE_SECONDARY_CODEC)
895 BA0WRITE4(sc, CS4281_SPMC, SPMC_RSTN | SPCM_ASDIN2E);
896 BA0WRITE4(sc, CS4281_SERMC, SERMC_TCID);
897 #endif
898 delay(50000);
899
900
901 BA0WRITE4(sc, CS4281_CLKCR1, CLKCR1_DLLP);
902 delay(50000);
903 BA0WRITE4(sc, CS4281_CLKCR1, CLKCR1_SWCE | CLKCR1_DLLP);
904
905
906 BA0WRITE4(sc, CS4281_SSPM,
907 SSPM_MIXEN |
908 SSPM_CSRCEN |
909 SSPM_PSRCEN |
910 SSPM_JSEN |
911 SSPM_ACLEN |
912 SSPM_FMEN
913 );
914
915
916 n = 0;
917 while ((BA0READ4(sc, CS4281_CLKCR1)& (CLKCR1_DLLRDY | CLKCR1_CLKON))
918 != (CLKCR1_DLLRDY | CLKCR1_CLKON)) {
919 delay(100);
920 if (++n > 1000)
921 return (-1);
922 }
923
924
925 BA0WRITE4(sc, CS4281_ACCTL, ACCTL_ESYN);
926
927
928 n = 0;
929 while((BA0READ4(sc, CS4281_ACSTS) & ACSTS_CRDY) == 0) {
930 delay(100);
931 if (++n > 1000)
932 return (-1);
933 }
934
935 #if defined(ENABLE_SECONDARY_CODEC)
936
937 n = 0;
938 while((BA0READ4(sc, CS4281_ACSTS2) & ACSTS2_CRDY2) == 0) {
939 delay(100);
940 if (++n > 1000)
941 return (-1);
942 }
943 #endif
944
945
946
947 BA0WRITE4(sc, CS4281_SERMC, SERMC_PTCAC97);
948
949
950 n = 0;
951 do {
952 delay(1000);
953 if (++n > 1000) {
954 printf("%s: Timeout waiting for Codec ready\n",
955 sc->sc_dev.dv_xname);
956 return -1;
957 }
958 dat32 = BA0READ4(sc, CS4281_ACSTS) & ACSTS_CRDY;
959 } while (dat32 == 0);
960
961
962 BA0WRITE4(sc, CS4281_ACCTL, ACCTL_ESYN | ACCTL_VFRM);
963
964
965 n = 0;
966 do {
967 delay(1);
968 if (++n > 1000) {
969 printf("%s: Timeout waiting for Codec calibration\n",
970 sc->sc_dev.dv_xname);
971 return -1;
972 }
973 cs4281_read_codec(sc, AC97_REG_POWER, &data);
974 } while ((data & 0x0f) != 0x0f);
975
976
977
978 BA0WRITE4(sc, CS4281_SERMC, SERMC_PTCAC97);
979
980
981 n = 0;
982 do {
983 delay(1000);
984 if (++n > 1000) {
985 printf("%s: Timeout waiting for sampled input slots as valid\n",
986 sc->sc_dev.dv_xname);
987 return -1;
988 }
989 dat32 = BA0READ4(sc, CS4281_ACISV) & (ACISV_ISV3 | ACISV_ISV4);
990 } while (dat32 != (ACISV_ISV3 | ACISV_ISV4));
991
992
993 BA0WRITE4(sc, CS4281_ACOSV, (ACOSV_SLV3 | ACOSV_SLV4));
994
995 cs4281_write_codec(sc, AC97_REG_HEADPHONE_VOLUME, 0);
996 cs4281_write_codec(sc, AC97_REG_MASTER_VOLUME, 0);
997
998
999 cs4281_read_codec(sc, AC97_REG_POWER, &data);
1000 cs4281_write_codec(sc, AC97_REG_POWER, data &= 0xfdff);
1001
1002
1003
1004
1005 for (n = 0; n < 32; ++n) {
1006 delay(1000);
1007 cs4281_read_codec(sc, AC97_REG_POWER, &data);
1008 if (data & 0x02)
1009 break;
1010 }
1011
1012
1013 cs4281_read_codec(sc, AC97_REG_POWER, &data);
1014 cs4281_write_codec(sc, AC97_REG_POWER, data &= 0xfeff);
1015
1016
1017
1018
1019 for (n = 0; n < 32; ++n) {
1020 delay(1000);
1021 cs4281_read_codec(sc, AC97_REG_POWER, &data);
1022 if (data & 0x01)
1023 break;
1024 }
1025
1026 #if 0
1027
1028
1029 BA0WRITE4(sc, CS4281_SSCR, ~SSCR_HVC);
1030 #endif
1031
1032
1033
1034
1035
1036
1037 #if 0
1038 BA0WRITE4(sc, CS4281_SSCR, SSCR_SB);
1039 #endif
1040
1041
1042
1043 BA0WRITE4(sc, CS4281_FCR0, (BA0READ4(sc,CS4281_FCR0) & ~FCRn_FEN));
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055 dat32 = 0x01 << 24 |
1056 0x00 << 16 |
1057 0x0f << 8 |
1058 0x00 << 0 ;
1059 BA0WRITE4(sc, CS4281_FCR0, dat32);
1060 BA0WRITE4(sc, CS4281_FCR0, dat32 | FCRn_FEN);
1061
1062
1063
1064 BA0WRITE4(sc, CS4281_FCR1, (BA0READ4(sc,CS4281_FCR1) & ~FCRn_FEN));
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076 dat32 = 0x0b << 24 |
1077 0x0a << 16 |
1078 0x0f << 8 |
1079 0x10 << 0 ;
1080
1081
1082 BA0WRITE4(sc, CS4281_FCR1, dat32 | FCRn_PSH);
1083 BA0WRITE4(sc, CS4281_FCR1, dat32 | FCRn_FEN);
1084
1085 #if 0
1086
1087 BA0WRITE4(sc, CS4281_FCR2, (BA0READ4(sc,CS4281_FCR2) & ~FCRn_FEN));
1088 BA0WRITE4(sc, CS4281_FCR3, (BA0READ4(sc,CS4281_FCR3) & ~FCRn_FEN));
1089 #endif
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116 dat32 = 0x0b << 24 |
1117 0x0a << 16 |
1118 0x01 << 8 |
1119 0x00 << 0;
1120 BA0WRITE4(sc, CS4281_SRCSA, dat32);
1121
1122
1123
1124
1125
1126 dat32 = DCRn_HTCIE | DCRn_TCIE | DCRn_MSK;
1127 BA0WRITE4(sc, CS4281_DCR0, dat32);
1128 BA0WRITE4(sc, CS4281_DCR1, dat32);
1129
1130
1131 BA0WRITE4(sc, CS4281_DMR0,
1132 DMRn_DMA | DMRn_AUTO | DMRn_TR_READ);
1133 BA0WRITE4(sc, CS4281_DMR1,
1134 DMRn_DMA | DMRn_AUTO | DMRn_TR_WRITE);
1135
1136
1137 dat32 = BA0READ4(sc, CS4281_HIMR) & 0xfffbfcff;
1138 BA0WRITE4(sc, CS4281_HIMR, dat32);
1139 return (0);
1140 }
1141
1142 void
1143 cs4281_power(why, v)
1144 int why;
1145 void *v;
1146 {
1147 struct cs4281_softc *sc = (struct cs4281_softc *)v;
1148 int i;
1149
1150 DPRINTF(("%s: cs4281_power why=%d\n", sc->sc_dev.dv_xname, why));
1151 if (why != PWR_RESUME) {
1152 sc->sc_suspend = why;
1153
1154 cs4281_halt_output(sc);
1155 cs4281_halt_input(sc);
1156
1157 for (i = 1; i <= CS4281_SAVE_REG_MAX; i++) {
1158 if (i == 0x04)
1159 continue;
1160 cs4281_read_codec(sc, 2*i, &sc->ac97_reg[i>>1]);
1161 }
1162
1163 cs4281_write_codec(sc, AC97_REG_POWER, CS4281_POWER_DOWN_ALL);
1164 } else {
1165 if (sc->sc_suspend == PWR_RESUME) {
1166 printf("cs4281_power: odd, resume without suspend.\n");
1167 sc->sc_suspend = why;
1168 return;
1169 }
1170 sc->sc_suspend = why;
1171 cs4281_init(sc);
1172 cs4281_reset_codec(sc);
1173
1174
1175 for (i = 1; i <= CS4281_SAVE_REG_MAX; i++) {
1176 if (i == 0x04)
1177 continue;
1178 cs4281_write_codec(sc, 2*i, sc->ac97_reg[i>>1]);
1179 }
1180 }
1181 }
1182
1183 void
1184 cs4281_reset_codec(void *addr)
1185 {
1186 struct cs4281_softc *sc;
1187 u_int16_t data;
1188 u_int32_t dat32;
1189 int n;
1190
1191 sc = addr;
1192
1193 DPRINTFN(3,("cs4281_reset_codec\n"));
1194
1195
1196 BA0WRITE4(sc, CS4281_ACCTL, 0);
1197 delay(50);
1198
1199 BA0WRITE4(sc, CS4281_SPMC, 0);
1200 delay(100);
1201 BA0WRITE4(sc, CS4281_SPMC, SPMC_RSTN);
1202 #if defined(ENABLE_SECONDARY_CODEC)
1203 BA0WRITE4(sc, CS4281_SPMC, SPMC_RSTN | SPCM_ASDIN2E);
1204 BA0WRITE4(sc, CS4281_SERMC, SERMC_TCID);
1205 #endif
1206 delay(50000);
1207
1208
1209 BA0WRITE4(sc, CS4281_ACCTL, ACCTL_ESYN);
1210
1211
1212 n = 0;
1213 while((BA0READ4(sc, CS4281_ACSTS) & ACSTS_CRDY) == 0) {
1214 delay(100);
1215 if (++n > 1000) {
1216 printf("reset_codec: AC97 codec ready timeout\n");
1217 return;
1218 }
1219 }
1220 #if defined(ENABLE_SECONDARY_CODEC)
1221
1222 n = 0;
1223 while((BA0READ4(sc, CS4281_ACSTS2) & ACSTS2_CRDY2) == 0) {
1224 delay(100);
1225 if (++n > 1000)
1226 return;
1227 }
1228 #endif
1229
1230
1231 BA0WRITE4(sc, CS4281_SERMC, SERMC_PTCAC97);
1232
1233
1234 n = 0;
1235 do {
1236 delay(1000);
1237 if (++n > 1000) {
1238 printf("%s: Timeout waiting for Codec ready\n",
1239 sc->sc_dev.dv_xname);
1240 return;
1241 }
1242 dat32 = BA0READ4(sc, CS4281_ACSTS) & ACSTS_CRDY;
1243 } while (dat32 == 0);
1244
1245
1246 BA0WRITE4(sc, CS4281_ACCTL, ACCTL_ESYN | ACCTL_VFRM);
1247
1248
1249 n = 0;
1250 do {
1251 delay(1);
1252 if (++n > 1000) {
1253 printf("%s: Timeout waiting for Codec calibration\n",
1254 sc->sc_dev.dv_xname);
1255 return ;
1256 }
1257 cs4281_read_codec(sc, AC97_REG_POWER, &data);
1258 } while ((data & 0x0f) != 0x0f);
1259
1260
1261
1262 BA0WRITE4(sc, CS4281_SERMC, SERMC_PTCAC97);
1263
1264
1265 n = 0;
1266 do {
1267 delay(1000);
1268 if (++n > 1000) {
1269 printf("%s: Timeout waiting for sampled input slots as valid\n",
1270 sc->sc_dev.dv_xname);
1271 return;
1272 }
1273 dat32 = BA0READ4(sc, CS4281_ACISV) & (ACISV_ISV3 | ACISV_ISV4) ;
1274 } while (dat32 != (ACISV_ISV3 | ACISV_ISV4));
1275
1276
1277 BA0WRITE4(sc, CS4281_ACOSV, (ACOSV_SLV3 | ACOSV_SLV4));
1278 }
1279
1280 int
1281 cs4281_open(void *addr, int flags)
1282 {
1283 return (0);
1284 }
1285
1286 void
1287 cs4281_close(void *addr)
1288 {
1289 struct cs4281_softc *sc;
1290
1291 sc = addr;
1292
1293 (*sc->halt_output)(sc);
1294 (*sc->halt_input)(sc);
1295
1296 sc->sc_pintr = 0;
1297 sc->sc_rintr = 0;
1298 }
1299
1300 int
1301 cs4281_round_blocksize(void *addr, int blk)
1302 {
1303 struct cs4281_softc *sc;
1304 int retval;
1305
1306 DPRINTFN(5,("cs4281_round_blocksize blk=%d -> ", blk));
1307
1308 sc=addr;
1309 if (blk < sc->hw_blocksize)
1310 retval = sc->hw_blocksize;
1311 else
1312 retval = blk & -(sc->hw_blocksize);
1313
1314 DPRINTFN(5,("%d\n", retval));
1315
1316 return (retval);
1317 }
1318
1319 int
1320 cs4281_mixer_set_port(void *addr, mixer_ctrl_t *cp)
1321 {
1322 struct cs4281_softc *sc;
1323 int val;
1324
1325 sc = addr;
1326 val = sc->codec_if->vtbl->mixer_set_port(sc->codec_if, cp);
1327 DPRINTFN(3,("mixer_set_port: val=%d\n", val));
1328 return (val);
1329 }
1330
1331 int
1332 cs4281_mixer_get_port(void *addr, mixer_ctrl_t *cp)
1333 {
1334 struct cs4281_softc *sc;
1335
1336 sc = addr;
1337 return (sc->codec_if->vtbl->mixer_get_port(sc->codec_if, cp));
1338 }
1339
1340
1341 int
1342 cs4281_query_devinfo(void *addr, mixer_devinfo_t *dip)
1343 {
1344 struct cs4281_softc *sc;
1345
1346 sc = addr;
1347 return (sc->codec_if->vtbl->query_devinfo(sc->codec_if, dip));
1348 }
1349
1350 void *
1351 cs4281_malloc(void *addr, int direction, size_t size, int pool, int flags)
1352 {
1353 struct cs4281_softc *sc;
1354 struct cs4281_dma *p;
1355 int error;
1356
1357 sc = addr;
1358
1359 p = malloc(sizeof(*p), pool, flags);
1360 if (!p)
1361 return (0);
1362
1363 error = cs4281_allocmem(sc, size, pool, flags, p);
1364
1365 if (error) {
1366 free(p, pool);
1367 return (0);
1368 }
1369
1370 p->next = sc->sc_dmas;
1371 sc->sc_dmas = p;
1372 return (BUFADDR(p));
1373 }
1374
1375
1376
1377 void
1378 cs4281_free(void *addr, void *ptr, int pool)
1379 {
1380 struct cs4281_softc *sc;
1381 struct cs4281_dma **pp, *p;
1382
1383 sc = addr;
1384 for (pp = &sc->sc_dmas; (p = *pp) != NULL; pp = &p->next) {
1385 if (BUFADDR(p) == ptr) {
1386 bus_dmamap_unload(sc->sc_dmatag, p->map);
1387 bus_dmamap_destroy(sc->sc_dmatag, p->map);
1388 bus_dmamem_unmap(sc->sc_dmatag, p->addr, p->size);
1389 bus_dmamem_free(sc->sc_dmatag, p->segs, p->nsegs);
1390 free(p->dum, pool);
1391 *pp = p->next;
1392 free(p, pool);
1393 return;
1394 }
1395 }
1396 }
1397
1398 size_t
1399 cs4281_round_buffersize(void *addr, int direction, size_t size)
1400 {
1401
1402
1403
1404
1405
1406
1407 return (size);
1408 }
1409
1410 paddr_t
1411 cs4281_mappage(void *addr, void *mem, off_t off, int prot)
1412 {
1413 struct cs4281_softc *sc;
1414 struct cs4281_dma *p;
1415
1416 sc = addr;
1417 if (off < 0)
1418 return -1;
1419
1420 for (p = sc->sc_dmas; p && BUFADDR(p) != mem; p = p->next)
1421 ;
1422
1423 if (!p) {
1424 DPRINTF(("cs4281_mappage: bad buffer address\n"));
1425 return (-1);
1426 }
1427
1428 return (bus_dmamem_mmap(sc->sc_dmatag, p->segs, p->nsegs, off, prot,
1429 BUS_DMA_WAITOK));
1430 }
1431
1432
1433 int
1434 cs4281_get_props(void *addr)
1435 {
1436 int retval;
1437
1438 retval = AUDIO_PROP_INDEPENDENT | AUDIO_PROP_FULLDUPLEX;
1439 #ifdef MMAP_READY
1440 retval |= AUDIO_PROP_MMAP;
1441 #endif
1442 return (retval);
1443 }
1444
1445
1446 int
1447 cs4281_attach_codec(void *addr, struct ac97_codec_if *codec_if)
1448 {
1449 struct cs4281_softc *sc;
1450
1451 DPRINTF(("cs4281_attach_codec:\n"));
1452 sc = addr;
1453 sc->codec_if = codec_if;
1454 return (0);
1455 }
1456
1457
1458 int
1459 cs4281_read_codec(void *addr, u_int8_t ac97_addr, u_int16_t *ac97_data)
1460 {
1461 struct cs4281_softc *sc;
1462 u_int32_t acctl;
1463 int n;
1464
1465 sc = addr;
1466
1467 DPRINTFN(5,("read_codec: add=0x%02x ", ac97_addr));
1468
1469
1470
1471
1472 BA0READ4(sc, CS4281_ACSDA);
1473
1474
1475 BA0WRITE4(sc, CS4281_ACCAD, ac97_addr);
1476 BA0WRITE4(sc, CS4281_ACCDA, 0);
1477
1478 acctl = ACCTL_ESYN | ACCTL_VFRM | ACCTL_CRW | ACCTL_DCV;
1479 BA0WRITE4(sc, CS4281_ACCTL, acctl);
1480
1481 if (cs4281_src_wait(sc) < 0) {
1482 printf("%s: AC97 read prob. (DCV!=0) for add=0x%0x\n",
1483 sc->sc_dev.dv_xname, ac97_addr);
1484 return 1;
1485 }
1486
1487
1488 n = 0;
1489 while ((BA0READ4(sc, CS4281_ACSTS) & ACSTS_VSTS) == 0) {
1490 delay(1);
1491 while (++n > 1000) {
1492 printf("%s: AC97 read fail (VSTS==0) for add=0x%0x\n",
1493 sc->sc_dev.dv_xname, ac97_addr);
1494 return 1;
1495 }
1496 }
1497 *ac97_data = BA0READ4(sc, CS4281_ACSDA);
1498 DPRINTFN(5,("data=0x%04x\n", *ac97_data));
1499 return (0);
1500 }
1501
1502 int
1503 cs4281_write_codec(void *addr, u_int8_t ac97_addr, u_int16_t ac97_data)
1504 {
1505 struct cs4281_softc *sc;
1506 u_int32_t acctl;
1507
1508 sc = addr;
1509
1510 DPRINTFN(5,("write_codec: add=0x%02x data=0x%04x\n", ac97_addr, ac97_data));
1511 BA0WRITE4(sc, CS4281_ACCAD, ac97_addr);
1512 BA0WRITE4(sc, CS4281_ACCDA, ac97_data);
1513
1514 acctl = ACCTL_ESYN | ACCTL_VFRM | ACCTL_DCV;
1515 BA0WRITE4(sc, CS4281_ACCTL, acctl);
1516
1517 if (cs4281_src_wait(sc) < 0) {
1518 printf("%s: AC97 write fail (DCV!=0) for add=0x%02x data="
1519 "0x%04x\n", sc->sc_dev.dv_xname, ac97_addr, ac97_data);
1520 return (1);
1521 }
1522 return (0);
1523 }
1524
1525 int
1526 cs4281_allocmem(struct cs4281_softc *sc, size_t size, int pool, int flags,
1527 struct cs4281_dma *p)
1528 {
1529 int error;
1530 size_t align;
1531
1532 align = sc->dma_align;
1533 p->size = sc->dma_size;
1534
1535 p->dum = malloc(size, pool, flags);
1536 if (!p->dum)
1537 return (1);
1538 error = bus_dmamem_alloc(sc->sc_dmatag, p->size, align, 0,
1539 p->segs, sizeof(p->segs)/sizeof(p->segs[0]),
1540 &p->nsegs, BUS_DMA_NOWAIT);
1541 if (error) {
1542 printf("%s: unable to allocate dma. error=%d\n",
1543 sc->sc_dev.dv_xname, error);
1544 return (error);
1545 }
1546
1547 error = bus_dmamem_map(sc->sc_dmatag, p->segs, p->nsegs, p->size,
1548 &p->addr, BUS_DMA_NOWAIT|BUS_DMA_COHERENT);
1549 if (error) {
1550 printf("%s: unable to map dma, error=%d\n",
1551 sc->sc_dev.dv_xname, error);
1552 goto free;
1553 }
1554
1555 error = bus_dmamap_create(sc->sc_dmatag, p->size, 1, p->size,
1556 0, BUS_DMA_NOWAIT, &p->map);
1557 if (error) {
1558 printf("%s: unable to create dma map, error=%d\n",
1559 sc->sc_dev.dv_xname, error);
1560 goto unmap;
1561 }
1562
1563 error = bus_dmamap_load(sc->sc_dmatag, p->map, p->addr, p->size, NULL,
1564 BUS_DMA_NOWAIT);
1565 if (error) {
1566 printf("%s: unable to load dma map, error=%d\n",
1567 sc->sc_dev.dv_xname, error);
1568 goto destroy;
1569 }
1570 return (0);
1571
1572 destroy:
1573 bus_dmamap_destroy(sc->sc_dmatag, p->map);
1574 unmap:
1575 bus_dmamem_unmap(sc->sc_dmatag, p->addr, p->size);
1576 free:
1577 bus_dmamem_free(sc->sc_dmatag, p->segs, p->nsegs);
1578 return (error);
1579 }
1580
1581
1582 int
1583 cs4281_src_wait(sc)
1584 struct cs4281_softc *sc;
1585 {
1586 int n;
1587
1588 n = 0;
1589 while ((BA0READ4(sc, CS4281_ACCTL) & ACCTL_DCV)) {
1590 delay(1000);
1591 if (++n > 1000)
1592 return (-1);
1593 }
1594 return (0);
1595 }