diff options
author | brian <brian@FreeBSD.org> | 1998-12-10 18:36:10 +0000 |
---|---|---|
committer | brian <brian@FreeBSD.org> | 1998-12-10 18:36:10 +0000 |
commit | 578a7c33753075a3c31c8ceee8d4af48b7ac0c5e (patch) | |
tree | e831792bcb226b180845f726c2300135d9bcc4f8 /sys/dev/sound/isa/sb8.c | |
parent | 8bc6574c8b2435450ac1c5a7d5ed19fa01a91f64 (diff) | |
download | FreeBSD-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.c | 133 |
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 */ |