video.c 26 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081
  1. /*++
  2. Copyright (c) 2014 Minoca Corp.
  3. This file is licensed under the terms of the GNU General Public License
  4. version 3. Alternative licensing terms are available. Contact
  5. info@minocacorp.com for details. See the LICENSE file at the root of this
  6. project for complete licensing information.
  7. Module Name:
  8. video.c
  9. Abstract:
  10. This module implements support for the BCM2709 SoC Family display
  11. controller.
  12. Author:
  13. Chris Stevens 21-Dec-2014
  14. Environment:
  15. Firmware
  16. --*/
  17. //
  18. // ------------------------------------------------------------------- Includes
  19. //
  20. #include <uefifw.h>
  21. #include <dev/bcm2709.h>
  22. #include <minoca/uefi/protocol/graphout.h>
  23. //
  24. // --------------------------------------------------------------------- Macros
  25. //
  26. //
  27. // ---------------------------------------------------------------- Definitions
  28. //
  29. #define EFI_BCM2709_VIDEO_DEVICE_GUID \
  30. { \
  31. 0x87FC0212, 0x9519, 0x11E4, \
  32. {0x92, 0x76, 0x04, 0x01, 0x0F, 0xDD, 0x74, 0x01} \
  33. }
  34. #define EFI_BCM2709_VIDEO_DEVICE_MAGIC 0x64695642 // 'diVB'
  35. #define EFI_BCM2709_VIDEO_MODE_ARRAY_LENGTH \
  36. (sizeof(EfiBcm2709VideoModes) / sizeof(EfiBcm2709VideoModes[0]))
  37. //
  38. // ------------------------------------------------------ Data Type Definitions
  39. //
  40. /*++
  41. Structure Description:
  42. This structure defines the data necessary to get the current mode.
  43. Members:
  44. Header - Stores a header that defines the total size of the messages being
  45. received from the mailbox.
  46. PhysicalResolution - Stores a request for the physical resolution when sent
  47. to the mailbox and receives the current physical resolution on return.
  48. EndTag - Stores the tag to denote the end of the mailbox message.
  49. --*/
  50. typedef struct _EFI_BCM2709_VIDEO_GET_MODE {
  51. BCM2709_MAILBOX_HEADER Header;
  52. BCM2709_MAILBOX_RESOLUTION PhysicalResolution;
  53. UINT32 EndTag;
  54. } EFI_BCM2709_VIDEO_GET_MODE, *PEFI_BCM2709_VIDEO_GET_MODE;
  55. /*++
  56. Structure Description:
  57. This structure defines the data necessary to initialize video and get a
  58. frame buffer.
  59. Members:
  60. Header - Stores a header that defines the total size of the messages being
  61. sent to and received from the mailbox.
  62. PhysicalResolution - Stores a request to set the physical resolution and
  63. receives the current physical resolution.
  64. VirtualResolution - Stores a request to set the virtual resolution and
  65. receives the current virtual resolution.
  66. BitsPerPixel - Stores a request to set the bits per pixel and receives the
  67. current bits per pixel.
  68. PixelOrder - Stores a request to set the pixel order and receives the
  69. current pixel order.
  70. AlphaMode - Stores a request to set the alpha mode.
  71. VirtualOffset - Stores a request to set the virtual offset.
  72. Overscan - Stores a request to set the screen's overscan.
  73. Pitch - Stores a request to get the pitch information.
  74. FrameBuffer - Stores a request to get the frame buffer.
  75. EndTag - Stores the tag to denote the end of the mailbox message.
  76. --*/
  77. typedef struct _EFI_BCM2709_VIDEO_INITIALIZE {
  78. BCM2709_MAILBOX_HEADER Header;
  79. BCM2709_MAILBOX_RESOLUTION PhysicalResolution;
  80. BCM2709_MAILBOX_RESOLUTION VirtualResolution;
  81. BCM2709_MAILBOX_BITS_PER_PIXEL BitsPerPixelMessage;
  82. BCM2709_MAILBOX_PIXEL_ORDER PixelOrderMessage;
  83. BCM2709_MAILBOX_ALPHA_MODE AlphaModeMessage;
  84. BCM2709_MAILBOX_VIRTUAL_OFFSET VirtualOffset;
  85. BCM2709_MAILBOX_OVERSCAN OverscanMessage;
  86. BCM2709_MAILBOX_PITCH Pitch;
  87. BCM2709_MAILBOX_FRAME_BUFFER FrameBufferMessage;
  88. UINT32 EndTag;
  89. } EFI_BCM2709_VIDEO_INITIALIZE, *PEFI_BCM2709_VIDEO_INITIALIZE;
  90. /*++
  91. Structure Description:
  92. This structure stores the structure of an BCM2709 video device path.
  93. Members:
  94. VendorPath - Stores the vendor path portion of the device path.
  95. End - Stores the end device path node.
  96. --*/
  97. typedef struct _EFI_BCM2709_VIDEO_DEVICE_PATH {
  98. VENDOR_DEVICE_PATH VendorPath;
  99. EFI_DEVICE_PATH_PROTOCOL End;
  100. } EFI_BCM2709_VIDEO_DEVICE_PATH, *PEFI_BCM2709_VIDEO_DEVICE_PATH;
  101. /*++
  102. Structure Description:
  103. This structure stores the internal context for an BCM2709 video device.
  104. Members:
  105. Magic - Stores the constant magic value EFI_BCM2709_VIDEO_DEVICE_MAGIC.
  106. Handle - Stores the graphics out handle.
  107. GraphicsOut - Stores the graphics output protocol.
  108. GraphicsOutMode - Stores the graphics output protocol mode.
  109. --*/
  110. typedef struct _EFI_BCM2709_VIDEO_DEVICE {
  111. UINT32 Magic;
  112. EFI_HANDLE Handle;
  113. EFI_GRAPHICS_OUTPUT_PROTOCOL GraphicsOut;
  114. EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE GraphicsOutMode;
  115. } EFI_BCM2709_VIDEO_DEVICE, *PEFI_BCM2709_VIDEO_DEVICE;
  116. //
  117. // ----------------------------------------------- Internal Function Prototypes
  118. //
  119. EFIAPI
  120. EFI_STATUS
  121. EfipBcm2709GraphicsQueryMode (
  122. EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
  123. UINT32 ModeNumber,
  124. UINTN *SizeOfInfo,
  125. EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info
  126. );
  127. EFIAPI
  128. EFI_STATUS
  129. EfipBcm2709GraphicsSetMode (
  130. EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
  131. UINT32 ModeNumber
  132. );
  133. EFIAPI
  134. EFI_STATUS
  135. EfipBcm2709GraphicsBlt (
  136. EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
  137. EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer,
  138. EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,
  139. UINTN SourceX,
  140. UINTN SourceY,
  141. UINTN DestinationX,
  142. UINTN DestinationY,
  143. UINTN Width,
  144. UINTN Height,
  145. UINTN Delta
  146. );
  147. EFI_STATUS
  148. EfipBcm2709VideoInitialize (
  149. EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Mode,
  150. EFI_PHYSICAL_ADDRESS *FrameBufferBase,
  151. UINTN *FrameBufferSize
  152. );
  153. VOID
  154. EfipBcm2709VideoInitializeModes (
  155. VOID
  156. );
  157. //
  158. // -------------------------------------------------------------------- Globals
  159. //
  160. //
  161. // Define a template for the call to get the video mode.
  162. //
  163. EFI_BCM2709_VIDEO_GET_MODE EfiBcm2709GetModeTemplate = {
  164. {
  165. sizeof(EFI_BCM2709_VIDEO_GET_MODE),
  166. 0
  167. },
  168. {
  169. {
  170. BCM2709_MAILBOX_TAG_GET_PHYSICAL_RESOLUTION,
  171. sizeof(BCM2709_RESOLUTION),
  172. 0
  173. },
  174. {
  175. 0,
  176. 0
  177. }
  178. },
  179. 0
  180. };
  181. //
  182. // Define a template for the call to initialize the video core and get a frame
  183. // buffer.
  184. //
  185. EFI_BCM2709_VIDEO_INITIALIZE EfiBcm2709InitializeVideoTemplate = {
  186. {
  187. sizeof(EFI_BCM2709_VIDEO_INITIALIZE),
  188. 0
  189. },
  190. {
  191. {
  192. BCM2709_MAILBOX_TAG_SET_PHYSICAL_RESOLUTION,
  193. sizeof(BCM2709_RESOLUTION),
  194. sizeof(BCM2709_RESOLUTION)
  195. },
  196. {
  197. 0,
  198. 0
  199. }
  200. },
  201. {
  202. {
  203. BCM2709_MAILBOX_TAG_SET_VIRTUAL_RESOLUTION,
  204. sizeof(BCM2709_RESOLUTION),
  205. sizeof(BCM2709_RESOLUTION)
  206. },
  207. {
  208. 0,
  209. 0
  210. }
  211. },
  212. {
  213. {
  214. BCM2709_MAILBOX_TAG_SET_BITS_PER_PIXEL,
  215. sizeof(UINT32),
  216. sizeof(UINT32)
  217. },
  218. BCM2709_DEFAULT_BITS_PER_PIXEL
  219. },
  220. {
  221. {
  222. BCM2709_MAILBOX_TAG_SET_PIXEL_ORDER,
  223. sizeof(UINT32),
  224. sizeof(UINT32)
  225. },
  226. BCM2709_MAILBOX_PIXEL_ORDER_BGR
  227. },
  228. {
  229. {
  230. BCM2709_MAILBOX_TAG_SET_ALPHA_MODE,
  231. sizeof(UINT32),
  232. sizeof(UINT32)
  233. },
  234. BCM2709_MAILBOX_ALPHA_MODE_IGNORED
  235. },
  236. {
  237. {
  238. BCM2709_MAILBOX_TAG_SET_VIRTUAL_OFFSET,
  239. sizeof(BCM2709_OFFSET),
  240. sizeof(BCM2709_OFFSET)
  241. },
  242. {
  243. 0,
  244. 0
  245. }
  246. },
  247. {
  248. {
  249. BCM2709_MAILBOX_TAG_SET_OVERSCAN,
  250. sizeof(BCM2709_OVERSCAN),
  251. sizeof(BCM2709_OVERSCAN)
  252. },
  253. {
  254. 0,
  255. 0,
  256. 0,
  257. 0
  258. }
  259. },
  260. {
  261. {
  262. BCM2709_MAILBOX_TAG_GET_PITCH,
  263. sizeof(UINT32),
  264. 0,
  265. },
  266. 0
  267. },
  268. {
  269. {
  270. BCM2709_MAILBOX_TAG_GET_FRAME_BUFFER,
  271. sizeof(BCM2709_FRAME_BUFFER),
  272. 0
  273. },
  274. {
  275. 0,
  276. 0
  277. }
  278. },
  279. 0
  280. };
  281. //
  282. // Store the device path of the video controller.
  283. //
  284. EFI_BCM2709_VIDEO_DEVICE_PATH EfiBcm2709VideoDevicePathTemplate = {
  285. {
  286. {
  287. HARDWARE_DEVICE_PATH,
  288. HW_VENDOR_DP,
  289. sizeof(VENDOR_DEVICE_PATH)
  290. },
  291. EFI_BCM2709_VIDEO_DEVICE_GUID,
  292. },
  293. {
  294. END_DEVICE_PATH_TYPE,
  295. END_ENTIRE_DEVICE_PATH_SUBTYPE,
  296. END_DEVICE_PATH_LENGTH
  297. }
  298. };
  299. EFI_GRAPHICS_OUTPUT_MODE_INFORMATION EfiBcm2709VideoModes[] = {
  300. {
  301. 0,
  302. 1024,
  303. 600,
  304. PixelBitMask,
  305. {
  306. BCM2709_BGR_RED_MASK,
  307. BCM2709_BGR_GREEN_MASK,
  308. BCM2709_BGR_BLUE_MASK,
  309. BCM2709_BGR_RESERVED_MASK
  310. },
  311. 1024
  312. },
  313. {
  314. 0,
  315. 1024,
  316. 768,
  317. PixelBitMask,
  318. {
  319. BCM2709_BGR_RED_MASK,
  320. BCM2709_BGR_GREEN_MASK,
  321. BCM2709_BGR_BLUE_MASK,
  322. BCM2709_BGR_RESERVED_MASK
  323. },
  324. 1024
  325. },
  326. {
  327. 0,
  328. 0,
  329. 0,
  330. PixelBitMask,
  331. {
  332. BCM2709_BGR_RED_MASK,
  333. BCM2709_BGR_GREEN_MASK,
  334. BCM2709_BGR_BLUE_MASK,
  335. BCM2709_BGR_RESERVED_MASK
  336. },
  337. 0
  338. },
  339. };
  340. UINT32 EfiBcm2709VideoModeCount = 2;
  341. //
  342. // ------------------------------------------------------------------ Functions
  343. //
  344. EFI_STATUS
  345. EfipBcm2709EnumerateVideo (
  346. VOID
  347. )
  348. /*++
  349. Routine Description:
  350. This routine enumerates the display on BCM2709 SoCs.
  351. Arguments:
  352. None.
  353. Return Value:
  354. EFI status code.
  355. --*/
  356. {
  357. PEFI_BCM2709_VIDEO_DEVICE Device;
  358. EFI_PHYSICAL_ADDRESS FrameBufferBase;
  359. UINTN FrameBufferSize;
  360. UINT32 Index;
  361. EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Mode;
  362. UINT32 ModeIndex;
  363. EFI_STATUS Status;
  364. Device = NULL;
  365. //
  366. // If the BCM2709 device library is not initialized, fail.
  367. //
  368. if (EfiBcm2709Initialized == FALSE) {
  369. return EFI_NOT_READY;
  370. }
  371. //
  372. // Initialize the set of available video modes.
  373. //
  374. EfipBcm2709VideoInitializeModes();
  375. //
  376. // Iterate over the list of available modes backwards until a suitable mode
  377. // is found.
  378. //
  379. Status = EFI_UNSUPPORTED;
  380. for (Index = EfiBcm2709VideoModeCount; Index != 0; Index -= 1) {
  381. ModeIndex = Index - 1;
  382. Mode = &(EfiBcm2709VideoModes[ModeIndex]);
  383. Status = EfipBcm2709VideoInitialize(Mode,
  384. &FrameBufferBase,
  385. &FrameBufferSize);
  386. if (!EFI_ERROR(Status)) {
  387. break;
  388. }
  389. //
  390. // That mode didn't work, so don't advertise it.
  391. //
  392. EfiBcm2709VideoModeCount -= 1;
  393. }
  394. if (EFI_ERROR(Status)) {
  395. goto EnumerateVideoEnd;
  396. }
  397. //
  398. // Everything's all set up, create the graphics output protocol.
  399. //
  400. Status = EfiAllocatePool(EfiBootServicesData,
  401. sizeof(EFI_BCM2709_VIDEO_DEVICE),
  402. (VOID **)&Device);
  403. if (EFI_ERROR(Status)) {
  404. goto EnumerateVideoEnd;
  405. }
  406. EfiSetMem(Device, sizeof(EFI_BCM2709_VIDEO_DEVICE), 0);
  407. Device->Magic = EFI_BCM2709_VIDEO_DEVICE_MAGIC;
  408. Device->GraphicsOut.QueryMode = EfipBcm2709GraphicsQueryMode;
  409. Device->GraphicsOut.SetMode = EfipBcm2709GraphicsSetMode;
  410. Device->GraphicsOut.Blt = EfipBcm2709GraphicsBlt;
  411. Device->GraphicsOut.Mode = &(Device->GraphicsOutMode);
  412. Device->GraphicsOutMode.MaxMode = EfiBcm2709VideoModeCount;
  413. Device->GraphicsOutMode.Mode = ModeIndex;
  414. Device->GraphicsOutMode.Info = Mode;
  415. Device->GraphicsOutMode.SizeOfInfo =
  416. sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
  417. Device->GraphicsOutMode.FrameBufferBase = FrameBufferBase;
  418. Device->GraphicsOutMode.FrameBufferSize = FrameBufferSize;
  419. Status = EfiInstallMultipleProtocolInterfaces(
  420. &(Device->Handle),
  421. &EfiGraphicsOutputProtocolGuid,
  422. &(Device->GraphicsOut),
  423. &EfiDevicePathProtocolGuid,
  424. &EfiBcm2709VideoDevicePathTemplate,
  425. NULL);
  426. if (EFI_ERROR(Status)) {
  427. goto EnumerateVideoEnd;
  428. }
  429. EnumerateVideoEnd:
  430. if (EFI_ERROR(Status)) {
  431. if (Device != NULL) {
  432. EfiFreePool(Device);
  433. }
  434. }
  435. return Status;
  436. }
  437. //
  438. // --------------------------------------------------------- Internal Functions
  439. //
  440. EFIAPI
  441. EFI_STATUS
  442. EfipBcm2709GraphicsQueryMode (
  443. EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
  444. UINT32 ModeNumber,
  445. UINTN *SizeOfInfo,
  446. EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info
  447. )
  448. /*++
  449. Routine Description:
  450. This routine returns information about available graphics modes that the
  451. graphics device and set of active video output devices support.
  452. Arguments:
  453. This - Supplies a pointer to the protocol instance.
  454. ModeNumber - Supplies the mode number to return information about.
  455. SizeOfInfo - Supplies a pointer that on input contains the size in bytes of
  456. the information buffer.
  457. Info - Supplies a pointer where a callee-allocated buffer will be returned
  458. containing information about the mode. The caller is responsible for
  459. calling FreePool to free this data.
  460. Return Value:
  461. EFI_SUCCESS on success.
  462. EFI_DEVICE_ERROR if a hardware error occurred trying to retrieve the video
  463. mode.
  464. EFI_INVALID_PARAMETER if the mode number is not valid.
  465. --*/
  466. {
  467. EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Information;
  468. EFI_STATUS Status;
  469. if ((ModeNumber >= EfiBcm2709VideoModeCount) || (SizeOfInfo == NULL)) {
  470. return EFI_INVALID_PARAMETER;
  471. }
  472. Status = EfiAllocatePool(EfiBootServicesData,
  473. sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION),
  474. (VOID **)&Information);
  475. if (EFI_ERROR(Status)) {
  476. return Status;
  477. }
  478. EfiCopyMem(Information,
  479. &(EfiBcm2709VideoModes[ModeNumber]),
  480. sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));
  481. *Info = Information;
  482. *SizeOfInfo = sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
  483. return EFI_SUCCESS;
  484. }
  485. EFIAPI
  486. EFI_STATUS
  487. EfipBcm2709GraphicsSetMode (
  488. EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
  489. UINT32 ModeNumber
  490. )
  491. /*++
  492. Routine Description:
  493. This routine sets the video device into the specified mode and clears the
  494. visible portions of the output display to black.
  495. Arguments:
  496. This - Supplies a pointer to the protocol instance.
  497. ModeNumber - Supplies the mode number to set.
  498. Return Value:
  499. EFI_SUCCESS on success.
  500. EFI_DEVICE_ERROR if a hardware error occurred trying to set the video mode.
  501. EFI_UNSUPPORTED if the mode number is not supported by this device.
  502. --*/
  503. {
  504. EFI_PHYSICAL_ADDRESS FrameBufferBase;
  505. UINTN FrameBufferSize;
  506. EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Mode;
  507. EFI_STATUS Status;
  508. if (ModeNumber >= EfiBcm2709VideoModeCount) {
  509. return EFI_UNSUPPORTED;
  510. }
  511. Mode = &(EfiBcm2709VideoModes[ModeNumber]);
  512. Status = EfipBcm2709VideoInitialize(Mode,
  513. &FrameBufferBase,
  514. &FrameBufferSize);
  515. if (EFI_ERROR(Status)) {
  516. return Status;
  517. }
  518. This->Mode->Info = Mode;
  519. This->Mode->Mode = ModeNumber;
  520. This->Mode->SizeOfInfo = sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
  521. This->Mode->FrameBufferBase = FrameBufferBase;
  522. This->Mode->FrameBufferSize = FrameBufferSize;
  523. return Status;
  524. }
  525. EFIAPI
  526. EFI_STATUS
  527. EfipBcm2709GraphicsBlt (
  528. EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
  529. EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer,
  530. EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,
  531. UINTN SourceX,
  532. UINTN SourceY,
  533. UINTN DestinationX,
  534. UINTN DestinationY,
  535. UINTN Width,
  536. UINTN Height,
  537. UINTN Delta
  538. )
  539. /*++
  540. Routine Description:
  541. This routine performs a Blt (copy) operation of pixels on the graphics
  542. screen. Blt stands for Block Transfer for those not up on their video lingo.
  543. Arguments:
  544. This - Supplies a pointer to the protocol instance.
  545. BltBuffer - Supplies an optional pointer to the data to transfer to the
  546. graphics screen. The size must be at least width * height *
  547. sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL).
  548. BltOperation - Supplies the operation to perform when copying the buffer to
  549. the screen.
  550. SourceX - Supplies the X coordinate of the source of the operation.
  551. SourceY - Supplies the Y coordinate of the source of the operation.
  552. DestinationX - Supplies the X coordinate of the destination of the
  553. operation.
  554. DestinationY - Supplies the Y coordinate of the destination of the
  555. operation.
  556. Width - Supplies the width of the rectangle in pixels.
  557. Height - Supplies the height of the rectangle in pixels.
  558. Delta - Supplies an optional number of bytes in a row of the given buffer.
  559. If a delta of zero is used, the entire buffer is being operated on.
  560. This is not used for EfiBltVideoFill or EfiBltVideoToVideo operations.
  561. Return Value:
  562. EFI_SUCCESS on success.
  563. EFI_INVALID_PARAMETER if the operation was not valid.
  564. EFI_DEVICE_ERROR if a hardware error occurred and the request could not be
  565. completed.
  566. --*/
  567. {
  568. return EFI_UNSUPPORTED;
  569. }
  570. EFI_STATUS
  571. EfipBcm2709VideoInitialize (
  572. EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Mode,
  573. EFI_PHYSICAL_ADDRESS *FrameBufferBase,
  574. UINTN *FrameBufferSize
  575. )
  576. /*++
  577. Routine Description:
  578. This routine initializes video by setting the controller to the given video
  579. mode.
  580. Arguments:
  581. Mode - Supplies a pointer to the desired video mode.
  582. FrameBufferBase - Supplies a pointer that receives the base address of the
  583. frame buffer.
  584. FrameBufferSize - Supplies a pointer that receives the size of the frame
  585. buffer in bytes.
  586. Return Value:
  587. Status code.
  588. --*/
  589. {
  590. UINT32 ExpectedLength;
  591. UINT32 Height;
  592. EFI_BCM2709_VIDEO_INITIALIZE InitializeVideo;
  593. UINT32 Length;
  594. UINT32 PixelOrder;
  595. UINT32 PixelsPerScanLine;
  596. EFI_STATUS Status;
  597. UINT32 Width;
  598. //
  599. // Update the video initialization template with the given mode information.
  600. //
  601. EfiCopyMem(&InitializeVideo,
  602. &EfiBcm2709InitializeVideoTemplate,
  603. sizeof(EFI_BCM2709_VIDEO_INITIALIZE));
  604. Width = Mode->HorizontalResolution;
  605. Height = Mode->VerticalResolution;
  606. InitializeVideo.PhysicalResolution.Resolution.Width = Width;
  607. InitializeVideo.PhysicalResolution.Resolution.Height = Height;
  608. InitializeVideo.VirtualResolution.Resolution.Width = Width;
  609. InitializeVideo.VirtualResolution.Resolution.Height = Height;
  610. //
  611. // Determine the pixel order and update the template if necessary.
  612. //
  613. if ((Mode->PixelFormat == PixelRedGreenBlueReserved8BitPerColor) ||
  614. ((Mode->PixelFormat == PixelBitMask) &&
  615. (Mode->PixelInformation.RedMask == BCM2709_BGR_RED_MASK))) {
  616. PixelOrder = BCM2709_MAILBOX_PIXEL_ORDER_BGR;
  617. } else {
  618. PixelOrder = BCM2709_MAILBOX_PIXEL_ORDER_RGB;
  619. }
  620. InitializeVideo.PixelOrderMessage.PixelOrder = PixelOrder;
  621. //
  622. // Send the initialization command to the BCM2709 mailbox. This is also a
  623. // GET operation as the frame buffer will be returned. The set actually
  624. // triggers a frame buffer allocation and the frame buffer cannot be
  625. // queried separately.
  626. //
  627. Status = EfipBcm2709MailboxSendCommand(
  628. BCM2709_MAILBOX_PROPERTIES_CHANNEL,
  629. &InitializeVideo,
  630. sizeof(EFI_BCM2709_VIDEO_INITIALIZE),
  631. FALSE);
  632. if (EFI_ERROR(Status)) {
  633. goto Bcm2709VideoInitializeEnd;
  634. }
  635. //
  636. // Check the values that are going to be used.
  637. //
  638. Length = InitializeVideo.PhysicalResolution.TagHeader.Length;
  639. ExpectedLength = sizeof(BCM2709_MAILBOX_RESOLUTION) -
  640. sizeof(BCM2709_MAILBOX_TAG);
  641. if (BCM2709_MAILBOX_CHECK_TAG_LENGTH(Length, ExpectedLength) == FALSE) {
  642. Status = EFI_DEVICE_ERROR;
  643. goto Bcm2709VideoInitializeEnd;
  644. }
  645. Length = InitializeVideo.VirtualResolution.TagHeader.Length;
  646. ExpectedLength = sizeof(BCM2709_MAILBOX_RESOLUTION) -
  647. sizeof(BCM2709_MAILBOX_TAG);
  648. if (BCM2709_MAILBOX_CHECK_TAG_LENGTH(Length, ExpectedLength) == FALSE) {
  649. Status = EFI_DEVICE_ERROR;
  650. goto Bcm2709VideoInitializeEnd;
  651. }
  652. Length = InitializeVideo.BitsPerPixelMessage.TagHeader.Length;
  653. ExpectedLength = sizeof(BCM2709_MAILBOX_BITS_PER_PIXEL) -
  654. sizeof(BCM2709_MAILBOX_TAG);
  655. if (BCM2709_MAILBOX_CHECK_TAG_LENGTH(Length, ExpectedLength) == FALSE) {
  656. Status = EFI_DEVICE_ERROR;
  657. goto Bcm2709VideoInitializeEnd;
  658. }
  659. Length = InitializeVideo.PixelOrderMessage.TagHeader.Length;
  660. ExpectedLength = sizeof(BCM2709_MAILBOX_PIXEL_ORDER) -
  661. sizeof(BCM2709_MAILBOX_TAG);
  662. if (BCM2709_MAILBOX_CHECK_TAG_LENGTH(Length, ExpectedLength) == FALSE) {
  663. Status = EFI_DEVICE_ERROR;
  664. goto Bcm2709VideoInitializeEnd;
  665. }
  666. Length = InitializeVideo.Pitch.TagHeader.Length;
  667. ExpectedLength = sizeof(BCM2709_MAILBOX_PITCH) -
  668. sizeof(BCM2709_MAILBOX_TAG);
  669. if (BCM2709_MAILBOX_CHECK_TAG_LENGTH(Length, ExpectedLength) == FALSE) {
  670. Status = EFI_DEVICE_ERROR;
  671. goto Bcm2709VideoInitializeEnd;
  672. }
  673. Length = InitializeVideo.FrameBufferMessage.TagHeader.Length;
  674. ExpectedLength = sizeof(BCM2709_MAILBOX_FRAME_BUFFER) -
  675. sizeof(BCM2709_MAILBOX_TAG);
  676. if (BCM2709_MAILBOX_CHECK_TAG_LENGTH(Length, ExpectedLength) == FALSE) {
  677. Status = EFI_DEVICE_ERROR;
  678. goto Bcm2709VideoInitializeEnd;
  679. }
  680. //
  681. // Make sure the virtual and physical resolutions match.
  682. //
  683. if ((InitializeVideo.PhysicalResolution.Resolution.Width !=
  684. InitializeVideo.VirtualResolution.Resolution.Width) ||
  685. (InitializeVideo.PhysicalResolution.Resolution.Height !=
  686. InitializeVideo.VirtualResolution.Resolution.Height)) {
  687. Status = EFI_DEVICE_ERROR;
  688. goto Bcm2709VideoInitializeEnd;
  689. }
  690. //
  691. // Make sure the resolution matches the requested modes resolution.
  692. //
  693. if ((InitializeVideo.PhysicalResolution.Resolution.Width != Width) ||
  694. (InitializeVideo.PhysicalResolution.Resolution.Height != Height)) {
  695. Status = EFI_DEVICE_ERROR;
  696. goto Bcm2709VideoInitializeEnd;
  697. }
  698. //
  699. // Make sure the result pixel order matches the requested pixel order.
  700. //
  701. if (InitializeVideo.PixelOrderMessage.PixelOrder != PixelOrder) {
  702. Status = EFI_DEVICE_ERROR;
  703. goto Bcm2709VideoInitializeEnd;
  704. }
  705. //
  706. // Check the pitch. The pixels per scan line better match that of the
  707. // requested mode.
  708. //
  709. PixelsPerScanLine = InitializeVideo.Pitch.BytesPerScanLine /
  710. (InitializeVideo.BitsPerPixelMessage.BitsPerPixel / 8);
  711. if (PixelsPerScanLine != Mode->PixelsPerScanLine) {
  712. Status = EFI_DEVICE_ERROR;
  713. goto Bcm2709VideoInitializeEnd;
  714. }
  715. //
  716. // The video core may return an aliased address out of range for the ARM
  717. // core. Shift the base address until it is accessible by the ARM core.
  718. //
  719. *FrameBufferBase = InitializeVideo.FrameBufferMessage.FrameBuffer.Base;
  720. *FrameBufferBase &= BCM2709_ARM_PHYSICAL_ADDRESS_MASK;
  721. *FrameBufferSize = InitializeVideo.FrameBufferMessage.FrameBuffer.Size;
  722. Status = EFI_SUCCESS;
  723. Bcm2709VideoInitializeEnd:
  724. return Status;
  725. }
  726. VOID
  727. EfipBcm2709VideoInitializeModes (
  728. VOID
  729. )
  730. /*++
  731. Routine Description:
  732. This routine initializes the video modes by adding a mode with the current
  733. resolution to the globally defined list if such a mode does not already
  734. exist.
  735. Arguments:
  736. None.
  737. Return Value:
  738. None.
  739. --*/
  740. {
  741. UINT32 ExpectedLength;
  742. UINT32 Height;
  743. UINT32 Index;
  744. UINT32 Length;
  745. EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Mode;
  746. EFI_STATUS Status;
  747. EFI_BCM2709_VIDEO_GET_MODE VideoMode;
  748. UINT32 Width;
  749. //
  750. // Get the current video mode's resolution.
  751. //
  752. EfiCopyMem(&VideoMode,
  753. &EfiBcm2709GetModeTemplate,
  754. sizeof(EFI_BCM2709_VIDEO_GET_MODE));
  755. Status = EfipBcm2709MailboxSendCommand(
  756. BCM2709_MAILBOX_PROPERTIES_CHANNEL,
  757. &VideoMode,
  758. sizeof(EFI_BCM2709_VIDEO_GET_MODE),
  759. FALSE);
  760. if (EFI_ERROR(Status)) {
  761. goto Bcm2709VideoInitializeModesEnd;
  762. }
  763. //
  764. // Validate the returned data.
  765. //
  766. Length = VideoMode.PhysicalResolution.TagHeader.Length;
  767. ExpectedLength = sizeof(BCM2709_MAILBOX_RESOLUTION) -
  768. sizeof(BCM2709_MAILBOX_TAG);
  769. if (BCM2709_MAILBOX_CHECK_TAG_LENGTH(Length, ExpectedLength) == FALSE) {
  770. goto Bcm2709VideoInitializeModesEnd;
  771. }
  772. Width = VideoMode.PhysicalResolution.Resolution.Width;
  773. Height = VideoMode.PhysicalResolution.Resolution.Height;
  774. //
  775. // Check to see if this resolution matches any of the current resolutions.
  776. //
  777. for (Index = 0; Index < EfiBcm2709VideoModeCount; Index += 1) {
  778. Mode = &(EfiBcm2709VideoModes[Index]);
  779. if ((Mode->HorizontalResolution == Width) &&
  780. (Mode->VerticalResolution == Height)) {
  781. EfiBcm2709VideoModeCount = Index + 1;
  782. goto Bcm2709VideoInitializeModesEnd;
  783. }
  784. }
  785. //
  786. // If there is no more space in the array, then skip it.
  787. //
  788. if (Index >= EFI_BCM2709_VIDEO_MODE_ARRAY_LENGTH) {
  789. goto Bcm2709VideoInitializeModesEnd;
  790. }
  791. //
  792. // Otherwise add this resolution as the next element in the array. The
  793. // pixel format is already set.
  794. //
  795. Mode = &(EfiBcm2709VideoModes[Index]);
  796. Mode->HorizontalResolution = Width;
  797. Mode->VerticalResolution = Height;
  798. Mode->PixelsPerScanLine = Width;
  799. EfiBcm2709VideoModeCount += 1;
  800. Bcm2709VideoInitializeModesEnd:
  801. return;
  802. }