VirtualBox

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

Last change on this file since 39603 was 39368, checked in by vboxsync, 13 years ago

VBOX_FULL_VERSION_MAKE: fixed copy & past bug messing up the build part.
SSM: Return VERR_SSM_LOADED_TOO_LITTLE if there is data in the buffer, not only if there are more records before the unit end.
HDA: Fixed the saved state loading stuff again. Canged the saved state to mark up arrays with lengths and serialize using structure puts.

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