1/* 2 * Copyright (c) 1999 Seigo Tanimura 3 * All rights reserved. 4 * 5 * Portions of this source are based on cwcealdr.cpp and dhwiface.cpp in 6 * cwcealdr1.zip, the sample sources by Crystal Semiconductor. 7 * Copyright (c) 1996-1998 Crystal Semiconductor Corp. 8 * --- 13 unchanged lines hidden (view full) --- 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 * |
30 * $FreeBSD: head/sys/dev/sound/pci/csapcm.c 70134 2000-12-18 01:36:41Z cg $ |
31 */ 32 33#include <sys/soundcard.h> 34#include <dev/sound/pcm/sound.h> 35#include <dev/sound/pcm/ac97.h> 36#include <dev/sound/chip.h> 37#include <dev/sound/pci/csareg.h> 38#include <dev/sound/pci/csavar.h> --- 38 unchanged lines hidden (view full) --- 77static void csa_stopplaydma(struct csa_info *csa); 78static void csa_stopcapturedma(struct csa_info *csa); 79static void csa_powerupadc(csa_res *resp); 80static void csa_powerupdac(csa_res *resp); 81static int csa_startdsp(csa_res *resp); 82static int csa_allocres(struct csa_info *scp, device_t dev); 83static void csa_releaseres(struct csa_info *scp, device_t dev); 84 |
85static u_int32_t csa_playfmt[] = { 86 AFMT_U8, 87 AFMT_STEREO | AFMT_U8, 88 AFMT_S8, 89 AFMT_STEREO | AFMT_S8, 90 AFMT_S16_LE, 91 AFMT_STEREO | AFMT_S16_LE, 92 AFMT_S16_BE, --- 4 unchanged lines hidden (view full) --- 97 98static u_int32_t csa_recfmt[] = { 99 AFMT_S16_LE, 100 AFMT_STEREO | AFMT_S16_LE, 101 0 102}; 103static pcmchan_caps csa_reccaps = {11025, 48000, csa_recfmt, 0}; 104 |
105/* -------------------------------------------------------------------- */ |
106/* ac97 codec */ |
107 |
108static int |
109csa_rdcd(kobj_t obj, void *devinfo, int regno) |
110{ |
111 u_int32_t data; 112 struct csa_info *csa = (struct csa_info *)devinfo; |
113 |
114 if (csa_readcodec(&csa->res, regno + BA0_AC97_RESET, &data)) 115 data = 0; |
116 |
117 return data; |
118} 119 120static int |
121csa_wrcd(kobj_t obj, void *devinfo, int regno, u_int32_t data) |
122{ |
123 struct csa_info *csa = (struct csa_info *)devinfo; |
124 |
125 csa_writecodec(&csa->res, regno + BA0_AC97_RESET, data); |
126 |
127 return 0; 128} 129 |
130static kobj_method_t csa_ac97_methods[] = { 131 KOBJMETHOD(ac97_read, csa_rdcd), 132 KOBJMETHOD(ac97_write, csa_wrcd), 133 { 0, 0 } 134}; 135AC97_DECLARE(csa_ac97); |
136 |
137static void 138csa_setplaysamplerate(csa_res *resp, u_long ulInRate) 139{ 140 u_long ulTemp1, ulTemp2; 141 u_long ulPhiIncr; 142 u_long ulCorrectionPerGOF, ulCorrectionPerSec; 143 u_long ulOutRate; 144 --- 144 unchanged lines hidden (view full) --- 289 */ 290 csa_writemem(resp, BA1_CFG1, dwFrameGroupLength); 291 csa_writemem(resp, BA1_CFG2, (0x00800000 | dwFrameGroupLength)); 292 csa_writemem(resp, BA1_CCST, 0x0000FFFF); 293 csa_writemem(resp, BA1_CSPB, ((65536 * ulOutRate) / 24000)); 294 csa_writemem(resp, (BA1_CSPB + 4), 0x0000FFFF); 295} 296 |
297static void 298csa_startplaydma(struct csa_info *csa) 299{ 300 csa_res *resp; 301 u_long ul; 302 303 if (!csa->pch.dma) { 304 resp = &csa->res; --- 201 unchanged lines hidden (view full) --- 506 * If the run at frame bit never reset, then return an error. 507 */ 508 if((ul & SPCR_RUNFR) != 0) 509 return (EAGAIN); 510 511 return (0); 512} 513 |
514/* -------------------------------------------------------------------- */ 515/* channel interface */ 516 517static void * 518csachan_init(kobj_t obj, void *devinfo, snd_dbuf *b, pcm_channel *c, int dir) 519{ 520 struct csa_info *csa = devinfo; 521 struct csa_chinfo *ch = (dir == PCMDIR_PLAY)? &csa->pch : &csa->rch; 522 523 ch->parent = csa; 524 ch->channel = c; 525 ch->buffer = b; 526 ch->buffer->bufsize = CS461x_BUFFSIZE; 527 if (chn_allocbuf(ch->buffer, csa->parent_dmat) == -1) return NULL; 528 return ch; 529} 530 |
531static int |
532csachan_setdir(kobj_t obj, void *data, int dir) |
533{ 534 struct csa_chinfo *ch = data; 535 struct csa_info *csa = ch->parent; 536 csa_res *resp; |
537 538 resp = &csa->res; 539 540 if (dir == PCMDIR_PLAY) 541 csa_writemem(resp, BA1_PBA, vtophys(ch->buffer->buf)); 542 else 543 csa_writemem(resp, BA1_CBA, vtophys(ch->buffer->buf)); 544 ch->dir = dir; 545 return 0; 546} 547 548static int 549csachan_setformat(kobj_t obj, void *data, u_int32_t format) 550{ 551 struct csa_chinfo *ch = data; 552 struct csa_info *csa = ch->parent; 553 u_long pdtc; 554 csa_res *resp; 555 556 resp = &csa->res; 557 558 if (ch->dir == PCMDIR_REC) 559 csa_writemem(resp, BA1_CIE, (csa_readmem(resp, BA1_CIE) & ~0x0000003f) | 0x00000001); 560 else { 561 csa->pfie = csa_readmem(resp, BA1_PFIE) & ~0x0000f03f; 562 if (format & AFMT_U8 || format & AFMT_U16_LE || format & AFMT_U16_BE) 563 csa->pfie |= 0x8000; 564 if (format & AFMT_S16_BE || format & AFMT_U16_BE) 565 csa->pfie |= 0x4000; 566 if (!(format & AFMT_STEREO)) 567 csa->pfie |= 0x2000; 568 if (format & AFMT_U8 || format & AFMT_S8) 569 csa->pfie |= 0x1000; 570 csa_writemem(resp, BA1_PFIE, csa->pfie); 571 pdtc = csa_readmem(resp, BA1_PDTC) & ~0x000003ff; 572 if ((format & AFMT_S16_BE || format & AFMT_U16_BE || format & AFMT_S16_LE || format & AFMT_U16_LE) && (format & AFMT_STEREO)) 573 pdtc |= 0x00f; 574 else if ((format & AFMT_S16_BE || format & AFMT_U16_BE || format & AFMT_S16_LE || format & AFMT_U16_LE) || (format & AFMT_STEREO)) 575 pdtc |= 0x007; 576 else 577 pdtc |= 0x003; 578 csa_writemem(resp, BA1_PDTC, pdtc); 579 } 580 ch->fmt = format; 581 return 0; 582} 583 584static int 585csachan_setspeed(kobj_t obj, void *data, u_int32_t speed) 586{ 587 struct csa_chinfo *ch = data; 588 struct csa_info *csa = ch->parent; 589 csa_res *resp; 590 591 resp = &csa->res; 592 593 if (ch->dir == PCMDIR_PLAY) 594 csa_setplaysamplerate(resp, speed); 595 else if (ch->dir == PCMDIR_REC) 596 csa_setcapturesamplerate(resp, speed); 597 598 /* rec/play speeds locked together - should indicate in flags */ 599#if 0 600 if (ch->direction == PCMDIR_PLAY) d->rec[0].speed = speed; 601 else d->play[0].speed = speed; 602#endif 603 return speed; /* XXX calc real speed */ 604} 605 606static int 607csachan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize) 608{ 609#if notdef 610 return blocksize; 611#else 612 struct csa_chinfo *ch = data; 613 return ch->buffer->bufsize / 2; 614#endif /* notdef */ 615} 616 617static int 618csachan_trigger(kobj_t obj, void *data, int go) 619{ 620 struct csa_chinfo *ch = data; 621 struct csa_info *csa = ch->parent; 622 623 if (go == PCMTRIG_EMLDMAWR || go == PCMTRIG_EMLDMARD) 624 return 0; 625 626 if (ch->dir == PCMDIR_PLAY) { 627 if (go == PCMTRIG_START) 628 csa_startplaydma(csa); 629 else 630 csa_stopplaydma(csa); 631 } else { 632 if (go == PCMTRIG_START) 633 csa_startcapturedma(csa); 634 else 635 csa_stopcapturedma(csa); 636 } 637 return 0; 638} 639 640static int 641csachan_getptr(kobj_t obj, void *data) 642{ 643 struct csa_chinfo *ch = data; 644 struct csa_info *csa = ch->parent; 645 csa_res *resp; |
646 int ptr; 647 648 resp = &csa->res; 649 650 if (ch->dir == PCMDIR_PLAY) { 651 ptr = csa_readmem(resp, BA1_PBA) - vtophys(ch->buffer->buf); 652 if ((ch->fmt & AFMT_U8) != 0 || (ch->fmt & AFMT_S8) != 0) 653 ptr >>= 1; 654 } else { 655 ptr = csa_readmem(resp, BA1_CBA) - vtophys(ch->buffer->buf); 656 if ((ch->fmt & AFMT_U8) != 0 || (ch->fmt & AFMT_S8) != 0) 657 ptr >>= 1; 658 } 659 660 return (ptr); 661} 662 663static pcmchan_caps * |
664csachan_getcaps(kobj_t obj, void *data) |
665{ 666 struct csa_chinfo *ch = data; 667 return (ch->dir == PCMDIR_PLAY)? &csa_playcaps : &csa_reccaps; 668} 669 |
670static kobj_method_t csachan_methods[] = { 671 KOBJMETHOD(channel_init, csachan_init), 672 KOBJMETHOD(channel_setdir, csachan_setdir), 673 KOBJMETHOD(channel_setformat, csachan_setformat), 674 KOBJMETHOD(channel_setspeed, csachan_setspeed), 675 KOBJMETHOD(channel_setblocksize, csachan_setblocksize), 676 KOBJMETHOD(channel_trigger, csachan_trigger), 677 KOBJMETHOD(channel_getptr, csachan_getptr), 678 KOBJMETHOD(channel_getcaps, csachan_getcaps), 679 { 0, 0 } 680}; 681CHANNEL_DECLARE(csachan); 682 683/* -------------------------------------------------------------------- */ |
684/* The interrupt handler */ 685static void 686csa_intr (void *p) 687{ 688 struct csa_info *csa = p; 689 690 if ((csa->binfo->hisr & HISR_VC0) != 0) 691 chn_intr(csa->pch.channel); --- 149 unchanged lines hidden (view full) --- 841 csa_releaseres(csa, dev); 842 return (ENXIO); 843 } 844 845 if (csa_init(csa)) { 846 csa_releaseres(csa, dev); 847 return (ENXIO); 848 } |
849 codec = AC97_CREATE(dev, csa, csa_ac97); |
850 if (codec == NULL) { 851 csa_releaseres(csa, dev); 852 return (ENXIO); 853 } |
854 if (mixer_init(dev, ac97_getmixerclass(), codec) == -1) { |
855 ac97_destroy(codec); 856 csa_releaseres(csa, dev); 857 return (ENXIO); 858 } 859 860 snprintf(status, SND_STATUSLEN, "at irq %ld", rman_get_start(resp->irq)); 861 862 /* Enable interrupt. */ --- 5 unchanged lines hidden (view full) --- 868 csa_writemem(resp, BA1_PFIE, csa_readmem(resp, BA1_PFIE) & ~0x0000f03f); 869 csa_writemem(resp, BA1_CIE, (csa_readmem(resp, BA1_CIE) & ~0x0000003f) | 0x00000001); 870 871 if (pcm_register(dev, csa, 1, 1)) { 872 ac97_destroy(codec); 873 csa_releaseres(csa, dev); 874 return (ENXIO); 875 } |
876 pcm_addchan(dev, PCMDIR_REC, &csachan_class, csa); 877 pcm_addchan(dev, PCMDIR_PLAY, &csachan_class, csa); |
878 pcm_setstatus(dev, status); 879 880 return (0); 881} 882 883static int 884pcmcsa_detach(device_t dev) 885{ --- 5 unchanged lines hidden (view full) --- 891 return r; 892 893 csa = pcm_getdevinfo(dev); 894 csa_releaseres(csa, dev); 895 896 return 0; 897} 898 |
899static device_method_t pcmcsa_methods[] = { 900 /* Device interface */ 901 DEVMETHOD(device_probe , pcmcsa_probe ), 902 DEVMETHOD(device_attach, pcmcsa_attach), 903 DEVMETHOD(device_detach, pcmcsa_detach), 904 905 { 0, 0 }, 906}; --- 13 unchanged lines hidden --- |