es137x.c revision 126695
150724Scg/*
253413Sroger * Support the ENSONIQ AudioPCI board and Creative Labs SoundBlaster PCI
353413Sroger * boards based on the ES1370, ES1371 and ES1373 chips.
450724Scg *
553413Sroger * Copyright (c) 1999 Russell Cattelan <cattelan@thebarn.com>
6119853Scg * Copyright (c) 1999 Cameron Grant <cg@freebsd.org>
750724Scg * Copyright (c) 1998 by Joachim Kuebart. All rights reserved.
850724Scg *
950724Scg * Redistribution and use in source and binary forms, with or without
1050724Scg * modification, are permitted provided that the following conditions
1150724Scg * are met:
1250724Scg *
1350724Scg * 1. Redistributions of source code must retain the above copyright
1450724Scg *    notice, this list of conditions and the following disclaimer.
1550724Scg *
1650724Scg * 2. Redistributions in binary form must reproduce the above copyright
1750724Scg *    notice, this list of conditions and the following disclaimer in
1850724Scg *    the documentation and/or other materials provided with the
1950724Scg *    distribution.
2050724Scg *
2150724Scg * 3. All advertising materials mentioning features or use of this
2250724Scg *    software must display the following acknowledgement:
2350724Scg *	This product includes software developed by Joachim Kuebart.
2450724Scg *
2550724Scg * 4. The name of the author may not be used to endorse or promote
2650724Scg *    products derived from this software without specific prior
2750724Scg *    written permission.
2850724Scg *
2950724Scg * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
3050724Scg * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
3150724Scg * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
3250724Scg * DISCLAIMED.	IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
3350724Scg * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
3450724Scg * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
3550724Scg * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3650724Scg * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
3750724Scg * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
3850724Scg * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
3950724Scg * OF THE POSSIBILITY OF SUCH DAMAGE.
4050724Scg */
4150724Scg
4253413Sroger/*
4353413Sroger * Part of this code was heavily inspired by the linux driver from
4453413Sroger * Thomas Sailer (sailer@ife.ee.ethz.ch)
4554831Scg * Just about everything has been touched and reworked in some way but
4654831Scg * the all the underlying sequences/timing/register values are from
4753413Sroger * Thomas' code.
4853413Sroger *
4953413Sroger*/
5053413Sroger
5153465Scg#include <dev/sound/pcm/sound.h>
5253465Scg#include <dev/sound/pcm/ac97.h>
5353465Scg#include <dev/sound/pci/es137x.h>
5450724Scg
55119287Simp#include <dev/pci/pcireg.h>
56119287Simp#include <dev/pci/pcivar.h>
5750724Scg
5853413Sroger#include <sys/sysctl.h>
5953413Sroger
6070134Scg#include "mixer_if.h"
6170134Scg
6282180ScgSND_DECLARE_FILE("$FreeBSD: head/sys/dev/sound/pci/es137x.c 126695 2004-03-06 15:52:42Z matk $");
6382180Scg
6453413Srogerstatic int debug = 0;
6553413SrogerSYSCTL_INT(_debug, OID_AUTO, es_debug, CTLFLAG_RW, &debug, 0, "");
6653413Sroger
6750724Scg#define MEM_MAP_REG 0x14
6850724Scg
6950724Scg/* PCI IDs of supported chips */
7050724Scg#define ES1370_PCI_ID 0x50001274
7153413Sroger#define ES1371_PCI_ID 0x13711274
7256154Speter#define ES1371_PCI_ID2 0x13713274
7376086Scg#define CT5880_PCI_ID 0x58801274
74119548Sorion#define CT4730_PCI_ID 0x89381102
7550724Scg
7678033Scg#define ES1371REV_ES1371_A  0x02
7776086Scg#define ES1371REV_ES1371_B  0x09
7876086Scg
7976086Scg#define ES1371REV_ES1373_8  0x08
8076086Scg#define ES1371REV_ES1373_A  0x04
8176086Scg#define ES1371REV_ES1373_B  0x06
8276086Scg
8376086Scg#define ES1371REV_CT5880_A  0x07
8476086Scg
8576086Scg#define CT5880REV_CT5880_C  0x02
8676086Scg#define CT5880REV_CT5880_D  0x03
8795678Scg#define CT5880REV_CT5880_E  0x04
8876086Scg
89119548Sorion#define CT4730REV_CT4730_A  0x00
90119548Sorion
9184658Scg#define ES_DEFAULT_BUFSZ 4096
9259019Scg
9350724Scg/* device private data */
9450724Scgstruct es_info;
9550724Scg
9655209Scgstruct es_chinfo {
9750724Scg	struct es_info *parent;
9874763Scg	struct pcm_channel *channel;
9974763Scg	struct snd_dbuf *buffer;
10054831Scg	int dir, num;
10170321Scg	u_int32_t fmt, blksz, bufsz;
10255209Scg};
10350724Scg
10455209Scgstruct es_info {
10550724Scg	bus_space_tag_t st;
10650724Scg	bus_space_handle_t sh;
10750724Scg	bus_dma_tag_t	parent_dmat;
10850724Scg
10965644Scg	struct resource *reg, *irq;
11065644Scg	int regtype, regid, irqid;
11165644Scg	void *ih;
11265644Scg
11359019Scg	device_t dev;
11454831Scg	int num;
11584658Scg	unsigned int bufsz;
11684658Scg
11750724Scg	/* Contents of board's registers */
11850724Scg	u_long		ctrl;
11950724Scg	u_long		sctrl;
12050724Scg	struct es_chinfo pch, rch;
12155209Scg};
12250724Scg
12350724Scg/* -------------------------------------------------------------------- */
12454831Scg
12553413Sroger/* prototypes */
12654831Scgstatic void     es_intr(void *);
12750724Scg
12855209Scgstatic u_int	es1371_wait_src_ready(struct es_info *);
12955209Scgstatic void	es1371_src_write(struct es_info *, u_short, unsigned short);
13055209Scgstatic u_int	es1371_adc_rate(struct es_info *, u_int, int);
13155209Scgstatic u_int	es1371_dac_rate(struct es_info *, u_int, int);
13271505Scgstatic int	es1371_init(struct es_info *, device_t);
13354831Scgstatic int      es1370_init(struct es_info *);
13454831Scgstatic int      es1370_wrcodec(struct es_info *, u_char, u_char);
13550724Scg
13664881Scgstatic u_int32_t es_playfmt[] = {
13764881Scg	AFMT_U8,
13864881Scg	AFMT_STEREO | AFMT_U8,
13964881Scg	AFMT_S16_LE,
14064881Scg	AFMT_STEREO | AFMT_S16_LE,
14164881Scg	0
14250724Scg};
14374763Scgstatic struct pcmchan_caps es_playcaps = {4000, 48000, es_playfmt, 0};
14450724Scg
14564881Scgstatic u_int32_t es_recfmt[] = {
14664881Scg	AFMT_U8,
14764881Scg	AFMT_STEREO | AFMT_U8,
14864881Scg	AFMT_S16_LE,
14964881Scg	AFMT_STEREO | AFMT_S16_LE,
15064881Scg	0
15150724Scg};
15274763Scgstatic struct pcmchan_caps es_reccaps = {4000, 48000, es_recfmt, 0};
15350724Scg
15450724Scgstatic const struct {
15550724Scg	unsigned        volidx:4;
15650724Scg	unsigned        left:4;
15750724Scg	unsigned        right:4;
15850724Scg	unsigned        stereo:1;
15950724Scg	unsigned        recmask:13;
16050724Scg	unsigned        avail:1;
16150724Scg}       mixtable[SOUND_MIXER_NRDEVICES] = {
16250724Scg	[SOUND_MIXER_VOLUME]	= { 0, 0x0, 0x1, 1, 0x0000, 1 },
16350724Scg	[SOUND_MIXER_PCM] 	= { 1, 0x2, 0x3, 1, 0x0400, 1 },
16450724Scg	[SOUND_MIXER_SYNTH]	= { 2, 0x4, 0x5, 1, 0x0060, 1 },
16550724Scg	[SOUND_MIXER_CD]	= { 3, 0x6, 0x7, 1, 0x0006, 1 },
16650724Scg	[SOUND_MIXER_LINE]	= { 4, 0x8, 0x9, 1, 0x0018, 1 },
16750724Scg	[SOUND_MIXER_LINE1]	= { 5, 0xa, 0xb, 1, 0x1800, 1 },
16850724Scg	[SOUND_MIXER_LINE2]	= { 6, 0xc, 0x0, 0, 0x0100, 1 },
16950724Scg	[SOUND_MIXER_LINE3]	= { 7, 0xd, 0x0, 0, 0x0200, 1 },
17050724Scg	[SOUND_MIXER_MIC]	= { 8, 0xe, 0x0, 0, 0x0001, 1 },
17154831Scg	[SOUND_MIXER_OGAIN]	= { 9, 0xf, 0x0, 0, 0x0000, 1 }
17254831Scg};
17350724Scg
17470134Scg/* -------------------------------------------------------------------- */
17570134Scg/* The es1370 mixer interface */
17670134Scg
17750724Scgstatic int
17874763Scges1370_mixinit(struct snd_mixer *m)
17950724Scg{
18050724Scg	int i;
18150724Scg	u_int32_t v;
18250724Scg
18350724Scg	v = 0;
18450724Scg	for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
18550724Scg		if (mixtable[i].avail) v |= (1 << i);
18650724Scg	mix_setdevs(m, v);
18750724Scg	v = 0;
18850724Scg	for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
18950724Scg		if (mixtable[i].recmask) v |= (1 << i);
19050724Scg	mix_setrecdevs(m, v);
19150724Scg	return 0;
19250724Scg}
19350724Scg
19450724Scgstatic int
19574763Scges1370_mixset(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right)
19650724Scg{
19750724Scg	int l, r, rl, rr;
19850724Scg
19950724Scg	if (!mixtable[dev].avail) return -1;
20050724Scg	l = left;
20150724Scg	r = mixtable[dev].stereo? right : l;
20250724Scg	if (mixtable[dev].left == 0xf) {
20350724Scg		rl = (l < 2)? 0x80 : 7 - (l - 2) / 14;
20450724Scg	} else {
20550724Scg		rl = (l < 10)? 0x80 : 15 - (l - 10) / 6;
20650724Scg	}
20750724Scg	if (mixtable[dev].stereo) {
20850724Scg		rr = (r < 10)? 0x80 : 15 - (r - 10) / 6;
20954831Scg		es1370_wrcodec(mix_getdevinfo(m), mixtable[dev].right, rr);
21050724Scg	}
21154831Scg	es1370_wrcodec(mix_getdevinfo(m), mixtable[dev].left, rl);
21250724Scg	return l | (r << 8);
21350724Scg}
21450724Scg
21550724Scgstatic int
21674763Scges1370_mixsetrecsrc(struct snd_mixer *m, u_int32_t src)
21750724Scg{
21850724Scg	int i, j = 0;
21950724Scg
22050724Scg	if (src == 0) src = 1 << SOUND_MIXER_MIC;
22150724Scg	src &= mix_getrecdevs(m);
22250724Scg	for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
22350724Scg		if ((src & (1 << i)) != 0) j |= mixtable[i].recmask;
22450724Scg
22554831Scg	es1370_wrcodec(mix_getdevinfo(m), CODEC_LIMIX1, j & 0x55);
22654831Scg	es1370_wrcodec(mix_getdevinfo(m), CODEC_RIMIX1, j & 0xaa);
22754831Scg	es1370_wrcodec(mix_getdevinfo(m), CODEC_LIMIX2, (j >> 8) & 0x17);
22854831Scg	es1370_wrcodec(mix_getdevinfo(m), CODEC_RIMIX2, (j >> 8) & 0x0f);
22954831Scg	es1370_wrcodec(mix_getdevinfo(m), CODEC_OMIX1, 0x7f);
23054831Scg	es1370_wrcodec(mix_getdevinfo(m), CODEC_OMIX2, 0x3f);
23150724Scg	return src;
23250724Scg}
23350724Scg
23470134Scgstatic kobj_method_t es1370_mixer_methods[] = {
23570134Scg    	KOBJMETHOD(mixer_init,		es1370_mixinit),
23670134Scg    	KOBJMETHOD(mixer_set,		es1370_mixset),
23770134Scg    	KOBJMETHOD(mixer_setrecsrc,	es1370_mixsetrecsrc),
23870134Scg	{ 0, 0 }
23970134Scg};
24070134ScgMIXER_DECLARE(es1370_mixer);
24170134Scg
24270134Scg/* -------------------------------------------------------------------- */
24370134Scg
24450724Scgstatic int
24554831Scges1370_wrcodec(struct es_info *es, u_char i, u_char data)
24650724Scg{
24750724Scg	int		wait = 100;	/* 100 msec timeout */
24850724Scg
24950724Scg	do {
25050724Scg		if ((bus_space_read_4(es->st, es->sh, ES1370_REG_STATUS) &
25150724Scg		      STAT_CSTAT) == 0) {
25250724Scg			bus_space_write_2(es->st, es->sh, ES1370_REG_CODEC,
25350724Scg				((u_short)i << CODEC_INDEX_SHIFT) | data);
25450724Scg			return 0;
25550724Scg		}
25650724Scg		DELAY(1000);
25750724Scg	} while (--wait);
25854831Scg	printf("pcm: es1370_wrcodec timed out\n");
25950724Scg	return -1;
26050724Scg}
26150724Scg
26250724Scg/* -------------------------------------------------------------------- */
26350724Scg
26450724Scg/* channel interface */
26550724Scgstatic void *
26674763Scgeschan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir)
26750724Scg{
26850724Scg	struct es_info *es = devinfo;
26950724Scg	struct es_chinfo *ch = (dir == PCMDIR_PLAY)? &es->pch : &es->rch;
27050724Scg
27150724Scg	ch->parent = es;
27250724Scg	ch->channel = c;
27350724Scg	ch->buffer = b;
27484658Scg	ch->bufsz = es->bufsz;
27570321Scg	ch->blksz = ch->bufsz / 2;
27654831Scg	ch->num = ch->parent->num++;
27770321Scg	if (sndbuf_alloc(ch->buffer, es->parent_dmat, ch->bufsz) == -1) return NULL;
27850724Scg	return ch;
27950724Scg}
28050724Scg
28150724Scgstatic int
28270134Scgeschan_setdir(kobj_t obj, void *data, int dir)
28350724Scg{
28450724Scg	struct es_chinfo *ch = data;
28550724Scg	struct es_info *es = ch->parent;
28650724Scg
28750724Scg	if (dir == PCMDIR_PLAY) {
28870321Scg		bus_space_write_1(es->st, es->sh, ES1370_REG_MEMPAGE, ES1370_REG_DAC2_FRAMEADR >> 8);
289111183Scognet		bus_space_write_4(es->st, es->sh, ES1370_REG_DAC2_FRAMEADR & 0xff, sndbuf_getbufaddr(ch->buffer));
29070321Scg		bus_space_write_4(es->st, es->sh, ES1370_REG_DAC2_FRAMECNT & 0xff, (ch->bufsz >> 2) - 1);
29150724Scg	} else {
29270321Scg		bus_space_write_1(es->st, es->sh, ES1370_REG_MEMPAGE, ES1370_REG_ADC_FRAMEADR >> 8);
293111183Scognet		bus_space_write_4(es->st, es->sh, ES1370_REG_ADC_FRAMEADR & 0xff, sndbuf_getbufaddr(ch->buffer));
29470321Scg		bus_space_write_4(es->st, es->sh, ES1370_REG_ADC_FRAMECNT & 0xff, (ch->bufsz >> 2) - 1);
29550724Scg	}
29650724Scg	ch->dir = dir;
29750724Scg	return 0;
29850724Scg}
29950724Scg
30050724Scgstatic int
30170134Scgeschan_setformat(kobj_t obj, void *data, u_int32_t format)
30250724Scg{
30350724Scg	struct es_chinfo *ch = data;
30450724Scg	struct es_info *es = ch->parent;
30550724Scg
30650724Scg	if (ch->dir == PCMDIR_PLAY) {
30750724Scg		es->sctrl &= ~SCTRL_P2FMT;
30850724Scg		if (format & AFMT_S16_LE) es->sctrl |= SCTRL_P2SEB;
30950724Scg		if (format & AFMT_STEREO) es->sctrl |= SCTRL_P2SMB;
31050724Scg	} else {
31150724Scg		es->sctrl &= ~SCTRL_R1FMT;
31250724Scg		if (format & AFMT_S16_LE) es->sctrl |= SCTRL_R1SEB;
31350724Scg		if (format & AFMT_STEREO) es->sctrl |= SCTRL_R1SMB;
31450724Scg	}
31550724Scg	bus_space_write_4(es->st, es->sh, ES1370_REG_SERIAL_CONTROL, es->sctrl);
31650724Scg	ch->fmt = format;
31750724Scg	return 0;
31850724Scg}
31950724Scg
32050724Scgstatic int
32170134Scgeschan1370_setspeed(kobj_t obj, void *data, u_int32_t speed)
32250724Scg{
32350724Scg	struct es_chinfo *ch = data;
32450724Scg	struct es_info *es = ch->parent;
32550724Scg
32650724Scg	es->ctrl &= ~CTRL_PCLKDIV;
32750724Scg	es->ctrl |= DAC2_SRTODIV(speed) << CTRL_SH_PCLKDIV;
32850724Scg	bus_space_write_4(es->st, es->sh, ES1370_REG_CONTROL, es->ctrl);
32950724Scg	/* rec/play speeds locked together - should indicate in flags */
33050724Scg	return speed; /* XXX calc real speed */
33150724Scg}
33250724Scg
33370134Scgstatic int
33470134Scgeschan1371_setspeed(kobj_t obj, void *data, u_int32_t speed)
33554831Scg{
33654831Scg  	struct es_chinfo *ch = data;
33754831Scg  	struct es_info *es = ch->parent;
33854831Scg
33954831Scg	if (ch->dir == PCMDIR_PLAY) {
34054831Scg  		return es1371_dac_rate(es, speed, 3 - ch->num); /* play */
34154831Scg	} else {
34254831Scg  		return es1371_adc_rate(es, speed, 1); /* record */
34354831Scg	}
34454831Scg}
34554831Scg
34650724Scgstatic int
34770134Scgeschan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
34850724Scg{
34970321Scg  	struct es_chinfo *ch = data;
35070321Scg
35170321Scg	ch->blksz = blocksize;
35270321Scg	ch->bufsz = ch->blksz * 2;
35370321Scg	sndbuf_resize(ch->buffer, 2, ch->blksz);
35470321Scg
35570321Scg	return ch->blksz;
35650724Scg}
35750724Scg
35850724Scgstatic int
35970134Scgeschan_trigger(kobj_t obj, void *data, int go)
36050724Scg{
36150724Scg	struct es_chinfo *ch = data;
36250724Scg	struct es_info *es = ch->parent;
36370298Scg	unsigned cnt;
36450724Scg
36560958Scg	if (go == PCMTRIG_EMLDMAWR || go == PCMTRIG_EMLDMARD)
36660958Scg		return 0;
36760958Scg
36870321Scg	cnt = (ch->blksz / sndbuf_getbps(ch->buffer)) - 1;
36960958Scg
37050724Scg	if (ch->dir == PCMDIR_PLAY) {
37150724Scg		if (go == PCMTRIG_START) {
37250724Scg			int b = (ch->fmt & AFMT_S16_LE)? 2 : 1;
37350724Scg			es->ctrl |= CTRL_DAC2_EN;
37470321Scg			es->sctrl &= ~(SCTRL_P2ENDINC | SCTRL_P2STINC | SCTRL_P2LOOPSEL | SCTRL_P2PAUSE | SCTRL_P2DACSEN);
37550724Scg			es->sctrl |= SCTRL_P2INTEN | (b << SCTRL_SH_P2ENDINC);
37670321Scg			bus_space_write_4(es->st, es->sh, ES1370_REG_DAC2_SCOUNT, cnt);
37759323Scg			/* start at beginning of buffer */
37870321Scg			bus_space_write_4(es->st, es->sh, ES1370_REG_MEMPAGE, ES1370_REG_DAC2_FRAMECNT >> 8);
37970321Scg			bus_space_write_4(es->st, es->sh, ES1370_REG_DAC2_FRAMECNT & 0xff, (ch->bufsz >> 2) - 1);
38050724Scg		} else es->ctrl &= ~CTRL_DAC2_EN;
38150724Scg	} else {
38250724Scg		if (go == PCMTRIG_START) {
38350724Scg			es->ctrl |= CTRL_ADC_EN;
38450724Scg			es->sctrl &= ~SCTRL_R1LOOPSEL;
38550724Scg			es->sctrl |= SCTRL_R1INTEN;
38670321Scg			bus_space_write_4(es->st, es->sh, ES1370_REG_ADC_SCOUNT, cnt);
38759323Scg			/* start at beginning of buffer */
38870321Scg			bus_space_write_4(es->st, es->sh, ES1370_REG_MEMPAGE, ES1370_REG_ADC_FRAMECNT >> 8);
38970321Scg			bus_space_write_4(es->st, es->sh, ES1370_REG_ADC_FRAMECNT & 0xff, (ch->bufsz >> 2) - 1);
39050724Scg		} else es->ctrl &= ~CTRL_ADC_EN;
39150724Scg	}
39250724Scg	bus_space_write_4(es->st, es->sh, ES1370_REG_SERIAL_CONTROL, es->sctrl);
39350724Scg	bus_space_write_4(es->st, es->sh, ES1370_REG_CONTROL, es->ctrl);
39450724Scg	return 0;
39550724Scg}
39650724Scg
39750724Scgstatic int
39870134Scgeschan_getptr(kobj_t obj, void *data)
39950724Scg{
40050724Scg	struct es_chinfo *ch = data;
40150724Scg	struct es_info *es = ch->parent;
40259323Scg	u_int32_t reg, cnt;
40359323Scg
40459323Scg	if (ch->dir == PCMDIR_PLAY)
40559323Scg		reg = ES1370_REG_DAC2_FRAMECNT;
40659323Scg	else
40759323Scg		reg = ES1370_REG_ADC_FRAMECNT;
40859323Scg
40959323Scg	bus_space_write_4(es->st, es->sh, ES1370_REG_MEMPAGE, reg >> 8);
41059323Scg	cnt = bus_space_read_4(es->st, es->sh, reg & 0x000000ff) >> 16;
41159323Scg	/* cnt is longwords */
41259323Scg	return cnt << 2;
41350724Scg}
41450724Scg
41574763Scgstatic struct pcmchan_caps *
41670134Scgeschan_getcaps(kobj_t obj, void *data)
41750724Scg{
41850724Scg	struct es_chinfo *ch = data;
41950724Scg	return (ch->dir == PCMDIR_PLAY)? &es_playcaps : &es_reccaps;
42050724Scg}
42150724Scg
42270134Scgstatic kobj_method_t eschan1370_methods[] = {
42370134Scg    	KOBJMETHOD(channel_init,		eschan_init),
42470134Scg    	KOBJMETHOD(channel_setdir,		eschan_setdir),
42570134Scg    	KOBJMETHOD(channel_setformat,		eschan_setformat),
42670134Scg    	KOBJMETHOD(channel_setspeed,		eschan1370_setspeed),
42770134Scg    	KOBJMETHOD(channel_setblocksize,	eschan_setblocksize),
42870134Scg    	KOBJMETHOD(channel_trigger,		eschan_trigger),
42970134Scg    	KOBJMETHOD(channel_getptr,		eschan_getptr),
43070134Scg    	KOBJMETHOD(channel_getcaps,		eschan_getcaps),
43170134Scg	{ 0, 0 }
43270134Scg};
43370134ScgCHANNEL_DECLARE(eschan1370);
43470134Scg
43570134Scgstatic kobj_method_t eschan1371_methods[] = {
43670134Scg    	KOBJMETHOD(channel_init,		eschan_init),
43770134Scg    	KOBJMETHOD(channel_setdir,		eschan_setdir),
43870134Scg    	KOBJMETHOD(channel_setformat,		eschan_setformat),
43970134Scg    	KOBJMETHOD(channel_setspeed,		eschan1371_setspeed),
44070134Scg    	KOBJMETHOD(channel_setblocksize,	eschan_setblocksize),
44170134Scg    	KOBJMETHOD(channel_trigger,		eschan_trigger),
44270134Scg    	KOBJMETHOD(channel_getptr,		eschan_getptr),
44370134Scg    	KOBJMETHOD(channel_getcaps,		eschan_getcaps),
44470134Scg	{ 0, 0 }
44570134Scg};
44670134ScgCHANNEL_DECLARE(eschan1371);
44770134Scg
44870134Scg/* -------------------------------------------------------------------- */
44950724Scg/* The interrupt handler */
45050724Scgstatic void
45154831Scges_intr(void *p)
45250724Scg{
45350724Scg	struct es_info *es = p;
45450724Scg	unsigned	intsrc, sctrl;
45550724Scg
45650724Scg	intsrc = bus_space_read_4(es->st, es->sh, ES1370_REG_STATUS);
45750724Scg	if ((intsrc & STAT_INTR) == 0) return;
45850724Scg
45950724Scg	sctrl = es->sctrl;
46050724Scg	if (intsrc & STAT_ADC)  sctrl &= ~SCTRL_R1INTEN;
46150724Scg	if (intsrc & STAT_DAC1)	sctrl &= ~SCTRL_P1INTEN;
46250724Scg	if (intsrc & STAT_DAC2)	sctrl &= ~SCTRL_P2INTEN;
46350724Scg
46450724Scg	bus_space_write_4(es->st, es->sh, ES1370_REG_SERIAL_CONTROL, sctrl);
46550724Scg	bus_space_write_4(es->st, es->sh, ES1370_REG_SERIAL_CONTROL, es->sctrl);
46650724Scg
46754831Scg	if (intsrc & STAT_ADC) chn_intr(es->rch.channel);
46854831Scg	if (intsrc & STAT_DAC1);
46950724Scg	if (intsrc & STAT_DAC2)	chn_intr(es->pch.channel);
47050724Scg}
47150724Scg
47254831Scg/* ES1370 specific */
47354831Scgstatic int
47454831Scges1370_init(struct es_info *es)
47554831Scg{
47654831Scg	es->ctrl = CTRL_CDC_EN | CTRL_SERR_DIS |
47754831Scg		(DAC2_SRTODIV(DSP_DEFAULT_SPEED) << CTRL_SH_PCLKDIV);
47854831Scg	bus_space_write_4(es->st, es->sh, ES1370_REG_CONTROL, es->ctrl);
47953413Sroger
48054831Scg	es->sctrl = 0;
48154831Scg	bus_space_write_4(es->st, es->sh, ES1370_REG_SERIAL_CONTROL, es->sctrl);
48253413Sroger
48354831Scg	es1370_wrcodec(es, CODEC_RES_PD, 3);/* No RST, PD */
48454831Scg	es1370_wrcodec(es, CODEC_CSEL, 0);	/* CODEC ADC and CODEC DAC use
48554831Scg					         * {LR,B}CLK2 and run off the LRCLK2
48654831Scg					         * PLL; program DAC_SYNC=0!  */
48754831Scg	es1370_wrcodec(es, CODEC_ADSEL, 0);/* Recording source is mixer */
48854831Scg	es1370_wrcodec(es, CODEC_MGAIN, 0);/* MIC amp is 0db */
48953413Sroger
49054831Scg	return 0;
49154831Scg}
49253413Sroger
49354831Scg/* ES1371 specific */
49453413Srogerint
49571505Scges1371_init(struct es_info *es, device_t dev)
49653413Sroger{
49753413Sroger	int idx;
49871505Scg	int devid = pci_get_devid(dev);
49971505Scg	int revid = pci_get_revid(dev);
50053413Sroger
50154831Scg	if (debug > 0) printf("es_init\n");
50254831Scg
50354831Scg	es->num = 0;
50453413Sroger	es->ctrl = 0;
50553413Sroger	es->sctrl = 0;
50653413Sroger	/* initialize the chips */
50776086Scg	if ((devid == ES1371_PCI_ID && revid == ES1371REV_ES1373_8) ||
50876086Scg	    (devid == ES1371_PCI_ID && revid == ES1371REV_CT5880_A) ||
50976086Scg	    (devid == CT5880_PCI_ID && revid == CT5880REV_CT5880_C) ||
51095678Scg	    (devid == CT5880_PCI_ID && revid == CT5880REV_CT5880_D) ||
511119548Sorion	    (devid == CT5880_PCI_ID && revid == CT5880REV_CT5880_E) ||
512119548Sorion	    (devid == CT4730_PCI_ID)) {
51376086Scg		bus_space_write_4(es->st, es->sh, ES1370_REG_STATUS, 0x20000000);
51474753Scg		DELAY(20000);
51576086Scg		if (debug > 0) device_printf(dev, "ac97 2.1 enabled\n");
51655209Scg	} else { /* pre ac97 2.1 card */
51755209Scg		bus_space_write_4(es->st, es->sh, ES1370_REG_CONTROL, es->ctrl);
51876086Scg		if (debug > 0) device_printf(dev, "ac97 pre-2.1 enabled\n");
51955209Scg	}
52053413Sroger	bus_space_write_4(es->st, es->sh, ES1370_REG_SERIAL_CONTROL, es->sctrl);
52153413Sroger	bus_space_write_4(es->st, es->sh, ES1371_REG_LEGACY, 0);
52253413Sroger	/* AC'97 warm reset to start the bitclk */
52353413Sroger	bus_space_write_4(es->st, es->sh, ES1371_REG_LEGACY, es->ctrl | ES1371_SYNC_RES);
52453413Sroger	DELAY(2000);
52555204Scg	bus_space_write_4(es->st, es->sh, ES1370_REG_SERIAL_CONTROL, es->ctrl);
52653413Sroger	/* Init the sample rate converter */
52753413Sroger	bus_space_write_4(es->st, es->sh, ES1371_REG_SMPRATE, ES1371_DIS_SRC);
52853413Sroger	for (idx = 0; idx < 0x80; idx++)
52954831Scg		es1371_src_write(es, idx, 0);
53053413Sroger	es1371_src_write(es, ES_SMPREG_DAC1 + ES_SMPREG_TRUNC_N,  16 << 4);
53153413Sroger	es1371_src_write(es, ES_SMPREG_DAC1 + ES_SMPREG_INT_REGS, 16 << 10);
53253413Sroger	es1371_src_write(es, ES_SMPREG_DAC2 + ES_SMPREG_TRUNC_N,  16 << 4);
53353413Sroger	es1371_src_write(es, ES_SMPREG_DAC2 + ES_SMPREG_INT_REGS, 16 << 10);
53453413Sroger	es1371_src_write(es, ES_SMPREG_VOL_ADC,                   1 << 12);
53553413Sroger	es1371_src_write(es, ES_SMPREG_VOL_ADC  + 1,              1 << 12);
53653413Sroger	es1371_src_write(es, ES_SMPREG_VOL_DAC1,                  1 << 12);
53753413Sroger	es1371_src_write(es, ES_SMPREG_VOL_DAC1 + 1,              1 << 12);
53853413Sroger	es1371_src_write(es, ES_SMPREG_VOL_DAC2,                  1 << 12);
53953413Sroger	es1371_src_write(es, ES_SMPREG_VOL_DAC2 + 1,              1 << 12);
54053413Sroger	es1371_adc_rate (es, 22050,                               1);
54154831Scg	es1371_dac_rate (es, 22050,                               1);
54254831Scg	es1371_dac_rate (es, 22050,                               2);
54353413Sroger	/* WARNING:
54453413Sroger	 * enabling the sample rate converter without properly programming
54553413Sroger	 * its parameters causes the chip to lock up (the SRC busy bit will
54653413Sroger	 * be stuck high, and I've found no way to rectify this other than
54753413Sroger	 * power cycle)
54853413Sroger	 */
54953413Sroger	bus_space_write_4(es->st, es->sh, ES1371_REG_SMPRATE, 0);
55053413Sroger
55153413Sroger	return (0);
55253413Sroger}
55353413Sroger
55470134Scg/* -------------------------------------------------------------------- */
55570134Scg
55670134Scgstatic int
55770134Scges1371_wrcd(kobj_t obj, void *s, int addr, u_int32_t data)
55853413Sroger{
55954831Scg    	int sl;
56054831Scg    	unsigned t, x;
56153413Sroger	struct es_info *es = (struct es_info*)s;
56253413Sroger
56354831Scg	if (debug > 0) printf("wrcodec addr 0x%x data 0x%x\n", addr, data);
56453413Sroger
56553413Sroger	for (t = 0; t < 0x1000; t++)
56654831Scg	  	if (!(bus_space_read_4(es->st, es->sh,(ES1371_REG_CODEC & CODEC_WIP))))
56753413Sroger			break;
56853413Sroger	sl = spltty();
56953413Sroger	/* save the current state for later */
57054831Scg 	x = bus_space_read_4(es->st, es->sh, ES1371_REG_SMPRATE);
57153413Sroger	/* enable SRC state data in SRC mux */
57253413Sroger	bus_space_write_4(es->st, es->sh, ES1371_REG_SMPRATE,
57354831Scg	  	(es1371_wait_src_ready(s) &
57454831Scg	   	(ES1371_DIS_SRC | ES1371_DIS_P1 | ES1371_DIS_P2 | ES1371_DIS_R1)));
57553413Sroger	/* wait for a SAFE time to write addr/data and then do it, dammit */
57653413Sroger	for (t = 0; t < 0x1000; t++)
57754831Scg	  	if ((bus_space_read_4(es->st, es->sh, ES1371_REG_SMPRATE) & 0x00070000) == 0x00010000)
57854831Scg			break;
57954831Scg
58072535Snyan	if (debug > 2)
58172535Snyan		printf("one b_s_w: 0x%lx 0x%x 0x%x\n",
58272535Snyan		       rman_get_start(es->reg), ES1371_REG_CODEC,
58372535Snyan		       ((addr << CODEC_POADD_SHIFT) & CODEC_POADD_MASK) |
58472535Snyan		       ((data << CODEC_PODAT_SHIFT) & CODEC_PODAT_MASK));
58554831Scg
58653413Sroger	bus_space_write_4(es->st, es->sh,ES1371_REG_CODEC,
58753413Sroger			  ((addr << CODEC_POADD_SHIFT) & CODEC_POADD_MASK) |
58853413Sroger			  ((data << CODEC_PODAT_SHIFT) & CODEC_PODAT_MASK));
58953413Sroger	/* restore SRC reg */
59053413Sroger	es1371_wait_src_ready(s);
59172535Snyan	if (debug > 2)
59272535Snyan		printf("two b_s_w: 0x%lx 0x%x 0x%x\n",
59372535Snyan		       rman_get_start(es->reg), ES1371_REG_SMPRATE, x);
59454831Scg	bus_space_write_4(es->st, es->sh, ES1371_REG_SMPRATE, x);
59553413Sroger	splx(sl);
59670134Scg
59770134Scg	return 0;
59853413Sroger}
59953413Sroger
60070134Scgstatic int
60170134Scges1371_rdcd(kobj_t obj, void *s, int addr)
60253413Sroger{
60354831Scg  	int sl;
60494767Sroberto  	unsigned t, x = 0;
60554831Scg  	struct es_info *es = (struct es_info *)s;
60653413Sroger
60754831Scg  	if (debug > 0) printf("rdcodec addr 0x%x ... ", addr);
60853413Sroger
60954831Scg  	for (t = 0; t < 0x1000; t++)
61054831Scg		if (!(x = bus_space_read_4(es->st, es->sh, ES1371_REG_CODEC) & CODEC_WIP))
61154831Scg	  		break;
61254831Scg   	if (debug > 0) printf("loop 1 t 0x%x x 0x%x ", t, x);
61353413Sroger
61454831Scg  	sl = spltty();
61553413Sroger
61654831Scg  	/* save the current state for later */
61754831Scg  	x = bus_space_read_4(es->st, es->sh, ES1371_REG_SMPRATE);
61854831Scg  	/* enable SRC state data in SRC mux */
61954831Scg  	bus_space_write_4(es->st, es->sh, ES1371_REG_SMPRATE,
62054831Scg			  (es1371_wait_src_ready(s) &
62154831Scg			  (ES1371_DIS_SRC | ES1371_DIS_P1 | ES1371_DIS_P2 | ES1371_DIS_R1)));
62254831Scg  	/* wait for a SAFE time to write addr/data and then do it, dammit */
62354831Scg  	for (t = 0; t < 0x5000; t++)
62454831Scg		if ((x = bus_space_read_4(es->st, es->sh, ES1371_REG_SMPRATE) & 0x00070000) == 0x00010000)
62554831Scg	  		break;
62654831Scg  	if (debug > 0) printf("loop 2 t 0x%x x 0x%x ", t, x);
62754831Scg  	bus_space_write_4(es->st, es->sh, ES1371_REG_CODEC,
62854831Scg			  ((addr << CODEC_POADD_SHIFT) & CODEC_POADD_MASK) | CODEC_PORD);
62953413Sroger
63054831Scg  	/* restore SRC reg */
63154831Scg  	es1371_wait_src_ready(s);
63254831Scg  	bus_space_write_4(es->st, es->sh, ES1371_REG_SMPRATE, x);
63353413Sroger
63454831Scg  	splx(sl);
63553413Sroger
63654831Scg  	/* now wait for the stinkin' data (RDY) */
63754831Scg  	for (t = 0; t < 0x1000; t++)
63854831Scg		if ((x = bus_space_read_4(es->st, es->sh, ES1371_REG_CODEC)) & CODEC_RDY)
63954831Scg	  		break;
64054831Scg  	if (debug > 0) printf("loop 3 t 0x%x 0x%x ret 0x%x\n", t, x, ((x & CODEC_PIDAT_MASK) >> CODEC_PIDAT_SHIFT));
64154831Scg  	return ((x & CODEC_PIDAT_MASK) >> CODEC_PIDAT_SHIFT);
64253413Sroger}
64353413Sroger
64470134Scgstatic kobj_method_t es1371_ac97_methods[] = {
64570134Scg    	KOBJMETHOD(ac97_read,		es1371_rdcd),
64670134Scg    	KOBJMETHOD(ac97_write,		es1371_wrcd),
64770134Scg	{ 0, 0 }
64870134Scg};
64970134ScgAC97_DECLARE(es1371_ac97);
65070134Scg
65170134Scg/* -------------------------------------------------------------------- */
65270134Scg
65353413Srogerstatic u_int
65455209Scges1371_src_read(struct es_info *es, u_short reg)
65554831Scg{
65654831Scg  	unsigned int r;
65753413Sroger
65854831Scg  	r = es1371_wait_src_ready(es) &
65954831Scg		(ES1371_DIS_SRC | ES1371_DIS_P1 | ES1371_DIS_P2 | ES1371_DIS_R1);
66054831Scg  	r |= ES1371_SRC_RAM_ADDRO(reg);
66154831Scg  	bus_space_write_4(es->st, es->sh, ES1371_REG_SMPRATE,r);
66254831Scg  	return ES1371_SRC_RAM_DATAI(es1371_wait_src_ready(es));
66353413Sroger}
66453413Sroger
66553413Srogerstatic void
66655209Scges1371_src_write(struct es_info *es, u_short reg, u_short data){
66753413Sroger	u_int r;
66853413Sroger
66953413Sroger	r = es1371_wait_src_ready(es) &
67054831Scg		(ES1371_DIS_SRC | ES1371_DIS_P1 | ES1371_DIS_P2 | ES1371_DIS_R1);
67153413Sroger	r |= ES1371_SRC_RAM_ADDRO(reg) |  ES1371_SRC_RAM_DATAO(data);
67253413Sroger	/*	printf("es1371_src_write 0x%x 0x%x\n",ES1371_REG_SMPRATE,r | ES1371_SRC_RAM_WE); */
67354831Scg	bus_space_write_4(es->st, es->sh, ES1371_REG_SMPRATE, r | ES1371_SRC_RAM_WE);
67453413Sroger}
67553413Sroger
67654831Scgstatic u_int
67755209Scges1371_adc_rate(struct es_info *es, u_int rate, int set)
67854831Scg{
67954831Scg  	u_int n, truncm, freq, result;
68054831Scg
68154831Scg  	if (rate > 48000) rate = 48000;
68254831Scg  	if (rate < 4000) rate = 4000;
68354831Scg  	n = rate / 3000;
68454831Scg  	if ((1 << n) & ((1 << 15) | (1 << 13) | (1 << 11) | (1 << 9)))
68554831Scg		n--;
68654831Scg  	truncm = (21 * n - 1) | 1;
68754831Scg  	freq = ((48000UL << 15) / rate) * n;
68854831Scg  	result = (48000UL << 15) / (freq / n);
68954831Scg  	if (set) {
69054831Scg		if (rate >= 24000) {
69154831Scg	  		if (truncm > 239) truncm = 239;
69254831Scg	  		es1371_src_write(es, ES_SMPREG_ADC + ES_SMPREG_TRUNC_N,
69354831Scg				(((239 - truncm) >> 1) << 9) | (n << 4));
69454831Scg		} else {
69554831Scg	  		if (truncm > 119) truncm = 119;
69654831Scg	  		es1371_src_write(es, ES_SMPREG_ADC + ES_SMPREG_TRUNC_N,
69754831Scg				0x8000 | (((119 - truncm) >> 1) << 9) | (n << 4));
69854831Scg		}
69954831Scg		es1371_src_write(es, ES_SMPREG_ADC + ES_SMPREG_INT_REGS,
70054831Scg		 	(es1371_src_read(es, ES_SMPREG_ADC + ES_SMPREG_INT_REGS) &
70154831Scg		  	0x00ff) | ((freq >> 5) & 0xfc00));
70254831Scg		es1371_src_write(es, ES_SMPREG_ADC + ES_SMPREG_VFREQ_FRAC, freq & 0x7fff);
70354831Scg		es1371_src_write(es, ES_SMPREG_VOL_ADC, n << 8);
70454831Scg		es1371_src_write(es, ES_SMPREG_VOL_ADC + 1, n << 8);
70553413Sroger	}
70653413Sroger	return result;
70753413Sroger}
70853413Sroger
70953413Srogerstatic u_int
71055209Scges1371_dac_rate(struct es_info *es, u_int rate, int set)
71154831Scg{
71254831Scg  	u_int freq, r, result, dac, dis;
71353413Sroger
71454831Scg  	if (rate > 48000) rate = 48000;
71554831Scg  	if (rate < 4000) rate = 4000;
71654831Scg  	freq = (rate << 15) / 3000;
71754831Scg  	result = (freq * 3000) >> 15;
71854831Scg  	if (set) {
71954831Scg		dac = (set == 1)? ES_SMPREG_DAC1 : ES_SMPREG_DAC2;
72054831Scg		dis = (set == 1)? ES1371_DIS_P2 : ES1371_DIS_P1;
72154831Scg
72254831Scg		r = (es1371_wait_src_ready(es) & (ES1371_DIS_SRC | ES1371_DIS_P1 | ES1371_DIS_P2 | ES1371_DIS_R1));
72354831Scg		bus_space_write_4(es->st, es->sh, ES1371_REG_SMPRATE, r);
72454831Scg		es1371_src_write(es, dac + ES_SMPREG_INT_REGS,
72554831Scg			 	(es1371_src_read(es, dac + ES_SMPREG_INT_REGS) & 0x00ff) | ((freq >> 5) & 0xfc00));
72654831Scg		es1371_src_write(es, dac + ES_SMPREG_VFREQ_FRAC, freq & 0x7fff);
72754831Scg		r = (es1371_wait_src_ready(es) & (ES1371_DIS_SRC | dis | ES1371_DIS_R1));
72854831Scg		bus_space_write_4(es->st, es->sh, ES1371_REG_SMPRATE, r);
72954831Scg  	}
73054831Scg  	return result;
73153413Sroger}
73253413Sroger
73353413Srogerstatic u_int
73455209Scges1371_wait_src_ready(struct es_info *es)
73554831Scg{
73654831Scg  	u_int t, r;
73753413Sroger
73854831Scg  	for (t = 0; t < 500; t++) {
73954831Scg		if (!((r = bus_space_read_4(es->st, es->sh, ES1371_REG_SMPRATE)) & ES1371_SRC_RAM_BUSY))
74054831Scg	  		return r;
74154831Scg		DELAY(1000);
74254831Scg  	}
74354831Scg  	printf("es1371: wait src ready timeout 0x%x [0x%x]\n", ES1371_REG_SMPRATE, r);
74454831Scg  	return 0;
74553413Sroger}
74653413Sroger
74750724Scg/* -------------------------------------------------------------------- */
74850724Scg
74950724Scg/*
75050724Scg * Probe and attach the card
75150724Scg */
75250724Scg
75350724Scgstatic int
75450724Scges_pci_probe(device_t dev)
75550724Scg{
75676086Scg	switch(pci_get_devid(dev)) {
75776086Scg	case ES1370_PCI_ID:
75850724Scg		device_set_desc(dev, "AudioPCI ES1370");
75950724Scg		return 0;
76076086Scg
76176086Scg	case ES1371_PCI_ID:
76276086Scg		switch(pci_get_revid(dev)) {
76378033Scg		case ES1371REV_ES1371_A:
76478033Scg			device_set_desc(dev, "AudioPCI ES1371-A");
76578033Scg			return 0;
76678033Scg
76776086Scg		case ES1371REV_ES1371_B:
76876086Scg			device_set_desc(dev, "AudioPCI ES1371-B");
76976086Scg			return 0;
77076086Scg
77176086Scg		case ES1371REV_ES1373_A:
77276086Scg			device_set_desc(dev, "AudioPCI ES1373-A");
77376086Scg			return 0;
77476086Scg
77576086Scg		case ES1371REV_ES1373_B:
77676086Scg			device_set_desc(dev, "AudioPCI ES1373-B");
77776086Scg			return 0;
77876086Scg
77976086Scg		case ES1371REV_ES1373_8:
78076086Scg			device_set_desc(dev, "AudioPCI ES1373-8");
78176086Scg			return 0;
78276086Scg
78376086Scg		case ES1371REV_CT5880_A:
78476086Scg			device_set_desc(dev, "Creative CT5880-A");
78576086Scg			return 0;
78676086Scg
78776086Scg		default:
78876086Scg			device_set_desc(dev, "AudioPCI ES1371-?");
78976086Scg			device_printf(dev, "unknown revision %d -- please report to cg@freebsd.org\n", pci_get_revid(dev));
79076086Scg			return 0;
79176086Scg		}
79276086Scg
79376086Scg	case ES1371_PCI_ID2:
79478033Scg		device_set_desc(dev, "Strange AudioPCI ES1371-? (vid=3274)");
79576086Scg		device_printf(dev, "unknown revision %d -- please report to cg@freebsd.org\n", pci_get_revid(dev));
79653413Sroger		return 0;
79776086Scg
798119548Sorion	case CT4730_PCI_ID:
799119548Sorion		switch(pci_get_revid(dev)) {
800119548Sorion		case CT4730REV_CT4730_A:
801119548Sorion			device_set_desc(dev, "Creative SB AudioPCI CT4730");
802119548Sorion			return 0;
803119548Sorion		default:
804119548Sorion			device_set_desc(dev, "Creative SB AudioPCI CT4730-?");
805119548Sorion			device_printf(dev, "unknown revision %d -- please report to cg@freebsd.org\n", pci_get_revid(dev));
806119548Sorion			return 0;
807119548Sorion		}
808119548Sorion
80976086Scg	case CT5880_PCI_ID:
81076086Scg		switch(pci_get_revid(dev)) {
81176086Scg		case CT5880REV_CT5880_C:
81276086Scg			device_set_desc(dev, "Creative CT5880-C");
81376086Scg			return 0;
81476086Scg
81576086Scg		case CT5880REV_CT5880_D:
81676086Scg			device_set_desc(dev, "Creative CT5880-D");
81776086Scg			return 0;
81876086Scg
81995678Scg		case CT5880REV_CT5880_E:
82095678Scg			device_set_desc(dev, "Creative CT5880-E");
82195678Scg			return 0;
82295678Scg
82376086Scg		default:
82476086Scg			device_set_desc(dev, "Creative CT5880-?");
82576086Scg			device_printf(dev, "unknown revision %d -- please report to cg@freebsd.org\n", pci_get_revid(dev));
82676086Scg			return 0;
82776086Scg		}
82876086Scg
82976086Scg	default:
83076086Scg		return ENXIO;
83150724Scg	}
83250724Scg}
83350724Scg
83450724Scgstatic int
83550724Scges_pci_attach(device_t dev)
83650724Scg{
83750724Scg	u_int32_t	data;
83850724Scg	struct es_info *es = 0;
83950724Scg	int		mapped;
84050724Scg	char		status[SND_STATUSLEN];
84165644Scg	struct ac97_info *codec = 0;
84270134Scg	kobj_class_t    ct = NULL;
84350724Scg
84478564Sgreid	if ((es = malloc(sizeof *es, M_DEVBUF, M_NOWAIT | M_ZERO)) == NULL) {
84550724Scg		device_printf(dev, "cannot allocate softc\n");
84650724Scg		return ENXIO;
84750724Scg	}
84850724Scg
84959019Scg	es->dev = dev;
85050724Scg	mapped = 0;
85150724Scg	data = pci_read_config(dev, PCIR_COMMAND, 2);
85255426Scg	data |= (PCIM_CMD_PORTEN|PCIM_CMD_MEMEN|PCIM_CMD_BUSMASTEREN);
85355426Scg	pci_write_config(dev, PCIR_COMMAND, data, 2);
85455426Scg	data = pci_read_config(dev, PCIR_COMMAND, 2);
85550724Scg	if (mapped == 0 && (data & PCIM_CMD_MEMEN)) {
85665644Scg		es->regid = MEM_MAP_REG;
85765644Scg		es->regtype = SYS_RES_MEMORY;
85865644Scg		es->reg = bus_alloc_resource(dev, es->regtype, &es->regid,
85950724Scg					 0, ~0, 1, RF_ACTIVE);
86065644Scg		if (es->reg) {
86165644Scg			es->st = rman_get_bustag(es->reg);
86265644Scg			es->sh = rman_get_bushandle(es->reg);
86350724Scg			mapped++;
86450724Scg		}
86550724Scg	}
86650724Scg	if (mapped == 0 && (data & PCIM_CMD_PORTEN)) {
867119690Sjhb		es->regid = PCIR_BAR(0);
86865644Scg		es->regtype = SYS_RES_IOPORT;
86965644Scg		es->reg = bus_alloc_resource(dev, es->regtype, &es->regid,
87050724Scg					 0, ~0, 1, RF_ACTIVE);
87165644Scg		if (es->reg) {
87265644Scg			es->st = rman_get_bustag(es->reg);
87365644Scg			es->sh = rman_get_bushandle(es->reg);
87450724Scg			mapped++;
87550724Scg		}
87650724Scg	}
87750724Scg	if (mapped == 0) {
87850724Scg		device_printf(dev, "unable to map register space\n");
87950724Scg		goto bad;
88050724Scg	}
88154831Scg
88284658Scg	es->bufsz = pcm_getbuffersize(dev, 4096, ES_DEFAULT_BUFSZ, 65536);
88384658Scg
88456154Speter	if (pci_get_devid(dev) == ES1371_PCI_ID ||
88565340Scg	    pci_get_devid(dev) == ES1371_PCI_ID2 ||
886119548Sorion	    pci_get_devid(dev) == CT5880_PCI_ID ||
887119548Sorion	    pci_get_devid(dev) == CT4730_PCI_ID) {
88871505Scg		if(-1 == es1371_init(es, dev)) {
88954831Scg			device_printf(dev, "unable to initialize the card\n");
89054831Scg			goto bad;
89154831Scg		}
89270134Scg		codec = AC97_CREATE(dev, es, es1371_ac97);
89354831Scg	  	if (codec == NULL) goto bad;
89454831Scg	  	/* our init routine does everything for us */
89554831Scg	  	/* set to NULL; flag mixer_init not to run the ac97_init */
89654831Scg	  	/*	  ac97_mixer.init = NULL;  */
89770134Scg		if (mixer_init(dev, ac97_getmixerclass(), codec)) goto bad;
89870134Scg		ct = &eschan1371_class;
89954831Scg	} else if (pci_get_devid(dev) == ES1370_PCI_ID) {
90054831Scg	  	if (-1 == es1370_init(es)) {
90154831Scg			device_printf(dev, "unable to initialize the card\n");
90254831Scg			goto bad;
90354831Scg	  	}
90470134Scg	  	if (mixer_init(dev, &es1370_mixer_class, es)) goto bad;
90570134Scg		ct = &eschan1370_class;
90654831Scg	} else goto bad;
90750724Scg
90865644Scg	es->irqid = 0;
90965644Scg	es->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &es->irqid,
91052046Simp				 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE);
91174763Scg	if (!es->irq || snd_setup_intr(dev, es->irq, 0, es_intr, es, &es->ih)) {
91250724Scg		device_printf(dev, "unable to map interrupt\n");
91350724Scg		goto bad;
91450724Scg	}
91550724Scg
91650724Scg	if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0,
91750724Scg		/*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
91850724Scg		/*highaddr*/BUS_SPACE_MAXADDR,
91950724Scg		/*filter*/NULL, /*filterarg*/NULL,
92084658Scg		/*maxsize*/es->bufsz, /*nsegments*/1, /*maxsegz*/0x3ffff,
921117126Sscottl		/*flags*/0, /*lockfunc*/busdma_lock_mutex,
922117126Sscottl		/*lockarg*/&Giant, &es->parent_dmat) != 0) {
92350724Scg		device_printf(dev, "unable to create dma tag\n");
92450724Scg		goto bad;
92550724Scg	}
92650724Scg
927126695Smatk	snprintf(status, SND_STATUSLEN, "at %s 0x%lx irq %ld %s",
92865644Scg		 (es->regtype == SYS_RES_IOPORT)? "io" : "memory",
929126695Smatk		 rman_get_start(es->reg), rman_get_start(es->irq),PCM_KLDSTRING(snd_es137x));
93050724Scg
93150724Scg	if (pcm_register(dev, es, 1, 1)) goto bad;
93254831Scg	pcm_addchan(dev, PCMDIR_REC, ct, es);
93354831Scg	pcm_addchan(dev, PCMDIR_PLAY, ct, es);
93450724Scg	pcm_setstatus(dev, status);
93550724Scg
93650724Scg	return 0;
93750724Scg
93850724Scg bad:
93965644Scg	if (codec) ac97_destroy(codec);
94065644Scg	if (es->reg) bus_release_resource(dev, es->regtype, es->regid, es->reg);
94165644Scg	if (es->ih) bus_teardown_intr(dev, es->irq, es->ih);
94265644Scg	if (es->irq) bus_release_resource(dev, SYS_RES_IRQ, es->irqid, es->irq);
94365644Scg	if (es->parent_dmat) bus_dma_tag_destroy(es->parent_dmat);
94450724Scg	if (es) free(es, M_DEVBUF);
94550724Scg	return ENXIO;
94650724Scg}
94750724Scg
94865644Scgstatic int
94965644Scges_pci_detach(device_t dev)
95065644Scg{
95165644Scg	int r;
95265644Scg	struct es_info *es;
95365644Scg
95465644Scg	r = pcm_unregister(dev);
95565644Scg	if (r)
95665644Scg		return r;
95765644Scg
95865644Scg	es = pcm_getdevinfo(dev);
95965644Scg	bus_release_resource(dev, es->regtype, es->regid, es->reg);
96065644Scg	bus_teardown_intr(dev, es->irq, es->ih);
96165644Scg	bus_release_resource(dev, SYS_RES_IRQ, es->irqid, es->irq);
96265644Scg	bus_dma_tag_destroy(es->parent_dmat);
96365644Scg	free(es, M_DEVBUF);
96465644Scg
96565644Scg	return 0;
96665644Scg}
96765644Scg
96850724Scgstatic device_method_t es_methods[] = {
96950724Scg	/* Device interface */
97050724Scg	DEVMETHOD(device_probe,		es_pci_probe),
97150724Scg	DEVMETHOD(device_attach,	es_pci_attach),
97265644Scg	DEVMETHOD(device_detach,	es_pci_detach),
97350724Scg
97450724Scg	{ 0, 0 }
97550724Scg};
97650724Scg
97750724Scgstatic driver_t es_driver = {
97850724Scg	"pcm",
97950724Scg	es_methods,
98082180Scg	PCM_SOFTC_SIZE,
98150724Scg};
98250724Scg
98362483ScgDRIVER_MODULE(snd_es137x, pci, es_driver, pcm_devclass, 0, 0);
98462483ScgMODULE_DEPEND(snd_es137x, snd_pcm, PCM_MINVER, PCM_PREFVER, PCM_MAXVER);
98562483ScgMODULE_VERSION(snd_es137x, 1);
986