1 /* $NetBSD: cs4280.c,v 1.34 2005/01/15 15:19:52 kent Exp $ */ 2 3 /* 4 * Copyright (c) 1999, 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 CS4280 (and maybe CS461x) driver. 35 * Data sheets can be found 36 * http://www.cirrus.com/ftp/pubs/4280.pdf 37 * http://www.cirrus.com/ftp/pubs/4297.pdf 38 * ftp://ftp.alsa-project.org/pub/manuals/cirrus/embedded_audio_spec.pdf 39 * ftp://ftp.alsa-project.org/pub/manuals/cirrus/embedded_audio_spec.doc 40 * 41 * Note: CS4610/CS4611 + CS423x ISA codec should be worked with 42 * wss* at pnpbios? 43 * or 44 * sb* at pnpbios? 45 * Since I could not find any documents on handling ISA codec, 46 * clcs does not support those chips. 47 */ 48 49 /* 50 * TODO 51 * Joystick support 52 */ 53 54 #include <sys/cdefs.h> 55 __KERNEL_RCSID(0, "$NetBSD: cs4280.c,v 1.34 2005/01/15 15:19:52 kent Exp $"); 56 57 #include "midi.h" 58 59 #include <sys/param.h> 60 #include <sys/systm.h> 61 #include <sys/kernel.h> 62 #include <sys/fcntl.h> 63 #include <sys/malloc.h> 64 #include <sys/device.h> 65 #include <sys/proc.h> 66 #include <sys/systm.h> 67 68 #include <dev/pci/pcidevs.h> 69 #include <dev/pci/pcivar.h> 70 #include <dev/pci/cs4280reg.h> 71 #include <dev/pci/cs4280_image.h> 72 #include <dev/pci/cs428xreg.h> 73 74 #include <sys/audioio.h> 75 #include <dev/audio_if.h> 76 #include <dev/midi_if.h> 77 #include <dev/mulaw.h> 78 #include <dev/auconv.h> 79 80 #include <dev/ic/ac97reg.h> 81 #include <dev/ic/ac97var.h> 82 83 #include <dev/pci/cs428x.h> 84 85 #include <machine/bus.h> 86 #include <machine/bswap.h> 87 88 #define BA1READ4(sc, r) bus_space_read_4((sc)->ba1t, (sc)->ba1h, (r)) 89 #define BA1WRITE4(sc, r, x) bus_space_write_4((sc)->ba1t, (sc)->ba1h, (r), (x)) 90 91 /* IF functions for audio driver */ 92 int cs4280_match(struct device *, struct cfdata *, void *); 93 void cs4280_attach(struct device *, struct device *, void *); 94 int cs4280_intr(void *); 95 int cs4280_query_encoding(void *, struct audio_encoding *); 96 int cs4280_set_params(void *, int, int, audio_params_t *, audio_params_t *, 97 stream_filter_list_t *, stream_filter_list_t *); 98 int cs4280_halt_output(void *); 99 int cs4280_halt_input(void *); 100 int cs4280_getdev(void *, struct audio_device *); 101 int cs4280_trigger_output(void *, void *, void *, int, void (*)(void *), 102 void *, const audio_params_t *); 103 int cs4280_trigger_input(void *, void *, void *, int, void (*)(void *), 104 void *, const audio_params_t *); 105 106 int cs4280_reset_codec(void *); 107 108 /* For PowerHook */ 109 void cs4280_power(int, void *); 110 111 /* Internal functions */ 112 void cs4280_set_adc_rate(struct cs428x_softc *, int ); 113 void cs4280_set_dac_rate(struct cs428x_softc *, int ); 114 int cs4280_download(struct cs428x_softc *, const uint32_t *, uint32_t, uint32_t); 115 int cs4280_download_image(struct cs428x_softc *); 116 void cs4280_reset(void *); 117 int cs4280_init(struct cs428x_softc *, int); 118 void cs4280_clear_fifos(struct cs428x_softc *); 119 120 #if CS4280_DEBUG > 10 121 /* Thease two function is only for checking image loading is succeeded or not. */ 122 int cs4280_check_images(struct cs428x_softc *); 123 int cs4280_checkimage(struct cs428x_softc *, uint32_t *, uint32_t, uint32_t); 124 #endif 125 126 const struct audio_hw_if cs4280_hw_if = { 127 NULL, /* open */ 128 NULL, /* close */ 129 NULL, 130 cs4280_query_encoding, 131 cs4280_set_params, 132 cs428x_round_blocksize, 133 NULL, 134 NULL, 135 NULL, 136 NULL, 137 NULL, 138 cs4280_halt_output, 139 cs4280_halt_input, 140 NULL, 141 cs4280_getdev, 142 NULL, 143 cs428x_mixer_set_port, 144 cs428x_mixer_get_port, 145 cs428x_query_devinfo, 146 cs428x_malloc, 147 cs428x_free, 148 cs428x_round_buffersize, 149 cs428x_mappage, 150 cs428x_get_props, 151 cs4280_trigger_output, 152 cs4280_trigger_input, 153 NULL, 154 }; 155 156 #if NMIDI > 0 157 /* Midi Interface */ 158 int cs4280_midi_open(void *, int, void (*)(void *, int), 159 void (*)(void *), void *); 160 void cs4280_midi_close(void*); 161 int cs4280_midi_output(void *, int); 162 void cs4280_midi_getinfo(void *, struct midi_info *); 163 164 const struct midi_hw_if cs4280_midi_hw_if = { 165 cs4280_midi_open, 166 cs4280_midi_close, 167 cs4280_midi_output, 168 cs4280_midi_getinfo, 169 0, 170 }; 171 #endif 172 173 CFATTACH_DECL(clcs, sizeof(struct cs428x_softc), 174 cs4280_match, cs4280_attach, NULL, NULL); 175 176 struct audio_device cs4280_device = { 177 "CS4280", 178 "", 179 "cs4280" 180 }; 181 182 183 int 184 cs4280_match(struct device *parent, struct cfdata *match, void *aux) 185 { 186 struct pci_attach_args *pa; 187 188 pa = (struct pci_attach_args *)aux; 189 if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_CIRRUS) 190 return 0; 191 if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_CIRRUS_CS4280 192 #if 0 /* I can't confirm */ 193 || PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_CIRRUS_CS4610 194 #endif 195 ) 196 return 1; 197 return 0; 198 } 199 200 void 201 cs4280_attach(struct device *parent, struct device *self, void *aux) 202 { 203 struct cs428x_softc *sc; 204 struct pci_attach_args *pa; 205 pci_chipset_tag_t pc; 206 char const *intrstr; 207 pci_intr_handle_t ih; 208 pcireg_t reg; 209 char devinfo[256]; 210 uint32_t mem; 211 int pci_pwrmgmt_cap_reg, pci_pwrmgmt_csr_reg; 212 213 sc = (struct cs428x_softc *)self; 214 pa = (struct pci_attach_args *)aux; 215 pc = pa->pa_pc; 216 aprint_naive(": Audio controller\n"); 217 218 pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo, sizeof(devinfo)); 219 aprint_normal(": %s (rev. 0x%02x)\n", devinfo, 220 PCI_REVISION(pa->pa_class)); 221 222 /* Map I/O register */ 223 if (pci_mapreg_map(pa, PCI_BA0, 224 PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT, 0, 225 &sc->ba0t, &sc->ba0h, NULL, NULL)) { 226 aprint_error("%s: can't map BA0 space\n", sc->sc_dev.dv_xname); 227 return; 228 } 229 if (pci_mapreg_map(pa, PCI_BA1, 230 PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT, 0, 231 &sc->ba1t, &sc->ba1h, NULL, NULL)) { 232 aprint_error("%s: can't map BA1 space\n", sc->sc_dev.dv_xname); 233 return; 234 } 235 236 sc->sc_dmatag = pa->pa_dmat; 237 238 /* Check and set Power State */ 239 if (pci_get_capability(pa->pa_pc, pa->pa_tag, PCI_CAP_PWRMGMT, 240 &pci_pwrmgmt_cap_reg, 0)) { 241 pci_pwrmgmt_csr_reg = pci_pwrmgmt_cap_reg + PCI_PMCSR; 242 reg = pci_conf_read(pa->pa_pc, pa->pa_tag, 243 pci_pwrmgmt_csr_reg); 244 DPRINTF(("%s: Power State is %d\n", 245 sc->sc_dev.dv_xname, reg & PCI_PMCSR_STATE_MASK)); 246 if ((reg & PCI_PMCSR_STATE_MASK) != PCI_PMCSR_STATE_D0) { 247 pci_conf_write(pc, pa->pa_tag, pci_pwrmgmt_csr_reg, 248 (reg & ~PCI_PMCSR_STATE_MASK) | 249 PCI_PMCSR_STATE_D0); 250 } 251 } 252 253 /* Enable the device (set bus master flag) */ 254 reg = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); 255 pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, 256 reg | PCI_COMMAND_MASTER_ENABLE); 257 258 /* LATENCY_TIMER setting */ 259 mem = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_BHLC_REG); 260 if ( PCI_LATTIMER(mem) < 32 ) { 261 mem &= 0xffff00ff; 262 mem |= 0x00002000; 263 pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_BHLC_REG, mem); 264 } 265 266 /* Map and establish the interrupt. */ 267 if (pci_intr_map(pa, &ih)) { 268 aprint_error("%s: couldn't map interrupt\n", 269 sc->sc_dev.dv_xname); 270 return; 271 } 272 intrstr = pci_intr_string(pc, ih); 273 274 sc->sc_ih = pci_intr_establish(pc, ih, IPL_AUDIO, cs4280_intr, sc); 275 if (sc->sc_ih == NULL) { 276 aprint_error("%s: couldn't establish interrupt", 277 sc->sc_dev.dv_xname); 278 if (intrstr != NULL) 279 aprint_normal(" at %s", intrstr); 280 aprint_normal("\n"); 281 return; 282 } 283 aprint_normal("%s: interrupting at %s\n", sc->sc_dev.dv_xname, intrstr); 284 285 /* Initialization */ 286 if(cs4280_init(sc, 1) != 0) 287 return; 288 289 sc->type = TYPE_CS4280; 290 sc->halt_input = cs4280_halt_input; 291 sc->halt_output = cs4280_halt_output; 292 293 /* setup buffer related parameters */ 294 sc->dma_size = CS4280_DCHUNK; 295 sc->dma_align = CS4280_DALIGN; 296 sc->hw_blocksize = CS4280_ICHUNK; 297 298 /* AC 97 attachment */ 299 sc->host_if.arg = sc; 300 sc->host_if.attach = cs428x_attach_codec; 301 sc->host_if.read = cs428x_read_codec; 302 sc->host_if.write = cs428x_write_codec; 303 sc->host_if.reset = cs4280_reset_codec; 304 if (ac97_attach(&sc->host_if, self) != 0) { 305 aprint_error("%s: ac97_attach failed\n", sc->sc_dev.dv_xname); 306 return; 307 } 308 309 audio_attach_mi(&cs4280_hw_if, sc, &sc->sc_dev); 310 311 #if NMIDI > 0 312 midi_attach_mi(&cs4280_midi_hw_if, sc, &sc->sc_dev); 313 #endif 314 315 sc->sc_suspend = PWR_RESUME; 316 sc->sc_powerhook = powerhook_establish(cs4280_power, sc); 317 } 318 319 /* Interrupt handling function */ 320 int 321 cs4280_intr(void *p) 322 { 323 /* 324 * XXX 325 * 326 * Since CS4280 has only 4kB DMA buffer and 327 * interrupt occurs every 2kB block, I create dummy buffer 328 * which returns to audio driver and actual DMA buffer 329 * using in DMA transfer. 330 * 331 * 332 * ring buffer in audio.c is pointed by BUFADDR 333 * <------ ring buffer size == 64kB ------> 334 * <-----> blksize == 2048*(sc->sc_[pr]count) kB 335 * |= = = =|= = = =|= = = =|= = = =|= = = =| 336 * | | | | | | <- call audio_intp every 337 * sc->sc_[pr]_count time. 338 * 339 * actual DMA buffer is pointed by KERNADDR 340 * <-> DMA buffer size = 4kB 341 * |= =| 342 * 343 * 344 */ 345 struct cs428x_softc *sc; 346 uint32_t intr, mem; 347 char * empty_dma; 348 int handled; 349 350 sc = p; 351 handled = 0; 352 /* grab interrupt register then clear it */ 353 intr = BA0READ4(sc, CS4280_HISR); 354 BA0WRITE4(sc, CS4280_HICR, HICR_CHGM | HICR_IEV); 355 356 /* Playback Interrupt */ 357 if (intr & HISR_PINT) { 358 handled = 1; 359 mem = BA1READ4(sc, CS4280_PFIE); 360 BA1WRITE4(sc, CS4280_PFIE, (mem & ~PFIE_PI_MASK) | PFIE_PI_DISABLE); 361 if (sc->sc_prun) { 362 if ((sc->sc_pi%sc->sc_pcount) == 0) 363 sc->sc_pintr(sc->sc_parg); 364 } else { 365 printf("unexpected play intr\n"); 366 } 367 /* copy buffer */ 368 ++sc->sc_pi; 369 empty_dma = sc->sc_pdma->addr; 370 if (sc->sc_pi&1) 371 empty_dma += sc->hw_blocksize; 372 memcpy(empty_dma, sc->sc_pn, sc->hw_blocksize); 373 sc->sc_pn += sc->hw_blocksize; 374 if (sc->sc_pn >= sc->sc_pe) 375 sc->sc_pn = sc->sc_ps; 376 BA1WRITE4(sc, CS4280_PFIE, mem); 377 } 378 /* Capture Interrupt */ 379 if (intr & HISR_CINT) { 380 int i; 381 int16_t rdata; 382 383 handled = 1; 384 mem = BA1READ4(sc, CS4280_CIE); 385 BA1WRITE4(sc, CS4280_CIE, (mem & ~CIE_CI_MASK) | CIE_CI_DISABLE); 386 ++sc->sc_ri; 387 empty_dma = sc->sc_rdma->addr; 388 if ((sc->sc_ri&1) == 0) 389 empty_dma += sc->hw_blocksize; 390 391 /* 392 * XXX 393 * I think this audio data conversion should be 394 * happend in upper layer, but I put this here 395 * since there is no conversion function available. 396 */ 397 switch(sc->sc_rparam) { 398 case CF_16BIT_STEREO: 399 /* just copy it */ 400 memcpy(sc->sc_rn, empty_dma, sc->hw_blocksize); 401 sc->sc_rn += sc->hw_blocksize; 402 break; 403 case CF_16BIT_MONO: 404 for (i = 0; i < 512; i++) { 405 rdata = *((int16_t *)empty_dma)>>1; 406 empty_dma += 2; 407 rdata += *((int16_t *)empty_dma)>>1; 408 empty_dma += 2; 409 *((int16_t *)sc->sc_rn) = rdata; 410 sc->sc_rn += 2; 411 } 412 break; 413 case CF_8BIT_STEREO: 414 for (i = 0; i < 512; i++) { 415 rdata = *((int16_t*)empty_dma); 416 empty_dma += 2; 417 *sc->sc_rn++ = rdata >> 8; 418 rdata = *((int16_t*)empty_dma); 419 empty_dma += 2; 420 *sc->sc_rn++ = rdata >> 8; 421 } 422 break; 423 case CF_8BIT_MONO: 424 for (i = 0; i < 512; i++) { 425 rdata = *((int16_t*)empty_dma) >>1; 426 empty_dma += 2; 427 rdata += *((int16_t*)empty_dma) >>1; 428 empty_dma += 2; 429 *sc->sc_rn++ = rdata >>8; 430 } 431 break; 432 default: 433 /* Should not reach here */ 434 printf("unknown sc->sc_rparam: %d\n", sc->sc_rparam); 435 } 436 if (sc->sc_rn >= sc->sc_re) 437 sc->sc_rn = sc->sc_rs; 438 BA1WRITE4(sc, CS4280_CIE, mem); 439 if (sc->sc_rrun) { 440 if ((sc->sc_ri%(sc->sc_rcount)) == 0) 441 sc->sc_rintr(sc->sc_rarg); 442 } else { 443 printf("unexpected record intr\n"); 444 } 445 } 446 447 #if NMIDI > 0 448 /* Midi port Interrupt */ 449 if (intr & HISR_MIDI) { 450 int data; 451 452 handled = 1; 453 DPRINTF(("i: %d: ", 454 BA0READ4(sc, CS4280_MIDSR))); 455 /* Read the received data */ 456 while ((sc->sc_iintr != NULL) && 457 ((BA0READ4(sc, CS4280_MIDSR) & MIDSR_RBE) == 0)) { 458 data = BA0READ4(sc, CS4280_MIDRP) & MIDRP_MASK; 459 DPRINTF(("r:%x\n",data)); 460 sc->sc_iintr(sc->sc_arg, data); 461 } 462 463 /* Write the data */ 464 #if 1 465 /* XXX: 466 * It seems "Transmit Buffer Full" never activate until EOI 467 * is deliverd. Shall I throw EOI top of this routine ? 468 */ 469 if ((BA0READ4(sc, CS4280_MIDSR) & MIDSR_TBF) == 0) { 470 DPRINTF(("w: ")); 471 if (sc->sc_ointr != NULL) 472 sc->sc_ointr(sc->sc_arg); 473 } 474 #else 475 while ((sc->sc_ointr != NULL) && 476 ((BA0READ4(sc, CS4280_MIDSR) & MIDSR_TBF) == 0)) { 477 DPRINTF(("w: ")); 478 sc->sc_ointr(sc->sc_arg); 479 } 480 #endif 481 DPRINTF(("\n")); 482 } 483 #endif 484 485 return handled; 486 } 487 488 int 489 cs4280_query_encoding(void *addr, struct audio_encoding *fp) 490 { 491 switch (fp->index) { 492 case 0: 493 strcpy(fp->name, AudioEulinear); 494 fp->encoding = AUDIO_ENCODING_ULINEAR; 495 fp->precision = 8; 496 fp->flags = 0; 497 break; 498 case 1: 499 strcpy(fp->name, AudioEmulaw); 500 fp->encoding = AUDIO_ENCODING_ULAW; 501 fp->precision = 8; 502 fp->flags = AUDIO_ENCODINGFLAG_EMULATED; 503 break; 504 case 2: 505 strcpy(fp->name, AudioEalaw); 506 fp->encoding = AUDIO_ENCODING_ALAW; 507 fp->precision = 8; 508 fp->flags = AUDIO_ENCODINGFLAG_EMULATED; 509 break; 510 case 3: 511 strcpy(fp->name, AudioEslinear); 512 fp->encoding = AUDIO_ENCODING_SLINEAR; 513 fp->precision = 8; 514 fp->flags = 0; 515 break; 516 case 4: 517 strcpy(fp->name, AudioEslinear_le); 518 fp->encoding = AUDIO_ENCODING_SLINEAR_LE; 519 fp->precision = 16; 520 fp->flags = 0; 521 break; 522 case 5: 523 strcpy(fp->name, AudioEulinear_le); 524 fp->encoding = AUDIO_ENCODING_ULINEAR_LE; 525 fp->precision = 16; 526 fp->flags = 0; 527 break; 528 case 6: 529 strcpy(fp->name, AudioEslinear_be); 530 fp->encoding = AUDIO_ENCODING_SLINEAR_BE; 531 fp->precision = 16; 532 fp->flags = 0; 533 break; 534 case 7: 535 strcpy(fp->name, AudioEulinear_be); 536 fp->encoding = AUDIO_ENCODING_ULINEAR_BE; 537 fp->precision = 16; 538 fp->flags = 0; 539 break; 540 default: 541 return EINVAL; 542 } 543 return 0; 544 } 545 546 int 547 cs4280_set_params(void *addr, int setmode, int usemode, 548 audio_params_t *play, audio_params_t *rec, 549 stream_filter_list_t *pfil, stream_filter_list_t *rfil) 550 { 551 audio_params_t hw; 552 struct cs428x_softc *sc; 553 struct audio_params *p; 554 stream_filter_list_t *fil; 555 int mode; 556 557 sc = addr; 558 for (mode = AUMODE_RECORD; mode != -1; 559 mode = mode == AUMODE_RECORD ? AUMODE_PLAY : -1 ) { 560 if ((setmode & mode) == 0) 561 continue; 562 563 p = mode == AUMODE_PLAY ? play : rec; 564 565 if (p == play) { 566 DPRINTFN(5,("play: sample=%ld precision=%d channels=%d\n", 567 p->sample_rate, p->precision, p->channels)); 568 /* play back data format may be 8- or 16-bit and 569 * either stereo or mono. 570 * playback rate may range from 8000Hz to 48000Hz 571 */ 572 if (p->sample_rate < 8000 || p->sample_rate > 48000 || 573 (p->precision != 8 && p->precision != 16) || 574 (p->channels != 1 && p->channels != 2) ) { 575 return EINVAL; 576 } 577 } else { 578 DPRINTFN(5,("rec: sample=%ld precision=%d channels=%d\n", 579 p->sample_rate, p->precision, p->channels)); 580 /* capture data format must be 16bit stereo 581 * and sample rate range from 11025Hz to 48000Hz. 582 * 583 * XXX: it looks like to work with 8000Hz, 584 * although data sheets say lower limit is 585 * 11025 Hz. 586 */ 587 588 if (p->sample_rate < 8000 || p->sample_rate > 48000 || 589 (p->precision != 8 && p->precision != 16) || 590 (p->channels != 1 && p->channels != 2) ) { 591 return EINVAL; 592 } 593 } 594 fil = mode == AUMODE_PLAY ? pfil : rfil; 595 hw = *p; 596 hw.encoding = AUDIO_ENCODING_SLINEAR_LE; 597 598 /* capturing data is slinear */ 599 switch (p->encoding) { 600 case AUDIO_ENCODING_SLINEAR_BE: 601 if (mode == AUMODE_RECORD && p->precision == 16) { 602 fil->append(fil, swap_bytes, &hw); 603 } 604 break; 605 case AUDIO_ENCODING_SLINEAR_LE: 606 break; 607 case AUDIO_ENCODING_ULINEAR_BE: 608 if (mode == AUMODE_RECORD) { 609 fil->append(fil, p->precision == 16 610 ? swap_bytes_change_sign16 611 : change_sign8, &hw); 612 } 613 break; 614 case AUDIO_ENCODING_ULINEAR_LE: 615 if (mode == AUMODE_RECORD) { 616 fil->append(fil, p->precision == 16 617 ? change_sign16 : change_sign8, 618 &hw); 619 } 620 break; 621 case AUDIO_ENCODING_ULAW: 622 if (mode == AUMODE_PLAY) { 623 hw.precision = 16; 624 hw.validbits = 16; 625 fil->append(fil, mulaw_to_linear16, &hw); 626 } else { 627 fil->append(fil, linear8_to_mulaw, &hw); 628 } 629 break; 630 case AUDIO_ENCODING_ALAW: 631 if (mode == AUMODE_PLAY) { 632 hw.precision = 16; 633 hw.validbits = 16; 634 fil->append(fil, alaw_to_linear16, &hw); 635 } else { 636 fil->append(fil, linear8_to_alaw, &hw); 637 } 638 break; 639 default: 640 return EINVAL; 641 } 642 } 643 644 /* set sample rate */ 645 cs4280_set_dac_rate(sc, play->sample_rate); 646 cs4280_set_adc_rate(sc, rec->sample_rate); 647 return 0; 648 } 649 650 int 651 cs4280_halt_output(void *addr) 652 { 653 struct cs428x_softc *sc; 654 uint32_t mem; 655 656 sc = addr; 657 mem = BA1READ4(sc, CS4280_PCTL); 658 BA1WRITE4(sc, CS4280_PCTL, mem & ~PCTL_MASK); 659 sc->sc_prun = 0; 660 return 0; 661 } 662 663 int 664 cs4280_halt_input(void *addr) 665 { 666 struct cs428x_softc *sc; 667 uint32_t mem; 668 669 sc = addr; 670 mem = BA1READ4(sc, CS4280_CCTL); 671 BA1WRITE4(sc, CS4280_CCTL, mem & ~CCTL_MASK); 672 sc->sc_rrun = 0; 673 return 0; 674 } 675 676 int 677 cs4280_getdev(void *addr, struct audio_device *retp) 678 { 679 680 *retp = cs4280_device; 681 return 0; 682 } 683 684 int 685 cs4280_trigger_output(void *addr, void *start, void *end, int blksize, 686 void (*intr)(void *), void *arg, 687 const audio_params_t *param) 688 { 689 struct cs428x_softc *sc; 690 uint32_t pfie, pctl, pdtc; 691 struct cs428x_dma *p; 692 693 sc = addr; 694 #ifdef DIAGNOSTIC 695 if (sc->sc_prun) 696 printf("cs4280_trigger_output: already running\n"); 697 #endif 698 sc->sc_prun = 1; 699 700 DPRINTF(("cs4280_trigger_output: sc=%p start=%p end=%p " 701 "blksize=%d intr=%p(%p)\n", addr, start, end, blksize, intr, arg)); 702 sc->sc_pintr = intr; 703 sc->sc_parg = arg; 704 705 /* stop playback DMA */ 706 BA1WRITE4(sc, CS4280_PCTL, BA1READ4(sc, CS4280_PCTL) & ~PCTL_MASK); 707 708 /* setup PDTC */ 709 pdtc = BA1READ4(sc, CS4280_PDTC); 710 pdtc &= ~PDTC_MASK; 711 pdtc |= CS4280_MK_PDTC(param->precision * param->channels); 712 BA1WRITE4(sc, CS4280_PDTC, pdtc); 713 714 DPRINTF(("param: precision=%d channels=%d encoding=%d\n", 715 param->precision, param->channels, param->encoding)); 716 for (p = sc->sc_dmas; p != NULL && BUFADDR(p) != start; p = p->next) 717 continue; 718 if (p == NULL) { 719 printf("cs4280_trigger_output: bad addr %p\n", start); 720 return EINVAL; 721 } 722 if (DMAADDR(p) % sc->dma_align != 0 ) { 723 printf("cs4280_trigger_output: DMAADDR(p)=0x%lx does not start" 724 "4kB align\n", (ulong)DMAADDR(p)); 725 return EINVAL; 726 } 727 728 sc->sc_pcount = blksize / sc->hw_blocksize; /* sc->hw_blocksize is fixed hardware blksize*/ 729 sc->sc_ps = (char *)start; 730 sc->sc_pe = (char *)end; 731 sc->sc_pdma = p; 732 sc->sc_pbuf = KERNADDR(p); 733 sc->sc_pi = 0; 734 sc->sc_pn = sc->sc_ps; 735 if (blksize >= sc->dma_size) { 736 sc->sc_pn = sc->sc_ps + sc->dma_size; 737 memcpy(sc->sc_pbuf, start, sc->dma_size); 738 ++sc->sc_pi; 739 } else { 740 sc->sc_pn = sc->sc_ps + sc->hw_blocksize; 741 memcpy(sc->sc_pbuf, start, sc->hw_blocksize); 742 } 743 744 /* initiate playback DMA */ 745 BA1WRITE4(sc, CS4280_PBA, DMAADDR(p)); 746 747 /* set PFIE */ 748 pfie = BA1READ4(sc, CS4280_PFIE) & ~PFIE_MASK; 749 750 if (param->precision == 8) 751 pfie |= PFIE_8BIT; 752 if (param->channels == 1) 753 pfie |= PFIE_MONO; 754 755 if (param->encoding == AUDIO_ENCODING_ULINEAR_BE || 756 param->encoding == AUDIO_ENCODING_SLINEAR_BE) 757 pfie |= PFIE_SWAPPED; 758 if (param->encoding == AUDIO_ENCODING_ULINEAR_BE || 759 param->encoding == AUDIO_ENCODING_ULINEAR_LE) 760 pfie |= PFIE_UNSIGNED; 761 762 BA1WRITE4(sc, CS4280_PFIE, pfie | PFIE_PI_ENABLE); 763 764 sc->sc_prate = param->sample_rate; 765 cs4280_set_dac_rate(sc, param->sample_rate); 766 767 pctl = BA1READ4(sc, CS4280_PCTL) & ~PCTL_MASK; 768 pctl |= sc->pctl; 769 BA1WRITE4(sc, CS4280_PCTL, pctl); 770 return 0; 771 } 772 773 int 774 cs4280_trigger_input(void *addr, void *start, void *end, int blksize, 775 void (*intr)(void *), void *arg, 776 const audio_params_t *param) 777 { 778 struct cs428x_softc *sc; 779 uint32_t cctl, cie; 780 struct cs428x_dma *p; 781 782 sc = addr; 783 #ifdef DIAGNOSTIC 784 if (sc->sc_rrun) 785 printf("cs4280_trigger_input: already running\n"); 786 #endif 787 sc->sc_rrun = 1; 788 789 DPRINTF(("cs4280_trigger_input: sc=%p start=%p end=%p " 790 "blksize=%d intr=%p(%p)\n", addr, start, end, blksize, intr, arg)); 791 sc->sc_rintr = intr; 792 sc->sc_rarg = arg; 793 794 /* stop capture DMA */ 795 BA1WRITE4(sc, CS4280_CCTL, BA1READ4(sc, CS4280_CCTL) & ~CCTL_MASK); 796 797 for (p = sc->sc_dmas; p && BUFADDR(p) != start; p = p->next) 798 continue; 799 if (p == NULL) { 800 printf("cs4280_trigger_input: bad addr %p\n", start); 801 return EINVAL; 802 } 803 if (DMAADDR(p) % sc->dma_align != 0) { 804 printf("cs4280_trigger_input: DMAADDR(p)=0x%lx does not start" 805 "4kB align\n", (ulong)DMAADDR(p)); 806 return EINVAL; 807 } 808 809 sc->sc_rcount = blksize / sc->hw_blocksize; /* sc->hw_blocksize is fixed hardware blksize*/ 810 sc->sc_rs = (char *)start; 811 sc->sc_re = (char *)end; 812 sc->sc_rdma = p; 813 sc->sc_rbuf = KERNADDR(p); 814 sc->sc_ri = 0; 815 sc->sc_rn = sc->sc_rs; 816 817 /* initiate capture DMA */ 818 BA1WRITE4(sc, CS4280_CBA, DMAADDR(p)); 819 820 /* setup format information for internal converter */ 821 sc->sc_rparam = 0; 822 if (param->precision == 8) { 823 sc->sc_rparam += CF_8BIT; 824 sc->sc_rcount <<= 1; 825 } 826 if (param->channels == 1) { 827 sc->sc_rparam += CF_MONO; 828 sc->sc_rcount <<= 1; 829 } 830 831 /* set CIE */ 832 cie = BA1READ4(sc, CS4280_CIE) & ~CIE_CI_MASK; 833 BA1WRITE4(sc, CS4280_CIE, cie | CIE_CI_ENABLE); 834 835 sc->sc_rrate = param->sample_rate; 836 cs4280_set_adc_rate(sc, param->sample_rate); 837 838 cctl = BA1READ4(sc, CS4280_CCTL) & ~CCTL_MASK; 839 cctl |= sc->cctl; 840 BA1WRITE4(sc, CS4280_CCTL, cctl); 841 return 0; 842 } 843 844 /* Power Hook */ 845 void 846 cs4280_power(int why, void *v) 847 { 848 static uint32_t pctl = 0, pba = 0, pfie = 0, pdtc = 0; 849 static uint32_t cctl = 0, cba = 0, cie = 0; 850 struct cs428x_softc *sc; 851 852 sc = (struct cs428x_softc *)v; 853 DPRINTF(("%s: cs4280_power why=%d\n", sc->sc_dev.dv_xname, why)); 854 switch (why) { 855 case PWR_SUSPEND: 856 case PWR_STANDBY: 857 sc->sc_suspend = why; 858 859 /* save current playback status */ 860 if (sc->sc_prun) { 861 pctl = BA1READ4(sc, CS4280_PCTL); 862 pfie = BA1READ4(sc, CS4280_PFIE); 863 pba = BA1READ4(sc, CS4280_PBA); 864 pdtc = BA1READ4(sc, CS4280_PDTC); 865 DPRINTF(("pctl=0x%08x pfie=0x%08x pba=0x%08x pdtc=0x%08x\n", 866 pctl, pfie, pba, pdtc)); 867 } 868 869 /* save current capture status */ 870 if (sc->sc_rrun) { 871 cctl = BA1READ4(sc, CS4280_CCTL); 872 cie = BA1READ4(sc, CS4280_CIE); 873 cba = BA1READ4(sc, CS4280_CBA); 874 DPRINTF(("cctl=0x%08x cie=0x%08x cba=0x%08x\n", 875 cctl, cie, cba)); 876 } 877 878 /* Stop DMA */ 879 BA1WRITE4(sc, CS4280_PCTL, pctl & ~PCTL_MASK); 880 BA1WRITE4(sc, CS4280_CCTL, BA1READ4(sc, CS4280_CCTL) & ~CCTL_MASK); 881 break; 882 case PWR_RESUME: 883 if (sc->sc_suspend == PWR_RESUME) { 884 printf("cs4280_power: odd, resume without suspend.\n"); 885 sc->sc_suspend = why; 886 return; 887 } 888 sc->sc_suspend = why; 889 cs4280_init(sc, 0); 890 cs4280_reset_codec(sc); 891 892 /* restore ac97 registers */ 893 (*sc->codec_if->vtbl->restore_ports)(sc->codec_if); 894 895 /* restore DMA related status */ 896 if(sc->sc_prun) { 897 DPRINTF(("pctl=0x%08x pfie=0x%08x pba=0x%08x pdtc=0x%08x\n", 898 pctl, pfie, pba, pdtc)); 899 cs4280_set_dac_rate(sc, sc->sc_prate); 900 BA1WRITE4(sc, CS4280_PDTC, pdtc); 901 BA1WRITE4(sc, CS4280_PBA, pba); 902 BA1WRITE4(sc, CS4280_PFIE, pfie); 903 BA1WRITE4(sc, CS4280_PCTL, pctl); 904 } 905 906 if (sc->sc_rrun) { 907 DPRINTF(("cctl=0x%08x cie=0x%08x cba=0x%08x\n", 908 cctl, cie, cba)); 909 cs4280_set_adc_rate(sc, sc->sc_rrate); 910 BA1WRITE4(sc, CS4280_CBA, cba); 911 BA1WRITE4(sc, CS4280_CIE, cie); 912 BA1WRITE4(sc, CS4280_CCTL, cctl); 913 } 914 break; 915 case PWR_SOFTSUSPEND: 916 case PWR_SOFTSTANDBY: 917 case PWR_SOFTRESUME: 918 break; 919 } 920 } 921 922 /* control AC97 codec */ 923 int 924 cs4280_reset_codec(void *addr) 925 { 926 struct cs428x_softc *sc; 927 int n; 928 929 sc = addr; 930 931 /* Reset codec */ 932 BA0WRITE4(sc, CS428X_ACCTL, 0); 933 delay(100); /* delay 100us */ 934 BA0WRITE4(sc, CS428X_ACCTL, ACCTL_RSTN); 935 936 /* 937 * It looks like we do the following procedure, too 938 */ 939 940 /* Enable AC-link sync generation */ 941 BA0WRITE4(sc, CS428X_ACCTL, ACCTL_ESYN | ACCTL_RSTN); 942 delay(50*1000); /* XXX delay 50ms */ 943 944 /* Assert valid frame signal */ 945 BA0WRITE4(sc, CS428X_ACCTL, ACCTL_VFRM | ACCTL_ESYN | ACCTL_RSTN); 946 947 /* Wait for valid AC97 input slot */ 948 n = 0; 949 while ((BA0READ4(sc, CS428X_ACISV) & (ACISV_ISV3 | ACISV_ISV4)) != 950 (ACISV_ISV3 | ACISV_ISV4)) { 951 delay(1000); 952 if (++n > 1000) { 953 printf("reset_codec: AC97 inputs slot ready timeout\n"); 954 return ETIMEDOUT; 955 } 956 } 957 return 0; 958 } 959 960 /* Internal functions */ 961 962 void 963 cs4280_set_adc_rate(struct cs428x_softc *sc, int rate) 964 { 965 /* calculate capture rate: 966 * 967 * capture_coefficient_increment = -round(rate*128*65536/48000; 968 * capture_phase_increment = floor(48000*65536*1024/rate); 969 * cx = round(48000*65536*1024 - capture_phase_increment*rate); 970 * cy = floor(cx/200); 971 * capture_sample_rate_correction = cx - 200*cy; 972 * capture_delay = ceil(24*48000/rate); 973 * capture_num_triplets = floor(65536*rate/24000); 974 * capture_group_length = 24000/GCD(rate, 24000); 975 * where GCD means "Greatest Common Divisor". 976 * 977 * capture_coefficient_increment, capture_phase_increment and 978 * capture_num_triplets are 32-bit signed quantities. 979 * capture_sample_rate_correction and capture_group_length are 980 * 16-bit signed quantities. 981 * capture_delay is a 14-bit unsigned quantity. 982 */ 983 uint32_t cci, cpi, cnt, cx, cy, tmp1; 984 uint16_t csrc, cgl, cdlay; 985 986 /* XXX 987 * Even though, embedded_audio_spec says capture rate range 11025 to 988 * 48000, dhwiface.cpp says, 989 * 990 * "We can only decimate by up to a factor of 1/9th the hardware rate. 991 * Return an error if an attempt is made to stray outside that limit." 992 * 993 * so assume range as 48000/9 to 48000 994 */ 995 996 if (rate < 8000) 997 rate = 8000; 998 if (rate > 48000) 999 rate = 48000; 1000 1001 cx = rate << 16; 1002 cci = cx / 48000; 1003 cx -= cci * 48000; 1004 cx <<= 7; 1005 cci <<= 7; 1006 cci += cx / 48000; 1007 cci = - cci; 1008 1009 cx = 48000 << 16; 1010 cpi = cx / rate; 1011 cx -= cpi * rate; 1012 cx <<= 10; 1013 cpi <<= 10; 1014 cy = cx / rate; 1015 cpi += cy; 1016 cx -= cy * rate; 1017 1018 cy = cx / 200; 1019 csrc = cx - 200*cy; 1020 1021 cdlay = ((48000 * 24) + rate - 1) / rate; 1022 #if 0 1023 cdlay &= 0x3fff; /* make sure cdlay is 14-bit */ 1024 #endif 1025 1026 cnt = rate << 16; 1027 cnt /= 24000; 1028 1029 cgl = 1; 1030 for (tmp1 = 2; tmp1 <= 64; tmp1 *= 2) { 1031 if (((rate / tmp1) * tmp1) != rate) 1032 cgl *= 2; 1033 } 1034 if (((rate / 3) * 3) != rate) 1035 cgl *= 3; 1036 for (tmp1 = 5; tmp1 <= 125; tmp1 *= 5) { 1037 if (((rate / tmp1) * tmp1) != rate) 1038 cgl *= 5; 1039 } 1040 #if 0 1041 /* XXX what manual says */ 1042 tmp1 = BA1READ4(sc, CS4280_CSRC) & ~CSRC_MASK; 1043 tmp1 |= csrc<<16; 1044 BA1WRITE4(sc, CS4280_CSRC, tmp1); 1045 #else 1046 /* suggested by cs461x.c (ALSA driver) */ 1047 BA1WRITE4(sc, CS4280_CSRC, CS4280_MK_CSRC(csrc, cy)); 1048 #endif 1049 1050 #if 0 1051 /* I am confused. The sample rate calculation section says 1052 * cci *is* 32-bit signed quantity but in the parameter description 1053 * section, CCI only assigned 16bit. 1054 * I believe size of the variable. 1055 */ 1056 tmp1 = BA1READ4(sc, CS4280_CCI) & ~CCI_MASK; 1057 tmp1 |= cci<<16; 1058 BA1WRITE4(sc, CS4280_CCI, tmp1); 1059 #else 1060 BA1WRITE4(sc, CS4280_CCI, cci); 1061 #endif 1062 1063 tmp1 = BA1READ4(sc, CS4280_CD) & ~CD_MASK; 1064 tmp1 |= cdlay <<18; 1065 BA1WRITE4(sc, CS4280_CD, tmp1); 1066 1067 BA1WRITE4(sc, CS4280_CPI, cpi); 1068 1069 tmp1 = BA1READ4(sc, CS4280_CGL) & ~CGL_MASK; 1070 tmp1 |= cgl; 1071 BA1WRITE4(sc, CS4280_CGL, tmp1); 1072 1073 BA1WRITE4(sc, CS4280_CNT, cnt); 1074 1075 tmp1 = BA1READ4(sc, CS4280_CGC) & ~CGC_MASK; 1076 tmp1 |= cgl; 1077 BA1WRITE4(sc, CS4280_CGC, tmp1); 1078 } 1079 1080 void 1081 cs4280_set_dac_rate(struct cs428x_softc *sc, int rate) 1082 { 1083 /* 1084 * playback rate may range from 8000Hz to 48000Hz 1085 * 1086 * play_phase_increment = floor(rate*65536*1024/48000) 1087 * px = round(rate*65536*1024 - play_phase_incremnt*48000) 1088 * py=floor(px/200) 1089 * play_sample_rate_correction = px - 200*py 1090 * 1091 * play_phase_increment is a 32bit signed quantity. 1092 * play_sample_rate_correction is a 16bit signed quantity. 1093 */ 1094 int32_t ppi; 1095 int16_t psrc; 1096 uint32_t px, py; 1097 1098 if (rate < 8000) 1099 rate = 8000; 1100 if (rate > 48000) 1101 rate = 48000; 1102 px = rate << 16; 1103 ppi = px/48000; 1104 px -= ppi*48000; 1105 ppi <<= 10; 1106 px <<= 10; 1107 py = px / 48000; 1108 ppi += py; 1109 px -= py*48000; 1110 py = px/200; 1111 px -= py*200; 1112 psrc = px; 1113 #if 0 1114 /* what manual says */ 1115 px = BA1READ4(sc, CS4280_PSRC) & ~PSRC_MASK; 1116 BA1WRITE4(sc, CS4280_PSRC, 1117 ( ((psrc<<16) & PSRC_MASK) | px )); 1118 #else 1119 /* suggested by cs461x.c (ALSA driver) */ 1120 BA1WRITE4(sc, CS4280_PSRC, CS4280_MK_PSRC(psrc,py)); 1121 #endif 1122 BA1WRITE4(sc, CS4280_PPI, ppi); 1123 } 1124 1125 /* Download Proceessor Code and Data image */ 1126 int 1127 cs4280_download(struct cs428x_softc *sc, const uint32_t *src, 1128 uint32_t offset, uint32_t len) 1129 { 1130 uint32_t ctr; 1131 #if CS4280_DEBUG > 10 1132 uint32_t con, data; 1133 uint8_t c0, c1, c2, c3; 1134 #endif 1135 if ((offset & 3) || (len & 3)) 1136 return -1; 1137 1138 len /= sizeof(uint32_t); 1139 for (ctr = 0; ctr < len; ctr++) { 1140 /* XXX: 1141 * I cannot confirm this is the right thing or not 1142 * on BIG-ENDIAN machines. 1143 */ 1144 BA1WRITE4(sc, offset+ctr*4, htole32(*(src+ctr))); 1145 #if CS4280_DEBUG > 10 1146 data = htole32(*(src+ctr)); 1147 c0 = bus_space_read_1(sc->ba1t, sc->ba1h, offset+ctr*4+0); 1148 c1 = bus_space_read_1(sc->ba1t, sc->ba1h, offset+ctr*4+1); 1149 c2 = bus_space_read_1(sc->ba1t, sc->ba1h, offset+ctr*4+2); 1150 c3 = bus_space_read_1(sc->ba1t, sc->ba1h, offset+ctr*4+3); 1151 con = (c3 << 24) | (c2 << 16) | (c1 << 8) | c0; 1152 if (data != con ) { 1153 printf("0x%06x: write=0x%08x read=0x%08x\n", 1154 offset+ctr*4, data, con); 1155 return -1; 1156 } 1157 #endif 1158 } 1159 return 0; 1160 } 1161 1162 int 1163 cs4280_download_image(struct cs428x_softc *sc) 1164 { 1165 int idx, err; 1166 uint32_t offset = 0; 1167 1168 err = 0; 1169 for (idx = 0; idx < BA1_MEMORY_COUNT; ++idx) { 1170 err = cs4280_download(sc, &BA1Struct.map[offset], 1171 BA1Struct.memory[idx].offset, 1172 BA1Struct.memory[idx].size); 1173 if (err != 0) { 1174 printf("%s: load_image failed at %d\n", 1175 sc->sc_dev.dv_xname, idx); 1176 return -1; 1177 } 1178 offset += BA1Struct.memory[idx].size / sizeof(uint32_t); 1179 } 1180 return err; 1181 } 1182 1183 /* Processor Soft Reset */ 1184 void 1185 cs4280_reset(void *sc_) 1186 { 1187 struct cs428x_softc *sc; 1188 1189 sc = sc_; 1190 /* Set RSTSP bit in SPCR (also clear RUN, RUNFR, and DRQEN) */ 1191 BA1WRITE4(sc, CS4280_SPCR, SPCR_RSTSP); 1192 delay(100); 1193 /* Clear RSTSP bit in SPCR */ 1194 BA1WRITE4(sc, CS4280_SPCR, 0); 1195 /* enable DMA reqest */ 1196 BA1WRITE4(sc, CS4280_SPCR, SPCR_DRQEN); 1197 } 1198 1199 int 1200 cs4280_init(struct cs428x_softc *sc, int init) 1201 { 1202 int n; 1203 uint32_t mem; 1204 1205 /* Start PLL out in known state */ 1206 BA0WRITE4(sc, CS4280_CLKCR1, 0); 1207 /* Start serial ports out in known state */ 1208 BA0WRITE4(sc, CS4280_SERMC1, 0); 1209 1210 /* Specify type of CODEC */ 1211 /* XXX should not be here */ 1212 #define SERACC_CODEC_TYPE_1_03 1213 #ifdef SERACC_CODEC_TYPE_1_03 1214 BA0WRITE4(sc, CS4280_SERACC, SERACC_HSP | SERACC_CTYPE_1_03); /* AC 97 1.03 */ 1215 #else 1216 BA0WRITE4(sc, CS4280_SERACC, SERACC_HSP | SERACC_CTYPE_2_0); /* AC 97 2.0 */ 1217 #endif 1218 1219 /* Reset codec */ 1220 BA0WRITE4(sc, CS428X_ACCTL, 0); 1221 delay(100); /* delay 100us */ 1222 BA0WRITE4(sc, CS428X_ACCTL, ACCTL_RSTN); 1223 1224 /* Enable AC-link sync generation */ 1225 BA0WRITE4(sc, CS428X_ACCTL, ACCTL_ESYN | ACCTL_RSTN); 1226 delay(50*1000); /* delay 50ms */ 1227 1228 /* Set the serial port timing configuration */ 1229 BA0WRITE4(sc, CS4280_SERMC1, SERMC1_PTC_AC97); 1230 1231 /* Setup clock control */ 1232 BA0WRITE4(sc, CS4280_PLLCC, PLLCC_CDR_STATE|PLLCC_LPF_STATE); 1233 BA0WRITE4(sc, CS4280_PLLM, PLLM_STATE); 1234 BA0WRITE4(sc, CS4280_CLKCR2, CLKCR2_PDIVS_8); 1235 1236 /* Power up the PLL */ 1237 BA0WRITE4(sc, CS4280_CLKCR1, CLKCR1_PLLP); 1238 delay(50*1000); /* delay 50ms */ 1239 1240 /* Turn on clock */ 1241 mem = BA0READ4(sc, CS4280_CLKCR1) | CLKCR1_SWCE; 1242 BA0WRITE4(sc, CS4280_CLKCR1, mem); 1243 1244 /* Set the serial port FIFO pointer to the 1245 * first sample in FIFO. (not documented) */ 1246 cs4280_clear_fifos(sc); 1247 1248 #if 0 1249 /* Set the serial port FIFO pointer to the first sample in the FIFO */ 1250 BA0WRITE4(sc, CS4280_SERBSP, 0); 1251 #endif 1252 1253 /* Configure the serial port */ 1254 BA0WRITE4(sc, CS4280_SERC1, SERC1_SO1EN | SERC1_SO1F_AC97); 1255 BA0WRITE4(sc, CS4280_SERC2, SERC2_SI1EN | SERC2_SI1F_AC97); 1256 BA0WRITE4(sc, CS4280_SERMC1, SERMC1_MSPE | SERMC1_PTC_AC97); 1257 1258 /* Wait for CODEC ready */ 1259 n = 0; 1260 while ((BA0READ4(sc, CS428X_ACSTS) & ACSTS_CRDY) == 0) { 1261 delay(125); 1262 if (++n > 1000) { 1263 printf("%s: codec ready timeout\n", 1264 sc->sc_dev.dv_xname); 1265 return 1; 1266 } 1267 } 1268 1269 /* Assert valid frame signal */ 1270 BA0WRITE4(sc, CS428X_ACCTL, ACCTL_VFRM | ACCTL_ESYN | ACCTL_RSTN); 1271 1272 /* Wait for valid AC97 input slot */ 1273 n = 0; 1274 while ((BA0READ4(sc, CS428X_ACISV) & (ACISV_ISV3 | ACISV_ISV4)) != 1275 (ACISV_ISV3 | ACISV_ISV4)) { 1276 delay(1000); 1277 if (++n > 1000) { 1278 printf("AC97 inputs slot ready timeout\n"); 1279 return 1; 1280 } 1281 } 1282 1283 /* Set AC97 output slot valid signals */ 1284 BA0WRITE4(sc, CS428X_ACOSV, ACOSV_SLV3 | ACOSV_SLV4); 1285 1286 /* reset the processor */ 1287 cs4280_reset(sc); 1288 1289 /* Download the image to the processor */ 1290 if (cs4280_download_image(sc) != 0) { 1291 printf("%s: image download error\n", sc->sc_dev.dv_xname); 1292 return 1; 1293 } 1294 1295 /* Save playback parameter and then write zero. 1296 * this ensures that DMA doesn't immediately occur upon 1297 * starting the processor core 1298 */ 1299 mem = BA1READ4(sc, CS4280_PCTL); 1300 sc->pctl = mem & PCTL_MASK; /* save startup value */ 1301 BA1WRITE4(sc, CS4280_PCTL, mem & ~PCTL_MASK); 1302 if (init != 0) 1303 sc->sc_prun = 0; 1304 1305 /* Save capture parameter and then write zero. 1306 * this ensures that DMA doesn't immediately occur upon 1307 * starting the processor core 1308 */ 1309 mem = BA1READ4(sc, CS4280_CCTL); 1310 sc->cctl = mem & CCTL_MASK; /* save startup value */ 1311 BA1WRITE4(sc, CS4280_CCTL, mem & ~CCTL_MASK); 1312 if (init != 0) 1313 sc->sc_rrun = 0; 1314 1315 /* Processor Startup Procedure */ 1316 BA1WRITE4(sc, CS4280_FRMT, FRMT_FTV); 1317 BA1WRITE4(sc, CS4280_SPCR, SPCR_RUN | SPCR_RUNFR | SPCR_DRQEN); 1318 1319 /* Monitor RUNFR bit in SPCR for 1 to 0 transition */ 1320 n = 0; 1321 while (BA1READ4(sc, CS4280_SPCR) & SPCR_RUNFR) { 1322 delay(10); 1323 if (++n > 1000) { 1324 printf("SPCR 1->0 transition timeout\n"); 1325 return 1; 1326 } 1327 } 1328 1329 n = 0; 1330 while (!(BA1READ4(sc, CS4280_SPCS) & SPCS_SPRUN)) { 1331 delay(10); 1332 if (++n > 1000) { 1333 printf("SPCS 0->1 transition timeout\n"); 1334 return 1; 1335 } 1336 } 1337 /* Processor is now running !!! */ 1338 1339 /* Setup volume */ 1340 BA1WRITE4(sc, CS4280_PVOL, 0x80008000); 1341 BA1WRITE4(sc, CS4280_CVOL, 0x80008000); 1342 1343 /* Interrupt enable */ 1344 BA0WRITE4(sc, CS4280_HICR, HICR_IEV|HICR_CHGM); 1345 1346 /* playback interrupt enable */ 1347 mem = BA1READ4(sc, CS4280_PFIE) & ~PFIE_PI_MASK; 1348 mem |= PFIE_PI_ENABLE; 1349 BA1WRITE4(sc, CS4280_PFIE, mem); 1350 /* capture interrupt enable */ 1351 mem = BA1READ4(sc, CS4280_CIE) & ~CIE_CI_MASK; 1352 mem |= CIE_CI_ENABLE; 1353 BA1WRITE4(sc, CS4280_CIE, mem); 1354 1355 #if NMIDI > 0 1356 /* Reset midi port */ 1357 mem = BA0READ4(sc, CS4280_MIDCR) & ~MIDCR_MASK; 1358 BA0WRITE4(sc, CS4280_MIDCR, mem | MIDCR_MRST); 1359 DPRINTF(("midi reset: 0x%x\n", BA0READ4(sc, CS4280_MIDCR))); 1360 /* midi interrupt enable */ 1361 mem |= MIDCR_TXE | MIDCR_RXE | MIDCR_RIE | MIDCR_TIE; 1362 BA0WRITE4(sc, CS4280_MIDCR, mem); 1363 #endif 1364 return 0; 1365 } 1366 1367 void 1368 cs4280_clear_fifos(struct cs428x_softc *sc) 1369 { 1370 int pd, cnt, n; 1371 uint32_t mem; 1372 1373 pd = 0; 1374 /* 1375 * If device power down, power up the device and keep power down 1376 * state. 1377 */ 1378 mem = BA0READ4(sc, CS4280_CLKCR1); 1379 if (!(mem & CLKCR1_SWCE)) { 1380 printf("cs4280_clear_fifo: power down found.\n"); 1381 BA0WRITE4(sc, CS4280_CLKCR1, mem | CLKCR1_SWCE); 1382 pd = 1; 1383 } 1384 BA0WRITE4(sc, CS4280_SERBWP, 0); 1385 for (cnt = 0; cnt < 256; cnt++) { 1386 n = 0; 1387 while (BA0READ4(sc, CS4280_SERBST) & SERBST_WBSY) { 1388 delay(1000); 1389 if (++n > 1000) { 1390 printf("clear_fifo: fist timeout cnt=%d\n", cnt); 1391 break; 1392 } 1393 } 1394 BA0WRITE4(sc, CS4280_SERBAD, cnt); 1395 BA0WRITE4(sc, CS4280_SERBCM, SERBCM_WRC); 1396 } 1397 if (pd) 1398 BA0WRITE4(sc, CS4280_CLKCR1, mem); 1399 } 1400 1401 #if NMIDI > 0 1402 int 1403 cs4280_midi_open(void *addr, int flags, void (*iintr)(void *, int), 1404 void (*ointr)(void *), void *arg) 1405 { 1406 struct cs428x_softc *sc; 1407 uint32_t mem; 1408 1409 DPRINTF(("midi_open\n")); 1410 sc = addr; 1411 sc->sc_iintr = iintr; 1412 sc->sc_ointr = ointr; 1413 sc->sc_arg = arg; 1414 1415 /* midi interrupt enable */ 1416 mem = BA0READ4(sc, CS4280_MIDCR) & ~MIDCR_MASK; 1417 mem |= MIDCR_TXE | MIDCR_RXE | MIDCR_RIE | MIDCR_TIE | MIDCR_MLB; 1418 BA0WRITE4(sc, CS4280_MIDCR, mem); 1419 #ifdef CS4280_DEBUG 1420 if (mem != BA0READ4(sc, CS4280_MIDCR)) { 1421 DPRINTF(("midi_open: MIDCR=%d\n", BA0READ4(sc, CS4280_MIDCR))); 1422 return(EINVAL); 1423 } 1424 DPRINTF(("MIDCR=0x%x\n", BA0READ4(sc, CS4280_MIDCR))); 1425 #endif 1426 return 0; 1427 } 1428 1429 void 1430 cs4280_midi_close(void *addr) 1431 { 1432 struct cs428x_softc *sc; 1433 uint32_t mem; 1434 1435 DPRINTF(("midi_close\n")); 1436 sc = addr; 1437 tsleep(sc, PWAIT, "cs0clm", hz/10); /* give uart a chance to drain */ 1438 mem = BA0READ4(sc, CS4280_MIDCR); 1439 mem &= ~MIDCR_MASK; 1440 BA0WRITE4(sc, CS4280_MIDCR, mem); 1441 1442 sc->sc_iintr = 0; 1443 sc->sc_ointr = 0; 1444 } 1445 1446 int 1447 cs4280_midi_output(void *addr, int d) 1448 { 1449 struct cs428x_softc *sc; 1450 uint32_t mem; 1451 int x; 1452 1453 sc = addr; 1454 for (x = 0; x != MIDI_BUSY_WAIT; x++) { 1455 if ((BA0READ4(sc, CS4280_MIDSR) & MIDSR_TBF) == 0) { 1456 mem = BA0READ4(sc, CS4280_MIDWP) & ~MIDWP_MASK; 1457 mem |= d & MIDWP_MASK; 1458 DPRINTFN(5,("midi_output d=0x%08x",d)); 1459 BA0WRITE4(sc, CS4280_MIDWP, mem); 1460 #ifdef DIAGNOSTIC 1461 if (mem != BA0READ4(sc, CS4280_MIDWP)) { 1462 DPRINTF(("Bad write data: %d %d", 1463 mem, BA0READ4(sc, CS4280_MIDWP))); 1464 return EIO; 1465 } 1466 #endif 1467 return 0; 1468 } 1469 delay(MIDI_BUSY_DELAY); 1470 } 1471 return EIO; 1472 } 1473 1474 void 1475 cs4280_midi_getinfo(void *addr, struct midi_info *mi) 1476 { 1477 1478 mi->name = "CS4280 MIDI UART"; 1479 mi->props = MIDI_PROP_CAN_INPUT | MIDI_PROP_OUT_INTR; 1480 } 1481 1482 #endif /* NMIDI */ 1483 1484 /* DEBUG functions */ 1485 #if CS4280_DEBUG > 10 1486 int 1487 cs4280_checkimage(struct cs428x_softc *sc, uint32_t *src, 1488 uint32_t offset, uint32_t len) 1489 { 1490 uint32_t ctr, data; 1491 int err; 1492 1493 if ((offset & 3) || (len & 3)) 1494 return -1; 1495 1496 err = 0; 1497 len /= sizeof(uint32_t); 1498 for (ctr = 0; ctr < len; ctr++) { 1499 /* I cannot confirm this is the right thing 1500 * on BIG-ENDIAN machines 1501 */ 1502 data = BA1READ4(sc, offset+ctr*4); 1503 if (data != htole32(*(src+ctr))) { 1504 printf("0x%06x: 0x%08x(0x%08x)\n", 1505 offset+ctr*4, data, *(src+ctr)); 1506 *(src+ctr) = data; 1507 ++err; 1508 } 1509 } 1510 return err; 1511 } 1512 1513 int 1514 cs4280_check_images(struct cs428x_softc *sc) 1515 { 1516 int idx, err; 1517 uint32_t offset; 1518 1519 offset = 0; 1520 err = 0; 1521 /*for (idx=0; idx < BA1_MEMORY_COUNT; ++idx) { */ 1522 for (idx = 0; idx < 1; ++idx) { 1523 err = cs4280_checkimage(sc, &BA1Struct.map[offset], 1524 BA1Struct.memory[idx].offset, 1525 BA1Struct.memory[idx].size); 1526 if (err != 0) { 1527 printf("%s: check_image failed at %d\n", 1528 sc->sc_dev.dv_xname, idx); 1529 } 1530 offset += BA1Struct.memory[idx].size / sizeof(uint32_t); 1531 } 1532 return err; 1533 } 1534 1535 #endif /* CS4280_DEBUG */ 1536