Deleted Added
sdiff udiff text old ( 67652 ) new ( 70134 )
full compact
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 $
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#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
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
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
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
549/* channel interface for ESS18xx */
550static void *
551esschan_init(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
571esschan_setformat(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
580esschan_setspeed(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
594esschan_setblocksize(void *data, u_int32_t blocksize)
595{
596 return blocksize;
597}
598
599static int
600esschan_trigger(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
626esschan_getptr(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 *
635esschan_getcaps(void *data)
636{
637 struct ess_chinfo *ch = data;
638
639 return (ch->dir == PCMDIR_PLAY)? &ess_playcaps : &ess_reccaps;
640}
641
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
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;
945 mixer_init(dev, &ess_mixer, sc);
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;
983 pcm_addchan(dev, PCMDIR_REC, &ess_chantemplate, sc);
984 pcm_addchan(dev, PCMDIR_PLAY, &ess_chantemplate, 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 ---