cs4281.c revision 1.2
1/* $NetBSD: cs4281.c,v 1.2 2001/01/22 01:44:56 augustss Exp $ */ 2 3/* 4 * Copyright (c) 2000 Tatoku Ogaito. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. All advertising materials mentioning features or use of this software 15 * must display the following acknowledgement: 16 * This product includes software developed by Tatoku Ogaito 17 * for the NetBSD Project. 18 * 4. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33/* 34 * Cirrus Logic CS4281 driver. 35 * Data sheets can be found 36 * http://www.cirrus.com/ftp/pub/4281.pdf 37 * ftp://ftp.alsa-project.org/pub/manuals/cirrus/cs4281tm.pdf 38 * 39 * TODO: 40 * 1: confirm this driver does work :-) 41 * 2: midi and FM support 42 * 3: ... 43 * 44 */ 45 46#include <sys/param.h> 47#include <sys/systm.h> 48#include <sys/kernel.h> 49#include <sys/malloc.h> 50#include <sys/fcntl.h> 51#include <sys/device.h> 52#include <sys/types.h> 53#include <sys/systm.h> 54 55#include <dev/pci/pcidevs.h> 56#include <dev/pci/pcivar.h> 57#include <dev/pci/cs4281reg.h> 58#include <dev/pci/cs428xreg.h> 59 60#include <sys/audioio.h> 61#include <dev/audio_if.h> 62#include <dev/midi_if.h> 63#include <dev/mulaw.h> 64#include <dev/auconv.h> 65 66#include <dev/ic/ac97reg.h> 67#include <dev/ic/ac97var.h> 68 69#include <dev/pci/cs428x.h> 70 71#include <machine/bus.h> 72 73#if defined(ENABLE_SECONDARY_CODEC) 74#define MAX_CHANNELS (4) 75#define MAX_FIFO_SIZE 32 /* 128/4channels */ 76#else 77#define MAX_CHANNELS (2) 78#define MAX_FIFO_SIZE 64 /* 128/2channels */ 79#endif 80 81/* IF functions for audio driver */ 82int cs4281_match(struct device *, struct cfdata *, void *); 83void cs4281_attach(struct device *, struct device *, void *); 84int cs4281_intr(void *); 85int cs4281_query_encoding(void *, struct audio_encoding *); 86int cs4281_set_params(void *, int, int, struct audio_params *, struct audio_params *); 87int cs4281_halt_output(void *); 88int cs4281_halt_input(void *); 89int cs4281_getdev(void *, struct audio_device *); 90int cs4281_trigger_output(void *, void *, void *, int, void (*)(void *), 91 void *, struct audio_params *); 92int cs4281_trigger_input(void *, void *, void *, int, void (*)(void *), 93 void *, struct audio_params *); 94 95/* Internal functions */ 96u_int8_t cs4281_sr2regval(int); 97void cs4281_set_dac_rate(struct cs428x_softc *, int ); 98void cs4281_set_adc_rate(struct cs428x_softc *, int ); 99int cs4281_init(struct cs428x_softc *); 100 101/* Power Management */ 102void cs4281_power(int, void *); 103 104#define NOT_SHARED 105 106#ifdef NOT_SHARED 107/* These functions may shared with cs4280.c */ 108int cs4281_open(void *, int); 109void cs4281_close(void *); 110int cs4281_round_blocksize(void *, int); 111int cs4281_get_props(void *); 112int cs4281_attach_codec(void *, struct ac97_codec_if *); 113int cs4281_read_codec(void *, u_int8_t , u_int16_t *); 114int cs4281_write_codec(void *, u_int8_t, u_int16_t); 115void cs4281_reset_codec(void *); 116 117int cs4281_mixer_set_port(void *, mixer_ctrl_t *); 118int cs4281_mixer_get_port(void *, mixer_ctrl_t *); 119int cs4281_query_devinfo(void *, mixer_devinfo_t *); 120void *cs4281_malloc(void *, int, size_t, int, int); 121size_t cs4281_round_buffersize(void *, int, size_t); 122void cs4281_free(void *, void *, int); 123paddr_t cs4281_mappage(void *, void *, off_t, int); 124 125/* internal functions */ 126int cs4281_allocmem(struct cs428x_softc*, size_t, int, int, 127 struct cs428x_dma *); 128int cs4281_src_wait(struct cs428x_softc *); 129 130#if defined(CS4281_DEBUG) 131#undef DPRINTF 132#undef DPRINTFN 133#define DPRINTF(x) if (cs4281_debug) printf x 134#define DPRINTFN(n,x) if (cs4281_debug>(n)) printf x 135int cs4281_debug = 5; 136#endif 137 138#endif /* NOT_SHARED */ 139 140struct audio_hw_if cs4281_hw_if = { 141 cs4281_open, 142 cs4281_close, 143 NULL, 144 cs4281_query_encoding, 145 cs4281_set_params, 146 cs4281_round_blocksize, 147 NULL, 148 NULL, 149 NULL, 150 NULL, 151 NULL, 152 cs4281_halt_output, 153 cs4281_halt_input, 154 NULL, 155 cs4281_getdev, 156 NULL, 157 cs4281_mixer_set_port, 158 cs4281_mixer_get_port, 159 cs4281_query_devinfo, 160 cs4281_malloc, 161 cs4281_free, 162 cs4281_round_buffersize, 163 cs4281_mappage, 164 cs4281_get_props, 165 cs4281_trigger_output, 166 cs4281_trigger_input, 167}; 168 169#if NMIDI > 0 && 0 170/* Midi Interface */ 171void cs4281_midi_close(void*); 172void cs4281_midi_getinfo(void *, struct midi_info *); 173int cs4281_midi_open(void *, int, void (*)(void *, int), 174 void (*)(void *), void *); 175int cs4281_midi_output(void *, int); 176 177struct midi_hw_if cs4281_midi_hw_if = { 178 cs4281_midi_open, 179 cs4281_midi_close, 180 cs4281_midi_output, 181 cs4281_midi_getinfo, 182 0, 183}; 184#endif 185 186struct cfattach clct_ca = { 187 sizeof(struct cs428x_softc), cs4281_match, cs4281_attach 188}; 189 190struct audio_device cs4281_device = { 191 "CS4281", 192 "", 193 "cs4281" 194}; 195 196 197int 198cs4281_match(parent, match, aux) 199 struct device *parent; 200 struct cfdata *match; 201 void *aux; 202{ 203 struct pci_attach_args *pa = (struct pci_attach_args *)aux; 204 205 if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_CIRRUS) 206 return 0; 207 if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_CIRRUS_CS4281) 208 return 1; 209 return 0; 210} 211 212void 213cs4281_attach(parent, self, aux) 214 struct device *parent; 215 struct device *self; 216 void *aux; 217{ 218 struct cs428x_softc *sc = (struct cs428x_softc *)self; 219 struct pci_attach_args *pa = (struct pci_attach_args *)aux; 220 pci_chipset_tag_t pc = pa->pa_pc; 221 char const *intrstr; 222 pci_intr_handle_t ih; 223 pcireg_t csr; 224 char devinfo[256]; 225 226 pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo); 227 printf(": %s (rev. 0x%02x)\n", devinfo, PCI_REVISION(pa->pa_class)); 228 229 /* Map I/O register */ 230 if (pci_mapreg_map(pa, PCI_BA0, 231 PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT, 0, 232 &sc->ba0t, &sc->ba0h, NULL, NULL)) { 233 printf("%s: can't map BA0 space\n", sc->sc_dev.dv_xname); 234 return; 235 } 236 if (pci_mapreg_map(pa, PCI_BA1, 237 PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT, 0, 238 &sc->ba1t, &sc->ba1h, NULL, NULL)) { 239 printf("%s: can't map BA1 space\n", sc->sc_dev.dv_xname); 240 return; 241 } 242 243 sc->sc_dmatag = pa->pa_dmat; 244 245 /* Enable the device (set bus master flag) */ 246 csr = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); 247 pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, 248 csr | PCI_COMMAND_MASTER_ENABLE); 249 250#if 0 251 /* LATENCY_TIMER setting */ 252 temp1 = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_BHLC_REG); 253 if ( PCI_LATTIMER(temp1) < 32 ) { 254 temp1 &= 0xffff00ff; 255 temp1 |= 0x00002000; 256 pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_BHLC_REG, temp1); 257 } 258#endif 259 260 /* Map and establish the interrupt. */ 261 if (pci_intr_map(pa, &ih)) { 262 printf("%s: couldn't map interrupt\n", sc->sc_dev.dv_xname); 263 return; 264 } 265 intrstr = pci_intr_string(pc, ih); 266 267 sc->sc_ih = pci_intr_establish(pc, ih, IPL_AUDIO, cs4281_intr, sc); 268 if (sc->sc_ih == NULL) { 269 printf("%s: couldn't establish interrupt",sc->sc_dev.dv_xname); 270 if (intrstr != NULL) 271 printf(" at %s", intrstr); 272 printf("\n"); 273 return; 274 } 275 printf("%s: interrupting at %s\n", sc->sc_dev.dv_xname, intrstr); 276 277 /* 278 * Sound System start-up 279 */ 280 if (cs4281_init(sc) != 0) 281 return; 282 283 sc->type = TYPE_CS4281; 284 sc->halt_input = cs4281_halt_input; 285 sc->halt_output = cs4281_halt_output; 286 287 sc->dma_size = CS4281_BUFFER_SIZE / MAX_CHANNELS; 288 sc->dma_align = 0x10; 289 sc->hw_blocksize = sc->dma_size / 2; 290 291 /* AC 97 attachment */ 292 sc->host_if.arg = sc; 293 sc->host_if.attach = cs4281_attach_codec; 294 sc->host_if.read = cs4281_read_codec; 295 sc->host_if.write = cs4281_write_codec; 296 sc->host_if.reset = cs4281_reset_codec; 297 if (ac97_attach(&sc->host_if) != 0) { 298 printf("%s: ac97_attach failed\n", sc->sc_dev.dv_xname); 299 return; 300 } 301 audio_attach_mi(&cs4281_hw_if, sc, &sc->sc_dev); 302 303#if NMIDI > 0 && 0 304 midi_attach_mi(&cs4281_midi_hw_if, sc, &sc->sc_dev); 305#endif 306 307 sc->sc_suspend = PWR_RESUME; 308 sc->sc_powerhook = powerhook_establish(cs4281_power, sc); 309} 310 311 312int 313cs4281_intr(p) 314 void *p; 315{ 316 struct cs428x_softc *sc = p; 317 u_int32_t intr, hdsr0, hdsr1; 318 char *empty_dma; 319 320 hdsr0 = 0; 321 hdsr1 = 0; 322 323 /* grab interrupt register */ 324 intr = BA0READ4(sc, CS4281_HISR); 325 326 DPRINTF(("cs4281_intr:")); 327 /* not for me */ 328 if ((intr & HISR_INTENA) == 0) { 329 /* clear the interrupt register */ 330 BA0WRITE4(sc, CS4281_HICR, HICR_CHGM | HICR_IEV); 331 return 0; 332 } 333 334 if (intr & HISR_DMA0) 335 hdsr0 = BA0READ4(sc, CS4281_HDSR0); /* clear intr condition */ 336 if (intr & HISR_DMA1) 337 hdsr1 = BA0READ4(sc, CS4281_HDSR1); /* clear intr condition */ 338 /* clear the interrupt register */ 339 BA0WRITE4(sc, CS4281_HICR, HICR_CHGM | HICR_IEV); 340 341 DPRINTF(("intr = 0x%08x, hdsr0 = 0x%08x hdsr1 = 0x%08x\n", 342 intr, hdsr0, hdsr1)); 343 344 /* Playback Interrupt */ 345 if (intr & HISR_DMA0) { 346 DPRINTF((" PB DMA 0x%x(%d)", (int)BA0READ4(sc, CS4281_DCA0), 347 (int)BA0READ4(sc, CS4281_DCC0))); 348 if (sc->sc_pintr) { 349 if ((sc->sc_pi%sc->sc_pcount) == 0) 350 sc->sc_pintr(sc->sc_parg); 351 } else { 352 printf("unexpected play intr\n"); 353 } 354 /* copy buffer */ 355 ++sc->sc_pi; 356 empty_dma = sc->sc_pdma->addr; 357 if (sc->sc_pi&1) 358 empty_dma += sc->hw_blocksize; 359 memcpy(empty_dma, sc->sc_pn, sc->hw_blocksize); 360 sc->sc_pn += sc->hw_blocksize; 361 if (sc->sc_pn >= sc->sc_pe) 362 sc->sc_pn = sc->sc_ps; 363 } 364 if (intr & HISR_DMA1) { 365 /* copy from dma */ 366 DPRINTF((" CP DMA 0x%x(%d)", (int)BA0READ4(sc, CS4281_DCA1), 367 (int)BA0READ4(sc, CS4281_DCC1))); 368 ++sc->sc_ri; 369 empty_dma = sc->sc_rdma->addr; 370 if ((sc->sc_ri & 1) == 0) 371 empty_dma += sc->hw_blocksize; 372 memcpy(sc->sc_rn, empty_dma, sc->hw_blocksize); 373 if (sc->sc_rn >= sc->sc_re) 374 sc->sc_rn = sc->sc_rs; 375 if (sc->sc_rintr) { 376 if ((sc->sc_ri % sc->sc_rcount) == 0) 377 sc->sc_rintr(sc->sc_rarg); 378 } else { 379 printf("unexpected record intr\n"); 380 } 381 } 382 DPRINTF(("\n")); 383 return 1; 384} 385 386int 387cs4281_query_encoding(addr, fp) 388 void *addr; 389 struct audio_encoding *fp; 390{ 391 switch (fp->index) { 392 case 0: 393 strcpy(fp->name, AudioEulinear); 394 fp->encoding = AUDIO_ENCODING_ULINEAR; 395 fp->precision = 8; 396 fp->flags = 0; 397 break; 398 case 1: 399 strcpy(fp->name, AudioEmulaw); 400 fp->encoding = AUDIO_ENCODING_ULAW; 401 fp->precision = 8; 402 fp->flags = AUDIO_ENCODINGFLAG_EMULATED; 403 break; 404 case 2: 405 strcpy(fp->name, AudioEalaw); 406 fp->encoding = AUDIO_ENCODING_ALAW; 407 fp->precision = 8; 408 fp->flags = AUDIO_ENCODINGFLAG_EMULATED; 409 break; 410 case 3: 411 strcpy(fp->name, AudioEslinear); 412 fp->encoding = AUDIO_ENCODING_SLINEAR; 413 fp->precision = 8; 414 fp->flags = 0; 415 break; 416 case 4: 417 strcpy(fp->name, AudioEslinear_le); 418 fp->encoding = AUDIO_ENCODING_SLINEAR_LE; 419 fp->precision = 16; 420 fp->flags = 0; 421 break; 422 case 5: 423 strcpy(fp->name, AudioEulinear_le); 424 fp->encoding = AUDIO_ENCODING_ULINEAR_LE; 425 fp->precision = 16; 426 fp->flags = 0; 427 break; 428 case 6: 429 strcpy(fp->name, AudioEslinear_be); 430 fp->encoding = AUDIO_ENCODING_SLINEAR_BE; 431 fp->precision = 16; 432 fp->flags = 0; 433 break; 434 case 7: 435 strcpy(fp->name, AudioEulinear_be); 436 fp->encoding = AUDIO_ENCODING_ULINEAR_BE; 437 fp->precision = 16; 438 fp->flags = 0; 439 break; 440 default: 441 return EINVAL; 442 } 443 return 0; 444} 445 446int 447cs4281_set_params(addr, setmode, usemode, play, rec) 448 void *addr; 449 int setmode, usemode; 450 struct audio_params *play, *rec; 451{ 452 struct cs428x_softc *sc = addr; 453 struct audio_params *p; 454 int mode; 455 456 for (mode = AUMODE_RECORD; mode != -1; 457 mode = mode == AUMODE_RECORD ? AUMODE_PLAY : -1) { 458 if ((setmode & mode) == 0) 459 continue; 460 461 p = mode == AUMODE_PLAY ? play : rec; 462 463 if (p == play) { 464 DPRINTFN(5,("play: sample=%ld precision=%d channels=%d\n", 465 p->sample_rate, p->precision, p->channels)); 466 if (p->sample_rate < 6023 || p->sample_rate > 48000 || 467 (p->precision != 8 && p->precision != 16) || 468 (p->channels != 1 && p->channels != 2)) { 469 return (EINVAL); 470 } 471 } else { 472 DPRINTFN(5,("rec: sample=%ld precision=%d channels=%d\n", 473 p->sample_rate, p->precision, p->channels)); 474 if (p->sample_rate < 6023 || p->sample_rate > 48000 || 475 (p->precision != 8 && p->precision != 16) || 476 (p->channels != 1 && p->channels != 2)) { 477 return (EINVAL); 478 } 479 } 480 p->factor = 1; 481 p->sw_code = 0; 482 483 switch (p->encoding) { 484 case AUDIO_ENCODING_SLINEAR_BE: 485 break; 486 case AUDIO_ENCODING_SLINEAR_LE: 487 break; 488 case AUDIO_ENCODING_ULINEAR_BE: 489 break; 490 case AUDIO_ENCODING_ULINEAR_LE: 491 break; 492 case AUDIO_ENCODING_ULAW: 493 if (mode == AUMODE_PLAY) { 494 p->sw_code = mulaw_to_slinear8; 495 } else { 496 p->sw_code = slinear8_to_mulaw; 497 } 498 break; 499 case AUDIO_ENCODING_ALAW: 500 if (mode == AUMODE_PLAY) { 501 p->sw_code = alaw_to_slinear8; 502 } else { 503 p->sw_code = slinear8_to_alaw; 504 } 505 break; 506 default: 507 return (EINVAL); 508 } 509 } 510 511 /* set sample rate */ 512 cs4281_set_dac_rate(sc, play->sample_rate); 513 cs4281_set_adc_rate(sc, rec->sample_rate); 514 return 0; 515} 516 517int 518cs4281_halt_output(addr) 519 void *addr; 520{ 521 struct cs428x_softc *sc = addr; 522 523 BA0WRITE4(sc, CS4281_DCR0, BA0READ4(sc, CS4281_DCR0) | DCRn_MSK); 524#ifdef DIAGNOSTIC 525 sc->sc_prun = 0; 526#endif 527 return 0; 528} 529 530int 531cs4281_halt_input(addr) 532 void *addr; 533{ 534 struct cs428x_softc *sc = addr; 535 536 BA0WRITE4(sc, CS4281_DCR1, BA0READ4(sc, CS4281_DCR1) | DCRn_MSK); 537#ifdef DIAGNOSTIC 538 sc->sc_rrun = 0; 539#endif 540 return 0; 541} 542 543int 544cs4281_getdev(addr, retp) 545 void *addr; 546 struct audio_device *retp; 547{ 548 *retp = cs4281_device; 549 return 0; 550} 551 552 553int 554cs4281_trigger_output(addr, start, end, blksize, intr, arg, param) 555 void *addr; 556 void *start, *end; 557 int blksize; 558 void (*intr) __P((void *)); 559 void *arg; 560 struct audio_params *param; 561{ 562 struct cs428x_softc *sc = addr; 563 u_int32_t fmt=0; 564 struct cs428x_dma *p; 565 int dma_count; 566 567#ifdef DIAGNOSTIC 568 if (sc->sc_prun) 569 printf("cs4281_trigger_output: already running\n"); 570 sc->sc_prun = 1; 571#endif 572 573 DPRINTF(("cs4281_trigger_output: sc=%p start=%p end=%p " 574 "blksize=%d intr=%p(%p)\n", addr, start, end, blksize, intr, arg)); 575 sc->sc_pintr = intr; 576 sc->sc_parg = arg; 577 578 /* stop playback DMA */ 579 BA0WRITE4(sc, CS4281_DCR0, BA0READ4(sc, CS4281_DCR0) | DCRn_MSK); 580 581 DPRINTF(("param: precision=%d factor=%d channels=%d encoding=%d\n", 582 param->precision, param->factor, param->channels, 583 param->encoding)); 584 for (p = sc->sc_dmas; p != NULL && BUFADDR(p) != start; p = p->next) 585 ; 586 if (p == NULL) { 587 printf("cs4281_trigger_output: bad addr %p\n", start); 588 return (EINVAL); 589 } 590 591 sc->sc_pcount = blksize / sc->hw_blocksize; 592 sc->sc_ps = (char *)start; 593 sc->sc_pe = (char *)end; 594 sc->sc_pdma = p; 595 sc->sc_pbuf = KERNADDR(p); 596 sc->sc_pi = 0; 597 sc->sc_pn = sc->sc_ps; 598 if (blksize >= sc->dma_size) { 599 sc->sc_pn = sc->sc_ps + sc->dma_size; 600 memcpy(sc->sc_pbuf, start, sc->dma_size); 601 ++sc->sc_pi; 602 } else { 603 sc->sc_pn = sc->sc_ps + sc->hw_blocksize; 604 memcpy(sc->sc_pbuf, start, sc->hw_blocksize); 605 } 606 607 dma_count = sc->dma_size; 608 if (param->precision * param->factor != 8) 609 dma_count /= 2; /* 16 bit */ 610 if (param->channels > 1) 611 dma_count /= 2; /* Stereo */ 612 613 DPRINTF(("cs4281_trigger_output: DMAADDR(p)=0x%x count=%d\n", 614 (int)DMAADDR(p), dma_count)); 615 BA0WRITE4(sc, CS4281_DBA0, DMAADDR(p)); 616 BA0WRITE4(sc, CS4281_DBC0, dma_count-1); 617 618 /* set playback format */ 619 fmt = BA0READ4(sc, CS4281_DMR0) & ~DMRn_FMTMSK; 620 if (param->precision * param->factor == 8) 621 fmt |= DMRn_SIZE8; 622 if (param->channels == 1) 623 fmt |= DMRn_MONO; 624 if (param->encoding == AUDIO_ENCODING_ULINEAR_BE || 625 param->encoding == AUDIO_ENCODING_SLINEAR_BE) 626 fmt |= DMRn_BEND; 627 if (param->encoding == AUDIO_ENCODING_ULINEAR_BE || 628 param->encoding == AUDIO_ENCODING_ULINEAR_LE) 629 fmt |= DMRn_USIGN; 630 BA0WRITE4(sc, CS4281_DMR0, fmt); 631 632 /* set sample rate */ 633 cs4281_set_dac_rate(sc, param->sample_rate); 634 635 /* start DMA */ 636 BA0WRITE4(sc, CS4281_DCR0, BA0READ4(sc, CS4281_DCR0) & ~DCRn_MSK); 637 /* Enable interrupts */ 638 BA0WRITE4(sc, CS4281_HICR, HICR_IEV | HICR_CHGM); 639 640#if 1 641 /* XXX 642 * I think these BA0WRITE4 should not be here 643 */ 644 BA0WRITE4(sc, CS4281_PPRVC, 7); 645 BA0WRITE4(sc, CS4281_PPLVC, 7); 646#endif 647 648 DPRINTF(("HICR =0x%08x(expected 0x00000001)\n", BA0READ4(sc, CS4281_HICR))); 649 DPRINTF(("HIMR =0x%08x(expected 0x00f0fc3f)\n", BA0READ4(sc, CS4281_HIMR))); 650 DPRINTF(("DMR0 =0x%08x(expected 0x2???0018)\n", BA0READ4(sc, CS4281_DMR0))); 651 DPRINTF(("DCR0 =0x%08x(expected 0x00030000)\n", BA0READ4(sc, CS4281_DCR0))); 652 DPRINTF(("FCR0 =0x%08x(expected 0x81000f00)\n", BA0READ4(sc, CS4281_FCR0))); 653 DPRINTF(("DACSR=0x%08x(expected 1 for 44kHz 5 for 8kHz)\n", 654 BA0READ4(sc, CS4281_DACSR))); 655 DPRINTF(("SRCSA=0x%08x(expected 0x0b0a0100)\n", BA0READ4(sc, CS4281_SRCSA))); 656 DPRINTF(("SSPM&SSPM_PSRCEN =0x%08x(expected 0x00000010)\n", 657 BA0READ4(sc, CS4281_SSPM) & SSPM_PSRCEN)); 658 659 return 0; 660} 661 662int 663cs4281_trigger_input(addr, start, end, blksize, intr, arg, param) 664 void *addr; 665 void *start, *end; 666 int blksize; 667 void (*intr) __P((void *)); 668 void *arg; 669 struct audio_params *param; 670{ 671 struct cs428x_softc *sc = addr; 672 struct cs428x_dma *p; 673 u_int32_t fmt=0; 674 int dma_count; 675 676 printf("cs4281_trigger_input: not implemented yet\n"); 677#ifdef DIAGNOSTIC 678 if (sc->sc_rrun) 679 printf("cs4281_trigger_input: already running\n"); 680 sc->sc_rrun = 1; 681#endif 682 DPRINTF(("cs4281_trigger_input: sc=%p start=%p end=%p " 683 "blksize=%d intr=%p(%p)\n", addr, start, end, blksize, intr, arg)); 684 sc->sc_rintr = intr; 685 sc->sc_rarg = arg; 686 687 /* stop recording DMA */ 688 BA0WRITE4(sc, CS4281_DCR1, BA0READ4(sc, CS4281_DCR1) | DCRn_MSK); 689 690 for (p = sc->sc_dmas; p && BUFADDR(p) != start; p = p->next) 691 ; 692 if (!p) { 693 printf("cs4281_trigger_input: bad addr %p\n", start); 694 return (EINVAL); 695 } 696 697 sc->sc_rcount = blksize / sc->hw_blocksize; 698 sc->sc_rs = (char *)start; 699 sc->sc_re = (char *)end; 700 sc->sc_rdma = p; 701 sc->sc_rbuf = KERNADDR(p); 702 sc->sc_ri = 0; 703 sc->sc_rn = sc->sc_rs; 704 705 dma_count = sc->dma_size; 706 if (param->precision * param->factor == 8) 707 dma_count /= 2; 708 if (param->channels > 1) 709 dma_count /= 2; 710 711 DPRINTF(("cs4281_trigger_input: DMAADDR(p)=0x%x count=%d\n", 712 (int)DMAADDR(p), dma_count)); 713 BA0WRITE4(sc, CS4281_DBA1, DMAADDR(p)); 714 BA0WRITE4(sc, CS4281_DBC1, dma_count-1); 715 716 /* set recording format */ 717 fmt = BA0READ4(sc, CS4281_DMR1) & ~DMRn_FMTMSK; 718 if (param->precision * param->factor == 8) 719 fmt |= DMRn_SIZE8; 720 if (param->channels == 1) 721 fmt |= DMRn_MONO; 722 if (param->encoding == AUDIO_ENCODING_ULINEAR_BE || 723 param->encoding == AUDIO_ENCODING_SLINEAR_BE) 724 fmt |= DMRn_BEND; 725 if (param->encoding == AUDIO_ENCODING_ULINEAR_BE || 726 param->encoding == AUDIO_ENCODING_ULINEAR_LE) 727 fmt |= DMRn_USIGN; 728 BA0WRITE4(sc, CS4281_DMR1, fmt); 729 730 /* set sample rate */ 731 cs4281_set_adc_rate(sc, param->sample_rate); 732 733 /* Start DMA */ 734 BA0WRITE4(sc, CS4281_DCR1, BA0READ4(sc, CS4281_DCR1) & ~DCRn_MSK); 735 /* Enable interrupts */ 736 BA0WRITE4(sc, CS4281_HICR, HICR_IEV | HICR_CHGM); 737 738 DPRINTF(("HICR=0x%08x\n", BA0READ4(sc, CS4281_HICR))); 739 DPRINTF(("HIMR=0x%08x\n", BA0READ4(sc, CS4281_HIMR))); 740 DPRINTF(("DMR1=0x%08x\n", BA0READ4(sc, CS4281_DMR1))); 741 DPRINTF(("DCR1=0x%08x\n", BA0READ4(sc, CS4281_DCR1))); 742 743 return 0; 744} 745 746/* convert sample rate to register value */ 747u_int8_t 748cs4281_sr2regval(rate) 749 int rate; 750{ 751 u_int8_t retval; 752 753 /* We don't have to change here. but anyway ... */ 754 if (rate > 48000) 755 rate = 48000; 756 if (rate < 6023) 757 rate = 6023; 758 759 switch (rate) { 760 case 8000: 761 retval = 5; 762 break; 763 case 11025: 764 retval = 4; 765 break; 766 case 16000: 767 retval = 3; 768 break; 769 case 22050: 770 retval = 2; 771 break; 772 case 44100: 773 retval = 1; 774 break; 775 case 48000: 776 retval = 0; 777 break; 778 default: 779 retval = 1536000/rate; /* == 24576000/(rate*16) */ 780 } 781 return retval; 782} 783 784 785void 786cs4281_set_dac_rate(sc, rate) 787 struct cs428x_softc *sc; 788 int rate; 789{ 790 BA0WRITE4(sc, CS4281_DACSR, cs4281_sr2regval(rate)); 791} 792 793void 794cs4281_set_adc_rate(sc, rate) 795 struct cs428x_softc *sc; 796 int rate; 797{ 798 BA0WRITE4(sc, CS4281_ADCSR, cs4281_sr2regval(rate)); 799} 800 801int 802cs4281_init(sc) 803 struct cs428x_softc *sc; 804{ 805 int n; 806 u_int16_t data; 807 u_int32_t dat32; 808 809 /* set "Configuration Write Protect" register to 810 * 0x4281 to allow to write */ 811 BA0WRITE4(sc, CS4281_CWPR, 0x4281); 812 813 /* Start PLL out in known state */ 814 BA0WRITE4(sc, CS4281_CLKCR1, 0); 815 /* Start serial ports out in known state */ 816 BA0WRITE4(sc, CS4281_SERMC, 0); 817 818 /* Reset codec */ 819 BA0WRITE4(sc, CS428X_ACCTL, 0); 820 delay(50); /* delay 50us */ 821 822 BA0WRITE4(sc, CS4281_SPMC, 0); 823 delay(100); /* delay 100us */ 824 BA0WRITE4(sc, CS4281_SPMC, SPMC_RSTN); 825#if defined(ENABLE_SECONDARY_CODEC) 826 BA0WRITE4(sc, CS4281_SPMC, SPMC_RSTN | SPCM_ASDIN2E); 827 BA0WRITE4(sc, CS4281_SERMC, SERMC_TCID); 828#endif 829 delay(50000); /* XXX: delay 50ms */ 830 831 /* Turn on Sound System clocks based on ABITCLK */ 832 BA0WRITE4(sc, CS4281_CLKCR1, CLKCR1_DLLP); 833 delay(50000); /* XXX: delay 50ms */ 834 BA0WRITE4(sc, CS4281_CLKCR1, CLKCR1_SWCE | CLKCR1_DLLP); 835 836 /* Set enables for sections that are needed in the SSPM registers */ 837 BA0WRITE4(sc, CS4281_SSPM, 838 SSPM_MIXEN | /* Mixer */ 839 SSPM_CSRCEN | /* Capture SRC */ 840 SSPM_PSRCEN | /* Playback SRC */ 841 SSPM_JSEN | /* Joystick */ 842 SSPM_ACLEN | /* AC LINK */ 843 SSPM_FMEN /* FM */ 844 ); 845 846 /* Wait for clock stabilization */ 847 n = 0; 848#if 1 849 /* what document says */ 850 while ( ( BA0READ4(sc, CS4281_CLKCR1)& (CLKCR1_DLLRDY | CLKCR1_CLKON)) 851 != (CLKCR1_DLLRDY | CLKCR1_CLKON )) { 852 delay(100); 853 if ( ++n > 1000 ) 854 return -1; 855 } 856#else 857 /* Cirrus driver for Linux does */ 858 while ( !(BA0READ4(sc, CS4281_CLKCR1) & CLKCR1_DLLRDY)) { 859 delay(1000); 860 if ( ++n > 1000 ) 861 return -1; 862 } 863#endif 864 865 /* Enable ASYNC generation */ 866 BA0WRITE4(sc, CS428X_ACCTL, ACCTL_ESYN); 867 868 /* Wait for Codec ready. Linux driver wait 50ms here */ 869 n = 0; 870 while((BA0READ4(sc, CS428X_ACSTS) & ACSTS_CRDY) == 0) { 871 delay(100); 872 if (++n > 1000) 873 return -1; 874 } 875 876#if defined(ENABLE_SECONDARY_CODEC) 877 /* secondary codec ready*/ 878 n = 0; 879 while((BA0READ4(sc, CS4281_ACSTS2) & ACSTS2_CRDY2) == 0) { 880 delay(100); 881 if (++n > 1000) 882 return -1; 883 } 884#endif 885 886 /* Set the serial timing configuration */ 887 /* XXX: undocumented but the Linux driver do this */ 888 BA0WRITE4(sc, CS4281_SERMC, SERMC_PTCAC97); 889 890 /* Wait for Codec ready signal */ 891 n = 0; 892 do { 893 delay(1000); 894 if (++n > 1000) { 895 printf("%s: Timeout waiting for Codec ready\n", 896 sc->sc_dev.dv_xname); 897 return -1; 898 } 899 dat32 = BA0READ4(sc, CS428X_ACSTS) & ACSTS_CRDY; 900 } while (dat32 == 0); 901 902 /* Enable Valid Frame output on ASDOUT */ 903 BA0WRITE4(sc, CS428X_ACCTL, ACCTL_ESYN | ACCTL_VFRM); 904 905 /* Wait until Codec Calibration is finished. Codec register 26h */ 906 n = 0; 907 do { 908 delay(1); 909 if (++n > 1000) { 910 printf("%s: Timeout waiting for Codec calibration\n", 911 sc->sc_dev.dv_xname); 912 return -1; 913 } 914 cs4281_read_codec(sc, AC97_REG_POWER, &data); 915 } while ((data & 0x0f) != 0x0f); 916 917 /* Set the serial timing configuration again */ 918 /* XXX: undocumented but the Linux driver do this */ 919 BA0WRITE4(sc, CS4281_SERMC, SERMC_PTCAC97); 920 921 /* Wait until we've sampled input slots 3 & 4 as valid */ 922 n = 0; 923 do { 924 delay(1000); 925 if (++n > 1000) { 926 printf("%s: Timeout waiting for sampled input slots as valid\n", 927 sc->sc_dev.dv_xname); 928 return -1; 929 } 930 dat32 = BA0READ4(sc, CS428X_ACISV) & (ACISV_ISV3 | ACISV_ISV4); 931 } while (dat32 != (ACISV_ISV3 | ACISV_ISV4)); 932 933 /* Start digital data transfer of audio data to the codec */ 934 BA0WRITE4(sc, CS428X_ACOSV, (ACOSV_SLV3 | ACOSV_SLV4)); 935 936 cs4281_write_codec(sc, AC97_REG_HEADPHONE_VOLUME, 0); 937 cs4281_write_codec(sc, AC97_REG_MASTER_VOLUME, 0); 938 939 /* Power on the DAC */ 940 cs4281_read_codec(sc, AC97_REG_POWER, &data); 941 cs4281_write_codec(sc, AC97_REG_POWER, data & 0xfdff); 942 943 /* Wait until we sample a DAC ready state. 944 * Not documented, but Linux driver does. 945 */ 946 for (n = 0; n < 32; ++n) { 947 delay(1000); 948 cs4281_read_codec(sc, AC97_REG_POWER, &data); 949 if (data & 0x02) 950 break; 951 } 952 953 /* Power on the ADC */ 954 cs4281_read_codec(sc, AC97_REG_POWER, &data); 955 cs4281_write_codec(sc, AC97_REG_POWER, data & 0xfeff); 956 957 /* Wait until we sample ADC ready state. 958 * Not documented, but Linux driver does. 959 */ 960 for (n = 0; n < 32; ++n) { 961 delay(1000); 962 cs4281_read_codec(sc, AC97_REG_POWER, &data); 963 if (data & 0x01) 964 break; 965 } 966 967#if 0 968 /* Initialize AC-Link features */ 969 /* variable sample-rate support */ 970 mem = BA0READ4(sc, CS4281_SERMC); 971 mem |= (SERMC_ODSEN1 | SERMC_ODSEN2); 972 BA0WRITE4(sc, CS4281_SERMC, mem); 973 /* XXX: more... */ 974 975 /* Initialize SSCR register features */ 976 /* XXX: hardware volume setting */ 977 BA0WRITE4(sc, CS4281_SSCR, ~SSCR_HVC); /* disable HW volume setting */ 978#endif 979 980 /* disable Sound Blaster Pro emulation */ 981 /* XXX: 982 * Cannot set since the documents does not describe which bit is 983 * correspond to SSCR_SB. Since the reset value of SSCR is 0, 984 * we can ignore it.*/ 985#if 0 986 BA0WRITE4(sc, CS4281_SSCR, SSCR_SB); 987#endif 988 989 /* map AC97 PCM playback to DMA Channel 0 */ 990 /* Reset FEN bit to setup first */ 991 BA0WRITE4(sc, CS4281_FCR0, (BA0READ4(sc,CS4281_FCR0) & ~FCRn_FEN)); 992 /* 993 *| RS[4:0]/| | 994 *| LS[4:0] | AC97 | Slot Function 995 *|---------+--------+-------------------- 996 *| 0 | 3 | Left PCM Playback 997 *| 1 | 4 | Right PCM Playback 998 *| 2 | 5 | Phone Line 1 DAC 999 *| 3 | 6 | Center PCM Playback 1000 *.... 1001 * quoted from Table 29(p109) 1002 */ 1003 dat32 = 0x01 << 24 | /* RS[4:0] = 1 see above */ 1004 0x00 << 16 | /* LS[4:0] = 0 see above */ 1005 0x0f << 8 | /* SZ[6:0] = 15 size of buffer */ 1006 0x00 << 0 ; /* OF[6:0] = 0 offset */ 1007 BA0WRITE4(sc, CS4281_FCR0, dat32); 1008 BA0WRITE4(sc, CS4281_FCR0, dat32 | FCRn_FEN); 1009 1010 /* map AC97 PCM record to DMA Channel 1 */ 1011 /* Reset FEN bit to setup first */ 1012 BA0WRITE4(sc, CS4281_FCR1, (BA0READ4(sc,CS4281_FCR1) & ~FCRn_FEN)); 1013 /* 1014 *| RS[4:0]/| 1015 *| LS[4:0] | AC97 | Slot Function 1016 *|---------+------+------------------- 1017 *| 10 | 3 | Left PCM Record 1018 *| 11 | 4 | Right PCM Record 1019 *| 12 | 5 | Phone Line 1 ADC 1020 *| 13 | 6 | Mic ADC 1021 *.... 1022 * quoted from Table 30(p109) 1023 */ 1024 dat32 = 0x0b << 24 | /* RS[4:0] = 11 See above */ 1025 0x0a << 16 | /* LS[4:0] = 10 See above */ 1026 0x0f << 8 | /* SZ[6:0] = 15 Size of buffer */ 1027 0x10 << 0 ; /* OF[6:0] = 16 offset */ 1028 1029 /* XXX: I cannot understand why FCRn_PSH is needed here. */ 1030 BA0WRITE4(sc, CS4281_FCR1, dat32 | FCRn_PSH); 1031 BA0WRITE4(sc, CS4281_FCR1, dat32 | FCRn_FEN); 1032 1033#if 0 1034 /* Disable DMA Channel 2, 3 */ 1035 BA0WRITE4(sc, CS4281_FCR2, (BA0READ4(sc,CS4281_FCR2) & ~FCRn_FEN)); 1036 BA0WRITE4(sc, CS4281_FCR3, (BA0READ4(sc,CS4281_FCR3) & ~FCRn_FEN)); 1037#endif 1038 1039 /* Set the SRC Slot Assignment accordingly */ 1040 /*| PLSS[4:0]/ 1041 *| PRSS[4:0] | AC97 | Slot Function 1042 *|-----------+------+---------------- 1043 *| 0 | 3 | Left PCM Playback 1044 *| 1 | 4 | Right PCM Playback 1045 *| 2 | 5 | phone line 1 DAC 1046 *| 3 | 6 | Center PCM Playback 1047 *| 4 | 7 | Left Surround PCM Playback 1048 *| 5 | 8 | Right Surround PCM Playback 1049 *...... 1050 * 1051 *| CLSS[4:0]/ 1052 *| CRSS[4:0] | AC97 | Codec |Slot Function 1053 *|-----------+------+-------+----------------- 1054 *| 10 | 3 |Primary| Left PCM Record 1055 *| 11 | 4 |Primary| Right PCM Record 1056 *| 12 | 5 |Primary| Phone Line 1 ADC 1057 *| 13 | 6 |Primary| Mic ADC 1058 *|..... 1059 *| 20 | 3 | Sec. | Left PCM Record 1060 *| 21 | 4 | Sec. | Right PCM Record 1061 *| 22 | 5 | Sec. | Phone Line 1 ADC 1062 *| 23 | 6 | Sec. | Mic ADC 1063 */ 1064 dat32 = 0x0b << 24 | /* CRSS[4:0] Right PCM Record(primary) */ 1065 0x0a << 16 | /* CLSS[4:0] Left PCM Record(primary) */ 1066 0x01 << 8 | /* PRSS[4:0] Right PCM Playback */ 1067 0x00 << 0; /* PLSS[4:0] Left PCM Playback */ 1068 BA0WRITE4(sc, CS4281_SRCSA, dat32); 1069 1070 /* Set interrupt to occured at Half and Full terminal 1071 * count interrupt enable for DMA channel 0 and 1. 1072 * To keep DMA stop, set MSK. 1073 */ 1074 dat32 = DCRn_HTCIE | DCRn_TCIE | DCRn_MSK; 1075 BA0WRITE4(sc, CS4281_DCR0, dat32); 1076 BA0WRITE4(sc, CS4281_DCR1, dat32); 1077 1078 /* Set Auto-Initialize Contorl enable */ 1079 BA0WRITE4(sc, CS4281_DMR0, 1080 DMRn_DMA | DMRn_AUTO | DMRn_TR_READ); 1081 BA0WRITE4(sc, CS4281_DMR1, 1082 DMRn_DMA | DMRn_AUTO | DMRn_TR_WRITE); 1083 1084 /* Clear DMA Mask in HIMR */ 1085 dat32 = ~HIMR_DMAIM & ~HIMR_D1IM & ~HIMR_D0IM; 1086 BA0WRITE4(sc, CS4281_HIMR, 1087 BA0READ4(sc, CS4281_HIMR) & dat32); 1088 return 0; 1089} 1090 1091void 1092cs4281_power(why, v) 1093 int why; 1094 void *v; 1095{ 1096 struct cs428x_softc *sc = (struct cs428x_softc *)v; 1097 1098 DPRINTF(("%s: cs4281_power why=%d\n", sc->sc_dev.dv_xname, why)); 1099 switch (why) { 1100 case PWR_SUSPEND: 1101 case PWR_STANDBY: 1102 sc->sc_suspend = why; 1103 1104 cs4281_halt_output(sc); 1105 cs4281_halt_input(sc); 1106 /* should I powerdown here ? */ 1107 cs4281_write_codec(sc, AC97_REG_POWER, CS4281_POWER_DOWN_ALL); 1108 break; 1109 case PWR_RESUME: 1110 if (sc->sc_suspend == PWR_RESUME) { 1111 printf("cs4281_power: odd, resume without suspend.\n"); 1112 sc->sc_suspend = why; 1113 return; 1114 } 1115 sc->sc_suspend = why; 1116 cs4281_init(sc); 1117 cs4281_reset_codec(sc); 1118 1119 (*sc->codec_if->vtbl->restore_ports)(sc->codec_if); 1120 break; 1121 case PWR_SOFTSUSPEND: 1122 case PWR_SOFTSTANDBY: 1123 case PWR_SOFTRESUME: 1124 break; 1125 } 1126} 1127 1128void 1129cs4281_reset_codec(void *addr) 1130{ 1131 struct cs428x_softc *sc; 1132 u_int16_t data; 1133 u_int32_t dat32; 1134 int n; 1135 1136 sc = addr; 1137 1138 DPRINTFN(3,("cs4281_reset_codec\n")); 1139 1140 /* Reset codec */ 1141 BA0WRITE4(sc, CS428X_ACCTL, 0); 1142 delay(50); /* delay 50us */ 1143 1144 BA0WRITE4(sc, CS4281_SPMC, 0); 1145 delay(100); /* delay 100us */ 1146 BA0WRITE4(sc, CS4281_SPMC, SPMC_RSTN); 1147#if defined(ENABLE_SECONDARY_CODEC) 1148 BA0WRITE4(sc, CS4281_SPMC, SPMC_RSTN | SPCM_ASDIN2E); 1149 BA0WRITE4(sc, CS4281_SERMC, SERMC_TCID); 1150#endif 1151 delay(50000); /* XXX: delay 50ms */ 1152 1153 /* Enable ASYNC generation */ 1154 BA0WRITE4(sc, CS428X_ACCTL, ACCTL_ESYN); 1155 1156 /* Wait for Codec ready. Linux driver wait 50ms here */ 1157 n = 0; 1158 while((BA0READ4(sc, CS428X_ACSTS) & ACSTS_CRDY) == 0) { 1159 delay(100); 1160 if (++n > 1000) { 1161 printf("reset_codec: AC97 codec ready timeout\n"); 1162 return; 1163 } 1164 } 1165#if defined(ENABLE_SECONDARY_CODEC) 1166 /* secondary codec ready*/ 1167 n = 0; 1168 while((BA0READ4(sc, CS4281_ACSTS2) & ACSTS2_CRDY2) == 0) { 1169 delay(100); 1170 if (++n > 1000) 1171 return; 1172 } 1173#endif 1174 /* Set the serial timing configuration */ 1175 /* XXX: undocumented but the Linux driver do this */ 1176 BA0WRITE4(sc, CS4281_SERMC, SERMC_PTCAC97); 1177 1178 /* Wait for Codec ready signal */ 1179 n = 0; 1180 do { 1181 delay(1000); 1182 if (++n > 1000) { 1183 printf("%s: Timeout waiting for Codec ready\n", 1184 sc->sc_dev.dv_xname); 1185 return; 1186 } 1187 dat32 = BA0READ4(sc, CS428X_ACSTS) & ACSTS_CRDY; 1188 } while (dat32 == 0); 1189 1190 /* Enable Valid Frame output on ASDOUT */ 1191 BA0WRITE4(sc, CS428X_ACCTL, ACCTL_ESYN | ACCTL_VFRM); 1192 1193 /* Wait until Codec Calibration is finished. Codec register 26h */ 1194 n = 0; 1195 do { 1196 delay(1); 1197 if (++n > 1000) { 1198 printf("%s: Timeout waiting for Codec calibration\n", 1199 sc->sc_dev.dv_xname); 1200 return ; 1201 } 1202 cs4281_read_codec(sc, AC97_REG_POWER, &data); 1203 } while ((data & 0x0f) != 0x0f); 1204 1205 /* Set the serial timing configuration again */ 1206 /* XXX: undocumented but the Linux driver do this */ 1207 BA0WRITE4(sc, CS4281_SERMC, SERMC_PTCAC97); 1208 1209 /* Wait until we've sampled input slots 3 & 4 as valid */ 1210 n = 0; 1211 do { 1212 delay(1000); 1213 if (++n > 1000) { 1214 printf("%s: Timeout waiting for sampled input slots as valid\n", 1215 sc->sc_dev.dv_xname); 1216 return; 1217 } 1218 dat32 = BA0READ4(sc, CS428X_ACISV) & (ACISV_ISV3 | ACISV_ISV4) ; 1219 } while (dat32 != (ACISV_ISV3 | ACISV_ISV4)); 1220 1221 /* Start digital data transfer of audio data to the codec */ 1222 BA0WRITE4(sc, CS428X_ACOSV, (ACOSV_SLV3 | ACOSV_SLV4)); 1223} 1224 1225#ifdef NOT_SHARED 1226/* From here to last, all functions may shared with cs4280.c */ 1227 1228int 1229cs4281_open(void *addr, int flags) 1230{ 1231 return 0; 1232} 1233 1234void 1235cs4281_close(void *addr) 1236{ 1237 struct cs428x_softc *sc; 1238 1239 sc = addr; 1240 1241 (*sc->halt_output)(sc); 1242 (*sc->halt_input)(sc); 1243 1244 sc->sc_pintr = 0; 1245 sc->sc_rintr = 0; 1246} 1247 1248int 1249cs4281_round_blocksize(void *addr, int blk) 1250{ 1251 struct cs428x_softc *sc; 1252 int retval; 1253 1254 DPRINTFN(5,("cs4281_round_blocksize blk=%d -> ", blk)); 1255 1256 sc=addr; 1257 if (blk < sc->hw_blocksize) 1258 retval = sc->hw_blocksize; 1259 else 1260 retval = blk & -(sc->hw_blocksize); 1261 1262 DPRINTFN(5,("%d\n", retval)); 1263 1264 return retval; 1265} 1266 1267int 1268cs4281_mixer_set_port(void *addr, mixer_ctrl_t *cp) 1269{ 1270 struct cs428x_softc *sc; 1271 int val; 1272 1273 sc = addr; 1274 val = sc->codec_if->vtbl->mixer_set_port(sc->codec_if, cp); 1275 DPRINTFN(3,("mixer_set_port: val=%d\n", val)); 1276 return (val); 1277} 1278 1279int 1280cs4281_mixer_get_port(void *addr, mixer_ctrl_t *cp) 1281{ 1282 struct cs428x_softc *sc; 1283 1284 sc = addr; 1285 return (sc->codec_if->vtbl->mixer_get_port(sc->codec_if, cp)); 1286} 1287 1288 1289int 1290cs4281_query_devinfo(void *addr, mixer_devinfo_t *dip) 1291{ 1292 struct cs428x_softc *sc; 1293 1294 sc = addr; 1295 return (sc->codec_if->vtbl->query_devinfo(sc->codec_if, dip)); 1296} 1297 1298void * 1299cs4281_malloc(void *addr, int direction, size_t size, int pool, int flags) 1300{ 1301 struct cs428x_softc *sc; 1302 struct cs428x_dma *p; 1303 int error; 1304 1305 sc = addr; 1306 1307 p = malloc(sizeof(*p), pool, flags); 1308 if (!p) 1309 return 0; 1310 1311 error = cs4281_allocmem(sc, size, pool, flags, p); 1312 1313 if (error) { 1314 free(p, pool); 1315 return 0; 1316 } 1317 1318 p->next = sc->sc_dmas; 1319 sc->sc_dmas = p; 1320 return BUFADDR(p); 1321} 1322 1323 1324 1325void 1326cs4281_free(void *addr, void *ptr, int pool) 1327{ 1328 struct cs428x_softc *sc; 1329 struct cs428x_dma **pp, *p; 1330 1331 sc = addr; 1332 for (pp = &sc->sc_dmas; (p = *pp) != NULL; pp = &p->next) { 1333 if (BUFADDR(p) == ptr) { 1334 bus_dmamap_unload(sc->sc_dmatag, p->map); 1335 bus_dmamap_destroy(sc->sc_dmatag, p->map); 1336 bus_dmamem_unmap(sc->sc_dmatag, p->addr, p->size); 1337 bus_dmamem_free(sc->sc_dmatag, p->segs, p->nsegs); 1338 free(p->dum, pool); 1339 *pp = p->next; 1340 free(p, pool); 1341 return; 1342 } 1343 } 1344} 1345 1346size_t 1347cs4281_round_buffersize(void *addr, int direction, size_t size) 1348{ 1349 /* The real dma buffersize are 4KB for CS4280 1350 * and 64kB/MAX_CHANNELS for CS4281. 1351 * But they are too small for high quality audio, 1352 * let the upper layer(audio) use a larger buffer. 1353 * (originally suggested by Lennart Augustsson.) 1354 */ 1355 return size; 1356} 1357 1358paddr_t 1359cs4281_mappage(void *addr, void *mem, off_t off, int prot) 1360{ 1361 struct cs428x_softc *sc; 1362 struct cs428x_dma *p; 1363 1364 sc = addr; 1365 if (off < 0) 1366 return -1; 1367 1368 for (p = sc->sc_dmas; p && BUFADDR(p) != mem; p = p->next) 1369 ; 1370 1371 if (!p) { 1372 DPRINTF(("cs4281_mappage: bad buffer address\n")); 1373 return -1; 1374 } 1375 1376 return (bus_dmamem_mmap(sc->sc_dmatag, p->segs, p->nsegs, 1377 off, prot, BUS_DMA_WAITOK)); 1378} 1379 1380 1381int 1382cs4281_get_props(void *addr) 1383{ 1384 int retval; 1385 1386 retval = AUDIO_PROP_INDEPENDENT | AUDIO_PROP_FULLDUPLEX; 1387#ifdef MMAP_READY 1388 retval |= AUDIO_PROP_MMAP; 1389#endif 1390 return retval; 1391} 1392 1393/* AC97 */ 1394int 1395cs4281_attach_codec(void *addr, struct ac97_codec_if *codec_if) 1396{ 1397 struct cs428x_softc *sc; 1398 1399 DPRINTF(("cs4281_attach_codec:\n")); 1400 sc = addr; 1401 sc->codec_if = codec_if; 1402 return 0; 1403} 1404 1405 1406int 1407cs4281_read_codec(void *addr, u_int8_t ac97_addr, u_int16_t *ac97_data) 1408{ 1409 struct cs428x_softc *sc; 1410 u_int32_t acctl; 1411 int n; 1412 1413 sc = addr; 1414 1415 DPRINTFN(5,("read_codec: add=0x%02x ", ac97_addr)); 1416 /* 1417 * Make sure that there is not data sitting around from a preivous 1418 * uncompleted access. 1419 */ 1420 BA0READ4(sc, CS428X_ACSDA); 1421 1422 /* Set up AC97 control registers. */ 1423 BA0WRITE4(sc, CS428X_ACCAD, ac97_addr); 1424 BA0WRITE4(sc, CS428X_ACCDA, 0); 1425 1426 acctl = ACCTL_ESYN | ACCTL_VFRM | ACCTL_CRW | ACCTL_DCV; 1427 if ( sc->type == TYPE_CS4280 ) 1428 acctl |= ACCTL_RSTN; 1429 BA0WRITE4(sc, CS428X_ACCTL, acctl); 1430 1431 if (cs4281_src_wait(sc) < 0) { 1432 printf("%s: AC97 read prob. (DCV!=0) for add=0x%0x\n", 1433 sc->sc_dev.dv_xname, ac97_addr); 1434 return 1; 1435 } 1436 1437 /* wait for valid status bit is active */ 1438 n = 0; 1439 while ((BA0READ4(sc, CS428X_ACSTS) & ACSTS_VSTS) == 0) { 1440 delay(1); 1441 while (++n > 1000) { 1442 printf("%s: AC97 read fail (VSTS==0) for add=0x%0x\n", 1443 sc->sc_dev.dv_xname, ac97_addr); 1444 return 1; 1445 } 1446 } 1447 *ac97_data = BA0READ4(sc, CS428X_ACSDA); 1448 DPRINTFN(5,("data=0x%04x\n", *ac97_data)); 1449 return 0; 1450} 1451 1452int 1453cs4281_write_codec(void *addr, u_int8_t ac97_addr, u_int16_t ac97_data) 1454{ 1455 struct cs428x_softc *sc; 1456 u_int32_t acctl; 1457 1458 sc = addr; 1459 1460 DPRINTFN(5,("write_codec: add=0x%02x data=0x%04x\n", ac97_addr, ac97_data)); 1461 BA0WRITE4(sc, CS428X_ACCAD, ac97_addr); 1462 BA0WRITE4(sc, CS428X_ACCDA, ac97_data); 1463 1464 acctl = ACCTL_ESYN | ACCTL_VFRM | ACCTL_DCV; 1465 if ( sc->type == TYPE_CS4280 ) 1466 acctl |= ACCTL_RSTN; 1467 BA0WRITE4(sc, CS428X_ACCTL, acctl); 1468 1469 if (cs4281_src_wait(sc) < 0) { 1470 printf("%s: AC97 write fail (DCV!=0) for add=0x%02x data=" 1471 "0x%04x\n", sc->sc_dev.dv_xname, ac97_addr, ac97_data); 1472 return 1; 1473 } 1474 return 0; 1475} 1476 1477/* Internal functions */ 1478int 1479cs4281_allocmem(struct cs428x_softc *sc, 1480 size_t size, int pool, int flags, 1481 struct cs428x_dma *p) 1482{ 1483 int error; 1484 size_t align; 1485 1486 align = sc->dma_align; 1487 p->size = sc->dma_size; 1488 /* allocate memory for upper audio driver */ 1489 p->dum = malloc(size, pool, flags); 1490 if (!p->dum) 1491 return 1; 1492 error = bus_dmamem_alloc(sc->sc_dmatag, p->size, align, 0, 1493 p->segs, sizeof(p->segs)/sizeof(p->segs[0]), 1494 &p->nsegs, BUS_DMA_NOWAIT); 1495 if (error) { 1496 printf("%s: unable to allocate dma. error=%d\n", 1497 sc->sc_dev.dv_xname, error); 1498 return error; 1499 } 1500 1501 error = bus_dmamem_map(sc->sc_dmatag, p->segs, p->nsegs, p->size, 1502 &p->addr, BUS_DMA_NOWAIT|BUS_DMA_COHERENT); 1503 if (error) { 1504 printf("%s: unable to map dma, error=%d\n", 1505 sc->sc_dev.dv_xname, error); 1506 goto free; 1507 } 1508 1509 error = bus_dmamap_create(sc->sc_dmatag, p->size, 1, p->size, 1510 0, BUS_DMA_NOWAIT, &p->map); 1511 if (error) { 1512 printf("%s: unable to create dma map, error=%d\n", 1513 sc->sc_dev.dv_xname, error); 1514 goto unmap; 1515 } 1516 1517 error = bus_dmamap_load(sc->sc_dmatag, p->map, p->addr, p->size, NULL, 1518 BUS_DMA_NOWAIT); 1519 if (error) { 1520 printf("%s: unable to load dma map, error=%d\n", 1521 sc->sc_dev.dv_xname, error); 1522 goto destroy; 1523 } 1524 return 0; 1525 1526destroy: 1527 bus_dmamap_destroy(sc->sc_dmatag, p->map); 1528unmap: 1529 bus_dmamem_unmap(sc->sc_dmatag, p->addr, p->size); 1530free: 1531 bus_dmamem_free(sc->sc_dmatag, p->segs, p->nsegs); 1532 return error; 1533} 1534 1535 1536int 1537cs4281_src_wait(sc) 1538 struct cs428x_softc *sc; 1539{ 1540 int n; 1541 1542 n = 0; 1543 while ((BA0READ4(sc, CS428X_ACCTL) & ACCTL_DCV)) { 1544 delay(1000); 1545 while (++n > 1000) 1546 return -1; 1547 } 1548 return 0; 1549} 1550 1551#endif /* NOT_SHARED */ 1552