FreeBSD kernel sound device code
envy24ht.c
Go to the documentation of this file.
1/*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3 *
4 * Copyright (c) 2006 Konstantin Dimitrov <kosio.dimitrov@gmail.com>
5 * Copyright (c) 2001 Katsurajima Naoto <raven@katsurajima.seya.yokohama.jp>
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHERIN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 */
30
31/*
32 * Konstantin Dimitrov's thanks list:
33 *
34 * A huge thanks goes to Spas Filipov for his friendship, support and his
35 * generous gift - an 'Audiotrak Prodigy HD2' audio card! I also want to
36 * thank Keiichi Iwasaki and his parents, because they helped Spas to get
37 * the card from Japan! Having hardware sample of Prodigy HD2 made adding
38 * support for that great card very easy and real fun and pleasure.
39 *
40 */
41
42#ifdef HAVE_KERNEL_OPTION_HEADERS
43#include "opt_snd.h"
44#endif
45
46#include <dev/sound/pcm/sound.h>
47#include <dev/sound/pcm/ac97.h>
50
51#include <dev/pci/pcireg.h>
52#include <dev/pci/pcivar.h>
53
54#include "mixer_if.h"
55
56SND_DECLARE_FILE("$FreeBSD$");
57
58static MALLOC_DEFINE(M_ENVY24HT, "envy24ht", "envy24ht audio");
59
60/* -------------------------------------------------------------------- */
61
62struct sc_info;
63
64#define ENVY24HT_PLAY_CHNUM 8
65#define ENVY24HT_REC_CHNUM 2
66#define ENVY24HT_PLAY_BUFUNIT (4 /* byte/sample */ * 8 /* channel */)
67#define ENVY24HT_REC_BUFUNIT (4 /* byte/sample */ * 2 /* channel */)
68#define ENVY24HT_SAMPLE_NUM 4096
69
70#define ENVY24HT_TIMEOUT 1000
71
72#define ENVY24HT_DEFAULT_FORMAT SND_FORMAT(AFMT_S16_LE, 2, 0)
73
74#define ENVY24HT_NAMELEN 32
75
77 volatile u_int32_t buffer;
78};
79
81
82/* channel registers */
83struct sc_chinfo {
84 struct snd_dbuf *buffer;
85 struct pcm_channel *channel;
86 struct sc_info *parent;
87 int dir;
88 unsigned num; /* hw channel number */
89
90 /* channel information */
91 u_int32_t format;
92 u_int32_t speed;
93 u_int32_t blk; /* hw block size(dword) */
94
95 /* format conversion structure */
96 u_int8_t *data;
97 unsigned int size; /* data buffer size(byte) */
98 int unit; /* sample size(byte) */
99 unsigned int offset; /* samples number offset */
100 void (*emldma)(struct sc_chinfo *);
101
102 /* flags */
103 int run;
104};
105
106/* codec interface entrys */
107struct codec_entry {
108 void *(*create)(device_t dev, void *devinfo, int dir, int num);
109 void (*destroy)(void *codec);
110 void (*init)(void *codec);
111 void (*reinit)(void *codec);
112 void (*setvolume)(void *codec, int dir, unsigned int left, unsigned int right);
113 void (*setrate)(void *codec, int which, int rate);
114};
115
116/* system configuration information */
117struct cfg_info {
118 char *name;
119 u_int16_t subvendor, subdevice;
120 u_int8_t scfg, acl, i2s, spdif;
122 u_int32_t cdti, cclk, cs;
123 u_int8_t cif, type, free;
124 struct codec_entry *codec;
125};
126
127/* device private data */
128struct sc_info {
129 device_t dev;
130 struct mtx *lock;
131
132 /* Control/Status registor */
133 struct resource *cs;
134 int csid;
135 bus_space_tag_t cst;
136 bus_space_handle_t csh;
137 /* MultiTrack registor */
138 struct resource *mt;
139 int mtid;
140 bus_space_tag_t mtt;
141 bus_space_handle_t mth;
142 /* DMA tag */
143 bus_dma_tag_t dmat;
144 /* IRQ resource */
145 struct resource *irq;
146 int irqid;
147 void *ih;
148
149 /* system configuration data */
150 struct cfg_info *cfg;
151
152 /* ADC/DAC number and info */
153 int adcn, dacn;
154 void *adc[4], *dac[4];
155
156 /* mixer control data */
157 u_int32_t src;
158 u_int8_t left[ENVY24HT_CHAN_NUM];
159 u_int8_t right[ENVY24HT_CHAN_NUM];
160
161 /* Play/Record DMA fifo */
164 u_int32_t psize, rsize; /* DMA buffer size(byte) */
165 u_int16_t blk[2]; /* transfer check blocksize(dword) */
166 bus_dmamap_t pmap, rmap;
167 bus_addr_t paddr, raddr;
168
169 /* current status */
170 u_int32_t speed;
171 int run[2];
172 u_int16_t intr[2];
173 struct pcmchan_caps caps[2];
174
175 /* channel info table */
176 unsigned chnum;
177 struct sc_chinfo chan[11];
178};
179
180/* -------------------------------------------------------------------- */
181
182/*
183 * prototypes
184 */
185
186/* DMA emulator */
187static void envy24ht_p8u(struct sc_chinfo *);
188static void envy24ht_p16sl(struct sc_chinfo *);
189static void envy24ht_p32sl(struct sc_chinfo *);
190static void envy24ht_r16sl(struct sc_chinfo *);
191static void envy24ht_r32sl(struct sc_chinfo *);
192
193/* channel interface */
194static void *envy24htchan_init(kobj_t, void *, struct snd_dbuf *, struct pcm_channel *, int);
195static int envy24htchan_setformat(kobj_t, void *, u_int32_t);
196static u_int32_t envy24htchan_setspeed(kobj_t, void *, u_int32_t);
197static u_int32_t envy24htchan_setblocksize(kobj_t, void *, u_int32_t);
198static int envy24htchan_trigger(kobj_t, void *, int);
199static u_int32_t envy24htchan_getptr(kobj_t, void *);
200static struct pcmchan_caps *envy24htchan_getcaps(kobj_t, void *);
201
202/* mixer interface */
203static int envy24htmixer_init(struct snd_mixer *);
204static int envy24htmixer_reinit(struct snd_mixer *);
205static int envy24htmixer_uninit(struct snd_mixer *);
206static int envy24htmixer_set(struct snd_mixer *, unsigned, unsigned, unsigned);
207static u_int32_t envy24htmixer_setrecsrc(struct snd_mixer *, u_int32_t);
208
209/* SPI codec access interface */
210static void *envy24ht_spi_create(device_t, void *, int, int);
211static void envy24ht_spi_destroy(void *);
212static void envy24ht_spi_init(void *);
213static void envy24ht_spi_reinit(void *);
214static void envy24ht_spi_setvolume(void *, int, unsigned int, unsigned int);
215
216/* -------------------------------------------------------------------- */
217
218/*
219 system constant tables
220*/
221
222/* API -> hardware channel map */
229 ENVY24HT_CHAN_REC_MIX, /* 5 */
234 ENVY24HT_CHAN_REC_ADC4, /* 10 */
235};
236
237/* mixer -> API channel map. see above */
238static int envy24ht_mixmap[] = {
239 -1, /* Master output level. It is depend on codec support */
240 -1, /* Treble level of all output channels */
241 -1, /* Bass level of all output channels */
242 -1, /* Volume of synthesier input */
243 0, /* Output level for the audio device */
244 -1, /* Output level for the PC speaker */
245 7, /* line in jack */
246 -1, /* microphone jack */
247 -1, /* CD audio input */
248 -1, /* Recording monitor */
249 1, /* alternative codec */
250 -1, /* global recording level */
251 -1, /* Input gain */
252 -1, /* Output gain */
253 8, /* Input source 1 */
254 9, /* Input source 2 */
255 10, /* Input source 3 */
256 6, /* Digital (input) 1 */
257 -1, /* Digital (input) 2 */
258 -1, /* Digital (input) 3 */
259 -1, /* Phone input */
260 -1, /* Phone output */
261 -1, /* Video/TV (audio) in */
262 -1, /* Radio in */
263 -1, /* Monitor volume */
264};
265
266/* variable rate audio */
267static u_int32_t envy24ht_speed[] = {
268 192000, 176400, 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000,
269 12000, 11025, 9600, 8000, 0
270};
271
272/* known boards configuration */
273static struct codec_entry spi_codec = {
279 NULL, /* setrate */
280};
281
282static struct cfg_info cfg_table[] = {
283 {
284 "Envy24HT audio (Terratec Aureon 7.1 Space)",
285 0x153b, 0x1145,
286 0x0b, 0x80, 0xfc, 0xc3,
287 0x21efff, 0x7fffff, 0x5e1000,
288 0x40000, 0x80000, 0x1000, 0x00, 0x02,
289 0,
290 &spi_codec,
291 },
292 {
293 "Envy24HT audio (Terratec Aureon 5.1 Sky)",
294 0x153b, 0x1147,
295 0x0a, 0x80, 0xfc, 0xc3,
296 0x21efff, 0x7fffff, 0x5e1000,
297 0x40000, 0x80000, 0x1000, 0x00, 0x02,
298 0,
299 &spi_codec,
300 },
301 {
302 "Envy24HT audio (Terratec Aureon 7.1 Universe)",
303 0x153b, 0x1153,
304 0x0b, 0x80, 0xfc, 0xc3,
305 0x21efff, 0x7fffff, 0x5e1000,
306 0x40000, 0x80000, 0x1000, 0x00, 0x02,
307 0,
308 &spi_codec,
309 },
310 {
311 "Envy24HT audio (AudioTrak Prodigy 7.1)",
312 0x4933, 0x4553,
313 0x0b, 0x80, 0xfc, 0xc3,
314 0x21efff, 0x7fffff, 0x5e1000,
315 0x40000, 0x80000, 0x1000, 0x00, 0x02,
316 0,
317 &spi_codec,
318 },
319 {
320 "Envy24HT audio (Terratec PHASE 28)",
321 0x153b, 0x1149,
322 0x0b, 0x80, 0xfc, 0xc3,
323 0x21efff, 0x7fffff, 0x5e1000,
324 0x40000, 0x80000, 0x1000, 0x00, 0x02,
325 0,
326 &spi_codec,
327 },
328 {
329 "Envy24HT-S audio (Terratec PHASE 22)",
330 0x153b, 0x1150,
331 0x10, 0x80, 0xf0, 0xc3,
332 0x7ffbc7, 0x7fffff, 0x438,
333 0x10, 0x20, 0x400, 0x01, 0x00,
334 0,
335 &spi_codec,
336 },
337 {
338 "Envy24HT audio (AudioTrak Prodigy 7.1 LT)",
339 0x3132, 0x4154,
340 0x4b, 0x80, 0xfc, 0xc3,
341 0x7ff8ff, 0x7fffff, 0x700,
342 0x400, 0x200, 0x100, 0x00, 0x02,
343 0,
344 &spi_codec,
345 },
346 {
347 "Envy24HT audio (AudioTrak Prodigy 7.1 XT)",
348 0x3136, 0x4154,
349 0x4b, 0x80, 0xfc, 0xc3,
350 0x7ff8ff, 0x7fffff, 0x700,
351 0x400, 0x200, 0x100, 0x00, 0x02,
352 0,
353 &spi_codec,
354 },
355 {
356 "Envy24HT audio (M-Audio Revolution 7.1)",
357 0x1412, 0x3630,
358 0x43, 0x80, 0xf8, 0xc1,
359 0x3fff85, 0x400072, 0x4000fa,
360 0x08, 0x02, 0x20, 0x00, 0x04,
361 0,
362 &spi_codec,
363 },
364 {
365 "Envy24GT audio (M-Audio Revolution 5.1)",
366 0x1412, 0x3631,
367 0x42, 0x80, 0xf8, 0xc1,
368 0x3fff05, 0x4000f0, 0x4000fa,
369 0x08, 0x02, 0x10, 0x00, 0x03,
370 0,
371 &spi_codec,
372 },
373 {
374 "Envy24HT audio (M-Audio Audiophile 192)",
375 0x1412, 0x3632,
376 0x68, 0x80, 0xf8, 0xc3,
377 0x45, 0x4000b5, 0x7fffba,
378 0x08, 0x02, 0x10, 0x00, 0x03,
379 0,
380 &spi_codec,
381 },
382 {
383 "Envy24HT audio (AudioTrak Prodigy HD2)",
384 0x3137, 0x4154,
385 0x68, 0x80, 0x78, 0xc3,
386 0xfff8ff, 0x200700, 0xdfffff,
387 0x400, 0x200, 0x100, 0x00, 0x05,
388 0,
389 &spi_codec,
390 },
391 {
392 "Envy24HT audio (ESI Juli@)",
393 0x3031, 0x4553,
394 0x20, 0x80, 0xf8, 0xc3,
395 0x7fff9f, 0x8016, 0x7fff9f,
396 0x08, 0x02, 0x10, 0x00, 0x03,
397 0,
398 &spi_codec,
399 },
400 {
401 "Envy24HT-S audio (Terrasoniq TS22PCI)",
402 0x153b, 0x117b,
403 0x10, 0x80, 0xf0, 0xc3,
404 0x7ffbc7, 0x7fffff, 0x438,
405 0x10, 0x20, 0x400, 0x01, 0x00,
406 0,
407 &spi_codec,
408 },
409 {
410 "Envy24HT audio (Generic)",
411 0, 0,
412 0x0b, 0x80, 0xfc, 0xc3,
413 0x21efff, 0x7fffff, 0x5e1000,
414 0x40000, 0x80000, 0x1000, 0x00, 0x02,
415 0,
416 &spi_codec, /* default codec routines */
417 }
418};
419
420static u_int32_t envy24ht_recfmt[] = {
421 SND_FORMAT(AFMT_S16_LE, 2, 0),
422 SND_FORMAT(AFMT_S32_LE, 2, 0),
423 0
424};
425static struct pcmchan_caps envy24ht_reccaps = {8000, 96000, envy24ht_recfmt, 0};
426
427static u_int32_t envy24ht_playfmt[] = {
428 SND_FORMAT(AFMT_U8, 2, 0),
429 SND_FORMAT(AFMT_S16_LE, 2, 0),
430 SND_FORMAT(AFMT_S32_LE, 2, 0),
431 0
432};
433
434static struct pcmchan_caps envy24ht_playcaps = {8000, 192000, envy24ht_playfmt, 0};
435
437 u_int32_t format;
438 void (*emldma)(struct sc_chinfo *);
439 int unit;
440};
441
443 {SND_FORMAT(AFMT_U8, 2, 0), envy24ht_p8u, 2},
444 {SND_FORMAT(AFMT_S16_LE, 2, 0), envy24ht_p16sl, 4},
445 {SND_FORMAT(AFMT_S32_LE, 2, 0), envy24ht_p32sl, 8},
446 {0, NULL, 0}
447};
448
450 {SND_FORMAT(AFMT_S16_LE, 2, 0), envy24ht_r16sl, 4},
451 {SND_FORMAT(AFMT_S32_LE, 2, 0), envy24ht_r32sl, 8},
452 {0, NULL, 0}
453};
454
455/* -------------------------------------------------------------------- */
456
457/* common routines */
458static u_int32_t
459envy24ht_rdcs(struct sc_info *sc, int regno, int size)
460{
461 switch (size) {
462 case 1:
463 return bus_space_read_1(sc->cst, sc->csh, regno);
464 case 2:
465 return bus_space_read_2(sc->cst, sc->csh, regno);
466 case 4:
467 return bus_space_read_4(sc->cst, sc->csh, regno);
468 default:
469 return 0xffffffff;
470 }
471}
472
473static void
474envy24ht_wrcs(struct sc_info *sc, int regno, u_int32_t data, int size)
475{
476 switch (size) {
477 case 1:
478 bus_space_write_1(sc->cst, sc->csh, regno, data);
479 break;
480 case 2:
481 bus_space_write_2(sc->cst, sc->csh, regno, data);
482 break;
483 case 4:
484 bus_space_write_4(sc->cst, sc->csh, regno, data);
485 break;
486 }
487}
488
489static u_int32_t
490envy24ht_rdmt(struct sc_info *sc, int regno, int size)
491{
492 switch (size) {
493 case 1:
494 return bus_space_read_1(sc->mtt, sc->mth, regno);
495 case 2:
496 return bus_space_read_2(sc->mtt, sc->mth, regno);
497 case 4:
498 return bus_space_read_4(sc->mtt, sc->mth, regno);
499 default:
500 return 0xffffffff;
501 }
502}
503
504static void
505envy24ht_wrmt(struct sc_info *sc, int regno, u_int32_t data, int size)
506{
507 switch (size) {
508 case 1:
509 bus_space_write_1(sc->mtt, sc->mth, regno, data);
510 break;
511 case 2:
512 bus_space_write_2(sc->mtt, sc->mth, regno, data);
513 break;
514 case 4:
515 bus_space_write_4(sc->mtt, sc->mth, regno, data);
516 break;
517 }
518}
519
520/* -------------------------------------------------------------------- */
521
522/* I2C port/E2PROM access routines */
523
524static int
525envy24ht_rdi2c(struct sc_info *sc, u_int32_t dev, u_int32_t addr)
526{
527 u_int32_t data;
528 int i;
529
530#if(0)
531 device_printf(sc->dev, "envy24ht_rdi2c(sc, 0x%02x, 0x%02x)\n", dev, addr);
532#endif
533 for (i = 0; i < ENVY24HT_TIMEOUT; i++) {
535 if ((data & ENVY24HT_CCS_I2CSTAT_BSY) == 0)
536 break;
537 DELAY(32); /* 31.25kHz */
538 }
539 if (i == ENVY24HT_TIMEOUT) {
540 return -1;
541 }
545 for (i = 0; i < ENVY24HT_TIMEOUT; i++) {
547 if ((data & ENVY24HT_CCS_I2CSTAT_BSY) == 0)
548 break;
549 DELAY(32); /* 31.25kHz */
550 }
551 if (i == ENVY24HT_TIMEOUT) {
552 return -1;
553 }
555
556#if(0)
557 device_printf(sc->dev, "envy24ht_rdi2c(): return 0x%x\n", data);
558#endif
559 return (int)data;
560}
561
562static int
563envy24ht_wri2c(struct sc_info *sc, u_int32_t dev, u_int32_t addr, u_int32_t data)
564{
565 u_int32_t tmp;
566 int i;
567
568#if(0)
569 device_printf(sc->dev, "envy24ht_rdi2c(sc, 0x%02x, 0x%02x)\n", dev, addr);
570#endif
571 for (i = 0; i < ENVY24HT_TIMEOUT; i++) {
573 if ((tmp & ENVY24HT_CCS_I2CSTAT_BSY) == 0)
574 break;
575 DELAY(32); /* 31.25kHz */
576 }
577 if (i == ENVY24HT_TIMEOUT) {
578 return -1;
579 }
584 for (i = 0; i < ENVY24HT_TIMEOUT; i++) {
586 if ((data & ENVY24HT_CCS_I2CSTAT_BSY) == 0)
587 break;
588 DELAY(32); /* 31.25kHz */
589 }
590 if (i == ENVY24HT_TIMEOUT) {
591 return -1;
592 }
593
594 return 0;
595}
596
597static int
598envy24ht_rdrom(struct sc_info *sc, u_int32_t addr)
599{
600 u_int32_t data;
601
602#if(0)
603 device_printf(sc->dev, "envy24ht_rdrom(sc, 0x%02x)\n", addr);
604#endif
606 if ((data & ENVY24HT_CCS_I2CSTAT_ROM) == 0) {
607#if(0)
608 device_printf(sc->dev, "envy24ht_rdrom(): E2PROM not presented\n");
609#endif
610 return -1;
611 }
612
614}
615
616static struct cfg_info *
618{
619 struct cfg_info *buff;
620 int size;
621 int i;
622
623#if(0)
624 device_printf(sc->dev, "envy24ht_rom2cfg(sc)\n");
625#endif
627 if ((size < ENVY24HT_E2PROM_GPIOSTATE + 3) || (size == 0x78)) {
628#if(0)
629 device_printf(sc->dev, "envy24ht_rom2cfg(): ENVY24HT_E2PROM_SIZE-->%d\n", size);
630#endif
631 buff = malloc(sizeof(*buff), M_ENVY24HT, M_NOWAIT);
632 if (buff == NULL) {
633#if(0)
634 device_printf(sc->dev, "envy24ht_rom2cfg(): malloc()\n");
635#endif
636 return NULL;
637 }
638 buff->free = 1;
639
640 /* no valid e2prom, using default values */
645 buff->scfg = 0x0b;
646 buff->acl = 0x80;
647 buff->i2s = 0xfc;
648 buff->spdif = 0xc3;
649 buff->gpiomask = 0x21efff;
650 buff->gpiostate = 0x7fffff;
651 buff->gpiodir = 0x5e1000;
652 buff->cdti = 0x40000;
653 buff->cclk = 0x80000;
654 buff->cs = 0x1000;
655 buff->cif = 0x00;
656 buff->type = 0x02;
657
658 for (i = 0; cfg_table[i].subvendor != 0 || cfg_table[i].subdevice != 0;
659i++)
660 if (cfg_table[i].subvendor == buff->subvendor &&
661 cfg_table[i].subdevice == buff->subdevice)
662 break;
663 buff->name = cfg_table[i].name;
664 buff->codec = cfg_table[i].codec;
665
666 return buff;
667#if 0
668 return NULL;
669#endif
670 }
671 buff = malloc(sizeof(*buff), M_ENVY24HT, M_NOWAIT);
672 if (buff == NULL) {
673#if(0)
674 device_printf(sc->dev, "envy24ht_rom2cfg(): malloc()\n");
675#endif
676 return NULL;
677 }
678 buff->free = 1;
679
689 envy24ht_rdrom(sc, ENVY24HT_E2PROM_GPIOMASK + 1) << 8 | \
690 envy24ht_rdrom(sc, ENVY24HT_E2PROM_GPIOMASK + 2) << 16;
692 envy24ht_rdrom(sc, ENVY24HT_E2PROM_GPIOSTATE + 1) << 8 | \
693 envy24ht_rdrom(sc, ENVY24HT_E2PROM_GPIOSTATE + 2) << 16;
695 envy24ht_rdrom(sc, ENVY24HT_E2PROM_GPIODIR + 1) << 8 | \
696 envy24ht_rdrom(sc, ENVY24HT_E2PROM_GPIODIR + 2) << 16;
697
698 for (i = 0; cfg_table[i].subvendor != 0 || cfg_table[i].subdevice != 0; i++)
699 if (cfg_table[i].subvendor == buff->subvendor &&
700 cfg_table[i].subdevice == buff->subdevice)
701 break;
702 buff->name = cfg_table[i].name;
703 buff->codec = cfg_table[i].codec;
704
705 return buff;
706}
707
708static void
710 if (cfg == NULL)
711 return;
712 if (cfg->free)
713 free(cfg, M_ENVY24HT);
714 return;
715}
716
717/* -------------------------------------------------------------------- */
718
719/* AC'97 codec access routines */
720
721#if 0
722static int
723envy24ht_coldcd(struct sc_info *sc)
724{
725 u_int32_t data;
726 int i;
727
728#if(0)
729 device_printf(sc->dev, "envy24ht_coldcd()\n");
730#endif
731 envy24ht_wrmt(sc, ENVY24HT_MT_AC97CMD, ENVY24HT_MT_AC97CMD_CLD, 1);
732 DELAY(10);
733 envy24ht_wrmt(sc, ENVY24HT_MT_AC97CMD, 0, 1);
734 DELAY(1000);
735 for (i = 0; i < ENVY24HT_TIMEOUT; i++) {
736 data = envy24ht_rdmt(sc, ENVY24HT_MT_AC97CMD, 1);
737 if (data & ENVY24HT_MT_AC97CMD_RDY) {
738 return 0;
739 }
740 }
741
742 return -1;
743}
744
745static int
746envy24ht_slavecd(struct sc_info *sc)
747{
748 u_int32_t data;
749 int i;
750
751#if(0)
752 device_printf(sc->dev, "envy24ht_slavecd()\n");
753#endif
754 envy24ht_wrmt(sc, ENVY24HT_MT_AC97CMD,
755 ENVY24HT_MT_AC97CMD_CLD | ENVY24HT_MT_AC97CMD_WRM, 1);
756 DELAY(10);
757 envy24ht_wrmt(sc, ENVY24HT_MT_AC97CMD, 0, 1);
758 DELAY(1000);
759 for (i = 0; i < ENVY24HT_TIMEOUT; i++) {
760 data = envy24ht_rdmt(sc, ENVY24HT_MT_AC97CMD, 1);
761 if (data & ENVY24HT_MT_AC97CMD_RDY) {
762 return 0;
763 }
764 }
765
766 return -1;
767}
768
769static int
770envy24ht_rdcd(kobj_t obj, void *devinfo, int regno)
771{
772 struct sc_info *sc = (struct sc_info *)devinfo;
773 u_int32_t data;
774 int i;
775
776#if(0)
777 device_printf(sc->dev, "envy24ht_rdcd(obj, sc, 0x%02x)\n", regno);
778#endif
779 envy24ht_wrmt(sc, ENVY24HT_MT_AC97IDX, (u_int32_t)regno, 1);
780 envy24ht_wrmt(sc, ENVY24HT_MT_AC97CMD, ENVY24HT_MT_AC97CMD_RD, 1);
781 for (i = 0; i < ENVY24HT_TIMEOUT; i++) {
782 data = envy24ht_rdmt(sc, ENVY24HT_MT_AC97CMD, 1);
783 if ((data & ENVY24HT_MT_AC97CMD_RD) == 0)
784 break;
785 }
786 data = envy24ht_rdmt(sc, ENVY24HT_MT_AC97DLO, 2);
787
788#if(0)
789 device_printf(sc->dev, "envy24ht_rdcd(): return 0x%x\n", data);
790#endif
791 return (int)data;
792}
793
794static int
795envy24ht_wrcd(kobj_t obj, void *devinfo, int regno, u_int16_t data)
796{
797 struct sc_info *sc = (struct sc_info *)devinfo;
798 u_int32_t cmd;
799 int i;
800
801#if(0)
802 device_printf(sc->dev, "envy24ht_wrcd(obj, sc, 0x%02x, 0x%04x)\n", regno, data);
803#endif
804 envy24ht_wrmt(sc, ENVY24HT_MT_AC97IDX, (u_int32_t)regno, 1);
805 envy24ht_wrmt(sc, ENVY24HT_MT_AC97DLO, (u_int32_t)data, 2);
806 envy24ht_wrmt(sc, ENVY24HT_MT_AC97CMD, ENVY24HT_MT_AC97CMD_WR, 1);
807 for (i = 0; i < ENVY24HT_TIMEOUT; i++) {
808 cmd = envy24ht_rdmt(sc, ENVY24HT_MT_AC97CMD, 1);
809 if ((cmd & ENVY24HT_MT_AC97CMD_WR) == 0)
810 break;
811 }
812
813 return 0;
814}
815
816static kobj_method_t envy24ht_ac97_methods[] = {
817 KOBJMETHOD(ac97_read, envy24ht_rdcd),
818 KOBJMETHOD(ac97_write, envy24ht_wrcd),
820};
821AC97_DECLARE(envy24ht_ac97);
822#endif
823
824/* -------------------------------------------------------------------- */
825
826/* GPIO access routines */
827
828static u_int32_t
830{
831 if (sc->cfg->subvendor == 0x153b && sc->cfg->subdevice == 0x1150)
833 else
835}
836
837static void
838envy24ht_gpiowr(struct sc_info *sc, u_int32_t data)
839{
840#if(0)
841 device_printf(sc->dev, "envy24ht_gpiowr(sc, 0x%02x)\n", data & 0x7FFFFF);
842 return;
843#endif
845 if (sc->cfg->subdevice != 0x1150)
847 return;
848}
849
850#if 0
851static u_int32_t
852envy24ht_gpiogetmask(struct sc_info *sc)
853{
855}
856#endif
857
858static void
859envy24ht_gpiosetmask(struct sc_info *sc, u_int32_t mask)
860{
862 if (sc->cfg->subdevice != 0x1150)
864 return;
865}
866
867#if 0
868static u_int32_t
869envy24ht_gpiogetdir(struct sc_info *sc)
870{
872}
873#endif
874
875static void
876envy24ht_gpiosetdir(struct sc_info *sc, u_int32_t dir)
877{
878 if (sc->cfg->subvendor == 0x153b && sc->cfg->subdevice == 0x1150)
880 else
882 return;
883}
884
885/* -------------------------------------------------------------------- */
886
887/* SPI codec access interface routine */
888
892 int dir;
893 int num;
894 int cs, cclk, cdti;
895};
896
897static void
898envy24ht_spi_ctl(void *codec, unsigned int cs, unsigned int cclk, unsigned int cdti)
899{
900 u_int32_t data = 0;
901 struct envy24ht_spi_codec *ptr = codec;
902
903#if(0)
904 device_printf(ptr->parent->dev, "--> %d, %d, %d\n", cs, cclk, cdti);
905#endif
907 data &= ~(ptr->cs | ptr->cclk | ptr->cdti);
908 if (cs) data += ptr->cs;
909 if (cclk) data += ptr->cclk;
910 if (cdti) data += ptr->cdti;
912 return;
913}
914
915static void *
916envy24ht_spi_create(device_t dev, void *info, int dir, int num)
917{
918 struct sc_info *sc = info;
919 struct envy24ht_spi_codec *buff = NULL;
920
921#if(0)
922 device_printf(sc->dev, "envy24ht_spi_create(dev, sc, %d, %d)\n", dir, num);
923#endif
924
925 buff = malloc(sizeof(*buff), M_ENVY24HT, M_NOWAIT);
926 if (buff == NULL)
927 return NULL;
928
929 if (dir == PCMDIR_REC && sc->adc[num] != NULL)
930 buff->info = ((struct envy24ht_spi_codec *)sc->adc[num])->info;
931 else if (dir == PCMDIR_PLAY && sc->dac[num] != NULL)
932 buff->info = ((struct envy24ht_spi_codec *)sc->dac[num])->info;
933 else
934 buff->info = spicds_create(dev, buff, num, envy24ht_spi_ctl);
935 if (buff->info == NULL) {
936 free(buff, M_ENVY24HT);
937 return NULL;
938 }
939
940 buff->parent = sc;
941 buff->dir = dir;
942 buff->num = num;
943
944 return (void *)buff;
945}
946
947static void
949{
950 struct envy24ht_spi_codec *ptr = codec;
951 if (ptr == NULL)
952 return;
953#if(0)
954 device_printf(ptr->parent->dev, "envy24ht_spi_destroy()\n");
955#endif
956
957 if (ptr->dir == PCMDIR_PLAY) {
958 if (ptr->parent->dac[ptr->num] != NULL)
959 spicds_destroy(ptr->info);
960 }
961 else {
962 if (ptr->parent->adc[ptr->num] != NULL)
963 spicds_destroy(ptr->info);
964 }
965
966 free(codec, M_ENVY24HT);
967}
968
969static void
971{
972 struct envy24ht_spi_codec *ptr = codec;
973 if (ptr == NULL)
974 return;
975#if(0)
976 device_printf(ptr->parent->dev, "envy24ht_spicds_init()\n");
977#endif
978 ptr->cs = ptr->parent->cfg->cs;
979 ptr->cclk = ptr->parent->cfg->cclk;
980 ptr->cdti = ptr->parent->cfg->cdti;
981 spicds_settype(ptr->info, ptr->parent->cfg->type);
982 spicds_setcif(ptr->info, ptr->parent->cfg->cif);
983 if (ptr->parent->cfg->type == SPICDS_TYPE_AK4524 || \
984 ptr->parent->cfg->type == SPICDS_TYPE_AK4528) {
988 }
989
990 /* for the time being, init only first codec */
991 if (ptr->num == 0)
992 spicds_init(ptr->info);
993}
994
995static void
997{
998 struct envy24ht_spi_codec *ptr = codec;
999 if (ptr == NULL)
1000 return;
1001#if(0)
1002 device_printf(ptr->parent->dev, "envy24ht_spi_reinit()\n");
1003#endif
1004
1005 spicds_reinit(ptr->info);
1006}
1007
1008static void
1009envy24ht_spi_setvolume(void *codec, int dir, unsigned int left, unsigned int right)
1010{
1011 struct envy24ht_spi_codec *ptr = codec;
1012 if (ptr == NULL)
1013 return;
1014#if(0)
1015 device_printf(ptr->parent->dev, "envy24ht_spi_set()\n");
1016#endif
1017
1018 spicds_set(ptr->info, dir, left, right);
1019}
1020
1021/* -------------------------------------------------------------------- */
1022
1023/* hardware access routeines */
1024
1025static struct {
1026 u_int32_t speed;
1027 u_int32_t code;
1028} envy24ht_speedtab[] = {
1029 {48000, ENVY24HT_MT_RATE_48000},
1030 {24000, ENVY24HT_MT_RATE_24000},
1031 {12000, ENVY24HT_MT_RATE_12000},
1032 {9600, ENVY24HT_MT_RATE_9600},
1033 {32000, ENVY24HT_MT_RATE_32000},
1034 {16000, ENVY24HT_MT_RATE_16000},
1035 {8000, ENVY24HT_MT_RATE_8000},
1036 {96000, ENVY24HT_MT_RATE_96000},
1037 {192000, ENVY24HT_MT_RATE_192000},
1038 {64000, ENVY24HT_MT_RATE_64000},
1039 {44100, ENVY24HT_MT_RATE_44100},
1040 {22050, ENVY24HT_MT_RATE_22050},
1041 {11025, ENVY24HT_MT_RATE_11025},
1042 {88200, ENVY24HT_MT_RATE_88200},
1043 {176400, ENVY24HT_MT_RATE_176400},
1044 {0, 0x10}
1046
1047static u_int32_t
1048envy24ht_setspeed(struct sc_info *sc, u_int32_t speed) {
1049 u_int32_t code, i2sfmt;
1050 int i = 0;
1051
1052#if(0)
1053 device_printf(sc->dev, "envy24ht_setspeed(sc, %d)\n", speed);
1054 if (speed == 0) {
1055 code = ENVY24HT_MT_RATE_SPDIF; /* external master clock */
1056 envy24ht_slavecd(sc);
1057 }
1058 else {
1059#endif
1060 for (i = 0; envy24ht_speedtab[i].speed != 0; i++) {
1061 if (envy24ht_speedtab[i].speed == speed)
1062 break;
1063 }
1064 code = envy24ht_speedtab[i].code;
1065#if 0
1066 }
1067 device_printf(sc->dev, "envy24ht_setspeed(): speed %d/code 0x%04x\n", envy24ht_speedtab[i].speed, code);
1068#endif
1069 if (code < 0x10) {
1071 if ((((sc->cfg->scfg & ENVY24HT_CCSM_SCFG_XIN2) == 0x00) && (code == ENVY24HT_MT_RATE_192000)) || \
1073 i2sfmt = envy24ht_rdmt(sc, ENVY24HT_MT_I2S, 1);
1074 i2sfmt |= ENVY24HT_MT_I2S_MLR128;
1075 envy24ht_wrmt(sc, ENVY24HT_MT_I2S, i2sfmt, 1);
1076 }
1077 else {
1078 i2sfmt = envy24ht_rdmt(sc, ENVY24HT_MT_I2S, 1);
1079 i2sfmt &= ~ENVY24HT_MT_I2S_MLR128;
1080 envy24ht_wrmt(sc, ENVY24HT_MT_I2S, i2sfmt, 1);
1081 }
1084 for (i = 0; envy24ht_speedtab[i].code < 0x10; i++) {
1085 if (envy24ht_speedtab[i].code == code)
1086 break;
1087 }
1088 speed = envy24ht_speedtab[i].speed;
1089 }
1090 else
1091 speed = 0;
1092
1093#if(0)
1094 device_printf(sc->dev, "envy24ht_setspeed(): return %d\n", speed);
1095#endif
1096 return speed;
1097}
1098
1099static void
1100envy24ht_setvolume(struct sc_info *sc, unsigned ch)
1101{
1102#if(0)
1103 device_printf(sc->dev, "envy24ht_setvolume(sc, %d)\n", ch);
1104 envy24ht_wrmt(sc, ENVY24HT_MT_VOLIDX, ch * 2, 1);
1105 envy24ht_wrmt(sc, ENVY24HT_MT_VOLUME, 0x7f00 | sc->left[ch], 2);
1106 envy24ht_wrmt(sc, ENVY24HT_MT_VOLIDX, ch * 2 + 1, 1);
1107 envy24ht_wrmt(sc, ENVY24HT_MT_VOLUME, (sc->right[ch] << 8) | 0x7f, 2);
1108#endif
1109}
1110
1111static void
1112envy24ht_mutevolume(struct sc_info *sc, unsigned ch)
1113{
1114#if 0
1115 u_int32_t vol;
1116
1117 device_printf(sc->dev, "envy24ht_mutevolume(sc, %d)\n", ch);
1119 envy24ht_wrmt(sc, ENVY24HT_MT_VOLIDX, ch * 2, 1);
1120 envy24ht_wrmt(sc, ENVY24HT_MT_VOLUME, vol, 2);
1121 envy24ht_wrmt(sc, ENVY24HT_MT_VOLIDX, ch * 2 + 1, 1);
1122 envy24ht_wrmt(sc, ENVY24HT_MT_VOLUME, vol, 2);
1123#endif
1124}
1125
1126static u_int32_t
1128{
1129 int unit, regno;
1130 u_int32_t ptr, rtn;
1131
1132#if(0)
1133 device_printf(sc->dev, "envy24ht_gethwptr(sc, %d)\n", dir);
1134#endif
1135 if (dir == PCMDIR_PLAY) {
1136 rtn = sc->psize / 4;
1137 unit = ENVY24HT_PLAY_BUFUNIT / 4;
1139 }
1140 else {
1141 rtn = sc->rsize / 4;
1142 unit = ENVY24HT_REC_BUFUNIT / 4;
1144 }
1145
1146 ptr = envy24ht_rdmt(sc, regno, 2);
1147 rtn -= (ptr + 1);
1148 rtn /= unit;
1149
1150#if(0)
1151 device_printf(sc->dev, "envy24ht_gethwptr(): return %d\n", rtn);
1152#endif
1153 return rtn;
1154}
1155
1156static void
1158{
1159 int regptr, regintr;
1160 u_int32_t mask, intr;
1161 u_int32_t ptr, size, cnt;
1162 u_int16_t blk;
1163
1164#if(0)
1165 device_printf(sc->dev, "envy24ht_updintr(sc, %d)\n", dir);
1166#endif
1167 if (dir == PCMDIR_PLAY) {
1168 blk = sc->blk[0];
1169 size = sc->psize / 4;
1170 regptr = ENVY24HT_MT_PCNT;
1171 regintr = ENVY24HT_MT_PTERM;
1172 mask = ~ENVY24HT_MT_INT_PMASK;
1173 }
1174 else {
1175 blk = sc->blk[1];
1176 size = sc->rsize / 4;
1177 regptr = ENVY24HT_MT_RCNT;
1178 regintr = ENVY24HT_MT_RTERM;
1179 mask = ~ENVY24HT_MT_INT_RMASK;
1180 }
1181
1182 ptr = size - envy24ht_rdmt(sc, regptr, 2) - 1;
1183 /*
1184 cnt = blk - ptr % blk - 1;
1185 if (cnt == 0)
1186 cnt = blk - 1;
1187 */
1188 cnt = blk - 1;
1189#if(0)
1190 device_printf(sc->dev, "envy24ht_updintr():ptr = %d, blk = %d, cnt = %d\n", ptr, blk, cnt);
1191#endif
1192 envy24ht_wrmt(sc, regintr, cnt, 2);
1194#if(0)
1195 device_printf(sc->dev, "envy24ht_updintr():intr = 0x%02x, mask = 0x%02x\n", intr, mask);
1196#endif
1198#if(0)
1199 device_printf(sc->dev, "envy24ht_updintr():INT-->0x%02x\n",
1201#endif
1202
1203 return;
1204}
1205
1206#if 0
1207static void
1208envy24ht_maskintr(struct sc_info *sc, int dir)
1209{
1210 u_int32_t mask, intr;
1211
1212#if(0)
1213 device_printf(sc->dev, "envy24ht_maskintr(sc, %d)\n", dir);
1214#endif
1215 if (dir == PCMDIR_PLAY)
1217 else
1219 intr = envy24ht_rdmt(sc, ENVY24HT_MT_INT, 1);
1220 envy24ht_wrmt(sc, ENVY24HT_MT_INT, intr | mask, 1);
1221
1222 return;
1223}
1224#endif
1225
1226static int
1228{
1229 u_int32_t mask, stat, intr, rtn;
1230
1231#if(0)
1232 device_printf(sc->dev, "envy24ht_checkintr(sc, %d)\n", dir);
1233#endif
1235 if (dir == PCMDIR_PLAY) {
1236 if ((rtn = intr & ENVY24HT_MT_INT_PSTAT) != 0) {
1237 mask = ~ENVY24HT_MT_INT_RSTAT;
1238 envy24ht_wrmt(sc, 0x1a, 0x01, 1);
1240 stat = envy24ht_rdmt(sc, ENVY24HT_MT_INT_MASK, 1);
1242 }
1243 }
1244 else {
1245 if ((rtn = intr & ENVY24HT_MT_INT_RSTAT) != 0) {
1246 mask = ~ENVY24HT_MT_INT_PSTAT;
1247#if 0
1249#endif
1251 stat = envy24ht_rdmt(sc, ENVY24HT_MT_INT_MASK, 1);
1253 }
1254 }
1255
1256 return rtn;
1257}
1258
1259static void
1261{
1262 u_int32_t stat, sw;
1263
1264#if(0)
1265 device_printf(sc->dev, "envy24ht_start(sc, %d)\n", dir);
1266#endif
1267 if (dir == PCMDIR_PLAY)
1269 else
1271
1272 stat = envy24ht_rdmt(sc, ENVY24HT_MT_PCTL, 1);
1273 envy24ht_wrmt(sc, ENVY24HT_MT_PCTL, stat | sw, 1);
1274#if(0)
1275 DELAY(100);
1276 device_printf(sc->dev, "PADDR:0x%08x\n", envy24ht_rdmt(sc, ENVY24HT_MT_PADDR, 4));
1277 device_printf(sc->dev, "PCNT:%ld\n", envy24ht_rdmt(sc, ENVY24HT_MT_PCNT, 2));
1278#endif
1279
1280 return;
1281}
1282
1283static void
1284envy24ht_stop(struct sc_info *sc, int dir)
1285{
1286 u_int32_t stat, sw;
1287
1288#if(0)
1289 device_printf(sc->dev, "envy24ht_stop(sc, %d)\n", dir);
1290#endif
1291 if (dir == PCMDIR_PLAY)
1292 sw = ~ENVY24HT_MT_PCTL_PSTART;
1293 else
1294 sw = ~ENVY24HT_MT_PCTL_RSTART;
1295
1296 stat = envy24ht_rdmt(sc, ENVY24HT_MT_PCTL, 1);
1297 envy24ht_wrmt(sc, ENVY24HT_MT_PCTL, stat & sw, 1);
1298
1299 return;
1300}
1301
1302#if 0
1303static int
1304envy24ht_route(struct sc_info *sc, int dac, int class, int adc, int rev)
1305{
1306 return 0;
1307}
1308#endif
1309
1310/* -------------------------------------------------------------------- */
1311
1312/* buffer copy routines */
1313static void
1315{
1316 int length;
1317 sample32_t *dmabuf;
1318 u_int32_t *data;
1319 int src, dst, ssize, dsize, slot;
1320 int i;
1321
1322 length = sndbuf_getready(ch->buffer) / 8;
1323 dmabuf = ch->parent->pbuf;
1324 data = (u_int32_t *)ch->data;
1325 src = sndbuf_getreadyptr(ch->buffer) / 4;
1326 dst = src / 2 + ch->offset;
1327 ssize = ch->size / 4;
1328 dsize = ch->size / 8;
1329 slot = ch->num * 2;
1330
1331 for (i = 0; i < length; i++) {
1332 dmabuf[dst * ENVY24HT_PLAY_CHNUM + slot].buffer = data[src];
1333 dmabuf[dst * ENVY24HT_PLAY_CHNUM + slot + 1].buffer = data[src + 1];
1334 dst++;
1335 dst %= dsize;
1336 src += 2;
1337 src %= ssize;
1338 }
1339
1340 return;
1341}
1342
1343static void
1345{
1346 int length;
1347 sample32_t *dmabuf;
1348 u_int16_t *data;
1349 int src, dst, ssize, dsize, slot;
1350 int i;
1351
1352#if(0)
1353 device_printf(ch->parent->dev, "envy24ht_p16sl()\n");
1354#endif
1355 length = sndbuf_getready(ch->buffer) / 4;
1356 dmabuf = ch->parent->pbuf;
1357 data = (u_int16_t *)ch->data;
1358 src = sndbuf_getreadyptr(ch->buffer) / 2;
1359 dst = src / 2 + ch->offset;
1360 ssize = ch->size / 2;
1361 dsize = ch->size / 4;
1362 slot = ch->num * 2;
1363#if(0)
1364 device_printf(ch->parent->dev, "envy24ht_p16sl():%lu-->%lu(%lu)\n", src, dst, length);
1365#endif
1366
1367 for (i = 0; i < length; i++) {
1368 dmabuf[dst * ENVY24HT_PLAY_CHNUM + slot].buffer = (u_int32_t)data[src] << 16;
1369 dmabuf[dst * ENVY24HT_PLAY_CHNUM + slot + 1].buffer = (u_int32_t)data[src + 1] << 16;
1370#if(0)
1371 if (i < 16) {
1372 printf("%08x", dmabuf[dst * ENVY24HT_PLAY_CHNUM + slot]);
1373 printf("%08x", dmabuf[dst * ENVY24HT_PLAY_CHNUM + slot + 1]);
1374 }
1375#endif
1376 dst++;
1377 dst %= dsize;
1378 src += 2;
1379 src %= ssize;
1380 }
1381#if(0)
1382 printf("\n");
1383#endif
1384
1385 return;
1386}
1387
1388static void
1390{
1391 int length;
1392 sample32_t *dmabuf;
1393 u_int8_t *data;
1394 int src, dst, ssize, dsize, slot;
1395 int i;
1396
1397 length = sndbuf_getready(ch->buffer) / 2;
1398 dmabuf = ch->parent->pbuf;
1399 data = (u_int8_t *)ch->data;
1401 dst = src / 2 + ch->offset;
1402 ssize = ch->size;
1403 dsize = ch->size / 4;
1404 slot = ch->num * 2;
1405
1406 for (i = 0; i < length; i++) {
1407 dmabuf[dst * ENVY24HT_PLAY_CHNUM + slot].buffer = ((u_int32_t)data[src] ^ 0x80) << 24;
1408 dmabuf[dst * ENVY24HT_PLAY_CHNUM + slot + 1].buffer = ((u_int32_t)data[src + 1] ^ 0x80) << 24;
1409 dst++;
1410 dst %= dsize;
1411 src += 2;
1412 src %= ssize;
1413 }
1414
1415 return;
1416}
1417
1418static void
1420{
1421 int length;
1422 sample32_t *dmabuf;
1423 u_int32_t *data;
1424 int src, dst, ssize, dsize, slot;
1425 int i;
1426
1427 length = sndbuf_getfree(ch->buffer) / 8;
1428 dmabuf = ch->parent->rbuf;
1429 data = (u_int32_t *)ch->data;
1430 dst = sndbuf_getfreeptr(ch->buffer) / 4;
1431 src = dst / 2 + ch->offset;
1432 dsize = ch->size / 4;
1433 ssize = ch->size / 8;
1434 slot = (ch->num - ENVY24HT_CHAN_REC_ADC1) * 2;
1435
1436 for (i = 0; i < length; i++) {
1437 data[dst] = dmabuf[src * ENVY24HT_REC_CHNUM + slot].buffer;
1438 data[dst + 1] = dmabuf[src * ENVY24HT_REC_CHNUM + slot + 1].buffer;
1439 dst += 2;
1440 dst %= dsize;
1441 src++;
1442 src %= ssize;
1443 }
1444
1445 return;
1446}
1447
1448static void
1450{
1451 int length;
1452 sample32_t *dmabuf;
1453 u_int16_t *data;
1454 int src, dst, ssize, dsize, slot;
1455 int i;
1456
1457 length = sndbuf_getfree(ch->buffer) / 4;
1458 dmabuf = ch->parent->rbuf;
1459 data = (u_int16_t *)ch->data;
1460 dst = sndbuf_getfreeptr(ch->buffer) / 2;
1461 src = dst / 2 + ch->offset;
1462 dsize = ch->size / 2;
1463 ssize = ch->size / 8;
1464 slot = (ch->num - ENVY24HT_CHAN_REC_ADC1) * 2;
1465
1466 for (i = 0; i < length; i++) {
1467 data[dst] = dmabuf[src * ENVY24HT_REC_CHNUM + slot].buffer;
1468 data[dst + 1] = dmabuf[src * ENVY24HT_REC_CHNUM + slot + 1].buffer;
1469 dst += 2;
1470 dst %= dsize;
1471 src++;
1472 src %= ssize;
1473 }
1474
1475 return;
1476}
1477
1478/* -------------------------------------------------------------------- */
1479
1480/* channel interface */
1481static void *
1482envy24htchan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir)
1483{
1484 struct sc_info *sc = (struct sc_info *)devinfo;
1485 struct sc_chinfo *ch;
1486 unsigned num;
1487
1488#if(0)
1489 device_printf(sc->dev, "envy24htchan_init(obj, devinfo, b, c, %d)\n", dir);
1490#endif
1491 snd_mtxlock(sc->lock);
1492#if 0
1493 if ((sc->chnum > ENVY24HT_CHAN_PLAY_SPDIF && dir != PCMDIR_REC) ||
1495 snd_mtxunlock(sc->lock);
1496 return NULL;
1497 }
1498#endif
1499 num = sc->chnum;
1500
1501 ch = &sc->chan[num];
1502 ch->size = 8 * ENVY24HT_SAMPLE_NUM;
1503 ch->data = malloc(ch->size, M_ENVY24HT, M_NOWAIT);
1504 if (ch->data == NULL) {
1505 ch->size = 0;
1506 ch = NULL;
1507 }
1508 else {
1509 ch->buffer = b;
1510 ch->channel = c;
1511 ch->parent = sc;
1512 ch->dir = dir;
1513 /* set channel map */
1514 ch->num = envy24ht_chanmap[num];
1515 snd_mtxunlock(sc->lock);
1516 sndbuf_setup(ch->buffer, ch->data, ch->size);
1517 snd_mtxlock(sc->lock);
1518 /* these 2 values are dummy */
1519 ch->unit = 4;
1520 ch->blk = 10240;
1521 }
1522 snd_mtxunlock(sc->lock);
1523
1524 return ch;
1525}
1526
1527static int
1528envy24htchan_free(kobj_t obj, void *data)
1529{
1530 struct sc_chinfo *ch = data;
1531 struct sc_info *sc = ch->parent;
1532
1533#if(0)
1534 device_printf(sc->dev, "envy24htchan_free()\n");
1535#endif
1536 snd_mtxlock(sc->lock);
1537 if (ch->data != NULL) {
1538 free(ch->data, M_ENVY24HT);
1539 ch->data = NULL;
1540 }
1541 snd_mtxunlock(sc->lock);
1542
1543 return 0;
1544}
1545
1546static int
1547envy24htchan_setformat(kobj_t obj, void *data, u_int32_t format)
1548{
1549 struct sc_chinfo *ch = data;
1550 struct sc_info *sc = ch->parent;
1551 struct envy24ht_emldma *emltab;
1552 /* unsigned int bcnt, bsize; */
1553 int i;
1554
1555#if(0)
1556 device_printf(sc->dev, "envy24htchan_setformat(obj, data, 0x%08x)\n", format);
1557#endif
1558 snd_mtxlock(sc->lock);
1559 /* check and get format related information */
1560 if (ch->dir == PCMDIR_PLAY)
1561 emltab = envy24ht_pemltab;
1562 else
1563 emltab = envy24ht_remltab;
1564 if (emltab == NULL) {
1565 snd_mtxunlock(sc->lock);
1566 return -1;
1567 }
1568 for (i = 0; emltab[i].format != 0; i++)
1569 if (emltab[i].format == format)
1570 break;
1571 if (emltab[i].format == 0) {
1572 snd_mtxunlock(sc->lock);
1573 return -1;
1574 }
1575
1576 /* set format information */
1577 ch->format = format;
1578 ch->emldma = emltab[i].emldma;
1579 if (ch->unit > emltab[i].unit)
1580 ch->blk *= ch->unit / emltab[i].unit;
1581 else
1582 ch->blk /= emltab[i].unit / ch->unit;
1583 ch->unit = emltab[i].unit;
1584
1585 /* set channel buffer information */
1586 ch->size = ch->unit * ENVY24HT_SAMPLE_NUM;
1587#if 0
1588 if (ch->dir == PCMDIR_PLAY)
1589 bsize = ch->blk * 4 / ENVY24HT_PLAY_BUFUNIT;
1590 else
1591 bsize = ch->blk * 4 / ENVY24HT_REC_BUFUNIT;
1592 bsize *= ch->unit;
1593 bcnt = ch->size / bsize;
1594 sndbuf_resize(ch->buffer, bcnt, bsize);
1595#endif
1596 snd_mtxunlock(sc->lock);
1597
1598#if(0)
1599 device_printf(sc->dev, "envy24htchan_setformat(): return 0x%08x\n", 0);
1600#endif
1601 return 0;
1602}
1603
1604/*
1605 IMPLEMENT NOTICE: In this driver, setspeed function only do setting
1606 of speed information value. And real hardware speed setting is done
1607 at start triggered(see envy24htchan_trigger()). So, at this function
1608 is called, any value that ENVY24 can use is able to set. But, at
1609 start triggerd, some other channel is running, and that channel's
1610 speed isn't same with, then trigger function will fail.
1611*/
1612static u_int32_t
1613envy24htchan_setspeed(kobj_t obj, void *data, u_int32_t speed)
1614{
1615 struct sc_chinfo *ch = data;
1616 u_int32_t val, prev;
1617 int i;
1618
1619#if(0)
1620 device_printf(ch->parent->dev, "envy24htchan_setspeed(obj, data, %d)\n", speed);
1621#endif
1622 prev = 0x7fffffff;
1623 for (i = 0; (val = envy24ht_speed[i]) != 0; i++) {
1624 if (abs(val - speed) < abs(prev - speed))
1625 prev = val;
1626 else
1627 break;
1628 }
1629 ch->speed = prev;
1630
1631#if(0)
1632 device_printf(ch->parent->dev, "envy24htchan_setspeed(): return %d\n", ch->speed);
1633#endif
1634 return ch->speed;
1635}
1636
1637static u_int32_t
1638envy24htchan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
1639{
1640 struct sc_chinfo *ch = data;
1641 /* struct sc_info *sc = ch->parent; */
1642 u_int32_t size, prev;
1643 unsigned int bcnt, bsize;
1644
1645#if(0)
1646 device_printf(sc->dev, "envy24htchan_setblocksize(obj, data, %d)\n", blocksize);
1647#endif
1648 prev = 0x7fffffff;
1649 /* snd_mtxlock(sc->lock); */
1650 for (size = ch->size / 2; size > 0; size /= 2) {
1651 if (abs(size - blocksize) < abs(prev - blocksize))
1652 prev = size;
1653 else
1654 break;
1655 }
1656
1657 ch->blk = prev / ch->unit;
1658 if (ch->dir == PCMDIR_PLAY)
1659 ch->blk *= ENVY24HT_PLAY_BUFUNIT / 4;
1660 else
1661 ch->blk *= ENVY24HT_REC_BUFUNIT / 4;
1662 /* set channel buffer information */
1663 /* ch->size = ch->unit * ENVY24HT_SAMPLE_NUM; */
1664 if (ch->dir == PCMDIR_PLAY)
1665 bsize = ch->blk * 4 / ENVY24HT_PLAY_BUFUNIT;
1666 else
1667 bsize = ch->blk * 4 / ENVY24HT_REC_BUFUNIT;
1668 bsize *= ch->unit;
1669 bcnt = ch->size / bsize;
1670 sndbuf_resize(ch->buffer, bcnt, bsize);
1671 /* snd_mtxunlock(sc->lock); */
1672
1673#if(0)
1674 device_printf(sc->dev, "envy24htchan_setblocksize(): return %d\n", prev);
1675#endif
1676 return prev;
1677}
1678
1679/* semantic note: must start at beginning of buffer */
1680static int
1681envy24htchan_trigger(kobj_t obj, void *data, int go)
1682{
1683 struct sc_chinfo *ch = data;
1684 struct sc_info *sc = ch->parent;
1685 u_int32_t ptr;
1686 int slot;
1687 int error = 0;
1688#if 0
1689 int i;
1690
1691 device_printf(sc->dev, "envy24htchan_trigger(obj, data, %d)\n", go);
1692#endif
1693 snd_mtxlock(sc->lock);
1694 if (ch->dir == PCMDIR_PLAY)
1695 slot = 0;
1696 else
1697 slot = 1;
1698 switch (go) {
1699 case PCMTRIG_START:
1700#if(0)
1701 device_printf(sc->dev, "envy24htchan_trigger(): start\n");
1702#endif
1703 /* check or set channel speed */
1704 if (sc->run[0] == 0 && sc->run[1] == 0) {
1705 sc->speed = envy24ht_setspeed(sc, ch->speed);
1706 sc->caps[0].minspeed = sc->caps[0].maxspeed = sc->speed;
1707 sc->caps[1].minspeed = sc->caps[1].maxspeed = sc->speed;
1708 }
1709 else if (ch->speed != 0 && ch->speed != sc->speed) {
1710 error = -1;
1711 goto fail;
1712 }
1713 if (ch->speed == 0)
1714 ch->channel->speed = sc->speed;
1715 /* start or enable channel */
1716 sc->run[slot]++;
1717 if (sc->run[slot] == 1) {
1718 /* first channel */
1719 ch->offset = 0;
1720 sc->blk[slot] = ch->blk;
1721 }
1722 else {
1723 ptr = envy24ht_gethwptr(sc, ch->dir);
1724 ch->offset = ((ptr / ch->blk + 1) * ch->blk %
1725 (ch->size / 4)) * 4 / ch->unit;
1726 if (ch->blk < sc->blk[slot])
1727 sc->blk[slot] = ch->blk;
1728 }
1729 if (ch->dir == PCMDIR_PLAY) {
1730 ch->emldma(ch);
1732 }
1733 envy24ht_updintr(sc, ch->dir);
1734 if (sc->run[slot] == 1)
1735 envy24ht_start(sc, ch->dir);
1736 ch->run = 1;
1737 break;
1738 case PCMTRIG_EMLDMAWR:
1739#if(0)
1740 device_printf(sc->dev, "envy24htchan_trigger(): emldmawr\n");
1741#endif
1742 if (ch->run != 1) {
1743 error = -1;
1744 goto fail;
1745 }
1746 ch->emldma(ch);
1747 break;
1748 case PCMTRIG_EMLDMARD:
1749#if(0)
1750 device_printf(sc->dev, "envy24htchan_trigger(): emldmard\n");
1751#endif
1752 if (ch->run != 1) {
1753 error = -1;
1754 goto fail;
1755 }
1756 ch->emldma(ch);
1757 break;
1758 case PCMTRIG_ABORT:
1759 if (ch->run) {
1760#if(0)
1761 device_printf(sc->dev, "envy24htchan_trigger(): abort\n");
1762#endif
1763 ch->run = 0;
1764 sc->run[slot]--;
1765 if (ch->dir == PCMDIR_PLAY)
1767 if (sc->run[slot] == 0) {
1768 envy24ht_stop(sc, ch->dir);
1769 sc->intr[slot] = 0;
1770 }
1771/* else if (ch->blk == sc->blk[slot]) {
1772 sc->blk[slot] = ENVY24HT_SAMPLE_NUM / 2;
1773 for (i = 0; i < ENVY24HT_CHAN_NUM; i++) {
1774 if (sc->chan[i].dir == ch->dir &&
1775 sc->chan[i].run == 1 &&
1776 sc->chan[i].blk < sc->blk[slot])
1777 sc->blk[slot] = sc->chan[i].blk;
1778 }
1779 if (ch->blk != sc->blk[slot])
1780 envy24ht_updintr(sc, ch->dir);
1781 }*/
1782 }
1783 break;
1784 }
1785fail:
1786 snd_mtxunlock(sc->lock);
1787 return (error);
1788}
1789
1790static u_int32_t
1791envy24htchan_getptr(kobj_t obj, void *data)
1792{
1793 struct sc_chinfo *ch = data;
1794 struct sc_info *sc = ch->parent;
1795 u_int32_t ptr, rtn;
1796
1797#if(0)
1798 device_printf(sc->dev, "envy24htchan_getptr()\n");
1799#endif
1800 snd_mtxlock(sc->lock);
1801 ptr = envy24ht_gethwptr(sc, ch->dir);
1802 rtn = ptr * ch->unit;
1803 snd_mtxunlock(sc->lock);
1804
1805#if(0)
1806 device_printf(sc->dev, "envy24htchan_getptr(): return %d\n",
1807 rtn);
1808#endif
1809 return rtn;
1810}
1811
1812static struct pcmchan_caps *
1813envy24htchan_getcaps(kobj_t obj, void *data)
1814{
1815 struct sc_chinfo *ch = data;
1816 struct sc_info *sc = ch->parent;
1817 struct pcmchan_caps *rtn;
1818
1819#if(0)
1820 device_printf(sc->dev, "envy24htchan_getcaps()\n");
1821#endif
1822 snd_mtxlock(sc->lock);
1823 if (ch->dir == PCMDIR_PLAY) {
1824 if (sc->run[0] == 0)
1825 rtn = &envy24ht_playcaps;
1826 else
1827 rtn = &sc->caps[0];
1828 }
1829 else {
1830 if (sc->run[1] == 0)
1831 rtn = &envy24ht_reccaps;
1832 else
1833 rtn = &sc->caps[1];
1834 }
1835 snd_mtxunlock(sc->lock);
1836
1837 return rtn;
1838}
1839
1840static kobj_method_t envy24htchan_methods[] = {
1841 KOBJMETHOD(channel_init, envy24htchan_init),
1842 KOBJMETHOD(channel_free, envy24htchan_free),
1843 KOBJMETHOD(channel_setformat, envy24htchan_setformat),
1844 KOBJMETHOD(channel_setspeed, envy24htchan_setspeed),
1845 KOBJMETHOD(channel_setblocksize, envy24htchan_setblocksize),
1846 KOBJMETHOD(channel_trigger, envy24htchan_trigger),
1847 KOBJMETHOD(channel_getptr, envy24htchan_getptr),
1848 KOBJMETHOD(channel_getcaps, envy24htchan_getcaps),
1850};
1851CHANNEL_DECLARE(envy24htchan);
1852
1853/* -------------------------------------------------------------------- */
1854
1855/* mixer interface */
1856
1857static int
1859{
1860 struct sc_info *sc = mix_getdevinfo(m);
1861
1862#if(0)
1863 device_printf(sc->dev, "envy24htmixer_init()\n");
1864#endif
1865 if (sc == NULL)
1866 return -1;
1867
1868 /* set volume control rate */
1869 snd_mtxlock(sc->lock);
1870#if 0
1871 envy24ht_wrmt(sc, ENVY24HT_MT_VOLRATE, 0x30, 1); /* 0x30 is default value */
1872#endif
1873
1875
1878
1879 snd_mtxunlock(sc->lock);
1880
1881 return 0;
1882}
1883
1884static int
1886{
1887 struct sc_info *sc = mix_getdevinfo(m);
1888
1889 if (sc == NULL)
1890 return -1;
1891#if(0)
1892 device_printf(sc->dev, "envy24htmixer_reinit()\n");
1893#endif
1894
1895 return 0;
1896}
1897
1898static int
1900{
1901 struct sc_info *sc = mix_getdevinfo(m);
1902
1903 if (sc == NULL)
1904 return -1;
1905#if(0)
1906 device_printf(sc->dev, "envy24htmixer_uninit()\n");
1907#endif
1908
1909 return 0;
1910}
1911
1912static int
1913envy24htmixer_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right)
1914{
1915 struct sc_info *sc = mix_getdevinfo(m);
1916 int ch = envy24ht_mixmap[dev];
1917 int hwch;
1918 int i;
1919
1920 if (sc == NULL)
1921 return -1;
1922 if (dev == 0 && sc->cfg->codec->setvolume == NULL)
1923 return -1;
1924 if (dev != 0 && ch == -1)
1925 return -1;
1926 hwch = envy24ht_chanmap[ch];
1927#if(0)
1928 device_printf(sc->dev, "envy24htmixer_set(m, %d, %d, %d)\n",
1929 dev, left, right);
1930#endif
1931
1932 snd_mtxlock(sc->lock);
1933 if (dev == 0) {
1934 for (i = 0; i < sc->dacn; i++) {
1935 sc->cfg->codec->setvolume(sc->dac[i], PCMDIR_PLAY, left, right);
1936 }
1937 }
1938 else {
1939 /* set volume value for hardware */
1940 if ((sc->left[hwch] = 100 - left) > ENVY24HT_VOL_MIN)
1941 sc->left[hwch] = ENVY24HT_VOL_MUTE;
1942 if ((sc->right[hwch] = 100 - right) > ENVY24HT_VOL_MIN)
1943 sc->right[hwch] = ENVY24HT_VOL_MUTE;
1944
1945 /* set volume for record channel and running play channel */
1946 if (hwch > ENVY24HT_CHAN_PLAY_SPDIF || sc->chan[ch].run)
1947 envy24ht_setvolume(sc, hwch);
1948 }
1949 snd_mtxunlock(sc->lock);
1950
1951 return right << 8 | left;
1952}
1953
1954static u_int32_t
1956{
1957 struct sc_info *sc = mix_getdevinfo(m);
1958 int ch = envy24ht_mixmap[src];
1959#if(0)
1960 device_printf(sc->dev, "envy24htmixer_setrecsrc(m, %d)\n", src);
1961#endif
1962
1964 sc->src = ch;
1965 return src;
1966}
1967
1968static kobj_method_t envy24htmixer_methods[] = {
1969 KOBJMETHOD(mixer_init, envy24htmixer_init),
1972 KOBJMETHOD(mixer_set, envy24htmixer_set),
1975};
1976MIXER_DECLARE(envy24htmixer);
1977
1978/* -------------------------------------------------------------------- */
1979
1980/* The interrupt handler */
1981static void
1983{
1984 struct sc_info *sc = (struct sc_info *)p;
1985 struct sc_chinfo *ch;
1986 u_int32_t ptr, dsize, feed;
1987 int i;
1988
1989#if(0)
1990 device_printf(sc->dev, "envy24ht_intr()\n");
1991#endif
1992 snd_mtxlock(sc->lock);
1994#if(0)
1995 device_printf(sc->dev, "envy24ht_intr(): play\n");
1996#endif
1997 dsize = sc->psize / 4;
1998 ptr = dsize - envy24ht_rdmt(sc, ENVY24HT_MT_PCNT, 2) - 1;
1999#if(0)
2000 device_printf(sc->dev, "envy24ht_intr(): ptr = %d-->", ptr);
2001#endif
2002 ptr -= ptr % sc->blk[0];
2003 feed = (ptr + dsize - sc->intr[0]) % dsize;
2004#if(0)
2005 printf("%d intr = %d feed = %d\n", ptr, sc->intr[0], feed);
2006#endif
2008 ch = &sc->chan[i];
2009#if(0)
2010 if (ch->run)
2011 device_printf(sc->dev, "envy24ht_intr(): chan[%d].blk = %d\n", i, ch->blk);
2012#endif
2013 if (ch->run && ch->blk <= feed) {
2014 snd_mtxunlock(sc->lock);
2015 chn_intr(ch->channel);
2016 snd_mtxlock(sc->lock);
2017 }
2018 }
2019 sc->intr[0] = ptr;
2021 }
2022 if (envy24ht_checkintr(sc, PCMDIR_REC)) {
2023#if(0)
2024 device_printf(sc->dev, "envy24ht_intr(): rec\n");
2025#endif
2026 dsize = sc->rsize / 4;
2027 ptr = dsize - envy24ht_rdmt(sc, ENVY24HT_MT_RCNT, 2) - 1;
2028 ptr -= ptr % sc->blk[1];
2029 feed = (ptr + dsize - sc->intr[1]) % dsize;
2030 for (i = ENVY24HT_CHAN_REC_ADC1; i <= ENVY24HT_CHAN_REC_SPDIF; i++) {
2031 ch = &sc->chan[i];
2032 if (ch->run && ch->blk <= feed) {
2033 snd_mtxunlock(sc->lock);
2034 chn_intr(ch->channel);
2035 snd_mtxlock(sc->lock);
2036 }
2037 }
2038 sc->intr[1] = ptr;
2040 }
2041 snd_mtxunlock(sc->lock);
2042
2043 return;
2044}
2045
2046/*
2047 * Probe and attach the card
2048 */
2049
2050static int
2052{
2053 u_int16_t sv, sd;
2054 int i;
2055
2056#if(0)
2057 printf("envy24ht_pci_probe()\n");
2058#endif
2059 if (pci_get_device(dev) == PCID_ENVY24HT &&
2060 pci_get_vendor(dev) == PCIV_ENVY24) {
2061 sv = pci_get_subvendor(dev);
2062 sd = pci_get_subdevice(dev);
2063 for (i = 0; cfg_table[i].subvendor != 0 || cfg_table[i].subdevice != 0; i++) {
2064 if (cfg_table[i].subvendor == sv &&
2065 cfg_table[i].subdevice == sd) {
2066 break;
2067 }
2068 }
2069 device_set_desc(dev, cfg_table[i].name);
2070#if(0)
2071 printf("envy24ht_pci_probe(): return 0\n");
2072#endif
2073 return 0;
2074 }
2075 else {
2076#if(0)
2077 printf("envy24ht_pci_probe(): return ENXIO\n");
2078#endif
2079 return ENXIO;
2080 }
2081}
2082
2083static void
2084envy24ht_dmapsetmap(void *arg, bus_dma_segment_t *segs, int nseg, int error)
2085{
2086 struct sc_info *sc = arg;
2087
2088 sc->paddr = segs->ds_addr;
2089#if(0)
2090 device_printf(sc->dev, "envy24ht_dmapsetmap()\n");
2091 if (bootverbose) {
2092 printf("envy24ht(play): setmap %lx, %lx; ",
2093 (unsigned long)segs->ds_addr,
2094 (unsigned long)segs->ds_len);
2095 }
2096#endif
2097 envy24ht_wrmt(sc, ENVY24HT_MT_PADDR, (uint32_t)segs->ds_addr, 4);
2098 envy24ht_wrmt(sc, ENVY24HT_MT_PCNT, (uint32_t)(segs->ds_len / 4 - 1), 2);
2099}
2100
2101static void
2102envy24ht_dmarsetmap(void *arg, bus_dma_segment_t *segs, int nseg, int error)
2103{
2104 struct sc_info *sc = arg;
2105
2106 sc->raddr = segs->ds_addr;
2107#if(0)
2108 device_printf(sc->dev, "envy24ht_dmarsetmap()\n");
2109 if (bootverbose) {
2110 printf("envy24ht(record): setmap %lx, %lx; ",
2111 (unsigned long)segs->ds_addr,
2112 (unsigned long)segs->ds_len);
2113 }
2114#endif
2115 envy24ht_wrmt(sc, ENVY24HT_MT_RADDR, (uint32_t)segs->ds_addr, 4);
2116 envy24ht_wrmt(sc, ENVY24HT_MT_RCNT, (uint32_t)(segs->ds_len / 4 - 1), 2);
2117}
2118
2119static void
2121{
2122#if(0)
2123 device_printf(sc->dev, "envy24ht_dmafree():");
2124 printf(" sc->raddr(0x%08x)", (u_int32_t)sc->raddr);
2125 printf(" sc->paddr(0x%08x)", (u_int32_t)sc->paddr);
2126 if (sc->rbuf) printf(" sc->rbuf(0x%08x)", (u_int32_t)sc->rbuf);
2127 else printf(" sc->rbuf(null)");
2128 if (sc->pbuf) printf(" sc->pbuf(0x%08x)\n", (u_int32_t)sc->pbuf);
2129 else printf(" sc->pbuf(null)\n");
2130#endif
2131#if(0)
2132 if (sc->raddr)
2133 bus_dmamap_unload(sc->dmat, sc->rmap);
2134 if (sc->paddr)
2135 bus_dmamap_unload(sc->dmat, sc->pmap);
2136 if (sc->rbuf)
2137 bus_dmamem_free(sc->dmat, sc->rbuf, sc->rmap);
2138 if (sc->pbuf)
2139 bus_dmamem_free(sc->dmat, sc->pbuf, sc->pmap);
2140#else
2141 bus_dmamap_unload(sc->dmat, sc->rmap);
2142 bus_dmamap_unload(sc->dmat, sc->pmap);
2143 bus_dmamem_free(sc->dmat, sc->rbuf, sc->rmap);
2144 bus_dmamem_free(sc->dmat, sc->pbuf, sc->pmap);
2145#endif
2146
2147 sc->raddr = sc->paddr = 0;
2148 sc->pbuf = NULL;
2149 sc->rbuf = NULL;
2150
2151 return;
2152}
2153
2154static int
2156{
2157
2158#if(0)
2159 device_printf(sc->dev, "envy24ht_dmainit()\n");
2160#endif
2161 /* init values */
2164 sc->pbuf = NULL;
2165 sc->rbuf = NULL;
2166 sc->paddr = sc->raddr = 0;
2167 sc->blk[0] = sc->blk[1] = 0;
2168
2169 /* allocate DMA buffer */
2170#if(0)
2171 device_printf(sc->dev, "envy24ht_dmainit(): bus_dmamem_alloc(): sc->pbuf\n");
2172#endif
2173 if (bus_dmamem_alloc(sc->dmat, (void **)&sc->pbuf, BUS_DMA_NOWAIT, &sc->pmap))
2174 goto bad;
2175#if(0)
2176 device_printf(sc->dev, "envy24ht_dmainit(): bus_dmamem_alloc(): sc->rbuf\n");
2177#endif
2178 if (bus_dmamem_alloc(sc->dmat, (void **)&sc->rbuf, BUS_DMA_NOWAIT, &sc->rmap))
2179 goto bad;
2180#if(0)
2181 device_printf(sc->dev, "envy24ht_dmainit(): bus_dmamem_load(): sc->pmap\n");
2182#endif
2183 if (bus_dmamap_load(sc->dmat, sc->pmap, sc->pbuf, sc->psize, envy24ht_dmapsetmap, sc, BUS_DMA_NOWAIT))
2184 goto bad;
2185#if(0)
2186 device_printf(sc->dev, "envy24ht_dmainit(): bus_dmamem_load(): sc->rmap\n");
2187#endif
2188 if (bus_dmamap_load(sc->dmat, sc->rmap, sc->rbuf, sc->rsize, envy24ht_dmarsetmap, sc, BUS_DMA_NOWAIT))
2189 goto bad;
2190 bzero(sc->pbuf, sc->psize);
2191 bzero(sc->rbuf, sc->rsize);
2192
2193 return 0;
2194 bad:
2195 envy24ht_dmafree(sc);
2196 return ENOSPC;
2197}
2198
2199static void
2201{
2202 device_printf(sc->dev, "system configuration\n");
2203 printf(" SubVendorID: 0x%04x, SubDeviceID: 0x%04x\n",
2204 sc->cfg->subvendor, sc->cfg->subdevice);
2205 printf(" XIN2 Clock Source: ");
2206 switch (sc->cfg->scfg & ENVY24HT_CCSM_SCFG_XIN2) {
2207 case 0x00:
2208 printf("24.576MHz(96kHz*256)\n");
2209 break;
2210 case 0x40:
2211 printf("49.152MHz(192kHz*256)\n");
2212 break;
2213 case 0x80:
2214 printf("reserved\n");
2215 break;
2216 default:
2217 printf("illegal system setting\n");
2218 }
2219 printf(" MPU-401 UART(s) #: ");
2220 if (sc->cfg->scfg & ENVY24HT_CCSM_SCFG_MPU)
2221 printf("1\n");
2222 else
2223 printf("not implemented\n");
2224 switch (sc->adcn) {
2225 case 0x01:
2226 case 0x02:
2227 printf(" ADC #: ");
2228 printf("%d\n", sc->adcn);
2229 break;
2230 case 0x03:
2231 printf(" ADC #: ");
2232 printf("%d", 1);
2233 printf(" and SPDIF receiver connected\n");
2234 break;
2235 default:
2236 printf(" no physical inputs\n");
2237 }
2238 printf(" DAC #: ");
2239 printf("%d\n", sc->dacn);
2240 printf(" Multi-track converter type: ");
2241 if ((sc->cfg->acl & ENVY24HT_CCSM_ACL_MTC) == 0) {
2242 printf("AC'97(SDATA_OUT:");
2243 if (sc->cfg->acl & ENVY24HT_CCSM_ACL_OMODE)
2244 printf("packed");
2245 else
2246 printf("split");
2247 printf(")\n");
2248 }
2249 else {
2250 printf("I2S(");
2251 if (sc->cfg->i2s & ENVY24HT_CCSM_I2S_VOL)
2252 printf("with volume, ");
2253 if (sc->cfg->i2s & ENVY24HT_CCSM_I2S_192KHZ)
2254 printf("192KHz support, ");
2255 else
2256 if (sc->cfg->i2s & ENVY24HT_CCSM_I2S_96KHZ)
2257 printf("192KHz support, ");
2258 else
2259 printf("48KHz support, ");
2260 switch (sc->cfg->i2s & ENVY24HT_CCSM_I2S_RES) {
2262 printf("16bit resolution, ");
2263 break;
2265 printf("18bit resolution, ");
2266 break;
2268 printf("20bit resolution, ");
2269 break;
2271 printf("24bit resolution, ");
2272 break;
2273 }
2274 printf("ID#0x%x)\n", sc->cfg->i2s & ENVY24HT_CCSM_I2S_ID);
2275 }
2276 printf(" S/PDIF(IN/OUT): ");
2277 if (sc->cfg->spdif & ENVY24HT_CCSM_SPDIF_IN)
2278 printf("1/");
2279 else
2280 printf("0/");
2282 printf("1 ");
2283 else
2284 printf("0 ");
2286 printf("ID# 0x%02x\n", (sc->cfg->spdif & ENVY24HT_CCSM_SPDIF_ID) >> 2);
2287 printf(" GPIO(mask/dir/state): 0x%02x/0x%02x/0x%02x\n",
2288 sc->cfg->gpiomask, sc->cfg->gpiodir, sc->cfg->gpiostate);
2289}
2290
2291static int
2293{
2294 u_int32_t data;
2295#if(0)
2296 int rtn;
2297#endif
2298 int i;
2299 u_int32_t sv, sd;
2300
2301#if(0)
2302 device_printf(sc->dev, "envy24ht_init()\n");
2303#endif
2304
2305 /* reset chip */
2306#if 0
2308 DELAY(200);
2309 envy24ht_wrcs(sc, ENVY24HT_CCS_CTL, ENVY24HT_CCS_CTL_NATIVE, 1);
2310 DELAY(200);
2311
2312 /* legacy hardware disable */
2313 data = pci_read_config(sc->dev, PCIR_LAC, 2);
2315 pci_write_config(sc->dev, PCIR_LAC, data, 2);
2316#endif
2317
2318 /* check system configuration */
2319 sc->cfg = NULL;
2320 for (i = 0; cfg_table[i].subvendor != 0 || cfg_table[i].subdevice != 0; i++) {
2321 /* 1st: search configuration from table */
2322 sv = pci_get_subvendor(sc->dev);
2323 sd = pci_get_subdevice(sc->dev);
2324 if (sv == cfg_table[i].subvendor && sd == cfg_table[i].subdevice) {
2325#if(0)
2326 device_printf(sc->dev, "Set configuration from table\n");
2327#endif
2328 sc->cfg = &cfg_table[i];
2329 break;
2330 }
2331 }
2332 if (sc->cfg == NULL) {
2333 /* 2nd: read configuration from table */
2334 sc->cfg = envy24ht_rom2cfg(sc);
2335 }
2336 sc->adcn = ((sc->cfg->scfg & ENVY24HT_CCSM_SCFG_ADC) >> 2) + 1; /* need to be fixed */
2337 sc->dacn = (sc->cfg->scfg & ENVY24HT_CCSM_SCFG_DAC) + 1;
2338
2339 if (1 /* bootverbose */) {
2340 envy24ht_putcfg(sc);
2341 }
2342
2343 /* set system configuration */
2345 envy24ht_wrcs(sc, ENVY24HT_CCS_ACL, sc->cfg->acl, 1);
2346 envy24ht_wrcs(sc, ENVY24HT_CCS_I2S, sc->cfg->i2s, 1);
2350 envy24ht_gpiowr(sc, sc->cfg->gpiostate);
2351
2352 if ((sc->cfg->subvendor == 0x3031) && (sc->cfg->subdevice == 0x4553)) {
2353 envy24ht_wri2c(sc, 0x22, 0x00, 0x07);
2354 envy24ht_wri2c(sc, 0x22, 0x04, 0x5f | 0x80);
2355 envy24ht_wri2c(sc, 0x22, 0x05, 0x5f | 0x80);
2356 }
2357
2358 for (i = 0; i < sc->adcn; i++) {
2359 sc->adc[i] = sc->cfg->codec->create(sc->dev, sc, PCMDIR_REC, i);
2360 sc->cfg->codec->init(sc->adc[i]);
2361 }
2362 for (i = 0; i < sc->dacn; i++) {
2363 sc->dac[i] = sc->cfg->codec->create(sc->dev, sc, PCMDIR_PLAY, i);
2364 sc->cfg->codec->init(sc->dac[i]);
2365 }
2366
2367 /* initialize DMA buffer */
2368#if(0)
2369 device_printf(sc->dev, "envy24ht_init(): initialize DMA buffer\n");
2370#endif
2371 if (envy24ht_dmainit(sc))
2372 return ENOSPC;
2373
2374 /* initialize status */
2375 sc->run[0] = sc->run[1] = 0;
2376 sc->intr[0] = sc->intr[1] = 0;
2377 sc->speed = 0;
2378 sc->caps[0].fmtlist = envy24ht_playfmt;
2379 sc->caps[1].fmtlist = envy24ht_recfmt;
2380
2381 /* set channel router */
2382#if 0
2383 envy24ht_route(sc, ENVY24HT_ROUTE_DAC_1, ENVY24HT_ROUTE_CLASS_MIX, 0, 0);
2384 envy24ht_route(sc, ENVY24HT_ROUTE_DAC_SPDIF, ENVY24HT_ROUTE_CLASS_DMA, 0, 0);
2385 envy24ht_route(sc, ENVY24HT_ROUTE_DAC_SPDIF, ENVY24HT_ROUTE_CLASS_MIX, 0, 0);
2386#endif
2387
2388 /* set macro interrupt mask */
2392#if(0)
2393 device_printf(sc->dev, "envy24ht_init(): CCS_IMASK-->0x%02x\n", data);
2394#endif
2395
2396 return 0;
2397}
2398
2399static int
2401{
2402 /* allocate I/O port resource */
2403 sc->csid = PCIR_CCS;
2404 sc->cs = bus_alloc_resource_any(sc->dev, SYS_RES_IOPORT,
2405 &sc->csid, RF_ACTIVE);
2406 sc->mtid = ENVY24HT_PCIR_MT;
2407 sc->mt = bus_alloc_resource_any(sc->dev, SYS_RES_IOPORT,
2408 &sc->mtid, RF_ACTIVE);
2409 if (!sc->cs || !sc->mt) {
2410 device_printf(sc->dev, "unable to map IO port space\n");
2411 return ENXIO;
2412 }
2413 sc->cst = rman_get_bustag(sc->cs);
2414 sc->csh = rman_get_bushandle(sc->cs);
2415 sc->mtt = rman_get_bustag(sc->mt);
2416 sc->mth = rman_get_bushandle(sc->mt);
2417#if(0)
2418 device_printf(sc->dev,
2419 "IO port register values\nCCS: 0x%lx\nMT: 0x%lx\n",
2420 pci_read_config(sc->dev, PCIR_CCS, 4),
2421 pci_read_config(sc->dev, PCIR_MT, 4));
2422#endif
2423
2424 /* allocate interrupt resource */
2425 sc->irqid = 0;
2426 sc->irq = bus_alloc_resource_any(sc->dev, SYS_RES_IRQ, &sc->irqid,
2427 RF_ACTIVE | RF_SHAREABLE);
2428 if (!sc->irq ||
2429 snd_setup_intr(sc->dev, sc->irq, INTR_MPSAFE, envy24ht_intr, sc, &sc->ih)) {
2430 device_printf(sc->dev, "unable to map interrupt\n");
2431 return ENXIO;
2432 }
2433
2434 /* allocate DMA resource */
2435 if (bus_dma_tag_create(/*parent*/bus_get_dma_tag(sc->dev),
2436 /*alignment*/4,
2437 /*boundary*/0,
2438 /*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
2439 /*highaddr*/BUS_SPACE_MAXADDR,
2440 /*filter*/NULL, /*filterarg*/NULL,
2441 /*maxsize*/BUS_SPACE_MAXSIZE_ENVY24,
2442 /*nsegments*/1, /*maxsegsz*/0x3ffff,
2443 /*flags*/0, /*lockfunc*/NULL,
2444 /*lockarg*/NULL, &sc->dmat) != 0) {
2445 device_printf(sc->dev, "unable to create dma tag\n");
2446 return ENXIO;
2447 }
2448
2449 return 0;
2450}
2451
2452static int
2454{
2455 struct sc_info *sc;
2456 char status[SND_STATUSLEN];
2457 int err = 0;
2458 int i;
2459
2460#if(0)
2461 device_printf(dev, "envy24ht_pci_attach()\n");
2462#endif
2463 /* get sc_info data area */
2464 if ((sc = malloc(sizeof(*sc), M_ENVY24HT, M_NOWAIT)) == NULL) {
2465 device_printf(dev, "cannot allocate softc\n");
2466 return ENXIO;
2467 }
2468
2469 bzero(sc, sizeof(*sc));
2470 sc->lock = snd_mtxcreate(device_get_nameunit(dev),
2471 "snd_envy24ht softc");
2472 sc->dev = dev;
2473
2474 /* initialize PCI interface */
2475 pci_enable_busmaster(dev);
2476
2477 /* allocate resources */
2478 err = envy24ht_alloc_resource(sc);
2479 if (err) {
2480 device_printf(dev, "unable to allocate system resources\n");
2481 goto bad;
2482 }
2483
2484 /* initialize card */
2485 err = envy24ht_init(sc);
2486 if (err) {
2487 device_printf(dev, "unable to initialize the card\n");
2488 goto bad;
2489 }
2490
2491 /* set multi track mixer */
2492 mixer_init(dev, &envy24htmixer_class, sc);
2493
2494 /* set channel information */
2495 /* err = pcm_register(dev, sc, 5, 2 + sc->adcn); */
2496 err = pcm_register(dev, sc, 1, 2 + sc->adcn);
2497 if (err)
2498 goto bad;
2499 sc->chnum = 0;
2500 /* for (i = 0; i < 5; i++) { */
2501 pcm_addchan(dev, PCMDIR_PLAY, &envy24htchan_class, sc);
2502 sc->chnum++;
2503 /* } */
2504 for (i = 0; i < 2 + sc->adcn; i++) {
2505 pcm_addchan(dev, PCMDIR_REC, &envy24htchan_class, sc);
2506 sc->chnum++;
2507 }
2508
2509 /* set status iformation */
2510 snprintf(status, SND_STATUSLEN,
2511 "at io 0x%jx:%jd,0x%jx:%jd irq %jd",
2512 rman_get_start(sc->cs),
2513 rman_get_end(sc->cs) - rman_get_start(sc->cs) + 1,
2514 rman_get_start(sc->mt),
2515 rman_get_end(sc->mt) - rman_get_start(sc->mt) + 1,
2516 rman_get_start(sc->irq));
2518
2519 return 0;
2520
2521bad:
2522 if (sc->ih)
2523 bus_teardown_intr(dev, sc->irq, sc->ih);
2524 if (sc->irq)
2525 bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq);
2526 envy24ht_dmafree(sc);
2527 if (sc->dmat)
2528 bus_dma_tag_destroy(sc->dmat);
2529 if (sc->cfg->codec->destroy != NULL) {
2530 for (i = 0; i < sc->adcn; i++)
2531 sc->cfg->codec->destroy(sc->adc[i]);
2532 for (i = 0; i < sc->dacn; i++)
2533 sc->cfg->codec->destroy(sc->dac[i]);
2534 }
2535 envy24ht_cfgfree(sc->cfg);
2536 if (sc->cs)
2537 bus_release_resource(dev, SYS_RES_IOPORT, sc->csid, sc->cs);
2538 if (sc->mt)
2539 bus_release_resource(dev, SYS_RES_IOPORT, sc->mtid, sc->mt);
2540 if (sc->lock)
2541 snd_mtxfree(sc->lock);
2542 free(sc, M_ENVY24HT);
2543 return err;
2544}
2545
2546static int
2548{
2549 struct sc_info *sc;
2550 int r;
2551 int i;
2552
2553#if(0)
2554 device_printf(dev, "envy24ht_pci_detach()\n");
2555#endif
2556 sc = pcm_getdevinfo(dev);
2557 if (sc == NULL)
2558 return 0;
2559 r = pcm_unregister(dev);
2560 if (r)
2561 return r;
2562
2563 envy24ht_dmafree(sc);
2564 if (sc->cfg->codec->destroy != NULL) {
2565 for (i = 0; i < sc->adcn; i++)
2566 sc->cfg->codec->destroy(sc->adc[i]);
2567 for (i = 0; i < sc->dacn; i++)
2568 sc->cfg->codec->destroy(sc->dac[i]);
2569 }
2570 envy24ht_cfgfree(sc->cfg);
2571 bus_dma_tag_destroy(sc->dmat);
2572 bus_teardown_intr(dev, sc->irq, sc->ih);
2573 bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq);
2574 bus_release_resource(dev, SYS_RES_IOPORT, sc->csid, sc->cs);
2575 bus_release_resource(dev, SYS_RES_IOPORT, sc->mtid, sc->mt);
2576 snd_mtxfree(sc->lock);
2577 free(sc, M_ENVY24HT);
2578 return 0;
2579}
2580
2581static device_method_t envy24ht_methods[] = {
2582 /* Device interface */
2583 DEVMETHOD(device_probe, envy24ht_pci_probe),
2584 DEVMETHOD(device_attach, envy24ht_pci_attach),
2585 DEVMETHOD(device_detach, envy24ht_pci_detach),
2586 { 0, 0 }
2587};
2588
2589static driver_t envy24ht_driver = {
2590 "pcm",
2593};
2594
2595DRIVER_MODULE(snd_envy24ht, pci, envy24ht_driver, pcm_devclass, 0, 0);
2597MODULE_DEPEND(snd_envy24ht, snd_spicds, 1, 1, 1);
2598MODULE_VERSION(snd_envy24ht, 1);
#define AC97_DECLARE(name)
Definition: ac97.h:88
u_int32_t data
Definition: ac97_if.m:60
int regno
Definition: ac97_if.m:53
void * devinfo
Definition: ac97_if.m:47
uint32_t format
Definition: audio_dai_if.m:39
uint32_t rate
Definition: audio_dai_if.m:58
int go
Definition: audio_dai_if.m:64
METHOD int intr
Definition: audio_dai_if.m:91
const char * name
Definition: audio_soc.c:90
int sndbuf_setup(struct snd_dbuf *b, void *buf, unsigned int size)
Definition: buffer.c:123
unsigned int sndbuf_getfreeptr(struct snd_dbuf *b)
Definition: buffer.c:531
unsigned int sndbuf_getfree(struct snd_dbuf *b)
Definition: buffer.c:522
unsigned int sndbuf_getready(struct snd_dbuf *b)
Definition: buffer.c:504
int sndbuf_resize(struct snd_dbuf *b, unsigned int blkcnt, unsigned int blksz)
Definition: buffer.c:164
unsigned int sndbuf_getreadyptr(struct snd_dbuf *b)
Definition: buffer.c:513
void chn_intr(struct pcm_channel *c)
Definition: channel.c:660
#define PCMDIR_PLAY
Definition: channel.h:339
#define PCMTRIG_START
Definition: channel.h:344
#define PCMTRIG_EMLDMARD
Definition: channel.h:346
#define PCMTRIG_EMLDMAWR
Definition: channel.h:345
#define PCMDIR_REC
Definition: channel.h:341
#define PCMTRIG_ABORT
Definition: channel.h:348
struct pcm_channel * c
Definition: channel_if.m:106
METHOD int free
Definition: channel_if.m:110
u_int32_t blocksize
Definition: channel_if.m:140
struct pcmchan_matrix * m
Definition: channel_if.m:232
struct snd_dbuf * b
Definition: channel_if.m:105
struct ehci_itd * prev
#define PCIM_LAC_DISABLE
Definition: envy24.h:45
#define BUS_SPACE_MAXSIZE_ENVY24
Definition: envy24.h:354
#define PCIR_CCS
Definition: envy24.h:39
#define PCIV_ENVY24
Definition: envy24.h:34
#define PCIR_MT
Definition: envy24.h:42
#define PCIR_LAC
Definition: envy24.h:44
static u_int32_t envy24htchan_setblocksize(kobj_t, void *, u_int32_t)
Definition: envy24ht.c:1638
static int envy24htmixer_uninit(struct snd_mixer *)
Definition: envy24ht.c:1899
static kobj_method_t envy24htchan_methods[]
Definition: envy24ht.c:1840
static void * envy24htchan_init(kobj_t, void *, struct snd_dbuf *, struct pcm_channel *, int)
Definition: envy24ht.c:1482
static int envy24htchan_setformat(kobj_t, void *, u_int32_t)
Definition: envy24ht.c:1547
static void envy24ht_spi_reinit(void *)
Definition: envy24ht.c:996
static void envy24ht_r16sl(struct sc_chinfo *)
Definition: envy24ht.c:1449
u_int32_t speed
Definition: envy24ht.c:1026
static void envy24ht_start(struct sc_info *sc, int dir)
Definition: envy24ht.c:1260
DRIVER_MODULE(snd_envy24ht, pci, envy24ht_driver, pcm_devclass, 0, 0)
static void envy24ht_p32sl(struct sc_chinfo *)
Definition: envy24ht.c:1314
static void envy24ht_gpiosetmask(struct sc_info *sc, u_int32_t mask)
Definition: envy24ht.c:859
static int envy24ht_init(struct sc_info *sc)
Definition: envy24ht.c:2292
static u_int32_t envy24htchan_getptr(kobj_t, void *)
Definition: envy24ht.c:1791
static u_int32_t envy24ht_rdcs(struct sc_info *sc, int regno, int size)
Definition: envy24ht.c:459
static int envy24ht_pci_probe(device_t dev)
Definition: envy24ht.c:2051
static struct envy24ht_emldma envy24ht_pemltab[]
Definition: envy24ht.c:442
static struct pcmchan_caps envy24ht_reccaps
Definition: envy24ht.c:425
static int envy24ht_pci_attach(device_t dev)
Definition: envy24ht.c:2453
#define ENVY24HT_PLAY_CHNUM
Definition: envy24ht.c:64
static void * envy24ht_spi_create(device_t, void *, int, int)
Definition: envy24ht.c:916
static void envy24ht_p8u(struct sc_chinfo *)
Definition: envy24ht.c:1389
static struct pcmchan_caps * envy24htchan_getcaps(kobj_t, void *)
Definition: envy24ht.c:1813
static void envy24ht_stop(struct sc_info *sc, int dir)
Definition: envy24ht.c:1284
static int envy24ht_pci_detach(device_t dev)
Definition: envy24ht.c:2547
static void envy24ht_dmarsetmap(void *arg, bus_dma_segment_t *segs, int nseg, int error)
Definition: envy24ht.c:2102
static void envy24ht_gpiosetdir(struct sc_info *sc, u_int32_t dir)
Definition: envy24ht.c:876
static int envy24ht_mixmap[]
Definition: envy24ht.c:238
#define ENVY24HT_REC_CHNUM
Definition: envy24ht.c:65
static int envy24ht_rdi2c(struct sc_info *sc, u_int32_t dev, u_int32_t addr)
Definition: envy24ht.c:525
static u_int32_t envy24ht_setspeed(struct sc_info *sc, u_int32_t speed)
Definition: envy24ht.c:1048
static int envy24htmixer_init(struct snd_mixer *)
Definition: envy24ht.c:1858
static int envy24htchan_free(kobj_t obj, void *data)
Definition: envy24ht.c:1528
static struct codec_entry spi_codec
Definition: envy24ht.c:273
static struct @6 envy24ht_speedtab[]
static void envy24ht_p16sl(struct sc_chinfo *)
Definition: envy24ht.c:1344
static struct cfg_info cfg_table[]
Definition: envy24ht.c:282
static void envy24ht_intr(void *p)
Definition: envy24ht.c:1982
static void envy24ht_spi_setvolume(void *, int, unsigned int, unsigned int)
Definition: envy24ht.c:1009
static int envy24htmixer_reinit(struct snd_mixer *)
Definition: envy24ht.c:1885
static u_int32_t envy24htchan_setspeed(kobj_t, void *, u_int32_t)
Definition: envy24ht.c:1613
static kobj_method_t envy24htmixer_methods[]
Definition: envy24ht.c:1968
SND_DECLARE_FILE("$FreeBSD$")
static device_method_t envy24ht_methods[]
Definition: envy24ht.c:2581
static void envy24ht_wrcs(struct sc_info *sc, int regno, u_int32_t data, int size)
Definition: envy24ht.c:474
static void envy24ht_spi_init(void *)
Definition: envy24ht.c:970
static MALLOC_DEFINE(M_ENVY24HT, "envy24ht", "envy24ht audio")
static void envy24ht_mutevolume(struct sc_info *sc, unsigned ch)
Definition: envy24ht.c:1112
static int envy24ht_checkintr(struct sc_info *sc, int dir)
Definition: envy24ht.c:1227
static struct pcmchan_caps envy24ht_playcaps
Definition: envy24ht.c:434
static int envy24ht_rdrom(struct sc_info *sc, u_int32_t addr)
Definition: envy24ht.c:598
static void envy24ht_gpiowr(struct sc_info *sc, u_int32_t data)
Definition: envy24ht.c:838
static int envy24ht_wri2c(struct sc_info *sc, u_int32_t dev, u_int32_t addr, u_int32_t data)
Definition: envy24ht.c:563
static int envy24ht_dmainit(struct sc_info *sc)
Definition: envy24ht.c:2155
static u_int32_t envy24ht_gethwptr(struct sc_info *sc, int dir)
Definition: envy24ht.c:1127
MODULE_VERSION(snd_envy24ht, 1)
static int envy24htmixer_set(struct snd_mixer *, unsigned, unsigned, unsigned)
Definition: envy24ht.c:1913
static void envy24ht_dmapsetmap(void *arg, bus_dma_segment_t *segs, int nseg, int error)
Definition: envy24ht.c:2084
static driver_t envy24ht_driver
Definition: envy24ht.c:2589
MIXER_DECLARE(envy24htmixer)
static u_int32_t envy24ht_recfmt[]
Definition: envy24ht.c:420
static void envy24ht_spi_ctl(void *codec, unsigned int cs, unsigned int cclk, unsigned int cdti)
Definition: envy24ht.c:898
static int envy24htchan_trigger(kobj_t, void *, int)
Definition: envy24ht.c:1681
static u_int32_t envy24ht_gpiord(struct sc_info *sc)
Definition: envy24ht.c:829
static u_int32_t envy24ht_speed[]
Definition: envy24ht.c:267
#define ENVY24HT_SAMPLE_NUM
Definition: envy24ht.c:68
static void envy24ht_cfgfree(struct cfg_info *cfg)
Definition: envy24ht.c:709
#define ENVY24HT_PLAY_BUFUNIT
Definition: envy24ht.c:66
static struct cfg_info * envy24ht_rom2cfg(struct sc_info *sc)
Definition: envy24ht.c:617
#define ENVY24HT_TIMEOUT
Definition: envy24ht.c:70
#define ENVY24HT_REC_BUFUNIT
Definition: envy24ht.c:67
static u_int32_t envy24ht_playfmt[]
Definition: envy24ht.c:427
static u_int32_t envy24htmixer_setrecsrc(struct snd_mixer *, u_int32_t)
Definition: envy24ht.c:1955
static struct envy24ht_emldma envy24ht_remltab[]
Definition: envy24ht.c:449
static void envy24ht_setvolume(struct sc_info *sc, unsigned ch)
Definition: envy24ht.c:1100
MODULE_DEPEND(snd_envy24ht, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER)
u_int32_t code
Definition: envy24ht.c:1027
static unsigned envy24ht_chanmap[ENVY24HT_CHAN_NUM]
Definition: envy24ht.c:223
static void envy24ht_spi_destroy(void *)
Definition: envy24ht.c:948
static void envy24ht_updintr(struct sc_info *sc, int dir)
Definition: envy24ht.c:1157
static void envy24ht_dmafree(struct sc_info *sc)
Definition: envy24ht.c:2120
static u_int32_t envy24ht_rdmt(struct sc_info *sc, int regno, int size)
Definition: envy24ht.c:490
static int envy24ht_alloc_resource(struct sc_info *sc)
Definition: envy24ht.c:2400
static void envy24ht_wrmt(struct sc_info *sc, int regno, u_int32_t data, int size)
Definition: envy24ht.c:505
CHANNEL_DECLARE(envy24htchan)
static void envy24ht_putcfg(struct sc_info *sc)
Definition: envy24ht.c:2200
static void envy24ht_r32sl(struct sc_chinfo *)
Definition: envy24ht.c:1419
#define ENVY24HT_CCS_I2CDATA
Definition: envy24ht.h:56
#define ENVY24HT_CCS_ACL
Definition: envy24ht.h:71
#define ENVY24HT_MT_I2S
Definition: envy24ht.h:121
#define ENVY24HT_CCS_I2CDEV_RD
Definition: envy24ht.h:53
#define ENVY24HT_MT_INT_PSTAT
Definition: envy24ht.h:97
#define ENVY24HT_CHAN_REC_MIX
Definition: envy24ht.h:170
#define ENVY24HT_CCS_SPDIF
Definition: envy24ht.h:86
#define ENVY24HT_CCS_GPIO_HMASK
Definition: envy24ht.h:185
#define ENVY24HT_MT_PCTL_RSTART
Definition: envy24ht.h:129
#define ENVY24HT_CCS_I2CDEV
Definition: envy24ht.h:49
#define ENVY24HT_E2PROM_SCFG
Definition: envy24ht.h:144
#define ENVY24HT_E2PROM_SUBVENDOR
Definition: envy24ht.h:140
#define ENVY24HT_MT_RATE_96000
Definition: envy24ht.h:111
#define ENVY24HT_VOL_MUTE
Definition: envy24ht.h:178
#define ENVY24HT_CHAN_REC_ADC3
Definition: envy24ht.h:167
#define ENVY24HT_MT_RATE_48000
Definition: envy24ht.h:104
#define ENVY24HT_CHAN_REC_ADC1
Definition: envy24ht.h:165
#define ENVY24HT_CCSM_SPDIF_ID
Definition: envy24ht.h:89
#define ENVY24HT_MT_INT_RSTAT
Definition: envy24ht.h:96
#define ENVY24HT_VOL_MIN
Definition: envy24ht.h:177
#define ENVY24HT_CCSM_I2S_18BIT
Definition: envy24ht.h:81
#define ENVY24HT_CCSM_I2S_RES
Definition: envy24ht.h:79
#define ENVY24HT_CCSM_I2S_96KHZ
Definition: envy24ht.h:77
#define ENVY24HT_CCS_I2CDEV_ADDR
Definition: envy24ht.h:50
#define ENVY24HT_E2PROM_SUBDEVICE
Definition: envy24ht.h:141
#define ENVY24HT_CCS_SCFG
Definition: envy24ht.h:62
#define ENVY24HT_MT_RATE_24000
Definition: envy24ht.h:105
#define ENVY24HT_MT_RATE_64000
Definition: envy24ht.h:113
#define ENVY24HT_CHAN_PLAY_SPDIF
Definition: envy24ht.h:164
#define ENVY24HT_CCS_I2CSTAT
Definition: envy24ht.h:58
#define ENVY24HT_MT_RATE_12000
Definition: envy24ht.h:106
#define ENVY24HT_CCSM_SPDIF_IN
Definition: envy24ht.h:90
#define ENVY24HT_MT_RATE_SPDIF
Definition: envy24ht.h:103
#define ENVY24HT_CCS_IMASK
Definition: envy24ht.h:46
#define ENVY24HT_CHAN_PLAY_DAC4
Definition: envy24ht.h:163
#define ENVY24HT_MT_INT_MASK
Definition: envy24ht.h:98
#define ENVY24HT_CCSM_SPDIF_OUT
Definition: envy24ht.h:91
#define ENVY24HT_CCS_CTL_RESET
Definition: envy24ht.h:44
#define ENVY24HT_MIX_MASK
Definition: envy24ht.h:172
#define ENVY24HT_CCS_IMASK_PMT
Definition: envy24ht.h:47
#define ENVY24HT_CCSM_ACL_OMODE
Definition: envy24ht.h:73
#define ENVY24HT_CCS_I2CDEV_WR
Definition: envy24ht.h:52
#define ENVY24HT_MT_RATE_9600
Definition: envy24ht.h:107
#define ENVY24HT_CHAN_REC_SPDIF
Definition: envy24ht.h:169
#define ENVY24HT_MT_RATE_11025
Definition: envy24ht.h:116
#define ENVY24HT_CCSM_I2S_16BIT
Definition: envy24ht.h:80
#define ENVY24HT_CCS_GPIO_CTLDIR
Definition: envy24ht.h:186
#define ENVY24HT_CCSM_SCFG_MPU
Definition: envy24ht.h:67
#define ENVY24HT_MT_PCTL
Definition: envy24ht.h:128
#define ENVY24HT_MT_I2S_MLR128
Definition: envy24ht.h:122
#define ENVY24HT_MT_RATE_176400
Definition: envy24ht.h:118
#define ENVY24HT_MT_RATE_16000
Definition: envy24ht.h:109
#define ENVY24HT_MT_RATE_8000
Definition: envy24ht.h:110
#define ENVY24HT_E2PROM_I2S
Definition: envy24ht.h:146
#define ENVY24HT_CCS_I2CSTAT_ROM
Definition: envy24ht.h:59
#define ENVY24HT_E2PROM_SPDIF
Definition: envy24ht.h:147
#define ENVY24HT_E2PROM_GPIOSTATE
Definition: envy24ht.h:149
#define ENVY24HT_CCSM_SCFG_ADC
Definition: envy24ht.h:68
#define ENVY24HT_CCS_I2CSTAT_BSY
Definition: envy24ht.h:60
#define ENVY24HT_MT_PADDR
Definition: envy24ht.h:124
#define ENVY24HT_CHAN_PLAY_DAC1
Definition: envy24ht.h:160
#define ENVY24HT_CHAN_PLAY_DAC3
Definition: envy24ht.h:162
#define ENVY24HT_MT_RATE_32000
Definition: envy24ht.h:108
#define ENVY24HT_MT_RCNT
Definition: envy24ht.h:133
#define ENVY24HT_CCSM_I2S_24BIT
Definition: envy24ht.h:83
#define ENVY24HT_MT_PCTL_PSTART
Definition: envy24ht.h:130
#define ENVY24HT_CHAN_REC_ADC2
Definition: envy24ht.h:166
#define ENVY24HT_CCS_I2CADDR
Definition: envy24ht.h:55
#define ENVY24HT_CHAN_PLAY_DAC2
Definition: envy24ht.h:161
#define ENVY24HT_E2PROM_ACL
Definition: envy24ht.h:145
#define ENVY24HT_CCSM_ACL_MTC
Definition: envy24ht.h:72
#define ENVY24HT_MT_INT_PMASK
Definition: envy24ht.h:100
#define ENVY24HT_CHAN_NUM
Definition: envy24ht.h:158
#define ENVY24HT_MT_PCNT
Definition: envy24ht.h:125
#define ENVY24HT_CCS_I2CDEV_ROM
Definition: envy24ht.h:51
#define ENVY24HT_CCS_CTL
Definition: envy24ht.h:43
#define ENVY24HT_MT_RATE_192000
Definition: envy24ht.h:112
#define ENVY24HT_CCSM_I2S_192KHZ
Definition: envy24ht.h:78
#define ENVY24HT_E2PROM_GPIODIR
Definition: envy24ht.h:150
#define ENVY24HT_MT_RATE_88200
Definition: envy24ht.h:117
#define ENVY24HT_MT_PTERM
Definition: envy24ht.h:126
#define ENVY24HT_CCSM_SCFG_XIN2
Definition: envy24ht.h:63
#define ENVY24HT_CCSM_SCFG_DAC
Definition: envy24ht.h:69
#define ENVY24HT_CCS_GPIO_LMASK
Definition: envy24ht.h:184
#define ENVY24HT_MT_RATE
Definition: envy24ht.h:102
#define ENVY24HT_CCSM_I2S_VOL
Definition: envy24ht.h:76
#define ENVY24HT_MT_RATE_22050
Definition: envy24ht.h:115
#define ENVY24HT_CCS_I2S
Definition: envy24ht.h:75
#define ENVY24HT_MT_RADDR
Definition: envy24ht.h:132
#define ENVY24HT_MT_RATE_MASK
Definition: envy24ht.h:119
#define ENVY24HT_CCSM_I2S_ID
Definition: envy24ht.h:84
#define ENVY24HT_MT_INT_RMASK
Definition: envy24ht.h:99
#define ENVY24HT_MT_INT_STAT
Definition: envy24ht.h:95
#define PCID_ENVY24HT
Definition: envy24ht.h:36
#define ENVY24HT_CCS_GPIO_LDATA
Definition: envy24ht.h:183
#define ENVY24HT_MIX_REC_MASK
Definition: envy24ht.h:173
#define ENVY24HT_E2PROM_GPIOMASK
Definition: envy24ht.h:148
#define ENVY24HT_MT_RTERM
Definition: envy24ht.h:134
#define ENVY24HT_CCSM_I2S_20BIT
Definition: envy24ht.h:82
#define ENVY24HT_MT_RATE_44100
Definition: envy24ht.h:114
#define ENVY24HT_CHAN_REC_ADC4
Definition: envy24ht.h:168
#define ENVY24HT_PCIR_MT
Definition: envy24ht.h:39
#define ENVY24HT_CCS_GPIO_HDATA
Definition: envy24ht.h:182
#define ENVY24HT_E2PROM_SIZE
Definition: envy24ht.h:142
unsigned right
Definition: es137x.c:261
unsigned left
Definition: es137x.c:260
METHOD int feed
Definition: feeder_if.m:82
uint8_t mask
Definition: hdac.c:212
int dir
Definition: hdac_if.m:45
uint8_t size
uint8_t r
uint16_t fail
struct @109 error
#define KOBJMETHOD_END
Definition: midi.c:76
static int mixer_setrecsrc(struct snd_mixer *mixer, u_int32_t src)
Definition: mixer.c:373
int mixer_init(device_t dev, kobj_class_t cls, void *devinfo)
Definition: mixer.c:725
static int mixer_set(struct snd_mixer *m, u_int dev, u_int32_t muted, u_int lev)
Definition: mixer.c:247
int mixer_uninit(device_t dev)
Definition: mixer.c:805
void mix_setdevs(struct snd_mixer *m, u_int32_t v)
Definition: mixer.c:489
int mixer_reinit(device_t dev)
Definition: mixer.c:860
void * mix_getdevinfo(struct snd_mixer *m)
Definition: mixer.c:645
void mix_setrecdevs(struct snd_mixer *m, u_int32_t v)
Record mask of available recording devices.
Definition: mixer.c:529
unsigned dev
Definition: mixer_if.m:59
u_int32_t src
Definition: mixer_if.m:66
bool * status
u_int32_t val
uint64_t * addr
u_int slot
void * snd_mtxcreate(const char *desc, const char *type)
Definition: sound.c:88
void pcm_setflags(device_t dev, uint32_t val)
Definition: sound.c:824
void * pcm_getdevinfo(device_t dev)
Definition: sound.c:832
uint32_t pcm_getflags(device_t dev)
Definition: sound.c:816
int pcm_setstatus(device_t dev, char *str)
Definition: sound.c:766
devclass_t pcm_devclass
Definition: sound.c:49
void snd_mtxfree(void *m)
Definition: sound.c:98
int pcm_addchan(device_t dev, int dir, kobj_class_t cls, void *devinfo)
Definition: sound.c:692
int pcm_unregister(device_t dev)
Definition: sound.c:1170
int pcm_register(device_t dev, void *devinfo, int numplay, int numrec)
Definition: sound.c:1080
int snd_setup_intr(device_t dev, struct resource *res, int flags, driver_intr_t hand, void *param, void **cookiep)
Definition: sound.c:117
#define SND_FORMAT(f, c, e)
Definition: sound.h:238
#define SOUND_PREFVER
Definition: sound.h:103
#define SOUND_MAXVER
Definition: sound.h:104
#define SD_F_SOFTPCMVOL
Definition: sound.h:134
#define snd_mtxlock(m)
Definition: sound.h:347
#define snd_mtxunlock(m)
Definition: sound.h:348
#define SOUND_MINVER
Definition: sound.h:102
#define PCM_SOFTC_SIZE
Definition: sound.h:96
#define SND_STATUSLEN
Definition: sound.h:98
void spicds_set(struct spicds_info *codec, int dir, unsigned int left, unsigned int right)
Definition: spicds.c:274
void spicds_setdvc(struct spicds_info *codec, unsigned int dvc)
Definition: spicds.c:199
void spicds_settype(struct spicds_info *codec, unsigned int type)
Definition: spicds.c:175
void spicds_setformat(struct spicds_info *codec, unsigned int format)
Definition: spicds.c:191
void spicds_reinit(struct spicds_info *codec)
Definition: spicds.c:253
struct spicds_info * spicds_create(device_t dev, void *devinfo, int num, spicds_ctrl ctrl)
Definition: spicds.c:142
void spicds_init(struct spicds_info *codec)
Definition: spicds.c:207
void spicds_setcif(struct spicds_info *codec, unsigned int cif)
Definition: spicds.c:183
void spicds_destroy(struct spicds_info *codec)
Definition: spicds.c:168
#define AK452X_FORMAT_256FSN
Definition: spicds.h:56
#define SPICDS_TYPE_AK4528
Definition: spicds.h:34
#define AK452X_DVC_DEMOFF
Definition: spicds.h:68
#define AK452X_FORMAT_1X
Definition: spicds.h:52
#define SPICDS_TYPE_AK4524
Definition: spicds.h:33
#define AK452X_FORMAT_I2S
Definition: spicds.h:64
u_int8_t acl
Definition: envy24.c:111
u_int8_t gpiodir
Definition: envy24.c:112
u_int16_t subvendor
Definition: envy24.c:110
char * name
Definition: envy24.c:109
u_int32_t gpiodir
Definition: envy24ht.c:121
u_int32_t cclk
Definition: envy24ht.c:122
u_int8_t free
Definition: envy24.c:114
u_int8_t spdif
Definition: envy24.c:111
u_int8_t type
Definition: envy24.c:113
u_int8_t cdti
Definition: envy24.c:113
u_int16_t subdevice
Definition: envy24.c:110
u_int8_t cs
Definition: envy24.c:113
u_int8_t gpiomask
Definition: envy24.c:112
u_int8_t cif
Definition: envy24.c:113
u_int8_t scfg
Definition: envy24.c:111
struct codec_entry * codec
Definition: envy24.c:115
u_int8_t cclk
Definition: envy24.c:113
u_int8_t gpiostate
Definition: envy24.c:112
u_int8_t i2s
Definition: envy24.c:111
Definition: envy24.c:98
void(* setrate)(void *codec, int which, int rate)
Definition: envy24.c:104
void(* reinit)(void *codec)
Definition: envy24.c:102
void(* destroy)(void *codec)
Definition: envy24.c:100
void(* setvolume)(void *codec, int dir, unsigned int left, unsigned int right)
Definition: envy24.c:103
void(* init)(void *codec)
Definition: envy24.c:101
void *(* create)(device_t dev, void *devinfo, int dir, int num)
Definition: envy24.c:99
volatile u_int32_t buffer
Definition: envy24.c:68
u_int32_t format
Definition: envy24ht.c:437
void(* emldma)(struct sc_chinfo *)
Definition: envy24ht.c:438
volatile u_int32_t buffer
Definition: envy24ht.c:77
struct sc_info * parent
Definition: envy24ht.c:891
struct spicds_info * info
Definition: envy24ht.c:890
u_int32_t speed
Definition: channel.h:94
u_int32_t maxspeed
Definition: channel.h:34
u_int32_t * fmtlist
Definition: channel.h:35
u_int32_t minspeed
Definition: channel.h:34
u_int32_t speed
Definition: als4000.c:70
unsigned int size
Definition: envy24.c:88
int run
Definition: envy24.c:94
int unit
Definition: envy24.c:89
u_int8_t * data
Definition: envy24.c:87
struct pcm_channel * channel
Definition: als4000.c:68
u_int32_t format
Definition: als4000.c:70
unsigned int offset
Definition: envy24.c:90
u_int32_t blk
Definition: envy24.c:84
void(* emldma)(struct sc_chinfo *)
Definition: envy24.c:91
struct sc_info * parent
Definition: als4000.c:67
unsigned num
Definition: envy24.c:79
int dir
Definition: als4000.c:73
struct snd_dbuf * buffer
Definition: als4000.c:69
u_int8_t right[ENVY24_CHAN_NUM]
Definition: envy24.c:160
u_int8_t left[ENVY24_CHAN_NUM]
Definition: envy24.c:159
int run[2]
Definition: envy24.c:172
struct resource * mt
Definition: envy24.c:139
struct mtx * lock
Definition: als4000.c:84
struct resource * cs
Definition: envy24.c:124
sample32_t * rbuf
Definition: envy24.c:164
bus_dmamap_t pmap
Definition: envy24.c:167
struct resource * irq
Definition: als4000.c:81
u_int16_t blk[2]
Definition: envy24.c:166
struct cfg_info * cfg
Definition: envy24.c:151
int dacn
Definition: envy24.c:154
sample32_t * pbuf
Definition: envy24.c:163
device_t dev
Definition: als4000.c:77
int mtid
Definition: envy24.c:140
int csid
Definition: envy24.c:125
bus_addr_t raddr
Definition: envy24.c:168
bus_space_handle_t csh
Definition: envy24.c:127
int irqid
Definition: als4000.c:82
bus_space_tag_t mtt
Definition: envy24.c:141
bus_space_handle_t mth
Definition: envy24.c:142
void * adc[4]
Definition: envy24.c:155
u_int32_t rsize
Definition: envy24.c:165
unsigned chnum
Definition: envy24.c:177
struct sc_chinfo chan[11]
Definition: envy24.c:178
struct pcmchan_caps caps[2]
Definition: envy24.c:174
bus_dma_tag_t dmat
Definition: envy24.c:144
bus_addr_t paddr
Definition: envy24.c:168
int adcn
Definition: envy24.c:154
void * ih
Definition: als4000.c:83
u_int16_t intr[2]
Definition: envy24.c:173
bus_space_tag_t cst
Definition: envy24.c:126
u_int32_t src
Definition: envy24.c:158
bus_dmamap_t rmap
Definition: envy24.c:167
struct sc_chinfo ch[3]
Definition: ich.c:192
void * dac[4]
Definition: envy24.c:155
struct ac97_info * codec
Definition: ich.c:191
u_int32_t psize
Definition: envy24.c:165
u_int32_t speed
Definition: envy24.c:171