summaryrefslogtreecommitdiffstats
path: root/sys/dev/sound/isa/sb8.c
diff options
context:
space:
mode:
authorbrian <brian@FreeBSD.org>1998-12-10 18:36:10 +0000
committerbrian <brian@FreeBSD.org>1998-12-10 18:36:10 +0000
commit578a7c33753075a3c31c8ceee8d4af48b7ac0c5e (patch)
treee831792bcb226b180845f726c2300135d9bcc4f8 /sys/dev/sound/isa/sb8.c
parent8bc6574c8b2435450ac1c5a7d5ed19fa01a91f64 (diff)
downloadFreeBSD-src-578a7c33753075a3c31c8ceee8d4af48b7ac0c5e.zip
FreeBSD-src-578a7c33753075a3c31c8ceee8d4af48b7ac0c5e.tar.gz
Support ESS1868 (and probably ESS688 & ESS1668).
Submitted by: Max Khon <fjoe@husky.iclub.nsu.ru>
Diffstat (limited to 'sys/dev/sound/isa/sb8.c')
-rw-r--r--sys/dev/sound/isa/sb8.c133
1 files changed, 93 insertions, 40 deletions
diff --git a/sys/dev/sound/isa/sb8.c b/sys/dev/sound/isa/sb8.c
index 06599ec..4bd5825 100644
--- a/sys/dev/sound/isa/sb8.c
+++ b/sys/dev/sound/isa/sb8.c
@@ -337,7 +337,7 @@ again:
/*
* the sb16 might have multiple sources etc.
*/
- if (d->bd_flags & BD_F_SB16 && (c & 3) )
+ if ((d->bd_flags & BD_F_SB16) && (c & 3))
goto again;
}
@@ -428,29 +428,63 @@ sb_callback(snddev_info *d, int reason)
d->dbuf_in.chan = d->dbuf_out.chan;
d->dbuf_out.chan = c ;
}
- } else if (d->bd_flags & BD_F_ESS) {
- u_char c ;
- if (d->play_fmt == 0) {
- /* initialize for record */
- static u_char cmd[] = {
- 0x51,0xd0,0x71,0xf4,0x51,0x98,0x71,0xbc
- };
- ess_write(d->io_base, 0xb8, 0x0e);
- c = ( ess_read(d->io_base, 0xa8) & 0xfc ) | 1 ;
- if (d->flags & SND_F_STEREO)
- c++ ;
- ess_write(d->io_base, 0xa8, c);
- ess_write(d->io_base, 0xb9, 2); /* 4bytes/transfer */
- /*
- * set format in b6, b7
- */
- } else {
- /* initialize for play */
- static u_char cmd[] = {
- 0x80,0x51,0xd0,0x00,0x71,0xf4,
- 0x80,0x51,0x98,0x00,0x71,0xbc
- };
- }
+ }
+ else if (d->bd_flags & BD_F_ESS) {
+ u_char c;
+
+ DEB(printf("SND_CB_INIT, play_fmt == 0x%x, rec_fmt == 0x%x\n",
+ (int) d->play_fmt, (int) d->rec_fmt));
+
+ /* autoinit DMA mode */
+ if (d->play_fmt)
+ ess_write(d->io_base, 0xb8, 0x04);
+ else
+ ess_write(d->io_base, 0xb8, 0x0e);
+
+ c = (ess_read(d->io_base, 0xa8) & ~0x03) | 0x01;
+ if ((d->flags & SND_F_STEREO) == 0)
+ c++;
+ ess_write(d->io_base, 0xa8, c); /* select mono/stereo */
+ ess_write(d->io_base, 0xb9, 2); /* demand 4 bytes/transfer */
+
+ switch (d->play_fmt ? d->play_fmt : d->rec_fmt) {
+ case AFMT_S16_LE:
+ if (d->flags & SND_F_STEREO) {
+ /* 16 bit stereo */
+ if (d->play_fmt)
+ ess_write(d->io_base, 0xb6, 0x00);
+ ess_write(d->io_base, 0xb7, 0x71);
+ ess_write(d->io_base, 0xb7, 0xbc);
+ }
+ else {
+ /* 16 bit mono */
+ if (d->play_fmt)
+ ess_write(d->io_base, 0xb6, 0x00);
+ ess_write(d->io_base, 0xb7, 0x71);
+ ess_write(d->io_base, 0xb7, 0xf4);
+ }
+ break;
+ case AFMT_U8:
+ if (d->flags & SND_F_STEREO) {
+ /* 8 bit stereo */
+ if (d->play_fmt)
+ ess_write(d->io_base, 0xb6, 0x80);
+ ess_write(d->io_base, 0xb7, 0x51);
+ ess_write(d->io_base, 0xb7, 0x98);
+ }
+ else {
+ /* 8 bit mono */
+ if (d->play_fmt)
+ ess_write(d->io_base, 0xb6, 0x80);
+ ess_write(d->io_base, 0xb7, 0x51);
+ ess_write(d->io_base, 0xb7, 0xd0);
+ }
+ break;
+ }
+ ess_write(d->io_base, 0xb1,
+ ess_read(d->io_base, 0xb1) | 0x50);
+ ess_write(d->io_base, 0xb2,
+ ess_read(d->io_base, 0xb1) | 0x50);
}
reset_dbuf(& (d->dbuf_in), SND_CHAN_RD );
reset_dbuf(& (d->dbuf_out), SND_CHAN_WR );
@@ -512,10 +546,18 @@ sb_callback(snddev_info *d, int reason)
sb_cmd(d->io_base, c );
sb_cmd3(d->io_base, c1 , l - 1) ;
} else if (d->bd_flags & BD_F_ESS) {
- /* XXX this code is still incomplete */
- sb_cmd2(d->io_base, 0xb8, rd ? 4 : 0xe ) ; /* auto dma */
- sb_cmd2(d->io_base, 0xa8, d->flags & SND_F_STEREO ? 1 : 2) ;
- sb_cmd2(d->io_base, 0xb9, 2) ; /* demand dma */
+ u_long fmt = rd ? d->rec_fmt : d->play_fmt;
+
+ DEB(printf("SND_CB_START: %s (%d)\n", rd ? "rd" : "wr", l));
+ if (fmt == AFMT_S16_LE)
+ l >>= 1;
+ l--;
+ if (!rd)
+ sb_cmd(d->io_base, DSP_CMD_SPKON);
+ ess_write(d->io_base, 0xa4, l);
+ ess_write(d->io_base, 0xa5, l >> 8);
+ ess_write(d->io_base, 0xb8,
+ ess_read(d->io_base, 0xb8) | (rd ? 0x0f : 0x05));
} else { /* SBPro -- stereo not supported */
u_char c ;
if (!rd)
@@ -546,6 +588,7 @@ sb_callback(snddev_info *d, int reason)
case SND_CB_STOP :
{
int cmd = DSP_CMD_DMAPAUSE_8 ; /* default: halt 8 bit chan */
+ DEB(printf("SND_CB_XXX: reason 0x%x\n", reason));
if ( b->chan > 4
|| (rd && d->rec_fmt == AFMT_S16_LE)
|| (!rd && d->play_fmt == AFMT_S16_LE)
@@ -722,14 +765,22 @@ sb_dsp_init(snddev_info *d, struct isa_device *dev)
/* the ESS488 can be treated as an SBPRO */
printf("ESS488 (rev %d)\n", ess_minor & 0x0f);
break ;
- } else if (ess_major == 0x68 && (ess_minor & 0xf0) == 0x80) {
- int rev = ess_minor & 0xf ;
- if ( rev >= 8 )
- printf("ESS1868 (rev %d)\n", rev);
- else
- printf("ESS688 (rev %d)\n", rev);
- /* d->audio_fmt |= AFMT_S16_LE; */ /* not yet... */
- break ; /* XXX */
+ }
+ else if (ess_major == 0x68 && (ess_minor & 0xf0) == 0x80) {
+ u_char cfg;
+ u_char bits;
+ int rev = ess_minor & 0xf;
+
+ if (rev >= 8)
+ printf("ESS1868 (rev %d)\n", rev);
+ else
+ printf("ESS688 (rev %d)\n", rev);
+ d->bd_flags |= BD_F_ESS;
+ d->audio_fmt |= AFMT_S16_LE;
+
+ /* enable extended ESS mode */
+ sb_cmd(d->io_base, 0xc6);
+ break;
} else {
printf("Unknown card 0x%x 0x%x -- hope it is SBPRO\n",
ess_major, ess_minor);
@@ -831,9 +882,9 @@ sb_setmixer(int io_base, u_int port, u_int value)
u_long flags;
flags = spltty();
- outb(io_base + 4, (u_char) (port & 0xff)); /* Select register */
+ outb(io_base + SB_MIX_ADDR, (u_char) (port & 0xff)); /* Select register */
DELAY(10);
- outb(io_base + 5, (u_char) (value & 0xff));
+ outb(io_base + SB_MIX_DATA, (u_char) (value & 0xff));
DELAY(10);
splx(flags);
}
@@ -1210,10 +1261,12 @@ ess1868_attach(u_long csn, u_long vend_id, char *name,
dev->id_drq = d.drq[0] ; /* primary dma */
dev->id_irq = (1 << d.irq[0] ) ;
- dev->id_intr = pcmintr ;
+ dev->id_intr = (inthand2_t *)pcmintr ;
dev->id_flags = 0 /* DV_F_DUAL_DMA | (d.drq[1] ) */;
+#if 0
snddev_last_probed->probe(dev); /* not really necessary but doesn't harm */
+#endif
pcmattach(dev);
}
@@ -1291,7 +1344,7 @@ sb16pnp_attach(u_long csn, u_long vend_id, char *name,
dev->id_drq = d.drq[0] ; /* primary dma */
dev->id_irq = (1 << d.irq[0] ) ;
- dev->id_intr = pcmintr ;
+ dev->id_intr = (inthand2_t *)pcmintr ;
dev->id_flags = DV_F_DUAL_DMA | (d.drq[1] ) ;
pcm_info[dev->id_unit] = tmp_d; /* pcm_info[] will be reinitialized after */
OpenPOWER on IntegriCloud