VirtualBox

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

Last change on this file since 31429 was 31357, checked in by vboxsync, 15 years ago

Audio/HDA: some todo and clean up.

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

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