VirtualBox

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

Last change on this file since 37636 was 37482, checked in by vboxsync, 13 years ago

Audio/HDA: SSMR3{Get,Put}Struct in HDA device implementation.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 79.0 KB
Line 
1/* $Id: DevCodec.cpp 37482 2011-06-16 04:09:27Z 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
34
35typedef struct CODECCOMMONNODE
36{
37 uint8_t id; /* 7 - bit format */
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->node.au32F00_param[2] = CODEC_MAKE_F00_02(0x1, 0x0, 0x34, 0x1); /* rev id */
277 break;
278 case 1:
279 pNode->node.au32F00_param[8] = CODEC_MAKE_F00_08(1, 0xd, 0xd);
280 pNode->node.au32F00_param[0xC] = CODEC_MAKE_F00_0C(0x17)
281 | CODEC_F00_0C_CAP_BALANCED_IO
282 | CODEC_F00_0C_CAP_INPUT
283 | CODEC_F00_0C_CAP_PRESENSE_DETECT
284 | CODEC_F00_0C_CAP_TRIGGER_REQUIRED
285 | CODEC_F00_0C_CAP_IMPENDANCE_SENSE;//(17 << 8)|RT_BIT(6)|RT_BIT(5)|RT_BIT(2)|RT_BIT(1)|RT_BIT(0);
286 pNode->node.au32F00_param[0xB] = CODEC_F00_0B_PCM;
287 pNode->node.au32F00_param[0xD] = CODEC_MAKE_F00_0D(1, 0x5, 0xE, 0);//RT_BIT(31)|(0x5 << 16)|(0xE)<<8;
288 pNode->node.au32F00_param[0x12] = RT_BIT(31)|(0x2 << 16)|(0x7f << 8)|0x7f;
289 pNode->node.au32F00_param[0x11] = CODEC_MAKE_F00_11(1, 1, 0, 0, 4);//0xc0000004;
290 pNode->node.au32F00_param[0xF] = CODEC_F00_0F_D3|CODEC_F00_0F_D2|CODEC_F00_0F_D1|CODEC_F00_0F_D0;
291 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 */
292 pNode->afg.u32F08_param = 0;
293 pNode->afg.u32F17_param = 0;
294 break;
295 case 2:
296 case 3:
297 case 4:
298 case 5:
299 memset(pNode->dac.B_params, 0, AMPLIFIER_SIZE);
300 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 */
301
302 AMPLIFIER_REGISTER(pNode->dac.B_params, AMPLIFIER_OUT, AMPLIFIER_LEFT, 0) = 0x7F | RT_BIT(7);
303 AMPLIFIER_REGISTER(pNode->dac.B_params, AMPLIFIER_OUT, AMPLIFIER_RIGHT, 0) = 0x7F | RT_BIT(7);
304
305 pNode->dac.node.au32F00_param[9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_AUDIO_OUTPUT, 0xD, 0)
306 | CODEC_F00_09_CAP_L_R_SWAP
307 | CODEC_F00_09_CAP_POWER_CTRL
308 | CODEC_F00_09_CAP_OUT_AMP_PRESENT
309 | CODEC_F00_09_CAP_LSB;//(0xD << 16) | RT_BIT(11) | RT_BIT(10) | RT_BIT(2) | RT_BIT(0);
310 pNode->dac.u32F0c_param = 0;
311 pNode->dac.u32F05_param = CODEC_MAKE_F05(0, 0, 0, CODEC_F05_D3, CODEC_F05_D3);//0x3 << 4 | 0x3; /* PS-Act: D3, Set: D3 */
312 break;
313 case 6:
314 pNode->node.au32F02_param[0] = 0x17;
315 goto adc_init;
316 case 7:
317 pNode->node.au32F02_param[0] = 0x18;
318 adc_init:
319 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 */
320 pNode->adc.node.au32F00_param[0xE] = CODEC_MAKE_F00_0E(0, 1);//RT_BIT(0);
321 pNode->adc.u32F03_param = RT_BIT(0);
322 pNode->adc.u32F05_param = CODEC_MAKE_F05(0, 0, 0, CODEC_F05_D3, CODEC_F05_D3);//0x3 << 4 | 0x3; /* PS-Act: D3 Set: D3 */
323 pNode->adc.u32F06_param = 0;
324 pNode->adc.node.au32F00_param[9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_AUDIO_INPUT, 0xD, 0)
325 | CODEC_F00_09_CAP_POWER_CTRL
326 | CODEC_F00_09_CAP_CONNECTION_LIST
327 | CODEC_F00_09_CAP_PROC_WIDGET
328 | CODEC_F00_09_CAP_LSB;//RT_BIT(20)| (0xd << 16) | RT_BIT(10) | RT_BIT(8) | RT_BIT(6)| RT_BIT(0);
329 break;
330 case 8:
331 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;
332 pNode->spdifout.node.au32F00_param[9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_AUDIO_OUTPUT, 0x4, 0)
333 | CODEC_F00_09_CAP_DIGITAL
334 | CODEC_F00_09_CAP_FMT_OVERRIDE
335 | CODEC_F00_09_CAP_LSB;//(4 << 16) | RT_BIT(9)|RT_BIT(4)|0x1;
336 pNode->node.au32F00_param[0xa] = pState->pNodes[1].node.au32F00_param[0xA];
337 pNode->spdifout.node.au32F00_param[0xB] = CODEC_F00_0B_PCM;
338 pNode->spdifout.u32F06_param = 0;
339 pNode->spdifout.u32F0d_param = 0;
340 break;
341 case 9:
342 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;
343 pNode->spdifin.node.au32F00_param[9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_AUDIO_INPUT, 0x4, 0)
344 | CODEC_F00_09_CAP_DIGITAL
345 | CODEC_F00_09_CAP_CONNECTION_LIST
346 | CODEC_F00_09_CAP_FMT_OVERRIDE
347 | CODEC_F00_09_CAP_LSB;//(0x1 << 20)|(4 << 16) | RT_BIT(9)| RT_BIT(8)|RT_BIT(4)|0x1;
348 pNode->node.au32F00_param[0xA] = pState->pNodes[1].node.au32F00_param[0xA];
349 pNode->node.au32F00_param[0xE] = CODEC_MAKE_F00_0E(0, 1);//RT_BIT(0);
350 pNode->node.au32F02_param[0] = 0x11;
351 pNode->spdifin.node.au32F00_param[0xB] = CODEC_F00_0B_PCM;
352 pNode->spdifin.u32F06_param = 0;
353 pNode->spdifin.u32F0d_param = 0;
354 break;
355 case 0xA:
356 pNode->node.au32F00_param[0xC] = CODEC_MAKE_F00_0C(0x17)
357 | CODEC_F00_0C_CAP_INPUT
358 | CODEC_F00_0C_CAP_OUTPUT
359 | CODEC_F00_0C_CAP_HP
360 | CODEC_F00_0C_CAP_PRESENSE_DETECT
361 | CODEC_F00_0C_CAP_TRIGGER_REQUIRED
362 | CODEC_F00_0C_CAP_IMPENDANCE_SENSE;//0x173f;
363 pNode->node.au32F02_param[0] = 0x2;
364 pNode->port.u32F07_param = CODEC_F07_IN_ENABLE
365 | CODEC_F07_OUT_ENABLE;
366 pNode->port.u32F08_param = 0;
367 if (!pState->fInReset)
368 pNode->port.u32F1c_param = CODEC_MAKE_F1C(CODEC_F1C_PORT_COMPLEX,
369 CODEC_F1C_LOCATION_FRONT,
370 CODEC_F1C_DEVICE_HP,
371 CODEC_F1C_CONNECTION_TYPE_1_8INCHES,
372 CODEC_F1C_COLOR_GREEN,
373 CODEC_F1C_MISC_JACK_DETECT,
374 0x2, 0);//RT_MAKE_U32_FROM_U8(0x20, 0x40, 0x21, 0x02);
375 goto port_init;
376 case 0xB:
377 pNode->node.au32F00_param[0xC] = CODEC_MAKE_F00_0C(0x17)
378 | CODEC_F00_0C_CAP_INPUT
379 | CODEC_F00_0C_CAP_OUTPUT
380 | CODEC_F00_0C_CAP_PRESENSE_DETECT
381 | CODEC_F00_0C_CAP_TRIGGER_REQUIRED
382 | CODEC_F00_0C_CAP_IMPENDANCE_SENSE;//0x1737;
383 pNode->node.au32F02_param[0] = 0x4;
384 pNode->port.u32F07_param = CODEC_F07_IN_ENABLE;
385 if (!pState->fInReset)
386 pNode->port.u32F1c_param = CODEC_MAKE_F1C(CODEC_F1C_PORT_COMPLEX,
387 CODEC_F1C_LOCATION_INTERNAL|CODEC_F1C_LOCATION_REAR,
388 CODEC_F1C_DEVICE_SPEAKER,
389 CODEC_F1C_CONNECTION_TYPE_1_8INCHES,
390 CODEC_F1C_COLOR_BLACK,
391 CODEC_F1C_MISC_JACK_DETECT,
392 0x1, 0x1);//RT_MAKE_U32_FROM_U8(0x11, 0x60, 0x11, 0x01);
393 goto port_init;
394 case 0xC:
395 pNode->node.au32F02_param[0] = 0x3;
396 pNode->node.au32F00_param[0xC] = CODEC_MAKE_F00_0C(0x17)
397 | CODEC_F00_0C_CAP_INPUT
398 | CODEC_F00_0C_CAP_OUTPUT
399 | CODEC_F00_0C_CAP_PRESENSE_DETECT
400 | CODEC_F00_0C_CAP_TRIGGER_REQUIRED
401 | CODEC_F00_0C_CAP_IMPENDANCE_SENSE;//0x1737;
402 pNode->port.u32F07_param = CODEC_F07_IN_ENABLE;
403 if (!pState->fInReset)
404 pNode->port.u32F1c_param = CODEC_MAKE_F1C(CODEC_F1C_PORT_COMPLEX,
405 CODEC_F1C_LOCATION_REAR,
406 CODEC_F1C_DEVICE_SPEAKER,
407 CODEC_F1C_CONNECTION_TYPE_1_8INCHES,
408 CODEC_F1C_COLOR_GREEN,
409 0x0, 0x1, 0x0);//RT_MAKE_U32_FROM_U8(0x10, 0x40, 0x11, 0x01);
410 goto port_init;
411 case 0xD:
412 pNode->node.au32F00_param[0xC] = CODEC_MAKE_F00_0C(0x17)
413 | CODEC_F00_0C_CAP_INPUT
414 | CODEC_F00_0C_CAP_OUTPUT
415 | CODEC_F00_0C_CAP_PRESENSE_DETECT
416 | CODEC_F00_0C_CAP_TRIGGER_REQUIRED
417 | CODEC_F00_0C_CAP_IMPENDANCE_SENSE;//0x1737;
418 pNode->port.u32F07_param = CODEC_F07_IN_ENABLE;
419 pNode->node.au32F02_param[0] = 0x2;
420 if (!pState->fInReset)
421 pNode->port.u32F1c_param = CODEC_MAKE_F1C(CODEC_F1C_PORT_COMPLEX,
422 CODEC_F1C_LOCATION_FRONT,
423 CODEC_F1C_DEVICE_MIC,
424 CODEC_F1C_CONNECTION_TYPE_1_8INCHES,
425 CODEC_F1C_COLOR_PINK,
426 0x0, 0x5, 0x0);//RT_MAKE_U32_FROM_U8(0x50, 0x90, 0xA1, 0x02); /* Microphone */
427 port_init:
428 pNode->port.u32F09_param = CODEC_MAKE_F09_ANALOG(1, CODEC_F09_ANALOG_NA);//RT_BIT(31)|0x7fffffff;
429 pNode->port.u32F08_param = 0;
430 pNode->node.au32F00_param[9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_PIN_COMPLEX, 0x0, 0)
431 | CODEC_F00_09_CAP_CONNECTION_LIST
432 | CODEC_F00_09_CAP_UNSOL
433 | CODEC_F00_09_CAP_LSB;//(4 << 20)|RT_BIT(8)|RT_BIT(7)|RT_BIT(0);
434 pNode->node.au32F00_param[0xE] = CODEC_MAKE_F00_0E(0, 1);//0x1;
435 break;
436 case 0xE:
437 pNode->node.au32F00_param[9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_PIN_COMPLEX, 0x0, 0)
438 | CODEC_F00_09_CAP_UNSOL
439 | CODEC_F00_09_CAP_LSB;//(4 << 20)|RT_BIT(7)|RT_BIT(0);
440 pNode->port.u32F08_param = 0;
441 pNode->node.au32F00_param[0xC] = CODEC_F00_0C_CAP_INPUT
442 | CODEC_F00_0C_CAP_OUTPUT
443 | CODEC_F00_0C_CAP_PRESENSE_DETECT;//0x34;
444 pNode->port.u32F07_param = CODEC_F07_IN_ENABLE;
445 pNode->port.u32F09_param = CODEC_MAKE_F09_ANALOG(0, CODEC_F09_ANALOG_NA);//0x7fffffff;
446 if (!pState->fInReset)
447 pNode->port.u32F1c_param = CODEC_MAKE_F1C(CODEC_F1C_PORT_COMPLEX,
448 CODEC_F1C_LOCATION_REAR,
449 CODEC_F1C_DEVICE_LINE_OUT,
450 CODEC_F1C_CONNECTION_TYPE_1_8INCHES,
451 CODEC_F1C_COLOR_BLUE,
452 0x0, 0x4, 0x0);//0x01013040; /* Line Out */
453 break;
454 case 0xF:
455 pNode->node.au32F00_param[9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_PIN_COMPLEX, 0x0, 0x0)
456 | CODEC_F00_09_CAP_CONNECTION_LIST
457 | CODEC_F00_09_CAP_UNSOL
458 | CODEC_F00_09_CAP_OUT_AMP_PRESENT
459 | CODEC_F00_09_CAP_LSB;//(4 << 20)|RT_BIT(8)|RT_BIT(7)|RT_BIT(2)|RT_BIT(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
463 /* | CODEC_F00_0C_CAP_TRIGGER_REQUIRED
464 | CODEC_F00_0C_CAP_IMPENDANCE_SENSE */;//0x37;
465 pNode->node.au32F00_param[0xE] = CODEC_MAKE_F00_0E(0, 1);//0x1;
466 pNode->port.u32F08_param = 0;
467 pNode->port.u32F07_param = CODEC_F07_OUT_ENABLE
468 | CODEC_F07_IN_ENABLE;
469 if (!pState->fInReset)
470 pNode->port.u32F1c_param = CODEC_MAKE_F1C(CODEC_F1C_PORT_COMPLEX,
471 CODEC_F1C_LOCATION_INTERNAL,
472 CODEC_F1C_DEVICE_SPEAKER,
473 CODEC_F1C_CONNECTION_TYPE_1_8INCHES,
474 CODEC_F1C_COLOR_ORANGE,
475 0x0, 0x1, 0x2);//RT_MAKE_U32_FROM_U8(0x12, 0x60, 0x11, 0x01);
476 pNode->node.au32F02_param[0] = 0x5;
477 pNode->port.u32F09_param = CODEC_MAKE_F09_ANALOG(0, CODEC_F09_ANALOG_NA);//0x7fffffff;
478 break;
479 case 0x10:
480 pNode->node.au32F00_param[9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_PIN_COMPLEX, 0x0, 0x0)
481 | CODEC_F00_09_CAP_DIGITAL
482 | CODEC_F00_09_CAP_CONNECTION_LIST
483 | CODEC_F00_09_CAP_LSB;//(4<<20)|RT_BIT(9)|RT_BIT(8)|RT_BIT(0);
484 pNode->node.au32F00_param[0xC] = CODEC_F00_0C_CAP_OUTPUT;//RT_BIT(4);
485 pNode->node.au32F00_param[0xE] = CODEC_MAKE_F00_0E(0, 0x3);
486 pNode->node.au32F02_param[0] = RT_MAKE_U32_FROM_U8(0x08, 0x17, 0x19, 0);
487 if (!pState->fInReset)
488 pNode->digout.u32F1c_param = CODEC_MAKE_F1C(CODEC_F1C_PORT_COMPLEX,
489 CODEC_F1C_LOCATION_REAR,
490 CODEC_F1C_DEVICE_SPDIF_OUT,
491 CODEC_F1C_CONNECTION_TYPE_DIN,
492 CODEC_F1C_COLOR_BLACK,
493 0x0, 0x3, 0x0);//RT_MAKE_U32_FROM_U8(0x30, 0x10, 0x45, 0x01);
494 break;
495 case 0x11:
496 pNode->node.au32F00_param[9] = (4 << 20)|(3<<16)|RT_BIT(10)|RT_BIT(9)|RT_BIT(7)|RT_BIT(0);
497 pNode->node.au32F00_param[0xC] = CODEC_F00_0C_CAP_EAPD
498 | CODEC_F00_0C_CAP_INPUT
499 | CODEC_F00_0C_CAP_PRESENSE_DETECT;//RT_BIT(16)| RT_BIT(5)|RT_BIT(2);
500 pNode->digin.u32F05_param = CODEC_MAKE_F05(0, 0, 0, CODEC_F05_D3, CODEC_F05_D3);//0x3 << 4 | 0x3; /* PS-Act: D3 -> D3 */
501 pNode->digin.u32F07_param = 0;
502 pNode->digin.u32F08_param = 0;
503 pNode->digin.u32F09_param = 0;
504 pNode->digin.u32F0c_param = 0;
505 if (!pState->fInReset)
506 pNode->digin.u32F1c_param = CODEC_MAKE_F1C(CODEC_F1C_PORT_COMPLEX,
507 CODEC_F1C_LOCATION_REAR,
508 CODEC_F1C_DEVICE_SPDIF_IN,
509 CODEC_F1C_CONNECTION_TYPE_OTHER_DIGITAL,
510 CODEC_F1C_COLOR_BLACK,
511 0x0, 0x6, 0x0);//(0x1 << 24) | (0xc5 << 16) | (0x10 << 8) | 0x60;
512 break;
513 case 0x12:
514 pNode->adcmux.u32F01_param = 0;
515 goto adcmux_init;
516 case 0x13:
517 pNode->adcmux.u32F01_param = 1;
518 adcmux_init:
519 pNode->node.au32F00_param[9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_AUDIO_SELECTOR, 0x0, 0)
520 | CODEC_F00_09_CAP_CONNECTION_LIST
521 | CODEC_F00_09_CAP_AMP_FMT_OVERRIDE
522 | CODEC_F00_09_CAP_OUT_AMP_PRESENT
523 | CODEC_F00_09_CAP_LSB;//(3<<20)|RT_BIT(8)|RT_BIT(3)|RT_BIT(2)|RT_BIT(0);
524 pNode->node.au32F00_param[0xe] = CODEC_MAKE_F00_0E(0, 0x7);
525 pNode->node.au32F00_param[0x12] = (0x27 << 16)|(0x4 << 8);
526 /* STAC 9220 v10 6.21-22.{4,5} both(left and right) out amplefiers inited with 0*/
527 memset(pNode->adcmux.B_params, 0, AMPLIFIER_SIZE);
528 pNode->node.au32F02_param[0] = RT_MAKE_U32_FROM_U8(0xe, 0x15, 0xf, 0xb);
529 pNode->node.au32F02_param[4] = RT_MAKE_U32_FROM_U8(0xc, 0xd, 0xa, 0x0);
530 break;
531 case 0x14:
532 pNode->node.au32F00_param[9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_BEEP_GEN, 0, 0)
533 | CODEC_F00_09_CAP_AMP_FMT_OVERRIDE
534 | CODEC_F00_09_CAP_OUT_AMP_PRESENT;//(7 << 20) | RT_BIT(3) | RT_BIT(2);
535 pNode->node.au32F00_param[0x12] = (0x17 << 16)|(0x3 << 8)| 0x3;
536 pNode->pcbeep.u32F0a_param = 0;
537 memset(pNode->pcbeep.B_params, 0, AMPLIFIER_SIZE);
538 break;
539 case 0x15:
540 pNode->node.au32F00_param[0x9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_PIN_COMPLEX, 0, 0)
541 | CODEC_F00_09_CAP_LSB;//(4 << 20)|RT_BIT(0);
542 pNode->node.au32F00_param[0xc] = CODEC_F00_0C_CAP_INPUT;//RT_BIT(5);
543 if (!pState->fInReset)
544 pNode->cdnode.u32F1c_param = CODEC_MAKE_F1C(CODEC_F1C_PORT_FIXED,
545 CODEC_F1C_LOCATION_INTERNAL,
546 CODEC_F1C_DEVICE_CD,
547 CODEC_F1C_CONNECTION_TYPE_ATAPI,
548 CODEC_F1C_COLOR_UNKNOWN,
549 0x0, 0x7, 0x0);//RT_MAKE_U32_FROM_U8(0x70, 0x0, 0x33, 0x90);
550 break;
551 case 0x16:
552 pNode->node.au32F00_param[0x9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_VOLUME_KNOB, 0x0, 0x0);//(0x6 << 20);
553 pNode->node.au32F00_param[0x13] = RT_BIT(7)| 0x7F;
554 pNode->node.au32F00_param[0xe] = CODEC_MAKE_F00_0E(0, 0x4);
555 pNode->node.au32F02_param[0] = RT_MAKE_U32_FROM_U8(0x2, 0x3, 0x4, 0x5);
556 pNode->volumeKnob.u32F08_param = 0;
557 pNode->volumeKnob.u32F0f_param = 0x7f;
558 break;
559 case 0x17:
560 pNode->node.au32F02_param[0] = 0x12;
561 goto adcvol_init;
562 case 0x18:
563 pNode->node.au32F02_param[0] = 0x13;
564 adcvol_init:
565 memset(pNode->adcvol.B_params, 0, AMPLIFIER_SIZE);
566
567 pNode->node.au32F00_param[0x9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_AUDIO_SELECTOR, 0, 0)
568 | CODEC_F00_09_CAP_L_R_SWAP
569 | CODEC_F00_09_CAP_CONNECTION_LIST
570 | CODEC_F00_09_CAP_IN_AMP_PRESENT
571 | CODEC_F00_09_CAP_LSB;//(0x3 << 20)|RT_BIT(11)|RT_BIT(8)|RT_BIT(1)|RT_BIT(0);
572 pNode->node.au32F00_param[0xe] = CODEC_MAKE_F00_0E(0, 0x1);
573 AMPLIFIER_REGISTER(pNode->adcvol.B_params, AMPLIFIER_IN, AMPLIFIER_LEFT, 0) = RT_BIT(7);
574 AMPLIFIER_REGISTER(pNode->adcvol.B_params, AMPLIFIER_IN, AMPLIFIER_RIGHT, 0) = RT_BIT(7);
575 pNode->adcvol.u32F0c_param = 0;
576 break;
577 case 0x19:
578 pNode->node.au32F00_param[0x9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_VENDOR_DEFINED, 0x3, 0)
579 | CODEC_F00_09_CAP_DIGITAL
580 | CODEC_F00_09_CAP_LSB;//(0xF << 20)|(0x3 << 16)|RT_BIT(9)|RT_BIT(0);
581 break;
582 case 0x1A:
583 pNode->node.au32F00_param[0x9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_AUDIO_OUTPUT, 0x3, 0)
584 | CODEC_F00_09_CAP_DIGITAL
585 | CODEC_F00_09_CAP_LSB;//(0x3 << 16)|RT_BIT(9)|RT_BIT(0);
586 break;
587 case 0x1B:
588 pNode->node.au32F00_param[0x9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_PIN_COMPLEX, 0, 0)
589 | CODEC_F00_09_CAP_DIGITAL
590 | CODEC_F00_09_CAP_CONNECTION_LIST
591 | CODEC_F00_09_CAP_LSB;//(0x4 << 20)|RT_BIT(9)|RT_BIT(8)|RT_BIT(0);
592 pNode->node.au32F00_param[0xE] = CODEC_MAKE_F00_0E(0, 0x1);
593 pNode->node.au32F00_param[0xC] = CODEC_F00_0C_CAP_OUTPUT;//0x10;
594 pNode->node.au32F02_param[0] = 0x1a;
595 pNode->reserved.u32F1c_param = CODEC_MAKE_F1C(CODEC_F1C_PORT_NO_PHYS,
596 CODEC_F1C_LOCATION_NA,
597 CODEC_F1C_DEVICE_LINE_OUT,
598 CODEC_F1C_CONNECTION_TYPE_UNKNOWN,
599 CODEC_F1C_COLOR_UNKNOWN,
600 0x0, 0x0, 0xf);//0x4000000f;
601 break;
602 default:
603 break;
604 }
605 return VINF_SUCCESS;
606}
607
608/* generic */
609
610#define DECLISNODEOFTYPE(type) \
611 static inline int codecIs##type##Node(struct CODECState *pState, uint8_t cNode) \
612 { \
613 Assert(pState->au8##type##s); \
614 for(int i = 0; pState->au8##type##s[i] != 0; ++i) \
615 if (pState->au8##type##s[i] == cNode) \
616 return 1; \
617 return 0; \
618 }
619/* codecIsPortNode */
620DECLISNODEOFTYPE(Port)
621/* codecIsDacNode */
622DECLISNODEOFTYPE(Dac)
623/* codecIsAdcVolNode */
624DECLISNODEOFTYPE(AdcVol)
625/* codecIsAdcNode */
626DECLISNODEOFTYPE(Adc)
627/* codecIsAdcMuxNode */
628DECLISNODEOFTYPE(AdcMux)
629/* codecIsPcbeepNode */
630DECLISNODEOFTYPE(Pcbeep)
631/* codecIsSpdifOutNode */
632DECLISNODEOFTYPE(SpdifOut)
633/* codecIsSpdifInNode */
634DECLISNODEOFTYPE(SpdifIn)
635/* codecIsDigInPinNode */
636DECLISNODEOFTYPE(DigInPin)
637/* codecIsDigOutPinNode */
638DECLISNODEOFTYPE(DigOutPin)
639/* codecIsCdNode */
640DECLISNODEOFTYPE(Cd)
641/* codecIsVolKnobNode */
642DECLISNODEOFTYPE(VolKnob)
643/* codecIsReservedNode */
644DECLISNODEOFTYPE(Reserved)
645
646static int codecToAudVolume(AMPLIFIER *pAmp, audmixerctl_t mt);
647
648static inline void codecSetRegister(uint32_t *pu32Reg, uint32_t u32Cmd, uint8_t u8Offset, uint32_t mask)
649{
650 Assert((pu32Reg && u8Offset < 32));
651 *pu32Reg &= ~(mask << u8Offset);
652 *pu32Reg |= (u32Cmd & mask) << u8Offset;
653}
654static inline void codecSetRegisterU8(uint32_t *pu32Reg, uint32_t u32Cmd, uint8_t u8Offset)
655{
656 codecSetRegister(pu32Reg, u32Cmd, u8Offset, CODEC_VERB_8BIT_DATA);
657}
658
659static inline void codecSetRegisterU16(uint32_t *pu32Reg, uint32_t u32Cmd, uint8_t u8Offset)
660{
661 codecSetRegister(pu32Reg, u32Cmd, u8Offset, CODEC_VERB_16BIT_DATA);
662}
663
664
665static int codecUnimplemented(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
666{
667 Log(("codecUnimplemented: cmd(raw:%x: cad:%x, d:%c, nid:%x, verb:%x)\n", cmd,
668 CODEC_CAD(cmd), CODEC_DIRECT(cmd) ? 'N' : 'Y', CODEC_NID(cmd), CODEC_VERBDATA(cmd)));
669 *pResp = 0;
670 return VINF_SUCCESS;
671}
672
673static int codecBreak(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
674{
675 int rc;
676 rc = codecUnimplemented(pState, cmd, pResp);
677 *pResp |= CODEC_RESPONSE_UNSOLICITED;
678 return rc;
679}
680/* B-- */
681static int codecGetAmplifier(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
682{
683 Assert((CODEC_CAD(cmd) == pState->id));
684 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
685 if (CODEC_NID(cmd) >= pState->cTotalNodes)
686 {
687 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
688 return VINF_SUCCESS;
689 }
690 *pResp = 0;
691 /* HDA spec 7.3.3.7 Note A */
692 /* @todo: if index out of range response should be 0 */
693 uint8_t u8Index = CODEC_GET_AMP_DIRECTION(cmd) == AMPLIFIER_OUT? 0 : CODEC_GET_AMP_INDEX(cmd);
694
695 PCODECNODE pNode = &pState->pNodes[CODEC_NID(cmd)];
696 if (codecIsDacNode(pState, CODEC_NID(cmd)))
697 *pResp = AMPLIFIER_REGISTER(pNode->dac.B_params,
698 CODEC_GET_AMP_DIRECTION(cmd),
699 CODEC_GET_AMP_SIDE(cmd),
700 u8Index);
701 else if (codecIsAdcVolNode(pState, CODEC_NID(cmd)))
702 *pResp = AMPLIFIER_REGISTER(pNode->adcvol.B_params,
703 CODEC_GET_AMP_DIRECTION(cmd),
704 CODEC_GET_AMP_SIDE(cmd),
705 u8Index);
706 else if (codecIsAdcMuxNode(pState, CODEC_NID(cmd)))
707 *pResp = AMPLIFIER_REGISTER(pNode->adcmux.B_params,
708 CODEC_GET_AMP_DIRECTION(cmd),
709 CODEC_GET_AMP_SIDE(cmd),
710 u8Index);
711 else if (codecIsPcbeepNode(pState, CODEC_NID(cmd)))
712 *pResp = AMPLIFIER_REGISTER(pNode->pcbeep.B_params,
713 CODEC_GET_AMP_DIRECTION(cmd),
714 CODEC_GET_AMP_SIDE(cmd),
715 u8Index);
716 else if (codecIsPortNode(pState, CODEC_NID(cmd)))
717 *pResp = AMPLIFIER_REGISTER(pNode->port.B_params,
718 CODEC_GET_AMP_DIRECTION(cmd),
719 CODEC_GET_AMP_SIDE(cmd),
720 u8Index);
721 else if (codecIsAdcNode(pState, CODEC_NID(cmd)))
722 *pResp = AMPLIFIER_REGISTER(pNode->adc.B_params,
723 CODEC_GET_AMP_DIRECTION(cmd),
724 CODEC_GET_AMP_SIDE(cmd),
725 u8Index);
726 else{
727 AssertMsgReturn(0, ("access to fields of %x need to be implemented\n", CODEC_NID(cmd)), VINF_SUCCESS);
728 }
729 return VINF_SUCCESS;
730}
731/* 3-- */
732static int codecSetAmplifier(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
733{
734 AMPLIFIER *pAmplifier = NULL;
735 bool fIsLeft = false;
736 bool fIsRight = false;
737 bool fIsOut = false;
738 bool fIsIn = false;
739 uint8_t u8Index = 0;
740 Assert((CODEC_CAD(cmd) == pState->id));
741 if (CODEC_NID(cmd) >= pState->cTotalNodes)
742 {
743 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
744 return VINF_SUCCESS;
745 }
746 *pResp = 0;
747 PCODECNODE pNode = &pState->pNodes[CODEC_NID(cmd)];
748 if (codecIsDacNode(pState, CODEC_NID(cmd)))
749 pAmplifier = &pNode->dac.B_params;
750 else if (codecIsAdcVolNode(pState, CODEC_NID(cmd)))
751 pAmplifier = &pNode->adcvol.B_params;
752 else if (codecIsAdcMuxNode(pState, CODEC_NID(cmd)))
753 pAmplifier = &pNode->adcmux.B_params;
754 else if (codecIsPcbeepNode(pState, CODEC_NID(cmd)))
755 pAmplifier = &pNode->pcbeep.B_params;
756 else if (codecIsPortNode(pState, CODEC_NID(cmd)))
757 pAmplifier = &pNode->port.B_params;
758 else if (codecIsAdcNode(pState, CODEC_NID(cmd)))
759 pAmplifier = &pNode->adc.B_params;
760 Assert(pAmplifier);
761 if (pAmplifier)
762 {
763 fIsOut = CODEC_SET_AMP_IS_OUT_DIRECTION(cmd);
764 fIsIn = CODEC_SET_AMP_IS_IN_DIRECTION(cmd);
765 fIsRight = CODEC_SET_AMP_IS_RIGHT_SIDE(cmd);
766 fIsLeft = CODEC_SET_AMP_IS_LEFT_SIDE(cmd);
767 u8Index = CODEC_SET_AMP_INDEX(cmd);
768 if ( (!fIsLeft && !fIsRight)
769 || (!fIsOut && !fIsIn))
770 return VINF_SUCCESS;
771 if (fIsIn)
772 {
773 if (fIsLeft)
774 codecSetRegisterU8(&AMPLIFIER_REGISTER(*pAmplifier, AMPLIFIER_IN, AMPLIFIER_LEFT, u8Index), cmd, 0);
775 if (fIsRight)
776 codecSetRegisterU8(&AMPLIFIER_REGISTER(*pAmplifier, AMPLIFIER_IN, AMPLIFIER_RIGHT, u8Index), cmd, 0);
777 }
778 if (fIsOut)
779 {
780 if (fIsLeft)
781 codecSetRegisterU8(&AMPLIFIER_REGISTER(*pAmplifier, AMPLIFIER_OUT, AMPLIFIER_LEFT, u8Index), cmd, 0);
782 if (fIsRight)
783 codecSetRegisterU8(&AMPLIFIER_REGISTER(*pAmplifier, AMPLIFIER_OUT, AMPLIFIER_RIGHT, u8Index), cmd, 0);
784 }
785 if (CODEC_NID(cmd) == pState->u8DacLineOut)
786 codecToAudVolume(pAmplifier, AUD_MIXER_VOLUME);
787 if (CODEC_NID(cmd) == pState->u8AdcVolsLineIn) /* Microphone */
788 codecToAudVolume(pAmplifier, AUD_MIXER_LINE_IN);
789 }
790 return VINF_SUCCESS;
791}
792
793static int codecGetParameter(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
794{
795 Assert((CODEC_CAD(cmd) == pState->id));
796 if (CODEC_NID(cmd) >= pState->cTotalNodes)
797 {
798 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
799 return VINF_SUCCESS;
800 }
801 Assert(((cmd & CODEC_VERB_8BIT_DATA) < CODECNODE_F0_PARAM_LENGTH));
802 if ((cmd & CODEC_VERB_8BIT_DATA) >= CODECNODE_F0_PARAM_LENGTH)
803 {
804 Log(("HDAcodec: invalid F00 parameter %d\n", (cmd & CODEC_VERB_8BIT_DATA)));
805 return VINF_SUCCESS;
806 }
807 *pResp = 0;
808 *pResp = pState->pNodes[CODEC_NID(cmd)].node.au32F00_param[cmd & CODEC_VERB_8BIT_DATA];
809 return VINF_SUCCESS;
810}
811
812/* F01 */
813static int codecGetConSelectCtrl(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
814{
815 Assert((CODEC_CAD(cmd) == pState->id));
816 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
817 if (CODEC_NID(cmd) >= pState->cTotalNodes)
818 {
819 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
820 return VINF_SUCCESS;
821 }
822 *pResp = 0;
823 if (codecIsAdcMuxNode(pState, CODEC_NID(cmd)))
824 *pResp = pState->pNodes[CODEC_NID(cmd)].adcmux.u32F01_param;
825 else if (codecIsDigOutPinNode(pState, CODEC_NID(cmd)))
826 *pResp = pState->pNodes[CODEC_NID(cmd)].digout.u32F01_param;
827 else if (codecIsPortNode(pState, CODEC_NID(cmd)))
828 *pResp = pState->pNodes[CODEC_NID(cmd)].port.u32F01_param;
829 else if (codecIsAdcNode(pState, CODEC_NID(cmd)))
830 *pResp = pState->pNodes[CODEC_NID(cmd)].adc.u32F01_param;
831 else if (codecIsAdcVolNode(pState, CODEC_NID(cmd)))
832 *pResp = pState->pNodes[CODEC_NID(cmd)].adcvol.u32F01_param;
833 return VINF_SUCCESS;
834}
835
836/* 701 */
837static int codecSetConSelectCtrl(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
838{
839 uint32_t *pu32Reg = NULL;
840 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
841 if (CODEC_NID(cmd) >= pState->cTotalNodes)
842 {
843 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
844 return VINF_SUCCESS;
845 }
846 *pResp = 0;
847 if (codecIsAdcMuxNode(pState, CODEC_NID(cmd)))
848 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].adcmux.u32F01_param;
849 else if (codecIsDigOutPinNode(pState, CODEC_NID(cmd)))
850 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].digout.u32F01_param;
851 else if (codecIsPortNode(pState, CODEC_NID(cmd)))
852 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].port.u32F01_param;
853 else if (codecIsAdcNode(pState, CODEC_NID(cmd)))
854 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].adc.u32F01_param;
855 else if (codecIsAdcVolNode(pState, CODEC_NID(cmd)))
856 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].adcvol.u32F01_param;
857 Assert((pu32Reg));
858 if (pu32Reg)
859 codecSetRegisterU8(pu32Reg, cmd, 0);
860 return VINF_SUCCESS;
861}
862
863/* F07 */
864static int codecGetPinCtrl(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
865{
866 Assert((CODEC_CAD(cmd) == pState->id));
867 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
868 if (CODEC_NID(cmd) >= pState->cTotalNodes)
869 {
870 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
871 return VINF_SUCCESS;
872 }
873 *pResp = 0;
874 if (codecIsPortNode(pState, CODEC_NID(cmd)))
875 *pResp = pState->pNodes[CODEC_NID(cmd)].port.u32F07_param;
876 else if (codecIsDigOutPinNode(pState, CODEC_NID(cmd)))
877 *pResp = pState->pNodes[CODEC_NID(cmd)].digout.u32F07_param;
878 else if (codecIsDigInPinNode(pState, CODEC_NID(cmd)))
879 *pResp = pState->pNodes[CODEC_NID(cmd)].digin.u32F07_param;
880 else if (codecIsCdNode(pState, CODEC_NID(cmd)))
881 *pResp = pState->pNodes[CODEC_NID(cmd)].cdnode.u32F07_param;
882 else if (codecIsPcbeepNode(pState, CODEC_NID(cmd)))
883 *pResp = pState->pNodes[CODEC_NID(cmd)].pcbeep.u32F07_param;
884 else if (codecIsReservedNode(pState, CODEC_NID(cmd)))
885 *pResp = pState->pNodes[CODEC_NID(cmd)].reserved.u32F07_param;
886 else
887 AssertMsgFailed(("Unsupported"));
888 return VINF_SUCCESS;
889}
890
891/* 707 */
892static int codecSetPinCtrl(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
893{
894 Assert((CODEC_CAD(cmd) == pState->id));
895 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
896 if (CODEC_NID(cmd) >= pState->cTotalNodes)
897 {
898 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
899 return VINF_SUCCESS;
900 }
901 *pResp = 0;
902 uint32_t *pu32Reg = NULL;
903 if (codecIsPortNode(pState, CODEC_NID(cmd)))
904 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].port.u32F07_param;
905 else if (codecIsDigInPinNode(pState, CODEC_NID(cmd)))
906 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].digin.u32F07_param;
907 else if (codecIsDigOutPinNode(pState, CODEC_NID(cmd)))
908 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].digout.u32F07_param;
909 else if (codecIsCdNode(pState, CODEC_NID(cmd)))
910 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].cdnode.u32F07_param;
911 else if (codecIsPcbeepNode(pState, CODEC_NID(cmd)))
912 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].pcbeep.u32F07_param;
913 else if ( codecIsReservedNode(pState, CODEC_NID(cmd))
914 && CODEC_NID(cmd) == 0x1b)
915 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].reserved.u32F07_param;
916 Assert((pu32Reg));
917 if (pu32Reg)
918 codecSetRegisterU8(pu32Reg, cmd, 0);
919 return VINF_SUCCESS;
920}
921
922/* F08 */
923static int codecGetUnsolicitedEnabled(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
924{
925 Assert((CODEC_CAD(cmd) == pState->id));
926 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
927 if (CODEC_NID(cmd) >= pState->cTotalNodes)
928 {
929 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
930 return VINF_SUCCESS;
931 }
932 *pResp = 0;
933 if (codecIsPortNode(pState, CODEC_NID(cmd)))
934 *pResp = pState->pNodes[CODEC_NID(cmd)].port.u32F08_param;
935 else if (codecIsDigInPinNode(pState, CODEC_NID(cmd)))
936 *pResp = pState->pNodes[CODEC_NID(cmd)].digin.u32F08_param;
937 else if ((cmd) == 1 /* AFG */)
938 *pResp = pState->pNodes[CODEC_NID(cmd)].afg.u32F08_param;
939 else if (codecIsVolKnobNode(pState, CODEC_NID(cmd)))
940 *pResp = pState->pNodes[CODEC_NID(cmd)].volumeKnob.u32F08_param;
941 else if (codecIsDigOutPinNode(pState, CODEC_NID(cmd)))
942 *pResp = pState->pNodes[CODEC_NID(cmd)].digout.u32F08_param;
943 else if (codecIsDigInPinNode(pState, CODEC_NID(cmd)))
944 *pResp = pState->pNodes[CODEC_NID(cmd)].digin.u32F08_param;
945 else
946 AssertMsgFailed(("unsupported operation %x on node: %x\n", CODEC_VERB_CMD8(cmd), CODEC_NID(cmd)));
947 return VINF_SUCCESS;
948}
949
950/* 708 */
951static int codecSetUnsolicitedEnabled(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
952{
953 Assert((CODEC_CAD(cmd) == pState->id));
954 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
955 if (CODEC_NID(cmd) >= pState->cTotalNodes)
956 {
957 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
958 return VINF_SUCCESS;
959 }
960 *pResp = 0;
961 uint32_t *pu32Reg = NULL;
962 if (codecIsPortNode(pState, CODEC_NID(cmd)))
963 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].port.u32F08_param;
964 else if (codecIsDigInPinNode(pState, CODEC_NID(cmd)))
965 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].digin.u32F08_param;
966 else if (CODEC_NID(cmd) == 1 /* AFG */)
967 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].afg.u32F08_param;
968 else if (codecIsVolKnobNode(pState, CODEC_NID(cmd)))
969 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].volumeKnob.u32F08_param;
970 else if (codecIsDigInPinNode(pState, CODEC_NID(cmd)))
971 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].digin.u32F08_param;
972 else if (codecIsDigOutPinNode(pState, CODEC_NID(cmd)))
973 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].digout.u32F08_param;
974 else
975 AssertMsgFailed(("unsupported operation %x on node: %x\n", CODEC_VERB_CMD8(cmd), CODEC_NID(cmd)));
976 Assert(pu32Reg);
977 if(pu32Reg)
978 codecSetRegisterU8(pu32Reg, cmd, 0);
979 return VINF_SUCCESS;
980}
981
982/* F09 */
983static int codecGetPinSense(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
984{
985 Assert((CODEC_CAD(cmd) == pState->id));
986 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
987 if (CODEC_NID(cmd) >= pState->cTotalNodes)
988 {
989 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
990 return VINF_SUCCESS;
991 }
992 *pResp = 0;
993 if (codecIsPortNode(pState, CODEC_NID(cmd)))
994 *pResp = pState->pNodes[CODEC_NID(cmd)].port.u32F09_param;
995 else if (codecIsDigInPinNode(pState, CODEC_NID(cmd)))
996 *pResp = pState->pNodes[CODEC_NID(cmd)].digin.u32F09_param;
997 else
998 AssertMsgFailed(("unsupported operation %x on node: %x\n", CODEC_VERB_CMD8(cmd), CODEC_NID(cmd)));
999 return VINF_SUCCESS;
1000}
1001
1002/* 709 */
1003static int codecSetPinSense(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1004{
1005 Assert((CODEC_CAD(cmd) == pState->id));
1006 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1007 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1008 {
1009 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1010 return VINF_SUCCESS;
1011 }
1012 *pResp = 0;
1013 uint32_t *pu32Reg = NULL;
1014 if (codecIsPortNode(pState, CODEC_NID(cmd)))
1015 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].port.u32F09_param;
1016 else if (codecIsDigInPinNode(pState, CODEC_NID(cmd)))
1017 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].digin.u32F09_param;
1018 Assert(pu32Reg);
1019 if(pu32Reg)
1020 codecSetRegisterU8(pu32Reg, cmd, 0);
1021 return VINF_SUCCESS;
1022}
1023
1024static int codecGetConnectionListEntry(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1025{
1026 Assert((CODEC_CAD(cmd) == pState->id));
1027 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1028 *pResp = 0;
1029 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1030 {
1031 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1032 return VINF_SUCCESS;
1033 }
1034 Assert((cmd & CODEC_VERB_8BIT_DATA) < CODECNODE_F02_PARAM_LENGTH);
1035 if ((cmd & CODEC_VERB_8BIT_DATA) >= CODECNODE_F02_PARAM_LENGTH)
1036 {
1037 Log(("HDAcodec: access to invalid F02 index %d\n", (cmd & CODEC_VERB_8BIT_DATA)));
1038 return VINF_SUCCESS;
1039 }
1040 *pResp = pState->pNodes[CODEC_NID(cmd)].node.au32F02_param[cmd & CODEC_VERB_8BIT_DATA];
1041 return VINF_SUCCESS;
1042}
1043/* F03 */
1044static int codecGetProcessingState(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1045{
1046 Assert((CODEC_CAD(cmd) == pState->id));
1047 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1048 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1049 {
1050 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1051 return VINF_SUCCESS;
1052 }
1053 *pResp = 0;
1054 if (codecIsAdcNode(pState, CODEC_NID(cmd)))
1055 *pResp = pState->pNodes[CODEC_NID(cmd)].adc.u32F03_param;
1056 return VINF_SUCCESS;
1057}
1058
1059/* 703 */
1060static int codecSetProcessingState(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1061{
1062 Assert((CODEC_CAD(cmd) == pState->id));
1063 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1064 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1065 {
1066 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1067 return VINF_SUCCESS;
1068 }
1069 *pResp = 0;
1070 if (codecIsAdcNode(pState, CODEC_NID(cmd)))
1071 {
1072 codecSetRegisterU8(&pState->pNodes[CODEC_NID(cmd)].adc.u32F03_param, cmd, 0);
1073 }
1074 return VINF_SUCCESS;
1075}
1076
1077/* F0D */
1078static int codecGetDigitalConverter(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1079{
1080 Assert((CODEC_CAD(cmd) == pState->id));
1081 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1082 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1083 {
1084 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1085 return VINF_SUCCESS;
1086 }
1087 *pResp = 0;
1088 if (codecIsSpdifOutNode(pState, CODEC_NID(cmd)))
1089 *pResp = pState->pNodes[CODEC_NID(cmd)].spdifout.u32F0d_param;
1090 else if (codecIsSpdifInNode(pState, CODEC_NID(cmd)))
1091 *pResp = pState->pNodes[CODEC_NID(cmd)].spdifin.u32F0d_param;
1092 return VINF_SUCCESS;
1093}
1094
1095static int codecSetDigitalConverter(struct CODECState *pState, uint32_t cmd, uint8_t u8Offset, uint64_t *pResp)
1096{
1097 Assert((CODEC_CAD(cmd) == pState->id));
1098 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1099 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1100 {
1101 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1102 return VINF_SUCCESS;
1103 }
1104 *pResp = 0;
1105 if (codecIsSpdifOutNode(pState, CODEC_NID(cmd)))
1106 codecSetRegisterU8(&pState->pNodes[CODEC_NID(cmd)].spdifout.u32F0d_param, cmd, u8Offset);
1107 else if (codecIsSpdifInNode(pState, CODEC_NID(cmd)))
1108 codecSetRegisterU8(&pState->pNodes[CODEC_NID(cmd)].spdifin.u32F0d_param, cmd, u8Offset);
1109 return VINF_SUCCESS;
1110}
1111
1112/* 70D */
1113static int codecSetDigitalConverter1(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1114{
1115 return codecSetDigitalConverter(pState, cmd, 0, pResp);
1116}
1117
1118/* 70E */
1119static int codecSetDigitalConverter2(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1120{
1121 return codecSetDigitalConverter(pState, cmd, 8, pResp);
1122}
1123
1124/* F20 */
1125static int codecGetSubId(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1126{
1127 Assert((CODEC_CAD(cmd) == pState->id));
1128 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1129 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1130 {
1131 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1132 return VINF_SUCCESS;
1133 }
1134 *pResp = 0;
1135 if (CODEC_NID(cmd) == 1 /* AFG */)
1136 {
1137 *pResp = pState->pNodes[CODEC_NID(cmd)].afg.u32F20_param;
1138 }
1139 return VINF_SUCCESS;
1140}
1141
1142static int codecSetSubIdX(struct CODECState *pState, uint32_t cmd, uint8_t u8Offset)
1143{
1144 Assert((CODEC_CAD(cmd) == pState->id));
1145 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1146 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1147 {
1148 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1149 return VINF_SUCCESS;
1150 }
1151 uint32_t *pu32Reg = NULL;
1152 if (CODEC_NID(cmd) == 0x1 /* AFG */)
1153 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].afg.u32F20_param;
1154 Assert((pu32Reg));
1155 if (pu32Reg)
1156 codecSetRegisterU8(pu32Reg, cmd, u8Offset);
1157 return VINF_SUCCESS;
1158}
1159/* 720 */
1160static int codecSetSubId0 (struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1161{
1162 *pResp = 0;
1163 return codecSetSubIdX(pState, cmd, 0);
1164}
1165
1166/* 721 */
1167static int codecSetSubId1 (struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1168{
1169 *pResp = 0;
1170 return codecSetSubIdX(pState, cmd, 8);
1171}
1172/* 722 */
1173static int codecSetSubId2 (struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1174{
1175 *pResp = 0;
1176 return codecSetSubIdX(pState, cmd, 16);
1177}
1178/* 723 */
1179static int codecSetSubId3 (struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1180{
1181 *pResp = 0;
1182 return codecSetSubIdX(pState, cmd, 24);
1183}
1184
1185static int codecReset(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1186{
1187 Assert((CODEC_CAD(cmd) == pState->id));
1188 Assert(CODEC_NID(cmd) == 1 /* AFG */);
1189 if(CODEC_NID(cmd) == 1 /* AFG */)
1190 {
1191 uint8_t i;
1192 Log(("HDAcodec: enters reset\n"));
1193 Assert(pState->pfnCodecNodeReset);
1194 for (i = 0; i < pState->cTotalNodes; ++i)
1195 {
1196 pState->pfnCodecNodeReset(pState, i, &pState->pNodes[i]);
1197 }
1198 pState->fInReset = false;
1199 Log(("HDAcodec: exits reset\n"));
1200 }
1201 *pResp = 0;
1202 return VINF_SUCCESS;
1203}
1204
1205/* F05 */
1206static int codecGetPowerState(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1207{
1208 Assert((CODEC_CAD(cmd) == pState->id));
1209 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1210 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1211 {
1212 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1213 return VINF_SUCCESS;
1214 }
1215 *pResp = 0;
1216 if (CODEC_NID(cmd) == 1 /* AFG */)
1217 *pResp = pState->pNodes[CODEC_NID(cmd)].afg.u32F05_param;
1218 else if (codecIsDacNode(pState, CODEC_NID(cmd)))
1219 *pResp = pState->pNodes[CODEC_NID(cmd)].dac.u32F05_param;
1220 else if (codecIsDigInPinNode(pState, CODEC_NID(cmd)))
1221 *pResp = pState->pNodes[CODEC_NID(cmd)].digin.u32F05_param;
1222 else if (codecIsAdcNode(pState, CODEC_NID(cmd)))
1223 *pResp = pState->pNodes[CODEC_NID(cmd)].adc.u32F05_param;
1224 else if (codecIsSpdifOutNode(pState, CODEC_NID(cmd)))
1225 *pResp = pState->pNodes[CODEC_NID(cmd)].spdifout.u32F05_param;
1226 else if (codecIsSpdifInNode(pState, CODEC_NID(cmd)))
1227 *pResp = pState->pNodes[CODEC_NID(cmd)].spdifin.u32F05_param;
1228 else if (codecIsReservedNode(pState, CODEC_NID(cmd)))
1229 *pResp = pState->pNodes[CODEC_NID(cmd)].reserved.u32F05_param;
1230 return VINF_SUCCESS;
1231}
1232
1233/* 705 */
1234
1235static inline void codecPropogatePowerState(uint32_t *pu32F05_param)
1236{
1237 Assert(pu32F05_param);
1238 if (!pu32F05_param)
1239 return;
1240 bool fReset = CODEC_F05_IS_RESET(*pu32F05_param);
1241 bool fStopOk = CODEC_F05_IS_STOPOK(*pu32F05_param);
1242 uint8_t u8SetPowerState = CODEC_F05_SET(*pu32F05_param);
1243 *pu32F05_param = CODEC_MAKE_F05(fReset, fStopOk, 0, u8SetPowerState, u8SetPowerState);
1244}
1245
1246static int codecSetPowerState(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1247{
1248 Assert((CODEC_CAD(cmd) == pState->id));
1249 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1250 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1251 {
1252 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1253 return VINF_SUCCESS;
1254 }
1255 uint32_t *pu32Reg = NULL;
1256 *pResp = 0;
1257 if (CODEC_NID(cmd) == 1 /* AFG */)
1258 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].afg.u32F05_param;
1259 else if (codecIsDacNode(pState, CODEC_NID(cmd)))
1260 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].dac.u32F05_param;
1261 else if (codecIsDigInPinNode(pState, CODEC_NID(cmd)))
1262 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].digin.u32F05_param;
1263 else if (codecIsAdcNode(pState, CODEC_NID(cmd)))
1264 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].adc.u32F05_param;
1265 else if (codecIsSpdifOutNode(pState, CODEC_NID(cmd)))
1266 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].spdifout.u32F05_param;
1267 else if (codecIsSpdifInNode(pState, CODEC_NID(cmd)))
1268 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].spdifin.u32F05_param;
1269 else if (codecIsReservedNode(pState, CODEC_NID(cmd)))
1270 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].reserved.u32F05_param;
1271 Assert((pu32Reg));
1272 if (!pu32Reg)
1273 return VINF_SUCCESS;
1274
1275 bool fReset = CODEC_F05_IS_RESET(*pu32Reg);
1276 bool fStopOk = CODEC_F05_IS_STOPOK(*pu32Reg);
1277
1278 if (CODEC_NID(cmd) != 1 /* AFG */)
1279 {
1280 /*
1281 * We shouldn't propogate actual power state, which actual for AFG
1282 */
1283 *pu32Reg = CODEC_MAKE_F05(fReset, fStopOk, 0,
1284 CODEC_F05_ACT(pState->pNodes[1].afg.u32F05_param),
1285 CODEC_F05_SET(cmd));
1286 }
1287
1288 /* Propagate next power state only if AFG is on or verb modifies AFG power state */
1289 if ( CODEC_NID(cmd) == 1 /* AFG */
1290 || !CODEC_F05_ACT(pState->pNodes[1].afg.u32F05_param))
1291 {
1292 *pu32Reg = CODEC_MAKE_F05(fReset, fStopOk, 0, CODEC_F05_SET(cmd), CODEC_F05_SET(cmd));
1293 if ( CODEC_NID(cmd) == 1 /* AFG */
1294 && (CODEC_F05_SET(cmd)) == CODEC_F05_D0)
1295 {
1296 /* now we're powered on AFG and may propogate power states on nodes */
1297 const uint8_t *pu8NodeIndex = &pState->au8Dacs[0];
1298 while (*(++pu8NodeIndex))
1299 codecPropogatePowerState(&pState->pNodes[*pu8NodeIndex].dac.u32F05_param);
1300
1301 pu8NodeIndex = &pState->au8Adcs[0];
1302 while (*(++pu8NodeIndex))
1303 codecPropogatePowerState(&pState->pNodes[*pu8NodeIndex].adc.u32F05_param);
1304
1305 pu8NodeIndex = &pState->au8DigInPins[0];
1306 while (*(++pu8NodeIndex))
1307 codecPropogatePowerState(&pState->pNodes[*pu8NodeIndex].digin.u32F05_param);
1308 }
1309 }
1310 return VINF_SUCCESS;
1311}
1312
1313static int codecGetStreamId(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 if (codecIsDacNode(pState, CODEC_NID(cmd)))
1324 *pResp = pState->pNodes[CODEC_NID(cmd)].dac.u32F06_param;
1325 else if (codecIsAdcNode(pState, CODEC_NID(cmd)))
1326 *pResp = pState->pNodes[CODEC_NID(cmd)].adc.u32F06_param;
1327 else if (codecIsSpdifInNode(pState, CODEC_NID(cmd)))
1328 *pResp = pState->pNodes[CODEC_NID(cmd)].spdifin.u32F06_param;
1329 else if (codecIsSpdifOutNode(pState, CODEC_NID(cmd)))
1330 *pResp = pState->pNodes[CODEC_NID(cmd)].spdifout.u32F06_param;
1331 else if (CODEC_NID(cmd) == 0x1A)
1332 *pResp = pState->pNodes[CODEC_NID(cmd)].reserved.u32F06_param;
1333 return VINF_SUCCESS;
1334}
1335static int codecSetStreamId(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1336{
1337 Assert((CODEC_CAD(cmd) == pState->id));
1338 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1339 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1340 {
1341 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1342 return VINF_SUCCESS;
1343 }
1344 *pResp = 0;
1345 uint32_t *pu32addr = NULL;
1346 *pResp = 0;
1347 if (codecIsDacNode(pState, CODEC_NID(cmd)))
1348 pu32addr = &pState->pNodes[CODEC_NID(cmd)].dac.u32F06_param;
1349 else if (codecIsAdcNode(pState, CODEC_NID(cmd)))
1350 pu32addr = &pState->pNodes[CODEC_NID(cmd)].adc.u32F06_param;
1351 else if (codecIsSpdifOutNode(pState, CODEC_NID(cmd)))
1352 pu32addr = &pState->pNodes[CODEC_NID(cmd)].spdifout.u32F06_param;
1353 else if (codecIsSpdifInNode(pState, CODEC_NID(cmd)))
1354 pu32addr = &pState->pNodes[CODEC_NID(cmd)].spdifin.u32F06_param;
1355 else if (codecIsReservedNode(pState, CODEC_NID(cmd)))
1356 pu32addr = &pState->pNodes[CODEC_NID(cmd)].reserved.u32F06_param;
1357 Assert((pu32addr));
1358 if (pu32addr)
1359 codecSetRegisterU8(pu32addr, cmd, 0);
1360 return VINF_SUCCESS;
1361}
1362
1363static int codecGetConverterFormat(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1364{
1365 Assert((CODEC_CAD(cmd) == pState->id));
1366 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1367 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1368 {
1369 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1370 return VINF_SUCCESS;
1371 }
1372 *pResp = 0;
1373 if (codecIsDacNode(pState, CODEC_NID(cmd)))
1374 *pResp = pState->pNodes[CODEC_NID(cmd)].dac.u32A_param;
1375 else if (codecIsAdcNode(pState, CODEC_NID(cmd)))
1376 *pResp = pState->pNodes[CODEC_NID(cmd)].adc.u32A_param;
1377 else if (codecIsSpdifOutNode(pState, CODEC_NID(cmd)))
1378 *pResp = pState->pNodes[CODEC_NID(cmd)].spdifout.u32A_param;
1379 else if (codecIsSpdifInNode(pState, CODEC_NID(cmd)))
1380 *pResp = pState->pNodes[CODEC_NID(cmd)].spdifin.u32A_param;
1381 return VINF_SUCCESS;
1382}
1383
1384static int codecSetConverterFormat(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1385{
1386 Assert((CODEC_CAD(cmd) == pState->id));
1387 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1388 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1389 {
1390 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1391 return VINF_SUCCESS;
1392 }
1393 *pResp = 0;
1394 if (codecIsDacNode(pState, CODEC_NID(cmd)))
1395 codecSetRegisterU16(&pState->pNodes[CODEC_NID(cmd)].dac.u32A_param, cmd, 0);
1396 else if (codecIsAdcNode(pState, CODEC_NID(cmd)))
1397 codecSetRegisterU16(&pState->pNodes[CODEC_NID(cmd)].adc.u32A_param, cmd, 0);
1398 else if (codecIsSpdifOutNode(pState, CODEC_NID(cmd)))
1399 codecSetRegisterU16(&pState->pNodes[CODEC_NID(cmd)].spdifout.u32A_param, cmd, 0);
1400 else if (codecIsSpdifInNode(pState, CODEC_NID(cmd)))
1401 codecSetRegisterU16(&pState->pNodes[CODEC_NID(cmd)].spdifin.u32A_param, cmd, 0);
1402 return VINF_SUCCESS;
1403}
1404
1405/* F0C */
1406static int codecGetEAPD_BTLEnabled(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1407{
1408 Assert((CODEC_CAD(cmd) == pState->id));
1409 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1410 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1411 {
1412 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1413 return VINF_SUCCESS;
1414 }
1415 *pResp = 0;
1416 if (codecIsAdcVolNode(pState, CODEC_NID(cmd)))
1417 *pResp = pState->pNodes[CODEC_NID(cmd)].adcvol.u32F0c_param;
1418 else if (codecIsDacNode(pState, CODEC_NID(cmd)))
1419 *pResp = pState->pNodes[CODEC_NID(cmd)].dac.u32F0c_param;
1420 else if (codecIsDigInPinNode(pState, CODEC_NID(cmd)))
1421 *pResp = pState->pNodes[CODEC_NID(cmd)].digin.u32F0c_param;
1422 return VINF_SUCCESS;
1423}
1424
1425/* 70C */
1426static int codecSetEAPD_BTLEnabled(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1427{
1428 Assert((CODEC_CAD(cmd) == pState->id));
1429 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1430 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1431 {
1432 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1433 return VINF_SUCCESS;
1434 }
1435 *pResp = 0;
1436 uint32_t *pu32Reg = NULL;
1437 if (codecIsAdcVolNode(pState, CODEC_NID(cmd)))
1438 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].adcvol.u32F0c_param;
1439 else if (codecIsDacNode(pState, CODEC_NID(cmd)))
1440 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].dac.u32F0c_param;
1441 else if (codecIsDigInPinNode(pState, CODEC_NID(cmd)))
1442 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].digin.u32F0c_param;
1443 *pResp = 0;
1444 Assert((pu32Reg));
1445 if (pu32Reg)
1446 codecSetRegisterU8(pu32Reg, cmd, 0);
1447 return VINF_SUCCESS;
1448}
1449
1450/* F0F */
1451static int codecGetVolumeKnobCtrl(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1452{
1453 Assert((CODEC_CAD(cmd) == pState->id));
1454 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1455 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1456 {
1457 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1458 return VINF_SUCCESS;
1459 }
1460 *pResp = 0;
1461 if (codecIsVolKnobNode(pState, CODEC_NID(cmd)))
1462 *pResp = pState->pNodes[CODEC_NID(cmd)].volumeKnob.u32F0f_param;
1463 return VINF_SUCCESS;
1464}
1465
1466/* 70F */
1467static int codecSetVolumeKnobCtrl(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1468{
1469 Assert((CODEC_CAD(cmd) == pState->id));
1470 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1471 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1472 {
1473 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1474 return VINF_SUCCESS;
1475 }
1476 uint32_t *pu32Reg = NULL;
1477 *pResp = 0;
1478 if (codecIsVolKnobNode(pState, CODEC_NID(cmd)))
1479 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].volumeKnob.u32F0f_param;
1480 Assert((pu32Reg));
1481 if (pu32Reg)
1482 codecSetRegisterU8(pu32Reg, cmd, 0);
1483 return VINF_SUCCESS;
1484}
1485
1486/* F17 */
1487static int codecGetGPIOUnsolisted (struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1488{
1489 Assert((CODEC_CAD(cmd) == pState->id));
1490 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1491 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1492 {
1493 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1494 return VINF_SUCCESS;
1495 }
1496 *pResp = 0;
1497 /* note: this is true for ALC885 */
1498 if (CODEC_NID(cmd) == 0x1 /* AFG */)
1499 *pResp = pState->pNodes[1].afg.u32F17_param;
1500 return VINF_SUCCESS;
1501}
1502
1503/* 717 */
1504static int codecSetGPIOUnsolisted (struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1505{
1506 Assert((CODEC_CAD(cmd) == pState->id));
1507 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1508 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1509 {
1510 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1511 return VINF_SUCCESS;
1512 }
1513 uint32_t *pu32Reg = NULL;
1514 *pResp = 0;
1515 if (CODEC_NID(cmd) == 1 /* AFG */)
1516 pu32Reg = &pState->pNodes[1].afg.u32F17_param;
1517 Assert((pu32Reg));
1518 if (pu32Reg)
1519 codecSetRegisterU8(pu32Reg, cmd, 0);
1520 return VINF_SUCCESS;
1521}
1522
1523/* F1C */
1524static int codecGetConfig (struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1525{
1526 Assert((CODEC_CAD(cmd) == pState->id));
1527 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1528 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1529 {
1530 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1531 return VINF_SUCCESS;
1532 }
1533 *pResp = 0;
1534 if (codecIsPortNode(pState, CODEC_NID(cmd)))
1535 *pResp = pState->pNodes[CODEC_NID(cmd)].port.u32F1c_param;
1536 else if (codecIsDigOutPinNode(pState, CODEC_NID(cmd)))
1537 *pResp = pState->pNodes[CODEC_NID(cmd)].digout.u32F1c_param;
1538 else if (codecIsDigInPinNode(pState, CODEC_NID(cmd)))
1539 *pResp = pState->pNodes[CODEC_NID(cmd)].digin.u32F1c_param;
1540 else if (codecIsPcbeepNode(pState, CODEC_NID(cmd)))
1541 *pResp = pState->pNodes[CODEC_NID(cmd)].pcbeep.u32F1c_param;
1542 else if (codecIsCdNode(pState, CODEC_NID(cmd)))
1543 *pResp = pState->pNodes[CODEC_NID(cmd)].cdnode.u32F1c_param;
1544 else if (codecIsReservedNode(pState, CODEC_NID(cmd)))
1545 *pResp = pState->pNodes[CODEC_NID(cmd)].reserved.u32F1c_param;
1546 return VINF_SUCCESS;
1547}
1548static int codecSetConfigX(struct CODECState *pState, uint32_t cmd, uint8_t u8Offset)
1549{
1550 Assert((CODEC_CAD(cmd) == pState->id));
1551 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1552 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1553 {
1554 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1555 return VINF_SUCCESS;
1556 }
1557 uint32_t *pu32Reg = NULL;
1558 if (codecIsPortNode(pState, CODEC_NID(cmd)))
1559 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].port.u32F1c_param;
1560 else if (codecIsDigInPinNode(pState, CODEC_NID(cmd)))
1561 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].digin.u32F1c_param;
1562 else if (codecIsDigOutPinNode(pState, CODEC_NID(cmd)))
1563 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].digout.u32F1c_param;
1564 else if (codecIsCdNode(pState, CODEC_NID(cmd)))
1565 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].cdnode.u32F1c_param;
1566 else if (codecIsPcbeepNode(pState, CODEC_NID(cmd)))
1567 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].pcbeep.u32F1c_param;
1568 else if (codecIsReservedNode(pState, CODEC_NID(cmd)))
1569 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].reserved.u32F1c_param;
1570 Assert((pu32Reg));
1571 if (pu32Reg)
1572 codecSetRegisterU8(pu32Reg, cmd, u8Offset);
1573 return VINF_SUCCESS;
1574}
1575/* 71C */
1576static int codecSetConfig0 (struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1577{
1578 *pResp = 0;
1579 return codecSetConfigX(pState, cmd, 0);
1580}
1581/* 71D */
1582static int codecSetConfig1 (struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1583{
1584 *pResp = 0;
1585 return codecSetConfigX(pState, cmd, 8);
1586}
1587/* 71E */
1588static int codecSetConfig2 (struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1589{
1590 *pResp = 0;
1591 return codecSetConfigX(pState, cmd, 16);
1592}
1593/* 71E */
1594static int codecSetConfig3 (struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1595{
1596 *pResp = 0;
1597 return codecSetConfigX(pState, cmd, 24);
1598}
1599
1600
1601static int codecToAudVolume(AMPLIFIER *pAmp, audmixerctl_t mt)
1602{
1603 uint32_t dir = AMPLIFIER_OUT;
1604 switch (mt)
1605 {
1606 case AUD_MIXER_VOLUME:
1607 case AUD_MIXER_PCM:
1608 dir = AMPLIFIER_OUT;
1609 break;
1610 case AUD_MIXER_LINE_IN:
1611 dir = AMPLIFIER_IN;
1612 break;
1613 }
1614 int mute = AMPLIFIER_REGISTER(*pAmp, dir, AMPLIFIER_LEFT, 0) & RT_BIT(7);
1615 mute |= AMPLIFIER_REGISTER(*pAmp, dir, AMPLIFIER_RIGHT, 0) & RT_BIT(7);
1616 mute >>=7;
1617 mute &= 0x1;
1618 uint8_t lVol = AMPLIFIER_REGISTER(*pAmp, dir, AMPLIFIER_LEFT, 0) & 0x7f;
1619 uint8_t rVol = AMPLIFIER_REGISTER(*pAmp, dir, AMPLIFIER_RIGHT, 0) & 0x7f;
1620 AUD_set_volume(mt, &mute, &lVol, &rVol);
1621 return VINF_SUCCESS;
1622}
1623
1624static CODECVERB CODECVERBS[] =
1625{
1626/* verb | verb mask | callback */
1627/* ----------- -------------------- ----------------------- */
1628 {0x000F0000, CODEC_VERB_8BIT_CMD , codecGetParameter },
1629 {0x000F0100, CODEC_VERB_8BIT_CMD , codecGetConSelectCtrl },
1630 {0x00070100, CODEC_VERB_8BIT_CMD , codecSetConSelectCtrl },
1631 {0x000F0600, CODEC_VERB_8BIT_CMD , codecGetStreamId },
1632 {0x00070600, CODEC_VERB_8BIT_CMD , codecSetStreamId },
1633 {0x000F0700, CODEC_VERB_8BIT_CMD , codecGetPinCtrl },
1634 {0x00070700, CODEC_VERB_8BIT_CMD , codecSetPinCtrl },
1635 {0x000F0800, CODEC_VERB_8BIT_CMD , codecGetUnsolicitedEnabled },
1636 {0x00070800, CODEC_VERB_8BIT_CMD , codecSetUnsolicitedEnabled },
1637 {0x000F0900, CODEC_VERB_8BIT_CMD , codecGetPinSense },
1638 {0x00070900, CODEC_VERB_8BIT_CMD , codecSetPinSense },
1639 {0x000F0200, CODEC_VERB_8BIT_CMD , codecGetConnectionListEntry },
1640 {0x000F0300, CODEC_VERB_8BIT_CMD , codecGetProcessingState },
1641 {0x00070300, CODEC_VERB_8BIT_CMD , codecSetProcessingState },
1642 {0x000F0D00, CODEC_VERB_8BIT_CMD , codecGetDigitalConverter },
1643 {0x00070D00, CODEC_VERB_8BIT_CMD , codecSetDigitalConverter1 },
1644 {0x00070E00, CODEC_VERB_8BIT_CMD , codecSetDigitalConverter2 },
1645 {0x000F2000, CODEC_VERB_8BIT_CMD , codecGetSubId },
1646 {0x00072000, CODEC_VERB_8BIT_CMD , codecSetSubId0 },
1647 {0x00072100, CODEC_VERB_8BIT_CMD , codecSetSubId1 },
1648 {0x00072200, CODEC_VERB_8BIT_CMD , codecSetSubId2 },
1649 {0x00072300, CODEC_VERB_8BIT_CMD , codecSetSubId3 },
1650 {0x0007FF00, CODEC_VERB_8BIT_CMD , codecReset },
1651 {0x000F0500, CODEC_VERB_8BIT_CMD , codecGetPowerState },
1652 {0x00070500, CODEC_VERB_8BIT_CMD , codecSetPowerState },
1653 {0x000F0C00, CODEC_VERB_8BIT_CMD , codecGetEAPD_BTLEnabled },
1654 {0x00070C00, CODEC_VERB_8BIT_CMD , codecSetEAPD_BTLEnabled },
1655 {0x000F0F00, CODEC_VERB_8BIT_CMD , codecGetVolumeKnobCtrl },
1656 {0x00070F00, CODEC_VERB_8BIT_CMD , codecSetVolumeKnobCtrl },
1657 {0x000F1700, CODEC_VERB_8BIT_CMD , codecGetGPIOUnsolisted },
1658 {0x00071700, CODEC_VERB_8BIT_CMD , codecSetGPIOUnsolisted },
1659 {0x000F1C00, CODEC_VERB_8BIT_CMD , codecGetConfig },
1660 {0x00071C00, CODEC_VERB_8BIT_CMD , codecSetConfig0 },
1661 {0x00071D00, CODEC_VERB_8BIT_CMD , codecSetConfig1 },
1662 {0x00071E00, CODEC_VERB_8BIT_CMD , codecSetConfig2 },
1663 {0x00071F00, CODEC_VERB_8BIT_CMD , codecSetConfig3 },
1664 {0x000A0000, CODEC_VERB_16BIT_CMD, codecGetConverterFormat },
1665 {0x00020000, CODEC_VERB_16BIT_CMD, codecSetConverterFormat },
1666 {0x000B0000, CODEC_VERB_16BIT_CMD, codecGetAmplifier },
1667 {0x00030000, CODEC_VERB_16BIT_CMD, codecSetAmplifier },
1668};
1669
1670static int codecLookup(CODECState *pState, uint32_t cmd, PPFNCODECVERBPROCESSOR pfn)
1671{
1672 int rc = VINF_SUCCESS;
1673 Assert(CODEC_CAD(cmd) == pState->id);
1674 if (codecIsReservedNode(pState, CODEC_NID(cmd)))
1675 {
1676 Log(("HDAcodec: cmd %x was addressed to reserved node\n", cmd));
1677 }
1678 if ( CODEC_VERBDATA(cmd) == 0
1679 || CODEC_NID(cmd) >= pState->cTotalNodes)
1680 {
1681 *pfn = codecUnimplemented;
1682 //** @todo r=michaln: There needs to be a counter to avoid log flooding (see e.g. DevRTC.cpp)
1683 Log(("HDAcodec: cmd %x was ignored\n", cmd));
1684 return VINF_SUCCESS;
1685 }
1686 for (int i = 0; i < pState->cVerbs; ++i)
1687 {
1688 if ((CODEC_VERBDATA(cmd) & pState->pVerbs[i].mask) == pState->pVerbs[i].verb)
1689 {
1690 *pfn = pState->pVerbs[i].pfn;
1691 return VINF_SUCCESS;
1692 }
1693 }
1694 *pfn = codecUnimplemented;
1695 Log(("HDAcodec: callback for %x wasn't found\n", CODEC_VERBDATA(cmd)));
1696 return rc;
1697}
1698
1699static void pi_callback (void *opaque, int avail)
1700{
1701 CODECState *pState = (CODECState *)opaque;
1702 pState->pfnTransfer(pState, PI_INDEX, avail);
1703}
1704
1705static void po_callback (void *opaque, int avail)
1706{
1707 CODECState *pState = (CODECState *)opaque;
1708 pState->pfnTransfer(pState, PO_INDEX, avail);
1709}
1710
1711/**
1712 *
1713 * routines open one of the voices (IN, OUT) with corresponding parameters.
1714 * this routine could be called from HDA on setting/resseting sound format.
1715 *
1716 * @todo: probably passed settings should be verified (if AFG's declared proposed format) before enabling.
1717 */
1718int codecOpenVoice(CODECState *pState, ENMSOUNDSOURCE enmSoundSource, audsettings_t *pAudioSettings)
1719{
1720 int rc = 0;
1721 Assert((pState && pAudioSettings));
1722 if ( !pState
1723 || !pAudioSettings)
1724 return -1;
1725 switch (enmSoundSource)
1726 {
1727 case PI_INDEX:
1728 pState->SwVoiceIn = AUD_open_in(&pState->card, pState->SwVoiceIn, "hda.in", pState, pi_callback, pAudioSettings);
1729 rc = pState->SwVoiceIn ? 0 : 1;
1730 break;
1731 case PO_INDEX:
1732 pState->SwVoiceOut = AUD_open_out(&pState->card, pState->SwVoiceOut, "hda.out", pState, po_callback, pAudioSettings);
1733 rc = pState->SwVoiceOut ? 0 : 1;
1734 break;
1735 default:
1736 return -1;
1737 }
1738 if (!rc)
1739 LogRel(("HDAcodec: can't open %s fmt(freq: %d)\n",
1740 enmSoundSource == PI_INDEX? "in" : "out",
1741 pAudioSettings->freq));
1742 return rc;
1743}
1744
1745int codecConstruct(PPDMDEVINS pDevIns, CODECState *pState, PCFGMNODE pCfgHandle)
1746{
1747 audsettings_t as;
1748 int rc;
1749 pState->pVerbs = (CODECVERB *)&CODECVERBS;
1750 pState->cVerbs = sizeof(CODECVERBS)/sizeof(CODECVERB);
1751 pState->pfnLookup = codecLookup;
1752 rc = stac9220Construct(pState);
1753 AssertRC(rc);
1754 /* common root node initializers */
1755 pState->pNodes[0].node.au32F00_param[0] = CODEC_MAKE_F00_00(pState->u16VendorId, pState->u16DeviceId);
1756 pState->pNodes[0].node.au32F00_param[4] = CODEC_MAKE_F00_04(0x1, 0x1);
1757 /* common AFG node initializers */
1758 pState->pNodes[1].node.au32F00_param[4] = CODEC_MAKE_F00_04(0x2, pState->cTotalNodes - 2);
1759 pState->pNodes[1].node.au32F00_param[5] = CODEC_MAKE_F00_05(1, CODEC_F00_05_AFG);
1760 pState->pNodes[1].afg.u32F20_param = CODEC_MAKE_F20(pState->u16VendorId, pState->u8BSKU, pState->u8AssemblyId);
1761
1762 //** @todo r=michaln: Was this meant to be 'HDA' or something like that? (AC'97 was on ICH0)
1763 AUD_register_card ("ICH0", &pState->card);
1764
1765 /* 44.1 kHz */
1766 as.freq = 44100;
1767 as.nchannels = 2;
1768 as.fmt = AUD_FMT_S16;
1769 as.endianness = 0;
1770
1771 pState->pNodes[1].node.au32F00_param[0xA] = CODEC_F00_0A_16_BIT;
1772 codecOpenVoice(pState, PI_INDEX, &as);
1773 codecOpenVoice(pState, PO_INDEX, &as);
1774 pState->pNodes[1].node.au32F00_param[0xA] |= CODEC_F00_0A_44_1KHZ;
1775
1776 uint8_t i;
1777 Assert(pState->pNodes);
1778 Assert(pState->pfnCodecNodeReset);
1779 for (i = 0; i < pState->cTotalNodes; ++i)
1780 {
1781 pState->pfnCodecNodeReset(pState, i, &pState->pNodes[i]);
1782 }
1783
1784 codecToAudVolume(&pState->pNodes[pState->u8DacLineOut].dac.B_params, AUD_MIXER_VOLUME);
1785 codecToAudVolume(&pState->pNodes[pState->u8AdcVolsLineIn].adcvol.B_params, AUD_MIXER_LINE_IN);
1786
1787 /* If no host voices were created, then fallback to nul audio. */
1788 if (!AUD_is_host_voice_in_ok(pState->SwVoiceIn))
1789 LogRel (("HDA: WARNING: Unable to open PCM IN!\n"));
1790 if (!AUD_is_host_voice_out_ok(pState->SwVoiceOut))
1791 LogRel (("HDA: WARNING: Unable to open PCM OUT!\n"));
1792
1793 if ( !AUD_is_host_voice_in_ok(pState->SwVoiceIn)
1794 && !AUD_is_host_voice_out_ok(pState->SwVoiceOut))
1795 {
1796 /* Was not able initialize *any* voice. Select the NULL audio driver instead */
1797 AUD_close_in (&pState->card, pState->SwVoiceIn);
1798 AUD_close_out (&pState->card, pState->SwVoiceOut);
1799 pState->SwVoiceOut = NULL;
1800 pState->SwVoiceIn = NULL;
1801 AUD_init_null ();
1802
1803 PDMDevHlpVMSetRuntimeError (pDevIns, 0 /*fFlags*/, "HostAudioNotResponding",
1804 N_ ("No audio devices could be opened. Selecting the NULL audio backend "
1805 "with the consequence that no sound is audible"));
1806 }
1807 else if ( !AUD_is_host_voice_in_ok(pState->SwVoiceIn)
1808 || !AUD_is_host_voice_out_ok(pState->SwVoiceOut))
1809 {
1810 char szMissingVoices[128];
1811 size_t len = 0;
1812 if (!AUD_is_host_voice_in_ok(pState->SwVoiceIn))
1813 len = RTStrPrintf (szMissingVoices, sizeof(szMissingVoices), "PCM_in");
1814 if (!AUD_is_host_voice_out_ok(pState->SwVoiceOut))
1815 len += RTStrPrintf (szMissingVoices + len, sizeof(szMissingVoices) - len, len ? ", PCM_out" : "PCM_out");
1816
1817 PDMDevHlpVMSetRuntimeError (pDevIns, 0 /*fFlags*/, "HostAudioNotResponding",
1818 N_ ("Some audio devices (%s) could not be opened. Guest applications generating audio "
1819 "output or depending on audio input may hang. Make sure your host audio device "
1820 "is working properly. Check the logfile for error messages of the audio "
1821 "subsystem"), szMissingVoices);
1822 }
1823
1824 return VINF_SUCCESS;
1825}
1826int codecDestruct(CODECState *pCodecState)
1827{
1828 RTMemFree(pCodecState->pNodes);
1829 return VINF_SUCCESS;
1830}
1831
1832int codecSaveState(CODECState *pCodecState, PSSMHANDLE pSSMHandle)
1833{
1834 SSMR3PutMem (pSSMHandle, pCodecState->pNodes, sizeof(CODECNODE) * pCodecState->cTotalNodes);
1835 return VINF_SUCCESS;
1836}
1837
1838static DECLCALLBACK(int)codecLoadV1(PCODECState pCodecState, PSSMHANDLE pSSMHandle, size_t cbOffset, size_t alignment)
1839{
1840 size_t cbRawNodesV1 = (sizeof(CODECNODE) + cbOffset + alignment) * pCodecState->cTotalNodes;
1841 uint8_t *pu8RawNodesV1 = (uint8_t *)RTMemAlloc(cbRawNodesV1);
1842 uint8_t *pu8NodeV1 = NULL;
1843 int idxNode = 0;
1844 if (!pu8RawNodesV1)
1845 return VERR_NO_MEMORY;
1846 int rc = SSMR3GetMem (pSSMHandle, pu8RawNodesV1, cbRawNodesV1);
1847
1848 if (RT_FAILURE(rc))
1849 {
1850 RTMemFree(pu8RawNodesV1);
1851 AssertRCReturn(rc, rc);
1852 }
1853 pu8NodeV1 = &pu8RawNodesV1[0];
1854 for (idxNode = 0; idxNode < pCodecState->cTotalNodes; ++idxNode)
1855 {
1856 pCodecState->pNodes[idxNode].node.id = pu8NodeV1[0];
1857 memcpy(pCodecState->pNodes[idxNode].node.au32F00_param,
1858 pu8NodeV1 + RT_OFFSETOF(CODECCOMMONNODE, au32F00_param) + alignment,
1859 sizeof(CODECNODE) - RT_OFFSETOF(CODECCOMMONNODE,au32F00_param));
1860 pu8NodeV1 += sizeof(CODECNODE) + cbOffset;
1861 }
1862
1863 RTMemFree(pu8RawNodesV1);
1864 return rc;
1865}
1866
1867int codecLoadState(CODECState *pCodecState, PSSMHANDLE pSSMHandle, uint32_t uVersion)
1868{
1869 int rc;
1870 if (uVersion == HDA_SSM_VERSION_1)
1871 {
1872#if RT_ARCH_X86
1873 if (SSMR3HandleHostBits(pSSMHandle) == 32)
1874 rc = codecLoadV1(pCodecState, pSSMHandle, sizeof(long), 0);
1875 else
1876 rc = codecLoadV1(pCodecState, pSSMHandle, sizeof(uint64_t), 4);
1877#else
1878 if (SSMR3HandleHostBits(pSSMHandle) == 64)
1879 rc = codecLoadV1(pCodecState, pSSMHandle, sizeof(long), 4);
1880 else
1881 rc = codecLoadV1(pCodecState, pSSMHandle, sizeof(uint32_t), 0);
1882#endif
1883 }
1884 else
1885 rc = SSMR3GetMem (pSSMHandle, pCodecState->pNodes, sizeof(CODECNODE) * pCodecState->cTotalNodes);
1886 if (codecIsDacNode(pCodecState, pCodecState->u8DacLineOut))
1887 codecToAudVolume(&pCodecState->pNodes[pCodecState->u8DacLineOut].dac.B_params, AUD_MIXER_VOLUME);
1888 else if (codecIsSpdifOutNode(pCodecState, pCodecState->u8DacLineOut))
1889 codecToAudVolume(&pCodecState->pNodes[pCodecState->u8DacLineOut].spdifout.B_params, AUD_MIXER_VOLUME);
1890 codecToAudVolume(&pCodecState->pNodes[pCodecState->u8AdcVolsLineIn].adcvol.B_params, AUD_MIXER_LINE_IN);
1891 return rc;
1892}
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