2019-09-03 11:58:42 +02:00
|
|
|
/*
|
|
|
|
* File: HdaCodecDump.c
|
|
|
|
*
|
|
|
|
* Copyright (c) 2018 John Davis
|
|
|
|
*
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|
|
|
* in the Software without restriction, including without limitation the rights
|
|
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
|
|
* copies of the Software, and to permit persons to whom the Software is
|
|
|
|
* furnished to do so, subject to the following conditions:
|
|
|
|
*
|
|
|
|
* The above copyright notice and this permission notice shall be included in all
|
|
|
|
* copies or substantial portions of the Software.
|
|
|
|
*
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
|
|
* SOFTWARE.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "HdaCodecDump.h"
|
|
|
|
#include "StateGenerator.h"
|
|
|
|
#include "AmlGenerator.h"
|
|
|
|
|
|
|
|
CONST CHAR8 *gWidgetNames[HDA_WIDGET_TYPE_VENDOR + 1] = {
|
|
|
|
"Audio Output", "Audio Input", "Audio Mixer",
|
|
|
|
"Audio Selector", "Pin Complex", "Power Widget",
|
|
|
|
"Volume Knob Widget", "Beep Generator Widget",
|
|
|
|
"Reserved", "Reserved", "Reserved", "Reserved",
|
|
|
|
"Reserved", "Reserved", "Reserved",
|
|
|
|
"Vendor Defined Widget" };
|
|
|
|
CONST CHAR8 *gPortConnectivities[4] = { "Jack", "None", "Fixed", "Int Jack" };
|
|
|
|
CONST CHAR8 *gDefaultDevices[HDA_CONFIG_DEFAULT_DEVICE_OTHER + 1] = {
|
|
|
|
"Line Out", "Speaker", "HP Out", "CD", "SPDIF Out",
|
|
|
|
"Digital Out", "Modem Line", "Modem Handset", "Line In", "Aux",
|
|
|
|
"Mic", "Telephone", "SPDIF In", "Digital In", "Reserved", "Other" };
|
|
|
|
CONST CHAR8 *gSurfaces[4] = { "Ext", "Int", "Ext", "Other" };
|
|
|
|
CONST CHAR8 *gLocations[0xF + 1] = {
|
|
|
|
"N/A", "Rear", "Front", "Left", "Right", "Top", "Bottom", "Special",
|
|
|
|
"Special", "Special", "Reserved", "Reserved", "Reserved", "Reserved" };
|
|
|
|
CONST CHAR8 *gConnTypes[HDA_CONFIG_DEFAULT_CONN_OTHER + 1] = {
|
|
|
|
"Unknown", "1/8", "1/4", "ATAPI", "RCA", "Optical", "Digital",
|
|
|
|
"Analog", "Multi", "XLR", "RJ11", "Combo", "Other", "Other", "Other", "Other" };
|
|
|
|
CONST CHAR8 *gColors[HDA_CONFIG_DEFAULT_COLOR_OTHER + 1] = {
|
|
|
|
"Unknown", "Black", "Grey", "Blue", "Green", "Red", "Orange",
|
|
|
|
"Yellow", "Purple", "Pink", "Reserved", "Reserved", "Reserved",
|
|
|
|
"Reserved", "White", "Other" };
|
|
|
|
|
|
|
|
#define HDC_ID { 'H','D','C','O' }
|
|
|
|
#define HdaLog(n, ...) MemLog(FALSE, 0, n, ##__VA_ARGS__)
|
|
|
|
|
|
|
|
CONST CHAR8 hdcID[4] = HDC_ID;
|
|
|
|
|
|
|
|
extern UINTN AudioNum;
|
|
|
|
extern HDA_OUTPUTS AudioList[20];
|
|
|
|
extern EFI_AUDIO_IO_PROTOCOL *AudioIo;
|
2020-02-17 21:41:09 +01:00
|
|
|
extern CONST CHAR16 *OEMPath;
|
2019-09-03 11:58:42 +02:00
|
|
|
|
|
|
|
VOID
|
|
|
|
EFIAPI
|
|
|
|
HdaCodecDumpPrintRatesFormats(
|
|
|
|
IN UINT32 Rates,
|
|
|
|
IN UINT32 Formats) {
|
|
|
|
// Print sample rates.
|
|
|
|
HdaLog(" rates [0x%04X]:", (UINT16)Rates);
|
|
|
|
if (Rates & HDA_PARAMETER_SUPPORTED_PCM_SIZE_RATES_8KHZ)
|
|
|
|
HdaLog(" 8000");
|
|
|
|
if (Rates & HDA_PARAMETER_SUPPORTED_PCM_SIZE_RATES_11KHZ)
|
|
|
|
HdaLog(" 11025");
|
|
|
|
if (Rates & HDA_PARAMETER_SUPPORTED_PCM_SIZE_RATES_16KHZ)
|
|
|
|
HdaLog(" 16000");
|
|
|
|
if (Rates & HDA_PARAMETER_SUPPORTED_PCM_SIZE_RATES_22KHZ)
|
|
|
|
HdaLog(" 22050");
|
|
|
|
if (Rates & HDA_PARAMETER_SUPPORTED_PCM_SIZE_RATES_32KHZ)
|
|
|
|
HdaLog(" 32000");
|
|
|
|
if (Rates & HDA_PARAMETER_SUPPORTED_PCM_SIZE_RATES_44KHZ)
|
|
|
|
HdaLog(" 44100");
|
|
|
|
if (Rates & HDA_PARAMETER_SUPPORTED_PCM_SIZE_RATES_48KHZ)
|
|
|
|
HdaLog(" 48000");
|
|
|
|
if (Rates & HDA_PARAMETER_SUPPORTED_PCM_SIZE_RATES_88KHZ)
|
|
|
|
HdaLog(" 88200");
|
|
|
|
if (Rates & HDA_PARAMETER_SUPPORTED_PCM_SIZE_RATES_96KHZ)
|
|
|
|
HdaLog(" 96000");
|
|
|
|
if (Rates & HDA_PARAMETER_SUPPORTED_PCM_SIZE_RATES_176KHZ)
|
|
|
|
HdaLog(" 176400");
|
|
|
|
if (Rates & HDA_PARAMETER_SUPPORTED_PCM_SIZE_RATES_192KHZ)
|
|
|
|
HdaLog(" 192000");
|
|
|
|
if (Rates & HDA_PARAMETER_SUPPORTED_PCM_SIZE_RATES_384KHZ)
|
|
|
|
HdaLog(" 384000");
|
|
|
|
HdaLog("\n");
|
|
|
|
|
|
|
|
// Print bits.
|
|
|
|
HdaLog(" bits [0x%04X]:", (UINT16)(Rates >> 16));
|
|
|
|
if (Rates & HDA_PARAMETER_SUPPORTED_PCM_SIZE_RATES_8BIT)
|
|
|
|
HdaLog(" 8");
|
|
|
|
if (Rates & HDA_PARAMETER_SUPPORTED_PCM_SIZE_RATES_16BIT)
|
|
|
|
HdaLog(" 16");
|
|
|
|
if (Rates & HDA_PARAMETER_SUPPORTED_PCM_SIZE_RATES_20BIT)
|
|
|
|
HdaLog(" 20");
|
|
|
|
if (Rates & HDA_PARAMETER_SUPPORTED_PCM_SIZE_RATES_24BIT)
|
|
|
|
HdaLog(" 24");
|
|
|
|
if (Rates & HDA_PARAMETER_SUPPORTED_PCM_SIZE_RATES_32BIT)
|
|
|
|
HdaLog(" 32");
|
|
|
|
HdaLog("\n");
|
|
|
|
|
|
|
|
// Print formats.
|
|
|
|
HdaLog(" formats [0x%08X]:", Formats);
|
|
|
|
if (Formats & HDA_PARAMETER_SUPPORTED_STREAM_FORMATS_PCM)
|
|
|
|
HdaLog(" PCM");
|
|
|
|
if (Formats & HDA_PARAMETER_SUPPORTED_STREAM_FORMATS_FLOAT32)
|
|
|
|
HdaLog(" FLOAT32");
|
|
|
|
if (Formats & HDA_PARAMETER_SUPPORTED_STREAM_FORMATS_AC3)
|
|
|
|
HdaLog(" AC3");
|
|
|
|
HdaLog("\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
|
|
EFIAPI
|
|
|
|
HdaCodecDumpPrintAmpCaps(
|
|
|
|
IN UINT32 AmpCaps) {
|
|
|
|
if (AmpCaps) {
|
|
|
|
HdaLog("ofs=0x%02X, nsteps=0x%02X, stepsize=%02X, mute=%u\n",
|
|
|
|
HDA_PARAMETER_AMP_CAPS_OFFSET(AmpCaps), HDA_PARAMETER_AMP_CAPS_NUM_STEPS(AmpCaps),
|
|
|
|
HDA_PARAMETER_AMP_CAPS_STEP_SIZE(AmpCaps), (AmpCaps & HDA_PARAMETER_AMP_CAPS_MUTE) != 0);
|
|
|
|
} else
|
|
|
|
HdaLog("N/A\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
|
|
EFIAPI
|
|
|
|
HdaCodecDumpPrintWidgets(
|
|
|
|
IN EFI_HDA_IO_PROTOCOL *HdaIo,
|
|
|
|
//IN HDA_WIDGET *Widgets,
|
|
|
|
IN HDA_WIDGET_DEV *Widgets,
|
|
|
|
IN UINTN WidgetCount) {
|
|
|
|
// Print each widget.
|
|
|
|
for (UINTN w = 0; w < WidgetCount; w++) {
|
|
|
|
// Print header and capabilities.
|
|
|
|
HdaLog("Node 0x%02X [%a] wcaps 0x%08X:", Widgets[w].NodeId,
|
|
|
|
gWidgetNames[HDA_PARAMETER_WIDGET_CAPS_TYPE(Widgets[w].Capabilities)], Widgets[w].Capabilities);
|
|
|
|
if (Widgets[w].Capabilities & HDA_PARAMETER_WIDGET_CAPS_STEREO)
|
|
|
|
HdaLog(" Stereo");
|
|
|
|
else
|
|
|
|
HdaLog(" Mono");
|
|
|
|
if (Widgets[w].Capabilities & HDA_PARAMETER_WIDGET_CAPS_DIGITAL)
|
|
|
|
HdaLog(" Digital");
|
|
|
|
if (Widgets[w].Capabilities & HDA_PARAMETER_WIDGET_CAPS_IN_AMP)
|
|
|
|
HdaLog(" Amp-In");
|
|
|
|
if (Widgets[w].Capabilities & HDA_PARAMETER_WIDGET_CAPS_OUT_AMP)
|
|
|
|
HdaLog(" Amp-Out");
|
|
|
|
if (Widgets[w].Capabilities & HDA_PARAMETER_WIDGET_CAPS_L_R_SWAP)
|
|
|
|
HdaLog(" R/L");
|
|
|
|
HdaLog("\n");
|
|
|
|
|
|
|
|
// Print input amp info.
|
|
|
|
if (Widgets[w].Capabilities & HDA_PARAMETER_WIDGET_CAPS_IN_AMP) {
|
|
|
|
// Print caps.
|
|
|
|
HdaLog(" Amp-In caps: ");
|
|
|
|
HdaCodecDumpPrintAmpCaps(Widgets[w].AmpInCapabilities);
|
|
|
|
|
|
|
|
// Print default values.
|
|
|
|
HdaLog(" Amp-In vals:");
|
|
|
|
for (UINT8 i = 0; i < HDA_PARAMETER_CONN_LIST_LENGTH_LEN(Widgets[w].ConnectionListLength); i++) {
|
|
|
|
if (Widgets[w].Capabilities & HDA_PARAMETER_WIDGET_CAPS_STEREO)
|
|
|
|
HdaLog(" [0x%02X 0x%02X]", Widgets[w].AmpInLeftDefaultGainMute[i], Widgets[w].AmpInRightDefaultGainMute[i]);
|
|
|
|
else
|
|
|
|
HdaLog(" [0x%02X]", Widgets[w].AmpInLeftDefaultGainMute[i]);
|
|
|
|
}
|
|
|
|
HdaLog("\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
// Print output amp info.
|
|
|
|
if (Widgets[w].Capabilities & HDA_PARAMETER_WIDGET_CAPS_OUT_AMP) {
|
|
|
|
// Print caps.
|
|
|
|
HdaLog(" Amp-Out caps: ");
|
|
|
|
HdaCodecDumpPrintAmpCaps(Widgets[w].AmpOutCapabilities);
|
|
|
|
|
|
|
|
// Print default values.
|
|
|
|
HdaLog(" Amp-Out vals:");
|
|
|
|
if (Widgets[w].Capabilities & HDA_PARAMETER_WIDGET_CAPS_STEREO)
|
|
|
|
HdaLog(" [0x%02X 0x%02X]\n", Widgets[w].AmpOutLeftDefaultGainMute, Widgets[w].AmpOutRightDefaultGainMute);
|
|
|
|
else
|
|
|
|
HdaLog(" [0x%02X]\n", Widgets[w].AmpOutLeftDefaultGainMute);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Print pin complexe info.
|
|
|
|
if (HDA_PARAMETER_WIDGET_CAPS_TYPE(Widgets[w].Capabilities) == HDA_WIDGET_TYPE_PIN_COMPLEX) {
|
|
|
|
// Print pin capabilities.
|
|
|
|
HdaLog(" Pincap 0x%08X:", Widgets[w].PinCapabilities);
|
|
|
|
if (Widgets[w].PinCapabilities & HDA_PARAMETER_PIN_CAPS_INPUT)
|
|
|
|
HdaLog(" IN");
|
|
|
|
if (Widgets[w].PinCapabilities & HDA_PARAMETER_PIN_CAPS_OUTPUT)
|
|
|
|
HdaLog(" OUT");
|
|
|
|
if (Widgets[w].PinCapabilities & HDA_PARAMETER_PIN_CAPS_HEADPHONE)
|
|
|
|
HdaLog(" HP");
|
|
|
|
if (Widgets[w].PinCapabilities & HDA_PARAMETER_PIN_CAPS_EAPD)
|
|
|
|
HdaLog(" EAPD");
|
|
|
|
if (Widgets[w].PinCapabilities & HDA_PARAMETER_PIN_CAPS_TRIGGER)
|
|
|
|
HdaLog(" Trigger");
|
|
|
|
if (Widgets[w].PinCapabilities & HDA_PARAMETER_PIN_CAPS_PRESENCE)
|
|
|
|
HdaLog(" Detect");
|
|
|
|
if (Widgets[w].PinCapabilities & HDA_PARAMETER_PIN_CAPS_HBR)
|
|
|
|
HdaLog(" HBR");
|
|
|
|
if (Widgets[w].PinCapabilities & HDA_PARAMETER_PIN_CAPS_HDMI)
|
|
|
|
HdaLog(" HDMI");
|
|
|
|
if (Widgets[w].PinCapabilities & HDA_PARAMETER_PIN_CAPS_DISPLAYPORT)
|
|
|
|
HdaLog(" DP");
|
|
|
|
HdaLog("\n");
|
|
|
|
|
|
|
|
// Print EAPD info.
|
|
|
|
if (Widgets[w].PinCapabilities & HDA_PARAMETER_PIN_CAPS_EAPD) {
|
|
|
|
HdaLog(" EAPD 0x%X:", Widgets[w].DefaultEapd);
|
|
|
|
if (Widgets[w].DefaultEapd & HDA_EAPD_BTL_ENABLE_BTL)
|
|
|
|
HdaLog(" BTL");
|
|
|
|
if (Widgets[w].DefaultEapd & HDA_EAPD_BTL_ENABLE_EAPD)
|
|
|
|
HdaLog(" EAPD");
|
|
|
|
if (Widgets[w].DefaultEapd & HDA_EAPD_BTL_ENABLE_L_R_SWAP)
|
|
|
|
HdaLog(" R/L");
|
|
|
|
HdaLog("\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
// Print pin default header.
|
|
|
|
HdaLog(" Pin Default 0x%08X: [%a] %a at %a %a\n", Widgets[w].DefaultConfiguration,
|
|
|
|
gPortConnectivities[HDA_VERB_GET_CONFIGURATION_DEFAULT_PORT_CONN(Widgets[w].DefaultConfiguration)],
|
|
|
|
gDefaultDevices[HDA_VERB_GET_CONFIGURATION_DEFAULT_DEVICE(Widgets[w].DefaultConfiguration)],
|
|
|
|
gSurfaces[HDA_VERB_GET_CONFIGURATION_DEFAULT_SURF(Widgets[w].DefaultConfiguration)],
|
|
|
|
gLocations[HDA_VERB_GET_CONFIGURATION_DEFAULT_LOC(Widgets[w].DefaultConfiguration)]);
|
|
|
|
|
|
|
|
// Print connection type and color.
|
|
|
|
HdaLog(" Conn = %a, Color = %a\n",
|
|
|
|
gConnTypes[HDA_VERB_GET_CONFIGURATION_DEFAULT_CONN_TYPE(Widgets[w].DefaultConfiguration)],
|
|
|
|
gColors[HDA_VERB_GET_CONFIGURATION_DEFAULT_COLOR(Widgets[w].DefaultConfiguration)]);
|
|
|
|
|
|
|
|
// Print default association and sequence.
|
|
|
|
HdaLog(" DefAssociation = 0x%1X, Sequence = 0x%1X\n",
|
|
|
|
HDA_VERB_GET_CONFIGURATION_DEFAULT_ASSOCIATION(Widgets[w].DefaultConfiguration),
|
|
|
|
HDA_VERB_GET_CONFIGURATION_DEFAULT_SEQUENCE(Widgets[w].DefaultConfiguration));
|
|
|
|
|
|
|
|
// Print default pin control.
|
|
|
|
HdaLog(" Pin-ctls: 0x%02X:", Widgets[w].DefaultPinControl);
|
|
|
|
if (Widgets[w].DefaultPinControl & HDA_PIN_WIDGET_CONTROL_VREF_EN)
|
|
|
|
HdaLog(" VREF");
|
|
|
|
if (Widgets[w].DefaultPinControl & HDA_PIN_WIDGET_CONTROL_IN_EN)
|
|
|
|
HdaLog(" IN");
|
|
|
|
if (Widgets[w].DefaultPinControl & HDA_PIN_WIDGET_CONTROL_OUT_EN)
|
|
|
|
HdaLog(" OUT");
|
|
|
|
if (Widgets[w].DefaultPinControl & HDA_PIN_WIDGET_CONTROL_HP_EN)
|
|
|
|
HdaLog(" HP");
|
|
|
|
HdaLog("\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
// Print connections.
|
|
|
|
if (Widgets[w].Capabilities & HDA_PARAMETER_WIDGET_CAPS_CONN_LIST) {
|
|
|
|
HdaLog(" Connection: %u\n ", HDA_PARAMETER_CONN_LIST_LENGTH_LEN(Widgets[w].ConnectionListLength));
|
|
|
|
for (UINT8 c = 0; c < HDA_PARAMETER_CONN_LIST_LENGTH_LEN(Widgets[w].ConnectionListLength); c++) {
|
|
|
|
HdaLog(" 0x%02X", Widgets[w].Connections[c]);
|
|
|
|
//if (c == Widgets[w].ConnectionSelect)
|
|
|
|
// HdaLog("*");
|
|
|
|
}
|
|
|
|
HdaLog("\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
EFI_STATUS SaveHdaDumpTxt() {
|
2019-09-12 14:44:44 +02:00
|
|
|
EFI_STATUS Status = EFI_NOT_FOUND;
|
2019-09-03 11:58:42 +02:00
|
|
|
AUDIO_IO_PRIVATE_DATA *AudioIoPrivateData;
|
|
|
|
HDA_CODEC_DEV *HdaCodecDev;
|
|
|
|
EFI_HDA_CODEC_INFO_PROTOCOL *HdaCodecInfo;
|
|
|
|
HDA_FUNC_GROUP *AudioFuncGroup;
|
|
|
|
EFI_HDA_IO_PROTOCOL *HdaIo;
|
|
|
|
CHAR16 *MiscPath = PoolPrint(L"%s\\misc", OEMPath);
|
|
|
|
CHAR8 *MemLogStart;
|
|
|
|
UINTN MemLogStartLen;
|
|
|
|
|
|
|
|
// Print each codec found.
|
|
|
|
for (UINTN i = 0; i < AudioNum; i++) {
|
|
|
|
MemLogStartLen = GetMemLogLen();
|
|
|
|
MemLogStart = GetMemLogBuffer() + MemLogStartLen;
|
|
|
|
|
|
|
|
HdaLog("HdaCodecDump Start\n");
|
|
|
|
|
|
|
|
Status = gBS->HandleProtocol(AudioList[i].Handle, &gEfiAudioIoProtocolGuid, (VOID**)&AudioIo);
|
|
|
|
|
|
|
|
if (EFI_ERROR(Status))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
AudioIoPrivateData = AUDIO_IO_PRIVATE_DATA_FROM_THIS(AudioIo);
|
|
|
|
|
|
|
|
if (!AudioIoPrivateData || !AudioIoPrivateData->HdaCodecDev ||
|
|
|
|
!AudioIoPrivateData->HdaCodecDev->HdaIo || !AudioIoPrivateData->HdaCodecDev->AudioFuncGroup)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
HdaCodecDev = AudioIoPrivateData->HdaCodecDev;
|
|
|
|
HdaCodecInfo = &HdaCodecDev->HdaCodecInfoData->HdaCodecInfo;
|
|
|
|
AudioFuncGroup = HdaCodecDev->AudioFuncGroup;
|
|
|
|
HdaIo = HdaCodecDev->HdaIo;
|
|
|
|
|
|
|
|
// Get name.
|
|
|
|
HdaLog("Codec: %s\n", HdaCodecDev->Name);
|
|
|
|
|
|
|
|
// Get address
|
|
|
|
UINT8 CodecAddress;
|
|
|
|
Status = HdaIo->GetAddress(HdaIo, &CodecAddress);
|
|
|
|
HdaLog("Address: %u\n", CodecAddress);
|
|
|
|
|
|
|
|
// Get AFG ID.
|
|
|
|
HdaLog("AFG Function Id: 0x%1X (unsol %u)\n", AudioFuncGroup->NodeId, AudioFuncGroup->UnsolCapable);
|
|
|
|
|
|
|
|
HdaLog("Vendor ID: 0x%08X\n", HdaCodecDev->VendorId);
|
|
|
|
HdaLog("Revision ID: 0x%08X\n", HdaCodecDev->RevisionId);
|
|
|
|
|
|
|
|
// Get supported rates/formats.
|
|
|
|
if ((AudioFuncGroup->SupportedPcmRates != 0) || (AudioFuncGroup->SupportedFormats != 0)) {
|
|
|
|
HdaLog("Default PCM:\n");
|
|
|
|
HdaCodecDumpPrintRatesFormats(AudioFuncGroup->SupportedPcmRates, AudioFuncGroup->SupportedFormats);
|
|
|
|
} else
|
|
|
|
HdaLog("Default PCM: N/A\n");
|
|
|
|
|
|
|
|
// Get default amp caps.
|
|
|
|
HdaLog("Default Amp-In caps: ");
|
|
|
|
HdaCodecDumpPrintAmpCaps(AudioFuncGroup->AmpInCapabilities);
|
|
|
|
HdaLog("Default Amp-Out caps: ");
|
|
|
|
HdaCodecDumpPrintAmpCaps(AudioFuncGroup->AmpOutCapabilities);
|
|
|
|
|
|
|
|
// Get widgets.
|
|
|
|
HDA_WIDGET_DEV *Widgets = AudioFuncGroup->Widgets;
|
|
|
|
UINTN WidgetCount = AudioFuncGroup->WidgetsCount;
|
|
|
|
HdaCodecDumpPrintWidgets(HdaIo, Widgets, WidgetCount);
|
|
|
|
|
|
|
|
CHAR16 *PathHdaDump = PoolPrint(L"%s\\HdaCodec#%d (%s).txt", MiscPath, i, HdaCodecDev->Name);
|
|
|
|
|
|
|
|
if (PathHdaDump != NULL) {
|
|
|
|
Status = egSaveFile(SelfRootDir, PathHdaDump, (VOID *)MemLogStart, GetMemLogLen() - MemLogStartLen);
|
|
|
|
|
|
|
|
if (EFI_ERROR(Status))
|
|
|
|
Status = egSaveFile(NULL, PathHdaDump, (VOID *)MemLogStart, GetMemLogLen() - MemLogStartLen);
|
|
|
|
|
|
|
|
FreePool(PathHdaDump);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
FreePool(MiscPath);
|
|
|
|
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
EFI_STATUS SaveHdaDumpBin() {
|
|
|
|
EFI_STATUS Status = EFI_NOT_FOUND;
|
|
|
|
AUDIO_IO_PRIVATE_DATA *AudioIoPrivateData;
|
|
|
|
HDA_CODEC_DEV *HdaCodecDev;
|
|
|
|
EFI_HDA_CODEC_INFO_PROTOCOL *HdaCodecInfo;
|
|
|
|
HDA_FUNC_GROUP *AudioFuncGroup;
|
|
|
|
EFI_HDA_IO_PROTOCOL *HdaIo;
|
|
|
|
CHAR16 *MiscPath = PoolPrint(L"%s\\misc", OEMPath);
|
|
|
|
|
|
|
|
if (MiscPath == NULL)
|
|
|
|
return EFI_OUT_OF_RESOURCES;
|
|
|
|
|
|
|
|
for (UINTN i = 0; i < AudioNum; i++) {
|
|
|
|
HDA_WIDGET_DEV *Widgets;
|
|
|
|
UINTN WidgetCount;
|
|
|
|
UINT32 HdaCodecDataSize;
|
|
|
|
HdaCodec HdaCodec;
|
|
|
|
UINT8 CodecAddress;
|
|
|
|
UINT8 *HdaCodecData;
|
|
|
|
UINT8 *HdaCodecDataPtr;
|
|
|
|
CHAR16 *PathHdaDump;
|
|
|
|
|
|
|
|
Status = gBS->HandleProtocol(AudioList[i].Handle, &gEfiAudioIoProtocolGuid, (VOID**)&AudioIo);
|
|
|
|
|
|
|
|
if (EFI_ERROR(Status))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
AudioIoPrivateData = AUDIO_IO_PRIVATE_DATA_FROM_THIS(AudioIo);
|
|
|
|
|
|
|
|
if (!AudioIoPrivateData || !AudioIoPrivateData->HdaCodecDev || !AudioIoPrivateData->HdaCodecDev->HdaIo)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
HdaCodecDev = AudioIoPrivateData->HdaCodecDev;
|
|
|
|
if(!HdaCodecDev || !HdaCodecDev->AudioFuncGroup)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
HdaCodecInfo = &HdaCodecDev->HdaCodecInfoData->HdaCodecInfo;
|
|
|
|
AudioFuncGroup = HdaCodecDev->AudioFuncGroup;
|
|
|
|
HdaIo = HdaCodecDev->HdaIo;
|
|
|
|
|
|
|
|
Widgets = AudioFuncGroup->Widgets;
|
|
|
|
WidgetCount = AudioFuncGroup->WidgetsCount;
|
|
|
|
HdaCodecDataSize = (UINT32)(sizeof(HdaCodec) + (WidgetCount * sizeof(HdaWidget)));
|
|
|
|
|
|
|
|
// Copy codec data
|
|
|
|
ZeroMem(&HdaCodec, sizeof(HdaCodec));
|
|
|
|
|
|
|
|
if(!EFI_ERROR(Status)) {
|
|
|
|
for (UINT32 j = 0; j < HDA_MAX_NAMELEN; j++) {
|
|
|
|
HdaCodec.Name[j] = (CHAR8)(HdaCodecDev->Name[j] & 0xFF);
|
|
|
|
if (HdaCodecDev->Name[j] == 0x0000)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Status = HdaIo->GetAddress(HdaIo, &CodecAddress);
|
|
|
|
|
|
|
|
CopyMem(HdaCodec.Header, hdcID, 4);
|
|
|
|
|
|
|
|
HdaCodec.CodecAddress = CodecAddress;
|
|
|
|
HdaCodec.AudioFuncId = AudioFuncGroup->NodeId;
|
|
|
|
HdaCodec.Unsol = AudioFuncGroup->UnsolCapable;
|
|
|
|
HdaCodec.VendorId = HdaCodecDev->VendorId;
|
|
|
|
HdaCodec.RevisionId = HdaCodecDev->RevisionId;
|
|
|
|
HdaCodec.Rates = AudioFuncGroup->SupportedPcmRates;
|
|
|
|
HdaCodec.Formats = AudioFuncGroup->SupportedFormats;
|
|
|
|
HdaCodec.AmpInCaps = AudioFuncGroup->AmpInCapabilities;
|
|
|
|
HdaCodec.AmpOutCaps = AudioFuncGroup->AmpOutCapabilities;
|
|
|
|
HdaCodec.WidgetCount = AudioFuncGroup->WidgetsCount;
|
|
|
|
|
|
|
|
// Allocate space for codec data
|
2019-12-21 01:31:49 +01:00
|
|
|
HdaCodecData = (__typeof__(HdaCodecData))AllocateZeroPool(HdaCodecDataSize);
|
2019-09-03 11:58:42 +02:00
|
|
|
HdaCodecDataPtr = HdaCodecData;
|
|
|
|
|
|
|
|
if (!HdaCodecData)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
CopyMem(HdaCodecDataPtr, &HdaCodec, sizeof(HdaCodec));
|
|
|
|
HdaCodecDataPtr += sizeof(HdaCodec);
|
|
|
|
|
|
|
|
for (UINT32 w = 0; w < WidgetCount; w++) {
|
|
|
|
UINTN ConnectionListLength;
|
|
|
|
HdaWidget HdaWidget;
|
|
|
|
|
|
|
|
ConnectionListLength = HDA_PARAMETER_CONN_LIST_LENGTH_LEN(Widgets[w].ConnectionListLength);
|
|
|
|
|
|
|
|
ZeroMem(&HdaWidget, sizeof(HdaWidget));
|
|
|
|
|
|
|
|
HdaWidget.NodeId = Widgets[w].NodeId;
|
|
|
|
HdaWidget.Type = Widgets[w].Type;
|
|
|
|
HdaWidget.Capabilities = Widgets[w].Capabilities;
|
|
|
|
HdaWidget.DefaultUnSol = Widgets[w].DefaultUnSol;
|
|
|
|
HdaWidget.ConnectionListLength = Widgets[w].ConnectionListLength;
|
|
|
|
HdaWidget.ConnectionSelect = 0;
|
|
|
|
HdaWidget.SupportedPowerStates = Widgets[w].SupportedPowerStates;
|
|
|
|
HdaWidget.DefaultPowerState = Widgets[w].DefaultPowerState;
|
|
|
|
HdaWidget.AmpOverride = Widgets[w].AmpOverride;
|
|
|
|
HdaWidget.AmpInCapabilities = Widgets[w].AmpInCapabilities;
|
|
|
|
HdaWidget.AmpOutCapabilities = Widgets[w].AmpOutCapabilities;
|
|
|
|
HdaWidget.AmpOutLeftDefaultGainMute = Widgets[w].AmpOutLeftDefaultGainMute;
|
|
|
|
HdaWidget.AmpOutRightDefaultGainMute = Widgets[w].AmpOutRightDefaultGainMute;
|
|
|
|
HdaWidget.SupportedPcmRates = Widgets[w].SupportedPcmRates;
|
|
|
|
HdaWidget.SupportedFormats = Widgets[w].SupportedFormats;
|
|
|
|
HdaWidget.DefaultConvFormat = Widgets[w].DefaultConvFormat;
|
|
|
|
HdaWidget.DefaultConvStreamChannel = Widgets[w].DefaultConvStreamChannel;
|
|
|
|
HdaWidget.DefaultConvChannelCount = Widgets[w].DefaultConvChannelCount;
|
|
|
|
HdaWidget.PinCapabilities = Widgets[w].PinCapabilities;
|
|
|
|
HdaWidget.DefaultEapd = Widgets[w].DefaultEapd;
|
|
|
|
HdaWidget.DefaultPinControl = Widgets[w].DefaultPinControl;
|
|
|
|
HdaWidget.DefaultConfiguration = Widgets[w].DefaultConfiguration;
|
|
|
|
HdaWidget.VolumeCapabilities = Widgets[w].VolumeCapabilities;
|
|
|
|
HdaWidget.DefaultVolume = Widgets[w].DefaultVolume;
|
|
|
|
|
|
|
|
for (UINT32 c = 0; c < ConnectionListLength; c++) {
|
|
|
|
if (Widgets[w].Capabilities & HDA_PARAMETER_WIDGET_CAPS_IN_AMP) {
|
|
|
|
HdaWidget.AmpInLeftDefaultGainMute[c] = Widgets[w].AmpInLeftDefaultGainMute[c];
|
|
|
|
|
|
|
|
if (Widgets[w].Capabilities & HDA_PARAMETER_WIDGET_CAPS_STEREO) {
|
|
|
|
HdaWidget.AmpInRightDefaultGainMute[c] = Widgets[w].AmpInRightDefaultGainMute[c];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Widgets[w].Capabilities & HDA_PARAMETER_WIDGET_CAPS_CONN_LIST) {
|
|
|
|
HdaWidget.Connections[c] = Widgets[w].Connections[c];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
CopyMem(HdaCodecDataPtr, &HdaWidget, sizeof(HdaWidget));
|
|
|
|
HdaCodecDataPtr += sizeof(HdaWidget);
|
|
|
|
}
|
|
|
|
|
|
|
|
PathHdaDump = PoolPrint(L"%s\\HdaCodec#%d (%s).bin", MiscPath, i, HdaCodecDev->Name);
|
|
|
|
|
|
|
|
if (PathHdaDump != NULL) {
|
|
|
|
Status = egSaveFile(SelfRootDir, PathHdaDump, HdaCodecData, HdaCodecDataSize);
|
|
|
|
|
|
|
|
if (EFI_ERROR(Status))
|
|
|
|
Status = egSaveFile(NULL, PathHdaDump, HdaCodecData, HdaCodecDataSize);
|
|
|
|
|
|
|
|
FreePool(PathHdaDump);
|
|
|
|
}
|
|
|
|
|
|
|
|
FreePool(HdaCodecData);
|
|
|
|
}
|
|
|
|
|
|
|
|
FreePool(MiscPath);
|
|
|
|
|
|
|
|
return EFI_SUCCESS;
|
2019-09-12 14:44:44 +02:00
|
|
|
}
|