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