58#ifdef HAVE_KERNEL_OPTION_HEADERS
67#include <sys/sysctl.h>
68#include <sys/endian.h>
74#define ATI_IXP_DMA_RETRY_MAX 100
76#define ATI_IXP_BUFSZ_MIN 4096
77#define ATI_IXP_BUFSZ_MAX 65536
78#define ATI_IXP_BUFSZ_DEFAULT 16384
80#define ATI_IXP_BLK_MIN 32
81#define ATI_IXP_BLK_ALIGN (~(ATI_IXP_BLK_MIN - 1))
83#define ATI_IXP_CHN_RUNNING 0x00000001
84#define ATI_IXP_CHN_SUSPEND 0x00000002
113 bus_space_handle_t
sh;
139#define atiixp_rd(_sc, _reg) \
140 bus_space_read_4((_sc)->st, (_sc)->sh, _reg)
141#define atiixp_wr(_sc, _reg, _val) \
142 bus_space_write_4((_sc)->st, (_sc)->sh, _reg, _val)
144#define atiixp_lock(_sc) snd_mtxlock((_sc)->lock)
145#define atiixp_unlock(_sc) snd_mtxunlock((_sc)->lock)
146#define atiixp_assert(_sc) snd_mtxassert((_sc)->lock)
191static int atiixp_wrcd(kobj_t,
void *,
int, uint32_t);
206static void atiixp_dma_cb(
void *, bus_dma_segment_t *,
int,
int);
263 uint32_t
value, timeout;
269 value &= ~ATI_REG_CMD_POWERDOWN;
287 value &= ~ATI_REG_CMD_AC_SOFT_RESET;
295 device_printf(sc->
dev,
"not up; resetting aclink hardware\n");
299 value &= ~ATI_REG_CMD_AC_RESET;
317 device_printf(sc->
dev,
"giving up aclink reset\n");
320 device_printf(sc->
dev,
"aclink hardware reset successful\n");
354 value &= ~ch->enable_bit;
404 device_printf(sc->
dev,
"codec read timeout! (reg 0x%x)\n",
reg);
497 value &= ~ATI_REG_CMD_INTERLEAVE_IN;
503 value &= ~ATI_REG_OUT_DMA_SLOT_MASK;
510 value &= ~ATI_REG_CMD_INTERLEAVE_OUT;
515 value &= ~ATI_REG_6CH_REORDER_EN;
561 device_printf(sc->
dev,
"%s: failed blksz=%u blkcnt=%u\n",
598 for (i = 0; i <
blkcnt; i++) {
607static __inline uint32_t
612 volatile uint32_t ptr;
627 if ((ptr & ~(ch->
blksz - 1)) != ch->
ptr) {
630 delta = (sz + ptr - ch->
prevptr) % sz;
631#ifndef ATI_IXP_DEBUG_VERBOSE
632 if (delta < ch->
blksz)
634 device_printf(sc->
dev,
635 "PCMDIR_%s: incoherent DMA "
638 "[delta=%u != blksz=%u] "
645 (delta < ch->
blksz) ?
646 "OVERLAPPED!" :
"Ok");
656 device_printf(sc->
dev,
"PCMDIR_%s: invalid DMA pointer ptr=%u\n",
666 volatile uint32_t ptr;
675 ptr &= ~(ch->
blksz - 1);
676 delta = (sz + ptr - ch->
prevptr) % sz;
678 if (delta < ch->
blksz)
686#define atiixp_chan_active(sc) (((sc)->pch.flags | (sc)->rch.flags) & \
743 pollticks = ((uint64_t)hz * ch->
blksz) /
755 device_printf(sc->
dev,
756 "%s: pollticks=%d\n",
757 __func__, pollticks);
759 device_printf(sc->
dev,
760 "%s: pollticks %d -> %d\n",
775 ch->
flags &= ~ATI_IXP_CHN_RUNNING;
785 pollticks = ((uint64_t)hz * ch->
blksz) /
795 device_printf(sc->
dev,
796 "%s: pollticks %d -> %d\n",
819 value &= ~ATI_REG_IER_SET_BUS_BUSY;
898 device_printf(sc->
dev,
899 "Recieve IN XRUN interrupt\n");
902 device_printf(sc->
dev,
903 "Recieve OUT XRUN interrupt\n");
914 enable &= ~detected_codecs;
970 dev = oidp->oid_arg1;
977 err = sysctl_handle_int(oidp, &
val, 0,
req);
979 if (err ||
req->newptr == NULL)
981 if (val < 0 || val > 1)
1008 int i, timeout, found,
polling;
1025 msleep(sc, sc->
lock, PWAIT,
"ixpslp",
max(hz / 10, 1));
1028 }
while (--timeout);
1035 device_printf(sc->
dev,
1036 "WARNING: timeout during codec detection; "
1037 "codecs might be present but haven't interrupted\n");
1072 if (sc->
codec == NULL)
1075 subdev = (pci_get_subdevice(sc->
dev) << 16) |
1076 pci_get_subvendor(sc->
dev);
1097 SYSCTL_ADD_PROC(device_get_sysctl_ctx(sc->
dev),
1098 SYSCTL_CHILDREN(device_get_sysctl_tree(sc->
dev)), OID_AUTO,
1099 "polling", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, sc->
dev,
1103 rman_get_start(sc->
reg), rman_get_start(sc->
irq),
1136 bus_teardown_intr(sc->
dev, sc->
irq, sc->
ih);
1144 bus_release_resource(sc->
dev, SYS_RES_IRQ, sc->
irqid, sc->
irq);
1182 return (BUS_PROBE_DEFAULT);
1195 sc = malloc(
sizeof(*sc), M_DEVBUF, M_WAITOK | M_ZERO);
1202 if (resource_int_value(device_get_name(sc->
dev),
1203 device_get_unit(sc->
dev),
"polling", &i) == 0 && i != 0)
1208 pci_enable_busmaster(
dev);
1213 &sc->
regid, RF_ACTIVE);
1216 device_printf(
dev,
"unable to allocate register space\n");
1220 sc->
st = rman_get_bustag(sc->
reg);
1221 sc->
sh = rman_get_bushandle(sc->
reg);
1227 sc->
irq = bus_alloc_resource_any(
dev, SYS_RES_IRQ, &sc->
irqid,
1228 RF_ACTIVE | RF_SHAREABLE);
1231 device_printf(
dev,
"unable to map interrupt\n");
1238 if (resource_int_value(device_get_name(
dev),
1239 device_get_unit(
dev),
"blocksize", &i) == 0 && i > 0) {
1247 sc->
blkcnt = 1 << (i - 1);
1259 if (bus_dma_tag_create(bus_get_dma_tag(
dev), 2,
1261 BUS_SPACE_MAXADDR_32BIT,
1264 sc->
bufsz, 1, 0x3ffff,
1267 device_printf(
dev,
"unable to create dma tag\n");
1271 if (bus_dma_tag_create(bus_get_dma_tag(
dev), 2,
1273 BUS_SPACE_MAXADDR_32BIT,
1281 device_printf(
dev,
"unable to create dma tag\n");
1319 if (sc->
codec != NULL) {
1325 if (sc->
st != 0 && sc->
sh != 0)
1374 device_printf(
dev,
"unable to reinitialize the mixer\n");
1386 sc->
pch.
flags &= ~ATI_IXP_CHN_SUSPEND;
1394 sc->
rch.
flags &= ~ATI_IXP_CHN_SUSPEND;
u_int32_t ac97_getflags(struct ac97_info *codec)
kobj_class_t ac97_getmixerclass(void)
void ac97_destroy(struct ac97_info *codec)
void ac97_setflags(struct ac97_info *codec, u_int32_t val)
#define AC97_CREATE(dev, devinfo, cls)
#define ATI_IXP_DMA_RETRY_MAX
static int atiixp_chan_trigger(kobj_t, void *, int)
static void atiixp_release_resource(struct atiixp_info *)
static kobj_method_t atiixp_ac97_methods[]
static int atiixp_pci_suspend(device_t)
#define atiixp_chan_active(sc)
static int sysctl_atiixp_polling(SYSCTL_HANDLER_ARGS)
#define ATI_IXP_BUFSZ_MAX
static uint32_t atiixp_fmt_32bit[]
static void atiixp_disable_interrupts(struct atiixp_info *)
static void atiixp_enable_interrupts(struct atiixp_info *)
static uint32_t atiixp_chan_setspeed(kobj_t, void *, uint32_t)
static int atiixp_pci_detach(device_t)
static struct pcmchan_caps atiixp_caps_32bit
#define atiixp_wr(_sc, _reg, _val)
#define ATI_IXP_BLK_ALIGN
#define atiixp_rd(_sc, _reg)
static void atiixp_flush_dma(struct atiixp_chinfo *)
#define ATI_IXP_CHN_RUNNING
static int atiixp_wrcd(kobj_t, void *, int, uint32_t)
#define ATI_IXP_CHN_SUSPEND
MODULE_VERSION(snd_atiixp, 1)
static void atiixp_buildsgdt(struct atiixp_chinfo *)
static __inline uint32_t atiixp_dmapos(struct atiixp_chinfo *)
static __inline int atiixp_poll_channel(struct atiixp_chinfo *ch)
static int atiixp_chan_setfragments(kobj_t, void *, uint32_t, uint32_t)
static struct pcmchan_caps atiixp_caps
static struct pcmchan_caps * atiixp_chan_getcaps(kobj_t, void *)
#define ATI_IXP_BUFSZ_DEFAULT
SND_DECLARE_FILE("$FreeBSD$")
static int atiixp_pci_attach(device_t)
static void atiixp_chip_post_init(void *)
CHANNEL_DECLARE(atiixp_chan)
static void atiixp_reset_aclink(struct atiixp_info *)
static int atiixp_waitready_codec(struct atiixp_info *)
static uint32_t atiixp_fmt[]
static void atiixp_dma_cb(void *, bus_dma_segment_t *, int, int)
MODULE_DEPEND(snd_atiixp, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER)
static void * atiixp_chan_init(kobj_t, void *, struct snd_dbuf *, struct pcm_channel *, int)
static void atiixp_enable_dma(struct atiixp_chinfo *)
static const struct @3 atiixp_hw[]
static void atiixp_intr(void *)
#define ATI_IXP_BUFSZ_MIN
#define atiixp_unlock(_sc)
static kobj_method_t atiixp_chan_methods[]
static void atiixp_disable_dma(struct atiixp_chinfo *)
static void atiixp_chip_pre_init(struct atiixp_info *)
static uint32_t atiixp_chan_setblocksize(kobj_t, void *, uint32_t)
static int atiixp_pci_probe(device_t)
static device_method_t atiixp_methods[]
static driver_t atiixp_driver
DRIVER_MODULE(snd_atiixp, pci, atiixp_driver, pcm_devclass, 0, 0)
static int atiixp_pci_resume(device_t)
static int atiixp_rdcd(kobj_t, void *, int)
static int atiixp_chan_setformat(kobj_t, void *, uint32_t)
AC97_DECLARE(atiixp_ac97)
static uint32_t atiixp_chan_getptr(kobj_t, void *)
static void atiixp_poll_callback(void *arg)
#define ATI_REG_OUT_DMA_DT_CUR
#define ATI_REG_OUT_DMA_THRESHOLD_SHIFT
#define ATI_REG_OUT_DMA_SLOT_BIT(x)
#define ATI_REG_CMD_RECEIVE_EN
#define ATI_REG_LINKPTR_EN
#define ATI_REG_CMD_IN_DMA_EN
#define ATI_REG_CMD_SPDF_OUT_EN
#define ATI_REG_CMD_SEND_EN
#define ATI_REG_6CH_REORDER
#define ATI_REG_PHYS_OUT_DATA_SHIFT
#define ATI_REG_ISR_CODEC0_NOT_READY
#define ATI_REG_ISR_IN_STATUS
#define ATI_REG_IER_IN_XRUN_EN
#define ATI_REG_CMD_INTERLEAVE_IN
#define ATI_REG_ISR_CODEC2_NOT_READY
#define ATI_REG_PHYS_IN_ADDR
#define ATI_REG_FIFO_IN_FLUSH
#define ATI_REG_OUT_DMA_LINKPTR
#define ATI_REG_FIFO_FLUSH
#define ATI_REG_ISR_OUT_STATUS
#define ATI_REG_CMD_OUT_DMA_EN
#define ATI_REG_ISR_CODEC1_NOT_READY
#define ATI_REG_OUT_DMA_SLOT
#define ATI_REG_CMD_POWERDOWN
#define ATI_IXP_BASE_RATE
#define ATI_REG_IER_SPDF_STATUS_EN
#define ATI_REG_IER_OUT_XRUN_EN
#define ATI_IXP_DMA_CHSEGS_MAX
#define ATI_IXP_DMA_CHSEGS
#define ATI_REG_PHYS_OUT_ADDR_EN
#define ATI_REG_PHYS_OUT_ADDR_SHIFT
#define ATI_IXP_DMA_CHSEGS_MIN
#define ATI_REG_IN_DMA_DT_CUR
#define ATI_REG_IER_SPDF_XRUN_EN
#define ATI_REG_PHYS_IN_READ_FLAG
#define ATI_REG_CMD_AC_SYNC
#define ATI_REG_FIFO_OUT_FLUSH
#define ATI_REG_PHYS_OUT_ADDR
#define ATI_REG_ISR_IN_XRUN
#define ATI_REG_PHYS_OUT_RW
#define ATI_REG_CMD_ACLINK_ACTIVE
#define ATI_REG_CMD_INTERLEAVE_OUT
#define ATI_REG_IER_SET_BUS_BUSY
#define ATI_REG_IER_IO_STATUS_EN
#define ATI_REG_CMD_AC_SOFT_RESET
#define ATI_REG_PHYS_IN_DATA_SHIFT
#define ATI_REG_ISR_OUT_XRUN
#define ATI_REG_CMD_AC_RESET
#define ATI_REG_IN_DMA_LINKPTR
unsigned int sndbuf_getspd(struct snd_dbuf *b)
int sndbuf_alloc(struct snd_dbuf *b, bus_dma_tag_t dmatag, int dmaflags, unsigned int size)
unsigned int sndbuf_getblkcnt(struct snd_dbuf *b)
bus_addr_t sndbuf_getbufaddr(struct snd_dbuf *buf)
unsigned int sndbuf_getalign(struct snd_dbuf *b)
unsigned int sndbuf_getblksz(struct snd_dbuf *b)
unsigned int sndbuf_getmaxsize(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)
int mixer_init(device_t dev, kobj_class_t cls, void *devinfo)
int mixer_reinit(device_t dev)
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)
struct atiixp_dma_op * sgd_table
struct pcm_channel * channel
struct atiixp_info * parent
struct intr_config_hook delayed_attach
struct callout poll_timer
uint32_t codec_not_ready_bits
struct atiixp_dma_op * sgd_table
bus_dma_tag_t parent_dmat