VirtualBox

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

Last change on this file since 40532 was 40111, checked in by vboxsync, 13 years ago

Audio/HDA: Don't bother with resseting at all if codec reset routine isn't specified.

  • 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 40111 2012-02-14 01:49:30Z 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 && pState->pfnCodecNodeReset)
1269 {
1270 uint8_t i;
1271 Log(("HDAcodec: enters reset\n"));
1272 Assert(pState->pfnCodecNodeReset);
1273 for (i = 0; i < pState->cTotalNodes; ++i)
1274 {
1275 pState->pfnCodecNodeReset(pState, i, &pState->pNodes[i]);
1276 }
1277 pState->fInReset = false;
1278 Log(("HDAcodec: exits reset\n"));
1279 }
1280 *pResp = 0;
1281 return VINF_SUCCESS;
1282}
1283
1284/* F05 */
1285static int codecGetPowerState(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1286{
1287 Assert((CODEC_CAD(cmd) == pState->id));
1288 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1289 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1290 {
1291 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1292 return VINF_SUCCESS;
1293 }
1294 *pResp = 0;
1295 if (CODEC_NID(cmd) == 1 /* AFG */)
1296 *pResp = pState->pNodes[CODEC_NID(cmd)].afg.u32F05_param;
1297 else if (codecIsDacNode(pState, CODEC_NID(cmd)))
1298 *pResp = pState->pNodes[CODEC_NID(cmd)].dac.u32F05_param;
1299 else if (codecIsDigInPinNode(pState, CODEC_NID(cmd)))
1300 *pResp = pState->pNodes[CODEC_NID(cmd)].digin.u32F05_param;
1301 else if (codecIsAdcNode(pState, CODEC_NID(cmd)))
1302 *pResp = pState->pNodes[CODEC_NID(cmd)].adc.u32F05_param;
1303 else if (codecIsSpdifOutNode(pState, CODEC_NID(cmd)))
1304 *pResp = pState->pNodes[CODEC_NID(cmd)].spdifout.u32F05_param;
1305 else if (codecIsSpdifInNode(pState, CODEC_NID(cmd)))
1306 *pResp = pState->pNodes[CODEC_NID(cmd)].spdifin.u32F05_param;
1307 else if (codecIsReservedNode(pState, CODEC_NID(cmd)))
1308 *pResp = pState->pNodes[CODEC_NID(cmd)].reserved.u32F05_param;
1309 return VINF_SUCCESS;
1310}
1311
1312/* 705 */
1313
1314static inline void codecPropogatePowerState(uint32_t *pu32F05_param)
1315{
1316 Assert(pu32F05_param);
1317 if (!pu32F05_param)
1318 return;
1319 bool fReset = CODEC_F05_IS_RESET(*pu32F05_param);
1320 bool fStopOk = CODEC_F05_IS_STOPOK(*pu32F05_param);
1321 uint8_t u8SetPowerState = CODEC_F05_SET(*pu32F05_param);
1322 *pu32F05_param = CODEC_MAKE_F05(fReset, fStopOk, 0, u8SetPowerState, u8SetPowerState);
1323}
1324
1325static int codecSetPowerState(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1326{
1327 Assert((CODEC_CAD(cmd) == pState->id));
1328 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1329 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1330 {
1331 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1332 return VINF_SUCCESS;
1333 }
1334 uint32_t *pu32Reg = NULL;
1335 *pResp = 0;
1336 if (CODEC_NID(cmd) == 1 /* AFG */)
1337 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].afg.u32F05_param;
1338 else if (codecIsDacNode(pState, CODEC_NID(cmd)))
1339 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].dac.u32F05_param;
1340 else if (codecIsDigInPinNode(pState, CODEC_NID(cmd)))
1341 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].digin.u32F05_param;
1342 else if (codecIsAdcNode(pState, CODEC_NID(cmd)))
1343 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].adc.u32F05_param;
1344 else if (codecIsSpdifOutNode(pState, CODEC_NID(cmd)))
1345 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].spdifout.u32F05_param;
1346 else if (codecIsSpdifInNode(pState, CODEC_NID(cmd)))
1347 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].spdifin.u32F05_param;
1348 else if (codecIsReservedNode(pState, CODEC_NID(cmd)))
1349 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].reserved.u32F05_param;
1350 Assert((pu32Reg));
1351 if (!pu32Reg)
1352 return VINF_SUCCESS;
1353
1354 bool fReset = CODEC_F05_IS_RESET(*pu32Reg);
1355 bool fStopOk = CODEC_F05_IS_STOPOK(*pu32Reg);
1356
1357 if (CODEC_NID(cmd) != 1 /* AFG */)
1358 {
1359 /*
1360 * We shouldn't propogate actual power state, which actual for AFG
1361 */
1362 *pu32Reg = CODEC_MAKE_F05(fReset, fStopOk, 0,
1363 CODEC_F05_ACT(pState->pNodes[1].afg.u32F05_param),
1364 CODEC_F05_SET(cmd));
1365 }
1366
1367 /* Propagate next power state only if AFG is on or verb modifies AFG power state */
1368 if ( CODEC_NID(cmd) == 1 /* AFG */
1369 || !CODEC_F05_ACT(pState->pNodes[1].afg.u32F05_param))
1370 {
1371 *pu32Reg = CODEC_MAKE_F05(fReset, fStopOk, 0, CODEC_F05_SET(cmd), CODEC_F05_SET(cmd));
1372 if ( CODEC_NID(cmd) == 1 /* AFG */
1373 && (CODEC_F05_SET(cmd)) == CODEC_F05_D0)
1374 {
1375 /* now we're powered on AFG and may propogate power states on nodes */
1376 const uint8_t *pu8NodeIndex = &pState->au8Dacs[0];
1377 while (*(++pu8NodeIndex))
1378 codecPropogatePowerState(&pState->pNodes[*pu8NodeIndex].dac.u32F05_param);
1379
1380 pu8NodeIndex = &pState->au8Adcs[0];
1381 while (*(++pu8NodeIndex))
1382 codecPropogatePowerState(&pState->pNodes[*pu8NodeIndex].adc.u32F05_param);
1383
1384 pu8NodeIndex = &pState->au8DigInPins[0];
1385 while (*(++pu8NodeIndex))
1386 codecPropogatePowerState(&pState->pNodes[*pu8NodeIndex].digin.u32F05_param);
1387 }
1388 }
1389 return VINF_SUCCESS;
1390}
1391
1392static int codecGetStreamId(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1393{
1394 Assert((CODEC_CAD(cmd) == pState->id));
1395 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1396 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1397 {
1398 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1399 return VINF_SUCCESS;
1400 }
1401 *pResp = 0;
1402 if (codecIsDacNode(pState, CODEC_NID(cmd)))
1403 *pResp = pState->pNodes[CODEC_NID(cmd)].dac.u32F06_param;
1404 else if (codecIsAdcNode(pState, CODEC_NID(cmd)))
1405 *pResp = pState->pNodes[CODEC_NID(cmd)].adc.u32F06_param;
1406 else if (codecIsSpdifInNode(pState, CODEC_NID(cmd)))
1407 *pResp = pState->pNodes[CODEC_NID(cmd)].spdifin.u32F06_param;
1408 else if (codecIsSpdifOutNode(pState, CODEC_NID(cmd)))
1409 *pResp = pState->pNodes[CODEC_NID(cmd)].spdifout.u32F06_param;
1410 else if (CODEC_NID(cmd) == 0x1A)
1411 *pResp = pState->pNodes[CODEC_NID(cmd)].reserved.u32F06_param;
1412 return VINF_SUCCESS;
1413}
1414static int codecSetStreamId(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1415{
1416 Assert((CODEC_CAD(cmd) == pState->id));
1417 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1418 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1419 {
1420 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1421 return VINF_SUCCESS;
1422 }
1423 *pResp = 0;
1424 uint32_t *pu32addr = NULL;
1425 *pResp = 0;
1426 if (codecIsDacNode(pState, CODEC_NID(cmd)))
1427 pu32addr = &pState->pNodes[CODEC_NID(cmd)].dac.u32F06_param;
1428 else if (codecIsAdcNode(pState, CODEC_NID(cmd)))
1429 pu32addr = &pState->pNodes[CODEC_NID(cmd)].adc.u32F06_param;
1430 else if (codecIsSpdifOutNode(pState, CODEC_NID(cmd)))
1431 pu32addr = &pState->pNodes[CODEC_NID(cmd)].spdifout.u32F06_param;
1432 else if (codecIsSpdifInNode(pState, CODEC_NID(cmd)))
1433 pu32addr = &pState->pNodes[CODEC_NID(cmd)].spdifin.u32F06_param;
1434 else if (codecIsReservedNode(pState, CODEC_NID(cmd)))
1435 pu32addr = &pState->pNodes[CODEC_NID(cmd)].reserved.u32F06_param;
1436 Assert((pu32addr));
1437 if (pu32addr)
1438 codecSetRegisterU8(pu32addr, cmd, 0);
1439 return VINF_SUCCESS;
1440}
1441
1442static int codecGetConverterFormat(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1443{
1444 Assert((CODEC_CAD(cmd) == pState->id));
1445 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1446 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1447 {
1448 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1449 return VINF_SUCCESS;
1450 }
1451 *pResp = 0;
1452 if (codecIsDacNode(pState, CODEC_NID(cmd)))
1453 *pResp = pState->pNodes[CODEC_NID(cmd)].dac.u32A_param;
1454 else if (codecIsAdcNode(pState, CODEC_NID(cmd)))
1455 *pResp = pState->pNodes[CODEC_NID(cmd)].adc.u32A_param;
1456 else if (codecIsSpdifOutNode(pState, CODEC_NID(cmd)))
1457 *pResp = pState->pNodes[CODEC_NID(cmd)].spdifout.u32A_param;
1458 else if (codecIsSpdifInNode(pState, CODEC_NID(cmd)))
1459 *pResp = pState->pNodes[CODEC_NID(cmd)].spdifin.u32A_param;
1460 return VINF_SUCCESS;
1461}
1462
1463static int codecSetConverterFormat(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1464{
1465 Assert((CODEC_CAD(cmd) == pState->id));
1466 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1467 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1468 {
1469 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1470 return VINF_SUCCESS;
1471 }
1472 *pResp = 0;
1473 if (codecIsDacNode(pState, CODEC_NID(cmd)))
1474 codecSetRegisterU16(&pState->pNodes[CODEC_NID(cmd)].dac.u32A_param, cmd, 0);
1475 else if (codecIsAdcNode(pState, CODEC_NID(cmd)))
1476 codecSetRegisterU16(&pState->pNodes[CODEC_NID(cmd)].adc.u32A_param, cmd, 0);
1477 else if (codecIsSpdifOutNode(pState, CODEC_NID(cmd)))
1478 codecSetRegisterU16(&pState->pNodes[CODEC_NID(cmd)].spdifout.u32A_param, cmd, 0);
1479 else if (codecIsSpdifInNode(pState, CODEC_NID(cmd)))
1480 codecSetRegisterU16(&pState->pNodes[CODEC_NID(cmd)].spdifin.u32A_param, cmd, 0);
1481 return VINF_SUCCESS;
1482}
1483
1484/* F0C */
1485static int codecGetEAPD_BTLEnabled(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1486{
1487 Assert((CODEC_CAD(cmd) == pState->id));
1488 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1489 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1490 {
1491 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1492 return VINF_SUCCESS;
1493 }
1494 *pResp = 0;
1495 if (codecIsAdcVolNode(pState, CODEC_NID(cmd)))
1496 *pResp = pState->pNodes[CODEC_NID(cmd)].adcvol.u32F0c_param;
1497 else if (codecIsDacNode(pState, CODEC_NID(cmd)))
1498 *pResp = pState->pNodes[CODEC_NID(cmd)].dac.u32F0c_param;
1499 else if (codecIsDigInPinNode(pState, CODEC_NID(cmd)))
1500 *pResp = pState->pNodes[CODEC_NID(cmd)].digin.u32F0c_param;
1501 return VINF_SUCCESS;
1502}
1503
1504/* 70C */
1505static int codecSetEAPD_BTLEnabled(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1506{
1507 Assert((CODEC_CAD(cmd) == pState->id));
1508 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1509 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1510 {
1511 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1512 return VINF_SUCCESS;
1513 }
1514 *pResp = 0;
1515 uint32_t *pu32Reg = NULL;
1516 if (codecIsAdcVolNode(pState, CODEC_NID(cmd)))
1517 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].adcvol.u32F0c_param;
1518 else if (codecIsDacNode(pState, CODEC_NID(cmd)))
1519 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].dac.u32F0c_param;
1520 else if (codecIsDigInPinNode(pState, CODEC_NID(cmd)))
1521 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].digin.u32F0c_param;
1522 *pResp = 0;
1523 Assert((pu32Reg));
1524 if (pu32Reg)
1525 codecSetRegisterU8(pu32Reg, cmd, 0);
1526 return VINF_SUCCESS;
1527}
1528
1529/* F0F */
1530static int codecGetVolumeKnobCtrl(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1531{
1532 Assert((CODEC_CAD(cmd) == pState->id));
1533 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1534 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1535 {
1536 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1537 return VINF_SUCCESS;
1538 }
1539 *pResp = 0;
1540 if (codecIsVolKnobNode(pState, CODEC_NID(cmd)))
1541 *pResp = pState->pNodes[CODEC_NID(cmd)].volumeKnob.u32F0f_param;
1542 return VINF_SUCCESS;
1543}
1544
1545/* 70F */
1546static int codecSetVolumeKnobCtrl(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1547{
1548 Assert((CODEC_CAD(cmd) == pState->id));
1549 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1550 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1551 {
1552 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1553 return VINF_SUCCESS;
1554 }
1555 uint32_t *pu32Reg = NULL;
1556 *pResp = 0;
1557 if (codecIsVolKnobNode(pState, CODEC_NID(cmd)))
1558 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].volumeKnob.u32F0f_param;
1559 Assert((pu32Reg));
1560 if (pu32Reg)
1561 codecSetRegisterU8(pu32Reg, cmd, 0);
1562 return VINF_SUCCESS;
1563}
1564
1565/* F17 */
1566static int codecGetGPIOUnsolisted (struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1567{
1568 Assert((CODEC_CAD(cmd) == pState->id));
1569 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1570 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1571 {
1572 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1573 return VINF_SUCCESS;
1574 }
1575 *pResp = 0;
1576 /* note: this is true for ALC885 */
1577 if (CODEC_NID(cmd) == 0x1 /* AFG */)
1578 *pResp = pState->pNodes[1].afg.u32F17_param;
1579 return VINF_SUCCESS;
1580}
1581
1582/* 717 */
1583static int codecSetGPIOUnsolisted (struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1584{
1585 Assert((CODEC_CAD(cmd) == pState->id));
1586 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1587 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1588 {
1589 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1590 return VINF_SUCCESS;
1591 }
1592 uint32_t *pu32Reg = NULL;
1593 *pResp = 0;
1594 if (CODEC_NID(cmd) == 1 /* AFG */)
1595 pu32Reg = &pState->pNodes[1].afg.u32F17_param;
1596 Assert((pu32Reg));
1597 if (pu32Reg)
1598 codecSetRegisterU8(pu32Reg, cmd, 0);
1599 return VINF_SUCCESS;
1600}
1601
1602/* F1C */
1603static int codecGetConfig (struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1604{
1605 Assert((CODEC_CAD(cmd) == pState->id));
1606 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1607 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1608 {
1609 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1610 return VINF_SUCCESS;
1611 }
1612 *pResp = 0;
1613 if (codecIsPortNode(pState, CODEC_NID(cmd)))
1614 *pResp = pState->pNodes[CODEC_NID(cmd)].port.u32F1c_param;
1615 else if (codecIsDigOutPinNode(pState, CODEC_NID(cmd)))
1616 *pResp = pState->pNodes[CODEC_NID(cmd)].digout.u32F1c_param;
1617 else if (codecIsDigInPinNode(pState, CODEC_NID(cmd)))
1618 *pResp = pState->pNodes[CODEC_NID(cmd)].digin.u32F1c_param;
1619 else if (codecIsPcbeepNode(pState, CODEC_NID(cmd)))
1620 *pResp = pState->pNodes[CODEC_NID(cmd)].pcbeep.u32F1c_param;
1621 else if (codecIsCdNode(pState, CODEC_NID(cmd)))
1622 *pResp = pState->pNodes[CODEC_NID(cmd)].cdnode.u32F1c_param;
1623 else if (codecIsReservedNode(pState, CODEC_NID(cmd)))
1624 *pResp = pState->pNodes[CODEC_NID(cmd)].reserved.u32F1c_param;
1625 return VINF_SUCCESS;
1626}
1627static int codecSetConfigX(struct CODECState *pState, uint32_t cmd, uint8_t u8Offset)
1628{
1629 Assert((CODEC_CAD(cmd) == pState->id));
1630 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1631 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1632 {
1633 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1634 return VINF_SUCCESS;
1635 }
1636 uint32_t *pu32Reg = NULL;
1637 if (codecIsPortNode(pState, CODEC_NID(cmd)))
1638 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].port.u32F1c_param;
1639 else if (codecIsDigInPinNode(pState, CODEC_NID(cmd)))
1640 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].digin.u32F1c_param;
1641 else if (codecIsDigOutPinNode(pState, CODEC_NID(cmd)))
1642 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].digout.u32F1c_param;
1643 else if (codecIsCdNode(pState, CODEC_NID(cmd)))
1644 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].cdnode.u32F1c_param;
1645 else if (codecIsPcbeepNode(pState, CODEC_NID(cmd)))
1646 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].pcbeep.u32F1c_param;
1647 else if (codecIsReservedNode(pState, CODEC_NID(cmd)))
1648 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].reserved.u32F1c_param;
1649 Assert((pu32Reg));
1650 if (pu32Reg)
1651 codecSetRegisterU8(pu32Reg, cmd, u8Offset);
1652 return VINF_SUCCESS;
1653}
1654/* 71C */
1655static int codecSetConfig0 (struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1656{
1657 *pResp = 0;
1658 return codecSetConfigX(pState, cmd, 0);
1659}
1660/* 71D */
1661static int codecSetConfig1 (struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1662{
1663 *pResp = 0;
1664 return codecSetConfigX(pState, cmd, 8);
1665}
1666/* 71E */
1667static int codecSetConfig2 (struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1668{
1669 *pResp = 0;
1670 return codecSetConfigX(pState, cmd, 16);
1671}
1672/* 71E */
1673static int codecSetConfig3 (struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1674{
1675 *pResp = 0;
1676 return codecSetConfigX(pState, cmd, 24);
1677}
1678
1679
1680static int codecToAudVolume(AMPLIFIER *pAmp, audmixerctl_t mt)
1681{
1682 uint32_t dir = AMPLIFIER_OUT;
1683 switch (mt)
1684 {
1685 case AUD_MIXER_VOLUME:
1686 case AUD_MIXER_PCM:
1687 dir = AMPLIFIER_OUT;
1688 break;
1689 case AUD_MIXER_LINE_IN:
1690 dir = AMPLIFIER_IN;
1691 break;
1692 }
1693 int mute = AMPLIFIER_REGISTER(*pAmp, dir, AMPLIFIER_LEFT, 0) & RT_BIT(7);
1694 mute |= AMPLIFIER_REGISTER(*pAmp, dir, AMPLIFIER_RIGHT, 0) & RT_BIT(7);
1695 mute >>=7;
1696 mute &= 0x1;
1697 uint8_t lVol = AMPLIFIER_REGISTER(*pAmp, dir, AMPLIFIER_LEFT, 0) & 0x7f;
1698 uint8_t rVol = AMPLIFIER_REGISTER(*pAmp, dir, AMPLIFIER_RIGHT, 0) & 0x7f;
1699 AUD_set_volume(mt, &mute, &lVol, &rVol);
1700 return VINF_SUCCESS;
1701}
1702
1703static CODECVERB CODECVERBS[] =
1704{
1705/* verb | verb mask | callback */
1706/* ----------- -------------------- ----------------------- */
1707 {0x000F0000, CODEC_VERB_8BIT_CMD , codecGetParameter },
1708 {0x000F0100, CODEC_VERB_8BIT_CMD , codecGetConSelectCtrl },
1709 {0x00070100, CODEC_VERB_8BIT_CMD , codecSetConSelectCtrl },
1710 {0x000F0600, CODEC_VERB_8BIT_CMD , codecGetStreamId },
1711 {0x00070600, CODEC_VERB_8BIT_CMD , codecSetStreamId },
1712 {0x000F0700, CODEC_VERB_8BIT_CMD , codecGetPinCtrl },
1713 {0x00070700, CODEC_VERB_8BIT_CMD , codecSetPinCtrl },
1714 {0x000F0800, CODEC_VERB_8BIT_CMD , codecGetUnsolicitedEnabled },
1715 {0x00070800, CODEC_VERB_8BIT_CMD , codecSetUnsolicitedEnabled },
1716 {0x000F0900, CODEC_VERB_8BIT_CMD , codecGetPinSense },
1717 {0x00070900, CODEC_VERB_8BIT_CMD , codecSetPinSense },
1718 {0x000F0200, CODEC_VERB_8BIT_CMD , codecGetConnectionListEntry },
1719 {0x000F0300, CODEC_VERB_8BIT_CMD , codecGetProcessingState },
1720 {0x00070300, CODEC_VERB_8BIT_CMD , codecSetProcessingState },
1721 {0x000F0D00, CODEC_VERB_8BIT_CMD , codecGetDigitalConverter },
1722 {0x00070D00, CODEC_VERB_8BIT_CMD , codecSetDigitalConverter1 },
1723 {0x00070E00, CODEC_VERB_8BIT_CMD , codecSetDigitalConverter2 },
1724 {0x000F2000, CODEC_VERB_8BIT_CMD , codecGetSubId },
1725 {0x00072000, CODEC_VERB_8BIT_CMD , codecSetSubId0 },
1726 {0x00072100, CODEC_VERB_8BIT_CMD , codecSetSubId1 },
1727 {0x00072200, CODEC_VERB_8BIT_CMD , codecSetSubId2 },
1728 {0x00072300, CODEC_VERB_8BIT_CMD , codecSetSubId3 },
1729 {0x0007FF00, CODEC_VERB_8BIT_CMD , codecReset },
1730 {0x000F0500, CODEC_VERB_8BIT_CMD , codecGetPowerState },
1731 {0x00070500, CODEC_VERB_8BIT_CMD , codecSetPowerState },
1732 {0x000F0C00, CODEC_VERB_8BIT_CMD , codecGetEAPD_BTLEnabled },
1733 {0x00070C00, CODEC_VERB_8BIT_CMD , codecSetEAPD_BTLEnabled },
1734 {0x000F0F00, CODEC_VERB_8BIT_CMD , codecGetVolumeKnobCtrl },
1735 {0x00070F00, CODEC_VERB_8BIT_CMD , codecSetVolumeKnobCtrl },
1736 {0x000F1700, CODEC_VERB_8BIT_CMD , codecGetGPIOUnsolisted },
1737 {0x00071700, CODEC_VERB_8BIT_CMD , codecSetGPIOUnsolisted },
1738 {0x000F1C00, CODEC_VERB_8BIT_CMD , codecGetConfig },
1739 {0x00071C00, CODEC_VERB_8BIT_CMD , codecSetConfig0 },
1740 {0x00071D00, CODEC_VERB_8BIT_CMD , codecSetConfig1 },
1741 {0x00071E00, CODEC_VERB_8BIT_CMD , codecSetConfig2 },
1742 {0x00071F00, CODEC_VERB_8BIT_CMD , codecSetConfig3 },
1743 {0x000A0000, CODEC_VERB_16BIT_CMD, codecGetConverterFormat },
1744 {0x00020000, CODEC_VERB_16BIT_CMD, codecSetConverterFormat },
1745 {0x000B0000, CODEC_VERB_16BIT_CMD, codecGetAmplifier },
1746 {0x00030000, CODEC_VERB_16BIT_CMD, codecSetAmplifier },
1747};
1748
1749static int codecLookup(CODECState *pState, uint32_t cmd, PPFNCODECVERBPROCESSOR pfn)
1750{
1751 int rc = VINF_SUCCESS;
1752 Assert(CODEC_CAD(cmd) == pState->id);
1753 if (codecIsReservedNode(pState, CODEC_NID(cmd)))
1754 {
1755 Log(("HDAcodec: cmd %x was addressed to reserved node\n", cmd));
1756 }
1757 if ( CODEC_VERBDATA(cmd) == 0
1758 || CODEC_NID(cmd) >= pState->cTotalNodes)
1759 {
1760 *pfn = codecUnimplemented;
1761 //** @todo r=michaln: There needs to be a counter to avoid log flooding (see e.g. DevRTC.cpp)
1762 Log(("HDAcodec: cmd %x was ignored\n", cmd));
1763 return VINF_SUCCESS;
1764 }
1765 for (int i = 0; i < pState->cVerbs; ++i)
1766 {
1767 if ((CODEC_VERBDATA(cmd) & pState->pVerbs[i].mask) == pState->pVerbs[i].verb)
1768 {
1769 *pfn = pState->pVerbs[i].pfn;
1770 return VINF_SUCCESS;
1771 }
1772 }
1773 *pfn = codecUnimplemented;
1774 Log(("HDAcodec: callback for %x wasn't found\n", CODEC_VERBDATA(cmd)));
1775 return rc;
1776}
1777
1778static void pi_callback (void *opaque, int avail)
1779{
1780 CODECState *pState = (CODECState *)opaque;
1781 pState->pfnTransfer(pState, PI_INDEX, avail);
1782}
1783
1784static void po_callback (void *opaque, int avail)
1785{
1786 CODECState *pState = (CODECState *)opaque;
1787 pState->pfnTransfer(pState, PO_INDEX, avail);
1788}
1789
1790/**
1791 *
1792 * routines open one of the voices (IN, OUT) with corresponding parameters.
1793 * this routine could be called from HDA on setting/resseting sound format.
1794 *
1795 * @todo: probably passed settings should be verified (if AFG's declared proposed format) before enabling.
1796 */
1797int codecOpenVoice(CODECState *pState, ENMSOUNDSOURCE enmSoundSource, audsettings_t *pAudioSettings)
1798{
1799 int rc = 0;
1800 Assert((pState && pAudioSettings));
1801 if ( !pState
1802 || !pAudioSettings)
1803 return -1;
1804 switch (enmSoundSource)
1805 {
1806 case PI_INDEX:
1807 pState->SwVoiceIn = AUD_open_in(&pState->card, pState->SwVoiceIn, "hda.in", pState, pi_callback, pAudioSettings);
1808 rc = pState->SwVoiceIn ? 0 : 1;
1809 break;
1810 case PO_INDEX:
1811 pState->SwVoiceOut = AUD_open_out(&pState->card, pState->SwVoiceOut, "hda.out", pState, po_callback, pAudioSettings);
1812 rc = pState->SwVoiceOut ? 0 : 1;
1813 break;
1814 default:
1815 return -1;
1816 }
1817 if (!rc)
1818 LogRel(("HDAcodec: can't open %s fmt(freq: %d)\n",
1819 enmSoundSource == PI_INDEX? "in" : "out",
1820 pAudioSettings->freq));
1821 return rc;
1822}
1823
1824int codecConstruct(PPDMDEVINS pDevIns, CODECState *pState, PCFGMNODE pCfgHandle)
1825{
1826 audsettings_t as;
1827 int rc;
1828 pState->pVerbs = (CODECVERB *)&CODECVERBS;
1829 pState->cVerbs = sizeof(CODECVERBS)/sizeof(CODECVERB);
1830 pState->pfnLookup = codecLookup;
1831 rc = stac9220Construct(pState);
1832 AssertRC(rc);
1833 /* common root node initializers */
1834 pState->pNodes[0].node.au32F00_param[0] = CODEC_MAKE_F00_00(pState->u16VendorId, pState->u16DeviceId);
1835 pState->pNodes[0].node.au32F00_param[4] = CODEC_MAKE_F00_04(0x1, 0x1);
1836 /* common AFG node initializers */
1837 pState->pNodes[1].node.au32F00_param[4] = CODEC_MAKE_F00_04(0x2, pState->cTotalNodes - 2);
1838 pState->pNodes[1].node.au32F00_param[5] = CODEC_MAKE_F00_05(1, CODEC_F00_05_AFG);
1839 pState->pNodes[1].afg.u32F20_param = CODEC_MAKE_F20(pState->u16VendorId, pState->u8BSKU, pState->u8AssemblyId);
1840
1841 //** @todo r=michaln: Was this meant to be 'HDA' or something like that? (AC'97 was on ICH0)
1842 AUD_register_card ("ICH0", &pState->card);
1843
1844 /* 44.1 kHz */
1845 as.freq = 44100;
1846 as.nchannels = 2;
1847 as.fmt = AUD_FMT_S16;
1848 as.endianness = 0;
1849
1850 pState->pNodes[1].node.au32F00_param[0xA] = CODEC_F00_0A_16_BIT;
1851 codecOpenVoice(pState, PI_INDEX, &as);
1852 codecOpenVoice(pState, PO_INDEX, &as);
1853 pState->pNodes[1].node.au32F00_param[0xA] |= CODEC_F00_0A_44_1KHZ;
1854
1855 uint8_t i;
1856 Assert(pState->pNodes);
1857 Assert(pState->pfnCodecNodeReset);
1858 for (i = 0; i < pState->cTotalNodes; ++i)
1859 {
1860 pState->pfnCodecNodeReset(pState, i, &pState->pNodes[i]);
1861 }
1862
1863 codecToAudVolume(&pState->pNodes[pState->u8DacLineOut].dac.B_params, AUD_MIXER_VOLUME);
1864 codecToAudVolume(&pState->pNodes[pState->u8AdcVolsLineIn].adcvol.B_params, AUD_MIXER_LINE_IN);
1865
1866 /* If no host voices were created, then fallback to nul audio. */
1867 if (!AUD_is_host_voice_in_ok(pState->SwVoiceIn))
1868 LogRel (("HDA: WARNING: Unable to open PCM IN!\n"));
1869 if (!AUD_is_host_voice_out_ok(pState->SwVoiceOut))
1870 LogRel (("HDA: WARNING: Unable to open PCM OUT!\n"));
1871
1872 if ( !AUD_is_host_voice_in_ok(pState->SwVoiceIn)
1873 && !AUD_is_host_voice_out_ok(pState->SwVoiceOut))
1874 {
1875 /* Was not able initialize *any* voice. Select the NULL audio driver instead */
1876 AUD_close_in (&pState->card, pState->SwVoiceIn);
1877 AUD_close_out (&pState->card, pState->SwVoiceOut);
1878 pState->SwVoiceOut = NULL;
1879 pState->SwVoiceIn = NULL;
1880 AUD_init_null ();
1881
1882 PDMDevHlpVMSetRuntimeError (pDevIns, 0 /*fFlags*/, "HostAudioNotResponding",
1883 N_ ("No audio devices could be opened. Selecting the NULL audio backend "
1884 "with the consequence that no sound is audible"));
1885 }
1886 else if ( !AUD_is_host_voice_in_ok(pState->SwVoiceIn)
1887 || !AUD_is_host_voice_out_ok(pState->SwVoiceOut))
1888 {
1889 char szMissingVoices[128];
1890 size_t len = 0;
1891 if (!AUD_is_host_voice_in_ok(pState->SwVoiceIn))
1892 len = RTStrPrintf (szMissingVoices, sizeof(szMissingVoices), "PCM_in");
1893 if (!AUD_is_host_voice_out_ok(pState->SwVoiceOut))
1894 len += RTStrPrintf (szMissingVoices + len, sizeof(szMissingVoices) - len, len ? ", PCM_out" : "PCM_out");
1895
1896 PDMDevHlpVMSetRuntimeError (pDevIns, 0 /*fFlags*/, "HostAudioNotResponding",
1897 N_ ("Some audio devices (%s) could not be opened. Guest applications generating audio "
1898 "output or depending on audio input may hang. Make sure your host audio device "
1899 "is working properly. Check the logfile for error messages of the audio "
1900 "subsystem"), szMissingVoices);
1901 }
1902
1903 return VINF_SUCCESS;
1904}
1905
1906int codecDestruct(CODECState *pCodecState)
1907{
1908 RTMemFree(pCodecState->pNodes);
1909 return VINF_SUCCESS;
1910}
1911
1912int codecSaveState(CODECState *pCodecState, PSSMHANDLE pSSM)
1913{
1914 AssertLogRelMsgReturn(pCodecState->cTotalNodes == 0x1c, ("cTotalNodes=%#x, should be 0x1c", pCodecState->cTotalNodes),
1915 VERR_INTERNAL_ERROR);
1916 SSMR3PutU32(pSSM, pCodecState->cTotalNodes);
1917 for (unsigned idxNode = 0; idxNode < pCodecState->cTotalNodes; ++idxNode)
1918 SSMR3PutStructEx(pSSM, &pCodecState->pNodes[idxNode].SavedState, sizeof(pCodecState->pNodes[idxNode].SavedState),
1919 0 /*fFlags*/, g_aCodecNodeFields, NULL /*pvUser*/);
1920 return VINF_SUCCESS;
1921}
1922
1923
1924int codecLoadState(CODECState *pCodecState, PSSMHANDLE pSSM, uint32_t uVersion)
1925{
1926 PCSSMFIELD pFields;
1927 uint32_t fFlags;
1928 switch (uVersion)
1929 {
1930 case HDA_SSM_VERSION_1:
1931 AssertReturn(pCodecState->cTotalNodes == 0x1c, VERR_INTERNAL_ERROR);
1932 pFields = g_aCodecNodeFieldsV1;
1933 fFlags = SSMSTRUCT_FLAGS_MEM_BAND_AID_RELAXED;
1934 break;
1935
1936 case HDA_SSM_VERSION_2:
1937 case HDA_SSM_VERSION_3:
1938 AssertReturn(pCodecState->cTotalNodes == 0x1c, VERR_INTERNAL_ERROR);
1939 pFields = g_aCodecNodeFields;
1940 fFlags = SSMSTRUCT_FLAGS_MEM_BAND_AID_RELAXED;
1941 break;
1942
1943 case HDA_SSM_VERSION:
1944 {
1945 uint32_t cNodes;
1946 int rc2 = SSMR3GetU32(pSSM, &cNodes);
1947 AssertRCReturn(rc2, rc2);
1948 if (cNodes != 0x1c)
1949 return VERR_SSM_DATA_UNIT_FORMAT_CHANGED;
1950 AssertReturn(pCodecState->cTotalNodes == 0x1c, VERR_INTERNAL_ERROR);
1951
1952 pFields = g_aCodecNodeFields;
1953 fFlags = 0;
1954 break;
1955 }
1956
1957 default:
1958 return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
1959 }
1960
1961 for (unsigned idxNode = 0; idxNode < pCodecState->cTotalNodes; ++idxNode)
1962 {
1963 uint8_t idOld = pCodecState->pNodes[idxNode].SavedState.Core.id;
1964 int rc = SSMR3GetStructEx(pSSM, &pCodecState->pNodes[idxNode].SavedState,
1965 sizeof(pCodecState->pNodes[idxNode].SavedState),
1966 fFlags, pFields, NULL);
1967 if (RT_FAILURE(rc))
1968 return rc;
1969 AssertLogRelMsgReturn(idOld == pCodecState->pNodes[idxNode].SavedState.Core.id,
1970 ("loaded %#x, expected \n", pCodecState->pNodes[idxNode].SavedState.Core.id, idOld),
1971 VERR_SSM_DATA_UNIT_FORMAT_CHANGED);
1972 }
1973
1974 /*
1975 * Update stuff after changing the state.
1976 */
1977 if (codecIsDacNode(pCodecState, pCodecState->u8DacLineOut))
1978 codecToAudVolume(&pCodecState->pNodes[pCodecState->u8DacLineOut].dac.B_params, AUD_MIXER_VOLUME);
1979 else if (codecIsSpdifOutNode(pCodecState, pCodecState->u8DacLineOut))
1980 codecToAudVolume(&pCodecState->pNodes[pCodecState->u8DacLineOut].spdifout.B_params, AUD_MIXER_VOLUME);
1981 codecToAudVolume(&pCodecState->pNodes[pCodecState->u8AdcVolsLineIn].adcvol.B_params, AUD_MIXER_LINE_IN);
1982
1983 return VINF_SUCCESS;
1984}
1985
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