2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4 * Copyright (c) 2001 Katsurajima Naoto <raven@katsurajima.seya.yokohama.jp>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHERIN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 #ifdef HAVE_KERNEL_OPTION_HEADERS
34 #include <dev/sound/pcm/sound.h>
35 #include <dev/sound/pcm/ac97.h>
36 #include <dev/sound/pci/spicds.h>
37 #include <dev/sound/pci/envy24.h>
39 #include <dev/pci/pcireg.h>
40 #include <dev/pci/pcivar.h>
44 SND_DECLARE_FILE("$FreeBSD$");
46 static MALLOC_DEFINE(M_ENVY24, "envy24", "envy24 audio");
48 /* -------------------------------------------------------------------- */
52 #define ENVY24_PLAY_CHNUM 10
53 #define ENVY24_REC_CHNUM 12
54 #define ENVY24_PLAY_BUFUNIT (4 /* byte/sample */ * 10 /* channel */)
55 #define ENVY24_REC_BUFUNIT (4 /* byte/sample */ * 12 /* channel */)
56 #define ENVY24_SAMPLE_NUM 4096
58 #define ENVY24_TIMEOUT 1000
60 #define ENVY24_DEFAULT_FORMAT SND_FORMAT(AFMT_S16_LE, 2, 0)
62 #define ENVY24_NAMELEN 32
67 struct envy24_sample {
68 volatile u_int32_t buffer;
71 typedef struct envy24_sample sample32_t;
73 /* channel registers */
75 struct snd_dbuf *buffer;
76 struct pcm_channel *channel;
77 struct sc_info *parent;
79 unsigned num; /* hw channel number */
81 /* channel information */
84 u_int32_t blk; /* hw block size(dword) */
86 /* format conversion structure */
88 unsigned int size; /* data buffer size(byte) */
89 int unit; /* sample size(byte) */
90 unsigned int offset; /* samples number offset */
91 void (*emldma)(struct sc_chinfo *);
97 /* codec interface entrys */
99 void *(*create)(device_t dev, void *devinfo, int dir, int num);
100 void (*destroy)(void *codec);
101 void (*init)(void *codec);
102 void (*reinit)(void *codec);
103 void (*setvolume)(void *codec, int dir, unsigned int left, unsigned int right);
104 void (*setrate)(void *codec, int which, int rate);
107 /* system configuration information */
110 u_int16_t subvendor, subdevice;
111 u_int8_t scfg, acl, i2s, spdif;
112 u_int8_t gpiomask, gpiostate, gpiodir;
113 u_int8_t cdti, cclk, cs, cif, type;
115 struct codec_entry *codec;
118 /* device private data */
123 /* Control/Status registor */
127 bus_space_handle_t csh;
129 struct resource *ddma;
131 bus_space_tag_t ddmat;
132 bus_space_handle_t ddmah;
133 /* Consumer Section DMA Channel Registers */
137 bus_space_handle_t dsh;
138 /* MultiTrack registor */
142 bus_space_handle_t mth;
146 struct resource *irq;
150 /* system configuration data */
151 struct cfg_info *cfg;
153 /* ADC/DAC number and info */
155 void *adc[4], *dac[4];
157 /* mixer control data */
159 u_int8_t left[ENVY24_CHAN_NUM];
160 u_int8_t right[ENVY24_CHAN_NUM];
162 /* Play/Record DMA fifo */
165 u_int32_t psize, rsize; /* DMA buffer size(byte) */
166 u_int16_t blk[2]; /* transfer check blocksize(dword) */
167 bus_dmamap_t pmap, rmap;
168 bus_addr_t paddr, raddr;
174 struct pcmchan_caps caps[2];
176 /* channel info table */
178 struct sc_chinfo chan[11];
181 /* -------------------------------------------------------------------- */
188 static void envy24_p8u(struct sc_chinfo *);
189 static void envy24_p16sl(struct sc_chinfo *);
190 static void envy24_p32sl(struct sc_chinfo *);
191 static void envy24_r16sl(struct sc_chinfo *);
192 static void envy24_r32sl(struct sc_chinfo *);
194 /* channel interface */
195 static void *envy24chan_init(kobj_t, void *, struct snd_dbuf *, struct pcm_channel *, int);
196 static int envy24chan_setformat(kobj_t, void *, u_int32_t);
197 static u_int32_t envy24chan_setspeed(kobj_t, void *, u_int32_t);
198 static u_int32_t envy24chan_setblocksize(kobj_t, void *, u_int32_t);
199 static int envy24chan_trigger(kobj_t, void *, int);
200 static u_int32_t envy24chan_getptr(kobj_t, void *);
201 static struct pcmchan_caps *envy24chan_getcaps(kobj_t, void *);
203 /* mixer interface */
204 static int envy24mixer_init(struct snd_mixer *);
205 static int envy24mixer_reinit(struct snd_mixer *);
206 static int envy24mixer_uninit(struct snd_mixer *);
207 static int envy24mixer_set(struct snd_mixer *, unsigned, unsigned, unsigned);
208 static u_int32_t envy24mixer_setrecsrc(struct snd_mixer *, u_int32_t);
210 /* M-Audio Delta series AK4524 access interface */
211 static void *envy24_delta_ak4524_create(device_t, void *, int, int);
212 static void envy24_delta_ak4524_destroy(void *);
213 static void envy24_delta_ak4524_init(void *);
214 static void envy24_delta_ak4524_reinit(void *);
215 static void envy24_delta_ak4524_setvolume(void *, int, unsigned int, unsigned int);
217 /* -------------------------------------------------------------------- */
220 system constant tables
223 /* API -> hardware channel map */
224 static unsigned envy24_chanmap[ENVY24_CHAN_NUM] = {
225 ENVY24_CHAN_PLAY_SPDIF, /* 0 */
226 ENVY24_CHAN_PLAY_DAC1, /* 1 */
227 ENVY24_CHAN_PLAY_DAC2, /* 2 */
228 ENVY24_CHAN_PLAY_DAC3, /* 3 */
229 ENVY24_CHAN_PLAY_DAC4, /* 4 */
230 ENVY24_CHAN_REC_MIX, /* 5 */
231 ENVY24_CHAN_REC_SPDIF, /* 6 */
232 ENVY24_CHAN_REC_ADC1, /* 7 */
233 ENVY24_CHAN_REC_ADC2, /* 8 */
234 ENVY24_CHAN_REC_ADC3, /* 9 */
235 ENVY24_CHAN_REC_ADC4, /* 10 */
238 /* mixer -> API channel map. see above */
239 static int envy24_mixmap[] = {
240 -1, /* Master output level. It is depend on codec support */
241 -1, /* Treble level of all output channels */
242 -1, /* Bass level of all output channels */
243 -1, /* Volume of synthesier input */
244 0, /* Output level for the audio device */
245 -1, /* Output level for the PC speaker */
246 7, /* line in jack */
247 -1, /* microphone jack */
248 -1, /* CD audio input */
249 -1, /* Recording monitor */
250 1, /* alternative codec */
251 -1, /* global recording level */
253 -1, /* Output gain */
254 8, /* Input source 1 */
255 9, /* Input source 2 */
256 10, /* Input source 3 */
257 6, /* Digital (input) 1 */
258 -1, /* Digital (input) 2 */
259 -1, /* Digital (input) 3 */
260 -1, /* Phone input */
261 -1, /* Phone output */
262 -1, /* Video/TV (audio) in */
264 -1, /* Monitor volume */
267 /* variable rate audio */
268 static u_int32_t envy24_speed[] = {
269 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000,
270 12000, 11025, 9600, 8000, 0
273 /* known boards configuration */
274 static struct codec_entry delta_codec = {
275 envy24_delta_ak4524_create,
276 envy24_delta_ak4524_destroy,
277 envy24_delta_ak4524_init,
278 envy24_delta_ak4524_reinit,
279 envy24_delta_ak4524_setvolume,
283 static struct cfg_info cfg_table[] = {
285 "Envy24 audio (M Audio Delta Dio 2496)",
287 0x10, 0x80, 0xf0, 0x03,
289 0x10, 0x20, 0x40, 0x00, 0x00,
294 "Envy24 audio (Terratec DMX 6fire)",
296 0x2f, 0x80, 0xf0, 0x03,
298 0x10, 0x20, 0x01, 0x01, 0x00,
303 "Envy24 audio (M Audio Audiophile 2496)",
305 0x10, 0x80, 0x72, 0x03,
307 0x08, 0x02, 0x20, 0x00, 0x01,
312 "Envy24 audio (M Audio Delta 66)",
314 0x15, 0x80, 0xf0, 0x03,
316 0x10, 0x20, 0x40, 0x00, 0x00,
321 "Envy24 audio (M Audio Delta 44)",
323 0x15, 0x80, 0xf0, 0x00,
325 0x10, 0x20, 0x40, 0x00, 0x00,
330 "Envy24 audio (M Audio Delta 1010)",
332 0x1f, 0x80, 0xf0, 0x03,
334 0x10, 0x20, 0x40, 0x00, 0x00,
339 "Envy24 audio (M Audio Delta 1010LT)",
341 0x1f, 0x80, 0x72, 0x03,
343 0x08, 0x02, 0x70, 0x00, 0x00,
348 "Envy24 audio (Terratec EWX 2496)",
350 0x10, 0x80, 0xf0, 0x03,
352 0x10, 0x20, 0x01, 0x01, 0x00,
357 "Envy24 audio (Generic)",
359 0x0f, 0x00, 0x01, 0x03,
361 0x10, 0x20, 0x40, 0x00, 0x00,
363 &delta_codec, /* default codec routines */
367 static u_int32_t envy24_recfmt[] = {
368 SND_FORMAT(AFMT_S16_LE, 2, 0),
369 SND_FORMAT(AFMT_S32_LE, 2, 0),
372 static struct pcmchan_caps envy24_reccaps = {8000, 96000, envy24_recfmt, 0};
374 static u_int32_t envy24_playfmt[] = {
375 SND_FORMAT(AFMT_U8, 2, 0),
376 SND_FORMAT(AFMT_S16_LE, 2, 0),
377 SND_FORMAT(AFMT_S32_LE, 2, 0),
381 static struct pcmchan_caps envy24_playcaps = {8000, 96000, envy24_playfmt, 0};
383 struct envy24_emldma {
385 void (*emldma)(struct sc_chinfo *);
389 static struct envy24_emldma envy24_pemltab[] = {
390 {SND_FORMAT(AFMT_U8, 2, 0), envy24_p8u, 2},
391 {SND_FORMAT(AFMT_S16_LE, 2, 0), envy24_p16sl, 4},
392 {SND_FORMAT(AFMT_S32_LE, 2, 0), envy24_p32sl, 8},
396 static struct envy24_emldma envy24_remltab[] = {
397 {SND_FORMAT(AFMT_S16_LE, 2, 0), envy24_r16sl, 4},
398 {SND_FORMAT(AFMT_S32_LE, 2, 0), envy24_r32sl, 8},
402 /* -------------------------------------------------------------------- */
404 /* common routines */
406 envy24_rdcs(struct sc_info *sc, int regno, int size)
410 return bus_space_read_1(sc->cst, sc->csh, regno);
412 return bus_space_read_2(sc->cst, sc->csh, regno);
414 return bus_space_read_4(sc->cst, sc->csh, regno);
421 envy24_wrcs(struct sc_info *sc, int regno, u_int32_t data, int size)
425 bus_space_write_1(sc->cst, sc->csh, regno, data);
428 bus_space_write_2(sc->cst, sc->csh, regno, data);
431 bus_space_write_4(sc->cst, sc->csh, regno, data);
437 envy24_rdmt(struct sc_info *sc, int regno, int size)
441 return bus_space_read_1(sc->mtt, sc->mth, regno);
443 return bus_space_read_2(sc->mtt, sc->mth, regno);
445 return bus_space_read_4(sc->mtt, sc->mth, regno);
452 envy24_wrmt(struct sc_info *sc, int regno, u_int32_t data, int size)
456 bus_space_write_1(sc->mtt, sc->mth, regno, data);
459 bus_space_write_2(sc->mtt, sc->mth, regno, data);
462 bus_space_write_4(sc->mtt, sc->mth, regno, data);
468 envy24_rdci(struct sc_info *sc, int regno)
470 envy24_wrcs(sc, ENVY24_CCS_INDEX, regno, 1);
471 return envy24_rdcs(sc, ENVY24_CCS_DATA, 1);
475 envy24_wrci(struct sc_info *sc, int regno, u_int32_t data)
477 envy24_wrcs(sc, ENVY24_CCS_INDEX, regno, 1);
478 envy24_wrcs(sc, ENVY24_CCS_DATA, data, 1);
481 /* -------------------------------------------------------------------- */
483 /* I2C port/E2PROM access routines */
486 envy24_rdi2c(struct sc_info *sc, u_int32_t dev, u_int32_t addr)
492 device_printf(sc->dev, "envy24_rdi2c(sc, 0x%02x, 0x%02x)\n", dev, addr);
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) {
503 envy24_wrcs(sc, ENVY24_CCS_I2CADDR, addr, 1);
504 envy24_wrcs(sc, ENVY24_CCS_I2CDEV,
505 (dev & ENVY24_CCS_I2CDEV_ADDR) | ENVY24_CCS_I2CDEV_RD, 1);
506 for (i = 0; i < ENVY24_TIMEOUT; i++) {
507 data = envy24_rdcs(sc, ENVY24_CCS_I2CSTAT, 1);
508 if ((data & ENVY24_CCS_I2CSTAT_BSY) == 0)
510 DELAY(32); /* 31.25kHz */
512 if (i == ENVY24_TIMEOUT) {
515 data = envy24_rdcs(sc, ENVY24_CCS_I2CDATA, 1);
518 device_printf(sc->dev, "envy24_rdi2c(): return 0x%x\n", data);
525 envy24_wri2c(struct sc_info *sc, u_int32_t dev, u_int32_t addr, u_int32_t data)
531 device_printf(sc->dev, "envy24_rdi2c(sc, 0x%02x, 0x%02x)\n", dev, addr);
533 for (i = 0; i < ENVY24_TIMEOUT; i++) {
534 tmp = envy24_rdcs(sc, ENVY24_CCS_I2CSTAT, 1);
535 if ((tmp & ENVY24_CCS_I2CSTAT_BSY) == 0)
537 DELAY(32); /* 31.25kHz */
539 if (i == ENVY24_TIMEOUT) {
542 envy24_wrcs(sc, ENVY24_CCS_I2CADDR, addr, 1);
543 envy24_wrcs(sc, ENVY24_CCS_I2CDATA, data, 1);
544 envy24_wrcs(sc, ENVY24_CCS_I2CDEV,
545 (dev & ENVY24_CCS_I2CDEV_ADDR) | ENVY24_CCS_I2CDEV_WR, 1);
546 for (i = 0; i < ENVY24_TIMEOUT; i++) {
547 data = envy24_rdcs(sc, ENVY24_CCS_I2CSTAT, 1);
548 if ((data & ENVY24_CCS_I2CSTAT_BSY) == 0)
550 DELAY(32); /* 31.25kHz */
552 if (i == ENVY24_TIMEOUT) {
561 envy24_rdrom(struct sc_info *sc, u_int32_t addr)
566 device_printf(sc->dev, "envy24_rdrom(sc, 0x%02x)\n", addr);
568 data = envy24_rdcs(sc, ENVY24_CCS_I2CSTAT, 1);
569 if ((data & ENVY24_CCS_I2CSTAT_ROM) == 0) {
571 device_printf(sc->dev, "envy24_rdrom(): E2PROM not presented\n");
576 return envy24_rdi2c(sc, ENVY24_CCS_I2CDEV_ROM, addr);
579 static struct cfg_info *
580 envy24_rom2cfg(struct sc_info *sc)
582 struct cfg_info *buff;
587 device_printf(sc->dev, "envy24_rom2cfg(sc)\n");
589 size = envy24_rdrom(sc, ENVY24_E2PROM_SIZE);
590 if (size < ENVY24_E2PROM_GPIODIR + 1) {
592 device_printf(sc->dev, "envy24_rom2cfg(): ENVY24_E2PROM_SIZE-->%d\n", size);
596 buff = malloc(sizeof(*buff), M_ENVY24, M_NOWAIT);
599 device_printf(sc->dev, "envy24_rom2cfg(): malloc()\n");
605 buff->subvendor = envy24_rdrom(sc, ENVY24_E2PROM_SUBVENDOR) << 8;
606 buff->subvendor += envy24_rdrom(sc, ENVY24_E2PROM_SUBVENDOR + 1);
607 buff->subdevice = envy24_rdrom(sc, ENVY24_E2PROM_SUBDEVICE) << 8;
608 buff->subdevice += envy24_rdrom(sc, ENVY24_E2PROM_SUBDEVICE + 1);
609 buff->scfg = envy24_rdrom(sc, ENVY24_E2PROM_SCFG);
610 buff->acl = envy24_rdrom(sc, ENVY24_E2PROM_ACL);
611 buff->i2s = envy24_rdrom(sc, ENVY24_E2PROM_I2S);
612 buff->spdif = envy24_rdrom(sc, ENVY24_E2PROM_SPDIF);
613 buff->gpiomask = envy24_rdrom(sc, ENVY24_E2PROM_GPIOMASK);
614 buff->gpiostate = envy24_rdrom(sc, ENVY24_E2PROM_GPIOSTATE);
615 buff->gpiodir = envy24_rdrom(sc, ENVY24_E2PROM_GPIODIR);
617 for (i = 0; cfg_table[i].subvendor != 0 || cfg_table[i].subdevice != 0; i++)
618 if (cfg_table[i].subvendor == buff->subvendor &&
619 cfg_table[i].subdevice == buff->subdevice)
621 buff->name = cfg_table[i].name;
622 buff->codec = cfg_table[i].codec;
628 envy24_cfgfree(struct cfg_info *cfg) {
636 /* -------------------------------------------------------------------- */
638 /* AC'97 codec access routines */
642 envy24_coldcd(struct sc_info *sc)
648 device_printf(sc->dev, "envy24_coldcd()\n");
650 envy24_wrmt(sc, ENVY24_MT_AC97CMD, ENVY24_MT_AC97CMD_CLD, 1);
652 envy24_wrmt(sc, ENVY24_MT_AC97CMD, 0, 1);
654 for (i = 0; i < ENVY24_TIMEOUT; i++) {
655 data = envy24_rdmt(sc, ENVY24_MT_AC97CMD, 1);
656 if (data & ENVY24_MT_AC97CMD_RDY) {
666 envy24_slavecd(struct sc_info *sc)
672 device_printf(sc->dev, "envy24_slavecd()\n");
674 envy24_wrmt(sc, ENVY24_MT_AC97CMD,
675 ENVY24_MT_AC97CMD_CLD | ENVY24_MT_AC97CMD_WRM, 1);
677 envy24_wrmt(sc, ENVY24_MT_AC97CMD, 0, 1);
679 for (i = 0; i < ENVY24_TIMEOUT; i++) {
680 data = envy24_rdmt(sc, ENVY24_MT_AC97CMD, 1);
681 if (data & ENVY24_MT_AC97CMD_RDY) {
691 envy24_rdcd(kobj_t obj, void *devinfo, int regno)
693 struct sc_info *sc = (struct sc_info *)devinfo;
698 device_printf(sc->dev, "envy24_rdcd(obj, sc, 0x%02x)\n", regno);
700 envy24_wrmt(sc, ENVY24_MT_AC97IDX, (u_int32_t)regno, 1);
701 envy24_wrmt(sc, ENVY24_MT_AC97CMD, ENVY24_MT_AC97CMD_RD, 1);
702 for (i = 0; i < ENVY24_TIMEOUT; i++) {
703 data = envy24_rdmt(sc, ENVY24_MT_AC97CMD, 1);
704 if ((data & ENVY24_MT_AC97CMD_RD) == 0)
707 data = envy24_rdmt(sc, ENVY24_MT_AC97DLO, 2);
710 device_printf(sc->dev, "envy24_rdcd(): return 0x%x\n", data);
716 envy24_wrcd(kobj_t obj, void *devinfo, int regno, u_int16_t data)
718 struct sc_info *sc = (struct sc_info *)devinfo;
723 device_printf(sc->dev, "envy24_wrcd(obj, sc, 0x%02x, 0x%04x)\n", regno, data);
725 envy24_wrmt(sc, ENVY24_MT_AC97IDX, (u_int32_t)regno, 1);
726 envy24_wrmt(sc, ENVY24_MT_AC97DLO, (u_int32_t)data, 2);
727 envy24_wrmt(sc, ENVY24_MT_AC97CMD, ENVY24_MT_AC97CMD_WR, 1);
728 for (i = 0; i < ENVY24_TIMEOUT; i++) {
729 cmd = envy24_rdmt(sc, ENVY24_MT_AC97CMD, 1);
730 if ((cmd & ENVY24_MT_AC97CMD_WR) == 0)
737 static kobj_method_t envy24_ac97_methods[] = {
738 KOBJMETHOD(ac97_read, envy24_rdcd),
739 KOBJMETHOD(ac97_write, envy24_wrcd),
742 AC97_DECLARE(envy24_ac97);
745 /* -------------------------------------------------------------------- */
747 /* GPIO access routines */
750 envy24_gpiord(struct sc_info *sc)
752 return envy24_rdci(sc, ENVY24_CCI_GPIODAT);
756 envy24_gpiowr(struct sc_info *sc, u_int32_t data)
759 device_printf(sc->dev, "envy24_gpiowr(sc, 0x%02x)\n", data & 0xff);
762 envy24_wrci(sc, ENVY24_CCI_GPIODAT, data);
768 envy24_gpiogetmask(struct sc_info *sc)
770 return envy24_rdci(sc, ENVY24_CCI_GPIOMASK);
775 envy24_gpiosetmask(struct sc_info *sc, u_int32_t mask)
777 envy24_wrci(sc, ENVY24_CCI_GPIOMASK, mask);
783 envy24_gpiogetdir(struct sc_info *sc)
785 return envy24_rdci(sc, ENVY24_CCI_GPIOCTL);
790 envy24_gpiosetdir(struct sc_info *sc, u_int32_t dir)
792 envy24_wrci(sc, ENVY24_CCI_GPIOCTL, dir);
796 /* -------------------------------------------------------------------- */
798 /* Envy24 I2C through GPIO bit-banging */
800 struct envy24_delta_ak4524_codec {
801 struct spicds_info *info;
802 struct sc_info *parent;
809 envy24_gpio_i2c_ctl(void *codec, unsigned int scl, unsigned int sda)
812 struct envy24_delta_ak4524_codec *ptr = codec;
814 device_printf(ptr->parent->dev, "--> %d, %d\n", scl, sda);
816 data = envy24_gpiord(ptr->parent);
817 data &= ~(SDA_GPIO | SCL_GPIO);
818 if (scl) data += SCL_GPIO;
819 if (sda) data += SDA_GPIO;
820 envy24_gpiowr(ptr->parent, data);
825 i2c_wrbit(void *codec, void (*ctrl)(void*, unsigned int, unsigned int), int bit)
827 struct envy24_delta_ak4524_codec *ptr = codec;
844 i2c_start(void *codec, void (*ctrl)(void*, unsigned int, unsigned int))
846 struct envy24_delta_ak4524_codec *ptr = codec;
857 i2c_stop(void *codec, void (*ctrl)(void*, unsigned int, unsigned int))
859 struct envy24_delta_ak4524_codec *ptr = codec;
870 i2c_ack(void *codec, void (*ctrl)(void*, unsigned int, unsigned int))
872 struct envy24_delta_ak4524_codec *ptr = codec;
878 /* dummy, need routine to change gpio direction */
884 i2c_wr(void *codec, void (*ctrl)(void*, unsigned int, unsigned int), u_int32_t dev, int reg, u_int8_t val)
886 struct envy24_delta_ak4524_codec *ptr = codec;
889 i2c_start(ptr, ctrl);
891 for (mask = 0x80; mask != 0; mask >>= 1)
892 i2c_wrbit(ptr, ctrl, dev & mask);
896 for (mask = 0x80; mask != 0; mask >>= 1)
897 i2c_wrbit(ptr, ctrl, reg & mask);
901 for (mask = 0x80; mask != 0; mask >>= 1)
902 i2c_wrbit(ptr, ctrl, val & mask);
908 /* -------------------------------------------------------------------- */
910 /* M-Audio Delta series AK4524 access interface routine */
913 envy24_delta_ak4524_ctl(void *codec, unsigned int cs, unsigned int cclk, unsigned int cdti)
916 struct envy24_delta_ak4524_codec *ptr = codec;
919 device_printf(ptr->parent->dev, "--> %d, %d, %d\n", cs, cclk, cdti);
921 data = envy24_gpiord(ptr->parent);
922 data &= ~(ptr->cs | ptr->cclk | ptr->cdti);
923 if (cs) data += ptr->cs;
924 if (cclk) data += ptr->cclk;
925 if (cdti) data += ptr->cdti;
926 envy24_gpiowr(ptr->parent, data);
931 envy24_delta_ak4524_create(device_t dev, void *info, int dir, int num)
933 struct sc_info *sc = info;
934 struct envy24_delta_ak4524_codec *buff = NULL;
937 device_printf(sc->dev, "envy24_delta_ak4524_create(dev, sc, %d, %d)\n", dir, num);
940 buff = malloc(sizeof(*buff), M_ENVY24, M_NOWAIT);
944 if (dir == PCMDIR_REC && sc->adc[num] != NULL)
945 buff->info = ((struct envy24_delta_ak4524_codec *)sc->adc[num])->info;
946 else if (dir == PCMDIR_PLAY && sc->dac[num] != NULL)
947 buff->info = ((struct envy24_delta_ak4524_codec *)sc->dac[num])->info;
949 buff->info = spicds_create(dev, buff, num, envy24_delta_ak4524_ctl);
950 if (buff->info == NULL) {
951 free(buff, M_ENVY24);
963 envy24_delta_ak4524_destroy(void *codec)
965 struct envy24_delta_ak4524_codec *ptr = codec;
969 device_printf(ptr->parent->dev, "envy24_delta_ak4524_destroy()\n");
972 if (ptr->dir == PCMDIR_PLAY) {
973 if (ptr->parent->dac[ptr->num] != NULL)
974 spicds_destroy(ptr->info);
977 if (ptr->parent->adc[ptr->num] != NULL)
978 spicds_destroy(ptr->info);
981 free(codec, M_ENVY24);
985 envy24_delta_ak4524_init(void *codec)
988 u_int32_t gpiomask, gpiodir;
990 struct envy24_delta_ak4524_codec *ptr = codec;
994 device_printf(ptr->parent->dev, "envy24_delta_ak4524_init()\n");
998 gpiomask = envy24_gpiogetmask(ptr->parent);
999 gpiomask &= ~(ENVY24_GPIO_AK4524_CDTI | ENVY24_GPIO_AK4524_CCLK | ENVY24_GPIO_AK4524_CS0 | ENVY24_GPIO_AK4524_CS1);
1000 envy24_gpiosetmask(ptr->parent, gpiomask);
1001 gpiodir = envy24_gpiogetdir(ptr->parent);
1002 gpiodir |= ENVY24_GPIO_AK4524_CDTI | ENVY24_GPIO_AK4524_CCLK | ENVY24_GPIO_AK4524_CS0 | ENVY24_GPIO_AK4524_CS1;
1003 envy24_gpiosetdir(ptr->parent, gpiodir);
1005 ptr->cs = ptr->parent->cfg->cs;
1007 envy24_gpiosetmask(ptr->parent, ENVY24_GPIO_CS8414_STATUS);
1008 envy24_gpiosetdir(ptr->parent, ~ENVY24_GPIO_CS8414_STATUS);
1010 ptr->cs = ENVY24_GPIO_AK4524_CS0;
1012 ptr->cs = ENVY24_GPIO_AK4524_CS1;
1013 ptr->cclk = ENVY24_GPIO_AK4524_CCLK;
1015 ptr->cclk = ptr->parent->cfg->cclk;
1016 ptr->cdti = ptr->parent->cfg->cdti;
1017 spicds_settype(ptr->info, ptr->parent->cfg->type);
1018 spicds_setcif(ptr->info, ptr->parent->cfg->cif);
1019 spicds_setformat(ptr->info,
1020 AK452X_FORMAT_I2S | AK452X_FORMAT_256FSN | AK452X_FORMAT_1X);
1021 spicds_setdvc(ptr->info, AK452X_DVC_DEMOFF);
1022 /* for the time being, init only first codec */
1024 spicds_init(ptr->info);
1026 /* 6fire rear input init test, set ptr->num to 1 for test */
1027 if (ptr->parent->cfg->subvendor == 0x153b && \
1028 ptr->parent->cfg->subdevice == 0x1138 && ptr->num == 100) {
1030 spicds_init(ptr->info);
1031 device_printf(ptr->parent->dev, "6fire rear input init\n");
1032 i2c_wr(ptr, envy24_gpio_i2c_ctl, \
1033 PCA9554_I2CDEV, PCA9554_DIR, 0x80);
1034 i2c_wr(ptr, envy24_gpio_i2c_ctl, \
1035 PCA9554_I2CDEV, PCA9554_OUT, 0x02);
1040 envy24_delta_ak4524_reinit(void *codec)
1042 struct envy24_delta_ak4524_codec *ptr = codec;
1046 device_printf(ptr->parent->dev, "envy24_delta_ak4524_reinit()\n");
1049 spicds_reinit(ptr->info);
1053 envy24_delta_ak4524_setvolume(void *codec, int dir, unsigned int left, unsigned int right)
1055 struct envy24_delta_ak4524_codec *ptr = codec;
1059 device_printf(ptr->parent->dev, "envy24_delta_ak4524_set()\n");
1062 spicds_set(ptr->info, dir, left, right);
1066 There is no need for AK452[48] codec to set sample rate
1068 envy24_delta_ak4524_setrate(struct envy24_delta_ak4524_codec *codec, int which, int rate)
1073 /* -------------------------------------------------------------------- */
1075 /* hardware access routeines */
1080 } envy24_speedtab[] = {
1081 {48000, ENVY24_MT_RATE_48000},
1082 {24000, ENVY24_MT_RATE_24000},
1083 {12000, ENVY24_MT_RATE_12000},
1084 {9600, ENVY24_MT_RATE_9600},
1085 {32000, ENVY24_MT_RATE_32000},
1086 {16000, ENVY24_MT_RATE_16000},
1087 {8000, ENVY24_MT_RATE_8000},
1088 {96000, ENVY24_MT_RATE_96000},
1089 {64000, ENVY24_MT_RATE_64000},
1090 {44100, ENVY24_MT_RATE_44100},
1091 {22050, ENVY24_MT_RATE_22050},
1092 {11025, ENVY24_MT_RATE_11025},
1093 {88200, ENVY24_MT_RATE_88200},
1098 envy24_setspeed(struct sc_info *sc, u_int32_t speed) {
1103 device_printf(sc->dev, "envy24_setspeed(sc, %d)\n", speed);
1106 code = ENVY24_MT_RATE_SPDIF; /* external master clock */
1110 for (i = 0; envy24_speedtab[i].speed != 0; i++) {
1111 if (envy24_speedtab[i].speed == speed)
1114 code = envy24_speedtab[i].code;
1117 device_printf(sc->dev, "envy24_setspeed(): speed %d/code 0x%04x\n", envy24_speedtab[i].speed, code);
1120 envy24_wrmt(sc, ENVY24_MT_RATE, code, 1);
1121 code = envy24_rdmt(sc, ENVY24_MT_RATE, 1);
1122 code &= ENVY24_MT_RATE_MASK;
1123 for (i = 0; envy24_speedtab[i].code < 0x10; i++) {
1124 if (envy24_speedtab[i].code == code)
1127 speed = envy24_speedtab[i].speed;
1133 device_printf(sc->dev, "envy24_setspeed(): return %d\n", speed);
1139 envy24_setvolume(struct sc_info *sc, unsigned ch)
1142 device_printf(sc->dev, "envy24_setvolume(sc, %d)\n", ch);
1144 if (sc->cfg->subvendor==0x153b && sc->cfg->subdevice==0x1138 ) {
1145 envy24_wrmt(sc, ENVY24_MT_VOLIDX, 16, 1);
1146 envy24_wrmt(sc, ENVY24_MT_VOLUME, 0x7f7f, 2);
1147 envy24_wrmt(sc, ENVY24_MT_VOLIDX, 17, 1);
1148 envy24_wrmt(sc, ENVY24_MT_VOLUME, 0x7f7f, 2);
1151 envy24_wrmt(sc, ENVY24_MT_VOLIDX, ch * 2, 1);
1152 envy24_wrmt(sc, ENVY24_MT_VOLUME, 0x7f00 | sc->left[ch], 2);
1153 envy24_wrmt(sc, ENVY24_MT_VOLIDX, ch * 2 + 1, 1);
1154 envy24_wrmt(sc, ENVY24_MT_VOLUME, (sc->right[ch] << 8) | 0x7f, 2);
1158 envy24_mutevolume(struct sc_info *sc, unsigned ch)
1163 device_printf(sc->dev, "envy24_mutevolume(sc, %d)\n", ch);
1165 vol = ENVY24_VOL_MUTE << 8 | ENVY24_VOL_MUTE;
1166 envy24_wrmt(sc, ENVY24_MT_VOLIDX, ch * 2, 1);
1167 envy24_wrmt(sc, ENVY24_MT_VOLUME, vol, 2);
1168 envy24_wrmt(sc, ENVY24_MT_VOLIDX, ch * 2 + 1, 1);
1169 envy24_wrmt(sc, ENVY24_MT_VOLUME, vol, 2);
1173 envy24_gethwptr(struct sc_info *sc, int dir)
1179 device_printf(sc->dev, "envy24_gethwptr(sc, %d)\n", dir);
1181 if (dir == PCMDIR_PLAY) {
1182 rtn = sc->psize / 4;
1183 unit = ENVY24_PLAY_BUFUNIT / 4;
1184 regno = ENVY24_MT_PCNT;
1187 rtn = sc->rsize / 4;
1188 unit = ENVY24_REC_BUFUNIT / 4;
1189 regno = ENVY24_MT_RCNT;
1192 ptr = envy24_rdmt(sc, regno, 2);
1197 device_printf(sc->dev, "envy24_gethwptr(): return %d\n", rtn);
1203 envy24_updintr(struct sc_info *sc, int dir)
1205 int regptr, regintr;
1206 u_int32_t mask, intr;
1207 u_int32_t ptr, size, cnt;
1211 device_printf(sc->dev, "envy24_updintr(sc, %d)\n", dir);
1213 if (dir == PCMDIR_PLAY) {
1215 size = sc->psize / 4;
1216 regptr = ENVY24_MT_PCNT;
1217 regintr = ENVY24_MT_PTERM;
1218 mask = ~ENVY24_MT_INT_PMASK;
1222 size = sc->rsize / 4;
1223 regptr = ENVY24_MT_RCNT;
1224 regintr = ENVY24_MT_RTERM;
1225 mask = ~ENVY24_MT_INT_RMASK;
1228 ptr = size - envy24_rdmt(sc, regptr, 2) - 1;
1230 cnt = blk - ptr % blk - 1;
1236 device_printf(sc->dev, "envy24_updintr():ptr = %d, blk = %d, cnt = %d\n", ptr, blk, cnt);
1238 envy24_wrmt(sc, regintr, cnt, 2);
1239 intr = envy24_rdmt(sc, ENVY24_MT_INT, 1);
1241 device_printf(sc->dev, "envy24_updintr():intr = 0x%02x, mask = 0x%02x\n", intr, mask);
1243 envy24_wrmt(sc, ENVY24_MT_INT, intr & mask, 1);
1245 device_printf(sc->dev, "envy24_updintr():INT-->0x%02x\n",
1246 envy24_rdmt(sc, ENVY24_MT_INT, 1));
1254 envy24_maskintr(struct sc_info *sc, int dir)
1256 u_int32_t mask, intr;
1259 device_printf(sc->dev, "envy24_maskintr(sc, %d)\n", dir);
1261 if (dir == PCMDIR_PLAY)
1262 mask = ENVY24_MT_INT_PMASK;
1264 mask = ENVY24_MT_INT_RMASK;
1265 intr = envy24_rdmt(sc, ENVY24_MT_INT, 1);
1266 envy24_wrmt(sc, ENVY24_MT_INT, intr | mask, 1);
1273 envy24_checkintr(struct sc_info *sc, int dir)
1275 u_int32_t mask, stat, intr, rtn;
1278 device_printf(sc->dev, "envy24_checkintr(sc, %d)\n", dir);
1280 intr = envy24_rdmt(sc, ENVY24_MT_INT, 1);
1281 if (dir == PCMDIR_PLAY) {
1282 if ((rtn = intr & ENVY24_MT_INT_PSTAT) != 0) {
1283 mask = ~ENVY24_MT_INT_RSTAT;
1284 stat = ENVY24_MT_INT_PSTAT | ENVY24_MT_INT_PMASK;
1285 envy24_wrmt(sc, ENVY24_MT_INT, (intr & mask) | stat, 1);
1289 if ((rtn = intr & ENVY24_MT_INT_RSTAT) != 0) {
1290 mask = ~ENVY24_MT_INT_PSTAT;
1291 stat = ENVY24_MT_INT_RSTAT | ENVY24_MT_INT_RMASK;
1292 envy24_wrmt(sc, ENVY24_MT_INT, (intr & mask) | stat, 1);
1300 envy24_start(struct sc_info *sc, int dir)
1305 device_printf(sc->dev, "envy24_start(sc, %d)\n", dir);
1307 if (dir == PCMDIR_PLAY)
1308 sw = ENVY24_MT_PCTL_PSTART;
1310 sw = ENVY24_MT_PCTL_RSTART;
1312 stat = envy24_rdmt(sc, ENVY24_MT_PCTL, 1);
1313 envy24_wrmt(sc, ENVY24_MT_PCTL, stat | sw, 1);
1316 device_printf(sc->dev, "PADDR:0x%08x\n", envy24_rdmt(sc, ENVY24_MT_PADDR, 4));
1317 device_printf(sc->dev, "PCNT:%ld\n", envy24_rdmt(sc, ENVY24_MT_PCNT, 2));
1324 envy24_stop(struct sc_info *sc, int dir)
1329 device_printf(sc->dev, "envy24_stop(sc, %d)\n", dir);
1331 if (dir == PCMDIR_PLAY)
1332 sw = ~ENVY24_MT_PCTL_PSTART;
1334 sw = ~ENVY24_MT_PCTL_RSTART;
1336 stat = envy24_rdmt(sc, ENVY24_MT_PCTL, 1);
1337 envy24_wrmt(sc, ENVY24_MT_PCTL, stat & sw, 1);
1343 envy24_route(struct sc_info *sc, int dac, int class, int adc, int rev)
1345 u_int32_t reg, mask;
1346 u_int32_t left, right;
1349 device_printf(sc->dev, "envy24_route(sc, %d, %d, %d, %d)\n",
1350 dac, class, adc, rev);
1352 /* parameter pattern check */
1353 if (dac < 0 || ENVY24_ROUTE_DAC_SPDIF < dac)
1355 if (class == ENVY24_ROUTE_CLASS_MIX &&
1356 (dac != ENVY24_ROUTE_DAC_1 && dac != ENVY24_ROUTE_DAC_SPDIF))
1359 left = ENVY24_ROUTE_RIGHT;
1360 right = ENVY24_ROUTE_LEFT;
1363 left = ENVY24_ROUTE_LEFT;
1364 right = ENVY24_ROUTE_RIGHT;
1367 if (dac == ENVY24_ROUTE_DAC_SPDIF) {
1368 reg = class | class << 2 |
1369 ((adc << 1 | left) | left << 3) << 8 |
1370 ((adc << 1 | right) | right << 3) << 12;
1372 device_printf(sc->dev, "envy24_route(): MT_SPDOUT-->0x%04x\n", reg);
1374 envy24_wrmt(sc, ENVY24_MT_SPDOUT, reg, 2);
1377 mask = ~(0x0303 << dac * 2);
1378 reg = envy24_rdmt(sc, ENVY24_MT_PSDOUT, 2);
1379 reg = (reg & mask) | ((class | class << 8) << dac * 2);
1381 device_printf(sc->dev, "envy24_route(): MT_PSDOUT-->0x%04x\n", reg);
1383 envy24_wrmt(sc, ENVY24_MT_PSDOUT, reg, 2);
1384 mask = ~(0xff << dac * 8);
1385 reg = envy24_rdmt(sc, ENVY24_MT_RECORD, 4);
1386 reg = (reg & mask) |
1387 (((adc << 1 | left) | left << 3) |
1388 ((adc << 1 | right) | right << 3) << 4) << dac * 8;
1390 device_printf(sc->dev, "envy24_route(): MT_RECORD-->0x%08x\n", reg);
1392 envy24_wrmt(sc, ENVY24_MT_RECORD, reg, 4);
1394 /* 6fire rear input init test */
1395 envy24_wrmt(sc, ENVY24_MT_RECORD, 0x00, 4);
1401 /* -------------------------------------------------------------------- */
1403 /* buffer copy routines */
1405 envy24_p32sl(struct sc_chinfo *ch)
1410 int src, dst, ssize, dsize, slot;
1413 length = sndbuf_getready(ch->buffer) / 8;
1414 dmabuf = ch->parent->pbuf;
1415 data = (u_int32_t *)ch->data;
1416 src = sndbuf_getreadyptr(ch->buffer) / 4;
1417 dst = src / 2 + ch->offset;
1418 ssize = ch->size / 4;
1419 dsize = ch->size / 8;
1422 for (i = 0; i < length; i++) {
1423 dmabuf[dst * ENVY24_PLAY_CHNUM + slot].buffer = data[src];
1424 dmabuf[dst * ENVY24_PLAY_CHNUM + slot + 1].buffer = data[src + 1];
1435 envy24_p16sl(struct sc_chinfo *ch)
1440 int src, dst, ssize, dsize, slot;
1444 device_printf(ch->parent->dev, "envy24_p16sl()\n");
1446 length = sndbuf_getready(ch->buffer) / 4;
1447 dmabuf = ch->parent->pbuf;
1448 data = (u_int16_t *)ch->data;
1449 src = sndbuf_getreadyptr(ch->buffer) / 2;
1450 dst = src / 2 + ch->offset;
1451 ssize = ch->size / 2;
1452 dsize = ch->size / 4;
1455 device_printf(ch->parent->dev, "envy24_p16sl():%lu-->%lu(%lu)\n", src, dst, length);
1458 for (i = 0; i < length; i++) {
1459 dmabuf[dst * ENVY24_PLAY_CHNUM + slot].buffer = (u_int32_t)data[src] << 16;
1460 dmabuf[dst * ENVY24_PLAY_CHNUM + slot + 1].buffer = (u_int32_t)data[src + 1] << 16;
1463 printf("%08x", dmabuf[dst * ENVY24_PLAY_CHNUM + slot]);
1464 printf("%08x", dmabuf[dst * ENVY24_PLAY_CHNUM + slot + 1]);
1480 envy24_p8u(struct sc_chinfo *ch)
1485 int src, dst, ssize, dsize, slot;
1488 length = sndbuf_getready(ch->buffer) / 2;
1489 dmabuf = ch->parent->pbuf;
1490 data = (u_int8_t *)ch->data;
1491 src = sndbuf_getreadyptr(ch->buffer);
1492 dst = src / 2 + ch->offset;
1494 dsize = ch->size / 4;
1497 for (i = 0; i < length; i++) {
1498 dmabuf[dst * ENVY24_PLAY_CHNUM + slot].buffer = ((u_int32_t)data[src] ^ 0x80) << 24;
1499 dmabuf[dst * ENVY24_PLAY_CHNUM + slot + 1].buffer = ((u_int32_t)data[src + 1] ^ 0x80) << 24;
1510 envy24_r32sl(struct sc_chinfo *ch)
1515 int src, dst, ssize, dsize, slot;
1518 length = sndbuf_getfree(ch->buffer) / 8;
1519 dmabuf = ch->parent->rbuf;
1520 data = (u_int32_t *)ch->data;
1521 dst = sndbuf_getfreeptr(ch->buffer) / 4;
1522 src = dst / 2 + ch->offset;
1523 dsize = ch->size / 4;
1524 ssize = ch->size / 8;
1525 slot = (ch->num - ENVY24_CHAN_REC_ADC1) * 2;
1527 for (i = 0; i < length; i++) {
1528 data[dst] = dmabuf[src * ENVY24_REC_CHNUM + slot].buffer;
1529 data[dst + 1] = dmabuf[src * ENVY24_REC_CHNUM + slot + 1].buffer;
1540 envy24_r16sl(struct sc_chinfo *ch)
1545 int src, dst, ssize, dsize, slot;
1548 length = sndbuf_getfree(ch->buffer) / 4;
1549 dmabuf = ch->parent->rbuf;
1550 data = (u_int16_t *)ch->data;
1551 dst = sndbuf_getfreeptr(ch->buffer) / 2;
1552 src = dst / 2 + ch->offset;
1553 dsize = ch->size / 2;
1554 ssize = ch->size / 8;
1555 slot = (ch->num - ENVY24_CHAN_REC_ADC1) * 2;
1557 for (i = 0; i < length; i++) {
1558 data[dst] = dmabuf[src * ENVY24_REC_CHNUM + slot].buffer;
1559 data[dst + 1] = dmabuf[src * ENVY24_REC_CHNUM + slot + 1].buffer;
1569 /* -------------------------------------------------------------------- */
1571 /* channel interface */
1573 envy24chan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir)
1575 struct sc_info *sc = (struct sc_info *)devinfo;
1576 struct sc_chinfo *ch;
1580 device_printf(sc->dev, "envy24chan_init(obj, devinfo, b, c, %d)\n", dir);
1582 snd_mtxlock(sc->lock);
1583 if ((sc->chnum > ENVY24_CHAN_PLAY_SPDIF && dir != PCMDIR_REC) ||
1584 (sc->chnum < ENVY24_CHAN_REC_ADC1 && dir != PCMDIR_PLAY)) {
1585 snd_mtxunlock(sc->lock);
1590 ch = &sc->chan[num];
1591 ch->size = 8 * ENVY24_SAMPLE_NUM;
1592 ch->data = malloc(ch->size, M_ENVY24, M_NOWAIT);
1593 if (ch->data == NULL) {
1602 /* set channel map */
1603 ch->num = envy24_chanmap[num];
1604 snd_mtxunlock(sc->lock);
1605 sndbuf_setup(ch->buffer, ch->data, ch->size);
1606 snd_mtxlock(sc->lock);
1607 /* these 2 values are dummy */
1611 snd_mtxunlock(sc->lock);
1617 envy24chan_free(kobj_t obj, void *data)
1619 struct sc_chinfo *ch = data;
1620 struct sc_info *sc = ch->parent;
1623 device_printf(sc->dev, "envy24chan_free()\n");
1625 snd_mtxlock(sc->lock);
1626 if (ch->data != NULL) {
1627 free(ch->data, M_ENVY24);
1630 snd_mtxunlock(sc->lock);
1636 envy24chan_setformat(kobj_t obj, void *data, u_int32_t format)
1638 struct sc_chinfo *ch = data;
1639 struct sc_info *sc = ch->parent;
1640 struct envy24_emldma *emltab;
1641 /* unsigned int bcnt, bsize; */
1645 device_printf(sc->dev, "envy24chan_setformat(obj, data, 0x%08x)\n", format);
1647 snd_mtxlock(sc->lock);
1648 /* check and get format related information */
1649 if (ch->dir == PCMDIR_PLAY)
1650 emltab = envy24_pemltab;
1652 emltab = envy24_remltab;
1653 if (emltab == NULL) {
1654 snd_mtxunlock(sc->lock);
1657 for (i = 0; emltab[i].format != 0; i++)
1658 if (emltab[i].format == format)
1660 if (emltab[i].format == 0) {
1661 snd_mtxunlock(sc->lock);
1665 /* set format information */
1666 ch->format = format;
1667 ch->emldma = emltab[i].emldma;
1668 if (ch->unit > emltab[i].unit)
1669 ch->blk *= ch->unit / emltab[i].unit;
1671 ch->blk /= emltab[i].unit / ch->unit;
1672 ch->unit = emltab[i].unit;
1674 /* set channel buffer information */
1675 ch->size = ch->unit * ENVY24_SAMPLE_NUM;
1677 if (ch->dir == PCMDIR_PLAY)
1678 bsize = ch->blk * 4 / ENVY24_PLAY_BUFUNIT;
1680 bsize = ch->blk * 4 / ENVY24_REC_BUFUNIT;
1682 bcnt = ch->size / bsize;
1683 sndbuf_resize(ch->buffer, bcnt, bsize);
1685 snd_mtxunlock(sc->lock);
1688 device_printf(sc->dev, "envy24chan_setformat(): return 0x%08x\n", 0);
1694 IMPLEMENT NOTICE: In this driver, setspeed function only do setting
1695 of speed information value. And real hardware speed setting is done
1696 at start triggered(see envy24chan_trigger()). So, at this function
1697 is called, any value that ENVY24 can use is able to set. But, at
1698 start triggerd, some other channel is running, and that channel's
1699 speed isn't same with, then trigger function will fail.
1702 envy24chan_setspeed(kobj_t obj, void *data, u_int32_t speed)
1704 struct sc_chinfo *ch = data;
1705 u_int32_t val, prev;
1709 device_printf(ch->parent->dev, "envy24chan_setspeed(obj, data, %d)\n", speed);
1712 for (i = 0; (val = envy24_speed[i]) != 0; i++) {
1713 if (abs(val - speed) < abs(prev - speed))
1721 device_printf(ch->parent->dev, "envy24chan_setspeed(): return %d\n", ch->speed);
1727 envy24chan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
1729 struct sc_chinfo *ch = data;
1730 /* struct sc_info *sc = ch->parent; */
1731 u_int32_t size, prev;
1732 unsigned int bcnt, bsize;
1735 device_printf(sc->dev, "envy24chan_setblocksize(obj, data, %d)\n", blocksize);
1738 /* snd_mtxlock(sc->lock); */
1739 for (size = ch->size / 2; size > 0; size /= 2) {
1740 if (abs(size - blocksize) < abs(prev - blocksize))
1746 ch->blk = prev / ch->unit;
1747 if (ch->dir == PCMDIR_PLAY)
1748 ch->blk *= ENVY24_PLAY_BUFUNIT / 4;
1750 ch->blk *= ENVY24_REC_BUFUNIT / 4;
1751 /* set channel buffer information */
1752 /* ch->size = ch->unit * ENVY24_SAMPLE_NUM; */
1753 if (ch->dir == PCMDIR_PLAY)
1754 bsize = ch->blk * 4 / ENVY24_PLAY_BUFUNIT;
1756 bsize = ch->blk * 4 / ENVY24_REC_BUFUNIT;
1758 bcnt = ch->size / bsize;
1759 sndbuf_resize(ch->buffer, bcnt, bsize);
1760 /* snd_mtxunlock(sc->lock); */
1763 device_printf(sc->dev, "envy24chan_setblocksize(): return %d\n", prev);
1768 /* semantic note: must start at beginning of buffer */
1770 envy24chan_trigger(kobj_t obj, void *data, int go)
1772 struct sc_chinfo *ch = data;
1773 struct sc_info *sc = ch->parent;
1780 device_printf(sc->dev, "envy24chan_trigger(obj, data, %d)\n", go);
1782 snd_mtxlock(sc->lock);
1783 if (ch->dir == PCMDIR_PLAY)
1790 device_printf(sc->dev, "envy24chan_trigger(): start\n");
1792 /* check or set channel speed */
1793 if (sc->run[0] == 0 && sc->run[1] == 0) {
1794 sc->speed = envy24_setspeed(sc, ch->speed);
1795 sc->caps[0].minspeed = sc->caps[0].maxspeed = sc->speed;
1796 sc->caps[1].minspeed = sc->caps[1].maxspeed = sc->speed;
1798 else if (ch->speed != 0 && ch->speed != sc->speed) {
1803 ch->channel->speed = sc->speed;
1804 /* start or enable channel */
1806 if (sc->run[slot] == 1) {
1809 sc->blk[slot] = ch->blk;
1812 ptr = envy24_gethwptr(sc, ch->dir);
1813 ch->offset = ((ptr / ch->blk + 1) * ch->blk %
1814 (ch->size / 4)) * 4 / ch->unit;
1815 if (ch->blk < sc->blk[slot])
1816 sc->blk[slot] = ch->blk;
1818 if (ch->dir == PCMDIR_PLAY) {
1820 envy24_setvolume(sc, ch->num);
1822 envy24_updintr(sc, ch->dir);
1823 if (sc->run[slot] == 1)
1824 envy24_start(sc, ch->dir);
1827 case PCMTRIG_EMLDMAWR:
1829 device_printf(sc->dev, "envy24chan_trigger(): emldmawr\n");
1837 case PCMTRIG_EMLDMARD:
1839 device_printf(sc->dev, "envy24chan_trigger(): emldmard\n");
1850 device_printf(sc->dev, "envy24chan_trigger(): abort\n");
1854 if (ch->dir == PCMDIR_PLAY)
1855 envy24_mutevolume(sc, ch->num);
1856 if (sc->run[slot] == 0) {
1857 envy24_stop(sc, ch->dir);
1861 else if (ch->blk == sc->blk[slot]) {
1862 sc->blk[slot] = ENVY24_SAMPLE_NUM / 2;
1863 for (i = 0; i < ENVY24_CHAN_NUM; i++) {
1864 if (sc->chan[i].dir == ch->dir &&
1865 sc->chan[i].run == 1 &&
1866 sc->chan[i].blk < sc->blk[slot])
1867 sc->blk[slot] = sc->chan[i].blk;
1869 if (ch->blk != sc->blk[slot])
1870 envy24_updintr(sc, ch->dir);
1877 snd_mtxunlock(sc->lock);
1882 envy24chan_getptr(kobj_t obj, void *data)
1884 struct sc_chinfo *ch = data;
1885 struct sc_info *sc = ch->parent;
1889 device_printf(sc->dev, "envy24chan_getptr()\n");
1891 snd_mtxlock(sc->lock);
1892 ptr = envy24_gethwptr(sc, ch->dir);
1893 rtn = ptr * ch->unit;
1894 snd_mtxunlock(sc->lock);
1897 device_printf(sc->dev, "envy24chan_getptr(): return %d\n",
1903 static struct pcmchan_caps *
1904 envy24chan_getcaps(kobj_t obj, void *data)
1906 struct sc_chinfo *ch = data;
1907 struct sc_info *sc = ch->parent;
1908 struct pcmchan_caps *rtn;
1911 device_printf(sc->dev, "envy24chan_getcaps()\n");
1913 snd_mtxlock(sc->lock);
1914 if (ch->dir == PCMDIR_PLAY) {
1915 if (sc->run[0] == 0)
1916 rtn = &envy24_playcaps;
1921 if (sc->run[1] == 0)
1922 rtn = &envy24_reccaps;
1926 snd_mtxunlock(sc->lock);
1931 static kobj_method_t envy24chan_methods[] = {
1932 KOBJMETHOD(channel_init, envy24chan_init),
1933 KOBJMETHOD(channel_free, envy24chan_free),
1934 KOBJMETHOD(channel_setformat, envy24chan_setformat),
1935 KOBJMETHOD(channel_setspeed, envy24chan_setspeed),
1936 KOBJMETHOD(channel_setblocksize, envy24chan_setblocksize),
1937 KOBJMETHOD(channel_trigger, envy24chan_trigger),
1938 KOBJMETHOD(channel_getptr, envy24chan_getptr),
1939 KOBJMETHOD(channel_getcaps, envy24chan_getcaps),
1942 CHANNEL_DECLARE(envy24chan);
1944 /* -------------------------------------------------------------------- */
1946 /* mixer interface */
1949 envy24mixer_init(struct snd_mixer *m)
1951 struct sc_info *sc = mix_getdevinfo(m);
1954 device_printf(sc->dev, "envy24mixer_init()\n");
1959 /* set volume control rate */
1960 snd_mtxlock(sc->lock);
1961 envy24_wrmt(sc, ENVY24_MT_VOLRATE, 0x30, 1); /* 0x30 is default value */
1963 mix_setdevs(m, ENVY24_MIX_MASK);
1964 mix_setrecdevs(m, ENVY24_MIX_REC_MASK);
1965 snd_mtxunlock(sc->lock);
1971 envy24mixer_reinit(struct snd_mixer *m)
1973 struct sc_info *sc = mix_getdevinfo(m);
1978 device_printf(sc->dev, "envy24mixer_reinit()\n");
1985 envy24mixer_uninit(struct snd_mixer *m)
1987 struct sc_info *sc = mix_getdevinfo(m);
1992 device_printf(sc->dev, "envy24mixer_uninit()\n");
1999 envy24mixer_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right)
2001 struct sc_info *sc = mix_getdevinfo(m);
2002 int ch = envy24_mixmap[dev];
2008 if (dev == 0 && sc->cfg->codec->setvolume == NULL)
2010 if (dev != 0 && ch == -1)
2012 hwch = envy24_chanmap[ch];
2014 device_printf(sc->dev, "envy24mixer_set(m, %d, %d, %d)\n",
2018 snd_mtxlock(sc->lock);
2020 for (i = 0; i < sc->dacn; i++) {
2021 sc->cfg->codec->setvolume(sc->dac[i], PCMDIR_PLAY, left, right);
2025 /* set volume value for hardware */
2026 if ((sc->left[hwch] = 100 - left) > ENVY24_VOL_MIN)
2027 sc->left[hwch] = ENVY24_VOL_MUTE;
2028 if ((sc->right[hwch] = 100 - right) > ENVY24_VOL_MIN)
2029 sc->right[hwch] = ENVY24_VOL_MUTE;
2031 /* set volume for record channel and running play channel */
2032 if (hwch > ENVY24_CHAN_PLAY_SPDIF || sc->chan[ch].run)
2033 envy24_setvolume(sc, hwch);
2035 snd_mtxunlock(sc->lock);
2037 return right << 8 | left;
2041 envy24mixer_setrecsrc(struct snd_mixer *m, u_int32_t src)
2043 struct sc_info *sc = mix_getdevinfo(m);
2044 int ch = envy24_mixmap[src];
2046 device_printf(sc->dev, "envy24mixer_setrecsrc(m, %d)\n", src);
2049 if (ch > ENVY24_CHAN_PLAY_SPDIF)
2054 static kobj_method_t envy24mixer_methods[] = {
2055 KOBJMETHOD(mixer_init, envy24mixer_init),
2056 KOBJMETHOD(mixer_reinit, envy24mixer_reinit),
2057 KOBJMETHOD(mixer_uninit, envy24mixer_uninit),
2058 KOBJMETHOD(mixer_set, envy24mixer_set),
2059 KOBJMETHOD(mixer_setrecsrc, envy24mixer_setrecsrc),
2062 MIXER_DECLARE(envy24mixer);
2064 /* -------------------------------------------------------------------- */
2066 /* The interrupt handler */
2068 envy24_intr(void *p)
2070 struct sc_info *sc = (struct sc_info *)p;
2071 struct sc_chinfo *ch;
2072 u_int32_t ptr, dsize, feed;
2076 device_printf(sc->dev, "envy24_intr()\n");
2078 snd_mtxlock(sc->lock);
2079 if (envy24_checkintr(sc, PCMDIR_PLAY)) {
2081 device_printf(sc->dev, "envy24_intr(): play\n");
2083 dsize = sc->psize / 4;
2084 ptr = dsize - envy24_rdmt(sc, ENVY24_MT_PCNT, 2) - 1;
2086 device_printf(sc->dev, "envy24_intr(): ptr = %d-->", ptr);
2088 ptr -= ptr % sc->blk[0];
2089 feed = (ptr + dsize - sc->intr[0]) % dsize;
2091 printf("%d intr = %d feed = %d\n", ptr, sc->intr[0], feed);
2093 for (i = ENVY24_CHAN_PLAY_DAC1; i <= ENVY24_CHAN_PLAY_SPDIF; i++) {
2097 device_printf(sc->dev, "envy24_intr(): chan[%d].blk = %d\n", i, ch->blk);
2099 if (ch->run && ch->blk <= feed) {
2100 snd_mtxunlock(sc->lock);
2101 chn_intr(ch->channel);
2102 snd_mtxlock(sc->lock);
2106 envy24_updintr(sc, PCMDIR_PLAY);
2108 if (envy24_checkintr(sc, PCMDIR_REC)) {
2110 device_printf(sc->dev, "envy24_intr(): rec\n");
2112 dsize = sc->rsize / 4;
2113 ptr = dsize - envy24_rdmt(sc, ENVY24_MT_RCNT, 2) - 1;
2114 ptr -= ptr % sc->blk[1];
2115 feed = (ptr + dsize - sc->intr[1]) % dsize;
2116 for (i = ENVY24_CHAN_REC_ADC1; i <= ENVY24_CHAN_REC_SPDIF; i++) {
2118 if (ch->run && ch->blk <= feed) {
2119 snd_mtxunlock(sc->lock);
2120 chn_intr(ch->channel);
2121 snd_mtxlock(sc->lock);
2125 envy24_updintr(sc, PCMDIR_REC);
2127 snd_mtxunlock(sc->lock);
2133 * Probe and attach the card
2137 envy24_pci_probe(device_t dev)
2143 printf("envy24_pci_probe()\n");
2145 if (pci_get_device(dev) == PCID_ENVY24 &&
2146 pci_get_vendor(dev) == PCIV_ENVY24) {
2147 sv = pci_get_subvendor(dev);
2148 sd = pci_get_subdevice(dev);
2149 for (i = 0; cfg_table[i].subvendor != 0 || cfg_table[i].subdevice != 0; i++) {
2150 if (cfg_table[i].subvendor == sv &&
2151 cfg_table[i].subdevice == sd) {
2155 device_set_desc(dev, cfg_table[i].name);
2157 printf("envy24_pci_probe(): return 0\n");
2163 printf("envy24_pci_probe(): return ENXIO\n");
2170 envy24_dmapsetmap(void *arg, bus_dma_segment_t *segs, int nseg, int error)
2172 struct sc_info *sc = (struct sc_info *)arg;
2174 sc->paddr = segs->ds_addr;
2176 device_printf(sc->dev, "envy24_dmapsetmap()\n");
2178 printf("envy24(play): setmap %lx, %lx; ",
2179 (unsigned long)segs->ds_addr,
2180 (unsigned long)segs->ds_len);
2181 printf("%p -> %lx\n", sc->pmap, sc->paddr);
2187 envy24_dmarsetmap(void *arg, bus_dma_segment_t *segs, int nseg, int error)
2189 struct sc_info *sc = (struct sc_info *)arg;
2191 sc->raddr = segs->ds_addr;
2193 device_printf(sc->dev, "envy24_dmarsetmap()\n");
2195 printf("envy24(record): setmap %lx, %lx; ",
2196 (unsigned long)segs->ds_addr,
2197 (unsigned long)segs->ds_len);
2198 printf("%p -> %lx\n", sc->rmap, sc->raddr);
2204 envy24_dmafree(struct sc_info *sc)
2207 device_printf(sc->dev, "envy24_dmafree():");
2208 printf(" sc->raddr(0x%08x)", (u_int32_t)sc->raddr);
2209 printf(" sc->paddr(0x%08x)", (u_int32_t)sc->paddr);
2210 if (sc->rbuf) printf(" sc->rbuf(0x%08x)", (u_int32_t)sc->rbuf);
2211 else printf(" sc->rbuf(null)");
2212 if (sc->pbuf) printf(" sc->pbuf(0x%08x)\n", (u_int32_t)sc->pbuf);
2213 else printf(" sc->pbuf(null)\n");
2217 bus_dmamap_unload(sc->dmat, sc->rmap);
2219 bus_dmamap_unload(sc->dmat, sc->pmap);
2221 bus_dmamem_free(sc->dmat, sc->rbuf, sc->rmap);
2223 bus_dmamem_free(sc->dmat, sc->pbuf, sc->pmap);
2225 bus_dmamap_unload(sc->dmat, sc->rmap);
2226 bus_dmamap_unload(sc->dmat, sc->pmap);
2227 bus_dmamem_free(sc->dmat, sc->rbuf, sc->rmap);
2228 bus_dmamem_free(sc->dmat, sc->pbuf, sc->pmap);
2231 sc->raddr = sc->paddr = 0;
2239 envy24_dmainit(struct sc_info *sc)
2243 device_printf(sc->dev, "envy24_dmainit()\n");
2246 sc->psize = ENVY24_PLAY_BUFUNIT * ENVY24_SAMPLE_NUM;
2247 sc->rsize = ENVY24_REC_BUFUNIT * ENVY24_SAMPLE_NUM;
2250 sc->paddr = sc->raddr = 0;
2251 sc->blk[0] = sc->blk[1] = 0;
2253 /* allocate DMA buffer */
2255 device_printf(sc->dev, "envy24_dmainit(): bus_dmamem_alloc(): sc->pbuf\n");
2257 if (bus_dmamem_alloc(sc->dmat, (void **)&sc->pbuf, BUS_DMA_NOWAIT, &sc->pmap))
2260 device_printf(sc->dev, "envy24_dmainit(): bus_dmamem_alloc(): sc->rbuf\n");
2262 if (bus_dmamem_alloc(sc->dmat, (void **)&sc->rbuf, BUS_DMA_NOWAIT, &sc->rmap))
2265 device_printf(sc->dev, "envy24_dmainit(): bus_dmamem_load(): sc->pmap\n");
2267 if (bus_dmamap_load(sc->dmat, sc->pmap, sc->pbuf, sc->psize, envy24_dmapsetmap, sc, 0))
2270 device_printf(sc->dev, "envy24_dmainit(): bus_dmamem_load(): sc->rmap\n");
2272 if (bus_dmamap_load(sc->dmat, sc->rmap, sc->rbuf, sc->rsize, envy24_dmarsetmap, sc, 0))
2274 bzero(sc->pbuf, sc->psize);
2275 bzero(sc->rbuf, sc->rsize);
2277 /* set values to register */
2279 device_printf(sc->dev, "paddr(0x%08x)\n", sc->paddr);
2281 envy24_wrmt(sc, ENVY24_MT_PADDR, sc->paddr, 4);
2283 device_printf(sc->dev, "PADDR-->(0x%08x)\n", envy24_rdmt(sc, ENVY24_MT_PADDR, 4));
2284 device_printf(sc->dev, "psize(%ld)\n", sc->psize / 4 - 1);
2286 envy24_wrmt(sc, ENVY24_MT_PCNT, sc->psize / 4 - 1, 2);
2288 device_printf(sc->dev, "PCNT-->(%ld)\n", envy24_rdmt(sc, ENVY24_MT_PCNT, 2));
2290 envy24_wrmt(sc, ENVY24_MT_RADDR, sc->raddr, 4);
2291 envy24_wrmt(sc, ENVY24_MT_RCNT, sc->rsize / 4 - 1, 2);
2300 envy24_putcfg(struct sc_info *sc)
2302 device_printf(sc->dev, "system configuration\n");
2303 printf(" SubVendorID: 0x%04x, SubDeviceID: 0x%04x\n",
2304 sc->cfg->subvendor, sc->cfg->subdevice);
2305 printf(" XIN2 Clock Source: ");
2306 switch (sc->cfg->scfg & PCIM_SCFG_XIN2) {
2308 printf("22.5792MHz(44.1kHz*512)\n");
2311 printf("16.9344MHz(44.1kHz*384)\n");
2314 printf("from external clock synthesizer chip\n");
2317 printf("illegal system setting\n");
2319 printf(" MPU-401 UART(s) #: ");
2320 if (sc->cfg->scfg & PCIM_SCFG_MPU)
2324 printf(" AC'97 codec: ");
2325 if (sc->cfg->scfg & PCIM_SCFG_AC97)
2326 printf("not exist\n");
2330 printf("%d\n", sc->adcn);
2332 printf("%d\n", sc->dacn);
2333 printf(" Multi-track converter type: ");
2334 if ((sc->cfg->acl & PCIM_ACL_MTC) == 0) {
2335 printf("AC'97(SDATA_OUT:");
2336 if (sc->cfg->acl & PCIM_ACL_OMODE)
2340 printf("|SDATA_IN:");
2341 if (sc->cfg->acl & PCIM_ACL_IMODE)
2349 if (sc->cfg->i2s & PCIM_I2S_VOL)
2350 printf("with volume, ");
2351 if (sc->cfg->i2s & PCIM_I2S_96KHZ)
2352 printf("96KHz support, ");
2353 switch (sc->cfg->i2s & PCIM_I2S_RES) {
2354 case PCIM_I2S_16BIT:
2355 printf("16bit resolution, ");
2357 case PCIM_I2S_18BIT:
2358 printf("18bit resolution, ");
2360 case PCIM_I2S_20BIT:
2361 printf("20bit resolution, ");
2363 case PCIM_I2S_24BIT:
2364 printf("24bit resolution, ");
2367 printf("ID#0x%x)\n", sc->cfg->i2s & PCIM_I2S_ID);
2369 printf(" S/PDIF(IN/OUT): ");
2370 if (sc->cfg->spdif & PCIM_SPDIF_IN)
2374 if (sc->cfg->spdif & PCIM_SPDIF_OUT)
2378 if (sc->cfg->spdif & (PCIM_SPDIF_IN | PCIM_SPDIF_OUT))
2379 printf("ID# 0x%02x\n", (sc->cfg->spdif & PCIM_SPDIF_ID) >> 2);
2380 printf(" GPIO(mask/dir/state): 0x%02x/0x%02x/0x%02x\n",
2381 sc->cfg->gpiomask, sc->cfg->gpiodir, sc->cfg->gpiostate);
2385 envy24_init(struct sc_info *sc)
2395 device_printf(sc->dev, "envy24_init()\n");
2399 envy24_wrcs(sc, ENVY24_CCS_CTL, ENVY24_CCS_CTL_RESET | ENVY24_CCS_CTL_NATIVE, 1);
2401 envy24_wrcs(sc, ENVY24_CCS_CTL, ENVY24_CCS_CTL_NATIVE, 1);
2404 /* legacy hardware disable */
2405 data = pci_read_config(sc->dev, PCIR_LAC, 2);
2406 data |= PCIM_LAC_DISABLE;
2407 pci_write_config(sc->dev, PCIR_LAC, data, 2);
2409 /* check system configuration */
2411 for (i = 0; cfg_table[i].subvendor != 0 || cfg_table[i].subdevice != 0; i++) {
2412 /* 1st: search configuration from table */
2413 sv = pci_get_subvendor(sc->dev);
2414 sd = pci_get_subdevice(sc->dev);
2415 if (sv == cfg_table[i].subvendor && sd == cfg_table[i].subdevice) {
2417 device_printf(sc->dev, "Set configuration from table\n");
2419 sc->cfg = &cfg_table[i];
2423 if (sc->cfg == NULL) {
2424 /* 2nd: read configuration from table */
2425 sc->cfg = envy24_rom2cfg(sc);
2427 sc->adcn = ((sc->cfg->scfg & PCIM_SCFG_ADC) >> 2) + 1;
2428 sc->dacn = (sc->cfg->scfg & PCIM_SCFG_DAC) + 1;
2430 if (1 /* bootverbose */) {
2434 /* set system configuration */
2435 pci_write_config(sc->dev, PCIR_SCFG, sc->cfg->scfg, 1);
2436 pci_write_config(sc->dev, PCIR_ACL, sc->cfg->acl, 1);
2437 pci_write_config(sc->dev, PCIR_I2S, sc->cfg->i2s, 1);
2438 pci_write_config(sc->dev, PCIR_SPDIF, sc->cfg->spdif, 1);
2439 envy24_gpiosetmask(sc, sc->cfg->gpiomask);
2440 envy24_gpiosetdir(sc, sc->cfg->gpiodir);
2441 envy24_gpiowr(sc, sc->cfg->gpiostate);
2442 for (i = 0; i < sc->adcn; i++) {
2443 sc->adc[i] = sc->cfg->codec->create(sc->dev, sc, PCMDIR_REC, i);
2444 sc->cfg->codec->init(sc->adc[i]);
2446 for (i = 0; i < sc->dacn; i++) {
2447 sc->dac[i] = sc->cfg->codec->create(sc->dev, sc, PCMDIR_PLAY, i);
2448 sc->cfg->codec->init(sc->dac[i]);
2451 /* initialize DMA buffer */
2453 device_printf(sc->dev, "envy24_init(): initialize DMA buffer\n");
2455 if (envy24_dmainit(sc))
2458 /* initialize status */
2459 sc->run[0] = sc->run[1] = 0;
2460 sc->intr[0] = sc->intr[1] = 0;
2462 sc->caps[0].fmtlist = envy24_playfmt;
2463 sc->caps[1].fmtlist = envy24_recfmt;
2465 /* set channel router */
2466 envy24_route(sc, ENVY24_ROUTE_DAC_1, ENVY24_ROUTE_CLASS_MIX, 0, 0);
2467 envy24_route(sc, ENVY24_ROUTE_DAC_SPDIF, ENVY24_ROUTE_CLASS_DMA, 0, 0);
2468 /* envy24_route(sc, ENVY24_ROUTE_DAC_SPDIF, ENVY24_ROUTE_CLASS_MIX, 0, 0); */
2470 /* set macro interrupt mask */
2471 data = envy24_rdcs(sc, ENVY24_CCS_IMASK, 1);
2472 envy24_wrcs(sc, ENVY24_CCS_IMASK, data & ~ENVY24_CCS_IMASK_PMT, 1);
2473 data = envy24_rdcs(sc, ENVY24_CCS_IMASK, 1);
2475 device_printf(sc->dev, "envy24_init(): CCS_IMASK-->0x%02x\n", data);
2482 envy24_alloc_resource(struct sc_info *sc)
2484 /* allocate I/O port resource */
2485 sc->csid = PCIR_CCS;
2486 sc->cs = bus_alloc_resource_any(sc->dev, SYS_RES_IOPORT,
2487 &sc->csid, RF_ACTIVE);
2488 sc->ddmaid = PCIR_DDMA;
2489 sc->ddma = bus_alloc_resource_any(sc->dev, SYS_RES_IOPORT,
2490 &sc->ddmaid, RF_ACTIVE);
2492 sc->ds = bus_alloc_resource_any(sc->dev, SYS_RES_IOPORT,
2493 &sc->dsid, RF_ACTIVE);
2495 sc->mt = bus_alloc_resource_any(sc->dev, SYS_RES_IOPORT,
2496 &sc->mtid, RF_ACTIVE);
2497 if (!sc->cs || !sc->ddma || !sc->ds || !sc->mt) {
2498 device_printf(sc->dev, "unable to map IO port space\n");
2501 sc->cst = rman_get_bustag(sc->cs);
2502 sc->csh = rman_get_bushandle(sc->cs);
2503 sc->ddmat = rman_get_bustag(sc->ddma);
2504 sc->ddmah = rman_get_bushandle(sc->ddma);
2505 sc->dst = rman_get_bustag(sc->ds);
2506 sc->dsh = rman_get_bushandle(sc->ds);
2507 sc->mtt = rman_get_bustag(sc->mt);
2508 sc->mth = rman_get_bushandle(sc->mt);
2510 device_printf(sc->dev,
2511 "IO port register values\nCCS: 0x%lx\nDDMA: 0x%lx\nDS: 0x%lx\nMT: 0x%lx\n",
2512 pci_read_config(sc->dev, PCIR_CCS, 4),
2513 pci_read_config(sc->dev, PCIR_DDMA, 4),
2514 pci_read_config(sc->dev, PCIR_DS, 4),
2515 pci_read_config(sc->dev, PCIR_MT, 4));
2518 /* allocate interrupt resource */
2520 sc->irq = bus_alloc_resource_any(sc->dev, SYS_RES_IRQ, &sc->irqid,
2521 RF_ACTIVE | RF_SHAREABLE);
2523 snd_setup_intr(sc->dev, sc->irq, INTR_MPSAFE, envy24_intr, sc, &sc->ih)) {
2524 device_printf(sc->dev, "unable to map interrupt\n");
2528 /* allocate DMA resource */
2529 if (bus_dma_tag_create(/*parent*/bus_get_dma_tag(sc->dev),
2532 /*lowaddr*/BUS_SPACE_MAXADDR_ENVY24,
2533 /*highaddr*/BUS_SPACE_MAXADDR_ENVY24,
2534 /*filter*/NULL, /*filterarg*/NULL,
2535 /*maxsize*/BUS_SPACE_MAXSIZE_ENVY24,
2536 /*nsegments*/1, /*maxsegsz*/0x3ffff,
2537 /*flags*/0, /*lockfunc*/busdma_lock_mutex,
2538 /*lockarg*/&Giant, &sc->dmat) != 0) {
2539 device_printf(sc->dev, "unable to create dma tag\n");
2547 envy24_pci_attach(device_t dev)
2550 char status[SND_STATUSLEN];
2555 device_printf(dev, "envy24_pci_attach()\n");
2557 /* get sc_info data area */
2558 if ((sc = malloc(sizeof(*sc), M_ENVY24, M_NOWAIT)) == NULL) {
2559 device_printf(dev, "cannot allocate softc\n");
2563 bzero(sc, sizeof(*sc));
2564 sc->lock = snd_mtxcreate(device_get_nameunit(dev), "snd_envy24 softc");
2567 /* initialize PCI interface */
2568 pci_enable_busmaster(dev);
2570 /* allocate resources */
2571 err = envy24_alloc_resource(sc);
2573 device_printf(dev, "unable to allocate system resources\n");
2577 /* initialize card */
2578 err = envy24_init(sc);
2580 device_printf(dev, "unable to initialize the card\n");
2584 /* set multi track mixer */
2585 mixer_init(dev, &envy24mixer_class, sc);
2587 /* set channel information */
2588 err = pcm_register(dev, sc, 5, 2 + sc->adcn);
2592 for (i = 0; i < 5; i++) {
2593 pcm_addchan(dev, PCMDIR_PLAY, &envy24chan_class, sc);
2596 for (i = 0; i < 2 + sc->adcn; i++) {
2597 pcm_addchan(dev, PCMDIR_REC, &envy24chan_class, sc);
2601 /* set status iformation */
2602 snprintf(status, SND_STATUSLEN,
2603 "at io 0x%jx:%jd,0x%jx:%jd,0x%jx:%jd,0x%jx:%jd irq %jd",
2604 rman_get_start(sc->cs),
2605 rman_get_end(sc->cs) - rman_get_start(sc->cs) + 1,
2606 rman_get_start(sc->ddma),
2607 rman_get_end(sc->ddma) - rman_get_start(sc->ddma) + 1,
2608 rman_get_start(sc->ds),
2609 rman_get_end(sc->ds) - rman_get_start(sc->ds) + 1,
2610 rman_get_start(sc->mt),
2611 rman_get_end(sc->mt) - rman_get_start(sc->mt) + 1,
2612 rman_get_start(sc->irq));
2613 pcm_setstatus(dev, status);
2619 bus_teardown_intr(dev, sc->irq, sc->ih);
2621 bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq);
2624 bus_dma_tag_destroy(sc->dmat);
2625 if (sc->cfg->codec->destroy != NULL) {
2626 for (i = 0; i < sc->adcn; i++)
2627 sc->cfg->codec->destroy(sc->adc[i]);
2628 for (i = 0; i < sc->dacn; i++)
2629 sc->cfg->codec->destroy(sc->dac[i]);
2631 envy24_cfgfree(sc->cfg);
2633 bus_release_resource(dev, SYS_RES_IOPORT, sc->csid, sc->cs);
2635 bus_release_resource(dev, SYS_RES_IOPORT, sc->ddmaid, sc->ddma);
2637 bus_release_resource(dev, SYS_RES_IOPORT, sc->dsid, sc->ds);
2639 bus_release_resource(dev, SYS_RES_IOPORT, sc->mtid, sc->mt);
2641 snd_mtxfree(sc->lock);
2647 envy24_pci_detach(device_t dev)
2654 device_printf(dev, "envy24_pci_detach()\n");
2656 sc = pcm_getdevinfo(dev);
2659 r = pcm_unregister(dev);
2664 if (sc->cfg->codec->destroy != NULL) {
2665 for (i = 0; i < sc->adcn; i++)
2666 sc->cfg->codec->destroy(sc->adc[i]);
2667 for (i = 0; i < sc->dacn; i++)
2668 sc->cfg->codec->destroy(sc->dac[i]);
2670 envy24_cfgfree(sc->cfg);
2671 bus_dma_tag_destroy(sc->dmat);
2672 bus_teardown_intr(dev, sc->irq, sc->ih);
2673 bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq);
2674 bus_release_resource(dev, SYS_RES_IOPORT, sc->csid, sc->cs);
2675 bus_release_resource(dev, SYS_RES_IOPORT, sc->ddmaid, sc->ddma);
2676 bus_release_resource(dev, SYS_RES_IOPORT, sc->dsid, sc->ds);
2677 bus_release_resource(dev, SYS_RES_IOPORT, sc->mtid, sc->mt);
2678 snd_mtxfree(sc->lock);
2683 static device_method_t envy24_methods[] = {
2684 /* Device interface */
2685 DEVMETHOD(device_probe, envy24_pci_probe),
2686 DEVMETHOD(device_attach, envy24_pci_attach),
2687 DEVMETHOD(device_detach, envy24_pci_detach),
2691 static driver_t envy24_driver = {
2697 DRIVER_MODULE(snd_envy24, pci, envy24_driver, pcm_devclass, 0, 0);
2698 MODULE_DEPEND(snd_envy24, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER);
2699 MODULE_DEPEND(snd_envy24, snd_spicds, 1, 1, 1);
2700 MODULE_VERSION(snd_envy24, 1);