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