cs4231.c revision 139749
1/*-
2 * Copyright (c) 1999 Jason L. Wright (jason@thought.net)
3 * Copyright (c) 2004 Pyun YongHyeon
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
19 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
23 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
24 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 * POSSIBILITY OF SUCH DAMAGE.
26 *
27 * Effort sponsored in part by the Defense Advanced Research Projects
28 * Agency (DARPA) and Air Force Research Laboratory, Air Force
29 * Materiel Command, USAF, under agreement number F30602-01-2-0537.
30 *
31 *	from: OpenBSD: cs4231.c,v 1.21 2003/07/03 20:36:07 jason Exp
32 */
33
34/*
35 * Driver for CS4231 based audio found in some sun4m systems (cs4231)
36 * based on ideas from the S/Linux project and the NetBSD project.
37 */
38
39#include <sys/cdefs.h>
40__FBSDID("$FreeBSD: head/sys/dev/sound/sbus/cs4231.c 139749 2005-01-06 01:43:34Z imp $");
41
42#include <sys/param.h>
43#include <sys/systm.h>
44#include <sys/bus.h>
45#include <sys/kernel.h>
46#include <sys/resource.h>
47
48#include <dev/ofw/ofw_bus.h>
49#include <dev/ofw/openfirm.h>
50#include <machine/bus.h>
51#include <machine/ofw_machdep.h>
52
53#include <dev/sound/pcm/sound.h>
54#include <dev/sound/sbus/apcdmareg.h>
55#include <dev/sound/sbus/cs4231.h>
56
57#include <sparc64/sbus/sbusvar.h>
58#include <sparc64/ebus/ebusreg.h>
59
60#include "mixer_if.h"
61
62/*
63 * The driver supports CS4231A audio chips found on Sbus/Ebus based
64 * UltraSPARCs. Though, CS4231A says it supports full-duplex mode, I
65 * doubt it due to the lack of independent sampling frequency register
66 * for playback/capture.
67 * Since I couldn't find any documentation for APCDMA programming
68 * information, I guessed the usage of APCDMA from that of OpenBSD's
69 * driver. The EBDMA infomation of PCIO can be obtained from
70 *  http://solutions.sun.com/embedded/databook/web/microprocessors/pcio.html
71 * And CS4231A datasheet can also be obtained from
72 *  ftp://ftp.alsa-project.org/pub/manuals/cirrus/4231a.pdf
73 *
74 * Audio capture(recording) was not tested at all and may have bugs.
75 * Sorry, I don't have microphone. Don't try to use full-duplex mode.
76 * It wouldn't work.
77 */
78#define CS_TIMEOUT		90000
79
80#define CS4231_MIN_BUF_SZ	(16*1024)
81#define CS4231_DEFAULT_BUF_SZ	(32*1024)
82#define CS4231_MAX_BUF_SZ	(64*1024)
83#define CS4231_MAX_BLK_SZ	(8*1024)
84#define CS4231_MAX_APC_DMA_SZ	(8*1024)
85
86
87#undef CS4231_DEBUG
88#ifdef CS4231_DEBUG
89#define DPRINTF(x)		printf x
90#else
91#define DPRINTF(x)
92#endif
93#define CS4231_AUTO_CALIBRATION
94
95struct cs4231_softc;
96
97struct cs4231_channel {
98	struct cs4231_softc	*parent;
99	struct pcm_channel	*channel;
100	struct snd_dbuf		*buffer;
101	u_int32_t		format;
102	u_int32_t		speed;
103	u_int32_t		nextaddr;
104	u_int32_t		togo;
105	int			dir;
106	int			locked;
107};
108
109#define CS4231_RES_MEM_MAX	4
110#define CS4231_RES_IRQ_MAX	2
111struct cs4231_softc {
112	struct device		*sc_dev;
113	int			sc_rid[CS4231_RES_MEM_MAX];
114	struct resource		*sc_res[CS4231_RES_MEM_MAX];
115	bus_space_handle_t	sc_regh[CS4231_RES_MEM_MAX];
116	bus_space_tag_t		sc_regt[CS4231_RES_MEM_MAX];
117
118	int			sc_irqrid[CS4231_RES_IRQ_MAX];
119	struct resource		*sc_irqres[CS4231_RES_IRQ_MAX];
120	void			*sc_ih[CS4231_RES_IRQ_MAX];
121	bus_dma_tag_t		sc_dmat[CS4231_RES_IRQ_MAX];
122	int			sc_burst;
123
124	u_int32_t		sc_bufsz;
125	struct cs4231_channel	sc_pch;
126	struct cs4231_channel	sc_rch;
127	int			sc_enabled;
128	int			sc_rtype;
129	int			sc_nmres;
130	int			sc_nires;
131	int			sc_codecv;
132	int			sc_chipvid;
133	int			sc_flags;
134#define CS4231_SBUS		0x01
135#define CS4231_EBUS		0x02
136
137	struct mtx		*sc_lock;
138};
139
140struct mix_table {
141	u_int32_t	reg:8;
142	u_int32_t	bits:8;
143	u_int32_t	mute:8;
144	u_int32_t	shift:4;
145	u_int32_t	neg:1;
146	u_int32_t	avail:1;
147	u_int32_t	recdev:1;
148};
149
150static int	cs4231_bus_probe(device_t);
151static int	cs4231_sbus_attach(device_t);
152static int	cs4231_ebus_attach(device_t);
153static int	cs4231_attach_common(struct cs4231_softc *);
154static int	cs4231_bus_detach(device_t);
155static int	cs4231_bus_suspend(device_t);
156static int	cs4231_bus_resume(device_t);
157static void	cs4231_getversion(struct cs4231_softc *);
158static void	cs4231_free_resource(struct cs4231_softc *);
159static void	cs4231_ebdma_reset(struct cs4231_softc *);
160static void	cs4231_power_reset(struct cs4231_softc *, int);
161static int	cs4231_enable(struct cs4231_softc *, int);
162static void	cs4231_disable(struct cs4231_softc *);
163static void	cs4231_write(struct cs4231_softc *, u_int8_t, u_int8_t);
164static u_int8_t cs4231_read(struct cs4231_softc *, u_int8_t);
165static void	cs4231_sbus_intr(void *);
166static void	cs4231_ebus_pintr(void *arg);
167static void	cs4231_ebus_cintr(void *arg);
168static int	cs4231_mixer_init(struct snd_mixer *);
169static void	cs4231_mixer_set_value(struct cs4231_softc *,
170    const struct mix_table *, u_int8_t);
171static int	cs4231_mixer_set(struct snd_mixer *, u_int32_t, u_int32_t,
172    u_int32_t);
173static int	cs4231_mixer_setrecsrc(struct snd_mixer *, u_int32_t);
174static void	*cs4231_chan_init(kobj_t, void *, struct snd_dbuf *,
175    struct pcm_channel *, int);
176static int	cs4231_chan_setformat(kobj_t, void *, u_int32_t);
177static int	cs4231_chan_setspeed(kobj_t, void *, u_int32_t);
178static void	cs4231_chan_fs(struct cs4231_softc *, int, u_int8_t);
179static int	cs4231_chan_setblocksize(kobj_t, void *, u_int32_t);
180static int	cs4231_chan_trigger(kobj_t, void *, int);
181static int	cs4231_chan_getptr(kobj_t, void *);
182static struct pcmchan_caps *
183    cs4231_chan_getcaps(kobj_t, void *);
184static void	cs4231_trigger(struct cs4231_channel *);
185static void	cs4231_apcdma_trigger(struct cs4231_softc *,
186    struct cs4231_channel *);
187static void	cs4231_ebdma_trigger(struct cs4231_softc *,
188    struct cs4231_channel *);
189static void	cs4231_halt(struct cs4231_channel *);
190
191#define CS4231_LOCK(sc)		snd_mtxlock(sc->sc_lock)
192#define CS4231_UNLOCK(sc)	snd_mtxunlock(sc->sc_lock)
193#define CS4231_LOCK_ASSERT(sc)	snd_mtxassert(sc->sc_lock)
194
195#define CS_WRITE(sc,r,v)	\
196    bus_space_write_1((sc)->sc_regt[0], (sc)->sc_regh[0], (r) << 2, (v))
197#define CS_READ(sc,r)		\
198    bus_space_read_1((sc)->sc_regt[0], (sc)->sc_regh[0], (r) << 2)
199
200#define APC_WRITE(sc,r,v)	\
201    bus_space_write_4(sc->sc_regt[0], sc->sc_regh[0], r, v)
202#define APC_READ(sc,r)		\
203    bus_space_read_4(sc->sc_regt[0], sc->sc_regh[0], r)
204
205#define EBDMA_P_WRITE(sc,r,v)	\
206    bus_space_write_4((sc)->sc_regt[1], (sc)->sc_regh[1], (r), (v))
207#define EBDMA_P_READ(sc,r)	\
208    bus_space_read_4((sc)->sc_regt[1], (sc)->sc_regh[1], (r))
209
210#define EBDMA_C_WRITE(sc,r,v)	\
211    bus_space_write_4((sc)->sc_regt[2], (sc)->sc_regh[2], (r), (v))
212#define EBDMA_C_READ(sc,r)	\
213    bus_space_read_4((sc)->sc_regt[2], (sc)->sc_regh[2], (r))
214
215#define AUXIO_CODEC		0x00
216#define AUXIO_WRITE(sc,r,v)	\
217    bus_space_write_4((sc)->sc_regt[3], (sc)->sc_regh[3], (r), (v))
218#define AUXIO_READ(sc,r)	\
219    bus_space_read_4((sc)->sc_regt[3], (sc)->sc_regh[3], (r))
220
221#define CODEC_WARM_RESET	0
222#define CODEC_COLD_RESET	1
223
224/* SBus */
225static device_method_t cs4231_sbus_methods[] = {
226	DEVMETHOD(device_probe,		cs4231_bus_probe),
227	DEVMETHOD(device_attach,	cs4231_sbus_attach),
228	DEVMETHOD(device_detach,	cs4231_bus_detach),
229	DEVMETHOD(device_suspend,	cs4231_bus_suspend),
230	DEVMETHOD(device_resume,	cs4231_bus_resume),
231	{0, 0}
232};
233
234static driver_t cs4231_sbus_driver = {
235	"pcm",
236	cs4231_sbus_methods,
237	PCM_SOFTC_SIZE
238};
239
240DRIVER_MODULE(snd_audiocs, sbus, cs4231_sbus_driver, pcm_devclass, 0, 0);
241
242/* EBus */
243static device_method_t cs4231_ebus_methods[] = {
244	DEVMETHOD(device_probe,		cs4231_bus_probe),
245	DEVMETHOD(device_attach,	cs4231_ebus_attach),
246	DEVMETHOD(device_detach,	cs4231_bus_detach),
247	DEVMETHOD(device_suspend,	cs4231_bus_suspend),
248	DEVMETHOD(device_resume,	cs4231_bus_resume),
249	{0, 0}
250};
251
252static driver_t cs4231_ebus_driver = {
253	"pcm",
254	cs4231_ebus_methods,
255	PCM_SOFTC_SIZE
256};
257
258DRIVER_MODULE(snd_audiocs, ebus, cs4231_ebus_driver, pcm_devclass, 0, 0);
259MODULE_DEPEND(snd_audiocs, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER);
260MODULE_VERSION(snd_audiocs, 1);
261
262
263static u_int32_t cs4231_fmt[] = {
264	AFMT_U8,
265	AFMT_STEREO | AFMT_U8,
266	AFMT_MU_LAW,
267	AFMT_STEREO | AFMT_MU_LAW,
268	AFMT_A_LAW,
269	AFMT_STEREO | AFMT_A_LAW,
270	AFMT_IMA_ADPCM,
271	AFMT_STEREO | AFMT_IMA_ADPCM,
272	AFMT_S16_LE,
273	AFMT_STEREO | AFMT_S16_LE,
274	AFMT_S16_BE,
275	AFMT_STEREO | AFMT_S16_BE,
276	0
277};
278
279static struct pcmchan_caps cs4231_caps = {5510, 48000, cs4231_fmt, 0};
280
281/*
282 * sound(4) channel interface
283 */
284static kobj_method_t cs4231_chan_methods[] = {
285	KOBJMETHOD(channel_init,		cs4231_chan_init),
286	KOBJMETHOD(channel_setformat,		cs4231_chan_setformat),
287	KOBJMETHOD(channel_setspeed,		cs4231_chan_setspeed),
288	KOBJMETHOD(channel_setblocksize,	cs4231_chan_setblocksize),
289	KOBJMETHOD(channel_trigger,		cs4231_chan_trigger),
290	KOBJMETHOD(channel_getptr,		cs4231_chan_getptr),
291	KOBJMETHOD(channel_getcaps,		cs4231_chan_getcaps),
292	{ 0, 0 }
293};
294CHANNEL_DECLARE(cs4231_chan);
295
296/*
297 * sound(4) mixer interface
298 */
299static kobj_method_t cs4231_mixer_methods[] = {
300	KOBJMETHOD(mixer_init,		cs4231_mixer_init),
301	KOBJMETHOD(mixer_set,		cs4231_mixer_set),
302	KOBJMETHOD(mixer_setrecsrc,	cs4231_mixer_setrecsrc),
303	{ 0, 0 }
304};
305MIXER_DECLARE(cs4231_mixer);
306
307static int
308cs4231_bus_probe(device_t dev)
309{
310	const char *name;
311
312	name = ofw_bus_get_name(dev);
313	if (strcmp("SUNW,CS4231", name) == 0) {
314		device_set_desc(dev, "Sun Audiocs");
315		return (0);
316	}
317	return (ENXIO);
318}
319
320static int
321cs4231_sbus_attach(device_t dev)
322{
323	struct snddev_info *d;
324	struct cs4231_softc *sc;
325	int burst;
326
327	d = device_get_softc(dev);
328	sc = malloc(sizeof(struct cs4231_softc), M_DEVBUF, M_NOWAIT | M_ZERO);
329	if (sc == NULL) {
330		device_printf(dev, "cannot allocate softc\n");
331		return (ENOMEM);
332	}
333	sc->sc_dev = dev;
334	/*
335	 * XXX
336	 * No public documentation exists on programming burst size of APCDMA.
337	 */
338	burst = sbus_get_burstsz(sc->sc_dev);
339	if ((burst & SBUS_BURST_64))
340		sc->sc_burst = 64;
341	else if ((burst & SBUS_BURST_32))
342		sc->sc_burst = 32;
343	else if ((burst & SBUS_BURST_16))
344		sc->sc_burst = 16;
345	else
346		sc->sc_burst = 0;
347	sc->sc_flags = CS4231_SBUS;
348	sc->sc_rtype = SYS_RES_MEMORY;
349	sc->sc_nmres = 1;
350	sc->sc_nires = 1;
351	return cs4231_attach_common(sc);
352}
353
354static int
355cs4231_ebus_attach(device_t dev)
356{
357	struct snddev_info *d;
358	struct cs4231_softc *sc;
359
360	d = device_get_softc(dev);
361	sc = malloc(sizeof(struct cs4231_softc), M_DEVBUF, M_NOWAIT | M_ZERO);
362	if (sc == NULL) {
363		device_printf(dev, "cannot allocate softc\n");
364		return (ENOMEM);
365	}
366	sc->sc_dev = dev;
367	sc->sc_burst = EBDCSR_BURST_1;
368	sc->sc_rtype = SYS_RES_IOPORT;
369	sc->sc_nmres = CS4231_RES_MEM_MAX;
370	sc->sc_nires = CS4231_RES_IRQ_MAX;
371	sc->sc_flags = CS4231_EBUS;
372	return cs4231_attach_common(sc);
373}
374
375static int
376cs4231_attach_common(struct cs4231_softc *sc)
377{
378	char status[SND_STATUSLEN];
379	driver_intr_t *ihandler;
380	int i;
381
382	sc->sc_lock = snd_mtxcreate(device_get_nameunit(sc->sc_dev),
383	    "sound softc");
384	if (sc->sc_lock == NULL) {
385		device_printf(sc->sc_dev, "cannot create mutex\n");
386		free(sc, M_DEVBUF);
387		return (ENXIO);
388	}
389
390	for (i = 0; i < sc->sc_nmres; i++) {
391		sc->sc_rid[i] = i;
392		if ((sc->sc_res[i] = bus_alloc_resource_any(sc->sc_dev,
393		    sc->sc_rtype, &sc->sc_rid[i], RF_ACTIVE)) == NULL) {
394			device_printf(sc->sc_dev,
395			    "cannot map register %d\n", i);
396			goto fail;
397		}
398		sc->sc_regt[i] = rman_get_bustag(sc->sc_res[i]);
399		sc->sc_regh[i] = rman_get_bushandle(sc->sc_res[i]);
400	}
401	for (i = 0; i < sc->sc_nires; i++) {
402		sc->sc_irqrid[i] = i;
403		if ((sc->sc_irqres[i] = bus_alloc_resource_any(sc->sc_dev,
404		    SYS_RES_IRQ, &sc->sc_irqrid[i], RF_SHAREABLE | RF_ACTIVE))
405		    == NULL) {
406			if ((sc->sc_flags & CS4231_SBUS) != 0)
407				device_printf(sc->sc_dev,
408				    "cannot allocate interrupt\n");
409			else
410				device_printf(sc->sc_dev, "cannot allocate %s "
411				    "interrupt\n", i == 0 ? "capture" :
412				    "playback");
413			goto fail;
414		}
415	}
416
417	ihandler = cs4231_sbus_intr;
418	for (i = 0; i < sc->sc_nires; i++) {
419		if ((sc->sc_flags & CS4231_EBUS) != 0) {
420			if (i == 0)
421				ihandler = cs4231_ebus_cintr;
422			else
423				ihandler = cs4231_ebus_pintr;
424		}
425		if (snd_setup_intr(sc->sc_dev, sc->sc_irqres[i], INTR_MPSAFE,
426		    ihandler, sc, &sc->sc_ih[i])) {
427			if ((sc->sc_flags & CS4231_SBUS) != 0)
428				device_printf(sc->sc_dev,
429				    "cannot set up interrupt\n");
430			else
431				device_printf(sc->sc_dev, "cannot set up %s "
432				    " interrupt\n", i == 0 ? "capture" :
433				    "playback");
434			goto fail;
435		}
436	}
437
438	sc->sc_bufsz = pcm_getbuffersize(sc->sc_dev, CS4231_MIN_BUF_SZ,
439	    CS4231_DEFAULT_BUF_SZ, CS4231_MAX_BUF_SZ);
440	for (i = 0; i < sc->sc_nires; i++) {
441		if (bus_dma_tag_create(
442		    NULL,			/* parent */
443		    64, 0,			/* alignment, boundary */
444		    BUS_SPACE_MAXADDR_32BIT,	/* lowaddr */
445		    BUS_SPACE_MAXADDR,		/* highaddr */
446		    NULL, NULL,			/* filtfunc, filtfuncarg */
447		    sc->sc_bufsz,		/* maxsize */
448		    1,				/* nsegments */
449		    sc->sc_bufsz,		/* maxsegsz */
450		    BUS_DMA_ALLOCNOW,		/* flags */
451		    NULL,			/* lockfunc */
452		    NULL,			/* lockfuncarg */
453		    &sc->sc_dmat[i])) {
454			if ((sc->sc_flags & CS4231_SBUS) != 0)
455				device_printf(sc->sc_dev,
456				    "cannot allocate DMA tag\n");
457			else
458				device_printf(sc->sc_dev, "cannot allocate %s "
459				    "DMA tag\n", i == 0 ? "capture" :
460				    "playback");
461			goto fail;
462		}
463	}
464	cs4231_enable(sc, CODEC_WARM_RESET);
465	cs4231_getversion(sc);
466	if (mixer_init(sc->sc_dev, &cs4231_mixer_class, sc) != 0)
467		goto fail;
468	if (pcm_register(sc->sc_dev, sc, 1, 1)) {
469		device_printf(sc->sc_dev, "cannot register to pcm\n");
470		goto fail;
471	}
472	if (pcm_addchan(sc->sc_dev, PCMDIR_REC, &cs4231_chan_class, sc) != 0)
473		goto chan_fail;
474	if (pcm_addchan(sc->sc_dev, PCMDIR_PLAY, &cs4231_chan_class, sc) != 0)
475		goto chan_fail;
476	if ((sc->sc_flags & CS4231_SBUS) != 0)
477		snprintf(status, SND_STATUSLEN, "at mem 0x%lx irq %ld bufsz %u",
478		    rman_get_start(sc->sc_res[0]),
479		    rman_get_start(sc->sc_irqres[0]), sc->sc_bufsz);
480	else
481		snprintf(status, SND_STATUSLEN, "at io 0x%lx 0x%lx 0x%lx 0x%lx "
482		    "irq %ld %ld bufsz %u", rman_get_start(sc->sc_res[0]),
483		    rman_get_start(sc->sc_res[1]),
484		    rman_get_start(sc->sc_res[2]),
485		    rman_get_start(sc->sc_res[3]),
486		    rman_get_start(sc->sc_irqres[0]),
487		    rman_get_start(sc->sc_irqres[1]), sc->sc_bufsz);
488	pcm_setstatus(sc->sc_dev, status);
489	return (0);
490
491chan_fail:
492	pcm_unregister(sc->sc_dev);
493fail:
494	cs4231_free_resource(sc);
495	return (ENXIO);
496}
497
498static int
499cs4231_bus_detach(device_t dev)
500{
501	struct cs4231_softc *sc;
502	struct cs4231_channel *pch, *rch;
503	int error;
504
505	sc = pcm_getdevinfo(dev);
506	CS4231_LOCK(sc);
507	pch = &sc->sc_pch;
508	rch = &sc->sc_pch;
509	if (pch->locked || rch->locked) {
510		CS4231_UNLOCK(sc);
511		return (EBUSY);
512	}
513	/*
514	 * Since EBDMA requires valid DMA buffer to drain its FIFO, we need
515	 * real DMA buffer for draining.
516	 */
517	if ((sc->sc_flags & CS4231_EBUS) != 0)
518		cs4231_ebdma_reset(sc);
519	CS4231_UNLOCK(sc);
520	error = pcm_unregister(dev);
521	if (error)
522		return (error);
523	cs4231_free_resource(sc);
524	return (0);
525}
526
527static int
528cs4231_bus_suspend(device_t dev)
529{
530
531	return (ENXIO);
532}
533
534static int
535cs4231_bus_resume(device_t dev)
536{
537
538	return (ENXIO);
539}
540
541static void
542cs4231_getversion(struct cs4231_softc *sc)
543{
544	u_int8_t v;
545
546	v = cs4231_read(sc, CS_MISC_INFO);
547	sc->sc_codecv = v & CS_CODEC_ID_MASK;
548	v = cs4231_read(sc, CS_VERSION_ID);
549	v &= (CS_VERSION_NUMBER | CS_VERSION_CHIPID);
550	sc->sc_chipvid = v;
551	switch(v) {
552		case 0x80:
553			device_printf(sc->sc_dev, "<CS4231 Codec Id. %d>\n",
554			    sc->sc_codecv);
555			break;
556		case 0xa0:
557			device_printf(sc->sc_dev, "<CS4231A Codec Id. %d>\n",
558			    sc->sc_codecv);
559			break;
560		case 0x82:
561			device_printf(sc->sc_dev, "<CS4232 Codec Id. %d>\n",
562			    sc->sc_codecv);
563			break;
564		default:
565			device_printf(sc->sc_dev,
566			    "<Unknown 0x%x Codec Id. %d\n", v, sc->sc_codecv);
567			break;
568	}
569}
570
571static void
572cs4231_ebdma_reset(struct cs4231_softc *sc)
573{
574	int i;
575
576	/* playback */
577	EBDMA_P_WRITE(sc, EBDMA_DCSR,
578	    EBDMA_P_READ(sc, EBDMA_DCSR) & ~(EBDCSR_INTEN | EBDCSR_NEXTEN));
579	EBDMA_P_WRITE(sc, EBDMA_DCSR, EBDCSR_RESET);
580	for (i = CS_TIMEOUT;
581	    i && EBDMA_P_READ(sc, EBDMA_DCSR) & EBDCSR_DRAIN; i--)
582		DELAY(1);
583	if (i == 0)
584		device_printf(sc->sc_dev,
585		    "timeout waiting for playback DMA reset\n");
586	EBDMA_P_WRITE(sc, EBDMA_DCSR, sc->sc_burst);
587	/* capture */
588	EBDMA_C_WRITE(sc, EBDMA_DCSR,
589	    EBDMA_C_READ(sc, EBDMA_DCSR) & ~(EBDCSR_INTEN | EBDCSR_NEXTEN));
590	EBDMA_C_WRITE(sc, EBDMA_DCSR, EBDCSR_RESET);
591	for (i = CS_TIMEOUT;
592	    i && EBDMA_C_READ(sc, EBDMA_DCSR) & EBDCSR_DRAIN; i--)
593		DELAY(1);
594	if (i == 0)
595		device_printf(sc->sc_dev,
596		    "timeout waiting for capture DMA reset\n");
597	EBDMA_C_WRITE(sc, EBDMA_DCSR, sc->sc_burst);
598}
599
600static void
601cs4231_power_reset(struct cs4231_softc *sc, int how)
602{
603	u_int32_t v;
604	int i;
605
606	if ((sc->sc_flags & CS4231_SBUS) != 0) {
607		APC_WRITE(sc, APC_CSR, APC_CSR_RESET);
608		DELAY(10);
609		APC_WRITE(sc, APC_CSR, 0);
610		DELAY(10);
611		APC_WRITE(sc,
612		    APC_CSR, APC_READ(sc, APC_CSR) | APC_CSR_CODEC_RESET);
613		DELAY(20);
614		APC_WRITE(sc,
615		    APC_CSR, APC_READ(sc, APC_CSR) & (~APC_CSR_CODEC_RESET));
616	} else {
617		v = AUXIO_READ(sc, AUXIO_CODEC);
618		if (how == CODEC_WARM_RESET && v != 0) {
619			AUXIO_WRITE(sc, AUXIO_CODEC, 0);
620			DELAY(20);
621		} else if (how == CODEC_COLD_RESET){
622			AUXIO_WRITE(sc, AUXIO_CODEC, 1);
623			DELAY(20);
624			AUXIO_WRITE(sc, AUXIO_CODEC, 0);
625			DELAY(20);
626		}
627		cs4231_ebdma_reset(sc);
628	}
629
630	for (i = CS_TIMEOUT;
631	    i && CS_READ(sc, CS4231_IADDR) == CS_IN_INIT; i--)
632		DELAY(10);
633	if (i == 0)
634		device_printf(sc->sc_dev, "timeout waiting for reset\n");
635
636	/* turn on cs4231 mode */
637	cs4231_write(sc, CS_MISC_INFO,
638	    cs4231_read(sc, CS_MISC_INFO) | CS_MODE2);
639	/* enable interupts & clear CSR */
640        cs4231_write(sc, CS_PIN_CONTROL,
641            cs4231_read(sc, CS_PIN_CONTROL) | INTERRUPT_ENABLE);
642	CS_WRITE(sc, CS4231_STATUS, 0);
643	/* enable DAC output */
644	cs4231_write(sc, CS_LEFT_OUTPUT_CONTROL,
645	    cs4231_read(sc, CS_LEFT_OUTPUT_CONTROL) & ~OUTPUT_MUTE);
646	cs4231_write(sc, CS_RIGHT_OUTPUT_CONTROL,
647	    cs4231_read(sc, CS_RIGHT_OUTPUT_CONTROL) & ~OUTPUT_MUTE);
648	/* mute AUX1 since it generates noises */
649	cs4231_write(sc, CS_LEFT_AUX1_CONTROL,
650	    cs4231_read(sc, CS_LEFT_AUX1_CONTROL) | AUX_INPUT_MUTE);
651	cs4231_write(sc, CS_RIGHT_AUX1_CONTROL,
652	    cs4231_read(sc, CS_RIGHT_AUX1_CONTROL) | AUX_INPUT_MUTE);
653	/* protect buffer underrun and set output level to 0dB */
654	cs4231_write(sc, CS_ALT_FEATURE1,
655	    cs4231_read(sc, CS_ALT_FEATURE1) | CS_DAC_ZERO | CS_OUTPUT_LVL);
656	/* enable high pass filter, dual xtal was disabled due to noises */
657	cs4231_write(sc, CS_ALT_FEATURE2,
658	    cs4231_read(sc, CS_ALT_FEATURE2) | CS_HPF_ENABLE);
659}
660
661static int
662cs4231_enable(struct cs4231_softc *sc, int how)
663{
664	cs4231_power_reset(sc, how);
665	sc->sc_enabled = 1;
666        return (0);
667}
668
669static void
670cs4231_disable(struct cs4231_softc *sc)
671{
672	u_int8_t v;
673
674	CS4231_LOCK_ASSERT(sc);
675
676	if (sc->sc_enabled == 0)
677		return;
678	sc->sc_enabled = 0;
679	CS4231_UNLOCK(sc);
680	cs4231_halt(&sc->sc_pch);
681	cs4231_halt(&sc->sc_rch);
682	CS4231_LOCK(sc);
683	v = cs4231_read(sc, CS_PIN_CONTROL) & ~INTERRUPT_ENABLE;
684	cs4231_write(sc, CS_PIN_CONTROL, v);
685
686	if ((sc->sc_flags & CS4231_SBUS) != 0) {
687		APC_WRITE(sc, APC_CSR, APC_CSR_RESET);
688		DELAY(10);
689		APC_WRITE(sc, APC_CSR, 0);
690		DELAY(10);
691	} else
692		cs4231_ebdma_reset(sc);
693}
694
695static void
696cs4231_free_resource(struct cs4231_softc *sc)
697{
698	int i;
699
700	CS4231_LOCK(sc);
701	cs4231_disable(sc);
702	CS4231_UNLOCK(sc);
703	for (i = 0; i < sc->sc_nires; i++) {
704		if (sc->sc_irqres[i]) {
705			if (sc->sc_ih[i]) {
706				bus_teardown_intr(sc->sc_dev, sc->sc_irqres[i],
707				    sc->sc_ih[i]);
708				sc->sc_ih[i] = NULL;
709			}
710			bus_release_resource(sc->sc_dev, SYS_RES_IRQ,
711			    sc->sc_irqrid[i], sc->sc_irqres[i]);
712			sc->sc_irqres[i] = NULL;
713		}
714	}
715	for (i = 0; i < sc->sc_nires; i++) {
716		if (sc->sc_dmat[i])
717			bus_dma_tag_destroy(sc->sc_dmat[i]);
718	}
719	for (i = 0; i < sc->sc_nmres; i++) {
720		if (sc->sc_res[i])
721			bus_release_resource(sc->sc_dev, sc->sc_rtype,
722			    sc->sc_rid[i], sc->sc_res[i]);
723	}
724	snd_mtxfree(sc->sc_lock);
725	free(sc, M_DEVBUF);
726}
727
728static void
729cs4231_write(struct cs4231_softc *sc, u_int8_t r, u_int8_t v)
730{
731	CS_WRITE(sc, CS4231_IADDR, r);
732	CS_WRITE(sc, CS4231_IDATA, v);
733}
734
735static u_int8_t
736cs4231_read(struct cs4231_softc *sc, u_int8_t r)
737{
738	CS_WRITE(sc, CS4231_IADDR, r);
739	return (CS_READ(sc, CS4231_IDATA));
740}
741
742static void
743cs4231_sbus_intr(void *arg)
744{
745	struct cs4231_softc *sc;
746	struct cs4231_channel *pch, *rch;
747	u_int32_t csr;
748	u_int8_t status;
749
750	sc = arg;
751	CS4231_LOCK(sc);
752
753	csr = APC_READ(sc, APC_CSR);
754	if ((csr & APC_CSR_GI) == 0) {
755		CS4231_UNLOCK(sc);
756		return;
757	}
758	APC_WRITE(sc, APC_CSR, csr);
759
760	if ((csr & APC_CSR_EIE) && (csr & APC_CSR_EI)) {
761		status = cs4231_read(sc, CS_TEST_AND_INIT);
762		device_printf(sc->sc_dev,
763		    "apc error interrupt : stat = 0x%x\n", status);
764	}
765
766	pch = rch = NULL;
767	if ((csr & APC_CSR_PMIE) && (csr & APC_CSR_PMI)) {
768		u_long nextaddr, saddr;
769		u_int32_t togo;
770
771		pch = &sc->sc_pch;
772		togo = pch->togo;
773		saddr = sndbuf_getbufaddr(pch->buffer);
774		nextaddr = pch->nextaddr + togo;
775		if (nextaddr >=  saddr + sndbuf_getsize(pch->buffer))
776			nextaddr = saddr;
777		APC_WRITE(sc, APC_PNVA, nextaddr);
778		APC_WRITE(sc, APC_PNC, togo);
779		pch->nextaddr = nextaddr;
780	}
781
782	if ((csr & APC_CSR_CIE) && (csr & APC_CSR_CI) && (csr & APC_CSR_CD)) {
783		u_long nextaddr, saddr;
784		u_int32_t togo;
785
786		rch = &sc->sc_rch;
787		togo = rch->togo;
788		saddr = sndbuf_getbufaddr(rch->buffer);
789		nextaddr = rch->nextaddr + togo;
790		if (nextaddr >= saddr + sndbuf_getsize(rch->buffer))
791			nextaddr = saddr;
792		APC_WRITE(sc, APC_CNVA, nextaddr);
793		APC_WRITE(sc, APC_CNC, togo);
794		rch->nextaddr = nextaddr;
795	}
796	CS4231_UNLOCK(sc);
797	if (pch)
798		chn_intr(pch->channel);
799	if (rch)
800		chn_intr(rch->channel);
801}
802
803/* playback interrupt handler */
804static void
805cs4231_ebus_pintr(void *arg)
806{
807	struct cs4231_softc *sc;
808	struct cs4231_channel *ch;
809	u_int32_t csr;
810	u_int8_t status;
811
812	sc = arg;
813	CS4231_LOCK(sc);
814
815	csr = EBDMA_P_READ(sc, EBDMA_DCSR);
816	if ((csr & EBDCSR_INT) == 0) {
817		CS4231_UNLOCK(sc);
818		return;
819	}
820
821	if ((csr & EBDCSR_ERR)) {
822		status = cs4231_read(sc, CS_TEST_AND_INIT);
823		device_printf(sc->sc_dev,
824		    "ebdma error interrupt : stat = 0x%x\n", status);
825	}
826	EBDMA_P_WRITE(sc, EBDMA_DCSR, csr | EBDCSR_TC);
827
828	ch = NULL;
829	if (csr & EBDCSR_TC) {
830		u_long nextaddr, saddr;
831		u_int32_t togo;
832
833		ch = &sc->sc_pch;
834		togo = ch->togo;
835		saddr = sndbuf_getbufaddr(ch->buffer);
836		nextaddr = ch->nextaddr + togo;
837		if (nextaddr >=  saddr + sndbuf_getsize(ch->buffer))
838			nextaddr = saddr;
839		/*
840		 * EBDMA_DCNT is loaded automatically
841		 * EBDMA_P_WRITE(sc, EBDMA_DCNT, togo);
842		 */
843		EBDMA_P_WRITE(sc, EBDMA_DADDR, nextaddr);
844		ch->nextaddr = nextaddr;
845	}
846	CS4231_UNLOCK(sc);
847	if (ch)
848		chn_intr(ch->channel);
849}
850
851/* capture interrupt handler */
852static void
853cs4231_ebus_cintr(void *arg)
854{
855	struct cs4231_softc *sc;
856	struct cs4231_channel *ch;
857	u_int32_t csr;
858	u_int8_t status;
859
860	sc = arg;
861	CS4231_LOCK(sc);
862
863	csr = EBDMA_C_READ(sc, EBDMA_DCSR);
864	if ((csr & EBDCSR_INT) == 0) {
865		CS4231_UNLOCK(sc);
866		return;
867	}
868	if ((csr & EBDCSR_ERR)) {
869		status = cs4231_read(sc, CS_TEST_AND_INIT);
870		device_printf(sc->sc_dev,
871		    "dma error interrupt : stat = 0x%x\n", status);
872	}
873	EBDMA_C_WRITE(sc, EBDMA_DCSR, csr | EBDCSR_TC);
874
875	ch = NULL;
876	if (csr & EBDCSR_TC) {
877		u_long nextaddr, saddr;
878		u_int32_t togo;
879
880		ch = &sc->sc_rch;
881		togo = ch->togo;
882		saddr = sndbuf_getbufaddr(ch->buffer);
883		nextaddr = ch->nextaddr + togo;
884		if (nextaddr >= saddr + sndbuf_getblksz(ch->buffer))
885			nextaddr = saddr;
886		/*
887		 * EBDMA_DCNT is loaded automatically
888		 * EBDMA_C_WRITE(sc, EBDMA_DCNT, togo);
889		 */
890		EBDMA_C_WRITE(sc, EBDMA_DADDR, nextaddr);
891		ch->nextaddr = nextaddr;
892	}
893	CS4231_UNLOCK(sc);
894	if (ch)
895		chn_intr(ch->channel);
896}
897
898static const struct mix_table cs4231_mix_table[SOUND_MIXER_NRDEVICES][2] = {
899	[SOUND_MIXER_PCM] = {
900		{ CS_LEFT_OUTPUT_CONTROL,	6, OUTPUT_MUTE, 0, 1, 1, 0 },
901		{ CS_RIGHT_OUTPUT_CONTROL,	6, OUTPUT_MUTE, 0, 1, 1, 0 }
902	},
903	[SOUND_MIXER_SPEAKER] = {
904		{ CS_MONO_IO_CONTROL,		4, MONO_OUTPUT_MUTE, 0, 1, 1, 0 },
905		{ CS_REG_NONE,			0, 0, 0, 0, 1, 0 }
906	},
907	[SOUND_MIXER_LINE] = {
908		{ CS_LEFT_LINE_CONTROL,		5, LINE_INPUT_MUTE, 0, 1, 1, 1 },
909		{ CS_RIGHT_LINE_CONTROL,	5, LINE_INPUT_MUTE, 0, 1, 1, 1 }
910	},
911	/*
912	 * AUX1 : removed intentionally since it generates noises
913	 * AUX2 : Ultra1/Ultra2 has no internal CD-ROM audio in
914	 */
915	[SOUND_MIXER_CD] = {
916		{ CS_LEFT_AUX2_CONTROL,		5, LINE_INPUT_MUTE, 0, 1, 1, 1 },
917		{ CS_RIGHT_AUX2_CONTROL,	5, LINE_INPUT_MUTE, 0, 1, 1, 1 }
918	},
919	[SOUND_MIXER_MIC] = {
920		{ CS_LEFT_INPUT_CONTROL,	4, 0, 0, 0, 1, 1 },
921		{ CS_RIGHT_INPUT_CONTROL,	4, 0, 0, 0, 1, 1 }
922	},
923	[SOUND_MIXER_IGAIN] = {
924		{ CS_LEFT_INPUT_CONTROL,	4, 0, 0, 1, 0 },
925		{ CS_RIGHT_INPUT_CONTROL,	4, 0, 0, 1, 0 }
926	}
927};
928
929static int
930cs4231_mixer_init(struct snd_mixer *m)
931{
932	u_int32_t v;
933	int i;
934
935	v = 0;
936	for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
937		if (cs4231_mix_table[i][0].avail != 0)
938			v |= (1 << i);
939	mix_setdevs(m, v);
940	v = 0;
941	for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
942		if (cs4231_mix_table[i][0].recdev != 0)
943			v |= (1 << i);
944	mix_setrecdevs(m, v);
945	return (0);
946}
947
948static void
949cs4231_mixer_set_value(struct cs4231_softc *sc,  const struct mix_table *mt,
950    u_int8_t v)
951{
952	u_int8_t mask, reg;
953	u_int8_t old, shift, val;
954
955	if (mt->avail == 0 || mt->reg == CS_REG_NONE)
956		return;
957	reg = mt->reg;
958	if (mt->neg != 0)
959		val = 100 - v;
960	else
961		val = v;
962	mask = (1 << mt->bits) - 1;
963	val = ((val * mask) + 50) / 100;
964	shift = mt->shift;
965	val <<= shift;
966	if (v == 0)
967		val |= mt->mute;
968	old = cs4231_read(sc, reg);
969	old &= ~(mt->mute | (mask << shift));
970	val |= old;
971	if (reg == CS_LEFT_INPUT_CONTROL || reg == CS_RIGHT_INPUT_CONTROL) {
972		if ((val & (mask << shift)) != 0)
973			val |= ADC_INPUT_GAIN_ENABLE;
974		else
975			val &= ~ADC_INPUT_GAIN_ENABLE;
976	}
977	cs4231_write(sc, reg, val);
978}
979
980static int
981cs4231_mixer_set(struct snd_mixer *m, u_int32_t dev, u_int32_t left,
982    u_int32_t right)
983{
984	struct cs4231_softc *sc;
985
986	sc = mix_getdevinfo(m);
987	CS4231_LOCK(sc);
988	cs4231_mixer_set_value(sc, &cs4231_mix_table[dev][0], left);
989	cs4231_mixer_set_value(sc, &cs4231_mix_table[dev][1], right);
990	CS4231_UNLOCK(sc);
991
992	return (left | (right << 8));
993}
994
995static int
996cs4231_mixer_setrecsrc(struct snd_mixer *m, u_int32_t src)
997{
998	struct cs4231_softc *sc;
999	u_int8_t	v;
1000
1001	sc = mix_getdevinfo(m);
1002	switch (src) {
1003	case SOUND_MASK_LINE:
1004		v = CS_IN_LINE;
1005		break;
1006
1007	case SOUND_MASK_CD:
1008		v = CS_IN_DAC;
1009		break;
1010
1011	case SOUND_MASK_MIC:
1012	default:
1013		v = CS_IN_MIC;
1014		src = SOUND_MASK_MIC;
1015		break;
1016	}
1017	CS4231_LOCK(sc);
1018	cs4231_write(sc, CS_LEFT_INPUT_CONTROL,
1019	    (cs4231_read(sc, CS_LEFT_INPUT_CONTROL) & CS_IN_MASK) | v);
1020	cs4231_write(sc, CS_RIGHT_INPUT_CONTROL,
1021	    (cs4231_read(sc, CS_RIGHT_INPUT_CONTROL) & CS_IN_MASK) | v);
1022	CS4231_UNLOCK(sc);
1023
1024	return (src);
1025}
1026
1027static void *
1028cs4231_chan_init(kobj_t obj, void *dev, struct snd_dbuf *b,
1029    struct pcm_channel *c, int dir)
1030{
1031	struct cs4231_softc *sc;
1032	struct cs4231_channel *ch;
1033	bus_dma_tag_t dmat;
1034
1035	sc = dev;
1036	ch = (dir == PCMDIR_PLAY) ? &sc->sc_pch : &sc->sc_rch;
1037	ch->parent = sc;
1038	ch->channel = c;
1039	ch->dir = dir;
1040	ch->buffer = b;
1041	if ((sc->sc_flags & CS4231_SBUS) != 0)
1042		dmat = sc->sc_dmat[0];
1043	else {
1044		if (dir == PCMDIR_PLAY)
1045			dmat = sc->sc_dmat[1];
1046		else
1047			dmat = sc->sc_dmat[0];
1048	}
1049	if (sndbuf_alloc(ch->buffer, dmat, sc->sc_bufsz) != 0)
1050		return (NULL);
1051	DPRINTF(("%s channel addr: 0x%lx\n", dir == PCMDIR_PLAY ? "playback" :
1052	    "capture", sndbuf_getbufaddr(ch->buffer)));
1053
1054	return (ch);
1055}
1056
1057static int
1058cs4231_chan_setformat(kobj_t obj, void *data, u_int32_t format)
1059{
1060	struct cs4231_softc *sc;
1061	struct cs4231_channel *ch;
1062	u_int32_t encoding;
1063	u_int8_t fs, v;
1064
1065	ch = data;
1066	sc = ch->parent;
1067
1068	CS4231_LOCK(sc);
1069	if (ch->format == format) {
1070		CS4231_UNLOCK(sc);
1071		return (0);
1072	}
1073
1074	encoding = format & ~AFMT_STEREO;
1075	fs = 0;
1076	switch (encoding) {
1077	case AFMT_U8:
1078		fs = CS_AFMT_U8;
1079		break;
1080	case AFMT_MU_LAW:
1081		fs = CS_AFMT_MU_LAW;
1082		break;
1083	case AFMT_S16_LE:
1084		fs = CS_AFMT_S16_LE;
1085		break;
1086	case AFMT_A_LAW:
1087		fs = CS_AFMT_A_LAW;
1088		break;
1089	case AFMT_IMA_ADPCM:
1090		fs = CS_AFMT_IMA_ADPCM;
1091		break;
1092	case AFMT_S16_BE:
1093		fs = CS_AFMT_S16_BE;
1094		break;
1095	default:
1096		fs = CS_AFMT_U8;
1097		format = AFMT_U8;
1098		break;
1099	}
1100
1101	if (format & AFMT_STEREO)
1102		fs |= CS_AFMT_STEREO;
1103
1104	DPRINTF(("FORMAT: %s : 0x%x\n", ch->dir == PCMDIR_PLAY ? "playback" :
1105	    "capture", format));
1106	v = cs4231_read(sc, CS_CLOCK_DATA_FORMAT);
1107	v &= CS_CLOCK_DATA_FORMAT_MASK;
1108	fs |= v;
1109	cs4231_chan_fs(sc, ch->dir, fs);
1110	ch->format = format;
1111	CS4231_UNLOCK(sc);
1112
1113	return (0);
1114}
1115
1116static int
1117cs4231_chan_setspeed(kobj_t obj, void *data, u_int32_t speed)
1118{
1119	typedef struct {
1120		u_int32_t speed;
1121		u_int8_t bits;
1122	} speed_struct;
1123
1124	const static speed_struct speed_table[] = {
1125		{5510,  (0 << 1) | CLOCK_XTAL2},
1126		{5510,  (0 << 1) | CLOCK_XTAL2},
1127		{6620,  (7 << 1) | CLOCK_XTAL2},
1128		{8000,  (0 << 1) | CLOCK_XTAL1},
1129		{9600,  (7 << 1) | CLOCK_XTAL1},
1130		{11025, (1 << 1) | CLOCK_XTAL2},
1131		{16000, (1 << 1) | CLOCK_XTAL1},
1132		{18900, (2 << 1) | CLOCK_XTAL2},
1133		{22050, (3 << 1) | CLOCK_XTAL2},
1134		{27420, (2 << 1) | CLOCK_XTAL1},
1135		{32000, (3 << 1) | CLOCK_XTAL1},
1136		{33075, (6 << 1) | CLOCK_XTAL2},
1137		{33075, (4 << 1) | CLOCK_XTAL2},
1138		{44100, (5 << 1) | CLOCK_XTAL2},
1139		{48000, (6 << 1) | CLOCK_XTAL1},
1140	};
1141
1142	struct cs4231_softc *sc;
1143	struct cs4231_channel *ch;
1144	int i, n, sel;
1145	u_int8_t fs;
1146
1147	ch = data;
1148	sc = ch->parent;
1149	CS4231_LOCK(sc);
1150	if (ch->speed == speed) {
1151		CS4231_UNLOCK(sc);
1152		return (speed);
1153	}
1154	n = sizeof(speed_table) / sizeof(speed_struct);
1155
1156	for (i = 1, sel =0; i < n - 1; i++)
1157		if (abs(speed - speed_table[i].speed) <
1158		    abs(speed - speed_table[sel].speed))
1159			sel = i;
1160	DPRINTF(("SPEED: %s : %dHz -> %dHz\n", ch->dir == PCMDIR_PLAY ?
1161	    "playback" : "capture", speed, speed_table[sel].speed));
1162	speed = speed_table[sel].speed;
1163
1164	fs = cs4231_read(sc, CS_CLOCK_DATA_FORMAT);
1165	fs &= ~CS_CLOCK_DATA_FORMAT_MASK;
1166	fs |= speed_table[sel].bits;
1167	cs4231_chan_fs(sc, ch->dir, fs);
1168	ch->speed = speed;
1169	CS4231_UNLOCK(sc);
1170
1171	return (speed);
1172}
1173
1174static void
1175cs4231_chan_fs(struct cs4231_softc *sc, int dir, u_int8_t fs)
1176{
1177	int i, doreset;
1178#ifdef CS4231_AUTO_CALIBRATION
1179	u_int8_t v;
1180#endif
1181
1182	CS4231_LOCK_ASSERT(sc);
1183
1184	/* set autocalibration */
1185	doreset = 0;
1186#ifdef CS4231_AUTO_CALIBRATION
1187	v = cs4231_read(sc, CS_INTERFACE_CONFIG) | AUTO_CAL_ENABLE;
1188	CS_WRITE(sc, CS4231_IADDR, MODE_CHANGE_ENABLE);
1189	CS_WRITE(sc, CS4231_IADDR, MODE_CHANGE_ENABLE | CS_INTERFACE_CONFIG);
1190	CS_WRITE(sc, CS4231_IDATA, v);
1191#endif
1192
1193	/*
1194	 * We always need to write CS_CLOCK_DATA_FORMAT register since
1195	 * the clock frequency is shared with playback/capture.
1196	 */
1197	CS_WRITE(sc, CS4231_IADDR, MODE_CHANGE_ENABLE | CS_CLOCK_DATA_FORMAT);
1198	CS_WRITE(sc, CS4231_IDATA, fs);
1199	CS_READ(sc, CS4231_IDATA);
1200	CS_READ(sc, CS4231_IDATA);
1201	for (i = CS_TIMEOUT;
1202	    i && CS_READ(sc, CS4231_IADDR) == CS_IN_INIT; i--)
1203		DELAY(10);
1204	if (i == 0) {
1205		device_printf(sc->sc_dev, "timeout setting playback speed\n");
1206		doreset++;
1207	}
1208
1209	/*
1210	 * capture channel
1211	 * cs4231 doesn't allow seperate fs setup for playback/capture.
1212	 * I believe this will break full-duplex operation.
1213	 */
1214	if (dir == PCMDIR_REC) {
1215		CS_WRITE(sc, CS4231_IADDR, MODE_CHANGE_ENABLE | CS_REC_FORMAT);
1216		CS_WRITE(sc, CS4231_IDATA, fs);
1217		CS_READ(sc, CS4231_IDATA);
1218		CS_READ(sc, CS4231_IDATA);
1219		for (i = CS_TIMEOUT;
1220		    i && CS_READ(sc, CS4231_IADDR) == CS_IN_INIT; i--)
1221			DELAY(10);
1222		if (i == 0) {
1223			device_printf(sc->sc_dev,
1224			    "timeout setting capture format\n");
1225			doreset++;
1226		}
1227	}
1228
1229	CS_WRITE(sc, CS4231_IADDR, 0);
1230	for (i = CS_TIMEOUT;
1231	    i && CS_READ(sc, CS4231_IADDR) == CS_IN_INIT; i--)
1232		DELAY(10);
1233	if (i == 0) {
1234		device_printf(sc->sc_dev, "timeout waiting for !MCE\n");
1235		doreset++;
1236	}
1237
1238#ifdef CS4231_AUTO_CALIBRATION
1239	CS_WRITE(sc, CS4231_IADDR, CS_TEST_AND_INIT);
1240	for (i = CS_TIMEOUT;
1241	    i && CS_READ(sc, CS4231_IDATA) & AUTO_CAL_IN_PROG; i--)
1242		DELAY(10);
1243	if (i == 0) {
1244		device_printf(sc->sc_dev,
1245		    "timeout waiting for autocalibration\n");
1246		doreset++;
1247	}
1248#endif
1249	if (doreset) {
1250		/*
1251		 * Maybe the last resort to avoid a dreadful message like
1252		 * "pcm0:play:0: play interrupt timeout, channel dead" would
1253		 * be hardware reset.
1254		 */
1255		device_printf(sc->sc_dev, "trying to hardware reset\n");
1256		cs4231_disable(sc);
1257		cs4231_enable(sc, CODEC_COLD_RESET);
1258		CS4231_UNLOCK(sc); /* XXX */
1259		if (mixer_reinit(sc->sc_dev) != 0)
1260			device_printf(sc->sc_dev,
1261			    "unable to reinitialize the mixer\n");
1262		CS4231_LOCK(sc);
1263	}
1264}
1265
1266static int
1267cs4231_chan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
1268{
1269	struct cs4231_softc *sc;
1270	struct cs4231_channel *ch;
1271	int nblks, error;
1272
1273	ch = data;
1274	sc = ch->parent;
1275
1276	if (blocksize > CS4231_MAX_BLK_SZ)
1277		blocksize = CS4231_MAX_BLK_SZ;
1278	nblks = sc->sc_bufsz / blocksize;
1279	error = sndbuf_resize(ch->buffer, nblks, blocksize);
1280	if (error != 0)
1281		device_printf(sc->sc_dev,
1282		    "unable to block size, blksz = %d, error = %d\n",
1283		    blocksize, error);
1284
1285        return (blocksize);
1286}
1287
1288static int
1289cs4231_chan_trigger(kobj_t obj, void *data, int go)
1290{
1291	struct cs4231_channel *ch;
1292
1293	ch = data;
1294	switch (go) {
1295	case PCMTRIG_EMLDMAWR:
1296	case PCMTRIG_EMLDMARD:
1297		break;
1298	case PCMTRIG_START:
1299		cs4231_trigger(ch);
1300		break;
1301	case PCMTRIG_ABORT:
1302	case PCMTRIG_STOP:
1303		cs4231_halt(ch);
1304		break;
1305	default:
1306		break;
1307	}
1308
1309	return (0);
1310}
1311
1312static int
1313cs4231_chan_getptr(kobj_t obj, void *data)
1314{
1315	struct cs4231_softc *sc;
1316	struct cs4231_channel *ch;
1317	u_int32_t cur;
1318	int ptr, sz;
1319
1320	ch = data;
1321	sc = ch->parent;
1322
1323	CS4231_LOCK(sc);
1324	if ((sc->sc_flags & CS4231_SBUS) != 0)
1325		cur = (ch->dir == PCMDIR_PLAY) ? APC_READ(sc, APC_PVA) :
1326		    APC_READ(sc, APC_CVA);
1327	else
1328		cur = (ch->dir == PCMDIR_PLAY) ? EBDMA_P_READ(sc, EBDMA_DADDR) :
1329			EBDMA_C_READ(sc, EBDMA_DADDR);
1330	sz = sndbuf_getsize(ch->buffer);
1331	ptr = cur - sndbuf_getbufaddr(ch->buffer) + sz;
1332	CS4231_UNLOCK(sc);
1333
1334	ptr %= sz;
1335	return (ptr);
1336}
1337
1338static struct pcmchan_caps *
1339cs4231_chan_getcaps(kobj_t obj, void *data)
1340{
1341
1342	return (&cs4231_caps);
1343}
1344
1345static void
1346cs4231_trigger(struct cs4231_channel *ch)
1347{
1348	struct cs4231_softc *sc;
1349
1350	sc = ch->parent;
1351	if ((sc->sc_flags & CS4231_SBUS) != 0)
1352		cs4231_apcdma_trigger(sc, ch);
1353	else
1354		cs4231_ebdma_trigger(sc, ch);
1355}
1356
1357static void
1358cs4231_apcdma_trigger(struct cs4231_softc *sc, struct cs4231_channel *ch)
1359{
1360	u_int32_t csr, togo;
1361	u_int32_t nextaddr;
1362
1363	CS4231_LOCK(sc);
1364	if (ch->locked) {
1365		device_printf(sc->sc_dev, "%s channel already triggered\n",
1366		    ch->dir == PCMDIR_PLAY ? "playback" : "capture");
1367		CS4231_UNLOCK(sc);
1368		return;
1369	}
1370
1371	nextaddr = sndbuf_getbufaddr(ch->buffer);
1372	togo = sndbuf_getsize(ch->buffer) / 2;
1373	if (togo > CS4231_MAX_APC_DMA_SZ)
1374		togo = CS4231_MAX_APC_DMA_SZ;
1375	ch->togo = togo;
1376	if (ch->dir == PCMDIR_PLAY) {
1377		DPRINTF(("TRG: PNVA = 0x%x, togo = 0x%x\n", nextaddr, togo));
1378
1379		cs4231_read(sc, CS_TEST_AND_INIT); /* clear pending error */
1380		csr = APC_READ(sc, APC_CSR);
1381		APC_WRITE(sc, APC_PNVA, nextaddr);
1382		APC_WRITE(sc, APC_PNC, togo);
1383
1384		if ((csr & APC_CSR_PDMA_GO) == 0 ||
1385		    (csr & APC_CSR_PPAUSE) != 0) {
1386			APC_WRITE(sc, APC_CSR, APC_READ(sc, APC_CSR) &
1387			    ~(APC_CSR_PIE | APC_CSR_PPAUSE));
1388			APC_WRITE(sc, APC_CSR, APC_READ(sc, APC_CSR) |
1389			    APC_CSR_GIE | APC_CSR_PIE | APC_CSR_EIE |
1390			    APC_CSR_EI | APC_CSR_PMIE | APC_CSR_PDMA_GO);
1391			cs4231_write(sc, CS_INTERFACE_CONFIG,
1392			    cs4231_read(sc, CS_INTERFACE_CONFIG) |
1393			    PLAYBACK_ENABLE);
1394		}
1395		/* load next address */
1396		if (APC_READ(sc, APC_CSR) & APC_CSR_PD) {
1397			nextaddr += togo;
1398			APC_WRITE(sc, APC_PNVA, nextaddr);
1399			APC_WRITE(sc, APC_PNC, togo);
1400		}
1401	} else {
1402		DPRINTF(("TRG: CNVA = 0x%x, togo = 0x%x\n", nextaddr, togo));
1403
1404		cs4231_read(sc, CS_TEST_AND_INIT); /* clear pending error */
1405		APC_WRITE(sc, APC_CNVA, nextaddr);
1406		APC_WRITE(sc, APC_CNC, togo);
1407		csr = APC_READ(sc, APC_CSR);
1408		if ((csr & APC_CSR_CDMA_GO) == 0 ||
1409		    (csr & APC_CSR_CPAUSE) != 0) {
1410			csr &= APC_CSR_CPAUSE;
1411			csr |= APC_CSR_GIE | APC_CSR_CMIE | APC_CSR_CIE |
1412			    APC_CSR_EI | APC_CSR_CDMA_GO;
1413			APC_WRITE(sc, APC_CSR, csr);
1414			cs4231_write(sc, CS_INTERFACE_CONFIG,
1415			    cs4231_read(sc, CS_INTERFACE_CONFIG) |
1416			    CAPTURE_ENABLE);
1417		}
1418		/* load next address */
1419		if (APC_READ(sc, APC_CSR) & APC_CSR_CD) {
1420			nextaddr += togo;
1421			APC_WRITE(sc, APC_CNVA, nextaddr);
1422			APC_WRITE(sc, APC_CNC, togo);
1423		}
1424	}
1425	ch->nextaddr = nextaddr;
1426	ch->locked = 1;
1427	CS4231_UNLOCK(sc);
1428}
1429
1430static void
1431cs4231_ebdma_trigger(struct cs4231_softc *sc, struct cs4231_channel *ch)
1432{
1433	u_int32_t csr, togo;
1434	u_int32_t nextaddr;
1435
1436	CS4231_LOCK(sc);
1437	if (ch->locked) {
1438		device_printf(sc->sc_dev, "%s channel already triggered\n",
1439		    ch->dir == PCMDIR_PLAY ? "playback" : "capture");
1440		CS4231_UNLOCK(sc);
1441		return;
1442	}
1443
1444	nextaddr = sndbuf_getbufaddr(ch->buffer);
1445	togo = sndbuf_getsize(ch->buffer) / 2;
1446	if (togo % 64 == 0)
1447		sc->sc_burst = EBDCSR_BURST_16;
1448	else if (togo % 32 == 0)
1449		sc->sc_burst = EBDCSR_BURST_8;
1450	else if (togo % 16 == 0)
1451		sc->sc_burst = EBDCSR_BURST_4;
1452	else
1453		sc->sc_burst = EBDCSR_BURST_1;
1454	ch->togo = togo;
1455	DPRINTF(("TRG: DNAR = 0x%x, togo = 0x%x\n", nextaddr, togo));
1456	if (ch->dir == PCMDIR_PLAY) {
1457		cs4231_read(sc, CS_TEST_AND_INIT); /* clear pending error */
1458		csr = EBDMA_P_READ(sc, EBDMA_DCSR);
1459
1460		if (csr & EBDCSR_DMAEN) {
1461			EBDMA_P_WRITE(sc, EBDMA_DCNT, togo);
1462			EBDMA_P_WRITE(sc, EBDMA_DADDR, nextaddr);
1463		} else {
1464			EBDMA_P_WRITE(sc, EBDMA_DCSR, EBDCSR_RESET);
1465			EBDMA_P_WRITE(sc, EBDMA_DCSR, sc->sc_burst);
1466			EBDMA_P_WRITE(sc, EBDMA_DCNT, togo);
1467			EBDMA_P_WRITE(sc, EBDMA_DADDR, nextaddr);
1468
1469			EBDMA_P_WRITE(sc, EBDMA_DCSR, sc->sc_burst |
1470			    EBDCSR_DMAEN | EBDCSR_INTEN | EBDCSR_CNTEN |
1471			    EBDCSR_NEXTEN);
1472			cs4231_write(sc, CS_INTERFACE_CONFIG,
1473			    cs4231_read(sc, CS_INTERFACE_CONFIG) |
1474			    PLAYBACK_ENABLE);
1475		}
1476		/* load next address */
1477		if (EBDMA_P_READ(sc, EBDMA_DCSR) & EBDCSR_A_LOADED) {
1478			nextaddr += togo;
1479			EBDMA_P_WRITE(sc, EBDMA_DCNT, togo);
1480			EBDMA_P_WRITE(sc, EBDMA_DADDR, nextaddr);
1481		}
1482	} else {
1483		cs4231_read(sc, CS_TEST_AND_INIT); /* clear pending error */
1484		csr = EBDMA_C_READ(sc, EBDMA_DCSR);
1485
1486		if (csr & EBDCSR_DMAEN) {
1487			EBDMA_C_WRITE(sc, EBDMA_DCNT, togo);
1488			EBDMA_C_WRITE(sc, EBDMA_DADDR, nextaddr);
1489		} else {
1490			EBDMA_C_WRITE(sc, EBDMA_DCSR, EBDCSR_RESET);
1491			EBDMA_C_WRITE(sc, EBDMA_DCSR, sc->sc_burst);
1492			EBDMA_C_WRITE(sc, EBDMA_DCNT, togo);
1493			EBDMA_C_WRITE(sc, EBDMA_DADDR, nextaddr);
1494
1495			EBDMA_C_WRITE(sc, EBDMA_DCSR, sc->sc_burst |
1496			    EBDCSR_WRITE | EBDCSR_DMAEN | EBDCSR_INTEN |
1497			    EBDCSR_CNTEN | EBDCSR_NEXTEN);
1498			cs4231_write(sc, CS_INTERFACE_CONFIG,
1499			    cs4231_read(sc, CS_INTERFACE_CONFIG) |
1500			    CAPTURE_ENABLE);
1501		}
1502		/* load next address */
1503		if (EBDMA_C_READ(sc, EBDMA_DCSR) & EBDCSR_A_LOADED) {
1504			nextaddr += togo;
1505			EBDMA_C_WRITE(sc, EBDMA_DCNT, togo);
1506			EBDMA_C_WRITE(sc, EBDMA_DADDR, nextaddr);
1507		}
1508	}
1509	ch->nextaddr = nextaddr;
1510	ch->locked = 1;
1511	CS4231_UNLOCK(sc);
1512}
1513
1514static void
1515cs4231_halt(struct cs4231_channel *ch)
1516{
1517	struct cs4231_softc *sc;
1518	u_int8_t status;
1519	int i;
1520
1521	sc = ch->parent;
1522	CS4231_LOCK(sc);
1523	if (ch->locked == 0) {
1524		CS4231_UNLOCK(sc);
1525		return;
1526	}
1527
1528	if (ch->dir == PCMDIR_PLAY ) {
1529		if ((sc->sc_flags & CS4231_SBUS) != 0) {
1530			/* XXX Kills some capture bits */
1531			APC_WRITE(sc, APC_CSR, APC_READ(sc, APC_CSR) &
1532			    ~(APC_CSR_EI | APC_CSR_GIE | APC_CSR_PIE |
1533			    APC_CSR_EIE | APC_CSR_PDMA_GO | APC_CSR_PMIE));
1534		} else {
1535			EBDMA_P_WRITE(sc, EBDMA_DCSR,
1536			    EBDMA_P_READ(sc, EBDMA_DCSR) & ~EBDCSR_DMAEN);
1537		}
1538		/* Waiting for playback FIFO to empty */
1539		status = cs4231_read(sc, CS_TEST_AND_INIT);
1540		for (i = CS_TIMEOUT;
1541		    i && (status & PLAYBACK_UNDERRUN) == 0; i--) {
1542			DELAY(5);
1543			status = cs4231_read(sc, CS_TEST_AND_INIT);
1544		}
1545		if (i == 0)
1546			device_printf(sc->sc_dev, "timeout waiting for "
1547			    "playback FIFO drain\n");
1548		cs4231_write(sc, CS_INTERFACE_CONFIG,
1549		    cs4231_read(sc, CS_INTERFACE_CONFIG) & (~PLAYBACK_ENABLE));
1550	} else {
1551		if ((sc->sc_flags & CS4231_SBUS) != 0) {
1552			/* XXX Kills some playback bits */
1553			APC_WRITE(sc, APC_CSR, APC_CSR_CAPTURE_PAUSE);
1554		} else {
1555			EBDMA_C_WRITE(sc, EBDMA_DCSR,
1556			    EBDMA_C_READ(sc, EBDMA_DCSR) & ~EBDCSR_DMAEN);
1557		}
1558		/* Waiting for capture FIFO to empty */
1559		status = cs4231_read(sc, CS_TEST_AND_INIT);
1560		for (i = CS_TIMEOUT;
1561		    i && (status & CAPTURE_OVERRUN) == 0; i--) {
1562			DELAY(5);
1563			status = cs4231_read(sc, CS_TEST_AND_INIT);
1564		}
1565		if (i == 0)
1566			device_printf(sc->sc_dev, "timeout waiting for "
1567			    "capture FIFO drain\n");
1568		cs4231_write(sc, CS_INTERFACE_CONFIG,
1569		    cs4231_read(sc, CS_INTERFACE_CONFIG) & (~CAPTURE_ENABLE));
1570	}
1571	ch->locked = 0;
1572	CS4231_UNLOCK(sc);
1573}
1574