Patrick Rudolph has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/39002 )
Change subject: [WIP]lib/edid_fill_fb: Support multiple framebuffers ......................................................................
[WIP]lib/edid_fill_fb: Support multiple framebuffers
Add an implementation that supports multiple framebuffers. This will allow to compile in multiple graphic drivers and select at runtime which one to choose.
Change-Id: I7264c2ea2f72f36adfd26f26b00e3ce172133621 Signed-off-by: Patrick Rudolph patrick.rudolph@9elements.com --- M src/include/edid.h A src/include/framebuffer_info.h M src/lib/edid_fill_fb.c M src/mainboard/google/kukui/mainboard.c 4 files changed, 174 insertions(+), 64 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/02/39002/1
diff --git a/src/include/edid.h b/src/include/edid.h index a97b99b..7c3e9c8 100644 --- a/src/include/edid.h +++ b/src/include/edid.h @@ -104,11 +104,12 @@ EDID_ABSENT, };
+struct edid_fb_info; /* Defined in src/lib/edid.c */ int decode_edid(unsigned char *edid, int size, struct edid *out); void edid_set_framebuffer_bits_per_pixel(struct edid *edid, int fb_bpp, int row_byte_alignment); -void set_vbe_mode_info_valid(const struct edid *edid, uintptr_t fb_addr); +struct edid_fb_info *set_vbe_mode_info_valid(const struct edid *edid, uintptr_t fb_addr); void set_vbe_framebuffer_orientation(enum lb_fb_orientation orientation); int set_display_mode(struct edid *edid, enum edid_modes mode);
diff --git a/src/include/framebuffer_info.h b/src/include/framebuffer_info.h new file mode 100644 index 0000000..6d2f9a6 --- /dev/null +++ b/src/include/framebuffer_info.h @@ -0,0 +1,45 @@ +/* + * Copyright 2013 Google Inc. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but without any warranty; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __FRAMEBUFFER_INFO_H_ +#define __FRAMEBUFFER_INFO_H_ + +#include <stdint.h> +#include <stdbool.h> +#include <commonlib/coreboot_tables.h> + +struct edid_fb_info; +struct edid_fb_info *fb_new_framebuffer_info(void); + +bool fb_fill_framebuffer_info_ex(struct edid_fb_info *info, + uintptr_t fb_addr, uint32_t x_resolution, + uint32_t y_resolution, uint32_t bytes_per_line, + uint8_t bits_per_pixel, uint8_t reserved_mask_pos, + uint8_t reserved_mask_size, uint8_t red_mask_pos, + uint8_t red_mask_size, uint8_t green_mask_pos, + uint8_t green_mask_size, uint8_t blue_mask_pos, + uint8_t blue_mask_size); + +bool fb_fill_framebuffer_info(struct edid_fb_info *info, + uintptr_t fb_addr, uint32_t x_resolution, + uint32_t y_resolution, uint32_t bytes_per_line, + uint8_t bits_per_pixel); + +void fb_fill_framebuffer_set_orientation(struct edid_fb_info *info, + enum lb_fb_orientation orientation); + +#endif /* __FRAMEBUFFER_INFO_H_ */ diff --git a/src/lib/edid_fill_fb.c b/src/lib/edid_fill_fb.c index 1b38ead..3abcdd0 100644 --- a/src/lib/edid_fill_fb.c +++ b/src/lib/edid_fill_fb.c @@ -23,75 +23,137 @@ #include <console/console.h> #include <edid.h> #include <boot/coreboot_tables.h> +#include <framebuffer_info.h> +#include <string.h> +#include <stdlib.h>
-static int fb_valid; -static struct lb_framebuffer edid_fb; +struct edid_fb_info { + bool valid; + struct lb_framebuffer edid_fb; + struct edid_fb_info *next; +}; +static struct edid_fb_info *list; + +/* + * Allocate a new framebuffer info struct on heap. + * Returns NULL on error. + */ +struct edid_fb_info *fb_new_framebuffer_info(void) +{ + struct edid_fb_info *ret; + ret = malloc(sizeof(struct edid_fb_info)); + if (ret) { + memset(ret, 0, sizeof(struct edid_fb_info)); + ret->next = list; + list = ret; + } + return ret; +} + +/* + * Fills a provided framebuffer info struct and sets the valid bit to true. + * Returns false on error. + */ +bool fb_fill_framebuffer_info_ex(struct edid_fb_info *info, + uintptr_t fb_addr, uint32_t x_resolution, + uint32_t y_resolution, uint32_t bytes_per_line, + uint8_t bits_per_pixel, uint8_t reserved_mask_pos, + uint8_t reserved_mask_size, uint8_t red_mask_pos, + uint8_t red_mask_size, uint8_t green_mask_pos, + uint8_t green_mask_size, uint8_t blue_mask_pos, + uint8_t blue_mask_size) +{ + /* Validate */ + if (!info) + return false; + + if (!x_resolution || !y_resolution || !bytes_per_line || !bits_per_pixel) { + printk(BIOS_ERR, "%s: Invalid framebuffer data provided\n", __func__); + return false; + } + + printk(BIOS_INFO, "framebuffer_info: bytes_per_line: %d, bits_per_pixel: %d\n " + " x_res x y_res: %d x %d, size: %d at %p\n", + bytes_per_line, bits_per_pixel, x_resolution, + y_resolution, (bytes_per_line * y_resolution), + (void *)fb_addr); + + /* Update */ + info->edid_fb.physical_address = fb_addr; + info->edid_fb.x_resolution = x_resolution; + info->edid_fb.y_resolution = y_resolution; + info->edid_fb.bytes_per_line = bytes_per_line; + info->edid_fb.bits_per_pixel = bits_per_pixel; + info->edid_fb.reserved_mask_pos = reserved_mask_pos; + info->edid_fb.reserved_mask_size = reserved_mask_size; + info->edid_fb.red_mask_pos = red_mask_pos; + info->edid_fb.red_mask_size = red_mask_size; + info->edid_fb.green_mask_pos = green_mask_pos; + info->edid_fb.green_mask_size = green_mask_size; + info->edid_fb.blue_mask_pos = blue_mask_pos; + info->edid_fb.blue_mask_size = blue_mask_size; + info->valid = true; + + return true; +} + +/* Fills a framebuffer into struct with common values for 32/24/16bpp framebuffers */ +bool fb_fill_framebuffer_info(struct edid_fb_info *info, + uintptr_t fb_addr, uint32_t x_resolution, + uint32_t y_resolution, uint32_t bytes_per_line, + uint8_t bits_per_pixel) +{ + if (!info) + return false; + + switch (bits_per_pixel) { + case 32: + case 24: + /* packed into 4-byte words */ + return fb_fill_framebuffer_info_ex(info, fb_addr, x_resolution, y_resolution, + bytes_per_line, bits_per_pixel, 24, 8, 16, 8, 8, 8, 0, 8); + break; + case 16: + /* packed into 2-byte words */ + return fb_fill_framebuffer_info_ex(info, fb_addr, x_resolution, y_resolution, + bytes_per_line, bits_per_pixel, 0, 0, 11, 5, 5, 6, 0, 5); + break; + default: + printk(BIOS_SPEW, "%s: unsupported BPP %d\n", __func__, bits_per_pixel); + return false; + } + return true; +} + +void fb_fill_framebuffer_set_orientation(struct edid_fb_info *info, + enum lb_fb_orientation orientation) +{ + if (!info) + return; + + info->edid_fb.orientation = orientation; +}
/* * Take an edid, and create a framebuffer. Set fb_valid to 1. */ -void set_vbe_mode_info_valid(const struct edid *edid, uintptr_t fb_addr) +struct edid_fb_info *set_vbe_mode_info_valid(const struct edid *edid, uintptr_t fb_addr) { - edid_fb.physical_address = fb_addr; - edid_fb.x_resolution = edid->x_resolution; - edid_fb.y_resolution = edid->y_resolution; - edid_fb.bytes_per_line = edid->bytes_per_line; - /* In the case of (e.g.) 24 framebuffer bits per pixel, the convention - * nowadays seems to be to round it up to the nearest reasonable - * boundary, because otherwise the byte-packing is hideous. - * So, for example, in RGB with no alpha, the bytes are still - * packed into 32-bit words, the so-called 32bpp-no-alpha mode. - * Or, in 5:6:5 mode, the bytes are also packed into 32-bit words, - * and in 4:4:4 mode, they are packed into 16-bit words. - * Good call on the hardware guys part. - * It's not clear we're covering all cases here, but - * I'm not sure with grahpics you ever can. - */ - edid_fb.bits_per_pixel = edid->framebuffer_bits_per_pixel; - edid_fb.reserved_mask_pos = 0; - edid_fb.reserved_mask_size = 0; - switch (edid->framebuffer_bits_per_pixel) { - case 32: - case 24: - /* packed into 4-byte words */ - edid_fb.reserved_mask_pos = 24; - edid_fb.reserved_mask_size = 8; - edid_fb.red_mask_pos = 16; - edid_fb.red_mask_size = 8; - edid_fb.green_mask_pos = 8; - edid_fb.green_mask_size = 8; - edid_fb.blue_mask_pos = 0; - edid_fb.blue_mask_size = 8; - break; - case 16: - /* packed into 2-byte words */ - edid_fb.red_mask_pos = 11; - edid_fb.red_mask_size = 5; - edid_fb.green_mask_pos = 5; - edid_fb.green_mask_size = 6; - edid_fb.blue_mask_pos = 0; - edid_fb.blue_mask_size = 5; - break; - default: - printk(BIOS_SPEW, "%s: unsupported BPP %d\n", __func__, - edid->framebuffer_bits_per_pixel); - return; - } - - fb_valid = 1; -} - -void set_vbe_framebuffer_orientation(enum lb_fb_orientation orientation) -{ - edid_fb.orientation = orientation; + struct edid_fb_info *info = fb_new_framebuffer_info(); + if (!info) + return NULL; + fb_fill_framebuffer_info(info, fb_addr, edid->x_resolution, edid->y_resolution, + edid->bytes_per_line, edid->framebuffer_bits_per_pixel); + return info; }
int fill_lb_framebuffer(struct lb_framebuffer *framebuffer) { - if (!fb_valid) - return -1; - - *framebuffer = edid_fb; - - return 0; + for (struct edid_fb_info *i = list; i != NULL; i = i->next) { + if (i->valid) { + *framebuffer = i->edid_fb; + return 0; + } + } + return -1; } diff --git a/src/mainboard/google/kukui/mainboard.c b/src/mainboard/google/kukui/mainboard.c index 844496d..4033d51 100644 --- a/src/mainboard/google/kukui/mainboard.c +++ b/src/mainboard/google/kukui/mainboard.c @@ -172,8 +172,10 @@ return false; } mtk_ddp_mode_set(edid); - set_vbe_mode_info_valid(edid, 0); - set_vbe_framebuffer_orientation(panel->s->orientation); + struct edid_fb_info *info = set_vbe_mode_info_valid(edid, 0); + if (info) + fb_fill_framebuffer_set_orientation(info, panel->s->orientation); + return true; }