xref: /freebsd/sys/dev/sound/pci/ich.c (revision 8fa113e5fc65fe6abc757f0089f477a87ee4d185)
1 /*
2  * Copyright (c) 2000 Katsurajima Naoto <raven@katsurajima.seya.yokohama.jp>
3  * Copyright (c) 2001 Cameron Grant <cg@freebsd.org>
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHERIN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THEPOSSIBILITY OF
25  * SUCH DAMAGE.
26  */
27 
28 #include <dev/sound/pcm/sound.h>
29 #include <dev/sound/pcm/ac97.h>
30 #include <dev/sound/pci/ich.h>
31 
32 #include <pci/pcireg.h>
33 #include <pci/pcivar.h>
34 
35 SND_DECLARE_FILE("$FreeBSD$");
36 
37 /* -------------------------------------------------------------------- */
38 
39 #define ICH_TIMEOUT 1000 /* semaphore timeout polling count */
40 #define ICH_DTBL_LENGTH 32
41 #define ICH_DEFAULT_BUFSZ 16384
42 #define ICH_MAX_BUFSZ 65536
43 
44 /* buffer descriptor */
45 struct ich_desc {
46 	volatile u_int32_t buffer;
47 	volatile u_int32_t length;
48 };
49 
50 struct sc_info;
51 
52 /* channel registers */
53 struct sc_chinfo {
54 	u_int32_t num, run;
55 	u_int32_t blksz, blkcnt;
56 	u_int32_t regbase, spdreg;
57 	u_int32_t civ;
58 
59 	struct snd_dbuf *buffer;
60 	struct pcm_channel *channel;
61 	struct sc_info *parent;
62 
63 	struct ich_desc *dtbl;
64 };
65 
66 /* device private data */
67 struct sc_info {
68 	device_t dev;
69 	int hasvra, hasvrm, hasmic;
70 	unsigned int chnum, bufsz;
71 
72 	struct resource *nambar, *nabmbar, *irq;
73 	int nambarid, nabmbarid, irqid;
74 	bus_space_tag_t nambart, nabmbart;
75 	bus_space_handle_t nambarh, nabmbarh;
76 	bus_dma_tag_t dmat;
77 	bus_dmamap_t dtmap;
78 	void *ih;
79 
80 	struct ac97_info *codec;
81 	struct sc_chinfo ch[3];
82 	struct ich_desc *dtbl;
83 };
84 
85 /* -------------------------------------------------------------------- */
86 
87 static u_int32_t ich_fmt[] = {
88 	AFMT_STEREO | AFMT_S16_LE,
89 	0
90 };
91 static struct pcmchan_caps ich_vrcaps = {8000, 48000, ich_fmt, 0};
92 static struct pcmchan_caps ich_caps = {48000, 48000, ich_fmt, 0};
93 
94 /* -------------------------------------------------------------------- */
95 /* Hardware */
96 static u_int32_t
97 ich_rd(struct sc_info *sc, int regno, int size)
98 {
99 	switch (size) {
100 	case 1:
101 		return bus_space_read_1(sc->nabmbart, sc->nabmbarh, regno);
102 	case 2:
103 		return bus_space_read_2(sc->nabmbart, sc->nabmbarh, regno);
104 	case 4:
105 		return bus_space_read_4(sc->nabmbart, sc->nabmbarh, regno);
106 	default:
107 		return 0xffffffff;
108 	}
109 }
110 
111 static void
112 ich_wr(struct sc_info *sc, int regno, u_int32_t data, int size)
113 {
114 	switch (size) {
115 	case 1:
116 		bus_space_write_1(sc->nabmbart, sc->nabmbarh, regno, data);
117 		break;
118 	case 2:
119 		bus_space_write_2(sc->nabmbart, sc->nabmbarh, regno, data);
120 		break;
121 	case 4:
122 		bus_space_write_4(sc->nabmbart, sc->nabmbarh, regno, data);
123 		break;
124 	}
125 }
126 
127 /* ac97 codec */
128 static int
129 ich_waitcd(void *devinfo)
130 {
131 	int i;
132 	u_int32_t data;
133 	struct sc_info *sc = (struct sc_info *)devinfo;
134 
135 	for (i = 0; i < ICH_TIMEOUT; i++) {
136 		data = ich_rd(sc, ICH_REG_ACC_SEMA, 1);
137 		if ((data & 0x01) == 0)
138 			return 0;
139 	}
140 	device_printf(sc->dev, "CODEC semaphore timeout\n");
141 	return ETIMEDOUT;
142 }
143 
144 static int
145 ich_rdcd(kobj_t obj, void *devinfo, int regno)
146 {
147 	struct sc_info *sc = (struct sc_info *)devinfo;
148 
149 	regno &= 0xff;
150 	ich_waitcd(sc);
151 
152 	return bus_space_read_2(sc->nambart, sc->nambarh, regno);
153 }
154 
155 static int
156 ich_wrcd(kobj_t obj, void *devinfo, int regno, u_int16_t data)
157 {
158 	struct sc_info *sc = (struct sc_info *)devinfo;
159 
160 	regno &= 0xff;
161 	ich_waitcd(sc);
162 	bus_space_write_2(sc->nambart, sc->nambarh, regno, data);
163 
164 	return 0;
165 }
166 
167 static kobj_method_t ich_ac97_methods[] = {
168 	KOBJMETHOD(ac97_read,		ich_rdcd),
169 	KOBJMETHOD(ac97_write,		ich_wrcd),
170 	{ 0, 0 }
171 };
172 AC97_DECLARE(ich_ac97);
173 
174 /* -------------------------------------------------------------------- */
175 /* common routines */
176 
177 static void
178 ich_filldtbl(struct sc_chinfo *ch)
179 {
180 	u_int32_t base;
181 	int i;
182 
183 	base = vtophys(sndbuf_getbuf(ch->buffer));
184 	ch->blkcnt = sndbuf_getsize(ch->buffer) / ch->blksz;
185 	if (ch->blkcnt != 2 && ch->blkcnt != 4 && ch->blkcnt != 8 && ch->blkcnt != 16 && ch->blkcnt != 32) {
186 		ch->blkcnt = 2;
187 		ch->blksz = sndbuf_getsize(ch->buffer) / ch->blkcnt;
188 	}
189 
190 	for (i = 0; i < ICH_DTBL_LENGTH; i++) {
191 		ch->dtbl[i].buffer = base + (ch->blksz * (i % ch->blkcnt));
192 		ch->dtbl[i].length = ICH_BDC_IOC | (ch->blksz / 2);
193 	}
194 }
195 
196 static int
197 ich_resetchan(struct sc_info *sc, int num)
198 {
199 	int i, cr, regbase;
200 
201 	if (num == 0)
202 		regbase = ICH_REG_PO_BASE;
203 	else if (num == 1)
204 		regbase = ICH_REG_PI_BASE;
205 	else if (num == 2)
206 		regbase = ICH_REG_MC_BASE;
207 	else
208 		return ENXIO;
209 
210 	ich_wr(sc, regbase + ICH_REG_X_CR, 0, 1);
211 	DELAY(100);
212 	ich_wr(sc, regbase + ICH_REG_X_CR, ICH_X_CR_RR, 1);
213 	for (i = 0; i < ICH_TIMEOUT; i++) {
214 		cr = ich_rd(sc, regbase + ICH_REG_X_CR, 1);
215 		if (cr == 0)
216 			return 0;
217 	}
218 
219 	device_printf(sc->dev, "cannot reset channel %d\n", num);
220 	return ENXIO;
221 }
222 
223 /* -------------------------------------------------------------------- */
224 /* channel interface */
225 
226 static void *
227 ichchan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir)
228 {
229 	struct sc_info *sc = devinfo;
230 	struct sc_chinfo *ch;
231 	unsigned int num;
232 
233 	num = sc->chnum++;
234 	ch = &sc->ch[num];
235 	ch->num = num;
236 	ch->buffer = b;
237 	ch->channel = c;
238 	ch->parent = sc;
239 	ch->run = 0;
240 	ch->dtbl = sc->dtbl + (ch->num * ICH_DTBL_LENGTH);
241 	ch->blkcnt = 2;
242 	ch->blksz = sc->bufsz / ch->blkcnt;
243 
244 	switch(ch->num) {
245 	case 0: /* play */
246 		KASSERT(dir == PCMDIR_PLAY, ("wrong direction"));
247 		ch->regbase = ICH_REG_PO_BASE;
248 		ch->spdreg = sc->hasvra? AC97_REGEXT_FDACRATE : 0;
249 		break;
250 
251 	case 1: /* record */
252 		KASSERT(dir == PCMDIR_REC, ("wrong direction"));
253 		ch->regbase = ICH_REG_PI_BASE;
254 		ch->spdreg = sc->hasvra? AC97_REGEXT_LADCRATE : 0;
255 		break;
256 
257 	case 2: /* mic */
258 		KASSERT(dir == PCMDIR_REC, ("wrong direction"));
259 		ch->regbase = ICH_REG_MC_BASE;
260 		ch->spdreg = sc->hasvrm? AC97_REGEXT_MADCRATE : 0;
261 		break;
262 
263 	default:
264 		return NULL;
265 	}
266 
267 	if (sndbuf_alloc(ch->buffer, sc->dmat, sc->bufsz))
268 		return NULL;
269 
270 	ich_wr(sc, ch->regbase + ICH_REG_X_BDBAR, (u_int32_t)vtophys(ch->dtbl), 4);
271 
272 	return ch;
273 }
274 
275 static int
276 ichchan_setformat(kobj_t obj, void *data, u_int32_t format)
277 {
278 	return 0;
279 }
280 
281 static int
282 ichchan_setspeed(kobj_t obj, void *data, u_int32_t speed)
283 {
284 	struct sc_chinfo *ch = data;
285 	struct sc_info *sc = ch->parent;
286 
287 	if (ch->spdreg)
288 		return ac97_setrate(sc->codec, ch->spdreg, speed);
289 	else
290 		return 48000;
291 }
292 
293 static int
294 ichchan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
295 {
296 	struct sc_chinfo *ch = data;
297 	struct sc_info *sc = ch->parent;
298 
299 	ch->blksz = blocksize;
300 	ich_filldtbl(ch);
301 	ich_wr(sc, ch->regbase + ICH_REG_X_LVI, ch->blkcnt - 1, 1);
302 
303 	return ch->blksz;
304 }
305 
306 static int
307 ichchan_trigger(kobj_t obj, void *data, int go)
308 {
309 	struct sc_chinfo *ch = data;
310 	struct sc_info *sc = ch->parent;
311 
312 	switch (go) {
313 	case PCMTRIG_START:
314 		ch->run = 1;
315 		ich_wr(sc, ch->regbase + ICH_REG_X_BDBAR, (u_int32_t)vtophys(ch->dtbl), 4);
316 		ich_wr(sc, ch->regbase + ICH_REG_X_CR, ICH_X_CR_RPBM | ICH_X_CR_LVBIE | ICH_X_CR_IOCE | ICH_X_CR_FEIE, 1);
317 		break;
318 
319 	case PCMTRIG_ABORT:
320 		ich_resetchan(sc, ch->num);
321 		ch->run = 0;
322 		break;
323 	}
324 	return 0;
325 }
326 
327 static int
328 ichchan_getptr(kobj_t obj, void *data)
329 {
330 	struct sc_chinfo *ch = data;
331 	struct sc_info *sc = ch->parent;
332       	u_int32_t pos;
333 
334 	ch->civ = ich_rd(sc, ch->regbase + ICH_REG_X_CIV, 1) % ch->blkcnt;
335 
336 	pos = ch->civ * ch->blksz;
337 
338 	return pos;
339 }
340 
341 static struct pcmchan_caps *
342 ichchan_getcaps(kobj_t obj, void *data)
343 {
344 	struct sc_chinfo *ch = data;
345 
346 	return ch->spdreg? &ich_vrcaps : &ich_caps;
347 }
348 
349 static kobj_method_t ichchan_methods[] = {
350 	KOBJMETHOD(channel_init,		ichchan_init),
351 	KOBJMETHOD(channel_setformat,		ichchan_setformat),
352 	KOBJMETHOD(channel_setspeed,		ichchan_setspeed),
353 	KOBJMETHOD(channel_setblocksize,	ichchan_setblocksize),
354 	KOBJMETHOD(channel_trigger,		ichchan_trigger),
355 	KOBJMETHOD(channel_getptr,		ichchan_getptr),
356 	KOBJMETHOD(channel_getcaps,		ichchan_getcaps),
357 	{ 0, 0 }
358 };
359 CHANNEL_DECLARE(ichchan);
360 
361 /* -------------------------------------------------------------------- */
362 /* The interrupt handler */
363 
364 static void
365 ich_intr(void *p)
366 {
367 	struct sc_info *sc = (struct sc_info *)p;
368 	struct sc_chinfo *ch;
369 	u_int32_t cbi, lbi, lvi, st;
370 	int i;
371 
372 	for (i = 0; i < 3; i++) {
373 		ch = &sc->ch[i];
374 		/* check channel status */
375 		st = ich_rd(sc, ch->regbase + ICH_REG_X_SR, 2);
376 		st &= ICH_X_SR_FIFOE | ICH_X_SR_BCIS | ICH_X_SR_LVBCI;
377 		if (st != 0) {
378 			if (st & (ICH_X_SR_BCIS | ICH_X_SR_LVBCI)) {
379 				/* block complete - update buffer */
380 				if (ch->run)
381 					chn_intr(ch->channel);
382 				lvi = ich_rd(sc, ch->regbase + ICH_REG_X_LVI, 1);
383 				cbi = ch->civ % ch->blkcnt;
384 				if (cbi == 0)
385 					cbi = ch->blkcnt - 1;
386 				else
387 					cbi--;
388 				lbi = lvi % ch->blkcnt;
389 				if (cbi >= lbi)
390 					lvi += cbi - lbi;
391 				else
392 					lvi += cbi + ch->blkcnt - lbi;
393 				lvi %= ICH_DTBL_LENGTH;
394 				ich_wr(sc, ch->regbase + ICH_REG_X_LVI, lvi, 1);
395 			}
396 			/* clear status bit */
397 			ich_wr(sc, ch->regbase + ICH_REG_X_SR, st, 2);
398 		}
399 	}
400 }
401 
402 /* -------------------------------------------------------------------- */
403 /* Probe and attach the card */
404 
405 static void
406 ich_setmap(void *arg, bus_dma_segment_t *segs, int nseg, int error)
407 {
408 	return;
409 }
410 
411 static int
412 ich_init(struct sc_info *sc)
413 {
414 	u_int32_t stat;
415 	int sz;
416 
417 	ich_wr(sc, ICH_REG_GLOB_CNT, ICH_GLOB_CTL_COLD, 4);
418 	DELAY(600000);
419 	stat = ich_rd(sc, ICH_REG_GLOB_STA, 4);
420 
421 	if ((stat & ICH_GLOB_STA_PCR) == 0)
422 		return ENXIO;
423 
424 	ich_wr(sc, ICH_REG_GLOB_CNT, ICH_GLOB_CTL_COLD | ICH_GLOB_CTL_PRES, 4);
425 
426 	if (ich_resetchan(sc, 0) || ich_resetchan(sc, 1))
427 		return ENXIO;
428 	if (sc->hasmic && ich_resetchan(sc, 2))
429 		return ENXIO;
430 
431 	if (bus_dmamem_alloc(sc->dmat, (void **)&sc->dtbl, BUS_DMA_NOWAIT, &sc->dtmap))
432 		return ENOSPC;
433 
434 	sz = sizeof(struct ich_desc) * ICH_DTBL_LENGTH * 3;
435 	if (bus_dmamap_load(sc->dmat, sc->dtmap, sc->dtbl, sz, ich_setmap, NULL, 0)) {
436 		bus_dmamem_free(sc->dmat, (void **)&sc->dtbl, sc->dtmap);
437 		return ENOSPC;
438 	}
439 
440 	return 0;
441 }
442 
443 static int
444 ich_pci_probe(device_t dev)
445 {
446 	switch(pci_get_devid(dev)) {
447 	case 0x71958086:
448 		device_set_desc(dev, "Intel 443MX");
449 		return 0;
450 
451 	case 0x24158086:
452 		device_set_desc(dev, "Intel 82801AA (ICH)");
453 		return 0;
454 
455 	case 0x24258086:
456 		device_set_desc(dev, "Intel 82801AB (ICH)");
457 		return 0;
458 
459 	case 0x24458086:
460 		device_set_desc(dev, "Intel 82801BA (ICH2)");
461 		return 0;
462 
463 	case 0x24858086:
464 		device_set_desc(dev, "Intel 82801CA (ICH3)");
465 		return 0;
466 
467 	default:
468 		return ENXIO;
469 	}
470 }
471 
472 static int
473 ich_pci_attach(device_t dev)
474 {
475 	u_int32_t		data;
476 	u_int16_t		extcaps;
477 	struct sc_info 		*sc;
478 	char 			status[SND_STATUSLEN];
479 
480 	if ((sc = malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT)) == NULL) {
481 		device_printf(dev, "cannot allocate softc\n");
482 		return ENXIO;
483 	}
484 
485 	bzero(sc, sizeof(*sc));
486 	sc->dev = dev;
487 
488 	data = pci_read_config(dev, PCIR_COMMAND, 2);
489 	data |= (PCIM_CMD_PORTEN | PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN);
490 	pci_write_config(dev, PCIR_COMMAND, data, 2);
491 	data = pci_read_config(dev, PCIR_COMMAND, 2);
492 
493 	sc->nambarid = PCIR_NAMBAR;
494 	sc->nabmbarid = PCIR_NABMBAR;
495 	sc->nambar = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->nambarid, 0, ~0, 1, RF_ACTIVE);
496 	sc->nabmbar = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->nabmbarid, 0, ~0, 1, RF_ACTIVE);
497 
498 	if (!sc->nambar || !sc->nabmbar) {
499 		device_printf(dev, "unable to map IO port space\n");
500 		goto bad;
501 	}
502 
503 	sc->nambart = rman_get_bustag(sc->nambar);
504 	sc->nambarh = rman_get_bushandle(sc->nambar);
505 	sc->nabmbart = rman_get_bustag(sc->nabmbar);
506 	sc->nabmbarh = rman_get_bushandle(sc->nabmbar);
507 
508 	sc->bufsz = pcm_getbuffersize(dev, 4096, ICH_DEFAULT_BUFSZ, ICH_MAX_BUFSZ);
509 	if (bus_dma_tag_create(NULL, 8, 0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR,
510 			       NULL, NULL, sc->bufsz, 1, 0x3ffff, 0, &sc->dmat) != 0) {
511 		device_printf(dev, "unable to create dma tag\n");
512 		goto bad;
513 	}
514 
515 	if (ich_init(sc)) {
516 		device_printf(dev, "unable to initialize the card\n");
517 		goto bad;
518 	}
519 
520 	sc->codec = AC97_CREATE(dev, sc, ich_ac97);
521 	if (sc->codec == NULL)
522 		goto bad;
523 	mixer_init(dev, ac97_getmixerclass(), sc->codec);
524 
525 	/* check and set VRA function */
526 	extcaps = ac97_getextcaps(sc->codec);
527 	sc->hasvra = extcaps & AC97_EXTCAP_VRA;
528 	sc->hasvrm = extcaps & AC97_EXTCAP_VRM;
529 	sc->hasmic = extcaps & AC97_CAP_MICCHANNEL;
530 	ac97_setextmode(sc->codec, sc->hasvra | sc->hasvrm | sc->hasmic);
531 
532 	sc->irqid = 0;
533 	sc->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->irqid, 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE);
534 	if (!sc->irq || snd_setup_intr(dev, sc->irq, INTR_MPSAFE, ich_intr, sc, &sc->ih)) {
535 		device_printf(dev, "unable to map interrupt\n");
536 		goto bad;
537 	}
538 
539 	if (pcm_register(dev, sc, 1, sc->hasmic? 2 : 1))
540 		goto bad;
541 
542 	pcm_addchan(dev, PCMDIR_PLAY, &ichchan_class, sc);		/* play */
543 	pcm_addchan(dev, PCMDIR_REC, &ichchan_class, sc);		/* record */
544 	if (sc->hasmic)
545 		pcm_addchan(dev, PCMDIR_REC, &ichchan_class, sc);	/* record mic */
546 
547 	snprintf(status, SND_STATUSLEN, "at io 0x%lx, 0x%lx irq %ld bufsz %u",
548 		 rman_get_start(sc->nambar), rman_get_start(sc->nabmbar), rman_get_start(sc->irq), sc->bufsz);
549 
550 	pcm_setstatus(dev, status);
551 
552 	return 0;
553 
554 bad:
555 	if (sc->codec)
556 		ac97_destroy(sc->codec);
557 	if (sc->nambar)
558 		bus_release_resource(dev, SYS_RES_IOPORT,
559 		    sc->nambarid, sc->nambar);
560 	if (sc->nabmbar)
561 		bus_release_resource(dev, SYS_RES_IOPORT,
562 		    sc->nabmbarid, sc->nabmbar);
563 	if (sc->ih)
564 		bus_teardown_intr(dev, sc->irq, sc->ih);
565 	if (sc->irq)
566 		bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq);
567 	free(sc, M_DEVBUF);
568 	return ENXIO;
569 }
570 
571 static int
572 ich_pci_detach(device_t dev)
573 {
574 	struct sc_info *sc;
575 	int r;
576 
577 	r = pcm_unregister(dev);
578 	if (r)
579 		return r;
580 	sc = pcm_getdevinfo(dev);
581 
582 	bus_teardown_intr(dev, sc->irq, sc->ih);
583 	bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq);
584 	bus_release_resource(dev, SYS_RES_IOPORT, sc->nambarid, sc->nambar);
585 	bus_release_resource(dev, SYS_RES_IOPORT, sc->nabmbarid, sc->nabmbar);
586 	bus_dma_tag_destroy(sc->dmat);
587 	free(sc, M_DEVBUF);
588 	return 0;
589 }
590 
591 static int
592 ich_pci_resume(device_t dev)
593 {
594 	struct sc_info *sc;
595 
596 	sc = pcm_getdevinfo(dev);
597 
598 	/* Reinit audio device */
599     	if (ich_init(sc) == -1) {
600 		device_printf(dev, "unable to reinitialize the card\n");
601 		return ENXIO;
602 	}
603 	/* Reinit mixer */
604     	if (mixer_reinit(dev) == -1) {
605 		device_printf(dev, "unable to reinitialize the mixer\n");
606 		return ENXIO;
607 	}
608 	return 0;
609 }
610 
611 static device_method_t ich_methods[] = {
612 	/* Device interface */
613 	DEVMETHOD(device_probe,		ich_pci_probe),
614 	DEVMETHOD(device_attach,	ich_pci_attach),
615 	DEVMETHOD(device_detach,	ich_pci_detach),
616 	DEVMETHOD(device_resume,	ich_pci_resume),
617 	{ 0, 0 }
618 };
619 
620 static driver_t ich_driver = {
621 	"pcm",
622 	ich_methods,
623 	PCM_SOFTC_SIZE,
624 };
625 
626 DRIVER_MODULE(snd_ich, pci, ich_driver, pcm_devclass, 0, 0);
627 MODULE_DEPEND(snd_ich, snd_pcm, PCM_MINVER, PCM_PREFVER, PCM_MAXVER);
628 MODULE_VERSION(snd_ich, 1);
629