VirtualBox

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

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

Audio/HDA: some todos.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 55.7 KB
Line 
1/* $Id: DevCodec.cpp 32805 2010-09-29 05:41:11Z 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.au8F02_param[0] = 0x17;
177 goto adc_init;
178 case 7:
179 pNode->adc.node.name = "ADC1";
180 pNode->node.au8F02_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.au8F02_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 *(uint32_t *)pNode->node.au8F02_param = 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 *(uint32_t *)pNode->node.au8F02_param = 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 *(uint32_t *)pNode->node.au8F02_param = 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 *(uint32_t *)pNode->node.au8F02_param = 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.au8F02_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 *(uint32_t *)pNode->node.au8F02_param = 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 *(uint32_t *)&pNode->node.au8F02_param[0] = RT_MAKE_U32_FROM_U8(0xe, 0x15, 0xf, 0xb);
311 *(uint32_t *)&pNode->node.au8F02_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 *(uint32_t *)pNode->node.au8F02_param = 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 *(uint32_t *)pNode->node.au8F02_param = 0x12;
340 goto adcvol_init;
341 case 0x18:
342 pNode->node.name = "ADC1Vol";
343 *(uint32_t *)pNode->node.au8F02_param = 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.au8F02_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/* generic */
376
377#define CODEC_POWER_MASK 0x3
378#define CODEC_POWER_ACT_SHIFT (4)
379#define CODEC_POWER_SET_SHIFT (0)
380#define CODEC_POWER_D0 (0)
381#define CODEC_POWER_D1 (1)
382#define CODEC_POWER_D2 (2)
383#define CODEC_POWER_D3 (3)
384#define CODEC_POWER_PROPOGATE_STATE(node) \
385 do { \
386 node.u32F05_param &= (CODEC_POWER_MASK); \
387 node.u32F05_param |= (node.u32F05_param & CODEC_POWER_MASK) << CODEC_POWER_ACT_SHIFT; \
388 }while(0)
389
390#define DECLISNODEOFTYPE(type) \
391 static inline int codecIs##type##Node(struct CODECState *pState, uint8_t cNode) \
392 { \
393 Assert(pState->au8##type##s); \
394 for(int i = 0; pState->au8##type##s[i] != 0; ++i) \
395 if (pState->au8##type##s[i] == cNode) \
396 return 1; \
397 return 0; \
398 }
399/* codecIsPortNode */
400DECLISNODEOFTYPE(Port)
401/* codecIsDacNode */
402DECLISNODEOFTYPE(Dac)
403/* codecIsAdcVolNode */
404DECLISNODEOFTYPE(AdcVol)
405/* codecIsAdcNode */
406DECLISNODEOFTYPE(Adc)
407/* codecIsAdcMuxNode */
408DECLISNODEOFTYPE(AdcMux)
409/* codecIsPcbeepNode */
410DECLISNODEOFTYPE(Pcbeep)
411/* codecIsSpdifOutNode */
412DECLISNODEOFTYPE(SpdifOut)
413/* codecIsSpdifInNode */
414DECLISNODEOFTYPE(SpdifIn)
415/* codecIsDigInPinNode */
416DECLISNODEOFTYPE(DigInPin)
417/* codecIsDigOutPinNode */
418DECLISNODEOFTYPE(DigOutPin)
419/* codecIsCdNode */
420DECLISNODEOFTYPE(Cd)
421/* codecIsVolKnobNode */
422DECLISNODEOFTYPE(VolKnob)
423/* codecIsReservedNode */
424DECLISNODEOFTYPE(Reserved)
425
426static int codecToAudVolume(AMPLIFIER *pAmp, audmixerctl_t mt);
427
428static inline void codecSetRegister(uint32_t *pu32Reg, uint32_t u32Cmd, uint8_t u8Offset, uint32_t mask)
429{
430 Assert((pu32Reg && u8Offset < 32));
431 *pu32Reg &= ~(mask << u8Offset);
432 *pu32Reg |= (u32Cmd & mask) << u8Offset;
433}
434static inline void codecSetRegisterU8(uint32_t *pu32Reg, uint32_t u32Cmd, uint8_t u8Offset)
435{
436 codecSetRegister(pu32Reg, u32Cmd, u8Offset, CODEC_VERB_8BIT_DATA);
437}
438
439static inline void codecSetRegisterU16(uint32_t *pu32Reg, uint32_t u32Cmd, uint8_t u8Offset)
440{
441 codecSetRegister(pu32Reg, u32Cmd, u8Offset, CODEC_VERB_16BIT_DATA);
442}
443
444
445static int codecUnimplemented(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
446{
447 Log(("codecUnimplemented: cmd(raw:%x: cad:%x, d:%c, nid:%x, verb:%x)\n", cmd,
448 CODEC_CAD(cmd), CODEC_DIRECT(cmd) ? 'N' : 'Y', CODEC_NID(cmd), CODEC_VERBDATA(cmd)));
449 *pResp = 0;
450 return VINF_SUCCESS;
451}
452
453static int codecBreak(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
454{
455 int rc;
456 rc = codecUnimplemented(pState, cmd, pResp);
457 *pResp |= CODEC_RESPONSE_UNSOLICITED;
458 return rc;
459}
460/* B-- */
461static int codecGetAmplifier(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
462{
463 Assert((CODEC_CAD(cmd) == pState->id));
464 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
465 if (CODEC_NID(cmd) >= pState->cTotalNodes)
466 {
467 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
468 return VINF_SUCCESS;
469 }
470 *pResp = 0;
471 /* HDA spec 7.3.3.7 Note A */
472 /* @todo: if index out of range response should be 0 */
473 uint8_t u8Index = CODEC_GET_AMP_DIRECTION(cmd) == AMPLIFIER_OUT? 0 : CODEC_GET_AMP_INDEX(cmd);
474
475 PCODECNODE pNode = &pState->pNodes[CODEC_NID(cmd)];
476 if (codecIsDacNode(pState, CODEC_NID(cmd)))
477 *pResp = AMPLIFIER_REGISTER(pNode->dac.B_params,
478 CODEC_GET_AMP_DIRECTION(cmd),
479 CODEC_GET_AMP_SIDE(cmd),
480 u8Index);
481 else if (codecIsAdcVolNode(pState, CODEC_NID(cmd)))
482 *pResp = AMPLIFIER_REGISTER(pNode->adcvol.B_params,
483 CODEC_GET_AMP_DIRECTION(cmd),
484 CODEC_GET_AMP_SIDE(cmd),
485 u8Index);
486 else if (codecIsAdcMuxNode(pState, CODEC_NID(cmd)))
487 *pResp = AMPLIFIER_REGISTER(pNode->adcmux.B_params,
488 CODEC_GET_AMP_DIRECTION(cmd),
489 CODEC_GET_AMP_SIDE(cmd),
490 u8Index);
491 else if (codecIsPcbeepNode(pState, CODEC_NID(cmd)))
492 *pResp = AMPLIFIER_REGISTER(pNode->pcbeep.B_params,
493 CODEC_GET_AMP_DIRECTION(cmd),
494 CODEC_GET_AMP_SIDE(cmd),
495 u8Index);
496 else{
497 AssertMsgReturn(0, ("access to fields of %x need to be implemented\n", CODEC_NID(cmd)), VINF_SUCCESS);
498 }
499 return VINF_SUCCESS;
500}
501/* 3-- */
502static int codecSetAmplifier(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
503{
504 AMPLIFIER *pAmplifier = NULL;
505 bool fIsLeft = false;
506 bool fIsRight = false;
507 bool fIsOut = false;
508 bool fIsIn = false;
509 uint8_t u8Index = 0;
510 Assert((CODEC_CAD(cmd) == pState->id));
511 if (CODEC_NID(cmd) >= pState->cTotalNodes)
512 {
513 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
514 return VINF_SUCCESS;
515 }
516 *pResp = 0;
517 PCODECNODE pNode = &pState->pNodes[CODEC_NID(cmd)];
518 if (codecIsDacNode(pState, CODEC_NID(cmd)))
519 pAmplifier = &pNode->dac.B_params;
520 else if (codecIsAdcVolNode(pState, CODEC_NID(cmd)))
521 pAmplifier = &pNode->adcvol.B_params;
522 else if (codecIsAdcMuxNode(pState, CODEC_NID(cmd)))
523 pAmplifier = &pNode->adcmux.B_params;
524 else if (codecIsPcbeepNode(pState, CODEC_NID(cmd)))
525 pAmplifier = &pNode->pcbeep.B_params;
526 Assert(pAmplifier);
527 if (pAmplifier)
528 {
529 fIsOut = CODEC_SET_AMP_IS_OUT_DIRECTION(cmd);
530 fIsIn = CODEC_SET_AMP_IS_IN_DIRECTION(cmd);
531 fIsRight = CODEC_SET_AMP_IS_RIGHT_SIDE(cmd);
532 fIsLeft = CODEC_SET_AMP_IS_LEFT_SIDE(cmd);
533 u8Index = CODEC_SET_AMP_INDEX(cmd);
534 if ( (!fIsLeft && !fIsRight)
535 || (!fIsOut && !fIsIn))
536 return VINF_SUCCESS;
537 if (fIsIn)
538 {
539 if (fIsLeft)
540 codecSetRegisterU8(&AMPLIFIER_REGISTER(*pAmplifier, AMPLIFIER_IN, AMPLIFIER_LEFT, u8Index), cmd, 0);
541 if (fIsRight)
542 codecSetRegisterU8(&AMPLIFIER_REGISTER(*pAmplifier, AMPLIFIER_IN, AMPLIFIER_RIGHT, u8Index), cmd, 0);
543 }
544 if (fIsOut)
545 {
546 if (fIsLeft)
547 codecSetRegisterU8(&AMPLIFIER_REGISTER(*pAmplifier, AMPLIFIER_OUT, AMPLIFIER_LEFT, u8Index), cmd, 0);
548 if (fIsRight)
549 codecSetRegisterU8(&AMPLIFIER_REGISTER(*pAmplifier, AMPLIFIER_OUT, AMPLIFIER_RIGHT, u8Index), cmd, 0);
550 }
551 if (CODEC_NID(cmd) == 2)
552 codecToAudVolume(pAmplifier, AUD_MIXER_VOLUME);
553 if (CODEC_NID(cmd) == 0x17) /* Microphone */
554 codecToAudVolume(pAmplifier, AUD_MIXER_LINE_IN);
555 }
556 return VINF_SUCCESS;
557}
558
559static int codecGetParameter(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
560{
561 Assert((CODEC_CAD(cmd) == pState->id));
562 if (CODEC_NID(cmd) >= pState->cTotalNodes)
563 {
564 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
565 return VINF_SUCCESS;
566 }
567 Assert(((cmd & CODEC_VERB_8BIT_DATA) < CODECNODE_F0_PARAM_LENGTH));
568 if ((cmd & CODEC_VERB_8BIT_DATA) >= CODECNODE_F0_PARAM_LENGTH)
569 {
570 Log(("HDAcodec: invalid F00 parameter %d\n", (cmd & CODEC_VERB_8BIT_DATA)));
571 return VINF_SUCCESS;
572 }
573 *pResp = 0;
574 *pResp = pState->pNodes[CODEC_NID(cmd)].node.au32F00_param[cmd & CODEC_VERB_8BIT_DATA];
575 return VINF_SUCCESS;
576}
577
578/* F01 */
579static int codecGetConSelectCtrl(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
580{
581 Assert((CODEC_CAD(cmd) == pState->id));
582 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
583 if (CODEC_NID(cmd) >= pState->cTotalNodes)
584 {
585 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
586 return VINF_SUCCESS;
587 }
588 *pResp = 0;
589 if (codecIsAdcMuxNode(pState, CODEC_NID(cmd)))
590 *pResp = pState->pNodes[CODEC_NID(cmd)].adcmux.u32F01_param;
591 else if (codecIsDigOutPinNode(pState, CODEC_NID(cmd)))
592 *pResp = pState->pNodes[CODEC_NID(cmd)].digout.u32F01_param;
593 return VINF_SUCCESS;
594}
595
596/* 701 */
597static int codecSetConSelectCtrl(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
598{
599 uint32_t *pu32Reg = NULL;
600 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
601 if (CODEC_NID(cmd) >= pState->cTotalNodes)
602 {
603 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
604 return VINF_SUCCESS;
605 }
606 *pResp = 0;
607 if (codecIsAdcMuxNode(pState, CODEC_NID(cmd)))
608 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].adcmux.u32F01_param;
609 else if (codecIsDigOutPinNode(pState, CODEC_NID(cmd)))
610 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].digout.u32F01_param;
611 Assert((pu32Reg));
612 if (pu32Reg)
613 codecSetRegisterU8(pu32Reg, cmd, 0);
614 return VINF_SUCCESS;
615}
616
617/* F07 */
618static int codecGetPinCtrl(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
619{
620 Assert((CODEC_CAD(cmd) == pState->id));
621 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
622 if (CODEC_NID(cmd) >= pState->cTotalNodes)
623 {
624 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
625 return VINF_SUCCESS;
626 }
627 *pResp = 0;
628 if (codecIsPortNode(pState, CODEC_NID(cmd)))
629 *pResp = pState->pNodes[CODEC_NID(cmd)].port.u32F07_param;
630 else if (codecIsDigOutPinNode(pState, CODEC_NID(cmd)))
631 *pResp = pState->pNodes[CODEC_NID(cmd)].digout.u32F07_param;
632 else if (codecIsDigInPinNode(pState, CODEC_NID(cmd)))
633 *pResp = pState->pNodes[CODEC_NID(cmd)].digin.u32F07_param;
634 else if (codecIsCdNode(pState, CODEC_NID(cmd)))
635 *pResp = pState->pNodes[CODEC_NID(cmd)].cdnode.u32F07_param;
636 else if ( codecIsReservedNode(pState, CODEC_NID(cmd))
637 && CODEC_NID(cmd) == 0x1b)
638 *pResp = pState->pNodes[CODEC_NID(cmd)].reserved.u32F07_param;
639 else
640 AssertMsgFailed(("Unsupported"));
641 return VINF_SUCCESS;
642}
643
644/* 707 */
645static int codecSetPinCtrl(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
646{
647 Assert((CODEC_CAD(cmd) == pState->id));
648 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
649 if (CODEC_NID(cmd) >= pState->cTotalNodes)
650 {
651 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
652 return VINF_SUCCESS;
653 }
654 *pResp = 0;
655 uint32_t *pu32Reg = NULL;
656 if (codecIsPortNode(pState, CODEC_NID(cmd)))
657 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].port.u32F07_param;
658 else if (codecIsDigInPinNode(pState, CODEC_NID(cmd)))
659 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].digin.u32F07_param;
660 else if (codecIsDigOutPinNode(pState, CODEC_NID(cmd)))
661 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].digout.u32F07_param;
662 else if (codecIsCdNode(pState, CODEC_NID(cmd)))
663 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].cdnode.u32F07_param;
664 else if ( codecIsReservedNode(pState, CODEC_NID(cmd))
665 && CODEC_NID(cmd) == 0x1b)
666 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].reserved.u32F07_param;
667 Assert((pu32Reg));
668 if (pu32Reg)
669 codecSetRegisterU8(pu32Reg, cmd, 0);
670 return VINF_SUCCESS;
671}
672
673/* F08 */
674static int codecGetUnsolicitedEnabled(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
675{
676 Assert((CODEC_CAD(cmd) == pState->id));
677 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
678 if (CODEC_NID(cmd) >= pState->cTotalNodes)
679 {
680 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
681 return VINF_SUCCESS;
682 }
683 *pResp = 0;
684 if (codecIsPortNode(pState, CODEC_NID(cmd)))
685 *pResp = pState->pNodes[CODEC_NID(cmd)].port.u32F08_param;
686 else if (codecIsDigInPinNode(pState, CODEC_NID(cmd)))
687 *pResp = pState->pNodes[CODEC_NID(cmd)].digin.u32F08_param;
688 else if ((cmd) == 1 /* AFG */)
689 *pResp = pState->pNodes[CODEC_NID(cmd)].afg.u32F08_param;
690 else if (codecIsVolKnobNode(pState, CODEC_NID(cmd)))
691 *pResp = pState->pNodes[CODEC_NID(cmd)].volumeKnob.u32F08_param;
692 else
693 AssertMsgFailed(("unsupported operation %x on node: %x\n", CODEC_VERB_CMD8(cmd), CODEC_NID(cmd)));
694 return VINF_SUCCESS;
695}
696
697/* 708 */
698static int codecSetUnsolicitedEnabled(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
699{
700 Assert((CODEC_CAD(cmd) == pState->id));
701 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
702 if (CODEC_NID(cmd) >= pState->cTotalNodes)
703 {
704 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
705 return VINF_SUCCESS;
706 }
707 *pResp = 0;
708 uint32_t *pu32Reg = NULL;
709 if (codecIsPortNode(pState, CODEC_NID(cmd)))
710 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].port.u32F08_param;
711 else if (codecIsDigInPinNode(pState, CODEC_NID(cmd)))
712 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].digin.u32F08_param;
713 else if (CODEC_NID(cmd) == 1 /* AFG */)
714 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].afg.u32F08_param;
715 else if (codecIsVolKnobNode(pState, CODEC_NID(cmd)))
716 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].volumeKnob.u32F08_param;
717 else
718 AssertMsgFailed(("unsupported operation %x on node: %x\n", CODEC_VERB_CMD8(cmd), CODEC_NID(cmd)));
719 Assert(pu32Reg);
720 if(pu32Reg)
721 codecSetRegisterU8(pu32Reg, cmd, 0);
722 return VINF_SUCCESS;
723}
724
725/* F09 */
726static int codecGetPinSense(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
727{
728 Assert((CODEC_CAD(cmd) == pState->id));
729 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
730 if (CODEC_NID(cmd) >= pState->cTotalNodes)
731 {
732 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
733 return VINF_SUCCESS;
734 }
735 *pResp = 0;
736 if (codecIsPortNode(pState, CODEC_NID(cmd)))
737 *pResp = pState->pNodes[CODEC_NID(cmd)].port.u32F09_param;
738 else if (codecIsDigInPinNode(pState, CODEC_NID(cmd)))
739 *pResp = pState->pNodes[CODEC_NID(cmd)].digin.u32F09_param;
740 else
741 AssertMsgFailed(("unsupported operation %x on node: %x\n", CODEC_VERB_CMD8(cmd), CODEC_NID(cmd)));
742 return VINF_SUCCESS;
743}
744
745/* 709 */
746static int codecSetPinSense(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
747{
748 Assert((CODEC_CAD(cmd) == pState->id));
749 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
750 if (CODEC_NID(cmd) >= pState->cTotalNodes)
751 {
752 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
753 return VINF_SUCCESS;
754 }
755 *pResp = 0;
756 uint32_t *pu32Reg = NULL;
757 if (codecIsPortNode(pState, CODEC_NID(cmd)))
758 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].port.u32F09_param;
759 else if (codecIsDigInPinNode(pState, CODEC_NID(cmd)))
760 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].digin.u32F09_param;
761 Assert(pu32Reg);
762 if(pu32Reg)
763 codecSetRegisterU8(pu32Reg, cmd, 0);
764 return VINF_SUCCESS;
765}
766
767static int codecGetConnectionListEntry(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
768{
769 Assert((CODEC_CAD(cmd) == pState->id));
770 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
771 if (CODEC_NID(cmd) >= pState->cTotalNodes)
772 {
773 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
774 return VINF_SUCCESS;
775 }
776 Assert((cmd & CODEC_VERB_8BIT_DATA) < 16);
777 if ((cmd & CODEC_VERB_8BIT_DATA) >= 16)
778 {
779 Log(("HDAcodec: access to invalid F02 index %d\n", (cmd & CODEC_VERB_8BIT_DATA)));
780 }
781 *pResp = *(uint32_t *)&pState->pNodes[CODEC_NID(cmd)].node.au8F02_param[cmd & CODEC_VERB_8BIT_DATA];
782 return VINF_SUCCESS;
783}
784/* F03 */
785static int codecGetProcessingState(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
786{
787 Assert((CODEC_CAD(cmd) == pState->id));
788 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
789 if (CODEC_NID(cmd) >= pState->cTotalNodes)
790 {
791 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
792 return VINF_SUCCESS;
793 }
794 *pResp = 0;
795 if (codecIsAdcNode(pState, CODEC_NID(cmd)))
796 *pResp = pState->pNodes[CODEC_NID(cmd)].adc.u32F03_param;
797 return VINF_SUCCESS;
798}
799
800/* 703 */
801static int codecSetProcessingState(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
802{
803 Assert((CODEC_CAD(cmd) == pState->id));
804 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
805 if (CODEC_NID(cmd) >= pState->cTotalNodes)
806 {
807 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
808 return VINF_SUCCESS;
809 }
810 *pResp = 0;
811 if (codecIsAdcNode(pState, CODEC_NID(cmd)))
812 {
813 codecSetRegisterU8(&pState->pNodes[CODEC_NID(cmd)].adc.u32F03_param, cmd, 0);
814 }
815 return VINF_SUCCESS;
816}
817
818/* F0D */
819static int codecGetDigitalConverter(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
820{
821 Assert((CODEC_CAD(cmd) == pState->id));
822 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
823 if (CODEC_NID(cmd) >= pState->cTotalNodes)
824 {
825 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
826 return VINF_SUCCESS;
827 }
828 *pResp = 0;
829 if (codecIsSpdifOutNode(pState, CODEC_NID(cmd)))
830 *pResp = pState->pNodes[CODEC_NID(cmd)].spdifout.u32F0d_param;
831 else if (codecIsSpdifInNode(pState, CODEC_NID(cmd)))
832 *pResp = pState->pNodes[CODEC_NID(cmd)].spdifin.u32F0d_param;
833 return VINF_SUCCESS;
834}
835
836static int codecSetDigitalConverter(struct CODECState *pState, uint32_t cmd, uint8_t u8Offset, uint64_t *pResp)
837{
838 Assert((CODEC_CAD(cmd) == pState->id));
839 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
840 if (CODEC_NID(cmd) >= pState->cTotalNodes)
841 {
842 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
843 return VINF_SUCCESS;
844 }
845 *pResp = 0;
846 if (codecIsSpdifOutNode(pState, CODEC_NID(cmd)))
847 codecSetRegisterU8(&pState->pNodes[CODEC_NID(cmd)].spdifout.u32F0d_param, cmd, u8Offset);
848 else if (codecIsSpdifInNode(pState, CODEC_NID(cmd)))
849 codecSetRegisterU8(&pState->pNodes[CODEC_NID(cmd)].spdifin.u32F0d_param, cmd, u8Offset);
850 return VINF_SUCCESS;
851}
852
853/* 70D */
854static int codecSetDigitalConverter1(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
855{
856 return codecSetDigitalConverter(pState, cmd, 0, pResp);
857}
858
859/* 70E */
860static int codecSetDigitalConverter2(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
861{
862 return codecSetDigitalConverter(pState, cmd, 8, pResp);
863}
864
865static int codecGetSubId(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
866{
867 Assert((CODEC_CAD(cmd) == pState->id));
868 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
869 if (CODEC_NID(cmd) >= pState->cTotalNodes)
870 {
871 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
872 return VINF_SUCCESS;
873 }
874 *pResp = 0;
875 if (CODEC_NID(cmd) == 1 /* AFG */)
876 {
877 *pResp = pState->pNodes[CODEC_NID(cmd)].afg.u32F20_param;
878 }
879 return VINF_SUCCESS;
880}
881
882static int codecReset(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
883{
884 Assert((CODEC_CAD(cmd) == pState->id));
885 Assert(CODEC_NID(cmd) == 1 /* AFG */);
886 if(CODEC_NID(cmd) == 1 /* AFG */)
887 {
888 uint8_t i;
889 Log(("HDAcodec: enters reset\n"));
890 Assert(pState->pfnCodecNodeReset);
891 for (i = 0; i < pState->cTotalNodes; ++i)
892 {
893 pState->pfnCodecNodeReset(pState, i, &pState->pNodes[i]);
894 }
895 pState->fInReset = false;
896 Log(("HDAcodec: exits reset\n"));
897 }
898 *pResp = 0;
899 return VINF_SUCCESS;
900}
901
902/* F05 */
903static int codecGetPowerState(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
904{
905 Assert((CODEC_CAD(cmd) == pState->id));
906 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
907 if (CODEC_NID(cmd) >= pState->cTotalNodes)
908 {
909 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
910 return VINF_SUCCESS;
911 }
912 *pResp = 0;
913 if (CODEC_NID(cmd) == 1 /* AFG */)
914 *pResp = pState->pNodes[CODEC_NID(cmd)].afg.u32F05_param;
915 else if (codecIsDacNode(pState, CODEC_NID(cmd)))
916 *pResp = pState->pNodes[CODEC_NID(cmd)].dac.u32F05_param;
917 else if (codecIsDigInPinNode(pState, CODEC_NID(cmd)))
918 *pResp = pState->pNodes[CODEC_NID(cmd)].digin.u32F05_param;
919 else if (codecIsAdcNode(pState, CODEC_NID(cmd)))
920 *pResp = pState->pNodes[CODEC_NID(cmd)].adc.u32F05_param;
921 return VINF_SUCCESS;
922}
923
924/* 705 */
925static int codecSetPowerState(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
926{
927 Assert((CODEC_CAD(cmd) == pState->id));
928 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
929 if (CODEC_NID(cmd) >= pState->cTotalNodes)
930 {
931 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
932 return VINF_SUCCESS;
933 }
934 uint32_t *pu32Reg = NULL;
935 *pResp = 0;
936 if (CODEC_NID(cmd) == 1 /* AFG */)
937 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].afg.u32F05_param;
938 else if (codecIsDacNode(pState, CODEC_NID(cmd)))
939 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].dac.u32F05_param;
940 else if (codecIsDigInPinNode(pState, CODEC_NID(cmd)))
941 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].digin.u32F05_param;
942 else if (codecIsAdcNode(pState, CODEC_NID(cmd)))
943 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].adc.u32F05_param;
944 Assert((pu32Reg));
945 if (!pu32Reg)
946 return VINF_SUCCESS;
947
948 if (!CODEC_NID(cmd) == 1 /* AFG */)
949 {
950 *pu32Reg &= ~CODEC_VERB_8BIT_DATA;
951 *pu32Reg |= (pState->pNodes[1].afg.u32F05_param & (CODEC_VERB_4BIT_DATA << 4));
952 }
953 else
954 *pu32Reg &= ~CODEC_VERB_4BIT_DATA;
955
956 *pu32Reg |= cmd & CODEC_VERB_4BIT_DATA;
957 /* Propogate next power state only if AFG is on or verb modifies AFG power state */
958 if ( CODEC_NID(cmd) == 1 /* AFG */
959 || !pState->pNodes[1].afg.u32F05_param)
960 {
961 *pu32Reg &= ~(CODEC_POWER_MASK << CODEC_POWER_ACT_SHIFT);
962 *pu32Reg |= (cmd & CODEC_VERB_4BIT_DATA) << 4;
963 if ( CODEC_NID(cmd) == 1 /* AFG */
964 && (cmd & CODEC_POWER_MASK) == CODEC_POWER_D0)
965 {
966 CODEC_POWER_PROPOGATE_STATE(pState->pNodes[2].dac);
967 CODEC_POWER_PROPOGATE_STATE(pState->pNodes[3].dac);
968 CODEC_POWER_PROPOGATE_STATE(pState->pNodes[4].dac);
969 CODEC_POWER_PROPOGATE_STATE(pState->pNodes[5].dac);
970 CODEC_POWER_PROPOGATE_STATE(pState->pNodes[6].dac);
971 CODEC_POWER_PROPOGATE_STATE(pState->pNodes[7].dac);
972 CODEC_POWER_PROPOGATE_STATE(pState->pNodes[0x11].dac);
973 }
974 }
975 return VINF_SUCCESS;
976}
977
978static int codecGetStreamId(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
979{
980 Assert((CODEC_CAD(cmd) == pState->id));
981 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
982 if (CODEC_NID(cmd) >= pState->cTotalNodes)
983 {
984 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
985 return VINF_SUCCESS;
986 }
987 *pResp = 0;
988 if (codecIsDacNode(pState, CODEC_NID(cmd)))
989 *pResp = pState->pNodes[CODEC_NID(cmd)].dac.u32F06_param;
990 else if (codecIsAdcNode(pState, CODEC_NID(cmd)))
991 *pResp = pState->pNodes[CODEC_NID(cmd)].adc.u32F06_param;
992 else if (codecIsSpdifInNode(pState, CODEC_NID(cmd)))
993 *pResp = pState->pNodes[CODEC_NID(cmd)].spdifin.u32F06_param;
994 else if (codecIsSpdifOutNode(pState, CODEC_NID(cmd)))
995 *pResp = pState->pNodes[CODEC_NID(cmd)].spdifout.u32F06_param;
996 else if (CODEC_NID(cmd) == 0x1A)
997 *pResp = pState->pNodes[CODEC_NID(cmd)].reserved.u32F06_param;
998 return VINF_SUCCESS;
999}
1000static int codecSetStreamId(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1001{
1002 Assert((CODEC_CAD(cmd) == pState->id));
1003 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1004 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1005 {
1006 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1007 return VINF_SUCCESS;
1008 }
1009 *pResp = 0;
1010 uint32_t *pu32addr = NULL;
1011 *pResp = 0;
1012 if (codecIsDacNode(pState, CODEC_NID(cmd)))
1013 pu32addr = &pState->pNodes[CODEC_NID(cmd)].dac.u32F06_param;
1014 else if (codecIsAdcNode(pState, CODEC_NID(cmd)))
1015 pu32addr = &pState->pNodes[CODEC_NID(cmd)].adc.u32F06_param;
1016 else if (codecIsSpdifOutNode(pState, CODEC_NID(cmd)))
1017 pu32addr = &pState->pNodes[CODEC_NID(cmd)].spdifout.u32F06_param;
1018 else if (codecIsSpdifInNode(pState, CODEC_NID(cmd)))
1019 pu32addr = &pState->pNodes[CODEC_NID(cmd)].spdifin.u32F06_param;
1020 else if (codecIsReservedNode(pState, CODEC_NID(cmd)))
1021 pu32addr = &pState->pNodes[CODEC_NID(cmd)].reserved.u32F06_param;
1022 Assert((pu32addr));
1023 if (pu32addr)
1024 codecSetRegisterU8(pu32addr, cmd, 0);
1025 return VINF_SUCCESS;
1026}
1027static int codecGetConverterFormat(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1028{
1029 Assert((CODEC_CAD(cmd) == pState->id));
1030 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1031 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1032 {
1033 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1034 return VINF_SUCCESS;
1035 }
1036 *pResp = 0;
1037 if (codecIsDacNode(pState, CODEC_NID(cmd)))
1038 *pResp = pState->pNodes[CODEC_NID(cmd)].dac.u32A_param;
1039 else if (codecIsAdcNode(pState, CODEC_NID(cmd)))
1040 *pResp = pState->pNodes[CODEC_NID(cmd)].adc.u32A_param;
1041 else if (codecIsSpdifOutNode(pState, CODEC_NID(cmd)))
1042 *pResp = pState->pNodes[CODEC_NID(cmd)].spdifout.u32A_param;
1043 else if (codecIsSpdifInNode(pState, CODEC_NID(cmd)))
1044 *pResp = pState->pNodes[CODEC_NID(cmd)].spdifin.u32A_param;
1045 return VINF_SUCCESS;
1046}
1047
1048static int codecSetConverterFormat(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1049{
1050 Assert((CODEC_CAD(cmd) == pState->id));
1051 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1052 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1053 {
1054 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1055 return VINF_SUCCESS;
1056 }
1057 *pResp = 0;
1058 if (codecIsDacNode(pState, CODEC_NID(cmd)))
1059 codecSetRegisterU16(&pState->pNodes[CODEC_NID(cmd)].dac.u32A_param, cmd, 0);
1060 else if (codecIsAdcNode(pState, CODEC_NID(cmd)))
1061 codecSetRegisterU16(&pState->pNodes[CODEC_NID(cmd)].adc.u32A_param, cmd, 0);
1062 else if (codecIsSpdifOutNode(pState, CODEC_NID(cmd)))
1063 codecSetRegisterU16(&pState->pNodes[CODEC_NID(cmd)].spdifout.u32A_param, cmd, 0);
1064 else if (codecIsSpdifInNode(pState, CODEC_NID(cmd)))
1065 codecSetRegisterU16(&pState->pNodes[CODEC_NID(cmd)].spdifin.u32A_param, cmd, 0);
1066 return VINF_SUCCESS;
1067}
1068
1069/* F0C */
1070static int codecGetEAPD_BTLEnabled(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1071{
1072 Assert((CODEC_CAD(cmd) == pState->id));
1073 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1074 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1075 {
1076 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1077 return VINF_SUCCESS;
1078 }
1079 *pResp = 0;
1080 if (codecIsAdcVolNode(pState, CODEC_NID(cmd)))
1081 *pResp = pState->pNodes[CODEC_NID(cmd)].adcvol.u32F0c_param;
1082 else if (codecIsDacNode(pState, CODEC_NID(cmd)))
1083 *pResp = pState->pNodes[CODEC_NID(cmd)].dac.u32F0c_param;
1084 else if (codecIsDigInPinNode(pState, CODEC_NID(cmd)))
1085 *pResp = pState->pNodes[CODEC_NID(cmd)].digin.u32F0c_param;
1086 return VINF_SUCCESS;
1087}
1088
1089/* 70C */
1090static int codecSetEAPD_BTLEnabled(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1091{
1092 Assert((CODEC_CAD(cmd) == pState->id));
1093 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1094 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1095 {
1096 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1097 return VINF_SUCCESS;
1098 }
1099 *pResp = 0;
1100 uint32_t *pu32Reg = NULL;
1101 if (codecIsAdcVolNode(pState, CODEC_NID(cmd)))
1102 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].adcvol.u32F0c_param;
1103 else if (codecIsDacNode(pState, CODEC_NID(cmd)))
1104 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].dac.u32F0c_param;
1105 else if (codecIsDigInPinNode(pState, CODEC_NID(cmd)))
1106 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].digin.u32F0c_param;
1107 *pResp = 0;
1108 Assert((pu32Reg));
1109 if (pu32Reg)
1110 codecSetRegisterU8(pu32Reg, cmd, 0);
1111 return VINF_SUCCESS;
1112}
1113
1114/* F0F */
1115static int codecGetVolumeKnobCtrl(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1116{
1117 Assert((CODEC_CAD(cmd) == pState->id));
1118 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1119 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1120 {
1121 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1122 return VINF_SUCCESS;
1123 }
1124 *pResp = 0;
1125 if (codecIsVolKnobNode(pState, CODEC_NID(cmd)))
1126 *pResp = pState->pNodes[CODEC_NID(cmd)].volumeKnob.u32F0f_param;
1127 return VINF_SUCCESS;
1128}
1129
1130/* 70F */
1131static int codecSetVolumeKnobCtrl(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1132{
1133 Assert((CODEC_CAD(cmd) == pState->id));
1134 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1135 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1136 {
1137 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1138 return VINF_SUCCESS;
1139 }
1140 uint32_t *pu32Reg = NULL;
1141 *pResp = 0;
1142 if (codecIsVolKnobNode(pState, CODEC_NID(cmd)))
1143 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].volumeKnob.u32F0f_param;
1144 Assert((pu32Reg));
1145 if (pu32Reg)
1146 codecSetRegisterU8(pu32Reg, cmd, 0);
1147 return VINF_SUCCESS;
1148}
1149
1150/* F1C */
1151static int codecGetConfig (struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1152{
1153 Assert((CODEC_CAD(cmd) == pState->id));
1154 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1155 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1156 {
1157 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1158 return VINF_SUCCESS;
1159 }
1160 *pResp = 0;
1161 if (codecIsPortNode(pState, CODEC_NID(cmd)))
1162 *pResp = pState->pNodes[CODEC_NID(cmd)].port.u32F1c_param;
1163 else if (codecIsDigOutPinNode(pState, CODEC_NID(cmd)))
1164 *pResp = pState->pNodes[CODEC_NID(cmd)].digout.u32F1c_param;
1165 else if (codecIsDigInPinNode(pState, CODEC_NID(cmd)))
1166 *pResp = pState->pNodes[CODEC_NID(cmd)].digin.u32F1c_param;
1167 else if (codecIsCdNode(pState, CODEC_NID(cmd)))
1168 *pResp = pState->pNodes[CODEC_NID(cmd)].cdnode.u32F1c_param;
1169 return VINF_SUCCESS;
1170}
1171static int codecSetConfigX(struct CODECState *pState, uint32_t cmd, uint8_t u8Offset)
1172{
1173 Assert((CODEC_CAD(cmd) == pState->id));
1174 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1175 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1176 {
1177 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1178 return VINF_SUCCESS;
1179 }
1180 uint32_t *pu32Reg = NULL;
1181 if (codecIsPortNode(pState, CODEC_NID(cmd)))
1182 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].port.u32F1c_param;
1183 else if (codecIsDigInPinNode(pState, CODEC_NID(cmd)))
1184 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].digin.u32F1c_param;
1185 else if (codecIsDigOutPinNode(pState, CODEC_NID(cmd)))
1186 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].digout.u32F1c_param;
1187 else if (codecIsCdNode(pState, CODEC_NID(cmd)))
1188 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].cdnode.u32F1c_param;
1189 else if (CODEC_NID(cmd) == 0x1B)
1190 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].reserved.u32F1c_param;
1191 Assert((pu32Reg));
1192 if (pu32Reg)
1193 codecSetRegisterU8(pu32Reg, cmd, u8Offset);
1194 return VINF_SUCCESS;
1195}
1196/* 71C */
1197static int codecSetConfig0 (struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1198{
1199 *pResp = 0;
1200 return codecSetConfigX(pState, cmd, 0);
1201}
1202/* 71D */
1203static int codecSetConfig1 (struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1204{
1205 *pResp = 0;
1206 return codecSetConfigX(pState, cmd, 8);
1207}
1208/* 71E */
1209static int codecSetConfig2 (struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1210{
1211 *pResp = 0;
1212 return codecSetConfigX(pState, cmd, 16);
1213}
1214/* 71E */
1215static int codecSetConfig3 (struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1216{
1217 *pResp = 0;
1218 return codecSetConfigX(pState, cmd, 24);
1219}
1220
1221
1222static int codecToAudVolume(AMPLIFIER *pAmp, audmixerctl_t mt)
1223{
1224 uint32_t dir = AMPLIFIER_OUT;
1225 switch (mt)
1226 {
1227 case AUD_MIXER_VOLUME:
1228 case AUD_MIXER_PCM:
1229 dir = AMPLIFIER_OUT;
1230 break;
1231 case AUD_MIXER_LINE_IN:
1232 dir = AMPLIFIER_IN;
1233 break;
1234 }
1235 int mute = AMPLIFIER_REGISTER(*pAmp, dir, AMPLIFIER_LEFT, 0) & RT_BIT(7);
1236 mute |= AMPLIFIER_REGISTER(*pAmp, dir, AMPLIFIER_RIGHT, 0) & RT_BIT(7);
1237 mute >>=7;
1238 mute &= 0x1;
1239 uint8_t lVol = AMPLIFIER_REGISTER(*pAmp, dir, AMPLIFIER_LEFT, 0) & 0x7f;
1240 uint8_t rVol = AMPLIFIER_REGISTER(*pAmp, dir, AMPLIFIER_RIGHT, 0) & 0x7f;
1241 AUD_set_volume(mt, &mute, &lVol, &rVol);
1242 return VINF_SUCCESS;
1243}
1244
1245static CODECVERB CODECVERBS[] =
1246{
1247/* verb | verb mask | callback */
1248/* ----------- -------------------- ----------------------- */
1249 {0x000F0000, CODEC_VERB_8BIT_CMD , codecGetParameter },
1250 {0x000F0100, CODEC_VERB_8BIT_CMD , codecGetConSelectCtrl },
1251 {0x00070100, CODEC_VERB_8BIT_CMD , codecSetConSelectCtrl },
1252 {0x000F0600, CODEC_VERB_8BIT_CMD , codecGetStreamId },
1253 {0x00070600, CODEC_VERB_8BIT_CMD , codecSetStreamId },
1254 {0x000F0700, CODEC_VERB_8BIT_CMD , codecGetPinCtrl },
1255 {0x00070700, CODEC_VERB_8BIT_CMD , codecSetPinCtrl },
1256 {0x000F0800, CODEC_VERB_8BIT_CMD , codecGetUnsolicitedEnabled },
1257 {0x00070800, CODEC_VERB_8BIT_CMD , codecSetUnsolicitedEnabled },
1258 {0x000F0900, CODEC_VERB_8BIT_CMD , codecGetPinSense },
1259 {0x00070900, CODEC_VERB_8BIT_CMD , codecSetPinSense },
1260 {0x000F0200, CODEC_VERB_8BIT_CMD , codecGetConnectionListEntry },
1261 {0x000F0300, CODEC_VERB_8BIT_CMD , codecGetProcessingState },
1262 {0x00070300, CODEC_VERB_8BIT_CMD , codecSetProcessingState },
1263 {0x000F0D00, CODEC_VERB_8BIT_CMD , codecGetDigitalConverter },
1264 {0x00070D00, CODEC_VERB_8BIT_CMD , codecSetDigitalConverter1 },
1265 {0x00070E00, CODEC_VERB_8BIT_CMD , codecSetDigitalConverter2 },
1266 {0x000F2000, CODEC_VERB_8BIT_CMD , codecGetSubId },
1267 {0x0007FF00, CODEC_VERB_8BIT_CMD , codecReset },
1268 {0x000F0500, CODEC_VERB_8BIT_CMD , codecGetPowerState },
1269 {0x00070500, CODEC_VERB_8BIT_CMD , codecSetPowerState },
1270 {0x000F0C00, CODEC_VERB_8BIT_CMD , codecGetEAPD_BTLEnabled },
1271 {0x00070C00, CODEC_VERB_8BIT_CMD , codecSetEAPD_BTLEnabled },
1272 {0x000F0F00, CODEC_VERB_8BIT_CMD , codecGetVolumeKnobCtrl },
1273 {0x00070F00, CODEC_VERB_8BIT_CMD , codecSetVolumeKnobCtrl },
1274 {0x000F1C00, CODEC_VERB_8BIT_CMD , codecGetConfig },
1275 {0x00071C00, CODEC_VERB_8BIT_CMD , codecSetConfig0 },
1276 {0x00071D00, CODEC_VERB_8BIT_CMD , codecSetConfig1 },
1277 {0x00071E00, CODEC_VERB_8BIT_CMD , codecSetConfig2 },
1278 {0x00071F00, CODEC_VERB_8BIT_CMD , codecSetConfig3 },
1279 {0x000A0000, CODEC_VERB_16BIT_CMD, codecGetConverterFormat },
1280 {0x00020000, CODEC_VERB_16BIT_CMD, codecSetConverterFormat },
1281 {0x000B0000, CODEC_VERB_16BIT_CMD, codecGetAmplifier },
1282 {0x00030000, CODEC_VERB_16BIT_CMD, codecSetAmplifier },
1283};
1284
1285static int codecLookup(CODECState *pState, uint32_t cmd, PPFNCODECVERBPROCESSOR pfn)
1286{
1287 int rc = VINF_SUCCESS;
1288 Assert(CODEC_CAD(cmd) == pState->id);
1289 if (codecIsReservedNode(pState, CODEC_NID(cmd)))
1290 {
1291 LogRel(("HDAcodec: cmd %x was addressed to reseved node\n", cmd));
1292 }
1293 if ( CODEC_VERBDATA(cmd) == 0
1294 || CODEC_NID(cmd) >= pState->cTotalNodes)
1295 {
1296 *pfn = codecUnimplemented;
1297 //** @todo r=michaln: There needs to be a counter to avoid log flooding (see e.g. DevRTC.cpp)
1298 LogRel(("HDAcodec: cmd %x was ignored\n", cmd));
1299 return VINF_SUCCESS;
1300 }
1301 for (int i = 0; i < pState->cVerbs; ++i)
1302 {
1303 if ((CODEC_VERBDATA(cmd) & pState->pVerbs[i].mask) == pState->pVerbs[i].verb)
1304 {
1305 *pfn = pState->pVerbs[i].pfn;
1306 return VINF_SUCCESS;
1307 }
1308 }
1309 *pfn = codecUnimplemented;
1310 LogRel(("HDAcodec: callback for %x wasn't found\n", CODEC_VERBDATA(cmd)));
1311 return rc;
1312}
1313
1314static int codec_dac_to_aud(CODECState *pState, audsettings_t *paud)
1315{
1316 paud->freq = 44100;
1317 paud->nchannels = 2;
1318 paud->fmt = AUD_FMT_S16;
1319
1320 paud->endianness = 0;
1321 return VINF_SUCCESS;
1322}
1323
1324static void pi_callback (void *opaque, int avail)
1325{
1326 CODECState *pState = (CODECState *)opaque;
1327 pState->pfnTransfer(pState, PI_INDEX, avail);
1328}
1329
1330static void po_callback (void *opaque, int avail)
1331{
1332 CODECState *pState = (CODECState *)opaque;
1333 pState->pfnTransfer(pState, PO_INDEX, avail);
1334}
1335
1336static void mc_callback (void *opaque, int avail)
1337{
1338 CODECState *pState = (CODECState *)opaque;
1339 pState->pfnTransfer(pState, MC_INDEX, avail);
1340}
1341
1342int codecConstruct(CODECState *pState, ENMCODEC enmCodec)
1343{
1344 audsettings_t as;
1345 int rc;
1346 pState->pVerbs = (CODECVERB *)&CODECVERBS;
1347 pState->cVerbs = sizeof(CODECVERBS)/sizeof(CODECVERB);
1348 pState->pfnLookup = codecLookup;
1349 pState->enmCodec = enmCodec;
1350 if (enmCodec == STAC9220_CODEC)
1351 {
1352 rc = stac9220Construct(pState);
1353 AssertRC(rc);
1354 }
1355 uint8_t i;
1356 Assert(pState->pNodes);
1357 Assert(pState->pfnCodecNodeReset);
1358 for (i = 0; i < pState->cTotalNodes; ++i)
1359 {
1360 pState->pfnCodecNodeReset(pState, i, &pState->pNodes[i]);
1361 }
1362 //** @todo r=michaln: Was this meant to be 'HDA' or something like that? (AC'97 was on ICH0)
1363 AUD_register_card ("ICH0", &pState->card);
1364
1365 codec_dac_to_aud(pState, &as);
1366 pState->voice_pi = AUD_open_in(&pState->card, pState->voice_pi, "hda.in", pState, pi_callback, &as);
1367 codec_dac_to_aud(pState, &as);
1368 pState->voice_po = AUD_open_out(&pState->card, pState->voice_po, "hda.out", pState, po_callback, &as);
1369 if (!pState->voice_pi)
1370 LogRel (("HDAcodec: WARNING: Unable to open PCM IN!\n"));
1371 if (!pState->voice_po)
1372 LogRel (("HDAcodec: WARNING: Unable to open PCM OUT!\n"));
1373 codecToAudVolume(&pState->pNodes[pState->u8DacLineOut].dac.B_params, AUD_MIXER_VOLUME);
1374 codecToAudVolume(&pState->pNodes[pState->u8AdcVolsLineIn].adcvol.B_params, AUD_MIXER_LINE_IN);
1375
1376 return VINF_SUCCESS;
1377}
1378int codecDestruct(CODECState *pCodecState)
1379{
1380 RTMemFree(pCodecState->pNodes);
1381 return VINF_SUCCESS;
1382}
1383
1384int codecSaveState(CODECState *pCodecState, PSSMHANDLE pSSMHandle)
1385{
1386 SSMR3PutMem (pSSMHandle, pCodecState->pNodes, sizeof(CODECNODE) * pCodecState->cTotalNodes);
1387 return VINF_SUCCESS;
1388}
1389
1390int codecLoadState(CODECState *pCodecState, PSSMHANDLE pSSMHandle)
1391{
1392 SSMR3GetMem (pSSMHandle, pCodecState->pNodes, sizeof(CODECNODE) * pCodecState->cTotalNodes);
1393 codecToAudVolume(&pCodecState->pNodes[pCodecState->u8DacLineOut].dac.B_params, AUD_MIXER_VOLUME);
1394 codecToAudVolume(&pCodecState->pNodes[pCodecState->u8AdcVolsLineIn].adcvol.B_params, AUD_MIXER_LINE_IN);
1395 return VINF_SUCCESS;
1396}
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