47#ifdef HAVE_KERNEL_OPTION_HEADERS
58#include <sys/sysctl.h>
67#define CMI8338A_PCI_ID 0x010013f6
68#define CMI8338B_PCI_ID 0x010113f6
69#define CMI8738_PCI_ID 0x011113f6
70#define CMI8738B_PCI_ID 0x011213f6
71#define CMI120_USB_ID 0x01030d8c
74#define CMI_DEFAULT_BUFSZ 16384
77#define CMI_INTR_PER_BUFFER 2
80#define CMPCI_REG_DMA0_MAX_SAMPLES CMPCI_REG_DMA0_BYTES
81#define CMPCI_REG_DMA0_INTR_SAMPLES CMPCI_REG_DMA0_SAMPLES
82#define CMPCI_REG_DMA1_MAX_SAMPLES CMPCI_REG_DMA1_BYTES
83#define CMPCI_REG_DMA1_INTR_SAMPLES CMPCI_REG_DMA1_SAMPLES
86#define CMPCI_NON_SB16_CONTROL 0xff
116 bus_space_handle_t
sh;
118 struct resource *
reg, *
irq;
155 return bus_space_read_1(sc->
st, sc->
sh,
regno);
157 return bus_space_read_2(sc->
st, sc->
sh,
regno);
159 return bus_space_read_4(sc->
st, sc->
sh,
regno);
184 int reg,
int shift, u_int32_t
mask, u_int32_t val)
189 r &= ~(
mask << shift);
218 22050, 32000, 44100, 48000};
219#define NUM_CMI_RATES (sizeof(cmi_rates)/sizeof(cmi_rates[0]))
237 r = ((i >> 1) | (i << 2)) & 0x07;
246 i = ((
r << 1) | (
r >> 2)) & 0x07;
247 DEB(printf(
"cmpci_regvalue_to_rate: %d -> %d\n",
r, i));
265 s = sz / ch->
bps - 1;
305 DEB(printf(
"cmi_ch1_start: dma prog\n"));
324 u_int32_t fcr1, lcr, mcr;
326 if (
speed >= 44100) {
329 mcr = (
speed == 48000) ?
332 fcr1 = mcr = lcr = 0;
361 DEB(printf(
"cmichan_init failed\n"));
384 if (
format & AFMT_S16_LE) {
458 DEB(printf(
"cmichan_setspeed (%s) %d -> %d (%d)\n",
520 u_int32_t physptr, bufptr, sz;
623}
static const cmt[SOUND_MIXER_NRDEVICES] = {
648#define MIXER_GAIN_REG_RTOL(r) (r - 1)
656 for(i = v = 0; i < SOUND_MIXER_NRDEVICES; i++) {
657 if (
cmt[i].bits) v |= 1 << i;
661 for(i = v = 0; i < SOUND_MIXER_NRDEVICES; i++) {
662 if (
cmt[i].rec) v |= 1 << i;
689 v |= ((l << 1) | (~l >> 3)) & 0x0f;
699 DEBMIX(printf(
"Mixer stereo write dev %d reg 0x%02x "\
700 "value 0x%02x:0x%02x\n",
705 DEBMIX(printf(
"Mixer mono write dev %d reg 0x%02x " \
706 "value 0x%02x:0x%02x\n",
712 if (l == 0 &&
r == 0) {
713 v &= ~cmt[
dev].oselect;
729 for(i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
739 DEBMIX(printf(
"cmimix_setrecsrc: reg 0x%02x val 0x%02x\n",
743 DEBMIX(printf(
"cmimix_setrecsrc: reg 0x%02x val 0x%02x\n",
759 SYSCTL_ADD_INT(device_get_sysctl_ctx(sc->
dev),
760 SYSCTL_CHILDREN(device_get_sysctl_tree(sc->
dev)),
761 OID_AUTO,
"spdif_enabled", CTLFLAG_RW,
763 "enable SPDIF output at 44.1 kHz and above");
786 d = bus_space_read_1(0,0, 0x330 +
reg);
796 bus_space_write_1(0,0,0x330 +
reg ,
b);
910 switch(pci_get_devid(
dev)) {
912 device_set_desc(
dev,
"CMedia CMI8338A");
913 return BUS_PROBE_DEFAULT;
915 device_set_desc(
dev,
"CMedia CMI8338B");
916 return BUS_PROBE_DEFAULT;
918 device_set_desc(
dev,
"CMedia CMI8738");
919 return BUS_PROBE_DEFAULT;
921 device_set_desc(
dev,
"CMedia CMI8738B");
922 return BUS_PROBE_DEFAULT;
924 device_set_desc(
dev,
"CMedia CMI120");
925 return BUS_PROBE_DEFAULT;
937 sc = malloc(
sizeof(*sc), M_DEVBUF, M_WAITOK | M_ZERO);
939 pci_enable_busmaster(
dev);
943 sc->
reg = bus_alloc_resource_any(
dev, SYS_RES_IOPORT, &sc->
regid,
946 device_printf(
dev,
"cmi_attach: Cannot allocate bus resource\n");
949 sc->
st = rman_get_bustag(sc->
reg);
950 sc->
sh = rman_get_bushandle(sc->
reg);
956 sc->
irq = bus_alloc_resource_any(
dev, SYS_RES_IRQ, &sc->
irqid,
957 RF_ACTIVE | RF_SHAREABLE);
960 device_printf(
dev,
"cmi_attach: Unable to map interrupt\n");
966 if (bus_dma_tag_create(bus_get_dma_tag(
dev), 2,
968 BUS_SPACE_MAXADDR_32BIT,
976 device_printf(
dev,
"cmi_attach: Unable to create dma tag\n");
999 DEB(printf(
"cmi_attach: succeeded\n"));
1006 bus_teardown_intr(
dev, sc->
irq, sc->
ih);
1008 bus_release_resource(
dev, SYS_RES_IRQ, sc->
irqid, sc->
irq);
1010 bus_release_resource(
dev, SYS_RES_IOPORT, sc->
regid, sc->
reg);
1033 bus_teardown_intr(
dev, sc->
irq, sc->
ih);
1034 bus_release_resource(
dev, SYS_RES_IRQ, sc->
irqid, sc->
irq);
1037 bus_release_resource(
dev, SYS_RES_IOPORT, sc->
regid, sc->
reg);
1068 device_printf(
dev,
"unable to reinitialize the card\n");
1074 device_printf(
dev,
"unable to reinitialize the mixer\n");
int sndbuf_alloc(struct snd_dbuf *b, bus_dma_tag_t dmatag, int dmaflags, unsigned int size)
bus_addr_t sndbuf_getbufaddr(struct snd_dbuf *buf)
unsigned int sndbuf_getsize(struct snd_dbuf *b)
int sndbuf_resize(struct snd_dbuf *b, unsigned int blkcnt, unsigned int blksz)
void chn_intr(struct pcm_channel *c)
#define PCMTRIG_COMMON(x)
struct pcmchan_matrix * m
static void cmi_set4(struct sc_info *sc, int reg, u_int32_t mask)
static int cmi_probe(device_t dev)
static int cmimix_init(struct snd_mixer *m)
static u_int32_t cmichan_setspeed(kobj_t obj, void *data, u_int32_t speed)
static void cmi_wr(struct sc_info *sc, int regno, u_int32_t data, int size)
static u_int32_t cmi_ch1_stop(struct sc_info *sc, struct sc_chinfo *ch)
static void cmi_ch1_start(struct sc_info *sc, struct sc_chinfo *ch)
static unsigned char cmi_mread(struct mpu401 *arg, void *sc, int reg)
static void cmi_clr4(struct sc_info *sc, int reg, u_int32_t mask)
static void cmi_ch0_start(struct sc_info *sc, struct sc_chinfo *ch)
static kobj_method_t cmi_mixer_methods[]
static int cmi_init(struct sc_info *sc)
static u_int8_t cmimix_rd(struct sc_info *sc, u_int8_t port)
static DEFINE_CLASS(cmi_mpu, cmi_mpu_methods, 0)
static kobj_method_t cmi_mpu_methods[]
static u_int32_t cmichan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
static u_int32_t cmi_rd(struct sc_info *sc, int regno, int size)
static int cmichan_trigger(kobj_t obj, void *data, int go)
static u_int32_t cmimix_setrecsrc(struct snd_mixer *m, u_int32_t src)
static u_int32_t cmichan_getptr(kobj_t obj, void *data)
static void * cmichan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir)
static int cmi_suspend(device_t dev)
#define MIXER_GAIN_REG_RTOL(r)
static int cmi_resume(device_t dev)
SND_DECLARE_FILE("$FreeBSD$")
static int cmpci_regvalue_to_rate(u_int32_t r)
static device_method_t cmi_methods[]
static int cmimix_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right)
static void cmi_partial_wr4(struct sc_info *sc, int reg, int shift, u_int32_t mask, u_int32_t val)
#define CMPCI_NON_SB16_CONTROL
DRIVER_MODULE(snd_cmi, pci, cmi_driver, pcm_devclass, 0, 0)
static driver_t cmi_driver
MODULE_VERSION(snd_cmi, 1)
static int cmi_initsys(struct sc_info *sc)
#define CMI_INTR_PER_BUFFER
static int cmi_muninit(struct mpu401 *arg, void *cookie)
static void cmimix_wr(struct sc_info *sc, u_int8_t port, u_int8_t val)
static void cmi_spdif_speed(struct sc_info *sc, int speed)
static void cmi_uninit(struct sc_info *sc)
static struct pcmchan_caps * cmichan_getcaps(kobj_t obj, void *data)
static u_int32_t cmi_fmt[]
static void cmi_intr(void *data)
static void cmi_mwrite(struct mpu401 *arg, void *sc, int reg, unsigned char b)
struct sb16props cmt[SOUND_MIXER_NRDEVICES]
static int cmi_attach(device_t dev)
static void cmi_midiattach(struct sc_info *sc)
static kobj_method_t cmichan_methods[]
static struct pcmchan_caps cmi_caps
static void cmi_dma_prog(struct sc_info *sc, struct sc_chinfo *ch, u_int32_t base)
static int cmichan_setformat(kobj_t obj, void *data, u_int32_t format)
static u_int32_t cmi_ch0_stop(struct sc_info *sc, struct sc_chinfo *ch)
static u_int32_t cmpci_rate_to_regvalue(int rate)
static int cmi_detach(device_t dev)
static void cmi_power(struct sc_info *sc, int state)
#define CMI_DEFAULT_BUFSZ
MODULE_DEPEND(snd_cmi, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER)
#define CMPCI_REG_AUX_MIC
#define CMPCI_REG_CH0_FORMAT_SHIFT
#define CMPCI_SB16_SW_MIC
#define CMPCI_REG_INTR_STATUS
#define CMPCI_SB16_SW_LINE
#define CMPCI_REG_CH1_FORMAT_SHIFT
#define CMPCI_REG_VMPUSEL_MASK
#define CMPCI_SB16_MIXER_TREBLE_R
#define CMPCI_REG_XSPDIF_ENABLE
#define CMPCI_SB16_MIXER_CDDA_R
#define CMPCI_REG_DAC_FS_SHIFT
#define CMPCI_REG_DMA1_BASE
#define CMPCI_SB16_MIXER_MASTER_R
#define CMPCI_SB16_MIXER_OUTMIX
#define CMPCI_REG_ADC_FS_MASK
#define CMPCI_SB16_MIXER_BASS_R
#define CMPCI_REG_TDMA_INTR_ENABLE
#define CMPCI_REG_ADC_FS_SHIFT
#define CMPCI_REG_CH0_INTR_ENABLE
#define CMPCI_SB16_MIXER_OUTGAIN_R
#define CMPCI_REG_UART_ENABLE
#define CMPCI_REG_CH1_ENABLE
#define CMPCI_SB16_MIXER_VOICE_R
#define CMPCI_SB16_MIXER_LINE_R
#define CMPCI_REG_ANY_INTR
#define CMPCI_REG_FORMAT_8BIT
#define CMPCI_REG_CH0_INTR
#define CMPCI_REG_BUS_AND_DSP_RESET
#define CMPCI_SB16_MIXER_RESET
#define CMPCI_SB16_MIXER_INGAIN_R
#define CMPCI_REG_CH0_FORMAT_MASK
#define CMPCI_REG_N4SPK3D
#define CMPCI_SB16_MIXER_FM_R
#define CMPCI_REG_CH1_FORMAT_MASK
#define CMPCI_REG_CH0_RESET
#define CMPCI_REG_CH1_INTR
#define CMPCI_SB16_MIXER_FM_SRC_R
#define CMPCI_REG_INTR_CTRL
#define CMPCI_REG_CH1_RESET
#define CMPCI_REG_SPDIF0_ENABLE
#define CMPCI_REG_POWER_DOWN
#define CMPCI_REG_SPDIF_48K
#define CMPCI_REG_CH0_ENABLE
#define CMPCI_REG_FORMAT_16BIT
#define CMPCI_SB16_MIXER_ADCMIX_L
#define CMPCI_REG_DMA0_BASE
#define CMPCI_REG_DAC_FS_MASK
#define CMPCI_REG_SPDIF_LOOP
#define CMPCI_REG_FORMAT_STEREO
#define CMPCI_REG_CHANNEL_FORMAT
#define CMPCI_SB16_MIXER_ADCMIX_R
#define CMPCI_SB16_MIXER_SRC_R_TO_L(v)
#define CMPCI_REG_CH1_DIR
#define CMPCI_SB16_MIXER_MIC_SRC
#define CMPCI_REG_W_SPDIF_48L
#define CMPCI_REG_CH0_DIR
#define CMPCI_REG_LEGACY_CTRL
#define CMPCI_SB16_MIXER_SPEAKER
#define CMPCI_REG_VMPUSEL_SHIFT
#define CMPCI_SB16_MIXER_MIC
#define CMPCI_REG_FORMAT_MONO
#define CMPCI_REG_CH1_INTR_ENABLE
#define CMPCI_SB16_MIXER_CD_SRC_R
#define CMPCI_SB16_MIXER_LINE_SRC_R
#define CMPCI_REG_SPDIF1_ENABLE
static int mixer_setrecsrc(struct snd_mixer *mixer, u_int32_t src)
int mixer_init(device_t dev, kobj_class_t cls, void *devinfo)
static int mixer_set(struct snd_mixer *m, u_int dev, u_int32_t muted, u_int lev)
void mix_setdevs(struct snd_mixer *m, u_int32_t v)
int mixer_reinit(device_t dev)
void * mix_getdevinfo(struct snd_mixer *m)
void mix_setrecdevs(struct snd_mixer *m, u_int32_t v)
Record mask of available recording devices.
int mpu401_uninit(struct mpu401 *m)
struct mpu401 * mpu401_init(kobj_class_t cls, void *cookie, driver_intr_t softintr, mpu401_intr_t **cb)
int mpu401_intr_t(struct mpu401 *_obj)
void * snd_mtxcreate(const char *desc, const char *type)
void * pcm_getdevinfo(device_t dev)
int pcm_setstatus(device_t dev, char *str)
void snd_mtxfree(void *m)
int pcm_addchan(device_t dev, int dir, kobj_class_t cls, void *devinfo)
int pcm_unregister(device_t dev)
int pcm_register(device_t dev, void *devinfo, int numplay, int numrec)
int snd_setup_intr(device_t dev, struct resource *res, int flags, driver_intr_t hand, void *param, void **cookiep)
unsigned int pcm_getbuffersize(device_t dev, unsigned int minbufsz, unsigned int deflt, unsigned int maxbufsz)
#define SND_FORMAT(f, c, e)
#define DSP_DEFAULT_SPEED
struct pcm_channel * channel
bus_space_handle_t mpu_bh
bus_dma_tag_t parent_dmat
struct resource * mpu_reg