VirtualBox

source: vbox/trunk/src/VBox/Devices/Audio/DevIchHdaCodec.cpp@ 56085

Last change on this file since 56085 was 56085, checked in by vboxsync, 10 years ago

PDM/Audio: Removed old audio architecture.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 101.2 KB
Line 
1/* $Id: DevIchHdaCodec.cpp 56085 2015-05-26 16:39:58Z vboxsync $ */
2/** @file
3 * DevIchHdaCodec - VBox ICH Intel HD Audio Codec.
4 *
5 * Implemented against "Intel I/O Controller Hub 6 (ICH6) High Definition
6 * Audio / AC '97 - Programmer's Reference Manual (PRM)", document number
7 * 302349-003.
8 */
9
10/*
11 * Copyright (C) 2006-2014 Oracle Corporation
12 *
13 * This file is part of VirtualBox Open Source Edition (OSE), as
14 * available from http://www.virtualbox.org. This file is free software;
15 * you can redistribute it and/or modify it under the terms of the GNU
16 * General Public License (GPL) as published by the Free Software
17 * Foundation, in version 2 as it comes in the "COPYING" file of the
18 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
19 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
20 */
21
22
23/*******************************************************************************
24* Header Files *
25*******************************************************************************/
26//#define LOG_GROUP LOG_GROUP_DEV_AUDIO
27#include <VBox/vmm/pdmdev.h>
28#include <VBox/vmm/pdmaudioifs.h>
29#include <iprt/assert.h>
30#include <iprt/uuid.h>
31#include <iprt/string.h>
32#include <iprt/mem.h>
33#include <iprt/asm.h>
34#include <iprt/cpp/utils.h>
35
36#include "VBoxDD.h"
37#include "DevIchHdaCodec.h"
38
39
40/*******************************************************************************
41* Defined Constants And Macros *
42*******************************************************************************/
43/* PRM 5.3.1 */
44/** Codec address mask. */
45#define CODEC_CAD_MASK 0xF0000000
46/** Codec address shift. */
47#define CODEC_CAD_SHIFT 28
48#define CODEC_DIRECT_MASK RT_BIT(27)
49/** Node ID mask. */
50#define CODEC_NID_MASK 0x07F00000
51/** Node ID shift. */
52#define CODEC_NID_SHIFT 20
53#define CODEC_VERBDATA_MASK 0x000FFFFF
54#define CODEC_VERB_4BIT_CMD 0x000FFFF0
55#define CODEC_VERB_4BIT_DATA 0x0000000F
56#define CODEC_VERB_8BIT_CMD 0x000FFF00
57#define CODEC_VERB_8BIT_DATA 0x000000FF
58#define CODEC_VERB_16BIT_CMD 0x000F0000
59#define CODEC_VERB_16BIT_DATA 0x0000FFFF
60
61#define CODEC_CAD(cmd) (((cmd) & CODEC_CAD_MASK) >> CODEC_CAD_SHIFT)
62#define CODEC_DIRECT(cmd) ((cmd) & CODEC_DIRECT_MASK)
63#define CODEC_NID(cmd) ((((cmd) & CODEC_NID_MASK)) >> CODEC_NID_SHIFT)
64#define CODEC_VERBDATA(cmd) ((cmd) & CODEC_VERBDATA_MASK)
65#define CODEC_VERB_CMD(cmd, mask, x) (((cmd) & (mask)) >> (x))
66#define CODEC_VERB_CMD4(cmd) (CODEC_VERB_CMD((cmd), CODEC_VERB_4BIT_CMD, 4))
67#define CODEC_VERB_CMD8(cmd) (CODEC_VERB_CMD((cmd), CODEC_VERB_8BIT_CMD, 8))
68#define CODEC_VERB_CMD16(cmd) (CODEC_VERB_CMD((cmd), CODEC_VERB_16BIT_CMD, 16))
69#define CODEC_VERB_PAYLOAD4(cmd) ((cmd) & CODEC_VERB_4BIT_DATA)
70#define CODEC_VERB_PAYLOAD8(cmd) ((cmd) & CODEC_VERB_8BIT_DATA)
71#define CODEC_VERB_PAYLOAD16(cmd) ((cmd) & CODEC_VERB_16BIT_DATA)
72
73#define CODEC_VERB_GET_AMP_DIRECTION RT_BIT(15)
74#define CODEC_VERB_GET_AMP_SIDE RT_BIT(13)
75#define CODEC_VERB_GET_AMP_INDEX 0x7
76
77/* HDA spec 7.3.3.7 NoteA */
78#define CODEC_GET_AMP_DIRECTION(cmd) (((cmd) & CODEC_VERB_GET_AMP_DIRECTION) >> 15)
79#define CODEC_GET_AMP_SIDE(cmd) (((cmd) & CODEC_VERB_GET_AMP_SIDE) >> 13)
80#define CODEC_GET_AMP_INDEX(cmd) (CODEC_GET_AMP_DIRECTION(cmd) ? 0 : ((cmd) & CODEC_VERB_GET_AMP_INDEX))
81
82/* HDA spec 7.3.3.7 NoteC */
83#define CODEC_VERB_SET_AMP_OUT_DIRECTION RT_BIT(15)
84#define CODEC_VERB_SET_AMP_IN_DIRECTION RT_BIT(14)
85#define CODEC_VERB_SET_AMP_LEFT_SIDE RT_BIT(13)
86#define CODEC_VERB_SET_AMP_RIGHT_SIDE RT_BIT(12)
87#define CODEC_VERB_SET_AMP_INDEX (0x7 << 8)
88
89#define CODEC_SET_AMP_IS_OUT_DIRECTION(cmd) (((cmd) & CODEC_VERB_SET_AMP_OUT_DIRECTION) != 0)
90#define CODEC_SET_AMP_IS_IN_DIRECTION(cmd) (((cmd) & CODEC_VERB_SET_AMP_IN_DIRECTION) != 0)
91#define CODEC_SET_AMP_IS_LEFT_SIDE(cmd) (((cmd) & CODEC_VERB_SET_AMP_LEFT_SIDE) != 0)
92#define CODEC_SET_AMP_IS_RIGHT_SIDE(cmd) (((cmd) & CODEC_VERB_SET_AMP_RIGHT_SIDE) != 0)
93#define CODEC_SET_AMP_INDEX(cmd) (((cmd) & CODEC_VERB_SET_AMP_INDEX) >> 7)
94
95/* HDA spec 7.3.3.1 defines layout of configuration registers/verbs (0xF00) */
96/* VendorID (7.3.4.1) */
97#define CODEC_MAKE_F00_00(vendorID, deviceID) (((vendorID) << 16) | (deviceID))
98#define CODEC_F00_00_VENDORID(f00_00) (((f00_00) >> 16) & 0xFFFF)
99#define CODEC_F00_00_DEVICEID(f00_00) ((f00_00) & 0xFFFF)
100/* RevisionID (7.3.4.2)*/
101#define CODEC_MAKE_F00_02(MajRev, MinRev, RevisionID, SteppingID) (((MajRev) << 20)|((MinRev) << 16)|((RevisionID) << 8)|(SteppingID))
102/* Subordinate node count (7.3.4.3)*/
103#define CODEC_MAKE_F00_04(startNodeNumber, totalNodeNumber) ((((startNodeNumber) & 0xFF) << 16)|((totalNodeNumber) & 0xFF))
104#define CODEC_F00_04_TO_START_NODE_NUMBER(f00_04) (((f00_04) >> 16) & 0xFF)
105#define CODEC_F00_04_TO_NODE_COUNT(f00_04) ((f00_04) & 0xFF)
106/*
107 * Function Group Type (7.3.4.4)
108 * 0 & [0x3-0x7f] are reserved types
109 * [0x80 - 0xff] are vendor defined function groups
110 */
111#define CODEC_MAKE_F00_05(UnSol, NodeType) (((UnSol) << 8)|(NodeType))
112#define CODEC_F00_05_UNSOL RT_BIT(8)
113#define CODEC_F00_05_AFG (0x1)
114#define CODEC_F00_05_MFG (0x2)
115#define CODEC_F00_05_IS_UNSOL(f00_05) RT_BOOL((f00_05) & RT_BIT(8))
116#define CODEC_F00_05_GROUP(f00_05) ((f00_05) & 0xff)
117/* Audio Function Group capabilities (7.3.4.5) */
118#define CODEC_MAKE_F00_08(BeepGen, InputDelay, OutputDelay) ((((BeepGen) & 0x1) << 16)| (((InputDelay) & 0xF) << 8) | ((OutputDelay) & 0xF))
119#define CODEC_F00_08_BEEP_GEN(f00_08) ((f00_08) & RT_BIT(16)
120
121/* Widget Capabilities (7.3.4.6) */
122#define CODEC_MAKE_F00_09(type, delay, chanel_count) \
123 ( (((type) & 0xF) << 20) \
124 | (((delay) & 0xF) << 16) \
125 | (((chanel_count) & 0xF) << 13))
126/* note: types 0x8-0xe are reserved */
127#define CODEC_F00_09_TYPE_AUDIO_OUTPUT (0x0)
128#define CODEC_F00_09_TYPE_AUDIO_INPUT (0x1)
129#define CODEC_F00_09_TYPE_AUDIO_MIXER (0x2)
130#define CODEC_F00_09_TYPE_AUDIO_SELECTOR (0x3)
131#define CODEC_F00_09_TYPE_PIN_COMPLEX (0x4)
132#define CODEC_F00_09_TYPE_POWER_WIDGET (0x5)
133#define CODEC_F00_09_TYPE_VOLUME_KNOB (0x6)
134#define CODEC_F00_09_TYPE_BEEP_GEN (0x7)
135#define CODEC_F00_09_TYPE_VENDOR_DEFINED (0xF)
136
137#define CODEC_F00_09_CAP_CP RT_BIT(12)
138#define CODEC_F00_09_CAP_L_R_SWAP RT_BIT(11)
139#define CODEC_F00_09_CAP_POWER_CTRL RT_BIT(10)
140#define CODEC_F00_09_CAP_DIGITAL RT_BIT(9)
141#define CODEC_F00_09_CAP_CONNECTION_LIST RT_BIT(8)
142#define CODEC_F00_09_CAP_UNSOL RT_BIT(7)
143#define CODEC_F00_09_CAP_PROC_WIDGET RT_BIT(6)
144#define CODEC_F00_09_CAP_STRIPE RT_BIT(5)
145#define CODEC_F00_09_CAP_FMT_OVERRIDE RT_BIT(4)
146#define CODEC_F00_09_CAP_AMP_FMT_OVERRIDE RT_BIT(3)
147#define CODEC_F00_09_CAP_OUT_AMP_PRESENT RT_BIT(2)
148#define CODEC_F00_09_CAP_IN_AMP_PRESENT RT_BIT(1)
149#define CODEC_F00_09_CAP_LSB RT_BIT(0)
150
151#define CODEC_F00_09_TYPE(f00_09) (((f00_09) >> 20) & 0xF)
152
153#define CODEC_F00_09_IS_CAP_CP(f00_09) RT_BOOL((f00_09) & RT_BIT(12))
154#define CODEC_F00_09_IS_CAP_L_R_SWAP(f00_09) RT_BOOL((f00_09) & RT_BIT(11))
155#define CODEC_F00_09_IS_CAP_POWER_CTRL(f00_09) RT_BOOL((f00_09) & RT_BIT(10))
156#define CODEC_F00_09_IS_CAP_DIGITAL(f00_09) RT_BOOL((f00_09) & RT_BIT(9))
157#define CODEC_F00_09_IS_CAP_CONNECTION_LIST(f00_09) RT_BOOL((f00_09) & RT_BIT(8))
158#define CODEC_F00_09_IS_CAP_UNSOL(f00_09) RT_BOOL((f00_09) & RT_BIT(7))
159#define CODEC_F00_09_IS_CAP_PROC_WIDGET(f00_09) RT_BOOL((f00_09) & RT_BIT(6))
160#define CODEC_F00_09_IS_CAP_STRIPE(f00_09) RT_BOOL((f00_09) & RT_BIT(5))
161#define CODEC_F00_09_IS_CAP_FMT_OVERRIDE(f00_09) RT_BOOL((f00_09) & RT_BIT(4))
162#define CODEC_F00_09_IS_CAP_AMP_OVERRIDE(f00_09) RT_BOOL((f00_09) & RT_BIT(3))
163#define CODEC_F00_09_IS_CAP_OUT_AMP_PRESENT(f00_09) RT_BOOL((f00_09) & RT_BIT(2))
164#define CODEC_F00_09_IS_CAP_IN_AMP_PRESENT(f00_09) RT_BOOL((f00_09) & RT_BIT(1))
165#define CODEC_F00_09_IS_CAP_LSB(f00_09) RT_BOOL((f00_09) & RT_BIT(0))
166
167/* Supported PCM size, rates (7.3.4.7) */
168#define CODEC_F00_0A_32_BIT RT_BIT(19)
169#define CODEC_F00_0A_24_BIT RT_BIT(18)
170#define CODEC_F00_0A_16_BIT RT_BIT(17)
171#define CODEC_F00_0A_8_BIT RT_BIT(16)
172
173#define CODEC_F00_0A_48KHZ_MULT_8X RT_BIT(11)
174#define CODEC_F00_0A_48KHZ_MULT_4X RT_BIT(10)
175#define CODEC_F00_0A_44_1KHZ_MULT_4X RT_BIT(9)
176#define CODEC_F00_0A_48KHZ_MULT_2X RT_BIT(8)
177#define CODEC_F00_0A_44_1KHZ_MULT_2X RT_BIT(7)
178#define CODEC_F00_0A_48KHZ RT_BIT(6)
179#define CODEC_F00_0A_44_1KHZ RT_BIT(5)
180/* 2/3 * 48kHz */
181#define CODEC_F00_0A_48KHZ_2_3X RT_BIT(4)
182/* 1/2 * 44.1kHz */
183#define CODEC_F00_0A_44_1KHZ_1_2X RT_BIT(3)
184/* 1/3 * 48kHz */
185#define CODEC_F00_0A_48KHZ_1_3X RT_BIT(2)
186/* 1/4 * 44.1kHz */
187#define CODEC_F00_0A_44_1KHZ_1_4X RT_BIT(1)
188/* 1/6 * 48kHz */
189#define CODEC_F00_0A_48KHZ_1_6X RT_BIT(0)
190
191/* Supported streams formats (7.3.4.8) */
192#define CODEC_F00_0B_AC3 RT_BIT(2)
193#define CODEC_F00_0B_FLOAT32 RT_BIT(1)
194#define CODEC_F00_0B_PCM RT_BIT(0)
195
196/* Pin Capabilities (7.3.4.9)*/
197#define CODEC_MAKE_F00_0C(vref_ctrl) (((vref_ctrl) & 0xFF) << 8)
198#define CODEC_F00_0C_CAP_HBR RT_BIT(27)
199#define CODEC_F00_0C_CAP_DP RT_BIT(24)
200#define CODEC_F00_0C_CAP_EAPD RT_BIT(16)
201#define CODEC_F00_0C_CAP_HDMI RT_BIT(7)
202#define CODEC_F00_0C_CAP_BALANCED_IO RT_BIT(6)
203#define CODEC_F00_0C_CAP_INPUT RT_BIT(5)
204#define CODEC_F00_0C_CAP_OUTPUT RT_BIT(4)
205#define CODEC_F00_0C_CAP_HP RT_BIT(3)
206#define CODEC_F00_0C_CAP_PRESENSE_DETECT RT_BIT(2)
207#define CODEC_F00_0C_CAP_TRIGGER_REQUIRED RT_BIT(1)
208#define CODEC_F00_0C_CAP_IMPENDANCE_SENSE RT_BIT(0)
209
210#define CODEC_F00_0C_IS_CAP_HBR(f00_0c) ((f00_0c) & RT_BIT(27))
211#define CODEC_F00_0C_IS_CAP_DP(f00_0c) ((f00_0c) & RT_BIT(24))
212#define CODEC_F00_0C_IS_CAP_EAPD(f00_0c) ((f00_0c) & RT_BIT(16))
213#define CODEC_F00_0C_IS_CAP_HDMI(f00_0c) ((f00_0c) & RT_BIT(7))
214#define CODEC_F00_0C_IS_CAP_BALANCED_IO(f00_0c) ((f00_0c) & RT_BIT(6))
215#define CODEC_F00_0C_IS_CAP_INPUT(f00_0c) ((f00_0c) & RT_BIT(5))
216#define CODEC_F00_0C_IS_CAP_OUTPUT(f00_0c) ((f00_0c) & RT_BIT(4))
217#define CODEC_F00_0C_IS_CAP_HP(f00_0c) ((f00_0c) & RT_BIT(3))
218#define CODEC_F00_0C_IS_CAP_PRESENSE_DETECT(f00_0c) ((f00_0c) & RT_BIT(2))
219#define CODEC_F00_0C_IS_CAP_TRIGGER_REQUIRED(f00_0c) ((f00_0c) & RT_BIT(1))
220#define CODEC_F00_0C_IS_CAP_IMPENDANCE_SENSE(f00_0c) ((f00_0c) & RT_BIT(0))
221
222/* Input Amplifier capabilities (7.3.4.10) */
223#define CODEC_MAKE_F00_0D(mute_cap, step_size, num_steps, offset) \
224 ( (((mute_cap) & 0x1) << 31) \
225 | (((step_size) & 0xFF) << 16) \
226 | (((num_steps) & 0xFF) << 8) \
227 | ((offset) & 0xFF))
228
229/* Output Amplifier capabilities (7.3.4.10) */
230#define CODEC_MAKE_F00_12 CODEC_MAKE_F00_0D
231
232/* Connection list lenght (7.3.4.11) */
233#define CODEC_MAKE_F00_0E(long_form, length) \
234 ( (((long_form) & 0x1) << 7) \
235 | ((length) & 0x7F))
236#define CODEC_F00_0E_IS_LONG(f00_0e) RT_BOOL((f00_0e) & RT_BIT(7))
237#define CODEC_F00_0E_COUNT(f00_0e) ((f00_0e) & 0x7F)
238/* Supported Power States (7.3.4.12) */
239#define CODEC_F00_0F_EPSS RT_BIT(31)
240#define CODEC_F00_0F_CLKSTOP RT_BIT(30)
241#define CODEC_F00_0F_S3D3 RT_BIT(29)
242#define CODEC_F00_0F_D3COLD RT_BIT(4)
243#define CODEC_F00_0F_D3 RT_BIT(3)
244#define CODEC_F00_0F_D2 RT_BIT(2)
245#define CODEC_F00_0F_D1 RT_BIT(1)
246#define CODEC_F00_0F_D0 RT_BIT(0)
247
248/* Processing capabilities 7.3.4.13 */
249#define CODEC_MAKE_F00_10(num, benign) ((((num) & 0xFF) << 8) | ((benign) & 0x1))
250#define CODEC_F00_10_NUM(f00_10) (((f00_10) & (0xFF << 8)) >> 8)
251#define CODEC_F00_10_BENING(f00_10) ((f00_10) & 0x1)
252
253/* CP/IO Count (7.3.4.14) */
254#define CODEC_MAKE_F00_11(wake, unsol, numgpi, numgpo, numgpio) \
255 ( (((wake) & 0x1) << 31) \
256 | (((unsol) & 0x1) << 30) \
257 | (((numgpi) & 0xFF) << 16) \
258 | (((numgpo) & 0xFF) << 8) \
259 | ((numgpio) & 0xFF))
260
261/* Processing States (7.3.3.4) */
262#define CODEC_F03_OFF (0)
263#define CODEC_F03_ON RT_BIT(0)
264#define CODEC_F03_BENING RT_BIT(1)
265/* Power States (7.3.3.10) */
266#define CODEC_MAKE_F05(reset, stopok, error, act, set) \
267 ( (((reset) & 0x1) << 10) \
268 | (((stopok) & 0x1) << 9) \
269 | (((error) & 0x1) << 8) \
270 | (((act) & 0x7) << 4) \
271 | ((set) & 0x7))
272#define CODEC_F05_D3COLD (4)
273#define CODEC_F05_D3 (3)
274#define CODEC_F05_D2 (2)
275#define CODEC_F05_D1 (1)
276#define CODEC_F05_D0 (0)
277
278#define CODEC_F05_IS_RESET(value) (((value) & RT_BIT(10)) != 0)
279#define CODEC_F05_IS_STOPOK(value) (((value) & RT_BIT(9)) != 0)
280#define CODEC_F05_IS_ERROR(value) (((value) & RT_BIT(8)) != 0)
281#define CODEC_F05_ACT(value) (((value) & 0x7) >> 4)
282#define CODEC_F05_SET(value) (((value) & 0x7))
283
284#define CODEC_F05_GE(p0, p1) ((p0) <= (p1))
285#define CODEC_F05_LE(p0, p1) ((p0) >= (p1))
286
287/* Pin Widged Control (7.3.3.13) */
288#define CODEC_F07_VREF_HIZ (0)
289#define CODEC_F07_VREF_50 (0x1)
290#define CODEC_F07_VREF_GROUND (0x2)
291#define CODEC_F07_VREF_80 (0x4)
292#define CODEC_F07_VREF_100 (0x5)
293#define CODEC_F07_IN_ENABLE RT_BIT(5)
294#define CODEC_F07_OUT_ENABLE RT_BIT(6)
295#define CODEC_F07_OUT_H_ENABLE RT_BIT(7)
296
297/* Unsolicited enabled (7.3.3.14) */
298#define CODEC_MAKE_F08(enable, tag) ((((enable) & 1) << 7) | ((tag) & 0x3F))
299
300/* Converter formats (7.3.3.8) and (3.7.1) */
301#define CODEC_MAKE_A(fNonPCM, f44_1BaseRate, mult, div, bits, chan) \
302 ( (((fNonPCM) & 0x1) << 15) \
303 | (((f44_1BaseRate) & 0x1) << 14) \
304 | (((mult) & 0x7) << 11) \
305 | (((div) & 0x7) << 8) \
306 | (((bits) & 0x7) << 4) \
307 | ((chan) & 0xF))
308
309#define CODEC_A_MULT_1X (0)
310#define CODEC_A_MULT_2X (1)
311#define CODEC_A_MULT_3X (2)
312#define CODEC_A_MULT_4X (3)
313
314#define CODEC_A_DIV_1X (0)
315#define CODEC_A_DIV_2X (1)
316#define CODEC_A_DIV_3X (2)
317#define CODEC_A_DIV_4X (3)
318#define CODEC_A_DIV_5X (4)
319#define CODEC_A_DIV_6X (5)
320#define CODEC_A_DIV_7X (6)
321#define CODEC_A_DIV_8X (7)
322
323#define CODEC_A_8_BIT (0)
324#define CODEC_A_16_BIT (1)
325#define CODEC_A_20_BIT (2)
326#define CODEC_A_24_BIT (3)
327#define CODEC_A_32_BIT (4)
328
329/* Pin Sense (7.3.3.15) */
330#define CODEC_MAKE_F09_ANALOG(fPresent, impedance) \
331( (((fPresent) & 0x1) << 31) \
332 | (((impedance) & 0x7FFFFFFF)))
333#define CODEC_F09_ANALOG_NA 0x7FFFFFFF
334#define CODEC_MAKE_F09_DIGITAL(fPresent, fELDValid) \
335( (((fPresent) & 0x1) << 31) \
336 | (((fELDValid) & 0x1) << 30))
337
338#define CODEC_MAKE_F0C(lrswap, eapd, btl) ((((lrswap) & 1) << 2) | (((eapd) & 1) << 1) | ((btl) & 1))
339#define CODEC_FOC_IS_LRSWAP(f0c) RT_BOOL((f0c) & RT_BIT(2))
340#define CODEC_FOC_IS_EAPD(f0c) RT_BOOL((f0c) & RT_BIT(1))
341#define CODEC_FOC_IS_BTL(f0c) RT_BOOL((f0c) & RT_BIT(0))
342/* HDA spec 7.3.3.31 defines layout of configuration registers/verbs (0xF1C) */
343/* Configuration's port connection */
344#define CODEC_F1C_PORT_MASK (0x3)
345#define CODEC_F1C_PORT_SHIFT (30)
346
347#define CODEC_F1C_PORT_COMPLEX (0x0)
348#define CODEC_F1C_PORT_NO_PHYS (0x1)
349#define CODEC_F1C_PORT_FIXED (0x2)
350#define CODEC_F1C_BOTH (0x3)
351
352/* Configuration's location */
353#define CODEC_F1C_LOCATION_MASK (0x3F)
354#define CODEC_F1C_LOCATION_SHIFT (24)
355/* [4:5] bits of location region means chassis attachment */
356#define CODEC_F1C_LOCATION_PRIMARY_CHASSIS (0)
357#define CODEC_F1C_LOCATION_INTERNAL RT_BIT(4)
358#define CODEC_F1C_LOCATION_SECONDRARY_CHASSIS RT_BIT(5)
359#define CODEC_F1C_LOCATION_OTHER (RT_BIT(5))
360
361/* [0:3] bits of location region means geometry location attachment */
362#define CODEC_F1C_LOCATION_NA (0)
363#define CODEC_F1C_LOCATION_REAR (0x1)
364#define CODEC_F1C_LOCATION_FRONT (0x2)
365#define CODEC_F1C_LOCATION_LEFT (0x3)
366#define CODEC_F1C_LOCATION_RIGTH (0x4)
367#define CODEC_F1C_LOCATION_TOP (0x5)
368#define CODEC_F1C_LOCATION_BOTTOM (0x6)
369#define CODEC_F1C_LOCATION_SPECIAL_0 (0x7)
370#define CODEC_F1C_LOCATION_SPECIAL_1 (0x8)
371#define CODEC_F1C_LOCATION_SPECIAL_2 (0x9)
372
373/* Configuration's devices */
374#define CODEC_F1C_DEVICE_MASK (0xF)
375#define CODEC_F1C_DEVICE_SHIFT (20)
376#define CODEC_F1C_DEVICE_LINE_OUT (0)
377#define CODEC_F1C_DEVICE_SPEAKER (0x1)
378#define CODEC_F1C_DEVICE_HP (0x2)
379#define CODEC_F1C_DEVICE_CD (0x3)
380#define CODEC_F1C_DEVICE_SPDIF_OUT (0x4)
381#define CODEC_F1C_DEVICE_DIGITAL_OTHER_OUT (0x5)
382#define CODEC_F1C_DEVICE_MODEM_LINE_SIDE (0x6)
383#define CODEC_F1C_DEVICE_MODEM_HANDSET_SIDE (0x7)
384#define CODEC_F1C_DEVICE_LINE_IN (0x8)
385#define CODEC_F1C_DEVICE_AUX (0x9)
386#define CODEC_F1C_DEVICE_MIC (0xA)
387#define CODEC_F1C_DEVICE_PHONE (0xB)
388#define CODEC_F1C_DEVICE_SPDIF_IN (0xC)
389#define CODEC_F1C_DEVICE_RESERVED (0xE)
390#define CODEC_F1C_DEVICE_OTHER (0xF)
391
392/* Configuration's Connection type */
393#define CODEC_F1C_CONNECTION_TYPE_MASK (0xF)
394#define CODEC_F1C_CONNECTION_TYPE_SHIFT (16)
395
396#define CODEC_F1C_CONNECTION_TYPE_UNKNOWN (0)
397#define CODEC_F1C_CONNECTION_TYPE_1_8INCHES (0x1)
398#define CODEC_F1C_CONNECTION_TYPE_1_4INCHES (0x2)
399#define CODEC_F1C_CONNECTION_TYPE_ATAPI (0x3)
400#define CODEC_F1C_CONNECTION_TYPE_RCA (0x4)
401#define CODEC_F1C_CONNECTION_TYPE_OPTICAL (0x5)
402#define CODEC_F1C_CONNECTION_TYPE_OTHER_DIGITAL (0x6)
403#define CODEC_F1C_CONNECTION_TYPE_ANALOG (0x7)
404#define CODEC_F1C_CONNECTION_TYPE_DIN (0x8)
405#define CODEC_F1C_CONNECTION_TYPE_XLR (0x9)
406#define CODEC_F1C_CONNECTION_TYPE_RJ_11 (0xA)
407#define CODEC_F1C_CONNECTION_TYPE_COMBO (0xB)
408#define CODEC_F1C_CONNECTION_TYPE_OTHER (0xF)
409
410/* Configuration's color */
411#define CODEC_F1C_COLOR_MASK (0xF)
412#define CODEC_F1C_COLOR_SHIFT (12)
413#define CODEC_F1C_COLOR_UNKNOWN (0)
414#define CODEC_F1C_COLOR_BLACK (0x1)
415#define CODEC_F1C_COLOR_GREY (0x2)
416#define CODEC_F1C_COLOR_BLUE (0x3)
417#define CODEC_F1C_COLOR_GREEN (0x4)
418#define CODEC_F1C_COLOR_RED (0x5)
419#define CODEC_F1C_COLOR_ORANGE (0x6)
420#define CODEC_F1C_COLOR_YELLOW (0x7)
421#define CODEC_F1C_COLOR_PURPLE (0x8)
422#define CODEC_F1C_COLOR_PINK (0x9)
423#define CODEC_F1C_COLOR_RESERVED_0 (0xA)
424#define CODEC_F1C_COLOR_RESERVED_1 (0xB)
425#define CODEC_F1C_COLOR_RESERVED_2 (0xC)
426#define CODEC_F1C_COLOR_RESERVED_3 (0xD)
427#define CODEC_F1C_COLOR_WHITE (0xE)
428#define CODEC_F1C_COLOR_OTHER (0xF)
429
430/* Configuration's misc */
431#define CODEC_F1C_MISC_MASK (0xF)
432#define CODEC_F1C_MISC_SHIFT (8)
433#define CODEC_F1C_MISC_JACK_DETECT (0)
434#define CODEC_F1C_MISC_RESERVED_0 (1)
435#define CODEC_F1C_MISC_RESERVED_1 (2)
436#define CODEC_F1C_MISC_RESERVED_2 (3)
437
438/* Configuration's association */
439#define CODEC_F1C_ASSOCIATION_MASK (0xF)
440#define CODEC_F1C_ASSOCIATION_SHIFT (4)
441/* Connection's sequence */
442#define CODEC_F1C_SEQ_MASK (0xF)
443#define CODEC_F1C_SEQ_SHIFT (0)
444
445/* Implementation identification (7.3.3.30) */
446#define CODEC_MAKE_F20(bmid, bsku, aid) \
447 ( (((bmid) & 0xFFFF) << 16) \
448 | (((bsku) & 0xFF) << 8) \
449 | (((aid) & 0xFF)) \
450 )
451
452/* macro definition helping in filling the configuration registers. */
453#define CODEC_MAKE_F1C(port_connectivity, location, device, connection_type, color, misc, association, sequence) \
454 ( ((port_connectivity) << CODEC_F1C_PORT_SHIFT) \
455 | ((location) << CODEC_F1C_LOCATION_SHIFT) \
456 | ((device) << CODEC_F1C_DEVICE_SHIFT) \
457 | ((connection_type) << CODEC_F1C_CONNECTION_TYPE_SHIFT) \
458 | ((color) << CODEC_F1C_COLOR_SHIFT) \
459 | ((misc) << CODEC_F1C_MISC_SHIFT) \
460 | ((association) << CODEC_F1C_ASSOCIATION_SHIFT) \
461 | ((sequence)))
462
463
464/*******************************************************************************
465* Structures and Typedefs *
466*******************************************************************************/
467/** The F00 parameter length (in dwords). */
468#define CODECNODE_F00_PARAM_LENGTH 20
469/** The F02 parameter length (in dwords). */
470#define CODECNODE_F02_PARAM_LENGTH 16
471
472/**
473 * Common (or core) codec node structure.
474 */
475typedef struct CODECCOMMONNODE
476{
477 /** Node id - 7 bit format */
478 uint8_t id;
479 /** The node name. */
480 char const *pszName;
481 /* PRM 5.3.6 */
482 uint32_t au32F00_param[CODECNODE_F00_PARAM_LENGTH];
483 uint32_t au32F02_param[CODECNODE_F02_PARAM_LENGTH];
484} CODECCOMMONNODE;
485typedef CODECCOMMONNODE *PCODECCOMMONNODE;
486AssertCompile(CODECNODE_F00_PARAM_LENGTH == 20); /* saved state */
487AssertCompile(CODECNODE_F02_PARAM_LENGTH == 16); /* saved state */
488
489/**
490 * Compile time assertion on the expected node size.
491 */
492#define AssertNodeSize(a_Node, a_cParams) \
493 AssertCompile((a_cParams) <= (60 + 6)); /* the max size - saved state */ \
494 AssertCompile( sizeof(a_Node) - sizeof(CODECCOMMONNODE) \
495 == (((a_cParams) * sizeof(uint32_t) + sizeof(void *) - 1) & ~(sizeof(void *) - 1)) )
496
497typedef struct ROOTCODECNODE
498{
499 CODECCOMMONNODE node;
500} ROOTCODECNODE, *PROOTCODECNODE;
501AssertNodeSize(ROOTCODECNODE, 0);
502
503#define AMPLIFIER_SIZE 60
504typedef uint32_t AMPLIFIER[AMPLIFIER_SIZE];
505#define AMPLIFIER_IN 0
506#define AMPLIFIER_OUT 1
507#define AMPLIFIER_LEFT 1
508#define AMPLIFIER_RIGHT 0
509#define AMPLIFIER_REGISTER(amp, inout, side, index) ((amp)[30*(inout) + 15*(side) + (index)])
510typedef struct DACNODE
511{
512 CODECCOMMONNODE node;
513 uint32_t u32F0d_param;
514 uint32_t u32F04_param;
515 uint32_t u32F05_param;
516 uint32_t u32F06_param;
517 uint32_t u32F0c_param;
518
519 uint32_t u32A_param;
520 AMPLIFIER B_params;
521
522} DACNODE, *PDACNODE;
523AssertNodeSize(DACNODE, 6 + 60);
524
525typedef struct ADCNODE
526{
527 CODECCOMMONNODE node;
528 uint32_t u32F03_param;
529 uint32_t u32F05_param;
530 uint32_t u32F06_param;
531 uint32_t u32F09_param;
532
533 uint32_t u32A_param;
534 uint32_t u32F01_param;
535 AMPLIFIER B_params;
536} ADCNODE, *PADCNODE;
537AssertNodeSize(DACNODE, 6 + 60);
538
539typedef struct SPDIFOUTNODE
540{
541 CODECCOMMONNODE node;
542 uint32_t u32F05_param;
543 uint32_t u32F06_param;
544 uint32_t u32F09_param;
545 uint32_t u32F0d_param;
546
547 uint32_t u32A_param;
548 AMPLIFIER B_params;
549} SPDIFOUTNODE, *PSPDIFOUTNODE;
550AssertNodeSize(SPDIFOUTNODE, 5 + 60);
551
552typedef struct SPDIFINNODE
553{
554 CODECCOMMONNODE node;
555 uint32_t u32F05_param;
556 uint32_t u32F06_param;
557 uint32_t u32F09_param;
558 uint32_t u32F0d_param;
559
560 uint32_t u32A_param;
561 AMPLIFIER B_params;
562} SPDIFINNODE, *PSPDIFINNODE;
563AssertNodeSize(SPDIFINNODE, 5 + 60);
564
565typedef struct AFGCODECNODE
566{
567 CODECCOMMONNODE node;
568 uint32_t u32F05_param;
569 uint32_t u32F08_param;
570 uint32_t u32F20_param;
571 uint32_t u32F17_param;
572} AFGCODECNODE, *PAFGCODECNODE;
573AssertNodeSize(AFGCODECNODE, 4);
574
575typedef struct PORTNODE
576{
577 CODECCOMMONNODE node;
578 uint32_t u32F07_param;
579 uint32_t u32F08_param;
580 uint32_t u32F09_param;
581 uint32_t u32F01_param;
582 uint32_t u32F1c_param;
583 AMPLIFIER B_params;
584} PORTNODE, *PPORTNODE;
585AssertNodeSize(PORTNODE, 5 + 60);
586
587typedef struct DIGOUTNODE
588{
589 CODECCOMMONNODE node;
590 uint32_t u32F01_param;
591 uint32_t u32F08_param;
592 uint32_t u32F07_param;
593 uint32_t u32F09_param;
594 uint32_t u32F1c_param;
595} DIGOUTNODE, *PDIGOUTNODE;
596AssertNodeSize(DIGOUTNODE, 5);
597
598typedef struct DIGINNODE
599{
600 CODECCOMMONNODE node;
601 uint32_t u32F05_param;
602 uint32_t u32F07_param;
603 uint32_t u32F08_param;
604 uint32_t u32F09_param;
605 uint32_t u32F0c_param;
606 uint32_t u32F1c_param;
607 uint32_t u32F1e_param;
608} DIGINNODE, *PDIGINNODE;
609AssertNodeSize(DIGINNODE, 7);
610
611typedef struct ADCMUXNODE
612{
613 CODECCOMMONNODE node;
614 uint32_t u32F01_param;
615
616 uint32_t u32A_param;
617 AMPLIFIER B_params;
618} ADCMUXNODE, *PADCMUXNODE;
619AssertNodeSize(ADCMUXNODE, 2 + 60);
620
621typedef struct PCBEEPNODE
622{
623 CODECCOMMONNODE node;
624 uint32_t u32F07_param;
625 uint32_t u32F0a_param;
626
627 uint32_t u32A_param;
628 AMPLIFIER B_params;
629 uint32_t u32F1c_param;
630} PCBEEPNODE, *PPCBEEPNODE;
631AssertNodeSize(PCBEEPNODE, 3 + 60 + 1);
632
633typedef struct CDNODE
634{
635 CODECCOMMONNODE node;
636 uint32_t u32F07_param;
637 uint32_t u32F1c_param;
638} CDNODE, *PCDNODE;
639AssertNodeSize(CDNODE, 2);
640
641typedef struct VOLUMEKNOBNODE
642{
643 CODECCOMMONNODE node;
644 uint32_t u32F08_param;
645 uint32_t u32F0f_param;
646} VOLUMEKNOBNODE, *PVOLUMEKNOBNODE;
647AssertNodeSize(VOLUMEKNOBNODE, 2);
648
649typedef struct ADCVOLNODE
650{
651 CODECCOMMONNODE node;
652 uint32_t u32F0c_param;
653 uint32_t u32F01_param;
654 uint32_t u32A_params;
655 AMPLIFIER B_params;
656} ADCVOLNODE, *PADCVOLNODE;
657AssertNodeSize(ADCVOLNODE, 3 + 60);
658
659typedef struct RESNODE
660{
661 CODECCOMMONNODE node;
662 uint32_t u32F05_param;
663 uint32_t u32F06_param;
664 uint32_t u32F07_param;
665 uint32_t u32F1c_param;
666} RESNODE, *PRESNODE;
667AssertNodeSize(RESNODE, 4);
668
669/**
670 * Used for the saved state.
671 */
672typedef struct CODECSAVEDSTATENODE
673{
674 CODECCOMMONNODE Core;
675 uint32_t au32Params[60 + 6];
676} CODECSAVEDSTATENODE;
677AssertNodeSize(CODECSAVEDSTATENODE, 60 + 6);
678
679typedef union CODECNODE
680{
681 CODECCOMMONNODE node;
682 ROOTCODECNODE root;
683 AFGCODECNODE afg;
684 DACNODE dac;
685 ADCNODE adc;
686 SPDIFOUTNODE spdifout;
687 SPDIFINNODE spdifin;
688 PORTNODE port;
689 DIGOUTNODE digout;
690 DIGINNODE digin;
691 ADCMUXNODE adcmux;
692 PCBEEPNODE pcbeep;
693 CDNODE cdnode;
694 VOLUMEKNOBNODE volumeKnob;
695 ADCVOLNODE adcvol;
696 RESNODE reserved;
697 CODECSAVEDSTATENODE SavedState;
698} CODECNODE, *PCODECNODE;
699AssertNodeSize(CODECNODE, 60 + 6);
700/*******************************************************************************
701* Global Variables *
702*******************************************************************************/
703/* STAC9220 - Referenced thru STAC9220WIDGET in the constructor below. */
704static uint8_t const g_abStac9220Ports[] = { 0x0A, 0xB, 0xC, 0xD, 0xE, 0xF, 0};
705static uint8_t const g_abStac9220Dacs[] = { 0x02, 0x3, 0x4, 0x5, 0};
706static uint8_t const g_abStac9220Adcs[] = { 0x06, 0x7, 0};
707static uint8_t const g_abStac9220SpdifOuts[] = { 0x08, 0 };
708static uint8_t const g_abStac9220SpdifIns[] = { 0x09, 0 };
709static uint8_t const g_abStac9220DigOutPins[] = { 0x10, 0 };
710static uint8_t const g_abStac9220DigInPins[] = { 0x11, 0 };
711static uint8_t const g_abStac9220AdcVols[] = { 0x17, 0x18, 0};
712static uint8_t const g_abStac9220AdcMuxs[] = { 0x12, 0x13, 0};
713static uint8_t const g_abStac9220Pcbeeps[] = { 0x14, 0 };
714static uint8_t const g_abStac9220Cds[] = { 0x15, 0 };
715static uint8_t const g_abStac9220VolKnobs[] = { 0x16, 0 };
716static uint8_t const g_abStac9220Reserveds[] = { 0x09, 0x19, 0x1a, 0x1b, 0 };
717
718
719/** SSM description of a CODECNODE. */
720static SSMFIELD const g_aCodecNodeFields[] =
721{
722 SSMFIELD_ENTRY( CODECSAVEDSTATENODE, Core.id),
723 SSMFIELD_ENTRY_PAD_HC_AUTO(3, 3),
724 SSMFIELD_ENTRY( CODECSAVEDSTATENODE, Core.au32F00_param),
725 SSMFIELD_ENTRY( CODECSAVEDSTATENODE, Core.au32F02_param),
726 SSMFIELD_ENTRY( CODECSAVEDSTATENODE, au32Params),
727 SSMFIELD_ENTRY_TERM()
728};
729
730/** Backward compatibility with v1 of the CODECNODE. */
731static SSMFIELD const g_aCodecNodeFieldsV1[] =
732{
733 SSMFIELD_ENTRY( CODECSAVEDSTATENODE, Core.id),
734 SSMFIELD_ENTRY_PAD_HC_AUTO(3, 7),
735 SSMFIELD_ENTRY_OLD_HCPTR(Core.name),
736 SSMFIELD_ENTRY( CODECSAVEDSTATENODE, Core.au32F00_param),
737 SSMFIELD_ENTRY( CODECSAVEDSTATENODE, Core.au32F02_param),
738 SSMFIELD_ENTRY( CODECSAVEDSTATENODE, au32Params),
739 SSMFIELD_ENTRY_TERM()
740};
741
742
743
744
745static int stac9220ResetNode(PHDACODEC pThis, uint8_t nodenum, PCODECNODE pNode)
746{
747 pNode->node.id = nodenum;
748 pNode->node.au32F00_param[0xF] = 0; /* Power statest Supported: are the same as AFG reports */
749 switch (nodenum)
750 {
751 /* Root Node*/
752 case 0:
753 pNode->node.au32F00_param[0x02] = CODEC_MAKE_F00_02(0x1, 0x0, 0x34, 0x1); /* rev id */
754 break;
755 case 1:
756 pNode->node.au32F00_param[0x08] = CODEC_MAKE_F00_08(1, 0xd, 0xd);
757 pNode->node.au32F00_param[0x0C] = CODEC_MAKE_F00_0C(0x17)
758 | CODEC_F00_0C_CAP_BALANCED_IO
759 | CODEC_F00_0C_CAP_INPUT
760 | CODEC_F00_0C_CAP_PRESENSE_DETECT
761 | CODEC_F00_0C_CAP_TRIGGER_REQUIRED
762 | CODEC_F00_0C_CAP_IMPENDANCE_SENSE;//(17 << 8)|RT_BIT(6)|RT_BIT(5)|RT_BIT(2)|RT_BIT(1)|RT_BIT(0);
763 pNode->node.au32F00_param[0x0B] = CODEC_F00_0B_PCM;
764 pNode->node.au32F00_param[0x0D] = CODEC_MAKE_F00_0D(1, 0x5, 0xE, 0);//RT_BIT(31)|(0x5 << 16)|(0xE)<<8;
765 pNode->node.au32F00_param[0x12] = RT_BIT(31)|(0x2 << 16)|(0x7f << 8)|0x7f;
766 pNode->node.au32F00_param[0x11] = CODEC_MAKE_F00_11(1, 1, 0, 0, 4);//0xc0000004;
767 pNode->node.au32F00_param[0x0F] = CODEC_F00_0F_D3|CODEC_F00_0F_D2|CODEC_F00_0F_D1|CODEC_F00_0F_D0;
768 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 */
769 pNode->afg.u32F08_param = 0;
770 pNode->afg.u32F17_param = 0;
771 break;
772 case 2:
773 case 3:
774 case 4:
775 case 5:
776 memset(pNode->dac.B_params, 0, AMPLIFIER_SIZE);
777 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 */
778
779 AMPLIFIER_REGISTER(pNode->dac.B_params, AMPLIFIER_OUT, AMPLIFIER_LEFT, 0) = 0x7F | RT_BIT(7);
780 AMPLIFIER_REGISTER(pNode->dac.B_params, AMPLIFIER_OUT, AMPLIFIER_RIGHT, 0) = 0x7F | RT_BIT(7);
781
782 pNode->dac.node.au32F00_param[9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_AUDIO_OUTPUT, 0xD, 0)
783 | CODEC_F00_09_CAP_L_R_SWAP
784 | CODEC_F00_09_CAP_POWER_CTRL
785 | CODEC_F00_09_CAP_OUT_AMP_PRESENT
786 | CODEC_F00_09_CAP_LSB;//(0xD << 16) | RT_BIT(11) | RT_BIT(10) | RT_BIT(2) | RT_BIT(0);
787 pNode->dac.u32F0c_param = 0;
788 pNode->dac.u32F05_param = CODEC_MAKE_F05(0, 0, 0, CODEC_F05_D3, CODEC_F05_D3);//0x3 << 4 | 0x3; /* PS-Act: D3, Set: D3 */
789 break;
790 case 6:
791 pNode->node.au32F02_param[0] = 0x17;
792 goto adc_init;
793 case 7:
794 pNode->node.au32F02_param[0] = 0x18;
795 adc_init:
796 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 */
797 pNode->adc.node.au32F00_param[0xE] = CODEC_MAKE_F00_0E(0, 1);//RT_BIT(0);
798 pNode->adc.u32F03_param = RT_BIT(0);
799 pNode->adc.u32F05_param = CODEC_MAKE_F05(0, 0, 0, CODEC_F05_D3, CODEC_F05_D3);//0x3 << 4 | 0x3; /* PS-Act: D3 Set: D3 */
800 pNode->adc.u32F06_param = 0;
801 pNode->adc.node.au32F00_param[9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_AUDIO_INPUT, 0xD, 0)
802 | CODEC_F00_09_CAP_POWER_CTRL
803 | CODEC_F00_09_CAP_CONNECTION_LIST
804 | CODEC_F00_09_CAP_PROC_WIDGET
805 | CODEC_F00_09_CAP_LSB;//RT_BIT(20)| (0xd << 16) | RT_BIT(10) | RT_BIT(8) | RT_BIT(6)| RT_BIT(0);
806 break;
807 case 8:
808 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;
809 pNode->spdifout.node.au32F00_param[9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_AUDIO_OUTPUT, 0x4, 0)
810 | CODEC_F00_09_CAP_DIGITAL
811 | CODEC_F00_09_CAP_FMT_OVERRIDE
812 | CODEC_F00_09_CAP_LSB;//(4 << 16) | RT_BIT(9)|RT_BIT(4)|0x1;
813 pNode->node.au32F00_param[0xa] = pThis->paNodes[1].node.au32F00_param[0xA];
814 pNode->spdifout.node.au32F00_param[0xB] = CODEC_F00_0B_PCM;
815 pNode->spdifout.u32F06_param = 0;
816 pNode->spdifout.u32F0d_param = 0;
817 break;
818 case 9:
819 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;
820 pNode->spdifin.node.au32F00_param[9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_AUDIO_INPUT, 0x4, 0)
821 | CODEC_F00_09_CAP_DIGITAL
822 | CODEC_F00_09_CAP_CONNECTION_LIST
823 | CODEC_F00_09_CAP_FMT_OVERRIDE
824 | CODEC_F00_09_CAP_LSB;//(0x1 << 20)|(4 << 16) | RT_BIT(9)| RT_BIT(8)|RT_BIT(4)|0x1;
825 pNode->node.au32F00_param[0xA] = pThis->paNodes[1].node.au32F00_param[0xA];
826 pNode->node.au32F00_param[0xE] = CODEC_MAKE_F00_0E(0, 1);//RT_BIT(0);
827 pNode->node.au32F02_param[0] = 0x11;
828 pNode->spdifin.node.au32F00_param[0xB] = CODEC_F00_0B_PCM;
829 pNode->spdifin.u32F06_param = 0;
830 pNode->spdifin.u32F0d_param = 0;
831 break;
832 case 0xA:
833 pNode->node.au32F00_param[0xC] = CODEC_MAKE_F00_0C(0x17)
834 | CODEC_F00_0C_CAP_INPUT
835 | CODEC_F00_0C_CAP_OUTPUT
836 | CODEC_F00_0C_CAP_HP
837 | CODEC_F00_0C_CAP_PRESENSE_DETECT
838 | CODEC_F00_0C_CAP_TRIGGER_REQUIRED
839 | CODEC_F00_0C_CAP_IMPENDANCE_SENSE;//0x173f;
840 pNode->node.au32F02_param[0] = 0x2;
841 pNode->port.u32F07_param = CODEC_F07_IN_ENABLE
842 | CODEC_F07_OUT_ENABLE;
843 pNode->port.u32F08_param = 0;
844 if (!pThis->fInReset)
845 pNode->port.u32F1c_param = CODEC_MAKE_F1C(CODEC_F1C_PORT_COMPLEX,
846 CODEC_F1C_LOCATION_FRONT,
847 CODEC_F1C_DEVICE_HP,
848 CODEC_F1C_CONNECTION_TYPE_1_8INCHES,
849 CODEC_F1C_COLOR_GREEN,
850 CODEC_F1C_MISC_JACK_DETECT,
851 0x2, 0);//RT_MAKE_U32_FROM_U8(0x20, 0x40, 0x21, 0x02);
852 goto port_init;
853 case 0xB:
854 pNode->node.au32F00_param[0xC] = CODEC_MAKE_F00_0C(0x17)
855 | CODEC_F00_0C_CAP_INPUT
856 | CODEC_F00_0C_CAP_OUTPUT
857 | CODEC_F00_0C_CAP_PRESENSE_DETECT
858 | CODEC_F00_0C_CAP_TRIGGER_REQUIRED
859 | CODEC_F00_0C_CAP_IMPENDANCE_SENSE;//0x1737;
860 pNode->node.au32F02_param[0] = 0x4;
861 pNode->port.u32F07_param = CODEC_F07_IN_ENABLE;
862 if (!pThis->fInReset)
863 pNode->port.u32F1c_param = CODEC_MAKE_F1C(CODEC_F1C_PORT_COMPLEX,
864 CODEC_F1C_LOCATION_INTERNAL|CODEC_F1C_LOCATION_REAR,
865 CODEC_F1C_DEVICE_SPEAKER,
866 CODEC_F1C_CONNECTION_TYPE_1_8INCHES,
867 CODEC_F1C_COLOR_BLACK,
868 CODEC_F1C_MISC_JACK_DETECT,
869 0x1, 0x1);//RT_MAKE_U32_FROM_U8(0x11, 0x60, 0x11, 0x01);
870 goto port_init;
871 case 0xC:
872 pNode->node.au32F02_param[0] = 0x3;
873 pNode->node.au32F00_param[0xC] = CODEC_MAKE_F00_0C(0x17)
874 | CODEC_F00_0C_CAP_INPUT
875 | CODEC_F00_0C_CAP_OUTPUT
876 | CODEC_F00_0C_CAP_PRESENSE_DETECT
877 | CODEC_F00_0C_CAP_TRIGGER_REQUIRED
878 | CODEC_F00_0C_CAP_IMPENDANCE_SENSE;//0x1737;
879 pNode->port.u32F07_param = CODEC_F07_IN_ENABLE;
880 if (!pThis->fInReset)
881 pNode->port.u32F1c_param = CODEC_MAKE_F1C(CODEC_F1C_PORT_COMPLEX,
882 CODEC_F1C_LOCATION_REAR,
883 CODEC_F1C_DEVICE_SPEAKER,
884 CODEC_F1C_CONNECTION_TYPE_1_8INCHES,
885 CODEC_F1C_COLOR_GREEN,
886 0x0, 0x1, 0x0);//RT_MAKE_U32_FROM_U8(0x10, 0x40, 0x11, 0x01);
887 goto port_init;
888 case 0xD:
889 pNode->node.au32F00_param[0xC] = CODEC_MAKE_F00_0C(0x17)
890 | CODEC_F00_0C_CAP_INPUT
891 | CODEC_F00_0C_CAP_OUTPUT
892 | CODEC_F00_0C_CAP_PRESENSE_DETECT
893 | CODEC_F00_0C_CAP_TRIGGER_REQUIRED
894 | CODEC_F00_0C_CAP_IMPENDANCE_SENSE;//0x1737;
895 pNode->port.u32F07_param = CODEC_F07_IN_ENABLE;
896 pNode->node.au32F02_param[0] = 0x2;
897 if (!pThis->fInReset)
898 pNode->port.u32F1c_param = CODEC_MAKE_F1C(CODEC_F1C_PORT_COMPLEX,
899 CODEC_F1C_LOCATION_FRONT,
900 CODEC_F1C_DEVICE_MIC,
901 CODEC_F1C_CONNECTION_TYPE_1_8INCHES,
902 CODEC_F1C_COLOR_PINK,
903 0x0, 0x5, 0x0);//RT_MAKE_U32_FROM_U8(0x50, 0x90, 0xA1, 0x02); /* Microphone */
904 port_init:
905 pNode->port.u32F09_param = CODEC_MAKE_F09_ANALOG(1, CODEC_F09_ANALOG_NA);//RT_BIT(31)|0x7fffffff;
906 pNode->port.u32F08_param = 0;
907 pNode->node.au32F00_param[9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_PIN_COMPLEX, 0x0, 0)
908 | CODEC_F00_09_CAP_CONNECTION_LIST
909 | CODEC_F00_09_CAP_UNSOL
910 | CODEC_F00_09_CAP_LSB;//(4 << 20)|RT_BIT(8)|RT_BIT(7)|RT_BIT(0);
911 pNode->node.au32F00_param[0xE] = CODEC_MAKE_F00_0E(0, 1);//0x1;
912 break;
913 case 0xE:
914 pNode->node.au32F00_param[9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_PIN_COMPLEX, 0x0, 0)
915 | CODEC_F00_09_CAP_UNSOL
916 | CODEC_F00_09_CAP_LSB;//(4 << 20)|RT_BIT(7)|RT_BIT(0);
917 pNode->port.u32F08_param = 0;
918 pNode->node.au32F00_param[0xC] = CODEC_F00_0C_CAP_INPUT
919 | CODEC_F00_0C_CAP_OUTPUT
920 | CODEC_F00_0C_CAP_PRESENSE_DETECT;//0x34;
921 pNode->port.u32F07_param = CODEC_F07_IN_ENABLE;
922 pNode->port.u32F09_param = CODEC_MAKE_F09_ANALOG(0, CODEC_F09_ANALOG_NA);//0x7fffffff;
923 if (!pThis->fInReset)
924 pNode->port.u32F1c_param = CODEC_MAKE_F1C(CODEC_F1C_PORT_COMPLEX,
925 CODEC_F1C_LOCATION_REAR,
926 CODEC_F1C_DEVICE_LINE_OUT,
927 CODEC_F1C_CONNECTION_TYPE_1_8INCHES,
928 CODEC_F1C_COLOR_BLUE,
929 0x0, 0x4, 0x0);//0x01013040; /* Line Out */
930 break;
931 case 0xF:
932 pNode->node.au32F00_param[9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_PIN_COMPLEX, 0x0, 0x0)
933 | CODEC_F00_09_CAP_CONNECTION_LIST
934 | CODEC_F00_09_CAP_UNSOL
935 | CODEC_F00_09_CAP_OUT_AMP_PRESENT
936 | CODEC_F00_09_CAP_LSB;//(4 << 20)|RT_BIT(8)|RT_BIT(7)|RT_BIT(2)|RT_BIT(0);
937 pNode->node.au32F00_param[0xC] = CODEC_F00_0C_CAP_INPUT
938 | CODEC_F00_0C_CAP_OUTPUT
939 | CODEC_F00_0C_CAP_PRESENSE_DETECT
940 /* | CODEC_F00_0C_CAP_TRIGGER_REQUIRED
941 | CODEC_F00_0C_CAP_IMPENDANCE_SENSE */;//0x37;
942 pNode->node.au32F00_param[0xE] = CODEC_MAKE_F00_0E(0, 1);//0x1;
943 pNode->port.u32F08_param = 0;
944 pNode->port.u32F07_param = CODEC_F07_OUT_ENABLE
945 | CODEC_F07_IN_ENABLE;
946 if (!pThis->fInReset)
947 pNode->port.u32F1c_param = CODEC_MAKE_F1C(CODEC_F1C_PORT_COMPLEX,
948 CODEC_F1C_LOCATION_INTERNAL,
949 CODEC_F1C_DEVICE_SPEAKER,
950 CODEC_F1C_CONNECTION_TYPE_1_8INCHES,
951 CODEC_F1C_COLOR_ORANGE,
952 0x0, 0x1, 0x2);//RT_MAKE_U32_FROM_U8(0x12, 0x60, 0x11, 0x01);
953 pNode->node.au32F02_param[0] = 0x5;
954 pNode->port.u32F09_param = CODEC_MAKE_F09_ANALOG(0, CODEC_F09_ANALOG_NA);//0x7fffffff;
955 break;
956 case 0x10:
957 pNode->node.au32F00_param[9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_PIN_COMPLEX, 0x0, 0x0)
958 | CODEC_F00_09_CAP_DIGITAL
959 | CODEC_F00_09_CAP_CONNECTION_LIST
960 | CODEC_F00_09_CAP_LSB;//(4<<20)|RT_BIT(9)|RT_BIT(8)|RT_BIT(0);
961 pNode->node.au32F00_param[0xC] = CODEC_F00_0C_CAP_OUTPUT;//RT_BIT(4);
962 pNode->node.au32F00_param[0xE] = CODEC_MAKE_F00_0E(0, 0x3);
963 pNode->node.au32F02_param[0] = RT_MAKE_U32_FROM_U8(0x08, 0x17, 0x19, 0);
964 if (!pThis->fInReset)
965 pNode->digout.u32F1c_param = CODEC_MAKE_F1C(CODEC_F1C_PORT_COMPLEX,
966 CODEC_F1C_LOCATION_REAR,
967 CODEC_F1C_DEVICE_SPDIF_OUT,
968 CODEC_F1C_CONNECTION_TYPE_DIN,
969 CODEC_F1C_COLOR_BLACK,
970 0x0, 0x3, 0x0);//RT_MAKE_U32_FROM_U8(0x30, 0x10, 0x45, 0x01);
971 break;
972 case 0x11:
973 pNode->node.au32F00_param[9] = (4 << 20) | (3 << 16) | RT_BIT(10) | RT_BIT(9) | RT_BIT(7) | RT_BIT(0);
974 pNode->node.au32F00_param[0xC] = CODEC_F00_0C_CAP_EAPD
975 | CODEC_F00_0C_CAP_INPUT
976 | CODEC_F00_0C_CAP_PRESENSE_DETECT;//RT_BIT(16)| RT_BIT(5)|RT_BIT(2);
977 pNode->digin.u32F05_param = CODEC_MAKE_F05(0, 0, 0, CODEC_F05_D3, CODEC_F05_D3);//0x3 << 4 | 0x3; /* PS-Act: D3 -> D3 */
978 pNode->digin.u32F07_param = 0;
979 pNode->digin.u32F08_param = 0;
980 pNode->digin.u32F09_param = 0;
981 pNode->digin.u32F0c_param = 0;
982 if (!pThis->fInReset)
983 pNode->digin.u32F1c_param = CODEC_MAKE_F1C(CODEC_F1C_PORT_COMPLEX,
984 CODEC_F1C_LOCATION_REAR,
985 CODEC_F1C_DEVICE_SPDIF_IN,
986 CODEC_F1C_CONNECTION_TYPE_OTHER_DIGITAL,
987 CODEC_F1C_COLOR_BLACK,
988 0x0, 0x6, 0x0);//(0x1 << 24) | (0xc5 << 16) | (0x10 << 8) | 0x60;
989 break;
990 case 0x12:
991 pNode->adcmux.u32F01_param = 0;
992 goto adcmux_init;
993 case 0x13:
994 pNode->adcmux.u32F01_param = 1;
995 adcmux_init:
996 pNode->node.au32F00_param[9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_AUDIO_SELECTOR, 0x0, 0)
997 | CODEC_F00_09_CAP_CONNECTION_LIST
998 | CODEC_F00_09_CAP_AMP_FMT_OVERRIDE
999 | CODEC_F00_09_CAP_OUT_AMP_PRESENT
1000 | CODEC_F00_09_CAP_LSB;//(3<<20)|RT_BIT(8)|RT_BIT(3)|RT_BIT(2)|RT_BIT(0);
1001 pNode->node.au32F00_param[0xe] = CODEC_MAKE_F00_0E(0, 0x7);
1002 pNode->node.au32F00_param[0x12] = (0x27 << 16)|(0x4 << 8);
1003 /* STAC 9220 v10 6.21-22.{4,5} both(left and right) out amplefiers inited with 0*/
1004 memset(pNode->adcmux.B_params, 0, AMPLIFIER_SIZE);
1005 pNode->node.au32F02_param[0] = RT_MAKE_U32_FROM_U8(0xe, 0x15, 0xf, 0xb);
1006 pNode->node.au32F02_param[4] = RT_MAKE_U32_FROM_U8(0xc, 0xd, 0xa, 0x0);
1007 break;
1008 case 0x14:
1009 pNode->node.au32F00_param[9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_BEEP_GEN, 0, 0)
1010 | CODEC_F00_09_CAP_AMP_FMT_OVERRIDE
1011 | CODEC_F00_09_CAP_OUT_AMP_PRESENT;//(7 << 20) | RT_BIT(3) | RT_BIT(2);
1012 pNode->node.au32F00_param[0x12] = (0x17 << 16)|(0x3 << 8)| 0x3;
1013 pNode->pcbeep.u32F0a_param = 0;
1014 memset(pNode->pcbeep.B_params, 0, AMPLIFIER_SIZE);
1015 break;
1016 case 0x15:
1017 pNode->node.au32F00_param[0x9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_PIN_COMPLEX, 0, 0)
1018 | CODEC_F00_09_CAP_LSB;//(4 << 20)|RT_BIT(0);
1019 pNode->node.au32F00_param[0xc] = CODEC_F00_0C_CAP_INPUT;//RT_BIT(5);
1020 if (!pThis->fInReset)
1021 pNode->cdnode.u32F1c_param = CODEC_MAKE_F1C(CODEC_F1C_PORT_FIXED,
1022 CODEC_F1C_LOCATION_INTERNAL,
1023 CODEC_F1C_DEVICE_CD,
1024 CODEC_F1C_CONNECTION_TYPE_ATAPI,
1025 CODEC_F1C_COLOR_UNKNOWN,
1026 0x0, 0x7, 0x0);//RT_MAKE_U32_FROM_U8(0x70, 0x0, 0x33, 0x90);
1027 break;
1028 case 0x16:
1029 pNode->node.au32F00_param[0x9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_VOLUME_KNOB, 0x0, 0x0);//(0x6 << 20);
1030 pNode->node.au32F00_param[0x13] = RT_BIT(7)| 0x7F;
1031 pNode->node.au32F00_param[0xe] = CODEC_MAKE_F00_0E(0, 0x4);
1032 pNode->node.au32F02_param[0] = RT_MAKE_U32_FROM_U8(0x2, 0x3, 0x4, 0x5);
1033 pNode->volumeKnob.u32F08_param = 0;
1034 pNode->volumeKnob.u32F0f_param = 0x7f;
1035 break;
1036 case 0x17:
1037 pNode->node.au32F02_param[0] = 0x12;
1038 goto adcvol_init;
1039 case 0x18:
1040 pNode->node.au32F02_param[0] = 0x13;
1041 adcvol_init:
1042 memset(pNode->adcvol.B_params, 0, AMPLIFIER_SIZE);
1043
1044 pNode->node.au32F00_param[0x9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_AUDIO_SELECTOR, 0, 0)
1045 | CODEC_F00_09_CAP_L_R_SWAP
1046 | CODEC_F00_09_CAP_CONNECTION_LIST
1047 | CODEC_F00_09_CAP_IN_AMP_PRESENT
1048 | CODEC_F00_09_CAP_LSB;//(0x3 << 20)|RT_BIT(11)|RT_BIT(8)|RT_BIT(1)|RT_BIT(0);
1049 pNode->node.au32F00_param[0xe] = CODEC_MAKE_F00_0E(0, 0x1);
1050 AMPLIFIER_REGISTER(pNode->adcvol.B_params, AMPLIFIER_IN, AMPLIFIER_LEFT, 0) = RT_BIT(7);
1051 AMPLIFIER_REGISTER(pNode->adcvol.B_params, AMPLIFIER_IN, AMPLIFIER_RIGHT, 0) = RT_BIT(7);
1052 pNode->adcvol.u32F0c_param = 0;
1053 break;
1054 case 0x19:
1055 pNode->node.au32F00_param[0x9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_VENDOR_DEFINED, 0x3, 0)
1056 | CODEC_F00_09_CAP_DIGITAL
1057 | CODEC_F00_09_CAP_LSB;//(0xF << 20)|(0x3 << 16)|RT_BIT(9)|RT_BIT(0);
1058 break;
1059 case 0x1A:
1060 pNode->node.au32F00_param[0x9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_AUDIO_OUTPUT, 0x3, 0)
1061 | CODEC_F00_09_CAP_DIGITAL
1062 | CODEC_F00_09_CAP_LSB;//(0x3 << 16)|RT_BIT(9)|RT_BIT(0);
1063 break;
1064 case 0x1B:
1065 pNode->node.au32F00_param[0x9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_PIN_COMPLEX, 0, 0)
1066 | CODEC_F00_09_CAP_DIGITAL
1067 | CODEC_F00_09_CAP_CONNECTION_LIST
1068 | CODEC_F00_09_CAP_LSB;//(0x4 << 20)|RT_BIT(9)|RT_BIT(8)|RT_BIT(0);
1069 pNode->node.au32F00_param[0xE] = CODEC_MAKE_F00_0E(0, 0x1);
1070 pNode->node.au32F00_param[0xC] = CODEC_F00_0C_CAP_OUTPUT;//0x10;
1071 pNode->node.au32F02_param[0] = 0x1a;
1072 pNode->reserved.u32F1c_param = CODEC_MAKE_F1C(CODEC_F1C_PORT_NO_PHYS,
1073 CODEC_F1C_LOCATION_NA,
1074 CODEC_F1C_DEVICE_LINE_OUT,
1075 CODEC_F1C_CONNECTION_TYPE_UNKNOWN,
1076 CODEC_F1C_COLOR_UNKNOWN,
1077 0x0, 0x0, 0xf);//0x4000000f;
1078 break;
1079 default:
1080 break;
1081 }
1082 return VINF_SUCCESS;
1083}
1084
1085
1086static int stac9220Construct(PHDACODEC pThis)
1087{
1088 unconst(pThis->cTotalNodes) = 0x1C;
1089 pThis->pfnCodecNodeReset = stac9220ResetNode;
1090 pThis->u16VendorId = 0x8384;
1091 pThis->u16DeviceId = 0x7680;
1092 pThis->u8BSKU = 0x76;
1093 pThis->u8AssemblyId = 0x80;
1094 pThis->paNodes = (PCODECNODE)RTMemAllocZ(sizeof(CODECNODE) * pThis->cTotalNodes);
1095 if (!pThis->paNodes)
1096 return VERR_NO_MEMORY;
1097 pThis->fInReset = false;
1098#define STAC9220WIDGET(type) pThis->au8##type##s = g_abStac9220##type##s
1099 STAC9220WIDGET(Port);
1100 STAC9220WIDGET(Dac);
1101 STAC9220WIDGET(Adc);
1102 STAC9220WIDGET(AdcVol);
1103 STAC9220WIDGET(AdcMux);
1104 STAC9220WIDGET(Pcbeep);
1105 STAC9220WIDGET(SpdifIn);
1106 STAC9220WIDGET(SpdifOut);
1107 STAC9220WIDGET(DigInPin);
1108 STAC9220WIDGET(DigOutPin);
1109 STAC9220WIDGET(Cd);
1110 STAC9220WIDGET(VolKnob);
1111 STAC9220WIDGET(Reserved);
1112#undef STAC9220WIDGET
1113 unconst(pThis->u8AdcVolsLineIn) = 0x17;
1114 unconst(pThis->u8DacLineOut) = 0x2;
1115
1116 return VINF_SUCCESS;
1117}
1118
1119
1120/*
1121 * Some generic predicate functions.
1122 */
1123
1124#define DECLISNODEOFTYPE(type) \
1125 DECLINLINE(int) hdaCodecIs##type##Node(PHDACODEC pThis, uint8_t cNode) \
1126 { \
1127 Assert(pThis->au8##type##s); \
1128 for (int i = 0; pThis->au8##type##s[i] != 0; ++i) \
1129 if (pThis->au8##type##s[i] == cNode) \
1130 return 1; \
1131 return 0; \
1132 }
1133/* hdaCodecIsPortNode */
1134DECLISNODEOFTYPE(Port)
1135/* hdaCodecIsDacNode */
1136DECLISNODEOFTYPE(Dac)
1137/* hdaCodecIsAdcVolNode */
1138DECLISNODEOFTYPE(AdcVol)
1139/* hdaCodecIsAdcNode */
1140DECLISNODEOFTYPE(Adc)
1141/* hdaCodecIsAdcMuxNode */
1142DECLISNODEOFTYPE(AdcMux)
1143/* hdaCodecIsPcbeepNode */
1144DECLISNODEOFTYPE(Pcbeep)
1145/* hdaCodecIsSpdifOutNode */
1146DECLISNODEOFTYPE(SpdifOut)
1147/* hdaCodecIsSpdifInNode */
1148DECLISNODEOFTYPE(SpdifIn)
1149/* hdaCodecIsDigInPinNode */
1150DECLISNODEOFTYPE(DigInPin)
1151/* hdaCodecIsDigOutPinNode */
1152DECLISNODEOFTYPE(DigOutPin)
1153/* hdaCodecIsCdNode */
1154DECLISNODEOFTYPE(Cd)
1155/* hdaCodecIsVolKnobNode */
1156DECLISNODEOFTYPE(VolKnob)
1157/* hdaCodecIsReservedNode */
1158DECLISNODEOFTYPE(Reserved)
1159
1160
1161/*
1162 * Misc helpers.
1163 */
1164static int hdaCodecToAudVolume(PHDACODEC pThis, AMPLIFIER *pAmp, PDMAUDIOMIXERCTL mt)
1165{
1166 uint32_t dir = AMPLIFIER_OUT;
1167 ENMSOUNDSOURCE enmSrc;
1168 switch (mt)
1169 {
1170 case PDMAUDIOMIXERCTL_PCM:
1171 enmSrc = PO_INDEX;
1172 dir = AMPLIFIER_OUT;
1173 break;
1174 case PDMAUDIOMIXERCTL_LINE_IN:
1175 enmSrc = PI_INDEX;
1176 dir = AMPLIFIER_IN;
1177 break;
1178 default:
1179 AssertMsgFailedReturn(("Invalid mixer control %ld\n", mt), VERR_INVALID_PARAMETER);
1180 break;
1181 }
1182
1183 int mute = AMPLIFIER_REGISTER(*pAmp, dir, AMPLIFIER_LEFT, 0) & RT_BIT(7);
1184 mute |= AMPLIFIER_REGISTER(*pAmp, dir, AMPLIFIER_RIGHT, 0) & RT_BIT(7);
1185 mute >>=7;
1186 mute &= 0x1;
1187 uint8_t lVol = AMPLIFIER_REGISTER(*pAmp, dir, AMPLIFIER_LEFT, 0) & 0x7f;
1188 uint8_t rVol = AMPLIFIER_REGISTER(*pAmp, dir, AMPLIFIER_RIGHT, 0) & 0x7f;
1189
1190 /* The STAC9220 volume controls have 0 to -96dB attenuation range in 128 steps.
1191 * We have 0 to -96dB range in 256 steps. HDA volume setting of 127 must map
1192 * to 255 internally (0dB), while HDA volume setting of 0 (-96dB) should map
1193 * to 1 (rather than zero) internally.
1194 */
1195 lVol = (lVol + 1) * (2 * 255) / 256;
1196 rVol = (rVol + 1) * (2 * 255) / 256;
1197
1198 return pThis->pfnSetVolume(pThis->pHDAState, enmSrc, RT_BOOL(mute), lVol, rVol);
1199}
1200
1201DECLINLINE(void) hdaCodecSetRegister(uint32_t *pu32Reg, uint32_t u32Cmd, uint8_t u8Offset, uint32_t mask)
1202{
1203 Assert((pu32Reg && u8Offset < 32));
1204 *pu32Reg &= ~(mask << u8Offset);
1205 *pu32Reg |= (u32Cmd & mask) << u8Offset;
1206}
1207
1208DECLINLINE(void) hdaCodecSetRegisterU8(uint32_t *pu32Reg, uint32_t u32Cmd, uint8_t u8Offset)
1209{
1210 hdaCodecSetRegister(pu32Reg, u32Cmd, u8Offset, CODEC_VERB_8BIT_DATA);
1211}
1212
1213DECLINLINE(void) hdaCodecSetRegisterU16(uint32_t *pu32Reg, uint32_t u32Cmd, uint8_t u8Offset)
1214{
1215 hdaCodecSetRegister(pu32Reg, u32Cmd, u8Offset, CODEC_VERB_16BIT_DATA);
1216}
1217
1218
1219/*
1220 * Verb processor functions.
1221 */
1222
1223static DECLCALLBACK(int) vrbProcUnimplemented(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
1224{
1225 LogFlowFunc(("cmd(raw:%x: cad:%x, d:%c, nid:%x, verb:%x)\n", cmd,
1226 CODEC_CAD(cmd), CODEC_DIRECT(cmd) ? 'N' : 'Y', CODEC_NID(cmd), CODEC_VERBDATA(cmd)));
1227 *pResp = 0;
1228 return VINF_SUCCESS;
1229}
1230
1231static DECLCALLBACK(int) vrbProcBreak(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
1232{
1233 int rc;
1234 rc = vrbProcUnimplemented(pThis, cmd, pResp);
1235 *pResp |= CODEC_RESPONSE_UNSOLICITED;
1236 return rc;
1237}
1238
1239/* B-- */
1240static DECLCALLBACK(int) vrbProcGetAmplifier(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
1241{
1242 Assert(CODEC_CAD(cmd) == pThis->id);
1243 Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
1244 if (CODEC_NID(cmd) >= pThis->cTotalNodes)
1245 {
1246 LogFlowFunc(("invalid node address %d\n", CODEC_NID(cmd)));
1247 return VINF_SUCCESS;
1248 }
1249 *pResp = 0;
1250 /* HDA spec 7.3.3.7 Note A */
1251 /** @todo: if index out of range response should be 0 */
1252 uint8_t u8Index = CODEC_GET_AMP_DIRECTION(cmd) == AMPLIFIER_OUT? 0 : CODEC_GET_AMP_INDEX(cmd);
1253
1254 PCODECNODE pNode = &pThis->paNodes[CODEC_NID(cmd)];
1255 if (hdaCodecIsDacNode(pThis, CODEC_NID(cmd)))
1256 *pResp = AMPLIFIER_REGISTER(pNode->dac.B_params,
1257 CODEC_GET_AMP_DIRECTION(cmd),
1258 CODEC_GET_AMP_SIDE(cmd),
1259 u8Index);
1260 else if (hdaCodecIsAdcVolNode(pThis, CODEC_NID(cmd)))
1261 *pResp = AMPLIFIER_REGISTER(pNode->adcvol.B_params,
1262 CODEC_GET_AMP_DIRECTION(cmd),
1263 CODEC_GET_AMP_SIDE(cmd),
1264 u8Index);
1265 else if (hdaCodecIsAdcMuxNode(pThis, CODEC_NID(cmd)))
1266 *pResp = AMPLIFIER_REGISTER(pNode->adcmux.B_params,
1267 CODEC_GET_AMP_DIRECTION(cmd),
1268 CODEC_GET_AMP_SIDE(cmd),
1269 u8Index);
1270 else if (hdaCodecIsPcbeepNode(pThis, CODEC_NID(cmd)))
1271 *pResp = AMPLIFIER_REGISTER(pNode->pcbeep.B_params,
1272 CODEC_GET_AMP_DIRECTION(cmd),
1273 CODEC_GET_AMP_SIDE(cmd),
1274 u8Index);
1275 else if (hdaCodecIsPortNode(pThis, CODEC_NID(cmd)))
1276 *pResp = AMPLIFIER_REGISTER(pNode->port.B_params,
1277 CODEC_GET_AMP_DIRECTION(cmd),
1278 CODEC_GET_AMP_SIDE(cmd),
1279 u8Index);
1280 else if (hdaCodecIsAdcNode(pThis, CODEC_NID(cmd)))
1281 *pResp = AMPLIFIER_REGISTER(pNode->adc.B_params,
1282 CODEC_GET_AMP_DIRECTION(cmd),
1283 CODEC_GET_AMP_SIDE(cmd),
1284 u8Index);
1285 else
1286 AssertMsgFailedReturn(("access to fields of %x need to be implemented\n", CODEC_NID(cmd)), VINF_SUCCESS);
1287 return VINF_SUCCESS;
1288}
1289
1290/* 3-- */
1291static DECLCALLBACK(int) vrbProcSetAmplifier(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
1292{
1293 bool fIsLeft = false;
1294 bool fIsRight = false;
1295 bool fIsOut = false;
1296 bool fIsIn = false;
1297 uint8_t u8Index = 0;
1298 Assert(CODEC_CAD(cmd) == pThis->id);
1299 if (CODEC_NID(cmd) >= pThis->cTotalNodes)
1300 {
1301 LogFlowFunc(("invalid node address %d\n", CODEC_NID(cmd)));
1302 return VINF_SUCCESS;
1303 }
1304 *pResp = 0;
1305 PCODECNODE pNode = &pThis->paNodes[CODEC_NID(cmd)];
1306 AMPLIFIER *pAmplifier;
1307 if (hdaCodecIsDacNode(pThis, CODEC_NID(cmd)))
1308 pAmplifier = &pNode->dac.B_params;
1309 else if (hdaCodecIsAdcVolNode(pThis, CODEC_NID(cmd)))
1310 pAmplifier = &pNode->adcvol.B_params;
1311 else if (hdaCodecIsAdcMuxNode(pThis, CODEC_NID(cmd)))
1312 pAmplifier = &pNode->adcmux.B_params;
1313 else if (hdaCodecIsPcbeepNode(pThis, CODEC_NID(cmd)))
1314 pAmplifier = &pNode->pcbeep.B_params;
1315 else if (hdaCodecIsPortNode(pThis, CODEC_NID(cmd)))
1316 pAmplifier = &pNode->port.B_params;
1317 else if (hdaCodecIsAdcNode(pThis, CODEC_NID(cmd)))
1318 pAmplifier = &pNode->adc.B_params;
1319 else
1320 AssertFailedReturn(VINF_SUCCESS);
1321
1322 fIsOut = CODEC_SET_AMP_IS_OUT_DIRECTION(cmd);
1323 fIsIn = CODEC_SET_AMP_IS_IN_DIRECTION(cmd);
1324 fIsRight = CODEC_SET_AMP_IS_RIGHT_SIDE(cmd);
1325 fIsLeft = CODEC_SET_AMP_IS_LEFT_SIDE(cmd);
1326 u8Index = CODEC_SET_AMP_INDEX(cmd);
1327 if ( (!fIsLeft && !fIsRight)
1328 || (!fIsOut && !fIsIn))
1329 return VINF_SUCCESS;
1330 if (fIsIn)
1331 {
1332 if (fIsLeft)
1333 hdaCodecSetRegisterU8(&AMPLIFIER_REGISTER(*pAmplifier, AMPLIFIER_IN, AMPLIFIER_LEFT, u8Index), cmd, 0);
1334 if (fIsRight)
1335 hdaCodecSetRegisterU8(&AMPLIFIER_REGISTER(*pAmplifier, AMPLIFIER_IN, AMPLIFIER_RIGHT, u8Index), cmd, 0);
1336
1337 /** @todo Fix ID of u8AdcVolsLineIn! */
1338 hdaCodecToAudVolume(pThis, pAmplifier, PDMAUDIOMIXERCTL_LINE_IN);
1339 }
1340 if (fIsOut)
1341 {
1342 if (fIsLeft)
1343 hdaCodecSetRegisterU8(&AMPLIFIER_REGISTER(*pAmplifier, AMPLIFIER_OUT, AMPLIFIER_LEFT, u8Index), cmd, 0);
1344 if (fIsRight)
1345 hdaCodecSetRegisterU8(&AMPLIFIER_REGISTER(*pAmplifier, AMPLIFIER_OUT, AMPLIFIER_RIGHT, u8Index), cmd, 0);
1346
1347 /** @todo Fix ID of u8DacLineOut! */
1348 hdaCodecToAudVolume(pThis, pAmplifier, PDMAUDIOMIXERCTL_PCM);
1349 }
1350
1351 return VINF_SUCCESS;
1352}
1353
1354static DECLCALLBACK(int) vrbProcGetParameter(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
1355{
1356 Assert(CODEC_CAD(cmd) == pThis->id);
1357 if (CODEC_NID(cmd) >= pThis->cTotalNodes)
1358 {
1359 LogFlowFunc(("invalid node address %d\n", CODEC_NID(cmd)));
1360 return VINF_SUCCESS;
1361 }
1362 Assert((cmd & CODEC_VERB_8BIT_DATA) < CODECNODE_F00_PARAM_LENGTH);
1363 if ((cmd & CODEC_VERB_8BIT_DATA) >= CODECNODE_F00_PARAM_LENGTH)
1364 {
1365 LogFlowFunc(("invalid F00 parameter %d\n", (cmd & CODEC_VERB_8BIT_DATA)));
1366 return VINF_SUCCESS;
1367 }
1368 *pResp = pThis->paNodes[CODEC_NID(cmd)].node.au32F00_param[cmd & CODEC_VERB_8BIT_DATA];
1369 return VINF_SUCCESS;
1370}
1371
1372/* F01 */
1373static DECLCALLBACK(int) vrbProcGetConSelectCtrl(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
1374{
1375 Assert(CODEC_CAD(cmd) == pThis->id);
1376 Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
1377 if (CODEC_NID(cmd) >= pThis->cTotalNodes)
1378 {
1379 LogFlowFunc(("invalid node address %d\n", CODEC_NID(cmd)));
1380 return VINF_SUCCESS;
1381 }
1382 *pResp = 0;
1383 if (hdaCodecIsAdcMuxNode(pThis, CODEC_NID(cmd)))
1384 *pResp = pThis->paNodes[CODEC_NID(cmd)].adcmux.u32F01_param;
1385 else if (hdaCodecIsDigOutPinNode(pThis, CODEC_NID(cmd)))
1386 *pResp = pThis->paNodes[CODEC_NID(cmd)].digout.u32F01_param;
1387 else if (hdaCodecIsPortNode(pThis, CODEC_NID(cmd)))
1388 *pResp = pThis->paNodes[CODEC_NID(cmd)].port.u32F01_param;
1389 else if (hdaCodecIsAdcNode(pThis, CODEC_NID(cmd)))
1390 *pResp = pThis->paNodes[CODEC_NID(cmd)].adc.u32F01_param;
1391 else if (hdaCodecIsAdcVolNode(pThis, CODEC_NID(cmd)))
1392 *pResp = pThis->paNodes[CODEC_NID(cmd)].adcvol.u32F01_param;
1393 return VINF_SUCCESS;
1394}
1395
1396/* 701 */
1397static DECLCALLBACK(int) vrbProcSetConSelectCtrl(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
1398{
1399 Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
1400 if (CODEC_NID(cmd) >= pThis->cTotalNodes)
1401 {
1402 LogFlowFunc(("invalid node address %d\n", CODEC_NID(cmd)));
1403 return VINF_SUCCESS;
1404 }
1405 *pResp = 0;
1406 uint32_t *pu32Reg;
1407 if (hdaCodecIsAdcMuxNode(pThis, CODEC_NID(cmd)))
1408 pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].adcmux.u32F01_param;
1409 else if (hdaCodecIsDigOutPinNode(pThis, CODEC_NID(cmd)))
1410 pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].digout.u32F01_param;
1411 else if (hdaCodecIsPortNode(pThis, CODEC_NID(cmd)))
1412 pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].port.u32F01_param;
1413 else if (hdaCodecIsAdcNode(pThis, CODEC_NID(cmd)))
1414 pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].adc.u32F01_param;
1415 else if (hdaCodecIsAdcVolNode(pThis, CODEC_NID(cmd)))
1416 pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].adcvol.u32F01_param;
1417 else
1418 AssertFailedReturn(VINF_SUCCESS);
1419 hdaCodecSetRegisterU8(pu32Reg, cmd, 0);
1420 return VINF_SUCCESS;
1421}
1422
1423/* F07 */
1424static DECLCALLBACK(int) vrbProcGetPinCtrl(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
1425{
1426 Assert(CODEC_CAD(cmd) == pThis->id);
1427 Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
1428 if (CODEC_NID(cmd) >= pThis->cTotalNodes)
1429 {
1430 LogFlowFunc(("invalid node address %d\n", CODEC_NID(cmd)));
1431 return VINF_SUCCESS;
1432 }
1433 *pResp = 0;
1434 if (hdaCodecIsPortNode(pThis, CODEC_NID(cmd)))
1435 *pResp = pThis->paNodes[CODEC_NID(cmd)].port.u32F07_param;
1436 else if (hdaCodecIsDigOutPinNode(pThis, CODEC_NID(cmd)))
1437 *pResp = pThis->paNodes[CODEC_NID(cmd)].digout.u32F07_param;
1438 else if (hdaCodecIsDigInPinNode(pThis, CODEC_NID(cmd)))
1439 *pResp = pThis->paNodes[CODEC_NID(cmd)].digin.u32F07_param;
1440 else if (hdaCodecIsCdNode(pThis, CODEC_NID(cmd)))
1441 *pResp = pThis->paNodes[CODEC_NID(cmd)].cdnode.u32F07_param;
1442 else if (hdaCodecIsPcbeepNode(pThis, CODEC_NID(cmd)))
1443 *pResp = pThis->paNodes[CODEC_NID(cmd)].pcbeep.u32F07_param;
1444 else if (hdaCodecIsReservedNode(pThis, CODEC_NID(cmd)))
1445 *pResp = pThis->paNodes[CODEC_NID(cmd)].reserved.u32F07_param;
1446 else
1447 AssertMsgFailed(("Unsupported"));
1448 return VINF_SUCCESS;
1449}
1450
1451/* 707 */
1452static DECLCALLBACK(int) vrbProcSetPinCtrl(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
1453{
1454 Assert(CODEC_CAD(cmd) == pThis->id);
1455 Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
1456 if (CODEC_NID(cmd) >= pThis->cTotalNodes)
1457 {
1458 LogFlowFunc(("invalid node address %d\n", CODEC_NID(cmd)));
1459 return VINF_SUCCESS;
1460 }
1461 *pResp = 0;
1462 uint32_t *pu32Reg;
1463 if (hdaCodecIsPortNode(pThis, CODEC_NID(cmd)))
1464 pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].port.u32F07_param;
1465 else if (hdaCodecIsDigInPinNode(pThis, CODEC_NID(cmd)))
1466 pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].digin.u32F07_param;
1467 else if (hdaCodecIsDigOutPinNode(pThis, CODEC_NID(cmd)))
1468 pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].digout.u32F07_param;
1469 else if (hdaCodecIsCdNode(pThis, CODEC_NID(cmd)))
1470 pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].cdnode.u32F07_param;
1471 else if (hdaCodecIsPcbeepNode(pThis, CODEC_NID(cmd)))
1472 pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].pcbeep.u32F07_param;
1473 else if ( hdaCodecIsReservedNode(pThis, CODEC_NID(cmd))
1474 && CODEC_NID(cmd) == 0x1b)
1475 pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].reserved.u32F07_param;
1476 else
1477 AssertFailedReturn(VINF_SUCCESS);
1478 hdaCodecSetRegisterU8(pu32Reg, cmd, 0);
1479 return VINF_SUCCESS;
1480}
1481
1482/* F08 */
1483static DECLCALLBACK(int) vrbProcGetUnsolicitedEnabled(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
1484{
1485 Assert(CODEC_CAD(cmd) == pThis->id);
1486 Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
1487 if (CODEC_NID(cmd) >= pThis->cTotalNodes)
1488 {
1489 LogFlowFunc(("invalid node address %d\n", CODEC_NID(cmd)));
1490 return VINF_SUCCESS;
1491 }
1492 *pResp = 0;
1493 if (hdaCodecIsPortNode(pThis, CODEC_NID(cmd)))
1494 *pResp = pThis->paNodes[CODEC_NID(cmd)].port.u32F08_param;
1495 else if (hdaCodecIsDigInPinNode(pThis, CODEC_NID(cmd)))
1496 *pResp = pThis->paNodes[CODEC_NID(cmd)].digin.u32F08_param;
1497 else if ((cmd) == 1 /* AFG */)
1498 *pResp = pThis->paNodes[CODEC_NID(cmd)].afg.u32F08_param;
1499 else if (hdaCodecIsVolKnobNode(pThis, CODEC_NID(cmd)))
1500 *pResp = pThis->paNodes[CODEC_NID(cmd)].volumeKnob.u32F08_param;
1501 else if (hdaCodecIsDigOutPinNode(pThis, CODEC_NID(cmd)))
1502 *pResp = pThis->paNodes[CODEC_NID(cmd)].digout.u32F08_param;
1503 else if (hdaCodecIsDigInPinNode(pThis, CODEC_NID(cmd)))
1504 *pResp = pThis->paNodes[CODEC_NID(cmd)].digin.u32F08_param;
1505 else
1506 AssertMsgFailed(("unsupported operation %x on node: %x\n", CODEC_VERB_CMD8(cmd), CODEC_NID(cmd)));
1507 return VINF_SUCCESS;
1508}
1509
1510/* 708 */
1511static DECLCALLBACK(int) vrbProcSetUnsolicitedEnabled(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
1512{
1513 Assert(CODEC_CAD(cmd) == pThis->id);
1514 Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
1515 if (CODEC_NID(cmd) >= pThis->cTotalNodes)
1516 {
1517 LogFlowFunc(("invalid node address %d\n", CODEC_NID(cmd)));
1518 return VINF_SUCCESS;
1519 }
1520 *pResp = 0;
1521 uint32_t *pu32Reg;
1522 if (hdaCodecIsPortNode(pThis, CODEC_NID(cmd)))
1523 pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].port.u32F08_param;
1524 else if (hdaCodecIsDigInPinNode(pThis, CODEC_NID(cmd)))
1525 pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].digin.u32F08_param;
1526 else if (CODEC_NID(cmd) == 1 /* AFG */)
1527 pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].afg.u32F08_param;
1528 else if (hdaCodecIsVolKnobNode(pThis, CODEC_NID(cmd)))
1529 pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].volumeKnob.u32F08_param;
1530 else if (hdaCodecIsDigInPinNode(pThis, CODEC_NID(cmd)))
1531 pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].digin.u32F08_param;
1532 else if (hdaCodecIsDigOutPinNode(pThis, CODEC_NID(cmd)))
1533 pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].digout.u32F08_param;
1534 else
1535 AssertMsgFailedReturn(("unsupported operation %x on node: %x\n", CODEC_VERB_CMD8(cmd), CODEC_NID(cmd)), VINF_SUCCESS);
1536 hdaCodecSetRegisterU8(pu32Reg, cmd, 0);
1537 return VINF_SUCCESS;
1538}
1539
1540/* F09 */
1541static DECLCALLBACK(int) vrbProcGetPinSense(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
1542{
1543 Assert(CODEC_CAD(cmd) == pThis->id);
1544 Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
1545 if (CODEC_NID(cmd) >= pThis->cTotalNodes)
1546 {
1547 LogFlowFunc(("invalid node address %d\n", CODEC_NID(cmd)));
1548 return VINF_SUCCESS;
1549 }
1550 *pResp = 0;
1551 if (hdaCodecIsPortNode(pThis, CODEC_NID(cmd)))
1552 *pResp = pThis->paNodes[CODEC_NID(cmd)].port.u32F09_param;
1553 else if (hdaCodecIsDigInPinNode(pThis, CODEC_NID(cmd)))
1554 *pResp = pThis->paNodes[CODEC_NID(cmd)].digin.u32F09_param;
1555 else
1556 AssertMsgFailed(("unsupported operation %x on node: %x\n", CODEC_VERB_CMD8(cmd), CODEC_NID(cmd)));
1557 return VINF_SUCCESS;
1558}
1559
1560/* 709 */
1561static DECLCALLBACK(int) vrbProcSetPinSense(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
1562{
1563 Assert(CODEC_CAD(cmd) == pThis->id);
1564 Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
1565 if (CODEC_NID(cmd) >= pThis->cTotalNodes)
1566 {
1567 LogFlowFunc(("invalid node address %d\n", CODEC_NID(cmd)));
1568 return VINF_SUCCESS;
1569 }
1570 *pResp = 0;
1571 uint32_t *pu32Reg;
1572 if (hdaCodecIsPortNode(pThis, CODEC_NID(cmd)))
1573 pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].port.u32F09_param;
1574 else if (hdaCodecIsDigInPinNode(pThis, CODEC_NID(cmd)))
1575 pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].digin.u32F09_param;
1576 else
1577 AssertFailedReturn(VINF_SUCCESS);
1578 hdaCodecSetRegisterU8(pu32Reg, cmd, 0);
1579 return VINF_SUCCESS;
1580}
1581
1582static DECLCALLBACK(int) vrbProcGetConnectionListEntry(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
1583{
1584 Assert(CODEC_CAD(cmd) == pThis->id);
1585 Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
1586 *pResp = 0;
1587 if (CODEC_NID(cmd) >= pThis->cTotalNodes)
1588 {
1589 LogFlowFunc(("invalid node address %d\n", CODEC_NID(cmd)));
1590 return VINF_SUCCESS;
1591 }
1592 Assert((cmd & CODEC_VERB_8BIT_DATA) < CODECNODE_F02_PARAM_LENGTH);
1593 if ((cmd & CODEC_VERB_8BIT_DATA) >= CODECNODE_F02_PARAM_LENGTH)
1594 {
1595 LogFlowFunc(("access to invalid F02 index %d\n", (cmd & CODEC_VERB_8BIT_DATA)));
1596 return VINF_SUCCESS;
1597 }
1598 *pResp = pThis->paNodes[CODEC_NID(cmd)].node.au32F02_param[cmd & CODEC_VERB_8BIT_DATA];
1599 return VINF_SUCCESS;
1600}
1601
1602/* F03 */
1603static DECLCALLBACK(int) vrbProcGetProcessingState(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
1604{
1605 Assert(CODEC_CAD(cmd) == pThis->id);
1606 Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
1607 if (CODEC_NID(cmd) >= pThis->cTotalNodes)
1608 {
1609 LogFlowFunc(("invalid node address %d\n", CODEC_NID(cmd)));
1610 return VINF_SUCCESS;
1611 }
1612 *pResp = 0;
1613 if (hdaCodecIsAdcNode(pThis, CODEC_NID(cmd)))
1614 *pResp = pThis->paNodes[CODEC_NID(cmd)].adc.u32F03_param;
1615 return VINF_SUCCESS;
1616}
1617
1618/* 703 */
1619static DECLCALLBACK(int) vrbProcSetProcessingState(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
1620{
1621 Assert(CODEC_CAD(cmd) == pThis->id);
1622 Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
1623 if (CODEC_NID(cmd) >= pThis->cTotalNodes)
1624 {
1625 LogFlowFunc(("invalid node address %d\n", CODEC_NID(cmd)));
1626 return VINF_SUCCESS;
1627 }
1628 *pResp = 0;
1629 if (hdaCodecIsAdcNode(pThis, CODEC_NID(cmd)))
1630 hdaCodecSetRegisterU8(&pThis->paNodes[CODEC_NID(cmd)].adc.u32F03_param, cmd, 0);
1631 return VINF_SUCCESS;
1632}
1633
1634/* F0D */
1635static DECLCALLBACK(int) vrbProcGetDigitalConverter(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
1636{
1637 Assert(CODEC_CAD(cmd) == pThis->id);
1638 Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
1639 if (CODEC_NID(cmd) >= pThis->cTotalNodes)
1640 {
1641 LogFlowFunc(("invalid node address %d\n", CODEC_NID(cmd)));
1642 return VINF_SUCCESS;
1643 }
1644 *pResp = 0;
1645 if (hdaCodecIsSpdifOutNode(pThis, CODEC_NID(cmd)))
1646 *pResp = pThis->paNodes[CODEC_NID(cmd)].spdifout.u32F0d_param;
1647 else if (hdaCodecIsSpdifInNode(pThis, CODEC_NID(cmd)))
1648 *pResp = pThis->paNodes[CODEC_NID(cmd)].spdifin.u32F0d_param;
1649 return VINF_SUCCESS;
1650}
1651
1652static int codecSetDigitalConverter(PHDACODEC pThis, uint32_t cmd, uint8_t u8Offset, uint64_t *pResp)
1653{
1654 Assert(CODEC_CAD(cmd) == pThis->id);
1655 Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
1656 if (CODEC_NID(cmd) >= pThis->cTotalNodes)
1657 {
1658 LogFlowFunc(("invalid node address %d\n", CODEC_NID(cmd)));
1659 return VINF_SUCCESS;
1660 }
1661 *pResp = 0;
1662 if (hdaCodecIsSpdifOutNode(pThis, CODEC_NID(cmd)))
1663 hdaCodecSetRegisterU8(&pThis->paNodes[CODEC_NID(cmd)].spdifout.u32F0d_param, cmd, u8Offset);
1664 else if (hdaCodecIsSpdifInNode(pThis, CODEC_NID(cmd)))
1665 hdaCodecSetRegisterU8(&pThis->paNodes[CODEC_NID(cmd)].spdifin.u32F0d_param, cmd, u8Offset);
1666 return VINF_SUCCESS;
1667}
1668
1669/* 70D */
1670static DECLCALLBACK(int) vrbProcSetDigitalConverter1(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
1671{
1672 return codecSetDigitalConverter(pThis, cmd, 0, pResp);
1673}
1674
1675/* 70E */
1676static DECLCALLBACK(int) vrbProcSetDigitalConverter2(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
1677{
1678 return codecSetDigitalConverter(pThis, cmd, 8, pResp);
1679}
1680
1681/* F20 */
1682static DECLCALLBACK(int) vrbProcGetSubId(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
1683{
1684 Assert(CODEC_CAD(cmd) == pThis->id);
1685 Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
1686 if (CODEC_NID(cmd) >= pThis->cTotalNodes)
1687 {
1688 LogFlowFunc(("invalid node address %d\n", CODEC_NID(cmd)));
1689 return VINF_SUCCESS;
1690 }
1691 if (CODEC_NID(cmd) == 1 /* AFG */)
1692 *pResp = pThis->paNodes[CODEC_NID(cmd)].afg.u32F20_param;
1693 else
1694 *pResp = 0;
1695 return VINF_SUCCESS;
1696}
1697
1698static int codecSetSubIdX(PHDACODEC pThis, uint32_t cmd, uint8_t u8Offset)
1699{
1700 Assert(CODEC_CAD(cmd) == pThis->id);
1701 Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
1702 if (CODEC_NID(cmd) >= pThis->cTotalNodes)
1703 {
1704 LogFlowFunc(("invalid node address %d\n", CODEC_NID(cmd)));
1705 return VINF_SUCCESS;
1706 }
1707 uint32_t *pu32Reg;
1708 if (CODEC_NID(cmd) == 0x1 /* AFG */)
1709 pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].afg.u32F20_param;
1710 else
1711 AssertFailedReturn(VINF_SUCCESS);
1712 hdaCodecSetRegisterU8(pu32Reg, cmd, u8Offset);
1713 return VINF_SUCCESS;
1714}
1715
1716/* 720 */
1717static DECLCALLBACK(int) vrbProcSetSubId0(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
1718{
1719 *pResp = 0;
1720 return codecSetSubIdX(pThis, cmd, 0);
1721}
1722
1723/* 721 */
1724static DECLCALLBACK(int) vrbProcSetSubId1(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
1725{
1726 *pResp = 0;
1727 return codecSetSubIdX(pThis, cmd, 8);
1728}
1729
1730/* 722 */
1731static DECLCALLBACK(int) vrbProcSetSubId2(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
1732{
1733 *pResp = 0;
1734 return codecSetSubIdX(pThis, cmd, 16);
1735}
1736
1737/* 723 */
1738static DECLCALLBACK(int) vrbProcSetSubId3(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
1739{
1740 *pResp = 0;
1741 return codecSetSubIdX(pThis, cmd, 24);
1742}
1743
1744static DECLCALLBACK(int) vrbProcReset(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
1745{
1746 Assert(CODEC_CAD(cmd) == pThis->id);
1747 Assert(CODEC_NID(cmd) == 1 /* AFG */);
1748 if ( CODEC_NID(cmd) == 1 /* AFG */
1749 && pThis->pfnCodecNodeReset)
1750 {
1751 uint8_t i;
1752 LogFlowFunc(("enters reset\n"));
1753 Assert(pThis->pfnCodecNodeReset);
1754 for (i = 0; i < pThis->cTotalNodes; ++i)
1755 {
1756 pThis->pfnCodecNodeReset(pThis, i, &pThis->paNodes[i]);
1757 }
1758 pThis->fInReset = false;
1759 LogFlowFunc(("exits reset\n"));
1760 }
1761 *pResp = 0;
1762 return VINF_SUCCESS;
1763}
1764
1765/* F05 */
1766static DECLCALLBACK(int) vrbProcGetPowerState(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
1767{
1768 Assert(CODEC_CAD(cmd) == pThis->id);
1769 Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
1770 if (CODEC_NID(cmd) >= pThis->cTotalNodes)
1771 {
1772 LogFlowFunc(("invalid node address %d\n", CODEC_NID(cmd)));
1773 return VINF_SUCCESS;
1774 }
1775 *pResp = 0;
1776 if (CODEC_NID(cmd) == 1 /* AFG */)
1777 *pResp = pThis->paNodes[CODEC_NID(cmd)].afg.u32F05_param;
1778 else if (hdaCodecIsDacNode(pThis, CODEC_NID(cmd)))
1779 *pResp = pThis->paNodes[CODEC_NID(cmd)].dac.u32F05_param;
1780 else if (hdaCodecIsDigInPinNode(pThis, CODEC_NID(cmd)))
1781 *pResp = pThis->paNodes[CODEC_NID(cmd)].digin.u32F05_param;
1782 else if (hdaCodecIsAdcNode(pThis, CODEC_NID(cmd)))
1783 *pResp = pThis->paNodes[CODEC_NID(cmd)].adc.u32F05_param;
1784 else if (hdaCodecIsSpdifOutNode(pThis, CODEC_NID(cmd)))
1785 *pResp = pThis->paNodes[CODEC_NID(cmd)].spdifout.u32F05_param;
1786 else if (hdaCodecIsSpdifInNode(pThis, CODEC_NID(cmd)))
1787 *pResp = pThis->paNodes[CODEC_NID(cmd)].spdifin.u32F05_param;
1788 else if (hdaCodecIsReservedNode(pThis, CODEC_NID(cmd)))
1789 *pResp = pThis->paNodes[CODEC_NID(cmd)].reserved.u32F05_param;
1790 return VINF_SUCCESS;
1791}
1792
1793/* 705 */
1794
1795DECLINLINE(void) codecPropogatePowerState(uint32_t *pu32F05_param)
1796{
1797 Assert(pu32F05_param);
1798 if (!pu32F05_param)
1799 return;
1800 bool fReset = CODEC_F05_IS_RESET(*pu32F05_param);
1801 bool fStopOk = CODEC_F05_IS_STOPOK(*pu32F05_param);
1802 uint8_t u8SetPowerState = CODEC_F05_SET(*pu32F05_param);
1803 *pu32F05_param = CODEC_MAKE_F05(fReset, fStopOk, 0, u8SetPowerState, u8SetPowerState);
1804}
1805
1806static DECLCALLBACK(int) vrbProcSetPowerState(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
1807{
1808 Assert(CODEC_CAD(cmd) == pThis->id);
1809 Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
1810 if (CODEC_NID(cmd) >= pThis->cTotalNodes)
1811 {
1812 LogFlowFunc(("invalid node address %d\n", CODEC_NID(cmd)));
1813 return VINF_SUCCESS;
1814 }
1815 *pResp = 0;
1816 uint32_t *pu32Reg;
1817 if (CODEC_NID(cmd) == 1 /* AFG */)
1818 pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].afg.u32F05_param;
1819 else if (hdaCodecIsDacNode(pThis, CODEC_NID(cmd)))
1820 pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].dac.u32F05_param;
1821 else if (hdaCodecIsDigInPinNode(pThis, CODEC_NID(cmd)))
1822 pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].digin.u32F05_param;
1823 else if (hdaCodecIsAdcNode(pThis, CODEC_NID(cmd)))
1824 pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].adc.u32F05_param;
1825 else if (hdaCodecIsSpdifOutNode(pThis, CODEC_NID(cmd)))
1826 pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].spdifout.u32F05_param;
1827 else if (hdaCodecIsSpdifInNode(pThis, CODEC_NID(cmd)))
1828 pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].spdifin.u32F05_param;
1829 else if (hdaCodecIsReservedNode(pThis, CODEC_NID(cmd)))
1830 pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].reserved.u32F05_param;
1831 else
1832 AssertFailedReturn(VINF_SUCCESS);
1833
1834 bool fReset = CODEC_F05_IS_RESET(*pu32Reg);
1835 bool fStopOk = CODEC_F05_IS_STOPOK(*pu32Reg);
1836
1837 if (CODEC_NID(cmd) != 1 /* AFG */)
1838 {
1839 /*
1840 * We shouldn't propogate actual power state, which actual for AFG
1841 */
1842 *pu32Reg = CODEC_MAKE_F05(fReset, fStopOk, 0,
1843 CODEC_F05_ACT(pThis->paNodes[1].afg.u32F05_param),
1844 CODEC_F05_SET(cmd));
1845 }
1846
1847 /* Propagate next power state only if AFG is on or verb modifies AFG power state */
1848 if ( CODEC_NID(cmd) == 1 /* AFG */
1849 || !CODEC_F05_ACT(pThis->paNodes[1].afg.u32F05_param))
1850 {
1851 *pu32Reg = CODEC_MAKE_F05(fReset, fStopOk, 0, CODEC_F05_SET(cmd), CODEC_F05_SET(cmd));
1852 if ( CODEC_NID(cmd) == 1 /* AFG */
1853 && (CODEC_F05_SET(cmd)) == CODEC_F05_D0)
1854 {
1855 /* now we're powered on AFG and may propogate power states on nodes */
1856 const uint8_t *pu8NodeIndex = &pThis->au8Dacs[0];
1857 while (*(++pu8NodeIndex))
1858 codecPropogatePowerState(&pThis->paNodes[*pu8NodeIndex].dac.u32F05_param);
1859
1860 pu8NodeIndex = &pThis->au8Adcs[0];
1861 while (*(++pu8NodeIndex))
1862 codecPropogatePowerState(&pThis->paNodes[*pu8NodeIndex].adc.u32F05_param);
1863
1864 pu8NodeIndex = &pThis->au8DigInPins[0];
1865 while (*(++pu8NodeIndex))
1866 codecPropogatePowerState(&pThis->paNodes[*pu8NodeIndex].digin.u32F05_param);
1867 }
1868 }
1869 return VINF_SUCCESS;
1870}
1871
1872static DECLCALLBACK(int) vrbProcGetStreamId(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
1873{
1874 Assert(CODEC_CAD(cmd) == pThis->id);
1875 Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
1876 if (CODEC_NID(cmd) >= pThis->cTotalNodes)
1877 {
1878 LogFlowFunc(("invalid node address %d\n", CODEC_NID(cmd)));
1879 return VINF_SUCCESS;
1880 }
1881 *pResp = 0;
1882 if (hdaCodecIsDacNode(pThis, CODEC_NID(cmd)))
1883 *pResp = pThis->paNodes[CODEC_NID(cmd)].dac.u32F06_param;
1884 else if (hdaCodecIsAdcNode(pThis, CODEC_NID(cmd)))
1885 *pResp = pThis->paNodes[CODEC_NID(cmd)].adc.u32F06_param;
1886 else if (hdaCodecIsSpdifInNode(pThis, CODEC_NID(cmd)))
1887 *pResp = pThis->paNodes[CODEC_NID(cmd)].spdifin.u32F06_param;
1888 else if (hdaCodecIsSpdifOutNode(pThis, CODEC_NID(cmd)))
1889 *pResp = pThis->paNodes[CODEC_NID(cmd)].spdifout.u32F06_param;
1890 else if (CODEC_NID(cmd) == 0x1A)
1891 *pResp = pThis->paNodes[CODEC_NID(cmd)].reserved.u32F06_param;
1892 return VINF_SUCCESS;
1893}
1894
1895static DECLCALLBACK(int) vrbProcSetStreamId(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
1896{
1897 Assert(CODEC_CAD(cmd) == pThis->id);
1898 Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
1899 if (CODEC_NID(cmd) >= pThis->cTotalNodes)
1900 {
1901 LogFlowFunc(("invalid node address %d\n", CODEC_NID(cmd)));
1902 return VINF_SUCCESS;
1903 }
1904 *pResp = 0;
1905 uint32_t *pu32addr;
1906 if (hdaCodecIsDacNode(pThis, CODEC_NID(cmd)))
1907 pu32addr = &pThis->paNodes[CODEC_NID(cmd)].dac.u32F06_param;
1908 else if (hdaCodecIsAdcNode(pThis, CODEC_NID(cmd)))
1909 pu32addr = &pThis->paNodes[CODEC_NID(cmd)].adc.u32F06_param;
1910 else if (hdaCodecIsSpdifOutNode(pThis, CODEC_NID(cmd)))
1911 pu32addr = &pThis->paNodes[CODEC_NID(cmd)].spdifout.u32F06_param;
1912 else if (hdaCodecIsSpdifInNode(pThis, CODEC_NID(cmd)))
1913 pu32addr = &pThis->paNodes[CODEC_NID(cmd)].spdifin.u32F06_param;
1914 else if (hdaCodecIsReservedNode(pThis, CODEC_NID(cmd)))
1915 pu32addr = &pThis->paNodes[CODEC_NID(cmd)].reserved.u32F06_param;
1916 else
1917 AssertFailedReturn(VINF_SUCCESS);
1918 hdaCodecSetRegisterU8(pu32addr, cmd, 0);
1919 return VINF_SUCCESS;
1920}
1921
1922static DECLCALLBACK(int) vrbProcGetConverterFormat(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
1923{
1924 Assert(CODEC_CAD(cmd) == pThis->id);
1925 Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
1926 if (CODEC_NID(cmd) >= pThis->cTotalNodes)
1927 {
1928 LogFlowFunc(("invalid node address %d\n", CODEC_NID(cmd)));
1929 return VINF_SUCCESS;
1930 }
1931 *pResp = 0;
1932 if (hdaCodecIsDacNode(pThis, CODEC_NID(cmd)))
1933 *pResp = pThis->paNodes[CODEC_NID(cmd)].dac.u32A_param;
1934 else if (hdaCodecIsAdcNode(pThis, CODEC_NID(cmd)))
1935 *pResp = pThis->paNodes[CODEC_NID(cmd)].adc.u32A_param;
1936 else if (hdaCodecIsSpdifOutNode(pThis, CODEC_NID(cmd)))
1937 *pResp = pThis->paNodes[CODEC_NID(cmd)].spdifout.u32A_param;
1938 else if (hdaCodecIsSpdifInNode(pThis, CODEC_NID(cmd)))
1939 *pResp = pThis->paNodes[CODEC_NID(cmd)].spdifin.u32A_param;
1940 return VINF_SUCCESS;
1941}
1942
1943static DECLCALLBACK(int) vrbProcSetConverterFormat(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
1944{
1945 Assert(CODEC_CAD(cmd) == pThis->id);
1946 Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
1947 if (CODEC_NID(cmd) >= pThis->cTotalNodes)
1948 {
1949 LogFlowFunc(("invalid node address %d\n", CODEC_NID(cmd)));
1950 return VINF_SUCCESS;
1951 }
1952 *pResp = 0;
1953 if (hdaCodecIsDacNode(pThis, CODEC_NID(cmd)))
1954 hdaCodecSetRegisterU16(&pThis->paNodes[CODEC_NID(cmd)].dac.u32A_param, cmd, 0);
1955 else if (hdaCodecIsAdcNode(pThis, CODEC_NID(cmd)))
1956 hdaCodecSetRegisterU16(&pThis->paNodes[CODEC_NID(cmd)].adc.u32A_param, cmd, 0);
1957 else if (hdaCodecIsSpdifOutNode(pThis, CODEC_NID(cmd)))
1958 hdaCodecSetRegisterU16(&pThis->paNodes[CODEC_NID(cmd)].spdifout.u32A_param, cmd, 0);
1959 else if (hdaCodecIsSpdifInNode(pThis, CODEC_NID(cmd)))
1960 hdaCodecSetRegisterU16(&pThis->paNodes[CODEC_NID(cmd)].spdifin.u32A_param, cmd, 0);
1961 return VINF_SUCCESS;
1962}
1963
1964/* F0C */
1965static DECLCALLBACK(int) vrbProcGetEAPD_BTLEnabled(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
1966{
1967 Assert(CODEC_CAD(cmd) == pThis->id);
1968 Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
1969 if (CODEC_NID(cmd) >= pThis->cTotalNodes)
1970 {
1971 LogFlowFunc(("invalid node address %d\n", CODEC_NID(cmd)));
1972 return VINF_SUCCESS;
1973 }
1974 *pResp = 0;
1975 if (hdaCodecIsAdcVolNode(pThis, CODEC_NID(cmd)))
1976 *pResp = pThis->paNodes[CODEC_NID(cmd)].adcvol.u32F0c_param;
1977 else if (hdaCodecIsDacNode(pThis, CODEC_NID(cmd)))
1978 *pResp = pThis->paNodes[CODEC_NID(cmd)].dac.u32F0c_param;
1979 else if (hdaCodecIsDigInPinNode(pThis, CODEC_NID(cmd)))
1980 *pResp = pThis->paNodes[CODEC_NID(cmd)].digin.u32F0c_param;
1981 return VINF_SUCCESS;
1982}
1983
1984/* 70C */
1985static DECLCALLBACK(int) vrbProcSetEAPD_BTLEnabled(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
1986{
1987 Assert(CODEC_CAD(cmd) == pThis->id);
1988 Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
1989 if (CODEC_NID(cmd) >= pThis->cTotalNodes)
1990 {
1991 LogFlowFunc(("invalid node address %d\n", CODEC_NID(cmd)));
1992 return VINF_SUCCESS;
1993 }
1994
1995 *pResp = 0;
1996 uint32_t *pu32Reg;
1997 if (hdaCodecIsAdcVolNode(pThis, CODEC_NID(cmd)))
1998 pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].adcvol.u32F0c_param;
1999 else if (hdaCodecIsDacNode(pThis, CODEC_NID(cmd)))
2000 pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].dac.u32F0c_param;
2001 else if (hdaCodecIsDigInPinNode(pThis, CODEC_NID(cmd)))
2002 pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].digin.u32F0c_param;
2003 else
2004 AssertFailedReturn(VINF_SUCCESS);
2005 hdaCodecSetRegisterU8(pu32Reg, cmd, 0);
2006
2007 return VINF_SUCCESS;
2008}
2009
2010/* F0F */
2011static DECLCALLBACK(int) vrbProcGetVolumeKnobCtrl(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
2012{
2013 Assert(CODEC_CAD(cmd) == pThis->id);
2014 Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
2015 if (CODEC_NID(cmd) >= pThis->cTotalNodes)
2016 {
2017 LogFlowFunc(("invalid node address %d\n", CODEC_NID(cmd)));
2018 return VINF_SUCCESS;
2019 }
2020 *pResp = 0;
2021 if (hdaCodecIsVolKnobNode(pThis, CODEC_NID(cmd)))
2022 *pResp = pThis->paNodes[CODEC_NID(cmd)].volumeKnob.u32F0f_param;
2023 return VINF_SUCCESS;
2024}
2025
2026/* 70F */
2027static DECLCALLBACK(int) vrbProcSetVolumeKnobCtrl(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
2028{
2029 Assert(CODEC_CAD(cmd) == pThis->id);
2030 Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
2031 if (CODEC_NID(cmd) >= pThis->cTotalNodes)
2032 {
2033 LogFlowFunc(("invalid node address %d\n", CODEC_NID(cmd)));
2034 return VINF_SUCCESS;
2035 }
2036 uint32_t *pu32Reg = NULL;
2037 *pResp = 0;
2038 if (hdaCodecIsVolKnobNode(pThis, CODEC_NID(cmd)))
2039 pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].volumeKnob.u32F0f_param;
2040 Assert(pu32Reg);
2041 if (pu32Reg)
2042 hdaCodecSetRegisterU8(pu32Reg, cmd, 0);
2043 return VINF_SUCCESS;
2044}
2045
2046/* F17 */
2047static DECLCALLBACK(int) vrbProcGetGPIOUnsolisted(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
2048{
2049 Assert(CODEC_CAD(cmd) == pThis->id);
2050 Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
2051 if (CODEC_NID(cmd) >= pThis->cTotalNodes)
2052 {
2053 LogFlowFunc(("invalid node address %d\n", CODEC_NID(cmd)));
2054 return VINF_SUCCESS;
2055 }
2056 *pResp = 0;
2057 /* note: this is true for ALC885 */
2058 if (CODEC_NID(cmd) == 0x1 /* AFG */)
2059 *pResp = pThis->paNodes[1].afg.u32F17_param;
2060 return VINF_SUCCESS;
2061}
2062
2063/* 717 */
2064static DECLCALLBACK(int) vrbProcSetGPIOUnsolisted(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
2065{
2066 Assert(CODEC_CAD(cmd) == pThis->id);
2067 Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
2068 if (CODEC_NID(cmd) >= pThis->cTotalNodes)
2069 {
2070 LogFlowFunc(("invalid node address %d\n", CODEC_NID(cmd)));
2071 return VINF_SUCCESS;
2072 }
2073 uint32_t *pu32Reg = NULL;
2074 *pResp = 0;
2075 if (CODEC_NID(cmd) == 1 /* AFG */)
2076 pu32Reg = &pThis->paNodes[1].afg.u32F17_param;
2077 Assert(pu32Reg);
2078 if (pu32Reg)
2079 hdaCodecSetRegisterU8(pu32Reg, cmd, 0);
2080 return VINF_SUCCESS;
2081}
2082
2083/* F1C */
2084static DECLCALLBACK(int) vrbProcGetConfig(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
2085{
2086 Assert(CODEC_CAD(cmd) == pThis->id);
2087 Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
2088 if (CODEC_NID(cmd) >= pThis->cTotalNodes)
2089 {
2090 LogFlowFunc(("invalid node address %d\n", CODEC_NID(cmd)));
2091 return VINF_SUCCESS;
2092 }
2093 *pResp = 0;
2094 if (hdaCodecIsPortNode(pThis, CODEC_NID(cmd)))
2095 *pResp = pThis->paNodes[CODEC_NID(cmd)].port.u32F1c_param;
2096 else if (hdaCodecIsDigOutPinNode(pThis, CODEC_NID(cmd)))
2097 *pResp = pThis->paNodes[CODEC_NID(cmd)].digout.u32F1c_param;
2098 else if (hdaCodecIsDigInPinNode(pThis, CODEC_NID(cmd)))
2099 *pResp = pThis->paNodes[CODEC_NID(cmd)].digin.u32F1c_param;
2100 else if (hdaCodecIsPcbeepNode(pThis, CODEC_NID(cmd)))
2101 *pResp = pThis->paNodes[CODEC_NID(cmd)].pcbeep.u32F1c_param;
2102 else if (hdaCodecIsCdNode(pThis, CODEC_NID(cmd)))
2103 *pResp = pThis->paNodes[CODEC_NID(cmd)].cdnode.u32F1c_param;
2104 else if (hdaCodecIsReservedNode(pThis, CODEC_NID(cmd)))
2105 *pResp = pThis->paNodes[CODEC_NID(cmd)].reserved.u32F1c_param;
2106 return VINF_SUCCESS;
2107}
2108
2109static int codecSetConfigX(PHDACODEC pThis, uint32_t cmd, uint8_t u8Offset)
2110{
2111 Assert(CODEC_CAD(cmd) == pThis->id);
2112 Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
2113 if (CODEC_NID(cmd) >= pThis->cTotalNodes)
2114 {
2115 LogFlowFunc(("invalid node address %d\n", CODEC_NID(cmd)));
2116 return VINF_SUCCESS;
2117 }
2118 uint32_t *pu32Reg = NULL;
2119 if (hdaCodecIsPortNode(pThis, CODEC_NID(cmd)))
2120 pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].port.u32F1c_param;
2121 else if (hdaCodecIsDigInPinNode(pThis, CODEC_NID(cmd)))
2122 pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].digin.u32F1c_param;
2123 else if (hdaCodecIsDigOutPinNode(pThis, CODEC_NID(cmd)))
2124 pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].digout.u32F1c_param;
2125 else if (hdaCodecIsCdNode(pThis, CODEC_NID(cmd)))
2126 pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].cdnode.u32F1c_param;
2127 else if (hdaCodecIsPcbeepNode(pThis, CODEC_NID(cmd)))
2128 pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].pcbeep.u32F1c_param;
2129 else if (hdaCodecIsReservedNode(pThis, CODEC_NID(cmd)))
2130 pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].reserved.u32F1c_param;
2131 Assert(pu32Reg);
2132 if (pu32Reg)
2133 hdaCodecSetRegisterU8(pu32Reg, cmd, u8Offset);
2134 return VINF_SUCCESS;
2135}
2136
2137/* 71C */
2138static DECLCALLBACK(int) vrbProcSetConfig0(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
2139{
2140 *pResp = 0;
2141 return codecSetConfigX(pThis, cmd, 0);
2142}
2143
2144/* 71D */
2145static DECLCALLBACK(int) vrbProcSetConfig1(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
2146{
2147 *pResp = 0;
2148 return codecSetConfigX(pThis, cmd, 8);
2149}
2150
2151/* 71E */
2152static DECLCALLBACK(int) vrbProcSetConfig2(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
2153{
2154 *pResp = 0;
2155 return codecSetConfigX(pThis, cmd, 16);
2156}
2157
2158/* 71E */
2159static DECLCALLBACK(int) vrbProcSetConfig3(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
2160{
2161 *pResp = 0;
2162 return codecSetConfigX(pThis, cmd, 24);
2163}
2164
2165
2166/**
2167 * HDA codec verb map.
2168 * @todo Any reason not to use binary search here?
2169 */
2170static const CODECVERB g_aCodecVerbs[] =
2171{
2172/* verb | verb mask | callback */
2173/* ----------- -------------------- ----------------------- */
2174 { 0x000F0000, CODEC_VERB_8BIT_CMD , vrbProcGetParameter },
2175 { 0x000F0100, CODEC_VERB_8BIT_CMD , vrbProcGetConSelectCtrl },
2176 { 0x00070100, CODEC_VERB_8BIT_CMD , vrbProcSetConSelectCtrl },
2177 { 0x000F0600, CODEC_VERB_8BIT_CMD , vrbProcGetStreamId },
2178 { 0x00070600, CODEC_VERB_8BIT_CMD , vrbProcSetStreamId },
2179 { 0x000F0700, CODEC_VERB_8BIT_CMD , vrbProcGetPinCtrl },
2180 { 0x00070700, CODEC_VERB_8BIT_CMD , vrbProcSetPinCtrl },
2181 { 0x000F0800, CODEC_VERB_8BIT_CMD , vrbProcGetUnsolicitedEnabled },
2182 { 0x00070800, CODEC_VERB_8BIT_CMD , vrbProcSetUnsolicitedEnabled },
2183 { 0x000F0900, CODEC_VERB_8BIT_CMD , vrbProcGetPinSense },
2184 { 0x00070900, CODEC_VERB_8BIT_CMD , vrbProcSetPinSense },
2185 { 0x000F0200, CODEC_VERB_8BIT_CMD , vrbProcGetConnectionListEntry },
2186 { 0x000F0300, CODEC_VERB_8BIT_CMD , vrbProcGetProcessingState },
2187 { 0x00070300, CODEC_VERB_8BIT_CMD , vrbProcSetProcessingState },
2188 { 0x000F0D00, CODEC_VERB_8BIT_CMD , vrbProcGetDigitalConverter },
2189 { 0x00070D00, CODEC_VERB_8BIT_CMD , vrbProcSetDigitalConverter1 },
2190 { 0x00070E00, CODEC_VERB_8BIT_CMD , vrbProcSetDigitalConverter2 },
2191 { 0x000F2000, CODEC_VERB_8BIT_CMD , vrbProcGetSubId },
2192 { 0x00072000, CODEC_VERB_8BIT_CMD , vrbProcSetSubId0 },
2193 { 0x00072100, CODEC_VERB_8BIT_CMD , vrbProcSetSubId1 },
2194 { 0x00072200, CODEC_VERB_8BIT_CMD , vrbProcSetSubId2 },
2195 { 0x00072300, CODEC_VERB_8BIT_CMD , vrbProcSetSubId3 },
2196 { 0x0007FF00, CODEC_VERB_8BIT_CMD , vrbProcReset },
2197 { 0x000F0500, CODEC_VERB_8BIT_CMD , vrbProcGetPowerState },
2198 { 0x00070500, CODEC_VERB_8BIT_CMD , vrbProcSetPowerState },
2199 { 0x000F0C00, CODEC_VERB_8BIT_CMD , vrbProcGetEAPD_BTLEnabled },
2200 { 0x00070C00, CODEC_VERB_8BIT_CMD , vrbProcSetEAPD_BTLEnabled },
2201 { 0x000F0F00, CODEC_VERB_8BIT_CMD , vrbProcGetVolumeKnobCtrl },
2202 { 0x00070F00, CODEC_VERB_8BIT_CMD , vrbProcSetVolumeKnobCtrl },
2203 { 0x000F1700, CODEC_VERB_8BIT_CMD , vrbProcGetGPIOUnsolisted },
2204 { 0x00071700, CODEC_VERB_8BIT_CMD , vrbProcSetGPIOUnsolisted },
2205 { 0x000F1C00, CODEC_VERB_8BIT_CMD , vrbProcGetConfig },
2206 { 0x00071C00, CODEC_VERB_8BIT_CMD , vrbProcSetConfig0 },
2207 { 0x00071D00, CODEC_VERB_8BIT_CMD , vrbProcSetConfig1 },
2208 { 0x00071E00, CODEC_VERB_8BIT_CMD , vrbProcSetConfig2 },
2209 { 0x00071F00, CODEC_VERB_8BIT_CMD , vrbProcSetConfig3 },
2210 { 0x000A0000, CODEC_VERB_16BIT_CMD, vrbProcGetConverterFormat },
2211 { 0x00020000, CODEC_VERB_16BIT_CMD, vrbProcSetConverterFormat },
2212 { 0x000B0000, CODEC_VERB_16BIT_CMD, vrbProcGetAmplifier },
2213 { 0x00030000, CODEC_VERB_16BIT_CMD, vrbProcSetAmplifier },
2214};
2215
2216static int codecLookup(PHDACODEC pThis, uint32_t cmd, PPFNHDACODECVERBPROCESSOR pfn)
2217{
2218 Assert(CODEC_CAD(cmd) == pThis->id);
2219 if (hdaCodecIsReservedNode(pThis, CODEC_NID(cmd)))
2220 LogFlowFunc(("cmd %x was addressed to reserved node\n", cmd));
2221
2222 if ( CODEC_VERBDATA(cmd) == 0
2223 || CODEC_NID(cmd) >= pThis->cTotalNodes)
2224 {
2225 *pfn = vrbProcUnimplemented;
2226 /// @todo r=michaln: There needs to be a counter to avoid log flooding (see e.g. DevRTC.cpp)
2227 LogFlowFunc(("cmd %x was ignored\n", cmd));
2228 return VINF_SUCCESS;
2229 }
2230
2231 for (int i = 0; i < pThis->cVerbs; ++i)
2232 {
2233 if ((CODEC_VERBDATA(cmd) & pThis->paVerbs[i].mask) == pThis->paVerbs[i].verb)
2234 {
2235 *pfn = pThis->paVerbs[i].pfn;
2236 return VINF_SUCCESS;
2237 }
2238 }
2239
2240 *pfn = vrbProcUnimplemented;
2241 LogFlowFunc(("callback for %x wasn't found\n", CODEC_VERBDATA(cmd)));
2242 return VINF_SUCCESS;
2243}
2244
2245/*
2246 * APIs exposed to DevHDA.
2247 */
2248
2249/**
2250 *
2251 * routines open one of the voices (IN, OUT) with corresponding parameters.
2252 * this routine could be called from HDA on setting/resseting sound format.
2253 *
2254 * @todo Probably passed settings should be verified (if AFG's declared proposed
2255 * format) before enabling.
2256 */
2257int hdaCodecOpenStream(PHDACODEC pThis, ENMSOUNDSOURCE enmSoundSource, PPDMAUDIOSTREAMCFG pCfg)
2258{
2259 AssertPtrReturn(pThis, VERR_INVALID_POINTER);
2260
2261 int rc;
2262
2263 switch (enmSoundSource)
2264 {
2265 case PI_INDEX:
2266 rc = pThis->pfnOpenIn(pThis->pHDAState, "hda.in", PDMAUDIORECSOURCE_LINE_IN, pCfg);
2267 break;
2268
2269 case PO_INDEX:
2270 rc = pThis->pfnOpenOut(pThis->pHDAState, "hda.out", pCfg);
2271 break;
2272
2273#ifdef VBOX_WITH_HDA_MIC_IN
2274 case MC_INDEX:
2275 rc = pThis->pfnOpenIn(pThis->pHDAState, "hda.mc", PDMAUDIORECSOURCE_MIC, pCfg);
2276 break;
2277#endif
2278 default:
2279 AssertMsgFailed(("Index %ld not implemented\n", enmSoundSource));
2280 rc = VERR_NOT_IMPLEMENTED;
2281 }
2282
2283 LogFlowFuncLeaveRC(rc);
2284 return rc;
2285}
2286
2287int hdaCodecSaveState(PHDACODEC pThis, PSSMHANDLE pSSM)
2288{
2289 AssertLogRelMsgReturn(pThis->cTotalNodes == 0x1c, ("cTotalNodes=%#x, should be 0x1c", pThis->cTotalNodes),
2290 VERR_INTERNAL_ERROR);
2291 SSMR3PutU32(pSSM, pThis->cTotalNodes);
2292 for (unsigned idxNode = 0; idxNode < pThis->cTotalNodes; ++idxNode)
2293 SSMR3PutStructEx(pSSM, &pThis->paNodes[idxNode].SavedState, sizeof(pThis->paNodes[idxNode].SavedState),
2294 0 /*fFlags*/, g_aCodecNodeFields, NULL /*pvUser*/);
2295 return VINF_SUCCESS;
2296}
2297
2298int hdaCodecLoadState(PHDACODEC pThis, PSSMHANDLE pSSM, uint32_t uVersion)
2299{
2300 PCSSMFIELD pFields;
2301 uint32_t fFlags;
2302 switch (uVersion)
2303 {
2304 case HDA_SSM_VERSION_1:
2305 AssertReturn(pThis->cTotalNodes == 0x1c, VERR_INTERNAL_ERROR);
2306 pFields = g_aCodecNodeFieldsV1;
2307 fFlags = SSMSTRUCT_FLAGS_MEM_BAND_AID_RELAXED;
2308 break;
2309
2310 case HDA_SSM_VERSION_2:
2311 case HDA_SSM_VERSION_3:
2312 AssertReturn(pThis->cTotalNodes == 0x1c, VERR_INTERNAL_ERROR);
2313 pFields = g_aCodecNodeFields;
2314 fFlags = SSMSTRUCT_FLAGS_MEM_BAND_AID_RELAXED;
2315 break;
2316
2317 case HDA_SSM_VERSION:
2318 {
2319 uint32_t cNodes;
2320 int rc2 = SSMR3GetU32(pSSM, &cNodes);
2321 AssertRCReturn(rc2, rc2);
2322 if (cNodes != 0x1c)
2323 return VERR_SSM_DATA_UNIT_FORMAT_CHANGED;
2324 AssertReturn(pThis->cTotalNodes == 0x1c, VERR_INTERNAL_ERROR);
2325
2326 pFields = g_aCodecNodeFields;
2327 fFlags = 0;
2328 break;
2329 }
2330
2331 default:
2332 return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
2333 }
2334
2335 for (unsigned idxNode = 0; idxNode < pThis->cTotalNodes; ++idxNode)
2336 {
2337 uint8_t idOld = pThis->paNodes[idxNode].SavedState.Core.id;
2338 int rc = SSMR3GetStructEx(pSSM, &pThis->paNodes[idxNode].SavedState,
2339 sizeof(pThis->paNodes[idxNode].SavedState),
2340 fFlags, pFields, NULL);
2341 if (RT_FAILURE(rc))
2342 return rc;
2343 AssertLogRelMsgReturn(idOld == pThis->paNodes[idxNode].SavedState.Core.id,
2344 ("loaded %#x, expected \n", pThis->paNodes[idxNode].SavedState.Core.id, idOld),
2345 VERR_SSM_DATA_UNIT_FORMAT_CHANGED);
2346 }
2347
2348 /*
2349 * Update stuff after changing the state.
2350 */
2351 if (hdaCodecIsDacNode(pThis, pThis->u8DacLineOut))
2352 hdaCodecToAudVolume(pThis, &pThis->paNodes[pThis->u8DacLineOut].dac.B_params, PDMAUDIOMIXERCTL_PCM);
2353 else if (hdaCodecIsSpdifOutNode(pThis, pThis->u8DacLineOut))
2354 hdaCodecToAudVolume(pThis, &pThis->paNodes[pThis->u8DacLineOut].spdifout.B_params, PDMAUDIOMIXERCTL_PCM);
2355 hdaCodecToAudVolume(pThis, &pThis->paNodes[pThis->u8AdcVolsLineIn].adcvol.B_params, PDMAUDIOMIXERCTL_LINE_IN);
2356
2357 return VINF_SUCCESS;
2358}
2359
2360int hdaCodecDestruct(PHDACODEC pThis)
2361{
2362 AssertPtrReturn(pThis, VERR_INVALID_POINTER);
2363
2364 if (pThis->paNodes)
2365 {
2366 RTMemFree(pThis->paNodes);
2367 pThis->paNodes = NULL;
2368 }
2369
2370 return VINF_SUCCESS;
2371}
2372
2373int hdaCodecConstruct(PPDMDEVINS pDevIns, PHDACODEC pThis,
2374 uint16_t uLUN, PCFGMNODE pCfg)
2375{
2376 AssertPtrReturn(pDevIns, VERR_INVALID_POINTER);
2377 AssertPtrReturn(pThis, VERR_INVALID_POINTER);
2378 AssertPtrReturn(pCfg, VERR_INVALID_POINTER);
2379
2380 pThis->id = uLUN;
2381 pThis->paVerbs = &g_aCodecVerbs[0];
2382 pThis->cVerbs = RT_ELEMENTS(g_aCodecVerbs);
2383 pThis->pfnLookup = codecLookup;
2384 int rc = stac9220Construct(pThis);
2385 AssertRC(rc);
2386
2387 /* common root node initializers */
2388 pThis->paNodes[0].node.au32F00_param[0] = CODEC_MAKE_F00_00(pThis->u16VendorId, pThis->u16DeviceId);
2389 pThis->paNodes[0].node.au32F00_param[4] = CODEC_MAKE_F00_04(0x1, 0x1);
2390 /* common AFG node initializers */
2391 pThis->paNodes[1].node.au32F00_param[4] = CODEC_MAKE_F00_04(0x2, pThis->cTotalNodes - 2);
2392 pThis->paNodes[1].node.au32F00_param[5] = CODEC_MAKE_F00_05(1, CODEC_F00_05_AFG);
2393 pThis->paNodes[1].afg.u32F20_param = CODEC_MAKE_F20(pThis->u16VendorId, pThis->u8BSKU, pThis->u8AssemblyId);
2394
2395 /* 44.1 kHz. */
2396 PDMAUDIOSTREAMCFG as;
2397 as.uHz = 44100;
2398 as.cChannels = 2;
2399 as.enmFormat = AUD_FMT_S16;
2400 as.enmEndianness = PDMAUDIOHOSTENDIANNESS;
2401
2402 pThis->paNodes[1].node.au32F00_param[0xA] = CODEC_F00_0A_16_BIT;
2403
2404 hdaCodecOpenStream(pThis, PI_INDEX, &as);
2405 hdaCodecOpenStream(pThis, PO_INDEX, &as);
2406#ifdef VBOX_WITH_HDA_MIC_IN
2407 hdaCodecOpenStream(pThis, MC_INDEX, &as);
2408#endif
2409
2410 pThis->paNodes[1].node.au32F00_param[0xA] |= CODEC_F00_0A_44_1KHZ;
2411
2412 uint8_t i;
2413 Assert(pThis->paNodes);
2414 Assert(pThis->pfnCodecNodeReset);
2415
2416 for (i = 0; i < pThis->cTotalNodes; ++i)
2417 pThis->pfnCodecNodeReset(pThis, i, &pThis->paNodes[i]);
2418
2419 hdaCodecToAudVolume(pThis, &pThis->paNodes[pThis->u8DacLineOut].dac.B_params, PDMAUDIOMIXERCTL_PCM);
2420 hdaCodecToAudVolume(pThis, &pThis->paNodes[pThis->u8AdcVolsLineIn].adcvol.B_params, PDMAUDIOMIXERCTL_LINE_IN);
2421
2422 return VINF_SUCCESS;
2423}
2424
Note: See TracBrowser for help on using the repository browser.

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