solo.c (67652) | solo.c (70134) |
---|---|
1/* 2 * Copyright (c) 1999 Cameron Grant <gandalf@vilnya.demon.co.uk> 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. --- 8 unchanged lines hidden (view full) --- 17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23 * SUCH DAMAGE. 24 * | 1/* 2 * Copyright (c) 1999 Cameron Grant <gandalf@vilnya.demon.co.uk> 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. --- 8 unchanged lines hidden (view full) --- 17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23 * SUCH DAMAGE. 24 * |
25 * $FreeBSD: head/sys/dev/sound/pci/solo.c 67652 2000-10-26 20:46:58Z cg $ | 25 * $FreeBSD: head/sys/dev/sound/pci/solo.c 70134 2000-12-18 01:36:41Z cg $ |
26 */ 27 28#include <dev/sound/pcm/sound.h> 29 30#include <pci/pcireg.h> 31#include <pci/pcivar.h> 32 33#include <dev/sound/isa/sb.h> 34#include <dev/sound/chip.h> 35 | 26 */ 27 28#include <dev/sound/pcm/sound.h> 29 30#include <pci/pcireg.h> 31#include <pci/pcivar.h> 32 33#include <dev/sound/isa/sb.h> 34#include <dev/sound/chip.h> 35 |
36#include "mixer_if.h" 37 |
|
36#define ESS_BUFFSIZE (16384) 37#define ABS(x) (((x) < 0)? -(x) : (x)) 38 39/* if defined, playback always uses the 2nd channel and full duplex works */ 40#undef ESS18XX_DUPLEX 41 42/* more accurate clocks and split audio1/audio2 rates */ 43#define ESS18XX_NEWSPEED 44 | 38#define ESS_BUFFSIZE (16384) 39#define ABS(x) (((x) < 0)? -(x) : (x)) 40 41/* if defined, playback always uses the 2nd channel and full duplex works */ 42#undef ESS18XX_DUPLEX 43 44/* more accurate clocks and split audio1/audio2 rates */ 45#define ESS18XX_NEWSPEED 46 |
45/* channel interface for ESS */ 46static void *esschan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir); 47static int esschan_setformat(void *data, u_int32_t format); 48static int esschan_setspeed(void *data, u_int32_t speed); 49static int esschan_setblocksize(void *data, u_int32_t blocksize); 50static int esschan_trigger(void *data, int go); 51static int esschan_getptr(void *data); 52static pcmchan_caps *esschan_getcaps(void *data); 53 | |
54static u_int32_t ess_playfmt[] = { 55 AFMT_U8, 56 AFMT_STEREO | AFMT_U8, 57 AFMT_S8, 58 AFMT_STEREO | AFMT_S8, 59 AFMT_S16_LE, 60 AFMT_STEREO | AFMT_S16_LE, 61 AFMT_U16_LE, --- 13 unchanged lines hidden (view full) --- 75 AFMT_S16_BE, 76 AFMT_STEREO | AFMT_S16_BE, 77 AFMT_U16_BE, 78 AFMT_STEREO | AFMT_U16_BE, 79 0 80}; 81static pcmchan_caps ess_reccaps = {5000, 49000, ess_recfmt, 0}; 82 | 47static u_int32_t ess_playfmt[] = { 48 AFMT_U8, 49 AFMT_STEREO | AFMT_U8, 50 AFMT_S8, 51 AFMT_STEREO | AFMT_S8, 52 AFMT_S16_LE, 53 AFMT_STEREO | AFMT_S16_LE, 54 AFMT_U16_LE, --- 13 unchanged lines hidden (view full) --- 68 AFMT_S16_BE, 69 AFMT_STEREO | AFMT_S16_BE, 70 AFMT_U16_BE, 71 AFMT_STEREO | AFMT_U16_BE, 72 0 73}; 74static pcmchan_caps ess_reccaps = {5000, 49000, ess_recfmt, 0}; 75 |
83static pcm_channel ess_chantemplate = { 84 esschan_init, 85 NULL, /* setdir */ 86 esschan_setformat, 87 esschan_setspeed, 88 esschan_setblocksize, 89 esschan_trigger, 90 esschan_getptr, 91 esschan_getcaps, 92 NULL, /* free */ 93 NULL, /* nop1 */ 94 NULL, /* nop2 */ 95 NULL, /* nop3 */ 96 NULL, /* nop4 */ 97 NULL, /* nop5 */ 98 NULL, /* nop6 */ 99 NULL, /* nop7 */ 100}; 101 | |
102struct ess_info; 103 104struct ess_chinfo { 105 struct ess_info *parent; 106 pcm_channel *channel; 107 snd_dbuf *buffer; 108 int dir, hwch, stopping; 109 u_int32_t fmt, spd; --- 26 unchanged lines hidden (view full) --- 136static int ess_setupch(struct ess_info *sc, int ch, int dir, int spd, u_int32_t fmt, int len); 137static int ess_start(struct ess_chinfo *ch); 138static int ess_stop(struct ess_chinfo *ch); 139 140static int ess_dmasetup(struct ess_info *sc, int ch, u_int32_t base, u_int16_t cnt, int dir); 141static int ess_dmapos(struct ess_info *sc, int ch); 142static int ess_dmatrigger(struct ess_info *sc, int ch, int go); 143 | 76struct ess_info; 77 78struct ess_chinfo { 79 struct ess_info *parent; 80 pcm_channel *channel; 81 snd_dbuf *buffer; 82 int dir, hwch, stopping; 83 u_int32_t fmt, spd; --- 26 unchanged lines hidden (view full) --- 110static int ess_setupch(struct ess_info *sc, int ch, int dir, int spd, u_int32_t fmt, int len); 111static int ess_start(struct ess_chinfo *ch); 112static int ess_stop(struct ess_chinfo *ch); 113 114static int ess_dmasetup(struct ess_info *sc, int ch, u_int32_t base, u_int16_t cnt, int dir); 115static int ess_dmapos(struct ess_info *sc, int ch); 116static int ess_dmatrigger(struct ess_info *sc, int ch, int go); 117 |
144static int essmix_init(snd_mixer *m); 145static int essmix_set(snd_mixer *m, unsigned dev, unsigned left, unsigned right); 146static int essmix_setrecsrc(snd_mixer *m, u_int32_t src); 147 148static snd_mixer ess_mixer = { 149 "ESS mixer", 150 essmix_init, 151 NULL, 152 NULL, 153 essmix_set, 154 essmix_setrecsrc, 155}; 156 | |
157static devclass_t pcm_devclass; 158 159/* 160 * Common code for the midi and pcm functions 161 * 162 * ess_cmd write a single byte to the CMD port. 163 * ess_cmd1 write a CMD + 1 byte arg 164 * ess_cmd2 write a CMD + 2 byte arg --- 376 unchanged lines hidden (view full) --- 541 if (ch->hwch == 1) 542 ess_write(sc, 0xb8, ess_read(sc, 0xb8) & ~0x04); 543 else 544 ess_setmixer(sc, 0x78, ess_getmixer(sc, 0x78) & ~0x10); 545 DEB(printf("done with stop\n")); 546 return 0; 547} 548 | 118static devclass_t pcm_devclass; 119 120/* 121 * Common code for the midi and pcm functions 122 * 123 * ess_cmd write a single byte to the CMD port. 124 * ess_cmd1 write a CMD + 1 byte arg 125 * ess_cmd2 write a CMD + 2 byte arg --- 376 unchanged lines hidden (view full) --- 502 if (ch->hwch == 1) 503 ess_write(sc, 0xb8, ess_read(sc, 0xb8) & ~0x04); 504 else 505 ess_setmixer(sc, 0x78, ess_getmixer(sc, 0x78) & ~0x10); 506 DEB(printf("done with stop\n")); 507 return 0; 508} 509 |
510/* -------------------------------------------------------------------- */ |
|
549/* channel interface for ESS18xx */ 550static void * | 511/* channel interface for ESS18xx */ 512static void * |
551esschan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir) | 513esschan_init(kobj_t obj, void *devinfo, snd_dbuf *b, pcm_channel *c, int dir) |
552{ 553 struct ess_info *sc = devinfo; 554 struct ess_chinfo *ch = (dir == PCMDIR_PLAY)? &sc->pch : &sc->rch; 555 556 DEB(printf("esschan_init\n")); 557 ch->parent = sc; 558 ch->channel = c; 559 ch->buffer = b; 560 ch->buffer->bufsize = ESS_BUFFSIZE; 561 ch->dir = dir; 562 if (chn_allocbuf(ch->buffer, sc->parent_dmat) == -1) 563 return NULL; 564 ch->hwch = 1; 565 if ((dir == PCMDIR_PLAY) && (sc->duplex)) 566 ch->hwch = 2; 567 return ch; 568} 569 570static int | 514{ 515 struct ess_info *sc = devinfo; 516 struct ess_chinfo *ch = (dir == PCMDIR_PLAY)? &sc->pch : &sc->rch; 517 518 DEB(printf("esschan_init\n")); 519 ch->parent = sc; 520 ch->channel = c; 521 ch->buffer = b; 522 ch->buffer->bufsize = ESS_BUFFSIZE; 523 ch->dir = dir; 524 if (chn_allocbuf(ch->buffer, sc->parent_dmat) == -1) 525 return NULL; 526 ch->hwch = 1; 527 if ((dir == PCMDIR_PLAY) && (sc->duplex)) 528 ch->hwch = 2; 529 return ch; 530} 531 532static int |
571esschan_setformat(void *data, u_int32_t format) | 533esschan_setformat(kobj_t obj, void *data, u_int32_t format) |
572{ 573 struct ess_chinfo *ch = data; 574 575 ch->fmt = format; 576 return 0; 577} 578 579static int | 534{ 535 struct ess_chinfo *ch = data; 536 537 ch->fmt = format; 538 return 0; 539} 540 541static int |
580esschan_setspeed(void *data, u_int32_t speed) | 542esschan_setspeed(kobj_t obj, void *data, u_int32_t speed) |
581{ 582 struct ess_chinfo *ch = data; 583 struct ess_info *sc = ch->parent; 584 585 ch->spd = speed; 586 if (sc->newspeed) 587 ess_calcspeed9(&ch->spd); 588 else 589 ess_calcspeed8(&ch->spd); 590 return ch->spd; 591} 592 593static int | 543{ 544 struct ess_chinfo *ch = data; 545 struct ess_info *sc = ch->parent; 546 547 ch->spd = speed; 548 if (sc->newspeed) 549 ess_calcspeed9(&ch->spd); 550 else 551 ess_calcspeed8(&ch->spd); 552 return ch->spd; 553} 554 555static int |
594esschan_setblocksize(void *data, u_int32_t blocksize) | 556esschan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize) |
595{ 596 return blocksize; 597} 598 599static int | 557{ 558 return blocksize; 559} 560 561static int |
600esschan_trigger(void *data, int go) | 562esschan_trigger(kobj_t obj, void *data, int go) |
601{ 602 struct ess_chinfo *ch = data; 603 struct ess_info *sc = ch->parent; 604 605 DEB(printf("esschan_trigger: %d\n",go)); 606 if (go == PCMTRIG_EMLDMAWR || go == PCMTRIG_EMLDMARD) 607 return 0; 608 --- 9 unchanged lines hidden (view full) --- 618 default: 619 ess_stop(ch); 620 break; 621 } 622 return 0; 623} 624 625static int | 563{ 564 struct ess_chinfo *ch = data; 565 struct ess_info *sc = ch->parent; 566 567 DEB(printf("esschan_trigger: %d\n",go)); 568 if (go == PCMTRIG_EMLDMAWR || go == PCMTRIG_EMLDMARD) 569 return 0; 570 --- 9 unchanged lines hidden (view full) --- 580 default: 581 ess_stop(ch); 582 break; 583 } 584 return 0; 585} 586 587static int |
626esschan_getptr(void *data) | 588esschan_getptr(kobj_t obj, void *data) |
627{ 628 struct ess_chinfo *ch = data; 629 struct ess_info *sc = ch->parent; 630 631 return ess_dmapos(sc, ch->hwch); 632} 633 634static pcmchan_caps * | 589{ 590 struct ess_chinfo *ch = data; 591 struct ess_info *sc = ch->parent; 592 593 return ess_dmapos(sc, ch->hwch); 594} 595 596static pcmchan_caps * |
635esschan_getcaps(void *data) | 597esschan_getcaps(kobj_t obj, void *data) |
636{ 637 struct ess_chinfo *ch = data; 638 639 return (ch->dir == PCMDIR_PLAY)? &ess_playcaps : &ess_reccaps; 640} 641 | 598{ 599 struct ess_chinfo *ch = data; 600 601 return (ch->dir == PCMDIR_PLAY)? &ess_playcaps : &ess_reccaps; 602} 603 |
604static kobj_method_t esschan_methods[] = { 605 KOBJMETHOD(channel_init, esschan_init), 606 KOBJMETHOD(channel_setformat, esschan_setformat), 607 KOBJMETHOD(channel_setspeed, esschan_setspeed), 608 KOBJMETHOD(channel_setblocksize, esschan_setblocksize), 609 KOBJMETHOD(channel_trigger, esschan_trigger), 610 KOBJMETHOD(channel_getptr, esschan_getptr), 611 KOBJMETHOD(channel_getcaps, esschan_getcaps), 612 { 0, 0 } 613}; 614CHANNEL_DECLARE(esschan); 615 |
|
642/************************************************************/ 643 644static int 645essmix_init(snd_mixer *m) 646{ 647 struct ess_info *sc = mix_getdevinfo(m); 648 649 mix_setrecdevs(m, SOUND_MASK_CD | SOUND_MASK_MIC | SOUND_MASK_LINE | --- 94 unchanged lines hidden (view full) --- 744 break; 745 } 746 747 ess_setmixer(sc, 0x1c, recdev); 748 749 return src; 750} 751 | 616/************************************************************/ 617 618static int 619essmix_init(snd_mixer *m) 620{ 621 struct ess_info *sc = mix_getdevinfo(m); 622 623 mix_setrecdevs(m, SOUND_MASK_CD | SOUND_MASK_MIC | SOUND_MASK_LINE | --- 94 unchanged lines hidden (view full) --- 718 break; 719 } 720 721 ess_setmixer(sc, 0x1c, recdev); 722 723 return src; 724} 725 |
726static kobj_method_t solomixer_methods[] = { 727 KOBJMETHOD(mixer_init, essmix_init), 728 KOBJMETHOD(mixer_set, essmix_set), 729 KOBJMETHOD(mixer_setrecsrc, essmix_setrecsrc), 730 { 0, 0 } 731}; 732MIXER_DECLARE(solomixer); 733 |
|
752/************************************************************/ 753 754static int 755ess_dmasetup(struct ess_info *sc, int ch, u_int32_t base, u_int16_t cnt, int dir) 756{ 757 KASSERT(ch == 1 || ch == 2, ("bad ch")); 758 sc->dmasz[ch - 1] = cnt; 759 if (ch == 1) { --- 177 unchanged lines hidden (view full) --- 937 938 ddma = rman_get_start(sc->vc) | 1; 939 pci_write_config(dev, PCI_LEGACYCONTROL, 0x805f, 2); 940 pci_write_config(dev, PCI_DDMACONTROL, ddma, 2); 941 pci_write_config(dev, PCI_CONFIG, 0, 2); 942 943 if (ess_reset_dsp(sc)) 944 goto no; | 734/************************************************************/ 735 736static int 737ess_dmasetup(struct ess_info *sc, int ch, u_int32_t base, u_int16_t cnt, int dir) 738{ 739 KASSERT(ch == 1 || ch == 2, ("bad ch")); 740 sc->dmasz[ch - 1] = cnt; 741 if (ch == 1) { --- 177 unchanged lines hidden (view full) --- 919 920 ddma = rman_get_start(sc->vc) | 1; 921 pci_write_config(dev, PCI_LEGACYCONTROL, 0x805f, 2); 922 pci_write_config(dev, PCI_DDMACONTROL, ddma, 2); 923 pci_write_config(dev, PCI_CONFIG, 0, 2); 924 925 if (ess_reset_dsp(sc)) 926 goto no; |
945 mixer_init(dev, &ess_mixer, sc); | 927 if (mixer_init(dev, &solomixer_class, sc)) 928 goto no; |
946 947 port_wr(sc->io, 0x7, 0xb0, 1); /* enable irqs */ 948#ifdef ESS18XX_DUPLEX 949 sc->duplex = 1; 950#else 951 sc->duplex = 0; 952#endif 953 --- 21 unchanged lines hidden (view full) --- 975 } 976 977 snprintf(status, SND_STATUSLEN, "at io 0x%lx,0x%lx,0x%lx irq %ld", 978 rman_get_start(sc->io), rman_get_start(sc->sb), rman_get_start(sc->vc), 979 rman_get_start(sc->irq)); 980 981 if (pcm_register(dev, sc, 1, 1)) 982 goto no; | 929 930 port_wr(sc->io, 0x7, 0xb0, 1); /* enable irqs */ 931#ifdef ESS18XX_DUPLEX 932 sc->duplex = 1; 933#else 934 sc->duplex = 0; 935#endif 936 --- 21 unchanged lines hidden (view full) --- 958 } 959 960 snprintf(status, SND_STATUSLEN, "at io 0x%lx,0x%lx,0x%lx irq %ld", 961 rman_get_start(sc->io), rman_get_start(sc->sb), rman_get_start(sc->vc), 962 rman_get_start(sc->irq)); 963 964 if (pcm_register(dev, sc, 1, 1)) 965 goto no; |
983 pcm_addchan(dev, PCMDIR_REC, &ess_chantemplate, sc); 984 pcm_addchan(dev, PCMDIR_PLAY, &ess_chantemplate, sc); | 966 pcm_addchan(dev, PCMDIR_REC, &esschan_class, sc); 967 pcm_addchan(dev, PCMDIR_PLAY, &esschan_class, sc); |
985 pcm_setstatus(dev, status); 986 987 return 0; 988 989no: 990 ess_release_resources(sc, dev); 991 return ENXIO; 992} --- 39 unchanged lines hidden --- | 968 pcm_setstatus(dev, status); 969 970 return 0; 971 972no: 973 ess_release_resources(sc, dev); 974 return ENXIO; 975} --- 39 unchanged lines hidden --- |