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
28 #include <dev/sound/pcm/sound.h>
29 #include <dev/sound/pcm/ac97.h>
30 #include <dev/sound/pci/spicds.h>
31 #include <dev/sound/pci/envy24.h>
33 #include <dev/pci/pcireg.h>
34 #include <dev/pci/pcivar.h>
38 SND_DECLARE_FILE("$FreeBSD$");
40 MALLOC_DEFINE(M_ENVY24, "envy24", "envy24 audio");
42 /* -------------------------------------------------------------------- */
46 #define ENVY24_PLAY_CHNUM 10
47 #define ENVY24_REC_CHNUM 12
48 #define ENVY24_PLAY_BUFUNIT (4 /* byte/sample */ * 10 /* channel */)
49 #define ENVY24_REC_BUFUNIT (4 /* byte/sample */ * 12 /* channel */)
50 #define ENVY24_SAMPLE_NUM 4096
52 #define ENVY24_TIMEOUT 1000
54 #define ENVY24_DEFAULT_FORMAT (AFMT_STEREO | AFMT_S16_LE)
56 #define ENVY24_NAMELEN 32
61 struct envy24_sample {
62 volatile u_int32_t buffer;
65 typedef struct envy24_sample sample32_t;
67 /* channel registers */
69 struct snd_dbuf *buffer;
70 struct pcm_channel *channel;
71 struct sc_info *parent;
73 unsigned num; /* hw channel number */
75 /* channel information */
78 u_int32_t blk; /* hw block size(dword) */
80 /* format conversion structure */
82 unsigned int size; /* data buffer size(byte) */
83 int unit; /* sample size(byte) */
84 unsigned int offset; /* samples number offset */
85 void (*emldma)(struct sc_chinfo *);
91 /* codec interface entrys */
93 void *(*create)(device_t dev, void *devinfo, int dir, int num);
94 void (*destroy)(void *codec);
95 void (*init)(void *codec);
96 void (*reinit)(void *codec);
97 void (*setvolume)(void *codec, int dir, unsigned int left, unsigned int right);
98 void (*setrate)(void *codec, int which, int rate);
101 /* system configuration information */
104 u_int16_t subvendor, subdevice;
105 u_int8_t scfg, acl, i2s, spdif;
106 u_int8_t gpiomask, gpiostate, gpiodir;
107 u_int8_t cdti, cclk, cs, cif, type;
109 struct codec_entry *codec;
112 /* device private data */
117 /* Control/Status registor */
121 bus_space_handle_t csh;
123 struct resource *ddma;
125 bus_space_tag_t ddmat;
126 bus_space_handle_t ddmah;
127 /* Consumer Section DMA Channel Registers */
131 bus_space_handle_t dsh;
132 /* MultiTrack registor */
136 bus_space_handle_t mth;
140 struct resource *irq;
144 /* system configuration data */
145 struct cfg_info *cfg;
147 /* ADC/DAC number and info */
149 void *adc[4], *dac[4];
151 /* mixer control data */
153 u_int8_t left[ENVY24_CHAN_NUM];
154 u_int8_t right[ENVY24_CHAN_NUM];
156 /* Play/Record DMA fifo */
159 u_int32_t psize, rsize; /* DMA buffer size(byte) */
160 u_int16_t blk[2]; /* transfer check blocksize(dword) */
161 bus_dmamap_t pmap, rmap;
167 struct pcmchan_caps caps[2];
169 /* channel info table */
171 struct sc_chinfo chan[11];
174 /* -------------------------------------------------------------------- */
181 static void envy24_p8u(struct sc_chinfo *);
182 static void envy24_p16sl(struct sc_chinfo *);
183 static void envy24_p32sl(struct sc_chinfo *);
184 static void envy24_r16sl(struct sc_chinfo *);
185 static void envy24_r32sl(struct sc_chinfo *);
187 /* channel interface */
188 static void *envy24chan_init(kobj_t, void *, struct snd_dbuf *, struct pcm_channel *, int);
189 static int envy24chan_setformat(kobj_t, void *, u_int32_t);
190 static int envy24chan_setspeed(kobj_t, void *, u_int32_t);
191 static int envy24chan_setblocksize(kobj_t, void *, u_int32_t);
192 static int envy24chan_trigger(kobj_t, void *, int);
193 static int envy24chan_getptr(kobj_t, void *);
194 static struct pcmchan_caps *envy24chan_getcaps(kobj_t, void *);
196 /* mixer interface */
197 static int envy24mixer_init(struct snd_mixer *);
198 static int envy24mixer_reinit(struct snd_mixer *);
199 static int envy24mixer_uninit(struct snd_mixer *);
200 static int envy24mixer_set(struct snd_mixer *, unsigned, unsigned, unsigned);
201 static u_int32_t envy24mixer_setrecsrc(struct snd_mixer *, u_int32_t);
203 /* M-Audio Delta series AK4524 access interface */
204 static void *envy24_delta_ak4524_create(device_t, void *, int, int);
205 static void envy24_delta_ak4524_destroy(void *);
206 static void envy24_delta_ak4524_init(void *);
207 static void envy24_delta_ak4524_reinit(void *);
208 static void envy24_delta_ak4524_setvolume(void *, int, unsigned int, unsigned int);
210 /* -------------------------------------------------------------------- */
213 system constant tables
216 /* API -> hardware channel map */
217 static unsigned envy24_chanmap[ENVY24_CHAN_NUM] = {
218 ENVY24_CHAN_PLAY_SPDIF, /* 0 */
219 ENVY24_CHAN_PLAY_DAC1, /* 1 */
220 ENVY24_CHAN_PLAY_DAC2, /* 2 */
221 ENVY24_CHAN_PLAY_DAC3, /* 3 */
222 ENVY24_CHAN_PLAY_DAC4, /* 4 */
223 ENVY24_CHAN_REC_MIX, /* 5 */
224 ENVY24_CHAN_REC_SPDIF, /* 6 */
225 ENVY24_CHAN_REC_ADC1, /* 7 */
226 ENVY24_CHAN_REC_ADC2, /* 8 */
227 ENVY24_CHAN_REC_ADC3, /* 9 */
228 ENVY24_CHAN_REC_ADC4, /* 10 */
231 /* mixer -> API channel map. see above */
232 static int envy24_mixmap[] = {
233 -1, /* Master output level. It is depend on codec support */
234 -1, /* Treble level of all output channels */
235 -1, /* Bass level of all output channels */
236 -1, /* Volume of synthesier input */
237 0, /* Output level for the audio device */
238 -1, /* Output level for the PC speaker */
239 7, /* line in jack */
240 -1, /* microphone jack */
241 -1, /* CD audio input */
242 -1, /* Recording monitor */
243 1, /* alternative codec */
244 -1, /* global recording level */
246 -1, /* Output gain */
247 8, /* Input source 1 */
248 9, /* Input source 2 */
249 10, /* Input source 3 */
250 6, /* Digital (input) 1 */
251 -1, /* Digital (input) 2 */
252 -1, /* Digital (input) 3 */
253 -1, /* Phone input */
254 -1, /* Phone output */
255 -1, /* Video/TV (audio) in */
257 -1, /* Monitor volume */
260 /* variable rate audio */
261 static u_int32_t envy24_speed[] = {
262 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000,
263 12000, 11025, 9600, 8000, 0
266 /* known boards configuration */
267 static struct codec_entry delta_codec = {
268 envy24_delta_ak4524_create,
269 envy24_delta_ak4524_destroy,
270 envy24_delta_ak4524_init,
271 envy24_delta_ak4524_reinit,
272 envy24_delta_ak4524_setvolume,
276 static struct cfg_info cfg_table[] = {
278 "Envy24 audio (M Audio Delta Dio 2496)",
280 0x10, 0x80, 0xf0, 0x03,
282 0x10, 0x20, 0x40, 0x00, 0x00,
287 "Envy24 audio (Terratec DMX 6fire)",
289 0x2f, 0x80, 0xf0, 0x03,
291 0x10, 0x20, 0x01, 0x01, 0x00,
296 "Envy24 audio (M Audio Audiophile 2496)",
298 0x10, 0x80, 0x72, 0x03,
300 0x08, 0x02, 0x20, 0x00, 0x01,
305 "Envy24 audio (Generic)",
307 0x0f, 0x00, 0x01, 0x03,
309 0x10, 0x20, 0x40, 0x00, 0x00,
311 &delta_codec, /* default codec routines */
315 static u_int32_t envy24_recfmt[] = {
316 AFMT_STEREO | AFMT_S16_LE,
317 AFMT_STEREO | AFMT_S32_LE,
320 static struct pcmchan_caps envy24_reccaps = {8000, 96000, envy24_recfmt, 0};
322 static u_int32_t envy24_playfmt[] = {
323 AFMT_STEREO | AFMT_U8,
324 AFMT_STEREO | AFMT_S16_LE,
325 AFMT_STEREO | AFMT_S32_LE,
329 static struct pcmchan_caps envy24_playcaps = {8000, 96000, envy24_playfmt, 0};
331 struct envy24_emldma {
333 void (*emldma)(struct sc_chinfo *);
337 static struct envy24_emldma envy24_pemltab[] = {
338 {AFMT_STEREO | AFMT_U8, envy24_p8u, 2},
339 {AFMT_STEREO | AFMT_S16_LE, envy24_p16sl, 4},
340 {AFMT_STEREO | AFMT_S32_LE, envy24_p32sl, 8},
344 static struct envy24_emldma envy24_remltab[] = {
345 {AFMT_STEREO | AFMT_S16_LE, envy24_r16sl, 4},
346 {AFMT_STEREO | AFMT_S32_LE, envy24_r32sl, 8},
350 /* -------------------------------------------------------------------- */
352 /* common routines */
354 envy24_rdcs(struct sc_info *sc, int regno, int size)
358 return bus_space_read_1(sc->cst, sc->csh, regno);
360 return bus_space_read_2(sc->cst, sc->csh, regno);
362 return bus_space_read_4(sc->cst, sc->csh, regno);
369 envy24_wrcs(struct sc_info *sc, int regno, u_int32_t data, int size)
373 bus_space_write_1(sc->cst, sc->csh, regno, data);
376 bus_space_write_2(sc->cst, sc->csh, regno, data);
379 bus_space_write_4(sc->cst, sc->csh, regno, data);
385 envy24_rdmt(struct sc_info *sc, int regno, int size)
389 return bus_space_read_1(sc->mtt, sc->mth, regno);
391 return bus_space_read_2(sc->mtt, sc->mth, regno);
393 return bus_space_read_4(sc->mtt, sc->mth, regno);
400 envy24_wrmt(struct sc_info *sc, int regno, u_int32_t data, int size)
404 bus_space_write_1(sc->mtt, sc->mth, regno, data);
407 bus_space_write_2(sc->mtt, sc->mth, regno, data);
410 bus_space_write_4(sc->mtt, sc->mth, regno, data);
416 envy24_rdci(struct sc_info *sc, int regno)
418 envy24_wrcs(sc, ENVY24_CCS_INDEX, regno, 1);
419 return envy24_rdcs(sc, ENVY24_CCS_DATA, 1);
423 envy24_wrci(struct sc_info *sc, int regno, u_int32_t data)
425 envy24_wrcs(sc, ENVY24_CCS_INDEX, regno, 1);
426 envy24_wrcs(sc, ENVY24_CCS_DATA, data, 1);
429 /* -------------------------------------------------------------------- */
431 /* I2C port/E2PROM access routines */
434 envy24_rdi2c(struct sc_info *sc, u_int32_t dev, u_int32_t addr)
440 device_printf(sc->dev, "envy24_rdi2c(sc, 0x%02x, 0x%02x)\n", dev, addr);
442 for (i = 0; i < ENVY24_TIMEOUT; i++) {
443 data = envy24_rdcs(sc, ENVY24_CCS_I2CSTAT, 1);
444 if ((data & ENVY24_CCS_I2CSTAT_BSY) == 0)
446 DELAY(32); /* 31.25kHz */
448 if (i == ENVY24_TIMEOUT) {
451 envy24_wrcs(sc, ENVY24_CCS_I2CADDR, addr, 1);
452 envy24_wrcs(sc, ENVY24_CCS_I2CDEV,
453 (dev & ENVY24_CCS_I2CDEV_ADDR) | ENVY24_CCS_I2CDEV_RD, 1);
454 for (i = 0; i < ENVY24_TIMEOUT; i++) {
455 data = envy24_rdcs(sc, ENVY24_CCS_I2CSTAT, 1);
456 if ((data & ENVY24_CCS_I2CSTAT_BSY) == 0)
458 DELAY(32); /* 31.25kHz */
460 if (i == ENVY24_TIMEOUT) {
463 data = envy24_rdcs(sc, ENVY24_CCS_I2CDATA, 1);
466 device_printf(sc->dev, "envy24_rdi2c(): return 0x%x\n", data);
473 envy24_wri2c(struct sc_info *sc, u_int32_t dev, u_int32_t addr, u_int32_t data)
479 device_printf(sc->dev, "envy24_rdi2c(sc, 0x%02x, 0x%02x)\n", dev, addr);
481 for (i = 0; i < ENVY24_TIMEOUT; i++) {
482 tmp = envy24_rdcs(sc, ENVY24_CCS_I2CSTAT, 1);
483 if ((tmp & ENVY24_CCS_I2CSTAT_BSY) == 0)
485 DELAY(32); /* 31.25kHz */
487 if (i == ENVY24_TIMEOUT) {
490 envy24_wrcs(sc, ENVY24_CCS_I2CADDR, addr, 1);
491 envy24_wrcs(sc, ENVY24_CCS_I2CDATA, data, 1);
492 envy24_wrcs(sc, ENVY24_CCS_I2CDEV,
493 (dev & ENVY24_CCS_I2CDEV_ADDR) | ENVY24_CCS_I2CDEV_WR, 1);
494 for (i = 0; i < ENVY24_TIMEOUT; i++) {
495 data = envy24_rdcs(sc, ENVY24_CCS_I2CSTAT, 1);
496 if ((data & ENVY24_CCS_I2CSTAT_BSY) == 0)
498 DELAY(32); /* 31.25kHz */
500 if (i == ENVY24_TIMEOUT) {
509 envy24_rdrom(struct sc_info *sc, u_int32_t addr)
514 device_printf(sc->dev, "envy24_rdrom(sc, 0x%02x)\n", addr);
516 data = envy24_rdcs(sc, ENVY24_CCS_I2CSTAT, 1);
517 if ((data & ENVY24_CCS_I2CSTAT_ROM) == 0) {
519 device_printf(sc->dev, "envy24_rdrom(): E2PROM not presented\n");
524 return envy24_rdi2c(sc, ENVY24_CCS_I2CDEV_ROM, addr);
527 static struct cfg_info *
528 envy24_rom2cfg(struct sc_info *sc)
530 struct cfg_info *buff;
535 device_printf(sc->dev, "envy24_rom2cfg(sc)\n");
537 size = envy24_rdrom(sc, ENVY24_E2PROM_SIZE);
538 if (size < ENVY24_E2PROM_GPIODIR + 1) {
540 device_printf(sc->dev, "envy24_rom2cfg(): ENVY24_E2PROM_SIZE-->%d\n", size);
544 buff = malloc(sizeof(*buff), M_ENVY24, M_NOWAIT);
547 device_printf(sc->dev, "envy24_rom2cfg(): malloc()\n");
553 buff->subvendor = envy24_rdrom(sc, ENVY24_E2PROM_SUBVENDOR) << 8;
554 buff->subvendor += envy24_rdrom(sc, ENVY24_E2PROM_SUBVENDOR + 1);
555 buff->subdevice = envy24_rdrom(sc, ENVY24_E2PROM_SUBDEVICE) << 8;
556 buff->subdevice += envy24_rdrom(sc, ENVY24_E2PROM_SUBDEVICE + 1);
557 buff->scfg = envy24_rdrom(sc, ENVY24_E2PROM_SCFG);
558 buff->acl = envy24_rdrom(sc, ENVY24_E2PROM_ACL);
559 buff->i2s = envy24_rdrom(sc, ENVY24_E2PROM_I2S);
560 buff->spdif = envy24_rdrom(sc, ENVY24_E2PROM_SPDIF);
561 buff->gpiomask = envy24_rdrom(sc, ENVY24_E2PROM_GPIOMASK);
562 buff->gpiostate = envy24_rdrom(sc, ENVY24_E2PROM_GPIOSTATE);
563 buff->gpiodir = envy24_rdrom(sc, ENVY24_E2PROM_GPIODIR);
565 for (i = 0; cfg_table[i].subvendor != 0 || cfg_table[i].subdevice != 0; i++)
566 if (cfg_table[i].subvendor == buff->subvendor &&
567 cfg_table[i].subdevice == buff->subdevice)
569 buff->name = cfg_table[i].name;
570 buff->codec = cfg_table[i].codec;
576 envy24_cfgfree(struct cfg_info *cfg) {
584 /* -------------------------------------------------------------------- */
586 /* AC'97 codec access routines */
590 envy24_coldcd(struct sc_info *sc)
596 device_printf(sc->dev, "envy24_coldcd()\n");
598 envy24_wrmt(sc, ENVY24_MT_AC97CMD, ENVY24_MT_AC97CMD_CLD, 1);
600 envy24_wrmt(sc, ENVY24_MT_AC97CMD, 0, 1);
602 for (i = 0; i < ENVY24_TIMEOUT; i++) {
603 data = envy24_rdmt(sc, ENVY24_MT_AC97CMD, 1);
604 if (data & ENVY24_MT_AC97CMD_RDY) {
614 envy24_slavecd(struct sc_info *sc)
620 device_printf(sc->dev, "envy24_slavecd()\n");
622 envy24_wrmt(sc, ENVY24_MT_AC97CMD,
623 ENVY24_MT_AC97CMD_CLD | ENVY24_MT_AC97CMD_WRM, 1);
625 envy24_wrmt(sc, ENVY24_MT_AC97CMD, 0, 1);
627 for (i = 0; i < ENVY24_TIMEOUT; i++) {
628 data = envy24_rdmt(sc, ENVY24_MT_AC97CMD, 1);
629 if (data & ENVY24_MT_AC97CMD_RDY) {
639 envy24_rdcd(kobj_t obj, void *devinfo, int regno)
641 struct sc_info *sc = (struct sc_info *)devinfo;
646 device_printf(sc->dev, "envy24_rdcd(obj, sc, 0x%02x)\n", regno);
648 envy24_wrmt(sc, ENVY24_MT_AC97IDX, (u_int32_t)regno, 1);
649 envy24_wrmt(sc, ENVY24_MT_AC97CMD, ENVY24_MT_AC97CMD_RD, 1);
650 for (i = 0; i < ENVY24_TIMEOUT; i++) {
651 data = envy24_rdmt(sc, ENVY24_MT_AC97CMD, 1);
652 if ((data & ENVY24_MT_AC97CMD_RD) == 0)
655 data = envy24_rdmt(sc, ENVY24_MT_AC97DLO, 2);
658 device_printf(sc->dev, "envy24_rdcd(): return 0x%x\n", data);
664 envy24_wrcd(kobj_t obj, void *devinfo, int regno, u_int16_t data)
666 struct sc_info *sc = (struct sc_info *)devinfo;
671 device_printf(sc->dev, "envy24_wrcd(obj, sc, 0x%02x, 0x%04x)\n", regno, data);
673 envy24_wrmt(sc, ENVY24_MT_AC97IDX, (u_int32_t)regno, 1);
674 envy24_wrmt(sc, ENVY24_MT_AC97DLO, (u_int32_t)data, 2);
675 envy24_wrmt(sc, ENVY24_MT_AC97CMD, ENVY24_MT_AC97CMD_WR, 1);
676 for (i = 0; i < ENVY24_TIMEOUT; i++) {
677 cmd = envy24_rdmt(sc, ENVY24_MT_AC97CMD, 1);
678 if ((cmd & ENVY24_MT_AC97CMD_WR) == 0)
685 static kobj_method_t envy24_ac97_methods[] = {
686 KOBJMETHOD(ac97_read, envy24_rdcd),
687 KOBJMETHOD(ac97_write, envy24_wrcd),
690 AC97_DECLARE(envy24_ac97);
693 /* -------------------------------------------------------------------- */
695 /* GPIO access routines */
698 envy24_gpiord(struct sc_info *sc)
700 return envy24_rdci(sc, ENVY24_CCI_GPIODAT);
704 envy24_gpiowr(struct sc_info *sc, u_int32_t data)
707 device_printf(sc->dev, "envy24_gpiowr(sc, 0x%02x)\n", data & 0xff);
710 envy24_wrci(sc, ENVY24_CCI_GPIODAT, data);
716 envy24_gpiogetmask(struct sc_info *sc)
718 return envy24_rdci(sc, ENVY24_CCI_GPIOMASK);
723 envy24_gpiosetmask(struct sc_info *sc, u_int32_t mask)
725 envy24_wrci(sc, ENVY24_CCI_GPIOMASK, mask);
731 envy24_gpiogetdir(struct sc_info *sc)
733 return envy24_rdci(sc, ENVY24_CCI_GPIOCTL);
738 envy24_gpiosetdir(struct sc_info *sc, u_int32_t dir)
740 envy24_wrci(sc, ENVY24_CCI_GPIOCTL, dir);
744 /* -------------------------------------------------------------------- */
746 /* Envy24 I2C through GPIO bit-banging */
748 struct envy24_delta_ak4524_codec {
749 struct spicds_info *info;
750 struct sc_info *parent;
757 envy24_gpio_i2c_ctl(void *codec, unsigned int scl, unsigned int sda)
760 struct envy24_delta_ak4524_codec *ptr = codec;
762 device_printf(ptr->parent->dev, "--> %d, %d\n", scl, sda);
764 data = envy24_gpiord(ptr->parent);
765 data &= ~(SDA_GPIO | SCL_GPIO);
766 if (scl) data += SCL_GPIO;
767 if (sda) data += SDA_GPIO;
768 envy24_gpiowr(ptr->parent, data);
773 i2c_wrbit(void *codec, void (*ctrl)(void*, unsigned int, unsigned int), int bit)
775 struct envy24_delta_ak4524_codec *ptr = codec;
792 i2c_start(void *codec, void (*ctrl)(void*, unsigned int, unsigned int))
794 struct envy24_delta_ak4524_codec *ptr = codec;
805 i2c_stop(void *codec, void (*ctrl)(void*, unsigned int, unsigned int))
807 struct envy24_delta_ak4524_codec *ptr = codec;
818 i2c_ack(void *codec, void (*ctrl)(void*, unsigned int, unsigned int))
820 struct envy24_delta_ak4524_codec *ptr = codec;
826 /* dummy, need routine to change gpio direction */
832 i2c_wr(void *codec, void (*ctrl)(void*, unsigned int, unsigned int), u_int32_t dev, int reg, u_int8_t val)
834 struct envy24_delta_ak4524_codec *ptr = codec;
837 i2c_start(ptr, ctrl);
839 for (mask = 0x80; mask != 0; mask >>= 1)
840 i2c_wrbit(ptr, ctrl, dev & mask);
844 for (mask = 0x80; mask != 0; mask >>= 1)
845 i2c_wrbit(ptr, ctrl, reg & mask);
849 for (mask = 0x80; mask != 0; mask >>= 1)
850 i2c_wrbit(ptr, ctrl, val & mask);
856 /* -------------------------------------------------------------------- */
858 /* M-Audio Delta series AK4524 access interface routine */
861 envy24_delta_ak4524_ctl(void *codec, unsigned int cs, unsigned int cclk, unsigned int cdti)
864 struct envy24_delta_ak4524_codec *ptr = codec;
867 device_printf(ptr->parent->dev, "--> %d, %d, %d\n", cs, cclk, cdti);
869 data = envy24_gpiord(ptr->parent);
870 data &= ~(ptr->cs | ptr->cclk | ptr->cdti);
871 if (cs) data += ptr->cs;
872 if (cclk) data += ptr->cclk;
873 if (cdti) data += ptr->cdti;
874 envy24_gpiowr(ptr->parent, data);
879 envy24_delta_ak4524_create(device_t dev, void *info, int dir, int num)
881 struct sc_info *sc = info;
882 struct envy24_delta_ak4524_codec *buff = NULL;
885 device_printf(sc->dev, "envy24_delta_ak4524_create(dev, sc, %d, %d)\n", dir, num);
888 buff = malloc(sizeof(*buff), M_ENVY24, M_NOWAIT);
892 if (dir == PCMDIR_REC && sc->adc[num] != NULL)
893 buff->info = ((struct envy24_delta_ak4524_codec *)sc->adc[num])->info;
894 else if (dir == PCMDIR_PLAY && sc->dac[num] != NULL)
895 buff->info = ((struct envy24_delta_ak4524_codec *)sc->dac[num])->info;
897 buff->info = spicds_create(dev, buff, num, envy24_delta_ak4524_ctl);
898 if (buff->info == NULL) {
899 free(buff, M_ENVY24);
911 envy24_delta_ak4524_destroy(void *codec)
913 struct envy24_delta_ak4524_codec *ptr = codec;
917 device_printf(ptr->parent->dev, "envy24_delta_ak4524_destroy()\n");
920 if (ptr->dir == PCMDIR_PLAY) {
921 if (ptr->parent->dac[ptr->num] != NULL)
922 spicds_destroy(ptr->info);
925 if (ptr->parent->adc[ptr->num] != NULL)
926 spicds_destroy(ptr->info);
929 free(codec, M_ENVY24);
933 envy24_delta_ak4524_init(void *codec)
936 u_int32_t gpiomask, gpiodir;
938 struct envy24_delta_ak4524_codec *ptr = codec;
942 device_printf(ptr->parent->dev, "envy24_delta_ak4524_init()\n");
946 gpiomask = envy24_gpiogetmask(ptr->parent);
947 gpiomask &= ~(ENVY24_GPIO_AK4524_CDTI | ENVY24_GPIO_AK4524_CCLK | ENVY24_GPIO_AK4524_CS0 | ENVY24_GPIO_AK4524_CS1);
948 envy24_gpiosetmask(ptr->parent, gpiomask);
949 gpiodir = envy24_gpiogetdir(ptr->parent);
950 gpiodir |= ENVY24_GPIO_AK4524_CDTI | ENVY24_GPIO_AK4524_CCLK | ENVY24_GPIO_AK4524_CS0 | ENVY24_GPIO_AK4524_CS1;
951 envy24_gpiosetdir(ptr->parent, gpiodir);
953 ptr->cs = ptr->parent->cfg->cs;
955 envy24_gpiosetmask(ptr->parent, ENVY24_GPIO_CS8414_STATUS);
956 envy24_gpiosetdir(ptr->parent, ~ENVY24_GPIO_CS8414_STATUS);
958 ptr->cs = ENVY24_GPIO_AK4524_CS0;
960 ptr->cs = ENVY24_GPIO_AK4524_CS1;
961 ptr->cclk = ENVY24_GPIO_AK4524_CCLK;
963 ptr->cclk = ptr->parent->cfg->cclk;
964 ptr->cdti = ptr->parent->cfg->cdti;
965 spicds_settype(ptr->info, ptr->parent->cfg->type);
966 spicds_setcif(ptr->info, ptr->parent->cfg->cif);
967 spicds_setformat(ptr->info,
968 AK452X_FORMAT_I2S | AK452X_FORMAT_256FSN | AK452X_FORMAT_1X);
969 spicds_setdvc(ptr->info, AK452X_DVC_DEMOFF);
970 /* for the time being, init only first codec */
972 spicds_init(ptr->info);
974 /* 6fire rear input init test, set ptr->num to 1 for test */
975 if (ptr->parent->cfg->subvendor == 0x153b && \
976 ptr->parent->cfg->subdevice == 0x1138 && ptr->num == 100) {
978 spicds_init(ptr->info);
979 device_printf(ptr->parent->dev, "6fire rear input init\n");
980 i2c_wr(ptr, envy24_gpio_i2c_ctl, \
981 PCA9554_I2CDEV, PCA9554_DIR, 0x80);
982 i2c_wr(ptr, envy24_gpio_i2c_ctl, \
983 PCA9554_I2CDEV, PCA9554_OUT, 0x02);
988 envy24_delta_ak4524_reinit(void *codec)
990 struct envy24_delta_ak4524_codec *ptr = codec;
994 device_printf(ptr->parent->dev, "envy24_delta_ak4524_reinit()\n");
997 spicds_reinit(ptr->info);
1001 envy24_delta_ak4524_setvolume(void *codec, int dir, unsigned int left, unsigned int right)
1003 struct envy24_delta_ak4524_codec *ptr = codec;
1007 device_printf(ptr->parent->dev, "envy24_delta_ak4524_set()\n");
1010 spicds_set(ptr->info, dir, left, right);
1014 There is no need for AK452[48] codec to set sample rate
1016 envy24_delta_ak4524_setrate(struct envy24_delta_ak4524_codec *codec, int which, int rate)
1021 /* -------------------------------------------------------------------- */
1023 /* hardware access routeines */
1028 } envy24_speedtab[] = {
1029 {48000, ENVY24_MT_RATE_48000},
1030 {24000, ENVY24_MT_RATE_24000},
1031 {12000, ENVY24_MT_RATE_12000},
1032 {9600, ENVY24_MT_RATE_9600},
1033 {32000, ENVY24_MT_RATE_32000},
1034 {16000, ENVY24_MT_RATE_16000},
1035 {8000, ENVY24_MT_RATE_8000},
1036 {96000, ENVY24_MT_RATE_96000},
1037 {64000, ENVY24_MT_RATE_64000},
1038 {44100, ENVY24_MT_RATE_44100},
1039 {22050, ENVY24_MT_RATE_22050},
1040 {11025, ENVY24_MT_RATE_11025},
1041 {88200, ENVY24_MT_RATE_88200},
1046 envy24_setspeed(struct sc_info *sc, u_int32_t speed) {
1051 device_printf(sc->dev, "envy24_setspeed(sc, %d)\n", speed);
1054 code = ENVY24_MT_RATE_SPDIF; /* external master clock */
1058 for (i = 0; envy24_speedtab[i].speed != 0; i++) {
1059 if (envy24_speedtab[i].speed == speed)
1062 code = envy24_speedtab[i].code;
1065 device_printf(sc->dev, "envy24_setspeed(): speed %d/code 0x%04x\n", envy24_speedtab[i].speed, code);
1068 envy24_wrmt(sc, ENVY24_MT_RATE, code, 1);
1069 code = envy24_rdmt(sc, ENVY24_MT_RATE, 1);
1070 code &= ENVY24_MT_RATE_MASK;
1071 for (i = 0; envy24_speedtab[i].code < 0x10; i++) {
1072 if (envy24_speedtab[i].code == code)
1075 speed = envy24_speedtab[i].speed;
1081 device_printf(sc->dev, "envy24_setspeed(): return %d\n", speed);
1087 envy24_setvolume(struct sc_info *sc, unsigned ch)
1090 device_printf(sc->dev, "envy24_setvolume(sc, %d)\n", ch);
1092 if (sc->cfg->subvendor==0x153b && sc->cfg->subdevice==0x1138 ) {
1093 envy24_wrmt(sc, ENVY24_MT_VOLIDX, 16, 1);
1094 envy24_wrmt(sc, ENVY24_MT_VOLUME, 0x7f7f, 2);
1095 envy24_wrmt(sc, ENVY24_MT_VOLIDX, 17, 1);
1096 envy24_wrmt(sc, ENVY24_MT_VOLUME, 0x7f7f, 2);
1099 envy24_wrmt(sc, ENVY24_MT_VOLIDX, ch * 2, 1);
1100 envy24_wrmt(sc, ENVY24_MT_VOLUME, 0x7f00 | sc->left[ch], 2);
1101 envy24_wrmt(sc, ENVY24_MT_VOLIDX, ch * 2 + 1, 1);
1102 envy24_wrmt(sc, ENVY24_MT_VOLUME, (sc->right[ch] << 8) | 0x7f, 2);
1106 envy24_mutevolume(struct sc_info *sc, unsigned ch)
1111 device_printf(sc->dev, "envy24_mutevolume(sc, %d)\n", ch);
1113 vol = ENVY24_VOL_MUTE << 8 | ENVY24_VOL_MUTE;
1114 envy24_wrmt(sc, ENVY24_MT_VOLIDX, ch * 2, 1);
1115 envy24_wrmt(sc, ENVY24_MT_VOLUME, vol, 2);
1116 envy24_wrmt(sc, ENVY24_MT_VOLIDX, ch * 2 + 1, 1);
1117 envy24_wrmt(sc, ENVY24_MT_VOLUME, vol, 2);
1121 envy24_gethwptr(struct sc_info *sc, int dir)
1127 device_printf(sc->dev, "envy24_gethwptr(sc, %d)\n", dir);
1129 if (dir == PCMDIR_PLAY) {
1130 rtn = sc->psize / 4;
1131 unit = ENVY24_PLAY_BUFUNIT / 4;
1132 regno = ENVY24_MT_PCNT;
1135 rtn = sc->rsize / 4;
1136 unit = ENVY24_REC_BUFUNIT / 4;
1137 regno = ENVY24_MT_RCNT;
1140 ptr = envy24_rdmt(sc, regno, 2);
1145 device_printf(sc->dev, "envy24_gethwptr(): return %d\n", rtn);
1151 envy24_updintr(struct sc_info *sc, int dir)
1153 int regptr, regintr;
1154 u_int32_t mask, intr;
1155 u_int32_t ptr, size, cnt;
1159 device_printf(sc->dev, "envy24_updintr(sc, %d)\n", dir);
1161 if (dir == PCMDIR_PLAY) {
1163 size = sc->psize / 4;
1164 regptr = ENVY24_MT_PCNT;
1165 regintr = ENVY24_MT_PTERM;
1166 mask = ~ENVY24_MT_INT_PMASK;
1170 size = sc->rsize / 4;
1171 regptr = ENVY24_MT_RCNT;
1172 regintr = ENVY24_MT_RTERM;
1173 mask = ~ENVY24_MT_INT_RMASK;
1176 ptr = size - envy24_rdmt(sc, regptr, 2) - 1;
1178 cnt = blk - ptr % blk - 1;
1184 device_printf(sc->dev, "envy24_updintr():ptr = %d, blk = %d, cnt = %d\n", ptr, blk, cnt);
1186 envy24_wrmt(sc, regintr, cnt, 2);
1187 intr = envy24_rdmt(sc, ENVY24_MT_INT, 1);
1189 device_printf(sc->dev, "envy24_updintr():intr = 0x%02x, mask = 0x%02x\n", intr, mask);
1191 envy24_wrmt(sc, ENVY24_MT_INT, intr & mask, 1);
1193 device_printf(sc->dev, "envy24_updintr():INT-->0x%02x\n",
1194 envy24_rdmt(sc, ENVY24_MT_INT, 1));
1202 envy24_maskintr(struct sc_info *sc, int dir)
1204 u_int32_t mask, intr;
1207 device_printf(sc->dev, "envy24_maskintr(sc, %d)\n", dir);
1209 if (dir == PCMDIR_PLAY)
1210 mask = ENVY24_MT_INT_PMASK;
1212 mask = ENVY24_MT_INT_RMASK;
1213 intr = envy24_rdmt(sc, ENVY24_MT_INT, 1);
1214 envy24_wrmt(sc, ENVY24_MT_INT, intr | mask, 1);
1221 envy24_checkintr(struct sc_info *sc, int dir)
1223 u_int32_t mask, stat, intr, rtn;
1226 device_printf(sc->dev, "envy24_checkintr(sc, %d)\n", dir);
1228 intr = envy24_rdmt(sc, ENVY24_MT_INT, 1);
1229 if (dir == PCMDIR_PLAY) {
1230 if ((rtn = intr & ENVY24_MT_INT_PSTAT) != 0) {
1231 mask = ~ENVY24_MT_INT_RSTAT;
1232 stat = ENVY24_MT_INT_PSTAT | ENVY24_MT_INT_PMASK;
1233 envy24_wrmt(sc, ENVY24_MT_INT, (intr & mask) | stat, 1);
1237 if ((rtn = intr & ENVY24_MT_INT_RSTAT) != 0) {
1238 mask = ~ENVY24_MT_INT_PSTAT;
1239 stat = ENVY24_MT_INT_RSTAT | ENVY24_MT_INT_RMASK;
1240 envy24_wrmt(sc, ENVY24_MT_INT, (intr & mask) | stat, 1);
1248 envy24_start(struct sc_info *sc, int dir)
1253 device_printf(sc->dev, "envy24_start(sc, %d)\n", dir);
1255 if (dir == PCMDIR_PLAY)
1256 sw = ENVY24_MT_PCTL_PSTART;
1258 sw = ENVY24_MT_PCTL_RSTART;
1260 stat = envy24_rdmt(sc, ENVY24_MT_PCTL, 1);
1261 envy24_wrmt(sc, ENVY24_MT_PCTL, stat | sw, 1);
1264 device_printf(sc->dev, "PADDR:0x%08x\n", envy24_rdmt(sc, ENVY24_MT_PADDR, 4));
1265 device_printf(sc->dev, "PCNT:%ld\n", envy24_rdmt(sc, ENVY24_MT_PCNT, 2));
1272 envy24_stop(struct sc_info *sc, int dir)
1277 device_printf(sc->dev, "envy24_stop(sc, %d)\n", dir);
1279 if (dir == PCMDIR_PLAY)
1280 sw = ~ENVY24_MT_PCTL_PSTART;
1282 sw = ~ENVY24_MT_PCTL_RSTART;
1284 stat = envy24_rdmt(sc, ENVY24_MT_PCTL, 1);
1285 envy24_wrmt(sc, ENVY24_MT_PCTL, stat & sw, 1);
1291 envy24_route(struct sc_info *sc, int dac, int class, int adc, int rev)
1293 u_int32_t reg, mask;
1294 u_int32_t left, right;
1297 device_printf(sc->dev, "envy24_route(sc, %d, %d, %d, %d)\n",
1298 dac, class, adc, rev);
1300 /* parameter pattern check */
1301 if (dac < 0 || ENVY24_ROUTE_DAC_SPDIF < dac)
1303 if (class == ENVY24_ROUTE_CLASS_MIX &&
1304 (dac != ENVY24_ROUTE_DAC_1 && dac != ENVY24_ROUTE_DAC_SPDIF))
1307 left = ENVY24_ROUTE_RIGHT;
1308 right = ENVY24_ROUTE_LEFT;
1311 left = ENVY24_ROUTE_LEFT;
1312 right = ENVY24_ROUTE_RIGHT;
1315 if (dac == ENVY24_ROUTE_DAC_SPDIF) {
1316 reg = class | class << 2 |
1317 ((adc << 1 | left) | left << 3) << 8 |
1318 ((adc << 1 | right) | right << 3) << 12;
1320 device_printf(sc->dev, "envy24_route(): MT_SPDOUT-->0x%04x\n", reg);
1322 envy24_wrmt(sc, ENVY24_MT_SPDOUT, reg, 2);
1325 mask = ~(0x0303 << dac * 2);
1326 reg = envy24_rdmt(sc, ENVY24_MT_PSDOUT, 2);
1327 reg = (reg & mask) | ((class | class << 8) << dac * 2);
1329 device_printf(sc->dev, "envy24_route(): MT_PSDOUT-->0x%04x\n", reg);
1331 envy24_wrmt(sc, ENVY24_MT_PSDOUT, reg, 2);
1332 mask = ~(0xff << dac * 8);
1333 reg = envy24_rdmt(sc, ENVY24_MT_RECORD, 4);
1334 reg = (reg & mask) |
1335 (((adc << 1 | left) | left << 3) |
1336 ((adc << 1 | right) | right << 3) << 4) << dac * 8;
1338 device_printf(sc->dev, "envy24_route(): MT_RECORD-->0x%08x\n", reg);
1340 envy24_wrmt(sc, ENVY24_MT_RECORD, reg, 4);
1342 /* 6fire rear input init test */
1343 envy24_wrmt(sc, ENVY24_MT_RECORD, 0x00, 4);
1349 /* -------------------------------------------------------------------- */
1351 /* buffer copy routines */
1353 envy24_p32sl(struct sc_chinfo *ch)
1358 int src, dst, ssize, dsize, slot;
1361 length = sndbuf_getready(ch->buffer) / 8;
1362 dmabuf = ch->parent->pbuf;
1363 data = (u_int32_t *)ch->data;
1364 src = sndbuf_getreadyptr(ch->buffer) / 4;
1365 dst = src / 2 + ch->offset;
1366 ssize = ch->size / 4;
1367 dsize = ch->size / 8;
1370 for (i = 0; i < length; i++) {
1371 dmabuf[dst * ENVY24_PLAY_CHNUM + slot].buffer = data[src];
1372 dmabuf[dst * ENVY24_PLAY_CHNUM + slot + 1].buffer = data[src + 1];
1383 envy24_p16sl(struct sc_chinfo *ch)
1388 int src, dst, ssize, dsize, slot;
1392 device_printf(ch->parent->dev, "envy24_p16sl()\n");
1394 length = sndbuf_getready(ch->buffer) / 4;
1395 dmabuf = ch->parent->pbuf;
1396 data = (u_int16_t *)ch->data;
1397 src = sndbuf_getreadyptr(ch->buffer) / 2;
1398 dst = src / 2 + ch->offset;
1399 ssize = ch->size / 2;
1400 dsize = ch->size / 4;
1403 device_printf(ch->parent->dev, "envy24_p16sl():%lu-->%lu(%lu)\n", src, dst, length);
1406 for (i = 0; i < length; i++) {
1407 dmabuf[dst * ENVY24_PLAY_CHNUM + slot].buffer = (u_int32_t)data[src] << 16;
1408 dmabuf[dst * ENVY24_PLAY_CHNUM + slot + 1].buffer = (u_int32_t)data[src + 1] << 16;
1411 printf("%08x", dmabuf[dst * ENVY24_PLAY_CHNUM + slot]);
1412 printf("%08x", dmabuf[dst * ENVY24_PLAY_CHNUM + slot + 1]);
1428 envy24_p8u(struct sc_chinfo *ch)
1433 int src, dst, ssize, dsize, slot;
1436 length = sndbuf_getready(ch->buffer) / 2;
1437 dmabuf = ch->parent->pbuf;
1438 data = (u_int8_t *)ch->data;
1439 src = sndbuf_getreadyptr(ch->buffer);
1440 dst = src / 2 + ch->offset;
1442 dsize = ch->size / 4;
1445 for (i = 0; i < length; i++) {
1446 dmabuf[dst * ENVY24_PLAY_CHNUM + slot].buffer = ((u_int32_t)data[src] ^ 0x80) << 24;
1447 dmabuf[dst * ENVY24_PLAY_CHNUM + slot + 1].buffer = ((u_int32_t)data[src + 1] ^ 0x80) << 24;
1458 envy24_r32sl(struct sc_chinfo *ch)
1463 int src, dst, ssize, dsize, slot;
1466 length = sndbuf_getfree(ch->buffer) / 8;
1467 dmabuf = ch->parent->rbuf;
1468 data = (u_int32_t *)ch->data;
1469 dst = sndbuf_getfreeptr(ch->buffer) / 4;
1470 src = dst / 2 + ch->offset;
1471 dsize = ch->size / 4;
1472 ssize = ch->size / 8;
1473 slot = (ch->num - ENVY24_CHAN_REC_ADC1) * 2;
1475 for (i = 0; i < length; i++) {
1476 data[dst] = dmabuf[src * ENVY24_REC_CHNUM + slot].buffer;
1477 data[dst + 1] = dmabuf[src * ENVY24_REC_CHNUM + slot + 1].buffer;
1488 envy24_r16sl(struct sc_chinfo *ch)
1493 int src, dst, ssize, dsize, slot;
1496 length = sndbuf_getfree(ch->buffer) / 4;
1497 dmabuf = ch->parent->rbuf;
1498 data = (u_int16_t *)ch->data;
1499 dst = sndbuf_getfreeptr(ch->buffer) / 2;
1500 src = dst / 2 + ch->offset;
1501 dsize = ch->size / 2;
1502 ssize = ch->size / 8;
1503 slot = (ch->num - ENVY24_CHAN_REC_ADC1) * 2;
1505 for (i = 0; i < length; i++) {
1506 data[dst] = dmabuf[src * ENVY24_REC_CHNUM + slot].buffer;
1507 data[dst + 1] = dmabuf[src * ENVY24_REC_CHNUM + slot + 1].buffer;
1517 /* -------------------------------------------------------------------- */
1519 /* channel interface */
1521 envy24chan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir)
1523 struct sc_info *sc = (struct sc_info *)devinfo;
1524 struct sc_chinfo *ch;
1528 device_printf(sc->dev, "envy24chan_init(obj, devinfo, b, c, %d)\n", dir);
1530 snd_mtxlock(sc->lock);
1531 if ((sc->chnum > ENVY24_CHAN_PLAY_SPDIF && dir != PCMDIR_REC) ||
1532 (sc->chnum < ENVY24_CHAN_REC_ADC1 && dir != PCMDIR_PLAY)) {
1533 snd_mtxunlock(sc->lock);
1538 ch = &sc->chan[num];
1539 ch->size = 8 * ENVY24_SAMPLE_NUM;
1540 ch->data = malloc(ch->size, M_ENVY24, M_NOWAIT);
1541 if (ch->data == NULL) {
1550 /* set channel map */
1551 ch->num = envy24_chanmap[num];
1552 snd_mtxunlock(sc->lock);
1553 sndbuf_setup(ch->buffer, ch->data, ch->size);
1554 snd_mtxlock(sc->lock);
1555 /* these 2 values are dummy */
1559 snd_mtxunlock(sc->lock);
1565 envy24chan_free(kobj_t obj, void *data)
1567 struct sc_chinfo *ch = data;
1568 struct sc_info *sc = ch->parent;
1571 device_printf(sc->dev, "envy24chan_free()\n");
1573 snd_mtxlock(sc->lock);
1574 if (ch->data != NULL) {
1575 free(ch->data, M_ENVY24);
1578 snd_mtxunlock(sc->lock);
1584 envy24chan_setformat(kobj_t obj, void *data, u_int32_t format)
1586 struct sc_chinfo *ch = data;
1587 struct sc_info *sc = ch->parent;
1588 struct envy24_emldma *emltab;
1589 /* unsigned int bcnt, bsize; */
1593 device_printf(sc->dev, "envy24chan_setformat(obj, data, 0x%08x)\n", format);
1595 snd_mtxlock(sc->lock);
1596 /* check and get format related information */
1597 if (ch->dir == PCMDIR_PLAY)
1598 emltab = envy24_pemltab;
1600 emltab = envy24_remltab;
1601 if (emltab == NULL) {
1602 snd_mtxunlock(sc->lock);
1605 for (i = 0; emltab[i].format != 0; i++)
1606 if (emltab[i].format == format)
1608 if (emltab[i].format == 0) {
1609 snd_mtxunlock(sc->lock);
1613 /* set format information */
1614 ch->format = format;
1615 ch->emldma = emltab[i].emldma;
1616 if (ch->unit > emltab[i].unit)
1617 ch->blk *= ch->unit / emltab[i].unit;
1619 ch->blk /= emltab[i].unit / ch->unit;
1620 ch->unit = emltab[i].unit;
1622 /* set channel buffer information */
1623 ch->size = ch->unit * ENVY24_SAMPLE_NUM;
1625 if (ch->dir == PCMDIR_PLAY)
1626 bsize = ch->blk * 4 / ENVY24_PLAY_BUFUNIT;
1628 bsize = ch->blk * 4 / ENVY24_REC_BUFUNIT;
1630 bcnt = ch->size / bsize;
1631 sndbuf_resize(ch->buffer, bcnt, bsize);
1633 snd_mtxunlock(sc->lock);
1636 device_printf(sc->dev, "envy24chan_setformat(): return 0x%08x\n", 0);
1642 IMPLEMENT NOTICE: In this driver, setspeed function only do setting
1643 of speed information value. And real hardware speed setting is done
1644 at start triggered(see envy24chan_trigger()). So, at this function
1645 is called, any value that ENVY24 can use is able to set. But, at
1646 start triggerd, some other channel is running, and that channel's
1647 speed isn't same with, then trigger function will fail.
1650 envy24chan_setspeed(kobj_t obj, void *data, u_int32_t speed)
1652 struct sc_chinfo *ch = data;
1653 u_int32_t val, prev;
1657 device_printf(ch->parent->dev, "envy24chan_setspeed(obj, data, %d)\n", speed);
1660 for (i = 0; (val = envy24_speed[i]) != 0; i++) {
1661 if (abs(val - speed) < abs(prev - speed))
1669 device_printf(ch->parent->dev, "envy24chan_setspeed(): return %d\n", ch->speed);
1675 envy24chan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
1677 struct sc_chinfo *ch = data;
1678 /* struct sc_info *sc = ch->parent; */
1679 u_int32_t size, prev;
1680 unsigned int bcnt, bsize;
1683 device_printf(sc->dev, "envy24chan_setblocksize(obj, data, %d)\n", blocksize);
1686 /* snd_mtxlock(sc->lock); */
1687 for (size = ch->size / 2; size > 0; size /= 2) {
1688 if (abs(size - blocksize) < abs(prev - blocksize))
1694 ch->blk = prev / ch->unit;
1695 if (ch->dir == PCMDIR_PLAY)
1696 ch->blk *= ENVY24_PLAY_BUFUNIT / 4;
1698 ch->blk *= ENVY24_REC_BUFUNIT / 4;
1699 /* set channel buffer information */
1700 /* ch->size = ch->unit * ENVY24_SAMPLE_NUM; */
1701 if (ch->dir == PCMDIR_PLAY)
1702 bsize = ch->blk * 4 / ENVY24_PLAY_BUFUNIT;
1704 bsize = ch->blk * 4 / ENVY24_REC_BUFUNIT;
1706 bcnt = ch->size / bsize;
1707 sndbuf_resize(ch->buffer, bcnt, bsize);
1708 /* snd_mtxunlock(sc->lock); */
1711 device_printf(sc->dev, "envy24chan_setblocksize(): return %d\n", prev);
1716 /* semantic note: must start at beginning of buffer */
1718 envy24chan_trigger(kobj_t obj, void *data, int go)
1720 struct sc_chinfo *ch = data;
1721 struct sc_info *sc = ch->parent;
1727 device_printf(sc->dev, "envy24chan_trigger(obj, data, %d)\n", go);
1729 snd_mtxlock(sc->lock);
1730 if (ch->dir == PCMDIR_PLAY)
1737 device_printf(sc->dev, "envy24chan_trigger(): start\n");
1739 /* check or set channel speed */
1740 if (sc->run[0] == 0 && sc->run[1] == 0) {
1741 sc->speed = envy24_setspeed(sc, ch->speed);
1742 sc->caps[0].minspeed = sc->caps[0].maxspeed = sc->speed;
1743 sc->caps[1].minspeed = sc->caps[1].maxspeed = sc->speed;
1745 else if (ch->speed != 0 && ch->speed != sc->speed)
1748 ch->channel->speed = sc->speed;
1749 /* start or enable channel */
1751 if (sc->run[slot] == 1) {
1754 sc->blk[slot] = ch->blk;
1757 ptr = envy24_gethwptr(sc, ch->dir);
1758 ch->offset = ((ptr / ch->blk + 1) * ch->blk %
1759 (ch->size / 4)) * 4 / ch->unit;
1760 if (ch->blk < sc->blk[slot])
1761 sc->blk[slot] = ch->blk;
1763 if (ch->dir == PCMDIR_PLAY) {
1765 envy24_setvolume(sc, ch->num);
1767 envy24_updintr(sc, ch->dir);
1768 if (sc->run[slot] == 1)
1769 envy24_start(sc, ch->dir);
1772 case PCMTRIG_EMLDMAWR:
1774 device_printf(sc->dev, "envy24chan_trigger(): emldmawr\n");
1780 case PCMTRIG_EMLDMARD:
1782 device_printf(sc->dev, "envy24chan_trigger(): emldmard\n");
1791 device_printf(sc->dev, "envy24chan_trigger(): abort\n");
1795 if (ch->dir == PCMDIR_PLAY)
1796 envy24_mutevolume(sc, ch->num);
1797 if (sc->run[slot] == 0) {
1798 envy24_stop(sc, ch->dir);
1802 else if (ch->blk == sc->blk[slot]) {
1803 sc->blk[slot] = ENVY24_SAMPLE_NUM / 2;
1804 for (i = 0; i < ENVY24_CHAN_NUM; i++) {
1805 if (sc->chan[i].dir == ch->dir &&
1806 sc->chan[i].run == 1 &&
1807 sc->chan[i].blk < sc->blk[slot])
1808 sc->blk[slot] = sc->chan[i].blk;
1810 if (ch->blk != sc->blk[slot])
1811 envy24_updintr(sc, ch->dir);
1817 snd_mtxunlock(sc->lock);
1823 envy24chan_getptr(kobj_t obj, void *data)
1825 struct sc_chinfo *ch = data;
1826 struct sc_info *sc = ch->parent;
1831 device_printf(sc->dev, "envy24chan_getptr()\n");
1833 snd_mtxlock(sc->lock);
1834 ptr = envy24_gethwptr(sc, ch->dir);
1835 rtn = ptr * ch->unit;
1836 snd_mtxunlock(sc->lock);
1839 device_printf(sc->dev, "envy24chan_getptr(): return %d\n",
1845 static struct pcmchan_caps *
1846 envy24chan_getcaps(kobj_t obj, void *data)
1848 struct sc_chinfo *ch = data;
1849 struct sc_info *sc = ch->parent;
1850 struct pcmchan_caps *rtn;
1853 device_printf(sc->dev, "envy24chan_getcaps()\n");
1855 snd_mtxlock(sc->lock);
1856 if (ch->dir == PCMDIR_PLAY) {
1857 if (sc->run[0] == 0)
1858 rtn = &envy24_playcaps;
1863 if (sc->run[1] == 0)
1864 rtn = &envy24_reccaps;
1868 snd_mtxunlock(sc->lock);
1873 static kobj_method_t envy24chan_methods[] = {
1874 KOBJMETHOD(channel_init, envy24chan_init),
1875 KOBJMETHOD(channel_free, envy24chan_free),
1876 KOBJMETHOD(channel_setformat, envy24chan_setformat),
1877 KOBJMETHOD(channel_setspeed, envy24chan_setspeed),
1878 KOBJMETHOD(channel_setblocksize, envy24chan_setblocksize),
1879 KOBJMETHOD(channel_trigger, envy24chan_trigger),
1880 KOBJMETHOD(channel_getptr, envy24chan_getptr),
1881 KOBJMETHOD(channel_getcaps, envy24chan_getcaps),
1884 CHANNEL_DECLARE(envy24chan);
1886 /* -------------------------------------------------------------------- */
1888 /* mixer interface */
1891 envy24mixer_init(struct snd_mixer *m)
1893 struct sc_info *sc = mix_getdevinfo(m);
1896 device_printf(sc->dev, "envy24mixer_init()\n");
1901 /* set volume control rate */
1902 snd_mtxlock(sc->lock);
1903 envy24_wrmt(sc, ENVY24_MT_VOLRATE, 0x30, 1); /* 0x30 is default value */
1905 mix_setdevs(m, ENVY24_MIX_MASK);
1906 mix_setrecdevs(m, ENVY24_MIX_REC_MASK);
1907 snd_mtxunlock(sc->lock);
1913 envy24mixer_reinit(struct snd_mixer *m)
1915 struct sc_info *sc = mix_getdevinfo(m);
1920 device_printf(sc->dev, "envy24mixer_reinit()\n");
1927 envy24mixer_uninit(struct snd_mixer *m)
1929 struct sc_info *sc = mix_getdevinfo(m);
1934 device_printf(sc->dev, "envy24mixer_uninit()\n");
1941 envy24mixer_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right)
1943 struct sc_info *sc = mix_getdevinfo(m);
1944 int ch = envy24_mixmap[dev];
1950 if (dev == 0 && sc->cfg->codec->setvolume == NULL)
1952 if (dev != 0 && ch == -1)
1954 hwch = envy24_chanmap[ch];
1956 device_printf(sc->dev, "envy24mixer_set(m, %d, %d, %d)\n",
1960 snd_mtxlock(sc->lock);
1962 for (i = 0; i < sc->dacn; i++) {
1963 sc->cfg->codec->setvolume(sc->dac[i], PCMDIR_PLAY, left, right);
1967 /* set volume value for hardware */
1968 if ((sc->left[hwch] = 100 - left) > ENVY24_VOL_MIN)
1969 sc->left[hwch] = ENVY24_VOL_MUTE;
1970 if ((sc->right[hwch] = 100 - right) > ENVY24_VOL_MIN)
1971 sc->right[hwch] = ENVY24_VOL_MUTE;
1973 /* set volume for record channel and running play channel */
1974 if (hwch > ENVY24_CHAN_PLAY_SPDIF || sc->chan[ch].run)
1975 envy24_setvolume(sc, hwch);
1977 snd_mtxunlock(sc->lock);
1979 return right << 8 | left;
1983 envy24mixer_setrecsrc(struct snd_mixer *m, u_int32_t src)
1985 struct sc_info *sc = mix_getdevinfo(m);
1986 int ch = envy24_mixmap[src];
1988 device_printf(sc->dev, "envy24mixer_setrecsrc(m, %d)\n", src);
1991 if (ch > ENVY24_CHAN_PLAY_SPDIF)
1996 static kobj_method_t envy24mixer_methods[] = {
1997 KOBJMETHOD(mixer_init, envy24mixer_init),
1998 KOBJMETHOD(mixer_reinit, envy24mixer_reinit),
1999 KOBJMETHOD(mixer_uninit, envy24mixer_uninit),
2000 KOBJMETHOD(mixer_set, envy24mixer_set),
2001 KOBJMETHOD(mixer_setrecsrc, envy24mixer_setrecsrc),
2004 MIXER_DECLARE(envy24mixer);
2006 /* -------------------------------------------------------------------- */
2008 /* The interrupt handler */
2010 envy24_intr(void *p)
2012 struct sc_info *sc = (struct sc_info *)p;
2013 struct sc_chinfo *ch;
2014 u_int32_t ptr, dsize, feed;
2018 device_printf(sc->dev, "envy24_intr()\n");
2020 snd_mtxlock(sc->lock);
2021 if (envy24_checkintr(sc, PCMDIR_PLAY)) {
2023 device_printf(sc->dev, "envy24_intr(): play\n");
2025 dsize = sc->psize / 4;
2026 ptr = dsize - envy24_rdmt(sc, ENVY24_MT_PCNT, 2) - 1;
2028 device_printf(sc->dev, "envy24_intr(): ptr = %d-->", ptr);
2030 ptr -= ptr % sc->blk[0];
2031 feed = (ptr + dsize - sc->intr[0]) % dsize;
2033 printf("%d intr = %d feed = %d\n", ptr, sc->intr[0], feed);
2035 for (i = ENVY24_CHAN_PLAY_DAC1; i <= ENVY24_CHAN_PLAY_SPDIF; i++) {
2039 device_printf(sc->dev, "envy24_intr(): chan[%d].blk = %d\n", i, ch->blk);
2041 if (ch->run && ch->blk <= feed) {
2042 snd_mtxunlock(sc->lock);
2043 chn_intr(ch->channel);
2044 snd_mtxlock(sc->lock);
2048 envy24_updintr(sc, PCMDIR_PLAY);
2050 if (envy24_checkintr(sc, PCMDIR_REC)) {
2052 device_printf(sc->dev, "envy24_intr(): rec\n");
2054 dsize = sc->rsize / 4;
2055 ptr = dsize - envy24_rdmt(sc, ENVY24_MT_RCNT, 2) - 1;
2056 ptr -= ptr % sc->blk[1];
2057 feed = (ptr + dsize - sc->intr[1]) % dsize;
2058 for (i = ENVY24_CHAN_REC_ADC1; i <= ENVY24_CHAN_REC_SPDIF; i++) {
2060 if (ch->run && ch->blk <= feed) {
2061 snd_mtxunlock(sc->lock);
2062 chn_intr(ch->channel);
2063 snd_mtxlock(sc->lock);
2067 envy24_updintr(sc, PCMDIR_REC);
2069 snd_mtxunlock(sc->lock);
2075 * Probe and attach the card
2079 envy24_pci_probe(device_t dev)
2085 printf("envy24_pci_probe()\n");
2087 if (pci_get_device(dev) == PCID_ENVY24 &&
2088 pci_get_vendor(dev) == PCIV_ENVY24) {
2089 sv = pci_get_subvendor(dev);
2090 sd = pci_get_subdevice(dev);
2091 for (i = 0; cfg_table[i].subvendor != 0 || cfg_table[i].subdevice != 0; i++) {
2092 if (cfg_table[i].subvendor == sv &&
2093 cfg_table[i].subdevice == sd) {
2097 device_set_desc(dev, cfg_table[i].name);
2099 printf("envy24_pci_probe(): return 0\n");
2105 printf("envy24_pci_probe(): return ENXIO\n");
2112 envy24_dmapsetmap(void *arg, bus_dma_segment_t *segs, int nseg, int error)
2114 /* struct sc_info *sc = (struct sc_info *)arg; */
2117 device_printf(sc->dev, "envy24_dmapsetmap()\n");
2119 printf("envy24(play): setmap %lx, %lx; ",
2120 (unsigned long)segs->ds_addr,
2121 (unsigned long)segs->ds_len);
2122 printf("%p -> %lx\n", sc->pmap, (unsigned long)vtophys(sc->pmap));
2128 envy24_dmarsetmap(void *arg, bus_dma_segment_t *segs, int nseg, int error)
2130 /* struct sc_info *sc = (struct sc_info *)arg; */
2133 device_printf(sc->dev, "envy24_dmarsetmap()\n");
2135 printf("envy24(record): setmap %lx, %lx; ",
2136 (unsigned long)segs->ds_addr,
2137 (unsigned long)segs->ds_len);
2138 printf("%p -> %lx\n", sc->rmap, (unsigned long)vtophys(sc->pmap));
2144 envy24_dmafree(struct sc_info *sc)
2147 device_printf(sc->dev, "envy24_dmafree():");
2148 if (sc->rmap) printf(" sc->rmap(0x%08x)", (u_int32_t)sc->rmap);
2149 else printf(" sc->rmap(null)");
2150 if (sc->pmap) printf(" sc->pmap(0x%08x)", (u_int32_t)sc->pmap);
2151 else printf(" sc->pmap(null)");
2152 if (sc->rbuf) printf(" sc->rbuf(0x%08x)", (u_int32_t)sc->rbuf);
2153 else printf(" sc->rbuf(null)");
2154 if (sc->pbuf) printf(" sc->pbuf(0x%08x)\n", (u_int32_t)sc->pbuf);
2155 else printf(" sc->pbuf(null)\n");
2159 bus_dmamap_unload(sc->dmat, sc->rmap);
2161 bus_dmamap_unload(sc->dmat, sc->pmap);
2163 bus_dmamem_free(sc->dmat, sc->rbuf, sc->rmap);
2165 bus_dmamem_free(sc->dmat, sc->pbuf, sc->pmap);
2167 bus_dmamap_unload(sc->dmat, sc->rmap);
2168 bus_dmamap_unload(sc->dmat, sc->pmap);
2169 bus_dmamem_free(sc->dmat, sc->rbuf, sc->rmap);
2170 bus_dmamem_free(sc->dmat, sc->pbuf, sc->pmap);
2173 sc->rmap = sc->pmap = NULL;
2181 envy24_dmainit(struct sc_info *sc)
2186 device_printf(sc->dev, "envy24_dmainit()\n");
2189 sc->psize = ENVY24_PLAY_BUFUNIT * ENVY24_SAMPLE_NUM;
2190 sc->rsize = ENVY24_REC_BUFUNIT * ENVY24_SAMPLE_NUM;
2193 sc->pmap = sc->rmap = NULL;
2194 sc->blk[0] = sc->blk[1] = 0;
2196 /* allocate DMA buffer */
2198 device_printf(sc->dev, "envy24_dmainit(): bus_dmamem_alloc(): sc->pbuf\n");
2200 if (bus_dmamem_alloc(sc->dmat, (void **)&sc->pbuf, BUS_DMA_NOWAIT, &sc->pmap))
2203 device_printf(sc->dev, "envy24_dmainit(): bus_dmamem_alloc(): sc->rbuf\n");
2205 if (bus_dmamem_alloc(sc->dmat, (void **)&sc->rbuf, BUS_DMA_NOWAIT, &sc->rmap))
2208 device_printf(sc->dev, "envy24_dmainit(): bus_dmamem_load(): sc->pmap\n");
2210 if (bus_dmamap_load(sc->dmat, sc->pmap, sc->pbuf, sc->psize, envy24_dmapsetmap, sc, 0))
2213 device_printf(sc->dev, "envy24_dmainit(): bus_dmamem_load(): sc->rmap\n");
2215 if (bus_dmamap_load(sc->dmat, sc->rmap, sc->rbuf, sc->rsize, envy24_dmarsetmap, sc, 0))
2217 bzero(sc->pbuf, sc->psize);
2218 bzero(sc->rbuf, sc->rsize);
2220 /* set values to register */
2221 addr = vtophys(sc->pbuf);
2223 device_printf(sc->dev, "pbuf(0x%08x)\n", addr);
2225 envy24_wrmt(sc, ENVY24_MT_PADDR, addr, 4);
2227 device_printf(sc->dev, "PADDR-->(0x%08x)\n", envy24_rdmt(sc, ENVY24_MT_PADDR, 4));
2228 device_printf(sc->dev, "psize(%ld)\n", sc->psize / 4 - 1);
2230 envy24_wrmt(sc, ENVY24_MT_PCNT, sc->psize / 4 - 1, 2);
2232 device_printf(sc->dev, "PCNT-->(%ld)\n", envy24_rdmt(sc, ENVY24_MT_PCNT, 2));
2234 addr = vtophys(sc->rbuf);
2235 envy24_wrmt(sc, ENVY24_MT_RADDR, addr, 4);
2236 envy24_wrmt(sc, ENVY24_MT_RCNT, sc->rsize / 4 - 1, 2);
2245 envy24_putcfg(struct sc_info *sc)
2247 device_printf(sc->dev, "system configuration\n");
2248 printf(" SubVendorID: 0x%04x, SubDeviceID: 0x%04x\n",
2249 sc->cfg->subvendor, sc->cfg->subdevice);
2250 printf(" XIN2 Clock Source: ");
2251 switch (sc->cfg->scfg & PCIM_SCFG_XIN2) {
2253 printf("22.5792MHz(44.1kHz*512)\n");
2256 printf("16.9344MHz(44.1kHz*384)\n");
2259 printf("from external clock synthesizer chip\n");
2262 printf("illeagal system setting\n");
2264 printf(" MPU-401 UART(s) #: ");
2265 if (sc->cfg->scfg & PCIM_SCFG_MPU)
2269 printf(" AC'97 codec: ");
2270 if (sc->cfg->scfg & PCIM_SCFG_AC97)
2271 printf("not exist\n");
2275 printf("%d\n", sc->adcn);
2277 printf("%d\n", sc->dacn);
2278 printf(" Multi-track converter type: ");
2279 if ((sc->cfg->acl & PCIM_ACL_MTC) == 0) {
2280 printf("AC'97(SDATA_OUT:");
2281 if (sc->cfg->acl & PCIM_ACL_OMODE)
2285 printf("|SDATA_IN:");
2286 if (sc->cfg->acl & PCIM_ACL_IMODE)
2294 if (sc->cfg->i2s & PCIM_I2S_VOL)
2295 printf("with volume, ");
2296 if (sc->cfg->i2s & PCIM_I2S_96KHZ)
2297 printf("96KHz support, ");
2298 switch (sc->cfg->i2s & PCIM_I2S_RES) {
2299 case PCIM_I2S_16BIT:
2300 printf("16bit resolution, ");
2302 case PCIM_I2S_18BIT:
2303 printf("18bit resolution, ");
2305 case PCIM_I2S_20BIT:
2306 printf("20bit resolution, ");
2308 case PCIM_I2S_24BIT:
2309 printf("24bit resolution, ");
2312 printf("ID#0x%x)\n", sc->cfg->i2s & PCIM_I2S_ID);
2314 printf(" S/PDIF(IN/OUT): ");
2315 if (sc->cfg->spdif & PCIM_SPDIF_IN)
2319 if (sc->cfg->spdif & PCIM_SPDIF_OUT)
2323 if (sc->cfg->spdif & (PCIM_SPDIF_IN | PCIM_SPDIF_OUT))
2324 printf("ID# 0x%02x\n", (sc->cfg->spdif & PCIM_SPDIF_ID) >> 2);
2325 printf(" GPIO(mask/dir/state): 0x%02x/0x%02x/0x%02x\n",
2326 sc->cfg->gpiomask, sc->cfg->gpiodir, sc->cfg->gpiostate);
2330 envy24_init(struct sc_info *sc)
2341 device_printf(sc->dev, "envy24_init()\n");
2345 envy24_wrcs(sc, ENVY24_CCS_CTL, ENVY24_CCS_CTL_RESET | ENVY24_CCS_CTL_NATIVE, 1);
2347 envy24_wrcs(sc, ENVY24_CCS_CTL, ENVY24_CCS_CTL_NATIVE, 1);
2350 /* legacy hardware disable */
2351 data = pci_read_config(sc->dev, PCIR_LAC, 2);
2352 data |= PCIM_LAC_DISABLE;
2353 pci_write_config(sc->dev, PCIR_LAC, data, 2);
2355 /* check system configuration */
2357 for (i = 0; cfg_table[i].subvendor != 0 || cfg_table[i].subdevice != 0; i++) {
2358 /* 1st: search configuration from table */
2359 sv = pci_get_subvendor(sc->dev);
2360 sd = pci_get_subdevice(sc->dev);
2361 if (sv == cfg_table[i].subvendor && sd == cfg_table[i].subdevice) {
2363 device_printf(sc->dev, "Set configuration from table\n");
2365 sc->cfg = &cfg_table[i];
2369 if (sc->cfg == NULL) {
2370 /* 2nd: read configuration from table */
2371 sc->cfg = envy24_rom2cfg(sc);
2373 sc->adcn = ((sc->cfg->scfg & PCIM_SCFG_ADC) >> 2) + 1;
2374 sc->dacn = (sc->cfg->scfg & PCIM_SCFG_DAC) + 1;
2376 if (1 /* bootverbose */) {
2380 /* set system configuration */
2381 pci_write_config(sc->dev, PCIR_SCFG, sc->cfg->scfg, 1);
2382 pci_write_config(sc->dev, PCIR_ACL, sc->cfg->acl, 1);
2383 pci_write_config(sc->dev, PCIR_I2S, sc->cfg->i2s, 1);
2384 pci_write_config(sc->dev, PCIR_SPDIF, sc->cfg->spdif, 1);
2385 envy24_gpiosetmask(sc, sc->cfg->gpiomask);
2386 envy24_gpiosetdir(sc, sc->cfg->gpiodir);
2387 envy24_gpiowr(sc, sc->cfg->gpiostate);
2388 for (i = 0; i < sc->adcn; i++) {
2389 sc->adc[i] = sc->cfg->codec->create(sc->dev, sc, PCMDIR_REC, i);
2390 sc->cfg->codec->init(sc->adc[i]);
2392 for (i = 0; i < sc->dacn; i++) {
2393 sc->dac[i] = sc->cfg->codec->create(sc->dev, sc, PCMDIR_PLAY, i);
2394 sc->cfg->codec->init(sc->dac[i]);
2397 /* initialize DMA buffer */
2399 device_printf(sc->dev, "envy24_init(): initialize DMA buffer\n");
2401 if (envy24_dmainit(sc))
2404 /* initialize status */
2405 sc->run[0] = sc->run[1] = 0;
2406 sc->intr[0] = sc->intr[1] = 0;
2408 sc->caps[0].fmtlist = envy24_playfmt;
2409 sc->caps[1].fmtlist = envy24_recfmt;
2411 /* set channel router */
2412 envy24_route(sc, ENVY24_ROUTE_DAC_1, ENVY24_ROUTE_CLASS_MIX, 0, 0);
2413 envy24_route(sc, ENVY24_ROUTE_DAC_SPDIF, ENVY24_ROUTE_CLASS_DMA, 0, 0);
2414 /* envy24_route(sc, ENVY24_ROUTE_DAC_SPDIF, ENVY24_ROUTE_CLASS_MIX, 0, 0); */
2416 /* set macro interrupt mask */
2417 data = envy24_rdcs(sc, ENVY24_CCS_IMASK, 1);
2418 envy24_wrcs(sc, ENVY24_CCS_IMASK, data & ~ENVY24_CCS_IMASK_PMT, 1);
2419 data = envy24_rdcs(sc, ENVY24_CCS_IMASK, 1);
2421 device_printf(sc->dev, "envy24_init(): CCS_IMASK-->0x%02x\n", data);
2428 envy24_alloc_resource(struct sc_info *sc)
2430 /* allocate I/O port resource */
2431 sc->csid = PCIR_CCS;
2432 sc->cs = bus_alloc_resource(sc->dev, SYS_RES_IOPORT,
2433 &sc->csid, 0, ~0, 1, RF_ACTIVE);
2434 sc->ddmaid = PCIR_DDMA;
2435 sc->ddma = bus_alloc_resource(sc->dev, SYS_RES_IOPORT,
2436 &sc->ddmaid, 0, ~0, 1, RF_ACTIVE);
2438 sc->ds = bus_alloc_resource(sc->dev, SYS_RES_IOPORT,
2439 &sc->dsid, 0, ~0, 1, RF_ACTIVE);
2441 sc->mt = bus_alloc_resource(sc->dev, SYS_RES_IOPORT,
2442 &sc->mtid, 0, ~0, 1, RF_ACTIVE);
2443 if (!sc->cs || !sc->ddma || !sc->ds || !sc->mt) {
2444 device_printf(sc->dev, "unable to map IO port space\n");
2447 sc->cst = rman_get_bustag(sc->cs);
2448 sc->csh = rman_get_bushandle(sc->cs);
2449 sc->ddmat = rman_get_bustag(sc->ddma);
2450 sc->ddmah = rman_get_bushandle(sc->ddma);
2451 sc->dst = rman_get_bustag(sc->ds);
2452 sc->dsh = rman_get_bushandle(sc->ds);
2453 sc->mtt = rman_get_bustag(sc->mt);
2454 sc->mth = rman_get_bushandle(sc->mt);
2456 device_printf(sc->dev,
2457 "IO port register values\nCCS: 0x%lx\nDDMA: 0x%lx\nDS: 0x%lx\nMT: 0x%lx\n",
2458 pci_read_config(sc->dev, PCIR_CCS, 4),
2459 pci_read_config(sc->dev, PCIR_DDMA, 4),
2460 pci_read_config(sc->dev, PCIR_DS, 4),
2461 pci_read_config(sc->dev, PCIR_MT, 4));
2464 /* allocate interrupt resource */
2466 sc->irq = bus_alloc_resource(sc->dev, SYS_RES_IRQ, &sc->irqid,
2467 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE);
2469 snd_setup_intr(sc->dev, sc->irq, INTR_MPSAFE, envy24_intr, sc, &sc->ih)) {
2470 device_printf(sc->dev, "unable to map interrupt\n");
2474 /* allocate DMA resource */
2475 if (bus_dma_tag_create(/*parent*/bus_get_dma_tag(sc->dev),
2478 /*lowaddr*/BUS_SPACE_MAXADDR_ENVY24,
2479 /*highaddr*/BUS_SPACE_MAXADDR_ENVY24,
2480 /*filter*/NULL, /*filterarg*/NULL,
2481 /*maxsize*/BUS_SPACE_MAXSIZE_ENVY24,
2482 /*nsegments*/1, /*maxsegsz*/0x3ffff,
2483 /*flags*/0, /*lockfunc*/busdma_lock_mutex,
2484 /*lockarg*/&Giant, &sc->dmat) != 0) {
2485 device_printf(sc->dev, "unable to create dma tag\n");
2493 envy24_pci_attach(device_t dev)
2497 char status[SND_STATUSLEN];
2502 device_printf(dev, "envy24_pci_attach()\n");
2504 /* get sc_info data area */
2505 if ((sc = malloc(sizeof(*sc), M_ENVY24, M_NOWAIT)) == NULL) {
2506 device_printf(dev, "cannot allocate softc\n");
2510 bzero(sc, sizeof(*sc));
2511 sc->lock = snd_mtxcreate(device_get_nameunit(dev), "snd_envy24 softc");
2514 /* initialize PCI interface */
2515 data = pci_read_config(dev, PCIR_COMMAND, 2);
2516 data |= (PCIM_CMD_PORTEN | PCIM_CMD_BUSMASTEREN);
2517 pci_write_config(dev, PCIR_COMMAND, data, 2);
2518 data = pci_read_config(dev, PCIR_COMMAND, 2);
2520 /* allocate resources */
2521 err = envy24_alloc_resource(sc);
2523 device_printf(dev, "unable to allocate system resources\n");
2527 /* initialize card */
2528 err = envy24_init(sc);
2530 device_printf(dev, "unable to initialize the card\n");
2534 /* set multi track mixer */
2535 mixer_init(dev, &envy24mixer_class, sc);
2537 /* set channel information */
2538 err = pcm_register(dev, sc, 5, 2 + sc->adcn);
2542 for (i = 0; i < 5; i++) {
2543 pcm_addchan(dev, PCMDIR_PLAY, &envy24chan_class, sc);
2546 for (i = 0; i < 2 + sc->adcn; i++) {
2547 pcm_addchan(dev, PCMDIR_REC, &envy24chan_class, sc);
2551 /* set status iformation */
2552 snprintf(status, SND_STATUSLEN,
2553 "at io 0x%lx:%ld,0x%lx:%ld,0x%lx:%ld,0x%lx:%ld irq %ld",
2554 rman_get_start(sc->cs),
2555 rman_get_end(sc->cs) - rman_get_start(sc->cs) + 1,
2556 rman_get_start(sc->ddma),
2557 rman_get_end(sc->ddma) - rman_get_start(sc->ddma) + 1,
2558 rman_get_start(sc->ds),
2559 rman_get_end(sc->ds) - rman_get_start(sc->ds) + 1,
2560 rman_get_start(sc->mt),
2561 rman_get_end(sc->mt) - rman_get_start(sc->mt) + 1,
2562 rman_get_start(sc->irq));
2563 pcm_setstatus(dev, status);
2569 bus_teardown_intr(dev, sc->irq, sc->ih);
2571 bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq);
2574 bus_dma_tag_destroy(sc->dmat);
2575 if (sc->cfg->codec->destroy != NULL) {
2576 for (i = 0; i < sc->adcn; i++)
2577 sc->cfg->codec->destroy(sc->adc[i]);
2578 for (i = 0; i < sc->dacn; i++)
2579 sc->cfg->codec->destroy(sc->dac[i]);
2581 envy24_cfgfree(sc->cfg);
2583 bus_release_resource(dev, SYS_RES_IOPORT, sc->csid, sc->cs);
2585 bus_release_resource(dev, SYS_RES_IOPORT, sc->ddmaid, sc->ddma);
2587 bus_release_resource(dev, SYS_RES_IOPORT, sc->dsid, sc->ds);
2589 bus_release_resource(dev, SYS_RES_IOPORT, sc->mtid, sc->mt);
2591 snd_mtxfree(sc->lock);
2597 envy24_pci_detach(device_t dev)
2604 device_printf(dev, "envy24_pci_detach()\n");
2606 sc = pcm_getdevinfo(dev);
2609 r = pcm_unregister(dev);
2614 if (sc->cfg->codec->destroy != NULL) {
2615 for (i = 0; i < sc->adcn; i++)
2616 sc->cfg->codec->destroy(sc->adc[i]);
2617 for (i = 0; i < sc->dacn; i++)
2618 sc->cfg->codec->destroy(sc->dac[i]);
2620 envy24_cfgfree(sc->cfg);
2621 bus_dma_tag_destroy(sc->dmat);
2622 bus_teardown_intr(dev, sc->irq, sc->ih);
2623 bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq);
2624 bus_release_resource(dev, SYS_RES_IOPORT, sc->csid, sc->cs);
2625 bus_release_resource(dev, SYS_RES_IOPORT, sc->ddmaid, sc->ddma);
2626 bus_release_resource(dev, SYS_RES_IOPORT, sc->dsid, sc->ds);
2627 bus_release_resource(dev, SYS_RES_IOPORT, sc->mtid, sc->mt);
2628 snd_mtxfree(sc->lock);
2633 static device_method_t envy24_methods[] = {
2634 /* Device interface */
2635 DEVMETHOD(device_probe, envy24_pci_probe),
2636 DEVMETHOD(device_attach, envy24_pci_attach),
2637 DEVMETHOD(device_detach, envy24_pci_detach),
2641 static driver_t envy24_driver = {
2644 #if __FreeBSD_version > 500000
2647 sizeof(struct snddev_info),
2651 DRIVER_MODULE(snd_envy24, pci, envy24_driver, pcm_devclass, 0, 0);
2652 MODULE_DEPEND(snd_envy24, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER);
2653 MODULE_DEPEND(snd_envy24, snd_spicds, 1, 1, 1);
2654 MODULE_VERSION(snd_envy24, 1);