CloverBootloader/Drivers/AudioDxe/HdaCodec/HdaCodecAudioIo.c
2019-09-03 12:58:42 +03:00

613 lines
21 KiB
C

/*
* File: HdaCodecAudioIo.c
*
* Copyright (c) 2018 John Davis
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifdef _WIN32
#pragma warning (disable: 4054)
#endif
//#include "HdaCodec.h"
#include "../AudioDxe.h"
//#include <IndustryStandard/HdaCodec.h>
#include <Protocol/AudioIo.h>
/*
// HDA I/O Stream callback.
VOID
HdaCodecHdaIoStreamCallback(
IN EFI_HDA_IO_PROTOCOL_TYPE Type,
IN VOID *Context1,
IN VOID *Context2,
IN VOID *Context3)
{
// DEBUG((DEBUG_INFO, "HdaCodecHdaIoStreamCallback(): start\n"));
// Create variables.
EFI_AUDIO_IO_PROTOCOL *AudioIo = (EFI_AUDIO_IO_PROTOCOL*)Context1;
EFI_AUDIO_IO_CALLBACK AudioIoCallback = (EFI_AUDIO_IO_CALLBACK)Context2;
// Ensure required parameters are valid.
if ((AudioIo == NULL) || (AudioIoCallback == NULL))
return;
// Invoke callback.
AudioIoCallback(AudioIo, Context3);
}
*/
/**
Gets the collection of output ports.
@param[in] This A pointer to the EFI_AUDIO_IO_PROTOCOL instance.
@param[out] OutputPorts A pointer to a buffer where the output ports will be placed.
@param[out] OutputPortsCount The number of ports in OutputPorts.
@retval EFI_SUCCESS The audio data was played successfully.
@retval EFI_INVALID_PARAMETER One or more parameters are invalid.
**/
EFI_STATUS
EFIAPI
HdaCodecAudioIoGetOutputs(
IN EFI_AUDIO_IO_PROTOCOL *This,
OUT EFI_AUDIO_IO_PROTOCOL_PORT **OutputPorts,
OUT UINTN *OutputPortsCount)
{
// DEBUG((DEBUG_INFO, "HdaCodecAudioIoGetOutputs(): start\n"));
// Create variables.
EFI_STATUS Status;
AUDIO_IO_PRIVATE_DATA *AudioIoPrivateData;
HDA_CODEC_DEV *HdaCodecDev;
EFI_AUDIO_IO_PROTOCOL_PORT *HdaOutputPorts;
UINT32 SupportedRates;
UINTN i;
// If a parameter is invalid, return error.
if ((This == NULL) || (OutputPorts == NULL) ||
(OutputPortsCount == NULL))
return EFI_INVALID_PARAMETER;
// Get private data.
AudioIoPrivateData = AUDIO_IO_PRIVATE_DATA_FROM_THIS(This);
if (!AudioIoPrivateData) {
return EFI_NOT_STARTED;
}
HdaCodecDev = AudioIoPrivateData->HdaCodecDev;
// Allocate buffer.
HdaOutputPorts = AllocateZeroPool(sizeof(EFI_AUDIO_IO_PROTOCOL_PORT) * HdaCodecDev->OutputPortsCount);
if (HdaOutputPorts == NULL)
return EFI_OUT_OF_RESOURCES;
// Get output ports.
for (i = 0; i < HdaCodecDev->OutputPortsCount; i++) {
// Port is an output.
HdaOutputPorts[i].Type = EfiAudioIoTypeOutput;
// Get device type.
switch (HDA_VERB_GET_CONFIGURATION_DEFAULT_DEVICE(HdaCodecDev->OutputPorts[i]->DefaultConfiguration))
{
case HDA_CONFIG_DEFAULT_DEVICE_LINE_OUT:
case HDA_CONFIG_DEFAULT_DEVICE_LINE_IN:
HdaOutputPorts[i].Device = EfiAudioIoDeviceLine;
break;
case HDA_CONFIG_DEFAULT_DEVICE_SPEAKER:
HdaOutputPorts[i].Device = EfiAudioIoDeviceSpeaker;
break;
case HDA_CONFIG_DEFAULT_DEVICE_HEADPHONE_OUT:
HdaOutputPorts[i].Device = EfiAudioIoDeviceHeadphones;
break;
case HDA_CONFIG_DEFAULT_DEVICE_SPDIF_OUT:
case HDA_CONFIG_DEFAULT_DEVICE_SPDIF_IN:
HdaOutputPorts[i].Device = EfiAudioIoDeviceSpdif;
break;
case HDA_CONFIG_DEFAULT_DEVICE_MIC_IN:
HdaOutputPorts[i].Device = EfiAudioIoDeviceMic;
break;
default:
if (HdaCodecDev->OutputPorts[i]->PinCapabilities & HDA_PARAMETER_PIN_CAPS_HDMI)
HdaOutputPorts[i].Device = EfiAudioIoDeviceHdmi;
else
HdaOutputPorts[i].Device = EfiAudioIoDeviceOther;
}
// Get location.
switch (HDA_VERB_GET_CONFIGURATION_DEFAULT_LOC(HdaCodecDev->OutputPorts[i]->DefaultConfiguration)) {
case HDA_CONFIG_DEFAULT_LOC_SPEC_NA:
HdaOutputPorts[i].Location = EfiAudioIoLocationNone;
break;
case HDA_CONFIG_DEFAULT_LOC_SPEC_REAR:
HdaOutputPorts[i].Location = EfiAudioIoLocationRear;
break;
case HDA_CONFIG_DEFAULT_LOC_SPEC_FRONT:
HdaOutputPorts[i].Location = EfiAudioIoLocationFront;
break;
case HDA_CONFIG_DEFAULT_LOC_SPEC_LEFT:
HdaOutputPorts[i].Location = EfiAudioIoLocationLeft;
break;
case HDA_CONFIG_DEFAULT_LOC_SPEC_RIGHT:
HdaOutputPorts[i].Location = EfiAudioIoLocationRight;
break;
case HDA_CONFIG_DEFAULT_LOC_SPEC_TOP:
HdaOutputPorts[i].Location = EfiAudioIoLocationTop;
break;
case HDA_CONFIG_DEFAULT_LOC_SPEC_BOTTOM:
HdaOutputPorts[i].Location = EfiAudioIoLocationBottom;
break;
default:
HdaOutputPorts[i].Location = EfiAudioIoLocationOther;
}
// Get surface.
switch (HDA_VERB_GET_CONFIGURATION_DEFAULT_SURF(HdaCodecDev->OutputPorts[i]->DefaultConfiguration)) {
case HDA_CONFIG_DEFAULT_LOC_SURF_EXTERNAL:
HdaOutputPorts[i].Surface = EfiAudioIoSurfaceExternal;
break;
case HDA_CONFIG_DEFAULT_LOC_SURF_INTERNAL:
HdaOutputPorts[i].Surface = EfiAudioIoSurfaceInternal;
break;
default:
HdaOutputPorts[i].Surface = EfiAudioIoSurfaceOther;
}
// Get supported stream formats.
Status = HdaCodecGetSupportedPcmRates(HdaCodecDev->OutputPorts[i], &SupportedRates);
if (EFI_ERROR(Status))
return Status;
// Get supported bit depths.
HdaOutputPorts[i].SupportedBits = 0;
if (SupportedRates & HDA_PARAMETER_SUPPORTED_PCM_SIZE_RATES_8BIT)
HdaOutputPorts[i].SupportedBits |= EfiAudioIoBits8;
if (SupportedRates & HDA_PARAMETER_SUPPORTED_PCM_SIZE_RATES_16BIT)
HdaOutputPorts[i].SupportedBits |= EfiAudioIoBits16;
if (SupportedRates & HDA_PARAMETER_SUPPORTED_PCM_SIZE_RATES_20BIT)
HdaOutputPorts[i].SupportedBits |= EfiAudioIoBits20;
if (SupportedRates & HDA_PARAMETER_SUPPORTED_PCM_SIZE_RATES_24BIT)
HdaOutputPorts[i].SupportedBits |= EfiAudioIoBits24;
if (SupportedRates & HDA_PARAMETER_SUPPORTED_PCM_SIZE_RATES_32BIT)
HdaOutputPorts[i].SupportedBits |= EfiAudioIoBits32;
// Get supported sample rates.
HdaOutputPorts[i].SupportedFreqs = 0;
if (SupportedRates & HDA_PARAMETER_SUPPORTED_PCM_SIZE_RATES_8KHZ)
HdaOutputPorts[i].SupportedFreqs |= EfiAudioIoFreq8kHz;
if (SupportedRates & HDA_PARAMETER_SUPPORTED_PCM_SIZE_RATES_11KHZ)
HdaOutputPorts[i].SupportedFreqs |= EfiAudioIoFreq11kHz;
if (SupportedRates & HDA_PARAMETER_SUPPORTED_PCM_SIZE_RATES_16KHZ)
HdaOutputPorts[i].SupportedFreqs |= EfiAudioIoFreq16kHz;
if (SupportedRates & HDA_PARAMETER_SUPPORTED_PCM_SIZE_RATES_22KHZ)
HdaOutputPorts[i].SupportedFreqs |= EfiAudioIoFreq22kHz;
if (SupportedRates & HDA_PARAMETER_SUPPORTED_PCM_SIZE_RATES_32KHZ)
HdaOutputPorts[i].SupportedFreqs |= EfiAudioIoFreq32kHz;
if (SupportedRates & HDA_PARAMETER_SUPPORTED_PCM_SIZE_RATES_44KHZ)
HdaOutputPorts[i].SupportedFreqs |= EfiAudioIoFreq44kHz;
if (SupportedRates & HDA_PARAMETER_SUPPORTED_PCM_SIZE_RATES_48KHZ)
HdaOutputPorts[i].SupportedFreqs |= EfiAudioIoFreq48kHz;
if (SupportedRates & HDA_PARAMETER_SUPPORTED_PCM_SIZE_RATES_88KHZ)
HdaOutputPorts[i].SupportedFreqs |= EfiAudioIoFreq88kHz;
if (SupportedRates & HDA_PARAMETER_SUPPORTED_PCM_SIZE_RATES_96KHZ)
HdaOutputPorts[i].SupportedFreqs |= EfiAudioIoFreq96kHz;
if (SupportedRates & HDA_PARAMETER_SUPPORTED_PCM_SIZE_RATES_192KHZ)
HdaOutputPorts[i].SupportedFreqs |= EfiAudioIoFreq192kHz;
}
// Ports gotten successfully.
*OutputPorts = HdaOutputPorts;
*OutputPortsCount = HdaCodecDev->OutputPortsCount;
return EFI_SUCCESS;
}
/**
Sets up the device to play audio data.
@param[in] This A pointer to the EFI_AUDIO_IO_PROTOCOL instance.
@param[in] OutputIndex The zero-based index of the desired output.
@param[in] Volume The volume (0-100) to use.
@param[in] Bits The width in bits of the source data.
@param[in] Freq The frequency of the source data.
@param[in] Channels The number of channels the source data contains.
@retval EFI_SUCCESS The audio data was played successfully.
@retval EFI_INVALID_PARAMETER One or more parameters are invalid.
**/
EFI_STATUS
EFIAPI
HdaCodecAudioIoSetupPlayback(
IN EFI_AUDIO_IO_PROTOCOL *This,
IN UINT8 OutputIndex,
IN UINT8 Volume,
IN EFI_AUDIO_IO_PROTOCOL_FREQ Freq,
IN EFI_AUDIO_IO_PROTOCOL_BITS Bits,
IN UINT8 Channels)
{
// DEBUG((DEBUG_INFO, "HdaCodecAudioIoSetupPlayback(): start\n"));
// Create variables.
EFI_STATUS Status;
AUDIO_IO_PRIVATE_DATA *AudioIoPrivateData;
HDA_CODEC_DEV *HdaCodecDev;
EFI_HDA_IO_PROTOCOL *HdaIo;
// Widgets.
HDA_WIDGET_DEV *PinWidget;
HDA_WIDGET_DEV *OutputWidget;
UINT32 SupportedRates;
UINT8 HdaStreamId;
// Stream.
UINT8 StreamBits, StreamDiv, StreamMult = 0;
BOOLEAN StreamBase44kHz = FALSE;
UINT16 StreamFmt;
// If a parameter is invalid, return error.
if ((This == NULL) || (Volume > EFI_AUDIO_IO_PROTOCOL_MAX_VOLUME))
return EFI_INVALID_PARAMETER;
// Get private data.
AudioIoPrivateData = AUDIO_IO_PRIVATE_DATA_FROM_THIS(This);
HdaCodecDev = AudioIoPrivateData->HdaCodecDev;
HdaIo = HdaCodecDev->HdaIo;
// Check that output index is within bounds and get our desired output.
if (OutputIndex >= HdaCodecDev->OutputPortsCount)
return EFI_INVALID_PARAMETER;
PinWidget = HdaCodecDev->OutputPorts[OutputIndex];
// Get the output DAC for the path.
Status = HdaCodecGetOutputDac(PinWidget, &OutputWidget);
if (EFI_ERROR(Status))
return Status;
// Get supported stream formats.
Status = HdaCodecGetSupportedPcmRates(OutputWidget, &SupportedRates);
if (EFI_ERROR(Status))
return Status;
// Determine bitness of samples, ensuring desired bitness is supported.
switch (Bits) {
// 8-bit.
case EfiAudioIoBits8:
if (!(SupportedRates & HDA_PARAMETER_SUPPORTED_PCM_SIZE_RATES_8BIT))
return EFI_UNSUPPORTED;
StreamBits = HDA_CONVERTER_FORMAT_BITS_8;
break;
// 16-bit.
case EfiAudioIoBits16:
if (!(SupportedRates & HDA_PARAMETER_SUPPORTED_PCM_SIZE_RATES_16BIT))
return EFI_UNSUPPORTED;
StreamBits = HDA_CONVERTER_FORMAT_BITS_16;
break;
// 20-bit.
case EfiAudioIoBits20:
if (!(SupportedRates & HDA_PARAMETER_SUPPORTED_PCM_SIZE_RATES_20BIT))
return EFI_UNSUPPORTED;
StreamBits = HDA_CONVERTER_FORMAT_BITS_20;
break;
// 24-bit.
case EfiAudioIoBits24:
if (!(SupportedRates & HDA_PARAMETER_SUPPORTED_PCM_SIZE_RATES_24BIT))
return EFI_UNSUPPORTED;
StreamBits = HDA_CONVERTER_FORMAT_BITS_24;
break;
// 32-bit.
case EfiAudioIoBits32:
if (!(SupportedRates & HDA_PARAMETER_SUPPORTED_PCM_SIZE_RATES_32BIT))
return EFI_UNSUPPORTED;
StreamBits = HDA_CONVERTER_FORMAT_BITS_32;
break;
// Others.
default:
return EFI_INVALID_PARAMETER;
}
// Determine base, divisor, and multipler.
switch (Freq) {
// 8 kHz.
case EfiAudioIoFreq8kHz:
if (!(SupportedRates & HDA_PARAMETER_SUPPORTED_PCM_SIZE_RATES_8KHZ))
return EFI_UNSUPPORTED;
StreamBase44kHz = FALSE;
StreamDiv = 6;
StreamMult = 1;
break;
// 11.025 kHz.
case EfiAudioIoFreq11kHz:
if (!(SupportedRates & HDA_PARAMETER_SUPPORTED_PCM_SIZE_RATES_11KHZ))
return EFI_UNSUPPORTED;
StreamBase44kHz = TRUE;
StreamDiv = 4;
StreamMult = 1;
break;
// 16 kHz.
case EfiAudioIoFreq16kHz:
if (!(SupportedRates & HDA_PARAMETER_SUPPORTED_PCM_SIZE_RATES_16KHZ))
return EFI_UNSUPPORTED;
StreamBase44kHz = FALSE;
StreamDiv = 3;
StreamMult = 1;
break;
// 22.05 kHz.
case EfiAudioIoFreq22kHz:
if (!(SupportedRates & HDA_PARAMETER_SUPPORTED_PCM_SIZE_RATES_22KHZ))
return EFI_UNSUPPORTED;
StreamBase44kHz = TRUE;
StreamDiv = 2;
StreamMult = 1;
break;
// 32 kHz.
case EfiAudioIoFreq32kHz:
if (!(SupportedRates & HDA_PARAMETER_SUPPORTED_PCM_SIZE_RATES_32KHZ))
return EFI_UNSUPPORTED;
StreamBase44kHz = FALSE;
StreamDiv = 3;
StreamMult = 2;
break;
// 44.1 kHz.
case EfiAudioIoFreq44kHz:
if (!(SupportedRates & HDA_PARAMETER_SUPPORTED_PCM_SIZE_RATES_44KHZ))
return EFI_UNSUPPORTED;
StreamBase44kHz = TRUE;
StreamDiv = 1;
StreamMult = 1;
break;
// 48 kHz.
case EfiAudioIoFreq48kHz:
if (!(SupportedRates & HDA_PARAMETER_SUPPORTED_PCM_SIZE_RATES_48KHZ))
return EFI_UNSUPPORTED;
StreamBase44kHz = FALSE;
StreamDiv = 1;
StreamMult = 1;
break;
// 88 kHz.
case EfiAudioIoFreq88kHz:
if (!(SupportedRates & HDA_PARAMETER_SUPPORTED_PCM_SIZE_RATES_88KHZ))
return EFI_UNSUPPORTED;
StreamBase44kHz = TRUE;
StreamDiv = 1;
StreamMult = 2;
break;
// 96 kHz.
case EfiAudioIoFreq96kHz:
if (!(SupportedRates & HDA_PARAMETER_SUPPORTED_PCM_SIZE_RATES_96KHZ))
return EFI_UNSUPPORTED;
StreamBase44kHz = FALSE;
StreamDiv = 1;
StreamMult = 2;
break;
// 192 kHz.
case EfiAudioIoFreq192kHz:
if (!(SupportedRates & HDA_PARAMETER_SUPPORTED_PCM_SIZE_RATES_192KHZ))
return EFI_UNSUPPORTED;
StreamBase44kHz = FALSE;
StreamDiv = 1;
StreamMult = 4;
break;
// Others.
default:
return EFI_INVALID_PARAMETER;
}
// Disable all widget paths.
for (UINTN w = 0; w < HdaCodecDev->OutputPortsCount; w++) {
if (w == OutputIndex)
continue;
Status = HdaCodecDisableWidgetPath(HdaCodecDev->OutputPorts[w]);
if (EFI_ERROR(Status))
return Status;
}
// Close stream first.
Status = HdaIo->CloseStream(HdaIo, EfiHdaIoTypeOutput);
if (EFI_ERROR(Status))
return Status;
// Calculate stream format and setup stream.
StreamFmt = HDA_CONVERTER_FORMAT_SET(Channels - 1, StreamBits,
StreamDiv - 1, StreamMult - 1, StreamBase44kHz);
DEBUG((DEBUG_INFO, "HdaCodecAudioIoPlay(): Stream format 0x%X\n", StreamFmt));
Status = HdaIo->SetupStream(HdaIo, EfiHdaIoTypeOutput, StreamFmt, &HdaStreamId);
if (EFI_ERROR(Status))
return Status;
// Setup widget path for desired output.
AudioIoPrivateData->SelectedOutputIndex = OutputIndex;
Status = HdaCodecEnableWidgetPath(PinWidget, Volume, HdaStreamId, StreamFmt);
if (EFI_ERROR(Status))
goto CLOSE_STREAM;
return EFI_SUCCESS;
CLOSE_STREAM:
// Close stream.
HdaIo->CloseStream(HdaIo, EfiHdaIoTypeOutput);
return Status;
}
/**
Begins playback on the device and waits for playback to complete.
@param[in] This A pointer to the EFI_AUDIO_IO_PROTOCOL instance.
@param[in] Data A pointer to the buffer containing the audio data to play.
@param[in] DataLength The size, in bytes, of the data buffer specified by Data.
@param[in] Position The position in the buffer to start at.
@retval EFI_SUCCESS The audio data was played successfully.
@retval EFI_INVALID_PARAMETER One or more parameters are invalid.
**/
EFI_STATUS
EFIAPI
HdaCodecAudioIoStartPlayback(
IN EFI_AUDIO_IO_PROTOCOL *This,
IN VOID *Data,
IN UINTN DataLength,
IN UINTN Position OPTIONAL)
{
// DEBUG((DEBUG_INFO, "HdaCodecAudioIoStartPlayback(): start\n"));
// Create variables.
EFI_STATUS Status;
AUDIO_IO_PRIVATE_DATA *AudioIoPrivateData;
EFI_HDA_IO_PROTOCOL *HdaIo;
BOOLEAN StreamRunning = FALSE;
// If a parameter is invalid, return error.
if ((This == NULL) || (Data == NULL) || (DataLength == 0))
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;
// Start stream.
Status = HdaIo->StartStream(HdaIo, EfiHdaIoTypeOutput, Data, DataLength, Position,
NULL, NULL, NULL, NULL);
if (EFI_ERROR(Status))
return Status;
// Wait for stream to stop.
StreamRunning = TRUE;
while (StreamRunning) {
Status = HdaIo->GetStream(HdaIo, EfiHdaIoTypeOutput, &StreamRunning);
if (EFI_ERROR(Status)) {
HdaIo->StopStream(HdaIo, EfiHdaIoTypeOutput);
return Status;
}
// Wait 100ms.
gBS->Stall(MS_TO_MICROSECOND(100));
}
return EFI_SUCCESS;
}
/**
Begins playback on the device asynchronously.
@param[in] This A pointer to the EFI_AUDIO_IO_PROTOCOL instance.
@param[in] Data A pointer to the buffer containing the audio data to play.
@param[in] DataLength The size, in bytes, of the data buffer specified by Data.
@param[in] Position The position in the buffer to start at.
@param[in] Callback A pointer to an optional callback to be invoked when playback is complete.
@param[in] Context A pointer to data to be passed to the callback function.
@retval EFI_SUCCESS The audio data was played successfully.
@retval EFI_INVALID_PARAMETER One or more parameters are invalid.
**/
EFI_STATUS
EFIAPI
HdaCodecAudioIoStartPlaybackAsync(
IN EFI_AUDIO_IO_PROTOCOL *This,
IN VOID *Data,
IN UINTN DataLength,
IN UINTN Position OPTIONAL,
IN EFI_AUDIO_IO_CALLBACK Callback OPTIONAL,
IN VOID *Context OPTIONAL)
{
// DEBUG((DEBUG_INFO, "HdaCodecAudioIoStartPlaybackAsync(): start\n"));
// Create variables.
EFI_STATUS Status;
AUDIO_IO_PRIVATE_DATA *AudioIoPrivateData;
EFI_HDA_IO_PROTOCOL *HdaIo;
// If a parameter is invalid, return error.
if ((This == NULL) || (Data == NULL) || (DataLength == 0))
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;
// Start stream.
// Status = HdaIo->StartStream(HdaIo, EfiHdaIoTypeOutput, Data, DataLength, Position,
// (VOID*)HdaCodecHdaIoStreamCallback, (VOID*)This, (VOID*)Callback, Context);
Status = HdaIo->StartStream(HdaIo, EfiHdaIoTypeOutput, Data, DataLength, Position,
NULL, (VOID*)This, NULL, Context);
return Status;
}
/**
Stops playback on the device.
@param[in] This A pointer to the EFI_AUDIO_IO_PROTOCOL instance.
@retval EFI_SUCCESS The audio data was played successfully.
@retval EFI_INVALID_PARAMETER One or more parameters are invalid.
**/
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);
if (!AudioIoPrivateData || !AudioIoPrivateData->HdaCodecDev || !AudioIoPrivateData->HdaCodecDev->HdaIo) {
return EFI_NOT_FOUND;
}
HdaIo = AudioIoPrivateData->HdaCodecDev->HdaIo;
// Stop stream.
return HdaIo->StopStream(HdaIo, EfiHdaIoTypeOutput);
}