VirtualBox

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

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

Devices: release log cosmetics.

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