1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #ifndef	_AUDIO810_H_
27 #define	_AUDIO810_H_
28 
29 /*
30  * Header file for the audio810 device driver
31  */
32 
33 /*
34  * Driver supported configuration information
35  */
36 #define	I810_NAME			"audio810"
37 #define	I810_MOD_NAME			"audio810 audio driver"
38 
39 #define	I810_INTS			(175)	/* default interrupt rate */
40 #define	I810_MIN_INTS			(24)	/* minimum interrupt rate */
41 #define	I810_MAX_INTS			(5000)	/* maximum interrupt rate */
42 #define	I810_NFRAGS			(8)	/* default # fragments */
43 
44 /*
45  * Misc. defines
46  */
47 
48 #define	I810_BD_NUMS			(32)
49 #define	I810_NUM_PORTS			(2)
50 #define	I810_MOD_SIZE			(16)
51 
52 #define	I810_ROUNDUP(x, algn)		(((x) + ((algn) - 1)) & ~((algn) - 1))
53 #define	I810_KIOP(X)			((kstat_intr_t *)(X->ksp->ks_data))
54 
55 /* The size of each entry of "reg" property is 5 integers */
56 #define	I810_INTS_PER_REG_PROP		5
57 
58 /* offset from the base of specified DMA engine */
59 #define	I810_OFFSET_BD_BASE		(0x00)
60 #define	I810_OFFSET_CIV			(0x04)
61 #define	I810_OFFSET_LVI			(0x05)
62 #define	I810_OFFSET_SR			(0x06)
63 #define	I810_OFFSET_PICB		(0x08)
64 #define	I810_OFFSET_PIV			(0x0A)
65 #define	I810_OFFSET_CR			(0x0B)
66 
67 /* DMA engine offset from base */
68 #define	I810_BASE_PCM_IN		(0x00)
69 #define	I810_BASE_PCM_OUT		(0x10)
70 #define	I810_BASE_MIC			(0x20)
71 
72 #define	I810_REG_GCR			0x2C
73 #define	I810_REG_GSR			0x30
74 #define	I810_REG_CASR			0x34
75 #define	I810_REG_SISCTL			0x4C	/* SiS 7012 control */
76 
77 /* bits of bus master status register */
78 #define	I810_BM_SR_DCH			0x01
79 #define	I810_BM_SR_CELV			0x02
80 #define	I810_BM_SR_LVBCI		0x04
81 #define	I810_BM_SR_BCIS			0x08
82 #define	I810_BM_SR_FIFOE		0x10
83 
84 /* bits of bus master control register */
85 #define	I810_BM_CR_RUN			0x01
86 #define	I810_BM_CR_RST			0x02
87 #define	I810_BM_CR_LVBIE		0x04
88 #define	I810_BM_CR_FEIE			0x08
89 #define	I810_BM_CR_IOCE			0x10
90 
91 #define	I810_BM_CR_PAUSE		0x00
92 
93 /*
94  * Global Control Register
95  */
96 #define	I810_GCR_GPIE			0x00000001
97 #define	I810_GCR_COLD_RST		0x00000002
98 #define	I810_GCR_WARM_RST		0x00000004
99 #define	I810_GCR_ACLINK_OFF		0x00000008
100 #define	I810_GCR_PRI_INTR_ENABLE	0x00000010
101 #define	I810_GCR_SEC_INTR_ENABLE	0x00000020
102 
103 /* For ICH2 or more, bit21:20 is the PCM 4/6-channel enable bits */
104 #define	I810_GCR_2_CHANNELS		(0 << 20)
105 #define	I810_GCR_4_CHANNELS		(1 << 20)
106 #define	I810_GCR_6_CHANNELS		(2 << 20)
107 #define	I810_GCR_CHANNELS_MASK		(3 << 20)
108 /* SiS 7012 has its own flags here */
109 #define	I810_GCR_SIS_2_CHANNELS		(0 << 6)
110 #define	I810_GCR_SIS_4_CHANNELS		(1 << 6)
111 #define	I810_GCR_SIS_6_CHANNELS		(2 << 6)
112 #define	I810_GCR_SIS_CHANNELS_MASK	(3 << 6)
113 
114 
115 /*
116  * Global Status Register
117  */
118 #define	I810_GSR_TRI_READY		0x10000000	/* for ICH4/5 */
119 #define	I810_GSR_CAP8CH			0x00400000
120 #define	I810_GSR_CAP6CH			0x00200000
121 #define	I810_GSR_CAP4CH			0x00100000
122 #define	I810_GSR_READ_COMPL		0x00008000
123 #define	I810_GSR_INTR_SEC_RESUME	0x00000800
124 #define	I810_GSR_INTR_PRI_RESUME	0x00000400
125 #define	I810_GSR_SEC_READY		0x00000200
126 #define	I810_GSR_PRI_READY		0x00000100
127 #define	I810_GSR_INTR_MIC		0x00000080
128 #define	I810_GSR_INTR_POUT		0x00000040
129 #define	I810_GSR_INTR_PIN		0x00000020
130 #define	I810_GSR_INTR_MO		0x00000004
131 #define	I810_GSR_INTR_MI		0x00000002
132 #define	I810_GSR_INTR_GSI		0x00000001
133 #define	I810_GSR_USE_INTR		0x00000060	/* PCM-IN ,PCM-OUT */
134 
135 /*
136  * SiS Control Register
137  */
138 #define	I810_SISCTL_UNMUTE		0x01
139 
140 /*
141  * Macro for AD1980 codec
142  */
143 #define	AD1980_VID1		0x4144
144 #define	AD1980_VID2		0x5370
145 #define	AD1985_VID2		0x5375
146 #define	CODEC_AD_REG_MISC	0x76	/* offset of ad1980 misc control reg */
147 #define	AD1980_MISC_LOSEL	0x0020	/* Line-out amplifier output selector */
148 #define	AD1980_MISC_HPSEL	0x0400	/* HP-out amplifier output selector */
149 #define	AD1980_SURR_MUTE	0x8080	/* Mute for surround volume register */
150 
151 #define	I810_PCM_IN		0
152 #define	I810_PCM_OUT		1
153 
154 struct audio810_port {
155 	struct audio810_state	*statep;
156 	int			num;
157 	ddi_dma_handle_t	samp_dmah;
158 	ddi_acc_handle_t	samp_acch;
159 	size_t			samp_size;
160 	caddr_t			samp_kaddr;
161 	uint32_t		samp_paddr;
162 
163 	ddi_dma_handle_t	bdl_dmah;
164 	ddi_acc_handle_t	bdl_acch;
165 	size_t			bdl_size;
166 	caddr_t			bdl_kaddr;
167 	uint32_t		bdl_paddr;
168 
169 	unsigned		intrs;
170 	unsigned		fragfr;
171 	unsigned		fragsz;
172 	uint64_t		count;
173 	uint8_t			nfrag;
174 	uint8_t			nchan;
175 
176 	uint8_t			regoff;
177 	uint8_t			stsoff;		/* status offset */
178 	uint8_t			picboff;	/* picb offset */
179 	uint8_t			civ;
180 	uint16_t		picb;
181 	unsigned		sync_dir;
182 
183 	boolean_t		started;
184 
185 	audio_engine_t		*engine;
186 };
187 typedef struct audio810_port audio810_port_t;
188 
189 /*
190  * buffer descripter list entry, sees datasheet
191  */
192 struct i810_bd_entry {
193 	uint32_t	buf_base;	/* the address of the buffer */
194 	uint16_t	buf_len;	/* the number of samples */
195 	uint16_t	buf_cmd;
196 };
197 typedef struct	i810_bd_entry	i810_bd_entry_t;
198 #define	BUF_CMD_BUP	0x4000
199 #define	BUF_CMD_IOC	0x8000
200 
201 typedef enum i810_quirk {
202 	QUIRK_NONE = 0,
203 	QUIRK_SIS7012,		/* weird registers and such */
204 } i810_quirk_t;
205 
206 /*
207  * audio810_state_t	-per instance state and operation data
208  */
209 struct audio810_state {
210 	kmutex_t		inst_lock;	/* state protection lock */
211 	kmutex_t		ac_lock;
212 	ddi_iblock_cookie_t	iblock;
213 	dev_info_t		*dip;	/* used by audio810_getinfo() */
214 	audio_dev_t		*adev;
215 	ac97_t			*ac97;
216 	audio810_port_t		*ports[2];
217 
218 	ddi_acc_handle_t	am_regs_handle;	/* for audio mixer register */
219 	ddi_acc_handle_t	bm_regs_handle;	/* for bus master register */
220 	caddr_t			am_regs_base;	/* base of audio mixer regs */
221 	caddr_t			bm_regs_base;	/* base of bus master regs */
222 
223 	kstat_t			*ksp;		/* kernel statistics */
224 
225 	boolean_t		intr_added;
226 	boolean_t		suspended;	/* suspend/resume state */
227 	uint8_t			maxch;
228 	i810_quirk_t		quirk;
229 };
230 typedef struct audio810_state	 audio810_state_t;
231 
232 /*
233  * Useful bit twiddlers
234  */
235 #define	I810_BM_GET8(reg)	\
236 	ddi_get8(statep->bm_regs_handle, \
237 	(void *)((char *)statep->bm_regs_base + (reg)))
238 
239 #define	I810_BM_GET16(reg)	\
240 	ddi_get16(statep->bm_regs_handle, \
241 	(void *)((char *)statep->bm_regs_base + (reg)))
242 
243 #define	I810_BM_GET32(reg)	\
244 	ddi_get32(statep->bm_regs_handle, \
245 	(void *)((char *)statep->bm_regs_base + (reg)))
246 
247 #define	I810_BM_PUT8(reg, val)	\
248 	ddi_put8(statep->bm_regs_handle, \
249 	(void *)((char *)statep->bm_regs_base + (reg)), (val))
250 
251 #define	I810_BM_PUT16(reg, val)	\
252 	ddi_put16(statep->bm_regs_handle, \
253 	(void *)((char *)statep->bm_regs_base + (reg)), (val))
254 
255 #define	I810_BM_PUT32(reg, val)	\
256 	ddi_put32(statep->bm_regs_handle, \
257 	(void *)((char *)statep->bm_regs_base + (reg)), (val))
258 
259 #define	I810_AM_GET16(reg)	\
260 	ddi_get16(statep->am_regs_handle, \
261 	(void *)((char *)statep->am_regs_base + (reg)))
262 
263 #define	I810_AM_PUT16(reg, val)	\
264 	ddi_put16(statep->am_regs_handle, \
265 	(void *)((char *)statep->am_regs_base + (reg)), (val))
266 
267 #endif /* _AUDIO810_H_ */
268