1139749Simp/*- 274711Scg * Copyright (c) 2001 George Reid <greid@ukug.uk.freebsd.org> 3119853Scg * Copyright (c) 1999 Cameron Grant <cg@freebsd.org> 4166426Sjoel * Copyright (c) 1997,1998 Luigi Rizzo 5166426Sjoel * Copyright (c) 1994,1995 Hannu Savolainen 650723Scg * All rights reserved. 750723Scg * 829415Sjmg * Redistribution and use in source and binary forms, with or without 929415Sjmg * modification, are permitted provided that the following conditions 1030869Sjmg * are met: 1130869Sjmg * 1. Redistributions of source code must retain the above copyright 1230869Sjmg * notice, this list of conditions and the following disclaimer. 1330869Sjmg * 2. Redistributions in binary form must reproduce the above copyright 1450723Scg * notice, this list of conditions and the following disclaimer in the 1550723Scg * documentation and/or other materials provided with the distribution. 1630869Sjmg * 1750723Scg * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1850723Scg * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1950723Scg * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2050723Scg * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2150723Scg * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2250723Scg * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2350723Scg * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2450723Scg * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2550723Scg * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2650723Scg * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2750723Scg * SUCH DAMAGE. 2829415Sjmg */ 2929415Sjmg 30193640Sariff#ifdef HAVE_KERNEL_OPTION_HEADERS 31193640Sariff#include "opt_snd.h" 32193640Sariff#endif 33193640Sariff 3453465Scg#include <dev/sound/pcm/sound.h> 3550723Scg 3682180ScgSND_DECLARE_FILE("$FreeBSD: releng/10.3/sys/dev/sound/isa/mss.c 193640 2009-06-07 19:12:08Z ariff $"); 3782180Scg 3850723Scg/* board-specific include files */ 3953465Scg#include <dev/sound/isa/mss.h> 4090241Stg#include <dev/sound/isa/sb.h> 4153553Stanimura#include <dev/sound/chip.h> 4229415Sjmg 43110499Snyan#include <isa/isavar.h> 44110499Snyan 4570134Scg#include "mixer_if.h" 4670134Scg 4783619Scg#define MSS_DEFAULT_BUFSZ (4096) 4864032Scg#define MSS_INDEXED_REGS 0x20 4964032Scg#define OPL_INDEXED_REGS 0x19 5053512Scg 5150723Scgstruct mss_info; 5229415Sjmg 5350723Scgstruct mss_chinfo { 5450723Scg struct mss_info *parent; 5574763Scg struct pcm_channel *channel; 5674763Scg struct snd_dbuf *buffer; 5750723Scg int dir; 5870291Scg u_int32_t fmt, blksz; 5950723Scg}; 6029415Sjmg 6150723Scgstruct mss_info { 6250723Scg struct resource *io_base; /* primary I/O address for the board */ 6350723Scg int io_rid; 6450723Scg struct resource *conf_base; /* and the opti931 also has a config space */ 6550723Scg int conf_rid; 6650723Scg struct resource *irq; 6750723Scg int irq_rid; 6850723Scg struct resource *drq1; /* play */ 6950723Scg int drq1_rid; 7050723Scg struct resource *drq2; /* rec */ 7150723Scg int drq2_rid; 7265644Scg void *ih; 7350723Scg bus_dma_tag_t parent_dmat; 74107285Scg struct mtx *lock; 7529415Sjmg 7664032Scg char mss_indexed_regs[MSS_INDEXED_REGS]; 7764032Scg char opl_indexed_regs[OPL_INDEXED_REGS]; 7850723Scg int bd_id; /* used to hold board-id info, eg. sb version, 7950723Scg * mss codec type, etc. etc. 8050723Scg */ 8152169Sdfr int opti_offset; /* offset from config_base for opti931 */ 8250723Scg u_long bd_flags; /* board-specific flags */ 8374711Scg int optibase; /* base address for OPTi9xx config */ 8474711Scg struct resource *indir; /* Indirect register index address */ 8574711Scg int indir_rid; 8674711Scg int password; /* password for opti9xx cards */ 8774711Scg int passwdreg; /* password register */ 8883619Scg unsigned int bufsize; 8950723Scg struct mss_chinfo pch, rch; 9050723Scg}; 9129415Sjmg 9250723Scgstatic int mss_probe(device_t dev); 9350723Scgstatic int mss_attach(device_t dev); 9429415Sjmg 9550723Scgstatic driver_intr_t mss_intr; 9629415Sjmg 9750723Scg/* prototypes for local functions */ 9850723Scgstatic int mss_detect(device_t dev, struct mss_info *mss); 99150014Simp#ifndef PC98 10074711Scgstatic int opti_detect(device_t dev, struct mss_info *mss); 101150014Simp#endif 10250723Scgstatic char *ymf_test(device_t dev, struct mss_info *mss); 10350723Scgstatic void ad_unmute(struct mss_info *mss); 10442284Sluigi 10550723Scg/* mixer set funcs */ 10650723Scgstatic int mss_mixer_set(struct mss_info *mss, int dev, int left, int right); 10750723Scgstatic int mss_set_recsrc(struct mss_info *mss, int mask); 10850723Scg 10950723Scg/* io funcs */ 11050723Scgstatic int ad_wait_init(struct mss_info *mss, int x); 11150723Scgstatic int ad_read(struct mss_info *mss, int reg); 11250723Scgstatic void ad_write(struct mss_info *mss, int reg, u_char data); 11350723Scgstatic void ad_write_cnt(struct mss_info *mss, int reg, u_short data); 11457770Scgstatic void ad_enter_MCE(struct mss_info *mss); 11557770Scgstatic void ad_leave_MCE(struct mss_info *mss); 11650723Scg 11774711Scg/* OPTi-specific functions */ 11874711Scgstatic void opti_write(struct mss_info *mss, u_char reg, 11974711Scg u_char data); 120150038Snyan#ifndef PC98 12174711Scgstatic u_char opti_read(struct mss_info *mss, u_char reg); 122150038Snyan#endif 12374711Scgstatic int opti_init(device_t dev, struct mss_info *mss); 12474711Scg 12550723Scg/* io primitives */ 12650723Scgstatic void conf_wr(struct mss_info *mss, u_char reg, u_char data); 12750723Scgstatic u_char conf_rd(struct mss_info *mss, u_char reg); 12850723Scg 12950723Scgstatic int pnpmss_probe(device_t dev); 13050723Scgstatic int pnpmss_attach(device_t dev); 13150723Scg 13250723Scgstatic driver_intr_t opti931_intr; 13342284Sluigi 13464881Scgstatic u_int32_t mss_fmt[] = { 135193640Sariff SND_FORMAT(AFMT_U8, 1, 0), 136193640Sariff SND_FORMAT(AFMT_U8, 2, 0), 137193640Sariff SND_FORMAT(AFMT_S16_LE, 1, 0), 138193640Sariff SND_FORMAT(AFMT_S16_LE, 2, 0), 139193640Sariff SND_FORMAT(AFMT_MU_LAW, 1, 0), 140193640Sariff SND_FORMAT(AFMT_MU_LAW, 2, 0), 141193640Sariff SND_FORMAT(AFMT_A_LAW, 1, 0), 142193640Sariff SND_FORMAT(AFMT_A_LAW, 2, 0), 14364881Scg 0 14450723Scg}; 14574763Scgstatic struct pcmchan_caps mss_caps = {4000, 48000, mss_fmt, 0}; 14629415Sjmg 14764881Scgstatic u_int32_t guspnp_fmt[] = { 148193640Sariff SND_FORMAT(AFMT_U8, 1, 0), 149193640Sariff SND_FORMAT(AFMT_U8, 2, 0), 150193640Sariff SND_FORMAT(AFMT_S16_LE, 1, 0), 151193640Sariff SND_FORMAT(AFMT_S16_LE, 2, 0), 152193640Sariff SND_FORMAT(AFMT_A_LAW, 1, 0), 153193640Sariff SND_FORMAT(AFMT_A_LAW, 2, 0), 15464881Scg 0 15550723Scg}; 15674763Scgstatic struct pcmchan_caps guspnp_caps = {4000, 48000, guspnp_fmt, 0}; 15750723Scg 15864881Scgstatic u_int32_t opti931_fmt[] = { 159193640Sariff SND_FORMAT(AFMT_U8, 1, 0), 160193640Sariff SND_FORMAT(AFMT_U8, 2, 0), 161193640Sariff SND_FORMAT(AFMT_S16_LE, 1, 0), 162193640Sariff SND_FORMAT(AFMT_S16_LE, 2, 0), 16364881Scg 0 16450723Scg}; 16574763Scgstatic struct pcmchan_caps opti931_caps = {4000, 48000, opti931_fmt, 0}; 16650723Scg 16750723Scg#define MD_AD1848 0x91 16850723Scg#define MD_AD1845 0x92 16954962Speter#define MD_CS42XX 0xA1 170108925Smdodd#define MD_CS423X 0xA2 17174711Scg#define MD_OPTI930 0xB0 17250723Scg#define MD_OPTI931 0xB1 17350723Scg#define MD_OPTI925 0xB2 17474711Scg#define MD_OPTI924 0xB3 17550723Scg#define MD_GUSPNP 0xB8 17653553Stanimura#define MD_GUSMAX 0xB9 17750723Scg#define MD_YM0020 0xC1 17850723Scg#define MD_VIVO 0xD1 17950723Scg 18050723Scg#define DV_F_TRUE_MSS 0x00010000 /* mss _with_ base regs */ 18150723Scg 18250723Scg#define FULL_DUPLEX(x) ((x)->bd_flags & BD_F_DUPLEX) 18350723Scg 18474763Scgstatic void 18574763Scgmss_lock(struct mss_info *mss) 18674763Scg{ 18774788Scg snd_mtxlock(mss->lock); 18874763Scg} 18974763Scg 19074763Scgstatic void 19174763Scgmss_unlock(struct mss_info *mss) 19274763Scg{ 19374788Scg snd_mtxunlock(mss->lock); 19474763Scg} 19574763Scg 19650723Scgstatic int 19750723Scgport_rd(struct resource *port, int off) 19850723Scg{ 19950723Scg if (port) 20050723Scg return bus_space_read_1(rman_get_bustag(port), 20150723Scg rman_get_bushandle(port), 20250723Scg off); 20350723Scg else 20450723Scg return -1; 20550723Scg} 20650723Scg 20750723Scgstatic void 20850723Scgport_wr(struct resource *port, int off, u_int8_t data) 20950723Scg{ 21050723Scg if (port) 211108064Ssemenu bus_space_write_1(rman_get_bustag(port), 212108064Ssemenu rman_get_bushandle(port), 213108064Ssemenu off, data); 21450723Scg} 21550723Scg 21650723Scgstatic int 21750723Scgio_rd(struct mss_info *mss, int reg) 21850723Scg{ 21950723Scg if (mss->bd_flags & BD_F_MSS_OFFSET) reg -= 4; 22050723Scg return port_rd(mss->io_base, reg); 22150723Scg} 22250723Scg 22350723Scgstatic void 22450723Scgio_wr(struct mss_info *mss, int reg, u_int8_t data) 22550723Scg{ 22650723Scg if (mss->bd_flags & BD_F_MSS_OFFSET) reg -= 4; 227108064Ssemenu port_wr(mss->io_base, reg, data); 22850723Scg} 22950723Scg 23050723Scgstatic void 23150723Scgconf_wr(struct mss_info *mss, u_char reg, u_char value) 23250723Scg{ 23350723Scg port_wr(mss->conf_base, 0, reg); 23450723Scg port_wr(mss->conf_base, 1, value); 23550723Scg} 23650723Scg 23750723Scgstatic u_char 23850723Scgconf_rd(struct mss_info *mss, u_char reg) 23950723Scg{ 24050723Scg port_wr(mss->conf_base, 0, reg); 24150723Scg return port_rd(mss->conf_base, 1); 24250723Scg} 24350723Scg 24452169Sdfrstatic void 24552169Sdfropti_wr(struct mss_info *mss, u_char reg, u_char value) 24652169Sdfr{ 24752169Sdfr port_wr(mss->conf_base, mss->opti_offset + 0, reg); 24852169Sdfr port_wr(mss->conf_base, mss->opti_offset + 1, value); 24952169Sdfr} 25052169Sdfr 25152169Sdfrstatic u_char 25252169Sdfropti_rd(struct mss_info *mss, u_char reg) 25352169Sdfr{ 25452169Sdfr port_wr(mss->conf_base, mss->opti_offset + 0, reg); 25552169Sdfr return port_rd(mss->conf_base, mss->opti_offset + 1); 25652169Sdfr} 25752169Sdfr 25850723Scgstatic void 25950723Scggus_wr(struct mss_info *mss, u_char reg, u_char value) 26050723Scg{ 26150723Scg port_wr(mss->conf_base, 3, reg); 26250723Scg port_wr(mss->conf_base, 5, value); 26350723Scg} 26450723Scg 26550723Scgstatic u_char 26650723Scggus_rd(struct mss_info *mss, u_char reg) 26750723Scg{ 26850723Scg port_wr(mss->conf_base, 3, reg); 26950723Scg return port_rd(mss->conf_base, 5); 27050723Scg} 27150723Scg 27250723Scgstatic void 27350723Scgmss_release_resources(struct mss_info *mss, device_t dev) 27450723Scg{ 27550723Scg if (mss->irq) { 27665644Scg if (mss->ih) 27765644Scg bus_teardown_intr(dev, mss->irq, mss->ih); 27865644Scg bus_release_resource(dev, SYS_RES_IRQ, mss->irq_rid, 27950723Scg mss->irq); 28050723Scg mss->irq = 0; 28150723Scg } 28284112Scg if (mss->drq2) { 28384112Scg if (mss->drq2 != mss->drq1) { 28484112Scg isa_dma_release(rman_get_start(mss->drq2)); 28584112Scg bus_release_resource(dev, SYS_RES_DRQ, mss->drq2_rid, 28684112Scg mss->drq2); 28784112Scg } 28870291Scg mss->drq2 = 0; 28970291Scg } 29070291Scg if (mss->drq1) { 29184112Scg isa_dma_release(rman_get_start(mss->drq1)); 29250723Scg bus_release_resource(dev, SYS_RES_DRQ, mss->drq1_rid, 29350723Scg mss->drq1); 29450723Scg mss->drq1 = 0; 29550723Scg } 29670291Scg if (mss->io_base) { 29750723Scg bus_release_resource(dev, SYS_RES_IOPORT, mss->io_rid, 29850723Scg mss->io_base); 29950723Scg mss->io_base = 0; 30050723Scg } 30150723Scg if (mss->conf_base) { 30250723Scg bus_release_resource(dev, SYS_RES_IOPORT, mss->conf_rid, 30350723Scg mss->conf_base); 30450723Scg mss->conf_base = 0; 30550723Scg } 30674789Scg if (mss->indir) { 30774789Scg bus_release_resource(dev, SYS_RES_IOPORT, mss->indir_rid, 30874789Scg mss->indir); 30974789Scg mss->indir = 0; 31074789Scg } 31165644Scg if (mss->parent_dmat) { 31265644Scg bus_dma_tag_destroy(mss->parent_dmat); 31365644Scg mss->parent_dmat = 0; 31465644Scg } 31574763Scg if (mss->lock) snd_mtxfree(mss->lock); 31674763Scg 31765644Scg free(mss, M_DEVBUF); 31850723Scg} 31950723Scg 32050723Scgstatic int 32150723Scgmss_alloc_resources(struct mss_info *mss, device_t dev) 32250723Scg{ 32370291Scg int pdma, rdma, ok = 1; 32450723Scg if (!mss->io_base) 325127135Snjl mss->io_base = bus_alloc_resource_any(dev, SYS_RES_IOPORT, 326127135Snjl &mss->io_rid, RF_ACTIVE); 32750723Scg if (!mss->irq) 328127135Snjl mss->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, 329127135Snjl &mss->irq_rid, RF_ACTIVE); 33050723Scg if (!mss->drq1) 331127135Snjl mss->drq1 = bus_alloc_resource_any(dev, SYS_RES_DRQ, 332127135Snjl &mss->drq1_rid, 333127135Snjl RF_ACTIVE); 33450723Scg if (mss->conf_rid >= 0 && !mss->conf_base) 335127135Snjl mss->conf_base = bus_alloc_resource_any(dev, SYS_RES_IOPORT, 336127135Snjl &mss->conf_rid, 337127135Snjl RF_ACTIVE); 33850723Scg if (mss->drq2_rid >= 0 && !mss->drq2) 339127135Snjl mss->drq2 = bus_alloc_resource_any(dev, SYS_RES_DRQ, 340127135Snjl &mss->drq2_rid, 341127135Snjl RF_ACTIVE); 34250723Scg 34374711Scg if (!mss->io_base || !mss->drq1 || !mss->irq) ok = 0; 34474711Scg if (mss->conf_rid >= 0 && !mss->conf_base) ok = 0; 34574711Scg if (mss->drq2_rid >= 0 && !mss->drq2) ok = 0; 34650723Scg 34750723Scg if (ok) { 34870291Scg pdma = rman_get_start(mss->drq1); 34970291Scg isa_dma_acquire(pdma); 35083619Scg isa_dmainit(pdma, mss->bufsize); 35150723Scg mss->bd_flags &= ~BD_F_DUPLEX; 35250723Scg if (mss->drq2) { 35370291Scg rdma = rman_get_start(mss->drq2); 35470291Scg isa_dma_acquire(rdma); 35583619Scg isa_dmainit(rdma, mss->bufsize); 35650723Scg mss->bd_flags |= BD_F_DUPLEX; 35770291Scg } else mss->drq2 = mss->drq1; 35850723Scg } 35950723Scg return ok; 36050723Scg} 36150723Scg 36274763Scg/* 36374763Scg * The various mixers use a variety of bitmasks etc. The Voxware 36474763Scg * driver had a very nice technique to describe a mixer and interface 36574763Scg * to it. A table defines, for each channel, which register, bits, 36674763Scg * offset, polarity to use. This procedure creates the new value 36774763Scg * using the table and the old value. 36874763Scg */ 36974763Scg 37074763Scgstatic void 37174763Scgchange_bits(mixer_tab *t, u_char *regval, int dev, int chn, int newval) 37274763Scg{ 37374763Scg u_char mask; 37474763Scg int shift; 37574763Scg 37674763Scg DEB(printf("ch_bits dev %d ch %d val %d old 0x%02x " 37774763Scg "r %d p %d bit %d off %d\n", 37874763Scg dev, chn, newval, *regval, 37974763Scg (*t)[dev][chn].regno, (*t)[dev][chn].polarity, 38074763Scg (*t)[dev][chn].nbits, (*t)[dev][chn].bitoffs ) ); 38174763Scg 38274763Scg if ( (*t)[dev][chn].polarity == 1) /* reverse */ 38374763Scg newval = 100 - newval ; 38474763Scg 38574763Scg mask = (1 << (*t)[dev][chn].nbits) - 1; 38674763Scg newval = (int) ((newval * mask) + 50) / 100; /* Scale it */ 38774763Scg shift = (*t)[dev][chn].bitoffs /*- (*t)[dev][LEFT_CHN].nbits + 1*/; 38874763Scg 38974763Scg *regval &= ~(mask << shift); /* Filter out the previous value */ 39074763Scg *regval |= (newval & mask) << shift; /* Set the new value */ 39174763Scg} 39274763Scg 39370134Scg/* -------------------------------------------------------------------- */ 39470134Scg/* only one source can be set... */ 39570134Scgstatic int 39670134Scgmss_set_recsrc(struct mss_info *mss, int mask) 39770134Scg{ 39870134Scg u_char recdev; 39970134Scg 40070134Scg switch (mask) { 40170134Scg case SOUND_MASK_LINE: 40270134Scg case SOUND_MASK_LINE3: 40370134Scg recdev = 0; 40470134Scg break; 40570134Scg 40670134Scg case SOUND_MASK_CD: 40770134Scg case SOUND_MASK_LINE1: 40870134Scg recdev = 0x40; 40970134Scg break; 41070134Scg 41170134Scg case SOUND_MASK_IMIX: 41270134Scg recdev = 0xc0; 41370134Scg break; 41470134Scg 41570134Scg case SOUND_MASK_MIC: 41670134Scg default: 41770134Scg mask = SOUND_MASK_MIC; 41870134Scg recdev = 0x80; 41970134Scg } 42070134Scg ad_write(mss, 0, (ad_read(mss, 0) & 0x3f) | recdev); 42170134Scg ad_write(mss, 1, (ad_read(mss, 1) & 0x3f) | recdev); 42270134Scg return mask; 42370134Scg} 42470134Scg 42570134Scg/* there are differences in the mixer depending on the actual sound card. */ 42670134Scgstatic int 42770134Scgmss_mixer_set(struct mss_info *mss, int dev, int left, int right) 42870134Scg{ 42970134Scg int regoffs; 43074711Scg mixer_tab *mix_d; 43170134Scg u_char old, val; 43270134Scg 43374711Scg switch (mss->bd_id) { 43474711Scg case MD_OPTI931: 43574711Scg mix_d = &opti931_devices; 43674711Scg break; 43774711Scg case MD_OPTI930: 43874711Scg mix_d = &opti930_devices; 43974711Scg break; 44074711Scg default: 44174711Scg mix_d = &mix_devices; 44274711Scg } 44374711Scg 44470134Scg if ((*mix_d)[dev][LEFT_CHN].nbits == 0) { 44570134Scg DEB(printf("nbits = 0 for dev %d\n", dev)); 44670134Scg return -1; 44770134Scg } 44870134Scg 44970134Scg if ((*mix_d)[dev][RIGHT_CHN].nbits == 0) right = left; /* mono */ 45070134Scg 45170134Scg /* Set the left channel */ 45270134Scg 45370134Scg regoffs = (*mix_d)[dev][LEFT_CHN].regno; 45470134Scg old = val = ad_read(mss, regoffs); 45570134Scg /* if volume is 0, mute chan. Otherwise, unmute. */ 45670134Scg if (regoffs != 0) val = (left == 0)? old | 0x80 : old & 0x7f; 45770134Scg change_bits(mix_d, &val, dev, LEFT_CHN, left); 45870134Scg ad_write(mss, regoffs, val); 45970134Scg 46070134Scg DEB(printf("LEFT: dev %d reg %d old 0x%02x new 0x%02x\n", 46170134Scg dev, regoffs, old, val)); 46270134Scg 46370134Scg if ((*mix_d)[dev][RIGHT_CHN].nbits != 0) { /* have stereo */ 46470134Scg /* Set the right channel */ 46570134Scg regoffs = (*mix_d)[dev][RIGHT_CHN].regno; 46670134Scg old = val = ad_read(mss, regoffs); 46770134Scg if (regoffs != 1) val = (right == 0)? old | 0x80 : old & 0x7f; 46870134Scg change_bits(mix_d, &val, dev, RIGHT_CHN, right); 46970134Scg ad_write(mss, regoffs, val); 47070134Scg 47170134Scg DEB(printf("RIGHT: dev %d reg %d old 0x%02x new 0x%02x\n", 47270134Scg dev, regoffs, old, val)); 47370134Scg } 47470134Scg return 0; /* success */ 47570134Scg} 47670134Scg 47770134Scg/* -------------------------------------------------------------------- */ 47870134Scg 47970134Scgstatic int 48074763Scgmssmix_init(struct snd_mixer *m) 48170134Scg{ 48270134Scg struct mss_info *mss = mix_getdevinfo(m); 48370134Scg 48470134Scg mix_setdevs(m, MODE2_MIXER_DEVICES); 48570134Scg mix_setrecdevs(m, MSS_REC_DEVICES); 48670134Scg switch(mss->bd_id) { 48774711Scg case MD_OPTI930: 48874711Scg mix_setdevs(m, OPTI930_MIXER_DEVICES); 48974711Scg break; 49074711Scg 49170134Scg case MD_OPTI931: 49270134Scg mix_setdevs(m, OPTI931_MIXER_DEVICES); 49374763Scg mss_lock(mss); 49470134Scg ad_write(mss, 20, 0x88); 49570134Scg ad_write(mss, 21, 0x88); 49674763Scg mss_unlock(mss); 49770134Scg break; 49870134Scg 49970134Scg case MD_AD1848: 50070134Scg mix_setdevs(m, MODE1_MIXER_DEVICES); 50170134Scg break; 50270134Scg 50370134Scg case MD_GUSPNP: 50470134Scg case MD_GUSMAX: 50570134Scg /* this is only necessary in mode 3 ... */ 50674763Scg mss_lock(mss); 50770134Scg ad_write(mss, 22, 0x88); 50870134Scg ad_write(mss, 23, 0x88); 50974763Scg mss_unlock(mss); 51070134Scg break; 51170134Scg } 51270134Scg return 0; 51370134Scg} 51470134Scg 51570134Scgstatic int 51674763Scgmssmix_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right) 51770134Scg{ 51870134Scg struct mss_info *mss = mix_getdevinfo(m); 51970134Scg 52074763Scg mss_lock(mss); 52170134Scg mss_mixer_set(mss, dev, left, right); 52274763Scg mss_unlock(mss); 52370134Scg 52470134Scg return left | (right << 8); 52570134Scg} 52670134Scg 527193640Sariffstatic u_int32_t 52874763Scgmssmix_setrecsrc(struct snd_mixer *m, u_int32_t src) 52970134Scg{ 53070134Scg struct mss_info *mss = mix_getdevinfo(m); 53170134Scg 53274763Scg mss_lock(mss); 53370134Scg src = mss_set_recsrc(mss, src); 53474763Scg mss_unlock(mss); 53570134Scg return src; 53670134Scg} 53770134Scg 53870134Scgstatic kobj_method_t mssmix_mixer_methods[] = { 53970134Scg KOBJMETHOD(mixer_init, mssmix_init), 54070134Scg KOBJMETHOD(mixer_set, mssmix_set), 54170134Scg KOBJMETHOD(mixer_setrecsrc, mssmix_setrecsrc), 542193640Sariff KOBJMETHOD_END 54370134Scg}; 54470134ScgMIXER_DECLARE(mssmix_mixer); 54570134Scg 54670134Scg/* -------------------------------------------------------------------- */ 54770134Scg 54870134Scgstatic int 54974763Scgymmix_init(struct snd_mixer *m) 55070134Scg{ 55170134Scg struct mss_info *mss = mix_getdevinfo(m); 55270134Scg 55370134Scg mssmix_init(m); 55470134Scg mix_setdevs(m, mix_getdevs(m) | SOUND_MASK_VOLUME | SOUND_MASK_MIC 55570134Scg | SOUND_MASK_BASS | SOUND_MASK_TREBLE); 55670134Scg /* Set master volume */ 55774763Scg mss_lock(mss); 55870134Scg conf_wr(mss, OPL3SAx_VOLUMEL, 7); 55970134Scg conf_wr(mss, OPL3SAx_VOLUMER, 7); 56074763Scg mss_unlock(mss); 56170134Scg 56270134Scg return 0; 56370134Scg} 56470134Scg 56570134Scgstatic int 56674763Scgymmix_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right) 56770134Scg{ 56870134Scg struct mss_info *mss = mix_getdevinfo(m); 56970134Scg int t, l, r; 57070134Scg 57174763Scg mss_lock(mss); 57270134Scg switch (dev) { 57370134Scg case SOUND_MIXER_VOLUME: 57470134Scg if (left) t = 15 - (left * 15) / 100; 57570134Scg else t = 0x80; /* mute */ 57670134Scg conf_wr(mss, OPL3SAx_VOLUMEL, t); 57770134Scg if (right) t = 15 - (right * 15) / 100; 57870134Scg else t = 0x80; /* mute */ 57970134Scg conf_wr(mss, OPL3SAx_VOLUMER, t); 58070134Scg break; 58170134Scg 58270134Scg case SOUND_MIXER_MIC: 58370134Scg t = left; 58470134Scg if (left) t = 31 - (left * 31) / 100; 58570134Scg else t = 0x80; /* mute */ 58670134Scg conf_wr(mss, OPL3SAx_MIC, t); 58770134Scg break; 58870134Scg 58970134Scg case SOUND_MIXER_BASS: 59070134Scg l = (left * 7) / 100; 59170134Scg r = (right * 7) / 100; 59270134Scg t = (r << 4) | l; 59370134Scg conf_wr(mss, OPL3SAx_BASS, t); 59470134Scg break; 59570134Scg 59670134Scg case SOUND_MIXER_TREBLE: 59770134Scg l = (left * 7) / 100; 59870134Scg r = (right * 7) / 100; 59970134Scg t = (r << 4) | l; 60070134Scg conf_wr(mss, OPL3SAx_TREBLE, t); 60170134Scg break; 60270134Scg 60370134Scg default: 60470134Scg mss_mixer_set(mss, dev, left, right); 60570134Scg } 60674763Scg mss_unlock(mss); 60770134Scg 60870134Scg return left | (right << 8); 60970134Scg} 61070134Scg 611193640Sariffstatic u_int32_t 61274763Scgymmix_setrecsrc(struct snd_mixer *m, u_int32_t src) 61370134Scg{ 61470134Scg struct mss_info *mss = mix_getdevinfo(m); 61574763Scg mss_lock(mss); 61670134Scg src = mss_set_recsrc(mss, src); 61774763Scg mss_unlock(mss); 61870134Scg return src; 61970134Scg} 62070134Scg 62170134Scgstatic kobj_method_t ymmix_mixer_methods[] = { 62270134Scg KOBJMETHOD(mixer_init, ymmix_init), 62370134Scg KOBJMETHOD(mixer_set, ymmix_set), 62470134Scg KOBJMETHOD(mixer_setrecsrc, ymmix_setrecsrc), 625193640Sariff KOBJMETHOD_END 62670134Scg}; 62770134ScgMIXER_DECLARE(ymmix_mixer); 62870134Scg 62970134Scg/* -------------------------------------------------------------------- */ 63053553Stanimura/* 63153553Stanimura * XXX This might be better off in the gusc driver. 63253553Stanimura */ 63353553Stanimurastatic void 63453553Stanimuragusmax_setup(struct mss_info *mss, device_t dev, struct resource *alt) 63553553Stanimura{ 63653553Stanimura static const unsigned char irq_bits[16] = { 63753553Stanimura 0, 0, 0, 3, 0, 2, 0, 4, 0, 1, 0, 5, 6, 0, 0, 7 63853553Stanimura }; 63953553Stanimura static const unsigned char dma_bits[8] = { 64053553Stanimura 0, 1, 0, 2, 0, 3, 4, 5 64153553Stanimura }; 64253553Stanimura device_t parent = device_get_parent(dev); 64353553Stanimura unsigned char irqctl, dmactl; 64453553Stanimura int s; 64553553Stanimura 64653553Stanimura s = splhigh(); 64753553Stanimura 64853553Stanimura port_wr(alt, 0x0f, 0x05); 64953553Stanimura port_wr(alt, 0x00, 0x0c); 65053553Stanimura port_wr(alt, 0x0b, 0x00); 65153553Stanimura 65253553Stanimura port_wr(alt, 0x0f, 0x00); 65353553Stanimura 65453553Stanimura irqctl = irq_bits[isa_get_irq(parent)]; 65553553Stanimura /* Share the IRQ with the MIDI driver. */ 65653553Stanimura irqctl |= 0x40; 65753553Stanimura dmactl = dma_bits[isa_get_drq(parent)]; 65853553Stanimura if (device_get_flags(parent) & DV_F_DUAL_DMA) 65953553Stanimura dmactl |= dma_bits[device_get_flags(parent) & DV_F_DRQ_MASK] 66053553Stanimura << 3; 66153553Stanimura 66253553Stanimura /* 66353553Stanimura * Set the DMA and IRQ control latches. 66453553Stanimura */ 66553553Stanimura port_wr(alt, 0x00, 0x0c); 66653553Stanimura port_wr(alt, 0x0b, dmactl | 0x80); 66753553Stanimura port_wr(alt, 0x00, 0x4c); 66853553Stanimura port_wr(alt, 0x0b, irqctl); 66953553Stanimura 67053553Stanimura port_wr(alt, 0x00, 0x0c); 67153553Stanimura port_wr(alt, 0x0b, dmactl); 67253553Stanimura port_wr(alt, 0x00, 0x4c); 67353553Stanimura port_wr(alt, 0x0b, irqctl); 67453553Stanimura 67553553Stanimura port_wr(mss->conf_base, 2, 0); 67653553Stanimura port_wr(alt, 0x00, 0x0c); 67753553Stanimura port_wr(mss->conf_base, 2, 0); 67853553Stanimura 67953553Stanimura splx(s); 68053553Stanimura} 68153553Stanimura 68250723Scgstatic int 68350723Scgmss_init(struct mss_info *mss, device_t dev) 68450723Scg{ 68551766Scg u_char r6, r9; 68651766Scg struct resource *alt; 68751766Scg int rid, tmp; 68851766Scg 68950723Scg mss->bd_flags |= BD_F_MCE_BIT; 69050723Scg switch(mss->bd_id) { 69150723Scg case MD_OPTI931: 69252169Sdfr /* 69352169Sdfr * The MED3931 v.1.0 allocates 3 bytes for the config 69452169Sdfr * space, whereas v.2.0 allocates 4 bytes. What I know 69552169Sdfr * for sure is that the upper two ports must be used, 69652169Sdfr * and they should end on a boundary of 4 bytes. So I 69752169Sdfr * need the following trick. 69852169Sdfr */ 69952169Sdfr mss->opti_offset = 70052169Sdfr (rman_get_start(mss->conf_base) & ~3) + 2 70152169Sdfr - rman_get_start(mss->conf_base); 70254165Scg BVDDB(printf("mss_init: opti_offset=%d\n", mss->opti_offset)); 70352169Sdfr opti_wr(mss, 4, 0xd6); /* fifo empty, OPL3, audio enable, SB3.2 */ 70450723Scg ad_write(mss, 10, 2); /* enable interrupts */ 70552169Sdfr opti_wr(mss, 6, 2); /* MCIR6: mss enable, sb disable */ 70652169Sdfr opti_wr(mss, 5, 0x28); /* MCIR5: codec in exp. mode,fifo */ 70750723Scg break; 70850723Scg 70950723Scg case MD_GUSPNP: 71053553Stanimura case MD_GUSMAX: 71150723Scg gus_wr(mss, 0x4c /* _URSTI */, 0);/* Pull reset */ 71250723Scg DELAY(1000 * 30); 71350723Scg /* release reset and enable DAC */ 71450723Scg gus_wr(mss, 0x4c /* _URSTI */, 3); 71550723Scg DELAY(1000 * 30); 71650723Scg /* end of reset */ 71750723Scg 71850723Scg rid = 0; 719127135Snjl alt = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, 720127135Snjl RF_ACTIVE); 72153553Stanimura if (alt == NULL) { 72253553Stanimura printf("XXX couldn't init GUS PnP/MAX\n"); 72353553Stanimura break; 72453553Stanimura } 72550723Scg port_wr(alt, 0, 0xC); /* enable int and dma */ 72653553Stanimura if (mss->bd_id == MD_GUSMAX) 72753553Stanimura gusmax_setup(mss, dev, alt); 72850723Scg bus_release_resource(dev, SYS_RES_IOPORT, rid, alt); 72950723Scg 73050723Scg /* 73150723Scg * unmute left & right line. Need to go in mode3, unmute, 73250723Scg * and back to mode 2 73350723Scg */ 73450723Scg tmp = ad_read(mss, 0x0c); 73550723Scg ad_write(mss, 0x0c, 0x6c); /* special value to enter mode 3 */ 73650723Scg ad_write(mss, 0x19, 0); /* unmute left */ 73750723Scg ad_write(mss, 0x1b, 0); /* unmute right */ 73850723Scg ad_write(mss, 0x0c, tmp); /* restore old mode */ 73950723Scg 74050723Scg /* send codec interrupts on irq1 and only use that one */ 74150723Scg gus_wr(mss, 0x5a, 0x4f); 74250723Scg 74350723Scg /* enable access to hidden regs */ 74450723Scg tmp = gus_rd(mss, 0x5b /* IVERI */); 74550723Scg gus_wr(mss, 0x5b, tmp | 1); 74650723Scg BVDDB(printf("GUS: silicon rev %c\n", 'A' + ((tmp & 0xf) >> 4))); 74750723Scg break; 74853553Stanimura 74950723Scg case MD_YM0020: 75051766Scg conf_wr(mss, OPL3SAx_DMACONF, 0xa9); /* dma-b rec, dma-a play */ 75150723Scg r6 = conf_rd(mss, OPL3SAx_DMACONF); 75250723Scg r9 = conf_rd(mss, OPL3SAx_MISC); /* version */ 75350723Scg BVDDB(printf("Yamaha: ver 0x%x DMA config 0x%x\n", r6, r9);) 75450723Scg /* yamaha - set volume to max */ 75550723Scg conf_wr(mss, OPL3SAx_VOLUMEL, 0); 75650723Scg conf_wr(mss, OPL3SAx_VOLUMER, 0); 75750723Scg conf_wr(mss, OPL3SAx_DMACONF, FULL_DUPLEX(mss)? 0xa9 : 0x8b); 75850723Scg break; 75951766Scg } 76050723Scg if (FULL_DUPLEX(mss) && mss->bd_id != MD_OPTI931) 76150723Scg ad_write(mss, 12, ad_read(mss, 12) | 0x40); /* mode 2 */ 76257770Scg ad_enter_MCE(mss); 76350723Scg ad_write(mss, 9, FULL_DUPLEX(mss)? 0 : 4); 76457770Scg ad_leave_MCE(mss); 76557770Scg ad_write(mss, 10, 2); /* int enable */ 76650723Scg io_wr(mss, MSS_STATUS, 0); /* Clear interrupt status */ 76750723Scg /* the following seem required on the CS4232 */ 76850723Scg ad_unmute(mss); 76950723Scg return 0; 77050723Scg} 77150723Scg 77270134Scg 77329415Sjmg/* 77470134Scg * main irq handler for the CS423x. The OPTi931 code is 77570134Scg * a separate one. 77670134Scg * The correct way to operate for a device with multiple internal 77770134Scg * interrupt sources is to loop on the status register and ack 77870134Scg * interrupts until all interrupts are served and none are reported. At 77970134Scg * this point the IRQ line to the ISA IRQ controller should go low 78070134Scg * and be raised at the next interrupt. 78170134Scg * 78270134Scg * Since the ISA IRQ controller is sent EOI _before_ passing control 78370134Scg * to the isr, it might happen that we serve an interrupt early, in 78470134Scg * which case the status register at the next interrupt should just 78570134Scg * say that there are no more interrupts... 78670134Scg */ 78770134Scg 78870134Scgstatic void 78970134Scgmss_intr(void *arg) 79070134Scg{ 79170134Scg struct mss_info *mss = arg; 79270134Scg u_char c = 0, served = 0; 79370134Scg int i; 79470134Scg 79570134Scg DEB(printf("mss_intr\n")); 79674763Scg mss_lock(mss); 79770134Scg ad_read(mss, 11); /* fake read of status bits */ 79870134Scg 79970134Scg /* loop until there are interrupts, but no more than 10 times. */ 80070134Scg for (i = 10; i > 0 && io_rd(mss, MSS_STATUS) & 1; i--) { 80170134Scg /* get exact reason for full-duplex boards */ 80270134Scg c = FULL_DUPLEX(mss)? ad_read(mss, 24) : 0x30; 80370134Scg c &= ~served; 80470291Scg if (sndbuf_runsz(mss->pch.buffer) && (c & 0x10)) { 80570134Scg served |= 0x10; 806148598Snetchild mss_unlock(mss); 80770134Scg chn_intr(mss->pch.channel); 808148598Snetchild mss_lock(mss); 80970134Scg } 81070291Scg if (sndbuf_runsz(mss->rch.buffer) && (c & 0x20)) { 81170134Scg served |= 0x20; 812148598Snetchild mss_unlock(mss); 81370134Scg chn_intr(mss->rch.channel); 814152150Sariff mss_lock(mss); 81570134Scg } 81670134Scg /* now ack the interrupt */ 81770134Scg if (FULL_DUPLEX(mss)) ad_write(mss, 24, ~c); /* ack selectively */ 81870134Scg else io_wr(mss, MSS_STATUS, 0); /* Clear interrupt status */ 81970134Scg } 82070134Scg if (i == 10) { 82170134Scg BVDDB(printf("mss_intr: irq, but not from mss\n")); 82270134Scg } else if (served == 0) { 82370134Scg BVDDB(printf("mss_intr: unexpected irq with reason %x\n", c)); 82470134Scg /* 82570134Scg * this should not happen... I have no idea what to do now. 82670134Scg * maybe should do a sanity check and restart dmas ? 82770134Scg */ 82870134Scg io_wr(mss, MSS_STATUS, 0); /* Clear interrupt status */ 82970134Scg } 83074763Scg mss_unlock(mss); 83170134Scg} 83270134Scg 83370134Scg/* 83470134Scg * AD_WAIT_INIT waits if we are initializing the board and 83570134Scg * we cannot modify its settings 83670134Scg */ 83770134Scgstatic int 83870134Scgad_wait_init(struct mss_info *mss, int x) 83970134Scg{ 84070134Scg int arg = x, n = 0; /* to shut up the compiler... */ 84170134Scg for (; x > 0; x--) 84288384Spb if ((n = io_rd(mss, MSS_INDEX)) & MSS_IDXBUSY) DELAY(10); 84370134Scg else return n; 84470134Scg printf("AD_WAIT_INIT FAILED %d 0x%02x\n", arg, n); 84570134Scg return n; 84670134Scg} 84770134Scg 84870134Scgstatic int 84970134Scgad_read(struct mss_info *mss, int reg) 85070134Scg{ 85170134Scg int x; 85270134Scg 85373775Scg ad_wait_init(mss, 201000); 85470134Scg x = io_rd(mss, MSS_INDEX) & ~MSS_IDXMASK; 85570134Scg io_wr(mss, MSS_INDEX, (u_char)(reg & MSS_IDXMASK) | x); 85670134Scg x = io_rd(mss, MSS_IDATA); 85770134Scg /* printf("ad_read %d, %x\n", reg, x); */ 85870134Scg return x; 85970134Scg} 86070134Scg 86170134Scgstatic void 86270134Scgad_write(struct mss_info *mss, int reg, u_char data) 86370134Scg{ 86474763Scg int x; 86570134Scg 86670134Scg /* printf("ad_write %d, %x\n", reg, data); */ 86773775Scg ad_wait_init(mss, 1002000); 86870134Scg x = io_rd(mss, MSS_INDEX) & ~MSS_IDXMASK; 86970134Scg io_wr(mss, MSS_INDEX, (u_char)(reg & MSS_IDXMASK) | x); 87070134Scg io_wr(mss, MSS_IDATA, data); 87170134Scg} 87270134Scg 87370134Scgstatic void 87470134Scgad_write_cnt(struct mss_info *mss, int reg, u_short cnt) 87570134Scg{ 87670134Scg ad_write(mss, reg+1, cnt & 0xff); 87770134Scg ad_write(mss, reg, cnt >> 8); /* upper base must be last */ 87870134Scg} 87970134Scg 88070134Scgstatic void 88170134Scgwait_for_calibration(struct mss_info *mss) 88270134Scg{ 88370134Scg int t; 88470134Scg 88570134Scg /* 88670134Scg * Wait until the auto calibration process has finished. 88770134Scg * 88870134Scg * 1) Wait until the chip becomes ready (reads don't return 0x80). 88970134Scg * 2) Wait until the ACI bit of I11 gets on 89070134Scg * 3) Wait until the ACI bit of I11 gets off 89170134Scg */ 89270134Scg 89373775Scg t = ad_wait_init(mss, 1000000); 89470134Scg if (t & MSS_IDXBUSY) printf("mss: Auto calibration timed out(1).\n"); 89570134Scg 89670134Scg /* 89770134Scg * The calibration mode for chips that support it is set so that 89870134Scg * we never see ACI go on. 89970134Scg */ 90070134Scg if (mss->bd_id == MD_GUSMAX || mss->bd_id == MD_GUSPNP) { 90170134Scg for (t = 100; t > 0 && (ad_read(mss, 11) & 0x20) == 0; t--); 90270134Scg } else { 90370134Scg /* 90470134Scg * XXX This should only be enabled for cards that *really* 90570134Scg * need it. Are there any? 90670134Scg */ 90770134Scg for (t = 100; t > 0 && (ad_read(mss, 11) & 0x20) == 0; t--) DELAY(100); 90870134Scg } 90970134Scg for (t = 100; t > 0 && ad_read(mss, 11) & 0x20; t--) DELAY(100); 91070134Scg} 91170134Scg 91270134Scgstatic void 91370134Scgad_unmute(struct mss_info *mss) 91470134Scg{ 91570134Scg ad_write(mss, 6, ad_read(mss, 6) & ~I6_MUTE); 91670134Scg ad_write(mss, 7, ad_read(mss, 7) & ~I6_MUTE); 91770134Scg} 91870134Scg 91970134Scgstatic void 92070134Scgad_enter_MCE(struct mss_info *mss) 92170134Scg{ 92270134Scg int prev; 92370134Scg 92470134Scg mss->bd_flags |= BD_F_MCE_BIT; 92573775Scg ad_wait_init(mss, 203000); 92670134Scg prev = io_rd(mss, MSS_INDEX); 92770134Scg prev &= ~MSS_TRD; 92870134Scg io_wr(mss, MSS_INDEX, prev | MSS_MCE); 92970134Scg} 93070134Scg 93170134Scgstatic void 93270134Scgad_leave_MCE(struct mss_info *mss) 93370134Scg{ 93470134Scg u_char prev; 93570134Scg 93670134Scg if ((mss->bd_flags & BD_F_MCE_BIT) == 0) { 93770134Scg DEB(printf("--- hey, leave_MCE: MCE bit was not set!\n")); 93870134Scg return; 93970134Scg } 94070134Scg 94173775Scg ad_wait_init(mss, 1000000); 94270134Scg 94370134Scg mss->bd_flags &= ~BD_F_MCE_BIT; 94470134Scg 94570134Scg prev = io_rd(mss, MSS_INDEX); 94670134Scg prev &= ~MSS_TRD; 94770134Scg io_wr(mss, MSS_INDEX, prev & ~MSS_MCE); /* Clear the MCE bit */ 94870134Scg wait_for_calibration(mss); 94970134Scg} 95070134Scg 95170134Scgstatic int 95270134Scgmss_speed(struct mss_chinfo *ch, int speed) 95370134Scg{ 95470134Scg struct mss_info *mss = ch->parent; 95570134Scg /* 95670134Scg * In the CS4231, the low 4 bits of I8 are used to hold the 95770134Scg * sample rate. Only a fixed number of values is allowed. This 95870134Scg * table lists them. The speed-setting routines scans the table 95970134Scg * looking for the closest match. This is the only supported method. 96070134Scg * 96170134Scg * In the CS4236, there is an alternate metod (which we do not 96270134Scg * support yet) which provides almost arbitrary frequency setting. 96370134Scg * In the AD1845, it looks like the sample rate can be 96470134Scg * almost arbitrary, and written directly to a register. 96570134Scg * In the OPTi931, there is a SB command which provides for 96670134Scg * almost arbitrary frequency setting. 96770134Scg * 96870134Scg */ 96970134Scg ad_enter_MCE(mss); 97070134Scg if (mss->bd_id == MD_AD1845) { /* Use alternate speed select regs */ 97170134Scg ad_write(mss, 22, (speed >> 8) & 0xff); /* Speed MSB */ 97270134Scg ad_write(mss, 23, speed & 0xff); /* Speed LSB */ 97370134Scg /* XXX must also do something in I27 for the ad1845 */ 97470134Scg } else { 97570134Scg int i, sel = 0; /* assume entry 0 does not contain -1 */ 97670134Scg static int speeds[] = 97770134Scg {8000, 5512, 16000, 11025, 27429, 18900, 32000, 22050, 97870134Scg -1, 37800, -1, 44100, 48000, 33075, 9600, 6615}; 97970134Scg 98070134Scg for (i = 1; i < 16; i++) 98170134Scg if (speeds[i] > 0 && 98270134Scg abs(speed-speeds[i]) < abs(speed-speeds[sel])) sel = i; 98370134Scg speed = speeds[sel]; 98470134Scg ad_write(mss, 8, (ad_read(mss, 8) & 0xf0) | sel); 985149987Snetchild ad_wait_init(mss, 10000); 98670134Scg } 98770134Scg ad_leave_MCE(mss); 98870134Scg 98970134Scg return speed; 99070134Scg} 99170134Scg 99270134Scg/* 99370134Scg * mss_format checks that the format is supported (or defaults to AFMT_U8) 99470134Scg * and returns the bit setting for the 1848 register corresponding to 99570134Scg * the desired format. 99670134Scg * 99770134Scg * fixed lr970724 99870134Scg */ 99970134Scg 100070134Scgstatic int 100170134Scgmss_format(struct mss_chinfo *ch, u_int32_t format) 100270134Scg{ 100370134Scg struct mss_info *mss = ch->parent; 1004193640Sariff int i, arg = AFMT_ENCODING(format); 100570134Scg 100670134Scg /* 100770134Scg * The data format uses 3 bits (just 2 on the 1848). For each 100870134Scg * bit setting, the following array returns the corresponding format. 100970134Scg * The code scans the array looking for a suitable format. In 101070134Scg * case it is not found, default to AFMT_U8 (not such a good 101170134Scg * choice, but let's do it for compatibility...). 101270134Scg */ 101370134Scg 101470134Scg static int fmts[] = 101570134Scg {AFMT_U8, AFMT_MU_LAW, AFMT_S16_LE, AFMT_A_LAW, 101670134Scg -1, AFMT_IMA_ADPCM, AFMT_U16_BE, -1}; 101770134Scg 101870134Scg ch->fmt = format; 101970134Scg for (i = 0; i < 8; i++) if (arg == fmts[i]) break; 102070134Scg arg = i << 1; 1021193640Sariff if (AFMT_CHANNEL(format) > 1) arg |= 1; 102270134Scg arg <<= 4; 102370134Scg ad_enter_MCE(mss); 102470134Scg ad_write(mss, 8, (ad_read(mss, 8) & 0x0f) | arg); 1025149987Snetchild ad_wait_init(mss, 10000); 1026149987Snetchild if (ad_read(mss, 12) & 0x40) { /* mode2? */ 1027149986Snetchild ad_write(mss, 28, arg); /* capture mode */ 1028149987Snetchild ad_wait_init(mss, 10000); 1029149987Snetchild } 103070134Scg ad_leave_MCE(mss); 103170134Scg return format; 103270134Scg} 103370134Scg 103470134Scgstatic int 103570134Scgmss_trigger(struct mss_chinfo *ch, int go) 103670134Scg{ 103770134Scg struct mss_info *mss = ch->parent; 103870134Scg u_char m; 103970134Scg int retry, wr, cnt, ss; 104070134Scg 104170134Scg ss = 1; 1042193640Sariff ss <<= (AFMT_CHANNEL(ch->fmt) > 1)? 1 : 0; 104370134Scg ss <<= (ch->fmt & AFMT_16BIT)? 1 : 0; 104470134Scg 104570134Scg wr = (ch->dir == PCMDIR_PLAY)? 1 : 0; 104670134Scg m = ad_read(mss, 9); 104770134Scg switch (go) { 104870134Scg case PCMTRIG_START: 104970291Scg cnt = (ch->blksz / ss) - 1; 105070134Scg 105170134Scg DEB(if (m & 4) printf("OUCH! reg 9 0x%02x\n", m);); 105270134Scg m |= wr? I9_PEN : I9_CEN; /* enable DMA */ 105370134Scg ad_write_cnt(mss, (wr || !FULL_DUPLEX(mss))? 14 : 30, cnt); 105470134Scg break; 105570134Scg 105670134Scg case PCMTRIG_STOP: 105770134Scg case PCMTRIG_ABORT: /* XXX check this... */ 105870134Scg m &= ~(wr? I9_PEN : I9_CEN); /* Stop DMA */ 105970134Scg#if 0 106070134Scg /* 106170134Scg * try to disable DMA by clearing count registers. Not sure it 106270134Scg * is needed, and it might cause false interrupts when the 106370134Scg * DMA is re-enabled later. 106470134Scg */ 106570134Scg ad_write_cnt(mss, (wr || !FULL_DUPLEX(mss))? 14 : 30, 0); 106670134Scg#endif 106770134Scg } 106870134Scg /* on the OPTi931 the enable bit seems hard to set... */ 106970134Scg for (retry = 10; retry > 0; retry--) { 107070134Scg ad_write(mss, 9, m); 107170134Scg if (ad_read(mss, 9) == m) break; 107270134Scg } 107370134Scg if (retry == 0) BVDDB(printf("stop dma, failed to set bit 0x%02x 0x%02x\n", \ 107470134Scg m, ad_read(mss, 9))); 107570134Scg return 0; 107670134Scg} 107770134Scg 107870134Scg 107970134Scg/* 108070134Scg * the opti931 seems to miss interrupts when working in full 108170134Scg * duplex, so we try some heuristics to catch them. 108270134Scg */ 108370134Scgstatic void 108470134Scgopti931_intr(void *arg) 108570134Scg{ 108670134Scg struct mss_info *mss = (struct mss_info *)arg; 108770134Scg u_char masked = 0, i11, mc11, c = 0; 108870134Scg u_char reason; /* b0 = playback, b1 = capture, b2 = timer */ 108970134Scg int loops = 10; 109070134Scg 109170134Scg#if 0 109270134Scg reason = io_rd(mss, MSS_STATUS); 109370134Scg if (!(reason & 1)) {/* no int, maybe a shared line ? */ 109470134Scg DEB(printf("intr: flag 0, mcir11 0x%02x\n", ad_read(mss, 11))); 109570134Scg return; 109670134Scg } 109770134Scg#endif 109874763Scg mss_lock(mss); 109970134Scg i11 = ad_read(mss, 11); /* XXX what's for ? */ 110070134Scg again: 110170134Scg 110270134Scg c = mc11 = FULL_DUPLEX(mss)? opti_rd(mss, 11) : 0xc; 110370134Scg mc11 &= 0x0c; 110470134Scg if (c & 0x10) { 110570134Scg DEB(printf("Warning: CD interrupt\n");) 110670134Scg mc11 |= 0x10; 110770134Scg } 110870134Scg if (c & 0x20) { 110970134Scg DEB(printf("Warning: MPU interrupt\n");) 111070134Scg mc11 |= 0x20; 111170134Scg } 111270134Scg if (mc11 & masked) BVDDB(printf("irq reset failed, mc11 0x%02x, 0x%02x\n",\ 111370134Scg mc11, masked)); 111470134Scg masked |= mc11; 111570134Scg /* 111670134Scg * the nice OPTi931 sets the IRQ line before setting the bits in 111770134Scg * mc11. So, on some occasions I have to retry (max 10 times). 111870134Scg */ 111970134Scg if (mc11 == 0) { /* perhaps can return ... */ 112070134Scg reason = io_rd(mss, MSS_STATUS); 112170134Scg if (reason & 1) { 112270134Scg DEB(printf("one more try...\n");) 112370134Scg if (--loops) goto again; 1124131918Smarcel else BVDDB(printf("intr, but mc11 not set\n");) 112570134Scg } 112670134Scg if (loops == 0) BVDDB(printf("intr, nothing in mcir11 0x%02x\n", mc11)); 112774763Scg mss_unlock(mss); 112870134Scg return; 112970134Scg } 113070134Scg 1131148598Snetchild if (sndbuf_runsz(mss->rch.buffer) && (mc11 & 8)) { 1132148598Snetchild mss_unlock(mss); 1133148598Snetchild chn_intr(mss->rch.channel); 1134148598Snetchild mss_lock(mss); 1135148598Snetchild } 1136148598Snetchild if (sndbuf_runsz(mss->pch.buffer) && (mc11 & 4)) { 1137148598Snetchild mss_unlock(mss); 1138148598Snetchild chn_intr(mss->pch.channel); 1139148598Snetchild mss_lock(mss); 1140148598Snetchild } 114170134Scg opti_wr(mss, 11, ~mc11); /* ack */ 114270134Scg if (--loops) goto again; 114374763Scg mss_unlock(mss); 114470134Scg DEB(printf("xxx too many loops\n");) 114570134Scg} 114670134Scg 114770134Scg/* -------------------------------------------------------------------- */ 114870134Scg/* channel interface */ 114970134Scgstatic void * 115074763Scgmsschan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir) 115170134Scg{ 115270134Scg struct mss_info *mss = devinfo; 115370134Scg struct mss_chinfo *ch = (dir == PCMDIR_PLAY)? &mss->pch : &mss->rch; 115470134Scg 115570134Scg ch->parent = mss; 115670134Scg ch->channel = c; 115770134Scg ch->buffer = b; 115870134Scg ch->dir = dir; 1159168847Sariff if (sndbuf_alloc(ch->buffer, mss->parent_dmat, 0, mss->bufsize) != 0) 1160136469Syongari return NULL; 1161110499Snyan sndbuf_dmasetup(ch->buffer, (dir == PCMDIR_PLAY)? mss->drq1 : mss->drq2); 116270134Scg return ch; 116370134Scg} 116470134Scg 116570134Scgstatic int 116670134Scgmsschan_setformat(kobj_t obj, void *data, u_int32_t format) 116770134Scg{ 116870134Scg struct mss_chinfo *ch = data; 116974763Scg struct mss_info *mss = ch->parent; 117070134Scg 117174763Scg mss_lock(mss); 117270134Scg mss_format(ch, format); 117374763Scg mss_unlock(mss); 117470134Scg return 0; 117570134Scg} 117670134Scg 1177193640Sariffstatic u_int32_t 117870134Scgmsschan_setspeed(kobj_t obj, void *data, u_int32_t speed) 117970134Scg{ 118070134Scg struct mss_chinfo *ch = data; 118174763Scg struct mss_info *mss = ch->parent; 1182193640Sariff u_int32_t r; 118370134Scg 118474763Scg mss_lock(mss); 118574763Scg r = mss_speed(ch, speed); 118674763Scg mss_unlock(mss); 118774763Scg 118874763Scg return r; 118970134Scg} 119070134Scg 1191193640Sariffstatic u_int32_t 119270134Scgmsschan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize) 119370134Scg{ 119470291Scg struct mss_chinfo *ch = data; 119570291Scg 119670291Scg ch->blksz = blocksize; 119783621Scg sndbuf_resize(ch->buffer, 2, ch->blksz); 119883621Scg 119970291Scg return ch->blksz; 120070134Scg} 120170134Scg 120270134Scgstatic int 120370134Scgmsschan_trigger(kobj_t obj, void *data, int go) 120470134Scg{ 120570134Scg struct mss_chinfo *ch = data; 120674763Scg struct mss_info *mss = ch->parent; 120770134Scg 1208170521Sariff if (!PCMTRIG_COMMON(go)) 120970134Scg return 0; 121070134Scg 1211110499Snyan sndbuf_dma(ch->buffer, go); 121274763Scg mss_lock(mss); 121370134Scg mss_trigger(ch, go); 121474763Scg mss_unlock(mss); 121570134Scg return 0; 121670134Scg} 121770134Scg 1218193640Sariffstatic u_int32_t 121970134Scgmsschan_getptr(kobj_t obj, void *data) 122070134Scg{ 122170134Scg struct mss_chinfo *ch = data; 1222110499Snyan return sndbuf_dmaptr(ch->buffer); 122370134Scg} 122470134Scg 122574763Scgstatic struct pcmchan_caps * 122670134Scgmsschan_getcaps(kobj_t obj, void *data) 122770134Scg{ 122870134Scg struct mss_chinfo *ch = data; 122970134Scg 123070134Scg switch(ch->parent->bd_id) { 123170134Scg case MD_OPTI931: 123270134Scg return &opti931_caps; 123370134Scg break; 123470134Scg 123570134Scg case MD_GUSPNP: 123670134Scg case MD_GUSMAX: 123770134Scg return &guspnp_caps; 123870134Scg break; 123970134Scg 124070134Scg default: 124170134Scg return &mss_caps; 124270134Scg break; 124370134Scg } 124470134Scg} 124570134Scg 124670134Scgstatic kobj_method_t msschan_methods[] = { 124770134Scg KOBJMETHOD(channel_init, msschan_init), 124870134Scg KOBJMETHOD(channel_setformat, msschan_setformat), 124970134Scg KOBJMETHOD(channel_setspeed, msschan_setspeed), 125070134Scg KOBJMETHOD(channel_setblocksize, msschan_setblocksize), 125170134Scg KOBJMETHOD(channel_trigger, msschan_trigger), 125270134Scg KOBJMETHOD(channel_getptr, msschan_getptr), 125370134Scg KOBJMETHOD(channel_getcaps, msschan_getcaps), 1254193640Sariff KOBJMETHOD_END 125570134Scg}; 125670134ScgCHANNEL_DECLARE(msschan); 125770134Scg 125870134Scg/* -------------------------------------------------------------------- */ 125970134Scg 126070134Scg/* 126130869Sjmg * mss_probe() is the probe routine. Note, it is not necessary to 126229415Sjmg * go through this for PnP devices, since they are already 126329415Sjmg * indentified precisely using their PnP id. 126429415Sjmg * 126529415Sjmg * The base address supplied in the device refers to the old MSS 126629415Sjmg * specs where the four 4 registers in io space contain configuration 126729415Sjmg * information. Some boards (as an example, early MSS boards) 126829415Sjmg * has such a block of registers, whereas others (generally CS42xx) 126929415Sjmg * do not. In order to distinguish between the two and do not have 127029415Sjmg * to supply two separate probe routines, the flags entry in isa_device 127129415Sjmg * has a bit to mark this. 127229415Sjmg * 127329415Sjmg */ 127429415Sjmg 127529415Sjmgstatic int 127650723Scgmss_probe(device_t dev) 127729415Sjmg{ 127850723Scg u_char tmp, tmpx; 127950723Scg int flags, irq, drq, result = ENXIO, setres = 0; 128050723Scg struct mss_info *mss; 128129415Sjmg 128262947Stanimura if (isa_get_logicalid(dev)) return ENXIO; /* not yet */ 128329415Sjmg 128478564Sgreid mss = (struct mss_info *)malloc(sizeof *mss, M_DEVBUF, M_NOWAIT | M_ZERO); 128550723Scg if (!mss) return ENXIO; 128629415Sjmg 128750723Scg mss->io_rid = 0; 128850723Scg mss->conf_rid = -1; 128950723Scg mss->irq_rid = 0; 129050723Scg mss->drq1_rid = 0; 129150723Scg mss->drq2_rid = -1; 129250723Scg mss->io_base = bus_alloc_resource(dev, SYS_RES_IOPORT, &mss->io_rid, 129350723Scg 0, ~0, 8, RF_ACTIVE); 129450723Scg if (!mss->io_base) { 129550723Scg BVDDB(printf("mss_probe: no address given, try 0x%x\n", 0x530)); 129650723Scg mss->io_rid = 0; 129750723Scg /* XXX verify this */ 129850723Scg setres = 1; 129952174Sdfr bus_set_resource(dev, SYS_RES_IOPORT, mss->io_rid, 130050723Scg 0x530, 8); 130150723Scg mss->io_base = bus_alloc_resource(dev, SYS_RES_IOPORT, &mss->io_rid, 130250723Scg 0, ~0, 8, RF_ACTIVE); 130350723Scg } 130450723Scg if (!mss->io_base) goto no; 130550723Scg 130650723Scg /* got irq/dma regs? */ 130751052Sdfr flags = device_get_flags(dev); 130850723Scg irq = isa_get_irq(dev); 130950723Scg drq = isa_get_drq(dev); 131050723Scg 131151052Sdfr if (!(device_get_flags(dev) & DV_F_TRUE_MSS)) goto mss_probe_end; 131250723Scg 131350723Scg /* 131450723Scg * Check if the IO port returns valid signature. The original MS 131550723Scg * Sound system returns 0x04 while some cards 131650723Scg * (AudioTriX Pro for example) return 0x00 or 0x0f. 131750723Scg */ 131850723Scg 131950723Scg device_set_desc(dev, "MSS"); 132050723Scg tmpx = tmp = io_rd(mss, 3); 132150723Scg if (tmp == 0xff) { /* Bus float */ 132250723Scg BVDDB(printf("I/O addr inactive (%x), try pseudo_mss\n", tmp)); 132351052Sdfr device_set_flags(dev, flags & ~DV_F_TRUE_MSS); 132450723Scg goto mss_probe_end; 132550723Scg } 132650723Scg tmp &= 0x3f; 1327169744Sjoel if (!(tmp == 0x04 || tmp == 0x0f || tmp == 0x00 || tmp == 0x05)) { 132850723Scg BVDDB(printf("No MSS signature detected on port 0x%lx (0x%x)\n", 132950723Scg rman_get_start(mss->io_base), tmpx)); 133050723Scg goto no; 133150723Scg } 133260711Snyan#ifdef PC98 133360711Snyan if (irq > 12) { 133460711Snyan#else 133550723Scg if (irq > 11) { 133660711Snyan#endif 133750723Scg printf("MSS: Bad IRQ %d\n", irq); 133850723Scg goto no; 133950723Scg } 134050723Scg if (!(drq == 0 || drq == 1 || drq == 3)) { 134150723Scg printf("MSS: Bad DMA %d\n", drq); 134250723Scg goto no; 134350723Scg } 134450723Scg if (tmpx & 0x80) { 134550723Scg /* 8-bit board: only drq1/3 and irq7/9 */ 134650723Scg if (drq == 0) { 134751766Scg printf("MSS: Can't use DMA0 with a 8 bit card/slot\n"); 134851766Scg goto no; 134950723Scg } 135050723Scg if (!(irq == 7 || irq == 9)) { 135151766Scg printf("MSS: Can't use IRQ%d with a 8 bit card/slot\n", 135251766Scg irq); 135351766Scg goto no; 135450723Scg } 135550723Scg } 135650723Scg mss_probe_end: 135750723Scg result = mss_detect(dev, mss); 135850723Scg no: 135950769Sdfr mss_release_resources(mss, dev); 136050769Sdfr#if 0 136150723Scg if (setres) ISA_DELETE_RESOURCE(device_get_parent(dev), dev, 136250723Scg SYS_RES_IOPORT, mss->io_rid); /* XXX ? */ 136350769Sdfr#endif 136450723Scg return result; 136529415Sjmg} 136629415Sjmg 136742284Sluigistatic int 136850723Scgmss_detect(device_t dev, struct mss_info *mss) 136942284Sluigi{ 137050723Scg int i; 137154942Scg u_char tmp = 0, tmp1, tmp2; 137250723Scg char *name, *yamaha; 137342284Sluigi 137450723Scg if (mss->bd_id != 0) { 137550723Scg device_printf(dev, "presel bd_id 0x%04x -- %s\n", mss->bd_id, 137650723Scg device_get_desc(dev)); 137750723Scg return 0; 137850723Scg } 137942284Sluigi 138050723Scg name = "AD1848"; 138150723Scg mss->bd_id = MD_AD1848; /* AD1848 or CS4248 */ 138242284Sluigi 1383149981Snetchild#ifndef PC98 138474711Scg if (opti_detect(dev, mss)) { 138574711Scg switch (mss->bd_id) { 138674711Scg case MD_OPTI924: 138774711Scg name = "OPTi924"; 138874711Scg break; 138974711Scg case MD_OPTI930: 139074711Scg name = "OPTi930"; 139174711Scg break; 139274711Scg } 139374711Scg printf("Found OPTi device %s\n", name); 139474711Scg if (opti_init(dev, mss) == 0) goto gotit; 139574711Scg } 1396149981Snetchild#endif 139774711Scg 139874711Scg /* 139950723Scg * Check that the I/O address is in use. 140050723Scg * 140150723Scg * bit 7 of the base I/O port is known to be 0 after the chip has 140250723Scg * performed its power on initialization. Just assume this has 140350723Scg * happened before the OS is starting. 140450723Scg * 140550723Scg * If the I/O address is unused, it typically returns 0xff. 140650723Scg */ 140742284Sluigi 140850723Scg for (i = 0; i < 10; i++) 140950723Scg if ((tmp = io_rd(mss, MSS_INDEX)) & MSS_IDXBUSY) DELAY(10000); 141050723Scg else break; 141142284Sluigi 1412108533Sschweikh if (i >= 10) { /* Not an AD1848 */ 141350723Scg BVDDB(printf("mss_detect, busy still set (0x%02x)\n", tmp)); 141450723Scg goto no; 141550723Scg } 141650723Scg /* 141750723Scg * Test if it's possible to change contents of the indirect 141850723Scg * registers. Registers 0 and 1 are ADC volume registers. The bit 141950723Scg * 0x10 is read only so try to avoid using it. 142050723Scg */ 142129415Sjmg 142250723Scg ad_write(mss, 0, 0xaa); 142350723Scg ad_write(mss, 1, 0x45);/* 0x55 with bit 0x10 clear */ 142450723Scg tmp1 = ad_read(mss, 0); 142550723Scg tmp2 = ad_read(mss, 1); 142650723Scg if (tmp1 != 0xaa || tmp2 != 0x45) { 142750723Scg BVDDB(printf("mss_detect error - IREG (%x/%x)\n", tmp1, tmp2)); 142850723Scg goto no; 142950723Scg } 143029415Sjmg 143150723Scg ad_write(mss, 0, 0x45); 143250723Scg ad_write(mss, 1, 0xaa); 143350723Scg tmp1 = ad_read(mss, 0); 143450723Scg tmp2 = ad_read(mss, 1); 143550723Scg if (tmp1 != 0x45 || tmp2 != 0xaa) { 143650723Scg BVDDB(printf("mss_detect error - IREG2 (%x/%x)\n", tmp1, tmp2)); 143750723Scg goto no; 143850723Scg } 143929415Sjmg 144050723Scg /* 144150723Scg * The indirect register I12 has some read only bits. Lets try to 144250723Scg * change them. 144350723Scg */ 144450723Scg 144550723Scg tmp = ad_read(mss, 12); 144650723Scg ad_write(mss, 12, (~tmp) & 0x0f); 144750723Scg tmp1 = ad_read(mss, 12); 144850723Scg 144950723Scg if ((tmp & 0x0f) != (tmp1 & 0x0f)) { 145050723Scg BVDDB(printf("mss_detect - I12 (0x%02x was 0x%02x)\n", tmp1, tmp)); 145150723Scg goto no; 145250723Scg } 145350723Scg 145450723Scg /* 145550723Scg * NOTE! Last 4 bits of the reg I12 tell the chip revision. 145650723Scg * 0x01=RevB 145750723Scg * 0x0A=RevC. also CS4231/CS4231A and OPTi931 145850723Scg */ 145950723Scg 146050723Scg BVDDB(printf("mss_detect - chip revision 0x%02x\n", tmp & 0x0f);) 146150723Scg 146250723Scg /* 146350723Scg * The original AD1848/CS4248 has just 16 indirect registers. This 146450723Scg * means that I0 and I16 should return the same value (etc.). Ensure 146550723Scg * that the Mode2 enable bit of I12 is 0. Otherwise this test fails 146650723Scg * with new parts. 146750723Scg */ 146850723Scg 146950723Scg ad_write(mss, 12, 0); /* Mode2=disabled */ 147050723Scg#if 0 147150723Scg for (i = 0; i < 16; i++) { 147250723Scg if ((tmp1 = ad_read(mss, i)) != (tmp2 = ad_read(mss, i + 16))) { 147350723Scg BVDDB(printf("mss_detect warning - I%d: 0x%02x/0x%02x\n", 147450723Scg i, tmp1, tmp2)); 147550723Scg /* 147650723Scg * note - this seems to fail on the 4232 on I11. So we just break 147750723Scg * rather than fail. (which makes this test pointless - cg) 147850723Scg */ 147950723Scg break; /* return 0; */ 148050723Scg } 148150723Scg } 148242292Sluigi#endif 148350723Scg /* 148450723Scg * Try to switch the chip to mode2 (CS4231) by setting the MODE2 bit 148550723Scg * (0x40). The bit 0x80 is always 1 in CS4248 and CS4231. 148650723Scg * 148750723Scg * On the OPTi931, however, I12 is readonly and only contains the 148850723Scg * chip revision ID (as in the CS4231A). The upper bits return 0. 148950723Scg */ 149030869Sjmg 149150723Scg ad_write(mss, 12, 0x40); /* Set mode2, clear 0x80 */ 149229415Sjmg 149350723Scg tmp1 = ad_read(mss, 12); 149450723Scg if (tmp1 & 0x80) name = "CS4248"; /* Our best knowledge just now */ 149550723Scg if ((tmp1 & 0xf0) == 0x00) { 149650723Scg BVDDB(printf("this should be an OPTi931\n");) 149750723Scg } else if ((tmp1 & 0xc0) != 0xC0) goto gotit; 149850723Scg /* 149950723Scg * The 4231 has bit7=1 always, and bit6 we just set to 1. 150050723Scg * We want to check that this is really a CS4231 150150723Scg * Verify that setting I0 doesn't change I16. 150250723Scg */ 150350723Scg ad_write(mss, 16, 0); /* Set I16 to known value */ 150450723Scg ad_write(mss, 0, 0x45); 150550723Scg if ((tmp1 = ad_read(mss, 16)) == 0x45) goto gotit; 150650723Scg 150750723Scg ad_write(mss, 0, 0xaa); 150850723Scg if ((tmp1 = ad_read(mss, 16)) == 0xaa) { /* Rotten bits? */ 150950723Scg BVDDB(printf("mss_detect error - step H(%x)\n", tmp1)); 151050723Scg goto no; 151129415Sjmg } 151250723Scg /* Verify that some bits of I25 are read only. */ 151350723Scg tmp1 = ad_read(mss, 25); /* Original bits */ 151450723Scg ad_write(mss, 25, ~tmp1); /* Invert all bits */ 151550723Scg if ((ad_read(mss, 25) & 0xe7) == (tmp1 & 0xe7)) { 151650723Scg int id; 151729415Sjmg 151850723Scg /* It's at least CS4231 */ 151950723Scg name = "CS4231"; 152054962Speter mss->bd_id = MD_CS42XX; 152129415Sjmg 152250723Scg /* 152350723Scg * It could be an AD1845 or CS4231A as well. 152450723Scg * CS4231 and AD1845 report the same revision info in I25 152550723Scg * while the CS4231A reports different. 152650723Scg */ 152729415Sjmg 152850723Scg id = ad_read(mss, 25) & 0xe7; 152950723Scg /* 153050723Scg * b7-b5 = version number; 153150723Scg * 100 : all CS4231 153250723Scg * 101 : CS4231A 153350723Scg * 153450723Scg * b2-b0 = chip id; 153550723Scg */ 153650723Scg switch (id) { 153729415Sjmg 153850723Scg case 0xa0: 153950723Scg name = "CS4231A"; 154054962Speter mss->bd_id = MD_CS42XX; 154150723Scg break; 154229415Sjmg 154350723Scg case 0xa2: 154450723Scg name = "CS4232"; 154554962Speter mss->bd_id = MD_CS42XX; 154650723Scg break; 154729415Sjmg 154850723Scg case 0xb2: 154950723Scg /* strange: the 4231 data sheet says b4-b3 are XX 155050723Scg * so this should be the same as 0xa2 155150723Scg */ 155250723Scg name = "CS4232A"; 155354962Speter mss->bd_id = MD_CS42XX; 155450723Scg break; 155529415Sjmg 155650723Scg case 0x80: 155750723Scg /* 155850723Scg * It must be a CS4231 or AD1845. The register I23 155950723Scg * of CS4231 is undefined and it appears to be read 156050723Scg * only. AD1845 uses I23 for setting sample rate. 156150723Scg * Assume the chip is AD1845 if I23 is changeable. 156250723Scg */ 156331361Sjmg 156450723Scg tmp = ad_read(mss, 23); 156529415Sjmg 156650723Scg ad_write(mss, 23, ~tmp); 156750723Scg if (ad_read(mss, 23) != tmp) { /* AD1845 ? */ 156850723Scg name = "AD1845"; 156950723Scg mss->bd_id = MD_AD1845; 157050723Scg } 157150723Scg ad_write(mss, 23, tmp); /* Restore */ 157250723Scg 157350723Scg yamaha = ymf_test(dev, mss); 157450723Scg if (yamaha) { 157550723Scg mss->bd_id = MD_YM0020; 157650723Scg name = yamaha; 157750723Scg } 157850723Scg break; 157950723Scg 158050723Scg case 0x83: /* CS4236 */ 158150723Scg case 0x03: /* CS4236 on Intel PR440FX motherboard XXX */ 158250723Scg name = "CS4236"; 158354962Speter mss->bd_id = MD_CS42XX; 158450723Scg break; 158550723Scg 158650723Scg default: /* Assume CS4231 */ 158750723Scg BVDDB(printf("unknown id 0x%02x, assuming CS4231\n", id);) 158854962Speter mss->bd_id = MD_CS42XX; 158950723Scg } 159029415Sjmg } 159150723Scg ad_write(mss, 25, tmp1); /* Restore bits */ 159250723Scggotit: 159350723Scg BVDDB(printf("mss_detect() - Detected %s\n", name)); 159450723Scg device_set_desc(dev, name); 159551052Sdfr device_set_flags(dev, 159651052Sdfr ((device_get_flags(dev) & ~DV_F_DEV_MASK) | 159751052Sdfr ((mss->bd_id << DV_F_DEV_SHIFT) & DV_F_DEV_MASK))); 159850723Scg return 0; 159950723Scgno: 160050723Scg return ENXIO; 160129415Sjmg} 160229415Sjmg 1603150014Simp#ifndef PC98 160474711Scgstatic int 160574711Scgopti_detect(device_t dev, struct mss_info *mss) 160674711Scg{ 160774711Scg int c; 160874711Scg static const struct opticard { 160974711Scg int boardid; 161074711Scg int passwdreg; 161174711Scg int password; 161274711Scg int base; 161374711Scg int indir_reg; 161474711Scg } cards[] = { 161574711Scg { MD_OPTI930, 0, 0xe4, 0xf8f, 0xe0e }, /* 930 */ 161674711Scg { MD_OPTI924, 3, 0xe5, 0xf8c, 0, }, /* 924 */ 161774711Scg { 0 }, 161874711Scg }; 161974711Scg mss->conf_rid = 3; 162074711Scg mss->indir_rid = 4; 162174711Scg for (c = 0; cards[c].base; c++) { 162274711Scg mss->optibase = cards[c].base; 162374711Scg mss->password = cards[c].password; 162474711Scg mss->passwdreg = cards[c].passwdreg; 162574711Scg mss->bd_id = cards[c].boardid; 162674711Scg 162774711Scg if (cards[c].indir_reg) 162874711Scg mss->indir = bus_alloc_resource(dev, SYS_RES_IOPORT, 162974711Scg &mss->indir_rid, cards[c].indir_reg, 163074711Scg cards[c].indir_reg+1, 1, RF_ACTIVE); 163174711Scg 163274711Scg mss->conf_base = bus_alloc_resource(dev, SYS_RES_IOPORT, 163374711Scg &mss->conf_rid, mss->optibase, mss->optibase+9, 163474711Scg 9, RF_ACTIVE); 163574711Scg 163674711Scg if (opti_read(mss, 1) != 0xff) { 163774711Scg return 1; 163874789Scg } else { 163974789Scg if (mss->indir) 164074789Scg bus_release_resource(dev, SYS_RES_IOPORT, mss->indir_rid, mss->indir); 164174789Scg mss->indir = NULL; 164274789Scg if (mss->conf_base) 164374789Scg bus_release_resource(dev, SYS_RES_IOPORT, mss->conf_rid, mss->conf_base); 164474789Scg mss->conf_base = NULL; 164574711Scg } 164674711Scg } 164774711Scg return 0; 164874711Scg} 1649150014Simp#endif 165074711Scg 165150723Scgstatic char * 165250723Scgymf_test(device_t dev, struct mss_info *mss) 165329415Sjmg{ 165450723Scg static int ports[] = {0x370, 0x310, 0x538}; 165550723Scg int p, i, j, version; 165650723Scg static char *chipset[] = { 165750723Scg NULL, /* 0 */ 165850723Scg "OPL3-SA2 (YMF711)", /* 1 */ 165950723Scg "OPL3-SA3 (YMF715)", /* 2 */ 166050723Scg "OPL3-SA3 (YMF715)", /* 3 */ 166150723Scg "OPL3-SAx (YMF719)", /* 4 */ 166250723Scg "OPL3-SAx (YMF719)", /* 5 */ 166350723Scg "OPL3-SAx (YMF719)", /* 6 */ 166450723Scg "OPL3-SAx (YMF719)", /* 7 */ 166550723Scg }; 166629415Sjmg 166750723Scg for (p = 0; p < 3; p++) { 166850723Scg mss->conf_rid = 1; 166950723Scg mss->conf_base = bus_alloc_resource(dev, 167050723Scg SYS_RES_IOPORT, 167150723Scg &mss->conf_rid, 167250723Scg ports[p], ports[p] + 1, 2, 167350723Scg RF_ACTIVE); 167450723Scg if (!mss->conf_base) return 0; 167529415Sjmg 167650723Scg /* Test the index port of the config registers */ 167750723Scg i = port_rd(mss->conf_base, 0); 167850723Scg port_wr(mss->conf_base, 0, OPL3SAx_DMACONF); 167950723Scg j = (port_rd(mss->conf_base, 0) == OPL3SAx_DMACONF)? 1 : 0; 168050723Scg port_wr(mss->conf_base, 0, i); 168150723Scg if (!j) { 168250723Scg bus_release_resource(dev, SYS_RES_IOPORT, 168350723Scg mss->conf_rid, mss->conf_base); 168460711Snyan#ifdef PC98 168560711Snyan /* PC98 need this. I don't know reason why. */ 168660711Snyan bus_delete_resource(dev, SYS_RES_IOPORT, mss->conf_rid); 168760711Snyan#endif 168850723Scg mss->conf_base = 0; 168950723Scg continue; 169050723Scg } 169150723Scg version = conf_rd(mss, OPL3SAx_MISC) & 0x07; 169250723Scg return chipset[version]; 169350723Scg } 169450723Scg return NULL; 169529415Sjmg} 169629415Sjmg 169729415Sjmgstatic int 169850723Scgmss_doattach(device_t dev, struct mss_info *mss) 169929415Sjmg{ 170070291Scg int pdma, rdma, flags = device_get_flags(dev); 170184111Scg char status[SND_STATUSLEN], status2[SND_STATUSLEN]; 170229415Sjmg 1703167608Sariff mss->lock = snd_mtxcreate(device_get_nameunit(dev), "snd_mss softc"); 170483619Scg mss->bufsize = pcm_getbuffersize(dev, 4096, MSS_DEFAULT_BUFSZ, 65536); 170550723Scg if (!mss_alloc_resources(mss, dev)) goto no; 170650723Scg mss_init(mss, dev); 170770291Scg pdma = rman_get_start(mss->drq1); 170870291Scg rdma = rman_get_start(mss->drq2); 170950723Scg if (flags & DV_F_TRUE_MSS) { 171050723Scg /* has IRQ/DMA registers, set IRQ and DMA addr */ 171160711Snyan#ifdef PC98 /* CS423[12] in PC98 can use IRQ3,5,10,12 */ 171260711Snyan static char interrupt_bits[13] = 171360711Snyan {-1, -1, -1, 0x08, -1, 0x10, -1, -1, -1, -1, 0x18, -1, 0x20}; 171460711Snyan#else 171550723Scg static char interrupt_bits[12] = 171650723Scg {-1, -1, -1, -1, -1, 0x28, -1, 0x08, -1, 0x10, 0x18, 0x20}; 171760711Snyan#endif 171850723Scg static char pdma_bits[4] = {1, 2, -1, 3}; 171950723Scg static char valid_rdma[4] = {1, 0, -1, 0}; 172050723Scg char bits; 172129415Sjmg 172250723Scg if (!mss->irq || (bits = interrupt_bits[rman_get_start(mss->irq)]) == -1) 172350723Scg goto no; 172460711Snyan#ifndef PC98 /* CS423[12] in PC98 don't support this. */ 172550723Scg io_wr(mss, 0, bits | 0x40); /* config port */ 172650723Scg if ((io_rd(mss, 3) & 0x40) == 0) device_printf(dev, "IRQ Conflict?\n"); 172760711Snyan#endif 172850723Scg /* Write IRQ+DMA setup */ 172970291Scg if (pdma_bits[pdma] == -1) goto no; 173070291Scg bits |= pdma_bits[pdma]; 173170291Scg if (pdma != rdma) { 173270291Scg if (rdma == valid_rdma[pdma]) bits |= 4; 173350723Scg else { 173470291Scg printf("invalid dual dma config %d:%d\n", pdma, rdma); 173550723Scg goto no; 173650723Scg } 173750723Scg } 173850723Scg io_wr(mss, 0, bits); 173950723Scg printf("drq/irq conf %x\n", io_rd(mss, 0)); 174050723Scg } 174170134Scg mixer_init(dev, (mss->bd_id == MD_YM0020)? &ymmix_mixer_class : &mssmix_mixer_class, mss); 174250723Scg switch (mss->bd_id) { 174350723Scg case MD_OPTI931: 1744128232Sgreen snd_setup_intr(dev, mss->irq, 0, opti931_intr, mss, &mss->ih); 174550723Scg break; 174650723Scg default: 1747128232Sgreen snd_setup_intr(dev, mss->irq, 0, mss_intr, mss, &mss->ih); 174850723Scg } 174970291Scg if (pdma == rdma) 175050723Scg pcm_setflags(dev, pcm_getflags(dev) | SD_F_SIMPLEX); 1751166904Snetchild if (bus_dma_tag_create(/*parent*/bus_get_dma_tag(dev), /*alignment*/2, 1752166904Snetchild /*boundary*/0, 175350723Scg /*lowaddr*/BUS_SPACE_MAXADDR_24BIT, 175450723Scg /*highaddr*/BUS_SPACE_MAXADDR, 175550723Scg /*filter*/NULL, /*filterarg*/NULL, 175683619Scg /*maxsize*/mss->bufsize, /*nsegments*/1, 1757117126Sscottl /*maxsegz*/0x3ffff, /*flags*/0, 1758117126Sscottl /*lockfunc*/busdma_lock_mutex, /*lockarg*/&Giant, 1759117126Sscottl &mss->parent_dmat) != 0) { 176050723Scg device_printf(dev, "unable to create dma tag\n"); 176150723Scg goto no; 176250723Scg } 176329415Sjmg 176484111Scg if (pdma != rdma) 176584111Scg snprintf(status2, SND_STATUSLEN, ":%d", rdma); 176684111Scg else 176784111Scg status2[0] = '\0'; 176884111Scg 176984111Scg snprintf(status, SND_STATUSLEN, "at io 0x%lx irq %ld drq %d%s bufsz %u", 177084111Scg rman_get_start(mss->io_base), rman_get_start(mss->irq), pdma, status2, mss->bufsize); 177184111Scg 177250723Scg if (pcm_register(dev, mss, 1, 1)) goto no; 177370134Scg pcm_addchan(dev, PCMDIR_REC, &msschan_class, mss); 177470134Scg pcm_addchan(dev, PCMDIR_PLAY, &msschan_class, mss); 177550723Scg pcm_setstatus(dev, status); 177629415Sjmg 177750723Scg return 0; 177850723Scgno: 177950723Scg mss_release_resources(mss, dev); 178050723Scg return ENXIO; 178150723Scg} 178250723Scg 178329415Sjmgstatic int 178465644Scgmss_detach(device_t dev) 178565644Scg{ 178665644Scg int r; 178765644Scg struct mss_info *mss; 178865644Scg 178965644Scg r = pcm_unregister(dev); 179065644Scg if (r) 179165644Scg return r; 179265644Scg 179365644Scg mss = pcm_getdevinfo(dev); 179465644Scg mss_release_resources(mss, dev); 179565644Scg 179665644Scg return 0; 179765644Scg} 179865644Scg 179965644Scgstatic int 180050723Scgmss_attach(device_t dev) 180129415Sjmg{ 180250723Scg struct mss_info *mss; 180351052Sdfr int flags = device_get_flags(dev); 180429415Sjmg 180578564Sgreid mss = (struct mss_info *)malloc(sizeof *mss, M_DEVBUF, M_NOWAIT | M_ZERO); 180650723Scg if (!mss) return ENXIO; 180729415Sjmg 180850723Scg mss->io_rid = 0; 180950723Scg mss->conf_rid = -1; 181050723Scg mss->irq_rid = 0; 181150723Scg mss->drq1_rid = 0; 181250723Scg mss->drq2_rid = -1; 181350723Scg if (flags & DV_F_DUAL_DMA) { 181452174Sdfr bus_set_resource(dev, SYS_RES_DRQ, 1, 181550723Scg flags & DV_F_DRQ_MASK, 1); 181650723Scg mss->drq2_rid = 1; 181750723Scg } 181851052Sdfr mss->bd_id = (device_get_flags(dev) & DV_F_DEV_MASK) >> DV_F_DEV_SHIFT; 181950723Scg if (mss->bd_id == MD_YM0020) ymf_test(dev, mss); 182050723Scg return mss_doattach(dev, mss); 182150723Scg} 182229415Sjmg 182364032Scg/* 182464032Scg * mss_resume() is the code to allow a laptop to resume using the sound 182564032Scg * card. 182664032Scg * 182764032Scg * This routine re-sets the state of the board to the state before going 182864032Scg * to sleep. According to the yamaha docs this is the right thing to do, 182964032Scg * but getting DMA restarted appears to be a bit of a trick, so the device 183064032Scg * has to be closed and re-opened to be re-used, but there is no skipping 183164032Scg * problem, and volume, bass/treble and most other things are restored 183264032Scg * properly. 183364032Scg * 183464032Scg */ 183564032Scg 183664032Scgstatic int 183764032Scgmss_resume(device_t dev) 183864032Scg{ 183964032Scg /* 184064032Scg * Restore the state taken below. 184164032Scg */ 184264032Scg struct mss_info *mss; 184364032Scg int i; 184464032Scg 184564032Scg mss = pcm_getdevinfo(dev); 184664032Scg 1847108925Smdodd if(mss->bd_id == MD_YM0020 || mss->bd_id == MD_CS423X) { 184864032Scg /* This works on a Toshiba Libretto 100CT. */ 184964032Scg for (i = 0; i < MSS_INDEXED_REGS; i++) 185064032Scg ad_write(mss, i, mss->mss_indexed_regs[i]); 185164032Scg for (i = 0; i < OPL_INDEXED_REGS; i++) 185264032Scg conf_wr(mss, i, mss->opl_indexed_regs[i]); 185364032Scg mss_intr(mss); 185464032Scg } 1855108925Smdodd 1856108925Smdodd if (mss->bd_id == MD_CS423X) { 1857108925Smdodd /* Needed on IBM Thinkpad 600E */ 1858142730Smdodd mss_lock(mss); 1859142730Smdodd mss_format(&mss->pch, mss->pch.channel->format); 1860142730Smdodd mss_speed(&mss->pch, mss->pch.channel->speed); 1861142730Smdodd mss_unlock(mss); 1862108925Smdodd } 1863108925Smdodd 186464032Scg return 0; 186564032Scg 186664032Scg} 186764032Scg 186864032Scg/* 186964032Scg * mss_suspend() is the code that gets called right before a laptop 187064032Scg * suspends. 187164032Scg * 187264032Scg * This code saves the state of the sound card right before shutdown 187364032Scg * so it can be restored above. 187464032Scg * 187564032Scg */ 187664032Scg 187764032Scgstatic int 187864032Scgmss_suspend(device_t dev) 187964032Scg{ 188064032Scg int i; 188164032Scg struct mss_info *mss; 188264032Scg 188364032Scg mss = pcm_getdevinfo(dev); 188464032Scg 1885108925Smdodd if(mss->bd_id == MD_YM0020 || mss->bd_id == MD_CS423X) 188664032Scg { 188764032Scg /* this stops playback. */ 188864032Scg conf_wr(mss, 0x12, 0x0c); 188964032Scg for(i = 0; i < MSS_INDEXED_REGS; i++) 189064032Scg mss->mss_indexed_regs[i] = ad_read(mss, i); 189164032Scg for(i = 0; i < OPL_INDEXED_REGS; i++) 189264032Scg mss->opl_indexed_regs[i] = conf_rd(mss, i); 189364032Scg mss->opl_indexed_regs[0x12] = 0x0; 189464032Scg } 189564032Scg return 0; 189664032Scg} 189764032Scg 189850723Scgstatic device_method_t mss_methods[] = { 189950723Scg /* Device interface */ 190050723Scg DEVMETHOD(device_probe, mss_probe), 190150723Scg DEVMETHOD(device_attach, mss_attach), 190265644Scg DEVMETHOD(device_detach, mss_detach), 190364032Scg DEVMETHOD(device_suspend, mss_suspend), 190464032Scg DEVMETHOD(device_resume, mss_resume), 190533474Sscrappy 190650723Scg { 0, 0 } 190750723Scg}; 190829415Sjmg 190950723Scgstatic driver_t mss_driver = { 191050723Scg "pcm", 191150723Scg mss_methods, 191282180Scg PCM_SOFTC_SIZE, 191350723Scg}; 191450723Scg 191562483ScgDRIVER_MODULE(snd_mss, isa, mss_driver, pcm_devclass, 0, 0); 1916132236StanimuraMODULE_DEPEND(snd_mss, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER); 191762483ScgMODULE_VERSION(snd_mss, 1); 191850723Scg 191990241Stgstatic int 192090241Stgazt2320_mss_mode(struct mss_info *mss, device_t dev) 192190241Stg{ 192290241Stg struct resource *sbport; 192390241Stg int i, ret, rid; 192490241Stg 192590241Stg rid = 0; 192690241Stg ret = -1; 1927127135Snjl sbport = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, RF_ACTIVE); 192890241Stg if (sbport) { 192990241Stg for (i = 0; i < 1000; i++) { 193090241Stg if ((port_rd(sbport, SBDSP_STATUS) & 0x80)) 193190241Stg DELAY((i > 100) ? 1000 : 10); 193290241Stg else { 193390241Stg port_wr(sbport, SBDSP_CMD, 0x09); 193490241Stg break; 193590241Stg } 193690241Stg } 193790241Stg for (i = 0; i < 1000; i++) { 193890241Stg if ((port_rd(sbport, SBDSP_STATUS) & 0x80)) 193990241Stg DELAY((i > 100) ? 1000 : 10); 194090241Stg else { 194190241Stg port_wr(sbport, SBDSP_CMD, 0x00); 194290241Stg ret = 0; 194390241Stg break; 194490241Stg } 194590241Stg } 194690241Stg DELAY(1000); 194790241Stg bus_release_resource(dev, SYS_RES_IOPORT, rid, sbport); 194890241Stg } 194990241Stg return ret; 195090241Stg} 195190241Stg 195254962Speterstatic struct isa_pnp_id pnpmss_ids[] = { 195354962Speter {0x0000630e, "CS423x"}, /* CSC0000 */ 195455279Speter {0x0001630e, "CS423x-PCI"}, /* CSC0100 */ 195554962Speter {0x01000000, "CMI8330"}, /* @@@0001 */ 195654962Speter {0x2100a865, "Yamaha OPL-SAx"}, /* YMH0021 */ 195754962Speter {0x1110d315, "ENSONIQ SoundscapeVIVO"}, /* ENS1011 */ 195854962Speter {0x1093143e, "OPTi931"}, /* OPT9310 */ 195954962Speter {0x5092143e, "OPTi925"}, /* OPT9250 XXX guess */ 196074711Scg {0x0000143e, "OPTi924"}, /* OPT0924 */ 196156449Speter {0x1022b839, "Neomagic 256AV (non-ac97)"}, /* NMX2210 */ 196290241Stg {0x01005407, "Aztech 2320"}, /* AZT0001 */ 196354962Speter#if 0 196454962Speter {0x0000561e, "GusPnP"}, /* GRV0000 */ 196554962Speter#endif 196654962Speter {0}, 196754962Speter}; 196854962Speter 196950723Scgstatic int 197050723Scgpnpmss_probe(device_t dev) 197129415Sjmg{ 197256774Scg u_int32_t lid, vid; 197356774Scg 197456774Scg lid = isa_get_logicalid(dev); 197556774Scg vid = isa_get_vendorid(dev); 197656774Scg if (lid == 0x01000000 && vid != 0x0100a90d) /* CMI0001 */ 197756774Scg return ENXIO; 197854962Speter return ISA_PNP_PROBE(device_get_parent(dev), dev, pnpmss_ids); 197929415Sjmg} 198029415Sjmg 198150723Scgstatic int 198250723Scgpnpmss_attach(device_t dev) 198329415Sjmg{ 198450723Scg struct mss_info *mss; 198529415Sjmg 1986170873Sariff mss = malloc(sizeof(*mss), M_DEVBUF, M_WAITOK | M_ZERO); 198750723Scg mss->io_rid = 0; 198850723Scg mss->conf_rid = -1; 198950723Scg mss->irq_rid = 0; 199050723Scg mss->drq1_rid = 0; 199150723Scg mss->drq2_rid = 1; 199259574Scg mss->bd_id = MD_CS42XX; 199342284Sluigi 199454962Speter switch (isa_get_logicalid(dev)) { 199554962Speter case 0x0000630e: /* CSC0000 */ 199655279Speter case 0x0001630e: /* CSC0100 */ 199754962Speter mss->bd_flags |= BD_F_MSS_OFFSET; 1998108925Smdodd mss->bd_id = MD_CS423X; 199954962Speter break; 200054962Speter 200154962Speter case 0x2100a865: /* YHM0021 */ 200250723Scg mss->io_rid = 1; 200350723Scg mss->conf_rid = 4; 200450723Scg mss->bd_id = MD_YM0020; 200529652Speter break; 200630869Sjmg 200754962Speter case 0x1110d315: /* ENS1011 */ 200850723Scg mss->io_rid = 1; 200950723Scg mss->bd_id = MD_VIVO; 201030869Sjmg break; 201130869Sjmg 201254962Speter case 0x1093143e: /* OPT9310 */ 201350723Scg mss->bd_flags |= BD_F_MSS_OFFSET; 201450723Scg mss->conf_rid = 3; 201550723Scg mss->bd_id = MD_OPTI931; 201629652Speter break; 201742284Sluigi 201854962Speter case 0x5092143e: /* OPT9250 XXX guess */ 201950723Scg mss->io_rid = 1; 202050723Scg mss->conf_rid = 3; 202150723Scg mss->bd_id = MD_OPTI925; 202250723Scg break; 202355879Scg 202474711Scg case 0x0000143e: /* OPT0924 */ 202574711Scg mss->password = 0xe5; 202674711Scg mss->passwdreg = 3; 202774711Scg mss->optibase = 0xf0c; 202874711Scg mss->io_rid = 2; 202974711Scg mss->conf_rid = 3; 203074711Scg mss->bd_id = MD_OPTI924; 203174711Scg mss->bd_flags |= BD_F_924PNP; 2032155336Snetchild if(opti_init(dev, mss) != 0) { 2033155336Snetchild free(mss, M_DEVBUF); 203474711Scg return ENXIO; 2035155336Snetchild } 203674711Scg break; 203774711Scg 203856449Speter case 0x1022b839: /* NMX2210 */ 203955879Scg mss->io_rid = 1; 204055879Scg break; 204156449Speter 204290241Stg case 0x01005407: /* AZT0001 */ 204390241Stg /* put into MSS mode first (snatched from NetBSD) */ 2044155336Snetchild if (azt2320_mss_mode(mss, dev) == -1) { 2045155336Snetchild free(mss, M_DEVBUF); 204690241Stg return ENXIO; 2047155336Snetchild } 204890241Stg 204990241Stg mss->bd_flags |= BD_F_MSS_OFFSET; 205090241Stg mss->io_rid = 2; 205190241Stg break; 205290241Stg 205353553Stanimura#if 0 205454962Speter case 0x0000561e: /* GRV0000 */ 205551120Sdfr mss->bd_flags |= BD_F_MSS_OFFSET; 205650723Scg mss->io_rid = 2; 205750723Scg mss->conf_rid = 1; 205850723Scg mss->drq1_rid = 1; 205950723Scg mss->drq2_rid = 0; 206050723Scg mss->bd_id = MD_GUSPNP; 206150723Scg break; 206253553Stanimura#endif 206359574Scg case 0x01000000: /* @@@0001 */ 206459574Scg mss->drq2_rid = -1; 206559574Scg break; 206659574Scg 206754962Speter /* Unknown MSS default. We could let the CSC0000 stuff match too */ 206850723Scg default: 206950723Scg mss->bd_flags |= BD_F_MSS_OFFSET; 207050723Scg break; 207150723Scg } 207250723Scg return mss_doattach(dev, mss); 207329415Sjmg} 207429415Sjmg 207574711Scgstatic int 207674711Scgopti_init(device_t dev, struct mss_info *mss) 207774711Scg{ 207874711Scg int flags = device_get_flags(dev); 207974711Scg int basebits = 0; 208074711Scg 208174711Scg if (!mss->conf_base) { 208274711Scg bus_set_resource(dev, SYS_RES_IOPORT, mss->conf_rid, 208374711Scg mss->optibase, 0x9); 208474711Scg 208574711Scg mss->conf_base = bus_alloc_resource(dev, SYS_RES_IOPORT, 208674711Scg &mss->conf_rid, mss->optibase, mss->optibase+0x9, 208774711Scg 0x9, RF_ACTIVE); 208874711Scg } 208974711Scg 209074711Scg if (!mss->conf_base) 209174711Scg return ENXIO; 209274711Scg 209374711Scg if (!mss->io_base) 209474711Scg mss->io_base = bus_alloc_resource(dev, SYS_RES_IOPORT, 209574711Scg &mss->io_rid, 0, ~0, 8, RF_ACTIVE); 209674711Scg 209774711Scg if (!mss->io_base) /* No hint specified, use 0x530 */ 209874711Scg mss->io_base = bus_alloc_resource(dev, SYS_RES_IOPORT, 209974711Scg &mss->io_rid, 0x530, 0x537, 8, RF_ACTIVE); 210074711Scg 210174711Scg if (!mss->io_base) 210274711Scg return ENXIO; 210374711Scg 210474711Scg switch (rman_get_start(mss->io_base)) { 210574711Scg case 0x530: 210674711Scg basebits = 0x0; 210774711Scg break; 210874711Scg case 0xe80: 210974711Scg basebits = 0x10; 211074711Scg break; 211174711Scg case 0xf40: 211274711Scg basebits = 0x20; 211374711Scg break; 211474711Scg case 0x604: 211574711Scg basebits = 0x30; 211674711Scg break; 211774711Scg default: 211874711Scg printf("opti_init: invalid MSS base address!\n"); 211974711Scg return ENXIO; 212074711Scg } 212174711Scg 212274711Scg 212374711Scg switch (mss->bd_id) { 212474711Scg case MD_OPTI924: 212574711Scg opti_write(mss, 1, 0x80 | basebits); /* MSS mode */ 212674711Scg opti_write(mss, 2, 0x00); /* Disable CD */ 212774711Scg opti_write(mss, 3, 0xf0); /* Disable SB IRQ */ 212874711Scg opti_write(mss, 4, 0xf0); 212974711Scg opti_write(mss, 5, 0x00); 213074711Scg opti_write(mss, 6, 0x02); /* MPU stuff */ 213174711Scg break; 213274711Scg 213374711Scg case MD_OPTI930: 213474711Scg opti_write(mss, 1, 0x00 | basebits); 213574711Scg opti_write(mss, 3, 0x00); /* Disable SB IRQ/DMA */ 213674711Scg opti_write(mss, 4, 0x52); /* Empty FIFO */ 213774711Scg opti_write(mss, 5, 0x3c); /* Mode 2 */ 213874711Scg opti_write(mss, 6, 0x02); /* Enable MSS */ 213974711Scg break; 214074711Scg } 214174711Scg 214274711Scg if (mss->bd_flags & BD_F_924PNP) { 214374711Scg u_int32_t irq = isa_get_irq(dev); 214474711Scg u_int32_t drq = isa_get_drq(dev); 214574711Scg bus_set_resource(dev, SYS_RES_IRQ, 0, irq, 1); 214674711Scg bus_set_resource(dev, SYS_RES_DRQ, mss->drq1_rid, drq, 1); 214774711Scg if (flags & DV_F_DUAL_DMA) { 214874711Scg bus_set_resource(dev, SYS_RES_DRQ, 1, 214974711Scg flags & DV_F_DRQ_MASK, 1); 215074711Scg mss->drq2_rid = 1; 215174711Scg } 215274711Scg } 215374711Scg 215474711Scg /* OPTixxx has I/DRQ registers */ 215574711Scg 215674711Scg device_set_flags(dev, device_get_flags(dev) | DV_F_TRUE_MSS); 215774711Scg 215874711Scg return 0; 215974711Scg} 216074711Scg 216174711Scgstatic void 216274711Scgopti_write(struct mss_info *mss, u_char reg, u_char val) 216374711Scg{ 216474711Scg port_wr(mss->conf_base, mss->passwdreg, mss->password); 216574711Scg 216674711Scg switch(mss->bd_id) { 216774711Scg case MD_OPTI924: 216874711Scg if (reg > 7) { /* Indirect register */ 216974711Scg port_wr(mss->conf_base, mss->passwdreg, reg); 217074711Scg port_wr(mss->conf_base, mss->passwdreg, 217174711Scg mss->password); 217274711Scg port_wr(mss->conf_base, 9, val); 217374711Scg return; 217474711Scg } 217574711Scg port_wr(mss->conf_base, reg, val); 217674711Scg break; 217774711Scg 217876635Sgreid case MD_OPTI930: 217974711Scg port_wr(mss->indir, 0, reg); 218074711Scg port_wr(mss->conf_base, mss->passwdreg, mss->password); 218174711Scg port_wr(mss->indir, 1, val); 218274711Scg break; 218374711Scg } 218474711Scg} 218574711Scg 2186150038Snyan#ifndef PC98 218774711Scgu_char 218874711Scgopti_read(struct mss_info *mss, u_char reg) 218974711Scg{ 219074711Scg port_wr(mss->conf_base, mss->passwdreg, mss->password); 219174711Scg 219274711Scg switch(mss->bd_id) { 219374711Scg case MD_OPTI924: 219474711Scg if (reg > 7) { /* Indirect register */ 219574711Scg port_wr(mss->conf_base, mss->passwdreg, reg); 219674711Scg port_wr(mss->conf_base, mss->passwdreg, mss->password); 219774711Scg return(port_rd(mss->conf_base, 9)); 219874711Scg } 219974711Scg return(port_rd(mss->conf_base, reg)); 220074711Scg break; 220174711Scg 220274711Scg case MD_OPTI930: 220374711Scg port_wr(mss->indir, 0, reg); 220474711Scg port_wr(mss->conf_base, mss->passwdreg, mss->password); 220574711Scg return port_rd(mss->indir, 1); 220674711Scg break; 220774711Scg } 220874711Scg return -1; 220974711Scg} 2210150038Snyan#endif 221174711Scg 221250723Scgstatic device_method_t pnpmss_methods[] = { 221350723Scg /* Device interface */ 221450723Scg DEVMETHOD(device_probe, pnpmss_probe), 221550723Scg DEVMETHOD(device_attach, pnpmss_attach), 221665644Scg DEVMETHOD(device_detach, mss_detach), 221764032Scg DEVMETHOD(device_suspend, mss_suspend), 221864032Scg DEVMETHOD(device_resume, mss_resume), 221950723Scg 222050723Scg { 0, 0 } 222129415Sjmg}; 222229415Sjmg 222350723Scgstatic driver_t pnpmss_driver = { 222450723Scg "pcm", 222550723Scg pnpmss_methods, 222682180Scg PCM_SOFTC_SIZE, 222750723Scg}; 222829415Sjmg 222962483ScgDRIVER_MODULE(snd_pnpmss, isa, pnpmss_driver, pcm_devclass, 0, 0); 2230136410SnjlDRIVER_MODULE(snd_pnpmss, acpi, pnpmss_driver, pcm_devclass, 0, 0); 2231132236StanimuraMODULE_DEPEND(snd_pnpmss, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER); 223262483ScgMODULE_VERSION(snd_pnpmss, 1); 223350723Scg 223442284Sluigistatic int 223553553Stanimuraguspcm_probe(device_t dev) 223653553Stanimura{ 223753553Stanimura struct sndcard_func *func; 223853553Stanimura 223953553Stanimura func = device_get_ivars(dev); 224053553Stanimura if (func == NULL || func->func != SCF_PCM) 224153553Stanimura return ENXIO; 224253553Stanimura 224353553Stanimura device_set_desc(dev, "GUS CS4231"); 224453553Stanimura return 0; 224553553Stanimura} 224653553Stanimura 224753553Stanimurastatic int 224853553Stanimuraguspcm_attach(device_t dev) 224953553Stanimura{ 225053553Stanimura device_t parent = device_get_parent(dev); 225153553Stanimura struct mss_info *mss; 225253553Stanimura int base, flags; 225353553Stanimura unsigned char ctl; 225453553Stanimura 225578564Sgreid mss = (struct mss_info *)malloc(sizeof *mss, M_DEVBUF, M_NOWAIT | M_ZERO); 225653553Stanimura if (mss == NULL) 225753553Stanimura return ENOMEM; 225853553Stanimura 225953553Stanimura mss->bd_flags = BD_F_MSS_OFFSET; 226053553Stanimura mss->io_rid = 2; 226153553Stanimura mss->conf_rid = 1; 226253553Stanimura mss->irq_rid = 0; 226353553Stanimura mss->drq1_rid = 1; 226453553Stanimura mss->drq2_rid = -1; 226553553Stanimura 226662947Stanimura if (isa_get_logicalid(parent) == 0) 226753553Stanimura mss->bd_id = MD_GUSMAX; 226853553Stanimura else { 226953553Stanimura mss->bd_id = MD_GUSPNP; 227053553Stanimura mss->drq2_rid = 0; 227153553Stanimura goto skip_setup; 227253553Stanimura } 227353553Stanimura 227453553Stanimura flags = device_get_flags(parent); 227553553Stanimura if (flags & DV_F_DUAL_DMA) 227653553Stanimura mss->drq2_rid = 0; 227753553Stanimura 227853553Stanimura mss->conf_base = bus_alloc_resource(dev, SYS_RES_IOPORT, &mss->conf_rid, 227953553Stanimura 0, ~0, 8, RF_ACTIVE); 228053553Stanimura 228153553Stanimura if (mss->conf_base == NULL) { 228253553Stanimura mss_release_resources(mss, dev); 228353553Stanimura return ENXIO; 228453553Stanimura } 228553553Stanimura 228653553Stanimura base = isa_get_port(parent); 228753553Stanimura 228853553Stanimura ctl = 0x40; /* CS4231 enable */ 228953553Stanimura if (isa_get_drq(dev) > 3) 229053553Stanimura ctl |= 0x10; /* 16-bit dma channel 1 */ 229153553Stanimura if ((flags & DV_F_DUAL_DMA) != 0 && (flags & DV_F_DRQ_MASK) > 3) 229253553Stanimura ctl |= 0x20; /* 16-bit dma channel 2 */ 229353553Stanimura ctl |= (base >> 4) & 0x0f; /* 2X0 -> 3XC */ 229453553Stanimura port_wr(mss->conf_base, 6, ctl); 229553553Stanimura 229653553Stanimuraskip_setup: 229753553Stanimura return mss_doattach(dev, mss); 229853553Stanimura} 229953553Stanimura 230053553Stanimurastatic device_method_t guspcm_methods[] = { 230153553Stanimura DEVMETHOD(device_probe, guspcm_probe), 230253553Stanimura DEVMETHOD(device_attach, guspcm_attach), 230365644Scg DEVMETHOD(device_detach, mss_detach), 230453553Stanimura 230553553Stanimura { 0, 0 } 230653553Stanimura}; 230753553Stanimura 230853553Stanimurastatic driver_t guspcm_driver = { 230953553Stanimura "pcm", 231053553Stanimura guspcm_methods, 231182180Scg PCM_SOFTC_SIZE, 231253553Stanimura}; 231353553Stanimura 231462483ScgDRIVER_MODULE(snd_guspcm, gusc, guspcm_driver, pcm_devclass, 0, 0); 2315132236StanimuraMODULE_DEPEND(snd_guspcm, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER); 231662483ScgMODULE_VERSION(snd_guspcm, 1); 231753553Stanimura 231862483Scg 2319