VirtualBox

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

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

HDA: Volume handling improvements.

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