This source file includes following definitions.
- auich_match
- auich_attach
- auich_read_codec
- auich_write_codec
- auich_attach_codec
- auich_reset_codec
- auich_flags_codec
- auich_open
- auich_close
- auich_query_encoding
- auich_set_params
- auich_round_blocksize
- auich_halt_output
- auich_halt_input
- auich_getdev
- auich_set_port
- auich_get_port
- auich_query_devinfo
- auich_allocm
- auich_freem
- auich_round_buffersize
- auich_mappage
- auich_get_props
- auich_intr
- auich_trigger_output
- auich_trigger_input
- auich_powerhook
- auich_calibrate
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 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/kernel.h>
41 #include <sys/malloc.h>
42 #include <sys/device.h>
43
44 #include <dev/pci/pcidevs.h>
45 #include <dev/pci/pcivar.h>
46
47 #include <sys/audioio.h>
48 #include <dev/audio_if.h>
49 #include <dev/mulaw.h>
50 #include <dev/auconv.h>
51
52 #include <machine/bus.h>
53
54 #include <dev/ic/ac97.h>
55
56
57 #define AUICH_NAMBAR 0x10
58
59 #define AUICH_NABMBAR 0x14
60 #define AUICH_CFG 0x41
61 #define AUICH_CFG_IOSE 0x01
62
63 #define AUICH_MMBAR 0x18
64
65 #define AUICH_MBBAR 0x1c
66 #define AUICH_S2CR 0x10000000
67
68
69 #define AUICH_BDBAR 0x00
70 #define AUICH_CIV 0x04
71 #define AUICH_LVI 0x05
72 #define AUICH_LVI_MASK 0x1f
73 #define AUICH_STS 0x06
74 #define AUICH_FIFOE 0x10
75 #define AUICH_BCIS 0x08
76 #define AUICH_LVBCI 0x04
77 #define AUICH_CELV 0x02
78 #define AUICH_DCH 0x01
79 #define AUICH_ISTS_BITS "\020\01dch\02celv\03lvbci\04bcis\05fifoe"
80 #define AUICH_PICB 0x08
81 #define AUICH_PIV 0x0a
82 #define AUICH_CTRL 0x0b
83 #define AUICH_IOCE 0x10
84 #define AUICH_FEIE 0x08
85 #define AUICH_LVBIE 0x04
86 #define AUICH_RR 0x02
87 #define AUICH_RPBM 0x01
88
89 #define AUICH_PCMI 0x00
90 #define AUICH_PCMO 0x10
91 #define AUICH_MICI 0x20
92
93 #define AUICH_GCTRL 0x2c
94 #define AUICH_SSM_78 0x40000000
95 #define AUICH_SSM_69 0x80000000
96 #define AUICH_SSM_1011 0xc0000000
97 #define AUICH_POM16 0x000000
98 #define AUICH_POM20 0x400000
99 #define AUICH_PCM246_MASK 0x300000
100 #define AUICH_PCM2 0x000000
101 #define AUICH_PCM4 0x100000
102 #define AUICH_PCM6 0x200000
103 #define AUICH_S2RIE 0x40
104 #define AUICH_SRIE 0x20
105 #define AUICH_PRIE 0x10
106 #define AUICH_ACLSO 0x08
107 #define AUICH_WRESET 0x04
108 #define AUICH_CRESET 0x02
109 #define AUICH_GIE 0x01
110 #define AUICH_GSTS 0x30
111 #define AUICH_MD3 0x20000
112 #define AUICH_AD3 0x10000
113 #define AUICH_RCS 0x08000
114 #define AUICH_B3S12 0x04000
115 #define AUICH_B2S12 0x02000
116 #define AUICH_B1S12 0x01000
117 #define AUICH_SRI 0x00800
118 #define AUICH_PRI 0x00400
119 #define AUICH_SCR 0x00200
120 #define AUICH_PCR 0x00100
121 #define AUICH_MINT 0x00080
122 #define AUICH_POINT 0x00040
123 #define AUICH_PIINT 0x00020
124 #define AUICH_MOINT 0x00004
125 #define AUICH_MIINT 0x00002
126 #define AUICH_GSCI 0x00001
127 #define AUICH_GSTS_BITS "\020\01gsci\02miict\03moint\06piint\07point\010mint\011pcr\012scr\013pri\014sri\015b1s12\016b2s12\017b3s12\020rcs\021ad3\022md3"
128 #define AUICH_CAS 0x34
129 #define AUICH_SEMATIMO 1000
130 #define AUICH_RESETIMO 500000
131
132 #define ICH_SIS_NV_CTL 0x4c
133 #define ICH_SIS_CTL_UNMUTE 0x01
134
135
136
137
138
139
140 #define AUICH_DMALIST_MAX 32
141 #define AUICH_DMASEG_MAX (65536*2)
142 struct auich_dmalist {
143 u_int32_t base;
144 u_int32_t len;
145 #define AUICH_DMAF_IOC 0x80000000
146 #define AUICH_DMAF_BUP 0x40000000
147 };
148
149 #define AUICH_FIXED_RATE 48000
150
151 struct auich_dma {
152 bus_dmamap_t map;
153 caddr_t addr;
154 bus_dma_segment_t segs[AUICH_DMALIST_MAX];
155 int nsegs;
156 size_t size;
157 struct auich_dma *next;
158 };
159
160 struct auich_softc {
161 struct device sc_dev;
162 void *sc_ih;
163
164 audio_device_t sc_audev;
165
166 bus_space_tag_t iot;
167 bus_space_tag_t iot_mix;
168 bus_space_handle_t mix_ioh;
169 bus_space_handle_t aud_ioh;
170 bus_dma_tag_t dmat;
171
172 struct ac97_codec_if *codec_if;
173 struct ac97_host_if host_if;
174
175
176 struct auich_dmalist *dmalist_pcmo, *dmap_pcmo;
177 struct auich_dmalist *dmalist_pcmi, *dmap_pcmi;
178 struct auich_dmalist *dmalist_mici, *dmap_mici;
179
180 bus_dmamap_t dmalist_map;
181 bus_dma_segment_t dmalist_seg[2];
182 caddr_t dmalist_kva;
183 bus_addr_t dmalist_pcmo_pa;
184 bus_addr_t dmalist_pcmi_pa;
185 bus_addr_t dmalist_mici_pa;
186
187
188 u_int32_t pcmo_start, pcmo_p, pcmo_end;
189 int pcmo_blksize, pcmo_fifoe;
190 u_int32_t pcmi_start, pcmi_p, pcmi_end;
191 int pcmi_blksize, pcmi_fifoe;
192 u_int32_t mici_start, mici_p, mici_end;
193 int mici_blksize, mici_fifoe;
194 struct auich_dma *sc_dmas;
195
196 void (*sc_pintr)(void *);
197 void *sc_parg;
198
199 void (*sc_rintr)(void *);
200 void *sc_rarg;
201
202 void *powerhook;
203 int suspend;
204 u_int16_t ext_ctrl;
205 int sc_sample_size;
206 int sc_sts_reg;
207 int sc_ignore_codecready;
208 int flags;
209 int sc_ac97rate;
210 };
211
212 #ifdef AUICH_DEBUG
213 #define DPRINTF(l,x) do { if (auich_debug & (l)) printf x; } while(0)
214 int auich_debug = 0xfffe;
215 #define AUICH_DEBUG_CODECIO 0x0001
216 #define AUICH_DEBUG_DMA 0x0002
217 #define AUICH_DEBUG_PARAM 0x0004
218 #else
219 #define DPRINTF(x,y)
220 #endif
221
222 struct cfdriver auich_cd = {
223 NULL, "auich", DV_DULL
224 };
225
226 int auich_match(struct device *, void *, void *);
227 void auich_attach(struct device *, struct device *, void *);
228 int auich_intr(void *);
229
230 struct cfattach auich_ca = {
231 sizeof(struct auich_softc), auich_match, auich_attach
232 };
233
234 static const struct auich_devtype {
235 int vendor;
236 int product;
237 int options;
238 char name[8];
239 } auich_devices[] = {
240 { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_6300ESB_ACA, 0, "ESB" },
241 { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_6321ESB_ACA, 0, "ESB2" },
242 { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801AA_ACA, 0, "ICH" },
243 { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801AB_ACA, 0, "ICH0" },
244 { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801BA_ACA, 0, "ICH2" },
245 { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801CA_ACA, 0, "ICH3" },
246 { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801DB_ACA, 0, "ICH4" },
247 { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801EB_ACA, 0, "ICH5" },
248 { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801FB_ACA, 0, "ICH6" },
249 { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801GB_ACA, 0, "ICH7" },
250 { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82440MX_ACA, 0, "440MX" },
251 { PCI_VENDOR_SIS, PCI_PRODUCT_SIS_7012_ACA, 0, "SiS7012" },
252 { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE_ACA, 0, "nForce" },
253 { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE2_ACA, 0, "nForce2" },
254 { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE2_400_ACA,
255 0, "nForce2" },
256 { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE3_ACA, 0, "nForce3" },
257 { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE3_250_ACA,
258 0, "nForce3" },
259 { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE4_AC, 0, "nForce4" },
260 { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP04_AC97, 0, "MCP04" },
261 { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP51_ACA, 0, "MCP51" },
262 { PCI_VENDOR_AMD, PCI_PRODUCT_AMD_PBC768_ACA, 0, "AMD768" },
263 { PCI_VENDOR_AMD, PCI_PRODUCT_AMD_8111_ACA, 0, "AMD8111" },
264 };
265
266 int auich_open(void *, int);
267 void auich_close(void *);
268 int auich_query_encoding(void *, struct audio_encoding *);
269 int auich_set_params(void *, int, int, struct audio_params *,
270 struct audio_params *);
271 int auich_round_blocksize(void *, int);
272 int auich_halt_output(void *);
273 int auich_halt_input(void *);
274 int auich_getdev(void *, struct audio_device *);
275 int auich_set_port(void *, mixer_ctrl_t *);
276 int auich_get_port(void *, mixer_ctrl_t *);
277 int auich_query_devinfo(void *, mixer_devinfo_t *);
278 void *auich_allocm(void *, int, size_t, int, int);
279 void auich_freem(void *, void *, int);
280 size_t auich_round_buffersize(void *, int, size_t);
281 paddr_t auich_mappage(void *, void *, off_t, int);
282 int auich_get_props(void *);
283 int auich_trigger_output(void *, void *, void *, int, void (*)(void *),
284 void *, struct audio_params *);
285 int auich_trigger_input(void *, void *, void *, int, void (*)(void *),
286 void *, struct audio_params *);
287
288 void auich_powerhook(int, void *);
289
290 struct audio_hw_if auich_hw_if = {
291 auich_open,
292 auich_close,
293 NULL,
294 auich_query_encoding,
295 auich_set_params,
296 auich_round_blocksize,
297 NULL,
298 NULL,
299 NULL,
300 NULL,
301 NULL,
302 auich_halt_output,
303 auich_halt_input,
304 NULL,
305 auich_getdev,
306 NULL,
307 auich_set_port,
308 auich_get_port,
309 auich_query_devinfo,
310 auich_allocm,
311 auich_freem,
312 auich_round_buffersize,
313 auich_mappage,
314 auich_get_props,
315 auich_trigger_output,
316 auich_trigger_input
317 };
318
319 int auich_attach_codec(void *, struct ac97_codec_if *);
320 int auich_read_codec(void *, u_int8_t, u_int16_t *);
321 int auich_write_codec(void *, u_int8_t, u_int16_t);
322 void auich_reset_codec(void *);
323 enum ac97_host_flags auich_flags_codec(void *);
324 unsigned int auich_calibrate(struct auich_softc *);
325
326 int
327 auich_match(parent, match, aux)
328 struct device *parent;
329 void *match;
330 void *aux;
331 {
332 struct pci_attach_args *pa = aux;
333 int i;
334
335 for (i = sizeof(auich_devices)/sizeof(auich_devices[0]); i--;)
336 if (PCI_VENDOR(pa->pa_id) == auich_devices[i].vendor &&
337 PCI_PRODUCT(pa->pa_id) == auich_devices[i].product)
338 return 1;
339
340 return 0;
341 }
342
343 void
344 auich_attach(parent, self, aux)
345 struct device *parent, *self;
346 void *aux;
347 {
348 struct auich_softc *sc = (struct auich_softc *)self;
349 struct pci_attach_args *pa = aux;
350 pci_intr_handle_t ih;
351 bus_size_t mix_size, aud_size;
352 pcireg_t csr;
353 const char *intrstr;
354 u_int32_t status;
355 bus_size_t dmasz;
356 int i, segs;
357
358 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_INTEL &&
359 (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_82801DB_ACA ||
360 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_82801EB_ACA ||
361 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_82801FB_ACA ||
362 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_82801GB_ACA)) {
363
364
365
366 if (pci_mapreg_map(pa, AUICH_MMBAR, PCI_MAPREG_TYPE_MEM, 0,
367 &sc->iot_mix, &sc->mix_ioh, NULL, &mix_size, 0)) {
368 csr = pci_conf_read(pa->pa_pc, pa->pa_tag, AUICH_CFG);
369 pci_conf_write(pa->pa_pc, pa->pa_tag, AUICH_CFG,
370 csr | AUICH_CFG_IOSE);
371 if (pci_mapreg_map(pa, AUICH_NAMBAR, PCI_MAPREG_TYPE_IO,
372 0, &sc->iot_mix, &sc->mix_ioh, NULL, &mix_size, 0)) {
373 printf(": can't map codec mem/io space\n");
374 return;
375 }
376 }
377
378 if (pci_mapreg_map(pa, AUICH_MBBAR, PCI_MAPREG_TYPE_MEM, 0,
379 &sc->iot, &sc->aud_ioh, NULL, &aud_size, 0)) {
380 csr = pci_conf_read(pa->pa_pc, pa->pa_tag, AUICH_CFG);
381 pci_conf_write(pa->pa_pc, pa->pa_tag, AUICH_CFG,
382 csr | AUICH_CFG_IOSE);
383 if (pci_mapreg_map(pa, AUICH_NABMBAR,
384 PCI_MAPREG_TYPE_IO, 0, &sc->iot,
385 &sc->aud_ioh, NULL, &aud_size, 0)) {
386 printf(": can't map device mem/io space\n");
387 bus_space_unmap(sc->iot_mix, sc->mix_ioh, mix_size);
388 return;
389 }
390 }
391 } else {
392 if (pci_mapreg_map(pa, AUICH_NAMBAR, PCI_MAPREG_TYPE_IO,
393 0, &sc->iot_mix, &sc->mix_ioh, NULL, &mix_size, 0)) {
394 printf(": can't map codec i/o space\n");
395 return;
396 }
397
398 if (pci_mapreg_map(pa, AUICH_NABMBAR, PCI_MAPREG_TYPE_IO,
399 0, &sc->iot, &sc->aud_ioh, NULL, &aud_size, 0)) {
400 printf(": can't map device i/o space\n");
401 bus_space_unmap(sc->iot_mix, sc->mix_ioh, mix_size);
402 return;
403 }
404 }
405 sc->dmat = pa->pa_dmat;
406
407
408 dmasz = AUICH_DMALIST_MAX * 3 * sizeof(struct auich_dma);
409 segs = 1;
410 if (bus_dmamem_alloc(sc->dmat, dmasz, PAGE_SIZE, 0, sc->dmalist_seg,
411 segs, &segs, BUS_DMA_NOWAIT)) {
412 printf(": failed to alloc dmalist\n");
413 return;
414 }
415 if (bus_dmamem_map(sc->dmat, sc->dmalist_seg, segs, dmasz,
416 &sc->dmalist_kva, BUS_DMA_NOWAIT)) {
417 printf(": failed to map dmalist\n");
418 bus_dmamem_free(sc->dmat, sc->dmalist_seg, segs);
419 return;
420 }
421 if (bus_dmamap_create(sc->dmat, dmasz, segs, dmasz, 0, BUS_DMA_NOWAIT,
422 &sc->dmalist_map)) {
423 printf(": failed to create dmalist map\n");
424 bus_dmamem_unmap(sc->dmat, sc->dmalist_kva, dmasz);
425 bus_dmamem_free(sc->dmat, sc->dmalist_seg, segs);
426 return;
427 }
428 if (bus_dmamap_load_raw(sc->dmat, sc->dmalist_map, sc->dmalist_seg,
429 segs, dmasz, BUS_DMA_NOWAIT)) {
430 printf(": failed to load dmalist map: %d segs %lu size\n",
431 segs, (u_long)dmasz);
432 bus_dmamap_destroy(sc->dmat, sc->dmalist_map);
433 bus_dmamem_unmap(sc->dmat, sc->dmalist_kva, dmasz);
434 bus_dmamem_free(sc->dmat, sc->dmalist_seg, segs);
435 return;
436 }
437
438 if (pci_intr_map(pa, &ih)) {
439 bus_space_unmap(sc->iot, sc->aud_ioh, aud_size);
440 bus_space_unmap(sc->iot_mix, sc->mix_ioh, mix_size);
441 return;
442 }
443 intrstr = pci_intr_string(pa->pa_pc, ih);
444 sc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_AUDIO, auich_intr,
445 sc, sc->sc_dev.dv_xname);
446 if (!sc->sc_ih) {
447 printf(": can't establish interrupt");
448 if (intrstr)
449 printf(" at %s", intrstr);
450 printf("\n");
451 bus_space_unmap(sc->iot, sc->aud_ioh, aud_size);
452 bus_space_unmap(sc->iot_mix, sc->mix_ioh, mix_size);
453 return;
454 }
455
456 for (i = sizeof(auich_devices)/sizeof(auich_devices[0]); i--;)
457 if (PCI_PRODUCT(pa->pa_id) == auich_devices[i].product)
458 break;
459
460 snprintf(sc->sc_audev.name, sizeof sc->sc_audev.name, "%s AC97",
461 auich_devices[i].name);
462 snprintf(sc->sc_audev.version, sizeof sc->sc_audev.version, "0x%02x",
463 PCI_REVISION(pa->pa_class));
464 strlcpy(sc->sc_audev.config, sc->sc_dev.dv_xname,
465 sizeof sc->sc_audev.config);
466
467 printf(": %s, %s\n", intrstr, sc->sc_audev.name);
468
469
470 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_SIS &&
471 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_SIS_7012_ACA) {
472 sc->sc_sts_reg = AUICH_PICB;
473 sc->sc_sample_size = 1;
474
475 bus_space_write_4(sc->iot, sc->aud_ioh, ICH_SIS_NV_CTL,
476 bus_space_read_4(sc->iot, sc->aud_ioh, ICH_SIS_NV_CTL) |
477 ICH_SIS_CTL_UNMUTE);
478 } else {
479 sc->sc_sts_reg = AUICH_STS;
480 sc->sc_sample_size = 2;
481 }
482
483 sc->dmalist_pcmo = (struct auich_dmalist *)(sc->dmalist_kva +
484 (0 * sizeof(struct auich_dmalist) + AUICH_DMALIST_MAX));
485 sc->dmalist_pcmo_pa = sc->dmalist_map->dm_segs[0].ds_addr +
486 (0 * sizeof(struct auich_dmalist) + AUICH_DMALIST_MAX);
487
488 sc->dmalist_pcmi = (struct auich_dmalist *)(sc->dmalist_kva +
489 (1 * sizeof(struct auich_dmalist) + AUICH_DMALIST_MAX));
490 sc->dmalist_pcmi_pa = sc->dmalist_map->dm_segs[0].ds_addr +
491 (1 * sizeof(struct auich_dmalist) + AUICH_DMALIST_MAX);
492
493 sc->dmalist_mici = (struct auich_dmalist *)(sc->dmalist_kva +
494 (2 * sizeof(struct auich_dmalist) + AUICH_DMALIST_MAX));
495 sc->dmalist_mici_pa = sc->dmalist_map->dm_segs[0].ds_addr +
496 (2 * sizeof(struct auich_dmalist) + AUICH_DMALIST_MAX);
497
498 DPRINTF(AUICH_DEBUG_DMA, ("auich_attach: lists %p %p %p\n",
499 sc->dmalist_pcmo, sc->dmalist_pcmi, sc->dmalist_mici));
500
501
502 auich_reset_codec(sc);
503 status = bus_space_read_4(sc->iot, sc->aud_ioh, AUICH_GSTS);
504 if (!(status & AUICH_PCR)) {
505 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_INTEL &&
506 (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_82801DB_ACA ||
507 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_82801EB_ACA ||
508 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_82801FB_ACA ||
509 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_82801GB_ACA)) {
510
511 sc->sc_ignore_codecready = 1;
512 } else {
513 printf("%s: reset failed!\n", sc->sc_dev.dv_xname);
514 return;
515 }
516 }
517
518 sc->host_if.arg = sc;
519 sc->host_if.attach = auich_attach_codec;
520 sc->host_if.read = auich_read_codec;
521 sc->host_if.write = auich_write_codec;
522 sc->host_if.reset = auich_reset_codec;
523 sc->host_if.flags = auich_flags_codec;
524 if (sc->sc_dev.dv_cfdata->cf_flags & 0x0001)
525 sc->flags = AC97_HOST_SWAPPED_CHANNELS;
526
527 if (ac97_attach(&sc->host_if) != 0) {
528 pci_intr_disestablish(pa->pa_pc, sc->sc_ih);
529 bus_space_unmap(sc->iot, sc->aud_ioh, aud_size);
530 bus_space_unmap(sc->iot_mix, sc->mix_ioh, mix_size);
531 return;
532 }
533
534 audio_attach_mi(&auich_hw_if, sc, &sc->sc_dev);
535
536
537 sc->suspend = PWR_RESUME;
538 sc->powerhook = powerhook_establish(auich_powerhook, sc);
539
540 sc->sc_ac97rate = -1;
541 }
542
543 int
544 auich_read_codec(v, reg, val)
545 void *v;
546 u_int8_t reg;
547 u_int16_t *val;
548 {
549 struct auich_softc *sc = v;
550 int i;
551
552
553 for (i = AUICH_SEMATIMO; i-- &&
554 bus_space_read_1(sc->iot, sc->aud_ioh, AUICH_CAS) & 1; DELAY(1));
555
556 if (!sc->sc_ignore_codecready && i < 0) {
557 DPRINTF(AUICH_DEBUG_CODECIO,
558 ("%s: read_codec timeout\n", sc->sc_dev.dv_xname));
559 return (-1);
560 }
561
562 *val = bus_space_read_2(sc->iot_mix, sc->mix_ioh, reg);
563 DPRINTF(AUICH_DEBUG_CODECIO, ("%s: read_codec(%x, %x)\n",
564 sc->sc_dev.dv_xname, reg, *val));
565 return (0);
566 }
567
568 int
569 auich_write_codec(v, reg, val)
570 void *v;
571 u_int8_t reg;
572 u_int16_t val;
573 {
574 struct auich_softc *sc = v;
575 int i;
576
577
578 for (i = AUICH_SEMATIMO; i-- &&
579 bus_space_read_1(sc->iot, sc->aud_ioh, AUICH_CAS) & 1; DELAY(1));
580
581 if (sc->sc_ignore_codecready || i >= 0) {
582 DPRINTF(AUICH_DEBUG_CODECIO, ("%s: write_codec(%x, %x)\n",
583 sc->sc_dev.dv_xname, reg, val));
584 bus_space_write_2(sc->iot_mix, sc->mix_ioh, reg, val);
585 return (0);
586 } else {
587 DPRINTF(AUICH_DEBUG_CODECIO,
588 ("%s: write_codec timeout\n", sc->sc_dev.dv_xname));
589 return (-1);
590 }
591 }
592
593 int
594 auich_attach_codec(v, cif)
595 void *v;
596 struct ac97_codec_if *cif;
597 {
598 struct auich_softc *sc = v;
599
600 sc->codec_if = cif;
601 return 0;
602 }
603
604 void
605 auich_reset_codec(v)
606 void *v;
607 {
608 struct auich_softc *sc = v;
609 u_int32_t control;
610 int i;
611
612 control = bus_space_read_4(sc->iot, sc->aud_ioh, AUICH_GCTRL);
613 control &= ~(AUICH_ACLSO | AUICH_PCM246_MASK);
614 control |= (control & AUICH_CRESET) ? AUICH_WRESET : AUICH_CRESET;
615 bus_space_write_4(sc->iot, sc->aud_ioh, AUICH_GCTRL, control);
616
617 for (i = AUICH_RESETIMO; i-- &&
618 !(bus_space_read_4(sc->iot, sc->aud_ioh, AUICH_GSTS) & AUICH_PCR);
619 DELAY(1));
620
621 if (i < 0)
622 DPRINTF(AUICH_DEBUG_CODECIO,
623 ("%s: reset_codec timeout\n", sc->sc_dev.dv_xname));
624 }
625
626 enum ac97_host_flags
627 auich_flags_codec(void *v)
628 {
629 struct auich_softc *sc = v;
630
631 return (sc->flags);
632 }
633
634 int
635 auich_open(v, flags)
636 void *v;
637 int flags;
638 {
639 struct auich_softc *sc = v;
640
641 if (sc->sc_ac97rate == -1)
642 sc->sc_ac97rate = auich_calibrate(sc);
643 return 0;
644 }
645
646 void
647 auich_close(v)
648 void *v;
649 {
650 }
651
652 int
653 auich_query_encoding(v, aep)
654 void *v;
655 struct audio_encoding *aep;
656 {
657 switch (aep->index) {
658 case 0:
659 strlcpy(aep->name, AudioEulinear, sizeof aep->name);
660 aep->encoding = AUDIO_ENCODING_ULINEAR;
661 aep->precision = 8;
662 aep->flags = 0;
663 return (0);
664 case 1:
665 strlcpy(aep->name, AudioEmulaw, sizeof aep->name);
666 aep->encoding = AUDIO_ENCODING_ULAW;
667 aep->precision = 8;
668 aep->flags = AUDIO_ENCODINGFLAG_EMULATED;
669 return (0);
670 case 2:
671 strlcpy(aep->name, AudioEalaw, sizeof aep->name);
672 aep->encoding = AUDIO_ENCODING_ALAW;
673 aep->precision = 8;
674 aep->flags = AUDIO_ENCODINGFLAG_EMULATED;
675 return (0);
676 case 3:
677 strlcpy(aep->name, AudioEslinear, sizeof aep->name);
678 aep->encoding = AUDIO_ENCODING_SLINEAR;
679 aep->precision = 8;
680 aep->flags = AUDIO_ENCODINGFLAG_EMULATED;
681 return (0);
682 case 4:
683 strlcpy(aep->name, AudioEslinear_le, sizeof aep->name);
684 aep->encoding = AUDIO_ENCODING_SLINEAR_LE;
685 aep->precision = 16;
686 aep->flags = 0;
687 return (0);
688 case 5:
689 strlcpy(aep->name, AudioEulinear_le, sizeof aep->name);
690 aep->encoding = AUDIO_ENCODING_ULINEAR_LE;
691 aep->precision = 16;
692 aep->flags = AUDIO_ENCODINGFLAG_EMULATED;
693 return (0);
694 case 6:
695 strlcpy(aep->name, AudioEslinear_be, sizeof aep->name);
696 aep->encoding = AUDIO_ENCODING_SLINEAR_BE;
697 aep->precision = 16;
698 aep->flags = AUDIO_ENCODINGFLAG_EMULATED;
699 return (0);
700 case 7:
701 strlcpy(aep->name, AudioEulinear_be, sizeof aep->name);
702 aep->encoding = AUDIO_ENCODING_ULINEAR_BE;
703 aep->precision = 16;
704 aep->flags = AUDIO_ENCODINGFLAG_EMULATED;
705 return (0);
706 default:
707 return (EINVAL);
708 }
709 }
710
711 int
712 auich_set_params(v, setmode, usemode, play, rec)
713 void *v;
714 int setmode, usemode;
715 struct audio_params *play, *rec;
716 {
717 struct auich_softc *sc = v;
718 int error;
719 u_int orate;
720 u_int adj_rate;
721
722 if (setmode & AUMODE_PLAY) {
723 play->factor = 1;
724 play->sw_code = NULL;
725 switch(play->encoding) {
726 case AUDIO_ENCODING_ULAW:
727 switch (play->channels) {
728 case 1:
729 play->factor = 4;
730 play->sw_code = mulaw_to_slinear16_mts;
731 break;
732 case 2:
733 play->factor = 2;
734 play->sw_code = mulaw_to_slinear16;
735 break;
736 default:
737 return (EINVAL);
738 }
739 break;
740 case AUDIO_ENCODING_SLINEAR_LE:
741 switch (play->precision) {
742 case 8:
743 switch (play->channels) {
744 case 1:
745 play->factor = 4;
746 play->sw_code = linear8_to_linear16_mts;
747 break;
748 case 2:
749 play->factor = 2;
750 play->sw_code = linear8_to_linear16;
751 break;
752 default:
753 return (EINVAL);
754 }
755 break;
756 case 16:
757 switch (play->channels) {
758 case 1:
759 play->factor = 2;
760 play->sw_code = noswap_bytes_mts;
761 break;
762 case 2:
763 break;
764 default:
765 return (EINVAL);
766 }
767 break;
768 default:
769 return (EINVAL);
770 }
771 break;
772 case AUDIO_ENCODING_ULINEAR_LE:
773 switch (play->precision) {
774 case 8:
775 switch (play->channels) {
776 case 1:
777 play->factor = 4;
778 play->sw_code = ulinear8_to_linear16_mts;
779 break;
780 case 2:
781 play->factor = 2;
782 play->sw_code = ulinear8_to_linear16;
783 break;
784 default:
785 return (EINVAL);
786 }
787 break;
788 case 16:
789 switch (play->channels) {
790 case 1:
791 play->factor = 2;
792 play->sw_code = change_sign16_mts;
793 break;
794 case 2:
795 play->sw_code = change_sign16;
796 break;
797 default:
798 return (EINVAL);
799 }
800 break;
801 default:
802 return (EINVAL);
803 }
804 break;
805 case AUDIO_ENCODING_ALAW:
806 switch (play->channels) {
807 case 1:
808 play->factor = 4;
809 play->sw_code = alaw_to_slinear16_mts;
810 break;
811 case 2:
812 play->factor = 2;
813 play->sw_code = alaw_to_slinear16;
814 break;
815 default:
816 return (EINVAL);
817 }
818 break;
819 case AUDIO_ENCODING_SLINEAR_BE:
820 switch (play->precision) {
821 case 8:
822 switch (play->channels) {
823 case 1:
824 play->factor = 4;
825 play->sw_code = linear8_to_linear16_mts;
826 break;
827 case 2:
828 play->factor = 2;
829 play->sw_code = linear8_to_linear16;
830 break;
831 default:
832 return (EINVAL);
833 }
834 break;
835 case 16:
836 switch (play->channels) {
837 case 1:
838 play->factor = 2;
839 play->sw_code = swap_bytes_mts;
840 break;
841 case 2:
842 play->sw_code = swap_bytes;
843 break;
844 default:
845 return (EINVAL);
846 }
847 break;
848 default:
849 return (EINVAL);
850 }
851 break;
852 case AUDIO_ENCODING_ULINEAR_BE:
853 switch (play->precision) {
854 case 8:
855 switch (play->channels) {
856 case 1:
857 play->factor = 4;
858 play->sw_code = ulinear8_to_linear16_mts;
859 break;
860 case 2:
861 play->factor = 2;
862 play->sw_code = ulinear8_to_linear16;
863 break;
864 default:
865 return (EINVAL);
866 }
867 break;
868 case 16:
869 switch (play->channels) {
870 case 1:
871 play->factor = 2;
872 play->sw_code = change_sign16_swap_bytes_mts;
873 break;
874 case 2:
875 play->sw_code = change_sign16_swap_bytes;
876 break;
877 default:
878 return (EINVAL);
879 }
880 break;
881 default:
882 return (EINVAL);
883 }
884 break;
885 default:
886 return (EINVAL);
887 }
888
889 orate = adj_rate = play->sample_rate;
890 if (sc->sc_ac97rate != 0)
891 adj_rate = orate * AUICH_FIXED_RATE / sc->sc_ac97rate;
892 play->sample_rate = adj_rate;
893 error = ac97_set_rate(sc->codec_if, play, AUMODE_PLAY);
894 if (play->sample_rate == adj_rate)
895 play->sample_rate = orate;
896 if (error)
897 return (error);
898 }
899
900 if (setmode & AUMODE_RECORD) {
901 rec->factor = 1;
902 rec->sw_code = 0;
903 switch(rec->encoding) {
904 case AUDIO_ENCODING_ULAW:
905 rec->sw_code = slinear16_to_mulaw_le;
906 rec->factor = 2;
907 break;
908 case AUDIO_ENCODING_ALAW:
909 rec->sw_code = slinear16_to_alaw_le;
910 rec->factor = 2;
911 break;
912 case AUDIO_ENCODING_SLINEAR_LE:
913 switch (rec->precision) {
914 case 8:
915 rec->sw_code = linear16_to_linear8_le;
916 rec->factor = 2;
917 break;
918 case 16:
919 break;
920 default:
921 return (EINVAL);
922 }
923 break;
924 case AUDIO_ENCODING_ULINEAR_LE:
925 switch (rec->precision) {
926 case 8:
927 rec->sw_code = linear16_to_ulinear8_le;
928 rec->factor = 2;
929 break;
930 case 16:
931 rec->sw_code = change_sign16_le;
932 break;
933 default:
934 return (EINVAL);
935 }
936 break;
937 case AUDIO_ENCODING_SLINEAR_BE:
938 switch (rec->precision) {
939 case 8:
940 rec->sw_code = linear16_to_linear8_le;
941 rec->factor = 2;
942 break;
943 case 16:
944 rec->sw_code = swap_bytes;
945 break;
946 default:
947 return (EINVAL);
948 }
949 break;
950 case AUDIO_ENCODING_ULINEAR_BE:
951 switch (rec->precision) {
952 case 8:
953 rec->sw_code = linear16_to_ulinear8_le;
954 rec->factor = 2;
955 break;
956 case 16:
957 rec->sw_code = change_sign16_swap_bytes_le;
958 break;
959 default:
960 return (EINVAL);
961 }
962 break;
963 default:
964 return (EINVAL);
965 }
966
967 orate = rec->sample_rate;
968 if (sc->sc_ac97rate != 0)
969 rec->sample_rate = orate * AUICH_FIXED_RATE /
970 sc->sc_ac97rate;
971 error = ac97_set_rate(sc->codec_if, rec, AUMODE_RECORD);
972 rec->sample_rate = orate;
973 if (error)
974 return (error);
975 }
976
977 return (0);
978 }
979
980 int
981 auich_round_blocksize(v, blk)
982 void *v;
983 int blk;
984 {
985 return (blk + 0x3f) & ~0x3f;
986 }
987
988 int
989 auich_halt_output(v)
990 void *v;
991 {
992 struct auich_softc *sc = v;
993
994 DPRINTF(AUICH_DEBUG_DMA, ("%s: halt_output\n", sc->sc_dev.dv_xname));
995
996 bus_space_write_1(sc->iot, sc->aud_ioh, AUICH_PCMO + AUICH_CTRL, AUICH_RR);
997
998 return 0;
999 }
1000
1001 int
1002 auich_halt_input(v)
1003 void *v;
1004 {
1005 struct auich_softc *sc = v;
1006
1007 DPRINTF(AUICH_DEBUG_DMA,
1008 ("%s: halt_input\n", sc->sc_dev.dv_xname));
1009
1010
1011
1012 bus_space_write_1(sc->iot, sc->aud_ioh, AUICH_PCMI + AUICH_CTRL, AUICH_RR);
1013 bus_space_write_1(sc->iot, sc->aud_ioh, AUICH_MICI + AUICH_CTRL, AUICH_RR);
1014
1015 return 0;
1016 }
1017
1018 int
1019 auich_getdev(v, adp)
1020 void *v;
1021 struct audio_device *adp;
1022 {
1023 struct auich_softc *sc = v;
1024 *adp = sc->sc_audev;
1025 return 0;
1026 }
1027
1028 int
1029 auich_set_port(v, cp)
1030 void *v;
1031 mixer_ctrl_t *cp;
1032 {
1033 struct auich_softc *sc = v;
1034 return sc->codec_if->vtbl->mixer_set_port(sc->codec_if, cp);
1035 }
1036
1037 int
1038 auich_get_port(v, cp)
1039 void *v;
1040 mixer_ctrl_t *cp;
1041 {
1042 struct auich_softc *sc = v;
1043 return sc->codec_if->vtbl->mixer_get_port(sc->codec_if, cp);
1044 }
1045
1046 int
1047 auich_query_devinfo(v, dp)
1048 void *v;
1049 mixer_devinfo_t *dp;
1050 {
1051 struct auich_softc *sc = v;
1052 return sc->codec_if->vtbl->query_devinfo(sc->codec_if, dp);
1053 }
1054
1055 void *
1056 auich_allocm(v, direction, size, pool, flags)
1057 void *v;
1058 int direction;
1059 size_t size;
1060 int pool, flags;
1061 {
1062 struct auich_softc *sc = v;
1063 struct auich_dma *p;
1064 int error;
1065
1066 if (size > AUICH_DMALIST_MAX * AUICH_DMASEG_MAX)
1067 return NULL;
1068
1069 p = malloc(sizeof(*p), pool, flags);
1070 if (!p)
1071 return NULL;
1072 bzero(p, sizeof(*p));
1073
1074 p->size = size;
1075 if ((error = bus_dmamem_alloc(sc->dmat, p->size, NBPG, 0, p->segs,
1076 1, &p->nsegs, BUS_DMA_NOWAIT)) != 0) {
1077 printf("%s: unable to allocate dma, error = %d\n",
1078 sc->sc_dev.dv_xname, error);
1079 free(p, pool);
1080 return NULL;
1081 }
1082
1083 if ((error = bus_dmamem_map(sc->dmat, p->segs, p->nsegs, p->size,
1084 &p->addr, BUS_DMA_NOWAIT | BUS_DMA_COHERENT)) != 0) {
1085 printf("%s: unable to map dma, error = %d\n",
1086 sc->sc_dev.dv_xname, error);
1087 bus_dmamem_free(sc->dmat, p->segs, p->nsegs);
1088 free(p, pool);
1089 return NULL;
1090 }
1091
1092 if ((error = bus_dmamap_create(sc->dmat, p->size, 1,
1093 p->size, 0, BUS_DMA_NOWAIT, &p->map)) != 0) {
1094 printf("%s: unable to create dma map, error = %d\n",
1095 sc->sc_dev.dv_xname, error);
1096 bus_dmamem_unmap(sc->dmat, p->addr, size);
1097 bus_dmamem_free(sc->dmat, p->segs, p->nsegs);
1098 free(p, pool);
1099 return NULL;
1100 }
1101
1102 if ((error = bus_dmamap_load(sc->dmat, p->map, p->addr, p->size,
1103 NULL, BUS_DMA_NOWAIT)) != 0) {
1104 printf("%s: unable to load dma map, error = %d\n",
1105 sc->sc_dev.dv_xname, error);
1106 bus_dmamap_destroy(sc->dmat, p->map);
1107 bus_dmamem_unmap(sc->dmat, p->addr, size);
1108 bus_dmamem_free(sc->dmat, p->segs, p->nsegs);
1109 free(p, pool);
1110 return NULL;
1111 }
1112
1113 p->next = sc->sc_dmas;
1114 sc->sc_dmas = p;
1115
1116 return p->addr;
1117 }
1118
1119 void
1120 auich_freem(v, ptr, pool)
1121 void *v;
1122 void *ptr;
1123 int pool;
1124 {
1125 struct auich_softc *sc = v;
1126 struct auich_dma *p;
1127
1128 for (p = sc->sc_dmas; p->addr != ptr; p = p->next)
1129 if (p->next == NULL) {
1130 printf("auich_freem: trying to free not allocated memory");
1131 return;
1132 }
1133
1134 bus_dmamap_unload(sc->dmat, p->map);
1135 bus_dmamap_destroy(sc->dmat, p->map);
1136 bus_dmamem_unmap(sc->dmat, p->addr, p->size);
1137 bus_dmamem_free(sc->dmat, p->segs, p->nsegs);
1138 free(p, pool);
1139 }
1140
1141 size_t
1142 auich_round_buffersize(v, direction, size)
1143 void *v;
1144 int direction;
1145 size_t size;
1146 {
1147 if (size > AUICH_DMALIST_MAX * AUICH_DMASEG_MAX)
1148 size = AUICH_DMALIST_MAX * AUICH_DMASEG_MAX;
1149
1150 return size;
1151 }
1152
1153 paddr_t
1154 auich_mappage(v, mem, off, prot)
1155 void *v;
1156 void *mem;
1157 off_t off;
1158 int prot;
1159 {
1160 struct auich_softc *sc = v;
1161 struct auich_dma *p;
1162
1163 if (off < 0)
1164 return -1;
1165
1166 for (p = sc->sc_dmas; p && p->addr != mem; p = p->next);
1167 if (!p)
1168 return -1;
1169
1170 return bus_dmamem_mmap(sc->dmat, p->segs, p->nsegs,
1171 off, prot, BUS_DMA_WAITOK);
1172 }
1173
1174 int
1175 auich_get_props(v)
1176 void *v;
1177 {
1178 return AUDIO_PROP_MMAP | AUDIO_PROP_INDEPENDENT | AUDIO_PROP_FULLDUPLEX;
1179 }
1180
1181 int
1182 auich_intr(v)
1183 void *v;
1184 {
1185 struct auich_softc *sc = v;
1186 int ret = 0, sts, gsts, i;
1187
1188 gsts = bus_space_read_2(sc->iot, sc->aud_ioh, AUICH_GSTS);
1189 DPRINTF(AUICH_DEBUG_DMA, ("auich_intr: gsts=%b\n", gsts, AUICH_GSTS_BITS));
1190
1191 if (gsts & AUICH_POINT) {
1192 sts = bus_space_read_2(sc->iot, sc->aud_ioh,
1193 AUICH_PCMO + sc->sc_sts_reg);
1194 DPRINTF(AUICH_DEBUG_DMA,
1195 ("auich_intr: osts=%b\n", sts, AUICH_ISTS_BITS));
1196
1197 #ifdef AUICH_DEBUG
1198 if (sts & AUICH_FIFOE) {
1199 printf("%s: fifo underrun # %u\n",
1200 sc->sc_dev.dv_xname, ++sc->pcmo_fifoe);
1201 }
1202 #endif
1203 i = bus_space_read_1(sc->iot, sc->aud_ioh, AUICH_PCMO + AUICH_CIV);
1204 if (sts & (AUICH_LVBCI | AUICH_CELV)) {
1205 struct auich_dmalist *q, *qe;
1206
1207 q = sc->dmap_pcmo;
1208 qe = &sc->dmalist_pcmo[i];
1209
1210 while (q != qe) {
1211
1212 q->base = sc->pcmo_p;
1213 q->len = (sc->pcmo_blksize /
1214 sc->sc_sample_size) | AUICH_DMAF_IOC;
1215 DPRINTF(AUICH_DEBUG_DMA,
1216 ("auich_intr: %p, %p = %x @ %p\n",
1217 qe, q, sc->pcmo_blksize /
1218 sc->sc_sample_size, sc->pcmo_p));
1219
1220 sc->pcmo_p += sc->pcmo_blksize;
1221 if (sc->pcmo_p >= sc->pcmo_end)
1222 sc->pcmo_p = sc->pcmo_start;
1223
1224 if (++q == &sc->dmalist_pcmo[AUICH_DMALIST_MAX])
1225 q = sc->dmalist_pcmo;
1226 }
1227
1228 sc->dmap_pcmo = q;
1229 bus_space_write_1(sc->iot, sc->aud_ioh,
1230 AUICH_PCMO + AUICH_LVI,
1231 (sc->dmap_pcmo - sc->dmalist_pcmo - 1) &
1232 AUICH_LVI_MASK);
1233 }
1234
1235 if (sts & AUICH_BCIS && sc->sc_pintr)
1236 sc->sc_pintr(sc->sc_parg);
1237
1238
1239 bus_space_write_2(sc->iot, sc->aud_ioh,
1240 AUICH_PCMO + sc->sc_sts_reg, sts &
1241 (AUICH_LVBCI | AUICH_CELV | AUICH_BCIS | AUICH_FIFOE));
1242 bus_space_write_2(sc->iot, sc->aud_ioh, AUICH_GSTS, AUICH_POINT);
1243 ret++;
1244 }
1245
1246 if (gsts & AUICH_PIINT) {
1247 sts = bus_space_read_2(sc->iot, sc->aud_ioh,
1248 AUICH_PCMI + sc->sc_sts_reg);
1249 DPRINTF(AUICH_DEBUG_DMA,
1250 ("auich_intr: ists=%b\n", sts, AUICH_ISTS_BITS));
1251
1252 #ifdef AUICH_DEBUG
1253 if (sts & AUICH_FIFOE) {
1254 printf("%s: in fifo overrun # %u\n",
1255 sc->sc_dev.dv_xname, ++sc->pcmi_fifoe);
1256 }
1257 #endif
1258 i = bus_space_read_1(sc->iot, sc->aud_ioh, AUICH_PCMI + AUICH_CIV);
1259 if (sts & (AUICH_LVBCI | AUICH_CELV)) {
1260 struct auich_dmalist *q, *qe;
1261
1262 q = sc->dmap_pcmi;
1263 qe = &sc->dmalist_pcmi[i];
1264
1265 while (q != qe) {
1266
1267 q->base = sc->pcmi_p;
1268 q->len = (sc->pcmi_blksize /
1269 sc->sc_sample_size) | AUICH_DMAF_IOC;
1270 DPRINTF(AUICH_DEBUG_DMA,
1271 ("auich_intr: %p, %p = %x @ %p\n",
1272 qe, q, sc->pcmi_blksize /
1273 sc->sc_sample_size, sc->pcmi_p));
1274
1275 sc->pcmi_p += sc->pcmi_blksize;
1276 if (sc->pcmi_p >= sc->pcmi_end)
1277 sc->pcmi_p = sc->pcmi_start;
1278
1279 if (++q == &sc->dmalist_pcmi[AUICH_DMALIST_MAX])
1280 q = sc->dmalist_pcmi;
1281 }
1282
1283 sc->dmap_pcmi = q;
1284 bus_space_write_1(sc->iot, sc->aud_ioh,
1285 AUICH_PCMI + AUICH_LVI,
1286 (sc->dmap_pcmi - sc->dmalist_pcmi - 1) &
1287 AUICH_LVI_MASK);
1288 }
1289
1290 if (sts & AUICH_BCIS && sc->sc_rintr)
1291 sc->sc_rintr(sc->sc_rarg);
1292
1293
1294 bus_space_write_2(sc->iot, sc->aud_ioh,
1295 AUICH_PCMI + sc->sc_sts_reg, sts &
1296 (AUICH_LVBCI | AUICH_CELV | AUICH_BCIS | AUICH_FIFOE));
1297 bus_space_write_2(sc->iot, sc->aud_ioh, AUICH_GSTS, AUICH_PIINT);
1298 ret++;
1299 }
1300
1301 if (gsts & AUICH_MIINT) {
1302 sts = bus_space_read_2(sc->iot, sc->aud_ioh,
1303 AUICH_MICI + sc->sc_sts_reg);
1304 DPRINTF(AUICH_DEBUG_DMA,
1305 ("auich_intr: ists=%b\n", sts, AUICH_ISTS_BITS));
1306 #ifdef AUICH_DEBUG
1307 if (sts & AUICH_FIFOE)
1308 printf("%s: mic fifo overrun\n", sc->sc_dev.dv_xname);
1309 #endif
1310
1311
1312
1313 bus_space_write_2(sc->iot, sc->aud_ioh, AUICH_GSTS, AUICH_MIINT);
1314 }
1315
1316 return ret;
1317 }
1318
1319 int
1320 auich_trigger_output(v, start, end, blksize, intr, arg, param)
1321 void *v;
1322 void *start, *end;
1323 int blksize;
1324 void (*intr)(void *);
1325 void *arg;
1326 struct audio_params *param;
1327 {
1328 struct auich_softc *sc = v;
1329 struct auich_dmalist *q;
1330 struct auich_dma *p;
1331
1332 DPRINTF(AUICH_DEBUG_DMA,
1333 ("auich_trigger_output(%x, %x, %d, %p, %p, %p)\n",
1334 start, end, blksize, intr, arg, param));
1335
1336 for (p = sc->sc_dmas; p && p->addr != start; p = p->next);
1337 if (!p)
1338 return -1;
1339
1340 sc->sc_pintr = intr;
1341 sc->sc_parg = arg;
1342
1343
1344
1345
1346
1347
1348 sc->pcmo_start = p->segs->ds_addr;
1349 sc->pcmo_p = sc->pcmo_start + blksize;
1350 sc->pcmo_end = sc->pcmo_start + ((char *)end - (char *)start);
1351 sc->pcmo_blksize = blksize;
1352
1353 q = sc->dmap_pcmo = sc->dmalist_pcmo;
1354 q->base = sc->pcmo_start;
1355 q->len = (blksize / sc->sc_sample_size) | AUICH_DMAF_IOC;
1356 if (++q == &sc->dmalist_pcmo[AUICH_DMALIST_MAX])
1357 q = sc->dmalist_pcmo;
1358 sc->dmap_pcmo = q;
1359
1360 bus_space_write_4(sc->iot, sc->aud_ioh, AUICH_PCMO + AUICH_BDBAR,
1361 sc->dmalist_pcmo_pa);
1362 bus_space_write_1(sc->iot, sc->aud_ioh, AUICH_PCMO + AUICH_CTRL,
1363 AUICH_IOCE | AUICH_FEIE | AUICH_LVBIE | AUICH_RPBM);
1364 bus_space_write_1(sc->iot, sc->aud_ioh, AUICH_PCMO + AUICH_LVI,
1365 (sc->dmap_pcmo - 1 - sc->dmalist_pcmo) & AUICH_LVI_MASK);
1366
1367 return 0;
1368 }
1369
1370 int
1371 auich_trigger_input(v, start, end, blksize, intr, arg, param)
1372 void *v;
1373 void *start, *end;
1374 int blksize;
1375 void (*intr)(void *);
1376 void *arg;
1377 struct audio_params *param;
1378 {
1379 struct auich_softc *sc = v;
1380 struct auich_dmalist *q;
1381 struct auich_dma *p;
1382
1383 DPRINTF(AUICH_DEBUG_DMA,
1384 ("auich_trigger_input(%x, %x, %d, %p, %p, %p)\n",
1385 start, end, blksize, intr, arg, param));
1386
1387 for (p = sc->sc_dmas; p && p->addr != start; p = p->next);
1388 if (!p)
1389 return -1;
1390
1391 sc->sc_rintr = intr;
1392 sc->sc_rarg = arg;
1393
1394
1395
1396
1397
1398
1399 sc->pcmi_start = p->segs->ds_addr;
1400 sc->pcmi_p = sc->pcmi_start + blksize;
1401 sc->pcmi_end = sc->pcmi_start + ((char *)end - (char *)start);
1402 sc->pcmi_blksize = blksize;
1403
1404 q = sc->dmap_pcmi = sc->dmalist_pcmi;
1405 q->base = sc->pcmi_start;
1406 q->len = (blksize / sc->sc_sample_size) | AUICH_DMAF_IOC;
1407 if (++q == &sc->dmalist_pcmi[AUICH_DMALIST_MAX])
1408 q = sc->dmalist_pcmi;
1409 sc->dmap_pcmi = q;
1410
1411 bus_space_write_4(sc->iot, sc->aud_ioh, AUICH_PCMI + AUICH_BDBAR,
1412 sc->dmalist_pcmi_pa);
1413 bus_space_write_1(sc->iot, sc->aud_ioh, AUICH_PCMI + AUICH_CTRL,
1414 AUICH_IOCE | AUICH_FEIE | AUICH_LVBIE | AUICH_RPBM);
1415 bus_space_write_1(sc->iot, sc->aud_ioh, AUICH_PCMI + AUICH_LVI,
1416 (sc->dmap_pcmi - 1 - sc->dmalist_pcmi) & AUICH_LVI_MASK);
1417
1418 return 0;
1419 }
1420
1421 void
1422 auich_powerhook(why, self)
1423 int why;
1424 void *self;
1425 {
1426 struct auich_softc *sc = (struct auich_softc *)self;
1427
1428 if (why != PWR_RESUME) {
1429
1430 DPRINTF(1, ("auich: power down\n"));
1431 sc->suspend = why;
1432 auich_read_codec(sc, AC97_REG_EXT_AUDIO_CTRL, &sc->ext_ctrl);
1433
1434 } else {
1435
1436 DPRINTF(1, ("auich: power resume\n"));
1437 if (sc->suspend == PWR_RESUME) {
1438 printf("%s: resume without suspend?\n",
1439 sc->sc_dev.dv_xname);
1440 sc->suspend = why;
1441 return;
1442 }
1443 sc->suspend = why;
1444 auich_reset_codec(sc);
1445 DELAY(1000);
1446 (sc->codec_if->vtbl->restore_ports)(sc->codec_if);
1447 auich_write_codec(sc, AC97_REG_EXT_AUDIO_CTRL, sc->ext_ctrl);
1448 }
1449 }
1450
1451
1452
1453
1454
1455
1456 unsigned int
1457 auich_calibrate(struct auich_softc *sc)
1458 {
1459 struct timeval t1, t2;
1460 u_int8_t ociv, nciv;
1461 u_int32_t wait_us, actual_48k_rate, bytes, ac97rate;
1462 void *temp_buffer;
1463 struct auich_dma *p;
1464 int i;
1465
1466 ac97rate = AUICH_FIXED_RATE;
1467
1468
1469
1470
1471
1472
1473
1474
1475 bytes = 16000;
1476 temp_buffer = auich_allocm(sc, AUMODE_RECORD, bytes, M_DEVBUF,
1477 M_NOWAIT);
1478 if (temp_buffer == NULL)
1479 return (ac97rate);
1480 for (p = sc->sc_dmas; p && p->addr != temp_buffer; p = p->next)
1481 ;
1482 if (p == NULL) {
1483 printf("auich_calibrate: bad address %p\n", temp_buffer);
1484 return (ac97rate);
1485 }
1486
1487 for (i = 0; i < AUICH_DMALIST_MAX; i++) {
1488 sc->dmalist_pcmi[i].base = p->map->dm_segs[0].ds_addr;
1489 sc->dmalist_pcmi[i].len = bytes / sc->sc_sample_size;
1490 }
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505 ociv = bus_space_read_1(sc->iot, sc->aud_ioh, AUICH_PCMI + AUICH_CIV);
1506 nciv = ociv;
1507 bus_space_write_4(sc->iot, sc->aud_ioh, AUICH_PCMI + AUICH_BDBAR,
1508 sc->dmalist_pcmi_pa);
1509 bus_space_write_1(sc->iot, sc->aud_ioh, AUICH_PCMI + AUICH_LVI,
1510 (0 - 1) & AUICH_LVI_MASK);
1511
1512
1513 microuptime(&t1);
1514 bus_space_write_1(sc->iot, sc->aud_ioh, AUICH_PCMI + AUICH_CTRL,
1515 AUICH_RPBM);
1516
1517
1518 while (nciv == ociv) {
1519 microuptime(&t2);
1520 if (t2.tv_sec - t1.tv_sec > 1)
1521 break;
1522 nciv = bus_space_read_1(sc->iot, sc->aud_ioh,
1523 AUICH_PCMI + AUICH_CIV);
1524 }
1525 microuptime(&t2);
1526
1527
1528 bus_space_write_1(sc->iot, sc->aud_ioh, AUICH_PCMI + AUICH_CTRL, AUICH_RR);
1529 bus_space_write_1(sc->iot, sc->aud_ioh, AUICH_MICI + AUICH_CTRL, AUICH_RR);
1530 DELAY(100);
1531
1532
1533 wait_us = ((t2.tv_sec - t1.tv_sec) * 1000000) + t2.tv_usec - t1.tv_usec;
1534
1535 #if 0
1536 auich_freem(sc, temp_buffer, M_DEVBUF);
1537 #endif
1538
1539 if (nciv == ociv) {
1540 printf("%s: ac97 link rate calibration timed out after %d us\n",
1541 sc->sc_dev.dv_xname, wait_us);
1542 return (ac97rate);
1543 }
1544
1545 actual_48k_rate = (bytes * 250000) / wait_us;
1546
1547 if (actual_48k_rate <= 48500)
1548 ac97rate = AUICH_FIXED_RATE;
1549 else
1550 ac97rate = actual_48k_rate;
1551
1552 printf("%s: measured ac97 link rate at %d Hz",
1553 sc->sc_dev.dv_xname, actual_48k_rate);
1554 if (ac97rate != actual_48k_rate)
1555 printf(", will use %d Hz", ac97rate);
1556 printf("\n");
1557
1558 return (ac97rate);
1559 }