xref: /openbsd/sys/dev/pci/maestro.c (revision 479c151d)
1 /*	$OpenBSD: maestro.c,v 1.56 2024/09/20 02:00:46 jsg Exp $	*/
2 /* $FreeBSD: /c/ncvs/src/sys/dev/sound/pci/maestro.c,v 1.3 2000/11/21 12:22:11 julian Exp $ */
3 /*
4  * FreeBSD's ESS Agogo/Maestro driver
5  * Converted from FreeBSD's pcm to OpenBSD's audio.
6  * Copyright (c) 2000, 2001 David Leonard & Marc Espie
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  */
30 /*-
31  * (FreeBSD) Credits:
32  * Copyright (c) 2000 Taku YAMAMOTO <taku@cent.saitama-u.ac.jp>
33  *
34  * Part of this code (especially in many magic numbers) was heavily inspired
35  * by the Linux driver originally written by
36  * Alan Cox <alan.cox@linux.org>, modified heavily by
37  * Zach Brown <zab@zabbo.net>.
38  *
39  * busdma()-ize and buffer size reduction were suggested by
40  * Cameron Grant <gandalf@vilnya.demon.co.uk>.
41  * Also he showed me the way to use busdma() suite.
42  *
43  * Internal speaker problems on NEC VersaPro's and Dell Inspiron 7500
44  * were looked at by
45  * Munehiro Matsuda <haro@tk.kubota.co.jp>,
46  * who brought patches based on the Linux driver with some simplification.
47  */
48 
49 #include <sys/param.h>
50 #include <sys/systm.h>
51 #include <sys/malloc.h>
52 #include <sys/device.h>
53 #include <sys/queue.h>
54 #include <sys/fcntl.h>
55 
56 #include <dev/pci/pcidevs.h>
57 #include <dev/pci/pcivar.h>
58 
59 #include <sys/audioio.h>
60 #include <dev/audio_if.h>
61 
62 #include <dev/ic/ac97.h>
63 
64 /* -----------------------------
65  * PCI config registers
66  */
67 
68 /* Legacy emulation */
69 #define CONF_LEGACY	0x40
70 
71 #define LEGACY_DISABLED	0x8000
72 
73 /* Chip configurations */
74 #define CONF_MAESTRO	0x50
75 #define MAESTRO_CHIBUS		0x00100000
76 #define MAESTRO_POSTEDWRITE	0x00000080
77 #define MAESTRO_DMA_PCITIMING	0x00000040
78 #define MAESTRO_SWAP_LR		0x00000010
79 
80 /* ACPI configurations */
81 #define CONF_ACPI_STOPCLOCK	0x54
82 #define ACPI_PART_2ndC_CLOCK	15
83 #define ACPI_PART_CODEC_CLOCK	14
84 #define ACPI_PART_978		13 /* Docking station or something */
85 #define ACPI_PART_SPDIF		12
86 #define ACPI_PART_GLUE		11 /* What? */
87 #define ACPI_PART_DAA		10
88 #define ACPI_PART_PCI_IF	9
89 #define ACPI_PART_HW_VOL	8
90 #define ACPI_PART_GPIO		7
91 #define ACPI_PART_ASSP		6
92 #define ACPI_PART_SB		5
93 #define ACPI_PART_FM		4
94 #define ACPI_PART_RINGBUS	3
95 #define ACPI_PART_MIDI		2
96 #define ACPI_PART_GAME_PORT	1
97 #define ACPI_PART_WP		0
98 
99 
100 /* -----------------------------
101  * I/O ports
102  */
103 
104 /* Direct Sound Processor (aka Wave Processor) */
105 #define PORT_DSP_DATA	0x00	/* WORD RW */
106 #define PORT_DSP_INDEX	0x02	/* WORD RW */
107 #define PORT_INT_STAT	0x04	/* WORD RW */
108 #define PORT_SAMPLE_CNT	0x06	/* WORD RO */
109 
110 /* WaveCache */
111 #define PORT_WAVCACHE_INDEX	0x10	/* WORD RW */
112 #define PORT_WAVCACHE_DATA	0x12	/* WORD RW */
113 #define WAVCACHE_PCMBAR		0x1fc
114 #define WAVCACHE_WTBAR		0x1f0
115 #define WAVCACHE_BASEADDR_SHIFT	12
116 
117 #define WAVCACHE_CHCTL_ADDRTAG_MASK	0xfff8
118 #define WAVCACHE_CHCTL_U8		0x0004
119 #define WAVCACHE_CHCTL_STEREO		0x0002
120 #define WAVCACHE_CHCTL_DECREMENTAL	0x0001
121 
122 #define PORT_WAVCACHE_CTRL	0x14	/* WORD RW */
123 #define WAVCACHE_EXTRA_CH_ENABLED	0x0200
124 #define WAVCACHE_ENABLED		0x0100
125 #define WAVCACHE_CH_60_ENABLED		0x0080
126 #define WAVCACHE_WTSIZE_MASK	0x0060
127 #define WAVCACHE_WTSIZE_1MB	0x0000
128 #define WAVCACHE_WTSIZE_2MB	0x0020
129 #define WAVCACHE_WTSIZE_4MB	0x0040
130 #define WAVCACHE_WTSIZE_8MB	0x0060
131 #define WAVCACHE_SGC_MASK		0x000c
132 #define WAVCACHE_SGC_DISABLED		0x0000
133 #define WAVCACHE_SGC_40_47		0x0004
134 #define WAVCACHE_SGC_32_47		0x0008
135 #define WAVCACHE_TESTMODE		0x0001
136 
137 /* Host Interruption */
138 #define PORT_HOSTINT_CTRL	0x18	/* WORD RW */
139 #define HOSTINT_CTRL_SOFT_RESET		0x8000
140 #define HOSTINT_CTRL_DSOUND_RESET	0x4000
141 #define HOSTINT_CTRL_HW_VOL_TO_PME	0x0400
142 #define HOSTINT_CTRL_CLKRUN_ENABLED	0x0100
143 #define HOSTINT_CTRL_HWVOL_ENABLED	0x0040
144 #define HOSTINT_CTRL_ASSP_INT_ENABLED	0x0010
145 #define HOSTINT_CTRL_ISDN_INT_ENABLED	0x0008
146 #define HOSTINT_CTRL_DSOUND_INT_ENABLED	0x0004
147 #define HOSTINT_CTRL_MPU401_INT_ENABLED	0x0002
148 #define HOSTINT_CTRL_SB_INT_ENABLED	0x0001
149 
150 #define PORT_HOSTINT_STAT	0x1a	/* BYTE RW */
151 #define HOSTINT_STAT_HWVOL	0x40
152 #define HOSTINT_STAT_ASSP	0x10
153 #define HOSTINT_STAT_ISDN	0x08
154 #define HOSTINT_STAT_DSOUND	0x04
155 #define HOSTINT_STAT_MPU401	0x02
156 #define HOSTINT_STAT_SB		0x01
157 
158 /* Hardware volume */
159 #define PORT_HWVOL_VOICE_SHADOW	0x1c	/* BYTE RW */
160 #define PORT_HWVOL_VOICE	0x1d	/* BYTE RW */
161 #define PORT_HWVOL_MASTER_SHADOW 0x1e	/* BYTE RW */
162 #define PORT_HWVOL_MASTER	0x1f	/* BYTE RW */
163 
164 /* CODEC */
165 #define	PORT_CODEC_CMD	0x30	/* BYTE W */
166 #define CODEC_CMD_READ	0x80
167 #define	CODEC_CMD_WRITE	0x00
168 #define	CODEC_CMD_ADDR_MASK	0x7f
169 
170 #define PORT_CODEC_STAT	0x30	/* BYTE R */
171 #define CODEC_STAT_MASK	0x01
172 #define CODEC_STAT_RW_DONE	0x00
173 #define CODEC_STAT_PROGLESS	0x01
174 
175 #define PORT_CODEC_REG	0x32	/* WORD RW */
176 
177 /* Ring bus control */
178 #define PORT_RINGBUS_CTRL	0x34	/* DWORD RW */
179 #define RINGBUS_CTRL_I2S_ENABLED	0x80000000
180 #define RINGBUS_CTRL_RINGBUS_ENABLED	0x20000000
181 #define RINGBUS_CTRL_ACLINK_ENABLED	0x10000000
182 #define RINGBUS_CTRL_AC97_SWRESET	0x08000000
183 #define RINGBUS_CTRL_IODMA_PLAYBACK_ENABLED	0x04000000
184 #define RINGBUS_CTRL_IODMA_RECORD_ENABLED	0x02000000
185 
186 #define RINGBUS_SRC_MIC		20
187 #define RINGBUS_SRC_I2S		16
188 #define RINGBUS_SRC_ADC		12
189 #define RINGBUS_SRC_MODEM	8
190 #define RINGBUS_SRC_DSOUND	4
191 #define RINGBUS_SRC_ASSP	0
192 
193 #define RINGBUS_DEST_MONORAL	000
194 #define RINGBUS_DEST_STEREO	010
195 #define RINGBUS_DEST_NONE	0
196 #define RINGBUS_DEST_DAC	1
197 #define RINGBUS_DEST_MODEM_IN	2
198 #define RINGBUS_DEST_RESERVED3	3
199 #define RINGBUS_DEST_DSOUND_IN	4
200 #define RINGBUS_DEST_ASSP_IN	5
201 
202 /* General Purpose I/O */
203 #define PORT_GPIO_DATA	0x60	/* WORD RW */
204 #define PORT_GPIO_MASK	0x64	/* WORD RW */
205 #define PORT_GPIO_DIR	0x68	/* WORD RW */
206 
207 /* Application Specific Signal Processor */
208 #define PORT_ASSP_MEM_INDEX	0x80	/* DWORD RW */
209 #define PORT_ASSP_MEM_DATA	0x84	/* WORD RW */
210 #define PORT_ASSP_CTRL_A	0xa2	/* BYTE RW */
211 #define PORT_ASSP_CTRL_B	0xa4	/* BYTE RW */
212 #define PORT_ASSP_CTRL_C	0xa6	/* BYTE RW */
213 #define PORT_ASSP_HOST_WR_INDEX	0xa8	/* BYTE W */
214 #define PORT_ASSP_HOST_WR_DATA	0xaa	/* BYTE RW */
215 #define PORT_ASSP_INT_STAT	0xac	/* BYTE RW */
216 
217 
218 /* -----------------------------
219  * Wave Processor Indexed Data Registers.
220  */
221 
222 #define WPREG_DATA_PORT		0
223 #define WPREG_CRAM_PTR		1
224 #define WPREG_CRAM_DATA		2
225 #define WPREG_WAVE_DATA		3
226 #define WPREG_WAVE_PTR_LOW	4
227 #define WPREG_WAVE_PTR_HIGH	5
228 
229 #define WPREG_TIMER_FREQ	6
230 #define WP_TIMER_FREQ_PRESCALE_MASK	0x00e0	/* actual - 9 */
231 #define WP_TIMER_FREQ_PRESCALE_SHIFT	5
232 #define WP_TIMER_FREQ_DIVIDE_MASK	0x001f
233 #define WP_TIMER_FREQ_DIVIDE_SHIFT	0
234 
235 #define WPREG_WAVE_ROMRAM	7
236 #define WP_WAVE_VIRTUAL_ENABLED	0x0400
237 #define WP_WAVE_8BITRAM_ENABLED	0x0200
238 #define WP_WAVE_DRAM_ENABLED	0x0100
239 #define WP_WAVE_RAMSPLIT_MASK	0x00ff
240 #define WP_WAVE_RAMSPLIT_SHIFT	0
241 
242 #define WPREG_BASE		12
243 #define WP_PARAOUT_BASE_MASK	0xf000
244 #define WP_PARAOUT_BASE_SHIFT	12
245 #define WP_PARAIN_BASE_MASK	0x0f00
246 #define WP_PARAIN_BASE_SHIFT	8
247 #define WP_SERIAL0_BASE_MASK	0x00f0
248 #define WP_SERIAL0_BASE_SHIFT	4
249 #define WP_SERIAL1_BASE_MASK	0x000f
250 #define WP_SERIAL1_BASE_SHIFT	0
251 
252 #define WPREG_TIMER_ENABLE	17
253 #define WPREG_TIMER_START	23
254 
255 
256 /* -----------------------------
257  * Audio Processing Unit.
258  */
259 #define APUREG_APUTYPE	0
260 #define APU_DMA_ENABLED	0x4000
261 #define APU_INT_ON_LOOP	0x2000
262 #define APU_ENDCURVE	0x1000
263 #define APU_APUTYPE_MASK	0x00f0
264 #define APU_FILTERTYPE_MASK	0x000c
265 #define APU_FILTERQ_MASK	0x0003
266 
267 /* APU types */
268 #define APU_APUTYPE_SHIFT	4
269 
270 #define APUTYPE_INACTIVE	0
271 #define APUTYPE_16BITLINEAR	1
272 #define APUTYPE_16BITSTEREO	2
273 #define APUTYPE_8BITLINEAR	3
274 #define APUTYPE_8BITSTEREO	4
275 #define APUTYPE_8BITDIFF	5
276 #define APUTYPE_DIGITALDELAY	6
277 #define APUTYPE_DUALTAP_READER	7
278 #define APUTYPE_CORRELATOR	8
279 #define APUTYPE_INPUTMIXER	9
280 #define APUTYPE_WAVETABLE	10
281 #define APUTYPE_RATECONV	11
282 #define APUTYPE_16BITPINGPONG	12
283 /* APU type 13 through 15 are reserved. */
284 
285 /* Filter types */
286 #define APU_FILTERTYPE_SHIFT	2
287 
288 #define FILTERTYPE_2POLE_LOPASS		0
289 #define FILTERTYPE_2POLE_BANDPASS	1
290 #define FILTERTYPE_2POLE_HIPASS		2
291 #define FILTERTYPE_1POLE_LOPASS		3
292 #define FILTERTYPE_1POLE_HIPASS		4
293 #define FILTERTYPE_PASSTHROUGH		5
294 
295 /* Filter Q */
296 #define APU_FILTERQ_SHIFT	0
297 
298 #define FILTERQ_LESSQ	0
299 #define FILTERQ_MOREQ	3
300 
301 /* APU register 2 */
302 #define APUREG_FREQ_LOBYTE	2
303 #define APU_FREQ_LOBYTE_MASK	0xff00
304 #define APU_plus6dB		0x0010
305 
306 /* APU register 3 */
307 #define APUREG_FREQ_HIWORD	3
308 #define APU_FREQ_HIWORD_MASK	0x0fff
309 
310 /* Frequency */
311 #define APU_FREQ_LOBYTE_SHIFT	8
312 #define APU_FREQ_HIWORD_SHIFT	0
313 #define FREQ_Hz2DIV(freq)	(((u_int64_t)(freq) << 16) / 48000)
314 
315 /* APU register 4 */
316 #define APUREG_WAVESPACE	4
317 #define APU_STEREO		0x8000
318 #define APU_USE_SYSMEM		0x4000
319 #define APU_PCMBAR_MASK		0x6000
320 #define APU_64KPAGE_MASK	0xff00
321 
322 /* PCM Base Address Register selection */
323 #define APU_PCMBAR_SHIFT	13
324 
325 /* 64KW (==128KB) Page */
326 #define APU_64KPAGE_SHIFT	8
327 
328 /* APU register 5 - 7 */
329 #define APUREG_CURPTR	5
330 #define APUREG_ENDPTR	6
331 #define APUREG_LOOPLEN	7
332 
333 /* APU register 9 */
334 #define APUREG_AMPLITUDE	9
335 #define APU_AMPLITUDE_NOW_MASK	0xff00
336 #define APU_AMPLITUDE_DEST_MASK	0x00ff
337 
338 /* Amplitude now? */
339 #define APU_AMPLITUDE_NOW_SHIFT	8
340 
341 /* APU register 10 */
342 #define APUREG_POSITION	10
343 #define APU_RADIUS_MASK	0x00c0
344 #define APU_PAN_MASK	0x003f
345 
346 /* Radius control. */
347 #define APU_RADIUS_SHIFT	6
348 #define RADIUS_CENTERCIRCLE	0
349 #define RADIUS_MIDDLE		1
350 #define RADIUS_OUTSIDE		2
351 
352 /* Polar pan. */
353 #define APU_PAN_SHIFT	0
354 #define PAN_RIGHT	0x00
355 #define PAN_FRONT	0x08
356 #define PAN_LEFT	0x10
357 
358 
359 /* -----------------------------
360  * Limits.
361  */
362 #define WPWA_MAX	((1 << 22) - 1)
363 #define WPWA_MAXADDR	((1 << 23) - 1)
364 #define MAESTRO_MAXADDR	((1 << 28) - 1)
365 
366 
367 
368 #ifdef AUDIO_DEBUG
369 #define DPRINTF(x)	if (maestrodebug) printf x
370 #define DLPRINTF(i, x)	if (maestrodebug & i) printf x
371 int	maestrodebug = 0;
372 u_long maestrointr_called;
373 u_long maestrodma_effective;
374 
375 #define MAESTRODEBUG_INTR 1
376 #define MAESTRODEBUG_TIMER 2
377 #else
378 #define DPRINTF(x)
379 #define DLPRINTF(i, x)
380 #endif
381 
382 #define MAESTRO_BUFSIZ		0x4000
383 #define lengthof(array)		(sizeof (array) / sizeof (array)[0])
384 
385 #define STEP_VOLUME		0x22
386 #define MIDDLE_VOLUME		(STEP_VOLUME * 4)
387 
388 typedef struct salloc_pool {
389 	struct salloc_zone {
390 		SLIST_ENTRY(salloc_zone) link;
391 		caddr_t		addr;
392 		size_t		size;
393 	} *zones;
394 	SLIST_HEAD(salloc_head, salloc_zone) free, used, spare;
395 } *salloc_t;
396 
397 struct maestro_softc;
398 
399 #define MAESTRO_PLAY	1
400 #define MAESTRO_STEREO	2
401 #define MAESTRO_8BIT	4
402 #define MAESTRO_UNSIGNED	8
403 #define MAESTRO_RUNNING	16
404 
405 struct maestro_channel {
406 	struct maestro_softc 	*sc;
407 	int			num;
408 	u_int32_t		blocksize;
409 	u_int16_t		mode;
410 	u_int32_t		speed;
411 	u_int32_t		dv;
412 	u_int16_t		start;
413 	u_int16_t		threshold;
414 	u_int16_t		end;
415 	u_int16_t		current;
416 	u_int			wpwa;
417 	void			(*intr)(void *);
418 	void			*intr_arg;
419 };
420 
421 struct maestro_softc {
422 	struct device		dev;
423 
424 	void			*ih;
425 	pci_chipset_tag_t	pc;
426 	pcitag_t		pt;
427 
428 #define MAESTRO_FLAG_SETUPGPIO	0x0001
429 	int			flags;
430 	bus_space_tag_t		iot;
431 	bus_space_handle_t	ioh;
432 	bus_dma_tag_t		dmat;
433 
434 	caddr_t			dmabase;
435 	bus_addr_t		physaddr;
436 	size_t			dmasize;
437 	bus_dmamap_t		dmamap;
438 	bus_dma_segment_t	dmaseg;
439 	salloc_t		dmapool;
440 
441 	struct ac97_codec_if	*codec_if;
442 	struct ac97_host_if	host_if;
443 
444 	int			suspend;
445 
446 	struct maestro_channel	play;
447 	struct maestro_channel	record;
448 };
449 
450 
451 typedef	u_int16_t wpreg_t;
452 typedef	u_int16_t wcreg_t;
453 
454 salloc_t salloc_new(caddr_t, size_t, int);
455 void	salloc_destroy(salloc_t);
456 caddr_t	salloc_alloc(salloc_t, size_t);
457 void	salloc_free(salloc_t, caddr_t);
458 void	salloc_insert(salloc_t, struct salloc_head *,
459 		struct salloc_zone *, int);
460 
461 int	maestro_match(struct device *, void *, void *);
462 void	maestro_attach(struct device *, struct device *, void *);
463 int	maestro_activate(struct device *, int);
464 int	maestro_intr(void *);
465 
466 int	maestro_open(void *, int);
467 void	maestro_close(void *);
468 int	maestro_set_params(void *, int, int, struct audio_params *,
469 			    struct audio_params *);
470 int	maestro_round_blocksize(void *, int);
471 int	maestro_halt_output(void *);
472 int	maestro_halt_input(void *);
473 int	maestro_set_port(void *, mixer_ctrl_t *);
474 int	maestro_get_port(void *, mixer_ctrl_t *);
475 int	maestro_query_devinfo(void *, mixer_devinfo_t *);
476 void	*maestro_malloc(void *, int, size_t, int, int);
477 void	maestro_free(void *, void *, int);
478 int	maestro_trigger_output(void *, void *, void *, int, void (*)(void *),
479 				void *, struct audio_params *);
480 int	maestro_trigger_input(void *, void *, void *, int, void (*)(void *),
481 			       void *, struct audio_params *);
482 
483 int	maestro_attach_codec(void *, struct ac97_codec_if *);
484 enum ac97_host_flags maestro_codec_flags(void *);
485 int	maestro_read_codec(void *, u_int8_t, u_int16_t *);
486 int	maestro_write_codec(void *, u_int8_t, u_int16_t);
487 void	maestro_reset_codec(void *);
488 
489 void	maestro_initcodec(void *);
490 
491 void	maestro_set_speed(struct maestro_channel *, u_long *);
492 void	maestro_init(struct maestro_softc *);
493 
494 void 	maestro_channel_start(struct maestro_channel *);
495 void 	maestro_channel_stop(struct maestro_channel *);
496 void 	maestro_channel_advance_dma(struct maestro_channel *);
497 void	maestro_channel_suppress_jitter(struct maestro_channel *);
498 
499 int	maestro_get_flags(struct pci_attach_args *);
500 
501 void	ringbus_setdest(struct maestro_softc *, int, int);
502 
503 wpreg_t	wp_reg_read(struct maestro_softc *, int);
504 void	wp_reg_write(struct maestro_softc *, int, wpreg_t);
505 wpreg_t	wp_apu_read(struct maestro_softc *, int, int);
506 void	wp_apu_write(struct maestro_softc *, int, int, wpreg_t);
507 void	wp_settimer(struct maestro_softc *, u_int);
508 void	wp_starttimer(struct maestro_softc *);
509 void	wp_stoptimer(struct maestro_softc *);
510 
511 wcreg_t	wc_reg_read(struct maestro_softc *, int);
512 void	wc_reg_write(struct maestro_softc *, int, wcreg_t);
513 wcreg_t	wc_ctrl_read(struct maestro_softc *, int);
514 void	wc_ctrl_write(struct maestro_softc *, int, wcreg_t);
515 
516 u_int maestro_calc_timer_freq(struct maestro_channel *);
517 void maestro_update_timer(struct maestro_softc *);
518 
519 struct cfdriver maestro_cd = {
520 	NULL, "maestro", DV_DULL
521 };
522 
523 const struct cfattach maestro_ca = {
524 	sizeof (struct maestro_softc), maestro_match, maestro_attach,
525 	NULL, maestro_activate
526 };
527 
528 const struct audio_hw_if maestro_hw_if = {
529 	.open = maestro_open,
530 	.close = maestro_close,
531 	.set_params = maestro_set_params,
532 	.round_blocksize = maestro_round_blocksize,
533 	.halt_output = maestro_halt_output,
534 	.halt_input = maestro_halt_input,
535 	.set_port = maestro_set_port,
536 	.get_port = maestro_get_port,
537 	.query_devinfo = maestro_query_devinfo,
538 	.allocm = maestro_malloc,
539 	.freem = maestro_free,
540 	.trigger_output = maestro_trigger_output,
541 	.trigger_input = maestro_trigger_input,
542 };
543 
544 const struct {
545 	u_short vendor, product;
546 	int flags;
547 } maestro_pcitab[] = {
548 	{ PCI_VENDOR_ESSTECH, PCI_PRODUCT_ESSTECH_MAESTROII,	0 },
549 	{ PCI_VENDOR_ESSTECH, PCI_PRODUCT_ESSTECH_MAESTRO2E,	0 },
550 	{ PCI_VENDOR_PLATFORM, PCI_PRODUCT_PLATFORM_ES1849,	0 },
551 	{ PCI_VENDOR_NEC, PCI_PRODUCT_NEC_VERSAMAESTRO,		MAESTRO_FLAG_SETUPGPIO },
552 	{ PCI_VENDOR_NEC, PCI_PRODUCT_NEC_VERSAPRONXVA26D,	MAESTRO_FLAG_SETUPGPIO }
553 };
554 #define NMAESTRO_PCITAB	lengthof(maestro_pcitab)
555 
556 int
maestro_get_flags(struct pci_attach_args * pa)557 maestro_get_flags(struct pci_attach_args *pa)
558 {
559 	int i;
560 
561 	/* Distinguish audio devices from modems with the same manfid */
562 	if (PCI_CLASS(pa->pa_class) != PCI_CLASS_MULTIMEDIA)
563 		return (-1);
564 	if (PCI_SUBCLASS(pa->pa_class) != PCI_SUBCLASS_MULTIMEDIA_AUDIO)
565 		return (-1);
566 	for (i = 0; i < NMAESTRO_PCITAB; i++)
567 		if (PCI_VENDOR(pa->pa_id) == maestro_pcitab[i].vendor &&
568 		    PCI_PRODUCT(pa->pa_id) == maestro_pcitab[i].product)
569 			return (maestro_pcitab[i].flags);
570 	return (-1);
571 }
572 
573 /* -----------------------------
574  * Driver interface.
575  */
576 
577 int
maestro_match(struct device * parent,void * match,void * aux)578 maestro_match(struct device *parent, void *match, void *aux)
579 {
580 	struct pci_attach_args *pa = (struct pci_attach_args *)aux;
581 
582 	if (maestro_get_flags(pa) == -1)
583 		return (0);
584 	else
585 		return (1);
586 }
587 
588 void
maestro_attach(struct device * parent,struct device * self,void * aux)589 maestro_attach(struct device *parent, struct device *self, void *aux)
590 {
591 	struct maestro_softc *sc = (struct maestro_softc *)self;
592 	struct pci_attach_args *pa = (struct pci_attach_args *)aux;
593 	pci_chipset_tag_t pc = pa->pa_pc;
594 	char const *intrstr;
595 	pci_intr_handle_t ih;
596 	int error;
597 	u_int16_t cdata;
598 	int dmastage = 0;
599 	int rseg;
600 
601 	sc->flags = maestro_get_flags(pa);
602 
603 	sc->pc = pa->pa_pc;
604 	sc->pt = pa->pa_tag;
605 	sc->dmat = pa->pa_dmat;
606 
607 	/* Map interrupt */
608 	if (pci_intr_map(pa, &ih)) {
609 		printf(": can't map interrupt\n");
610 		return;
611 	}
612 	intrstr = pci_intr_string(pc, ih);
613 	sc->ih = pci_intr_establish(pc, ih, IPL_AUDIO | IPL_MPSAFE,
614 	    maestro_intr, sc, sc->dev.dv_xname);
615 	if (sc->ih == NULL) {
616 		printf(": can't establish interrupt");
617 		if (intrstr != NULL)
618 			printf(" at %s\n", intrstr);
619 		return;
620 	}
621 	printf(": %s", intrstr);
622 
623 	pci_set_powerstate(pc, sc->pt, PCI_PMCSR_STATE_D0);
624 
625 	/* Map i/o */
626 	if ((error = pci_mapreg_map(pa, PCI_MAPS, PCI_MAPREG_TYPE_IO,
627 	    0, &sc->iot, &sc->ioh, NULL, NULL, 0)) != 0) {
628 		printf(", can't map i/o space\n");
629 		goto bad;
630 	}
631 
632 	/* Allocate fixed DMA segment :-( */
633 	sc->dmasize = MAESTRO_BUFSIZ * 16;
634 	if ((error = bus_dmamem_alloc(sc->dmat, sc->dmasize, NBPG, 0,
635 	    &sc->dmaseg, 1, &rseg, BUS_DMA_NOWAIT)) != 0) {
636 		printf(", unable to alloc dma, error %d\n", error);
637 		goto bad;
638 	}
639 	dmastage = 1;
640 	if ((error = bus_dmamem_map(sc->dmat, &sc->dmaseg, 1,
641 	    sc->dmasize, &sc->dmabase, BUS_DMA_NOWAIT |
642 	    BUS_DMA_COHERENT)) != 0) {
643 		printf(", unable to map dma, error %d\n", error);
644 		goto bad;
645 	}
646 	dmastage = 2;
647 	if ((error = bus_dmamap_create(sc->dmat, sc->dmasize, 1,
648 	    sc->dmasize, 0, BUS_DMA_NOWAIT, &sc->dmamap)) != 0) {
649 		printf(", unable to create dma map, error %d\n", error);
650 		goto bad;
651 	}
652 	dmastage = 3;
653 	if ((error = bus_dmamap_load(sc->dmat, sc->dmamap,
654 	    sc->dmabase, sc->dmasize, NULL, BUS_DMA_NOWAIT)) != 0) {
655 		printf(", unable to load dma map, error %d\n", error);
656 		goto bad;
657 	}
658 
659 	/* XXX
660 	 * The first byte of the allocated memory is not usable,
661 	 * the WP sometimes uses it to store status.
662 	 */
663 	/* Make DMA memory pool */
664 	if ((sc->dmapool = salloc_new(sc->dmabase+16, sc->dmasize-16,
665 	    128/*overkill?*/)) == NULL) {
666 		printf(", unable to make dma pool\n");
667 		goto bad;
668 	}
669 
670 	sc->physaddr = sc->dmamap->dm_segs[0].ds_addr;
671 
672 	printf("\n");
673 
674 	/* Kick device */
675 	maestro_init(sc);
676 	maestro_read_codec(sc, 0, &cdata);
677 	if (cdata == 0x80) {
678 		printf("%s: PT101 codec unsupported, no mixer\n",
679 		    sc->dev.dv_xname);
680 		/* Init values from Linux, no idea what this does. */
681 		maestro_write_codec(sc, 0x2a, 0x0001);
682 		maestro_write_codec(sc, 0x2C, 0x0000);
683 		maestro_write_codec(sc, 0x2C, 0xFFFF);
684 		maestro_write_codec(sc, 0x10, 0x9F1F);
685 		maestro_write_codec(sc, 0x12, 0x0808);
686 		maestro_write_codec(sc, 0x14, 0x9F1F);
687 		maestro_write_codec(sc, 0x16, 0x9F1F);
688 		maestro_write_codec(sc, 0x18, 0x0404);
689 		maestro_write_codec(sc, 0x1A, 0x0000);
690 		maestro_write_codec(sc, 0x1C, 0x0000);
691 		maestro_write_codec(sc, 0x02, 0x0404);
692 		maestro_write_codec(sc, 0x04, 0x0808);
693 		maestro_write_codec(sc, 0x0C, 0x801F);
694 		maestro_write_codec(sc, 0x0E, 0x801F);
695 		/* no control over the mixer, sorry */
696 		sc->codec_if = NULL;
697 	} else {
698 		/* Attach the AC'97 */
699 		sc->host_if.arg = sc;
700 		sc->host_if.attach = maestro_attach_codec;
701 		sc->host_if.flags = maestro_codec_flags;
702 		sc->host_if.read = maestro_read_codec;
703 		sc->host_if.write = maestro_write_codec;
704 		sc->host_if.reset = maestro_reset_codec;
705 		if (ac97_attach(&sc->host_if) != 0) {
706 			printf("%s: can't attach codec\n", sc->dev.dv_xname);
707 			goto bad;
708 		}
709 	}
710 
711 	sc->play.mode = MAESTRO_PLAY;
712 	sc->play.sc = sc;
713 	sc->play.num = 0;
714 	sc->record.sc = sc;
715 	sc->record.num = 2;
716 	sc->record.mode = 0;
717 
718 	/* Attach audio */
719 	audio_attach_mi(&maestro_hw_if, sc, NULL, &sc->dev);
720 	return;
721 
722  bad:
723 	if (sc->ih)
724 		pci_intr_disestablish(pc, sc->ih);
725 	printf("%s: disabled\n", sc->dev.dv_xname);
726 	if (sc->dmapool)
727 		salloc_destroy(sc->dmapool);
728 	if (dmastage >= 3)
729 		bus_dmamap_destroy(sc->dmat, sc->dmamap);
730 	if (dmastage >= 2)
731 		bus_dmamem_unmap(sc->dmat, sc->dmabase, sc->dmasize);
732 	if (dmastage >= 1)
733 		bus_dmamem_free(sc->dmat, &sc->dmaseg, 1);
734 }
735 
736 void
maestro_init(struct maestro_softc * sc)737 maestro_init(struct maestro_softc *sc)
738 {
739 	int reg;
740 	pcireg_t data;
741 
742 	/* Disable all legacy emulations. */
743 	data = pci_conf_read(sc->pc, sc->pt, CONF_LEGACY);
744 	data |= LEGACY_DISABLED;
745 	pci_conf_write(sc->pc, sc->pt, CONF_LEGACY, data);
746 
747 	/* Disconnect from CHI. (Makes Dell inspiron 7500 work?)
748 	 * Enable posted write.
749 	 * Prefer PCI timing rather than that of ISA.
750 	 * Don't swap L/R. */
751 	data = pci_conf_read(sc->pc, sc->pt, CONF_MAESTRO);
752 	data |= MAESTRO_CHIBUS | MAESTRO_POSTEDWRITE | MAESTRO_DMA_PCITIMING;
753 	data &= ~MAESTRO_SWAP_LR;
754 	pci_conf_write(sc->pc, sc->pt, CONF_MAESTRO, data);
755 	/* Reset direct sound. */
756 	bus_space_write_2(sc->iot, sc->ioh, PORT_HOSTINT_CTRL,
757 	    HOSTINT_CTRL_DSOUND_RESET);
758 	DELAY(10000);	/* XXX - too long? */
759 	bus_space_write_2(sc->iot, sc->ioh, PORT_HOSTINT_CTRL, 0);
760 	DELAY(10000);
761 
762 	/* Enable direct sound and hardware volume control interruptions. */
763 	bus_space_write_2(sc->iot, sc->ioh, PORT_HOSTINT_CTRL,
764 	    HOSTINT_CTRL_DSOUND_INT_ENABLED | HOSTINT_CTRL_HWVOL_ENABLED);
765 
766 	/* Setup Wave Processor. */
767 
768 	/* Enable WaveCache, set DMA base address. */
769 	wp_reg_write(sc, WPREG_WAVE_ROMRAM,
770 	    WP_WAVE_VIRTUAL_ENABLED | WP_WAVE_DRAM_ENABLED);
771 	bus_space_write_2(sc->iot, sc->ioh, PORT_WAVCACHE_CTRL,
772 	    WAVCACHE_ENABLED | WAVCACHE_WTSIZE_4MB);
773 
774 	for (reg = WAVCACHE_PCMBAR; reg < WAVCACHE_PCMBAR + 4; reg++)
775 		wc_reg_write(sc, reg,
776 			sc->physaddr >> WAVCACHE_BASEADDR_SHIFT);
777 
778 	/* Setup Codec/Ringbus. */
779 	maestro_initcodec(sc);
780 	bus_space_write_4(sc->iot, sc->ioh, PORT_RINGBUS_CTRL,
781 	    RINGBUS_CTRL_RINGBUS_ENABLED | RINGBUS_CTRL_ACLINK_ENABLED);
782 
783 	wp_reg_write(sc, WPREG_BASE, 0x8500);	/* Parallel I/O */
784 	ringbus_setdest(sc, RINGBUS_SRC_ADC,
785 	    RINGBUS_DEST_STEREO | RINGBUS_DEST_DSOUND_IN);
786 	ringbus_setdest(sc, RINGBUS_SRC_DSOUND,
787 	    RINGBUS_DEST_STEREO | RINGBUS_DEST_DAC);
788 
789 	/* Setup ASSP. Needed for Dell Inspiron 7500? */
790 	bus_space_write_1(sc->iot, sc->ioh, PORT_ASSP_CTRL_B, 0x00);
791 	bus_space_write_1(sc->iot, sc->ioh, PORT_ASSP_CTRL_A, 0x03);
792 	bus_space_write_1(sc->iot, sc->ioh, PORT_ASSP_CTRL_C, 0x00);
793 
794 	/*
795 	 * Reset hw volume to a known value so that we may handle diffs
796 	 * off to AC'97.
797 	 */
798 
799 	bus_space_write_1(sc->iot, sc->ioh, PORT_HWVOL_MASTER, MIDDLE_VOLUME);
800 	/* Setup GPIO if needed (NEC systems) */
801 	if (sc->flags & MAESTRO_FLAG_SETUPGPIO) {
802 		/* Matthew Braithwaite <matt@braithwaite.net> reported that
803 		 * NEC Versa LX doesn't need GPIO operation. */
804 		bus_space_write_2(sc->iot, sc->ioh,
805 		    PORT_GPIO_MASK, 0x9ff);
806 		bus_space_write_2(sc->iot, sc->ioh, PORT_GPIO_DIR,
807 		    bus_space_read_2(sc->iot, sc->ioh, PORT_GPIO_DIR) | 0x600);
808 		bus_space_write_2(sc->iot, sc->ioh,
809 		    PORT_GPIO_DATA, 0x200);
810 	}
811 }
812 
813 /* -----------------------------
814  * Audio interface
815  */
816 
817 int
maestro_round_blocksize(void * self,int blk)818 maestro_round_blocksize(void *self, int blk)
819 {
820 	return ((blk + 0xf) & ~0xf);
821 }
822 
823 void *
maestro_malloc(void * arg,int dir,size_t size,int pool,int flags)824 maestro_malloc(void *arg, int dir, size_t size, int pool, int flags)
825 {
826 	struct maestro_softc *sc = (struct maestro_softc *)arg;
827 
828 	return (salloc_alloc(sc->dmapool, size));
829 }
830 
831 void
maestro_free(void * self,void * ptr,int pool)832 maestro_free(void *self, void *ptr, int pool)
833 {
834 	struct maestro_softc *sc = (struct maestro_softc *)self;
835 
836 	salloc_free(sc->dmapool, ptr);
837 }
838 
839 int
maestro_set_port(void * self,mixer_ctrl_t * cp)840 maestro_set_port(void *self, mixer_ctrl_t *cp)
841 {
842 	struct ac97_codec_if *c = ((struct maestro_softc *)self)->codec_if;
843 	int rc;
844 
845 	if (c) {
846 		/* interrupts use the mixer */
847 		mtx_enter(&audio_lock);
848 		rc = c->vtbl->mixer_set_port(c, cp);
849 		mtx_leave(&audio_lock);
850 		return rc;
851 	} else
852 		return (ENXIO);
853 }
854 
855 int
maestro_get_port(void * self,mixer_ctrl_t * cp)856 maestro_get_port(void *self, mixer_ctrl_t *cp)
857 {
858 	struct ac97_codec_if *c = ((struct maestro_softc *)self)->codec_if;
859 	int rc;
860 
861 	if (c) {
862 		/* interrupts use the mixer */
863 		mtx_enter(&audio_lock);
864 		rc = c->vtbl->mixer_get_port(c, cp);
865 		mtx_leave(&audio_lock);
866 		return rc;
867 	} else
868 		return (ENXIO);
869 }
870 
871 int
maestro_query_devinfo(void * self,mixer_devinfo_t * cp)872 maestro_query_devinfo(void *self, mixer_devinfo_t *cp)
873 {
874 	struct ac97_codec_if *c = ((struct maestro_softc *)self)->codec_if;
875 	int rc;
876 
877 	if (c)  {
878 		/* interrupts use the mixer */
879 		mtx_enter(&audio_lock);
880 		rc = c->vtbl->query_devinfo(c, cp);
881 		mtx_leave(&audio_lock);
882 		return rc;
883 	} else
884 		return (ENXIO);
885 }
886 
887 #define UNUSED __attribute__((unused))
888 
889 void
maestro_set_speed(struct maestro_channel * ch,u_long * prate)890 maestro_set_speed(struct maestro_channel *ch, u_long *prate)
891 {
892 	ch->speed = *prate;
893 	if ((ch->mode & (MAESTRO_8BIT | MAESTRO_STEREO)) == MAESTRO_8BIT)
894 		ch->speed /= 2;
895 
896 	/* special common case */
897 	if (ch->speed == 48000) {
898 		ch->dv = 0x10000;
899 	} else {
900 		/* compute 16 bits fixed point value of speed/48000,
901 		 * being careful not to overflow */
902 		ch->dv = (((ch->speed % 48000) << 16U) + 24000) / 48000
903 		    + ((ch->speed / 48000) << 16U);
904 		/* And this is the real rate obtained */
905 		ch->speed = (ch->dv >> 16U) * 48000 +
906 		    (((ch->dv & 0xffff)*48000)>>16U);
907 	}
908 	*prate = ch->speed;
909 	if ((ch->mode & (MAESTRO_8BIT | MAESTRO_STEREO)) == MAESTRO_8BIT)
910 		*prate *= 2;
911 }
912 
913 u_int
maestro_calc_timer_freq(struct maestro_channel * ch)914 maestro_calc_timer_freq(struct maestro_channel *ch)
915 {
916 	u_int	ss = 2;
917 
918 	if (ch->mode & MAESTRO_8BIT)
919 		ss = 1;
920 	return (ch->speed * ss) / ch->blocksize;
921 }
922 
923 void
maestro_update_timer(struct maestro_softc * sc)924 maestro_update_timer(struct maestro_softc *sc)
925 {
926 	u_int freq = 0;
927 	u_int n;
928 
929 	if (sc->play.mode & MAESTRO_RUNNING)
930 		freq = maestro_calc_timer_freq(&sc->play);
931 	if (sc->record.mode & MAESTRO_RUNNING) {
932 		n = maestro_calc_timer_freq(&sc->record);
933 		if (freq < n)
934 			freq = n;
935 	}
936 	if (freq) {
937 		wp_settimer(sc, freq);
938 		wp_starttimer(sc);
939     	} else
940 		wp_stoptimer(sc);
941 }
942 
943 
944 int
maestro_set_params(void * hdl,int setmode,int usemode,struct audio_params * play,struct audio_params * rec)945 maestro_set_params(void *hdl, int setmode, int usemode,
946     struct audio_params *play, struct audio_params *rec)
947 {
948 	struct maestro_softc *sc = (struct maestro_softc *)hdl;
949 
950 	if ((setmode & AUMODE_PLAY) == 0)
951 		return (0);
952 
953 	/* Disallow parameter change on a running audio for now */
954 	if (sc->play.mode & MAESTRO_RUNNING)
955 		return (EINVAL);
956 
957 	if (play->sample_rate < 4000)
958 		play->sample_rate = 4000;
959 	else if (play->sample_rate > 48000)
960 		play->sample_rate = 48000;
961 
962 	if (play->channels > 2)
963 		play->channels = 2;
964 
965 	sc->play.mode = MAESTRO_PLAY;
966 	if (play->channels == 2)
967 		sc->play.mode |= MAESTRO_STEREO;
968 
969 	if (play->precision == 8) {
970 		sc->play.mode |= MAESTRO_8BIT;
971 		if (play->encoding == AUDIO_ENCODING_ULINEAR_LE ||
972 		    play->encoding == AUDIO_ENCODING_ULINEAR_BE)
973 		    sc->play.mode |= MAESTRO_UNSIGNED;
974 	}
975 	else if (play->encoding != AUDIO_ENCODING_SLINEAR_LE)
976 		return (EINVAL);
977 
978 	play->bps = AUDIO_BPS(play->precision);
979 	play->msb = 1;
980 
981 	maestro_set_speed(&sc->play, &play->sample_rate);
982 	return (0);
983 }
984 
985 int
maestro_open(void * hdl,int flags)986 maestro_open(void *hdl, int flags)
987 {
988 	struct maestro_softc *sc = (struct maestro_softc *)hdl;
989 	DPRINTF(("%s: open(%d)\n", sc->dev.dv_xname, flags));
990 
991 	if ((flags & (FWRITE | FREAD)) == (FWRITE | FREAD))
992 		return ENXIO;	/* XXX */
993 
994 /* XXX work around VM brokenness */
995 #if 0
996 	if ((OFLAGS(flags) & O_ACCMODE) != O_WRONLY)
997 		return (EINVAL);
998 #endif
999 	sc->play.mode = MAESTRO_PLAY;
1000 	sc->record.mode = 0;
1001 #ifdef AUDIO_DEBUG
1002 	maestrointr_called = 0;
1003 	maestrodma_effective = 0;
1004 #endif
1005 	return (0);
1006 }
1007 
1008 void
maestro_close(void * hdl)1009 maestro_close(void *hdl)
1010 {
1011 	struct maestro_softc *sc UNUSED = (struct maestro_softc *)hdl;
1012 	/* nothing to do */
1013 }
1014 
1015 
1016 void
maestro_channel_stop(struct maestro_channel * ch)1017 maestro_channel_stop(struct maestro_channel *ch)
1018 {
1019 	wp_apu_write(ch->sc, ch->num, APUREG_APUTYPE,
1020 	    APUTYPE_INACTIVE << APU_APUTYPE_SHIFT);
1021 	if (ch->mode & MAESTRO_STEREO)
1022 	    wp_apu_write(ch->sc, ch->num+1, APUREG_APUTYPE,
1023 		APUTYPE_INACTIVE << APU_APUTYPE_SHIFT);
1024 	/* four channels for record... */
1025 	if (ch->mode & MAESTRO_PLAY)
1026 		return;
1027 	wp_apu_write(ch->sc, ch->num+2, APUREG_APUTYPE,
1028 	    APUTYPE_INACTIVE << APU_APUTYPE_SHIFT);
1029 	if (ch->mode & MAESTRO_STEREO)
1030 	    wp_apu_write(ch->sc, ch->num+3, APUREG_APUTYPE,
1031 		APUTYPE_INACTIVE << APU_APUTYPE_SHIFT);
1032 
1033 }
1034 
1035 int
maestro_halt_input(void * hdl)1036 maestro_halt_input(void *hdl)
1037 {
1038 	struct maestro_softc *sc = (struct maestro_softc *)hdl;
1039 
1040 	mtx_enter(&audio_lock);
1041 	maestro_channel_stop(&sc->record);
1042 	sc->record.mode &= ~MAESTRO_RUNNING;
1043 	maestro_update_timer(sc);
1044 	mtx_leave(&audio_lock);
1045 	return 0;
1046 }
1047 
1048 int
maestro_halt_output(void * hdl)1049 maestro_halt_output(void *hdl)
1050 {
1051 	struct maestro_softc *sc = (struct maestro_softc *)hdl;
1052 
1053 	mtx_enter(&audio_lock);
1054 	maestro_channel_stop(&sc->play);
1055 	sc->play.mode &= ~MAESTRO_RUNNING;
1056 	maestro_update_timer(sc);
1057 	mtx_leave(&audio_lock);
1058 	return 0;
1059 }
1060 
1061 int
maestro_trigger_input(void * hdl,void * start,void * end,int blksize,void (* intr)(void *),void * arg,struct audio_params * param)1062 maestro_trigger_input(void *hdl, void *start, void *end, int blksize,
1063     void (*intr)(void *), void *arg, struct audio_params *param)
1064 {
1065 	struct maestro_softc *sc = (struct maestro_softc *)hdl;
1066 
1067 	mtx_enter(&audio_lock);
1068 	sc->record.mode |= MAESTRO_RUNNING;
1069 	sc->record.blocksize = blksize;
1070 
1071 	maestro_channel_start(&sc->record);
1072 
1073 	sc->record.threshold = sc->record.start;
1074 	maestro_update_timer(sc);
1075 	mtx_leave(&audio_lock);
1076 	return 0;
1077 }
1078 
1079 void
maestro_channel_start(struct maestro_channel * ch)1080 maestro_channel_start(struct maestro_channel *ch)
1081 {
1082 	struct maestro_softc *sc = ch->sc;
1083 	int n = ch->num;
1084 	int aputype;
1085 	wcreg_t wcreg = (sc->physaddr - 16) & WAVCACHE_CHCTL_ADDRTAG_MASK;
1086 
1087 	switch(ch->mode & (MAESTRO_STEREO | MAESTRO_8BIT)) {
1088 	case 0:
1089 		aputype = APUTYPE_16BITLINEAR;
1090 		break;
1091 	case MAESTRO_STEREO:
1092 		aputype = APUTYPE_16BITSTEREO;
1093 		break;
1094 	case MAESTRO_8BIT:
1095 		aputype = APUTYPE_8BITLINEAR;
1096 		break;
1097 	case MAESTRO_8BIT|MAESTRO_STEREO:
1098 		aputype = APUTYPE_8BITSTEREO;
1099 		break;
1100 	}
1101 	if (ch->mode & MAESTRO_UNSIGNED)
1102 		wcreg |= WAVCACHE_CHCTL_U8;
1103 	if ((ch->mode & MAESTRO_STEREO) == 0) {
1104 		DPRINTF(("Setting mono parameters\n"));
1105 		wp_apu_write(sc, n, APUREG_WAVESPACE, ch->wpwa & 0xff00);
1106 		wp_apu_write(sc, n, APUREG_CURPTR, ch->current);
1107 		wp_apu_write(sc, n, APUREG_ENDPTR, ch->end);
1108 		wp_apu_write(sc, n, APUREG_LOOPLEN, ch->end - ch->start);
1109 		wp_apu_write(sc, n, APUREG_AMPLITUDE, 0xe800);
1110 		wp_apu_write(sc, n, APUREG_POSITION, 0x8f00
1111 		    | (RADIUS_CENTERCIRCLE << APU_RADIUS_SHIFT)
1112 		    | (PAN_FRONT << APU_PAN_SHIFT));
1113 		wp_apu_write(sc, n, APUREG_FREQ_LOBYTE, APU_plus6dB
1114 		    | ((ch->dv & 0xff) << APU_FREQ_LOBYTE_SHIFT));
1115 		wp_apu_write(sc, n, APUREG_FREQ_HIWORD, ch->dv >> 8);
1116 		wc_ctrl_write(sc, n, wcreg);
1117 		wp_apu_write(sc, n, APUREG_APUTYPE,
1118 		    (aputype << APU_APUTYPE_SHIFT) | APU_DMA_ENABLED | 0xf);
1119 	} else {
1120 		wcreg |= WAVCACHE_CHCTL_STEREO;
1121 		DPRINTF(("Setting stereo parameters\n"));
1122 		wp_apu_write(sc, n+1, APUREG_WAVESPACE, ch->wpwa & 0xff00);
1123 		wp_apu_write(sc, n+1, APUREG_CURPTR, ch->current);
1124 		wp_apu_write(sc, n+1, APUREG_ENDPTR, ch->end);
1125 		wp_apu_write(sc, n+1, APUREG_LOOPLEN, ch->end - ch->start);
1126 		wp_apu_write(sc, n+1, APUREG_AMPLITUDE, 0xe800);
1127 		wp_apu_write(sc, n+1, APUREG_POSITION, 0x8f00
1128 		    | (RADIUS_CENTERCIRCLE << APU_RADIUS_SHIFT)
1129 		    | (PAN_LEFT << APU_PAN_SHIFT));
1130 		wp_apu_write(sc, n+1, APUREG_FREQ_LOBYTE, APU_plus6dB
1131 		    | ((ch->dv & 0xff) << APU_FREQ_LOBYTE_SHIFT));
1132 		wp_apu_write(sc, n+1, APUREG_FREQ_HIWORD, ch->dv >> 8);
1133 		if (ch->mode & MAESTRO_8BIT)
1134 			wp_apu_write(sc, n, APUREG_WAVESPACE,
1135 			    ch->wpwa & 0xff00);
1136 		    else
1137 			wp_apu_write(sc, n, APUREG_WAVESPACE,
1138 			    (ch->wpwa|(APU_STEREO >> 1)) & 0xff00);
1139 		wp_apu_write(sc, n, APUREG_CURPTR, ch->current);
1140 		wp_apu_write(sc, n, APUREG_ENDPTR, ch->end);
1141 		wp_apu_write(sc, n, APUREG_LOOPLEN, ch->end - ch->start);
1142 		wp_apu_write(sc, n, APUREG_AMPLITUDE, 0xe800);
1143 		wp_apu_write(sc, n, APUREG_POSITION, 0x8f00
1144 		    | (RADIUS_CENTERCIRCLE << APU_RADIUS_SHIFT)
1145 		    | (PAN_RIGHT << APU_PAN_SHIFT));
1146 		wp_apu_write(sc, n, APUREG_FREQ_LOBYTE, APU_plus6dB
1147 		    | ((ch->dv & 0xff) << APU_FREQ_LOBYTE_SHIFT));
1148 		wp_apu_write(sc, n, APUREG_FREQ_HIWORD, ch->dv >> 8);
1149 		wc_ctrl_write(sc, n, wcreg);
1150 		wc_ctrl_write(sc, n+1, wcreg);
1151 		wp_apu_write(sc, n, APUREG_APUTYPE,
1152 		    (aputype << APU_APUTYPE_SHIFT) | APU_DMA_ENABLED | 0xf);
1153 		wp_apu_write(sc, n+1, APUREG_APUTYPE,
1154 		    (aputype << APU_APUTYPE_SHIFT) | APU_DMA_ENABLED | 0xf);
1155 	}
1156 }
1157 
1158 int
maestro_trigger_output(void * hdl,void * start,void * end,int blksize,void (* intr)(void *),void * arg,struct audio_params * param)1159 maestro_trigger_output(void *hdl, void *start, void *end, int blksize,
1160     void (*intr)(void *), void *arg, struct audio_params *param)
1161 {
1162 	struct maestro_softc *sc = (struct maestro_softc *)hdl;
1163 	u_int offset = ((caddr_t)start - sc->dmabase) >> 1;
1164 	u_int size = ((char *)end - (char *)start) >> 1;
1165 
1166 	mtx_enter(&audio_lock);
1167 	sc->play.mode |= MAESTRO_RUNNING;
1168 	sc->play.wpwa = APU_USE_SYSMEM | (offset >> 8);
1169 	DPRINTF(("maestro_trigger_output: start=%p, end=%p, blksize=%x ",
1170 		start, end, blksize));
1171     	DPRINTF(("offset = %x, size=%x\n", offset, size));
1172 
1173 	sc->play.intr = intr;
1174 	sc->play.intr_arg = arg;
1175 	sc->play.blocksize = blksize;
1176 	sc->play.end = offset+size;
1177 	sc->play.start = offset;
1178 	sc->play.current = sc->play.start;
1179 	if ((sc->play.mode & (MAESTRO_STEREO | MAESTRO_8BIT)) == MAESTRO_STEREO) {
1180 		sc->play.wpwa >>= 1;
1181 		sc->play.start >>= 1;
1182 		sc->play.end >>= 1;
1183 		sc->play.blocksize >>= 1;
1184 	}
1185 	maestro_channel_start(&sc->play);
1186 
1187 	sc->play.threshold = sc->play.start;
1188 	maestro_update_timer(sc);
1189 	mtx_leave(&audio_lock);
1190 	return 0;
1191 }
1192 
1193 /* -----------------------------
1194  * Codec interface
1195  */
1196 
1197 enum ac97_host_flags
maestro_codec_flags(void * self)1198 maestro_codec_flags(void *self)
1199 {
1200 	return AC97_HOST_DONT_READ;
1201 }
1202 
1203 int
maestro_read_codec(void * self,u_int8_t regno,u_int16_t * datap)1204 maestro_read_codec(void *self, u_int8_t regno, u_int16_t *datap)
1205 {
1206 	struct maestro_softc *sc = (struct maestro_softc *)self;
1207 	int t;
1208 
1209 	/* We have to wait for a SAFE time to write addr/data */
1210 	for (t = 0; t < 20; t++) {
1211 		if ((bus_space_read_1(sc->iot, sc->ioh, PORT_CODEC_STAT)
1212 		    & CODEC_STAT_MASK) != CODEC_STAT_PROGLESS)
1213 			break;
1214 		DELAY(2);	/* 20.8us / 13 */
1215 	}
1216 	if (t == 20)
1217 		printf("%s: maestro_read_codec() PROGLESS timed out.\n",
1218 		    sc->dev.dv_xname);
1219 		/* XXX return 1 */
1220 
1221 	bus_space_write_1(sc->iot, sc->ioh, PORT_CODEC_CMD,
1222 	    CODEC_CMD_READ | regno);
1223 	DELAY(21);	/* AC97 cycle = 20.8usec */
1224 
1225 	/* Wait for data retrieve */
1226 	for (t = 0; t < 20; t++) {
1227 		if ((bus_space_read_1(sc->iot, sc->ioh, PORT_CODEC_STAT)
1228 		    & CODEC_STAT_MASK) == CODEC_STAT_RW_DONE)
1229 			break;
1230 		DELAY(2);	/* 20.8us / 13 */
1231 	}
1232 	if (t == 20)
1233 		/* Timed out, but perform dummy read. */
1234 		printf("%s: maestro_read_codec() RW_DONE timed out.\n",
1235 		    sc->dev.dv_xname);
1236 
1237 	*datap = bus_space_read_2(sc->iot, sc->ioh, PORT_CODEC_REG);
1238 	return 0;
1239 }
1240 
1241 int
maestro_write_codec(void * self,u_int8_t regno,u_int16_t data)1242 maestro_write_codec(void *self, u_int8_t regno, u_int16_t data)
1243 {
1244 	struct maestro_softc *sc = (struct maestro_softc *)self;
1245 	int t;
1246 
1247 	/* We have to wait for a SAFE time to write addr/data */
1248 	for (t = 0; t < 20; t++) {
1249 		if ((bus_space_read_1(sc->iot, sc->ioh, PORT_CODEC_STAT)
1250 		    & CODEC_STAT_MASK) != CODEC_STAT_PROGLESS)
1251 			break;
1252 		DELAY(2);	/* 20.8us / 13 */
1253 	}
1254 	if (t == 20) {
1255 		/* Timed out. Abort writing. */
1256 		printf("%s: maestro_write_codec() PROGLESS timed out.\n",
1257 		    sc->dev.dv_xname);
1258 		return 1;
1259 	}
1260 
1261 	bus_space_write_2(sc->iot, sc->ioh, PORT_CODEC_REG, data);
1262 	bus_space_write_1(sc->iot, sc->ioh, PORT_CODEC_CMD,
1263 	    CODEC_CMD_WRITE | regno);
1264 
1265 	return 0;
1266 }
1267 
1268 int
maestro_attach_codec(void * self,struct ac97_codec_if * cif)1269 maestro_attach_codec(void *self, struct ac97_codec_if *cif)
1270 {
1271 	struct maestro_softc *sc = (struct maestro_softc *)self;
1272 
1273 	sc->codec_if = cif;
1274 	return 0;
1275 }
1276 
1277 void
maestro_reset_codec(void * self UNUSED)1278 maestro_reset_codec(void *self UNUSED)
1279 {
1280 }
1281 
1282 void
maestro_initcodec(void * self)1283 maestro_initcodec(void *self)
1284 {
1285 	struct maestro_softc *sc = (struct maestro_softc *)self;
1286 	u_int16_t data;
1287 
1288 	if (bus_space_read_4(sc->iot, sc->ioh, PORT_RINGBUS_CTRL)
1289 	    & RINGBUS_CTRL_ACLINK_ENABLED) {
1290 		bus_space_write_4(sc->iot, sc->ioh, PORT_RINGBUS_CTRL, 0);
1291 		DELAY(104);	/* 20.8us * (4 + 1) */
1292 	}
1293 	/* XXX - 2nd codec should be looked at. */
1294 	bus_space_write_4(sc->iot, sc->ioh,
1295 	    PORT_RINGBUS_CTRL, RINGBUS_CTRL_AC97_SWRESET);
1296 	DELAY(2);
1297 	bus_space_write_4(sc->iot, sc->ioh,
1298 	    PORT_RINGBUS_CTRL, RINGBUS_CTRL_ACLINK_ENABLED);
1299 	DELAY(21);
1300 
1301 	maestro_read_codec(sc, 0, &data);
1302 	if ((bus_space_read_1(sc->iot, sc->ioh, PORT_CODEC_STAT)
1303 	    & CODEC_STAT_MASK) != 0) {
1304 		bus_space_write_4(sc->iot, sc->ioh,
1305 		    PORT_RINGBUS_CTRL, 0);
1306 		DELAY(21);
1307 
1308 		/* Try cold reset. */
1309 		printf("%s: resetting codec\n", sc->dev.dv_xname);
1310 
1311 		data = bus_space_read_2(sc->iot, sc->ioh, PORT_GPIO_DIR);
1312 		if (pci_conf_read(sc->pc, sc->pt, 0x58) & 1)
1313 			data |= 0x10;
1314 		data |= 0x009 &
1315 		    ~bus_space_read_2(sc->iot, sc->ioh, PORT_GPIO_DATA);
1316 		bus_space_write_2(sc->iot, sc->ioh,
1317 		    PORT_GPIO_MASK, 0xff6);
1318 		bus_space_write_2(sc->iot, sc->ioh,
1319 		    PORT_GPIO_DIR, data | 0x009);
1320 		bus_space_write_2(sc->iot, sc->ioh,
1321 		    PORT_GPIO_DATA, 0x000);
1322 		DELAY(2);
1323 		bus_space_write_2(sc->iot, sc->ioh,
1324 		    PORT_GPIO_DATA, 0x001);
1325 		DELAY(1);
1326 		bus_space_write_2(sc->iot, sc->ioh,
1327 		    PORT_GPIO_DATA, 0x009);
1328 		DELAY(500000);
1329 		bus_space_write_2(sc->iot, sc->ioh,
1330 		    PORT_GPIO_DIR, data);
1331 		DELAY(84);	/* 20.8us * 4 */
1332 		bus_space_write_4(sc->iot, sc->ioh,
1333 		    PORT_RINGBUS_CTRL, RINGBUS_CTRL_ACLINK_ENABLED);
1334 		DELAY(21);
1335 	}
1336 
1337 	/* Check the codec to see is still busy */
1338 	if ((bus_space_read_1(sc->iot, sc->ioh, PORT_CODEC_STAT) &
1339 	    CODEC_STAT_MASK) != 0) {
1340 		printf("%s: codec failure\n", sc->dev.dv_xname);
1341 	}
1342 }
1343 
1344 /* -----------------------------
1345  * Power management interface
1346  */
1347 
1348 int
maestro_activate(struct device * self,int act)1349 maestro_activate(struct device *self, int act)
1350 {
1351 	struct maestro_softc *sc = (struct maestro_softc *)self;
1352 	int rv;
1353 
1354 	switch (act) {
1355 	case DVACT_SUSPEND:
1356 		rv = config_activate_children(self, act);
1357 		/* Power down device on shutdown. */
1358 		DPRINTF(("maestro: power down\n"));
1359 		if (sc->record.mode & MAESTRO_RUNNING) {
1360 		    	sc->record.current = wp_apu_read(sc, sc->record.num, APUREG_CURPTR);
1361 			maestro_channel_stop(&sc->record);
1362 		}
1363 		if (sc->play.mode & MAESTRO_RUNNING) {
1364 		    	sc->play.current = wp_apu_read(sc, sc->play.num, APUREG_CURPTR);
1365 			maestro_channel_stop(&sc->play);
1366 		}
1367 
1368 		wp_stoptimer(sc);
1369 
1370 		/* Power down everything except clock. */
1371 		bus_space_write_2(sc->iot, sc->ioh, PORT_HOSTINT_CTRL, 0);
1372 		maestro_write_codec(sc, AC97_REG_POWER, 0xdf00);
1373 		DELAY(20);
1374 		bus_space_write_4(sc->iot, sc->ioh, PORT_RINGBUS_CTRL, 0);
1375 		DELAY(1);
1376 		break;
1377 	case DVACT_RESUME:
1378 		/* Power up device on resume. */
1379 		DPRINTF(("maestro: power resume\n"));
1380 		maestro_init(sc);
1381 		/* Restore codec settings */
1382 		if (sc->play.mode & MAESTRO_RUNNING)
1383 			maestro_channel_start(&sc->play);
1384 		if (sc->record.mode & MAESTRO_RUNNING)
1385 			maestro_channel_start(&sc->record);
1386 		maestro_update_timer(sc);
1387 		rv = config_activate_children(self, act);
1388 		break;
1389 	default:
1390 		rv = config_activate_children(self, act);
1391 		break;
1392 	}
1393 	return rv;
1394 }
1395 
1396 void
maestro_channel_advance_dma(struct maestro_channel * ch)1397 maestro_channel_advance_dma(struct maestro_channel *ch)
1398 {
1399 	wpreg_t pos;
1400 #ifdef AUDIO_DEBUG
1401 	maestrointr_called++;
1402 #endif
1403 	for (;;) {
1404 		pos = wp_apu_read(ch->sc, ch->num, APUREG_CURPTR);
1405 		/* Are we still processing the current dma block ? */
1406 		if (pos >= ch->threshold &&
1407 		    pos < ch->threshold + ch->blocksize/2)
1408 			break;
1409 		ch->threshold += ch->blocksize/2;
1410 		if (ch->threshold >= ch->end)
1411 			ch->threshold = ch->start;
1412 		(*ch->intr)(ch->intr_arg);
1413 #ifdef AUDIO_DEBUG
1414 		maestrodma_effective++;
1415 #endif
1416 	}
1417 
1418 #ifdef AUDIO_DEBUG
1419 	if (maestrodebug && maestrointr_called % 64 == 0)
1420 		printf("maestro: dma advanced %lu for %lu calls\n",
1421 			maestrodma_effective, maestrointr_called);
1422 #endif
1423 }
1424 
1425 /* Some maestro makes sometimes get desynchronized in stereo mode. */
1426 void
maestro_channel_suppress_jitter(struct maestro_channel * ch)1427 maestro_channel_suppress_jitter(struct maestro_channel *ch)
1428 {
1429 	int cp, diff;
1430 
1431 	/* Verify that both channels are not too far off. */
1432 	cp = wp_apu_read(ch->sc, ch->num, APUREG_CURPTR);
1433 	diff = wp_apu_read(ch->sc, ch->num+1, APUREG_CURPTR) - cp;
1434 	if (diff > 4 || diff < -4)
1435 		/* Otherwise, directly resynch the 2nd channel. */
1436 		bus_space_write_2(ch->sc->iot, ch->sc->ioh,
1437 		    PORT_DSP_DATA, cp);
1438 }
1439 
1440 /* -----------------------------
1441  * Interrupt handler interface
1442  */
1443 int
maestro_intr(void * arg)1444 maestro_intr(void *arg)
1445 {
1446 	struct maestro_softc *sc = (struct maestro_softc *)arg;
1447 	u_int16_t status;
1448 
1449 	status = bus_space_read_1(sc->iot, sc->ioh, PORT_HOSTINT_STAT);
1450 	if (status == 0)
1451 		return 0;	/* Not for us? */
1452 
1453 	mtx_enter(&audio_lock);
1454 
1455 	/* Acknowledge all. */
1456 	bus_space_write_2(sc->iot, sc->ioh, PORT_INT_STAT, 1);
1457 	bus_space_write_1(sc->iot, sc->ioh, PORT_HOSTINT_STAT, status);
1458 
1459 	/* Hardware volume support */
1460 	if (status & HOSTINT_STAT_HWVOL && sc->codec_if != NULL) {
1461 		int n, i, delta, v;
1462 		mixer_ctrl_t hwvol;
1463 
1464 		n = bus_space_read_1(sc->iot, sc->ioh, PORT_HWVOL_MASTER);
1465 		/* Special case: Mute key */
1466 		if (n & 0x11) {
1467 			hwvol.type = AUDIO_MIXER_ENUM;
1468 			hwvol.dev =
1469 			    sc->codec_if->vtbl->get_portnum_by_name(sc->codec_if,
1470 				AudioCoutputs, AudioNmaster, AudioNmute);
1471 			sc->codec_if->vtbl->mixer_get_port(sc->codec_if, &hwvol);
1472 			hwvol.un.ord = !hwvol.un.ord;
1473 		} else {
1474 			hwvol.type = AUDIO_MIXER_VALUE;
1475 			hwvol.un.value.num_channels = 2;
1476 			hwvol.dev =
1477 			    sc->codec_if->vtbl->get_portnum_by_name(
1478 			    	sc->codec_if, AudioCoutputs, AudioNmaster,
1479 				    NULL);
1480 			sc->codec_if->vtbl->mixer_get_port(sc->codec_if, &hwvol);
1481 			/* XXX AC'97 yields five bits for master volume. */
1482 			delta = (n - MIDDLE_VOLUME)/STEP_VOLUME * 8;
1483 			for (i = 0; i < hwvol.un.value.num_channels; i++) {
1484 				v = ((int)hwvol.un.value.level[i]) + delta;
1485 				if (v < 0)
1486 					v = 0;
1487 				else if (v > 255)
1488 					v = 255;
1489 				hwvol.un.value.level[i] = v;
1490 			}
1491 		}
1492 		sc->codec_if->vtbl->mixer_set_port(sc->codec_if, &hwvol);
1493 		/* Reset to compute next diffs */
1494 		bus_space_write_1(sc->iot, sc->ioh, PORT_HWVOL_MASTER,
1495 		    MIDDLE_VOLUME);
1496 	}
1497 
1498 	if (sc->play.mode & MAESTRO_RUNNING) {
1499 		maestro_channel_advance_dma(&sc->play);
1500 		if (sc->play.mode & MAESTRO_STEREO)
1501 			maestro_channel_suppress_jitter(&sc->play);
1502 	}
1503 
1504 	if (sc->record.mode & MAESTRO_RUNNING)
1505 		maestro_channel_advance_dma(&sc->record);
1506 
1507 	mtx_leave(&audio_lock);
1508 	return 1;
1509 }
1510 
1511 /* -----------------------------
1512  * Hardware interface
1513  */
1514 
1515 /* Codec/Ringbus */
1516 
1517 void
ringbus_setdest(struct maestro_softc * sc,int src,int dest)1518 ringbus_setdest(struct maestro_softc *sc, int src, int dest)
1519 {
1520 	u_int32_t	data;
1521 
1522 	data = bus_space_read_4(sc->iot, sc->ioh, PORT_RINGBUS_CTRL);
1523 	data &= ~(0xfU << src);
1524 	data |= (0xfU & dest) << src;
1525 	bus_space_write_4(sc->iot, sc->ioh, PORT_RINGBUS_CTRL, data);
1526 }
1527 
1528 /* Wave Processor */
1529 
1530 wpreg_t
wp_reg_read(struct maestro_softc * sc,int reg)1531 wp_reg_read(struct maestro_softc *sc, int reg)
1532 {
1533 	bus_space_write_2(sc->iot, sc->ioh, PORT_DSP_INDEX, reg);
1534 	return bus_space_read_2(sc->iot, sc->ioh, PORT_DSP_DATA);
1535 }
1536 
1537 void
wp_reg_write(struct maestro_softc * sc,int reg,wpreg_t data)1538 wp_reg_write(struct maestro_softc *sc, int reg, wpreg_t data)
1539 {
1540 	bus_space_write_2(sc->iot, sc->ioh, PORT_DSP_INDEX, reg);
1541 	bus_space_write_2(sc->iot, sc->ioh, PORT_DSP_DATA, data);
1542 }
1543 
1544 static void
apu_setindex(struct maestro_softc * sc,int reg)1545 apu_setindex(struct maestro_softc *sc, int reg)
1546 {
1547 	int t;
1548 
1549 	wp_reg_write(sc, WPREG_CRAM_PTR, reg);
1550 	/* Sometimes WP fails to set apu register index. */
1551 	for (t = 0; t < 1000; t++) {
1552 		if (bus_space_read_2(sc->iot, sc->ioh,
1553 		    PORT_DSP_DATA) == reg)
1554 			break;
1555 		bus_space_write_2(sc->iot, sc->ioh, PORT_DSP_DATA, reg);
1556 	}
1557 	if (t == 1000)
1558 		printf("%s: apu_setindex() timeout\n", sc->dev.dv_xname);
1559 }
1560 
1561 wpreg_t
wp_apu_read(struct maestro_softc * sc,int ch,int reg)1562 wp_apu_read(struct maestro_softc *sc, int ch, int reg)
1563 {
1564 	wpreg_t ret;
1565 
1566 	apu_setindex(sc, ((unsigned)ch << 4) + reg);
1567 	ret = wp_reg_read(sc, WPREG_DATA_PORT);
1568 	return ret;
1569 }
1570 
1571 void
wp_apu_write(struct maestro_softc * sc,int ch,int reg,wpreg_t data)1572 wp_apu_write(struct maestro_softc *sc, int ch, int reg, wpreg_t data)
1573 {
1574 	int t;
1575 
1576 	apu_setindex(sc, ((unsigned)ch << 4) + reg);
1577 	wp_reg_write(sc, WPREG_DATA_PORT, data);
1578 	for (t = 0; t < 1000; t++) {
1579 		if (bus_space_read_2(sc->iot, sc->ioh, PORT_DSP_DATA) == data)
1580 			break;
1581 		bus_space_write_2(sc->iot, sc->ioh, PORT_DSP_DATA, data);
1582 	}
1583 	if (t == 1000)
1584 		printf("%s: wp_apu_write() timeout\n", sc->dev.dv_xname);
1585 }
1586 
1587 void
wp_settimer(struct maestro_softc * sc,u_int freq)1588 wp_settimer(struct maestro_softc *sc, u_int freq)
1589 {
1590 	u_int clock = 48000 << 2;
1591 	u_int prescale = 0, divide = (freq != 0) ? (clock / freq) : ~0;
1592 
1593 	if (divide < 4)
1594 		divide = 4;
1595 	else if (divide > 32 << 8)
1596 		divide = 32 << 8;
1597 
1598 	for (; divide > 32 << 1; divide >>= 1)
1599 		prescale++;
1600 	divide = (divide + 1) >> 1;
1601 
1602 	for (; prescale < 7 && divide > 2 && !(divide & 1); divide >>= 1)
1603 		prescale++;
1604 
1605 	wp_reg_write(sc, WPREG_TIMER_ENABLE, 0);
1606 	wp_reg_write(sc, WPREG_TIMER_FREQ,
1607 	    (prescale << WP_TIMER_FREQ_PRESCALE_SHIFT) | (divide - 1));
1608 	wp_reg_write(sc, WPREG_TIMER_ENABLE, 1);
1609 }
1610 
1611 void
wp_starttimer(struct maestro_softc * sc)1612 wp_starttimer(struct maestro_softc *sc)
1613 {
1614 	wp_reg_write(sc, WPREG_TIMER_START, 1);
1615 }
1616 
1617 void
wp_stoptimer(struct maestro_softc * sc)1618 wp_stoptimer(struct maestro_softc *sc)
1619 {
1620 	wp_reg_write(sc, WPREG_TIMER_START, 0);
1621 	bus_space_write_2(sc->iot, sc->ioh, PORT_INT_STAT, 1);
1622 }
1623 
1624 /* WaveCache */
1625 
1626 wcreg_t
wc_reg_read(struct maestro_softc * sc,int reg)1627 wc_reg_read(struct maestro_softc *sc, int reg)
1628 {
1629 	bus_space_write_2(sc->iot, sc->ioh, PORT_WAVCACHE_INDEX, reg);
1630 	return bus_space_read_2(sc->iot, sc->ioh, PORT_WAVCACHE_DATA);
1631 }
1632 
1633 void
wc_reg_write(struct maestro_softc * sc,int reg,wcreg_t data)1634 wc_reg_write(struct maestro_softc *sc, int reg, wcreg_t data)
1635 {
1636 	bus_space_write_2(sc->iot, sc->ioh, PORT_WAVCACHE_INDEX, reg);
1637 	bus_space_write_2(sc->iot, sc->ioh, PORT_WAVCACHE_DATA, data);
1638 }
1639 
1640 u_int16_t
wc_ctrl_read(struct maestro_softc * sc,int ch)1641 wc_ctrl_read(struct maestro_softc *sc, int ch)
1642 {
1643 	return wc_reg_read(sc, ch << 3);
1644 }
1645 
1646 void
wc_ctrl_write(struct maestro_softc * sc,int ch,wcreg_t data)1647 wc_ctrl_write(struct maestro_softc *sc, int ch, wcreg_t data)
1648 {
1649 	wc_reg_write(sc, ch << 3, data);
1650 }
1651 
1652 /* -----------------------------
1653  * Simple zone allocator.
1654  * (All memory allocated in advance)
1655  */
1656 
1657 salloc_t
salloc_new(caddr_t addr,size_t size,int nzones)1658 salloc_new(caddr_t addr, size_t size, int nzones)
1659 {
1660 	struct salloc_pool *pool;
1661 	struct salloc_zone *space;
1662 	int i;
1663 
1664 	pool = malloc(sizeof *pool + nzones * sizeof pool->zones[0],
1665 	    M_TEMP, M_NOWAIT);
1666 	if (pool == NULL)
1667 		return NULL;
1668 	SLIST_INIT(&pool->free);
1669 	SLIST_INIT(&pool->used);
1670 	SLIST_INIT(&pool->spare);
1671 	/* Espie says the following line is obvious */
1672 	pool->zones = (struct salloc_zone *)(pool + 1);
1673 	for (i = 1; i < nzones; i++)
1674 		SLIST_INSERT_HEAD(&pool->spare, &pool->zones[i], link);
1675 	space = &pool->zones[0];
1676 	space->addr = addr;
1677 	space->size = size;
1678 	SLIST_INSERT_HEAD(&pool->free, space, link);
1679 	return pool;
1680 }
1681 
1682 void
salloc_destroy(salloc_t pool)1683 salloc_destroy(salloc_t pool)
1684 {
1685 	free(pool, M_TEMP, 0);
1686 }
1687 
1688 void
salloc_insert(salloc_t pool,struct salloc_head * head,struct salloc_zone * zone,int merge)1689 salloc_insert(salloc_t pool, struct salloc_head *head, struct salloc_zone *zone,
1690     int merge)
1691 {
1692 	struct salloc_zone *prev, *next;
1693 
1694 	/*
1695 	 * Insert a zone into an ordered list of zones, possibly
1696 	 * merging adjacent zones.
1697 	 */
1698 	prev = NULL;
1699 	SLIST_FOREACH(next, head, link) {
1700 		if (next->addr > zone->addr)
1701 			break;
1702 		prev = next;
1703 	}
1704 
1705 	if (merge && prev && prev->addr + prev->size == zone->addr) {
1706 		prev->size += zone->size;
1707 		SLIST_INSERT_HEAD(&pool->spare, zone, link);
1708 		zone = prev;
1709 	} else if (prev)
1710 		SLIST_INSERT_AFTER(prev, zone, link);
1711 	else
1712 		SLIST_INSERT_HEAD(head, zone, link);
1713 	if (merge && next && zone->addr + zone->size == next->addr) {
1714 		zone->size += next->size;
1715 		SLIST_REMOVE(head, next, salloc_zone, link);
1716 		SLIST_INSERT_HEAD(&pool->spare, next, link);
1717 	}
1718 }
1719 
1720 caddr_t
salloc_alloc(salloc_t pool,size_t size)1721 salloc_alloc(salloc_t pool, size_t size)
1722 {
1723 	struct salloc_zone *zone, *uzone;
1724 
1725 	SLIST_FOREACH(zone, &pool->free, link)
1726 		if (zone->size >= size)
1727 			break;
1728 	if (zone == NULL)
1729 		return NULL;
1730 	if (zone->size == size) {
1731 		SLIST_REMOVE(&pool->free, zone, salloc_zone, link);
1732 		uzone = zone;
1733 	} else {
1734 		uzone = SLIST_FIRST(&pool->spare);
1735 		if (uzone == NULL)
1736 			return NULL;		/* XXX */
1737 		SLIST_REMOVE_HEAD(&pool->spare, link);
1738 		uzone->size = size;
1739 		uzone->addr = zone->addr;
1740 		zone->size -= size;
1741 		zone->addr += size;
1742 	}
1743 	salloc_insert(pool, &pool->used, uzone, 0);
1744 	return uzone->addr;
1745 }
1746 
1747 void
salloc_free(salloc_t pool,caddr_t addr)1748 salloc_free(salloc_t pool, caddr_t addr)
1749 {
1750 	struct salloc_zone *zone;
1751 
1752 	SLIST_FOREACH(zone, &pool->used, link)
1753 		if (zone->addr == addr)
1754 			break;
1755 #ifdef DIAGNOSTIC
1756 	if (zone == NULL)
1757 		panic("salloc_free: freeing unallocated memory");
1758 #endif
1759 	SLIST_REMOVE(&pool->used, zone, salloc_zone, link);
1760 	salloc_insert(pool, &pool->free, zone, 1);
1761 }
1762