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