Deleted Added
full compact
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 ---