maestro.c revision 78362
1/*-
2 * Copyright (c) 2000 Taku YAMAMOTO <taku@cent.saitama-u.ac.jp>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 *	$Id: maestro.c,v 1.12 2000/09/06 03:32:34 taku Exp $
27 * $FreeBSD: head/sys/dev/sound/pci/maestro.c 78362 2001-06-16 21:25:10Z cg $
28 */
29
30/*
31 * Credits:
32 *
33 * Part of this code (especially in many magic numbers) was heavily inspired
34 * by the Linux driver originally written by
35 * Alan Cox <alan.cox@linux.org>, modified heavily by
36 * Zach Brown <zab@zabbo.net>.
37 *
38 * busdma()-ize and buffer size reduction were suggested by
39 * Cameron Grant <gandalf@vilnya.demon.co.uk>.
40 * Also he showed me the way to use busdma() suite.
41 *
42 * Internal speaker problems on NEC VersaPro's and Dell Inspiron 7500
43 * were looked at by
44 * Munehiro Matsuda <haro@tk.kubota.co.jp>,
45 * who brought patches based on the Linux driver with some simplification.
46 */
47
48#include <dev/sound/pcm/sound.h>
49#include <dev/sound/pcm/ac97.h>
50#include <pci/pcireg.h>
51#include <pci/pcivar.h>
52
53#include <dev/sound/pci/maestro_reg.h>
54
55#define inline __inline
56
57/*
58 * PCI IDs of supported chips:
59 *
60 * MAESTRO-1	0x01001285
61 * MAESTRO-2	0x1968125d
62 * MAESTRO-2E	0x1978125d
63 */
64
65#define MAESTRO_1_PCI_ID	0x01001285
66#define MAESTRO_2_PCI_ID	0x1968125d
67#define MAESTRO_2E_PCI_ID	0x1978125d
68
69#define NEC_SUBID1	0x80581033	/* Taken from Linux driver */
70#define NEC_SUBID2	0x803c1033	/* NEC VersaProNX VA26D    */
71
72#ifndef AGG_MAXPLAYCH
73# define AGG_MAXPLAYCH	4
74#endif
75
76#define AGG_BUFSIZ	0x4000 /* 0x1000, but gets underflows */
77
78
79/* -----------------------------
80 * Data structures.
81 */
82struct agg_chinfo {
83	struct agg_info		*parent;
84	struct pcm_channel	*channel;
85	struct snd_dbuf		*buffer;
86	bus_addr_t		offset;
87	u_int32_t		blocksize;
88	u_int32_t		speed;
89	int			dir;
90	u_int			num;
91	u_int16_t		aputype;
92	u_int16_t		wcreg_tpl;
93};
94
95struct agg_info {
96	device_t		dev;
97	struct resource		*reg;
98	int			regid;
99
100	bus_space_tag_t		st;
101	bus_space_handle_t	sh;
102	bus_dma_tag_t		parent_dmat;
103
104	struct resource		*irq;
105	int			irqid;
106	void			*ih;
107
108	u_int8_t		*stat;
109	bus_addr_t		baseaddr;
110
111	struct ac97_info	*codec;
112	void			*lock;
113
114	u_int			playchns, active;
115	struct agg_chinfo	pch[AGG_MAXPLAYCH];
116	struct agg_chinfo	rch;
117};
118
119static inline void	 ringbus_setdest(struct agg_info*, int, int);
120
121static inline u_int16_t	 wp_rdreg(struct agg_info*, u_int16_t);
122static inline void	 wp_wrreg(struct agg_info*, u_int16_t, u_int16_t);
123static inline u_int16_t	 wp_rdapu(struct agg_info*, int, u_int16_t);
124static inline void	 wp_wrapu(struct agg_info*, int, u_int16_t, u_int16_t);
125static inline void	 wp_settimer(struct agg_info*, u_int);
126static inline void	 wp_starttimer(struct agg_info*);
127static inline void	 wp_stoptimer(struct agg_info*);
128
129static inline u_int16_t	 wc_rdreg(struct agg_info*, u_int16_t);
130static inline void	 wc_wrreg(struct agg_info*, u_int16_t, u_int16_t);
131static inline u_int16_t	 wc_rdchctl(struct agg_info*, int);
132static inline void	 wc_wrchctl(struct agg_info*, int, u_int16_t);
133
134static inline void	 agg_power(struct agg_info*, int);
135
136static void		 agg_init(struct agg_info*);
137
138static void		 aggch_start_dac(struct agg_chinfo*);
139static void		 aggch_stop_dac(struct agg_chinfo*);
140
141static inline void	 suppress_jitter(struct agg_chinfo*);
142
143static inline u_int	 calc_timer_freq(struct agg_chinfo*);
144static void		 set_timer(struct agg_info*);
145
146static void		 agg_intr(void *);
147static int		 agg_probe(device_t);
148static int		 agg_attach(device_t);
149static int		 agg_detach(device_t);
150static int		 agg_suspend(device_t);
151static int		 agg_resume(device_t);
152static int		 agg_shutdown(device_t);
153
154static void	*dma_malloc(struct agg_info*, u_int32_t, bus_addr_t*);
155static void	 dma_free(struct agg_info*, void *);
156
157/* -----------------------------
158 * Subsystems.
159 */
160
161/* Codec/Ringbus */
162
163/* -------------------------------------------------------------------- */
164
165static u_int32_t
166agg_ac97_init(kobj_t obj, void *sc)
167{
168	struct agg_info *ess = sc;
169
170	return (bus_space_read_1(ess->st, ess->sh, PORT_CODEC_STAT) & CODEC_STAT_MASK)? 0 : 1;
171}
172
173static int
174agg_rdcodec(kobj_t obj, void *sc, int regno)
175{
176	struct agg_info *ess = sc;
177	unsigned t;
178
179	/* We have to wait for a SAFE time to write addr/data */
180	for (t = 0; t < 20; t++) {
181		if ((bus_space_read_1(ess->st, ess->sh, PORT_CODEC_STAT)
182		    & CODEC_STAT_MASK) != CODEC_STAT_PROGLESS)
183			break;
184		DELAY(2);	/* 20.8us / 13 */
185	}
186	if (t == 20)
187		device_printf(ess->dev, "agg_rdcodec() PROGLESS timed out.\n");
188
189	bus_space_write_1(ess->st, ess->sh, PORT_CODEC_CMD,
190	    CODEC_CMD_READ | regno);
191	DELAY(21);	/* AC97 cycle = 20.8usec */
192
193	/* Wait for data retrieve */
194	for (t = 0; t < 20; t++) {
195		if ((bus_space_read_1(ess->st, ess->sh, PORT_CODEC_STAT)
196		    & CODEC_STAT_MASK) == CODEC_STAT_RW_DONE)
197			break;
198		DELAY(2);	/* 20.8us / 13 */
199	}
200	if (t == 20)
201		/* Timed out, but perform dummy read. */
202		device_printf(ess->dev, "agg_rdcodec() RW_DONE timed out.\n");
203
204	return bus_space_read_2(ess->st, ess->sh, PORT_CODEC_REG);
205}
206
207static int
208agg_wrcodec(kobj_t obj, void *sc, int regno, u_int32_t data)
209{
210	unsigned t;
211	struct agg_info *ess = sc;
212
213	/* We have to wait for a SAFE time to write addr/data */
214	for (t = 0; t < 20; t++) {
215		if ((bus_space_read_1(ess->st, ess->sh, PORT_CODEC_STAT)
216		    & CODEC_STAT_MASK) != CODEC_STAT_PROGLESS)
217			break;
218		DELAY(2);	/* 20.8us / 13 */
219	}
220	if (t == 20) {
221		/* Timed out. Abort writing. */
222		device_printf(ess->dev, "agg_wrcodec() PROGLESS timed out.\n");
223		return -1;
224	}
225
226	bus_space_write_2(ess->st, ess->sh, PORT_CODEC_REG, data);
227	bus_space_write_1(ess->st, ess->sh, PORT_CODEC_CMD,
228	    CODEC_CMD_WRITE | regno);
229
230	return 0;
231}
232
233static kobj_method_t agg_ac97_methods[] = {
234    	KOBJMETHOD(ac97_init,		agg_ac97_init),
235    	KOBJMETHOD(ac97_read,		agg_rdcodec),
236    	KOBJMETHOD(ac97_write,		agg_wrcodec),
237	{ 0, 0 }
238};
239AC97_DECLARE(agg_ac97);
240
241/* -------------------------------------------------------------------- */
242
243static inline void
244ringbus_setdest(struct agg_info *ess, int src, int dest)
245{
246	u_int32_t	data;
247
248	data = bus_space_read_4(ess->st, ess->sh, PORT_RINGBUS_CTRL);
249	data &= ~(0xfU << src);
250	data |= (0xfU & dest) << src;
251	bus_space_write_4(ess->st, ess->sh, PORT_RINGBUS_CTRL, data);
252}
253
254/* Wave Processor */
255
256static inline u_int16_t
257wp_rdreg(struct agg_info *ess, u_int16_t reg)
258{
259	bus_space_write_2(ess->st, ess->sh, PORT_DSP_INDEX, reg);
260	return bus_space_read_2(ess->st, ess->sh, PORT_DSP_DATA);
261}
262
263static inline void
264wp_wrreg(struct agg_info *ess, u_int16_t reg, u_int16_t data)
265{
266	bus_space_write_2(ess->st, ess->sh, PORT_DSP_INDEX, reg);
267	bus_space_write_2(ess->st, ess->sh, PORT_DSP_DATA, data);
268}
269
270static inline void
271apu_setindex(struct agg_info *ess, u_int16_t reg)
272{
273	int t;
274
275	wp_wrreg(ess, WPREG_CRAM_PTR, reg);
276	/* Sometimes WP fails to set apu register index. */
277	for (t = 0; t < 1000; t++) {
278		if (bus_space_read_2(ess->st, ess->sh, PORT_DSP_DATA) == reg)
279			break;
280		bus_space_write_2(ess->st, ess->sh, PORT_DSP_DATA, reg);
281	}
282	if (t == 1000)
283		device_printf(ess->dev, "apu_setindex() timed out.\n");
284}
285
286static inline u_int16_t
287wp_rdapu(struct agg_info *ess, int ch, u_int16_t reg)
288{
289	u_int16_t ret;
290
291	apu_setindex(ess, ((unsigned)ch << 4) + reg);
292	ret = wp_rdreg(ess, WPREG_DATA_PORT);
293	return ret;
294}
295
296static inline void
297wp_wrapu(struct agg_info *ess, int ch, u_int16_t reg, u_int16_t data)
298{
299	int t;
300
301	apu_setindex(ess, ((unsigned)ch << 4) + reg);
302	wp_wrreg(ess, WPREG_DATA_PORT, data);
303	for (t = 0; t < 1000; t++) {
304		if (bus_space_read_2(ess->st, ess->sh, PORT_DSP_DATA) == data)
305			break;
306		bus_space_write_2(ess->st, ess->sh, PORT_DSP_DATA, data);
307	}
308	if (t == 1000)
309		device_printf(ess->dev, "wp_wrapu() timed out.\n");
310}
311
312static inline void
313wp_settimer(struct agg_info *ess, u_int freq)
314{
315	u_int clock = 48000 << 2;
316	u_int prescale = 0, divide = (freq != 0) ? (clock / freq) : ~0;
317
318	RANGE(divide, 4, 32 << 8);
319
320	for (; divide > 32 << 1; divide >>= 1)
321		prescale++;
322	divide = (divide + 1) >> 1;
323
324	for (; prescale < 7 && divide > 2 && !(divide & 1); divide >>= 1)
325		prescale++;
326
327	wp_wrreg(ess, WPREG_TIMER_ENABLE, 0);
328	wp_wrreg(ess, WPREG_TIMER_FREQ,
329	    (prescale << WP_TIMER_FREQ_PRESCALE_SHIFT) | (divide - 1));
330	wp_wrreg(ess, WPREG_TIMER_ENABLE, 1);
331}
332
333static inline void
334wp_starttimer(struct agg_info *ess)
335{
336	wp_wrreg(ess, WPREG_TIMER_START, 1);
337}
338
339static inline void
340wp_stoptimer(struct agg_info *ess)
341{
342	wp_wrreg(ess, WPREG_TIMER_START, 0);
343	bus_space_write_2(ess->st, ess->sh, PORT_INT_STAT, 1);
344}
345
346/* WaveCache */
347
348static inline u_int16_t
349wc_rdreg(struct agg_info *ess, u_int16_t reg)
350{
351	bus_space_write_2(ess->st, ess->sh, PORT_WAVCACHE_INDEX, reg);
352	return bus_space_read_2(ess->st, ess->sh, PORT_WAVCACHE_DATA);
353}
354
355static inline void
356wc_wrreg(struct agg_info *ess, u_int16_t reg, u_int16_t data)
357{
358	bus_space_write_2(ess->st, ess->sh, PORT_WAVCACHE_INDEX, reg);
359	bus_space_write_2(ess->st, ess->sh, PORT_WAVCACHE_DATA, data);
360}
361
362static inline u_int16_t
363wc_rdchctl(struct agg_info *ess, int ch)
364{
365	return wc_rdreg(ess, ch << 3);
366}
367
368static inline void
369wc_wrchctl(struct agg_info *ess, int ch, u_int16_t data)
370{
371	wc_wrreg(ess, ch << 3, data);
372}
373
374/* Power management */
375
376static inline void
377agg_power(struct agg_info *ess, int status)
378{
379	u_int8_t data;
380
381	data = pci_read_config(ess->dev, CONF_PM_PTR, 1);
382	if (pci_read_config(ess->dev, data, 1) == PPMI_CID)
383		pci_write_config(ess->dev, data + PM_CTRL, status, 1);
384}
385
386
387/* -----------------------------
388 * Controller.
389 */
390
391static inline void
392agg_initcodec(struct agg_info* ess)
393{
394	u_int16_t data;
395
396	if (bus_space_read_4(ess->st, ess->sh, PORT_RINGBUS_CTRL)
397	    & RINGBUS_CTRL_ACLINK_ENABLED) {
398		bus_space_write_4(ess->st, ess->sh, PORT_RINGBUS_CTRL, 0);
399		DELAY(104);	/* 20.8us * (4 + 1) */
400	}
401	/* XXX - 2nd codec should be looked at. */
402	bus_space_write_4(ess->st, ess->sh, PORT_RINGBUS_CTRL,
403	    RINGBUS_CTRL_AC97_SWRESET);
404	DELAY(2);
405	bus_space_write_4(ess->st, ess->sh, PORT_RINGBUS_CTRL,
406	    RINGBUS_CTRL_ACLINK_ENABLED);
407	DELAY(21);
408
409	agg_rdcodec(NULL, ess, 0);
410	if (bus_space_read_1(ess->st, ess->sh, PORT_CODEC_STAT)
411	    & CODEC_STAT_MASK) {
412		bus_space_write_4(ess->st, ess->sh, PORT_RINGBUS_CTRL, 0);
413		DELAY(21);
414
415		/* Try cold reset. */
416		device_printf(ess->dev, "will perform cold reset.\n");
417		data = bus_space_read_2(ess->st, ess->sh, PORT_GPIO_DIR);
418		if (pci_read_config(ess->dev, 0x58, 2) & 1)
419			data |= 0x10;
420		data |= 0x009 &
421		    ~bus_space_read_2(ess->st, ess->sh, PORT_GPIO_DATA);
422		bus_space_write_2(ess->st, ess->sh, PORT_GPIO_MASK, 0xff6);
423		bus_space_write_2(ess->st, ess->sh, PORT_GPIO_DIR,
424		    data | 0x009);
425		bus_space_write_2(ess->st, ess->sh, PORT_GPIO_DATA, 0x000);
426		DELAY(2);
427		bus_space_write_2(ess->st, ess->sh, PORT_GPIO_DATA, 0x001);
428		DELAY(1);
429		bus_space_write_2(ess->st, ess->sh, PORT_GPIO_DATA, 0x009);
430		DELAY(500000);
431		bus_space_write_2(ess->st, ess->sh, PORT_GPIO_DIR, data);
432		DELAY(84);	/* 20.8us * 4 */
433		bus_space_write_4(ess->st, ess->sh, PORT_RINGBUS_CTRL,
434		    RINGBUS_CTRL_ACLINK_ENABLED);
435		DELAY(21);
436	}
437}
438
439static void
440agg_init(struct agg_info* ess)
441{
442	u_int32_t data;
443
444	/* Setup PCI config registers. */
445
446	/* Disable all legacy emulations. */
447	data = pci_read_config(ess->dev, CONF_LEGACY, 2);
448	data |= LEGACY_DISABLED;
449	pci_write_config(ess->dev, CONF_LEGACY, data, 2);
450
451	/* Disconnect from CHI. (Makes Dell inspiron 7500 work?)
452	 * Enable posted write.
453	 * Prefer PCI timing rather than that of ISA.
454	 * Don't swap L/R. */
455	data = pci_read_config(ess->dev, CONF_MAESTRO, 4);
456	data |= MAESTRO_CHIBUS | MAESTRO_POSTEDWRITE | MAESTRO_DMA_PCITIMING;
457	data &= ~MAESTRO_SWAP_LR;
458	pci_write_config(ess->dev, CONF_MAESTRO, data, 4);
459
460	/* Reset direct sound. */
461	bus_space_write_2(ess->st, ess->sh, PORT_HOSTINT_CTRL,
462	    HOSTINT_CTRL_DSOUND_RESET);
463	DELAY(10000);	/* XXX - too long? */
464	bus_space_write_2(ess->st, ess->sh, PORT_HOSTINT_CTRL, 0);
465	DELAY(10000);
466
467	/* Enable direct sound interruption and hardware volume control. */
468	bus_space_write_2(ess->st, ess->sh, PORT_HOSTINT_CTRL,
469	    HOSTINT_CTRL_DSOUND_INT_ENABLED | HOSTINT_CTRL_HWVOL_ENABLED);
470
471	/* Setup Wave Processor. */
472
473	/* Enable WaveCache, set DMA base address. */
474	wp_wrreg(ess, WPREG_WAVE_ROMRAM,
475	    WP_WAVE_VIRTUAL_ENABLED | WP_WAVE_DRAM_ENABLED);
476	bus_space_write_2(ess->st, ess->sh, PORT_WAVCACHE_CTRL,
477	    WAVCACHE_ENABLED | WAVCACHE_WTSIZE_4MB);
478
479	for (data = WAVCACHE_PCMBAR; data < WAVCACHE_PCMBAR + 4; data++)
480		wc_wrreg(ess, data, ess->baseaddr >> WAVCACHE_BASEADDR_SHIFT);
481
482	/* Setup Codec/Ringbus. */
483	agg_initcodec(ess);
484	bus_space_write_4(ess->st, ess->sh, PORT_RINGBUS_CTRL,
485	    RINGBUS_CTRL_RINGBUS_ENABLED | RINGBUS_CTRL_ACLINK_ENABLED);
486
487	wp_wrreg(ess, WPREG_BASE, 0x8500);	/* Parallel I/O */
488	ringbus_setdest(ess, RINGBUS_SRC_ADC,
489	    RINGBUS_DEST_STEREO | RINGBUS_DEST_DSOUND_IN);
490	ringbus_setdest(ess, RINGBUS_SRC_DSOUND,
491	    RINGBUS_DEST_STEREO | RINGBUS_DEST_DAC);
492
493	/* Setup ASSP. Needed for Dell Inspiron 7500? */
494	bus_space_write_1(ess->st, ess->sh, PORT_ASSP_CTRL_B, 0x00);
495	bus_space_write_1(ess->st, ess->sh, PORT_ASSP_CTRL_A, 0x03);
496	bus_space_write_1(ess->st, ess->sh, PORT_ASSP_CTRL_C, 0x00);
497
498	/*
499	 * Setup GPIO.
500	 * There seems to be speciality with NEC systems.
501	 */
502	switch (pci_get_subvendor(ess->dev)
503	    | (pci_get_subdevice(ess->dev) << 16)) {
504	case NEC_SUBID1:
505	case NEC_SUBID2:
506		/* Matthew Braithwaite <matt@braithwaite.net> reported that
507		 * NEC Versa LX doesn't need GPIO operation. */
508		bus_space_write_2(ess->st, ess->sh, PORT_GPIO_MASK, 0x9ff);
509		bus_space_write_2(ess->st, ess->sh, PORT_GPIO_DIR,
510		    bus_space_read_2(ess->st, ess->sh, PORT_GPIO_DIR) | 0x600);
511		bus_space_write_2(ess->st, ess->sh, PORT_GPIO_DATA, 0x200);
512		break;
513	}
514}
515
516/* Channel controller. */
517
518static void
519aggch_start_dac(struct agg_chinfo *ch)
520{
521	u_int wpwa = APU_USE_SYSMEM | (ch->offset >> 9);
522	u_int size = AGG_BUFSIZ >> 1;
523	u_int speed = ch->speed;
524	u_int offset = ch->offset >> 1;
525	u_int cp = 0;
526	u_int16_t apuch = ch->num << 1;
527	u_int dv;
528	int pan = 0;
529
530	switch (ch->aputype) {
531	case APUTYPE_16BITSTEREO:
532		wpwa >>= 1;
533		size >>= 1;
534		offset >>= 1;
535		cp >>= 1;
536		/* FALLTHROUGH */
537	case APUTYPE_8BITSTEREO:
538		pan = 8;
539		apuch++;
540		break;
541	case APUTYPE_8BITLINEAR:
542		speed >>= 1;
543		break;
544	}
545
546	dv = (((speed % 48000) << 16) + 24000) / 48000
547	    + ((speed / 48000) << 16);
548
549	do {
550		wp_wrapu(ch->parent, apuch, APUREG_WAVESPACE, wpwa & 0xff00);
551		wp_wrapu(ch->parent, apuch, APUREG_CURPTR, offset + cp);
552		wp_wrapu(ch->parent, apuch, APUREG_ENDPTR, offset + size);
553		wp_wrapu(ch->parent, apuch, APUREG_LOOPLEN, size);
554		wp_wrapu(ch->parent, apuch, APUREG_AMPLITUDE, 0xe800);
555		wp_wrapu(ch->parent, apuch, APUREG_POSITION, 0x8f00
556		    | (RADIUS_CENTERCIRCLE << APU_RADIUS_SHIFT)
557		    | ((PAN_FRONT + pan) << APU_PAN_SHIFT));
558		wp_wrapu(ch->parent, apuch, APUREG_FREQ_LOBYTE, APU_plus6dB
559		    | ((dv & 0xff) << APU_FREQ_LOBYTE_SHIFT));
560		wp_wrapu(ch->parent, apuch, APUREG_FREQ_HIWORD, dv >> 8);
561
562		if (ch->aputype == APUTYPE_16BITSTEREO)
563			wpwa |= APU_STEREO >> 1;
564		pan = -pan;
565	} while (pan < 0 && apuch--);
566
567	wc_wrchctl(ch->parent, apuch, ch->wcreg_tpl);
568	wc_wrchctl(ch->parent, apuch + 1, ch->wcreg_tpl);
569
570	wp_wrapu(ch->parent, apuch, APUREG_APUTYPE,
571	    (ch->aputype << APU_APUTYPE_SHIFT) | APU_DMA_ENABLED | 0xf);
572	if (ch->wcreg_tpl & WAVCACHE_CHCTL_STEREO)
573		wp_wrapu(ch->parent, apuch + 1, APUREG_APUTYPE,
574		    (ch->aputype << APU_APUTYPE_SHIFT) | APU_DMA_ENABLED | 0xf);
575}
576
577static void
578aggch_stop_dac(struct agg_chinfo *ch)
579{
580	wp_wrapu(ch->parent, (ch->num << 1), APUREG_APUTYPE,
581	    APUTYPE_INACTIVE << APU_APUTYPE_SHIFT);
582	wp_wrapu(ch->parent, (ch->num << 1) + 1, APUREG_APUTYPE,
583	    APUTYPE_INACTIVE << APU_APUTYPE_SHIFT);
584}
585
586/*
587 * Stereo jitter suppressor.
588 * Sometimes playback pointers differ in stereo-paired channels.
589 * Calling this routine within intr fixes the problem.
590 */
591static inline void
592suppress_jitter(struct agg_chinfo *ch)
593{
594	if (ch->wcreg_tpl & WAVCACHE_CHCTL_STEREO) {
595		int cp, diff, halfsize = AGG_BUFSIZ >> 2;
596
597		if (ch->aputype == APUTYPE_16BITSTEREO)
598			halfsize >>= 1;
599		cp = wp_rdapu(ch->parent, (ch->num << 1), APUREG_CURPTR);
600		diff = wp_rdapu(ch->parent, (ch->num << 1) + 1, APUREG_CURPTR);
601		diff -= cp;
602		if (diff >> 1 && diff > -halfsize && diff < halfsize)
603			bus_space_write_2(ch->parent->st, ch->parent->sh,
604			    PORT_DSP_DATA, cp);
605	}
606}
607
608static inline u_int
609calc_timer_freq(struct agg_chinfo *ch)
610{
611	u_int	ss = 2;
612
613	if (ch->aputype == APUTYPE_16BITSTEREO)
614		ss <<= 1;
615	if (ch->aputype == APUTYPE_8BITLINEAR)
616		ss >>= 1;
617
618	return (ch->speed * ss) / ch->blocksize;
619}
620
621static void
622set_timer(struct agg_info *ess)
623{
624	int i;
625	u_int	freq = 0;
626
627	for (i = 0; i < ess->playchns; i++)
628		if ((ess->active & (1 << i)) &&
629		    (freq < calc_timer_freq(ess->pch + i)))
630			freq = calc_timer_freq(ess->pch + i);
631
632	wp_settimer(ess, freq);
633}
634
635
636/* -----------------------------
637 * Newpcm glue.
638 */
639
640static void *
641aggch_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir)
642{
643	struct agg_info *ess = devinfo;
644	struct agg_chinfo *ch;
645	bus_addr_t physaddr;
646	void *p;
647
648	ch = (dir == PCMDIR_PLAY)? ess->pch + ess->playchns : &ess->rch;
649
650	ch->parent = ess;
651	ch->channel = c;
652	ch->buffer = b;
653	ch->num = ess->playchns;
654	ch->dir = dir;
655
656	p = dma_malloc(ess, AGG_BUFSIZ, &physaddr);
657	if (p == NULL)
658		return NULL;
659	sndbuf_setup(b, p, AGG_BUFSIZ);
660
661	ch->offset = physaddr - ess->baseaddr;
662	if (physaddr < ess->baseaddr || ch->offset > WPWA_MAXADDR) {
663		device_printf(ess->dev,
664		    "offset %#x exceeds limit. ", ch->offset);
665		dma_free(ess, sndbuf_getbuf(b));
666		return NULL;
667	}
668
669	ch->wcreg_tpl = (physaddr - 16) & WAVCACHE_CHCTL_ADDRTAG_MASK;
670
671	if (dir == PCMDIR_PLAY) {
672		ess->playchns++;
673		if (bootverbose)
674			device_printf(ess->dev, "pch[%d].offset = %#x\n", ch->num, ch->offset);
675	} else if (bootverbose)
676		device_printf(ess->dev, "rch.offset = %#x\n", ch->offset);
677
678	return ch;
679}
680
681static int
682aggch_free(kobj_t obj, void *data)
683{
684	struct agg_chinfo *ch = data;
685	struct agg_info *ess = ch->parent;
686
687	/* free up buffer - called after channel stopped */
688	dma_free(ess, sndbuf_getbuf(ch->buffer));
689
690	/* return 0 if ok */
691	return 0;
692}
693
694static int
695aggch_setplayformat(kobj_t obj, void *data, u_int32_t format)
696{
697	struct agg_chinfo *ch = data;
698	u_int16_t wcreg_tpl;
699	u_int16_t aputype = APUTYPE_16BITLINEAR;
700
701	wcreg_tpl = ch->wcreg_tpl & WAVCACHE_CHCTL_ADDRTAG_MASK;
702
703	if (format & AFMT_STEREO) {
704		wcreg_tpl |= WAVCACHE_CHCTL_STEREO;
705		aputype += 1;
706	}
707	if (format & AFMT_U8 || format & AFMT_S8) {
708		aputype += 2;
709		if (format & AFMT_U8)
710			wcreg_tpl |= WAVCACHE_CHCTL_U8;
711	}
712	if (format & AFMT_BIGENDIAN || format & AFMT_U16_LE) {
713		format &= ~AFMT_BIGENDIAN & ~AFMT_U16_LE;
714		format |= AFMT_S16_LE;
715	}
716	ch->wcreg_tpl = wcreg_tpl;
717	ch->aputype = aputype;
718	return format;
719}
720
721static int
722aggch_setspeed(kobj_t obj, void *data, u_int32_t speed)
723{
724	struct agg_chinfo *ch = data;
725
726	ch->speed = speed;
727	return ch->speed;
728}
729
730static int
731aggch_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
732{
733	return ((struct agg_chinfo*)data)->blocksize = blocksize;
734}
735
736static int
737aggch_trigger(kobj_t obj, void *data, int go)
738{
739	struct agg_chinfo *ch = data;
740
741	switch (go) {
742	case PCMTRIG_EMLDMAWR:
743		return 0;
744	case PCMTRIG_START:
745		ch->parent->active |= (1 << ch->num);
746		if (ch->dir == PCMDIR_PLAY)
747			aggch_start_dac(ch);
748#if 0	/* XXX - RECORDING */
749		else
750			aggch_start_adc(ch);
751#endif
752		break;
753	case PCMTRIG_ABORT:
754	case PCMTRIG_STOP:
755		ch->parent->active &= ~(1 << ch->num);
756		if (ch->dir == PCMDIR_PLAY)
757			aggch_stop_dac(ch);
758#if 0	/* XXX - RECORDING */
759		else
760			aggch_stop_adc(ch);
761#endif
762		break;
763	}
764
765	if (ch->parent->active) {
766		set_timer(ch->parent);
767		wp_starttimer(ch->parent);
768	} else
769		wp_stoptimer(ch->parent);
770
771	return 0;
772}
773
774static int
775aggch_getplayptr(kobj_t obj, void *data)
776{
777	struct agg_chinfo *ch = data;
778	u_int cp;
779
780	cp = wp_rdapu(ch->parent, (ch->num << 1), APUREG_CURPTR);
781	if (ch->aputype == APUTYPE_16BITSTEREO)
782		cp = (0xffff << 2) & ((cp << 2) - ch->offset);
783	else
784		cp = (0xffff << 1) & ((cp << 1) - ch->offset);
785
786	return cp;
787}
788
789static struct pcmchan_caps *
790aggch_getcaps(kobj_t obj, void *data)
791{
792	static u_int32_t playfmt[] = {
793		AFMT_U8,
794		AFMT_STEREO | AFMT_U8,
795		AFMT_S8,
796		AFMT_STEREO | AFMT_S8,
797		AFMT_S16_LE,
798		AFMT_STEREO | AFMT_S16_LE,
799		0
800	};
801	static struct pcmchan_caps playcaps = {2000, 96000, playfmt, 0};
802
803	static u_int32_t recfmt[] = {
804		AFMT_S8,
805		AFMT_STEREO | AFMT_S8,
806		AFMT_S16_LE,
807		AFMT_STEREO | AFMT_S16_LE,
808		0
809	};
810	static struct pcmchan_caps reccaps = {4000, 48000, recfmt, 0};
811
812	return (((struct agg_chinfo*)data)->dir == PCMDIR_PLAY)?
813	    &playcaps : &reccaps;
814}
815
816static kobj_method_t aggch_methods[] = {
817    	KOBJMETHOD(channel_init,		aggch_init),
818    	KOBJMETHOD(channel_free,		aggch_free),
819    	KOBJMETHOD(channel_setformat,		aggch_setplayformat),
820    	KOBJMETHOD(channel_setspeed,		aggch_setspeed),
821    	KOBJMETHOD(channel_setblocksize,	aggch_setblocksize),
822    	KOBJMETHOD(channel_trigger,		aggch_trigger),
823    	KOBJMETHOD(channel_getptr,		aggch_getplayptr),
824    	KOBJMETHOD(channel_getcaps,		aggch_getcaps),
825	{ 0, 0 }
826};
827CHANNEL_DECLARE(aggch);
828
829/* -----------------------------
830 * Bus space.
831 */
832
833static void
834agg_intr(void *sc)
835{
836	struct agg_info* ess = sc;
837	u_int16_t status;
838	int i;
839
840	status = bus_space_read_1(ess->st, ess->sh, PORT_HOSTINT_STAT);
841	if (!status)
842		return;
843
844	/* Acknowledge all. */
845	bus_space_write_2(ess->st, ess->sh, PORT_INT_STAT, 1);
846	bus_space_write_1(ess->st, ess->sh, PORT_HOSTINT_STAT, 0xff);
847
848	if (status & HOSTINT_STAT_HWVOL) {
849		u_int event;
850
851		event = bus_space_read_1(ess->st, ess->sh, PORT_HWVOL_MASTER);
852		switch (event) {
853		case HWVOL_MUTE:
854			mixer_hwvol_mute(ess->dev);
855			break;
856		case HWVOL_UP:
857			mixer_hwvol_step(ess->dev, 1, 1);
858			break;
859		case HWVOL_DOWN:
860			mixer_hwvol_step(ess->dev, -1, -1);
861			break;
862		case HWVOL_NOP:
863			break;
864		default:
865			device_printf(ess->dev, "%s: unknown HWVOL event 0x%x\n",
866			    device_get_nameunit(ess->dev), event);
867		}
868		bus_space_write_1(ess->st, ess->sh, PORT_HWVOL_MASTER,
869		    HWVOL_NOP);
870	}
871
872	for (i = 0; i < ess->playchns; i++)
873		if (ess->active & (1 << i)) {
874			suppress_jitter(ess->pch + i);
875			chn_intr(ess->pch[i].channel);
876		}
877#if 0	/* XXX - RECORDING */
878	if (ess->active & (1 << i))
879		chn_intr(ess->rch.channel);
880#endif
881}
882
883static void
884setmap(void *arg, bus_dma_segment_t *segs, int nseg, int error)
885{
886	bus_addr_t *phys = arg;
887
888	*phys = error? 0 : segs->ds_addr;
889
890	if (bootverbose) {
891		printf("setmap (%lx, %lx), nseg=%d, error=%d\n",
892		    (unsigned long)segs->ds_addr, (unsigned long)segs->ds_len,
893		    nseg, error);
894	}
895}
896
897static void *
898dma_malloc(struct agg_info *sc, u_int32_t sz, bus_addr_t *phys)
899{
900	void *buf;
901	bus_dmamap_t map;
902
903	if (bus_dmamem_alloc(sc->parent_dmat, &buf, BUS_DMA_NOWAIT, &map))
904		return NULL;
905	if (bus_dmamap_load(sc->parent_dmat, map, buf, sz, setmap, phys, 0)
906	    || !*phys) {
907		bus_dmamem_free(sc->parent_dmat, buf, map);
908		return NULL;
909	}
910	return buf;
911}
912
913static void
914dma_free(struct agg_info *sc, void *buf)
915{
916	bus_dmamem_free(sc->parent_dmat, buf, NULL);
917}
918
919static int
920agg_probe(device_t dev)
921{
922	char *s = NULL;
923
924	switch (pci_get_devid(dev)) {
925	case MAESTRO_1_PCI_ID:
926		s = "ESS Technology Maestro-1";
927		break;
928
929	case MAESTRO_2_PCI_ID:
930		s = "ESS Technology Maestro-2";
931		break;
932
933	case MAESTRO_2E_PCI_ID:
934		s = "ESS Technology Maestro-2E";
935		break;
936	}
937
938	if (s != NULL && pci_get_class(dev) == PCIC_MULTIMEDIA) {
939		device_set_desc(dev, s);
940		return 0;
941	}
942	return ENXIO;
943}
944
945static int
946agg_attach(device_t dev)
947{
948	struct agg_info	*ess = NULL;
949	u_int32_t	data;
950	int	mapped = 0;
951	int	regid = PCIR_MAPS;
952	struct resource	*reg = NULL;
953	struct ac97_info	*codec = NULL;
954	int	irqid = 0;
955	struct resource	*irq = NULL;
956	void	*ih = NULL;
957	char	status[SND_STATUSLEN];
958
959	if ((ess = malloc(sizeof *ess, M_DEVBUF, M_NOWAIT)) == NULL) {
960		device_printf(dev, "cannot allocate softc\n");
961		return ENXIO;
962	}
963	bzero(ess, sizeof *ess);
964	ess->dev = dev;
965
966	if (bus_dma_tag_create(/*parent*/NULL,
967	    /*alignment*/1 << WAVCACHE_BASEADDR_SHIFT,
968	    /*boundary*/WPWA_MAXADDR + 1,
969	    /*lowaddr*/MAESTRO_MAXADDR, /*highaddr*/BUS_SPACE_MAXADDR,
970	    /*filter*/NULL, /*filterarg*/NULL,
971	    /*maxsize*/AGG_BUFSIZ * 2, /*nsegments*/1, /*maxsegz*/0x3ffff,
972	    /*flags*/0, &ess->parent_dmat) != 0) {
973		device_printf(dev, "unable to create dma tag\n");
974		goto bad;
975	}
976
977	ess->stat = dma_malloc(ess, AGG_BUFSIZ, &ess->baseaddr);
978	if (ess->stat == NULL) {
979		device_printf(dev, "cannot allocate status buffer\n");
980		goto bad;
981	}
982	if (bootverbose)
983		device_printf(dev, "Maestro DMA base: %#x\n", ess->baseaddr);
984
985	agg_power(ess, PPMI_D0);
986	DELAY(100000);
987
988	data = pci_read_config(dev, PCIR_COMMAND, 2);
989	data |= (PCIM_CMD_PORTEN|PCIM_CMD_BUSMASTEREN);
990	pci_write_config(dev, PCIR_COMMAND, data, 2);
991	data = pci_read_config(dev, PCIR_COMMAND, 2);
992
993	if (data & PCIM_CMD_PORTEN) {
994		reg = bus_alloc_resource(dev, SYS_RES_IOPORT, &regid,
995		    0, BUS_SPACE_UNRESTRICTED, 256, RF_ACTIVE);
996		if (reg != NULL) {
997			ess->reg = reg;
998			ess->regid = regid;
999			ess->st = rman_get_bustag(reg);
1000			ess->sh = rman_get_bushandle(reg);
1001			mapped++;
1002		}
1003	}
1004	if (mapped == 0) {
1005		device_printf(dev, "unable to map register space\n");
1006		goto bad;
1007	}
1008
1009	agg_init(ess);
1010	if (agg_rdcodec(NULL, ess, 0) == 0x80) {
1011		device_printf(dev, "PT101 codec detected!\n");
1012		goto bad;
1013	}
1014	codec = AC97_CREATE(dev, ess, agg_ac97);
1015	if (codec == NULL)
1016		goto bad;
1017	if (mixer_init(dev, ac97_getmixerclass(), codec) == -1)
1018		goto bad;
1019	ess->codec = codec;
1020
1021	irq = bus_alloc_resource(dev, SYS_RES_IRQ, &irqid,
1022	    0, BUS_SPACE_UNRESTRICTED, 1, RF_ACTIVE | RF_SHAREABLE);
1023	if (irq == NULL || snd_setup_intr(dev, irq, 0, agg_intr, ess, &ih)) {
1024		device_printf(dev, "unable to map interrupt\n");
1025		goto bad;
1026	}
1027	ess->irq = irq;
1028	ess->irqid = irqid;
1029	ess->ih = ih;
1030
1031	snprintf(status, SND_STATUSLEN, "at I/O port 0x%lx irq %ld",
1032	    rman_get_start(reg), rman_get_start(irq));
1033
1034	if (pcm_register(dev, ess, AGG_MAXPLAYCH, 1))
1035		goto bad;
1036
1037	mixer_hwvol_init(dev);
1038	for (data = 0; data < AGG_MAXPLAYCH; data++)
1039		pcm_addchan(dev, PCMDIR_PLAY, &aggch_class, ess);
1040#if 0	/* XXX - RECORDING */
1041	pcm_addchan(dev, PCMDIR_REC, &aggrch_class, ess);
1042#endif
1043	pcm_setstatus(dev, status);
1044
1045	return 0;
1046
1047 bad:
1048	if (codec != NULL)
1049		ac97_destroy(codec);
1050	if (ih != NULL)
1051		bus_teardown_intr(dev, irq, ih);
1052	if (irq != NULL)
1053		bus_release_resource(dev, SYS_RES_IRQ, irqid, irq);
1054	if (reg != NULL)
1055		bus_release_resource(dev, SYS_RES_IOPORT, regid, reg);
1056	if (ess != NULL) {
1057		agg_power(ess, PPMI_D3);
1058		if (ess->stat != NULL)
1059			dma_free(ess, ess->stat);
1060		if (ess->parent_dmat != NULL)
1061			bus_dma_tag_destroy(ess->parent_dmat);
1062		free(ess, M_DEVBUF);
1063	}
1064
1065	return ENXIO;
1066}
1067
1068static int
1069agg_detach(device_t dev)
1070{
1071	struct agg_info	*ess = pcm_getdevinfo(dev);
1072	int r;
1073
1074	r = pcm_unregister(dev);
1075	if (r)
1076		return r;
1077
1078	ess = pcm_getdevinfo(dev);
1079	dma_free(ess, ess->stat);
1080
1081	/* Power down everything except clock and vref. */
1082	agg_wrcodec(NULL, ess, AC97_REG_POWER, 0xd700);
1083	DELAY(20);
1084	bus_space_write_4(ess->st, ess->sh, PORT_RINGBUS_CTRL, 0);
1085	agg_power(ess, PPMI_D3);
1086
1087	bus_teardown_intr(dev, ess->irq, ess->ih);
1088	bus_release_resource(dev, SYS_RES_IRQ, ess->irqid, ess->irq);
1089	bus_release_resource(dev, SYS_RES_IOPORT, ess->regid, ess->reg);
1090	bus_dma_tag_destroy(ess->parent_dmat);
1091	free(ess, M_DEVBUF);
1092	return 0;
1093}
1094
1095static int
1096agg_suspend(device_t dev)
1097{
1098	struct agg_info *ess = pcm_getdevinfo(dev);
1099	int i, x;
1100
1101	x = spltty();
1102	wp_stoptimer(ess);
1103	bus_space_write_2(ess->st, ess->sh, PORT_HOSTINT_CTRL, 0);
1104
1105	for (i = 0; i < ess->playchns; i++)
1106		aggch_stop_dac(ess->pch + i);
1107
1108#if 0	/* XXX - RECORDING */
1109	aggch_stop_adc(&ess->rch);
1110#endif
1111	splx(x);
1112	/* Power down everything except clock. */
1113	agg_wrcodec(NULL, ess, AC97_REG_POWER, 0xdf00);
1114	DELAY(20);
1115	bus_space_write_4(ess->st, ess->sh, PORT_RINGBUS_CTRL, 0);
1116	DELAY(1);
1117	agg_power(ess, PPMI_D3);
1118
1119	return 0;
1120}
1121
1122static int
1123agg_resume(device_t dev)
1124{
1125	int i, x;
1126	struct agg_info *ess = pcm_getdevinfo(dev);
1127
1128	agg_power(ess, PPMI_D0);
1129	DELAY(100000);
1130	agg_init(ess);
1131	if (mixer_reinit(dev)) {
1132		device_printf(dev, "unable to reinitialize the mixer\n");
1133		return ENXIO;
1134	}
1135
1136	x = spltty();
1137	for (i = 0; i < ess->playchns; i++)
1138		if (ess->active & (1 << i))
1139			aggch_start_dac(ess->pch + i);
1140#if 0	/* XXX - RECORDING */
1141	if (ess->active & (1 << i))
1142		aggch_start_adc(&ess->rch);
1143#endif
1144	if (ess->active) {
1145		set_timer(ess);
1146		wp_starttimer(ess);
1147	}
1148	splx(x);
1149	return 0;
1150}
1151
1152static int
1153agg_shutdown(device_t dev)
1154{
1155	struct agg_info *ess = pcm_getdevinfo(dev);
1156	int i;
1157
1158	wp_stoptimer(ess);
1159	bus_space_write_2(ess->st, ess->sh, PORT_HOSTINT_CTRL, 0);
1160
1161	for (i = 0; i < ess->playchns; i++)
1162		aggch_stop_dac(ess->pch + i);
1163
1164#if 0	/* XXX - RECORDING */
1165	aggch_stop_adc(&ess->rch);
1166#endif
1167	return 0;
1168}
1169
1170
1171static device_method_t agg_methods[] = {
1172    DEVMETHOD(device_probe,	agg_probe),
1173    DEVMETHOD(device_attach,	agg_attach),
1174    DEVMETHOD(device_detach,	agg_detach),
1175    DEVMETHOD(device_suspend,	agg_suspend),
1176    DEVMETHOD(device_resume,	agg_resume),
1177    DEVMETHOD(device_shutdown,	agg_shutdown),
1178
1179    { 0, 0 }
1180};
1181
1182static driver_t agg_driver = {
1183    "pcm",
1184    agg_methods,
1185    sizeof(struct snddev_info),
1186};
1187
1188DRIVER_MODULE(snd_maestro, pci, agg_driver, pcm_devclass, 0, 0);
1189MODULE_DEPEND(snd_maestro, snd_pcm, PCM_MINVER, PCM_PREFVER, PCM_MAXVER);
1190MODULE_VERSION(snd_maestro, 1);
1191