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;
171 struct pcmchan_caps caps[2];
173 /* channel info table */
175 struct sc_chinfo chan[11];
178 /* -------------------------------------------------------------------- */
185 static void envy24_p8u(struct sc_chinfo *);
186 static void envy24_p16sl(struct sc_chinfo *);
187 static void envy24_p32sl(struct sc_chinfo *);
188 static void envy24_r16sl(struct sc_chinfo *);
189 static void envy24_r32sl(struct sc_chinfo *);
191 /* channel interface */
192 static void *envy24chan_init(kobj_t, void *, struct snd_dbuf *, struct pcm_channel *, int);
193 static int envy24chan_setformat(kobj_t, void *, u_int32_t);
194 static u_int32_t envy24chan_setspeed(kobj_t, void *, u_int32_t);
195 static u_int32_t envy24chan_setblocksize(kobj_t, void *, u_int32_t);
196 static int envy24chan_trigger(kobj_t, void *, int);
197 static u_int32_t envy24chan_getptr(kobj_t, void *);
198 static struct pcmchan_caps *envy24chan_getcaps(kobj_t, void *);
200 /* mixer interface */
201 static int envy24mixer_init(struct snd_mixer *);
202 static int envy24mixer_reinit(struct snd_mixer *);
203 static int envy24mixer_uninit(struct snd_mixer *);
204 static int envy24mixer_set(struct snd_mixer *, unsigned, unsigned, unsigned);
205 static u_int32_t envy24mixer_setrecsrc(struct snd_mixer *, u_int32_t);
207 /* M-Audio Delta series AK4524 access interface */
208 static void *envy24_delta_ak4524_create(device_t, void *, int, int);
209 static void envy24_delta_ak4524_destroy(void *);
210 static void envy24_delta_ak4524_init(void *);
211 static void envy24_delta_ak4524_reinit(void *);
212 static void envy24_delta_ak4524_setvolume(void *, int, unsigned int, unsigned int);
214 /* -------------------------------------------------------------------- */
217 system constant tables
220 /* API -> hardware channel map */
221 static unsigned envy24_chanmap[ENVY24_CHAN_NUM] = {
222 ENVY24_CHAN_PLAY_SPDIF, /* 0 */
223 ENVY24_CHAN_PLAY_DAC1, /* 1 */
224 ENVY24_CHAN_PLAY_DAC2, /* 2 */
225 ENVY24_CHAN_PLAY_DAC3, /* 3 */
226 ENVY24_CHAN_PLAY_DAC4, /* 4 */
227 ENVY24_CHAN_REC_MIX, /* 5 */
228 ENVY24_CHAN_REC_SPDIF, /* 6 */
229 ENVY24_CHAN_REC_ADC1, /* 7 */
230 ENVY24_CHAN_REC_ADC2, /* 8 */
231 ENVY24_CHAN_REC_ADC3, /* 9 */
232 ENVY24_CHAN_REC_ADC4, /* 10 */
235 /* mixer -> API channel map. see above */
236 static int envy24_mixmap[] = {
237 -1, /* Master output level. It is depend on codec support */
238 -1, /* Treble level of all output channels */
239 -1, /* Bass level of all output channels */
240 -1, /* Volume of synthesier input */
241 0, /* Output level for the audio device */
242 -1, /* Output level for the PC speaker */
243 7, /* line in jack */
244 -1, /* microphone jack */
245 -1, /* CD audio input */
246 -1, /* Recording monitor */
247 1, /* alternative codec */
248 -1, /* global recording level */
250 -1, /* Output gain */
251 8, /* Input source 1 */
252 9, /* Input source 2 */
253 10, /* Input source 3 */
254 6, /* Digital (input) 1 */
255 -1, /* Digital (input) 2 */
256 -1, /* Digital (input) 3 */
257 -1, /* Phone input */
258 -1, /* Phone output */
259 -1, /* Video/TV (audio) in */
261 -1, /* Monitor volume */
264 /* variable rate audio */
265 static u_int32_t envy24_speed[] = {
266 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000,
267 12000, 11025, 9600, 8000, 0
270 /* known boards configuration */
271 static struct codec_entry delta_codec = {
272 envy24_delta_ak4524_create,
273 envy24_delta_ak4524_destroy,
274 envy24_delta_ak4524_init,
275 envy24_delta_ak4524_reinit,
276 envy24_delta_ak4524_setvolume,
280 static struct cfg_info cfg_table[] = {
282 "Envy24 audio (M Audio Delta Dio 2496)",
284 0x10, 0x80, 0xf0, 0x03,
286 0x10, 0x20, 0x40, 0x00, 0x00,
291 "Envy24 audio (Terratec DMX 6fire)",
293 0x2f, 0x80, 0xf0, 0x03,
295 0x10, 0x20, 0x01, 0x01, 0x00,
300 "Envy24 audio (M Audio Audiophile 2496)",
302 0x10, 0x80, 0x72, 0x03,
304 0x08, 0x02, 0x20, 0x00, 0x01,
309 "Envy24 audio (M Audio Delta 66)",
311 0x15, 0x80, 0xf0, 0x03,
313 0x10, 0x20, 0x40, 0x00, 0x00,
318 "Envy24 audio (M Audio Delta 44)",
320 0x15, 0x80, 0xf0, 0x00,
322 0x10, 0x20, 0x40, 0x00, 0x00,
327 "Envy24 audio (M Audio Delta 1010)",
329 0x1f, 0x80, 0xf0, 0x03,
331 0x10, 0x20, 0x40, 0x00, 0x00,
336 "Envy24 audio (M Audio Delta 1010LT)",
338 0x1f, 0x80, 0x72, 0x03,
340 0x08, 0x02, 0x70, 0x00, 0x00,
345 "Envy24 audio (Terratec EWX 2496)",
347 0x10, 0x80, 0xf0, 0x03,
349 0x10, 0x20, 0x01, 0x01, 0x00,
354 "Envy24 audio (Generic)",
356 0x0f, 0x00, 0x01, 0x03,
358 0x10, 0x20, 0x40, 0x00, 0x00,
360 &delta_codec, /* default codec routines */
364 static u_int32_t envy24_recfmt[] = {
365 SND_FORMAT(AFMT_S16_LE, 2, 0),
366 SND_FORMAT(AFMT_S32_LE, 2, 0),
369 static struct pcmchan_caps envy24_reccaps = {8000, 96000, envy24_recfmt, 0};
371 static u_int32_t envy24_playfmt[] = {
372 SND_FORMAT(AFMT_U8, 2, 0),
373 SND_FORMAT(AFMT_S16_LE, 2, 0),
374 SND_FORMAT(AFMT_S32_LE, 2, 0),
378 static struct pcmchan_caps envy24_playcaps = {8000, 96000, envy24_playfmt, 0};
380 struct envy24_emldma {
382 void (*emldma)(struct sc_chinfo *);
386 static struct envy24_emldma envy24_pemltab[] = {
387 {SND_FORMAT(AFMT_U8, 2, 0), envy24_p8u, 2},
388 {SND_FORMAT(AFMT_S16_LE, 2, 0), envy24_p16sl, 4},
389 {SND_FORMAT(AFMT_S32_LE, 2, 0), envy24_p32sl, 8},
393 static struct envy24_emldma envy24_remltab[] = {
394 {SND_FORMAT(AFMT_S16_LE, 2, 0), envy24_r16sl, 4},
395 {SND_FORMAT(AFMT_S32_LE, 2, 0), envy24_r32sl, 8},
399 /* -------------------------------------------------------------------- */
401 /* common routines */
403 envy24_rdcs(struct sc_info *sc, int regno, int size)
407 return bus_space_read_1(sc->cst, sc->csh, regno);
409 return bus_space_read_2(sc->cst, sc->csh, regno);
411 return bus_space_read_4(sc->cst, sc->csh, regno);
418 envy24_wrcs(struct sc_info *sc, int regno, u_int32_t data, int size)
422 bus_space_write_1(sc->cst, sc->csh, regno, data);
425 bus_space_write_2(sc->cst, sc->csh, regno, data);
428 bus_space_write_4(sc->cst, sc->csh, regno, data);
434 envy24_rdmt(struct sc_info *sc, int regno, int size)
438 return bus_space_read_1(sc->mtt, sc->mth, regno);
440 return bus_space_read_2(sc->mtt, sc->mth, regno);
442 return bus_space_read_4(sc->mtt, sc->mth, regno);
449 envy24_wrmt(struct sc_info *sc, int regno, u_int32_t data, int size)
453 bus_space_write_1(sc->mtt, sc->mth, regno, data);
456 bus_space_write_2(sc->mtt, sc->mth, regno, data);
459 bus_space_write_4(sc->mtt, sc->mth, regno, data);
465 envy24_rdci(struct sc_info *sc, int regno)
467 envy24_wrcs(sc, ENVY24_CCS_INDEX, regno, 1);
468 return envy24_rdcs(sc, ENVY24_CCS_DATA, 1);
472 envy24_wrci(struct sc_info *sc, int regno, u_int32_t data)
474 envy24_wrcs(sc, ENVY24_CCS_INDEX, regno, 1);
475 envy24_wrcs(sc, ENVY24_CCS_DATA, data, 1);
478 /* -------------------------------------------------------------------- */
480 /* I2C port/E2PROM access routines */
483 envy24_rdi2c(struct sc_info *sc, u_int32_t dev, u_int32_t addr)
489 device_printf(sc->dev, "envy24_rdi2c(sc, 0x%02x, 0x%02x)\n", dev, addr);
491 for (i = 0; i < ENVY24_TIMEOUT; i++) {
492 data = envy24_rdcs(sc, ENVY24_CCS_I2CSTAT, 1);
493 if ((data & ENVY24_CCS_I2CSTAT_BSY) == 0)
495 DELAY(32); /* 31.25kHz */
497 if (i == ENVY24_TIMEOUT) {
500 envy24_wrcs(sc, ENVY24_CCS_I2CADDR, addr, 1);
501 envy24_wrcs(sc, ENVY24_CCS_I2CDEV,
502 (dev & ENVY24_CCS_I2CDEV_ADDR) | ENVY24_CCS_I2CDEV_RD, 1);
503 for (i = 0; i < ENVY24_TIMEOUT; i++) {
504 data = envy24_rdcs(sc, ENVY24_CCS_I2CSTAT, 1);
505 if ((data & ENVY24_CCS_I2CSTAT_BSY) == 0)
507 DELAY(32); /* 31.25kHz */
509 if (i == ENVY24_TIMEOUT) {
512 data = envy24_rdcs(sc, ENVY24_CCS_I2CDATA, 1);
515 device_printf(sc->dev, "envy24_rdi2c(): return 0x%x\n", data);
522 envy24_wri2c(struct sc_info *sc, u_int32_t dev, u_int32_t addr, u_int32_t data)
528 device_printf(sc->dev, "envy24_rdi2c(sc, 0x%02x, 0x%02x)\n", dev, addr);
530 for (i = 0; i < ENVY24_TIMEOUT; i++) {
531 tmp = envy24_rdcs(sc, ENVY24_CCS_I2CSTAT, 1);
532 if ((tmp & ENVY24_CCS_I2CSTAT_BSY) == 0)
534 DELAY(32); /* 31.25kHz */
536 if (i == ENVY24_TIMEOUT) {
539 envy24_wrcs(sc, ENVY24_CCS_I2CADDR, addr, 1);
540 envy24_wrcs(sc, ENVY24_CCS_I2CDATA, data, 1);
541 envy24_wrcs(sc, ENVY24_CCS_I2CDEV,
542 (dev & ENVY24_CCS_I2CDEV_ADDR) | ENVY24_CCS_I2CDEV_WR, 1);
543 for (i = 0; i < ENVY24_TIMEOUT; i++) {
544 data = envy24_rdcs(sc, ENVY24_CCS_I2CSTAT, 1);
545 if ((data & ENVY24_CCS_I2CSTAT_BSY) == 0)
547 DELAY(32); /* 31.25kHz */
549 if (i == ENVY24_TIMEOUT) {
558 envy24_rdrom(struct sc_info *sc, u_int32_t addr)
563 device_printf(sc->dev, "envy24_rdrom(sc, 0x%02x)\n", addr);
565 data = envy24_rdcs(sc, ENVY24_CCS_I2CSTAT, 1);
566 if ((data & ENVY24_CCS_I2CSTAT_ROM) == 0) {
568 device_printf(sc->dev, "envy24_rdrom(): E2PROM not presented\n");
573 return envy24_rdi2c(sc, ENVY24_CCS_I2CDEV_ROM, addr);
576 static struct cfg_info *
577 envy24_rom2cfg(struct sc_info *sc)
579 struct cfg_info *buff;
584 device_printf(sc->dev, "envy24_rom2cfg(sc)\n");
586 size = envy24_rdrom(sc, ENVY24_E2PROM_SIZE);
587 if (size < ENVY24_E2PROM_GPIODIR + 1) {
589 device_printf(sc->dev, "envy24_rom2cfg(): ENVY24_E2PROM_SIZE-->%d\n", size);
593 buff = malloc(sizeof(*buff), M_ENVY24, M_NOWAIT);
596 device_printf(sc->dev, "envy24_rom2cfg(): malloc()\n");
602 buff->subvendor = envy24_rdrom(sc, ENVY24_E2PROM_SUBVENDOR) << 8;
603 buff->subvendor += envy24_rdrom(sc, ENVY24_E2PROM_SUBVENDOR + 1);
604 buff->subdevice = envy24_rdrom(sc, ENVY24_E2PROM_SUBDEVICE) << 8;
605 buff->subdevice += envy24_rdrom(sc, ENVY24_E2PROM_SUBDEVICE + 1);
606 buff->scfg = envy24_rdrom(sc, ENVY24_E2PROM_SCFG);
607 buff->acl = envy24_rdrom(sc, ENVY24_E2PROM_ACL);
608 buff->i2s = envy24_rdrom(sc, ENVY24_E2PROM_I2S);
609 buff->spdif = envy24_rdrom(sc, ENVY24_E2PROM_SPDIF);
610 buff->gpiomask = envy24_rdrom(sc, ENVY24_E2PROM_GPIOMASK);
611 buff->gpiostate = envy24_rdrom(sc, ENVY24_E2PROM_GPIOSTATE);
612 buff->gpiodir = envy24_rdrom(sc, ENVY24_E2PROM_GPIODIR);
614 for (i = 0; cfg_table[i].subvendor != 0 || cfg_table[i].subdevice != 0; i++)
615 if (cfg_table[i].subvendor == buff->subvendor &&
616 cfg_table[i].subdevice == buff->subdevice)
618 buff->name = cfg_table[i].name;
619 buff->codec = cfg_table[i].codec;
625 envy24_cfgfree(struct cfg_info *cfg) {
633 /* -------------------------------------------------------------------- */
635 /* AC'97 codec access routines */
639 envy24_coldcd(struct sc_info *sc)
645 device_printf(sc->dev, "envy24_coldcd()\n");
647 envy24_wrmt(sc, ENVY24_MT_AC97CMD, ENVY24_MT_AC97CMD_CLD, 1);
649 envy24_wrmt(sc, ENVY24_MT_AC97CMD, 0, 1);
651 for (i = 0; i < ENVY24_TIMEOUT; i++) {
652 data = envy24_rdmt(sc, ENVY24_MT_AC97CMD, 1);
653 if (data & ENVY24_MT_AC97CMD_RDY) {
663 envy24_slavecd(struct sc_info *sc)
669 device_printf(sc->dev, "envy24_slavecd()\n");
671 envy24_wrmt(sc, ENVY24_MT_AC97CMD,
672 ENVY24_MT_AC97CMD_CLD | ENVY24_MT_AC97CMD_WRM, 1);
674 envy24_wrmt(sc, ENVY24_MT_AC97CMD, 0, 1);
676 for (i = 0; i < ENVY24_TIMEOUT; i++) {
677 data = envy24_rdmt(sc, ENVY24_MT_AC97CMD, 1);
678 if (data & ENVY24_MT_AC97CMD_RDY) {
688 envy24_rdcd(kobj_t obj, void *devinfo, int regno)
690 struct sc_info *sc = (struct sc_info *)devinfo;
695 device_printf(sc->dev, "envy24_rdcd(obj, sc, 0x%02x)\n", regno);
697 envy24_wrmt(sc, ENVY24_MT_AC97IDX, (u_int32_t)regno, 1);
698 envy24_wrmt(sc, ENVY24_MT_AC97CMD, ENVY24_MT_AC97CMD_RD, 1);
699 for (i = 0; i < ENVY24_TIMEOUT; i++) {
700 data = envy24_rdmt(sc, ENVY24_MT_AC97CMD, 1);
701 if ((data & ENVY24_MT_AC97CMD_RD) == 0)
704 data = envy24_rdmt(sc, ENVY24_MT_AC97DLO, 2);
707 device_printf(sc->dev, "envy24_rdcd(): return 0x%x\n", data);
713 envy24_wrcd(kobj_t obj, void *devinfo, int regno, u_int16_t data)
715 struct sc_info *sc = (struct sc_info *)devinfo;
720 device_printf(sc->dev, "envy24_wrcd(obj, sc, 0x%02x, 0x%04x)\n", regno, data);
722 envy24_wrmt(sc, ENVY24_MT_AC97IDX, (u_int32_t)regno, 1);
723 envy24_wrmt(sc, ENVY24_MT_AC97DLO, (u_int32_t)data, 2);
724 envy24_wrmt(sc, ENVY24_MT_AC97CMD, ENVY24_MT_AC97CMD_WR, 1);
725 for (i = 0; i < ENVY24_TIMEOUT; i++) {
726 cmd = envy24_rdmt(sc, ENVY24_MT_AC97CMD, 1);
727 if ((cmd & ENVY24_MT_AC97CMD_WR) == 0)
734 static kobj_method_t envy24_ac97_methods[] = {
735 KOBJMETHOD(ac97_read, envy24_rdcd),
736 KOBJMETHOD(ac97_write, envy24_wrcd),
739 AC97_DECLARE(envy24_ac97);
742 /* -------------------------------------------------------------------- */
744 /* GPIO access routines */
747 envy24_gpiord(struct sc_info *sc)
749 return envy24_rdci(sc, ENVY24_CCI_GPIODAT);
753 envy24_gpiowr(struct sc_info *sc, u_int32_t data)
756 device_printf(sc->dev, "envy24_gpiowr(sc, 0x%02x)\n", data & 0xff);
759 envy24_wrci(sc, ENVY24_CCI_GPIODAT, data);
765 envy24_gpiogetmask(struct sc_info *sc)
767 return envy24_rdci(sc, ENVY24_CCI_GPIOMASK);
772 envy24_gpiosetmask(struct sc_info *sc, u_int32_t mask)
774 envy24_wrci(sc, ENVY24_CCI_GPIOMASK, mask);
780 envy24_gpiogetdir(struct sc_info *sc)
782 return envy24_rdci(sc, ENVY24_CCI_GPIOCTL);
787 envy24_gpiosetdir(struct sc_info *sc, u_int32_t dir)
789 envy24_wrci(sc, ENVY24_CCI_GPIOCTL, dir);
793 /* -------------------------------------------------------------------- */
795 /* Envy24 I2C through GPIO bit-banging */
797 struct envy24_delta_ak4524_codec {
798 struct spicds_info *info;
799 struct sc_info *parent;
806 envy24_gpio_i2c_ctl(void *codec, unsigned int scl, unsigned int sda)
809 struct envy24_delta_ak4524_codec *ptr = codec;
811 device_printf(ptr->parent->dev, "--> %d, %d\n", scl, sda);
813 data = envy24_gpiord(ptr->parent);
814 data &= ~(SDA_GPIO | SCL_GPIO);
815 if (scl) data += SCL_GPIO;
816 if (sda) data += SDA_GPIO;
817 envy24_gpiowr(ptr->parent, data);
822 i2c_wrbit(void *codec, void (*ctrl)(void*, unsigned int, unsigned int), int bit)
824 struct envy24_delta_ak4524_codec *ptr = codec;
841 i2c_start(void *codec, void (*ctrl)(void*, unsigned int, unsigned int))
843 struct envy24_delta_ak4524_codec *ptr = codec;
854 i2c_stop(void *codec, void (*ctrl)(void*, unsigned int, unsigned int))
856 struct envy24_delta_ak4524_codec *ptr = codec;
867 i2c_ack(void *codec, void (*ctrl)(void*, unsigned int, unsigned int))
869 struct envy24_delta_ak4524_codec *ptr = codec;
875 /* dummy, need routine to change gpio direction */
881 i2c_wr(void *codec, void (*ctrl)(void*, unsigned int, unsigned int), u_int32_t dev, int reg, u_int8_t val)
883 struct envy24_delta_ak4524_codec *ptr = codec;
886 i2c_start(ptr, ctrl);
888 for (mask = 0x80; mask != 0; mask >>= 1)
889 i2c_wrbit(ptr, ctrl, dev & mask);
893 for (mask = 0x80; mask != 0; mask >>= 1)
894 i2c_wrbit(ptr, ctrl, reg & mask);
898 for (mask = 0x80; mask != 0; mask >>= 1)
899 i2c_wrbit(ptr, ctrl, val & mask);
905 /* -------------------------------------------------------------------- */
907 /* M-Audio Delta series AK4524 access interface routine */
910 envy24_delta_ak4524_ctl(void *codec, unsigned int cs, unsigned int cclk, unsigned int cdti)
913 struct envy24_delta_ak4524_codec *ptr = codec;
916 device_printf(ptr->parent->dev, "--> %d, %d, %d\n", cs, cclk, cdti);
918 data = envy24_gpiord(ptr->parent);
919 data &= ~(ptr->cs | ptr->cclk | ptr->cdti);
920 if (cs) data += ptr->cs;
921 if (cclk) data += ptr->cclk;
922 if (cdti) data += ptr->cdti;
923 envy24_gpiowr(ptr->parent, data);
928 envy24_delta_ak4524_create(device_t dev, void *info, int dir, int num)
930 struct sc_info *sc = info;
931 struct envy24_delta_ak4524_codec *buff = NULL;
934 device_printf(sc->dev, "envy24_delta_ak4524_create(dev, sc, %d, %d)\n", dir, num);
937 buff = malloc(sizeof(*buff), M_ENVY24, M_NOWAIT);
941 if (dir == PCMDIR_REC && sc->adc[num] != NULL)
942 buff->info = ((struct envy24_delta_ak4524_codec *)sc->adc[num])->info;
943 else if (dir == PCMDIR_PLAY && sc->dac[num] != NULL)
944 buff->info = ((struct envy24_delta_ak4524_codec *)sc->dac[num])->info;
946 buff->info = spicds_create(dev, buff, num, envy24_delta_ak4524_ctl);
947 if (buff->info == NULL) {
948 free(buff, M_ENVY24);
960 envy24_delta_ak4524_destroy(void *codec)
962 struct envy24_delta_ak4524_codec *ptr = codec;
966 device_printf(ptr->parent->dev, "envy24_delta_ak4524_destroy()\n");
969 if (ptr->dir == PCMDIR_PLAY) {
970 if (ptr->parent->dac[ptr->num] != NULL)
971 spicds_destroy(ptr->info);
974 if (ptr->parent->adc[ptr->num] != NULL)
975 spicds_destroy(ptr->info);
978 free(codec, M_ENVY24);
982 envy24_delta_ak4524_init(void *codec)
985 u_int32_t gpiomask, gpiodir;
987 struct envy24_delta_ak4524_codec *ptr = codec;
991 device_printf(ptr->parent->dev, "envy24_delta_ak4524_init()\n");
995 gpiomask = envy24_gpiogetmask(ptr->parent);
996 gpiomask &= ~(ENVY24_GPIO_AK4524_CDTI | ENVY24_GPIO_AK4524_CCLK | ENVY24_GPIO_AK4524_CS0 | ENVY24_GPIO_AK4524_CS1);
997 envy24_gpiosetmask(ptr->parent, gpiomask);
998 gpiodir = envy24_gpiogetdir(ptr->parent);
999 gpiodir |= ENVY24_GPIO_AK4524_CDTI | ENVY24_GPIO_AK4524_CCLK | ENVY24_GPIO_AK4524_CS0 | ENVY24_GPIO_AK4524_CS1;
1000 envy24_gpiosetdir(ptr->parent, gpiodir);
1002 ptr->cs = ptr->parent->cfg->cs;
1004 envy24_gpiosetmask(ptr->parent, ENVY24_GPIO_CS8414_STATUS);
1005 envy24_gpiosetdir(ptr->parent, ~ENVY24_GPIO_CS8414_STATUS);
1007 ptr->cs = ENVY24_GPIO_AK4524_CS0;
1009 ptr->cs = ENVY24_GPIO_AK4524_CS1;
1010 ptr->cclk = ENVY24_GPIO_AK4524_CCLK;
1012 ptr->cclk = ptr->parent->cfg->cclk;
1013 ptr->cdti = ptr->parent->cfg->cdti;
1014 spicds_settype(ptr->info, ptr->parent->cfg->type);
1015 spicds_setcif(ptr->info, ptr->parent->cfg->cif);
1016 spicds_setformat(ptr->info,
1017 AK452X_FORMAT_I2S | AK452X_FORMAT_256FSN | AK452X_FORMAT_1X);
1018 spicds_setdvc(ptr->info, AK452X_DVC_DEMOFF);
1019 /* for the time being, init only first codec */
1021 spicds_init(ptr->info);
1023 /* 6fire rear input init test, set ptr->num to 1 for test */
1024 if (ptr->parent->cfg->subvendor == 0x153b && \
1025 ptr->parent->cfg->subdevice == 0x1138 && ptr->num == 100) {
1027 spicds_init(ptr->info);
1028 device_printf(ptr->parent->dev, "6fire rear input init\n");
1029 i2c_wr(ptr, envy24_gpio_i2c_ctl, \
1030 PCA9554_I2CDEV, PCA9554_DIR, 0x80);
1031 i2c_wr(ptr, envy24_gpio_i2c_ctl, \
1032 PCA9554_I2CDEV, PCA9554_OUT, 0x02);
1037 envy24_delta_ak4524_reinit(void *codec)
1039 struct envy24_delta_ak4524_codec *ptr = codec;
1043 device_printf(ptr->parent->dev, "envy24_delta_ak4524_reinit()\n");
1046 spicds_reinit(ptr->info);
1050 envy24_delta_ak4524_setvolume(void *codec, int dir, unsigned int left, unsigned int right)
1052 struct envy24_delta_ak4524_codec *ptr = codec;
1056 device_printf(ptr->parent->dev, "envy24_delta_ak4524_set()\n");
1059 spicds_set(ptr->info, dir, left, right);
1063 There is no need for AK452[48] codec to set sample rate
1065 envy24_delta_ak4524_setrate(struct envy24_delta_ak4524_codec *codec, int which, int rate)
1070 /* -------------------------------------------------------------------- */
1072 /* hardware access routeines */
1077 } envy24_speedtab[] = {
1078 {48000, ENVY24_MT_RATE_48000},
1079 {24000, ENVY24_MT_RATE_24000},
1080 {12000, ENVY24_MT_RATE_12000},
1081 {9600, ENVY24_MT_RATE_9600},
1082 {32000, ENVY24_MT_RATE_32000},
1083 {16000, ENVY24_MT_RATE_16000},
1084 {8000, ENVY24_MT_RATE_8000},
1085 {96000, ENVY24_MT_RATE_96000},
1086 {64000, ENVY24_MT_RATE_64000},
1087 {44100, ENVY24_MT_RATE_44100},
1088 {22050, ENVY24_MT_RATE_22050},
1089 {11025, ENVY24_MT_RATE_11025},
1090 {88200, ENVY24_MT_RATE_88200},
1095 envy24_setspeed(struct sc_info *sc, u_int32_t speed) {
1100 device_printf(sc->dev, "envy24_setspeed(sc, %d)\n", speed);
1103 code = ENVY24_MT_RATE_SPDIF; /* external master clock */
1107 for (i = 0; envy24_speedtab[i].speed != 0; i++) {
1108 if (envy24_speedtab[i].speed == speed)
1111 code = envy24_speedtab[i].code;
1114 device_printf(sc->dev, "envy24_setspeed(): speed %d/code 0x%04x\n", envy24_speedtab[i].speed, code);
1117 envy24_wrmt(sc, ENVY24_MT_RATE, code, 1);
1118 code = envy24_rdmt(sc, ENVY24_MT_RATE, 1);
1119 code &= ENVY24_MT_RATE_MASK;
1120 for (i = 0; envy24_speedtab[i].code < 0x10; i++) {
1121 if (envy24_speedtab[i].code == code)
1124 speed = envy24_speedtab[i].speed;
1130 device_printf(sc->dev, "envy24_setspeed(): return %d\n", speed);
1136 envy24_setvolume(struct sc_info *sc, unsigned ch)
1139 device_printf(sc->dev, "envy24_setvolume(sc, %d)\n", ch);
1141 if (sc->cfg->subvendor==0x153b && sc->cfg->subdevice==0x1138 ) {
1142 envy24_wrmt(sc, ENVY24_MT_VOLIDX, 16, 1);
1143 envy24_wrmt(sc, ENVY24_MT_VOLUME, 0x7f7f, 2);
1144 envy24_wrmt(sc, ENVY24_MT_VOLIDX, 17, 1);
1145 envy24_wrmt(sc, ENVY24_MT_VOLUME, 0x7f7f, 2);
1148 envy24_wrmt(sc, ENVY24_MT_VOLIDX, ch * 2, 1);
1149 envy24_wrmt(sc, ENVY24_MT_VOLUME, 0x7f00 | sc->left[ch], 2);
1150 envy24_wrmt(sc, ENVY24_MT_VOLIDX, ch * 2 + 1, 1);
1151 envy24_wrmt(sc, ENVY24_MT_VOLUME, (sc->right[ch] << 8) | 0x7f, 2);
1155 envy24_mutevolume(struct sc_info *sc, unsigned ch)
1160 device_printf(sc->dev, "envy24_mutevolume(sc, %d)\n", ch);
1162 vol = ENVY24_VOL_MUTE << 8 | ENVY24_VOL_MUTE;
1163 envy24_wrmt(sc, ENVY24_MT_VOLIDX, ch * 2, 1);
1164 envy24_wrmt(sc, ENVY24_MT_VOLUME, vol, 2);
1165 envy24_wrmt(sc, ENVY24_MT_VOLIDX, ch * 2 + 1, 1);
1166 envy24_wrmt(sc, ENVY24_MT_VOLUME, vol, 2);
1170 envy24_gethwptr(struct sc_info *sc, int dir)
1176 device_printf(sc->dev, "envy24_gethwptr(sc, %d)\n", dir);
1178 if (dir == PCMDIR_PLAY) {
1179 rtn = sc->psize / 4;
1180 unit = ENVY24_PLAY_BUFUNIT / 4;
1181 regno = ENVY24_MT_PCNT;
1184 rtn = sc->rsize / 4;
1185 unit = ENVY24_REC_BUFUNIT / 4;
1186 regno = ENVY24_MT_RCNT;
1189 ptr = envy24_rdmt(sc, regno, 2);
1194 device_printf(sc->dev, "envy24_gethwptr(): return %d\n", rtn);
1200 envy24_updintr(struct sc_info *sc, int dir)
1202 int regptr, regintr;
1203 u_int32_t mask, intr;
1204 u_int32_t ptr, size, cnt;
1208 device_printf(sc->dev, "envy24_updintr(sc, %d)\n", dir);
1210 if (dir == PCMDIR_PLAY) {
1212 size = sc->psize / 4;
1213 regptr = ENVY24_MT_PCNT;
1214 regintr = ENVY24_MT_PTERM;
1215 mask = ~ENVY24_MT_INT_PMASK;
1219 size = sc->rsize / 4;
1220 regptr = ENVY24_MT_RCNT;
1221 regintr = ENVY24_MT_RTERM;
1222 mask = ~ENVY24_MT_INT_RMASK;
1225 ptr = size - envy24_rdmt(sc, regptr, 2) - 1;
1227 cnt = blk - ptr % blk - 1;
1233 device_printf(sc->dev, "envy24_updintr():ptr = %d, blk = %d, cnt = %d\n", ptr, blk, cnt);
1235 envy24_wrmt(sc, regintr, cnt, 2);
1236 intr = envy24_rdmt(sc, ENVY24_MT_INT, 1);
1238 device_printf(sc->dev, "envy24_updintr():intr = 0x%02x, mask = 0x%02x\n", intr, mask);
1240 envy24_wrmt(sc, ENVY24_MT_INT, intr & mask, 1);
1242 device_printf(sc->dev, "envy24_updintr():INT-->0x%02x\n",
1243 envy24_rdmt(sc, ENVY24_MT_INT, 1));
1251 envy24_maskintr(struct sc_info *sc, int dir)
1253 u_int32_t mask, intr;
1256 device_printf(sc->dev, "envy24_maskintr(sc, %d)\n", dir);
1258 if (dir == PCMDIR_PLAY)
1259 mask = ENVY24_MT_INT_PMASK;
1261 mask = ENVY24_MT_INT_RMASK;
1262 intr = envy24_rdmt(sc, ENVY24_MT_INT, 1);
1263 envy24_wrmt(sc, ENVY24_MT_INT, intr | mask, 1);
1270 envy24_checkintr(struct sc_info *sc, int dir)
1272 u_int32_t mask, stat, intr, rtn;
1275 device_printf(sc->dev, "envy24_checkintr(sc, %d)\n", dir);
1277 intr = envy24_rdmt(sc, ENVY24_MT_INT, 1);
1278 if (dir == PCMDIR_PLAY) {
1279 if ((rtn = intr & ENVY24_MT_INT_PSTAT) != 0) {
1280 mask = ~ENVY24_MT_INT_RSTAT;
1281 stat = ENVY24_MT_INT_PSTAT | ENVY24_MT_INT_PMASK;
1282 envy24_wrmt(sc, ENVY24_MT_INT, (intr & mask) | stat, 1);
1286 if ((rtn = intr & ENVY24_MT_INT_RSTAT) != 0) {
1287 mask = ~ENVY24_MT_INT_PSTAT;
1288 stat = ENVY24_MT_INT_RSTAT | ENVY24_MT_INT_RMASK;
1289 envy24_wrmt(sc, ENVY24_MT_INT, (intr & mask) | stat, 1);
1297 envy24_start(struct sc_info *sc, int dir)
1302 device_printf(sc->dev, "envy24_start(sc, %d)\n", dir);
1304 if (dir == PCMDIR_PLAY)
1305 sw = ENVY24_MT_PCTL_PSTART;
1307 sw = ENVY24_MT_PCTL_RSTART;
1309 stat = envy24_rdmt(sc, ENVY24_MT_PCTL, 1);
1310 envy24_wrmt(sc, ENVY24_MT_PCTL, stat | sw, 1);
1313 device_printf(sc->dev, "PADDR:0x%08x\n", envy24_rdmt(sc, ENVY24_MT_PADDR, 4));
1314 device_printf(sc->dev, "PCNT:%ld\n", envy24_rdmt(sc, ENVY24_MT_PCNT, 2));
1321 envy24_stop(struct sc_info *sc, int dir)
1326 device_printf(sc->dev, "envy24_stop(sc, %d)\n", dir);
1328 if (dir == PCMDIR_PLAY)
1329 sw = ~ENVY24_MT_PCTL_PSTART;
1331 sw = ~ENVY24_MT_PCTL_RSTART;
1333 stat = envy24_rdmt(sc, ENVY24_MT_PCTL, 1);
1334 envy24_wrmt(sc, ENVY24_MT_PCTL, stat & sw, 1);
1340 envy24_route(struct sc_info *sc, int dac, int class, int adc, int rev)
1342 u_int32_t reg, mask;
1343 u_int32_t left, right;
1346 device_printf(sc->dev, "envy24_route(sc, %d, %d, %d, %d)\n",
1347 dac, class, adc, rev);
1349 /* parameter pattern check */
1350 if (dac < 0 || ENVY24_ROUTE_DAC_SPDIF < dac)
1352 if (class == ENVY24_ROUTE_CLASS_MIX &&
1353 (dac != ENVY24_ROUTE_DAC_1 && dac != ENVY24_ROUTE_DAC_SPDIF))
1356 left = ENVY24_ROUTE_RIGHT;
1357 right = ENVY24_ROUTE_LEFT;
1360 left = ENVY24_ROUTE_LEFT;
1361 right = ENVY24_ROUTE_RIGHT;
1364 if (dac == ENVY24_ROUTE_DAC_SPDIF) {
1365 reg = class | class << 2 |
1366 ((adc << 1 | left) | left << 3) << 8 |
1367 ((adc << 1 | right) | right << 3) << 12;
1369 device_printf(sc->dev, "envy24_route(): MT_SPDOUT-->0x%04x\n", reg);
1371 envy24_wrmt(sc, ENVY24_MT_SPDOUT, reg, 2);
1374 mask = ~(0x0303 << dac * 2);
1375 reg = envy24_rdmt(sc, ENVY24_MT_PSDOUT, 2);
1376 reg = (reg & mask) | ((class | class << 8) << dac * 2);
1378 device_printf(sc->dev, "envy24_route(): MT_PSDOUT-->0x%04x\n", reg);
1380 envy24_wrmt(sc, ENVY24_MT_PSDOUT, reg, 2);
1381 mask = ~(0xff << dac * 8);
1382 reg = envy24_rdmt(sc, ENVY24_MT_RECORD, 4);
1383 reg = (reg & mask) |
1384 (((adc << 1 | left) | left << 3) |
1385 ((adc << 1 | right) | right << 3) << 4) << dac * 8;
1387 device_printf(sc->dev, "envy24_route(): MT_RECORD-->0x%08x\n", reg);
1389 envy24_wrmt(sc, ENVY24_MT_RECORD, reg, 4);
1391 /* 6fire rear input init test */
1392 envy24_wrmt(sc, ENVY24_MT_RECORD, 0x00, 4);
1398 /* -------------------------------------------------------------------- */
1400 /* buffer copy routines */
1402 envy24_p32sl(struct sc_chinfo *ch)
1407 int src, dst, ssize, dsize, slot;
1410 length = sndbuf_getready(ch->buffer) / 8;
1411 dmabuf = ch->parent->pbuf;
1412 data = (u_int32_t *)ch->data;
1413 src = sndbuf_getreadyptr(ch->buffer) / 4;
1414 dst = src / 2 + ch->offset;
1415 ssize = ch->size / 4;
1416 dsize = ch->size / 8;
1419 for (i = 0; i < length; i++) {
1420 dmabuf[dst * ENVY24_PLAY_CHNUM + slot].buffer = data[src];
1421 dmabuf[dst * ENVY24_PLAY_CHNUM + slot + 1].buffer = data[src + 1];
1432 envy24_p16sl(struct sc_chinfo *ch)
1437 int src, dst, ssize, dsize, slot;
1441 device_printf(ch->parent->dev, "envy24_p16sl()\n");
1443 length = sndbuf_getready(ch->buffer) / 4;
1444 dmabuf = ch->parent->pbuf;
1445 data = (u_int16_t *)ch->data;
1446 src = sndbuf_getreadyptr(ch->buffer) / 2;
1447 dst = src / 2 + ch->offset;
1448 ssize = ch->size / 2;
1449 dsize = ch->size / 4;
1452 device_printf(ch->parent->dev, "envy24_p16sl():%lu-->%lu(%lu)\n", src, dst, length);
1455 for (i = 0; i < length; i++) {
1456 dmabuf[dst * ENVY24_PLAY_CHNUM + slot].buffer = (u_int32_t)data[src] << 16;
1457 dmabuf[dst * ENVY24_PLAY_CHNUM + slot + 1].buffer = (u_int32_t)data[src + 1] << 16;
1460 printf("%08x", dmabuf[dst * ENVY24_PLAY_CHNUM + slot]);
1461 printf("%08x", dmabuf[dst * ENVY24_PLAY_CHNUM + slot + 1]);
1477 envy24_p8u(struct sc_chinfo *ch)
1482 int src, dst, ssize, dsize, slot;
1485 length = sndbuf_getready(ch->buffer) / 2;
1486 dmabuf = ch->parent->pbuf;
1487 data = (u_int8_t *)ch->data;
1488 src = sndbuf_getreadyptr(ch->buffer);
1489 dst = src / 2 + ch->offset;
1491 dsize = ch->size / 4;
1494 for (i = 0; i < length; i++) {
1495 dmabuf[dst * ENVY24_PLAY_CHNUM + slot].buffer = ((u_int32_t)data[src] ^ 0x80) << 24;
1496 dmabuf[dst * ENVY24_PLAY_CHNUM + slot + 1].buffer = ((u_int32_t)data[src + 1] ^ 0x80) << 24;
1507 envy24_r32sl(struct sc_chinfo *ch)
1512 int src, dst, ssize, dsize, slot;
1515 length = sndbuf_getfree(ch->buffer) / 8;
1516 dmabuf = ch->parent->rbuf;
1517 data = (u_int32_t *)ch->data;
1518 dst = sndbuf_getfreeptr(ch->buffer) / 4;
1519 src = dst / 2 + ch->offset;
1520 dsize = ch->size / 4;
1521 ssize = ch->size / 8;
1522 slot = (ch->num - ENVY24_CHAN_REC_ADC1) * 2;
1524 for (i = 0; i < length; i++) {
1525 data[dst] = dmabuf[src * ENVY24_REC_CHNUM + slot].buffer;
1526 data[dst + 1] = dmabuf[src * ENVY24_REC_CHNUM + slot + 1].buffer;
1537 envy24_r16sl(struct sc_chinfo *ch)
1542 int src, dst, ssize, dsize, slot;
1545 length = sndbuf_getfree(ch->buffer) / 4;
1546 dmabuf = ch->parent->rbuf;
1547 data = (u_int16_t *)ch->data;
1548 dst = sndbuf_getfreeptr(ch->buffer) / 2;
1549 src = dst / 2 + ch->offset;
1550 dsize = ch->size / 2;
1551 ssize = ch->size / 8;
1552 slot = (ch->num - ENVY24_CHAN_REC_ADC1) * 2;
1554 for (i = 0; i < length; i++) {
1555 data[dst] = dmabuf[src * ENVY24_REC_CHNUM + slot].buffer;
1556 data[dst + 1] = dmabuf[src * ENVY24_REC_CHNUM + slot + 1].buffer;
1566 /* -------------------------------------------------------------------- */
1568 /* channel interface */
1570 envy24chan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir)
1572 struct sc_info *sc = (struct sc_info *)devinfo;
1573 struct sc_chinfo *ch;
1577 device_printf(sc->dev, "envy24chan_init(obj, devinfo, b, c, %d)\n", dir);
1579 snd_mtxlock(sc->lock);
1580 if ((sc->chnum > ENVY24_CHAN_PLAY_SPDIF && dir != PCMDIR_REC) ||
1581 (sc->chnum < ENVY24_CHAN_REC_ADC1 && dir != PCMDIR_PLAY)) {
1582 snd_mtxunlock(sc->lock);
1587 ch = &sc->chan[num];
1588 ch->size = 8 * ENVY24_SAMPLE_NUM;
1589 ch->data = malloc(ch->size, M_ENVY24, M_NOWAIT);
1590 if (ch->data == NULL) {
1599 /* set channel map */
1600 ch->num = envy24_chanmap[num];
1601 snd_mtxunlock(sc->lock);
1602 sndbuf_setup(ch->buffer, ch->data, ch->size);
1603 snd_mtxlock(sc->lock);
1604 /* these 2 values are dummy */
1608 snd_mtxunlock(sc->lock);
1614 envy24chan_free(kobj_t obj, void *data)
1616 struct sc_chinfo *ch = data;
1617 struct sc_info *sc = ch->parent;
1620 device_printf(sc->dev, "envy24chan_free()\n");
1622 snd_mtxlock(sc->lock);
1623 if (ch->data != NULL) {
1624 free(ch->data, M_ENVY24);
1627 snd_mtxunlock(sc->lock);
1633 envy24chan_setformat(kobj_t obj, void *data, u_int32_t format)
1635 struct sc_chinfo *ch = data;
1636 struct sc_info *sc = ch->parent;
1637 struct envy24_emldma *emltab;
1638 /* unsigned int bcnt, bsize; */
1642 device_printf(sc->dev, "envy24chan_setformat(obj, data, 0x%08x)\n", format);
1644 snd_mtxlock(sc->lock);
1645 /* check and get format related information */
1646 if (ch->dir == PCMDIR_PLAY)
1647 emltab = envy24_pemltab;
1649 emltab = envy24_remltab;
1650 if (emltab == NULL) {
1651 snd_mtxunlock(sc->lock);
1654 for (i = 0; emltab[i].format != 0; i++)
1655 if (emltab[i].format == format)
1657 if (emltab[i].format == 0) {
1658 snd_mtxunlock(sc->lock);
1662 /* set format information */
1663 ch->format = format;
1664 ch->emldma = emltab[i].emldma;
1665 if (ch->unit > emltab[i].unit)
1666 ch->blk *= ch->unit / emltab[i].unit;
1668 ch->blk /= emltab[i].unit / ch->unit;
1669 ch->unit = emltab[i].unit;
1671 /* set channel buffer information */
1672 ch->size = ch->unit * ENVY24_SAMPLE_NUM;
1674 if (ch->dir == PCMDIR_PLAY)
1675 bsize = ch->blk * 4 / ENVY24_PLAY_BUFUNIT;
1677 bsize = ch->blk * 4 / ENVY24_REC_BUFUNIT;
1679 bcnt = ch->size / bsize;
1680 sndbuf_resize(ch->buffer, bcnt, bsize);
1682 snd_mtxunlock(sc->lock);
1685 device_printf(sc->dev, "envy24chan_setformat(): return 0x%08x\n", 0);
1691 IMPLEMENT NOTICE: In this driver, setspeed function only do setting
1692 of speed information value. And real hardware speed setting is done
1693 at start triggered(see envy24chan_trigger()). So, at this function
1694 is called, any value that ENVY24 can use is able to set. But, at
1695 start triggerd, some other channel is running, and that channel's
1696 speed isn't same with, then trigger function will fail.
1699 envy24chan_setspeed(kobj_t obj, void *data, u_int32_t speed)
1701 struct sc_chinfo *ch = data;
1702 u_int32_t val, prev;
1706 device_printf(ch->parent->dev, "envy24chan_setspeed(obj, data, %d)\n", speed);
1709 for (i = 0; (val = envy24_speed[i]) != 0; i++) {
1710 if (abs(val - speed) < abs(prev - speed))
1718 device_printf(ch->parent->dev, "envy24chan_setspeed(): return %d\n", ch->speed);
1724 envy24chan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
1726 struct sc_chinfo *ch = data;
1727 /* struct sc_info *sc = ch->parent; */
1728 u_int32_t size, prev;
1729 unsigned int bcnt, bsize;
1732 device_printf(sc->dev, "envy24chan_setblocksize(obj, data, %d)\n", blocksize);
1735 /* snd_mtxlock(sc->lock); */
1736 for (size = ch->size / 2; size > 0; size /= 2) {
1737 if (abs(size - blocksize) < abs(prev - blocksize))
1743 ch->blk = prev / ch->unit;
1744 if (ch->dir == PCMDIR_PLAY)
1745 ch->blk *= ENVY24_PLAY_BUFUNIT / 4;
1747 ch->blk *= ENVY24_REC_BUFUNIT / 4;
1748 /* set channel buffer information */
1749 /* ch->size = ch->unit * ENVY24_SAMPLE_NUM; */
1750 if (ch->dir == PCMDIR_PLAY)
1751 bsize = ch->blk * 4 / ENVY24_PLAY_BUFUNIT;
1753 bsize = ch->blk * 4 / ENVY24_REC_BUFUNIT;
1755 bcnt = ch->size / bsize;
1756 sndbuf_resize(ch->buffer, bcnt, bsize);
1757 /* snd_mtxunlock(sc->lock); */
1760 device_printf(sc->dev, "envy24chan_setblocksize(): return %d\n", prev);
1765 /* semantic note: must start at beginning of buffer */
1767 envy24chan_trigger(kobj_t obj, void *data, int go)
1769 struct sc_chinfo *ch = data;
1770 struct sc_info *sc = ch->parent;
1777 device_printf(sc->dev, "envy24chan_trigger(obj, data, %d)\n", go);
1779 snd_mtxlock(sc->lock);
1780 if (ch->dir == PCMDIR_PLAY)
1787 device_printf(sc->dev, "envy24chan_trigger(): start\n");
1789 /* check or set channel speed */
1790 if (sc->run[0] == 0 && sc->run[1] == 0) {
1791 sc->speed = envy24_setspeed(sc, ch->speed);
1792 sc->caps[0].minspeed = sc->caps[0].maxspeed = sc->speed;
1793 sc->caps[1].minspeed = sc->caps[1].maxspeed = sc->speed;
1795 else if (ch->speed != 0 && ch->speed != sc->speed) {
1800 ch->channel->speed = sc->speed;
1801 /* start or enable channel */
1803 if (sc->run[slot] == 1) {
1806 sc->blk[slot] = ch->blk;
1809 ptr = envy24_gethwptr(sc, ch->dir);
1810 ch->offset = ((ptr / ch->blk + 1) * ch->blk %
1811 (ch->size / 4)) * 4 / ch->unit;
1812 if (ch->blk < sc->blk[slot])
1813 sc->blk[slot] = ch->blk;
1815 if (ch->dir == PCMDIR_PLAY) {
1817 envy24_setvolume(sc, ch->num);
1819 envy24_updintr(sc, ch->dir);
1820 if (sc->run[slot] == 1)
1821 envy24_start(sc, ch->dir);
1824 case PCMTRIG_EMLDMAWR:
1826 device_printf(sc->dev, "envy24chan_trigger(): emldmawr\n");
1834 case PCMTRIG_EMLDMARD:
1836 device_printf(sc->dev, "envy24chan_trigger(): emldmard\n");
1847 device_printf(sc->dev, "envy24chan_trigger(): abort\n");
1851 if (ch->dir == PCMDIR_PLAY)
1852 envy24_mutevolume(sc, ch->num);
1853 if (sc->run[slot] == 0) {
1854 envy24_stop(sc, ch->dir);
1858 else if (ch->blk == sc->blk[slot]) {
1859 sc->blk[slot] = ENVY24_SAMPLE_NUM / 2;
1860 for (i = 0; i < ENVY24_CHAN_NUM; i++) {
1861 if (sc->chan[i].dir == ch->dir &&
1862 sc->chan[i].run == 1 &&
1863 sc->chan[i].blk < sc->blk[slot])
1864 sc->blk[slot] = sc->chan[i].blk;
1866 if (ch->blk != sc->blk[slot])
1867 envy24_updintr(sc, ch->dir);
1874 snd_mtxunlock(sc->lock);
1879 envy24chan_getptr(kobj_t obj, void *data)
1881 struct sc_chinfo *ch = data;
1882 struct sc_info *sc = ch->parent;
1886 device_printf(sc->dev, "envy24chan_getptr()\n");
1888 snd_mtxlock(sc->lock);
1889 ptr = envy24_gethwptr(sc, ch->dir);
1890 rtn = ptr * ch->unit;
1891 snd_mtxunlock(sc->lock);
1894 device_printf(sc->dev, "envy24chan_getptr(): return %d\n",
1900 static struct pcmchan_caps *
1901 envy24chan_getcaps(kobj_t obj, void *data)
1903 struct sc_chinfo *ch = data;
1904 struct sc_info *sc = ch->parent;
1905 struct pcmchan_caps *rtn;
1908 device_printf(sc->dev, "envy24chan_getcaps()\n");
1910 snd_mtxlock(sc->lock);
1911 if (ch->dir == PCMDIR_PLAY) {
1912 if (sc->run[0] == 0)
1913 rtn = &envy24_playcaps;
1918 if (sc->run[1] == 0)
1919 rtn = &envy24_reccaps;
1923 snd_mtxunlock(sc->lock);
1928 static kobj_method_t envy24chan_methods[] = {
1929 KOBJMETHOD(channel_init, envy24chan_init),
1930 KOBJMETHOD(channel_free, envy24chan_free),
1931 KOBJMETHOD(channel_setformat, envy24chan_setformat),
1932 KOBJMETHOD(channel_setspeed, envy24chan_setspeed),
1933 KOBJMETHOD(channel_setblocksize, envy24chan_setblocksize),
1934 KOBJMETHOD(channel_trigger, envy24chan_trigger),
1935 KOBJMETHOD(channel_getptr, envy24chan_getptr),
1936 KOBJMETHOD(channel_getcaps, envy24chan_getcaps),
1939 CHANNEL_DECLARE(envy24chan);
1941 /* -------------------------------------------------------------------- */
1943 /* mixer interface */
1946 envy24mixer_init(struct snd_mixer *m)
1948 struct sc_info *sc = mix_getdevinfo(m);
1951 device_printf(sc->dev, "envy24mixer_init()\n");
1956 /* set volume control rate */
1957 snd_mtxlock(sc->lock);
1958 envy24_wrmt(sc, ENVY24_MT_VOLRATE, 0x30, 1); /* 0x30 is default value */
1960 mix_setdevs(m, ENVY24_MIX_MASK);
1961 mix_setrecdevs(m, ENVY24_MIX_REC_MASK);
1962 snd_mtxunlock(sc->lock);
1968 envy24mixer_reinit(struct snd_mixer *m)
1970 struct sc_info *sc = mix_getdevinfo(m);
1975 device_printf(sc->dev, "envy24mixer_reinit()\n");
1982 envy24mixer_uninit(struct snd_mixer *m)
1984 struct sc_info *sc = mix_getdevinfo(m);
1989 device_printf(sc->dev, "envy24mixer_uninit()\n");
1996 envy24mixer_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right)
1998 struct sc_info *sc = mix_getdevinfo(m);
1999 int ch = envy24_mixmap[dev];
2005 if (dev == 0 && sc->cfg->codec->setvolume == NULL)
2007 if (dev != 0 && ch == -1)
2009 hwch = envy24_chanmap[ch];
2011 device_printf(sc->dev, "envy24mixer_set(m, %d, %d, %d)\n",
2015 snd_mtxlock(sc->lock);
2017 for (i = 0; i < sc->dacn; i++) {
2018 sc->cfg->codec->setvolume(sc->dac[i], PCMDIR_PLAY, left, right);
2022 /* set volume value for hardware */
2023 if ((sc->left[hwch] = 100 - left) > ENVY24_VOL_MIN)
2024 sc->left[hwch] = ENVY24_VOL_MUTE;
2025 if ((sc->right[hwch] = 100 - right) > ENVY24_VOL_MIN)
2026 sc->right[hwch] = ENVY24_VOL_MUTE;
2028 /* set volume for record channel and running play channel */
2029 if (hwch > ENVY24_CHAN_PLAY_SPDIF || sc->chan[ch].run)
2030 envy24_setvolume(sc, hwch);
2032 snd_mtxunlock(sc->lock);
2034 return right << 8 | left;
2038 envy24mixer_setrecsrc(struct snd_mixer *m, u_int32_t src)
2040 struct sc_info *sc = mix_getdevinfo(m);
2041 int ch = envy24_mixmap[src];
2043 device_printf(sc->dev, "envy24mixer_setrecsrc(m, %d)\n", src);
2046 if (ch > ENVY24_CHAN_PLAY_SPDIF)
2051 static kobj_method_t envy24mixer_methods[] = {
2052 KOBJMETHOD(mixer_init, envy24mixer_init),
2053 KOBJMETHOD(mixer_reinit, envy24mixer_reinit),
2054 KOBJMETHOD(mixer_uninit, envy24mixer_uninit),
2055 KOBJMETHOD(mixer_set, envy24mixer_set),
2056 KOBJMETHOD(mixer_setrecsrc, envy24mixer_setrecsrc),
2059 MIXER_DECLARE(envy24mixer);
2061 /* -------------------------------------------------------------------- */
2063 /* The interrupt handler */
2065 envy24_intr(void *p)
2067 struct sc_info *sc = (struct sc_info *)p;
2068 struct sc_chinfo *ch;
2069 u_int32_t ptr, dsize, feed;
2073 device_printf(sc->dev, "envy24_intr()\n");
2075 snd_mtxlock(sc->lock);
2076 if (envy24_checkintr(sc, PCMDIR_PLAY)) {
2078 device_printf(sc->dev, "envy24_intr(): play\n");
2080 dsize = sc->psize / 4;
2081 ptr = dsize - envy24_rdmt(sc, ENVY24_MT_PCNT, 2) - 1;
2083 device_printf(sc->dev, "envy24_intr(): ptr = %d-->", ptr);
2085 ptr -= ptr % sc->blk[0];
2086 feed = (ptr + dsize - sc->intr[0]) % dsize;
2088 printf("%d intr = %d feed = %d\n", ptr, sc->intr[0], feed);
2090 for (i = ENVY24_CHAN_PLAY_DAC1; i <= ENVY24_CHAN_PLAY_SPDIF; i++) {
2094 device_printf(sc->dev, "envy24_intr(): chan[%d].blk = %d\n", i, ch->blk);
2096 if (ch->run && ch->blk <= feed) {
2097 snd_mtxunlock(sc->lock);
2098 chn_intr(ch->channel);
2099 snd_mtxlock(sc->lock);
2103 envy24_updintr(sc, PCMDIR_PLAY);
2105 if (envy24_checkintr(sc, PCMDIR_REC)) {
2107 device_printf(sc->dev, "envy24_intr(): rec\n");
2109 dsize = sc->rsize / 4;
2110 ptr = dsize - envy24_rdmt(sc, ENVY24_MT_RCNT, 2) - 1;
2111 ptr -= ptr % sc->blk[1];
2112 feed = (ptr + dsize - sc->intr[1]) % dsize;
2113 for (i = ENVY24_CHAN_REC_ADC1; i <= ENVY24_CHAN_REC_SPDIF; i++) {
2115 if (ch->run && ch->blk <= feed) {
2116 snd_mtxunlock(sc->lock);
2117 chn_intr(ch->channel);
2118 snd_mtxlock(sc->lock);
2122 envy24_updintr(sc, PCMDIR_REC);
2124 snd_mtxunlock(sc->lock);
2130 * Probe and attach the card
2134 envy24_pci_probe(device_t dev)
2140 printf("envy24_pci_probe()\n");
2142 if (pci_get_device(dev) == PCID_ENVY24 &&
2143 pci_get_vendor(dev) == PCIV_ENVY24) {
2144 sv = pci_get_subvendor(dev);
2145 sd = pci_get_subdevice(dev);
2146 for (i = 0; cfg_table[i].subvendor != 0 || cfg_table[i].subdevice != 0; i++) {
2147 if (cfg_table[i].subvendor == sv &&
2148 cfg_table[i].subdevice == sd) {
2152 device_set_desc(dev, cfg_table[i].name);
2154 printf("envy24_pci_probe(): return 0\n");
2160 printf("envy24_pci_probe(): return ENXIO\n");
2167 envy24_dmapsetmap(void *arg, bus_dma_segment_t *segs, int nseg, int error)
2169 /* struct sc_info *sc = (struct sc_info *)arg; */
2172 device_printf(sc->dev, "envy24_dmapsetmap()\n");
2174 printf("envy24(play): setmap %lx, %lx; ",
2175 (unsigned long)segs->ds_addr,
2176 (unsigned long)segs->ds_len);
2177 printf("%p -> %lx\n", sc->pmap, (unsigned long)vtophys(sc->pmap));
2183 envy24_dmarsetmap(void *arg, bus_dma_segment_t *segs, int nseg, int error)
2185 /* struct sc_info *sc = (struct sc_info *)arg; */
2188 device_printf(sc->dev, "envy24_dmarsetmap()\n");
2190 printf("envy24(record): setmap %lx, %lx; ",
2191 (unsigned long)segs->ds_addr,
2192 (unsigned long)segs->ds_len);
2193 printf("%p -> %lx\n", sc->rmap, (unsigned long)vtophys(sc->pmap));
2199 envy24_dmafree(struct sc_info *sc)
2202 device_printf(sc->dev, "envy24_dmafree():");
2203 if (sc->rmap) printf(" sc->rmap(0x%08x)", (u_int32_t)sc->rmap);
2204 else printf(" sc->rmap(null)");
2205 if (sc->pmap) printf(" sc->pmap(0x%08x)", (u_int32_t)sc->pmap);
2206 else printf(" sc->pmap(null)");
2207 if (sc->rbuf) printf(" sc->rbuf(0x%08x)", (u_int32_t)sc->rbuf);
2208 else printf(" sc->rbuf(null)");
2209 if (sc->pbuf) printf(" sc->pbuf(0x%08x)\n", (u_int32_t)sc->pbuf);
2210 else printf(" sc->pbuf(null)\n");
2214 bus_dmamap_unload(sc->dmat, sc->rmap);
2216 bus_dmamap_unload(sc->dmat, sc->pmap);
2218 bus_dmamem_free(sc->dmat, sc->rbuf, sc->rmap);
2220 bus_dmamem_free(sc->dmat, sc->pbuf, sc->pmap);
2222 bus_dmamap_unload(sc->dmat, sc->rmap);
2223 bus_dmamap_unload(sc->dmat, sc->pmap);
2224 bus_dmamem_free(sc->dmat, sc->rbuf, sc->rmap);
2225 bus_dmamem_free(sc->dmat, sc->pbuf, sc->pmap);
2228 sc->rmap = sc->pmap = NULL;
2236 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->pmap = sc->rmap = NULL;
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 */
2276 addr = vtophys(sc->pbuf);
2278 device_printf(sc->dev, "pbuf(0x%08x)\n", addr);
2280 envy24_wrmt(sc, ENVY24_MT_PADDR, addr, 4);
2282 device_printf(sc->dev, "PADDR-->(0x%08x)\n", envy24_rdmt(sc, ENVY24_MT_PADDR, 4));
2283 device_printf(sc->dev, "psize(%ld)\n", sc->psize / 4 - 1);
2285 envy24_wrmt(sc, ENVY24_MT_PCNT, sc->psize / 4 - 1, 2);
2287 device_printf(sc->dev, "PCNT-->(%ld)\n", envy24_rdmt(sc, ENVY24_MT_PCNT, 2));
2289 addr = vtophys(sc->rbuf);
2290 envy24_wrmt(sc, ENVY24_MT_RADDR, addr, 4);
2291 envy24_wrmt(sc, ENVY24_MT_RCNT, sc->rsize / 4 - 1, 2);
2300 envy24_putcfg(struct sc_info *sc)
2302 device_printf(sc->dev, "system configuration\n");
2303 printf(" SubVendorID: 0x%04x, SubDeviceID: 0x%04x\n",
2304 sc->cfg->subvendor, sc->cfg->subdevice);
2305 printf(" XIN2 Clock Source: ");
2306 switch (sc->cfg->scfg & PCIM_SCFG_XIN2) {
2308 printf("22.5792MHz(44.1kHz*512)\n");
2311 printf("16.9344MHz(44.1kHz*384)\n");
2314 printf("from external clock synthesizer chip\n");
2317 printf("illeagal system setting\n");
2319 printf(" MPU-401 UART(s) #: ");
2320 if (sc->cfg->scfg & PCIM_SCFG_MPU)
2324 printf(" AC'97 codec: ");
2325 if (sc->cfg->scfg & PCIM_SCFG_AC97)
2326 printf("not exist\n");
2330 printf("%d\n", sc->adcn);
2332 printf("%d\n", sc->dacn);
2333 printf(" Multi-track converter type: ");
2334 if ((sc->cfg->acl & PCIM_ACL_MTC) == 0) {
2335 printf("AC'97(SDATA_OUT:");
2336 if (sc->cfg->acl & PCIM_ACL_OMODE)
2340 printf("|SDATA_IN:");
2341 if (sc->cfg->acl & PCIM_ACL_IMODE)
2349 if (sc->cfg->i2s & PCIM_I2S_VOL)
2350 printf("with volume, ");
2351 if (sc->cfg->i2s & PCIM_I2S_96KHZ)
2352 printf("96KHz support, ");
2353 switch (sc->cfg->i2s & PCIM_I2S_RES) {
2354 case PCIM_I2S_16BIT:
2355 printf("16bit resolution, ");
2357 case PCIM_I2S_18BIT:
2358 printf("18bit resolution, ");
2360 case PCIM_I2S_20BIT:
2361 printf("20bit resolution, ");
2363 case PCIM_I2S_24BIT:
2364 printf("24bit resolution, ");
2367 printf("ID#0x%x)\n", sc->cfg->i2s & PCIM_I2S_ID);
2369 printf(" S/PDIF(IN/OUT): ");
2370 if (sc->cfg->spdif & PCIM_SPDIF_IN)
2374 if (sc->cfg->spdif & PCIM_SPDIF_OUT)
2378 if (sc->cfg->spdif & (PCIM_SPDIF_IN | PCIM_SPDIF_OUT))
2379 printf("ID# 0x%02x\n", (sc->cfg->spdif & PCIM_SPDIF_ID) >> 2);
2380 printf(" GPIO(mask/dir/state): 0x%02x/0x%02x/0x%02x\n",
2381 sc->cfg->gpiomask, sc->cfg->gpiodir, sc->cfg->gpiostate);
2385 envy24_init(struct sc_info *sc)
2396 device_printf(sc->dev, "envy24_init()\n");
2400 envy24_wrcs(sc, ENVY24_CCS_CTL, ENVY24_CCS_CTL_RESET | ENVY24_CCS_CTL_NATIVE, 1);
2402 envy24_wrcs(sc, ENVY24_CCS_CTL, ENVY24_CCS_CTL_NATIVE, 1);
2405 /* legacy hardware disable */
2406 data = pci_read_config(sc->dev, PCIR_LAC, 2);
2407 data |= PCIM_LAC_DISABLE;
2408 pci_write_config(sc->dev, PCIR_LAC, data, 2);
2410 /* check system configuration */
2412 for (i = 0; cfg_table[i].subvendor != 0 || cfg_table[i].subdevice != 0; i++) {
2413 /* 1st: search configuration from table */
2414 sv = pci_get_subvendor(sc->dev);
2415 sd = pci_get_subdevice(sc->dev);
2416 if (sv == cfg_table[i].subvendor && sd == cfg_table[i].subdevice) {
2418 device_printf(sc->dev, "Set configuration from table\n");
2420 sc->cfg = &cfg_table[i];
2424 if (sc->cfg == NULL) {
2425 /* 2nd: read configuration from table */
2426 sc->cfg = envy24_rom2cfg(sc);
2428 sc->adcn = ((sc->cfg->scfg & PCIM_SCFG_ADC) >> 2) + 1;
2429 sc->dacn = (sc->cfg->scfg & PCIM_SCFG_DAC) + 1;
2431 if (1 /* bootverbose */) {
2435 /* set system configuration */
2436 pci_write_config(sc->dev, PCIR_SCFG, sc->cfg->scfg, 1);
2437 pci_write_config(sc->dev, PCIR_ACL, sc->cfg->acl, 1);
2438 pci_write_config(sc->dev, PCIR_I2S, sc->cfg->i2s, 1);
2439 pci_write_config(sc->dev, PCIR_SPDIF, sc->cfg->spdif, 1);
2440 envy24_gpiosetmask(sc, sc->cfg->gpiomask);
2441 envy24_gpiosetdir(sc, sc->cfg->gpiodir);
2442 envy24_gpiowr(sc, sc->cfg->gpiostate);
2443 for (i = 0; i < sc->adcn; i++) {
2444 sc->adc[i] = sc->cfg->codec->create(sc->dev, sc, PCMDIR_REC, i);
2445 sc->cfg->codec->init(sc->adc[i]);
2447 for (i = 0; i < sc->dacn; i++) {
2448 sc->dac[i] = sc->cfg->codec->create(sc->dev, sc, PCMDIR_PLAY, i);
2449 sc->cfg->codec->init(sc->dac[i]);
2452 /* initialize DMA buffer */
2454 device_printf(sc->dev, "envy24_init(): initialize DMA buffer\n");
2456 if (envy24_dmainit(sc))
2459 /* initialize status */
2460 sc->run[0] = sc->run[1] = 0;
2461 sc->intr[0] = sc->intr[1] = 0;
2463 sc->caps[0].fmtlist = envy24_playfmt;
2464 sc->caps[1].fmtlist = envy24_recfmt;
2466 /* set channel router */
2467 envy24_route(sc, ENVY24_ROUTE_DAC_1, ENVY24_ROUTE_CLASS_MIX, 0, 0);
2468 envy24_route(sc, ENVY24_ROUTE_DAC_SPDIF, ENVY24_ROUTE_CLASS_DMA, 0, 0);
2469 /* envy24_route(sc, ENVY24_ROUTE_DAC_SPDIF, ENVY24_ROUTE_CLASS_MIX, 0, 0); */
2471 /* set macro interrupt mask */
2472 data = envy24_rdcs(sc, ENVY24_CCS_IMASK, 1);
2473 envy24_wrcs(sc, ENVY24_CCS_IMASK, data & ~ENVY24_CCS_IMASK_PMT, 1);
2474 data = envy24_rdcs(sc, ENVY24_CCS_IMASK, 1);
2476 device_printf(sc->dev, "envy24_init(): CCS_IMASK-->0x%02x\n", data);
2483 envy24_alloc_resource(struct sc_info *sc)
2485 /* allocate I/O port resource */
2486 sc->csid = PCIR_CCS;
2487 sc->cs = bus_alloc_resource(sc->dev, SYS_RES_IOPORT,
2488 &sc->csid, 0, ~0, 1, RF_ACTIVE);
2489 sc->ddmaid = PCIR_DDMA;
2490 sc->ddma = bus_alloc_resource(sc->dev, SYS_RES_IOPORT,
2491 &sc->ddmaid, 0, ~0, 1, RF_ACTIVE);
2493 sc->ds = bus_alloc_resource(sc->dev, SYS_RES_IOPORT,
2494 &sc->dsid, 0, ~0, 1, RF_ACTIVE);
2496 sc->mt = bus_alloc_resource(sc->dev, SYS_RES_IOPORT,
2497 &sc->mtid, 0, ~0, 1, RF_ACTIVE);
2498 if (!sc->cs || !sc->ddma || !sc->ds || !sc->mt) {
2499 device_printf(sc->dev, "unable to map IO port space\n");
2502 sc->cst = rman_get_bustag(sc->cs);
2503 sc->csh = rman_get_bushandle(sc->cs);
2504 sc->ddmat = rman_get_bustag(sc->ddma);
2505 sc->ddmah = rman_get_bushandle(sc->ddma);
2506 sc->dst = rman_get_bustag(sc->ds);
2507 sc->dsh = rman_get_bushandle(sc->ds);
2508 sc->mtt = rman_get_bustag(sc->mt);
2509 sc->mth = rman_get_bushandle(sc->mt);
2511 device_printf(sc->dev,
2512 "IO port register values\nCCS: 0x%lx\nDDMA: 0x%lx\nDS: 0x%lx\nMT: 0x%lx\n",
2513 pci_read_config(sc->dev, PCIR_CCS, 4),
2514 pci_read_config(sc->dev, PCIR_DDMA, 4),
2515 pci_read_config(sc->dev, PCIR_DS, 4),
2516 pci_read_config(sc->dev, PCIR_MT, 4));
2519 /* allocate interrupt resource */
2521 sc->irq = bus_alloc_resource(sc->dev, SYS_RES_IRQ, &sc->irqid,
2522 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE);
2524 snd_setup_intr(sc->dev, sc->irq, INTR_MPSAFE, envy24_intr, sc, &sc->ih)) {
2525 device_printf(sc->dev, "unable to map interrupt\n");
2529 /* allocate DMA resource */
2530 if (bus_dma_tag_create(/*parent*/bus_get_dma_tag(sc->dev),
2533 /*lowaddr*/BUS_SPACE_MAXADDR_ENVY24,
2534 /*highaddr*/BUS_SPACE_MAXADDR_ENVY24,
2535 /*filter*/NULL, /*filterarg*/NULL,
2536 /*maxsize*/BUS_SPACE_MAXSIZE_ENVY24,
2537 /*nsegments*/1, /*maxsegsz*/0x3ffff,
2538 /*flags*/0, /*lockfunc*/busdma_lock_mutex,
2539 /*lockarg*/&Giant, &sc->dmat) != 0) {
2540 device_printf(sc->dev, "unable to create dma tag\n");
2548 envy24_pci_attach(device_t dev)
2551 char status[SND_STATUSLEN];
2556 device_printf(dev, "envy24_pci_attach()\n");
2558 /* get sc_info data area */
2559 if ((sc = malloc(sizeof(*sc), M_ENVY24, M_NOWAIT)) == NULL) {
2560 device_printf(dev, "cannot allocate softc\n");
2564 bzero(sc, sizeof(*sc));
2565 sc->lock = snd_mtxcreate(device_get_nameunit(dev), "snd_envy24 softc");
2568 /* initialize PCI interface */
2569 pci_enable_busmaster(dev);
2571 /* allocate resources */
2572 err = envy24_alloc_resource(sc);
2574 device_printf(dev, "unable to allocate system resources\n");
2578 /* initialize card */
2579 err = envy24_init(sc);
2581 device_printf(dev, "unable to initialize the card\n");
2585 /* set multi track mixer */
2586 mixer_init(dev, &envy24mixer_class, sc);
2588 /* set channel information */
2589 err = pcm_register(dev, sc, 5, 2 + sc->adcn);
2593 for (i = 0; i < 5; i++) {
2594 pcm_addchan(dev, PCMDIR_PLAY, &envy24chan_class, sc);
2597 for (i = 0; i < 2 + sc->adcn; i++) {
2598 pcm_addchan(dev, PCMDIR_REC, &envy24chan_class, sc);
2602 /* set status iformation */
2603 snprintf(status, SND_STATUSLEN,
2604 "at io 0x%lx:%ld,0x%lx:%ld,0x%lx:%ld,0x%lx:%ld irq %ld",
2605 rman_get_start(sc->cs),
2606 rman_get_end(sc->cs) - rman_get_start(sc->cs) + 1,
2607 rman_get_start(sc->ddma),
2608 rman_get_end(sc->ddma) - rman_get_start(sc->ddma) + 1,
2609 rman_get_start(sc->ds),
2610 rman_get_end(sc->ds) - rman_get_start(sc->ds) + 1,
2611 rman_get_start(sc->mt),
2612 rman_get_end(sc->mt) - rman_get_start(sc->mt) + 1,
2613 rman_get_start(sc->irq));
2614 pcm_setstatus(dev, status);
2620 bus_teardown_intr(dev, sc->irq, sc->ih);
2622 bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq);
2625 bus_dma_tag_destroy(sc->dmat);
2626 if (sc->cfg->codec->destroy != NULL) {
2627 for (i = 0; i < sc->adcn; i++)
2628 sc->cfg->codec->destroy(sc->adc[i]);
2629 for (i = 0; i < sc->dacn; i++)
2630 sc->cfg->codec->destroy(sc->dac[i]);
2632 envy24_cfgfree(sc->cfg);
2634 bus_release_resource(dev, SYS_RES_IOPORT, sc->csid, sc->cs);
2636 bus_release_resource(dev, SYS_RES_IOPORT, sc->ddmaid, sc->ddma);
2638 bus_release_resource(dev, SYS_RES_IOPORT, sc->dsid, sc->ds);
2640 bus_release_resource(dev, SYS_RES_IOPORT, sc->mtid, sc->mt);
2642 snd_mtxfree(sc->lock);
2648 envy24_pci_detach(device_t dev)
2655 device_printf(dev, "envy24_pci_detach()\n");
2657 sc = pcm_getdevinfo(dev);
2660 r = pcm_unregister(dev);
2665 if (sc->cfg->codec->destroy != NULL) {
2666 for (i = 0; i < sc->adcn; i++)
2667 sc->cfg->codec->destroy(sc->adc[i]);
2668 for (i = 0; i < sc->dacn; i++)
2669 sc->cfg->codec->destroy(sc->dac[i]);
2671 envy24_cfgfree(sc->cfg);
2672 bus_dma_tag_destroy(sc->dmat);
2673 bus_teardown_intr(dev, sc->irq, sc->ih);
2674 bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq);
2675 bus_release_resource(dev, SYS_RES_IOPORT, sc->csid, sc->cs);
2676 bus_release_resource(dev, SYS_RES_IOPORT, sc->ddmaid, sc->ddma);
2677 bus_release_resource(dev, SYS_RES_IOPORT, sc->dsid, sc->ds);
2678 bus_release_resource(dev, SYS_RES_IOPORT, sc->mtid, sc->mt);
2679 snd_mtxfree(sc->lock);
2684 static device_method_t envy24_methods[] = {
2685 /* Device interface */
2686 DEVMETHOD(device_probe, envy24_pci_probe),
2687 DEVMETHOD(device_attach, envy24_pci_attach),
2688 DEVMETHOD(device_detach, envy24_pci_detach),
2692 static driver_t envy24_driver = {
2695 #if __FreeBSD_version > 500000
2698 sizeof(struct snddev_info),
2702 DRIVER_MODULE(snd_envy24, pci, envy24_driver, pcm_devclass, 0, 0);
2703 MODULE_DEPEND(snd_envy24, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER);
2704 MODULE_DEPEND(snd_envy24, snd_spicds, 1, 1, 1);
2705 MODULE_VERSION(snd_envy24, 1);