1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (c) 2001 Katsurajima Naoto <raven@katsurajima.seya.yokohama.jp>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHERIN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 *
28 */
29
30 #ifdef HAVE_KERNEL_OPTION_HEADERS
31 #include "opt_snd.h"
32 #endif
33
34 #include <dev/sound/pcm/sound.h>
35 #include <dev/sound/pcm/ac97.h>
36 #include <dev/sound/pci/spicds.h>
37 #include <dev/sound/pci/envy24.h>
38
39 #include <dev/pci/pcireg.h>
40 #include <dev/pci/pcivar.h>
41
42 #include "mixer_if.h"
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 mtx *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
envy24_rdcs(struct sc_info * sc,int regno,int size)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
envy24_wrcs(struct sc_info * sc,int regno,u_int32_t data,int size)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
envy24_rdmt(struct sc_info * sc,int regno,int size)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
envy24_wrmt(struct sc_info * sc,int regno,u_int32_t data,int size)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
envy24_rdci(struct sc_info * sc,int regno)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
envy24_wrci(struct sc_info * sc,int regno,u_int32_t data)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
envy24_rdi2c(struct sc_info * sc,u_int32_t dev,u_int32_t addr)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
envy24_rdrom(struct sc_info * sc,u_int32_t addr)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 *
envy24_rom2cfg(struct sc_info * sc)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 = malloc(sizeof(*buff), M_ENVY24, M_NOWAIT);
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
envy24_cfgfree(struct cfg_info * cfg)626 envy24_cfgfree(struct cfg_info *cfg) {
627 if (cfg == NULL)
628 return;
629 if (cfg->free)
630 free(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
envy24_slavecd(struct sc_info * sc)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
envy24_gpiord(struct sc_info * sc)748 envy24_gpiord(struct sc_info *sc)
749 {
750 return envy24_rdci(sc, ENVY24_CCI_GPIODAT);
751 }
752
753 static void
envy24_gpiowr(struct sc_info * sc,u_int32_t data)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
envy24_gpiosetmask(struct sc_info * sc,u_int32_t mask)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
envy24_gpiosetdir(struct sc_info * sc,u_int32_t dir)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
envy24_gpio_i2c_ctl(void * codec,unsigned int scl,unsigned int sda)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
i2c_wrbit(void * codec,void (* ctrl)(void *,unsigned int,unsigned int),int bit)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
i2c_start(void * codec,void (* ctrl)(void *,unsigned int,unsigned int))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
i2c_stop(void * codec,void (* ctrl)(void *,unsigned int,unsigned int))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
i2c_ack(void * codec,void (* ctrl)(void *,unsigned int,unsigned int))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
i2c_wr(void * codec,void (* ctrl)(void *,unsigned int,unsigned int),u_int32_t dev,int reg,u_int8_t val)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
envy24_delta_ak4524_ctl(void * codec,unsigned int cs,unsigned int cclk,unsigned int cdti)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 *
envy24_delta_ak4524_create(device_t dev,void * info,int dir,int num)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 = malloc(sizeof(*buff), M_ENVY24, M_NOWAIT);
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 free(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
envy24_delta_ak4524_destroy(void * codec)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 free(codec, M_ENVY24);
980 }
981
982 static void
envy24_delta_ak4524_init(void * codec)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
envy24_delta_ak4524_reinit(void * codec)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
envy24_delta_ak4524_setvolume(void * codec,int dir,unsigned int left,unsigned int right)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
envy24_setspeed(struct sc_info * sc,u_int32_t speed)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
envy24_setvolume(struct sc_info * sc,unsigned ch)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
envy24_mutevolume(struct sc_info * sc,unsigned ch)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
envy24_gethwptr(struct sc_info * sc,int dir)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
envy24_updintr(struct sc_info * sc,int dir)1201 envy24_updintr(struct sc_info *sc, int dir)
1202 {
1203 int regintr;
1204 u_int32_t mask, intr;
1205 u_int32_t 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 regintr = ENVY24_MT_PTERM;
1214 mask = ~ENVY24_MT_INT_PMASK;
1215 }
1216 else {
1217 blk = sc->blk[1];
1218 regintr = ENVY24_MT_RTERM;
1219 mask = ~ENVY24_MT_INT_RMASK;
1220 }
1221
1222 cnt = blk - 1;
1223 #if(0)
1224 device_printf(sc->dev, "envy24_updintr():blk = %d, cnt = %d\n", blk, cnt);
1225 #endif
1226 envy24_wrmt(sc, regintr, cnt, 2);
1227 intr = envy24_rdmt(sc, ENVY24_MT_INT, 1);
1228 #if(0)
1229 device_printf(sc->dev, "envy24_updintr():intr = 0x%02x, mask = 0x%02x\n", intr, mask);
1230 #endif
1231 envy24_wrmt(sc, ENVY24_MT_INT, intr & mask, 1);
1232 #if(0)
1233 device_printf(sc->dev, "envy24_updintr():INT-->0x%02x\n",
1234 envy24_rdmt(sc, ENVY24_MT_INT, 1));
1235 #endif
1236
1237 return;
1238 }
1239
1240 #if 0
1241 static void
1242 envy24_maskintr(struct sc_info *sc, int dir)
1243 {
1244 u_int32_t mask, intr;
1245
1246 #if(0)
1247 device_printf(sc->dev, "envy24_maskintr(sc, %d)\n", dir);
1248 #endif
1249 if (dir == PCMDIR_PLAY)
1250 mask = ENVY24_MT_INT_PMASK;
1251 else
1252 mask = ENVY24_MT_INT_RMASK;
1253 intr = envy24_rdmt(sc, ENVY24_MT_INT, 1);
1254 envy24_wrmt(sc, ENVY24_MT_INT, intr | mask, 1);
1255
1256 return;
1257 }
1258 #endif
1259
1260 static int
envy24_checkintr(struct sc_info * sc,int dir)1261 envy24_checkintr(struct sc_info *sc, int dir)
1262 {
1263 u_int32_t mask, stat, intr, rtn;
1264
1265 #if(0)
1266 device_printf(sc->dev, "envy24_checkintr(sc, %d)\n", dir);
1267 #endif
1268 intr = envy24_rdmt(sc, ENVY24_MT_INT, 1);
1269 if (dir == PCMDIR_PLAY) {
1270 if ((rtn = intr & ENVY24_MT_INT_PSTAT) != 0) {
1271 mask = ~ENVY24_MT_INT_RSTAT;
1272 stat = ENVY24_MT_INT_PSTAT | ENVY24_MT_INT_PMASK;
1273 envy24_wrmt(sc, ENVY24_MT_INT, (intr & mask) | stat, 1);
1274 }
1275 }
1276 else {
1277 if ((rtn = intr & ENVY24_MT_INT_RSTAT) != 0) {
1278 mask = ~ENVY24_MT_INT_PSTAT;
1279 stat = ENVY24_MT_INT_RSTAT | ENVY24_MT_INT_RMASK;
1280 envy24_wrmt(sc, ENVY24_MT_INT, (intr & mask) | stat, 1);
1281 }
1282 }
1283
1284 return rtn;
1285 }
1286
1287 static void
envy24_start(struct sc_info * sc,int dir)1288 envy24_start(struct sc_info *sc, int dir)
1289 {
1290 u_int32_t stat, sw;
1291
1292 #if(0)
1293 device_printf(sc->dev, "envy24_start(sc, %d)\n", dir);
1294 #endif
1295 if (dir == PCMDIR_PLAY)
1296 sw = ENVY24_MT_PCTL_PSTART;
1297 else
1298 sw = ENVY24_MT_PCTL_RSTART;
1299
1300 stat = envy24_rdmt(sc, ENVY24_MT_PCTL, 1);
1301 envy24_wrmt(sc, ENVY24_MT_PCTL, stat | sw, 1);
1302 #if(0)
1303 DELAY(100);
1304 device_printf(sc->dev, "PADDR:0x%08x\n", envy24_rdmt(sc, ENVY24_MT_PADDR, 4));
1305 device_printf(sc->dev, "PCNT:%ld\n", envy24_rdmt(sc, ENVY24_MT_PCNT, 2));
1306 #endif
1307
1308 return;
1309 }
1310
1311 static void
envy24_stop(struct sc_info * sc,int dir)1312 envy24_stop(struct sc_info *sc, int dir)
1313 {
1314 u_int32_t stat, sw;
1315
1316 #if(0)
1317 device_printf(sc->dev, "envy24_stop(sc, %d)\n", dir);
1318 #endif
1319 if (dir == PCMDIR_PLAY)
1320 sw = ~ENVY24_MT_PCTL_PSTART;
1321 else
1322 sw = ~ENVY24_MT_PCTL_RSTART;
1323
1324 stat = envy24_rdmt(sc, ENVY24_MT_PCTL, 1);
1325 envy24_wrmt(sc, ENVY24_MT_PCTL, stat & sw, 1);
1326
1327 return;
1328 }
1329
1330 static int
envy24_route(struct sc_info * sc,int dac,int class,int adc,int rev)1331 envy24_route(struct sc_info *sc, int dac, int class, int adc, int rev)
1332 {
1333 u_int32_t reg, mask;
1334 u_int32_t left, right;
1335
1336 #if(0)
1337 device_printf(sc->dev, "envy24_route(sc, %d, %d, %d, %d)\n",
1338 dac, class, adc, rev);
1339 #endif
1340 /* parameter pattern check */
1341 if (dac < 0 || ENVY24_ROUTE_DAC_SPDIF < dac)
1342 return -1;
1343 if (class == ENVY24_ROUTE_CLASS_MIX &&
1344 (dac != ENVY24_ROUTE_DAC_1 && dac != ENVY24_ROUTE_DAC_SPDIF))
1345 return -1;
1346 if (rev) {
1347 left = ENVY24_ROUTE_RIGHT;
1348 right = ENVY24_ROUTE_LEFT;
1349 }
1350 else {
1351 left = ENVY24_ROUTE_LEFT;
1352 right = ENVY24_ROUTE_RIGHT;
1353 }
1354
1355 if (dac == ENVY24_ROUTE_DAC_SPDIF) {
1356 reg = class | class << 2 |
1357 ((adc << 1 | left) | left << 3) << 8 |
1358 ((adc << 1 | right) | right << 3) << 12;
1359 #if(0)
1360 device_printf(sc->dev, "envy24_route(): MT_SPDOUT-->0x%04x\n", reg);
1361 #endif
1362 envy24_wrmt(sc, ENVY24_MT_SPDOUT, reg, 2);
1363 }
1364 else {
1365 mask = ~(0x0303 << dac * 2);
1366 reg = envy24_rdmt(sc, ENVY24_MT_PSDOUT, 2);
1367 reg = (reg & mask) | ((class | class << 8) << dac * 2);
1368 #if(0)
1369 device_printf(sc->dev, "envy24_route(): MT_PSDOUT-->0x%04x\n", reg);
1370 #endif
1371 envy24_wrmt(sc, ENVY24_MT_PSDOUT, reg, 2);
1372 mask = ~(0xff << dac * 8);
1373 reg = envy24_rdmt(sc, ENVY24_MT_RECORD, 4);
1374 reg = (reg & mask) |
1375 (((adc << 1 | left) | left << 3) |
1376 ((adc << 1 | right) | right << 3) << 4) << dac * 8;
1377 #if(0)
1378 device_printf(sc->dev, "envy24_route(): MT_RECORD-->0x%08x\n", reg);
1379 #endif
1380 envy24_wrmt(sc, ENVY24_MT_RECORD, reg, 4);
1381
1382 /* 6fire rear input init test */
1383 envy24_wrmt(sc, ENVY24_MT_RECORD, 0x00, 4);
1384 }
1385
1386 return 0;
1387 }
1388
1389 /* -------------------------------------------------------------------- */
1390
1391 /* buffer copy routines */
1392 static void
envy24_p32sl(struct sc_chinfo * ch)1393 envy24_p32sl(struct sc_chinfo *ch)
1394 {
1395 int length;
1396 sample32_t *dmabuf;
1397 u_int32_t *data;
1398 int src, dst, ssize, dsize, slot;
1399 int i;
1400
1401 length = sndbuf_getready(ch->buffer) / 8;
1402 dmabuf = ch->parent->pbuf;
1403 data = (u_int32_t *)ch->data;
1404 src = sndbuf_getreadyptr(ch->buffer) / 4;
1405 dst = src / 2 + ch->offset;
1406 ssize = ch->size / 4;
1407 dsize = ch->size / 8;
1408 slot = ch->num * 2;
1409
1410 for (i = 0; i < length; i++) {
1411 dmabuf[dst * ENVY24_PLAY_CHNUM + slot].buffer = data[src];
1412 dmabuf[dst * ENVY24_PLAY_CHNUM + slot + 1].buffer = data[src + 1];
1413 dst++;
1414 dst %= dsize;
1415 src += 2;
1416 src %= ssize;
1417 }
1418
1419 return;
1420 }
1421
1422 static void
envy24_p16sl(struct sc_chinfo * ch)1423 envy24_p16sl(struct sc_chinfo *ch)
1424 {
1425 int length;
1426 sample32_t *dmabuf;
1427 u_int16_t *data;
1428 int src, dst, ssize, dsize, slot;
1429 int i;
1430
1431 #if(0)
1432 device_printf(ch->parent->dev, "envy24_p16sl()\n");
1433 #endif
1434 length = sndbuf_getready(ch->buffer) / 4;
1435 dmabuf = ch->parent->pbuf;
1436 data = (u_int16_t *)ch->data;
1437 src = sndbuf_getreadyptr(ch->buffer) / 2;
1438 dst = src / 2 + ch->offset;
1439 ssize = ch->size / 2;
1440 dsize = ch->size / 4;
1441 slot = ch->num * 2;
1442 #if(0)
1443 device_printf(ch->parent->dev, "envy24_p16sl():%lu-->%lu(%lu)\n", src, dst, length);
1444 #endif
1445
1446 for (i = 0; i < length; i++) {
1447 dmabuf[dst * ENVY24_PLAY_CHNUM + slot].buffer = (u_int32_t)data[src] << 16;
1448 dmabuf[dst * ENVY24_PLAY_CHNUM + slot + 1].buffer = (u_int32_t)data[src + 1] << 16;
1449 #if(0)
1450 if (i < 16) {
1451 printf("%08x", dmabuf[dst * ENVY24_PLAY_CHNUM + slot]);
1452 printf("%08x", dmabuf[dst * ENVY24_PLAY_CHNUM + slot + 1]);
1453 }
1454 #endif
1455 dst++;
1456 dst %= dsize;
1457 src += 2;
1458 src %= ssize;
1459 }
1460 #if(0)
1461 printf("\n");
1462 #endif
1463
1464 return;
1465 }
1466
1467 static void
envy24_p8u(struct sc_chinfo * ch)1468 envy24_p8u(struct sc_chinfo *ch)
1469 {
1470 int length;
1471 sample32_t *dmabuf;
1472 u_int8_t *data;
1473 int src, dst, ssize, dsize, slot;
1474 int i;
1475
1476 length = sndbuf_getready(ch->buffer) / 2;
1477 dmabuf = ch->parent->pbuf;
1478 data = (u_int8_t *)ch->data;
1479 src = sndbuf_getreadyptr(ch->buffer);
1480 dst = src / 2 + ch->offset;
1481 ssize = ch->size;
1482 dsize = ch->size / 4;
1483 slot = ch->num * 2;
1484
1485 for (i = 0; i < length; i++) {
1486 dmabuf[dst * ENVY24_PLAY_CHNUM + slot].buffer = ((u_int32_t)data[src] ^ 0x80) << 24;
1487 dmabuf[dst * ENVY24_PLAY_CHNUM + slot + 1].buffer = ((u_int32_t)data[src + 1] ^ 0x80) << 24;
1488 dst++;
1489 dst %= dsize;
1490 src += 2;
1491 src %= ssize;
1492 }
1493
1494 return;
1495 }
1496
1497 static void
envy24_r32sl(struct sc_chinfo * ch)1498 envy24_r32sl(struct sc_chinfo *ch)
1499 {
1500 int length;
1501 sample32_t *dmabuf;
1502 u_int32_t *data;
1503 int src, dst, ssize, dsize, slot;
1504 int i;
1505
1506 length = sndbuf_getfree(ch->buffer) / 8;
1507 dmabuf = ch->parent->rbuf;
1508 data = (u_int32_t *)ch->data;
1509 dst = sndbuf_getfreeptr(ch->buffer) / 4;
1510 src = dst / 2 + ch->offset;
1511 dsize = ch->size / 4;
1512 ssize = ch->size / 8;
1513 slot = (ch->num - ENVY24_CHAN_REC_ADC1) * 2;
1514
1515 for (i = 0; i < length; i++) {
1516 data[dst] = dmabuf[src * ENVY24_REC_CHNUM + slot].buffer;
1517 data[dst + 1] = dmabuf[src * ENVY24_REC_CHNUM + slot + 1].buffer;
1518 dst += 2;
1519 dst %= dsize;
1520 src++;
1521 src %= ssize;
1522 }
1523
1524 return;
1525 }
1526
1527 static void
envy24_r16sl(struct sc_chinfo * ch)1528 envy24_r16sl(struct sc_chinfo *ch)
1529 {
1530 int length;
1531 sample32_t *dmabuf;
1532 u_int16_t *data;
1533 int src, dst, ssize, dsize, slot;
1534 int i;
1535
1536 length = sndbuf_getfree(ch->buffer) / 4;
1537 dmabuf = ch->parent->rbuf;
1538 data = (u_int16_t *)ch->data;
1539 dst = sndbuf_getfreeptr(ch->buffer) / 2;
1540 src = dst / 2 + ch->offset;
1541 dsize = ch->size / 2;
1542 ssize = ch->size / 8;
1543 slot = (ch->num - ENVY24_CHAN_REC_ADC1) * 2;
1544
1545 for (i = 0; i < length; i++) {
1546 data[dst] = dmabuf[src * ENVY24_REC_CHNUM + slot].buffer;
1547 data[dst + 1] = dmabuf[src * ENVY24_REC_CHNUM + slot + 1].buffer;
1548 dst += 2;
1549 dst %= dsize;
1550 src++;
1551 src %= ssize;
1552 }
1553
1554 return;
1555 }
1556
1557 /* -------------------------------------------------------------------- */
1558
1559 /* channel interface */
1560 static void *
envy24chan_init(kobj_t obj,void * devinfo,struct snd_dbuf * b,struct pcm_channel * c,int dir)1561 envy24chan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir)
1562 {
1563 struct sc_info *sc = (struct sc_info *)devinfo;
1564 struct sc_chinfo *ch;
1565 unsigned num;
1566
1567 #if(0)
1568 device_printf(sc->dev, "envy24chan_init(obj, devinfo, b, c, %d)\n", dir);
1569 #endif
1570 snd_mtxlock(sc->lock);
1571 if ((sc->chnum > ENVY24_CHAN_PLAY_SPDIF && dir != PCMDIR_REC) ||
1572 (sc->chnum < ENVY24_CHAN_REC_ADC1 && dir != PCMDIR_PLAY)) {
1573 snd_mtxunlock(sc->lock);
1574 return NULL;
1575 }
1576 num = sc->chnum;
1577
1578 ch = &sc->chan[num];
1579 ch->size = 8 * ENVY24_SAMPLE_NUM;
1580 ch->data = malloc(ch->size, M_ENVY24, M_NOWAIT);
1581 if (ch->data == NULL) {
1582 ch->size = 0;
1583 ch = NULL;
1584 }
1585 else {
1586 ch->buffer = b;
1587 ch->channel = c;
1588 ch->parent = sc;
1589 ch->dir = dir;
1590 /* set channel map */
1591 ch->num = envy24_chanmap[num];
1592 snd_mtxunlock(sc->lock);
1593 sndbuf_setup(ch->buffer, ch->data, ch->size);
1594 snd_mtxlock(sc->lock);
1595 /* these 2 values are dummy */
1596 ch->unit = 4;
1597 ch->blk = 10240;
1598 }
1599 snd_mtxunlock(sc->lock);
1600
1601 return ch;
1602 }
1603
1604 static int
envy24chan_free(kobj_t obj,void * data)1605 envy24chan_free(kobj_t obj, void *data)
1606 {
1607 struct sc_chinfo *ch = data;
1608 struct sc_info *sc = ch->parent;
1609
1610 #if(0)
1611 device_printf(sc->dev, "envy24chan_free()\n");
1612 #endif
1613 snd_mtxlock(sc->lock);
1614 if (ch->data != NULL) {
1615 free(ch->data, M_ENVY24);
1616 ch->data = NULL;
1617 }
1618 snd_mtxunlock(sc->lock);
1619
1620 return 0;
1621 }
1622
1623 static int
envy24chan_setformat(kobj_t obj,void * data,u_int32_t format)1624 envy24chan_setformat(kobj_t obj, void *data, u_int32_t format)
1625 {
1626 struct sc_chinfo *ch = data;
1627 struct sc_info *sc = ch->parent;
1628 struct envy24_emldma *emltab;
1629 /* unsigned int bcnt, bsize; */
1630 int i;
1631
1632 #if(0)
1633 device_printf(sc->dev, "envy24chan_setformat(obj, data, 0x%08x)\n", format);
1634 #endif
1635 snd_mtxlock(sc->lock);
1636 /* check and get format related information */
1637 if (ch->dir == PCMDIR_PLAY)
1638 emltab = envy24_pemltab;
1639 else
1640 emltab = envy24_remltab;
1641 if (emltab == NULL) {
1642 snd_mtxunlock(sc->lock);
1643 return -1;
1644 }
1645 for (i = 0; emltab[i].format != 0; i++)
1646 if (emltab[i].format == format)
1647 break;
1648 if (emltab[i].format == 0) {
1649 snd_mtxunlock(sc->lock);
1650 return -1;
1651 }
1652
1653 /* set format information */
1654 ch->format = format;
1655 ch->emldma = emltab[i].emldma;
1656 if (ch->unit > emltab[i].unit)
1657 ch->blk *= ch->unit / emltab[i].unit;
1658 else
1659 ch->blk /= emltab[i].unit / ch->unit;
1660 ch->unit = emltab[i].unit;
1661
1662 /* set channel buffer information */
1663 ch->size = ch->unit * ENVY24_SAMPLE_NUM;
1664 #if 0
1665 if (ch->dir == PCMDIR_PLAY)
1666 bsize = ch->blk * 4 / ENVY24_PLAY_BUFUNIT;
1667 else
1668 bsize = ch->blk * 4 / ENVY24_REC_BUFUNIT;
1669 bsize *= ch->unit;
1670 bcnt = ch->size / bsize;
1671 sndbuf_resize(ch->buffer, bcnt, bsize);
1672 #endif
1673 snd_mtxunlock(sc->lock);
1674
1675 #if(0)
1676 device_printf(sc->dev, "envy24chan_setformat(): return 0x%08x\n", 0);
1677 #endif
1678 return 0;
1679 }
1680
1681 /*
1682 IMPLEMENT NOTICE: In this driver, setspeed function only do setting
1683 of speed information value. And real hardware speed setting is done
1684 at start triggered(see envy24chan_trigger()). So, at this function
1685 is called, any value that ENVY24 can use is able to set. But, at
1686 start triggerd, some other channel is running, and that channel's
1687 speed isn't same with, then trigger function will fail.
1688 */
1689 static u_int32_t
envy24chan_setspeed(kobj_t obj,void * data,u_int32_t speed)1690 envy24chan_setspeed(kobj_t obj, void *data, u_int32_t speed)
1691 {
1692 struct sc_chinfo *ch = data;
1693 u_int32_t val, prev;
1694 int i;
1695
1696 #if(0)
1697 device_printf(ch->parent->dev, "envy24chan_setspeed(obj, data, %d)\n", speed);
1698 #endif
1699 prev = 0x7fffffff;
1700 for (i = 0; (val = envy24_speed[i]) != 0; i++) {
1701 if (abs(val - speed) < abs(prev - speed))
1702 prev = val;
1703 else
1704 break;
1705 }
1706 ch->speed = prev;
1707
1708 #if(0)
1709 device_printf(ch->parent->dev, "envy24chan_setspeed(): return %d\n", ch->speed);
1710 #endif
1711 return ch->speed;
1712 }
1713
1714 static u_int32_t
envy24chan_setblocksize(kobj_t obj,void * data,u_int32_t blocksize)1715 envy24chan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
1716 {
1717 struct sc_chinfo *ch = data;
1718 /* struct sc_info *sc = ch->parent; */
1719 u_int32_t size, prev;
1720 unsigned int bcnt, bsize;
1721
1722 #if(0)
1723 device_printf(sc->dev, "envy24chan_setblocksize(obj, data, %d)\n", blocksize);
1724 #endif
1725 prev = 0x7fffffff;
1726 /* snd_mtxlock(sc->lock); */
1727 for (size = ch->size / 2; size > 0; size /= 2) {
1728 if (abs(size - blocksize) < abs(prev - blocksize))
1729 prev = size;
1730 else
1731 break;
1732 }
1733
1734 ch->blk = prev / ch->unit;
1735 if (ch->dir == PCMDIR_PLAY)
1736 ch->blk *= ENVY24_PLAY_BUFUNIT / 4;
1737 else
1738 ch->blk *= ENVY24_REC_BUFUNIT / 4;
1739 /* set channel buffer information */
1740 /* ch->size = ch->unit * ENVY24_SAMPLE_NUM; */
1741 if (ch->dir == PCMDIR_PLAY)
1742 bsize = ch->blk * 4 / ENVY24_PLAY_BUFUNIT;
1743 else
1744 bsize = ch->blk * 4 / ENVY24_REC_BUFUNIT;
1745 bsize *= ch->unit;
1746 bcnt = ch->size / bsize;
1747 sndbuf_resize(ch->buffer, bcnt, bsize);
1748 /* snd_mtxunlock(sc->lock); */
1749
1750 #if(0)
1751 device_printf(sc->dev, "envy24chan_setblocksize(): return %d\n", prev);
1752 #endif
1753 return prev;
1754 }
1755
1756 /* semantic note: must start at beginning of buffer */
1757 static int
envy24chan_trigger(kobj_t obj,void * data,int go)1758 envy24chan_trigger(kobj_t obj, void *data, int go)
1759 {
1760 struct sc_chinfo *ch = data;
1761 struct sc_info *sc = ch->parent;
1762 u_int32_t ptr;
1763 int slot;
1764 int error = 0;
1765 #if 0
1766 int i;
1767
1768 device_printf(sc->dev, "envy24chan_trigger(obj, data, %d)\n", go);
1769 #endif
1770 snd_mtxlock(sc->lock);
1771 if (ch->dir == PCMDIR_PLAY)
1772 slot = 0;
1773 else
1774 slot = 1;
1775 switch (go) {
1776 case PCMTRIG_START:
1777 #if(0)
1778 device_printf(sc->dev, "envy24chan_trigger(): start\n");
1779 #endif
1780 /* check or set channel speed */
1781 if (sc->run[0] == 0 && sc->run[1] == 0) {
1782 sc->speed = envy24_setspeed(sc, ch->speed);
1783 sc->caps[0].minspeed = sc->caps[0].maxspeed = sc->speed;
1784 sc->caps[1].minspeed = sc->caps[1].maxspeed = sc->speed;
1785 }
1786 else if (ch->speed != 0 && ch->speed != sc->speed) {
1787 error = -1;
1788 goto fail;
1789 }
1790 if (ch->speed == 0)
1791 ch->channel->speed = sc->speed;
1792 /* start or enable channel */
1793 sc->run[slot]++;
1794 if (sc->run[slot] == 1) {
1795 /* first channel */
1796 ch->offset = 0;
1797 sc->blk[slot] = ch->blk;
1798 }
1799 else {
1800 ptr = envy24_gethwptr(sc, ch->dir);
1801 ch->offset = ((ptr / ch->blk + 1) * ch->blk %
1802 (ch->size / 4)) * 4 / ch->unit;
1803 if (ch->blk < sc->blk[slot])
1804 sc->blk[slot] = ch->blk;
1805 }
1806 if (ch->dir == PCMDIR_PLAY) {
1807 ch->emldma(ch);
1808 envy24_setvolume(sc, ch->num);
1809 }
1810 envy24_updintr(sc, ch->dir);
1811 if (sc->run[slot] == 1)
1812 envy24_start(sc, ch->dir);
1813 ch->run = 1;
1814 break;
1815 case PCMTRIG_EMLDMAWR:
1816 #if(0)
1817 device_printf(sc->dev, "envy24chan_trigger(): emldmawr\n");
1818 #endif
1819 if (ch->run != 1) {
1820 error = -1;
1821 goto fail;
1822 }
1823 ch->emldma(ch);
1824 break;
1825 case PCMTRIG_EMLDMARD:
1826 #if(0)
1827 device_printf(sc->dev, "envy24chan_trigger(): emldmard\n");
1828 #endif
1829 if (ch->run != 1) {
1830 error = -1;
1831 goto fail;
1832 }
1833 ch->emldma(ch);
1834 break;
1835 case PCMTRIG_ABORT:
1836 if (ch->run) {
1837 #if(0)
1838 device_printf(sc->dev, "envy24chan_trigger(): abort\n");
1839 #endif
1840 ch->run = 0;
1841 sc->run[slot]--;
1842 if (ch->dir == PCMDIR_PLAY)
1843 envy24_mutevolume(sc, ch->num);
1844 if (sc->run[slot] == 0) {
1845 envy24_stop(sc, ch->dir);
1846 sc->intr[slot] = 0;
1847 }
1848 #if 0
1849 else if (ch->blk == sc->blk[slot]) {
1850 sc->blk[slot] = ENVY24_SAMPLE_NUM / 2;
1851 for (i = 0; i < ENVY24_CHAN_NUM; i++) {
1852 if (sc->chan[i].dir == ch->dir &&
1853 sc->chan[i].run == 1 &&
1854 sc->chan[i].blk < sc->blk[slot])
1855 sc->blk[slot] = sc->chan[i].blk;
1856 }
1857 if (ch->blk != sc->blk[slot])
1858 envy24_updintr(sc, ch->dir);
1859 }
1860 #endif
1861 }
1862 break;
1863 }
1864 fail:
1865 snd_mtxunlock(sc->lock);
1866 return (error);
1867 }
1868
1869 static u_int32_t
envy24chan_getptr(kobj_t obj,void * data)1870 envy24chan_getptr(kobj_t obj, void *data)
1871 {
1872 struct sc_chinfo *ch = data;
1873 struct sc_info *sc = ch->parent;
1874 u_int32_t ptr, rtn;
1875
1876 #if(0)
1877 device_printf(sc->dev, "envy24chan_getptr()\n");
1878 #endif
1879 snd_mtxlock(sc->lock);
1880 ptr = envy24_gethwptr(sc, ch->dir);
1881 rtn = ptr * ch->unit;
1882 snd_mtxunlock(sc->lock);
1883
1884 #if(0)
1885 device_printf(sc->dev, "envy24chan_getptr(): return %d\n",
1886 rtn);
1887 #endif
1888 return rtn;
1889 }
1890
1891 static struct pcmchan_caps *
envy24chan_getcaps(kobj_t obj,void * data)1892 envy24chan_getcaps(kobj_t obj, void *data)
1893 {
1894 struct sc_chinfo *ch = data;
1895 struct sc_info *sc = ch->parent;
1896 struct pcmchan_caps *rtn;
1897
1898 #if(0)
1899 device_printf(sc->dev, "envy24chan_getcaps()\n");
1900 #endif
1901 snd_mtxlock(sc->lock);
1902 if (ch->dir == PCMDIR_PLAY) {
1903 if (sc->run[0] == 0)
1904 rtn = &envy24_playcaps;
1905 else
1906 rtn = &sc->caps[0];
1907 }
1908 else {
1909 if (sc->run[1] == 0)
1910 rtn = &envy24_reccaps;
1911 else
1912 rtn = &sc->caps[1];
1913 }
1914 snd_mtxunlock(sc->lock);
1915
1916 return rtn;
1917 }
1918
1919 static kobj_method_t envy24chan_methods[] = {
1920 KOBJMETHOD(channel_init, envy24chan_init),
1921 KOBJMETHOD(channel_free, envy24chan_free),
1922 KOBJMETHOD(channel_setformat, envy24chan_setformat),
1923 KOBJMETHOD(channel_setspeed, envy24chan_setspeed),
1924 KOBJMETHOD(channel_setblocksize, envy24chan_setblocksize),
1925 KOBJMETHOD(channel_trigger, envy24chan_trigger),
1926 KOBJMETHOD(channel_getptr, envy24chan_getptr),
1927 KOBJMETHOD(channel_getcaps, envy24chan_getcaps),
1928 KOBJMETHOD_END
1929 };
1930 CHANNEL_DECLARE(envy24chan);
1931
1932 /* -------------------------------------------------------------------- */
1933
1934 /* mixer interface */
1935
1936 static int
envy24mixer_init(struct snd_mixer * m)1937 envy24mixer_init(struct snd_mixer *m)
1938 {
1939 struct sc_info *sc = mix_getdevinfo(m);
1940
1941 #if(0)
1942 device_printf(sc->dev, "envy24mixer_init()\n");
1943 #endif
1944 if (sc == NULL)
1945 return -1;
1946
1947 /* set volume control rate */
1948 snd_mtxlock(sc->lock);
1949 envy24_wrmt(sc, ENVY24_MT_VOLRATE, 0x30, 1); /* 0x30 is default value */
1950
1951 mix_setdevs(m, ENVY24_MIX_MASK);
1952 mix_setrecdevs(m, ENVY24_MIX_REC_MASK);
1953 snd_mtxunlock(sc->lock);
1954
1955 return 0;
1956 }
1957
1958 static int
envy24mixer_reinit(struct snd_mixer * m)1959 envy24mixer_reinit(struct snd_mixer *m)
1960 {
1961 struct sc_info *sc = mix_getdevinfo(m);
1962
1963 if (sc == NULL)
1964 return -1;
1965 #if(0)
1966 device_printf(sc->dev, "envy24mixer_reinit()\n");
1967 #endif
1968
1969 return 0;
1970 }
1971
1972 static int
envy24mixer_uninit(struct snd_mixer * m)1973 envy24mixer_uninit(struct snd_mixer *m)
1974 {
1975 struct sc_info *sc = mix_getdevinfo(m);
1976
1977 if (sc == NULL)
1978 return -1;
1979 #if(0)
1980 device_printf(sc->dev, "envy24mixer_uninit()\n");
1981 #endif
1982
1983 return 0;
1984 }
1985
1986 static int
envy24mixer_set(struct snd_mixer * m,unsigned dev,unsigned left,unsigned right)1987 envy24mixer_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right)
1988 {
1989 struct sc_info *sc = mix_getdevinfo(m);
1990 int ch = envy24_mixmap[dev];
1991 int hwch;
1992 int i;
1993
1994 if (sc == NULL)
1995 return -1;
1996 if (dev == 0 && sc->cfg->codec->setvolume == NULL)
1997 return -1;
1998 if (dev != 0 && ch == -1)
1999 return -1;
2000 hwch = envy24_chanmap[ch];
2001 #if(0)
2002 device_printf(sc->dev, "envy24mixer_set(m, %d, %d, %d)\n",
2003 dev, left, right);
2004 #endif
2005
2006 snd_mtxlock(sc->lock);
2007 if (dev == 0) {
2008 for (i = 0; i < sc->dacn; i++) {
2009 sc->cfg->codec->setvolume(sc->dac[i], PCMDIR_PLAY, left, right);
2010 }
2011 }
2012 else {
2013 /* set volume value for hardware */
2014 if ((sc->left[hwch] = 100 - left) > ENVY24_VOL_MIN)
2015 sc->left[hwch] = ENVY24_VOL_MUTE;
2016 if ((sc->right[hwch] = 100 - right) > ENVY24_VOL_MIN)
2017 sc->right[hwch] = ENVY24_VOL_MUTE;
2018
2019 /* set volume for record channel and running play channel */
2020 if (hwch > ENVY24_CHAN_PLAY_SPDIF || sc->chan[ch].run)
2021 envy24_setvolume(sc, hwch);
2022 }
2023 snd_mtxunlock(sc->lock);
2024
2025 return right << 8 | left;
2026 }
2027
2028 static u_int32_t
envy24mixer_setrecsrc(struct snd_mixer * m,u_int32_t src)2029 envy24mixer_setrecsrc(struct snd_mixer *m, u_int32_t src)
2030 {
2031 struct sc_info *sc = mix_getdevinfo(m);
2032 int ch = envy24_mixmap[src];
2033 #if(0)
2034 device_printf(sc->dev, "envy24mixer_setrecsrc(m, %d)\n", src);
2035 #endif
2036
2037 if (ch > ENVY24_CHAN_PLAY_SPDIF)
2038 sc->src = ch;
2039 return src;
2040 }
2041
2042 static kobj_method_t envy24mixer_methods[] = {
2043 KOBJMETHOD(mixer_init, envy24mixer_init),
2044 KOBJMETHOD(mixer_reinit, envy24mixer_reinit),
2045 KOBJMETHOD(mixer_uninit, envy24mixer_uninit),
2046 KOBJMETHOD(mixer_set, envy24mixer_set),
2047 KOBJMETHOD(mixer_setrecsrc, envy24mixer_setrecsrc),
2048 KOBJMETHOD_END
2049 };
2050 MIXER_DECLARE(envy24mixer);
2051
2052 /* -------------------------------------------------------------------- */
2053
2054 /* The interrupt handler */
2055 static void
envy24_intr(void * p)2056 envy24_intr(void *p)
2057 {
2058 struct sc_info *sc = (struct sc_info *)p;
2059 struct sc_chinfo *ch;
2060 u_int32_t ptr, dsize, feed;
2061 int i;
2062
2063 #if(0)
2064 device_printf(sc->dev, "envy24_intr()\n");
2065 #endif
2066 snd_mtxlock(sc->lock);
2067 if (envy24_checkintr(sc, PCMDIR_PLAY)) {
2068 #if(0)
2069 device_printf(sc->dev, "envy24_intr(): play\n");
2070 #endif
2071 dsize = sc->psize / 4;
2072 ptr = dsize - envy24_rdmt(sc, ENVY24_MT_PCNT, 2) - 1;
2073 #if(0)
2074 device_printf(sc->dev, "envy24_intr(): ptr = %d-->", ptr);
2075 #endif
2076 ptr -= ptr % sc->blk[0];
2077 feed = (ptr + dsize - sc->intr[0]) % dsize;
2078 #if(0)
2079 printf("%d intr = %d feed = %d\n", ptr, sc->intr[0], feed);
2080 #endif
2081 for (i = ENVY24_CHAN_PLAY_DAC1; i <= ENVY24_CHAN_PLAY_SPDIF; i++) {
2082 ch = &sc->chan[i];
2083 #if(0)
2084 if (ch->run)
2085 device_printf(sc->dev, "envy24_intr(): chan[%d].blk = %d\n", i, ch->blk);
2086 #endif
2087 if (ch->run && ch->blk <= feed) {
2088 snd_mtxunlock(sc->lock);
2089 chn_intr(ch->channel);
2090 snd_mtxlock(sc->lock);
2091 }
2092 }
2093 sc->intr[0] = ptr;
2094 envy24_updintr(sc, PCMDIR_PLAY);
2095 }
2096 if (envy24_checkintr(sc, PCMDIR_REC)) {
2097 #if(0)
2098 device_printf(sc->dev, "envy24_intr(): rec\n");
2099 #endif
2100 dsize = sc->rsize / 4;
2101 ptr = dsize - envy24_rdmt(sc, ENVY24_MT_RCNT, 2) - 1;
2102 ptr -= ptr % sc->blk[1];
2103 feed = (ptr + dsize - sc->intr[1]) % dsize;
2104 for (i = ENVY24_CHAN_REC_ADC1; i <= ENVY24_CHAN_REC_SPDIF; i++) {
2105 ch = &sc->chan[i];
2106 if (ch->run && ch->blk <= feed) {
2107 snd_mtxunlock(sc->lock);
2108 chn_intr(ch->channel);
2109 snd_mtxlock(sc->lock);
2110 }
2111 }
2112 sc->intr[1] = ptr;
2113 envy24_updintr(sc, PCMDIR_REC);
2114 }
2115 snd_mtxunlock(sc->lock);
2116
2117 return;
2118 }
2119
2120 /*
2121 * Probe and attach the card
2122 */
2123
2124 static int
envy24_pci_probe(device_t dev)2125 envy24_pci_probe(device_t dev)
2126 {
2127 u_int16_t sv, sd;
2128 int i;
2129
2130 #if(0)
2131 printf("envy24_pci_probe()\n");
2132 #endif
2133 if (pci_get_device(dev) == PCID_ENVY24 &&
2134 pci_get_vendor(dev) == PCIV_ENVY24) {
2135 sv = pci_get_subvendor(dev);
2136 sd = pci_get_subdevice(dev);
2137 for (i = 0; cfg_table[i].subvendor != 0 || cfg_table[i].subdevice != 0; i++) {
2138 if (cfg_table[i].subvendor == sv &&
2139 cfg_table[i].subdevice == sd) {
2140 break;
2141 }
2142 }
2143 device_set_desc(dev, cfg_table[i].name);
2144 #if(0)
2145 printf("envy24_pci_probe(): return 0\n");
2146 #endif
2147 return 0;
2148 }
2149 else {
2150 #if(0)
2151 printf("envy24_pci_probe(): return ENXIO\n");
2152 #endif
2153 return ENXIO;
2154 }
2155 }
2156
2157 static void
envy24_dmapsetmap(void * arg,bus_dma_segment_t * segs,int nseg,int error)2158 envy24_dmapsetmap(void *arg, bus_dma_segment_t *segs, int nseg, int error)
2159 {
2160 struct sc_info *sc = (struct sc_info *)arg;
2161
2162 sc->paddr = segs->ds_addr;
2163 #if(0)
2164 device_printf(sc->dev, "envy24_dmapsetmap()\n");
2165 if (bootverbose) {
2166 printf("envy24(play): setmap %lx, %lx; ",
2167 (unsigned long)segs->ds_addr,
2168 (unsigned long)segs->ds_len);
2169 printf("%p -> %lx\n", sc->pmap, sc->paddr);
2170 }
2171 #endif
2172 }
2173
2174 static void
envy24_dmarsetmap(void * arg,bus_dma_segment_t * segs,int nseg,int error)2175 envy24_dmarsetmap(void *arg, bus_dma_segment_t *segs, int nseg, int error)
2176 {
2177 struct sc_info *sc = (struct sc_info *)arg;
2178
2179 sc->raddr = segs->ds_addr;
2180 #if(0)
2181 device_printf(sc->dev, "envy24_dmarsetmap()\n");
2182 if (bootverbose) {
2183 printf("envy24(record): setmap %lx, %lx; ",
2184 (unsigned long)segs->ds_addr,
2185 (unsigned long)segs->ds_len);
2186 printf("%p -> %lx\n", sc->rmap, sc->raddr);
2187 }
2188 #endif
2189 }
2190
2191 static void
envy24_dmafree(struct sc_info * sc)2192 envy24_dmafree(struct sc_info *sc)
2193 {
2194 #if(0)
2195 device_printf(sc->dev, "envy24_dmafree():");
2196 printf(" sc->raddr(0x%08x)", (u_int32_t)sc->raddr);
2197 printf(" sc->paddr(0x%08x)", (u_int32_t)sc->paddr);
2198 if (sc->rbuf) printf(" sc->rbuf(0x%08x)", (u_int32_t)sc->rbuf);
2199 else printf(" sc->rbuf(null)");
2200 if (sc->pbuf) printf(" sc->pbuf(0x%08x)\n", (u_int32_t)sc->pbuf);
2201 else printf(" sc->pbuf(null)\n");
2202 #endif
2203 #if(0)
2204 if (sc->raddr)
2205 bus_dmamap_unload(sc->dmat, sc->rmap);
2206 if (sc->paddr)
2207 bus_dmamap_unload(sc->dmat, sc->pmap);
2208 if (sc->rbuf)
2209 bus_dmamem_free(sc->dmat, sc->rbuf, sc->rmap);
2210 if (sc->pbuf)
2211 bus_dmamem_free(sc->dmat, sc->pbuf, sc->pmap);
2212 #else
2213 bus_dmamap_unload(sc->dmat, sc->rmap);
2214 bus_dmamap_unload(sc->dmat, sc->pmap);
2215 bus_dmamem_free(sc->dmat, sc->rbuf, sc->rmap);
2216 bus_dmamem_free(sc->dmat, sc->pbuf, sc->pmap);
2217 #endif
2218
2219 sc->raddr = sc->paddr = 0;
2220 sc->pbuf = NULL;
2221 sc->rbuf = NULL;
2222
2223 return;
2224 }
2225
2226 static int
envy24_dmainit(struct sc_info * sc)2227 envy24_dmainit(struct sc_info *sc)
2228 {
2229
2230 #if(0)
2231 device_printf(sc->dev, "envy24_dmainit()\n");
2232 #endif
2233 /* init values */
2234 sc->psize = ENVY24_PLAY_BUFUNIT * ENVY24_SAMPLE_NUM;
2235 sc->rsize = ENVY24_REC_BUFUNIT * ENVY24_SAMPLE_NUM;
2236 sc->pbuf = NULL;
2237 sc->rbuf = NULL;
2238 sc->paddr = sc->raddr = 0;
2239 sc->blk[0] = sc->blk[1] = 0;
2240
2241 /* allocate DMA buffer */
2242 #if(0)
2243 device_printf(sc->dev, "envy24_dmainit(): bus_dmamem_alloc(): sc->pbuf\n");
2244 #endif
2245 if (bus_dmamem_alloc(sc->dmat, (void **)&sc->pbuf, BUS_DMA_NOWAIT, &sc->pmap))
2246 goto bad;
2247 #if(0)
2248 device_printf(sc->dev, "envy24_dmainit(): bus_dmamem_alloc(): sc->rbuf\n");
2249 #endif
2250 if (bus_dmamem_alloc(sc->dmat, (void **)&sc->rbuf, BUS_DMA_NOWAIT, &sc->rmap))
2251 goto bad;
2252 #if(0)
2253 device_printf(sc->dev, "envy24_dmainit(): bus_dmamem_load(): sc->pmap\n");
2254 #endif
2255 if (bus_dmamap_load(sc->dmat, sc->pmap, sc->pbuf, sc->psize,
2256 envy24_dmapsetmap, sc, BUS_DMA_NOWAIT))
2257 goto bad;
2258 #if(0)
2259 device_printf(sc->dev, "envy24_dmainit(): bus_dmamem_load(): sc->rmap\n");
2260 #endif
2261 if (bus_dmamap_load(sc->dmat, sc->rmap, sc->rbuf, sc->rsize,
2262 envy24_dmarsetmap, sc, BUS_DMA_NOWAIT))
2263 goto bad;
2264 bzero(sc->pbuf, sc->psize);
2265 bzero(sc->rbuf, sc->rsize);
2266
2267 /* set values to register */
2268 #if(0)
2269 device_printf(sc->dev, "paddr(0x%08x)\n", sc->paddr);
2270 #endif
2271 envy24_wrmt(sc, ENVY24_MT_PADDR, sc->paddr, 4);
2272 #if(0)
2273 device_printf(sc->dev, "PADDR-->(0x%08x)\n", envy24_rdmt(sc, ENVY24_MT_PADDR, 4));
2274 device_printf(sc->dev, "psize(%ld)\n", sc->psize / 4 - 1);
2275 #endif
2276 envy24_wrmt(sc, ENVY24_MT_PCNT, sc->psize / 4 - 1, 2);
2277 #if(0)
2278 device_printf(sc->dev, "PCNT-->(%ld)\n", envy24_rdmt(sc, ENVY24_MT_PCNT, 2));
2279 #endif
2280 envy24_wrmt(sc, ENVY24_MT_RADDR, sc->raddr, 4);
2281 envy24_wrmt(sc, ENVY24_MT_RCNT, sc->rsize / 4 - 1, 2);
2282
2283 return 0;
2284 bad:
2285 envy24_dmafree(sc);
2286 return ENOSPC;
2287 }
2288
2289 static void
envy24_putcfg(struct sc_info * sc)2290 envy24_putcfg(struct sc_info *sc)
2291 {
2292 device_printf(sc->dev, "system configuration\n");
2293 printf(" SubVendorID: 0x%04x, SubDeviceID: 0x%04x\n",
2294 sc->cfg->subvendor, sc->cfg->subdevice);
2295 printf(" XIN2 Clock Source: ");
2296 switch (sc->cfg->scfg & PCIM_SCFG_XIN2) {
2297 case 0x00:
2298 printf("22.5792MHz(44.1kHz*512)\n");
2299 break;
2300 case 0x40:
2301 printf("16.9344MHz(44.1kHz*384)\n");
2302 break;
2303 case 0x80:
2304 printf("from external clock synthesizer chip\n");
2305 break;
2306 default:
2307 printf("illegal system setting\n");
2308 }
2309 printf(" MPU-401 UART(s) #: ");
2310 if (sc->cfg->scfg & PCIM_SCFG_MPU)
2311 printf("2\n");
2312 else
2313 printf("1\n");
2314 printf(" AC'97 codec: ");
2315 if (sc->cfg->scfg & PCIM_SCFG_AC97)
2316 printf("not exist\n");
2317 else
2318 printf("exist\n");
2319 printf(" ADC #: ");
2320 printf("%d\n", sc->adcn);
2321 printf(" DAC #: ");
2322 printf("%d\n", sc->dacn);
2323 printf(" Multi-track converter type: ");
2324 if ((sc->cfg->acl & PCIM_ACL_MTC) == 0) {
2325 printf("AC'97(SDATA_OUT:");
2326 if (sc->cfg->acl & PCIM_ACL_OMODE)
2327 printf("packed");
2328 else
2329 printf("split");
2330 printf("|SDATA_IN:");
2331 if (sc->cfg->acl & PCIM_ACL_IMODE)
2332 printf("packed");
2333 else
2334 printf("split");
2335 printf(")\n");
2336 }
2337 else {
2338 printf("I2S(");
2339 if (sc->cfg->i2s & PCIM_I2S_VOL)
2340 printf("with volume, ");
2341 if (sc->cfg->i2s & PCIM_I2S_96KHZ)
2342 printf("96KHz support, ");
2343 switch (sc->cfg->i2s & PCIM_I2S_RES) {
2344 case PCIM_I2S_16BIT:
2345 printf("16bit resolution, ");
2346 break;
2347 case PCIM_I2S_18BIT:
2348 printf("18bit resolution, ");
2349 break;
2350 case PCIM_I2S_20BIT:
2351 printf("20bit resolution, ");
2352 break;
2353 case PCIM_I2S_24BIT:
2354 printf("24bit resolution, ");
2355 break;
2356 }
2357 printf("ID#0x%x)\n", sc->cfg->i2s & PCIM_I2S_ID);
2358 }
2359 printf(" S/PDIF(IN/OUT): ");
2360 if (sc->cfg->spdif & PCIM_SPDIF_IN)
2361 printf("1/");
2362 else
2363 printf("0/");
2364 if (sc->cfg->spdif & PCIM_SPDIF_OUT)
2365 printf("1 ");
2366 else
2367 printf("0 ");
2368 if (sc->cfg->spdif & (PCIM_SPDIF_IN | PCIM_SPDIF_OUT))
2369 printf("ID# 0x%02x\n", (sc->cfg->spdif & PCIM_SPDIF_ID) >> 2);
2370 printf(" GPIO(mask/dir/state): 0x%02x/0x%02x/0x%02x\n",
2371 sc->cfg->gpiomask, sc->cfg->gpiodir, sc->cfg->gpiostate);
2372 }
2373
2374 static int
envy24_init(struct sc_info * sc)2375 envy24_init(struct sc_info *sc)
2376 {
2377 u_int32_t data;
2378 #if(0)
2379 int rtn;
2380 #endif
2381 int i;
2382 u_int32_t sv, sd;
2383
2384 #if(0)
2385 device_printf(sc->dev, "envy24_init()\n");
2386 #endif
2387
2388 /* reset chip */
2389 envy24_wrcs(sc, ENVY24_CCS_CTL, ENVY24_CCS_CTL_RESET | ENVY24_CCS_CTL_NATIVE, 1);
2390 DELAY(200);
2391 envy24_wrcs(sc, ENVY24_CCS_CTL, ENVY24_CCS_CTL_NATIVE, 1);
2392 DELAY(200);
2393
2394 /* legacy hardware disable */
2395 data = pci_read_config(sc->dev, PCIR_LAC, 2);
2396 data |= PCIM_LAC_DISABLE;
2397 pci_write_config(sc->dev, PCIR_LAC, data, 2);
2398
2399 /* check system configuration */
2400 sc->cfg = NULL;
2401 for (i = 0; cfg_table[i].subvendor != 0 || cfg_table[i].subdevice != 0; i++) {
2402 /* 1st: search configuration from table */
2403 sv = pci_get_subvendor(sc->dev);
2404 sd = pci_get_subdevice(sc->dev);
2405 if (sv == cfg_table[i].subvendor && sd == cfg_table[i].subdevice) {
2406 #if(0)
2407 device_printf(sc->dev, "Set configuration from table\n");
2408 #endif
2409 sc->cfg = &cfg_table[i];
2410 break;
2411 }
2412 }
2413 if (sc->cfg == NULL) {
2414 /* 2nd: read configuration from table */
2415 sc->cfg = envy24_rom2cfg(sc);
2416 }
2417 sc->adcn = ((sc->cfg->scfg & PCIM_SCFG_ADC) >> 2) + 1;
2418 sc->dacn = (sc->cfg->scfg & PCIM_SCFG_DAC) + 1;
2419
2420 if (1 /* bootverbose */) {
2421 envy24_putcfg(sc);
2422 }
2423
2424 /* set system configuration */
2425 pci_write_config(sc->dev, PCIR_SCFG, sc->cfg->scfg, 1);
2426 pci_write_config(sc->dev, PCIR_ACL, sc->cfg->acl, 1);
2427 pci_write_config(sc->dev, PCIR_I2S, sc->cfg->i2s, 1);
2428 pci_write_config(sc->dev, PCIR_SPDIF, sc->cfg->spdif, 1);
2429 envy24_gpiosetmask(sc, sc->cfg->gpiomask);
2430 envy24_gpiosetdir(sc, sc->cfg->gpiodir);
2431 envy24_gpiowr(sc, sc->cfg->gpiostate);
2432 for (i = 0; i < sc->adcn; i++) {
2433 sc->adc[i] = sc->cfg->codec->create(sc->dev, sc, PCMDIR_REC, i);
2434 sc->cfg->codec->init(sc->adc[i]);
2435 }
2436 for (i = 0; i < sc->dacn; i++) {
2437 sc->dac[i] = sc->cfg->codec->create(sc->dev, sc, PCMDIR_PLAY, i);
2438 sc->cfg->codec->init(sc->dac[i]);
2439 }
2440
2441 /* initialize DMA buffer */
2442 #if(0)
2443 device_printf(sc->dev, "envy24_init(): initialize DMA buffer\n");
2444 #endif
2445 if (envy24_dmainit(sc))
2446 return ENOSPC;
2447
2448 /* initialize status */
2449 sc->run[0] = sc->run[1] = 0;
2450 sc->intr[0] = sc->intr[1] = 0;
2451 sc->speed = 0;
2452 sc->caps[0].fmtlist = envy24_playfmt;
2453 sc->caps[1].fmtlist = envy24_recfmt;
2454
2455 /* set channel router */
2456 envy24_route(sc, ENVY24_ROUTE_DAC_1, ENVY24_ROUTE_CLASS_MIX, 0, 0);
2457 envy24_route(sc, ENVY24_ROUTE_DAC_SPDIF, ENVY24_ROUTE_CLASS_DMA, 0, 0);
2458 /* envy24_route(sc, ENVY24_ROUTE_DAC_SPDIF, ENVY24_ROUTE_CLASS_MIX, 0, 0); */
2459
2460 /* set macro interrupt mask */
2461 data = envy24_rdcs(sc, ENVY24_CCS_IMASK, 1);
2462 envy24_wrcs(sc, ENVY24_CCS_IMASK, data & ~ENVY24_CCS_IMASK_PMT, 1);
2463 data = envy24_rdcs(sc, ENVY24_CCS_IMASK, 1);
2464 #if(0)
2465 device_printf(sc->dev, "envy24_init(): CCS_IMASK-->0x%02x\n", data);
2466 #endif
2467
2468 return 0;
2469 }
2470
2471 static int
envy24_alloc_resource(struct sc_info * sc)2472 envy24_alloc_resource(struct sc_info *sc)
2473 {
2474 /* allocate I/O port resource */
2475 sc->csid = PCIR_CCS;
2476 sc->cs = bus_alloc_resource_any(sc->dev, SYS_RES_IOPORT,
2477 &sc->csid, RF_ACTIVE);
2478 sc->ddmaid = PCIR_DDMA;
2479 sc->ddma = bus_alloc_resource_any(sc->dev, SYS_RES_IOPORT,
2480 &sc->ddmaid, RF_ACTIVE);
2481 sc->dsid = PCIR_DS;
2482 sc->ds = bus_alloc_resource_any(sc->dev, SYS_RES_IOPORT,
2483 &sc->dsid, RF_ACTIVE);
2484 sc->mtid = PCIR_MT;
2485 sc->mt = bus_alloc_resource_any(sc->dev, SYS_RES_IOPORT,
2486 &sc->mtid, RF_ACTIVE);
2487 if (!sc->cs || !sc->ddma || !sc->ds || !sc->mt) {
2488 device_printf(sc->dev, "unable to map IO port space\n");
2489 return ENXIO;
2490 }
2491 sc->cst = rman_get_bustag(sc->cs);
2492 sc->csh = rman_get_bushandle(sc->cs);
2493 sc->ddmat = rman_get_bustag(sc->ddma);
2494 sc->ddmah = rman_get_bushandle(sc->ddma);
2495 sc->dst = rman_get_bustag(sc->ds);
2496 sc->dsh = rman_get_bushandle(sc->ds);
2497 sc->mtt = rman_get_bustag(sc->mt);
2498 sc->mth = rman_get_bushandle(sc->mt);
2499 #if(0)
2500 device_printf(sc->dev,
2501 "IO port register values\nCCS: 0x%lx\nDDMA: 0x%lx\nDS: 0x%lx\nMT: 0x%lx\n",
2502 pci_read_config(sc->dev, PCIR_CCS, 4),
2503 pci_read_config(sc->dev, PCIR_DDMA, 4),
2504 pci_read_config(sc->dev, PCIR_DS, 4),
2505 pci_read_config(sc->dev, PCIR_MT, 4));
2506 #endif
2507
2508 /* allocate interrupt resource */
2509 sc->irqid = 0;
2510 sc->irq = bus_alloc_resource_any(sc->dev, SYS_RES_IRQ, &sc->irqid,
2511 RF_ACTIVE | RF_SHAREABLE);
2512 if (!sc->irq ||
2513 snd_setup_intr(sc->dev, sc->irq, INTR_MPSAFE, envy24_intr, sc, &sc->ih)) {
2514 device_printf(sc->dev, "unable to map interrupt\n");
2515 return ENXIO;
2516 }
2517
2518 /* allocate DMA resource */
2519 if (bus_dma_tag_create(/*parent*/bus_get_dma_tag(sc->dev),
2520 /*alignment*/4,
2521 /*boundary*/0,
2522 /*lowaddr*/BUS_SPACE_MAXADDR_ENVY24,
2523 /*highaddr*/BUS_SPACE_MAXADDR_ENVY24,
2524 /*filter*/NULL, /*filterarg*/NULL,
2525 /*maxsize*/BUS_SPACE_MAXSIZE_ENVY24,
2526 /*nsegments*/1, /*maxsegsz*/0x3ffff,
2527 /*flags*/0, /*lockfunc*/NULL, /*lockarg*/NULL,
2528 &sc->dmat) != 0) {
2529 device_printf(sc->dev, "unable to create dma tag\n");
2530 return ENXIO;
2531 }
2532
2533 return 0;
2534 }
2535
2536 static int
envy24_pci_attach(device_t dev)2537 envy24_pci_attach(device_t dev)
2538 {
2539 struct sc_info *sc;
2540 char status[SND_STATUSLEN];
2541 int err = 0;
2542 int i;
2543
2544 #if(0)
2545 device_printf(dev, "envy24_pci_attach()\n");
2546 #endif
2547 /* get sc_info data area */
2548 if ((sc = malloc(sizeof(*sc), M_ENVY24, M_NOWAIT)) == NULL) {
2549 device_printf(dev, "cannot allocate softc\n");
2550 return ENXIO;
2551 }
2552
2553 bzero(sc, sizeof(*sc));
2554 sc->lock = snd_mtxcreate(device_get_nameunit(dev), "snd_envy24 softc");
2555 sc->dev = dev;
2556
2557 /* initialize PCI interface */
2558 pci_enable_busmaster(dev);
2559
2560 /* allocate resources */
2561 err = envy24_alloc_resource(sc);
2562 if (err) {
2563 device_printf(dev, "unable to allocate system resources\n");
2564 goto bad;
2565 }
2566
2567 /* initialize card */
2568 err = envy24_init(sc);
2569 if (err) {
2570 device_printf(dev, "unable to initialize the card\n");
2571 goto bad;
2572 }
2573
2574 /* set multi track mixer */
2575 mixer_init(dev, &envy24mixer_class, sc);
2576
2577 /* set channel information */
2578 pcm_init(dev, sc);
2579 sc->chnum = 0;
2580 for (i = 0; i < 5; i++) {
2581 pcm_addchan(dev, PCMDIR_PLAY, &envy24chan_class, sc);
2582 sc->chnum++;
2583 }
2584 for (i = 0; i < 2 + sc->adcn; i++) {
2585 pcm_addchan(dev, PCMDIR_REC, &envy24chan_class, sc);
2586 sc->chnum++;
2587 }
2588
2589 /* set status iformation */
2590 snprintf(status, SND_STATUSLEN,
2591 "port 0x%jx:%jd,0x%jx:%jd,0x%jx:%jd,0x%jx:%jd irq %jd on %s",
2592 rman_get_start(sc->cs),
2593 rman_get_end(sc->cs) - rman_get_start(sc->cs) + 1,
2594 rman_get_start(sc->ddma),
2595 rman_get_end(sc->ddma) - rman_get_start(sc->ddma) + 1,
2596 rman_get_start(sc->ds),
2597 rman_get_end(sc->ds) - rman_get_start(sc->ds) + 1,
2598 rman_get_start(sc->mt),
2599 rman_get_end(sc->mt) - rman_get_start(sc->mt) + 1,
2600 rman_get_start(sc->irq),
2601 device_get_nameunit(device_get_parent(dev)));
2602 if (pcm_register(dev, status))
2603 goto bad;
2604
2605 return 0;
2606
2607 bad:
2608 if (sc->ih)
2609 bus_teardown_intr(dev, sc->irq, sc->ih);
2610 if (sc->irq)
2611 bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq);
2612 envy24_dmafree(sc);
2613 if (sc->dmat)
2614 bus_dma_tag_destroy(sc->dmat);
2615 if (sc->cfg->codec->destroy != NULL) {
2616 for (i = 0; i < sc->adcn; i++)
2617 sc->cfg->codec->destroy(sc->adc[i]);
2618 for (i = 0; i < sc->dacn; i++)
2619 sc->cfg->codec->destroy(sc->dac[i]);
2620 }
2621 envy24_cfgfree(sc->cfg);
2622 if (sc->cs)
2623 bus_release_resource(dev, SYS_RES_IOPORT, sc->csid, sc->cs);
2624 if (sc->ddma)
2625 bus_release_resource(dev, SYS_RES_IOPORT, sc->ddmaid, sc->ddma);
2626 if (sc->ds)
2627 bus_release_resource(dev, SYS_RES_IOPORT, sc->dsid, sc->ds);
2628 if (sc->mt)
2629 bus_release_resource(dev, SYS_RES_IOPORT, sc->mtid, sc->mt);
2630 if (sc->lock)
2631 snd_mtxfree(sc->lock);
2632 free(sc, M_ENVY24);
2633 return err;
2634 }
2635
2636 static int
envy24_pci_detach(device_t dev)2637 envy24_pci_detach(device_t dev)
2638 {
2639 struct sc_info *sc;
2640 int r;
2641 int i;
2642
2643 #if(0)
2644 device_printf(dev, "envy24_pci_detach()\n");
2645 #endif
2646 sc = pcm_getdevinfo(dev);
2647 if (sc == NULL)
2648 return 0;
2649 r = pcm_unregister(dev);
2650 if (r)
2651 return r;
2652
2653 envy24_dmafree(sc);
2654 if (sc->cfg->codec->destroy != NULL) {
2655 for (i = 0; i < sc->adcn; i++)
2656 sc->cfg->codec->destroy(sc->adc[i]);
2657 for (i = 0; i < sc->dacn; i++)
2658 sc->cfg->codec->destroy(sc->dac[i]);
2659 }
2660 envy24_cfgfree(sc->cfg);
2661 bus_dma_tag_destroy(sc->dmat);
2662 bus_teardown_intr(dev, sc->irq, sc->ih);
2663 bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq);
2664 bus_release_resource(dev, SYS_RES_IOPORT, sc->csid, sc->cs);
2665 bus_release_resource(dev, SYS_RES_IOPORT, sc->ddmaid, sc->ddma);
2666 bus_release_resource(dev, SYS_RES_IOPORT, sc->dsid, sc->ds);
2667 bus_release_resource(dev, SYS_RES_IOPORT, sc->mtid, sc->mt);
2668 snd_mtxfree(sc->lock);
2669 free(sc, M_ENVY24);
2670 return 0;
2671 }
2672
2673 static device_method_t envy24_methods[] = {
2674 /* Device interface */
2675 DEVMETHOD(device_probe, envy24_pci_probe),
2676 DEVMETHOD(device_attach, envy24_pci_attach),
2677 DEVMETHOD(device_detach, envy24_pci_detach),
2678 { 0, 0 }
2679 };
2680
2681 static driver_t envy24_driver = {
2682 "pcm",
2683 envy24_methods,
2684 PCM_SOFTC_SIZE,
2685 };
2686
2687 DRIVER_MODULE(snd_envy24, pci, envy24_driver, 0, 0);
2688 MODULE_DEPEND(snd_envy24, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER);
2689 MODULE_DEPEND(snd_envy24, snd_spicds, 1, 1, 1);
2690 MODULE_VERSION(snd_envy24, 1);
2691