summaryrefslogtreecommitdiffstats
path: root/src/drivers/intel/fsp2_0/graphics.c
blob: a98f3bbba2cd8d71b71a9c037005be1bc5be6fa0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
/* SPDX-License-Identifier: GPL-2.0-or-later */

#include <boot/coreboot_tables.h>
#include <console/console.h>
#include <elog.h>
#include <fsp/graphics.h>
#include <fsp/util.h>
#include <soc/intel/common/vbt.h>
#include <types.h>
#include <framebuffer_info.h>

enum pixel_format {
	pixel_rgbx_8bpc = 0,
	pixel_bgrx_8bpc = 1,
	pixel_bitmask = 2,		/* defined by <rgb>_mask values */
};

static const uint8_t fsp_graphics_info_guid[16] = {
	0xce, 0x2c, 0xf6, 0x39, 0x25, 0x68, 0x69, 0x46,
	0xbb, 0x56, 0x54, 0x1a, 0xba, 0x75, 0x3a, 0x07
};

struct hob_graphics_info {
	uint64_t framebuffer_base;
	uint32_t framebuffer_size;
	uint32_t version;
	uint32_t horizontal_resolution;
	uint32_t vertical_resolution;
	uint32_t pixel_format;		/* See enum pixel_format */
	uint32_t red_mask;
	uint32_t green_mask;
	uint32_t blue_mask;
	uint32_t reserved_mask;
	uint32_t pixels_per_scanline;
} __packed;

struct pixel {
	uint8_t pos;
	uint8_t size;
};

static const struct fsp_framebuffer {
	struct pixel red;
	struct pixel green;
	struct pixel blue;
	struct pixel rsvd;
} fsp_framebuffer_format_map[] = {
	[pixel_rgbx_8bpc] = { {0, 8}, {8, 8}, {16, 8}, {24, 8} },
	[pixel_bgrx_8bpc] = { {16, 8}, {8, 8}, {0, 8}, {24, 8} },
};

enum fw_splash_screen_status {
	FW_SPLASH_SCREEN_DISABLED,
	FW_SPLASH_SCREEN_ENABLED,
};

/* Check and report if an external display is attached */
__weak int fsp_soc_report_external_display(void)
{
	/* Default implementation, on-board display enabled */
	return 0;
}

/*
 * Update elog with Firmware Splash Screen related information
 * based on enum fw_splash_screen_status.
 *
 * Possible values for input argument are:
 * TRUE - FSP initializes display when BMP_LOGO config is enabled.
 * FALSE - Failed to initialize display although BMP_LOGO config is selected.
 *
 * Ignore if BMP_LOGO config is not selected.
 */
static void update_fw_splash_screen_event(enum fw_splash_screen_status status)
{
	if (!CONFIG(BMP_LOGO))
		return;

	elog_add_event_byte(ELOG_TYPE_FW_SPLASH_SCREEN, status);
}

void fsp_report_framebuffer_info(const uintptr_t framebuffer_bar,
				 enum lb_fb_orientation orientation)
{
	size_t size;
	const struct hob_graphics_info *ginfo;
	const struct fsp_framebuffer *fbinfo;

	/*
	 * Pci enumeration happens after silicon init.
	 * After enumeration graphic framebuffer base may be relocated.
	 */
	if (!framebuffer_bar) {
		printk(BIOS_ALERT, "Framebuffer BAR invalid\n");
		update_fw_splash_screen_event(FW_SPLASH_SCREEN_DISABLED);
		return;
	}

	ginfo = fsp_find_extension_hob_by_guid(fsp_graphics_info_guid, &size);

	if (!ginfo) {
		printk(BIOS_ALERT, "Graphics hand-off block not found\n");
		update_fw_splash_screen_event(FW_SPLASH_SCREEN_DISABLED);
		return;
	}

	if (ginfo->pixel_format >= ARRAY_SIZE(fsp_framebuffer_format_map)) {
		printk(BIOS_ALERT, "FSP set unknown framebuffer format: %d\n",
		       ginfo->pixel_format);
		update_fw_splash_screen_event(FW_SPLASH_SCREEN_DISABLED);
		return;
	}

	update_fw_splash_screen_event(FW_SPLASH_SCREEN_ENABLED);
	fbinfo = fsp_framebuffer_format_map + ginfo->pixel_format;

	const struct lb_framebuffer fb = {
		.physical_address    = framebuffer_bar,
		.x_resolution        = ginfo->horizontal_resolution,
		.y_resolution        = ginfo->vertical_resolution,
		.bytes_per_line      = ginfo->pixels_per_scanline * 4,
		.bits_per_pixel      = fbinfo->rsvd.size + fbinfo->red.size +
				       fbinfo->green.size + fbinfo->blue.size,
		.red_mask_pos        = fbinfo->red.pos,
		.red_mask_size       = fbinfo->red.size,
		.green_mask_pos      = fbinfo->green.pos,
		.green_mask_size     = fbinfo->green.size,
		.blue_mask_pos       = fbinfo->blue.pos,
		.blue_mask_size      = fbinfo->blue.size,
		.reserved_mask_pos   = fbinfo->rsvd.pos,
		.reserved_mask_size  = fbinfo->rsvd.size,
		.orientation         = orientation,
		.flags = {
			.has_external_display = fsp_soc_report_external_display(),
		},
	};

	fb_add_framebuffer_info_ex(&fb);
}