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