Patrick Rudolph has uploaded this change for review.

View Change

[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;
}


To view, visit change 39002. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: coreboot
Gerrit-Branch: master
Gerrit-Change-Id: I7264c2ea2f72f36adfd26f26b00e3ce172133621
Gerrit-Change-Number: 39002
Gerrit-PatchSet: 1
Gerrit-Owner: Patrick Rudolph <patrick.rudolph@9elements.com>
Gerrit-MessageType: newchange