aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/sound/pci/hda/hdaa.h
blob: 2435d64887a290fe6cb79f438261b786d60899dc (plain) (blame)
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
/*-7
 * Copyright (c) 2006 Stephane E. Potvin <sepotvin@videotron.ca>
 * Copyright (c) 2006 Ariff Abdullah <ariff@FreeBSD.org>
 * Copyright (c) 2008-2012 Alexander Motin <mav@FreeBSD.org>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * $FreeBSD$
 */

/*
 * Intel High Definition Audio (Audio function quirks) driver for FreeBSD.
 */

#ifndef _HDAA_QUIRKS_H_
#define _HDAA_QUIRKS_H_

#define HDAA_GPIO_SHIFT(n)	(n * 3)
#define HDAA_GPIO_MASK(n)	(0x7 << (n * 3))
#define HDAA_GPIO_KEEP(n)	(0x0 << (n * 3))
#define HDAA_GPIO_SET(n)	(0x1 << (n * 3))
#define HDAA_GPIO_CLEAR(n)	(0x2 << (n * 3))
#define HDAA_GPIO_DISABLE(n)	(0x3 << (n * 3))
#define HDAA_GPIO_INPUT(n)	(0x4 << (n * 3))

/* 9 - 25 = anything else */
#define HDAA_QUIRK_SOFTPCMVOL	(1 << 9)
#define HDAA_QUIRK_FIXEDRATE	(1 << 10)
#define HDAA_QUIRK_FORCESTEREO	(1 << 11)
#define HDAA_QUIRK_EAPDINV	(1 << 12)
#define HDAA_QUIRK_SENSEINV	(1 << 14)

/* 26 - 31 = vrefs */
#define HDAA_QUIRK_IVREF50	(1 << 26)
#define HDAA_QUIRK_IVREF80	(1 << 27)
#define HDAA_QUIRK_IVREF100	(1 << 28)
#define HDAA_QUIRK_OVREF50	(1 << 29)
#define HDAA_QUIRK_OVREF80	(1 << 30)
#define HDAA_QUIRK_OVREF100	(1 << 31)

#define HDAA_QUIRK_IVREF	(HDAA_QUIRK_IVREF50 | HDAA_QUIRK_IVREF80 | \
						HDAA_QUIRK_IVREF100)
#define HDAA_QUIRK_OVREF	(HDAA_QUIRK_OVREF50 | HDAA_QUIRK_OVREF80 | \
						HDAA_QUIRK_OVREF100)
#define HDAA_QUIRK_VREF		(HDAA_QUIRK_IVREF | HDAA_QUIRK_OVREF)

#define HDAA_AMP_VOL_DEFAULT	(-1)
#define HDAA_AMP_MUTE_DEFAULT	(0xffffffff)
#define HDAA_AMP_MUTE_NONE	(0)
#define HDAA_AMP_MUTE_LEFT	(1 << 0)
#define HDAA_AMP_MUTE_RIGHT	(1 << 1)
#define HDAA_AMP_MUTE_ALL	(HDAA_AMP_MUTE_LEFT | HDAA_AMP_MUTE_RIGHT)

#define HDAA_AMP_LEFT_MUTED(v)	((v) & (HDAA_AMP_MUTE_LEFT))
#define HDAA_AMP_RIGHT_MUTED(v)	(((v) & HDAA_AMP_MUTE_RIGHT) >> 1)

/* Widget in playback receiving signal from recording. */
#define HDAA_ADC_MONITOR		(1 << 0)
/* Input mixer widget needs volume control as destination. */
#define HDAA_IMIX_AS_DST		(2 << 0)

#define HDAA_CTL_OUT		1
#define HDAA_CTL_IN		2

#define HDA_MAX_CONNS	32
#define HDA_MAX_NAMELEN	32

struct hdaa_audio_as;
struct hdaa_audio_ctl;
struct hdaa_chan;
struct hdaa_devinfo;
struct hdaa_pcm_devinfo;
struct hdaa_widget;

struct hdaa_widget {
	nid_t nid;
	int type;
	int enable;
	int nconns, selconn;
	int waspin;
	uint32_t pflags;
	int bindas;
	int bindseqmask;
	int ossdev;
	uint32_t ossmask;
	int unsol;
	nid_t conns[HDA_MAX_CONNS];
	u_char connsenable[HDA_MAX_CONNS];
	char name[HDA_MAX_NAMELEN];
	uint8_t	*eld;
	int	eld_len;
	struct hdaa_devinfo *devinfo;
	struct {
		uint32_t widget_cap;
		uint32_t outamp_cap;
		uint32_t inamp_cap;
		uint32_t supp_stream_formats;
		uint32_t supp_pcm_size_rate;
		uint32_t eapdbtl;
	} param;
	union {
		struct {
			uint32_t config;
			uint32_t original;
			uint32_t newconf;
			uint32_t cap;
			uint32_t ctrl;
		} pin;
		struct {
			uint8_t	stripecap;
		} conv;
	} wclass;
};

struct hdaa_audio_ctl {
	struct hdaa_widget *widget, *childwidget;
	int enable;
	int index, dir, ndir;
	int mute, step, size, offset;
	int left, right, forcemute;
	uint32_t muted;
	uint32_t ossmask;	/* OSS devices that may affect control. */
	int	devleft[SOUND_MIXER_NRDEVICES]; /* Left ampl in 1/4dB. */
	int	devright[SOUND_MIXER_NRDEVICES]; /* Right ampl in 1/4dB. */
	int	devmute[SOUND_MIXER_NRDEVICES]; /* Mutes per OSS device. */
};

/* Association is a group of pins bound for some special function. */
struct hdaa_audio_as {
	u_char enable;
	u_char index;
	u_char dir;
	u_char pincnt;
	u_char fakeredir;
	u_char digital;
	uint16_t pinset;
	nid_t hpredir;
	nid_t pins[16];
	nid_t dacs[2][16];
	int num_chans;
	int chans[2];
	int location;	/* Pins location, if all have the same */
	int mixed;	/* Mixed/multiplexed recording, not multichannel. */
	struct hdaa_pcm_devinfo *pdevinfo;
};

struct hdaa_pcm_devinfo {
	device_t dev;
	struct hdaa_devinfo *devinfo;
	struct	snd_mixer *mixer;
	int	index;
	int	registered;
	int	playas, recas;
	u_char	left[SOUND_MIXER_NRDEVICES];
	u_char	right[SOUND_MIXER_NRDEVICES];
	int	minamp[SOUND_MIXER_NRDEVICES]; /* Minimal amps in 1/4dB. */
	int	maxamp[SOUND_MIXER_NRDEVICES]; /* Maximal amps in 1/4dB. */
	int	chan_size;
	int	chan_blkcnt;
	u_char	digital;
	uint32_t	ossmask;	/* Mask of supported OSS devices. */
	uint32_t	recsrc;		/* Mask of supported OSS sources. */
};

struct hdaa_devinfo {
	device_t		dev;
	struct mtx		*lock;
	nid_t			nid;
	nid_t			startnode, endnode;
	uint32_t		outamp_cap;
	uint32_t		inamp_cap;
	uint32_t		supp_stream_formats;
	uint32_t		supp_pcm_size_rate;
	uint32_t		gpio_cap;
	uint32_t		quirks;
	uint32_t		newquirks;
	uint32_t		gpio;
	uint32_t		newgpio;
	uint32_t		gpo;
	uint32_t		newgpo;
	int			nodecnt;
	int			ctlcnt;
	int			ascnt;
	int			num_devs;
	int			num_chans;
	struct hdaa_widget	*widget;
	struct hdaa_audio_ctl	*ctl;
	struct hdaa_audio_as	*as;
	struct hdaa_pcm_devinfo	*devs;
	struct hdaa_chan	*chans;
	struct callout		poll_jack;
	int			poll_ival;
};

#define HDAA_CHN_RUNNING	0x00000001
#define HDAA_CHN_SUSPEND	0x00000002

struct hdaa_chan {
	struct snd_dbuf *b;
	struct pcm_channel *c;
	struct pcmchan_caps caps;
	struct hdaa_devinfo *devinfo;
	struct hdaa_pcm_devinfo *pdevinfo;
	uint32_t spd, fmt, fmtlist[32], pcmrates[16];
	uint32_t supp_stream_formats, supp_pcm_size_rate;
	uint32_t blkcnt, blksz;
	uint32_t *dmapos;
	uint32_t flags;
	int dir;
	int off;
	int sid;
	int bit16, bit32;
	int channels;	/* Number of audio channels. */
	int as;		/* Number of association. */
	int asindex;	/* Index within association. */
	nid_t io[16];
	uint8_t	stripecap;	/* AND of stripecap of all ios. */
	uint8_t	stripectl;	/* stripe to use to all ios. */
};

#define MINQDB(ctl)							\
	((0 - (ctl)->offset) * ((ctl)->size + 1))

#define MAXQDB(ctl)							\
	(((ctl)->step - (ctl)->offset) * ((ctl)->size + 1))

#define RANGEQDB(ctl)							\
	((ctl)->step * ((ctl)->size + 1))

#define VAL2QDB(ctl, val) 						\
	(((ctl)->size + 1) * ((int)(val) - (ctl)->offset))

#define QDB2VAL(ctl, qdb) 						\
	imax(imin((((qdb) + (ctl)->size / 2 * ((qdb) > 0 ? 1 : -1)) /	\
	 ((ctl)->size + 1) + (ctl)->offset), (ctl)->step), 0)

#define hdaa_codec_id(devinfo)						\
		(((uint32_t)hda_get_vendor_id(devinfo->dev) << 16) +	\
		hda_get_device_id(devinfo->dev))

#define hdaa_subvendor_id(devinfo)					\
		(((uint32_t)hda_get_subvendor_id(devinfo->dev) << 16) +	\
		hda_get_subdevice_id(devinfo->dev))

struct hdaa_widget	*hdaa_widget_get(struct hdaa_devinfo *, nid_t);
uint32_t		hdaa_widget_pin_patch(uint32_t config, const char *str);
uint32_t		hdaa_gpio_patch(uint32_t gpio, const char *str);

void			hdaa_patch(struct hdaa_devinfo *devinfo);
void			hdaa_patch_direct(struct hdaa_devinfo *devinfo);

#endif