1/*
2 * Common code to disable/enable mixer emulation at run time
3 *
4 * Copyright (C) 2013 Red Hat, Inc.
5 *
6 * Written by Bandan Das <bsd@redhat.com>
7 * with important bits picked up from hda-codec.c
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation; either version 2 or
12 * (at your option) version 3 of the License.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, see <http://www.gnu.org/licenses/>.
21 */
22
23/*
24 * HDA codec descriptions
25 */
26
27#ifdef HDA_MIXER
28#define QEMU_HDA_ID_OUTPUT ((QEMU_HDA_ID_VENDOR << 16) | 0x12)
29#define QEMU_HDA_ID_DUPLEX ((QEMU_HDA_ID_VENDOR << 16) | 0x22)
30#define QEMU_HDA_ID_MICRO ((QEMU_HDA_ID_VENDOR << 16) | 0x32)
31#define QEMU_HDA_AMP_CAPS \
32 (AC_AMPCAP_MUTE | \
33 (QEMU_HDA_AMP_STEPS << AC_AMPCAP_OFFSET_SHIFT) | \
34 (QEMU_HDA_AMP_STEPS << AC_AMPCAP_NUM_STEPS_SHIFT) | \
35 (3 << AC_AMPCAP_STEP_SIZE_SHIFT))
36#else
37#define QEMU_HDA_ID_OUTPUT ((QEMU_HDA_ID_VENDOR << 16) | 0x11)
38#define QEMU_HDA_ID_DUPLEX ((QEMU_HDA_ID_VENDOR << 16) | 0x21)
39#define QEMU_HDA_ID_MICRO ((QEMU_HDA_ID_VENDOR << 16) | 0x31)
40#define QEMU_HDA_AMP_CAPS QEMU_HDA_AMP_NONE
41#endif
42
43
44/* common: audio output widget */
45static const desc_param glue(common_params_audio_dac_, PARAM)[] = {
46 {
47 .id = AC_PAR_AUDIO_WIDGET_CAP,
48 .val = ((AC_WID_AUD_OUT << AC_WCAP_TYPE_SHIFT) |
49 AC_WCAP_FORMAT_OVRD |
50 AC_WCAP_AMP_OVRD |
51 AC_WCAP_OUT_AMP |
52 AC_WCAP_STEREO),
53 },{
54 .id = AC_PAR_PCM,
55 .val = QEMU_HDA_PCM_FORMATS,
56 },{
57 .id = AC_PAR_STREAM,
58 .val = AC_SUPFMT_PCM,
59 },{
60 .id = AC_PAR_AMP_IN_CAP,
61 .val = QEMU_HDA_AMP_NONE,
62 },{
63 .id = AC_PAR_AMP_OUT_CAP,
64 .val = QEMU_HDA_AMP_CAPS,
65 },
66};
67
68/* common: audio input widget */
69static const desc_param glue(common_params_audio_adc_, PARAM)[] = {
70 {
71 .id = AC_PAR_AUDIO_WIDGET_CAP,
72 .val = ((AC_WID_AUD_IN << AC_WCAP_TYPE_SHIFT) |
73 AC_WCAP_CONN_LIST |
74 AC_WCAP_FORMAT_OVRD |
75 AC_WCAP_AMP_OVRD |
76 AC_WCAP_IN_AMP |
77 AC_WCAP_STEREO),
78 },{
79 .id = AC_PAR_CONNLIST_LEN,
80 .val = 1,
81 },{
82 .id = AC_PAR_PCM,
83 .val = QEMU_HDA_PCM_FORMATS,
84 },{
85 .id = AC_PAR_STREAM,
86 .val = AC_SUPFMT_PCM,
87 },{
88 .id = AC_PAR_AMP_IN_CAP,
89 .val = QEMU_HDA_AMP_CAPS,
90 },{
91 .id = AC_PAR_AMP_OUT_CAP,
92 .val = QEMU_HDA_AMP_NONE,
93 },
94};
95
96/* common: pin widget (line-out) */
97static const desc_param glue(common_params_audio_lineout_, PARAM)[] = {
98 {
99 .id = AC_PAR_AUDIO_WIDGET_CAP,
100 .val = ((AC_WID_PIN << AC_WCAP_TYPE_SHIFT) |
101 AC_WCAP_CONN_LIST |
102 AC_WCAP_STEREO),
103 },{
104 .id = AC_PAR_PIN_CAP,
105 .val = AC_PINCAP_OUT,
106 },{
107 .id = AC_PAR_CONNLIST_LEN,
108 .val = 1,
109 },{
110 .id = AC_PAR_AMP_IN_CAP,
111 .val = QEMU_HDA_AMP_NONE,
112 },{
113 .id = AC_PAR_AMP_OUT_CAP,
114 .val = QEMU_HDA_AMP_NONE,
115 },
116};
117
118/* common: pin widget (line-in) */
119static const desc_param glue(common_params_audio_linein_, PARAM)[] = {
120 {
121 .id = AC_PAR_AUDIO_WIDGET_CAP,
122 .val = ((AC_WID_PIN << AC_WCAP_TYPE_SHIFT) |
123 AC_WCAP_STEREO),
124 },{
125 .id = AC_PAR_PIN_CAP,
126 .val = AC_PINCAP_IN,
127 },{
128 .id = AC_PAR_AMP_IN_CAP,
129 .val = QEMU_HDA_AMP_NONE,
130 },{
131 .id = AC_PAR_AMP_OUT_CAP,
132 .val = QEMU_HDA_AMP_NONE,
133 },
134};
135
136/* output: root node */
137static const desc_param glue(output_params_root_, PARAM)[] = {
138 {
139 .id = AC_PAR_VENDOR_ID,
140 .val = QEMU_HDA_ID_OUTPUT,
141 },{
142 .id = AC_PAR_SUBSYSTEM_ID,
143 .val = QEMU_HDA_ID_OUTPUT,
144 },{
145 .id = AC_PAR_REV_ID,
146 .val = 0x00100101,
147 },{
148 .id = AC_PAR_NODE_COUNT,
149 .val = 0x00010001,
150 },
151};
152
153/* output: audio function */
154static const desc_param glue(output_params_audio_func_, PARAM)[] = {
155 {
156 .id = AC_PAR_FUNCTION_TYPE,
157 .val = AC_GRP_AUDIO_FUNCTION,
158 },{
159 .id = AC_PAR_SUBSYSTEM_ID,
160 .val = QEMU_HDA_ID_OUTPUT,
161 },{
162 .id = AC_PAR_NODE_COUNT,
163 .val = 0x00020002,
164 },{
165 .id = AC_PAR_PCM,
166 .val = QEMU_HDA_PCM_FORMATS,
167 },{
168 .id = AC_PAR_STREAM,
169 .val = AC_SUPFMT_PCM,
170 },{
171 .id = AC_PAR_AMP_IN_CAP,
172 .val = QEMU_HDA_AMP_NONE,
173 },{
174 .id = AC_PAR_AMP_OUT_CAP,
175 .val = QEMU_HDA_AMP_NONE,
176 },{
177 .id = AC_PAR_GPIO_CAP,
178 .val = 0,
179 },{
180 .id = AC_PAR_AUDIO_FG_CAP,
181 .val = 0x00000808,
182 },{
183 .id = AC_PAR_POWER_STATE,
184 .val = 0,
185 },
186};
187
188/* output: nodes */
189static const desc_node glue(output_nodes_, PARAM)[] = {
190 {
191 .nid = AC_NODE_ROOT,
192 .name = "root",
193 .params = glue(output_params_root_, PARAM),
194 .nparams = ARRAY_SIZE(glue(output_params_root_, PARAM)),
195 },{
196 .nid = 1,
197 .name = "func",
198 .params = glue(output_params_audio_func_, PARAM),
199 .nparams = ARRAY_SIZE(glue(output_params_audio_func_, PARAM)),
200 },{
201 .nid = 2,
202 .name = "dac",
203 .params = glue(common_params_audio_dac_, PARAM),
204 .nparams = ARRAY_SIZE(glue(common_params_audio_dac_, PARAM)),
205 .stindex = 0,
206 },{
207 .nid = 3,
208 .name = "out",
209 .params = glue(common_params_audio_lineout_, PARAM),
210 .nparams = ARRAY_SIZE(glue(common_params_audio_lineout_, PARAM)),
211 .config = ((AC_JACK_PORT_COMPLEX << AC_DEFCFG_PORT_CONN_SHIFT) |
212 (AC_JACK_LINE_OUT << AC_DEFCFG_DEVICE_SHIFT) |
213 (AC_JACK_CONN_UNKNOWN << AC_DEFCFG_CONN_TYPE_SHIFT) |
214 (AC_JACK_COLOR_GREEN << AC_DEFCFG_COLOR_SHIFT) |
215 0x10),
216 .pinctl = AC_PINCTL_OUT_EN,
217 .conn = (uint32_t[]) { 2 },
218 }
219};
220
221/* output: codec */
222static const desc_codec glue(output_, PARAM) = {
223 .name = "output",
224 .iid = QEMU_HDA_ID_OUTPUT,
225 .nodes = glue(output_nodes_, PARAM),
226 .nnodes = ARRAY_SIZE(glue(output_nodes_, PARAM)),
227};
228
229/* duplex: root node */
230static const desc_param glue(duplex_params_root_, PARAM)[] = {
231 {
232 .id = AC_PAR_VENDOR_ID,
233 .val = QEMU_HDA_ID_DUPLEX,
234 },{
235 .id = AC_PAR_SUBSYSTEM_ID,
236 .val = QEMU_HDA_ID_DUPLEX,
237 },{
238 .id = AC_PAR_REV_ID,
239 .val = 0x00100101,
240 },{
241 .id = AC_PAR_NODE_COUNT,
242 .val = 0x00010001,
243 },
244};
245
246/* duplex: audio function */
247static const desc_param glue(duplex_params_audio_func_, PARAM)[] = {
248 {
249 .id = AC_PAR_FUNCTION_TYPE,
250 .val = AC_GRP_AUDIO_FUNCTION,
251 },{
252 .id = AC_PAR_SUBSYSTEM_ID,
253 .val = QEMU_HDA_ID_DUPLEX,
254 },{
255 .id = AC_PAR_NODE_COUNT,
256 .val = 0x00020004,
257 },{
258 .id = AC_PAR_PCM,
259 .val = QEMU_HDA_PCM_FORMATS,
260 },{
261 .id = AC_PAR_STREAM,
262 .val = AC_SUPFMT_PCM,
263 },{
264 .id = AC_PAR_AMP_IN_CAP,
265 .val = QEMU_HDA_AMP_NONE,
266 },{
267 .id = AC_PAR_AMP_OUT_CAP,
268 .val = QEMU_HDA_AMP_NONE,
269 },{
270 .id = AC_PAR_GPIO_CAP,
271 .val = 0,
272 },{
273 .id = AC_PAR_AUDIO_FG_CAP,
274 .val = 0x00000808,
275 },{
276 .id = AC_PAR_POWER_STATE,
277 .val = 0,
278 },
279};
280
281/* duplex: nodes */
282static const desc_node glue(duplex_nodes_, PARAM)[] = {
283 {
284 .nid = AC_NODE_ROOT,
285 .name = "root",
286 .params = glue(duplex_params_root_, PARAM),
287 .nparams = ARRAY_SIZE(glue(duplex_params_root_, PARAM)),
288 },{
289 .nid = 1,
290 .name = "func",
291 .params = glue(duplex_params_audio_func_, PARAM),
292 .nparams = ARRAY_SIZE(glue(duplex_params_audio_func_, PARAM)),
293 },{
294 .nid = 2,
295 .name = "dac",
296 .params = glue(common_params_audio_dac_, PARAM),
297 .nparams = ARRAY_SIZE(glue(common_params_audio_dac_, PARAM)),
298 .stindex = 0,
299 },{
300 .nid = 3,
301 .name = "out",
302 .params = glue(common_params_audio_lineout_, PARAM),
303 .nparams = ARRAY_SIZE(glue(common_params_audio_lineout_, PARAM)),
304 .config = ((AC_JACK_PORT_COMPLEX << AC_DEFCFG_PORT_CONN_SHIFT) |
305 (AC_JACK_LINE_OUT << AC_DEFCFG_DEVICE_SHIFT) |
306 (AC_JACK_CONN_UNKNOWN << AC_DEFCFG_CONN_TYPE_SHIFT) |
307 (AC_JACK_COLOR_GREEN << AC_DEFCFG_COLOR_SHIFT) |
308 0x10),
309 .pinctl = AC_PINCTL_OUT_EN,
310 .conn = (uint32_t[]) { 2 },
311 },{
312 .nid = 4,
313 .name = "adc",
314 .params = glue(common_params_audio_adc_, PARAM),
315 .nparams = ARRAY_SIZE(glue(common_params_audio_adc_, PARAM)),
316 .stindex = 1,
317 .conn = (uint32_t[]) { 5 },
318 },{
319 .nid = 5,
320 .name = "in",
321 .params = glue(common_params_audio_linein_, PARAM),
322 .nparams = ARRAY_SIZE(glue(common_params_audio_linein_, PARAM)),
323 .config = ((AC_JACK_PORT_COMPLEX << AC_DEFCFG_PORT_CONN_SHIFT) |
324 (AC_JACK_LINE_IN << AC_DEFCFG_DEVICE_SHIFT) |
325 (AC_JACK_CONN_UNKNOWN << AC_DEFCFG_CONN_TYPE_SHIFT) |
326 (AC_JACK_COLOR_RED << AC_DEFCFG_COLOR_SHIFT) |
327 0x20),
328 .pinctl = AC_PINCTL_IN_EN,
329 }
330};
331
332/* duplex: codec */
333static const desc_codec glue(duplex_, PARAM) = {
334 .name = "duplex",
335 .iid = QEMU_HDA_ID_DUPLEX,
336 .nodes = glue(duplex_nodes_, PARAM),
337 .nnodes = ARRAY_SIZE(glue(duplex_nodes_, PARAM)),
338};
339
340/* micro: root node */
341static const desc_param glue(micro_params_root_, PARAM)[] = {
342 {
343 .id = AC_PAR_VENDOR_ID,
344 .val = QEMU_HDA_ID_MICRO,
345 },{
346 .id = AC_PAR_SUBSYSTEM_ID,
347 .val = QEMU_HDA_ID_MICRO,
348 },{
349 .id = AC_PAR_REV_ID,
350 .val = 0x00100101,
351 },{
352 .id = AC_PAR_NODE_COUNT,
353 .val = 0x00010001,
354 },
355};
356
357/* micro: audio function */
358static const desc_param glue(micro_params_audio_func_, PARAM)[] = {
359 {
360 .id = AC_PAR_FUNCTION_TYPE,
361 .val = AC_GRP_AUDIO_FUNCTION,
362 },{
363 .id = AC_PAR_SUBSYSTEM_ID,
364 .val = QEMU_HDA_ID_MICRO,
365 },{
366 .id = AC_PAR_NODE_COUNT,
367 .val = 0x00020004,
368 },{
369 .id = AC_PAR_PCM,
370 .val = QEMU_HDA_PCM_FORMATS,
371 },{
372 .id = AC_PAR_STREAM,
373 .val = AC_SUPFMT_PCM,
374 },{
375 .id = AC_PAR_AMP_IN_CAP,
376 .val = QEMU_HDA_AMP_NONE,
377 },{
378 .id = AC_PAR_AMP_OUT_CAP,
379 .val = QEMU_HDA_AMP_NONE,
380 },{
381 .id = AC_PAR_GPIO_CAP,
382 .val = 0,
383 },{
384 .id = AC_PAR_AUDIO_FG_CAP,
385 .val = 0x00000808,
386 },{
387 .id = AC_PAR_POWER_STATE,
388 .val = 0,
389 },
390};
391
392/* micro: nodes */
393static const desc_node glue(micro_nodes_, PARAM)[] = {
394 {
395 .nid = AC_NODE_ROOT,
396 .name = "root",
397 .params = glue(micro_params_root_, PARAM),
398 .nparams = ARRAY_SIZE(glue(micro_params_root_, PARAM)),
399 },{
400 .nid = 1,
401 .name = "func",
402 .params = glue(micro_params_audio_func_, PARAM),
403 .nparams = ARRAY_SIZE(glue(micro_params_audio_func_, PARAM)),
404 },{
405 .nid = 2,
406 .name = "dac",
407 .params = glue(common_params_audio_dac_, PARAM),
408 .nparams = ARRAY_SIZE(glue(common_params_audio_dac_, PARAM)),
409 .stindex = 0,
410 },{
411 .nid = 3,
412 .name = "out",
413 .params = glue(common_params_audio_lineout_, PARAM),
414 .nparams = ARRAY_SIZE(glue(common_params_audio_lineout_, PARAM)),
415 .config = ((AC_JACK_PORT_COMPLEX << AC_DEFCFG_PORT_CONN_SHIFT) |
416 (AC_JACK_SPEAKER << AC_DEFCFG_DEVICE_SHIFT) |
417 (AC_JACK_CONN_UNKNOWN << AC_DEFCFG_CONN_TYPE_SHIFT) |
418 (AC_JACK_COLOR_GREEN << AC_DEFCFG_COLOR_SHIFT) |
419 0x10),
420 .pinctl = AC_PINCTL_OUT_EN,
421 .conn = (uint32_t[]) { 2 },
422 },{
423 .nid = 4,
424 .name = "adc",
425 .params = glue(common_params_audio_adc_, PARAM),
426 .nparams = ARRAY_SIZE(glue(common_params_audio_adc_, PARAM)),
427 .stindex = 1,
428 .conn = (uint32_t[]) { 5 },
429 },{
430 .nid = 5,
431 .name = "in",
432 .params = glue(common_params_audio_linein_, PARAM),
433 .nparams = ARRAY_SIZE(glue(common_params_audio_linein_, PARAM)),
434 .config = ((AC_JACK_PORT_COMPLEX << AC_DEFCFG_PORT_CONN_SHIFT) |
435 (AC_JACK_MIC_IN << AC_DEFCFG_DEVICE_SHIFT) |
436 (AC_JACK_CONN_UNKNOWN << AC_DEFCFG_CONN_TYPE_SHIFT) |
437 (AC_JACK_COLOR_RED << AC_DEFCFG_COLOR_SHIFT) |
438 0x20),
439 .pinctl = AC_PINCTL_IN_EN,
440 }
441};
442
443/* micro: codec */
444static const desc_codec glue(micro_, PARAM) = {
445 .name = "micro",
446 .iid = QEMU_HDA_ID_MICRO,
447 .nodes = glue(micro_nodes_, PARAM),
448 .nnodes = ARRAY_SIZE(glue(micro_nodes_, PARAM)),
449};
450
451#undef PARAM
452#undef HDA_MIXER
453#undef QEMU_HDA_ID_OUTPUT
454#undef QEMU_HDA_ID_DUPLEX
455#undef QEMU_HDA_ID_MICRO
456#undef QEMU_HDA_AMP_CAPS
457