summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulius Werner <jwerner@chromium.org>2016-04-06 12:50:40 -0700
committerJulius Werner <jwerner@chromium.org>2016-04-07 20:46:38 +0200
commit2b6db9738ef6d09a068b65ef472c2d54f99abc37 (patch)
treeab43af5cac7b2d75fbb65705b2c43d1db0e45eca
parent2268e0dc15d076c61792b97e954cad3f7c5f8c00 (diff)
edid: Make framebuffer row alignment configurable
Our EDID code had always been aligning the framebuffer's bytes_per_line (and x_resolution dependent on that) to 64. It turns out that this is a controller-dependent parameter that seems to only really be necessary for Intel chipsets, and commit 6911219cc (edid: Add helper function to calculate bits-per-pixel dependent values) probably actually broke this for some other controllers by applying the alignment too widely. This patch makes it explicitly configurable and depends the default on ARCH_X86 (which seems to be the simplest and least intrusive way to make it fit most cases for now... boards where this doesn't apply can still override it manually by calling edid_set_framebuffer_bits_per_pixel() again). Change-Id: I1c565a72826fc5ddfbb1ae4a5db5e9063b761455 Signed-off-by: Julius Werner <jwerner@chromium.org> Reviewed-on: https://review.coreboot.org/14267 Tested-by: build bot (Jenkins) Reviewed-by: Ronald G. Minnich <rminnich@gmail.com>
-rw-r--r--src/drivers/emulation/qemu/bochs.c2
-rw-r--r--src/drivers/emulation/qemu/cirrus.c2
-rw-r--r--src/include/edid.h3
-rw-r--r--src/lib/edid.c17
-rw-r--r--src/soc/nvidia/tegra124/display.c2
-rw-r--r--src/soc/nvidia/tegra132/dc.c2
-rw-r--r--src/soc/nvidia/tegra210/dc.c2
-rw-r--r--src/soc/rockchip/rk3288/display.c2
8 files changed, 20 insertions, 12 deletions
diff --git a/src/drivers/emulation/qemu/bochs.c b/src/drivers/emulation/qemu/bochs.c
index f32fee008c..74a72471a7 100644
--- a/src/drivers/emulation/qemu/bochs.c
+++ b/src/drivers/emulation/qemu/bochs.c
@@ -113,7 +113,7 @@ static void bochs_init(struct device *dev)
edid.mode.va = height;
edid.panel_bits_per_color = 8;
edid.panel_bits_per_pixel = 24;
- edid_set_framebuffer_bits_per_pixel(&edid, 32);
+ edid_set_framebuffer_bits_per_pixel(&edid, 32, 0);
set_vbe_mode_info_valid(&edid, addr);
#else
vga_misc_write(0x1);
diff --git a/src/drivers/emulation/qemu/cirrus.c b/src/drivers/emulation/qemu/cirrus.c
index 84c2958031..dc20f540ae 100644
--- a/src/drivers/emulation/qemu/cirrus.c
+++ b/src/drivers/emulation/qemu/cirrus.c
@@ -332,7 +332,7 @@ static void cirrus_init(struct device *dev)
edid.mode.va = height;
edid.panel_bits_per_color = 8;
edid.panel_bits_per_pixel = 24;
- edid_set_framebuffer_bits_per_pixel(&edid, 32);
+ edid_set_framebuffer_bits_per_pixel(&edid, 32, 0);
set_vbe_mode_info_valid(&edid, addr);
#else
vga_misc_write(0x1);
diff --git a/src/include/edid.h b/src/include/edid.h
index f46c761935..73412a3304 100644
--- a/src/include/edid.h
+++ b/src/include/edid.h
@@ -93,7 +93,8 @@ struct edid {
/* 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);
+void edid_set_framebuffer_bits_per_pixel(struct edid *edid, int fb_bpp,
+ int row_byte_alignment);
void set_vbe_mode_info_valid(struct edid *edid, uintptr_t fb_addr);
int set_display_mode(struct edid *edid, enum edid_modes mode);
diff --git a/src/lib/edid.c b/src/lib/edid.c
index 52898fbfa6..8bcb95630f 100644
--- a/src/lib/edid.c
+++ b/src/lib/edid.c
@@ -481,9 +481,14 @@ detailed_block(struct edid *result_edid, unsigned char *x, int in_extension,
out->mode.vborder = x[16];
/* We assume rgb888 (32 bits per pixel) framebuffers by default.
- * Chipsets that want something else will need to override this
- * with another call to edid_set_framebuffer_bits_per_pixel(). */
- edid_set_framebuffer_bits_per_pixel(out, 32);
+ * Chipsets that want something else will need to override this with
+ * another call to edid_set_framebuffer_bits_per_pixel(). As a cheap
+ * heuristic, assume that X86 systems require a 64-byte row alignment
+ * (since that seems to be true for most Intel chipsets). */
+ if (IS_ENABLED(CONFIG_ARCH_X86))
+ edid_set_framebuffer_bits_per_pixel(out, 32, 64);
+ else
+ edid_set_framebuffer_bits_per_pixel(out, 32, 0);
switch ((x[17] & 0x18) >> 3) {
case 0x00:
@@ -1524,14 +1529,16 @@ int decode_edid(unsigned char *edid, int size, struct edid *out)
*/
/* Set the framebuffer bits-per-pixel, recalculating all dependent values. */
-void edid_set_framebuffer_bits_per_pixel(struct edid *edid, int fb_bpp)
+void edid_set_framebuffer_bits_per_pixel(struct edid *edid, int fb_bpp,
+ int row_byte_alignment)
{
/* Caller should pass a supported value, everything else is BUG(). */
assert(fb_bpp == 32 || fb_bpp == 24 || fb_bpp == 16);
+ row_byte_alignment = max(row_byte_alignment, 1);
edid->framebuffer_bits_per_pixel = fb_bpp;
edid->bytes_per_line = ALIGN_UP(edid->mode.ha *
- div_round_up(fb_bpp, 8), 64);
+ div_round_up(fb_bpp, 8), row_byte_alignment);
edid->x_resolution = edid->bytes_per_line / (fb_bpp / 8);
edid->y_resolution = edid->mode.va;
}
diff --git a/src/soc/nvidia/tegra124/display.c b/src/soc/nvidia/tegra124/display.c
index 74202bad23..bb96831514 100644
--- a/src/soc/nvidia/tegra124/display.c
+++ b/src/soc/nvidia/tegra124/display.c
@@ -334,6 +334,6 @@ void display_startup(device_t dev)
edid.mode.va = config->yres;
edid.mode.ha = config->xres;
edid_set_framebuffer_bits_per_pixel(&edid,
- config->framebuffer_bits_per_pixel);
+ config->framebuffer_bits_per_pixel, 0);
set_vbe_mode_info_valid(&edid, (uintptr_t)(framebuffer_base_mb*MiB));
}
diff --git a/src/soc/nvidia/tegra132/dc.c b/src/soc/nvidia/tegra132/dc.c
index 562061a1d3..3ae25bc2f5 100644
--- a/src/soc/nvidia/tegra132/dc.c
+++ b/src/soc/nvidia/tegra132/dc.c
@@ -230,7 +230,7 @@ void pass_mode_info_to_payload(
edid.mode.va = config->display_yres;
edid.mode.ha = config->display_xres;
edid_set_framebuffer_bits_per_pixel(&edid,
- config->framebuffer_bits_per_pixel);
+ config->framebuffer_bits_per_pixel, 0);
printk(BIOS_INFO, "%s: bytes_per_line: %d, bits_per_pixel: %d\n "
" x_res x y_res: %d x %d, size: %d\n",
diff --git a/src/soc/nvidia/tegra210/dc.c b/src/soc/nvidia/tegra210/dc.c
index 72f1bcb3fa..88e599defd 100644
--- a/src/soc/nvidia/tegra210/dc.c
+++ b/src/soc/nvidia/tegra210/dc.c
@@ -230,7 +230,7 @@ void pass_mode_info_to_payload(
edid.mode.va = config->display_yres;
edid.mode.ha = config->display_xres;
edid_set_framebuffer_bits_per_pixel(&edid,
- config->framebuffer_bits_per_pixel);
+ config->framebuffer_bits_per_pixel, 0);
printk(BIOS_INFO, "%s: bytes_per_line: %d, bits_per_pixel: %d\n "
" x_res x y_res: %d x %d, size: %d\n",
diff --git a/src/soc/rockchip/rk3288/display.c b/src/soc/rockchip/rk3288/display.c
index 66b2edc5b8..306baad3b6 100644
--- a/src/soc/rockchip/rk3288/display.c
+++ b/src/soc/rockchip/rk3288/display.c
@@ -95,7 +95,7 @@ void rk_display_init(device_t dev, u32 lcdbase,
}
edid_set_framebuffer_bits_per_pixel(&edid,
- conf->framebuffer_bits_per_pixel);
+ conf->framebuffer_bits_per_pixel, 0);
rkvop_mode_set(conf->vop_id, &edid, detected_mode);
rkvop_enable(conf->vop_id, lcdbase, &edid);