DevIchHdaCodec.cpp revision 174f3dff60f96d89b320f9a322307118676db1db
/* $Id$ */
/** @file
* DevIchHdaCodec - VBox ICH Intel HD Audio Codec.
*
* Implemented against "Intel I/O Controller Hub 6 (ICH6) High Definition
* Audio / AC '97 - Programmer's Reference Manual (PRM)", document number
* 302349-003.
*/
/*
* Copyright (C) 2006-2014 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*/
/*******************************************************************************
* Header Files *
*******************************************************************************/
//#define LOG_GROUP LOG_GROUP_DEV_AUDIO
#include "VBoxDD.h"
#ifndef VBOX_WITH_PDM_AUDIO_DRIVER
extern "C" {
#include "audio.h"
}
#endif
#include "DevIchHdaCodec.h"
/*******************************************************************************
* Defined Constants And Macros *
*******************************************************************************/
/* PRM 5.3.1 */
/** Codec address mask. */
#define CODEC_CAD_MASK 0xF0000000
/** Codec address shift. */
#define CODEC_CAD_SHIFT 28
/** Node ID mask. */
#define CODEC_NID_MASK 0x07F00000
/** Node ID shift. */
#define CODEC_NID_SHIFT 20
#define CODEC_VERBDATA_MASK 0x000FFFFF
#define CODEC_VERB_4BIT_CMD 0x000FFFF0
#define CODEC_VERB_4BIT_DATA 0x0000000F
#define CODEC_VERB_8BIT_CMD 0x000FFF00
#define CODEC_VERB_8BIT_DATA 0x000000FF
#define CODEC_VERB_16BIT_CMD 0x000F0000
#define CODEC_VERB_16BIT_DATA 0x0000FFFF
#define CODEC_VERB_GET_AMP_INDEX 0x7
/* HDA spec 7.3.3.7 NoteA */
#define CODEC_GET_AMP_INDEX(cmd) (CODEC_GET_AMP_DIRECTION(cmd) ? 0 : ((cmd) & CODEC_VERB_GET_AMP_INDEX))
/* HDA spec 7.3.3.7 NoteC */
/* VendorID (7.3.4.1) */
/* RevisionID (7.3.4.2)*/
#define CODEC_MAKE_F00_02(MajRev, MinRev, RevisionID, SteppingID) (((MajRev) << 20)|((MinRev) << 16)|((RevisionID) << 8)|(SteppingID))
/* Subordinate node count (7.3.4.3)*/
#define CODEC_MAKE_F00_04(startNodeNumber, totalNodeNumber) ((((startNodeNumber) & 0xFF) << 16)|((totalNodeNumber) & 0xFF))
/*
* Function Group Type (7.3.4.4)
* 0 & [0x3-0x7f] are reserved types
* [0x80 - 0xff] are vendor defined function groups
*/
#define CODEC_F00_05_AFG (0x1)
#define CODEC_F00_05_MFG (0x2)
/* Audio Function Group capabilities (7.3.4.5) */
#define CODEC_MAKE_F00_08(BeepGen, InputDelay, OutputDelay) ((((BeepGen) & 0x1) << 16)| (((InputDelay) & 0xF) << 8) | ((OutputDelay) & 0xF))
/* Widget Capabilities (7.3.4.6) */
/* note: types 0x8-0xe are reserved */
#define CODEC_F00_09_TYPE_AUDIO_OUTPUT (0x0)
#define CODEC_F00_09_TYPE_AUDIO_INPUT (0x1)
#define CODEC_F00_09_TYPE_AUDIO_MIXER (0x2)
#define CODEC_F00_09_TYPE_AUDIO_SELECTOR (0x3)
#define CODEC_F00_09_TYPE_PIN_COMPLEX (0x4)
#define CODEC_F00_09_TYPE_POWER_WIDGET (0x5)
#define CODEC_F00_09_TYPE_VOLUME_KNOB (0x6)
#define CODEC_F00_09_TYPE_BEEP_GEN (0x7)
#define CODEC_F00_09_TYPE_VENDOR_DEFINED (0xF)
#define CODEC_F00_09_CAP_LSB RT_BIT(0)
/* Supported PCM size, rates (7.3.4.7) */
/* 2/3 * 48kHz */
/* 1/2 * 44.1kHz */
/* 1/3 * 48kHz */
/* 1/4 * 44.1kHz */
/* 1/6 * 48kHz */
#define CODEC_F00_0A_48KHZ_1_6X RT_BIT(0)
/* Supported streams formats (7.3.4.8) */
#define CODEC_F00_0B_PCM RT_BIT(0)
/* Pin Capabilities (7.3.4.9)*/
#define CODEC_F00_0C_CAP_IMPENDANCE_SENSE RT_BIT(0)
/* Input Amplifier capabilities (7.3.4.10) */
| ((offset) & 0xFF))
/* Output Amplifier capabilities (7.3.4.10) */
#define CODEC_MAKE_F00_12 CODEC_MAKE_F00_0D
/* Connection list lenght (7.3.4.11) */
| ((length) & 0x7F))
/* Supported Power States (7.3.4.12) */
#define CODEC_F00_0F_D0 RT_BIT(0)
/* Processing capabilities 7.3.4.13 */
| ((numgpio) & 0xFF))
/* Processing States (7.3.3.4) */
#define CODEC_F03_OFF (0)
#define CODEC_F03_ON RT_BIT(0)
/* Power States (7.3.3.10) */
| ((set) & 0x7))
#define CODEC_F05_D3COLD (4)
#define CODEC_F05_D3 (3)
#define CODEC_F05_D2 (2)
#define CODEC_F05_D1 (1)
#define CODEC_F05_D0 (0)
/* Pin Widged Control (7.3.3.13) */
#define CODEC_F07_VREF_HIZ (0)
#define CODEC_F07_VREF_50 (0x1)
#define CODEC_F07_VREF_GROUND (0x2)
#define CODEC_F07_VREF_80 (0x4)
#define CODEC_F07_VREF_100 (0x5)
/* Unsolicited enabled (7.3.3.14) */
/* Converter formats (7.3.3.8) and (3.7.1) */
| ((chan) & 0xF))
#define CODEC_A_MULT_1X (0)
#define CODEC_A_MULT_2X (1)
#define CODEC_A_MULT_3X (2)
#define CODEC_A_MULT_4X (3)
#define CODEC_A_DIV_1X (0)
#define CODEC_A_DIV_2X (1)
#define CODEC_A_DIV_3X (2)
#define CODEC_A_DIV_4X (3)
#define CODEC_A_DIV_5X (4)
#define CODEC_A_DIV_6X (5)
#define CODEC_A_DIV_7X (6)
#define CODEC_A_DIV_8X (7)
#define CODEC_A_8_BIT (0)
#define CODEC_A_16_BIT (1)
#define CODEC_A_20_BIT (2)
#define CODEC_A_24_BIT (3)
#define CODEC_A_32_BIT (4)
/* Pin Sense (7.3.3.15) */
| (((impedance) & 0x7FFFFFFF)))
#define CODEC_F09_ANALOG_NA 0x7FFFFFFF
#define CODEC_MAKE_F0C(lrswap, eapd, btl) ((((lrswap) & 1) << 2) | (((eapd) & 1) << 1) | ((btl) & 1))
/* Configuration's port connection */
#define CODEC_F1C_PORT_MASK (0x3)
#define CODEC_F1C_PORT_SHIFT (30)
#define CODEC_F1C_PORT_COMPLEX (0x0)
#define CODEC_F1C_PORT_NO_PHYS (0x1)
#define CODEC_F1C_PORT_FIXED (0x2)
#define CODEC_F1C_BOTH (0x3)
/* Configuration's location */
#define CODEC_F1C_LOCATION_MASK (0x3F)
#define CODEC_F1C_LOCATION_SHIFT (24)
/* [4:5] bits of location region means chassis attachment */
#define CODEC_F1C_LOCATION_PRIMARY_CHASSIS (0)
/* [0:3] bits of location region means geometry location attachment */
#define CODEC_F1C_LOCATION_NA (0)
#define CODEC_F1C_LOCATION_REAR (0x1)
#define CODEC_F1C_LOCATION_FRONT (0x2)
#define CODEC_F1C_LOCATION_LEFT (0x3)
#define CODEC_F1C_LOCATION_RIGTH (0x4)
#define CODEC_F1C_LOCATION_TOP (0x5)
#define CODEC_F1C_LOCATION_BOTTOM (0x6)
#define CODEC_F1C_LOCATION_SPECIAL_0 (0x7)
#define CODEC_F1C_LOCATION_SPECIAL_1 (0x8)
#define CODEC_F1C_LOCATION_SPECIAL_2 (0x9)
/* Configuration's devices */
#define CODEC_F1C_DEVICE_MASK (0xF)
#define CODEC_F1C_DEVICE_SHIFT (20)
#define CODEC_F1C_DEVICE_LINE_OUT (0)
#define CODEC_F1C_DEVICE_SPEAKER (0x1)
#define CODEC_F1C_DEVICE_HP (0x2)
#define CODEC_F1C_DEVICE_CD (0x3)
#define CODEC_F1C_DEVICE_SPDIF_OUT (0x4)
#define CODEC_F1C_DEVICE_DIGITAL_OTHER_OUT (0x5)
#define CODEC_F1C_DEVICE_MODEM_LINE_SIDE (0x6)
#define CODEC_F1C_DEVICE_MODEM_HANDSET_SIDE (0x7)
#define CODEC_F1C_DEVICE_LINE_IN (0x8)
#define CODEC_F1C_DEVICE_AUX (0x9)
#define CODEC_F1C_DEVICE_MIC (0xA)
#define CODEC_F1C_DEVICE_PHONE (0xB)
#define CODEC_F1C_DEVICE_SPDIF_IN (0xC)
#define CODEC_F1C_DEVICE_RESERVED (0xE)
#define CODEC_F1C_DEVICE_OTHER (0xF)
/* Configuration's Connection type */
#define CODEC_F1C_CONNECTION_TYPE_MASK (0xF)
#define CODEC_F1C_CONNECTION_TYPE_SHIFT (16)
#define CODEC_F1C_CONNECTION_TYPE_UNKNOWN (0)
#define CODEC_F1C_CONNECTION_TYPE_1_8INCHES (0x1)
#define CODEC_F1C_CONNECTION_TYPE_1_4INCHES (0x2)
#define CODEC_F1C_CONNECTION_TYPE_ATAPI (0x3)
#define CODEC_F1C_CONNECTION_TYPE_RCA (0x4)
#define CODEC_F1C_CONNECTION_TYPE_OPTICAL (0x5)
#define CODEC_F1C_CONNECTION_TYPE_OTHER_DIGITAL (0x6)
#define CODEC_F1C_CONNECTION_TYPE_ANALOG (0x7)
#define CODEC_F1C_CONNECTION_TYPE_DIN (0x8)
#define CODEC_F1C_CONNECTION_TYPE_XLR (0x9)
#define CODEC_F1C_CONNECTION_TYPE_RJ_11 (0xA)
#define CODEC_F1C_CONNECTION_TYPE_COMBO (0xB)
#define CODEC_F1C_CONNECTION_TYPE_OTHER (0xF)
/* Configuration's color */
#define CODEC_F1C_COLOR_MASK (0xF)
#define CODEC_F1C_COLOR_SHIFT (12)
#define CODEC_F1C_COLOR_UNKNOWN (0)
#define CODEC_F1C_COLOR_BLACK (0x1)
#define CODEC_F1C_COLOR_GREY (0x2)
#define CODEC_F1C_COLOR_BLUE (0x3)
#define CODEC_F1C_COLOR_GREEN (0x4)
#define CODEC_F1C_COLOR_RED (0x5)
#define CODEC_F1C_COLOR_ORANGE (0x6)
#define CODEC_F1C_COLOR_YELLOW (0x7)
#define CODEC_F1C_COLOR_PURPLE (0x8)
#define CODEC_F1C_COLOR_PINK (0x9)
#define CODEC_F1C_COLOR_RESERVED_0 (0xA)
#define CODEC_F1C_COLOR_RESERVED_1 (0xB)
#define CODEC_F1C_COLOR_RESERVED_2 (0xC)
#define CODEC_F1C_COLOR_RESERVED_3 (0xD)
#define CODEC_F1C_COLOR_WHITE (0xE)
#define CODEC_F1C_COLOR_OTHER (0xF)
/* Configuration's misc */
#define CODEC_F1C_MISC_MASK (0xF)
#define CODEC_F1C_MISC_SHIFT (8)
#define CODEC_F1C_MISC_JACK_DETECT (0)
#define CODEC_F1C_MISC_RESERVED_0 (1)
#define CODEC_F1C_MISC_RESERVED_1 (2)
#define CODEC_F1C_MISC_RESERVED_2 (3)
/* Configuration's association */
#define CODEC_F1C_ASSOCIATION_MASK (0xF)
#define CODEC_F1C_ASSOCIATION_SHIFT (4)
/* Connection's sequence */
#define CODEC_F1C_SEQ_MASK (0xF)
#define CODEC_F1C_SEQ_SHIFT (0)
/* Implementation identification (7.3.3.30) */
| (((aid) & 0xFF)) \
)
/* macro definition helping in filling the configuration registers. */
#define CODEC_MAKE_F1C(port_connectivity, location, device, connection_type, color, misc, association, sequence) \
( ((port_connectivity) << CODEC_F1C_PORT_SHIFT) \
| ((location) << CODEC_F1C_LOCATION_SHIFT) \
| ((device) << CODEC_F1C_DEVICE_SHIFT) \
| ((connection_type) << CODEC_F1C_CONNECTION_TYPE_SHIFT) \
| ((color) << CODEC_F1C_COLOR_SHIFT) \
| ((misc) << CODEC_F1C_MISC_SHIFT) \
| ((association) << CODEC_F1C_ASSOCIATION_SHIFT) \
| ((sequence)))
/*******************************************************************************
* Structures and Typedefs *
*******************************************************************************/
/** The F00 parameter length (in dwords). */
#define CODECNODE_F00_PARAM_LENGTH 20
/** The F02 parameter length (in dwords). */
#define CODECNODE_F02_PARAM_LENGTH 16
/**
* Common (or core) codec node structure.
*/
typedef struct CODECCOMMONNODE
{
/** Node id - 7 bit format */
/** The node name. */
char const *pszName;
/* PRM 5.3.6 */
typedef CODECCOMMONNODE *PCODECCOMMONNODE;
/**
* Compile time assertion on the expected node size.
*/
typedef struct ROOTCODECNODE
{
#define AMPLIFIER_SIZE 60
#define AMPLIFIER_IN 0
#define AMPLIFIER_OUT 1
#define AMPLIFIER_LEFT 1
#define AMPLIFIER_RIGHT 0
typedef struct DACNODE
{
typedef struct ADCNODE
{
typedef struct SPDIFOUTNODE
{
typedef struct SPDIFINNODE
{
} SPDIFINNODE, *PSPDIFINNODE;
typedef struct AFGCODECNODE
{
typedef struct PORTNODE
{
typedef struct DIGOUTNODE
{
} DIGOUTNODE, *PDIGOUTNODE;
typedef struct DIGINNODE
{
} DIGINNODE, *PDIGINNODE;
typedef struct ADCMUXNODE
{
} ADCMUXNODE, *PADCMUXNODE;
typedef struct PCBEEPNODE
{
} PCBEEPNODE, *PPCBEEPNODE;
typedef struct CDNODE
{
typedef struct VOLUMEKNOBNODE
{
typedef struct ADCVOLNODE
{
} ADCVOLNODE, *PADCVOLNODE;
typedef struct RESNODE
{
/**
* Used for the saved state.
*/
typedef struct CODECSAVEDSTATENODE
{
typedef union CODECNODE
{
} CODECNODE, *PCODECNODE;
/*******************************************************************************
* Global Variables *
*******************************************************************************/
/* STAC9220 - Referenced thru STAC9220WIDGET in the constructor below. */
/** SSM description of a CODECNODE. */
static SSMFIELD const g_aCodecNodeFields[] =
{
};
/** Backward compatibility with v1 of the CODECNODE. */
static SSMFIELD const g_aCodecNodeFieldsV1[] =
{
};
{
switch (nodenum)
{
/* Root Node*/
case 0:
break;
case 1:
| CODEC_F00_0C_CAP_IMPENDANCE_SENSE;//(17 << 8)|RT_BIT(6)|RT_BIT(5)|RT_BIT(2)|RT_BIT(1)|RT_BIT(0);
pNode->node.au32F00_param[0x0D] = CODEC_MAKE_F00_0D(1, 0x5, 0xE, 0);//RT_BIT(31)|(0x5 << 16)|(0xE)<<8;
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 */
break;
case 2:
case 3:
case 4:
case 5:
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 */
| CODEC_F00_09_CAP_LSB;//(0xD << 16) | RT_BIT(11) | RT_BIT(10) | RT_BIT(2) | RT_BIT(0);
pNode->dac.u32F05_param = CODEC_MAKE_F05(0, 0, 0, CODEC_F05_D3, CODEC_F05_D3);//0x3 << 4 | 0x3; /* PS-Act: D3, Set: D3 */
break;
case 6:
goto adc_init;
case 7:
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 */
pNode->adc.u32F05_param = CODEC_MAKE_F05(0, 0, 0, CODEC_F05_D3, CODEC_F05_D3);//0x3 << 4 | 0x3; /* PS-Act: D3 Set: D3 */
| CODEC_F00_09_CAP_LSB;//RT_BIT(20)| (0xd << 16) | RT_BIT(10) | RT_BIT(8) | RT_BIT(6)| RT_BIT(0);
break;
case 8:
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;
| CODEC_F00_09_CAP_LSB;//(4 << 16) | RT_BIT(9)|RT_BIT(4)|0x1;
break;
case 9:
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;
| CODEC_F00_09_CAP_LSB;//(0x1 << 20)|(4 << 16) | RT_BIT(9)| RT_BIT(8)|RT_BIT(4)|0x1;
break;
case 0xA:
| CODEC_F00_0C_CAP_IMPENDANCE_SENSE;//0x173f;
0x2, 0);//RT_MAKE_U32_FROM_U8(0x20, 0x40, 0x21, 0x02);
goto port_init;
case 0xB:
| CODEC_F00_0C_CAP_IMPENDANCE_SENSE;//0x1737;
0x1, 0x1);//RT_MAKE_U32_FROM_U8(0x11, 0x60, 0x11, 0x01);
goto port_init;
case 0xC:
| CODEC_F00_0C_CAP_IMPENDANCE_SENSE;//0x1737;
0x0, 0x1, 0x0);//RT_MAKE_U32_FROM_U8(0x10, 0x40, 0x11, 0x01);
goto port_init;
case 0xD:
| CODEC_F00_0C_CAP_IMPENDANCE_SENSE;//0x1737;
0x0, 0x5, 0x0);//RT_MAKE_U32_FROM_U8(0x50, 0x90, 0xA1, 0x02); /* Microphone */
| CODEC_F00_09_CAP_LSB;//(4 << 20)|RT_BIT(8)|RT_BIT(7)|RT_BIT(0);
break;
case 0xE:
| CODEC_F00_09_CAP_LSB;//(4 << 20)|RT_BIT(7)|RT_BIT(0);
| CODEC_F00_0C_CAP_PRESENSE_DETECT;//0x34;
0x0, 0x4, 0x0);//0x01013040; /* Line Out */
break;
case 0xF:
| CODEC_F00_09_CAP_LSB;//(4 << 20)|RT_BIT(8)|RT_BIT(7)|RT_BIT(2)|RT_BIT(0);
/* | CODEC_F00_0C_CAP_TRIGGER_REQUIRED
| CODEC_F00_0C_CAP_IMPENDANCE_SENSE */;//0x37;
0x0, 0x1, 0x2);//RT_MAKE_U32_FROM_U8(0x12, 0x60, 0x11, 0x01);
break;
case 0x10:
| CODEC_F00_09_CAP_LSB;//(4<<20)|RT_BIT(9)|RT_BIT(8)|RT_BIT(0);
0x0, 0x3, 0x0);//RT_MAKE_U32_FROM_U8(0x30, 0x10, 0x45, 0x01);
break;
case 0x11:
pNode->node.au32F00_param[9] = (4 << 20) | (3 << 16) | RT_BIT(10) | RT_BIT(9) | RT_BIT(7) | RT_BIT(0);
| CODEC_F00_0C_CAP_PRESENSE_DETECT;//RT_BIT(16)| RT_BIT(5)|RT_BIT(2);
pNode->digin.u32F05_param = CODEC_MAKE_F05(0, 0, 0, CODEC_F05_D3, CODEC_F05_D3);//0x3 << 4 | 0x3; /* PS-Act: D3 -> D3 */
0x0, 0x6, 0x0);//(0x1 << 24) | (0xc5 << 16) | (0x10 << 8) | 0x60;
break;
case 0x12:
goto adcmux_init;
case 0x13:
| CODEC_F00_09_CAP_LSB;//(3<<20)|RT_BIT(8)|RT_BIT(3)|RT_BIT(2)|RT_BIT(0);
/* STAC 9220 v10 6.21-22.{4,5} both(left and right) out amplefiers inited with 0*/
break;
case 0x14:
| CODEC_F00_09_CAP_OUT_AMP_PRESENT;//(7 << 20) | RT_BIT(3) | RT_BIT(2);
break;
case 0x15:
| CODEC_F00_09_CAP_LSB;//(4 << 20)|RT_BIT(0);
0x0, 0x7, 0x0);//RT_MAKE_U32_FROM_U8(0x70, 0x0, 0x33, 0x90);
break;
case 0x16:
pNode->node.au32F00_param[0x9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_VOLUME_KNOB, 0x0, 0x0);//(0x6 << 20);
break;
case 0x17:
goto adcvol_init;
case 0x18:
| CODEC_F00_09_CAP_LSB;//(0x3 << 20)|RT_BIT(11)|RT_BIT(8)|RT_BIT(1)|RT_BIT(0);
break;
case 0x19:
| CODEC_F00_09_CAP_LSB;//(0xF << 20)|(0x3 << 16)|RT_BIT(9)|RT_BIT(0);
break;
case 0x1A:
| CODEC_F00_09_CAP_LSB;//(0x3 << 16)|RT_BIT(9)|RT_BIT(0);
break;
case 0x1B:
| CODEC_F00_09_CAP_LSB;//(0x4 << 20)|RT_BIT(9)|RT_BIT(8)|RT_BIT(0);
0x0, 0x0, 0xf);//0x4000000f;
break;
default:
break;
}
return VINF_SUCCESS;
}
{
return VERR_NO_MEMORY;
return VINF_SUCCESS;
}
/*
* Some generic predicate functions.
*/
#define DECLISNODEOFTYPE(type) \
{ \
return 1; \
return 0; \
}
/* hdaCodecIsPortNode */
/* hdaCodecIsDacNode */
/* hdaCodecIsAdcVolNode */
/* hdaCodecIsAdcNode */
/* hdaCodecIsAdcMuxNode */
/* hdaCodecIsPcbeepNode */
/* hdaCodecIsSpdifOutNode */
/* hdaCodecIsSpdifInNode */
/* hdaCodecIsDigInPinNode */
/* hdaCodecIsDigOutPinNode */
/* hdaCodecIsCdNode */
/* hdaCodecIsVolKnobNode */
/* hdaCodecIsReservedNode */
/*
* Misc helpers.
*/
#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
#else
#endif
{
switch (mt)
{
#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
case PDMAUDIOMIXERCTL_VOLUME:
case PDMAUDIOMIXERCTL_PCM:
#else
case AUD_MIXER_VOLUME:
case AUD_MIXER_PCM:
#endif
dir = AMPLIFIER_OUT;
break;
#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
case PDMAUDIOMIXERCTL_LINE_IN:
#else
case AUD_MIXER_LINE_IN:
#endif
dir = AMPLIFIER_IN;
break;
default:
break;
}
mute >>=7;
mute &= 0x1;
#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
/** @todo In SetVolume no passing audmixerctl_in as its not used in DrvAudio.cpp. */
#else
#endif
return VINF_SUCCESS;
}
DECLINLINE(void) hdaCodecSetRegister(uint32_t *pu32Reg, uint32_t u32Cmd, uint8_t u8Offset, uint32_t mask)
{
}
{
}
{
}
/*
* Verb processor functions.
*/
{
*pResp = 0;
return VINF_SUCCESS;
}
{
int rc;
return rc;
}
/* B-- */
{
{
return VINF_SUCCESS;
}
*pResp = 0;
/* HDA spec 7.3.3.7 Note A */
/** @todo: if index out of range response should be 0 */
u8Index);
u8Index);
u8Index);
u8Index);
u8Index);
u8Index);
else
AssertMsgFailedReturn(("access to fields of %x need to be implemented\n", CODEC_NID(cmd)), VINF_SUCCESS);
return VINF_SUCCESS;
}
/* 3-- */
{
bool fIsLeft = false;
bool fIsRight = false;
bool fIsOut = false;
bool fIsIn = false;
{
return VINF_SUCCESS;
}
*pResp = 0;
else
return VINF_SUCCESS;
if (fIsIn)
{
if (fIsLeft)
hdaCodecSetRegisterU8(&LIFIER_REGISTER(*pAmplifier, AMPLIFIER_IN, AMPLIFIER_LEFT, u8Index), cmd, 0);
if (fIsRight)
hdaCodecSetRegisterU8(&LIFIER_REGISTER(*pAmplifier, AMPLIFIER_IN, AMPLIFIER_RIGHT, u8Index), cmd, 0);
}
if (fIsOut)
{
if (fIsLeft)
hdaCodecSetRegisterU8(&LIFIER_REGISTER(*pAmplifier, AMPLIFIER_OUT, AMPLIFIER_LEFT, u8Index), cmd, 0);
if (fIsRight)
hdaCodecSetRegisterU8(&LIFIER_REGISTER(*pAmplifier, AMPLIFIER_OUT, AMPLIFIER_RIGHT, u8Index), cmd, 0);
}
#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
#else
#endif
#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
#else
#endif
return VINF_SUCCESS;
}
{
{
return VINF_SUCCESS;
}
{
return VINF_SUCCESS;
}
return VINF_SUCCESS;
}
/* F01 */
{
{
return VINF_SUCCESS;
}
*pResp = 0;
return VINF_SUCCESS;
}
/* 701 */
{
{
return VINF_SUCCESS;
}
*pResp = 0;
else
return VINF_SUCCESS;
}
/* F07 */
{
{
return VINF_SUCCESS;
}
*pResp = 0;
else
AssertMsgFailed(("Unsupported"));
return VINF_SUCCESS;
}
/* 707 */
{
{
return VINF_SUCCESS;
}
*pResp = 0;
else
return VINF_SUCCESS;
}
/* F08 */
static DECLCALLBACK(int) vrbProcGetUnsolicitedEnabled(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
{
{
return VINF_SUCCESS;
}
*pResp = 0;
else
return VINF_SUCCESS;
}
/* 708 */
static DECLCALLBACK(int) vrbProcSetUnsolicitedEnabled(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
{
{
return VINF_SUCCESS;
}
*pResp = 0;
else
AssertMsgFailedReturn(("unsupported operation %x on node: %x\n", CODEC_VERB_CMD8(cmd), CODEC_NID(cmd)), VINF_SUCCESS);
return VINF_SUCCESS;
}
/* F09 */
{
{
return VINF_SUCCESS;
}
*pResp = 0;
else
return VINF_SUCCESS;
}
/* 709 */
{
{
return VINF_SUCCESS;
}
*pResp = 0;
else
return VINF_SUCCESS;
}
static DECLCALLBACK(int) vrbProcGetConnectionListEntry(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
{
*pResp = 0;
{
return VINF_SUCCESS;
}
{
return VINF_SUCCESS;
}
return VINF_SUCCESS;
}
/* F03 */
{
{
return VINF_SUCCESS;
}
*pResp = 0;
return VINF_SUCCESS;
}
/* 703 */
{
{
return VINF_SUCCESS;
}
*pResp = 0;
return VINF_SUCCESS;
}
/* F0D */
{
{
return VINF_SUCCESS;
}
*pResp = 0;
return VINF_SUCCESS;
}
static int codecSetDigitalConverter(PHDACODEC pThis, uint32_t cmd, uint8_t u8Offset, uint64_t *pResp)
{
{
return VINF_SUCCESS;
}
*pResp = 0;
return VINF_SUCCESS;
}
/* 70D */
static DECLCALLBACK(int) vrbProcSetDigitalConverter1(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
{
}
/* 70E */
static DECLCALLBACK(int) vrbProcSetDigitalConverter2(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
{
}
/* F20 */
{
{
return VINF_SUCCESS;
}
else
*pResp = 0;
return VINF_SUCCESS;
}
{
{
return VINF_SUCCESS;
}
else
return VINF_SUCCESS;
}
/* 720 */
{
*pResp = 0;
}
/* 721 */
{
*pResp = 0;
}
/* 722 */
{
*pResp = 0;
}
/* 723 */
{
*pResp = 0;
}
{
&& pThis->pfnCodecNodeReset)
{
uint8_t i;
LogFlowFunc(("enters reset\n"));
for (i = 0; i < pThis->cTotalNodes; ++i)
{
}
LogFlowFunc(("exits reset\n"));
}
*pResp = 0;
return VINF_SUCCESS;
}
/* F05 */
{
{
return VINF_SUCCESS;
}
*pResp = 0;
return VINF_SUCCESS;
}
/* 705 */
{
if (!pu32F05_param)
return;
}
{
{
return VINF_SUCCESS;
}
*pResp = 0;
else
{
/*
* We shouldn't propogate actual power state, which actual for AFG
*/
CODEC_F05_SET(cmd));
}
/* Propagate next power state only if AFG is on or verb modifies AFG power state */
{
{
/* now we're powered on AFG and may propogate power states on nodes */
while (*(++pu8NodeIndex))
while (*(++pu8NodeIndex))
while (*(++pu8NodeIndex))
}
}
return VINF_SUCCESS;
}
{
{
return VINF_SUCCESS;
}
*pResp = 0;
return VINF_SUCCESS;
}
{
{
return VINF_SUCCESS;
}
*pResp = 0;
else
return VINF_SUCCESS;
}
{
{
return VINF_SUCCESS;
}
*pResp = 0;
return VINF_SUCCESS;
}
{
{
return VINF_SUCCESS;
}
*pResp = 0;
return VINF_SUCCESS;
}
/* F0C */
{
{
return VINF_SUCCESS;
}
*pResp = 0;
return VINF_SUCCESS;
}
/* 70C */
{
{
return VINF_SUCCESS;
}
*pResp = 0;
else
return VINF_SUCCESS;
}
/* F0F */
{
{
return VINF_SUCCESS;
}
*pResp = 0;
return VINF_SUCCESS;
}
/* 70F */
{
{
return VINF_SUCCESS;
}
*pResp = 0;
if (pu32Reg)
return VINF_SUCCESS;
}
/* F17 */
{
{
return VINF_SUCCESS;
}
*pResp = 0;
/* note: this is true for ALC885 */
return VINF_SUCCESS;
}
/* 717 */
{
{
return VINF_SUCCESS;
}
*pResp = 0;
if (pu32Reg)
return VINF_SUCCESS;
}
/* F1C */
{
{
return VINF_SUCCESS;
}
*pResp = 0;
return VINF_SUCCESS;
}
{
{
return VINF_SUCCESS;
}
if (pu32Reg)
return VINF_SUCCESS;
}
/* 71C */
{
*pResp = 0;
}
/* 71D */
{
*pResp = 0;
}
/* 71E */
{
*pResp = 0;
}
/* 71E */
{
*pResp = 0;
}
/**
* HDA codec verb map.
* @todo Any reason not to use binary search here?
*/
static const CODECVERB g_aCodecVerbs[] =
{
/* verb | verb mask | callback */
/* ----------- -------------------- ----------------------- */
};
{
if ( CODEC_VERBDATA(cmd) == 0
{
/// @todo r=michaln: There needs to be a counter to avoid log flooding (see e.g. DevRTC.cpp)
return VINF_SUCCESS;
}
{
{
return VINF_SUCCESS;
}
}
return VINF_SUCCESS;
}
#ifndef VBOX_WITH_PDM_AUDIO_DRIVER
{
}
{
}
#endif /* VBOX_WITH_PDM_AUDIO_DRIVER */
/*
* APIs exposed to DevHDA.
*/
/**
*
* routines open one of the voices (IN, OUT) with corresponding parameters.
*
* @todo Probably passed settings should be verified (if AFG's declared proposed
* format) before enabling.
*/
#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
#else
int hdaCodecOpenStream(PHDACODEC pThis, ENMSOUNDSOURCE enmSoundSource, audsettings_t *pAudioSettings)
#endif
{
int rc;
switch (enmSoundSource)
{
case PI_INDEX:
#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
/* old and new stream settings are not same. Then only call open */
//if (!hdaCodecCompareAudioSettings(&(pThis->SwVoiceIn)->info, pAudioSettings) && !pThis->SwVoiceIn)
#else
pThis->SwVoiceIn = AUD_open_in(&pThis->card, pThis->SwVoiceIn, "hda.in", pThis, pi_callback, pAudioSettings);
#endif
break;
case PO_INDEX:
#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
#else
pThis->SwVoiceOut = AUD_open_out(&pThis->card, pThis->SwVoiceOut, "hda.out", pThis, po_callback, pAudioSettings);
#endif
break;
#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
case MC_INDEX:
/* old and new stream settings are not same. Then only call open */
//if (!hdaCodecCompareAudioSettings(&(pThis->SwVoiceIn)->info, pAudioSettings) && !pThis->SwVoiceIn)
break;
#endif /* VBOX_WITH_PDM_AUDIO_DRIVER */
default:
}
return rc;
}
{
AssertLogRelMsgReturn(pThis->cTotalNodes == 0x1c, ("cTotalNodes=%#x, should be 0x1c", pThis->cTotalNodes),
SSMR3PutStructEx(pSSM, &pThis->paNodes[idxNode].SavedState, sizeof(pThis->paNodes[idxNode].SavedState),
return VINF_SUCCESS;
}
{
switch (uVersion)
{
case HDA_SSM_VERSION_1:
break;
case HDA_SSM_VERSION_2:
case HDA_SSM_VERSION_3:
break;
case HDA_SSM_VERSION:
{
if (cNodes != 0x1c)
fFlags = 0;
break;
}
default:
}
{
if (RT_FAILURE(rc))
return rc;
}
/*
* Update stuff after changing the state.
*/
#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
hdaCodecToAudVolume(pThis, &pThis->paNodes[pThis->u8DacLineOut].dac.B_params, PDMAUDIOMIXERCTL_VOLUME);
#else
#endif
#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
hdaCodecToAudVolume(pThis, &pThis->paNodes[pThis->u8DacLineOut].spdifout.B_params, PDMAUDIOMIXERCTL_VOLUME);
hdaCodecToAudVolume(pThis, &pThis->paNodes[pThis->u8AdcVolsLineIn].adcvol.B_params, PDMAUDIOMIXERCTL_LINE_IN);
#else
#endif
return VINF_SUCCESS;
}
{
{
}
return VINF_SUCCESS;
}
{
/* common root node initializers */
pThis->paNodes[0].node.au32F00_param[0] = CODEC_MAKE_F00_00(pThis->u16VendorId, pThis->u16DeviceId);
/* common AFG node initializers */
pThis->paNodes[1].afg.u32F20_param = CODEC_MAKE_F20(pThis->u16VendorId, pThis->u8BSKU, pThis->u8AssemblyId);
#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
/* 44.1 kHz. */
#else
/* 44.1 kHz */
as.endianness = 0;
#endif
uint8_t i;
for (i = 0; i < pThis->cTotalNodes; ++i)
#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
hdaCodecToAudVolume(pThis, &pThis->paNodes[pThis->u8DacLineOut].dac.B_params, PDMAUDIOMIXERCTL_VOLUME);
hdaCodecToAudVolume(pThis, &pThis->paNodes[pThis->u8AdcVolsLineIn].adcvol.B_params, PDMAUDIOMIXERCTL_LINE_IN);
#else
LogRel (("HDA: WARNING: Unable to open PCM IN!\n"));
LogRel (("HDA: WARNING: Unable to open PCM OUT!\n"));
{
AUD_init_null ();
N_ ("No audio devices could be opened. Selecting the NULL audio backend "
"with the consequence that no sound is audible"));
}
{
char szMissingVoices[128];
len += RTStrPrintf (szMissingVoices + len, sizeof(szMissingVoices) - len, len ? ", PCM_out" : "PCM_out");
N_ ("Some audio devices (%s) could not be opened. Guest applications generating audio "
"output or depending on audio input may hang. Make sure your host audio device "
"is working properly. Check the logfile for error messages of the audio "
"subsystem"), szMissingVoices);
}
#endif
return VINF_SUCCESS;
}