cs4281.c revision 1.28
1/*	$NetBSD: cs4281.c,v 1.28 2006/04/15 21:20:47 jmcneill Exp $	*/
2
3/*
4 * Copyright (c) 2000 Tatoku Ogaito.  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 * 3. All advertising materials mentioning features or use of this software
15 *    must display the following acknowledgement:
16 *      This product includes software developed by Tatoku Ogaito
17 *	for the NetBSD Project.
18 * 4. The name of the author may not be used to endorse or promote products
19 *    derived from this software without specific prior written permission
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33/*
34 * Cirrus Logic CS4281 driver.
35 * Data sheets can be found
36 * http://www.cirrus.com/ftp/pub/4281.pdf
37 * ftp://ftp.alsa-project.org/pub/manuals/cirrus/cs4281tm.pdf
38 *
39 * TODO:
40 *   1: midi and FM support
41 *   2: ...
42 *
43 */
44
45#include <sys/cdefs.h>
46__KERNEL_RCSID(0, "$NetBSD: cs4281.c,v 1.28 2006/04/15 21:20:47 jmcneill Exp $");
47
48#include <sys/param.h>
49#include <sys/systm.h>
50#include <sys/kernel.h>
51#include <sys/malloc.h>
52#include <sys/fcntl.h>
53#include <sys/device.h>
54#include <sys/systm.h>
55
56#include <dev/pci/pcidevs.h>
57#include <dev/pci/pcivar.h>
58#include <dev/pci/cs4281reg.h>
59#include <dev/pci/cs428xreg.h>
60
61#include <sys/audioio.h>
62#include <dev/audio_if.h>
63#include <dev/midi_if.h>
64#include <dev/mulaw.h>
65#include <dev/auconv.h>
66
67#include <dev/ic/ac97reg.h>
68#include <dev/ic/ac97var.h>
69
70#include <dev/pci/cs428x.h>
71
72#include <machine/bus.h>
73
74#if defined(ENABLE_SECONDARY_CODEC)
75#define MAX_CHANNELS  (4)
76#define MAX_FIFO_SIZE 32 /* 128/4channels */
77#else
78#define MAX_CHANNELS  (2)
79#define MAX_FIFO_SIZE 64 /* 128/2channels */
80#endif
81
82/* IF functions for audio driver */
83static int	cs4281_match(struct device *, struct cfdata *, void *);
84static void	cs4281_attach(struct device *, struct device *, void *);
85static int	cs4281_intr(void *);
86static int	cs4281_query_encoding(void *, struct audio_encoding *);
87static int	cs4281_set_params(void *, int, int, audio_params_t *,
88				  audio_params_t *, stream_filter_list_t *,
89				  stream_filter_list_t *);
90static int	cs4281_halt_output(void *);
91static int	cs4281_halt_input(void *);
92static int	cs4281_getdev(void *, struct audio_device *);
93static int	cs4281_trigger_output(void *, void *, void *, int,
94				      void (*)(void *), void *,
95				      const audio_params_t *);
96static int	cs4281_trigger_input(void *, void *, void *, int,
97				     void (*)(void *), void *,
98				     const audio_params_t *);
99
100static int     cs4281_reset_codec(void *);
101
102/* Internal functions */
103static uint8_t cs4281_sr2regval(int);
104static void	 cs4281_set_dac_rate(struct cs428x_softc *, int);
105static void	 cs4281_set_adc_rate(struct cs428x_softc *, int);
106static int      cs4281_init(struct cs428x_softc *, int);
107
108/* Power Management */
109static void cs4281_power(int, void *);
110
111static const struct audio_hw_if cs4281_hw_if = {
112	NULL,			/* open */
113	NULL,			/* close */
114	NULL,
115	cs4281_query_encoding,
116	cs4281_set_params,
117	cs428x_round_blocksize,
118	NULL,
119	NULL,
120	NULL,
121	NULL,
122	NULL,
123	cs4281_halt_output,
124	cs4281_halt_input,
125	NULL,
126	cs4281_getdev,
127	NULL,
128	cs428x_mixer_set_port,
129	cs428x_mixer_get_port,
130	cs428x_query_devinfo,
131	cs428x_malloc,
132	cs428x_free,
133	cs428x_round_buffersize,
134	cs428x_mappage,
135	cs428x_get_props,
136	cs4281_trigger_output,
137	cs4281_trigger_input,
138	NULL,
139};
140
141#if NMIDI > 0 && 0
142/* Midi Interface */
143static void	cs4281_midi_close(void*);
144static void	cs4281_midi_getinfo(void *, struct midi_info *);
145static int	cs4281_midi_open(void *, int, void (*)(void *, int),
146			 void (*)(void *), void *);
147static int	cs4281_midi_output(void *, int);
148
149static const struct midi_hw_if cs4281_midi_hw_if = {
150	cs4281_midi_open,
151	cs4281_midi_close,
152	cs4281_midi_output,
153	cs4281_midi_getinfo,
154	0,
155};
156#endif
157
158CFATTACH_DECL(clct, sizeof(struct cs428x_softc),
159    cs4281_match, cs4281_attach, NULL, NULL);
160
161static struct audio_device cs4281_device = {
162	"CS4281",
163	"",
164	"cs4281"
165};
166
167
168static int
169cs4281_match(struct device *parent, struct cfdata *match, void *aux)
170{
171	struct pci_attach_args *pa;
172
173	pa = (struct pci_attach_args *)aux;
174	if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_CIRRUS)
175		return 0;
176	if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_CIRRUS_CS4281)
177		return 1;
178	return 0;
179}
180
181static void
182cs4281_attach(struct device *parent, struct device *self, void *aux)
183{
184	struct cs428x_softc *sc;
185	struct pci_attach_args *pa;
186	pci_chipset_tag_t pc;
187	char const *intrstr;
188	pci_intr_handle_t ih;
189	pcireg_t reg;
190	char devinfo[256];
191	int pci_pwrmgmt_cap_reg, pci_pwrmgmt_csr_reg;
192
193	sc = (struct cs428x_softc *)self;
194	pa = (struct pci_attach_args *)aux;
195	pc = pa->pa_pc;
196	aprint_naive(": Audio controller\n");
197
198	pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo, sizeof(devinfo));
199	aprint_normal(": %s (rev. 0x%02x)\n", devinfo,
200	    PCI_REVISION(pa->pa_class));
201
202	/* Map I/O register */
203	if (pci_mapreg_map(pa, PCI_BA0,
204	    PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT, 0,
205	    &sc->ba0t, &sc->ba0h, NULL, NULL)) {
206		aprint_error("%s: can't map BA0 space\n", sc->sc_dev.dv_xname);
207		return;
208	}
209	if (pci_mapreg_map(pa, PCI_BA1,
210	    PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT, 0,
211	    &sc->ba1t, &sc->ba1h, NULL, NULL)) {
212		aprint_error("%s: can't map BA1 space\n", sc->sc_dev.dv_xname);
213		return;
214	}
215
216	sc->sc_dmatag = pa->pa_dmat;
217
218	/*
219	 * Set Power State D0.
220	 * Without do this, 0xffffffff is read from all registers after
221	 * using Windows.
222	 * On my IBM Thinkpad X20, it is set to D3 after using Windows2000.
223	 */
224	if (pci_get_capability(pa->pa_pc, pa->pa_tag, PCI_CAP_PWRMGMT,
225			       &pci_pwrmgmt_cap_reg, 0)) {
226
227		pci_pwrmgmt_csr_reg = pci_pwrmgmt_cap_reg + PCI_PMCSR;
228		reg = pci_conf_read(pa->pa_pc, pa->pa_tag,
229				    pci_pwrmgmt_csr_reg);
230		if ((reg & PCI_PMCSR_STATE_MASK) != PCI_PMCSR_STATE_D0) {
231			pci_conf_write(pc, pa->pa_tag, pci_pwrmgmt_csr_reg,
232				       (reg & ~PCI_PMCSR_STATE_MASK) |
233				       PCI_PMCSR_STATE_D0);
234		}
235	}
236
237	/* Enable the device (set bus master flag) */
238	reg = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);
239	pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG,
240	    reg | PCI_COMMAND_MASTER_ENABLE);
241
242#if 0
243	/* LATENCY_TIMER setting */
244	temp1 = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_BHLC_REG);
245	if (PCI_LATTIMER(temp1) < 32) {
246		temp1 &= 0xffff00ff;
247		temp1 |= 0x00002000;
248		pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_BHLC_REG, temp1);
249	}
250#endif
251
252	/* Map and establish the interrupt. */
253	if (pci_intr_map(pa, &ih)) {
254		aprint_error("%s: couldn't map interrupt\n",
255		    sc->sc_dev.dv_xname);
256		return;
257	}
258	intrstr = pci_intr_string(pc, ih);
259
260	sc->sc_ih = pci_intr_establish(pc, ih, IPL_AUDIO, cs4281_intr, sc);
261	if (sc->sc_ih == NULL) {
262		aprint_error("%s: couldn't establish interrupt",
263		    sc->sc_dev.dv_xname);
264		if (intrstr != NULL)
265			aprint_normal(" at %s", intrstr);
266		aprint_normal("\n");
267		return;
268	}
269	aprint_normal("%s: interrupting at %s\n", sc->sc_dev.dv_xname, intrstr);
270
271	/*
272	 * Sound System start-up
273	 */
274	if (cs4281_init(sc, 1) != 0)
275		return;
276
277	sc->type = TYPE_CS4281;
278	sc->halt_input  = cs4281_halt_input;
279	sc->halt_output = cs4281_halt_output;
280
281	sc->dma_size     = CS4281_BUFFER_SIZE / MAX_CHANNELS;
282	sc->dma_align    = 0x10;
283	sc->hw_blocksize = sc->dma_size / 2;
284
285	/* AC 97 attachment */
286	sc->host_if.arg = sc;
287	sc->host_if.attach = cs428x_attach_codec;
288	sc->host_if.read   = cs428x_read_codec;
289	sc->host_if.write  = cs428x_write_codec;
290	sc->host_if.reset  = cs4281_reset_codec;
291	if (ac97_attach(&sc->host_if, self) != 0) {
292		aprint_error("%s: ac97_attach failed\n", sc->sc_dev.dv_xname);
293		return;
294	}
295	audio_attach_mi(&cs4281_hw_if, sc, &sc->sc_dev);
296
297#if NMIDI > 0 && 0
298	midi_attach_mi(&cs4281_midi_hw_if, sc, &sc->sc_dev);
299#endif
300
301	sc->sc_suspend = PWR_RESUME;
302	sc->sc_powerhook = powerhook_establish(cs4281_power, sc);
303}
304
305static int
306cs4281_intr(void *p)
307{
308	struct cs428x_softc *sc;
309	uint32_t intr, hdsr0, hdsr1;
310	char *empty_dma;
311	int handled;
312
313	sc = p;
314	handled = 0;
315	hdsr0 = 0;
316	hdsr1 = 0;
317
318	/* grab interrupt register */
319	intr = BA0READ4(sc, CS4281_HISR);
320
321	DPRINTF(("cs4281_intr:"));
322	/* not for me */
323	if ((intr & HISR_INTENA) == 0) {
324		/* clear the interrupt register */
325		BA0WRITE4(sc, CS4281_HICR, HICR_CHGM | HICR_IEV);
326		return 0;
327	}
328
329	if (intr & HISR_DMA0)
330		hdsr0 = BA0READ4(sc, CS4281_HDSR0); /* clear intr condition */
331	if (intr & HISR_DMA1)
332		hdsr1 = BA0READ4(sc, CS4281_HDSR1); /* clear intr condition */
333	/* clear the interrupt register */
334	BA0WRITE4(sc, CS4281_HICR, HICR_CHGM | HICR_IEV);
335
336	DPRINTF(("intr = 0x%08x, hdsr0 = 0x%08x hdsr1 = 0x%08x\n",
337		 intr, hdsr0, hdsr1));
338
339	/* Playback Interrupt */
340	if (intr & HISR_DMA0) {
341		handled = 1;
342		if (sc->sc_prun) {
343			DPRINTF((" PB DMA 0x%x(%d)",
344				(int)BA0READ4(sc, CS4281_DCA0),
345				(int)BA0READ4(sc, CS4281_DCC0)));
346			if ((sc->sc_pi%sc->sc_pcount) == 0)
347				sc->sc_pintr(sc->sc_parg);
348			/* copy buffer */
349			++sc->sc_pi;
350			empty_dma = sc->sc_pdma->addr;
351			if (sc->sc_pi&1)
352				empty_dma += sc->hw_blocksize;
353			memcpy(empty_dma, sc->sc_pn, sc->hw_blocksize);
354			sc->sc_pn += sc->hw_blocksize;
355			if (sc->sc_pn >= sc->sc_pe)
356				sc->sc_pn = sc->sc_ps;
357		} else {
358			printf("%s: unexpected play intr\n",
359			       sc->sc_dev.dv_xname);
360		}
361	}
362	if (intr & HISR_DMA1) {
363		handled = 1;
364		if (sc->sc_rrun) {
365			/* copy from DMA */
366			DPRINTF((" CP DMA 0x%x(%d)", (int)BA0READ4(sc, CS4281_DCA1),
367				(int)BA0READ4(sc, CS4281_DCC1)));
368			++sc->sc_ri;
369			empty_dma = sc->sc_rdma->addr;
370			if ((sc->sc_ri & 1) == 0)
371				empty_dma += sc->hw_blocksize;
372			memcpy(sc->sc_rn, empty_dma, sc->hw_blocksize);
373			sc->sc_rn += sc->hw_blocksize;
374			if (sc->sc_rn >= sc->sc_re)
375				sc->sc_rn = sc->sc_rs;
376			if ((sc->sc_ri % sc->sc_rcount) == 0)
377				sc->sc_rintr(sc->sc_rarg);
378		} else {
379			printf("%s: unexpected record intr\n",
380			       sc->sc_dev.dv_xname);
381		}
382	}
383	DPRINTF(("\n"));
384
385	return handled;
386}
387
388static int
389cs4281_query_encoding(void *addr, struct audio_encoding *fp)
390{
391
392	switch (fp->index) {
393	case 0:
394		strcpy(fp->name, AudioEulinear);
395		fp->encoding = AUDIO_ENCODING_ULINEAR;
396		fp->precision = 8;
397		fp->flags = 0;
398		break;
399	case 1:
400		strcpy(fp->name, AudioEmulaw);
401		fp->encoding = AUDIO_ENCODING_ULAW;
402		fp->precision = 8;
403		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
404		break;
405	case 2:
406		strcpy(fp->name, AudioEalaw);
407		fp->encoding = AUDIO_ENCODING_ALAW;
408		fp->precision = 8;
409		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
410		break;
411	case 3:
412		strcpy(fp->name, AudioEslinear);
413		fp->encoding = AUDIO_ENCODING_SLINEAR;
414		fp->precision = 8;
415		fp->flags = 0;
416		break;
417	case 4:
418		strcpy(fp->name, AudioEslinear_le);
419		fp->encoding = AUDIO_ENCODING_SLINEAR_LE;
420		fp->precision = 16;
421		fp->flags = 0;
422		break;
423	case 5:
424		strcpy(fp->name, AudioEulinear_le);
425		fp->encoding = AUDIO_ENCODING_ULINEAR_LE;
426		fp->precision = 16;
427		fp->flags = 0;
428		break;
429	case 6:
430		strcpy(fp->name, AudioEslinear_be);
431		fp->encoding = AUDIO_ENCODING_SLINEAR_BE;
432		fp->precision = 16;
433		fp->flags = 0;
434		break;
435	case 7:
436		strcpy(fp->name, AudioEulinear_be);
437		fp->encoding = AUDIO_ENCODING_ULINEAR_BE;
438		fp->precision = 16;
439		fp->flags = 0;
440		break;
441	default:
442		return EINVAL;
443	}
444	return 0;
445}
446
447static int
448cs4281_set_params(void *addr, int setmode, int usemode,
449		  audio_params_t *play, audio_params_t *rec,
450		  stream_filter_list_t *pfil, stream_filter_list_t *rfil)
451{
452	audio_params_t hw;
453	struct cs428x_softc *sc;
454	audio_params_t *p;
455	stream_filter_list_t *fil;
456	int mode;
457
458	sc = addr;
459	for (mode = AUMODE_RECORD; mode != -1;
460	    mode = mode == AUMODE_RECORD ? AUMODE_PLAY : -1) {
461		if ((setmode & mode) == 0)
462			continue;
463
464		p = mode == AUMODE_PLAY ? play : rec;
465
466		if (p == play) {
467			DPRINTFN(5,
468			    ("play: sample=%u precision=%u channels=%u\n",
469			    p->sample_rate, p->precision, p->channels));
470			if (p->sample_rate < 6023 || p->sample_rate > 48000 ||
471			    (p->precision != 8 && p->precision != 16) ||
472			    (p->channels != 1  && p->channels != 2)) {
473				return EINVAL;
474			}
475		} else {
476			DPRINTFN(5,
477			    ("rec: sample=%u precision=%u channels=%u\n",
478			    p->sample_rate, p->precision, p->channels));
479			if (p->sample_rate < 6023 || p->sample_rate > 48000 ||
480			    (p->precision != 8 && p->precision != 16) ||
481			    (p->channels != 1 && p->channels != 2)) {
482				return EINVAL;
483			}
484		}
485		hw = *p;
486		fil = mode == AUMODE_PLAY ? pfil : rfil;
487
488		switch (p->encoding) {
489		case AUDIO_ENCODING_SLINEAR_BE:
490			break;
491		case AUDIO_ENCODING_SLINEAR_LE:
492			break;
493		case AUDIO_ENCODING_ULINEAR_BE:
494			break;
495		case AUDIO_ENCODING_ULINEAR_LE:
496			break;
497		case AUDIO_ENCODING_ULAW:
498			hw.encoding = AUDIO_ENCODING_SLINEAR_LE;
499			fil->append(fil, mode == AUMODE_PLAY ? mulaw_to_linear8
500				    :  linear8_to_mulaw, &hw);
501			break;
502		case AUDIO_ENCODING_ALAW:
503			hw.encoding = AUDIO_ENCODING_SLINEAR_LE;
504			fil->append(fil, mode == AUMODE_PLAY ? alaw_to_linear8
505				    : linear8_to_alaw, &hw);
506			break;
507		default:
508			return EINVAL;
509		}
510	}
511
512	/* set sample rate */
513	cs4281_set_dac_rate(sc, play->sample_rate);
514	cs4281_set_adc_rate(sc, rec->sample_rate);
515	return 0;
516}
517
518static int
519cs4281_halt_output(void *addr)
520{
521	struct cs428x_softc *sc;
522
523	sc = addr;
524	BA0WRITE4(sc, CS4281_DCR0, BA0READ4(sc, CS4281_DCR0) | DCRn_MSK);
525	sc->sc_prun = 0;
526	return 0;
527}
528
529static int
530cs4281_halt_input(void *addr)
531{
532	struct cs428x_softc *sc;
533
534	sc = addr;
535	BA0WRITE4(sc, CS4281_DCR1, BA0READ4(sc, CS4281_DCR1) | DCRn_MSK);
536	sc->sc_rrun = 0;
537	return 0;
538}
539
540static int
541cs4281_getdev(void *addr, struct audio_device *retp)
542{
543
544	*retp = cs4281_device;
545	return 0;
546}
547
548static int
549cs4281_trigger_output(void *addr, void *start, void *end, int blksize,
550		      void (*intr)(void *), void *arg,
551		      const audio_params_t *param)
552{
553	struct cs428x_softc *sc;
554	uint32_t fmt;
555	struct cs428x_dma *p;
556	int dma_count;
557
558	sc = addr;
559	fmt = 0;
560#ifdef DIAGNOSTIC
561	if (sc->sc_prun)
562		printf("cs4281_trigger_output: already running\n");
563#endif
564	sc->sc_prun = 1;
565
566	DPRINTF(("cs4281_trigger_output: sc=%p start=%p end=%p "
567		 "blksize=%d intr=%p(%p)\n", addr, start, end, blksize, intr, arg));
568	sc->sc_pintr = intr;
569	sc->sc_parg  = arg;
570
571	/* stop playback DMA */
572	BA0WRITE4(sc, CS4281_DCR0, BA0READ4(sc, CS4281_DCR0) | DCRn_MSK);
573
574	DPRINTF(("param: precision=%d channels=%d encoding=%d\n",
575	       param->precision, param->channels, param->encoding));
576	for (p = sc->sc_dmas; p != NULL && BUFADDR(p) != start; p = p->next)
577		continue;
578	if (p == NULL) {
579		printf("cs4281_trigger_output: bad addr %p\n", start);
580		return EINVAL;
581	}
582
583	sc->sc_pcount = blksize / sc->hw_blocksize;
584	sc->sc_ps = (char *)start;
585	sc->sc_pe = (char *)end;
586	sc->sc_pdma = p;
587	sc->sc_pbuf = KERNADDR(p);
588	sc->sc_pi = 0;
589	sc->sc_pn = sc->sc_ps;
590	if (blksize >= sc->dma_size) {
591		sc->sc_pn = sc->sc_ps + sc->dma_size;
592		memcpy(sc->sc_pbuf, start, sc->dma_size);
593		++sc->sc_pi;
594	} else {
595		sc->sc_pn = sc->sc_ps + sc->hw_blocksize;
596		memcpy(sc->sc_pbuf, start, sc->hw_blocksize);
597	}
598
599	dma_count = sc->dma_size;
600	if (param->precision != 8)
601		dma_count /= 2;   /* 16 bit */
602	if (param->channels > 1)
603		dma_count /= 2;   /* Stereo */
604
605	DPRINTF(("cs4281_trigger_output: DMAADDR(p)=0x%x count=%d\n",
606		 (int)DMAADDR(p), dma_count));
607	BA0WRITE4(sc, CS4281_DBA0, DMAADDR(p));
608	BA0WRITE4(sc, CS4281_DBC0, dma_count-1);
609
610	/* set playback format */
611	fmt = BA0READ4(sc, CS4281_DMR0) & ~DMRn_FMTMSK;
612	if (param->precision == 8)
613		fmt |= DMRn_SIZE8;
614	if (param->channels == 1)
615		fmt |= DMRn_MONO;
616	if (param->encoding == AUDIO_ENCODING_ULINEAR_BE ||
617	    param->encoding == AUDIO_ENCODING_SLINEAR_BE)
618		fmt |= DMRn_BEND;
619	if (param->encoding == AUDIO_ENCODING_ULINEAR_BE ||
620	    param->encoding == AUDIO_ENCODING_ULINEAR_LE)
621		fmt |= DMRn_USIGN;
622	BA0WRITE4(sc, CS4281_DMR0, fmt);
623
624	/* set sample rate */
625	sc->sc_prate = param->sample_rate;
626	cs4281_set_dac_rate(sc, param->sample_rate);
627
628	/* start DMA */
629	BA0WRITE4(sc, CS4281_DCR0, BA0READ4(sc, CS4281_DCR0) & ~DCRn_MSK);
630	/* Enable interrupts */
631	BA0WRITE4(sc, CS4281_HICR, HICR_IEV | HICR_CHGM);
632
633	DPRINTF(("HICR =0x%08x(expected 0x00000001)\n", BA0READ4(sc, CS4281_HICR)));
634	DPRINTF(("HIMR =0x%08x(expected 0x00f0fc3f)\n", BA0READ4(sc, CS4281_HIMR)));
635	DPRINTF(("DMR0 =0x%08x(expected 0x2???0018)\n", BA0READ4(sc, CS4281_DMR0)));
636	DPRINTF(("DCR0 =0x%08x(expected 0x00030000)\n", BA0READ4(sc, CS4281_DCR0)));
637	DPRINTF(("FCR0 =0x%08x(expected 0x81000f00)\n", BA0READ4(sc, CS4281_FCR0)));
638	DPRINTF(("DACSR=0x%08x(expected 1 for 44kHz 5 for 8kHz)\n",
639		 BA0READ4(sc, CS4281_DACSR)));
640	DPRINTF(("SRCSA=0x%08x(expected 0x0b0a0100)\n", BA0READ4(sc, CS4281_SRCSA)));
641	DPRINTF(("SSPM&SSPM_PSRCEN =0x%08x(expected 0x00000010)\n",
642		 BA0READ4(sc, CS4281_SSPM) & SSPM_PSRCEN));
643
644	return 0;
645}
646
647static int
648cs4281_trigger_input(void *addr, void *start, void *end, int blksize,
649		     void (*intr)(void *), void *arg,
650		     const audio_params_t *param)
651{
652	struct cs428x_softc *sc;
653	struct cs428x_dma *p;
654	uint32_t fmt;
655	int dma_count;
656
657	sc = addr;
658	fmt = 0;
659#ifdef DIAGNOSTIC
660	if (sc->sc_rrun)
661		printf("cs4281_trigger_input: already running\n");
662#endif
663	sc->sc_rrun = 1;
664	DPRINTF(("cs4281_trigger_input: sc=%p start=%p end=%p "
665	    "blksize=%d intr=%p(%p)\n", addr, start, end, blksize, intr, arg));
666	sc->sc_rintr = intr;
667	sc->sc_rarg  = arg;
668
669	/* stop recording DMA */
670	BA0WRITE4(sc, CS4281_DCR1, BA0READ4(sc, CS4281_DCR1) | DCRn_MSK);
671
672	for (p = sc->sc_dmas; p && BUFADDR(p) != start; p = p->next)
673		continue;
674	if (!p) {
675		printf("cs4281_trigger_input: bad addr %p\n", start);
676		return EINVAL;
677	}
678
679	sc->sc_rcount = blksize / sc->hw_blocksize;
680	sc->sc_rs = (char *)start;
681	sc->sc_re = (char *)end;
682	sc->sc_rdma = p;
683	sc->sc_rbuf = KERNADDR(p);
684	sc->sc_ri = 0;
685	sc->sc_rn = sc->sc_rs;
686
687	dma_count = sc->dma_size;
688	if (param->precision != 8)
689		dma_count /= 2;
690	if (param->channels > 1)
691		dma_count /= 2;
692
693	DPRINTF(("cs4281_trigger_input: DMAADDR(p)=0x%x count=%d\n",
694		 (int)DMAADDR(p), dma_count));
695	BA0WRITE4(sc, CS4281_DBA1, DMAADDR(p));
696	BA0WRITE4(sc, CS4281_DBC1, dma_count-1);
697
698	/* set recording format */
699	fmt = BA0READ4(sc, CS4281_DMR1) & ~DMRn_FMTMSK;
700	if (param->precision == 8)
701		fmt |= DMRn_SIZE8;
702	if (param->channels == 1)
703		fmt |= DMRn_MONO;
704	if (param->encoding == AUDIO_ENCODING_ULINEAR_BE ||
705	    param->encoding == AUDIO_ENCODING_SLINEAR_BE)
706		fmt |= DMRn_BEND;
707	if (param->encoding == AUDIO_ENCODING_ULINEAR_BE ||
708	    param->encoding == AUDIO_ENCODING_ULINEAR_LE)
709		fmt |= DMRn_USIGN;
710	BA0WRITE4(sc, CS4281_DMR1, fmt);
711
712	/* set sample rate */
713	sc->sc_rrate = param->sample_rate;
714	cs4281_set_adc_rate(sc, param->sample_rate);
715
716	/* Start DMA */
717	BA0WRITE4(sc, CS4281_DCR1, BA0READ4(sc, CS4281_DCR1) & ~DCRn_MSK);
718	/* Enable interrupts */
719	BA0WRITE4(sc, CS4281_HICR, HICR_IEV | HICR_CHGM);
720
721	DPRINTF(("HICR=0x%08x\n", BA0READ4(sc, CS4281_HICR)));
722	DPRINTF(("HIMR=0x%08x\n", BA0READ4(sc, CS4281_HIMR)));
723	DPRINTF(("DMR1=0x%08x\n", BA0READ4(sc, CS4281_DMR1)));
724	DPRINTF(("DCR1=0x%08x\n", BA0READ4(sc, CS4281_DCR1)));
725
726	return 0;
727}
728
729/* Power Hook */
730static void
731cs4281_power(int why, void *v)
732{
733	static uint32_t dba0 = 0, dbc0 = 0, dmr0 = 0, dcr0 = 0;
734	static uint32_t dba1 = 0, dbc1 = 0, dmr1 = 0, dcr1 = 0;
735	struct cs428x_softc *sc;
736
737	sc = (struct cs428x_softc *)v;
738	DPRINTF(("%s: cs4281_power why=%d\n", sc->sc_dev.dv_xname, why));
739	switch (why) {
740	case PWR_SUSPEND:
741	case PWR_STANDBY:
742		sc->sc_suspend = why;
743
744		/* save current playback status */
745		if (sc->sc_prun) {
746			dcr0 = BA0READ4(sc, CS4281_DCR0);
747			dmr0 = BA0READ4(sc, CS4281_DMR0);
748			dbc0 = BA0READ4(sc, CS4281_DBC0);
749			dba0 = BA0READ4(sc, CS4281_DBA0);
750		}
751
752		/* save current capture status */
753		if (sc->sc_rrun) {
754			dcr1 = BA0READ4(sc, CS4281_DCR1);
755			dmr1 = BA0READ4(sc, CS4281_DMR1);
756			dbc1 = BA0READ4(sc, CS4281_DBC1);
757			dba1 = BA0READ4(sc, CS4281_DBA1);
758		}
759		/* Stop DMA */
760		BA0WRITE4(sc, CS4281_DCR0, BA0READ4(sc, CS4281_DCR0) | DCRn_MSK);
761		BA0WRITE4(sc, CS4281_DCR1, BA0READ4(sc, CS4281_DCR1) | DCRn_MSK);
762		break;
763	case PWR_RESUME:
764		if (sc->sc_suspend == PWR_RESUME) {
765			printf("cs4281_power: odd, resume without suspend.\n");
766			sc->sc_suspend = why;
767			return;
768		}
769		sc->sc_suspend = why;
770		cs4281_init(sc, 0);
771		cs4281_reset_codec(sc);
772
773		/* restore ac97 registers */
774		(*sc->codec_if->vtbl->restore_ports)(sc->codec_if);
775
776		/* restore DMA related status */
777		if (sc->sc_prun) {
778			cs4281_set_dac_rate(sc, sc->sc_prate);
779			BA0WRITE4(sc, CS4281_DBA0, dba0);
780			BA0WRITE4(sc, CS4281_DBC0, dbc0);
781			BA0WRITE4(sc, CS4281_DMR0, dmr0);
782			BA0WRITE4(sc, CS4281_DCR0, dcr0);
783		}
784		if (sc->sc_rrun) {
785			cs4281_set_adc_rate(sc, sc->sc_rrate);
786			BA0WRITE4(sc, CS4281_DBA1, dba1);
787			BA0WRITE4(sc, CS4281_DBC1, dbc1);
788			BA0WRITE4(sc, CS4281_DMR1, dmr1);
789			BA0WRITE4(sc, CS4281_DCR1, dcr1);
790		}
791		/* enable intterupts */
792		if (sc->sc_prun || sc->sc_rrun)
793			BA0WRITE4(sc, CS4281_HICR, HICR_IEV | HICR_CHGM);
794		break;
795	case PWR_SOFTSUSPEND:
796	case PWR_SOFTSTANDBY:
797	case PWR_SOFTRESUME:
798		break;
799	}
800}
801
802/* control AC97 codec */
803static int
804cs4281_reset_codec(void *addr)
805{
806	struct cs428x_softc *sc;
807	uint16_t data;
808	uint32_t dat32;
809	int n;
810
811	sc = addr;
812
813	DPRINTFN(3, ("cs4281_reset_codec\n"));
814
815	/* Reset codec */
816	BA0WRITE4(sc, CS428X_ACCTL, 0);
817	delay(50);    /* delay 50us */
818
819	BA0WRITE4(sc, CS4281_SPMC, 0);
820	delay(100);	/* delay 100us */
821	BA0WRITE4(sc, CS4281_SPMC, SPMC_RSTN);
822#if defined(ENABLE_SECONDARY_CODEC)
823	BA0WRITE4(sc, CS4281_SPMC, SPMC_RSTN | SPCM_ASDIN2E);
824	BA0WRITE4(sc, CS4281_SERMC, SERMC_TCID);
825#endif
826	delay(50000);   /* XXX: delay 50ms */
827
828	/* Enable ASYNC generation */
829	BA0WRITE4(sc, CS428X_ACCTL, ACCTL_ESYN);
830
831	/* Wait for codec ready. Linux driver waits 50ms here */
832	n = 0;
833	while ((BA0READ4(sc, CS428X_ACSTS) & ACSTS_CRDY) == 0) {
834		delay(100);
835		if (++n > 1000) {
836			printf("reset_codec: AC97 codec ready timeout\n");
837			return ETIMEDOUT;
838		}
839	}
840#if defined(ENABLE_SECONDARY_CODEC)
841	/* secondary codec ready*/
842	n = 0;
843	while ((BA0READ4(sc, CS4281_ACSTS2) & ACSTS2_CRDY2) == 0) {
844		delay(100);
845		if (++n > 1000)
846			return 0;
847	}
848#endif
849	/* Set the serial timing configuration */
850	/* XXX: undocumented but the Linux driver do this */
851	BA0WRITE4(sc, CS4281_SERMC, SERMC_PTCAC97);
852
853	/* Wait for codec ready signal */
854	n = 0;
855	do {
856		delay(1000);
857		if (++n > 1000) {
858			printf("%s: timeout waiting for codec ready\n",
859			       sc->sc_dev.dv_xname);
860			return ETIMEDOUT;
861		}
862		dat32 = BA0READ4(sc, CS428X_ACSTS) & ACSTS_CRDY;
863	} while (dat32 == 0);
864
865	/* Enable Valid Frame output on ASDOUT */
866	BA0WRITE4(sc, CS428X_ACCTL, ACCTL_ESYN | ACCTL_VFRM);
867
868	/* Wait until codec calibration is finished. Codec register 26h */
869	n = 0;
870	do {
871		delay(1);
872		if (++n > 1000) {
873			printf("%s: timeout waiting for codec calibration\n",
874			       sc->sc_dev.dv_xname);
875			return ETIMEDOUT;
876		}
877		cs428x_read_codec(sc, AC97_REG_POWER, &data);
878	} while ((data & 0x0f) != 0x0f);
879
880	/* Set the serial timing configuration again */
881	/* XXX: undocumented but the Linux driver do this */
882	BA0WRITE4(sc, CS4281_SERMC, SERMC_PTCAC97);
883
884	/* Wait until we've sampled input slots 3 & 4 as valid */
885	n = 0;
886	do {
887		delay(1000);
888		if (++n > 1000) {
889			printf("%s: timeout waiting for sampled input slots as valid\n",
890			       sc->sc_dev.dv_xname);
891			return ETIMEDOUT;
892		}
893		dat32 = BA0READ4(sc, CS428X_ACISV) & (ACISV_ISV3 | ACISV_ISV4) ;
894	} while (dat32 != (ACISV_ISV3 | ACISV_ISV4));
895
896	/* Start digital data transfer of audio data to the codec */
897	BA0WRITE4(sc, CS428X_ACOSV, (ACOSV_SLV3 | ACOSV_SLV4));
898	return 0;
899}
900
901
902/* Internal functions */
903
904/* convert sample rate to register value */
905static uint8_t
906cs4281_sr2regval(int rate)
907{
908	uint8_t retval;
909
910	/* We don't have to change here. but anyway ... */
911	if (rate > 48000)
912		rate = 48000;
913	if (rate < 6023)
914		rate = 6023;
915
916	switch (rate) {
917	case 8000:
918		retval = 5;
919		break;
920	case 11025:
921		retval = 4;
922		break;
923	case 16000:
924		retval = 3;
925		break;
926	case 22050:
927		retval = 2;
928		break;
929	case 44100:
930		retval = 1;
931		break;
932	case 48000:
933		retval = 0;
934		break;
935	default:
936		retval = 1536000/rate; /* == 24576000/(rate*16) */
937	}
938	return retval;
939}
940
941static void
942cs4281_set_adc_rate(struct cs428x_softc *sc, int rate)
943{
944
945	BA0WRITE4(sc, CS4281_ADCSR, cs4281_sr2regval(rate));
946}
947
948static void
949cs4281_set_dac_rate(struct cs428x_softc *sc, int rate)
950{
951
952	BA0WRITE4(sc, CS4281_DACSR, cs4281_sr2regval(rate));
953}
954
955static int
956cs4281_init(struct cs428x_softc *sc, int init)
957{
958	int n;
959	uint16_t data;
960	uint32_t dat32;
961
962	/* set "Configuration Write Protect" register to
963	 * 0x4281 to allow to write */
964	BA0WRITE4(sc, CS4281_CWPR, 0x4281);
965
966	/*
967	 * Unset "Full Power-Down bit of Extended PCI Power Management
968	 * Control" register to release the reset state.
969	 */
970	dat32 = BA0READ4(sc, CS4281_EPPMC);
971	if (dat32 & EPPMC_FPDN) {
972		BA0WRITE4(sc, CS4281_EPPMC, dat32 & ~EPPMC_FPDN);
973	}
974
975	/* Start PLL out in known state */
976	BA0WRITE4(sc, CS4281_CLKCR1, 0);
977	/* Start serial ports out in known state */
978	BA0WRITE4(sc, CS4281_SERMC, 0);
979
980	/* Reset codec */
981	BA0WRITE4(sc, CS428X_ACCTL, 0);
982	delay(50);	/* delay 50us */
983
984	BA0WRITE4(sc, CS4281_SPMC, 0);
985	delay(100);	/* delay 100us */
986	BA0WRITE4(sc, CS4281_SPMC, SPMC_RSTN);
987#if defined(ENABLE_SECONDARY_CODEC)
988	BA0WRITE4(sc, CS4281_SPMC, SPMC_RSTN | SPCM_ASDIN2E);
989	BA0WRITE4(sc, CS4281_SERMC, SERMC_TCID);
990#endif
991	delay(50000);   /* XXX: delay 50ms */
992
993	/* Turn on Sound System clocks based on ABITCLK */
994	BA0WRITE4(sc, CS4281_CLKCR1, CLKCR1_DLLP);
995	delay(50000);   /* XXX: delay 50ms */
996	BA0WRITE4(sc, CS4281_CLKCR1, CLKCR1_SWCE | CLKCR1_DLLP);
997
998	/* Set enables for sections that are needed in the SSPM registers */
999	BA0WRITE4(sc, CS4281_SSPM,
1000		  SSPM_MIXEN |		/* Mixer */
1001		  SSPM_CSRCEN |		/* Capture SRC */
1002		  SSPM_PSRCEN |		/* Playback SRC */
1003		  SSPM_JSEN |		/* Joystick */
1004		  SSPM_ACLEN |		/* AC LINK */
1005		  SSPM_FMEN		/* FM */
1006		  );
1007
1008	/* Wait for clock stabilization */
1009	n = 0;
1010#if 1
1011	/* what document says */
1012	while ((BA0READ4(sc, CS4281_CLKCR1)& (CLKCR1_DLLRDY | CLKCR1_CLKON))
1013		 != (CLKCR1_DLLRDY | CLKCR1_CLKON)) {
1014		delay(100);
1015		if (++n > 1000) {
1016			printf("%s: timeout waiting for clock stabilization\n",
1017			       sc->sc_dev.dv_xname);
1018			return -1;
1019		}
1020	}
1021#else
1022	/* Cirrus driver for Linux does */
1023	while (!(BA0READ4(sc, CS4281_CLKCR1) & CLKCR1_DLLRDY)) {
1024		delay(1000);
1025		if (++n > 1000) {
1026			printf("%s: timeout waiting for clock stabilization\n",
1027			       sc->sc_dev.dv_xname);
1028			return -1;
1029		}
1030	}
1031#endif
1032
1033	/* Enable ASYNC generation */
1034	BA0WRITE4(sc, CS428X_ACCTL, ACCTL_ESYN);
1035
1036	/* Wait for codec ready. Linux driver waits 50ms here */
1037	n = 0;
1038	while ((BA0READ4(sc, CS428X_ACSTS) & ACSTS_CRDY) == 0) {
1039		delay(100);
1040		if (++n > 1000) {
1041			printf("%s: timeout waiting for codec ready\n",
1042			       sc->sc_dev.dv_xname);
1043			return -1;
1044		}
1045	}
1046
1047#if defined(ENABLE_SECONDARY_CODEC)
1048	/* secondary codec ready*/
1049	n = 0;
1050	while ((BA0READ4(sc, CS4281_ACSTS2) & ACSTS2_CRDY2) == 0) {
1051		delay(100);
1052		if (++n > 1000) {
1053			printf("%s: timeout waiting for secondary codec ready\n",
1054			       sc->sc_dev.dv_xname);
1055			return -1;
1056		}
1057	}
1058#endif
1059
1060	/* Set the serial timing configuration */
1061	/* XXX: undocumented but the Linux driver do this */
1062	BA0WRITE4(sc, CS4281_SERMC, SERMC_PTCAC97);
1063
1064	/* Wait for codec ready signal */
1065	n = 0;
1066	do {
1067		delay(1000);
1068		if (++n > 1000) {
1069			printf("%s: timeout waiting for codec ready\n",
1070			       sc->sc_dev.dv_xname);
1071			return -1;
1072		}
1073		dat32 = BA0READ4(sc, CS428X_ACSTS) & ACSTS_CRDY;
1074	} while (dat32 == 0);
1075
1076	/* Enable Valid Frame output on ASDOUT */
1077	BA0WRITE4(sc, CS428X_ACCTL, ACCTL_ESYN | ACCTL_VFRM);
1078
1079	/* Wait until codec calibration is finished. codec register 26h */
1080	n = 0;
1081	do {
1082		delay(1);
1083		if (++n > 1000) {
1084			printf("%s: timeout waiting for codec calibration\n",
1085			       sc->sc_dev.dv_xname);
1086			return -1;
1087		}
1088		cs428x_read_codec(sc, AC97_REG_POWER, &data);
1089	} while ((data & 0x0f) != 0x0f);
1090
1091	/* Set the serial timing configuration again */
1092	/* XXX: undocumented but the Linux driver do this */
1093	BA0WRITE4(sc, CS4281_SERMC, SERMC_PTCAC97);
1094
1095	/* Wait until we've sampled input slots 3 & 4 as valid */
1096	n = 0;
1097	do {
1098		delay(1000);
1099		if (++n > 1000) {
1100			printf("%s: timeout waiting for sampled input slots as valid\n",
1101			       sc->sc_dev.dv_xname);
1102			return -1;
1103		}
1104		dat32 = BA0READ4(sc, CS428X_ACISV) & (ACISV_ISV3 | ACISV_ISV4);
1105	} while (dat32 != (ACISV_ISV3 | ACISV_ISV4));
1106
1107	/* Start digital data transfer of audio data to the codec */
1108	BA0WRITE4(sc, CS428X_ACOSV, (ACOSV_SLV3 | ACOSV_SLV4));
1109
1110	cs428x_write_codec(sc, AC97_REG_HEADPHONE_VOLUME, 0);
1111	cs428x_write_codec(sc, AC97_REG_MASTER_VOLUME, 0);
1112
1113	/* Power on the DAC */
1114	cs428x_read_codec(sc, AC97_REG_POWER, &data);
1115	cs428x_write_codec(sc, AC97_REG_POWER, data & 0xfdff);
1116
1117	/* Wait until we sample a DAC ready state.
1118	 * Not documented, but Linux driver does.
1119	 */
1120	for (n = 0; n < 32; ++n) {
1121		delay(1000);
1122		cs428x_read_codec(sc, AC97_REG_POWER, &data);
1123		if (data & 0x02)
1124			break;
1125	}
1126
1127	/* Power on the ADC */
1128	cs428x_read_codec(sc, AC97_REG_POWER, &data);
1129	cs428x_write_codec(sc, AC97_REG_POWER, data & 0xfeff);
1130
1131	/* Wait until we sample ADC ready state.
1132	 * Not documented, but Linux driver does.
1133	 */
1134	for (n = 0; n < 32; ++n) {
1135		delay(1000);
1136		cs428x_read_codec(sc, AC97_REG_POWER, &data);
1137		if (data & 0x01)
1138			break;
1139	}
1140
1141#if 0
1142	/* Initialize AC-Link features */
1143	/* variable sample-rate support */
1144	mem = BA0READ4(sc, CS4281_SERMC);
1145	mem |=  (SERMC_ODSEN1 | SERMC_ODSEN2);
1146	BA0WRITE4(sc, CS4281_SERMC, mem);
1147	/* XXX: more... */
1148
1149	/* Initialize SSCR register features */
1150	/* XXX: hardware volume setting */
1151	BA0WRITE4(sc, CS4281_SSCR, ~SSCR_HVC); /* disable HW volume setting */
1152#endif
1153
1154	/* disable Sound Blaster Pro emulation */
1155	/* XXX:
1156	 * Cannot set since the documents does not describe which bit is
1157	 * correspond to SSCR_SB. Since the reset value of SSCR is 0,
1158	 * we can ignore it.*/
1159#if 0
1160	BA0WRITE4(sc, CS4281_SSCR, SSCR_SB);
1161#endif
1162
1163	/* map AC97 PCM playback to DMA Channel 0 */
1164	/* Reset FEN bit to setup first */
1165	BA0WRITE4(sc, CS4281_FCR0, (BA0READ4(sc, CS4281_FCR0) & ~FCRn_FEN));
1166	/*
1167	 *| RS[4:0]/|        |
1168	 *| LS[4:0] |  AC97  | Slot Function
1169	 *|---------+--------+--------------------
1170	 *|     0   |    3   | Left PCM Playback
1171	 *|     1   |    4   | Right PCM Playback
1172	 *|     2   |    5   | Phone Line 1 DAC
1173	 *|     3   |    6   | Center PCM Playback
1174	 *....
1175	 *  quoted from Table 29(p109)
1176	 */
1177	dat32 = 0x01 << 24 |   /* RS[4:0] =  1 see above */
1178		0x00 << 16 |   /* LS[4:0] =  0 see above */
1179		0x0f <<  8 |   /* SZ[6:0] = 15 size of buffer */
1180		0x00 <<  0 ;   /* OF[6:0] =  0 offset */
1181	BA0WRITE4(sc, CS4281_FCR0, dat32);
1182	BA0WRITE4(sc, CS4281_FCR0, dat32 | FCRn_FEN);
1183
1184	/* map AC97 PCM record to DMA Channel 1 */
1185	/* Reset FEN bit to setup first */
1186	BA0WRITE4(sc, CS4281_FCR1, (BA0READ4(sc, CS4281_FCR1) & ~FCRn_FEN));
1187	/*
1188	 *| RS[4:0]/|
1189	 *| LS[4:0] | AC97 | Slot Function
1190	 *|---------+------+-------------------
1191	 *|   10    |   3  | Left PCM Record
1192	 *|   11    |   4  | Right PCM Record
1193	 *|   12    |   5  | Phone Line 1 ADC
1194	 *|   13    |   6  | Mic ADC
1195	 *....
1196	 * quoted from Table 30(p109)
1197	 */
1198	dat32 = 0x0b << 24 |    /* RS[4:0] = 11 See above */
1199		0x0a << 16 |    /* LS[4:0] = 10 See above */
1200		0x0f <<  8 |    /* SZ[6:0] = 15 Size of buffer */
1201		0x10 <<  0 ;    /* OF[6:0] = 16 offset */
1202
1203	/* XXX: I cannot understand why FCRn_PSH is needed here. */
1204	BA0WRITE4(sc, CS4281_FCR1, dat32 | FCRn_PSH);
1205	BA0WRITE4(sc, CS4281_FCR1, dat32 | FCRn_FEN);
1206
1207#if 0
1208	/* Disable DMA Channel 2, 3 */
1209	BA0WRITE4(sc, CS4281_FCR2, (BA0READ4(sc, CS4281_FCR2) & ~FCRn_FEN));
1210	BA0WRITE4(sc, CS4281_FCR3, (BA0READ4(sc, CS4281_FCR3) & ~FCRn_FEN));
1211#endif
1212
1213	/* Set the SRC Slot Assignment accordingly */
1214	/*| PLSS[4:0]/
1215	 *| PRSS[4:0] | AC97 | Slot Function
1216	 *|-----------+------+----------------
1217	 *|     0     |  3   | Left PCM Playback
1218	 *|     1     |  4   | Right PCM Playback
1219	 *|     2     |  5   | phone line 1 DAC
1220	 *|     3     |  6   | Center PCM Playback
1221	 *|     4     |  7   | Left Surround PCM Playback
1222	 *|     5     |  8   | Right Surround PCM Playback
1223	 *......
1224	 *
1225	 *| CLSS[4:0]/
1226	 *| CRSS[4:0] | AC97 | Codec |Slot Function
1227	 *|-----------+------+-------+-----------------
1228	 *|    10     |   3  |Primary| Left PCM Record
1229	 *|    11     |   4  |Primary| Right PCM Record
1230	 *|    12     |   5  |Primary| Phone Line 1 ADC
1231	 *|    13     |   6  |Primary| Mic ADC
1232	 *|.....
1233	 *|    20     |   3  |  Sec. | Left PCM Record
1234	 *|    21     |   4  |  Sec. | Right PCM Record
1235	 *|    22     |   5  |  Sec. | Phone Line 1 ADC
1236	 *|    23     |   6  |  Sec. | Mic ADC
1237	 */
1238	dat32 = 0x0b << 24 |   /* CRSS[4:0] Right PCM Record(primary) */
1239		0x0a << 16 |   /* CLSS[4:0] Left  PCM Record(primary) */
1240		0x01 <<  8 |   /* PRSS[4:0] Right PCM Playback */
1241		0x00 <<  0;    /* PLSS[4:0] Left  PCM Playback */
1242	BA0WRITE4(sc, CS4281_SRCSA, dat32);
1243
1244	/* Set interrupt to occurred at Half and Full terminal
1245	 * count interrupt enable for DMA channel 0 and 1.
1246	 * To keep DMA stop, set MSK.
1247	 */
1248	dat32 = DCRn_HTCIE | DCRn_TCIE | DCRn_MSK;
1249	BA0WRITE4(sc, CS4281_DCR0, dat32);
1250	BA0WRITE4(sc, CS4281_DCR1, dat32);
1251
1252	/* Set Auto-Initialize Contorl enable */
1253	BA0WRITE4(sc, CS4281_DMR0,
1254		  DMRn_DMA | DMRn_AUTO | DMRn_TR_READ);
1255	BA0WRITE4(sc, CS4281_DMR1,
1256		  DMRn_DMA | DMRn_AUTO | DMRn_TR_WRITE);
1257
1258	/* Clear DMA Mask in HIMR */
1259	dat32 = ~HIMR_DMAIM & ~HIMR_D1IM & ~HIMR_D0IM;
1260	BA0WRITE4(sc, CS4281_HIMR,
1261		  BA0READ4(sc, CS4281_HIMR) & dat32);
1262
1263	/* set current status */
1264	if (init != 0) {
1265		sc->sc_prun = 0;
1266		sc->sc_rrun = 0;
1267	}
1268
1269	/* setup playback volume */
1270	BA0WRITE4(sc, CS4281_PPRVC, 7);
1271	BA0WRITE4(sc, CS4281_PPLVC, 7);
1272
1273	return 0;
1274}
1275