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 THEPOSSIBILITY OF
26 * $FreeBSD: src/sys/dev/sound/pci/envy24.c,v 1.11.2.2 2007/06/11 19:33:27 ariff Exp $
27 * $DragonFly: src/sys/dev/sound/pci/envy24.c,v 1.3 2008/01/05 14:02:38 swildner Exp $
30 #include <dev/sound/pcm/sound.h>
31 #include <dev/sound/pcm/ac97.h>
32 #include <dev/sound/pci/spicds.h>
33 #include <dev/sound/pci/envy24.h>
35 #include <bus/pci/pcireg.h>
36 #include <bus/pci/pcivar.h>
40 SND_DECLARE_FILE("$DragonFly: src/sys/dev/sound/pci/envy24.c,v 1.3 2008/01/05 14:02:38 swildner Exp $");
42 MALLOC_DEFINE(M_ENVY24, "envy24", "envy24 audio");
44 /* -------------------------------------------------------------------- */
48 #define ENVY24_PLAY_CHNUM 10
49 #define ENVY24_REC_CHNUM 12
50 #define ENVY24_PLAY_BUFUNIT (4 /* byte/sample */ * 10 /* channel */)
51 #define ENVY24_REC_BUFUNIT (4 /* byte/sample */ * 12 /* channel */)
52 #define ENVY24_SAMPLE_NUM 4096
54 #define ENVY24_TIMEOUT 1000
56 #define ENVY24_DEFAULT_FORMAT (AFMT_STEREO | AFMT_S16_LE)
58 #define ENVY24_NAMELEN 32
63 #define abs(i) (i < 0 ? -i : i)
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 int envy24chan_setspeed(kobj_t, void *, u_int32_t);
195 static int envy24chan_setblocksize(kobj_t, void *, u_int32_t);
196 static int envy24chan_trigger(kobj_t, void *, int);
197 static int 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 (Generic)",
311 0x0f, 0x00, 0x01, 0x03,
313 0x10, 0x20, 0x40, 0x00, 0x00,
315 &delta_codec, /* default codec routines */
319 static u_int32_t envy24_recfmt[] = {
320 AFMT_STEREO | AFMT_S16_LE,
321 AFMT_STEREO | AFMT_S32_LE,
324 static struct pcmchan_caps envy24_reccaps = {8000, 96000, envy24_recfmt, 0};
326 static u_int32_t envy24_playfmt[] = {
327 AFMT_STEREO | AFMT_U8,
328 AFMT_STEREO | AFMT_S16_LE,
329 AFMT_STEREO | AFMT_S32_LE,
333 static struct pcmchan_caps envy24_playcaps = {8000, 96000, envy24_playfmt, 0};
335 struct envy24_emldma {
337 void (*emldma)(struct sc_chinfo *);
341 static struct envy24_emldma envy24_pemltab[] = {
342 {AFMT_STEREO | AFMT_U8, envy24_p8u, 2},
343 {AFMT_STEREO | AFMT_S16_LE, envy24_p16sl, 4},
344 {AFMT_STEREO | AFMT_S32_LE, envy24_p32sl, 8},
348 static struct envy24_emldma envy24_remltab[] = {
349 {AFMT_STEREO | AFMT_S16_LE, envy24_r16sl, 4},
350 {AFMT_STEREO | AFMT_S32_LE, envy24_r32sl, 8},
354 /* -------------------------------------------------------------------- */
356 /* common routines */
358 envy24_rdcs(struct sc_info *sc, int regno, int size)
362 return bus_space_read_1(sc->cst, sc->csh, regno);
364 return bus_space_read_2(sc->cst, sc->csh, regno);
366 return bus_space_read_4(sc->cst, sc->csh, regno);
373 envy24_wrcs(struct sc_info *sc, int regno, u_int32_t data, int size)
377 bus_space_write_1(sc->cst, sc->csh, regno, data);
380 bus_space_write_2(sc->cst, sc->csh, regno, data);
383 bus_space_write_4(sc->cst, sc->csh, regno, data);
389 envy24_rdmt(struct sc_info *sc, int regno, int size)
393 return bus_space_read_1(sc->mtt, sc->mth, regno);
395 return bus_space_read_2(sc->mtt, sc->mth, regno);
397 return bus_space_read_4(sc->mtt, sc->mth, regno);
404 envy24_wrmt(struct sc_info *sc, int regno, u_int32_t data, int size)
408 bus_space_write_1(sc->mtt, sc->mth, regno, data);
411 bus_space_write_2(sc->mtt, sc->mth, regno, data);
414 bus_space_write_4(sc->mtt, sc->mth, regno, data);
420 envy24_rdci(struct sc_info *sc, int regno)
422 envy24_wrcs(sc, ENVY24_CCS_INDEX, regno, 1);
423 return envy24_rdcs(sc, ENVY24_CCS_DATA, 1);
427 envy24_wrci(struct sc_info *sc, int regno, u_int32_t data)
429 envy24_wrcs(sc, ENVY24_CCS_INDEX, regno, 1);
430 envy24_wrcs(sc, ENVY24_CCS_DATA, data, 1);
433 /* -------------------------------------------------------------------- */
435 /* I2C port/E2PROM access routines */
438 envy24_rdi2c(struct sc_info *sc, u_int32_t dev, u_int32_t addr)
444 device_printf(sc->dev, "envy24_rdi2c(sc, 0x%02x, 0x%02x)\n", dev, addr);
446 for (i = 0; i < ENVY24_TIMEOUT; i++) {
447 data = envy24_rdcs(sc, ENVY24_CCS_I2CSTAT, 1);
448 if ((data & ENVY24_CCS_I2CSTAT_BSY) == 0)
450 DELAY(32); /* 31.25kHz */
452 if (i == ENVY24_TIMEOUT) {
455 envy24_wrcs(sc, ENVY24_CCS_I2CADDR, addr, 1);
456 envy24_wrcs(sc, ENVY24_CCS_I2CDEV,
457 (dev & ENVY24_CCS_I2CDEV_ADDR) | ENVY24_CCS_I2CDEV_RD, 1);
458 for (i = 0; i < ENVY24_TIMEOUT; i++) {
459 data = envy24_rdcs(sc, ENVY24_CCS_I2CSTAT, 1);
460 if ((data & ENVY24_CCS_I2CSTAT_BSY) == 0)
462 DELAY(32); /* 31.25kHz */
464 if (i == ENVY24_TIMEOUT) {
467 data = envy24_rdcs(sc, ENVY24_CCS_I2CDATA, 1);
470 device_printf(sc->dev, "envy24_rdi2c(): return 0x%x\n", data);
477 envy24_wri2c(struct sc_info *sc, u_int32_t dev, u_int32_t addr, u_int32_t data)
483 device_printf(sc->dev, "envy24_rdi2c(sc, 0x%02x, 0x%02x)\n", dev, addr);
485 for (i = 0; i < ENVY24_TIMEOUT; i++) {
486 tmp = envy24_rdcs(sc, ENVY24_CCS_I2CSTAT, 1);
487 if ((tmp & ENVY24_CCS_I2CSTAT_BSY) == 0)
489 DELAY(32); /* 31.25kHz */
491 if (i == ENVY24_TIMEOUT) {
494 envy24_wrcs(sc, ENVY24_CCS_I2CADDR, addr, 1);
495 envy24_wrcs(sc, ENVY24_CCS_I2CDATA, data, 1);
496 envy24_wrcs(sc, ENVY24_CCS_I2CDEV,
497 (dev & ENVY24_CCS_I2CDEV_ADDR) | ENVY24_CCS_I2CDEV_WR, 1);
498 for (i = 0; i < ENVY24_TIMEOUT; i++) {
499 data = envy24_rdcs(sc, ENVY24_CCS_I2CSTAT, 1);
500 if ((data & ENVY24_CCS_I2CSTAT_BSY) == 0)
502 DELAY(32); /* 31.25kHz */
504 if (i == ENVY24_TIMEOUT) {
513 envy24_rdrom(struct sc_info *sc, u_int32_t addr)
518 device_printf(sc->dev, "envy24_rdrom(sc, 0x%02x)\n", addr);
520 data = envy24_rdcs(sc, ENVY24_CCS_I2CSTAT, 1);
521 if ((data & ENVY24_CCS_I2CSTAT_ROM) == 0) {
523 device_printf(sc->dev, "envy24_rdrom(): E2PROM not presented\n");
528 return envy24_rdi2c(sc, ENVY24_CCS_I2CDEV_ROM, addr);
531 static struct cfg_info *
532 envy24_rom2cfg(struct sc_info *sc)
534 struct cfg_info *buff;
539 device_printf(sc->dev, "envy24_rom2cfg(sc)\n");
541 size = envy24_rdrom(sc, ENVY24_E2PROM_SIZE);
542 if (size < ENVY24_E2PROM_GPIODIR + 1) {
544 device_printf(sc->dev, "envy24_rom2cfg(): ENVY24_E2PROM_SIZE-->%d\n", size);
548 buff = kmalloc(sizeof(*buff), M_ENVY24, M_WAITOK);
551 buff->subvendor = envy24_rdrom(sc, ENVY24_E2PROM_SUBVENDOR) << 8;
552 buff->subvendor += envy24_rdrom(sc, ENVY24_E2PROM_SUBVENDOR + 1);
553 buff->subdevice = envy24_rdrom(sc, ENVY24_E2PROM_SUBDEVICE) << 8;
554 buff->subdevice += envy24_rdrom(sc, ENVY24_E2PROM_SUBDEVICE + 1);
555 buff->scfg = envy24_rdrom(sc, ENVY24_E2PROM_SCFG);
556 buff->acl = envy24_rdrom(sc, ENVY24_E2PROM_ACL);
557 buff->i2s = envy24_rdrom(sc, ENVY24_E2PROM_I2S);
558 buff->spdif = envy24_rdrom(sc, ENVY24_E2PROM_SPDIF);
559 buff->gpiomask = envy24_rdrom(sc, ENVY24_E2PROM_GPIOMASK);
560 buff->gpiostate = envy24_rdrom(sc, ENVY24_E2PROM_GPIOSTATE);
561 buff->gpiodir = envy24_rdrom(sc, ENVY24_E2PROM_GPIODIR);
563 for (i = 0; cfg_table[i].subvendor != 0 || cfg_table[i].subdevice != 0; i++)
564 if (cfg_table[i].subvendor == buff->subvendor &&
565 cfg_table[i].subdevice == buff->subdevice)
567 buff->name = cfg_table[i].name;
568 buff->codec = cfg_table[i].codec;
574 envy24_cfgfree(struct cfg_info *cfg) {
578 kfree(cfg, M_ENVY24);
582 /* -------------------------------------------------------------------- */
584 /* AC'97 codec access routines */
588 envy24_coldcd(struct sc_info *sc)
594 device_printf(sc->dev, "envy24_coldcd()\n");
596 envy24_wrmt(sc, ENVY24_MT_AC97CMD, ENVY24_MT_AC97CMD_CLD, 1);
598 envy24_wrmt(sc, ENVY24_MT_AC97CMD, 0, 1);
600 for (i = 0; i < ENVY24_TIMEOUT; i++) {
601 data = envy24_rdmt(sc, ENVY24_MT_AC97CMD, 1);
602 if (data & ENVY24_MT_AC97CMD_RDY) {
612 envy24_slavecd(struct sc_info *sc)
618 device_printf(sc->dev, "envy24_slavecd()\n");
620 envy24_wrmt(sc, ENVY24_MT_AC97CMD,
621 ENVY24_MT_AC97CMD_CLD | ENVY24_MT_AC97CMD_WRM, 1);
623 envy24_wrmt(sc, ENVY24_MT_AC97CMD, 0, 1);
625 for (i = 0; i < ENVY24_TIMEOUT; i++) {
626 data = envy24_rdmt(sc, ENVY24_MT_AC97CMD, 1);
627 if (data & ENVY24_MT_AC97CMD_RDY) {
637 envy24_rdcd(kobj_t obj, void *devinfo, int regno)
639 struct sc_info *sc = (struct sc_info *)devinfo;
644 device_printf(sc->dev, "envy24_rdcd(obj, sc, 0x%02x)\n", regno);
646 envy24_wrmt(sc, ENVY24_MT_AC97IDX, (u_int32_t)regno, 1);
647 envy24_wrmt(sc, ENVY24_MT_AC97CMD, ENVY24_MT_AC97CMD_RD, 1);
648 for (i = 0; i < ENVY24_TIMEOUT; i++) {
649 data = envy24_rdmt(sc, ENVY24_MT_AC97CMD, 1);
650 if ((data & ENVY24_MT_AC97CMD_RD) == 0)
653 data = envy24_rdmt(sc, ENVY24_MT_AC97DLO, 2);
656 device_printf(sc->dev, "envy24_rdcd(): return 0x%x\n", data);
662 envy24_wrcd(kobj_t obj, void *devinfo, int regno, u_int16_t data)
664 struct sc_info *sc = (struct sc_info *)devinfo;
669 device_printf(sc->dev, "envy24_wrcd(obj, sc, 0x%02x, 0x%04x)\n", regno, data);
671 envy24_wrmt(sc, ENVY24_MT_AC97IDX, (u_int32_t)regno, 1);
672 envy24_wrmt(sc, ENVY24_MT_AC97DLO, (u_int32_t)data, 2);
673 envy24_wrmt(sc, ENVY24_MT_AC97CMD, ENVY24_MT_AC97CMD_WR, 1);
674 for (i = 0; i < ENVY24_TIMEOUT; i++) {
675 cmd = envy24_rdmt(sc, ENVY24_MT_AC97CMD, 1);
676 if ((cmd & ENVY24_MT_AC97CMD_WR) == 0)
683 static kobj_method_t envy24_ac97_methods[] = {
684 KOBJMETHOD(ac97_read, envy24_rdcd),
685 KOBJMETHOD(ac97_write, envy24_wrcd),
688 AC97_DECLARE(envy24_ac97);
691 /* -------------------------------------------------------------------- */
693 /* GPIO access routines */
696 envy24_gpiord(struct sc_info *sc)
698 return envy24_rdci(sc, ENVY24_CCI_GPIODAT);
702 envy24_gpiowr(struct sc_info *sc, u_int32_t data)
705 device_printf(sc->dev, "envy24_gpiowr(sc, 0x%02x)\n", data & 0xff);
708 envy24_wrci(sc, ENVY24_CCI_GPIODAT, data);
714 envy24_gpiogetmask(struct sc_info *sc)
716 return envy24_rdci(sc, ENVY24_CCI_GPIOMASK);
721 envy24_gpiosetmask(struct sc_info *sc, u_int32_t mask)
723 envy24_wrci(sc, ENVY24_CCI_GPIOMASK, mask);
729 envy24_gpiogetdir(struct sc_info *sc)
731 return envy24_rdci(sc, ENVY24_CCI_GPIOCTL);
736 envy24_gpiosetdir(struct sc_info *sc, u_int32_t dir)
738 envy24_wrci(sc, ENVY24_CCI_GPIOCTL, dir);
742 /* -------------------------------------------------------------------- */
744 /* Envy24 I2C through GPIO bit-banging */
746 struct envy24_delta_ak4524_codec {
747 struct spicds_info *info;
748 struct sc_info *parent;
755 envy24_gpio_i2c_ctl(void *codec, unsigned int scl, unsigned int sda)
758 struct envy24_delta_ak4524_codec *ptr = codec;
760 device_printf(ptr->parent->dev, "--> %d, %d\n", scl, sda);
762 data = envy24_gpiord(ptr->parent);
763 data &= ~(SDA_GPIO | SCL_GPIO);
764 if (scl) data += SCL_GPIO;
765 if (sda) data += SDA_GPIO;
766 envy24_gpiowr(ptr->parent, data);
771 i2c_wrbit(void *codec, void (*ctrl)(void*, unsigned int, unsigned int), int bit)
773 struct envy24_delta_ak4524_codec *ptr = codec;
790 i2c_start(void *codec, void (*ctrl)(void*, unsigned int, unsigned int))
792 struct envy24_delta_ak4524_codec *ptr = codec;
803 i2c_stop(void *codec, void (*ctrl)(void*, unsigned int, unsigned int))
805 struct envy24_delta_ak4524_codec *ptr = codec;
816 i2c_ack(void *codec, void (*ctrl)(void*, unsigned int, unsigned int))
818 struct envy24_delta_ak4524_codec *ptr = codec;
824 /* dummy, need routine to change gpio direction */
830 i2c_wr(void *codec, void (*ctrl)(void*, unsigned int, unsigned int), u_int32_t dev, int reg, u_int8_t val)
832 struct envy24_delta_ak4524_codec *ptr = codec;
835 i2c_start(ptr, ctrl);
837 for (mask = 0x80; mask != 0; mask >>= 1)
838 i2c_wrbit(ptr, ctrl, dev & mask);
842 for (mask = 0x80; mask != 0; mask >>= 1)
843 i2c_wrbit(ptr, ctrl, reg & mask);
847 for (mask = 0x80; mask != 0; mask >>= 1)
848 i2c_wrbit(ptr, ctrl, val & mask);
854 /* -------------------------------------------------------------------- */
856 /* M-Audio Delta series AK4524 access interface routine */
859 envy24_delta_ak4524_ctl(void *codec, unsigned int cs, unsigned int cclk, unsigned int cdti)
862 struct envy24_delta_ak4524_codec *ptr = codec;
865 device_printf(ptr->parent->dev, "--> %d, %d, %d\n", cs, cclk, cdti);
867 data = envy24_gpiord(ptr->parent);
868 data &= ~(ptr->cs | ptr->cclk | ptr->cdti);
869 if (cs) data += ptr->cs;
870 if (cclk) data += ptr->cclk;
871 if (cdti) data += ptr->cdti;
872 envy24_gpiowr(ptr->parent, data);
877 envy24_delta_ak4524_create(device_t dev, void *info, int dir, int num)
879 struct sc_info *sc = info;
880 struct envy24_delta_ak4524_codec *buff = NULL;
883 device_printf(sc->dev, "envy24_delta_ak4524_create(dev, sc, %d, %d)\n", dir, num);
886 buff = kmalloc(sizeof(*buff), M_ENVY24, M_WAITOK);
888 if (dir == PCMDIR_REC && sc->adc[num] != NULL)
889 buff->info = ((struct envy24_delta_ak4524_codec *)sc->adc[num])->info;
890 else if (dir == PCMDIR_PLAY && sc->dac[num] != NULL)
891 buff->info = ((struct envy24_delta_ak4524_codec *)sc->dac[num])->info;
893 buff->info = spicds_create(dev, buff, num, envy24_delta_ak4524_ctl);
894 if (buff->info == NULL) {
895 kfree(buff, M_ENVY24);
907 envy24_delta_ak4524_destroy(void *codec)
909 struct envy24_delta_ak4524_codec *ptr = codec;
913 device_printf(ptr->parent->dev, "envy24_delta_ak4524_destroy()\n");
916 if (ptr->dir == PCMDIR_PLAY) {
917 if (ptr->parent->dac[ptr->num] != NULL)
918 spicds_destroy(ptr->info);
921 if (ptr->parent->adc[ptr->num] != NULL)
922 spicds_destroy(ptr->info);
925 kfree(codec, M_ENVY24);
929 envy24_delta_ak4524_init(void *codec)
932 u_int32_t gpiomask, gpiodir;
934 struct envy24_delta_ak4524_codec *ptr = codec;
938 device_printf(ptr->parent->dev, "envy24_delta_ak4524_init()\n");
942 gpiomask = envy24_gpiogetmask(ptr->parent);
943 gpiomask &= ~(ENVY24_GPIO_AK4524_CDTI | ENVY24_GPIO_AK4524_CCLK | ENVY24_GPIO_AK4524_CS0 | ENVY24_GPIO_AK4524_CS1);
944 envy24_gpiosetmask(ptr->parent, gpiomask);
945 gpiodir = envy24_gpiogetdir(ptr->parent);
946 gpiodir |= ENVY24_GPIO_AK4524_CDTI | ENVY24_GPIO_AK4524_CCLK | ENVY24_GPIO_AK4524_CS0 | ENVY24_GPIO_AK4524_CS1;
947 envy24_gpiosetdir(ptr->parent, gpiodir);
949 ptr->cs = ptr->parent->cfg->cs;
951 envy24_gpiosetmask(ptr->parent, ENVY24_GPIO_CS8414_STATUS);
952 envy24_gpiosetdir(ptr->parent, ~ENVY24_GPIO_CS8414_STATUS);
954 ptr->cs = ENVY24_GPIO_AK4524_CS0;
956 ptr->cs = ENVY24_GPIO_AK4524_CS1;
957 ptr->cclk = ENVY24_GPIO_AK4524_CCLK;
959 ptr->cclk = ptr->parent->cfg->cclk;
960 ptr->cdti = ptr->parent->cfg->cdti;
961 spicds_settype(ptr->info, ptr->parent->cfg->type);
962 spicds_setcif(ptr->info, ptr->parent->cfg->cif);
963 spicds_setformat(ptr->info,
964 AK452X_FORMAT_I2S | AK452X_FORMAT_256FSN | AK452X_FORMAT_1X);
965 spicds_setdvc(ptr->info, AK452X_DVC_DEMOFF);
966 /* for the time being, init only first codec */
968 spicds_init(ptr->info);
970 /* 6fire rear input init test, set ptr->num to 1 for test */
971 if (ptr->parent->cfg->subvendor == 0x153b && \
972 ptr->parent->cfg->subdevice == 0x1138 && ptr->num == 100) {
974 spicds_init(ptr->info);
975 device_printf(ptr->parent->dev, "6fire rear input init\n");
976 i2c_wr(ptr, envy24_gpio_i2c_ctl, \
977 PCA9554_I2CDEV, PCA9554_DIR, 0x80);
978 i2c_wr(ptr, envy24_gpio_i2c_ctl, \
979 PCA9554_I2CDEV, PCA9554_OUT, 0x02);
984 envy24_delta_ak4524_reinit(void *codec)
986 struct envy24_delta_ak4524_codec *ptr = codec;
990 device_printf(ptr->parent->dev, "envy24_delta_ak4524_reinit()\n");
993 spicds_reinit(ptr->info);
997 envy24_delta_ak4524_setvolume(void *codec, int dir, unsigned int left, unsigned int right)
999 struct envy24_delta_ak4524_codec *ptr = codec;
1003 device_printf(ptr->parent->dev, "envy24_delta_ak4524_set()\n");
1006 spicds_set(ptr->info, dir, left, right);
1010 There is no need for AK452[48] codec to set sample rate
1012 envy24_delta_ak4524_setrate(struct envy24_delta_ak4524_codec *codec, int which, int rate)
1017 /* -------------------------------------------------------------------- */
1019 /* hardware access routeines */
1024 } envy24_speedtab[] = {
1025 {48000, ENVY24_MT_RATE_48000},
1026 {24000, ENVY24_MT_RATE_24000},
1027 {12000, ENVY24_MT_RATE_12000},
1028 {9600, ENVY24_MT_RATE_9600},
1029 {32000, ENVY24_MT_RATE_32000},
1030 {16000, ENVY24_MT_RATE_16000},
1031 {8000, ENVY24_MT_RATE_8000},
1032 {96000, ENVY24_MT_RATE_96000},
1033 {64000, ENVY24_MT_RATE_64000},
1034 {44100, ENVY24_MT_RATE_44100},
1035 {22050, ENVY24_MT_RATE_22050},
1036 {11025, ENVY24_MT_RATE_11025},
1037 {88200, ENVY24_MT_RATE_88200},
1042 envy24_setspeed(struct sc_info *sc, u_int32_t speed) {
1047 device_printf(sc->dev, "envy24_setspeed(sc, %d)\n", speed);
1050 code = ENVY24_MT_RATE_SPDIF; /* external master clock */
1054 for (i = 0; envy24_speedtab[i].speed != 0; i++) {
1055 if (envy24_speedtab[i].speed == speed)
1058 code = envy24_speedtab[i].code;
1061 device_printf(sc->dev, "envy24_setspeed(): speed %d/code 0x%04x\n", envy24_speedtab[i].speed, code);
1064 envy24_wrmt(sc, ENVY24_MT_RATE, code, 1);
1065 code = envy24_rdmt(sc, ENVY24_MT_RATE, 1);
1066 code &= ENVY24_MT_RATE_MASK;
1067 for (i = 0; envy24_speedtab[i].code < 0x10; i++) {
1068 if (envy24_speedtab[i].code == code)
1071 speed = envy24_speedtab[i].speed;
1077 device_printf(sc->dev, "envy24_setspeed(): return %d\n", speed);
1083 envy24_setvolume(struct sc_info *sc, unsigned ch)
1086 device_printf(sc->dev, "envy24_setvolume(sc, %d)\n", ch);
1088 if (sc->cfg->subvendor==0x153b && sc->cfg->subdevice==0x1138 ) {
1089 envy24_wrmt(sc, ENVY24_MT_VOLIDX, 16, 1);
1090 envy24_wrmt(sc, ENVY24_MT_VOLUME, 0x7f7f, 2);
1091 envy24_wrmt(sc, ENVY24_MT_VOLIDX, 17, 1);
1092 envy24_wrmt(sc, ENVY24_MT_VOLUME, 0x7f7f, 2);
1095 envy24_wrmt(sc, ENVY24_MT_VOLIDX, ch * 2, 1);
1096 envy24_wrmt(sc, ENVY24_MT_VOLUME, 0x7f00 | sc->left[ch], 2);
1097 envy24_wrmt(sc, ENVY24_MT_VOLIDX, ch * 2 + 1, 1);
1098 envy24_wrmt(sc, ENVY24_MT_VOLUME, (sc->right[ch] << 8) | 0x7f, 2);
1102 envy24_mutevolume(struct sc_info *sc, unsigned ch)
1107 device_printf(sc->dev, "envy24_mutevolume(sc, %d)\n", ch);
1109 vol = ENVY24_VOL_MUTE << 8 | ENVY24_VOL_MUTE;
1110 envy24_wrmt(sc, ENVY24_MT_VOLIDX, ch * 2, 1);
1111 envy24_wrmt(sc, ENVY24_MT_VOLUME, vol, 2);
1112 envy24_wrmt(sc, ENVY24_MT_VOLIDX, ch * 2 + 1, 1);
1113 envy24_wrmt(sc, ENVY24_MT_VOLUME, vol, 2);
1117 envy24_gethwptr(struct sc_info *sc, int dir)
1123 device_printf(sc->dev, "envy24_gethwptr(sc, %d)\n", dir);
1125 if (dir == PCMDIR_PLAY) {
1126 rtn = sc->psize / 4;
1127 unit = ENVY24_PLAY_BUFUNIT / 4;
1128 regno = ENVY24_MT_PCNT;
1131 rtn = sc->rsize / 4;
1132 unit = ENVY24_REC_BUFUNIT / 4;
1133 regno = ENVY24_MT_RCNT;
1136 ptr = envy24_rdmt(sc, regno, 2);
1141 device_printf(sc->dev, "envy24_gethwptr(): return %d\n", rtn);
1147 envy24_updintr(struct sc_info *sc, int dir)
1149 int regptr, regintr;
1150 u_int32_t mask, intr;
1151 u_int32_t ptr, size, cnt;
1155 device_printf(sc->dev, "envy24_updintr(sc, %d)\n", dir);
1157 if (dir == PCMDIR_PLAY) {
1159 size = sc->psize / 4;
1160 regptr = ENVY24_MT_PCNT;
1161 regintr = ENVY24_MT_PTERM;
1162 mask = ~ENVY24_MT_INT_PMASK;
1166 size = sc->rsize / 4;
1167 regptr = ENVY24_MT_RCNT;
1168 regintr = ENVY24_MT_RTERM;
1169 mask = ~ENVY24_MT_INT_RMASK;
1172 ptr = size - envy24_rdmt(sc, regptr, 2) - 1;
1174 cnt = blk - ptr % blk - 1;
1180 device_printf(sc->dev, "envy24_updintr():ptr = %d, blk = %d, cnt = %d\n", ptr, blk, cnt);
1182 envy24_wrmt(sc, regintr, cnt, 2);
1183 intr = envy24_rdmt(sc, ENVY24_MT_INT, 1);
1185 device_printf(sc->dev, "envy24_updintr():intr = 0x%02x, mask = 0x%02x\n", intr, mask);
1187 envy24_wrmt(sc, ENVY24_MT_INT, intr & mask, 1);
1189 device_printf(sc->dev, "envy24_updintr():INT-->0x%02x\n",
1190 envy24_rdmt(sc, ENVY24_MT_INT, 1));
1198 envy24_maskintr(struct sc_info *sc, int dir)
1200 u_int32_t mask, intr;
1203 device_printf(sc->dev, "envy24_maskintr(sc, %d)\n", dir);
1205 if (dir == PCMDIR_PLAY)
1206 mask = ENVY24_MT_INT_PMASK;
1208 mask = ENVY24_MT_INT_RMASK;
1209 intr = envy24_rdmt(sc, ENVY24_MT_INT, 1);
1210 envy24_wrmt(sc, ENVY24_MT_INT, intr | mask, 1);
1217 envy24_checkintr(struct sc_info *sc, int dir)
1219 u_int32_t mask, stat, intr, rtn;
1222 device_printf(sc->dev, "envy24_checkintr(sc, %d)\n", dir);
1224 intr = envy24_rdmt(sc, ENVY24_MT_INT, 1);
1225 if (dir == PCMDIR_PLAY) {
1226 if ((rtn = intr & ENVY24_MT_INT_PSTAT) != 0) {
1227 mask = ~ENVY24_MT_INT_RSTAT;
1228 stat = ENVY24_MT_INT_PSTAT | ENVY24_MT_INT_PMASK;
1229 envy24_wrmt(sc, ENVY24_MT_INT, (intr & mask) | stat, 1);
1233 if ((rtn = intr & ENVY24_MT_INT_RSTAT) != 0) {
1234 mask = ~ENVY24_MT_INT_PSTAT;
1235 stat = ENVY24_MT_INT_RSTAT | ENVY24_MT_INT_RMASK;
1236 envy24_wrmt(sc, ENVY24_MT_INT, (intr & mask) | stat, 1);
1244 envy24_start(struct sc_info *sc, int dir)
1249 device_printf(sc->dev, "envy24_start(sc, %d)\n", dir);
1251 if (dir == PCMDIR_PLAY)
1252 sw = ENVY24_MT_PCTL_PSTART;
1254 sw = ENVY24_MT_PCTL_RSTART;
1256 stat = envy24_rdmt(sc, ENVY24_MT_PCTL, 1);
1257 envy24_wrmt(sc, ENVY24_MT_PCTL, stat | sw, 1);
1260 device_printf(sc->dev, "PADDR:0x%08x\n", envy24_rdmt(sc, ENVY24_MT_PADDR, 4));
1261 device_printf(sc->dev, "PCNT:%ld\n", envy24_rdmt(sc, ENVY24_MT_PCNT, 2));
1268 envy24_stop(struct sc_info *sc, int dir)
1273 device_printf(sc->dev, "envy24_stop(sc, %d)\n", dir);
1275 if (dir == PCMDIR_PLAY)
1276 sw = ~ENVY24_MT_PCTL_PSTART;
1278 sw = ~ENVY24_MT_PCTL_RSTART;
1280 stat = envy24_rdmt(sc, ENVY24_MT_PCTL, 1);
1281 envy24_wrmt(sc, ENVY24_MT_PCTL, stat & sw, 1);
1287 envy24_route(struct sc_info *sc, int dac, int class, int adc, int rev)
1289 u_int32_t reg, mask;
1290 u_int32_t left, right;
1293 device_printf(sc->dev, "envy24_route(sc, %d, %d, %d, %d)\n",
1294 dac, class, adc, rev);
1296 /* parameter pattern check */
1297 if (dac < 0 || ENVY24_ROUTE_DAC_SPDIF < dac)
1299 if (class == ENVY24_ROUTE_CLASS_MIX &&
1300 (dac != ENVY24_ROUTE_DAC_1 && dac != ENVY24_ROUTE_DAC_SPDIF))
1303 left = ENVY24_ROUTE_RIGHT;
1304 right = ENVY24_ROUTE_LEFT;
1307 left = ENVY24_ROUTE_LEFT;
1308 right = ENVY24_ROUTE_RIGHT;
1311 if (dac == ENVY24_ROUTE_DAC_SPDIF) {
1312 reg = class | class << 2 |
1313 ((adc << 1 | left) | left << 3) << 8 |
1314 ((adc << 1 | right) | right << 3) << 12;
1316 device_printf(sc->dev, "envy24_route(): MT_SPDOUT-->0x%04x\n", reg);
1318 envy24_wrmt(sc, ENVY24_MT_SPDOUT, reg, 2);
1321 mask = ~(0x0303 << dac * 2);
1322 reg = envy24_rdmt(sc, ENVY24_MT_PSDOUT, 2);
1323 reg = (reg & mask) | ((class | class << 8) << dac * 2);
1325 device_printf(sc->dev, "envy24_route(): MT_PSDOUT-->0x%04x\n", reg);
1327 envy24_wrmt(sc, ENVY24_MT_PSDOUT, reg, 2);
1328 mask = ~(0xff << dac * 8);
1329 reg = envy24_rdmt(sc, ENVY24_MT_RECORD, 4);
1330 reg = (reg & mask) |
1331 (((adc << 1 | left) | left << 3) |
1332 ((adc << 1 | right) | right << 3) << 4) << dac * 8;
1334 device_printf(sc->dev, "envy24_route(): MT_RECORD-->0x%08x\n", reg);
1336 envy24_wrmt(sc, ENVY24_MT_RECORD, reg, 4);
1338 /* 6fire rear input init test */
1339 envy24_wrmt(sc, ENVY24_MT_RECORD, 0x00, 4);
1345 /* -------------------------------------------------------------------- */
1347 /* buffer copy routines */
1349 envy24_p32sl(struct sc_chinfo *ch)
1354 int src, dst, ssize, dsize, slot;
1357 length = sndbuf_getready(ch->buffer) / 8;
1358 dmabuf = ch->parent->pbuf;
1359 data = (u_int32_t *)ch->data;
1360 src = sndbuf_getreadyptr(ch->buffer) / 4;
1361 dst = src / 2 + ch->offset;
1362 ssize = ch->size / 4;
1363 dsize = ch->size / 8;
1366 for (i = 0; i < length; i++) {
1367 dmabuf[dst * ENVY24_PLAY_CHNUM + slot].buffer = data[src];
1368 dmabuf[dst * ENVY24_PLAY_CHNUM + slot + 1].buffer = data[src + 1];
1379 envy24_p16sl(struct sc_chinfo *ch)
1384 int src, dst, ssize, dsize, slot;
1388 device_printf(ch->parent->dev, "envy24_p16sl()\n");
1390 length = sndbuf_getready(ch->buffer) / 4;
1391 dmabuf = ch->parent->pbuf;
1392 data = (u_int16_t *)ch->data;
1393 src = sndbuf_getreadyptr(ch->buffer) / 2;
1394 dst = src / 2 + ch->offset;
1395 ssize = ch->size / 2;
1396 dsize = ch->size / 4;
1399 device_printf(ch->parent->dev, "envy24_p16sl():%lu-->%lu(%lu)\n", src, dst, length);
1402 for (i = 0; i < length; i++) {
1403 dmabuf[dst * ENVY24_PLAY_CHNUM + slot].buffer = (u_int32_t)data[src] << 16;
1404 dmabuf[dst * ENVY24_PLAY_CHNUM + slot + 1].buffer = (u_int32_t)data[src + 1] << 16;
1407 printf("%08x", dmabuf[dst * ENVY24_PLAY_CHNUM + slot]);
1408 printf("%08x", dmabuf[dst * ENVY24_PLAY_CHNUM + slot + 1]);
1424 envy24_p8u(struct sc_chinfo *ch)
1429 int src, dst, ssize, dsize, slot;
1432 length = sndbuf_getready(ch->buffer) / 2;
1433 dmabuf = ch->parent->pbuf;
1434 data = (u_int8_t *)ch->data;
1435 src = sndbuf_getreadyptr(ch->buffer);
1436 dst = src / 2 + ch->offset;
1438 dsize = ch->size / 4;
1441 for (i = 0; i < length; i++) {
1442 dmabuf[dst * ENVY24_PLAY_CHNUM + slot].buffer = ((u_int32_t)data[src] ^ 0x80) << 24;
1443 dmabuf[dst * ENVY24_PLAY_CHNUM + slot + 1].buffer = ((u_int32_t)data[src + 1] ^ 0x80) << 24;
1454 envy24_r32sl(struct sc_chinfo *ch)
1459 int src, dst, ssize, dsize, slot;
1462 length = sndbuf_getfree(ch->buffer) / 8;
1463 dmabuf = ch->parent->rbuf;
1464 data = (u_int32_t *)ch->data;
1465 dst = sndbuf_getfreeptr(ch->buffer) / 4;
1466 src = dst / 2 + ch->offset;
1467 dsize = ch->size / 4;
1468 ssize = ch->size / 8;
1469 slot = (ch->num - ENVY24_CHAN_REC_ADC1) * 2;
1471 for (i = 0; i < length; i++) {
1472 data[dst] = dmabuf[src * ENVY24_REC_CHNUM + slot].buffer;
1473 data[dst + 1] = dmabuf[src * ENVY24_REC_CHNUM + slot + 1].buffer;
1484 envy24_r16sl(struct sc_chinfo *ch)
1489 int src, dst, ssize, dsize, slot;
1492 length = sndbuf_getfree(ch->buffer) / 4;
1493 dmabuf = ch->parent->rbuf;
1494 data = (u_int16_t *)ch->data;
1495 dst = sndbuf_getfreeptr(ch->buffer) / 2;
1496 src = dst / 2 + ch->offset;
1497 dsize = ch->size / 2;
1498 ssize = ch->size / 8;
1499 slot = (ch->num - ENVY24_CHAN_REC_ADC1) * 2;
1501 for (i = 0; i < length; i++) {
1502 data[dst] = dmabuf[src * ENVY24_REC_CHNUM + slot].buffer;
1503 data[dst + 1] = dmabuf[src * ENVY24_REC_CHNUM + slot + 1].buffer;
1513 /* -------------------------------------------------------------------- */
1515 /* channel interface */
1517 envy24chan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir)
1519 struct sc_info *sc = (struct sc_info *)devinfo;
1520 struct sc_chinfo *ch;
1524 device_printf(sc->dev, "envy24chan_init(obj, devinfo, b, c, %d)\n", dir);
1526 snd_mtxlock(sc->lock);
1527 if ((sc->chnum > ENVY24_CHAN_PLAY_SPDIF && dir != PCMDIR_REC) ||
1528 (sc->chnum < ENVY24_CHAN_REC_ADC1 && dir != PCMDIR_PLAY)) {
1529 snd_mtxunlock(sc->lock);
1534 ch = &sc->chan[num];
1535 ch->size = 8 * ENVY24_SAMPLE_NUM;
1536 ch->data = kmalloc(ch->size, M_ENVY24, M_WAITOK);
1542 /* set channel map */
1543 ch->num = envy24_chanmap[num];
1544 snd_mtxunlock(sc->lock);
1545 sndbuf_setup(ch->buffer, ch->data, ch->size);
1546 snd_mtxlock(sc->lock);
1547 /* these 2 values are dummy */
1551 snd_mtxunlock(sc->lock);
1557 envy24chan_free(kobj_t obj, void *data)
1559 struct sc_chinfo *ch = data;
1560 struct sc_info *sc = ch->parent;
1563 device_printf(sc->dev, "envy24chan_free()\n");
1565 snd_mtxlock(sc->lock);
1566 if (ch->data != NULL) {
1567 kfree(ch->data, M_ENVY24);
1570 snd_mtxunlock(sc->lock);
1576 envy24chan_setformat(kobj_t obj, void *data, u_int32_t format)
1578 struct sc_chinfo *ch = data;
1579 struct sc_info *sc = ch->parent;
1580 struct envy24_emldma *emltab;
1581 /* unsigned int bcnt, bsize; */
1585 device_printf(sc->dev, "envy24chan_setformat(obj, data, 0x%08x)\n", format);
1587 snd_mtxlock(sc->lock);
1588 /* check and get format related information */
1589 if (ch->dir == PCMDIR_PLAY)
1590 emltab = envy24_pemltab;
1592 emltab = envy24_remltab;
1593 if (emltab == NULL) {
1594 snd_mtxunlock(sc->lock);
1597 for (i = 0; emltab[i].format != 0; i++)
1598 if (emltab[i].format == format)
1600 if (emltab[i].format == 0) {
1601 snd_mtxunlock(sc->lock);
1605 /* set format information */
1606 ch->format = format;
1607 ch->emldma = emltab[i].emldma;
1608 if (ch->unit > emltab[i].unit)
1609 ch->blk *= ch->unit / emltab[i].unit;
1611 ch->blk /= emltab[i].unit / ch->unit;
1612 ch->unit = emltab[i].unit;
1614 /* set channel buffer information */
1615 ch->size = ch->unit * ENVY24_SAMPLE_NUM;
1617 if (ch->dir == PCMDIR_PLAY)
1618 bsize = ch->blk * 4 / ENVY24_PLAY_BUFUNIT;
1620 bsize = ch->blk * 4 / ENVY24_REC_BUFUNIT;
1622 bcnt = ch->size / bsize;
1623 sndbuf_resize(ch->buffer, bcnt, bsize);
1625 snd_mtxunlock(sc->lock);
1628 device_printf(sc->dev, "envy24chan_setformat(): return 0x%08x\n", 0);
1634 IMPLEMENT NOTICE: In this driver, setspeed function only do setting
1635 of speed information value. And real hardware speed setting is done
1636 at start triggered(see envy24chan_trigger()). So, at this function
1637 is called, any value that ENVY24 can use is able to set. But, at
1638 start triggerd, some other channel is running, and that channel's
1639 speed isn't same with, then trigger function will fail.
1642 envy24chan_setspeed(kobj_t obj, void *data, u_int32_t speed)
1644 struct sc_chinfo *ch = data;
1645 u_int32_t val, prev;
1649 device_printf(ch->parent->dev, "envy24chan_setspeed(obj, data, %d)\n", speed);
1652 for (i = 0; (val = envy24_speed[i]) != 0; i++) {
1653 if (abs(val - speed) < abs(prev - speed))
1661 device_printf(ch->parent->dev, "envy24chan_setspeed(): return %d\n", ch->speed);
1667 envy24chan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
1669 struct sc_chinfo *ch = data;
1670 /* struct sc_info *sc = ch->parent; */
1671 u_int32_t size, prev;
1672 unsigned int bcnt, bsize;
1675 device_printf(sc->dev, "envy24chan_setblocksize(obj, data, %d)\n", blocksize);
1678 /* snd_mtxlock(sc->lock); */
1679 for (size = ch->size / 2; size > 0; size /= 2) {
1680 if (abs(size - blocksize) < abs(prev - blocksize))
1686 ch->blk = prev / ch->unit;
1687 if (ch->dir == PCMDIR_PLAY)
1688 ch->blk *= ENVY24_PLAY_BUFUNIT / 4;
1690 ch->blk *= ENVY24_REC_BUFUNIT / 4;
1691 /* set channel buffer information */
1692 /* ch->size = ch->unit * ENVY24_SAMPLE_NUM; */
1693 if (ch->dir == PCMDIR_PLAY)
1694 bsize = ch->blk * 4 / ENVY24_PLAY_BUFUNIT;
1696 bsize = ch->blk * 4 / ENVY24_REC_BUFUNIT;
1698 bcnt = ch->size / bsize;
1699 sndbuf_resize(ch->buffer, bcnt, bsize);
1700 /* snd_mtxunlock(sc->lock); */
1703 device_printf(sc->dev, "envy24chan_setblocksize(): return %d\n", prev);
1708 /* semantic note: must start at beginning of buffer */
1710 envy24chan_trigger(kobj_t obj, void *data, int go)
1712 struct sc_chinfo *ch = data;
1713 struct sc_info *sc = ch->parent;
1719 device_printf(sc->dev, "envy24chan_trigger(obj, data, %d)\n", go);
1721 snd_mtxlock(sc->lock);
1722 if (ch->dir == PCMDIR_PLAY)
1729 device_printf(sc->dev, "envy24chan_trigger(): start\n");
1731 /* check or set channel speed */
1732 if (sc->run[0] == 0 && sc->run[1] == 0) {
1733 sc->speed = envy24_setspeed(sc, ch->speed);
1734 sc->caps[0].minspeed = sc->caps[0].maxspeed = sc->speed;
1735 sc->caps[1].minspeed = sc->caps[1].maxspeed = sc->speed;
1737 else if (ch->speed != 0 && ch->speed != sc->speed)
1740 ch->channel->speed = sc->speed;
1741 /* start or enable channel */
1743 if (sc->run[slot] == 1) {
1746 sc->blk[slot] = ch->blk;
1749 ptr = envy24_gethwptr(sc, ch->dir);
1750 ch->offset = ((ptr / ch->blk + 1) * ch->blk %
1751 (ch->size / 4)) * 4 / ch->unit;
1752 if (ch->blk < sc->blk[slot])
1753 sc->blk[slot] = ch->blk;
1755 if (ch->dir == PCMDIR_PLAY) {
1757 envy24_setvolume(sc, ch->num);
1759 envy24_updintr(sc, ch->dir);
1760 if (sc->run[slot] == 1)
1761 envy24_start(sc, ch->dir);
1764 case PCMTRIG_EMLDMAWR:
1766 device_printf(sc->dev, "envy24chan_trigger(): emldmawr\n");
1772 case PCMTRIG_EMLDMARD:
1774 device_printf(sc->dev, "envy24chan_trigger(): emldmard\n");
1783 device_printf(sc->dev, "envy24chan_trigger(): abort\n");
1787 if (ch->dir == PCMDIR_PLAY)
1788 envy24_mutevolume(sc, ch->num);
1789 if (sc->run[slot] == 0) {
1790 envy24_stop(sc, ch->dir);
1794 else if (ch->blk == sc->blk[slot]) {
1795 sc->blk[slot] = ENVY24_SAMPLE_NUM / 2;
1796 for (i = 0; i < ENVY24_CHAN_NUM; i++) {
1797 if (sc->chan[i].dir == ch->dir &&
1798 sc->chan[i].run == 1 &&
1799 sc->chan[i].blk < sc->blk[slot])
1800 sc->blk[slot] = sc->chan[i].blk;
1802 if (ch->blk != sc->blk[slot])
1803 envy24_updintr(sc, ch->dir);
1809 snd_mtxunlock(sc->lock);
1815 envy24chan_getptr(kobj_t obj, void *data)
1817 struct sc_chinfo *ch = data;
1818 struct sc_info *sc = ch->parent;
1823 device_printf(sc->dev, "envy24chan_getptr()\n");
1825 snd_mtxlock(sc->lock);
1826 ptr = envy24_gethwptr(sc, ch->dir);
1827 rtn = ptr * ch->unit;
1828 snd_mtxunlock(sc->lock);
1831 device_printf(sc->dev, "envy24chan_getptr(): return %d\n",
1837 static struct pcmchan_caps *
1838 envy24chan_getcaps(kobj_t obj, void *data)
1840 struct sc_chinfo *ch = data;
1841 struct sc_info *sc = ch->parent;
1842 struct pcmchan_caps *rtn;
1845 device_printf(sc->dev, "envy24chan_getcaps()\n");
1847 snd_mtxlock(sc->lock);
1848 if (ch->dir == PCMDIR_PLAY) {
1849 if (sc->run[0] == 0)
1850 rtn = &envy24_playcaps;
1855 if (sc->run[1] == 0)
1856 rtn = &envy24_reccaps;
1860 snd_mtxunlock(sc->lock);
1865 static kobj_method_t envy24chan_methods[] = {
1866 KOBJMETHOD(channel_init, envy24chan_init),
1867 KOBJMETHOD(channel_free, envy24chan_free),
1868 KOBJMETHOD(channel_setformat, envy24chan_setformat),
1869 KOBJMETHOD(channel_setspeed, envy24chan_setspeed),
1870 KOBJMETHOD(channel_setblocksize, envy24chan_setblocksize),
1871 KOBJMETHOD(channel_trigger, envy24chan_trigger),
1872 KOBJMETHOD(channel_getptr, envy24chan_getptr),
1873 KOBJMETHOD(channel_getcaps, envy24chan_getcaps),
1876 CHANNEL_DECLARE(envy24chan);
1878 /* -------------------------------------------------------------------- */
1880 /* mixer interface */
1883 envy24mixer_init(struct snd_mixer *m)
1885 struct sc_info *sc = mix_getdevinfo(m);
1888 device_printf(sc->dev, "envy24mixer_init()\n");
1893 /* set volume control rate */
1894 snd_mtxlock(sc->lock);
1895 envy24_wrmt(sc, ENVY24_MT_VOLRATE, 0x30, 1); /* 0x30 is default value */
1897 mix_setdevs(m, ENVY24_MIX_MASK);
1898 mix_setrecdevs(m, ENVY24_MIX_REC_MASK);
1899 snd_mtxunlock(sc->lock);
1905 envy24mixer_reinit(struct snd_mixer *m)
1907 struct sc_info *sc = mix_getdevinfo(m);
1912 device_printf(sc->dev, "envy24mixer_reinit()\n");
1919 envy24mixer_uninit(struct snd_mixer *m)
1921 struct sc_info *sc = mix_getdevinfo(m);
1926 device_printf(sc->dev, "envy24mixer_uninit()\n");
1933 envy24mixer_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right)
1935 struct sc_info *sc = mix_getdevinfo(m);
1936 int ch = envy24_mixmap[dev];
1942 if (dev == 0 && sc->cfg->codec->setvolume == NULL)
1944 if (dev != 0 && ch == -1)
1946 hwch = envy24_chanmap[ch];
1948 device_printf(sc->dev, "envy24mixer_set(m, %d, %d, %d)\n",
1952 snd_mtxlock(sc->lock);
1954 for (i = 0; i < sc->dacn; i++) {
1955 sc->cfg->codec->setvolume(sc->dac[i], PCMDIR_PLAY, left, right);
1959 /* set volume value for hardware */
1960 if ((sc->left[hwch] = 100 - left) > ENVY24_VOL_MIN)
1961 sc->left[hwch] = ENVY24_VOL_MUTE;
1962 if ((sc->right[hwch] = 100 - right) > ENVY24_VOL_MIN)
1963 sc->right[hwch] = ENVY24_VOL_MUTE;
1965 /* set volume for record channel and running play channel */
1966 if (hwch > ENVY24_CHAN_PLAY_SPDIF || sc->chan[ch].run)
1967 envy24_setvolume(sc, hwch);
1969 snd_mtxunlock(sc->lock);
1971 return right << 8 | left;
1975 envy24mixer_setrecsrc(struct snd_mixer *m, u_int32_t src)
1977 struct sc_info *sc = mix_getdevinfo(m);
1978 int ch = envy24_mixmap[src];
1980 device_printf(sc->dev, "envy24mixer_setrecsrc(m, %d)\n", src);
1983 if (ch > ENVY24_CHAN_PLAY_SPDIF)
1988 static kobj_method_t envy24mixer_methods[] = {
1989 KOBJMETHOD(mixer_init, envy24mixer_init),
1990 KOBJMETHOD(mixer_reinit, envy24mixer_reinit),
1991 KOBJMETHOD(mixer_uninit, envy24mixer_uninit),
1992 KOBJMETHOD(mixer_set, envy24mixer_set),
1993 KOBJMETHOD(mixer_setrecsrc, envy24mixer_setrecsrc),
1996 MIXER_DECLARE(envy24mixer);
1998 /* -------------------------------------------------------------------- */
2000 /* The interrupt handler */
2002 envy24_intr(void *p)
2004 struct sc_info *sc = (struct sc_info *)p;
2005 struct sc_chinfo *ch;
2006 u_int32_t ptr, dsize, feed;
2010 device_printf(sc->dev, "envy24_intr()\n");
2012 snd_mtxlock(sc->lock);
2013 if (envy24_checkintr(sc, PCMDIR_PLAY)) {
2015 device_printf(sc->dev, "envy24_intr(): play\n");
2017 dsize = sc->psize / 4;
2018 ptr = dsize - envy24_rdmt(sc, ENVY24_MT_PCNT, 2) - 1;
2020 device_printf(sc->dev, "envy24_intr(): ptr = %d-->", ptr);
2022 ptr -= ptr % sc->blk[0];
2023 feed = (ptr + dsize - sc->intr[0]) % dsize;
2025 printf("%d intr = %d feed = %d\n", ptr, sc->intr[0], feed);
2027 for (i = ENVY24_CHAN_PLAY_DAC1; i <= ENVY24_CHAN_PLAY_SPDIF; i++) {
2031 device_printf(sc->dev, "envy24_intr(): chan[%d].blk = %d\n", i, ch->blk);
2033 if (ch->run && ch->blk <= feed) {
2034 snd_mtxunlock(sc->lock);
2035 chn_intr(ch->channel);
2036 snd_mtxlock(sc->lock);
2040 envy24_updintr(sc, PCMDIR_PLAY);
2042 if (envy24_checkintr(sc, PCMDIR_REC)) {
2044 device_printf(sc->dev, "envy24_intr(): rec\n");
2046 dsize = sc->rsize / 4;
2047 ptr = dsize - envy24_rdmt(sc, ENVY24_MT_RCNT, 2) - 1;
2048 ptr -= ptr % sc->blk[1];
2049 feed = (ptr + dsize - sc->intr[1]) % dsize;
2050 for (i = ENVY24_CHAN_REC_ADC1; i <= ENVY24_CHAN_REC_SPDIF; i++) {
2052 if (ch->run && ch->blk <= feed) {
2053 snd_mtxunlock(sc->lock);
2054 chn_intr(ch->channel);
2055 snd_mtxlock(sc->lock);
2059 envy24_updintr(sc, PCMDIR_REC);
2061 snd_mtxunlock(sc->lock);
2067 * Probe and attach the card
2071 envy24_pci_probe(device_t dev)
2077 printf("envy24_pci_probe()\n");
2079 if (pci_get_device(dev) == PCID_ENVY24 &&
2080 pci_get_vendor(dev) == PCIV_ENVY24) {
2081 sv = pci_get_subvendor(dev);
2082 sd = pci_get_subdevice(dev);
2083 for (i = 0; cfg_table[i].subvendor != 0 || cfg_table[i].subdevice != 0; i++) {
2084 if (cfg_table[i].subvendor == sv &&
2085 cfg_table[i].subdevice == sd) {
2089 device_set_desc(dev, cfg_table[i].name);
2091 printf("envy24_pci_probe(): return 0\n");
2097 printf("envy24_pci_probe(): return ENXIO\n");
2104 envy24_dmapsetmap(void *arg, bus_dma_segment_t *segs, int nseg, int error)
2106 /* struct sc_info *sc = (struct sc_info *)arg; */
2109 device_printf(sc->dev, "envy24_dmapsetmap()\n");
2111 printf("envy24(play): setmap %lx, %lx; ",
2112 (unsigned long)segs->ds_addr,
2113 (unsigned long)segs->ds_len);
2114 printf("%p -> %lx\n", sc->pmap, (unsigned long)vtophys(sc->pmap));
2120 envy24_dmarsetmap(void *arg, bus_dma_segment_t *segs, int nseg, int error)
2122 /* struct sc_info *sc = (struct sc_info *)arg; */
2125 device_printf(sc->dev, "envy24_dmarsetmap()\n");
2127 printf("envy24(record): setmap %lx, %lx; ",
2128 (unsigned long)segs->ds_addr,
2129 (unsigned long)segs->ds_len);
2130 printf("%p -> %lx\n", sc->rmap, (unsigned long)vtophys(sc->pmap));
2136 envy24_dmafree(struct sc_info *sc)
2139 device_printf(sc->dev, "envy24_dmafree():");
2140 if (sc->rmap) printf(" sc->rmap(0x%08x)", (u_int32_t)sc->rmap);
2141 else printf(" sc->rmap(null)");
2142 if (sc->pmap) printf(" sc->pmap(0x%08x)", (u_int32_t)sc->pmap);
2143 else printf(" sc->pmap(null)");
2144 if (sc->rbuf) printf(" sc->rbuf(0x%08x)", (u_int32_t)sc->rbuf);
2145 else printf(" sc->rbuf(null)");
2146 if (sc->pbuf) printf(" sc->pbuf(0x%08x)\n", (u_int32_t)sc->pbuf);
2147 else printf(" sc->pbuf(null)\n");
2151 bus_dmamap_unload(sc->dmat, sc->rmap);
2153 bus_dmamap_unload(sc->dmat, sc->pmap);
2155 bus_dmamem_free(sc->dmat, sc->rbuf, sc->rmap);
2157 bus_dmamem_free(sc->dmat, sc->pbuf, sc->pmap);
2159 bus_dmamap_unload(sc->dmat, sc->rmap);
2160 bus_dmamap_unload(sc->dmat, sc->pmap);
2161 bus_dmamem_free(sc->dmat, sc->rbuf, sc->rmap);
2162 bus_dmamem_free(sc->dmat, sc->pbuf, sc->pmap);
2165 sc->rmap = sc->pmap = NULL;
2173 envy24_dmainit(struct sc_info *sc)
2178 device_printf(sc->dev, "envy24_dmainit()\n");
2181 sc->psize = ENVY24_PLAY_BUFUNIT * ENVY24_SAMPLE_NUM;
2182 sc->rsize = ENVY24_REC_BUFUNIT * ENVY24_SAMPLE_NUM;
2185 sc->pmap = sc->rmap = NULL;
2186 sc->blk[0] = sc->blk[1] = 0;
2188 /* allocate DMA buffer */
2190 device_printf(sc->dev, "envy24_dmainit(): bus_dmamem_alloc(): sc->pbuf\n");
2192 if (bus_dmamem_alloc(sc->dmat, (void **)&sc->pbuf, BUS_DMA_NOWAIT, &sc->pmap))
2195 device_printf(sc->dev, "envy24_dmainit(): bus_dmamem_alloc(): sc->rbuf\n");
2197 if (bus_dmamem_alloc(sc->dmat, (void **)&sc->rbuf, BUS_DMA_NOWAIT, &sc->rmap))
2200 device_printf(sc->dev, "envy24_dmainit(): bus_dmamem_load(): sc->pmap\n");
2202 if (bus_dmamap_load(sc->dmat, sc->pmap, sc->pbuf, sc->psize, envy24_dmapsetmap, sc, 0))
2205 device_printf(sc->dev, "envy24_dmainit(): bus_dmamem_load(): sc->rmap\n");
2207 if (bus_dmamap_load(sc->dmat, sc->rmap, sc->rbuf, sc->rsize, envy24_dmarsetmap, sc, 0))
2209 bzero(sc->pbuf, sc->psize);
2210 bzero(sc->rbuf, sc->rsize);
2212 /* set values to register */
2213 addr = vtophys(sc->pbuf);
2215 device_printf(sc->dev, "pbuf(0x%08x)\n", addr);
2217 envy24_wrmt(sc, ENVY24_MT_PADDR, addr, 4);
2219 device_printf(sc->dev, "PADDR-->(0x%08x)\n", envy24_rdmt(sc, ENVY24_MT_PADDR, 4));
2220 device_printf(sc->dev, "psize(%ld)\n", sc->psize / 4 - 1);
2222 envy24_wrmt(sc, ENVY24_MT_PCNT, sc->psize / 4 - 1, 2);
2224 device_printf(sc->dev, "PCNT-->(%ld)\n", envy24_rdmt(sc, ENVY24_MT_PCNT, 2));
2226 addr = vtophys(sc->rbuf);
2227 envy24_wrmt(sc, ENVY24_MT_RADDR, addr, 4);
2228 envy24_wrmt(sc, ENVY24_MT_RCNT, sc->rsize / 4 - 1, 2);
2237 envy24_putcfg(struct sc_info *sc)
2239 device_printf(sc->dev, "system configuration\n");
2240 kprintf(" SubVendorID: 0x%04x, SubDeviceID: 0x%04x\n",
2241 sc->cfg->subvendor, sc->cfg->subdevice);
2242 kprintf(" XIN2 Clock Source: ");
2243 switch (sc->cfg->scfg & PCIM_SCFG_XIN2) {
2245 kprintf("22.5792MHz(44.1kHz*512)\n");
2248 kprintf("16.9344MHz(44.1kHz*384)\n");
2251 kprintf("from external clock synthesizer chip\n");
2254 kprintf("illegal system setting\n");
2256 kprintf(" MPU-401 UART(s) #: ");
2257 if (sc->cfg->scfg & PCIM_SCFG_MPU)
2261 kprintf(" AC'97 codec: ");
2262 if (sc->cfg->scfg & PCIM_SCFG_AC97)
2263 kprintf("not exist\n");
2266 kprintf(" ADC #: ");
2267 kprintf("%d\n", sc->adcn);
2268 kprintf(" DAC #: ");
2269 kprintf("%d\n", sc->dacn);
2270 kprintf(" Multi-track converter type: ");
2271 if ((sc->cfg->acl & PCIM_ACL_MTC) == 0) {
2272 kprintf("AC'97(SDATA_OUT:");
2273 if (sc->cfg->acl & PCIM_ACL_OMODE)
2277 kprintf("|SDATA_IN:");
2278 if (sc->cfg->acl & PCIM_ACL_IMODE)
2286 if (sc->cfg->i2s & PCIM_I2S_VOL)
2287 kprintf("with volume, ");
2288 if (sc->cfg->i2s & PCIM_I2S_96KHZ)
2289 kprintf("96KHz support, ");
2290 switch (sc->cfg->i2s & PCIM_I2S_RES) {
2291 case PCIM_I2S_16BIT:
2292 kprintf("16bit resolution, ");
2294 case PCIM_I2S_18BIT:
2295 kprintf("18bit resolution, ");
2297 case PCIM_I2S_20BIT:
2298 kprintf("20bit resolution, ");
2300 case PCIM_I2S_24BIT:
2301 kprintf("24bit resolution, ");
2304 kprintf("ID#0x%x)\n", sc->cfg->i2s & PCIM_I2S_ID);
2306 kprintf(" S/PDIF(IN/OUT): ");
2307 if (sc->cfg->spdif & PCIM_SPDIF_IN)
2311 if (sc->cfg->spdif & PCIM_SPDIF_OUT)
2315 if (sc->cfg->spdif & (PCIM_SPDIF_IN | PCIM_SPDIF_OUT))
2316 kprintf("ID# 0x%02x\n", (sc->cfg->spdif & PCIM_SPDIF_ID) >> 2);
2317 kprintf(" GPIO(mask/dir/state): 0x%02x/0x%02x/0x%02x\n",
2318 sc->cfg->gpiomask, sc->cfg->gpiodir, sc->cfg->gpiostate);
2322 envy24_init(struct sc_info *sc)
2333 device_printf(sc->dev, "envy24_init()\n");
2337 envy24_wrcs(sc, ENVY24_CCS_CTL, ENVY24_CCS_CTL_RESET | ENVY24_CCS_CTL_NATIVE, 1);
2339 envy24_wrcs(sc, ENVY24_CCS_CTL, ENVY24_CCS_CTL_NATIVE, 1);
2342 /* legacy hardware disable */
2343 data = pci_read_config(sc->dev, PCIR_LAC, 2);
2344 data |= PCIM_LAC_DISABLE;
2345 pci_write_config(sc->dev, PCIR_LAC, data, 2);
2347 /* check system configuration */
2349 for (i = 0; cfg_table[i].subvendor != 0 || cfg_table[i].subdevice != 0; i++) {
2350 /* 1st: search configuration from table */
2351 sv = pci_get_subvendor(sc->dev);
2352 sd = pci_get_subdevice(sc->dev);
2353 if (sv == cfg_table[i].subvendor && sd == cfg_table[i].subdevice) {
2355 device_printf(sc->dev, "Set configuration from table\n");
2357 sc->cfg = &cfg_table[i];
2361 if (sc->cfg == NULL) {
2362 /* 2nd: read configuration from table */
2363 sc->cfg = envy24_rom2cfg(sc);
2365 sc->adcn = ((sc->cfg->scfg & PCIM_SCFG_ADC) >> 2) + 1;
2366 sc->dacn = (sc->cfg->scfg & PCIM_SCFG_DAC) + 1;
2368 if (1 /* bootverbose */) {
2372 /* set system configuration */
2373 pci_write_config(sc->dev, PCIR_SCFG, sc->cfg->scfg, 1);
2374 pci_write_config(sc->dev, PCIR_ACL, sc->cfg->acl, 1);
2375 pci_write_config(sc->dev, PCIR_I2S, sc->cfg->i2s, 1);
2376 pci_write_config(sc->dev, PCIR_SPDIF, sc->cfg->spdif, 1);
2377 envy24_gpiosetmask(sc, sc->cfg->gpiomask);
2378 envy24_gpiosetdir(sc, sc->cfg->gpiodir);
2379 envy24_gpiowr(sc, sc->cfg->gpiostate);
2380 for (i = 0; i < sc->adcn; i++) {
2381 sc->adc[i] = sc->cfg->codec->create(sc->dev, sc, PCMDIR_REC, i);
2382 sc->cfg->codec->init(sc->adc[i]);
2384 for (i = 0; i < sc->dacn; i++) {
2385 sc->dac[i] = sc->cfg->codec->create(sc->dev, sc, PCMDIR_PLAY, i);
2386 sc->cfg->codec->init(sc->dac[i]);
2389 /* initialize DMA buffer */
2391 device_printf(sc->dev, "envy24_init(): initialize DMA buffer\n");
2393 if (envy24_dmainit(sc))
2396 /* initialize status */
2397 sc->run[0] = sc->run[1] = 0;
2398 sc->intr[0] = sc->intr[1] = 0;
2400 sc->caps[0].fmtlist = envy24_playfmt;
2401 sc->caps[1].fmtlist = envy24_recfmt;
2403 /* set channel router */
2404 envy24_route(sc, ENVY24_ROUTE_DAC_1, ENVY24_ROUTE_CLASS_MIX, 0, 0);
2405 envy24_route(sc, ENVY24_ROUTE_DAC_SPDIF, ENVY24_ROUTE_CLASS_DMA, 0, 0);
2406 /* envy24_route(sc, ENVY24_ROUTE_DAC_SPDIF, ENVY24_ROUTE_CLASS_MIX, 0, 0); */
2408 /* set macro interrupt mask */
2409 data = envy24_rdcs(sc, ENVY24_CCS_IMASK, 1);
2410 envy24_wrcs(sc, ENVY24_CCS_IMASK, data & ~ENVY24_CCS_IMASK_PMT, 1);
2411 data = envy24_rdcs(sc, ENVY24_CCS_IMASK, 1);
2413 device_printf(sc->dev, "envy24_init(): CCS_IMASK-->0x%02x\n", data);
2420 envy24_alloc_resource(struct sc_info *sc)
2422 /* allocate I/O port resource */
2423 sc->csid = PCIR_CCS;
2424 sc->cs = bus_alloc_resource(sc->dev, SYS_RES_IOPORT,
2425 &sc->csid, 0, ~0, 1, RF_ACTIVE);
2426 sc->ddmaid = PCIR_DDMA;
2427 sc->ddma = bus_alloc_resource(sc->dev, SYS_RES_IOPORT,
2428 &sc->ddmaid, 0, ~0, 1, RF_ACTIVE);
2430 sc->ds = bus_alloc_resource(sc->dev, SYS_RES_IOPORT,
2431 &sc->dsid, 0, ~0, 1, RF_ACTIVE);
2433 sc->mt = bus_alloc_resource(sc->dev, SYS_RES_IOPORT,
2434 &sc->mtid, 0, ~0, 1, RF_ACTIVE);
2435 if (!sc->cs || !sc->ddma || !sc->ds || !sc->mt) {
2436 device_printf(sc->dev, "unable to map IO port space\n");
2439 sc->cst = rman_get_bustag(sc->cs);
2440 sc->csh = rman_get_bushandle(sc->cs);
2441 sc->ddmat = rman_get_bustag(sc->ddma);
2442 sc->ddmah = rman_get_bushandle(sc->ddma);
2443 sc->dst = rman_get_bustag(sc->ds);
2444 sc->dsh = rman_get_bushandle(sc->ds);
2445 sc->mtt = rman_get_bustag(sc->mt);
2446 sc->mth = rman_get_bushandle(sc->mt);
2448 device_printf(sc->dev,
2449 "IO port register values\nCCS: 0x%lx\nDDMA: 0x%lx\nDS: 0x%lx\nMT: 0x%lx\n",
2450 pci_read_config(sc->dev, PCIR_CCS, 4),
2451 pci_read_config(sc->dev, PCIR_DDMA, 4),
2452 pci_read_config(sc->dev, PCIR_DS, 4),
2453 pci_read_config(sc->dev, PCIR_MT, 4));
2456 /* allocate interupt resource */
2458 sc->irq = bus_alloc_resource(sc->dev, SYS_RES_IRQ, &sc->irqid,
2459 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE);
2461 snd_setup_intr(sc->dev, sc->irq, INTR_MPSAFE, envy24_intr, sc, &sc->ih)) {
2462 device_printf(sc->dev, "unable to map interrupt\n");
2466 /* allocate DMA resource */
2467 if (bus_dma_tag_create(/*parent*/NULL,
2470 /*lowaddr*/BUS_SPACE_MAXADDR_ENVY24,
2471 /*highaddr*/BUS_SPACE_MAXADDR_ENVY24,
2472 /*filter*/NULL, /*filterarg*/NULL,
2473 /*maxsize*/BUS_SPACE_MAXSIZE_ENVY24,
2474 /*nsegments*/1, /*maxsegsz*/0x3ffff,
2475 /*flags*/0, &sc->dmat) != 0) {
2476 device_printf(sc->dev, "unable to create dma tag\n");
2484 envy24_pci_attach(device_t dev)
2488 char status[SND_STATUSLEN];
2493 device_printf(dev, "envy24_pci_attach()\n");
2495 /* get sc_info data area */
2496 sc = kmalloc(sizeof(*sc), M_ENVY24, M_WAITOK | M_ZERO);
2497 sc->lock = snd_mtxcreate(device_get_nameunit(dev), "snd_envy24 softc");
2500 /* initialize PCI interface */
2501 data = pci_read_config(dev, PCIR_COMMAND, 2);
2502 data |= (PCIM_CMD_PORTEN | PCIM_CMD_BUSMASTEREN);
2503 pci_write_config(dev, PCIR_COMMAND, data, 2);
2504 data = pci_read_config(dev, PCIR_COMMAND, 2);
2506 /* allocate resources */
2507 err = envy24_alloc_resource(sc);
2509 device_printf(dev, "unable to allocate system resources\n");
2513 /* initialize card */
2514 err = envy24_init(sc);
2516 device_printf(dev, "unable to initialize the card\n");
2520 /* set multi track mixer */
2521 mixer_init(dev, &envy24mixer_class, sc);
2523 /* set channel information */
2524 err = pcm_register(dev, sc, 5, 2 + sc->adcn);
2528 for (i = 0; i < 5; i++) {
2529 pcm_addchan(dev, PCMDIR_PLAY, &envy24chan_class, sc);
2532 for (i = 0; i < 2 + sc->adcn; i++) {
2533 pcm_addchan(dev, PCMDIR_REC, &envy24chan_class, sc);
2537 /* set status iformation */
2538 ksnprintf(status, SND_STATUSLEN,
2539 "at io 0x%lx:%ld,0x%lx:%ld,0x%lx:%ld,0x%lx:%ld irq %ld",
2540 rman_get_start(sc->cs),
2541 rman_get_end(sc->cs) - rman_get_start(sc->cs) + 1,
2542 rman_get_start(sc->ddma),
2543 rman_get_end(sc->ddma) - rman_get_start(sc->ddma) + 1,
2544 rman_get_start(sc->ds),
2545 rman_get_end(sc->ds) - rman_get_start(sc->ds) + 1,
2546 rman_get_start(sc->mt),
2547 rman_get_end(sc->mt) - rman_get_start(sc->mt) + 1,
2548 rman_get_start(sc->irq));
2549 pcm_setstatus(dev, status);
2555 bus_teardown_intr(dev, sc->irq, sc->ih);
2557 bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq);
2560 bus_dma_tag_destroy(sc->dmat);
2561 if (sc->cfg->codec->destroy != NULL) {
2562 for (i = 0; i < sc->adcn; i++)
2563 sc->cfg->codec->destroy(sc->adc[i]);
2564 for (i = 0; i < sc->dacn; i++)
2565 sc->cfg->codec->destroy(sc->dac[i]);
2567 envy24_cfgfree(sc->cfg);
2569 bus_release_resource(dev, SYS_RES_IOPORT, sc->csid, sc->cs);
2571 bus_release_resource(dev, SYS_RES_IOPORT, sc->ddmaid, sc->ddma);
2573 bus_release_resource(dev, SYS_RES_IOPORT, sc->dsid, sc->ds);
2575 bus_release_resource(dev, SYS_RES_IOPORT, sc->mtid, sc->mt);
2577 snd_mtxfree(sc->lock);
2578 kfree(sc, M_ENVY24);
2583 envy24_pci_detach(device_t dev)
2590 device_printf(dev, "envy24_pci_detach()\n");
2592 sc = pcm_getdevinfo(dev);
2595 r = pcm_unregister(dev);
2600 if (sc->cfg->codec->destroy != NULL) {
2601 for (i = 0; i < sc->adcn; i++)
2602 sc->cfg->codec->destroy(sc->adc[i]);
2603 for (i = 0; i < sc->dacn; i++)
2604 sc->cfg->codec->destroy(sc->dac[i]);
2606 envy24_cfgfree(sc->cfg);
2607 bus_dma_tag_destroy(sc->dmat);
2608 bus_teardown_intr(dev, sc->irq, sc->ih);
2609 bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq);
2610 bus_release_resource(dev, SYS_RES_IOPORT, sc->csid, sc->cs);
2611 bus_release_resource(dev, SYS_RES_IOPORT, sc->ddmaid, sc->ddma);
2612 bus_release_resource(dev, SYS_RES_IOPORT, sc->dsid, sc->ds);
2613 bus_release_resource(dev, SYS_RES_IOPORT, sc->mtid, sc->mt);
2614 snd_mtxfree(sc->lock);
2615 kfree(sc, M_ENVY24);
2619 static device_method_t envy24_methods[] = {
2620 /* Device interface */
2621 DEVMETHOD(device_probe, envy24_pci_probe),
2622 DEVMETHOD(device_attach, envy24_pci_attach),
2623 DEVMETHOD(device_detach, envy24_pci_detach),
2627 static driver_t envy24_driver = {
2630 #if __FreeBSD_version > 500000
2633 sizeof(struct snddev_info),
2637 DRIVER_MODULE(snd_envy24, pci, envy24_driver, pcm_devclass, 0, 0);
2638 MODULE_DEPEND(snd_envy24, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER);
2639 MODULE_DEPEND(snd_envy24, snd_spicds, 1, 1, 1);
2640 MODULE_VERSION(snd_envy24, 1);