VirtualBox

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

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

Audio/HDA: alc885 codec is introduced(workable with Linux guest, recognized by Mac guest), not configurable (disabled).

F02 verb handling is fixed.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 74.8 KB
Line 
1/* $Id: DevCodec.cpp 32933 2010-10-06 08:55:41Z 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->pNodes = (PCODECNODE)RTMemAllocZ(sizeof(CODECNODE) * pState->cTotalNodes);
98 pState->fInReset = false;
99#define STAC9220WIDGET(type) pState->au8##type##s = au8Stac9220##type##s
100 STAC9220WIDGET(Port);
101 STAC9220WIDGET(Dac);
102 STAC9220WIDGET(Adc);
103 STAC9220WIDGET(AdcVol);
104 STAC9220WIDGET(AdcMux);
105 STAC9220WIDGET(Pcbeep);
106 STAC9220WIDGET(SpdifIn);
107 STAC9220WIDGET(SpdifOut);
108 STAC9220WIDGET(DigInPin);
109 STAC9220WIDGET(DigOutPin);
110 STAC9220WIDGET(Cd);
111 STAC9220WIDGET(VolKnob);
112 STAC9220WIDGET(Reserved);
113#undef STAC9220WIDGET
114 unconst(pState->u8AdcVolsLineIn) = 0x17;
115 unconst(pState->u8DacLineOut) = 0x2;
116
117 return VINF_SUCCESS;
118}
119
120static int stac9220ResetNode(struct CODECState *pState, uint8_t nodenum, PCODECNODE pNode)
121{
122 pNode->node.id = nodenum;
123 pNode->node.au32F00_param[0xF] = 0; /* Power statest Supported: are the same as AFG reports */
124 switch (nodenum)
125 {
126 /* Root Node*/
127 case 0:
128 pNode->root.node.name = "Root";
129 //** @todo r=michaln: I fear the use of RT_MAKE_U32_FROM_U8() here makes the
130 // code much harder to read, not easier.
131 pNode->node.au32F00_param[0] = RT_MAKE_U32_FROM_U8(0x80, 0x76, 0x84, 0x83); /* VendorID = STAC9220/ DevId = 0x7680 */
132 pNode->node.au32F00_param[2] = RT_MAKE_U32_FROM_U8(0x1, 0x34, 0x10, 0x00); /* rev id */
133 pNode->node.au32F00_param[4] = RT_MAKE_U32_FROM_U8(0x1, 0x00, 0x01, 0x00); /* node info (start node: 1, start id = 1) */
134 break;
135 case 1:
136 pNode->afg.node.name = "AFG";
137 pNode->node.au32F00_param[4] = 2 << 16 | 0x1A; /* starting node - 2; total numbers of nodes 0x1A */
138 pNode->node.au32F00_param[5] = RT_BIT(8)|RT_BIT(0);
139 pNode->node.au32F00_param[8] = RT_MAKE_U32_FROM_U8(0x0d, 0x0d, 0x01, 0x0); /* Capabilities */
140 //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);
141 pNode->node.au32F00_param[0xA] = RT_BIT(17)|RT_BIT(5);
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] = 0;
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 = 0x83847882;
150 pNode->afg.u32F08_param = 0;
151 break;
152 case 2:
153 pNode->dac.node.name = "DAC0";
154 goto dac_init;
155 case 3:
156 pNode->dac.node.name = "DAC1";
157 goto dac_init;
158 case 4:
159 pNode->dac.node.name = "DAC2";
160 goto dac_init;
161 case 5:
162 pNode->dac.node.name = "DAC3";
163 dac_init:
164 memset(pNode->dac.B_params, 0, AMPLIFIER_SIZE);
165 pNode->dac.u32A_param = RT_BIT(14)|(0x1 << 4)|0x1; /* 441000Hz/16bit/2ch */
166
167 AMPLIFIER_REGISTER(pNode->dac.B_params, AMPLIFIER_OUT, AMPLIFIER_LEFT, 0) = 0x7F | RT_BIT(7);
168 AMPLIFIER_REGISTER(pNode->dac.B_params, AMPLIFIER_OUT, AMPLIFIER_RIGHT, 0) = 0x7F | RT_BIT(7);
169
170 pNode->dac.node.au32F00_param[9] = (0xD << 16) | RT_BIT(11) | RT_BIT(10) | RT_BIT(2) | RT_BIT(0);
171 pNode->dac.u32F0c_param = 0;
172 pNode->dac.u32F05_param = 0x3 << 4 | 0x3; /* PS-Act: D3, Set: D3 */
173 break;
174 case 6:
175 pNode->adc.node.name = "ADC0";
176 pNode->node.au32F02_param[0] = 0x17;
177 goto adc_init;
178 case 7:
179 pNode->adc.node.name = "ADC1";
180 pNode->node.au32F02_param[0] = 0x18;
181 adc_init:
182 pNode->adc.u32A_param = RT_BIT(14)|(0x1 << 3)|0x1; /* 441000Hz/16bit/2ch */
183 pNode->adc.node.au32F00_param[0xE] = RT_BIT(0);
184 pNode->adc.u32F03_param = RT_BIT(0);
185 pNode->adc.u32F05_param = 0x3 << 4 | 0x3; /* PS-Act: D3 Set: D3 */
186 pNode->adc.u32F06_param = 0;
187 pNode->adc.node.au32F00_param[9] = RT_BIT(20)| (0xd << 16) | RT_BIT(10) | RT_BIT(8) | RT_BIT(6)| RT_BIT(0);
188 break;
189 case 8:
190 pNode->spdifout.node.name = "SPDIFOut";
191 pNode->spdifout.u32A_param = (1<<14)|(0x1<<4) | 0x1;
192 pNode->spdifout.node.au32F00_param[9] = (4 << 16) | RT_BIT(9)|RT_BIT(4)|0x1;
193 pNode->node.au32F00_param[0xa] = RT_BIT(17)|RT_BIT(5);
194 pNode->spdifout.node.au32F00_param[0xB] = RT_BIT(2)|RT_BIT(0);
195 pNode->spdifout.u32F06_param = 0;
196 pNode->spdifout.u32F0d_param = 0;
197 //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);
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] = RT_BIT(17)|RT_BIT(5);
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 = 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.u32F09_param = 0;
234 pNode->port.u32F07_param = RT_BIT(5);
235 if (!pState->fInReset)
236 pNode->port.u32F1c_param = RT_MAKE_U32_FROM_U8(0x10, 0x40, 0x11, 0x01);
237 goto port_init;
238 case 0xD:
239 pNode->node.name = "PortD";
240 pNode->node.au32F00_param[0xC] = 0x173f;
241 pNode->port.u32F09_param = 0;
242 pNode->port.u32F07_param = RT_BIT(6);
243 pNode->node.au32F02_param[0] = 0x2;
244 if (!pState->fInReset)
245 pNode->port.u32F1c_param = 0x01013040; /* Line Out */
246 port_init:
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] = RT_BIT(5)|RT_BIT(2);
256 pNode->port.u32F07_param = RT_BIT(5);
257 pNode->port.u32F09_param = RT_BIT(31);
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(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 = 0;
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 = 0;
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.au32F02_param[0] = 0x1a;
366 pNode->reserved.u32F07_param = 0;
367 pNode->reserved.u32F1c_param = 0x400000fb; /* dumped from real stac9220 chip */
368 break;
369 default:
370 break;
371 }
372 return VINF_SUCCESS;
373}
374
375/* ALC885 */
376const static uint8_t au8Alc889aPorts[] = { 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0};
377const static uint8_t au8Alc889aDacs[] = { 0x2, 0x3, 0x4, 0x5, 0x25, 0};
378const static uint8_t au8Alc889aAdcs[] = { 0x7, 0x8, 0x9, 0};
379const static uint8_t au8Alc889aSpdifOuts[] = { 0x6, 0 };
380const static uint8_t au8Alc889aSpdifIns[] = { 0xA, 0 };
381const static uint8_t au8Alc889aDigOutPins[] = { 0x1E, 0 };
382const static uint8_t au8Alc889aDigInPins[] = { 0x1F, 0 };
383const static uint8_t au8Alc889aAdcVols[] = { 0xE, 0xF, 0xD, 0xC, 0x26, 0xB, 0};
384const static uint8_t au8Alc889aAdcMuxs[] = { 0x22, 0x23, 0x24, 0};
385const static uint8_t au8Alc889aPcbeeps[] = { 0x1D, 0 };
386const static uint8_t au8Alc889aCds[] = { 0x1C, 0 };
387const static uint8_t au8Alc889aVolKnobs[] = { 0x21, 0 };
388const static uint8_t au8Alc889aReserveds[] = { 0x10, 0x11, 0x12, 0x13, 0 };
389
390
391static int alc885ResetNode(struct CODECState *pState, uint8_t nodenum, PCODECNODE pNode);
392
393static int alc885Construct(CODECState *pState)
394{
395 unconst(pState->cTotalNodes) = 0x27;
396 pState->pfnCodecNodeReset = alc885ResetNode;
397 pState->pNodes = (PCODECNODE)RTMemAllocZ(sizeof(CODECNODE) * pState->cTotalNodes);
398 pState->fInReset = false;
399#define ALC885WIDGET(type) pState->au8##type##s = au8Alc889a##type##s
400 ALC885WIDGET(Port);
401 ALC885WIDGET(Dac);
402 ALC885WIDGET(Adc);
403 ALC885WIDGET(AdcVol);
404 ALC885WIDGET(AdcMux);
405 ALC885WIDGET(Pcbeep);
406 ALC885WIDGET(SpdifIn);
407 ALC885WIDGET(SpdifOut);
408 ALC885WIDGET(DigInPin);
409 ALC885WIDGET(DigOutPin);
410 ALC885WIDGET(Cd);
411 ALC885WIDGET(VolKnob);
412 ALC885WIDGET(Reserved);
413#undef ALC885WIDGET
414 /* @todo: test more */
415 unconst(pState->u8AdcVolsLineIn) = 0x1a;
416 unconst(pState->u8DacLineOut) = 0x0d;
417
418 return VINF_SUCCESS;
419}
420
421static int alc885ResetNode(struct CODECState *pState, uint8_t nodenum, PCODECNODE pNode)
422{
423 pNode->node.id = nodenum;
424 switch (nodenum)
425 {
426 case 0: /* Root */
427 pNode->node.au32F00_param[0] = (0x10EC /* Realtek */ << 16) | 0x885 /* device */;
428 pNode->node.au32F00_param[2] = RT_BIT(20); /* Realtek 889 (8.1.9)*/
429 pNode->node.au32F00_param[4] = (1 << 16)|0x1; /* start node 1, total 1*/
430 pNode->node.au32F00_param[0xA] = RT_BIT(17)|RT_BIT(5);
431
432 break;
433 case 0x1: /* AFG */
434 pNode->node.au32F00_param[4] = (2 << 16)|0x25; /* start node 1, total 1*/
435 pNode->node.au32F00_param[5] = RT_BIT(8) | 0x1; /* UnSol: enabled, function group type: AFG */
436 pNode->node.au32F00_param[0xa] = 0xe0560;
437 pNode->afg.u32F20_param = 0x10ec0889;
438 pNode->node.au32F00_param[0xB] = 0x1;
439 break;
440 /* DACs */
441 case 0x2:
442 pNode->node.name = "DAC-0";
443 goto dac_init;
444 case 0x3:
445 pNode->node.name = "DAC-1";
446 goto dac_init;
447 case 0x4:
448 pNode->node.name = "DAC-2";
449 goto dac_init;
450 case 0x5:
451 pNode->node.name = "DAC-3";
452 goto dac_init;
453 case 0x25:
454 pNode->node.name = "DAC-4";
455 dac_init:
456 pNode->node.au32F00_param[0xA] = RT_BIT(17)|RT_BIT(5);
457 pNode->node.au32F00_param[0x9] = 0x11;
458 pNode->node.au32F00_param[0xB] = 0x1;
459 pNode->dac.u32A_param = (1<<14)|(0x1<<4) | 0x1;
460 break;
461 /* SPDIFs */
462 case 0x6:
463 pNode->node.name = "SPDIFOUT-0";
464 pNode->node.au32F00_param[0x9] = 0x211;
465 pNode->node.au32F00_param[0xB] = 0x1;
466 pNode->node.au32F00_param[0xA] = RT_BIT(17)|RT_BIT(5);
467 pNode->spdifout.u32A_param = (1<<14)|(0x1<<4) | 0x1;
468 break;
469 case 0xA:
470 pNode->node.name = "SPDIFIN-0";
471 pNode->node.au32F00_param[0x9] = 0x100391;
472 pNode->node.au32F00_param[0xA] = 0x1e0560;
473 pNode->node.au32F00_param[0xB] = 0x1;
474 pNode->node.au32F02_param[0] = RT_MAKE_U32_FROM_U8(0x1F, 0, 0, 0);
475 pNode->node.au32F02_param[1] = RT_MAKE_U32_FROM_U8(0x1F, 0, 0, 0);
476 pNode->node.au32F02_param[2] = RT_MAKE_U32_FROM_U8(0x1F, 0, 0, 0);
477 pNode->node.au32F02_param[3] = RT_MAKE_U32_FROM_U8(0x1F, 0, 0, 0);
478 pNode->node.au32F00_param[0xA] = RT_BIT(17)|RT_BIT(5);
479 pNode->spdifin.u32A_param = (1<<14)|(0x1<<4) | 0x1;
480 break;
481 /* VENDOR DEFINE */
482 case 0x10:
483 pNode->node.name = "VENDEF-0";
484 goto vendor_define_init;
485 case 0x11:
486 pNode->node.name = "VENDEF-1";
487 goto vendor_define_init;
488 case 0x12:
489 pNode->node.name = "VENDEF-2";
490 goto vendor_define_init;
491 case 0x13:
492 pNode->node.name = "VENDEF-3";
493 goto vendor_define_init;
494 case 0x20:
495 pNode->node.name = "VENDEF-4";
496 vendor_define_init:
497 pNode->node.au32F00_param[0x9] = 0xf00000;
498 break;
499
500 /* DIGPIN */
501 case 0x1E:
502 pNode->node.name = "DIGOUT-1";
503 pNode->node.au32F00_param[0x9] = 0x400300;
504 pNode->node.au32F00_param[0xE] = 0x1;
505 pNode->port.u32F1c_param = 0x14be060;
506 pNode->node.au32F00_param[0xC] = RT_BIT(4);
507 /* N = 0~3 */
508 pNode->node.au32F02_param[0] = RT_MAKE_U32_FROM_U8(0x6, 0x0, 0x0, 0x0);
509 pNode->node.au32F02_param[1] = RT_MAKE_U32_FROM_U8(0x6, 0x0, 0x0, 0x0);
510 pNode->node.au32F02_param[2] = RT_MAKE_U32_FROM_U8(0x6, 0x0, 0x0, 0x0);
511 pNode->node.au32F02_param[3] = RT_MAKE_U32_FROM_U8(0x6, 0x0, 0x0, 0x0);
512 break;
513 case 0x1F:
514 pNode->node.name = "DIGOUT-0";
515 pNode->node.au32F00_param[9] = 0x400200;
516 /* N = 0~3 */
517 pNode->node.au32F02_param[0] = RT_MAKE_U32_FROM_U8(0xA, 0x0, 0x0, 0x0);
518 pNode->node.au32F02_param[1] = RT_MAKE_U32_FROM_U8(0xA, 0x0, 0x0, 0x0);
519 pNode->node.au32F02_param[2] = RT_MAKE_U32_FROM_U8(0xA, 0x0, 0x0, 0x0);
520 pNode->node.au32F02_param[3] = RT_MAKE_U32_FROM_U8(0xA, 0x0, 0x0, 0x0);
521 break;
522 /* ADCs */
523 case 0x7:
524 pNode->node.name = "ADC-0";
525 pNode->node.au32F02_param[0] = RT_MAKE_U32_FROM_U8(0x23, 0, 0, 0);
526 pNode->node.au32F02_param[1] = RT_MAKE_U32_FROM_U8(0x23, 0, 0, 0);
527 pNode->node.au32F02_param[2] = RT_MAKE_U32_FROM_U8(0x23, 0, 0, 0);
528 pNode->node.au32F02_param[3] = RT_MAKE_U32_FROM_U8(0x23, 0, 0, 0);
529 goto adc_init;
530 break;
531 case 0x8:
532 pNode->node.name = "ADC-1";
533 pNode->node.au32F02_param[0] = RT_MAKE_U32_FROM_U8(0x24, 0, 0, 0);
534 pNode->node.au32F02_param[1] = RT_MAKE_U32_FROM_U8(0x24, 0, 0, 0);
535 pNode->node.au32F02_param[2] = RT_MAKE_U32_FROM_U8(0x24, 0, 0, 0);
536 pNode->node.au32F02_param[3] = RT_MAKE_U32_FROM_U8(0x24, 0, 0, 0);
537 goto adc_init;
538 break;
539 case 0x9:
540 pNode->node.name = "ADC-2";
541 pNode->node.au32F02_param[0] = RT_MAKE_U32_FROM_U8(0x22, 0, 0, 0);
542 pNode->node.au32F02_param[1] = RT_MAKE_U32_FROM_U8(0x22, 0, 0, 0);
543 pNode->node.au32F02_param[2] = RT_MAKE_U32_FROM_U8(0x22, 0, 0, 0);
544 pNode->node.au32F02_param[3] = RT_MAKE_U32_FROM_U8(0x22, 0, 0, 0);
545 adc_init:
546 pNode->node.au32F00_param[0xB] = 0x1;
547 pNode->node.au32F00_param[0x9] = 0x10011b;
548 pNode->node.au32F00_param[0xD] = 0x80032e10;
549 pNode->node.au32F00_param[0xE] = 0x1;
550 pNode->node.au32F00_param[0xA] = RT_BIT(17)|RT_BIT(5);
551 pNode->adc.u32A_param = (1<<14)|(0x1<<4) | 0x1;
552 break;
553 /* Ports */
554 case 0x14:
555 pNode->node.name = "PORT-D";
556 pNode->port.u32F1c_param = 0x12b4050;
557 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);
558 goto port_init;
559 break;
560 case 0x15:
561 pNode->node.name = "PORT-A";
562 pNode->port.u32F1c_param = 0x18b3020;
563 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);
564 goto port_init;
565 break;
566 case 0x16:
567 pNode->node.name = "PORT-G";
568 pNode->port.u32F1c_param = 0x400000f0;
569 pNode->node.au32F00_param[0xC] = RT_BIT(4)|RT_BIT(3)|RT_BIT(2);
570 goto port_init;
571 break;
572 case 0x17:
573 pNode->node.name = "PORT-H";
574 pNode->port.u32F1c_param = 0x400000f0;
575 pNode->node.au32F00_param[0xC] = RT_BIT(4)|RT_BIT(3)|RT_BIT(2);
576 goto port_init;
577 break;
578 case 0x18:
579 pNode->node.name = "PORT-B";
580 pNode->port.u32F1c_param = 0x90100140;
581 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);
582 goto port_init;
583 break;
584 case 0x19:
585 pNode->node.name = "PORT-F";
586 pNode->port.u32F1c_param = 0x90a00110;
587 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);
588 goto port_init;
589 break;
590 case 0x1A:
591 pNode->node.name = "PORT-C";
592 pNode->port.u32F1c_param = 0x90100141;
593 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);
594 goto port_init;
595 break;
596 case 0x1B:
597 pNode->node.name = "PORT-E";
598 pNode->port.u32F1c_param = 0x400000f0;
599 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);
600 port_init:
601 pNode->node.au32F00_param[0x9] = 0x40018f;
602 pNode->node.au32F00_param[0xD] = 0x270300;
603 pNode->node.au32F00_param[0xE] = 0x5;
604 /* N = 0~3 */
605 pNode->node.au32F02_param[0] = RT_MAKE_U32_FROM_U8(0xC, 0xD, 0xE, 0xF);
606 pNode->node.au32F02_param[1] = RT_MAKE_U32_FROM_U8(0xC, 0xD, 0xE, 0xF);
607 pNode->node.au32F02_param[2] = RT_MAKE_U32_FROM_U8(0xC, 0xD, 0xE, 0xF);
608 pNode->node.au32F02_param[3] = RT_MAKE_U32_FROM_U8(0xC, 0xD, 0xE, 0xF);
609 /* N = 4~7 */
610 pNode->node.au32F02_param[4] = RT_MAKE_U32_FROM_U8(0x26, 0, 0, 0);
611 pNode->node.au32F02_param[5] = RT_MAKE_U32_FROM_U8(0x26, 0, 0, 0);
612 pNode->node.au32F02_param[6] = RT_MAKE_U32_FROM_U8(0x26, 0, 0, 0);
613 pNode->node.au32F02_param[7] = RT_MAKE_U32_FROM_U8(0x26, 0, 0, 0);
614 break;
615 /* ADCVols */
616 case 0x26:
617 pNode->node.name = "AdcVol-0";
618 pNode->node.au32F00_param[0x9] = 0x20010f;
619 pNode->node.au32F00_param[0xD] = 0x80000000;
620 pNode->node.au32F00_param[0xE] = 0x2;
621 pNode->node.au32F00_param[0x12] = 0x34040;
622 pNode->node.au32F02_param[0] = RT_MAKE_U32_FROM_U8(0x25, 0xB, 0, 0);
623 pNode->node.au32F02_param[1] = RT_MAKE_U32_FROM_U8(0x25, 0xB, 0, 0);
624 pNode->node.au32F02_param[2] = RT_MAKE_U32_FROM_U8(0x25, 0xB, 0, 0);
625 pNode->node.au32F02_param[3] = RT_MAKE_U32_FROM_U8(0x25, 0xB, 0, 0);
626 break;
627 case 0xF:
628 pNode->node.name = "AdcVol-1";
629 pNode->node.au32F00_param[0x9] = 0x20010f;
630 pNode->node.au32F00_param[0xE] = 0x2;
631 pNode->node.au32F00_param[0x12] = 0x34040;
632 pNode->node.au32F02_param[0] = RT_MAKE_U32_FROM_U8(0x5, 0xB, 0, 0);
633 pNode->node.au32F02_param[1] = RT_MAKE_U32_FROM_U8(0x5, 0xB, 0, 0);
634 pNode->node.au32F02_param[2] = RT_MAKE_U32_FROM_U8(0x5, 0xB, 0, 0);
635 pNode->node.au32F02_param[3] = RT_MAKE_U32_FROM_U8(0x5, 0xB, 0, 0);
636 break;
637 case 0xE:
638 pNode->node.name = "AdcVol-2";
639 pNode->node.au32F00_param[0x9] = 0x20010f;
640 pNode->node.au32F00_param[0xE] = 0x2;
641 pNode->node.au32F00_param[0xD] = 0x80000000;
642 pNode->node.au32F00_param[0x12] = 0x34040;
643 pNode->node.au32F02_param[0] = RT_MAKE_U32_FROM_U8(0x4, 0xB, 0, 0);
644 pNode->node.au32F02_param[1] = RT_MAKE_U32_FROM_U8(0x4, 0xB, 0, 0);
645 pNode->node.au32F02_param[2] = RT_MAKE_U32_FROM_U8(0x4, 0xB, 0, 0);
646 pNode->node.au32F02_param[3] = RT_MAKE_U32_FROM_U8(0x4, 0xB, 0, 0);
647 break;
648 case 0xD:
649 pNode->node.name = "AdcVol-3";
650 pNode->node.au32F00_param[0x9] = 0x20010f;
651 pNode->node.au32F00_param[0xE] = 0x2;
652 pNode->node.au32F00_param[0xD] = 0x80000000;
653 pNode->node.au32F00_param[0x12] = 0x34040;
654 pNode->node.au32F02_param[0] = RT_MAKE_U32_FROM_U8(0x3, 0xB, 0, 0);
655 pNode->node.au32F02_param[1] = RT_MAKE_U32_FROM_U8(0x3, 0xB, 0, 0);
656 pNode->node.au32F02_param[2] = RT_MAKE_U32_FROM_U8(0x3, 0xB, 0, 0);
657 pNode->node.au32F02_param[3] = RT_MAKE_U32_FROM_U8(0x3, 0xB, 0, 0);
658 break;
659 case 0xC:
660 pNode->node.name = "AdcVol-4";
661 pNode->node.au32F00_param[0x9] = 0x20010f;
662 pNode->node.au32F00_param[0xE] = 0x2;
663 pNode->node.au32F00_param[0xD] = 0x80000000;
664 pNode->node.au32F00_param[0x12] = 0x34040;
665 pNode->node.au32F02_param[0] = RT_MAKE_U32_FROM_U8(0x2, 0xB, 0, 0);
666 pNode->node.au32F02_param[1] = RT_MAKE_U32_FROM_U8(0x2, 0xB, 0, 0);
667 pNode->node.au32F02_param[2] = RT_MAKE_U32_FROM_U8(0x2, 0xB, 0, 0);
668 pNode->node.au32F02_param[3] = RT_MAKE_U32_FROM_U8(0x2, 0xB, 0, 0);
669 break;
670 case 0xB:
671 pNode->node.name = "AdcVol-5";
672 pNode->node.au32F00_param[0x9] = 0x20010b;
673 //pNode->node.au32F00_param[0xA] = 0x80051f17;
674 pNode->node.au32F00_param[0xD] = 0x80051f17;
675 /* N = 0~3 */
676 pNode->node.au32F02_param[0] = RT_MAKE_U32_FROM_U8(0x18, 0x19, 0x1A, 0x1B);
677 pNode->node.au32F02_param[1] = RT_MAKE_U32_FROM_U8(0x18, 0x19, 0x1A, 0x1B);
678 pNode->node.au32F02_param[2] = RT_MAKE_U32_FROM_U8(0x18, 0x19, 0x1A, 0x1B);
679 pNode->node.au32F02_param[3] = RT_MAKE_U32_FROM_U8(0x18, 0x19, 0x1A, 0x1B);
680 /* N = 4~7 */
681 pNode->node.au32F02_param[4] = RT_MAKE_U32_FROM_U8(0x1C, 0x1D, 0x14, 0x15);
682 pNode->node.au32F02_param[5] = RT_MAKE_U32_FROM_U8(0x1C, 0x1D, 0x14, 0x15);
683 pNode->node.au32F02_param[6] = RT_MAKE_U32_FROM_U8(0x1C, 0x1D, 0x14, 0x15);
684 pNode->node.au32F02_param[7] = RT_MAKE_U32_FROM_U8(0x1C, 0x1D, 0x14, 0x15);
685 /* N = 8~11 */
686 pNode->node.au32F02_param[8] = RT_MAKE_U32_FROM_U8(0x16, 0x17, 0, 0);
687 pNode->node.au32F02_param[9] = RT_MAKE_U32_FROM_U8(0x16, 0x17, 0, 0);
688 pNode->node.au32F02_param[10] = RT_MAKE_U32_FROM_U8(0x16, 0x17, 0, 0);
689 pNode->node.au32F02_param[11] = RT_MAKE_U32_FROM_U8(0x16, 0x17, 0, 0);
690 break;
691 /* AdcMuxs */
692 case 0x22:
693 pNode->node.name = "AdcMux-0";
694 pNode->node.au32F00_param[0x9] = 0x20010b;
695 pNode->node.au32F00_param[0xD] = 0x80000000;
696 pNode->node.au32F00_param[0xE] = 0xb;
697 goto adc_mux_init;
698 case 0x23:
699 pNode->node.name = "AdcMux-1";
700 pNode->node.au32F00_param[0x9] = 0x20010b;
701 pNode->node.au32F00_param[0xD] = 0x80000000;
702 pNode->node.au32F00_param[0xE] = 0xb;
703 goto adc_mux_init;
704 case 0x24:
705 pNode->node.name = "AdcMux-2";
706 pNode->node.au32F00_param[0x9] = 0x20010b;
707 pNode->node.au32F00_param[0xD] = 0x80000000;
708 pNode->node.au32F00_param[0xE] = 0xb;
709 adc_mux_init:
710 /* N = 0~3 */
711 pNode->node.au32F02_param[0] = RT_MAKE_U32_FROM_U8(0x18, 0x19, 0x1A, 0x1B);
712 pNode->node.au32F02_param[1] = RT_MAKE_U32_FROM_U8(0x18, 0x19, 0x1A, 0x1B);
713 pNode->node.au32F02_param[2] = RT_MAKE_U32_FROM_U8(0x18, 0x19, 0x1A, 0x1B);
714 pNode->node.au32F02_param[3] = RT_MAKE_U32_FROM_U8(0x18, 0x19, 0x1A, 0x1B);
715 /* N = 4~7 */
716 pNode->node.au32F02_param[4] = RT_MAKE_U32_FROM_U8(0x1C, 0x1D, 0x14, 0x15);
717 pNode->node.au32F02_param[5] = RT_MAKE_U32_FROM_U8(0x1C, 0x1D, 0x14, 0x15);
718 pNode->node.au32F02_param[6] = RT_MAKE_U32_FROM_U8(0x1C, 0x1D, 0x14, 0x15);
719 pNode->node.au32F02_param[7] = RT_MAKE_U32_FROM_U8(0x1C, 0x1D, 0x14, 0x15);
720 /* N = 8~11 */
721 pNode->node.au32F02_param[8] = RT_MAKE_U32_FROM_U8(0x16, 0x17, 0xB, 0);
722 pNode->node.au32F02_param[9] = RT_MAKE_U32_FROM_U8(0x16, 0x17, 0xB, 0);
723 pNode->node.au32F02_param[10] = RT_MAKE_U32_FROM_U8(0x16, 0x17, 0xB, 0);
724 pNode->node.au32F02_param[11] = RT_MAKE_U32_FROM_U8(0x16, 0x17, 0xB, 0);
725 break;
726 /* PCBEEP */
727 case 0x1D:
728 pNode->node.name = "PCBEEP";
729 pNode->node.au32F00_param[0x9] = 0x400000;
730 pNode->port.u32F1c_param = 0x400000f0;
731 pNode->node.au32F00_param[0xC] = RT_BIT(5);
732 break;
733 /* CD */
734 case 0x1C:
735 pNode->node.name = "CD";
736 pNode->node.au32F00_param[0x9] = 0x400001;
737 pNode->port.u32F1c_param = 0x400000f0;
738 pNode->node.au32F00_param[0xC] = RT_BIT(5);
739 break;
740 case 0x21:
741 pNode->node.name = "VolumeKnob";
742 pNode->node.au32F00_param[0x9] = (0x6 << 20)|RT_BIT(7);
743 break;
744 default:
745 AssertMsgFailed(("Unsupported Node"));
746 }
747 return VINF_SUCCESS;
748}
749
750
751/* generic */
752
753#define CODEC_POWER_MASK 0x3
754#define CODEC_POWER_ACT_SHIFT (4)
755#define CODEC_POWER_SET_SHIFT (0)
756#define CODEC_POWER_D0 (0)
757#define CODEC_POWER_D1 (1)
758#define CODEC_POWER_D2 (2)
759#define CODEC_POWER_D3 (3)
760#define CODEC_POWER_PROPOGATE_STATE(node) \
761 do { \
762 node.u32F05_param &= (CODEC_POWER_MASK); \
763 node.u32F05_param |= (node.u32F05_param & CODEC_POWER_MASK) << CODEC_POWER_ACT_SHIFT; \
764 }while(0)
765
766#define DECLISNODEOFTYPE(type) \
767 static inline int codecIs##type##Node(struct CODECState *pState, uint8_t cNode) \
768 { \
769 Assert(pState->au8##type##s); \
770 for(int i = 0; pState->au8##type##s[i] != 0; ++i) \
771 if (pState->au8##type##s[i] == cNode) \
772 return 1; \
773 return 0; \
774 }
775/* codecIsPortNode */
776DECLISNODEOFTYPE(Port)
777/* codecIsDacNode */
778DECLISNODEOFTYPE(Dac)
779/* codecIsAdcVolNode */
780DECLISNODEOFTYPE(AdcVol)
781/* codecIsAdcNode */
782DECLISNODEOFTYPE(Adc)
783/* codecIsAdcMuxNode */
784DECLISNODEOFTYPE(AdcMux)
785/* codecIsPcbeepNode */
786DECLISNODEOFTYPE(Pcbeep)
787/* codecIsSpdifOutNode */
788DECLISNODEOFTYPE(SpdifOut)
789/* codecIsSpdifInNode */
790DECLISNODEOFTYPE(SpdifIn)
791/* codecIsDigInPinNode */
792DECLISNODEOFTYPE(DigInPin)
793/* codecIsDigOutPinNode */
794DECLISNODEOFTYPE(DigOutPin)
795/* codecIsCdNode */
796DECLISNODEOFTYPE(Cd)
797/* codecIsVolKnobNode */
798DECLISNODEOFTYPE(VolKnob)
799/* codecIsReservedNode */
800DECLISNODEOFTYPE(Reserved)
801
802static int codecToAudVolume(AMPLIFIER *pAmp, audmixerctl_t mt);
803
804static inline void codecSetRegister(uint32_t *pu32Reg, uint32_t u32Cmd, uint8_t u8Offset, uint32_t mask)
805{
806 Assert((pu32Reg && u8Offset < 32));
807 *pu32Reg &= ~(mask << u8Offset);
808 *pu32Reg |= (u32Cmd & mask) << u8Offset;
809}
810static inline void codecSetRegisterU8(uint32_t *pu32Reg, uint32_t u32Cmd, uint8_t u8Offset)
811{
812 codecSetRegister(pu32Reg, u32Cmd, u8Offset, CODEC_VERB_8BIT_DATA);
813}
814
815static inline void codecSetRegisterU16(uint32_t *pu32Reg, uint32_t u32Cmd, uint8_t u8Offset)
816{
817 codecSetRegister(pu32Reg, u32Cmd, u8Offset, CODEC_VERB_16BIT_DATA);
818}
819
820
821static int codecUnimplemented(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
822{
823 Log(("codecUnimplemented: cmd(raw:%x: cad:%x, d:%c, nid:%x, verb:%x)\n", cmd,
824 CODEC_CAD(cmd), CODEC_DIRECT(cmd) ? 'N' : 'Y', CODEC_NID(cmd), CODEC_VERBDATA(cmd)));
825 *pResp = 0;
826 return VINF_SUCCESS;
827}
828
829static int codecBreak(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
830{
831 int rc;
832 rc = codecUnimplemented(pState, cmd, pResp);
833 *pResp |= CODEC_RESPONSE_UNSOLICITED;
834 return rc;
835}
836/* B-- */
837static int codecGetAmplifier(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
838{
839 Assert((CODEC_CAD(cmd) == pState->id));
840 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
841 if (CODEC_NID(cmd) >= pState->cTotalNodes)
842 {
843 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
844 return VINF_SUCCESS;
845 }
846 *pResp = 0;
847 /* HDA spec 7.3.3.7 Note A */
848 /* @todo: if index out of range response should be 0 */
849 uint8_t u8Index = CODEC_GET_AMP_DIRECTION(cmd) == AMPLIFIER_OUT? 0 : CODEC_GET_AMP_INDEX(cmd);
850
851 PCODECNODE pNode = &pState->pNodes[CODEC_NID(cmd)];
852 if (codecIsDacNode(pState, CODEC_NID(cmd)))
853 *pResp = AMPLIFIER_REGISTER(pNode->dac.B_params,
854 CODEC_GET_AMP_DIRECTION(cmd),
855 CODEC_GET_AMP_SIDE(cmd),
856 u8Index);
857 else if (codecIsAdcVolNode(pState, CODEC_NID(cmd)))
858 *pResp = AMPLIFIER_REGISTER(pNode->adcvol.B_params,
859 CODEC_GET_AMP_DIRECTION(cmd),
860 CODEC_GET_AMP_SIDE(cmd),
861 u8Index);
862 else if (codecIsAdcMuxNode(pState, CODEC_NID(cmd)))
863 *pResp = AMPLIFIER_REGISTER(pNode->adcmux.B_params,
864 CODEC_GET_AMP_DIRECTION(cmd),
865 CODEC_GET_AMP_SIDE(cmd),
866 u8Index);
867 else if (codecIsPcbeepNode(pState, CODEC_NID(cmd)))
868 *pResp = AMPLIFIER_REGISTER(pNode->pcbeep.B_params,
869 CODEC_GET_AMP_DIRECTION(cmd),
870 CODEC_GET_AMP_SIDE(cmd),
871 u8Index);
872 else if (codecIsPortNode(pState, CODEC_NID(cmd)))
873 *pResp = AMPLIFIER_REGISTER(pNode->port.B_params,
874 CODEC_GET_AMP_DIRECTION(cmd),
875 CODEC_GET_AMP_SIDE(cmd),
876 u8Index);
877 else if (codecIsAdcNode(pState, CODEC_NID(cmd)))
878 *pResp = AMPLIFIER_REGISTER(pNode->adc.B_params,
879 CODEC_GET_AMP_DIRECTION(cmd),
880 CODEC_GET_AMP_SIDE(cmd),
881 u8Index);
882 else{
883 AssertMsgReturn(0, ("access to fields of %x need to be implemented\n", CODEC_NID(cmd)), VINF_SUCCESS);
884 }
885 return VINF_SUCCESS;
886}
887/* 3-- */
888static int codecSetAmplifier(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
889{
890 AMPLIFIER *pAmplifier = NULL;
891 bool fIsLeft = false;
892 bool fIsRight = false;
893 bool fIsOut = false;
894 bool fIsIn = false;
895 uint8_t u8Index = 0;
896 Assert((CODEC_CAD(cmd) == pState->id));
897 if (CODEC_NID(cmd) >= pState->cTotalNodes)
898 {
899 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
900 return VINF_SUCCESS;
901 }
902 *pResp = 0;
903 PCODECNODE pNode = &pState->pNodes[CODEC_NID(cmd)];
904 if (codecIsDacNode(pState, CODEC_NID(cmd)))
905 pAmplifier = &pNode->dac.B_params;
906 else if (codecIsAdcVolNode(pState, CODEC_NID(cmd)))
907 pAmplifier = &pNode->adcvol.B_params;
908 else if (codecIsAdcMuxNode(pState, CODEC_NID(cmd)))
909 pAmplifier = &pNode->adcmux.B_params;
910 else if (codecIsPcbeepNode(pState, CODEC_NID(cmd)))
911 pAmplifier = &pNode->pcbeep.B_params;
912 else if (codecIsPortNode(pState, CODEC_NID(cmd)))
913 pAmplifier = &pNode->port.B_params;
914 else if (codecIsAdcNode(pState, CODEC_NID(cmd)))
915 pAmplifier = &pNode->adc.B_params;
916 Assert(pAmplifier);
917 if (pAmplifier)
918 {
919 fIsOut = CODEC_SET_AMP_IS_OUT_DIRECTION(cmd);
920 fIsIn = CODEC_SET_AMP_IS_IN_DIRECTION(cmd);
921 fIsRight = CODEC_SET_AMP_IS_RIGHT_SIDE(cmd);
922 fIsLeft = CODEC_SET_AMP_IS_LEFT_SIDE(cmd);
923 u8Index = CODEC_SET_AMP_INDEX(cmd);
924 if ( (!fIsLeft && !fIsRight)
925 || (!fIsOut && !fIsIn))
926 return VINF_SUCCESS;
927 if (fIsIn)
928 {
929 if (fIsLeft)
930 codecSetRegisterU8(&AMPLIFIER_REGISTER(*pAmplifier, AMPLIFIER_IN, AMPLIFIER_LEFT, u8Index), cmd, 0);
931 if (fIsRight)
932 codecSetRegisterU8(&AMPLIFIER_REGISTER(*pAmplifier, AMPLIFIER_IN, AMPLIFIER_RIGHT, u8Index), cmd, 0);
933 }
934 if (fIsOut)
935 {
936 if (fIsLeft)
937 codecSetRegisterU8(&AMPLIFIER_REGISTER(*pAmplifier, AMPLIFIER_OUT, AMPLIFIER_LEFT, u8Index), cmd, 0);
938 if (fIsRight)
939 codecSetRegisterU8(&AMPLIFIER_REGISTER(*pAmplifier, AMPLIFIER_OUT, AMPLIFIER_RIGHT, u8Index), cmd, 0);
940 }
941 if (CODEC_NID(cmd) == pState->u8DacLineOut)
942 codecToAudVolume(pAmplifier, AUD_MIXER_VOLUME);
943 if (CODEC_NID(cmd) == pState->u8AdcVolsLineIn) /* Microphone */
944 codecToAudVolume(pAmplifier, AUD_MIXER_LINE_IN);
945 }
946 return VINF_SUCCESS;
947}
948
949static int codecGetParameter(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
950{
951 Assert((CODEC_CAD(cmd) == pState->id));
952 if (CODEC_NID(cmd) >= pState->cTotalNodes)
953 {
954 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
955 return VINF_SUCCESS;
956 }
957 Assert(((cmd & CODEC_VERB_8BIT_DATA) < CODECNODE_F0_PARAM_LENGTH));
958 if ((cmd & CODEC_VERB_8BIT_DATA) >= CODECNODE_F0_PARAM_LENGTH)
959 {
960 Log(("HDAcodec: invalid F00 parameter %d\n", (cmd & CODEC_VERB_8BIT_DATA)));
961 return VINF_SUCCESS;
962 }
963 *pResp = 0;
964 *pResp = pState->pNodes[CODEC_NID(cmd)].node.au32F00_param[cmd & CODEC_VERB_8BIT_DATA];
965 return VINF_SUCCESS;
966}
967
968/* F01 */
969static int codecGetConSelectCtrl(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
970{
971 Assert((CODEC_CAD(cmd) == pState->id));
972 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
973 if (CODEC_NID(cmd) >= pState->cTotalNodes)
974 {
975 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
976 return VINF_SUCCESS;
977 }
978 *pResp = 0;
979 if (codecIsAdcMuxNode(pState, CODEC_NID(cmd)))
980 *pResp = pState->pNodes[CODEC_NID(cmd)].adcmux.u32F01_param;
981 else if (codecIsDigOutPinNode(pState, CODEC_NID(cmd)))
982 *pResp = pState->pNodes[CODEC_NID(cmd)].digout.u32F01_param;
983 else if (codecIsPortNode(pState, CODEC_NID(cmd)))
984 *pResp = pState->pNodes[CODEC_NID(cmd)].port.u32F01_param;
985 else if (codecIsAdcNode(pState, CODEC_NID(cmd)))
986 *pResp = pState->pNodes[CODEC_NID(cmd)].adc.u32F01_param;
987 return VINF_SUCCESS;
988}
989
990/* 701 */
991static int codecSetConSelectCtrl(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
992{
993 uint32_t *pu32Reg = NULL;
994 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
995 if (CODEC_NID(cmd) >= pState->cTotalNodes)
996 {
997 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
998 return VINF_SUCCESS;
999 }
1000 *pResp = 0;
1001 if (codecIsAdcMuxNode(pState, CODEC_NID(cmd)))
1002 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].adcmux.u32F01_param;
1003 else if (codecIsDigOutPinNode(pState, CODEC_NID(cmd)))
1004 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].digout.u32F01_param;
1005 else if (codecIsPortNode(pState, CODEC_NID(cmd)))
1006 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].port.u32F01_param;
1007 else if (codecIsAdcNode(pState, CODEC_NID(cmd)))
1008 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].adc.u32F01_param;
1009 Assert((pu32Reg));
1010 if (pu32Reg)
1011 codecSetRegisterU8(pu32Reg, cmd, 0);
1012 return VINF_SUCCESS;
1013}
1014
1015/* F07 */
1016static int codecGetPinCtrl(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1017{
1018 Assert((CODEC_CAD(cmd) == pState->id));
1019 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1020 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1021 {
1022 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1023 return VINF_SUCCESS;
1024 }
1025 *pResp = 0;
1026 if (codecIsPortNode(pState, CODEC_NID(cmd)))
1027 *pResp = pState->pNodes[CODEC_NID(cmd)].port.u32F07_param;
1028 else if (codecIsDigOutPinNode(pState, CODEC_NID(cmd)))
1029 *pResp = pState->pNodes[CODEC_NID(cmd)].digout.u32F07_param;
1030 else if (codecIsDigInPinNode(pState, CODEC_NID(cmd)))
1031 *pResp = pState->pNodes[CODEC_NID(cmd)].digin.u32F07_param;
1032 else if (codecIsCdNode(pState, CODEC_NID(cmd)))
1033 *pResp = pState->pNodes[CODEC_NID(cmd)].cdnode.u32F07_param;
1034 else if ( codecIsReservedNode(pState, CODEC_NID(cmd))
1035 && CODEC_NID(cmd) == 0x1b)
1036 *pResp = pState->pNodes[CODEC_NID(cmd)].reserved.u32F07_param;
1037 else
1038 AssertMsgFailed(("Unsupported"));
1039 return VINF_SUCCESS;
1040}
1041
1042/* 707 */
1043static int codecSetPinCtrl(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1044{
1045 Assert((CODEC_CAD(cmd) == pState->id));
1046 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1047 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1048 {
1049 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1050 return VINF_SUCCESS;
1051 }
1052 *pResp = 0;
1053 uint32_t *pu32Reg = NULL;
1054 if (codecIsPortNode(pState, CODEC_NID(cmd)))
1055 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].port.u32F07_param;
1056 else if (codecIsDigInPinNode(pState, CODEC_NID(cmd)))
1057 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].digin.u32F07_param;
1058 else if (codecIsDigOutPinNode(pState, CODEC_NID(cmd)))
1059 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].digout.u32F07_param;
1060 else if (codecIsCdNode(pState, CODEC_NID(cmd)))
1061 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].cdnode.u32F07_param;
1062 else if ( codecIsReservedNode(pState, CODEC_NID(cmd))
1063 && CODEC_NID(cmd) == 0x1b)
1064 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].reserved.u32F07_param;
1065 Assert((pu32Reg));
1066 if (pu32Reg)
1067 codecSetRegisterU8(pu32Reg, cmd, 0);
1068 return VINF_SUCCESS;
1069}
1070
1071/* F08 */
1072static int codecGetUnsolicitedEnabled(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1073{
1074 Assert((CODEC_CAD(cmd) == pState->id));
1075 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1076 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1077 {
1078 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1079 return VINF_SUCCESS;
1080 }
1081 *pResp = 0;
1082 if (codecIsPortNode(pState, CODEC_NID(cmd)))
1083 *pResp = pState->pNodes[CODEC_NID(cmd)].port.u32F08_param;
1084 else if (codecIsDigInPinNode(pState, CODEC_NID(cmd)))
1085 *pResp = pState->pNodes[CODEC_NID(cmd)].digin.u32F08_param;
1086 else if ((cmd) == 1 /* AFG */)
1087 *pResp = pState->pNodes[CODEC_NID(cmd)].afg.u32F08_param;
1088 else if (codecIsVolKnobNode(pState, CODEC_NID(cmd)))
1089 *pResp = pState->pNodes[CODEC_NID(cmd)].volumeKnob.u32F08_param;
1090 else
1091 AssertMsgFailed(("unsupported operation %x on node: %x\n", CODEC_VERB_CMD8(cmd), CODEC_NID(cmd)));
1092 return VINF_SUCCESS;
1093}
1094
1095/* 708 */
1096static int codecSetUnsolicitedEnabled(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1097{
1098 Assert((CODEC_CAD(cmd) == pState->id));
1099 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1100 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1101 {
1102 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1103 return VINF_SUCCESS;
1104 }
1105 *pResp = 0;
1106 uint32_t *pu32Reg = NULL;
1107 if (codecIsPortNode(pState, CODEC_NID(cmd)))
1108 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].port.u32F08_param;
1109 else if (codecIsDigInPinNode(pState, CODEC_NID(cmd)))
1110 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].digin.u32F08_param;
1111 else if (CODEC_NID(cmd) == 1 /* AFG */)
1112 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].afg.u32F08_param;
1113 else if (codecIsVolKnobNode(pState, CODEC_NID(cmd)))
1114 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].volumeKnob.u32F08_param;
1115 else
1116 AssertMsgFailed(("unsupported operation %x on node: %x\n", CODEC_VERB_CMD8(cmd), CODEC_NID(cmd)));
1117 Assert(pu32Reg);
1118 if(pu32Reg)
1119 codecSetRegisterU8(pu32Reg, cmd, 0);
1120 return VINF_SUCCESS;
1121}
1122
1123/* F09 */
1124static int codecGetPinSense(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1125{
1126 Assert((CODEC_CAD(cmd) == pState->id));
1127 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1128 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1129 {
1130 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1131 return VINF_SUCCESS;
1132 }
1133 *pResp = 0;
1134 if (codecIsPortNode(pState, CODEC_NID(cmd)))
1135 *pResp = pState->pNodes[CODEC_NID(cmd)].port.u32F09_param;
1136 else if (codecIsDigInPinNode(pState, CODEC_NID(cmd)))
1137 *pResp = pState->pNodes[CODEC_NID(cmd)].digin.u32F09_param;
1138 else
1139 AssertMsgFailed(("unsupported operation %x on node: %x\n", CODEC_VERB_CMD8(cmd), CODEC_NID(cmd)));
1140 return VINF_SUCCESS;
1141}
1142
1143/* 709 */
1144static int codecSetPinSense(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1145{
1146 Assert((CODEC_CAD(cmd) == pState->id));
1147 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1148 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1149 {
1150 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1151 return VINF_SUCCESS;
1152 }
1153 *pResp = 0;
1154 uint32_t *pu32Reg = NULL;
1155 if (codecIsPortNode(pState, CODEC_NID(cmd)))
1156 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].port.u32F09_param;
1157 else if (codecIsDigInPinNode(pState, CODEC_NID(cmd)))
1158 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].digin.u32F09_param;
1159 Assert(pu32Reg);
1160 if(pu32Reg)
1161 codecSetRegisterU8(pu32Reg, cmd, 0);
1162 return VINF_SUCCESS;
1163}
1164
1165static int codecGetConnectionListEntry(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1166{
1167 Assert((CODEC_CAD(cmd) == pState->id));
1168 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1169 *pResp = 0;
1170 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1171 {
1172 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1173 return VINF_SUCCESS;
1174 }
1175 Assert((cmd & CODEC_VERB_8BIT_DATA) < CODECNODE_F02_PARAM_LENGTH);
1176 if ((cmd & CODEC_VERB_8BIT_DATA) >= CODECNODE_F02_PARAM_LENGTH)
1177 {
1178 Log(("HDAcodec: access to invalid F02 index %d\n", (cmd & CODEC_VERB_8BIT_DATA)));
1179 return VINF_SUCCESS;
1180 }
1181 *pResp = pState->pNodes[CODEC_NID(cmd)].node.au32F02_param[cmd & CODEC_VERB_8BIT_DATA];
1182 return VINF_SUCCESS;
1183}
1184/* F03 */
1185static int codecGetProcessingState(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1186{
1187 Assert((CODEC_CAD(cmd) == pState->id));
1188 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1189 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1190 {
1191 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1192 return VINF_SUCCESS;
1193 }
1194 *pResp = 0;
1195 if (codecIsAdcNode(pState, CODEC_NID(cmd)))
1196 *pResp = pState->pNodes[CODEC_NID(cmd)].adc.u32F03_param;
1197 return VINF_SUCCESS;
1198}
1199
1200/* 703 */
1201static int codecSetProcessingState(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1202{
1203 Assert((CODEC_CAD(cmd) == pState->id));
1204 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1205 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1206 {
1207 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1208 return VINF_SUCCESS;
1209 }
1210 *pResp = 0;
1211 if (codecIsAdcNode(pState, CODEC_NID(cmd)))
1212 {
1213 codecSetRegisterU8(&pState->pNodes[CODEC_NID(cmd)].adc.u32F03_param, cmd, 0);
1214 }
1215 return VINF_SUCCESS;
1216}
1217
1218/* F0D */
1219static int codecGetDigitalConverter(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1220{
1221 Assert((CODEC_CAD(cmd) == pState->id));
1222 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1223 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1224 {
1225 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1226 return VINF_SUCCESS;
1227 }
1228 *pResp = 0;
1229 if (codecIsSpdifOutNode(pState, CODEC_NID(cmd)))
1230 *pResp = pState->pNodes[CODEC_NID(cmd)].spdifout.u32F0d_param;
1231 else if (codecIsSpdifInNode(pState, CODEC_NID(cmd)))
1232 *pResp = pState->pNodes[CODEC_NID(cmd)].spdifin.u32F0d_param;
1233 return VINF_SUCCESS;
1234}
1235
1236static int codecSetDigitalConverter(struct CODECState *pState, uint32_t cmd, uint8_t u8Offset, uint64_t *pResp)
1237{
1238 Assert((CODEC_CAD(cmd) == pState->id));
1239 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1240 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1241 {
1242 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1243 return VINF_SUCCESS;
1244 }
1245 *pResp = 0;
1246 if (codecIsSpdifOutNode(pState, CODEC_NID(cmd)))
1247 codecSetRegisterU8(&pState->pNodes[CODEC_NID(cmd)].spdifout.u32F0d_param, cmd, u8Offset);
1248 else if (codecIsSpdifInNode(pState, CODEC_NID(cmd)))
1249 codecSetRegisterU8(&pState->pNodes[CODEC_NID(cmd)].spdifin.u32F0d_param, cmd, u8Offset);
1250 return VINF_SUCCESS;
1251}
1252
1253/* 70D */
1254static int codecSetDigitalConverter1(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1255{
1256 return codecSetDigitalConverter(pState, cmd, 0, pResp);
1257}
1258
1259/* 70E */
1260static int codecSetDigitalConverter2(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1261{
1262 return codecSetDigitalConverter(pState, cmd, 8, pResp);
1263}
1264
1265static int codecGetSubId(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1266{
1267 Assert((CODEC_CAD(cmd) == pState->id));
1268 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1269 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1270 {
1271 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1272 return VINF_SUCCESS;
1273 }
1274 *pResp = 0;
1275 if (CODEC_NID(cmd) == 1 /* AFG */)
1276 {
1277 *pResp = pState->pNodes[CODEC_NID(cmd)].afg.u32F20_param;
1278 }
1279 return VINF_SUCCESS;
1280}
1281
1282static int codecReset(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1283{
1284 Assert((CODEC_CAD(cmd) == pState->id));
1285 Assert(CODEC_NID(cmd) == 1 /* AFG */);
1286 if(CODEC_NID(cmd) == 1 /* AFG */)
1287 {
1288 uint8_t i;
1289 Log(("HDAcodec: enters reset\n"));
1290 Assert(pState->pfnCodecNodeReset);
1291 for (i = 0; i < pState->cTotalNodes; ++i)
1292 {
1293 pState->pfnCodecNodeReset(pState, i, &pState->pNodes[i]);
1294 }
1295 pState->fInReset = false;
1296 Log(("HDAcodec: exits reset\n"));
1297 }
1298 *pResp = 0;
1299 return VINF_SUCCESS;
1300}
1301
1302/* F05 */
1303static int codecGetPowerState(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1304{
1305 Assert((CODEC_CAD(cmd) == pState->id));
1306 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1307 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1308 {
1309 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1310 return VINF_SUCCESS;
1311 }
1312 *pResp = 0;
1313 if (CODEC_NID(cmd) == 1 /* AFG */)
1314 *pResp = pState->pNodes[CODEC_NID(cmd)].afg.u32F05_param;
1315 else if (codecIsDacNode(pState, CODEC_NID(cmd)))
1316 *pResp = pState->pNodes[CODEC_NID(cmd)].dac.u32F05_param;
1317 else if (codecIsDigInPinNode(pState, CODEC_NID(cmd)))
1318 *pResp = pState->pNodes[CODEC_NID(cmd)].digin.u32F05_param;
1319 else if (codecIsAdcNode(pState, CODEC_NID(cmd)))
1320 *pResp = pState->pNodes[CODEC_NID(cmd)].adc.u32F05_param;
1321 return VINF_SUCCESS;
1322}
1323
1324/* 705 */
1325static int codecSetPowerState(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1326{
1327 Assert((CODEC_CAD(cmd) == pState->id));
1328 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1329 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1330 {
1331 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1332 return VINF_SUCCESS;
1333 }
1334 uint32_t *pu32Reg = NULL;
1335 *pResp = 0;
1336 if (CODEC_NID(cmd) == 1 /* AFG */)
1337 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].afg.u32F05_param;
1338 else if (codecIsDacNode(pState, CODEC_NID(cmd)))
1339 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].dac.u32F05_param;
1340 else if (codecIsDigInPinNode(pState, CODEC_NID(cmd)))
1341 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].digin.u32F05_param;
1342 else if (codecIsAdcNode(pState, CODEC_NID(cmd)))
1343 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].adc.u32F05_param;
1344 Assert((pu32Reg));
1345 if (!pu32Reg)
1346 return VINF_SUCCESS;
1347
1348 if (!CODEC_NID(cmd) == 1 /* AFG */)
1349 {
1350 *pu32Reg &= ~CODEC_VERB_8BIT_DATA;
1351 *pu32Reg |= (pState->pNodes[1].afg.u32F05_param & (CODEC_VERB_4BIT_DATA << 4));
1352 }
1353 else
1354 *pu32Reg &= ~CODEC_VERB_4BIT_DATA;
1355
1356 *pu32Reg |= cmd & CODEC_VERB_4BIT_DATA;
1357 /* Propogate next power state only if AFG is on or verb modifies AFG power state */
1358 if ( CODEC_NID(cmd) == 1 /* AFG */
1359 || !pState->pNodes[1].afg.u32F05_param)
1360 {
1361 *pu32Reg &= ~(CODEC_POWER_MASK << CODEC_POWER_ACT_SHIFT);
1362 *pu32Reg |= (cmd & CODEC_VERB_4BIT_DATA) << 4;
1363 if ( CODEC_NID(cmd) == 1 /* AFG */
1364 && (cmd & CODEC_POWER_MASK) == CODEC_POWER_D0)
1365 {
1366 CODEC_POWER_PROPOGATE_STATE(pState->pNodes[2].dac);
1367 CODEC_POWER_PROPOGATE_STATE(pState->pNodes[3].dac);
1368 CODEC_POWER_PROPOGATE_STATE(pState->pNodes[4].dac);
1369 CODEC_POWER_PROPOGATE_STATE(pState->pNodes[5].dac);
1370 CODEC_POWER_PROPOGATE_STATE(pState->pNodes[6].dac);
1371 CODEC_POWER_PROPOGATE_STATE(pState->pNodes[7].dac);
1372 CODEC_POWER_PROPOGATE_STATE(pState->pNodes[0x11].dac);
1373 }
1374 }
1375 return VINF_SUCCESS;
1376}
1377
1378static int codecGetStreamId(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1379{
1380 Assert((CODEC_CAD(cmd) == pState->id));
1381 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1382 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1383 {
1384 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1385 return VINF_SUCCESS;
1386 }
1387 *pResp = 0;
1388 if (codecIsDacNode(pState, CODEC_NID(cmd)))
1389 *pResp = pState->pNodes[CODEC_NID(cmd)].dac.u32F06_param;
1390 else if (codecIsAdcNode(pState, CODEC_NID(cmd)))
1391 *pResp = pState->pNodes[CODEC_NID(cmd)].adc.u32F06_param;
1392 else if (codecIsSpdifInNode(pState, CODEC_NID(cmd)))
1393 *pResp = pState->pNodes[CODEC_NID(cmd)].spdifin.u32F06_param;
1394 else if (codecIsSpdifOutNode(pState, CODEC_NID(cmd)))
1395 *pResp = pState->pNodes[CODEC_NID(cmd)].spdifout.u32F06_param;
1396 else if (CODEC_NID(cmd) == 0x1A)
1397 *pResp = pState->pNodes[CODEC_NID(cmd)].reserved.u32F06_param;
1398 return VINF_SUCCESS;
1399}
1400static int codecSetStreamId(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1401{
1402 Assert((CODEC_CAD(cmd) == pState->id));
1403 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1404 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1405 {
1406 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1407 return VINF_SUCCESS;
1408 }
1409 *pResp = 0;
1410 uint32_t *pu32addr = NULL;
1411 *pResp = 0;
1412 if (codecIsDacNode(pState, CODEC_NID(cmd)))
1413 pu32addr = &pState->pNodes[CODEC_NID(cmd)].dac.u32F06_param;
1414 else if (codecIsAdcNode(pState, CODEC_NID(cmd)))
1415 pu32addr = &pState->pNodes[CODEC_NID(cmd)].adc.u32F06_param;
1416 else if (codecIsSpdifOutNode(pState, CODEC_NID(cmd)))
1417 pu32addr = &pState->pNodes[CODEC_NID(cmd)].spdifout.u32F06_param;
1418 else if (codecIsSpdifInNode(pState, CODEC_NID(cmd)))
1419 pu32addr = &pState->pNodes[CODEC_NID(cmd)].spdifin.u32F06_param;
1420 else if (codecIsReservedNode(pState, CODEC_NID(cmd)))
1421 pu32addr = &pState->pNodes[CODEC_NID(cmd)].reserved.u32F06_param;
1422 Assert((pu32addr));
1423 if (pu32addr)
1424 codecSetRegisterU8(pu32addr, cmd, 0);
1425 return VINF_SUCCESS;
1426}
1427static int codecGetConverterFormat(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1428{
1429 Assert((CODEC_CAD(cmd) == pState->id));
1430 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1431 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1432 {
1433 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1434 return VINF_SUCCESS;
1435 }
1436 *pResp = 0;
1437 if (codecIsDacNode(pState, CODEC_NID(cmd)))
1438 *pResp = pState->pNodes[CODEC_NID(cmd)].dac.u32A_param;
1439 else if (codecIsAdcNode(pState, CODEC_NID(cmd)))
1440 *pResp = pState->pNodes[CODEC_NID(cmd)].adc.u32A_param;
1441 else if (codecIsSpdifOutNode(pState, CODEC_NID(cmd)))
1442 *pResp = pState->pNodes[CODEC_NID(cmd)].spdifout.u32A_param;
1443 else if (codecIsSpdifInNode(pState, CODEC_NID(cmd)))
1444 *pResp = pState->pNodes[CODEC_NID(cmd)].spdifin.u32A_param;
1445 return VINF_SUCCESS;
1446}
1447
1448static int codecSetConverterFormat(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1449{
1450 Assert((CODEC_CAD(cmd) == pState->id));
1451 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1452 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1453 {
1454 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1455 return VINF_SUCCESS;
1456 }
1457 *pResp = 0;
1458 if (codecIsDacNode(pState, CODEC_NID(cmd)))
1459 codecSetRegisterU16(&pState->pNodes[CODEC_NID(cmd)].dac.u32A_param, cmd, 0);
1460 else if (codecIsAdcNode(pState, CODEC_NID(cmd)))
1461 codecSetRegisterU16(&pState->pNodes[CODEC_NID(cmd)].adc.u32A_param, cmd, 0);
1462 else if (codecIsSpdifOutNode(pState, CODEC_NID(cmd)))
1463 codecSetRegisterU16(&pState->pNodes[CODEC_NID(cmd)].spdifout.u32A_param, cmd, 0);
1464 else if (codecIsSpdifInNode(pState, CODEC_NID(cmd)))
1465 codecSetRegisterU16(&pState->pNodes[CODEC_NID(cmd)].spdifin.u32A_param, cmd, 0);
1466 return VINF_SUCCESS;
1467}
1468
1469/* F0C */
1470static int codecGetEAPD_BTLEnabled(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1471{
1472 Assert((CODEC_CAD(cmd) == pState->id));
1473 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1474 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1475 {
1476 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1477 return VINF_SUCCESS;
1478 }
1479 *pResp = 0;
1480 if (codecIsAdcVolNode(pState, CODEC_NID(cmd)))
1481 *pResp = pState->pNodes[CODEC_NID(cmd)].adcvol.u32F0c_param;
1482 else if (codecIsDacNode(pState, CODEC_NID(cmd)))
1483 *pResp = pState->pNodes[CODEC_NID(cmd)].dac.u32F0c_param;
1484 else if (codecIsDigInPinNode(pState, CODEC_NID(cmd)))
1485 *pResp = pState->pNodes[CODEC_NID(cmd)].digin.u32F0c_param;
1486 return VINF_SUCCESS;
1487}
1488
1489/* 70C */
1490static int codecSetEAPD_BTLEnabled(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1491{
1492 Assert((CODEC_CAD(cmd) == pState->id));
1493 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1494 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1495 {
1496 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1497 return VINF_SUCCESS;
1498 }
1499 *pResp = 0;
1500 uint32_t *pu32Reg = NULL;
1501 if (codecIsAdcVolNode(pState, CODEC_NID(cmd)))
1502 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].adcvol.u32F0c_param;
1503 else if (codecIsDacNode(pState, CODEC_NID(cmd)))
1504 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].dac.u32F0c_param;
1505 else if (codecIsDigInPinNode(pState, CODEC_NID(cmd)))
1506 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].digin.u32F0c_param;
1507 *pResp = 0;
1508 Assert((pu32Reg));
1509 if (pu32Reg)
1510 codecSetRegisterU8(pu32Reg, cmd, 0);
1511 return VINF_SUCCESS;
1512}
1513
1514/* F0F */
1515static int codecGetVolumeKnobCtrl(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1516{
1517 Assert((CODEC_CAD(cmd) == pState->id));
1518 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1519 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1520 {
1521 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1522 return VINF_SUCCESS;
1523 }
1524 *pResp = 0;
1525 if (codecIsVolKnobNode(pState, CODEC_NID(cmd)))
1526 *pResp = pState->pNodes[CODEC_NID(cmd)].volumeKnob.u32F0f_param;
1527 return VINF_SUCCESS;
1528}
1529
1530/* 70F */
1531static int codecSetVolumeKnobCtrl(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1532{
1533 Assert((CODEC_CAD(cmd) == pState->id));
1534 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1535 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1536 {
1537 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1538 return VINF_SUCCESS;
1539 }
1540 uint32_t *pu32Reg = NULL;
1541 *pResp = 0;
1542 if (codecIsVolKnobNode(pState, CODEC_NID(cmd)))
1543 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].volumeKnob.u32F0f_param;
1544 Assert((pu32Reg));
1545 if (pu32Reg)
1546 codecSetRegisterU8(pu32Reg, cmd, 0);
1547 return VINF_SUCCESS;
1548}
1549
1550/* F1C */
1551static int codecGetConfig (struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1552{
1553 Assert((CODEC_CAD(cmd) == pState->id));
1554 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1555 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1556 {
1557 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1558 return VINF_SUCCESS;
1559 }
1560 *pResp = 0;
1561 if (codecIsPortNode(pState, CODEC_NID(cmd)))
1562 *pResp = pState->pNodes[CODEC_NID(cmd)].port.u32F1c_param;
1563 else if (codecIsDigOutPinNode(pState, CODEC_NID(cmd)))
1564 *pResp = pState->pNodes[CODEC_NID(cmd)].digout.u32F1c_param;
1565 else if (codecIsDigInPinNode(pState, CODEC_NID(cmd)))
1566 *pResp = pState->pNodes[CODEC_NID(cmd)].digin.u32F1c_param;
1567 else if (codecIsCdNode(pState, CODEC_NID(cmd)))
1568 *pResp = pState->pNodes[CODEC_NID(cmd)].cdnode.u32F1c_param;
1569 return VINF_SUCCESS;
1570}
1571static int codecSetConfigX(struct CODECState *pState, uint32_t cmd, uint8_t u8Offset)
1572{
1573 Assert((CODEC_CAD(cmd) == pState->id));
1574 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1575 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1576 {
1577 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1578 return VINF_SUCCESS;
1579 }
1580 uint32_t *pu32Reg = NULL;
1581 if (codecIsPortNode(pState, CODEC_NID(cmd)))
1582 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].port.u32F1c_param;
1583 else if (codecIsDigInPinNode(pState, CODEC_NID(cmd)))
1584 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].digin.u32F1c_param;
1585 else if (codecIsDigOutPinNode(pState, CODEC_NID(cmd)))
1586 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].digout.u32F1c_param;
1587 else if (codecIsCdNode(pState, CODEC_NID(cmd)))
1588 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].cdnode.u32F1c_param;
1589 else if ( CODEC_NID(cmd) == 0x1B
1590 && pState->enmCodec == STAC9220_CODEC)
1591 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].reserved.u32F1c_param;
1592 Assert((pu32Reg));
1593 if (pu32Reg)
1594 codecSetRegisterU8(pu32Reg, cmd, u8Offset);
1595 return VINF_SUCCESS;
1596}
1597/* 71C */
1598static int codecSetConfig0 (struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1599{
1600 *pResp = 0;
1601 return codecSetConfigX(pState, cmd, 0);
1602}
1603/* 71D */
1604static int codecSetConfig1 (struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1605{
1606 *pResp = 0;
1607 return codecSetConfigX(pState, cmd, 8);
1608}
1609/* 71E */
1610static int codecSetConfig2 (struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1611{
1612 *pResp = 0;
1613 return codecSetConfigX(pState, cmd, 16);
1614}
1615/* 71E */
1616static int codecSetConfig3 (struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1617{
1618 *pResp = 0;
1619 return codecSetConfigX(pState, cmd, 24);
1620}
1621
1622
1623static int codecToAudVolume(AMPLIFIER *pAmp, audmixerctl_t mt)
1624{
1625 uint32_t dir = AMPLIFIER_OUT;
1626 switch (mt)
1627 {
1628 case AUD_MIXER_VOLUME:
1629 case AUD_MIXER_PCM:
1630 dir = AMPLIFIER_OUT;
1631 break;
1632 case AUD_MIXER_LINE_IN:
1633 dir = AMPLIFIER_IN;
1634 break;
1635 }
1636 int mute = AMPLIFIER_REGISTER(*pAmp, dir, AMPLIFIER_LEFT, 0) & RT_BIT(7);
1637 mute |= AMPLIFIER_REGISTER(*pAmp, dir, AMPLIFIER_RIGHT, 0) & RT_BIT(7);
1638 mute >>=7;
1639 mute &= 0x1;
1640 uint8_t lVol = AMPLIFIER_REGISTER(*pAmp, dir, AMPLIFIER_LEFT, 0) & 0x7f;
1641 uint8_t rVol = AMPLIFIER_REGISTER(*pAmp, dir, AMPLIFIER_RIGHT, 0) & 0x7f;
1642 AUD_set_volume(mt, &mute, &lVol, &rVol);
1643 return VINF_SUCCESS;
1644}
1645
1646static CODECVERB CODECVERBS[] =
1647{
1648/* verb | verb mask | callback */
1649/* ----------- -------------------- ----------------------- */
1650 {0x000F0000, CODEC_VERB_8BIT_CMD , codecGetParameter },
1651 {0x000F0100, CODEC_VERB_8BIT_CMD , codecGetConSelectCtrl },
1652 {0x00070100, CODEC_VERB_8BIT_CMD , codecSetConSelectCtrl },
1653 {0x000F0600, CODEC_VERB_8BIT_CMD , codecGetStreamId },
1654 {0x00070600, CODEC_VERB_8BIT_CMD , codecSetStreamId },
1655 {0x000F0700, CODEC_VERB_8BIT_CMD , codecGetPinCtrl },
1656 {0x00070700, CODEC_VERB_8BIT_CMD , codecSetPinCtrl },
1657 {0x000F0800, CODEC_VERB_8BIT_CMD , codecGetUnsolicitedEnabled },
1658 {0x00070800, CODEC_VERB_8BIT_CMD , codecSetUnsolicitedEnabled },
1659 {0x000F0900, CODEC_VERB_8BIT_CMD , codecGetPinSense },
1660 {0x00070900, CODEC_VERB_8BIT_CMD , codecSetPinSense },
1661 {0x000F0200, CODEC_VERB_8BIT_CMD , codecGetConnectionListEntry },
1662 {0x000F0300, CODEC_VERB_8BIT_CMD , codecGetProcessingState },
1663 {0x00070300, CODEC_VERB_8BIT_CMD , codecSetProcessingState },
1664 {0x000F0D00, CODEC_VERB_8BIT_CMD , codecGetDigitalConverter },
1665 {0x00070D00, CODEC_VERB_8BIT_CMD , codecSetDigitalConverter1 },
1666 {0x00070E00, CODEC_VERB_8BIT_CMD , codecSetDigitalConverter2 },
1667 {0x000F2000, CODEC_VERB_8BIT_CMD , codecGetSubId },
1668 {0x0007FF00, CODEC_VERB_8BIT_CMD , codecReset },
1669 {0x000F0500, CODEC_VERB_8BIT_CMD , codecGetPowerState },
1670 {0x00070500, CODEC_VERB_8BIT_CMD , codecSetPowerState },
1671 {0x000F0C00, CODEC_VERB_8BIT_CMD , codecGetEAPD_BTLEnabled },
1672 {0x00070C00, CODEC_VERB_8BIT_CMD , codecSetEAPD_BTLEnabled },
1673 {0x000F0F00, CODEC_VERB_8BIT_CMD , codecGetVolumeKnobCtrl },
1674 {0x00070F00, CODEC_VERB_8BIT_CMD , codecSetVolumeKnobCtrl },
1675 {0x000F1C00, CODEC_VERB_8BIT_CMD , codecGetConfig },
1676 {0x00071C00, CODEC_VERB_8BIT_CMD , codecSetConfig0 },
1677 {0x00071D00, CODEC_VERB_8BIT_CMD , codecSetConfig1 },
1678 {0x00071E00, CODEC_VERB_8BIT_CMD , codecSetConfig2 },
1679 {0x00071F00, CODEC_VERB_8BIT_CMD , codecSetConfig3 },
1680 {0x000A0000, CODEC_VERB_16BIT_CMD, codecGetConverterFormat },
1681 {0x00020000, CODEC_VERB_16BIT_CMD, codecSetConverterFormat },
1682 {0x000B0000, CODEC_VERB_16BIT_CMD, codecGetAmplifier },
1683 {0x00030000, CODEC_VERB_16BIT_CMD, codecSetAmplifier },
1684};
1685
1686static int codecLookup(CODECState *pState, uint32_t cmd, PPFNCODECVERBPROCESSOR pfn)
1687{
1688 int rc = VINF_SUCCESS;
1689 Assert(CODEC_CAD(cmd) == pState->id);
1690 if (codecIsReservedNode(pState, CODEC_NID(cmd)))
1691 {
1692 LogRel(("HDAcodec: cmd %x was addressed to reseved node\n", cmd));
1693 }
1694 if ( CODEC_VERBDATA(cmd) == 0
1695 || CODEC_NID(cmd) >= pState->cTotalNodes)
1696 {
1697 *pfn = codecUnimplemented;
1698 //** @todo r=michaln: There needs to be a counter to avoid log flooding (see e.g. DevRTC.cpp)
1699 LogRel(("HDAcodec: cmd %x was ignored\n", cmd));
1700 return VINF_SUCCESS;
1701 }
1702 for (int i = 0; i < pState->cVerbs; ++i)
1703 {
1704 if ((CODEC_VERBDATA(cmd) & pState->pVerbs[i].mask) == pState->pVerbs[i].verb)
1705 {
1706 *pfn = pState->pVerbs[i].pfn;
1707 return VINF_SUCCESS;
1708 }
1709 }
1710 *pfn = codecUnimplemented;
1711 LogRel(("HDAcodec: callback for %x wasn't found\n", CODEC_VERBDATA(cmd)));
1712 return rc;
1713}
1714
1715static int codec_dac_to_aud(CODECState *pState, audsettings_t *paud)
1716{
1717 paud->freq = 44100;
1718 paud->nchannels = 2;
1719 paud->fmt = AUD_FMT_S16;
1720
1721 paud->endianness = 0;
1722 return VINF_SUCCESS;
1723}
1724
1725static void pi_callback (void *opaque, int avail)
1726{
1727 CODECState *pState = (CODECState *)opaque;
1728 pState->pfnTransfer(pState, PI_INDEX, avail);
1729}
1730
1731static void po_callback (void *opaque, int avail)
1732{
1733 CODECState *pState = (CODECState *)opaque;
1734 pState->pfnTransfer(pState, PO_INDEX, avail);
1735}
1736
1737static void mc_callback (void *opaque, int avail)
1738{
1739 CODECState *pState = (CODECState *)opaque;
1740 pState->pfnTransfer(pState, MC_INDEX, avail);
1741}
1742
1743int codecConstruct(CODECState *pState, ENMCODEC enmCodec)
1744{
1745 audsettings_t as;
1746 int rc;
1747 pState->pVerbs = (CODECVERB *)&CODECVERBS;
1748 pState->cVerbs = sizeof(CODECVERBS)/sizeof(CODECVERB);
1749 pState->pfnLookup = codecLookup;
1750 pState->enmCodec = enmCodec;
1751 switch (enmCodec)
1752 {
1753 case STAC9220_CODEC:
1754 rc = stac9220Construct(pState);
1755 AssertRC(rc);
1756 break;
1757 case ALC885_CODEC:
1758 rc = alc885Construct(pState);
1759 AssertRC(rc);
1760 break;
1761 default:
1762 AssertMsgFailed(("Unsupported Codec"));
1763 }
1764 uint8_t i;
1765 Assert(pState->pNodes);
1766 Assert(pState->pfnCodecNodeReset);
1767 for (i = 0; i < pState->cTotalNodes; ++i)
1768 {
1769 pState->pfnCodecNodeReset(pState, i, &pState->pNodes[i]);
1770 }
1771 //** @todo r=michaln: Was this meant to be 'HDA' or something like that? (AC'97 was on ICH0)
1772 AUD_register_card ("ICH0", &pState->card);
1773
1774 codec_dac_to_aud(pState, &as);
1775 pState->voice_pi = AUD_open_in(&pState->card, pState->voice_pi, "hda.in", pState, pi_callback, &as);
1776 codec_dac_to_aud(pState, &as);
1777 pState->voice_po = AUD_open_out(&pState->card, pState->voice_po, "hda.out", pState, po_callback, &as);
1778 if (!pState->voice_pi)
1779 LogRel (("HDAcodec: WARNING: Unable to open PCM IN!\n"));
1780 if (!pState->voice_po)
1781 LogRel (("HDAcodec: WARNING: Unable to open PCM OUT!\n"));
1782 codecToAudVolume(&pState->pNodes[pState->u8DacLineOut].dac.B_params, AUD_MIXER_VOLUME);
1783 codecToAudVolume(&pState->pNodes[pState->u8AdcVolsLineIn].adcvol.B_params, AUD_MIXER_LINE_IN);
1784
1785 return VINF_SUCCESS;
1786}
1787int codecDestruct(CODECState *pCodecState)
1788{
1789 RTMemFree(pCodecState->pNodes);
1790 return VINF_SUCCESS;
1791}
1792
1793int codecSaveState(CODECState *pCodecState, PSSMHANDLE pSSMHandle)
1794{
1795 SSMR3PutMem (pSSMHandle, pCodecState->pNodes, sizeof(CODECNODE) * pCodecState->cTotalNodes);
1796 return VINF_SUCCESS;
1797}
1798
1799int codecLoadState(CODECState *pCodecState, PSSMHANDLE pSSMHandle)
1800{
1801 SSMR3GetMem (pSSMHandle, pCodecState->pNodes, sizeof(CODECNODE) * pCodecState->cTotalNodes);
1802 codecToAudVolume(&pCodecState->pNodes[pCodecState->u8DacLineOut].dac.B_params, AUD_MIXER_VOLUME);
1803 codecToAudVolume(&pCodecState->pNodes[pCodecState->u8AdcVolsLineIn].adcvol.B_params, AUD_MIXER_LINE_IN);
1804 return VINF_SUCCESS;
1805}
Note: See TracBrowser for help on using the repository browser.

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