VirtualBox

source: vbox/trunk/src/VBox/Devices/Audio/DevCodec.cpp@ 35487

Last change on this file since 35487 was 35487, checked in by vboxsync, 14 years ago

Devices/Audio: fixed fallback to nul host audio driver. Added the fallback to HDA audio device. (xTracker 5404).

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 100.7 KB
Line 
1/* $Id: DevCodec.cpp 35487 2011-01-11 13:45:20Z vboxsync $ */
2/** @file
3 * DevCodec - VBox ICH Intel HD Audio Codec.
4 */
5
6/*
7 * Copyright (C) 2006-2008 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17#define LOG_GROUP LOG_GROUP_DEV_AUDIO
18#include <VBox/vmm/pdmdev.h>
19#include <iprt/assert.h>
20#include <iprt/uuid.h>
21#include <iprt/string.h>
22#include <iprt/mem.h>
23#include <iprt/asm.h>
24#include <iprt/cpp/utils.h>
25
26#include "VBoxDD.h"
27extern "C" {
28#include "audio.h"
29}
30#include "DevCodec.h"
31
32#define CODECNODE_F0_PARAM_LENGTH 0x14
33#define CODECNODE_F02_PARAM_LENGTH 16
34typedef struct CODECCOMMONNODE
35{
36 uint8_t id; /* 7 - bit format */
37 const char *name;
38 /* RPM 5.3.6 */
39 uint32_t au32F00_param[CODECNODE_F0_PARAM_LENGTH];
40 uint32_t au32F02_param[CODECNODE_F02_PARAM_LENGTH];
41} CODECCOMMONNODE, *PCODECCOMMONNODE;
42
43typedef struct ROOTCODECNODE
44{
45 CODECCOMMONNODE node;
46}ROOTCODECNODE, *PROOTCODECNODE;
47
48#define AMPLIFIER_SIZE 60
49typedef uint32_t AMPLIFIER[AMPLIFIER_SIZE];
50#define AMPLIFIER_IN 0
51#define AMPLIFIER_OUT 1
52#define AMPLIFIER_LEFT 1
53#define AMPLIFIER_RIGHT 0
54#define AMPLIFIER_REGISTER(amp, inout, side, index) ((amp)[30*(inout) + 15*(side) + (index)])
55typedef struct DACNODE
56{
57 CODECCOMMONNODE node;
58 uint32_t u32F0d_param;
59 uint32_t u32F04_param;
60 uint32_t u32F05_param;
61 uint32_t u32F06_param;
62 uint32_t u32F0c_param;
63
64 uint32_t u32A_param;
65 AMPLIFIER B_params;
66
67} DACNODE, *PDACNODE;
68
69typedef struct ADCNODE
70{
71 CODECCOMMONNODE node;
72 uint32_t u32F03_param;
73 uint32_t u32F05_param;
74 uint32_t u32F06_param;
75 uint32_t u32F09_param;
76
77 uint32_t u32A_param;
78 uint32_t u32F01_param;
79 AMPLIFIER B_params;
80} ADCNODE, *PADCNODE;
81
82typedef struct SPDIFOUTNODE
83{
84 CODECCOMMONNODE node;
85 uint32_t u32F05_param;
86 uint32_t u32F06_param;
87 uint32_t u32F09_param;
88 uint32_t u32F0d_param;
89
90 uint32_t u32A_param;
91 AMPLIFIER B_params;
92} SPDIFOUTNODE, *PSPDIFOUTNODE;
93
94typedef struct SPDIFINNODE
95{
96 CODECCOMMONNODE node;
97 uint32_t u32F05_param;
98 uint32_t u32F06_param;
99 uint32_t u32F09_param;
100 uint32_t u32F0d_param;
101
102 uint32_t u32A_param;
103 AMPLIFIER B_params;
104} SPDIFINNODE, *PSPDIFINNODE;
105
106typedef struct AFGCODECNODE
107{
108 CODECCOMMONNODE node;
109 uint32_t u32F05_param;
110 uint32_t u32F08_param;
111 uint32_t u32F20_param;
112 uint32_t u32F17_param;
113} AFGCODECNODE, *PAFGCODECNODE;
114
115typedef struct PORTNODE
116{
117 CODECCOMMONNODE node;
118 uint32_t u32F07_param;
119 uint32_t u32F08_param;
120 uint32_t u32F09_param;
121 uint32_t u32F01_param;
122 uint32_t u32F1c_param;
123 AMPLIFIER B_params;
124} PORTNODE, *PPORTNODE;
125
126typedef struct DIGOUTNODE
127{
128 CODECCOMMONNODE node;
129 uint32_t u32F01_param;
130 uint32_t u32F08_param;
131 uint32_t u32F07_param;
132 uint32_t u32F09_param;
133 uint32_t u32F1c_param;
134} DIGOUTNODE, *PDIGOUTNODE;
135
136typedef struct DIGINNODE
137{
138 CODECCOMMONNODE node;
139 uint32_t u32F05_param;
140 uint32_t u32F07_param;
141 uint32_t u32F08_param;
142 uint32_t u32F09_param;
143 uint32_t u32F0c_param;
144 uint32_t u32F1c_param;
145 uint32_t u32F1e_param;
146} DIGINNODE, *PDIGINNODE;
147
148typedef struct ADCMUXNODE
149{
150 CODECCOMMONNODE node;
151 uint32_t u32F01_param;
152
153 uint32_t u32A_param;
154 AMPLIFIER B_params;
155} ADCMUXNODE, *PADCMUXNODE;
156
157typedef struct PCBEEPNODE
158{
159 CODECCOMMONNODE node;
160 uint32_t u32F07_param;
161 uint32_t u32F0a_param;
162
163 uint32_t u32A_param;
164 AMPLIFIER B_params;
165 uint32_t u32F1c_param;
166} PCBEEPNODE, *PPCBEEPNODE;
167
168typedef struct CDNODE
169{
170 CODECCOMMONNODE node;
171 uint32_t u32F07_param;
172 uint32_t u32F1c_param;
173} CDNODE, *PCDNODE;
174
175typedef struct VOLUMEKNOBNODE
176{
177 CODECCOMMONNODE node;
178 uint32_t u32F08_param;
179 uint32_t u32F0f_param;
180} VOLUMEKNOBNODE, *PVOLUMEKNOBNODE;
181
182typedef struct ADCVOLNODE
183{
184 CODECCOMMONNODE node;
185 uint32_t u32F0c_param;
186 uint32_t u32F01_param;
187 uint32_t u32A_params;
188 AMPLIFIER B_params;
189} ADCVOLNODE, *PADCVOLNODE;
190
191typedef struct RESNODE
192{
193 CODECCOMMONNODE node;
194 uint32_t u32F05_param;
195 uint32_t u32F06_param;
196 uint32_t u32F07_param;
197 uint32_t u32F1c_param;
198} RESNODE, *PRESNODE;
199
200typedef union CODECNODE
201{
202 CODECCOMMONNODE node;
203 ROOTCODECNODE root;
204 AFGCODECNODE afg;
205 DACNODE dac;
206 ADCNODE adc;
207 SPDIFOUTNODE spdifout;
208 SPDIFINNODE spdifin;
209 PORTNODE port;
210 DIGOUTNODE digout;
211 DIGINNODE digin;
212 ADCMUXNODE adcmux;
213 PCBEEPNODE pcbeep;
214 CDNODE cdnode;
215 VOLUMEKNOBNODE volumeKnob;
216 ADCVOLNODE adcvol;
217 RESNODE reserved;
218} CODECNODE, *PCODECNODE;
219
220/* STAC9220 */
221const static uint8_t au8Stac9220Ports[] = { 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, 0};
222const static uint8_t au8Stac9220Dacs[] = { 0x2, 0x3, 0x4, 0x5, 0};
223const static uint8_t au8Stac9220Adcs[] = { 0x6, 0x7, 0};
224const static uint8_t au8Stac9220SpdifOuts[] = { 0x8, 0 };
225const static uint8_t au8Stac9220SpdifIns[] = { 0x9, 0 };
226const static uint8_t au8Stac9220DigOutPins[] = { 0x10, 0 };
227const static uint8_t au8Stac9220DigInPins[] = { 0x11, 0 };
228const static uint8_t au8Stac9220AdcVols[] = { 0x17, 0x18, 0};
229const static uint8_t au8Stac9220AdcMuxs[] = { 0x12, 0x13, 0};
230const static uint8_t au8Stac9220Pcbeeps[] = { 0x14, 0 };
231const static uint8_t au8Stac9220Cds[] = { 0x15, 0 };
232const static uint8_t au8Stac9220VolKnobs[] = { 0x16, 0 };
233const static uint8_t au8Stac9220Reserveds[] = { 0x9, 0x19, 0x1a, 0x1b, 0 };
234
235static int stac9220ResetNode(struct CODECState *pState, uint8_t nodenum, PCODECNODE pNode);
236
237static int stac9220Construct(CODECState *pState)
238{
239 unconst(pState->cTotalNodes) = 0x1C;
240 pState->pfnCodecNodeReset = stac9220ResetNode;
241 pState->u16VendorId = 0x8384;
242 pState->u16DeviceId = 0x7680;
243 pState->u8BSKU = 0x76;
244 pState->u8AssemblyId = 0x80;
245 pState->pNodes = (PCODECNODE)RTMemAllocZ(sizeof(CODECNODE) * pState->cTotalNodes);
246 pState->fInReset = false;
247#define STAC9220WIDGET(type) pState->au8##type##s = au8Stac9220##type##s
248 STAC9220WIDGET(Port);
249 STAC9220WIDGET(Dac);
250 STAC9220WIDGET(Adc);
251 STAC9220WIDGET(AdcVol);
252 STAC9220WIDGET(AdcMux);
253 STAC9220WIDGET(Pcbeep);
254 STAC9220WIDGET(SpdifIn);
255 STAC9220WIDGET(SpdifOut);
256 STAC9220WIDGET(DigInPin);
257 STAC9220WIDGET(DigOutPin);
258 STAC9220WIDGET(Cd);
259 STAC9220WIDGET(VolKnob);
260 STAC9220WIDGET(Reserved);
261#undef STAC9220WIDGET
262 unconst(pState->u8AdcVolsLineIn) = 0x17;
263 unconst(pState->u8DacLineOut) = 0x2;
264
265 return VINF_SUCCESS;
266}
267
268static int stac9220ResetNode(struct CODECState *pState, uint8_t nodenum, PCODECNODE pNode)
269{
270 pNode->node.id = nodenum;
271 pNode->node.au32F00_param[0xF] = 0; /* Power statest Supported: are the same as AFG reports */
272 switch (nodenum)
273 {
274 /* Root Node*/
275 case 0:
276 pNode->root.node.name = "Root";
277 pNode->node.au32F00_param[2] = CODEC_MAKE_F00_02(0x1, 0x0, 0x34, 0x1); /* rev id */
278 break;
279 case 1:
280 pNode->afg.node.name = "AFG";
281 pNode->node.au32F00_param[8] = CODEC_MAKE_F00_08(CODEC_F00_08_BEEP_GEN, 0xd, 0xd);
282 pNode->node.au32F00_param[0xC] = CODEC_MAKE_F00_0C(0x17)
283 | CODEC_F00_0C_CAP_BALANCED_IO
284 | CODEC_F00_0C_CAP_INPUT
285 | CODEC_F00_0C_CAP_PRESENSE_DETECT
286 | CODEC_F00_0C_CAP_TRIGGER_REQUIRED
287 | CODEC_F00_0C_CAP_IMPENDANCE_SENSE;//(17 << 8)|RT_BIT(6)|RT_BIT(5)|RT_BIT(2)|RT_BIT(1)|RT_BIT(0);
288 pNode->node.au32F00_param[0xB] = CODEC_F00_0B_PCM;
289 pNode->node.au32F00_param[0xD] = CODEC_MAKE_F00_0D(1, 0x5, 0xE, 0);//RT_BIT(31)|(0x5 << 16)|(0xE)<<8;
290 pNode->node.au32F00_param[0x12] = RT_BIT(31)|(0x2 << 16)|(0x7f << 8)|0x7f;
291 pNode->node.au32F00_param[0x11] = CODEC_MAKE_F00_11(1, 1, 0, 0, 4);//0xc0000004;
292 pNode->node.au32F00_param[0xF] = CODEC_F00_0F_D3|CODEC_F00_0F_D2|CODEC_F00_0F_D1|CODEC_F00_0F_D0;
293 pNode->afg.u32F05_param = CODEC_MAKE_F05(0, 0, 0, CODEC_F05_D2, CODEC_F05_D2);//0x2 << 4| 0x2; /* PS-Act: D3, PS->Set D3 */
294 pNode->afg.u32F08_param = 0;
295 pNode->afg.u32F17_param = 0;
296 break;
297 case 2:
298 pNode->dac.node.name = "DAC0";
299 goto dac_init;
300 case 3:
301 pNode->dac.node.name = "DAC1";
302 goto dac_init;
303 case 4:
304 pNode->dac.node.name = "DAC2";
305 goto dac_init;
306 case 5:
307 pNode->dac.node.name = "DAC3";
308 dac_init:
309 memset(pNode->dac.B_params, 0, AMPLIFIER_SIZE);
310 pNode->dac.u32A_param = CODEC_MAKE_A(0, 1, CODEC_A_MULT_1X, CODEC_A_DIV_1X, CODEC_A_16_BIT, 1);//RT_BIT(14)|(0x1 << 4)|0x1; /* 441000Hz/16bit/2ch */
311
312 AMPLIFIER_REGISTER(pNode->dac.B_params, AMPLIFIER_OUT, AMPLIFIER_LEFT, 0) = 0x7F | RT_BIT(7);
313 AMPLIFIER_REGISTER(pNode->dac.B_params, AMPLIFIER_OUT, AMPLIFIER_RIGHT, 0) = 0x7F | RT_BIT(7);
314
315 pNode->dac.node.au32F00_param[9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_AUDIO_OUTPUT, 0xD, 0)
316 | CODEC_F00_09_CAP_L_R_SWAP
317 | CODEC_F00_09_CAP_POWER_CTRL
318 | CODEC_F00_09_CAP_OUT_AMP_PRESENT
319 | CODEC_F00_09_CAP_LSB;//(0xD << 16) | RT_BIT(11) | RT_BIT(10) | RT_BIT(2) | RT_BIT(0);
320 pNode->dac.u32F0c_param = 0;
321 pNode->dac.u32F05_param = CODEC_MAKE_F05(0, 0, 0, CODEC_F05_D3, CODEC_F05_D3);//0x3 << 4 | 0x3; /* PS-Act: D3, Set: D3 */
322 break;
323 case 6:
324 pNode->adc.node.name = "ADC0";
325 pNode->node.au32F02_param[0] = 0x17;
326 goto adc_init;
327 case 7:
328 pNode->adc.node.name = "ADC1";
329 pNode->node.au32F02_param[0] = 0x18;
330 adc_init:
331 pNode->adc.u32A_param = CODEC_MAKE_A(0, 1, CODEC_A_MULT_1X, CODEC_A_DIV_1X, CODEC_A_16_BIT, 1);//RT_BIT(14)|(0x1 << 3)|0x1; /* 441000Hz/16bit/2ch */
332 pNode->adc.node.au32F00_param[0xE] = CODEC_MAKE_F00_0E(0, 1);//RT_BIT(0);
333 pNode->adc.u32F03_param = RT_BIT(0);
334 pNode->adc.u32F05_param = CODEC_MAKE_F05(0, 0, 0, CODEC_F05_D3, CODEC_F05_D3);//0x3 << 4 | 0x3; /* PS-Act: D3 Set: D3 */
335 pNode->adc.u32F06_param = 0;
336 pNode->adc.node.au32F00_param[9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_AUDIO_INPUT, 0xD, 0)
337 | CODEC_F00_09_CAP_POWER_CTRL
338 | CODEC_F00_09_CAP_CONNECTION_LIST
339 | CODEC_F00_09_CAP_PROC_WIDGET
340 | CODEC_F00_09_CAP_LSB;//RT_BIT(20)| (0xd << 16) | RT_BIT(10) | RT_BIT(8) | RT_BIT(6)| RT_BIT(0);
341 break;
342 case 8:
343 pNode->spdifout.node.name = "SPDIFOut";
344 pNode->spdifout.u32A_param = CODEC_MAKE_A(0, 1, CODEC_A_MULT_1X, CODEC_A_DIV_1X, CODEC_A_16_BIT, 1);//(1<<14)|(0x1<<4) | 0x1;
345 pNode->spdifout.node.au32F00_param[9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_AUDIO_OUTPUT, 0x4, 0)
346 | CODEC_F00_09_CAP_DIGITAL
347 | CODEC_F00_09_CAP_FMT_OVERRIDE
348 | CODEC_F00_09_CAP_LSB;//(4 << 16) | RT_BIT(9)|RT_BIT(4)|0x1;
349 pNode->node.au32F00_param[0xa] = pState->pNodes[1].node.au32F00_param[0xA];
350 pNode->spdifout.node.au32F00_param[0xB] = CODEC_F00_0B_PCM;
351 pNode->spdifout.u32F06_param = 0;
352 pNode->spdifout.u32F0d_param = 0;
353 break;
354 case 9:
355 pNode->node.name = "Reserved_0";
356 pNode->spdifin.u32A_param = CODEC_MAKE_A(0, 1, CODEC_A_MULT_1X, CODEC_A_DIV_1X, CODEC_A_16_BIT, 1);//(0x1<<4) | 0x1;
357 pNode->spdifin.node.au32F00_param[9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_AUDIO_INPUT, 0x4, 0)
358 | CODEC_F00_09_CAP_DIGITAL
359 | CODEC_F00_09_CAP_CONNECTION_LIST
360 | CODEC_F00_09_CAP_FMT_OVERRIDE
361 | CODEC_F00_09_CAP_LSB;//(0x1 << 20)|(4 << 16) | RT_BIT(9)| RT_BIT(8)|RT_BIT(4)|0x1;
362 pNode->node.au32F00_param[0xA] = pState->pNodes[1].node.au32F00_param[0xA];
363 pNode->node.au32F00_param[0xE] = CODEC_MAKE_F00_0E(0, 1);//RT_BIT(0);
364 pNode->node.au32F02_param[0] = 0x11;
365 pNode->spdifin.node.au32F00_param[0xB] = CODEC_F00_0B_PCM;
366 pNode->spdifin.u32F06_param = 0;
367 pNode->spdifin.u32F0d_param = 0;
368 break;
369 case 0xA:
370 pNode->node.name = "PortA";
371 pNode->node.au32F00_param[0xC] = CODEC_MAKE_F00_0C(0x17)
372 | CODEC_F00_0C_CAP_INPUT
373 | CODEC_F00_0C_CAP_OUTPUT
374 | CODEC_F00_0C_CAP_HP
375 | CODEC_F00_0C_CAP_PRESENSE_DETECT
376 | CODEC_F00_0C_CAP_TRIGGER_REQUIRED
377 | CODEC_F00_0C_CAP_IMPENDANCE_SENSE;//0x173f;
378 pNode->node.au32F02_param[0] = 0x2;
379 pNode->port.u32F07_param = CODEC_F07_IN_ENABLE
380 | CODEC_F07_OUT_ENABLE;
381 pNode->port.u32F08_param = 0;
382 if (!pState->fInReset)
383 pNode->port.u32F1c_param = CODEC_MAKE_F1C(CODEC_F1C_PORT_COMPLEX,
384 CODEC_F1C_LOCATION_FRONT,
385 CODEC_F1C_DEVICE_HP,
386 CODEC_F1C_CONNECTION_TYPE_1_8INCHES,
387 CODEC_F1C_COLOR_GREEN,
388 CODEC_F1C_MISC_JACK_DETECT,
389 0x2, 0);//RT_MAKE_U32_FROM_U8(0x20, 0x40, 0x21, 0x02);
390 goto port_init;
391 case 0xB:
392 pNode->node.name = "PortB";
393 pNode->node.au32F00_param[0xC] = CODEC_MAKE_F00_0C(0x17)
394 | CODEC_F00_0C_CAP_INPUT
395 | CODEC_F00_0C_CAP_OUTPUT
396 | CODEC_F00_0C_CAP_PRESENSE_DETECT
397 | CODEC_F00_0C_CAP_TRIGGER_REQUIRED
398 | CODEC_F00_0C_CAP_IMPENDANCE_SENSE;//0x1737;
399 pNode->node.au32F02_param[0] = 0x4;
400 pNode->port.u32F07_param = CODEC_F07_IN_ENABLE;
401 if (!pState->fInReset)
402 pNode->port.u32F1c_param = CODEC_MAKE_F1C(CODEC_F1C_PORT_COMPLEX,
403 CODEC_F1C_LOCATION_INTERNAL|CODEC_F1C_LOCATION_REAR,
404 CODEC_F1C_DEVICE_SPEAKER,
405 CODEC_F1C_CONNECTION_TYPE_1_8INCHES,
406 CODEC_F1C_COLOR_BLACK,
407 CODEC_F1C_MISC_JACK_DETECT,
408 0x1, 0x1);//RT_MAKE_U32_FROM_U8(0x11, 0x60, 0x11, 0x01);
409 goto port_init;
410 case 0xC:
411 pNode->node.name = "PortC";
412 pNode->node.au32F02_param[0] = 0x3;
413 pNode->node.au32F00_param[0xC] = CODEC_MAKE_F00_0C(0x17)
414 | CODEC_F00_0C_CAP_INPUT
415 | CODEC_F00_0C_CAP_OUTPUT
416 | CODEC_F00_0C_CAP_PRESENSE_DETECT
417 | CODEC_F00_0C_CAP_TRIGGER_REQUIRED
418 | CODEC_F00_0C_CAP_IMPENDANCE_SENSE;//0x1737;
419 pNode->port.u32F07_param = CODEC_F07_IN_ENABLE;
420 if (!pState->fInReset)
421 pNode->port.u32F1c_param = CODEC_MAKE_F1C(CODEC_F1C_PORT_COMPLEX,
422 CODEC_F1C_LOCATION_REAR,
423 CODEC_F1C_DEVICE_SPEAKER,
424 CODEC_F1C_CONNECTION_TYPE_1_8INCHES,
425 CODEC_F1C_COLOR_GREEN,
426 0x0, 0x1, 0x0);//RT_MAKE_U32_FROM_U8(0x10, 0x40, 0x11, 0x01);
427 goto port_init;
428 case 0xD:
429 pNode->node.name = "PortD";
430 pNode->node.au32F00_param[0xC] = CODEC_MAKE_F00_0C(0x17)
431 | CODEC_F00_0C_CAP_INPUT
432 | CODEC_F00_0C_CAP_OUTPUT
433 | CODEC_F00_0C_CAP_PRESENSE_DETECT
434 | CODEC_F00_0C_CAP_TRIGGER_REQUIRED
435 | CODEC_F00_0C_CAP_IMPENDANCE_SENSE;//0x1737;
436 pNode->port.u32F07_param = CODEC_F07_IN_ENABLE;
437 pNode->node.au32F02_param[0] = 0x2;
438 if (!pState->fInReset)
439 pNode->port.u32F1c_param = CODEC_MAKE_F1C(CODEC_F1C_PORT_COMPLEX,
440 CODEC_F1C_LOCATION_FRONT,
441 CODEC_F1C_DEVICE_MIC,
442 CODEC_F1C_CONNECTION_TYPE_1_8INCHES,
443 CODEC_F1C_COLOR_PINK,
444 0x0, 0x5, 0x0);//RT_MAKE_U32_FROM_U8(0x50, 0x90, 0xA1, 0x02); /* Microphone */
445 port_init:
446 pNode->port.u32F09_param = CODEC_MAKE_F09_ANALOG(1, CODEC_F09_ANALOG_NA);//RT_BIT(31)|0x7fffffff;
447 pNode->port.u32F08_param = 0;
448 pNode->node.au32F00_param[9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_PIN_COMPLEX, 0x0, 0)
449 | CODEC_F00_09_CAP_CONNECTION_LIST
450 | CODEC_F00_09_CAP_UNSOL
451 | CODEC_F00_09_CAP_LSB;//(4 << 20)|RT_BIT(8)|RT_BIT(7)|RT_BIT(0);
452 pNode->node.au32F00_param[0xE] = CODEC_MAKE_F00_0E(0, 1);//0x1;
453 break;
454 case 0xE:
455 pNode->node.name = "PortE";
456 pNode->node.au32F00_param[9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_PIN_COMPLEX, 0x0, 0)
457 | CODEC_F00_09_CAP_UNSOL
458 | CODEC_F00_09_CAP_LSB;//(4 << 20)|RT_BIT(7)|RT_BIT(0);
459 pNode->port.u32F08_param = 0;
460 pNode->node.au32F00_param[0xC] = CODEC_F00_0C_CAP_INPUT
461 | CODEC_F00_0C_CAP_OUTPUT
462 | CODEC_F00_0C_CAP_PRESENSE_DETECT;//0x34;
463 pNode->port.u32F07_param = CODEC_F07_IN_ENABLE;
464 pNode->port.u32F09_param = CODEC_MAKE_F09_ANALOG(0, CODEC_F09_ANALOG_NA);//0x7fffffff;
465 if (!pState->fInReset)
466 pNode->port.u32F1c_param = CODEC_MAKE_F1C(CODEC_F1C_PORT_COMPLEX,
467 CODEC_F1C_LOCATION_REAR,
468 CODEC_F1C_DEVICE_LINE_OUT,
469 CODEC_F1C_CONNECTION_TYPE_1_8INCHES,
470 CODEC_F1C_COLOR_BLUE,
471 0x0, 0x4, 0x0);//0x01013040; /* Line Out */
472 break;
473 case 0xF:
474 pNode->node.name = "PortF";
475 pNode->node.au32F00_param[9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_PIN_COMPLEX, 0x0, 0x0)
476 | CODEC_F00_09_CAP_CONNECTION_LIST
477 | CODEC_F00_09_CAP_UNSOL
478 | CODEC_F00_09_CAP_OUT_AMP_PRESENT
479 | CODEC_F00_09_CAP_LSB;//(4 << 20)|RT_BIT(8)|RT_BIT(7)|RT_BIT(2)|RT_BIT(0);
480 pNode->node.au32F00_param[0xC] = CODEC_F00_0C_CAP_INPUT
481 | CODEC_F00_0C_CAP_OUTPUT
482 | CODEC_F00_0C_CAP_PRESENSE_DETECT
483 /* | CODEC_F00_0C_CAP_TRIGGER_REQUIRED
484 | CODEC_F00_0C_CAP_IMPENDANCE_SENSE */;//0x37;
485 pNode->node.au32F00_param[0xE] = CODEC_MAKE_F00_0E(0, 1);//0x1;
486 pNode->port.u32F08_param = 0;
487 pNode->port.u32F07_param = CODEC_F07_OUT_ENABLE
488 | CODEC_F07_IN_ENABLE;
489 if (!pState->fInReset)
490 pNode->port.u32F1c_param = CODEC_MAKE_F1C(CODEC_F1C_PORT_COMPLEX,
491 CODEC_F1C_LOCATION_INTERNAL,
492 CODEC_F1C_DEVICE_SPEAKER,
493 CODEC_F1C_CONNECTION_TYPE_1_8INCHES,
494 CODEC_F1C_COLOR_ORANGE,
495 0x0, 0x1, 0x2);//RT_MAKE_U32_FROM_U8(0x12, 0x60, 0x11, 0x01);
496 pNode->node.au32F02_param[0] = 0x5;
497 pNode->port.u32F09_param = CODEC_MAKE_F09_ANALOG(0, CODEC_F09_ANALOG_NA);//0x7fffffff;
498 break;
499 case 0x10:
500 pNode->node.name = "DigOut_0";
501 pNode->node.au32F00_param[9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_PIN_COMPLEX, 0x0, 0x0)
502 | CODEC_F00_09_CAP_DIGITAL
503 | CODEC_F00_09_CAP_CONNECTION_LIST
504 | CODEC_F00_09_CAP_LSB;//(4<<20)|RT_BIT(9)|RT_BIT(8)|RT_BIT(0);
505 pNode->node.au32F00_param[0xC] = CODEC_F00_0C_CAP_OUTPUT;//RT_BIT(4);
506 pNode->node.au32F00_param[0xE] = CODEC_MAKE_F00_0E(0, 0x3);
507 pNode->node.au32F02_param[0] = RT_MAKE_U32_FROM_U8(0x08, 0x17, 0x19, 0);
508 if (!pState->fInReset)
509 pNode->digout.u32F1c_param = CODEC_MAKE_F1C(CODEC_F1C_PORT_COMPLEX,
510 CODEC_F1C_LOCATION_REAR,
511 CODEC_F1C_DEVICE_SPDIF_OUT,
512 CODEC_F1C_CONNECTION_TYPE_DIN,
513 CODEC_F1C_COLOR_BLACK,
514 0x0, 0x3, 0x0);//RT_MAKE_U32_FROM_U8(0x30, 0x10, 0x45, 0x01);
515 break;
516 case 0x11:
517 pNode->node.name = "DigIn_0";
518 pNode->node.au32F00_param[9] = (4 << 20)|(3<<16)|RT_BIT(10)|RT_BIT(9)|RT_BIT(7)|RT_BIT(0);
519 pNode->node.au32F00_param[0xC] = CODEC_F00_0C_CAP_EAPD
520 | CODEC_F00_0C_CAP_INPUT
521 | CODEC_F00_0C_CAP_PRESENSE_DETECT;//RT_BIT(16)| RT_BIT(5)|RT_BIT(2);
522 pNode->digin.u32F05_param = CODEC_MAKE_F05(0, 0, 0, CODEC_F05_D3, CODEC_F05_D3);//0x3 << 4 | 0x3; /* PS-Act: D3 -> D3 */
523 pNode->digin.u32F07_param = 0;
524 pNode->digin.u32F08_param = 0;
525 pNode->digin.u32F09_param = 0;
526 pNode->digin.u32F0c_param = 0;
527 if (!pState->fInReset)
528 pNode->digin.u32F1c_param = CODEC_MAKE_F1C(CODEC_F1C_PORT_COMPLEX,
529 CODEC_F1C_LOCATION_REAR,
530 CODEC_F1C_DEVICE_SPDIF_IN,
531 CODEC_F1C_CONNECTION_TYPE_OTHER_DIGITAL,
532 CODEC_F1C_COLOR_BLACK,
533 0x0, 0x6, 0x0);//(0x1 << 24) | (0xc5 << 16) | (0x10 << 8) | 0x60;
534 break;
535 case 0x12:
536 pNode->node.name = "ADCMux_0";
537 pNode->adcmux.u32F01_param = 0;
538 goto adcmux_init;
539 case 0x13:
540 pNode->node.name = "ADCMux_1";
541 pNode->adcmux.u32F01_param = 1;
542 adcmux_init:
543 pNode->node.au32F00_param[9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_AUDIO_SELECTOR, 0x0, 0)
544 | CODEC_F00_09_CAP_CONNECTION_LIST
545 | CODEC_F00_09_CAP_AMP_FMT_OVERRIDE
546 | CODEC_F00_09_CAP_OUT_AMP_PRESENT
547 | CODEC_F00_09_CAP_LSB;//(3<<20)|RT_BIT(8)|RT_BIT(3)|RT_BIT(2)|RT_BIT(0);
548 pNode->node.au32F00_param[0xe] = CODEC_MAKE_F00_0E(0, 0x7);
549 pNode->node.au32F00_param[0x12] = (0x27 << 16)|(0x4 << 8);
550 /* STAC 9220 v10 6.21-22.{4,5} both(left and right) out amplefiers inited with 0*/
551 memset(pNode->adcmux.B_params, 0, AMPLIFIER_SIZE);
552 pNode->node.au32F02_param[0] = RT_MAKE_U32_FROM_U8(0xe, 0x15, 0xf, 0xb);
553 pNode->node.au32F02_param[4] = RT_MAKE_U32_FROM_U8(0xc, 0xd, 0xa, 0x0);
554 break;
555 case 0x14:
556 pNode->node.name = "PCBEEP";
557 pNode->node.au32F00_param[9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_BEEP_GEN, 0, 0)
558 | CODEC_F00_09_CAP_AMP_FMT_OVERRIDE
559 | CODEC_F00_09_CAP_OUT_AMP_PRESENT;//(7 << 20) | RT_BIT(3) | RT_BIT(2);
560 pNode->node.au32F00_param[0x12] = (0x17 << 16)|(0x3 << 8)| 0x3;
561 pNode->pcbeep.u32F0a_param = 0;
562 memset(pNode->pcbeep.B_params, 0, AMPLIFIER_SIZE);
563 break;
564 case 0x15:
565 pNode->node.name = "CD";
566 pNode->node.au32F00_param[0x9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_PIN_COMPLEX, 0, 0)
567 | CODEC_F00_09_CAP_LSB;//(4 << 20)|RT_BIT(0);
568 pNode->node.au32F00_param[0xc] = CODEC_F00_0C_CAP_INPUT;//RT_BIT(5);
569 if (!pState->fInReset)
570 pNode->cdnode.u32F1c_param = CODEC_MAKE_F1C(CODEC_F1C_PORT_FIXED,
571 CODEC_F1C_LOCATION_INTERNAL,
572 CODEC_F1C_DEVICE_CD,
573 CODEC_F1C_CONNECTION_TYPE_ATAPI,
574 CODEC_F1C_COLOR_UNKNOWN,
575 0x0, 0x7, 0x0);//RT_MAKE_U32_FROM_U8(0x70, 0x0, 0x33, 0x90);
576 break;
577 case 0x16:
578 pNode->node.name = "VolumeKnob";
579 pNode->node.au32F00_param[0x9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_VOLUME_KNOB, 0x0, 0x0);//(0x6 << 20);
580 pNode->node.au32F00_param[0x13] = RT_BIT(7)| 0x7F;
581 pNode->node.au32F00_param[0xe] = CODEC_MAKE_F00_0E(0, 0x4);
582 pNode->node.au32F02_param[0] = RT_MAKE_U32_FROM_U8(0x2, 0x3, 0x4, 0x5);
583 pNode->volumeKnob.u32F08_param = 0;
584 pNode->volumeKnob.u32F0f_param = 0x7f;
585 break;
586 case 0x17:
587 pNode->node.name = "ADC0Vol";
588 pNode->node.au32F02_param[0] = 0x12;
589 goto adcvol_init;
590 case 0x18:
591 pNode->node.name = "ADC1Vol";
592 pNode->node.au32F02_param[0] = 0x13;
593 adcvol_init:
594 memset(pNode->adcvol.B_params, 0, AMPLIFIER_SIZE);
595
596 pNode->node.au32F00_param[0x9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_AUDIO_SELECTOR, 0, 0)
597 | CODEC_F00_09_CAP_L_R_SWAP
598 | CODEC_F00_09_CAP_CONNECTION_LIST
599 | CODEC_F00_09_CAP_IN_AMP_PRESENT
600 | CODEC_F00_09_CAP_LSB;//(0x3 << 20)|RT_BIT(11)|RT_BIT(8)|RT_BIT(1)|RT_BIT(0);
601 pNode->node.au32F00_param[0xe] = CODEC_MAKE_F00_0E(0, 0x1);
602 AMPLIFIER_REGISTER(pNode->adcvol.B_params, AMPLIFIER_IN, AMPLIFIER_LEFT, 0) = RT_BIT(7);
603 AMPLIFIER_REGISTER(pNode->adcvol.B_params, AMPLIFIER_IN, AMPLIFIER_RIGHT, 0) = RT_BIT(7);
604 pNode->adcvol.u32F0c_param = 0;
605 break;
606 case 0x19:
607 pNode->node.name = "Reserved_1";
608 pNode->node.au32F00_param[0x9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_VENDOR_DEFINED, 0x3, 0)
609 | CODEC_F00_09_CAP_DIGITAL
610 | CODEC_F00_09_CAP_LSB;//(0xF << 20)|(0x3 << 16)|RT_BIT(9)|RT_BIT(0);
611 break;
612 case 0x1A:
613 pNode->node.name = "Reserved_2";
614 pNode->node.au32F00_param[0x9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_AUDIO_OUTPUT, 0x3, 0)
615 | CODEC_F00_09_CAP_DIGITAL
616 | CODEC_F00_09_CAP_LSB;//(0x3 << 16)|RT_BIT(9)|RT_BIT(0);
617 break;
618 case 0x1B:
619 pNode->node.name = "Reserved_3";
620 pNode->node.au32F00_param[0x9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_PIN_COMPLEX, 0, 0)
621 | CODEC_F00_09_CAP_DIGITAL
622 | CODEC_F00_09_CAP_CONNECTION_LIST
623 | CODEC_F00_09_CAP_LSB;//(0x4 << 20)|RT_BIT(9)|RT_BIT(8)|RT_BIT(0);
624 pNode->node.au32F00_param[0xE] = CODEC_MAKE_F00_0E(0, 0x1);
625 pNode->node.au32F00_param[0xC] = CODEC_F00_0C_CAP_OUTPUT;//0x10;
626 pNode->node.au32F02_param[0] = 0x1a;
627 pNode->reserved.u32F1c_param = CODEC_MAKE_F1C(CODEC_F1C_PORT_NO_PHYS,
628 CODEC_F1C_LOCATION_NA,
629 CODEC_F1C_DEVICE_LINE_OUT,
630 CODEC_F1C_CONNECTION_TYPE_UNKNOWN,
631 CODEC_F1C_COLOR_UNKNOWN,
632 0x0, 0x0, 0xf);//0x4000000f;
633 break;
634 default:
635 break;
636 }
637 return VINF_SUCCESS;
638}
639
640/* ALC885 */
641const static uint8_t au8Alc885Ports[] = { 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0};
642const static uint8_t au8Alc885Dacs[] = { 0x2, 0x3, 0x4, 0x5, 0x25, 0};
643const static uint8_t au8Alc885Adcs[] = { 0x7, 0x8, 0x9, 0};
644const static uint8_t au8Alc885SpdifOuts[] = { 0x6, 0 };
645const static uint8_t au8Alc885SpdifIns[] = { 0xA, 0 };
646const static uint8_t au8Alc885DigOutPins[] = { 0x1E, 0 };
647const static uint8_t au8Alc885DigInPins[] = { 0x1F, 0 };
648const static uint8_t au8Alc885AdcVols[] = { 0xE, 0xF, 0xD, 0xC, 0x26, 0xB, 0};
649const static uint8_t au8Alc885AdcMuxs[] = { 0x22, 0x23, 0x24, 0};
650const static uint8_t au8Alc885Pcbeeps[] = { 0x1D, 0 };
651const static uint8_t au8Alc885Cds[] = { 0x1C, 0 };
652const static uint8_t au8Alc885VolKnobs[] = { 0x21, 0 };
653const static uint8_t au8Alc885Reserveds[] = { 0x10, 0x11, 0x12, 0x13, 0 };
654
655
656static int alc885ResetNode(struct CODECState *pState, uint8_t nodenum, PCODECNODE pNode);
657
658static int alc885Construct(CODECState *pState)
659{
660 unconst(pState->cTotalNodes) = 0x27;
661 pState->u16VendorId = 0x10ec;
662 pState->u16DeviceId = 0x0885;
663 pState->u8BSKU = 0x08;
664 pState->u8AssemblyId = 0x85;
665 pState->pfnCodecNodeReset = alc885ResetNode;
666 pState->pNodes = (PCODECNODE)RTMemAllocZ(sizeof(CODECNODE) * pState->cTotalNodes);
667 pState->fInReset = false;
668#define ALC885WIDGET(type) pState->au8##type##s = au8Alc885##type##s
669 ALC885WIDGET(Port);
670 ALC885WIDGET(Dac);
671 ALC885WIDGET(Adc);
672 ALC885WIDGET(AdcVol);
673 ALC885WIDGET(AdcMux);
674 ALC885WIDGET(Pcbeep);
675 ALC885WIDGET(SpdifIn);
676 ALC885WIDGET(SpdifOut);
677 ALC885WIDGET(DigInPin);
678 ALC885WIDGET(DigOutPin);
679 ALC885WIDGET(Cd);
680 ALC885WIDGET(VolKnob);
681 ALC885WIDGET(Reserved);
682#undef ALC885WIDGET
683 /* @todo: test more */
684 unconst(pState->u8AdcVolsLineIn) = 0x1a;
685 unconst(pState->u8DacLineOut) = 0x0d;
686
687 return VINF_SUCCESS;
688}
689
690static int alc885ResetNode(struct CODECState *pState, uint8_t nodenum, PCODECNODE pNode)
691{
692 pNode->node.id = nodenum;
693 switch (nodenum)
694 {
695 case 0: /* Root */
696 pNode->node.au32F00_param[2] = CODEC_MAKE_F00_02(0x1, 0x0, 0x0, 0x0); /* Realtek 889 (8.1.9)*/
697 pNode->node.au32F00_param[0xA] = pState->pNodes[1].node.au32F00_param[0xA];
698
699 break;
700 case 0x1: /* AFG */
701 pNode->node.au32F00_param[0xB] = CODEC_F00_0B_PCM;
702 pNode->node.au32F00_param[0x11] = RT_BIT(30)|0x2;
703 break;
704 /* DACs */
705 case 0x2:
706 pNode->node.name = "DAC-0";
707 goto dac_init;
708 case 0x3:
709 pNode->node.name = "DAC-1";
710 goto dac_init;
711 case 0x4:
712 pNode->node.name = "DAC-2";
713 goto dac_init;
714 case 0x5:
715 pNode->node.name = "DAC-3";
716 goto dac_init;
717 case 0x25:
718 pNode->node.name = "DAC-4";
719 dac_init:
720 pNode->node.au32F00_param[0xA] = pState->pNodes[1].node.au32F00_param[0xA];
721 pNode->node.au32F00_param[0x9] = 0x11;
722 pNode->node.au32F00_param[0xB] = CODEC_F00_0B_PCM;
723 pNode->dac.u32A_param = CODEC_MAKE_A(0, 1, CODEC_A_MULT_1X, CODEC_A_DIV_1X, CODEC_A_16_BIT, 1);//(1<<14)|(0x1<<4) | 0x1;
724 break;
725 /* SPDIFs */
726 case 0x6:
727 pNode->node.name = "SPDIFOUT-0";
728 pNode->node.au32F00_param[0x9] = 0x211;
729 pNode->node.au32F00_param[0xB] = 0x1;
730 pNode->node.au32F00_param[0xA] = pState->pNodes[1].node.au32F00_param[0xA];
731 pNode->spdifout.u32A_param = CODEC_MAKE_A(0, 1, CODEC_A_MULT_1X, CODEC_A_DIV_1X, CODEC_A_16_BIT, 1);//(1<<14)|(0x1<<4) | 0x1;
732 break;
733 case 0xA:
734 pNode->node.name = "SPDIFIN-0";
735 pNode->node.au32F00_param[0x9] = 0x100391;
736 pNode->node.au32F00_param[0xA] = pState->pNodes[1].node.au32F00_param[0xA];
737 pNode->node.au32F00_param[0xB] = 0x1;
738 pNode->node.au32F02_param[0] = RT_MAKE_U32_FROM_U8(0x1F, 0, 0, 0);
739 pNode->node.au32F02_param[1] = RT_MAKE_U32_FROM_U8(0x1F, 0, 0, 0);
740 pNode->node.au32F02_param[2] = RT_MAKE_U32_FROM_U8(0x1F, 0, 0, 0);
741 pNode->node.au32F02_param[3] = RT_MAKE_U32_FROM_U8(0x1F, 0, 0, 0);
742 pNode->node.au32F00_param[0xA] = pState->pNodes[1].node.au32F00_param[0xA];
743 pNode->spdifin.u32A_param = CODEC_MAKE_A(0, 1, CODEC_A_MULT_1X, CODEC_A_DIV_1X, CODEC_A_16_BIT, 1);//(1<<14)|(0x1<<4) | 0x1;
744 break;
745 /* VENDOR DEFINE */
746 case 0x10:
747 pNode->node.name = "VENDEF-0";
748 goto vendor_define_init;
749 case 0x11:
750 pNode->node.name = "VENDEF-1";
751 goto vendor_define_init;
752 case 0x12:
753 pNode->node.name = "VENDEF-2";
754 goto vendor_define_init;
755 case 0x13:
756 pNode->node.name = "VENDEF-3";
757 goto vendor_define_init;
758 case 0x20:
759 pNode->node.name = "VENDEF-4";
760 vendor_define_init:
761 pNode->node.au32F00_param[0x9] = 0xf00000;
762 break;
763
764 /* DIGPIN */
765 case 0x1E:
766 pNode->node.name = "DIGOUT-1";
767 pNode->node.au32F00_param[0x9] = 0x400300;
768 pNode->node.au32F00_param[0xE] = 0x1;
769 pNode->port.u32F1c_param = 0x14be060;
770 pNode->node.au32F00_param[0xC] = RT_BIT(4);
771 /* N = 0~3 */
772 pNode->node.au32F02_param[0] = RT_MAKE_U32_FROM_U8(0x6, 0x0, 0x0, 0x0);
773 pNode->node.au32F02_param[1] = RT_MAKE_U32_FROM_U8(0x6, 0x0, 0x0, 0x0);
774 pNode->node.au32F02_param[2] = RT_MAKE_U32_FROM_U8(0x6, 0x0, 0x0, 0x0);
775 pNode->node.au32F02_param[3] = RT_MAKE_U32_FROM_U8(0x6, 0x0, 0x0, 0x0);
776 break;
777 case 0x1F:
778 pNode->node.name = "DIGIN-0";
779 pNode->node.au32F00_param[9] = 0x400200;
780 /* N = 0~3 */
781 pNode->node.au32F02_param[0] = RT_MAKE_U32_FROM_U8(0xA, 0x0, 0x0, 0x0);
782 pNode->node.au32F02_param[1] = RT_MAKE_U32_FROM_U8(0xA, 0x0, 0x0, 0x0);
783 pNode->node.au32F02_param[2] = RT_MAKE_U32_FROM_U8(0xA, 0x0, 0x0, 0x0);
784 pNode->node.au32F02_param[3] = RT_MAKE_U32_FROM_U8(0xA, 0x0, 0x0, 0x0);
785 break;
786 /* ADCs */
787 case 0x7:
788 pNode->node.name = "ADC-0";
789 pNode->node.au32F02_param[0] = RT_MAKE_U32_FROM_U8(0x23, 0, 0, 0);
790 pNode->node.au32F02_param[1] = RT_MAKE_U32_FROM_U8(0x23, 0, 0, 0);
791 pNode->node.au32F02_param[2] = RT_MAKE_U32_FROM_U8(0x23, 0, 0, 0);
792 pNode->node.au32F02_param[3] = RT_MAKE_U32_FROM_U8(0x23, 0, 0, 0);
793 goto adc_init;
794 break;
795 case 0x8:
796 pNode->node.name = "ADC-1";
797 pNode->node.au32F02_param[0] = RT_MAKE_U32_FROM_U8(0x24, 0, 0, 0);
798 pNode->node.au32F02_param[1] = RT_MAKE_U32_FROM_U8(0x24, 0, 0, 0);
799 pNode->node.au32F02_param[2] = RT_MAKE_U32_FROM_U8(0x24, 0, 0, 0);
800 pNode->node.au32F02_param[3] = RT_MAKE_U32_FROM_U8(0x24, 0, 0, 0);
801 goto adc_init;
802 break;
803 case 0x9:
804 pNode->node.name = "ADC-2";
805 pNode->node.au32F02_param[0] = RT_MAKE_U32_FROM_U8(0x22, 0, 0, 0);
806 pNode->node.au32F02_param[1] = RT_MAKE_U32_FROM_U8(0x22, 0, 0, 0);
807 pNode->node.au32F02_param[2] = RT_MAKE_U32_FROM_U8(0x22, 0, 0, 0);
808 pNode->node.au32F02_param[3] = RT_MAKE_U32_FROM_U8(0x22, 0, 0, 0);
809 adc_init:
810 pNode->node.au32F00_param[0xB] = 0x1;
811 pNode->node.au32F00_param[0x9] = 0x10011b;
812 pNode->node.au32F00_param[0xD] = 0x80032e10;
813 pNode->node.au32F00_param[0xE] = 0x1;
814 pNode->node.au32F00_param[0xA] = pState->pNodes[1].node.au32F00_param[0xA];
815 pNode->adc.u32A_param = CODEC_MAKE_A(0, 1, CODEC_A_MULT_1X, CODEC_A_DIV_1X, CODEC_A_16_BIT, 1);//(1<<14)|(0x1<<4) | 0x1;
816 break;
817 /* Ports */
818 case 0x14:
819 pNode->node.name = "PORT-D";
820 pNode->port.u32F1c_param = 0x12b4050;
821 pNode->node.au32F00_param[0xC] = RT_BIT(13)|RT_BIT(12)|RT_BIT(11)|RT_BIT(10)|RT_BIT(9)|RT_BIT(8)|RT_BIT(5)|RT_BIT(4)|RT_BIT(3)|RT_BIT(2);
822 goto port_init;
823 break;
824 case 0x15:
825 pNode->node.name = "PORT-A";
826 pNode->port.u32F1c_param = 0x18b3020;
827 pNode->node.au32F00_param[0xC] = RT_BIT(13)|RT_BIT(12)|RT_BIT(11)|RT_BIT(10)|RT_BIT(9)|RT_BIT(8)|RT_BIT(5)|RT_BIT(4)|RT_BIT(3)|RT_BIT(2);
828 goto port_init;
829 break;
830 case 0x16:
831 pNode->node.name = "PORT-G";
832 pNode->port.u32F1c_param = 0x400000f0;
833 pNode->node.au32F00_param[0xC] = RT_BIT(4)|RT_BIT(3)|RT_BIT(2);
834 goto port_init;
835 break;
836 case 0x17:
837 pNode->node.name = "PORT-H";
838 pNode->port.u32F1c_param = 0x400000f0;
839 pNode->node.au32F00_param[0xC] = RT_BIT(4)|RT_BIT(3)|RT_BIT(2);
840 goto port_init;
841 break;
842 case 0x18:
843 pNode->node.name = "PORT-B";
844 pNode->port.u32F1c_param = 0x90100140;
845 pNode->node.au32F00_param[0xC] = RT_BIT(13)|RT_BIT(12)|RT_BIT(11)|RT_BIT(10)|RT_BIT(9)|RT_BIT(8)|RT_BIT(5)|RT_BIT(4)|RT_BIT(3)|RT_BIT(2);
846 goto port_init;
847 break;
848 case 0x19:
849 pNode->node.name = "PORT-F";
850 pNode->port.u32F1c_param = 0x90a00110;
851 pNode->node.au32F00_param[0xC] = RT_BIT(13)|RT_BIT(12)|RT_BIT(11)|RT_BIT(10)|RT_BIT(9)|RT_BIT(8)|RT_BIT(5)|RT_BIT(4)|RT_BIT(3)|RT_BIT(2);
852 goto port_init;
853 break;
854 case 0x1A:
855 pNode->node.name = "PORT-C";
856 pNode->port.u32F1c_param = 0x90100141;
857 pNode->node.au32F00_param[0xC] = RT_BIT(13)|RT_BIT(12)|RT_BIT(11)|RT_BIT(10)|RT_BIT(9)|RT_BIT(8)|RT_BIT(5)|RT_BIT(4)|RT_BIT(3)|RT_BIT(2);
858 goto port_init;
859 break;
860 case 0x1B:
861 pNode->node.name = "PORT-E";
862 pNode->port.u32F1c_param = 0x400000f0;
863 pNode->node.au32F00_param[0xC] = RT_BIT(13)|RT_BIT(12)|RT_BIT(11)|RT_BIT(10)|RT_BIT(9)|RT_BIT(8)|RT_BIT(5)|RT_BIT(4)|RT_BIT(3)|RT_BIT(2);
864 port_init:
865 pNode->node.au32F00_param[0x9] = 0x40018f;
866 pNode->node.au32F00_param[0xD] = 0x270300;
867 pNode->node.au32F00_param[0xE] = 0x5;
868 /* N = 0~3 */
869 pNode->node.au32F02_param[0] = RT_MAKE_U32_FROM_U8(0xC, 0xD, 0xE, 0xF);
870 pNode->node.au32F02_param[1] = RT_MAKE_U32_FROM_U8(0xC, 0xD, 0xE, 0xF);
871 pNode->node.au32F02_param[2] = RT_MAKE_U32_FROM_U8(0xC, 0xD, 0xE, 0xF);
872 pNode->node.au32F02_param[3] = RT_MAKE_U32_FROM_U8(0xC, 0xD, 0xE, 0xF);
873 /* N = 4~7 */
874 pNode->node.au32F02_param[4] = RT_MAKE_U32_FROM_U8(0x26, 0, 0, 0);
875 pNode->node.au32F02_param[5] = RT_MAKE_U32_FROM_U8(0x26, 0, 0, 0);
876 pNode->node.au32F02_param[6] = RT_MAKE_U32_FROM_U8(0x26, 0, 0, 0);
877 pNode->node.au32F02_param[7] = RT_MAKE_U32_FROM_U8(0x26, 0, 0, 0);
878 break;
879 /* ADCVols */
880 case 0x26:
881 pNode->node.name = "AdcVol-0";
882 pNode->node.au32F00_param[0x9] = 0x20010f;
883 pNode->node.au32F00_param[0xD] = 0x80000000;
884 pNode->node.au32F00_param[0xE] = 0x2;
885 pNode->node.au32F00_param[0x12] = 0x34040;
886 pNode->node.au32F02_param[0] = RT_MAKE_U32_FROM_U8(0x25, 0xB, 0, 0);
887 pNode->node.au32F02_param[1] = RT_MAKE_U32_FROM_U8(0x25, 0xB, 0, 0);
888 pNode->node.au32F02_param[2] = RT_MAKE_U32_FROM_U8(0x25, 0xB, 0, 0);
889 pNode->node.au32F02_param[3] = RT_MAKE_U32_FROM_U8(0x25, 0xB, 0, 0);
890 break;
891 case 0xF:
892 pNode->node.name = "AdcVol-1";
893 pNode->node.au32F00_param[0x9] = 0x20010f;
894 pNode->node.au32F00_param[0xE] = 0x2;
895 pNode->node.au32F00_param[0x12] = 0x34040;
896 pNode->node.au32F02_param[0] = RT_MAKE_U32_FROM_U8(0x5, 0xB, 0, 0);
897 pNode->node.au32F02_param[1] = RT_MAKE_U32_FROM_U8(0x5, 0xB, 0, 0);
898 pNode->node.au32F02_param[2] = RT_MAKE_U32_FROM_U8(0x5, 0xB, 0, 0);
899 pNode->node.au32F02_param[3] = RT_MAKE_U32_FROM_U8(0x5, 0xB, 0, 0);
900 break;
901 case 0xE:
902 pNode->node.name = "AdcVol-2";
903 pNode->node.au32F00_param[0x9] = 0x20010f;
904 pNode->node.au32F00_param[0xE] = 0x2;
905 pNode->node.au32F00_param[0xD] = 0x80000000;
906 pNode->node.au32F00_param[0x12] = 0x34040;
907 pNode->node.au32F02_param[0] = RT_MAKE_U32_FROM_U8(0x4, 0xB, 0, 0);
908 pNode->node.au32F02_param[1] = RT_MAKE_U32_FROM_U8(0x4, 0xB, 0, 0);
909 pNode->node.au32F02_param[2] = RT_MAKE_U32_FROM_U8(0x4, 0xB, 0, 0);
910 pNode->node.au32F02_param[3] = RT_MAKE_U32_FROM_U8(0x4, 0xB, 0, 0);
911 break;
912 case 0xD:
913 pNode->node.name = "AdcVol-3";
914 pNode->node.au32F00_param[0x9] = 0x20010f;
915 pNode->node.au32F00_param[0xE] = 0x2;
916 pNode->node.au32F00_param[0xD] = 0x80000000;
917 pNode->node.au32F00_param[0x12] = 0x34040;
918 pNode->node.au32F02_param[0] = RT_MAKE_U32_FROM_U8(0x3, 0xB, 0, 0);
919 pNode->node.au32F02_param[1] = RT_MAKE_U32_FROM_U8(0x3, 0xB, 0, 0);
920 pNode->node.au32F02_param[2] = RT_MAKE_U32_FROM_U8(0x3, 0xB, 0, 0);
921 pNode->node.au32F02_param[3] = RT_MAKE_U32_FROM_U8(0x3, 0xB, 0, 0);
922 break;
923 case 0xC:
924 pNode->node.name = "AdcVol-4";
925 pNode->node.au32F00_param[0x9] = 0x20010f;
926 pNode->node.au32F00_param[0xE] = 0x2;
927 pNode->node.au32F00_param[0xD] = 0x80000000;
928 pNode->node.au32F00_param[0x12] = 0x34040;
929 pNode->node.au32F02_param[0] = RT_MAKE_U32_FROM_U8(0x2, 0xB, 0, 0);
930 pNode->node.au32F02_param[1] = RT_MAKE_U32_FROM_U8(0x2, 0xB, 0, 0);
931 pNode->node.au32F02_param[2] = RT_MAKE_U32_FROM_U8(0x2, 0xB, 0, 0);
932 pNode->node.au32F02_param[3] = RT_MAKE_U32_FROM_U8(0x2, 0xB, 0, 0);
933 break;
934 case 0xB:
935 pNode->node.name = "AdcVol-5";
936 pNode->node.au32F00_param[0x9] = 0x20010b;
937 pNode->node.au32F00_param[0xD] = 0x80051f17;
938 /* N = 0~3 */
939 pNode->node.au32F02_param[0] = RT_MAKE_U32_FROM_U8(0x18, 0x19, 0x1A, 0x1B);
940 pNode->node.au32F02_param[1] = RT_MAKE_U32_FROM_U8(0x18, 0x19, 0x1A, 0x1B);
941 pNode->node.au32F02_param[2] = RT_MAKE_U32_FROM_U8(0x18, 0x19, 0x1A, 0x1B);
942 pNode->node.au32F02_param[3] = RT_MAKE_U32_FROM_U8(0x18, 0x19, 0x1A, 0x1B);
943 /* N = 4~7 */
944 pNode->node.au32F02_param[4] = RT_MAKE_U32_FROM_U8(0x1C, 0x1D, 0x14, 0x15);
945 pNode->node.au32F02_param[5] = RT_MAKE_U32_FROM_U8(0x1C, 0x1D, 0x14, 0x15);
946 pNode->node.au32F02_param[6] = RT_MAKE_U32_FROM_U8(0x1C, 0x1D, 0x14, 0x15);
947 pNode->node.au32F02_param[7] = RT_MAKE_U32_FROM_U8(0x1C, 0x1D, 0x14, 0x15);
948 /* N = 8~11 */
949 pNode->node.au32F02_param[8] = RT_MAKE_U32_FROM_U8(0x16, 0x17, 0, 0);
950 pNode->node.au32F02_param[9] = RT_MAKE_U32_FROM_U8(0x16, 0x17, 0, 0);
951 pNode->node.au32F02_param[10] = RT_MAKE_U32_FROM_U8(0x16, 0x17, 0, 0);
952 pNode->node.au32F02_param[11] = RT_MAKE_U32_FROM_U8(0x16, 0x17, 0, 0);
953 break;
954 /* AdcMuxs */
955 case 0x22:
956 pNode->node.name = "AdcMux-0";
957 pNode->node.au32F00_param[0x9] = 0x20010b;
958 pNode->node.au32F00_param[0xD] = 0x80000000;
959 pNode->node.au32F00_param[0xE] = 0xb;
960 goto adc_mux_init;
961 case 0x23:
962 pNode->node.name = "AdcMux-1";
963 pNode->node.au32F00_param[0x9] = 0x20010b;
964 pNode->node.au32F00_param[0xD] = 0x80000000;
965 pNode->node.au32F00_param[0xE] = 0xb;
966 adc_mux_init:
967 /* N = 0~3 */
968 pNode->node.au32F02_param[0] = RT_MAKE_U32_FROM_U8(0x18, 0x19, 0x1A, 0x1B);
969 pNode->node.au32F02_param[1] = RT_MAKE_U32_FROM_U8(0x18, 0x19, 0x1A, 0x1B);
970 pNode->node.au32F02_param[2] = RT_MAKE_U32_FROM_U8(0x18, 0x19, 0x1A, 0x1B);
971 pNode->node.au32F02_param[3] = RT_MAKE_U32_FROM_U8(0x18, 0x19, 0x1A, 0x1B);
972 /* N = 4~7 */
973 pNode->node.au32F02_param[4] = RT_MAKE_U32_FROM_U8(0x1C, 0x1D, 0x14, 0x15);
974 pNode->node.au32F02_param[5] = RT_MAKE_U32_FROM_U8(0x1C, 0x1D, 0x14, 0x15);
975 pNode->node.au32F02_param[6] = RT_MAKE_U32_FROM_U8(0x1C, 0x1D, 0x14, 0x15);
976 pNode->node.au32F02_param[7] = RT_MAKE_U32_FROM_U8(0x1C, 0x1D, 0x14, 0x15);
977 /* N = 8~11 */
978 pNode->node.au32F02_param[8] = RT_MAKE_U32_FROM_U8(0x16, 0x17, 0xB, 0);
979 pNode->node.au32F02_param[9] = RT_MAKE_U32_FROM_U8(0x16, 0x17, 0xB, 0);
980 pNode->node.au32F02_param[10] = RT_MAKE_U32_FROM_U8(0x16, 0x17, 0xB, 0);
981 pNode->node.au32F02_param[11] = RT_MAKE_U32_FROM_U8(0x16, 0x17, 0xB, 0);
982 break;
983 case 0x24:
984 pNode->node.name = "AdcMux-2";
985 pNode->node.au32F00_param[0x9] = 0x20010b;
986 pNode->node.au32F00_param[0xD] = 0x80000000;
987 pNode->node.au32F00_param[0xE] = 0xb;
988 /* N = 0~3 */
989 pNode->node.au32F02_param[0] = RT_MAKE_U32_FROM_U8(0x18, 0x19, 0x1A, 0x1B);
990 pNode->node.au32F02_param[1] = RT_MAKE_U32_FROM_U8(0x18, 0x19, 0x1A, 0x1B);
991 pNode->node.au32F02_param[2] = RT_MAKE_U32_FROM_U8(0x18, 0x19, 0x1A, 0x1B);
992 pNode->node.au32F02_param[3] = RT_MAKE_U32_FROM_U8(0x18, 0x19, 0x1A, 0x1B);
993 /* N = 4~7 */
994 pNode->node.au32F02_param[4] = RT_MAKE_U32_FROM_U8(0x1C, 0x1D, 0x14, 0x15);
995 pNode->node.au32F02_param[5] = RT_MAKE_U32_FROM_U8(0x1C, 0x1D, 0x14, 0x15);
996 pNode->node.au32F02_param[6] = RT_MAKE_U32_FROM_U8(0x1C, 0x1D, 0x14, 0x15);
997 pNode->node.au32F02_param[7] = RT_MAKE_U32_FROM_U8(0x1C, 0x1D, 0x14, 0x15);
998 /* N = 8~11 */
999 pNode->node.au32F02_param[8] = RT_MAKE_U32_FROM_U8(0x16, 0x17, 0xB, 0x12);
1000 pNode->node.au32F02_param[9] = RT_MAKE_U32_FROM_U8(0x16, 0x17, 0xB, 0x12);
1001 pNode->node.au32F02_param[10] = RT_MAKE_U32_FROM_U8(0x16, 0x17, 0xB, 0x12);
1002 pNode->node.au32F02_param[11] = RT_MAKE_U32_FROM_U8(0x16, 0x17, 0xB, 0x12);
1003 break;
1004 /* PCBEEP */
1005 case 0x1D:
1006 pNode->node.name = "PCBEEP";
1007 pNode->node.au32F00_param[0x9] = 0x400000;
1008 pNode->port.u32F1c_param = 0x400000f0;
1009 pNode->node.au32F00_param[0xC] = RT_BIT(5);
1010 break;
1011 /* CD */
1012 case 0x1C:
1013 pNode->node.name = "CD";
1014 pNode->node.au32F00_param[0x9] = 0x400001;
1015 pNode->port.u32F1c_param = 0x400000f0;
1016 pNode->node.au32F00_param[0xC] = RT_BIT(5);
1017 break;
1018 case 0x21:
1019 pNode->node.name = "VolumeKnob";
1020 pNode->node.au32F00_param[0x9] = (0x6 << 20)|RT_BIT(7);
1021 break;
1022 default:
1023 AssertMsgFailed(("Unsupported Node"));
1024 }
1025 return VINF_SUCCESS;
1026}
1027
1028
1029/* generic */
1030
1031#define DECLISNODEOFTYPE(type) \
1032 static inline int codecIs##type##Node(struct CODECState *pState, uint8_t cNode) \
1033 { \
1034 Assert(pState->au8##type##s); \
1035 for(int i = 0; pState->au8##type##s[i] != 0; ++i) \
1036 if (pState->au8##type##s[i] == cNode) \
1037 return 1; \
1038 return 0; \
1039 }
1040/* codecIsPortNode */
1041DECLISNODEOFTYPE(Port)
1042/* codecIsDacNode */
1043DECLISNODEOFTYPE(Dac)
1044/* codecIsAdcVolNode */
1045DECLISNODEOFTYPE(AdcVol)
1046/* codecIsAdcNode */
1047DECLISNODEOFTYPE(Adc)
1048/* codecIsAdcMuxNode */
1049DECLISNODEOFTYPE(AdcMux)
1050/* codecIsPcbeepNode */
1051DECLISNODEOFTYPE(Pcbeep)
1052/* codecIsSpdifOutNode */
1053DECLISNODEOFTYPE(SpdifOut)
1054/* codecIsSpdifInNode */
1055DECLISNODEOFTYPE(SpdifIn)
1056/* codecIsDigInPinNode */
1057DECLISNODEOFTYPE(DigInPin)
1058/* codecIsDigOutPinNode */
1059DECLISNODEOFTYPE(DigOutPin)
1060/* codecIsCdNode */
1061DECLISNODEOFTYPE(Cd)
1062/* codecIsVolKnobNode */
1063DECLISNODEOFTYPE(VolKnob)
1064/* codecIsReservedNode */
1065DECLISNODEOFTYPE(Reserved)
1066
1067static int codecToAudVolume(AMPLIFIER *pAmp, audmixerctl_t mt);
1068
1069static inline void codecSetRegister(uint32_t *pu32Reg, uint32_t u32Cmd, uint8_t u8Offset, uint32_t mask)
1070{
1071 Assert((pu32Reg && u8Offset < 32));
1072 *pu32Reg &= ~(mask << u8Offset);
1073 *pu32Reg |= (u32Cmd & mask) << u8Offset;
1074}
1075static inline void codecSetRegisterU8(uint32_t *pu32Reg, uint32_t u32Cmd, uint8_t u8Offset)
1076{
1077 codecSetRegister(pu32Reg, u32Cmd, u8Offset, CODEC_VERB_8BIT_DATA);
1078}
1079
1080static inline void codecSetRegisterU16(uint32_t *pu32Reg, uint32_t u32Cmd, uint8_t u8Offset)
1081{
1082 codecSetRegister(pu32Reg, u32Cmd, u8Offset, CODEC_VERB_16BIT_DATA);
1083}
1084
1085
1086static int codecUnimplemented(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1087{
1088 Log(("codecUnimplemented: cmd(raw:%x: cad:%x, d:%c, nid:%x, verb:%x)\n", cmd,
1089 CODEC_CAD(cmd), CODEC_DIRECT(cmd) ? 'N' : 'Y', CODEC_NID(cmd), CODEC_VERBDATA(cmd)));
1090 *pResp = 0;
1091 return VINF_SUCCESS;
1092}
1093
1094static int codecBreak(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1095{
1096 int rc;
1097 rc = codecUnimplemented(pState, cmd, pResp);
1098 *pResp |= CODEC_RESPONSE_UNSOLICITED;
1099 return rc;
1100}
1101/* B-- */
1102static int codecGetAmplifier(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1103{
1104 Assert((CODEC_CAD(cmd) == pState->id));
1105 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1106 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1107 {
1108 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1109 return VINF_SUCCESS;
1110 }
1111 *pResp = 0;
1112 /* HDA spec 7.3.3.7 Note A */
1113 /* @todo: if index out of range response should be 0 */
1114 uint8_t u8Index = CODEC_GET_AMP_DIRECTION(cmd) == AMPLIFIER_OUT? 0 : CODEC_GET_AMP_INDEX(cmd);
1115
1116 PCODECNODE pNode = &pState->pNodes[CODEC_NID(cmd)];
1117 if (codecIsDacNode(pState, CODEC_NID(cmd)))
1118 *pResp = AMPLIFIER_REGISTER(pNode->dac.B_params,
1119 CODEC_GET_AMP_DIRECTION(cmd),
1120 CODEC_GET_AMP_SIDE(cmd),
1121 u8Index);
1122 else if (codecIsAdcVolNode(pState, CODEC_NID(cmd)))
1123 *pResp = AMPLIFIER_REGISTER(pNode->adcvol.B_params,
1124 CODEC_GET_AMP_DIRECTION(cmd),
1125 CODEC_GET_AMP_SIDE(cmd),
1126 u8Index);
1127 else if (codecIsAdcMuxNode(pState, CODEC_NID(cmd)))
1128 *pResp = AMPLIFIER_REGISTER(pNode->adcmux.B_params,
1129 CODEC_GET_AMP_DIRECTION(cmd),
1130 CODEC_GET_AMP_SIDE(cmd),
1131 u8Index);
1132 else if (codecIsPcbeepNode(pState, CODEC_NID(cmd)))
1133 *pResp = AMPLIFIER_REGISTER(pNode->pcbeep.B_params,
1134 CODEC_GET_AMP_DIRECTION(cmd),
1135 CODEC_GET_AMP_SIDE(cmd),
1136 u8Index);
1137 else if (codecIsPortNode(pState, CODEC_NID(cmd)))
1138 *pResp = AMPLIFIER_REGISTER(pNode->port.B_params,
1139 CODEC_GET_AMP_DIRECTION(cmd),
1140 CODEC_GET_AMP_SIDE(cmd),
1141 u8Index);
1142 else if (codecIsAdcNode(pState, CODEC_NID(cmd)))
1143 *pResp = AMPLIFIER_REGISTER(pNode->adc.B_params,
1144 CODEC_GET_AMP_DIRECTION(cmd),
1145 CODEC_GET_AMP_SIDE(cmd),
1146 u8Index);
1147 else{
1148 AssertMsgReturn(0, ("access to fields of %x need to be implemented\n", CODEC_NID(cmd)), VINF_SUCCESS);
1149 }
1150 return VINF_SUCCESS;
1151}
1152/* 3-- */
1153static int codecSetAmplifier(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1154{
1155 AMPLIFIER *pAmplifier = NULL;
1156 bool fIsLeft = false;
1157 bool fIsRight = false;
1158 bool fIsOut = false;
1159 bool fIsIn = false;
1160 uint8_t u8Index = 0;
1161 Assert((CODEC_CAD(cmd) == pState->id));
1162 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1163 {
1164 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1165 return VINF_SUCCESS;
1166 }
1167 *pResp = 0;
1168 PCODECNODE pNode = &pState->pNodes[CODEC_NID(cmd)];
1169 if (codecIsDacNode(pState, CODEC_NID(cmd)))
1170 pAmplifier = &pNode->dac.B_params;
1171 else if (codecIsAdcVolNode(pState, CODEC_NID(cmd)))
1172 pAmplifier = &pNode->adcvol.B_params;
1173 else if (codecIsAdcMuxNode(pState, CODEC_NID(cmd)))
1174 pAmplifier = &pNode->adcmux.B_params;
1175 else if (codecIsPcbeepNode(pState, CODEC_NID(cmd)))
1176 pAmplifier = &pNode->pcbeep.B_params;
1177 else if (codecIsPortNode(pState, CODEC_NID(cmd)))
1178 pAmplifier = &pNode->port.B_params;
1179 else if (codecIsAdcNode(pState, CODEC_NID(cmd)))
1180 pAmplifier = &pNode->adc.B_params;
1181 Assert(pAmplifier);
1182 if (pAmplifier)
1183 {
1184 fIsOut = CODEC_SET_AMP_IS_OUT_DIRECTION(cmd);
1185 fIsIn = CODEC_SET_AMP_IS_IN_DIRECTION(cmd);
1186 fIsRight = CODEC_SET_AMP_IS_RIGHT_SIDE(cmd);
1187 fIsLeft = CODEC_SET_AMP_IS_LEFT_SIDE(cmd);
1188 u8Index = CODEC_SET_AMP_INDEX(cmd);
1189 if ( (!fIsLeft && !fIsRight)
1190 || (!fIsOut && !fIsIn))
1191 return VINF_SUCCESS;
1192 if (fIsIn)
1193 {
1194 if (fIsLeft)
1195 codecSetRegisterU8(&AMPLIFIER_REGISTER(*pAmplifier, AMPLIFIER_IN, AMPLIFIER_LEFT, u8Index), cmd, 0);
1196 if (fIsRight)
1197 codecSetRegisterU8(&AMPLIFIER_REGISTER(*pAmplifier, AMPLIFIER_IN, AMPLIFIER_RIGHT, u8Index), cmd, 0);
1198 }
1199 if (fIsOut)
1200 {
1201 if (fIsLeft)
1202 codecSetRegisterU8(&AMPLIFIER_REGISTER(*pAmplifier, AMPLIFIER_OUT, AMPLIFIER_LEFT, u8Index), cmd, 0);
1203 if (fIsRight)
1204 codecSetRegisterU8(&AMPLIFIER_REGISTER(*pAmplifier, AMPLIFIER_OUT, AMPLIFIER_RIGHT, u8Index), cmd, 0);
1205 }
1206 if (CODEC_NID(cmd) == pState->u8DacLineOut)
1207 codecToAudVolume(pAmplifier, AUD_MIXER_VOLUME);
1208 if (CODEC_NID(cmd) == pState->u8AdcVolsLineIn) /* Microphone */
1209 codecToAudVolume(pAmplifier, AUD_MIXER_LINE_IN);
1210 }
1211 return VINF_SUCCESS;
1212}
1213
1214static int codecGetParameter(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1215{
1216 Assert((CODEC_CAD(cmd) == pState->id));
1217 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1218 {
1219 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1220 return VINF_SUCCESS;
1221 }
1222 Assert(((cmd & CODEC_VERB_8BIT_DATA) < CODECNODE_F0_PARAM_LENGTH));
1223 if ((cmd & CODEC_VERB_8BIT_DATA) >= CODECNODE_F0_PARAM_LENGTH)
1224 {
1225 Log(("HDAcodec: invalid F00 parameter %d\n", (cmd & CODEC_VERB_8BIT_DATA)));
1226 return VINF_SUCCESS;
1227 }
1228 *pResp = 0;
1229 *pResp = pState->pNodes[CODEC_NID(cmd)].node.au32F00_param[cmd & CODEC_VERB_8BIT_DATA];
1230 return VINF_SUCCESS;
1231}
1232
1233/* F01 */
1234static int codecGetConSelectCtrl(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1235{
1236 Assert((CODEC_CAD(cmd) == pState->id));
1237 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1238 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1239 {
1240 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1241 return VINF_SUCCESS;
1242 }
1243 *pResp = 0;
1244 if (codecIsAdcMuxNode(pState, CODEC_NID(cmd)))
1245 *pResp = pState->pNodes[CODEC_NID(cmd)].adcmux.u32F01_param;
1246 else if (codecIsDigOutPinNode(pState, CODEC_NID(cmd)))
1247 *pResp = pState->pNodes[CODEC_NID(cmd)].digout.u32F01_param;
1248 else if (codecIsPortNode(pState, CODEC_NID(cmd)))
1249 *pResp = pState->pNodes[CODEC_NID(cmd)].port.u32F01_param;
1250 else if (codecIsAdcNode(pState, CODEC_NID(cmd)))
1251 *pResp = pState->pNodes[CODEC_NID(cmd)].adc.u32F01_param;
1252 else if (codecIsAdcVolNode(pState, CODEC_NID(cmd)))
1253 *pResp = pState->pNodes[CODEC_NID(cmd)].adcvol.u32F01_param;
1254 return VINF_SUCCESS;
1255}
1256
1257/* 701 */
1258static int codecSetConSelectCtrl(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1259{
1260 uint32_t *pu32Reg = NULL;
1261 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1262 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1263 {
1264 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1265 return VINF_SUCCESS;
1266 }
1267 *pResp = 0;
1268 if (codecIsAdcMuxNode(pState, CODEC_NID(cmd)))
1269 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].adcmux.u32F01_param;
1270 else if (codecIsDigOutPinNode(pState, CODEC_NID(cmd)))
1271 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].digout.u32F01_param;
1272 else if (codecIsPortNode(pState, CODEC_NID(cmd)))
1273 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].port.u32F01_param;
1274 else if (codecIsAdcNode(pState, CODEC_NID(cmd)))
1275 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].adc.u32F01_param;
1276 else if (codecIsAdcVolNode(pState, CODEC_NID(cmd)))
1277 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].adcvol.u32F01_param;
1278 Assert((pu32Reg));
1279 if (pu32Reg)
1280 codecSetRegisterU8(pu32Reg, cmd, 0);
1281 return VINF_SUCCESS;
1282}
1283
1284/* F07 */
1285static int codecGetPinCtrl(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1286{
1287 Assert((CODEC_CAD(cmd) == pState->id));
1288 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1289 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1290 {
1291 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1292 return VINF_SUCCESS;
1293 }
1294 *pResp = 0;
1295 if (codecIsPortNode(pState, CODEC_NID(cmd)))
1296 *pResp = pState->pNodes[CODEC_NID(cmd)].port.u32F07_param;
1297 else if (codecIsDigOutPinNode(pState, CODEC_NID(cmd)))
1298 *pResp = pState->pNodes[CODEC_NID(cmd)].digout.u32F07_param;
1299 else if (codecIsDigInPinNode(pState, CODEC_NID(cmd)))
1300 *pResp = pState->pNodes[CODEC_NID(cmd)].digin.u32F07_param;
1301 else if (codecIsCdNode(pState, CODEC_NID(cmd)))
1302 *pResp = pState->pNodes[CODEC_NID(cmd)].cdnode.u32F07_param;
1303 else if (codecIsPcbeepNode(pState, CODEC_NID(cmd)))
1304 *pResp = pState->pNodes[CODEC_NID(cmd)].pcbeep.u32F07_param;
1305 else if (codecIsReservedNode(pState, CODEC_NID(cmd)))
1306 *pResp = pState->pNodes[CODEC_NID(cmd)].reserved.u32F07_param;
1307 else
1308 AssertMsgFailed(("Unsupported"));
1309 return VINF_SUCCESS;
1310}
1311
1312/* 707 */
1313static int codecSetPinCtrl(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1314{
1315 Assert((CODEC_CAD(cmd) == pState->id));
1316 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1317 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1318 {
1319 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1320 return VINF_SUCCESS;
1321 }
1322 *pResp = 0;
1323 uint32_t *pu32Reg = NULL;
1324 if (codecIsPortNode(pState, CODEC_NID(cmd)))
1325 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].port.u32F07_param;
1326 else if (codecIsDigInPinNode(pState, CODEC_NID(cmd)))
1327 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].digin.u32F07_param;
1328 else if (codecIsDigOutPinNode(pState, CODEC_NID(cmd)))
1329 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].digout.u32F07_param;
1330 else if (codecIsCdNode(pState, CODEC_NID(cmd)))
1331 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].cdnode.u32F07_param;
1332 else if (codecIsPcbeepNode(pState, CODEC_NID(cmd)))
1333 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].pcbeep.u32F07_param;
1334 else if ( codecIsReservedNode(pState, CODEC_NID(cmd))
1335 && CODEC_NID(cmd) == 0x1b
1336 && pState->enmCodec == STAC9220_CODEC)
1337 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].reserved.u32F07_param;
1338 Assert((pu32Reg));
1339 if (pu32Reg)
1340 codecSetRegisterU8(pu32Reg, cmd, 0);
1341 return VINF_SUCCESS;
1342}
1343
1344/* F08 */
1345static int codecGetUnsolicitedEnabled(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1346{
1347 Assert((CODEC_CAD(cmd) == pState->id));
1348 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1349 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1350 {
1351 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1352 return VINF_SUCCESS;
1353 }
1354 *pResp = 0;
1355 if (codecIsPortNode(pState, CODEC_NID(cmd)))
1356 *pResp = pState->pNodes[CODEC_NID(cmd)].port.u32F08_param;
1357 else if (codecIsDigInPinNode(pState, CODEC_NID(cmd)))
1358 *pResp = pState->pNodes[CODEC_NID(cmd)].digin.u32F08_param;
1359 else if ((cmd) == 1 /* AFG */)
1360 *pResp = pState->pNodes[CODEC_NID(cmd)].afg.u32F08_param;
1361 else if (codecIsVolKnobNode(pState, CODEC_NID(cmd)))
1362 *pResp = pState->pNodes[CODEC_NID(cmd)].volumeKnob.u32F08_param;
1363 else if (codecIsDigOutPinNode(pState, CODEC_NID(cmd)))
1364 *pResp = pState->pNodes[CODEC_NID(cmd)].digout.u32F08_param;
1365 else if (codecIsDigInPinNode(pState, CODEC_NID(cmd)))
1366 *pResp = pState->pNodes[CODEC_NID(cmd)].digin.u32F08_param;
1367 else
1368 AssertMsgFailed(("unsupported operation %x on node: %x\n", CODEC_VERB_CMD8(cmd), CODEC_NID(cmd)));
1369 return VINF_SUCCESS;
1370}
1371
1372/* 708 */
1373static int codecSetUnsolicitedEnabled(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1374{
1375 Assert((CODEC_CAD(cmd) == pState->id));
1376 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1377 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1378 {
1379 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1380 return VINF_SUCCESS;
1381 }
1382 *pResp = 0;
1383 uint32_t *pu32Reg = NULL;
1384 if (codecIsPortNode(pState, CODEC_NID(cmd)))
1385 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].port.u32F08_param;
1386 else if (codecIsDigInPinNode(pState, CODEC_NID(cmd)))
1387 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].digin.u32F08_param;
1388 else if (CODEC_NID(cmd) == 1 /* AFG */)
1389 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].afg.u32F08_param;
1390 else if (codecIsVolKnobNode(pState, CODEC_NID(cmd)))
1391 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].volumeKnob.u32F08_param;
1392 else if (codecIsDigInPinNode(pState, CODEC_NID(cmd)))
1393 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].digin.u32F08_param;
1394 else if (codecIsDigOutPinNode(pState, CODEC_NID(cmd)))
1395 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].digout.u32F08_param;
1396 else
1397 AssertMsgFailed(("unsupported operation %x on node: %x\n", CODEC_VERB_CMD8(cmd), CODEC_NID(cmd)));
1398 Assert(pu32Reg);
1399 if(pu32Reg)
1400 codecSetRegisterU8(pu32Reg, cmd, 0);
1401 return VINF_SUCCESS;
1402}
1403
1404/* F09 */
1405static int codecGetPinSense(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1406{
1407 Assert((CODEC_CAD(cmd) == pState->id));
1408 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1409 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1410 {
1411 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1412 return VINF_SUCCESS;
1413 }
1414 *pResp = 0;
1415 if (codecIsPortNode(pState, CODEC_NID(cmd)))
1416 *pResp = pState->pNodes[CODEC_NID(cmd)].port.u32F09_param;
1417 else if (codecIsDigInPinNode(pState, CODEC_NID(cmd)))
1418 *pResp = pState->pNodes[CODEC_NID(cmd)].digin.u32F09_param;
1419 else
1420 AssertMsgFailed(("unsupported operation %x on node: %x\n", CODEC_VERB_CMD8(cmd), CODEC_NID(cmd)));
1421 return VINF_SUCCESS;
1422}
1423
1424/* 709 */
1425static int codecSetPinSense(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1426{
1427 Assert((CODEC_CAD(cmd) == pState->id));
1428 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1429 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1430 {
1431 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1432 return VINF_SUCCESS;
1433 }
1434 *pResp = 0;
1435 uint32_t *pu32Reg = NULL;
1436 if (codecIsPortNode(pState, CODEC_NID(cmd)))
1437 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].port.u32F09_param;
1438 else if (codecIsDigInPinNode(pState, CODEC_NID(cmd)))
1439 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].digin.u32F09_param;
1440 Assert(pu32Reg);
1441 if(pu32Reg)
1442 codecSetRegisterU8(pu32Reg, cmd, 0);
1443 return VINF_SUCCESS;
1444}
1445
1446static int codecGetConnectionListEntry(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1447{
1448 Assert((CODEC_CAD(cmd) == pState->id));
1449 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1450 *pResp = 0;
1451 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1452 {
1453 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1454 return VINF_SUCCESS;
1455 }
1456 Assert((cmd & CODEC_VERB_8BIT_DATA) < CODECNODE_F02_PARAM_LENGTH);
1457 if ((cmd & CODEC_VERB_8BIT_DATA) >= CODECNODE_F02_PARAM_LENGTH)
1458 {
1459 Log(("HDAcodec: access to invalid F02 index %d\n", (cmd & CODEC_VERB_8BIT_DATA)));
1460 return VINF_SUCCESS;
1461 }
1462 *pResp = pState->pNodes[CODEC_NID(cmd)].node.au32F02_param[cmd & CODEC_VERB_8BIT_DATA];
1463 return VINF_SUCCESS;
1464}
1465/* F03 */
1466static int codecGetProcessingState(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1467{
1468 Assert((CODEC_CAD(cmd) == pState->id));
1469 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1470 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1471 {
1472 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1473 return VINF_SUCCESS;
1474 }
1475 *pResp = 0;
1476 if (codecIsAdcNode(pState, CODEC_NID(cmd)))
1477 *pResp = pState->pNodes[CODEC_NID(cmd)].adc.u32F03_param;
1478 return VINF_SUCCESS;
1479}
1480
1481/* 703 */
1482static int codecSetProcessingState(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1483{
1484 Assert((CODEC_CAD(cmd) == pState->id));
1485 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1486 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1487 {
1488 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1489 return VINF_SUCCESS;
1490 }
1491 *pResp = 0;
1492 if (codecIsAdcNode(pState, CODEC_NID(cmd)))
1493 {
1494 codecSetRegisterU8(&pState->pNodes[CODEC_NID(cmd)].adc.u32F03_param, cmd, 0);
1495 }
1496 return VINF_SUCCESS;
1497}
1498
1499/* F0D */
1500static int codecGetDigitalConverter(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1501{
1502 Assert((CODEC_CAD(cmd) == pState->id));
1503 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1504 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1505 {
1506 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1507 return VINF_SUCCESS;
1508 }
1509 *pResp = 0;
1510 if (codecIsSpdifOutNode(pState, CODEC_NID(cmd)))
1511 *pResp = pState->pNodes[CODEC_NID(cmd)].spdifout.u32F0d_param;
1512 else if (codecIsSpdifInNode(pState, CODEC_NID(cmd)))
1513 *pResp = pState->pNodes[CODEC_NID(cmd)].spdifin.u32F0d_param;
1514 return VINF_SUCCESS;
1515}
1516
1517static int codecSetDigitalConverter(struct CODECState *pState, uint32_t cmd, uint8_t u8Offset, uint64_t *pResp)
1518{
1519 Assert((CODEC_CAD(cmd) == pState->id));
1520 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1521 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1522 {
1523 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1524 return VINF_SUCCESS;
1525 }
1526 *pResp = 0;
1527 if (codecIsSpdifOutNode(pState, CODEC_NID(cmd)))
1528 codecSetRegisterU8(&pState->pNodes[CODEC_NID(cmd)].spdifout.u32F0d_param, cmd, u8Offset);
1529 else if (codecIsSpdifInNode(pState, CODEC_NID(cmd)))
1530 codecSetRegisterU8(&pState->pNodes[CODEC_NID(cmd)].spdifin.u32F0d_param, cmd, u8Offset);
1531 return VINF_SUCCESS;
1532}
1533
1534/* 70D */
1535static int codecSetDigitalConverter1(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1536{
1537 return codecSetDigitalConverter(pState, cmd, 0, pResp);
1538}
1539
1540/* 70E */
1541static int codecSetDigitalConverter2(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1542{
1543 return codecSetDigitalConverter(pState, cmd, 8, pResp);
1544}
1545
1546/* F20 */
1547static int codecGetSubId(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1548{
1549 Assert((CODEC_CAD(cmd) == pState->id));
1550 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1551 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1552 {
1553 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1554 return VINF_SUCCESS;
1555 }
1556 *pResp = 0;
1557 if (CODEC_NID(cmd) == 1 /* AFG */)
1558 {
1559 *pResp = pState->pNodes[CODEC_NID(cmd)].afg.u32F20_param;
1560 }
1561 return VINF_SUCCESS;
1562}
1563
1564static int codecSetSubIdX(struct CODECState *pState, uint32_t cmd, uint8_t u8Offset)
1565{
1566 Assert((CODEC_CAD(cmd) == pState->id));
1567 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1568 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1569 {
1570 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1571 return VINF_SUCCESS;
1572 }
1573 uint32_t *pu32Reg = NULL;
1574 if (CODEC_NID(cmd) == 0x1 /* AFG */)
1575 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].afg.u32F20_param;
1576 Assert((pu32Reg));
1577 if (pu32Reg)
1578 codecSetRegisterU8(pu32Reg, cmd, u8Offset);
1579 return VINF_SUCCESS;
1580}
1581/* 720 */
1582static int codecSetSubId0 (struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1583{
1584 *pResp = 0;
1585 return codecSetSubIdX(pState, cmd, 0);
1586}
1587
1588/* 721 */
1589static int codecSetSubId1 (struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1590{
1591 *pResp = 0;
1592 return codecSetSubIdX(pState, cmd, 8);
1593}
1594/* 722 */
1595static int codecSetSubId2 (struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1596{
1597 *pResp = 0;
1598 return codecSetSubIdX(pState, cmd, 16);
1599}
1600/* 723 */
1601static int codecSetSubId3 (struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1602{
1603 *pResp = 0;
1604 return codecSetSubIdX(pState, cmd, 24);
1605}
1606
1607static int codecReset(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1608{
1609 Assert((CODEC_CAD(cmd) == pState->id));
1610 Assert(CODEC_NID(cmd) == 1 /* AFG */);
1611 if(CODEC_NID(cmd) == 1 /* AFG */)
1612 {
1613 uint8_t i;
1614 Log(("HDAcodec: enters reset\n"));
1615 Assert(pState->pfnCodecNodeReset);
1616 for (i = 0; i < pState->cTotalNodes; ++i)
1617 {
1618 pState->pfnCodecNodeReset(pState, i, &pState->pNodes[i]);
1619 }
1620 pState->fInReset = false;
1621 Log(("HDAcodec: exits reset\n"));
1622 }
1623 *pResp = 0;
1624 return VINF_SUCCESS;
1625}
1626
1627/* F05 */
1628static int codecGetPowerState(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1629{
1630 Assert((CODEC_CAD(cmd) == pState->id));
1631 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1632 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1633 {
1634 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1635 return VINF_SUCCESS;
1636 }
1637 *pResp = 0;
1638 if (CODEC_NID(cmd) == 1 /* AFG */)
1639 *pResp = pState->pNodes[CODEC_NID(cmd)].afg.u32F05_param;
1640 else if (codecIsDacNode(pState, CODEC_NID(cmd)))
1641 *pResp = pState->pNodes[CODEC_NID(cmd)].dac.u32F05_param;
1642 else if (codecIsDigInPinNode(pState, CODEC_NID(cmd)))
1643 *pResp = pState->pNodes[CODEC_NID(cmd)].digin.u32F05_param;
1644 else if (codecIsAdcNode(pState, CODEC_NID(cmd)))
1645 *pResp = pState->pNodes[CODEC_NID(cmd)].adc.u32F05_param;
1646 else if (codecIsSpdifOutNode(pState, CODEC_NID(cmd)))
1647 *pResp = pState->pNodes[CODEC_NID(cmd)].spdifout.u32F05_param;
1648 else if (codecIsSpdifInNode(pState, CODEC_NID(cmd)))
1649 *pResp = pState->pNodes[CODEC_NID(cmd)].spdifin.u32F05_param;
1650 else if (codecIsReservedNode(pState, CODEC_NID(cmd)))
1651 *pResp = pState->pNodes[CODEC_NID(cmd)].reserved.u32F05_param;
1652 return VINF_SUCCESS;
1653}
1654
1655/* 705 */
1656
1657static inline void codecPropogatePowerState(uint32_t *pu32F05_param)
1658{
1659 Assert(pu32F05_param);
1660 if (!pu32F05_param)
1661 return;
1662 bool fReset = CODEC_F05_IS_RESET(*pu32F05_param);
1663 bool fStopOk = CODEC_F05_IS_STOPOK(*pu32F05_param);
1664 uint8_t u8SetPowerState = CODEC_F05_SET(*pu32F05_param);
1665 *pu32F05_param = CODEC_MAKE_F05(fReset, fStopOk, 0, u8SetPowerState, u8SetPowerState);
1666}
1667
1668static int codecSetPowerState(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1669{
1670 Assert((CODEC_CAD(cmd) == pState->id));
1671 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1672 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1673 {
1674 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1675 return VINF_SUCCESS;
1676 }
1677 uint32_t *pu32Reg = NULL;
1678 *pResp = 0;
1679 if (CODEC_NID(cmd) == 1 /* AFG */)
1680 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].afg.u32F05_param;
1681 else if (codecIsDacNode(pState, CODEC_NID(cmd)))
1682 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].dac.u32F05_param;
1683 else if (codecIsDigInPinNode(pState, CODEC_NID(cmd)))
1684 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].digin.u32F05_param;
1685 else if (codecIsAdcNode(pState, CODEC_NID(cmd)))
1686 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].adc.u32F05_param;
1687 else if (codecIsSpdifOutNode(pState, CODEC_NID(cmd)))
1688 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].spdifout.u32F05_param;
1689 else if (codecIsSpdifInNode(pState, CODEC_NID(cmd)))
1690 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].spdifin.u32F05_param;
1691 else if (codecIsReservedNode(pState, CODEC_NID(cmd)))
1692 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].reserved.u32F05_param;
1693 Assert((pu32Reg));
1694 if (!pu32Reg)
1695 return VINF_SUCCESS;
1696
1697 bool fReset = CODEC_F05_IS_RESET(*pu32Reg);
1698 bool fStopOk = CODEC_F05_IS_STOPOK(*pu32Reg);
1699
1700 if (CODEC_NID(cmd) != 1 /* AFG */)
1701 {
1702 /*
1703 * We shouldn't propogate actual power state, which actual for AFG
1704 */
1705 *pu32Reg = CODEC_MAKE_F05(fReset, fStopOk, 0,
1706 CODEC_F05_ACT(pState->pNodes[1].afg.u32F05_param),
1707 CODEC_F05_SET(cmd));
1708 }
1709
1710 /* Propagate next power state only if AFG is on or verb modifies AFG power state */
1711 if ( CODEC_NID(cmd) == 1 /* AFG */
1712 || !CODEC_F05_ACT(pState->pNodes[1].afg.u32F05_param))
1713 {
1714 *pu32Reg = CODEC_MAKE_F05(fReset, fStopOk, 0, CODEC_F05_SET(cmd), CODEC_F05_SET(cmd));
1715 if ( CODEC_NID(cmd) == 1 /* AFG */
1716 && (CODEC_F05_SET(cmd)) == CODEC_F05_D0)
1717 {
1718 /* now we're powered on AFG and may propogate power states on nodes */
1719 const uint8_t *pu8NodeIndex = &pState->au8Dacs[0];
1720 while (*(++pu8NodeIndex))
1721 codecPropogatePowerState(&pState->pNodes[*pu8NodeIndex].dac.u32F05_param);
1722
1723 pu8NodeIndex = &pState->au8Adcs[0];
1724 while (*(++pu8NodeIndex))
1725 codecPropogatePowerState(&pState->pNodes[*pu8NodeIndex].adc.u32F05_param);
1726
1727 pu8NodeIndex = &pState->au8DigInPins[0];
1728 while (*(++pu8NodeIndex))
1729 codecPropogatePowerState(&pState->pNodes[*pu8NodeIndex].digin.u32F05_param);
1730 }
1731 }
1732 return VINF_SUCCESS;
1733}
1734
1735static int codecGetStreamId(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1736{
1737 Assert((CODEC_CAD(cmd) == pState->id));
1738 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1739 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1740 {
1741 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1742 return VINF_SUCCESS;
1743 }
1744 *pResp = 0;
1745 if (codecIsDacNode(pState, CODEC_NID(cmd)))
1746 *pResp = pState->pNodes[CODEC_NID(cmd)].dac.u32F06_param;
1747 else if (codecIsAdcNode(pState, CODEC_NID(cmd)))
1748 *pResp = pState->pNodes[CODEC_NID(cmd)].adc.u32F06_param;
1749 else if (codecIsSpdifInNode(pState, CODEC_NID(cmd)))
1750 *pResp = pState->pNodes[CODEC_NID(cmd)].spdifin.u32F06_param;
1751 else if (codecIsSpdifOutNode(pState, CODEC_NID(cmd)))
1752 *pResp = pState->pNodes[CODEC_NID(cmd)].spdifout.u32F06_param;
1753 else if (CODEC_NID(cmd) == 0x1A)
1754 *pResp = pState->pNodes[CODEC_NID(cmd)].reserved.u32F06_param;
1755 return VINF_SUCCESS;
1756}
1757static int codecSetStreamId(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1758{
1759 Assert((CODEC_CAD(cmd) == pState->id));
1760 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1761 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1762 {
1763 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1764 return VINF_SUCCESS;
1765 }
1766 *pResp = 0;
1767 uint32_t *pu32addr = NULL;
1768 *pResp = 0;
1769 if (codecIsDacNode(pState, CODEC_NID(cmd)))
1770 pu32addr = &pState->pNodes[CODEC_NID(cmd)].dac.u32F06_param;
1771 else if (codecIsAdcNode(pState, CODEC_NID(cmd)))
1772 pu32addr = &pState->pNodes[CODEC_NID(cmd)].adc.u32F06_param;
1773 else if (codecIsSpdifOutNode(pState, CODEC_NID(cmd)))
1774 pu32addr = &pState->pNodes[CODEC_NID(cmd)].spdifout.u32F06_param;
1775 else if (codecIsSpdifInNode(pState, CODEC_NID(cmd)))
1776 pu32addr = &pState->pNodes[CODEC_NID(cmd)].spdifin.u32F06_param;
1777 else if (codecIsReservedNode(pState, CODEC_NID(cmd)))
1778 pu32addr = &pState->pNodes[CODEC_NID(cmd)].reserved.u32F06_param;
1779 Assert((pu32addr));
1780 if (pu32addr)
1781 codecSetRegisterU8(pu32addr, cmd, 0);
1782 return VINF_SUCCESS;
1783}
1784
1785static int codecGetConverterFormat(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1786{
1787 Assert((CODEC_CAD(cmd) == pState->id));
1788 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1789 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1790 {
1791 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1792 return VINF_SUCCESS;
1793 }
1794 *pResp = 0;
1795 if (codecIsDacNode(pState, CODEC_NID(cmd)))
1796 *pResp = pState->pNodes[CODEC_NID(cmd)].dac.u32A_param;
1797 else if (codecIsAdcNode(pState, CODEC_NID(cmd)))
1798 *pResp = pState->pNodes[CODEC_NID(cmd)].adc.u32A_param;
1799 else if (codecIsSpdifOutNode(pState, CODEC_NID(cmd)))
1800 *pResp = pState->pNodes[CODEC_NID(cmd)].spdifout.u32A_param;
1801 else if (codecIsSpdifInNode(pState, CODEC_NID(cmd)))
1802 *pResp = pState->pNodes[CODEC_NID(cmd)].spdifin.u32A_param;
1803 return VINF_SUCCESS;
1804}
1805
1806static int codecSetConverterFormat(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1807{
1808 Assert((CODEC_CAD(cmd) == pState->id));
1809 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1810 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1811 {
1812 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1813 return VINF_SUCCESS;
1814 }
1815 *pResp = 0;
1816 if (codecIsDacNode(pState, CODEC_NID(cmd)))
1817 codecSetRegisterU16(&pState->pNodes[CODEC_NID(cmd)].dac.u32A_param, cmd, 0);
1818 else if (codecIsAdcNode(pState, CODEC_NID(cmd)))
1819 codecSetRegisterU16(&pState->pNodes[CODEC_NID(cmd)].adc.u32A_param, cmd, 0);
1820 else if (codecIsSpdifOutNode(pState, CODEC_NID(cmd)))
1821 codecSetRegisterU16(&pState->pNodes[CODEC_NID(cmd)].spdifout.u32A_param, cmd, 0);
1822 else if (codecIsSpdifInNode(pState, CODEC_NID(cmd)))
1823 codecSetRegisterU16(&pState->pNodes[CODEC_NID(cmd)].spdifin.u32A_param, cmd, 0);
1824 return VINF_SUCCESS;
1825}
1826
1827/* F0C */
1828static int codecGetEAPD_BTLEnabled(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1829{
1830 Assert((CODEC_CAD(cmd) == pState->id));
1831 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1832 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1833 {
1834 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1835 return VINF_SUCCESS;
1836 }
1837 *pResp = 0;
1838 if (codecIsAdcVolNode(pState, CODEC_NID(cmd)))
1839 *pResp = pState->pNodes[CODEC_NID(cmd)].adcvol.u32F0c_param;
1840 else if (codecIsDacNode(pState, CODEC_NID(cmd)))
1841 *pResp = pState->pNodes[CODEC_NID(cmd)].dac.u32F0c_param;
1842 else if (codecIsDigInPinNode(pState, CODEC_NID(cmd)))
1843 *pResp = pState->pNodes[CODEC_NID(cmd)].digin.u32F0c_param;
1844 return VINF_SUCCESS;
1845}
1846
1847/* 70C */
1848static int codecSetEAPD_BTLEnabled(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1849{
1850 Assert((CODEC_CAD(cmd) == pState->id));
1851 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1852 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1853 {
1854 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1855 return VINF_SUCCESS;
1856 }
1857 *pResp = 0;
1858 uint32_t *pu32Reg = NULL;
1859 if (codecIsAdcVolNode(pState, CODEC_NID(cmd)))
1860 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].adcvol.u32F0c_param;
1861 else if (codecIsDacNode(pState, CODEC_NID(cmd)))
1862 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].dac.u32F0c_param;
1863 else if (codecIsDigInPinNode(pState, CODEC_NID(cmd)))
1864 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].digin.u32F0c_param;
1865 *pResp = 0;
1866 Assert((pu32Reg));
1867 if (pu32Reg)
1868 codecSetRegisterU8(pu32Reg, cmd, 0);
1869 return VINF_SUCCESS;
1870}
1871
1872/* F0F */
1873static int codecGetVolumeKnobCtrl(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1874{
1875 Assert((CODEC_CAD(cmd) == pState->id));
1876 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1877 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1878 {
1879 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1880 return VINF_SUCCESS;
1881 }
1882 *pResp = 0;
1883 if (codecIsVolKnobNode(pState, CODEC_NID(cmd)))
1884 *pResp = pState->pNodes[CODEC_NID(cmd)].volumeKnob.u32F0f_param;
1885 return VINF_SUCCESS;
1886}
1887
1888/* 70F */
1889static int codecSetVolumeKnobCtrl(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1890{
1891 Assert((CODEC_CAD(cmd) == pState->id));
1892 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1893 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1894 {
1895 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1896 return VINF_SUCCESS;
1897 }
1898 uint32_t *pu32Reg = NULL;
1899 *pResp = 0;
1900 if (codecIsVolKnobNode(pState, CODEC_NID(cmd)))
1901 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].volumeKnob.u32F0f_param;
1902 Assert((pu32Reg));
1903 if (pu32Reg)
1904 codecSetRegisterU8(pu32Reg, cmd, 0);
1905 return VINF_SUCCESS;
1906}
1907
1908/* F17 */
1909static int codecGetGPIOUnsolisted (struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1910{
1911 Assert((CODEC_CAD(cmd) == pState->id));
1912 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1913 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1914 {
1915 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1916 return VINF_SUCCESS;
1917 }
1918 *pResp = 0;
1919 /* note: this is true for ALC885 */
1920 if (CODEC_NID(cmd) == 0x1 /* AFG */)
1921 *pResp = pState->pNodes[1].afg.u32F17_param;
1922 return VINF_SUCCESS;
1923}
1924
1925/* 717 */
1926static int codecSetGPIOUnsolisted (struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1927{
1928 Assert((CODEC_CAD(cmd) == pState->id));
1929 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1930 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1931 {
1932 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1933 return VINF_SUCCESS;
1934 }
1935 uint32_t *pu32Reg = NULL;
1936 *pResp = 0;
1937 if (CODEC_NID(cmd) == 1 /* AFG */)
1938 pu32Reg = &pState->pNodes[1].afg.u32F17_param;
1939 Assert((pu32Reg));
1940 if (pu32Reg)
1941 codecSetRegisterU8(pu32Reg, cmd, 0);
1942 return VINF_SUCCESS;
1943}
1944
1945/* F1C */
1946static int codecGetConfig (struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1947{
1948 Assert((CODEC_CAD(cmd) == pState->id));
1949 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1950 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1951 {
1952 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1953 return VINF_SUCCESS;
1954 }
1955 *pResp = 0;
1956 if (codecIsPortNode(pState, CODEC_NID(cmd)))
1957 *pResp = pState->pNodes[CODEC_NID(cmd)].port.u32F1c_param;
1958 else if (codecIsDigOutPinNode(pState, CODEC_NID(cmd)))
1959 *pResp = pState->pNodes[CODEC_NID(cmd)].digout.u32F1c_param;
1960 else if (codecIsDigInPinNode(pState, CODEC_NID(cmd)))
1961 *pResp = pState->pNodes[CODEC_NID(cmd)].digin.u32F1c_param;
1962 else if (codecIsPcbeepNode(pState, CODEC_NID(cmd)))
1963 *pResp = pState->pNodes[CODEC_NID(cmd)].pcbeep.u32F1c_param;
1964 else if (codecIsCdNode(pState, CODEC_NID(cmd)))
1965 *pResp = pState->pNodes[CODEC_NID(cmd)].cdnode.u32F1c_param;
1966 else if (codecIsReservedNode(pState, CODEC_NID(cmd)))
1967 *pResp = pState->pNodes[CODEC_NID(cmd)].reserved.u32F1c_param;
1968 return VINF_SUCCESS;
1969}
1970static int codecSetConfigX(struct CODECState *pState, uint32_t cmd, uint8_t u8Offset)
1971{
1972 Assert((CODEC_CAD(cmd) == pState->id));
1973 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1974 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1975 {
1976 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1977 return VINF_SUCCESS;
1978 }
1979 uint32_t *pu32Reg = NULL;
1980 if (codecIsPortNode(pState, CODEC_NID(cmd)))
1981 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].port.u32F1c_param;
1982 else if (codecIsDigInPinNode(pState, CODEC_NID(cmd)))
1983 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].digin.u32F1c_param;
1984 else if (codecIsDigOutPinNode(pState, CODEC_NID(cmd)))
1985 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].digout.u32F1c_param;
1986 else if (codecIsCdNode(pState, CODEC_NID(cmd)))
1987 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].cdnode.u32F1c_param;
1988 else if (codecIsPcbeepNode(pState, CODEC_NID(cmd)))
1989 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].pcbeep.u32F1c_param;
1990 else if (codecIsReservedNode(pState, CODEC_NID(cmd)))
1991 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].reserved.u32F1c_param;
1992 Assert((pu32Reg));
1993 if (pu32Reg)
1994 codecSetRegisterU8(pu32Reg, cmd, u8Offset);
1995 return VINF_SUCCESS;
1996}
1997/* 71C */
1998static int codecSetConfig0 (struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1999{
2000 *pResp = 0;
2001 return codecSetConfigX(pState, cmd, 0);
2002}
2003/* 71D */
2004static int codecSetConfig1 (struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
2005{
2006 *pResp = 0;
2007 return codecSetConfigX(pState, cmd, 8);
2008}
2009/* 71E */
2010static int codecSetConfig2 (struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
2011{
2012 *pResp = 0;
2013 return codecSetConfigX(pState, cmd, 16);
2014}
2015/* 71E */
2016static int codecSetConfig3 (struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
2017{
2018 *pResp = 0;
2019 return codecSetConfigX(pState, cmd, 24);
2020}
2021
2022
2023static int codecToAudVolume(AMPLIFIER *pAmp, audmixerctl_t mt)
2024{
2025 uint32_t dir = AMPLIFIER_OUT;
2026 switch (mt)
2027 {
2028 case AUD_MIXER_VOLUME:
2029 case AUD_MIXER_PCM:
2030 dir = AMPLIFIER_OUT;
2031 break;
2032 case AUD_MIXER_LINE_IN:
2033 dir = AMPLIFIER_IN;
2034 break;
2035 }
2036 int mute = AMPLIFIER_REGISTER(*pAmp, dir, AMPLIFIER_LEFT, 0) & RT_BIT(7);
2037 mute |= AMPLIFIER_REGISTER(*pAmp, dir, AMPLIFIER_RIGHT, 0) & RT_BIT(7);
2038 mute >>=7;
2039 mute &= 0x1;
2040 uint8_t lVol = AMPLIFIER_REGISTER(*pAmp, dir, AMPLIFIER_LEFT, 0) & 0x7f;
2041 uint8_t rVol = AMPLIFIER_REGISTER(*pAmp, dir, AMPLIFIER_RIGHT, 0) & 0x7f;
2042 AUD_set_volume(mt, &mute, &lVol, &rVol);
2043 return VINF_SUCCESS;
2044}
2045
2046static CODECVERB CODECVERBS[] =
2047{
2048/* verb | verb mask | callback */
2049/* ----------- -------------------- ----------------------- */
2050 {0x000F0000, CODEC_VERB_8BIT_CMD , codecGetParameter },
2051 {0x000F0100, CODEC_VERB_8BIT_CMD , codecGetConSelectCtrl },
2052 {0x00070100, CODEC_VERB_8BIT_CMD , codecSetConSelectCtrl },
2053 {0x000F0600, CODEC_VERB_8BIT_CMD , codecGetStreamId },
2054 {0x00070600, CODEC_VERB_8BIT_CMD , codecSetStreamId },
2055 {0x000F0700, CODEC_VERB_8BIT_CMD , codecGetPinCtrl },
2056 {0x00070700, CODEC_VERB_8BIT_CMD , codecSetPinCtrl },
2057 {0x000F0800, CODEC_VERB_8BIT_CMD , codecGetUnsolicitedEnabled },
2058 {0x00070800, CODEC_VERB_8BIT_CMD , codecSetUnsolicitedEnabled },
2059 {0x000F0900, CODEC_VERB_8BIT_CMD , codecGetPinSense },
2060 {0x00070900, CODEC_VERB_8BIT_CMD , codecSetPinSense },
2061 {0x000F0200, CODEC_VERB_8BIT_CMD , codecGetConnectionListEntry },
2062 {0x000F0300, CODEC_VERB_8BIT_CMD , codecGetProcessingState },
2063 {0x00070300, CODEC_VERB_8BIT_CMD , codecSetProcessingState },
2064 {0x000F0D00, CODEC_VERB_8BIT_CMD , codecGetDigitalConverter },
2065 {0x00070D00, CODEC_VERB_8BIT_CMD , codecSetDigitalConverter1 },
2066 {0x00070E00, CODEC_VERB_8BIT_CMD , codecSetDigitalConverter2 },
2067 {0x000F2000, CODEC_VERB_8BIT_CMD , codecGetSubId },
2068 {0x00072000, CODEC_VERB_8BIT_CMD , codecSetSubId0 },
2069 {0x00072100, CODEC_VERB_8BIT_CMD , codecSetSubId1 },
2070 {0x00072200, CODEC_VERB_8BIT_CMD , codecSetSubId2 },
2071 {0x00072300, CODEC_VERB_8BIT_CMD , codecSetSubId3 },
2072 {0x0007FF00, CODEC_VERB_8BIT_CMD , codecReset },
2073 {0x000F0500, CODEC_VERB_8BIT_CMD , codecGetPowerState },
2074 {0x00070500, CODEC_VERB_8BIT_CMD , codecSetPowerState },
2075 {0x000F0C00, CODEC_VERB_8BIT_CMD , codecGetEAPD_BTLEnabled },
2076 {0x00070C00, CODEC_VERB_8BIT_CMD , codecSetEAPD_BTLEnabled },
2077 {0x000F0F00, CODEC_VERB_8BIT_CMD , codecGetVolumeKnobCtrl },
2078 {0x00070F00, CODEC_VERB_8BIT_CMD , codecSetVolumeKnobCtrl },
2079 {0x000F1700, CODEC_VERB_8BIT_CMD , codecGetGPIOUnsolisted },
2080 {0x00071700, CODEC_VERB_8BIT_CMD , codecSetGPIOUnsolisted },
2081 {0x000F1C00, CODEC_VERB_8BIT_CMD , codecGetConfig },
2082 {0x00071C00, CODEC_VERB_8BIT_CMD , codecSetConfig0 },
2083 {0x00071D00, CODEC_VERB_8BIT_CMD , codecSetConfig1 },
2084 {0x00071E00, CODEC_VERB_8BIT_CMD , codecSetConfig2 },
2085 {0x00071F00, CODEC_VERB_8BIT_CMD , codecSetConfig3 },
2086 {0x000A0000, CODEC_VERB_16BIT_CMD, codecGetConverterFormat },
2087 {0x00020000, CODEC_VERB_16BIT_CMD, codecSetConverterFormat },
2088 {0x000B0000, CODEC_VERB_16BIT_CMD, codecGetAmplifier },
2089 {0x00030000, CODEC_VERB_16BIT_CMD, codecSetAmplifier },
2090};
2091
2092static int codecLookup(CODECState *pState, uint32_t cmd, PPFNCODECVERBPROCESSOR pfn)
2093{
2094 int rc = VINF_SUCCESS;
2095 Assert(CODEC_CAD(cmd) == pState->id);
2096 if (codecIsReservedNode(pState, CODEC_NID(cmd)))
2097 {
2098 Log(("HDAcodec: cmd %x was addressed to reserved node\n", cmd));
2099 }
2100 if ( CODEC_VERBDATA(cmd) == 0
2101 || CODEC_NID(cmd) >= pState->cTotalNodes)
2102 {
2103 *pfn = codecUnimplemented;
2104 //** @todo r=michaln: There needs to be a counter to avoid log flooding (see e.g. DevRTC.cpp)
2105 Log(("HDAcodec: cmd %x was ignored\n", cmd));
2106 return VINF_SUCCESS;
2107 }
2108 for (int i = 0; i < pState->cVerbs; ++i)
2109 {
2110 if ((CODEC_VERBDATA(cmd) & pState->pVerbs[i].mask) == pState->pVerbs[i].verb)
2111 {
2112 *pfn = pState->pVerbs[i].pfn;
2113 return VINF_SUCCESS;
2114 }
2115 }
2116 *pfn = codecUnimplemented;
2117 Log(("HDAcodec: callback for %x wasn't found\n", CODEC_VERBDATA(cmd)));
2118 return rc;
2119}
2120
2121static void pi_callback (void *opaque, int avail)
2122{
2123 CODECState *pState = (CODECState *)opaque;
2124 pState->pfnTransfer(pState, PI_INDEX, avail);
2125}
2126
2127static void po_callback (void *opaque, int avail)
2128{
2129 CODECState *pState = (CODECState *)opaque;
2130 pState->pfnTransfer(pState, PO_INDEX, avail);
2131}
2132
2133static void mc_callback (void *opaque, int avail)
2134{
2135 CODECState *pState = (CODECState *)opaque;
2136 pState->pfnTransfer(pState, MC_INDEX, avail);
2137}
2138
2139int codecConstruct(PPDMDEVINS pDevIns, CODECState *pState, ENMCODEC enmCodec)
2140{
2141 audsettings_t as;
2142 int rc;
2143 pState->pVerbs = (CODECVERB *)&CODECVERBS;
2144 pState->cVerbs = sizeof(CODECVERBS)/sizeof(CODECVERB);
2145 pState->pfnLookup = codecLookup;
2146 pState->enmCodec = enmCodec;
2147 switch (enmCodec)
2148 {
2149 case STAC9220_CODEC:
2150 rc = stac9220Construct(pState);
2151 AssertRC(rc);
2152 break;
2153 case ALC885_CODEC:
2154 rc = alc885Construct(pState);
2155 AssertRC(rc);
2156 break;
2157 default:
2158 AssertMsgFailed(("Unsupported Codec"));
2159 }
2160 /* common root node initializers */
2161 pState->pNodes[0].node.au32F00_param[0] = CODEC_MAKE_F00_00(pState->u16VendorId, pState->u16DeviceId);
2162 pState->pNodes[0].node.au32F00_param[4] = CODEC_MAKE_F00_04(0x1, 0x1);
2163 /* common AFG node initializers */
2164 pState->pNodes[1].node.au32F00_param[4] = CODEC_MAKE_F00_04(0x2, pState->cTotalNodes - 2);
2165 pState->pNodes[1].node.au32F00_param[5] = CODEC_MAKE_F00_05(CODEC_F00_05_UNSOL, CODEC_F00_05_AFG);
2166 pState->pNodes[1].afg.u32F20_param = CODEC_MAKE_F20(pState->u16VendorId, pState->u8BSKU, pState->u8AssemblyId);
2167
2168 //** @todo r=michaln: Was this meant to be 'HDA' or something like that? (AC'97 was on ICH0)
2169 AUD_register_card ("ICH0", &pState->card);
2170
2171 /* 44.1 kHz */
2172 as.freq = 44100;
2173 as.nchannels = 2;
2174 as.fmt = AUD_FMT_S16;
2175 as.endianness = 0;
2176 #define SETUP_AUDIO_FORMAT(pState, base, mult, div, name, as, in_callback, out_callback) \
2177 do{ \
2178 AUDIO_FORMAT_SELECTOR((pState), Out, (base), (mult), div) = AUD_open_out(&(pState)->card, \
2179 AUDIO_FORMAT_SELECTOR(pState, Out, (base), (mult), (div)), name ".out", (pState), (out_callback), &(as)); \
2180 if (!AUDIO_FORMAT_SELECTOR(pState, Out, (base), (mult), (div))) \
2181 LogRel (("HDAcodec: WARNING: Unable to open PCM OUT(%s)!\n", name ".out")); \
2182 AUDIO_FORMAT_SELECTOR(pState, In, (base), (mult), (div)) = AUD_open_in(&(pState)->card, \
2183 AUDIO_FORMAT_SELECTOR(pState, In, (base), (mult), (div)), name ".in", (pState), (in_callback), &(as)); \
2184 if (!AUDIO_FORMAT_SELECTOR(pState, In, (base), (mult), (div))) \
2185 LogRel (("HDAcodec: WARNING: Unable to open PCM IN(%s)!\n", name ".in")); \
2186 } while(0)
2187 #define IS_FORMAT_SUPPORTED_BY_HOST(pState, base, mult, div) (AUDIO_FORMAT_SELECTOR((pState), Out, (base), (mult), (div)) \
2188 && AUDIO_FORMAT_SELECTOR((pState), In, (base), (mult), (div)))
2189
2190 pState->pNodes[1].node.au32F00_param[0xA] = CODEC_F00_0A_16_BIT;
2191 SETUP_AUDIO_FORMAT(pState, AFMT_HZ_44_1K, AFMT_MULT_X1, AFMT_DIV_X1, "hda44_1", as, pi_callback, po_callback);
2192 pState->pNodes[1].node.au32F00_param[0xA] |= IS_FORMAT_SUPPORTED_BY_HOST(pState, AFMT_HZ_44_1K, AFMT_MULT_X1, AFMT_DIV_X1) ? CODEC_F00_0A_44_1KHZ : 0;
2193
2194#ifdef VBOX_WITH_AUDIO_FLEXIBLE_FORMAT
2195 as.freq *= 2; /* 2 * 44.1kHz */
2196 SETUP_AUDIO_FORMAT(pState, AFMT_HZ_44_1K, AFMT_MULT_X2, AFMT_DIV_X1, "hda44_1_2x", as, pi_callback, po_callback);
2197 pState->pNodes[1].node.au32F00_param[0xA] |= IS_FORMAT_SUPPORTED_BY_HOST(pState, AFMT_HZ_44_1K, AFMT_MULT_X2, AFMT_DIV_X1) ? CODEC_F00_0A_44_1KHZ_MULT_2X : 0;
2198
2199 as.freq *= 2; /* 4 * 44.1kHz */
2200 SETUP_AUDIO_FORMAT(pState, AFMT_HZ_44_1K, AFMT_MULT_X4, AFMT_DIV_X1, "hda44_1_4x", as, pi_callback, po_callback);
2201 pState->pNodes[1].node.au32F00_param[0xA] |= IS_FORMAT_SUPPORTED_BY_HOST(pState, AFMT_HZ_44_1K, AFMT_MULT_X4, AFMT_DIV_X1) ? CODEC_F00_0A_44_1KHZ_MULT_4X : 0;
2202
2203 as.freq = 48000;
2204 SETUP_AUDIO_FORMAT(pState, AFMT_HZ_48K, AFMT_MULT_X1, AFMT_DIV_X1, "hda48", as, pi_callback, po_callback);
2205 pState->pNodes[1].node.au32F00_param[0xA] |= IS_FORMAT_SUPPORTED_BY_HOST(pState, AFMT_HZ_48K, AFMT_MULT_X1, AFMT_DIV_X1) ? CODEC_F00_0A_48KHZ : 0;
2206
2207# if 0
2208 as.freq *= 2; /* 2 * 48kHz */
2209 SETUP_AUDIO_FORMAT(pState, AFMT_HZ_48K, AFMT_MULT_X2, AFMT_DIV_X1, "hda48_2x", as, pi_callback, po_callback);
2210 pState->pNodes[1].node.au32F00_param[0xA] |= IS_FORMAT_SUPPORTED_BY_HOST(pState, AFMT_HZ_48K, AFMT_MULT_X2, AFMT_DIV_X1) ? CODEC_F00_0A_48KHZ_MULT_2X : 0;
2211
2212 as.freq *= 2; /* 4 * 48kHz */
2213 SETUP_AUDIO_FORMAT(pState, AFMT_HZ_48K, AFMT_MULT_X4, AFMT_DIV_X1, "hda48_4x", as, pi_callback, po_callback);
2214 pState->pNodes[1].node.au32F00_param[0xA] |= IS_FORMAT_SUPPORTED_BY_HOST(pState, AFMT_HZ_48K, AFMT_MULT_X4, AFMT_DIV_X1) ? CODEC_F00_0A_48KHZ_MULT_4X : 0;
2215# endif
2216#endif
2217 #undef SETUP_AUDIO_FORMAT
2218 #undef IS_FORMAT_SUPPORTED_BY_HOST
2219
2220 uint8_t i;
2221 Assert(pState->pNodes);
2222 Assert(pState->pfnCodecNodeReset);
2223 for (i = 0; i < pState->cTotalNodes; ++i)
2224 {
2225 pState->pfnCodecNodeReset(pState, i, &pState->pNodes[i]);
2226 }
2227
2228 codecToAudVolume(&pState->pNodes[pState->u8DacLineOut].dac.B_params, AUD_MIXER_VOLUME);
2229 codecToAudVolume(&pState->pNodes[pState->u8AdcVolsLineIn].adcvol.B_params, AUD_MIXER_LINE_IN);
2230
2231#ifdef VBOX_WITH_AUDIO_FLEXIBLE_FORMAT
2232 /* @todo If no host voices were created, then fallback to nul audio. */
2233#else
2234 /* If no host voices were created, then fallback to nul audio. */
2235 if (!AUD_is_host_voice_in_ok(pState->SwVoiceIn))
2236 LogRel (("HDA: WARNING: Unable to open PCM IN!\n"));
2237 if (!AUD_is_host_voice_in_ok(pState->voice_mc))
2238 LogRel (("HDA: WARNING: Unable to open PCM MC!\n"));
2239 if (!AUD_is_host_voice_out_ok(pState->SwVoiceOut))
2240 LogRel (("HDA: WARNING: Unable to open PCM OUT!\n"));
2241
2242 if ( !AUD_is_host_voice_in_ok(pState->SwVoiceIn)
2243 && !AUD_is_host_voice_out_ok(pState->SwVoiceOut)
2244 && !AUD_is_host_voice_in_ok(pState->voice_mc))
2245 {
2246 /* Was not able initialize *any* voice. Select the NULL audio driver instead */
2247 AUD_close_in (&pState->card, pState->SwVoiceIn);
2248 AUD_close_out (&pState->card, pState->SwVoiceOut);
2249 AUD_close_in (&pState->card, pState->voice_mc);
2250 pState->SwVoiceOut = NULL;
2251 pState->SwVoiceIn = NULL;
2252 pState->voice_mc = NULL;
2253 AUD_init_null ();
2254
2255 PDMDevHlpVMSetRuntimeError (pDevIns, 0 /*fFlags*/, "HostAudioNotResponding",
2256 N_ ("No audio devices could be opened. Selecting the NULL audio backend "
2257 "with the consequence that no sound is audible"));
2258 }
2259 else if ( !AUD_is_host_voice_in_ok(pState->SwVoiceIn)
2260 || !AUD_is_host_voice_out_ok(pState->SwVoiceOut)
2261 || !AUD_is_host_voice_in_ok(pState->voice_mc))
2262 {
2263 char szMissingVoices[128];
2264 size_t len = 0;
2265 if (!AUD_is_host_voice_in_ok(pState->SwVoiceIn))
2266 len = RTStrPrintf (szMissingVoices, sizeof(szMissingVoices), "PCM_in");
2267 if (!AUD_is_host_voice_out_ok(pState->SwVoiceOut))
2268 len += RTStrPrintf (szMissingVoices + len, sizeof(szMissingVoices) - len, len ? ", PCM_out" : "PCM_out");
2269 if (!AUD_is_host_voice_in_ok(pState->voice_mc))
2270 len += RTStrPrintf (szMissingVoices + len, sizeof(szMissingVoices) - len, len ? ", PCM_mic" : "PCM_mic");
2271
2272 PDMDevHlpVMSetRuntimeError (pDevIns, 0 /*fFlags*/, "HostAudioNotResponding",
2273 N_ ("Some audio devices (%s) could not be opened. Guest applications generating audio "
2274 "output or depending on audio input may hang. Make sure your host audio device "
2275 "is working properly. Check the logfile for error messages of the audio "
2276 "subsystem"), szMissingVoices);
2277 }
2278#endif /* VBOX_WITH_AUDIO_FLEXIBLE_FORMAT */
2279
2280 return VINF_SUCCESS;
2281}
2282int codecDestruct(CODECState *pCodecState)
2283{
2284 RTMemFree(pCodecState->pNodes);
2285 return VINF_SUCCESS;
2286}
2287
2288int codecSaveState(CODECState *pCodecState, PSSMHANDLE pSSMHandle)
2289{
2290 SSMR3PutMem (pSSMHandle, pCodecState->pNodes, sizeof(CODECNODE) * pCodecState->cTotalNodes);
2291 return VINF_SUCCESS;
2292}
2293
2294int codecLoadState(CODECState *pCodecState, PSSMHANDLE pSSMHandle)
2295{
2296 SSMR3GetMem (pSSMHandle, pCodecState->pNodes, sizeof(CODECNODE) * pCodecState->cTotalNodes);
2297 if (codecIsDacNode(pCodecState, pCodecState->u8DacLineOut))
2298 codecToAudVolume(&pCodecState->pNodes[pCodecState->u8DacLineOut].dac.B_params, AUD_MIXER_VOLUME);
2299 else if (codecIsSpdifOutNode(pCodecState, pCodecState->u8DacLineOut))
2300 codecToAudVolume(&pCodecState->pNodes[pCodecState->u8DacLineOut].spdifout.B_params, AUD_MIXER_VOLUME);
2301 codecToAudVolume(&pCodecState->pNodes[pCodecState->u8AdcVolsLineIn].adcvol.B_params, AUD_MIXER_LINE_IN);
2302 return VINF_SUCCESS;
2303}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette