1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com>
5 * EFI framebuffer driver based on GOP
19 static const struct efi_framebuffer
{
24 } efi_framebuffer_format_map
[] = {
25 [EFI_GOT_RGBA8
] = { {0, 8}, {8, 8}, {16, 8}, {24, 8} },
26 [EFI_GOT_BGRA8
] = { {16, 8}, {8, 8}, {0, 8}, {24, 8} },
29 static void efi_find_pixel_bits(u32 mask
, u8
*pos
, u8
*size
)
37 while (!(mask
& 0x1)) {
52 static int save_vesa_mode(struct vesa_mode_info
*vesa
)
54 struct efi_entry_gopmode
*mode
;
55 const struct efi_framebuffer
*fbinfo
;
59 ret
= efi_info_get(EFIET_GOP_MODE
, (void **)&mode
, &size
);
61 debug("efi graphics output protocol mode not found\n");
65 vesa
->phys_base_ptr
= mode
->fb_base
;
66 vesa
->x_resolution
= mode
->info
->width
;
67 vesa
->y_resolution
= mode
->info
->height
;
69 if (mode
->info
->pixel_format
< EFI_GOT_BITMASK
) {
70 fbinfo
= &efi_framebuffer_format_map
[mode
->info
->pixel_format
];
71 vesa
->red_mask_size
= fbinfo
->red
.size
;
72 vesa
->red_mask_pos
= fbinfo
->red
.pos
;
73 vesa
->green_mask_size
= fbinfo
->green
.size
;
74 vesa
->green_mask_pos
= fbinfo
->green
.pos
;
75 vesa
->blue_mask_size
= fbinfo
->blue
.size
;
76 vesa
->blue_mask_pos
= fbinfo
->blue
.pos
;
77 vesa
->reserved_mask_size
= fbinfo
->rsvd
.size
;
78 vesa
->reserved_mask_pos
= fbinfo
->rsvd
.pos
;
80 vesa
->bits_per_pixel
= 32;
81 vesa
->bytes_per_scanline
= mode
->info
->pixels_per_scanline
* 4;
82 } else if (mode
->info
->pixel_format
== EFI_GOT_BITMASK
) {
83 efi_find_pixel_bits(mode
->info
->pixel_bitmask
[0],
85 &vesa
->red_mask_size
);
86 efi_find_pixel_bits(mode
->info
->pixel_bitmask
[1],
87 &vesa
->green_mask_pos
,
88 &vesa
->green_mask_size
);
89 efi_find_pixel_bits(mode
->info
->pixel_bitmask
[2],
91 &vesa
->blue_mask_size
);
92 efi_find_pixel_bits(mode
->info
->pixel_bitmask
[3],
93 &vesa
->reserved_mask_pos
,
94 &vesa
->reserved_mask_size
);
95 vesa
->bits_per_pixel
= vesa
->red_mask_size
+
96 vesa
->green_mask_size
+
97 vesa
->blue_mask_size
+
98 vesa
->reserved_mask_size
;
99 vesa
->bytes_per_scanline
= (mode
->info
->pixels_per_scanline
*
100 vesa
->bits_per_pixel
) / 8;
102 debug("efi set unknown framebuffer format: %d\n",
103 mode
->info
->pixel_format
);
110 static int efi_video_probe(struct udevice
*dev
)
112 struct video_uc_platdata
*plat
= dev_get_uclass_platdata(dev
);
113 struct video_priv
*uc_priv
= dev_get_uclass_priv(dev
);
114 struct vesa_mode_info
*vesa
= &mode_info
.vesa
;
117 /* Initialize vesa_mode_info structure */
118 ret
= save_vesa_mode(vesa
);
122 ret
= vbe_setup_video_priv(vesa
, uc_priv
, plat
);
126 printf("Video: %dx%dx%d\n", uc_priv
->xsize
, uc_priv
->ysize
,
127 vesa
->bits_per_pixel
);
132 printf("No video mode configured in EFI!\n");
136 static const struct udevice_id efi_video_ids
[] = {
137 { .compatible
= "efi-fb" },
141 U_BOOT_DRIVER(efi_video
) = {
144 .of_match
= efi_video_ids
,
145 .probe
= efi_video_probe
,