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
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 = 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
envy24_cfgfree(struct cfg_info * cfg)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
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 = 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
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 kfree(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 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
envy24_checkintr(struct sc_info * sc,int dir)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
envy24_start(struct sc_info * sc,int dir)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
envy24_stop(struct sc_info * sc,int dir)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
envy24_route(struct sc_info * sc,int dac,int class,int adc,int rev)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
envy24_p32sl(struct sc_chinfo * ch)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
envy24_p16sl(struct sc_chinfo * ch)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
envy24_p8u(struct sc_chinfo * ch)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
envy24_r32sl(struct sc_chinfo * ch)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
envy24_r16sl(struct sc_chinfo * ch)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 *
envy24chan_init(kobj_t obj,void * devinfo,struct snd_dbuf * b,struct pcm_channel * c,int dir)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
envy24chan_free(kobj_t obj,void * data)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
envy24chan_setformat(kobj_t obj,void * data,u_int32_t format)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
envy24chan_setspeed(kobj_t obj,void * data,u_int32_t speed)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
envy24chan_setblocksize(kobj_t obj,void * data,u_int32_t blocksize)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
envy24chan_trigger(kobj_t obj,void * data,int go)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
envy24chan_getptr(kobj_t obj,void * data)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 *
envy24chan_getcaps(kobj_t obj,void * data)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
envy24mixer_init(struct snd_mixer * m)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
envy24mixer_reinit(struct snd_mixer * m)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
envy24mixer_uninit(struct snd_mixer * m)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
envy24mixer_set(struct snd_mixer * m,unsigned dev,unsigned left,unsigned right)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
envy24mixer_setrecsrc(struct snd_mixer * m,u_int32_t src)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
envy24_intr(void * p)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
envy24_pci_probe(device_t dev)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
envy24_dmapsetmap(void * arg,bus_dma_segment_t * segs,int nseg,int error)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
envy24_dmarsetmap(void * arg,bus_dma_segment_t * segs,int nseg,int error)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
envy24_dmafree(struct sc_info * sc)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
envy24_dmainit(struct sc_info * sc)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
envy24_putcfg(struct sc_info * sc)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
envy24_init(struct sc_info * sc)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
envy24_alloc_resource(struct sc_info * sc)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 /*maxsize*/BUS_SPACE_MAXSIZE_ENVY24,
2534 /*nsegments*/1, /*maxsegsz*/0x3ffff,
2535 /*flags*/0,
2536 &sc->dmat) != 0) {
2537 device_printf(sc->dev, "unable to create dma tag\n");
2538 return ENXIO;
2539 }
2540
2541 return 0;
2542 }
2543
2544 static int
envy24_pci_attach(device_t dev)2545 envy24_pci_attach(device_t dev)
2546 {
2547 struct sc_info *sc;
2548 char status[SND_STATUSLEN];
2549 int err = 0;
2550 int i;
2551
2552 #if(0)
2553 device_printf(dev, "envy24_pci_attach()\n");
2554 #endif
2555 /* get sc_info data area */
2556 if ((sc = kmalloc(sizeof(*sc), M_ENVY24, M_WAITOK | M_ZERO)) == NULL) {
2557 device_printf(dev, "cannot allocate softc\n");
2558 return ENXIO;
2559 }
2560
2561 bzero(sc, sizeof(*sc));
2562 sc->lock = snd_mtxcreate(device_get_nameunit(dev), "snd_envy24 softc");
2563 sc->dev = dev;
2564
2565 /* initialize PCI interface */
2566 pci_enable_busmaster(dev);
2567
2568 /* allocate resources */
2569 err = envy24_alloc_resource(sc);
2570 if (err) {
2571 device_printf(dev, "unable to allocate system resources\n");
2572 goto bad;
2573 }
2574
2575 /* initialize card */
2576 err = envy24_init(sc);
2577 if (err) {
2578 device_printf(dev, "unable to initialize the card\n");
2579 goto bad;
2580 }
2581
2582 /* set multi track mixer */
2583 mixer_init(dev, &envy24mixer_class, sc);
2584
2585 /* set channel information */
2586 err = pcm_register(dev, sc, 5, 2 + sc->adcn);
2587 if (err)
2588 goto bad;
2589 sc->chnum = 0;
2590 for (i = 0; i < 5; i++) {
2591 pcm_addchan(dev, PCMDIR_PLAY, &envy24chan_class, sc);
2592 sc->chnum++;
2593 }
2594 for (i = 0; i < 2 + sc->adcn; i++) {
2595 pcm_addchan(dev, PCMDIR_REC, &envy24chan_class, sc);
2596 sc->chnum++;
2597 }
2598
2599 /* set status iformation */
2600 ksnprintf(status, SND_STATUSLEN,
2601 "at io 0x%lx:%ld,0x%lx:%ld,0x%lx:%ld,0x%lx:%ld irq %ld",
2602 rman_get_start(sc->cs),
2603 rman_get_end(sc->cs) - rman_get_start(sc->cs) + 1,
2604 rman_get_start(sc->ddma),
2605 rman_get_end(sc->ddma) - rman_get_start(sc->ddma) + 1,
2606 rman_get_start(sc->ds),
2607 rman_get_end(sc->ds) - rman_get_start(sc->ds) + 1,
2608 rman_get_start(sc->mt),
2609 rman_get_end(sc->mt) - rman_get_start(sc->mt) + 1,
2610 rman_get_start(sc->irq));
2611 pcm_setstatus(dev, status);
2612
2613 return 0;
2614
2615 bad:
2616 if (sc->ih)
2617 bus_teardown_intr(dev, sc->irq, sc->ih);
2618 if (sc->irq)
2619 bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq);
2620 envy24_dmafree(sc);
2621 if (sc->dmat)
2622 bus_dma_tag_destroy(sc->dmat);
2623 if (sc->cfg->codec->destroy != NULL) {
2624 for (i = 0; i < sc->adcn; i++)
2625 sc->cfg->codec->destroy(sc->adc[i]);
2626 for (i = 0; i < sc->dacn; i++)
2627 sc->cfg->codec->destroy(sc->dac[i]);
2628 }
2629 envy24_cfgfree(sc->cfg);
2630 if (sc->cs)
2631 bus_release_resource(dev, SYS_RES_IOPORT, sc->csid, sc->cs);
2632 if (sc->ddma)
2633 bus_release_resource(dev, SYS_RES_IOPORT, sc->ddmaid, sc->ddma);
2634 if (sc->ds)
2635 bus_release_resource(dev, SYS_RES_IOPORT, sc->dsid, sc->ds);
2636 if (sc->mt)
2637 bus_release_resource(dev, SYS_RES_IOPORT, sc->mtid, sc->mt);
2638 if (sc->lock)
2639 snd_mtxfree(sc->lock);
2640 kfree(sc, M_ENVY24);
2641 return err;
2642 }
2643
2644 static int
envy24_pci_detach(device_t dev)2645 envy24_pci_detach(device_t dev)
2646 {
2647 struct sc_info *sc;
2648 int r;
2649 int i;
2650
2651 #if(0)
2652 device_printf(dev, "envy24_pci_detach()\n");
2653 #endif
2654 sc = pcm_getdevinfo(dev);
2655 if (sc == NULL)
2656 return 0;
2657 r = pcm_unregister(dev);
2658 if (r)
2659 return r;
2660
2661 envy24_dmafree(sc);
2662 if (sc->cfg->codec->destroy != NULL) {
2663 for (i = 0; i < sc->adcn; i++)
2664 sc->cfg->codec->destroy(sc->adc[i]);
2665 for (i = 0; i < sc->dacn; i++)
2666 sc->cfg->codec->destroy(sc->dac[i]);
2667 }
2668 envy24_cfgfree(sc->cfg);
2669 bus_dma_tag_destroy(sc->dmat);
2670 bus_teardown_intr(dev, sc->irq, sc->ih);
2671 bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq);
2672 bus_release_resource(dev, SYS_RES_IOPORT, sc->csid, sc->cs);
2673 bus_release_resource(dev, SYS_RES_IOPORT, sc->ddmaid, sc->ddma);
2674 bus_release_resource(dev, SYS_RES_IOPORT, sc->dsid, sc->ds);
2675 bus_release_resource(dev, SYS_RES_IOPORT, sc->mtid, sc->mt);
2676 snd_mtxfree(sc->lock);
2677 kfree(sc, M_ENVY24);
2678 return 0;
2679 }
2680
2681 static device_method_t envy24_methods[] = {
2682 /* Device interface */
2683 DEVMETHOD(device_probe, envy24_pci_probe),
2684 DEVMETHOD(device_attach, envy24_pci_attach),
2685 DEVMETHOD(device_detach, envy24_pci_detach),
2686 { 0, 0 }
2687 };
2688
2689 static driver_t envy24_driver = {
2690 "pcm",
2691 envy24_methods,
2692 PCM_SOFTC_SIZE,
2693 };
2694
2695 DRIVER_MODULE(snd_envy24, pci, envy24_driver, pcm_devclass, NULL, NULL);
2696 MODULE_DEPEND(snd_envy24, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER);
2697 MODULE_DEPEND(snd_envy24, snd_spicds, 1, 1, 1);
2698 MODULE_VERSION(snd_envy24, 1);
2699