PchHdaAcpi.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324
  1. /** @file
  2. Initializes the PCH HD Audio ACPI Tables.
  3. Copyright (c) 2019 - 2020 Intel Corporation. All rights reserved. <BR>
  4. SPDX-License-Identifier: BSD-2-Clause-Patent
  5. **/
  6. #include <Library/DebugLib.h>
  7. #include <Library/IoLib.h>
  8. #include <Library/BaseMemoryLib.h>
  9. #include <Library/PciSegmentLib.h>
  10. #include <Library/UefiBootServicesTableLib.h>
  11. #include <Library/UefiLib.h>
  12. #include <Protocol/AcpiTable.h>
  13. #include <Library/ConfigBlockLib.h>
  14. #include "PchInit.h"
  15. #include <Protocol/PchPolicy.h>
  16. #include <ConfigBlock/HdAudioConfig.h>
  17. #include <Private/PchConfigHob.h>
  18. #include <Library/PchInfoLib.h>
  19. #include <Private/Library/PchHdaLib.h>
  20. #include <IndustryStandard/Pci30.h>
  21. #include <Register/PchRegs.h>
  22. #include <Register/PchRegsHda.h>
  23. PCH_HDA_NHLT_ENDPOINTS mPchHdaNhltEndpoints[HdaEndpointMax] =
  24. {
  25. {HdaDmicX1, B_HDA_DMIC_1CH_48KHZ_16BIT_FORMAT, 0, FALSE},
  26. {HdaDmicX2, (B_HDA_DMIC_2CH_48KHZ_16BIT_FORMAT | B_HDA_DMIC_2CH_48KHZ_32BIT_FORMAT), 0, FALSE},
  27. {HdaDmicX4, (B_HDA_DMIC_4CH_48KHZ_16BIT_FORMAT | B_HDA_DMIC_4CH_48KHZ_32BIT_FORMAT), 0, FALSE},
  28. {HdaBtRender, (B_HDA_BT_NARROWBAND_FORMAT | B_HDA_BT_WIDEBAND_FORMAT | B_HDA_BT_A2DP_FORMAT), 0, FALSE},
  29. {HdaBtCapture, (B_HDA_BT_NARROWBAND_FORMAT | B_HDA_BT_WIDEBAND_FORMAT), 0, FALSE},
  30. {HdaI2sRender1, B_HDA_I2S_RTK274_RENDER_4CH_48KHZ_24BIT_FORMAT, B_HDA_I2S_RENDER_DEVICE_INFO, FALSE},
  31. {HdaI2sRender2, B_HDA_I2S_RTK274_RENDER_4CH_48KHZ_24BIT_FORMAT, B_HDA_I2S_RENDER_DEVICE_INFO, FALSE},
  32. {HdaI2sCapture, B_HDA_I2S_RTK274_CAPTURE_4CH_48KHZ_24BIT_FORMAT, B_HDA_I2S_CAPTURE_DEVICE_INFO, FALSE}
  33. };
  34. #define DSP_FW_STOLEN_MEMORY_SIZE 0x400000 //4MB
  35. /**
  36. Allocates 4MB of memory for DSP FW usage.
  37. @retval EFI_PHYSICAL_ADDRESS Allocated memory address
  38. **/
  39. EFI_PHYSICAL_ADDRESS
  40. AllocateAudioDspStolenMemory (
  41. )
  42. {
  43. EFI_STATUS Status;
  44. EFI_PHYSICAL_ADDRESS DspStolenMemBaseAddress;
  45. DspStolenMemBaseAddress = 0;
  46. DEBUG ((DEBUG_INFO, "AllocateAudioDspStolenMemory()\n"));
  47. //
  48. // Reserve memory to store Acpi Debug data.
  49. //
  50. DspStolenMemBaseAddress = 0xFFFFFFFF;
  51. Status = gBS->AllocatePages (
  52. AllocateMaxAddress,
  53. EfiReservedMemoryType,
  54. EFI_SIZE_TO_PAGES (DSP_FW_STOLEN_MEMORY_SIZE),
  55. &DspStolenMemBaseAddress
  56. );
  57. ASSERT_EFI_ERROR(Status);
  58. ZeroMem ((VOID *) (UINTN) DspStolenMemBaseAddress, DSP_FW_STOLEN_MEMORY_SIZE);
  59. mPchNvsAreaProtocol.Area->DSPM = (UINT32) DspStolenMemBaseAddress;
  60. DEBUG ((DEBUG_INFO, "mPchNvsAreaProtocol.Area->DSPM = 0x%016x\n", mPchNvsAreaProtocol.Area->DSPM));
  61. return DspStolenMemBaseAddress;
  62. }
  63. /**
  64. Retrieves address of NHLT table from XSDT/RSDT.
  65. @retval NHLT_ACPI_TABLE* Pointer to NHLT table if found
  66. @retval NULL NHLT could not be found
  67. **/
  68. NHLT_ACPI_TABLE *
  69. LocateNhltAcpiTable (
  70. VOID
  71. )
  72. {
  73. EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER *Rsdp;
  74. EFI_ACPI_DESCRIPTION_HEADER *Xsdt;
  75. NHLT_ACPI_TABLE *Nhlt;
  76. UINTN Index;
  77. UINT64 Data64;
  78. EFI_STATUS Status;
  79. Rsdp = NULL;
  80. Xsdt = NULL;
  81. Nhlt = NULL;
  82. ///
  83. /// Find the AcpiSupport protocol returns RSDP (or RSD PTR) address.
  84. ///
  85. DEBUG ((DEBUG_INFO, "LocateNhltAcpiTable() Start\n"));
  86. Status = EfiGetSystemConfigurationTable (&gEfiAcpiTableGuid, (VOID *) &Rsdp);
  87. if (EFI_ERROR (Status) || (Rsdp == NULL)) {
  88. DEBUG ((DEBUG_ERROR, "EFI_ERROR or Rsdp == NULL\n"));
  89. return NULL;
  90. }
  91. Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *) (UINTN) Rsdp->XsdtAddress;
  92. if (Xsdt == NULL || Xsdt->Signature != EFI_ACPI_5_0_EXTENDED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE) {
  93. // If XSDT has not been found, check RSDT
  94. Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *) (UINTN) Rsdp->RsdtAddress;
  95. if (Xsdt == NULL || Xsdt->Signature != EFI_ACPI_5_0_ROOT_SYSTEM_DESCRIPTION_TABLE_SIGNATURE) {
  96. DEBUG ((DEBUG_ERROR, "XSDT/RSDT == NULL or wrong signature\n"));
  97. return NULL;
  98. }
  99. }
  100. for (Index = sizeof (EFI_ACPI_DESCRIPTION_HEADER); Index < Xsdt->Length; Index = Index + sizeof (UINT64)) {
  101. Data64 = *(UINT64 *) ((UINT8 *) Xsdt + Index);
  102. Nhlt = (NHLT_ACPI_TABLE *) (UINTN) Data64;
  103. if (Nhlt->Header.Signature == NHLT_ACPI_TABLE_SIGNATURE) {
  104. break;
  105. }
  106. }
  107. if (Nhlt == NULL || Nhlt->Header.Signature != NHLT_ACPI_TABLE_SIGNATURE) {
  108. DEBUG ((DEBUG_ERROR, "Nhlt == NULL or wrong signature\n"));
  109. return NULL;
  110. }
  111. DEBUG ((DEBUG_INFO, "Found NhltTable, Address = 0x%016x\n", Nhlt));
  112. return Nhlt;
  113. }
  114. /**
  115. Constructs and installs NHLT table.
  116. @retval EFI_SUCCESS ACPI Table installed successfully
  117. @retval EFI_UNSUPPORTED ACPI Table protocol not found
  118. **/
  119. EFI_STATUS
  120. PublishNhltAcpiTable (
  121. VOID
  122. )
  123. {
  124. UINTN AcpiTableKey;
  125. EFI_ACPI_TABLE_PROTOCOL *AcpiTable;
  126. NHLT_ACPI_TABLE *NhltTable;
  127. UINT32 TableLength;
  128. EFI_STATUS Status;
  129. AcpiTable = NULL;
  130. NhltTable = NULL;
  131. AcpiTableKey = 0;
  132. DEBUG ((DEBUG_INFO, "PublishNhltAcpiTable() Start\n"));
  133. //
  134. // Locate ACPI support protocol
  135. //
  136. Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **) &AcpiTable);
  137. if ( EFI_ERROR (Status) || AcpiTable == NULL) {
  138. return EFI_UNSUPPORTED;
  139. }
  140. NhltConstructor (mPchHdaNhltEndpoints, &NhltTable, &TableLength);
  141. NhltAcpiHeaderConstructor (NhltTable, TableLength);
  142. Status = AcpiTable->InstallAcpiTable (AcpiTable, NhltTable, NhltTable->Header.Length, &AcpiTableKey);
  143. DEBUG ((DEBUG_INFO, "PublishNhltAcpiTable() End\n"));
  144. return Status;
  145. }
  146. /**
  147. Sets NVS ACPI variables for HDAS._DSM and SNDW._DSD accordingly to policy.
  148. @param[in] NhltAcpiTableAddress
  149. @param[in] NhltAcpiTableLength
  150. @param[in] *HdAudioConfigHob
  151. @param[in] *HdAudioDxeConfig
  152. **/
  153. VOID
  154. UpdateHdaAcpiData (
  155. IN UINT64 NhltAcpiTableAddress,
  156. IN UINT32 NhltAcpiTableLength,
  157. IN CONST HDAUDIO_HOB *HdAudioConfigHob,
  158. IN CONST PCH_HDAUDIO_DXE_CONFIG *HdAudioDxeConfig
  159. )
  160. {
  161. DEBUG ((DEBUG_INFO, "UpdateHdaAcpiData():\n NHLT Address = 0x%016x, Length = 0x%08x\n", NhltAcpiTableAddress, NhltAcpiTableLength));
  162. DEBUG ((DEBUG_INFO, " FeatureMask = 0x%08x\n", HdAudioDxeConfig->DspFeatureMask));
  163. mPchNvsAreaProtocol.Area->NHLA = NhltAcpiTableAddress;
  164. mPchNvsAreaProtocol.Area->NHLL = NhltAcpiTableLength;
  165. mPchNvsAreaProtocol.Area->ADFM = HdAudioDxeConfig->DspFeatureMask;
  166. mPchNvsAreaProtocol.Area->SWQ0 = HdAudioConfigHob->AudioLinkSndw1 ? 0 : BIT1;
  167. mPchNvsAreaProtocol.Area->SWQ1 = HdAudioConfigHob->AudioLinkSndw2 ? 0 : BIT1;
  168. mPchNvsAreaProtocol.Area->SWQ2 = HdAudioConfigHob->AudioLinkSndw3 ? 0 : BIT1;
  169. mPchNvsAreaProtocol.Area->SWQ3 = HdAudioConfigHob->AudioLinkSndw4 ? 0 : BIT1;
  170. }
  171. /**
  172. Initialize and publish NHLT (Non-HDA Link Table), update NVS variables.
  173. @param[in] *HdAudioConfigHob
  174. @param[in] *HdAudioDxeConfig
  175. @retval EFI_SUCCESS The function completed successfully
  176. **/
  177. EFI_STATUS
  178. SetHdaAcpiTable (
  179. IN CONST HDAUDIO_HOB *HdAudioConfigHob,
  180. IN CONST PCH_HDAUDIO_DXE_CONFIG *HdAudioDxeConfig
  181. )
  182. {
  183. NHLT_ACPI_TABLE *NhltTable;
  184. EFI_STATUS Status;
  185. NhltTable = NULL;
  186. Status = EFI_SUCCESS;
  187. if (HdAudioDxeConfig->NhltDefaultFlow == TRUE) {
  188. switch (HdAudioDxeConfig->DspEndpointDmic) {
  189. case PchHdaDmic1chArray:
  190. mPchHdaNhltEndpoints[HdaDmicX1].Enable = TRUE;
  191. break;
  192. case PchHdaDmic2chArray:
  193. mPchHdaNhltEndpoints[HdaDmicX2].Enable = TRUE;
  194. break;
  195. case PchHdaDmic4chArray:
  196. mPchHdaNhltEndpoints[HdaDmicX4].Enable = TRUE;
  197. break;
  198. case PchHdaDmicDisabled:
  199. default:
  200. mPchHdaNhltEndpoints[HdaDmicX2].Enable = FALSE;
  201. mPchHdaNhltEndpoints[HdaDmicX4].Enable = FALSE;
  202. }
  203. if (HdAudioDxeConfig->DspEndpointBluetooth) {
  204. mPchHdaNhltEndpoints[HdaBtRender].Enable = TRUE;
  205. mPchHdaNhltEndpoints[HdaBtCapture].Enable = TRUE;
  206. }
  207. if (HdAudioDxeConfig->DspEndpointI2s) {
  208. mPchHdaNhltEndpoints[HdaI2sRender1].Enable = TRUE;
  209. mPchHdaNhltEndpoints[HdaI2sRender2].Enable = TRUE;
  210. mPchHdaNhltEndpoints[HdaI2sCapture].Enable = TRUE;
  211. }
  212. Status = PublishNhltAcpiTable ();
  213. }
  214. NhltTable = LocateNhltAcpiTable ();
  215. if (NhltTable == NULL) {
  216. return EFI_LOAD_ERROR;
  217. }
  218. UpdateHdaAcpiData ((UINT64) (UINTN) NhltTable, (UINT32) (NhltTable->Header.Length), HdAudioConfigHob, HdAudioDxeConfig);
  219. if (IsPchLp () && (PchStepping () < PCH_B0)) {
  220. AllocateAudioDspStolenMemory ();
  221. }
  222. DEBUG_CODE ( NhltAcpiTableDump (NhltTable); );
  223. return Status;
  224. }
  225. /**
  226. Initialize Intel High Definition Audio ACPI Tables
  227. @retval EFI_SUCCESS The function completed successfully
  228. @retval EFI_LOAD_ERROR ACPI table cannot be installed
  229. @retval EFI_UNSUPPORTED ACPI table not set because DSP is disabled
  230. **/
  231. EFI_STATUS
  232. PchHdAudioAcpiInit (
  233. VOID
  234. )
  235. {
  236. EFI_STATUS Status;
  237. UINT64 HdaPciBase;
  238. CONST HDAUDIO_HOB *HdAudioConfigHob;
  239. PCH_POLICY_PROTOCOL *PchPolicy;
  240. PCH_HDAUDIO_DXE_CONFIG *HdAudioDxeConfig;
  241. DEBUG ((DEBUG_INFO, "PchHdAudioAcpiInit() Start\n"));
  242. HdAudioConfigHob = &mPchConfigHob->HdAudio;
  243. ///
  244. /// Get PCH Policy Protocol
  245. ///
  246. Status = gBS->LocateProtocol (&gPchPolicyProtocolGuid, NULL, (VOID **)&PchPolicy);
  247. ASSERT_EFI_ERROR (Status);
  248. ///
  249. /// Get HD Audio DXE Config Block
  250. ///
  251. Status = GetConfigBlock ((VOID *)PchPolicy, &gHdAudioDxeConfigGuid, (VOID *)&HdAudioDxeConfig);
  252. ASSERT_EFI_ERROR (Status);
  253. HdaPciBase = PCI_SEGMENT_LIB_ADDRESS (
  254. DEFAULT_PCI_SEGMENT_NUMBER_PCH,
  255. DEFAULT_PCI_BUS_NUMBER_PCH,
  256. PCI_DEVICE_NUMBER_PCH_HDA,
  257. PCI_FUNCTION_NUMBER_PCH_HDA,
  258. 0
  259. );
  260. if ((PciSegmentRead16 (HdaPciBase + PCI_VENDOR_ID_OFFSET) == 0xFFFF) || (HdAudioConfigHob->DspEnable == FALSE)) {
  261. // Do not set ACPI tables if HDAudio is Function disabled or DSP is disabled
  262. DEBUG ((DEBUG_INFO, "AudioDSP: Non-HDAudio ACPI Table (NHLT) not set!\n"));
  263. return EFI_UNSUPPORTED;
  264. }
  265. Status = SetHdaAcpiTable (HdAudioConfigHob, HdAudioDxeConfig);
  266. DEBUG ((DEBUG_INFO, "PchHdAudioAcpiInit() End - Status = %r\n", Status));
  267. return Status;
  268. }