VirtualBox

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

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

HDA: Removed incorrect F00/05 parameter for DACs (it was probably meant to be verb F05/00).

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