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