/** @file This DXE driver configures Sndw controllers, performs codecs enumeration process, allows to send/receive messages to/from them. @copyright INTEL CONFIDENTIAL Copyright 2020 - 2021 Intel Corporation. The source code contained or described herein and all documents related to the source code ("Material") are owned by Intel Corporation or its suppliers or licensors. Title to the Material remains with Intel Corporation or its suppliers and licensors. The Material may contain trade secrets and proprietary and confidential information of Intel Corporation and its suppliers and licensors, and is protected by worldwide copyright and trade secret laws and treaty provisions. No part of the Material may be used, copied, reproduced, modified, published, uploaded, posted, transmitted, distributed, or disclosed in any way without Intel's prior express written permission. No license under any patent, copyright, trade secret or other intellectual property right is granted to or conferred upon you by disclosure or delivery of the Materials, either expressly, by implication, inducement, estoppel or otherwise. Any license under such intellectual property rights must be express and approved by Intel in writing. Unless otherwise agreed by Intel in writing, you may not remove or alter this notice or any other notice embedded in Materials by Intel or Intel's suppliers or licensors in any way. This file contains a 'Sample Driver' and is licensed as such under the terms of your license agreement with Intel or your vendor. This file may be modified by the user, subject to the additional terms of the license agreement. @par Specification Reference: **/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define SNDW_ACCESS_SIGNATURE SIGNATURE_32 ('s', 'd', 'w', 'a') GLOBAL_REMOVE_IF_UNREFERENCED SNDW_COMMAND MipiSndwPeripheralInitCmds = { .TxWrite = { .OpCode = SndwCmdWrite, .RegAddr = 0x0049, .RegData = 0x01, } }; typedef struct { LIST_ENTRY ListEntry; SNDW_CODEC_INFO CodecInfo; UINTN SndwControllerMmioOffset; UINT32 PeripheralIndex; } CODEC_LIST_ENTRY; #define CODEC_LIST_ENTRY_FROM_LIST_ENTRY(a) BASE_CR (a, CODEC_LIST_ENTRY, ListEntry) typedef struct { UINTN Signature; SNDW_ACCESS_PROTOCOL SndwAccessProtocol; CODEC_LIST_ENTRY *CodecListHead; UINTN EnableCounter; } SNDW_ACCESS_CONTEXT; #define SNDW_ACCESS_CONTEXT_FROM_SNDW_ACCESS_PROTOCOL(a) CR (a, SNDW_ACCESS_CONTEXT, SndwAccessProtocol, SNDW_ACCESS_SIGNATURE) EFI_STATUS EnableHdaDspMmioAccess ( IN OUT UINT64 *HdaBar, IN OUT UINT64 *DspBar, OUT BOOLEAN *IsTemporaryBar ) { UINT64 HdaPciBase; *IsTemporaryBar = FALSE; HdaPciBase = PCI_SEGMENT_LIB_ADDRESS ( DEFAULT_PCI_SEGMENT_NUMBER_PCH, DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_HDA, PCI_FUNCTION_NUMBER_PCH_HDA, 0 ); if (PciSegmentRead16 (HdaPciBase + PCI_DEVICE_ID_OFFSET) == 0xFFFF) { DEBUG ((DEBUG_WARN, "HDA is not enabled in this phase.\n")); return EFI_UNSUPPORTED; } *HdaBar = (UINT64) PciSegmentRead32 (HdaPciBase + R_HDA_CFG_HDALBA); if ((*HdaBar & B_PCI_BAR_MEMORY_TYPE_MASK) == B_PCI_BAR_MEMORY_TYPE_64) { *HdaBar |= LShiftU64 ((UINT64) PciSegmentRead32 (HdaPciBase + R_HDA_CFG_HDAUBA), 32); } *HdaBar &= ~((UINT64) (0xFFFFF)); *DspBar = (UINT64) PciSegmentRead32 (HdaPciBase + R_HDA_CFG_ADSPLBA); if ((*DspBar & B_PCI_BAR_MEMORY_TYPE_MASK) == B_PCI_BAR_MEMORY_TYPE_64) { *DspBar |= LShiftU64 ((UINT64) PciSegmentRead32 (HdaPciBase + R_HDA_CFG_ADSPUBA), 32); } *DspBar &= ~((UINT64) (0xFFFFF)); if (*HdaBar == 0 || *DspBar == 0) { DEBUG ((DEBUG_WARN, "DSP Bar isn't programmed in this phase, set HDA and DSP bars to temporary value.\n")); *HdaBar = (UINT64) PcdGet32 (PcdSiliconInitTempMemBaseAddr); *DspBar = (UINT64) PcdGet32 (PcdSiliconInitTempMemBaseAddr) + (UINT64) V_HDA_CFG_HDABAR_SIZE; PciSegmentWrite32 (HdaPciBase + R_HDA_CFG_HDALBA, (UINT32) *HdaBar); PciSegmentWrite32 (HdaPciBase + R_HDA_CFG_HDAUBA, 0); PciSegmentWrite32 (HdaPciBase + R_HDA_CFG_ADSPLBA, (UINT32) *DspBar); PciSegmentWrite32 (HdaPciBase + R_HDA_CFG_ADSPUBA, 0); *IsTemporaryBar = TRUE; } // // Enable memory map access // PciSegmentOr16 (HdaPciBase + PCI_COMMAND_OFFSET, (UINT16) EFI_PCI_COMMAND_MEMORY_SPACE); return EFI_SUCCESS; } VOID DisableHdaDspMmioAccess ( IN BOOLEAN IsTemporaryBar ) { UINTN HdaPciBase; HdaPciBase = PCI_SEGMENT_LIB_ADDRESS ( DEFAULT_PCI_SEGMENT_NUMBER_PCH, DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_HDA, PCI_FUNCTION_NUMBER_PCH_HDA, 0 ); // // Disable memory map access // PciSegmentAnd16 (HdaPciBase + PCI_COMMAND_OFFSET, (UINT16) (~EFI_PCI_COMMAND_MEMORY_SPACE)); // // Clear DSP and HDA BARs // if (IsTemporaryBar == TRUE) { PciSegmentWrite32 (HdaPciBase + R_HDA_CFG_HDALBA, 0); PciSegmentWrite32 (HdaPciBase + R_HDA_CFG_HDAUBA, 0); PciSegmentWrite32 (HdaPciBase + R_HDA_CFG_ADSPLBA, 0); PciSegmentWrite32 (HdaPciBase + R_HDA_CFG_ADSPUBA, 0); } } EFI_STATUS GetCodecAddressFromCodecInfo ( IN SNDW_ACCESS_CONTEXT *SndwAccessContext, IN SNDW_CODEC_INFO *SndwCodecInfo, IN OUT UINT32 *PeripheralIndex, IN OUT UINTN *SndwControllerMmioOffset ) { CODEC_LIST_ENTRY *CurrentSndwListEntry; LIST_ENTRY *ListEntryHead; LIST_ENTRY *CurrentListEntry; *SndwControllerMmioOffset = 0; *PeripheralIndex = 0; CurrentSndwListEntry = SndwAccessContext->CodecListHead; CurrentListEntry = &(CurrentSndwListEntry->ListEntry); ListEntryHead = CurrentListEntry; while (CurrentListEntry != NULL) { CurrentSndwListEntry = CODEC_LIST_ENTRY_FROM_LIST_ENTRY (CurrentListEntry); if ((CurrentSndwListEntry->CodecInfo.SndwLinkIndex == SndwCodecInfo->SndwLinkIndex) && (CompareMem (CurrentSndwListEntry->CodecInfo.CodecId.Data, SndwCodecInfo->CodecId.Data, sizeof (SNDW_CODEC_ID)) == 0)) { *PeripheralIndex = CurrentSndwListEntry->PeripheralIndex; *SndwControllerMmioOffset = CurrentSndwListEntry->SndwControllerMmioOffset; DEBUG ((DEBUG_INFO, "Codec Found - PeripheralIndex: 0x%x, SndwControllerMmioOffset: 0x%x\n", *PeripheralIndex, *SndwControllerMmioOffset)); return EFI_SUCCESS; } CurrentListEntry = GetNextNode (ListEntryHead, CurrentListEntry); if (CurrentListEntry == ListEntryHead) { return EFI_NOT_FOUND; } } return EFI_NOT_FOUND; } /** Function operating on Sndw Fifo buffer for sending messages to codecs. @param[in] This Pointer to Sndw Access Protocol @param[in] SndwCodecInfo Sndw codec information @param[in] TxCommands Pointer to send messages @param[in] TxSize Size of messages to send @retval EFI_SUCCESS Message sent successfully @retval EFI_NOT_FOUND Given codec not found **/ EFI_STATUS EFIAPI DxeSndwSend ( IN CONST SNDW_ACCESS_PROTOCOL *This, IN SNDW_CODEC_INFO SndwCodecInfo, IN SNDW_COMMAND *TxCommand, IN UINTN TxSize ) { EFI_STATUS Status; SNDW_ACCESS_CONTEXT *SndwAccessContext; UINTN SndwControllerMmioOffset; UINTN Index; UINT64 HdaBar; UINT64 DspBar; UINT32 PeripheralIndex; BOOLEAN IsTemporaryBar; DEBUG ((DEBUG_INFO, "%a () - Start.\n", __FUNCTION__)); if (This == NULL) { DEBUG ((DEBUG_ERROR, "Sndw Access protocol has not been passed, aborting.\n")); return EFI_INVALID_PARAMETER; } EnableHdaDspMmioAccess (&HdaBar, &DspBar, &IsTemporaryBar); SndwAccessContext = SNDW_ACCESS_CONTEXT_FROM_SNDW_ACCESS_PROTOCOL (This); Status = GetCodecAddressFromCodecInfo (SndwAccessContext, &SndwCodecInfo, &PeripheralIndex, &SndwControllerMmioOffset); if (EFI_ERROR (Status)) { DisableHdaDspMmioAccess (IsTemporaryBar); DEBUG ((DEBUG_INFO, "%a () - End. Status = %r\n", __FUNCTION__, Status)); return EFI_NOT_FOUND; } for (Index = 0; Index < TxSize; Index++) { TxCommand[Index].TxWrite.DeviceAddress = PeripheralIndex; } Send (DspBar + SndwControllerMmioOffset, TxCommand, TxSize); DisableHdaDspMmioAccess (IsTemporaryBar); DEBUG ((DEBUG_INFO, "%a () - End.\n", __FUNCTION__)); return EFI_SUCCESS; } /** Function sends one message through the Sndw interface and waits for the corresponding ACK message. @param[in] This Pointer to Sndw Access Protocol @param[in] SndwCodecInfo Sndw codec information @param[in] TxCommands Pointer to sending message @param[out] RxCommands Pointer to receiving message @retval EFI_SUCCESS The function completed successfully @retval EFI_NOT_FOUND Given codec not found @retval EFI_TIMEOUT Sending command has failed @retval EFI_DEVICE_ERROR Response command has failed **/ EFI_STATUS EFIAPI DxeSndwSendWithAck ( IN CONST SNDW_ACCESS_PROTOCOL *This, IN SNDW_CODEC_INFO SndwCodecInfo, IN SNDW_COMMAND TxCommand, OUT SNDW_COMMAND* RxCommand OPTIONAL ) { EFI_STATUS Status; SNDW_ACCESS_CONTEXT *SndwAccessContext; UINTN SndwControllerMmioOffset; UINT64 HdaBar; UINT64 DspBar; UINT32 PeripheralIndex; BOOLEAN IsTemporaryBar; DEBUG ((DEBUG_INFO, "%a () - Start.\n", __FUNCTION__)); if (This == NULL) { DEBUG ((DEBUG_ERROR, "Sndw Access protocol has not been passed, aborting.\n")); return EFI_INVALID_PARAMETER; } EnableHdaDspMmioAccess (&HdaBar, &DspBar, &IsTemporaryBar); SndwAccessContext = SNDW_ACCESS_CONTEXT_FROM_SNDW_ACCESS_PROTOCOL (This); Status = GetCodecAddressFromCodecInfo (SndwAccessContext, &SndwCodecInfo, &PeripheralIndex, &SndwControllerMmioOffset); if (EFI_ERROR (Status)) { DisableHdaDspMmioAccess (IsTemporaryBar); DEBUG ((DEBUG_INFO, "%a () - End. Status = %r\n", __FUNCTION__, Status)); return EFI_NOT_FOUND; } DEBUG ((DEBUG_INFO, "PeripheralIndex: %d\n", PeripheralIndex)); DEBUG ((DEBUG_INFO, "Sndw%d: Controller mmio address: 0x%X.\n", SndwCodecInfo.SndwLinkIndex, DspBar + SndwControllerMmioOffset)); TxCommand.TxWrite.DeviceAddress = PeripheralIndex; SendwAck (DspBar + SndwControllerMmioOffset, TxCommand, RxCommand); DisableHdaDspMmioAccess (IsTemporaryBar); DEBUG ((DEBUG_INFO, "%a () - End.\n", __FUNCTION__)); return EFI_SUCCESS; } /** Function operating on Sndw Fifo for receiving messages from codecs. @param[in] This Pointer to Sndw Access Protocol @param[in] SndwCodecInfo Sndw codec information @param[out] RxCommands Pointer to pointer to received messages. Memory pool is allocated in this function, but the caller is responsible for freeing the memory with FreePool. @param[out] RxSize Size of received messages @retval EFI_SUCCESS Message received successfully @retval EFI_NOT_FOUND Given codec not found @retval EFI_OUT_OF_RESOURCES Memory allocation for response failed **/ EFI_STATUS EFIAPI DxeSndwReceive ( IN CONST SNDW_ACCESS_PROTOCOL *This, IN SNDW_CODEC_INFO SndwCodecInfo, OUT SNDW_COMMAND **RxCommands, OUT UINTN* RxSize ) { EFI_STATUS Status; SNDW_ACCESS_CONTEXT *SndwAccessContext; UINTN SndwControllerMmioOffset; UINT64 HdaBar; UINT64 DspBar; BOOLEAN IsTemporaryBar; DEBUG ((DEBUG_INFO, "%a () - Start.\n", __FUNCTION__)); if (This == NULL) { DEBUG ((DEBUG_ERROR, "Sndw Access protocol has not been passed, aborting.\n")); return EFI_INVALID_PARAMETER; } EnableHdaDspMmioAccess (&HdaBar, &DspBar, &IsTemporaryBar); SndwAccessContext = SNDW_ACCESS_CONTEXT_FROM_SNDW_ACCESS_PROTOCOL (This); Status = GetCodecAddressFromCodecInfo (SndwAccessContext, &SndwCodecInfo, NULL, &SndwControllerMmioOffset); if (EFI_ERROR (Status)) { DisableHdaDspMmioAccess (IsTemporaryBar); DEBUG ((DEBUG_INFO, "%a () - End. Status = %r\n", __FUNCTION__, Status)); return EFI_NOT_FOUND; } Receive (DspBar + SndwControllerMmioOffset, RxCommands, RxSize); DisableHdaDspMmioAccess (IsTemporaryBar); if (*RxCommands == NULL) { return EFI_OUT_OF_RESOURCES; } DEBUG ((DEBUG_INFO, "%a () - End.\n", __FUNCTION__)); return EFI_SUCCESS; } /** Function disables Soundwire interface @param[in] This Pointer to Sndw Access Protocol @retval EFI_SUCCESS @retval EFI_DEVICE_ERROR **/ EFI_STATUS EFIAPI DxeSndwAccessDisable ( IN CONST SNDW_ACCESS_PROTOCOL *This ) { SNDW_ACCESS_CONTEXT *SndwAccessContext; UINT64 HdaBar; UINT64 DspBar; BOOLEAN IsTemporaryBar; if (This == NULL) { DEBUG ((DEBUG_ERROR, "Sndw Access protocol has not been passed, aborting.\n")); return EFI_INVALID_PARAMETER; } SndwAccessContext = SNDW_ACCESS_CONTEXT_FROM_SNDW_ACCESS_PROTOCOL (This); if (SndwAccessContext->EnableCounter <= 0) { DEBUG ((DEBUG_ERROR, "SndwAccess already disabled.\n")); return EFI_SUCCESS; } SndwAccessContext->EnableCounter -= 1; if (SndwAccessContext->EnableCounter > 0) { DEBUG ((DEBUG_ERROR, "SndwAccess still being used.\n")); return EFI_SUCCESS; } EnableHdaDspMmioAccess (&HdaBar, &DspBar, &IsTemporaryBar); ResetDsp (DspBar); DisableHdaDspMmioAccess (IsTemporaryBar); return EFI_SUCCESS; } /** Function initializes Soundwire controllers @param[in, out] NumberOfSupportedSndwLinks Pointer to number of supported Sndw links @param[in] HdaBar HDA base address @param[in] DspBar DSP base address @retval EFI_SUCCESS @retval EFI_DEVICE_ERROR **/ EFI_STATUS InitializeSndwControllers ( IN OUT UINTN *NumberOfSupportedSndwLinks, IN UINT64 HdaBar, IN UINT64 DspBar ) { EFI_STATUS Status; UINT64 SndwControllerMmioOffset; UINT32 SndwLinkIndex; Status = GetDspOutOfReset (HdaBar, DspBar); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_INFO, "%a () - End. Status = %r\n", __FUNCTION__, Status)); return EFI_DEVICE_ERROR; } /// /// Read number of supported links /// Status = GetNumberOfSupportedSndwLinks (DspBar, NumberOfSupportedSndwLinks); DEBUG ((DEBUG_INFO, "Number of Supported Sndw Links %d\n", *NumberOfSupportedSndwLinks)); for (SndwLinkIndex = 0; SndwLinkIndex < *NumberOfSupportedSndwLinks; SndwLinkIndex++) { Status = GetSndwLinkOutOfReset (DspBar, SndwLinkIndex); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_INFO, "%a () - End. Status = %r\n", __FUNCTION__, Status)); return EFI_DEVICE_ERROR; } SetSndwShimRegisters (DspBar, SndwLinkIndex); /// /// Read address of SndwX controller /// GetLinkControllerMmioAddress (DspBar, SndwLinkIndex, &SndwControllerMmioOffset); DEBUG ((DEBUG_INFO, "Sndw%d: Controller mmio address: 0x%X.\n", SndwLinkIndex+1, DspBar + SndwControllerMmioOffset)); /// /// Check access to SndwX controller /// if (SndwIoAccessReady (DspBar + SndwControllerMmioOffset) == FALSE) { DEBUG ((DEBUG_INFO, "No access to Sndw%d Controller registers! Aborting", SndwLinkIndex+1)); return EFI_DEVICE_ERROR; } /// /// Initialize SndwX controller /// Status = SndwControllerInit (DspBar + SndwControllerMmioOffset); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_INFO, "%a () - End. Status = %r\n", __FUNCTION__, Status)); return EFI_DEVICE_ERROR; } } return EFI_SUCCESS; } /** Function enumerates connected Soundwire codecs @param[in] SndwAccessContext Pointer to Sndw access context @param[in] NumberOfSupportedSndwLinks Number of supported Sndw links @param[in] DspBar DSP base address @retval EFI_SUCCESS @retval EFI_DEVICE_ERROR **/ EFI_STATUS EnumerateSndwCodecs ( IN SNDW_ACCESS_CONTEXT *SndwAccessContext, IN UINTN NumberOfSupportedSndwLinks, IN UINT64 DspBar ) { EFI_STATUS Status; CODEC_LIST_ENTRY *CodecListEntry; SNDW_CODEC_ID CodecId; SNDW_COMMAND RxCommand; LIST_ENTRY *CodecListHead; UINT64 SndwControllerMmioOffset; UINT32 SndwLinkIndex; UINT32 PeripheralIndex; UINT32 PeripheralsStatus; CodecListHead = NULL; /// /// Controller after initialization sending ping message automatically /// MicroSecondDelay (SNDW_WAIT_PERIOD * 100); for (SndwLinkIndex = 0; SndwLinkIndex < NumberOfSupportedSndwLinks; SndwLinkIndex++) { // // Read address of SndwX controller // Status = GetLinkControllerMmioAddress (DspBar, SndwLinkIndex, &SndwControllerMmioOffset); if (EFI_ERROR (Status)) { continue; } DEBUG ((DEBUG_INFO, "Sndw%d controller mmio address: 0x%X.\n", SndwLinkIndex+1, DspBar + SndwControllerMmioOffset)); /// /// Now we are ready to send data to codecs /// for (PeripheralIndex = 0; PeripheralIndex < SNDW_MAX_PERIPHERAL_NUMBER; PeripheralIndex++) { /// /// Codecs enumeration process, check peripherals status /// Status = SndwReadCodecsStatus (DspBar + SndwControllerMmioOffset, &PeripheralsStatus); if (EFI_ERROR (Status)) { continue; } DEBUG ((DEBUG_INFO, "Sndw%d peripheral status: 0x%X.\n", SndwLinkIndex+1, PeripheralsStatus)); if ((PeripheralsStatus & B_SNDW_MEM_PERIPHERALSTAT_STATUS (PeripheralIndex)) == SndwPeripheralAttachedOk) { DEBUG ((DEBUG_INFO, "Peripheral number: %d attached correctly.\n", PeripheralIndex)); /// /// Waiting a few ms after sending init msg /// MicroSecondDelay (SNDW_WAIT_PERIOD * 100); /// /// Read if Codec is connected to PeripheralIndex /// Status = ReadPeripheralId (DspBar + SndwControllerMmioOffset, PeripheralIndex, &CodecId); if (EFI_ERROR (Status)) { return EFI_DEVICE_ERROR; } /// /// Waiting a few ms after sending init msg /// MicroSecondDelay (SNDW_WAIT_PERIOD * 100); /// /// Send Init commands to codecs /// MipiSndwPeripheralInitCmds.TxWrite.DeviceAddress = PeripheralIndex; Status = SendwAck (DspBar + SndwControllerMmioOffset, MipiSndwPeripheralInitCmds, &RxCommand); if (EFI_ERROR (Status) || (RxCommand.Rx.Ack == 0)) { DEBUG ((DEBUG_INFO, "Sndw%d controller - Peripheral number: %d initialization failed.\n", SndwLinkIndex+1, PeripheralIndex)); continue; } CodecListEntry = AllocatePool (sizeof (CODEC_LIST_ENTRY)); if (CodecListEntry == NULL) { return EFI_OUT_OF_RESOURCES; } CodecListEntry->CodecInfo.SndwLinkIndex = SndwLinkIndex; CodecListEntry->PeripheralIndex = PeripheralIndex; CodecListEntry->SndwControllerMmioOffset = SndwControllerMmioOffset; CopyMem (CodecListEntry->CodecInfo.CodecId.Data, CodecId.Data, sizeof (SNDW_CODEC_ID)); PrintCodecInfo (&(CodecListEntry->CodecInfo)); if (CodecListHead == NULL) { SndwAccessContext->CodecListHead = CodecListEntry; CodecListHead = &(CodecListEntry->ListEntry); InitializeListHead (CodecListHead); } else { InsertTailList (CodecListHead, &(CodecListEntry->ListEntry)); } } } } return EFI_SUCCESS; } /** Function enables Soundwire interface and enumerates attached codecs @param[in] This Pointer to Sndw Access Protocol @retval EFI_SUCCESS @retval EFI_DEVICE_ERROR **/ EFI_STATUS EFIAPI DxeSndwAccessEnable ( IN CONST SNDW_ACCESS_PROTOCOL *This ) { EFI_STATUS Status; SNDW_ACCESS_CONTEXT *SndwAccessContext; UINTN NumberOfSupportedSndwLinks; UINT64 HdaBar; UINT64 DspBar; BOOLEAN IsTemporaryBar; DEBUG ((DEBUG_INFO, "%a () - Start.\n", __FUNCTION__)); if (This == NULL) { DEBUG ((DEBUG_ERROR, "Sndw Access protocol has not been passed, aborting.\n")); return EFI_INVALID_PARAMETER; } SndwAccessContext = SNDW_ACCESS_CONTEXT_FROM_SNDW_ACCESS_PROTOCOL (This); SndwAccessContext->EnableCounter += 1; if (SndwAccessContext->EnableCounter != 1) { DEBUG ((DEBUG_ERROR, "SndwAccess already enabled.\n")); return EFI_SUCCESS; } EnableHdaDspMmioAccess (&HdaBar, &DspBar, &IsTemporaryBar); Status = InitializeSndwControllers (&NumberOfSupportedSndwLinks, HdaBar, DspBar); if (Status == EFI_SUCCESS) { Status = EnumerateSndwCodecs (SndwAccessContext, NumberOfSupportedSndwLinks, DspBar); } DisableHdaDspMmioAccess (IsTemporaryBar); DEBUG ((DEBUG_INFO, "%a () - End. Status = %r.\n", __FUNCTION__, Status)); return Status; } /** Function return first codec saved in codecs list. If it does not exist, function sets *CodecInfo to NULL. @param[in] This Pointer to Sndw Access Protocol @param[out] SndwCodecInfo Pointer to pointer to Sndw codec information structure. The caller is responsible for freeing the memory. @retval EFI_SUCCESS Codec found @retval EFI_NOT_FOUND Codec not found @retval EFI_OUT_OF_RESOURCES Memory allocation for codec info failed **/ EFI_STATUS EFIAPI DxeSndwGetFirstCodec ( IN CONST SNDW_ACCESS_PROTOCOL *This, OUT SNDW_CODEC_INFO **SndwCodecInfo ) { SNDW_ACCESS_CONTEXT *SndwAccessContext; CODEC_LIST_ENTRY *CurrentCodecListEntry; if (This == NULL) { DEBUG ((DEBUG_ERROR, "Sndw Access protocol has not been passed, aborting.\n")); return EFI_INVALID_PARAMETER; } SndwAccessContext = SNDW_ACCESS_CONTEXT_FROM_SNDW_ACCESS_PROTOCOL (This); CurrentCodecListEntry = SndwAccessContext->CodecListHead; if (CurrentCodecListEntry != NULL) { *SndwCodecInfo = AllocatePool (sizeof (SNDW_CODEC_INFO)); if (*SndwCodecInfo == NULL) { DEBUG ((DEBUG_INFO, "Couldn't allocate the memory for Sndw Codec Info!\n")); return EFI_OUT_OF_RESOURCES; } (*SndwCodecInfo)->SndwLinkIndex = CurrentCodecListEntry->CodecInfo.SndwLinkIndex; CopyMem (&((*SndwCodecInfo)->CodecId.Data), &(CurrentCodecListEntry->CodecInfo.CodecId.Data), sizeof (SNDW_CODEC_ID)); } else { *SndwCodecInfo = NULL; return EFI_NOT_FOUND; } return EFI_SUCCESS; } /** Function retrieves the next codec saved in codecs list that follows the given one. If it does not exist, function sets *NextCodecInfo to NULL. @param[in] This Pointer to Sndw Access Protocol @param[in] SndwCodecInfo Pointer to Sndw codec information structure. @param[out] NextCodecInfo Pointer to pointer to Sndw codec information structure. The caller is responsible for freeing the memory. @retval EFI_SUCCESS Codec found @retval EFI_NOT_FOUND Codec not found @retval EFI_OUT_OF_RESOURCES Memory allocation for codec info failed **/ EFI_STATUS EFIAPI DxeSndwGetNextCodec ( IN CONST SNDW_ACCESS_PROTOCOL *This, IN SNDW_CODEC_INFO *SndwCodecInfo, OUT SNDW_CODEC_INFO **NextSndwCodecInfo ) { SNDW_ACCESS_CONTEXT *SndwAccessContext; CODEC_LIST_ENTRY *CurrentCodecListEntry; LIST_ENTRY *ListHead; LIST_ENTRY *CurrentListEntry; if (This == NULL) { DEBUG ((DEBUG_ERROR, "Sndw Access protocol has not been passed, aborting.\n")); return EFI_INVALID_PARAMETER; } SndwAccessContext = SNDW_ACCESS_CONTEXT_FROM_SNDW_ACCESS_PROTOCOL (This); ListHead = &(SndwAccessContext->CodecListHead->ListEntry); CurrentListEntry = ListHead; while (TRUE) { CurrentCodecListEntry = CODEC_LIST_ENTRY_FROM_LIST_ENTRY (CurrentListEntry); if ((CurrentCodecListEntry->CodecInfo.SndwLinkIndex == SndwCodecInfo->SndwLinkIndex) && (CompareMem (CurrentCodecListEntry->CodecInfo.CodecId.Data, SndwCodecInfo->CodecId.Data, sizeof (SNDW_CODEC_ID)) == 0)) { CurrentListEntry = GetNextNode (ListHead, CurrentListEntry); if (CurrentListEntry == ListHead) { *NextSndwCodecInfo = NULL; return EFI_NOT_FOUND; } CurrentCodecListEntry = CODEC_LIST_ENTRY_FROM_LIST_ENTRY (CurrentListEntry); *NextSndwCodecInfo = AllocatePool (sizeof (SNDW_CODEC_INFO)); if (*NextSndwCodecInfo == NULL) { DEBUG ((DEBUG_INFO, "Couldn't allocate the memory for Sndw Codec Info!\n")); return EFI_OUT_OF_RESOURCES; } (*NextSndwCodecInfo)->SndwLinkIndex = CurrentCodecListEntry->CodecInfo.SndwLinkIndex; CopyMem (&((*NextSndwCodecInfo)->CodecId.Data), &(CurrentCodecListEntry->CodecInfo.CodecId.Data), sizeof (SNDW_CODEC_ID)); break; } CurrentListEntry = GetNextNode (ListHead, CurrentListEntry); if (CurrentListEntry == ListHead) { *NextSndwCodecInfo = NULL; return EFI_NOT_FOUND; } } return EFI_SUCCESS; } /** This function is the entry point of this DXE Sndw Init Driver. @param ImageHandle The firmware allocated handle for the EFI image. @param SystemTable A pointer to the EFI System Table. @retval EFI_SUCCESS The function completed successfully. @retval EFI_DEVICE_ERROR Not able to enable DSP memory space. @retval EFI_UNSUPPORTED Requested Sndw link not exists. **/ EFI_STATUS EFIAPI DxeSndwInitEntryPoint ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { EFI_STATUS Status; SNDW_ACCESS_CONTEXT *SndwAccessContext; EFI_HANDLE SndwAccessHandle; DEBUG ((DEBUG_INFO, "%a () Start.\n", __FUNCTION__)); SndwAccessHandle = NULL; SndwAccessContext = AllocateZeroPool (sizeof (SNDW_ACCESS_CONTEXT)); if (NULL == SndwAccessContext) { DEBUG ((DEBUG_INFO, "%a () - End. Memory pool allocation error.\n", __FUNCTION__)); return EFI_OUT_OF_RESOURCES; } SndwAccessContext->Signature = SNDW_ACCESS_SIGNATURE; SndwAccessContext->SndwAccessProtocol.Enable = DxeSndwAccessEnable; SndwAccessContext->SndwAccessProtocol.Disable = DxeSndwAccessDisable; SndwAccessContext->SndwAccessProtocol.Send = DxeSndwSend; SndwAccessContext->SndwAccessProtocol.Receive = DxeSndwReceive; SndwAccessContext->SndwAccessProtocol.SendWithAck = DxeSndwSendWithAck; SndwAccessContext->SndwAccessProtocol.GetFirstCodec = DxeSndwGetFirstCodec; SndwAccessContext->SndwAccessProtocol.GetNextCodec = DxeSndwGetNextCodec; SndwAccessContext->CodecListHead = NULL; SndwAccessContext->EnableCounter = 0; // // Install on a new handle // Status = gBS->InstallProtocolInterface ( &SndwAccessHandle, &gSndwAccessProtocolGuid, EFI_NATIVE_INTERFACE, &SndwAccessContext->SndwAccessProtocol ); DEBUG ((DEBUG_INFO, "Sndw access Protocol Installattion Status = %r\n", Status)); if (EFI_ERROR (Status)) { FreePool (SndwAccessContext); } DEBUG ((DEBUG_INFO, "%a () - End. Status = %r.\n", __FUNCTION__, Status)); return Status; }