summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/io/audio/drv/audiocmihd/audiocmihd.h
blob: 10e423459d019cfdbeb692a6da9b5a98cb365a18 (plain)
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
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
/*
 * 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 2009 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

/*
 * Purpose: Definitions for the CMedia 8788 driver.
 */
/*
 * This file is part of Open Sound System
 *
 * Copyright (C) 4Front Technologies 1996-2011.
 *
 * 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	CMEDIAHD_H
#define	CMEDIAHD_H

#define	CMEDIAHD_NAME		"audiocmihd"

#define	CMEDIAHD_NUM_PORTC		2
#define	CMEDIAHD_PLAY			0
#define	CMEDIAHD_REC			1

/*
 * Number of fragments must be multiple of 2 because the
 * hardware supports only full and half buffer interrupts. In
 * addition it looks like 8 fragments is the minimum.
 */
#define	CMEDIAHD_BUF_LEN		(65536)

#define	PCI_VENDOR_ID_CMEDIA 		0x13F6
#define	PCI_DEVICE_ID_CMEDIAHD		0x8788

#define	CMEDIAHD_MAX_INTRS		512
#define	CMEDIAHD_MIN_INTRS		48
#define	CMEDIAHD_INTRS			100

/*
 * PCI registers
 */

#define	RECA_ADDR		(devc->base+0x00)
#define	RECA_SIZE		(devc->base+0x04)
#define	RECA_FRAG		(devc->base+0x06)
#define	RECB_ADDR		(devc->base+0x08)
#define	RECB_SIZE		(devc->base+0x0C)
#define	RECB_FRAG		(devc->base+0x0E)
#define	RECC_ADDR		(devc->base+0x10)
#define	RECC_SIZE		(devc->base+0x14)
#define	RECC_FRAG		(devc->base+0x16)
#define	SPDIF_ADDR		(devc->base+0x18)
#define	SPDIF_SIZE		(devc->base+0x1C)
#define	SPDIF_FRAG		(devc->base+0x1E)
#define	MULTICH_ADDR		(devc->base+0x20)
#define	MULTICH_SIZE		(devc->base+0x24)
#define	MULTICH_FRAG		(devc->base+0x28)
#define	FPOUT_ADDR		(devc->base+0x30)
#define	FPOUT_SIZE		(devc->base+0x34)
#define	FPOUT_FRAG		(devc->base+0x36)

#define	DMA_START		(devc->base+0x40)
#define	CHAN_RESET		(devc->base+0x42)
#define	MULTICH_MODE		(devc->base+0x43)
#define	IRQ_MASK		(devc->base+0x44)
#define	IRQ_STAT		(devc->base+0x46)
#define	MISC_REG		(devc->base+0x48)
#define	REC_FORMAT		(devc->base+0x4A)
#define	PLAY_FORMAT		(devc->base+0x4B)
#define	REC_MODE		(devc->base+0x4C)
#define	FUNCTION		(devc->base+0x50)

#define	I2S_MULTICH_DAC		(devc->base+0x60)
#define	I2S_ADC1		(devc->base+0x62)
#define	I2S_ADC2		(devc->base+0x64)
#define	I2S_ADC3		(devc->base+0x66)

#define	SPDIF_FUNC		(devc->base+0x70)
#define	SPDIFOUT_CHAN_STAT	(devc->base+0x74)
#define	SPDIFIN_CHAN_STAT	(devc->base+0x78)

#define	TWO_WIRE_ADDR		(devc->base+0x90)
#define	TWO_WIRE_MAP		(devc->base+0x91)
#define	TWO_WIRE_DATA		(devc->base+0x92)
#define	TWO_WIRE_CTRL		(devc->base+0x94)

#define	SPI_CONTROL		(devc->base+0x98)
#define	SPI_DATA		(devc->base+0x99)

#define	MPU401_DATA		(devc->base+0xA0)
#define	MPU401_COMMAND		(devc->base+0xA1)
#define	MPU401_CONTROL		(devc->base+0xA2)

#define	GPI_DATA		(devc->base+0xA4)
#define	GPI_IRQ_MASK		(devc->base+0xA5)
#define	GPIO_DATA		(devc->base+0xA6)
#define	GPIO_CONTROL		(devc->base+0xA8)
#define	GPIO_IRQ_MASK		(devc->base+0xAA)
#define	DEVICE_SENSE		(devc->base+0xAC)

#define	PLAY_ROUTING		(devc->base+0xC0)
#define	REC_ROUTING		(devc->base+0xC2)
#define	REC_MONITOR		(devc->base+0xC3)
#define	MONITOR_ROUTING		(devc->base+0xC4)

#define	AC97_CTRL		(devc->base+0xD0)
#define	AC97_INTR_MASK		(devc->base+0xD2)
#define	AC97_INTR_STAT		(devc->base+0xD3)
#define	AC97_OUT_CHAN_CONFIG	(devc->base+0xD4)
#define	AC97_IN_CHAN_CONFIG	(devc->base+0xD8)
#define	AC97_CMD_DATA		(devc->base+0xDC)

#define	CODEC_VERSION		(devc->base+0xE4)
#define	CTRL_VERSION		(devc->base+0xE6)

/* Device IDs */
#define	ASUS_VENDOR_ID		0x1043
#define	SUBID_XONAR_D2		0x8269
#define	SUBID_XONAR_D2X		0x82b7
#define	SUBID_XONAR_D1		0x834f
#define	SUBID_XONAR_DX		0x8275
#define	SUBID_XONAR_STX		0x835c
#define	SUBID_XONAR_DS		0x838e


#define	SUBID_GENERIC		0x0000

/* Xonar specific */
#define	XONAR_DX_FRONTDAC	0x9e
#define	XONAR_DX_SURRDAC	0x30
#define	XONAR_STX_FRONTDAC	0x98
#define	XONAR_DS_FRONTDAC	0x1
#define	XONAR_DS_SURRDAC	0x0

/* defs for AKM 4396 DAC */
#define	AK4396_CTL1		0x00
#define	AK4396_CTL2		0x01
#define	AK4396_CTL3		0x02
#define	AK4396_LchATTCtl	0x03
#define	AK4396_RchATTCtl	0x04

/* defs for CS4398 DAC */
#define	CS4398_CHIP_ID		0x01
#define	CS4398_MODE_CTRL	0x02
#define	CS4398_MIXING		0x03
#define	CS4398_MUTE_CTRL	0x04
#define	CS4398_VOLA		0x05
#define	CS4398_VOLB		0x06
#define	CS4398_RAMP_CTRL	0x07
#define	CS4398_MISC_CTRL	0x08
#define	CS4398_MISC2_CTRL	0x09
#define	CS4398_POWER_DOWN	(1<<7)	/* Obvious */
#define	CS4398_CPEN		(1<<6)  /* Control Port Enable */
#define	CS4398_FREEZE		(1<<5)	/* Freezes registers, unfreeze to */
					/* accept changed registers */
#define	CS4398_MCLKDIV2		(1<<4)	/* Divide MCLK by 2 */
#define	CS4398_MCLKDIV3		(1<<3)	/* Divive MCLK by 3 */
#define	CS4398_I2S		(1<<4)	/* Set I2S mode */

/* defs for CS4362A DAC */
#define	CS4362A_MODE1_CTRL	0x01
#define	CS4362A_MODE2_CTRL	0x02
#define	CS4362A_MODE3_CTRL	0x03
#define	CS4362A_FILTER_CTRL	0x04
#define	CS4362A_INVERT_CTRL	0x05
#define	CS4362A_MIX1_CTRL	0x06
#define	CS4362A_VOLA_1		0x07
#define	CS4362A_VOLB_1		0x08
#define	CS4362A_MIX2_CTRL	0x09
#define	CS4362A_VOLA_2		0x0A
#define	CS4362A_VOLB_2		0x0B
#define	CS4362A_MIX3_CTRL	0x0C
#define	CS4362A_VOLA_3		0x0D
#define	CS4362A_VOLB_3		0x0E
#define	CS4362A_CHIP_REV	0x12

/* CS4362A Reg 01h */
#define	CS4362A_CPEN		(1<<7)
#define	CS4362A_FREEZE		(1<<6)
#define	CS4362A_MCLKDIV		(1<<5)
#define	CS4362A_DAC3_ENABLE	(1<<3)
#define	CS4362A_DAC2_ENABLE	(1<<2)
#define	CS4362A_DAC1_ENABLE	(1<<1)
#define	CS4362A_POWER_DOWN	(1)

/* CS4362A Reg 02h */
#define	CS4362A_DIF_LJUST	0x00
#define	CS4362A_DIF_I2S		0x10
#define	CS4362A_DIF_RJUST16	0x20
#define	CS4362A_DIF_RJUST24	0x30
#define	CS4362A_DIF_RJUST20	0x40
#define	CS4362A_DIF_RJUST18	0x50

/* CS4362A Reg 03h */
#define	CS4362A_RAMP_IMMEDIATE	0x00
#define	CS4362A_RAMP_ZEROCROSS	0x40
#define	CS4362A_RAMP_SOFT	0x80
#define	CS4362A_RAMP_SOFTZERO	0xC0
#define	CS4362A_SINGLE_VOL	0x20
#define	CS4362A_RAMP_ERROR	0x10
#define	CS4362A_MUTEC_POL	0x08
#define	CS4362A_AUTOMUTE	0x04
#define	CS4362A_SIX_MUTE	0x00
#define	CS4362A_ONE_MUTE	0x01
#define	CS4362A_THREE_MUTE	0x03

/* CS4362A Reg 04h */
#define	CS4362A_FILT_SEL	0x10
#define	CS4362A_DEM_NONE	0x00
#define	CS4362A_DEM_44KHZ	0x02
#define	CS4362A_DEM_48KHZ	0x04
#define	CS4362A_DEM_32KHZ	0x06
#define	CS4362A_RAMPDOWN	0x01


/* CS4362A Reg 05h */
#define	CS4362A_INV_A3		(1<<4)
#define	CS4362A_INV_B3		(1<<5)
#define	CS4362A_INV_A2		(1<<2)
#define	CS4362A_INV_B2		(1<<3)
#define	CS4362A_INV_A1		(1)
#define	CS4362A_INV_B1		(1<<1)

/* CS4362A Reg 06h, 09h, 0Ch */
/* ATAPI crap, does anyone still use analog CD playback? */

/* CS4362A Reg 07h, 08h, 0Ah, 0Bh, 0Dh, 0Eh */
/* Volume registers */
#define	CS4362A_VOL_MUTE	0x80

/* 0-100. Start at -96dB. */
#define	CS4398_VOL(x) \
	((x) == 0 ? 0xFF : (0xC0 - ((x)*192/100)))
/* 0-100. Start at -96dB. Bit 7 is mute. */
#define	CS4362A_VOL(x) \
	(char)((x) == 0 ? 0xFF : (0x60 - ((x)*96/100)))

/* Xonar D2/D2X codec remap */
static const char xd2_codec_map[4] = {
	0, 1, 2, 4
};


typedef struct _cmediahd_devc_t cmediahd_devc_t;
typedef struct _cmediahd_portc_t cmediahd_portc_t;

typedef enum {
	CTL_VOLUME = 0,
	CTL_FRONT,
	CTL_REAR,
	CTL_CENTER,
	CTL_LFE,
	CTL_SURROUND,
	CTL_MONITOR,
	CTL_RECSRC,
	CTL_RECGAIN,
	CTL_MICVOL,
	CTL_AUXVOL,
	CTL_CDVOL,
	CTL_LOOP,
	CTL_SPREAD,
	CTL_NUM		/* must be last */
} cmediahd_ctrl_num_t;

typedef struct cmediahd_ctrl
{
	cmediahd_devc_t		*devc;
	audio_ctrl_t		*ctrl;
	cmediahd_ctrl_num_t	num;
	uint64_t		val;
} cmediahd_ctrl_t;

typedef struct cmediahd_regs
{
	caddr_t addr;	/* base address */
	caddr_t size;	/* current count */
	caddr_t frag;	/* terminal count */
	caddr_t i2s;    /* i2s reg */
	int chan; 	/* rec a/b/c, play spdif/multi/front */
#define	REC_A 0
#define	REC_B 1
#define	REC_C 2
#define	PLAY_SPDIF 3
#define	PLAY_MULTI 4
#define	PLAY_FRONT 5
} cmediahd_regs_t;

struct _cmediahd_portc_t
{
	cmediahd_devc_t *devc;
	audio_engine_t *engine;

	int			chans;
	int			direction;

	ddi_dma_handle_t	buf_dmah;	/* dma for buffers */
	ddi_acc_handle_t	buf_acch;
	uint32_t		paddr;
	caddr_t			kaddr;
	size_t			buf_size;
	size_t			buf_frames;	/* Buffer size in frames */
	unsigned		fragfr;
	unsigned		nfrags;
	unsigned		nframes;
	unsigned		bufsz;
	size_t			offset;
	uint64_t		count;
	int			syncdir;
};

struct _cmediahd_devc_t
{
	dev_info_t		*dip;
	audio_dev_t		*adev;
	boolean_t		has_ac97, has_fp_ac97;
	int			model;
	ac97_t			*ac97, *fp_ac97;

	boolean_t		suspended;
	ddi_acc_handle_t	pcih;
	ddi_acc_handle_t	regsh;
	caddr_t			base;
	kmutex_t		mutex;		/* For normal locking */
	kmutex_t		low_mutex;	/* For low level routines */
	cmediahd_regs_t		rec_eng;	/* which rec engine to use */
	cmediahd_portc_t 	*portc[CMEDIAHD_NUM_PORTC];
	int			gpio_mic, gpio_out, gpio_codec, gpio_alt;
	cmediahd_ctrl_t		controls[CTL_NUM];
};

#define	INB(devc, reg)		ddi_get8(devc->regsh, (void *)(reg))
#define	OUTB(devc, val, reg)	ddi_put8(devc->regsh, (void *)(reg), (val))

#define	INW(devc, reg)		ddi_get16(devc->regsh, (void *)(reg))
#define	OUTW(devc, val, reg)	ddi_put16(devc->regsh, (void *)(reg), (val))

#define	INL(devc, reg)		ddi_get32(devc->regsh, (void *)(reg))
#define	OUTL(devc, val, reg)	ddi_put32(devc->regsh, (void *)(reg), (val))

#endif /* CMEDIAHD_H */