video.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724
  1. /*++
  2. Copyright (c) 2015 Minoca Corp. All Rights Reserved
  3. Module Name:
  4. video.c
  5. Abstract:
  6. This module implements support for the RK3288 VOP (Video Output Processor).
  7. Author:
  8. Evan Green 10-Jul-2015
  9. Environment:
  10. Firmware
  11. --*/
  12. //
  13. // ------------------------------------------------------------------- Includes
  14. //
  15. #include <uefifw.h>
  16. #include <minoca/uefi/protocol/graphout.h>
  17. #include "veyronfw.h"
  18. //
  19. // --------------------------------------------------------------------- Macros
  20. //
  21. #define READ_LCD(_Register) \
  22. EfiReadRegister32((VOID *)(RK32_LCD_BASE + (_Register)))
  23. #define WRITE_LCD(_Register, _Value) \
  24. EfiWriteRegister32((VOID *)(RK32_LCD_BASE + (_Register)), (_Value))
  25. #define RK32_CPU_AXI_QOS_PRIORITY_LEVEL(_HValue, _LValue) \
  26. ((((_HValue) & 3) << 2) | ((_LValue) & 3))
  27. //
  28. // ---------------------------------------------------------------- Definitions
  29. //
  30. #define EFI_RK32_VIDEO_DEVICE_GUID \
  31. { \
  32. 0x32B82BC3, 0xFAF1, 0x41BB, \
  33. {0xB0, 0xBC, 0xEF, 0xF5, 0x6D, 0xE7, 0x8F, 0x0F} \
  34. }
  35. #define EFI_RK32_VIDEO_DEVICE_MAGIC 0x56336B52
  36. //
  37. // Define the default mode to initialize in.
  38. //
  39. #define EFI_RK32_VIDEO_DEFAULT_MODE 0
  40. #define EFI_RK32_VIDEO_MODE_COUNT \
  41. (sizeof(EfiRk32VideoModes) / sizeof(EfiRk32VideoModes[0]))
  42. //
  43. // Define the size of the frame buffer to allocate, which should be large
  44. // enough to support the largest resolution.
  45. //
  46. #define EFI_RK32_FRAME_BUFFER_SIZE (1366 * 768 * sizeof(UINT16))
  47. //
  48. // Define the LCD controller to talk to.
  49. //
  50. #define RK32_LCD_BASE RK32_VOP_LITTLE_BASE
  51. //
  52. // ------------------------------------------------------ Data Type Definitions
  53. //
  54. /*++
  55. Structure Description:
  56. This structure stores the RK32xx graphics output mode information.
  57. Members:
  58. Information - Stores the information structure.
  59. --*/
  60. typedef struct _EFI_RK32_VIDEO_MODE {
  61. EFI_GRAPHICS_OUTPUT_MODE_INFORMATION Information;
  62. } EFI_RK32_VIDEO_MODE, *PEFI_RK32_VIDEO_MODE;
  63. /*++
  64. Structure Description:
  65. This structure stores the structure of an RK32 video device path.
  66. Members:
  67. VendorPath - Stores the vendor path portion of the device path.
  68. End - Stores the end device path node.
  69. --*/
  70. typedef struct _EFI_RK32_VIDEO_DEVICE_PATH {
  71. VENDOR_DEVICE_PATH VendorPath;
  72. EFI_DEVICE_PATH_PROTOCOL End;
  73. } EFI_RK32_VIDEO_DEVICE_PATH, *PEFI_RK32_VIDEO_DEVICE_PATH;
  74. /*++
  75. Structure Description:
  76. This structure stores the internal context for an RK32xx video device.
  77. Members:
  78. Magic - Stores the constant magic value EFI_RK32_VIDEO_DEVICE_MAGIC.
  79. Handle - Stores the graphics out handle.
  80. GraphicsOut - Stores the graphics output protocol.
  81. GraphicsOutMode - Stores the graphics output protocol mode.
  82. --*/
  83. typedef struct _EFI_RK32_VIDEO_DEVICE {
  84. UINT32 Magic;
  85. EFI_HANDLE Handle;
  86. EFI_GRAPHICS_OUTPUT_PROTOCOL GraphicsOut;
  87. EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE GraphicsOutMode;
  88. } EFI_RK32_VIDEO_DEVICE, *PEFI_RK32_VIDEO_DEVICE;
  89. //
  90. // ----------------------------------------------- Internal Function Prototypes
  91. //
  92. EFIAPI
  93. EFI_STATUS
  94. EfipRk32GraphicsQueryMode (
  95. EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
  96. UINT32 ModeNumber,
  97. UINTN *SizeOfInfo,
  98. EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info
  99. );
  100. EFIAPI
  101. EFI_STATUS
  102. EfipRk32GraphicsSetMode (
  103. EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
  104. UINT32 ModeNumber
  105. );
  106. EFIAPI
  107. EFI_STATUS
  108. EfipRk32GraphicsBlt (
  109. EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
  110. EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer,
  111. EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,
  112. UINTN SourceX,
  113. UINTN SourceY,
  114. UINTN DestinationX,
  115. UINTN DestinationY,
  116. UINTN Width,
  117. UINTN Height,
  118. UINTN Delta
  119. );
  120. EFI_STATUS
  121. EfipRk32VideoInitialize (
  122. EFI_PHYSICAL_ADDRESS FrameBufferBase,
  123. UINT32 FrameBufferWidth,
  124. UINT32 FrameBufferHeight
  125. );
  126. VOID
  127. EfipRk32LcdMask (
  128. RK32_LCD_REGISTER Register,
  129. UINT32 Mask,
  130. UINT32 Value
  131. );
  132. VOID
  133. EfipRk32GpioMask (
  134. VOID *GpioBase,
  135. RK32_GPIO_REGISTER Register,
  136. UINT32 Mask,
  137. UINT32 Value
  138. );
  139. //
  140. // -------------------------------------------------------------------- Globals
  141. //
  142. //
  143. // Store the device path of the video controller.
  144. //
  145. EFI_RK32_VIDEO_DEVICE_PATH EfiRk32VideoDevicePathTemplate = {
  146. {
  147. {
  148. HARDWARE_DEVICE_PATH,
  149. HW_VENDOR_DP,
  150. sizeof(VENDOR_DEVICE_PATH)
  151. },
  152. EFI_RK32_VIDEO_DEVICE_GUID,
  153. },
  154. {
  155. END_DEVICE_PATH_TYPE,
  156. END_ENTIRE_DEVICE_PATH_SUBTYPE,
  157. END_DEVICE_PATH_LENGTH
  158. }
  159. };
  160. //
  161. // Define the supported video modes.
  162. //
  163. EFI_RK32_VIDEO_MODE EfiRk32VideoModes[] = {
  164. {
  165. {
  166. 0,
  167. 1366,
  168. 768,
  169. PixelBitMask,
  170. {
  171. 0x0000F800,
  172. 0x000007E0,
  173. 0x0000001F,
  174. 0x00000000
  175. },
  176. 1366
  177. },
  178. }
  179. };
  180. //
  181. // ------------------------------------------------------------------ Functions
  182. //
  183. EFI_STATUS
  184. EfipVeyronEnumerateVideo (
  185. VOID
  186. )
  187. /*++
  188. Routine Description:
  189. This routine enumerates the display on the Veyron.
  190. Arguments:
  191. None.
  192. Return Value:
  193. EFI status code.
  194. --*/
  195. {
  196. PEFI_RK32_VIDEO_DEVICE Device;
  197. EFI_PHYSICAL_ADDRESS FrameBufferBase;
  198. PEFI_RK32_VIDEO_MODE Mode;
  199. EFI_STATUS Status;
  200. FrameBufferBase = -1;
  201. Device = NULL;
  202. Mode = &(EfiRk32VideoModes[EFI_RK32_VIDEO_DEFAULT_MODE]);
  203. //
  204. // Allocate space for the frame buffer.
  205. //
  206. Status = EfiAllocatePages(AllocateAnyPages,
  207. EfiMemoryMappedIO,
  208. EFI_SIZE_TO_PAGES(EFI_RK32_FRAME_BUFFER_SIZE),
  209. &FrameBufferBase);
  210. if (EFI_ERROR(Status)) {
  211. return Status;
  212. }
  213. //
  214. // Initialize the video to the default mode.
  215. //
  216. Status = EfipRk32VideoInitialize(FrameBufferBase,
  217. Mode->Information.HorizontalResolution,
  218. Mode->Information.VerticalResolution);
  219. if (EFI_ERROR(Status)) {
  220. goto EnumerateVideoEnd;
  221. }
  222. //
  223. // Everything's all set up, create the graphics output protocol.
  224. //
  225. Status = EfiAllocatePool(EfiBootServicesData,
  226. sizeof(EFI_RK32_VIDEO_DEVICE),
  227. (VOID **)&Device);
  228. if (EFI_ERROR(Status)) {
  229. goto EnumerateVideoEnd;
  230. }
  231. EfiSetMem(Device, sizeof(EFI_RK32_VIDEO_DEVICE), 0);
  232. Device->Magic = EFI_RK32_VIDEO_DEVICE_MAGIC;
  233. Device->GraphicsOut.QueryMode = EfipRk32GraphicsQueryMode;
  234. Device->GraphicsOut.SetMode = EfipRk32GraphicsSetMode;
  235. Device->GraphicsOut.Blt = EfipRk32GraphicsBlt;
  236. Device->GraphicsOut.Mode = &(Device->GraphicsOutMode);
  237. Device->GraphicsOutMode.MaxMode = EFI_RK32_VIDEO_MODE_COUNT;
  238. Device->GraphicsOutMode.Mode = EFI_RK32_VIDEO_DEFAULT_MODE;
  239. Device->GraphicsOutMode.Info = &(Mode->Information);
  240. Device->GraphicsOutMode.SizeOfInfo =
  241. sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
  242. Device->GraphicsOutMode.FrameBufferBase = FrameBufferBase;
  243. Device->GraphicsOutMode.FrameBufferSize = EFI_RK32_FRAME_BUFFER_SIZE;
  244. Status = EfiInstallMultipleProtocolInterfaces(
  245. &(Device->Handle),
  246. &EfiGraphicsOutputProtocolGuid,
  247. &(Device->GraphicsOut),
  248. &EfiDevicePathProtocolGuid,
  249. &EfiRk32VideoDevicePathTemplate,
  250. NULL);
  251. if (EFI_ERROR(Status)) {
  252. goto EnumerateVideoEnd;
  253. }
  254. EnumerateVideoEnd:
  255. if (EFI_ERROR(Status)) {
  256. if (FrameBufferBase != -1) {
  257. EfiFreePages(FrameBufferBase,
  258. EFI_SIZE_TO_PAGES(EFI_RK32_FRAME_BUFFER_SIZE));
  259. }
  260. if (Device != NULL) {
  261. EfiFreePool(Device);
  262. }
  263. }
  264. return Status;
  265. }
  266. //
  267. // --------------------------------------------------------- Internal Functions
  268. //
  269. EFIAPI
  270. EFI_STATUS
  271. EfipRk32GraphicsQueryMode (
  272. EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
  273. UINT32 ModeNumber,
  274. UINTN *SizeOfInfo,
  275. EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info
  276. )
  277. /*++
  278. Routine Description:
  279. This routine returns information about available graphics modes that the
  280. graphics device and set of active video output devices support.
  281. Arguments:
  282. This - Supplies a pointer to the protocol instance.
  283. ModeNumber - Supplies the mode number to return information about.
  284. SizeOfInfo - Supplies a pointer that on input contains the size in bytes of
  285. the information buffer.
  286. Info - Supplies a pointer where a callee-allocated buffer will be returned
  287. containing information about the mode. The caller is responsible for
  288. calling FreePool to free this data.
  289. Return Value:
  290. EFI_SUCCESS on success.
  291. EFI_DEVICE_ERROR if a hardware error occurred trying to retrieve the video
  292. mode.
  293. EFI_INVALID_PARAMETER if the mode number is not valid.
  294. --*/
  295. {
  296. EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Information;
  297. EFI_STATUS Status;
  298. if ((ModeNumber >= EFI_RK32_VIDEO_MODE_COUNT) || (SizeOfInfo == NULL)) {
  299. return EFI_INVALID_PARAMETER;
  300. }
  301. Status = EfiAllocatePool(EfiBootServicesData,
  302. sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION),
  303. (VOID **)&Information);
  304. if (EFI_ERROR(Status)) {
  305. return Status;
  306. }
  307. EfiCopyMem(Information,
  308. &(EfiRk32VideoModes[ModeNumber].Information),
  309. sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));
  310. *Info = Information;
  311. *SizeOfInfo = sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
  312. return EFI_SUCCESS;
  313. }
  314. EFIAPI
  315. EFI_STATUS
  316. EfipRk32GraphicsSetMode (
  317. EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
  318. UINT32 ModeNumber
  319. )
  320. /*++
  321. Routine Description:
  322. This routine sets the video device into the specified mode and clears the
  323. visible portions of the output display to black.
  324. Arguments:
  325. This - Supplies a pointer to the protocol instance.
  326. ModeNumber - Supplies the mode number to set.
  327. Return Value:
  328. EFI_SUCCESS on success.
  329. EFI_DEVICE_ERROR if a hardware error occurred trying to set the video mode.
  330. EFI_UNSUPPORTED if the mode number is not supported by this device.
  331. --*/
  332. {
  333. PEFI_RK32_VIDEO_MODE Mode;
  334. EFI_STATUS Status;
  335. if (ModeNumber >= EFI_RK32_VIDEO_MODE_COUNT) {
  336. return EFI_UNSUPPORTED;
  337. }
  338. Mode = &(EfiRk32VideoModes[ModeNumber]);
  339. Status = EfipRk32VideoInitialize(This->Mode->FrameBufferBase,
  340. Mode->Information.HorizontalResolution,
  341. Mode->Information.VerticalResolution);
  342. if (EFI_ERROR(Status)) {
  343. return Status;
  344. }
  345. This->Mode->Info = &(Mode->Information);
  346. This->Mode->Mode = ModeNumber;
  347. This->Mode->SizeOfInfo = sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
  348. return EFI_SUCCESS;
  349. }
  350. EFIAPI
  351. EFI_STATUS
  352. EfipRk32GraphicsBlt (
  353. EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
  354. EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer,
  355. EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,
  356. UINTN SourceX,
  357. UINTN SourceY,
  358. UINTN DestinationX,
  359. UINTN DestinationY,
  360. UINTN Width,
  361. UINTN Height,
  362. UINTN Delta
  363. )
  364. /*++
  365. Routine Description:
  366. This routine performs a Blt (copy) operation of pixels on the graphics
  367. screen. Blt stands for Block Transfer for those not up on their video lingo.
  368. Arguments:
  369. This - Supplies a pointer to the protocol instance.
  370. BltBuffer - Supplies an optional pointer to the data to transfer to the
  371. graphics screen. The size must be at least width * height *
  372. sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL).
  373. BltOperation - Supplies the operation to perform when copying the buffer to
  374. the screen.
  375. SourceX - Supplies the X coordinate of the source of the operation.
  376. SourceY - Supplies the Y coordinate of the source of the operation.
  377. DestinationX - Supplies the X coordinate of the destination of the
  378. operation.
  379. DestinationY - Supplies the Y coordinate of the destination of the
  380. operation.
  381. Width - Supplies the width of the rectangle in pixels.
  382. Height - Supplies the height of the rectangle in pixels.
  383. Delta - Supplies an optional number of bytes in a row of the given buffer.
  384. If a delta of zero is used, the entire buffer is being operated on.
  385. This is not used for EfiBltVideoFill or EfiBltVideoToVideo operations.
  386. Return Value:
  387. EFI_SUCCESS on success.
  388. EFI_INVALID_PARAMETER if the operation was not valid.
  389. EFI_DEVICE_ERROR if a hardware error occurred and the request could not be
  390. completed.
  391. --*/
  392. {
  393. return EFI_UNSUPPORTED;
  394. }
  395. EFI_STATUS
  396. EfipRk32VideoInitialize (
  397. EFI_PHYSICAL_ADDRESS FrameBufferBase,
  398. UINT32 FrameBufferWidth,
  399. UINT32 FrameBufferHeight
  400. )
  401. /*++
  402. Routine Description:
  403. This routine initialize the video subsystem on the RK3288.
  404. Arguments:
  405. FrameBufferBase - Supplies the physical address where the frame buffer is
  406. located.
  407. FrameBufferWidth - Supplies the width of the frame buffer in pixels.
  408. FrameBufferHeight - Supplies the height of the frame buffer in pixels.
  409. Return Value:
  410. Status code.
  411. --*/
  412. {
  413. VOID *Gpio7Base;
  414. UINT32 Height;
  415. UINT32 Mask;
  416. UINT32 Value;
  417. UINT32 Width;
  418. //
  419. // Make sure window 0's display matches the given frame buffer dimensions.
  420. //
  421. Value = READ_LCD(Rk32LcdWin0DisplayInformation);
  422. Width = (Value & RK32_LCD_DSP_INFORMATION_WIDTH_MASK) >>
  423. RK32_LCD_DSP_INFORMATION_WIDTH_SHIFT;
  424. Width += 1;
  425. Height = (Value & RK32_LCD_DSP_INFORMATION_HEIGHT_MASK) >>
  426. RK32_LCD_DSP_INFORMATION_HEIGHT_SHIFT;
  427. Height += 1;
  428. if ((Width != FrameBufferWidth) || (Height != FrameBufferHeight)) {
  429. return EFI_UNSUPPORTED;
  430. }
  431. //
  432. // Update the window 0 framebuffer.
  433. //
  434. WRITE_LCD(Rk32LcdWin0YrgbFrameBufferBase, (UINT32)FrameBufferBase);
  435. //
  436. // Take the LCD out of standby and enable EDP out.
  437. //
  438. Mask = RK32_LCD_SYSTEM_CONTROL_AUTO_GATING |
  439. RK32_LCD_SYSTEM_CONTROL_STANDBY |
  440. RK32_LCD_SYSTEM_CONTROL_EDP_OUT |
  441. RK32_LCD_SYSTEM_CONTROL_DMA_STOP |
  442. RK32_LCD_SYSTEM_CONTROL_MMU_ENABLE;
  443. Value = RK32_LCD_SYSTEM_CONTROL_AUTO_GATING |
  444. RK32_LCD_SYSTEM_CONTROL_EDP_OUT;
  445. EfipRk32LcdMask(Rk32LcdSystemControl, Mask, Value);
  446. WRITE_LCD(Rk32LcdConfigurationDone, 1);
  447. //
  448. // Enable the backlight. Set the Port A backligh enable direction bit to
  449. // output and then set the bit in the data register.
  450. //
  451. Gpio7Base = (VOID *)RK32_GPIO7_BASE;
  452. Value = RK32_GPIO7_BACKLIGHT_ENABLE | RK32_GPIO7_LCD_BACKLIGHT;
  453. EfipRk32GpioMask(Gpio7Base, Rk32GpioPortADirection, 0, Value);
  454. Mask = RK32_GPIO7_BACKLIGHT_ENABLE;
  455. EfipRk32GpioMask(Gpio7Base, Rk32GpioPortAData, Mask, 0);
  456. Value = RK32_GPIO7_LCD_BACKLIGHT;
  457. EfipRk32GpioMask(Gpio7Base, Rk32GpioPortAData, 0, Value);
  458. EfiStall(10000);
  459. Value = RK32_GPIO7_BACKLIGHT_ENABLE;
  460. EfipRk32GpioMask(Gpio7Base, Rk32GpioPortAData, 0, Value);
  461. return EFI_SUCCESS;
  462. }
  463. VOID
  464. EfipRk32LcdMask (
  465. RK32_LCD_REGISTER Register,
  466. UINT32 Mask,
  467. UINT32 Value
  468. )
  469. /*++
  470. Routine Description:
  471. This routine masks out the given mask, then ORs in the given value.
  472. Arguments:
  473. Register - Supplies the register to operate on.
  474. Mask - Supplies the mask to remove.
  475. Value - Supplies the value to OR in.
  476. Return Value:
  477. None.
  478. --*/
  479. {
  480. UINT32 NewValue;
  481. NewValue = READ_LCD(Register);
  482. NewValue &= ~Mask;
  483. NewValue |= Value;
  484. WRITE_LCD(Register, NewValue);
  485. return;
  486. }
  487. VOID
  488. EfipRk32GpioMask (
  489. VOID *GpioBase,
  490. RK32_GPIO_REGISTER Register,
  491. UINT32 Mask,
  492. UINT32 Value
  493. )
  494. /*++
  495. Routine Description:
  496. This routine masks out the given mask, then ORs in the given value.
  497. Arguments:
  498. GpioBase - Supplies the GPIO base address.
  499. Register - Supplies the register to operate on.
  500. Mask - Supplies the mask to remove.
  501. Value - Supplies the value to OR in.
  502. Return Value:
  503. None.
  504. --*/
  505. {
  506. UINT32 NewValue;
  507. NewValue = EfiReadRegister32(GpioBase + Register);
  508. NewValue &= ~Mask;
  509. NewValue |= Value;
  510. EfiWriteRegister32(GpioBase + Register, NewValue);
  511. return;
  512. }