es137x.c revision 168847
1139743Simp/*-
2123474Swpaul * Support the ENSONIQ AudioPCI board and Creative Labs SoundBlaster PCI
3123474Swpaul * boards based on the ES1370, ES1371 and ES1373 chips.
4123474Swpaul *
5123474Swpaul * Copyright (c) 1999 Russell Cattelan <cattelan@thebarn.com>
6123474Swpaul * Copyright (c) 1999 Cameron Grant <cg@freebsd.org>
7123474Swpaul * Copyright (c) 1998 by Joachim Kuebart. All rights reserved.
8123474Swpaul *
9123474Swpaul * Redistribution and use in source and binary forms, with or without
10123474Swpaul * modification, are permitted provided that the following conditions
11123474Swpaul * are met:
12123474Swpaul *
13123474Swpaul * 1. Redistributions of source code must retain the above copyright
14123474Swpaul *    notice, this list of conditions and the following disclaimer.
15123474Swpaul *
16123474Swpaul * 2. Redistributions in binary form must reproduce the above copyright
17123474Swpaul *    notice, this list of conditions and the following disclaimer in
18123474Swpaul *    the documentation and/or other materials provided with the
19123474Swpaul *    distribution.
20123474Swpaul *
21123474Swpaul * 3. All advertising materials mentioning features or use of this
22123474Swpaul *    software must display the following acknowledgement:
23123474Swpaul *	This product includes software developed by Joachim Kuebart.
24123474Swpaul *
25123474Swpaul * 4. The name of the author may not be used to endorse or promote
26123474Swpaul *    products derived from this software without specific prior
27123474Swpaul *    written permission.
28123474Swpaul *
29123474Swpaul * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
30123474Swpaul * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
31123474Swpaul * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
32123474Swpaul * DISCLAIMED.	IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
33123474Swpaul * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
34123474Swpaul * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
35123474Swpaul * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36123474Swpaul * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
37123474Swpaul * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38140751Swpaul * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
39140751Swpaul * OF THE POSSIBILITY OF SUCH DAMAGE.
40140751Swpaul */
41140751Swpaul
42140751Swpaul/*
43140751Swpaul * Part of this code was heavily inspired by the linux driver from
44140751Swpaul * Thomas Sailer (sailer@ife.ee.ethz.ch)
45140751Swpaul * Just about everything has been touched and reworked in some way but
46140751Swpaul * the all the underlying sequences/timing/register values are from
47140751Swpaul * Thomas' code.
48140751Swpaul *
49140751Swpaul*/
50140751Swpaul
51140751Swpaul#include <dev/sound/pcm/sound.h>
52140751Swpaul#include <dev/sound/pcm/ac97.h>
53140751Swpaul#include <dev/sound/pci/es137x.h>
54140751Swpaul
55140751Swpaul#include <dev/pci/pcireg.h>
56140751Swpaul#include <dev/pci/pcivar.h>
57140751Swpaul
58140751Swpaul#include <sys/sysctl.h>
59140751Swpaul
60140751Swpaul#include "mixer_if.h"
61140751Swpaul
62140751SwpaulSND_DECLARE_FILE("$FreeBSD: head/sys/dev/sound/pci/es137x.c 168847 2007-04-18 18:26:41Z ariff $");
63140751Swpaul
64140751Swpaul#define MEM_MAP_REG 0x14
65140751Swpaul
66140751Swpaul/* PCI IDs of supported chips */
67140751Swpaul#define ES1370_PCI_ID 0x50001274
68140751Swpaul#define ES1371_PCI_ID 0x13711274
69140751Swpaul#define ES1371_PCI_ID2 0x13713274
70140751Swpaul#define CT5880_PCI_ID 0x58801274
71140751Swpaul#define CT4730_PCI_ID 0x89381102
72140751Swpaul
73140751Swpaul#define ES1371REV_ES1371_A  0x02
74140751Swpaul#define ES1371REV_ES1371_B  0x09
75140751Swpaul
76140751Swpaul#define ES1371REV_ES1373_8  0x08
77140751Swpaul#define ES1371REV_ES1373_A  0x04
78140751Swpaul#define ES1371REV_ES1373_B  0x06
79140751Swpaul
80140751Swpaul#define ES1371REV_CT5880_A  0x07
81140751Swpaul
82140751Swpaul#define CT5880REV_CT5880_C  0x02
83140751Swpaul#define CT5880REV_CT5880_D  0x03
84140751Swpaul#define CT5880REV_CT5880_E  0x04
85140751Swpaul
86140751Swpaul#define CT4730REV_CT4730_A  0x00
87140751Swpaul
88140751Swpaul#define ES_DEFAULT_BUFSZ 4096
89140751Swpaul
90140751Swpaul/* 2 DAC for playback, 1 ADC for record */
91140751Swpaul#define ES_DAC1		0
92140751Swpaul#define ES_DAC2		1
93140751Swpaul#define ES_ADC		2
94140751Swpaul#define ES_NCHANS	3
95140751Swpaul
96140751Swpaul#define ES_DMA_SEGS_MIN	2
97140751Swpaul#define ES_DMA_SEGS_MAX	256
98140751Swpaul#define ES_BLK_MIN	64
99140751Swpaul#define ES_BLK_ALIGN	(~(ES_BLK_MIN - 1))
100140751Swpaul
101140751Swpaul#define ES1370_DAC1_MINSPEED	5512
102140751Swpaul#define ES1370_DAC1_MAXSPEED	44100
103142530Swpaul
104140751Swpaul/* device private data */
105142530Swpaulstruct es_info;
106142530Swpaul
107142530Swpaulstruct es_chinfo {
108123512Swpaul	struct es_info *parent;
109140751Swpaul	struct pcm_channel *channel;
110140751Swpaul	struct snd_dbuf *buffer;
111123512Swpaul	struct pcmchan_caps caps;
112140751Swpaul	int dir, num, index;
113140751Swpaul	uint32_t fmt, blksz, blkcnt, bufsz;
114140751Swpaul	uint32_t ptr, prevptr;
115140751Swpaul	int active;
116140751Swpaul};
117140751Swpaul
118123512Swpaul/*
119140751Swpaul *     32bit Ensoniq Configuration (es->escfg).
120123512Swpaul *     ----------------------------------------
121140751Swpaul *
122123757Swpaul *     +-------+--------+------+------+---------+--------+---------+---------+
123123757Swpaul * len |  16   |    1   |  1   |  1   |    2    |   2    |    1    |    8    |
124140751Swpaul *     +-------+--------+------+------+---------+--------+---------+---------+
125123757Swpaul *     | fixed | single |      |      |         |        |   is    | general |
126123757Swpaul *     | rate  |   pcm  | DACx | DACy | numplay | numrec | es1370? | purpose |
127140751Swpaul *     |       |  mixer |      |      |         |        |         |         |
128140751Swpaul *     +-------+--------+------+------+---------+--------+---------+---------+
129140751Swpaul */
130140751Swpaul#define ES_FIXED_RATE(cfgv)	\
131140751Swpaul		(((cfgv) & 0xffff0000) >> 16)
132140751Swpaul#define ES_SET_FIXED_RATE(cfgv, nv)	\
133144175Swpaul		(((cfgv) & ~0xffff0000) | (((nv) & 0xffff) << 16))
134140751Swpaul#define ES_SINGLE_PCM_MIX(cfgv)	\
135140751Swpaul		(((cfgv) & 0x8000) >> 15)
136140751Swpaul#define ES_SET_SINGLE_PCM_MIX(cfgv, nv)	\
137140751Swpaul		(((cfgv) & ~0x8000) | (((nv) ? 1 : 0) << 15))
138123512Swpaul#define ES_DAC_FIRST(cfgv)	\
139140751Swpaul		(((cfgv) & 0x4000) >> 14)
140140751Swpaul#define ES_SET_DAC_FIRST(cfgv, nv)	\
141140751Swpaul		(((cfgv) & ~0x4000) | (((nv) & 0x1) << 14))
142140751Swpaul#define ES_DAC_SECOND(cfgv)	\
143140751Swpaul		(((cfgv) & 0x2000) >> 13)
144140751Swpaul#define ES_SET_DAC_SECOND(cfgv, nv)	\
145140751Swpaul		(((cfgv) & ~0x2000) | (((nv) & 0x1) << 13))
146124729Swpaul#define ES_NUMPLAY(cfgv)	\
147124729Swpaul		(((cfgv) & 0x1800) >> 11)
148124729Swpaul#define ES_SET_NUMPLAY(cfgv, nv)	\
149124729Swpaul		(((cfgv) & ~0x1800) | (((nv) & 0x3) << 11))
150124729Swpaul#define ES_NUMREC(cfgv)	\
151124729Swpaul		(((cfgv) & 0x600) >> 9)
152124729Swpaul#define ES_SET_NUMREC(cfgv, nv)	\
153124582Sobrien		(((cfgv) & ~0x600) | (((nv) & 0x3) << 9))
154124582Sobrien#define ES_IS_ES1370(cfgv)	\
155124582Sobrien		(((cfgv) & 0x100) >> 8)
156124582Sobrien#define ES_SET_IS_ES1370(cfgv, nv)	\
157124582Sobrien		(((cfgv) & ~0x100) | (((nv) ? 1 : 0) << 8))
158124582Sobrien#define ES_GP(cfgv)	\
159124582Sobrien		((cfgv) & 0xff)
160124582Sobrien#define ES_SET_GP(cfgv, nv)	\
161124582Sobrien		(((cfgv) & ~0xff) | ((nv) & 0xff))
162124582Sobrien
163124582Sobrien#define ES_DAC1_ENABLED(cfgv)	\
164124582Sobrien		(ES_NUMPLAY(cfgv) > 1 || \
165124582Sobrien		(ES_NUMPLAY(cfgv) == 1 && ES_DAC_FIRST(cfgv) == ES_DAC1))
166124582Sobrien#define ES_DAC2_ENABLED(cfgv)	\
167124582Sobrien		(ES_NUMPLAY(cfgv) > 1 || \
168124582Sobrien		(ES_NUMPLAY(cfgv) == 1 && ES_DAC_FIRST(cfgv) == ES_DAC2))
169124582Sobrien
170124582Sobrien/*
171124582Sobrien * DAC 1/2 configuration through kernel hint - hint.pcm.<unit>.dac="val"
172124582Sobrien *
173123474Swpaul * 0 = Enable both DACs - Default
174124582Sobrien * 1 = Enable single DAC (DAC1)
175124582Sobrien * 2 = Enable single DAC (DAC2)
176123474Swpaul * 3 = Enable both DACs, swap position (DAC2 comes first instead of DAC1)
177123474Swpaul */
178123474Swpaul#define ES_DEFAULT_DAC_CFG	0
179123474Swpaul
180123474Swpaulstruct es_info {
181123474Swpaul	bus_space_tag_t st;
182123474Swpaul	bus_space_handle_t sh;
183123474Swpaul	bus_dma_tag_t	parent_dmat;
184123474Swpaul
185123474Swpaul	struct resource *reg, *irq;
186123474Swpaul	int regtype, regid, irqid;
187123474Swpaul	void *ih;
188123474Swpaul
189123474Swpaul	device_t dev;
190123474Swpaul	int num;
191123474Swpaul	unsigned int bufsz, blkcnt;
192123474Swpaul
193123507Swpaul	/* Contents of board's registers */
194123507Swpaul	uint32_t	ctrl;
195123507Swpaul	uint32_t	sctrl;
196123507Swpaul	uint32_t	escfg;
197123507Swpaul	struct es_chinfo ch[ES_NCHANS];
198123507Swpaul	struct mtx	*lock;
199123507Swpaul	struct callout	poll_timer;
200125551Swpaul	int poll_ticks, polling;
201141524Swpaul};
202125551Swpaul
203125551Swpaul#define ES_LOCK(sc)		snd_mtxlock((sc)->lock)
204125551Swpaul#define ES_UNLOCK(sc)		snd_mtxunlock((sc)->lock)
205125551Swpaul#define ES_LOCK_ASSERT(sc)	snd_mtxassert((sc)->lock)
206125551Swpaul
207125551Swpaul/* prototypes */
208125551Swpaulstatic void     es_intr(void *);
209125551Swpaulstatic uint32_t	es1371_wait_src_ready(struct es_info *);
210125551Swpaulstatic void	es1371_src_write(struct es_info *,
211125551Swpaul					unsigned short, unsigned short);
212125551Swpaulstatic unsigned int	es1371_adc_rate(struct es_info *, unsigned int, int);
213125551Swpaulstatic unsigned int	es1371_dac_rate(struct es_info *, unsigned int, int);
214125551Swpaulstatic int	es1371_init(struct es_info *);
215125551Swpaulstatic int      es1370_init(struct es_info *);
216125551Swpaulstatic int      es1370_wrcodec(struct es_info *, unsigned char, unsigned char);
217125551Swpaul
218125551Swpaulstatic uint32_t es_fmt[] = {
219125551Swpaul	AFMT_U8,
220125551Swpaul	AFMT_STEREO | AFMT_U8,
221125551Swpaul	AFMT_S16_LE,
222125551Swpaul	AFMT_STEREO | AFMT_S16_LE,
223125551Swpaul	0
224125551Swpaul};
225125551Swpaulstatic struct pcmchan_caps es_caps = {4000, 48000, es_fmt, 0};
226125551Swpaul
227125551Swpaulstatic const struct {
228125551Swpaul	unsigned        volidx:4;
229125551Swpaul	unsigned        left:4;
230125551Swpaul	unsigned        right:4;
231125551Swpaul	unsigned        stereo:1;
232125551Swpaul	unsigned        recmask:13;
233125551Swpaul	unsigned        avail:1;
234125551Swpaul}       mixtable[SOUND_MIXER_NRDEVICES] = {
235125551Swpaul	[SOUND_MIXER_VOLUME]	= { 0, 0x0, 0x1, 1, 0x1f7f, 1 },
236125551Swpaul	[SOUND_MIXER_PCM] 	= { 1, 0x2, 0x3, 1, 0x0400, 1 },
237125551Swpaul	[SOUND_MIXER_SYNTH]	= { 2, 0x4, 0x5, 1, 0x0060, 1 },
238125551Swpaul	[SOUND_MIXER_CD]	= { 3, 0x6, 0x7, 1, 0x0006, 1 },
239125551Swpaul	[SOUND_MIXER_LINE]	= { 4, 0x8, 0x9, 1, 0x0018, 1 },
240125551Swpaul	[SOUND_MIXER_LINE1]	= { 5, 0xa, 0xb, 1, 0x1800, 1 },
241125860Swpaul	[SOUND_MIXER_LINE2]	= { 6, 0xc, 0x0, 0, 0x0100, 1 },
242125551Swpaul	[SOUND_MIXER_LINE3]	= { 7, 0xd, 0x0, 0, 0x0200, 1 },
243141524Swpaul	[SOUND_MIXER_MIC]	= { 8, 0xe, 0x0, 0, 0x0001, 1 },
244141524Swpaul	[SOUND_MIXER_OGAIN]	= { 9, 0xf, 0x0, 0, 0x0000, 1 }
245125551Swpaul};
246125551Swpaul
247125551Swpaulstatic __inline uint32_t
248125551Swpaules_rd(struct es_info *es, int regno, int size)
249125551Swpaul{
250125551Swpaul	switch (size) {
251125551Swpaul	case 1:
252125551Swpaul		return (bus_space_read_1(es->st, es->sh, regno));
253125551Swpaul	case 2:
254125551Swpaul		return (bus_space_read_2(es->st, es->sh, regno));
255125551Swpaul	case 4:
256125551Swpaul		return (bus_space_read_4(es->st, es->sh, regno));
257125551Swpaul	default:
258125551Swpaul		return (0xFFFFFFFF);
259125551Swpaul	}
260125551Swpaul}
261125551Swpaul
262125551Swpaulstatic __inline void
263125551Swpaules_wr(struct es_info *es, int regno, uint32_t data, int size)
264125551Swpaul{
265125551Swpaul
266125551Swpaul	switch (size) {
267125551Swpaul	case 1:
268125551Swpaul		bus_space_write_1(es->st, es->sh, regno, data);
269125551Swpaul		break;
270125551Swpaul	case 2:
271125551Swpaul		bus_space_write_2(es->st, es->sh, regno, data);
272125551Swpaul		break;
273125551Swpaul	case 4:
274125551Swpaul		bus_space_write_4(es->st, es->sh, regno, data);
275125551Swpaul		break;
276125551Swpaul	}
277125551Swpaul}
278125551Swpaul
279125551Swpaul/* -------------------------------------------------------------------- */
280128229Swpaul/* The es1370 mixer interface */
281125551Swpaul
282125551Swpaulstatic int
283125551Swpaules1370_mixinit(struct snd_mixer *m)
284125551Swpaul{
285125551Swpaul	struct es_info *es;
286125551Swpaul	int i;
287125551Swpaul	uint32_t v;
288125551Swpaul
289125551Swpaul	es = mix_getdevinfo(m);
290125551Swpaul	v = 0;
291128229Swpaul	for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
292128229Swpaul		if (mixtable[i].avail)
293128229Swpaul			v |= (1 << i);
294128229Swpaul	}
295128449Swpaul	/*
296128229Swpaul	 * Each DAC1/2 for ES1370 can be controlled independently
297128229Swpaul	 *   DAC1 = controlled by synth
298128295Swpaul	 *   DAC2 = controlled by pcm
299128229Swpaul	 * This is indeed can confuse user if DAC1 become primary playback
300128229Swpaul	 * channel. Try to be smart and combine both if necessary.
301128229Swpaul	 */
302128229Swpaul	if (ES_SINGLE_PCM_MIX(es->escfg))
303125551Swpaul		v &= ~(1 << SOUND_MIXER_SYNTH);
304125551Swpaul	mix_setdevs(m, v);
305125551Swpaul	v = 0;
306125551Swpaul	for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
307125551Swpaul		if (mixtable[i].recmask)
308125551Swpaul			v |= (1 << i);
309125551Swpaul	}
310125551Swpaul	if (ES_SINGLE_PCM_MIX(es->escfg)) /* ditto */
311125551Swpaul		v &= ~(1 << SOUND_MIXER_SYNTH);
312125551Swpaul	mix_setrecdevs(m, v);
313125551Swpaul	return (0);
314125551Swpaul}
315125551Swpaul
316126620Swpaulstatic int
317126620Swpaules1370_mixset(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right)
318126620Swpaul{
319126620Swpaul	struct es_info *es;
320126620Swpaul	int l, r, rl, rr, set_dac1;
321126620Swpaul
322126620Swpaul	if (!mixtable[dev].avail)
323126620Swpaul		return (-1);
324126620Swpaul	l = left;
325126620Swpaul	r = (mixtable[dev].stereo) ? right : l;
326126620Swpaul	if (mixtable[dev].left == 0xf)
327126620Swpaul		rl = (l < 2) ? 0x80 : 7 - (l - 2) / 14;
328126620Swpaul	else
329125551Swpaul		rl = (l < 10) ? 0x80 : 15 - (l - 10) / 6;
330125551Swpaul	es = mix_getdevinfo(m);
331125551Swpaul	ES_LOCK(es);
332126620Swpaul	if (dev == SOUND_MIXER_PCM && (ES_SINGLE_PCM_MIX(es->escfg)) &&
333126620Swpaul	    ES_DAC1_ENABLED(es->escfg))
334126620Swpaul		set_dac1 = 1;
335126620Swpaul	else
336125551Swpaul		set_dac1 = 0;
337125551Swpaul	if (mixtable[dev].stereo) {
338125551Swpaul		rr = (r < 10) ? 0x80 : 15 - (r - 10) / 6;
339125551Swpaul		es1370_wrcodec(es, mixtable[dev].right, rr);
340126620Swpaul		if (set_dac1 && mixtable[SOUND_MIXER_SYNTH].stereo)
341126620Swpaul			es1370_wrcodec(es,
342126620Swpaul			    mixtable[SOUND_MIXER_SYNTH].right, rr);
343126620Swpaul	}
344126620Swpaul	es1370_wrcodec(es, mixtable[dev].left, rl);
345125551Swpaul	if (set_dac1)
346125551Swpaul		es1370_wrcodec(es, mixtable[SOUND_MIXER_SYNTH].left, rl);
347125551Swpaul	ES_UNLOCK(es);
348125551Swpaul
349125551Swpaul	return (l | (r << 8));
350125551Swpaul}
351125551Swpaul
352125551Swpaulstatic int
353125551Swpaules1370_mixsetrecsrc(struct snd_mixer *m, uint32_t src)
354144888Swpaul{
355125551Swpaul	struct es_info *es;
356125551Swpaul	int i, j = 0;
357125551Swpaul
358125551Swpaul	es = mix_getdevinfo(m);
359125551Swpaul	if (src == 0) src = 1 << SOUND_MIXER_MIC;
360125551Swpaul	src &= mix_getrecdevs(m);
361140827Swpaul	for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
362125551Swpaul		if ((src & (1 << i)) != 0) j |= mixtable[i].recmask;
363125551Swpaul
364125551Swpaul	ES_LOCK(es);
365127552Swpaul	if ((src & (1 << SOUND_MIXER_PCM)) && ES_SINGLE_PCM_MIX(es->escfg) &&
366125551Swpaul	    ES_DAC1_ENABLED(es->escfg))
367125551Swpaul		j |= mixtable[SOUND_MIXER_SYNTH].recmask;
368126620Swpaul	es1370_wrcodec(es, CODEC_LIMIX1, j & 0x55);
369126620Swpaul	es1370_wrcodec(es, CODEC_RIMIX1, j & 0xaa);
370125551Swpaul	es1370_wrcodec(es, CODEC_LIMIX2, (j >> 8) & 0x17);
371125551Swpaul	es1370_wrcodec(es, CODEC_RIMIX2, (j >> 8) & 0x0f);
372125551Swpaul	es1370_wrcodec(es, CODEC_OMIX1, 0x7f);
373125551Swpaul	es1370_wrcodec(es, CODEC_OMIX2, 0x3f);
374125551Swpaul	ES_UNLOCK(es);
375125551Swpaul
376125551Swpaul	return (src);
377125551Swpaul}
378125551Swpaul
379125551Swpaulstatic kobj_method_t es1370_mixer_methods[] = {
380125551Swpaul	KOBJMETHOD(mixer_init,		es1370_mixinit),
381125551Swpaul	KOBJMETHOD(mixer_set,		es1370_mixset),
382125551Swpaul	KOBJMETHOD(mixer_setrecsrc,	es1370_mixsetrecsrc),
383126620Swpaul	{ 0, 0 }
384126620Swpaul};
385126620SwpaulMIXER_DECLARE(es1370_mixer);
386126620Swpaul
387125551Swpaul/* -------------------------------------------------------------------- */
388125551Swpaul
389125551Swpaulstatic int
390125551Swpaules1370_wrcodec(struct es_info *es, unsigned char i, unsigned char data)
391125551Swpaul{
392126620Swpaul	unsigned int t;
393126620Swpaul
394126620Swpaul	ES_LOCK_ASSERT(es);
395125551Swpaul
396125551Swpaul	for (t = 0; t < 0x1000; t++) {
397125860Swpaul		if ((es_rd(es, ES1370_REG_STATUS, 4) &
398125860Swpaul		    STAT_CSTAT) == 0) {
399123474Swpaul			es_wr(es, ES1370_REG_CODEC,
400123474Swpaul			    ((unsigned short)i << CODEC_INDEX_SHIFT) | data, 2);
401123474Swpaul			return (0);
402123474Swpaul		}
403123474Swpaul		DELAY(1);
404123474Swpaul	}
405123474Swpaul	device_printf(es->dev, "%s: timed out\n", __func__);
406123474Swpaul	return (-1);
407123474Swpaul}
408123474Swpaul
409123474Swpaul/* -------------------------------------------------------------------- */
410123474Swpaul
411123474Swpaul/* channel interface */
412123474Swpaulstatic void *
413123474Swpauleschan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b,
414123474Swpaul				struct pcm_channel *c, int dir)
415123474Swpaul{
416123474Swpaul	struct es_info *es = devinfo;
417123474Swpaul	struct es_chinfo *ch;
418123507Swpaul	uint32_t index;
419123474Swpaul
420123474Swpaul	ES_LOCK(es);
421123474Swpaul
422123474Swpaul	if (dir == PCMDIR_PLAY) {
423123474Swpaul		index = ES_GP(es->escfg);
424123474Swpaul		es->escfg = ES_SET_GP(es->escfg, index + 1);
425123474Swpaul		if (index == 0)
426123474Swpaul			index = ES_DAC_FIRST(es->escfg);
427123474Swpaul		else if (index == 1)
428123474Swpaul			index = ES_DAC_SECOND(es->escfg);
429123474Swpaul		else {
430123474Swpaul			device_printf(es->dev,
431144240Swpaul			    "Invalid ES_GP index: %d\n", index);
432123474Swpaul			ES_UNLOCK(es);
433144240Swpaul			return (NULL);
434123474Swpaul		}
435123474Swpaul		if (!(index == ES_DAC1 || index == ES_DAC2)) {
436123474Swpaul			device_printf(es->dev, "Unknown DAC: %d\n", index + 1);
437123474Swpaul			ES_UNLOCK(es);
438123474Swpaul			return (NULL);
439123474Swpaul		}
440123474Swpaul		if (es->ch[index].channel != NULL) {
441123474Swpaul			device_printf(es->dev, "DAC%d already initialized!\n",
442125551Swpaul			    index + 1);
443123474Swpaul			ES_UNLOCK(es);
444125551Swpaul			return (NULL);
445125551Swpaul		}
446125551Swpaul	} else
447125551Swpaul		index = ES_ADC;
448125551Swpaul
449125551Swpaul	ch = &es->ch[index];
450125551Swpaul	ch->index = index;
451125551Swpaul	ch->num = es->num++;
452125551Swpaul	ch->caps = es_caps;
453125551Swpaul	if (ES_IS_ES1370(es->escfg)) {
454125551Swpaul		if (ch->index == ES_DAC1) {
455125551Swpaul			ch->caps.maxspeed = ES1370_DAC1_MAXSPEED;
456125551Swpaul			ch->caps.minspeed = ES1370_DAC1_MINSPEED;
457125551Swpaul		} else {
458125551Swpaul			uint32_t fixed_rate = ES_FIXED_RATE(es->escfg);
459125551Swpaul			if (!(fixed_rate < es_caps.minspeed ||
460125551Swpaul			    fixed_rate > es_caps.maxspeed)) {
461125551Swpaul				ch->caps.maxspeed = fixed_rate;
462125551Swpaul				ch->caps.minspeed = fixed_rate;
463125551Swpaul			}
464125551Swpaul		}
465125551Swpaul	}
466125551Swpaul	ch->parent = es;
467125551Swpaul	ch->channel = c;
468125551Swpaul	ch->buffer = b;
469125551Swpaul	ch->bufsz = es->bufsz;
470125551Swpaul	ch->blkcnt = es->blkcnt;
471125551Swpaul	ch->blksz = ch->bufsz / ch->blkcnt;
472125551Swpaul	ch->dir = dir;
473125551Swpaul	ES_UNLOCK(es);
474125551Swpaul	if (sndbuf_alloc(ch->buffer, es->parent_dmat, 0, ch->bufsz) != 0)
475125551Swpaul		return (NULL);
476125551Swpaul	ES_LOCK(es);
477125551Swpaul	if (dir == PCMDIR_PLAY) {
478125551Swpaul		if (ch->index == ES_DAC1) {
479125551Swpaul			es_wr(es, ES1370_REG_MEMPAGE,
480125551Swpaul			    ES1370_REG_DAC1_FRAMEADR >> 8, 1);
481125551Swpaul			es_wr(es, ES1370_REG_DAC1_FRAMEADR & 0xff,
482125551Swpaul			    sndbuf_getbufaddr(ch->buffer), 4);
483125551Swpaul			es_wr(es, ES1370_REG_DAC1_FRAMECNT & 0xff,
484125551Swpaul			    (ch->bufsz >> 2) - 1, 4);
485125551Swpaul		} else {
486125551Swpaul			es_wr(es, ES1370_REG_MEMPAGE,
487125551Swpaul			    ES1370_REG_DAC2_FRAMEADR >> 8, 1);
488125551Swpaul			es_wr(es, ES1370_REG_DAC2_FRAMEADR & 0xff,
489125551Swpaul			    sndbuf_getbufaddr(ch->buffer), 4);
490125551Swpaul			es_wr(es, ES1370_REG_DAC2_FRAMECNT & 0xff,
491125551Swpaul			    (ch->bufsz >> 2) - 1, 4);
492125551Swpaul		}
493125551Swpaul	} else {
494125551Swpaul		es_wr(es, ES1370_REG_MEMPAGE, ES1370_REG_ADC_FRAMEADR >> 8, 1);
495125551Swpaul		es_wr(es, ES1370_REG_ADC_FRAMEADR & 0xff,
496125551Swpaul		    sndbuf_getbufaddr(ch->buffer), 4);
497125551Swpaul		es_wr(es, ES1370_REG_ADC_FRAMECNT & 0xff,
498140751Swpaul		    (ch->bufsz >> 2) - 1, 4);
499140751Swpaul	}
500140751Swpaul	ES_UNLOCK(es);
501140751Swpaul	return (ch);
502140751Swpaul}
503140751Swpaul
504140751Swpaulstatic int
505140751Swpauleschan_setformat(kobj_t obj, void *data, uint32_t format)
506140751Swpaul{
507141524Swpaul	struct es_chinfo *ch = data;
508141524Swpaul	struct es_info *es = ch->parent;
509141524Swpaul
510141524Swpaul	ES_LOCK(es);
511141524Swpaul	if (ch->dir == PCMDIR_PLAY) {
512141524Swpaul		if (ch->index == ES_DAC1) {
513141524Swpaul			es->sctrl &= ~SCTRL_P1FMT;
514141524Swpaul			if (format & AFMT_S16_LE)
515140751Swpaul				es->sctrl |= SCTRL_P1SEB;
516140751Swpaul			if (format & AFMT_STEREO)
517140751Swpaul				es->sctrl |= SCTRL_P1SMB;
518140751Swpaul		} else {
519141524Swpaul			es->sctrl &= ~SCTRL_P2FMT;
520141524Swpaul			if (format & AFMT_S16_LE)
521141524Swpaul				es->sctrl |= SCTRL_P2SEB;
522141524Swpaul			if (format & AFMT_STEREO)
523141524Swpaul				es->sctrl |= SCTRL_P2SMB;
524141524Swpaul		}
525141524Swpaul	} else {
526140751Swpaul		es->sctrl &= ~SCTRL_R1FMT;
527140751Swpaul		if (format & AFMT_S16_LE)
528140751Swpaul			es->sctrl |= SCTRL_R1SEB;
529140751Swpaul		if (format & AFMT_STEREO)
530140751Swpaul			es->sctrl |= SCTRL_R1SMB;
531140751Swpaul	}
532140751Swpaul	es_wr(es, ES1370_REG_SERIAL_CONTROL, es->sctrl, 4);
533140751Swpaul	ES_UNLOCK(es);
534140751Swpaul	ch->fmt = format;
535140751Swpaul	return (0);
536140751Swpaul}
537140751Swpaul
538140751Swpaulstatic int
539140751Swpauleschan1370_setspeed(kobj_t obj, void *data, uint32_t speed)
540140751Swpaul{
541140751Swpaul	struct es_chinfo *ch = data;
542125551Swpaul	struct es_info *es = ch->parent;
543125551Swpaul
544125551Swpaul	ES_LOCK(es);
545125551Swpaul	/* Fixed rate , do nothing. */
546141524Swpaul	if (ch->caps.minspeed == ch->caps.maxspeed)
547125551Swpaul		return (ch->caps.maxspeed);
548125551Swpaul	if (speed < ch->caps.minspeed)
549125551Swpaul		speed = ch->caps.minspeed;
550125551Swpaul	if (speed > ch->caps.maxspeed)
551125551Swpaul		speed = ch->caps.maxspeed;
552125551Swpaul	if (ch->index == ES_DAC1) {
553125551Swpaul		/*
554125551Swpaul		 * DAC1 does not support continuous rate settings.
555141524Swpaul		 * Pick the nearest and use it since FEEDER_RATE will
556125551Swpaul		 * do the the proper conversion for us.
557125551Swpaul		 */
558125551Swpaul		es->ctrl &= ~CTRL_WTSRSEL;
559125551Swpaul		if (speed < 8268) {
560125551Swpaul			speed = 5512;
561125551Swpaul			es->ctrl |= 0 << CTRL_SH_WTSRSEL;
562125551Swpaul		} else if (speed < 16537) {
563125551Swpaul			speed = 11025;
564125551Swpaul			es->ctrl |= 1 << CTRL_SH_WTSRSEL;
565125551Swpaul		} else if (speed < 33075) {
566125551Swpaul			speed = 22050;
567125551Swpaul			es->ctrl |= 2 << CTRL_SH_WTSRSEL;
568125551Swpaul		} else {
569140751Swpaul			speed = 44100;
570125551Swpaul			es->ctrl |= 3 << CTRL_SH_WTSRSEL;
571125551Swpaul		}
572125551Swpaul	} else {
573125551Swpaul		es->ctrl &= ~CTRL_PCLKDIV;
574125551Swpaul		es->ctrl |= DAC2_SRTODIV(speed) << CTRL_SH_PCLKDIV;
575140751Swpaul	}
576140751Swpaul	es_wr(es, ES1370_REG_CONTROL, es->ctrl, 4);
577140751Swpaul	ES_UNLOCK(es);
578140751Swpaul	return (speed);
579140751Swpaul}
580140751Swpaul
581140751Swpaulstatic int
582140751Swpauleschan1371_setspeed(kobj_t obj, void *data, uint32_t speed)
583142311Swpaul{
584142311Swpaul  	struct es_chinfo *ch = data;
585142311Swpaul  	struct es_info *es = ch->parent;
586142311Swpaul	uint32_t i;
587142311Swpaul	int delta;
588142311Swpaul
589142311Swpaul	ES_LOCK(es);
590142311Swpaul	if (ch->dir == PCMDIR_PLAY)
591142311Swpaul  		i = es1371_dac_rate(es, speed, ch->index); /* play */
592142311Swpaul	else
593142311Swpaul  		i = es1371_adc_rate(es, speed, ch->index); /* record */
594142311Swpaul	ES_UNLOCK(es);
595142311Swpaul	delta = (speed > i) ? (speed - i) : (i - speed);
596142311Swpaul	if (delta < 2)
597142311Swpaul		return (speed);
598142311Swpaul	return (i);
599142311Swpaul}
600142311Swpaul
601142311Swpaulstatic int
602142311Swpauleschan_setfragments(kobj_t obj, void *data, uint32_t blksz, uint32_t blkcnt)
603140751Swpaul{
604140751Swpaul  	struct es_chinfo *ch = data;
605140751Swpaul  	struct es_info *es = ch->parent;
606140751Swpaul
607140751Swpaul	blksz &= ES_BLK_ALIGN;
608140751Swpaul
609140751Swpaul	if (blksz > (sndbuf_getmaxsize(ch->buffer) / ES_DMA_SEGS_MIN))
610140751Swpaul		blksz = sndbuf_getmaxsize(ch->buffer) / ES_DMA_SEGS_MIN;
611140751Swpaul	if (blksz < ES_BLK_MIN)
612140751Swpaul		blksz = ES_BLK_MIN;
613140751Swpaul	if (blkcnt > ES_DMA_SEGS_MAX)
614140751Swpaul		blkcnt = ES_DMA_SEGS_MAX;
615140751Swpaul	if (blkcnt < ES_DMA_SEGS_MIN)
616140751Swpaul		blkcnt = ES_DMA_SEGS_MIN;
617140751Swpaul
618140751Swpaul	while ((blksz * blkcnt) > sndbuf_getmaxsize(ch->buffer)) {
619140751Swpaul		if ((blkcnt >> 1) >= ES_DMA_SEGS_MIN)
620140751Swpaul			blkcnt >>= 1;
621140751Swpaul		else if ((blksz >> 1) >= ES_BLK_MIN)
622140751Swpaul			blksz >>= 1;
623140751Swpaul		else
624140751Swpaul			break;
625140751Swpaul	}
626140751Swpaul
627140751Swpaul	if ((sndbuf_getblksz(ch->buffer) != blksz ||
628140751Swpaul	    sndbuf_getblkcnt(ch->buffer) != blkcnt) &&
629140751Swpaul	    sndbuf_resize(ch->buffer, blkcnt, blksz) != 0)
630140751Swpaul		device_printf(es->dev, "%s: failed blksz=%u blkcnt=%u\n",
631140751Swpaul		    __func__, blksz, blkcnt);
632140751Swpaul
633140751Swpaul	ch->bufsz = sndbuf_getsize(ch->buffer);
634140751Swpaul	ch->blksz = sndbuf_getblksz(ch->buffer);
635140751Swpaul	ch->blkcnt = sndbuf_getblkcnt(ch->buffer);
636140751Swpaul
637140751Swpaul	return (1);
638140751Swpaul}
639140751Swpaul
640140751Swpaulstatic int
641140751Swpauleschan_setblocksize(kobj_t obj, void *data, uint32_t blksz)
642140751Swpaul{
643140751Swpaul  	struct es_chinfo *ch = data;
644140751Swpaul  	struct es_info *es = ch->parent;
645140751Swpaul
646140751Swpaul	eschan_setfragments(obj, data, blksz, es->blkcnt);
647140751Swpaul
648140751Swpaul	return (ch->blksz);
649140751Swpaul}
650140751Swpaul
651140751Swpaul#define es_chan_active(es)	((es)->ch[ES_DAC1].active + \
652140751Swpaul				(es)->ch[ES_DAC2].active + \
653140751Swpaul				(es)->ch[ES_ADC].active)
654140751Swpaul
655140751Swpaulstatic __inline int
656140751Swpaules_poll_channel(struct es_chinfo *ch)
657140751Swpaul{
658140751Swpaul	struct es_info *es;
659144240Swpaul	uint32_t sz, delta;
660140751Swpaul	uint32_t reg, ptr;
661140751Swpaul
662140751Swpaul	if (ch == NULL || ch->channel == NULL || ch->active == 0)
663140751Swpaul		return (0);
664140751Swpaul
665140751Swpaul	es = ch->parent;
666140751Swpaul	if (ch->dir == PCMDIR_PLAY) {
667140751Swpaul		if (ch->index == ES_DAC1)
668140751Swpaul			reg = ES1370_REG_DAC1_FRAMECNT;
669140751Swpaul		else
670140751Swpaul			reg = ES1370_REG_DAC2_FRAMECNT;
671140751Swpaul	} else
672140751Swpaul		reg = ES1370_REG_ADC_FRAMECNT;
673140751Swpaul	sz = ch->blksz * ch->blkcnt;
674140751Swpaul	es_wr(es, ES1370_REG_MEMPAGE, reg >> 8, 4);
675140751Swpaul	ptr = es_rd(es, reg & 0x000000ff, 4) >> 16;
676140751Swpaul	ptr <<= 2;
677140751Swpaul	ch->ptr = ptr;
678140751Swpaul	ptr %= sz;
679140751Swpaul	ptr &= ~(ch->blksz - 1);
680140751Swpaul	delta = (sz + ptr - ch->prevptr) % sz;
681140751Swpaul
682140751Swpaul	if (delta < ch->blksz)
683140751Swpaul		return (0);
684140751Swpaul
685140751Swpaul	ch->prevptr = ptr;
686140751Swpaul
687140751Swpaul	return (1);
688140751Swpaul}
689140751Swpaul
690140751Swpaulstatic void
691140751Swpaules_poll_callback(void *arg)
692140751Swpaul{
693140751Swpaul	struct es_info *es = arg;
694140751Swpaul	uint32_t trigger = 0;
695140751Swpaul	int i;
696140751Swpaul
697140751Swpaul	if (es == NULL)
698140751Swpaul		return;
699140751Swpaul
700140751Swpaul	ES_LOCK(es);
701140751Swpaul	if (es->polling == 0 || es_chan_active(es) == 0) {
702140751Swpaul		ES_UNLOCK(es);
703140751Swpaul		return;
704140751Swpaul	}
705140751Swpaul
706140751Swpaul	for (i = 0; i < ES_NCHANS; i++) {
707140751Swpaul		if (es_poll_channel(&es->ch[i]) != 0)
708140751Swpaul			trigger |= 1 << i;
709140751Swpaul	}
710140751Swpaul
711140751Swpaul	/* XXX */
712140751Swpaul	callout_reset(&es->poll_timer, 1/*es->poll_ticks*/,
713140751Swpaul	    es_poll_callback, es);
714140751Swpaul
715140751Swpaul	ES_UNLOCK(es);
716140751Swpaul
717140751Swpaul	for (i = 0; i < ES_NCHANS; i++) {
718140751Swpaul		if (trigger & (1 << i))
719140751Swpaul			chn_intr(es->ch[i].channel);
720140751Swpaul	}
721140751Swpaul}
722140751Swpaul
723140751Swpaulstatic int
724140751Swpauleschan_trigger(kobj_t obj, void *data, int go)
725140751Swpaul{
726140751Swpaul	struct es_chinfo *ch = data;
727140751Swpaul	struct es_info *es = ch->parent;
728140751Swpaul	uint32_t cnt, b = 0;
729140751Swpaul
730140751Swpaul	if (go == PCMTRIG_EMLDMAWR || go == PCMTRIG_EMLDMARD)
731140751Swpaul		return (0);
732140751Swpaul
733140751Swpaul	ES_LOCK(es);
734140751Swpaul	cnt = (ch->blksz / sndbuf_getbps(ch->buffer)) - 1;
735140751Swpaul	if (ch->fmt & AFMT_16BIT)
736140751Swpaul		b |= 0x02;
737140751Swpaul	if (ch->fmt & AFMT_STEREO)
738140751Swpaul		b |= 0x01;
739140751Swpaul	if (ch->dir == PCMDIR_PLAY) {
740140751Swpaul		if (go == PCMTRIG_START) {
741140751Swpaul			if (ch->index == ES_DAC1) {
742140751Swpaul				es->ctrl |= CTRL_DAC1_EN;
743140751Swpaul				es->sctrl &= ~(SCTRL_P1LOOPSEL |
744140751Swpaul				    SCTRL_P1PAUSE | SCTRL_P1SCTRLD);
745140751Swpaul				if (es->polling == 0)
746140751Swpaul					es->sctrl |= SCTRL_P1INTEN;
747140751Swpaul				else
748140751Swpaul					es->sctrl &= ~SCTRL_P1INTEN;
749140751Swpaul				es->sctrl |= b;
750140751Swpaul				es_wr(es, ES1370_REG_DAC1_SCOUNT, cnt, 4);
751140751Swpaul				/* start at beginning of buffer */
752142311Swpaul				es_wr(es, ES1370_REG_MEMPAGE,
753142311Swpaul				    ES1370_REG_DAC1_FRAMECNT >> 8, 4);
754142311Swpaul				es_wr(es, ES1370_REG_DAC1_FRAMECNT & 0xff,
755142311Swpaul				    (ch->bufsz >> 2) - 1, 4);
756142311Swpaul			} else {
757142311Swpaul				es->ctrl |= CTRL_DAC2_EN;
758142311Swpaul				es->sctrl &= ~(SCTRL_P2ENDINC | SCTRL_P2STINC |
759142497Swpaul				    SCTRL_P2LOOPSEL | SCTRL_P2PAUSE |
760142497Swpaul				    SCTRL_P2DACSEN);
761142497Swpaul				if (es->polling == 0)
762142497Swpaul					es->sctrl |= SCTRL_P2INTEN;
763142497Swpaul				else
764142497Swpaul					es->sctrl &= ~SCTRL_P2INTEN;
765142497Swpaul				es->sctrl |= (b << 2) |
766142497Swpaul				    ((((b >> 1) & 1) + 1) << SCTRL_SH_P2ENDINC);
767142497Swpaul				es_wr(es, ES1370_REG_DAC2_SCOUNT, cnt, 4);
768142311Swpaul				/* start at beginning of buffer */
769142311Swpaul				es_wr(es, ES1370_REG_MEMPAGE,
770142497Swpaul				    ES1370_REG_DAC2_FRAMECNT >> 8, 4);
771142497Swpaul				es_wr(es, ES1370_REG_DAC2_FRAMECNT & 0xff,
772142497Swpaul				    (ch->bufsz >> 2) - 1, 4);
773142497Swpaul			}
774142497Swpaul		} else
775142497Swpaul			es->ctrl &= ~((ch->index == ES_DAC1) ?
776142497Swpaul			    CTRL_DAC1_EN : CTRL_DAC2_EN);
777142497Swpaul	} else {
778142497Swpaul		if (go == PCMTRIG_START) {
779142497Swpaul			es->ctrl |= CTRL_ADC_EN;
780140751Swpaul			es->sctrl &= ~SCTRL_R1LOOPSEL;
781140751Swpaul			if (es->polling == 0)
782140751Swpaul				es->sctrl |= SCTRL_R1INTEN;
783140751Swpaul			else
784140751Swpaul				es->sctrl &= ~SCTRL_R1INTEN;
785140751Swpaul			es->sctrl |= b << 4;
786140751Swpaul			es_wr(es, ES1370_REG_ADC_SCOUNT, cnt, 4);
787141524Swpaul			/* start at beginning of buffer */
788141524Swpaul			es_wr(es, ES1370_REG_MEMPAGE,
789140751Swpaul			    ES1370_REG_ADC_FRAMECNT >> 8, 4);
790140751Swpaul			es_wr(es, ES1370_REG_ADC_FRAMECNT & 0xff,
791140751Swpaul			    (ch->bufsz >> 2) - 1, 4);
792140751Swpaul		} else
793140751Swpaul			es->ctrl &= ~CTRL_ADC_EN;
794140751Swpaul	}
795140751Swpaul	es_wr(es, ES1370_REG_SERIAL_CONTROL, es->sctrl, 4);
796140751Swpaul	es_wr(es, ES1370_REG_CONTROL, es->ctrl, 4);
797140751Swpaul	if (go == PCMTRIG_START) {
798140751Swpaul		if (es->polling != 0) {
799140751Swpaul			ch->ptr = 0;
800140751Swpaul			ch->prevptr = 0;
801140751Swpaul			if (es_chan_active(es) == 0) {
802140751Swpaul				es->poll_ticks = 1;
803140751Swpaul				callout_reset(&es->poll_timer, 1,
804140751Swpaul				    es_poll_callback, es);
805140751Swpaul			}
806140751Swpaul		}
807140751Swpaul		ch->active = 1;
808140751Swpaul	} else {
809140751Swpaul		ch->active = 0;
810140751Swpaul		if (es->polling != 0) {
811144888Swpaul			if (es_chan_active(es) == 0) {
812141524Swpaul				callout_stop(&es->poll_timer);
813144888Swpaul				es->poll_ticks = 1;
814142311Swpaul			}
815141524Swpaul		}
816140751Swpaul	}
817140751Swpaul	ES_UNLOCK(es);
818140751Swpaul	return (0);
819140751Swpaul}
820140751Swpaul
821140751Swpaulstatic int
822140751Swpauleschan_getptr(kobj_t obj, void *data)
823140751Swpaul{
824140751Swpaul	struct es_chinfo *ch = data;
825140751Swpaul	struct es_info *es = ch->parent;
826140751Swpaul	uint32_t reg, cnt;
827140751Swpaul
828140751Swpaul	ES_LOCK(es);
829140751Swpaul	if (es->polling != 0)
830140751Swpaul		cnt = ch->ptr;
831140751Swpaul	else {
832140751Swpaul		if (ch->dir == PCMDIR_PLAY) {
833140751Swpaul			if (ch->index == ES_DAC1)
834142311Swpaul				reg = ES1370_REG_DAC1_FRAMECNT;
835142311Swpaul			else
836142311Swpaul				reg = ES1370_REG_DAC2_FRAMECNT;
837142311Swpaul		} else
838142311Swpaul			reg = ES1370_REG_ADC_FRAMECNT;
839142311Swpaul		es_wr(es, ES1370_REG_MEMPAGE, reg >> 8, 4);
840142311Swpaul		cnt = es_rd(es, reg & 0x000000ff, 4) >> 16;
841142311Swpaul		/* cnt is longwords */
842142311Swpaul		cnt <<= 2;
843142311Swpaul	}
844142311Swpaul	ES_UNLOCK(es);
845142311Swpaul
846142311Swpaul	cnt &= ES_BLK_ALIGN;
847142311Swpaul
848142311Swpaul	return (cnt);
849142311Swpaul}
850140751Swpaul
851140751Swpaulstatic struct pcmchan_caps *
852140751Swpauleschan_getcaps(kobj_t obj, void *data)
853140751Swpaul{
854140751Swpaul	struct es_chinfo *ch = data;
855142311Swpaul
856140751Swpaul	return (&ch->caps);
857140751Swpaul}
858140751Swpaul
859141524Swpaulstatic kobj_method_t eschan1370_methods[] = {
860140751Swpaul	KOBJMETHOD(channel_init,		eschan_init),
861140751Swpaul	KOBJMETHOD(channel_setformat,		eschan_setformat),
862140751Swpaul	KOBJMETHOD(channel_setspeed,		eschan1370_setspeed),
863140751Swpaul	KOBJMETHOD(channel_setblocksize,	eschan_setblocksize),
864140751Swpaul	KOBJMETHOD(channel_setfragments,	eschan_setfragments),
865140751Swpaul	KOBJMETHOD(channel_trigger,		eschan_trigger),
866140751Swpaul	KOBJMETHOD(channel_getptr,		eschan_getptr),
867140751Swpaul	KOBJMETHOD(channel_getcaps,		eschan_getcaps),
868140751Swpaul	{ 0, 0 }
869140751Swpaul};
870140751SwpaulCHANNEL_DECLARE(eschan1370);
871140751Swpaul
872125551Swpaulstatic kobj_method_t eschan1371_methods[] = {
873140751Swpaul	KOBJMETHOD(channel_init,		eschan_init),
874140751Swpaul	KOBJMETHOD(channel_setformat,		eschan_setformat),
875140751Swpaul	KOBJMETHOD(channel_setspeed,		eschan1371_setspeed),
876140751Swpaul	KOBJMETHOD(channel_setblocksize,	eschan_setblocksize),
877140751Swpaul	KOBJMETHOD(channel_setfragments,	eschan_setfragments),
878140751Swpaul	KOBJMETHOD(channel_trigger,		eschan_trigger),
879140751Swpaul	KOBJMETHOD(channel_getptr,		eschan_getptr),
880140751Swpaul	KOBJMETHOD(channel_getcaps,		eschan_getcaps),
881140751Swpaul	{ 0, 0 }
882140751Swpaul};
883140751SwpaulCHANNEL_DECLARE(eschan1371);
884140751Swpaul
885140751Swpaul/* -------------------------------------------------------------------- */
886140751Swpaul/* The interrupt handler */
887140751Swpaulstatic void
888140751Swpaules_intr(void *p)
889140751Swpaul{
890140751Swpaul	struct es_info *es = p;
891140751Swpaul	uint32_t intsrc, sctrl;
892140751Swpaul
893141524Swpaul	ES_LOCK(es);
894140751Swpaul	if (es->polling != 0) {
895140751Swpaul		ES_UNLOCK(es);
896140751Swpaul		return;
897140751Swpaul	}
898140751Swpaul	intsrc = es_rd(es, ES1370_REG_STATUS, 4);
899140751Swpaul	if ((intsrc & STAT_INTR) == 0) {
900140751Swpaul		ES_UNLOCK(es);
901142311Swpaul		return;
902140751Swpaul	}
903140751Swpaul
904140751Swpaul	sctrl = es->sctrl;
905140751Swpaul	if (intsrc & STAT_ADC)
906140751Swpaul		sctrl &= ~SCTRL_R1INTEN;
907140751Swpaul	if (intsrc & STAT_DAC1)
908140751Swpaul		sctrl &= ~SCTRL_P1INTEN;
909140751Swpaul	if (intsrc & STAT_DAC2)
910140751Swpaul		sctrl &= ~SCTRL_P2INTEN;
911140751Swpaul
912140751Swpaul	es_wr(es, ES1370_REG_SERIAL_CONTROL, sctrl, 4);
913140751Swpaul	es_wr(es, ES1370_REG_SERIAL_CONTROL, es->sctrl, 4);
914140751Swpaul	ES_UNLOCK(es);
915140751Swpaul
916140751Swpaul	if (intsrc & STAT_ADC)
917140751Swpaul		chn_intr(es->ch[ES_ADC].channel);
918140751Swpaul	if (intsrc & STAT_DAC1)
919140751Swpaul		chn_intr(es->ch[ES_DAC1].channel);
920140751Swpaul	if (intsrc & STAT_DAC2)
921140751Swpaul		chn_intr(es->ch[ES_DAC2].channel);
922140751Swpaul}
923140751Swpaul
924140751Swpaul/* ES1370 specific */
925140751Swpaulstatic int
926140751Swpaules1370_init(struct es_info *es)
927140751Swpaul{
928125551Swpaul	uint32_t fixed_rate;
929125551Swpaul	int r, single_pcm;
930140751Swpaul
931140751Swpaul	/* ES1370 default to fixed rate operation */
932140751Swpaul	if (resource_int_value(device_get_name(es->dev),
933125551Swpaul	    device_get_unit(es->dev), "fixed_rate", &r) == 0) {
934125551Swpaul		fixed_rate = r;
935142311Swpaul		if (fixed_rate) {
936144888Swpaul			if (fixed_rate < es_caps.minspeed)
937142311Swpaul				fixed_rate = es_caps.minspeed;
938141524Swpaul			if (fixed_rate > es_caps.maxspeed)
939141524Swpaul				fixed_rate = es_caps.maxspeed;
940141524Swpaul		}
941142311Swpaul	} else
942142311Swpaul		fixed_rate = es_caps.maxspeed;
943142311Swpaul
944141524Swpaul	if (resource_int_value(device_get_name(es->dev),
945140751Swpaul	    device_get_unit(es->dev), "single_pcm_mixer", &r) == 0)
946140751Swpaul		single_pcm = (r != 0) ? 1 : 0;
947140751Swpaul	else
948140751Swpaul		single_pcm = 1;
949140751Swpaul
950140751Swpaul	ES_LOCK(es);
951141524Swpaul	if (ES_NUMPLAY(es->escfg) == 1)
952141524Swpaul		single_pcm = 1;
953141524Swpaul	/* This is ES1370 */
954141524Swpaul	es->escfg = ES_SET_IS_ES1370(es->escfg, 1);
955141524Swpaul	if (fixed_rate)
956141524Swpaul		es->escfg = ES_SET_FIXED_RATE(es->escfg, fixed_rate);
957140751Swpaul	else {
958140751Swpaul		es->escfg = ES_SET_FIXED_RATE(es->escfg, 0);
959140751Swpaul		fixed_rate = DSP_DEFAULT_SPEED;
960140751Swpaul	}
961140751Swpaul	if (single_pcm)
962140751Swpaul		es->escfg = ES_SET_SINGLE_PCM_MIX(es->escfg, 1);
963140751Swpaul	else
964141524Swpaul		es->escfg = ES_SET_SINGLE_PCM_MIX(es->escfg, 0);
965141524Swpaul	es->ctrl = CTRL_CDC_EN | CTRL_JYSTK_EN | CTRL_SERR_DIS |
966141524Swpaul	    (DAC2_SRTODIV(fixed_rate) << CTRL_SH_PCLKDIV);
967140751Swpaul	es->ctrl |= 3 << CTRL_SH_WTSRSEL;
968140751Swpaul	es_wr(es, ES1370_REG_CONTROL, es->ctrl, 4);
969140751Swpaul
970140751Swpaul	es->sctrl = 0;
971140751Swpaul	es_wr(es, ES1370_REG_SERIAL_CONTROL, es->sctrl, 4);
972140751Swpaul
973140751Swpaul	/* No RST, PD */
974140751Swpaul	es1370_wrcodec(es, CODEC_RES_PD, 3);
975140751Swpaul	/*
976140751Swpaul	 * CODEC ADC and CODEC DAC use {LR,B}CLK2 and run off the LRCLK2 PLL;
977140751Swpaul	 * program DAC_SYNC=0!
978140751Swpaul	 */
979140751Swpaul	es1370_wrcodec(es, CODEC_CSEL, 0);
980140751Swpaul	/* Recording source is mixer */
981140751Swpaul	es1370_wrcodec(es, CODEC_ADSEL, 0);
982140751Swpaul	/* MIC amp is 0db */
983140751Swpaul	es1370_wrcodec(es, CODEC_MGAIN, 0);
984140751Swpaul	ES_UNLOCK(es);
985140751Swpaul
986140751Swpaul	return (0);
987144175Swpaul}
988144175Swpaul
989144175Swpaul/* ES1371 specific */
990144175Swpaulint
991144175Swpaules1371_init(struct es_info *es)
992144175Swpaul{
993144888Swpaul	uint32_t cssr, devid, revid, subdev;
994125551Swpaul	int idx;
995140751Swpaul
996140751Swpaul	ES_LOCK(es);
997140751Swpaul	/* This is NOT ES1370 */
998140751Swpaul	es->escfg = ES_SET_IS_ES1370(es->escfg, 0);
999140751Swpaul	es->num = 0;
1000140751Swpaul	es->sctrl = 0;
1001140751Swpaul	cssr = 0;
1002140751Swpaul	devid = pci_get_devid(es->dev);
1003140751Swpaul	revid = pci_get_revid(es->dev);
1004140751Swpaul	subdev = (pci_get_subdevice(es->dev) << 16) |
1005140751Swpaul	    pci_get_subvendor(es->dev);
1006140751Swpaul	/*
1007140751Swpaul	 * Joyport blacklist. Either we're facing with broken hardware
1008140751Swpaul	 * or because this hardware need special (unknown) initialization
1009140751Swpaul	 * procedures.
1010140751Swpaul	 */
1011140751Swpaul	switch (subdev) {
1012140751Swpaul	case 0x20001274:	/* old Ensoniq */
1013141524Swpaul		es->ctrl = 0;
1014140751Swpaul		break;
1015140751Swpaul	default:
1016140751Swpaul		es->ctrl = CTRL_JYSTK_EN;
1017140751Swpaul		break;
1018140751Swpaul	}
1019140751Swpaul	if (devid == CT4730_PCI_ID) {
1020141524Swpaul		/* XXX amplifier hack? */
1021140751Swpaul		es->ctrl |= (1 << 16);
1022140751Swpaul	}
1023140751Swpaul	/* initialize the chips */
1024140751Swpaul	es_wr(es, ES1370_REG_CONTROL, es->ctrl, 4);
1025125551Swpaul	es_wr(es, ES1370_REG_SERIAL_CONTROL, es->sctrl, 4);
1026125551Swpaul	es_wr(es, ES1371_REG_LEGACY, 0, 4);
1027125551Swpaul	if ((devid == ES1371_PCI_ID && revid == ES1371REV_ES1373_8) ||
1028125551Swpaul	    (devid == ES1371_PCI_ID && revid == ES1371REV_CT5880_A) ||
1029125551Swpaul	    (devid == CT5880_PCI_ID && revid == CT5880REV_CT5880_C) ||
1030125551Swpaul	    (devid == CT5880_PCI_ID && revid == CT5880REV_CT5880_D) ||
1031125551Swpaul	    (devid == CT5880_PCI_ID && revid == CT5880REV_CT5880_E)) {
1032125551Swpaul		cssr = 1 << 29;
1033125551Swpaul		es_wr(es, ES1370_REG_STATUS, cssr, 4);
1034125551Swpaul		DELAY(20000);
1035125551Swpaul	}
1036125551Swpaul	/* AC'97 warm reset to start the bitclk */
1037125551Swpaul	es_wr(es, ES1370_REG_CONTROL, es->ctrl, 4);
1038125551Swpaul	es_wr(es, ES1371_REG_LEGACY, ES1371_SYNC_RES, 4);
1039125551Swpaul	DELAY(2000);
1040125551Swpaul	es_wr(es, ES1370_REG_CONTROL, es->sctrl, 4);
1041125551Swpaul	es1371_wait_src_ready(es);
1042125551Swpaul	/* Init the sample rate converter */
1043125551Swpaul	es_wr(es, ES1371_REG_SMPRATE, ES1371_DIS_SRC, 4);
1044125551Swpaul	for (idx = 0; idx < 0x80; idx++)
1045125551Swpaul		es1371_src_write(es, idx, 0);
1046141524Swpaul	es1371_src_write(es, ES_SMPREG_DAC1 + ES_SMPREG_TRUNC_N, 16 << 4);
1047141524Swpaul	es1371_src_write(es, ES_SMPREG_DAC1 + ES_SMPREG_INT_REGS, 16 << 10);
1048141524Swpaul	es1371_src_write(es, ES_SMPREG_DAC2 + ES_SMPREG_TRUNC_N, 16 << 4);
1049141524Swpaul	es1371_src_write(es, ES_SMPREG_DAC2 + ES_SMPREG_INT_REGS, 16 << 10);
1050141524Swpaul	es1371_src_write(es, ES_SMPREG_VOL_ADC, 1 << 12);
1051141524Swpaul	es1371_src_write(es, ES_SMPREG_VOL_ADC + 1, 1 << 12);
1052141524Swpaul	es1371_src_write(es, ES_SMPREG_VOL_DAC1, 1 << 12);
1053141524Swpaul	es1371_src_write(es, ES_SMPREG_VOL_DAC1 + 1, 1 << 12);
1054141524Swpaul	es1371_src_write(es, ES_SMPREG_VOL_DAC2, 1 << 12);
1055141524Swpaul	es1371_src_write(es, ES_SMPREG_VOL_DAC2 + 1, 1 << 12);
1056141524Swpaul	es1371_adc_rate(es, 22050, ES_ADC);
1057141524Swpaul	es1371_dac_rate(es, 22050, ES_DAC1);
1058141524Swpaul	es1371_dac_rate(es, 22050, ES_DAC2);
1059141524Swpaul	/*
1060141524Swpaul	 * WARNING:
1061141524Swpaul	 * enabling the sample rate converter without properly programming
1062141524Swpaul	 * its parameters causes the chip to lock up (the SRC busy bit will
1063141524Swpaul	 * be stuck high, and I've found no way to rectify this other than
1064141524Swpaul	 * power cycle)
1065141524Swpaul	 */
1066141524Swpaul	es1371_wait_src_ready(es);
1067141524Swpaul	es_wr(es, ES1371_REG_SMPRATE, 0, 4);
1068141524Swpaul	/* try to reset codec directly */
1069141524Swpaul	es_wr(es, ES1371_REG_CODEC, 0, 4);
1070141524Swpaul	es_wr(es, ES1370_REG_STATUS, cssr, 4);
1071141524Swpaul	ES_UNLOCK(es);
1072141524Swpaul
1073141524Swpaul	return (0);
1074141524Swpaul}
1075141524Swpaul
1076141524Swpaul/* -------------------------------------------------------------------- */
1077141524Swpaul
1078141524Swpaulstatic int
1079141524Swpaules1371_wrcd(kobj_t obj, void *s, int addr, uint32_t data)
1080141524Swpaul{
1081141524Swpaul	uint32_t t, x, orig;
1082141524Swpaul	struct es_info *es = (struct es_info*)s;
1083141524Swpaul
1084141524Swpaul	for (t = 0; t < 0x1000; t++) {
1085141524Swpaul	  	if (!es_rd(es, ES1371_REG_CODEC & CODEC_WIP, 4))
1086141524Swpaul			break;
1087141524Swpaul	}
1088141524Swpaul	/* save the current state for later */
1089141524Swpaul 	x = orig = es_rd(es, ES1371_REG_SMPRATE, 4);
1090141524Swpaul	/* enable SRC state data in SRC mux */
1091141524Swpaul	es_wr(es, ES1371_REG_SMPRATE, (x & (ES1371_DIS_SRC | ES1371_DIS_P1 |
1092141524Swpaul	    ES1371_DIS_P2 | ES1371_DIS_R1)) | 0x00010000, 4);
1093141524Swpaul	/* busy wait */
1094141524Swpaul	for (t = 0; t < 0x1000; t++) {
1095141524Swpaul	  	if ((es_rd(es, ES1371_REG_SMPRATE, 4) & 0x00870000) ==
1096141524Swpaul		    0x00000000)
1097141524Swpaul			break;
1098141524Swpaul	}
1099141524Swpaul	/* wait for a SAFE time to write addr/data and then do it, dammit */
1100141524Swpaul	for (t = 0; t < 0x1000; t++) {
1101141524Swpaul	  	if ((es_rd(es, ES1371_REG_SMPRATE, 4) & 0x00870000) ==
1102141524Swpaul		    0x00010000)
1103141524Swpaul			break;
1104141524Swpaul	}
1105141524Swpaul
1106141524Swpaul	es_wr(es, ES1371_REG_CODEC, ((addr << CODEC_POADD_SHIFT) &
1107141524Swpaul	    CODEC_POADD_MASK) | ((data << CODEC_PODAT_SHIFT) &
1108141524Swpaul	    CODEC_PODAT_MASK), 4);
1109141524Swpaul	/* restore SRC reg */
1110141524Swpaul	es1371_wait_src_ready(s);
1111141524Swpaul	es_wr(es, ES1371_REG_SMPRATE, orig, 4);
1112141524Swpaul
1113141524Swpaul	return (0);
1114141524Swpaul}
1115141524Swpaul
1116141524Swpaulstatic int
1117141524Swpaules1371_rdcd(kobj_t obj, void *s, int addr)
1118141524Swpaul{
1119141524Swpaul  	uint32_t t, x, orig;
1120141524Swpaul  	struct es_info *es = (struct es_info *)s;
1121125551Swpaul
1122125551Swpaul  	for (t = 0; t < 0x1000; t++) {
1123125551Swpaul		if (!(x = es_rd(es, ES1371_REG_CODEC, 4) & CODEC_WIP))
1124125551Swpaul	  		break;
1125125551Swpaul	}
1126142443Swpaul
1127125551Swpaul  	/* save the current state for later */
1128125551Swpaul  	x = orig = es_rd(es, ES1371_REG_SMPRATE, 4);
1129141524Swpaul  	/* enable SRC state data in SRC mux */
1130125551Swpaul  	es_wr(es, ES1371_REG_SMPRATE, (x & (ES1371_DIS_SRC | ES1371_DIS_P1 |
1131125551Swpaul	    ES1371_DIS_P2 | ES1371_DIS_R1)) | 0x00010000, 4);
1132125551Swpaul	/* busy wait */
1133141524Swpaul  	for (t = 0; t < 0x1000; t++) {
1134125551Swpaul		if ((x = es_rd(es, ES1371_REG_SMPRATE, 4) & 0x00870000) ==
1135125551Swpaul		    0x00000000)
1136125551Swpaul	  		break;
1137141524Swpaul	}
1138141524Swpaul  	/* wait for a SAFE time to write addr/data and then do it, dammit */
1139141524Swpaul  	for (t = 0; t < 0x1000; t++) {
1140141524Swpaul		if ((x = es_rd(es, ES1371_REG_SMPRATE, 4) & 0x00870000) ==
1141141524Swpaul		    0x00010000)
1142141524Swpaul	  		break;
1143141524Swpaul	}
1144141524Swpaul
1145141524Swpaul  	es_wr(es, ES1371_REG_CODEC, ((addr << CODEC_POADD_SHIFT) &
1146141524Swpaul	    CODEC_POADD_MASK) | CODEC_PORD, 4);
1147141524Swpaul
1148127284Swpaul  	/* restore SRC reg */
1149127284Swpaul  	es1371_wait_src_ready(s);
1150127284Swpaul  	es_wr(es, ES1371_REG_SMPRATE, orig, 4);
1151127284Swpaul
1152127284Swpaul  	/* now wait for the stinkin' data (RDY) */
1153127284Swpaul  	for (t = 0; t < 0x1000; t++) {
1154127284Swpaul		if ((x = es_rd(es, ES1371_REG_CODEC, 4)) & CODEC_RDY)
1155144888Swpaul	  		break;
1156144888Swpaul	}
1157144888Swpaul
1158144888Swpaul  	return ((x & CODEC_PIDAT_MASK) >> CODEC_PIDAT_SHIFT);
1159144888Swpaul}
1160144888Swpaul
1161144888Swpaulstatic kobj_method_t es1371_ac97_methods[] = {
1162144888Swpaul	KOBJMETHOD(ac97_read,		es1371_rdcd),
1163144888Swpaul	KOBJMETHOD(ac97_write,		es1371_wrcd),
1164144888Swpaul	{ 0, 0 }
1165123474Swpaul};
1166141963SwpaulAC97_DECLARE(es1371_ac97);
1167123474Swpaul
1168123474Swpaul/* -------------------------------------------------------------------- */
1169141524Swpaul
1170141524Swpaulstatic unsigned int
1171142399Swpaules1371_src_read(struct es_info *es, unsigned short reg)
1172141524Swpaul{
1173141524Swpaul  	uint32_t r;
1174141524Swpaul
1175141524Swpaul  	r = es1371_wait_src_ready(es) & (ES1371_DIS_SRC | ES1371_DIS_P1 |
1176141524Swpaul	    ES1371_DIS_P2 | ES1371_DIS_R1);
1177141524Swpaul  	r |= ES1371_SRC_RAM_ADDRO(reg);
1178144888Swpaul  	es_wr(es, ES1371_REG_SMPRATE, r, 4);
1179141963Swpaul  	return (ES1371_SRC_RAM_DATAI(es1371_wait_src_ready(es)));
1180144888Swpaul}
1181144888Swpaul
1182141524Swpaulstatic void
1183123474Swpaules1371_src_write(struct es_info *es, unsigned short reg, unsigned short data)
1184123474Swpaul{
1185144888Swpaul	uint32_t r;
1186144888Swpaul
1187144888Swpaul	r = es1371_wait_src_ready(es) & (ES1371_DIS_SRC | ES1371_DIS_P1 |
1188144888Swpaul	    ES1371_DIS_P2 | ES1371_DIS_R1);
1189144888Swpaul	r |= ES1371_SRC_RAM_ADDRO(reg) |  ES1371_SRC_RAM_DATAO(data);
1190144888Swpaul	es_wr(es, ES1371_REG_SMPRATE, r | ES1371_SRC_RAM_WE, 4);
1191144888Swpaul}
1192144888Swpaul
1193144888Swpaulstatic unsigned int
1194144888Swpaules1371_adc_rate(struct es_info *es, unsigned int rate, int set)
1195127248Swpaul{
1196144888Swpaul  	unsigned int n, truncm, freq, result;
1197144888Swpaul
1198144888Swpaul	ES_LOCK_ASSERT(es);
1199144888Swpaul
1200144888Swpaul  	if (rate > 48000)
1201144175Swpaul		rate = 48000;
1202144888Swpaul  	if (rate < 4000)
1203144888Swpaul		rate = 4000;
1204144888Swpaul  	n = rate / 3000;
1205144175Swpaul  	if ((1 << n) & ((1 << 15) | (1 << 13) | (1 << 11) | (1 << 9)))
1206144888Swpaul		n--;
1207144888Swpaul  	truncm = (21 * n - 1) | 1;
1208144175Swpaul  	freq = ((48000UL << 15) / rate) * n;
1209144888Swpaul  	result = (48000UL << 15) / (freq / n);
1210144888Swpaul  	if (set) {
1211144888Swpaul		if (rate >= 24000) {
1212144888Swpaul	  		if (truncm > 239)
1213144888Swpaul				truncm = 239;
1214144888Swpaul	  		es1371_src_write(es, ES_SMPREG_ADC + ES_SMPREG_TRUNC_N,
1215141524Swpaul			    (((239 - truncm) >> 1) << 9) | (n << 4));
1216144888Swpaul		} else {
1217144888Swpaul	  		if (truncm > 119)
1218141524Swpaul				truncm = 119;
1219144888Swpaul	  		es1371_src_write(es, ES_SMPREG_ADC + ES_SMPREG_TRUNC_N,
1220144888Swpaul			    0x8000 | (((119 - truncm) >> 1) << 9) | (n << 4));
1221144888Swpaul		}
1222144888Swpaul		es1371_src_write(es, ES_SMPREG_ADC + ES_SMPREG_INT_REGS,
1223144888Swpaul		    (es1371_src_read(es, ES_SMPREG_ADC + ES_SMPREG_INT_REGS) &
1224144888Swpaul		    0x00ff) | ((freq >> 5) & 0xfc00));
1225144888Swpaul		es1371_src_write(es, ES_SMPREG_ADC + ES_SMPREG_VFREQ_FRAC,
1226144888Swpaul		    freq & 0x7fff);
1227144888Swpaul		es1371_src_write(es, ES_SMPREG_VOL_ADC, n << 8);
1228141524Swpaul		es1371_src_write(es, ES_SMPREG_VOL_ADC + 1, n << 8);
1229144888Swpaul	}
1230144888Swpaul	return (result);
1231128229Swpaul}
1232144888Swpaul
1233144888Swpaulstatic unsigned int
1234140751Swpaules1371_dac_rate(struct es_info *es, unsigned int rate, int set)
1235128229Swpaul{
1236128229Swpaul  	unsigned int freq, r, result, dac, dis;
1237128229Swpaul
1238128229Swpaul	ES_LOCK_ASSERT(es);
1239128229Swpaul
1240144888Swpaul  	if (rate > 48000)
1241144888Swpaul		rate = 48000;
1242144888Swpaul  	if (rate < 4000)
1243144888Swpaul		rate = 4000;
1244144888Swpaul  	freq = ((rate << 15) + 1500) / 3000;
1245144888Swpaul  	result = (freq * 3000) >> 15;
1246128229Swpaul
1247141963Swpaul	dac = (set == ES_DAC1) ? ES_SMPREG_DAC1 : ES_SMPREG_DAC2;
1248141963Swpaul	dis = (set == ES_DAC1) ? ES1371_DIS_P2 : ES1371_DIS_P1;
1249141980Swpaul	r = (es1371_wait_src_ready(es) & (ES1371_DIS_SRC | ES1371_DIS_P1 |
1250141980Swpaul	    ES1371_DIS_P2 | ES1371_DIS_R1));
1251141963Swpaul	es_wr(es, ES1371_REG_SMPRATE, r, 4);
1252141963Swpaul	es1371_src_write(es, dac + ES_SMPREG_INT_REGS,
1253141963Swpaul	    (es1371_src_read(es, dac + ES_SMPREG_INT_REGS) & 0x00ff) |
1254141963Swpaul	    ((freq >> 5) & 0xfc00));
1255141963Swpaul	es1371_src_write(es, dac + ES_SMPREG_VFREQ_FRAC, freq & 0x7fff);
1256141963Swpaul	r = (es1371_wait_src_ready(es) &
1257141963Swpaul	    (ES1371_DIS_SRC | dis | ES1371_DIS_R1));
1258141963Swpaul	es_wr(es, ES1371_REG_SMPRATE, r, 4);
1259141963Swpaul  	return (result);
1260123474Swpaul}
1261123474Swpaul
1262123474Swpaulstatic uint32_t
1263es1371_wait_src_ready(struct es_info *es)
1264{
1265  	uint32_t t, r;
1266
1267  	for (t = 0; t < 0x1000; t++) {
1268		if (!((r = es_rd(es, ES1371_REG_SMPRATE, 4)) &
1269		    ES1371_SRC_RAM_BUSY))
1270	  		return (r);
1271		DELAY(1);
1272  	}
1273	device_printf(es->dev, "%s: timed out 0x%x [0x%x]\n", __func__,
1274		ES1371_REG_SMPRATE, r);
1275  	return (0);
1276}
1277
1278/* -------------------------------------------------------------------- */
1279
1280/*
1281 * Probe and attach the card
1282 */
1283
1284static int
1285es_pci_probe(device_t dev)
1286{
1287	switch(pci_get_devid(dev)) {
1288	case ES1370_PCI_ID:
1289		device_set_desc(dev, "AudioPCI ES1370");
1290		return (BUS_PROBE_DEFAULT);
1291	case ES1371_PCI_ID:
1292		switch(pci_get_revid(dev)) {
1293		case ES1371REV_ES1371_A:
1294			device_set_desc(dev, "AudioPCI ES1371-A");
1295			return (BUS_PROBE_DEFAULT);
1296		case ES1371REV_ES1371_B:
1297			device_set_desc(dev, "AudioPCI ES1371-B");
1298			return (BUS_PROBE_DEFAULT);
1299		case ES1371REV_ES1373_A:
1300			device_set_desc(dev, "AudioPCI ES1373-A");
1301			return (BUS_PROBE_DEFAULT);
1302		case ES1371REV_ES1373_B:
1303			device_set_desc(dev, "AudioPCI ES1373-B");
1304			return (BUS_PROBE_DEFAULT);
1305		case ES1371REV_ES1373_8:
1306			device_set_desc(dev, "AudioPCI ES1373-8");
1307			return (BUS_PROBE_DEFAULT);
1308		case ES1371REV_CT5880_A:
1309			device_set_desc(dev, "Creative CT5880-A");
1310			return (BUS_PROBE_DEFAULT);
1311		default:
1312			device_set_desc(dev, "AudioPCI ES1371-?");
1313			device_printf(dev,
1314			    "unknown revision %d -- please report to "
1315			    "freebsd-multimedia@freebsd.org\n",
1316			    pci_get_revid(dev));
1317			return (BUS_PROBE_DEFAULT);
1318		}
1319	case ES1371_PCI_ID2:
1320		device_set_desc(dev, "Strange AudioPCI ES1371-? (vid=3274)");
1321		device_printf(dev,
1322		    "unknown revision %d -- please report to "
1323		    "freebsd-multimedia@freebsd.org\n", pci_get_revid(dev));
1324		return (BUS_PROBE_DEFAULT);
1325	case CT4730_PCI_ID:
1326		switch(pci_get_revid(dev)) {
1327		case CT4730REV_CT4730_A:
1328			device_set_desc(dev,
1329			    "Creative SB AudioPCI CT4730/EV1938");
1330			return (BUS_PROBE_DEFAULT);
1331		default:
1332			device_set_desc(dev, "Creative SB AudioPCI CT4730-?");
1333			device_printf(dev,
1334			    "unknown revision %d -- please report to "
1335			    "freebsd-multimedia@freebsd.org\n",
1336			    pci_get_revid(dev));
1337			return (BUS_PROBE_DEFAULT);
1338		}
1339	case CT5880_PCI_ID:
1340		switch(pci_get_revid(dev)) {
1341		case CT5880REV_CT5880_C:
1342			device_set_desc(dev, "Creative CT5880-C");
1343			return (BUS_PROBE_DEFAULT);
1344		case CT5880REV_CT5880_D:
1345			device_set_desc(dev, "Creative CT5880-D");
1346			return (BUS_PROBE_DEFAULT);
1347		case CT5880REV_CT5880_E:
1348			device_set_desc(dev, "Creative CT5880-E");
1349			return (BUS_PROBE_DEFAULT);
1350		default:
1351			device_set_desc(dev, "Creative CT5880-?");
1352			device_printf(dev,
1353			    "unknown revision %d -- please report to "
1354			    "freebsd-multimedia@freebsd.org\n",
1355			    pci_get_revid(dev));
1356			return (BUS_PROBE_DEFAULT);
1357		}
1358	default:
1359		return (ENXIO);
1360	}
1361}
1362
1363#ifdef SND_DYNSYSCTL
1364static int
1365sysctl_es137x_spdif_enable(SYSCTL_HANDLER_ARGS)
1366{
1367	struct es_info *es;
1368	device_t dev;
1369	uint32_t r;
1370	int err, new_en;
1371
1372	dev = oidp->oid_arg1;
1373	es = pcm_getdevinfo(dev);
1374	ES_LOCK(es);
1375	r = es_rd(es, ES1370_REG_STATUS, 4);
1376	ES_UNLOCK(es);
1377	new_en = (r & ENABLE_SPDIF) ? 1 : 0;
1378	err = sysctl_handle_int(oidp, &new_en, sizeof(new_en), req);
1379
1380	if (err || req->newptr == NULL)
1381		return (err);
1382	if (new_en < 0 || new_en > 1)
1383		return (EINVAL);
1384
1385	ES_LOCK(es);
1386	if (new_en) {
1387		r |= ENABLE_SPDIF;
1388		es->ctrl |= SPDIFEN_B;
1389		es->ctrl |= RECEN_B;
1390	} else {
1391		r &= ~ENABLE_SPDIF;
1392		es->ctrl &= ~SPDIFEN_B;
1393		es->ctrl &= ~RECEN_B;
1394	}
1395	es_wr(es, ES1370_REG_CONTROL, es->ctrl, 4);
1396	es_wr(es, ES1370_REG_STATUS, r, 4);
1397	ES_UNLOCK(es);
1398
1399	return (0);
1400}
1401
1402static int
1403sysctl_es137x_latency_timer(SYSCTL_HANDLER_ARGS)
1404{
1405	struct es_info *es;
1406	device_t dev;
1407	uint32_t val;
1408	int err;
1409
1410	dev = oidp->oid_arg1;
1411	es = pcm_getdevinfo(dev);
1412	ES_LOCK(es);
1413	val = pci_read_config(dev, PCIR_LATTIMER, 1);
1414	ES_UNLOCK(es);
1415	err = sysctl_handle_int(oidp, &val, sizeof(val), req);
1416
1417	if (err || req->newptr == NULL)
1418		return (err);
1419	if (val > 255)
1420		return (EINVAL);
1421
1422	ES_LOCK(es);
1423	pci_write_config(dev, PCIR_LATTIMER, val, 1);
1424	ES_UNLOCK(es);
1425
1426	return (0);
1427}
1428
1429static int
1430sysctl_es137x_fixed_rate(SYSCTL_HANDLER_ARGS)
1431{
1432	struct es_info *es;
1433	device_t dev;
1434	uint32_t val;
1435	int err;
1436
1437	dev = oidp->oid_arg1;
1438	es = pcm_getdevinfo(dev);
1439	ES_LOCK(es);
1440	val = ES_FIXED_RATE(es->escfg);
1441	if (val < es_caps.minspeed)
1442		val = 0;
1443	ES_UNLOCK(es);
1444	err = sysctl_handle_int(oidp, &val, sizeof(val), req);
1445
1446	if (err || req->newptr == NULL)
1447		return (err);
1448	if (val != 0 && (val < es_caps.minspeed || val > es_caps.maxspeed))
1449		return (EINVAL);
1450
1451	ES_LOCK(es);
1452	if (es->ctrl & (CTRL_DAC2_EN|CTRL_ADC_EN)) {
1453		ES_UNLOCK(es);
1454		return (EBUSY);
1455	}
1456	if (val) {
1457		if (val != ES_FIXED_RATE(es->escfg)) {
1458			es->escfg = ES_SET_FIXED_RATE(es->escfg, val);
1459			es->ch[ES_DAC2].caps.maxspeed = val;
1460			es->ch[ES_DAC2].caps.minspeed = val;
1461			es->ch[ES_ADC].caps.maxspeed = val;
1462			es->ch[ES_ADC].caps.minspeed = val;
1463			es->ctrl &= ~CTRL_PCLKDIV;
1464			es->ctrl |= DAC2_SRTODIV(val) << CTRL_SH_PCLKDIV;
1465			es_wr(es, ES1370_REG_CONTROL, es->ctrl, 4);
1466		}
1467	} else {
1468		es->escfg = ES_SET_FIXED_RATE(es->escfg, 0);
1469		es->ch[ES_DAC2].caps = es_caps;
1470		es->ch[ES_ADC].caps = es_caps;
1471	}
1472	ES_UNLOCK(es);
1473
1474	return (0);
1475}
1476
1477static int
1478sysctl_es137x_single_pcm_mixer(SYSCTL_HANDLER_ARGS)
1479{
1480	struct es_info *es;
1481	struct snddev_info *d;
1482	struct snd_mixer *m;
1483	struct cdev *i_dev;
1484	device_t dev;
1485	uint32_t val, set;
1486	int recsrc, level, err;
1487
1488	dev = oidp->oid_arg1;
1489	d = device_get_softc(dev);
1490	if (d == NULL || d->mixer_dev == NULL || d->mixer_dev->si_drv1 == NULL)
1491		return (EINVAL);
1492	es = d->devinfo;
1493	if (es == NULL)
1494		return (EINVAL);
1495	ES_LOCK(es);
1496	set = ES_SINGLE_PCM_MIX(es->escfg);
1497	val = set;
1498	ES_UNLOCK(es);
1499	err = sysctl_handle_int(oidp, &val, sizeof(val), req);
1500
1501	if (err || req->newptr == NULL)
1502		return (err);
1503	if (!(val == 0 || val == 1))
1504		return (EINVAL);
1505	if (val == set)
1506		return (0);
1507	i_dev = d->mixer_dev;
1508	if (mixer_ioctl(i_dev, 0, (caddr_t)&recsrc, 0, NULL) != EBADF)
1509		return (EBUSY);
1510	err = mixer_ioctl(i_dev, MIXER_READ(SOUND_MIXER_PCM), (caddr_t)&level,
1511	    -1, NULL);
1512	if (!err)
1513		err = mixer_ioctl(i_dev, MIXER_READ(SOUND_MIXER_RECSRC),
1514		    (caddr_t)&recsrc, -1, NULL);
1515	if (err)
1516		return (err);
1517	if (level < 0)
1518		return (EINVAL);
1519
1520	ES_LOCK(es);
1521	if (es->ctrl & (CTRL_ADC_EN | CTRL_DAC1_EN | CTRL_DAC2_EN)) {
1522		ES_UNLOCK(es);
1523		return (EBUSY);
1524	}
1525	if (val)
1526		es->escfg = ES_SET_SINGLE_PCM_MIX(es->escfg, 1);
1527	else
1528		es->escfg = ES_SET_SINGLE_PCM_MIX(es->escfg, 0);
1529	ES_UNLOCK(es);
1530	m = i_dev->si_drv1;
1531	if (!val) {
1532		mix_setdevs(m, mix_getdevs(d->mixer_dev->si_drv1) |
1533		    (1 << SOUND_MIXER_SYNTH));
1534		mix_setrecdevs(m, mix_getrecdevs(d->mixer_dev->si_drv1) |
1535		    (1 << SOUND_MIXER_SYNTH));
1536		err = mixer_ioctl(i_dev, MIXER_WRITE(SOUND_MIXER_SYNTH),
1537		    (caddr_t)&level, -1, NULL);
1538	} else {
1539		err = mixer_ioctl(i_dev, MIXER_WRITE(SOUND_MIXER_SYNTH),
1540		    (caddr_t)&level, -1, NULL);
1541		mix_setdevs(m, mix_getdevs(d->mixer_dev->si_drv1) &
1542		    ~(1 << SOUND_MIXER_SYNTH));
1543		mix_setrecdevs(m, mix_getrecdevs(d->mixer_dev->si_drv1) &
1544		    ~(1 << SOUND_MIXER_SYNTH));
1545	}
1546	if (!err) {
1547		level = recsrc;
1548		if (recsrc & (1 << SOUND_MIXER_PCM))
1549			recsrc |= 1 << SOUND_MIXER_SYNTH;
1550		else if (recsrc & (1 << SOUND_MIXER_SYNTH))
1551			recsrc |= 1 << SOUND_MIXER_PCM;
1552		if (level != recsrc)
1553			err = mixer_ioctl(i_dev,
1554			    MIXER_WRITE(SOUND_MIXER_RECSRC),
1555			    (caddr_t)&recsrc, -1, NULL);
1556	}
1557	return (err);
1558}
1559
1560static int
1561sysctl_es_polling(SYSCTL_HANDLER_ARGS)
1562{
1563	struct es_info *es;
1564	device_t dev;
1565	int err, val;
1566
1567	dev = oidp->oid_arg1;
1568	es = pcm_getdevinfo(dev);
1569	if (es == NULL)
1570		return (EINVAL);
1571	ES_LOCK(es);
1572	val = es->polling;
1573	ES_UNLOCK(es);
1574	err = sysctl_handle_int(oidp, &val, sizeof(val), req);
1575
1576	if (err || req->newptr == NULL)
1577		return (err);
1578	if (val < 0 || val > 1)
1579		return (EINVAL);
1580
1581	ES_LOCK(es);
1582	if (val != es->polling) {
1583		if (es_chan_active(es) != 0)
1584			err = EBUSY;
1585		else if (val == 0)
1586			es->polling = 0;
1587		else
1588			es->polling = 1;
1589	}
1590	ES_UNLOCK(es);
1591
1592	return (err);
1593}
1594#endif /* SND_DYNSYSCTL */
1595
1596static void
1597es_init_sysctls(device_t dev)
1598{
1599#ifdef SND_DYNSYSCTL
1600	struct es_info *es;
1601	int r, devid, revid;
1602
1603	devid = pci_get_devid(dev);
1604	revid = pci_get_revid(dev);
1605	es = pcm_getdevinfo(dev);
1606	if ((devid == ES1371_PCI_ID && revid == ES1371REV_ES1373_8) ||
1607	    (devid == ES1371_PCI_ID && revid == ES1371REV_CT5880_A) ||
1608	    (devid == CT5880_PCI_ID && revid == CT5880REV_CT5880_C) ||
1609	    (devid == CT5880_PCI_ID && revid == CT5880REV_CT5880_D) ||
1610	    (devid == CT5880_PCI_ID && revid == CT5880REV_CT5880_E)) {
1611		/* XXX: an user should be able to set this with a control tool,
1612		   if not done before 7.0-RELEASE, this needs to be converted
1613		   to a device specific sysctl "dev.pcm.X.yyy" via
1614		   device_get_sysctl_*() as discussed on multimedia@ in msg-id
1615		   <861wujij2q.fsf@xps.des.no> */
1616		SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
1617		    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
1618		    "spdif_enabled", CTLTYPE_INT | CTLFLAG_RW, dev, sizeof(dev),
1619		    sysctl_es137x_spdif_enable, "I",
1620		    "Enable S/PDIF output on primary playback channel");
1621	} else if (devid == ES1370_PCI_ID) {
1622		/*
1623		 * Enable fixed rate sysctl if both DAC2 / ADC enabled.
1624		 */
1625		if (es->ch[ES_DAC2].channel != NULL &&
1626		    es->ch[ES_ADC].channel != NULL) {
1627		/* XXX: an user should be able to set this with a control tool,
1628		   if not done before 7.0-RELEASE, this needs to be converted
1629		   to a device specific sysctl "dev.pcm.X.yyy" via
1630		   device_get_sysctl_*() as discussed on multimedia@ in msg-id
1631		   <861wujij2q.fsf@xps.des.no> */
1632			SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
1633			    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
1634			    OID_AUTO, "fixed_rate", CTLTYPE_INT | CTLFLAG_RW,
1635			    dev, sizeof(dev), sysctl_es137x_fixed_rate, "I",
1636			    "Enable fixed rate playback/recording");
1637		}
1638		/*
1639		 * Enable single pcm mixer sysctl if both DAC1/2 enabled.
1640		 */
1641		if (es->ch[ES_DAC1].channel != NULL &&
1642		    es->ch[ES_DAC2].channel != NULL) {
1643		/* XXX: an user should be able to set this with a control tool,
1644		   if not done before 7.0-RELEASE, this needs to be converted
1645		   to a device specific sysctl "dev.pcm.X.yyy" via
1646		   device_get_sysctl_*() as discussed on multimedia@ in msg-id
1647		   <861wujij2q.fsf@xps.des.no> */
1648			SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
1649			    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
1650			    OID_AUTO, "single_pcm_mixer",
1651			    CTLTYPE_INT | CTLFLAG_RW, dev, sizeof(dev),
1652			    sysctl_es137x_single_pcm_mixer, "I",
1653			    "Single PCM mixer controller for both DAC1/DAC2");
1654		}
1655	}
1656	if (resource_int_value(device_get_name(dev), device_get_unit(dev),
1657	    "latency_timer", &r) == 0 && !(r < 0 || r > 255))
1658		pci_write_config(dev, PCIR_LATTIMER, r, 1);
1659	/* XXX: this needs to be converted to a device specific sysctl
1660	   "dev.pcm.X.yyy" via device_get_sysctl_*() as discussed on
1661	   multimedia@ in msg-id <861wujij2q.fsf@xps.des.no> */
1662	SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
1663	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
1664	    "latency_timer", CTLTYPE_INT | CTLFLAG_RW, dev, sizeof(dev),
1665	    sysctl_es137x_latency_timer, "I",
1666	    "PCI Latency Timer configuration");
1667	SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
1668	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
1669	    "polling", CTLTYPE_INT | CTLFLAG_RW, dev, sizeof(dev),
1670	    sysctl_es_polling, "I",
1671	    "Enable polling mode");
1672#endif /* SND_DYNSYSCTL */
1673}
1674
1675static int
1676es_pci_attach(device_t dev)
1677{
1678	uint32_t	data;
1679	struct es_info *es = NULL;
1680	int		mapped, i, numplay, dac_cfg;
1681	char		status[SND_STATUSLEN];
1682	struct ac97_info *codec = NULL;
1683	kobj_class_t    ct = NULL;
1684	uint32_t devid;
1685
1686	if ((es = malloc(sizeof *es, M_DEVBUF, M_NOWAIT | M_ZERO)) == NULL) {
1687		device_printf(dev, "cannot allocate softc\n");
1688		return (ENXIO);
1689	}
1690	es->lock = snd_mtxcreate(device_get_nameunit(dev), "snd_es137x softc");
1691	es->dev = dev;
1692	es->escfg = 0;
1693	mapped = 0;
1694
1695	pci_enable_busmaster(dev);
1696	data = pci_read_config(dev, PCIR_COMMAND, 2);
1697	data |= (PCIM_CMD_PORTEN|PCIM_CMD_MEMEN);
1698	pci_write_config(dev, PCIR_COMMAND, data, 2);
1699	data = pci_read_config(dev, PCIR_COMMAND, 2);
1700	if (mapped == 0 && (data & PCIM_CMD_MEMEN)) {
1701		es->regid = MEM_MAP_REG;
1702		es->regtype = SYS_RES_MEMORY;
1703		es->reg = bus_alloc_resource_any(dev, es->regtype, &es->regid,
1704		    RF_ACTIVE);
1705		if (es->reg)
1706			mapped++;
1707	}
1708	if (mapped == 0 && (data & PCIM_CMD_PORTEN)) {
1709		es->regid = PCIR_BAR(0);
1710		es->regtype = SYS_RES_IOPORT;
1711		es->reg = bus_alloc_resource_any(dev, es->regtype, &es->regid,
1712		    RF_ACTIVE);
1713		if (es->reg)
1714			mapped++;
1715	}
1716	if (mapped == 0) {
1717		device_printf(dev, "unable to map register space\n");
1718		goto bad;
1719	}
1720
1721	es->st = rman_get_bustag(es->reg);
1722	es->sh = rman_get_bushandle(es->reg);
1723	callout_init(&es->poll_timer, CALLOUT_MPSAFE);
1724	es->poll_ticks = 1;
1725
1726	if (resource_int_value(device_get_name(dev),
1727	    device_get_unit(dev), "polling", &i) == 0 && i != 0)
1728		es->polling = 1;
1729	else
1730		es->polling = 0;
1731
1732	es->bufsz = pcm_getbuffersize(dev, 4096, ES_DEFAULT_BUFSZ, 65536);
1733	if (resource_int_value(device_get_name(dev),
1734	    device_get_unit(dev), "blocksize", &i) == 0 && i > 0) {
1735		i &= ES_BLK_ALIGN;
1736		if (i < ES_BLK_MIN)
1737			i = ES_BLK_MIN;
1738		es->blkcnt = es->bufsz / i;
1739		i = 0;
1740		while (es->blkcnt >> i)
1741			i++;
1742		es->blkcnt = 1 << (i - 1);
1743		if (es->blkcnt < ES_DMA_SEGS_MIN)
1744			es->blkcnt = ES_DMA_SEGS_MIN;
1745		else if (es->blkcnt > ES_DMA_SEGS_MAX)
1746			es->blkcnt = ES_DMA_SEGS_MAX;
1747
1748	} else
1749		es->blkcnt = 2;
1750
1751	if (resource_int_value(device_get_name(dev), device_get_unit(dev),
1752	    "dac", &dac_cfg) == 0) {
1753		if (dac_cfg < 0 || dac_cfg > 3)
1754			dac_cfg = ES_DEFAULT_DAC_CFG;
1755	} else
1756		dac_cfg = ES_DEFAULT_DAC_CFG;
1757
1758	switch (dac_cfg) {
1759	case 0:	/* Enable all DAC: DAC1, DAC2 */
1760		numplay = 2;
1761		es->escfg = ES_SET_DAC_FIRST(es->escfg, ES_DAC1);
1762		es->escfg = ES_SET_DAC_SECOND(es->escfg, ES_DAC2);
1763		break;
1764	case 1: /* Only DAC1 */
1765		numplay = 1;
1766		es->escfg = ES_SET_DAC_FIRST(es->escfg, ES_DAC1);
1767		break;
1768	case 3: /* Enable all DAC / swap position: DAC2, DAC1 */
1769		numplay = 2;
1770		es->escfg = ES_SET_DAC_FIRST(es->escfg, ES_DAC2);
1771		es->escfg = ES_SET_DAC_SECOND(es->escfg, ES_DAC1);
1772		break;
1773	case 2: /* Only DAC2 */
1774	default:
1775		numplay = 1;
1776		es->escfg = ES_SET_DAC_FIRST(es->escfg, ES_DAC2);
1777		break;
1778	}
1779	es->escfg = ES_SET_NUMPLAY(es->escfg, numplay);
1780	es->escfg = ES_SET_NUMREC(es->escfg, 1);
1781
1782	devid = pci_get_devid(dev);
1783	switch (devid) {
1784	case ES1371_PCI_ID:
1785	case ES1371_PCI_ID2:
1786	case CT5880_PCI_ID:
1787	case CT4730_PCI_ID:
1788		es1371_init(es);
1789		codec = AC97_CREATE(dev, es, es1371_ac97);
1790	  	if (codec == NULL)
1791			goto bad;
1792	  	/* our init routine does everything for us */
1793	  	/* set to NULL; flag mixer_init not to run the ac97_init */
1794	  	/*	  ac97_mixer.init = NULL;  */
1795		if (mixer_init(dev, ac97_getmixerclass(), codec))
1796			goto bad;
1797		ct = &eschan1371_class;
1798		break;
1799	case ES1370_PCI_ID:
1800	  	es1370_init(es);
1801		/*
1802		 * Disable fixed rate operation if DAC2 disabled.
1803		 * This is a special case for es1370 only, where the
1804		 * speed of both ADC and DAC2 locked together.
1805		 */
1806		if (!ES_DAC2_ENABLED(es->escfg))
1807			es->escfg = ES_SET_FIXED_RATE(es->escfg, 0);
1808	  	if (mixer_init(dev, &es1370_mixer_class, es))
1809			goto bad;
1810		ct = &eschan1370_class;
1811		break;
1812	default:
1813		goto bad;
1814		/* NOTREACHED */
1815	}
1816
1817	es->irqid = 0;
1818	es->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &es->irqid,
1819	    RF_ACTIVE | RF_SHAREABLE);
1820	if (!es->irq || snd_setup_intr(dev, es->irq, INTR_MPSAFE, es_intr,
1821	    es, &es->ih)) {
1822		device_printf(dev, "unable to map interrupt\n");
1823		goto bad;
1824	}
1825
1826	if (bus_dma_tag_create(/*parent*/bus_get_dma_tag(dev),
1827		/*alignment*/2, /*boundary*/0,
1828		/*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
1829		/*highaddr*/BUS_SPACE_MAXADDR,
1830		/*filter*/NULL, /*filterarg*/NULL,
1831		/*maxsize*/es->bufsz, /*nsegments*/1, /*maxsegz*/0x3ffff,
1832		/*flags*/0, /*lockfunc*/NULL,
1833		/*lockarg*/NULL, &es->parent_dmat) != 0) {
1834		device_printf(dev, "unable to create dma tag\n");
1835		goto bad;
1836	}
1837
1838	snprintf(status, SND_STATUSLEN, "at %s 0x%lx irq %ld %s",
1839	    (es->regtype == SYS_RES_IOPORT)? "io" : "memory",
1840	    rman_get_start(es->reg), rman_get_start(es->irq),
1841	    PCM_KLDSTRING(snd_es137x));
1842
1843	if (pcm_register(dev, es, numplay, 1))
1844		goto bad;
1845	for (i = 0; i < numplay; i++)
1846		pcm_addchan(dev, PCMDIR_PLAY, ct, es);
1847	pcm_addchan(dev, PCMDIR_REC, ct, es);
1848	es_init_sysctls(dev);
1849	pcm_setstatus(dev, status);
1850	es->escfg = ES_SET_GP(es->escfg, 0);
1851	if (numplay == 1)
1852		device_printf(dev, "<Playback: DAC%d / Record: ADC>\n",
1853		    ES_DAC_FIRST(es->escfg) + 1);
1854	else if (numplay == 2)
1855		device_printf(dev, "<Playback: DAC%d,DAC%d / Record: ADC>\n",
1856		    ES_DAC_FIRST(es->escfg) + 1, ES_DAC_SECOND(es->escfg) + 1);
1857	return (0);
1858
1859bad:
1860	if (es->parent_dmat)
1861		bus_dma_tag_destroy(es->parent_dmat);
1862	if (es->ih)
1863		bus_teardown_intr(dev, es->irq, es->ih);
1864	if (es->irq)
1865		bus_release_resource(dev, SYS_RES_IRQ, es->irqid, es->irq);
1866	if (codec)
1867		ac97_destroy(codec);
1868	if (es->reg)
1869		bus_release_resource(dev, es->regtype, es->regid, es->reg);
1870	if (es->lock)
1871		snd_mtxfree(es->lock);
1872	if (es)
1873		free(es, M_DEVBUF);
1874	return (ENXIO);
1875}
1876
1877static int
1878es_pci_detach(device_t dev)
1879{
1880	int r;
1881	struct es_info *es;
1882
1883	r = pcm_unregister(dev);
1884	if (r)
1885		return (r);
1886
1887	es = pcm_getdevinfo(dev);
1888	bus_teardown_intr(dev, es->irq, es->ih);
1889	bus_release_resource(dev, SYS_RES_IRQ, es->irqid, es->irq);
1890	bus_release_resource(dev, es->regtype, es->regid, es->reg);
1891	bus_dma_tag_destroy(es->parent_dmat);
1892	snd_mtxfree(es->lock);
1893	free(es, M_DEVBUF);
1894
1895	return (0);
1896}
1897
1898static device_method_t es_methods[] = {
1899	/* Device interface */
1900	DEVMETHOD(device_probe,		es_pci_probe),
1901	DEVMETHOD(device_attach,	es_pci_attach),
1902	DEVMETHOD(device_detach,	es_pci_detach),
1903
1904	{ 0, 0 }
1905};
1906
1907static driver_t es_driver = {
1908	"pcm",
1909	es_methods,
1910	PCM_SOFTC_SIZE,
1911};
1912
1913DRIVER_MODULE(snd_es137x, pci, es_driver, pcm_devclass, 0, 0);
1914MODULE_DEPEND(snd_es137x, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER);
1915MODULE_VERSION(snd_es137x, 1);
1916