atiixp.c revision 170521
1/*-
2 * Copyright (c) 2005 Ariff Abdullah <ariff@FreeBSD.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHERIN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THEPOSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27/*
28 * FreeBSD pcm driver for ATI IXP 150/200/250/300 AC97 controllers
29 *
30 * Features
31 *	* 16bit playback / recording
32 *	* 32bit native playback - yay!
33 *	* 32bit native recording (seems broken on few hardwares)
34 *
35 * Issues / TODO:
36 *	* SPDIF
37 *	* Support for more than 2 channels.
38 *	* VRA ? VRM ? DRA ?
39 *	* 32bit native recording seems broken on few hardwares, most
40 *	  probably because of incomplete VRA/DRA cleanup.
41 *
42 *
43 * Thanks goes to:
44 *
45 *   Shaharil @ SCAN Associates whom relentlessly providing me the
46 *   mind blowing Acer Ferrari 4002 WLMi with this ATI IXP hardware.
47 *
48 *   Reinoud Zandijk <reinoud@NetBSD.org> (auixp), which this driver is
49 *   largely based upon although large part of it has been reworked. His
50 *   driver is the primary reference and pretty much well documented.
51 *
52 *   Takashi Iwai (ALSA snd-atiixp), for register definitions and some
53 *   random ninja hackery.
54 */
55
56#include <dev/sound/pcm/sound.h>
57#include <dev/sound/pcm/ac97.h>
58
59#include <dev/pci/pcireg.h>
60#include <dev/pci/pcivar.h>
61#include <sys/sysctl.h>
62#include <sys/endian.h>
63
64#include <dev/sound/pci/atiixp.h>
65
66SND_DECLARE_FILE("$FreeBSD: head/sys/dev/sound/pci/atiixp.c 170521 2007-06-11 00:49:46Z ariff $");
67
68#define ATI_IXP_DMA_RETRY_MAX	100
69
70#define ATI_IXP_BUFSZ_MIN	4096
71#define ATI_IXP_BUFSZ_MAX	65536
72#define ATI_IXP_BUFSZ_DEFAULT	16384
73
74#define ATI_IXP_BLK_MIN		32
75#define ATI_IXP_BLK_ALIGN	(~(ATI_IXP_BLK_MIN - 1))
76
77struct atiixp_dma_op {
78	volatile uint32_t addr;
79	volatile uint16_t status;
80	volatile uint16_t size;
81	volatile uint32_t next;
82};
83
84struct atiixp_info;
85
86struct atiixp_chinfo {
87	struct snd_dbuf *buffer;
88	struct pcm_channel *channel;
89	struct atiixp_info *parent;
90	struct atiixp_dma_op *sgd_table;
91	bus_addr_t sgd_addr;
92	uint32_t enable_bit, flush_bit, linkptr_bit, dt_cur_bit;
93	uint32_t blksz, blkcnt;
94	uint32_t ptr, prevptr;
95	uint32_t fmt;
96	int caps_32bit, dir, active;
97};
98
99struct atiixp_info {
100	device_t dev;
101
102	bus_space_tag_t st;
103	bus_space_handle_t sh;
104	bus_dma_tag_t parent_dmat;
105	bus_dma_tag_t sgd_dmat;
106	bus_dmamap_t sgd_dmamap;
107	bus_addr_t sgd_addr;
108
109	struct resource *reg, *irq;
110	int regtype, regid, irqid;
111	void *ih;
112	struct ac97_info *codec;
113
114	struct atiixp_chinfo pch;
115	struct atiixp_chinfo rch;
116	struct atiixp_dma_op *sgd_table;
117	struct intr_config_hook delayed_attach;
118
119	uint32_t bufsz;
120	uint32_t codec_not_ready_bits, codec_idx, codec_found;
121	uint32_t blkcnt;
122	int registered_channels;
123
124	struct mtx *lock;
125	struct callout poll_timer;
126	int poll_ticks, polling;
127};
128
129#define atiixp_rd(_sc, _reg)	\
130		bus_space_read_4((_sc)->st, (_sc)->sh, _reg)
131#define atiixp_wr(_sc, _reg, _val)	\
132		bus_space_write_4((_sc)->st, (_sc)->sh, _reg, _val)
133
134#define atiixp_lock(_sc)	snd_mtxlock((_sc)->lock)
135#define atiixp_unlock(_sc)	snd_mtxunlock((_sc)->lock)
136#define atiixp_assert(_sc)	snd_mtxassert((_sc)->lock)
137
138static uint32_t atiixp_fmt_32bit[] = {
139	AFMT_STEREO | AFMT_S16_LE,
140	AFMT_STEREO | AFMT_S32_LE,
141	0
142};
143
144static uint32_t atiixp_fmt[] = {
145	AFMT_STEREO | AFMT_S16_LE,
146	0
147};
148
149static struct pcmchan_caps atiixp_caps_32bit = {
150	ATI_IXP_BASE_RATE,
151	ATI_IXP_BASE_RATE,
152	atiixp_fmt_32bit, 0
153};
154
155static struct pcmchan_caps atiixp_caps = {
156	ATI_IXP_BASE_RATE,
157	ATI_IXP_BASE_RATE,
158	atiixp_fmt, 0
159};
160
161static const struct {
162	uint16_t vendor;
163	uint16_t devid;
164	char	 *desc;
165} atiixp_hw[] = {
166	{ ATI_VENDOR_ID, ATI_IXP_200_ID, "ATI IXP 200" },
167	{ ATI_VENDOR_ID, ATI_IXP_300_ID, "ATI IXP 300" },
168	{ ATI_VENDOR_ID, ATI_IXP_400_ID, "ATI IXP 400" },
169};
170
171static void atiixp_enable_interrupts(struct atiixp_info *);
172static void atiixp_disable_interrupts(struct atiixp_info *);
173static void atiixp_reset_aclink(struct atiixp_info *);
174static void atiixp_flush_dma(struct atiixp_chinfo *);
175static void atiixp_enable_dma(struct atiixp_chinfo *);
176static void atiixp_disable_dma(struct atiixp_chinfo *);
177
178static int atiixp_waitready_codec(struct atiixp_info *);
179static int atiixp_rdcd(kobj_t, void *, int);
180static int atiixp_wrcd(kobj_t, void *, int, uint32_t);
181
182static void  *atiixp_chan_init(kobj_t, void *, struct snd_dbuf *,
183						struct pcm_channel *, int);
184static int    atiixp_chan_setformat(kobj_t, void *, uint32_t);
185static int    atiixp_chan_setspeed(kobj_t, void *, uint32_t);
186static int    atiixp_chan_setfragments(kobj_t, void *, uint32_t, uint32_t);
187static int    atiixp_chan_setblocksize(kobj_t, void *, uint32_t);
188static void   atiixp_buildsgdt(struct atiixp_chinfo *);
189static int    atiixp_chan_trigger(kobj_t, void *, int);
190static __inline uint32_t atiixp_dmapos(struct atiixp_chinfo *);
191static int    atiixp_chan_getptr(kobj_t, void *);
192static struct pcmchan_caps *atiixp_chan_getcaps(kobj_t, void *);
193
194static void atiixp_intr(void *);
195static void atiixp_dma_cb(void *, bus_dma_segment_t *, int, int);
196static void atiixp_chip_pre_init(struct atiixp_info *);
197static void atiixp_chip_post_init(void *);
198static void atiixp_release_resource(struct atiixp_info *);
199static int  atiixp_pci_probe(device_t);
200static int  atiixp_pci_attach(device_t);
201static int  atiixp_pci_detach(device_t);
202static int  atiixp_pci_suspend(device_t);
203static int  atiixp_pci_resume(device_t);
204
205/*
206 * ATI IXP helper functions
207 */
208static void
209atiixp_enable_interrupts(struct atiixp_info *sc)
210{
211	uint32_t value;
212
213	/* clear all pending */
214	atiixp_wr(sc, ATI_REG_ISR, 0xffffffff);
215
216	/* enable all relevant interrupt sources we can handle */
217	value = atiixp_rd(sc, ATI_REG_IER);
218
219	value |= ATI_REG_IER_IO_STATUS_EN;
220
221	/*
222	 * Disable / ignore internal xrun/spdf interrupt flags
223	 * since it doesn't interest us (for now).
224	 */
225#if 1
226	value &= ~(ATI_REG_IER_IN_XRUN_EN | ATI_REG_IER_OUT_XRUN_EN |
227	    ATI_REG_IER_SPDF_XRUN_EN | ATI_REG_IER_SPDF_STATUS_EN);
228#else
229	value |= ATI_REG_IER_IN_XRUN_EN;
230	value |= ATI_REG_IER_OUT_XRUN_EN;
231
232	value |= ATI_REG_IER_SPDF_XRUN_EN;
233	value |= ATI_REG_IER_SPDF_STATUS_EN;
234#endif
235
236	atiixp_wr(sc, ATI_REG_IER, value);
237}
238
239static void
240atiixp_disable_interrupts(struct atiixp_info *sc)
241{
242	/* disable all interrupt sources */
243	atiixp_wr(sc, ATI_REG_IER, 0);
244
245	/* clear all pending */
246	atiixp_wr(sc, ATI_REG_ISR, 0xffffffff);
247}
248
249static void
250atiixp_reset_aclink(struct atiixp_info *sc)
251{
252	uint32_t value, timeout;
253
254	/* if power is down, power it up */
255	value = atiixp_rd(sc, ATI_REG_CMD);
256	if (value & ATI_REG_CMD_POWERDOWN) {
257		/* explicitly enable power */
258		value &= ~ATI_REG_CMD_POWERDOWN;
259		atiixp_wr(sc, ATI_REG_CMD, value);
260
261		/* have to wait at least 10 usec for it to initialise */
262		DELAY(20);
263	}
264
265	/* perform a soft reset */
266	value  = atiixp_rd(sc, ATI_REG_CMD);
267	value |= ATI_REG_CMD_AC_SOFT_RESET;
268	atiixp_wr(sc, ATI_REG_CMD, value);
269
270	/* need to read the CMD reg and wait aprox. 10 usec to init */
271	value  = atiixp_rd(sc, ATI_REG_CMD);
272	DELAY(20);
273
274	/* clear soft reset flag again */
275	value  = atiixp_rd(sc, ATI_REG_CMD);
276	value &= ~ATI_REG_CMD_AC_SOFT_RESET;
277	atiixp_wr(sc, ATI_REG_CMD, value);
278
279	/* check if the ac-link is working; reset device otherwise */
280	timeout = 10;
281	value = atiixp_rd(sc, ATI_REG_CMD);
282	while (!(value & ATI_REG_CMD_ACLINK_ACTIVE) && --timeout) {
283#if 0
284		device_printf(sc->dev, "not up; resetting aclink hardware\n");
285#endif
286
287		/* dip aclink reset but keep the acsync */
288		value &= ~ATI_REG_CMD_AC_RESET;
289		value |=  ATI_REG_CMD_AC_SYNC;
290		atiixp_wr(sc, ATI_REG_CMD, value);
291
292		/* need to read CMD again and wait again (clocking in issue?) */
293		value = atiixp_rd(sc, ATI_REG_CMD);
294		DELAY(20);
295
296		/* assert aclink reset again */
297		value = atiixp_rd(sc, ATI_REG_CMD);
298		value |=  ATI_REG_CMD_AC_RESET;
299		atiixp_wr(sc, ATI_REG_CMD, value);
300
301		/* check if its active now */
302		value = atiixp_rd(sc, ATI_REG_CMD);
303	}
304
305	if (timeout == 0)
306		device_printf(sc->dev, "giving up aclink reset\n");
307#if 0
308	if (timeout != 10)
309		device_printf(sc->dev, "aclink hardware reset successful\n");
310#endif
311
312	/* assert reset and sync for safety */
313	value  = atiixp_rd(sc, ATI_REG_CMD);
314	value |= ATI_REG_CMD_AC_SYNC | ATI_REG_CMD_AC_RESET;
315	atiixp_wr(sc, ATI_REG_CMD, value);
316}
317
318static void
319atiixp_flush_dma(struct atiixp_chinfo *ch)
320{
321	atiixp_wr(ch->parent, ATI_REG_FIFO_FLUSH, ch->flush_bit);
322}
323
324static void
325atiixp_enable_dma(struct atiixp_chinfo *ch)
326{
327	uint32_t value;
328
329	value = atiixp_rd(ch->parent, ATI_REG_CMD);
330	if (!(value & ch->enable_bit)) {
331		value |= ch->enable_bit;
332		atiixp_wr(ch->parent, ATI_REG_CMD, value);
333	}
334}
335
336static void
337atiixp_disable_dma(struct atiixp_chinfo *ch)
338{
339	uint32_t value;
340
341	value = atiixp_rd(ch->parent, ATI_REG_CMD);
342	if (value & ch->enable_bit) {
343		value &= ~ch->enable_bit;
344		atiixp_wr(ch->parent, ATI_REG_CMD, value);
345	}
346}
347
348/*
349 * AC97 interface
350 */
351static int
352atiixp_waitready_codec(struct atiixp_info *sc)
353{
354	int timeout = 500;
355
356	do {
357		if ((atiixp_rd(sc, ATI_REG_PHYS_OUT_ADDR) &
358		    ATI_REG_PHYS_OUT_ADDR_EN) == 0)
359			return (0);
360		DELAY(1);
361	} while (--timeout);
362
363	return (-1);
364}
365
366static int
367atiixp_rdcd(kobj_t obj, void *devinfo, int reg)
368{
369	struct atiixp_info *sc = devinfo;
370	uint32_t data;
371	int timeout;
372
373	if (atiixp_waitready_codec(sc))
374		return (-1);
375
376	data = (reg << ATI_REG_PHYS_OUT_ADDR_SHIFT) |
377	    ATI_REG_PHYS_OUT_ADDR_EN | ATI_REG_PHYS_OUT_RW | sc->codec_idx;
378
379	atiixp_wr(sc, ATI_REG_PHYS_OUT_ADDR, data);
380
381	if (atiixp_waitready_codec(sc))
382		return (-1);
383
384	timeout = 500;
385	do {
386		data = atiixp_rd(sc, ATI_REG_PHYS_IN_ADDR);
387		if (data & ATI_REG_PHYS_IN_READ_FLAG)
388			return (data >> ATI_REG_PHYS_IN_DATA_SHIFT);
389		DELAY(1);
390	} while (--timeout);
391
392	if (reg < 0x7c)
393		device_printf(sc->dev, "codec read timeout! (reg 0x%x)\n", reg);
394
395	return (-1);
396}
397
398static int
399atiixp_wrcd(kobj_t obj, void *devinfo, int reg, uint32_t data)
400{
401	struct atiixp_info *sc = devinfo;
402
403	if (atiixp_waitready_codec(sc))
404		return (-1);
405
406	data = (data << ATI_REG_PHYS_OUT_DATA_SHIFT) |
407	    (((uint32_t)reg) << ATI_REG_PHYS_OUT_ADDR_SHIFT) |
408	    ATI_REG_PHYS_OUT_ADDR_EN | sc->codec_idx;
409
410	atiixp_wr(sc, ATI_REG_PHYS_OUT_ADDR, data);
411
412	return (0);
413}
414
415static kobj_method_t atiixp_ac97_methods[] = {
416	KOBJMETHOD(ac97_read,		atiixp_rdcd),
417	KOBJMETHOD(ac97_write,		atiixp_wrcd),
418	{ 0, 0 }
419};
420AC97_DECLARE(atiixp_ac97);
421
422/*
423 * Playback / Record channel interface
424 */
425static void *
426atiixp_chan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b,
427					struct pcm_channel *c, int dir)
428{
429	struct atiixp_info *sc = devinfo;
430	struct atiixp_chinfo *ch;
431	int num;
432
433	atiixp_lock(sc);
434
435	if (dir == PCMDIR_PLAY) {
436		ch = &sc->pch;
437		ch->linkptr_bit = ATI_REG_OUT_DMA_LINKPTR;
438		ch->enable_bit = ATI_REG_CMD_OUT_DMA_EN | ATI_REG_CMD_SEND_EN;
439		ch->flush_bit = ATI_REG_FIFO_OUT_FLUSH;
440		ch->dt_cur_bit = ATI_REG_OUT_DMA_DT_CUR;
441		/* Native 32bit playback working properly */
442		ch->caps_32bit = 1;
443	} else {
444		ch = &sc->rch;
445		ch->linkptr_bit = ATI_REG_IN_DMA_LINKPTR;
446		ch->enable_bit = ATI_REG_CMD_IN_DMA_EN | ATI_REG_CMD_RECEIVE_EN;
447		ch->flush_bit = ATI_REG_FIFO_IN_FLUSH;
448		ch->dt_cur_bit = ATI_REG_IN_DMA_DT_CUR;
449		/* XXX Native 32bit recording appear to be broken */
450		ch->caps_32bit = 1;
451	}
452
453	ch->buffer = b;
454	ch->parent = sc;
455	ch->channel = c;
456	ch->dir = dir;
457	ch->blkcnt = sc->blkcnt;
458	ch->blksz = sc->bufsz / ch->blkcnt;
459
460	atiixp_unlock(sc);
461
462	if (sndbuf_alloc(ch->buffer, sc->parent_dmat, 0, sc->bufsz) == -1)
463		return (NULL);
464
465	atiixp_lock(sc);
466	num = sc->registered_channels++;
467	ch->sgd_table = &sc->sgd_table[num * ATI_IXP_DMA_CHSEGS_MAX];
468	ch->sgd_addr = sc->sgd_addr + (num * ATI_IXP_DMA_CHSEGS_MAX *
469	    sizeof(struct atiixp_dma_op));
470	atiixp_disable_dma(ch);
471	atiixp_unlock(sc);
472
473	return (ch);
474}
475
476static int
477atiixp_chan_setformat(kobj_t obj, void *data, uint32_t format)
478{
479	struct atiixp_chinfo *ch = data;
480	struct atiixp_info *sc = ch->parent;
481	uint32_t value;
482
483	atiixp_lock(sc);
484	if (ch->dir == PCMDIR_REC) {
485		value = atiixp_rd(sc, ATI_REG_CMD);
486		value &= ~ATI_REG_CMD_INTERLEAVE_IN;
487		if ((format & AFMT_32BIT) == 0)
488			value |= ATI_REG_CMD_INTERLEAVE_IN;
489		atiixp_wr(sc, ATI_REG_CMD, value);
490	} else {
491		value = atiixp_rd(sc, ATI_REG_OUT_DMA_SLOT);
492		value &= ~ATI_REG_OUT_DMA_SLOT_MASK;
493		/* We do not have support for more than 2 channels, _yet_. */
494		value |= ATI_REG_OUT_DMA_SLOT_BIT(3) |
495		    ATI_REG_OUT_DMA_SLOT_BIT(4);
496		value |= 0x04 << ATI_REG_OUT_DMA_THRESHOLD_SHIFT;
497		atiixp_wr(sc, ATI_REG_OUT_DMA_SLOT, value);
498		value = atiixp_rd(sc, ATI_REG_CMD);
499		value &= ~ATI_REG_CMD_INTERLEAVE_OUT;
500		if ((format & AFMT_32BIT) == 0)
501			value |= ATI_REG_CMD_INTERLEAVE_OUT;
502		atiixp_wr(sc, ATI_REG_CMD, value);
503		value = atiixp_rd(sc, ATI_REG_6CH_REORDER);
504		value &= ~ATI_REG_6CH_REORDER_EN;
505		atiixp_wr(sc, ATI_REG_6CH_REORDER, value);
506	}
507	ch->fmt = format;
508	atiixp_unlock(sc);
509
510	return (0);
511}
512
513static int
514atiixp_chan_setspeed(kobj_t obj, void *data, uint32_t spd)
515{
516	/* XXX We're supposed to do VRA/DRA processing right here */
517	return (ATI_IXP_BASE_RATE);
518}
519
520static int
521atiixp_chan_setfragments(kobj_t obj, void *data,
522					uint32_t blksz, uint32_t blkcnt)
523{
524	struct atiixp_chinfo *ch = data;
525	struct atiixp_info *sc = ch->parent;
526
527	blksz &= ATI_IXP_BLK_ALIGN;
528
529	if (blksz > (sndbuf_getmaxsize(ch->buffer) / ATI_IXP_DMA_CHSEGS_MIN))
530		blksz = sndbuf_getmaxsize(ch->buffer) / ATI_IXP_DMA_CHSEGS_MIN;
531	if (blksz < ATI_IXP_BLK_MIN)
532		blksz = ATI_IXP_BLK_MIN;
533	if (blkcnt > ATI_IXP_DMA_CHSEGS_MAX)
534		blkcnt = ATI_IXP_DMA_CHSEGS_MAX;
535	if (blkcnt < ATI_IXP_DMA_CHSEGS_MIN)
536		blkcnt = ATI_IXP_DMA_CHSEGS_MIN;
537
538	while ((blksz * blkcnt) > sndbuf_getmaxsize(ch->buffer)) {
539		if ((blkcnt >> 1) >= ATI_IXP_DMA_CHSEGS_MIN)
540			blkcnt >>= 1;
541		else if ((blksz >> 1) >= ATI_IXP_BLK_MIN)
542			blksz >>= 1;
543		else
544			break;
545	}
546
547	if ((sndbuf_getblksz(ch->buffer) != blksz ||
548	    sndbuf_getblkcnt(ch->buffer) != blkcnt) &&
549	    sndbuf_resize(ch->buffer, blkcnt, blksz) != 0)
550		device_printf(sc->dev, "%s: failed blksz=%u blkcnt=%u\n",
551		    __func__, blksz, blkcnt);
552
553	ch->blksz = sndbuf_getblksz(ch->buffer);
554	ch->blkcnt = sndbuf_getblkcnt(ch->buffer);
555
556	return (1);
557}
558
559static int
560atiixp_chan_setblocksize(kobj_t obj, void *data, uint32_t blksz)
561{
562	struct atiixp_chinfo *ch = data;
563	struct atiixp_info *sc = ch->parent;
564
565	atiixp_chan_setfragments(obj, data, blksz, sc->blkcnt);
566
567	return (ch->blksz);
568}
569
570static void
571atiixp_buildsgdt(struct atiixp_chinfo *ch)
572{
573	struct atiixp_info *sc = ch->parent;
574	uint32_t addr, blksz, blkcnt;
575	int i;
576
577	addr = sndbuf_getbufaddr(ch->buffer);
578
579	if (sc->polling != 0) {
580		blksz = ch->blksz * ch->blkcnt;
581		blkcnt = 1;
582	} else {
583		blksz = ch->blksz;
584		blkcnt = ch->blkcnt;
585	}
586
587	for (i = 0; i < blkcnt; i++) {
588		ch->sgd_table[i].addr = htole32(addr + (i * blksz));
589		ch->sgd_table[i].status = htole16(0);
590		ch->sgd_table[i].size = htole16(blksz >> 2);
591		ch->sgd_table[i].next = htole32((uint32_t)ch->sgd_addr +
592		    (((i + 1) % blkcnt) * sizeof(struct atiixp_dma_op)));
593	}
594}
595
596static __inline uint32_t
597atiixp_dmapos(struct atiixp_chinfo *ch)
598{
599	struct atiixp_info *sc = ch->parent;
600	uint32_t reg, addr, sz, retry;
601	volatile uint32_t ptr;
602
603	reg = ch->dt_cur_bit;
604	addr = sndbuf_getbufaddr(ch->buffer);
605	sz = ch->blkcnt * ch->blksz;
606	retry = ATI_IXP_DMA_RETRY_MAX;
607
608	do {
609		ptr = atiixp_rd(sc, reg);
610		if (ptr < addr)
611			continue;
612		ptr -= addr;
613		if (ptr < sz) {
614#if 0
615#ifdef ATI_IXP_DEBUG
616			if ((ptr & ~(ch->blksz - 1)) != ch->ptr) {
617				uint32_t delta;
618
619				delta = (sz + ptr - ch->prevptr) % sz;
620#ifndef ATI_IXP_DEBUG_VERBOSE
621				if (delta < ch->blksz)
622#endif
623					device_printf(sc->dev,
624						"PCMDIR_%s: incoherent DMA "
625						"prevptr=%u ptr=%u "
626						"ptr=%u blkcnt=%u "
627						"[delta=%u != blksz=%u] "
628						"(%s)\n",
629						(ch->dir == PCMDIR_PLAY) ?
630						"PLAY" : "REC",
631						ch->prevptr, ptr,
632						ch->ptr, ch->blkcnt,
633						delta, ch->blksz,
634						(delta < ch->blksz) ?
635						"OVERLAPPED!" : "Ok");
636				ch->ptr = ptr & ~(ch->blksz - 1);
637			}
638			ch->prevptr = ptr;
639#endif
640#endif
641			return (ptr);
642		}
643	} while (--retry);
644
645	device_printf(sc->dev, "PCMDIR_%s: invalid DMA pointer ptr=%u\n",
646	    (ch->dir == PCMDIR_PLAY) ? "PLAY" : "REC", ptr);
647
648	return (0);
649}
650
651static __inline int
652atiixp_poll_channel(struct atiixp_chinfo *ch)
653{
654	uint32_t sz, delta;
655	volatile uint32_t ptr;
656
657	if (ch->active == 0)
658		return (0);
659
660	sz = ch->blksz * ch->blkcnt;
661	ptr = atiixp_dmapos(ch);
662	ch->ptr = ptr;
663	ptr %= sz;
664	ptr &= ~(ch->blksz - 1);
665	delta = (sz + ptr - ch->prevptr) % sz;
666
667	if (delta < ch->blksz)
668		return (0);
669
670	ch->prevptr = ptr;
671
672	return (1);
673}
674
675#define atiixp_chan_active(sc)	((sc)->pch.active + (sc)->rch.active)
676
677static void
678atiixp_poll_callback(void *arg)
679{
680	struct atiixp_info *sc = arg;
681	uint32_t trigger = 0;
682
683	if (sc == NULL)
684		return;
685
686	atiixp_lock(sc);
687	if (sc->polling == 0 || atiixp_chan_active(sc) == 0) {
688		atiixp_unlock(sc);
689		return;
690	}
691
692	trigger |= (atiixp_poll_channel(&sc->pch) != 0) ? 1 : 0;
693	trigger |= (atiixp_poll_channel(&sc->rch) != 0) ? 2 : 0;
694
695	/* XXX */
696	callout_reset(&sc->poll_timer, 1/*sc->poll_ticks*/,
697	    atiixp_poll_callback, sc);
698
699	atiixp_unlock(sc);
700
701	if (trigger & 1)
702		chn_intr(sc->pch.channel);
703	if (trigger & 2)
704		chn_intr(sc->rch.channel);
705}
706
707static int
708atiixp_chan_trigger(kobj_t obj, void *data, int go)
709{
710	struct atiixp_chinfo *ch = data;
711	struct atiixp_info *sc = ch->parent;
712	uint32_t value;
713	int pollticks;
714
715	if (!PCMTRIG_COMMON(go))
716		return (0);
717
718	atiixp_lock(sc);
719
720	switch (go) {
721	case PCMTRIG_START:
722		atiixp_flush_dma(ch);
723		atiixp_buildsgdt(ch);
724		atiixp_wr(sc, ch->linkptr_bit, 0);
725		atiixp_enable_dma(ch);
726		atiixp_wr(sc, ch->linkptr_bit,
727		    (uint32_t)ch->sgd_addr | ATI_REG_LINKPTR_EN);
728		if (sc->polling != 0) {
729			ch->ptr = 0;
730			ch->prevptr = 0;
731			pollticks = ((uint64_t)hz * ch->blksz) /
732			    ((uint64_t)sndbuf_getbps(ch->buffer) *
733			    sndbuf_getspd(ch->buffer));
734			pollticks >>= 2;
735			if (pollticks > hz)
736				pollticks = hz;
737			if (pollticks < 1)
738				pollticks = 1;
739			if (atiixp_chan_active(sc) == 0 ||
740			    pollticks < sc->poll_ticks) {
741			    	if (bootverbose) {
742					if (atiixp_chan_active(sc) == 0)
743						device_printf(sc->dev,
744						    "%s: pollticks=%d\n",
745						    __func__, pollticks);
746					else
747						device_printf(sc->dev,
748						    "%s: pollticks %d -> %d\n",
749						    __func__, sc->poll_ticks,
750						    pollticks);
751				}
752				sc->poll_ticks = pollticks;
753				callout_reset(&sc->poll_timer, 1,
754				    atiixp_poll_callback, sc);
755			}
756		}
757		ch->active = 1;
758		break;
759	case PCMTRIG_STOP:
760	case PCMTRIG_ABORT:
761		atiixp_disable_dma(ch);
762		atiixp_flush_dma(ch);
763		ch->active = 0;
764		if (sc->polling != 0) {
765			if (atiixp_chan_active(sc) == 0) {
766				callout_stop(&sc->poll_timer);
767				sc->poll_ticks = 1;
768			} else {
769				if (sc->pch.active != 0)
770					ch = &sc->pch;
771				else
772					ch = &sc->rch;
773				pollticks = ((uint64_t)hz * ch->blksz) /
774				    ((uint64_t)sndbuf_getbps(ch->buffer) *
775				    sndbuf_getspd(ch->buffer));
776				pollticks >>= 2;
777				if (pollticks > hz)
778					pollticks = hz;
779				if (pollticks < 1)
780					pollticks = 1;
781				if (pollticks > sc->poll_ticks) {
782					if (bootverbose)
783						device_printf(sc->dev,
784						    "%s: pollticks %d -> %d\n",
785						    __func__, sc->poll_ticks,
786						    pollticks);
787					sc->poll_ticks = pollticks;
788					callout_reset(&sc->poll_timer,
789					    1, atiixp_poll_callback,
790					    sc);
791				}
792			}
793		}
794		break;
795	default:
796		atiixp_unlock(sc);
797		return (0);
798		break;
799	}
800
801	/* Update bus busy status */
802	value = atiixp_rd(sc, ATI_REG_IER);
803	if (atiixp_rd(sc, ATI_REG_CMD) & (ATI_REG_CMD_SEND_EN |
804	    ATI_REG_CMD_RECEIVE_EN | ATI_REG_CMD_SPDF_OUT_EN))
805		value |= ATI_REG_IER_SET_BUS_BUSY;
806	else
807		value &= ~ATI_REG_IER_SET_BUS_BUSY;
808	atiixp_wr(sc, ATI_REG_IER, value);
809
810	atiixp_unlock(sc);
811
812	return (0);
813}
814
815static int
816atiixp_chan_getptr(kobj_t obj, void *data)
817{
818	struct atiixp_chinfo *ch = data;
819	struct atiixp_info *sc = ch->parent;
820	uint32_t ptr;
821
822	atiixp_lock(sc);
823	if (sc->polling != 0)
824		ptr = ch->ptr;
825	else
826		ptr = atiixp_dmapos(ch);
827	atiixp_unlock(sc);
828
829	return (ptr);
830}
831
832static struct pcmchan_caps *
833atiixp_chan_getcaps(kobj_t obj, void *data)
834{
835	struct atiixp_chinfo *ch = data;
836
837	if (ch->caps_32bit)
838		return (&atiixp_caps_32bit);
839	return (&atiixp_caps);
840}
841
842static kobj_method_t atiixp_chan_methods[] = {
843	KOBJMETHOD(channel_init,		atiixp_chan_init),
844	KOBJMETHOD(channel_setformat,		atiixp_chan_setformat),
845	KOBJMETHOD(channel_setspeed,		atiixp_chan_setspeed),
846	KOBJMETHOD(channel_setblocksize,	atiixp_chan_setblocksize),
847	KOBJMETHOD(channel_setfragments,	atiixp_chan_setfragments),
848	KOBJMETHOD(channel_trigger,		atiixp_chan_trigger),
849	KOBJMETHOD(channel_getptr,		atiixp_chan_getptr),
850	KOBJMETHOD(channel_getcaps,		atiixp_chan_getcaps),
851	{ 0, 0 }
852};
853CHANNEL_DECLARE(atiixp_chan);
854
855/*
856 * PCI driver interface
857 */
858static void
859atiixp_intr(void *p)
860{
861	struct atiixp_info *sc = p;
862	uint32_t status, enable, detected_codecs;
863	uint32_t trigger = 0;
864
865	atiixp_lock(sc);
866	if (sc->polling != 0) {
867		atiixp_unlock(sc);
868		return;
869	}
870	status = atiixp_rd(sc, ATI_REG_ISR);
871
872	if (status == 0) {
873		atiixp_unlock(sc);
874		return;
875	}
876
877	if ((status & ATI_REG_ISR_OUT_STATUS) && sc->pch.active != 0)
878		trigger |= 1;
879	if ((status & ATI_REG_ISR_IN_STATUS) && sc->rch.active != 0)
880		trigger |= 2;
881
882#if 0
883	if (status & ATI_REG_ISR_IN_XRUN) {
884		device_printf(sc->dev,
885			"Recieve IN XRUN interrupt\n");
886	}
887	if (status & ATI_REG_ISR_OUT_XRUN) {
888		device_printf(sc->dev,
889			"Recieve OUT XRUN interrupt\n");
890	}
891#endif
892
893	if (status & CODEC_CHECK_BITS) {
894		/* mark missing codecs as not ready */
895		detected_codecs = status & CODEC_CHECK_BITS;
896		sc->codec_not_ready_bits |= detected_codecs;
897
898		/* disable detected interupt sources */
899		enable  = atiixp_rd(sc, ATI_REG_IER);
900		enable &= ~detected_codecs;
901		atiixp_wr(sc, ATI_REG_IER, enable);
902	}
903
904	/* acknowledge */
905	atiixp_wr(sc, ATI_REG_ISR, status);
906	atiixp_unlock(sc);
907
908	if (trigger & 1)
909		chn_intr(sc->pch.channel);
910	if (trigger & 2)
911		chn_intr(sc->rch.channel);
912}
913
914static void
915atiixp_dma_cb(void *p, bus_dma_segment_t *bds, int a, int b)
916{
917	struct atiixp_info *sc = (struct atiixp_info *)p;
918	sc->sgd_addr = bds->ds_addr;
919}
920
921static void
922atiixp_chip_pre_init(struct atiixp_info *sc)
923{
924	uint32_t value;
925
926	atiixp_lock(sc);
927
928	/* disable interrupts */
929	atiixp_disable_interrupts(sc);
930
931	/* clear all DMA enables (preserving rest of settings) */
932	value = atiixp_rd(sc, ATI_REG_CMD);
933	value &= ~(ATI_REG_CMD_IN_DMA_EN | ATI_REG_CMD_OUT_DMA_EN |
934	    ATI_REG_CMD_SPDF_OUT_EN );
935	atiixp_wr(sc, ATI_REG_CMD, value);
936
937	/* reset aclink */
938	atiixp_reset_aclink(sc);
939
940	sc->codec_not_ready_bits = 0;
941
942	/* enable all codecs to interrupt as well as the new frame interrupt */
943	atiixp_wr(sc, ATI_REG_IER, CODEC_CHECK_BITS);
944
945	atiixp_unlock(sc);
946}
947
948#ifdef SND_DYNSYSCTL
949static int
950sysctl_atiixp_polling(SYSCTL_HANDLER_ARGS)
951{
952	struct atiixp_info *sc;
953	device_t dev;
954	int err, val;
955
956	dev = oidp->oid_arg1;
957	sc = pcm_getdevinfo(dev);
958	if (sc == NULL)
959		return (EINVAL);
960	atiixp_lock(sc);
961	val = sc->polling;
962	atiixp_unlock(sc);
963	err = sysctl_handle_int(oidp, &val, 0, req);
964
965	if (err || req->newptr == NULL)
966		return (err);
967	if (val < 0 || val > 1)
968		return (EINVAL);
969
970	atiixp_lock(sc);
971	if (val != sc->polling) {
972		if (atiixp_chan_active(sc) != 0)
973			err = EBUSY;
974		else if (val == 0) {
975			atiixp_enable_interrupts(sc);
976			sc->polling = 0;
977			DELAY(1000);
978		} else {
979			atiixp_disable_interrupts(sc);
980			sc->polling = 1;
981			DELAY(1000);
982		}
983	}
984	atiixp_unlock(sc);
985
986	return (err);
987}
988#endif
989
990static void
991atiixp_chip_post_init(void *arg)
992{
993	struct atiixp_info *sc = (struct atiixp_info *)arg;
994	uint32_t subdev;
995	int i, timeout, found, polling;
996	char status[SND_STATUSLEN];
997
998	atiixp_lock(sc);
999
1000	if (sc->delayed_attach.ich_func) {
1001		config_intrhook_disestablish(&sc->delayed_attach);
1002		sc->delayed_attach.ich_func = NULL;
1003	}
1004
1005	polling = sc->polling;
1006	sc->polling = 0;
1007
1008	/* wait for the interrupts to happen */
1009	timeout = 100;
1010	do {
1011		msleep(sc, sc->lock, PWAIT, "ixpslp", 1);
1012		if (sc->codec_not_ready_bits)
1013			break;
1014	} while (--timeout);
1015
1016	sc->polling = polling;
1017	atiixp_disable_interrupts(sc);
1018
1019	if (timeout == 0) {
1020		device_printf(sc->dev,
1021			"WARNING: timeout during codec detection; "
1022			"codecs might be present but haven't interrupted\n");
1023		atiixp_unlock(sc);
1024		goto postinitbad;
1025	}
1026
1027	found = 0;
1028
1029	/*
1030	 * ATI IXP can have upto 3 codecs, but single codec should be
1031	 * suffice for now.
1032	 */
1033	if (!(sc->codec_not_ready_bits & ATI_REG_ISR_CODEC0_NOT_READY)) {
1034		/* codec 0 present */
1035		sc->codec_found++;
1036		sc->codec_idx = 0;
1037		found++;
1038	}
1039
1040	if (!(sc->codec_not_ready_bits & ATI_REG_ISR_CODEC1_NOT_READY)) {
1041		/* codec 1 present */
1042		sc->codec_found++;
1043	}
1044
1045	if (!(sc->codec_not_ready_bits & ATI_REG_ISR_CODEC2_NOT_READY)) {
1046		/* codec 2 present */
1047		sc->codec_found++;
1048	}
1049
1050	atiixp_unlock(sc);
1051
1052	if (found == 0)
1053		goto postinitbad;
1054
1055	/* create/init mixer */
1056	sc->codec = AC97_CREATE(sc->dev, sc, atiixp_ac97);
1057	if (sc->codec == NULL)
1058		goto postinitbad;
1059
1060	subdev = (pci_get_subdevice(sc->dev) << 16) |
1061	    pci_get_subvendor(sc->dev);
1062	switch (subdev) {
1063	case 0x11831043:	/* ASUS A6R */
1064	case 0x2043161f:	/* Maxselect x710s - http://maxselect.ru/ */
1065		ac97_setflags(sc->codec, ac97_getflags(sc->codec) |
1066		    AC97_F_EAPD_INV);
1067		break;
1068	default:
1069		break;
1070	}
1071
1072	mixer_init(sc->dev, ac97_getmixerclass(), sc->codec);
1073
1074	if (pcm_register(sc->dev, sc, ATI_IXP_NPCHAN, ATI_IXP_NRCHAN))
1075		goto postinitbad;
1076
1077	for (i = 0; i < ATI_IXP_NPCHAN; i++)
1078		pcm_addchan(sc->dev, PCMDIR_PLAY, &atiixp_chan_class, sc);
1079	for (i = 0; i < ATI_IXP_NRCHAN; i++)
1080		pcm_addchan(sc->dev, PCMDIR_REC, &atiixp_chan_class, sc);
1081
1082#ifdef SND_DYNSYSCTL
1083	SYSCTL_ADD_PROC(device_get_sysctl_ctx(sc->dev),
1084	    SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev)), OID_AUTO,
1085	    "polling", CTLTYPE_INT | CTLFLAG_RW, sc->dev, sizeof(sc->dev),
1086	    sysctl_atiixp_polling, "I", "Enable polling mode");
1087#endif
1088
1089	snprintf(status, SND_STATUSLEN, "at memory 0x%lx irq %ld %s",
1090	    rman_get_start(sc->reg), rman_get_start(sc->irq),
1091	    PCM_KLDSTRING(snd_atiixp));
1092
1093	pcm_setstatus(sc->dev, status);
1094
1095	atiixp_lock(sc);
1096	if (sc->polling == 0)
1097		atiixp_enable_interrupts(sc);
1098	atiixp_unlock(sc);
1099
1100	return;
1101
1102postinitbad:
1103	atiixp_release_resource(sc);
1104}
1105
1106static void
1107atiixp_release_resource(struct atiixp_info *sc)
1108{
1109	if (sc == NULL)
1110		return;
1111	if (sc->codec) {
1112		ac97_destroy(sc->codec);
1113		sc->codec = NULL;
1114	}
1115	if (sc->ih) {
1116		bus_teardown_intr(sc->dev, sc->irq, sc->ih);
1117		sc->ih = NULL;
1118	}
1119	if (sc->reg) {
1120		bus_release_resource(sc->dev, sc->regtype, sc->regid, sc->reg);
1121		sc->reg = NULL;
1122	}
1123	if (sc->irq) {
1124		bus_release_resource(sc->dev, SYS_RES_IRQ, sc->irqid, sc->irq);
1125		sc->irq = NULL;
1126	}
1127	if (sc->parent_dmat) {
1128		bus_dma_tag_destroy(sc->parent_dmat);
1129		sc->parent_dmat = NULL;
1130	}
1131	if (sc->sgd_dmamap)
1132		bus_dmamap_unload(sc->sgd_dmat, sc->sgd_dmamap);
1133	if (sc->sgd_table) {
1134		bus_dmamem_free(sc->sgd_dmat, sc->sgd_table, sc->sgd_dmamap);
1135		sc->sgd_table = NULL;
1136	}
1137	sc->sgd_dmamap = NULL;
1138	if (sc->sgd_dmat) {
1139		bus_dma_tag_destroy(sc->sgd_dmat);
1140		sc->sgd_dmat = NULL;
1141	}
1142	if (sc->lock) {
1143		snd_mtxfree(sc->lock);
1144		sc->lock = NULL;
1145	}
1146}
1147
1148static int
1149atiixp_pci_probe(device_t dev)
1150{
1151	int i;
1152	uint16_t devid, vendor;
1153
1154	vendor = pci_get_vendor(dev);
1155	devid = pci_get_device(dev);
1156	for (i = 0; i < sizeof(atiixp_hw) / sizeof(atiixp_hw[0]); i++) {
1157		if (vendor == atiixp_hw[i].vendor &&
1158		    devid == atiixp_hw[i].devid) {
1159			device_set_desc(dev, atiixp_hw[i].desc);
1160			return (BUS_PROBE_DEFAULT);
1161		}
1162	}
1163
1164	return (ENXIO);
1165}
1166
1167static int
1168atiixp_pci_attach(device_t dev)
1169{
1170	struct atiixp_info *sc;
1171	int i;
1172
1173	if ((sc = malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT | M_ZERO)) == NULL) {
1174		device_printf(dev, "cannot allocate softc\n");
1175		return (ENXIO);
1176	}
1177
1178	sc->lock = snd_mtxcreate(device_get_nameunit(dev), "snd_atiixp softc");
1179	sc->dev = dev;
1180
1181	callout_init(&sc->poll_timer, CALLOUT_MPSAFE);
1182	sc->poll_ticks = 1;
1183
1184	if (resource_int_value(device_get_name(sc->dev),
1185	    device_get_unit(sc->dev), "polling", &i) == 0 && i != 0)
1186		sc->polling = 1;
1187	else
1188		sc->polling = 0;
1189
1190	pci_set_powerstate(dev, PCI_POWERSTATE_D0);
1191	pci_enable_busmaster(dev);
1192
1193	sc->regid = PCIR_BAR(0);
1194	sc->regtype = SYS_RES_MEMORY;
1195	sc->reg = bus_alloc_resource_any(dev, sc->regtype,
1196	    &sc->regid, RF_ACTIVE);
1197
1198	if (!sc->reg) {
1199		device_printf(dev, "unable to allocate register space\n");
1200		goto bad;
1201	}
1202
1203	sc->st = rman_get_bustag(sc->reg);
1204	sc->sh = rman_get_bushandle(sc->reg);
1205
1206	sc->bufsz = pcm_getbuffersize(dev, ATI_IXP_BUFSZ_MIN,
1207	    ATI_IXP_BUFSZ_DEFAULT, ATI_IXP_BUFSZ_MAX);
1208
1209	sc->irqid = 0;
1210	sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irqid,
1211	    RF_ACTIVE | RF_SHAREABLE);
1212	if (!sc->irq || snd_setup_intr(dev, sc->irq, INTR_MPSAFE,
1213	    atiixp_intr, sc, &sc->ih)) {
1214		device_printf(dev, "unable to map interrupt\n");
1215		goto bad;
1216	}
1217
1218	/*
1219	 * Let the user choose the best DMA segments.
1220	 */
1221	if (resource_int_value(device_get_name(dev),
1222	    device_get_unit(dev), "blocksize", &i) == 0 && i > 0) {
1223		i &= ATI_IXP_BLK_ALIGN;
1224		if (i < ATI_IXP_BLK_MIN)
1225			i = ATI_IXP_BLK_MIN;
1226		sc->blkcnt = sc->bufsz / i;
1227		i = 0;
1228		while (sc->blkcnt >> i)
1229			i++;
1230		sc->blkcnt = 1 << (i - 1);
1231		if (sc->blkcnt < ATI_IXP_DMA_CHSEGS_MIN)
1232			sc->blkcnt = ATI_IXP_DMA_CHSEGS_MIN;
1233		else if (sc->blkcnt > ATI_IXP_DMA_CHSEGS_MAX)
1234			sc->blkcnt = ATI_IXP_DMA_CHSEGS_MAX;
1235
1236	} else
1237		sc->blkcnt = ATI_IXP_DMA_CHSEGS;
1238
1239	/*
1240	 * DMA tag for scatter-gather buffers and link pointers
1241	 */
1242	if (bus_dma_tag_create(/*parent*/bus_get_dma_tag(dev), /*alignment*/2,
1243		/*boundary*/0,
1244		/*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
1245		/*highaddr*/BUS_SPACE_MAXADDR,
1246		/*filter*/NULL, /*filterarg*/NULL,
1247		/*maxsize*/sc->bufsz, /*nsegments*/1, /*maxsegz*/0x3ffff,
1248		/*flags*/0, /*lockfunc*/NULL,
1249		/*lockarg*/NULL, &sc->parent_dmat) != 0) {
1250		device_printf(dev, "unable to create dma tag\n");
1251		goto bad;
1252	}
1253
1254	if (bus_dma_tag_create(/*parent*/bus_get_dma_tag(dev), /*alignment*/2,
1255		/*boundary*/0,
1256		/*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
1257		/*highaddr*/BUS_SPACE_MAXADDR,
1258		/*filter*/NULL, /*filterarg*/NULL,
1259		/*maxsize*/ATI_IXP_DMA_CHSEGS_MAX * ATI_IXP_NCHANS *
1260		sizeof(struct atiixp_dma_op),
1261		/*nsegments*/1, /*maxsegz*/0x3ffff,
1262		/*flags*/0, /*lockfunc*/NULL,
1263		/*lockarg*/NULL, &sc->sgd_dmat) != 0) {
1264		device_printf(dev, "unable to create dma tag\n");
1265		goto bad;
1266	}
1267
1268	if (bus_dmamem_alloc(sc->sgd_dmat, (void **)&sc->sgd_table,
1269	    BUS_DMA_NOWAIT, &sc->sgd_dmamap) == -1)
1270		goto bad;
1271
1272	if (bus_dmamap_load(sc->sgd_dmat, sc->sgd_dmamap, sc->sgd_table,
1273	    ATI_IXP_DMA_CHSEGS_MAX * ATI_IXP_NCHANS *
1274	    sizeof(struct atiixp_dma_op), atiixp_dma_cb, sc, 0))
1275		goto bad;
1276
1277
1278	atiixp_chip_pre_init(sc);
1279
1280	sc->delayed_attach.ich_func = atiixp_chip_post_init;
1281	sc->delayed_attach.ich_arg = sc;
1282	if (cold == 0 ||
1283	    config_intrhook_establish(&sc->delayed_attach) != 0) {
1284		sc->delayed_attach.ich_func = NULL;
1285		atiixp_chip_post_init(sc);
1286	}
1287
1288	return (0);
1289
1290bad:
1291	atiixp_release_resource(sc);
1292	return (ENXIO);
1293}
1294
1295static int
1296atiixp_pci_detach(device_t dev)
1297{
1298	int r;
1299	struct atiixp_info *sc;
1300
1301	sc = pcm_getdevinfo(dev);
1302	if (sc != NULL) {
1303		if (sc->codec != NULL) {
1304			r = pcm_unregister(dev);
1305			if (r)
1306				return (r);
1307		}
1308		sc->codec = NULL;
1309		if (sc->st != 0 && sc->sh != 0)
1310			atiixp_disable_interrupts(sc);
1311		atiixp_release_resource(sc);
1312		free(sc, M_DEVBUF);
1313	}
1314	return (0);
1315}
1316
1317static int
1318atiixp_pci_suspend(device_t dev)
1319{
1320	struct atiixp_info *sc = pcm_getdevinfo(dev);
1321	uint32_t value;
1322
1323	/* quickly disable interrupts and save channels active state */
1324	atiixp_lock(sc);
1325	atiixp_disable_interrupts(sc);
1326	atiixp_unlock(sc);
1327
1328	/* stop everything */
1329	if (sc->pch.active != 0)
1330		atiixp_chan_trigger(NULL, &sc->pch, PCMTRIG_STOP);
1331	if (sc->rch.active != 0)
1332		atiixp_chan_trigger(NULL, &sc->rch, PCMTRIG_STOP);
1333
1334	/* power down aclink and pci bus */
1335	atiixp_lock(sc);
1336	value = atiixp_rd(sc, ATI_REG_CMD);
1337	value |= ATI_REG_CMD_POWERDOWN | ATI_REG_CMD_AC_RESET;
1338	atiixp_wr(sc, ATI_REG_CMD, ATI_REG_CMD_POWERDOWN);
1339	pci_set_powerstate(dev, PCI_POWERSTATE_D3);
1340	atiixp_unlock(sc);
1341
1342	return (0);
1343}
1344
1345static int
1346atiixp_pci_resume(device_t dev)
1347{
1348	struct atiixp_info *sc = pcm_getdevinfo(dev);
1349
1350	atiixp_lock(sc);
1351	/* power up pci bus */
1352	pci_set_powerstate(dev, PCI_POWERSTATE_D0);
1353	pci_enable_io(dev, SYS_RES_MEMORY);
1354	pci_enable_busmaster(dev);
1355	/* reset / power up aclink */
1356	atiixp_reset_aclink(sc);
1357	atiixp_unlock(sc);
1358
1359	if (mixer_reinit(dev) == -1) {
1360		device_printf(dev, "unable to reinitialize the mixer\n");
1361		return (ENXIO);
1362	}
1363
1364	/*
1365	 * Resume channel activities. Reset channel format regardless
1366	 * of its previous state.
1367	 */
1368	if (sc->pch.channel != NULL) {
1369		if (sc->pch.fmt != 0)
1370			atiixp_chan_setformat(NULL, &sc->pch, sc->pch.fmt);
1371		if (sc->pch.active != 0)
1372			atiixp_chan_trigger(NULL, &sc->pch, PCMTRIG_START);
1373	}
1374	if (sc->rch.channel != NULL) {
1375		if (sc->rch.fmt != 0)
1376			atiixp_chan_setformat(NULL, &sc->rch, sc->rch.fmt);
1377		if (sc->rch.active != 0)
1378			atiixp_chan_trigger(NULL, &sc->rch, PCMTRIG_START);
1379	}
1380
1381	/* enable interrupts */
1382	atiixp_lock(sc);
1383	if (sc->polling == 0)
1384		atiixp_enable_interrupts(sc);
1385	atiixp_unlock(sc);
1386
1387	return (0);
1388}
1389
1390static device_method_t atiixp_methods[] = {
1391	DEVMETHOD(device_probe,		atiixp_pci_probe),
1392	DEVMETHOD(device_attach,	atiixp_pci_attach),
1393	DEVMETHOD(device_detach,	atiixp_pci_detach),
1394	DEVMETHOD(device_suspend,	atiixp_pci_suspend),
1395	DEVMETHOD(device_resume,	atiixp_pci_resume),
1396	{ 0, 0 }
1397};
1398
1399static driver_t atiixp_driver = {
1400	"pcm",
1401	atiixp_methods,
1402	PCM_SOFTC_SIZE,
1403};
1404
1405DRIVER_MODULE(snd_atiixp, pci, atiixp_driver, pcm_devclass, 0, 0);
1406MODULE_DEPEND(snd_atiixp, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER);
1407MODULE_VERSION(snd_atiixp, 1);
1408