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