This source file includes following definitions.
- auixp_open
- auixp_close
- auixp_query_encoding
- auixp_commit_settings
- auixp_set_params
- auixp_round_blocksize
- auixp_malloc
- auixp_free
- auixp_getdev
- auixp_set_port
- auixp_get_port
- auixp_query_devinfo
- auixp_round_buffersize
- auixp_get_props
- auixp_link_daisychain
- auixp_allocate_dma_chain
- auixp_program_dma_chain
- auixp_dma_update
- auixp_update_busbusy
- auixp_trigger_output
- auixp_halt_output
- auixp_trigger_input
- auixp_halt_input
- auixp_intr
- auixp_allocmem
- auixp_freemem
- auixp_mappage
- auixp_match
- auixp_attach
- auixp_post_config
- auixp_enable_interrupts
- auixp_disable_interrupts
- auixp_detach
- auixp_attach_codec
- auixp_read_codec
- auixp_write_codec
- auixp_reset_codec
- auixp_flags_codec
- auixp_wait_for_codecs
- auixp_autodetect_codecs
- auixp_disable_dma
- auixp_enable_dma
- auixp_reset_aclink
- auixp_init
- auixp_power
- auixp_powerhook
- auixp_suspend
- auixp_resume
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
45
46
47
48
49
50
51
52
53 #include <sys/types.h>
54 #include <sys/errno.h>
55 #include <sys/param.h>
56 #include <sys/systm.h>
57 #include <sys/malloc.h>
58 #include <sys/device.h>
59 #include <sys/conf.h>
60 #include <sys/exec.h>
61 #include <sys/selinfo.h>
62 #include <sys/audioio.h>
63 #include <sys/queue.h>
64
65 #include <machine/bus.h>
66 #include <machine/intr.h>
67
68 #include <dev/pci/pcidevs.h>
69 #include <dev/pci/pcivar.h>
70
71 #include <dev/audio_if.h>
72 #include <dev/mulaw.h>
73 #include <dev/auconv.h>
74 #include <dev/ic/ac97.h>
75
76 #include <dev/pci/auixpreg.h>
77 #include <dev/pci/auixpvar.h>
78
79
80 #define ALL_CODECS_NOT_READY \
81 (ATI_REG_ISR_CODEC0_NOT_READY | ATI_REG_ISR_CODEC1_NOT_READY |\
82 ATI_REG_ISR_CODEC2_NOT_READY)
83 #define CODEC_CHECK_BITS (ALL_CODECS_NOT_READY|ATI_REG_ISR_NEW_FRAME)
84
85
86 #define PCI_CBIO 0x10
87
88
89 #define KERNADDR(p) ((void *)((p)->addr))
90 #define DMAADDR(p) ((p)->map->dm_segs[0].ds_addr)
91
92 const struct pci_matchid auixp_pci_devices[] = {
93 { PCI_VENDOR_ATI, PCI_PRODUCT_ATI_IXP_AUDIO_200 },
94 { PCI_VENDOR_ATI, PCI_PRODUCT_ATI_IXP_AUDIO_300 },
95 { PCI_VENDOR_ATI, PCI_PRODUCT_ATI_IXP_AUDIO_400 },
96 };
97
98 struct cfdriver auixp_cd = {
99 NULL, "auixp", DV_DULL
100 };
101
102 int auixp_match( struct device *, void *, void *);
103 void auixp_attach(struct device *, struct device *, void *);
104 int auixp_detach(struct device *, int);
105
106 struct cfattach auixp_ca = {
107 sizeof(struct auixp_softc), auixp_match, auixp_attach
108 };
109
110 int auixp_open(void *v, int flags);
111 void auixp_close(void *v);
112 int auixp_query_encoding(void *, struct audio_encoding *);
113 int auixp_set_params(void *, int, int, struct audio_params *,
114 struct audio_params *);
115 int auixp_commit_settings(void *);
116 int auixp_round_blocksize(void *, int);
117 int auixp_trigger_output(void *, void *, void *, int,
118 void (*)(void *), void *, struct audio_params *);
119 int auixp_trigger_input(void *, void *, void *, int,
120 void (*)(void *), void *, struct audio_params *);
121 int auixp_halt_output(void *);
122 int auixp_halt_input(void *);
123 int auixp_set_port(void *, mixer_ctrl_t *);
124 int auixp_get_port(void *, mixer_ctrl_t *);
125 int auixp_query_devinfo(void *, mixer_devinfo_t *);
126 void * auixp_malloc(void *, int, size_t, int, int);
127 void auixp_free(void *, void *, int);
128 int auixp_getdev(void *, struct audio_device *);
129 size_t auixp_round_buffersize(void *, int, size_t);
130 int auixp_get_props(void *);
131 int auixp_intr(void *);
132 int auixp_allocmem(struct auixp_softc *, size_t, size_t,
133 struct auixp_dma *);
134 int auixp_freemem(struct auixp_softc *, struct auixp_dma *);
135 paddr_t auixp_mappage(void *, void *, off_t, int);
136
137
138
139 int auixp_power(struct auixp_softc *, int);
140 #if 0
141 void auixp_powerhook(int, void *);
142 int auixp_suspend(struct auixp_softc *);
143 int auixp_resume(struct auixp_softc *);
144 #endif
145
146
147
148 int auixp_init(struct auixp_softc *);
149 void auixp_autodetect_codecs(struct auixp_softc *);
150 void auixp_post_config(void *);
151
152 void auixp_reset_aclink(struct auixp_softc *);
153 int auixp_attach_codec(void *, struct ac97_codec_if *);
154 int auixp_read_codec(void *, u_int8_t, u_int16_t *);
155 int auixp_write_codec(void *, u_int8_t, u_int16_t);
156 int auixp_wait_for_codecs(struct auixp_softc *, const char *);
157 void auixp_reset_codec(void *);
158 enum ac97_host_flags auixp_flags_codec(void *);
159
160 void auixp_enable_dma(struct auixp_softc *, struct auixp_dma *);
161 void auixp_disable_dma(struct auixp_softc *, struct auixp_dma *);
162 void auixp_enable_interrupts(struct auixp_softc *);
163 void auixp_disable_interrupts(struct auixp_softc *);
164
165 void auixp_link_daisychain(struct auixp_softc *,
166 struct auixp_dma *, struct auixp_dma *, int, int);
167 int auixp_allocate_dma_chain(struct auixp_softc *, struct auixp_dma **);
168 void auixp_program_dma_chain(struct auixp_softc *, struct auixp_dma *);
169 void auixp_dma_update(struct auixp_softc *, struct auixp_dma *);
170 void auixp_update_busbusy(struct auixp_softc *);
171
172 #ifdef DEBUG_AUIXP
173 #define DPRINTF(x) printf x;
174 #else
175 #define DPRINTF(x)
176 #endif
177
178 struct audio_hw_if auixp_hw_if = {
179 auixp_open,
180 auixp_close,
181 NULL,
182 auixp_query_encoding,
183 auixp_set_params,
184 auixp_round_blocksize,
185 auixp_commit_settings,
186 NULL,
187 NULL,
188 NULL,
189 NULL,
190 auixp_halt_output,
191 auixp_halt_input,
192 NULL,
193 auixp_getdev,
194 NULL,
195 auixp_set_port,
196 auixp_get_port,
197 auixp_query_devinfo,
198 auixp_malloc,
199 auixp_free,
200 auixp_round_buffersize,
201 auixp_mappage,
202 auixp_get_props,
203 auixp_trigger_output,
204 auixp_trigger_input
205 };
206
207 int
208 auixp_open(void *v, int flags)
209 {
210
211 return 0;
212 }
213
214 void
215 auixp_close(void *v)
216 {
217 }
218
219 int
220 auixp_query_encoding(void *hdl, struct audio_encoding *aep)
221 {
222 switch (aep->index) {
223 case 0:
224 strlcpy(aep->name, AudioEulinear, sizeof aep->name);
225 aep->encoding = AUDIO_ENCODING_ULINEAR;
226 aep->precision = 8;
227 aep->flags = AUDIO_ENCODINGFLAG_EMULATED;
228 return (0);
229 case 1:
230 strlcpy(aep->name, AudioEmulaw, sizeof aep->name);
231 aep->encoding = AUDIO_ENCODING_ULAW;
232 aep->precision = 8;
233 aep->flags = AUDIO_ENCODINGFLAG_EMULATED;
234 return (0);
235 case 2:
236 strlcpy(aep->name, AudioEalaw, sizeof aep->name);
237 aep->encoding = AUDIO_ENCODING_ALAW;
238 aep->precision = 8;
239 aep->flags = AUDIO_ENCODINGFLAG_EMULATED;
240 return (0);
241 case 3:
242 strlcpy(aep->name, AudioEslinear, sizeof aep->name);
243 aep->encoding = AUDIO_ENCODING_SLINEAR;
244 aep->precision = 8;
245 aep->flags = AUDIO_ENCODINGFLAG_EMULATED;
246 return (0);
247 case 4:
248 strlcpy(aep->name, AudioEslinear_le, sizeof aep->name);
249 aep->encoding = AUDIO_ENCODING_SLINEAR_LE;
250 aep->precision = 16;
251 aep->flags = 0;
252 return (0);
253 case 5:
254 strlcpy(aep->name, AudioEulinear_le, sizeof aep->name);
255 aep->encoding = AUDIO_ENCODING_ULINEAR_LE;
256 aep->precision = 16;
257 aep->flags = AUDIO_ENCODINGFLAG_EMULATED;
258 return (0);
259 case 6:
260 strlcpy(aep->name, AudioEslinear_be, sizeof aep->name);
261 aep->encoding = AUDIO_ENCODING_SLINEAR_BE;
262 aep->precision = 16;
263 aep->flags = AUDIO_ENCODINGFLAG_EMULATED;
264 return (0);
265 case 7:
266 strlcpy(aep->name, AudioEulinear_be, sizeof aep->name);
267 aep->encoding = AUDIO_ENCODING_ULINEAR_BE;
268 aep->precision = 16;
269 aep->flags = AUDIO_ENCODINGFLAG_EMULATED;
270 return (0);
271 default:
272 return (EINVAL);
273 }
274 }
275
276
277
278 int
279 auixp_commit_settings(void *hdl)
280 {
281 struct auixp_codec *co;
282 struct auixp_softc *sc;
283 bus_space_tag_t iot;
284 bus_space_handle_t ioh;
285 struct audio_params *params;
286 u_int32_t value;
287
288
289 co = (struct auixp_codec *) hdl;
290 sc = co->sc;
291 iot = sc->sc_iot;
292 ioh = sc->sc_ioh;
293
294
295 params = &sc->sc_play_params;
296
297
298 value = bus_space_read_4(iot, ioh, ATI_REG_CMD);
299 value &= ~ATI_REG_CMD_INTERLEAVE_IN;
300 if (params->precision <= 16)
301 value |= ATI_REG_CMD_INTERLEAVE_IN;
302 bus_space_write_4(iot, ioh, ATI_REG_CMD, value);
303
304
305 params = &sc->sc_play_params;
306
307 value = bus_space_read_4(iot, ioh, ATI_REG_OUT_DMA_SLOT);
308 value &= ~ATI_REG_OUT_DMA_SLOT_MASK;
309
310
311 switch (params->channels) {
312 case 6:
313 value |= ATI_REG_OUT_DMA_SLOT_BIT(7) |
314 ATI_REG_OUT_DMA_SLOT_BIT(8);
315
316 case 4:
317 value |= ATI_REG_OUT_DMA_SLOT_BIT(6) |
318 ATI_REG_OUT_DMA_SLOT_BIT(9);
319
320 default:
321 value |= ATI_REG_OUT_DMA_SLOT_BIT(3) |
322 ATI_REG_OUT_DMA_SLOT_BIT(4);
323 break;
324 }
325
326 value |= 0x04 << ATI_REG_OUT_DMA_THRESHOLD_SHIFT;
327 bus_space_write_4(iot, ioh, ATI_REG_OUT_DMA_SLOT, value);
328
329
330 value = bus_space_read_4(iot, ioh, ATI_REG_CMD);
331 value &= ~ATI_REG_CMD_INTERLEAVE_OUT;
332 if (params->precision <= 16)
333 value |= ATI_REG_CMD_INTERLEAVE_OUT;
334 bus_space_write_4(iot, ioh, ATI_REG_CMD, value);
335
336
337 value = bus_space_read_4(iot, ioh, ATI_REG_6CH_REORDER);
338 value &= ~ATI_REG_6CH_REORDER_EN;
339 if (params->channels == 6)
340 value |= ATI_REG_6CH_REORDER_EN;
341 bus_space_write_4(iot, ioh, ATI_REG_6CH_REORDER, value);
342
343 if (sc->has_spdif) {
344
345 value = bus_space_read_4(iot, ioh, ATI_REG_CMD);
346 value &= ~ATI_REG_CMD_SPDF_CONFIG_MASK;
347 value |= ATI_REG_CMD_SPDF_CONFIG_34;
348
349
350 value &= ~ATI_REG_CMD_INTERLEAVE_SPDF;
351 if (params->precision <= 16)
352 value |= ATI_REG_CMD_INTERLEAVE_SPDF;
353 bus_space_write_4(iot, ioh, ATI_REG_CMD, value);
354 }
355
356 return 0;
357 }
358
359
360
361 int
362 auixp_set_params(void *hdl, int setmode, int usemode,
363 struct audio_params *play, struct audio_params *rec)
364 {
365 struct auixp_codec *co;
366 struct auixp_softc *sc;
367 int error;
368
369 co = (struct auixp_codec *) hdl;
370 sc = co->sc;
371 if (setmode & AUMODE_PLAY) {
372 play->factor = 1;
373 play->sw_code = NULL;
374 switch(play->encoding) {
375 case AUDIO_ENCODING_ULAW:
376 switch (play->channels) {
377 case 1:
378 play->factor = 4;
379 play->sw_code = mulaw_to_slinear16_mts;
380 break;
381 case 2:
382 play->factor = 2;
383 play->sw_code = mulaw_to_slinear16;
384 break;
385 default:
386 return (EINVAL);
387 }
388 break;
389 case AUDIO_ENCODING_SLINEAR_LE:
390 switch (play->precision) {
391 case 8:
392 switch (play->channels) {
393 case 1:
394 play->factor = 4;
395 play->sw_code = linear8_to_linear16_mts;
396 break;
397 case 2:
398 play->factor = 2;
399 play->sw_code = linear8_to_linear16;
400 break;
401 default:
402 return (EINVAL);
403 }
404 break;
405 case 16:
406 switch (play->channels) {
407 case 1:
408 play->factor = 2;
409 play->sw_code = noswap_bytes_mts;
410 break;
411 case 2:
412 break;
413 default:
414 return (EINVAL);
415 }
416 break;
417 default:
418 return (EINVAL);
419 }
420 break;
421 case AUDIO_ENCODING_ULINEAR_LE:
422 switch (play->precision) {
423 case 8:
424 switch (play->channels) {
425 case 1:
426 play->factor = 4;
427 play->sw_code = ulinear8_to_linear16_mts;
428 break;
429 case 2:
430 play->factor = 2;
431 play->sw_code = ulinear8_to_linear16;
432 break;
433 default:
434 return (EINVAL);
435 }
436 break;
437 case 16:
438 switch (play->channels) {
439 case 1:
440 play->factor = 2;
441 play->sw_code = change_sign16_mts;
442 break;
443 case 2:
444 play->sw_code = change_sign16;
445 break;
446 default:
447 return (EINVAL);
448 }
449 break;
450 default:
451 return (EINVAL);
452 }
453 break;
454 case AUDIO_ENCODING_ALAW:
455 switch (play->channels) {
456 case 1:
457 play->factor = 4;
458 play->sw_code = alaw_to_slinear16_mts;
459 break;
460 case 2:
461 play->factor = 2;
462 play->sw_code = alaw_to_slinear16;
463 break;
464 default:
465 return (EINVAL);
466 }
467 break;
468 case AUDIO_ENCODING_SLINEAR_BE:
469 switch (play->precision) {
470 case 8:
471 switch (play->channels) {
472 case 1:
473 play->factor = 4;
474 play->sw_code = linear8_to_linear16_mts;
475 break;
476 case 2:
477 play->factor = 2;
478 play->sw_code = linear8_to_linear16;
479 break;
480 default:
481 return (EINVAL);
482 }
483 break;
484 case 16:
485 switch (play->channels) {
486 case 1:
487 play->factor = 2;
488 play->sw_code = swap_bytes_mts;
489 break;
490 case 2:
491 play->sw_code = swap_bytes;
492 break;
493 default:
494 return (EINVAL);
495 }
496 break;
497 default:
498 return (EINVAL);
499 }
500 break;
501 case AUDIO_ENCODING_ULINEAR_BE:
502 switch (play->precision) {
503 case 8:
504 switch (play->channels) {
505 case 1:
506 play->factor = 4;
507 play->sw_code = ulinear8_to_linear16_mts;
508 break;
509 case 2:
510 play->factor = 2;
511 play->sw_code = ulinear8_to_linear16;
512 break;
513 default:
514 return (EINVAL);
515 }
516 break;
517 case 16:
518 switch (play->channels) {
519 case 1:
520 play->factor = 2;
521 play->sw_code = change_sign16_swap_bytes_mts;
522 break;
523 case 2:
524 play->sw_code = change_sign16_swap_bytes;
525 break;
526 default:
527 return (EINVAL);
528 }
529 break;
530 default:
531 return (EINVAL);
532 }
533 break;
534 default:
535 return (EINVAL);
536 }
537
538 error = ac97_set_rate(co->codec_if, play, AUMODE_PLAY);
539 if (error)
540 return (error);
541 }
542
543 if (setmode & AUMODE_RECORD) {
544 rec->factor = 1;
545 rec->sw_code = 0;
546 switch(rec->encoding) {
547 case AUDIO_ENCODING_ULAW:
548 rec->sw_code = ulinear8_to_mulaw;
549 break;
550 case AUDIO_ENCODING_SLINEAR_LE:
551 if (rec->precision == 8)
552 rec->sw_code = change_sign8;
553 break;
554 case AUDIO_ENCODING_ULINEAR_LE:
555 if (rec->precision == 16)
556 rec->sw_code = change_sign16;
557 break;
558 case AUDIO_ENCODING_ALAW:
559 rec->sw_code = ulinear8_to_alaw;
560 break;
561 case AUDIO_ENCODING_SLINEAR_BE:
562 if (rec->precision == 16)
563 rec->sw_code = swap_bytes;
564 else
565 rec->sw_code = change_sign8;
566 break;
567 case AUDIO_ENCODING_ULINEAR_BE:
568 if (rec->precision == 16)
569 rec->sw_code = swap_bytes_change_sign16;
570 break;
571 default:
572 return (EINVAL);
573 }
574
575 error = ac97_set_rate(co->codec_if, rec, AUMODE_RECORD);
576 if (error)
577 return (error);
578 }
579
580 return (0);
581 }
582
583
584
585 int
586 auixp_round_blocksize(void *v, int blk)
587 {
588
589 blk = (blk + 0x1f) & ~0x1f;
590
591 if (blk > 0x10000)
592 blk = 0x10000;
593
594 return blk;
595 }
596
597
598
599
600
601
602
603 void *
604 auixp_malloc(void *hdl, int direction, size_t size, int pool, int flags)
605 {
606 struct auixp_codec *co;
607 struct auixp_softc *sc;
608 struct auixp_dma *dma;
609 int error;
610
611 co = (struct auixp_codec *) hdl;
612 sc = co->sc;
613
614 dma = malloc(sizeof(*dma), pool, flags);
615 if (!dma)
616 return NULL;
617
618
619 error = auixp_allocmem(sc, size, 16, dma);
620 if (error) {
621 free(dma, pool);
622 printf("%s: auixp_malloc: not enough memory\n",
623 sc->sc_dev.dv_xname);
624 return NULL;
625 }
626 SLIST_INSERT_HEAD(&sc->sc_dma_list, dma, dma_chain);
627
628 DPRINTF(("auixp_malloc: returning kern %p, hw 0x%08x for %d bytes "
629 "in %d segs\n", KERNADDR(dma), (u_int32_t) DMAADDR(dma), dma->size,
630 dma->nsegs)
631 );
632
633 return KERNADDR(dma);
634 }
635
636
637
638
639
640 void
641 auixp_free(void *hdl, void *addr, int pool)
642 {
643 struct auixp_codec *co;
644 struct auixp_softc *sc;
645 struct auixp_dma *dma;
646
647 co = (struct auixp_codec *) hdl;
648 sc = co->sc;
649 SLIST_FOREACH(dma, &sc->sc_dma_list, dma_chain) {
650 if (KERNADDR(dma) == addr) {
651 SLIST_REMOVE(&sc->sc_dma_list, dma, auixp_dma,
652 dma_chain);
653 auixp_freemem(sc, dma);
654 free(dma, pool);
655 return;
656 }
657 }
658 }
659
660 int
661 auixp_getdev(void *v, struct audio_device *adp)
662 {
663 struct auixp_softc *sc = v;
664 *adp = sc->sc_audev;
665 return 0;
666 }
667
668
669 int
670 auixp_set_port(void *hdl, mixer_ctrl_t *mc)
671 {
672 struct auixp_codec *co;
673
674 co = (struct auixp_codec *) hdl;
675 return co->codec_if->vtbl->mixer_set_port(co->codec_if, mc);
676 }
677
678
679
680 int
681 auixp_get_port(void *hdl, mixer_ctrl_t *mc)
682 {
683 struct auixp_codec *co;
684
685 co = (struct auixp_codec *) hdl;
686 return co->codec_if->vtbl->mixer_get_port(co->codec_if, mc);
687 }
688
689
690 int
691 auixp_query_devinfo(void *hdl, mixer_devinfo_t *di)
692 {
693 struct auixp_codec *co;
694
695 co = (struct auixp_codec *) hdl;
696 return co->codec_if->vtbl->query_devinfo(co->codec_if, di);
697 }
698
699
700 size_t
701 auixp_round_buffersize(void *hdl, int direction, size_t bufsize)
702 {
703
704
705 return bufsize;
706 }
707
708
709 int
710 auixp_get_props(void *hdl)
711 {
712
713 return AUDIO_PROP_MMAP | AUDIO_PROP_INDEPENDENT | AUDIO_PROP_FULLDUPLEX;
714 }
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731 void
732 auixp_link_daisychain(struct auixp_softc *sc,
733 struct auixp_dma *c_dma, struct auixp_dma *s_dma,
734 int blksize, int blocks)
735 {
736 atiixp_dma_desc_t *caddr_v, *next_caddr_v;
737 u_int32_t caddr_p, next_caddr_p, saddr_p;
738 int i;
739
740
741 auixp_disable_dma(sc, c_dma);
742
743
744 caddr_v = KERNADDR(c_dma);
745 caddr_p = DMAADDR(c_dma);
746 saddr_p = DMAADDR(s_dma);
747
748
749 for (i = 0; i < blocks; i++) {
750
751 bzero(caddr_v, sizeof(atiixp_dma_desc_t));
752
753
754 next_caddr_v = caddr_v + 1;
755 next_caddr_p = caddr_p + sizeof(atiixp_dma_desc_t);
756
757 if (i == blocks-1) {
758 next_caddr_v = KERNADDR(c_dma);
759 next_caddr_p = DMAADDR(c_dma);
760 }
761
762
763 caddr_v->addr = htole32(saddr_p);
764 caddr_v->status = htole16(0);
765 caddr_v->size = htole16((blksize >> 2));
766 caddr_v->next = htole32(next_caddr_p);
767
768
769 saddr_p += blksize;
770 caddr_v = next_caddr_v;
771 caddr_p = next_caddr_p;
772 }
773 }
774
775
776 int
777 auixp_allocate_dma_chain(struct auixp_softc *sc, struct auixp_dma **dmap)
778 {
779 struct auixp_dma *dma;
780 int error;
781
782
783 *dmap = NULL;
784 dma = malloc(sizeof(*dma), M_DEVBUF, M_NOWAIT);
785 if (!dma)
786 return ENOMEM;
787 bzero(dma, sizeof(*dma));
788
789
790 error = auixp_allocmem(sc, DMA_DESC_CHAIN * sizeof(atiixp_dma_desc_t),
791 16, dma);
792 if (error) {
793 printf("%s: can't malloc dma descriptor chain\n",
794 sc->sc_dev.dv_xname);
795 free(dma, M_DEVBUF);
796 return ENOMEM;
797 }
798
799
800 dma->intr = NULL;
801 dma->intrarg = NULL;
802
803 *dmap = dma;
804 return 0;
805 }
806
807
808
809 void
810 auixp_program_dma_chain(struct auixp_softc *sc, struct auixp_dma *dma)
811 {
812 bus_space_tag_t iot;
813 bus_space_handle_t ioh;
814 u_int32_t value;
815
816 iot = sc->sc_iot;
817 ioh = sc->sc_ioh;
818
819
820 value = DMAADDR(dma);
821 value = value | ATI_REG_LINKPTR_EN;
822
823
824 bus_space_write_4(iot, ioh, dma->linkptr, 0);
825
826
827 auixp_disable_dma(sc, dma);
828 auixp_enable_dma(sc, dma);
829
830
831 bus_space_write_4(iot, ioh, dma->linkptr, value);
832 }
833
834
835
836 void
837 auixp_dma_update(struct auixp_softc *sc, struct auixp_dma *dma)
838 {
839
840
841 if (!dma)
842 panic("auixp: update: dma = NULL");
843 if (!dma->intr)
844 panic("auixp: update: dma->intr = NULL");
845
846
847 (*dma->intr)(dma->intrarg);
848 }
849
850
851
852
853
854
855 void
856 auixp_update_busbusy(struct auixp_softc *sc)
857 {
858 bus_space_tag_t iot;
859 bus_space_handle_t ioh;
860 u_int32_t value;
861 int running;
862
863 iot = sc->sc_iot;
864 ioh = sc->sc_ioh;
865
866 value = bus_space_read_4(iot, ioh, ATI_REG_IER);
867 value &= ~ATI_REG_IER_SET_BUS_BUSY;
868
869 running = ((sc->sc_output_dma->running) || (sc->sc_input_dma->running));
870 if (running)
871 value |= ATI_REG_IER_SET_BUS_BUSY;
872
873 bus_space_write_4(iot, ioh, ATI_REG_IER, value);
874
875 }
876
877
878
879
880
881
882
883
884 int
885 auixp_trigger_output(void *hdl, void *start, void *end, int blksize,
886 void (*intr)(void *), void *intrarg, struct audio_params *param)
887 {
888 struct auixp_codec *co;
889 struct auixp_softc *sc;
890 struct auixp_dma *chain_dma;
891 struct auixp_dma *sound_dma;
892 u_int32_t blocks;
893
894 co = (struct auixp_codec *) hdl;
895 sc = co->sc;
896 chain_dma = sc->sc_output_dma;
897
898 chain_dma->intr = intr;
899 chain_dma->intrarg = intrarg;
900
901
902
903
904
905
906
907
908 blocks = (size_t) (((caddr_t) end) - ((caddr_t) start)) / blksize;
909
910
911 SLIST_FOREACH(sound_dma, &sc->sc_dma_list, dma_chain) {
912 if (KERNADDR(sound_dma) == start)
913 break;
914 }
915
916
917 if (!sound_dma) {
918 printf("%s: auixp_trigger_output: bad sound addr %p\n",
919 sc->sc_dev.dv_xname, start);
920 return EINVAL;
921 }
922
923
924 auixp_link_daisychain(sc, chain_dma, sound_dma, blksize, blocks);
925 auixp_program_dma_chain(sc, chain_dma);
926
927
928 chain_dma->running = 1;
929
930
931 auixp_update_busbusy(sc);
932
933
934 return 0;
935 }
936
937
938
939 int
940 auixp_halt_output(void *hdl)
941 {
942 struct auixp_codec *co;
943 struct auixp_softc *sc;
944 struct auixp_dma *dma;
945
946 co = (struct auixp_codec *) hdl;
947 sc = co->sc;
948 dma = sc->sc_output_dma;
949 auixp_disable_dma(sc, dma);
950
951 dma->running = 0;
952 auixp_update_busbusy(sc);
953
954 return 0;
955 }
956
957
958
959 int
960 auixp_trigger_input(void *hdl, void *start, void *end, int blksize,
961 void (*intr)(void *), void *intrarg, struct audio_params *param)
962 {
963 struct auixp_codec *co;
964 struct auixp_softc *sc;
965 struct auixp_dma *chain_dma;
966 struct auixp_dma *sound_dma;
967 u_int32_t blocks;
968
969 co = (struct auixp_codec *) hdl;
970 sc = co->sc;
971 chain_dma = sc->sc_input_dma;
972
973 chain_dma->intr = intr;
974 chain_dma->intrarg = intrarg;
975
976
977
978
979
980
981
982
983 blocks = (size_t) (((caddr_t) end) - ((caddr_t) start)) / blksize;
984
985
986 SLIST_FOREACH(sound_dma, &sc->sc_dma_list, dma_chain) {
987 if (KERNADDR(sound_dma) == start)
988 break;
989 }
990
991
992 if (!sound_dma) {
993 printf("%s: auixp_trigger_input: bad sound addr %p\n",
994 sc->sc_dev.dv_xname, start);
995 return EINVAL;
996 }
997
998
999 auixp_link_daisychain(sc, chain_dma, sound_dma, blksize, blocks);
1000 auixp_program_dma_chain(sc, chain_dma);
1001
1002
1003 chain_dma->running = 1;
1004
1005
1006 auixp_update_busbusy(sc);
1007
1008
1009 return 0;
1010 }
1011
1012
1013
1014 int
1015 auixp_halt_input(void *hdl)
1016 {
1017 struct auixp_codec *co;
1018 struct auixp_softc *sc;
1019 struct auixp_dma *dma;
1020
1021 co = (struct auixp_codec *) hdl;
1022 sc = co->sc;
1023 dma = sc->sc_input_dma;
1024 auixp_disable_dma(sc, dma);
1025
1026 dma->running = 0;
1027 auixp_update_busbusy(sc);
1028
1029 return 0;
1030 }
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041 int
1042 auixp_intr(void *softc)
1043 {
1044 struct auixp_softc *sc;
1045 bus_space_tag_t iot;
1046 bus_space_handle_t ioh;
1047 u_int32_t status, enable, detected_codecs;
1048 int ret;
1049
1050 sc = softc;
1051 iot = sc->sc_iot;
1052 ioh = sc->sc_ioh;
1053 ret = 0;
1054
1055 status = bus_space_read_4(iot, ioh, ATI_REG_ISR);
1056
1057 if (status == 0)
1058 return 0;
1059
1060 DPRINTF(("%s: (status = %x)\n", sc->sc_dev.dv_xname, status));
1061
1062
1063 if (status & ATI_REG_ISR_IN_STATUS) {
1064 ret++; DPRINTF(("IN_STATUS\n"));
1065 auixp_dma_update(sc, sc->sc_input_dma);
1066 }
1067 if (status & ATI_REG_ISR_OUT_STATUS) {
1068 ret++; DPRINTF(("OUT_STATUS\n"));
1069 auixp_dma_update(sc, sc->sc_output_dma);
1070 }
1071
1072
1073
1074 if (status & ATI_REG_ISR_IN_XRUN) {
1075 ret++; DPRINTF(("IN_XRUN\n"));
1076
1077 }
1078 if (status & ATI_REG_ISR_OUT_XRUN) {
1079 ret++; DPRINTF(("OUT_XRUN\n"));
1080
1081 }
1082
1083
1084 if (status & CODEC_CHECK_BITS) {
1085 ret++;
1086
1087 detected_codecs = status & CODEC_CHECK_BITS;
1088 sc->sc_codec_not_ready_bits |= detected_codecs;
1089
1090
1091 enable = bus_space_read_4(iot, ioh, ATI_REG_IER);
1092 enable &= ~detected_codecs;
1093 bus_space_write_4(iot, ioh, ATI_REG_IER, enable);
1094 }
1095
1096
1097 bus_space_write_4(iot, ioh, ATI_REG_ISR, status);
1098
1099 return ret;
1100 }
1101
1102
1103
1104 int
1105 auixp_allocmem(struct auixp_softc *sc, size_t size,
1106 size_t align, struct auixp_dma *dma)
1107 {
1108 int error;
1109
1110
1111 dma->size = size;
1112
1113
1114 error = bus_dmamem_alloc(sc->sc_dmat, dma->size, align, 0,
1115 dma->segs, sizeof(dma->segs) / sizeof(dma->segs[0]), &dma->nsegs,
1116 BUS_DMA_NOWAIT);
1117 if (error)
1118 return error;
1119
1120
1121
1122
1123
1124 error = bus_dmamem_map(sc->sc_dmat, dma->segs, dma->nsegs, dma->size,
1125 &dma->addr, BUS_DMA_NOWAIT | BUS_DMA_COHERENT);
1126 if (error)
1127 goto free;
1128
1129
1130 error = bus_dmamap_create(sc->sc_dmat, dma->size, 1, dma->size, 0,
1131 BUS_DMA_NOWAIT, &dma->map);
1132 if (error)
1133 goto unmap;
1134
1135
1136
1137
1138
1139 error = bus_dmamap_load(sc->sc_dmat, dma->map, dma->addr, dma->size, NULL,
1140 BUS_DMA_NOWAIT);
1141 if (error)
1142 goto destroy;
1143
1144 return 0;
1145
1146 destroy:
1147 bus_dmamap_destroy(sc->sc_dmat, dma->map);
1148 unmap:
1149 bus_dmamem_unmap(sc->sc_dmat, dma->addr, dma->size);
1150 free:
1151 bus_dmamem_free(sc->sc_dmat, dma->segs, dma->nsegs);
1152
1153 return error;
1154 }
1155
1156
1157
1158 int
1159 auixp_freemem(struct auixp_softc *sc, struct auixp_dma *p)
1160 {
1161
1162 bus_dmamap_unload(sc->sc_dmat, p->map);
1163 bus_dmamap_destroy(sc->sc_dmat, p->map);
1164 bus_dmamem_unmap(sc->sc_dmat, p->addr, p->size);
1165 bus_dmamem_free(sc->sc_dmat, p->segs, p->nsegs);
1166
1167 return 0;
1168 }
1169
1170
1171
1172 paddr_t
1173 auixp_mappage(void *hdl, void *mem, off_t off, int prot)
1174 {
1175 struct auixp_codec *co;
1176 struct auixp_softc *sc;
1177 struct auixp_dma *p;
1178
1179 co = (struct auixp_codec *) hdl;
1180 sc = co->sc;
1181
1182 if (off < 0)
1183 return -1;
1184
1185
1186 SLIST_FOREACH(p, &sc->sc_dma_list, dma_chain) {
1187 if (KERNADDR(p) == mem)
1188 break;
1189 }
1190
1191
1192 if (!p)
1193 return -1;
1194
1195
1196 return bus_dmamem_mmap(sc->sc_dmat, p->segs, p->nsegs,
1197 off, prot, BUS_DMA_WAITOK);
1198 }
1199
1200 int
1201 auixp_match(struct device *dev, void *match, void *aux)
1202 {
1203 return (pci_matchbyid((struct pci_attach_args *)aux, auixp_pci_devices,
1204 sizeof(auixp_pci_devices)/sizeof(auixp_pci_devices[0])));
1205 }
1206
1207 void
1208 auixp_attach(struct device *parent, struct device *self, void *aux)
1209 {
1210 struct auixp_softc *sc;
1211 struct pci_attach_args *pa;
1212 pcitag_t tag;
1213 pci_chipset_tag_t pc;
1214 pci_intr_handle_t ih;
1215 const char *intrstr;
1216 int len;
1217
1218 sc = (struct auixp_softc *)self;
1219 pa = (struct pci_attach_args *)aux;
1220 tag = pa->pa_tag;
1221 pc = pa->pa_pc;
1222
1223
1224 if (pci_mapreg_map(pa, PCI_CBIO, PCI_MAPREG_TYPE_MEM, 0,
1225 &sc->sc_iot, &sc->sc_ioh, &sc->sc_iob, &sc->sc_ios, 0)) {
1226 printf(": can't map memory space\n");
1227 return;
1228 }
1229
1230
1231 sc->sc_tag = tag;
1232 sc->sc_pct = pc;
1233 sc->sc_dmat = pa->pa_dmat;
1234 SLIST_INIT(&sc->sc_dma_list);
1235
1236
1237 auixp_allocate_dma_chain(sc, &sc->sc_output_dma);
1238 auixp_allocate_dma_chain(sc, &sc->sc_input_dma);
1239
1240
1241 if (!sc->sc_output_dma || !sc->sc_input_dma)
1242 return;
1243
1244
1245
1246
1247 sc->sc_output_dma->linkptr = ATI_REG_OUT_DMA_LINKPTR;
1248 sc->sc_output_dma->dma_enable_bit = ATI_REG_CMD_OUT_DMA_EN |
1249 ATI_REG_CMD_SEND_EN;
1250
1251 if (sc->has_spdif)
1252 sc->sc_output_dma->dma_enable_bit |= ATI_REG_CMD_SPDF_OUT_EN;
1253
1254
1255 sc->sc_input_dma->linkptr = ATI_REG_IN_DMA_LINKPTR;
1256 sc->sc_input_dma->dma_enable_bit = ATI_REG_CMD_IN_DMA_EN |
1257 ATI_REG_CMD_RECEIVE_EN;
1258
1259 #if 0
1260
1261 auixp_program_dma_chain(sc, sc->sc_output_dma);
1262 auixp_program_dma_chain(sc, sc->sc_input_dma);
1263 #endif
1264
1265 if (pci_intr_map(pa, &ih)) {
1266 printf(": can't map interrupt\n");
1267 return;
1268 }
1269 intrstr = pci_intr_string(pc, ih);
1270 sc->sc_ih = pci_intr_establish(pc, ih, IPL_AUDIO, auixp_intr, sc,
1271 sc->sc_dev.dv_xname);
1272 if (sc->sc_ih == NULL) {
1273 printf(": can't establish interrupt");
1274 if (intrstr != NULL)
1275 printf(" at %s", intrstr);
1276 printf("\n");
1277 return;
1278 }
1279 printf(": %s\n", intrstr);
1280
1281 strlcpy(sc->sc_audev.name, "ATI IXP AC97", sizeof sc->sc_audev.name);
1282 snprintf(sc->sc_audev.version, sizeof sc->sc_audev.version, "0x%02x",
1283 PCI_REVISION(pa->pa_class));
1284 strlcpy(sc->sc_audev.config, sc->sc_dev.dv_xname,
1285 sizeof sc->sc_audev.config);
1286
1287
1288 auixp_power(sc, PCI_PMCSR_STATE_D0);
1289
1290
1291 if (auixp_init(sc) == -1) {
1292 printf("%s: auixp_attach: unable to initialize the card\n",
1293 sc->sc_dev.dv_xname);
1294 return;
1295 }
1296
1297
1298
1299 len = 1;
1300 #ifdef notyet
1301
1302 len = sizeof(u_int16_t) * (ESA_REV_B_CODE_MEMORY_LENGTH
1303 + ESA_REV_B_DATA_MEMORY_LENGTH + 1);
1304 sc->savemem = (u_int16_t *)malloc(len, M_DEVBUF, M_NOWAIT | M_ZERO);
1305 if (sc->savemem == NULL) {
1306 printf("%s: unable to allocate suspend buffer\n",
1307 sc->sc_dev.dv_xname);
1308 return;
1309 }
1310
1311 sc->powerhook = powerhook_establish(auixp_powerhook, sc);
1312 if (sc->powerhook == NULL)
1313 printf("%s: WARNING: unable to establish powerhook\n",
1314 sc->sc_dev.dv_xname);
1315
1316 #endif
1317
1318
1319
1320
1321
1322 mountroothook_establish(auixp_post_config, self);
1323 }
1324
1325
1326 void
1327 auixp_post_config(void *self)
1328 {
1329 struct auixp_softc *sc;
1330 struct auixp_codec *codec;
1331 int codec_nr;
1332
1333 sc = (struct auixp_softc *)self;
1334
1335 auixp_autodetect_codecs(sc);
1336
1337 #if notyet
1338
1339 sc->has_4ch = AC97_IS_4CH(codec->codec_if);
1340 sc->has_6ch = AC97_IS_6CH(codec->codec_if);
1341 sc->is_fixed = AC97_IS_FIXED_RATE(codec->codec_if);
1342 sc->has_spdif = AC97_HAS_SPDIF(codec->codec_if);
1343 #endif
1344
1345
1346 for (codec_nr = 0; codec_nr < ATI_IXP_CODECS; codec_nr++) {
1347 codec = &sc->sc_codec[codec_nr];
1348 if (codec->present)
1349 audio_attach_mi(&auixp_hw_if, codec, &sc->sc_dev);
1350 }
1351
1352
1353 auixp_enable_interrupts(sc);
1354 }
1355
1356 void
1357 auixp_enable_interrupts(struct auixp_softc *sc)
1358 {
1359 bus_space_tag_t iot;
1360 bus_space_handle_t ioh;
1361 u_int32_t value;
1362
1363 iot = sc->sc_iot;
1364 ioh = sc->sc_ioh;
1365
1366 bus_space_write_4(iot, ioh, ATI_REG_ISR, 0xffffffff);
1367
1368
1369 value = bus_space_read_4(iot, ioh, ATI_REG_IER);
1370
1371 value |= ATI_REG_IER_IO_STATUS_EN;
1372 #ifdef notyet
1373 value |= ATI_REG_IER_IN_XRUN_EN;
1374 value |= ATI_REG_IER_OUT_XRUN_EN;
1375
1376 value |= ATI_REG_IER_SPDIF_XRUN_EN;
1377 value |= ATI_REG_IER_SPDF_STATUS_EN;
1378 #endif
1379
1380 bus_space_write_4(iot, ioh, ATI_REG_IER, value);
1381 }
1382
1383 void
1384 auixp_disable_interrupts(struct auixp_softc *sc)
1385 {
1386 bus_space_tag_t iot;
1387 bus_space_handle_t ioh;
1388
1389 iot = sc->sc_iot;
1390 ioh = sc->sc_ioh;
1391
1392 bus_space_write_4(iot, ioh, ATI_REG_IER, 0);
1393
1394
1395 bus_space_write_4(iot, ioh, ATI_REG_ISR, 0xffffffff);
1396 }
1397
1398
1399 int
1400 auixp_detach(struct device *self, int flags)
1401 {
1402 struct auixp_softc *sc;
1403
1404 sc = (struct auixp_softc *)self;
1405
1406
1407
1408
1409
1410 auixp_disable_interrupts(sc);
1411
1412
1413 config_detach(&sc->sc_dev, flags);
1414
1415 if (sc->sc_ih != NULL)
1416 pci_intr_disestablish(sc->sc_pct, sc->sc_ih);
1417 if (sc->sc_ios)
1418 bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios);
1419
1420 if (sc->savemem)
1421 free(sc->savemem, M_DEVBUF);
1422
1423 return 0;
1424 }
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436 int
1437 auixp_attach_codec(void *aux, struct ac97_codec_if *codec_if)
1438 {
1439 struct auixp_codec *ixp_codec;
1440
1441 ixp_codec = aux;
1442 ixp_codec->codec_if = codec_if;
1443 ixp_codec->present = 1;
1444
1445 return 0;
1446 }
1447
1448 int
1449 auixp_read_codec(void *aux, u_int8_t reg, u_int16_t *result)
1450 {
1451 struct auixp_codec *co;
1452 struct auixp_softc *sc;
1453 bus_space_tag_t iot;
1454 bus_space_handle_t ioh;
1455 u_int32_t data;
1456 int timeout;
1457
1458 co = aux;
1459 sc = co->sc;
1460 iot = sc->sc_iot;
1461 ioh = sc->sc_ioh;
1462 if (auixp_wait_for_codecs(sc, "read_codec"))
1463 return 0xffff;
1464
1465
1466 data = (reg << ATI_REG_PHYS_OUT_ADDR_SHIFT) |
1467 ATI_REG_PHYS_OUT_ADDR_EN |
1468 ATI_REG_PHYS_OUT_RW |
1469 co->codec_nr;
1470
1471 bus_space_write_4(iot, ioh, ATI_REG_PHYS_OUT_ADDR, data);
1472
1473 if (auixp_wait_for_codecs(sc, "read_codec"))
1474 return 0xffff;
1475
1476
1477 timeout = 500;
1478 do {
1479 data = bus_space_read_4(iot, ioh, ATI_REG_PHYS_IN_ADDR);
1480 if (data & ATI_REG_PHYS_IN_READ_FLAG) {
1481 DPRINTF(("read ac'97 codec reg 0x%x = 0x%08x\n",
1482 reg, data >> ATI_REG_PHYS_IN_DATA_SHIFT));
1483 *result = data >> ATI_REG_PHYS_IN_DATA_SHIFT;
1484 return 0;
1485 }
1486 DELAY(2);
1487 timeout--;
1488 } while (timeout > 0);
1489
1490 if (reg < 0x7c)
1491 printf("%s: codec read timeout! (reg %x)\n",
1492 sc->sc_dev.dv_xname, reg);
1493
1494 return 0xffff;
1495 }
1496
1497 int
1498 auixp_write_codec(void *aux, u_int8_t reg, u_int16_t data)
1499 {
1500 struct auixp_codec *co;
1501 struct auixp_softc *sc;
1502 bus_space_tag_t iot;
1503 bus_space_handle_t ioh;
1504 u_int32_t value;
1505
1506 DPRINTF(("write ac'97 codec reg 0x%x = 0x%08x\n", reg, data));
1507 co = aux;
1508 sc = co->sc;
1509 iot = sc->sc_iot;
1510 ioh = sc->sc_ioh;
1511 if (auixp_wait_for_codecs(sc, "write_codec"))
1512 return -1;
1513
1514
1515 value = (((u_int32_t) data) << ATI_REG_PHYS_OUT_DATA_SHIFT) |
1516 (((u_int32_t) reg) << ATI_REG_PHYS_OUT_ADDR_SHIFT) |
1517 ATI_REG_PHYS_OUT_ADDR_EN |
1518 co->codec_nr;
1519
1520 bus_space_write_4(iot, ioh, ATI_REG_PHYS_OUT_ADDR, value);
1521
1522 return 0;
1523 }
1524
1525 void
1526 auixp_reset_codec(void *aux)
1527 {
1528
1529
1530 }
1531
1532 enum ac97_host_flags
1533 auixp_flags_codec(void *aux)
1534 {
1535 struct auixp_codec *ixp_codec;
1536
1537 ixp_codec = aux;
1538 return ixp_codec->codec_flags;
1539 }
1540
1541 int
1542 auixp_wait_for_codecs(struct auixp_softc *sc, const char *func)
1543 {
1544 bus_space_tag_t iot;
1545 bus_space_handle_t ioh;
1546 u_int32_t value;
1547 int timeout;
1548
1549 iot = sc->sc_iot;
1550 ioh = sc->sc_ioh;
1551
1552 timeout = 500;
1553 do {
1554 value = bus_space_read_4(iot, ioh, ATI_REG_PHYS_OUT_ADDR);
1555 if ((value & ATI_REG_PHYS_OUT_ADDR_EN) == 0)
1556 return 0;
1557
1558 DELAY(2);
1559 timeout--;
1560 } while (timeout > 0);
1561
1562 printf("%s: %s: timed out\n", func, sc->sc_dev.dv_xname);
1563 return -1;
1564 }
1565
1566 void
1567 auixp_autodetect_codecs(struct auixp_softc *sc)
1568 {
1569 bus_space_tag_t iot;
1570 bus_space_handle_t ioh;
1571 pcireg_t subdev;
1572 struct auixp_codec *codec;
1573 int timeout, codec_nr;
1574
1575 iot = sc->sc_iot;
1576 ioh = sc->sc_ioh;
1577 subdev = pci_conf_read(sc->sc_pct, sc->sc_tag, PCI_SUBSYS_ID_REG);
1578
1579
1580 sc->sc_codec_not_ready_bits = 0;
1581 sc->sc_num_codecs = 0;
1582
1583
1584 bus_space_write_4(iot, ioh, ATI_REG_IER, CODEC_CHECK_BITS);
1585
1586
1587 timeout = 100;
1588
1589 while (timeout > 0) {
1590 DELAY(1000);
1591 if (sc->sc_codec_not_ready_bits)
1592 break;
1593 timeout--;
1594 }
1595
1596 if (timeout == 0)
1597 printf("%s: WARNING: timeout during codec detection; "
1598 "codecs might be present but haven't interrupted\n",
1599 sc->sc_dev.dv_xname);
1600
1601
1602 auixp_disable_interrupts(sc);
1603
1604
1605 for (codec_nr = 0; codec_nr < ATI_IXP_CODECS; codec_nr++) {
1606 codec = &sc->sc_codec[codec_nr];
1607 bzero(codec, sizeof(struct auixp_codec));
1608
1609 codec->sc = sc;
1610 codec->codec_nr = codec_nr;
1611 codec->present = 0;
1612
1613 codec->host_if.arg = codec;
1614 codec->host_if.attach = auixp_attach_codec;
1615 codec->host_if.read = auixp_read_codec;
1616 codec->host_if.write = auixp_write_codec;
1617 codec->host_if.reset = auixp_reset_codec;
1618 codec->host_if.flags = auixp_flags_codec;
1619 switch (subdev) {
1620 case 0x1311462:
1621 codec->codec_flags = AC97_HOST_DONT_ENABLE_SPDIF;
1622 break;
1623 }
1624 }
1625
1626 if (!(sc->sc_codec_not_ready_bits & ATI_REG_ISR_CODEC0_NOT_READY)) {
1627
1628 DPRINTF(("auixp : YAY! codec 0 present!\n"));
1629 if (ac97_attach(&sc->sc_codec[0].host_if) == 0)
1630 sc->sc_num_codecs++;
1631 }
1632
1633 #ifdef notyet
1634 if (!(sc->sc_codec_not_ready_bits & ATI_REG_ISR_CODEC1_NOT_READY)) {
1635
1636 DPRINTF(("auixp : YAY! codec 1 present!\n"));
1637 if (ac97_attach(&sc->sc_codec[1].host_if, &sc->sc_dev) == 0)
1638 sc->sc_num_codecs++;
1639 }
1640
1641 if (!(sc->sc_codec_not_ready_bits & ATI_REG_ISR_CODEC2_NOT_READY)) {
1642
1643 DPRINTF(("auixp : YAY! codec 2 present!\n"));
1644 if (ac97_attach(&sc->sc_codec[2].host_if, &sc->sc_dev) == 0)
1645 sc->sc_num_codecs++;
1646 }
1647 #endif
1648
1649 if (sc->sc_num_codecs == 0) {
1650 printf("%s: no codecs detected or initialised\n",
1651 sc->sc_dev.dv_xname);
1652 return;
1653 }
1654 }
1655
1656 void
1657 auixp_disable_dma(struct auixp_softc *sc, struct auixp_dma *dma)
1658 {
1659 bus_space_tag_t iot;
1660 bus_space_handle_t ioh;
1661 u_int32_t value;
1662
1663 iot = sc->sc_iot;
1664 ioh = sc->sc_ioh;
1665
1666 value = bus_space_read_4(iot, ioh, ATI_REG_CMD);
1667 if (value & dma->dma_enable_bit) {
1668 value &= ~dma->dma_enable_bit;
1669 bus_space_write_4(iot, ioh, ATI_REG_CMD, value);
1670 }
1671 }
1672
1673 void
1674 auixp_enable_dma(struct auixp_softc *sc, struct auixp_dma *dma)
1675 {
1676 bus_space_tag_t iot;
1677 bus_space_handle_t ioh;
1678 u_int32_t value;
1679
1680 iot = sc->sc_iot;
1681 ioh = sc->sc_ioh;
1682
1683 value = bus_space_read_4(iot, ioh, ATI_REG_CMD);
1684 if (!(value & dma->dma_enable_bit)) {
1685 value |= dma->dma_enable_bit;
1686 bus_space_write_4(iot, ioh, ATI_REG_CMD, value);
1687 }
1688 }
1689
1690 void
1691 auixp_reset_aclink(struct auixp_softc *sc)
1692 {
1693 bus_space_tag_t iot;
1694 bus_space_handle_t ioh;
1695 u_int32_t value, timeout;
1696
1697 iot = sc->sc_iot;
1698 ioh = sc->sc_ioh;
1699
1700
1701 value = bus_space_read_4(iot, ioh, ATI_REG_CMD);
1702 if (value & ATI_REG_CMD_POWERDOWN) {
1703 printf("%s: powering up\n", sc->sc_dev.dv_xname);
1704
1705
1706 value &= ~ATI_REG_CMD_POWERDOWN;
1707 bus_space_write_4(iot, ioh, ATI_REG_CMD, value);
1708
1709
1710 DELAY(20);
1711 };
1712
1713 printf("%s: soft resetting aclink\n", sc->sc_dev.dv_xname);
1714
1715
1716 value = bus_space_read_4(iot, ioh, ATI_REG_CMD);
1717 value |= ATI_REG_CMD_AC_SOFT_RESET;
1718 bus_space_write_4(iot, ioh, ATI_REG_CMD, value);
1719
1720
1721 value = bus_space_read_4(iot, ioh, ATI_REG_CMD);
1722 DELAY(20);
1723
1724
1725 value = bus_space_read_4(iot, ioh, ATI_REG_CMD);
1726 value &= ~ATI_REG_CMD_AC_SOFT_RESET;
1727 bus_space_write_4(iot, ioh, ATI_REG_CMD, value);
1728
1729
1730 timeout = 10;
1731 value = bus_space_read_4(iot, ioh, ATI_REG_CMD);
1732 while (!(value & ATI_REG_CMD_ACLINK_ACTIVE)) {
1733 printf("%s: not up; resetting aclink hardware\n",
1734 sc->sc_dev.dv_xname);
1735
1736
1737 value &= ~ATI_REG_CMD_AC_RESET;
1738 value |= ATI_REG_CMD_AC_SYNC;
1739 bus_space_write_4(iot, ioh, ATI_REG_CMD, value);
1740
1741
1742 value = bus_space_read_4(iot, ioh, ATI_REG_CMD);
1743 DELAY(20);
1744
1745
1746 value = bus_space_read_4(iot, ioh, ATI_REG_CMD);
1747 value |= ATI_REG_CMD_AC_RESET;
1748 bus_space_write_4(iot, ioh, ATI_REG_CMD, value);
1749
1750
1751 value = bus_space_read_4(iot, ioh, ATI_REG_CMD);
1752
1753 timeout--;
1754 if (timeout == 0) break;
1755 };
1756
1757 if (timeout == 0) {
1758 printf("%s: giving up aclink reset\n", sc->sc_dev.dv_xname);
1759 };
1760 if (timeout != 10) {
1761 printf("%s: aclink hardware reset successful\n",
1762 sc->sc_dev.dv_xname);
1763 };
1764
1765
1766 value = bus_space_read_4(iot, ioh, ATI_REG_CMD);
1767 value |= ATI_REG_CMD_AC_SYNC | ATI_REG_CMD_AC_RESET;
1768 bus_space_write_4(iot, ioh, ATI_REG_CMD, value);
1769 }
1770
1771
1772 int
1773 auixp_init(struct auixp_softc *sc)
1774 {
1775 bus_space_tag_t iot;
1776 bus_space_handle_t ioh;
1777 u_int32_t value;
1778
1779 iot = sc->sc_iot;
1780 ioh = sc->sc_ioh;
1781
1782 auixp_disable_interrupts(sc);
1783
1784
1785 value = bus_space_read_4(iot, ioh, ATI_REG_CMD);
1786 value &= ~( ATI_REG_CMD_IN_DMA_EN |
1787 ATI_REG_CMD_OUT_DMA_EN |
1788 ATI_REG_CMD_SPDF_OUT_EN );
1789 bus_space_write_4(iot, ioh, ATI_REG_CMD, value);
1790
1791
1792 auixp_reset_aclink(sc);
1793
1794
1795
1796
1797
1798
1799
1800
1801 return 0;
1802 }
1803
1804
1805
1806
1807 int
1808 auixp_power(struct auixp_softc *sc, int state)
1809 {
1810 pcitag_t tag;
1811 pci_chipset_tag_t pc;
1812 pcireg_t data;
1813 int pmcapreg;
1814
1815 tag = sc->sc_tag;
1816 pc = sc->sc_pct;
1817 if (pci_get_capability(pc, tag, PCI_CAP_PWRMGMT, &pmcapreg, 0)) {
1818 data = pci_conf_read(pc, tag, pmcapreg + PCI_PMCSR);
1819 if ((data & PCI_PMCSR_STATE_MASK) != state)
1820 pci_conf_write(pc, tag, pmcapreg + PCI_PMCSR, state);
1821 }
1822
1823 return 0;
1824 }
1825
1826 #if 0
1827 void
1828 auixp_powerhook(int why, void *hdl)
1829 {
1830 struct auixp_softc *sc;
1831
1832 sc = (struct auixp_softc *)hdl;
1833 switch (why) {
1834 case PWR_SUSPEND:
1835 case PWR_STANDBY:
1836 auixp_suspend(sc);
1837 break;
1838 case PWR_RESUME:
1839 auixp_resume(sc);
1840
1841 (sc->codec_if->vtbl->restore_ports)(sc->codec_if);
1842 break;
1843 }
1844 }
1845
1846 int
1847 auixp_suspend(struct auixp_softc *sc)
1848 {
1849
1850
1851 return 0;
1852 }
1853
1854 int
1855 auixp_resume(struct auixp_softc *sc)
1856 {
1857
1858
1859 return 0;
1860 }
1861 #endif