VirtualBox

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

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

*: spelling fixes, thanks Timeless!

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