kernel: Add descriptions to the intrhooks that miss them.
[dragonfly.git] / sys / dev / sound / pci / atiixp.c
CommitLineData
558a398b
SS
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 *
2ff93029 26 * $FreeBSD: src/sys/dev/sound/pci/atiixp.c,v 1.2.2.8 2007/11/06 02:08:25 ariff Exp $
558a398b
SS
27 */
28
29/*
30 * FreeBSD pcm driver for ATI IXP 150/200/250/300 AC97 controllers
31 *
32 * Features
33 * * 16bit playback / recording
34 * * 32bit native playback - yay!
35 * * 32bit native recording (seems broken on few hardwares)
36 *
37 * Issues / TODO:
38 * * SPDIF
39 * * Support for more than 2 channels.
40 * * VRA ? VRM ? DRA ?
41 * * 32bit native recording seems broken on few hardwares, most
42 * probably because of incomplete VRA/DRA cleanup.
43 *
44 *
45 * Thanks goes to:
46 *
47 * Shaharil @ SCAN Associates whom relentlessly providing me the
48 * mind blowing Acer Ferrari 4002 WLMi with this ATI IXP hardware.
49 *
50 * Reinoud Zandijk <reinoud@NetBSD.org> (auixp), which this driver is
51 * largely based upon although large part of it has been reworked. His
52 * driver is the primary reference and pretty much well documented.
53 *
54 * Takashi Iwai (ALSA snd-atiixp), for register definitions and some
55 * random ninja hackery.
56 */
57
58#include <dev/sound/pcm/sound.h>
59#include <dev/sound/pcm/ac97.h>
60
61#include <bus/pci/pcireg.h>
62#include <bus/pci/pcivar.h>
63#include <sys/sysctl.h>
64#include <sys/endian.h>
65
66#include <dev/sound/pci/atiixp.h>
67
558a398b
SS
68struct atiixp_dma_op {
69 volatile uint32_t addr;
70 volatile uint16_t status;
71 volatile uint16_t size;
72 volatile uint32_t next;
73};
74
75struct atiixp_info;
76
77struct atiixp_chinfo {
78 struct snd_dbuf *buffer;
79 struct pcm_channel *channel;
80 struct atiixp_info *parent;
81 struct atiixp_dma_op *sgd_table;
82 bus_addr_t sgd_addr;
83 uint32_t enable_bit, flush_bit, linkptr_bit, dma_dt_cur_bit;
84 uint32_t dma_segs;
85 uint32_t fmt;
86 int caps_32bit, dir, active;
87};
88
89struct atiixp_info {
90 device_t dev;
91
92 bus_space_tag_t st;
93 bus_space_handle_t sh;
94 bus_dma_tag_t parent_dmat;
95 bus_dma_tag_t sgd_dmat;
96 bus_dmamap_t sgd_dmamap;
97 bus_addr_t sgd_addr;
98
99 struct resource *reg, *irq;
100 int regtype, regid, irqid;
101 void *ih;
102 struct ac97_info *codec;
103
104 struct atiixp_chinfo pch;
105 struct atiixp_chinfo rch;
106 struct atiixp_dma_op *sgd_table;
107 struct intr_config_hook delayed_attach;
108
109 uint32_t bufsz;
110 uint32_t codec_not_ready_bits, codec_idx, codec_found;
111 uint32_t dma_segs;
112 int registered_channels;
113
cad195a6 114 sndlock_t lock;
558a398b
SS
115};
116
117#define atiixp_rd(_sc, _reg) \
118 bus_space_read_4((_sc)->st, (_sc)->sh, _reg)
119#define atiixp_wr(_sc, _reg, _val) \
120 bus_space_write_4((_sc)->st, (_sc)->sh, _reg, _val)
121
122#define atiixp_lock(_sc) snd_mtxlock((_sc)->lock)
123#define atiixp_unlock(_sc) snd_mtxunlock((_sc)->lock)
124#define atiixp_assert(_sc) snd_mtxassert((_sc)->lock)
125
126static uint32_t atiixp_fmt_32bit[] = {
127 AFMT_STEREO | AFMT_S16_LE,
128 AFMT_STEREO | AFMT_S32_LE,
129 0
130};
131
132static uint32_t atiixp_fmt[] = {
133 AFMT_STEREO | AFMT_S16_LE,
134 0
135};
136
137static struct pcmchan_caps atiixp_caps_32bit = {
138 ATI_IXP_BASE_RATE,
139 ATI_IXP_BASE_RATE,
140 atiixp_fmt_32bit, 0
141};
142
143static struct pcmchan_caps atiixp_caps = {
144 ATI_IXP_BASE_RATE,
145 ATI_IXP_BASE_RATE,
146 atiixp_fmt, 0
147};
148
149static const struct {
150 uint16_t vendor;
151 uint16_t devid;
152 char *desc;
153} atiixp_hw[] = {
154 { ATI_VENDOR_ID, ATI_IXP_200_ID, "ATI IXP 200" },
155 { ATI_VENDOR_ID, ATI_IXP_300_ID, "ATI IXP 300" },
156 { ATI_VENDOR_ID, ATI_IXP_400_ID, "ATI IXP 400" },
2ff93029 157 { ATI_VENDOR_ID, ATI_IXP_SB600_ID, "ATI IXP SB600" },
558a398b
SS
158};
159
160static void atiixp_enable_interrupts(struct atiixp_info *);
161static void atiixp_disable_interrupts(struct atiixp_info *);
162static void atiixp_reset_aclink(struct atiixp_info *);
163static void atiixp_flush_dma(struct atiixp_info *, struct atiixp_chinfo *);
164static void atiixp_enable_dma(struct atiixp_info *, struct atiixp_chinfo *);
165static void atiixp_disable_dma(struct atiixp_info *, struct atiixp_chinfo *);
166
167static int atiixp_waitready_codec(struct atiixp_info *);
168static int atiixp_rdcd(kobj_t, void *, int);
169static int atiixp_wrcd(kobj_t, void *, int, uint32_t);
170
171static void *atiixp_chan_init(kobj_t, void *, struct snd_dbuf *,
172 struct pcm_channel *, int);
173static int atiixp_chan_setformat(kobj_t, void *, uint32_t);
174static int atiixp_chan_setspeed(kobj_t, void *, uint32_t);
175static int atiixp_chan_setblocksize(kobj_t, void *, uint32_t);
176static void atiixp_buildsgdt(struct atiixp_chinfo *);
177static int atiixp_chan_trigger(kobj_t, void *, int);
178static int atiixp_chan_getptr(kobj_t, void *);
179static struct pcmchan_caps *atiixp_chan_getcaps(kobj_t, void *);
180
181static void atiixp_intr(void *);
182static void atiixp_dma_cb(void *, bus_dma_segment_t *, int, int);
183static void atiixp_chip_pre_init(struct atiixp_info *);
184static void atiixp_chip_post_init(void *);
185static void atiixp_release_resource(struct atiixp_info *);
186static int atiixp_pci_probe(device_t);
187static int atiixp_pci_attach(device_t);
188static int atiixp_pci_detach(device_t);
189static int atiixp_pci_suspend(device_t);
190static int atiixp_pci_resume(device_t);
191
192/*
193 * ATI IXP helper functions
194 */
195static void
196atiixp_enable_interrupts(struct atiixp_info *sc)
197{
198 uint32_t value;
199
200 /* clear all pending */
201 atiixp_wr(sc, ATI_REG_ISR, 0xffffffff);
202
203 /* enable all relevant interrupt sources we can handle */
204 value = atiixp_rd(sc, ATI_REG_IER);
205
206 value |= ATI_REG_IER_IO_STATUS_EN;
207
208 /*
209 * Disable / ignore internal xrun/spdf interrupt flags
210 * since it doesn't interest us (for now).
211 */
212#if 0
213 value |= ATI_REG_IER_IN_XRUN_EN;
214 value |= ATI_REG_IER_OUT_XRUN_EN;
215
216 value |= ATI_REG_IER_SPDF_XRUN_EN;
217 value |= ATI_REG_IER_SPDF_STATUS_EN;
218#endif
219
220 atiixp_wr(sc, ATI_REG_IER, value);
221}
222
223static void
224atiixp_disable_interrupts(struct atiixp_info *sc)
225{
226 /* disable all interrupt sources */
227 atiixp_wr(sc, ATI_REG_IER, 0);
228
229 /* clear all pending */
230 atiixp_wr(sc, ATI_REG_ISR, 0xffffffff);
231}
232
233static void
234atiixp_reset_aclink(struct atiixp_info *sc)
235{
236 uint32_t value, timeout;
237
238 /* if power is down, power it up */
239 value = atiixp_rd(sc, ATI_REG_CMD);
240 if (value & ATI_REG_CMD_POWERDOWN) {
241 /* explicitly enable power */
242 value &= ~ATI_REG_CMD_POWERDOWN;
243 atiixp_wr(sc, ATI_REG_CMD, value);
244
245 /* have to wait at least 10 usec for it to initialise */
246 DELAY(20);
247 };
248
249 /* perform a soft reset */
250 value = atiixp_rd(sc, ATI_REG_CMD);
251 value |= ATI_REG_CMD_AC_SOFT_RESET;
252 atiixp_wr(sc, ATI_REG_CMD, value);
253
254 /* need to read the CMD reg and wait aprox. 10 usec to init */
255 value = atiixp_rd(sc, ATI_REG_CMD);
256 DELAY(20);
257
258 /* clear soft reset flag again */
259 value = atiixp_rd(sc, ATI_REG_CMD);
260 value &= ~ATI_REG_CMD_AC_SOFT_RESET;
261 atiixp_wr(sc, ATI_REG_CMD, value);
262
263 /* check if the ac-link is working; reset device otherwise */
264 timeout = 10;
265 value = atiixp_rd(sc, ATI_REG_CMD);
266 while (!(value & ATI_REG_CMD_ACLINK_ACTIVE)
267 && --timeout) {
268#if 0
269 device_printf(sc->dev, "not up; resetting aclink hardware\n");
270#endif
271
272 /* dip aclink reset but keep the acsync */
273 value &= ~ATI_REG_CMD_AC_RESET;
274 value |= ATI_REG_CMD_AC_SYNC;
275 atiixp_wr(sc, ATI_REG_CMD, value);
276
277 /* need to read CMD again and wait again (clocking in issue?) */
278 value = atiixp_rd(sc, ATI_REG_CMD);
279 DELAY(20);
280
281 /* assert aclink reset again */
282 value = atiixp_rd(sc, ATI_REG_CMD);
283 value |= ATI_REG_CMD_AC_RESET;
284 atiixp_wr(sc, ATI_REG_CMD, value);
285
286 /* check if its active now */
287 value = atiixp_rd(sc, ATI_REG_CMD);
288 };
289
290 if (timeout == 0)
291 device_printf(sc->dev, "giving up aclink reset\n");
292#if 0
293 if (timeout != 10)
294 device_printf(sc->dev, "aclink hardware reset successful\n");
295#endif
296
297 /* assert reset and sync for safety */
298 value = atiixp_rd(sc, ATI_REG_CMD);
299 value |= ATI_REG_CMD_AC_SYNC | ATI_REG_CMD_AC_RESET;
300 atiixp_wr(sc, ATI_REG_CMD, value);
301}
302
303static void
304atiixp_flush_dma(struct atiixp_info *sc, struct atiixp_chinfo *ch)
305{
306 atiixp_wr(sc, ATI_REG_FIFO_FLUSH, ch->flush_bit);
307}
308
309static void
310atiixp_enable_dma(struct atiixp_info *sc, struct atiixp_chinfo *ch)
311{
312 uint32_t value;
313
314 value = atiixp_rd(sc, ATI_REG_CMD);
315 if (!(value & ch->enable_bit)) {
316 value |= ch->enable_bit;
317 atiixp_wr(sc, ATI_REG_CMD, value);
318 }
319}
320
321static void
322atiixp_disable_dma(struct atiixp_info *sc, struct atiixp_chinfo *ch)
323{
324 uint32_t value;
325
326 value = atiixp_rd(sc, ATI_REG_CMD);
327 if (value & ch->enable_bit) {
328 value &= ~ch->enable_bit;
329 atiixp_wr(sc, ATI_REG_CMD, value);
330 }
331}
332
333/*
334 * AC97 interface
335 */
336static int
337atiixp_waitready_codec(struct atiixp_info *sc)
338{
339 int timeout = 500;
340
341 do {
342 if ((atiixp_rd(sc, ATI_REG_PHYS_OUT_ADDR) &
343 ATI_REG_PHYS_OUT_ADDR_EN) == 0)
344 return 0;
345 DELAY(1);
346 } while (timeout--);
347
348 return -1;
349}
350
351static int
352atiixp_rdcd(kobj_t obj, void *devinfo, int reg)
353{
354 struct atiixp_info *sc = devinfo;
355 uint32_t data;
356 int timeout;
357
358 if (atiixp_waitready_codec(sc))
359 return -1;
360
361 data = (reg << ATI_REG_PHYS_OUT_ADDR_SHIFT) |
362 ATI_REG_PHYS_OUT_ADDR_EN |
363 ATI_REG_PHYS_OUT_RW | sc->codec_idx;
364
365 atiixp_wr(sc, ATI_REG_PHYS_OUT_ADDR, data);
366
367 if (atiixp_waitready_codec(sc))
368 return -1;
369
370 timeout = 500;
371 do {
372 data = atiixp_rd(sc, ATI_REG_PHYS_IN_ADDR);
373 if (data & ATI_REG_PHYS_IN_READ_FLAG)
374 return data >> ATI_REG_PHYS_IN_DATA_SHIFT;
375 DELAY(1);
376 } while (timeout--);
377
378 if (reg < 0x7c)
379 device_printf(sc->dev, "codec read timeout! (reg 0x%x)\n", reg);
380
381 return -1;
382}
383
384static int
385atiixp_wrcd(kobj_t obj, void *devinfo, int reg, uint32_t data)
386{
387 struct atiixp_info *sc = devinfo;
388
389 if (atiixp_waitready_codec(sc))
390 return -1;
391
392 data = (data << ATI_REG_PHYS_OUT_DATA_SHIFT) |
393 (((uint32_t)reg) << ATI_REG_PHYS_OUT_ADDR_SHIFT) |
394 ATI_REG_PHYS_OUT_ADDR_EN | sc->codec_idx;
395
396 atiixp_wr(sc, ATI_REG_PHYS_OUT_ADDR, data);
397
398 return 0;
399}
400
401static kobj_method_t atiixp_ac97_methods[] = {
402 KOBJMETHOD(ac97_read, atiixp_rdcd),
403 KOBJMETHOD(ac97_write, atiixp_wrcd),
404 { 0, 0 }
405};
406AC97_DECLARE(atiixp_ac97);
407
408/*
409 * Playback / Record channel interface
410 */
411static void *
412atiixp_chan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b,
413 struct pcm_channel *c, int dir)
414{
415 struct atiixp_info *sc = devinfo;
416 struct atiixp_chinfo *ch;
417 int num;
418
419 atiixp_lock(sc);
420
421 if (dir == PCMDIR_PLAY) {
422 ch = &sc->pch;
423 ch->linkptr_bit = ATI_REG_OUT_DMA_LINKPTR;
424 ch->enable_bit = ATI_REG_CMD_OUT_DMA_EN | ATI_REG_CMD_SEND_EN;
425 ch->flush_bit = ATI_REG_FIFO_OUT_FLUSH;
426 ch->dma_dt_cur_bit = ATI_REG_OUT_DMA_DT_CUR;
427 /* Native 32bit playback working properly */
428 ch->caps_32bit = 1;
429 } else {
430 ch = &sc->rch;
431 ch->linkptr_bit = ATI_REG_IN_DMA_LINKPTR;
432 ch->enable_bit = ATI_REG_CMD_IN_DMA_EN | ATI_REG_CMD_RECEIVE_EN;
433 ch->flush_bit = ATI_REG_FIFO_IN_FLUSH;
434 ch->dma_dt_cur_bit = ATI_REG_IN_DMA_DT_CUR;
435 /* XXX Native 32bit recording appear to be broken */
436 ch->caps_32bit = 1;
437 }
438
439 ch->buffer = b;
440 ch->parent = sc;
441 ch->channel = c;
442 ch->dir = dir;
443 ch->dma_segs = sc->dma_segs;
444
445 atiixp_unlock(sc);
446
447 if (sndbuf_alloc(ch->buffer, sc->parent_dmat, sc->bufsz) == -1)
448 return NULL;
449
450 atiixp_lock(sc);
451 num = sc->registered_channels++;
452 ch->sgd_table = &sc->sgd_table[num * ch->dma_segs];
453 ch->sgd_addr = sc->sgd_addr +
454 (num * ch->dma_segs * sizeof(struct atiixp_dma_op));
455 atiixp_disable_dma(sc, ch);
456 atiixp_unlock(sc);
457
458 return ch;
459}
460
461static int
462atiixp_chan_setformat(kobj_t obj, void *data, uint32_t format)
463{
464 struct atiixp_chinfo *ch = data;
465 struct atiixp_info *sc = ch->parent;
466 uint32_t value;
467
468 atiixp_lock(sc);
469 if (ch->dir == PCMDIR_REC) {
470 value = atiixp_rd(sc, ATI_REG_CMD);
471 value &= ~ATI_REG_CMD_INTERLEAVE_IN;
472 if ((format & AFMT_32BIT) == 0)
473 value |= ATI_REG_CMD_INTERLEAVE_IN;
474 atiixp_wr(sc, ATI_REG_CMD, value);
475 } else {
476 value = atiixp_rd(sc, ATI_REG_OUT_DMA_SLOT);
477 value &= ~ATI_REG_OUT_DMA_SLOT_MASK;
478 /* We do not have support for more than 2 channels, _yet_. */
479 value |= ATI_REG_OUT_DMA_SLOT_BIT(3) |
480 ATI_REG_OUT_DMA_SLOT_BIT(4);
481 value |= 0x04 << ATI_REG_OUT_DMA_THRESHOLD_SHIFT;
482 atiixp_wr(sc, ATI_REG_OUT_DMA_SLOT, value);
483 value = atiixp_rd(sc, ATI_REG_CMD);
484 value &= ~ATI_REG_CMD_INTERLEAVE_OUT;
485 if ((format & AFMT_32BIT) == 0)
486 value |= ATI_REG_CMD_INTERLEAVE_OUT;
487 atiixp_wr(sc, ATI_REG_CMD, value);
488 value = atiixp_rd(sc, ATI_REG_6CH_REORDER);
489 value &= ~ATI_REG_6CH_REORDER_EN;
490 atiixp_wr(sc, ATI_REG_6CH_REORDER, value);
491 }
492 ch->fmt = format;
493 atiixp_unlock(sc);
494
495 return 0;
496}
497
498static int
499atiixp_chan_setspeed(kobj_t obj, void *data, uint32_t spd)
500{
501 /* XXX We're supposed to do VRA/DRA processing right here */
502 return ATI_IXP_BASE_RATE;
503}
504
505static int
506atiixp_chan_setblocksize(kobj_t obj, void *data, uint32_t blksz)
507{
508 struct atiixp_chinfo *ch = data;
509 struct atiixp_info *sc = ch->parent;
510
511 if (blksz > (sc->bufsz / ch->dma_segs))
512 blksz = sc->bufsz / ch->dma_segs;
513
514 sndbuf_resize(ch->buffer, ch->dma_segs, blksz);
515
516 return sndbuf_getblksz(ch->buffer);
517}
518
519static void
520atiixp_buildsgdt(struct atiixp_chinfo *ch)
521{
522 uint32_t addr, blksz;
523 int i;
524
525 addr = sndbuf_getbufaddr(ch->buffer);
526 blksz = sndbuf_getblksz(ch->buffer);
527
528 for (i = 0; i < ch->dma_segs; i++) {
529 ch->sgd_table[i].addr = htole32(addr + (i * blksz));
530 ch->sgd_table[i].status = htole16(0);
531 ch->sgd_table[i].size = htole16(blksz >> 2);
532 ch->sgd_table[i].next = htole32((uint32_t)ch->sgd_addr +
533 (((i + 1) % ch->dma_segs) *
534 sizeof(struct atiixp_dma_op)));
535 }
536}
537
538static int
539atiixp_chan_trigger(kobj_t obj, void *data, int go)
540{
541 struct atiixp_chinfo *ch = data;
542 struct atiixp_info *sc = ch->parent;
543 uint32_t value;
544
545 atiixp_lock(sc);
546
547 switch (go) {
548 case PCMTRIG_START:
549 atiixp_flush_dma(sc, ch);
550 atiixp_buildsgdt(ch);
551 atiixp_wr(sc, ch->linkptr_bit, 0);
552 atiixp_enable_dma(sc, ch);
553 atiixp_wr(sc, ch->linkptr_bit,
554 (uint32_t)ch->sgd_addr | ATI_REG_LINKPTR_EN);
555 break;
556 case PCMTRIG_STOP:
557 case PCMTRIG_ABORT:
558 atiixp_disable_dma(sc, ch);
559 atiixp_flush_dma(sc, ch);
560 break;
561 default:
562 atiixp_unlock(sc);
563 return 0;
564 break;
565 }
566
567 /* Update bus busy status */
568 value = atiixp_rd(sc, ATI_REG_IER);
569 if (atiixp_rd(sc, ATI_REG_CMD) & (
570 ATI_REG_CMD_SEND_EN | ATI_REG_CMD_RECEIVE_EN |
571 ATI_REG_CMD_SPDF_OUT_EN))
572 value |= ATI_REG_IER_SET_BUS_BUSY;
573 else
574 value &= ~ATI_REG_IER_SET_BUS_BUSY;
575 atiixp_wr(sc, ATI_REG_IER, value);
576
577 atiixp_unlock(sc);
578
579 return 0;
580}
581
582static int
583atiixp_chan_getptr(kobj_t obj, void *data)
584{
585 struct atiixp_chinfo *ch = data;
586 struct atiixp_info *sc = ch->parent;
587 uint32_t addr, align, retry, sz;
588 volatile uint32_t ptr;
589
590 addr = sndbuf_getbufaddr(ch->buffer);
591 align = (ch->fmt & AFMT_32BIT) ? 7 : 3;
592 retry = 100;
593 sz = sndbuf_getblksz(ch->buffer) * ch->dma_segs;
594
595 atiixp_lock(sc);
596 do {
597 ptr = atiixp_rd(sc, ch->dma_dt_cur_bit);
598 if (ptr < addr)
599 continue;
600 ptr -= addr;
601 if (ptr < sz && !(ptr & align))
602 break;
603 } while (--retry);
604 atiixp_unlock(sc);
605
606#if 0
607 if (retry != 100) {
608 device_printf(sc->dev,
609 "%saligned hwptr: dir=PCMDIR_%s ptr=%u fmt=0x%08x retry=%d\n",
610 (ptr & align) ? "un" : "",
611 (ch->dir == PCMDIR_PLAY) ? "PLAY" : "REC", ptr,
612 ch->fmt, 100 - retry);
613 }
614#endif
615
616 return (retry > 0) ? ptr : 0;
617}
618
619static struct pcmchan_caps *
620atiixp_chan_getcaps(kobj_t obj, void *data)
621{
622 struct atiixp_chinfo *ch = data;
623
624 if (ch->caps_32bit)
625 return &atiixp_caps_32bit;
626 return &atiixp_caps;
627}
628
629static kobj_method_t atiixp_chan_methods[] = {
630 KOBJMETHOD(channel_init, atiixp_chan_init),
631 KOBJMETHOD(channel_setformat, atiixp_chan_setformat),
632 KOBJMETHOD(channel_setspeed, atiixp_chan_setspeed),
633 KOBJMETHOD(channel_setblocksize, atiixp_chan_setblocksize),
634 KOBJMETHOD(channel_trigger, atiixp_chan_trigger),
635 KOBJMETHOD(channel_getptr, atiixp_chan_getptr),
636 KOBJMETHOD(channel_getcaps, atiixp_chan_getcaps),
637 { 0, 0 }
638};
639CHANNEL_DECLARE(atiixp_chan);
640
641/*
642 * PCI driver interface
643 */
644static void
645atiixp_intr(void *p)
646{
647 struct atiixp_info *sc = p;
648 uint32_t status, enable, detected_codecs;
649
650 atiixp_lock(sc);
651 status = atiixp_rd(sc, ATI_REG_ISR);
652
653 if (status == 0) {
654 atiixp_unlock(sc);
655 return;
656 }
657
658 if ((status & ATI_REG_ISR_IN_STATUS) && sc->rch.channel) {
659 atiixp_unlock(sc);
660 chn_intr(sc->rch.channel);
661 atiixp_lock(sc);
662 }
663 if ((status & ATI_REG_ISR_OUT_STATUS) && sc->pch.channel) {
664 atiixp_unlock(sc);
665 chn_intr(sc->pch.channel);
666 atiixp_lock(sc);
667 }
668
669#if 0
670 if (status & ATI_REG_ISR_IN_XRUN) {
671 device_printf(sc->dev,
3f625015 672 "Receive IN XRUN interrupt\n");
558a398b
SS
673 }
674 if (status & ATI_REG_ISR_OUT_XRUN) {
675 device_printf(sc->dev,
3f625015 676 "Receive OUT XRUN interrupt\n");
558a398b
SS
677 }
678#endif
679
680 if (status & CODEC_CHECK_BITS) {
681 /* mark missing codecs as not ready */
682 detected_codecs = status & CODEC_CHECK_BITS;
683 sc->codec_not_ready_bits |= detected_codecs;
684
685 /* disable detected interupt sources */
686 enable = atiixp_rd(sc, ATI_REG_IER);
687 enable &= ~detected_codecs;
688 atiixp_wr(sc, ATI_REG_IER, enable);
689 }
690
691 /* acknowledge */
692 atiixp_wr(sc, ATI_REG_ISR, status);
693 atiixp_unlock(sc);
694}
695
696static void
697atiixp_dma_cb(void *p, bus_dma_segment_t *bds, int a, int b)
698{
699 struct atiixp_info *sc = (struct atiixp_info *)p;
700 sc->sgd_addr = bds->ds_addr;
701}
702
703static void
704atiixp_chip_pre_init(struct atiixp_info *sc)
705{
706 uint32_t value;
707
708 atiixp_lock(sc);
709
710 /* disable interrupts */
711 atiixp_disable_interrupts(sc);
712
713 /* clear all DMA enables (preserving rest of settings) */
714 value = atiixp_rd(sc, ATI_REG_CMD);
715 value &= ~(ATI_REG_CMD_IN_DMA_EN | ATI_REG_CMD_OUT_DMA_EN |
716 ATI_REG_CMD_SPDF_OUT_EN );
717 atiixp_wr(sc, ATI_REG_CMD, value);
718
719 /* reset aclink */
720 atiixp_reset_aclink(sc);
721
722 sc->codec_not_ready_bits = 0;
723
724 /* enable all codecs to interrupt as well as the new frame interrupt */
725 atiixp_wr(sc, ATI_REG_IER, CODEC_CHECK_BITS);
726
727 atiixp_unlock(sc);
728}
729
730static void
731atiixp_chip_post_init(void *arg)
732{
733 struct atiixp_info *sc = (struct atiixp_info *)arg;
734 uint32_t subdev;
735 int i, timeout, found;
736 char status[SND_STATUSLEN];
737
738 atiixp_lock(sc);
739
740 if (sc->delayed_attach.ich_func) {
741 config_intrhook_disestablish(&sc->delayed_attach);
742 sc->delayed_attach.ich_func = NULL;
743 }
744
745 /* wait for the interrupts to happen */
746 timeout = 100;
747 while (--timeout) {
cad195a6 748 snd_mtxsleep(sc, sc->lock, 0, "ixpslp", 1);
558a398b
SS
749 if (sc->codec_not_ready_bits)
750 break;
751 }
752
753 atiixp_disable_interrupts(sc);
754
755 if (timeout == 0) {
756 device_printf(sc->dev,
757 "WARNING: timeout during codec detection; "
758 "codecs might be present but haven't interrupted\n");
759 atiixp_unlock(sc);
760 goto postinitbad;
761 }
762
763 found = 0;
764
765 /*
766 * ATI IXP can have upto 3 codecs, but single codec should be
767 * suffice for now.
768 */
769 if (!(sc->codec_not_ready_bits &
770 ATI_REG_ISR_CODEC0_NOT_READY)) {
771 /* codec 0 present */
772 sc->codec_found++;
773 sc->codec_idx = 0;
774 found++;
775 }
776
777 if (!(sc->codec_not_ready_bits &
778 ATI_REG_ISR_CODEC1_NOT_READY)) {
779 /* codec 1 present */
780 sc->codec_found++;
781 }
782
783 if (!(sc->codec_not_ready_bits &
784 ATI_REG_ISR_CODEC2_NOT_READY)) {
785 /* codec 2 present */
786 sc->codec_found++;
787 }
788
789 atiixp_unlock(sc);
790
791 if (found == 0)
792 goto postinitbad;
793
794 /* create/init mixer */
795 sc->codec = AC97_CREATE(sc->dev, sc, atiixp_ac97);
796 if (sc->codec == NULL)
797 goto postinitbad;
798
799 subdev = (pci_get_subdevice(sc->dev) << 16) | pci_get_subvendor(sc->dev);
800 switch (subdev) {
4886ec58 801 case 0x11831043: /* ASUS A6R */
558a398b
SS
802 case 0x2043161f: /* Maxselect x710s - http://maxselect.ru/ */
803 ac97_setflags(sc->codec, ac97_getflags(sc->codec) | AC97_F_EAPD_INV);
804 break;
805 default:
806 break;
807 }
808
809 mixer_init(sc->dev, ac97_getmixerclass(), sc->codec);
810
811 if (pcm_register(sc->dev, sc, ATI_IXP_NPCHAN, ATI_IXP_NRCHAN))
812 goto postinitbad;
813
814 for (i = 0; i < ATI_IXP_NPCHAN; i++)
815 pcm_addchan(sc->dev, PCMDIR_PLAY, &atiixp_chan_class, sc);
816 for (i = 0; i < ATI_IXP_NRCHAN; i++)
817 pcm_addchan(sc->dev, PCMDIR_REC, &atiixp_chan_class, sc);
818
819 ksnprintf(status, SND_STATUSLEN, "at memory 0x%lx irq %ld %s",
820 rman_get_start(sc->reg), rman_get_start(sc->irq),
821 PCM_KLDSTRING(snd_atiixp));
822
823 pcm_setstatus(sc->dev, status);
824
825 atiixp_lock(sc);
826 atiixp_enable_interrupts(sc);
827 atiixp_unlock(sc);
828
829 return;
830
831postinitbad:
832 atiixp_release_resource(sc);
833}
834
835static void
836atiixp_release_resource(struct atiixp_info *sc)
837{
838 if (sc == NULL)
839 return;
840 if (sc->codec) {
841 ac97_destroy(sc->codec);
842 sc->codec = NULL;
843 }
844 if (sc->ih) {
845 bus_teardown_intr(sc->dev, sc->irq, sc->ih);
4886ec58 846 sc->ih = NULL;
558a398b
SS
847 }
848 if (sc->reg) {
849 bus_release_resource(sc->dev, sc->regtype, sc->regid, sc->reg);
4886ec58 850 sc->reg = NULL;
558a398b
SS
851 }
852 if (sc->irq) {
853 bus_release_resource(sc->dev, SYS_RES_IRQ, sc->irqid, sc->irq);
4886ec58 854 sc->irq = NULL;
558a398b
SS
855 }
856 if (sc->parent_dmat) {
857 bus_dma_tag_destroy(sc->parent_dmat);
4886ec58 858 sc->parent_dmat = NULL;
558a398b 859 }
4886ec58 860 if (sc->sgd_dmamap)
558a398b 861 bus_dmamap_unload(sc->sgd_dmat, sc->sgd_dmamap);
4886ec58
HT
862 if (sc->sgd_table) {
863 bus_dmamem_free(sc->sgd_dmat, sc->sgd_table, sc->sgd_dmamap);
864 sc->sgd_table = NULL;
558a398b 865 }
4886ec58 866 sc->sgd_dmamap = NULL;
558a398b
SS
867 if (sc->sgd_dmat) {
868 bus_dma_tag_destroy(sc->sgd_dmat);
4886ec58 869 sc->sgd_dmat = NULL;
558a398b
SS
870 }
871 if (sc->lock) {
872 snd_mtxfree(sc->lock);
873 sc->lock = NULL;
874 }
875}
876
877static int
878atiixp_pci_probe(device_t dev)
879{
880 int i;
881 uint16_t devid, vendor;
882
883 vendor = pci_get_vendor(dev);
884 devid = pci_get_device(dev);
c157ff7a 885 for (i = 0; i < NELEM(atiixp_hw); i++) {
558a398b
SS
886 if (vendor == atiixp_hw[i].vendor &&
887 devid == atiixp_hw[i].devid) {
888 device_set_desc(dev, atiixp_hw[i].desc);
889 return BUS_PROBE_DEFAULT;
890 }
891 }
892
893 return ENXIO;
894}
895
896static int
897atiixp_pci_attach(device_t dev)
898{
899 struct atiixp_info *sc;
900 int i;
901
7522187f 902 sc = kmalloc(sizeof(*sc), M_DEVBUF, M_WAITOK | M_ZERO);
558a398b
SS
903 sc->lock = snd_mtxcreate(device_get_nameunit(dev), "sound softc");
904 sc->dev = dev;
905 /*
906 * Default DMA segments per playback / recording channel
907 */
908 sc->dma_segs = ATI_IXP_DMA_CHSEGS;
909
910 pci_set_powerstate(dev, PCI_POWERSTATE_D0);
911 pci_enable_busmaster(dev);
912
913 sc->regid = PCIR_BAR(0);
914 sc->regtype = SYS_RES_MEMORY;
915 sc->reg = bus_alloc_resource_any(dev, sc->regtype, &sc->regid,
916 RF_ACTIVE);
917
918 if (!sc->reg) {
919 device_printf(dev, "unable to allocate register space\n");
920 goto bad;
921 }
922
923 sc->st = rman_get_bustag(sc->reg);
924 sc->sh = rman_get_bushandle(sc->reg);
925
926 sc->bufsz = pcm_getbuffersize(dev, 4096, ATI_IXP_DEFAULT_BUFSZ, 65536);
927
928 sc->irqid = 0;
929 sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irqid,
930 RF_ACTIVE | RF_SHAREABLE);
931 if (!sc->irq ||
932 snd_setup_intr(dev, sc->irq, INTR_MPSAFE,
933 atiixp_intr, sc, &sc->ih)) {
934 device_printf(dev, "unable to map interrupt\n");
935 goto bad;
936 }
937
938 /*
939 * Let the user choose the best DMA segments.
940 */
941 if (resource_int_value(device_get_name(dev),
942 device_get_unit(dev), "dma_segs",
943 &i) == 0) {
944 if (i < ATI_IXP_DMA_CHSEGS_MIN)
945 i = ATI_IXP_DMA_CHSEGS_MIN;
946 if (i > ATI_IXP_DMA_CHSEGS_MAX)
947 i = ATI_IXP_DMA_CHSEGS_MAX;
948 sc->dma_segs = i;
949 }
950
951 /*
952 * round the value to the nearest ^2
953 */
954 i = 0;
955 while (sc->dma_segs >> i)
956 i++;
957 sc->dma_segs = 1 << (i - 1);
958 if (sc->dma_segs < ATI_IXP_DMA_CHSEGS_MIN)
959 sc->dma_segs = ATI_IXP_DMA_CHSEGS_MIN;
960 else if (sc->dma_segs > ATI_IXP_DMA_CHSEGS_MAX)
961 sc->dma_segs = ATI_IXP_DMA_CHSEGS_MAX;
962
963 /*
964 * DMA tag for scatter-gather buffers and link pointers
965 */
e2339ccc 966 if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0,
558a398b
SS
967 /*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
968 /*highaddr*/BUS_SPACE_MAXADDR,
969 /*filter*/NULL, /*filterarg*/NULL,
970 /*maxsize*/sc->bufsz, /*nsegments*/1, /*maxsegz*/0x3ffff,
971 /*flags*/0,
972 &sc->parent_dmat) != 0) {
973 device_printf(dev, "unable to create dma tag\n");
974 goto bad;
975 }
976
977 if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0,
978 /*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
979 /*highaddr*/BUS_SPACE_MAXADDR,
980 /*filter*/NULL, /*filterarg*/NULL,
981 /*maxsize*/sc->dma_segs * ATI_IXP_NCHANS *
982 sizeof(struct atiixp_dma_op),
983 /*nsegments*/1, /*maxsegz*/0x3ffff,
984 /*flags*/0,
985 &sc->sgd_dmat) != 0) {
986 device_printf(dev, "unable to create dma tag\n");
987 goto bad;
988 }
989
990 if (bus_dmamem_alloc(sc->sgd_dmat, (void **)&sc->sgd_table,
991 BUS_DMA_NOWAIT, &sc->sgd_dmamap) == -1)
992 goto bad;
993
994 if (bus_dmamap_load(sc->sgd_dmat, sc->sgd_dmamap, sc->sgd_table,
995 sc->dma_segs * ATI_IXP_NCHANS *
996 sizeof(struct atiixp_dma_op),
997 atiixp_dma_cb, sc, 0))
998 goto bad;
999
1000
1001 atiixp_chip_pre_init(sc);
1002
1003 sc->delayed_attach.ich_func = atiixp_chip_post_init;
1004 sc->delayed_attach.ich_arg = sc;
52800c9d 1005 sc->delayed_attach.ich_desc = "snd_atiixp";
558a398b
SS
1006 if (cold == 0 ||
1007 config_intrhook_establish(&sc->delayed_attach) != 0) {
1008 sc->delayed_attach.ich_func = NULL;
1009 atiixp_chip_post_init(sc);
1010 }
1011
1012 return 0;
1013
1014bad:
1015 atiixp_release_resource(sc);
1016 return ENXIO;
1017}
1018
1019static int
1020atiixp_pci_detach(device_t dev)
1021{
1022 int r;
1023 struct atiixp_info *sc;
1024
1025 sc = pcm_getdevinfo(dev);
1026 if (sc != NULL) {
1027 if (sc->codec != NULL) {
1028 r = pcm_unregister(dev);
1029 if (r)
1030 return r;
1031 }
1032 sc->codec = NULL;
1033 atiixp_disable_interrupts(sc);
1034 atiixp_release_resource(sc);
1035 kfree(sc, M_DEVBUF);
1036 }
1037 return 0;
1038}
1039
1040static int
1041atiixp_pci_suspend(device_t dev)
1042{
1043 struct atiixp_info *sc = pcm_getdevinfo(dev);
1044 uint32_t value;
1045
1046 /* quickly disable interrupts and save channels active state */
1047 atiixp_lock(sc);
1048 atiixp_disable_interrupts(sc);
1049 value = atiixp_rd(sc, ATI_REG_CMD);
1050 sc->pch.active = (value & ATI_REG_CMD_SEND_EN) ? 1 : 0;
1051 sc->rch.active = (value & ATI_REG_CMD_RECEIVE_EN) ? 1 : 0;
1052 atiixp_unlock(sc);
1053
1054 /* stop everything */
1055 if (sc->pch.channel && sc->pch.active)
1056 atiixp_chan_trigger(NULL, &sc->pch, PCMTRIG_STOP);
1057 if (sc->rch.channel && sc->rch.active)
1058 atiixp_chan_trigger(NULL, &sc->rch, PCMTRIG_STOP);
1059
1060 /* power down aclink and pci bus */
1061 atiixp_lock(sc);
1062 value = atiixp_rd(sc, ATI_REG_CMD);
1063 value |= ATI_REG_CMD_POWERDOWN | ATI_REG_CMD_AC_RESET;
1064 atiixp_wr(sc, ATI_REG_CMD, ATI_REG_CMD_POWERDOWN);
1065 pci_set_powerstate(dev, PCI_POWERSTATE_D3);
1066 atiixp_unlock(sc);
1067
1068 return 0;
1069}
1070
1071static int
1072atiixp_pci_resume(device_t dev)
1073{
1074 struct atiixp_info *sc = pcm_getdevinfo(dev);
1075
1076 atiixp_lock(sc);
1077 /* power up pci bus */
1078 pci_set_powerstate(dev, PCI_POWERSTATE_D0);
1079 pci_enable_io(dev, SYS_RES_MEMORY);
1080 pci_enable_busmaster(dev);
1081 /* reset / power up aclink */
1082 atiixp_reset_aclink(sc);
1083 atiixp_unlock(sc);
1084
1085 if (mixer_reinit(dev) == -1) {
1086 device_printf(dev, "unable to reinitialize the mixer\n");
1087 return ENXIO;
1088 }
1089
1090 /*
1091 * Resume channel activities. Reset channel format regardless
1092 * of its previous state.
1093 */
1094 if (sc->pch.channel) {
1095 if (sc->pch.fmt)
1096 atiixp_chan_setformat(NULL, &sc->pch, sc->pch.fmt);
1097 if (sc->pch.active)
1098 atiixp_chan_trigger(NULL, &sc->pch, PCMTRIG_START);
1099 }
1100 if (sc->rch.channel) {
1101 if (sc->rch.fmt)
1102 atiixp_chan_setformat(NULL, &sc->rch, sc->rch.fmt);
1103 if (sc->rch.active)
1104 atiixp_chan_trigger(NULL, &sc->rch, PCMTRIG_START);
1105 }
1106
1107 /* enable interrupts */
1108 atiixp_lock(sc);
1109 atiixp_enable_interrupts(sc);
1110 atiixp_unlock(sc);
1111
1112 return 0;
1113}
1114
1115static device_method_t atiixp_methods[] = {
1116 DEVMETHOD(device_probe, atiixp_pci_probe),
1117 DEVMETHOD(device_attach, atiixp_pci_attach),
1118 DEVMETHOD(device_detach, atiixp_pci_detach),
1119 DEVMETHOD(device_suspend, atiixp_pci_suspend),
1120 DEVMETHOD(device_resume, atiixp_pci_resume),
1121 { 0, 0 }
1122};
1123
1124static driver_t atiixp_driver = {
1125 "pcm",
1126 atiixp_methods,
1127 PCM_SOFTC_SIZE,
1128};
1129
aa2b9d05 1130DRIVER_MODULE(snd_atiixp, pci, atiixp_driver, pcm_devclass, NULL, NULL);
558a398b
SS
1131MODULE_DEPEND(snd_atiixp, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER);
1132MODULE_VERSION(snd_atiixp, 1);