summaryrefslogtreecommitdiffstats
path: root/sys/dev/sound/pci
diff options
context:
space:
mode:
authorcg <cg@FreeBSD.org>2000-12-18 01:36:41 +0000
committercg <cg@FreeBSD.org>2000-12-18 01:36:41 +0000
commit2fae4aec24ea4529882b3ec4cda45661ccd48ea8 (patch)
treee7e32573ed48df98bed54daa386c3520e959e951 /sys/dev/sound/pci
parent1fd2c926a884cc824e7da7ee1a51dad72b1dec5b (diff)
downloadFreeBSD-src-2fae4aec24ea4529882b3ec4cda45661ccd48ea8.zip
FreeBSD-src-2fae4aec24ea4529882b3ec4cda45661ccd48ea8.tar.gz
kobjify.
this gives us several benefits, including: * easier extensibility- new optional methods can be added to ac97/mixer/channel classes without having to fixup every driver. * forward compatibility for drivers, provided no new mandatory methods are added.
Diffstat (limited to 'sys/dev/sound/pci')
-rw-r--r--sys/dev/sound/pci/aureal.c99
-rw-r--r--sys/dev/sound/pci/csapcm.c333
-rw-r--r--sys/dev/sound/pci/ds1.c152
-rw-r--r--sys/dev/sound/pci/emu10k1.c162
-rw-r--r--sys/dev/sound/pci/es137x.c163
-rw-r--r--sys/dev/sound/pci/fm801.c419
-rw-r--r--sys/dev/sound/pci/maestro.c114
-rw-r--r--sys/dev/sound/pci/neomagic.c97
-rw-r--r--sys/dev/sound/pci/solo.c85
-rw-r--r--sys/dev/sound/pci/t4dwave.c96
-rw-r--r--sys/dev/sound/pci/via82c686.c482
11 files changed, 1024 insertions, 1178 deletions
diff --git a/sys/dev/sound/pci/aureal.c b/sys/dev/sound/pci/aureal.c
index 9a9dd0a..e957b07 100644
--- a/sys/dev/sound/pci/aureal.c
+++ b/sys/dev/sound/pci/aureal.c
@@ -37,15 +37,6 @@
#define AU8820_PCI_ID 0x000112eb
/* channel interface */
-static void *auchan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir);
-static int auchan_setdir(void *data, int dir);
-static int auchan_setformat(void *data, u_int32_t format);
-static int auchan_setspeed(void *data, u_int32_t speed);
-static int auchan_setblocksize(void *data, u_int32_t blocksize);
-static int auchan_trigger(void *data, int go);
-static int auchan_getptr(void *data);
-static pcmchan_caps *auchan_getcaps(void *data);
-
static u_int32_t au_playfmt[] = {
AFMT_U8,
AFMT_STEREO | AFMT_U8,
@@ -64,30 +55,8 @@ static u_int32_t au_recfmt[] = {
};
static pcmchan_caps au_reccaps = {4000, 48000, au_recfmt, 0};
-static pcm_channel au_chantemplate = {
- auchan_init,
- auchan_setdir,
- auchan_setformat,
- auchan_setspeed,
- auchan_setblocksize,
- auchan_trigger,
- auchan_getptr,
- auchan_getcaps,
- NULL, /* free */
- NULL, /* nop1 */
- NULL, /* nop2 */
- NULL, /* nop3 */
- NULL, /* nop4 */
- NULL, /* nop5 */
- NULL, /* nop6 */
- NULL, /* nop7 */
-};
-
/* -------------------------------------------------------------------- */
-static u_int32_t au_rdcd(void *arg, int regno);
-static void au_wrcd(void *arg, int regno, u_int32_t data);
-
struct au_info;
struct au_chinfo {
@@ -147,8 +116,10 @@ au_wr(struct au_info *au, int mapno, int regno, u_int32_t data, int size)
}
}
-static u_int32_t
-au_rdcd(void *arg, int regno)
+/* -------------------------------------------------------------------- */
+
+static int
+au_rdcd(kobj_t obj, void *arg, int regno)
{
struct au_info *au = (struct au_info *)arg;
int i=0, j=0;
@@ -166,8 +137,8 @@ au_rdcd(void *arg, int regno)
return i & AU_CDC_DATAMASK;
}
-static void
-au_wrcd(void *arg, int regno, u_int32_t data)
+static int
+au_wrcd(kobj_t obj, void *arg, int regno, u_int32_t data)
{
struct au_info *au = (struct au_info *)arg;
int i, j, tries;
@@ -188,8 +159,19 @@ au_wrcd(void *arg, int regno, u_int32_t data)
/*
if (tries == 3) printf("giving up writing 0x%4x to codec reg %2x\n", data, regno);
*/
+
+ return 0;
}
+static kobj_method_t au_ac97_methods[] = {
+ KOBJMETHOD(ac97_read, au_rdcd),
+ KOBJMETHOD(ac97_write, au_wrcd),
+ { 0, 0 }
+};
+AC97_DECLARE(au_ac97);
+
+/* -------------------------------------------------------------------- */
+
static void
au_setbit(u_int32_t *p, char bit, u_int32_t value)
{
@@ -308,9 +290,10 @@ au_prepareoutput(struct au_chinfo *ch, u_int32_t format)
au_addroute(au, 0x11, stereo? 0 : 1, 0x59);
}
+/* -------------------------------------------------------------------- */
/* channel interface */
static void *
-auchan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir)
+auchan_init(kobj_t obj, void *devinfo, snd_dbuf *b, pcm_channel *c, int dir)
{
struct au_info *au = devinfo;
struct au_chinfo *ch = (dir == PCMDIR_PLAY)? &au->pch : NULL;
@@ -319,23 +302,13 @@ auchan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir)
ch->channel = c;
ch->buffer = b;
ch->buffer->bufsize = AU_BUFFSIZE;
+ ch->dir = dir;
if (chn_allocbuf(ch->buffer, au->parent_dmat) == -1) return NULL;
return ch;
}
static int
-auchan_setdir(void *data, int dir)
-{
- struct au_chinfo *ch = data;
- if (dir == PCMDIR_PLAY) {
- } else {
- }
- ch->dir = dir;
- return 0;
-}
-
-static int
-auchan_setformat(void *data, u_int32_t format)
+auchan_setformat(kobj_t obj, void *data, u_int32_t format)
{
struct au_chinfo *ch = data;
@@ -344,7 +317,7 @@ auchan_setformat(void *data, u_int32_t format)
}
static int
-auchan_setspeed(void *data, u_int32_t speed)
+auchan_setspeed(kobj_t obj, void *data, u_int32_t speed)
{
struct au_chinfo *ch = data;
if (ch->dir == PCMDIR_PLAY) {
@@ -354,13 +327,13 @@ auchan_setspeed(void *data, u_int32_t speed)
}
static int
-auchan_setblocksize(void *data, u_int32_t blocksize)
+auchan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
{
return blocksize;
}
static int
-auchan_trigger(void *data, int go)
+auchan_trigger(kobj_t obj, void *data, int go)
{
struct au_chinfo *ch = data;
struct au_info *au = ch->parent;
@@ -382,7 +355,7 @@ auchan_trigger(void *data, int go)
}
static int
-auchan_getptr(void *data)
+auchan_getptr(kobj_t obj, void *data)
{
struct au_chinfo *ch = data;
struct au_info *au = ch->parent;
@@ -394,12 +367,25 @@ auchan_getptr(void *data)
}
static pcmchan_caps *
-auchan_getcaps(void *data)
+auchan_getcaps(kobj_t obj, void *data)
{
struct au_chinfo *ch = data;
return (ch->dir == PCMDIR_PLAY)? &au_playcaps : &au_reccaps;
}
+static kobj_method_t auchan_methods[] = {
+ KOBJMETHOD(channel_init, auchan_init),
+ KOBJMETHOD(channel_setformat, auchan_setformat),
+ KOBJMETHOD(channel_setspeed, auchan_setspeed),
+ KOBJMETHOD(channel_setblocksize, auchan_setblocksize),
+ KOBJMETHOD(channel_trigger, auchan_trigger),
+ KOBJMETHOD(channel_getptr, auchan_getptr),
+ KOBJMETHOD(channel_getcaps, auchan_getcaps),
+ { 0, 0 }
+};
+CHANNEL_DECLARE(auchan);
+
+/* -------------------------------------------------------------------- */
/* The interrupt handler */
static void
au_intr (void *p)
@@ -571,7 +557,6 @@ au_pci_attach(device_t dev)
struct ac97_info *codec;
char status[SND_STATUSLEN];
- d = device_get_softc(dev);
if ((au = malloc(sizeof(*au), M_DEVBUF, M_NOWAIT)) == NULL) {
device_printf(dev, "cannot allocate softc\n");
return ENXIO;
@@ -649,9 +634,9 @@ au_pci_attach(device_t dev)
goto bad;
}
- codec = ac97_create(dev, au, NULL, au_rdcd, au_wrcd);
+ codec = AC97_CREATE(dev, au, au_ac97);
if (codec == NULL) goto bad;
- if (mixer_init(dev, &ac97_mixer, codec) == -1) goto bad;
+ if (mixer_init(dev, ac97_getmixerclass(), codec) == -1) goto bad;
if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0,
/*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
@@ -669,7 +654,7 @@ au_pci_attach(device_t dev)
if (pcm_register(dev, au, 1, 1)) goto bad;
/* pcm_addchan(dev, PCMDIR_REC, &au_chantemplate, au); */
- pcm_addchan(dev, PCMDIR_PLAY, &au_chantemplate, au);
+ pcm_addchan(dev, PCMDIR_PLAY, &auchan_class, au);
pcm_setstatus(dev, status);
return 0;
diff --git a/sys/dev/sound/pci/csapcm.c b/sys/dev/sound/pci/csapcm.c
index 1a5f807..c3ae93e 100644
--- a/sys/dev/sound/pci/csapcm.c
+++ b/sys/dev/sound/pci/csapcm.c
@@ -82,20 +82,6 @@ static int csa_startdsp(csa_res *resp);
static int csa_allocres(struct csa_info *scp, device_t dev);
static void csa_releaseres(struct csa_info *scp, device_t dev);
-/* talk to the codec - called from ac97.c */
-static u_int32_t csa_rdcd(void *, int);
-static void csa_wrcd(void *, int, u_int32_t);
-
-/* channel interface */
-static void *csachan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir);
-static int csachan_setdir(void *data, int dir);
-static int csachan_setformat(void *data, u_int32_t format);
-static int csachan_setspeed(void *data, u_int32_t speed);
-static int csachan_setblocksize(void *data, u_int32_t blocksize);
-static int csachan_trigger(void *data, int go);
-static int csachan_getptr(void *data);
-static pcmchan_caps *csachan_getcaps(void *data);
-
static u_int32_t csa_playfmt[] = {
AFMT_U8,
AFMT_STEREO | AFMT_U8,
@@ -116,116 +102,37 @@ static u_int32_t csa_recfmt[] = {
};
static pcmchan_caps csa_reccaps = {11025, 48000, csa_recfmt, 0};
-static pcm_channel csa_chantemplate = {
- csachan_init,
- csachan_setdir,
- csachan_setformat,
- csachan_setspeed,
- csachan_setblocksize,
- csachan_trigger,
- csachan_getptr,
- csachan_getcaps,
- NULL, /* free */
- NULL, /* nop1 */
- NULL, /* nop2 */
- NULL, /* nop3 */
- NULL, /* nop4 */
- NULL, /* nop5 */
- NULL, /* nop6 */
- NULL, /* nop7 */
-};
-
/* -------------------------------------------------------------------- */
-
-/* channel interface */
-static void *
-csachan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir)
-{
- struct csa_info *csa = devinfo;
- struct csa_chinfo *ch = (dir == PCMDIR_PLAY)? &csa->pch : &csa->rch;
-
- ch->parent = csa;
- ch->channel = c;
- ch->buffer = b;
- ch->buffer->bufsize = CS461x_BUFFSIZE;
- if (chn_allocbuf(ch->buffer, csa->parent_dmat) == -1) return NULL;
- return ch;
-}
+/* ac97 codec */
static int
-csachan_setdir(void *data, int dir)
+csa_rdcd(kobj_t obj, void *devinfo, int regno)
{
- struct csa_chinfo *ch = data;
- struct csa_info *csa = ch->parent;
- csa_res *resp;
+ u_int32_t data;
+ struct csa_info *csa = (struct csa_info *)devinfo;
- resp = &csa->res;
+ if (csa_readcodec(&csa->res, regno + BA0_AC97_RESET, &data))
+ data = 0;
- if (dir == PCMDIR_PLAY)
- csa_writemem(resp, BA1_PBA, vtophys(ch->buffer->buf));
- else
- csa_writemem(resp, BA1_CBA, vtophys(ch->buffer->buf));
- ch->dir = dir;
- return 0;
+ return data;
}
static int
-csachan_setformat(void *data, u_int32_t format)
+csa_wrcd(kobj_t obj, void *devinfo, int regno, u_int32_t data)
{
- struct csa_chinfo *ch = data;
- struct csa_info *csa = ch->parent;
- u_long pdtc;
- csa_res *resp;
+ struct csa_info *csa = (struct csa_info *)devinfo;
- resp = &csa->res;
+ csa_writecodec(&csa->res, regno + BA0_AC97_RESET, data);
- if (ch->dir == PCMDIR_REC)
- csa_writemem(resp, BA1_CIE, (csa_readmem(resp, BA1_CIE) & ~0x0000003f) | 0x00000001);
- else {
- csa->pfie = csa_readmem(resp, BA1_PFIE) & ~0x0000f03f;
- if (format & AFMT_U8 || format & AFMT_U16_LE || format & AFMT_U16_BE)
- csa->pfie |= 0x8000;
- if (format & AFMT_S16_BE || format & AFMT_U16_BE)
- csa->pfie |= 0x4000;
- if (!(format & AFMT_STEREO))
- csa->pfie |= 0x2000;
- if (format & AFMT_U8 || format & AFMT_S8)
- csa->pfie |= 0x1000;
- csa_writemem(resp, BA1_PFIE, csa->pfie);
- pdtc = csa_readmem(resp, BA1_PDTC) & ~0x000003ff;
- if ((format & AFMT_S16_BE || format & AFMT_U16_BE || format & AFMT_S16_LE || format & AFMT_U16_LE) && (format & AFMT_STEREO))
- pdtc |= 0x00f;
- else if ((format & AFMT_S16_BE || format & AFMT_U16_BE || format & AFMT_S16_LE || format & AFMT_U16_LE) || (format & AFMT_STEREO))
- pdtc |= 0x007;
- else
- pdtc |= 0x003;
- csa_writemem(resp, BA1_PDTC, pdtc);
- }
- ch->fmt = format;
return 0;
}
-static int
-csachan_setspeed(void *data, u_int32_t speed)
-{
- struct csa_chinfo *ch = data;
- struct csa_info *csa = ch->parent;
- csa_res *resp;
-
- resp = &csa->res;
-
- if (ch->dir == PCMDIR_PLAY)
- csa_setplaysamplerate(resp, speed);
- else if (ch->dir == PCMDIR_REC)
- csa_setcapturesamplerate(resp, speed);
-
- /* rec/play speeds locked together - should indicate in flags */
-#if 0
- if (ch->direction == PCMDIR_PLAY) d->rec[0].speed = speed;
- else d->play[0].speed = speed;
-#endif
- return speed; /* XXX calc real speed */
-}
+static kobj_method_t csa_ac97_methods[] = {
+ KOBJMETHOD(ac97_read, csa_rdcd),
+ KOBJMETHOD(ac97_write, csa_wrcd),
+ { 0, 0 }
+};
+AC97_DECLARE(csa_ac97);
static void
csa_setplaysamplerate(csa_res *resp, u_long ulInRate)
@@ -387,40 +294,6 @@ csa_setcapturesamplerate(csa_res *resp, u_long ulOutRate)
csa_writemem(resp, (BA1_CSPB + 4), 0x0000FFFF);
}
-static int
-csachan_setblocksize(void *data, u_int32_t blocksize)
-{
-#if notdef
- return blocksize;
-#else
- struct csa_chinfo *ch = data;
- return ch->buffer->bufsize / 2;
-#endif /* notdef */
-}
-
-static int
-csachan_trigger(void *data, int go)
-{
- struct csa_chinfo *ch = data;
- struct csa_info *csa = ch->parent;
-
- if (go == PCMTRIG_EMLDMAWR || go == PCMTRIG_EMLDMARD)
- return 0;
-
- if (ch->dir == PCMDIR_PLAY) {
- if (go == PCMTRIG_START)
- csa_startplaydma(csa);
- else
- csa_stopplaydma(csa);
- } else {
- if (go == PCMTRIG_START)
- csa_startcapturedma(csa);
- else
- csa_stopcapturedma(csa);
- }
- return 0;
-}
-
static void
csa_startplaydma(struct csa_info *csa)
{
@@ -638,8 +511,134 @@ csa_startdsp(csa_res *resp)
return (0);
}
+/* -------------------------------------------------------------------- */
+/* channel interface */
+
+static void *
+csachan_init(kobj_t obj, void *devinfo, snd_dbuf *b, pcm_channel *c, int dir)
+{
+ struct csa_info *csa = devinfo;
+ struct csa_chinfo *ch = (dir == PCMDIR_PLAY)? &csa->pch : &csa->rch;
+
+ ch->parent = csa;
+ ch->channel = c;
+ ch->buffer = b;
+ ch->buffer->bufsize = CS461x_BUFFSIZE;
+ if (chn_allocbuf(ch->buffer, csa->parent_dmat) == -1) return NULL;
+ return ch;
+}
+
+static int
+csachan_setdir(kobj_t obj, void *data, int dir)
+{
+ struct csa_chinfo *ch = data;
+ struct csa_info *csa = ch->parent;
+ csa_res *resp;
+
+ resp = &csa->res;
+
+ if (dir == PCMDIR_PLAY)
+ csa_writemem(resp, BA1_PBA, vtophys(ch->buffer->buf));
+ else
+ csa_writemem(resp, BA1_CBA, vtophys(ch->buffer->buf));
+ ch->dir = dir;
+ return 0;
+}
+
+static int
+csachan_setformat(kobj_t obj, void *data, u_int32_t format)
+{
+ struct csa_chinfo *ch = data;
+ struct csa_info *csa = ch->parent;
+ u_long pdtc;
+ csa_res *resp;
+
+ resp = &csa->res;
+
+ if (ch->dir == PCMDIR_REC)
+ csa_writemem(resp, BA1_CIE, (csa_readmem(resp, BA1_CIE) & ~0x0000003f) | 0x00000001);
+ else {
+ csa->pfie = csa_readmem(resp, BA1_PFIE) & ~0x0000f03f;
+ if (format & AFMT_U8 || format & AFMT_U16_LE || format & AFMT_U16_BE)
+ csa->pfie |= 0x8000;
+ if (format & AFMT_S16_BE || format & AFMT_U16_BE)
+ csa->pfie |= 0x4000;
+ if (!(format & AFMT_STEREO))
+ csa->pfie |= 0x2000;
+ if (format & AFMT_U8 || format & AFMT_S8)
+ csa->pfie |= 0x1000;
+ csa_writemem(resp, BA1_PFIE, csa->pfie);
+ pdtc = csa_readmem(resp, BA1_PDTC) & ~0x000003ff;
+ if ((format & AFMT_S16_BE || format & AFMT_U16_BE || format & AFMT_S16_LE || format & AFMT_U16_LE) && (format & AFMT_STEREO))
+ pdtc |= 0x00f;
+ else if ((format & AFMT_S16_BE || format & AFMT_U16_BE || format & AFMT_S16_LE || format & AFMT_U16_LE) || (format & AFMT_STEREO))
+ pdtc |= 0x007;
+ else
+ pdtc |= 0x003;
+ csa_writemem(resp, BA1_PDTC, pdtc);
+ }
+ ch->fmt = format;
+ return 0;
+}
+
+static int
+csachan_setspeed(kobj_t obj, void *data, u_int32_t speed)
+{
+ struct csa_chinfo *ch = data;
+ struct csa_info *csa = ch->parent;
+ csa_res *resp;
+
+ resp = &csa->res;
+
+ if (ch->dir == PCMDIR_PLAY)
+ csa_setplaysamplerate(resp, speed);
+ else if (ch->dir == PCMDIR_REC)
+ csa_setcapturesamplerate(resp, speed);
+
+ /* rec/play speeds locked together - should indicate in flags */
+#if 0
+ if (ch->direction == PCMDIR_PLAY) d->rec[0].speed = speed;
+ else d->play[0].speed = speed;
+#endif
+ return speed; /* XXX calc real speed */
+}
+
static int
-csachan_getptr(void *data)
+csachan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
+{
+#if notdef
+ return blocksize;
+#else
+ struct csa_chinfo *ch = data;
+ return ch->buffer->bufsize / 2;
+#endif /* notdef */
+}
+
+static int
+csachan_trigger(kobj_t obj, void *data, int go)
+{
+ struct csa_chinfo *ch = data;
+ struct csa_info *csa = ch->parent;
+
+ if (go == PCMTRIG_EMLDMAWR || go == PCMTRIG_EMLDMARD)
+ return 0;
+
+ if (ch->dir == PCMDIR_PLAY) {
+ if (go == PCMTRIG_START)
+ csa_startplaydma(csa);
+ else
+ csa_stopplaydma(csa);
+ } else {
+ if (go == PCMTRIG_START)
+ csa_startcapturedma(csa);
+ else
+ csa_stopcapturedma(csa);
+ }
+ return 0;
+}
+
+static int
+csachan_getptr(kobj_t obj, void *data)
{
struct csa_chinfo *ch = data;
struct csa_info *csa = ch->parent;
@@ -662,12 +661,26 @@ csachan_getptr(void *data)
}
static pcmchan_caps *
-csachan_getcaps(void *data)
+csachan_getcaps(kobj_t obj, void *data)
{
struct csa_chinfo *ch = data;
return (ch->dir == PCMDIR_PLAY)? &csa_playcaps : &csa_reccaps;
}
+static kobj_method_t csachan_methods[] = {
+ KOBJMETHOD(channel_init, csachan_init),
+ KOBJMETHOD(channel_setdir, csachan_setdir),
+ KOBJMETHOD(channel_setformat, csachan_setformat),
+ KOBJMETHOD(channel_setspeed, csachan_setspeed),
+ KOBJMETHOD(channel_setblocksize, csachan_setblocksize),
+ KOBJMETHOD(channel_trigger, csachan_trigger),
+ KOBJMETHOD(channel_getptr, csachan_getptr),
+ KOBJMETHOD(channel_getcaps, csachan_getcaps),
+ { 0, 0 }
+};
+CHANNEL_DECLARE(csachan);
+
+/* -------------------------------------------------------------------- */
/* The interrupt handler */
static void
csa_intr (void *p)
@@ -833,12 +846,12 @@ pcmcsa_attach(device_t dev)
csa_releaseres(csa, dev);
return (ENXIO);
}
- codec = ac97_create(dev, csa, NULL, csa_rdcd, csa_wrcd);
+ codec = AC97_CREATE(dev, csa, csa_ac97);
if (codec == NULL) {
csa_releaseres(csa, dev);
return (ENXIO);
}
- if (mixer_init(dev, &ac97_mixer, codec) == -1) {
+ if (mixer_init(dev, ac97_getmixerclass(), codec) == -1) {
ac97_destroy(codec);
csa_releaseres(csa, dev);
return (ENXIO);
@@ -860,8 +873,8 @@ pcmcsa_attach(device_t dev)
csa_releaseres(csa, dev);
return (ENXIO);
}
- pcm_addchan(dev, PCMDIR_REC, &csa_chantemplate, csa);
- pcm_addchan(dev, PCMDIR_PLAY, &csa_chantemplate, csa);
+ pcm_addchan(dev, PCMDIR_REC, &csachan_class, csa);
+ pcm_addchan(dev, PCMDIR_PLAY, &csachan_class, csa);
pcm_setstatus(dev, status);
return (0);
@@ -883,28 +896,6 @@ pcmcsa_detach(device_t dev)
return 0;
}
-/* ac97 codec */
-
-static u_int32_t
-csa_rdcd(void *devinfo, int regno)
-{
- u_int32_t data;
- struct csa_info *csa = (struct csa_info *)devinfo;
-
- if (csa_readcodec(&csa->res, regno + BA0_AC97_RESET, &data))
- data = 0;
-
- return data;
-}
-
-static void
-csa_wrcd(void *devinfo, int regno, u_int32_t data)
-{
- struct csa_info *csa = (struct csa_info *)devinfo;
-
- csa_writecodec(&csa->res, regno + BA0_AC97_RESET, data);
-}
-
static device_method_t pcmcsa_methods[] = {
/* Device interface */
DEVMETHOD(device_probe , pcmcsa_probe ),
diff --git a/sys/dev/sound/pci/ds1.c b/sys/dev/sound/pci/ds1.c
index bf2c79a..c215b5a 100644
--- a/sys/dev/sound/pci/ds1.c
+++ b/sys/dev/sound/pci/ds1.c
@@ -130,7 +130,6 @@ struct {
char *name;
u_int32_t *mcode;
} ds_devs[] = {
-/* Beware, things know the indexes here */
{0x00041073, 0, "Yamaha DS-1 (YMF724)", CntrlInst},
{0x000d1073, 0, "Yamaha DS-1E (YMF724F)", CntrlInst1E},
{0x00051073, 0, "Yamaha DS-1? (YMF734)", CntrlInst},
@@ -139,10 +138,10 @@ struct {
{0x00061073, 0, "Yamaha DS-1? (YMF738_TEG)", CntrlInst},
{0x000a1073, 0x00041073, "Yamaha DS-1 (YMF740)", CntrlInst},
{0x000a1073, 0x000a1073, "Yamaha DS-1 (YMF740B)", CntrlInst},
-/*8*/ {0x000a1073, 0x53328086, "Yamaha DS-1 (YMF740I)", CntrlInst},
+ {0x000a1073, 0x53328086, "Yamaha DS-1 (YMF740I)", CntrlInst},
{0x000a1073, 0, "Yamaha DS-1 (YMF740?)", CntrlInst},
{0x000c1073, 0, "Yamaha DS-1E (YMF740C)", CntrlInst1E},
-/*11*/ {0x00101073, 0, "Yamaha DS-1E (YMF744)", CntrlInst1E},
+ {0x00101073, 0, "Yamaha DS-1E (YMF744)", CntrlInst1E},
{0x00121073, 0, "Yamaha DS-1E (YMF754)", CntrlInst1E},
{0, 0, NULL, NULL}
};
@@ -153,27 +152,6 @@ struct {
* prototypes
*/
-/* channel interface */
-static void *ds1pchan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir);
-static int ds1pchan_setformat(void *data, u_int32_t format);
-static int ds1pchan_setspeed(void *data, u_int32_t speed);
-static int ds1pchan_setblocksize(void *data, u_int32_t blocksize);
-static int ds1pchan_trigger(void *data, int go);
-static int ds1pchan_getptr(void *data);
-static pcmchan_caps *ds1pchan_getcaps(void *data);
-
-static void *ds1rchan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir);
-static int ds1rchan_setformat(void *data, u_int32_t format);
-static int ds1rchan_setspeed(void *data, u_int32_t speed);
-static int ds1rchan_setblocksize(void *data, u_int32_t blocksize);
-static int ds1rchan_trigger(void *data, int go);
-static int ds1rchan_getptr(void *data);
-static pcmchan_caps *ds1rchan_getcaps(void *data);
-
-/* talk to the codec - called from ac97.c */
-static u_int32_t ds_rdcd(void *, int);
-static void ds_wrcd(void *, int, u_int32_t);
-
/* stuff */
static int ds_init(struct sc_info *);
static void ds_intr(void *);
@@ -206,44 +184,6 @@ static u_int32_t ds_playfmt[] = {
};
static pcmchan_caps ds_playcaps = {4000, 96000, ds_playfmt, 0};
-static pcm_channel ds_pchantemplate = {
- ds1pchan_init,
- NULL, /* setdir */
- ds1pchan_setformat,
- ds1pchan_setspeed,
- ds1pchan_setblocksize,
- ds1pchan_trigger,
- ds1pchan_getptr,
- ds1pchan_getcaps,
- NULL, /* free */
- NULL, /* nop1 */
- NULL, /* nop2 */
- NULL, /* nop3 */
- NULL, /* nop4 */
- NULL, /* nop5 */
- NULL, /* nop6 */
- NULL, /* nop7 */
-};
-
-static pcm_channel ds_rchantemplate = {
- ds1rchan_init,
- NULL, /* setdir */
- ds1rchan_setformat,
- ds1rchan_setspeed,
- ds1rchan_setblocksize,
- ds1rchan_trigger,
- ds1rchan_getptr,
- ds1rchan_getcaps,
- NULL, /* free */
- NULL, /* nop1 */
- NULL, /* nop2 */
- NULL, /* nop3 */
- NULL, /* nop4 */
- NULL, /* nop5 */
- NULL, /* nop6 */
- NULL, /* nop7 */
-};
-
/* -------------------------------------------------------------------- */
/* Hardware */
static u_int32_t
@@ -284,6 +224,7 @@ wrl(struct sc_info *sc, u_int32_t *ptr, u_int32_t val)
bus_space_barrier(sc->st, sc->sh, 0, 0, BUS_SPACE_BARRIER_WRITE);
}
+/* -------------------------------------------------------------------- */
/* ac97 codec */
static int
ds_cdbusy(struct sc_info *sc, int sec)
@@ -301,7 +242,7 @@ ds_cdbusy(struct sc_info *sc, int sec)
}
static u_int32_t
-ds_initcd(void *devinfo)
+ds_initcd(kobj_t obj, void *devinfo)
{
struct sc_info *sc = (struct sc_info *)devinfo;
u_int32_t x;
@@ -326,8 +267,8 @@ ds_initcd(void *devinfo)
return ds_cdbusy(sc, 0)? 0 : 1;
}
-static u_int32_t
-ds_rdcd(void *devinfo, int regno)
+static int
+ds_rdcd(kobj_t obj, void *devinfo, int regno)
{
struct sc_info *sc = (struct sc_info *)devinfo;
int sec, cid, i;
@@ -353,8 +294,8 @@ ds_rdcd(void *devinfo, int regno)
return ds_rd(sc, reg, 2);
}
-static void
-ds_wrcd(void *devinfo, int regno, u_int32_t data)
+static int
+ds_wrcd(kobj_t obj, void *devinfo, int regno, u_int32_t data)
{
struct sc_info *sc = (struct sc_info *)devinfo;
int sec, cid;
@@ -364,16 +305,26 @@ ds_wrcd(void *devinfo, int regno, u_int32_t data)
regno &= 0xff;
cid = sec? (sc->cd2id << 8) : 0;
if (sec && cid == 0)
- return;
+ return ENXIO;
cmd = YDSXG_AC97WRITECMD | cid | regno;
cmd <<= 16;
cmd |= data;
ds_wr(sc, YDSXGR_AC97CMDDATA, cmd, 4);
- ds_cdbusy(sc, sec);
+ return ds_cdbusy(sc, sec);
}
+static kobj_method_t ds_ac97_methods[] = {
+ KOBJMETHOD(ac97_init, ds_initcd),
+ KOBJMETHOD(ac97_read, ds_rdcd),
+ KOBJMETHOD(ac97_write, ds_wrcd),
+ { 0, 0 }
+};
+AC97_DECLARE(ds_ac97);
+
+/* -------------------------------------------------------------------- */
+
static void
ds_enadsp(struct sc_info *sc, int on)
{
@@ -517,9 +468,10 @@ ds_setuprch(struct sc_rchinfo *ch)
ds_wr(sc, pri? YDSXGR_ADCSLOTSR : YDSXGR_RECSLOTSR, y, 4);
}
+/* -------------------------------------------------------------------- */
/* play channel interface */
static void *
-ds1pchan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir)
+ds1pchan_init(kobj_t obj, void *devinfo, snd_dbuf *b, pcm_channel *c, int dir)
{
struct sc_info *sc = devinfo;
struct sc_pchinfo *ch;
@@ -548,7 +500,7 @@ ds1pchan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir)
}
static int
-ds1pchan_setformat(void *data, u_int32_t format)
+ds1pchan_setformat(kobj_t obj, void *data, u_int32_t format)
{
struct sc_pchinfo *ch = data;
@@ -558,7 +510,7 @@ ds1pchan_setformat(void *data, u_int32_t format)
}
static int
-ds1pchan_setspeed(void *data, u_int32_t speed)
+ds1pchan_setspeed(kobj_t obj, void *data, u_int32_t speed)
{
struct sc_pchinfo *ch = data;
@@ -568,14 +520,14 @@ ds1pchan_setspeed(void *data, u_int32_t speed)
}
static int
-ds1pchan_setblocksize(void *data, u_int32_t blocksize)
+ds1pchan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
{
return blocksize;
}
/* semantic note: must start at beginning of buffer */
static int
-ds1pchan_trigger(void *data, int go)
+ds1pchan_trigger(kobj_t obj, void *data, int go)
{
struct sc_pchinfo *ch = data;
struct sc_info *sc = ch->parent;
@@ -601,7 +553,7 @@ ds1pchan_trigger(void *data, int go)
}
static int
-ds1pchan_getptr(void *data)
+ds1pchan_getptr(kobj_t obj, void *data)
{
struct sc_pchinfo *ch = data;
struct sc_info *sc = ch->parent;
@@ -620,14 +572,27 @@ ds1pchan_getptr(void *data)
}
static pcmchan_caps *
-ds1pchan_getcaps(void *data)
+ds1pchan_getcaps(kobj_t obj, void *data)
{
return &ds_playcaps;
}
+static kobj_method_t ds1pchan_methods[] = {
+ KOBJMETHOD(channel_init, ds1pchan_init),
+ KOBJMETHOD(channel_setformat, ds1pchan_setformat),
+ KOBJMETHOD(channel_setspeed, ds1pchan_setspeed),
+ KOBJMETHOD(channel_setblocksize, ds1pchan_setblocksize),
+ KOBJMETHOD(channel_trigger, ds1pchan_trigger),
+ KOBJMETHOD(channel_getptr, ds1pchan_getptr),
+ KOBJMETHOD(channel_getcaps, ds1pchan_getcaps),
+ { 0, 0 }
+};
+CHANNEL_DECLARE(ds1pchan);
+
+/* -------------------------------------------------------------------- */
/* record channel interface */
static void *
-ds1rchan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir)
+ds1rchan_init(kobj_t obj, void *devinfo, snd_dbuf *b, pcm_channel *c, int dir)
{
struct sc_info *sc = devinfo;
struct sc_rchinfo *ch;
@@ -653,7 +618,7 @@ ds1rchan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir)
}
static int
-ds1rchan_setformat(void *data, u_int32_t format)
+ds1rchan_setformat(kobj_t obj, void *data, u_int32_t format)
{
struct sc_rchinfo *ch = data;
@@ -663,7 +628,7 @@ ds1rchan_setformat(void *data, u_int32_t format)
}
static int
-ds1rchan_setspeed(void *data, u_int32_t speed)
+ds1rchan_setspeed(kobj_t obj, void *data, u_int32_t speed)
{
struct sc_rchinfo *ch = data;
@@ -673,14 +638,14 @@ ds1rchan_setspeed(void *data, u_int32_t speed)
}
static int
-ds1rchan_setblocksize(void *data, u_int32_t blocksize)
+ds1rchan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
{
return blocksize;
}
/* semantic note: must start at beginning of buffer */
static int
-ds1rchan_trigger(void *data, int go)
+ds1rchan_trigger(kobj_t obj, void *data, int go)
{
struct sc_rchinfo *ch = data;
struct sc_info *sc = ch->parent;
@@ -706,7 +671,7 @@ ds1rchan_trigger(void *data, int go)
}
static int
-ds1rchan_getptr(void *data)
+ds1rchan_getptr(kobj_t obj, void *data)
{
struct sc_rchinfo *ch = data;
struct sc_info *sc = ch->parent;
@@ -715,11 +680,24 @@ ds1rchan_getptr(void *data)
}
static pcmchan_caps *
-ds1rchan_getcaps(void *data)
+ds1rchan_getcaps(kobj_t obj, void *data)
{
return &ds_reccaps;
}
+static kobj_method_t ds1rchan_methods[] = {
+ KOBJMETHOD(channel_init, ds1rchan_init),
+ KOBJMETHOD(channel_setformat, ds1rchan_setformat),
+ KOBJMETHOD(channel_setspeed, ds1rchan_setspeed),
+ KOBJMETHOD(channel_setblocksize, ds1rchan_setblocksize),
+ KOBJMETHOD(channel_trigger, ds1rchan_trigger),
+ KOBJMETHOD(channel_getptr, ds1rchan_getptr),
+ KOBJMETHOD(channel_getcaps, ds1rchan_getcaps),
+ { 0, 0 }
+};
+CHANNEL_DECLARE(ds1rchan);
+
+/* -------------------------------------------------------------------- */
/* The interrupt handler */
static void
ds_intr(void *p)
@@ -970,10 +948,10 @@ ds_pci_attach(device_t dev)
goto bad;
}
- codec = ac97_create(dev, sc, ds_initcd, ds_rdcd, ds_wrcd);
+ codec = AC97_CREATE(dev, sc, ds_ac97);
if (codec == NULL)
goto bad;
- mixer_init(dev, &ac97_mixer, codec);
+ mixer_init(dev, ac97_getmixerclass(), codec);
sc->irqid = 0;
sc->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->irqid,
@@ -990,9 +968,9 @@ ds_pci_attach(device_t dev)
if (pcm_register(dev, sc, DS1_CHANS, 2))
goto bad;
for (i = 0; i < DS1_CHANS; i++)
- pcm_addchan(dev, PCMDIR_PLAY, &ds_pchantemplate, sc);
+ pcm_addchan(dev, PCMDIR_PLAY, &ds1pchan_class, sc);
for (i = 0; i < 2; i++)
- pcm_addchan(dev, PCMDIR_REC, &ds_rchantemplate, sc);
+ pcm_addchan(dev, PCMDIR_REC, &ds1rchan_class, sc);
pcm_setstatus(dev, status);
return 0;
diff --git a/sys/dev/sound/pci/emu10k1.c b/sys/dev/sound/pci/emu10k1.c
index 98d55c7..2e46ede 100644
--- a/sys/dev/sound/pci/emu10k1.c
+++ b/sys/dev/sound/pci/emu10k1.c
@@ -111,31 +111,6 @@ struct sc_info {
* prototypes
*/
-/* channel interface */
-static void *emupchan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir);
-static int emupchan_free(void *data);
-static int emupchan_setdir(void *data, int dir);
-static int emupchan_setformat(void *data, u_int32_t format);
-static int emupchan_setspeed(void *data, u_int32_t speed);
-static int emupchan_setblocksize(void *data, u_int32_t blocksize);
-static int emupchan_trigger(void *data, int go);
-static int emupchan_getptr(void *data);
-static pcmchan_caps *emupchan_getcaps(void *data);
-
-/* channel interface */
-static void *emurchan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir);
-static int emurchan_setdir(void *data, int dir);
-static int emurchan_setformat(void *data, u_int32_t format);
-static int emurchan_setspeed(void *data, u_int32_t speed);
-static int emurchan_setblocksize(void *data, u_int32_t blocksize);
-static int emurchan_trigger(void *data, int go);
-static int emurchan_getptr(void *data);
-static pcmchan_caps *emurchan_getcaps(void *data);
-
-/* talk to the codec - called from ac97.c */
-static u_int32_t emu_rdcd(void *, int);
-static void emu_wrcd(void *, int, u_int32_t);
-
/* stuff */
static int emu_init(struct sc_info *);
static void emu_intr(void *);
@@ -183,45 +158,7 @@ static u_int32_t emu_pfmt[] = {
0
};
-static pcmchan_caps emu_playcaps = {4000, 48000, emu_pfmt, 0};
-
-static pcm_channel emu_chantemplate = {
- emupchan_init,
- emupchan_setdir,
- emupchan_setformat,
- emupchan_setspeed,
- emupchan_setblocksize,
- emupchan_trigger,
- emupchan_getptr,
- emupchan_getcaps,
- emupchan_free, /* free */
- NULL, /* nop1 */
- NULL, /* nop2 */
- NULL, /* nop3 */
- NULL, /* nop4 */
- NULL, /* nop5 */
- NULL, /* nop6 */
- NULL, /* nop7 */
-};
-
-static pcm_channel emur_chantemplate = {
- emurchan_init,
- emurchan_setdir,
- emurchan_setformat,
- emurchan_setspeed,
- emurchan_setblocksize,
- emurchan_trigger,
- emurchan_getptr,
- emurchan_getcaps,
- NULL, /* free */
- NULL, /* nop1 */
- NULL, /* nop2 */
- NULL, /* nop3 */
- NULL, /* nop4 */
- NULL, /* nop5 */
- NULL, /* nop6 */
- NULL, /* nop7 */
-};
+static pcmchan_caps emu_playcaps = {48000, 48000, emu_pfmt, 0};
static int adcspeed[8] = {48000, 44100, 32000, 24000, 22050, 16000, 11025, 8000};
@@ -300,9 +237,11 @@ emu_wrefx(struct sc_info *sc, unsigned int pc, unsigned int data)
emu_wrptr(sc, 0, MICROCODEBASE + pc, data);
}
+/* -------------------------------------------------------------------- */
/* ac97 codec */
-static u_int32_t
-emu_rdcd(void *devinfo, int regno)
+
+static int
+emu_rdcd(kobj_t obj, void *devinfo, int regno)
{
struct sc_info *sc = (struct sc_info *)devinfo;
@@ -310,15 +249,25 @@ emu_rdcd(void *devinfo, int regno)
return emu_rd(sc, AC97DATA, 2);
}
-static void
-emu_wrcd(void *devinfo, int regno, u_int32_t data)
+static int
+emu_wrcd(kobj_t obj, void *devinfo, int regno, u_int32_t data)
{
struct sc_info *sc = (struct sc_info *)devinfo;
emu_wr(sc, AC97ADDRESS, regno, 1);
emu_wr(sc, AC97DATA, data, 2);
+ return 0;
}
+static kobj_method_t emu_ac97_methods[] = {
+ KOBJMETHOD(ac97_read, emu_rdcd),
+ KOBJMETHOD(ac97_write, emu_wrcd),
+ { 0, 0 }
+};
+AC97_DECLARE(emu_ac97);
+
+/* -------------------------------------------------------------------- */
+
#if 0
/* playback channel interrupts */
static u_int32_t
@@ -671,8 +620,8 @@ emu_vdump(struct sc_info *sc, struct emu_voice *v)
#endif
/* channel interface */
-void *
-emupchan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir)
+static void *
+emupchan_init(kobj_t obj, void *devinfo, snd_dbuf *b, pcm_channel *c, int dir)
{
struct sc_info *sc = devinfo;
struct sc_pchinfo *ch;
@@ -691,7 +640,7 @@ emupchan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir)
}
static int
-emupchan_free(void *data)
+emupchan_free(kobj_t obj, void *data)
{
struct sc_pchinfo *ch = data;
struct sc_info *sc = ch->parent;
@@ -700,13 +649,7 @@ emupchan_free(void *data)
}
static int
-emupchan_setdir(void *data, int dir)
-{
- return 0;
-}
-
-static int
-emupchan_setformat(void *data, u_int32_t format)
+emupchan_setformat(kobj_t obj, void *data, u_int32_t format)
{
struct sc_pchinfo *ch = data;
@@ -715,7 +658,7 @@ emupchan_setformat(void *data, u_int32_t format)
}
static int
-emupchan_setspeed(void *data, u_int32_t speed)
+emupchan_setspeed(kobj_t obj, void *data, u_int32_t speed)
{
struct sc_pchinfo *ch = data;
@@ -724,13 +667,13 @@ emupchan_setspeed(void *data, u_int32_t speed)
}
static int
-emupchan_setblocksize(void *data, u_int32_t blocksize)
+emupchan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
{
return blocksize;
}
static int
-emupchan_trigger(void *data, int go)
+emupchan_trigger(kobj_t obj, void *data, int go)
{
struct sc_pchinfo *ch = data;
struct sc_info *sc = ch->parent;
@@ -757,7 +700,7 @@ emupchan_trigger(void *data, int go)
}
static int
-emupchan_getptr(void *data)
+emupchan_getptr(kobj_t obj, void *data)
{
struct sc_pchinfo *ch = data;
struct sc_info *sc = ch->parent;
@@ -766,14 +709,27 @@ emupchan_getptr(void *data)
}
static pcmchan_caps *
-emupchan_getcaps(void *data)
+emupchan_getcaps(kobj_t obj, void *data)
{
return &emu_playcaps;
}
+static kobj_method_t emupchan_methods[] = {
+ KOBJMETHOD(channel_init, emupchan_init),
+ KOBJMETHOD(channel_free, emupchan_free),
+ KOBJMETHOD(channel_setformat, emupchan_setformat),
+ KOBJMETHOD(channel_setspeed, emupchan_setspeed),
+ KOBJMETHOD(channel_setblocksize, emupchan_setblocksize),
+ KOBJMETHOD(channel_trigger, emupchan_trigger),
+ KOBJMETHOD(channel_getptr, emupchan_getptr),
+ KOBJMETHOD(channel_getcaps, emupchan_getcaps),
+ { 0, 0 }
+};
+CHANNEL_DECLARE(emupchan);
+
/* channel interface */
static void *
-emurchan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir)
+emurchan_init(kobj_t obj, void *devinfo, snd_dbuf *b, pcm_channel *c, int dir)
{
struct sc_info *sc = devinfo;
struct sc_rchinfo *ch;
@@ -823,13 +779,7 @@ emurchan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir)
}
static int
-emurchan_setdir(void *data, int dir)
-{
- return 0;
-}
-
-static int
-emurchan_setformat(void *data, u_int32_t format)
+emurchan_setformat(kobj_t obj, void *data, u_int32_t format)
{
struct sc_rchinfo *ch = data;
@@ -838,7 +788,7 @@ emurchan_setformat(void *data, u_int32_t format)
}
static int
-emurchan_setspeed(void *data, u_int32_t speed)
+emurchan_setspeed(kobj_t obj, void *data, u_int32_t speed)
{
struct sc_rchinfo *ch = data;
@@ -853,14 +803,14 @@ emurchan_setspeed(void *data, u_int32_t speed)
}
static int
-emurchan_setblocksize(void *data, u_int32_t blocksize)
+emurchan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
{
return blocksize;
}
/* semantic note: must start at beginning of buffer */
static int
-emurchan_trigger(void *data, int go)
+emurchan_trigger(kobj_t obj, void *data, int go)
{
struct sc_rchinfo *ch = data;
struct sc_info *sc = ch->parent;
@@ -903,7 +853,7 @@ emurchan_trigger(void *data, int go)
}
static int
-emurchan_getptr(void *data)
+emurchan_getptr(kobj_t obj, void *data)
{
struct sc_rchinfo *ch = data;
struct sc_info *sc = ch->parent;
@@ -912,7 +862,7 @@ emurchan_getptr(void *data)
}
static pcmchan_caps *
-emurchan_getcaps(void *data)
+emurchan_getcaps(kobj_t obj, void *data)
{
struct sc_rchinfo *ch = data;
@@ -979,6 +929,18 @@ emu_intr(void *p)
}
}
+static kobj_method_t emurchan_methods[] = {
+ KOBJMETHOD(channel_init, emurchan_init),
+ KOBJMETHOD(channel_setformat, emurchan_setformat),
+ KOBJMETHOD(channel_setspeed, emurchan_setspeed),
+ KOBJMETHOD(channel_setblocksize, emurchan_setblocksize),
+ KOBJMETHOD(channel_trigger, emurchan_trigger),
+ KOBJMETHOD(channel_getptr, emurchan_getptr),
+ KOBJMETHOD(channel_getcaps, emurchan_getcaps),
+ { 0, 0 }
+};
+CHANNEL_DECLARE(emurchan);
+
/* -------------------------------------------------------------------- */
static void
@@ -1468,9 +1430,9 @@ emu_pci_attach(device_t dev)
goto bad;
}
- codec = ac97_create(dev, sc, NULL, emu_rdcd, emu_wrcd);
+ codec = AC97_CREATE(dev, sc, emu_ac97);
if (codec == NULL) goto bad;
- if (mixer_init(dev, &ac97_mixer, codec) == -1) goto bad;
+ if (mixer_init(dev, ac97_getmixerclass(), codec) == -1) goto bad;
sc->irqid = 0;
sc->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->irqid,
@@ -1487,9 +1449,9 @@ emu_pci_attach(device_t dev)
if (pcm_register(dev, sc, EMU_CHANS, 3)) goto bad;
for (i = 0; i < EMU_CHANS; i++)
- pcm_addchan(dev, PCMDIR_PLAY, &emu_chantemplate, sc);
+ pcm_addchan(dev, PCMDIR_PLAY, &emupchan_class, sc);
for (i = 0; i < 3; i++)
- pcm_addchan(dev, PCMDIR_REC, &emur_chantemplate, sc);
+ pcm_addchan(dev, PCMDIR_REC, &emurchan_class, sc);
pcm_setstatus(dev, status);
diff --git a/sys/dev/sound/pci/es137x.c b/sys/dev/sound/pci/es137x.c
index 2b736c2..15779e8 100644
--- a/sys/dev/sound/pci/es137x.c
+++ b/sys/dev/sound/pci/es137x.c
@@ -59,6 +59,8 @@
#include <sys/sysctl.h>
+#include "mixer_if.h"
+
static int debug = 0;
SYSCTL_INT(_debug, OID_AUTO, es_debug, CTLFLAG_RW, &debug, 0, "");
@@ -105,8 +107,6 @@ struct es_info {
/* prototypes */
static void es_intr(void *);
-static void es1371_wrcodec(void *, int, u_int32_t);
-static u_int32_t es1371_rdcodec(void *, int);
static u_int es1371_wait_src_ready(struct es_info *);
static void es1371_src_write(struct es_info *, u_short, unsigned short);
static u_int es1371_adc_rate(struct es_info *, u_int, int);
@@ -115,17 +115,6 @@ static int es1371_init(struct es_info *es, int);
static int es1370_init(struct es_info *);
static int es1370_wrcodec(struct es_info *, u_char, u_char);
-/* channel interface */
-static void *eschan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir);
-static int eschan_setdir(void *data, int dir);
-static int eschan_setformat(void *data, u_int32_t format);
-static int eschan1370_setspeed(void *data, u_int32_t speed);
-static int eschan1371_setspeed(void *data, u_int32_t speed);
-static int eschan_setblocksize(void *data, u_int32_t blocksize);
-static int eschan_trigger(void *data, int go);
-static int eschan_getptr(void *data);
-static pcmchan_caps *eschan_getcaps(void *data);
-
static u_int32_t es_playfmt[] = {
AFMT_U8,
AFMT_STEREO | AFMT_U8,
@@ -144,61 +133,6 @@ static u_int32_t es_recfmt[] = {
};
static pcmchan_caps es_reccaps = {4000, 48000, es_recfmt, 0};
-static pcm_channel es1370_chantemplate = {
- eschan_init,
- eschan_setdir,
- eschan_setformat,
- eschan1370_setspeed,
- eschan_setblocksize,
- eschan_trigger,
- eschan_getptr,
- eschan_getcaps,
- NULL, /* free */
- NULL, /* nop1 */
- NULL, /* nop2 */
- NULL, /* nop3 */
- NULL, /* nop4 */
- NULL, /* nop5 */
- NULL, /* nop6 */
- NULL, /* nop7 */
-};
-
-static pcm_channel es1371_chantemplate = {
- eschan_init,
- eschan_setdir,
- eschan_setformat,
- eschan1371_setspeed,
- eschan_setblocksize,
- eschan_trigger,
- eschan_getptr,
- eschan_getcaps,
- NULL, /* free */
- NULL, /* nop1 */
- NULL, /* nop2 */
- NULL, /* nop3 */
- NULL, /* nop4 */
- NULL, /* nop5 */
- NULL, /* nop6 */
- NULL, /* nop7 */
-};
-
-/* -------------------------------------------------------------------- */
-
-/* The es1370 mixer interface */
-
-static int es1370_mixinit(snd_mixer *m);
-static int es1370_mixset(snd_mixer *m, unsigned dev, unsigned left, unsigned right);
-static int es1370_mixsetrecsrc(snd_mixer *m, u_int32_t src);
-
-static snd_mixer es1370_mixer = {
- "AudioPCI 1370 mixer",
- es1370_mixinit,
- NULL,
- NULL,
- es1370_mixset,
- es1370_mixsetrecsrc,
-};
-
static const struct {
unsigned volidx:4;
unsigned left:4;
@@ -219,6 +153,9 @@ static const struct {
[SOUND_MIXER_OGAIN] = { 9, 0xf, 0x0, 0, 0x0000, 1 }
};
+/* -------------------------------------------------------------------- */
+/* The es1370 mixer interface */
+
static int
es1370_mixinit(snd_mixer *m)
{
@@ -276,6 +213,16 @@ es1370_mixsetrecsrc(snd_mixer *m, u_int32_t src)
return src;
}
+static kobj_method_t es1370_mixer_methods[] = {
+ KOBJMETHOD(mixer_init, es1370_mixinit),
+ KOBJMETHOD(mixer_set, es1370_mixset),
+ KOBJMETHOD(mixer_setrecsrc, es1370_mixsetrecsrc),
+ { 0, 0 }
+};
+MIXER_DECLARE(es1370_mixer);
+
+/* -------------------------------------------------------------------- */
+
static int
es1370_wrcodec(struct es_info *es, u_char i, u_char data)
{
@@ -298,7 +245,7 @@ es1370_wrcodec(struct es_info *es, u_char i, u_char data)
/* channel interface */
static void *
-eschan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir)
+eschan_init(kobj_t obj, void *devinfo, snd_dbuf *b, pcm_channel *c, int dir)
{
struct es_info *es = devinfo;
struct es_chinfo *ch = (dir == PCMDIR_PLAY)? &es->pch : &es->rch;
@@ -313,7 +260,7 @@ eschan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir)
}
static int
-eschan_setdir(void *data, int dir)
+eschan_setdir(kobj_t obj, void *data, int dir)
{
struct es_chinfo *ch = data;
struct es_info *es = ch->parent;
@@ -338,7 +285,7 @@ eschan_setdir(void *data, int dir)
}
static int
-eschan_setformat(void *data, u_int32_t format)
+eschan_setformat(kobj_t obj, void *data, u_int32_t format)
{
struct es_chinfo *ch = data;
struct es_info *es = ch->parent;
@@ -358,7 +305,7 @@ eschan_setformat(void *data, u_int32_t format)
}
static int
-eschan1370_setspeed(void *data, u_int32_t speed)
+eschan1370_setspeed(kobj_t obj, void *data, u_int32_t speed)
{
struct es_chinfo *ch = data;
struct es_info *es = ch->parent;
@@ -370,8 +317,8 @@ eschan1370_setspeed(void *data, u_int32_t speed)
return speed; /* XXX calc real speed */
}
-int
-eschan1371_setspeed(void *data, u_int32_t speed)
+static int
+eschan1371_setspeed(kobj_t obj, void *data, u_int32_t speed)
{
struct es_chinfo *ch = data;
struct es_info *es = ch->parent;
@@ -384,13 +331,13 @@ eschan1371_setspeed(void *data, u_int32_t speed)
}
static int
-eschan_setblocksize(void *data, u_int32_t blocksize)
+eschan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
{
return blocksize;
}
static int
-eschan_trigger(void *data, int go)
+eschan_trigger(kobj_t obj, void *data, int go)
{
struct es_chinfo *ch = data;
struct es_info *es = ch->parent;
@@ -442,7 +389,7 @@ eschan_trigger(void *data, int go)
}
static int
-eschan_getptr(void *data)
+eschan_getptr(kobj_t obj, void *data)
{
struct es_chinfo *ch = data;
struct es_info *es = ch->parent;
@@ -460,12 +407,39 @@ eschan_getptr(void *data)
}
static pcmchan_caps *
-eschan_getcaps(void *data)
+eschan_getcaps(kobj_t obj, void *data)
{
struct es_chinfo *ch = data;
return (ch->dir == PCMDIR_PLAY)? &es_playcaps : &es_reccaps;
}
+static kobj_method_t eschan1370_methods[] = {
+ KOBJMETHOD(channel_init, eschan_init),
+ KOBJMETHOD(channel_setdir, eschan_setdir),
+ KOBJMETHOD(channel_setformat, eschan_setformat),
+ KOBJMETHOD(channel_setspeed, eschan1370_setspeed),
+ KOBJMETHOD(channel_setblocksize, eschan_setblocksize),
+ KOBJMETHOD(channel_trigger, eschan_trigger),
+ KOBJMETHOD(channel_getptr, eschan_getptr),
+ KOBJMETHOD(channel_getcaps, eschan_getcaps),
+ { 0, 0 }
+};
+CHANNEL_DECLARE(eschan1370);
+
+static kobj_method_t eschan1371_methods[] = {
+ KOBJMETHOD(channel_init, eschan_init),
+ KOBJMETHOD(channel_setdir, eschan_setdir),
+ KOBJMETHOD(channel_setformat, eschan_setformat),
+ KOBJMETHOD(channel_setspeed, eschan1371_setspeed),
+ KOBJMETHOD(channel_setblocksize, eschan_setblocksize),
+ KOBJMETHOD(channel_trigger, eschan_trigger),
+ KOBJMETHOD(channel_getptr, eschan_getptr),
+ KOBJMETHOD(channel_getcaps, eschan_getcaps),
+ { 0, 0 }
+};
+CHANNEL_DECLARE(eschan1371);
+
+/* -------------------------------------------------------------------- */
/* The interrupt handler */
static void
es_intr(void *p)
@@ -564,8 +538,10 @@ es1371_init(struct es_info *es, int rev)
return (0);
}
-static void
-es1371_wrcodec(void *s, int addr, u_int32_t data)
+/* -------------------------------------------------------------------- */
+
+static int
+es1371_wrcd(kobj_t obj, void *s, int addr, u_int32_t data)
{
int sl;
unsigned t, x;
@@ -600,10 +576,12 @@ es1371_wrcodec(void *s, int addr, u_int32_t data)
if (debug > 2) printf("two b_s_w: 0x%x 0x%x 0x%x\n", es->sh, ES1371_REG_SMPRATE, x);
bus_space_write_4(es->st, es->sh, ES1371_REG_SMPRATE, x);
splx(sl);
+
+ return 0;
}
-static u_int32_t
-es1371_rdcodec(void *s, int addr)
+static int
+es1371_rdcd(kobj_t obj, void *s, int addr)
{
int sl;
unsigned t, x;
@@ -646,6 +624,15 @@ es1371_rdcodec(void *s, int addr)
return ((x & CODEC_PIDAT_MASK) >> CODEC_PIDAT_SHIFT);
}
+static kobj_method_t es1371_ac97_methods[] = {
+ KOBJMETHOD(ac97_read, es1371_rdcd),
+ KOBJMETHOD(ac97_write, es1371_wrcd),
+ { 0, 0 }
+};
+AC97_DECLARE(es1371_ac97);
+
+/* -------------------------------------------------------------------- */
+
static u_int
es1371_src_read(struct es_info *es, u_short reg)
{
@@ -769,7 +756,7 @@ es_pci_attach(device_t dev)
int mapped;
char status[SND_STATUSLEN];
struct ac97_info *codec = 0;
- pcm_channel *ct = NULL;
+ kobj_class_t ct = NULL;
if ((es = malloc(sizeof *es, M_DEVBUF, M_NOWAIT)) == NULL) {
device_printf(dev, "cannot allocate softc\n");
@@ -817,20 +804,20 @@ es_pci_attach(device_t dev)
device_printf(dev, "unable to initialize the card\n");
goto bad;
}
- codec = ac97_create(dev, es, NULL, es1371_rdcodec, es1371_wrcodec);
+ codec = AC97_CREATE(dev, es, es1371_ac97);
if (codec == NULL) goto bad;
/* our init routine does everything for us */
/* set to NULL; flag mixer_init not to run the ac97_init */
/* ac97_mixer.init = NULL; */
- if (mixer_init(dev, &ac97_mixer, codec) == -1) goto bad;
- ct = &es1371_chantemplate;
+ if (mixer_init(dev, ac97_getmixerclass(), codec)) goto bad;
+ ct = &eschan1371_class;
} else if (pci_get_devid(dev) == ES1370_PCI_ID) {
if (-1 == es1370_init(es)) {
device_printf(dev, "unable to initialize the card\n");
goto bad;
}
- mixer_init(dev, &es1370_mixer, es);
- ct = &es1370_chantemplate;
+ if (mixer_init(dev, &es1370_mixer_class, es)) goto bad;
+ ct = &eschan1370_class;
} else goto bad;
es->irqid = 0;
diff --git a/sys/dev/sound/pci/fm801.c b/sys/dev/sound/pci/fm801.c
index 2173c0a..a01ea8e 100644
--- a/sys/dev/sound/pci/fm801.c
+++ b/sys/dev/sound/pci/fm801.c
@@ -101,15 +101,6 @@
/* debug purposes */
#define DPRINT if(0) printf
-
-/* channel interface */
-static void *fm801ch_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir);
-static int fm801ch_setformat(void *data, u_int32_t format);
-static int fm801ch_setspeed(void *data, u_int32_t speed);
-static int fm801ch_setblocksize(void *data, u_int32_t blocksize);
-static int fm801ch_trigger(void *data, int go);
-static int fm801ch_getptr(void *data);
-static pcmchan_caps *fm801ch_getcaps(void *data);
/*
static int fm801ch_setup(pcm_channel *c);
*/
@@ -127,25 +118,6 @@ static pcmchan_caps fm801ch_caps = {
fmts, 0
};
-static pcm_channel fm801_chantemplate = {
- fm801ch_init,
- NULL, /* setdir */
- fm801ch_setformat,
- fm801ch_setspeed,
- fm801ch_setblocksize,
- fm801ch_trigger,
- fm801ch_getptr,
- fm801ch_getcaps,
- NULL, /* free */
- NULL, /* nop1 */
- NULL, /* nop2 */
- NULL, /* nop3 */
- NULL, /* nop4 */
- NULL, /* nop5 */
- NULL, /* nop6 */
- NULL, /* nop7 */
-};
-
struct fm801_info;
struct fm801_chinfo {
@@ -220,12 +192,13 @@ fm801_wr(struct fm801_info *fm801, int regno, u_int32_t data, int size)
}
}
+/* -------------------------------------------------------------------- */
/*
* ac97 codec routines
*/
#define TIMO 50
-static u_int32_t
-fm801_rdcd(void *devinfo, int regno)
+static int
+fm801_rdcd(kobj_t obj, void *devinfo, int regno)
{
struct fm801_info *fm801 = (struct fm801_info *)devinfo;
int i;
@@ -254,8 +227,8 @@ fm801_rdcd(void *devinfo, int regno)
return fm801_rd(fm801,FM_CODEC_DATA,2);
}
-static void
-fm801_wrcd(void *devinfo, int regno, u_int32_t data)
+static int
+fm801_wrcd(kobj_t obj, void *devinfo, int regno, u_int32_t data)
{
struct fm801_info *fm801 = (struct fm801_info *)devinfo;
int i;
@@ -271,7 +244,7 @@ fm801_wrcd(void *devinfo, int regno, u_int32_t data)
}
if (i >= TIMO) {
printf("fm801 wrcd: read codec busy\n");
- return;
+ return -1;
}
fm801_wr(fm801,FM_CODEC_DATA,data, 2);
@@ -284,12 +257,21 @@ fm801_wrcd(void *devinfo, int regno, u_int32_t data)
}
if (i >= TIMO) {
printf("fm801 wrcd: read codec busy\n");
- return;
+ return -1;
}
DPRINT("fm801 wrcd release reg 0x%x val 0x%x\n",regno, data);
- return;
+ return 0;
}
+static kobj_method_t fm801_ac97_methods[] = {
+ KOBJMETHOD(ac97_read, fm801_rdcd),
+ KOBJMETHOD(ac97_write, fm801_wrcd),
+ { 0, 0 }
+};
+AC97_DECLARE(fm801_ac97);
+
+/* -------------------------------------------------------------------- */
+
/*
* The interrupt handler
*/
@@ -337,179 +319,10 @@ fm801_intr(void *p)
fm801_wr(fm801, FM_INTSTATUS, intsrc & (FM_INTSTATUS_PLAY | FM_INTSTATUS_REC), 2);
}
-/*
- * Init routine is taken from an original NetBSD driver
- */
-static int
-fm801_init(struct fm801_info *fm801)
-{
- u_int32_t k1;
-
- /* reset codec */
- fm801_wr(fm801, FM_CODEC_CTL, 0x0020,2);
- DELAY(100000);
- fm801_wr(fm801, FM_CODEC_CTL, 0x0000,2);
- DELAY(100000);
-
- fm801_wr(fm801, FM_PCM_VOLUME, 0x0808,2);
- fm801_wr(fm801, FM_FM_VOLUME, 0x0808,2);
- fm801_wr(fm801, FM_I2S_VOLUME, 0x0808,2);
- fm801_wr(fm801, 0x40,0x107f,2); /* enable legacy audio */
-
- fm801_wr((void *)fm801, FM_RECORD_SOURCE, 0x0000,2);
-
- /* Unmask playback, record and mpu interrupts, mask the rest */
- k1 = fm801_rd((void *)fm801, FM_INTMASK,2);
- fm801_wr(fm801, FM_INTMASK,
- (k1 & ~(FM_INTMASK_PLAY | FM_INTMASK_REC | FM_INTMASK_MPU)) |
- FM_INTMASK_VOL,2);
- fm801_wr(fm801, FM_INTSTATUS,
- FM_INTSTATUS_PLAY | FM_INTSTATUS_REC | FM_INTSTATUS_MPU |
- FM_INTSTATUS_VOL,2);
-
- DPRINT("FM801 init Ok\n");
- return 0;
-}
-
-static int
-fm801_pci_attach(device_t dev)
-{
- u_int32_t data;
- struct ac97_info *codec = 0;
- struct fm801_info *fm801;
- int i;
- int mapped = 0;
- char status[SND_STATUSLEN];
-
- if ((fm801 = (struct fm801_info *)malloc(sizeof(*fm801),M_DEVBUF, M_NOWAIT)) == NULL) {
- device_printf(dev, "cannot allocate softc\n");
- return ENXIO;
- }
-
- bzero(fm801, sizeof(*fm801));
- fm801->type = pci_get_devid(dev);
-
- data = pci_read_config(dev, PCIR_COMMAND, 2);
- data |= (PCIM_CMD_PORTEN|PCIM_CMD_MEMEN|PCIM_CMD_BUSMASTEREN);
- pci_write_config(dev, PCIR_COMMAND, data, 2);
- data = pci_read_config(dev, PCIR_COMMAND, 2);
-
- for (i = 0; (mapped == 0) && (i < PCI_MAXMAPS_0); i++) {
- fm801->regid = PCIR_MAPS + i*4;
- fm801->regtype = SYS_RES_MEMORY;
- fm801->reg = bus_alloc_resource(dev, fm801->regtype, &fm801->regid,
- 0, ~0, 1, RF_ACTIVE);
- if(!fm801->reg)
- {
- fm801->regtype = SYS_RES_IOPORT;
- fm801->reg = bus_alloc_resource(dev, fm801->regtype, &fm801->regid,
- 0, ~0, 1, RF_ACTIVE);
- }
-
- if(fm801->reg) {
- fm801->st = rman_get_bustag(fm801->reg);
- fm801->sh = rman_get_bushandle(fm801->reg);
- mapped++;
- }
- }
-
- if (mapped == 0) {
- device_printf(dev, "unable to map register space\n");
- goto oops;
- }
-
- fm801_init(fm801);
-
- codec = ac97_create(dev, (void *)fm801, NULL, fm801_rdcd, fm801_wrcd);
- if (codec == NULL) goto oops;
-
- if (mixer_init(dev, &ac97_mixer, codec) == -1) goto oops;
-
- fm801->irqid = 0;
- fm801->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &fm801->irqid,
- 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE);
- if (!fm801->irq ||
- bus_setup_intr(dev, fm801->irq, INTR_TYPE_TTY,
- fm801_intr, fm801, &fm801->ih)) {
- device_printf(dev, "unable to map interrupt\n");
- goto oops;
- }
-
- if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0,
- /*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
- /*highaddr*/BUS_SPACE_MAXADDR,
- /*filter*/NULL, /*filterarg*/NULL,
- /*maxsize*/FM801_BUFFSIZE, /*nsegments*/1, /*maxsegz*/0x3ffff,
- /*flags*/0, &fm801->parent_dmat) != 0) {
- device_printf(dev, "unable to create dma tag\n");
- goto oops;
- }
-
- snprintf(status, 64, "at %s 0x%lx irq %ld",
- (fm801->regtype == SYS_RES_IOPORT)? "io" : "memory",
- rman_get_start(fm801->reg), rman_get_start(fm801->irq));
-
-#define FM801_MAXPLAYCH 1
- if (pcm_register(dev, fm801, FM801_MAXPLAYCH, 1)) goto oops;
- pcm_addchan(dev, PCMDIR_PLAY, &fm801_chantemplate, fm801);
- pcm_addchan(dev, PCMDIR_REC, &fm801_chantemplate, fm801);
- pcm_setstatus(dev, status);
-
- return 0;
-
-oops:
- if (codec) ac97_destroy(codec);
- if (fm801->reg) bus_release_resource(dev, fm801->regtype, fm801->regid, fm801->reg);
- if (fm801->ih) bus_teardown_intr(dev, fm801->irq, fm801->ih);
- if (fm801->irq) bus_release_resource(dev, SYS_RES_IRQ, fm801->irqid, fm801->irq);
- if (fm801->parent_dmat) bus_dma_tag_destroy(fm801->parent_dmat);
- free(fm801, M_DEVBUF);
- return ENXIO;
-}
-
-static int
-fm801_pci_detach(device_t dev)
-{
- int r;
- struct fm801_info *fm801;
-
- DPRINT("Forte Media FM801 detach\n");
-
- r = pcm_unregister(dev);
- if (r)
- return r;
-
- fm801 = pcm_getdevinfo(dev);
- bus_release_resource(dev, fm801->regtype, fm801->regid, fm801->reg);
- bus_teardown_intr(dev, fm801->irq, fm801->ih);
- bus_release_resource(dev, SYS_RES_IRQ, fm801->irqid, fm801->irq);
- bus_dma_tag_destroy(fm801->parent_dmat);
- free(fm801, M_DEVBUF);
- return 0;
-}
-
-static int
-fm801_pci_probe( device_t dev )
-{
- int id;
- if ((id = pci_get_devid(dev)) == PCI_DEVICE_FORTEMEDIA1 ) {
- device_set_desc(dev, "Forte Media FM801 Audio Controller");
- return 0;
- }
-/*
- if ((id = pci_get_devid(dev)) == PCI_DEVICE_FORTEMEDIA2 ) {
- device_set_desc(dev, "Forte Media FM801 Joystick (Not Supported)");
- return ENXIO;
- }
-*/
- return ENXIO;
-}
-
-
-
+/* -------------------------------------------------------------------- */
/* channel interface */
static void *
-fm801ch_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir)
+fm801ch_init(kobj_t obj, void *devinfo, snd_dbuf *b, pcm_channel *c, int dir)
{
struct fm801_info *fm801 = (struct fm801_info *)devinfo;
struct fm801_chinfo *ch = (dir == PCMDIR_PLAY)? &fm801->pch : &fm801->rch;
@@ -525,7 +338,7 @@ fm801ch_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir)
}
static int
-fm801ch_setformat(void *data, u_int32_t format)
+fm801ch_setformat(kobj_t obj, void *data, u_int32_t format)
{
struct fm801_chinfo *ch = data;
struct fm801_info *fm801 = ch->parent;
@@ -570,7 +383,7 @@ struct {
};
static int
-fm801ch_setspeed(void *data, u_int32_t speed)
+fm801ch_setspeed(kobj_t obj, void *data, u_int32_t speed)
{
struct fm801_chinfo *ch = data;
struct fm801_info *fm801 = ch->parent;
@@ -597,7 +410,7 @@ fm801ch_setspeed(void *data, u_int32_t speed)
}
static int
-fm801ch_setblocksize(void *data, u_int32_t blocksize)
+fm801ch_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
{
struct fm801_chinfo *ch = data;
struct fm801_info *fm801 = ch->parent;
@@ -618,7 +431,7 @@ fm801ch_setblocksize(void *data, u_int32_t blocksize)
}
static int
-fm801ch_trigger(void *data, int go)
+fm801ch_trigger(kobj_t obj, void *data, int go)
{
struct fm801_chinfo *ch = data;
struct fm801_info *fm801 = ch->parent;
@@ -678,7 +491,7 @@ fm801ch_trigger(void *data, int go)
/* Almost ALSA copy */
static int
-fm801ch_getptr(void *data)
+fm801ch_getptr(kobj_t obj, void *data)
{
struct fm801_chinfo *ch = data;
struct fm801_info *fm801 = ch->parent;
@@ -704,11 +517,193 @@ fm801ch_getptr(void *data)
}
static pcmchan_caps *
-fm801ch_getcaps(void *data)
+fm801ch_getcaps(kobj_t obj, void *data)
{
return &fm801ch_caps;
}
+static kobj_method_t fm801ch_methods[] = {
+ KOBJMETHOD(channel_init, fm801ch_init),
+ KOBJMETHOD(channel_setformat, fm801ch_setformat),
+ KOBJMETHOD(channel_setspeed, fm801ch_setspeed),
+ KOBJMETHOD(channel_setblocksize, fm801ch_setblocksize),
+ KOBJMETHOD(channel_trigger, fm801ch_trigger),
+ KOBJMETHOD(channel_getptr, fm801ch_getptr),
+ KOBJMETHOD(channel_getcaps, fm801ch_getcaps),
+ { 0, 0 }
+};
+CHANNEL_DECLARE(fm801ch);
+
+/* -------------------------------------------------------------------- */
+
+/*
+ * Init routine is taken from an original NetBSD driver
+ */
+static int
+fm801_init(struct fm801_info *fm801)
+{
+ u_int32_t k1;
+
+ /* reset codec */
+ fm801_wr(fm801, FM_CODEC_CTL, 0x0020,2);
+ DELAY(100000);
+ fm801_wr(fm801, FM_CODEC_CTL, 0x0000,2);
+ DELAY(100000);
+
+ fm801_wr(fm801, FM_PCM_VOLUME, 0x0808,2);
+ fm801_wr(fm801, FM_FM_VOLUME, 0x0808,2);
+ fm801_wr(fm801, FM_I2S_VOLUME, 0x0808,2);
+ fm801_wr(fm801, 0x40,0x107f,2); /* enable legacy audio */
+
+ fm801_wr((void *)fm801, FM_RECORD_SOURCE, 0x0000,2);
+
+ /* Unmask playback, record and mpu interrupts, mask the rest */
+ k1 = fm801_rd((void *)fm801, FM_INTMASK,2);
+ fm801_wr(fm801, FM_INTMASK,
+ (k1 & ~(FM_INTMASK_PLAY | FM_INTMASK_REC | FM_INTMASK_MPU)) |
+ FM_INTMASK_VOL,2);
+ fm801_wr(fm801, FM_INTSTATUS,
+ FM_INTSTATUS_PLAY | FM_INTSTATUS_REC | FM_INTSTATUS_MPU |
+ FM_INTSTATUS_VOL,2);
+
+ DPRINT("FM801 init Ok\n");
+ return 0;
+}
+
+static int
+fm801_pci_attach(device_t dev)
+{
+ u_int32_t data;
+ struct ac97_info *codec = 0;
+ struct fm801_info *fm801;
+ int i;
+ int mapped = 0;
+ char status[SND_STATUSLEN];
+
+ if ((fm801 = (struct fm801_info *)malloc(sizeof(*fm801),M_DEVBUF, M_NOWAIT)) == NULL) {
+ device_printf(dev, "cannot allocate softc\n");
+ return ENXIO;
+ }
+
+ bzero(fm801, sizeof(*fm801));
+ fm801->type = pci_get_devid(dev);
+
+ data = pci_read_config(dev, PCIR_COMMAND, 2);
+ data |= (PCIM_CMD_PORTEN|PCIM_CMD_MEMEN|PCIM_CMD_BUSMASTEREN);
+ pci_write_config(dev, PCIR_COMMAND, data, 2);
+ data = pci_read_config(dev, PCIR_COMMAND, 2);
+
+ for (i = 0; (mapped == 0) && (i < PCI_MAXMAPS_0); i++) {
+ fm801->regid = PCIR_MAPS + i*4;
+ fm801->regtype = SYS_RES_MEMORY;
+ fm801->reg = bus_alloc_resource(dev, fm801->regtype, &fm801->regid,
+ 0, ~0, 1, RF_ACTIVE);
+ if(!fm801->reg)
+ {
+ fm801->regtype = SYS_RES_IOPORT;
+ fm801->reg = bus_alloc_resource(dev, fm801->regtype, &fm801->regid,
+ 0, ~0, 1, RF_ACTIVE);
+ }
+
+ if(fm801->reg) {
+ fm801->st = rman_get_bustag(fm801->reg);
+ fm801->sh = rman_get_bushandle(fm801->reg);
+ mapped++;
+ }
+ }
+
+ if (mapped == 0) {
+ device_printf(dev, "unable to map register space\n");
+ goto oops;
+ }
+
+ fm801_init(fm801);
+
+ codec = AC97_CREATE(dev, fm801, fm801_ac97);
+ if (codec == NULL) goto oops;
+
+ if (mixer_init(dev, ac97_getmixerclass(), codec) == -1) goto oops;
+
+ fm801->irqid = 0;
+ fm801->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &fm801->irqid,
+ 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE);
+ if (!fm801->irq ||
+ bus_setup_intr(dev, fm801->irq, INTR_TYPE_TTY,
+ fm801_intr, fm801, &fm801->ih)) {
+ device_printf(dev, "unable to map interrupt\n");
+ goto oops;
+ }
+
+ if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0,
+ /*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
+ /*highaddr*/BUS_SPACE_MAXADDR,
+ /*filter*/NULL, /*filterarg*/NULL,
+ /*maxsize*/FM801_BUFFSIZE, /*nsegments*/1, /*maxsegz*/0x3ffff,
+ /*flags*/0, &fm801->parent_dmat) != 0) {
+ device_printf(dev, "unable to create dma tag\n");
+ goto oops;
+ }
+
+ snprintf(status, 64, "at %s 0x%lx irq %ld",
+ (fm801->regtype == SYS_RES_IOPORT)? "io" : "memory",
+ rman_get_start(fm801->reg), rman_get_start(fm801->irq));
+
+#define FM801_MAXPLAYCH 1
+ if (pcm_register(dev, fm801, FM801_MAXPLAYCH, 1)) goto oops;
+ pcm_addchan(dev, PCMDIR_PLAY, &fm801ch_class, fm801);
+ pcm_addchan(dev, PCMDIR_REC, &fm801ch_class, fm801);
+ pcm_setstatus(dev, status);
+
+ return 0;
+
+oops:
+ if (codec) ac97_destroy(codec);
+ if (fm801->reg) bus_release_resource(dev, fm801->regtype, fm801->regid, fm801->reg);
+ if (fm801->ih) bus_teardown_intr(dev, fm801->irq, fm801->ih);
+ if (fm801->irq) bus_release_resource(dev, SYS_RES_IRQ, fm801->irqid, fm801->irq);
+ if (fm801->parent_dmat) bus_dma_tag_destroy(fm801->parent_dmat);
+ free(fm801, M_DEVBUF);
+ return ENXIO;
+}
+
+static int
+fm801_pci_detach(device_t dev)
+{
+ int r;
+ struct fm801_info *fm801;
+
+ DPRINT("Forte Media FM801 detach\n");
+
+ r = pcm_unregister(dev);
+ if (r)
+ return r;
+
+ fm801 = pcm_getdevinfo(dev);
+ bus_release_resource(dev, fm801->regtype, fm801->regid, fm801->reg);
+ bus_teardown_intr(dev, fm801->irq, fm801->ih);
+ bus_release_resource(dev, SYS_RES_IRQ, fm801->irqid, fm801->irq);
+ bus_dma_tag_destroy(fm801->parent_dmat);
+ free(fm801, M_DEVBUF);
+ return 0;
+}
+
+static int
+fm801_pci_probe( device_t dev )
+{
+ int id;
+ if ((id = pci_get_devid(dev)) == PCI_DEVICE_FORTEMEDIA1 ) {
+ device_set_desc(dev, "Forte Media FM801 Audio Controller");
+ return 0;
+ }
+/*
+ if ((id = pci_get_devid(dev)) == PCI_DEVICE_FORTEMEDIA2 ) {
+ device_set_desc(dev, "Forte Media FM801 Joystick (Not Supported)");
+ return ENXIO;
+ }
+*/
+ return ENXIO;
+}
+
static device_method_t fm801_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, fm801_pci_probe),
diff --git a/sys/dev/sound/pci/maestro.c b/sys/dev/sound/pci/maestro.c
index 60afaa5..5955f77 100644
--- a/sys/dev/sound/pci/maestro.c
+++ b/sys/dev/sound/pci/maestro.c
@@ -114,10 +114,6 @@ struct agg_info {
struct agg_chinfo rch;
};
-
-static u_int32_t agg_rdcodec(void *, int);
-static void agg_wrcodec(void *, int, u_int32_t);
-
static inline void ringbus_setdest(struct agg_info*, int, int);
static inline u_int16_t wp_rdreg(struct agg_info*, u_int16_t);
@@ -136,7 +132,6 @@ static inline void wc_wrchctl(struct agg_info*, int, u_int16_t);
static inline void agg_power(struct agg_info*, int);
static void agg_init(struct agg_info*);
-static u_int32_t agg_ac97_init(void *);
static void aggch_start_dac(struct agg_chinfo*);
static void aggch_stop_dac(struct agg_chinfo*);
@@ -146,15 +141,6 @@ static inline void suppress_jitter(struct agg_chinfo*);
static inline u_int calc_timer_freq(struct agg_chinfo*);
static void set_timer(struct agg_info*);
-static pcmchan_init_t aggch_init;
-static pcmchan_free_t aggch_free;
-static pcmchan_setformat_t aggch_setplayformat;
-static pcmchan_setspeed_t aggch_setspeed;
-static pcmchan_setblocksize_t aggch_setblocksize;
-static pcmchan_trigger_t aggch_trigger;
-static pcmchan_getptr_t aggch_getplayptr;
-static pcmchan_getcaps_t aggch_getcaps;
-
static void agg_intr(void *);
static int agg_probe(device_t);
static int agg_attach(device_t);
@@ -172,8 +158,18 @@ static void dma_free(struct agg_info*, void *);
/* Codec/Ringbus */
+/* -------------------------------------------------------------------- */
+
static u_int32_t
-agg_rdcodec(void *sc, int regno)
+agg_ac97_init(kobj_t obj, void *sc)
+{
+ struct agg_info *ess = sc;
+
+ return (bus_space_read_1(ess->st, ess->sh, PORT_CODEC_STAT) & CODEC_STAT_MASK)? 0 : 1;
+}
+
+static int
+agg_rdcodec(kobj_t obj, void *sc, int regno)
{
struct agg_info *ess = sc;
unsigned t;
@@ -206,8 +202,8 @@ agg_rdcodec(void *sc, int regno)
return bus_space_read_2(ess->st, ess->sh, PORT_CODEC_REG);
}
-static void
-agg_wrcodec(void *sc, int regno, u_int32_t data)
+static int
+agg_wrcodec(kobj_t obj, void *sc, int regno, u_int32_t data)
{
unsigned t;
struct agg_info *ess = sc;
@@ -222,14 +218,26 @@ agg_wrcodec(void *sc, int regno, u_int32_t data)
if (t == 20) {
/* Timed out. Abort writing. */
device_printf(ess->dev, "agg_wrcodec() PROGLESS timed out.\n");
- return;
+ return -1;
}
bus_space_write_2(ess->st, ess->sh, PORT_CODEC_REG, data);
bus_space_write_1(ess->st, ess->sh, PORT_CODEC_CMD,
CODEC_CMD_WRITE | regno);
+
+ return 0;
}
+static kobj_method_t agg_ac97_methods[] = {
+ KOBJMETHOD(ac97_init, agg_ac97_init),
+ KOBJMETHOD(ac97_read, agg_rdcodec),
+ KOBJMETHOD(ac97_write, agg_wrcodec),
+ { 0, 0 }
+};
+AC97_DECLARE(agg_ac97);
+
+/* -------------------------------------------------------------------- */
+
static inline void
ringbus_setdest(struct agg_info *ess, int src, int dest)
{
@@ -396,7 +404,7 @@ agg_initcodec(struct agg_info* ess)
RINGBUS_CTRL_ACLINK_ENABLED);
DELAY(21);
- agg_rdcodec(ess, 0);
+ agg_rdcodec(NULL, ess, 0);
if (bus_space_read_1(ess->st, ess->sh, PORT_CODEC_STAT)
& CODEC_STAT_MASK) {
bus_space_write_4(ess->st, ess->sh, PORT_RINGBUS_CTRL, 0);
@@ -627,16 +635,8 @@ set_timer(struct agg_info *ess)
* Newpcm glue.
*/
-static u_int32_t
-agg_ac97_init(void *sc)
-{
- struct agg_info *ess = sc;
-
- return (bus_space_read_1(ess->st, ess->sh, PORT_CODEC_STAT) & CODEC_STAT_MASK)? 0 : 1;
-}
-
static void *
-aggch_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir)
+aggch_init(kobj_t obj, void *devinfo, snd_dbuf *b, pcm_channel *c, int dir)
{
struct agg_info *ess = devinfo;
struct agg_chinfo *ch;
@@ -677,7 +677,7 @@ aggch_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir)
}
static int
-aggch_free(void *data)
+aggch_free(kobj_t obj, void *data)
{
struct agg_chinfo *ch = data;
struct agg_info *ess = ch->parent;
@@ -690,7 +690,7 @@ aggch_free(void *data)
}
static int
-aggch_setplayformat(void *data, u_int32_t format)
+aggch_setplayformat(kobj_t obj, void *data, u_int32_t format)
{
struct agg_chinfo *ch = data;
u_int16_t wcreg_tpl;
@@ -717,19 +717,19 @@ aggch_setplayformat(void *data, u_int32_t format)
}
static int
-aggch_setspeed(void *data, u_int32_t speed)
+aggch_setspeed(kobj_t obj, void *data, u_int32_t speed)
{
return speed;
}
static int
-aggch_setblocksize(void *data, u_int32_t blocksize)
+aggch_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
{
return ((struct agg_chinfo*)data)->blocksize = blocksize;
}
static int
-aggch_trigger(void *data, int go)
+aggch_trigger(kobj_t obj, void *data, int go)
{
struct agg_chinfo *ch = data;
@@ -767,7 +767,7 @@ aggch_trigger(void *data, int go)
}
static int
-aggch_getplayptr(void *data)
+aggch_getplayptr(kobj_t obj, void *data)
{
struct agg_chinfo *ch = data;
u_int cp;
@@ -782,7 +782,7 @@ aggch_getplayptr(void *data)
}
static pcmchan_caps *
-aggch_getcaps(void *data)
+aggch_getcaps(kobj_t obj, void *data)
{
static u_int32_t playfmt[] = {
AFMT_U8,
@@ -808,6 +808,18 @@ aggch_getcaps(void *data)
&playcaps : &reccaps;
}
+static kobj_method_t aggch_methods[] = {
+ KOBJMETHOD(channel_init, aggch_init),
+ KOBJMETHOD(channel_free, aggch_free),
+ KOBJMETHOD(channel_setformat, aggch_setplayformat),
+ KOBJMETHOD(channel_setspeed, aggch_setspeed),
+ KOBJMETHOD(channel_setblocksize, aggch_setblocksize),
+ KOBJMETHOD(channel_trigger, aggch_trigger),
+ KOBJMETHOD(channel_getptr, aggch_getplayptr),
+ KOBJMETHOD(channel_getcaps, aggch_getcaps),
+ { 0, 0 }
+};
+CHANNEL_DECLARE(aggch);
/* -----------------------------
* Bus space.
@@ -933,24 +945,6 @@ agg_attach(device_t dev)
struct resource *irq = NULL;
void *ih = NULL;
char status[SND_STATUSLEN];
- static pcm_channel agg_pchtpl = {
- aggch_init,
- NULL, /* setdir */
- aggch_setplayformat,
- aggch_setspeed,
- aggch_setblocksize,
- aggch_trigger,
- aggch_getplayptr,
- aggch_getcaps,
- aggch_free, /* free */
- NULL, /* nop1 */
- NULL, /* nop2 */
- NULL, /* nop3 */
- NULL, /* nop4 */
- NULL, /* nop5 */
- NULL, /* nop6 */
- NULL, /* nop7 */
- };
if ((ess = malloc(sizeof *ess, M_DEVBUF, M_NOWAIT)) == NULL) {
device_printf(dev, "cannot allocate softc\n");
@@ -1003,14 +997,14 @@ agg_attach(device_t dev)
}
agg_init(ess);
- if (agg_rdcodec(ess, 0) == 0x80) {
+ if (agg_rdcodec(NULL, ess, 0) == 0x80) {
device_printf(dev, "PT101 codec detected!\n");
goto bad;
}
- codec = ac97_create(dev, ess, agg_ac97_init, agg_rdcodec, agg_wrcodec);
+ codec = AC97_CREATE(dev, ess, agg_ac97);
if (codec == NULL)
goto bad;
- if (mixer_init(dev, &ac97_mixer, codec) == -1)
+ if (mixer_init(dev, ac97_getmixerclass(), codec) == -1)
goto bad;
ess->codec = codec;
@@ -1032,9 +1026,9 @@ agg_attach(device_t dev)
goto bad;
for (data = 0; data < AGG_MAXPLAYCH; data++)
- pcm_addchan(dev, PCMDIR_PLAY, &agg_pchtpl, ess);
+ pcm_addchan(dev, PCMDIR_PLAY, &aggch_class, ess);
#if 0 /* XXX - RECORDING */
- pcm_addchan(dev, PCMDIR_REC, &agg_rchtpl, ess);
+ pcm_addchan(dev, PCMDIR_REC, &aggrch_class, ess);
#endif
pcm_setstatus(dev, status);
@@ -1075,7 +1069,7 @@ agg_detach(device_t dev)
dma_free(ess, ess->stat);
/* Power down everything except clock and vref. */
- agg_wrcodec(ess, AC97_REG_POWER, 0xd700);
+ agg_wrcodec(NULL, ess, AC97_REG_POWER, 0xd700);
DELAY(20);
bus_space_write_4(ess->st, ess->sh, PORT_RINGBUS_CTRL, 0);
agg_power(ess, PPMI_D3);
@@ -1106,7 +1100,7 @@ agg_suspend(device_t dev)
#endif
splx(x);
/* Power down everything except clock. */
- agg_wrcodec(ess, AC97_REG_POWER, 0xdf00);
+ agg_wrcodec(NULL, ess, AC97_REG_POWER, 0xdf00);
DELAY(20);
bus_space_write_4(ess->st, ess->sh, PORT_RINGBUS_CTRL, 0);
DELAY(1);
diff --git a/sys/dev/sound/pci/neomagic.c b/sys/dev/sound/pci/neomagic.c
index 6867253..1e2760c 100644
--- a/sys/dev/sound/pci/neomagic.c
+++ b/sys/dev/sound/pci/neomagic.c
@@ -76,21 +76,6 @@ struct sc_info {
* prototypes
*/
-/* channel interface */
-static void *nmchan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir);
-static int nmchan_free(void *data);
-static int nmchan_setformat(void *data, u_int32_t format);
-static int nmchan_setspeed(void *data, u_int32_t speed);
-static int nmchan_setblocksize(void *data, u_int32_t blocksize);
-static int nmchan_trigger(void *data, int go);
-static int nmchan_getptr(void *data);
-static pcmchan_caps *nmchan_getcaps(void *data);
-
-static int nm_waitcd(struct sc_info *sc);
-/* talk to the codec - called from ac97.c */
-static u_int32_t nm_rdcd(void *, int);
-static void nm_wrcd(void *, int, u_int32_t);
-
/* stuff */
static int nm_loadcoeff(struct sc_info *sc, int dir, int num);
static int nm_setch(struct sc_chinfo *ch);
@@ -134,25 +119,6 @@ static u_int32_t nm_fmt[] = {
};
static pcmchan_caps nm_caps = {4000, 48000, nm_fmt, 0};
-static pcm_channel nm_chantemplate = {
- nmchan_init,
- NULL, /* setdir */
- nmchan_setformat,
- nmchan_setspeed,
- nmchan_setblocksize,
- nmchan_trigger,
- nmchan_getptr,
- nmchan_getcaps,
- nmchan_free, /* free */
- NULL, /* nop1 */
- NULL, /* nop2 */
- NULL, /* nop3 */
- NULL, /* nop4 */
- NULL, /* nop5 */
- NULL, /* nop6 */
- NULL, /* nop7 */
-};
-
/* -------------------------------------------------------------------- */
/* Hardware */
@@ -230,6 +196,7 @@ nm_wrbuf(struct sc_info *sc, int regno, u_int32_t data, int size)
}
}
+/* -------------------------------------------------------------------- */
/* ac97 codec */
static int
nm_waitcd(struct sc_info *sc)
@@ -246,7 +213,7 @@ nm_waitcd(struct sc_info *sc)
}
static u_int32_t
-nm_initcd(void *devinfo)
+nm_initcd(kobj_t obj, void *devinfo)
{
struct sc_info *sc = (struct sc_info *)devinfo;
@@ -257,8 +224,8 @@ nm_initcd(void *devinfo)
return 1;
}
-static u_int32_t
-nm_rdcd(void *devinfo, int regno)
+static int
+nm_rdcd(kobj_t obj, void *devinfo, int regno)
{
struct sc_info *sc = (struct sc_info *)devinfo;
u_int32_t x;
@@ -269,12 +236,12 @@ nm_rdcd(void *devinfo, int regno)
return x;
} else {
device_printf(sc->dev, "ac97 codec not ready\n");
- return 0xffffffff;
+ return -1;
}
}
-static void
-nm_wrcd(void *devinfo, int regno, u_int32_t data)
+static int
+nm_wrcd(kobj_t obj, void *devinfo, int regno, u_int32_t data)
{
struct sc_info *sc = (struct sc_info *)devinfo;
int cnt = 3;
@@ -284,13 +251,24 @@ nm_wrcd(void *devinfo, int regno, u_int32_t data)
nm_wr(sc, sc->ac97_base + regno, data, 2);
if (!nm_waitcd(sc)) {
DELAY(1000);
- return;
+ return 0;
}
}
}
device_printf(sc->dev, "ac97 codec not ready\n");
+ return -1;
}
+static kobj_method_t nm_ac97_methods[] = {
+ KOBJMETHOD(ac97_init, nm_initcd),
+ KOBJMETHOD(ac97_read, nm_rdcd),
+ KOBJMETHOD(ac97_write, nm_wrcd),
+ { 0, 0 }
+};
+AC97_DECLARE(nm_ac97);
+
+/* -------------------------------------------------------------------- */
+
static void
nm_ackint(struct sc_info *sc, u_int32_t num)
{
@@ -351,7 +329,7 @@ nm_setch(struct sc_chinfo *ch)
/* channel interface */
static void *
-nmchan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir)
+nmchan_init(kobj_t obj, void *devinfo, snd_dbuf *b, pcm_channel *c, int dir)
{
struct sc_info *sc = devinfo;
struct sc_chinfo *ch;
@@ -372,13 +350,13 @@ nmchan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir)
}
static int
-nmchan_free(void *data)
+nmchan_free(kobj_t obj, void *data)
{
return 0;
}
static int
-nmchan_setformat(void *data, u_int32_t format)
+nmchan_setformat(kobj_t obj, void *data, u_int32_t format)
{
struct sc_chinfo *ch = data;
@@ -387,7 +365,7 @@ nmchan_setformat(void *data, u_int32_t format)
}
static int
-nmchan_setspeed(void *data, u_int32_t speed)
+nmchan_setspeed(kobj_t obj, void *data, u_int32_t speed)
{
struct sc_chinfo *ch = data;
@@ -396,13 +374,13 @@ nmchan_setspeed(void *data, u_int32_t speed)
}
static int
-nmchan_setblocksize(void *data, u_int32_t blocksize)
+nmchan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
{
return blocksize;
}
static int
-nmchan_trigger(void *data, int go)
+nmchan_trigger(kobj_t obj, void *data, int go)
{
struct sc_chinfo *ch = data;
struct sc_info *sc = ch->parent;
@@ -444,7 +422,7 @@ nmchan_trigger(void *data, int go)
}
static int
-nmchan_getptr(void *data)
+nmchan_getptr(kobj_t obj, void *data)
{
struct sc_chinfo *ch = data;
struct sc_info *sc = ch->parent;
@@ -456,11 +434,24 @@ nmchan_getptr(void *data)
}
static pcmchan_caps *
-nmchan_getcaps(void *data)
+nmchan_getcaps(kobj_t obj, void *data)
{
return &nm_caps;
}
+static kobj_method_t nmchan_methods[] = {
+ KOBJMETHOD(channel_init, nmchan_init),
+ KOBJMETHOD(channel_free, nmchan_free),
+ KOBJMETHOD(channel_setformat, nmchan_setformat),
+ KOBJMETHOD(channel_setspeed, nmchan_setspeed),
+ KOBJMETHOD(channel_setblocksize, nmchan_setblocksize),
+ KOBJMETHOD(channel_trigger, nmchan_trigger),
+ KOBJMETHOD(channel_getptr, nmchan_getptr),
+ KOBJMETHOD(channel_getcaps, nmchan_getcaps),
+ { 0, 0 }
+};
+CHANNEL_DECLARE(nmchan);
+
/* The interrupt handler */
static void
nm_intr(void *p)
@@ -626,9 +617,9 @@ nm_pci_attach(device_t dev)
goto bad;
}
- codec = ac97_create(dev, sc, nm_initcd, nm_rdcd, nm_wrcd);
+ codec = AC97_CREATE(dev, sc, nm_ac97);
if (codec == NULL) goto bad;
- if (mixer_init(dev, &ac97_mixer, codec) == -1) goto bad;
+ if (mixer_init(dev, ac97_getmixerclass(), codec) == -1) goto bad;
sc->irqid = 0;
sc->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->irqid,
@@ -644,8 +635,8 @@ nm_pci_attach(device_t dev)
rman_get_start(sc->irq));
if (pcm_register(dev, sc, 1, 1)) goto bad;
- pcm_addchan(dev, PCMDIR_REC, &nm_chantemplate, sc);
- pcm_addchan(dev, PCMDIR_PLAY, &nm_chantemplate, sc);
+ pcm_addchan(dev, PCMDIR_REC, &nmchan_class, sc);
+ pcm_addchan(dev, PCMDIR_PLAY, &nmchan_class, sc);
pcm_setstatus(dev, status);
return 0;
diff --git a/sys/dev/sound/pci/solo.c b/sys/dev/sound/pci/solo.c
index 672c7a0..7cb10f3 100644
--- a/sys/dev/sound/pci/solo.c
+++ b/sys/dev/sound/pci/solo.c
@@ -33,6 +33,8 @@
#include <dev/sound/isa/sb.h>
#include <dev/sound/chip.h>
+#include "mixer_if.h"
+
#define ESS_BUFFSIZE (16384)
#define ABS(x) (((x) < 0)? -(x) : (x))
@@ -42,15 +44,6 @@
/* more accurate clocks and split audio1/audio2 rates */
#define ESS18XX_NEWSPEED
-/* channel interface for ESS */
-static void *esschan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir);
-static int esschan_setformat(void *data, u_int32_t format);
-static int esschan_setspeed(void *data, u_int32_t speed);
-static int esschan_setblocksize(void *data, u_int32_t blocksize);
-static int esschan_trigger(void *data, int go);
-static int esschan_getptr(void *data);
-static pcmchan_caps *esschan_getcaps(void *data);
-
static u_int32_t ess_playfmt[] = {
AFMT_U8,
AFMT_STEREO | AFMT_U8,
@@ -80,25 +73,6 @@ static u_int32_t ess_recfmt[] = {
};
static pcmchan_caps ess_reccaps = {5000, 49000, ess_recfmt, 0};
-static pcm_channel ess_chantemplate = {
- esschan_init,
- NULL, /* setdir */
- esschan_setformat,
- esschan_setspeed,
- esschan_setblocksize,
- esschan_trigger,
- esschan_getptr,
- esschan_getcaps,
- NULL, /* free */
- NULL, /* nop1 */
- NULL, /* nop2 */
- NULL, /* nop3 */
- NULL, /* nop4 */
- NULL, /* nop5 */
- NULL, /* nop6 */
- NULL, /* nop7 */
-};
-
struct ess_info;
struct ess_chinfo {
@@ -141,19 +115,6 @@ static int ess_dmasetup(struct ess_info *sc, int ch, u_int32_t base, u_int16_t c
static int ess_dmapos(struct ess_info *sc, int ch);
static int ess_dmatrigger(struct ess_info *sc, int ch, int go);
-static int essmix_init(snd_mixer *m);
-static int essmix_set(snd_mixer *m, unsigned dev, unsigned left, unsigned right);
-static int essmix_setrecsrc(snd_mixer *m, u_int32_t src);
-
-static snd_mixer ess_mixer = {
- "ESS mixer",
- essmix_init,
- NULL,
- NULL,
- essmix_set,
- essmix_setrecsrc,
-};
-
static devclass_t pcm_devclass;
/*
@@ -546,9 +507,10 @@ ess_stop(struct ess_chinfo *ch)
return 0;
}
+/* -------------------------------------------------------------------- */
/* channel interface for ESS18xx */
static void *
-esschan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir)
+esschan_init(kobj_t obj, void *devinfo, snd_dbuf *b, pcm_channel *c, int dir)
{
struct ess_info *sc = devinfo;
struct ess_chinfo *ch = (dir == PCMDIR_PLAY)? &sc->pch : &sc->rch;
@@ -568,7 +530,7 @@ esschan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir)
}
static int
-esschan_setformat(void *data, u_int32_t format)
+esschan_setformat(kobj_t obj, void *data, u_int32_t format)
{
struct ess_chinfo *ch = data;
@@ -577,7 +539,7 @@ esschan_setformat(void *data, u_int32_t format)
}
static int
-esschan_setspeed(void *data, u_int32_t speed)
+esschan_setspeed(kobj_t obj, void *data, u_int32_t speed)
{
struct ess_chinfo *ch = data;
struct ess_info *sc = ch->parent;
@@ -591,13 +553,13 @@ esschan_setspeed(void *data, u_int32_t speed)
}
static int
-esschan_setblocksize(void *data, u_int32_t blocksize)
+esschan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
{
return blocksize;
}
static int
-esschan_trigger(void *data, int go)
+esschan_trigger(kobj_t obj, void *data, int go)
{
struct ess_chinfo *ch = data;
struct ess_info *sc = ch->parent;
@@ -623,7 +585,7 @@ esschan_trigger(void *data, int go)
}
static int
-esschan_getptr(void *data)
+esschan_getptr(kobj_t obj, void *data)
{
struct ess_chinfo *ch = data;
struct ess_info *sc = ch->parent;
@@ -632,13 +594,25 @@ esschan_getptr(void *data)
}
static pcmchan_caps *
-esschan_getcaps(void *data)
+esschan_getcaps(kobj_t obj, void *data)
{
struct ess_chinfo *ch = data;
return (ch->dir == PCMDIR_PLAY)? &ess_playcaps : &ess_reccaps;
}
+static kobj_method_t esschan_methods[] = {
+ KOBJMETHOD(channel_init, esschan_init),
+ KOBJMETHOD(channel_setformat, esschan_setformat),
+ KOBJMETHOD(channel_setspeed, esschan_setspeed),
+ KOBJMETHOD(channel_setblocksize, esschan_setblocksize),
+ KOBJMETHOD(channel_trigger, esschan_trigger),
+ KOBJMETHOD(channel_getptr, esschan_getptr),
+ KOBJMETHOD(channel_getcaps, esschan_getcaps),
+ { 0, 0 }
+};
+CHANNEL_DECLARE(esschan);
+
/************************************************************/
static int
@@ -749,6 +723,14 @@ essmix_setrecsrc(snd_mixer *m, u_int32_t src)
return src;
}
+static kobj_method_t solomixer_methods[] = {
+ KOBJMETHOD(mixer_init, essmix_init),
+ KOBJMETHOD(mixer_set, essmix_set),
+ KOBJMETHOD(mixer_setrecsrc, essmix_setrecsrc),
+ { 0, 0 }
+};
+MIXER_DECLARE(solomixer);
+
/************************************************************/
static int
@@ -942,7 +924,8 @@ ess_attach(device_t dev)
if (ess_reset_dsp(sc))
goto no;
- mixer_init(dev, &ess_mixer, sc);
+ if (mixer_init(dev, &solomixer_class, sc))
+ goto no;
port_wr(sc->io, 0x7, 0xb0, 1); /* enable irqs */
#ifdef ESS18XX_DUPLEX
@@ -980,8 +963,8 @@ ess_attach(device_t dev)
if (pcm_register(dev, sc, 1, 1))
goto no;
- pcm_addchan(dev, PCMDIR_REC, &ess_chantemplate, sc);
- pcm_addchan(dev, PCMDIR_PLAY, &ess_chantemplate, sc);
+ pcm_addchan(dev, PCMDIR_REC, &esschan_class, sc);
+ pcm_addchan(dev, PCMDIR_PLAY, &esschan_class, sc);
pcm_setstatus(dev, status);
return 0;
diff --git a/sys/dev/sound/pci/t4dwave.c b/sys/dev/sound/pci/t4dwave.c
index df11fb9..dee0f9f 100644
--- a/sys/dev/sound/pci/t4dwave.c
+++ b/sys/dev/sound/pci/t4dwave.c
@@ -81,20 +81,6 @@ struct tr_info {
* prototypes
*/
-/* channel interface */
-static void *trchan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir);
-static int trchan_setdir(void *data, int dir);
-static int trchan_setformat(void *data, u_int32_t format);
-static int trchan_setspeed(void *data, u_int32_t speed);
-static int trchan_setblocksize(void *data, u_int32_t blocksize);
-static int trchan_trigger(void *data, int go);
-static int trchan_getptr(void *data);
-static pcmchan_caps *trchan_getcaps(void *data);
-
-/* talk to the codec - called from ac97.c */
-static u_int32_t tr_rdcd(void *, int);
-static void tr_wrcd(void *, int, u_int32_t);
-
/* stuff */
static int tr_init(struct tr_info *);
static void tr_intr(void *);
@@ -141,25 +127,6 @@ static u_int32_t tr_playfmt[] = {
};
static pcmchan_caps tr_playcaps = {4000, 48000, tr_playfmt, 0};
-static pcm_channel tr_chantemplate = {
- trchan_init,
- trchan_setdir,
- trchan_setformat,
- trchan_setspeed,
- trchan_setblocksize,
- trchan_trigger,
- trchan_getptr,
- trchan_getcaps,
- NULL, /* free */
- NULL, /* nop1 */
- NULL, /* nop2 */
- NULL, /* nop3 */
- NULL, /* nop4 */
- NULL, /* nop5 */
- NULL, /* nop6 */
- NULL, /* nop7 */
-};
-
/* -------------------------------------------------------------------- */
static u_int32_t
@@ -205,10 +172,11 @@ tr_wr(struct tr_info *tr, int regno, u_int32_t data, int size)
}
}
+/* -------------------------------------------------------------------- */
/* ac97 codec */
-static u_int32_t
-tr_rdcd(void *devinfo, int regno)
+static int
+tr_rdcd(kobj_t obj, void *devinfo, int regno)
{
struct tr_info *tr = (struct tr_info *)devinfo;
int i, j, treg, trw;
@@ -224,7 +192,7 @@ tr_rdcd(void *devinfo, int regno)
break;
default:
printf("!!! tr_rdcd defaulted !!!\n");
- return 0xffffffff;
+ return -1;
}
regno &= 0x7f;
@@ -235,8 +203,8 @@ tr_rdcd(void *devinfo, int regno)
return (j >> TR_CDC_DATA) & 0xffff;
}
-static void
-tr_wrcd(void *devinfo, int regno, u_int32_t data)
+static int
+tr_wrcd(kobj_t obj, void *devinfo, int regno, u_int32_t data)
{
struct tr_info *tr = (struct tr_info *)devinfo;
int i, j, treg, trw;
@@ -252,7 +220,7 @@ tr_wrcd(void *devinfo, int regno, u_int32_t data)
break;
default:
printf("!!! tr_wrcd defaulted !!!");
- return;
+ return -1;
}
regno &= 0x7f;
@@ -266,8 +234,17 @@ tr_wrcd(void *devinfo, int regno, u_int32_t data)
printf(" - wrote %x, now %x\n", data, tr_rdcd(devinfo, regno));
#endif
if (i==0) printf("codec timeout writing %x, data %x\n", regno, data);
+ return (i > 0)? 0 : -1;
}
+static kobj_method_t tr_ac97_methods[] = {
+ KOBJMETHOD(ac97_read, tr_rdcd),
+ KOBJMETHOD(ac97_write, tr_wrcd),
+ { 0, 0 }
+};
+AC97_DECLARE(tr_ac97);
+
+/* -------------------------------------------------------------------- */
/* playback channel interrupts */
static u_int32_t
@@ -398,10 +375,11 @@ tr_rdch(struct tr_info *tr, char channel, struct tr_chinfo *ch)
}
}
+/* -------------------------------------------------------------------- */
/* channel interface */
-void *
-trchan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir)
+static void *
+trchan_init(kobj_t obj, void *devinfo, snd_dbuf *b, pcm_channel *c, int dir)
{
struct tr_info *tr = devinfo;
struct tr_chinfo *ch;
@@ -421,7 +399,7 @@ trchan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir)
}
static int
-trchan_setdir(void *data, int dir)
+trchan_setdir(kobj_t obj, void *data, int dir)
{
struct tr_chinfo *ch = data;
struct tr_info *tr = ch->parent;
@@ -454,7 +432,7 @@ trchan_setdir(void *data, int dir)
}
static int
-trchan_setformat(void *data, u_int32_t format)
+trchan_setformat(kobj_t obj, void *data, u_int32_t format)
{
struct tr_chinfo *ch = data;
struct tr_info *tr = ch->parent;
@@ -481,7 +459,7 @@ trchan_setformat(void *data, u_int32_t format)
}
static int
-trchan_setspeed(void *data, u_int32_t speed)
+trchan_setspeed(kobj_t obj, void *data, u_int32_t speed)
{
struct tr_chinfo *ch = data;
struct tr_info *tr = ch->parent;
@@ -501,14 +479,14 @@ trchan_setspeed(void *data, u_int32_t speed)
}
static int
-trchan_setblocksize(void *data, u_int32_t blocksize)
+trchan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
{
struct tr_chinfo *ch = data;
return ch->buffer->bufsize / 2;
}
static int
-trchan_trigger(void *data, int go)
+trchan_trigger(kobj_t obj, void *data, int go)
{
struct tr_chinfo *ch = data;
struct tr_info *tr = ch->parent;
@@ -531,7 +509,7 @@ trchan_trigger(void *data, int go)
}
static int
-trchan_getptr(void *data)
+trchan_getptr(kobj_t obj, void *data)
{
struct tr_chinfo *ch = data;
struct tr_info *tr = ch->parent;
@@ -543,12 +521,26 @@ trchan_getptr(void *data)
}
static pcmchan_caps *
-trchan_getcaps(void *data)
+trchan_getcaps(kobj_t obj, void *data)
{
struct tr_chinfo *ch = data;
return (ch->index >= 0)? &tr_playcaps : &tr_reccaps;
}
+static kobj_method_t trchan_methods[] = {
+ KOBJMETHOD(channel_init, trchan_init),
+ KOBJMETHOD(channel_setdir, trchan_setdir),
+ KOBJMETHOD(channel_setformat, trchan_setformat),
+ KOBJMETHOD(channel_setspeed, trchan_setspeed),
+ KOBJMETHOD(channel_setblocksize, trchan_setblocksize),
+ KOBJMETHOD(channel_trigger, trchan_trigger),
+ KOBJMETHOD(channel_getptr, trchan_getptr),
+ KOBJMETHOD(channel_getcaps, trchan_getcaps),
+ { 0, 0 }
+};
+CHANNEL_DECLARE(trchan);
+
+/* -------------------------------------------------------------------- */
/* The interrupt handler */
static void
@@ -659,9 +651,9 @@ tr_pci_attach(device_t dev)
goto bad;
}
- codec = ac97_create(dev, tr, NULL, tr_rdcd, tr_wrcd);
+ codec = AC97_CREATE(dev, tr, tr_ac97);
if (codec == NULL) goto bad;
- if (mixer_init(dev, &ac97_mixer, codec) == -1) goto bad;
+ if (mixer_init(dev, ac97_getmixerclass(), codec) == -1) goto bad;
tr->irqid = 0;
tr->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &tr->irqid,
@@ -687,9 +679,9 @@ tr_pci_attach(device_t dev)
rman_get_start(tr->reg), rman_get_start(tr->irq));
if (pcm_register(dev, tr, TR_MAXPLAYCH, 1)) goto bad;
- pcm_addchan(dev, PCMDIR_REC, &tr_chantemplate, tr);
+ pcm_addchan(dev, PCMDIR_REC, &trchan_class, tr);
for (i = 0; i < TR_MAXPLAYCH; i++)
- pcm_addchan(dev, PCMDIR_PLAY, &tr_chantemplate, tr);
+ pcm_addchan(dev, PCMDIR_PLAY, &trchan_class, tr);
pcm_setstatus(dev, status);
return 0;
diff --git a/sys/dev/sound/pci/via82c686.c b/sys/dev/sound/pci/via82c686.c
index df72136..27d7aef 100644
--- a/sys/dev/sound/pci/via82c686.c
+++ b/sys/dev/sound/pci/via82c686.c
@@ -70,25 +70,9 @@ struct via_info {
static u_int32_t via_rd(struct via_info *via, int regno, int size);
static void via_wr(struct via_info *, int regno, u_int32_t data, int size);
-int via_waitready_codec(struct via_info *via);
-int via_waitvalid_codec(struct via_info *via);
-u_int32_t via_read_codec(void *addr, int reg);
-void via_write_codec(void *addr, int reg, u_int32_t val);
-
static void via_intr(void *);
bus_dmamap_callback_t dma_cb;
-
-/* channel interface */
-static void *viachan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir);
-static int viachan_setdir(void *data, int dir);
-static int viachan_setformat(void *data, u_int32_t format);
-static int viachan_setspeed(void *data, u_int32_t speed);
-static int viachan_setblocksize(void *data, u_int32_t blocksize);
-static int viachan_trigger(void *data, int go);
-static int viachan_getptr(void *data);
-static pcmchan_caps *viachan_getcaps(void *data);
-
static u_int32_t via_playfmt[] = {
AFMT_U8,
AFMT_STEREO | AFMT_U8,
@@ -107,217 +91,6 @@ static u_int32_t via_recfmt[] = {
};
static pcmchan_caps via_reccaps = {4000, 48000, via_recfmt, 0};
-static pcm_channel via_chantemplate = {
- viachan_init,
- viachan_setdir,
- viachan_setformat,
- viachan_setspeed,
- viachan_setblocksize,
- viachan_trigger,
- viachan_getptr,
- viachan_getcaps,
- NULL, /* free */
- NULL, /* nop1 */
- NULL, /* nop2 */
- NULL, /* nop3 */
- NULL, /* nop4 */
- NULL, /* nop5 */
- NULL, /* nop6 */
- NULL, /* nop7 */
-};
-
-
-/*
- * Probe and attach the card
- */
-static int
-via_probe(device_t dev)
-{
- if (pci_get_devid(dev) == VIA_PCI_ID) {
- device_set_desc(dev, "VIA VT82C686A AC'97 Audio");
- return 0;
- }
- return ENXIO;
-}
-
-
-void dma_cb(void *p, bus_dma_segment_t *bds, int a, int b)
-{
-}
-
-
-static int
-via_attach(device_t dev)
-{
- struct via_info *via = 0;
- struct ac97_info *codec = 0;
- char status[SND_STATUSLEN];
-
- u_int32_t data;
-
- u_int16_t v;
- bus_dmamap_t sgd_dma_map;
-
- if ((via = malloc(sizeof *via, M_DEVBUF, M_NOWAIT)) == NULL) {
- device_printf(dev, "cannot allocate softc\n");
- return ENXIO;
- }
- bzero(via, sizeof *via);
-
- /* Get resources */
- data = pci_read_config(dev, PCIR_COMMAND, 2);
- data |= (PCIM_CMD_PORTEN | PCIM_CMD_BUSMASTEREN);
- pci_write_config(dev, PCIR_COMMAND, data, 2);
- data = pci_read_config(dev, PCIR_COMMAND, 2);
-
- pci_write_config(dev, VIA_PCICONF_MISC,
- VIA_PCICONF_ACLINKENAB | VIA_PCICONF_ACSGD |
- VIA_PCICONF_ACNOTRST | VIA_PCICONF_ACVSR, 1);
-
- via->regid = PCIR_MAPS;
- via->reg = bus_alloc_resource(dev, SYS_RES_IOPORT, &via->regid,
- 0, ~0, 1, RF_ACTIVE);
- if (!via->reg) {
- device_printf(dev, "via: Cannot allocate bus resource.");
- goto bad;
- }
- via->st = rman_get_bustag(via->reg);
- via->sh = rman_get_bushandle(via->reg);
-
- via->irqid = 0;
- via->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &via->irqid,
- 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE);
- if (!via->irq
- || bus_setup_intr(dev, via->irq, INTR_TYPE_TTY, via_intr, via, &via->ih)){
- device_printf(dev, "unable to map interrupt\n");
- goto bad;
- }
-
- via_wr(via, VIA_PLAY_MODE,
- VIA_RPMODE_AUTOSTART |
- VIA_RPMODE_INTR_FLAG | VIA_RPMODE_INTR_EOL, 1);
- via_wr(via, VIA_RECORD_MODE,
- VIA_RPMODE_AUTOSTART |
- VIA_RPMODE_INTR_FLAG | VIA_RPMODE_INTR_EOL, 1);
-
- codec = ac97_create(dev, via, NULL,
- via_read_codec, via_write_codec);
- if (!codec) goto bad;
-
- mixer_init(dev, &ac97_mixer, codec);
-
- /*
- * The mixer init resets the codec. So enabling VRA must be done
- * afterwards.
- */
- v = via_read_codec(via, AC97_REG_EXT_AUDIO_ID);
- v &= (AC97_ENAB_VRA | AC97_ENAB_MICVRA);
- via_write_codec(via, AC97_REG_EXT_AUDIO_STAT, v);
- via->codec_caps = v;
- {
- v = via_read_codec(via, AC97_REG_EXT_AUDIO_STAT);
- DEB(printf("init: codec stat: %d\n", v));
- }
-
- if (!(v & AC97_CODEC_DOES_VRA)) {
- /* no VRA => can do only 48 kbps */
- via_playcaps.minspeed = 48000;
- via_reccaps.minspeed = 48000;
- }
-
- /* DMA tag for buffers */
- if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0,
- /*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
- /*highaddr*/BUS_SPACE_MAXADDR,
- /*filter*/NULL, /*filterarg*/NULL,
- /*maxsize*/VIA_BUFFSIZE, /*nsegments*/1, /*maxsegz*/0x3ffff,
- /*flags*/0, &via->parent_dmat) != 0) {
- device_printf(dev, "unable to create dma tag\n");
- goto bad;
- }
-
- /*
- * DMA tag for SGD table. The 686 uses scatter/gather DMA and
- * requires a list in memory of work to do. We need only 16 bytes
- * for this list, and it is wasteful to allocate 16K.
- */
- if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0,
- /*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
- /*highaddr*/BUS_SPACE_MAXADDR,
- /*filter*/NULL, /*filterarg*/NULL,
- /*maxsize*/NSEGS * sizeof(struct via_dma_op),
- /*nsegments*/1, /*maxsegz*/0x3ffff,
- /*flags*/0, &via->sgd_dmat) != 0) {
- device_printf(dev, "unable to create dma tag\n");
- goto bad;
- }
-
- if (bus_dmamem_alloc(via->sgd_dmat, (void **)&via->sgd_table,
- BUS_DMA_NOWAIT, &sgd_dma_map) == -1) goto bad;
- if (bus_dmamap_load(via->sgd_dmat, sgd_dma_map, via->sgd_table,
- NSEGS * sizeof(struct via_dma_op), dma_cb, 0, 0)) goto bad;
-
- snprintf(status, SND_STATUSLEN, "at io 0x%lx irq %ld",
- rman_get_start(via->reg), rman_get_start(via->irq));
-
- /* Register */
- if (pcm_register(dev, via, 1, 1)) goto bad;
- pcm_addchan(dev, PCMDIR_PLAY, &via_chantemplate, via);
- pcm_addchan(dev, PCMDIR_REC, &via_chantemplate, via);
- pcm_setstatus(dev, status);
- return 0;
-bad:
- if (codec) ac97_destroy(codec);
- if (via->reg) bus_release_resource(dev, SYS_RES_IOPORT, via->regid, via->reg);
- if (via->ih) bus_teardown_intr(dev, via->irq, via->ih);
- if (via->irq) bus_release_resource(dev, SYS_RES_IRQ, via->irqid, via->irq);
- if (via->parent_dmat) bus_dma_tag_destroy(via->parent_dmat);
- if (via->sgd_dmat) bus_dma_tag_destroy(via->sgd_dmat);
- if (via) free(via, M_DEVBUF);
- return ENXIO;
-}
-
-static int
-via_detach(device_t dev)
-{
- int r;
- struct via_info *via = 0;
-
- r = pcm_unregister(dev);
- if (r)
- return r;
-
- via = pcm_getdevinfo(dev);
- bus_release_resource(dev, SYS_RES_IOPORT, via->regid, via->reg);
- bus_teardown_intr(dev, via->irq, via->ih);
- bus_release_resource(dev, SYS_RES_IRQ, via->irqid, via->irq);
- bus_dma_tag_destroy(via->parent_dmat);
- bus_dma_tag_destroy(via->sgd_dmat);
- free(via, M_DEVBUF);
- return 0;
-}
-
-
-static device_method_t via_methods[] = {
- DEVMETHOD(device_probe, via_probe),
- DEVMETHOD(device_attach, via_attach),
- DEVMETHOD(device_detach, via_detach),
- { 0, 0}
-};
-
-static driver_t via_driver = {
- "pcm",
- via_methods,
- sizeof(snddev_info),
-};
-
-static devclass_t pcm_devclass;
-
-DRIVER_MODULE(via, pci, via_driver, pcm_devclass, 0, 0);
-MODULE_DEPEND(via, snd_pcm, PCM_MINVER, PCM_PREFVER, PCM_MAXVER);
-MODULE_VERSION(via, 1);
-
-
static u_int32_t
via_rd(struct via_info *via, int regno, int size)
{
@@ -352,9 +125,10 @@ via_wr(struct via_info *via, int regno, u_int32_t data, int size)
}
}
-
+/* -------------------------------------------------------------------- */
/* Codec interface */
-int
+
+static int
via_waitready_codec(struct via_info *via)
{
int i;
@@ -372,7 +146,7 @@ via_waitready_codec(struct via_info *via)
}
-int
+static int
via_waitvalid_codec(struct via_info *via)
{
int i;
@@ -390,20 +164,22 @@ via_waitvalid_codec(struct via_info *via)
}
-void
-via_write_codec(void *addr, int reg, u_int32_t val)
+static int
+via_write_codec(kobj_t obj, void *addr, int reg, u_int32_t val)
{
struct via_info *via = addr;
- if (via_waitready_codec(via)) return;
+ if (via_waitready_codec(via)) return -1;
via_wr(via, VIA_CODEC_CTL,
VIA_CODEC_PRIVALID | VIA_CODEC_INDEX(reg) | val, 4);
+
+ return 0;
}
-u_int32_t
-via_read_codec(void *addr, int reg)
+static int
+via_read_codec(kobj_t obj, void *addr, int reg)
{
struct via_info *via = addr;
@@ -422,10 +198,18 @@ via_read_codec(void *addr, int reg)
return via_rd(via, VIA_CODEC_CTL, 2);
}
+static kobj_method_t via_ac97_methods[] = {
+ KOBJMETHOD(ac97_read, via_read_codec),
+ KOBJMETHOD(ac97_write, via_write_codec),
+ { 0, 0 }
+};
+AC97_DECLARE(via_ac97);
+
+/* -------------------------------------------------------------------- */
/* channel interface */
static void *
-viachan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir)
+viachan_init(kobj_t obj, void *devinfo, snd_dbuf *b, pcm_channel *c, int dir)
{
struct via_info *via = devinfo;
struct via_chinfo *ch = (dir == PCMDIR_PLAY) ? &via->pch : &via->rch;
@@ -440,7 +224,7 @@ viachan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir)
}
static int
-viachan_setdir(void *data, int dir)
+viachan_setdir(kobj_t obj, void *data, int dir)
{
struct via_chinfo *ch = data;
struct via_info *via = ch->parent;
@@ -477,7 +261,7 @@ DEB(printf("ado->ptr/flags = %x/%x\n", phys_addr, flag));
}
static int
-viachan_setformat(void *data, u_int32_t format)
+viachan_setformat(kobj_t obj, void *data, u_int32_t format)
{
struct via_chinfo *ch = data;
struct via_info *via = ch->parent;
@@ -509,7 +293,7 @@ DEB(printf("set record format: %x\n", format));
}
static int
-viachan_setspeed(void *data, u_int32_t speed)
+viachan_setspeed(kobj_t obj, void *data, u_int32_t speed)
{
struct via_chinfo *ch = data;
struct via_info *via = ch->parent;
@@ -526,8 +310,8 @@ viachan_setspeed(void *data, u_int32_t speed)
if (ch->dir == PCMDIR_PLAY) {
DEB(printf("requested play speed: %d\n", speed));
if (via->codec_caps & AC97_CODEC_DOES_VRA) {
- via_write_codec(via, AC97_REG_EXT_DAC_RATE, speed);
- speed = via_read_codec(via, AC97_REG_EXT_DAC_RATE);
+ via_write_codec(NULL, via, AC97_REG_EXT_DAC_RATE, speed);
+ speed = via_read_codec(NULL, via, AC97_REG_EXT_DAC_RATE);
}
else {
DEB(printf("VRA not supported!\n"));
@@ -538,8 +322,8 @@ DEB(printf("obtained play speed: %d\n", speed));
else {
DEB(printf("requested record speed: %d\n", speed));
if (via->codec_caps & AC97_CODEC_DOES_VRA) {
- via_write_codec(via, AC97_REG_EXT_ADC_RATE, speed);
- speed = via_read_codec(via, AC97_REG_EXT_ADC_RATE);
+ via_write_codec(NULL, via, AC97_REG_EXT_ADC_RATE, speed);
+ speed = via_read_codec(NULL, via, AC97_REG_EXT_ADC_RATE);
}
else {
DEB(printf("VRA not supported!\n"));
@@ -551,7 +335,7 @@ DEB(printf("obtained record speed: %d\n", speed));
}
static int
-viachan_setblocksize(void *data, u_int32_t blocksize)
+viachan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
{
struct via_chinfo *ch = data;
@@ -559,7 +343,7 @@ viachan_setblocksize(void *data, u_int32_t blocksize)
}
static int
-viachan_trigger(void *data, int go)
+viachan_trigger(kobj_t obj, void *data, int go)
{
struct via_chinfo *ch = data;
struct via_info *via = ch->parent;
@@ -600,7 +384,7 @@ DEB(printf("viachan_trigger: go=%d\n", go));
}
static int
-viachan_getptr(void *data)
+viachan_getptr(kobj_t obj, void *data)
{
struct via_chinfo *ch = data;
struct via_info *via = ch->parent;
@@ -658,12 +442,27 @@ DEB(printf("return ptr=%d\n", ptr));
}
static pcmchan_caps *
-viachan_getcaps(void *data)
+viachan_getcaps(kobj_t obj, void *data)
{
struct via_chinfo *ch = data;
return (ch->dir == PCMDIR_PLAY) ? &via_playcaps : &via_reccaps;
}
+static kobj_method_t viachan_methods[] = {
+ KOBJMETHOD(channel_init, viachan_init),
+ KOBJMETHOD(channel_setdir, viachan_setdir),
+ KOBJMETHOD(channel_setformat, viachan_setformat),
+ KOBJMETHOD(channel_setspeed, viachan_setspeed),
+ KOBJMETHOD(channel_setblocksize, viachan_setblocksize),
+ KOBJMETHOD(channel_trigger, viachan_trigger),
+ KOBJMETHOD(channel_getptr, viachan_getptr),
+ KOBJMETHOD(channel_getcaps, viachan_getcaps),
+ { 0, 0 }
+};
+CHANNEL_DECLARE(viachan);
+
+/* -------------------------------------------------------------------- */
+
static void
via_intr(void *p)
{
@@ -686,4 +485,193 @@ DEB(printf("viachan_intr\n"));
}
}
+/*
+ * Probe and attach the card
+ */
+static int
+via_probe(device_t dev)
+{
+ if (pci_get_devid(dev) == VIA_PCI_ID) {
+ device_set_desc(dev, "VIA VT82C686A AC'97 Audio");
+ return 0;
+ }
+ return ENXIO;
+}
+
+
+void dma_cb(void *p, bus_dma_segment_t *bds, int a, int b)
+{
+}
+
+
+static int
+via_attach(device_t dev)
+{
+ struct via_info *via = 0;
+ struct ac97_info *codec = 0;
+ char status[SND_STATUSLEN];
+
+ u_int32_t data;
+
+ u_int16_t v;
+ bus_dmamap_t sgd_dma_map;
+
+ if ((via = malloc(sizeof *via, M_DEVBUF, M_NOWAIT)) == NULL) {
+ device_printf(dev, "cannot allocate softc\n");
+ return ENXIO;
+ }
+ bzero(via, sizeof *via);
+
+ /* Get resources */
+ data = pci_read_config(dev, PCIR_COMMAND, 2);
+ data |= (PCIM_CMD_PORTEN | PCIM_CMD_BUSMASTEREN);
+ pci_write_config(dev, PCIR_COMMAND, data, 2);
+ data = pci_read_config(dev, PCIR_COMMAND, 2);
+
+ pci_write_config(dev, VIA_PCICONF_MISC,
+ VIA_PCICONF_ACLINKENAB | VIA_PCICONF_ACSGD |
+ VIA_PCICONF_ACNOTRST | VIA_PCICONF_ACVSR, 1);
+
+ via->regid = PCIR_MAPS;
+ via->reg = bus_alloc_resource(dev, SYS_RES_IOPORT, &via->regid,
+ 0, ~0, 1, RF_ACTIVE);
+ if (!via->reg) {
+ device_printf(dev, "via: Cannot allocate bus resource.");
+ goto bad;
+ }
+ via->st = rman_get_bustag(via->reg);
+ via->sh = rman_get_bushandle(via->reg);
+
+ via->irqid = 0;
+ via->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &via->irqid,
+ 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE);
+ if (!via->irq
+ || bus_setup_intr(dev, via->irq, INTR_TYPE_TTY, via_intr, via, &via->ih)){
+ device_printf(dev, "unable to map interrupt\n");
+ goto bad;
+ }
+
+ via_wr(via, VIA_PLAY_MODE,
+ VIA_RPMODE_AUTOSTART |
+ VIA_RPMODE_INTR_FLAG | VIA_RPMODE_INTR_EOL, 1);
+ via_wr(via, VIA_RECORD_MODE,
+ VIA_RPMODE_AUTOSTART |
+ VIA_RPMODE_INTR_FLAG | VIA_RPMODE_INTR_EOL, 1);
+
+ codec = AC97_CREATE(dev, via, via_ac97);
+ if (!codec) goto bad;
+
+ mixer_init(dev, ac97_getmixerclass(), codec);
+
+ /*
+ * The mixer init resets the codec. So enabling VRA must be done
+ * afterwards.
+ */
+ v = via_read_codec(NULL, via, AC97_REG_EXT_AUDIO_ID);
+ v &= (AC97_ENAB_VRA | AC97_ENAB_MICVRA);
+ via_write_codec(NULL, via, AC97_REG_EXT_AUDIO_STAT, v);
+ via->codec_caps = v;
+ {
+ v = via_read_codec(NULL, via, AC97_REG_EXT_AUDIO_STAT);
+ DEB(printf("init: codec stat: %d\n", v));
+ }
+
+ if (!(v & AC97_CODEC_DOES_VRA)) {
+ /* no VRA => can do only 48 kbps */
+ via_playcaps.minspeed = 48000;
+ via_reccaps.minspeed = 48000;
+ }
+
+ /* DMA tag for buffers */
+ if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0,
+ /*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
+ /*highaddr*/BUS_SPACE_MAXADDR,
+ /*filter*/NULL, /*filterarg*/NULL,
+ /*maxsize*/VIA_BUFFSIZE, /*nsegments*/1, /*maxsegz*/0x3ffff,
+ /*flags*/0, &via->parent_dmat) != 0) {
+ device_printf(dev, "unable to create dma tag\n");
+ goto bad;
+ }
+
+ /*
+ * DMA tag for SGD table. The 686 uses scatter/gather DMA and
+ * requires a list in memory of work to do. We need only 16 bytes
+ * for this list, and it is wasteful to allocate 16K.
+ */
+ if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0,
+ /*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
+ /*highaddr*/BUS_SPACE_MAXADDR,
+ /*filter*/NULL, /*filterarg*/NULL,
+ /*maxsize*/NSEGS * sizeof(struct via_dma_op),
+ /*nsegments*/1, /*maxsegz*/0x3ffff,
+ /*flags*/0, &via->sgd_dmat) != 0) {
+ device_printf(dev, "unable to create dma tag\n");
+ goto bad;
+ }
+
+ if (bus_dmamem_alloc(via->sgd_dmat, (void **)&via->sgd_table,
+ BUS_DMA_NOWAIT, &sgd_dma_map) == -1) goto bad;
+ if (bus_dmamap_load(via->sgd_dmat, sgd_dma_map, via->sgd_table,
+ NSEGS * sizeof(struct via_dma_op), dma_cb, 0, 0)) goto bad;
+
+ snprintf(status, SND_STATUSLEN, "at io 0x%lx irq %ld",
+ rman_get_start(via->reg), rman_get_start(via->irq));
+
+ /* Register */
+ if (pcm_register(dev, via, 1, 1)) goto bad;
+ pcm_addchan(dev, PCMDIR_PLAY, &viachan_class, via);
+ pcm_addchan(dev, PCMDIR_REC, &viachan_class, via);
+ pcm_setstatus(dev, status);
+ return 0;
+bad:
+ if (codec) ac97_destroy(codec);
+ if (via->reg) bus_release_resource(dev, SYS_RES_IOPORT, via->regid, via->reg);
+ if (via->ih) bus_teardown_intr(dev, via->irq, via->ih);
+ if (via->irq) bus_release_resource(dev, SYS_RES_IRQ, via->irqid, via->irq);
+ if (via->parent_dmat) bus_dma_tag_destroy(via->parent_dmat);
+ if (via->sgd_dmat) bus_dma_tag_destroy(via->sgd_dmat);
+ if (via) free(via, M_DEVBUF);
+ return ENXIO;
+}
+
+static int
+via_detach(device_t dev)
+{
+ int r;
+ struct via_info *via = 0;
+
+ r = pcm_unregister(dev);
+ if (r)
+ return r;
+
+ via = pcm_getdevinfo(dev);
+ bus_release_resource(dev, SYS_RES_IOPORT, via->regid, via->reg);
+ bus_teardown_intr(dev, via->irq, via->ih);
+ bus_release_resource(dev, SYS_RES_IRQ, via->irqid, via->irq);
+ bus_dma_tag_destroy(via->parent_dmat);
+ bus_dma_tag_destroy(via->sgd_dmat);
+ free(via, M_DEVBUF);
+ return 0;
+}
+
+
+static device_method_t via_methods[] = {
+ DEVMETHOD(device_probe, via_probe),
+ DEVMETHOD(device_attach, via_attach),
+ DEVMETHOD(device_detach, via_detach),
+ { 0, 0}
+};
+
+static driver_t via_driver = {
+ "pcm",
+ via_methods,
+ sizeof(snddev_info),
+};
+
+static devclass_t pcm_devclass;
+
+DRIVER_MODULE(via, pci, via_driver, pcm_devclass, 0, 0);
+MODULE_DEPEND(via, snd_pcm, PCM_MINVER, PCM_PREFVER, PCM_MAXVER);
+MODULE_VERSION(via, 1);
+
OpenPOWER on IntegriCloud