1/*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (c) 1999 Seigo Tanimura
5 * All rights reserved.
6 *
7 * Portions of this source are based on cwcealdr.cpp and dhwiface.cpp in
8 * cwcealdr1.zip, the sample sources by Crystal Semiconductor.
9 * Copyright (c) 1996-1998 Crystal Semiconductor Corp.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 *    notice, this list of conditions and the following disclaimer in the
18 *    documentation and/or other materials provided with the distribution.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33#ifdef HAVE_KERNEL_OPTION_HEADERS
34#include "opt_snd.h"
35#endif
36
37#include <dev/sound/pcm/sound.h>
38#include <dev/sound/pcm/ac97.h>
39#include <dev/sound/pci/csareg.h>
40#include <dev/sound/pci/csavar.h>
41
42#include <dev/pci/pcireg.h>
43#include <dev/pci/pcivar.h>
44
45/* Buffer size on dma transfer. Fixed for CS416x. */
46#define CS461x_BUFFSIZE   (4 * 1024)
47
48#define GOF_PER_SEC 200
49
50/* device private data */
51struct csa_info;
52
53struct csa_chinfo {
54	struct csa_info *parent;
55	struct pcm_channel *channel;
56	struct snd_dbuf *buffer;
57	int dir;
58	u_int32_t fmt, spd;
59	int dma;
60};
61
62struct csa_info {
63	csa_res		res; /* resource */
64	void		*ih; /* Interrupt cookie */
65	bus_dma_tag_t	parent_dmat; /* DMA tag */
66	struct csa_bridgeinfo *binfo; /* The state of the parent. */
67	struct csa_card *card;
68
69	int active;
70	/* Contents of board's registers */
71	u_long		pfie;
72	u_long		pctl;
73	u_long		cctl;
74	struct csa_chinfo pch, rch;
75	u_int32_t	ac97[CS461x_AC97_NUMBER_RESTORE_REGS];
76	u_int32_t	ac97_powerdown;
77	u_int32_t	ac97_general_purpose;
78};
79
80/* -------------------------------------------------------------------- */
81
82/* prototypes */
83static int      csa_init(struct csa_info *);
84static void     csa_intr(void *);
85static void	csa_setplaysamplerate(csa_res *resp, u_long ulInRate);
86static void	csa_setcapturesamplerate(csa_res *resp, u_long ulOutRate);
87static void	csa_startplaydma(struct csa_info *csa);
88static void	csa_startcapturedma(struct csa_info *csa);
89static void	csa_stopplaydma(struct csa_info *csa);
90static void	csa_stopcapturedma(struct csa_info *csa);
91static int	csa_startdsp(csa_res *resp);
92static int	csa_stopdsp(csa_res *resp);
93static int	csa_allocres(struct csa_info *scp, device_t dev);
94static void	csa_releaseres(struct csa_info *scp, device_t dev);
95static void	csa_ac97_suspend(struct csa_info *csa);
96static void	csa_ac97_resume(struct csa_info *csa);
97
98static u_int32_t csa_playfmt[] = {
99	SND_FORMAT(AFMT_U8, 1, 0),
100	SND_FORMAT(AFMT_U8, 2, 0),
101	SND_FORMAT(AFMT_S8, 1, 0),
102	SND_FORMAT(AFMT_S8, 2, 0),
103	SND_FORMAT(AFMT_S16_LE, 1, 0),
104	SND_FORMAT(AFMT_S16_LE, 2, 0),
105	SND_FORMAT(AFMT_S16_BE, 1, 0),
106	SND_FORMAT(AFMT_S16_BE, 2, 0),
107	0
108};
109static struct pcmchan_caps csa_playcaps = {8000, 48000, csa_playfmt, 0};
110
111static u_int32_t csa_recfmt[] = {
112	SND_FORMAT(AFMT_S16_LE, 1, 0),
113	SND_FORMAT(AFMT_S16_LE, 2, 0),
114	0
115};
116static struct pcmchan_caps csa_reccaps = {11025, 48000, csa_recfmt, 0};
117
118/* -------------------------------------------------------------------- */
119
120static int
121csa_active(struct csa_info *csa, int run)
122{
123	int old;
124
125	old = csa->active;
126	csa->active += run;
127
128	if ((csa->active > 1) || (csa->active < -1))
129		csa->active = 0;
130	if (csa->card->active)
131		return (csa->card->active(!(csa->active && old)));
132
133	return 0;
134}
135
136/* -------------------------------------------------------------------- */
137/* ac97 codec */
138
139static int
140csa_rdcd(kobj_t obj, void *devinfo, int regno)
141{
142	u_int32_t data;
143	struct csa_info *csa = (struct csa_info *)devinfo;
144
145	csa_active(csa, 1);
146	if (csa_readcodec(&csa->res, regno + BA0_AC97_RESET, &data))
147		data = 0;
148	csa_active(csa, -1);
149
150	return data;
151}
152
153static int
154csa_wrcd(kobj_t obj, void *devinfo, int regno, u_int32_t data)
155{
156	struct csa_info *csa = (struct csa_info *)devinfo;
157
158	csa_active(csa, 1);
159	csa_writecodec(&csa->res, regno + BA0_AC97_RESET, data);
160	csa_active(csa, -1);
161
162	return 0;
163}
164
165static kobj_method_t csa_ac97_methods[] = {
166    	KOBJMETHOD(ac97_read,		csa_rdcd),
167    	KOBJMETHOD(ac97_write,		csa_wrcd),
168	KOBJMETHOD_END
169};
170AC97_DECLARE(csa_ac97);
171
172static void
173csa_setplaysamplerate(csa_res *resp, u_long ulInRate)
174{
175	u_long ulTemp1, ulTemp2;
176	u_long ulPhiIncr;
177	u_long ulCorrectionPerGOF, ulCorrectionPerSec;
178	u_long ulOutRate;
179
180	ulOutRate = 48000;
181
182	/*
183	 * Compute the values used to drive the actual sample rate conversion.
184	 * The following formulas are being computed, using inline assembly
185	 * since we need to use 64 bit arithmetic to compute the values:
186	 *
187	 *     ulPhiIncr = floor((Fs,in * 2^26) / Fs,out)
188	 *     ulCorrectionPerGOF = floor((Fs,in * 2^26 - Fs,out * ulPhiIncr) /
189	 *                                GOF_PER_SEC)
190	 *     ulCorrectionPerSec = Fs,in * 2^26 - Fs,out * phiIncr -
191	 *                          GOF_PER_SEC * ulCorrectionPerGOF
192	 *
193	 * i.e.
194	 *
195	 *     ulPhiIncr:ulOther = dividend:remainder((Fs,in * 2^26) / Fs,out)
196	 *     ulCorrectionPerGOF:ulCorrectionPerSec =
197	 *         dividend:remainder(ulOther / GOF_PER_SEC)
198	 */
199	ulTemp1 = ulInRate << 16;
200	ulPhiIncr = ulTemp1 / ulOutRate;
201	ulTemp1 -= ulPhiIncr * ulOutRate;
202	ulTemp1 <<= 10;
203	ulPhiIncr <<= 10;
204	ulTemp2 = ulTemp1 / ulOutRate;
205	ulPhiIncr += ulTemp2;
206	ulTemp1 -= ulTemp2 * ulOutRate;
207	ulCorrectionPerGOF = ulTemp1 / GOF_PER_SEC;
208	ulTemp1 -= ulCorrectionPerGOF * GOF_PER_SEC;
209	ulCorrectionPerSec = ulTemp1;
210
211	/*
212	 * Fill in the SampleRateConverter control block.
213	 */
214	csa_writemem(resp, BA1_PSRC, ((ulCorrectionPerSec << 16) & 0xFFFF0000) | (ulCorrectionPerGOF & 0xFFFF));
215	csa_writemem(resp, BA1_PPI, ulPhiIncr);
216}
217
218static void
219csa_setcapturesamplerate(csa_res *resp, u_long ulOutRate)
220{
221	u_long ulPhiIncr, ulCoeffIncr, ulTemp1, ulTemp2;
222	u_long ulCorrectionPerGOF, ulCorrectionPerSec, ulInitialDelay;
223	u_long dwFrameGroupLength, dwCnt;
224	u_long ulInRate;
225
226	ulInRate = 48000;
227
228	/*
229	 * We can only decimate by up to a factor of 1/9th the hardware rate.
230	 * Return an error if an attempt is made to stray outside that limit.
231	 */
232	if((ulOutRate * 9) < ulInRate)
233		return;
234
235	/*
236	 * We can not capture at at rate greater than the Input Rate (48000).
237	 * Return an error if an attempt is made to stray outside that limit.
238	 */
239	if(ulOutRate > ulInRate)
240		return;
241
242	/*
243	 * Compute the values used to drive the actual sample rate conversion.
244	 * The following formulas are being computed, using inline assembly
245	 * since we need to use 64 bit arithmetic to compute the values:
246	 *
247	 *     ulCoeffIncr = -floor((Fs,out * 2^23) / Fs,in)
248	 *     ulPhiIncr = floor((Fs,in * 2^26) / Fs,out)
249	 *     ulCorrectionPerGOF = floor((Fs,in * 2^26 - Fs,out * ulPhiIncr) /
250	 *                                GOF_PER_SEC)
251	 *     ulCorrectionPerSec = Fs,in * 2^26 - Fs,out * phiIncr -
252	 *                          GOF_PER_SEC * ulCorrectionPerGOF
253	 *     ulInitialDelay = ceil((24 * Fs,in) / Fs,out)
254	 *
255	 * i.e.
256	 *
257	 *     ulCoeffIncr = neg(dividend((Fs,out * 2^23) / Fs,in))
258	 *     ulPhiIncr:ulOther = dividend:remainder((Fs,in * 2^26) / Fs,out)
259	 *     ulCorrectionPerGOF:ulCorrectionPerSec =
260	 *         dividend:remainder(ulOther / GOF_PER_SEC)
261	 *     ulInitialDelay = dividend(((24 * Fs,in) + Fs,out - 1) / Fs,out)
262	 */
263	ulTemp1 = ulOutRate << 16;
264	ulCoeffIncr = ulTemp1 / ulInRate;
265	ulTemp1 -= ulCoeffIncr * ulInRate;
266	ulTemp1 <<= 7;
267	ulCoeffIncr <<= 7;
268	ulCoeffIncr += ulTemp1 / ulInRate;
269	ulCoeffIncr ^= 0xFFFFFFFF;
270	ulCoeffIncr++;
271	ulTemp1 = ulInRate << 16;
272	ulPhiIncr = ulTemp1 / ulOutRate;
273	ulTemp1 -= ulPhiIncr * ulOutRate;
274	ulTemp1 <<= 10;
275	ulPhiIncr <<= 10;
276	ulTemp2 = ulTemp1 / ulOutRate;
277	ulPhiIncr += ulTemp2;
278	ulTemp1 -= ulTemp2 * ulOutRate;
279	ulCorrectionPerGOF = ulTemp1 / GOF_PER_SEC;
280	ulTemp1 -= ulCorrectionPerGOF * GOF_PER_SEC;
281	ulCorrectionPerSec = ulTemp1;
282	ulInitialDelay = ((ulInRate * 24) + ulOutRate - 1) / ulOutRate;
283
284	/*
285	 * Fill in the VariDecimate control block.
286	 */
287	csa_writemem(resp, BA1_CSRC,
288		     ((ulCorrectionPerSec << 16) & 0xFFFF0000) | (ulCorrectionPerGOF & 0xFFFF));
289	csa_writemem(resp, BA1_CCI, ulCoeffIncr);
290	csa_writemem(resp, BA1_CD,
291	     (((BA1_VARIDEC_BUF_1 + (ulInitialDelay << 2)) << 16) & 0xFFFF0000) | 0x80);
292	csa_writemem(resp, BA1_CPI, ulPhiIncr);
293
294	/*
295	 * Figure out the frame group length for the write back task.  Basically,
296	 * this is just the factors of 24000 (2^6*3*5^3) that are not present in
297	 * the output sample rate.
298	 */
299	dwFrameGroupLength = 1;
300	for(dwCnt = 2; dwCnt <= 64; dwCnt *= 2)
301	{
302		if(((ulOutRate / dwCnt) * dwCnt) !=
303		   ulOutRate)
304		{
305			dwFrameGroupLength *= 2;
306		}
307	}
308	if(((ulOutRate / 3) * 3) !=
309	   ulOutRate)
310	{
311		dwFrameGroupLength *= 3;
312	}
313	for(dwCnt = 5; dwCnt <= 125; dwCnt *= 5)
314	{
315		if(((ulOutRate / dwCnt) * dwCnt) !=
316		   ulOutRate)
317		{
318			dwFrameGroupLength *= 5;
319		}
320	}
321
322	/*
323	 * Fill in the WriteBack control block.
324	 */
325	csa_writemem(resp, BA1_CFG1, dwFrameGroupLength);
326	csa_writemem(resp, BA1_CFG2, (0x00800000 | dwFrameGroupLength));
327	csa_writemem(resp, BA1_CCST, 0x0000FFFF);
328	csa_writemem(resp, BA1_CSPB, ((65536 * ulOutRate) / 24000));
329	csa_writemem(resp, (BA1_CSPB + 4), 0x0000FFFF);
330}
331
332static void
333csa_startplaydma(struct csa_info *csa)
334{
335	csa_res *resp;
336	u_long ul;
337
338	if (!csa->pch.dma) {
339		resp = &csa->res;
340		ul = csa_readmem(resp, BA1_PCTL);
341		ul &= 0x0000ffff;
342		csa_writemem(resp, BA1_PCTL, ul | csa->pctl);
343		csa_writemem(resp, BA1_PVOL, 0x80008000);
344		csa->pch.dma = 1;
345	}
346}
347
348static void
349csa_startcapturedma(struct csa_info *csa)
350{
351	csa_res *resp;
352	u_long ul;
353
354	if (!csa->rch.dma) {
355		resp = &csa->res;
356		ul = csa_readmem(resp, BA1_CCTL);
357		ul &= 0xffff0000;
358		csa_writemem(resp, BA1_CCTL, ul | csa->cctl);
359		csa_writemem(resp, BA1_CVOL, 0x80008000);
360		csa->rch.dma = 1;
361	}
362}
363
364static void
365csa_stopplaydma(struct csa_info *csa)
366{
367	csa_res *resp;
368	u_long ul;
369
370	if (csa->pch.dma) {
371		resp = &csa->res;
372		ul = csa_readmem(resp, BA1_PCTL);
373		csa->pctl = ul & 0xffff0000;
374		csa_writemem(resp, BA1_PCTL, ul & 0x0000ffff);
375		csa_writemem(resp, BA1_PVOL, 0xffffffff);
376		csa->pch.dma = 0;
377
378		/*
379		 * The bitwise pointer of the serial FIFO in the DSP
380		 * seems to make an error upon starting or stopping the
381		 * DSP. Clear the FIFO and correct the pointer if we
382		 * are not capturing.
383		 */
384		if (!csa->rch.dma) {
385			csa_clearserialfifos(resp);
386			csa_writeio(resp, BA0_SERBSP, 0);
387		}
388	}
389}
390
391static void
392csa_stopcapturedma(struct csa_info *csa)
393{
394	csa_res *resp;
395	u_long ul;
396
397	if (csa->rch.dma) {
398		resp = &csa->res;
399		ul = csa_readmem(resp, BA1_CCTL);
400		csa->cctl = ul & 0x0000ffff;
401		csa_writemem(resp, BA1_CCTL, ul & 0xffff0000);
402		csa_writemem(resp, BA1_CVOL, 0xffffffff);
403		csa->rch.dma = 0;
404
405		/*
406		 * The bitwise pointer of the serial FIFO in the DSP
407		 * seems to make an error upon starting or stopping the
408		 * DSP. Clear the FIFO and correct the pointer if we
409		 * are not playing.
410		 */
411		if (!csa->pch.dma) {
412			csa_clearserialfifos(resp);
413			csa_writeio(resp, BA0_SERBSP, 0);
414		}
415	}
416}
417
418static int
419csa_startdsp(csa_res *resp)
420{
421	int i;
422	u_long ul;
423
424	/*
425	 * Set the frame timer to reflect the number of cycles per frame.
426	 */
427	csa_writemem(resp, BA1_FRMT, 0xadf);
428
429	/*
430	 * Turn on the run, run at frame, and DMA enable bits in the local copy of
431	 * the SP control register.
432	 */
433	csa_writemem(resp, BA1_SPCR, SPCR_RUN | SPCR_RUNFR | SPCR_DRQEN);
434
435	/*
436	 * Wait until the run at frame bit resets itself in the SP control
437	 * register.
438	 */
439	ul = 0;
440	for (i = 0 ; i < 25 ; i++) {
441		/*
442		 * Wait a little bit, so we don't issue PCI reads too frequently.
443		 */
444		DELAY(50);
445		/*
446		 * Fetch the current value of the SP status register.
447		 */
448		ul = csa_readmem(resp, BA1_SPCR);
449
450		/*
451		 * If the run at frame bit has reset, then stop waiting.
452		 */
453		if((ul & SPCR_RUNFR) == 0)
454			break;
455	}
456	/*
457	 * If the run at frame bit never reset, then return an error.
458	 */
459	if((ul & SPCR_RUNFR) != 0)
460		return (EAGAIN);
461
462	return (0);
463}
464
465static int
466csa_stopdsp(csa_res *resp)
467{
468	/*
469	 * Turn off the run, run at frame, and DMA enable bits in
470	 * the local copy of the SP control register.
471	 */
472	csa_writemem(resp, BA1_SPCR, 0);
473
474	return (0);
475}
476
477static int
478csa_setupchan(struct csa_chinfo *ch)
479{
480	struct csa_info *csa = ch->parent;
481	csa_res *resp = &csa->res;
482	u_long pdtc, tmp;
483
484	if (ch->dir == PCMDIR_PLAY) {
485		/* direction */
486		csa_writemem(resp, BA1_PBA, sndbuf_getbufaddr(ch->buffer));
487
488		/* format */
489		csa->pfie = csa_readmem(resp, BA1_PFIE) & ~0x0000f03f;
490		if (!(ch->fmt & AFMT_SIGNED))
491			csa->pfie |= 0x8000;
492		if (ch->fmt & AFMT_BIGENDIAN)
493			csa->pfie |= 0x4000;
494		if (AFMT_CHANNEL(ch->fmt) < 2)
495			csa->pfie |= 0x2000;
496		if (ch->fmt & AFMT_8BIT)
497			csa->pfie |= 0x1000;
498		csa_writemem(resp, BA1_PFIE, csa->pfie);
499
500		tmp = 4;
501		if (ch->fmt & AFMT_16BIT)
502			tmp <<= 1;
503		if (AFMT_CHANNEL(ch->fmt) > 1)
504			tmp <<= 1;
505		tmp--;
506
507		pdtc = csa_readmem(resp, BA1_PDTC) & ~0x000001ff;
508		pdtc |= tmp;
509		csa_writemem(resp, BA1_PDTC, pdtc);
510
511		/* rate */
512		csa_setplaysamplerate(resp, ch->spd);
513	} else if (ch->dir == PCMDIR_REC) {
514		/* direction */
515		csa_writemem(resp, BA1_CBA, sndbuf_getbufaddr(ch->buffer));
516
517		/* format */
518		csa_writemem(resp, BA1_CIE, (csa_readmem(resp, BA1_CIE) & ~0x0000003f) | 0x00000001);
519
520		/* rate */
521		csa_setcapturesamplerate(resp, ch->spd);
522	}
523	return 0;
524}
525
526/* -------------------------------------------------------------------- */
527/* channel interface */
528
529static void *
530csachan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir)
531{
532	struct csa_info *csa = devinfo;
533	struct csa_chinfo *ch = (dir == PCMDIR_PLAY)? &csa->pch : &csa->rch;
534
535	ch->parent = csa;
536	ch->channel = c;
537	ch->buffer = b;
538	ch->dir = dir;
539	if (sndbuf_alloc(ch->buffer, csa->parent_dmat, 0, CS461x_BUFFSIZE) != 0)
540		return NULL;
541	return ch;
542}
543
544static int
545csachan_setformat(kobj_t obj, void *data, u_int32_t format)
546{
547	struct csa_chinfo *ch = data;
548
549	ch->fmt = format;
550	return 0;
551}
552
553static u_int32_t
554csachan_setspeed(kobj_t obj, void *data, u_int32_t speed)
555{
556	struct csa_chinfo *ch = data;
557
558	ch->spd = speed;
559	return ch->spd; /* XXX calc real speed */
560}
561
562static u_int32_t
563csachan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
564{
565	return CS461x_BUFFSIZE / 2;
566}
567
568static int
569csachan_trigger(kobj_t obj, void *data, int go)
570{
571	struct csa_chinfo *ch = data;
572	struct csa_info *csa = ch->parent;
573
574	if (!PCMTRIG_COMMON(go))
575		return 0;
576
577	if (go == PCMTRIG_START) {
578		csa_active(csa, 1);
579		csa_setupchan(ch);
580		if (ch->dir == PCMDIR_PLAY)
581			csa_startplaydma(csa);
582		else
583			csa_startcapturedma(csa);
584	} else {
585		if (ch->dir == PCMDIR_PLAY)
586			csa_stopplaydma(csa);
587		else
588			csa_stopcapturedma(csa);
589		csa_active(csa, -1);
590	}
591	return 0;
592}
593
594static u_int32_t
595csachan_getptr(kobj_t obj, void *data)
596{
597	struct csa_chinfo *ch = data;
598	struct csa_info *csa = ch->parent;
599	csa_res *resp;
600	u_int32_t ptr;
601
602	resp = &csa->res;
603
604	if (ch->dir == PCMDIR_PLAY) {
605		ptr = csa_readmem(resp, BA1_PBA) - sndbuf_getbufaddr(ch->buffer);
606		if ((ch->fmt & AFMT_U8) != 0 || (ch->fmt & AFMT_S8) != 0)
607			ptr >>= 1;
608	} else {
609		ptr = csa_readmem(resp, BA1_CBA) - sndbuf_getbufaddr(ch->buffer);
610		if ((ch->fmt & AFMT_U8) != 0 || (ch->fmt & AFMT_S8) != 0)
611			ptr >>= 1;
612	}
613
614	return (ptr);
615}
616
617static struct pcmchan_caps *
618csachan_getcaps(kobj_t obj, void *data)
619{
620	struct csa_chinfo *ch = data;
621	return (ch->dir == PCMDIR_PLAY)? &csa_playcaps : &csa_reccaps;
622}
623
624static kobj_method_t csachan_methods[] = {
625    	KOBJMETHOD(channel_init,		csachan_init),
626    	KOBJMETHOD(channel_setformat,		csachan_setformat),
627    	KOBJMETHOD(channel_setspeed,		csachan_setspeed),
628    	KOBJMETHOD(channel_setblocksize,	csachan_setblocksize),
629    	KOBJMETHOD(channel_trigger,		csachan_trigger),
630    	KOBJMETHOD(channel_getptr,		csachan_getptr),
631    	KOBJMETHOD(channel_getcaps,		csachan_getcaps),
632	KOBJMETHOD_END
633};
634CHANNEL_DECLARE(csachan);
635
636/* -------------------------------------------------------------------- */
637/* The interrupt handler */
638static void
639csa_intr(void *p)
640{
641	struct csa_info *csa = p;
642
643	if ((csa->binfo->hisr & HISR_VC0) != 0)
644		chn_intr(csa->pch.channel);
645	if ((csa->binfo->hisr & HISR_VC1) != 0)
646		chn_intr(csa->rch.channel);
647}
648
649/* -------------------------------------------------------------------- */
650
651/*
652 * Probe and attach the card
653 */
654
655static int
656csa_init(struct csa_info *csa)
657{
658	csa_res *resp;
659
660	resp = &csa->res;
661
662	csa->pfie = 0;
663	csa_stopplaydma(csa);
664	csa_stopcapturedma(csa);
665
666	if (csa_startdsp(resp))
667		return (1);
668
669	/* Crank up the power on the DAC and ADC. */
670	csa_setplaysamplerate(resp, 8000);
671	csa_setcapturesamplerate(resp, 8000);
672	/* Set defaults */
673	csa_writeio(resp, BA0_EGPIODR, EGPIODR_GPOE0);
674	csa_writeio(resp, BA0_EGPIOPTR, EGPIOPTR_GPPT0);
675	/* Power up amplifier */
676	csa_writeio(resp, BA0_EGPIODR, csa_readio(resp, BA0_EGPIODR) |
677		EGPIODR_GPOE2);
678	csa_writeio(resp, BA0_EGPIOPTR, csa_readio(resp, BA0_EGPIOPTR) |
679		EGPIOPTR_GPPT2);
680
681	return 0;
682}
683
684/* Allocates resources. */
685static int
686csa_allocres(struct csa_info *csa, device_t dev)
687{
688	csa_res *resp;
689
690	resp = &csa->res;
691	if (resp->io == NULL) {
692		resp->io = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
693			&resp->io_rid, RF_ACTIVE);
694		if (resp->io == NULL)
695			return (1);
696	}
697	if (resp->mem == NULL) {
698		resp->mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
699			&resp->mem_rid, RF_ACTIVE);
700		if (resp->mem == NULL)
701			return (1);
702	}
703	if (resp->irq == NULL) {
704		resp->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ,
705			&resp->irq_rid, RF_ACTIVE | RF_SHAREABLE);
706		if (resp->irq == NULL)
707			return (1);
708	}
709	if (bus_dma_tag_create(/*parent*/bus_get_dma_tag(dev),
710			       /*alignment*/CS461x_BUFFSIZE,
711			       /*boundary*/CS461x_BUFFSIZE,
712			       /*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
713			       /*highaddr*/BUS_SPACE_MAXADDR,
714			       /*filter*/NULL, /*filterarg*/NULL,
715			       /*maxsize*/CS461x_BUFFSIZE, /*nsegments*/1, /*maxsegz*/0x3ffff,
716			       /*flags*/0, /*lockfunc*/NULL, /*lockarg*/NULL,
717			       &csa->parent_dmat) != 0)
718		return (1);
719
720	return (0);
721}
722
723/* Releases resources. */
724static void
725csa_releaseres(struct csa_info *csa, device_t dev)
726{
727	csa_res *resp;
728
729	KASSERT(csa != NULL, ("called with bogus resource structure"));
730
731	resp = &csa->res;
732	if (resp->irq != NULL) {
733		if (csa->ih)
734			bus_teardown_intr(dev, resp->irq, csa->ih);
735		bus_release_resource(dev, SYS_RES_IRQ, resp->irq_rid, resp->irq);
736		resp->irq = NULL;
737	}
738	if (resp->io != NULL) {
739		bus_release_resource(dev, SYS_RES_MEMORY, resp->io_rid, resp->io);
740		resp->io = NULL;
741	}
742	if (resp->mem != NULL) {
743		bus_release_resource(dev, SYS_RES_MEMORY, resp->mem_rid, resp->mem);
744		resp->mem = NULL;
745	}
746	if (csa->parent_dmat != NULL) {
747		bus_dma_tag_destroy(csa->parent_dmat);
748		csa->parent_dmat = NULL;
749	}
750
751	free(csa, M_DEVBUF);
752}
753
754static int
755pcmcsa_probe(device_t dev)
756{
757	char *s;
758	struct sndcard_func *func;
759
760	/* The parent device has already been probed. */
761
762	func = device_get_ivars(dev);
763	if (func == NULL || func->func != SCF_PCM)
764		return (ENXIO);
765
766	s = "CS461x PCM Audio";
767
768	device_set_desc(dev, s);
769	return (0);
770}
771
772static int
773pcmcsa_attach(device_t dev)
774{
775	struct csa_info *csa;
776	csa_res *resp;
777	char status[SND_STATUSLEN];
778	struct ac97_info *codec;
779	struct sndcard_func *func;
780
781	csa = malloc(sizeof(*csa), M_DEVBUF, M_WAITOK | M_ZERO);
782	func = device_get_ivars(dev);
783	csa->binfo = func->varinfo;
784	/*
785	 * Fake the status of DMA so that the initial value of
786	 * PCTL and CCTL can be stored into csa->pctl and csa->cctl,
787	 * respectively.
788	 */
789	csa->pch.dma = csa->rch.dma = 1;
790	csa->active = 0;
791	csa->card = csa->binfo->card;
792
793	/* Allocate the resources. */
794	resp = &csa->res;
795	resp->io_rid = PCIR_BAR(0);
796	resp->mem_rid = PCIR_BAR(1);
797	resp->irq_rid = 0;
798	if (csa_allocres(csa, dev)) {
799		csa_releaseres(csa, dev);
800		return (ENXIO);
801	}
802
803	csa_active(csa, 1);
804	if (csa_init(csa)) {
805		csa_releaseres(csa, dev);
806		return (ENXIO);
807	}
808	codec = AC97_CREATE(dev, csa, csa_ac97);
809	if (codec == NULL) {
810		csa_releaseres(csa, dev);
811		return (ENXIO);
812	}
813	if (csa->card->inv_eapd)
814		ac97_setflags(codec, AC97_F_EAPD_INV);
815	if (mixer_init(dev, ac97_getmixerclass(), codec) == -1) {
816		ac97_destroy(codec);
817		csa_releaseres(csa, dev);
818		return (ENXIO);
819	}
820
821	snprintf(status, SND_STATUSLEN, "irq %jd on %s",
822			rman_get_start(resp->irq),
823			device_get_nameunit(device_get_parent(dev)));
824
825	/* Enable interrupt. */
826	if (snd_setup_intr(dev, resp->irq, 0, csa_intr, csa, &csa->ih)) {
827		ac97_destroy(codec);
828		csa_releaseres(csa, dev);
829		return (ENXIO);
830	}
831	csa_writemem(resp, BA1_PFIE, csa_readmem(resp, BA1_PFIE) & ~0x0000f03f);
832	csa_writemem(resp, BA1_CIE, (csa_readmem(resp, BA1_CIE) & ~0x0000003f) | 0x00000001);
833	csa_active(csa, -1);
834
835	if (pcm_register(dev, csa, 1, 1)) {
836		ac97_destroy(codec);
837		csa_releaseres(csa, dev);
838		return (ENXIO);
839	}
840	pcm_addchan(dev, PCMDIR_REC, &csachan_class, csa);
841	pcm_addchan(dev, PCMDIR_PLAY, &csachan_class, csa);
842	pcm_setstatus(dev, status);
843
844	return (0);
845}
846
847static int
848pcmcsa_detach(device_t dev)
849{
850	int r;
851	struct csa_info *csa;
852
853	r = pcm_unregister(dev);
854	if (r)
855		return r;
856
857	csa = pcm_getdevinfo(dev);
858	csa_releaseres(csa, dev);
859
860	return 0;
861}
862
863static void
864csa_ac97_suspend(struct csa_info *csa)
865{
866	int count, i;
867	uint32_t tmp;
868
869	for (count = 0x2, i=0;
870	    (count <= CS461x_AC97_HIGHESTREGTORESTORE) &&
871	    (i < CS461x_AC97_NUMBER_RESTORE_REGS);
872	    count += 2, i++)
873		csa_readcodec(&csa->res, BA0_AC97_RESET + count, &csa->ac97[i]);
874
875	/* mute the outputs */
876	csa_writecodec(&csa->res, BA0_AC97_MASTER_VOLUME, 0x8000);
877	csa_writecodec(&csa->res, BA0_AC97_HEADPHONE_VOLUME, 0x8000);
878	csa_writecodec(&csa->res, BA0_AC97_MASTER_VOLUME_MONO, 0x8000);
879	csa_writecodec(&csa->res, BA0_AC97_PCM_OUT_VOLUME, 0x8000);
880	/* save the registers that cause pops */
881	csa_readcodec(&csa->res, BA0_AC97_POWERDOWN, &csa->ac97_powerdown);
882	csa_readcodec(&csa->res, BA0_AC97_GENERAL_PURPOSE,
883	    &csa->ac97_general_purpose);
884
885	/*
886	 * And power down everything on the AC97 codec. Well, for now,
887	 * only power down the DAC/ADC and MIXER VREFON components.
888	 * trouble with removing VREF.
889	 */
890
891	/* MIXVON */
892	csa_readcodec(&csa->res, BA0_AC97_POWERDOWN, &tmp);
893	csa_writecodec(&csa->res, BA0_AC97_POWERDOWN,
894	    tmp | CS_AC97_POWER_CONTROL_MIXVON);
895	/* ADC */
896	csa_readcodec(&csa->res, BA0_AC97_POWERDOWN, &tmp);
897	csa_writecodec(&csa->res, BA0_AC97_POWERDOWN,
898	    tmp | CS_AC97_POWER_CONTROL_ADC);
899	/* DAC */
900	csa_readcodec(&csa->res, BA0_AC97_POWERDOWN, &tmp);
901	csa_writecodec(&csa->res, BA0_AC97_POWERDOWN,
902	    tmp | CS_AC97_POWER_CONTROL_DAC);
903}
904
905static void
906csa_ac97_resume(struct csa_info *csa)
907{
908	int count, i;
909
910	/*
911	 * First, we restore the state of the general purpose register.  This
912	 * contains the mic select (mic1 or mic2) and if we restore this after
913	 * we restore the mic volume/boost state and mic2 was selected at
914	 * suspend time, we will end up with a brief period of time where mic1
915	 * is selected with the volume/boost settings for mic2, causing
916	 * acoustic feedback.  So we restore the general purpose register
917	 * first, thereby getting the correct mic selected before we restore
918	 * the mic volume/boost.
919	 */
920	csa_writecodec(&csa->res, BA0_AC97_GENERAL_PURPOSE,
921	    csa->ac97_general_purpose);
922	/*
923	 * Now, while the outputs are still muted, restore the state of power
924	 * on the AC97 part.
925	 */
926	csa_writecodec(&csa->res, BA0_AC97_POWERDOWN, csa->ac97_powerdown);
927	/*
928	 * Restore just the first set of registers, from register number
929	 * 0x02 to the register number that ulHighestRegToRestore specifies.
930	 */
931	for (count = 0x2, i=0;
932	    (count <= CS461x_AC97_HIGHESTREGTORESTORE) &&
933	    (i < CS461x_AC97_NUMBER_RESTORE_REGS);
934	    count += 2, i++)
935		csa_writecodec(&csa->res, BA0_AC97_RESET + count, csa->ac97[i]);
936}
937
938static int
939pcmcsa_suspend(device_t dev)
940{
941	struct csa_info *csa;
942	csa_res *resp;
943
944	csa = pcm_getdevinfo(dev);
945	resp = &csa->res;
946
947	csa_active(csa, 1);
948
949	/* playback interrupt disable */
950	csa_writemem(resp, BA1_PFIE,
951	    (csa_readmem(resp, BA1_PFIE) & ~0x0000f03f) | 0x00000010);
952	/* capture interrupt disable */
953	csa_writemem(resp, BA1_CIE,
954	    (csa_readmem(resp, BA1_CIE) & ~0x0000003f) | 0x00000011);
955	csa_stopplaydma(csa);
956	csa_stopcapturedma(csa);
957
958	csa_ac97_suspend(csa);
959
960	csa_resetdsp(resp);
961
962	csa_stopdsp(resp);
963	/*
964	 *  Power down the DAC and ADC.  For now leave the other areas on.
965	 */
966	csa_writecodec(&csa->res, BA0_AC97_POWERDOWN, 0x300);
967	/*
968	 *  Power down the PLL.
969	 */
970	csa_writemem(resp, BA0_CLKCR1, 0);
971	/*
972	 * Turn off the Processor by turning off the software clock
973	 * enable flag in the clock control register.
974	 */
975	csa_writemem(resp, BA0_CLKCR1,
976	    csa_readmem(resp, BA0_CLKCR1) & ~CLKCR1_SWCE);
977
978	csa_active(csa, -1);
979
980	return 0;
981}
982
983static int
984pcmcsa_resume(device_t dev)
985{
986	struct csa_info *csa;
987	csa_res *resp;
988
989	csa = pcm_getdevinfo(dev);
990	resp = &csa->res;
991
992	csa_active(csa, 1);
993
994	/* cs_hardware_init */
995	csa_stopplaydma(csa);
996	csa_stopcapturedma(csa);
997	csa_ac97_resume(csa);
998	if (csa_startdsp(resp))
999		return (ENXIO);
1000	/* Enable interrupts on the part. */
1001	if ((csa_readio(resp, BA0_HISR) & HISR_INTENA) == 0)
1002		csa_writeio(resp, BA0_HICR, HICR_IEV | HICR_CHGM);
1003	/* playback interrupt enable */
1004	csa_writemem(resp, BA1_PFIE, csa_readmem(resp, BA1_PFIE) & ~0x0000f03f);
1005	/* capture interrupt enable */
1006	csa_writemem(resp, BA1_CIE,
1007	    (csa_readmem(resp, BA1_CIE) & ~0x0000003f) | 0x00000001);
1008	/* cs_restart_part */
1009	csa_setupchan(&csa->pch);
1010	csa_startplaydma(csa);
1011	csa_setupchan(&csa->rch);
1012	csa_startcapturedma(csa);
1013
1014	csa_active(csa, -1);
1015
1016	return 0;
1017}
1018
1019static device_method_t pcmcsa_methods[] = {
1020	/* Device interface */
1021	DEVMETHOD(device_probe , pcmcsa_probe ),
1022	DEVMETHOD(device_attach, pcmcsa_attach),
1023	DEVMETHOD(device_detach, pcmcsa_detach),
1024	DEVMETHOD(device_suspend, pcmcsa_suspend),
1025	DEVMETHOD(device_resume, pcmcsa_resume),
1026
1027	{ 0, 0 },
1028};
1029
1030static driver_t pcmcsa_driver = {
1031	"pcm",
1032	pcmcsa_methods,
1033	PCM_SOFTC_SIZE,
1034};
1035
1036DRIVER_MODULE(snd_csapcm, csa, pcmcsa_driver, 0, 0);
1037MODULE_DEPEND(snd_csapcm, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER);
1038MODULE_DEPEND(snd_csapcm, snd_csa, 1, 1, 1);
1039MODULE_VERSION(snd_csapcm, 1);
1040