VirtualBox

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

最後變更 在這個檔案從32010是 31990,由 vboxsync 提交於 15 年 前

Audio/HDA: fixes assertion 0x1b is pin-node.

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 52.6 KB
 
1/* $Id: DevCodec.cpp 31990 2010-08-26 12:45:26Z vboxsync $ */
2/** @file
3 * DevCodec - VBox ICH Intel HD Audio Codec.
4 */
5
6/*
7 * Copyright (C) 2006-2008 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.alldomusa.eu.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17#define LOG_GROUP LOG_GROUP_DEV_AUDIO
18#include <VBox/pdmdev.h>
19#include <iprt/assert.h>
20#include <iprt/uuid.h>
21#include <iprt/string.h>
22#include <iprt/mem.h>
23#include <iprt/asm.h>
24
25#include "../Builtins.h"
26extern "C" {
27#include "audio.h"
28}
29#include "DevCodec.h"
30
31#define CODEC_CAD_MASK 0xF0000000
32#define CODEC_CAD_SHIFT 28
33#define CODEC_DIRECT_MASK RT_BIT(27)
34#define CODEC_NID_MASK 0x07F00000
35#define CODEC_NID_SHIFT 20
36#define CODEC_VERBDATA_MASK 0x000FFFFF
37#define CODEC_VERB_4BIT_CMD 0x000FFFF0
38#define CODEC_VERB_4BIT_DATA 0x0000000F
39#define CODEC_VERB_8BIT_CMD 0x000FFF00
40#define CODEC_VERB_8BIT_DATA 0x000000FF
41#define CODEC_VERB_16BIT_CMD 0x000F0000
42#define CODEC_VERB_16BIT_DATA 0x0000FFFF
43
44#define CODEC_CAD(cmd) ((cmd) & CODEC_CAD_MASK)
45#define CODEC_DIRECT(cmd) ((cmd) & CODEC_DIRECT_MASK)
46#define CODEC_NID(cmd) ((((cmd) & CODEC_NID_MASK)) >> CODEC_NID_SHIFT)
47#define CODEC_VERBDATA(cmd) ((cmd) & CODEC_VERBDATA_MASK)
48#define CODEC_VERB_CMD(cmd, mask, x) (((cmd) & (mask)) >> (x))
49#define CODEC_VERB_CMD4(cmd) (CODEC_VERB_CMD((cmd), CODEC_VERB_4BIT_CMD, 4))
50#define CODEC_VERB_CMD8(cmd) (CODEC_VERB_CMD((cmd), CODEC_VERB_8BIT_CMD, 8))
51#define CODEC_VERB_CMD16(cmd) (CODEC_VERB_CMD((cmd), CODEC_VERB_16BIT_CMD, 16))
52
53#define CODEC_VERB_GET_AMP_DIRECTION RT_BIT(15)
54#define CODEC_VERB_GET_AMP_SIDE RT_BIT(13)
55#define CODEC_VERB_GET_AMP_INDEX 0x7
56
57/* HDA spec 7.3.3.7 NoteA */
58#define CODEC_GET_AMP_DIRECTION(cmd) (((cmd) & CODEC_VERB_GET_AMP_DIRECTION) >> 15)
59#define CODEC_GET_AMP_SIDE(cmd) (((cmd) & CODEC_VERB_GET_AMP_SIDE) >> 13)
60#define CODEC_GET_AMP_INDEX(cmd) (CODEC_GET_AMP_DIRECTION(cmd) ? 0 : ((cmd) & CODEC_VERB_GET_AMP_INDEX))
61
62/* HDA spec 7.3.3.7 NoteC */
63#define CODEC_VERB_SET_AMP_OUT_DIRECTION RT_BIT(15)
64#define CODEC_VERB_SET_AMP_IN_DIRECTION RT_BIT(14)
65#define CODEC_VERB_SET_AMP_LEFT_SIDE RT_BIT(13)
66#define CODEC_VERB_SET_AMP_RIGHT_SIDE RT_BIT(12)
67#define CODEC_VERB_SET_AMP_INDEX (0x7 << 8)
68
69#define CODEC_SET_AMP_IS_OUT_DIRECTION(cmd) (((cmd) & CODEC_VERB_SET_AMP_OUT_DIRECTION) != 0)
70#define CODEC_SET_AMP_IS_IN_DIRECTION(cmd) (((cmd) & CODEC_VERB_SET_AMP_IN_DIRECTION) != 0)
71#define CODEC_SET_AMP_IS_LEFT_SIDE(cmd) (((cmd) & CODEC_VERB_SET_AMP_LEFT_SIDE) != 0)
72#define CODEC_SET_AMP_IS_RIGHT_SIDE(cmd) (((cmd) & CODEC_VERB_SET_AMP_RIGHT_SIDE) != 0)
73#define CODEC_SET_AMP_INDEX(cmd) (((cmd) & CODEC_VERB_SET_AMP_INDEX) >> 7)
74
75
76#define STAC9220_NODE_COUNT 0x1C
77
78#define STAC9220_IS_AFG_CMD(cmd) ( \
79 CODEC_NID(cmd) == 0x1)
80
81#define STAC9220_IS_PORT_CMD(cmd) ( \
82 CODEC_NID(cmd) == 0xA \
83 || CODEC_NID(cmd) == 0xB \
84 || CODEC_NID(cmd) == 0xC \
85 || CODEC_NID(cmd) == 0xD \
86 || CODEC_NID(cmd) == 0xE \
87 || CODEC_NID(cmd) == 0xF)
88
89#define STAC9220_IS_DAC_CMD(cmd) ( \
90 CODEC_NID(cmd) == 0x2 \
91 || CODEC_NID(cmd) == 0x3 \
92 || CODEC_NID(cmd) == 0x4 \
93 || CODEC_NID(cmd) == 0x5)
94
95#define STAC9220_IS_ADCVOL_CMD(cmd) ( \
96 CODEC_NID(cmd) == 0x17 \
97 || CODEC_NID(cmd) == 0x18)
98
99#define STAC9220_IS_ADC_CMD(cmd) ( \
100 CODEC_NID(cmd) == 0x6 \
101 || CODEC_NID(cmd) == 0x7)
102
103#define STAC9220_IS_ADCMUX_CMD(cmd) ( \
104 CODEC_NID(cmd) == 0x12 \
105 || CODEC_NID(cmd) == 0x13)
106
107#define STAC9220_IS_PCBEEP_CMD(cmd) (CODEC_NID((cmd)) == 0x14)
108#define STAC9220_IS_SPDIFOUT_CMD(cmd) (CODEC_NID((cmd)) == 0x8)
109#define STAC9220_IS_SPDIFIN_CMD(cmd) (CODEC_NID((cmd)) == 0x9)
110
111#define STAC9220_IS_DIGINPIN_CMD(cmd) (CODEC_NID((cmd)) == 0x11)
112#define STAC9220_IS_DIGOUTPIN_CMD(cmd) (CODEC_NID((cmd)) == 0x10)
113
114#define STAC9220_IS_CD_CMD(cmd) (CODEC_NID((cmd)) == 0x15)
115
116#define STAC9220_IS_VOLKNOB_CMD(cmd) (CODEC_NID((cmd)) == 0x16)
117
118/* STAC9220 6.2 & 6.12 */
119#define STAC9220_IS_RESERVED_CMD(cmd) ( \
120 CODEC_NID((cmd)) == 0x9 \
121 || CODEC_NID((cmd)) == 0x19 \
122 || CODEC_NID((cmd)) == 0x1A \
123 || CODEC_NID((cmd)) == 0x1B)
124
125#define CODEC_POWER_MASK 0x3
126#define CODEC_POWER_ACT_SHIFT (4)
127#define CODEC_POWER_SET_SHIFT (0)
128#define CODEC_POWER_D0 (0)
129#define CODEC_POWER_D1 (1)
130#define CODEC_POWER_D2 (2)
131#define CODEC_POWER_D3 (3)
132#define CODEC_POWER_PROPOGATE_STATE(node) \
133 do { \
134 node.u32F05_param &= (CODEC_POWER_MASK); \
135 node.u32F05_param |= (node.u32F05_param & CODEC_POWER_MASK) << CODEC_POWER_ACT_SHIFT; \
136 }while(0)
137
138static int stac9220ResetNode(struct CODECState *pState, uint8_t nodenum, PCODECNODE pNode);
139static int codecToAudVolume(AMPLIFIER *pAmp, audmixerctl_t mt);
140
141static inline void codecSetRegister(uint32_t *pu32Reg, uint32_t u32Cmd, uint8_t u8Offset, uint32_t mask)
142{
143 Assert((pu32Reg && u8Offset < 32));
144 *pu32Reg &= ~(mask << u8Offset);
145 *pu32Reg |= (u32Cmd & mask) << u8Offset;
146}
147static inline void codecSetRegisterU8(uint32_t *pu32Reg, uint32_t u32Cmd, uint8_t u8Offset)
148{
149 codecSetRegister(pu32Reg, u32Cmd, u8Offset, CODEC_VERB_8BIT_DATA);
150}
151
152static inline void codecSetRegisterU16(uint32_t *pu32Reg, uint32_t u32Cmd, uint8_t u8Offset)
153{
154 codecSetRegister(pu32Reg, u32Cmd, u8Offset, CODEC_VERB_16BIT_DATA);
155}
156
157
158static int codecUnimplemented(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
159{
160 Log(("codecUnimplemented: cmd(raw:%x: cad:%x, d:%c, nid:%x, verb:%x)\n", cmd,
161 CODEC_CAD(cmd), CODEC_DIRECT(cmd) ? 'N' : 'Y', CODEC_NID(cmd), CODEC_VERBDATA(cmd)));
162 *pResp = 0;
163 return VINF_SUCCESS;
164}
165
166static int codecBreak(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
167{
168 int rc;
169 rc = codecUnimplemented(pState, cmd, pResp);
170 *pResp |= CODEC_RESPONSE_UNSOLICITED;
171 return rc;
172}
173/* B-- */
174static int codecGetAmplifier(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
175{
176 Assert((CODEC_CAD(cmd) == pState->id));
177 Assert((CODEC_NID(cmd) < STAC9220_NODE_COUNT));
178 if (CODEC_NID(cmd) >= STAC9220_NODE_COUNT)
179 {
180 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
181 return VINF_SUCCESS;
182 }
183 *pResp = 0;
184 /* HDA spec 7.3.3.7 Note A */
185 /* @todo: if index out of range response should be 0 */
186 uint8_t u8Index = CODEC_GET_AMP_DIRECTION(cmd) == AMPLIFIER_OUT? 0 : CODEC_GET_AMP_INDEX(cmd);
187
188 PCODECNODE pNode = &pState->pNodes[CODEC_NID(cmd)];
189 if (STAC9220_IS_DAC_CMD(cmd))
190 *pResp = AMPLIFIER_REGISTER(pNode->dac.B_params,
191 CODEC_GET_AMP_DIRECTION(cmd),
192 CODEC_GET_AMP_SIDE(cmd),
193 u8Index);
194 else if (STAC9220_IS_ADCVOL_CMD(cmd))
195 *pResp = AMPLIFIER_REGISTER(pNode->adcvol.B_params,
196 CODEC_GET_AMP_DIRECTION(cmd),
197 CODEC_GET_AMP_SIDE(cmd),
198 u8Index);
199 else if (STAC9220_IS_ADCMUX_CMD(cmd))
200 *pResp = AMPLIFIER_REGISTER(pNode->adcmux.B_params,
201 CODEC_GET_AMP_DIRECTION(cmd),
202 CODEC_GET_AMP_SIDE(cmd),
203 u8Index);
204 else if (STAC9220_IS_PCBEEP_CMD(cmd))
205 *pResp = AMPLIFIER_REGISTER(pNode->pcbeep.B_params,
206 CODEC_GET_AMP_DIRECTION(cmd),
207 CODEC_GET_AMP_SIDE(cmd),
208 u8Index);
209 else{
210 AssertMsgReturn(0, ("access to fields of %x need to be implemented\n", CODEC_NID(cmd)), VINF_SUCCESS);
211 }
212 return VINF_SUCCESS;
213}
214/* 3-- */
215static int codecSetAmplifier(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
216{
217 AMPLIFIER *pAmplifier = NULL;
218 bool fIsLeft = false;
219 bool fIsRight = false;
220 bool fIsOut = false;
221 bool fIsIn = false;
222 uint8_t u8Index = 0;
223 Assert((CODEC_CAD(cmd) == pState->id));
224 if (CODEC_NID(cmd) >= STAC9220_NODE_COUNT)
225 {
226 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
227 return VINF_SUCCESS;
228 }
229 *pResp = 0;
230 PCODECNODE pNode = &pState->pNodes[CODEC_NID(cmd)];
231 if (STAC9220_IS_DAC_CMD(cmd))
232 pAmplifier = &pNode->dac.B_params;
233 else if (STAC9220_IS_ADCVOL_CMD(cmd))
234 pAmplifier = &pNode->adcvol.B_params;
235 else if (STAC9220_IS_ADCMUX_CMD(cmd))
236 pAmplifier = &pNode->adcmux.B_params;
237 else if (STAC9220_IS_PCBEEP_CMD(cmd))
238 pAmplifier = &pNode->pcbeep.B_params;
239 Assert(pAmplifier);
240 if (pAmplifier)
241 {
242 fIsOut = CODEC_SET_AMP_IS_OUT_DIRECTION(cmd);
243 fIsIn = CODEC_SET_AMP_IS_IN_DIRECTION(cmd);
244 fIsRight = CODEC_SET_AMP_IS_RIGHT_SIDE(cmd);
245 fIsLeft = CODEC_SET_AMP_IS_LEFT_SIDE(cmd);
246 u8Index = CODEC_SET_AMP_INDEX(cmd);
247 if ( (!fIsLeft && !fIsRight)
248 || (!fIsOut && !fIsIn))
249 return VINF_SUCCESS;
250 if (fIsIn)
251 {
252 if (fIsLeft)
253 codecSetRegisterU8(&AMPLIFIER_REGISTER(*pAmplifier, AMPLIFIER_IN, AMPLIFIER_LEFT, u8Index), cmd, 0);
254 if (fIsRight)
255 codecSetRegisterU8(&AMPLIFIER_REGISTER(*pAmplifier, AMPLIFIER_IN, AMPLIFIER_RIGHT, u8Index), cmd, 0);
256 }
257 if (fIsOut)
258 {
259 if (fIsLeft)
260 codecSetRegisterU8(&AMPLIFIER_REGISTER(*pAmplifier, AMPLIFIER_OUT, AMPLIFIER_LEFT, u8Index), cmd, 0);
261 if (fIsRight)
262 codecSetRegisterU8(&AMPLIFIER_REGISTER(*pAmplifier, AMPLIFIER_OUT, AMPLIFIER_RIGHT, u8Index), cmd, 0);
263 }
264 if (CODEC_NID(cmd) == 2)
265 codecToAudVolume(pAmplifier, AUD_MIXER_VOLUME);
266 if (CODEC_NID(cmd) == 0x17) /* Microphone */
267 codecToAudVolume(pAmplifier, AUD_MIXER_LINE_IN);
268 }
269 return VINF_SUCCESS;
270}
271
272static int codecGetParameter(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
273{
274 Assert((CODEC_CAD(cmd) == pState->id));
275 if (CODEC_NID(cmd) >= STAC9220_NODE_COUNT)
276 {
277 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
278 return VINF_SUCCESS;
279 }
280 Assert(((cmd & CODEC_VERB_8BIT_DATA) < CODECNODE_F0_PARAM_LENGTH));
281 if ((cmd & CODEC_VERB_8BIT_DATA) >= CODECNODE_F0_PARAM_LENGTH)
282 {
283 Log(("HDAcodec: invalid F00 parameter %d\n", (cmd & CODEC_VERB_8BIT_DATA)));
284 return VINF_SUCCESS;
285 }
286 *pResp = 0;
287 *pResp = pState->pNodes[CODEC_NID(cmd)].node.au32F00_param[cmd & CODEC_VERB_8BIT_DATA];
288 return VINF_SUCCESS;
289}
290
291/* F01 */
292static int codecGetConSelectCtrl(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
293{
294 Assert((CODEC_CAD(cmd) == pState->id));
295 Assert((CODEC_NID(cmd) < STAC9220_NODE_COUNT));
296 if (CODEC_NID(cmd) >= STAC9220_NODE_COUNT)
297 {
298 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
299 return VINF_SUCCESS;
300 }
301 *pResp = 0;
302 if (STAC9220_IS_ADCMUX_CMD(cmd))
303 *pResp = pState->pNodes[CODEC_NID(cmd)].adcmux.u32F01_param;
304 else if (STAC9220_IS_DIGOUTPIN_CMD(cmd))
305 *pResp = pState->pNodes[CODEC_NID(cmd)].digout.u32F01_param;
306 return VINF_SUCCESS;
307}
308
309/* 701 */
310static int codecSetConSelectCtrl(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
311{
312 uint32_t *pu32Reg = NULL;
313 Assert((CODEC_NID(cmd) < STAC9220_NODE_COUNT));
314 if (CODEC_NID(cmd) >= STAC9220_NODE_COUNT)
315 {
316 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
317 return VINF_SUCCESS;
318 }
319 *pResp = 0;
320 if (STAC9220_IS_ADCMUX_CMD(cmd))
321 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].adcmux.u32F01_param;
322 else if (STAC9220_IS_DIGOUTPIN_CMD(cmd))
323 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].digout.u32F01_param;
324 Assert((pu32Reg));
325 if (pu32Reg)
326 codecSetRegisterU8(pu32Reg, cmd, 0);
327 return VINF_SUCCESS;
328}
329
330/* F07 */
331static int codecGetPinCtrl(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
332{
333 Assert((CODEC_CAD(cmd) == pState->id));
334 Assert((CODEC_NID(cmd) < STAC9220_NODE_COUNT));
335 if (CODEC_NID(cmd) >= STAC9220_NODE_COUNT)
336 {
337 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
338 return VINF_SUCCESS;
339 }
340 *pResp = 0;
341 if (STAC9220_IS_PORT_CMD(cmd))
342 *pResp = pState->pNodes[CODEC_NID(cmd)].port.u32F07_param;
343 else if (STAC9220_IS_DIGOUTPIN_CMD(cmd))
344 *pResp = pState->pNodes[CODEC_NID(cmd)].digout.u32F07_param;
345 else if (STAC9220_IS_DIGINPIN_CMD(cmd))
346 *pResp = pState->pNodes[CODEC_NID(cmd)].digin.u32F07_param;
347 else if (STAC9220_IS_CD_CMD(cmd))
348 *pResp = pState->pNodes[CODEC_NID(cmd)].cdnode.u32F07_param;
349 else if ( STAC9220_IS_RESERVED_CMD(cmd)
350 && CODEC_NID(cmd) == 0x1b)
351 *pResp = pState->pNodes[CODEC_NID(cmd)].reserved.u32F07_param;
352 else
353 AssertMsgFailed(("Unsupported"));
354 return VINF_SUCCESS;
355}
356
357/* 707 */
358static int codecSetPinCtrl(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
359{
360 Assert((CODEC_CAD(cmd) == pState->id));
361 Assert((CODEC_NID(cmd) < STAC9220_NODE_COUNT));
362 if (CODEC_NID(cmd) >= STAC9220_NODE_COUNT)
363 {
364 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
365 return VINF_SUCCESS;
366 }
367 *pResp = 0;
368 uint32_t *pu32Reg = NULL;
369 if (STAC9220_IS_PORT_CMD(cmd))
370 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].port.u32F07_param;
371 else if (STAC9220_IS_DIGINPIN_CMD(cmd))
372 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].digin.u32F07_param;
373 else if (STAC9220_IS_DIGOUTPIN_CMD(cmd))
374 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].digout.u32F07_param;
375 else if (STAC9220_IS_CD_CMD(cmd))
376 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].cdnode.u32F07_param;
377 else if ( STAC9220_IS_RESERVED_CMD(cmd)
378 && CODEC_NID(cmd) == 0x1b)
379 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].reserved.u32F07_param;
380 Assert((pu32Reg));
381 if (pu32Reg)
382 codecSetRegisterU8(pu32Reg, cmd, 0);
383 return VINF_SUCCESS;
384}
385
386/* F08 */
387static int codecGetUnsolicitedEnabled(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
388{
389 Assert((CODEC_CAD(cmd) == pState->id));
390 Assert((CODEC_NID(cmd) < STAC9220_NODE_COUNT));
391 if (CODEC_NID(cmd) >= STAC9220_NODE_COUNT)
392 {
393 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
394 return VINF_SUCCESS;
395 }
396 *pResp = 0;
397 if (STAC9220_IS_PORT_CMD(cmd))
398 *pResp = pState->pNodes[CODEC_NID(cmd)].port.u32F08_param;
399 else if (STAC9220_IS_DIGINPIN_CMD(cmd))
400 *pResp = pState->pNodes[CODEC_NID(cmd)].digin.u32F08_param;
401 else if (STAC9220_IS_AFG_CMD(cmd))
402 *pResp = pState->pNodes[CODEC_NID(cmd)].afg.u32F08_param;
403 else if (STAC9220_IS_VOLKNOB_CMD(cmd))
404 *pResp = pState->pNodes[CODEC_NID(cmd)].volumeKnob.u32F08_param;
405 else
406 AssertMsgFailed(("unsupported operation %x on node: %x\n", CODEC_VERB_CMD8(cmd), CODEC_NID(cmd)));
407 return VINF_SUCCESS;
408}
409
410/* 708 */
411static int codecSetUnsolicitedEnabled(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
412{
413 Assert((CODEC_CAD(cmd) == pState->id));
414 Assert((CODEC_NID(cmd) < STAC9220_NODE_COUNT));
415 if (CODEC_NID(cmd) >= STAC9220_NODE_COUNT)
416 {
417 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
418 return VINF_SUCCESS;
419 }
420 *pResp = 0;
421 uint32_t *pu32Reg = NULL;
422 if (STAC9220_IS_PORT_CMD(cmd))
423 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].port.u32F08_param;
424 else if (STAC9220_IS_DIGINPIN_CMD(cmd))
425 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].digin.u32F08_param;
426 else if (STAC9220_IS_AFG_CMD(cmd))
427 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].afg.u32F08_param;
428 else if (STAC9220_IS_VOLKNOB_CMD(cmd))
429 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].volumeKnob.u32F08_param;
430 else
431 AssertMsgFailed(("unsupported operation %x on node: %x\n", CODEC_VERB_CMD8(cmd), CODEC_NID(cmd)));
432 Assert(pu32Reg);
433 if(pu32Reg)
434 codecSetRegisterU8(pu32Reg, cmd, 0);
435 return VINF_SUCCESS;
436}
437
438/* F09 */
439static int codecGetPinSense(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
440{
441 Assert((CODEC_CAD(cmd) == pState->id));
442 Assert((CODEC_NID(cmd) < STAC9220_NODE_COUNT));
443 if (CODEC_NID(cmd) >= STAC9220_NODE_COUNT)
444 {
445 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
446 return VINF_SUCCESS;
447 }
448 *pResp = 0;
449 if (STAC9220_IS_PORT_CMD(cmd))
450 *pResp = pState->pNodes[CODEC_NID(cmd)].port.u32F09_param;
451 else if (STAC9220_IS_DIGINPIN_CMD(cmd))
452 *pResp = pState->pNodes[CODEC_NID(cmd)].digin.u32F09_param;
453 else
454 AssertMsgFailed(("unsupported operation %x on node: %x\n", CODEC_VERB_CMD8(cmd), CODEC_NID(cmd)));
455 return VINF_SUCCESS;
456}
457
458/* 709 */
459static int codecSetPinSense(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
460{
461 Assert((CODEC_CAD(cmd) == pState->id));
462 Assert((CODEC_NID(cmd) < STAC9220_NODE_COUNT));
463 if (CODEC_NID(cmd) >= STAC9220_NODE_COUNT)
464 {
465 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
466 return VINF_SUCCESS;
467 }
468 *pResp = 0;
469 uint32_t *pu32Reg = NULL;
470 if (STAC9220_IS_PORT_CMD(cmd))
471 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].port.u32F08_param;
472 else if (STAC9220_IS_DIGINPIN_CMD(cmd))
473 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].digin.u32F08_param;
474 Assert(pu32Reg);
475 if(pu32Reg)
476 codecSetRegisterU8(pu32Reg, cmd, 0);
477 return VINF_SUCCESS;
478}
479
480static int codecGetConnectionListEntry(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
481{
482 Assert((CODEC_CAD(cmd) == pState->id));
483 Assert((CODEC_NID(cmd) < STAC9220_NODE_COUNT));
484 if (CODEC_NID(cmd) >= STAC9220_NODE_COUNT)
485 {
486 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
487 return VINF_SUCCESS;
488 }
489 Assert((cmd & CODEC_VERB_8BIT_DATA) < 16);
490 if ((cmd & CODEC_VERB_8BIT_DATA) >= 16)
491 {
492 Log(("HDAcodec: access to invalid F02 index %d\n", (cmd & CODEC_VERB_8BIT_DATA)));
493 }
494 *pResp = *(uint32_t *)&pState->pNodes[CODEC_NID(cmd)].node.au8F02_param[cmd & CODEC_VERB_8BIT_DATA];
495 return VINF_SUCCESS;
496}
497/* F03 */
498static int codecGetProcessingState(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
499{
500 Assert((CODEC_CAD(cmd) == pState->id));
501 Assert((CODEC_NID(cmd) < STAC9220_NODE_COUNT));
502 if (CODEC_NID(cmd) >= STAC9220_NODE_COUNT)
503 {
504 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
505 return VINF_SUCCESS;
506 }
507 *pResp = 0;
508 if (STAC9220_IS_ADC_CMD(cmd))
509 *pResp = pState->pNodes[CODEC_NID(cmd)].adc.u32F03_param;
510 return VINF_SUCCESS;
511}
512
513/* 703 */
514static int codecSetProcessingState(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
515{
516 Assert((CODEC_CAD(cmd) == pState->id));
517 Assert((CODEC_NID(cmd) < STAC9220_NODE_COUNT));
518 if (CODEC_NID(cmd) >= STAC9220_NODE_COUNT)
519 {
520 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
521 return VINF_SUCCESS;
522 }
523 *pResp = 0;
524 if (STAC9220_IS_ADC_CMD(cmd))
525 {
526 codecSetRegisterU8(&pState->pNodes[CODEC_NID(cmd)].adc.u32F03_param, cmd, 0);
527 }
528 return VINF_SUCCESS;
529}
530
531/* F0D */
532static int codecGetDigitalConverter(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
533{
534 Assert((CODEC_CAD(cmd) == pState->id));
535 Assert((CODEC_NID(cmd) < STAC9220_NODE_COUNT));
536 if (CODEC_NID(cmd) >= STAC9220_NODE_COUNT)
537 {
538 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
539 return VINF_SUCCESS;
540 }
541 *pResp = 0;
542 if (STAC9220_IS_SPDIFOUT_CMD(cmd))
543 *pResp = pState->pNodes[CODEC_NID(cmd)].spdifout.u32F0d_param;
544 else if (STAC9220_IS_SPDIFIN_CMD(cmd))
545 *pResp = pState->pNodes[CODEC_NID(cmd)].spdifin.u32F0d_param;
546 return VINF_SUCCESS;
547}
548
549static int codecSetDigitalConverter(struct CODECState *pState, uint32_t cmd, uint8_t u8Offset, uint64_t *pResp)
550{
551 Assert((CODEC_CAD(cmd) == pState->id));
552 Assert((CODEC_NID(cmd) < STAC9220_NODE_COUNT));
553 if (CODEC_NID(cmd) >= STAC9220_NODE_COUNT)
554 {
555 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
556 return VINF_SUCCESS;
557 }
558 *pResp = 0;
559 if (STAC9220_IS_SPDIFOUT_CMD(cmd))
560 codecSetRegisterU8(&pState->pNodes[CODEC_NID(cmd)].spdifout.u32F0d_param, cmd, u8Offset);
561 else if (STAC9220_IS_SPDIFIN_CMD(cmd))
562 codecSetRegisterU8(&pState->pNodes[CODEC_NID(cmd)].spdifin.u32F0d_param, cmd, u8Offset);
563 return VINF_SUCCESS;
564}
565
566/* 70D */
567static int codecSetDigitalConverter1(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
568{
569 return codecSetDigitalConverter(pState, cmd, 0, pResp);
570}
571
572/* 70E */
573static int codecSetDigitalConverter2(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
574{
575 return codecSetDigitalConverter(pState, cmd, 8, pResp);
576}
577
578static int codecGetSubId(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
579{
580 Assert((CODEC_CAD(cmd) == pState->id));
581 Assert((CODEC_NID(cmd) < STAC9220_NODE_COUNT));
582 if (CODEC_NID(cmd) >= STAC9220_NODE_COUNT)
583 {
584 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
585 return VINF_SUCCESS;
586 }
587 *pResp = 0;
588 if (STAC9220_IS_AFG_CMD(cmd))
589 {
590 *pResp = pState->pNodes[CODEC_NID(cmd)].afg.u32F20_param;
591 }
592 return VINF_SUCCESS;
593}
594
595static int codecReset(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
596{
597 Assert((CODEC_CAD(cmd) == pState->id));
598 Assert(STAC9220_IS_AFG_CMD(cmd));
599 if(STAC9220_IS_AFG_CMD(cmd))
600 {
601 uint8_t i;
602 Log(("HDAcodec: enters reset\n"));
603 for (i = 0; i < STAC9220_NODE_COUNT; ++i)
604 {
605 stac9220ResetNode(pState, i, &pState->pNodes[i]);
606 }
607 pState->fInReset = false;
608 Log(("HDAcodec: exits reset\n"));
609 }
610 *pResp = 0;
611 return VINF_SUCCESS;
612}
613
614/* F05 */
615static int codecGetPowerState(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
616{
617 Assert((CODEC_CAD(cmd) == pState->id));
618 Assert((CODEC_NID(cmd) < STAC9220_NODE_COUNT));
619 if (CODEC_NID(cmd) >= STAC9220_NODE_COUNT)
620 {
621 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
622 return VINF_SUCCESS;
623 }
624 *pResp = 0;
625 if (STAC9220_IS_AFG_CMD(cmd))
626 *pResp = pState->pNodes[CODEC_NID(cmd)].afg.u32F05_param;
627 else if (STAC9220_IS_DAC_CMD(cmd))
628 *pResp = pState->pNodes[CODEC_NID(cmd)].dac.u32F05_param;
629 else if (STAC9220_IS_DIGINPIN_CMD(cmd))
630 *pResp = pState->pNodes[CODEC_NID(cmd)].digin.u32F05_param;
631 else if (STAC9220_IS_ADC_CMD(cmd))
632 *pResp = pState->pNodes[CODEC_NID(cmd)].adc.u32F05_param;
633 return VINF_SUCCESS;
634}
635
636/* 705 */
637static int codecSetPowerState(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
638{
639 Assert((CODEC_CAD(cmd) == pState->id));
640 Assert((CODEC_NID(cmd) < STAC9220_NODE_COUNT));
641 if (CODEC_NID(cmd) >= STAC9220_NODE_COUNT)
642 {
643 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
644 return VINF_SUCCESS;
645 }
646 uint32_t *pu32Reg = NULL;
647 *pResp = 0;
648 if (STAC9220_IS_AFG_CMD(cmd))
649 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].afg.u32F05_param;
650 else if (STAC9220_IS_DAC_CMD(cmd))
651 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].dac.u32F05_param;
652 else if (STAC9220_IS_DIGINPIN_CMD(cmd))
653 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].digin.u32F05_param;
654 else if (STAC9220_IS_ADC_CMD(cmd))
655 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].adc.u32F05_param;
656 Assert((pu32Reg));
657 if (!pu32Reg)
658 return VINF_SUCCESS;
659
660 if (!STAC9220_IS_AFG_CMD(cmd))
661 {
662 *pu32Reg &= ~CODEC_VERB_8BIT_DATA;
663 *pu32Reg |= (pState->pNodes[1].afg.u32F05_param & (CODEC_VERB_4BIT_DATA << 4));
664 }
665 else
666 *pu32Reg &= ~CODEC_VERB_4BIT_DATA;
667
668 *pu32Reg |= cmd & CODEC_VERB_4BIT_DATA;
669 /* Propogate next power state only if AFG is on or verb modifies AFG power state */
670 if ( STAC9220_IS_AFG_CMD(cmd)
671 || !pState->pNodes[1].afg.u32F05_param)
672 {
673 *pu32Reg &= ~(CODEC_POWER_MASK << CODEC_POWER_ACT_SHIFT);
674 *pu32Reg |= (cmd & CODEC_VERB_4BIT_DATA) << 4;
675 if ( STAC9220_IS_AFG_CMD(cmd)
676 && (cmd & CODEC_POWER_MASK) == CODEC_POWER_D0)
677 {
678 CODEC_POWER_PROPOGATE_STATE(pState->pNodes[2].dac);
679 CODEC_POWER_PROPOGATE_STATE(pState->pNodes[3].dac);
680 CODEC_POWER_PROPOGATE_STATE(pState->pNodes[4].dac);
681 CODEC_POWER_PROPOGATE_STATE(pState->pNodes[5].dac);
682 CODEC_POWER_PROPOGATE_STATE(pState->pNodes[6].dac);
683 CODEC_POWER_PROPOGATE_STATE(pState->pNodes[7].dac);
684 CODEC_POWER_PROPOGATE_STATE(pState->pNodes[0x11].dac);
685 }
686 }
687 return VINF_SUCCESS;
688}
689
690static int codecGetStreamId(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
691{
692 Assert((CODEC_CAD(cmd) == pState->id));
693 Assert((CODEC_NID(cmd) < STAC9220_NODE_COUNT));
694 if (CODEC_NID(cmd) >= STAC9220_NODE_COUNT)
695 {
696 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
697 return VINF_SUCCESS;
698 }
699 *pResp = 0;
700 if (STAC9220_IS_DAC_CMD(cmd))
701 *pResp = pState->pNodes[CODEC_NID(cmd)].dac.u32F06_param;
702 else if (STAC9220_IS_ADC_CMD(cmd))
703 *pResp = pState->pNodes[CODEC_NID(cmd)].adc.u32F06_param;
704 else if (STAC9220_IS_SPDIFIN_CMD(cmd))
705 *pResp = pState->pNodes[CODEC_NID(cmd)].spdifin.u32F06_param;
706 else if (STAC9220_IS_SPDIFOUT_CMD(cmd))
707 *pResp = pState->pNodes[CODEC_NID(cmd)].spdifout.u32F06_param;
708 return VINF_SUCCESS;
709}
710static int codecSetStreamId(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
711{
712 Assert((CODEC_CAD(cmd) == pState->id));
713 Assert((CODEC_NID(cmd) < STAC9220_NODE_COUNT));
714 if (CODEC_NID(cmd) >= STAC9220_NODE_COUNT)
715 {
716 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
717 return VINF_SUCCESS;
718 }
719 *pResp = 0;
720 uint32_t *pu32addr = NULL;
721 *pResp = 0;
722 if (STAC9220_IS_DAC_CMD(cmd))
723 pu32addr = &pState->pNodes[CODEC_NID(cmd)].dac.u32F06_param;
724 else if (STAC9220_IS_ADC_CMD(cmd))
725 pu32addr = &pState->pNodes[CODEC_NID(cmd)].adc.u32F06_param;
726 else if (STAC9220_IS_SPDIFOUT_CMD(cmd))
727 pu32addr = &pState->pNodes[CODEC_NID(cmd)].spdifout.u32F06_param;
728 else if (STAC9220_IS_SPDIFIN_CMD(cmd))
729 pu32addr = &pState->pNodes[CODEC_NID(cmd)].spdifin.u32F06_param;
730 Assert((pu32addr));
731 if (pu32addr)
732 codecSetRegisterU8(pu32addr, cmd, 0);
733 return VINF_SUCCESS;
734}
735static int codecGetConverterFormat(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
736{
737 Assert((CODEC_CAD(cmd) == pState->id));
738 Assert((CODEC_NID(cmd) < STAC9220_NODE_COUNT));
739 if (CODEC_NID(cmd) >= STAC9220_NODE_COUNT)
740 {
741 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
742 return VINF_SUCCESS;
743 }
744 *pResp = 0;
745 if (STAC9220_IS_DAC_CMD(cmd))
746 *pResp = pState->pNodes[CODEC_NID(cmd)].dac.u32A_param;
747 else if (STAC9220_IS_ADC_CMD(cmd))
748 *pResp = pState->pNodes[CODEC_NID(cmd)].adc.u32A_param;
749 else if (STAC9220_IS_SPDIFOUT_CMD(cmd))
750 *pResp = pState->pNodes[CODEC_NID(cmd)].spdifout.u32A_param;
751 else if (STAC9220_IS_SPDIFIN_CMD(cmd))
752 *pResp = pState->pNodes[CODEC_NID(cmd)].spdifin.u32A_param;
753 return VINF_SUCCESS;
754}
755
756static int codecSetConverterFormat(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
757{
758 Assert((CODEC_CAD(cmd) == pState->id));
759 Assert((CODEC_NID(cmd) < STAC9220_NODE_COUNT));
760 if (CODEC_NID(cmd) >= STAC9220_NODE_COUNT)
761 {
762 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
763 return VINF_SUCCESS;
764 }
765 *pResp = 0;
766 if (STAC9220_IS_DAC_CMD(cmd))
767 codecSetRegisterU16(&pState->pNodes[CODEC_NID(cmd)].dac.u32A_param, cmd, 0);
768 else if (STAC9220_IS_ADC_CMD(cmd))
769 codecSetRegisterU16(&pState->pNodes[CODEC_NID(cmd)].adc.u32A_param, cmd, 0);
770 else if (STAC9220_IS_SPDIFOUT_CMD(cmd))
771 codecSetRegisterU16(&pState->pNodes[CODEC_NID(cmd)].spdifout.u32A_param, cmd, 0);
772 else if (STAC9220_IS_SPDIFIN_CMD(cmd))
773 codecSetRegisterU16(&pState->pNodes[CODEC_NID(cmd)].spdifin.u32A_param, cmd, 0);
774 return VINF_SUCCESS;
775}
776
777/* F0C */
778static int codecGetEAPD_BTLEnabled(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
779{
780 Assert((CODEC_CAD(cmd) == pState->id));
781 Assert((CODEC_NID(cmd) < STAC9220_NODE_COUNT));
782 if (CODEC_NID(cmd) >= STAC9220_NODE_COUNT)
783 {
784 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
785 return VINF_SUCCESS;
786 }
787 *pResp = 0;
788 if (STAC9220_IS_ADCVOL_CMD(cmd))
789 *pResp = pState->pNodes[CODEC_NID(cmd)].adcvol.u32F0c_param;
790 else if (STAC9220_IS_DAC_CMD(cmd))
791 *pResp = pState->pNodes[CODEC_NID(cmd)].dac.u32F0c_param;
792 else if (STAC9220_IS_DIGINPIN_CMD(cmd))
793 *pResp = pState->pNodes[CODEC_NID(cmd)].digin.u32F0c_param;
794 return VINF_SUCCESS;
795}
796
797/* 70C */
798static int codecSetEAPD_BTLEnabled(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
799{
800 Assert((CODEC_CAD(cmd) == pState->id));
801 Assert((CODEC_NID(cmd) < STAC9220_NODE_COUNT));
802 if (CODEC_NID(cmd) >= STAC9220_NODE_COUNT)
803 {
804 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
805 return VINF_SUCCESS;
806 }
807 *pResp = 0;
808 uint32_t *pu32Reg = NULL;
809 if (STAC9220_IS_ADCVOL_CMD(cmd))
810 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].adcvol.u32F0c_param;
811 else if (STAC9220_IS_DAC_CMD(cmd))
812 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].dac.u32F0c_param;
813 else if (STAC9220_IS_DIGINPIN_CMD(cmd))
814 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].digin.u32F0c_param;
815 *pResp = 0;
816 Assert((pu32Reg));
817 if (pu32Reg)
818 codecSetRegisterU8(pu32Reg, cmd, 0);
819 return VINF_SUCCESS;
820}
821
822/* F0F */
823static int codecGetVolumeKnobCtrl(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
824{
825 Assert((CODEC_CAD(cmd) == pState->id));
826 Assert((CODEC_NID(cmd) < STAC9220_NODE_COUNT));
827 if (CODEC_NID(cmd) >= STAC9220_NODE_COUNT)
828 {
829 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
830 return VINF_SUCCESS;
831 }
832 *pResp = 0;
833 if (STAC9220_IS_VOLKNOB_CMD(cmd))
834 *pResp = pState->pNodes[CODEC_NID(cmd)].volumeKnob.u32F0f_param;
835 return VINF_SUCCESS;
836}
837
838/* 70F */
839static int codecSetVolumeKnobCtrl(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
840{
841 Assert((CODEC_CAD(cmd) == pState->id));
842 Assert((CODEC_NID(cmd) < STAC9220_NODE_COUNT));
843 if (CODEC_NID(cmd) >= STAC9220_NODE_COUNT)
844 {
845 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
846 return VINF_SUCCESS;
847 }
848 uint32_t *pu32Reg = NULL;
849 *pResp = 0;
850 if (STAC9220_IS_VOLKNOB_CMD(cmd))
851 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].volumeKnob.u32F0f_param;
852 Assert((pu32Reg));
853 if (pu32Reg)
854 codecSetRegisterU8(pu32Reg, cmd, 0);
855 return VINF_SUCCESS;
856}
857
858/* F1C */
859static int codecGetConfig (struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
860{
861 Assert((CODEC_CAD(cmd) == pState->id));
862 Assert((CODEC_NID(cmd) < STAC9220_NODE_COUNT));
863 if (CODEC_NID(cmd) >= STAC9220_NODE_COUNT)
864 {
865 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
866 return VINF_SUCCESS;
867 }
868 *pResp = 0;
869 if (STAC9220_IS_PORT_CMD(cmd))
870 *pResp = pState->pNodes[CODEC_NID(cmd)].port.u32F1c_param;
871 else if (STAC9220_IS_DIGOUTPIN_CMD(cmd))
872 *pResp = pState->pNodes[CODEC_NID(cmd)].digout.u32F1c_param;
873 else if (STAC9220_IS_DIGINPIN_CMD(cmd))
874 *pResp = pState->pNodes[CODEC_NID(cmd)].digin.u32F1c_param;
875 else if (STAC9220_IS_CD_CMD(cmd))
876 *pResp = pState->pNodes[CODEC_NID(cmd)].cdnode.u32F1c_param;
877 return VINF_SUCCESS;
878}
879static int codecSetConfigX(struct CODECState *pState, uint32_t cmd, uint8_t u8Offset)
880{
881 Assert((CODEC_CAD(cmd) == pState->id));
882 Assert((CODEC_NID(cmd) < STAC9220_NODE_COUNT));
883 if (CODEC_NID(cmd) >= STAC9220_NODE_COUNT)
884 {
885 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
886 return VINF_SUCCESS;
887 }
888 uint32_t *pu32Reg = NULL;
889 if (STAC9220_IS_PORT_CMD(cmd))
890 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].port.u32F1c_param;
891 else if (STAC9220_IS_DIGINPIN_CMD(cmd))
892 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].digin.u32F1c_param;
893 else if (STAC9220_IS_DIGOUTPIN_CMD(cmd))
894 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].digout.u32F1c_param;
895 else if (STAC9220_IS_CD_CMD(cmd))
896 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].cdnode.u32F1c_param;
897 Assert((pu32Reg));
898 if (pu32Reg)
899 codecSetRegisterU8(pu32Reg, cmd, u8Offset);
900 return VINF_SUCCESS;
901}
902/* 71C */
903static int codecSetConfig0 (struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
904{
905 *pResp = 0;
906 return codecSetConfigX(pState, cmd, 0);
907}
908/* 71D */
909static int codecSetConfig1 (struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
910{
911 *pResp = 0;
912 return codecSetConfigX(pState, cmd, 8);
913}
914/* 71E */
915static int codecSetConfig2 (struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
916{
917 *pResp = 0;
918 return codecSetConfigX(pState, cmd, 16);
919}
920/* 71E */
921static int codecSetConfig3 (struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
922{
923 *pResp = 0;
924 return codecSetConfigX(pState, cmd, 24);
925}
926
927static int stac9220ResetNode(struct CODECState *pState, uint8_t nodenum, PCODECNODE pNode)
928{
929 pNode->node.id = nodenum;
930 pNode->node.au32F00_param[0xF] = 0; /* Power statest Supported: are the same as AFG reports */
931 switch (nodenum)
932 {
933 /* Root Node*/
934 case 0:
935 pNode->root.node.name = "Root";
936 //** @todo r=michaln: I fear the use of RT_MAKE_U32_FROM_U8() here makes the
937 // code much harder to read, not easier.
938 pNode->node.au32F00_param[0] = RT_MAKE_U32_FROM_U8(0x80, 0x76, 0x84, 0x83); /* VendorID = STAC9220/ DevId = 0x7680 */
939 pNode->node.au32F00_param[2] = RT_MAKE_U32_FROM_U8(0x1, 0x34, 0x10, 0x00); /* rev id */
940 pNode->node.au32F00_param[4] = RT_MAKE_U32_FROM_U8(0x1, 0x00, 0x01, 0x00); /* node info (start node: 1, start id = 1) */
941 break;
942 case 1:
943 pNode->afg.node.name = "AFG";
944 pNode->node.au32F00_param[4] = 2 << 16 | 0x1A; /* starting node - 2; total numbers of nodes 0x1A */
945 pNode->node.au32F00_param[5] = RT_BIT(8)|RT_BIT(0);
946 pNode->node.au32F00_param[8] = RT_MAKE_U32_FROM_U8(0x0d, 0x0d, 0x01, 0x0); /* Capabilities */
947 //pNode->node.au32F00_param[0xa] = RT_BIT(19)|RT_BIT(18)|RT_BIT(17)|RT_BIT(10)|RT_BIT(9)|RT_BIT(8)|RT_BIT(7)|RT_BIT(6)|RT_BIT(5);
948 pNode->node.au32F00_param[0xA] = RT_BIT(17)|RT_BIT(5);
949 pNode->node.au32F00_param[0xC] = (17 << 8)|RT_BIT(6)|RT_BIT(5)|RT_BIT(2)|RT_BIT(1)|RT_BIT(0);
950 pNode->node.au32F00_param[0xB] = RT_BIT(0);
951 pNode->node.au32F00_param[0xD] = RT_BIT(31)|(0x5 << 16)|(0xE)<<8;
952 pNode->node.au32F00_param[0x12] = RT_BIT(31)|(0x2 << 16)|(0x7f << 8)|0x7f;
953 pNode->node.au32F00_param[0x11] = 0;
954 pNode->node.au32F00_param[0xF] = 0xF;
955 pNode->afg.u32F05_param = 0x2 << 4| 0x2; /* PS-Act: D3, PS->Set D3 */
956 pNode->afg.u32F20_param = 0x83847882;
957 pNode->afg.u32F08_param = 0;
958 break;
959 case 2:
960 pNode->dac.node.name = "DAC0";
961 goto dac_init;
962 case 3:
963 pNode->dac.node.name = "DAC1";
964 goto dac_init;
965 case 4:
966 pNode->dac.node.name = "DAC2";
967 goto dac_init;
968 case 5:
969 pNode->dac.node.name = "DAC3";
970 dac_init:
971 memset(pNode->dac.B_params, 0, AMPLIFIER_SIZE);
972 pNode->dac.u32A_param = RT_BIT(14)|(0x1 << 4)|0x1; /* 441000Hz/16bit/2ch */
973
974 AMPLIFIER_REGISTER(pNode->dac.B_params, AMPLIFIER_OUT, AMPLIFIER_LEFT, 0) = 0x7F | RT_BIT(7);
975 AMPLIFIER_REGISTER(pNode->dac.B_params, AMPLIFIER_OUT, AMPLIFIER_RIGHT, 0) = 0x7F | RT_BIT(7);
976
977 pNode->dac.node.au32F00_param[9] = (0xD << 16) | RT_BIT(11) | RT_BIT(10) | RT_BIT(2) | RT_BIT(0);
978 pNode->dac.u32F0c_param = 0;
979 pNode->dac.u32F05_param = 0x3 << 4 | 0x3; /* PS-Act: D3, Set: D3 */
980 break;
981 case 6:
982 pNode->adc.node.name = "ADC0";
983 pNode->node.au8F02_param[0] = 0x17;
984 goto adc_init;
985 case 7:
986 pNode->adc.node.name = "ADC1";
987 pNode->node.au8F02_param[0] = 0x18;
988 adc_init:
989 pNode->adc.u32A_param = RT_BIT(14)|(0x1 << 3)|0x1; /* 441000Hz/16bit/2ch */
990 pNode->adc.node.au32F00_param[0xE] = RT_BIT(0);
991 pNode->adc.u32F03_param = RT_BIT(0);
992 pNode->adc.u32F05_param = 0x3 << 4 | 0x3; /* PS-Act: D3 Set: D3 */
993 pNode->adc.u32F06_param = 0;
994 pNode->adc.node.au32F00_param[9] = RT_BIT(20)| (0xd << 16) | RT_BIT(10) | RT_BIT(8) | RT_BIT(6)| RT_BIT(0);
995 break;
996 case 8:
997 pNode->spdifout.node.name = "SPDIFOut";
998 pNode->spdifout.u32A_param = (1<<14)|(0x1<<4) | 0x1;
999 pNode->spdifout.node.au32F00_param[9] = (4 << 16) | RT_BIT(9)|RT_BIT(4)|0x1;
1000 pNode->node.au32F00_param[0xa] = RT_BIT(17)|RT_BIT(5);
1001 pNode->spdifout.node.au32F00_param[0xB] = RT_BIT(2)|RT_BIT(0);
1002 pNode->spdifout.u32F06_param = 0;
1003 pNode->spdifout.u32F0d_param = 0;
1004 //pNode->spdifout.node.au32F00_param[0xA] = RT_BIT(19)|RT_BIT(18)|RT_BIT(17)|RT_BIT(10)|RT_BIT(9)|RT_BIT(8)|RT_BIT(7)|RT_BIT(6);
1005 break;
1006 case 9:
1007 pNode->node.name = "Reserved_0";
1008 pNode->spdifin.u32A_param = (0x1<<4) | 0x1;
1009 pNode->spdifin.node.au32F00_param[9] = (0x1 << 20)|(4 << 16) | RT_BIT(9)| RT_BIT(8)|RT_BIT(4)|0x1;
1010 pNode->node.au32F00_param[0xA] = RT_BIT(17)|RT_BIT(5);
1011 pNode->node.au32F00_param[0xE] = RT_BIT(0);
1012 pNode->node.au8F02_param[0] = 0x11;
1013 pNode->spdifin.node.au32F00_param[0xB] = RT_BIT(2)|RT_BIT(0);
1014 pNode->spdifin.u32F06_param = 0;
1015 pNode->spdifin.u32F0d_param = 0;
1016 break;
1017 case 0xA:
1018 pNode->node.name = "PortA";
1019 pNode->node.au32F00_param[0xC] = 0x173f;
1020 *(uint32_t *)pNode->node.au8F02_param = 0x2;
1021 pNode->port.u32F07_param = RT_BIT(6);
1022 pNode->port.u32F08_param = 0;
1023 pNode->port.u32F09_param = RT_BIT(31)|0x9920; /* 39.2 kOm */
1024 if (!pState->fInReset)
1025 pNode->port.u32F1c_param = RT_MAKE_U32_FROM_U8(0x20, 0x40, 0x21, 0x02);
1026 goto port_init;
1027 case 0xB:
1028 pNode->node.name = "PortB";
1029 pNode->node.au32F00_param[0xC] = 0x1737;
1030 *(uint32_t *)pNode->node.au8F02_param = 0x4;
1031 pNode->port.u32F09_param = 0;
1032 pNode->port.u32F07_param = RT_BIT(5);
1033 if (!pState->fInReset)
1034 pNode->port.u32F1c_param = RT_MAKE_U32_FROM_U8(0x11, 0x60, 0x11, 0x01);
1035 goto port_init;
1036 case 0xC:
1037 pNode->node.name = "PortC";
1038 *(uint32_t *)pNode->node.au8F02_param = 0x3;
1039 pNode->node.au32F00_param[0xC] = 0x1737;
1040 pNode->port.u32F09_param = 0;
1041 pNode->port.u32F07_param = RT_BIT(5);
1042 if (!pState->fInReset)
1043 pNode->port.u32F1c_param = RT_MAKE_U32_FROM_U8(0x10, 0x40, 0x11, 0x01);
1044 goto port_init;
1045 case 0xD:
1046 pNode->node.name = "PortD";
1047 pNode->port.u32F09_param = 0;
1048 pNode->node.au32F00_param[0xC] = 0x173f;
1049 *(uint32_t *)pNode->node.au8F02_param = 0x2;
1050 port_init:
1051 pNode->port.u32F08_param = 0;
1052 pNode->node.au32F00_param[9] = (4 << 20)|RT_BIT(8)|RT_BIT(7)|RT_BIT(0);
1053 pNode->node.au32F00_param[0xE] = 0x1;
1054 break;
1055 case 0xE:
1056 pNode->node.name = "PortE";
1057 pNode->node.au32F00_param[9] = (4 << 20)|RT_BIT(7)|RT_BIT(0);
1058 pNode->port.u32F08_param = 0;
1059 pNode->node.au32F00_param[0xC] = RT_BIT(5)|RT_BIT(2);
1060 pNode->port.u32F07_param = RT_BIT(5);
1061 pNode->port.u32F09_param = RT_BIT(31);
1062 if (!pState->fInReset)
1063 pNode->port.u32F1c_param = (0x2 << 30) /* built-in */ | (0xA << 20) /* mic. */
1064 | (0x1 << 16) | (0x30 << 8) | 0x51;
1065 break;
1066 case 0xF:
1067 pNode->node.name = "PortF";
1068 pNode->node.au32F00_param[9] = (4 << 20)|RT_BIT(8)|RT_BIT(7)|RT_BIT(0);
1069 pNode->node.au32F00_param[0xC] = 0x37;
1070 pNode->node.au32F00_param[0xE] = 0x1;
1071 pNode->port.u32F08_param = 0;
1072 pNode->port.u32F07_param = 0;
1073 if (!pState->fInReset)
1074 pNode->port.u32F1c_param = RT_MAKE_U32_FROM_U8(0x12, 0x60, 0x11, 0x01);
1075 pNode->node.au8F02_param[0] = 0x5;
1076 pNode->port.u32F09_param = 0;
1077 break;
1078 case 0x10:
1079 pNode->node.name = "DigOut_0";
1080 pNode->node.au32F00_param[9] = (4<<20)|RT_BIT(9)|RT_BIT(8)|RT_BIT(0);
1081 pNode->node.au32F00_param[0xC] = RT_BIT(4);
1082 pNode->node.au32F00_param[0xE] = 0x3;
1083 pNode->digout.u32F01_param = 0;
1084 /* STAC9220 spec defines default connection list containing reserved nodes, that confuses some drivers. */
1085 *(uint32_t *)pNode->node.au8F02_param = RT_MAKE_U32_FROM_U8(0x08, 0x17, 0x19, 0);
1086 pNode->digout.u32F07_param = 0;
1087 if (!pState->fInReset)
1088 pNode->digout.u32F1c_param = RT_MAKE_U32_FROM_U8(0x30, 0x10, 0x45, 0x01);
1089 break;
1090 case 0x11:
1091 pNode->node.name = "DigIn_0";
1092 pNode->node.au32F00_param[9] = (4 << 20)|(3<<16)|RT_BIT(10)|RT_BIT(9)|RT_BIT(7)|RT_BIT(0);
1093 pNode->node.au32F00_param[0xC] = /* RT_BIT(16)|*/ RT_BIT(5)|RT_BIT(2);
1094 pNode->digin.u32F05_param = 0x3 << 4 | 0x3; /* PS-Act: D3 -> D3 */
1095 pNode->digin.u32F07_param = 0;
1096 pNode->digin.u32F08_param = 0;
1097 pNode->digin.u32F09_param = 0;
1098 pNode->digin.u32F0c_param = 0;
1099 if (!pState->fInReset)
1100 pNode->digin.u32F1c_param = (0x1 << 24) | (0xc5 << 16) | (0x10 << 8) | 0x60;
1101 break;
1102 case 0x12:
1103 pNode->node.name = "ADCMux_0";
1104 pNode->adcmux.u32F01_param = 0;
1105 goto adcmux_init;
1106 case 0x13:
1107 pNode->node.name = "ADCMux_1";
1108 pNode->adcmux.u32F01_param = 1;
1109 adcmux_init:
1110 pNode->node.au32F00_param[9] = (3<<20)|RT_BIT(8)|RT_BIT(3)|RT_BIT(2)|RT_BIT(0);
1111 pNode->node.au32F00_param[0xe] = 0x7;
1112 pNode->node.au32F00_param[0x12] = (0x27 << 16)|(0x4 << 8);
1113 /* STAC 9220 v10 6.21-22.{4,5} both(left and right) out amplefiers inited with 0*/
1114 memset(pNode->adcmux.B_params, 0, AMPLIFIER_SIZE);
1115 *(uint32_t *)&pNode->node.au8F02_param[0] = RT_MAKE_U32_FROM_U8(0xe, 0x15, 0xf, 0xb);
1116 *(uint32_t *)&pNode->node.au8F02_param[4] = RT_MAKE_U32_FROM_U8(0xc, 0xd, 0xa, 0x0);
1117 break;
1118 case 0x14:
1119 pNode->node.name = "PCBEEP";
1120 pNode->node.au32F00_param[9] = (7 << 20) | RT_BIT(3) | RT_BIT(2);
1121 pNode->node.au32F00_param[0x12] = (0x17 << 16)|(0x3 << 8)| 0x3;
1122 pNode->pcbeep.u32F0a_param = 0;
1123 memset(pNode->pcbeep.B_params, 0, AMPLIFIER_SIZE);
1124 break;
1125 case 0x15:
1126 pNode->node.name = "CD";
1127 pNode->node.au32F00_param[0x9] = (4 << 20)|RT_BIT(0);
1128 pNode->node.au32F00_param[0xc] = RT_BIT(5);
1129 pNode->cdnode.u32F07_param = 0;
1130 if (!pState->fInReset)
1131 pNode->cdnode.u32F1c_param = RT_MAKE_U32_FROM_U8(0x52, 0x0, 0x33, 0x90);
1132 break;
1133 case 0x16:
1134 pNode->node.name = "VolumeKnob";
1135 pNode->node.au32F00_param[0x9] = (0x6 << 20);
1136 pNode->node.au32F00_param[0x13] = RT_BIT(7)| 0x7F;
1137 pNode->node.au32F00_param[0xe] = 0x4;
1138 *(uint32_t *)pNode->node.au8F02_param = RT_MAKE_U32_FROM_U8(0x2, 0x3, 0x4, 0x5);
1139 pNode->volumeKnob.u32F08_param = 0;
1140 pNode->volumeKnob.u32F0f_param = 0x7f;
1141 break;
1142 case 0x17:
1143 pNode->node.name = "ADC0Vol";
1144 *(uint32_t *)pNode->node.au8F02_param = 0x12;
1145 goto adcvol_init;
1146 case 0x18:
1147 pNode->node.name = "ADC1Vol";
1148 *(uint32_t *)pNode->node.au8F02_param = 0x13;
1149 adcvol_init:
1150 memset(pNode->adcvol.B_params, 0, AMPLIFIER_SIZE);
1151
1152 pNode->node.au32F00_param[0x9] = (0x3 << 20)|RT_BIT(11)|RT_BIT(8)|RT_BIT(1)|RT_BIT(0);
1153 pNode->node.au32F00_param[0xe] = 0x1;
1154 AMPLIFIER_REGISTER(pNode->adcvol.B_params, AMPLIFIER_IN, AMPLIFIER_LEFT, 0) = RT_BIT(7);
1155 AMPLIFIER_REGISTER(pNode->adcvol.B_params, AMPLIFIER_IN, AMPLIFIER_RIGHT, 0) = RT_BIT(7);
1156 pNode->adcvol.u32F0c_param = 0;
1157 break;
1158 case 0x19:
1159 pNode->node.name = "Reserved_1";
1160 pNode->node.au32F00_param[0x9] = (0xF << 20)|(0x3 << 16)|RT_BIT(9)|RT_BIT(0);
1161 break;
1162 case 0x1A:
1163 pNode->node.name = "Reserved_2";
1164 pNode->node.au32F00_param[0x9] = (0x3 << 16)|RT_BIT(9)|RT_BIT(0);
1165 break;
1166 case 0x1B:
1167 pNode->node.name = "Reserved_3";
1168 pNode->node.au32F00_param[0x9] = (0x4 << 20)|RT_BIT(9)|RT_BIT(8)|RT_BIT(0);
1169 pNode->node.au32F00_param[0xE] = 0x1;
1170 pNode->node.au8F02_param[0] = 0x1a;
1171 pNode->reserved.u32F07_param = 0;
1172 break;
1173 default:
1174 break;
1175 }
1176 return VINF_SUCCESS;
1177}
1178
1179static int codecToAudVolume(AMPLIFIER *pAmp, audmixerctl_t mt)
1180{
1181 uint32_t dir = AMPLIFIER_OUT;
1182 switch (mt)
1183 {
1184 case AUD_MIXER_VOLUME:
1185 case AUD_MIXER_PCM:
1186 dir = AMPLIFIER_OUT;
1187 break;
1188 case AUD_MIXER_LINE_IN:
1189 dir = AMPLIFIER_IN;
1190 break;
1191 }
1192 int mute = AMPLIFIER_REGISTER(*pAmp, dir, AMPLIFIER_LEFT, 0) & RT_BIT(7);
1193 mute |= AMPLIFIER_REGISTER(*pAmp, dir, AMPLIFIER_RIGHT, 0) & RT_BIT(7);
1194 mute >>=7;
1195 mute &= 0x1;
1196 uint8_t lVol = AMPLIFIER_REGISTER(*pAmp, dir, AMPLIFIER_LEFT, 0) & 0x7f;
1197 uint8_t rVol = AMPLIFIER_REGISTER(*pAmp, dir, AMPLIFIER_RIGHT, 0) & 0x7f;
1198 AUD_set_volume(mt, &mute, &lVol, &rVol);
1199 return VINF_SUCCESS;
1200}
1201
1202static CODECVERB STAC9220VERB[] =
1203{
1204/* verb | verb mask | callback */
1205/* ----------- -------------------- ----------------------- */
1206 {0x000F0000, CODEC_VERB_8BIT_CMD , codecGetParameter },
1207 {0x000F0100, CODEC_VERB_8BIT_CMD , codecGetConSelectCtrl },
1208 {0x00070100, CODEC_VERB_8BIT_CMD , codecSetConSelectCtrl },
1209 {0x000F0600, CODEC_VERB_8BIT_CMD , codecGetStreamId },
1210 {0x00070600, CODEC_VERB_8BIT_CMD , codecSetStreamId },
1211 {0x000F0700, CODEC_VERB_8BIT_CMD , codecGetPinCtrl },
1212 {0x00070700, CODEC_VERB_8BIT_CMD , codecSetPinCtrl },
1213 {0x000F0800, CODEC_VERB_8BIT_CMD , codecGetUnsolicitedEnabled },
1214 {0x00070800, CODEC_VERB_8BIT_CMD , codecSetUnsolicitedEnabled },
1215 {0x000F0900, CODEC_VERB_8BIT_CMD , codecGetPinSense },
1216 {0x00070900, CODEC_VERB_8BIT_CMD , codecSetPinSense },
1217 {0x000F0200, CODEC_VERB_8BIT_CMD , codecGetConnectionListEntry },
1218 {0x000F0300, CODEC_VERB_8BIT_CMD , codecGetProcessingState },
1219 {0x00070300, CODEC_VERB_8BIT_CMD , codecSetProcessingState },
1220 {0x000F0D00, CODEC_VERB_8BIT_CMD , codecGetDigitalConverter },
1221 {0x00070D00, CODEC_VERB_8BIT_CMD , codecSetDigitalConverter1 },
1222 {0x00070E00, CODEC_VERB_8BIT_CMD , codecSetDigitalConverter2 },
1223 {0x000F2000, CODEC_VERB_8BIT_CMD , codecGetSubId },
1224 {0x0007FF00, CODEC_VERB_8BIT_CMD , codecReset },
1225 {0x000F0500, CODEC_VERB_8BIT_CMD , codecGetPowerState },
1226 {0x00070500, CODEC_VERB_8BIT_CMD , codecSetPowerState },
1227 {0x000F0C00, CODEC_VERB_8BIT_CMD , codecGetEAPD_BTLEnabled },
1228 {0x00070C00, CODEC_VERB_8BIT_CMD , codecSetEAPD_BTLEnabled },
1229 {0x000F0F00, CODEC_VERB_8BIT_CMD , codecGetVolumeKnobCtrl },
1230 {0x00070F00, CODEC_VERB_8BIT_CMD , codecSetVolumeKnobCtrl },
1231 {0x000F1C00, CODEC_VERB_8BIT_CMD , codecGetConfig },
1232 {0x00071C00, CODEC_VERB_8BIT_CMD , codecSetConfig0 },
1233 {0x00071D00, CODEC_VERB_8BIT_CMD , codecSetConfig1 },
1234 {0x00071E00, CODEC_VERB_8BIT_CMD , codecSetConfig2 },
1235 {0x00071F00, CODEC_VERB_8BIT_CMD , codecSetConfig3 },
1236 {0x000A0000, CODEC_VERB_16BIT_CMD, codecGetConverterFormat },
1237 {0x00020000, CODEC_VERB_16BIT_CMD, codecSetConverterFormat },
1238 {0x000B0000, CODEC_VERB_16BIT_CMD, codecGetAmplifier },
1239 {0x00030000, CODEC_VERB_16BIT_CMD, codecSetAmplifier },
1240};
1241
1242static int codecLookup(CODECState *pState, uint32_t cmd, PPFNCODECVERBPROCESSOR pfn)
1243{
1244 int rc = VINF_SUCCESS;
1245 Assert(CODEC_CAD(cmd) == pState->id);
1246 if (STAC9220_IS_RESERVED_CMD(cmd))
1247 {
1248 LogRel(("HDAcodec: cmd %x was addressed to reseved node\n", cmd));
1249 }
1250 if ( CODEC_VERBDATA(cmd) == 0
1251 || CODEC_NID(cmd) >= STAC9220_NODE_COUNT)
1252 {
1253 *pfn = codecUnimplemented;
1254 //** @todo r=michaln: There needs to be a counter to avoid log flooding (see e.g. DevRTC.cpp)
1255 LogRel(("HDAcodec: cmd %x was ignored\n", cmd));
1256 return VINF_SUCCESS;
1257 }
1258 for (int i = 0; i < pState->cVerbs; ++i)
1259 {
1260 if ((CODEC_VERBDATA(cmd) & pState->pVerbs[i].mask) == pState->pVerbs[i].verb)
1261 {
1262 *pfn = pState->pVerbs[i].pfn;
1263 return VINF_SUCCESS;
1264 }
1265 }
1266 *pfn = codecUnimplemented;
1267 LogRel(("HDAcodec: callback for %x wasn't found\n", CODEC_VERBDATA(cmd)));
1268 return rc;
1269}
1270
1271static int codec_dac_to_aud(CODECState *pState, int dacnum, audsettings_t *paud)
1272{
1273 paud->freq = 44100;
1274 paud->nchannels = 2;
1275 paud->fmt = AUD_FMT_S16;
1276
1277 paud->endianness = 0;
1278 return VINF_SUCCESS;
1279}
1280
1281static void pi_callback (void *opaque, int avail)
1282{
1283 CODECState *pState = (CODECState *)opaque;
1284 pState->pfnTransfer(pState, PI_INDEX, avail);
1285}
1286
1287static void po_callback (void *opaque, int avail)
1288{
1289 CODECState *pState = (CODECState *)opaque;
1290 pState->pfnTransfer(pState, PO_INDEX, avail);
1291}
1292
1293static void mc_callback (void *opaque, int avail)
1294{
1295 CODECState *pState = (CODECState *)opaque;
1296 pState->pfnTransfer(pState, MC_INDEX, avail);
1297}
1298#define STAC9220_DAC_PI (0x2)
1299#define STAC9220_DAC_MC (0x3)
1300#define STAC9220_DAC_PO (0x4)
1301int stac9220Construct(CODECState *pState)
1302{
1303 audsettings_t as;
1304 pState->pVerbs = (CODECVERB *)&STAC9220VERB;
1305 pState->cVerbs = sizeof(STAC9220VERB)/sizeof(CODECVERB);
1306 pState->pfnLookup = codecLookup;
1307 pState->pNodes = (PCODECNODE)RTMemAllocZ(sizeof(CODECNODE) * STAC9220_NODE_COUNT);
1308 pState->fInReset = false;
1309 uint8_t i;
1310 for (i = 0; i < STAC9220_NODE_COUNT; ++i)
1311 {
1312 stac9220ResetNode(pState, i, &pState->pNodes[i]);
1313 }
1314 //** @todo r=michaln: Was this meant to be 'HDA' or something like that? (AC'97 was on ICH0)
1315 AUD_register_card ("ICH0", &pState->card);
1316
1317
1318 codec_dac_to_aud(pState, STAC9220_DAC_PI, &as);
1319 pState->voice_pi = AUD_open_in(&pState->card, pState->voice_pi, "hda.in", pState, pi_callback, &as);
1320 codec_dac_to_aud(pState, STAC9220_DAC_PO, &as);
1321 pState->voice_po = AUD_open_out(&pState->card, pState->voice_po, "hda.out", pState, po_callback, &as);
1322 codec_dac_to_aud(pState, STAC9220_DAC_MC, &as);
1323 pState->voice_mc = AUD_open_in(&pState->card, pState->voice_mc, "hda.mc", pState, mc_callback, &as);
1324 if (!pState->voice_pi)
1325 LogRel (("HDAcodec: WARNING: Unable to open PCM IN!\n"));
1326 if (!pState->voice_mc)
1327 LogRel (("HDAcodec: WARNING: Unable to open PCM MC!\n"));
1328 if (!pState->voice_po)
1329 LogRel (("HDAcodec: WARNING: Unable to open PCM OUT!\n"));
1330 codecToAudVolume(&pState->pNodes[2].dac.B_params, AUD_MIXER_VOLUME);
1331 codecToAudVolume(&pState->pNodes[0x17].adcvol.B_params, AUD_MIXER_LINE_IN);
1332 return VINF_SUCCESS;
1333}
1334int stac9220Destruct(CODECState *pCodecState)
1335{
1336 RTMemFree(pCodecState->pNodes);
1337 return VINF_SUCCESS;
1338}
1339
1340int stac9220SaveState(CODECState *pCodecState, PSSMHANDLE pSSMHandle)
1341{
1342 SSMR3PutMem (pSSMHandle, pCodecState->pNodes, sizeof(CODECNODE) * STAC9220_NODE_COUNT);
1343 return VINF_SUCCESS;
1344}
1345int stac9220LoadState(CODECState *pCodecState, PSSMHANDLE pSSMHandle)
1346{
1347 SSMR3GetMem (pSSMHandle, pCodecState->pNodes, sizeof(CODECNODE) * STAC9220_NODE_COUNT);
1348 codecToAudVolume(&pCodecState->pNodes[2].dac.B_params, AUD_MIXER_VOLUME);
1349 codecToAudVolume(&pCodecState->pNodes[0x17].adcvol.B_params, AUD_MIXER_LINE_IN);
1350 return VINF_SUCCESS;
1351}
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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