1 /* $OpenBSD: auich.c,v 1.12 2001/06/12 15:40:30 niklas 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 * 3. The name of the author may not be used to endorse or promote products 16 * derived from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT, 22 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 27 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 28 * THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 /* #define AUICH_DEBUG */ 32 /* 33 * AC'97 audio found on Intel 810/815/820/440MX chipsets. 34 * http://developer.intel.com/design/chipsets/datashts/290655.htm 35 * http://developer.intel.com/design/chipsets/manuals/298028.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_SRIE 0x20 /* int when 2ndary codec resume */ 88 #define AUICH_PRIE 0x10 /* int when primary codec resume */ 89 #define AUICH_ACLSO 0x08 /* aclink shut off */ 90 #define AUICH_WRESET 0x04 /* warm reset */ 91 #define AUICH_CRESET 0x02 /* cold reset */ 92 #define AUICH_GIE 0x01 /* gpi int enable */ 93 #define AUICH_GSTS 0x30 94 #define AUICH_MD3 0x20000 /* pwr-dn semaphore for modem */ 95 #define AUICH_AD3 0x10000 /* pwr-dn semaphore for audio */ 96 #define AUICH_RCS 0x08000 /* read completion status */ 97 #define AUICH_B3S12 0x04000 /* bit 3 of slot 12 */ 98 #define AUICH_B2S12 0x02000 /* bit 2 of slot 12 */ 99 #define AUICH_B1S12 0x01000 /* bit 1 of slot 12 */ 100 #define AUICH_SRI 0x00800 /* secondary resume int */ 101 #define AUICH_PRI 0x00400 /* primary resume int */ 102 #define AUICH_SCR 0x00200 /* secondary codec ready */ 103 #define AUICH_PCR 0x00100 /* primary codec ready */ 104 #define AUICH_MINT 0x00080 /* mic in int */ 105 #define AUICH_POINT 0x00040 /* pcm out int */ 106 #define AUICH_PIINT 0x00020 /* pcm in int */ 107 #define AUICH_MOINT 0x00004 /* modem out int */ 108 #define AUICH_MIINT 0x00002 /* modem in int */ 109 #define AUICH_GSCI 0x00001 /* gpi status change */ 110 #define AUICH_GSTS_BITS "\020\01gsci\02miict\03moint\06piint\07point\010mint\011pcr\012scr\013pri\014sri\015b1s12\016b2s12\017b3s12\020rcs\021ad3\022md3" 111 #define AUICH_CAS 0x34 /* 1/8 bit */ 112 #define AUICH_SEMATIMO 1000 /* us */ 113 114 /* 115 * according to the dev/audiovar.h AU_RING_SIZE is 2^16, what fits 116 * in our limits perfectly, i.e. setting it to higher value 117 * in your kernel config would improve perfomance, still 2^21 is the max 118 */ 119 #define AUICH_DMALIST_MAX 32 120 #define AUICH_DMASEG_MAX (65536*2) /* 64k samples, 2x16 bit samples */ 121 struct auich_dmalist { 122 u_int32_t base; 123 u_int32_t len; 124 #define AUICH_DMAF_IOC 0x80000000 /* 1-int on complete */ 125 #define AUICH_DMAF_BUP 0x40000000 /* 0-retrans last, 1-transmit 0 */ 126 }; 127 128 struct auich_dma { 129 bus_dmamap_t map; 130 caddr_t addr; 131 bus_dma_segment_t segs[AUICH_DMALIST_MAX]; 132 int nsegs; 133 size_t size; 134 struct auich_dma *next; 135 }; 136 137 struct auich_softc { 138 struct device sc_dev; 139 void *sc_ih; 140 141 audio_device_t sc_audev; 142 143 bus_space_tag_t iot; 144 bus_space_handle_t mix_ioh; 145 bus_space_handle_t aud_ioh; 146 bus_dma_tag_t dmat; 147 148 struct ac97_codec_if *codec_if; 149 struct ac97_host_if host_if; 150 151 /* dma scatter-gather buffer lists, aligned to 8 bytes */ 152 struct auich_dmalist *dmalist_pcmo, *dmap_pcmo, 153 dmasto_pcmo[AUICH_DMALIST_MAX+1]; 154 struct auich_dmalist *dmalist_pcmi, *dmap_pcmi, 155 dmasto_pcmi[AUICH_DMALIST_MAX+1];; 156 struct auich_dmalist *dmalist_mici, *dmap_mici, 157 dmasto_mici[AUICH_DMALIST_MAX+1];; 158 /* i/o buffer pointers */ 159 u_int32_t pcmo_start, pcmo_p, pcmo_end; 160 int pcmo_blksize, pcmo_fifoe; 161 u_int32_t pcmi_start, pcmi_p, pcmi_end; 162 int pcmi_blksize, pcmi_fifoe; 163 u_int32_t mici_start, mici_p, mici_end; 164 int mici_blksize, mici_fifoe; 165 struct auich_dma *sc_dmas; 166 167 void (*sc_pintr) __P((void *)); 168 void *sc_parg; 169 170 void (*sc_rintr) __P((void *)); 171 void *sc_rarg; 172 }; 173 174 #ifdef AUICH_DEBUG 175 #define DPRINTF(l,x) do { if (auich_debug & (l)) printf x; } while(0) 176 int auich_debug = 0xfffe; 177 #define AUICH_DEBUG_CODECIO 0x0001 178 #define AUICH_DEBUG_DMA 0x0002 179 #define AUICH_DEBUG_PARAM 0x0004 180 #else 181 #define DPRINTF(x,y) /* nothing */ 182 #endif 183 184 struct cfdriver auich_cd = { 185 NULL, "auich", DV_DULL 186 }; 187 188 int auich_match __P((struct device *, void *, void *)); 189 void auich_attach __P((struct device *, struct device *, void *)); 190 int auich_intr __P((void *)); 191 192 struct cfattach auich_ca = { 193 sizeof(struct auich_softc), auich_match, auich_attach 194 }; 195 196 static const struct auich_devtype { 197 int product; 198 int options; 199 char name[8]; 200 } auich_devices[] = { 201 { PCI_PRODUCT_INTEL_82801AA_ACA, 0, "ICH" }, 202 { PCI_PRODUCT_INTEL_82801AB_ACA, 0, "ICH0" }, 203 { PCI_PRODUCT_INTEL_82801BA_ACA, 0, "ICH2" }, 204 { PCI_PRODUCT_INTEL_82440MX_ACA, 0, "440MX" }, 205 }; 206 207 int auich_open __P((void *, int)); 208 void auich_close __P((void *)); 209 int auich_query_encoding __P((void *, struct audio_encoding *)); 210 int auich_set_params __P((void *, int, int, struct audio_params *, 211 struct audio_params *)); 212 int auich_round_blocksize __P((void *, int)); 213 int auich_halt_output __P((void *)); 214 int auich_halt_input __P((void *)); 215 int auich_getdev __P((void *, struct audio_device *)); 216 int auich_set_port __P((void *, mixer_ctrl_t *)); 217 int auich_get_port __P((void *, mixer_ctrl_t *)); 218 int auich_query_devinfo __P((void *, mixer_devinfo_t *)); 219 void *auich_allocm __P((void *, u_long, int, int)); 220 void auich_freem __P((void *, void *, int)); 221 u_long auich_round_buffersize __P((void *, u_long)); 222 int auich_mappage __P((void *, void *, int, int)); 223 int auich_get_props __P((void *)); 224 int auich_trigger_output __P((void *, void *, void *, int, void (*)(void *), 225 void *, struct audio_params *)); 226 int auich_trigger_input __P((void *, void *, void *, int, void (*)(void *), 227 void *, struct audio_params *)); 228 229 struct audio_hw_if auich_hw_if = { 230 auich_open, 231 auich_close, 232 NULL, /* drain */ 233 auich_query_encoding, 234 auich_set_params, 235 auich_round_blocksize, 236 NULL, /* commit_setting */ 237 NULL, /* init_output */ 238 NULL, /* init_input */ 239 NULL, /* start_output */ 240 NULL, /* start_input */ 241 auich_halt_output, 242 auich_halt_input, 243 NULL, /* speaker_ctl */ 244 auich_getdev, 245 NULL, /* getfd */ 246 auich_set_port, 247 auich_get_port, 248 auich_query_devinfo, 249 auich_allocm, 250 auich_freem, 251 auich_round_buffersize, 252 auich_mappage, 253 auich_get_props, 254 auich_trigger_output, 255 auich_trigger_input 256 }; 257 258 int auich_attach_codec __P((void *, struct ac97_codec_if *)); 259 int auich_read_codec __P((void *, u_int8_t, u_int16_t *)); 260 int auich_write_codec __P((void *, u_int8_t, u_int16_t)); 261 void auich_reset_codec __P((void *)); 262 263 int 264 auich_match(parent, match, aux) 265 struct device *parent; 266 void *match; 267 void *aux; 268 { 269 struct pci_attach_args *pa = aux; 270 int i; 271 272 if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_INTEL) 273 return 0; 274 275 for (i = sizeof(auich_devices)/sizeof(auich_devices[0]); i--;) 276 if (PCI_PRODUCT(pa->pa_id) == auich_devices[i].product) 277 return 1; 278 279 return 0; 280 } 281 282 void 283 auich_attach(parent, self, aux) 284 struct device *parent, *self; 285 void *aux; 286 { 287 struct auich_softc *sc = (struct auich_softc *)self; 288 struct pci_attach_args *pa = aux; 289 pci_intr_handle_t ih; 290 bus_size_t mix_size, aud_size; 291 pcireg_t csr; 292 const char *intrstr; 293 int i; 294 295 if (pci_mapreg_map(pa, AUICH_NAMBAR, PCI_MAPREG_TYPE_IO, 0, 296 &sc->iot, &sc->mix_ioh, NULL, &mix_size, 0)) { 297 printf(": can't map codec i/o space\n"); 298 return; 299 } 300 if (pci_mapreg_map(pa, AUICH_NABMBAR, PCI_MAPREG_TYPE_IO, 0, 301 &sc->iot, &sc->aud_ioh, NULL, &aud_size, 0)) { 302 printf(": can't map device i/o space\n"); 303 bus_space_unmap(sc->iot, sc->mix_ioh, mix_size); 304 return; 305 } 306 sc->dmat = pa->pa_dmat; 307 308 /* enable bus mastering (should not it be mi?) */ 309 csr = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); 310 pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, 311 csr | PCI_COMMAND_MASTER_ENABLE); 312 313 if (pci_intr_map(pa->pa_pc, pa->pa_intrtag, pa->pa_intrpin, 314 pa->pa_intrline, &ih)) { 315 printf(": can't map interrupt\n"); 316 bus_space_unmap(sc->iot, sc->aud_ioh, aud_size); 317 bus_space_unmap(sc->iot, sc->mix_ioh, mix_size); 318 return; 319 } 320 intrstr = pci_intr_string(pa->pa_pc, ih); 321 sc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_AUDIO, auich_intr, sc, 322 sc->sc_dev.dv_xname); 323 if (!sc->sc_ih) { 324 printf(": can't establish interrupt"); 325 if (intrstr) 326 printf(" at %s", intrstr); 327 printf("\n"); 328 bus_space_unmap(sc->iot, sc->aud_ioh, aud_size); 329 bus_space_unmap(sc->iot, sc->mix_ioh, mix_size); 330 return; 331 } 332 333 for (i = sizeof(auich_devices)/sizeof(auich_devices[0]); i--;) 334 if (PCI_PRODUCT(pa->pa_id) == auich_devices[i].product) 335 break; 336 337 sprintf(sc->sc_audev.name, "%s AC97", auich_devices[i].name); 338 sprintf(sc->sc_audev.version, "0x%02x", PCI_REVISION(pa->pa_class)); 339 strcpy(sc->sc_audev.config, sc->sc_dev.dv_xname); 340 341 printf(": %s %s\n", intrstr, sc->sc_audev.name); 342 343 /* allocate dma lists */ 344 #define a(a) (void*)(((u_long)(a) + sizeof(*(a)) - 1) & ~(sizeof(*(a))-1)) 345 sc->dmalist_pcmo = sc->dmap_pcmo = a(sc->dmasto_pcmo); 346 sc->dmalist_pcmi = sc->dmap_pcmi = a(sc->dmasto_pcmi); 347 sc->dmalist_mici = sc->dmap_mici = a(sc->dmasto_mici); 348 #undef a 349 DPRINTF(AUICH_DEBUG_DMA, ("auich_attach: lists %p %p %p\n", 350 sc->dmalist_pcmo, sc->dmalist_pcmi, sc->dmalist_mici)); 351 352 /* Reset codec and AC'97 */ 353 auich_reset_codec(sc); 354 355 sc->host_if.arg = sc; 356 sc->host_if.attach = auich_attach_codec; 357 sc->host_if.read = auich_read_codec; 358 sc->host_if.write = auich_write_codec; 359 sc->host_if.reset = auich_reset_codec; 360 361 if (ac97_attach(&sc->host_if) != 0) { 362 pci_intr_disestablish(pa->pa_pc, sc->sc_ih); 363 bus_space_unmap(sc->iot, sc->aud_ioh, aud_size); 364 bus_space_unmap(sc->iot, sc->mix_ioh, mix_size); 365 return; 366 } 367 368 audio_attach_mi(&auich_hw_if, sc, &sc->sc_dev); 369 } 370 371 int 372 auich_read_codec(v, reg, val) 373 void *v; 374 u_int8_t reg; 375 u_int16_t *val; 376 { 377 struct auich_softc *sc = v; 378 int i; 379 380 /* wait for an access semaphore */ 381 for (i = AUICH_SEMATIMO; i-- && 382 bus_space_read_1(sc->iot, sc->aud_ioh, AUICH_CAS) & 1; DELAY(1)); 383 384 if (i > 0) { 385 *val = bus_space_read_2(sc->iot, sc->mix_ioh, reg); 386 DPRINTF(AUICH_DEBUG_CODECIO, ("%s: read_codec(%x, %x)\n", 387 sc->sc_dev.dv_xname, reg, *val)); 388 389 return 0; 390 } else { 391 DPRINTF(AUICH_DEBUG_CODECIO, 392 ("%s: read_codec timeout\n", sc->sc_dev.dv_xname)); 393 return -1; 394 } 395 } 396 397 int 398 auich_write_codec(v, reg, val) 399 void *v; 400 u_int8_t reg; 401 u_int16_t val; 402 { 403 struct auich_softc *sc = v; 404 int i; 405 406 /* wait for an access semaphore */ 407 for (i = AUICH_SEMATIMO; i-- && 408 bus_space_read_1(sc->iot, sc->aud_ioh, AUICH_CAS) & 1; DELAY(1)); 409 410 if (i > 0) { 411 DPRINTF(AUICH_DEBUG_CODECIO, ("%s: write_codec(%x, %x)\n", 412 sc->sc_dev.dv_xname, reg, val)); 413 bus_space_write_2(sc->iot, sc->mix_ioh, reg, val); 414 return 0; 415 } else { 416 DPRINTF(AUICH_DEBUG_CODECIO, 417 ("%s: write_codec timeout\n", sc->sc_dev.dv_xname)); 418 return -1; 419 } 420 } 421 422 int 423 auich_attach_codec(v, cif) 424 void *v; 425 struct ac97_codec_if *cif; 426 { 427 struct auich_softc *sc = v; 428 429 sc->codec_if = cif; 430 return 0; 431 } 432 433 void 434 auich_reset_codec(v) 435 void *v; 436 { 437 struct auich_softc *sc = v; 438 bus_space_write_4(sc->iot, sc->aud_ioh, AUICH_GCTRL, 0); 439 DELAY(10); 440 bus_space_write_4(sc->iot, sc->aud_ioh, AUICH_GCTRL, AUICH_CRESET); 441 } 442 443 int 444 auich_open(v, flags) 445 void *v; 446 int flags; 447 { 448 return 0; 449 } 450 451 void 452 auich_close(v) 453 void *v; 454 { 455 } 456 457 int 458 auich_query_encoding(v, aep) 459 void *v; 460 struct audio_encoding *aep; 461 { 462 switch (aep->index) { 463 case 0: 464 strcpy(aep->name, AudioEulinear); 465 aep->encoding = AUDIO_ENCODING_ULINEAR; 466 aep->precision = 8; 467 aep->flags = 0; 468 return (0); 469 case 1: 470 strcpy(aep->name, AudioEmulaw); 471 aep->encoding = AUDIO_ENCODING_ULAW; 472 aep->precision = 8; 473 aep->flags = AUDIO_ENCODINGFLAG_EMULATED; 474 return (0); 475 case 2: 476 strcpy(aep->name, AudioEalaw); 477 aep->encoding = AUDIO_ENCODING_ALAW; 478 aep->precision = 8; 479 aep->flags = AUDIO_ENCODINGFLAG_EMULATED; 480 return (0); 481 case 3: 482 strcpy(aep->name, AudioEslinear); 483 aep->encoding = AUDIO_ENCODING_SLINEAR; 484 aep->precision = 8; 485 aep->flags = AUDIO_ENCODINGFLAG_EMULATED; 486 return (0); 487 case 4: 488 strcpy(aep->name, AudioEslinear_le); 489 aep->encoding = AUDIO_ENCODING_SLINEAR_LE; 490 aep->precision = 16; 491 aep->flags = 0; 492 return (0); 493 case 5: 494 strcpy(aep->name, AudioEulinear_le); 495 aep->encoding = AUDIO_ENCODING_ULINEAR_LE; 496 aep->precision = 16; 497 aep->flags = AUDIO_ENCODINGFLAG_EMULATED; 498 return (0); 499 case 6: 500 strcpy(aep->name, AudioEslinear_be); 501 aep->encoding = AUDIO_ENCODING_SLINEAR_BE; 502 aep->precision = 16; 503 aep->flags = AUDIO_ENCODINGFLAG_EMULATED; 504 return (0); 505 case 7: 506 strcpy(aep->name, AudioEulinear_be); 507 aep->encoding = AUDIO_ENCODING_ULINEAR_BE; 508 aep->precision = 16; 509 aep->flags = AUDIO_ENCODINGFLAG_EMULATED; 510 return (0); 511 default: 512 return (EINVAL); 513 } 514 } 515 516 int 517 auich_set_params(v, setmode, usemode, play, rec) 518 void *v; 519 int setmode, usemode; 520 struct audio_params *play, *rec; 521 { 522 struct auich_softc *sc = v; 523 int error; 524 525 if (setmode & AUMODE_PLAY) { 526 play->factor = 1; 527 play->sw_code = NULL; 528 switch(play->encoding) { 529 case AUDIO_ENCODING_ULAW: 530 play->factor = 2; 531 play->sw_code = mulaw_to_slinear16; 532 break; 533 case AUDIO_ENCODING_SLINEAR_LE: 534 if (play->precision == 8) 535 play->sw_code = change_sign8; 536 break; 537 case AUDIO_ENCODING_ULINEAR_LE: 538 if (play->precision == 16) 539 play->sw_code = change_sign16; 540 break; 541 case AUDIO_ENCODING_ALAW: 542 play->factor = 2; 543 play->sw_code = alaw_to_slinear16; 544 break; 545 case AUDIO_ENCODING_SLINEAR_BE: 546 if (play->precision == 16) 547 play->sw_code = swap_bytes; 548 else 549 play->sw_code = change_sign8; 550 break; 551 case AUDIO_ENCODING_ULINEAR_BE: 552 if (play->precision == 16) 553 play->sw_code = change_sign16_swap_bytes; 554 break; 555 default: 556 return (EINVAL); 557 } 558 559 if ((error = ac97_set_rate(sc->codec_if, play, AUMODE_PLAY))) 560 return (error); 561 } 562 563 if (setmode & AUMODE_RECORD) { 564 rec->factor = 1; 565 rec->sw_code = 0; 566 switch(rec->encoding) { 567 case AUDIO_ENCODING_ULAW: 568 rec->sw_code = ulinear8_to_mulaw; 569 break; 570 case AUDIO_ENCODING_SLINEAR_LE: 571 if (rec->precision == 8) 572 rec->sw_code = change_sign8; 573 break; 574 case AUDIO_ENCODING_ULINEAR_LE: 575 if (rec->precision == 16) 576 rec->sw_code = change_sign16; 577 break; 578 case AUDIO_ENCODING_ALAW: 579 rec->sw_code = ulinear8_to_alaw; 580 break; 581 case AUDIO_ENCODING_SLINEAR_BE: 582 if (rec->precision == 16) 583 rec->sw_code = swap_bytes; 584 else 585 rec->sw_code = change_sign8; 586 break; 587 case AUDIO_ENCODING_ULINEAR_BE: 588 if (rec->precision == 16) 589 rec->sw_code = swap_bytes_change_sign16; 590 break; 591 default: 592 return (EINVAL); 593 } 594 595 if ((error = ac97_set_rate(sc->codec_if, rec, AUMODE_RECORD))) 596 return (error); 597 } 598 599 return (0); 600 } 601 602 int 603 auich_round_blocksize(v, blk) 604 void *v; 605 int blk; 606 { 607 return blk & ~0x3f; 608 } 609 610 int 611 auich_halt_output(v) 612 void *v; 613 { 614 struct auich_softc *sc = v; 615 616 DPRINTF(AUICH_DEBUG_DMA, ("%s: halt_output\n", sc->sc_dev.dv_xname)); 617 618 bus_space_write_1(sc->iot, sc->aud_ioh, AUICH_PCMO + AUICH_CTRL, AUICH_RR); 619 620 return 0; 621 } 622 623 int 624 auich_halt_input(v) 625 void *v; 626 { 627 struct auich_softc *sc = v; 628 629 DPRINTF(AUICH_DEBUG_DMA, 630 ("%s: halt_input\n", sc->sc_dev.dv_xname)); 631 632 /* XXX halt both unless known otherwise */ 633 634 bus_space_write_1(sc->iot, sc->aud_ioh, AUICH_PCMI + AUICH_CTRL, AUICH_RR); 635 bus_space_write_1(sc->iot, sc->aud_ioh, AUICH_MICI + AUICH_CTRL, AUICH_RR); 636 637 return 0; 638 } 639 640 int 641 auich_getdev(v, adp) 642 void *v; 643 struct audio_device *adp; 644 { 645 struct auich_softc *sc = v; 646 *adp = sc->sc_audev; 647 return 0; 648 } 649 650 int 651 auich_set_port(v, cp) 652 void *v; 653 mixer_ctrl_t *cp; 654 { 655 struct auich_softc *sc = v; 656 return sc->codec_if->vtbl->mixer_set_port(sc->codec_if, cp); 657 } 658 659 int 660 auich_get_port(v, cp) 661 void *v; 662 mixer_ctrl_t *cp; 663 { 664 struct auich_softc *sc = v; 665 return sc->codec_if->vtbl->mixer_get_port(sc->codec_if, cp); 666 } 667 668 int 669 auich_query_devinfo(v, dp) 670 void *v; 671 mixer_devinfo_t *dp; 672 { 673 struct auich_softc *sc = v; 674 return sc->codec_if->vtbl->query_devinfo(sc->codec_if, dp); 675 } 676 677 void * 678 auich_allocm(v, size, pool, flags) 679 void *v; 680 u_long size; 681 int pool, flags; 682 { 683 struct auich_softc *sc = v; 684 struct auich_dma *p; 685 int error; 686 687 if (size > AUICH_DMALIST_MAX * AUICH_DMASEG_MAX) 688 return NULL; 689 690 p = malloc(sizeof(*p), pool, flags); 691 if (!p) 692 return NULL; 693 694 bzero(p, sizeof(p)); 695 696 p->size = size; 697 if ((error = bus_dmamem_alloc(sc->dmat, p->size, NBPG, 0, p->segs, 698 1, &p->nsegs, BUS_DMA_NOWAIT)) != 0) { 699 printf("%s: unable to allocate dma, error = %d\n", 700 sc->sc_dev.dv_xname, error); 701 free(p, pool); 702 return NULL; 703 } 704 705 if ((error = bus_dmamem_map(sc->dmat, p->segs, p->nsegs, p->size, 706 &p->addr, BUS_DMA_NOWAIT | BUS_DMA_COHERENT)) != 0) { 707 printf("%s: unable to map dma, error = %d\n", 708 sc->sc_dev.dv_xname, error); 709 bus_dmamem_free(sc->dmat, p->segs, p->nsegs); 710 free(p, pool); 711 return NULL; 712 } 713 714 if ((error = bus_dmamap_create(sc->dmat, p->size, 1, 715 p->size, 0, BUS_DMA_NOWAIT, &p->map)) != 0) { 716 printf("%s: unable to create dma map, error = %d\n", 717 sc->sc_dev.dv_xname, error); 718 bus_dmamem_unmap(sc->dmat, p->addr, size); 719 bus_dmamem_free(sc->dmat, p->segs, p->nsegs); 720 free(p, pool); 721 return NULL; 722 } 723 724 if ((error = bus_dmamap_load(sc->dmat, p->map, p->addr, p->size, 725 NULL, BUS_DMA_NOWAIT)) != 0) { 726 printf("%s: unable to load dma map, error = %d\n", 727 sc->sc_dev.dv_xname, error); 728 bus_dmamap_destroy(sc->dmat, p->map); 729 bus_dmamem_unmap(sc->dmat, p->addr, size); 730 bus_dmamem_free(sc->dmat, p->segs, p->nsegs); 731 free(p, pool); 732 return NULL; 733 } 734 735 p->next = sc->sc_dmas; 736 sc->sc_dmas = p; 737 738 return p->addr; 739 } 740 741 void 742 auich_freem(v, ptr, pool) 743 void *v; 744 void *ptr; 745 int pool; 746 { 747 struct auich_softc *sc = v; 748 struct auich_dma *p; 749 750 for (p = sc->sc_dmas; p->addr != ptr; p = p->next) 751 if (p->next == NULL) { 752 printf("auich_freem: trying to free not allocated memory"); 753 return; 754 } 755 756 bus_dmamap_unload(sc->dmat, p->map); 757 bus_dmamap_destroy(sc->dmat, p->map); 758 bus_dmamem_unmap(sc->dmat, p->addr, p->size); 759 bus_dmamem_free(sc->dmat, p->segs, p->nsegs); 760 free(p, pool); 761 } 762 763 u_long 764 auich_round_buffersize(v, size) 765 void *v; 766 u_long size; 767 { 768 if (size > AUICH_DMALIST_MAX * AUICH_DMASEG_MAX) 769 size = AUICH_DMALIST_MAX * AUICH_DMASEG_MAX; 770 771 return size; 772 } 773 774 int 775 auich_mappage(v, mem, off, prot) 776 void *v; 777 void *mem; 778 int off; 779 int prot; 780 { 781 struct auich_softc *sc = v; 782 struct auich_dma *p; 783 784 if (off < 0) 785 return -1; 786 787 for (p = sc->sc_dmas; p && p->addr != mem; p = p->next); 788 if (!p) 789 return -1; 790 791 return bus_dmamem_mmap(sc->dmat, p->segs, p->nsegs, 792 off, prot, BUS_DMA_WAITOK); 793 } 794 795 int 796 auich_get_props(v) 797 void *v; 798 { 799 return AUDIO_PROP_MMAP | AUDIO_PROP_INDEPENDENT | AUDIO_PROP_FULLDUPLEX; 800 } 801 802 int 803 auich_intr(v) 804 void *v; 805 { 806 struct auich_softc *sc = v; 807 int ret = 0, sts, gsts, i; 808 809 gsts = bus_space_read_2(sc->iot, sc->aud_ioh, AUICH_GSTS); 810 DPRINTF(AUICH_DEBUG_DMA, ("auich_intr: gsts=%b\n", gsts, AUICH_GSTS_BITS)); 811 812 if (gsts & AUICH_POINT) { 813 sts = bus_space_read_2(sc->iot, sc->aud_ioh, AUICH_PCMO+AUICH_STS); 814 DPRINTF(AUICH_DEBUG_DMA, 815 ("auich_intr: osts=%b\n", sts, AUICH_ISTS_BITS)); 816 817 if (sts & AUICH_FIFOE) { 818 printf("%s: fifo underrun # %u\n", 819 sc->sc_dev.dv_xname, ++sc->pcmo_fifoe); 820 } 821 822 i = bus_space_read_1(sc->iot, sc->aud_ioh, AUICH_PCMO + AUICH_CIV); 823 if (sts & (AUICH_LVBCI | AUICH_CELV)) { 824 struct auich_dmalist *q, *qe; 825 826 q = sc->dmap_pcmo; 827 qe = &sc->dmalist_pcmo[i]; 828 829 while (q != qe) { 830 831 q->base = sc->pcmo_p; 832 q->len = (sc->pcmo_blksize / 2) | AUICH_DMAF_IOC; 833 DPRINTF(AUICH_DEBUG_DMA, 834 ("auich_intr: %p, %p = %x @ %p\n", 835 qe, q, sc->pcmo_blksize / 2, sc->pcmo_p)); 836 837 sc->pcmo_p += sc->pcmo_blksize; 838 if (sc->pcmo_p >= sc->pcmo_end) 839 sc->pcmo_p = sc->pcmo_start; 840 841 if (++q == &sc->dmalist_pcmo[AUICH_DMALIST_MAX]) 842 q = sc->dmalist_pcmo; 843 } 844 845 sc->dmap_pcmo = q; 846 bus_space_write_1(sc->iot, sc->aud_ioh, 847 AUICH_PCMO + AUICH_LVI, 848 (sc->dmap_pcmo - sc->dmalist_pcmo - 1) & 849 AUICH_LVI_MASK); 850 } 851 852 if (sts & AUICH_BCIS && sc->sc_pintr) 853 sc->sc_pintr(sc->sc_parg); 854 855 /* int ack */ 856 bus_space_write_2(sc->iot, sc->aud_ioh, AUICH_PCMO + AUICH_STS, 857 sts & (AUICH_LVBCI | AUICH_CELV | AUICH_BCIS | AUICH_FIFOE)); 858 bus_space_write_2(sc->iot, sc->aud_ioh, AUICH_GSTS, AUICH_POINT); 859 ret++; 860 } 861 862 if (gsts & AUICH_PIINT) { 863 sts = bus_space_read_2(sc->iot, sc->aud_ioh, AUICH_PCMI+AUICH_STS); 864 DPRINTF(AUICH_DEBUG_DMA, 865 ("auich_intr: ists=%b\n", sts, AUICH_ISTS_BITS)); 866 867 if (sts & AUICH_FIFOE) { 868 printf("%s: in fifo overrun # %u\n", 869 sc->sc_dev.dv_xname, ++sc->pcmi_fifoe); 870 } 871 872 i = bus_space_read_1(sc->iot, sc->aud_ioh, AUICH_PCMI + AUICH_CIV); 873 if (sts & (AUICH_LVBCI | AUICH_CELV)) { 874 struct auich_dmalist *q, *qe; 875 876 q = sc->dmap_pcmi; 877 qe = &sc->dmalist_pcmi[i]; 878 879 while (q != qe) { 880 881 q->base = sc->pcmi_p; 882 q->len = (sc->pcmi_blksize / 2) | AUICH_DMAF_IOC; 883 DPRINTF(AUICH_DEBUG_DMA, 884 ("auich_intr: %p, %p = %x @ %p\n", 885 qe, q, sc->pcmi_blksize / 2, sc->pcmi_p)); 886 887 sc->pcmi_p += sc->pcmi_blksize; 888 if (sc->pcmi_p >= sc->pcmi_end) 889 sc->pcmi_p = sc->pcmi_start; 890 891 if (++q == &sc->dmalist_pcmi[AUICH_DMALIST_MAX]) 892 q = sc->dmalist_pcmi; 893 } 894 895 sc->dmap_pcmi = q; 896 bus_space_write_1(sc->iot, sc->aud_ioh, 897 AUICH_PCMI + AUICH_LVI, 898 (sc->dmap_pcmi - sc->dmalist_pcmi - 1) & 899 AUICH_LVI_MASK); 900 } 901 902 if (sts & AUICH_BCIS && sc->sc_rintr) 903 sc->sc_rintr(sc->sc_rarg); 904 905 /* int ack */ 906 bus_space_write_2(sc->iot, sc->aud_ioh, AUICH_PCMI + AUICH_STS, 907 sts & (AUICH_LVBCI | AUICH_CELV | AUICH_BCIS | AUICH_FIFOE)); 908 bus_space_write_2(sc->iot, sc->aud_ioh, AUICH_GSTS, AUICH_POINT); 909 ret++; 910 } 911 912 if (gsts & AUICH_MIINT) { 913 sts = bus_space_read_2(sc->iot, sc->aud_ioh, AUICH_MICI+AUICH_STS); 914 DPRINTF(AUICH_DEBUG_DMA, 915 ("auich_intr: ists=%b\n", sts, AUICH_ISTS_BITS)); 916 if (sts & AUICH_FIFOE) 917 printf("%s: mic fifo overrun\n", sc->sc_dev.dv_xname); 918 919 /* TODO mic input dma */ 920 921 bus_space_write_2(sc->iot, sc->aud_ioh, AUICH_GSTS, AUICH_MIINT); 922 } 923 924 return ret; 925 } 926 927 int 928 auich_trigger_output(v, start, end, blksize, intr, arg, param) 929 void *v; 930 void *start, *end; 931 int blksize; 932 void (*intr)(void *); 933 void *arg; 934 struct audio_params *param; 935 { 936 struct auich_softc *sc = v; 937 struct auich_dmalist *q; 938 939 DPRINTF(AUICH_DEBUG_DMA, 940 ("auich_trigger_output(%x, %x, %d, %p, %p, %p)\n", 941 kvtop((caddr_t)start), kvtop((caddr_t)end), 942 blksize, intr, arg, param)); 943 944 #ifdef DIAGNOSTIC 945 { 946 struct auich_dma *p; 947 for (p = sc->sc_dmas; p && p->addr != start; p = p->next); 948 if (!p) 949 return -1; 950 } 951 #endif 952 sc->sc_pintr = intr; 953 sc->sc_parg = arg; 954 955 /* 956 * The logic behind this is: 957 * setup one buffer to play, then LVI dump out the rest 958 * to the scatter-gather chain. 959 */ 960 sc->pcmo_start = kvtop((caddr_t)start); 961 sc->pcmo_p = sc->pcmo_start + blksize; 962 sc->pcmo_end = kvtop((caddr_t)end); 963 sc->pcmo_blksize = blksize; 964 965 q = sc->dmap_pcmo = sc->dmalist_pcmo; 966 q->base = sc->pcmo_start; 967 q->len = (blksize / 2) | AUICH_DMAF_IOC; 968 if (++q == &sc->dmalist_pcmo[AUICH_DMALIST_MAX]) 969 q = sc->dmalist_pcmo; 970 sc->dmap_pcmo = q; 971 972 bus_space_write_4(sc->iot, sc->aud_ioh, AUICH_PCMO + AUICH_BDBAR, 973 kvtop((caddr_t)sc->dmalist_pcmo)); 974 bus_space_write_1(sc->iot, sc->aud_ioh, AUICH_PCMO + AUICH_CTRL, 975 AUICH_IOCE | AUICH_FEIE | AUICH_LVBIE | AUICH_RPBM); 976 bus_space_write_1(sc->iot, sc->aud_ioh, AUICH_PCMO + AUICH_LVI, 977 (sc->dmap_pcmo - 1 - sc->dmalist_pcmo) & AUICH_LVI_MASK); 978 979 return 0; 980 } 981 982 int 983 auich_trigger_input(v, start, end, blksize, intr, arg, param) 984 void *v; 985 void *start, *end; 986 int blksize; 987 void (*intr)(void *); 988 void *arg; 989 struct audio_params *param; 990 { 991 struct auich_softc *sc = v; 992 struct auich_dmalist *q; 993 994 DPRINTF(AUICH_DEBUG_DMA, 995 ("auich_trigger_input(%x, %x, %d, %p, %p, %p)\n", 996 kvtop((caddr_t)start), kvtop((caddr_t)end), 997 blksize, intr, arg, param)); 998 999 #ifdef DIAGNOSTIC 1000 { 1001 struct auich_dma *p; 1002 for (p = sc->sc_dmas; p && p->addr != start; p = p->next); 1003 if (!p) 1004 return -1; 1005 } 1006 #endif 1007 sc->sc_rintr = intr; 1008 sc->sc_rarg = arg; 1009 1010 /* 1011 * The logic behind this is: 1012 * setup one buffer to play, then LVI dump out the rest 1013 * to the scatter-gather chain. 1014 */ 1015 sc->pcmi_start = kvtop((caddr_t)start); 1016 sc->pcmi_p = sc->pcmi_start + blksize; 1017 sc->pcmi_end = kvtop((caddr_t)end); 1018 sc->pcmi_blksize = blksize; 1019 1020 q = sc->dmap_pcmi = sc->dmalist_pcmi; 1021 q->base = sc->pcmi_start; 1022 q->len = (blksize / 2) | AUICH_DMAF_IOC; 1023 if (++q == &sc->dmalist_pcmi[AUICH_DMALIST_MAX]) 1024 q = sc->dmalist_pcmi; 1025 sc->dmap_pcmi = q; 1026 1027 bus_space_write_4(sc->iot, sc->aud_ioh, AUICH_PCMI + AUICH_BDBAR, 1028 kvtop((caddr_t)sc->dmalist_pcmi)); 1029 bus_space_write_1(sc->iot, sc->aud_ioh, AUICH_PCMI + AUICH_CTRL, 1030 AUICH_IOCE | AUICH_FEIE | AUICH_LVBIE | AUICH_RPBM); 1031 bus_space_write_1(sc->iot, sc->aud_ioh, AUICH_PCMI + AUICH_LVI, 1032 (sc->dmap_pcmi - 1 - sc->dmalist_pcmi) & AUICH_LVI_MASK); 1033 1034 return 0; 1035 } 1036 1037