1 /* $OpenBSD: auich.c,v 1.35 2003/06/12 18:08:09 mickey Exp $ */ 2 3 /* 4 * Copyright (c) 2000,2001 Michael Shalayeff 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT, 20 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 24 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 25 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 26 * THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 /* #define AUICH_DEBUG */ 30 /* 31 * AC'97 audio found on Intel 810/815/820/440MX chipsets. 32 * http://developer.intel.com/design/chipsets/datashts/290655.htm 33 * http://developer.intel.com/design/chipsets/manuals/298028.htm 34 * http://www.intel.com/design/chipsets/datashts/290716.htm 35 * http://www.intel.com/design/chipsets/datashts/290744.htm 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 /* 12.1.10 NAMBAR - native audio mixer base address register */ 57 #define AUICH_NAMBAR 0x10 58 /* 12.1.11 NABMBAR - native audio bus mastering base address register */ 59 #define AUICH_NABMBAR 0x14 60 61 /* table 12-3. native audio bus master control registers */ 62 #define AUICH_BDBAR 0x00 /* 8-byte aligned address */ 63 #define AUICH_CIV 0x04 /* 5 bits current index value */ 64 #define AUICH_LVI 0x05 /* 5 bits last valid index value */ 65 #define AUICH_LVI_MASK 0x1f 66 #define AUICH_STS 0x06 /* 16 bits status */ 67 #define AUICH_FIFOE 0x10 /* fifo error */ 68 #define AUICH_BCIS 0x08 /* r- buf cmplt int sts; wr ack */ 69 #define AUICH_LVBCI 0x04 /* r- last valid bci, wr ack */ 70 #define AUICH_CELV 0x02 /* current equals last valid */ 71 #define AUICH_DCH 0x01 /* dma halted */ 72 #define AUICH_ISTS_BITS "\020\01dch\02celv\03lvbci\04bcis\05fifoe" 73 #define AUICH_PICB 0x08 /* 16 bits */ 74 #define AUICH_PIV 0x0a /* 5 bits prefetched index value */ 75 #define AUICH_CTRL 0x0b /* control */ 76 #define AUICH_IOCE 0x10 /* int on completion enable */ 77 #define AUICH_FEIE 0x08 /* fifo error int enable */ 78 #define AUICH_LVBIE 0x04 /* last valid buf int enable */ 79 #define AUICH_RR 0x02 /* 1 - reset regs */ 80 #define AUICH_RPBM 0x01 /* 1 - run, 0 - pause */ 81 82 #define AUICH_PCMI 0x00 83 #define AUICH_PCMO 0x10 84 #define AUICH_MICI 0x20 85 86 #define AUICH_GCTRL 0x2c 87 #define AUICH_SSM_78 0x40000000 /* S/PDIF slots 7 and 8 */ 88 #define AUICH_SSM_69 0x80000000 /* S/PDIF slots 6 and 9 */ 89 #define AUICH_SSM_1011 0xc0000000 /* S/PDIF slots 10 and 11 */ 90 #define AUICH_POM16 0x000000 /* PCM out precision 16bit */ 91 #define AUICH_POM20 0x400000 /* PCM out precision 20bit */ 92 #define AUICH_PCM246_MASK 0x300000 93 #define AUICH_PCM2 0x000000 /* 2ch output */ 94 #define AUICH_PCM4 0x100000 /* 4ch output */ 95 #define AUICH_PCM6 0x200000 /* 6ch output */ 96 #define AUICH_S2RIE 0x40 /* int when tertiary codec resume */ 97 #define AUICH_SRIE 0x20 /* int when 2ndary codec resume */ 98 #define AUICH_PRIE 0x10 /* int when primary codec resume */ 99 #define AUICH_ACLSO 0x08 /* aclink shut off */ 100 #define AUICH_WRESET 0x04 /* warm reset */ 101 #define AUICH_CRESET 0x02 /* cold reset */ 102 #define AUICH_GIE 0x01 /* gpi int enable */ 103 #define AUICH_GSTS 0x30 104 #define AUICH_MD3 0x20000 /* pwr-dn semaphore for modem */ 105 #define AUICH_AD3 0x10000 /* pwr-dn semaphore for audio */ 106 #define AUICH_RCS 0x08000 /* read completion status */ 107 #define AUICH_B3S12 0x04000 /* bit 3 of slot 12 */ 108 #define AUICH_B2S12 0x02000 /* bit 2 of slot 12 */ 109 #define AUICH_B1S12 0x01000 /* bit 1 of slot 12 */ 110 #define AUICH_SRI 0x00800 /* secondary resume int */ 111 #define AUICH_PRI 0x00400 /* primary resume int */ 112 #define AUICH_SCR 0x00200 /* secondary codec ready */ 113 #define AUICH_PCR 0x00100 /* primary codec ready */ 114 #define AUICH_MINT 0x00080 /* mic in int */ 115 #define AUICH_POINT 0x00040 /* pcm out int */ 116 #define AUICH_PIINT 0x00020 /* pcm in int */ 117 #define AUICH_MOINT 0x00004 /* modem out int */ 118 #define AUICH_MIINT 0x00002 /* modem in int */ 119 #define AUICH_GSCI 0x00001 /* gpi status change */ 120 #define AUICH_GSTS_BITS "\020\01gsci\02miict\03moint\06piint\07point\010mint\011pcr\012scr\013pri\014sri\015b1s12\016b2s12\017b3s12\020rcs\021ad3\022md3" 121 #define AUICH_CAS 0x34 /* 1/8 bit */ 122 #define AUICH_SEMATIMO 1000 /* us */ 123 #define AUICH_RESETIMO 500000 /* us */ 124 125 /* 126 * according to the dev/audiovar.h AU_RING_SIZE is 2^16, what fits 127 * in our limits perfectly, i.e. setting it to higher value 128 * in your kernel config would improve perfomance, still 2^21 is the max 129 */ 130 #define AUICH_DMALIST_MAX 32 131 #define AUICH_DMASEG_MAX (65536*2) /* 64k samples, 2x16 bit samples */ 132 struct auich_dmalist { 133 u_int32_t base; 134 u_int32_t len; 135 #define AUICH_DMAF_IOC 0x80000000 /* 1-int on complete */ 136 #define AUICH_DMAF_BUP 0x40000000 /* 0-retrans last, 1-transmit 0 */ 137 }; 138 139 struct auich_dma { 140 bus_dmamap_t map; 141 caddr_t addr; 142 bus_dma_segment_t segs[AUICH_DMALIST_MAX]; 143 int nsegs; 144 size_t size; 145 struct auich_dma *next; 146 }; 147 148 struct auich_softc { 149 struct device sc_dev; 150 void *sc_ih; 151 152 audio_device_t sc_audev; 153 154 bus_space_tag_t iot; 155 bus_space_handle_t mix_ioh; 156 bus_space_handle_t aud_ioh; 157 bus_dma_tag_t dmat; 158 159 struct ac97_codec_if *codec_if; 160 struct ac97_host_if host_if; 161 162 /* dma scatter-gather buffer lists, aligned to 8 bytes */ 163 struct auich_dmalist *dmalist_pcmo, *dmap_pcmo, 164 dmasto_pcmo[AUICH_DMALIST_MAX+1]; 165 struct auich_dmalist *dmalist_pcmi, *dmap_pcmi, 166 dmasto_pcmi[AUICH_DMALIST_MAX+1];; 167 struct auich_dmalist *dmalist_mici, *dmap_mici, 168 dmasto_mici[AUICH_DMALIST_MAX+1];; 169 /* i/o buffer pointers */ 170 u_int32_t pcmo_start, pcmo_p, pcmo_end; 171 int pcmo_blksize, pcmo_fifoe; 172 u_int32_t pcmi_start, pcmi_p, pcmi_end; 173 int pcmi_blksize, pcmi_fifoe; 174 u_int32_t mici_start, mici_p, mici_end; 175 int mici_blksize, mici_fifoe; 176 struct auich_dma *sc_dmas; 177 178 void (*sc_pintr)(void *); 179 void *sc_parg; 180 181 void (*sc_rintr)(void *); 182 void *sc_rarg; 183 184 void *powerhook; 185 int suspend; 186 u_int16_t ext_ctrl; 187 int sc_sample_size; 188 int sc_sts_reg; 189 int sc_ignore_codecready; 190 int flags; 191 }; 192 193 #ifdef AUICH_DEBUG 194 #define DPRINTF(l,x) do { if (auich_debug & (l)) printf x; } while(0) 195 int auich_debug = 0xfffe; 196 #define AUICH_DEBUG_CODECIO 0x0001 197 #define AUICH_DEBUG_DMA 0x0002 198 #define AUICH_DEBUG_PARAM 0x0004 199 #else 200 #define DPRINTF(x,y) /* nothing */ 201 #endif 202 203 struct cfdriver auich_cd = { 204 NULL, "auich", DV_DULL 205 }; 206 207 int auich_match(struct device *, void *, void *); 208 void auich_attach(struct device *, struct device *, void *); 209 int auich_intr(void *); 210 211 struct cfattach auich_ca = { 212 sizeof(struct auich_softc), auich_match, auich_attach 213 }; 214 215 static const struct auich_devtype { 216 int vendor; 217 int product; 218 int options; 219 char name[8]; 220 } auich_devices[] = { 221 { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801AA_ACA, 0, "ICH" }, 222 { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801AB_ACA, 0, "ICH0" }, 223 { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801BA_ACA, 0, "ICH2" }, 224 { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801CA_ACA, 0, "ICH3" }, 225 { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801DB_ACA, 0, "ICH4" }, 226 { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801EB_ACA, 0, "ICH5" }, 227 { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82440MX_ACA, 0, "440MX" }, 228 { PCI_VENDOR_SIS, PCI_PRODUCT_SIS_7012_ACA, 0, "SiS7012" }, 229 { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE_ACA, 0, "nForce" }, 230 { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE2_ACA, 0, "nForce2" }, 231 { PCI_VENDOR_AMD, PCI_PRODUCT_AMD_PBC768_ACA, 0, "AMD768" }, 232 { PCI_VENDOR_AMD, PCI_PRODUCT_AMD_8111_ACA, 0, "AMD8111" }, 233 }; 234 235 int auich_open(void *, int); 236 void auich_close(void *); 237 int auich_query_encoding(void *, struct audio_encoding *); 238 int auich_set_params(void *, int, int, struct audio_params *, 239 struct audio_params *); 240 int auich_round_blocksize(void *, int); 241 int auich_halt_output(void *); 242 int auich_halt_input(void *); 243 int auich_getdev(void *, struct audio_device *); 244 int auich_set_port(void *, mixer_ctrl_t *); 245 int auich_get_port(void *, mixer_ctrl_t *); 246 int auich_query_devinfo(void *, mixer_devinfo_t *); 247 void *auich_allocm(void *, int, size_t, int, int); 248 void auich_freem(void *, void *, int); 249 size_t auich_round_buffersize(void *, int, size_t); 250 paddr_t auich_mappage(void *, void *, off_t, int); 251 int auich_get_props(void *); 252 int auich_trigger_output(void *, void *, void *, int, void (*)(void *), 253 void *, struct audio_params *); 254 int auich_trigger_input(void *, void *, void *, int, void (*)(void *), 255 void *, struct audio_params *); 256 257 void auich_powerhook(int, void *); 258 259 struct audio_hw_if auich_hw_if = { 260 auich_open, 261 auich_close, 262 NULL, /* drain */ 263 auich_query_encoding, 264 auich_set_params, 265 auich_round_blocksize, 266 NULL, /* commit_setting */ 267 NULL, /* init_output */ 268 NULL, /* init_input */ 269 NULL, /* start_output */ 270 NULL, /* start_input */ 271 auich_halt_output, 272 auich_halt_input, 273 NULL, /* speaker_ctl */ 274 auich_getdev, 275 NULL, /* getfd */ 276 auich_set_port, 277 auich_get_port, 278 auich_query_devinfo, 279 auich_allocm, 280 auich_freem, 281 auich_round_buffersize, 282 auich_mappage, 283 auich_get_props, 284 auich_trigger_output, 285 auich_trigger_input 286 }; 287 288 int auich_attach_codec(void *, struct ac97_codec_if *); 289 int auich_read_codec(void *, u_int8_t, u_int16_t *); 290 int auich_write_codec(void *, u_int8_t, u_int16_t); 291 void auich_reset_codec(void *); 292 enum ac97_host_flags auich_flags_codec(void *); 293 294 int 295 auich_match(parent, match, aux) 296 struct device *parent; 297 void *match; 298 void *aux; 299 { 300 struct pci_attach_args *pa = aux; 301 int i; 302 303 for (i = sizeof(auich_devices)/sizeof(auich_devices[0]); i--;) 304 if (PCI_VENDOR(pa->pa_id) == auich_devices[i].vendor && 305 PCI_PRODUCT(pa->pa_id) == auich_devices[i].product) 306 return 1; 307 308 return 0; 309 } 310 311 void 312 auich_attach(parent, self, aux) 313 struct device *parent, *self; 314 void *aux; 315 { 316 struct auich_softc *sc = (struct auich_softc *)self; 317 struct pci_attach_args *pa = aux; 318 pci_intr_handle_t ih; 319 bus_size_t mix_size, aud_size; 320 pcireg_t csr; 321 const char *intrstr; 322 u_int32_t status; 323 int i; 324 325 /* SiS 7012 needs special handling */ 326 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_SIS && 327 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_SIS_7012_ACA) { 328 sc->sc_sts_reg = AUICH_PICB; 329 sc->sc_sample_size = 1; 330 } else { 331 sc->sc_sts_reg = AUICH_STS; 332 sc->sc_sample_size = 2; 333 } 334 335 if (pci_mapreg_map(pa, AUICH_NAMBAR, PCI_MAPREG_TYPE_IO, 0, 336 &sc->iot, &sc->mix_ioh, NULL, &mix_size, 0)) { 337 printf(": can't map codec i/o space\n"); 338 return; 339 } 340 if (pci_mapreg_map(pa, AUICH_NABMBAR, PCI_MAPREG_TYPE_IO, 0, 341 &sc->iot, &sc->aud_ioh, NULL, &aud_size, 0)) { 342 printf(": can't map device i/o space\n"); 343 bus_space_unmap(sc->iot, sc->mix_ioh, mix_size); 344 return; 345 } 346 sc->dmat = pa->pa_dmat; 347 348 /* enable bus mastering (should not it be mi?) */ 349 csr = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); 350 pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, 351 csr | PCI_COMMAND_MASTER_ENABLE); 352 353 if (pci_intr_map(pa, &ih)) { 354 printf(": can't map interrupt\n"); 355 bus_space_unmap(sc->iot, sc->aud_ioh, aud_size); 356 bus_space_unmap(sc->iot, sc->mix_ioh, mix_size); 357 return; 358 } 359 intrstr = pci_intr_string(pa->pa_pc, ih); 360 sc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_AUDIO, auich_intr, 361 sc, sc->sc_dev.dv_xname); 362 if (!sc->sc_ih) { 363 printf(": can't establish interrupt"); 364 if (intrstr) 365 printf(" at %s", intrstr); 366 printf("\n"); 367 bus_space_unmap(sc->iot, sc->aud_ioh, aud_size); 368 bus_space_unmap(sc->iot, sc->mix_ioh, mix_size); 369 return; 370 } 371 372 for (i = sizeof(auich_devices)/sizeof(auich_devices[0]); i--;) 373 if (PCI_PRODUCT(pa->pa_id) == auich_devices[i].product) 374 break; 375 376 snprintf(sc->sc_audev.name, sizeof sc->sc_audev.name, "%s AC97", 377 auich_devices[i].name); 378 snprintf(sc->sc_audev.version, sizeof sc->sc_audev.version, "0x%02x", 379 PCI_REVISION(pa->pa_class)); 380 strlcpy(sc->sc_audev.config, sc->sc_dev.dv_xname, 381 sizeof sc->sc_audev.config); 382 383 printf(": %s, %s\n", intrstr, sc->sc_audev.name); 384 385 /* allocate dma lists */ 386 #define a(a) (void *)(((u_long)(a) + sizeof(*(a)) - 1) & ~(sizeof(*(a))-1)) 387 sc->dmalist_pcmo = sc->dmap_pcmo = a(sc->dmasto_pcmo); 388 sc->dmalist_pcmi = sc->dmap_pcmi = a(sc->dmasto_pcmi); 389 sc->dmalist_mici = sc->dmap_mici = a(sc->dmasto_mici); 390 #undef a 391 DPRINTF(AUICH_DEBUG_DMA, ("auich_attach: lists %p %p %p\n", 392 sc->dmalist_pcmo, sc->dmalist_pcmi, sc->dmalist_mici)); 393 394 /* Reset codec and AC'97 */ 395 auich_reset_codec(sc); 396 status = bus_space_read_4(sc->iot, sc->aud_ioh, AUICH_GSTS); 397 if (!(status & AUICH_PCR)) { /* reset failure */ 398 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_INTEL && 399 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_82801DB_ACA) { 400 /* MSI 845G Max never return AUICH_PCR */ 401 sc->sc_ignore_codecready = 1; 402 } else 403 return; 404 } 405 406 sc->host_if.arg = sc; 407 sc->host_if.attach = auich_attach_codec; 408 sc->host_if.read = auich_read_codec; 409 sc->host_if.write = auich_write_codec; 410 sc->host_if.reset = auich_reset_codec; 411 sc->host_if.flags = auich_flags_codec; 412 if (sc->sc_dev.dv_cfdata->cf_flags & 0x0001) 413 sc->flags = AC97_HOST_SWAPPED_CHANNELS; 414 415 if (ac97_attach(&sc->host_if) != 0) { 416 pci_intr_disestablish(pa->pa_pc, sc->sc_ih); 417 bus_space_unmap(sc->iot, sc->aud_ioh, aud_size); 418 bus_space_unmap(sc->iot, sc->mix_ioh, mix_size); 419 return; 420 } 421 422 audio_attach_mi(&auich_hw_if, sc, &sc->sc_dev); 423 424 /* Watch for power changes */ 425 sc->suspend = PWR_RESUME; 426 sc->powerhook = powerhook_establish(auich_powerhook, sc); 427 } 428 429 int 430 auich_read_codec(v, reg, val) 431 void *v; 432 u_int8_t reg; 433 u_int16_t *val; 434 { 435 struct auich_softc *sc = v; 436 int i; 437 438 /* wait for an access semaphore */ 439 for (i = AUICH_SEMATIMO; i-- && 440 bus_space_read_1(sc->iot, sc->aud_ioh, AUICH_CAS) & 1; DELAY(1)); 441 442 if (!sc->sc_ignore_codecready && i < 0) { 443 DPRINTF(AUICH_DEBUG_CODECIO, 444 ("%s: read_codec timeout\n", sc->sc_dev.dv_xname)); 445 return (-1); 446 } 447 448 *val = bus_space_read_2(sc->iot, sc->mix_ioh, reg); 449 DPRINTF(AUICH_DEBUG_CODECIO, ("%s: read_codec(%x, %x)\n", 450 sc->sc_dev.dv_xname, reg, *val)); 451 return (0); 452 } 453 454 int 455 auich_write_codec(v, reg, val) 456 void *v; 457 u_int8_t reg; 458 u_int16_t val; 459 { 460 struct auich_softc *sc = v; 461 int i; 462 463 /* wait for an access semaphore */ 464 for (i = AUICH_SEMATIMO; i-- && 465 bus_space_read_1(sc->iot, sc->aud_ioh, AUICH_CAS) & 1; DELAY(1)); 466 467 if (sc->sc_ignore_codecready || i >= 0) { 468 DPRINTF(AUICH_DEBUG_CODECIO, ("%s: write_codec(%x, %x)\n", 469 sc->sc_dev.dv_xname, reg, val)); 470 bus_space_write_2(sc->iot, sc->mix_ioh, reg, val); 471 return (0); 472 } else { 473 DPRINTF(AUICH_DEBUG_CODECIO, 474 ("%s: write_codec timeout\n", sc->sc_dev.dv_xname)); 475 return (-1); 476 } 477 } 478 479 int 480 auich_attach_codec(v, cif) 481 void *v; 482 struct ac97_codec_if *cif; 483 { 484 struct auich_softc *sc = v; 485 486 sc->codec_if = cif; 487 return 0; 488 } 489 490 void 491 auich_reset_codec(v) 492 void *v; 493 { 494 struct auich_softc *sc = v; 495 u_int32_t control; 496 int i; 497 498 control = bus_space_read_4(sc->iot, sc->aud_ioh, AUICH_GCTRL); 499 control &= ~(AUICH_ACLSO | AUICH_PCM246_MASK); 500 control |= (control & AUICH_CRESET) ? AUICH_WRESET : AUICH_CRESET; 501 bus_space_write_4(sc->iot, sc->aud_ioh, AUICH_GCTRL, AUICH_CRESET); 502 503 for (i = AUICH_RESETIMO; i-- && 504 !(bus_space_read_4(sc->iot, sc->aud_ioh, AUICH_GSTS) & AUICH_PCR); 505 DELAY(1)); 506 507 if (i < 0) 508 DPRINTF(AUICH_DEBUG_CODECIO, 509 ("%s: reset_codec timeout\n", sc->sc_dev.dv_xname)); 510 } 511 512 enum ac97_host_flags 513 auich_flags_codec(void *v) 514 { 515 struct auich_softc *sc = v; 516 517 return (sc->flags); 518 } 519 520 int 521 auich_open(v, flags) 522 void *v; 523 int flags; 524 { 525 return 0; 526 } 527 528 void 529 auich_close(v) 530 void *v; 531 { 532 } 533 534 int 535 auich_query_encoding(v, aep) 536 void *v; 537 struct audio_encoding *aep; 538 { 539 switch (aep->index) { 540 case 0: 541 strlcpy(aep->name, AudioEulinear, sizeof aep->name); 542 aep->encoding = AUDIO_ENCODING_ULINEAR; 543 aep->precision = 8; 544 aep->flags = 0; 545 return (0); 546 case 1: 547 strlcpy(aep->name, AudioEmulaw, sizeof aep->name); 548 aep->encoding = AUDIO_ENCODING_ULAW; 549 aep->precision = 8; 550 aep->flags = AUDIO_ENCODINGFLAG_EMULATED; 551 return (0); 552 case 2: 553 strlcpy(aep->name, AudioEalaw, sizeof aep->name); 554 aep->encoding = AUDIO_ENCODING_ALAW; 555 aep->precision = 8; 556 aep->flags = AUDIO_ENCODINGFLAG_EMULATED; 557 return (0); 558 case 3: 559 strlcpy(aep->name, AudioEslinear, sizeof aep->name); 560 aep->encoding = AUDIO_ENCODING_SLINEAR; 561 aep->precision = 8; 562 aep->flags = AUDIO_ENCODINGFLAG_EMULATED; 563 return (0); 564 case 4: 565 strlcpy(aep->name, AudioEslinear_le, sizeof aep->name); 566 aep->encoding = AUDIO_ENCODING_SLINEAR_LE; 567 aep->precision = 16; 568 aep->flags = 0; 569 return (0); 570 case 5: 571 strlcpy(aep->name, AudioEulinear_le, sizeof aep->name); 572 aep->encoding = AUDIO_ENCODING_ULINEAR_LE; 573 aep->precision = 16; 574 aep->flags = AUDIO_ENCODINGFLAG_EMULATED; 575 return (0); 576 case 6: 577 strlcpy(aep->name, AudioEslinear_be, sizeof aep->name); 578 aep->encoding = AUDIO_ENCODING_SLINEAR_BE; 579 aep->precision = 16; 580 aep->flags = AUDIO_ENCODINGFLAG_EMULATED; 581 return (0); 582 case 7: 583 strlcpy(aep->name, AudioEulinear_be, sizeof aep->name); 584 aep->encoding = AUDIO_ENCODING_ULINEAR_BE; 585 aep->precision = 16; 586 aep->flags = AUDIO_ENCODINGFLAG_EMULATED; 587 return (0); 588 default: 589 return (EINVAL); 590 } 591 } 592 593 int 594 auich_set_params(v, setmode, usemode, play, rec) 595 void *v; 596 int setmode, usemode; 597 struct audio_params *play, *rec; 598 { 599 struct auich_softc *sc = v; 600 int error; 601 602 if (setmode & AUMODE_PLAY) { 603 play->factor = 1; 604 play->sw_code = NULL; 605 switch(play->encoding) { 606 case AUDIO_ENCODING_ULAW: 607 switch (play->channels) { 608 case 1: 609 play->factor = 4; 610 play->sw_code = mulaw_to_slinear16_mts; 611 break; 612 case 2: 613 play->factor = 2; 614 play->sw_code = mulaw_to_slinear16; 615 break; 616 default: 617 return (EINVAL); 618 } 619 break; 620 case AUDIO_ENCODING_SLINEAR_LE: 621 switch (play->precision) { 622 case 8: 623 switch (play->channels) { 624 case 1: 625 play->factor = 4; 626 play->sw_code = linear8_to_linear16_mts; 627 break; 628 case 2: 629 play->factor = 2; 630 play->sw_code = linear8_to_linear16; 631 break; 632 default: 633 return (EINVAL); 634 } 635 break; 636 case 16: 637 switch (play->channels) { 638 case 1: 639 play->factor = 2; 640 play->sw_code = noswap_bytes_mts; 641 break; 642 case 2: 643 break; 644 default: 645 return (EINVAL); 646 } 647 break; 648 default: 649 return (EINVAL); 650 } 651 break; 652 case AUDIO_ENCODING_ULINEAR_LE: 653 switch (play->precision) { 654 case 8: 655 switch (play->channels) { 656 case 1: 657 play->factor = 4; 658 play->sw_code = ulinear8_to_linear16_mts; 659 break; 660 case 2: 661 play->factor = 2; 662 play->sw_code = ulinear8_to_linear16; 663 break; 664 default: 665 return (EINVAL); 666 } 667 break; 668 case 16: 669 switch (play->channels) { 670 case 1: 671 play->factor = 2; 672 play->sw_code = change_sign16_mts; 673 break; 674 case 2: 675 play->sw_code = change_sign16; 676 break; 677 default: 678 return (EINVAL); 679 } 680 break; 681 default: 682 return (EINVAL); 683 } 684 break; 685 case AUDIO_ENCODING_ALAW: 686 switch (play->channels) { 687 case 1: 688 play->factor = 4; 689 play->sw_code = alaw_to_slinear16_mts; 690 case 2: 691 play->factor = 2; 692 play->sw_code = alaw_to_slinear16; 693 default: 694 return (EINVAL); 695 } 696 break; 697 case AUDIO_ENCODING_SLINEAR_BE: 698 switch (play->precision) { 699 case 8: 700 switch (play->channels) { 701 case 1: 702 play->factor = 4; 703 play->sw_code = linear8_to_linear16_mts; 704 break; 705 case 2: 706 play->factor = 2; 707 play->sw_code = linear8_to_linear16; 708 break; 709 default: 710 return (EINVAL); 711 } 712 break; 713 case 16: 714 switch (play->channels) { 715 case 1: 716 play->factor = 2; 717 play->sw_code = swap_bytes_mts; 718 break; 719 case 2: 720 play->sw_code = swap_bytes; 721 break; 722 default: 723 return (EINVAL); 724 } 725 break; 726 default: 727 return (EINVAL); 728 } 729 break; 730 case AUDIO_ENCODING_ULINEAR_BE: 731 switch (play->precision) { 732 case 8: 733 switch (play->channels) { 734 case 1: 735 play->factor = 4; 736 play->sw_code = ulinear8_to_linear16_mts; 737 break; 738 case 2: 739 play->factor = 2; 740 play->sw_code = ulinear8_to_linear16; 741 break; 742 default: 743 return (EINVAL); 744 } 745 break; 746 case 16: 747 switch (play->channels) { 748 case 1: 749 play->factor = 2; 750 play->sw_code = change_sign16_swap_bytes_mts; 751 break; 752 case 2: 753 play->sw_code = change_sign16_swap_bytes; 754 break; 755 default: 756 return (EINVAL); 757 } 758 break; 759 default: 760 return (EINVAL); 761 } 762 break; 763 default: 764 return (EINVAL); 765 } 766 767 if ((error = ac97_set_rate(sc->codec_if, play, AUMODE_PLAY))) 768 return (error); 769 } 770 771 if (setmode & AUMODE_RECORD) { 772 rec->factor = 1; 773 rec->sw_code = 0; 774 switch(rec->encoding) { 775 case AUDIO_ENCODING_ULAW: 776 rec->sw_code = ulinear8_to_mulaw; 777 break; 778 case AUDIO_ENCODING_SLINEAR_LE: 779 if (rec->precision == 8) 780 rec->sw_code = change_sign8; 781 break; 782 case AUDIO_ENCODING_ULINEAR_LE: 783 if (rec->precision == 16) 784 rec->sw_code = change_sign16; 785 break; 786 case AUDIO_ENCODING_ALAW: 787 rec->sw_code = ulinear8_to_alaw; 788 break; 789 case AUDIO_ENCODING_SLINEAR_BE: 790 if (rec->precision == 16) 791 rec->sw_code = swap_bytes; 792 else 793 rec->sw_code = change_sign8; 794 break; 795 case AUDIO_ENCODING_ULINEAR_BE: 796 if (rec->precision == 16) 797 rec->sw_code = swap_bytes_change_sign16; 798 break; 799 default: 800 return (EINVAL); 801 } 802 803 if ((error = ac97_set_rate(sc->codec_if, rec, AUMODE_RECORD))) 804 return (error); 805 } 806 807 return (0); 808 } 809 810 int 811 auich_round_blocksize(v, blk) 812 void *v; 813 int blk; 814 { 815 return blk & ~0x3f; 816 } 817 818 int 819 auich_halt_output(v) 820 void *v; 821 { 822 struct auich_softc *sc = v; 823 824 DPRINTF(AUICH_DEBUG_DMA, ("%s: halt_output\n", sc->sc_dev.dv_xname)); 825 826 bus_space_write_1(sc->iot, sc->aud_ioh, AUICH_PCMO + AUICH_CTRL, AUICH_RR); 827 828 return 0; 829 } 830 831 int 832 auich_halt_input(v) 833 void *v; 834 { 835 struct auich_softc *sc = v; 836 837 DPRINTF(AUICH_DEBUG_DMA, 838 ("%s: halt_input\n", sc->sc_dev.dv_xname)); 839 840 /* XXX halt both unless known otherwise */ 841 842 bus_space_write_1(sc->iot, sc->aud_ioh, AUICH_PCMI + AUICH_CTRL, AUICH_RR); 843 bus_space_write_1(sc->iot, sc->aud_ioh, AUICH_MICI + AUICH_CTRL, AUICH_RR); 844 845 return 0; 846 } 847 848 int 849 auich_getdev(v, adp) 850 void *v; 851 struct audio_device *adp; 852 { 853 struct auich_softc *sc = v; 854 *adp = sc->sc_audev; 855 return 0; 856 } 857 858 int 859 auich_set_port(v, cp) 860 void *v; 861 mixer_ctrl_t *cp; 862 { 863 struct auich_softc *sc = v; 864 return sc->codec_if->vtbl->mixer_set_port(sc->codec_if, cp); 865 } 866 867 int 868 auich_get_port(v, cp) 869 void *v; 870 mixer_ctrl_t *cp; 871 { 872 struct auich_softc *sc = v; 873 return sc->codec_if->vtbl->mixer_get_port(sc->codec_if, cp); 874 } 875 876 int 877 auich_query_devinfo(v, dp) 878 void *v; 879 mixer_devinfo_t *dp; 880 { 881 struct auich_softc *sc = v; 882 return sc->codec_if->vtbl->query_devinfo(sc->codec_if, dp); 883 } 884 885 void * 886 auich_allocm(v, direction, size, pool, flags) 887 void *v; 888 int direction; 889 size_t size; 890 int pool, flags; 891 { 892 struct auich_softc *sc = v; 893 struct auich_dma *p; 894 int error; 895 896 if (size > AUICH_DMALIST_MAX * AUICH_DMASEG_MAX) 897 return NULL; 898 899 p = malloc(sizeof(*p), pool, flags); 900 if (!p) 901 return NULL; 902 bzero(p, sizeof(*p)); 903 904 p->size = size; 905 if ((error = bus_dmamem_alloc(sc->dmat, p->size, NBPG, 0, p->segs, 906 1, &p->nsegs, BUS_DMA_NOWAIT)) != 0) { 907 printf("%s: unable to allocate dma, error = %d\n", 908 sc->sc_dev.dv_xname, error); 909 free(p, pool); 910 return NULL; 911 } 912 913 if ((error = bus_dmamem_map(sc->dmat, p->segs, p->nsegs, p->size, 914 &p->addr, BUS_DMA_NOWAIT | BUS_DMA_COHERENT)) != 0) { 915 printf("%s: unable to map dma, error = %d\n", 916 sc->sc_dev.dv_xname, error); 917 bus_dmamem_free(sc->dmat, p->segs, p->nsegs); 918 free(p, pool); 919 return NULL; 920 } 921 922 if ((error = bus_dmamap_create(sc->dmat, p->size, 1, 923 p->size, 0, BUS_DMA_NOWAIT, &p->map)) != 0) { 924 printf("%s: unable to create dma map, error = %d\n", 925 sc->sc_dev.dv_xname, error); 926 bus_dmamem_unmap(sc->dmat, p->addr, size); 927 bus_dmamem_free(sc->dmat, p->segs, p->nsegs); 928 free(p, pool); 929 return NULL; 930 } 931 932 if ((error = bus_dmamap_load(sc->dmat, p->map, p->addr, p->size, 933 NULL, BUS_DMA_NOWAIT)) != 0) { 934 printf("%s: unable to load dma map, error = %d\n", 935 sc->sc_dev.dv_xname, error); 936 bus_dmamap_destroy(sc->dmat, p->map); 937 bus_dmamem_unmap(sc->dmat, p->addr, size); 938 bus_dmamem_free(sc->dmat, p->segs, p->nsegs); 939 free(p, pool); 940 return NULL; 941 } 942 943 p->next = sc->sc_dmas; 944 sc->sc_dmas = p; 945 946 return p->addr; 947 } 948 949 void 950 auich_freem(v, ptr, pool) 951 void *v; 952 void *ptr; 953 int pool; 954 { 955 struct auich_softc *sc = v; 956 struct auich_dma *p; 957 958 for (p = sc->sc_dmas; p->addr != ptr; p = p->next) 959 if (p->next == NULL) { 960 printf("auich_freem: trying to free not allocated memory"); 961 return; 962 } 963 964 bus_dmamap_unload(sc->dmat, p->map); 965 bus_dmamap_destroy(sc->dmat, p->map); 966 bus_dmamem_unmap(sc->dmat, p->addr, p->size); 967 bus_dmamem_free(sc->dmat, p->segs, p->nsegs); 968 free(p, pool); 969 } 970 971 size_t 972 auich_round_buffersize(v, direction, size) 973 void *v; 974 int direction; 975 size_t size; 976 { 977 if (size > AUICH_DMALIST_MAX * AUICH_DMASEG_MAX) 978 size = AUICH_DMALIST_MAX * AUICH_DMASEG_MAX; 979 980 return size; 981 } 982 983 paddr_t 984 auich_mappage(v, mem, off, prot) 985 void *v; 986 void *mem; 987 off_t off; 988 int prot; 989 { 990 struct auich_softc *sc = v; 991 struct auich_dma *p; 992 993 if (off < 0) 994 return -1; 995 996 for (p = sc->sc_dmas; p && p->addr != mem; p = p->next); 997 if (!p) 998 return -1; 999 1000 return bus_dmamem_mmap(sc->dmat, p->segs, p->nsegs, 1001 off, prot, BUS_DMA_WAITOK); 1002 } 1003 1004 int 1005 auich_get_props(v) 1006 void *v; 1007 { 1008 return AUDIO_PROP_MMAP | AUDIO_PROP_INDEPENDENT | AUDIO_PROP_FULLDUPLEX; 1009 } 1010 1011 int 1012 auich_intr(v) 1013 void *v; 1014 { 1015 struct auich_softc *sc = v; 1016 int ret = 0, sts, gsts, i; 1017 1018 gsts = bus_space_read_2(sc->iot, sc->aud_ioh, AUICH_GSTS); 1019 DPRINTF(AUICH_DEBUG_DMA, ("auich_intr: gsts=%b\n", gsts, AUICH_GSTS_BITS)); 1020 1021 if (gsts & AUICH_POINT) { 1022 sts = bus_space_read_2(sc->iot, sc->aud_ioh, 1023 AUICH_PCMO + sc->sc_sts_reg); 1024 DPRINTF(AUICH_DEBUG_DMA, 1025 ("auich_intr: osts=%b\n", sts, AUICH_ISTS_BITS)); 1026 1027 if (sts & AUICH_FIFOE) { 1028 printf("%s: fifo underrun # %u\n", 1029 sc->sc_dev.dv_xname, ++sc->pcmo_fifoe); 1030 } 1031 1032 i = bus_space_read_1(sc->iot, sc->aud_ioh, AUICH_PCMO + AUICH_CIV); 1033 if (sts & (AUICH_LVBCI | AUICH_CELV)) { 1034 struct auich_dmalist *q, *qe; 1035 1036 q = sc->dmap_pcmo; 1037 qe = &sc->dmalist_pcmo[i]; 1038 1039 while (q != qe) { 1040 1041 q->base = sc->pcmo_p; 1042 q->len = (sc->pcmo_blksize / 1043 sc->sc_sample_size) | AUICH_DMAF_IOC; 1044 DPRINTF(AUICH_DEBUG_DMA, 1045 ("auich_intr: %p, %p = %x @ %p\n", 1046 qe, q, sc->pcmo_blksize / 1047 sc->sc_sample_size, sc->pcmo_p)); 1048 1049 sc->pcmo_p += sc->pcmo_blksize; 1050 if (sc->pcmo_p >= sc->pcmo_end) 1051 sc->pcmo_p = sc->pcmo_start; 1052 1053 if (++q == &sc->dmalist_pcmo[AUICH_DMALIST_MAX]) 1054 q = sc->dmalist_pcmo; 1055 } 1056 1057 sc->dmap_pcmo = q; 1058 bus_space_write_1(sc->iot, sc->aud_ioh, 1059 AUICH_PCMO + AUICH_LVI, 1060 (sc->dmap_pcmo - sc->dmalist_pcmo - 1) & 1061 AUICH_LVI_MASK); 1062 } 1063 1064 if (sts & AUICH_BCIS && sc->sc_pintr) 1065 sc->sc_pintr(sc->sc_parg); 1066 1067 /* int ack */ 1068 bus_space_write_2(sc->iot, sc->aud_ioh, 1069 AUICH_PCMO + sc->sc_sts_reg, sts & 1070 (AUICH_LVBCI | AUICH_CELV | AUICH_BCIS | AUICH_FIFOE)); 1071 bus_space_write_2(sc->iot, sc->aud_ioh, AUICH_GSTS, AUICH_POINT); 1072 ret++; 1073 } 1074 1075 if (gsts & AUICH_PIINT) { 1076 sts = bus_space_read_2(sc->iot, sc->aud_ioh, 1077 AUICH_PCMI + sc->sc_sts_reg); 1078 DPRINTF(AUICH_DEBUG_DMA, 1079 ("auich_intr: ists=%b\n", sts, AUICH_ISTS_BITS)); 1080 1081 if (sts & AUICH_FIFOE) { 1082 printf("%s: in fifo overrun # %u\n", 1083 sc->sc_dev.dv_xname, ++sc->pcmi_fifoe); 1084 } 1085 1086 i = bus_space_read_1(sc->iot, sc->aud_ioh, AUICH_PCMI + AUICH_CIV); 1087 if (sts & (AUICH_LVBCI | AUICH_CELV)) { 1088 struct auich_dmalist *q, *qe; 1089 1090 q = sc->dmap_pcmi; 1091 qe = &sc->dmalist_pcmi[i]; 1092 1093 while (q != qe) { 1094 1095 q->base = sc->pcmi_p; 1096 q->len = (sc->pcmi_blksize / 1097 sc->sc_sample_size) | AUICH_DMAF_IOC; 1098 DPRINTF(AUICH_DEBUG_DMA, 1099 ("auich_intr: %p, %p = %x @ %p\n", 1100 qe, q, sc->pcmi_blksize / 1101 sc->sc_sample_size, sc->pcmi_p)); 1102 1103 sc->pcmi_p += sc->pcmi_blksize; 1104 if (sc->pcmi_p >= sc->pcmi_end) 1105 sc->pcmi_p = sc->pcmi_start; 1106 1107 if (++q == &sc->dmalist_pcmi[AUICH_DMALIST_MAX]) 1108 q = sc->dmalist_pcmi; 1109 } 1110 1111 sc->dmap_pcmi = q; 1112 bus_space_write_1(sc->iot, sc->aud_ioh, 1113 AUICH_PCMI + AUICH_LVI, 1114 (sc->dmap_pcmi - sc->dmalist_pcmi - 1) & 1115 AUICH_LVI_MASK); 1116 } 1117 1118 if (sts & AUICH_BCIS && sc->sc_rintr) 1119 sc->sc_rintr(sc->sc_rarg); 1120 1121 /* int ack */ 1122 bus_space_write_2(sc->iot, sc->aud_ioh, 1123 AUICH_PCMI + sc->sc_sts_reg, sts & 1124 (AUICH_LVBCI | AUICH_CELV | AUICH_BCIS | AUICH_FIFOE)); 1125 bus_space_write_2(sc->iot, sc->aud_ioh, AUICH_GSTS, AUICH_POINT); 1126 ret++; 1127 } 1128 1129 if (gsts & AUICH_MIINT) { 1130 sts = bus_space_read_2(sc->iot, sc->aud_ioh, 1131 AUICH_MICI + sc->sc_sts_reg); 1132 DPRINTF(AUICH_DEBUG_DMA, 1133 ("auich_intr: ists=%b\n", sts, AUICH_ISTS_BITS)); 1134 if (sts & AUICH_FIFOE) 1135 printf("%s: mic fifo overrun\n", sc->sc_dev.dv_xname); 1136 1137 /* TODO mic input dma */ 1138 1139 bus_space_write_2(sc->iot, sc->aud_ioh, AUICH_GSTS, AUICH_MIINT); 1140 } 1141 1142 return ret; 1143 } 1144 1145 int 1146 auich_trigger_output(v, start, end, blksize, intr, arg, param) 1147 void *v; 1148 void *start, *end; 1149 int blksize; 1150 void (*intr)(void *); 1151 void *arg; 1152 struct audio_params *param; 1153 { 1154 struct auich_softc *sc = v; 1155 struct auich_dmalist *q; 1156 struct auich_dma *p; 1157 1158 DPRINTF(AUICH_DEBUG_DMA, 1159 ("auich_trigger_output(%x, %x, %d, %p, %p, %p)\n", 1160 start, end, blksize, intr, arg, param)); 1161 1162 for (p = sc->sc_dmas; p && p->addr != start; p = p->next); 1163 if (!p) 1164 return -1; 1165 1166 sc->sc_pintr = intr; 1167 sc->sc_parg = arg; 1168 1169 /* 1170 * The logic behind this is: 1171 * setup one buffer to play, then LVI dump out the rest 1172 * to the scatter-gather chain. 1173 */ 1174 sc->pcmo_start = p->segs->ds_addr; 1175 sc->pcmo_p = sc->pcmo_start + blksize; 1176 sc->pcmo_end = sc->pcmo_start + (end - start); 1177 sc->pcmo_blksize = blksize; 1178 1179 q = sc->dmap_pcmo = sc->dmalist_pcmo; 1180 q->base = sc->pcmo_start; 1181 q->len = (blksize / sc->sc_sample_size) | AUICH_DMAF_IOC; 1182 if (++q == &sc->dmalist_pcmo[AUICH_DMALIST_MAX]) 1183 q = sc->dmalist_pcmo; 1184 sc->dmap_pcmo = q; 1185 1186 bus_space_write_4(sc->iot, sc->aud_ioh, AUICH_PCMO + AUICH_BDBAR, 1187 kvtop((caddr_t)sc->dmalist_pcmo)); 1188 bus_space_write_1(sc->iot, sc->aud_ioh, AUICH_PCMO + AUICH_CTRL, 1189 AUICH_IOCE | AUICH_FEIE | AUICH_LVBIE | AUICH_RPBM); 1190 bus_space_write_1(sc->iot, sc->aud_ioh, AUICH_PCMO + AUICH_LVI, 1191 (sc->dmap_pcmo - 1 - sc->dmalist_pcmo) & AUICH_LVI_MASK); 1192 1193 return 0; 1194 } 1195 1196 int 1197 auich_trigger_input(v, start, end, blksize, intr, arg, param) 1198 void *v; 1199 void *start, *end; 1200 int blksize; 1201 void (*intr)(void *); 1202 void *arg; 1203 struct audio_params *param; 1204 { 1205 struct auich_softc *sc = v; 1206 struct auich_dmalist *q; 1207 struct auich_dma *p; 1208 1209 DPRINTF(AUICH_DEBUG_DMA, 1210 ("auich_trigger_input(%x, %x, %d, %p, %p, %p)\n", 1211 start, end, blksize, intr, arg, param)); 1212 1213 for (p = sc->sc_dmas; p && p->addr != start; p = p->next); 1214 if (!p) 1215 return -1; 1216 1217 sc->sc_rintr = intr; 1218 sc->sc_rarg = arg; 1219 1220 /* 1221 * The logic behind this is: 1222 * setup one buffer to play, then LVI dump out the rest 1223 * to the scatter-gather chain. 1224 */ 1225 sc->pcmi_start = p->segs->ds_addr; 1226 sc->pcmi_p = sc->pcmi_start + blksize; 1227 sc->pcmi_end = sc->pcmi_start + (end - start); 1228 sc->pcmi_blksize = blksize; 1229 1230 q = sc->dmap_pcmi = sc->dmalist_pcmi; 1231 q->base = sc->pcmi_start; 1232 q->len = (blksize / sc->sc_sample_size) | AUICH_DMAF_IOC; 1233 if (++q == &sc->dmalist_pcmi[AUICH_DMALIST_MAX]) 1234 q = sc->dmalist_pcmi; 1235 sc->dmap_pcmi = q; 1236 1237 bus_space_write_4(sc->iot, sc->aud_ioh, AUICH_PCMI + AUICH_BDBAR, 1238 kvtop((caddr_t)sc->dmalist_pcmi)); 1239 bus_space_write_1(sc->iot, sc->aud_ioh, AUICH_PCMI + AUICH_CTRL, 1240 AUICH_IOCE | AUICH_FEIE | AUICH_LVBIE | AUICH_RPBM); 1241 bus_space_write_1(sc->iot, sc->aud_ioh, AUICH_PCMI + AUICH_LVI, 1242 (sc->dmap_pcmi - 1 - sc->dmalist_pcmi) & AUICH_LVI_MASK); 1243 1244 return 0; 1245 } 1246 1247 void 1248 auich_powerhook(why, self) 1249 int why; 1250 void *self; 1251 { 1252 struct auich_softc *sc = (struct auich_softc *)self; 1253 1254 if (why != PWR_RESUME) { 1255 /* Power down */ 1256 DPRINTF(1, ("auich: power down\n")); 1257 sc->suspend = why; 1258 auich_read_codec(sc, AC97_REG_EXT_AUDIO_CTRL, &sc->ext_ctrl); 1259 1260 } else { 1261 /* Wake up */ 1262 DPRINTF(1, ("auich: power resume\n")); 1263 if (sc->suspend == PWR_RESUME) { 1264 printf("%s: resume without suspend?\n", 1265 sc->sc_dev.dv_xname); 1266 sc->suspend = why; 1267 return; 1268 } 1269 sc->suspend = why; 1270 auich_reset_codec(sc); 1271 DELAY(1000); 1272 (sc->codec_if->vtbl->restore_ports)(sc->codec_if); 1273 auich_write_codec(sc, AC97_REG_EXT_AUDIO_CTRL, sc->ext_ctrl); 1274 } 1275 } 1276