VirtualBox

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

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

Audio/HDA: logs.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 109.6 KB
Line 
1/* $Id: DevCodec.cpp 34590 2010-12-02 03:22:29Z 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/* HDA spec 7.3.3.1 defines layout of configuration registers/verbs (0xF00) */
77/* VendorID (7.3.4.1) */
78#define CODEC_MAKE_F00_00(vendorID, deviceID) (((vendorID) << 16) | (deviceID))
79/* RevisionID (7.3.4.2)*/
80#define CODEC_MAKE_F00_02(MajRev, MinRev, RevisionID, SteppingID) (((MajRev) << 20)|((MinRev) << 16)|((RevisionID) << 8)|(SteppingID))
81/* Subordinate node count (7.3.4.3)*/
82#define CODEC_MAKE_F00_04(startNodeNumber, totalNodeNumber) ((((startNodeNumber) & 0xFF) << 16)|((totalNodeNumber) & 0xFF))
83/*
84 * Function Group Type (7.3.4.4)
85 * 0 & [0x3-0x7f] are reserved types
86 * [0x80 - 0xff] are vendor defined function groups
87 */
88#define CODEC_MAKE_F00_05(UnSol, NodeType) ((UnSol)|(NodeType))
89#define CODEC_F00_05_UNSOL RT_BIT(8)
90#define CODEC_F00_05_AFG (0x1)
91#define CODEC_F00_05_MFG (0x2)
92/* Audio Function Group capabilities (7.3.4.5) */
93#define CODEC_MAKE_F00_08(BeepGen, InputDelay, OutputDelay) ((BeepGen)| (((InputDelay) & 0xF) << 8) | ((OutputDelay) & 0xF))
94#define CODEC_F00_08_BEEP_GEN RT_BIT(16)
95
96/* Widget Capabilities (7.3.4.6) */
97#define CODEC_MAKE_F00_09(type, delay, chanel_count) \
98 ( (((type) & 0xF) << 20) \
99 | (((delay) & 0xF) << 16) \
100 | (((chanel_count) & 0xF) << 13))
101/* note: types 0x8-0xe are reserved */
102#define CODEC_F00_09_TYPE_AUDIO_OUTPUT (0x0)
103#define CODEC_F00_09_TYPE_AUDIO_INPUT (0x1)
104#define CODEC_F00_09_TYPE_AUDIO_MIXER (0x2)
105#define CODEC_F00_09_TYPE_AUDIO_SELECTOR (0x3)
106#define CODEC_F00_09_TYPE_PIN_COMPLEX (0x4)
107#define CODEC_F00_09_TYPE_POWER_WIDGET (0x5)
108#define CODEC_F00_09_TYPE_VOLUME_KNOB (0x6)
109#define CODEC_F00_09_TYPE_BEEP_GEN (0x7)
110#define CODEC_F00_09_TYPE_VENDOR_DEFINED (0xF)
111
112#define CODEC_F00_09_CAP_CP RT_BIT(12)
113#define CODEC_F00_09_CAP_L_R_SWAP RT_BIT(11)
114#define CODEC_F00_09_CAP_POWER_CTRL RT_BIT(10)
115#define CODEC_F00_09_CAP_DIGITAL RT_BIT(9)
116#define CODEC_F00_09_CAP_CONNECTION_LIST RT_BIT(8)
117#define CODEC_F00_09_CAP_UNSOL RT_BIT(7)
118#define CODEC_F00_09_CAP_PROC_WIDGET RT_BIT(6)
119#define CODEC_F00_09_CAP_STRIPE RT_BIT(5)
120#define CODEC_F00_09_CAP_FMT_OVERRIDE RT_BIT(4)
121#define CODEC_F00_09_CAP_AMP_FMT_OVERRIDE RT_BIT(3)
122#define CODEC_F00_09_CAP_OUT_AMP_PRESENT RT_BIT(2)
123#define CODEC_F00_09_CAP_IN_AMP_PRESENT RT_BIT(1)
124#define CODEC_F00_09_CAP_LSB RT_BIT(0)
125
126/* Supported PCM size, rates (7.3.4.7) */
127#define CODEC_F00_0A_32_BIT RT_BIT(19)
128#define CODEC_F00_0A_24_BIT RT_BIT(18)
129#define CODEC_F00_0A_16_BIT RT_BIT(17)
130#define CODEC_F00_0A_8_BIT RT_BIT(16)
131
132#define CODEC_F00_0A_48KHZ_MULT_8X RT_BIT(11)
133#define CODEC_F00_0A_48KHZ_MULT_4X RT_BIT(10)
134#define CODEC_F00_0A_44_1KHZ_MULT_4X RT_BIT(9)
135#define CODEC_F00_0A_48KHZ_MULT_2X RT_BIT(8)
136#define CODEC_F00_0A_44_1KHZ_MULT_2X RT_BIT(7)
137#define CODEC_F00_0A_48KHZ RT_BIT(6)
138#define CODEC_F00_0A_44_1KHZ RT_BIT(5)
139/* 2/3 * 48kHz */
140#define CODEC_F00_0A_48KHZ_2_3X RT_BIT(4)
141/* 1/2 * 44.1kHz */
142#define CODEC_F00_0A_44_1KHZ_1_2X RT_BIT(3)
143/* 1/3 * 48kHz */
144#define CODEC_F00_0A_48KHZ_1_3X RT_BIT(2)
145/* 1/4 * 44.1kHz */
146#define CODEC_F00_0A_44_1KHZ_1_4X RT_BIT(1)
147/* 1/6 * 48kHz */
148#define CODEC_F00_0A_48KHZ_1_6X RT_BIT(0)
149
150/* Supported streams formats (7.3.4.8) */
151#define CODEC_F00_0B_AC3 RT_BIT(2)
152#define CODEC_F00_0B_FLOAT32 RT_BIT(1)
153#define CODEC_F00_0B_PCM RT_BIT(0)
154
155/* Pin Capabilities (7.3.4.9)*/
156#define CODEC_MAKE_F00_0C(vref_ctrl) (((vref_ctrl) & 0xFF) << 8)
157#define CODEC_F00_0C_CAP_HBR RT_BIT(27)
158#define CODEC_F00_0C_CAP_DP RT_BIT(24)
159#define CODEC_F00_0C_CAP_EAPD RT_BIT(16)
160#define CODEC_F00_0C_CAP_HDMI RT_BIT(7)
161#define CODEC_F00_0C_CAP_BALANCED_IO RT_BIT(6)
162#define CODEC_F00_0C_CAP_INPUT RT_BIT(5)
163#define CODEC_F00_0C_CAP_OUTPUT RT_BIT(4)
164#define CODEC_F00_0C_CAP_HP RT_BIT(3)
165#define CODEC_F00_0C_CAP_PRESENSE_DETECT RT_BIT(2)
166#define CODEC_F00_0C_CAP_TRIGGER_REQUIRED RT_BIT(1)
167#define CODEC_F00_0C_CAP_IMPENDANCE_SENSE RT_BIT(0)
168
169/* Amplifier capabilities (7.3.4.10) */
170#define CODEC_MAKE_F00_0D(mute_cap, step_size, num_steps, offset) \
171 ( (((mute_cap) & 0x1) << 31) \
172 | (((step_size) & 0xFF) << 16) \
173 | (((num_steps) & 0xFF) << 8) \
174 | ((offset) & 0xFF))
175
176/* Connection list lenght (7.3.4.11) */
177#define CODEC_MAKE_F00_0E(long_form, length) \
178 ( (((long_form) & 0x1) << 7) \
179 | ((length) & 0x7F))
180/* Supported Power States (7.3.4.12) */
181#define CODEC_F00_0F_EPSS RT_BIT(31)
182#define CODEC_F00_0F_CLKSTOP RT_BIT(30)
183#define CODEC_F00_0F_S3D3 RT_BIT(29)
184#define CODEC_F00_0F_D3COLD RT_BIT(4)
185#define CODEC_F00_0F_D3 RT_BIT(3)
186#define CODEC_F00_0F_D2 RT_BIT(2)
187#define CODEC_F00_0F_D1 RT_BIT(1)
188#define CODEC_F00_0F_D0 RT_BIT(0)
189
190/* CP/IO Count (7.3.4.14) */
191#define CODEC_MAKE_F00_11(wake, unsol, numgpi, numgpo, numgpio) \
192 ( (((wake) & 0x1) << 31) \
193 | (((unsol) & 0x1) << 30) \
194 | (((numgpi) & 0xFF) << 16) \
195 | (((numgpo) & 0xFF) << 8) \
196 | ((numgpio) & 0xFF))
197
198/* Power States (7.3.3.10) */
199#define CODEC_MAKE_F05(reset, stopok, error, act, set) \
200 ( (((reset) & 0x1) << 10) \
201 | (((stopok) & 0x1) << 9) \
202 | (((error) & 0x1) << 8) \
203 | (((act) & 0x7) << 4) \
204 | ((set) & 0x7))
205#define CODEC_F05_D3COLD (4)
206#define CODEC_F05_D3 (3)
207#define CODEC_F05_D2 (2)
208#define CODEC_F05_D1 (1)
209#define CODEC_F05_D0 (0)
210
211#define CODEC_F05_IS_RESET(value) (((value) & RT_BIT(10)) != 0)
212#define CODEC_F05_IS_STOPOK(value) (((value) & RT_BIT(9)) != 0)
213#define CODEC_F05_IS_ERROR(value) (((value) & RT_BIT(8)) != 0)
214#define CODEC_F05_ACT(value) (((value) & 0x7) >> 4)
215#define CODEC_F05_SET(value) (((value) & 0x7))
216
217/* Converter formats (7.3.3.8) and (3.7.1) */
218#define CODEC_MAKE_A(fNonPCM, f44_1BaseRate, mult, div, bits, chan) \
219 ( (((fNonPCM) & 0x1) << 15) \
220 | (((f44_1BaseRate) & 0x1) << 14) \
221 | (((mult) & 0x7) << 11) \
222 | (((div) & 0x7) << 8) \
223 | (((bits) & 0x7) << 4) \
224 | ((chan) & 0xF))
225
226#define CODEC_A_MULT_1X (0)
227#define CODEC_A_MULT_2X (1)
228#define CODEC_A_MULT_3X (2)
229#define CODEC_A_MULT_4X (3)
230
231#define CODEC_A_DIV_1X (0)
232#define CODEC_A_DIV_2X (1)
233#define CODEC_A_DIV_3X (2)
234#define CODEC_A_DIV_4X (3)
235#define CODEC_A_DIV_5X (4)
236#define CODEC_A_DIV_6X (5)
237#define CODEC_A_DIV_7X (6)
238#define CODEC_A_DIV_8X (7)
239
240#define CODEC_A_8_BIT (0)
241#define CODEC_A_16_BIT (1)
242#define CODEC_A_20_BIT (2)
243#define CODEC_A_24_BIT (3)
244#define CODEC_A_32_BIT (4)
245
246/* Pin Sense (7.3.3.15) */
247#define CODEC_MAKE_F09_ANALOG(fPresent, impedance) \
248( (((fPresent) & 0x1) << 31) \
249 | (((impedance) & 0x7FFFFFFF)))
250#define CODEC_F09_ANALOG_NA 0x7FFFFFFF
251#define CODEC_MAKE_F09_DIGITAL(fPresent, fELDValid) \
252( (((fPresent) & 0x1) << 31) \
253 | (((fELDValid) & 0x1) << 30))
254
255/* HDA spec 7.3.3.31 defines layout of configuration registers/verbs (0xF1C) */
256/* Configuration's port connection */
257#define CODEC_F1C_PORT_MASK (0x3)
258#define CODEC_F1C_PORT_SHIFT (30)
259
260#define CODEC_F1C_PORT_COMPLEX (0x0)
261#define CODEC_F1C_PORT_NO_PHYS (0x1)
262#define CODEC_F1C_PORT_FIXED (0x2)
263#define CODEC_F1C_BOTH (0x3)
264
265/* Configuration's location */
266#define CODEC_F1C_LOCATION_MASK (0x3F)
267#define CODEC_F1C_LOCATION_SHIFT (24)
268/* [4:5] bits of location region means chassis attachment */
269#define CODEC_F1C_LOCATION_PRIMARY_CHASSIS (0)
270#define CODEC_F1C_LOCATION_INTERNAL RT_BIT(4)
271#define CODEC_F1C_LOCATION_SECONDRARY_CHASSIS RT_BIT(5)
272#define CODEC_F1C_LOCATION_OTHER (RT_BIT(5))
273
274/* [0:3] bits of location region means geometry location attachment */
275#define CODEC_F1C_LOCATION_NA (0)
276#define CODEC_F1C_LOCATION_REAR (0x1)
277#define CODEC_F1C_LOCATION_FRONT (0x2)
278#define CODEC_F1C_LOCATION_LEFT (0x3)
279#define CODEC_F1C_LOCATION_RIGTH (0x4)
280#define CODEC_F1C_LOCATION_TOP (0x5)
281#define CODEC_F1C_LOCATION_BOTTOM (0x6)
282#define CODEC_F1C_LOCATION_SPECIAL_0 (0x7)
283#define CODEC_F1C_LOCATION_SPECIAL_1 (0x8)
284#define CODEC_F1C_LOCATION_SPECIAL_3 (0x9)
285
286/* Configuration's devices */
287#define CODEC_F1C_DEVICE_MASK (0xF)
288#define CODEC_F1C_DEVICE_SHIFT (20)
289#define CODEC_F1C_DEVICE_LINE_OUT (0)
290#define CODEC_F1C_DEVICE_SPEAKER (0x1)
291#define CODEC_F1C_DEVICE_HP (0x2)
292#define CODEC_F1C_DEVICE_CD (0x3)
293#define CODEC_F1C_DEVICE_SPDIF_OUT (0x4)
294#define CODEC_F1C_DEVICE_DIGITAL_OTHER_OUT (0x5)
295#define CODEC_F1C_DEVICE_MODEM_LINE_SIDE (0x6)
296#define CODEC_F1C_DEVICE_MODEM_HANDSET_SIDE (0x7)
297#define CODEC_F1C_DEVICE_LINE_IN (0x8)
298#define CODEC_F1C_DEVICE_AUX (0x9)
299#define CODEC_F1C_DEVICE_MIC (0xA)
300#define CODEC_F1C_DEVICE_PHONE (0xB)
301#define CODEC_F1C_DEVICE_SPDIF_IN (0xC)
302#define CODEC_F1C_DEVICE_RESERVED (0xE)
303#define CODEC_F1C_DEVICE_OTHER (0xF)
304
305/* Configuration's Connection type */
306#define CODEC_F1C_CONNECTION_TYPE_MASK (0xF)
307#define CODEC_F1C_CONNECTION_TYPE_SHIFT (16)
308
309#define CODEC_F1C_CONNECTION_TYPE_UNKNOWN (0)
310#define CODEC_F1C_CONNECTION_TYPE_1_8INCHES (0x1)
311#define CODEC_F1C_CONNECTION_TYPE_1_4INCHES (0x2)
312#define CODEC_F1C_CONNECTION_TYPE_ATAPI (0x3)
313#define CODEC_F1C_CONNECTION_TYPE_RCA (0x4)
314#define CODEC_F1C_CONNECTION_TYPE_OPTICAL (0x5)
315#define CODEC_F1C_CONNECTION_TYPE_OTHER_DIGITAL (0x6)
316#define CODEC_F1C_CONNECTION_TYPE_ANALOG (0x7)
317#define CODEC_F1C_CONNECTION_TYPE_DIN (0x8)
318#define CODEC_F1C_CONNECTION_TYPE_XLR (0x9)
319#define CODEC_F1C_CONNECTION_TYPE_RJ_11 (0xA)
320#define CODEC_F1C_CONNECTION_TYPE_COMBO (0xB)
321#define CODEC_F1C_CONNECTION_TYPE_OTHER (0xF)
322
323/* Configuration's color */
324#define CODEC_F1C_COLOR_MASK (0xF)
325#define CODEC_F1C_COLOR_SHIFT (12)
326#define CODEC_F1C_COLOR_UNKNOWN (0)
327#define CODEC_F1C_COLOR_BLACK (0x1)
328#define CODEC_F1C_COLOR_GREY (0x2)
329#define CODEC_F1C_COLOR_BLUE (0x3)
330#define CODEC_F1C_COLOR_GREEN (0x4)
331#define CODEC_F1C_COLOR_RED (0x5)
332#define CODEC_F1C_COLOR_ORANGE (0x6)
333#define CODEC_F1C_COLOR_YELLOW (0x7)
334#define CODEC_F1C_COLOR_PURPLE (0x8)
335#define CODEC_F1C_COLOR_PINK (0x9)
336#define CODEC_F1C_COLOR_RESERVED_0 (0xA)
337#define CODEC_F1C_COLOR_RESERVED_1 (0xB)
338#define CODEC_F1C_COLOR_RESERVED_2 (0xC)
339#define CODEC_F1C_COLOR_RESERVED_3 (0xD)
340#define CODEC_F1C_COLOR_WHITE (0xE)
341#define CODEC_F1C_COLOR_OTHER (0xF)
342
343/* Configuration's misc */
344#define CODEC_F1C_MISC_MASK (0xF)
345#define CODEC_F1C_MISC_SHIFT (8)
346#define CODEC_F1C_MISC_JACK_DETECT RT_BIT(0)
347#define CODEC_F1C_MISC_RESERVED_0 RT_BIT(1)
348#define CODEC_F1C_MISC_RESERVED_1 RT_BIT(2)
349#define CODEC_F1C_MISC_RESERVED_2 RT_BIT(3)
350
351/* Configuration's association */
352#define CODEC_F1C_ASSOCIATION_MASK (0xF)
353#define CODEC_F1C_ASSOCIATION_SHIFT (4)
354/* Connection's sequence */
355#define CODEC_F1C_SEQ_MASK (0xF)
356#define CODEC_F1C_SEQ_SHIFT (0)
357
358/* Implementation identification (7.3.3.30) */
359#define CODEC_MAKE_F20(bmid, bsku, aid) \
360 ( (((bmid) & 0xFFFF) << 16) \
361 | (((bsku) & 0xFF) << 8) \
362 | (((aid) & 0xFF)) \
363 )
364
365/* macro definition helping in filling the configuration registers. */
366#define CODEC_MAKE_F1C(port_connectivity, location, device, connection_type, color, misc, association, sequence) \
367 ( ((port_connectivity) << CODEC_F1C_PORT_SHIFT) \
368 | ((location) << CODEC_F1C_LOCATION_SHIFT) \
369 | ((device) << CODEC_F1C_DEVICE_SHIFT) \
370 | ((connection_type) << CODEC_F1C_CONNECTION_TYPE_SHIFT) \
371 | ((color) << CODEC_F1C_COLOR_SHIFT) \
372 | ((misc) << CODEC_F1C_MISC_SHIFT) \
373 | ((association) << CODEC_F1C_ASSOCIATION_SHIFT) \
374 | ((sequence)))
375
376/* STAC9220 */
377const static uint8_t au8Stac9220Ports[] = { 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, 0};
378const static uint8_t au8Stac9220Dacs[] = { 0x2, 0x3, 0x4, 0x5, 0};
379const static uint8_t au8Stac9220Adcs[] = { 0x6, 0x7, 0};
380const static uint8_t au8Stac9220SpdifOuts[] = { 0x8, 0 };
381const static uint8_t au8Stac9220SpdifIns[] = { 0x9, 0 };
382const static uint8_t au8Stac9220DigOutPins[] = { 0x10, 0 };
383const static uint8_t au8Stac9220DigInPins[] = { 0x11, 0 };
384const static uint8_t au8Stac9220AdcVols[] = { 0x17, 0x18, 0};
385const static uint8_t au8Stac9220AdcMuxs[] = { 0x12, 0x13, 0};
386const static uint8_t au8Stac9220Pcbeeps[] = { 0x14, 0 };
387const static uint8_t au8Stac9220Cds[] = { 0x15, 0 };
388const static uint8_t au8Stac9220VolKnobs[] = { 0x16, 0 };
389const static uint8_t au8Stac9220Reserveds[] = { 0x9, 0x19, 0x1a, 0x1b, 0 };
390
391static int stac9220ResetNode(struct CODECState *pState, uint8_t nodenum, PCODECNODE pNode);
392
393static int stac9220Construct(CODECState *pState)
394{
395 unconst(pState->cTotalNodes) = 0x1C;
396 pState->pfnCodecNodeReset = stac9220ResetNode;
397 pState->u16VendorId = 0x8384;
398 pState->u16DeviceId = 0x7680;
399 pState->u8BSKU = 0x76;
400 pState->u8AssemblyId = 0x80;
401 pState->pNodes = (PCODECNODE)RTMemAllocZ(sizeof(CODECNODE) * pState->cTotalNodes);
402 pState->fInReset = false;
403#define STAC9220WIDGET(type) pState->au8##type##s = au8Stac9220##type##s
404 STAC9220WIDGET(Port);
405 STAC9220WIDGET(Dac);
406 STAC9220WIDGET(Adc);
407 STAC9220WIDGET(AdcVol);
408 STAC9220WIDGET(AdcMux);
409 STAC9220WIDGET(Pcbeep);
410 STAC9220WIDGET(SpdifIn);
411 STAC9220WIDGET(SpdifOut);
412 STAC9220WIDGET(DigInPin);
413 STAC9220WIDGET(DigOutPin);
414 STAC9220WIDGET(Cd);
415 STAC9220WIDGET(VolKnob);
416 STAC9220WIDGET(Reserved);
417#undef STAC9220WIDGET
418 unconst(pState->u8AdcVolsLineIn) = 0x17;
419 unconst(pState->u8DacLineOut) = 0x2;
420
421 return VINF_SUCCESS;
422}
423
424static int stac9220ResetNode(struct CODECState *pState, uint8_t nodenum, PCODECNODE pNode)
425{
426 pNode->node.id = nodenum;
427 pNode->node.au32F00_param[0xF] = 0; /* Power statest Supported: are the same as AFG reports */
428 switch (nodenum)
429 {
430 /* Root Node*/
431 case 0:
432 pNode->root.node.name = "Root";
433 pNode->node.au32F00_param[2] = CODEC_MAKE_F00_02(0x1, 0x0, 0x34, 0x1); /* rev id */
434 break;
435 case 1:
436 pNode->afg.node.name = "AFG";
437 pNode->node.au32F00_param[8] = CODEC_MAKE_F00_08(CODEC_F00_08_BEEP_GEN, 0xd, 0xd);
438 pNode->node.au32F00_param[0xC] = CODEC_MAKE_F00_0C(0x17)
439 | CODEC_F00_0C_CAP_BALANCED_IO
440 | CODEC_F00_0C_CAP_INPUT
441 | CODEC_F00_0C_CAP_PRESENSE_DETECT
442 | CODEC_F00_0C_CAP_TRIGGER_REQUIRED
443 | CODEC_F00_0C_CAP_IMPENDANCE_SENSE;//(17 << 8)|RT_BIT(6)|RT_BIT(5)|RT_BIT(2)|RT_BIT(1)|RT_BIT(0);
444 pNode->node.au32F00_param[0xB] = CODEC_F00_0B_PCM;
445 pNode->node.au32F00_param[0xD] = CODEC_MAKE_F00_0D(1, 0x5, 0xE, 0);//RT_BIT(31)|(0x5 << 16)|(0xE)<<8;
446 pNode->node.au32F00_param[0x12] = RT_BIT(31)|(0x2 << 16)|(0x7f << 8)|0x7f;
447 pNode->node.au32F00_param[0x11] = CODEC_MAKE_F00_11(1, 1, 0, 0, 4);//0xc0000004;
448 pNode->node.au32F00_param[0xF] = CODEC_F00_0F_D3|CODEC_F00_0F_D2|CODEC_F00_0F_D1|CODEC_F00_0F_D0;
449 pNode->afg.u32F05_param = CODEC_MAKE_F05(0, 0, 0, CODEC_F05_D2, CODEC_F05_D2);//0x2 << 4| 0x2; /* PS-Act: D3, PS->Set D3 */
450 pNode->afg.u32F08_param = 0;
451 pNode->afg.u32F17_param = 0;
452 break;
453 case 2:
454 pNode->dac.node.name = "DAC0";
455 goto dac_init;
456 case 3:
457 pNode->dac.node.name = "DAC1";
458 goto dac_init;
459 case 4:
460 pNode->dac.node.name = "DAC2";
461 goto dac_init;
462 case 5:
463 pNode->dac.node.name = "DAC3";
464 dac_init:
465 memset(pNode->dac.B_params, 0, AMPLIFIER_SIZE);
466 pNode->dac.u32A_param = CODEC_MAKE_A(0, 1, CODEC_A_MULT_1X, CODEC_A_DIV_1X, CODEC_A_16_BIT, 1);//RT_BIT(14)|(0x1 << 4)|0x1; /* 441000Hz/16bit/2ch */
467
468 AMPLIFIER_REGISTER(pNode->dac.B_params, AMPLIFIER_OUT, AMPLIFIER_LEFT, 0) = 0x7F | RT_BIT(7);
469 AMPLIFIER_REGISTER(pNode->dac.B_params, AMPLIFIER_OUT, AMPLIFIER_RIGHT, 0) = 0x7F | RT_BIT(7);
470
471 pNode->dac.node.au32F00_param[9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_AUDIO_OUTPUT, 0xD, 0)
472 | CODEC_F00_09_CAP_L_R_SWAP
473 | CODEC_F00_09_CAP_POWER_CTRL
474 | CODEC_F00_09_CAP_OUT_AMP_PRESENT
475 | CODEC_F00_09_CAP_LSB;//(0xD << 16) | RT_BIT(11) | RT_BIT(10) | RT_BIT(2) | RT_BIT(0);
476 pNode->dac.u32F0c_param = 0;
477 pNode->dac.u32F05_param = CODEC_MAKE_F05(0, 0, 0, CODEC_F05_D3, CODEC_F05_D3);//0x3 << 4 | 0x3; /* PS-Act: D3, Set: D3 */
478 break;
479 case 6:
480 pNode->adc.node.name = "ADC0";
481 pNode->node.au32F02_param[0] = 0x17;
482 goto adc_init;
483 case 7:
484 pNode->adc.node.name = "ADC1";
485 pNode->node.au32F02_param[0] = 0x18;
486 adc_init:
487 pNode->adc.u32A_param = CODEC_MAKE_A(0, 1, CODEC_A_MULT_1X, CODEC_A_DIV_1X, CODEC_A_16_BIT, 1);//RT_BIT(14)|(0x1 << 3)|0x1; /* 441000Hz/16bit/2ch */
488 pNode->adc.node.au32F00_param[0xE] = CODEC_MAKE_F00_0E(0, 1);//RT_BIT(0);
489 pNode->adc.u32F03_param = RT_BIT(0);
490 pNode->adc.u32F05_param = CODEC_MAKE_F05(0, 0, 0, CODEC_F05_D3, CODEC_F05_D3);//0x3 << 4 | 0x3; /* PS-Act: D3 Set: D3 */
491 pNode->adc.u32F06_param = 0;
492 pNode->adc.node.au32F00_param[9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_AUDIO_INPUT, 0xD, 0)
493 | CODEC_F00_09_CAP_POWER_CTRL
494 | CODEC_F00_09_CAP_CONNECTION_LIST
495 | CODEC_F00_09_CAP_PROC_WIDGET
496 | CODEC_F00_09_CAP_LSB;//RT_BIT(20)| (0xd << 16) | RT_BIT(10) | RT_BIT(8) | RT_BIT(6)| RT_BIT(0);
497 break;
498 case 8:
499 pNode->spdifout.node.name = "SPDIFOut";
500 pNode->spdifout.u32A_param = CODEC_MAKE_A(0, 1, CODEC_A_MULT_1X, CODEC_A_DIV_1X, CODEC_A_16_BIT, 1);//(1<<14)|(0x1<<4) | 0x1;
501 pNode->spdifout.node.au32F00_param[9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_AUDIO_OUTPUT, 0x4, 0)
502 | CODEC_F00_09_CAP_DIGITAL
503 | CODEC_F00_09_CAP_FMT_OVERRIDE
504 | CODEC_F00_09_CAP_LSB;//(4 << 16) | RT_BIT(9)|RT_BIT(4)|0x1;
505 pNode->node.au32F00_param[0xa] = pState->pNodes[1].node.au32F00_param[0xA];
506 pNode->spdifout.node.au32F00_param[0xB] = CODEC_F00_0B_PCM;
507 pNode->spdifout.u32F06_param = 0;
508 pNode->spdifout.u32F0d_param = 0;
509 break;
510 case 9:
511 pNode->node.name = "Reserved_0";
512 pNode->spdifin.u32A_param = CODEC_MAKE_A(0, 1, CODEC_A_MULT_1X, CODEC_A_DIV_1X, CODEC_A_16_BIT, 1);//(0x1<<4) | 0x1;
513 pNode->spdifin.u32F09_param = CODEC_MAKE_F09_ANALOG(0, CODEC_F09_ANALOG_NA);//RT_BIT(31)|0x7fffffff;
514 pNode->spdifin.node.au32F00_param[9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_AUDIO_INPUT, 0x4, 0)
515 | CODEC_F00_09_CAP_DIGITAL
516 | CODEC_F00_09_CAP_CONNECTION_LIST
517 | CODEC_F00_09_CAP_FMT_OVERRIDE
518 | CODEC_F00_09_CAP_LSB;//(0x1 << 20)|(4 << 16) | RT_BIT(9)| RT_BIT(8)|RT_BIT(4)|0x1;
519 pNode->node.au32F00_param[0xA] = pState->pNodes[1].node.au32F00_param[0xA];
520 pNode->node.au32F00_param[0xE] = CODEC_MAKE_F00_0E(0, 1);//RT_BIT(0);
521 pNode->node.au32F02_param[0] = 0x11;
522 pNode->spdifin.node.au32F00_param[0xB] = CODEC_F00_0B_PCM;
523 pNode->spdifin.u32F06_param = 0;
524 pNode->spdifin.u32F0d_param = 0;
525 break;
526 case 0xA:
527 pNode->node.name = "PortA";
528 pNode->node.au32F00_param[0xC] = CODEC_MAKE_F00_0C(0x17)
529 | CODEC_F00_0C_CAP_INPUT
530 | CODEC_F00_0C_CAP_OUTPUT
531 | CODEC_F00_0C_CAP_HP
532 | CODEC_F00_0C_CAP_PRESENSE_DETECT
533 | CODEC_F00_0C_CAP_TRIGGER_REQUIRED
534 | CODEC_F00_0C_CAP_IMPENDANCE_SENSE;//0x173f;
535 pNode->node.au32F02_param[0] = 0x2;
536 pNode->port.u32F07_param = 0xc0;//RT_BIT(6);
537 pNode->port.u32F08_param = 0;
538 if (!pState->fInReset)
539 pNode->port.u32F1c_param = CODEC_MAKE_F1C(CODEC_F1C_PORT_COMPLEX,
540 CODEC_F1C_LOCATION_FRONT,
541 CODEC_F1C_DEVICE_HP,
542 CODEC_F1C_CONNECTION_TYPE_1_8INCHES,
543 CODEC_F1C_COLOR_GREEN,
544 CODEC_F1C_MISC_JACK_DETECT,
545 0x2, 0);//RT_MAKE_U32_FROM_U8(0x20, 0x40, 0x21, 0x02);
546 goto port_init;
547 case 0xB:
548 pNode->node.name = "PortB";
549 pNode->node.au32F00_param[0xC] = CODEC_MAKE_F00_0C(0x17)
550 | CODEC_F00_0C_CAP_INPUT
551 | CODEC_F00_0C_CAP_OUTPUT
552 | CODEC_F00_0C_CAP_PRESENSE_DETECT
553 | CODEC_F00_0C_CAP_TRIGGER_REQUIRED
554 | CODEC_F00_0C_CAP_IMPENDANCE_SENSE;//0x1737;
555 pNode->node.au32F02_param[0] = 0x4;
556 pNode->port.u32F07_param = RT_BIT(5);
557 if (!pState->fInReset)
558 pNode->port.u32F1c_param = CODEC_MAKE_F1C(CODEC_F1C_PORT_COMPLEX,
559 CODEC_F1C_LOCATION_INTERNAL|CODEC_F1C_LOCATION_REAR,
560 CODEC_F1C_DEVICE_SPEAKER,
561 CODEC_F1C_CONNECTION_TYPE_1_8INCHES,
562 CODEC_F1C_COLOR_BLACK,
563 CODEC_F1C_MISC_JACK_DETECT,
564 0x1, 0x1);//RT_MAKE_U32_FROM_U8(0x11, 0x60, 0x11, 0x01);
565 goto port_init;
566 case 0xC:
567 pNode->node.name = "PortC";
568 pNode->node.au32F02_param[0] = 0x3;
569 pNode->node.au32F00_param[0xC] = CODEC_MAKE_F00_0C(0x17)
570 | CODEC_F00_0C_CAP_INPUT
571 | CODEC_F00_0C_CAP_OUTPUT
572 | CODEC_F00_0C_CAP_PRESENSE_DETECT
573 | CODEC_F00_0C_CAP_TRIGGER_REQUIRED
574 | CODEC_F00_0C_CAP_IMPENDANCE_SENSE;//0x1737;
575 pNode->port.u32F07_param = RT_BIT(5);
576 if (!pState->fInReset)
577 pNode->port.u32F1c_param = CODEC_MAKE_F1C(CODEC_F1C_PORT_COMPLEX,
578 CODEC_F1C_LOCATION_REAR,
579 CODEC_F1C_DEVICE_SPEAKER,
580 CODEC_F1C_CONNECTION_TYPE_1_8INCHES,
581 CODEC_F1C_COLOR_GREEN,
582 0x0, 0x1, 0x0);//RT_MAKE_U32_FROM_U8(0x10, 0x40, 0x11, 0x01);
583 goto port_init;
584 case 0xD:
585 pNode->node.name = "PortD";
586 pNode->node.au32F00_param[0xC] = CODEC_MAKE_F00_0C(0x17)
587 | CODEC_F00_0C_CAP_INPUT
588 | CODEC_F00_0C_CAP_OUTPUT
589 | CODEC_F00_0C_CAP_PRESENSE_DETECT
590 | CODEC_F00_0C_CAP_TRIGGER_REQUIRED
591 | CODEC_F00_0C_CAP_IMPENDANCE_SENSE;//0x1737;
592 pNode->port.u32F07_param = RT_BIT(5);
593 pNode->node.au32F02_param[0] = 0x2;
594 if (!pState->fInReset)
595 pNode->port.u32F1c_param = CODEC_MAKE_F1C(CODEC_F1C_PORT_COMPLEX,
596 CODEC_F1C_LOCATION_FRONT,
597 CODEC_F1C_DEVICE_MIC,
598 CODEC_F1C_CONNECTION_TYPE_1_8INCHES,
599 CODEC_F1C_COLOR_PINK,
600 0x0, 0x5, 0x0);//RT_MAKE_U32_FROM_U8(0x50, 0x90, 0xA1, 0x02); /* Microphone */
601 port_init:
602 pNode->port.u32F09_param = CODEC_MAKE_F09_ANALOG(1, CODEC_F09_ANALOG_NA);//RT_BIT(31)|0x7fffffff;
603 pNode->port.u32F08_param = 0;
604 pNode->node.au32F00_param[9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_PIN_COMPLEX, 0x0, 0)
605 | CODEC_F00_09_CAP_CONNECTION_LIST
606 | CODEC_F00_09_CAP_UNSOL
607 | CODEC_F00_09_CAP_LSB;//(4 << 20)|RT_BIT(8)|RT_BIT(7)|RT_BIT(0);
608 pNode->node.au32F00_param[0xE] = CODEC_MAKE_F00_0E(0, 1);//0x1;
609 break;
610 case 0xE:
611 pNode->node.name = "PortE";
612 pNode->node.au32F00_param[9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_PIN_COMPLEX, 0x0, 0)
613 | CODEC_F00_09_CAP_UNSOL
614 | CODEC_F00_09_CAP_LSB;//(4 << 20)|RT_BIT(7)|RT_BIT(0);
615 pNode->port.u32F08_param = 0;
616 pNode->node.au32F00_param[0xC] = CODEC_F00_0C_CAP_INPUT
617 | CODEC_F00_0C_CAP_OUTPUT
618 | CODEC_F00_0C_CAP_PRESENSE_DETECT;//0x34;
619 pNode->port.u32F07_param = RT_BIT(5);
620 pNode->port.u32F09_param = CODEC_MAKE_F09_ANALOG(0, CODEC_F09_ANALOG_NA);//0x7fffffff;
621 if (!pState->fInReset)
622 pNode->port.u32F1c_param = CODEC_MAKE_F1C(CODEC_F1C_PORT_COMPLEX,
623 CODEC_F1C_LOCATION_REAR,
624 CODEC_F1C_DEVICE_LINE_OUT,
625 CODEC_F1C_CONNECTION_TYPE_1_8INCHES,
626 CODEC_F1C_COLOR_BLUE,
627 0x0, 0x4, 0x0);//0x01013040; /* Line Out */
628 break;
629 case 0xF:
630 pNode->node.name = "PortF";
631 pNode->node.au32F00_param[9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_PIN_COMPLEX, 0x0, 0x0)
632 | CODEC_F00_09_CAP_CONNECTION_LIST
633 | CODEC_F00_09_CAP_UNSOL
634 | CODEC_F00_09_CAP_OUT_AMP_PRESENT
635 | CODEC_F00_09_CAP_LSB;//(4 << 20)|RT_BIT(8)|RT_BIT(7)|RT_BIT(2)|RT_BIT(0);
636 pNode->node.au32F00_param[0xC] = CODEC_F00_0C_CAP_INPUT
637 | CODEC_F00_0C_CAP_OUTPUT
638 | CODEC_F00_0C_CAP_PRESENSE_DETECT
639 | CODEC_F00_0C_CAP_TRIGGER_REQUIRED
640 | CODEC_F00_0C_CAP_IMPENDANCE_SENSE;//0x37;
641 pNode->node.au32F00_param[0xE] = CODEC_MAKE_F00_0E(0, 1);//0x1;
642 pNode->port.u32F08_param = 0;
643 pNode->port.u32F07_param = 0x40;
644 if (!pState->fInReset)
645 pNode->port.u32F1c_param = CODEC_MAKE_F1C(CODEC_F1C_PORT_COMPLEX,
646 CODEC_F1C_LOCATION_REAR,
647 CODEC_F1C_DEVICE_SPEAKER,
648 CODEC_F1C_CONNECTION_TYPE_1_8INCHES,
649 CODEC_F1C_COLOR_ORANGE,
650 0x0, 0x1, 0x2);//RT_MAKE_U32_FROM_U8(0x12, 0x60, 0x11, 0x01);
651 pNode->node.au32F02_param[0] = 0x5;
652 pNode->port.u32F09_param = CODEC_MAKE_F09_ANALOG(0, CODEC_F09_ANALOG_NA);//0x7fffffff;
653 break;
654 case 0x10:
655 pNode->node.name = "DigOut_0";
656 pNode->node.au32F00_param[9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_PIN_COMPLEX, 0x0, 0x0)
657 | CODEC_F00_09_CAP_DIGITAL
658 | CODEC_F00_09_CAP_CONNECTION_LIST
659 | CODEC_F00_09_CAP_LSB;//(4<<20)|RT_BIT(9)|RT_BIT(8)|RT_BIT(0);
660 pNode->node.au32F00_param[0xC] = CODEC_F00_0C_CAP_OUTPUT;//RT_BIT(4);
661 pNode->node.au32F00_param[0xE] = CODEC_MAKE_F00_0E(0, 0x3);
662 pNode->digout.u32F01_param = 0;
663 pNode->node.au32F02_param[0] = RT_MAKE_U32_FROM_U8(0x08, 0x17, 0x19, 0);
664 pNode->digout.u32F07_param = 0;
665 if (!pState->fInReset)
666 pNode->digout.u32F1c_param = CODEC_MAKE_F1C(CODEC_F1C_PORT_COMPLEX,
667 CODEC_F1C_LOCATION_REAR,
668 CODEC_F1C_DEVICE_SPDIF_OUT,
669 CODEC_F1C_CONNECTION_TYPE_DIN,
670 CODEC_F1C_COLOR_BLACK,
671 0x0, 0x3, 0x0);//RT_MAKE_U32_FROM_U8(0x30, 0x10, 0x45, 0x01);
672 break;
673 case 0x11:
674 pNode->node.name = "DigIn_0";
675 pNode->node.au32F00_param[9] = (4 << 20)|(3<<16)|RT_BIT(10)|RT_BIT(9)|RT_BIT(7)|RT_BIT(0);
676 pNode->node.au32F00_param[0xC] = CODEC_F00_0C_CAP_EAPD
677 | CODEC_F00_0C_CAP_INPUT
678 | CODEC_F00_0C_CAP_PRESENSE_DETECT;//RT_BIT(16)| RT_BIT(5)|RT_BIT(2);
679 pNode->digin.u32F05_param = CODEC_MAKE_F05(0, 0, 0, CODEC_F05_D3, CODEC_F05_D3);//0x3 << 4 | 0x3; /* PS-Act: D3 -> D3 */
680 pNode->digin.u32F07_param = 0;
681 pNode->digin.u32F08_param = 0;
682 pNode->digin.u32F09_param = 0;
683 pNode->digin.u32F0c_param = 0;
684 if (!pState->fInReset)
685 pNode->digin.u32F1c_param = CODEC_MAKE_F1C(CODEC_F1C_PORT_COMPLEX,
686 CODEC_F1C_LOCATION_REAR,
687 CODEC_F1C_DEVICE_SPDIF_IN,
688 CODEC_F1C_CONNECTION_TYPE_OTHER_DIGITAL,
689 CODEC_F1C_COLOR_BLACK,
690 0x0, 0x6, 0x0);//(0x1 << 24) | (0xc5 << 16) | (0x10 << 8) | 0x60;
691 break;
692 case 0x12:
693 pNode->node.name = "ADCMux_0";
694 pNode->adcmux.u32F01_param = 0;
695 goto adcmux_init;
696 case 0x13:
697 pNode->node.name = "ADCMux_1";
698 pNode->adcmux.u32F01_param = 1;
699 adcmux_init:
700 pNode->node.au32F00_param[9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_AUDIO_SELECTOR, 0x0, 0)
701 | CODEC_F00_09_CAP_CONNECTION_LIST
702 | CODEC_F00_09_CAP_AMP_FMT_OVERRIDE
703 | CODEC_F00_09_CAP_OUT_AMP_PRESENT
704 | CODEC_F00_09_CAP_LSB;//(3<<20)|RT_BIT(8)|RT_BIT(3)|RT_BIT(2)|RT_BIT(0);
705 pNode->node.au32F00_param[0xe] = CODEC_MAKE_F00_0E(0, 0x7);
706 pNode->node.au32F00_param[0x12] = (0x27 << 16)|(0x4 << 8);
707 /* STAC 9220 v10 6.21-22.{4,5} both(left and right) out amplefiers inited with 0*/
708 memset(pNode->adcmux.B_params, 0, AMPLIFIER_SIZE);
709 pNode->node.au32F02_param[0] = RT_MAKE_U32_FROM_U8(0xe, 0x15, 0xf, 0xb);
710 pNode->node.au32F02_param[4] = RT_MAKE_U32_FROM_U8(0xc, 0xd, 0xa, 0x0);
711 break;
712 case 0x14:
713 pNode->node.name = "PCBEEP";
714 pNode->node.au32F00_param[9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_BEEP_GEN, 0, 0)
715 | CODEC_F00_09_CAP_AMP_FMT_OVERRIDE
716 | CODEC_F00_09_CAP_OUT_AMP_PRESENT;//(7 << 20) | RT_BIT(3) | RT_BIT(2);
717 pNode->node.au32F00_param[0x12] = (0x17 << 16)|(0x3 << 8)| 0x3;
718 pNode->pcbeep.u32F0a_param = 0;
719 memset(pNode->pcbeep.B_params, 0, AMPLIFIER_SIZE);
720 break;
721 case 0x15:
722 pNode->node.name = "CD";
723 pNode->node.au32F00_param[0x9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_PIN_COMPLEX, 0, 0)
724 | CODEC_F00_09_CAP_LSB;//(4 << 20)|RT_BIT(0);
725 pNode->node.au32F00_param[0xc] = CODEC_F00_0C_CAP_INPUT;//RT_BIT(5);
726 pNode->cdnode.u32F07_param = 0;
727 if (!pState->fInReset)
728 pNode->cdnode.u32F1c_param = CODEC_MAKE_F1C(CODEC_F1C_PORT_FIXED,
729 CODEC_F1C_LOCATION_INTERNAL,
730 CODEC_F1C_DEVICE_CD,
731 CODEC_F1C_CONNECTION_TYPE_ATAPI,
732 CODEC_F1C_COLOR_UNKNOWN,
733 0x0, 0x7, 0x0);//RT_MAKE_U32_FROM_U8(0x70, 0x0, 0x33, 0x90);
734 break;
735 case 0x16:
736 pNode->node.name = "VolumeKnob";
737 pNode->node.au32F00_param[0x9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_VOLUME_KNOB, 0x0, 0x0);//(0x6 << 20);
738 pNode->node.au32F00_param[0x13] = RT_BIT(7)| 0x7F;
739 pNode->node.au32F00_param[0xe] = CODEC_MAKE_F00_0E(0, 0x4);
740 pNode->node.au32F02_param[0] = RT_MAKE_U32_FROM_U8(0x2, 0x3, 0x4, 0x5);
741 pNode->volumeKnob.u32F08_param = 0;
742 pNode->volumeKnob.u32F0f_param = 0x7f;
743 break;
744 case 0x17:
745 pNode->node.name = "ADC0Vol";
746 pNode->node.au32F02_param[0] = 0x12;
747 goto adcvol_init;
748 case 0x18:
749 pNode->node.name = "ADC1Vol";
750 pNode->node.au32F02_param[0] = 0x13;
751 adcvol_init:
752 memset(pNode->adcvol.B_params, 0, AMPLIFIER_SIZE);
753
754 pNode->node.au32F00_param[0x9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_AUDIO_SELECTOR, 0, 0)
755 | CODEC_F00_09_CAP_L_R_SWAP
756 | CODEC_F00_09_CAP_CONNECTION_LIST
757 | CODEC_F00_09_CAP_IN_AMP_PRESENT
758 | CODEC_F00_09_CAP_LSB;//(0x3 << 20)|RT_BIT(11)|RT_BIT(8)|RT_BIT(1)|RT_BIT(0);
759 pNode->node.au32F00_param[0xe] = CODEC_MAKE_F00_0E(0, 0x1);
760 AMPLIFIER_REGISTER(pNode->adcvol.B_params, AMPLIFIER_IN, AMPLIFIER_LEFT, 0) = RT_BIT(7);
761 AMPLIFIER_REGISTER(pNode->adcvol.B_params, AMPLIFIER_IN, AMPLIFIER_RIGHT, 0) = RT_BIT(7);
762 pNode->adcvol.u32F0c_param = 0;
763 break;
764 case 0x19:
765 pNode->node.name = "Reserved_1";
766 pNode->node.au32F00_param[0x9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_VENDOR_DEFINED, 0x3, 0)
767 | CODEC_F00_09_CAP_DIGITAL
768 | CODEC_F00_09_CAP_LSB;//(0xF << 20)|(0x3 << 16)|RT_BIT(9)|RT_BIT(0);
769 break;
770 case 0x1A:
771 pNode->node.name = "Reserved_2";
772 pNode->node.au32F00_param[0x9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_AUDIO_OUTPUT, 0x3, 0)
773 | CODEC_F00_09_CAP_DIGITAL
774 | CODEC_F00_09_CAP_LSB;//(0x3 << 16)|RT_BIT(9)|RT_BIT(0);
775 break;
776 case 0x1B:
777 pNode->node.name = "Reserved_3";
778 pNode->node.au32F00_param[0x9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_PIN_COMPLEX, 0, 0)
779 | CODEC_F00_09_CAP_DIGITAL
780 | CODEC_F00_09_CAP_CONNECTION_LIST
781 | CODEC_F00_09_CAP_LSB;//(0x4 << 20)|RT_BIT(9)|RT_BIT(8)|RT_BIT(0);
782 pNode->node.au32F00_param[0xE] = CODEC_MAKE_F00_0E(0, 0x1);
783 pNode->node.au32F00_param[0xC] = CODEC_F00_0C_CAP_OUTPUT;//0x10;
784 pNode->node.au32F02_param[0] = 0x1a;
785 pNode->reserved.u32F07_param = 0;
786 pNode->reserved.u32F1c_param = CODEC_MAKE_F1C(CODEC_F1C_PORT_NO_PHYS,
787 CODEC_F1C_LOCATION_NA,
788 CODEC_F1C_DEVICE_LINE_OUT,
789 CODEC_F1C_CONNECTION_TYPE_UNKNOWN,
790 CODEC_F1C_COLOR_UNKNOWN,
791 0x0, 0x0, 0xf);//0x4000000f;
792 break;
793 default:
794 break;
795 }
796 return VINF_SUCCESS;
797}
798
799/* ALC885 */
800const static uint8_t au8Alc885Ports[] = { 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0};
801const static uint8_t au8Alc885Dacs[] = { 0x2, 0x3, 0x4, 0x5, 0x25, 0};
802const static uint8_t au8Alc885Adcs[] = { 0x7, 0x8, 0x9, 0};
803const static uint8_t au8Alc885SpdifOuts[] = { 0x6, 0 };
804const static uint8_t au8Alc885SpdifIns[] = { 0xA, 0 };
805const static uint8_t au8Alc885DigOutPins[] = { 0x1E, 0 };
806const static uint8_t au8Alc885DigInPins[] = { 0x1F, 0 };
807const static uint8_t au8Alc885AdcVols[] = { 0xE, 0xF, 0xD, 0xC, 0x26, 0xB, 0};
808const static uint8_t au8Alc885AdcMuxs[] = { 0x22, 0x23, 0x24, 0};
809const static uint8_t au8Alc885Pcbeeps[] = { 0x1D, 0 };
810const static uint8_t au8Alc885Cds[] = { 0x1C, 0 };
811const static uint8_t au8Alc885VolKnobs[] = { 0x21, 0 };
812const static uint8_t au8Alc885Reserveds[] = { 0x10, 0x11, 0x12, 0x13, 0 };
813
814
815static int alc885ResetNode(struct CODECState *pState, uint8_t nodenum, PCODECNODE pNode);
816
817static int alc885Construct(CODECState *pState)
818{
819 unconst(pState->cTotalNodes) = 0x27;
820 pState->u16VendorId = 0x10ec;
821 pState->u16DeviceId = 0x0885;
822 pState->u8BSKU = 0x08;
823 pState->u8AssemblyId = 0x85;
824 pState->pfnCodecNodeReset = alc885ResetNode;
825 pState->pNodes = (PCODECNODE)RTMemAllocZ(sizeof(CODECNODE) * pState->cTotalNodes);
826 pState->fInReset = false;
827#define ALC885WIDGET(type) pState->au8##type##s = au8Alc885##type##s
828 ALC885WIDGET(Port);
829 ALC885WIDGET(Dac);
830 ALC885WIDGET(Adc);
831 ALC885WIDGET(AdcVol);
832 ALC885WIDGET(AdcMux);
833 ALC885WIDGET(Pcbeep);
834 ALC885WIDGET(SpdifIn);
835 ALC885WIDGET(SpdifOut);
836 ALC885WIDGET(DigInPin);
837 ALC885WIDGET(DigOutPin);
838 ALC885WIDGET(Cd);
839 ALC885WIDGET(VolKnob);
840 ALC885WIDGET(Reserved);
841#undef ALC885WIDGET
842 /* @todo: test more */
843 unconst(pState->u8AdcVolsLineIn) = 0x1a;
844 unconst(pState->u8DacLineOut) = 0x0d;
845
846 return VINF_SUCCESS;
847}
848
849static int alc885ResetNode(struct CODECState *pState, uint8_t nodenum, PCODECNODE pNode)
850{
851 pNode->node.id = nodenum;
852 switch (nodenum)
853 {
854 case 0: /* Root */
855 pNode->node.au32F00_param[2] = CODEC_MAKE_F00_02(0x1, 0x0, 0x0, 0x0); /* Realtek 889 (8.1.9)*/
856 pNode->node.au32F00_param[0xA] = pState->pNodes[1].node.au32F00_param[0xA];
857
858 break;
859 case 0x1: /* AFG */
860 pNode->node.au32F00_param[0xB] = CODEC_F00_0B_PCM;
861 pNode->node.au32F00_param[0x11] = RT_BIT(30)|0x2;
862 break;
863 /* DACs */
864 case 0x2:
865 pNode->node.name = "DAC-0";
866 goto dac_init;
867 case 0x3:
868 pNode->node.name = "DAC-1";
869 goto dac_init;
870 case 0x4:
871 pNode->node.name = "DAC-2";
872 goto dac_init;
873 case 0x5:
874 pNode->node.name = "DAC-3";
875 goto dac_init;
876 case 0x25:
877 pNode->node.name = "DAC-4";
878 dac_init:
879 pNode->node.au32F00_param[0xA] = pState->pNodes[1].node.au32F00_param[0xA];
880 pNode->node.au32F00_param[0x9] = 0x11;
881 pNode->node.au32F00_param[0xB] = CODEC_F00_0B_PCM;
882 pNode->dac.u32A_param = CODEC_MAKE_A(0, 1, CODEC_A_MULT_1X, CODEC_A_DIV_1X, CODEC_A_16_BIT, 1);//(1<<14)|(0x1<<4) | 0x1;
883 break;
884 /* SPDIFs */
885 case 0x6:
886 pNode->node.name = "SPDIFOUT-0";
887 pNode->node.au32F00_param[0x9] = 0x211;
888 pNode->node.au32F00_param[0xB] = 0x1;
889 pNode->node.au32F00_param[0xA] = pState->pNodes[1].node.au32F00_param[0xA];
890 pNode->spdifout.u32A_param = CODEC_MAKE_A(0, 1, CODEC_A_MULT_1X, CODEC_A_DIV_1X, CODEC_A_16_BIT, 1);//(1<<14)|(0x1<<4) | 0x1;
891 break;
892 case 0xA:
893 pNode->node.name = "SPDIFIN-0";
894 pNode->node.au32F00_param[0x9] = 0x100391;
895 pNode->node.au32F00_param[0xA] = pState->pNodes[1].node.au32F00_param[0xA];
896 pNode->node.au32F00_param[0xB] = 0x1;
897 pNode->node.au32F02_param[0] = RT_MAKE_U32_FROM_U8(0x1F, 0, 0, 0);
898 pNode->node.au32F02_param[1] = RT_MAKE_U32_FROM_U8(0x1F, 0, 0, 0);
899 pNode->node.au32F02_param[2] = RT_MAKE_U32_FROM_U8(0x1F, 0, 0, 0);
900 pNode->node.au32F02_param[3] = RT_MAKE_U32_FROM_U8(0x1F, 0, 0, 0);
901 pNode->node.au32F00_param[0xA] = pState->pNodes[1].node.au32F00_param[0xA];
902 pNode->spdifin.u32A_param = CODEC_MAKE_A(0, 1, CODEC_A_MULT_1X, CODEC_A_DIV_1X, CODEC_A_16_BIT, 1);//(1<<14)|(0x1<<4) | 0x1;
903 break;
904 /* VENDOR DEFINE */
905 case 0x10:
906 pNode->node.name = "VENDEF-0";
907 goto vendor_define_init;
908 case 0x11:
909 pNode->node.name = "VENDEF-1";
910 goto vendor_define_init;
911 case 0x12:
912 pNode->node.name = "VENDEF-2";
913 goto vendor_define_init;
914 case 0x13:
915 pNode->node.name = "VENDEF-3";
916 goto vendor_define_init;
917 case 0x20:
918 pNode->node.name = "VENDEF-4";
919 vendor_define_init:
920 pNode->node.au32F00_param[0x9] = 0xf00000;
921 break;
922
923 /* DIGPIN */
924 case 0x1E:
925 pNode->node.name = "DIGOUT-1";
926 pNode->node.au32F00_param[0x9] = 0x400300;
927 pNode->node.au32F00_param[0xE] = 0x1;
928 pNode->port.u32F1c_param = 0x14be060;
929 pNode->node.au32F00_param[0xC] = RT_BIT(4);
930 /* N = 0~3 */
931 pNode->node.au32F02_param[0] = RT_MAKE_U32_FROM_U8(0x6, 0x0, 0x0, 0x0);
932 pNode->node.au32F02_param[1] = RT_MAKE_U32_FROM_U8(0x6, 0x0, 0x0, 0x0);
933 pNode->node.au32F02_param[2] = RT_MAKE_U32_FROM_U8(0x6, 0x0, 0x0, 0x0);
934 pNode->node.au32F02_param[3] = RT_MAKE_U32_FROM_U8(0x6, 0x0, 0x0, 0x0);
935 break;
936 case 0x1F:
937 pNode->node.name = "DIGIN-0";
938 pNode->node.au32F00_param[9] = 0x400200;
939 /* N = 0~3 */
940 pNode->node.au32F02_param[0] = RT_MAKE_U32_FROM_U8(0xA, 0x0, 0x0, 0x0);
941 pNode->node.au32F02_param[1] = RT_MAKE_U32_FROM_U8(0xA, 0x0, 0x0, 0x0);
942 pNode->node.au32F02_param[2] = RT_MAKE_U32_FROM_U8(0xA, 0x0, 0x0, 0x0);
943 pNode->node.au32F02_param[3] = RT_MAKE_U32_FROM_U8(0xA, 0x0, 0x0, 0x0);
944 break;
945 /* ADCs */
946 case 0x7:
947 pNode->node.name = "ADC-0";
948 pNode->node.au32F02_param[0] = RT_MAKE_U32_FROM_U8(0x23, 0, 0, 0);
949 pNode->node.au32F02_param[1] = RT_MAKE_U32_FROM_U8(0x23, 0, 0, 0);
950 pNode->node.au32F02_param[2] = RT_MAKE_U32_FROM_U8(0x23, 0, 0, 0);
951 pNode->node.au32F02_param[3] = RT_MAKE_U32_FROM_U8(0x23, 0, 0, 0);
952 goto adc_init;
953 break;
954 case 0x8:
955 pNode->node.name = "ADC-1";
956 pNode->node.au32F02_param[0] = RT_MAKE_U32_FROM_U8(0x24, 0, 0, 0);
957 pNode->node.au32F02_param[1] = RT_MAKE_U32_FROM_U8(0x24, 0, 0, 0);
958 pNode->node.au32F02_param[2] = RT_MAKE_U32_FROM_U8(0x24, 0, 0, 0);
959 pNode->node.au32F02_param[3] = RT_MAKE_U32_FROM_U8(0x24, 0, 0, 0);
960 goto adc_init;
961 break;
962 case 0x9:
963 pNode->node.name = "ADC-2";
964 pNode->node.au32F02_param[0] = RT_MAKE_U32_FROM_U8(0x22, 0, 0, 0);
965 pNode->node.au32F02_param[1] = RT_MAKE_U32_FROM_U8(0x22, 0, 0, 0);
966 pNode->node.au32F02_param[2] = RT_MAKE_U32_FROM_U8(0x22, 0, 0, 0);
967 pNode->node.au32F02_param[3] = RT_MAKE_U32_FROM_U8(0x22, 0, 0, 0);
968 adc_init:
969 pNode->node.au32F00_param[0xB] = 0x1;
970 pNode->node.au32F00_param[0x9] = 0x10011b;
971 pNode->node.au32F00_param[0xD] = 0x80032e10;
972 pNode->node.au32F00_param[0xE] = 0x1;
973 pNode->node.au32F00_param[0xA] = pState->pNodes[1].node.au32F00_param[0xA];
974 pNode->adc.u32A_param = CODEC_MAKE_A(0, 1, CODEC_A_MULT_1X, CODEC_A_DIV_1X, CODEC_A_16_BIT, 1);//(1<<14)|(0x1<<4) | 0x1;
975 break;
976 /* Ports */
977 case 0x14:
978 pNode->node.name = "PORT-D";
979 pNode->port.u32F1c_param = 0x12b4050;
980 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);
981 goto port_init;
982 break;
983 case 0x15:
984 pNode->node.name = "PORT-A";
985 pNode->port.u32F1c_param = 0x18b3020;
986 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);
987 goto port_init;
988 break;
989 case 0x16:
990 pNode->node.name = "PORT-G";
991 pNode->port.u32F1c_param = 0x400000f0;
992 pNode->node.au32F00_param[0xC] = RT_BIT(4)|RT_BIT(3)|RT_BIT(2);
993 goto port_init;
994 break;
995 case 0x17:
996 pNode->node.name = "PORT-H";
997 pNode->port.u32F1c_param = 0x400000f0;
998 pNode->node.au32F00_param[0xC] = RT_BIT(4)|RT_BIT(3)|RT_BIT(2);
999 goto port_init;
1000 break;
1001 case 0x18:
1002 pNode->node.name = "PORT-B";
1003 pNode->port.u32F1c_param = 0x90100140;
1004 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);
1005 goto port_init;
1006 break;
1007 case 0x19:
1008 pNode->node.name = "PORT-F";
1009 pNode->port.u32F1c_param = 0x90a00110;
1010 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);
1011 goto port_init;
1012 break;
1013 case 0x1A:
1014 pNode->node.name = "PORT-C";
1015 pNode->port.u32F1c_param = 0x90100141;
1016 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);
1017 goto port_init;
1018 break;
1019 case 0x1B:
1020 pNode->node.name = "PORT-E";
1021 pNode->port.u32F1c_param = 0x400000f0;
1022 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);
1023 port_init:
1024 pNode->node.au32F00_param[0x9] = 0x40018f;
1025 pNode->node.au32F00_param[0xD] = 0x270300;
1026 pNode->node.au32F00_param[0xE] = 0x5;
1027 /* N = 0~3 */
1028 pNode->node.au32F02_param[0] = RT_MAKE_U32_FROM_U8(0xC, 0xD, 0xE, 0xF);
1029 pNode->node.au32F02_param[1] = RT_MAKE_U32_FROM_U8(0xC, 0xD, 0xE, 0xF);
1030 pNode->node.au32F02_param[2] = RT_MAKE_U32_FROM_U8(0xC, 0xD, 0xE, 0xF);
1031 pNode->node.au32F02_param[3] = RT_MAKE_U32_FROM_U8(0xC, 0xD, 0xE, 0xF);
1032 /* N = 4~7 */
1033 pNode->node.au32F02_param[4] = RT_MAKE_U32_FROM_U8(0x26, 0, 0, 0);
1034 pNode->node.au32F02_param[5] = RT_MAKE_U32_FROM_U8(0x26, 0, 0, 0);
1035 pNode->node.au32F02_param[6] = RT_MAKE_U32_FROM_U8(0x26, 0, 0, 0);
1036 pNode->node.au32F02_param[7] = RT_MAKE_U32_FROM_U8(0x26, 0, 0, 0);
1037 break;
1038 /* ADCVols */
1039 case 0x26:
1040 pNode->node.name = "AdcVol-0";
1041 pNode->node.au32F00_param[0x9] = 0x20010f;
1042 pNode->node.au32F00_param[0xD] = 0x80000000;
1043 pNode->node.au32F00_param[0xE] = 0x2;
1044 pNode->node.au32F00_param[0x12] = 0x34040;
1045 pNode->node.au32F02_param[0] = RT_MAKE_U32_FROM_U8(0x25, 0xB, 0, 0);
1046 pNode->node.au32F02_param[1] = RT_MAKE_U32_FROM_U8(0x25, 0xB, 0, 0);
1047 pNode->node.au32F02_param[2] = RT_MAKE_U32_FROM_U8(0x25, 0xB, 0, 0);
1048 pNode->node.au32F02_param[3] = RT_MAKE_U32_FROM_U8(0x25, 0xB, 0, 0);
1049 break;
1050 case 0xF:
1051 pNode->node.name = "AdcVol-1";
1052 pNode->node.au32F00_param[0x9] = 0x20010f;
1053 pNode->node.au32F00_param[0xE] = 0x2;
1054 pNode->node.au32F00_param[0x12] = 0x34040;
1055 pNode->node.au32F02_param[0] = RT_MAKE_U32_FROM_U8(0x5, 0xB, 0, 0);
1056 pNode->node.au32F02_param[1] = RT_MAKE_U32_FROM_U8(0x5, 0xB, 0, 0);
1057 pNode->node.au32F02_param[2] = RT_MAKE_U32_FROM_U8(0x5, 0xB, 0, 0);
1058 pNode->node.au32F02_param[3] = RT_MAKE_U32_FROM_U8(0x5, 0xB, 0, 0);
1059 break;
1060 case 0xE:
1061 pNode->node.name = "AdcVol-2";
1062 pNode->node.au32F00_param[0x9] = 0x20010f;
1063 pNode->node.au32F00_param[0xE] = 0x2;
1064 pNode->node.au32F00_param[0xD] = 0x80000000;
1065 pNode->node.au32F00_param[0x12] = 0x34040;
1066 pNode->node.au32F02_param[0] = RT_MAKE_U32_FROM_U8(0x4, 0xB, 0, 0);
1067 pNode->node.au32F02_param[1] = RT_MAKE_U32_FROM_U8(0x4, 0xB, 0, 0);
1068 pNode->node.au32F02_param[2] = RT_MAKE_U32_FROM_U8(0x4, 0xB, 0, 0);
1069 pNode->node.au32F02_param[3] = RT_MAKE_U32_FROM_U8(0x4, 0xB, 0, 0);
1070 break;
1071 case 0xD:
1072 pNode->node.name = "AdcVol-3";
1073 pNode->node.au32F00_param[0x9] = 0x20010f;
1074 pNode->node.au32F00_param[0xE] = 0x2;
1075 pNode->node.au32F00_param[0xD] = 0x80000000;
1076 pNode->node.au32F00_param[0x12] = 0x34040;
1077 pNode->node.au32F02_param[0] = RT_MAKE_U32_FROM_U8(0x3, 0xB, 0, 0);
1078 pNode->node.au32F02_param[1] = RT_MAKE_U32_FROM_U8(0x3, 0xB, 0, 0);
1079 pNode->node.au32F02_param[2] = RT_MAKE_U32_FROM_U8(0x3, 0xB, 0, 0);
1080 pNode->node.au32F02_param[3] = RT_MAKE_U32_FROM_U8(0x3, 0xB, 0, 0);
1081 break;
1082 case 0xC:
1083 pNode->node.name = "AdcVol-4";
1084 pNode->node.au32F00_param[0x9] = 0x20010f;
1085 pNode->node.au32F00_param[0xE] = 0x2;
1086 pNode->node.au32F00_param[0xD] = 0x80000000;
1087 pNode->node.au32F00_param[0x12] = 0x34040;
1088 pNode->node.au32F02_param[0] = RT_MAKE_U32_FROM_U8(0x2, 0xB, 0, 0);
1089 pNode->node.au32F02_param[1] = RT_MAKE_U32_FROM_U8(0x2, 0xB, 0, 0);
1090 pNode->node.au32F02_param[2] = RT_MAKE_U32_FROM_U8(0x2, 0xB, 0, 0);
1091 pNode->node.au32F02_param[3] = RT_MAKE_U32_FROM_U8(0x2, 0xB, 0, 0);
1092 break;
1093 case 0xB:
1094 pNode->node.name = "AdcVol-5";
1095 pNode->node.au32F00_param[0x9] = 0x20010b;
1096 pNode->node.au32F00_param[0xD] = 0x80051f17;
1097 /* N = 0~3 */
1098 pNode->node.au32F02_param[0] = RT_MAKE_U32_FROM_U8(0x18, 0x19, 0x1A, 0x1B);
1099 pNode->node.au32F02_param[1] = RT_MAKE_U32_FROM_U8(0x18, 0x19, 0x1A, 0x1B);
1100 pNode->node.au32F02_param[2] = RT_MAKE_U32_FROM_U8(0x18, 0x19, 0x1A, 0x1B);
1101 pNode->node.au32F02_param[3] = RT_MAKE_U32_FROM_U8(0x18, 0x19, 0x1A, 0x1B);
1102 /* N = 4~7 */
1103 pNode->node.au32F02_param[4] = RT_MAKE_U32_FROM_U8(0x1C, 0x1D, 0x14, 0x15);
1104 pNode->node.au32F02_param[5] = RT_MAKE_U32_FROM_U8(0x1C, 0x1D, 0x14, 0x15);
1105 pNode->node.au32F02_param[6] = RT_MAKE_U32_FROM_U8(0x1C, 0x1D, 0x14, 0x15);
1106 pNode->node.au32F02_param[7] = RT_MAKE_U32_FROM_U8(0x1C, 0x1D, 0x14, 0x15);
1107 /* N = 8~11 */
1108 pNode->node.au32F02_param[8] = RT_MAKE_U32_FROM_U8(0x16, 0x17, 0, 0);
1109 pNode->node.au32F02_param[9] = RT_MAKE_U32_FROM_U8(0x16, 0x17, 0, 0);
1110 pNode->node.au32F02_param[10] = RT_MAKE_U32_FROM_U8(0x16, 0x17, 0, 0);
1111 pNode->node.au32F02_param[11] = RT_MAKE_U32_FROM_U8(0x16, 0x17, 0, 0);
1112 break;
1113 /* AdcMuxs */
1114 case 0x22:
1115 pNode->node.name = "AdcMux-0";
1116 pNode->node.au32F00_param[0x9] = 0x20010b;
1117 pNode->node.au32F00_param[0xD] = 0x80000000;
1118 pNode->node.au32F00_param[0xE] = 0xb;
1119 goto adc_mux_init;
1120 case 0x23:
1121 pNode->node.name = "AdcMux-1";
1122 pNode->node.au32F00_param[0x9] = 0x20010b;
1123 pNode->node.au32F00_param[0xD] = 0x80000000;
1124 pNode->node.au32F00_param[0xE] = 0xb;
1125 adc_mux_init:
1126 /* N = 0~3 */
1127 pNode->node.au32F02_param[0] = RT_MAKE_U32_FROM_U8(0x18, 0x19, 0x1A, 0x1B);
1128 pNode->node.au32F02_param[1] = RT_MAKE_U32_FROM_U8(0x18, 0x19, 0x1A, 0x1B);
1129 pNode->node.au32F02_param[2] = RT_MAKE_U32_FROM_U8(0x18, 0x19, 0x1A, 0x1B);
1130 pNode->node.au32F02_param[3] = RT_MAKE_U32_FROM_U8(0x18, 0x19, 0x1A, 0x1B);
1131 /* N = 4~7 */
1132 pNode->node.au32F02_param[4] = RT_MAKE_U32_FROM_U8(0x1C, 0x1D, 0x14, 0x15);
1133 pNode->node.au32F02_param[5] = RT_MAKE_U32_FROM_U8(0x1C, 0x1D, 0x14, 0x15);
1134 pNode->node.au32F02_param[6] = RT_MAKE_U32_FROM_U8(0x1C, 0x1D, 0x14, 0x15);
1135 pNode->node.au32F02_param[7] = RT_MAKE_U32_FROM_U8(0x1C, 0x1D, 0x14, 0x15);
1136 /* N = 8~11 */
1137 pNode->node.au32F02_param[8] = RT_MAKE_U32_FROM_U8(0x16, 0x17, 0xB, 0);
1138 pNode->node.au32F02_param[9] = RT_MAKE_U32_FROM_U8(0x16, 0x17, 0xB, 0);
1139 pNode->node.au32F02_param[10] = RT_MAKE_U32_FROM_U8(0x16, 0x17, 0xB, 0);
1140 pNode->node.au32F02_param[11] = RT_MAKE_U32_FROM_U8(0x16, 0x17, 0xB, 0);
1141 break;
1142 case 0x24:
1143 pNode->node.name = "AdcMux-2";
1144 pNode->node.au32F00_param[0x9] = 0x20010b;
1145 pNode->node.au32F00_param[0xD] = 0x80000000;
1146 pNode->node.au32F00_param[0xE] = 0xb;
1147 /* N = 0~3 */
1148 pNode->node.au32F02_param[0] = RT_MAKE_U32_FROM_U8(0x18, 0x19, 0x1A, 0x1B);
1149 pNode->node.au32F02_param[1] = RT_MAKE_U32_FROM_U8(0x18, 0x19, 0x1A, 0x1B);
1150 pNode->node.au32F02_param[2] = RT_MAKE_U32_FROM_U8(0x18, 0x19, 0x1A, 0x1B);
1151 pNode->node.au32F02_param[3] = RT_MAKE_U32_FROM_U8(0x18, 0x19, 0x1A, 0x1B);
1152 /* N = 4~7 */
1153 pNode->node.au32F02_param[4] = RT_MAKE_U32_FROM_U8(0x1C, 0x1D, 0x14, 0x15);
1154 pNode->node.au32F02_param[5] = RT_MAKE_U32_FROM_U8(0x1C, 0x1D, 0x14, 0x15);
1155 pNode->node.au32F02_param[6] = RT_MAKE_U32_FROM_U8(0x1C, 0x1D, 0x14, 0x15);
1156 pNode->node.au32F02_param[7] = RT_MAKE_U32_FROM_U8(0x1C, 0x1D, 0x14, 0x15);
1157 /* N = 8~11 */
1158 pNode->node.au32F02_param[8] = RT_MAKE_U32_FROM_U8(0x16, 0x17, 0xB, 0x12);
1159 pNode->node.au32F02_param[9] = RT_MAKE_U32_FROM_U8(0x16, 0x17, 0xB, 0x12);
1160 pNode->node.au32F02_param[10] = RT_MAKE_U32_FROM_U8(0x16, 0x17, 0xB, 0x12);
1161 pNode->node.au32F02_param[11] = RT_MAKE_U32_FROM_U8(0x16, 0x17, 0xB, 0x12);
1162 break;
1163 /* PCBEEP */
1164 case 0x1D:
1165 pNode->node.name = "PCBEEP";
1166 pNode->node.au32F00_param[0x9] = 0x400000;
1167 pNode->port.u32F1c_param = 0x400000f0;
1168 pNode->node.au32F00_param[0xC] = RT_BIT(5);
1169 break;
1170 /* CD */
1171 case 0x1C:
1172 pNode->node.name = "CD";
1173 pNode->node.au32F00_param[0x9] = 0x400001;
1174 pNode->port.u32F1c_param = 0x400000f0;
1175 pNode->node.au32F00_param[0xC] = RT_BIT(5);
1176 break;
1177 case 0x21:
1178 pNode->node.name = "VolumeKnob";
1179 pNode->node.au32F00_param[0x9] = (0x6 << 20)|RT_BIT(7);
1180 break;
1181 default:
1182 AssertMsgFailed(("Unsupported Node"));
1183 }
1184 return VINF_SUCCESS;
1185}
1186
1187
1188/* generic */
1189
1190#define DECLISNODEOFTYPE(type) \
1191 static inline int codecIs##type##Node(struct CODECState *pState, uint8_t cNode) \
1192 { \
1193 Assert(pState->au8##type##s); \
1194 for(int i = 0; pState->au8##type##s[i] != 0; ++i) \
1195 if (pState->au8##type##s[i] == cNode) \
1196 return 1; \
1197 return 0; \
1198 }
1199/* codecIsPortNode */
1200DECLISNODEOFTYPE(Port)
1201/* codecIsDacNode */
1202DECLISNODEOFTYPE(Dac)
1203/* codecIsAdcVolNode */
1204DECLISNODEOFTYPE(AdcVol)
1205/* codecIsAdcNode */
1206DECLISNODEOFTYPE(Adc)
1207/* codecIsAdcMuxNode */
1208DECLISNODEOFTYPE(AdcMux)
1209/* codecIsPcbeepNode */
1210DECLISNODEOFTYPE(Pcbeep)
1211/* codecIsSpdifOutNode */
1212DECLISNODEOFTYPE(SpdifOut)
1213/* codecIsSpdifInNode */
1214DECLISNODEOFTYPE(SpdifIn)
1215/* codecIsDigInPinNode */
1216DECLISNODEOFTYPE(DigInPin)
1217/* codecIsDigOutPinNode */
1218DECLISNODEOFTYPE(DigOutPin)
1219/* codecIsCdNode */
1220DECLISNODEOFTYPE(Cd)
1221/* codecIsVolKnobNode */
1222DECLISNODEOFTYPE(VolKnob)
1223/* codecIsReservedNode */
1224DECLISNODEOFTYPE(Reserved)
1225
1226static int codecToAudVolume(AMPLIFIER *pAmp, audmixerctl_t mt);
1227
1228static inline void codecSetRegister(uint32_t *pu32Reg, uint32_t u32Cmd, uint8_t u8Offset, uint32_t mask)
1229{
1230 Assert((pu32Reg && u8Offset < 32));
1231 *pu32Reg &= ~(mask << u8Offset);
1232 *pu32Reg |= (u32Cmd & mask) << u8Offset;
1233}
1234static inline void codecSetRegisterU8(uint32_t *pu32Reg, uint32_t u32Cmd, uint8_t u8Offset)
1235{
1236 codecSetRegister(pu32Reg, u32Cmd, u8Offset, CODEC_VERB_8BIT_DATA);
1237}
1238
1239static inline void codecSetRegisterU16(uint32_t *pu32Reg, uint32_t u32Cmd, uint8_t u8Offset)
1240{
1241 codecSetRegister(pu32Reg, u32Cmd, u8Offset, CODEC_VERB_16BIT_DATA);
1242}
1243
1244
1245static int codecUnimplemented(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1246{
1247 Log(("codecUnimplemented: cmd(raw:%x: cad:%x, d:%c, nid:%x, verb:%x)\n", cmd,
1248 CODEC_CAD(cmd), CODEC_DIRECT(cmd) ? 'N' : 'Y', CODEC_NID(cmd), CODEC_VERBDATA(cmd)));
1249 *pResp = 0;
1250 return VINF_SUCCESS;
1251}
1252
1253static int codecBreak(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1254{
1255 int rc;
1256 rc = codecUnimplemented(pState, cmd, pResp);
1257 *pResp |= CODEC_RESPONSE_UNSOLICITED;
1258 return rc;
1259}
1260/* B-- */
1261static int codecGetAmplifier(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1262{
1263 Assert((CODEC_CAD(cmd) == pState->id));
1264 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1265 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1266 {
1267 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1268 return VINF_SUCCESS;
1269 }
1270 *pResp = 0;
1271 /* HDA spec 7.3.3.7 Note A */
1272 /* @todo: if index out of range response should be 0 */
1273 uint8_t u8Index = CODEC_GET_AMP_DIRECTION(cmd) == AMPLIFIER_OUT? 0 : CODEC_GET_AMP_INDEX(cmd);
1274
1275 PCODECNODE pNode = &pState->pNodes[CODEC_NID(cmd)];
1276 if (codecIsDacNode(pState, CODEC_NID(cmd)))
1277 *pResp = AMPLIFIER_REGISTER(pNode->dac.B_params,
1278 CODEC_GET_AMP_DIRECTION(cmd),
1279 CODEC_GET_AMP_SIDE(cmd),
1280 u8Index);
1281 else if (codecIsAdcVolNode(pState, CODEC_NID(cmd)))
1282 *pResp = AMPLIFIER_REGISTER(pNode->adcvol.B_params,
1283 CODEC_GET_AMP_DIRECTION(cmd),
1284 CODEC_GET_AMP_SIDE(cmd),
1285 u8Index);
1286 else if (codecIsAdcMuxNode(pState, CODEC_NID(cmd)))
1287 *pResp = AMPLIFIER_REGISTER(pNode->adcmux.B_params,
1288 CODEC_GET_AMP_DIRECTION(cmd),
1289 CODEC_GET_AMP_SIDE(cmd),
1290 u8Index);
1291 else if (codecIsPcbeepNode(pState, CODEC_NID(cmd)))
1292 *pResp = AMPLIFIER_REGISTER(pNode->pcbeep.B_params,
1293 CODEC_GET_AMP_DIRECTION(cmd),
1294 CODEC_GET_AMP_SIDE(cmd),
1295 u8Index);
1296 else if (codecIsPortNode(pState, CODEC_NID(cmd)))
1297 *pResp = AMPLIFIER_REGISTER(pNode->port.B_params,
1298 CODEC_GET_AMP_DIRECTION(cmd),
1299 CODEC_GET_AMP_SIDE(cmd),
1300 u8Index);
1301 else if (codecIsAdcNode(pState, CODEC_NID(cmd)))
1302 *pResp = AMPLIFIER_REGISTER(pNode->adc.B_params,
1303 CODEC_GET_AMP_DIRECTION(cmd),
1304 CODEC_GET_AMP_SIDE(cmd),
1305 u8Index);
1306 else{
1307 AssertMsgReturn(0, ("access to fields of %x need to be implemented\n", CODEC_NID(cmd)), VINF_SUCCESS);
1308 }
1309 return VINF_SUCCESS;
1310}
1311/* 3-- */
1312static int codecSetAmplifier(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1313{
1314 AMPLIFIER *pAmplifier = NULL;
1315 bool fIsLeft = false;
1316 bool fIsRight = false;
1317 bool fIsOut = false;
1318 bool fIsIn = false;
1319 uint8_t u8Index = 0;
1320 Assert((CODEC_CAD(cmd) == pState->id));
1321 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1322 {
1323 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1324 return VINF_SUCCESS;
1325 }
1326 *pResp = 0;
1327 PCODECNODE pNode = &pState->pNodes[CODEC_NID(cmd)];
1328 if (codecIsDacNode(pState, CODEC_NID(cmd)))
1329 pAmplifier = &pNode->dac.B_params;
1330 else if (codecIsAdcVolNode(pState, CODEC_NID(cmd)))
1331 pAmplifier = &pNode->adcvol.B_params;
1332 else if (codecIsAdcMuxNode(pState, CODEC_NID(cmd)))
1333 pAmplifier = &pNode->adcmux.B_params;
1334 else if (codecIsPcbeepNode(pState, CODEC_NID(cmd)))
1335 pAmplifier = &pNode->pcbeep.B_params;
1336 else if (codecIsPortNode(pState, CODEC_NID(cmd)))
1337 pAmplifier = &pNode->port.B_params;
1338 else if (codecIsAdcNode(pState, CODEC_NID(cmd)))
1339 pAmplifier = &pNode->adc.B_params;
1340 Assert(pAmplifier);
1341 if (pAmplifier)
1342 {
1343 fIsOut = CODEC_SET_AMP_IS_OUT_DIRECTION(cmd);
1344 fIsIn = CODEC_SET_AMP_IS_IN_DIRECTION(cmd);
1345 fIsRight = CODEC_SET_AMP_IS_RIGHT_SIDE(cmd);
1346 fIsLeft = CODEC_SET_AMP_IS_LEFT_SIDE(cmd);
1347 u8Index = CODEC_SET_AMP_INDEX(cmd);
1348 if ( (!fIsLeft && !fIsRight)
1349 || (!fIsOut && !fIsIn))
1350 return VINF_SUCCESS;
1351 if (fIsIn)
1352 {
1353 if (fIsLeft)
1354 codecSetRegisterU8(&AMPLIFIER_REGISTER(*pAmplifier, AMPLIFIER_IN, AMPLIFIER_LEFT, u8Index), cmd, 0);
1355 if (fIsRight)
1356 codecSetRegisterU8(&AMPLIFIER_REGISTER(*pAmplifier, AMPLIFIER_IN, AMPLIFIER_RIGHT, u8Index), cmd, 0);
1357 }
1358 if (fIsOut)
1359 {
1360 if (fIsLeft)
1361 codecSetRegisterU8(&AMPLIFIER_REGISTER(*pAmplifier, AMPLIFIER_OUT, AMPLIFIER_LEFT, u8Index), cmd, 0);
1362 if (fIsRight)
1363 codecSetRegisterU8(&AMPLIFIER_REGISTER(*pAmplifier, AMPLIFIER_OUT, AMPLIFIER_RIGHT, u8Index), cmd, 0);
1364 }
1365 if (CODEC_NID(cmd) == pState->u8DacLineOut)
1366 codecToAudVolume(pAmplifier, AUD_MIXER_VOLUME);
1367 if (CODEC_NID(cmd) == pState->u8AdcVolsLineIn) /* Microphone */
1368 codecToAudVolume(pAmplifier, AUD_MIXER_LINE_IN);
1369 }
1370 return VINF_SUCCESS;
1371}
1372
1373static int codecGetParameter(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1374{
1375 Assert((CODEC_CAD(cmd) == pState->id));
1376 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1377 {
1378 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1379 return VINF_SUCCESS;
1380 }
1381 Assert(((cmd & CODEC_VERB_8BIT_DATA) < CODECNODE_F0_PARAM_LENGTH));
1382 if ((cmd & CODEC_VERB_8BIT_DATA) >= CODECNODE_F0_PARAM_LENGTH)
1383 {
1384 Log(("HDAcodec: invalid F00 parameter %d\n", (cmd & CODEC_VERB_8BIT_DATA)));
1385 return VINF_SUCCESS;
1386 }
1387 *pResp = 0;
1388 *pResp = pState->pNodes[CODEC_NID(cmd)].node.au32F00_param[cmd & CODEC_VERB_8BIT_DATA];
1389 return VINF_SUCCESS;
1390}
1391
1392/* F01 */
1393static int codecGetConSelectCtrl(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1394{
1395 Assert((CODEC_CAD(cmd) == pState->id));
1396 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1397 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1398 {
1399 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1400 return VINF_SUCCESS;
1401 }
1402 *pResp = 0;
1403 if (codecIsAdcMuxNode(pState, CODEC_NID(cmd)))
1404 *pResp = pState->pNodes[CODEC_NID(cmd)].adcmux.u32F01_param;
1405 else if (codecIsDigOutPinNode(pState, CODEC_NID(cmd)))
1406 *pResp = pState->pNodes[CODEC_NID(cmd)].digout.u32F01_param;
1407 else if (codecIsPortNode(pState, CODEC_NID(cmd)))
1408 *pResp = pState->pNodes[CODEC_NID(cmd)].port.u32F01_param;
1409 else if (codecIsAdcNode(pState, CODEC_NID(cmd)))
1410 *pResp = pState->pNodes[CODEC_NID(cmd)].adc.u32F01_param;
1411 else if (codecIsAdcVolNode(pState, CODEC_NID(cmd)))
1412 *pResp = pState->pNodes[CODEC_NID(cmd)].adcvol.u32F01_param;
1413 return VINF_SUCCESS;
1414}
1415
1416/* 701 */
1417static int codecSetConSelectCtrl(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1418{
1419 uint32_t *pu32Reg = NULL;
1420 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1421 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1422 {
1423 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1424 return VINF_SUCCESS;
1425 }
1426 *pResp = 0;
1427 if (codecIsAdcMuxNode(pState, CODEC_NID(cmd)))
1428 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].adcmux.u32F01_param;
1429 else if (codecIsDigOutPinNode(pState, CODEC_NID(cmd)))
1430 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].digout.u32F01_param;
1431 else if (codecIsPortNode(pState, CODEC_NID(cmd)))
1432 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].port.u32F01_param;
1433 else if (codecIsAdcNode(pState, CODEC_NID(cmd)))
1434 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].adc.u32F01_param;
1435 else if (codecIsAdcVolNode(pState, CODEC_NID(cmd)))
1436 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].adcvol.u32F01_param;
1437 Assert((pu32Reg));
1438 if (pu32Reg)
1439 codecSetRegisterU8(pu32Reg, cmd, 0);
1440 return VINF_SUCCESS;
1441}
1442
1443/* F07 */
1444static int codecGetPinCtrl(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1445{
1446 Assert((CODEC_CAD(cmd) == pState->id));
1447 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1448 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1449 {
1450 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1451 return VINF_SUCCESS;
1452 }
1453 *pResp = 0;
1454 if (codecIsPortNode(pState, CODEC_NID(cmd)))
1455 *pResp = pState->pNodes[CODEC_NID(cmd)].port.u32F07_param;
1456 else if (codecIsDigOutPinNode(pState, CODEC_NID(cmd)))
1457 *pResp = pState->pNodes[CODEC_NID(cmd)].digout.u32F07_param;
1458 else if (codecIsDigInPinNode(pState, CODEC_NID(cmd)))
1459 *pResp = pState->pNodes[CODEC_NID(cmd)].digin.u32F07_param;
1460 else if (codecIsCdNode(pState, CODEC_NID(cmd)))
1461 *pResp = pState->pNodes[CODEC_NID(cmd)].cdnode.u32F07_param;
1462 else if (codecIsPcbeepNode(pState, CODEC_NID(cmd)))
1463 *pResp = pState->pNodes[CODEC_NID(cmd)].pcbeep.u32F07_param;
1464 else if (codecIsReservedNode(pState, CODEC_NID(cmd)))
1465 *pResp = pState->pNodes[CODEC_NID(cmd)].reserved.u32F07_param;
1466 else
1467 AssertMsgFailed(("Unsupported"));
1468 return VINF_SUCCESS;
1469}
1470
1471/* 707 */
1472static int codecSetPinCtrl(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1473{
1474 Assert((CODEC_CAD(cmd) == pState->id));
1475 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1476 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1477 {
1478 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1479 return VINF_SUCCESS;
1480 }
1481 *pResp = 0;
1482 uint32_t *pu32Reg = NULL;
1483 if (codecIsPortNode(pState, CODEC_NID(cmd)))
1484 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].port.u32F07_param;
1485 else if (codecIsDigInPinNode(pState, CODEC_NID(cmd)))
1486 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].digin.u32F07_param;
1487 else if (codecIsDigOutPinNode(pState, CODEC_NID(cmd)))
1488 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].digout.u32F07_param;
1489 else if (codecIsCdNode(pState, CODEC_NID(cmd)))
1490 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].cdnode.u32F07_param;
1491 else if (codecIsPcbeepNode(pState, CODEC_NID(cmd)))
1492 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].pcbeep.u32F07_param;
1493 else if ( codecIsReservedNode(pState, CODEC_NID(cmd))
1494 && CODEC_NID(cmd) == 0x1b
1495 && pState->enmCodec == STAC9220_CODEC)
1496 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].reserved.u32F07_param;
1497 Assert((pu32Reg));
1498 if (pu32Reg)
1499 codecSetRegisterU8(pu32Reg, cmd, 0);
1500 return VINF_SUCCESS;
1501}
1502
1503/* F08 */
1504static int codecGetUnsolicitedEnabled(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1505{
1506 Assert((CODEC_CAD(cmd) == pState->id));
1507 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1508 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1509 {
1510 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1511 return VINF_SUCCESS;
1512 }
1513 *pResp = 0;
1514 if (codecIsPortNode(pState, CODEC_NID(cmd)))
1515 *pResp = pState->pNodes[CODEC_NID(cmd)].port.u32F08_param;
1516 else if (codecIsDigInPinNode(pState, CODEC_NID(cmd)))
1517 *pResp = pState->pNodes[CODEC_NID(cmd)].digin.u32F08_param;
1518 else if ((cmd) == 1 /* AFG */)
1519 *pResp = pState->pNodes[CODEC_NID(cmd)].afg.u32F08_param;
1520 else if (codecIsVolKnobNode(pState, CODEC_NID(cmd)))
1521 *pResp = pState->pNodes[CODEC_NID(cmd)].volumeKnob.u32F08_param;
1522 else if (codecIsDigOutPinNode(pState, CODEC_NID(cmd)))
1523 *pResp = pState->pNodes[CODEC_NID(cmd)].digout.u32F08_param;
1524 else if (codecIsDigInPinNode(pState, CODEC_NID(cmd)))
1525 *pResp = pState->pNodes[CODEC_NID(cmd)].digin.u32F08_param;
1526 else
1527 AssertMsgFailed(("unsupported operation %x on node: %x\n", CODEC_VERB_CMD8(cmd), CODEC_NID(cmd)));
1528 return VINF_SUCCESS;
1529}
1530
1531/* 708 */
1532static int codecSetUnsolicitedEnabled(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1533{
1534 Assert((CODEC_CAD(cmd) == pState->id));
1535 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1536 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1537 {
1538 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1539 return VINF_SUCCESS;
1540 }
1541 *pResp = 0;
1542 uint32_t *pu32Reg = NULL;
1543 if (codecIsPortNode(pState, CODEC_NID(cmd)))
1544 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].port.u32F08_param;
1545 else if (codecIsDigInPinNode(pState, CODEC_NID(cmd)))
1546 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].digin.u32F08_param;
1547 else if (CODEC_NID(cmd) == 1 /* AFG */)
1548 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].afg.u32F08_param;
1549 else if (codecIsVolKnobNode(pState, CODEC_NID(cmd)))
1550 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].volumeKnob.u32F08_param;
1551 else if (codecIsDigInPinNode(pState, CODEC_NID(cmd)))
1552 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].digin.u32F08_param;
1553 else if (codecIsDigOutPinNode(pState, CODEC_NID(cmd)))
1554 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].digout.u32F08_param;
1555 else
1556 AssertMsgFailed(("unsupported operation %x on node: %x\n", CODEC_VERB_CMD8(cmd), CODEC_NID(cmd)));
1557 Assert(pu32Reg);
1558 if(pu32Reg)
1559 codecSetRegisterU8(pu32Reg, cmd, 0);
1560 return VINF_SUCCESS;
1561}
1562
1563/* F09 */
1564static int codecGetPinSense(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1565{
1566 Assert((CODEC_CAD(cmd) == pState->id));
1567 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1568 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1569 {
1570 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1571 return VINF_SUCCESS;
1572 }
1573 *pResp = 0;
1574 if (codecIsPortNode(pState, CODEC_NID(cmd)))
1575 *pResp = pState->pNodes[CODEC_NID(cmd)].port.u32F09_param;
1576 else if (codecIsDigInPinNode(pState, CODEC_NID(cmd)))
1577 *pResp = pState->pNodes[CODEC_NID(cmd)].digin.u32F09_param;
1578 else
1579 AssertMsgFailed(("unsupported operation %x on node: %x\n", CODEC_VERB_CMD8(cmd), CODEC_NID(cmd)));
1580 return VINF_SUCCESS;
1581}
1582
1583/* 709 */
1584static int codecSetPinSense(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1585{
1586 Assert((CODEC_CAD(cmd) == pState->id));
1587 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1588 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1589 {
1590 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1591 return VINF_SUCCESS;
1592 }
1593 *pResp = 0;
1594 uint32_t *pu32Reg = NULL;
1595 if (codecIsPortNode(pState, CODEC_NID(cmd)))
1596 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].port.u32F09_param;
1597 else if (codecIsDigInPinNode(pState, CODEC_NID(cmd)))
1598 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].digin.u32F09_param;
1599 Assert(pu32Reg);
1600 if(pu32Reg)
1601 codecSetRegisterU8(pu32Reg, cmd, 0);
1602 return VINF_SUCCESS;
1603}
1604
1605static int codecGetConnectionListEntry(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1606{
1607 Assert((CODEC_CAD(cmd) == pState->id));
1608 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1609 *pResp = 0;
1610 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1611 {
1612 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1613 return VINF_SUCCESS;
1614 }
1615 Assert((cmd & CODEC_VERB_8BIT_DATA) < CODECNODE_F02_PARAM_LENGTH);
1616 if ((cmd & CODEC_VERB_8BIT_DATA) >= CODECNODE_F02_PARAM_LENGTH)
1617 {
1618 Log(("HDAcodec: access to invalid F02 index %d\n", (cmd & CODEC_VERB_8BIT_DATA)));
1619 return VINF_SUCCESS;
1620 }
1621 *pResp = pState->pNodes[CODEC_NID(cmd)].node.au32F02_param[cmd & CODEC_VERB_8BIT_DATA];
1622 return VINF_SUCCESS;
1623}
1624/* F03 */
1625static int codecGetProcessingState(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1626{
1627 Assert((CODEC_CAD(cmd) == pState->id));
1628 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1629 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1630 {
1631 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1632 return VINF_SUCCESS;
1633 }
1634 *pResp = 0;
1635 if (codecIsAdcNode(pState, CODEC_NID(cmd)))
1636 *pResp = pState->pNodes[CODEC_NID(cmd)].adc.u32F03_param;
1637 return VINF_SUCCESS;
1638}
1639
1640/* 703 */
1641static int codecSetProcessingState(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1642{
1643 Assert((CODEC_CAD(cmd) == pState->id));
1644 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1645 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1646 {
1647 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1648 return VINF_SUCCESS;
1649 }
1650 *pResp = 0;
1651 if (codecIsAdcNode(pState, CODEC_NID(cmd)))
1652 {
1653 codecSetRegisterU8(&pState->pNodes[CODEC_NID(cmd)].adc.u32F03_param, cmd, 0);
1654 }
1655 return VINF_SUCCESS;
1656}
1657
1658/* F0D */
1659static int codecGetDigitalConverter(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1660{
1661 Assert((CODEC_CAD(cmd) == pState->id));
1662 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1663 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1664 {
1665 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1666 return VINF_SUCCESS;
1667 }
1668 *pResp = 0;
1669 if (codecIsSpdifOutNode(pState, CODEC_NID(cmd)))
1670 *pResp = pState->pNodes[CODEC_NID(cmd)].spdifout.u32F0d_param;
1671 else if (codecIsSpdifInNode(pState, CODEC_NID(cmd)))
1672 *pResp = pState->pNodes[CODEC_NID(cmd)].spdifin.u32F0d_param;
1673 return VINF_SUCCESS;
1674}
1675
1676static int codecSetDigitalConverter(struct CODECState *pState, uint32_t cmd, uint8_t u8Offset, uint64_t *pResp)
1677{
1678 Assert((CODEC_CAD(cmd) == pState->id));
1679 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1680 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1681 {
1682 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1683 return VINF_SUCCESS;
1684 }
1685 *pResp = 0;
1686 if (codecIsSpdifOutNode(pState, CODEC_NID(cmd)))
1687 codecSetRegisterU8(&pState->pNodes[CODEC_NID(cmd)].spdifout.u32F0d_param, cmd, u8Offset);
1688 else if (codecIsSpdifInNode(pState, CODEC_NID(cmd)))
1689 codecSetRegisterU8(&pState->pNodes[CODEC_NID(cmd)].spdifin.u32F0d_param, cmd, u8Offset);
1690 return VINF_SUCCESS;
1691}
1692
1693/* 70D */
1694static int codecSetDigitalConverter1(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1695{
1696 return codecSetDigitalConverter(pState, cmd, 0, pResp);
1697}
1698
1699/* 70E */
1700static int codecSetDigitalConverter2(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1701{
1702 return codecSetDigitalConverter(pState, cmd, 8, pResp);
1703}
1704
1705/* F20 */
1706static int codecGetSubId(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1707{
1708 Assert((CODEC_CAD(cmd) == pState->id));
1709 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1710 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1711 {
1712 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1713 return VINF_SUCCESS;
1714 }
1715 *pResp = 0;
1716 if (CODEC_NID(cmd) == 1 /* AFG */)
1717 {
1718 *pResp = pState->pNodes[CODEC_NID(cmd)].afg.u32F20_param;
1719 }
1720 return VINF_SUCCESS;
1721}
1722
1723static int codecSetSubIdX(struct CODECState *pState, uint32_t cmd, uint8_t u8Offset)
1724{
1725 Assert((CODEC_CAD(cmd) == pState->id));
1726 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1727 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1728 {
1729 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1730 return VINF_SUCCESS;
1731 }
1732 uint32_t *pu32Reg = NULL;
1733 if (CODEC_NID(cmd) == 0x1 /* AFG */)
1734 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].afg.u32F20_param;
1735 Assert((pu32Reg));
1736 if (pu32Reg)
1737 codecSetRegisterU8(pu32Reg, cmd, u8Offset);
1738 return VINF_SUCCESS;
1739}
1740/* 720 */
1741static int codecSetSubId0 (struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1742{
1743 *pResp = 0;
1744 return codecSetSubIdX(pState, cmd, 0);
1745}
1746
1747/* 721 */
1748static int codecSetSubId1 (struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1749{
1750 *pResp = 0;
1751 return codecSetSubIdX(pState, cmd, 8);
1752}
1753/* 722 */
1754static int codecSetSubId2 (struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1755{
1756 *pResp = 0;
1757 return codecSetSubIdX(pState, cmd, 16);
1758}
1759/* 723 */
1760static int codecSetSubId3 (struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1761{
1762 *pResp = 0;
1763 return codecSetSubIdX(pState, cmd, 24);
1764}
1765
1766static int codecReset(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1767{
1768 Assert((CODEC_CAD(cmd) == pState->id));
1769 Assert(CODEC_NID(cmd) == 1 /* AFG */);
1770 if(CODEC_NID(cmd) == 1 /* AFG */)
1771 {
1772 uint8_t i;
1773 Log(("HDAcodec: enters reset\n"));
1774 Assert(pState->pfnCodecNodeReset);
1775 for (i = 0; i < pState->cTotalNodes; ++i)
1776 {
1777 pState->pfnCodecNodeReset(pState, i, &pState->pNodes[i]);
1778 }
1779 pState->fInReset = false;
1780 Log(("HDAcodec: exits reset\n"));
1781 }
1782 *pResp = 0;
1783 return VINF_SUCCESS;
1784}
1785
1786/* F05 */
1787static int codecGetPowerState(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1788{
1789 Assert((CODEC_CAD(cmd) == pState->id));
1790 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1791 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1792 {
1793 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1794 return VINF_SUCCESS;
1795 }
1796 *pResp = 0;
1797 if (CODEC_NID(cmd) == 1 /* AFG */)
1798 *pResp = pState->pNodes[CODEC_NID(cmd)].afg.u32F05_param;
1799 else if (codecIsDacNode(pState, CODEC_NID(cmd)))
1800 *pResp = pState->pNodes[CODEC_NID(cmd)].dac.u32F05_param;
1801 else if (codecIsDigInPinNode(pState, CODEC_NID(cmd)))
1802 *pResp = pState->pNodes[CODEC_NID(cmd)].digin.u32F05_param;
1803 else if (codecIsAdcNode(pState, CODEC_NID(cmd)))
1804 *pResp = pState->pNodes[CODEC_NID(cmd)].adc.u32F05_param;
1805 else if (codecIsSpdifOutNode(pState, CODEC_NID(cmd)))
1806 *pResp = pState->pNodes[CODEC_NID(cmd)].spdifout.u32F05_param;
1807 else if (codecIsSpdifInNode(pState, CODEC_NID(cmd)))
1808 *pResp = pState->pNodes[CODEC_NID(cmd)].spdifin.u32F05_param;
1809 else if (codecIsReservedNode(pState, CODEC_NID(cmd)))
1810 *pResp = pState->pNodes[CODEC_NID(cmd)].reserved.u32F05_param;
1811 return VINF_SUCCESS;
1812}
1813
1814/* 705 */
1815
1816static inline void codecPropogatePowerState(uint32_t *pu32F05_param)
1817{
1818 Assert(pu32F05_param);
1819 if (!pu32F05_param)
1820 return;
1821 bool fReset = CODEC_F05_IS_RESET(*pu32F05_param);
1822 bool fStopOk = CODEC_F05_IS_STOPOK(*pu32F05_param);
1823 uint8_t u8SetPowerState = CODEC_F05_SET(*pu32F05_param);
1824 *pu32F05_param = CODEC_MAKE_F05(fReset, fStopOk, 0, u8SetPowerState, u8SetPowerState);
1825}
1826
1827static int codecSetPowerState(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1828{
1829 Assert((CODEC_CAD(cmd) == pState->id));
1830 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1831 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1832 {
1833 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1834 return VINF_SUCCESS;
1835 }
1836 uint32_t *pu32Reg = NULL;
1837 *pResp = 0;
1838 if (CODEC_NID(cmd) == 1 /* AFG */)
1839 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].afg.u32F05_param;
1840 else if (codecIsDacNode(pState, CODEC_NID(cmd)))
1841 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].dac.u32F05_param;
1842 else if (codecIsDigInPinNode(pState, CODEC_NID(cmd)))
1843 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].digin.u32F05_param;
1844 else if (codecIsAdcNode(pState, CODEC_NID(cmd)))
1845 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].adc.u32F05_param;
1846 else if (codecIsSpdifOutNode(pState, CODEC_NID(cmd)))
1847 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].spdifout.u32F05_param;
1848 else if (codecIsSpdifInNode(pState, CODEC_NID(cmd)))
1849 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].spdifin.u32F05_param;
1850 else if (codecIsReservedNode(pState, CODEC_NID(cmd)))
1851 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].reserved.u32F05_param;
1852 Assert((pu32Reg));
1853 if (!pu32Reg)
1854 return VINF_SUCCESS;
1855
1856 bool fReset = CODEC_F05_IS_RESET(*pu32Reg);
1857 bool fStopOk = CODEC_F05_IS_STOPOK(*pu32Reg);
1858
1859 if (CODEC_NID(cmd) != 1 /* AFG */)
1860 {
1861 /*
1862 * We shouldn't propogate actual power state, which actual for AFG
1863 */
1864 *pu32Reg = CODEC_MAKE_F05(fReset, fStopOk, 0,
1865 CODEC_F05_ACT(pState->pNodes[1].afg.u32F05_param),
1866 CODEC_F05_SET(cmd));
1867 }
1868
1869 /* Propagate next power state only if AFG is on or verb modifies AFG power state */
1870 if ( CODEC_NID(cmd) == 1 /* AFG */
1871 || !CODEC_F05_ACT(pState->pNodes[1].afg.u32F05_param))
1872 {
1873 *pu32Reg = CODEC_MAKE_F05(fReset, fStopOk, 0, CODEC_F05_SET(cmd), CODEC_F05_SET(cmd));
1874 if ( CODEC_NID(cmd) == 1 /* AFG */
1875 && (CODEC_F05_SET(cmd)) == CODEC_F05_D0)
1876 {
1877 /* now we're powered on AFG and may propogate power states on nodes */
1878 const uint8_t *pu8NodeIndex = &pState->au8Dacs[0];
1879 while (*(++pu8NodeIndex))
1880 codecPropogatePowerState(&pState->pNodes[*pu8NodeIndex].dac.u32F05_param);
1881
1882 pu8NodeIndex = &pState->au8Adcs[0];
1883 while (*(++pu8NodeIndex))
1884 codecPropogatePowerState(&pState->pNodes[*pu8NodeIndex].adc.u32F05_param);
1885
1886 pu8NodeIndex = &pState->au8DigInPins[0];
1887 while (*(++pu8NodeIndex))
1888 codecPropogatePowerState(&pState->pNodes[*pu8NodeIndex].digin.u32F05_param);
1889 }
1890 }
1891 return VINF_SUCCESS;
1892}
1893
1894static int codecGetStreamId(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1895{
1896 Assert((CODEC_CAD(cmd) == pState->id));
1897 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1898 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1899 {
1900 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1901 return VINF_SUCCESS;
1902 }
1903 *pResp = 0;
1904 if (codecIsDacNode(pState, CODEC_NID(cmd)))
1905 *pResp = pState->pNodes[CODEC_NID(cmd)].dac.u32F06_param;
1906 else if (codecIsAdcNode(pState, CODEC_NID(cmd)))
1907 *pResp = pState->pNodes[CODEC_NID(cmd)].adc.u32F06_param;
1908 else if (codecIsSpdifInNode(pState, CODEC_NID(cmd)))
1909 *pResp = pState->pNodes[CODEC_NID(cmd)].spdifin.u32F06_param;
1910 else if (codecIsSpdifOutNode(pState, CODEC_NID(cmd)))
1911 *pResp = pState->pNodes[CODEC_NID(cmd)].spdifout.u32F06_param;
1912 else if (CODEC_NID(cmd) == 0x1A)
1913 *pResp = pState->pNodes[CODEC_NID(cmd)].reserved.u32F06_param;
1914 return VINF_SUCCESS;
1915}
1916static int codecSetStreamId(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1917{
1918 Assert((CODEC_CAD(cmd) == pState->id));
1919 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1920 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1921 {
1922 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1923 return VINF_SUCCESS;
1924 }
1925 *pResp = 0;
1926 uint32_t *pu32addr = NULL;
1927 *pResp = 0;
1928 if (codecIsDacNode(pState, CODEC_NID(cmd)))
1929 pu32addr = &pState->pNodes[CODEC_NID(cmd)].dac.u32F06_param;
1930 else if (codecIsAdcNode(pState, CODEC_NID(cmd)))
1931 pu32addr = &pState->pNodes[CODEC_NID(cmd)].adc.u32F06_param;
1932 else if (codecIsSpdifOutNode(pState, CODEC_NID(cmd)))
1933 pu32addr = &pState->pNodes[CODEC_NID(cmd)].spdifout.u32F06_param;
1934 else if (codecIsSpdifInNode(pState, CODEC_NID(cmd)))
1935 pu32addr = &pState->pNodes[CODEC_NID(cmd)].spdifin.u32F06_param;
1936 else if (codecIsReservedNode(pState, CODEC_NID(cmd)))
1937 pu32addr = &pState->pNodes[CODEC_NID(cmd)].reserved.u32F06_param;
1938 Assert((pu32addr));
1939 if (pu32addr)
1940 codecSetRegisterU8(pu32addr, cmd, 0);
1941 return VINF_SUCCESS;
1942}
1943
1944static int codecGetConverterFormat(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1945{
1946 Assert((CODEC_CAD(cmd) == pState->id));
1947 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1948 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1949 {
1950 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1951 return VINF_SUCCESS;
1952 }
1953 *pResp = 0;
1954 if (codecIsDacNode(pState, CODEC_NID(cmd)))
1955 *pResp = pState->pNodes[CODEC_NID(cmd)].dac.u32A_param;
1956 else if (codecIsAdcNode(pState, CODEC_NID(cmd)))
1957 *pResp = pState->pNodes[CODEC_NID(cmd)].adc.u32A_param;
1958 else if (codecIsSpdifOutNode(pState, CODEC_NID(cmd)))
1959 *pResp = pState->pNodes[CODEC_NID(cmd)].spdifout.u32A_param;
1960 else if (codecIsSpdifInNode(pState, CODEC_NID(cmd)))
1961 *pResp = pState->pNodes[CODEC_NID(cmd)].spdifin.u32A_param;
1962 return VINF_SUCCESS;
1963}
1964
1965static int codecSetConverterFormat(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1966{
1967 Assert((CODEC_CAD(cmd) == pState->id));
1968 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1969 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1970 {
1971 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1972 return VINF_SUCCESS;
1973 }
1974 *pResp = 0;
1975 if (codecIsDacNode(pState, CODEC_NID(cmd)))
1976 codecSetRegisterU16(&pState->pNodes[CODEC_NID(cmd)].dac.u32A_param, cmd, 0);
1977 else if (codecIsAdcNode(pState, CODEC_NID(cmd)))
1978 codecSetRegisterU16(&pState->pNodes[CODEC_NID(cmd)].adc.u32A_param, cmd, 0);
1979 else if (codecIsSpdifOutNode(pState, CODEC_NID(cmd)))
1980 codecSetRegisterU16(&pState->pNodes[CODEC_NID(cmd)].spdifout.u32A_param, cmd, 0);
1981 else if (codecIsSpdifInNode(pState, CODEC_NID(cmd)))
1982 codecSetRegisterU16(&pState->pNodes[CODEC_NID(cmd)].spdifin.u32A_param, cmd, 0);
1983 return VINF_SUCCESS;
1984}
1985
1986/* F0C */
1987static int codecGetEAPD_BTLEnabled(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
1988{
1989 Assert((CODEC_CAD(cmd) == pState->id));
1990 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
1991 if (CODEC_NID(cmd) >= pState->cTotalNodes)
1992 {
1993 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
1994 return VINF_SUCCESS;
1995 }
1996 *pResp = 0;
1997 if (codecIsAdcVolNode(pState, CODEC_NID(cmd)))
1998 *pResp = pState->pNodes[CODEC_NID(cmd)].adcvol.u32F0c_param;
1999 else if (codecIsDacNode(pState, CODEC_NID(cmd)))
2000 *pResp = pState->pNodes[CODEC_NID(cmd)].dac.u32F0c_param;
2001 else if (codecIsDigInPinNode(pState, CODEC_NID(cmd)))
2002 *pResp = pState->pNodes[CODEC_NID(cmd)].digin.u32F0c_param;
2003 return VINF_SUCCESS;
2004}
2005
2006/* 70C */
2007static int codecSetEAPD_BTLEnabled(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
2008{
2009 Assert((CODEC_CAD(cmd) == pState->id));
2010 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
2011 if (CODEC_NID(cmd) >= pState->cTotalNodes)
2012 {
2013 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
2014 return VINF_SUCCESS;
2015 }
2016 *pResp = 0;
2017 uint32_t *pu32Reg = NULL;
2018 if (codecIsAdcVolNode(pState, CODEC_NID(cmd)))
2019 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].adcvol.u32F0c_param;
2020 else if (codecIsDacNode(pState, CODEC_NID(cmd)))
2021 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].dac.u32F0c_param;
2022 else if (codecIsDigInPinNode(pState, CODEC_NID(cmd)))
2023 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].digin.u32F0c_param;
2024 *pResp = 0;
2025 Assert((pu32Reg));
2026 if (pu32Reg)
2027 codecSetRegisterU8(pu32Reg, cmd, 0);
2028 return VINF_SUCCESS;
2029}
2030
2031/* F0F */
2032static int codecGetVolumeKnobCtrl(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
2033{
2034 Assert((CODEC_CAD(cmd) == pState->id));
2035 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
2036 if (CODEC_NID(cmd) >= pState->cTotalNodes)
2037 {
2038 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
2039 return VINF_SUCCESS;
2040 }
2041 *pResp = 0;
2042 if (codecIsVolKnobNode(pState, CODEC_NID(cmd)))
2043 *pResp = pState->pNodes[CODEC_NID(cmd)].volumeKnob.u32F0f_param;
2044 return VINF_SUCCESS;
2045}
2046
2047/* 70F */
2048static int codecSetVolumeKnobCtrl(struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
2049{
2050 Assert((CODEC_CAD(cmd) == pState->id));
2051 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
2052 if (CODEC_NID(cmd) >= pState->cTotalNodes)
2053 {
2054 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
2055 return VINF_SUCCESS;
2056 }
2057 uint32_t *pu32Reg = NULL;
2058 *pResp = 0;
2059 if (codecIsVolKnobNode(pState, CODEC_NID(cmd)))
2060 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].volumeKnob.u32F0f_param;
2061 Assert((pu32Reg));
2062 if (pu32Reg)
2063 codecSetRegisterU8(pu32Reg, cmd, 0);
2064 return VINF_SUCCESS;
2065}
2066
2067/* F17 */
2068static int codecGetGPIOUnsolisted (struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
2069{
2070 Assert((CODEC_CAD(cmd) == pState->id));
2071 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
2072 if (CODEC_NID(cmd) >= pState->cTotalNodes)
2073 {
2074 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
2075 return VINF_SUCCESS;
2076 }
2077 *pResp = 0;
2078 /* note: this is true for ALC885 */
2079 if (CODEC_NID(cmd) == 0x1 /* AFG */)
2080 *pResp = pState->pNodes[1].afg.u32F17_param;
2081 return VINF_SUCCESS;
2082}
2083
2084/* 717 */
2085static int codecSetGPIOUnsolisted (struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
2086{
2087 Assert((CODEC_CAD(cmd) == pState->id));
2088 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
2089 if (CODEC_NID(cmd) >= pState->cTotalNodes)
2090 {
2091 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
2092 return VINF_SUCCESS;
2093 }
2094 uint32_t *pu32Reg = NULL;
2095 *pResp = 0;
2096 if (CODEC_NID(cmd) == 1 /* AFG */)
2097 pu32Reg = &pState->pNodes[1].afg.u32F17_param;
2098 Assert((pu32Reg));
2099 if (pu32Reg)
2100 codecSetRegisterU8(pu32Reg, cmd, 0);
2101 return VINF_SUCCESS;
2102}
2103
2104/* F1C */
2105static int codecGetConfig (struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
2106{
2107 Assert((CODEC_CAD(cmd) == pState->id));
2108 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
2109 if (CODEC_NID(cmd) >= pState->cTotalNodes)
2110 {
2111 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
2112 return VINF_SUCCESS;
2113 }
2114 *pResp = 0;
2115 if (codecIsPortNode(pState, CODEC_NID(cmd)))
2116 *pResp = pState->pNodes[CODEC_NID(cmd)].port.u32F1c_param;
2117 else if (codecIsDigOutPinNode(pState, CODEC_NID(cmd)))
2118 *pResp = pState->pNodes[CODEC_NID(cmd)].digout.u32F1c_param;
2119 else if (codecIsDigInPinNode(pState, CODEC_NID(cmd)))
2120 *pResp = pState->pNodes[CODEC_NID(cmd)].digin.u32F1c_param;
2121 else if (codecIsPcbeepNode(pState, CODEC_NID(cmd)))
2122 *pResp = pState->pNodes[CODEC_NID(cmd)].pcbeep.u32F1c_param;
2123 else if (codecIsCdNode(pState, CODEC_NID(cmd)))
2124 *pResp = pState->pNodes[CODEC_NID(cmd)].cdnode.u32F1c_param;
2125 else if (codecIsReservedNode(pState, CODEC_NID(cmd)))
2126 *pResp = pState->pNodes[CODEC_NID(cmd)].reserved.u32F1c_param;
2127 return VINF_SUCCESS;
2128}
2129static int codecSetConfigX(struct CODECState *pState, uint32_t cmd, uint8_t u8Offset)
2130{
2131 Assert((CODEC_CAD(cmd) == pState->id));
2132 Assert((CODEC_NID(cmd) < pState->cTotalNodes));
2133 if (CODEC_NID(cmd) >= pState->cTotalNodes)
2134 {
2135 Log(("HDAcodec: invalid node address %d\n", CODEC_NID(cmd)));
2136 return VINF_SUCCESS;
2137 }
2138 uint32_t *pu32Reg = NULL;
2139 if (codecIsPortNode(pState, CODEC_NID(cmd)))
2140 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].port.u32F1c_param;
2141 else if (codecIsDigInPinNode(pState, CODEC_NID(cmd)))
2142 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].digin.u32F1c_param;
2143 else if (codecIsDigOutPinNode(pState, CODEC_NID(cmd)))
2144 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].digout.u32F1c_param;
2145 else if (codecIsCdNode(pState, CODEC_NID(cmd)))
2146 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].cdnode.u32F1c_param;
2147 else if (codecIsPcbeepNode(pState, CODEC_NID(cmd)))
2148 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].pcbeep.u32F1c_param;
2149 else if (codecIsReservedNode(pState, CODEC_NID(cmd)))
2150 pu32Reg = &pState->pNodes[CODEC_NID(cmd)].reserved.u32F1c_param;
2151 Assert((pu32Reg));
2152 if (pu32Reg)
2153 codecSetRegisterU8(pu32Reg, cmd, u8Offset);
2154 return VINF_SUCCESS;
2155}
2156/* 71C */
2157static int codecSetConfig0 (struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
2158{
2159 *pResp = 0;
2160 return codecSetConfigX(pState, cmd, 0);
2161}
2162/* 71D */
2163static int codecSetConfig1 (struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
2164{
2165 *pResp = 0;
2166 return codecSetConfigX(pState, cmd, 8);
2167}
2168/* 71E */
2169static int codecSetConfig2 (struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
2170{
2171 *pResp = 0;
2172 return codecSetConfigX(pState, cmd, 16);
2173}
2174/* 71E */
2175static int codecSetConfig3 (struct CODECState *pState, uint32_t cmd, uint64_t *pResp)
2176{
2177 *pResp = 0;
2178 return codecSetConfigX(pState, cmd, 24);
2179}
2180
2181
2182static int codecToAudVolume(AMPLIFIER *pAmp, audmixerctl_t mt)
2183{
2184 uint32_t dir = AMPLIFIER_OUT;
2185 switch (mt)
2186 {
2187 case AUD_MIXER_VOLUME:
2188 case AUD_MIXER_PCM:
2189 dir = AMPLIFIER_OUT;
2190 break;
2191 case AUD_MIXER_LINE_IN:
2192 dir = AMPLIFIER_IN;
2193 break;
2194 }
2195 int mute = AMPLIFIER_REGISTER(*pAmp, dir, AMPLIFIER_LEFT, 0) & RT_BIT(7);
2196 mute |= AMPLIFIER_REGISTER(*pAmp, dir, AMPLIFIER_RIGHT, 0) & RT_BIT(7);
2197 mute >>=7;
2198 mute &= 0x1;
2199 uint8_t lVol = AMPLIFIER_REGISTER(*pAmp, dir, AMPLIFIER_LEFT, 0) & 0x7f;
2200 uint8_t rVol = AMPLIFIER_REGISTER(*pAmp, dir, AMPLIFIER_RIGHT, 0) & 0x7f;
2201 AUD_set_volume(mt, &mute, &lVol, &rVol);
2202 return VINF_SUCCESS;
2203}
2204
2205static CODECVERB CODECVERBS[] =
2206{
2207/* verb | verb mask | callback */
2208/* ----------- -------------------- ----------------------- */
2209 {0x000F0000, CODEC_VERB_8BIT_CMD , codecGetParameter },
2210 {0x000F0100, CODEC_VERB_8BIT_CMD , codecGetConSelectCtrl },
2211 {0x00070100, CODEC_VERB_8BIT_CMD , codecSetConSelectCtrl },
2212 {0x000F0600, CODEC_VERB_8BIT_CMD , codecGetStreamId },
2213 {0x00070600, CODEC_VERB_8BIT_CMD , codecSetStreamId },
2214 {0x000F0700, CODEC_VERB_8BIT_CMD , codecGetPinCtrl },
2215 {0x00070700, CODEC_VERB_8BIT_CMD , codecSetPinCtrl },
2216 {0x000F0800, CODEC_VERB_8BIT_CMD , codecGetUnsolicitedEnabled },
2217 {0x00070800, CODEC_VERB_8BIT_CMD , codecSetUnsolicitedEnabled },
2218 {0x000F0900, CODEC_VERB_8BIT_CMD , codecGetPinSense },
2219 {0x00070900, CODEC_VERB_8BIT_CMD , codecSetPinSense },
2220 {0x000F0200, CODEC_VERB_8BIT_CMD , codecGetConnectionListEntry },
2221 {0x000F0300, CODEC_VERB_8BIT_CMD , codecGetProcessingState },
2222 {0x00070300, CODEC_VERB_8BIT_CMD , codecSetProcessingState },
2223 {0x000F0D00, CODEC_VERB_8BIT_CMD , codecGetDigitalConverter },
2224 {0x00070D00, CODEC_VERB_8BIT_CMD , codecSetDigitalConverter1 },
2225 {0x00070E00, CODEC_VERB_8BIT_CMD , codecSetDigitalConverter2 },
2226 {0x000F2000, CODEC_VERB_8BIT_CMD , codecGetSubId },
2227 {0x00072000, CODEC_VERB_8BIT_CMD , codecSetSubId0 },
2228 {0x00072100, CODEC_VERB_8BIT_CMD , codecSetSubId1 },
2229 {0x00072200, CODEC_VERB_8BIT_CMD , codecSetSubId2 },
2230 {0x00072300, CODEC_VERB_8BIT_CMD , codecSetSubId3 },
2231 {0x0007FF00, CODEC_VERB_8BIT_CMD , codecReset },
2232 {0x000F0500, CODEC_VERB_8BIT_CMD , codecGetPowerState },
2233 {0x00070500, CODEC_VERB_8BIT_CMD , codecSetPowerState },
2234 {0x000F0C00, CODEC_VERB_8BIT_CMD , codecGetEAPD_BTLEnabled },
2235 {0x00070C00, CODEC_VERB_8BIT_CMD , codecSetEAPD_BTLEnabled },
2236 {0x000F0F00, CODEC_VERB_8BIT_CMD , codecGetVolumeKnobCtrl },
2237 {0x00070F00, CODEC_VERB_8BIT_CMD , codecSetVolumeKnobCtrl },
2238 {0x000F1700, CODEC_VERB_8BIT_CMD , codecGetGPIOUnsolisted },
2239 {0x00071700, CODEC_VERB_8BIT_CMD , codecSetGPIOUnsolisted },
2240 {0x000F1C00, CODEC_VERB_8BIT_CMD , codecGetConfig },
2241 {0x00071C00, CODEC_VERB_8BIT_CMD , codecSetConfig0 },
2242 {0x00071D00, CODEC_VERB_8BIT_CMD , codecSetConfig1 },
2243 {0x00071E00, CODEC_VERB_8BIT_CMD , codecSetConfig2 },
2244 {0x00071F00, CODEC_VERB_8BIT_CMD , codecSetConfig3 },
2245 {0x000A0000, CODEC_VERB_16BIT_CMD, codecGetConverterFormat },
2246 {0x00020000, CODEC_VERB_16BIT_CMD, codecSetConverterFormat },
2247 {0x000B0000, CODEC_VERB_16BIT_CMD, codecGetAmplifier },
2248 {0x00030000, CODEC_VERB_16BIT_CMD, codecSetAmplifier },
2249};
2250
2251static int codecLookup(CODECState *pState, uint32_t cmd, PPFNCODECVERBPROCESSOR pfn)
2252{
2253 int rc = VINF_SUCCESS;
2254 Assert(CODEC_CAD(cmd) == pState->id);
2255 if (codecIsReservedNode(pState, CODEC_NID(cmd)))
2256 {
2257 Log(("HDAcodec: cmd %x was addressed to reserved node\n", cmd));
2258 }
2259 if ( CODEC_VERBDATA(cmd) == 0
2260 || CODEC_NID(cmd) >= pState->cTotalNodes)
2261 {
2262 *pfn = codecUnimplemented;
2263 //** @todo r=michaln: There needs to be a counter to avoid log flooding (see e.g. DevRTC.cpp)
2264 Log(("HDAcodec: cmd %x was ignored\n", cmd));
2265 return VINF_SUCCESS;
2266 }
2267 for (int i = 0; i < pState->cVerbs; ++i)
2268 {
2269 if ((CODEC_VERBDATA(cmd) & pState->pVerbs[i].mask) == pState->pVerbs[i].verb)
2270 {
2271 *pfn = pState->pVerbs[i].pfn;
2272 return VINF_SUCCESS;
2273 }
2274 }
2275 *pfn = codecUnimplemented;
2276 Log(("HDAcodec: callback for %x wasn't found\n", CODEC_VERBDATA(cmd)));
2277 return rc;
2278}
2279
2280static void pi_callback (void *opaque, int avail)
2281{
2282 CODECState *pState = (CODECState *)opaque;
2283 pState->pfnTransfer(pState, PI_INDEX, avail);
2284}
2285
2286static void po_callback (void *opaque, int avail)
2287{
2288 CODECState *pState = (CODECState *)opaque;
2289 pState->pfnTransfer(pState, PO_INDEX, avail);
2290}
2291
2292static void mc_callback (void *opaque, int avail)
2293{
2294 CODECState *pState = (CODECState *)opaque;
2295 pState->pfnTransfer(pState, MC_INDEX, avail);
2296}
2297
2298int codecConstruct(CODECState *pState, ENMCODEC enmCodec)
2299{
2300 audsettings_t as;
2301 int rc;
2302 pState->pVerbs = (CODECVERB *)&CODECVERBS;
2303 pState->cVerbs = sizeof(CODECVERBS)/sizeof(CODECVERB);
2304 pState->pfnLookup = codecLookup;
2305 pState->enmCodec = enmCodec;
2306 switch (enmCodec)
2307 {
2308 case STAC9220_CODEC:
2309 rc = stac9220Construct(pState);
2310 AssertRC(rc);
2311 break;
2312 case ALC885_CODEC:
2313 rc = alc885Construct(pState);
2314 AssertRC(rc);
2315 break;
2316 default:
2317 AssertMsgFailed(("Unsupported Codec"));
2318 }
2319 /* common root node initializers */
2320 pState->pNodes[0].node.au32F00_param[0] = CODEC_MAKE_F00_00(pState->u16VendorId, pState->u16DeviceId);
2321 pState->pNodes[0].node.au32F00_param[4] = CODEC_MAKE_F00_04(0x1, 0x1);
2322 /* common AFG node initializers */
2323 pState->pNodes[1].node.au32F00_param[4] = CODEC_MAKE_F00_04(0x2, pState->cTotalNodes - 2);
2324 pState->pNodes[1].node.au32F00_param[5] = CODEC_MAKE_F00_05(CODEC_F00_05_UNSOL, CODEC_F00_05_AFG);
2325 pState->pNodes[1].afg.u32F20_param = CODEC_MAKE_F20(pState->u16VendorId, pState->u8BSKU, pState->u8AssemblyId);
2326
2327 //** @todo r=michaln: Was this meant to be 'HDA' or something like that? (AC'97 was on ICH0)
2328 AUD_register_card ("ICH0", &pState->card);
2329
2330 /* 44.1 kHz */
2331 as.freq = 44100;
2332 as.nchannels = 2;
2333 as.fmt = AUD_FMT_S16;
2334 as.endianness = 0;
2335 #define SETUP_AUDIO_FORMAT(pState, base, mult, div, name, as, in_callback, out_callback) \
2336 do{ \
2337 AUDIO_FORMAT_SELECTOR((pState), Out, (base), (mult), div) = AUD_open_out(&(pState)->card, \
2338 AUDIO_FORMAT_SELECTOR(pState, Out, (base), (mult), (div)), name ".out", (pState), (out_callback), &(as)); \
2339 if (!AUDIO_FORMAT_SELECTOR(pState, Out, (base), (mult), (div))) \
2340 LogRel (("HDAcodec: WARNING: Unable to open PCM OUT(%s)!\n", name ".out")); \
2341 AUDIO_FORMAT_SELECTOR(pState, In, (base), (mult), (div)) = AUD_open_in(&(pState)->card, \
2342 AUDIO_FORMAT_SELECTOR(pState, In, (base), (mult), (div)), name ".in", (pState), (in_callback), &(as)); \
2343 if (!AUDIO_FORMAT_SELECTOR(pState, In, (base), (mult), (div))) \
2344 LogRel (("HDAcodec: WARNING: Unable to open PCM IN(%s)!\n", name ".in")); \
2345 } while(0)
2346 #define IS_FORMAT_SUPPORTED_BY_HOST(pState, base, mult, div) (AUDIO_FORMAT_SELECTOR((pState), Out, (base), (mult), (div)) \
2347 && AUDIO_FORMAT_SELECTOR((pState), In, (base), (mult), (div)))
2348
2349 pState->pNodes[1].node.au32F00_param[0xA] = CODEC_F00_0A_16_BIT;
2350 SETUP_AUDIO_FORMAT(pState, AFMT_HZ_44_1K, AFMT_MULT_X1, AFMT_DIV_X1, "hda44_1", as, pi_callback, po_callback);
2351 pState->pNodes[1].node.au32F00_param[0xA] |= IS_FORMAT_SUPPORTED_BY_HOST(pState, AFMT_HZ_44_1K, AFMT_MULT_X1, AFMT_DIV_X1) ? CODEC_F00_0A_44_1KHZ : 0;
2352
2353#ifdef VBOX_WITH_AUDIO_FLEXIBLE_FORMAT
2354 as.freq *= 2; /* 2 * 44.1kHz */
2355 SETUP_AUDIO_FORMAT(pState, AFMT_HZ_44_1K, AFMT_MULT_X2, AFMT_DIV_X1, "hda44_1_2x", as, pi_callback, po_callback);
2356 pState->pNodes[1].node.au32F00_param[0xA] |= IS_FORMAT_SUPPORTED_BY_HOST(pState, AFMT_HZ_44_1K, AFMT_MULT_X2, AFMT_DIV_X1) ? CODEC_F00_0A_44_1KHZ_MULT_2X : 0;
2357
2358 as.freq *= 2; /* 4 * 44.1kHz */
2359 SETUP_AUDIO_FORMAT(pState, AFMT_HZ_44_1K, AFMT_MULT_X4, AFMT_DIV_X1, "hda44_1_4x", as, pi_callback, po_callback);
2360 pState->pNodes[1].node.au32F00_param[0xA] |= IS_FORMAT_SUPPORTED_BY_HOST(pState, AFMT_HZ_44_1K, AFMT_MULT_X4, AFMT_DIV_X1) ? CODEC_F00_0A_44_1KHZ_MULT_4X : 0;
2361
2362 as.freq = 48000;
2363 SETUP_AUDIO_FORMAT(pState, AFMT_HZ_48K, AFMT_MULT_X1, AFMT_DIV_X1, "hda48", as, pi_callback, po_callback);
2364 pState->pNodes[1].node.au32F00_param[0xA] |= IS_FORMAT_SUPPORTED_BY_HOST(pState, AFMT_HZ_48K, AFMT_MULT_X1, AFMT_DIV_X1) ? CODEC_F00_0A_48KHZ : 0;
2365
2366# if 0
2367 as.freq *= 2; /* 2 * 48kHz */
2368 SETUP_AUDIO_FORMAT(pState, AFMT_HZ_48K, AFMT_MULT_X2, AFMT_DIV_X1, "hda48_2x", as, pi_callback, po_callback);
2369 pState->pNodes[1].node.au32F00_param[0xA] |= IS_FORMAT_SUPPORTED_BY_HOST(pState, AFMT_HZ_48K, AFMT_MULT_X2, AFMT_DIV_X1) ? CODEC_F00_0A_48KHZ_MULT_2X : 0;
2370
2371 as.freq *= 2; /* 4 * 48kHz */
2372 SETUP_AUDIO_FORMAT(pState, AFMT_HZ_48K, AFMT_MULT_X4, AFMT_DIV_X1, "hda48_4x", as, pi_callback, po_callback);
2373 pState->pNodes[1].node.au32F00_param[0xA] |= IS_FORMAT_SUPPORTED_BY_HOST(pState, AFMT_HZ_48K, AFMT_MULT_X4, AFMT_DIV_X1) ? CODEC_F00_0A_48KHZ_MULT_4X : 0;
2374# endif
2375#endif
2376 #undef SETUP_AUDIO_FORMAT
2377 #undef IS_FORMAT_SUPPORTED_BY_HOST
2378
2379 uint8_t i;
2380 Assert(pState->pNodes);
2381 Assert(pState->pfnCodecNodeReset);
2382 for (i = 0; i < pState->cTotalNodes; ++i)
2383 {
2384 pState->pfnCodecNodeReset(pState, i, &pState->pNodes[i]);
2385 }
2386
2387 codecToAudVolume(&pState->pNodes[pState->u8DacLineOut].dac.B_params, AUD_MIXER_VOLUME);
2388 codecToAudVolume(&pState->pNodes[pState->u8AdcVolsLineIn].adcvol.B_params, AUD_MIXER_LINE_IN);
2389
2390 return VINF_SUCCESS;
2391}
2392int codecDestruct(CODECState *pCodecState)
2393{
2394 RTMemFree(pCodecState->pNodes);
2395 return VINF_SUCCESS;
2396}
2397
2398int codecSaveState(CODECState *pCodecState, PSSMHANDLE pSSMHandle)
2399{
2400 SSMR3PutMem (pSSMHandle, pCodecState->pNodes, sizeof(CODECNODE) * pCodecState->cTotalNodes);
2401 return VINF_SUCCESS;
2402}
2403
2404int codecLoadState(CODECState *pCodecState, PSSMHANDLE pSSMHandle)
2405{
2406 SSMR3GetMem (pSSMHandle, pCodecState->pNodes, sizeof(CODECNODE) * pCodecState->cTotalNodes);
2407 if (codecIsDacNode(pCodecState, pCodecState->u8DacLineOut))
2408 codecToAudVolume(&pCodecState->pNodes[pCodecState->u8DacLineOut].dac.B_params, AUD_MIXER_VOLUME);
2409 else if (codecIsSpdifOutNode(pCodecState, pCodecState->u8DacLineOut))
2410 codecToAudVolume(&pCodecState->pNodes[pCodecState->u8DacLineOut].spdifout.B_params, AUD_MIXER_VOLUME);
2411 codecToAudVolume(&pCodecState->pNodes[pCodecState->u8AdcVolsLineIn].adcvol.B_params, AUD_MIXER_LINE_IN);
2412 return VINF_SUCCESS;
2413}
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