2 * Copyright (c) 2001 Katsurajima Naoto <raven@katsurajima.seya.yokohama.jp>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHERIN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 #ifdef HAVE_KERNEL_OPTION_HEADERS
32 #include <dev/sound/pcm/sound.h>
33 #include <dev/sound/pcm/ac97.h>
34 #include <dev/sound/pci/spicds.h>
35 #include <dev/sound/pci/envy24.h>
37 #include <dev/pci/pcireg.h>
38 #include <dev/pci/pcivar.h>
42 SND_DECLARE_FILE("$FreeBSD$");
44 static MALLOC_DEFINE(M_ENVY24, "envy24", "envy24 audio");
46 /* -------------------------------------------------------------------- */
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
56 #define ENVY24_TIMEOUT 1000
58 #define ENVY24_DEFAULT_FORMAT SND_FORMAT(AFMT_S16_LE, 2, 0)
60 #define ENVY24_NAMELEN 32
65 struct envy24_sample {
66 volatile u_int32_t buffer;
69 typedef struct envy24_sample sample32_t;
71 /* channel registers */
73 struct snd_dbuf *buffer;
74 struct pcm_channel *channel;
75 struct sc_info *parent;
77 unsigned num; /* hw channel number */
79 /* channel information */
82 u_int32_t blk; /* hw block size(dword) */
84 /* format conversion structure */
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 *);
95 /* codec interface entrys */
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);
105 /* system configuration information */
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;
113 struct codec_entry *codec;
116 /* device private data */
121 /* Control/Status registor */
125 bus_space_handle_t csh;
127 struct resource *ddma;
129 bus_space_tag_t ddmat;
130 bus_space_handle_t ddmah;
131 /* Consumer Section DMA Channel Registers */
135 bus_space_handle_t dsh;
136 /* MultiTrack registor */
140 bus_space_handle_t mth;
144 struct resource *irq;
148 /* system configuration data */
149 struct cfg_info *cfg;
151 /* ADC/DAC number and info */
153 void *adc[4], *dac[4];
155 /* mixer control data */
157 u_int8_t left[ENVY24_CHAN_NUM];
158 u_int8_t right[ENVY24_CHAN_NUM];
160 /* Play/Record DMA fifo */
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;
172 struct pcmchan_caps caps[2];
174 /* channel info table */
176 struct sc_chinfo chan[11];
179 /* -------------------------------------------------------------------- */
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 *);
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 *);
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);
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);
215 /* -------------------------------------------------------------------- */
218 system constant tables
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 */
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 */
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 */
262 -1, /* Monitor volume */
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
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,
281 static struct cfg_info cfg_table[] = {
283 "Envy24 audio (M Audio Delta Dio 2496)",
285 0x10, 0x80, 0xf0, 0x03,
287 0x10, 0x20, 0x40, 0x00, 0x00,
292 "Envy24 audio (Terratec DMX 6fire)",
294 0x2f, 0x80, 0xf0, 0x03,
296 0x10, 0x20, 0x01, 0x01, 0x00,
301 "Envy24 audio (M Audio Audiophile 2496)",
303 0x10, 0x80, 0x72, 0x03,
305 0x08, 0x02, 0x20, 0x00, 0x01,
310 "Envy24 audio (M Audio Delta 66)",
312 0x15, 0x80, 0xf0, 0x03,
314 0x10, 0x20, 0x40, 0x00, 0x00,
319 "Envy24 audio (M Audio Delta 44)",
321 0x15, 0x80, 0xf0, 0x00,
323 0x10, 0x20, 0x40, 0x00, 0x00,
328 "Envy24 audio (M Audio Delta 1010)",
330 0x1f, 0x80, 0xf0, 0x03,
332 0x10, 0x20, 0x40, 0x00, 0x00,
337 "Envy24 audio (M Audio Delta 1010LT)",
339 0x1f, 0x80, 0x72, 0x03,
341 0x08, 0x02, 0x70, 0x00, 0x00,
346 "Envy24 audio (Terratec EWX 2496)",
348 0x10, 0x80, 0xf0, 0x03,
350 0x10, 0x20, 0x01, 0x01, 0x00,
355 "Envy24 audio (Generic)",
357 0x0f, 0x00, 0x01, 0x03,
359 0x10, 0x20, 0x40, 0x00, 0x00,
361 &delta_codec, /* default codec routines */
365 static u_int32_t envy24_recfmt[] = {
366 SND_FORMAT(AFMT_S16_LE, 2, 0),
367 SND_FORMAT(AFMT_S32_LE, 2, 0),
370 static struct pcmchan_caps envy24_reccaps = {8000, 96000, envy24_recfmt, 0};
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),
379 static struct pcmchan_caps envy24_playcaps = {8000, 96000, envy24_playfmt, 0};
381 struct envy24_emldma {
383 void (*emldma)(struct sc_chinfo *);
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},
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},
400 /* -------------------------------------------------------------------- */
402 /* common routines */
404 envy24_rdcs(struct sc_info *sc, int regno, int size)
408 return bus_space_read_1(sc->cst, sc->csh, regno);
410 return bus_space_read_2(sc->cst, sc->csh, regno);
412 return bus_space_read_4(sc->cst, sc->csh, regno);
419 envy24_wrcs(struct sc_info *sc, int regno, u_int32_t data, int size)
423 bus_space_write_1(sc->cst, sc->csh, regno, data);
426 bus_space_write_2(sc->cst, sc->csh, regno, data);
429 bus_space_write_4(sc->cst, sc->csh, regno, data);
435 envy24_rdmt(struct sc_info *sc, int regno, int size)
439 return bus_space_read_1(sc->mtt, sc->mth, regno);
441 return bus_space_read_2(sc->mtt, sc->mth, regno);
443 return bus_space_read_4(sc->mtt, sc->mth, regno);
450 envy24_wrmt(struct sc_info *sc, int regno, u_int32_t data, int size)
454 bus_space_write_1(sc->mtt, sc->mth, regno, data);
457 bus_space_write_2(sc->mtt, sc->mth, regno, data);
460 bus_space_write_4(sc->mtt, sc->mth, regno, data);
466 envy24_rdci(struct sc_info *sc, int regno)
468 envy24_wrcs(sc, ENVY24_CCS_INDEX, regno, 1);
469 return envy24_rdcs(sc, ENVY24_CCS_DATA, 1);
473 envy24_wrci(struct sc_info *sc, int regno, u_int32_t data)
475 envy24_wrcs(sc, ENVY24_CCS_INDEX, regno, 1);
476 envy24_wrcs(sc, ENVY24_CCS_DATA, data, 1);
479 /* -------------------------------------------------------------------- */
481 /* I2C port/E2PROM access routines */
484 envy24_rdi2c(struct sc_info *sc, u_int32_t dev, u_int32_t addr)
490 device_printf(sc->dev, "envy24_rdi2c(sc, 0x%02x, 0x%02x)\n", dev, addr);
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)
496 DELAY(32); /* 31.25kHz */
498 if (i == ENVY24_TIMEOUT) {
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)
508 DELAY(32); /* 31.25kHz */
510 if (i == ENVY24_TIMEOUT) {
513 data = envy24_rdcs(sc, ENVY24_CCS_I2CDATA, 1);
516 device_printf(sc->dev, "envy24_rdi2c(): return 0x%x\n", data);
523 envy24_wri2c(struct sc_info *sc, u_int32_t dev, u_int32_t addr, u_int32_t data)
529 device_printf(sc->dev, "envy24_rdi2c(sc, 0x%02x, 0x%02x)\n", dev, addr);
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)
535 DELAY(32); /* 31.25kHz */
537 if (i == ENVY24_TIMEOUT) {
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)
548 DELAY(32); /* 31.25kHz */
550 if (i == ENVY24_TIMEOUT) {
559 envy24_rdrom(struct sc_info *sc, u_int32_t addr)
564 device_printf(sc->dev, "envy24_rdrom(sc, 0x%02x)\n", addr);
566 data = envy24_rdcs(sc, ENVY24_CCS_I2CSTAT, 1);
567 if ((data & ENVY24_CCS_I2CSTAT_ROM) == 0) {
569 device_printf(sc->dev, "envy24_rdrom(): E2PROM not presented\n");
574 return envy24_rdi2c(sc, ENVY24_CCS_I2CDEV_ROM, addr);
577 static struct cfg_info *
578 envy24_rom2cfg(struct sc_info *sc)
580 struct cfg_info *buff;
585 device_printf(sc->dev, "envy24_rom2cfg(sc)\n");
587 size = envy24_rdrom(sc, ENVY24_E2PROM_SIZE);
588 if (size < ENVY24_E2PROM_GPIODIR + 1) {
590 device_printf(sc->dev, "envy24_rom2cfg(): ENVY24_E2PROM_SIZE-->%d\n", size);
594 buff = malloc(sizeof(*buff), M_ENVY24, M_NOWAIT);
597 device_printf(sc->dev, "envy24_rom2cfg(): malloc()\n");
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);
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)
619 buff->name = cfg_table[i].name;
620 buff->codec = cfg_table[i].codec;
626 envy24_cfgfree(struct cfg_info *cfg) {
634 /* -------------------------------------------------------------------- */
636 /* AC'97 codec access routines */
640 envy24_coldcd(struct sc_info *sc)
646 device_printf(sc->dev, "envy24_coldcd()\n");
648 envy24_wrmt(sc, ENVY24_MT_AC97CMD, ENVY24_MT_AC97CMD_CLD, 1);
650 envy24_wrmt(sc, ENVY24_MT_AC97CMD, 0, 1);
652 for (i = 0; i < ENVY24_TIMEOUT; i++) {
653 data = envy24_rdmt(sc, ENVY24_MT_AC97CMD, 1);
654 if (data & ENVY24_MT_AC97CMD_RDY) {
664 envy24_slavecd(struct sc_info *sc)
670 device_printf(sc->dev, "envy24_slavecd()\n");
672 envy24_wrmt(sc, ENVY24_MT_AC97CMD,
673 ENVY24_MT_AC97CMD_CLD | ENVY24_MT_AC97CMD_WRM, 1);
675 envy24_wrmt(sc, ENVY24_MT_AC97CMD, 0, 1);
677 for (i = 0; i < ENVY24_TIMEOUT; i++) {
678 data = envy24_rdmt(sc, ENVY24_MT_AC97CMD, 1);
679 if (data & ENVY24_MT_AC97CMD_RDY) {
689 envy24_rdcd(kobj_t obj, void *devinfo, int regno)
691 struct sc_info *sc = (struct sc_info *)devinfo;
696 device_printf(sc->dev, "envy24_rdcd(obj, sc, 0x%02x)\n", regno);
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)
705 data = envy24_rdmt(sc, ENVY24_MT_AC97DLO, 2);
708 device_printf(sc->dev, "envy24_rdcd(): return 0x%x\n", data);
714 envy24_wrcd(kobj_t obj, void *devinfo, int regno, u_int16_t data)
716 struct sc_info *sc = (struct sc_info *)devinfo;
721 device_printf(sc->dev, "envy24_wrcd(obj, sc, 0x%02x, 0x%04x)\n", regno, data);
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)
735 static kobj_method_t envy24_ac97_methods[] = {
736 KOBJMETHOD(ac97_read, envy24_rdcd),
737 KOBJMETHOD(ac97_write, envy24_wrcd),
740 AC97_DECLARE(envy24_ac97);
743 /* -------------------------------------------------------------------- */
745 /* GPIO access routines */
748 envy24_gpiord(struct sc_info *sc)
750 return envy24_rdci(sc, ENVY24_CCI_GPIODAT);
754 envy24_gpiowr(struct sc_info *sc, u_int32_t data)
757 device_printf(sc->dev, "envy24_gpiowr(sc, 0x%02x)\n", data & 0xff);
760 envy24_wrci(sc, ENVY24_CCI_GPIODAT, data);
766 envy24_gpiogetmask(struct sc_info *sc)
768 return envy24_rdci(sc, ENVY24_CCI_GPIOMASK);
773 envy24_gpiosetmask(struct sc_info *sc, u_int32_t mask)
775 envy24_wrci(sc, ENVY24_CCI_GPIOMASK, mask);
781 envy24_gpiogetdir(struct sc_info *sc)
783 return envy24_rdci(sc, ENVY24_CCI_GPIOCTL);
788 envy24_gpiosetdir(struct sc_info *sc, u_int32_t dir)
790 envy24_wrci(sc, ENVY24_CCI_GPIOCTL, dir);
794 /* -------------------------------------------------------------------- */
796 /* Envy24 I2C through GPIO bit-banging */
798 struct envy24_delta_ak4524_codec {
799 struct spicds_info *info;
800 struct sc_info *parent;
807 envy24_gpio_i2c_ctl(void *codec, unsigned int scl, unsigned int sda)
810 struct envy24_delta_ak4524_codec *ptr = codec;
812 device_printf(ptr->parent->dev, "--> %d, %d\n", scl, sda);
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);
823 i2c_wrbit(void *codec, void (*ctrl)(void*, unsigned int, unsigned int), int bit)
825 struct envy24_delta_ak4524_codec *ptr = codec;
842 i2c_start(void *codec, void (*ctrl)(void*, unsigned int, unsigned int))
844 struct envy24_delta_ak4524_codec *ptr = codec;
855 i2c_stop(void *codec, void (*ctrl)(void*, unsigned int, unsigned int))
857 struct envy24_delta_ak4524_codec *ptr = codec;
868 i2c_ack(void *codec, void (*ctrl)(void*, unsigned int, unsigned int))
870 struct envy24_delta_ak4524_codec *ptr = codec;
876 /* dummy, need routine to change gpio direction */
882 i2c_wr(void *codec, void (*ctrl)(void*, unsigned int, unsigned int), u_int32_t dev, int reg, u_int8_t val)
884 struct envy24_delta_ak4524_codec *ptr = codec;
887 i2c_start(ptr, ctrl);
889 for (mask = 0x80; mask != 0; mask >>= 1)
890 i2c_wrbit(ptr, ctrl, dev & mask);
894 for (mask = 0x80; mask != 0; mask >>= 1)
895 i2c_wrbit(ptr, ctrl, reg & mask);
899 for (mask = 0x80; mask != 0; mask >>= 1)
900 i2c_wrbit(ptr, ctrl, val & mask);
906 /* -------------------------------------------------------------------- */
908 /* M-Audio Delta series AK4524 access interface routine */
911 envy24_delta_ak4524_ctl(void *codec, unsigned int cs, unsigned int cclk, unsigned int cdti)
914 struct envy24_delta_ak4524_codec *ptr = codec;
917 device_printf(ptr->parent->dev, "--> %d, %d, %d\n", cs, cclk, cdti);
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);
929 envy24_delta_ak4524_create(device_t dev, void *info, int dir, int num)
931 struct sc_info *sc = info;
932 struct envy24_delta_ak4524_codec *buff = NULL;
935 device_printf(sc->dev, "envy24_delta_ak4524_create(dev, sc, %d, %d)\n", dir, num);
938 buff = malloc(sizeof(*buff), M_ENVY24, M_NOWAIT);
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;
947 buff->info = spicds_create(dev, buff, num, envy24_delta_ak4524_ctl);
948 if (buff->info == NULL) {
949 free(buff, M_ENVY24);
961 envy24_delta_ak4524_destroy(void *codec)
963 struct envy24_delta_ak4524_codec *ptr = codec;
967 device_printf(ptr->parent->dev, "envy24_delta_ak4524_destroy()\n");
970 if (ptr->dir == PCMDIR_PLAY) {
971 if (ptr->parent->dac[ptr->num] != NULL)
972 spicds_destroy(ptr->info);
975 if (ptr->parent->adc[ptr->num] != NULL)
976 spicds_destroy(ptr->info);
979 free(codec, M_ENVY24);
983 envy24_delta_ak4524_init(void *codec)
986 u_int32_t gpiomask, gpiodir;
988 struct envy24_delta_ak4524_codec *ptr = codec;
992 device_printf(ptr->parent->dev, "envy24_delta_ak4524_init()\n");
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);
1003 ptr->cs = ptr->parent->cfg->cs;
1005 envy24_gpiosetmask(ptr->parent, ENVY24_GPIO_CS8414_STATUS);
1006 envy24_gpiosetdir(ptr->parent, ~ENVY24_GPIO_CS8414_STATUS);
1008 ptr->cs = ENVY24_GPIO_AK4524_CS0;
1010 ptr->cs = ENVY24_GPIO_AK4524_CS1;
1011 ptr->cclk = ENVY24_GPIO_AK4524_CCLK;
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 */
1022 spicds_init(ptr->info);
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) {
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);
1038 envy24_delta_ak4524_reinit(void *codec)
1040 struct envy24_delta_ak4524_codec *ptr = codec;
1044 device_printf(ptr->parent->dev, "envy24_delta_ak4524_reinit()\n");
1047 spicds_reinit(ptr->info);
1051 envy24_delta_ak4524_setvolume(void *codec, int dir, unsigned int left, unsigned int right)
1053 struct envy24_delta_ak4524_codec *ptr = codec;
1057 device_printf(ptr->parent->dev, "envy24_delta_ak4524_set()\n");
1060 spicds_set(ptr->info, dir, left, right);
1064 There is no need for AK452[48] codec to set sample rate
1066 envy24_delta_ak4524_setrate(struct envy24_delta_ak4524_codec *codec, int which, int rate)
1071 /* -------------------------------------------------------------------- */
1073 /* hardware access routeines */
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},
1096 envy24_setspeed(struct sc_info *sc, u_int32_t speed) {
1101 device_printf(sc->dev, "envy24_setspeed(sc, %d)\n", speed);
1104 code = ENVY24_MT_RATE_SPDIF; /* external master clock */
1108 for (i = 0; envy24_speedtab[i].speed != 0; i++) {
1109 if (envy24_speedtab[i].speed == speed)
1112 code = envy24_speedtab[i].code;
1115 device_printf(sc->dev, "envy24_setspeed(): speed %d/code 0x%04x\n", envy24_speedtab[i].speed, code);
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)
1125 speed = envy24_speedtab[i].speed;
1131 device_printf(sc->dev, "envy24_setspeed(): return %d\n", speed);
1137 envy24_setvolume(struct sc_info *sc, unsigned ch)
1140 device_printf(sc->dev, "envy24_setvolume(sc, %d)\n", ch);
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);
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);
1156 envy24_mutevolume(struct sc_info *sc, unsigned ch)
1161 device_printf(sc->dev, "envy24_mutevolume(sc, %d)\n", ch);
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);
1171 envy24_gethwptr(struct sc_info *sc, int dir)
1177 device_printf(sc->dev, "envy24_gethwptr(sc, %d)\n", dir);
1179 if (dir == PCMDIR_PLAY) {
1180 rtn = sc->psize / 4;
1181 unit = ENVY24_PLAY_BUFUNIT / 4;
1182 regno = ENVY24_MT_PCNT;
1185 rtn = sc->rsize / 4;
1186 unit = ENVY24_REC_BUFUNIT / 4;
1187 regno = ENVY24_MT_RCNT;
1190 ptr = envy24_rdmt(sc, regno, 2);
1195 device_printf(sc->dev, "envy24_gethwptr(): return %d\n", rtn);
1201 envy24_updintr(struct sc_info *sc, int dir)
1203 int regptr, regintr;
1204 u_int32_t mask, intr;
1205 u_int32_t ptr, size, cnt;
1209 device_printf(sc->dev, "envy24_updintr(sc, %d)\n", dir);
1211 if (dir == PCMDIR_PLAY) {
1213 size = sc->psize / 4;
1214 regptr = ENVY24_MT_PCNT;
1215 regintr = ENVY24_MT_PTERM;
1216 mask = ~ENVY24_MT_INT_PMASK;
1220 size = sc->rsize / 4;
1221 regptr = ENVY24_MT_RCNT;
1222 regintr = ENVY24_MT_RTERM;
1223 mask = ~ENVY24_MT_INT_RMASK;
1226 ptr = size - envy24_rdmt(sc, regptr, 2) - 1;
1228 cnt = blk - ptr % blk - 1;
1234 device_printf(sc->dev, "envy24_updintr():ptr = %d, blk = %d, cnt = %d\n", ptr, blk, cnt);
1236 envy24_wrmt(sc, regintr, cnt, 2);
1237 intr = envy24_rdmt(sc, ENVY24_MT_INT, 1);
1239 device_printf(sc->dev, "envy24_updintr():intr = 0x%02x, mask = 0x%02x\n", intr, mask);
1241 envy24_wrmt(sc, ENVY24_MT_INT, intr & mask, 1);
1243 device_printf(sc->dev, "envy24_updintr():INT-->0x%02x\n",
1244 envy24_rdmt(sc, ENVY24_MT_INT, 1));
1252 envy24_maskintr(struct sc_info *sc, int dir)
1254 u_int32_t mask, intr;
1257 device_printf(sc->dev, "envy24_maskintr(sc, %d)\n", dir);
1259 if (dir == PCMDIR_PLAY)
1260 mask = ENVY24_MT_INT_PMASK;
1262 mask = ENVY24_MT_INT_RMASK;
1263 intr = envy24_rdmt(sc, ENVY24_MT_INT, 1);
1264 envy24_wrmt(sc, ENVY24_MT_INT, intr | mask, 1);
1271 envy24_checkintr(struct sc_info *sc, int dir)
1273 u_int32_t mask, stat, intr, rtn;
1276 device_printf(sc->dev, "envy24_checkintr(sc, %d)\n", dir);
1278 intr = envy24_rdmt(sc, ENVY24_MT_INT, 1);
1279 if (dir == PCMDIR_PLAY) {
1280 if ((rtn = intr & ENVY24_MT_INT_PSTAT) != 0) {
1281 mask = ~ENVY24_MT_INT_RSTAT;
1282 stat = ENVY24_MT_INT_PSTAT | ENVY24_MT_INT_PMASK;
1283 envy24_wrmt(sc, ENVY24_MT_INT, (intr & mask) | stat, 1);
1287 if ((rtn = intr & ENVY24_MT_INT_RSTAT) != 0) {
1288 mask = ~ENVY24_MT_INT_PSTAT;
1289 stat = ENVY24_MT_INT_RSTAT | ENVY24_MT_INT_RMASK;
1290 envy24_wrmt(sc, ENVY24_MT_INT, (intr & mask) | stat, 1);
1298 envy24_start(struct sc_info *sc, int dir)
1303 device_printf(sc->dev, "envy24_start(sc, %d)\n", dir);
1305 if (dir == PCMDIR_PLAY)
1306 sw = ENVY24_MT_PCTL_PSTART;
1308 sw = ENVY24_MT_PCTL_RSTART;
1310 stat = envy24_rdmt(sc, ENVY24_MT_PCTL, 1);
1311 envy24_wrmt(sc, ENVY24_MT_PCTL, stat | sw, 1);
1314 device_printf(sc->dev, "PADDR:0x%08x\n", envy24_rdmt(sc, ENVY24_MT_PADDR, 4));
1315 device_printf(sc->dev, "PCNT:%ld\n", envy24_rdmt(sc, ENVY24_MT_PCNT, 2));
1322 envy24_stop(struct sc_info *sc, int dir)
1327 device_printf(sc->dev, "envy24_stop(sc, %d)\n", dir);
1329 if (dir == PCMDIR_PLAY)
1330 sw = ~ENVY24_MT_PCTL_PSTART;
1332 sw = ~ENVY24_MT_PCTL_RSTART;
1334 stat = envy24_rdmt(sc, ENVY24_MT_PCTL, 1);
1335 envy24_wrmt(sc, ENVY24_MT_PCTL, stat & sw, 1);
1341 envy24_route(struct sc_info *sc, int dac, int class, int adc, int rev)
1343 u_int32_t reg, mask;
1344 u_int32_t left, right;
1347 device_printf(sc->dev, "envy24_route(sc, %d, %d, %d, %d)\n",
1348 dac, class, adc, rev);
1350 /* parameter pattern check */
1351 if (dac < 0 || ENVY24_ROUTE_DAC_SPDIF < dac)
1353 if (class == ENVY24_ROUTE_CLASS_MIX &&
1354 (dac != ENVY24_ROUTE_DAC_1 && dac != ENVY24_ROUTE_DAC_SPDIF))
1357 left = ENVY24_ROUTE_RIGHT;
1358 right = ENVY24_ROUTE_LEFT;
1361 left = ENVY24_ROUTE_LEFT;
1362 right = ENVY24_ROUTE_RIGHT;
1365 if (dac == ENVY24_ROUTE_DAC_SPDIF) {
1366 reg = class | class << 2 |
1367 ((adc << 1 | left) | left << 3) << 8 |
1368 ((adc << 1 | right) | right << 3) << 12;
1370 device_printf(sc->dev, "envy24_route(): MT_SPDOUT-->0x%04x\n", reg);
1372 envy24_wrmt(sc, ENVY24_MT_SPDOUT, reg, 2);
1375 mask = ~(0x0303 << dac * 2);
1376 reg = envy24_rdmt(sc, ENVY24_MT_PSDOUT, 2);
1377 reg = (reg & mask) | ((class | class << 8) << dac * 2);
1379 device_printf(sc->dev, "envy24_route(): MT_PSDOUT-->0x%04x\n", reg);
1381 envy24_wrmt(sc, ENVY24_MT_PSDOUT, reg, 2);
1382 mask = ~(0xff << dac * 8);
1383 reg = envy24_rdmt(sc, ENVY24_MT_RECORD, 4);
1384 reg = (reg & mask) |
1385 (((adc << 1 | left) | left << 3) |
1386 ((adc << 1 | right) | right << 3) << 4) << dac * 8;
1388 device_printf(sc->dev, "envy24_route(): MT_RECORD-->0x%08x\n", reg);
1390 envy24_wrmt(sc, ENVY24_MT_RECORD, reg, 4);
1392 /* 6fire rear input init test */
1393 envy24_wrmt(sc, ENVY24_MT_RECORD, 0x00, 4);
1399 /* -------------------------------------------------------------------- */
1401 /* buffer copy routines */
1403 envy24_p32sl(struct sc_chinfo *ch)
1408 int src, dst, ssize, dsize, slot;
1411 length = sndbuf_getready(ch->buffer) / 8;
1412 dmabuf = ch->parent->pbuf;
1413 data = (u_int32_t *)ch->data;
1414 src = sndbuf_getreadyptr(ch->buffer) / 4;
1415 dst = src / 2 + ch->offset;
1416 ssize = ch->size / 4;
1417 dsize = ch->size / 8;
1420 for (i = 0; i < length; i++) {
1421 dmabuf[dst * ENVY24_PLAY_CHNUM + slot].buffer = data[src];
1422 dmabuf[dst * ENVY24_PLAY_CHNUM + slot + 1].buffer = data[src + 1];
1433 envy24_p16sl(struct sc_chinfo *ch)
1438 int src, dst, ssize, dsize, slot;
1442 device_printf(ch->parent->dev, "envy24_p16sl()\n");
1444 length = sndbuf_getready(ch->buffer) / 4;
1445 dmabuf = ch->parent->pbuf;
1446 data = (u_int16_t *)ch->data;
1447 src = sndbuf_getreadyptr(ch->buffer) / 2;
1448 dst = src / 2 + ch->offset;
1449 ssize = ch->size / 2;
1450 dsize = ch->size / 4;
1453 device_printf(ch->parent->dev, "envy24_p16sl():%lu-->%lu(%lu)\n", src, dst, length);
1456 for (i = 0; i < length; i++) {
1457 dmabuf[dst * ENVY24_PLAY_CHNUM + slot].buffer = (u_int32_t)data[src] << 16;
1458 dmabuf[dst * ENVY24_PLAY_CHNUM + slot + 1].buffer = (u_int32_t)data[src + 1] << 16;
1461 printf("%08x", dmabuf[dst * ENVY24_PLAY_CHNUM + slot]);
1462 printf("%08x", dmabuf[dst * ENVY24_PLAY_CHNUM + slot + 1]);
1478 envy24_p8u(struct sc_chinfo *ch)
1483 int src, dst, ssize, dsize, slot;
1486 length = sndbuf_getready(ch->buffer) / 2;
1487 dmabuf = ch->parent->pbuf;
1488 data = (u_int8_t *)ch->data;
1489 src = sndbuf_getreadyptr(ch->buffer);
1490 dst = src / 2 + ch->offset;
1492 dsize = ch->size / 4;
1495 for (i = 0; i < length; i++) {
1496 dmabuf[dst * ENVY24_PLAY_CHNUM + slot].buffer = ((u_int32_t)data[src] ^ 0x80) << 24;
1497 dmabuf[dst * ENVY24_PLAY_CHNUM + slot + 1].buffer = ((u_int32_t)data[src + 1] ^ 0x80) << 24;
1508 envy24_r32sl(struct sc_chinfo *ch)
1513 int src, dst, ssize, dsize, slot;
1516 length = sndbuf_getfree(ch->buffer) / 8;
1517 dmabuf = ch->parent->rbuf;
1518 data = (u_int32_t *)ch->data;
1519 dst = sndbuf_getfreeptr(ch->buffer) / 4;
1520 src = dst / 2 + ch->offset;
1521 dsize = ch->size / 4;
1522 ssize = ch->size / 8;
1523 slot = (ch->num - ENVY24_CHAN_REC_ADC1) * 2;
1525 for (i = 0; i < length; i++) {
1526 data[dst] = dmabuf[src * ENVY24_REC_CHNUM + slot].buffer;
1527 data[dst + 1] = dmabuf[src * ENVY24_REC_CHNUM + slot + 1].buffer;
1538 envy24_r16sl(struct sc_chinfo *ch)
1543 int src, dst, ssize, dsize, slot;
1546 length = sndbuf_getfree(ch->buffer) / 4;
1547 dmabuf = ch->parent->rbuf;
1548 data = (u_int16_t *)ch->data;
1549 dst = sndbuf_getfreeptr(ch->buffer) / 2;
1550 src = dst / 2 + ch->offset;
1551 dsize = ch->size / 2;
1552 ssize = ch->size / 8;
1553 slot = (ch->num - ENVY24_CHAN_REC_ADC1) * 2;
1555 for (i = 0; i < length; i++) {
1556 data[dst] = dmabuf[src * ENVY24_REC_CHNUM + slot].buffer;
1557 data[dst + 1] = dmabuf[src * ENVY24_REC_CHNUM + slot + 1].buffer;
1567 /* -------------------------------------------------------------------- */
1569 /* channel interface */
1571 envy24chan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir)
1573 struct sc_info *sc = (struct sc_info *)devinfo;
1574 struct sc_chinfo *ch;
1578 device_printf(sc->dev, "envy24chan_init(obj, devinfo, b, c, %d)\n", dir);
1580 snd_mtxlock(sc->lock);
1581 if ((sc->chnum > ENVY24_CHAN_PLAY_SPDIF && dir != PCMDIR_REC) ||
1582 (sc->chnum < ENVY24_CHAN_REC_ADC1 && dir != PCMDIR_PLAY)) {
1583 snd_mtxunlock(sc->lock);
1588 ch = &sc->chan[num];
1589 ch->size = 8 * ENVY24_SAMPLE_NUM;
1590 ch->data = malloc(ch->size, M_ENVY24, M_NOWAIT);
1591 if (ch->data == NULL) {
1600 /* set channel map */
1601 ch->num = envy24_chanmap[num];
1602 snd_mtxunlock(sc->lock);
1603 sndbuf_setup(ch->buffer, ch->data, ch->size);
1604 snd_mtxlock(sc->lock);
1605 /* these 2 values are dummy */
1609 snd_mtxunlock(sc->lock);
1615 envy24chan_free(kobj_t obj, void *data)
1617 struct sc_chinfo *ch = data;
1618 struct sc_info *sc = ch->parent;
1621 device_printf(sc->dev, "envy24chan_free()\n");
1623 snd_mtxlock(sc->lock);
1624 if (ch->data != NULL) {
1625 free(ch->data, M_ENVY24);
1628 snd_mtxunlock(sc->lock);
1634 envy24chan_setformat(kobj_t obj, void *data, u_int32_t format)
1636 struct sc_chinfo *ch = data;
1637 struct sc_info *sc = ch->parent;
1638 struct envy24_emldma *emltab;
1639 /* unsigned int bcnt, bsize; */
1643 device_printf(sc->dev, "envy24chan_setformat(obj, data, 0x%08x)\n", format);
1645 snd_mtxlock(sc->lock);
1646 /* check and get format related information */
1647 if (ch->dir == PCMDIR_PLAY)
1648 emltab = envy24_pemltab;
1650 emltab = envy24_remltab;
1651 if (emltab == NULL) {
1652 snd_mtxunlock(sc->lock);
1655 for (i = 0; emltab[i].format != 0; i++)
1656 if (emltab[i].format == format)
1658 if (emltab[i].format == 0) {
1659 snd_mtxunlock(sc->lock);
1663 /* set format information */
1664 ch->format = format;
1665 ch->emldma = emltab[i].emldma;
1666 if (ch->unit > emltab[i].unit)
1667 ch->blk *= ch->unit / emltab[i].unit;
1669 ch->blk /= emltab[i].unit / ch->unit;
1670 ch->unit = emltab[i].unit;
1672 /* set channel buffer information */
1673 ch->size = ch->unit * ENVY24_SAMPLE_NUM;
1675 if (ch->dir == PCMDIR_PLAY)
1676 bsize = ch->blk * 4 / ENVY24_PLAY_BUFUNIT;
1678 bsize = ch->blk * 4 / ENVY24_REC_BUFUNIT;
1680 bcnt = ch->size / bsize;
1681 sndbuf_resize(ch->buffer, bcnt, bsize);
1683 snd_mtxunlock(sc->lock);
1686 device_printf(sc->dev, "envy24chan_setformat(): return 0x%08x\n", 0);
1692 IMPLEMENT NOTICE: In this driver, setspeed function only do setting
1693 of speed information value. And real hardware speed setting is done
1694 at start triggered(see envy24chan_trigger()). So, at this function
1695 is called, any value that ENVY24 can use is able to set. But, at
1696 start triggerd, some other channel is running, and that channel's
1697 speed isn't same with, then trigger function will fail.
1700 envy24chan_setspeed(kobj_t obj, void *data, u_int32_t speed)
1702 struct sc_chinfo *ch = data;
1703 u_int32_t val, prev;
1707 device_printf(ch->parent->dev, "envy24chan_setspeed(obj, data, %d)\n", speed);
1710 for (i = 0; (val = envy24_speed[i]) != 0; i++) {
1711 if (abs(val - speed) < abs(prev - speed))
1719 device_printf(ch->parent->dev, "envy24chan_setspeed(): return %d\n", ch->speed);
1725 envy24chan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
1727 struct sc_chinfo *ch = data;
1728 /* struct sc_info *sc = ch->parent; */
1729 u_int32_t size, prev;
1730 unsigned int bcnt, bsize;
1733 device_printf(sc->dev, "envy24chan_setblocksize(obj, data, %d)\n", blocksize);
1736 /* snd_mtxlock(sc->lock); */
1737 for (size = ch->size / 2; size > 0; size /= 2) {
1738 if (abs(size - blocksize) < abs(prev - blocksize))
1744 ch->blk = prev / ch->unit;
1745 if (ch->dir == PCMDIR_PLAY)
1746 ch->blk *= ENVY24_PLAY_BUFUNIT / 4;
1748 ch->blk *= ENVY24_REC_BUFUNIT / 4;
1749 /* set channel buffer information */
1750 /* ch->size = ch->unit * ENVY24_SAMPLE_NUM; */
1751 if (ch->dir == PCMDIR_PLAY)
1752 bsize = ch->blk * 4 / ENVY24_PLAY_BUFUNIT;
1754 bsize = ch->blk * 4 / ENVY24_REC_BUFUNIT;
1756 bcnt = ch->size / bsize;
1757 sndbuf_resize(ch->buffer, bcnt, bsize);
1758 /* snd_mtxunlock(sc->lock); */
1761 device_printf(sc->dev, "envy24chan_setblocksize(): return %d\n", prev);
1766 /* semantic note: must start at beginning of buffer */
1768 envy24chan_trigger(kobj_t obj, void *data, int go)
1770 struct sc_chinfo *ch = data;
1771 struct sc_info *sc = ch->parent;
1778 device_printf(sc->dev, "envy24chan_trigger(obj, data, %d)\n", go);
1780 snd_mtxlock(sc->lock);
1781 if (ch->dir == PCMDIR_PLAY)
1788 device_printf(sc->dev, "envy24chan_trigger(): start\n");
1790 /* check or set channel speed */
1791 if (sc->run[0] == 0 && sc->run[1] == 0) {
1792 sc->speed = envy24_setspeed(sc, ch->speed);
1793 sc->caps[0].minspeed = sc->caps[0].maxspeed = sc->speed;
1794 sc->caps[1].minspeed = sc->caps[1].maxspeed = sc->speed;
1796 else if (ch->speed != 0 && ch->speed != sc->speed) {
1801 ch->channel->speed = sc->speed;
1802 /* start or enable channel */
1804 if (sc->run[slot] == 1) {
1807 sc->blk[slot] = ch->blk;
1810 ptr = envy24_gethwptr(sc, ch->dir);
1811 ch->offset = ((ptr / ch->blk + 1) * ch->blk %
1812 (ch->size / 4)) * 4 / ch->unit;
1813 if (ch->blk < sc->blk[slot])
1814 sc->blk[slot] = ch->blk;
1816 if (ch->dir == PCMDIR_PLAY) {
1818 envy24_setvolume(sc, ch->num);
1820 envy24_updintr(sc, ch->dir);
1821 if (sc->run[slot] == 1)
1822 envy24_start(sc, ch->dir);
1825 case PCMTRIG_EMLDMAWR:
1827 device_printf(sc->dev, "envy24chan_trigger(): emldmawr\n");
1835 case PCMTRIG_EMLDMARD:
1837 device_printf(sc->dev, "envy24chan_trigger(): emldmard\n");
1848 device_printf(sc->dev, "envy24chan_trigger(): abort\n");
1852 if (ch->dir == PCMDIR_PLAY)
1853 envy24_mutevolume(sc, ch->num);
1854 if (sc->run[slot] == 0) {
1855 envy24_stop(sc, ch->dir);
1859 else if (ch->blk == sc->blk[slot]) {
1860 sc->blk[slot] = ENVY24_SAMPLE_NUM / 2;
1861 for (i = 0; i < ENVY24_CHAN_NUM; i++) {
1862 if (sc->chan[i].dir == ch->dir &&
1863 sc->chan[i].run == 1 &&
1864 sc->chan[i].blk < sc->blk[slot])
1865 sc->blk[slot] = sc->chan[i].blk;
1867 if (ch->blk != sc->blk[slot])
1868 envy24_updintr(sc, ch->dir);
1875 snd_mtxunlock(sc->lock);
1880 envy24chan_getptr(kobj_t obj, void *data)
1882 struct sc_chinfo *ch = data;
1883 struct sc_info *sc = ch->parent;
1887 device_printf(sc->dev, "envy24chan_getptr()\n");
1889 snd_mtxlock(sc->lock);
1890 ptr = envy24_gethwptr(sc, ch->dir);
1891 rtn = ptr * ch->unit;
1892 snd_mtxunlock(sc->lock);
1895 device_printf(sc->dev, "envy24chan_getptr(): return %d\n",
1901 static struct pcmchan_caps *
1902 envy24chan_getcaps(kobj_t obj, void *data)
1904 struct sc_chinfo *ch = data;
1905 struct sc_info *sc = ch->parent;
1906 struct pcmchan_caps *rtn;
1909 device_printf(sc->dev, "envy24chan_getcaps()\n");
1911 snd_mtxlock(sc->lock);
1912 if (ch->dir == PCMDIR_PLAY) {
1913 if (sc->run[0] == 0)
1914 rtn = &envy24_playcaps;
1919 if (sc->run[1] == 0)
1920 rtn = &envy24_reccaps;
1924 snd_mtxunlock(sc->lock);
1929 static kobj_method_t envy24chan_methods[] = {
1930 KOBJMETHOD(channel_init, envy24chan_init),
1931 KOBJMETHOD(channel_free, envy24chan_free),
1932 KOBJMETHOD(channel_setformat, envy24chan_setformat),
1933 KOBJMETHOD(channel_setspeed, envy24chan_setspeed),
1934 KOBJMETHOD(channel_setblocksize, envy24chan_setblocksize),
1935 KOBJMETHOD(channel_trigger, envy24chan_trigger),
1936 KOBJMETHOD(channel_getptr, envy24chan_getptr),
1937 KOBJMETHOD(channel_getcaps, envy24chan_getcaps),
1940 CHANNEL_DECLARE(envy24chan);
1942 /* -------------------------------------------------------------------- */
1944 /* mixer interface */
1947 envy24mixer_init(struct snd_mixer *m)
1949 struct sc_info *sc = mix_getdevinfo(m);
1952 device_printf(sc->dev, "envy24mixer_init()\n");
1957 /* set volume control rate */
1958 snd_mtxlock(sc->lock);
1959 envy24_wrmt(sc, ENVY24_MT_VOLRATE, 0x30, 1); /* 0x30 is default value */
1961 mix_setdevs(m, ENVY24_MIX_MASK);
1962 mix_setrecdevs(m, ENVY24_MIX_REC_MASK);
1963 snd_mtxunlock(sc->lock);
1969 envy24mixer_reinit(struct snd_mixer *m)
1971 struct sc_info *sc = mix_getdevinfo(m);
1976 device_printf(sc->dev, "envy24mixer_reinit()\n");
1983 envy24mixer_uninit(struct snd_mixer *m)
1985 struct sc_info *sc = mix_getdevinfo(m);
1990 device_printf(sc->dev, "envy24mixer_uninit()\n");
1997 envy24mixer_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right)
1999 struct sc_info *sc = mix_getdevinfo(m);
2000 int ch = envy24_mixmap[dev];
2006 if (dev == 0 && sc->cfg->codec->setvolume == NULL)
2008 if (dev != 0 && ch == -1)
2010 hwch = envy24_chanmap[ch];
2012 device_printf(sc->dev, "envy24mixer_set(m, %d, %d, %d)\n",
2016 snd_mtxlock(sc->lock);
2018 for (i = 0; i < sc->dacn; i++) {
2019 sc->cfg->codec->setvolume(sc->dac[i], PCMDIR_PLAY, left, right);
2023 /* set volume value for hardware */
2024 if ((sc->left[hwch] = 100 - left) > ENVY24_VOL_MIN)
2025 sc->left[hwch] = ENVY24_VOL_MUTE;
2026 if ((sc->right[hwch] = 100 - right) > ENVY24_VOL_MIN)
2027 sc->right[hwch] = ENVY24_VOL_MUTE;
2029 /* set volume for record channel and running play channel */
2030 if (hwch > ENVY24_CHAN_PLAY_SPDIF || sc->chan[ch].run)
2031 envy24_setvolume(sc, hwch);
2033 snd_mtxunlock(sc->lock);
2035 return right << 8 | left;
2039 envy24mixer_setrecsrc(struct snd_mixer *m, u_int32_t src)
2041 struct sc_info *sc = mix_getdevinfo(m);
2042 int ch = envy24_mixmap[src];
2044 device_printf(sc->dev, "envy24mixer_setrecsrc(m, %d)\n", src);
2047 if (ch > ENVY24_CHAN_PLAY_SPDIF)
2052 static kobj_method_t envy24mixer_methods[] = {
2053 KOBJMETHOD(mixer_init, envy24mixer_init),
2054 KOBJMETHOD(mixer_reinit, envy24mixer_reinit),
2055 KOBJMETHOD(mixer_uninit, envy24mixer_uninit),
2056 KOBJMETHOD(mixer_set, envy24mixer_set),
2057 KOBJMETHOD(mixer_setrecsrc, envy24mixer_setrecsrc),
2060 MIXER_DECLARE(envy24mixer);
2062 /* -------------------------------------------------------------------- */
2064 /* The interrupt handler */
2066 envy24_intr(void *p)
2068 struct sc_info *sc = (struct sc_info *)p;
2069 struct sc_chinfo *ch;
2070 u_int32_t ptr, dsize, feed;
2074 device_printf(sc->dev, "envy24_intr()\n");
2076 snd_mtxlock(sc->lock);
2077 if (envy24_checkintr(sc, PCMDIR_PLAY)) {
2079 device_printf(sc->dev, "envy24_intr(): play\n");
2081 dsize = sc->psize / 4;
2082 ptr = dsize - envy24_rdmt(sc, ENVY24_MT_PCNT, 2) - 1;
2084 device_printf(sc->dev, "envy24_intr(): ptr = %d-->", ptr);
2086 ptr -= ptr % sc->blk[0];
2087 feed = (ptr + dsize - sc->intr[0]) % dsize;
2089 printf("%d intr = %d feed = %d\n", ptr, sc->intr[0], feed);
2091 for (i = ENVY24_CHAN_PLAY_DAC1; i <= ENVY24_CHAN_PLAY_SPDIF; i++) {
2095 device_printf(sc->dev, "envy24_intr(): chan[%d].blk = %d\n", i, ch->blk);
2097 if (ch->run && ch->blk <= feed) {
2098 snd_mtxunlock(sc->lock);
2099 chn_intr(ch->channel);
2100 snd_mtxlock(sc->lock);
2104 envy24_updintr(sc, PCMDIR_PLAY);
2106 if (envy24_checkintr(sc, PCMDIR_REC)) {
2108 device_printf(sc->dev, "envy24_intr(): rec\n");
2110 dsize = sc->rsize / 4;
2111 ptr = dsize - envy24_rdmt(sc, ENVY24_MT_RCNT, 2) - 1;
2112 ptr -= ptr % sc->blk[1];
2113 feed = (ptr + dsize - sc->intr[1]) % dsize;
2114 for (i = ENVY24_CHAN_REC_ADC1; i <= ENVY24_CHAN_REC_SPDIF; i++) {
2116 if (ch->run && ch->blk <= feed) {
2117 snd_mtxunlock(sc->lock);
2118 chn_intr(ch->channel);
2119 snd_mtxlock(sc->lock);
2123 envy24_updintr(sc, PCMDIR_REC);
2125 snd_mtxunlock(sc->lock);
2131 * Probe and attach the card
2135 envy24_pci_probe(device_t dev)
2141 printf("envy24_pci_probe()\n");
2143 if (pci_get_device(dev) == PCID_ENVY24 &&
2144 pci_get_vendor(dev) == PCIV_ENVY24) {
2145 sv = pci_get_subvendor(dev);
2146 sd = pci_get_subdevice(dev);
2147 for (i = 0; cfg_table[i].subvendor != 0 || cfg_table[i].subdevice != 0; i++) {
2148 if (cfg_table[i].subvendor == sv &&
2149 cfg_table[i].subdevice == sd) {
2153 device_set_desc(dev, cfg_table[i].name);
2155 printf("envy24_pci_probe(): return 0\n");
2161 printf("envy24_pci_probe(): return ENXIO\n");
2168 envy24_dmapsetmap(void *arg, bus_dma_segment_t *segs, int nseg, int error)
2170 struct sc_info *sc = (struct sc_info *)arg;
2172 sc->paddr = segs->ds_addr;
2174 device_printf(sc->dev, "envy24_dmapsetmap()\n");
2176 printf("envy24(play): setmap %lx, %lx; ",
2177 (unsigned long)segs->ds_addr,
2178 (unsigned long)segs->ds_len);
2179 printf("%p -> %lx\n", sc->pmap, sc->paddr);
2185 envy24_dmarsetmap(void *arg, bus_dma_segment_t *segs, int nseg, int error)
2187 struct sc_info *sc = (struct sc_info *)arg;
2189 sc->raddr = segs->ds_addr;
2191 device_printf(sc->dev, "envy24_dmarsetmap()\n");
2193 printf("envy24(record): setmap %lx, %lx; ",
2194 (unsigned long)segs->ds_addr,
2195 (unsigned long)segs->ds_len);
2196 printf("%p -> %lx\n", sc->rmap, sc->raddr);
2202 envy24_dmafree(struct sc_info *sc)
2205 device_printf(sc->dev, "envy24_dmafree():");
2206 printf(" sc->raddr(0x%08x)", (u_int32_t)sc->raddr);
2207 printf(" sc->paddr(0x%08x)", (u_int32_t)sc->paddr);
2208 if (sc->rbuf) printf(" sc->rbuf(0x%08x)", (u_int32_t)sc->rbuf);
2209 else printf(" sc->rbuf(null)");
2210 if (sc->pbuf) printf(" sc->pbuf(0x%08x)\n", (u_int32_t)sc->pbuf);
2211 else printf(" sc->pbuf(null)\n");
2215 bus_dmamap_unload(sc->dmat, sc->rmap);
2217 bus_dmamap_unload(sc->dmat, sc->pmap);
2219 bus_dmamem_free(sc->dmat, sc->rbuf, sc->rmap);
2221 bus_dmamem_free(sc->dmat, sc->pbuf, sc->pmap);
2223 bus_dmamap_unload(sc->dmat, sc->rmap);
2224 bus_dmamap_unload(sc->dmat, sc->pmap);
2225 bus_dmamem_free(sc->dmat, sc->rbuf, sc->rmap);
2226 bus_dmamem_free(sc->dmat, sc->pbuf, sc->pmap);
2229 sc->raddr = sc->paddr = 0;
2237 envy24_dmainit(struct sc_info *sc)
2241 device_printf(sc->dev, "envy24_dmainit()\n");
2244 sc->psize = ENVY24_PLAY_BUFUNIT * ENVY24_SAMPLE_NUM;
2245 sc->rsize = ENVY24_REC_BUFUNIT * ENVY24_SAMPLE_NUM;
2248 sc->paddr = sc->raddr = 0;
2249 sc->blk[0] = sc->blk[1] = 0;
2251 /* allocate DMA buffer */
2253 device_printf(sc->dev, "envy24_dmainit(): bus_dmamem_alloc(): sc->pbuf\n");
2255 if (bus_dmamem_alloc(sc->dmat, (void **)&sc->pbuf, BUS_DMA_NOWAIT, &sc->pmap))
2258 device_printf(sc->dev, "envy24_dmainit(): bus_dmamem_alloc(): sc->rbuf\n");
2260 if (bus_dmamem_alloc(sc->dmat, (void **)&sc->rbuf, BUS_DMA_NOWAIT, &sc->rmap))
2263 device_printf(sc->dev, "envy24_dmainit(): bus_dmamem_load(): sc->pmap\n");
2265 if (bus_dmamap_load(sc->dmat, sc->pmap, sc->pbuf, sc->psize, envy24_dmapsetmap, sc, 0))
2268 device_printf(sc->dev, "envy24_dmainit(): bus_dmamem_load(): sc->rmap\n");
2270 if (bus_dmamap_load(sc->dmat, sc->rmap, sc->rbuf, sc->rsize, envy24_dmarsetmap, sc, 0))
2272 bzero(sc->pbuf, sc->psize);
2273 bzero(sc->rbuf, sc->rsize);
2275 /* set values to register */
2277 device_printf(sc->dev, "paddr(0x%08x)\n", sc->paddr);
2279 envy24_wrmt(sc, ENVY24_MT_PADDR, sc->paddr, 4);
2281 device_printf(sc->dev, "PADDR-->(0x%08x)\n", envy24_rdmt(sc, ENVY24_MT_PADDR, 4));
2282 device_printf(sc->dev, "psize(%ld)\n", sc->psize / 4 - 1);
2284 envy24_wrmt(sc, ENVY24_MT_PCNT, sc->psize / 4 - 1, 2);
2286 device_printf(sc->dev, "PCNT-->(%ld)\n", envy24_rdmt(sc, ENVY24_MT_PCNT, 2));
2288 envy24_wrmt(sc, ENVY24_MT_RADDR, sc->raddr, 4);
2289 envy24_wrmt(sc, ENVY24_MT_RCNT, sc->rsize / 4 - 1, 2);
2298 envy24_putcfg(struct sc_info *sc)
2300 device_printf(sc->dev, "system configuration\n");
2301 printf(" SubVendorID: 0x%04x, SubDeviceID: 0x%04x\n",
2302 sc->cfg->subvendor, sc->cfg->subdevice);
2303 printf(" XIN2 Clock Source: ");
2304 switch (sc->cfg->scfg & PCIM_SCFG_XIN2) {
2306 printf("22.5792MHz(44.1kHz*512)\n");
2309 printf("16.9344MHz(44.1kHz*384)\n");
2312 printf("from external clock synthesizer chip\n");
2315 printf("illegal system setting\n");
2317 printf(" MPU-401 UART(s) #: ");
2318 if (sc->cfg->scfg & PCIM_SCFG_MPU)
2322 printf(" AC'97 codec: ");
2323 if (sc->cfg->scfg & PCIM_SCFG_AC97)
2324 printf("not exist\n");
2328 printf("%d\n", sc->adcn);
2330 printf("%d\n", sc->dacn);
2331 printf(" Multi-track converter type: ");
2332 if ((sc->cfg->acl & PCIM_ACL_MTC) == 0) {
2333 printf("AC'97(SDATA_OUT:");
2334 if (sc->cfg->acl & PCIM_ACL_OMODE)
2338 printf("|SDATA_IN:");
2339 if (sc->cfg->acl & PCIM_ACL_IMODE)
2347 if (sc->cfg->i2s & PCIM_I2S_VOL)
2348 printf("with volume, ");
2349 if (sc->cfg->i2s & PCIM_I2S_96KHZ)
2350 printf("96KHz support, ");
2351 switch (sc->cfg->i2s & PCIM_I2S_RES) {
2352 case PCIM_I2S_16BIT:
2353 printf("16bit resolution, ");
2355 case PCIM_I2S_18BIT:
2356 printf("18bit resolution, ");
2358 case PCIM_I2S_20BIT:
2359 printf("20bit resolution, ");
2361 case PCIM_I2S_24BIT:
2362 printf("24bit resolution, ");
2365 printf("ID#0x%x)\n", sc->cfg->i2s & PCIM_I2S_ID);
2367 printf(" S/PDIF(IN/OUT): ");
2368 if (sc->cfg->spdif & PCIM_SPDIF_IN)
2372 if (sc->cfg->spdif & PCIM_SPDIF_OUT)
2376 if (sc->cfg->spdif & (PCIM_SPDIF_IN | PCIM_SPDIF_OUT))
2377 printf("ID# 0x%02x\n", (sc->cfg->spdif & PCIM_SPDIF_ID) >> 2);
2378 printf(" GPIO(mask/dir/state): 0x%02x/0x%02x/0x%02x\n",
2379 sc->cfg->gpiomask, sc->cfg->gpiodir, sc->cfg->gpiostate);
2383 envy24_init(struct sc_info *sc)
2394 device_printf(sc->dev, "envy24_init()\n");
2398 envy24_wrcs(sc, ENVY24_CCS_CTL, ENVY24_CCS_CTL_RESET | ENVY24_CCS_CTL_NATIVE, 1);
2400 envy24_wrcs(sc, ENVY24_CCS_CTL, ENVY24_CCS_CTL_NATIVE, 1);
2403 /* legacy hardware disable */
2404 data = pci_read_config(sc->dev, PCIR_LAC, 2);
2405 data |= PCIM_LAC_DISABLE;
2406 pci_write_config(sc->dev, PCIR_LAC, data, 2);
2408 /* check system configuration */
2410 for (i = 0; cfg_table[i].subvendor != 0 || cfg_table[i].subdevice != 0; i++) {
2411 /* 1st: search configuration from table */
2412 sv = pci_get_subvendor(sc->dev);
2413 sd = pci_get_subdevice(sc->dev);
2414 if (sv == cfg_table[i].subvendor && sd == cfg_table[i].subdevice) {
2416 device_printf(sc->dev, "Set configuration from table\n");
2418 sc->cfg = &cfg_table[i];
2422 if (sc->cfg == NULL) {
2423 /* 2nd: read configuration from table */
2424 sc->cfg = envy24_rom2cfg(sc);
2426 sc->adcn = ((sc->cfg->scfg & PCIM_SCFG_ADC) >> 2) + 1;
2427 sc->dacn = (sc->cfg->scfg & PCIM_SCFG_DAC) + 1;
2429 if (1 /* bootverbose */) {
2433 /* set system configuration */
2434 pci_write_config(sc->dev, PCIR_SCFG, sc->cfg->scfg, 1);
2435 pci_write_config(sc->dev, PCIR_ACL, sc->cfg->acl, 1);
2436 pci_write_config(sc->dev, PCIR_I2S, sc->cfg->i2s, 1);
2437 pci_write_config(sc->dev, PCIR_SPDIF, sc->cfg->spdif, 1);
2438 envy24_gpiosetmask(sc, sc->cfg->gpiomask);
2439 envy24_gpiosetdir(sc, sc->cfg->gpiodir);
2440 envy24_gpiowr(sc, sc->cfg->gpiostate);
2441 for (i = 0; i < sc->adcn; i++) {
2442 sc->adc[i] = sc->cfg->codec->create(sc->dev, sc, PCMDIR_REC, i);
2443 sc->cfg->codec->init(sc->adc[i]);
2445 for (i = 0; i < sc->dacn; i++) {
2446 sc->dac[i] = sc->cfg->codec->create(sc->dev, sc, PCMDIR_PLAY, i);
2447 sc->cfg->codec->init(sc->dac[i]);
2450 /* initialize DMA buffer */
2452 device_printf(sc->dev, "envy24_init(): initialize DMA buffer\n");
2454 if (envy24_dmainit(sc))
2457 /* initialize status */
2458 sc->run[0] = sc->run[1] = 0;
2459 sc->intr[0] = sc->intr[1] = 0;
2461 sc->caps[0].fmtlist = envy24_playfmt;
2462 sc->caps[1].fmtlist = envy24_recfmt;
2464 /* set channel router */
2465 envy24_route(sc, ENVY24_ROUTE_DAC_1, ENVY24_ROUTE_CLASS_MIX, 0, 0);
2466 envy24_route(sc, ENVY24_ROUTE_DAC_SPDIF, ENVY24_ROUTE_CLASS_DMA, 0, 0);
2467 /* envy24_route(sc, ENVY24_ROUTE_DAC_SPDIF, ENVY24_ROUTE_CLASS_MIX, 0, 0); */
2469 /* set macro interrupt mask */
2470 data = envy24_rdcs(sc, ENVY24_CCS_IMASK, 1);
2471 envy24_wrcs(sc, ENVY24_CCS_IMASK, data & ~ENVY24_CCS_IMASK_PMT, 1);
2472 data = envy24_rdcs(sc, ENVY24_CCS_IMASK, 1);
2474 device_printf(sc->dev, "envy24_init(): CCS_IMASK-->0x%02x\n", data);
2481 envy24_alloc_resource(struct sc_info *sc)
2483 /* allocate I/O port resource */
2484 sc->csid = PCIR_CCS;
2485 sc->cs = bus_alloc_resource_any(sc->dev, SYS_RES_IOPORT,
2486 &sc->csid, RF_ACTIVE);
2487 sc->ddmaid = PCIR_DDMA;
2488 sc->ddma = bus_alloc_resource_any(sc->dev, SYS_RES_IOPORT,
2489 &sc->ddmaid, RF_ACTIVE);
2491 sc->ds = bus_alloc_resource_any(sc->dev, SYS_RES_IOPORT,
2492 &sc->dsid, RF_ACTIVE);
2494 sc->mt = bus_alloc_resource_any(sc->dev, SYS_RES_IOPORT,
2495 &sc->mtid, RF_ACTIVE);
2496 if (!sc->cs || !sc->ddma || !sc->ds || !sc->mt) {
2497 device_printf(sc->dev, "unable to map IO port space\n");
2500 sc->cst = rman_get_bustag(sc->cs);
2501 sc->csh = rman_get_bushandle(sc->cs);
2502 sc->ddmat = rman_get_bustag(sc->ddma);
2503 sc->ddmah = rman_get_bushandle(sc->ddma);
2504 sc->dst = rman_get_bustag(sc->ds);
2505 sc->dsh = rman_get_bushandle(sc->ds);
2506 sc->mtt = rman_get_bustag(sc->mt);
2507 sc->mth = rman_get_bushandle(sc->mt);
2509 device_printf(sc->dev,
2510 "IO port register values\nCCS: 0x%lx\nDDMA: 0x%lx\nDS: 0x%lx\nMT: 0x%lx\n",
2511 pci_read_config(sc->dev, PCIR_CCS, 4),
2512 pci_read_config(sc->dev, PCIR_DDMA, 4),
2513 pci_read_config(sc->dev, PCIR_DS, 4),
2514 pci_read_config(sc->dev, PCIR_MT, 4));
2517 /* allocate interrupt resource */
2519 sc->irq = bus_alloc_resource_any(sc->dev, SYS_RES_IRQ, &sc->irqid,
2520 RF_ACTIVE | RF_SHAREABLE);
2522 snd_setup_intr(sc->dev, sc->irq, INTR_MPSAFE, envy24_intr, sc, &sc->ih)) {
2523 device_printf(sc->dev, "unable to map interrupt\n");
2527 /* allocate DMA resource */
2528 if (bus_dma_tag_create(/*parent*/bus_get_dma_tag(sc->dev),
2531 /*lowaddr*/BUS_SPACE_MAXADDR_ENVY24,
2532 /*highaddr*/BUS_SPACE_MAXADDR_ENVY24,
2533 /*filter*/NULL, /*filterarg*/NULL,
2534 /*maxsize*/BUS_SPACE_MAXSIZE_ENVY24,
2535 /*nsegments*/1, /*maxsegsz*/0x3ffff,
2536 /*flags*/0, /*lockfunc*/busdma_lock_mutex,
2537 /*lockarg*/&Giant, &sc->dmat) != 0) {
2538 device_printf(sc->dev, "unable to create dma tag\n");
2546 envy24_pci_attach(device_t dev)
2549 char status[SND_STATUSLEN];
2554 device_printf(dev, "envy24_pci_attach()\n");
2556 /* get sc_info data area */
2557 if ((sc = malloc(sizeof(*sc), M_ENVY24, M_NOWAIT)) == NULL) {
2558 device_printf(dev, "cannot allocate softc\n");
2562 bzero(sc, sizeof(*sc));
2563 sc->lock = snd_mtxcreate(device_get_nameunit(dev), "snd_envy24 softc");
2566 /* initialize PCI interface */
2567 pci_enable_busmaster(dev);
2569 /* allocate resources */
2570 err = envy24_alloc_resource(sc);
2572 device_printf(dev, "unable to allocate system resources\n");
2576 /* initialize card */
2577 err = envy24_init(sc);
2579 device_printf(dev, "unable to initialize the card\n");
2583 /* set multi track mixer */
2584 mixer_init(dev, &envy24mixer_class, sc);
2586 /* set channel information */
2587 err = pcm_register(dev, sc, 5, 2 + sc->adcn);
2591 for (i = 0; i < 5; i++) {
2592 pcm_addchan(dev, PCMDIR_PLAY, &envy24chan_class, sc);
2595 for (i = 0; i < 2 + sc->adcn; i++) {
2596 pcm_addchan(dev, PCMDIR_REC, &envy24chan_class, sc);
2600 /* set status iformation */
2601 snprintf(status, SND_STATUSLEN,
2602 "at io 0x%jx:%jd,0x%jx:%jd,0x%jx:%jd,0x%jx:%jd irq %jd",
2603 rman_get_start(sc->cs),
2604 rman_get_end(sc->cs) - rman_get_start(sc->cs) + 1,
2605 rman_get_start(sc->ddma),
2606 rman_get_end(sc->ddma) - rman_get_start(sc->ddma) + 1,
2607 rman_get_start(sc->ds),
2608 rman_get_end(sc->ds) - rman_get_start(sc->ds) + 1,
2609 rman_get_start(sc->mt),
2610 rman_get_end(sc->mt) - rman_get_start(sc->mt) + 1,
2611 rman_get_start(sc->irq));
2612 pcm_setstatus(dev, status);
2618 bus_teardown_intr(dev, sc->irq, sc->ih);
2620 bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq);
2623 bus_dma_tag_destroy(sc->dmat);
2624 if (sc->cfg->codec->destroy != NULL) {
2625 for (i = 0; i < sc->adcn; i++)
2626 sc->cfg->codec->destroy(sc->adc[i]);
2627 for (i = 0; i < sc->dacn; i++)
2628 sc->cfg->codec->destroy(sc->dac[i]);
2630 envy24_cfgfree(sc->cfg);
2632 bus_release_resource(dev, SYS_RES_IOPORT, sc->csid, sc->cs);
2634 bus_release_resource(dev, SYS_RES_IOPORT, sc->ddmaid, sc->ddma);
2636 bus_release_resource(dev, SYS_RES_IOPORT, sc->dsid, sc->ds);
2638 bus_release_resource(dev, SYS_RES_IOPORT, sc->mtid, sc->mt);
2640 snd_mtxfree(sc->lock);
2646 envy24_pci_detach(device_t dev)
2653 device_printf(dev, "envy24_pci_detach()\n");
2655 sc = pcm_getdevinfo(dev);
2658 r = pcm_unregister(dev);
2663 if (sc->cfg->codec->destroy != NULL) {
2664 for (i = 0; i < sc->adcn; i++)
2665 sc->cfg->codec->destroy(sc->adc[i]);
2666 for (i = 0; i < sc->dacn; i++)
2667 sc->cfg->codec->destroy(sc->dac[i]);
2669 envy24_cfgfree(sc->cfg);
2670 bus_dma_tag_destroy(sc->dmat);
2671 bus_teardown_intr(dev, sc->irq, sc->ih);
2672 bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq);
2673 bus_release_resource(dev, SYS_RES_IOPORT, sc->csid, sc->cs);
2674 bus_release_resource(dev, SYS_RES_IOPORT, sc->ddmaid, sc->ddma);
2675 bus_release_resource(dev, SYS_RES_IOPORT, sc->dsid, sc->ds);
2676 bus_release_resource(dev, SYS_RES_IOPORT, sc->mtid, sc->mt);
2677 snd_mtxfree(sc->lock);
2682 static device_method_t envy24_methods[] = {
2683 /* Device interface */
2684 DEVMETHOD(device_probe, envy24_pci_probe),
2685 DEVMETHOD(device_attach, envy24_pci_attach),
2686 DEVMETHOD(device_detach, envy24_pci_detach),
2690 static driver_t envy24_driver = {
2696 DRIVER_MODULE(snd_envy24, pci, envy24_driver, pcm_devclass, 0, 0);
2697 MODULE_DEPEND(snd_envy24, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER);
2698 MODULE_DEPEND(snd_envy24, snd_spicds, 1, 1, 1);
2699 MODULE_VERSION(snd_envy24, 1);