VirtualBox

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

Last change on this file since 49983 was 44669, checked in by vboxsync, 12 years ago

Renamed the DevIchIntelHDA.cpp to DevIchHda.cpp (ICH include Intel already), and DevCodec.* to DevIchHdaCodec.* since these are only used by the HDA device and using the same base name makes that a lot clearer (DevCodec is way to generic).

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