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
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
|
/*
* 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.
*/
/*
* Purpose: Driver for CMEDIA CM8738 PCI audio controller.
*/
/*
* This file is part of Open Sound System
*
* Copyright (C) 4Front Technologies 1996-2008.
*
* This software is released under CDDL 1.0 source license.
* See the COPYING file included in the main directory of this source
* distribution for the license terms and conditions.
*/
#ifndef _AUDIOCMI_H
#define _AUDIOCMI_H
#define CMEDIA_VENDOR_ID 0x13F6
#define CMEDIA_CM8738 0x0111
#define CMEDIA_CM8338A 0x0100
#define CMEDIA_CM8338B 0x0101
/*
* CM8338 registers definition
*/
#define REG_FUNCTRL0 0x00
#define REG_FUNCTRL1 0x04
#define REG_CHFORMAT 0x08
#define REG_INTCTRL 0x0C
#define REG_INTSTAT 0x10
#define REG_LEGACY 0x14
#define REG_MISC 0x18
#define REG_TDMAPOS 0x1C
#define REG_SBVER 0x20 /* 8 bit access only */
#define REG_IDXDATA 0x22 /* 8 bit access only */
#define REG_IDXADDR 0x23 /* 8 bit access only */
#define REG_MIX2 0x24
#define REG_MIX3 0x25
#define REG_VAUX 0x26
#define REG_CH0_PADDR 0x80 /* buffer address (32b) */
#define REG_CH0_BUFSZ 0x84 /* buffer size in samples (16b) */
#define REG_CH0_FRAGSZ 0x86 /* fragment size in samples (16b) */
#define REG_CH1_PADDR 0x88
#define REG_CH1_BUFSZ 0x8C
#define REG_CH1_FRAGSZ 0x8E
#define REG_SPDIF_STAT 0x90
#define REG_MISC2 0x92
#define FUNCTRL0_CH1_RST BIT(19)
#define FUNCTRL0_CH0_RST BIT(18)
#define FUNCTRL0_CH1_EN BIT(17)
#define FUNCTRL0_CH0_EN BIT(16)
#define FUNCTRL0_CH1_PAUSE BIT(3)
#define FUNCTRL0_CH0_PAUSE BIT(2)
#define FUNCTRL0_CH1_REC BIT(1)
#define FUNCTRL0_CH0_REC BIT(0)
#define FUNCTRL1_DAC_RATE_MASK (0x7 << 13)
#define FUNCTRL1_DAC_RATE_48K (0x7 << 13)
#define FUNCTRL1_DAC_RATE_32K (0x6 << 13)
#define FUNCTRL1_DAC_RATE_16K (0x5 << 13)
#define FUNCTRL1_DAC_RATE_8K (0x4 << 13)
#define FUNCTRL1_DAC_RATE_44K (0x3 << 13)
#define FUNCTRL1_DAC_RATE_22K (0x2 << 13)
#define FUNCTRL1_DAC_RATE_11K (0x1 << 13)
#define FUNCTRL1_DAC_RATE_5K (0x0 << 13)
#define FUNCTRL1_ADC_RATE_MASK (0x7 << 10)
#define FUNCTRL1_ADC_RATE_48K (0x7 << 10)
#define FUNCTRL1_ADC_RATE_32K (0x6 << 10)
#define FUNCTRL1_ADC_RATE_16K (0x5 << 10)
#define FUNCTRL1_ADC_RATE_8K (0x4 << 10)
#define FUNCTRL1_ADC_RATE_44K (0x3 << 10)
#define FUNCTRL1_ADC_RATE_22K (0x2 << 10)
#define FUNCTRL1_ADC_RATE_11K (0x1 << 10)
#define FUNCTRL1_ADC_RATE_5K (0x0 << 10)
#define FUNCTRL1_INTRM BIT(5) /* enable MCB intr */
#define FUNCTRL1_BREQ BIT(4) /* bus master enable */
#define FUNCTRL1_VOICE_EN BIT(3)
#define FUNCTRL1_UART_EN BIT(2)
#define FUNCTRL1_JYSTK_EN BIT(1)
#define CHFORMAT_CHB3D5C BIT(31) /* 5 channel surround */
#define CHFORMAT_CHB3D BIT(29) /* 4 channel surround */
#define CHFORMAT_VER_MASK (0x1f << 24)
#define CHFORMAT_VER_033 0
#define CHFORMAT_VER_037 1
#define CHFORMAT_CH1_MASK (0x3 << 2)
#define CHFORMAT_CH1_16ST (0x3 << 2)
#define CHFORMAT_CH1_16MO (0x2 << 2)
#define CHFORMAT_CH1_8ST (0x1 << 2)
#define CHFORMAT_CH1_8MO (0x0 << 2)
#define CHFORMAT_CH0_MASK (0x3 << 0)
#define CHFORMAT_CH0_16ST (0x3 << 0)
#define CHFORMAT_CH0_16MO (0x2 << 0)
#define CHFORMAT_CH0_8ST (0x1 << 0)
#define CHFORMAT_CH0_8MO (0x0 << 0)
#define INTCTRL_MDL_MASK (0xffU << 24)
#define INTCTRL_MDL_068 (0x28 << 24)
#define INTCTRL_MDL_055 (0x8 << 24)
#define INTCTRL_MDL_039 (0x4 << 24)
#define INTCTRL_TDMA_EN BIT(18)
#define INTCTRL_CH1_EN BIT(17)
#define INTCTRL_CH0_EN BIT(16)
#define INTSTAT_INTR BIT(31)
#define INTSTAT_MCB_INT BIT(26)
#define INTSTAT_UART_INT BIT(16)
#define INTSTAT_LTDMA_INT BIT(15)
#define INTSTAT_HTDMA_INT BIT(14)
#define INTSTAT_LHBTOG BIT(7)
#define INTSTAT_LEGDMA BIT(6)
#define INTSTAT_LEGHIGH BIT(5)
#define INTSTAT_LEGSTEREO BIT(4)
#define INTSTAT_CH1_BUSY BIT(3)
#define INTSTAT_CH0_BUSY BIT(2)
#define INTSTAT_CH1_INT BIT(1)
#define INTSTAT_CH0_INT BIT(0)
#define LEGACY_NXCHG BIT(31)
#define LEGACY_CHB3D6C BIT(15) /* 6 channel surround */
#define LEGACY_CENTR2LN BIT(14) /* line in as center out */
#define LEGACY_BASS2LN BIT(13) /* line in as lfe */
#define LEGACY_EXBASSEN BIT(12) /* external bass input enable */
#define MISC_PWD BIT(31) /* power down */
#define MISC_RESET BIT(30)
#define MISC_N4SPK3D BIT(26) /* 4 channel emulation */
#define MISC_ENDBDAC BIT(23) /* dual dac */
#define MISC_XCHGDAC BIT(22) /* swap front/rear dacs */
#define MISC_SPD32SEL BIT(21) /* 32-bit SPDIF (default 16-bit) */
#define MISC_FM_EN BIT(19) /* enable legacy FM */
#define MISC_SPDF_AC97 BIT(15) /* spdif out 44.1k (0), 48 k (1) */
#define MISC_ENCENTER BIT(7) /* enable center */
#define MISC_REAR2LN BIT(6) /* send rear to line in */
#define MIX2_FMMUTE BIT(7)
#define MIX2_WSMUTE BIT(6)
#define MIX2_SPK4 BIT(5) /* line-in is rear out */
#define MIX2_REAR2FRONT BIT(4) /* swap front and rear */
#define MIX2_WAVEIN_L BIT(3) /* for recording wave out */
#define MIX2_WAVEIN_R BIT(2) /* for recording wave out */
#define MIX2_X3DEN BIT(1) /* 3D surround enable */
#define MIX2_CDPLAY BIT(0) /* spdif-in PCM to DAC */
#define MIX3_RAUXREN BIT(7)
#define MIX3_RAUXLEN BIT(6)
#define MIX3_VAUXRM BIT(5) /* r-aux mute */
#define MIX3_VAUXLM BIT(4) /* l-aux mute */
#define MIX3_VADCMIC_MASK (0x7 << 1) /* rec mic volume */
#define MIX3_CEN2MIC BIT(2)
#define MIX3_MICGAINZ BIT(0) /* mic gain */
#define VAUX_L_MASK 0xf0
#define VAUX_R_MASK 0x0f
#define MISC2_CHB3D8C BIT(5) /* 8 channel surround */
#define MISC2_SPD32FMT BIT(4) /* spdif at 32 kHz */
#define MISC2_ADC2SPDIF BIT(3) /* send adc to spdif out */
#define MISC2_SHAREADC BIT(2) /* use adc for cen/lfe */
/* Indexes via SBINDEX */
#define IDX_MASTER_LEFT 0x30
#define IDX_MASTER_RIGHT 0x31
#define IDX_VOICE_LEFT 0x32 /* PCM volume */
#define IDX_VOICE_RIGHT 0x33
#define IDX_CDDA_LEFT 0x36
#define IDX_CDDA_RIGHT 0x37
#define IDX_LINEIN_LEFT 0x38
#define IDX_LINEIN_RIGHT 0x39
#define IDX_MIC 0x3A
#define IDX_SPEAKER 0x3B
#define IDX_OUTMIX 0x3C
#define OUTMIX_MIC 0x01
#define OUTMIX_CD_R 0x02
#define OUTMIX_CD_L 0x04
#define OUTMIX_LINE_R 0x08
#define OUTMIX_LINE_L 0x10
#define IDX_INMIX_L 0x3D
#define IDX_INMIX_R 0x3E
#define INMIX_LINE_R 0x08
#define INMIX_LINE_L 0x10
#define INMIX_CD_R 0x20
#define INMIX_CD_L 0x40
#define INMIX_MIC 0x01
#define IDX_IGAIN_L 0x3F
#define IDX_IGAIN_R 0x40
#define IDX_OGAIN_L 0x41
#define IDX_OGAIN_R 0x42
#define IDX_AGC 0x43
#define IDX_TREBLE_L 0x44
#define IDX_TREBLE_R 0x45
#define IDX_BASS_L 0x46
#define IDX_BASS_R 0x47
#define IDX_EXTENSION 0xf0
#define EXTENSION_VPHONE_MASK (0x7 << 5)
#define EXTENSION_VPHONE_MUTE BIT(4)
#define EXTENSION_BEEPER_MUTE BIT(3)
#define EXTENSION_VADCMIC3 BIT(0)
enum {
SRC_MIC = 0,
SRC_LINE,
SRC_CD,
SRC_AUX,
SRC_MIX,
};
enum {
CTL_VOLUME = 0,
CTL_LINEOUT,
CTL_SPEAKER,
CTL_MIC,
CTL_LINEIN,
CTL_CD,
CTL_AUX,
CTL_RECSRCS,
CTL_MONSRCS,
CTL_MICBOOST,
CTL_NUM
};
typedef struct cmpci_port cmpci_port_t;
typedef struct cmpci_dev cmpci_dev_t;
typedef struct cmpci_ctrl cmpci_ctrl_t;
struct cmpci_ctrl {
cmpci_dev_t *dev;
audio_ctrl_t *ctrl;
uint64_t value;
};
struct cmpci_port {
cmpci_dev_t *dev;
audio_engine_t *engine;
int num;
ddi_acc_handle_t acch;
ddi_dma_handle_t dmah;
caddr_t kaddr;
uint32_t paddr;
unsigned nframes;
unsigned bufsz;
unsigned nchan;
boolean_t capture;
boolean_t open;
/* registers & bit masks */
uint8_t reg_paddr;
uint8_t reg_bufsz;
uint8_t reg_fragsz;
uint32_t fc0_rst_bit;
uint32_t fc0_rec_bit;
uint32_t fc0_en_bit;
uint32_t int_en_bit;
uint32_t fc1_rate_mask;
uint32_t chformat_mask;
int sync_dir;
uint32_t offset; /* in bytes */
uint64_t count; /* in bytes */
void (*callb)(audio_engine_t *);
cmpci_ctrl_t controls[CTL_NUM];
};
#define PORT_MAX 2
struct cmpci_dev {
audio_dev_t *adev;
dev_info_t *dip;
ddi_acc_handle_t acch;
caddr_t regs;
boolean_t softvol;
int pintrs;
int rintrs;
ddi_intr_handle_t ihandle;
kstat_t *ksp;
int maxch;
kmutex_t mutex;
cmpci_port_t port[PORT_MAX];
cmpci_ctrl_t controls[CTL_NUM];
};
/*
* The hardware appears to be able to address up to 16-bits worth of samples,
* giving a total address space of 256K. Note, however, that we will restrict
* this further when we do fragment and memory allocation.
*/
#define DEFINTS 175
#define GET8(dev, offset) \
ddi_get8(dev->acch, (uint8_t *)(dev->regs + (offset)))
#define GET16(dev, offset) \
ddi_get16(dev->acch, (uint16_t *)(void *)(dev->regs + (offset)))
#define GET32(dev, offset) \
ddi_get32(dev->acch, (uint32_t *)(void *)(dev->regs + (offset)))
#define PUT8(dev, offset, v) \
ddi_put8(dev->acch, (uint8_t *)(dev->regs + (offset)), v)
#define PUT16(dev, offset, v) \
ddi_put16(dev->acch, (uint16_t *)(void *)(dev->regs + (offset)), v)
#define PUT32(dev, offset, v) \
ddi_put32(dev->acch, (uint32_t *)(void *)(dev->regs + (offset)), v)
#define CLR8(dev, offset, v) PUT8(dev, offset, GET8(dev, offset) & ~(v))
#define SET8(dev, offset, v) PUT8(dev, offset, GET8(dev, offset) | (v))
#define CLR16(dev, offset, v) PUT16(dev, offset, GET16(dev, offset) & ~(v))
#define SET16(dev, offset, v) PUT16(dev, offset, GET16(dev, offset) | (v))
#define CLR32(dev, offset, v) PUT32(dev, offset, GET32(dev, offset) & ~(v))
#define SET32(dev, offset, v) PUT32(dev, offset, GET32(dev, offset) | (v))
#define BIT(n) (1U << (n))
#endif /* _AUDIOCMI_H */
|