VirtualBox

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

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

Audio/HDA: some cosmetic. tune port F params.

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