diff --git a/Drivers/AudioDxe/AudioDxe.c b/Drivers/AudioDxe/AudioDxe.c index 42739bd8d..1051ef07e 100644 --- a/Drivers/AudioDxe/AudioDxe.c +++ b/Drivers/AudioDxe/AudioDxe.c @@ -52,7 +52,8 @@ EFI_STATUS EFIAPI AudioDxeInit( IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable) { + IN EFI_SYSTEM_TABLE *SystemTable) +{ DEBUG((DEBUG_INFO, "Starting AudioDxe...\n")); // Create variables. diff --git a/Drivers/AudioDxe/HdaCodec/HdaCodec.c b/Drivers/AudioDxe/HdaCodec/HdaCodec.c index d767ac32d..208ca5ea1 100644 --- a/Drivers/AudioDxe/HdaCodec/HdaCodec.c +++ b/Drivers/AudioDxe/HdaCodec/HdaCodec.c @@ -30,1134 +30,1137 @@ EFI_STATUS EFIAPI HdaCodecProbeWidget( - IN HDA_WIDGET_DEV *HdaWidget) + IN HDA_WIDGET_DEV *HdaWidget) { - //DEBUG((DEBUG_INFO, "HdaCodecProbeWidget(): start\n")); - - // Create variables. - EFI_STATUS Status; - EFI_HDA_IO_PROTOCOL *HdaIo = HdaWidget->FuncGroup->HdaCodecDev->HdaIo; - UINT32 Response = 0; - UINT8 ConnectionListThresh; - UINT8 AmpInCount; - - // Get widget capabilities. + //DEBUG((DEBUG_INFO, "HdaCodecProbeWidget(): start\n")); + + // Create variables. + EFI_STATUS Status; + EFI_HDA_IO_PROTOCOL *HdaIo = HdaWidget->FuncGroup->HdaCodecDev->HdaIo; + UINT32 Response = 0; + UINT8 ConnectionListThresh; + UINT8 AmpInCount; + + // Get widget capabilities. + Status = HdaIo->SendCommand(HdaIo, HdaWidget->NodeId, + HDA_CODEC_VERB(HDA_VERB_GET_PARAMETER, HDA_PARAMETER_WIDGET_CAPS), &HdaWidget->Capabilities); + if (EFI_ERROR(Status)) + return Status; + HdaWidget->Type = HDA_PARAMETER_WIDGET_CAPS_TYPE(HdaWidget->Capabilities); + HdaWidget->AmpOverride = HdaWidget->Capabilities & HDA_PARAMETER_WIDGET_CAPS_AMP_OVERRIDE; + //DEBUG((DEBUG_INFO, "Widget @ 0x%X type: 0x%X\n", HdaWidget->NodeId, HdaWidget->Type)); + //DEBUG((DEBUG_INFO, "Widget @ 0x%X capabilities: 0x%X\n", HdaWidget->NodeId, HdaWidget->Capabilities)); + + // Get default unsolicitation. + if (HdaWidget->Capabilities & HDA_PARAMETER_WIDGET_CAPS_UNSOL_CAPABLE) { Status = HdaIo->SendCommand(HdaIo, HdaWidget->NodeId, - HDA_CODEC_VERB(HDA_VERB_GET_PARAMETER, HDA_PARAMETER_WIDGET_CAPS), &HdaWidget->Capabilities); + HDA_CODEC_VERB(HDA_VERB_GET_UNSOL_RESPONSE, 0), &Response); if (EFI_ERROR(Status)) - return Status; - HdaWidget->Type = HDA_PARAMETER_WIDGET_CAPS_TYPE(HdaWidget->Capabilities); - HdaWidget->AmpOverride = HdaWidget->Capabilities & HDA_PARAMETER_WIDGET_CAPS_AMP_OVERRIDE; - //DEBUG((DEBUG_INFO, "Widget @ 0x%X type: 0x%X\n", HdaWidget->NodeId, HdaWidget->Type)); - //DEBUG((DEBUG_INFO, "Widget @ 0x%X capabilities: 0x%X\n", HdaWidget->NodeId, HdaWidget->Capabilities)); - - // Get default unsolicitation. - if (HdaWidget->Capabilities & HDA_PARAMETER_WIDGET_CAPS_UNSOL_CAPABLE) { - Status = HdaIo->SendCommand(HdaIo, HdaWidget->NodeId, - HDA_CODEC_VERB(HDA_VERB_GET_UNSOL_RESPONSE, 0), &Response); - if (EFI_ERROR(Status)) - return Status; - HdaWidget->DefaultUnSol = (UINT8)Response; - //DEBUG((DEBUG_INFO, "Widget @ 0x%X unsolicitation: 0x%X\n", HdaWidget->NodeId, HdaWidget->DefaultUnSol)); - } - + return Status; + HdaWidget->DefaultUnSol = (UINT8)Response; + //DEBUG((DEBUG_INFO, "Widget @ 0x%X unsolicitation: 0x%X\n", HdaWidget->NodeId, HdaWidget->DefaultUnSol)); + } + + // Get connections. + if (HdaWidget->Capabilities & HDA_PARAMETER_WIDGET_CAPS_CONN_LIST) { + // Get connection list length. + Status = HdaIo->SendCommand(HdaIo, HdaWidget->NodeId, + HDA_CODEC_VERB(HDA_VERB_GET_PARAMETER, HDA_PARAMETER_CONN_LIST_LENGTH), &HdaWidget->ConnectionListLength); + if (EFI_ERROR(Status)) + return Status; + HdaWidget->ConnectionCount = HDA_PARAMETER_CONN_LIST_LENGTH_LEN(HdaWidget->ConnectionListLength); + //DEBUG((DEBUG_INFO, "Widget @ 0x%X connection list length: 0x%X\n", HdaWidget->NodeId, HdaWidget->ConnectionListLength)); + // Get connections. - if (HdaWidget->Capabilities & HDA_PARAMETER_WIDGET_CAPS_CONN_LIST) { - // Get connection list length. + HdaWidget->Connections = AllocateZeroPool(sizeof(UINT16) * HdaWidget->ConnectionCount); + if (HdaWidget->Connections == NULL) + return EFI_OUT_OF_RESOURCES; + ConnectionListThresh = (HdaWidget->ConnectionListLength & HDA_PARAMETER_CONN_LIST_LENGTH_LONG) ? 2 : 4; + for (UINT8 c = 0; c < HdaWidget->ConnectionCount; c++) { + // Do we need to get entries? + if (!(c % ConnectionListThresh)) { + // Get connection entries. Status = HdaIo->SendCommand(HdaIo, HdaWidget->NodeId, - HDA_CODEC_VERB(HDA_VERB_GET_PARAMETER, HDA_PARAMETER_CONN_LIST_LENGTH), &HdaWidget->ConnectionListLength); + HDA_CODEC_VERB(HDA_VERB_GET_CONN_LIST_ENTRY, c), &Response); if (EFI_ERROR(Status)) - return Status; - HdaWidget->ConnectionCount = HDA_PARAMETER_CONN_LIST_LENGTH_LEN(HdaWidget->ConnectionListLength); - //DEBUG((DEBUG_INFO, "Widget @ 0x%X connection list length: 0x%X\n", HdaWidget->NodeId, HdaWidget->ConnectionListLength)); - - // Get connections. - HdaWidget->Connections = AllocateZeroPool(sizeof(UINT16) * HdaWidget->ConnectionCount); - if (HdaWidget->Connections == NULL) - return EFI_OUT_OF_RESOURCES; - ConnectionListThresh = (HdaWidget->ConnectionListLength & HDA_PARAMETER_CONN_LIST_LENGTH_LONG) ? 2 : 4; - for (UINT8 c = 0; c < HdaWidget->ConnectionCount; c++) { - // Do we need to get entries? - if (!(c % ConnectionListThresh)) { - // Get connection entries. - Status = HdaIo->SendCommand(HdaIo, HdaWidget->NodeId, - HDA_CODEC_VERB(HDA_VERB_GET_CONN_LIST_ENTRY, c), &Response); - if (EFI_ERROR(Status)) - return Status; - } - - // Populate entry list. - if ((HdaWidget->ConnectionListLength & HDA_PARAMETER_CONN_LIST_LENGTH_LONG)) - HdaWidget->Connections[c] = HDA_VERB_GET_CONN_LIST_ENTRY_LONG(Response, c % 2); - else - HdaWidget->Connections[c] = HDA_VERB_GET_CONN_LIST_ENTRY_SHORT(Response, c % 4); - } + return Status; + } + + // Populate entry list. + if ((HdaWidget->ConnectionListLength & HDA_PARAMETER_CONN_LIST_LENGTH_LONG)) + HdaWidget->Connections[c] = HDA_VERB_GET_CONN_LIST_ENTRY_LONG(Response, c % 2); + else + HdaWidget->Connections[c] = HDA_VERB_GET_CONN_LIST_ENTRY_SHORT(Response, c % 4); } - - // Print connections. - //DEBUG((DEBUG_INFO, "Widget @ 0x%X connections (%u):", HdaWidget->NodeId, HdaWidget->ConnectionCount)); - //for (UINT8 c = 0; c < HdaWidget->ConnectionCount; c++) - //DEBUG((DEBUG_INFO, " 0x%X", HdaWidget->Connections[c])); - //DEBUG((DEBUG_INFO, "\n")); - - // Does the widget support power management? - if (HdaWidget->Capabilities & HDA_PARAMETER_WIDGET_CAPS_POWER_CNTRL) { - // Get supported power states. - Status = HdaIo->SendCommand(HdaIo, HdaWidget->NodeId, - HDA_CODEC_VERB(HDA_VERB_GET_PARAMETER, HDA_PARAMETER_SUPPORTED_POWER_STATES), &HdaWidget->SupportedPowerStates); - if (EFI_ERROR(Status)) - return Status; - //DEBUG((DEBUG_INFO, "Widget @ 0x%X supported power states: 0x%X\n", HdaWidget->NodeId, HdaWidget->SupportedPowerStates)); - - // Get default power state. - Status = HdaIo->SendCommand(HdaIo, HdaWidget->NodeId, - HDA_CODEC_VERB(HDA_VERB_GET_POWER_STATE, 0), &HdaWidget->DefaultPowerState); - if (EFI_ERROR(Status)) - return Status; - //DEBUG((DEBUG_INFO, "Widget @ 0x%X power state: 0x%X\n", HdaWidget->NodeId, HdaWidget->DefaultPowerState)); + } + + // Print connections. + //DEBUG((DEBUG_INFO, "Widget @ 0x%X connections (%u):", HdaWidget->NodeId, HdaWidget->ConnectionCount)); + //for (UINT8 c = 0; c < HdaWidget->ConnectionCount; c++) + //DEBUG((DEBUG_INFO, " 0x%X", HdaWidget->Connections[c])); + //DEBUG((DEBUG_INFO, "\n")); + + // Does the widget support power management? + if (HdaWidget->Capabilities & HDA_PARAMETER_WIDGET_CAPS_POWER_CNTRL) { + // Get supported power states. + Status = HdaIo->SendCommand(HdaIo, HdaWidget->NodeId, + HDA_CODEC_VERB(HDA_VERB_GET_PARAMETER, HDA_PARAMETER_SUPPORTED_POWER_STATES), &HdaWidget->SupportedPowerStates); + if (EFI_ERROR(Status)) + return Status; + //DEBUG((DEBUG_INFO, "Widget @ 0x%X supported power states: 0x%X\n", HdaWidget->NodeId, HdaWidget->SupportedPowerStates)); + + // Get default power state. + Status = HdaIo->SendCommand(HdaIo, HdaWidget->NodeId, + HDA_CODEC_VERB(HDA_VERB_GET_POWER_STATE, 0), &HdaWidget->DefaultPowerState); + if (EFI_ERROR(Status)) + return Status; + //DEBUG((DEBUG_INFO, "Widget @ 0x%X power state: 0x%X\n", HdaWidget->NodeId, HdaWidget->DefaultPowerState)); + } + + // Do we have input amps? + if (HdaWidget->Capabilities & HDA_PARAMETER_WIDGET_CAPS_IN_AMP) { + // Get input amp capabilities. + Status = HdaIo->SendCommand(HdaIo, HdaWidget->NodeId, + HDA_CODEC_VERB(HDA_VERB_GET_PARAMETER, HDA_PARAMETER_AMP_CAPS_INPUT), &HdaWidget->AmpInCapabilities); + if (EFI_ERROR(Status)) + return Status; + //DEBUG((DEBUG_INFO, "Widget @ 0x%X input amp capabilities: 0x%X\n", HdaWidget->NodeId, HdaWidget->AmpInCapabilities)); + + // Determine number of input amps and allocate arrays. + AmpInCount = HdaWidget->ConnectionCount; + if (AmpInCount < 1) + AmpInCount = 1; + HdaWidget->AmpInLeftDefaultGainMute = AllocateZeroPool(sizeof(UINT8) * AmpInCount); + HdaWidget->AmpInRightDefaultGainMute = AllocateZeroPool(sizeof(UINT8) * AmpInCount); + if ((HdaWidget->AmpInLeftDefaultGainMute == NULL) || (HdaWidget->AmpInRightDefaultGainMute == NULL)) + return EFI_OUT_OF_RESOURCES; + + // Get default gain/mute for input amps. + for (UINT8 i = 0; i < AmpInCount; i++) { + // Get left. + Status = HdaIo->SendCommand(HdaIo, HdaWidget->NodeId, + HDA_CODEC_VERB(HDA_VERB_GET_AMP_GAIN_MUTE, + HDA_VERB_GET_AMP_GAIN_MUTE_PAYLOAD(i, TRUE, FALSE)), &Response); + if (EFI_ERROR(Status)) + return Status; + HdaWidget->AmpInLeftDefaultGainMute[i] = (UINT8)Response; + + // Get right. + Status = HdaIo->SendCommand(HdaIo, HdaWidget->NodeId, + HDA_CODEC_VERB(HDA_VERB_GET_AMP_GAIN_MUTE, + HDA_VERB_GET_AMP_GAIN_MUTE_PAYLOAD(i, FALSE, FALSE)), &Response); + if (EFI_ERROR(Status)) + return Status; + HdaWidget->AmpInRightDefaultGainMute[i] = (UINT8)Response; + //DEBUG((DEBUG_INFO, "Widget @ 0x%X input amp %u defaults: 0x%X 0x%X\n", HdaWidget->NodeId, i, + // HdaWidget->AmpInLeftDefaultGainMute[i], HdaWidget->AmpInRightDefaultGainMute[i])); } - - // Do we have input amps? - if (HdaWidget->Capabilities & HDA_PARAMETER_WIDGET_CAPS_IN_AMP) { - // Get input amp capabilities. - Status = HdaIo->SendCommand(HdaIo, HdaWidget->NodeId, - HDA_CODEC_VERB(HDA_VERB_GET_PARAMETER, HDA_PARAMETER_AMP_CAPS_INPUT), &HdaWidget->AmpInCapabilities); - if (EFI_ERROR(Status)) - return Status; - //DEBUG((DEBUG_INFO, "Widget @ 0x%X input amp capabilities: 0x%X\n", HdaWidget->NodeId, HdaWidget->AmpInCapabilities)); - - // Determine number of input amps and allocate arrays. - AmpInCount = HdaWidget->ConnectionCount; - if (AmpInCount < 1) - AmpInCount = 1; - HdaWidget->AmpInLeftDefaultGainMute = AllocateZeroPool(sizeof(UINT8) * AmpInCount); - HdaWidget->AmpInRightDefaultGainMute = AllocateZeroPool(sizeof(UINT8) * AmpInCount); - if ((HdaWidget->AmpInLeftDefaultGainMute == NULL) || (HdaWidget->AmpInRightDefaultGainMute == NULL)) - return EFI_OUT_OF_RESOURCES; - - // Get default gain/mute for input amps. - for (UINT8 i = 0; i < AmpInCount; i++) { - // Get left. - Status = HdaIo->SendCommand(HdaIo, HdaWidget->NodeId, - HDA_CODEC_VERB(HDA_VERB_GET_AMP_GAIN_MUTE, - HDA_VERB_GET_AMP_GAIN_MUTE_PAYLOAD(i, TRUE, FALSE)), &Response); - if (EFI_ERROR(Status)) - return Status; - HdaWidget->AmpInLeftDefaultGainMute[i] = (UINT8)Response; - - // Get right. - Status = HdaIo->SendCommand(HdaIo, HdaWidget->NodeId, - HDA_CODEC_VERB(HDA_VERB_GET_AMP_GAIN_MUTE, - HDA_VERB_GET_AMP_GAIN_MUTE_PAYLOAD(i, FALSE, FALSE)), &Response); - if (EFI_ERROR(Status)) - return Status; - HdaWidget->AmpInRightDefaultGainMute[i] = (UINT8)Response; - //DEBUG((DEBUG_INFO, "Widget @ 0x%X input amp %u defaults: 0x%X 0x%X\n", HdaWidget->NodeId, i, - // HdaWidget->AmpInLeftDefaultGainMute[i], HdaWidget->AmpInRightDefaultGainMute[i])); - } + } + + // Do we have an output amp? + if (HdaWidget->Capabilities & HDA_PARAMETER_WIDGET_CAPS_OUT_AMP) { + // Get output amp capabilities. + Status = HdaIo->SendCommand(HdaIo, HdaWidget->NodeId, + HDA_CODEC_VERB(HDA_VERB_GET_PARAMETER, HDA_PARAMETER_AMP_CAPS_OUTPUT), &HdaWidget->AmpOutCapabilities); + if (EFI_ERROR(Status)) + return Status; + //DEBUG((DEBUG_INFO, "Widget @ 0x%X output amp capabilities: 0x%X\n", HdaWidget->NodeId, HdaWidget->AmpOutCapabilities)); + + // Get left. + Status = HdaIo->SendCommand(HdaIo, HdaWidget->NodeId, + HDA_CODEC_VERB(HDA_VERB_GET_AMP_GAIN_MUTE, + HDA_VERB_GET_AMP_GAIN_MUTE_PAYLOAD(0, TRUE, TRUE)), &Response); + if (EFI_ERROR(Status)) + return Status; + HdaWidget->AmpOutLeftDefaultGainMute = (UINT8)Response; + + // Get right. + Status = HdaIo->SendCommand(HdaIo, HdaWidget->NodeId, + HDA_CODEC_VERB(HDA_VERB_GET_AMP_GAIN_MUTE, + HDA_VERB_GET_AMP_GAIN_MUTE_PAYLOAD(0, FALSE, TRUE)), &Response); + if (EFI_ERROR(Status)) + return Status; + HdaWidget->AmpOutRightDefaultGainMute = (UINT8)Response; + //DEBUG((DEBUG_INFO, "Widget @ 0x%X output amp defaults: 0x%X 0x%X\n", HdaWidget->NodeId, + // HdaWidget->AmpOutLeftDefaultGainMute, HdaWidget->AmpOutRightDefaultGainMute)); + } + + // Is the widget an Input or Output? + if (HdaWidget->Type == HDA_WIDGET_TYPE_INPUT || HdaWidget->Type == HDA_WIDGET_TYPE_OUTPUT) { + if (HdaWidget->Capabilities & HDA_PARAMETER_WIDGET_CAPS_FORMAT_OVERRIDE) { + // Get supported PCM sizes/rates. + Status = HdaIo->SendCommand(HdaIo, HdaWidget->NodeId, + HDA_CODEC_VERB(HDA_VERB_GET_PARAMETER, HDA_PARAMETER_SUPPORTED_PCM_SIZE_RATES), &HdaWidget->SupportedPcmRates); + if (EFI_ERROR(Status)) + return Status; + //DEBUG((DEBUG_INFO, "Widget @ 0x%X supported PCM sizes/rates: 0x%X\n", HdaWidget->NodeId, HdaWidget->SupportedPcmRates)); + + // Get supported stream formats. + Status = HdaIo->SendCommand(HdaIo, HdaWidget->NodeId, + HDA_CODEC_VERB(HDA_VERB_GET_PARAMETER, HDA_PARAMETER_SUPPORTED_STREAM_FORMATS), &HdaWidget->SupportedFormats); + if (EFI_ERROR(Status)) + return Status; + //DEBUG((DEBUG_INFO, "Widget @ 0x%X supported formats: 0x%X\n", HdaWidget->NodeId, HdaWidget->SupportedFormats)); } - - // Do we have an output amp? - if (HdaWidget->Capabilities & HDA_PARAMETER_WIDGET_CAPS_OUT_AMP) { - // Get output amp capabilities. - Status = HdaIo->SendCommand(HdaIo, HdaWidget->NodeId, - HDA_CODEC_VERB(HDA_VERB_GET_PARAMETER, HDA_PARAMETER_AMP_CAPS_OUTPUT), &HdaWidget->AmpOutCapabilities); - if (EFI_ERROR(Status)) - return Status; - //DEBUG((DEBUG_INFO, "Widget @ 0x%X output amp capabilities: 0x%X\n", HdaWidget->NodeId, HdaWidget->AmpOutCapabilities)); - - // Get left. - Status = HdaIo->SendCommand(HdaIo, HdaWidget->NodeId, - HDA_CODEC_VERB(HDA_VERB_GET_AMP_GAIN_MUTE, - HDA_VERB_GET_AMP_GAIN_MUTE_PAYLOAD(0, TRUE, TRUE)), &Response); - if (EFI_ERROR(Status)) - return Status; - HdaWidget->AmpOutLeftDefaultGainMute = (UINT8)Response; - - // Get right. - Status = HdaIo->SendCommand(HdaIo, HdaWidget->NodeId, - HDA_CODEC_VERB(HDA_VERB_GET_AMP_GAIN_MUTE, - HDA_VERB_GET_AMP_GAIN_MUTE_PAYLOAD(0, FALSE, TRUE)), &Response); - if (EFI_ERROR(Status)) - return Status; - HdaWidget->AmpOutRightDefaultGainMute = (UINT8)Response; - //DEBUG((DEBUG_INFO, "Widget @ 0x%X output amp defaults: 0x%X 0x%X\n", HdaWidget->NodeId, - // HdaWidget->AmpOutLeftDefaultGainMute, HdaWidget->AmpOutRightDefaultGainMute)); + + // Get default converter format. + Status = HdaIo->SendCommand(HdaIo, HdaWidget->NodeId, + HDA_CODEC_VERB(HDA_VERB_GET_CONVERTER_FORMAT, 0), &Response); + if (EFI_ERROR(Status)) + return Status; + HdaWidget->DefaultConvFormat = (UINT16)Response; + //DEBUG((DEBUG_INFO, "Widget @ 0x%X default format: 0x%X\n", HdaWidget->NodeId, HdaWidget->DefaultConvFormat)); + + // Get default converter stream/channel. + Status = HdaIo->SendCommand(HdaIo, HdaWidget->NodeId, + HDA_CODEC_VERB(HDA_VERB_GET_CONVERTER_STREAM_CHANNEL, 0), &Response); + if (EFI_ERROR(Status)) + return Status; + HdaWidget->DefaultConvStreamChannel = (UINT8)Response; + //DEBUG((DEBUG_INFO, "Widget @ 0x%X default stream/channel: 0x%X\n", HdaWidget->NodeId, HdaWidget->DefaultConvStreamChannel)); + + // Get default converter channel count. + Status = HdaIo->SendCommand(HdaIo, HdaWidget->NodeId, + HDA_CODEC_VERB(HDA_VERB_GET_CONVERTER_CHANNEL_COUNT, 0), &Response); + if (EFI_ERROR(Status)) + return Status; + HdaWidget->DefaultConvChannelCount = (UINT8)Response; + //DEBUG((DEBUG_INFO, "Widget @ 0x%X default channel count: 0x%X\n", HdaWidget->NodeId, HdaWidget->DefaultConvChannelCount)); + } else if (HdaWidget->Type == HDA_WIDGET_TYPE_PIN_COMPLEX) { // Is the widget a Pin Complex? + // Get pin capabilities. + Status = HdaIo->SendCommand(HdaIo, HdaWidget->NodeId, + HDA_CODEC_VERB(HDA_VERB_GET_PARAMETER, HDA_PARAMETER_PIN_CAPS), &HdaWidget->PinCapabilities); + if (EFI_ERROR(Status)) + return Status; + //DEBUG((DEBUG_INFO, "Widget @ 0x%X pin capabilities: 0x%X\n", HdaWidget->NodeId, HdaWidget->PinCapabilities)); + + // Get default EAPD. + if (HdaWidget->PinCapabilities & HDA_PARAMETER_PIN_CAPS_EAPD) { + Status = HdaIo->SendCommand(HdaIo, HdaWidget->NodeId, + HDA_CODEC_VERB(HDA_VERB_GET_EAPD_BTL_ENABLE, 0), &Response); + if (EFI_ERROR(Status)) + return Status; + HdaWidget->DefaultEapd = (UINT8)Response; + HdaWidget->DefaultEapd &= 0x7; + HdaWidget->DefaultEapd |= HDA_EAPD_BTL_ENABLE_EAPD; + //DEBUG((DEBUG_INFO, "Widget @ 0x%X EAPD: 0x%X\n", HdaWidget->NodeId, HdaWidget->DefaultEapd)); } - - // Is the widget an Input or Output? - if (HdaWidget->Type == HDA_WIDGET_TYPE_INPUT || HdaWidget->Type == HDA_WIDGET_TYPE_OUTPUT) { - if (HdaWidget->Capabilities & HDA_PARAMETER_WIDGET_CAPS_FORMAT_OVERRIDE) { - // Get supported PCM sizes/rates. - Status = HdaIo->SendCommand(HdaIo, HdaWidget->NodeId, - HDA_CODEC_VERB(HDA_VERB_GET_PARAMETER, HDA_PARAMETER_SUPPORTED_PCM_SIZE_RATES), &HdaWidget->SupportedPcmRates); - if (EFI_ERROR(Status)) - return Status; - //DEBUG((DEBUG_INFO, "Widget @ 0x%X supported PCM sizes/rates: 0x%X\n", HdaWidget->NodeId, HdaWidget->SupportedPcmRates)); - - // Get supported stream formats. - Status = HdaIo->SendCommand(HdaIo, HdaWidget->NodeId, - HDA_CODEC_VERB(HDA_VERB_GET_PARAMETER, HDA_PARAMETER_SUPPORTED_STREAM_FORMATS), &HdaWidget->SupportedFormats); - if (EFI_ERROR(Status)) - return Status; - //DEBUG((DEBUG_INFO, "Widget @ 0x%X supported formats: 0x%X\n", HdaWidget->NodeId, HdaWidget->SupportedFormats)); - } - - // Get default converter format. - Status = HdaIo->SendCommand(HdaIo, HdaWidget->NodeId, - HDA_CODEC_VERB(HDA_VERB_GET_CONVERTER_FORMAT, 0), &Response); - if (EFI_ERROR(Status)) - return Status; - HdaWidget->DefaultConvFormat = (UINT16)Response; - //DEBUG((DEBUG_INFO, "Widget @ 0x%X default format: 0x%X\n", HdaWidget->NodeId, HdaWidget->DefaultConvFormat)); - - // Get default converter stream/channel. - Status = HdaIo->SendCommand(HdaIo, HdaWidget->NodeId, - HDA_CODEC_VERB(HDA_VERB_GET_CONVERTER_STREAM_CHANNEL, 0), &Response); - if (EFI_ERROR(Status)) - return Status; - HdaWidget->DefaultConvStreamChannel = (UINT8)Response; - //DEBUG((DEBUG_INFO, "Widget @ 0x%X default stream/channel: 0x%X\n", HdaWidget->NodeId, HdaWidget->DefaultConvStreamChannel)); - - // Get default converter channel count. - Status = HdaIo->SendCommand(HdaIo, HdaWidget->NodeId, - HDA_CODEC_VERB(HDA_VERB_GET_CONVERTER_CHANNEL_COUNT, 0), &Response); - if (EFI_ERROR(Status)) - return Status; - HdaWidget->DefaultConvChannelCount = (UINT8)Response; - //DEBUG((DEBUG_INFO, "Widget @ 0x%X default channel count: 0x%X\n", HdaWidget->NodeId, HdaWidget->DefaultConvChannelCount)); - } else if (HdaWidget->Type == HDA_WIDGET_TYPE_PIN_COMPLEX) { // Is the widget a Pin Complex? - // Get pin capabilities. - Status = HdaIo->SendCommand(HdaIo, HdaWidget->NodeId, - HDA_CODEC_VERB(HDA_VERB_GET_PARAMETER, HDA_PARAMETER_PIN_CAPS), &HdaWidget->PinCapabilities); - if (EFI_ERROR(Status)) - return Status; - //DEBUG((DEBUG_INFO, "Widget @ 0x%X pin capabilities: 0x%X\n", HdaWidget->NodeId, HdaWidget->PinCapabilities)); - - // Get default EAPD. - if (HdaWidget->PinCapabilities & HDA_PARAMETER_PIN_CAPS_EAPD) { - Status = HdaIo->SendCommand(HdaIo, HdaWidget->NodeId, - HDA_CODEC_VERB(HDA_VERB_GET_EAPD_BTL_ENABLE, 0), &Response); - if (EFI_ERROR(Status)) - return Status; - HdaWidget->DefaultEapd = (UINT8)Response; - HdaWidget->DefaultEapd &= 0x7; - HdaWidget->DefaultEapd |= HDA_EAPD_BTL_ENABLE_EAPD; - //DEBUG((DEBUG_INFO, "Widget @ 0x%X EAPD: 0x%X\n", HdaWidget->NodeId, HdaWidget->DefaultEapd)); - } - - // Get default pin control. - Status = HdaIo->SendCommand(HdaIo, HdaWidget->NodeId, - HDA_CODEC_VERB(HDA_VERB_GET_PIN_WIDGET_CONTROL, 0), &Response); - if (EFI_ERROR(Status)) - return Status; - HdaWidget->DefaultPinControl = (UINT8)Response; - //DEBUG((DEBUG_INFO, "Widget @ 0x%X default pin control: 0x%X\n", HdaWidget->NodeId, HdaWidget->DefaultPinControl)); - - // Get default pin configuration. - Status = HdaIo->SendCommand(HdaIo, HdaWidget->NodeId, - HDA_CODEC_VERB(HDA_VERB_GET_CONFIGURATION_DEFAULT, 0), &HdaWidget->DefaultConfiguration); - if (EFI_ERROR(Status)) - return Status; - //DEBUG((DEBUG_INFO, "Widget @ 0x%X default pin configuration: 0x%X\n", HdaWidget->NodeId, HdaWidget->DefaultConfiguration)); - } else if (HdaWidget->Type == HDA_WIDGET_TYPE_VOLUME_KNOB) { // Is the widget a Volume Knob? - // Get volume knob capabilities. - Status = HdaIo->SendCommand(HdaIo, HdaWidget->NodeId, - HDA_CODEC_VERB(HDA_VERB_GET_PARAMETER, HDA_PARAMETER_VOLUME_KNOB_CAPS), &HdaWidget->VolumeCapabilities); - if (EFI_ERROR(Status)) - return Status; - //DEBUG((DEBUG_INFO, "Widget @ 0x%X volume knob capabilities: 0x%X\n", HdaWidget->NodeId, HdaWidget->VolumeCapabilities)); - - // Get default volume. - Status = HdaIo->SendCommand(HdaIo, HdaWidget->NodeId, - HDA_CODEC_VERB(HDA_VERB_GET_VOLUME_KNOB, 0), &Response); - if (EFI_ERROR(Status)) - return Status; - HdaWidget->DefaultVolume = (UINT8)Response; - //DEBUG((DEBUG_INFO, "Widget @ 0x%X default volume: 0x%X\n", HdaWidget->NodeId, HdaWidget->DefaultVolume)); - } - - return EFI_SUCCESS; + + // Get default pin control. + Status = HdaIo->SendCommand(HdaIo, HdaWidget->NodeId, + HDA_CODEC_VERB(HDA_VERB_GET_PIN_WIDGET_CONTROL, 0), &Response); + if (EFI_ERROR(Status)) + return Status; + HdaWidget->DefaultPinControl = (UINT8)Response; + //DEBUG((DEBUG_INFO, "Widget @ 0x%X default pin control: 0x%X\n", HdaWidget->NodeId, HdaWidget->DefaultPinControl)); + + // Get default pin configuration. + Status = HdaIo->SendCommand(HdaIo, HdaWidget->NodeId, + HDA_CODEC_VERB(HDA_VERB_GET_CONFIGURATION_DEFAULT, 0), &HdaWidget->DefaultConfiguration); + if (EFI_ERROR(Status)) + return Status; + //DEBUG((DEBUG_INFO, "Widget @ 0x%X default pin configuration: 0x%X\n", HdaWidget->NodeId, HdaWidget->DefaultConfiguration)); + } else if (HdaWidget->Type == HDA_WIDGET_TYPE_VOLUME_KNOB) { // Is the widget a Volume Knob? + // Get volume knob capabilities. + Status = HdaIo->SendCommand(HdaIo, HdaWidget->NodeId, + HDA_CODEC_VERB(HDA_VERB_GET_PARAMETER, HDA_PARAMETER_VOLUME_KNOB_CAPS), &HdaWidget->VolumeCapabilities); + if (EFI_ERROR(Status)) + return Status; + //DEBUG((DEBUG_INFO, "Widget @ 0x%X volume knob capabilities: 0x%X\n", HdaWidget->NodeId, HdaWidget->VolumeCapabilities)); + + // Get default volume. + Status = HdaIo->SendCommand(HdaIo, HdaWidget->NodeId, + HDA_CODEC_VERB(HDA_VERB_GET_VOLUME_KNOB, 0), &Response); + if (EFI_ERROR(Status)) + return Status; + HdaWidget->DefaultVolume = (UINT8)Response; + //DEBUG((DEBUG_INFO, "Widget @ 0x%X default volume: 0x%X\n", HdaWidget->NodeId, HdaWidget->DefaultVolume)); + } + + return EFI_SUCCESS; } EFI_STATUS EFIAPI HdaCodecProbeFuncGroup( - IN HDA_FUNC_GROUP *FuncGroup) { - //DEBUG((DEBUG_INFO, "HdaCodecProbeFuncGroup(): start\n")); - - // Create variables. - EFI_STATUS Status; - EFI_HDA_IO_PROTOCOL *HdaIo = FuncGroup->HdaCodecDev->HdaIo; - UINT32 Response; - - UINT8 WidgetStart; - UINT8 WidgetEnd; - UINT8 WidgetCount; - HDA_WIDGET_DEV *HdaWidget; - HDA_WIDGET_DEV *HdaConnectedWidget; - - // Get function group type. - Status = HdaIo->SendCommand(HdaIo, FuncGroup->NodeId, - HDA_CODEC_VERB(HDA_VERB_GET_PARAMETER, HDA_PARAMETER_FUNC_GROUP_TYPE), &Response); - if (EFI_ERROR(Status)) - return Status; - FuncGroup->Type = HDA_PARAMETER_FUNC_GROUP_TYPE_NODETYPE(Response); - FuncGroup->UnsolCapable = (Response & HDA_PARAMETER_FUNC_GROUP_TYPE_UNSOL) != 0; - - // Determine if function group is an audio one. If not, we cannot support it. - DEBUG((DEBUG_INFO, "Function group @ 0x%X is of type 0x%X\n", FuncGroup->NodeId, FuncGroup->Type)); - if (FuncGroup->Type != HDA_FUNC_GROUP_TYPE_AUDIO) - return EFI_UNSUPPORTED; - - // Get function group capabilities. - Status = HdaIo->SendCommand(HdaIo, FuncGroup->NodeId, - HDA_CODEC_VERB(HDA_VERB_GET_PARAMETER, HDA_PARAMETER_FUNC_GROUP_CAPS), &FuncGroup->Capabilities); - if (EFI_ERROR(Status)) - return Status; - //DEBUG((DEBUG_INFO, "Function group @ 0x%X capabilities: 0x%X\n", FuncGroup->NodeId, FuncGroup->Capabilities)); - - // Get default supported PCM sizes/rates. - Status = HdaIo->SendCommand(HdaIo, FuncGroup->NodeId, - HDA_CODEC_VERB(HDA_VERB_GET_PARAMETER, HDA_PARAMETER_SUPPORTED_PCM_SIZE_RATES), &FuncGroup->SupportedPcmRates); - if (EFI_ERROR(Status)) - return Status; - //DEBUG((DEBUG_INFO, "Function group @ 0x%X supported PCM sizes/rates: 0x%X\n", FuncGroup->NodeId, FuncGroup->SupportedPcmRates)); - - // Get default supported stream formats. - Status = HdaIo->SendCommand(HdaIo, FuncGroup->NodeId, - HDA_CODEC_VERB(HDA_VERB_GET_PARAMETER, HDA_PARAMETER_SUPPORTED_STREAM_FORMATS), &FuncGroup->SupportedFormats); - if (EFI_ERROR(Status)) - return Status; - //DEBUG((DEBUG_INFO, "Function group @ 0x%X supported formats: 0x%X\n", FuncGroup->NodeId, FuncGroup->SupportedFormats)); - - // Get default input amp capabilities. - Status = HdaIo->SendCommand(HdaIo, FuncGroup->NodeId, - HDA_CODEC_VERB(HDA_VERB_GET_PARAMETER, HDA_PARAMETER_AMP_CAPS_INPUT), &FuncGroup->AmpInCapabilities); - if (EFI_ERROR(Status)) - return Status; - //DEBUG((DEBUG_INFO, "Function group @ 0x%X input amp capabilities: 0x%X\n", FuncGroup->NodeId, FuncGroup->AmpInCapabilities)); - - // Get default output amp capabilities. - Status = HdaIo->SendCommand(HdaIo, FuncGroup->NodeId, - HDA_CODEC_VERB(HDA_VERB_GET_PARAMETER, HDA_PARAMETER_AMP_CAPS_OUTPUT), &FuncGroup->AmpOutCapabilities); - if (EFI_ERROR(Status)) - return Status; - //DEBUG((DEBUG_INFO, "Function group @ 0x%X output amp capabilities: 0x%X\n", FuncGroup->NodeId, FuncGroup->AmpOutCapabilities)); - - // Get supported power states. - Status = HdaIo->SendCommand(HdaIo, FuncGroup->NodeId, - HDA_CODEC_VERB(HDA_VERB_GET_PARAMETER, HDA_PARAMETER_SUPPORTED_POWER_STATES), &FuncGroup->SupportedPowerStates); - if (EFI_ERROR(Status)) - return Status; - //DEBUG((DEBUG_INFO, "Function group @ 0x%X supported power states: 0x%X\n", FuncGroup->NodeId, FuncGroup->SupportedPowerStates)); - - // Get GPIO capabilities. - Status = HdaIo->SendCommand(HdaIo, FuncGroup->NodeId, - HDA_CODEC_VERB(HDA_VERB_GET_PARAMETER, HDA_PARAMETER_GPIO_COUNT), &FuncGroup->GpioCapabilities); - if (EFI_ERROR(Status)) - return Status; - //DEBUG((DEBUG_INFO, "Function group @ 0x%X GPIO capabilities: 0x%X\n", FuncGroup->NodeId, FuncGroup->GpioCapabilities)); - - // Get number of widgets in function group. - Status = HdaIo->SendCommand(HdaIo, FuncGroup->NodeId, - HDA_CODEC_VERB(HDA_VERB_GET_PARAMETER, HDA_PARAMETER_SUBNODE_COUNT), &Response); - if (EFI_ERROR(Status)) - return Status; - WidgetStart = HDA_PARAMETER_SUBNODE_COUNT_START(Response); - WidgetCount = HDA_PARAMETER_SUBNODE_COUNT_TOTAL(Response); - WidgetEnd = WidgetStart + WidgetCount - 1; - DEBUG((DEBUG_INFO, "Function group @ 0x%X contains %u widgets, start @ 0x%X, end @ 0x%X\n", - FuncGroup->NodeId, WidgetCount, WidgetStart, WidgetEnd)); - - // Power up. - Status = HdaIo->SendCommand(HdaIo, FuncGroup->NodeId, HDA_CODEC_VERB(HDA_VERB_SET_POWER_STATE, 0), &Response); + IN HDA_FUNC_GROUP *FuncGroup) { + //DEBUG((DEBUG_INFO, "HdaCodecProbeFuncGroup(): start\n")); + + // Create variables. + EFI_STATUS Status; + EFI_HDA_IO_PROTOCOL *HdaIo = FuncGroup->HdaCodecDev->HdaIo; + UINT32 Response; + + UINT8 WidgetStart; + UINT8 WidgetEnd; + UINT8 WidgetCount; + HDA_WIDGET_DEV *HdaWidget; + HDA_WIDGET_DEV *HdaConnectedWidget; + + // Get function group type. + Status = HdaIo->SendCommand(HdaIo, FuncGroup->NodeId, + HDA_CODEC_VERB(HDA_VERB_GET_PARAMETER, HDA_PARAMETER_FUNC_GROUP_TYPE), &Response); + if (EFI_ERROR(Status)) + return Status; + FuncGroup->Type = HDA_PARAMETER_FUNC_GROUP_TYPE_NODETYPE(Response); + FuncGroup->UnsolCapable = (Response & HDA_PARAMETER_FUNC_GROUP_TYPE_UNSOL) != 0; + + // Determine if function group is an audio one. If not, we cannot support it. + DEBUG((DEBUG_INFO, "Function group @ 0x%X is of type 0x%X\n", FuncGroup->NodeId, FuncGroup->Type)); + if (FuncGroup->Type != HDA_FUNC_GROUP_TYPE_AUDIO) + return EFI_UNSUPPORTED; + + // Get function group capabilities. + Status = HdaIo->SendCommand(HdaIo, FuncGroup->NodeId, + HDA_CODEC_VERB(HDA_VERB_GET_PARAMETER, HDA_PARAMETER_FUNC_GROUP_CAPS), &FuncGroup->Capabilities); + if (EFI_ERROR(Status)) + return Status; + //DEBUG((DEBUG_INFO, "Function group @ 0x%X capabilities: 0x%X\n", FuncGroup->NodeId, FuncGroup->Capabilities)); + + // Get default supported PCM sizes/rates. + Status = HdaIo->SendCommand(HdaIo, FuncGroup->NodeId, + HDA_CODEC_VERB(HDA_VERB_GET_PARAMETER, HDA_PARAMETER_SUPPORTED_PCM_SIZE_RATES), &FuncGroup->SupportedPcmRates); + if (EFI_ERROR(Status)) + return Status; + //DEBUG((DEBUG_INFO, "Function group @ 0x%X supported PCM sizes/rates: 0x%X\n", FuncGroup->NodeId, FuncGroup->SupportedPcmRates)); + + // Get default supported stream formats. + Status = HdaIo->SendCommand(HdaIo, FuncGroup->NodeId, + HDA_CODEC_VERB(HDA_VERB_GET_PARAMETER, HDA_PARAMETER_SUPPORTED_STREAM_FORMATS), &FuncGroup->SupportedFormats); + if (EFI_ERROR(Status)) + return Status; + //DEBUG((DEBUG_INFO, "Function group @ 0x%X supported formats: 0x%X\n", FuncGroup->NodeId, FuncGroup->SupportedFormats)); + + // Get default input amp capabilities. + Status = HdaIo->SendCommand(HdaIo, FuncGroup->NodeId, + HDA_CODEC_VERB(HDA_VERB_GET_PARAMETER, HDA_PARAMETER_AMP_CAPS_INPUT), &FuncGroup->AmpInCapabilities); + if (EFI_ERROR(Status)) + return Status; + //DEBUG((DEBUG_INFO, "Function group @ 0x%X input amp capabilities: 0x%X\n", FuncGroup->NodeId, FuncGroup->AmpInCapabilities)); + + // Get default output amp capabilities. + Status = HdaIo->SendCommand(HdaIo, FuncGroup->NodeId, + HDA_CODEC_VERB(HDA_VERB_GET_PARAMETER, HDA_PARAMETER_AMP_CAPS_OUTPUT), &FuncGroup->AmpOutCapabilities); + if (EFI_ERROR(Status)) + return Status; + //DEBUG((DEBUG_INFO, "Function group @ 0x%X output amp capabilities: 0x%X\n", FuncGroup->NodeId, FuncGroup->AmpOutCapabilities)); + + // Get supported power states. + Status = HdaIo->SendCommand(HdaIo, FuncGroup->NodeId, + HDA_CODEC_VERB(HDA_VERB_GET_PARAMETER, HDA_PARAMETER_SUPPORTED_POWER_STATES), &FuncGroup->SupportedPowerStates); + if (EFI_ERROR(Status)) + return Status; + //DEBUG((DEBUG_INFO, "Function group @ 0x%X supported power states: 0x%X\n", FuncGroup->NodeId, FuncGroup->SupportedPowerStates)); + + // Get GPIO capabilities. + Status = HdaIo->SendCommand(HdaIo, FuncGroup->NodeId, + HDA_CODEC_VERB(HDA_VERB_GET_PARAMETER, HDA_PARAMETER_GPIO_COUNT), &FuncGroup->GpioCapabilities); + if (EFI_ERROR(Status)) + return Status; + //DEBUG((DEBUG_INFO, "Function group @ 0x%X GPIO capabilities: 0x%X\n", FuncGroup->NodeId, FuncGroup->GpioCapabilities)); + + // Get number of widgets in function group. + Status = HdaIo->SendCommand(HdaIo, FuncGroup->NodeId, + HDA_CODEC_VERB(HDA_VERB_GET_PARAMETER, HDA_PARAMETER_SUBNODE_COUNT), &Response); + if (EFI_ERROR(Status)) + return Status; + WidgetStart = HDA_PARAMETER_SUBNODE_COUNT_START(Response); + WidgetCount = HDA_PARAMETER_SUBNODE_COUNT_TOTAL(Response); + WidgetEnd = WidgetStart + WidgetCount - 1; + DEBUG((DEBUG_INFO, "Function group @ 0x%X contains %u widgets, start @ 0x%X, end @ 0x%X\n", + FuncGroup->NodeId, WidgetCount, WidgetStart, WidgetEnd)); + + // Power up. + Status = HdaIo->SendCommand(HdaIo, FuncGroup->NodeId, HDA_CODEC_VERB(HDA_VERB_SET_POWER_STATE, 0), &Response); + ASSERT_EFI_ERROR(Status); + + // Ensure there are widgets. + if (WidgetCount == 0) + return EFI_UNSUPPORTED; + + // Allocate space for widgets. + FuncGroup->Widgets = AllocateZeroPool(sizeof(HDA_WIDGET_DEV) * WidgetCount); + if (FuncGroup->Widgets == NULL) + return EFI_OUT_OF_RESOURCES; + FuncGroup->WidgetsCount = WidgetCount; + + // Probe widgets. + DEBUG((DEBUG_INFO, "HdaCodecProbeFuncGroup(): probing widgets\n")); + for (UINT8 w = 0; w < WidgetCount; w++) { + // Get widget. + HdaWidget = FuncGroup->Widgets + w; + + // Probe widget. + HdaWidget->FuncGroup = FuncGroup; + HdaWidget->NodeId = WidgetStart + w; + Status = HdaCodecProbeWidget(HdaWidget); ASSERT_EFI_ERROR(Status); - - // Ensure there are widgets. - if (WidgetCount == 0) - return EFI_UNSUPPORTED; - - // Allocate space for widgets. - FuncGroup->Widgets = AllocateZeroPool(sizeof(HDA_WIDGET_DEV) * WidgetCount); - if (FuncGroup->Widgets == NULL) + + // Power up. + if (HdaWidget->Capabilities & HDA_PARAMETER_WIDGET_CAPS_POWER_CNTRL) { + Status = HdaIo->SendCommand(HdaIo, HdaWidget->NodeId, HDA_CODEC_VERB(HDA_VERB_SET_POWER_STATE, 0), &Response); + ASSERT_EFI_ERROR(Status); + } + } + + // Probe widget connections. + DEBUG((DEBUG_INFO, "HdaCodecProbeFuncGroup(): probing widget connections\n")); + for (UINT8 w = 0; w < WidgetCount; w++) { + // Get widget. + HdaWidget = FuncGroup->Widgets + w; + + // Get connections. + if (HdaWidget->ConnectionCount > 0) { + // Allocate array of widget pointers. + HdaWidget->WidgetConnections = AllocateZeroPool(sizeof(HDA_WIDGET_DEV*) * HdaWidget->ConnectionCount); + if (HdaWidget->WidgetConnections == NULL) return EFI_OUT_OF_RESOURCES; - FuncGroup->WidgetsCount = WidgetCount; - - // Probe widgets. - DEBUG((DEBUG_INFO, "HdaCodecProbeFuncGroup(): probing widgets\n")); - for (UINT8 w = 0; w < WidgetCount; w++) { - // Get widget. - HdaWidget = FuncGroup->Widgets + w; - - // Probe widget. - HdaWidget->FuncGroup = FuncGroup; - HdaWidget->NodeId = WidgetStart + w; - Status = HdaCodecProbeWidget(HdaWidget); - ASSERT_EFI_ERROR(Status); - - // Power up. - if (HdaWidget->Capabilities & HDA_PARAMETER_WIDGET_CAPS_POWER_CNTRL) { - Status = HdaIo->SendCommand(HdaIo, HdaWidget->NodeId, HDA_CODEC_VERB(HDA_VERB_SET_POWER_STATE, 0), &Response); - ASSERT_EFI_ERROR(Status); + + // Populate array. + for (UINT8 c = 0; c < HdaWidget->ConnectionCount; c++) { + // Get widget index. + // This can be gotten using the node ID of the connection minus our starting node ID. + UINT16 WidgetIndex = HdaWidget->Connections[c] - WidgetStart; + if (WidgetIndex < 0) { + DEBUG((DEBUG_INFO, "Widget @ 0x%X error connection to index %u (0x%X) is invalid\n", WidgetIndex, HdaWidget->Connections[c])); + continue; } + + // Save pointer to widget. + HdaConnectedWidget = FuncGroup->Widgets + WidgetIndex; + //DEBUG((DEBUG_INFO, "Widget @ 0x%X found connection to index %u (0x%X, type 0x%X)\n", + // HdaWidget->NodeId, WidgetIndex, HdaConnectedWidget->NodeId, HdaConnectedWidget->Type)); + HdaWidget->WidgetConnections[c] = HdaConnectedWidget; + } } - - // Probe widget connections. - DEBUG((DEBUG_INFO, "HdaCodecProbeFuncGroup(): probing widget connections\n")); - for (UINT8 w = 0; w < WidgetCount; w++) { - // Get widget. - HdaWidget = FuncGroup->Widgets + w; - - // Get connections. - if (HdaWidget->ConnectionCount > 0) { - // Allocate array of widget pointers. - HdaWidget->WidgetConnections = AllocateZeroPool(sizeof(HDA_WIDGET_DEV*) * HdaWidget->ConnectionCount); - if (HdaWidget->WidgetConnections == NULL) - return EFI_OUT_OF_RESOURCES; - - // Populate array. - for (UINT8 c = 0; c < HdaWidget->ConnectionCount; c++) { - // Get widget index. - // This can be gotten using the node ID of the connection minus our starting node ID. - UINT16 WidgetIndex = HdaWidget->Connections[c] - WidgetStart; - if (WidgetIndex < 0) { - DEBUG((DEBUG_INFO, "Widget @ 0x%X error connection to index %u (0x%X) is invalid\n", WidgetIndex, HdaWidget->Connections[c])); - continue; - } - - // Save pointer to widget. - HdaConnectedWidget = FuncGroup->Widgets + WidgetIndex; - //DEBUG((DEBUG_INFO, "Widget @ 0x%X found connection to index %u (0x%X, type 0x%X)\n", - // HdaWidget->NodeId, WidgetIndex, HdaConnectedWidget->NodeId, HdaConnectedWidget->Type)); - HdaWidget->WidgetConnections[c] = HdaConnectedWidget; - } - } - } - - return EFI_SUCCESS; + } + + return EFI_SUCCESS; } EFI_STATUS EFIAPI HdaCodecProbeCodec( - IN HDA_CODEC_DEV *HdaCodecDev) + IN HDA_CODEC_DEV *HdaCodecDev) { - //DEBUG((DEBUG_INFO, "HdaCodecProbeCodec(): start\n")); - - // Create variables. - EFI_STATUS Status; - EFI_HDA_IO_PROTOCOL *HdaIo = HdaCodecDev->HdaIo; - UINT32 Response; - UINT8 FuncStart; - UINT8 FuncEnd; - UINT8 FuncCount; - - // Get vendor and device ID. - Status = HdaIo->SendCommand(HdaIo, HDA_NID_ROOT, - HDA_CODEC_VERB(HDA_VERB_GET_PARAMETER, HDA_PARAMETER_VENDOR_ID), &HdaCodecDev->VendorId); - if (EFI_ERROR(Status)) - return Status; - DEBUG((DEBUG_INFO, "Codec ID: 0x%X:0x%X\n", HDA_PARAMETER_VENDOR_ID_VEN(HdaCodecDev->VendorId), HDA_PARAMETER_VENDOR_ID_DEV(HdaCodecDev->VendorId))); - - // Get revision ID. - Status = HdaIo->SendCommand(HdaIo, HDA_NID_ROOT, - HDA_CODEC_VERB(HDA_VERB_GET_PARAMETER, HDA_PARAMETER_REVISION_ID), &HdaCodecDev->RevisionId); - if (EFI_ERROR(Status)) - return Status; - - HdaCodecGetName(HdaCodecDev->VendorId, (UINT16)HdaCodecDev->RevisionId, &HdaCodecDev->Name); - - // Get function group count. - Status = HdaIo->SendCommand(HdaIo, HDA_NID_ROOT, - HDA_CODEC_VERB(HDA_VERB_GET_PARAMETER, HDA_PARAMETER_SUBNODE_COUNT), &Response); - if (EFI_ERROR(Status)) - return Status; - FuncStart = HDA_PARAMETER_SUBNODE_COUNT_START(Response); - FuncCount = HDA_PARAMETER_SUBNODE_COUNT_TOTAL(Response); - FuncEnd = FuncStart + FuncCount - 1; - DEBUG((DEBUG_INFO, "Codec contains %u function groups, start @ 0x%X, end @ 0x%X\n", FuncCount, FuncStart, FuncEnd)); - - // Ensure there are functions. - if (FuncCount == 0) - return EFI_UNSUPPORTED; - - // Allocate space for function groups. - HdaCodecDev->FuncGroups = AllocateZeroPool(sizeof(HDA_FUNC_GROUP) * FuncCount); - if (HdaCodecDev->FuncGroups == NULL) - return EFI_OUT_OF_RESOURCES; - HdaCodecDev->FuncGroupsCount = FuncCount; - HdaCodecDev->AudioFuncGroup = NULL; - - // Probe functions. - for (UINT8 i = 0; i < FuncCount; i++) { - HdaCodecDev->FuncGroups[i].HdaCodecDev = HdaCodecDev; - HdaCodecDev->FuncGroups[i].NodeId = FuncStart + i; - Status = HdaCodecProbeFuncGroup(HdaCodecDev->FuncGroups + i); - if (!(EFI_ERROR(Status)) && (HdaCodecDev->AudioFuncGroup == NULL)) - HdaCodecDev->AudioFuncGroup = HdaCodecDev->FuncGroups + i; - } - - return EFI_SUCCESS; + //DEBUG((DEBUG_INFO, "HdaCodecProbeCodec(): start\n")); + + // Create variables. + EFI_STATUS Status; + EFI_HDA_IO_PROTOCOL *HdaIo = HdaCodecDev->HdaIo; + UINT32 Response; + UINT8 FuncStart; + UINT8 FuncEnd; + UINT8 FuncCount; + + // Get vendor and device ID. + Status = HdaIo->SendCommand(HdaIo, HDA_NID_ROOT, + HDA_CODEC_VERB(HDA_VERB_GET_PARAMETER, HDA_PARAMETER_VENDOR_ID), &HdaCodecDev->VendorId); + if (EFI_ERROR(Status)) + return Status; + DEBUG((DEBUG_INFO, "Codec ID: 0x%X:0x%X\n", HDA_PARAMETER_VENDOR_ID_VEN(HdaCodecDev->VendorId), HDA_PARAMETER_VENDOR_ID_DEV(HdaCodecDev->VendorId))); + + // Get revision ID. + Status = HdaIo->SendCommand(HdaIo, HDA_NID_ROOT, + HDA_CODEC_VERB(HDA_VERB_GET_PARAMETER, HDA_PARAMETER_REVISION_ID), &HdaCodecDev->RevisionId); + if (EFI_ERROR(Status)) + return Status; + + HdaCodecGetName(HdaCodecDev->VendorId, (UINT16)HdaCodecDev->RevisionId, &HdaCodecDev->Name); + + // Get function group count. + Status = HdaIo->SendCommand(HdaIo, HDA_NID_ROOT, + HDA_CODEC_VERB(HDA_VERB_GET_PARAMETER, HDA_PARAMETER_SUBNODE_COUNT), &Response); + if (EFI_ERROR(Status)) + return Status; + FuncStart = HDA_PARAMETER_SUBNODE_COUNT_START(Response); + FuncCount = HDA_PARAMETER_SUBNODE_COUNT_TOTAL(Response); + FuncEnd = FuncStart + FuncCount - 1; + DEBUG((DEBUG_INFO, "Codec contains %u function groups, start @ 0x%X, end @ 0x%X\n", FuncCount, FuncStart, FuncEnd)); + + // Ensure there are functions. + if (FuncCount == 0) + return EFI_UNSUPPORTED; + + // Allocate space for function groups. + HdaCodecDev->FuncGroups = AllocateZeroPool(sizeof(HDA_FUNC_GROUP) * FuncCount); + if (HdaCodecDev->FuncGroups == NULL) + return EFI_OUT_OF_RESOURCES; + HdaCodecDev->FuncGroupsCount = FuncCount; + HdaCodecDev->AudioFuncGroup = NULL; + + // Probe functions. + for (UINT8 i = 0; i < FuncCount; i++) { + HdaCodecDev->FuncGroups[i].HdaCodecDev = HdaCodecDev; + HdaCodecDev->FuncGroups[i].NodeId = FuncStart + i; + Status = HdaCodecProbeFuncGroup(HdaCodecDev->FuncGroups + i); + if (!(EFI_ERROR(Status)) && (HdaCodecDev->AudioFuncGroup == NULL)) + HdaCodecDev->AudioFuncGroup = HdaCodecDev->FuncGroups + i; + } + + return EFI_SUCCESS; } EFI_STATUS EFIAPI HdaCodecFindUpstreamOutput( - IN HDA_WIDGET_DEV *HdaWidget, - IN UINT8 Level) + IN HDA_WIDGET_DEV *HdaWidget, + IN UINT8 Level) { - EFI_STATUS Status; - HDA_WIDGET_DEV *HdaConnectedWidget; - - //DEBUG((DEBUG_INFO, "HdaCodecFindUpstreamOutput(): start\n")); - - // If level is above 15, we may have entered an infinite loop so just give up. - if (Level > 15) { - return EFI_ABORTED; + EFI_STATUS Status; + HDA_WIDGET_DEV *HdaConnectedWidget; + + //DEBUG((DEBUG_INFO, "HdaCodecFindUpstreamOutput(): start\n")); + + // If level is above 15, we may have entered an infinite loop so just give up. + if (Level > 15) { + return EFI_ABORTED; + } + + // Go through connections and check for Output widgets. + for (UINT8 c = 0; c < HdaWidget->ConnectionCount; c++) { + // Get connected widget. + HdaConnectedWidget = HdaWidget->WidgetConnections[c]; + for (UINT8 i = 0; i <= Level; i++) { + DEBUG((DEBUG_INFO, " ")); } - - // Go through connections and check for Output widgets. - for (UINT8 c = 0; c < HdaWidget->ConnectionCount; c++) { - // Get connected widget. - HdaConnectedWidget = HdaWidget->WidgetConnections[c]; - for (UINT8 i = 0; i <= Level; i++) { - DEBUG((DEBUG_INFO, " ")); - } - DEBUG((DEBUG_INFO, "Widget @ 0x%X (type 0x%X)\n", HdaConnectedWidget->NodeId, HdaConnectedWidget->Type)); - - // If this is an Output, we are done. - if (HdaConnectedWidget->Type == HDA_WIDGET_TYPE_OUTPUT) { - HdaWidget->UpstreamWidget = HdaConnectedWidget; - HdaWidget->UpstreamIndex = c; - return EFI_SUCCESS; - } - - // Check connections of connected widget. - // If a success status is returned, that means an Output widget was found and we are done. - Status = HdaCodecFindUpstreamOutput(HdaConnectedWidget, Level + 1); - if (Status == EFI_SUCCESS) { - HdaWidget->UpstreamWidget = HdaConnectedWidget; - HdaWidget->UpstreamIndex = c; - return EFI_SUCCESS; - } + DEBUG((DEBUG_INFO, "Widget @ 0x%X (type 0x%X)\n", HdaConnectedWidget->NodeId, HdaConnectedWidget->Type)); + + // If this is an Output, we are done. + if (HdaConnectedWidget->Type == HDA_WIDGET_TYPE_OUTPUT) { + HdaWidget->UpstreamWidget = HdaConnectedWidget; + HdaWidget->UpstreamIndex = c; + return EFI_SUCCESS; } - - // We didn't find an Output if we got here (probably zero connections). - return EFI_NOT_FOUND; + + // Check connections of connected widget. + // If a success status is returned, that means an Output widget was found and we are done. + Status = HdaCodecFindUpstreamOutput(HdaConnectedWidget, Level + 1); + if (Status == EFI_SUCCESS) { + HdaWidget->UpstreamWidget = HdaConnectedWidget; + HdaWidget->UpstreamIndex = c; + return EFI_SUCCESS; + } + } + + // We didn't find an Output if we got here (probably zero connections). + return EFI_NOT_FOUND; } EFI_STATUS EFIAPI HdaCodecParsePorts( - IN HDA_CODEC_DEV *HdaCodecDev) { - //DEBUG((DEBUG_INFO, "HdaCodecParsePorts(): start\n")); - - // Create variables. - EFI_STATUS Status; - EFI_HDA_IO_PROTOCOL *HdaIo = HdaCodecDev->HdaIo; - HDA_FUNC_GROUP *HdaFuncGroup; - HDA_WIDGET_DEV *HdaWidget; - UINT8 DefaultDeviceType; - UINT32 Response; - - // Loop through each function group. - for (UINT8 f = 0; f < HdaCodecDev->FuncGroupsCount; f++) { - // Get function group. - HdaFuncGroup = HdaCodecDev->FuncGroups + f; - - // Loop through each widget. - for (UINT8 w = 0; w < HdaFuncGroup->WidgetsCount; w++) { - // Get widget. - HdaWidget = HdaFuncGroup->Widgets + w; - - // Is the widget a pin complex? If not, ignore it. - // If this is a pin complex but it has no connection to a port, also ignore it. - // If the default association for the pin complex is zero, also ignore it. - if ((HdaWidget->Type != HDA_WIDGET_TYPE_PIN_COMPLEX) || - (HDA_VERB_GET_CONFIGURATION_DEFAULT_PORT_CONN(HdaWidget->DefaultConfiguration) == HDA_CONFIG_DEFAULT_PORT_CONN_NONE) || - (HDA_VERB_GET_CONFIGURATION_DEFAULT_ASSOCIATION(HdaWidget->DefaultConfiguration) == 0)) - continue; - - // Determine if port is an output based on the device type. - DefaultDeviceType = HDA_VERB_GET_CONFIGURATION_DEFAULT_DEVICE(HdaWidget->DefaultConfiguration); - if ((DefaultDeviceType == HDA_CONFIG_DEFAULT_DEVICE_LINE_OUT) || (DefaultDeviceType == HDA_CONFIG_DEFAULT_DEVICE_SPEAKER) || - (DefaultDeviceType == HDA_CONFIG_DEFAULT_DEVICE_HEADPHONE_OUT) || (DefaultDeviceType == HDA_CONFIG_DEFAULT_DEVICE_SPDIF_OUT) || - (DefaultDeviceType == HDA_CONFIG_DEFAULT_DEVICE_OTHER_DIGITAL_OUT)) { - - // Try to get upstream output. - DEBUG((DEBUG_INFO, "Port widget @ 0x%X is an output (pin defaults 0x%X)\n", HdaWidget->NodeId, HdaWidget->DefaultConfiguration)); - Status = HdaCodecFindUpstreamOutput(HdaWidget, 0); - if (EFI_ERROR(Status)) - continue; - - // Enable output amp. - Status = HdaIo->SendCommand(HdaIo, HdaWidget->NodeId, HDA_CODEC_VERB(HDA_VERB_SET_PIN_WIDGET_CONTROL, - HDA_VERB_SET_PIN_WIDGET_CONTROL_PAYLOAD(0, FALSE, FALSE, TRUE, FALSE)), &Response); - if (EFI_ERROR(Status)) - continue; - - // If EAPD is present, enable. - if (HdaWidget->PinCapabilities & HDA_PARAMETER_PIN_CAPS_EAPD) { - // Get current EAPD setting. - Status = HdaIo->SendCommand(HdaIo, HdaWidget->NodeId, HDA_CODEC_VERB(HDA_VERB_GET_EAPD_BTL_ENABLE, 0), &Response); - if (EFI_ERROR(Status)) - return Status; - - // If the EAPD is not set, set it. - if (!(Response & HDA_EAPD_BTL_ENABLE_EAPD)) { - Response |= HDA_EAPD_BTL_ENABLE_EAPD; - Status = HdaIo->SendCommand(HdaIo, HdaWidget->NodeId, HDA_CODEC_VERB(HDA_VERB_SET_EAPD_BTL_ENABLE, - (UINT8)Response), &Response); - if (EFI_ERROR(Status)) - return Status; - } - } - - // If the output amp supports muting, unmute. - if (HdaWidget->AmpOutCapabilities & HDA_PARAMETER_AMP_CAPS_MUTE) { - UINT8 offset = HDA_PARAMETER_AMP_CAPS_OFFSET(HdaWidget->AmpOutCapabilities); // TODO set volume. - - // If there are no overriden amp capabilities, check function group. - if (!(HdaWidget->AmpOverride)) - offset = HDA_PARAMETER_AMP_CAPS_OFFSET(HdaWidget->FuncGroup->AmpOutCapabilities); - - // Unmute amp. - Status = HdaIo->SendCommand(HdaIo, HdaWidget->NodeId, HDA_CODEC_VERB(HDA_VERB_SET_AMP_GAIN_MUTE, - HDA_VERB_SET_AMP_GAIN_MUTE_PAYLOAD(0, offset, FALSE, TRUE, TRUE, FALSE, TRUE)), &Response); - if (EFI_ERROR(Status)) - return Status; - } - - // Reallocate output array. - HdaCodecDev->OutputPorts = ReallocatePool(sizeof(HDA_WIDGET_DEV*) * HdaCodecDev->OutputPortsCount, sizeof(HDA_WIDGET_DEV*) * (HdaCodecDev->OutputPortsCount + 1), HdaCodecDev->OutputPorts); - if (HdaCodecDev->OutputPorts == NULL) - return EFI_OUT_OF_RESOURCES; - HdaCodecDev->OutputPortsCount++; - - // Add widget to output array. - HdaCodecDev->OutputPorts[HdaCodecDev->OutputPortsCount - 1] = HdaWidget; - } + IN HDA_CODEC_DEV *HdaCodecDev) +{ + //DEBUG((DEBUG_INFO, "HdaCodecParsePorts(): start\n")); + + // Create variables. + EFI_STATUS Status; + EFI_HDA_IO_PROTOCOL *HdaIo = HdaCodecDev->HdaIo; + HDA_FUNC_GROUP *HdaFuncGroup; + HDA_WIDGET_DEV *HdaWidget; + UINT8 DefaultDeviceType; + UINT32 Response; + + // Loop through each function group. + for (UINT8 f = 0; f < HdaCodecDev->FuncGroupsCount; f++) { + // Get function group. + HdaFuncGroup = HdaCodecDev->FuncGroups + f; + + // Loop through each widget. + for (UINT8 w = 0; w < HdaFuncGroup->WidgetsCount; w++) { + // Get widget. + HdaWidget = HdaFuncGroup->Widgets + w; + + // Is the widget a pin complex? If not, ignore it. + // If this is a pin complex but it has no connection to a port, also ignore it. + // If the default association for the pin complex is zero, also ignore it. + if ((HdaWidget->Type != HDA_WIDGET_TYPE_PIN_COMPLEX) || + (HDA_VERB_GET_CONFIGURATION_DEFAULT_PORT_CONN(HdaWidget->DefaultConfiguration) == HDA_CONFIG_DEFAULT_PORT_CONN_NONE) || + (HDA_VERB_GET_CONFIGURATION_DEFAULT_ASSOCIATION(HdaWidget->DefaultConfiguration) == 0)) + continue; + + // Determine if port is an output based on the device type. + DefaultDeviceType = HDA_VERB_GET_CONFIGURATION_DEFAULT_DEVICE(HdaWidget->DefaultConfiguration); + if ((DefaultDeviceType == HDA_CONFIG_DEFAULT_DEVICE_LINE_OUT) || (DefaultDeviceType == HDA_CONFIG_DEFAULT_DEVICE_SPEAKER) || + (DefaultDeviceType == HDA_CONFIG_DEFAULT_DEVICE_HEADPHONE_OUT) || (DefaultDeviceType == HDA_CONFIG_DEFAULT_DEVICE_SPDIF_OUT) || + (DefaultDeviceType == HDA_CONFIG_DEFAULT_DEVICE_OTHER_DIGITAL_OUT)) { + + // Try to get upstream output. + DEBUG((DEBUG_INFO, "Port widget @ 0x%X is an output (pin defaults 0x%X)\n", HdaWidget->NodeId, HdaWidget->DefaultConfiguration)); + Status = HdaCodecFindUpstreamOutput(HdaWidget, 0); + if (EFI_ERROR(Status)) + continue; + + // Enable output amp. + Status = HdaIo->SendCommand(HdaIo, HdaWidget->NodeId, HDA_CODEC_VERB(HDA_VERB_SET_PIN_WIDGET_CONTROL, + HDA_VERB_SET_PIN_WIDGET_CONTROL_PAYLOAD(0, FALSE, FALSE, TRUE, FALSE)), &Response); + if (EFI_ERROR(Status)) + continue; + + // If EAPD is present, enable. + if (HdaWidget->PinCapabilities & HDA_PARAMETER_PIN_CAPS_EAPD) { + // Get current EAPD setting. + Status = HdaIo->SendCommand(HdaIo, HdaWidget->NodeId, HDA_CODEC_VERB(HDA_VERB_GET_EAPD_BTL_ENABLE, 0), &Response); + if (EFI_ERROR(Status)) + return Status; + + // If the EAPD is not set, set it. + if (!(Response & HDA_EAPD_BTL_ENABLE_EAPD)) { + Response |= HDA_EAPD_BTL_ENABLE_EAPD; + Status = HdaIo->SendCommand(HdaIo, HdaWidget->NodeId, HDA_CODEC_VERB(HDA_VERB_SET_EAPD_BTL_ENABLE, + (UINT8)Response), &Response); + if (EFI_ERROR(Status)) + return Status; + } } + + // If the output amp supports muting, unmute. + if (HdaWidget->AmpOutCapabilities & HDA_PARAMETER_AMP_CAPS_MUTE) { + UINT8 offset = HDA_PARAMETER_AMP_CAPS_OFFSET(HdaWidget->AmpOutCapabilities); // TODO set volume. + + // If there are no overriden amp capabilities, check function group. + if (!(HdaWidget->AmpOverride)) + offset = HDA_PARAMETER_AMP_CAPS_OFFSET(HdaWidget->FuncGroup->AmpOutCapabilities); + + // Unmute amp. + Status = HdaIo->SendCommand(HdaIo, HdaWidget->NodeId, HDA_CODEC_VERB(HDA_VERB_SET_AMP_GAIN_MUTE, + HDA_VERB_SET_AMP_GAIN_MUTE_PAYLOAD(0, offset, FALSE, TRUE, TRUE, FALSE, TRUE)), &Response); + if (EFI_ERROR(Status)) + return Status; + } + + // Reallocate output array. + HdaCodecDev->OutputPorts = ReallocatePool(sizeof(HDA_WIDGET_DEV*) * HdaCodecDev->OutputPortsCount, sizeof(HDA_WIDGET_DEV*) * (HdaCodecDev->OutputPortsCount + 1), HdaCodecDev->OutputPorts); + if (HdaCodecDev->OutputPorts == NULL) + return EFI_OUT_OF_RESOURCES; + HdaCodecDev->OutputPortsCount++; + + // Add widget to output array. + HdaCodecDev->OutputPorts[HdaCodecDev->OutputPortsCount - 1] = HdaWidget; + } } - - // Wait 1000ms for all widgets to fully come on. - gBS->Stall(MS_TO_MICROSECOND(1000)); - - return EFI_SUCCESS; + } + + // Wait 1000ms for all widgets to fully come on. + gBS->Stall(MS_TO_MICROSECOND(1000)); + + return EFI_SUCCESS; } EFI_STATUS EFIAPI HdaCodecInstallProtocols( - IN HDA_CODEC_DEV *HdaCodecDev) { - DEBUG((DEBUG_INFO, "HdaCodecInstallProtocols(): start\n")); - - // Create variables. - EFI_STATUS Status; - HDA_CODEC_INFO_PRIVATE_DATA *HdaCodecInfoData; - AUDIO_IO_PRIVATE_DATA *AudioIoData; - - // Allocate space for protocol data. - HdaCodecInfoData = AllocateZeroPool(sizeof(HDA_CODEC_INFO_PRIVATE_DATA)); - AudioIoData = AllocateZeroPool(sizeof(AUDIO_IO_PRIVATE_DATA)); - if ((HdaCodecInfoData == NULL) || (AudioIoData == NULL)) { - Status = EFI_OUT_OF_RESOURCES; - goto FREE_POOLS; - } - - // Populate info protocol data. - HdaCodecInfoData->Signature = HDA_CODEC_PRIVATE_DATA_SIGNATURE; - HdaCodecInfoData->HdaCodecDev = HdaCodecDev; - HdaCodecInfoData->HdaCodecInfo.GetName = HdaCodecInfoGetCodecName; - HdaCodecInfoData->HdaCodecInfo.GetVendorId = HdaCodecInfoGetVendorId; - HdaCodecInfoData->HdaCodecInfo.GetRevisionId = HdaCodecInfoGetRevisionId; - HdaCodecInfoData->HdaCodecInfo.GetAudioFuncId = HdaCodecInfoGetAudioFuncId; - HdaCodecInfoData->HdaCodecInfo.GetDefaultRatesFormats = HdaCodecInfoGetDefaultRatesFormats; - HdaCodecInfoData->HdaCodecInfo.GetDefaultAmpCaps = HdaCodecInfoGetDefaultAmpCaps; - HdaCodecInfoData->HdaCodecInfo.GetWidgets = HdaCodecInfoGetWidgets; - HdaCodecInfoData->HdaCodecInfo.FreeWidgetsBuffer = HdaCodecInfoFreeWidgetsBuffer; - HdaCodecDev->HdaCodecInfoData = HdaCodecInfoData; - - // Populate I/O protocol data. - AudioIoData->Signature = HDA_CODEC_PRIVATE_DATA_SIGNATURE; - AudioIoData->HdaCodecDev = HdaCodecDev; - AudioIoData->AudioIo.GetOutputs = HdaCodecAudioIoGetOutputs; - AudioIoData->AudioIo.SetupPlayback = HdaCodecAudioIoSetupPlayback; - AudioIoData->AudioIo.StartPlayback = HdaCodecAudioIoStartPlayback; - AudioIoData->AudioIo.StartPlaybackAsync = HdaCodecAudioIoStartPlaybackAsync; - AudioIoData->AudioIo.StopPlayback = HdaCodecAudioIoStopPlayback; - HdaCodecDev->AudioIoData = AudioIoData; - - // Install protocols. - Status = gBS->InstallMultipleProtocolInterfaces(&HdaCodecDev->ControllerHandle, - &gEfiHdaCodecInfoProtocolGuid, &HdaCodecInfoData->HdaCodecInfo, - &gEfiAudioIoProtocolGuid, &AudioIoData->AudioIo, - &gEfiCallerIdGuid, HdaCodecDev, NULL); - if (EFI_ERROR(Status)) - goto FREE_POOLS; - return EFI_SUCCESS; - + IN HDA_CODEC_DEV *HdaCodecDev) +{ + DEBUG((DEBUG_INFO, "HdaCodecInstallProtocols(): start\n")); + + // Create variables. + EFI_STATUS Status; + HDA_CODEC_INFO_PRIVATE_DATA *HdaCodecInfoData; + AUDIO_IO_PRIVATE_DATA *AudioIoData; + + // Allocate space for protocol data. + HdaCodecInfoData = AllocateZeroPool(sizeof(HDA_CODEC_INFO_PRIVATE_DATA)); + AudioIoData = AllocateZeroPool(sizeof(AUDIO_IO_PRIVATE_DATA)); + if ((HdaCodecInfoData == NULL) || (AudioIoData == NULL)) { + Status = EFI_OUT_OF_RESOURCES; + goto FREE_POOLS; + } + + // Populate info protocol data. + HdaCodecInfoData->Signature = HDA_CODEC_PRIVATE_DATA_SIGNATURE; + HdaCodecInfoData->HdaCodecDev = HdaCodecDev; + HdaCodecInfoData->HdaCodecInfo.GetName = HdaCodecInfoGetCodecName; + HdaCodecInfoData->HdaCodecInfo.GetVendorId = HdaCodecInfoGetVendorId; + HdaCodecInfoData->HdaCodecInfo.GetRevisionId = HdaCodecInfoGetRevisionId; + HdaCodecInfoData->HdaCodecInfo.GetAudioFuncId = HdaCodecInfoGetAudioFuncId; + HdaCodecInfoData->HdaCodecInfo.GetDefaultRatesFormats = HdaCodecInfoGetDefaultRatesFormats; + HdaCodecInfoData->HdaCodecInfo.GetDefaultAmpCaps = HdaCodecInfoGetDefaultAmpCaps; + HdaCodecInfoData->HdaCodecInfo.GetWidgets = HdaCodecInfoGetWidgets; + HdaCodecInfoData->HdaCodecInfo.FreeWidgetsBuffer = HdaCodecInfoFreeWidgetsBuffer; + HdaCodecDev->HdaCodecInfoData = HdaCodecInfoData; + + // Populate I/O protocol data. + AudioIoData->Signature = HDA_CODEC_PRIVATE_DATA_SIGNATURE; + AudioIoData->HdaCodecDev = HdaCodecDev; + AudioIoData->AudioIo.GetOutputs = HdaCodecAudioIoGetOutputs; + AudioIoData->AudioIo.SetupPlayback = HdaCodecAudioIoSetupPlayback; + AudioIoData->AudioIo.StartPlayback = HdaCodecAudioIoStartPlayback; + AudioIoData->AudioIo.StartPlaybackAsync = HdaCodecAudioIoStartPlaybackAsync; + AudioIoData->AudioIo.StopPlayback = HdaCodecAudioIoStopPlayback; + HdaCodecDev->AudioIoData = AudioIoData; + + // Install protocols. + Status = gBS->InstallMultipleProtocolInterfaces(&HdaCodecDev->ControllerHandle, + &gEfiHdaCodecInfoProtocolGuid, &HdaCodecInfoData->HdaCodecInfo, + &gEfiAudioIoProtocolGuid, &AudioIoData->AudioIo, + &gEfiCallerIdGuid, HdaCodecDev, NULL); + if (EFI_ERROR(Status)) + goto FREE_POOLS; + return EFI_SUCCESS; + FREE_POOLS: - if (HdaCodecInfoData != NULL) - FreePool(HdaCodecInfoData); - if (AudioIoData != NULL) - FreePool(AudioIoData); - return Status; + if (HdaCodecInfoData != NULL) + FreePool(HdaCodecInfoData); + if (AudioIoData != NULL) + FreePool(AudioIoData); + return Status; } EFI_STATUS EFIAPI HdaCodecGetOutputDac( - IN HDA_WIDGET_DEV *HdaWidget, - OUT HDA_WIDGET_DEV **HdaOutputWidget) + IN HDA_WIDGET_DEV *HdaWidget, + OUT HDA_WIDGET_DEV **HdaOutputWidget) { - DEBUG((DEBUG_INFO, "HdaCodecGetOutputDac(): start\n")); - - // Check that parameters are valid. - if ((HdaWidget == NULL) || (HdaOutputWidget == NULL)) - return EFI_INVALID_PARAMETER; - - // Crawl through widget path looking for output DAC. - while (HdaWidget != NULL) { - // Is this widget an output DAC? - if (HdaWidget->Type == HDA_WIDGET_TYPE_OUTPUT) { - *HdaOutputWidget = HdaWidget; - return EFI_SUCCESS; - } - - // Move to upstream widget. - HdaWidget = HdaWidget->UpstreamWidget; + DEBUG((DEBUG_INFO, "HdaCodecGetOutputDac(): start\n")); + + // Check that parameters are valid. + if ((HdaWidget == NULL) || (HdaOutputWidget == NULL)) + return EFI_INVALID_PARAMETER; + + // Crawl through widget path looking for output DAC. + while (HdaWidget != NULL) { + // Is this widget an output DAC? + if (HdaWidget->Type == HDA_WIDGET_TYPE_OUTPUT) { + *HdaOutputWidget = HdaWidget; + return EFI_SUCCESS; } - - // If we get here, we couldn't find the DAC. - return EFI_NOT_FOUND; + + // Move to upstream widget. + HdaWidget = HdaWidget->UpstreamWidget; + } + + // If we get here, we couldn't find the DAC. + return EFI_NOT_FOUND; } EFI_STATUS EFIAPI HdaCodecGetSupportedPcmRates( - IN HDA_WIDGET_DEV *HdaPinWidget, - OUT UINT32 *SupportedRates) + IN HDA_WIDGET_DEV *HdaPinWidget, + OUT UINT32 *SupportedRates) { - EFI_STATUS Status; - HDA_WIDGET_DEV *HdaOutputWidget; - -// DEBUG((DEBUG_INFO, "HdaCodecGetSupportedPcmRates(): start\n")); - - // Check that parameters are valid. - if ((HdaPinWidget == NULL) || (SupportedRates == NULL)) - return EFI_INVALID_PARAMETER; - - // Get output DAC widget. - Status = HdaCodecGetOutputDac(HdaPinWidget, &HdaOutputWidget); - if (EFI_ERROR(Status)) - return Status; - - // Does the widget specify format info? - if (HdaOutputWidget->Capabilities & HDA_PARAMETER_WIDGET_CAPS_FORMAT_OVERRIDE) { - // Check widget for PCM support. - if (!(HdaOutputWidget->SupportedFormats & HDA_PARAMETER_SUPPORTED_STREAM_FORMATS_PCM)) - return EFI_UNSUPPORTED; - *SupportedRates = HdaOutputWidget->SupportedPcmRates; - } else { - // Check function group for PCM support. - if (!(HdaOutputWidget->FuncGroup->SupportedFormats & HDA_PARAMETER_SUPPORTED_STREAM_FORMATS_PCM)) - return EFI_UNSUPPORTED; - *SupportedRates = HdaOutputWidget->FuncGroup->SupportedPcmRates; - } - return EFI_SUCCESS; + EFI_STATUS Status; + HDA_WIDGET_DEV *HdaOutputWidget; + + // DEBUG((DEBUG_INFO, "HdaCodecGetSupportedPcmRates(): start\n")); + + // Check that parameters are valid. + if ((HdaPinWidget == NULL) || (SupportedRates == NULL)) + return EFI_INVALID_PARAMETER; + + // Get output DAC widget. + Status = HdaCodecGetOutputDac(HdaPinWidget, &HdaOutputWidget); + if (EFI_ERROR(Status)) + return Status; + + // Does the widget specify format info? + if (HdaOutputWidget->Capabilities & HDA_PARAMETER_WIDGET_CAPS_FORMAT_OVERRIDE) { + // Check widget for PCM support. + if (!(HdaOutputWidget->SupportedFormats & HDA_PARAMETER_SUPPORTED_STREAM_FORMATS_PCM)) + return EFI_UNSUPPORTED; + *SupportedRates = HdaOutputWidget->SupportedPcmRates; + } else { + // Check function group for PCM support. + if (!(HdaOutputWidget->FuncGroup->SupportedFormats & HDA_PARAMETER_SUPPORTED_STREAM_FORMATS_PCM)) + return EFI_UNSUPPORTED; + *SupportedRates = HdaOutputWidget->FuncGroup->SupportedPcmRates; + } + return EFI_SUCCESS; } EFI_STATUS EFIAPI HdaCodecDisableWidgetPath( - IN HDA_WIDGET_DEV *HdaWidget) + IN HDA_WIDGET_DEV *HdaWidget) { - // Create variables. - EFI_STATUS Status; - EFI_HDA_IO_PROTOCOL *HdaIo = HdaWidget->FuncGroup->HdaCodecDev->HdaIo; - UINT32 Response = 0; - - //DEBUG((DEBUG_INFO, "HdaCodecDisableWidgetPath(): start\n")); - - // Check if widget is valid. - if (HdaWidget == NULL) - return EFI_INVALID_PARAMETER; - - // Crawl through widget path. - while (HdaWidget != NULL) { - // If Output, disable stream. - if (HdaWidget->Type == HDA_WIDGET_TYPE_OUTPUT) { - Status = HdaIo->SendCommand(HdaIo, HdaWidget->NodeId, HDA_CODEC_VERB(HDA_VERB_SET_CONVERTER_STREAM_CHANNEL, - HDA_VERB_SET_CONVERTER_STREAM_PAYLOAD(0, 0)), &Response); - if (EFI_ERROR(Status)) - return Status; - } - - // If widget is a pin complex, disable output. - if (HdaWidget->Type == HDA_WIDGET_TYPE_PIN_COMPLEX) { - Status = HdaIo->SendCommand(HdaIo, HdaWidget->NodeId, HDA_CODEC_VERB(HDA_VERB_SET_PIN_WIDGET_CONTROL, - HDA_VERB_SET_PIN_WIDGET_CONTROL_PAYLOAD(0, FALSE, FALSE, FALSE, FALSE)), &Response); - if (EFI_ERROR(Status)) - return Status; - } - - // Move to upstream widget. - HdaWidget = HdaWidget->UpstreamWidget; + // Create variables. + EFI_STATUS Status; + EFI_HDA_IO_PROTOCOL *HdaIo = HdaWidget->FuncGroup->HdaCodecDev->HdaIo; + UINT32 Response = 0; + + //DEBUG((DEBUG_INFO, "HdaCodecDisableWidgetPath(): start\n")); + + // Check if widget is valid. + if (HdaWidget == NULL) + return EFI_INVALID_PARAMETER; + + // Crawl through widget path. + while (HdaWidget != NULL) { + // If Output, disable stream. + if (HdaWidget->Type == HDA_WIDGET_TYPE_OUTPUT) { + Status = HdaIo->SendCommand(HdaIo, HdaWidget->NodeId, HDA_CODEC_VERB(HDA_VERB_SET_CONVERTER_STREAM_CHANNEL, + HDA_VERB_SET_CONVERTER_STREAM_PAYLOAD(0, 0)), &Response); + if (EFI_ERROR(Status)) + return Status; } - - // Path disabled. - return EFI_SUCCESS; + + // If widget is a pin complex, disable output. + if (HdaWidget->Type == HDA_WIDGET_TYPE_PIN_COMPLEX) { + Status = HdaIo->SendCommand(HdaIo, HdaWidget->NodeId, HDA_CODEC_VERB(HDA_VERB_SET_PIN_WIDGET_CONTROL, + HDA_VERB_SET_PIN_WIDGET_CONTROL_PAYLOAD(0, FALSE, FALSE, FALSE, FALSE)), &Response); + if (EFI_ERROR(Status)) + return Status; + } + + // Move to upstream widget. + HdaWidget = HdaWidget->UpstreamWidget; + } + + // Path disabled. + return EFI_SUCCESS; } EFI_STATUS EFIAPI HdaCodecEnableWidgetPath( - IN HDA_WIDGET_DEV *HdaWidget, - IN UINT8 Volume, - IN UINT8 StreamId, - IN UINT16 StreamFormat) + IN HDA_WIDGET_DEV *HdaWidget, + IN UINT8 Volume, + IN UINT8 StreamId, + IN UINT16 StreamFormat) { - // Create variables. - EFI_STATUS Status; - EFI_HDA_IO_PROTOCOL *HdaIo = HdaWidget->FuncGroup->HdaCodecDev->HdaIo; - UINT32 Response = 0; - - //DEBUG((DEBUG_INFO, "HdaCodecEnableWidgetPath(): start\n")); - - // Check if widget is valid. - if ((HdaWidget == NULL) || (Volume > EFI_AUDIO_IO_PROTOCOL_MAX_VOLUME)) - return EFI_INVALID_PARAMETER; - - // Crawl through widget path. - while (HdaWidget != NULL) { - DEBUG((DEBUG_INFO, "Widget @ 0x%X setting up\n", HdaWidget->NodeId)); - - // If pin complex, set as output. - if (HdaWidget->Type == HDA_WIDGET_TYPE_PIN_COMPLEX) { - Status = HdaIo->SendCommand(HdaIo, HdaWidget->NodeId, HDA_CODEC_VERB(HDA_VERB_SET_PIN_WIDGET_CONTROL, - HDA_VERB_SET_PIN_WIDGET_CONTROL_PAYLOAD(0, FALSE, FALSE, TRUE, FALSE)), &Response); - if (EFI_ERROR(Status)) - return Status; - - // If EAPD, enable. - if (HdaWidget->PinCapabilities & HDA_PARAMETER_PIN_CAPS_EAPD) { - // Get current EAPD setting. - Status = HdaIo->SendCommand(HdaIo, HdaWidget->NodeId, HDA_CODEC_VERB(HDA_VERB_GET_EAPD_BTL_ENABLE, 0), &Response); - if (EFI_ERROR(Status)) - return Status; - - // If the EAPD is not set, set it. - if (!(Response & HDA_EAPD_BTL_ENABLE_EAPD)) { - Response |= HDA_EAPD_BTL_ENABLE_EAPD; - Status = HdaIo->SendCommand(HdaIo, HdaWidget->NodeId, HDA_CODEC_VERB(HDA_VERB_SET_EAPD_BTL_ENABLE, - (UINT8)Response), &Response); - if (EFI_ERROR(Status)) - return Status; - } - } + // Create variables. + EFI_STATUS Status; + EFI_HDA_IO_PROTOCOL *HdaIo = HdaWidget->FuncGroup->HdaCodecDev->HdaIo; + UINT32 Response = 0; + + //DEBUG((DEBUG_INFO, "HdaCodecEnableWidgetPath(): start\n")); + + // Check if widget is valid. + if ((HdaWidget == NULL) || (Volume > EFI_AUDIO_IO_PROTOCOL_MAX_VOLUME)) + return EFI_INVALID_PARAMETER; + + // Crawl through widget path. + while (HdaWidget != NULL) { + DEBUG((DEBUG_INFO, "Widget @ 0x%X setting up\n", HdaWidget->NodeId)); + + // If pin complex, set as output. + if (HdaWidget->Type == HDA_WIDGET_TYPE_PIN_COMPLEX) { + Status = HdaIo->SendCommand(HdaIo, HdaWidget->NodeId, HDA_CODEC_VERB(HDA_VERB_SET_PIN_WIDGET_CONTROL, + HDA_VERB_SET_PIN_WIDGET_CONTROL_PAYLOAD(0, FALSE, FALSE, TRUE, FALSE)), &Response); + if (EFI_ERROR(Status)) + return Status; + + // If EAPD, enable. + if (HdaWidget->PinCapabilities & HDA_PARAMETER_PIN_CAPS_EAPD) { + // Get current EAPD setting. + Status = HdaIo->SendCommand(HdaIo, HdaWidget->NodeId, HDA_CODEC_VERB(HDA_VERB_GET_EAPD_BTL_ENABLE, 0), &Response); + if (EFI_ERROR(Status)) + return Status; + + // If the EAPD is not set, set it. + if (!(Response & HDA_EAPD_BTL_ENABLE_EAPD)) { + Response |= HDA_EAPD_BTL_ENABLE_EAPD; + Status = HdaIo->SendCommand(HdaIo, HdaWidget->NodeId, HDA_CODEC_VERB(HDA_VERB_SET_EAPD_BTL_ENABLE, + (UINT8)Response), &Response); + if (EFI_ERROR(Status)) + return Status; } - - // If this is a digital widget, enable digital output. - if (HdaWidget->Capabilities & HDA_PARAMETER_WIDGET_CAPS_DIGITAL) { - // Enable digital output. - Status = HdaIo->SendCommand(HdaIo, HdaWidget->NodeId, HDA_CODEC_VERB(HDA_VERB_SET_DIGITAL_CONV_CONTROL1, - HDA_DIGITAL_CONV_CONTROL_DIGEN), &Response); - if (EFI_ERROR(Status)) - return Status; - - Status = HdaIo->SendCommand(HdaIo, HdaWidget->NodeId, HDA_CODEC_VERB(HDA_VERB_SET_ASP_MAPPING, - 0x00), &Response); - if (EFI_ERROR(Status)) - return Status; - Status = HdaIo->SendCommand(HdaIo, HdaWidget->NodeId, HDA_CODEC_VERB(HDA_VERB_SET_ASP_MAPPING, - 0x11), &Response); - if (EFI_ERROR(Status)) - return Status; - } - - // If there is an output amp, unmute. - if (HdaWidget->Capabilities & HDA_PARAMETER_WIDGET_CAPS_OUT_AMP) { - UINT8 offset = HDA_PARAMETER_AMP_CAPS_OFFSET(HdaWidget->AmpOutCapabilities); // TODO set volume. - - // If there are no overriden amp capabilities, check function group. - if (!(HdaWidget->AmpOverride)) - offset = HDA_PARAMETER_AMP_CAPS_OFFSET(HdaWidget->FuncGroup->AmpOutCapabilities); - - // Calculate offset. - offset = (offset * Volume) / EFI_AUDIO_IO_PROTOCOL_MAX_VOLUME; - DEBUG((DEBUG_INFO, "HdaCodecEnableWidgetPath(): Amp out offset 0x%X\n", offset)); - Status = HdaIo->SendCommand(HdaIo, HdaWidget->NodeId, HDA_CODEC_VERB(HDA_VERB_SET_AMP_GAIN_MUTE, - HDA_VERB_SET_AMP_GAIN_MUTE_PAYLOAD(0, offset, FALSE, TRUE, TRUE, FALSE, TRUE)), &Response); - if (EFI_ERROR(Status)) - return Status; - } - - // If there are input amps, mute all but the upstream. - if (HdaWidget->Capabilities & HDA_PARAMETER_WIDGET_CAPS_IN_AMP) { - DEBUG((DEBUG_INFO, "Widget @ 0x%X in amp\n", HdaWidget->NodeId)); - for (UINT8 c = 0; c < HdaWidget->ConnectionCount; c++) { - if (HdaWidget->UpstreamIndex == c) { - UINT8 offset = HDA_PARAMETER_AMP_CAPS_OFFSET(HdaWidget->AmpInCapabilities); - // If there are no overriden amp capabilities, check function group. - if (!(HdaWidget->AmpOverride)) - offset = HDA_PARAMETER_AMP_CAPS_OFFSET(HdaWidget->FuncGroup->AmpInCapabilities); - Status = HdaIo->SendCommand(HdaIo, HdaWidget->NodeId, HDA_CODEC_VERB(HDA_VERB_SET_AMP_GAIN_MUTE, - HDA_VERB_SET_AMP_GAIN_MUTE_PAYLOAD(c, offset, FALSE, TRUE, TRUE, TRUE, FALSE)), &Response); - if (EFI_ERROR(Status)) - return Status; - } else { - Status = HdaIo->SendCommand(HdaIo, HdaWidget->NodeId, HDA_CODEC_VERB(HDA_VERB_SET_AMP_GAIN_MUTE, - HDA_VERB_SET_AMP_GAIN_MUTE_PAYLOAD(c, 0, TRUE, TRUE, TRUE, TRUE, FALSE)), &Response); - if (EFI_ERROR(Status)) - return Status; - } - } - } - - // If there is more than one connection, select our upstream. - if (HdaWidget->ConnectionCount > 1) { - Status = HdaIo->SendCommand(HdaIo, HdaWidget->NodeId, HDA_CODEC_VERB(HDA_VERB_SET_CONN_SELECT_CONTROL, - HdaWidget->UpstreamIndex), &Response); - if (EFI_ERROR(Status)) - return Status; - } - - // If Output, set up stream. - if (HdaWidget->Type == HDA_WIDGET_TYPE_OUTPUT) { - DEBUG((DEBUG_INFO, "Widget @ 0x%X output\n", HdaWidget->NodeId)); - Status = HdaIo->SendCommand(HdaIo, HdaWidget->NodeId, HDA_CODEC_VERB(HDA_VERB_SET_CONVERTER_FORMAT, - StreamFormat), &Response); - if (EFI_ERROR(Status)) - return Status; - Status = HdaIo->SendCommand(HdaIo, HdaWidget->NodeId, HDA_CODEC_VERB(HDA_VERB_SET_CONVERTER_STREAM_CHANNEL, - HDA_VERB_SET_CONVERTER_STREAM_PAYLOAD(0, StreamId)), &Response); - if (EFI_ERROR(Status)) - return Status; - } - - // Move to upstream widget. - HdaWidget = HdaWidget->UpstreamWidget; + } } - return EFI_SUCCESS; + + // If this is a digital widget, enable digital output. + if (HdaWidget->Capabilities & HDA_PARAMETER_WIDGET_CAPS_DIGITAL) { + // Enable digital output. + Status = HdaIo->SendCommand(HdaIo, HdaWidget->NodeId, HDA_CODEC_VERB(HDA_VERB_SET_DIGITAL_CONV_CONTROL1, + HDA_DIGITAL_CONV_CONTROL_DIGEN), &Response); + if (EFI_ERROR(Status)) + return Status; + + Status = HdaIo->SendCommand(HdaIo, HdaWidget->NodeId, HDA_CODEC_VERB(HDA_VERB_SET_ASP_MAPPING, + 0x00), &Response); + if (EFI_ERROR(Status)) + return Status; + Status = HdaIo->SendCommand(HdaIo, HdaWidget->NodeId, HDA_CODEC_VERB(HDA_VERB_SET_ASP_MAPPING, + 0x11), &Response); + if (EFI_ERROR(Status)) + return Status; + } + + // If there is an output amp, unmute. + if (HdaWidget->Capabilities & HDA_PARAMETER_WIDGET_CAPS_OUT_AMP) { + UINT8 offset = HDA_PARAMETER_AMP_CAPS_OFFSET(HdaWidget->AmpOutCapabilities); // TODO set volume. + + // If there are no overriden amp capabilities, check function group. + if (!(HdaWidget->AmpOverride)) + offset = HDA_PARAMETER_AMP_CAPS_OFFSET(HdaWidget->FuncGroup->AmpOutCapabilities); + + // Calculate offset. + offset = (offset * Volume) / EFI_AUDIO_IO_PROTOCOL_MAX_VOLUME; + DEBUG((DEBUG_INFO, "HdaCodecEnableWidgetPath(): Amp out offset 0x%X\n", offset)); + Status = HdaIo->SendCommand(HdaIo, HdaWidget->NodeId, HDA_CODEC_VERB(HDA_VERB_SET_AMP_GAIN_MUTE, + HDA_VERB_SET_AMP_GAIN_MUTE_PAYLOAD(0, offset, FALSE, TRUE, TRUE, FALSE, TRUE)), &Response); + if (EFI_ERROR(Status)) + return Status; + } + + // If there are input amps, mute all but the upstream. + if (HdaWidget->Capabilities & HDA_PARAMETER_WIDGET_CAPS_IN_AMP) { + DEBUG((DEBUG_INFO, "Widget @ 0x%X in amp\n", HdaWidget->NodeId)); + for (UINT8 c = 0; c < HdaWidget->ConnectionCount; c++) { + if (HdaWidget->UpstreamIndex == c) { + UINT8 offset = HDA_PARAMETER_AMP_CAPS_OFFSET(HdaWidget->AmpInCapabilities); + // If there are no overriden amp capabilities, check function group. + if (!(HdaWidget->AmpOverride)) + offset = HDA_PARAMETER_AMP_CAPS_OFFSET(HdaWidget->FuncGroup->AmpInCapabilities); + Status = HdaIo->SendCommand(HdaIo, HdaWidget->NodeId, HDA_CODEC_VERB(HDA_VERB_SET_AMP_GAIN_MUTE, + HDA_VERB_SET_AMP_GAIN_MUTE_PAYLOAD(c, offset, FALSE, TRUE, TRUE, TRUE, FALSE)), &Response); + if (EFI_ERROR(Status)) + return Status; + } else { + Status = HdaIo->SendCommand(HdaIo, HdaWidget->NodeId, HDA_CODEC_VERB(HDA_VERB_SET_AMP_GAIN_MUTE, + HDA_VERB_SET_AMP_GAIN_MUTE_PAYLOAD(c, 0, TRUE, TRUE, TRUE, TRUE, FALSE)), &Response); + if (EFI_ERROR(Status)) + return Status; + } + } + } + + // If there is more than one connection, select our upstream. + if (HdaWidget->ConnectionCount > 1) { + Status = HdaIo->SendCommand(HdaIo, HdaWidget->NodeId, HDA_CODEC_VERB(HDA_VERB_SET_CONN_SELECT_CONTROL, + HdaWidget->UpstreamIndex), &Response); + if (EFI_ERROR(Status)) + return Status; + } + + // If Output, set up stream. + if (HdaWidget->Type == HDA_WIDGET_TYPE_OUTPUT) { + DEBUG((DEBUG_INFO, "Widget @ 0x%X output\n", HdaWidget->NodeId)); + Status = HdaIo->SendCommand(HdaIo, HdaWidget->NodeId, HDA_CODEC_VERB(HDA_VERB_SET_CONVERTER_FORMAT, + StreamFormat), &Response); + if (EFI_ERROR(Status)) + return Status; + Status = HdaIo->SendCommand(HdaIo, HdaWidget->NodeId, HDA_CODEC_VERB(HDA_VERB_SET_CONVERTER_STREAM_CHANNEL, + HDA_VERB_SET_CONVERTER_STREAM_PAYLOAD(0, StreamId)), &Response); + if (EFI_ERROR(Status)) + return Status; + } + + // Move to upstream widget. + HdaWidget = HdaWidget->UpstreamWidget; + } + return EFI_SUCCESS; } VOID EFIAPI HdaCodecCleanup( - IN HDA_CODEC_DEV *HdaCodecDev) + IN HDA_CODEC_DEV *HdaCodecDev) { -// DEBUG((DEBUG_INFO, "HdaCodecCleanup(): start\n")); - - // Create variables. - EFI_STATUS Status; - HDA_FUNC_GROUP *HdaFuncGroup; - HDA_WIDGET_DEV *HdaWidget; - - // If codec is already clear, we are done. - if (HdaCodecDev == NULL) - return; - - // Clean HDA Codec Info protocol. - if (HdaCodecDev->HdaCodecInfoData != NULL) { - // Uninstall protocol. - DEBUG((DEBUG_INFO, "HdaCodecCleanup(): clean Hda Codec Info\n")); - Status = gBS->UninstallProtocolInterface(HdaCodecDev->ControllerHandle, - &gEfiHdaCodecInfoProtocolGuid, &HdaCodecDev->HdaCodecInfoData->HdaCodecInfo); - ASSERT_EFI_ERROR(Status); - - // Free data. - FreePool(HdaCodecDev->HdaCodecInfoData); - } - - // Clean Audio I/O protocol. - if (HdaCodecDev->AudioIoData != NULL) { - // Uninstall protocol. - DEBUG((DEBUG_INFO, "HdaCodecCleanup(): clean Audio I/O\n")); - Status = gBS->UninstallProtocolInterface(HdaCodecDev->ControllerHandle, - &gEfiAudioIoProtocolGuid, &HdaCodecDev->AudioIoData->AudioIo); - ASSERT_EFI_ERROR(Status); - - // Free data. - FreePool(HdaCodecDev->AudioIoData); - } - - // Clean up input and output port arrays. - if (HdaCodecDev->OutputPorts != NULL) - FreePool(HdaCodecDev->OutputPorts); - if (HdaCodecDev->InputPorts != NULL) - FreePool(HdaCodecDev->InputPorts); - - // Clean function groups. - if (HdaCodecDev->FuncGroups != NULL) { - // Clean each function group. - for (UINT8 f = 0; f < HdaCodecDev->FuncGroupsCount; f++) { - HdaFuncGroup = HdaCodecDev->FuncGroups + f; - - // Clean widgets in function group. - if (HdaFuncGroup->Widgets != NULL) { - for (UINT8 w = 0; w < HdaFuncGroup->WidgetsCount; w++) { - HdaWidget = HdaFuncGroup->Widgets + w; - - // Clean input amp default arrays. - if (HdaWidget->AmpInLeftDefaultGainMute != NULL) - FreePool(HdaWidget->AmpInLeftDefaultGainMute); - if (HdaWidget->AmpInRightDefaultGainMute != NULL) - FreePool(HdaWidget->AmpInRightDefaultGainMute); - - // Clean connections array. - if (HdaWidget->WidgetConnections != NULL) - FreePool(HdaWidget->WidgetConnections); - if (HdaWidget->Connections != NULL) - FreePool(HdaWidget->Connections); - } - - // Free widgets array. - FreePool(HdaFuncGroup->Widgets); - } + // DEBUG((DEBUG_INFO, "HdaCodecCleanup(): start\n")); + + // Create variables. + EFI_STATUS Status; + HDA_FUNC_GROUP *HdaFuncGroup; + HDA_WIDGET_DEV *HdaWidget; + + // If codec is already clear, we are done. + if (HdaCodecDev == NULL) + return; + + // Clean HDA Codec Info protocol. + if (HdaCodecDev->HdaCodecInfoData != NULL) { + // Uninstall protocol. + DEBUG((DEBUG_INFO, "HdaCodecCleanup(): clean Hda Codec Info\n")); + Status = gBS->UninstallProtocolInterface(HdaCodecDev->ControllerHandle, + &gEfiHdaCodecInfoProtocolGuid, &HdaCodecDev->HdaCodecInfoData->HdaCodecInfo); + ASSERT_EFI_ERROR(Status); + + // Free data. + FreePool(HdaCodecDev->HdaCodecInfoData); + } + + // Clean Audio I/O protocol. + if (HdaCodecDev->AudioIoData != NULL) { + // Uninstall protocol. + DEBUG((DEBUG_INFO, "HdaCodecCleanup(): clean Audio I/O\n")); + Status = gBS->UninstallProtocolInterface(HdaCodecDev->ControllerHandle, + &gEfiAudioIoProtocolGuid, &HdaCodecDev->AudioIoData->AudioIo); + ASSERT_EFI_ERROR(Status); + + // Free data. + FreePool(HdaCodecDev->AudioIoData); + } + + // Clean up input and output port arrays. + if (HdaCodecDev->OutputPorts != NULL) + FreePool(HdaCodecDev->OutputPorts); + if (HdaCodecDev->InputPorts != NULL) + FreePool(HdaCodecDev->InputPorts); + + // Clean function groups. + if (HdaCodecDev->FuncGroups != NULL) { + // Clean each function group. + for (UINT8 f = 0; f < HdaCodecDev->FuncGroupsCount; f++) { + HdaFuncGroup = HdaCodecDev->FuncGroups + f; + + // Clean widgets in function group. + if (HdaFuncGroup->Widgets != NULL) { + for (UINT8 w = 0; w < HdaFuncGroup->WidgetsCount; w++) { + HdaWidget = HdaFuncGroup->Widgets + w; + + // Clean input amp default arrays. + if (HdaWidget->AmpInLeftDefaultGainMute != NULL) + FreePool(HdaWidget->AmpInLeftDefaultGainMute); + if (HdaWidget->AmpInRightDefaultGainMute != NULL) + FreePool(HdaWidget->AmpInRightDefaultGainMute); + + // Clean connections array. + if (HdaWidget->WidgetConnections != NULL) + FreePool(HdaWidget->WidgetConnections); + if (HdaWidget->Connections != NULL) + FreePool(HdaWidget->Connections); } - - // Free function group array. - FreePool(HdaCodecDev->FuncGroups); + + // Free widgets array. + FreePool(HdaFuncGroup->Widgets); + } } - - // Free codec device. - gBS->UninstallProtocolInterface(HdaCodecDev->ControllerHandle, - &gEfiCallerIdGuid, HdaCodecDev); - FreePool(HdaCodecDev); + + // Free function group array. + FreePool(HdaCodecDev->FuncGroups); + } + + // Free codec device. + gBS->UninstallProtocolInterface(HdaCodecDev->ControllerHandle, + &gEfiCallerIdGuid, HdaCodecDev); + FreePool(HdaCodecDev); } EFI_STATUS EFIAPI HdaCodecDriverBindingSupported( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE ControllerHandle, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL) + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL) { - - // Create variables. - EFI_STATUS Status; - EFI_HDA_IO_PROTOCOL *HdaIo; - UINT8 CodecAddress; - - // Attempt to open the HDA codec protocol. If it can be opened, we can support it. - Status = gBS->OpenProtocol(ControllerHandle, &gEfiHdaIoProtocolGuid, (VOID**)&HdaIo, - This->DriverBindingHandle, ControllerHandle, EFI_OPEN_PROTOCOL_BY_DRIVER); - if (EFI_ERROR(Status)) - return Status; - - // Get address of codec. - Status = HdaIo->GetAddress(HdaIo, &CodecAddress); - if (EFI_ERROR(Status)) - goto CLOSE_CODEC; - - // Codec can be supported. - DEBUG((DEBUG_INFO, "HdaCodecDriverBindingSupported(): attaching to codec 0x%X\n", CodecAddress)); - Status = EFI_SUCCESS; - -CLOSE_CODEC: - // Close protocol. - gBS->CloseProtocol(ControllerHandle, &gEfiHdaIoProtocolGuid, This->DriverBindingHandle, ControllerHandle); + + // Create variables. + EFI_STATUS Status; + EFI_HDA_IO_PROTOCOL *HdaIo; + UINT8 CodecAddress; + + // Attempt to open the HDA codec protocol. If it can be opened, we can support it. + Status = gBS->OpenProtocol(ControllerHandle, &gEfiHdaIoProtocolGuid, (VOID**)&HdaIo, + This->DriverBindingHandle, ControllerHandle, EFI_OPEN_PROTOCOL_BY_DRIVER); + if (EFI_ERROR(Status)) return Status; + + // Get address of codec. + Status = HdaIo->GetAddress(HdaIo, &CodecAddress); + if (EFI_ERROR(Status)) + goto CLOSE_CODEC; + + // Codec can be supported. + DEBUG((DEBUG_INFO, "HdaCodecDriverBindingSupported(): attaching to codec 0x%X\n", CodecAddress)); + Status = EFI_SUCCESS; + +CLOSE_CODEC: + // Close protocol. + gBS->CloseProtocol(ControllerHandle, &gEfiHdaIoProtocolGuid, This->DriverBindingHandle, ControllerHandle); + return Status; } EFI_STATUS EFIAPI HdaCodecDriverBindingStart( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE ControllerHandle, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL) + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL) { -// DEBUG((DEBUG_INFO, "HdaCodecDriverBindingStart(): start\n")); - - // Create variables. - EFI_STATUS Status; - EFI_HDA_IO_PROTOCOL *HdaIo; - EFI_DEVICE_PATH_PROTOCOL *HdaCodecDevicePath; - HDA_CODEC_DEV *HdaCodecDev; - - // Open HDA I/O protocol. - Status = gBS->OpenProtocol(ControllerHandle, &gEfiHdaIoProtocolGuid, (VOID**)&HdaIo, - This->DriverBindingHandle, ControllerHandle, EFI_OPEN_PROTOCOL_BY_DRIVER); - if (EFI_ERROR(Status)) - return Status; - - // Open Device Path protocol. - Status = gBS->OpenProtocol(ControllerHandle, &gEfiDevicePathProtocolGuid, (VOID**)&HdaCodecDevicePath, - This->DriverBindingHandle, ControllerHandle, EFI_OPEN_PROTOCOL_BY_DRIVER); - if (EFI_ERROR(Status)) - goto CLOSE_CODEC; - // Allocate codec device. - HdaCodecDev = AllocateZeroPool(sizeof(HDA_CODEC_DEV)); - if (HdaCodecDev == NULL) { - Status = EFI_OUT_OF_RESOURCES; - goto CLOSE_CODEC; - } - - // Fill codec device data. - HdaCodecDev->Signature = HDA_CODEC_PRIVATE_DATA_SIGNATURE; - HdaCodecDev->HdaIo = HdaIo; - HdaCodecDev->DevicePath = HdaCodecDevicePath; - HdaCodecDev->ControllerHandle = ControllerHandle; - // Probe codec. - Status = HdaCodecProbeCodec(HdaCodecDev); - if (EFI_ERROR(Status)) - goto FREE_CODEC; - - // Get ports. - Status = HdaCodecParsePorts(HdaCodecDev); - if (EFI_ERROR(Status)) - goto FREE_CODEC; - - // Publish protocols. - Status = HdaCodecInstallProtocols(HdaCodecDev); - ASSERT_EFI_ERROR(Status); - if (EFI_ERROR(Status)) - goto FREE_CODEC; - - // Success. - return EFI_SUCCESS; - -FREE_CODEC: - // Cleanup codec. - HdaCodecCleanup(HdaCodecDev); - -CLOSE_CODEC: - // Close protocols. - gBS->CloseProtocol(ControllerHandle, &gEfiDevicePathProtocolGuid, This->DriverBindingHandle, ControllerHandle); - gBS->CloseProtocol(ControllerHandle, &gEfiHdaIoProtocolGuid, This->DriverBindingHandle, ControllerHandle); + // DEBUG((DEBUG_INFO, "HdaCodecDriverBindingStart(): start\n")); + + // Create variables. + EFI_STATUS Status; + EFI_HDA_IO_PROTOCOL *HdaIo; + EFI_DEVICE_PATH_PROTOCOL *HdaCodecDevicePath; + HDA_CODEC_DEV *HdaCodecDev; + + // Open HDA I/O protocol. + Status = gBS->OpenProtocol(ControllerHandle, &gEfiHdaIoProtocolGuid, (VOID**)&HdaIo, + This->DriverBindingHandle, ControllerHandle, EFI_OPEN_PROTOCOL_BY_DRIVER); + if (EFI_ERROR(Status)) return Status; + + // Open Device Path protocol. + Status = gBS->OpenProtocol(ControllerHandle, &gEfiDevicePathProtocolGuid, (VOID**)&HdaCodecDevicePath, + This->DriverBindingHandle, ControllerHandle, EFI_OPEN_PROTOCOL_BY_DRIVER); + if (EFI_ERROR(Status)) + goto CLOSE_CODEC; + // Allocate codec device. + HdaCodecDev = AllocateZeroPool(sizeof(HDA_CODEC_DEV)); + if (HdaCodecDev == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto CLOSE_CODEC; + } + + // Fill codec device data. + HdaCodecDev->Signature = HDA_CODEC_PRIVATE_DATA_SIGNATURE; + HdaCodecDev->HdaIo = HdaIo; + HdaCodecDev->DevicePath = HdaCodecDevicePath; + HdaCodecDev->ControllerHandle = ControllerHandle; + // Probe codec. + Status = HdaCodecProbeCodec(HdaCodecDev); + if (EFI_ERROR(Status)) + goto FREE_CODEC; + + // Get ports. + Status = HdaCodecParsePorts(HdaCodecDev); + if (EFI_ERROR(Status)) + goto FREE_CODEC; + + // Publish protocols. + Status = HdaCodecInstallProtocols(HdaCodecDev); + ASSERT_EFI_ERROR(Status); + if (EFI_ERROR(Status)) + goto FREE_CODEC; + + // Success. + return EFI_SUCCESS; + +FREE_CODEC: + // Cleanup codec. + HdaCodecCleanup(HdaCodecDev); + +CLOSE_CODEC: + // Close protocols. + gBS->CloseProtocol(ControllerHandle, &gEfiDevicePathProtocolGuid, This->DriverBindingHandle, ControllerHandle); + gBS->CloseProtocol(ControllerHandle, &gEfiHdaIoProtocolGuid, This->DriverBindingHandle, ControllerHandle); + return Status; } EFI_STATUS EFIAPI HdaCodecDriverBindingStop( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE ControllerHandle, - IN UINTN NumberOfChildren, - IN EFI_HANDLE *ChildHandleBuffer OPTIONAL) + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer OPTIONAL) { -// DEBUG((DEBUG_INFO, "HdaCodecDriverBindingStop(): start\n")); - - // Create variables. - EFI_STATUS Status; - HDA_CODEC_DEV *HdaCodecDev; - - // Get codec device. - Status = gBS->OpenProtocol(ControllerHandle, &gEfiCallerIdGuid, (VOID**)&HdaCodecDev, - This->DriverBindingHandle, ControllerHandle, EFI_OPEN_PROTOCOL_GET_PROTOCOL); - if (!(EFI_ERROR(Status))) { - // Ensure codec device is valid. - if (HdaCodecDev->Signature != HDA_CODEC_PRIVATE_DATA_SIGNATURE) - return EFI_INVALID_PARAMETER; - - // Cleanup codec. - HdaCodecCleanup(HdaCodecDev); - } - - // Close protocols. - gBS->CloseProtocol(ControllerHandle, &gEfiDevicePathProtocolGuid, This->DriverBindingHandle, ControllerHandle); - gBS->CloseProtocol(ControllerHandle, &gEfiHdaIoProtocolGuid, This->DriverBindingHandle, ControllerHandle); - return EFI_SUCCESS; + // DEBUG((DEBUG_INFO, "HdaCodecDriverBindingStop(): start\n")); + + // Create variables. + EFI_STATUS Status; + HDA_CODEC_DEV *HdaCodecDev; + + // Get codec device. + Status = gBS->OpenProtocol(ControllerHandle, &gEfiCallerIdGuid, (VOID**)&HdaCodecDev, + This->DriverBindingHandle, ControllerHandle, EFI_OPEN_PROTOCOL_GET_PROTOCOL); + if (!(EFI_ERROR(Status))) { + // Ensure codec device is valid. + if (HdaCodecDev->Signature != HDA_CODEC_PRIVATE_DATA_SIGNATURE) + return EFI_INVALID_PARAMETER; + + // Cleanup codec. + HdaCodecCleanup(HdaCodecDev); + } + + // Close protocols. + gBS->CloseProtocol(ControllerHandle, &gEfiDevicePathProtocolGuid, This->DriverBindingHandle, ControllerHandle); + gBS->CloseProtocol(ControllerHandle, &gEfiHdaIoProtocolGuid, This->DriverBindingHandle, ControllerHandle); + return EFI_SUCCESS; } + diff --git a/Drivers/AudioDxe/HdaCodec/HdaCodecAudioIo.c b/Drivers/AudioDxe/HdaCodec/HdaCodecAudioIo.c index 5ca90b840..8cf4a5080 100644 --- a/Drivers/AudioDxe/HdaCodec/HdaCodecAudioIo.c +++ b/Drivers/AudioDxe/HdaCodec/HdaCodecAudioIo.c @@ -589,24 +589,25 @@ HdaCodecAudioIoStartPlaybackAsync( EFI_STATUS EFIAPI HdaCodecAudioIoStopPlayback( - IN EFI_AUDIO_IO_PROTOCOL *This) { - DEBUG((DEBUG_INFO, "HdaCodecAudioIoStopPlayback(): start\n")); - - // Create variables. - AUDIO_IO_PRIVATE_DATA *AudioIoPrivateData; - EFI_HDA_IO_PROTOCOL *HdaIo; - - // If a parameter is invalid, return error. - if (This == NULL) - return EFI_INVALID_PARAMETER; - - // Get private data. - AudioIoPrivateData = AUDIO_IO_PRIVATE_DATA_FROM_THIS(This); + IN EFI_AUDIO_IO_PROTOCOL *This) +{ + DEBUG((DEBUG_INFO, "HdaCodecAudioIoStopPlayback(): start\n")); + + // Create variables. + AUDIO_IO_PRIVATE_DATA *AudioIoPrivateData; + EFI_HDA_IO_PROTOCOL *HdaIo; + + // If a parameter is invalid, return error. + if (This == NULL) + return EFI_INVALID_PARAMETER; + + // Get private data. + AudioIoPrivateData = AUDIO_IO_PRIVATE_DATA_FROM_THIS(This); if (!AudioIoPrivateData || !AudioIoPrivateData->HdaCodecDev || !AudioIoPrivateData->HdaCodecDev->HdaIo) { return EFI_NOT_FOUND; } - HdaIo = AudioIoPrivateData->HdaCodecDev->HdaIo; - - // Stop stream. - return HdaIo->StopStream(HdaIo, EfiHdaIoTypeOutput); + HdaIo = AudioIoPrivateData->HdaCodecDev->HdaIo; + + // Stop stream. + return HdaIo->StopStream(HdaIo, EfiHdaIoTypeOutput); } diff --git a/Drivers/AudioDxe/HdaController/HdaController.c b/Drivers/AudioDxe/HdaController/HdaController.c index ee7b36764..68587f8d8 100644 --- a/Drivers/AudioDxe/HdaController/HdaController.c +++ b/Drivers/AudioDxe/HdaController/HdaController.c @@ -216,45 +216,45 @@ EFIAPI HdaControllerReset( IN HDA_CONTROLLER_DEV *HdaControllerDev) { -// DEBUG((DEBUG_INFO, "HdaControllerReset(): start\n")); - - // Create variables. - EFI_STATUS Status; - EFI_PCI_IO_PROTOCOL *PciIo = HdaControllerDev->PciIo; - UINT32 HdaGCtl = 0; - UINT64 Tmp = 0; - - // Get value of CRST bit. - Status = PciIo->Mem.Read(PciIo, EfiPciIoWidthUint32, PCI_HDA_BAR, HDA_REG_GCTL, 1, &HdaGCtl); - if (EFI_ERROR(Status)) - return Status; - - // Check if the controller is already in reset. If not, clear bit. - if (!(HdaGCtl & HDA_REG_GCTL_CRST)) { - HdaGCtl &= ~HDA_REG_GCTL_CRST; - Status = PciIo->Mem.Write(PciIo, EfiPciIoWidthUint32, PCI_HDA_BAR, HDA_REG_GCTL, 1, &HdaGCtl); - if (EFI_ERROR(Status)) - return Status; - } - - // Set CRST bit to begin the process of coming out of reset. - HdaGCtl |= HDA_REG_GCTL_CRST; + // DEBUG((DEBUG_INFO, "HdaControllerReset(): start\n")); + + // Create variables. + EFI_STATUS Status; + EFI_PCI_IO_PROTOCOL *PciIo = HdaControllerDev->PciIo; + UINT32 HdaGCtl = 0; + UINT64 Tmp = 0; + + // Get value of CRST bit. + Status = PciIo->Mem.Read(PciIo, EfiPciIoWidthUint32, PCI_HDA_BAR, HDA_REG_GCTL, 1, &HdaGCtl); + if (EFI_ERROR(Status)) + return Status; + + // Check if the controller is already in reset. If not, clear bit. + if (!(HdaGCtl & HDA_REG_GCTL_CRST)) { + HdaGCtl &= ~HDA_REG_GCTL_CRST; Status = PciIo->Mem.Write(PciIo, EfiPciIoWidthUint32, PCI_HDA_BAR, HDA_REG_GCTL, 1, &HdaGCtl); if (EFI_ERROR(Status)) - return Status; - - // Wait for bit to be set. Once bit is set, the controller is ready. - Status = PciIo->PollMem(PciIo, EfiPciIoWidthUint32, PCI_HDA_BAR, HDA_REG_GCTL, - HDA_REG_GCTL_CRST, HDA_REG_GCTL_CRST, MS_TO_NANOSECOND(100), &Tmp); - if (EFI_ERROR(Status)) - return Status; - - // Wait 100ms to ensure all codecs have also reset. - gBS->Stall(MS_TO_MICROSECOND(100)); - - // Controller is reset. -// DEBUG((DEBUG_INFO, "HdaControllerReset(): done\n")); - return EFI_SUCCESS; + return Status; + } + + // Set CRST bit to begin the process of coming out of reset. + HdaGCtl |= HDA_REG_GCTL_CRST; + Status = PciIo->Mem.Write(PciIo, EfiPciIoWidthUint32, PCI_HDA_BAR, HDA_REG_GCTL, 1, &HdaGCtl); + if (EFI_ERROR(Status)) + return Status; + + // Wait for bit to be set. Once bit is set, the controller is ready. + Status = PciIo->PollMem(PciIo, EfiPciIoWidthUint32, PCI_HDA_BAR, HDA_REG_GCTL, + HDA_REG_GCTL_CRST, HDA_REG_GCTL_CRST, MS_TO_NANOSECOND(100), &Tmp); + if (EFI_ERROR(Status)) + return Status; + + // Wait 100ms to ensure all codecs have also reset. + gBS->Stall(MS_TO_MICROSECOND(100)); + + // Controller is reset. + // DEBUG((DEBUG_INFO, "HdaControllerReset(): done\n")); + return EFI_SUCCESS; } EFI_STATUS @@ -262,141 +262,142 @@ EFIAPI HdaControllerScanCodecs( IN HDA_CONTROLLER_DEV *HdaControllerDev) { -// DEBUG((DEBUG_INFO, "HdaControllerScanCodecs(): start\n")); - - // Create variables. - EFI_STATUS Status; - EFI_PCI_IO_PROTOCOL *PciIo; - UINT16 HdaStatests = 0; - EFI_HDA_IO_VERB_LIST HdaCodecVerbList; - UINT32 VendorVerb; - UINT32 VendorResponse; - UINT8 i; - - // Streams. - UINTN CurrentOutputStreamIndex = 0; - UINTN CurrentInputStreamIndex = 0; - - // Protocols. - HDA_IO_PRIVATE_DATA *HdaIoPrivateData; - VOID *TmpProtocol; - - if (!HdaControllerDev) { - return EFI_INVALID_PARAMETER; - } - - PciIo = HdaControllerDev->PciIo; - - // Get STATESTS register. - Status = PciIo->Mem.Read(PciIo, EfiPciIoWidthUint16, PCI_HDA_BAR, HDA_REG_STATESTS, 1, &HdaStatests); - if (EFI_ERROR(Status)) - return Status; - - // Create verb list with single item. - VendorVerb = HDA_CODEC_VERB(HDA_VERB_GET_PARAMETER, HDA_PARAMETER_VENDOR_ID); - SetMem(&HdaCodecVerbList, sizeof(EFI_HDA_IO_VERB_LIST), 0); - HdaCodecVerbList.Count = 1; - HdaCodecVerbList.Verbs = &VendorVerb; - HdaCodecVerbList.Responses = &VendorResponse; - - // Iterate through register looking for active codecs. - for (i = 0; i < HDA_MAX_CODECS; i++) { - // Do we have a codec at this address? - if ((HdaStatests & (1 << i))) { -// DEBUG((DEBUG_INFO, "HdaControllerScanCodecs(): found codec @ 0x%X\n", i)); - - // Try to get the vendor ID. If this fails, ignore the codec. - VendorResponse = 0; - Status = HdaControllerSendCommands(HdaControllerDev, i, HDA_NID_ROOT, &HdaCodecVerbList); - if ((EFI_ERROR(Status)) || (VendorResponse == 0)) - continue; - - // Create HDA I/O protocol private data structure. - HdaIoPrivateData = AllocateZeroPool(sizeof(HDA_IO_PRIVATE_DATA)); - if (HdaIoPrivateData == NULL) { - Status = EFI_OUT_OF_RESOURCES; - goto FREE_CODECS; - } - - // Fill HDA I/O protocol private data structure. - HdaIoPrivateData->Signature = HDA_CONTROLLER_PRIVATE_DATA_SIGNATURE; - HdaIoPrivateData->HdaCodecAddress = i; - HdaIoPrivateData->HdaControllerDev = HdaControllerDev; - HdaIoPrivateData->HdaIo.GetAddress = HdaControllerHdaIoGetAddress; - HdaIoPrivateData->HdaIo.SendCommand = HdaControllerHdaIoSendCommand; - HdaIoPrivateData->HdaIo.SetupStream = HdaControllerHdaIoSetupStream; - HdaIoPrivateData->HdaIo.CloseStream = HdaControllerHdaIoCloseStream; - HdaIoPrivateData->HdaIo.GetStream = HdaControllerHdaIoGetStream; - HdaIoPrivateData->HdaIo.StartStream = HdaControllerHdaIoStartStream; - HdaIoPrivateData->HdaIo.StopStream = HdaControllerHdaIoStopStream; - - // Assign output stream. - if (CurrentOutputStreamIndex < HdaControllerDev->OutputStreamsCount) { - // DEBUG((DEBUG_INFO, "Assigning output stream %u to codec\n", CurrentOutputStreamIndex)); - HdaIoPrivateData->HdaOutputStream = HdaControllerDev->OutputStreams + CurrentOutputStreamIndex; - CurrentOutputStreamIndex++; - } - - // Assign input stream. - if (CurrentInputStreamIndex < HdaControllerDev->InputStreamsCount) { -// DEBUG((DEBUG_INFO, "Assigning input stream %u to codec\n", CurrentInputStreamIndex)); - HdaIoPrivateData->HdaInputStream = HdaControllerDev->InputStreams + CurrentInputStreamIndex; - CurrentInputStreamIndex++; - } - - // Add to array. - HdaControllerDev->HdaIoChildren[i].PrivateData = HdaIoPrivateData; - } - } - - // Clear STATESTS register. - HdaStatests = HDA_REG_STATESTS_CLEAR; - Status = PciIo->Mem.Write(PciIo, EfiPciIoWidthUint16, PCI_HDA_BAR, HDA_REG_STATESTS, 1, &HdaStatests); - if (EFI_ERROR(Status)) - return Status; - - // Install protocols on each codec. + // DEBUG((DEBUG_INFO, "HdaControllerScanCodecs(): start\n")); - for (i = 0; i < HDA_MAX_CODECS; i++) { - // Do we have a codec at this address? - if (HdaControllerDev->HdaIoChildren[i].PrivateData != NULL) { - // Create Device Path for codec. - EFI_HDA_IO_DEVICE_PATH HdaIoDevicePathNode; //EFI_HDA_IO_DEVICE_PATH_TEMPLATE; - HdaIoDevicePathNode.Header.Type = MESSAGING_DEVICE_PATH; - HdaIoDevicePathNode.Header.SubType = MSG_VENDOR_DP; - HdaIoDevicePathNode.Header.Length[0] = (UINT8)(sizeof(EFI_HDA_IO_DEVICE_PATH)); - HdaIoDevicePathNode.Header.Length[1] = (UINT8)((sizeof(EFI_HDA_IO_DEVICE_PATH)) >> 8); - HdaIoDevicePathNode.Guid = gEfiHdaIoDevicePathGuid; -// CopyMem((VOID*)&HdaIoDevicePathNode.Guid, (VOID*)&gEfiHdaIoDevicePathGuid, sizeof(EFI_GUID)); - HdaIoDevicePathNode.Address = i; - HdaControllerDev->HdaIoChildren[i].DevicePath = AppendDevicePathNode(HdaControllerDev->DevicePath, (EFI_DEVICE_PATH_PROTOCOL*)&HdaIoDevicePathNode); - if (HdaControllerDev->HdaIoChildren[i].DevicePath == NULL) { - Status = EFI_INVALID_PARAMETER; - goto FREE_CODECS; - } - - // Install protocols for the codec. The codec driver will later bind to this. - HdaControllerDev->HdaIoChildren[i].Handle = NULL; - Status = gBS->InstallMultipleProtocolInterfaces(&HdaControllerDev->HdaIoChildren[i].Handle, - &gEfiDevicePathProtocolGuid, HdaControllerDev->HdaIoChildren[i].DevicePath, - &gEfiHdaIoProtocolGuid, &HdaControllerDev->HdaIoChildren[i].PrivateData->HdaIo, NULL); - if (EFI_ERROR(Status)) - goto FREE_CODECS; - - // Connect child to parent. - Status = gBS->OpenProtocol(HdaControllerDev->ControllerHandle, &gEfiPciIoProtocolGuid, &TmpProtocol, - HdaControllerDev->DriverBinding->DriverBindingHandle, HdaControllerDev->HdaIoChildren[i].Handle, EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER); - if (EFI_ERROR(Status)) - goto FREE_CODECS; - } - } - - return EFI_SUCCESS; - -FREE_CODECS: - //DEBUG((DEBUG_INFO, "HdaControllerScanCodecs(): failed to load driver for codec @ 0x%X\n", i)); - + // Create variables. + EFI_STATUS Status; + EFI_PCI_IO_PROTOCOL *PciIo; + UINT16 HdaStatests = 0; + EFI_HDA_IO_VERB_LIST HdaCodecVerbList; + UINT32 VendorVerb; + UINT32 VendorResponse; + UINT8 i; + + // Streams. + UINTN CurrentOutputStreamIndex = 0; + UINTN CurrentInputStreamIndex = 0; + + // Protocols. + HDA_IO_PRIVATE_DATA *HdaIoPrivateData; + VOID *TmpProtocol; + + if (!HdaControllerDev) { + return EFI_INVALID_PARAMETER; + } + + PciIo = HdaControllerDev->PciIo; + + // Get STATESTS register. + Status = PciIo->Mem.Read(PciIo, EfiPciIoWidthUint16, PCI_HDA_BAR, HDA_REG_STATESTS, 1, &HdaStatests); + if (EFI_ERROR(Status)) return Status; + + // Create verb list with single item. + VendorVerb = HDA_CODEC_VERB(HDA_VERB_GET_PARAMETER, HDA_PARAMETER_VENDOR_ID); + SetMem(&HdaCodecVerbList, sizeof(EFI_HDA_IO_VERB_LIST), 0); + HdaCodecVerbList.Count = 1; + HdaCodecVerbList.Verbs = &VendorVerb; + HdaCodecVerbList.Responses = &VendorResponse; + + // Iterate through register looking for active codecs. + for (i = 0; i < HDA_MAX_CODECS; i++) { + // Do we have a codec at this address? + if ((HdaStatests & (1 << i))) { + // DEBUG((DEBUG_INFO, "HdaControllerScanCodecs(): found codec @ 0x%X\n", i)); + + // Try to get the vendor ID. If this fails, ignore the codec. + VendorResponse = 0; + Status = HdaControllerSendCommands(HdaControllerDev, i, HDA_NID_ROOT, &HdaCodecVerbList); + if ((EFI_ERROR(Status)) || (VendorResponse == 0)) + continue; + + // Create HDA I/O protocol private data structure. + HdaIoPrivateData = AllocateZeroPool(sizeof(HDA_IO_PRIVATE_DATA)); + if (HdaIoPrivateData == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto FREE_CODECS; + } + + // Fill HDA I/O protocol private data structure. + HdaIoPrivateData->Signature = HDA_CONTROLLER_PRIVATE_DATA_SIGNATURE; + HdaIoPrivateData->HdaCodecAddress = i; + HdaIoPrivateData->HdaControllerDev = HdaControllerDev; + HdaIoPrivateData->HdaIo.GetAddress = HdaControllerHdaIoGetAddress; + HdaIoPrivateData->HdaIo.SendCommand = HdaControllerHdaIoSendCommand; + HdaIoPrivateData->HdaIo.SetupStream = HdaControllerHdaIoSetupStream; + HdaIoPrivateData->HdaIo.CloseStream = HdaControllerHdaIoCloseStream; + HdaIoPrivateData->HdaIo.GetStream = HdaControllerHdaIoGetStream; + HdaIoPrivateData->HdaIo.StartStream = HdaControllerHdaIoStartStream; + HdaIoPrivateData->HdaIo.StopStream = HdaControllerHdaIoStopStream; + + // Assign output stream. + if (CurrentOutputStreamIndex < HdaControllerDev->OutputStreamsCount) { + // DEBUG((DEBUG_INFO, "Assigning output stream %u to codec\n", CurrentOutputStreamIndex)); + HdaIoPrivateData->HdaOutputStream = HdaControllerDev->OutputStreams + CurrentOutputStreamIndex; + CurrentOutputStreamIndex++; + } + + // Assign input stream. + if (CurrentInputStreamIndex < HdaControllerDev->InputStreamsCount) { + // DEBUG((DEBUG_INFO, "Assigning input stream %u to codec\n", CurrentInputStreamIndex)); + HdaIoPrivateData->HdaInputStream = HdaControllerDev->InputStreams + CurrentInputStreamIndex; + CurrentInputStreamIndex++; + } + + // Add to array. + HdaControllerDev->HdaIoChildren[i].PrivateData = HdaIoPrivateData; + } + } + + // Clear STATESTS register. + HdaStatests = HDA_REG_STATESTS_CLEAR; + Status = PciIo->Mem.Write(PciIo, EfiPciIoWidthUint16, PCI_HDA_BAR, HDA_REG_STATESTS, 1, &HdaStatests); + if (EFI_ERROR(Status)) { + return Status; + } + + // Install protocols on each codec. + + for (i = 0; i < HDA_MAX_CODECS; i++) { + // Do we have a codec at this address? + if (HdaControllerDev->HdaIoChildren[i].PrivateData != NULL) { + // Create Device Path for codec. + EFI_HDA_IO_DEVICE_PATH HdaIoDevicePathNode; //EFI_HDA_IO_DEVICE_PATH_TEMPLATE; + HdaIoDevicePathNode.Header.Type = MESSAGING_DEVICE_PATH; + HdaIoDevicePathNode.Header.SubType = MSG_VENDOR_DP; + HdaIoDevicePathNode.Header.Length[0] = (UINT8)(sizeof(EFI_HDA_IO_DEVICE_PATH)); + HdaIoDevicePathNode.Header.Length[1] = (UINT8)((sizeof(EFI_HDA_IO_DEVICE_PATH)) >> 8); + HdaIoDevicePathNode.Guid = gEfiHdaIoDevicePathGuid; + // CopyMem((VOID*)&HdaIoDevicePathNode.Guid, (VOID*)&gEfiHdaIoDevicePathGuid, sizeof(EFI_GUID)); + HdaIoDevicePathNode.Address = i; + HdaControllerDev->HdaIoChildren[i].DevicePath = AppendDevicePathNode(HdaControllerDev->DevicePath, (EFI_DEVICE_PATH_PROTOCOL*)&HdaIoDevicePathNode); + if (HdaControllerDev->HdaIoChildren[i].DevicePath == NULL) { + Status = EFI_INVALID_PARAMETER; + goto FREE_CODECS; + } + + // Install protocols for the codec. The codec driver will later bind to this. + HdaControllerDev->HdaIoChildren[i].Handle = NULL; + Status = gBS->InstallMultipleProtocolInterfaces(&HdaControllerDev->HdaIoChildren[i].Handle, + &gEfiDevicePathProtocolGuid, HdaControllerDev->HdaIoChildren[i].DevicePath, + &gEfiHdaIoProtocolGuid, &HdaControllerDev->HdaIoChildren[i].PrivateData->HdaIo, NULL); + if (EFI_ERROR(Status)) + goto FREE_CODECS; + + // Connect child to parent. + Status = gBS->OpenProtocol(HdaControllerDev->ControllerHandle, &gEfiPciIoProtocolGuid, &TmpProtocol, + HdaControllerDev->DriverBinding->DriverBindingHandle, HdaControllerDev->HdaIoChildren[i].Handle, EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER); + if (EFI_ERROR(Status)) + goto FREE_CODECS; + } + } + + return EFI_SUCCESS; + +FREE_CODECS: + //DEBUG((DEBUG_INFO, "HdaControllerScanCodecs(): failed to load driver for codec @ 0x%X\n", i)); + + return Status; } EFI_STATUS diff --git a/Drivers/AudioDxe/HdaController/HdaControllerHdaIo.c b/Drivers/AudioDxe/HdaController/HdaControllerHdaIo.c index ad3c99983..8fb4d5b1c 100644 --- a/Drivers/AudioDxe/HdaController/HdaControllerHdaIo.c +++ b/Drivers/AudioDxe/HdaController/HdaControllerHdaIo.c @@ -134,7 +134,7 @@ HdaControllerHdaIoSetupStream( UINT16 HdaStreamFormat = 0; UINT8 HdaStreamId = 0; EFI_TPL OldTpl = 0; - UINT8 i; + UINT8 i; // If a parameter is invalid, return error. if ((This == NULL) || (Type >= EfiHdaIoTypeMaximum) || (StreamId == NULL)) diff --git a/Drivers/AudioDxe/HdaController/HdaControllerMem.c b/Drivers/AudioDxe/HdaController/HdaControllerMem.c index 51e7367ec..dfec12a7d 100644 --- a/Drivers/AudioDxe/HdaController/HdaControllerMem.c +++ b/Drivers/AudioDxe/HdaController/HdaControllerMem.c @@ -37,7 +37,7 @@ HdaControllerInitCorb( EFI_PCI_IO_PROTOCOL *PciIo = HdaDev->PciIo; // HDA register values. - UINT8 HdaCorbSize; + UINT8 HdaCorbSize = 0; UINT32 HdaLowerCorbBaseAddr; UINT32 HdaUpperCorbBaseAddr; UINT16 HdaCorbWp; @@ -197,7 +197,7 @@ HdaControllerSetCorb( // Create variables. EFI_STATUS Status; EFI_PCI_IO_PROTOCOL *PciIo = HdaDev->PciIo; - UINT8 HdaCorbCtl; + UINT8 HdaCorbCtl = 0; UINT64 Tmp; // Get current value of CORBCTL. diff --git a/rEFIt_UEFI/Platform/DataHubCpu.cpp b/rEFIt_UEFI/Platform/DataHubCpu.cpp index 412ef1e72..b6bf38be8 100644 --- a/rEFIt_UEFI/Platform/DataHubCpu.cpp +++ b/rEFIt_UEFI/Platform/DataHubCpu.cpp @@ -325,11 +325,12 @@ SetVariablesForOSX(LOADER_ENTRY *Entry) UINT16 DensityThreshold = 0x96; UINT64 ConfigStatus = 0; Color = gSettings.DefaultBackgroundColor; - AddNvramVariable(L"DefaultBackgroundColor", &gEfiAppleNvramGuid, Attributes, 4, &Color); + DBG("set DefaultBackgroundColor=0x%x\n", Color); + SetNvramVariable(L"DefaultBackgroundColor", &gEfiAppleNvramGuid, Attributes, 4, &Color); // add some UI variables - AddNvramVariable(L"ActualDensity", &gEfiAppleBootGuid, Attributes, 2, &ActualDensity); - AddNvramVariable(L"DensityThreshold", &gEfiAppleBootGuid, Attributes, 2, &DensityThreshold); - AddNvramVariable(L"gfx-saved-config-restore-status", &gEfiAppleNvramGuid, Attributes, 8, &ConfigStatus); + SetNvramVariable(L"ActualDensity", &gEfiAppleBootGuid, Attributes, 2, &ActualDensity); + SetNvramVariable(L"DensityThreshold", &gEfiAppleBootGuid, Attributes, 2, &DensityThreshold); + SetNvramVariable(L"gfx-saved-config-restore-status", &gEfiAppleNvramGuid, Attributes, 8, &ConfigStatus); } if (gSettings.UIScale == 0x80000000) { diff --git a/rEFIt_UEFI/Platform/StartupSound.cpp b/rEFIt_UEFI/Platform/StartupSound.cpp index a985dcfc9..a8da19522 100644 --- a/rEFIt_UEFI/Platform/StartupSound.cpp +++ b/rEFIt_UEFI/Platform/StartupSound.cpp @@ -393,8 +393,12 @@ EFI_STATUS CheckSyncSound(BOOLEAN Stop) Status = HdaIo->GetStream(HdaIo, EfiHdaIoTypeOutput, &StreamRunning); if ((EFI_ERROR(Status) || Stop) && StreamRunning) { - DBG("stream stopping\n"); + DBG("stream stopping & controller reset\n"); HdaIo->StopStream(HdaIo, EfiHdaIoTypeOutput); +// HDA_IO_PRIVATE_DATA *HdaIoPrivateData = HDA_IO_PRIVATE_DATA_FROM_THIS(HdaIo); +// HDA_CONTROLLER_DEV *HdaControllerDev = HdaIoPrivateData->HdaControllerDev; +// EFI_PCI_IO_PROTOCOL *PciIo = HdaControllerDev->PciIo; +// HdaControllerCleanup(HdaControllerDev); } if (!StreamRunning) { diff --git a/rEFIt_UEFI/refit/main.cpp b/rEFIt_UEFI/refit/main.cpp index 926bb0414..9838b2a75 100644 --- a/rEFIt_UEFI/refit/main.cpp +++ b/rEFIt_UEFI/refit/main.cpp @@ -108,6 +108,8 @@ EFI_HANDLE ConsoleInHandle; EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL* SimpleTextEx; EFI_KEY_DATA KeyData; +EFI_HANDLE AudioDriverHandle; + CONST CHAR8* AudioOutputNames[] = { "LineOut", "Speaker", @@ -831,8 +833,13 @@ VOID LOADER_ENTRY::StartLoader() } if (AudioIo) { -// AudioIo->StopPlayback(AudioIo); - CheckSyncSound(true); + AudioIo->StopPlayback(AudioIo); +// CheckSyncSound(true); + EFI_DRIVER_BINDING_PROTOCOL *DriverBinding = NULL; + Status = gBS->HandleProtocol(AudioDriverHandle, &gEfiDriverBindingProtocolGuid, (VOID **)&DriverBinding); + if (DriverBinding) { + DriverBinding->Stop(DriverBinding, AudioDriverHandle, 0, NULL); + } } // DBG("Set FakeCPUID: 0x%X\n", gSettings.FakeCPUID); @@ -848,9 +855,9 @@ VOID LOADER_ENTRY::StartLoader() // which is wrong // apianti - only block console output if using graphics // but don't block custom boot logo - if ( LoadOptions.containsIC("-v") ) { + if (LoadOptions.containsIC("-v")) { Flags = OSFLAG_UNSET(Flags, OSFLAG_USEGRAPHICS); - } + } } else if (OSTYPE_IS_WINDOWS(LoaderType)) { @@ -1153,6 +1160,9 @@ static VOID ScanDriverDir(IN CONST CHAR16 *Path, OUT EFI_HANDLE **DriversToConne if (EFI_ERROR(Status)) { continue; } + if (StrStr(FileName, L"AudioDxe") != NULL) { + AudioDriverHandle = DriverHandle; + } if (StrStr(FileName, L"EmuVariable") != NULL) { gDriversFlags.EmuVariableLoaded = TRUE; } else if (StrStr(FileName, L"Video") != NULL) {