Merge branch 'vendor/OPENSSH'
[dragonfly.git] / sys / dev / sound / pci / envy24.c
1 /*-
2  * Copyright (c) 2001 Katsurajima Naoto <raven@katsurajima.seya.yokohama.jp>
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 THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  */
27
28 #ifdef HAVE_KERNEL_OPTION_HEADERS
29 #include "opt_snd.h"
30 #endif
31
32 #include <dev/sound/pcm/sound.h>
33 #include <dev/sound/pcm/ac97.h>
34 #include <dev/sound/pci/spicds.h>
35 #include <dev/sound/pci/envy24.h>
36
37 #include <bus/pci/pcireg.h>
38 #include <bus/pci/pcivar.h>
39
40 #include "mixer_if.h"
41
42 SND_DECLARE_FILE("$FreeBSD: head/sys/dev/sound/pci/envy24.c 274035 2014-11-03 11:11:45Z bapt $");
43
44 static MALLOC_DEFINE(M_ENVY24, "envy24", "envy24 audio");
45
46 /* -------------------------------------------------------------------- */
47
48 struct sc_info;
49
50 #define ENVY24_PLAY_CHNUM 10
51 #define ENVY24_REC_CHNUM 12
52 #define ENVY24_PLAY_BUFUNIT (4 /* byte/sample */ * 10 /* channel */)
53 #define ENVY24_REC_BUFUNIT  (4 /* byte/sample */ * 12 /* channel */)
54 #define ENVY24_SAMPLE_NUM   4096
55
56 #define ENVY24_TIMEOUT 1000
57
58 #define ENVY24_DEFAULT_FORMAT   SND_FORMAT(AFMT_S16_LE, 2, 0)
59
60 #define ENVY24_NAMELEN 32
61
62 #define SDA_GPIO 0x10
63 #define SCL_GPIO 0x20
64
65 struct envy24_sample {
66         volatile u_int32_t buffer;
67 };
68
69 typedef struct envy24_sample sample32_t;
70
71 /* channel registers */
72 struct sc_chinfo {
73         struct snd_dbuf         *buffer;
74         struct pcm_channel      *channel;
75         struct sc_info          *parent;
76         int                     dir;
77         unsigned                num; /* hw channel number */
78
79         /* channel information */
80         u_int32_t               format;
81         u_int32_t               speed;
82         u_int32_t               blk; /* hw block size(dword) */
83
84         /* format conversion structure */
85         u_int8_t                *data;
86         unsigned int            size; /* data buffer size(byte) */
87         int                     unit; /* sample size(byte) */
88         unsigned int            offset; /* samples number offset */
89         void                    (*emldma)(struct sc_chinfo *);
90
91         /* flags */
92         int                     run;
93 };
94
95 /* codec interface entrys */
96 struct codec_entry {
97         void *(*create)(device_t dev, void *devinfo, int dir, int num);
98         void (*destroy)(void *codec);
99         void (*init)(void *codec);
100         void (*reinit)(void *codec);
101         void (*setvolume)(void *codec, int dir, unsigned int left, unsigned int right);
102         void (*setrate)(void *codec, int which, int rate);
103 };
104
105 /* system configuration information */
106 struct cfg_info {
107         char *name;
108         u_int16_t subvendor, subdevice;
109         u_int8_t scfg, acl, i2s, spdif;
110         u_int8_t gpiomask, gpiostate, gpiodir;
111         u_int8_t cdti, cclk, cs, cif, type;
112         u_int8_t free;
113         struct codec_entry *codec;
114 };
115
116 /* device private data */
117 struct sc_info {
118         device_t        dev;
119         struct lock     *lock;
120
121         /* Control/Status registor */
122         struct resource *cs;
123         int             csid;
124         bus_space_tag_t cst;
125         bus_space_handle_t csh;
126         /* DDMA registor */
127         struct resource *ddma;
128         int             ddmaid;
129         bus_space_tag_t ddmat;
130         bus_space_handle_t ddmah;
131         /* Consumer Section DMA Channel Registers */
132         struct resource *ds;
133         int             dsid;
134         bus_space_tag_t dst;
135         bus_space_handle_t dsh;
136         /* MultiTrack registor */
137         struct resource *mt;
138         int             mtid;
139         bus_space_tag_t mtt;
140         bus_space_handle_t mth;
141         /* DMA tag */
142         bus_dma_tag_t dmat;
143         /* IRQ resource */
144         struct resource *irq;
145         int             irqid;
146         void            *ih;
147
148         /* system configuration data */
149         struct cfg_info *cfg;
150
151         /* ADC/DAC number and info */
152         int             adcn, dacn;
153         void            *adc[4], *dac[4];
154
155         /* mixer control data */
156         u_int32_t       src;
157         u_int8_t        left[ENVY24_CHAN_NUM];
158         u_int8_t        right[ENVY24_CHAN_NUM];
159
160         /* Play/Record DMA fifo */
161         sample32_t      *pbuf;
162         sample32_t      *rbuf;
163         u_int32_t       psize, rsize; /* DMA buffer size(byte) */
164         u_int16_t       blk[2]; /* transfer check blocksize(dword) */
165         bus_dmamap_t    pmap, rmap;
166         bus_addr_t      paddr, raddr;
167
168         /* current status */
169         u_int32_t       speed;
170         int             run[2];
171         u_int16_t       intr[2];
172         struct pcmchan_caps     caps[2];
173
174         /* channel info table */
175         unsigned        chnum;
176         struct sc_chinfo chan[11];
177 };
178
179 /* -------------------------------------------------------------------- */
180
181 /*
182  * prototypes
183  */
184
185 /* DMA emulator */
186 static void envy24_p8u(struct sc_chinfo *);
187 static void envy24_p16sl(struct sc_chinfo *);
188 static void envy24_p32sl(struct sc_chinfo *);
189 static void envy24_r16sl(struct sc_chinfo *);
190 static void envy24_r32sl(struct sc_chinfo *);
191
192 /* channel interface */
193 static void *envy24chan_init(kobj_t, void *, struct snd_dbuf *, struct pcm_channel *, int);
194 static int envy24chan_setformat(kobj_t, void *, u_int32_t);
195 static u_int32_t envy24chan_setspeed(kobj_t, void *, u_int32_t);
196 static u_int32_t envy24chan_setblocksize(kobj_t, void *, u_int32_t);
197 static int envy24chan_trigger(kobj_t, void *, int);
198 static u_int32_t envy24chan_getptr(kobj_t, void *);
199 static struct pcmchan_caps *envy24chan_getcaps(kobj_t, void *);
200
201 /* mixer interface */
202 static int envy24mixer_init(struct snd_mixer *);
203 static int envy24mixer_reinit(struct snd_mixer *);
204 static int envy24mixer_uninit(struct snd_mixer *);
205 static int envy24mixer_set(struct snd_mixer *, unsigned, unsigned, unsigned);
206 static u_int32_t envy24mixer_setrecsrc(struct snd_mixer *, u_int32_t);
207
208 /* M-Audio Delta series AK4524 access interface */
209 static void *envy24_delta_ak4524_create(device_t, void *, int, int);
210 static void envy24_delta_ak4524_destroy(void *);
211 static void envy24_delta_ak4524_init(void *);
212 static void envy24_delta_ak4524_reinit(void *);
213 static void envy24_delta_ak4524_setvolume(void *, int, unsigned int, unsigned int);
214
215 /* -------------------------------------------------------------------- */
216
217 /*
218   system constant tables
219 */
220
221 /* API -> hardware channel map */
222 static unsigned envy24_chanmap[ENVY24_CHAN_NUM] = {
223         ENVY24_CHAN_PLAY_SPDIF, /* 0 */
224         ENVY24_CHAN_PLAY_DAC1,  /* 1 */
225         ENVY24_CHAN_PLAY_DAC2,  /* 2 */
226         ENVY24_CHAN_PLAY_DAC3,  /* 3 */
227         ENVY24_CHAN_PLAY_DAC4,  /* 4 */
228         ENVY24_CHAN_REC_MIX,    /* 5 */
229         ENVY24_CHAN_REC_SPDIF,  /* 6 */
230         ENVY24_CHAN_REC_ADC1,   /* 7 */
231         ENVY24_CHAN_REC_ADC2,   /* 8 */
232         ENVY24_CHAN_REC_ADC3,   /* 9 */
233         ENVY24_CHAN_REC_ADC4,   /* 10 */
234 };
235
236 /* mixer -> API channel map. see above */
237 static int envy24_mixmap[] = {
238         -1, /* Master output level. It is depend on codec support */
239         -1, /* Treble level of all output channels */
240         -1, /* Bass level of all output channels */
241         -1, /* Volume of synthesier input */
242         0,  /* Output level for the audio device */
243         -1, /* Output level for the PC speaker */
244         7,  /* line in jack */
245         -1, /* microphone jack */
246         -1, /* CD audio input */
247         -1, /* Recording monitor */
248         1,  /* alternative codec */
249         -1, /* global recording level */
250         -1, /* Input gain */
251         -1, /* Output gain */
252         8,  /* Input source 1 */
253         9,  /* Input source 2 */
254         10, /* Input source 3 */
255         6,  /* Digital (input) 1 */
256         -1, /* Digital (input) 2 */
257         -1, /* Digital (input) 3 */
258         -1, /* Phone input */
259         -1, /* Phone output */
260         -1, /* Video/TV (audio) in */
261         -1, /* Radio in */
262         -1, /* Monitor volume */
263 };
264
265 /* variable rate audio */
266 static u_int32_t envy24_speed[] = {
267     96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000,
268     12000, 11025, 9600, 8000, 0
269 };
270
271 /* known boards configuration */
272 static struct codec_entry delta_codec = {
273         envy24_delta_ak4524_create,
274         envy24_delta_ak4524_destroy,
275         envy24_delta_ak4524_init,
276         envy24_delta_ak4524_reinit,
277         envy24_delta_ak4524_setvolume,
278         NULL, /* setrate */
279 };
280
281 static struct cfg_info cfg_table[] = {
282         {
283                 "Envy24 audio (M Audio Delta Dio 2496)",
284                 0x1412, 0xd631,
285                 0x10, 0x80, 0xf0, 0x03,
286                 0x02, 0xc0, 0xfd,
287                 0x10, 0x20, 0x40, 0x00, 0x00,
288                 0x00,
289                 &delta_codec,
290         },
291         {
292                 "Envy24 audio (Terratec DMX 6fire)",
293                 0x153b, 0x1138,
294                 0x2f, 0x80, 0xf0, 0x03,
295                 0xc0, 0xff, 0x7f,
296                 0x10, 0x20, 0x01, 0x01, 0x00,
297                 0x00,
298                 &delta_codec,
299         },
300         {
301                 "Envy24 audio (M Audio Audiophile 2496)",
302                 0x1412, 0xd634,
303                 0x10, 0x80, 0x72, 0x03,
304                 0x04, 0xfe, 0xfb,
305                 0x08, 0x02, 0x20, 0x00, 0x01,
306                 0x00,
307                 &delta_codec,
308         },
309         {
310                 "Envy24 audio (M Audio Delta 66)",
311                 0x1412, 0xd632,
312                 0x15, 0x80, 0xf0, 0x03,
313                 0x02, 0xc0, 0xfd,
314                 0x10, 0x20, 0x40, 0x00, 0x00,
315                 0x00,
316                 &delta_codec,
317         },
318         {
319                 "Envy24 audio (M Audio Delta 44)",
320                 0x1412, 0xd633,
321                 0x15, 0x80, 0xf0, 0x00,
322                 0x02, 0xc0, 0xfd,
323                 0x10, 0x20, 0x40, 0x00, 0x00,
324                 0x00,
325                 &delta_codec,
326         },
327         {
328                 "Envy24 audio (M Audio Delta 1010)",
329                 0x1412, 0xd630,
330                 0x1f, 0x80, 0xf0, 0x03,
331                 0x22, 0xd0, 0xdd,
332                 0x10, 0x20, 0x40, 0x00, 0x00,
333                 0x00,
334                 &delta_codec,
335         },
336         {
337                 "Envy24 audio (M Audio Delta 1010LT)",
338                 0x1412, 0xd63b,
339                 0x1f, 0x80, 0x72, 0x03,
340                 0x04, 0x7e, 0xfb,
341                 0x08, 0x02, 0x70, 0x00, 0x00,
342                 0x00,
343                 &delta_codec,
344         },
345         {
346                 "Envy24 audio (Terratec EWX 2496)",
347                 0x153b, 0x1130,
348                 0x10, 0x80, 0xf0, 0x03,
349                 0xc0, 0x3f, 0x3f,
350                 0x10, 0x20, 0x01, 0x01, 0x00,
351                 0x00,
352                 &delta_codec,
353         },
354         {
355                 "Envy24 audio (Generic)",
356                 0, 0,
357                 0x0f, 0x00, 0x01, 0x03,
358                 0xff, 0x00, 0x00,
359                 0x10, 0x20, 0x40, 0x00, 0x00,
360                 0x00,
361                 &delta_codec, /* default codec routines */
362         }
363 };
364
365 static u_int32_t envy24_recfmt[] = {
366         SND_FORMAT(AFMT_S16_LE, 2, 0),
367         SND_FORMAT(AFMT_S32_LE, 2, 0),
368         0
369 };
370 static struct pcmchan_caps envy24_reccaps = {8000, 96000, envy24_recfmt, 0};
371
372 static u_int32_t envy24_playfmt[] = {
373         SND_FORMAT(AFMT_U8, 2, 0),
374         SND_FORMAT(AFMT_S16_LE, 2, 0),
375         SND_FORMAT(AFMT_S32_LE, 2, 0),
376         0
377 };
378
379 static struct pcmchan_caps envy24_playcaps = {8000, 96000, envy24_playfmt, 0};
380
381 struct envy24_emldma {
382         u_int32_t       format;
383         void            (*emldma)(struct sc_chinfo *);
384         int             unit;
385 };
386
387 static struct envy24_emldma envy24_pemltab[] = {
388         {SND_FORMAT(AFMT_U8, 2, 0), envy24_p8u, 2},
389         {SND_FORMAT(AFMT_S16_LE, 2, 0), envy24_p16sl, 4},
390         {SND_FORMAT(AFMT_S32_LE, 2, 0), envy24_p32sl, 8},
391         {0, NULL, 0}
392 };
393
394 static struct envy24_emldma envy24_remltab[] = {
395         {SND_FORMAT(AFMT_S16_LE, 2, 0), envy24_r16sl, 4},
396         {SND_FORMAT(AFMT_S32_LE, 2, 0), envy24_r32sl, 8},
397         {0, NULL, 0}
398 };
399
400 /* -------------------------------------------------------------------- */
401
402 /* common routines */
403 static u_int32_t
404 envy24_rdcs(struct sc_info *sc, int regno, int size)
405 {
406         switch (size) {
407         case 1:
408                 return bus_space_read_1(sc->cst, sc->csh, regno);
409         case 2:
410                 return bus_space_read_2(sc->cst, sc->csh, regno);
411         case 4:
412                 return bus_space_read_4(sc->cst, sc->csh, regno);
413         default:
414                 return 0xffffffff;
415         }
416 }
417
418 static void
419 envy24_wrcs(struct sc_info *sc, int regno, u_int32_t data, int size)
420 {
421         switch (size) {
422         case 1:
423                 bus_space_write_1(sc->cst, sc->csh, regno, data);
424                 break;
425         case 2:
426                 bus_space_write_2(sc->cst, sc->csh, regno, data);
427                 break;
428         case 4:
429                 bus_space_write_4(sc->cst, sc->csh, regno, data);
430                 break;
431         }
432 }
433
434 static u_int32_t
435 envy24_rdmt(struct sc_info *sc, int regno, int size)
436 {
437         switch (size) {
438         case 1:
439                 return bus_space_read_1(sc->mtt, sc->mth, regno);
440         case 2:
441                 return bus_space_read_2(sc->mtt, sc->mth, regno);
442         case 4:
443                 return bus_space_read_4(sc->mtt, sc->mth, regno);
444         default:
445                 return 0xffffffff;
446         }
447 }
448
449 static void
450 envy24_wrmt(struct sc_info *sc, int regno, u_int32_t data, int size)
451 {
452         switch (size) {
453         case 1:
454                 bus_space_write_1(sc->mtt, sc->mth, regno, data);
455                 break;
456         case 2:
457                 bus_space_write_2(sc->mtt, sc->mth, regno, data);
458                 break;
459         case 4:
460                 bus_space_write_4(sc->mtt, sc->mth, regno, data);
461                 break;
462         }
463 }
464
465 static u_int32_t
466 envy24_rdci(struct sc_info *sc, int regno)
467 {
468         envy24_wrcs(sc, ENVY24_CCS_INDEX, regno, 1);
469         return envy24_rdcs(sc, ENVY24_CCS_DATA, 1);
470 }
471
472 static void
473 envy24_wrci(struct sc_info *sc, int regno, u_int32_t data)
474 {
475         envy24_wrcs(sc, ENVY24_CCS_INDEX, regno, 1);
476         envy24_wrcs(sc, ENVY24_CCS_DATA, data, 1);
477 }
478
479 /* -------------------------------------------------------------------- */
480
481 /* I2C port/E2PROM access routines */
482
483 static int
484 envy24_rdi2c(struct sc_info *sc, u_int32_t dev, u_int32_t addr)
485 {
486         u_int32_t data;
487         int i;
488
489 #if(0)
490         device_printf(sc->dev, "envy24_rdi2c(sc, 0x%02x, 0x%02x)\n", dev, addr);
491 #endif
492         for (i = 0; i < ENVY24_TIMEOUT; i++) {
493                 data = envy24_rdcs(sc, ENVY24_CCS_I2CSTAT, 1);
494                 if ((data & ENVY24_CCS_I2CSTAT_BSY) == 0)
495                         break;
496                 DELAY(32); /* 31.25kHz */
497         }
498         if (i == ENVY24_TIMEOUT) {
499                 return -1;
500         }
501         envy24_wrcs(sc, ENVY24_CCS_I2CADDR, addr, 1);
502         envy24_wrcs(sc, ENVY24_CCS_I2CDEV,
503             (dev & ENVY24_CCS_I2CDEV_ADDR) | ENVY24_CCS_I2CDEV_RD, 1);
504         for (i = 0; i < ENVY24_TIMEOUT; i++) {
505                 data = envy24_rdcs(sc, ENVY24_CCS_I2CSTAT, 1);
506                 if ((data & ENVY24_CCS_I2CSTAT_BSY) == 0)
507                         break;
508                 DELAY(32); /* 31.25kHz */
509         }
510         if (i == ENVY24_TIMEOUT) {
511                 return -1;
512         }
513         data = envy24_rdcs(sc, ENVY24_CCS_I2CDATA, 1);
514
515 #if(0)
516         device_printf(sc->dev, "envy24_rdi2c(): return 0x%x\n", data);
517 #endif
518         return (int)data;
519 }
520
521 #if 0
522 static int
523 envy24_wri2c(struct sc_info *sc, u_int32_t dev, u_int32_t addr, u_int32_t data)
524 {
525         u_int32_t tmp;
526         int i;
527
528 #if(0)
529         device_printf(sc->dev, "envy24_rdi2c(sc, 0x%02x, 0x%02x)\n", dev, addr);
530 #endif
531         for (i = 0; i < ENVY24_TIMEOUT; i++) {
532                 tmp = envy24_rdcs(sc, ENVY24_CCS_I2CSTAT, 1);
533                 if ((tmp & ENVY24_CCS_I2CSTAT_BSY) == 0)
534                         break;
535                 DELAY(32); /* 31.25kHz */
536         }
537         if (i == ENVY24_TIMEOUT) {
538                 return -1;
539         }
540         envy24_wrcs(sc, ENVY24_CCS_I2CADDR, addr, 1);
541         envy24_wrcs(sc, ENVY24_CCS_I2CDATA, data, 1);
542         envy24_wrcs(sc, ENVY24_CCS_I2CDEV,
543             (dev & ENVY24_CCS_I2CDEV_ADDR) | ENVY24_CCS_I2CDEV_WR, 1);
544         for (i = 0; i < ENVY24_TIMEOUT; i++) {
545                 data = envy24_rdcs(sc, ENVY24_CCS_I2CSTAT, 1);
546                 if ((data & ENVY24_CCS_I2CSTAT_BSY) == 0)
547                         break;
548                 DELAY(32); /* 31.25kHz */
549         }
550         if (i == ENVY24_TIMEOUT) {
551                 return -1;
552         }
553
554         return 0;
555 }
556 #endif
557
558 static int
559 envy24_rdrom(struct sc_info *sc, u_int32_t addr)
560 {
561         u_int32_t data;
562
563 #if(0)
564         device_printf(sc->dev, "envy24_rdrom(sc, 0x%02x)\n", addr);
565 #endif
566         data = envy24_rdcs(sc, ENVY24_CCS_I2CSTAT, 1);
567         if ((data & ENVY24_CCS_I2CSTAT_ROM) == 0) {
568 #if(0)
569                 device_printf(sc->dev, "envy24_rdrom(): E2PROM not presented\n");
570 #endif
571                 return -1;
572         }
573
574         return envy24_rdi2c(sc, ENVY24_CCS_I2CDEV_ROM, addr);
575 }
576
577 static struct cfg_info *
578 envy24_rom2cfg(struct sc_info *sc)
579 {
580         struct cfg_info *buff;
581         int size;
582         int i;
583
584 #if(0)
585         device_printf(sc->dev, "envy24_rom2cfg(sc)\n");
586 #endif
587         size = envy24_rdrom(sc, ENVY24_E2PROM_SIZE);
588         if (size < ENVY24_E2PROM_GPIODIR + 1) {
589 #if(0)
590                 device_printf(sc->dev, "envy24_rom2cfg(): ENVY24_E2PROM_SIZE-->%d\n", size);
591 #endif
592                 return NULL;
593         }
594         buff = kmalloc(sizeof(*buff), M_ENVY24, M_WAITOK | M_ZERO);
595         if (buff == NULL) {
596 #if(0)
597                 device_printf(sc->dev, "envy24_rom2cfg(): malloc()\n");
598 #endif
599                 return NULL;
600         }
601         buff->free = 1;
602
603         buff->subvendor = envy24_rdrom(sc, ENVY24_E2PROM_SUBVENDOR) << 8;
604         buff->subvendor += envy24_rdrom(sc, ENVY24_E2PROM_SUBVENDOR + 1);
605         buff->subdevice = envy24_rdrom(sc, ENVY24_E2PROM_SUBDEVICE) << 8;
606         buff->subdevice += envy24_rdrom(sc, ENVY24_E2PROM_SUBDEVICE + 1);
607         buff->scfg = envy24_rdrom(sc, ENVY24_E2PROM_SCFG);
608         buff->acl = envy24_rdrom(sc, ENVY24_E2PROM_ACL);
609         buff->i2s = envy24_rdrom(sc, ENVY24_E2PROM_I2S);
610         buff->spdif = envy24_rdrom(sc, ENVY24_E2PROM_SPDIF);
611         buff->gpiomask = envy24_rdrom(sc, ENVY24_E2PROM_GPIOMASK);
612         buff->gpiostate = envy24_rdrom(sc, ENVY24_E2PROM_GPIOSTATE);
613         buff->gpiodir = envy24_rdrom(sc, ENVY24_E2PROM_GPIODIR);
614
615         for (i = 0; cfg_table[i].subvendor != 0 || cfg_table[i].subdevice != 0; i++)
616                 if (cfg_table[i].subvendor == buff->subvendor &&
617                     cfg_table[i].subdevice == buff->subdevice)
618                         break;
619         buff->name = cfg_table[i].name;
620         buff->codec = cfg_table[i].codec;
621
622         return buff;
623 }
624
625 static void
626 envy24_cfgfree(struct cfg_info *cfg) {
627         if (cfg == NULL)
628                 return;
629         if (cfg->free)
630                 kfree(cfg, M_ENVY24);
631         return;
632 }
633
634 /* -------------------------------------------------------------------- */
635
636 /* AC'97 codec access routines */
637
638 #if 0
639 static int
640 envy24_coldcd(struct sc_info *sc)
641 {
642         u_int32_t data;
643         int i;
644
645 #if(0)
646         device_printf(sc->dev, "envy24_coldcd()\n");
647 #endif
648         envy24_wrmt(sc, ENVY24_MT_AC97CMD, ENVY24_MT_AC97CMD_CLD, 1);
649         DELAY(10);
650         envy24_wrmt(sc, ENVY24_MT_AC97CMD, 0, 1);
651         DELAY(1000);
652         for (i = 0; i < ENVY24_TIMEOUT; i++) {
653                 data = envy24_rdmt(sc, ENVY24_MT_AC97CMD, 1);
654                 if (data & ENVY24_MT_AC97CMD_RDY) {
655                         return 0;
656                 }
657         }
658
659         return -1;
660 }
661 #endif
662
663 static int
664 envy24_slavecd(struct sc_info *sc)
665 {
666         u_int32_t data;
667         int i;
668
669 #if(0)
670         device_printf(sc->dev, "envy24_slavecd()\n");
671 #endif
672         envy24_wrmt(sc, ENVY24_MT_AC97CMD,
673             ENVY24_MT_AC97CMD_CLD | ENVY24_MT_AC97CMD_WRM, 1);
674         DELAY(10);
675         envy24_wrmt(sc, ENVY24_MT_AC97CMD, 0, 1);
676         DELAY(1000);
677         for (i = 0; i < ENVY24_TIMEOUT; i++) {
678                 data = envy24_rdmt(sc, ENVY24_MT_AC97CMD, 1);
679                 if (data & ENVY24_MT_AC97CMD_RDY) {
680                         return 0;
681                 }
682         }
683
684         return -1;
685 }
686
687 #if 0
688 static int
689 envy24_rdcd(kobj_t obj, void *devinfo, int regno)
690 {
691         struct sc_info *sc = (struct sc_info *)devinfo;
692         u_int32_t data;
693         int i;
694
695 #if(0)
696         device_printf(sc->dev, "envy24_rdcd(obj, sc, 0x%02x)\n", regno);
697 #endif
698         envy24_wrmt(sc, ENVY24_MT_AC97IDX, (u_int32_t)regno, 1);
699         envy24_wrmt(sc, ENVY24_MT_AC97CMD, ENVY24_MT_AC97CMD_RD, 1);
700         for (i = 0; i < ENVY24_TIMEOUT; i++) {
701                 data = envy24_rdmt(sc, ENVY24_MT_AC97CMD, 1);
702                 if ((data & ENVY24_MT_AC97CMD_RD) == 0)
703                         break;
704         }
705         data = envy24_rdmt(sc, ENVY24_MT_AC97DLO, 2);
706
707 #if(0)
708         device_printf(sc->dev, "envy24_rdcd(): return 0x%x\n", data);
709 #endif
710         return (int)data;
711 }
712
713 static int
714 envy24_wrcd(kobj_t obj, void *devinfo, int regno, u_int16_t data)
715 {
716         struct sc_info *sc = (struct sc_info *)devinfo;
717         u_int32_t cmd;
718         int i;
719
720 #if(0)
721         device_printf(sc->dev, "envy24_wrcd(obj, sc, 0x%02x, 0x%04x)\n", regno, data);
722 #endif
723         envy24_wrmt(sc, ENVY24_MT_AC97IDX, (u_int32_t)regno, 1);
724         envy24_wrmt(sc, ENVY24_MT_AC97DLO, (u_int32_t)data, 2);
725         envy24_wrmt(sc, ENVY24_MT_AC97CMD, ENVY24_MT_AC97CMD_WR, 1);
726         for (i = 0; i < ENVY24_TIMEOUT; i++) {
727                 cmd = envy24_rdmt(sc, ENVY24_MT_AC97CMD, 1);
728                 if ((cmd & ENVY24_MT_AC97CMD_WR) == 0)
729                         break;
730         }
731
732         return 0;
733 }
734
735 static kobj_method_t envy24_ac97_methods[] = {
736         KOBJMETHOD(ac97_read,   envy24_rdcd),
737         KOBJMETHOD(ac97_write,  envy24_wrcd),
738         KOBJMETHOD_END
739 };
740 AC97_DECLARE(envy24_ac97);
741 #endif
742
743 /* -------------------------------------------------------------------- */
744
745 /* GPIO access routines */
746
747 static u_int32_t
748 envy24_gpiord(struct sc_info *sc)
749 {
750         return envy24_rdci(sc, ENVY24_CCI_GPIODAT);
751 }
752
753 static void
754 envy24_gpiowr(struct sc_info *sc, u_int32_t data)
755 {
756 #if(0)
757         device_printf(sc->dev, "envy24_gpiowr(sc, 0x%02x)\n", data & 0xff);
758         return;
759 #endif
760         envy24_wrci(sc, ENVY24_CCI_GPIODAT, data);
761         return;
762 }
763
764 #if 0
765 static u_int32_t
766 envy24_gpiogetmask(struct sc_info *sc)
767 {
768         return envy24_rdci(sc, ENVY24_CCI_GPIOMASK);
769 }
770 #endif
771
772 static void
773 envy24_gpiosetmask(struct sc_info *sc, u_int32_t mask)
774 {
775         envy24_wrci(sc, ENVY24_CCI_GPIOMASK, mask);
776         return;
777 }
778
779 #if 0
780 static u_int32_t
781 envy24_gpiogetdir(struct sc_info *sc)
782 {
783         return envy24_rdci(sc, ENVY24_CCI_GPIOCTL);
784 }
785 #endif
786
787 static void
788 envy24_gpiosetdir(struct sc_info *sc, u_int32_t dir)
789 {
790         envy24_wrci(sc, ENVY24_CCI_GPIOCTL, dir);
791         return;
792 }
793
794 /* -------------------------------------------------------------------- */
795
796 /* Envy24 I2C through GPIO bit-banging */
797
798 struct envy24_delta_ak4524_codec {
799         struct spicds_info *info;
800         struct sc_info *parent;
801         int dir;
802         int num;
803         int cs, cclk, cdti;
804 };
805
806 static void
807 envy24_gpio_i2c_ctl(void *codec, unsigned int scl, unsigned int sda)
808 {
809         u_int32_t data = 0;
810         struct envy24_delta_ak4524_codec *ptr = codec;
811 #if(0)
812         device_printf(ptr->parent->dev, "--> %d, %d\n", scl, sda);
813 #endif
814         data = envy24_gpiord(ptr->parent);
815         data &= ~(SDA_GPIO | SCL_GPIO);
816         if (scl) data += SCL_GPIO;
817         if (sda) data += SDA_GPIO;
818         envy24_gpiowr(ptr->parent, data);
819         return;
820 }
821
822 static void
823 i2c_wrbit(void *codec, void (*ctrl)(void*, unsigned int, unsigned int), int bit)
824 {
825         struct envy24_delta_ak4524_codec *ptr = codec;
826         unsigned int sda;
827
828         if (bit)
829                 sda = 1;
830         else
831                 sda = 0;
832
833         ctrl(ptr, 0, sda);
834         DELAY(I2C_DELAY);
835         ctrl(ptr, 1, sda);
836         DELAY(I2C_DELAY);
837         ctrl(ptr, 0, sda);
838         DELAY(I2C_DELAY);
839 }
840
841 static void
842 i2c_start(void *codec, void (*ctrl)(void*, unsigned int, unsigned int))
843 {
844         struct envy24_delta_ak4524_codec *ptr = codec;
845
846         ctrl(ptr, 1, 1);
847         DELAY(I2C_DELAY);
848         ctrl(ptr, 1, 0);
849         DELAY(I2C_DELAY);
850         ctrl(ptr, 0, 0);
851         DELAY(I2C_DELAY);
852 }
853
854 static void
855 i2c_stop(void *codec, void (*ctrl)(void*, unsigned int, unsigned int))
856 {
857         struct envy24_delta_ak4524_codec *ptr = codec;
858
859         ctrl(ptr, 0, 0);
860         DELAY(I2C_DELAY);
861         ctrl(ptr, 1, 0);
862         DELAY(I2C_DELAY);
863         ctrl(ptr, 1, 1);
864         DELAY(I2C_DELAY);
865 }
866
867 static void
868 i2c_ack(void *codec, void (*ctrl)(void*, unsigned int, unsigned int))
869 {
870         struct envy24_delta_ak4524_codec *ptr = codec;
871
872         ctrl(ptr, 0, 1);
873         DELAY(I2C_DELAY);
874         ctrl(ptr, 1, 1);
875         DELAY(I2C_DELAY);
876         /* dummy, need routine to change gpio direction */
877         ctrl(ptr, 0, 1);
878         DELAY(I2C_DELAY);
879 }
880
881 static void
882 i2c_wr(void *codec,  void (*ctrl)(void*, unsigned int, unsigned int), u_int32_t dev, int reg, u_int8_t val)
883 {
884         struct envy24_delta_ak4524_codec *ptr = codec;
885         int mask;
886
887         i2c_start(ptr, ctrl);
888
889         for (mask = 0x80; mask != 0; mask >>= 1)
890                 i2c_wrbit(ptr, ctrl, dev & mask);
891         i2c_ack(ptr, ctrl);
892
893         if (reg != 0xff) {
894         for (mask = 0x80; mask != 0; mask >>= 1)
895                 i2c_wrbit(ptr, ctrl, reg & mask);
896         i2c_ack(ptr, ctrl);
897         }
898
899         for (mask = 0x80; mask != 0; mask >>= 1)
900                 i2c_wrbit(ptr, ctrl, val & mask);
901         i2c_ack(ptr, ctrl);
902
903         i2c_stop(ptr, ctrl);
904 }
905
906 /* -------------------------------------------------------------------- */
907
908 /* M-Audio Delta series AK4524 access interface routine */
909
910 static void
911 envy24_delta_ak4524_ctl(void *codec, unsigned int cs, unsigned int cclk, unsigned int cdti)
912 {
913         u_int32_t data = 0;
914         struct envy24_delta_ak4524_codec *ptr = codec;
915
916 #if(0)
917         device_printf(ptr->parent->dev, "--> %d, %d, %d\n", cs, cclk, cdti);
918 #endif
919         data = envy24_gpiord(ptr->parent);
920         data &= ~(ptr->cs | ptr->cclk | ptr->cdti);
921         if (cs) data += ptr->cs;
922         if (cclk) data += ptr->cclk;
923         if (cdti) data += ptr->cdti;
924         envy24_gpiowr(ptr->parent, data);
925         return;
926 }
927
928 static void *
929 envy24_delta_ak4524_create(device_t dev, void *info, int dir, int num)
930 {
931         struct sc_info *sc = info;
932         struct envy24_delta_ak4524_codec *buff = NULL;
933
934 #if(0)
935         device_printf(sc->dev, "envy24_delta_ak4524_create(dev, sc, %d, %d)\n", dir, num);
936 #endif
937         
938         buff = kmalloc(sizeof(*buff), M_ENVY24, M_WAITOK | M_ZERO);
939         if (buff == NULL)
940                 return NULL;
941
942         if (dir == PCMDIR_REC && sc->adc[num] != NULL)
943                 buff->info = ((struct envy24_delta_ak4524_codec *)sc->adc[num])->info;
944         else if (dir == PCMDIR_PLAY && sc->dac[num] != NULL)
945                 buff->info = ((struct envy24_delta_ak4524_codec *)sc->dac[num])->info;
946         else
947                 buff->info = spicds_create(dev, buff, num, envy24_delta_ak4524_ctl);
948         if (buff->info == NULL) {
949                 kfree(buff, M_ENVY24);
950                 return NULL;
951         }
952
953         buff->parent = sc;
954         buff->dir = dir;
955         buff->num = num;
956
957         return (void *)buff;
958 }
959
960 static void
961 envy24_delta_ak4524_destroy(void *codec)
962 {
963         struct envy24_delta_ak4524_codec *ptr = codec;
964         if (ptr == NULL)
965                 return;
966 #if(0)
967         device_printf(ptr->parent->dev, "envy24_delta_ak4524_destroy()\n");
968 #endif
969
970         if (ptr->dir == PCMDIR_PLAY) {
971                 if (ptr->parent->dac[ptr->num] != NULL)
972                         spicds_destroy(ptr->info);
973         }
974         else {
975                 if (ptr->parent->adc[ptr->num] != NULL)
976                         spicds_destroy(ptr->info);
977         }
978
979         kfree(codec, M_ENVY24);
980 }
981
982 static void
983 envy24_delta_ak4524_init(void *codec)
984 {
985 #if 0
986         u_int32_t gpiomask, gpiodir;
987 #endif
988         struct envy24_delta_ak4524_codec *ptr = codec;
989         if (ptr == NULL)
990                 return;
991 #if(0)
992         device_printf(ptr->parent->dev, "envy24_delta_ak4524_init()\n");
993 #endif
994
995         /*
996         gpiomask = envy24_gpiogetmask(ptr->parent);
997         gpiomask &= ~(ENVY24_GPIO_AK4524_CDTI | ENVY24_GPIO_AK4524_CCLK | ENVY24_GPIO_AK4524_CS0 | ENVY24_GPIO_AK4524_CS1);
998         envy24_gpiosetmask(ptr->parent, gpiomask);
999         gpiodir = envy24_gpiogetdir(ptr->parent);
1000         gpiodir |= ENVY24_GPIO_AK4524_CDTI | ENVY24_GPIO_AK4524_CCLK | ENVY24_GPIO_AK4524_CS0 | ENVY24_GPIO_AK4524_CS1;
1001         envy24_gpiosetdir(ptr->parent, gpiodir);
1002         */
1003         ptr->cs = ptr->parent->cfg->cs;
1004 #if 0
1005         envy24_gpiosetmask(ptr->parent, ENVY24_GPIO_CS8414_STATUS);
1006         envy24_gpiosetdir(ptr->parent, ~ENVY24_GPIO_CS8414_STATUS);
1007         if (ptr->num == 0)
1008                 ptr->cs = ENVY24_GPIO_AK4524_CS0;
1009         else
1010                 ptr->cs = ENVY24_GPIO_AK4524_CS1;
1011         ptr->cclk = ENVY24_GPIO_AK4524_CCLK;
1012 #endif
1013         ptr->cclk = ptr->parent->cfg->cclk;
1014         ptr->cdti = ptr->parent->cfg->cdti;
1015         spicds_settype(ptr->info,  ptr->parent->cfg->type);
1016         spicds_setcif(ptr->info, ptr->parent->cfg->cif);
1017         spicds_setformat(ptr->info,
1018             AK452X_FORMAT_I2S | AK452X_FORMAT_256FSN | AK452X_FORMAT_1X);
1019         spicds_setdvc(ptr->info, AK452X_DVC_DEMOFF);
1020         /* for the time being, init only first codec */
1021         if (ptr->num == 0)
1022                 spicds_init(ptr->info);
1023
1024         /* 6fire rear input init test, set ptr->num to 1 for test */
1025         if (ptr->parent->cfg->subvendor == 0x153b && \
1026                 ptr->parent->cfg->subdevice == 0x1138 && ptr->num == 100) {
1027                 ptr->cs = 0x02;  
1028                 spicds_init(ptr->info);
1029                 device_printf(ptr->parent->dev, "6fire rear input init\n");
1030                 i2c_wr(ptr, envy24_gpio_i2c_ctl, \
1031                         PCA9554_I2CDEV, PCA9554_DIR, 0x80);
1032                 i2c_wr(ptr, envy24_gpio_i2c_ctl, \
1033                         PCA9554_I2CDEV, PCA9554_OUT, 0x02);
1034         }
1035 }
1036
1037 static void
1038 envy24_delta_ak4524_reinit(void *codec)
1039 {
1040         struct envy24_delta_ak4524_codec *ptr = codec;
1041         if (ptr == NULL)
1042                 return;
1043 #if(0)
1044         device_printf(ptr->parent->dev, "envy24_delta_ak4524_reinit()\n");
1045 #endif
1046
1047         spicds_reinit(ptr->info);
1048 }
1049
1050 static void
1051 envy24_delta_ak4524_setvolume(void *codec, int dir, unsigned int left, unsigned int right)
1052 {
1053         struct envy24_delta_ak4524_codec *ptr = codec;
1054         if (ptr == NULL)
1055                 return;
1056 #if(0)
1057         device_printf(ptr->parent->dev, "envy24_delta_ak4524_set()\n");
1058 #endif
1059
1060         spicds_set(ptr->info, dir, left, right);
1061 }
1062
1063 /*
1064   There is no need for AK452[48] codec to set sample rate
1065   static void
1066   envy24_delta_ak4524_setrate(struct envy24_delta_ak4524_codec *codec, int which, int rate)
1067   {
1068   }
1069 */
1070
1071 /* -------------------------------------------------------------------- */
1072
1073 /* hardware access routeines */
1074
1075 static struct {
1076         u_int32_t speed;
1077         u_int32_t code;
1078 } envy24_speedtab[] = {
1079         {48000, ENVY24_MT_RATE_48000},
1080         {24000, ENVY24_MT_RATE_24000},
1081         {12000, ENVY24_MT_RATE_12000},
1082         {9600, ENVY24_MT_RATE_9600},
1083         {32000, ENVY24_MT_RATE_32000},
1084         {16000, ENVY24_MT_RATE_16000},
1085         {8000, ENVY24_MT_RATE_8000},
1086         {96000, ENVY24_MT_RATE_96000},
1087         {64000, ENVY24_MT_RATE_64000},
1088         {44100, ENVY24_MT_RATE_44100},
1089         {22050, ENVY24_MT_RATE_22050},
1090         {11025, ENVY24_MT_RATE_11025},
1091         {88200, ENVY24_MT_RATE_88200},
1092         {0, 0x10}
1093 };
1094
1095 static u_int32_t
1096 envy24_setspeed(struct sc_info *sc, u_int32_t speed) {
1097         u_int32_t code;
1098         int i = 0;
1099
1100 #if(0)
1101         device_printf(sc->dev, "envy24_setspeed(sc, %d)\n", speed);
1102 #endif
1103         if (speed == 0) {
1104                 code = ENVY24_MT_RATE_SPDIF; /* external master clock */
1105                 envy24_slavecd(sc);
1106         }
1107         else {
1108                 for (i = 0; envy24_speedtab[i].speed != 0; i++) {
1109                         if (envy24_speedtab[i].speed == speed)
1110                                 break;
1111                 }
1112                 code = envy24_speedtab[i].code;
1113         }
1114 #if(0)
1115         device_printf(sc->dev, "envy24_setspeed(): speed %d/code 0x%04x\n", envy24_speedtab[i].speed, code);
1116 #endif
1117         if (code < 0x10) {
1118                 envy24_wrmt(sc, ENVY24_MT_RATE, code, 1);
1119                 code = envy24_rdmt(sc, ENVY24_MT_RATE, 1);
1120                 code &= ENVY24_MT_RATE_MASK;
1121                 for (i = 0; envy24_speedtab[i].code < 0x10; i++) {
1122                         if (envy24_speedtab[i].code == code)
1123                                 break;
1124                 }
1125                 speed = envy24_speedtab[i].speed;
1126         }
1127         else
1128                 speed = 0;
1129
1130 #if(0)
1131         device_printf(sc->dev, "envy24_setspeed(): return %d\n", speed);
1132 #endif
1133         return speed;
1134 }
1135
1136 static void
1137 envy24_setvolume(struct sc_info *sc, unsigned ch)
1138 {
1139 #if(0)
1140         device_printf(sc->dev, "envy24_setvolume(sc, %d)\n", ch);
1141 #endif
1142 if (sc->cfg->subvendor==0x153b  && sc->cfg->subdevice==0x1138 ) {
1143         envy24_wrmt(sc, ENVY24_MT_VOLIDX, 16, 1);
1144         envy24_wrmt(sc, ENVY24_MT_VOLUME, 0x7f7f, 2);
1145         envy24_wrmt(sc, ENVY24_MT_VOLIDX, 17, 1);
1146         envy24_wrmt(sc, ENVY24_MT_VOLUME, 0x7f7f, 2);
1147         }
1148
1149         envy24_wrmt(sc, ENVY24_MT_VOLIDX, ch * 2, 1);
1150         envy24_wrmt(sc, ENVY24_MT_VOLUME, 0x7f00 | sc->left[ch], 2);
1151         envy24_wrmt(sc, ENVY24_MT_VOLIDX, ch * 2 + 1, 1);
1152         envy24_wrmt(sc, ENVY24_MT_VOLUME, (sc->right[ch] << 8) | 0x7f, 2);
1153 }
1154
1155 static void
1156 envy24_mutevolume(struct sc_info *sc, unsigned ch)
1157 {
1158         u_int32_t vol;
1159
1160 #if(0)
1161         device_printf(sc->dev, "envy24_mutevolume(sc, %d)\n", ch);
1162 #endif
1163         vol = ENVY24_VOL_MUTE << 8 | ENVY24_VOL_MUTE;
1164         envy24_wrmt(sc, ENVY24_MT_VOLIDX, ch * 2, 1);
1165         envy24_wrmt(sc, ENVY24_MT_VOLUME, vol, 2);
1166         envy24_wrmt(sc, ENVY24_MT_VOLIDX, ch * 2 + 1, 1);
1167         envy24_wrmt(sc, ENVY24_MT_VOLUME, vol, 2);
1168 }
1169
1170 static u_int32_t
1171 envy24_gethwptr(struct sc_info *sc, int dir)
1172 {
1173         int unit, regno;
1174         u_int32_t ptr, rtn;
1175
1176 #if(0)
1177         device_printf(sc->dev, "envy24_gethwptr(sc, %d)\n", dir);
1178 #endif
1179         if (dir == PCMDIR_PLAY) {
1180                 rtn = sc->psize / 4;
1181                 unit = ENVY24_PLAY_BUFUNIT / 4;
1182                 regno = ENVY24_MT_PCNT;
1183         }
1184         else {
1185                 rtn = sc->rsize / 4;
1186                 unit = ENVY24_REC_BUFUNIT / 4;
1187                 regno = ENVY24_MT_RCNT;
1188         }
1189
1190         ptr = envy24_rdmt(sc, regno, 2);
1191         rtn -= (ptr + 1);
1192         rtn /= unit;
1193
1194 #if(0)
1195         device_printf(sc->dev, "envy24_gethwptr(): return %d\n", rtn);
1196 #endif
1197         return rtn;
1198 }
1199
1200 static void
1201 envy24_updintr(struct sc_info *sc, int dir)
1202 {
1203         int regptr, regintr;
1204         u_int32_t mask, intr;
1205         u_int32_t ptr, size, cnt;
1206         u_int16_t blk;
1207
1208 #if(0)
1209         device_printf(sc->dev, "envy24_updintr(sc, %d)\n", dir);
1210 #endif
1211         if (dir == PCMDIR_PLAY) {
1212                 blk = sc->blk[0];
1213                 size = sc->psize / 4;
1214                 regptr = ENVY24_MT_PCNT;
1215                 regintr = ENVY24_MT_PTERM;
1216                 mask = ~ENVY24_MT_INT_PMASK;
1217         }
1218         else {
1219                 blk = sc->blk[1];
1220                 size = sc->rsize / 4;
1221                 regptr = ENVY24_MT_RCNT;
1222                 regintr = ENVY24_MT_RTERM;
1223                 mask = ~ENVY24_MT_INT_RMASK;
1224         }
1225
1226         ptr = size - envy24_rdmt(sc, regptr, 2) - 1;
1227         /*
1228         cnt = blk - ptr % blk - 1;
1229         if (cnt == 0)
1230                 cnt = blk - 1;
1231         */
1232         cnt = blk - 1;
1233 #if(0)
1234         device_printf(sc->dev, "envy24_updintr():ptr = %d, blk = %d, cnt = %d\n", ptr, blk, cnt);
1235 #endif
1236         envy24_wrmt(sc, regintr, cnt, 2);
1237         intr = envy24_rdmt(sc, ENVY24_MT_INT, 1);
1238 #if(0)
1239         device_printf(sc->dev, "envy24_updintr():intr = 0x%02x, mask = 0x%02x\n", intr, mask);
1240 #endif
1241         envy24_wrmt(sc, ENVY24_MT_INT, intr & mask, 1);
1242 #if(0)
1243         device_printf(sc->dev, "envy24_updintr():INT-->0x%02x\n",
1244                       envy24_rdmt(sc, ENVY24_MT_INT, 1));
1245 #endif
1246
1247         return;
1248 }
1249
1250 #if 0
1251 static void
1252 envy24_maskintr(struct sc_info *sc, int dir)
1253 {
1254         u_int32_t mask, intr;
1255
1256 #if(0)
1257         device_printf(sc->dev, "envy24_maskintr(sc, %d)\n", dir);
1258 #endif
1259         if (dir == PCMDIR_PLAY)
1260                 mask = ENVY24_MT_INT_PMASK;
1261         else
1262                 mask = ENVY24_MT_INT_RMASK;
1263         intr = envy24_rdmt(sc, ENVY24_MT_INT, 1);
1264         envy24_wrmt(sc, ENVY24_MT_INT, intr | mask, 1);
1265
1266         return;
1267 }
1268 #endif
1269
1270 static int
1271 envy24_checkintr(struct sc_info *sc, int dir)
1272 {
1273         u_int32_t mask, stat, intr, rtn;
1274
1275 #if(0)
1276         device_printf(sc->dev, "envy24_checkintr(sc, %d)\n", dir);
1277 #endif
1278         intr = envy24_rdmt(sc, ENVY24_MT_INT, 1);
1279         if (dir == PCMDIR_PLAY) {
1280                 if ((rtn = intr & ENVY24_MT_INT_PSTAT) != 0) {
1281                         mask = ~ENVY24_MT_INT_RSTAT;
1282                         stat = ENVY24_MT_INT_PSTAT | ENVY24_MT_INT_PMASK;
1283                         envy24_wrmt(sc, ENVY24_MT_INT, (intr & mask) | stat, 1);
1284                 }
1285         }
1286         else {
1287                 if ((rtn = intr & ENVY24_MT_INT_RSTAT) != 0) {
1288                         mask = ~ENVY24_MT_INT_PSTAT;
1289                         stat = ENVY24_MT_INT_RSTAT | ENVY24_MT_INT_RMASK;
1290                         envy24_wrmt(sc, ENVY24_MT_INT, (intr & mask) | stat, 1);
1291                 }
1292         }
1293
1294         return rtn;
1295 }
1296
1297 static void
1298 envy24_start(struct sc_info *sc, int dir)
1299 {
1300         u_int32_t stat, sw;
1301
1302 #if(0)
1303         device_printf(sc->dev, "envy24_start(sc, %d)\n", dir);
1304 #endif
1305         if (dir == PCMDIR_PLAY)
1306                 sw = ENVY24_MT_PCTL_PSTART;
1307         else
1308                 sw = ENVY24_MT_PCTL_RSTART;
1309
1310         stat = envy24_rdmt(sc, ENVY24_MT_PCTL, 1);
1311         envy24_wrmt(sc, ENVY24_MT_PCTL, stat | sw, 1);
1312 #if(0)
1313         DELAY(100);
1314         device_printf(sc->dev, "PADDR:0x%08x\n", envy24_rdmt(sc, ENVY24_MT_PADDR, 4));
1315         device_printf(sc->dev, "PCNT:%ld\n", envy24_rdmt(sc, ENVY24_MT_PCNT, 2));
1316 #endif
1317
1318         return;
1319 }
1320
1321 static void
1322 envy24_stop(struct sc_info *sc, int dir)
1323 {
1324         u_int32_t stat, sw;
1325
1326 #if(0)
1327         device_printf(sc->dev, "envy24_stop(sc, %d)\n", dir);
1328 #endif
1329         if (dir == PCMDIR_PLAY)
1330                 sw = ~ENVY24_MT_PCTL_PSTART;
1331         else
1332                 sw = ~ENVY24_MT_PCTL_RSTART;
1333
1334         stat = envy24_rdmt(sc, ENVY24_MT_PCTL, 1);
1335         envy24_wrmt(sc, ENVY24_MT_PCTL, stat & sw, 1);
1336
1337         return;
1338 }
1339
1340 static int
1341 envy24_route(struct sc_info *sc, int dac, int class, int adc, int rev)
1342 {
1343         u_int32_t reg, mask;
1344         u_int32_t left, right;
1345
1346 #if(0)
1347         device_printf(sc->dev, "envy24_route(sc, %d, %d, %d, %d)\n",
1348             dac, class, adc, rev);
1349 #endif
1350         /* parameter pattern check */
1351         if (dac < 0 || ENVY24_ROUTE_DAC_SPDIF < dac)
1352                 return -1;
1353         if (class == ENVY24_ROUTE_CLASS_MIX &&
1354             (dac != ENVY24_ROUTE_DAC_1 && dac != ENVY24_ROUTE_DAC_SPDIF))
1355                 return -1;
1356         if (rev) {
1357                 left = ENVY24_ROUTE_RIGHT;
1358                 right = ENVY24_ROUTE_LEFT;
1359         }
1360         else {
1361                 left = ENVY24_ROUTE_LEFT;
1362                 right = ENVY24_ROUTE_RIGHT;
1363         }
1364
1365         if (dac == ENVY24_ROUTE_DAC_SPDIF) {
1366                 reg = class | class << 2 |
1367                         ((adc << 1 | left) | left << 3) << 8 |
1368                         ((adc << 1 | right) | right << 3) << 12;
1369 #if(0)
1370                 device_printf(sc->dev, "envy24_route(): MT_SPDOUT-->0x%04x\n", reg);
1371 #endif
1372                 envy24_wrmt(sc, ENVY24_MT_SPDOUT, reg, 2);
1373         }
1374         else {
1375                 mask = ~(0x0303 << dac * 2);
1376                 reg = envy24_rdmt(sc, ENVY24_MT_PSDOUT, 2);
1377                 reg = (reg & mask) | ((class | class << 8) << dac * 2);
1378 #if(0)
1379                 device_printf(sc->dev, "envy24_route(): MT_PSDOUT-->0x%04x\n", reg);
1380 #endif
1381                 envy24_wrmt(sc, ENVY24_MT_PSDOUT, reg, 2);
1382                 mask = ~(0xff << dac * 8);
1383                 reg = envy24_rdmt(sc, ENVY24_MT_RECORD, 4);
1384                 reg = (reg & mask) |
1385                         (((adc << 1 | left) | left << 3) |
1386                          ((adc << 1 | right) | right << 3) << 4) << dac * 8;
1387 #if(0)
1388                 device_printf(sc->dev, "envy24_route(): MT_RECORD-->0x%08x\n", reg);
1389 #endif
1390                 envy24_wrmt(sc, ENVY24_MT_RECORD, reg, 4);
1391
1392                 /* 6fire rear input init test */
1393                 envy24_wrmt(sc, ENVY24_MT_RECORD, 0x00, 4);
1394         }
1395
1396         return 0;
1397 }
1398
1399 /* -------------------------------------------------------------------- */
1400
1401 /* buffer copy routines */
1402 static void
1403 envy24_p32sl(struct sc_chinfo *ch)
1404 {
1405         int length;
1406         sample32_t *dmabuf;
1407         u_int32_t *data;
1408         int src, dst, ssize, dsize, slot;
1409         int i;
1410
1411         length = sndbuf_getready(ch->buffer) / 8;
1412         dmabuf = ch->parent->pbuf;
1413         data = (u_int32_t *)ch->data;
1414         src = sndbuf_getreadyptr(ch->buffer) / 4;
1415         dst = src / 2 + ch->offset;
1416         ssize = ch->size / 4;
1417         dsize = ch->size / 8;
1418         slot = ch->num * 2;
1419
1420         for (i = 0; i < length; i++) {
1421                 dmabuf[dst * ENVY24_PLAY_CHNUM + slot].buffer = data[src];
1422                 dmabuf[dst * ENVY24_PLAY_CHNUM + slot + 1].buffer = data[src + 1];
1423                 dst++;
1424                 dst %= dsize;
1425                 src += 2;
1426                 src %= ssize;
1427         }
1428         
1429         return;
1430 }
1431
1432 static void
1433 envy24_p16sl(struct sc_chinfo *ch)
1434 {
1435         int length;
1436         sample32_t *dmabuf;
1437         u_int16_t *data;
1438         int src, dst, ssize, dsize, slot;
1439         int i;
1440
1441 #if(0)
1442         device_printf(ch->parent->dev, "envy24_p16sl()\n");
1443 #endif
1444         length = sndbuf_getready(ch->buffer) / 4;
1445         dmabuf = ch->parent->pbuf;
1446         data = (u_int16_t *)ch->data;
1447         src = sndbuf_getreadyptr(ch->buffer) / 2;
1448         dst = src / 2 + ch->offset;
1449         ssize = ch->size / 2;
1450         dsize = ch->size / 4;
1451         slot = ch->num * 2;
1452 #if(0)
1453         device_printf(ch->parent->dev, "envy24_p16sl():%lu-->%lu(%lu)\n", src, dst, length);
1454 #endif
1455         
1456         for (i = 0; i < length; i++) {
1457                 dmabuf[dst * ENVY24_PLAY_CHNUM + slot].buffer = (u_int32_t)data[src] << 16;
1458                 dmabuf[dst * ENVY24_PLAY_CHNUM + slot + 1].buffer = (u_int32_t)data[src + 1] << 16;
1459 #if(0)
1460                 if (i < 16) {
1461                         printf("%08x", dmabuf[dst * ENVY24_PLAY_CHNUM + slot]);
1462                         printf("%08x", dmabuf[dst * ENVY24_PLAY_CHNUM + slot + 1]);
1463                 }
1464 #endif
1465                 dst++;
1466                 dst %= dsize;
1467                 src += 2;
1468                 src %= ssize;
1469         }
1470 #if(0)
1471         printf("\n");
1472 #endif
1473         
1474         return;
1475 }
1476
1477 static void
1478 envy24_p8u(struct sc_chinfo *ch)
1479 {
1480         int length;
1481         sample32_t *dmabuf;
1482         u_int8_t *data;
1483         int src, dst, ssize, dsize, slot;
1484         int i;
1485
1486         length = sndbuf_getready(ch->buffer) / 2;
1487         dmabuf = ch->parent->pbuf;
1488         data = (u_int8_t *)ch->data;
1489         src = sndbuf_getreadyptr(ch->buffer);
1490         dst = src / 2 + ch->offset;
1491         ssize = ch->size;
1492         dsize = ch->size / 4;
1493         slot = ch->num * 2;
1494         
1495         for (i = 0; i < length; i++) {
1496                 dmabuf[dst * ENVY24_PLAY_CHNUM + slot].buffer = ((u_int32_t)data[src] ^ 0x80) << 24;
1497                 dmabuf[dst * ENVY24_PLAY_CHNUM + slot + 1].buffer = ((u_int32_t)data[src + 1] ^ 0x80) << 24;
1498                 dst++;
1499                 dst %= dsize;
1500                 src += 2;
1501                 src %= ssize;
1502         }
1503         
1504         return;
1505 }
1506
1507 static void
1508 envy24_r32sl(struct sc_chinfo *ch)
1509 {
1510         int length;
1511         sample32_t *dmabuf;
1512         u_int32_t *data;
1513         int src, dst, ssize, dsize, slot;
1514         int i;
1515
1516         length = sndbuf_getfree(ch->buffer) / 8;
1517         dmabuf = ch->parent->rbuf;
1518         data = (u_int32_t *)ch->data;
1519         dst = sndbuf_getfreeptr(ch->buffer) / 4;
1520         src = dst / 2 + ch->offset;
1521         dsize = ch->size / 4;
1522         ssize = ch->size / 8;
1523         slot = (ch->num - ENVY24_CHAN_REC_ADC1) * 2;
1524
1525         for (i = 0; i < length; i++) {
1526                 data[dst] = dmabuf[src * ENVY24_REC_CHNUM + slot].buffer;
1527                 data[dst + 1] = dmabuf[src * ENVY24_REC_CHNUM + slot + 1].buffer;
1528                 dst += 2;
1529                 dst %= dsize;
1530                 src++;
1531                 src %= ssize;
1532         }
1533         
1534         return;
1535 }
1536
1537 static void
1538 envy24_r16sl(struct sc_chinfo *ch)
1539 {
1540         int length;
1541         sample32_t *dmabuf;
1542         u_int16_t *data;
1543         int src, dst, ssize, dsize, slot;
1544         int i;
1545
1546         length = sndbuf_getfree(ch->buffer) / 4;
1547         dmabuf = ch->parent->rbuf;
1548         data = (u_int16_t *)ch->data;
1549         dst = sndbuf_getfreeptr(ch->buffer) / 2;
1550         src = dst / 2 + ch->offset;
1551         dsize = ch->size / 2;
1552         ssize = ch->size / 8;
1553         slot = (ch->num - ENVY24_CHAN_REC_ADC1) * 2;
1554
1555         for (i = 0; i < length; i++) {
1556                 data[dst] = dmabuf[src * ENVY24_REC_CHNUM + slot].buffer;
1557                 data[dst + 1] = dmabuf[src * ENVY24_REC_CHNUM + slot + 1].buffer;
1558                 dst += 2;
1559                 dst %= dsize;
1560                 src++;
1561                 src %= ssize;
1562         }
1563         
1564         return;
1565 }
1566
1567 /* -------------------------------------------------------------------- */
1568
1569 /* channel interface */
1570 static void *
1571 envy24chan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir)
1572 {
1573         struct sc_info  *sc = (struct sc_info *)devinfo;
1574         struct sc_chinfo *ch;
1575         unsigned num;
1576
1577 #if(0)
1578         device_printf(sc->dev, "envy24chan_init(obj, devinfo, b, c, %d)\n", dir);
1579 #endif
1580         snd_mtxlock(sc->lock);
1581         if ((sc->chnum > ENVY24_CHAN_PLAY_SPDIF && dir != PCMDIR_REC) ||
1582             (sc->chnum < ENVY24_CHAN_REC_ADC1 && dir != PCMDIR_PLAY)) {
1583                 snd_mtxunlock(sc->lock);
1584                 return NULL;
1585         }
1586         num = sc->chnum;
1587
1588         ch = &sc->chan[num];
1589         ch->size = 8 * ENVY24_SAMPLE_NUM;
1590         ch->data = kmalloc(ch->size, M_ENVY24, M_WAITOK | M_ZERO);
1591         if (ch->data == NULL) {
1592                 ch->size = 0;
1593                 ch = NULL;
1594         }
1595         else {
1596                 ch->buffer = b;
1597                 ch->channel = c;
1598                 ch->parent = sc;
1599                 ch->dir = dir;
1600                 /* set channel map */
1601                 ch->num = envy24_chanmap[num];
1602                 snd_mtxunlock(sc->lock);
1603                 sndbuf_setup(ch->buffer, ch->data, ch->size);
1604                 snd_mtxlock(sc->lock);
1605                 /* these 2 values are dummy */
1606                 ch->unit = 4;
1607                 ch->blk = 10240;
1608         }
1609         snd_mtxunlock(sc->lock);
1610
1611         return ch;
1612 }
1613
1614 static int
1615 envy24chan_free(kobj_t obj, void *data)
1616 {
1617         struct sc_chinfo *ch = data;
1618         struct sc_info *sc = ch->parent;
1619
1620 #if(0)
1621         device_printf(sc->dev, "envy24chan_free()\n");
1622 #endif
1623         snd_mtxlock(sc->lock);
1624         if (ch->data != NULL) {
1625                 kfree(ch->data, M_ENVY24);
1626                 ch->data = NULL;
1627         }
1628         snd_mtxunlock(sc->lock);
1629
1630         return 0;
1631 }
1632
1633 static int
1634 envy24chan_setformat(kobj_t obj, void *data, u_int32_t format)
1635 {
1636         struct sc_chinfo *ch = data;
1637         struct sc_info *sc = ch->parent;
1638         struct envy24_emldma *emltab;
1639         /* unsigned int bcnt, bsize; */
1640         int i;
1641
1642 #if(0)
1643         device_printf(sc->dev, "envy24chan_setformat(obj, data, 0x%08x)\n", format);
1644 #endif
1645         snd_mtxlock(sc->lock);
1646         /* check and get format related information */
1647         if (ch->dir == PCMDIR_PLAY)
1648                 emltab = envy24_pemltab;
1649         else
1650                 emltab = envy24_remltab;
1651         if (emltab == NULL) {
1652                 snd_mtxunlock(sc->lock);
1653                 return -1;
1654         }
1655         for (i = 0; emltab[i].format != 0; i++)
1656                 if (emltab[i].format == format)
1657                         break;
1658         if (emltab[i].format == 0) {
1659                 snd_mtxunlock(sc->lock);
1660                 return -1;
1661         }
1662
1663         /* set format information */
1664         ch->format = format;
1665         ch->emldma = emltab[i].emldma;
1666         if (ch->unit > emltab[i].unit)
1667                 ch->blk *= ch->unit / emltab[i].unit;
1668         else
1669                 ch->blk /= emltab[i].unit / ch->unit;
1670         ch->unit = emltab[i].unit;
1671
1672         /* set channel buffer information */
1673         ch->size = ch->unit * ENVY24_SAMPLE_NUM;
1674 #if 0
1675         if (ch->dir == PCMDIR_PLAY)
1676                 bsize = ch->blk * 4 / ENVY24_PLAY_BUFUNIT;
1677         else
1678                 bsize = ch->blk * 4 / ENVY24_REC_BUFUNIT;
1679         bsize *= ch->unit;
1680         bcnt = ch->size / bsize;
1681         sndbuf_resize(ch->buffer, bcnt, bsize);
1682 #endif
1683         snd_mtxunlock(sc->lock);
1684
1685 #if(0)
1686         device_printf(sc->dev, "envy24chan_setformat(): return 0x%08x\n", 0);
1687 #endif
1688         return 0;
1689 }
1690
1691 /*
1692   IMPLEMENT NOTICE: In this driver, setspeed function only do setting
1693   of speed information value. And real hardware speed setting is done
1694   at start triggered(see envy24chan_trigger()). So, at this function
1695   is called, any value that ENVY24 can use is able to set. But, at
1696   start triggerd, some other channel is running, and that channel's
1697   speed isn't same with, then trigger function will fail.
1698 */
1699 static u_int32_t
1700 envy24chan_setspeed(kobj_t obj, void *data, u_int32_t speed)
1701 {
1702         struct sc_chinfo *ch = data;
1703         u_int32_t val, prev;
1704         int i;
1705
1706 #if(0)
1707         device_printf(ch->parent->dev, "envy24chan_setspeed(obj, data, %d)\n", speed);
1708 #endif
1709         prev = 0x7fffffff;
1710         for (i = 0; (val = envy24_speed[i]) != 0; i++) {
1711                 if (abs(val - speed) < abs(prev - speed))
1712                         prev = val;
1713                 else
1714                         break;
1715         }
1716         ch->speed = prev;
1717         
1718 #if(0)
1719         device_printf(ch->parent->dev, "envy24chan_setspeed(): return %d\n", ch->speed);
1720 #endif
1721         return ch->speed;
1722 }
1723
1724 static u_int32_t
1725 envy24chan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
1726 {
1727         struct sc_chinfo *ch = data;
1728         /* struct sc_info *sc = ch->parent; */
1729         u_int32_t size, prev;
1730         unsigned int bcnt, bsize;
1731
1732 #if(0)
1733         device_printf(sc->dev, "envy24chan_setblocksize(obj, data, %d)\n", blocksize);
1734 #endif
1735         prev = 0x7fffffff;
1736         /* snd_mtxlock(sc->lock); */
1737         for (size = ch->size / 2; size > 0; size /= 2) {
1738                 if (abs(size - blocksize) < abs(prev - blocksize))
1739                         prev = size;
1740                 else
1741                         break;
1742         }
1743
1744         ch->blk = prev / ch->unit;
1745         if (ch->dir == PCMDIR_PLAY)
1746                 ch->blk *= ENVY24_PLAY_BUFUNIT / 4;
1747         else
1748                 ch->blk *= ENVY24_REC_BUFUNIT / 4;
1749         /* set channel buffer information */
1750         /* ch->size = ch->unit * ENVY24_SAMPLE_NUM; */
1751         if (ch->dir == PCMDIR_PLAY)
1752                 bsize = ch->blk * 4 / ENVY24_PLAY_BUFUNIT;
1753         else
1754                 bsize = ch->blk * 4 / ENVY24_REC_BUFUNIT;
1755         bsize *= ch->unit;
1756         bcnt = ch->size / bsize;
1757         sndbuf_resize(ch->buffer, bcnt, bsize);
1758         /* snd_mtxunlock(sc->lock); */
1759
1760 #if(0)
1761         device_printf(sc->dev, "envy24chan_setblocksize(): return %d\n", prev);
1762 #endif
1763         return prev;
1764 }
1765
1766 /* semantic note: must start at beginning of buffer */
1767 static int
1768 envy24chan_trigger(kobj_t obj, void *data, int go)
1769 {
1770         struct sc_chinfo *ch = data;
1771         struct sc_info *sc = ch->parent;
1772         u_int32_t ptr;
1773         int slot;
1774         int error = 0;
1775 #if 0
1776         int i;
1777
1778         device_printf(sc->dev, "envy24chan_trigger(obj, data, %d)\n", go);
1779 #endif
1780         snd_mtxlock(sc->lock);
1781         if (ch->dir == PCMDIR_PLAY)
1782                 slot = 0;
1783         else
1784                 slot = 1;
1785         switch (go) {
1786         case PCMTRIG_START:
1787 #if(0)
1788                 device_printf(sc->dev, "envy24chan_trigger(): start\n");
1789 #endif
1790                 /* check or set channel speed */
1791                 if (sc->run[0] == 0 && sc->run[1] == 0) {
1792                         sc->speed = envy24_setspeed(sc, ch->speed);
1793                         sc->caps[0].minspeed = sc->caps[0].maxspeed = sc->speed;
1794                         sc->caps[1].minspeed = sc->caps[1].maxspeed = sc->speed;
1795                 }
1796                 else if (ch->speed != 0 && ch->speed != sc->speed) {
1797                         error = -1;
1798                         goto fail;
1799                 }
1800                 if (ch->speed == 0)
1801                         ch->channel->speed = sc->speed;
1802                 /* start or enable channel */
1803                 sc->run[slot]++;
1804                 if (sc->run[slot] == 1) {
1805                         /* first channel */
1806                         ch->offset = 0;
1807                         sc->blk[slot] = ch->blk;
1808                 }
1809                 else {
1810                         ptr = envy24_gethwptr(sc, ch->dir);
1811                         ch->offset = ((ptr / ch->blk + 1) * ch->blk %
1812                             (ch->size / 4)) * 4 / ch->unit;
1813                         if (ch->blk < sc->blk[slot])
1814                                 sc->blk[slot] = ch->blk;
1815                 }
1816                 if (ch->dir == PCMDIR_PLAY) {
1817                         ch->emldma(ch);
1818                         envy24_setvolume(sc, ch->num);
1819                 }
1820                 envy24_updintr(sc, ch->dir);
1821                 if (sc->run[slot] == 1)
1822                         envy24_start(sc, ch->dir);
1823                 ch->run = 1;
1824                 break;
1825         case PCMTRIG_EMLDMAWR:
1826 #if(0)
1827                 device_printf(sc->dev, "envy24chan_trigger(): emldmawr\n");
1828 #endif
1829                 if (ch->run != 1) {
1830                         error = -1;
1831                         goto fail;
1832                 }
1833                 ch->emldma(ch);
1834                 break;
1835         case PCMTRIG_EMLDMARD:
1836 #if(0)
1837                 device_printf(sc->dev, "envy24chan_trigger(): emldmard\n");
1838 #endif
1839                 if (ch->run != 1) {
1840                         error = -1;
1841                         goto fail;
1842                 }
1843                 ch->emldma(ch);
1844                 break;
1845         case PCMTRIG_ABORT:
1846                 if (ch->run) {
1847 #if(0)
1848                 device_printf(sc->dev, "envy24chan_trigger(): abort\n");
1849 #endif
1850                 ch->run = 0;
1851                 sc->run[slot]--;
1852                 if (ch->dir == PCMDIR_PLAY)
1853                         envy24_mutevolume(sc, ch->num);
1854                 if (sc->run[slot] == 0) {
1855                         envy24_stop(sc, ch->dir);
1856                         sc->intr[slot] = 0;
1857                 }
1858 #if 0
1859                 else if (ch->blk == sc->blk[slot]) {
1860                         sc->blk[slot] = ENVY24_SAMPLE_NUM / 2;
1861                         for (i = 0; i < ENVY24_CHAN_NUM; i++) {
1862                                 if (sc->chan[i].dir == ch->dir &&
1863                                     sc->chan[i].run == 1 &&
1864                                     sc->chan[i].blk < sc->blk[slot])
1865                                         sc->blk[slot] = sc->chan[i].blk;
1866                         }
1867                         if (ch->blk != sc->blk[slot])
1868                                 envy24_updintr(sc, ch->dir);
1869                 }
1870 #endif
1871                 }
1872                 break;
1873         }
1874 fail:
1875         snd_mtxunlock(sc->lock);
1876         return (error);
1877 }
1878
1879 static u_int32_t
1880 envy24chan_getptr(kobj_t obj, void *data)
1881 {
1882         struct sc_chinfo *ch = data;
1883         struct sc_info *sc = ch->parent;
1884         u_int32_t ptr, rtn;
1885
1886 #if(0)
1887         device_printf(sc->dev, "envy24chan_getptr()\n");
1888 #endif
1889         snd_mtxlock(sc->lock);
1890         ptr = envy24_gethwptr(sc, ch->dir);
1891         rtn = ptr * ch->unit;
1892         snd_mtxunlock(sc->lock);
1893
1894 #if(0)
1895         device_printf(sc->dev, "envy24chan_getptr(): return %d\n",
1896             rtn);
1897 #endif
1898         return rtn;
1899 }
1900
1901 static struct pcmchan_caps *
1902 envy24chan_getcaps(kobj_t obj, void *data)
1903 {
1904         struct sc_chinfo *ch = data;
1905         struct sc_info *sc = ch->parent;
1906         struct pcmchan_caps *rtn;
1907
1908 #if(0)
1909         device_printf(sc->dev, "envy24chan_getcaps()\n");
1910 #endif
1911         snd_mtxlock(sc->lock);
1912         if (ch->dir == PCMDIR_PLAY) {
1913                 if (sc->run[0] == 0)
1914                         rtn = &envy24_playcaps;
1915                 else
1916                         rtn = &sc->caps[0];
1917         }
1918         else {
1919                 if (sc->run[1] == 0)
1920                         rtn = &envy24_reccaps;
1921                 else
1922                         rtn = &sc->caps[1];
1923         }
1924         snd_mtxunlock(sc->lock);
1925
1926         return rtn;
1927 }
1928
1929 static kobj_method_t envy24chan_methods[] = {
1930         KOBJMETHOD(channel_init,                envy24chan_init),
1931         KOBJMETHOD(channel_free,                envy24chan_free),
1932         KOBJMETHOD(channel_setformat,           envy24chan_setformat),
1933         KOBJMETHOD(channel_setspeed,            envy24chan_setspeed),
1934         KOBJMETHOD(channel_setblocksize,        envy24chan_setblocksize),
1935         KOBJMETHOD(channel_trigger,             envy24chan_trigger),
1936         KOBJMETHOD(channel_getptr,              envy24chan_getptr),
1937         KOBJMETHOD(channel_getcaps,             envy24chan_getcaps),
1938         KOBJMETHOD_END
1939 };
1940 CHANNEL_DECLARE(envy24chan);
1941
1942 /* -------------------------------------------------------------------- */
1943
1944 /* mixer interface */
1945
1946 static int
1947 envy24mixer_init(struct snd_mixer *m)
1948 {
1949         struct sc_info *sc = mix_getdevinfo(m);
1950
1951 #if(0)
1952         device_printf(sc->dev, "envy24mixer_init()\n");
1953 #endif
1954         if (sc == NULL)
1955                 return -1;
1956
1957         /* set volume control rate */
1958         snd_mtxlock(sc->lock);
1959         envy24_wrmt(sc, ENVY24_MT_VOLRATE, 0x30, 1); /* 0x30 is default value */
1960
1961         mix_setdevs(m, ENVY24_MIX_MASK);
1962         mix_setrecdevs(m, ENVY24_MIX_REC_MASK);
1963         snd_mtxunlock(sc->lock);
1964
1965         return 0;
1966 }
1967
1968 static int
1969 envy24mixer_reinit(struct snd_mixer *m)
1970 {
1971         struct sc_info *sc = mix_getdevinfo(m);
1972
1973         if (sc == NULL)
1974                 return -1;
1975 #if(0)
1976         device_printf(sc->dev, "envy24mixer_reinit()\n");
1977 #endif
1978
1979         return 0;
1980 }
1981
1982 static int
1983 envy24mixer_uninit(struct snd_mixer *m)
1984 {
1985         struct sc_info *sc = mix_getdevinfo(m);
1986
1987         if (sc == NULL)
1988                 return -1;
1989 #if(0)
1990         device_printf(sc->dev, "envy24mixer_uninit()\n");
1991 #endif
1992
1993         return 0;
1994 }
1995
1996 static int
1997 envy24mixer_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right)
1998 {
1999         struct sc_info *sc = mix_getdevinfo(m);
2000         int ch = envy24_mixmap[dev];
2001         int hwch;
2002         int i;
2003
2004         if (sc == NULL)
2005                 return -1;
2006         if (dev == 0 && sc->cfg->codec->setvolume == NULL)
2007                 return -1;
2008         if (dev != 0 && ch == -1)
2009                 return -1;
2010         hwch = envy24_chanmap[ch];
2011 #if(0)
2012         device_printf(sc->dev, "envy24mixer_set(m, %d, %d, %d)\n",
2013             dev, left, right);
2014 #endif
2015
2016         snd_mtxlock(sc->lock);
2017         if (dev == 0) {
2018                 for (i = 0; i < sc->dacn; i++) {
2019                         sc->cfg->codec->setvolume(sc->dac[i], PCMDIR_PLAY, left, right);
2020                 }
2021         }
2022         else {
2023                 /* set volume value for hardware */
2024                 if ((sc->left[hwch] = 100 - left) > ENVY24_VOL_MIN)
2025                         sc->left[hwch] = ENVY24_VOL_MUTE;
2026                 if ((sc->right[hwch] = 100 - right) > ENVY24_VOL_MIN)
2027                         sc->right[hwch] = ENVY24_VOL_MUTE;
2028
2029                 /* set volume for record channel and running play channel */
2030                 if (hwch > ENVY24_CHAN_PLAY_SPDIF || sc->chan[ch].run)
2031                         envy24_setvolume(sc, hwch);
2032         }
2033         snd_mtxunlock(sc->lock);
2034
2035         return right << 8 | left;
2036 }
2037
2038 static u_int32_t
2039 envy24mixer_setrecsrc(struct snd_mixer *m, u_int32_t src)
2040 {
2041         struct sc_info *sc = mix_getdevinfo(m);
2042         int ch = envy24_mixmap[src];
2043 #if(0)
2044         device_printf(sc->dev, "envy24mixer_setrecsrc(m, %d)\n", src);
2045 #endif
2046
2047         if (ch > ENVY24_CHAN_PLAY_SPDIF)
2048                 sc->src = ch;
2049         return src;
2050 }
2051
2052 static kobj_method_t envy24mixer_methods[] = {
2053         KOBJMETHOD(mixer_init,          envy24mixer_init),
2054         KOBJMETHOD(mixer_reinit,        envy24mixer_reinit),
2055         KOBJMETHOD(mixer_uninit,        envy24mixer_uninit),
2056         KOBJMETHOD(mixer_set,           envy24mixer_set),
2057         KOBJMETHOD(mixer_setrecsrc,     envy24mixer_setrecsrc),
2058         KOBJMETHOD_END
2059 };
2060 MIXER_DECLARE(envy24mixer);
2061
2062 /* -------------------------------------------------------------------- */
2063
2064 /* The interrupt handler */
2065 static void
2066 envy24_intr(void *p)
2067 {
2068         struct sc_info *sc = (struct sc_info *)p;
2069         struct sc_chinfo *ch;
2070         u_int32_t ptr, dsize, feed;
2071         int i;
2072
2073 #if(0)
2074         device_printf(sc->dev, "envy24_intr()\n");
2075 #endif
2076         snd_mtxlock(sc->lock);
2077         if (envy24_checkintr(sc, PCMDIR_PLAY)) {
2078 #if(0)
2079                 device_printf(sc->dev, "envy24_intr(): play\n");
2080 #endif
2081                 dsize = sc->psize / 4;
2082                 ptr = dsize - envy24_rdmt(sc, ENVY24_MT_PCNT, 2) - 1;
2083 #if(0)
2084                 device_printf(sc->dev, "envy24_intr(): ptr = %d-->", ptr);
2085 #endif
2086                 ptr -= ptr % sc->blk[0];
2087                 feed = (ptr + dsize - sc->intr[0]) % dsize; 
2088 #if(0)
2089                 printf("%d intr = %d feed = %d\n", ptr, sc->intr[0], feed);
2090 #endif
2091                 for (i = ENVY24_CHAN_PLAY_DAC1; i <= ENVY24_CHAN_PLAY_SPDIF; i++) {
2092                         ch = &sc->chan[i];
2093 #if(0)
2094                         if (ch->run)
2095                                 device_printf(sc->dev, "envy24_intr(): chan[%d].blk = %d\n", i, ch->blk);
2096 #endif
2097                         if (ch->run && ch->blk <= feed) {
2098                                 snd_mtxunlock(sc->lock);
2099                                 chn_intr(ch->channel);
2100                                 snd_mtxlock(sc->lock);
2101                         }
2102                 }
2103                 sc->intr[0] = ptr;
2104                 envy24_updintr(sc, PCMDIR_PLAY);
2105         }
2106         if (envy24_checkintr(sc, PCMDIR_REC)) {
2107 #if(0)
2108                 device_printf(sc->dev, "envy24_intr(): rec\n");
2109 #endif
2110                 dsize = sc->rsize / 4;
2111                 ptr = dsize - envy24_rdmt(sc, ENVY24_MT_RCNT, 2) - 1;
2112                 ptr -= ptr % sc->blk[1];
2113                 feed = (ptr + dsize - sc->intr[1]) % dsize; 
2114                 for (i = ENVY24_CHAN_REC_ADC1; i <= ENVY24_CHAN_REC_SPDIF; i++) {
2115                         ch = &sc->chan[i];
2116                         if (ch->run && ch->blk <= feed) {
2117                                 snd_mtxunlock(sc->lock);
2118                                 chn_intr(ch->channel);
2119                                 snd_mtxlock(sc->lock);
2120                         }
2121                 }
2122                 sc->intr[1] = ptr;
2123                 envy24_updintr(sc, PCMDIR_REC);
2124         }
2125         snd_mtxunlock(sc->lock);
2126
2127         return;
2128 }
2129
2130 /*
2131  * Probe and attach the card
2132  */
2133
2134 static int
2135 envy24_pci_probe(device_t dev)
2136 {
2137         u_int16_t sv, sd;
2138         int i;
2139
2140 #if(0)
2141         printf("envy24_pci_probe()\n");
2142 #endif
2143         if (pci_get_device(dev) == PCID_ENVY24 &&
2144             pci_get_vendor(dev) == PCIV_ENVY24) {
2145                 sv = pci_get_subvendor(dev);
2146                 sd = pci_get_subdevice(dev);
2147                 for (i = 0; cfg_table[i].subvendor != 0 || cfg_table[i].subdevice != 0; i++) {
2148                         if (cfg_table[i].subvendor == sv &&
2149                             cfg_table[i].subdevice == sd) {
2150                                 break;
2151                         }
2152                 }
2153                 device_set_desc(dev, cfg_table[i].name);
2154 #if(0)
2155                 printf("envy24_pci_probe(): return 0\n");
2156 #endif
2157                 return 0;
2158         }
2159         else {
2160 #if(0)
2161                 printf("envy24_pci_probe(): return ENXIO\n");
2162 #endif
2163                 return ENXIO;
2164         }
2165 }
2166
2167 static void
2168 envy24_dmapsetmap(void *arg, bus_dma_segment_t *segs, int nseg, int error)
2169 {
2170         struct sc_info *sc = (struct sc_info *)arg;
2171
2172         sc->paddr = segs->ds_addr;
2173 #if(0)
2174         device_printf(sc->dev, "envy24_dmapsetmap()\n");
2175         if (bootverbose) {
2176                 printf("envy24(play): setmap %lx, %lx; ",
2177                     (unsigned long)segs->ds_addr,
2178                     (unsigned long)segs->ds_len);
2179                 printf("%p -> %lx\n", sc->pmap, sc->paddr);
2180         }
2181 #endif
2182 }
2183
2184 static void
2185 envy24_dmarsetmap(void *arg, bus_dma_segment_t *segs, int nseg, int error)
2186 {
2187         struct sc_info *sc = (struct sc_info *)arg;
2188
2189         sc->raddr = segs->ds_addr;
2190 #if(0)
2191         device_printf(sc->dev, "envy24_dmarsetmap()\n");
2192         if (bootverbose) {
2193                 printf("envy24(record): setmap %lx, %lx; ",
2194                     (unsigned long)segs->ds_addr,
2195                     (unsigned long)segs->ds_len);
2196                 printf("%p -> %lx\n", sc->rmap, sc->raddr);
2197         }
2198 #endif
2199 }
2200
2201 static void
2202 envy24_dmafree(struct sc_info *sc)
2203 {
2204 #if(0)
2205         device_printf(sc->dev, "envy24_dmafree():");
2206         printf(" sc->raddr(0x%08x)", (u_int32_t)sc->raddr);
2207         printf(" sc->paddr(0x%08x)", (u_int32_t)sc->paddr);
2208         if (sc->rbuf) printf(" sc->rbuf(0x%08x)", (u_int32_t)sc->rbuf);
2209         else printf(" sc->rbuf(null)");
2210         if (sc->pbuf) printf(" sc->pbuf(0x%08x)\n", (u_int32_t)sc->pbuf);
2211         else printf(" sc->pbuf(null)\n");
2212 #endif
2213 #if(0)
2214         if (sc->raddr)
2215                 bus_dmamap_unload(sc->dmat, sc->rmap);
2216         if (sc->paddr)
2217                 bus_dmamap_unload(sc->dmat, sc->pmap);
2218         if (sc->rbuf)
2219                 bus_dmamem_free(sc->dmat, sc->rbuf, sc->rmap);
2220         if (sc->pbuf)
2221                 bus_dmamem_free(sc->dmat, sc->pbuf, sc->pmap);
2222 #else
2223         bus_dmamap_unload(sc->dmat, sc->rmap);
2224         bus_dmamap_unload(sc->dmat, sc->pmap);
2225         bus_dmamem_free(sc->dmat, sc->rbuf, sc->rmap);
2226         bus_dmamem_free(sc->dmat, sc->pbuf, sc->pmap);
2227 #endif
2228
2229         sc->raddr = sc->paddr = 0;
2230         sc->pbuf = NULL;
2231         sc->rbuf = NULL;
2232
2233         return;
2234 }
2235
2236 static int
2237 envy24_dmainit(struct sc_info *sc)
2238 {
2239
2240 #if(0)
2241         device_printf(sc->dev, "envy24_dmainit()\n");
2242 #endif
2243         /* init values */
2244         sc->psize = ENVY24_PLAY_BUFUNIT * ENVY24_SAMPLE_NUM;
2245         sc->rsize = ENVY24_REC_BUFUNIT * ENVY24_SAMPLE_NUM;
2246         sc->pbuf = NULL;
2247         sc->rbuf = NULL;
2248         sc->paddr = sc->raddr = 0;
2249         sc->blk[0] = sc->blk[1] = 0;
2250
2251         /* allocate DMA buffer */
2252 #if(0)
2253         device_printf(sc->dev, "envy24_dmainit(): bus_dmamem_alloc(): sc->pbuf\n");
2254 #endif
2255         if (bus_dmamem_alloc(sc->dmat, (void **)&sc->pbuf, BUS_DMA_NOWAIT, &sc->pmap))
2256                 goto bad;
2257 #if(0)
2258         device_printf(sc->dev, "envy24_dmainit(): bus_dmamem_alloc(): sc->rbuf\n");
2259 #endif
2260         if (bus_dmamem_alloc(sc->dmat, (void **)&sc->rbuf, BUS_DMA_NOWAIT, &sc->rmap))
2261                 goto bad;
2262 #if(0)
2263         device_printf(sc->dev, "envy24_dmainit(): bus_dmamem_load(): sc->pmap\n");
2264 #endif
2265         if (bus_dmamap_load(sc->dmat, sc->pmap, sc->pbuf, sc->psize, envy24_dmapsetmap, sc, 0))
2266                 goto bad;
2267 #if(0)
2268         device_printf(sc->dev, "envy24_dmainit(): bus_dmamem_load(): sc->rmap\n");
2269 #endif
2270         if (bus_dmamap_load(sc->dmat, sc->rmap, sc->rbuf, sc->rsize, envy24_dmarsetmap, sc, 0))
2271                 goto bad;
2272         bzero(sc->pbuf, sc->psize);
2273         bzero(sc->rbuf, sc->rsize);
2274
2275         /* set values to register */
2276 #if(0)
2277         device_printf(sc->dev, "paddr(0x%08x)\n", sc->paddr);
2278 #endif
2279         envy24_wrmt(sc, ENVY24_MT_PADDR, sc->paddr, 4);
2280 #if(0)
2281         device_printf(sc->dev, "PADDR-->(0x%08x)\n", envy24_rdmt(sc, ENVY24_MT_PADDR, 4));
2282         device_printf(sc->dev, "psize(%ld)\n", sc->psize / 4 - 1);
2283 #endif
2284         envy24_wrmt(sc, ENVY24_MT_PCNT, sc->psize / 4 - 1, 2);
2285 #if(0)
2286         device_printf(sc->dev, "PCNT-->(%ld)\n", envy24_rdmt(sc, ENVY24_MT_PCNT, 2));
2287 #endif
2288         envy24_wrmt(sc, ENVY24_MT_RADDR, sc->raddr, 4);
2289         envy24_wrmt(sc, ENVY24_MT_RCNT, sc->rsize / 4 - 1, 2);
2290
2291         return 0;
2292  bad:
2293         envy24_dmafree(sc);
2294         return ENOSPC;
2295 }
2296
2297 static void
2298 envy24_putcfg(struct sc_info *sc)
2299 {
2300         device_printf(sc->dev, "system configuration\n");
2301         kprintf("  SubVendorID: 0x%04x, SubDeviceID: 0x%04x\n",
2302             sc->cfg->subvendor, sc->cfg->subdevice);
2303         kprintf("  XIN2 Clock Source: ");
2304         switch (sc->cfg->scfg & PCIM_SCFG_XIN2) {
2305         case 0x00:
2306                 kprintf("22.5792MHz(44.1kHz*512)\n");
2307                 break;
2308         case 0x40:
2309                 kprintf("16.9344MHz(44.1kHz*384)\n");
2310                 break;
2311         case 0x80:
2312                 kprintf("from external clock synthesizer chip\n");
2313                 break;
2314         default:
2315                 kprintf("illegal system setting\n");
2316         }
2317         kprintf("  MPU-401 UART(s) #: ");
2318         if (sc->cfg->scfg & PCIM_SCFG_MPU)
2319                 kprintf("2\n");
2320         else
2321                 kprintf("1\n");
2322         kprintf("  AC'97 codec: ");
2323         if (sc->cfg->scfg & PCIM_SCFG_AC97)
2324                 kprintf("not exist\n");
2325         else
2326                 kprintf("exist\n");
2327         kprintf("  ADC #: ");
2328         kprintf("%d\n", sc->adcn);
2329         kprintf("  DAC #: ");
2330         kprintf("%d\n", sc->dacn);
2331         kprintf("  Multi-track converter type: ");
2332         if ((sc->cfg->acl & PCIM_ACL_MTC) == 0) {
2333                 kprintf("AC'97(SDATA_OUT:");
2334                 if (sc->cfg->acl & PCIM_ACL_OMODE)
2335                         kprintf("packed");
2336                 else
2337                         kprintf("split");
2338                 kprintf("|SDATA_IN:");
2339                 if (sc->cfg->acl & PCIM_ACL_IMODE)
2340                         kprintf("packed");
2341                 else
2342                         kprintf("split");
2343                 kprintf(")\n");
2344         }
2345         else {
2346                 kprintf("I2S(");
2347                 if (sc->cfg->i2s & PCIM_I2S_VOL)
2348                         kprintf("with volume, ");
2349                 if (sc->cfg->i2s & PCIM_I2S_96KHZ)
2350                         kprintf("96KHz support, ");
2351                 switch (sc->cfg->i2s & PCIM_I2S_RES) {
2352                 case PCIM_I2S_16BIT:
2353                         kprintf("16bit resolution, ");
2354                         break;
2355                 case PCIM_I2S_18BIT:
2356                         kprintf("18bit resolution, ");
2357                         break;
2358                 case PCIM_I2S_20BIT:
2359                         kprintf("20bit resolution, ");
2360                         break;
2361                 case PCIM_I2S_24BIT:
2362                         kprintf("24bit resolution, ");
2363                         break;
2364                 }
2365                 kprintf("ID#0x%x)\n", sc->cfg->i2s & PCIM_I2S_ID);
2366         }
2367         kprintf("  S/PDIF(IN/OUT): ");
2368         if (sc->cfg->spdif & PCIM_SPDIF_IN)
2369                 kprintf("1/");
2370         else
2371                 kprintf("0/");
2372         if (sc->cfg->spdif & PCIM_SPDIF_OUT)
2373                 kprintf("1 ");
2374         else
2375                 kprintf("0 ");
2376         if (sc->cfg->spdif & (PCIM_SPDIF_IN | PCIM_SPDIF_OUT))
2377                 kprintf("ID# 0x%02x\n", (sc->cfg->spdif & PCIM_SPDIF_ID) >> 2);
2378         kprintf("  GPIO(mask/dir/state): 0x%02x/0x%02x/0x%02x\n",
2379             sc->cfg->gpiomask, sc->cfg->gpiodir, sc->cfg->gpiostate);
2380 }
2381
2382 static int
2383 envy24_init(struct sc_info *sc)
2384 {
2385         u_int32_t data;
2386 #if(0)
2387         int rtn;
2388 #endif
2389         int i;
2390         u_int32_t sv, sd;
2391
2392
2393 #if(0)
2394         device_printf(sc->dev, "envy24_init()\n");
2395 #endif
2396
2397         /* reset chip */
2398         envy24_wrcs(sc, ENVY24_CCS_CTL, ENVY24_CCS_CTL_RESET | ENVY24_CCS_CTL_NATIVE, 1);
2399         DELAY(200);
2400         envy24_wrcs(sc, ENVY24_CCS_CTL, ENVY24_CCS_CTL_NATIVE, 1);
2401         DELAY(200);
2402
2403         /* legacy hardware disable */
2404         data = pci_read_config(sc->dev, PCIR_LAC, 2);
2405         data |= PCIM_LAC_DISABLE;
2406         pci_write_config(sc->dev, PCIR_LAC, data, 2);
2407
2408         /* check system configuration */
2409         sc->cfg = NULL;
2410         for (i = 0; cfg_table[i].subvendor != 0 || cfg_table[i].subdevice != 0; i++) {
2411                 /* 1st: search configuration from table */
2412                 sv = pci_get_subvendor(sc->dev);
2413                 sd = pci_get_subdevice(sc->dev);
2414                 if (sv == cfg_table[i].subvendor && sd == cfg_table[i].subdevice) {
2415 #if(0)
2416                         device_printf(sc->dev, "Set configuration from table\n");
2417 #endif
2418                         sc->cfg = &cfg_table[i];
2419                         break;
2420                 }
2421         }
2422         if (sc->cfg == NULL) {
2423                 /* 2nd: read configuration from table */
2424                 sc->cfg = envy24_rom2cfg(sc);
2425         }
2426         sc->adcn = ((sc->cfg->scfg & PCIM_SCFG_ADC) >> 2) + 1;
2427         sc->dacn = (sc->cfg->scfg & PCIM_SCFG_DAC) + 1;
2428
2429         if (1 /* bootverbose */) {
2430                 envy24_putcfg(sc);
2431         }
2432
2433         /* set system configuration */
2434         pci_write_config(sc->dev, PCIR_SCFG, sc->cfg->scfg, 1);
2435         pci_write_config(sc->dev, PCIR_ACL, sc->cfg->acl, 1);
2436         pci_write_config(sc->dev, PCIR_I2S, sc->cfg->i2s, 1);
2437         pci_write_config(sc->dev, PCIR_SPDIF, sc->cfg->spdif, 1);
2438         envy24_gpiosetmask(sc, sc->cfg->gpiomask);
2439         envy24_gpiosetdir(sc, sc->cfg->gpiodir);
2440         envy24_gpiowr(sc, sc->cfg->gpiostate);
2441         for (i = 0; i < sc->adcn; i++) {
2442                 sc->adc[i] = sc->cfg->codec->create(sc->dev, sc, PCMDIR_REC, i);
2443                 sc->cfg->codec->init(sc->adc[i]);
2444         }
2445         for (i = 0; i < sc->dacn; i++) {
2446                 sc->dac[i] = sc->cfg->codec->create(sc->dev, sc, PCMDIR_PLAY, i);
2447                 sc->cfg->codec->init(sc->dac[i]);
2448         }
2449
2450         /* initialize DMA buffer */
2451 #if(0)
2452         device_printf(sc->dev, "envy24_init(): initialize DMA buffer\n");
2453 #endif
2454         if (envy24_dmainit(sc))
2455                 return ENOSPC;
2456
2457         /* initialize status */
2458         sc->run[0] = sc->run[1] = 0;
2459         sc->intr[0] = sc->intr[1] = 0;
2460         sc->speed = 0;
2461         sc->caps[0].fmtlist = envy24_playfmt;
2462         sc->caps[1].fmtlist = envy24_recfmt;
2463
2464         /* set channel router */
2465         envy24_route(sc, ENVY24_ROUTE_DAC_1, ENVY24_ROUTE_CLASS_MIX, 0, 0);
2466         envy24_route(sc, ENVY24_ROUTE_DAC_SPDIF, ENVY24_ROUTE_CLASS_DMA, 0, 0);
2467         /* envy24_route(sc, ENVY24_ROUTE_DAC_SPDIF, ENVY24_ROUTE_CLASS_MIX, 0, 0); */
2468
2469         /* set macro interrupt mask */
2470         data = envy24_rdcs(sc, ENVY24_CCS_IMASK, 1);
2471         envy24_wrcs(sc, ENVY24_CCS_IMASK, data & ~ENVY24_CCS_IMASK_PMT, 1);
2472         data = envy24_rdcs(sc, ENVY24_CCS_IMASK, 1);
2473 #if(0)
2474         device_printf(sc->dev, "envy24_init(): CCS_IMASK-->0x%02x\n", data);
2475 #endif
2476
2477         return 0;
2478 }
2479
2480 static int
2481 envy24_alloc_resource(struct sc_info *sc)
2482 {
2483         /* allocate I/O port resource */
2484         sc->csid = PCIR_CCS;
2485         sc->cs = bus_alloc_resource(sc->dev, SYS_RES_IOPORT,
2486             &sc->csid, 0, ~0, 1, RF_ACTIVE);
2487         sc->ddmaid = PCIR_DDMA;
2488         sc->ddma = bus_alloc_resource(sc->dev, SYS_RES_IOPORT,
2489             &sc->ddmaid, 0, ~0, 1, RF_ACTIVE);
2490         sc->dsid = PCIR_DS;
2491         sc->ds = bus_alloc_resource(sc->dev, SYS_RES_IOPORT,
2492             &sc->dsid, 0, ~0, 1, RF_ACTIVE);
2493         sc->mtid = PCIR_MT;
2494         sc->mt = bus_alloc_resource(sc->dev, SYS_RES_IOPORT,
2495             &sc->mtid, 0, ~0, 1, RF_ACTIVE);
2496         if (!sc->cs || !sc->ddma || !sc->ds || !sc->mt) {
2497                 device_printf(sc->dev, "unable to map IO port space\n");
2498                 return ENXIO;
2499         }
2500         sc->cst = rman_get_bustag(sc->cs);
2501         sc->csh = rman_get_bushandle(sc->cs);
2502         sc->ddmat = rman_get_bustag(sc->ddma);
2503         sc->ddmah = rman_get_bushandle(sc->ddma);
2504         sc->dst = rman_get_bustag(sc->ds);
2505         sc->dsh = rman_get_bushandle(sc->ds);
2506         sc->mtt = rman_get_bustag(sc->mt);
2507         sc->mth = rman_get_bushandle(sc->mt);
2508 #if(0)
2509         device_printf(sc->dev,
2510             "IO port register values\nCCS: 0x%lx\nDDMA: 0x%lx\nDS: 0x%lx\nMT: 0x%lx\n",
2511             pci_read_config(sc->dev, PCIR_CCS, 4),
2512             pci_read_config(sc->dev, PCIR_DDMA, 4),
2513             pci_read_config(sc->dev, PCIR_DS, 4),
2514             pci_read_config(sc->dev, PCIR_MT, 4));
2515 #endif
2516
2517         /* allocate interrupt resource */
2518         sc->irqid = 0;
2519         sc->irq = bus_alloc_resource(sc->dev, SYS_RES_IRQ, &sc->irqid,
2520                                  0, ~0, 1, RF_ACTIVE | RF_SHAREABLE);
2521         if (!sc->irq ||
2522             snd_setup_intr(sc->dev, sc->irq, INTR_MPSAFE, envy24_intr, sc, &sc->ih)) {
2523                 device_printf(sc->dev, "unable to map interrupt\n");
2524                 return ENXIO;
2525         }
2526
2527         /* allocate DMA resource */
2528         if (bus_dma_tag_create(/*parent*/bus_get_dma_tag(sc->dev),
2529             /*alignment*/4,
2530             /*boundary*/0,
2531             /*lowaddr*/BUS_SPACE_MAXADDR_ENVY24,
2532             /*highaddr*/BUS_SPACE_MAXADDR_ENVY24,
2533             /*filter*/NULL, /*filterarg*/NULL,
2534             /*maxsize*/BUS_SPACE_MAXSIZE_ENVY24,
2535             /*nsegments*/1, /*maxsegsz*/0x3ffff,
2536             /*flags*/0,
2537             &sc->dmat) != 0) {
2538                 device_printf(sc->dev, "unable to create dma tag\n");
2539                 return ENXIO;
2540         }
2541
2542         return 0;
2543 }
2544
2545 static int
2546 envy24_pci_attach(device_t dev)
2547 {
2548         struct sc_info          *sc;
2549         char                    status[SND_STATUSLEN];
2550         int                     err = 0;
2551         int                     i;
2552
2553 #if(0)
2554         device_printf(dev, "envy24_pci_attach()\n");
2555 #endif
2556         /* get sc_info data area */
2557         if ((sc = kmalloc(sizeof(*sc), M_ENVY24, M_WAITOK | M_ZERO)) == NULL) {
2558                 device_printf(dev, "cannot allocate softc\n");
2559                 return ENXIO;
2560         }
2561
2562         bzero(sc, sizeof(*sc));
2563         sc->lock = snd_mtxcreate(device_get_nameunit(dev), "snd_envy24 softc");
2564         sc->dev = dev;
2565
2566         /* initialize PCI interface */
2567         pci_enable_busmaster(dev);
2568
2569         /* allocate resources */
2570         err = envy24_alloc_resource(sc);
2571         if (err) {
2572                 device_printf(dev, "unable to allocate system resources\n");
2573                 goto bad;
2574         }
2575
2576         /* initialize card */
2577         err = envy24_init(sc);
2578         if (err) {
2579                 device_printf(dev, "unable to initialize the card\n");
2580                 goto bad;
2581         }
2582
2583         /* set multi track mixer */
2584         mixer_init(dev, &envy24mixer_class, sc);
2585
2586         /* set channel information */
2587         err = pcm_register(dev, sc, 5, 2 + sc->adcn);
2588         if (err)
2589                 goto bad;
2590         sc->chnum = 0;
2591         for (i = 0; i < 5; i++) {
2592                 pcm_addchan(dev, PCMDIR_PLAY, &envy24chan_class, sc);
2593                 sc->chnum++;
2594         }
2595         for (i = 0; i < 2 + sc->adcn; i++) {
2596                 pcm_addchan(dev, PCMDIR_REC, &envy24chan_class, sc);
2597                 sc->chnum++;
2598         }
2599
2600         /* set status iformation */
2601         ksnprintf(status, SND_STATUSLEN,
2602             "at io 0x%lx:%ld,0x%lx:%ld,0x%lx:%ld,0x%lx:%ld irq %ld",
2603             rman_get_start(sc->cs),
2604             rman_get_end(sc->cs) - rman_get_start(sc->cs) + 1,
2605             rman_get_start(sc->ddma),
2606             rman_get_end(sc->ddma) - rman_get_start(sc->ddma) + 1,
2607             rman_get_start(sc->ds),
2608             rman_get_end(sc->ds) - rman_get_start(sc->ds) + 1,
2609             rman_get_start(sc->mt),
2610             rman_get_end(sc->mt) - rman_get_start(sc->mt) + 1,
2611             rman_get_start(sc->irq));
2612         pcm_setstatus(dev, status);
2613
2614         return 0;
2615
2616 bad:
2617         if (sc->ih)
2618                 bus_teardown_intr(dev, sc->irq, sc->ih);
2619         if (sc->irq)
2620                 bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq);
2621         envy24_dmafree(sc);
2622         if (sc->dmat)
2623                 bus_dma_tag_destroy(sc->dmat);
2624         if (sc->cfg->codec->destroy != NULL) {
2625                 for (i = 0; i < sc->adcn; i++)
2626                         sc->cfg->codec->destroy(sc->adc[i]);
2627                 for (i = 0; i < sc->dacn; i++)
2628                         sc->cfg->codec->destroy(sc->dac[i]);
2629         }
2630         envy24_cfgfree(sc->cfg);
2631         if (sc->cs)
2632                 bus_release_resource(dev, SYS_RES_IOPORT, sc->csid, sc->cs);
2633         if (sc->ddma)
2634                 bus_release_resource(dev, SYS_RES_IOPORT, sc->ddmaid, sc->ddma);
2635         if (sc->ds)
2636                 bus_release_resource(dev, SYS_RES_IOPORT, sc->dsid, sc->ds);
2637         if (sc->mt)
2638                 bus_release_resource(dev, SYS_RES_IOPORT, sc->mtid, sc->mt);
2639         if (sc->lock)
2640                 snd_mtxfree(sc->lock);
2641         kfree(sc, M_ENVY24);
2642         return err;
2643 }
2644
2645 static int
2646 envy24_pci_detach(device_t dev)
2647 {
2648         struct sc_info *sc;
2649         int r;
2650         int i;
2651
2652 #if(0)
2653         device_printf(dev, "envy24_pci_detach()\n");
2654 #endif
2655         sc = pcm_getdevinfo(dev);
2656         if (sc == NULL)
2657                 return 0;
2658         r = pcm_unregister(dev);
2659         if (r)
2660                 return r;
2661
2662         envy24_dmafree(sc);
2663         if (sc->cfg->codec->destroy != NULL) {
2664                 for (i = 0; i < sc->adcn; i++)
2665                         sc->cfg->codec->destroy(sc->adc[i]);
2666                 for (i = 0; i < sc->dacn; i++)
2667                         sc->cfg->codec->destroy(sc->dac[i]);
2668         }
2669         envy24_cfgfree(sc->cfg);
2670         bus_dma_tag_destroy(sc->dmat);
2671         bus_teardown_intr(dev, sc->irq, sc->ih);
2672         bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq);
2673         bus_release_resource(dev, SYS_RES_IOPORT, sc->csid, sc->cs);
2674         bus_release_resource(dev, SYS_RES_IOPORT, sc->ddmaid, sc->ddma);
2675         bus_release_resource(dev, SYS_RES_IOPORT, sc->dsid, sc->ds);
2676         bus_release_resource(dev, SYS_RES_IOPORT, sc->mtid, sc->mt);
2677         snd_mtxfree(sc->lock);
2678         kfree(sc, M_ENVY24);
2679         return 0;
2680 }
2681
2682 static device_method_t envy24_methods[] = {
2683         /* Device interface */
2684         DEVMETHOD(device_probe,         envy24_pci_probe),
2685         DEVMETHOD(device_attach,        envy24_pci_attach),
2686         DEVMETHOD(device_detach,        envy24_pci_detach),
2687         { 0, 0 }
2688 };
2689
2690 static driver_t envy24_driver = {
2691         "pcm",
2692         envy24_methods,
2693         PCM_SOFTC_SIZE,
2694 };
2695
2696 DRIVER_MODULE(snd_envy24, pci, envy24_driver, pcm_devclass, NULL, NULL);
2697 MODULE_DEPEND(snd_envy24, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER);
2698 MODULE_DEPEND(snd_envy24, snd_spicds, 1, 1, 1);
2699 MODULE_VERSION(snd_envy24, 1);