xref: /rk3399_rockchip-uboot/lib/efi_loader/efi_gop.c (revision be8d324191f3cd2f4861629ccf69106d58aaa70f)
1*be8d3241SAlexander Graf /*
2*be8d3241SAlexander Graf  *  EFI application disk support
3*be8d3241SAlexander Graf  *
4*be8d3241SAlexander Graf  *  Copyright (c) 2016 Alexander Graf
5*be8d3241SAlexander Graf  *
6*be8d3241SAlexander Graf  *  SPDX-License-Identifier:     GPL-2.0+
7*be8d3241SAlexander Graf  */
8*be8d3241SAlexander Graf 
9*be8d3241SAlexander Graf #include <common.h>
10*be8d3241SAlexander Graf #include <efi_loader.h>
11*be8d3241SAlexander Graf #include <inttypes.h>
12*be8d3241SAlexander Graf #include <lcd.h>
13*be8d3241SAlexander Graf #include <malloc.h>
14*be8d3241SAlexander Graf 
15*be8d3241SAlexander Graf DECLARE_GLOBAL_DATA_PTR;
16*be8d3241SAlexander Graf 
17*be8d3241SAlexander Graf static const efi_guid_t efi_gop_guid = EFI_GOP_GUID;
18*be8d3241SAlexander Graf 
19*be8d3241SAlexander Graf struct efi_gop_obj {
20*be8d3241SAlexander Graf 	/* Generic EFI object parent class data */
21*be8d3241SAlexander Graf 	struct efi_object parent;
22*be8d3241SAlexander Graf 	/* EFI Interface callback struct for gop */
23*be8d3241SAlexander Graf 	struct efi_gop ops;
24*be8d3241SAlexander Graf 	/* The only mode we support */
25*be8d3241SAlexander Graf 	struct efi_gop_mode_info info;
26*be8d3241SAlexander Graf 	struct efi_gop_mode mode;
27*be8d3241SAlexander Graf };
28*be8d3241SAlexander Graf 
29*be8d3241SAlexander Graf static efi_status_t EFIAPI gop_query_mode(struct efi_gop *this, u32 mode_number,
30*be8d3241SAlexander Graf 					  unsigned long *size_of_info,
31*be8d3241SAlexander Graf 					  struct efi_gop_mode_info **info)
32*be8d3241SAlexander Graf {
33*be8d3241SAlexander Graf 	struct efi_gop_obj *gopobj;
34*be8d3241SAlexander Graf 
35*be8d3241SAlexander Graf 	EFI_ENTRY("%p, %x, %p, %p", this, mode_number, size_of_info, info);
36*be8d3241SAlexander Graf 
37*be8d3241SAlexander Graf 	gopobj = container_of(this, struct efi_gop_obj, ops);
38*be8d3241SAlexander Graf 	*size_of_info = sizeof(gopobj->info);
39*be8d3241SAlexander Graf 	*info = &gopobj->info;
40*be8d3241SAlexander Graf 
41*be8d3241SAlexander Graf 	return EFI_EXIT(EFI_SUCCESS);
42*be8d3241SAlexander Graf }
43*be8d3241SAlexander Graf 
44*be8d3241SAlexander Graf static efi_status_t EFIAPI gop_set_mode(struct efi_gop *this, u32 mode_number)
45*be8d3241SAlexander Graf {
46*be8d3241SAlexander Graf 	EFI_ENTRY("%p, %x", this, mode_number);
47*be8d3241SAlexander Graf 
48*be8d3241SAlexander Graf 	if (mode_number != 0)
49*be8d3241SAlexander Graf 		return EFI_EXIT(EFI_INVALID_PARAMETER);
50*be8d3241SAlexander Graf 
51*be8d3241SAlexander Graf 	return EFI_EXIT(EFI_SUCCESS);
52*be8d3241SAlexander Graf }
53*be8d3241SAlexander Graf 
54*be8d3241SAlexander Graf static efi_status_t EFIAPI gop_blt(struct efi_gop *this, void *buffer,
55*be8d3241SAlexander Graf 				   unsigned long operation, unsigned long sx,
56*be8d3241SAlexander Graf 				   unsigned long sy, unsigned long dx,
57*be8d3241SAlexander Graf 				   unsigned long dy, unsigned long width,
58*be8d3241SAlexander Graf 				   unsigned long height, unsigned long delta)
59*be8d3241SAlexander Graf {
60*be8d3241SAlexander Graf 	int i, j, line_len16, line_len32;
61*be8d3241SAlexander Graf 	void *fb;
62*be8d3241SAlexander Graf 
63*be8d3241SAlexander Graf 	EFI_ENTRY("%p, %p, %lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx", this,
64*be8d3241SAlexander Graf 		  buffer, operation, sx, sy, dx, dy, width, height, delta);
65*be8d3241SAlexander Graf 
66*be8d3241SAlexander Graf 	if (operation != EFI_BLT_BUFFER_TO_VIDEO)
67*be8d3241SAlexander Graf 		return EFI_EXIT(EFI_INVALID_PARAMETER);
68*be8d3241SAlexander Graf 
69*be8d3241SAlexander Graf 	fb = (void*)gd->fb_base;
70*be8d3241SAlexander Graf 	line_len16 = panel_info.vl_col * sizeof(u16);
71*be8d3241SAlexander Graf 	line_len32 = panel_info.vl_col * sizeof(u32);
72*be8d3241SAlexander Graf 
73*be8d3241SAlexander Graf 	/* Copy the contents line by line */
74*be8d3241SAlexander Graf 
75*be8d3241SAlexander Graf 	switch (panel_info.vl_bpix) {
76*be8d3241SAlexander Graf 	case LCD_COLOR32:
77*be8d3241SAlexander Graf 		for (i = 0; i < height; i++) {
78*be8d3241SAlexander Graf 			u32 *dest = fb + ((i + dy)  * line_len32) +
79*be8d3241SAlexander Graf 					 (dx * sizeof(u32));
80*be8d3241SAlexander Graf 			u32 *src = buffer + ((i + sy)  * line_len32) +
81*be8d3241SAlexander Graf 					 (sx * sizeof(u32));
82*be8d3241SAlexander Graf 
83*be8d3241SAlexander Graf 			/* Same color format, just memcpy */
84*be8d3241SAlexander Graf 			memcpy(dest, src, width * sizeof(u32));
85*be8d3241SAlexander Graf 		}
86*be8d3241SAlexander Graf 		break;
87*be8d3241SAlexander Graf 	case LCD_COLOR16:
88*be8d3241SAlexander Graf 		for (i = 0; i < height; i++) {
89*be8d3241SAlexander Graf 			u16 *dest = fb + ((i + dy)  * line_len16) +
90*be8d3241SAlexander Graf 					 (dx * sizeof(u16));
91*be8d3241SAlexander Graf 			u32 *src = buffer + ((i + sy)  * line_len32) +
92*be8d3241SAlexander Graf 					 (sx * sizeof(u32));
93*be8d3241SAlexander Graf 
94*be8d3241SAlexander Graf 			/* Convert from rgb888 to rgb565 */
95*be8d3241SAlexander Graf 			for (j = 0; j < width; j++) {
96*be8d3241SAlexander Graf 				u32 rgb888 = src[j];
97*be8d3241SAlexander Graf 				dest[j] = ((((rgb888 >> (16 + 3)) & 0x1f) << 11) |
98*be8d3241SAlexander Graf 					   (((rgb888 >> (8 + 2)) & 0x3f) << 5) |
99*be8d3241SAlexander Graf 					   (((rgb888 >> (0 + 3)) & 0x1f) << 0));
100*be8d3241SAlexander Graf 			}
101*be8d3241SAlexander Graf 		}
102*be8d3241SAlexander Graf 		break;
103*be8d3241SAlexander Graf 	}
104*be8d3241SAlexander Graf 
105*be8d3241SAlexander Graf 	lcd_sync();
106*be8d3241SAlexander Graf 
107*be8d3241SAlexander Graf 	return EFI_EXIT(EFI_SUCCESS);
108*be8d3241SAlexander Graf }
109*be8d3241SAlexander Graf 
110*be8d3241SAlexander Graf /* This gets called from do_bootefi_exec(). */
111*be8d3241SAlexander Graf int efi_gop_register(void)
112*be8d3241SAlexander Graf {
113*be8d3241SAlexander Graf 	struct efi_gop_obj *gopobj;
114*be8d3241SAlexander Graf 	int line_len;
115*be8d3241SAlexander Graf 
116*be8d3241SAlexander Graf 	switch (panel_info.vl_bpix) {
117*be8d3241SAlexander Graf 	case LCD_COLOR32:
118*be8d3241SAlexander Graf 	case LCD_COLOR16:
119*be8d3241SAlexander Graf 		break;
120*be8d3241SAlexander Graf 	default:
121*be8d3241SAlexander Graf 		/* So far, we only work in 16 or 32 bit mode */
122*be8d3241SAlexander Graf 		return -1;
123*be8d3241SAlexander Graf 	}
124*be8d3241SAlexander Graf 
125*be8d3241SAlexander Graf 	gopobj = calloc(1, sizeof(*gopobj));
126*be8d3241SAlexander Graf 
127*be8d3241SAlexander Graf 	/* Fill in object data */
128*be8d3241SAlexander Graf 	gopobj->parent.protocols[0].guid = &efi_gop_guid;
129*be8d3241SAlexander Graf 	gopobj->parent.protocols[0].open = efi_return_handle;
130*be8d3241SAlexander Graf 	gopobj->parent.handle = &gopobj->ops;
131*be8d3241SAlexander Graf 	gopobj->ops.query_mode = gop_query_mode;
132*be8d3241SAlexander Graf 	gopobj->ops.set_mode = gop_set_mode;
133*be8d3241SAlexander Graf 	gopobj->ops.blt = gop_blt;
134*be8d3241SAlexander Graf 	gopobj->ops.mode = &gopobj->mode;
135*be8d3241SAlexander Graf 
136*be8d3241SAlexander Graf 	gopobj->mode.max_mode = 1;
137*be8d3241SAlexander Graf 	gopobj->mode.info = &gopobj->info;
138*be8d3241SAlexander Graf 	gopobj->mode.info_size = sizeof(gopobj->info);
139*be8d3241SAlexander Graf 	gopobj->mode.fb_base = gd->fb_base;
140*be8d3241SAlexander Graf 	gopobj->mode.fb_size = lcd_get_size(&line_len);
141*be8d3241SAlexander Graf 
142*be8d3241SAlexander Graf 	gopobj->info.version = 0;
143*be8d3241SAlexander Graf 	gopobj->info.width = panel_info.vl_col;
144*be8d3241SAlexander Graf 	gopobj->info.height = panel_info.vl_row;
145*be8d3241SAlexander Graf 	gopobj->info.pixel_format = EFI_GOT_RGBA8;
146*be8d3241SAlexander Graf 	gopobj->info.pixels_per_scanline = panel_info.vl_col;
147*be8d3241SAlexander Graf 
148*be8d3241SAlexander Graf 	/* Hook up to the device list */
149*be8d3241SAlexander Graf 	list_add_tail(&gopobj->parent.link, &efi_obj_list);
150*be8d3241SAlexander Graf 
151*be8d3241SAlexander Graf 	return 0;
152*be8d3241SAlexander Graf }
153