Patrick Rudolph has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/35726 )
Change subject: drivers/aspeed/common: Add support for high resolution framebuffer ......................................................................
drivers/aspeed/common: Add support for high resolution framebuffer
Implement reading EDID over software I2C. Copy the linux kernel code and add a bunch of wrapper structs to make it compile. Convert the EDID to a drm_display_mode, which is understood by the driver.
Tested on Supermicro X11SSH-TF using FullHD VGA monitor. Initializes the graphics in about 1 second, which is twice as fast as the VGA Option ROM.
The framebuffer is advertised and woring in tianocore.
Change-Id: I7803566b64158405efc04a39f80a0ec98b44e646 Signed-off-by: Patrick Rudolph patrick.rudolph@9elements.com --- M src/drivers/aspeed/ast2050/Kconfig M src/drivers/aspeed/ast2050/ast2050.c M src/drivers/aspeed/common/Kconfig M src/drivers/aspeed/common/Makefile.inc M src/drivers/aspeed/common/ast_drv.h A src/drivers/aspeed/common/ast_i2c.c A src/drivers/aspeed/common/ast_mode.c M src/drivers/aspeed/common/ast_tables.h 8 files changed, 1,159 insertions(+), 85 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/26/35726/1
diff --git a/src/drivers/aspeed/ast2050/Kconfig b/src/drivers/aspeed/ast2050/Kconfig index 337b181..7d2c728 100644 --- a/src/drivers/aspeed/ast2050/Kconfig +++ b/src/drivers/aspeed/ast2050/Kconfig @@ -1,5 +1,4 @@ config DRIVERS_ASPEED_AST2050 bool select DRIVERS_ASPEED_AST_COMMON - select HAVE_VGA_TEXT_FRAMEBUFFER select MAINBOARD_HAS_NATIVE_VGA_INIT diff --git a/src/drivers/aspeed/ast2050/ast2050.c b/src/drivers/aspeed/ast2050/ast2050.c index 59659b8..01d58f9 100644 --- a/src/drivers/aspeed/ast2050/ast2050.c +++ b/src/drivers/aspeed/ast2050/ast2050.c @@ -34,6 +34,7 @@ pci_dev_set_resources(dev); }
+ static void aspeed_ast2050_init(struct device *dev) { struct drm_device drm_dev; @@ -50,13 +51,19 @@ outb(0xa6, 0x3d4); outb(0x2f, 0x3d5); outb(0xa7, 0x3d4); outb(0x3f, 0x3d5);
- /* Initialize standard VGA text mode */ - vga_io_init(); - vga_textmode_init(); - printk(BIOS_INFO, "ASpeed VGA text mode initialized\n"); + if (CONFIG(VGA_TEXT_FRAMEBUFFER)) { + /* Initialize standard VGA text mode */ + vga_io_init();
- /* if we don't have console, at least print something... */ - vga_line_write(0, "ASpeed VGA text mode initialized"); + vga_textmode_init(); + printk(BIOS_INFO, "ASpeed VGA text mode initialized\n"); + + /* if we don't have console, at least print something... */ + vga_line_write(0, "ASpeed VGA text mode initialized"); + } else if (CONFIG(GENERIC_LINEAR_FRAMEBUFFER)) { + ast_driver_framebuffer_init(&drm_dev, 0); + printk(BIOS_INFO, "ASpeed high resolution framebuffer initialized\n"); + } }
static struct device_operations aspeed_ast2050_ops = { diff --git a/src/drivers/aspeed/common/Kconfig b/src/drivers/aspeed/common/Kconfig index 653782f..c292bcf 100644 --- a/src/drivers/aspeed/common/Kconfig +++ b/src/drivers/aspeed/common/Kconfig @@ -1,3 +1,12 @@ config DRIVERS_ASPEED_AST_COMMON bool - select VGA + select HAVE_LINEAR_FRAMEBUFFER + select HAVE_VGA_TEXT_FRAMEBUFFER + select VGA if VGA_TEXT_FRAMEBUFFER + select SOFTWARE_I2C if GENERIC_LINEAR_FRAMEBUFFER + +config DRIVERS_ASPEED_I2C_BUS + int + depends on DRIVERS_ASPEED_AST_COMMON + depends on SOFTWARE_I2C + default 0 diff --git a/src/drivers/aspeed/common/Makefile.inc b/src/drivers/aspeed/common/Makefile.inc index 75f8b48..01e09a1 100644 --- a/src/drivers/aspeed/common/Makefile.inc +++ b/src/drivers/aspeed/common/Makefile.inc @@ -1 +1,4 @@ -ramstage-$(CONFIG_DRIVERS_ASPEED_AST_COMMON) += ast_dp501.c ast_main.c ast_post.c +ifeq ($(CONFIG_DRIVERS_ASPEED_AST_COMMON),y) +ramstage-y += ast_dp501.c ast_main.c ast_post.c +ramstage-$(CONFIG_GENERIC_LINEAR_FRAMEBUFFER) += ast_mode.c ast_i2c.c +endif diff --git a/src/drivers/aspeed/common/ast_drv.h b/src/drivers/aspeed/common/ast_drv.h index 53640f1..b46e98a 100644 --- a/src/drivers/aspeed/common/ast_drv.h +++ b/src/drivers/aspeed/common/ast_drv.h @@ -44,6 +44,7 @@ AST2150, AST2300, AST2400, + AST2500, AST1180, };
@@ -190,6 +191,8 @@ #define AST_HWC_SIZE (AST_MAX_HWC_WIDTH*AST_MAX_HWC_HEIGHT*2) #define AST_HWC_SIGNATURE_SIZE 32
+#define EINVAL 22 /* Invalid argument */ + #define AST_DEFAULT_HWC_NUM 2 /* define for signature structure */ #define AST_HWC_SIGNATURE_CHECKSUM 0x00 @@ -200,6 +203,98 @@ #define AST_HWC_SIGNATURE_HOTSPOTX 0x14 #define AST_HWC_SIGNATURE_HOTSPOTY 0x18
+/* ast_mode.c stuff */ +struct ast_vbios_stdtable { + u8 misc; + u8 seq[4]; + u8 crtc[25]; + u8 ar[20]; + u8 gr[9]; +}; + +struct ast_vbios_enhtable { + u32 ht; + u32 hde; + u32 hfp; + u32 hsync; + u32 vt; + u32 vde; + u32 vfp; + u32 vsync; + u32 dclk_index; + u32 flags; + u32 refresh_rate; + u32 refresh_rate_index; + u32 mode_id; +}; + +struct ast_vbios_dclk_info { + u8 param1; + u8 param2; + u8 param3; +}; + +struct ast_vbios_mode_info { + const struct ast_vbios_stdtable *std_table; + const struct ast_vbios_enhtable *enh_table; +}; + +#define DRM_MODE_FLAG_NVSYNC NVSync +#define DRM_MODE_FLAG_PVSYNC PVSync +#define DRM_MODE_FLAG_NHSYNC NHSync +#define DRM_MODE_FLAG_PHSYNC PHSync + +struct drm_display_mode { + /* Proposed mode values */ + u16 vrefresh; /* in Hz */ + u32 clock; + u16 hdisplay; + u16 vdisplay; + u32 flags; + + /* Actual mode we give to hw */ + u16 crtc_hdisplay; + u16 crtc_htotal; + u16 crtc_hblank_start; + u16 crtc_hblank_end; + u16 crtc_hsync_start; + u16 crtc_hsync_end; + u16 crtc_vtotal; + u16 crtc_vsync_start; + u16 crtc_vsync_end; + u16 crtc_vdisplay; + u16 crtc_vblank_start; + u16 crtc_vblank_end; +}; + +struct drm_format { + u32 cpp[1]; /* Colors per pixel */ +}; + +struct drm_framebuffer { + u32 pitches[1]; + struct drm_format *format; +}; + +struct drm_primary { + struct drm_framebuffer *fb; +}; + +struct drm_crtc { + struct drm_device *dev; + struct drm_primary *primary; + struct drm_display_mode mode; +}; + +struct drm_connector { + struct drm_device *dev; +}; + +enum drm_mode_status { + MODE_NOMODE, + MODE_OK +}; + #define AST_MM_ALIGN_SHIFT 4 #define AST_MM_ALIGN_MASK ((1 << AST_MM_ALIGN_SHIFT) - 1)
@@ -220,4 +315,12 @@ bool ast_dp501_read_edid(struct drm_device *dev, u8 *ediddata); u8 ast_get_dp501_max_clk(struct drm_device *dev); void ast_init_3rdtx(struct drm_device *dev); + +/* ast mode */ +int ast_driver_framebuffer_init(struct drm_device *dev, int flags); + +/* ast i2c */ +void ast_software_i2c_init(unsigned bus); +int ast_software_i2c_read(unsigned bus, struct ast_private *ast_priv, uint8_t edid[256]); + #endif diff --git a/src/drivers/aspeed/common/ast_i2c.c b/src/drivers/aspeed/common/ast_i2c.c new file mode 100644 index 0000000..92cce3d --- /dev/null +++ b/src/drivers/aspeed/common/ast_i2c.c @@ -0,0 +1,137 @@ + +/* + * Copied from Linux drivers/gpu/drm/ast/ast_mode.c + * + * Copyright 2012 Red Hat Inc. + * Parts based on xf86-video-ast + * Copyright (c) 2005 ASPEED Technology Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + */ +/* + * Authors: Dave Airlie airlied@redhat.com + * Authors: 9Elements Agency GmbH patrick.rudolph@9elements.com + */ +#include <delay.h> +#include <device/i2c_simple.h> + +#include "ast_drv.h" + +#if CONFIG_DRIVER_TPM_I2C_BUS == CONFIG_DRIVERS_ASPEED_I2C_BUS +#error Software I2C bus collision! +#endif + +#if CONFIG_EC_GOOGLE_CHROMEEC_I2C_BUS == CONFIG_DRIVERS_ASPEED_I2C_BUS +#error Software I2C bus collision! +#endif + +static struct ast_private *ast; + +static int get_clock(unsigned int bus) +{ + uint32_t val, val2, count, pass; + + count = 0; + pass = 0; + val = (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x10) >> 4) & 0x01; + do { + val2 = (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x10) >> 4) & 0x01; + if (val == val2) { + pass++; + } else { + pass = 0; + val = (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x10) >> 4) & 0x01; + } + } while ((pass < 5) && (count++ < 0x10000)); + + return val & 1 ? 1 : 0; +} + +static int get_data(unsigned int bus) +{ + uint32_t val, val2, count, pass; + + count = 0; + pass = 0; + val = (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x20) >> 5) & 0x01; + do { + val2 = (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x20) >> 5) & 0x01; + if (val == val2) { + pass++; + } else { + pass = 0; + val = (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x20) >> 5) & 0x01; + } + } while ((pass < 5) && (count++ < 0x10000)); + + return val & 1 ? 1 : 0; +} + +static void set_clock(unsigned int bus, int clock) +{ + int i; + u8 ujcrb7, jtemp; + + for (i = 0; i < 0x10000; i++) { + ujcrb7 = ((clock & 0x01) ? 0 : 1); + ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0xf4, ujcrb7); + jtemp = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x01); + if (ujcrb7 == jtemp) + break; + } +} + +static void set_data(unsigned int bus, int data) +{ + int i; + u8 ujcrb7, jtemp; + + for (i = 0; i < 0x10000; i++) { + ujcrb7 = ((data & 0x01) ? 0 : 1) << 2; + ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0xf1, ujcrb7); + jtemp = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x04); + if (ujcrb7 == jtemp) + break; + } +} + +static struct software_i2c_ops ast_ops = { + .set_sda = set_data, + .set_scl = set_clock, + .get_sda = get_data, + .get_scl = get_clock, +}; + +void ast_software_i2c_init(unsigned bus) +{ + software_i2c[bus] = &ast_ops; + + i2c_recover_bus(bus); +} + +int ast_software_i2c_read(unsigned bus, struct ast_private *ast_priv, uint8_t edid[256]) +{ + ast = ast_priv; + + /* Need to reset internal EEPROM counter to 0 */ + return i2c_read_bytes(bus, 0x50, 0, edid, 256); +} diff --git a/src/drivers/aspeed/common/ast_mode.c b/src/drivers/aspeed/common/ast_mode.c new file mode 100644 index 0000000..b321f5d --- /dev/null +++ b/src/drivers/aspeed/common/ast_mode.c @@ -0,0 +1,777 @@ + +/* + * Copied from Linux drivers/gpu/drm/ast/ast_mode.c + * + * Copyright 2012 Red Hat Inc. + * Parts based on xf86-video-ast + * Copyright (c) 2005 ASPEED Technology Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + */ +/* + * Authors: Dave Airlie airlied@redhat.com + * Authors: 9Elements Agency GmbH patrick.rudolph@9elements.com + */ +#include <edid.h> +#include <device/i2c_simple.h> + +#include "ast_drv.h" +#include "ast_tables.h" + + +static inline void ast_load_palette_index(struct ast_private *ast, + u8 index, u8 red, u8 green, + u8 blue) +{ + ast_io_write8(ast, AST_IO_DAC_INDEX_WRITE, index); + ast_io_read8(ast, AST_IO_SEQ_PORT); + ast_io_write8(ast, AST_IO_DAC_DATA, red); + ast_io_read8(ast, AST_IO_SEQ_PORT); + ast_io_write8(ast, AST_IO_DAC_DATA, green); + ast_io_read8(ast, AST_IO_SEQ_PORT); + ast_io_write8(ast, AST_IO_DAC_DATA, blue); + ast_io_read8(ast, AST_IO_SEQ_PORT); +} + +static void ast_crtc_load_lut(struct drm_crtc *crtc) +{ + struct ast_private *ast = crtc->dev->dev_private; + /* FIXME: Gamma cor 2.6 ? */ + for (int i = 0; i < 256; i++) + ast_load_palette_index(ast, i, i, i, i); + +} + +static bool ast_get_vbios_mode_info(struct drm_crtc *crtc, struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode, + struct ast_vbios_mode_info *vbios_mode) +{ + struct ast_private *ast = crtc->dev->dev_private; + const struct drm_framebuffer *fb = crtc->primary->fb; + u32 refresh_rate_index = 0, mode_id, color_index, refresh_rate; + const struct ast_vbios_enhtable *best = NULL; + u32 hborder, vborder; + bool check_sync; + dev_err(crtc->dev->pdev, "fb->format->cpp[0] * 8 = %d\n", fb->format->cpp[0] * 8); + + switch (fb->format->cpp[0] * 8) { + case 8: + vbios_mode->std_table = &vbios_stdtable[VGAModeIndex]; + color_index = VGAModeIndex - 1; + break; + case 16: + vbios_mode->std_table = &vbios_stdtable[HiCModeIndex]; + color_index = HiCModeIndex; + break; + case 24: + case 32: + vbios_mode->std_table = &vbios_stdtable[TrueCModeIndex]; + color_index = TrueCModeIndex; + break; + default: + return false; + } + dev_err(crtc->dev->pdev, "crtc->mode.crtc_hdisplay = %d\n", crtc->mode.crtc_hdisplay); + + switch (crtc->mode.crtc_hdisplay) { + case 640: + vbios_mode->enh_table = &res_640x480[refresh_rate_index]; + break; + case 800: + vbios_mode->enh_table = &res_800x600[refresh_rate_index]; + break; + case 1024: + vbios_mode->enh_table = &res_1024x768[refresh_rate_index]; + break; + case 1280: + if (crtc->mode.crtc_vdisplay == 800) + vbios_mode->enh_table = &res_1280x800[refresh_rate_index]; + else + vbios_mode->enh_table = &res_1280x1024[refresh_rate_index]; + break; + case 1360: + vbios_mode->enh_table = &res_1360x768[refresh_rate_index]; + break; + case 1440: + vbios_mode->enh_table = &res_1440x900[refresh_rate_index]; + break; + case 1600: + if (crtc->mode.crtc_vdisplay == 900) + vbios_mode->enh_table = &res_1600x900[refresh_rate_index]; + else + vbios_mode->enh_table = &res_1600x1200[refresh_rate_index]; + break; + case 1680: + vbios_mode->enh_table = &res_1680x1050[refresh_rate_index]; + break; + case 1920: + if (crtc->mode.crtc_vdisplay == 1080) + vbios_mode->enh_table = &res_1920x1080[refresh_rate_index]; + else + vbios_mode->enh_table = &res_1920x1200[refresh_rate_index]; + break; + default: + return false; + } + + refresh_rate = mode->vrefresh; + check_sync = vbios_mode->enh_table->flags & WideScreenMode; + do { + const struct ast_vbios_enhtable *loop = vbios_mode->enh_table; + + while (loop->refresh_rate != 0xff) { + if ((check_sync) && + (((mode->flags & DRM_MODE_FLAG_NVSYNC) && + (loop->flags & PVSync)) || + ((mode->flags & DRM_MODE_FLAG_PVSYNC) && + (loop->flags & NVSync)) || + ((mode->flags & DRM_MODE_FLAG_NHSYNC) && + (loop->flags & PHSync)) || + ((mode->flags & DRM_MODE_FLAG_PHSYNC) && + (loop->flags & NHSync)))) { + loop++; + continue; + } + if (loop->refresh_rate <= refresh_rate + && (!best || loop->refresh_rate > best->refresh_rate)) + best = loop; + loop++; + } + if (best || !check_sync) + break; + check_sync = 0; + } while (1); + if (best) + vbios_mode->enh_table = best; + + hborder = (vbios_mode->enh_table->flags & HBorder) ? 8 : 0; + vborder = (vbios_mode->enh_table->flags & VBorder) ? 8 : 0; + + adjusted_mode->crtc_htotal = vbios_mode->enh_table->ht; + adjusted_mode->crtc_hblank_start = vbios_mode->enh_table->hde + hborder; + adjusted_mode->crtc_hblank_end = vbios_mode->enh_table->ht - hborder; + adjusted_mode->crtc_hsync_start = vbios_mode->enh_table->hde + hborder + + vbios_mode->enh_table->hfp; + adjusted_mode->crtc_hsync_end = (vbios_mode->enh_table->hde + hborder + + vbios_mode->enh_table->hfp + + vbios_mode->enh_table->hsync); + + adjusted_mode->crtc_vtotal = vbios_mode->enh_table->vt; + adjusted_mode->crtc_vblank_start = vbios_mode->enh_table->vde + vborder; + adjusted_mode->crtc_vblank_end = vbios_mode->enh_table->vt - vborder; + adjusted_mode->crtc_vsync_start = vbios_mode->enh_table->vde + vborder + + vbios_mode->enh_table->vfp; + adjusted_mode->crtc_vsync_end = (vbios_mode->enh_table->vde + vborder + + vbios_mode->enh_table->vfp + + vbios_mode->enh_table->vsync); + + refresh_rate_index = vbios_mode->enh_table->refresh_rate_index; + mode_id = vbios_mode->enh_table->mode_id; + + if (ast->chip == AST1180) { + /* TODO 1180 */ + } else { + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x8c, (u8)((color_index & 0xf) << 4)); + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x8d, refresh_rate_index & 0xff); + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x8e, mode_id & 0xff); + + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x91, 0x00); + if (vbios_mode->enh_table->flags & NewModeInfo) { + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x91, 0xa8); + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x92, + fb->format->cpp[0] * 8); + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x93, adjusted_mode->clock / 1000); + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x94, adjusted_mode->crtc_hdisplay); + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x95, adjusted_mode->crtc_hdisplay >> 8); + + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x96, adjusted_mode->crtc_vdisplay); + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x97, adjusted_mode->crtc_vdisplay >> 8); + } + } + + return true; +} + +static void ast_set_std_reg(struct drm_crtc *crtc, struct drm_display_mode *mode, + struct ast_vbios_mode_info *vbios_mode) +{ + struct ast_private *ast = crtc->dev->dev_private; + const struct ast_vbios_stdtable *stdtable; + u32 i; + u8 jreg; + + /* Only 32 BPP support */ + stdtable = &vbios_stdtable[TrueCModeIndex]; + + jreg = stdtable->misc; + ast_io_write8(ast, AST_IO_MISC_PORT_WRITE, jreg); + + /* Set SEQ */ + ast_set_index_reg(ast, AST_IO_SEQ_PORT, 0x00, 0x03); + for (i = 0; i < 4; i++) { + jreg = stdtable->seq[i]; + if (!i) + jreg |= 0x20; + ast_set_index_reg(ast, AST_IO_SEQ_PORT, (i + 1) , jreg); + } + + /* Set CRTC */ + ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x11, 0x7f, 0x00); + for (i = 0; i < 25; i++) + ast_set_index_reg(ast, AST_IO_CRTC_PORT, i, stdtable->crtc[i]); + + /* set AR */ + jreg = ast_io_read8(ast, AST_IO_INPUT_STATUS1_READ); + for (i = 0; i < 20; i++) { + jreg = stdtable->ar[i]; + ast_io_write8(ast, AST_IO_AR_PORT_WRITE, (u8)i); + ast_io_write8(ast, AST_IO_AR_PORT_WRITE, jreg); + } + ast_io_write8(ast, AST_IO_AR_PORT_WRITE, 0x14); + ast_io_write8(ast, AST_IO_AR_PORT_WRITE, 0x00); + + jreg = ast_io_read8(ast, AST_IO_INPUT_STATUS1_READ); + ast_io_write8(ast, AST_IO_AR_PORT_WRITE, 0x20); + + /* Set GR */ + for (i = 0; i < 9; i++) + ast_set_index_reg(ast, AST_IO_GR_PORT, i, stdtable->gr[i]); +} + +static void ast_set_crtc_reg(struct drm_crtc *crtc, struct drm_display_mode *mode, + struct ast_vbios_mode_info *vbios_mode) +{ + struct ast_private *ast = crtc->dev->dev_private; + u8 jreg05 = 0, jreg07 = 0, jreg09 = 0, jregAC = 0, jregAD = 0, jregAE = 0; + u16 temp, precache = 0; + + if ((ast->chip == AST2500) && + (vbios_mode->enh_table->flags & AST2500PreCatchCRT)) + precache = 40; + + ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x11, 0x7f, 0x00); + + temp = (mode->crtc_htotal >> 3) - 5; + if (temp & 0x100) + jregAC |= 0x01; /* HT D[8] */ + ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x00, 0x00, temp); + + temp = (mode->crtc_hdisplay >> 3) - 1; + if (temp & 0x100) + jregAC |= 0x04; /* HDE D[8] */ + ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x01, 0x00, temp); + + temp = (mode->crtc_hblank_start >> 3) - 1; + if (temp & 0x100) + jregAC |= 0x10; /* HBS D[8] */ + ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x02, 0x00, temp); + + temp = ((mode->crtc_hblank_end >> 3) - 1) & 0x7f; + if (temp & 0x20) + jreg05 |= 0x80; /* HBE D[5] */ + if (temp & 0x40) + jregAD |= 0x01; /* HBE D[5] */ + ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x03, 0xE0, (temp & 0x1f)); + + temp = ((mode->crtc_hsync_start-precache) >> 3) - 1; + if (temp & 0x100) + jregAC |= 0x40; /* HRS D[5] */ + ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x04, 0x00, temp); + + temp = (((mode->crtc_hsync_end-precache) >> 3) - 1) & 0x3f; + if (temp & 0x20) + jregAD |= 0x04; /* HRE D[5] */ + ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x05, 0x60, (u8)((temp & 0x1f) | jreg05)); + + ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xAC, 0x00, jregAC); + ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xAD, 0x00, jregAD); + + /* vert timings */ + temp = (mode->crtc_vtotal) - 2; + if (temp & 0x100) + jreg07 |= 0x01; + if (temp & 0x200) + jreg07 |= 0x20; + if (temp & 0x400) + jregAE |= 0x01; + ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x06, 0x00, temp); + + temp = (mode->crtc_vsync_start) - 1; + if (temp & 0x100) + jreg07 |= 0x04; + if (temp & 0x200) + jreg07 |= 0x80; + if (temp & 0x400) + jregAE |= 0x08; + ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x10, 0x00, temp); + + temp = (mode->crtc_vsync_end - 1) & 0x3f; + if (temp & 0x10) + jregAE |= 0x20; + if (temp & 0x20) + jregAE |= 0x40; + ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x11, 0x70, temp & 0xf); + + temp = mode->crtc_vdisplay - 1; + if (temp & 0x100) + jreg07 |= 0x02; + if (temp & 0x200) + jreg07 |= 0x40; + if (temp & 0x400) + jregAE |= 0x02; + ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x12, 0x00, temp); + + temp = mode->crtc_vblank_start - 1; + if (temp & 0x100) + jreg07 |= 0x08; + if (temp & 0x200) + jreg09 |= 0x20; + if (temp & 0x400) + jregAE |= 0x04; + ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x15, 0x00, temp); + + temp = mode->crtc_vblank_end - 1; + if (temp & 0x100) + jregAE |= 0x10; + ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x16, 0x00, temp); + + ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x07, 0x00, jreg07); + ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x09, 0xdf, jreg09); + ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xAE, 0x00, (jregAE | 0x80)); + + if (precache) + ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0x3f, 0x80); + else + ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0x3f, 0x00); + + ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x11, 0x7f, 0x80); +} + +static void ast_set_offset_reg(struct drm_crtc *crtc) +{ + struct ast_private *ast = crtc->dev->dev_private; + const struct drm_framebuffer *fb = crtc->primary->fb; + + u16 offset; + + offset = fb->pitches[0] >> 3; + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x13, (offset & 0xff)); + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xb0, (offset >> 8) & 0x3f); +} + +static void ast_set_dclk_reg(struct drm_device *dev, struct drm_display_mode *mode, + struct ast_vbios_mode_info *vbios_mode) +{ + struct ast_private *ast = dev->dev_private; + const struct ast_vbios_dclk_info *clk_info; + + if (ast->chip == AST2500) + clk_info = &dclk_table_ast2500[vbios_mode->enh_table->dclk_index]; + else + clk_info = &dclk_table[vbios_mode->enh_table->dclk_index]; + + ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xc0, 0x00, clk_info->param1); + ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xc1, 0x00, clk_info->param2); + ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xbb, 0x0f, + (clk_info->param3 & 0xc0) | + ((clk_info->param3 & 0x3) << 4)); +} + +static void ast_set_ext_reg(struct drm_crtc *crtc, struct drm_display_mode *mode, + struct ast_vbios_mode_info *vbios_mode) +{ + struct ast_private *ast = crtc->dev->dev_private; + u8 jregA0 = 0, jregA3 = 0, jregA8 = 0; + + /* 32 BPP */ + jregA0 = 0x70; + jregA3 = 0x08; + jregA8 = 0x02; + + ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa0, 0x8f, jregA0); + ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa3, 0xf0, jregA3); + ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa8, 0xfd, jregA8); + + /* Set Threshold */ + if (ast->chip == AST2300 || ast->chip == AST2400 || + ast->chip == AST2500) { + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa7, 0x78); + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa6, 0x60); + } else if (ast->chip == AST2100 || + ast->chip == AST1100 || + ast->chip == AST2200 || + ast->chip == AST2150) { + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa7, 0x3f); + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa6, 0x2f); + } else { + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa7, 0x2f); + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa6, 0x1f); + } +} + +static void ast_set_sync_reg(struct drm_device *dev, struct drm_display_mode *mode, + struct ast_vbios_mode_info *vbios_mode) +{ + struct ast_private *ast = dev->dev_private; + u8 jreg; + + jreg = ast_io_read8(ast, AST_IO_MISC_PORT_READ); + jreg &= ~0xC0; + if (vbios_mode->enh_table->flags & NVSync) jreg |= 0x80; + if (vbios_mode->enh_table->flags & NHSync) jreg |= 0x40; + ast_io_write8(ast, AST_IO_MISC_PORT_WRITE, jreg); +} + +static void ast_set_start_address_crt1(struct ast_private *ast, u32 offset) +{ + u32 addr; + + addr = offset >> 2; + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x0d, (u8)(addr & 0xff)); + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x0c, (u8)((addr >> 8) & 0xff)); + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xaf, (u8)((addr >> 16) & 0xff)); +} + +static int ast_crtc_do_set_base(struct drm_crtc *crtc) +{ + struct ast_private *ast = crtc->dev->dev_private; + u64 gpu_addr; + + /* PCI BAR 0 */ + struct resource *res = find_resource(crtc->dev->pdev, 0x10); + if (!res) { + dev_err(dev->pdev, "BAR0 resource not found.\n"); + return -EIO; + } + + gpu_addr = (uintptr_t)res2mmio(res, 0, 0); + + ast_set_offset_reg(crtc); + ast_set_start_address_crt1(ast, (u32)gpu_addr); + + return 0; +} + +static int ast_crtc_mode_set(struct drm_crtc *crtc, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + struct drm_device *dev = crtc->dev; + struct ast_private *ast = crtc->dev->dev_private; + struct ast_vbios_mode_info vbios_mode; + bool ret; + if (ast->chip == AST1180) { + dev_err(dev->pdev, "AST 1180 modesetting not supported\n"); + return -EINVAL; + } + + /* DPMS, set on */ + ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT, 0x1, 0xdf, 0); + if (ast->tx_chip_type == AST_TX_DP501) + ast_set_dp501_video_output(crtc->dev, 1); + ast_crtc_load_lut(crtc); + + /* Get mode */ + ret = ast_get_vbios_mode_info(crtc, mode, adjusted_mode, &vbios_mode); + if (ret == false) { + dev_err(dev->pdev, "Failed to find compatible vbios mode\n"); + return -EINVAL; + } + ast_open_key(ast); + + ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa1, 0xff, 0x04); + + ast_set_std_reg(crtc, adjusted_mode, &vbios_mode); + ast_set_crtc_reg(crtc, adjusted_mode, &vbios_mode); + ast_set_offset_reg(crtc); + ast_set_dclk_reg(dev, adjusted_mode, &vbios_mode); + ast_set_ext_reg(crtc, adjusted_mode, &vbios_mode); + ast_set_sync_reg(dev, adjusted_mode, &vbios_mode); + + ast_crtc_do_set_base(crtc); + + /* Commit changes */ + + ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT, 0x1, 0xdf, 0); + ast_crtc_load_lut(crtc); + + return 0; +} + +static int ast_get_modes(struct drm_connector *connector, struct edid *out) +{ + struct ast_private *ast = connector->dev->dev_private; + u8 edid[128]; + + bool flags = false; + if (ast->tx_chip_type == AST_TX_DP501) { + ast->dp501_maxclk = 0xff; + flags = ast_dp501_read_edid(connector->dev, (u8 *)edid); + if (flags) + ast->dp501_maxclk = ast_get_dp501_max_clk(connector->dev); + else + dev_err(dev->pdev, "I2C transmission error\n"); + } + + if (!flags) { + ast_software_i2c_read(CONFIG_DRIVERS_ASPEED_I2C_BUS, ast, edid); + } + if (decode_edid(edid, sizeof(edid), out) != EDID_CONFORMANT) { + dev_err(dev->pdev, "Failed to decode EDID\n"); + return -EIO; + } + + return 0; +} + +static enum drm_mode_status ast_mode_valid(struct drm_connector *connector, + struct drm_display_mode *mode) +{ + struct ast_private *ast = connector->dev->dev_private; + int flags = MODE_NOMODE; + uint32_t jtemp; + + if (ast->support_wide_screen) { + if ((mode->hdisplay == 1680) && (mode->vdisplay == 1050)) + return MODE_OK; + if ((mode->hdisplay == 1280) && (mode->vdisplay == 800)) + return MODE_OK; + if ((mode->hdisplay == 1440) && (mode->vdisplay == 900)) + return MODE_OK; + if ((mode->hdisplay == 1360) && (mode->vdisplay == 768)) + return MODE_OK; + if ((mode->hdisplay == 1600) && (mode->vdisplay == 900)) + return MODE_OK; + + if ((ast->chip == AST2100) || (ast->chip == AST2200) || + (ast->chip == AST2300) || (ast->chip == AST2400) || + (ast->chip == AST2500) || (ast->chip == AST1180)) { + if ((mode->hdisplay == 1920) && (mode->vdisplay == 1080)) + return MODE_OK; + + if ((mode->hdisplay == 1920) && (mode->vdisplay == 1200)) { + jtemp = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd1, 0xff); + if (jtemp & 0x01) + return MODE_NOMODE; + else + return MODE_OK; + } + } + } + switch (mode->hdisplay) { + case 640: + if (mode->vdisplay == 480) flags = MODE_OK; + break; + case 800: + if (mode->vdisplay == 600) flags = MODE_OK; + break; + case 1024: + if (mode->vdisplay == 768) flags = MODE_OK; + break; + case 1280: + if (mode->vdisplay == 1024) flags = MODE_OK; + break; + case 1600: + if (mode->vdisplay == 1200) flags = MODE_OK; + break; + default: + return flags; + } + + return flags; +} + +static void ast_edid_to_drmmode(struct edid *edid, struct drm_display_mode *mode) +{ + memset(mode, 0, sizeof(*mode)); + + mode->hdisplay = edid->mode.ha; + mode->vdisplay = edid->mode.va; + mode->crtc_hdisplay = edid->mode.ha; + mode->crtc_vdisplay = edid->mode.va; + + mode->clock = edid->mode.pixel_clock; + mode->vrefresh = edid->mode.refresh; + + mode->crtc_hblank_start = edid->mode.ha + edid->mode.hso; + mode->crtc_hblank_end = edid->mode.ha + edid->mode.hso + edid->mode.hbl; + mode->crtc_hsync_start = edid->mode.ha + edid->mode.hso; + mode->crtc_hsync_end = edid->mode.ha + edid->mode.hso + edid->mode.hspw; + mode->crtc_htotal = MAX(mode->crtc_hblank_end, mode->crtc_hsync_end); + + mode->crtc_vblank_start = edid->mode.va + edid->mode.vso; + mode->crtc_vblank_end = edid->mode.va + edid->mode.vso + edid->mode.vbl; + mode->crtc_vsync_start = edid->mode.va + edid->mode.vso; + mode->crtc_vsync_end = edid->mode.va + edid->mode.vso + edid->mode.vspw; + mode->crtc_vtotal = MAX(mode->crtc_vblank_end, mode->crtc_vsync_end); + + mode->flags = 0; + if (edid->mode.phsync == '+') + mode->flags |= DRM_MODE_FLAG_PHSYNC; + else + mode->flags |= DRM_MODE_FLAG_NHSYNC; + + if (edid->mode.pvsync == '+') + mode->flags |= DRM_MODE_FLAG_PVSYNC; + else + mode->flags |= DRM_MODE_FLAG_NVSYNC; +} + +static int ast_select_mode(struct drm_connector *connector, + struct edid *edid, struct drm_display_mode *mode) +{ + bool widescreen; + int ret; + + ret = ast_get_modes(connector, edid); + if (ret) { + dev_err(dev->pdev, "Failed to get mode from EDID\n"); + return ret; + } + printk(BIOS_DEBUG, "Display has %dpx x %dpx\n", edid->mode.ha, edid->mode.va); + + widescreen = !!(((edid->mode.ha * 4) % (edid->mode.va * 3))); + + do { + /* Select a compatible smaller mode */ + if (edid->mode.ha > 1920 && widescreen) { + edid->mode.ha = 1920; + edid->mode.va = 1080; + } else if (edid->mode.ha >= 1920 && widescreen) { + edid->mode.ha = 1680; + edid->mode.va = 1050; + } else if (edid->mode.ha >= 1680 && widescreen) { + edid->mode.ha = 1600; + edid->mode.va = 900; + } else if (edid->mode.ha >= 1680 && !widescreen) { + edid->mode.ha = 1600; + edid->mode.va = 1200; + } else if (edid->mode.ha >= 1600 && widescreen) { + edid->mode.ha = 1440; + edid->mode.va = 900; + } else if (edid->mode.ha >= 1440 && widescreen) { + edid->mode.ha = 1360; + edid->mode.va = 768; + } else if (edid->mode.ha >= 1360 && widescreen) { + edid->mode.ha = 1280; + edid->mode.va = 800; + } else if (edid->mode.ha >= 1360 && !widescreen) { + edid->mode.ha = 1280; + edid->mode.va = 1024; + } else if (edid->mode.ha >= 1280) { + edid->mode.ha = 1024; + edid->mode.va = 768; + } else if (edid->mode.ha >= 1024) { + edid->mode.ha = 800; + edid->mode.va = 600; + } else if (edid->mode.ha >= 800) { + edid->mode.ha = 640; + edid->mode.va = 480; + } else { + dev_err(dev->pdev, "No compatible mode found.\n"); + + return -EIO; + } + + ast_edid_to_drmmode(edid, mode); + + } while (ast_mode_valid(connector, mode) != MODE_OK); + + /* Update EDID info */ + edid->x_resolution = edid->mode.ha; + edid->y_resolution = edid->mode.va; + edid->bytes_per_line = ALIGN_UP(edid->x_resolution * 4, 8); + + printk(BIOS_DEBUG, "Using framebuffer %dpx x %dpx pitch %d\n", + edid->x_resolution, edid->y_resolution, edid->bytes_per_line); + + return 0; +} + +static void ast_hide_cursor(struct drm_crtc *crtc) +{ + struct ast_private *ast = crtc->dev->dev_private; + ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xcb, 0xfc, 0x00); +} + +int ast_driver_framebuffer_init(struct drm_device *dev, int flags) +{ + struct drm_display_mode adjusted_mode; + struct drm_crtc crtc; + struct drm_format format; + struct drm_primary primary; + struct drm_framebuffer fb; + struct drm_connector connector; + struct edid edid; + int ret; + + /* Init structs */ + connector.dev = dev; + + format.cpp[0] = 4; /* 32 BPP */ + fb.format = &format; + + primary.fb = &fb; + + crtc.dev = dev; + crtc.primary = &primary; + + /* Init I2C */ + ast_software_i2c_init(CONFIG_DRIVERS_ASPEED_I2C_BUS); + + /* Read EDID and find mode */ + ret = ast_select_mode(&connector, &edid, &crtc.mode); + if (ret) { + dev_err(dev->pdev, "Failed to select mode.\n"); + return ret; + } + + fb.pitches[0] = edid.bytes_per_line; + + memcpy(&adjusted_mode, &crtc.mode, sizeof(crtc.mode)); + + ret = ast_crtc_mode_set(&crtc, &crtc.mode, &adjusted_mode); + if (ret) { + dev_err(dev->pdev, "Failed to set mode.\n"); + return ret; + } + + ast_hide_cursor(&crtc); + + /* Advertise new mode */ + + /* PCI BAR 0 */ + struct resource *res = find_resource(dev->pdev, 0x10); + if (!res) { + dev_err(dev->pdev, "BAR0 resource not found.\n"); + return -EIO; + } + uintptr_t gpu_addr = (uintptr_t)res2mmio(res, 0, 0); + + edid.framebuffer_bits_per_pixel = 32; /* 32 BPP */ + set_vbe_mode_info_valid(&edid, gpu_addr); + + /* Clear display */ + memset((void *)gpu_addr, 0, edid.bytes_per_line * edid.y_resolution); + + return 0; +} diff --git a/src/drivers/aspeed/common/ast_tables.h b/src/drivers/aspeed/common/ast_tables.h index 6c20f36..aa54fcf 100644 --- a/src/drivers/aspeed/common/ast_tables.h +++ b/src/drivers/aspeed/common/ast_tables.h @@ -47,6 +47,7 @@ #define SyncPN (PVSync | NHSync) #define SyncNP (NVSync | PHSync) #define SyncNN (NVSync | NHSync) +#define AST2500PreCatchCRT 0x00004000
/* DCLK Index */ #define VCLK25_175 0x00 @@ -108,80 +109,110 @@ {0x3b, 0x2c, 0x81}, /* 1A: VCLK118_25 */ };
+static const struct ast_vbios_dclk_info dclk_table_ast2500[] = { + {0x2C, 0xE7, 0x03}, /* 00: VCLK25_175 */ + {0x95, 0x62, 0x03}, /* 01: VCLK28_322 */ + {0x67, 0x63, 0x01}, /* 02: VCLK31_5 */ + {0x76, 0x63, 0x01}, /* 03: VCLK36 */ + {0xEE, 0x67, 0x01}, /* 04: VCLK40 */ + {0x82, 0x62, 0x01}, /* 05: VCLK49_5 */ + {0xC6, 0x64, 0x01}, /* 06: VCLK50 */ + {0x94, 0x62, 0x01}, /* 07: VCLK56_25 */ + {0x80, 0x64, 0x00}, /* 08: VCLK65 */ + {0x7B, 0x63, 0x00}, /* 09: VCLK75 */ + {0x67, 0x62, 0x00}, /* 0A: VCLK78_75 */ + {0x7C, 0x62, 0x00}, /* 0B: VCLK94_5 */ + {0x8E, 0x62, 0x00}, /* 0C: VCLK108 */ + {0x85, 0x24, 0x00}, /* 0D: VCLK135 */ + {0x67, 0x22, 0x00}, /* 0E: VCLK157_5 */ + {0x6A, 0x22, 0x00}, /* 0F: VCLK162 */ + {0x4d, 0x4c, 0x80}, /* 10: VCLK154 */ + {0x68, 0x6f, 0x80}, /* 11: VCLK83.5 */ + {0x28, 0x49, 0x80}, /* 12: VCLK106.5 */ + {0x37, 0x49, 0x80}, /* 13: VCLK146.25 */ + {0x1f, 0x45, 0x80}, /* 14: VCLK148.5 */ + {0x47, 0x6c, 0x80}, /* 15: VCLK71 */ + {0x25, 0x65, 0x80}, /* 16: VCLK88.75 */ + {0x58, 0x01, 0x42}, /* 17: VCLK119 */ + {0x32, 0x67, 0x80}, /* 18: VCLK85_5 */ + {0x6a, 0x6d, 0x80}, /* 19: VCLK97_75 */ + {0x44, 0x20, 0x43}, /* 1A: VCLK118_25 */ +}; + static struct ast_vbios_stdtable vbios_stdtable[] = { /* MD_2_3_400 */ { 0x67, - {0x00,0x03,0x00,0x02}, - {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f, - 0x00,0x4f,0x0d,0x0e,0x00,0x00,0x00,0x00, - 0x9c,0x8e,0x8f,0x28,0x1f,0x96,0xb9,0xa3, - 0xff}, - {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07, - 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f, - 0x0c,0x00,0x0f,0x08}, - {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00, - 0xff} + {0x00, 0x03, 0x00, 0x02}, + {0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f, + 0x00, 0x4f, 0x0d, 0x0e, 0x00, 0x00, 0x00, 0x00, + 0x9c, 0x8e, 0x8f, 0x28, 0x1f, 0x96, 0xb9, 0xa3, + 0xff}, + {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x0c, 0x00, 0x0f, 0x08}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x00, + 0xff} }, /* Mode12/ExtEGATable */ { 0xe3, - {0x01,0x0f,0x00,0x06}, - {0x5f,0x4f,0x50,0x82,0x55,0x81,0x0b,0x3e, - 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00, - 0xe9,0x8b,0xdf,0x28,0x00,0xe7,0x04,0xe3, - 0xff}, - {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07, - 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f, - 0x01,0x00,0x0f,0x00}, - {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0f, - 0xff} + {0x01, 0x0f, 0x00, 0x06}, + {0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0x0b, 0x3e, + 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xe9, 0x8b, 0xdf, 0x28, 0x00, 0xe7, 0x04, 0xe3, + 0xff}, + {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x01, 0x00, 0x0f, 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0f, + 0xff} }, /* ExtVGATable */ { 0x2f, - {0x01,0x0f,0x00,0x0e}, - {0x5f,0x4f,0x50,0x82,0x54,0x80,0x0b,0x3e, - 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00, - 0xea,0x8c,0xdf,0x28,0x40,0xe7,0x04,0xa3, - 0xff}, - {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, - 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f, - 0x01,0x00,0x00,0x00}, - {0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0f, - 0xff} + {0x01, 0x0f, 0x00, 0x0e}, + {0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0x0b, 0x3e, + 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xea, 0x8c, 0xdf, 0x28, 0x40, 0xe7, 0x04, 0xa3, + 0xff}, + {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x01, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0f, + 0xff} }, /* ExtHiCTable */ { 0x2f, - {0x01,0x0f,0x00,0x0e}, - {0x5f,0x4f,0x50,0x82,0x54,0x80,0x0b,0x3e, - 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00, - 0xea,0x8c,0xdf,0x28,0x40,0xe7,0x04,0xa3, - 0xff}, - {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, - 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f, - 0x01,0x00,0x00,0x00}, - {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0f, - 0xff} + {0x01, 0x0f, 0x00, 0x0e}, + {0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0x0b, 0x3e, + 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xea, 0x8c, 0xdf, 0x28, 0x40, 0xe7, 0x04, 0xa3, + 0xff}, + {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x01, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0f, + 0xff} }, /* ExtTrueCTable */ { 0x2f, - {0x01,0x0f,0x00,0x0e}, - {0x5f,0x4f,0x50,0x82,0x54,0x80,0x0b,0x3e, - 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00, - 0xea,0x8c,0xdf,0x28,0x40,0xe7,0x04,0xa3, + {0x01, 0x0f, 0x00, 0x0e}, + {0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0x0b, 0x3e, + 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xea, 0x8c, 0xdf, 0x28, 0x40, 0xe7, 0x04, 0xa3, 0xff}, - {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, - 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f, - 0x01,0x00,0x00,0x00}, - {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0f, + {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x01, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0f, 0xff} }, };
-static struct ast_vbios_enhtable res_640x480[] = { +static const struct ast_vbios_enhtable res_640x480[] = { { 800, 640, 8, 96, 525, 480, 2, 2, VCLK25_175, /* 60Hz */ (SyncNN | HBorder | VBorder | Charx8Dot), 60, 1, 0x2E }, { 832, 640, 16, 40, 520, 480, 1, 3, VCLK31_5, /* 72Hz */ @@ -194,7 +225,7 @@ (SyncNN | Charx8Dot) , 0xFF, 4, 0x2E }, };
-static struct ast_vbios_enhtable res_800x600[] = { +static const struct ast_vbios_enhtable res_800x600[] = { {1024, 800, 24, 72, 625, 600, 1, 2, VCLK36, /* 56Hz */ (SyncPP | Charx8Dot), 56, 1, 0x30 }, {1056, 800, 40, 128, 628, 600, 1, 4, VCLK40, /* 60Hz */ @@ -210,7 +241,7 @@ };
-static struct ast_vbios_enhtable res_1024x768[] = { +static const struct ast_vbios_enhtable res_1024x768[] = { {1344, 1024, 24, 136, 806, 768, 3, 6, VCLK65, /* 60Hz */ (SyncNN | Charx8Dot), 60, 1, 0x31 }, {1328, 1024, 24, 136, 806, 768, 3, 6, VCLK75, /* 70Hz */ @@ -223,7 +254,7 @@ (SyncPP | Charx8Dot), 0xFF, 4, 0x31 }, };
-static struct ast_vbios_enhtable res_1280x1024[] = { +static const struct ast_vbios_enhtable res_1280x1024[] = { {1688, 1280, 48, 112, 1066, 1024, 1, 3, VCLK108, /* 60Hz */ (SyncPP | Charx8Dot), 60, 1, 0x32 }, {1688, 1280, 16, 144, 1066, 1024, 1, 3, VCLK135, /* 75Hz */ @@ -234,7 +265,7 @@ (SyncPP | Charx8Dot), 0xFF, 3, 0x32 }, };
-static struct ast_vbios_enhtable res_1600x1200[] = { +static const struct ast_vbios_enhtable res_1600x1200[] = { {2160, 1600, 64, 192, 1250, 1200, 1, 3, VCLK162, /* 60Hz */ (SyncPP | Charx8Dot), 60, 1, 0x33 }, {2160, 1600, 64, 192, 1250, 1200, 1, 3, VCLK162, /* end */ @@ -242,34 +273,39 @@ };
/* 16:9 */ -static struct ast_vbios_enhtable res_1360x768[] = { - {1792, 1360, 64,112, 795, 768, 3, 6, VCLK85_5, /* 60Hz */ +static const struct ast_vbios_enhtable res_1360x768[] = { + {1792, 1360, 64, 112, 795, 768, 3, 6, VCLK85_5, /* 60Hz */ (SyncPP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 60, 1, 0x39 }, - {1792, 1360, 64,112, 795, 768, 3, 6, VCLK85_5, /* end */ - (SyncPP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 0xFF, 1, 0x39 }, + {1792, 1360, 64, 112, 795, 768, 3, 6, VCLK85_5, /* end */ + (SyncPP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo | + AST2500PreCatchCRT), 0xFF, 1, 0x39 }, };
-static struct ast_vbios_enhtable res_1600x900[] = { - {1760, 1600, 48, 32, 926, 900, 3, 5, VCLK97_75, /* 60Hz CVT RB */ - (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 60, 1, 0x3A }, - {2112, 1600, 88,168, 934, 900, 3, 5, VCLK118_25, /* 60Hz CVT */ +static const struct ast_vbios_enhtable res_1600x900[] = { + {1760, 1600, 48, 32, 926, 900, 3, 5, VCLK97_75, /* 60Hz CVT RB */ + (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo | + AST2500PreCatchCRT), 60, 1, 0x3A }, + {2112, 1600, 88, 168, 934, 900, 3, 5, VCLK118_25, /* 60Hz CVT */ (SyncPN | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 60, 2, 0x3A }, - {2112, 1600, 88,168, 934, 900, 3, 5, VCLK118_25, /* 60Hz CVT */ + {2112, 1600, 88, 168, 934, 900, 3, 5, VCLK118_25, /* 60Hz CVT */ (SyncPN | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 0xFF, 2, 0x3A }, };
-static struct ast_vbios_enhtable res_1920x1080[] = { +static const struct ast_vbios_enhtable res_1920x1080[] = { {2200, 1920, 88, 44, 1125, 1080, 4, 5, VCLK148_5, /* 60Hz */ - (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 60, 1, 0x38 }, + (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo | + AST2500PreCatchCRT), 60, 1, 0x38 }, {2200, 1920, 88, 44, 1125, 1080, 4, 5, VCLK148_5, /* 60Hz */ - (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 0xFF, 1, 0x38 }, + (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo | + AST2500PreCatchCRT), 0xFF, 1, 0x38 }, };
/* 16:10 */ -static struct ast_vbios_enhtable res_1280x800[] = { +static const struct ast_vbios_enhtable res_1280x800[] = { {1440, 1280, 48, 32, 823, 800, 3, 6, VCLK71, /* 60Hz RB */ - (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 60, 1, 0x35 }, + (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo | + AST2500PreCatchCRT), 60, 1, 0x35 }, {1680, 1280, 72,128, 831, 800, 3, 6, VCLK83_5, /* 60Hz */ (SyncPN | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 60, 2, 0x35 }, {1680, 1280, 72,128, 831, 800, 3, 6, VCLK83_5, /* 60Hz */ @@ -277,29 +313,32 @@
};
-static struct ast_vbios_enhtable res_1440x900[] = { +static const struct ast_vbios_enhtable res_1440x900[] = { {1600, 1440, 48, 32, 926, 900, 3, 6, VCLK88_75, /* 60Hz RB */ - (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 60, 1, 0x36 }, + (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo | + AST2500PreCatchCRT), 60, 1, 0x36 }, {1904, 1440, 80,152, 934, 900, 3, 6, VCLK106_5, /* 60Hz */ (SyncPN | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 60, 2, 0x36 }, {1904, 1440, 80,152, 934, 900, 3, 6, VCLK106_5, /* 60Hz */ (SyncPN | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 0xFF, 2, 0x36 }, };
-static struct ast_vbios_enhtable res_1680x1050[] = { +static const struct ast_vbios_enhtable res_1680x1050[] = { {1840, 1680, 48, 32, 1080, 1050, 3, 6, VCLK119, /* 60Hz RB */ - (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 60, 1, 0x37 }, + (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo | + AST2500PreCatchCRT), 60, 1, 0x37 }, {2240, 1680,104,176, 1089, 1050, 3, 6, VCLK146_25, /* 60Hz */ (SyncPN | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 60, 2, 0x37 }, {2240, 1680,104,176, 1089, 1050, 3, 6, VCLK146_25, /* 60Hz */ (SyncPN | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 0xFF, 2, 0x37 }, };
-static struct ast_vbios_enhtable res_1920x1200[] = { +static const struct ast_vbios_enhtable res_1920x1200[] = { {2080, 1920, 48, 32, 1235, 1200, 3, 6, VCLK154, /* 60Hz RB*/ - (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 60, 1, 0x34 }, - {2080, 1920, 48, 32, 1235, 1200, 3, 6, VCLK154, /* 60Hz RB */ - (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 0xFF, 1, 0x34 }, + (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo | + AST2500PreCatchCRT), 60, 1, 0x34 }, + {2080, 1920, 48, 32, 1235, 1200, 3, 6, VCLK154, /* 60Hz RB */ + (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo | + AST2500PreCatchCRT), 0xFF, 1, 0x34 }, }; - #endif
Paul Menzel has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/35726 )
Change subject: drivers/aspeed/common: Add support for high resolution framebuffer ......................................................................
Patch Set 1:
(5 comments)
https://review.coreboot.org/c/coreboot/+/35726/1//COMMIT_MSG Commit Message:
https://review.coreboot.org/c/coreboot/+/35726/1//COMMIT_MSG@10 PS1, Line 10: Copy the linux kernel code and add a bunch of wrapper structs to make it : compile. : Convert the EDID to a drm_display_mode, which is understood by the : driver. Please format this as a list, if you list the changes.
https://review.coreboot.org/c/coreboot/+/35726/1//COMMIT_MSG@19 PS1, Line 19: woring working
https://review.coreboot.org/c/coreboot/+/35726/1/src/drivers/aspeed/ast2050/... File src/drivers/aspeed/ast2050/ast2050.c:
https://review.coreboot.org/c/coreboot/+/35726/1/src/drivers/aspeed/ast2050/... PS1, Line 37: Why the new blank line?
https://review.coreboot.org/c/coreboot/+/35726/1/src/drivers/aspeed/common/a... File src/drivers/aspeed/common/ast_i2c.c:
https://review.coreboot.org/c/coreboot/+/35726/1/src/drivers/aspeed/common/a... PS1, Line 1: Remove the blank line?
https://review.coreboot.org/c/coreboot/+/35726/1/src/drivers/aspeed/common/a... File src/drivers/aspeed/common/ast_mode.c:
https://review.coreboot.org/c/coreboot/+/35726/1/src/drivers/aspeed/common/a... PS1, Line 1: Remove blank line?
Julius Werner has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/35726 )
Change subject: drivers/aspeed/common: Add support for high resolution framebuffer ......................................................................
Patch Set 1:
(3 comments)
https://review.coreboot.org/c/coreboot/+/35726/1/src/drivers/aspeed/common/a... File src/drivers/aspeed/common/ast_i2c.c:
https://review.coreboot.org/c/coreboot/+/35726/1/src/drivers/aspeed/common/a... PS1, Line 126: software_i2c[bus] = &ast_ops; You should probably have a check or assert for the bus number here, since your code is clearly only working for a single bus.
https://review.coreboot.org/c/coreboot/+/35726/1/src/drivers/aspeed/common/a... PS1, Line 128: i2c_recover_bus(bus); Why are you doing this here? Do you have reason to believe the bus would be wedged here? I'd keep this separate from just enabling/disabling software I2C unless there's really a reason the bus is always wedged on this platform.
https://review.coreboot.org/c/coreboot/+/35726/1/src/drivers/aspeed/common/a... PS1, Line 133: ast = ast_priv; I don't want to look too closely into the platform code here, but... what is this? If you need to pass platform information in from the calling code, why don't you pass it once into ast_software_i2c_init() rather than for every read?
Christian Walter has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/35726 )
Change subject: drivers/aspeed/common: Add support for high resolution framebuffer ......................................................................
Patch Set 1:
(1 comment)
https://review.coreboot.org/c/coreboot/+/35726/1/src/drivers/aspeed/common/a... File src/drivers/aspeed/common/ast_drv.h:
https://review.coreboot.org/c/coreboot/+/35726/1/src/drivers/aspeed/common/a... PS1, Line 47: AST2500, Why has this been added here?
Patrick Rudolph has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/35726 )
Change subject: drivers/aspeed/common: Add support for high resolution framebuffer ......................................................................
Patch Set 1:
(3 comments)
https://review.coreboot.org/c/coreboot/+/35726/1/src/drivers/aspeed/common/a... File src/drivers/aspeed/common/ast_drv.h:
https://review.coreboot.org/c/coreboot/+/35726/1/src/drivers/aspeed/common/a... PS1, Line 47: AST2500,
Why has this been added here?
It's used by ast_mode.c.
https://review.coreboot.org/c/coreboot/+/35726/1/src/drivers/aspeed/common/a... File src/drivers/aspeed/common/ast_i2c.c:
https://review.coreboot.org/c/coreboot/+/35726/1/src/drivers/aspeed/common/a... PS1, Line 128: i2c_recover_bus(bus);
Why are you doing this here? Do you have reason to believe the bus would be wedged here? I'd keep th […]
Both sda and scl have been pulled low by the ast post code. The code brings the bus back into a known state.
https://review.coreboot.org/c/coreboot/+/35726/1/src/drivers/aspeed/common/a... PS1, Line 133: ast = ast_priv;
I don't want to look too closely into the platform code here, but... […]
Both functions are only called once. I'll remove one of them.
Hello build bot (Jenkins), Patrick Georgi, Martin Roth,
I'd like you to reexamine a change. Please visit
https://review.coreboot.org/c/coreboot/+/35726
to look at the new patch set (#2).
Change subject: drivers/aspeed/common: Add support for high resolution framebuffer ......................................................................
drivers/aspeed/common: Add support for high resolution framebuffer
* Implement reading EDID over software I2C. * Copy the linux kernel code and add a bunch of wrapper structs to make it compile. * Convert the EDID to a drm_display_mode, which is understood by the driver.
Tested on Supermicro X11SSH-TF using FullHD VGA monitor. Initializes the graphics in about 1 second, which is twice as fast as the VGA Option ROM.
The framebuffer is advertised and woring in tianocore.
Change-Id: I7803566b64158405efc04a39f80a0ec98b44e646 Signed-off-by: Patrick Rudolph patrick.rudolph@9elements.com --- M src/drivers/aspeed/ast2050/Kconfig M src/drivers/aspeed/ast2050/ast2050.c M src/drivers/aspeed/common/Kconfig M src/drivers/aspeed/common/Makefile.inc M src/drivers/aspeed/common/ast_drv.h A src/drivers/aspeed/common/ast_i2c.c A src/drivers/aspeed/common/ast_mode.c M src/drivers/aspeed/common/ast_tables.h 8 files changed, 1,160 insertions(+), 85 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/26/35726/2
Patrick Rudolph has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/35726 )
Change subject: drivers/aspeed/common: Add support for high resolution framebuffer ......................................................................
Patch Set 2:
(1 comment)
https://review.coreboot.org/c/coreboot/+/35726/1/src/drivers/aspeed/common/a... File src/drivers/aspeed/common/ast_i2c.c:
https://review.coreboot.org/c/coreboot/+/35726/1/src/drivers/aspeed/common/a... PS1, Line 1:
Remove the blank line?
Done
Patrick Rudolph has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/35726 )
Change subject: drivers/aspeed/common: Add support for high resolution framebuffer ......................................................................
Patch Set 2:
(4 comments)
https://review.coreboot.org/c/coreboot/+/35726/1//COMMIT_MSG Commit Message:
https://review.coreboot.org/c/coreboot/+/35726/1//COMMIT_MSG@10 PS1, Line 10: Copy the linux kernel code and add a bunch of wrapper structs to make it : compile. : Convert the EDID to a drm_display_mode, which is understood by the : driver.
Please format this as a list, if you list the changes.
Done
https://review.coreboot.org/c/coreboot/+/35726/1/src/drivers/aspeed/common/a... File src/drivers/aspeed/common/ast_i2c.c:
https://review.coreboot.org/c/coreboot/+/35726/1/src/drivers/aspeed/common/a... PS1, Line 126: software_i2c[bus] = &ast_ops;
You should probably have a check or assert for the bus number here, since your code is clearly only […]
Reworked i2c handling
https://review.coreboot.org/c/coreboot/+/35726/1/src/drivers/aspeed/common/a... PS1, Line 133: ast = ast_priv;
Both functions are only called once. I'll remove one of them.
Reworked i2c handling
https://review.coreboot.org/c/coreboot/+/35726/1/src/drivers/aspeed/common/a... File src/drivers/aspeed/common/ast_mode.c:
https://review.coreboot.org/c/coreboot/+/35726/1/src/drivers/aspeed/common/a... PS1, Line 1:
Remove blank line?
Done
Hello build bot (Jenkins), Patrick Georgi, Martin Roth,
I'd like you to reexamine a change. Please visit
https://review.coreboot.org/c/coreboot/+/35726
to look at the new patch set (#3).
Change subject: drivers/aspeed/common: Add support for high resolution framebuffer ......................................................................
drivers/aspeed/common: Add support for high resolution framebuffer
* Implement reading EDID over software I2C. * Copy the linux kernel code and add a bunch of wrapper structs to make it compile. * Convert the EDID to a drm_display_mode, which is understood by the driver.
Tested on Supermicro X11SSH-TF using FullHD VGA monitor. Initializes the graphics in about 1 second, which is twice as fast as the VGA Option ROM.
The framebuffer is advertised and working in tianocore.
Change-Id: I7803566b64158405efc04a39f80a0ec98b44e646 Signed-off-by: Patrick Rudolph patrick.rudolph@9elements.com --- M src/drivers/aspeed/ast2050/Kconfig M src/drivers/aspeed/ast2050/ast2050.c M src/drivers/aspeed/common/Kconfig M src/drivers/aspeed/common/Makefile.inc M src/drivers/aspeed/common/ast_drv.h A src/drivers/aspeed/common/ast_i2c.c A src/drivers/aspeed/common/ast_mode.c M src/drivers/aspeed/common/ast_tables.h 8 files changed, 1,159 insertions(+), 85 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/26/35726/3
Patrick Rudolph has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/35726 )
Change subject: drivers/aspeed/common: Add support for high resolution framebuffer ......................................................................
Patch Set 3:
(2 comments)
https://review.coreboot.org/c/coreboot/+/35726/1//COMMIT_MSG Commit Message:
https://review.coreboot.org/c/coreboot/+/35726/1//COMMIT_MSG@19 PS1, Line 19: woring
working
Done
https://review.coreboot.org/c/coreboot/+/35726/1/src/drivers/aspeed/ast2050/... File src/drivers/aspeed/ast2050/ast2050.c:
https://review.coreboot.org/c/coreboot/+/35726/1/src/drivers/aspeed/ast2050/... PS1, Line 37:
Why the new blank line?
Done
Michael Niewöhner has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/35726 )
Change subject: drivers/aspeed/common: Add support for high resolution framebuffer ......................................................................
Patch Set 3:
From X11SSM-F with i2c+vga patches applied:
PCI: 06:00.0 init ... ASpeed AST2050: initializing video device ast_detect_chip: AST 2400 detected ast_detect_chip: VGA not enabled on entry, requesting chip POST ast_detect_chip: Analog VGA only ast_driver_load: dram 1632000000 1 16 01000000 software_i2c(0): Trying i2c bus recovery software_i2c(0): ERROR: Clock stretching timeout before recovery! software_i2c(0): ERROR: Clock stretching timeout before stop condition! software_i2c(0): ERROR: Clock stretching timeout before stop condition! software_i2c(0): ERROR: Clock stretching timeout before stop condition! software_i2c(0): ERROR: Clock stretching timeout before stop condition! software_i2c(0): ERROR: Clock stretching timeout before stop condition! software_i2c(0): ERROR: Clock stretching timeout before stop condition! software_i2c(0): ERROR: Clock stretching timeout before stop condition! software_i2c(0): ERROR: Clock stretching timeout before stop condition! software_i2c(0): ERROR: Clock stretching timeout before stop condition! WARNING: EDID block does NOT fully conform to EDID 1.3. Missing name descriptor Display has 1920px x 1080px Using framebuffer 1680px x 1050px pitch 6720 ast_get_vbios_mode_info: FB BPP = 32 ast_get_vbios_mode_info: crtc_hdisplay = 1680 ASpeed high resolution framebuffer initialized PCI: 06:00.0 init finished in 1374298 usecs
Hello build bot (Jenkins), Patrick Georgi, Martin Roth,
I'd like you to reexamine a change. Please visit
https://review.coreboot.org/c/coreboot/+/35726
to look at the new patch set (#4).
Change subject: drivers/aspeed/common: Add support for high resolution framebuffer ......................................................................
drivers/aspeed/common: Add support for high resolution framebuffer
* Implement reading EDID over software I2C. * Fall back to VGA if no monitor connected for BMC KVM * Copy the linux kernel code and add a bunch of wrapper structs to make it compile. * Convert the EDID to a drm_display_mode, which is understood by the driver.
Tested on Supermicro X11SSH-TF using FullHD VGA monitor. Initializes the graphics in about 1 second, which is twice as fast as the VGA Option ROM.
The framebuffer is advertised and working in tianocore.
Change-Id: I7803566b64158405efc04a39f80a0ec98b44e646 Signed-off-by: Patrick Rudolph patrick.rudolph@9elements.com --- M src/drivers/aspeed/ast2050/Kconfig M src/drivers/aspeed/ast2050/ast2050.c M src/drivers/aspeed/common/Kconfig M src/drivers/aspeed/common/Makefile.inc M src/drivers/aspeed/common/ast_drv.h A src/drivers/aspeed/common/ast_i2c.c A src/drivers/aspeed/common/ast_mode.c M src/drivers/aspeed/common/ast_tables.h 8 files changed, 1,210 insertions(+), 85 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/26/35726/4
Patrick Rudolph has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/35726 )
Change subject: drivers/aspeed/common: Add support for high resolution framebuffer ......................................................................
Patch Set 4:
(1 comment)
Removed the broken i2c recovery and fixed a bug with KVM when resolution was >1024x768.
https://review.coreboot.org/c/coreboot/+/35726/1/src/drivers/aspeed/common/a... File src/drivers/aspeed/common/ast_i2c.c:
https://review.coreboot.org/c/coreboot/+/35726/1/src/drivers/aspeed/common/a... PS1, Line 128: i2c_recover_bus(bus);
Both sda and scl have been pulled low by the ast post code. […]
Removed, as it's not needed.
Michael Niewöhner has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/35726 )
Change subject: drivers/aspeed/common: Add support for high resolution framebuffer ......................................................................
Patch Set 4: Code-Review+1
(1 comment)
Tested on X11SSM-F; works perfectly :-)
https://review.coreboot.org/c/coreboot/+/35726/4/src/drivers/aspeed/common/a... File src/drivers/aspeed/common/ast_drv.h:
https://review.coreboot.org/c/coreboot/+/35726/4/src/drivers/aspeed/common/a... PS4, Line 47: AST2500 this should be mentioned in the commit msg
Patrick Rudolph has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/35726 )
Change subject: drivers/aspeed/common: Add support for high resolution framebuffer ......................................................................
Patch Set 4:
(1 comment)
https://review.coreboot.org/c/coreboot/+/35726/4/src/drivers/aspeed/common/a... File src/drivers/aspeed/common/ast_drv.h:
https://review.coreboot.org/c/coreboot/+/35726/4/src/drivers/aspeed/common/a... PS4, Line 47: AST2500
this should be mentioned in the commit msg
It doesn't add ast2500 support, it's just to make the code compile. We have a separate patch for ast2500 support.
Michael Niewöhner has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/35726 )
Change subject: drivers/aspeed/common: Add support for high resolution framebuffer ......................................................................
Patch Set 4:
(1 comment)
https://review.coreboot.org/c/coreboot/+/35726/4/src/drivers/aspeed/common/a... File src/drivers/aspeed/common/ast_drv.h:
https://review.coreboot.org/c/coreboot/+/35726/4/src/drivers/aspeed/common/a... PS4, Line 47: AST2500
It doesn't add ast2500 support, it's just to make the code compile. […]
Ack
Nico Huber has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/35726 )
Change subject: drivers/aspeed/common: Add support for high resolution framebuffer ......................................................................
Patch Set 4:
(2 comments)
https://review.coreboot.org/c/coreboot/+/35726/4/src/drivers/aspeed/ast2050/... File src/drivers/aspeed/ast2050/Kconfig:
https://review.coreboot.org/c/coreboot/+/35726/4/src/drivers/aspeed/ast2050/... PS4, Line 4: select HAVE_VGA_TEXT_FRAMEBUFFER This was just wrong, it should only be selected if the user activated the driver, i.e. enabled NGI in `.config`. This was covered up by the first boards with this driver as they force NGI.
https://review.coreboot.org/c/coreboot/+/35726/4/src/drivers/aspeed/common/K... File src/drivers/aspeed/common/Kconfig:
https://review.coreboot.org/c/coreboot/+/35726/4/src/drivers/aspeed/common/K... PS4, Line 3: select HAVE_LINEAR_FRAMEBUFFER : select HAVE_VGA_TEXT_FRAMEBUFFER `if MAINBOARD_DO_NATIVE_VGA_INIT` for both, please.
Michael Niewöhner has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/35726 )
Change subject: drivers/aspeed/common: Add support for high resolution framebuffer ......................................................................
Patch Set 4:
(1 comment)
https://review.coreboot.org/c/coreboot/+/35726/4/src/drivers/aspeed/common/K... File src/drivers/aspeed/common/Kconfig:
https://review.coreboot.org/c/coreboot/+/35726/4/src/drivers/aspeed/common/K... PS4, Line 3: select HAVE_LINEAR_FRAMEBUFFER : select HAVE_VGA_TEXT_FRAMEBUFFER
`if MAINBOARD_DO_NATIVE_VGA_INIT` for both, please.
MAINBOARD_DO_NATIVE_VGA_INIT depends on MAINBOARD_HAS_NATIVE_VGA_INIT, so every mainboard having a AST2400/2500 with a VGA port connected must select MAINBOARD_HAS_NATIVE_VGA_INIT, too then
Michael Niewöhner has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/35726 )
Change subject: drivers/aspeed/common: Add support for high resolution framebuffer ......................................................................
Patch Set 4:
(1 comment)
https://review.coreboot.org/c/coreboot/+/35726/4/src/drivers/aspeed/common/K... File src/drivers/aspeed/common/Kconfig:
https://review.coreboot.org/c/coreboot/+/35726/4/src/drivers/aspeed/common/K... PS4, Line 3: select HAVE_LINEAR_FRAMEBUFFER : select HAVE_VGA_TEXT_FRAMEBUFFER
MAINBOARD_DO_NATIVE_VGA_INIT depends on MAINBOARD_HAS_NATIVE_VGA_INIT, so every mainboard having a A […]
ok, just ignore my comment and add what Nico said, as discussed on IRC
Hello Michael Niewöhner, build bot (Jenkins), Patrick Georgi, Martin Roth,
I'd like you to reexamine a change. Please visit
https://review.coreboot.org/c/coreboot/+/35726
to look at the new patch set (#5).
Change subject: drivers/aspeed/common: Add support for high resolution framebuffer ......................................................................
drivers/aspeed/common: Add support for high resolution framebuffer
* Implement reading EDID over software I2C. * Fall back to VGA if no monitor connected for BMC KVM * Copy the linux kernel code and add a bunch of wrapper structs to make it compile. * Convert the EDID to a drm_display_mode, which is understood by the driver. * Properly select HAVE_LINEAR_FRAMEBUFFER and HAVE_VGA_TEXT_FRAMEBUFFER
Tested on Supermicro X11SSH-TF using FullHD VGA monitor. Initializes the graphics in about 1 second, which is twice as fast as the VGA Option ROM.
The framebuffer is advertised and working in tianocore.
Change-Id: I7803566b64158405efc04a39f80a0ec98b44e646 Signed-off-by: Patrick Rudolph patrick.rudolph@9elements.com --- M src/drivers/aspeed/ast2050/Kconfig M src/drivers/aspeed/ast2050/ast2050.c M src/drivers/aspeed/common/Kconfig M src/drivers/aspeed/common/Makefile.inc M src/drivers/aspeed/common/ast_drv.h A src/drivers/aspeed/common/ast_i2c.c A src/drivers/aspeed/common/ast_mode.c M src/drivers/aspeed/common/ast_tables.h 8 files changed, 1,210 insertions(+), 85 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/26/35726/5
Patrick Rudolph has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/35726 )
Change subject: drivers/aspeed/common: Add support for high resolution framebuffer ......................................................................
Patch Set 5:
(1 comment)
https://review.coreboot.org/c/coreboot/+/35726/4/src/drivers/aspeed/common/K... File src/drivers/aspeed/common/Kconfig:
https://review.coreboot.org/c/coreboot/+/35726/4/src/drivers/aspeed/common/K... PS4, Line 3: select HAVE_LINEAR_FRAMEBUFFER : select HAVE_VGA_TEXT_FRAMEBUFFER
ok, just ignore my comment and add what Nico said, as discussed on IRC
Done
Nico Huber has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/35726 )
Change subject: drivers/aspeed/common: Add support for high resolution framebuffer ......................................................................
Patch Set 5:
(1 comment)
https://review.coreboot.org/c/coreboot/+/35726/5/src/drivers/aspeed/common/a... File src/drivers/aspeed/common/ast_i2c.c:
https://review.coreboot.org/c/coreboot/+/35726/5/src/drivers/aspeed/common/a... PS5, Line 123: backup = software_i2c[ASPEED_BUS]; : : software_i2c[ASPEED_BUS] = &ast_ops; : This looks pretty odd. Looking at the few (dead) code examples in the tree, I guess the idea was as follows:
* software_i2c implementations provide a registration function that takes the bus number * some central place (I'd suggest mainboard code) calls that functions and assigns unique (on the board) bus numbers
Julius Werner has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/35726 )
Change subject: drivers/aspeed/common: Add support for high resolution framebuffer ......................................................................
Patch Set 5: Code-Review+1
(2 comments)
FWIW the way the I2C stuff is used here LGTM. Don't want to review the rest of the patch though.
https://review.coreboot.org/c/coreboot/+/35726/5/src/drivers/aspeed/common/a... File src/drivers/aspeed/common/ast_i2c.c:
https://review.coreboot.org/c/coreboot/+/35726/5/src/drivers/aspeed/common/a... PS5, Line 123: backup = software_i2c[ASPEED_BUS]; : : software_i2c[ASPEED_BUS] = &ast_ops; :
This looks pretty odd. Looking at the few (dead) code examples in the tree, […]
It's not exactly dead? It's just a debug feature that you normally wouldn't enable in committed code (although I don't mind its use here if it helps). The implementation in src/soc/rockchip/rk3288/software_i2c.c should be considered canonical. The idea was that you could hack in
software_i2c_attach(some_bus); software_i2c_wedge_write(some_bus); software_i2c_detach(some_bus);
in some place and then see how the hardware I2C controller deals with that afterwards.
In this case, I think the way it's written here is probably the best way to do it. You have the weirdness that all our I2C functions need a bus number, but usually the SoC is the only thing in charge of assigning bus numbers (because the SoC should know how many I2C controllers it has). The problem here is that this is a pseudo-I2C controller that's independent from the SoC, because it's tunneled over another transport interface. So we don't really have a number we can give it that we can guarantee will not interfere with the SoC's assignments. The solution chosen here is to just pick 0 as the bus number and override the software_i2c[] array only for the duration of this function, restoring the previous state afterwards, which makes sure it cannot clash with anything else that may have a different concept of what "bus 0" is.
https://review.coreboot.org/c/coreboot/+/35726/5/src/drivers/aspeed/common/a... PS5, Line 133: ast = ast_priv; Don't you need to do this before you call set_clock() and set_data() above?
Michael Niewöhner has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/35726 )
Change subject: drivers/aspeed/common: Add support for high resolution framebuffer ......................................................................
Patch Set 5: Code-Review+1
Hello Julius Werner, Michael Niewöhner, build bot (Jenkins), Patrick Georgi, Martin Roth,
I'd like you to reexamine a change. Please visit
https://review.coreboot.org/c/coreboot/+/35726
to look at the new patch set (#6).
Change subject: drivers/aspeed/common: Add support for high resolution framebuffer ......................................................................
drivers/aspeed/common: Add support for high resolution framebuffer
* Implement reading EDID over software I2C. * Fall back to VGA if no monitor connected for BMC KVM * Copy the linux kernel code and add a bunch of wrapper structs to make it compile. * Convert the EDID to a drm_display_mode, which is understood by the driver. * Properly select HAVE_LINEAR_FRAMEBUFFER and HAVE_VGA_TEXT_FRAMEBUFFER
Tested on Supermicro X11SSH-TF using FullHD VGA monitor. Initializes the graphics in about 1 second, which is twice as fast as the VGA Option ROM.
The framebuffer is advertised and working in tianocore.
Change-Id: I7803566b64158405efc04a39f80a0ec98b44e646 Signed-off-by: Patrick Rudolph patrick.rudolph@9elements.com --- M src/drivers/aspeed/ast2050/Kconfig M src/drivers/aspeed/ast2050/ast2050.c M src/drivers/aspeed/common/Kconfig M src/drivers/aspeed/common/Makefile.inc M src/drivers/aspeed/common/ast_drv.h A src/drivers/aspeed/common/ast_i2c.c A src/drivers/aspeed/common/ast_mode.c A src/drivers/aspeed/common/ast_mode_corebootfb.c M src/drivers/aspeed/common/ast_tables.h 9 files changed, 1,251 insertions(+), 85 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/26/35726/6
Arthur Heymans has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/35726 )
Change subject: drivers/aspeed/common: Add support for high resolution framebuffer ......................................................................
Patch Set 6: Code-Review+2
(1 comment)
https://review.coreboot.org/c/coreboot/+/35726/6/src/drivers/aspeed/common/a... File src/drivers/aspeed/common/ast_tables.h:
https://review.coreboot.org/c/coreboot/+/35726/6/src/drivers/aspeed/common/a... PS6, Line 147: 0x67, : {0x00, 0x03, 0x00, 0x02}, : {0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f, : 0x00, 0x4f, 0x0d, 0x0e, 0x00, 0x00, 0x00, 0x00, : 0x9c, 0x8e, 0x8f, 0x28, 0x1f, 0x96, 0xb9, 0xa3, : 0xff}, : {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, : 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, : 0x0c, 0x00, 0x0f, 0x08}, : {0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x00, : 0xff} This is all cosmetic?
Michael Niewöhner has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/35726 )
Change subject: drivers/aspeed/common: Add support for high resolution framebuffer ......................................................................
Patch Set 6: Code-Review+1
(7 comments)
https://review.coreboot.org/c/coreboot/+/35726/6/src/drivers/aspeed/common/a... File src/drivers/aspeed/common/ast_i2c.c:
https://review.coreboot.org/c/coreboot/+/35726/6/src/drivers/aspeed/common/a... PS6, Line 30: * Authors: Dave Airlie airlied@redhat.com why not just put these two lines below the copyright above?
https://review.coreboot.org/c/coreboot/+/35726/6/src/drivers/aspeed/common/a... PS6, Line 32: */ : #include nit: newline before include
https://review.coreboot.org/c/coreboot/+/35726/6/src/drivers/aspeed/common/a... File src/drivers/aspeed/common/ast_mode.c:
https://review.coreboot.org/c/coreboot/+/35726/6/src/drivers/aspeed/common/a... PS6, Line 29: /* : * Authors: Dave Airlie airlied@redhat.com : * Authors: 9Elements Agency GmbH patrick.rudolph@9elements.com move up below copyright?
https://review.coreboot.org/c/coreboot/+/35726/6/src/drivers/aspeed/common/a... PS6, Line 34: */ : #include newline after comment
https://review.coreboot.org/c/coreboot/+/35726/6/src/drivers/aspeed/common/a... PS6, Line 37: why two newlines?
https://review.coreboot.org/c/coreboot/+/35726/6/src/drivers/aspeed/common/a... File src/drivers/aspeed/common/ast_mode_corebootfb.c:
https://review.coreboot.org/c/coreboot/+/35726/6/src/drivers/aspeed/common/a... PS6, Line 28: */ : /* : * Authors: Dave Airlie airlied@redhat.com : * Authors: 9Elements Agency GmbH patrick.rudolph@9elements.com move below Copyright?
https://review.coreboot.org/c/coreboot/+/35726/6/src/drivers/aspeed/common/a... PS6, Line 32: */ newline
Nico Huber has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/35726 )
Change subject: drivers/aspeed/common: Add support for high resolution framebuffer ......................................................................
Patch Set 6:
(7 comments)
https://review.coreboot.org/c/coreboot/+/35726/5/src/drivers/aspeed/common/a... File src/drivers/aspeed/common/ast_i2c.c:
https://review.coreboot.org/c/coreboot/+/35726/5/src/drivers/aspeed/common/a... PS5, Line 123: backup = software_i2c[ASPEED_BUS]; : : software_i2c[ASPEED_BUS] = &ast_ops; :
It's not exactly dead? It's just a debug feature that you normally wouldn't enable in committed code […]
Well, I see what this code is doing. But it's just weird and a bad example, IMHO, for anyone who's going to look in existing code how to use it. Making a backup of nothing for the case that somebody activates incompatible debug code? shouldn't it be the other way around, the code that requires software_i2c is clean and the debug code looks weird?
https://review.coreboot.org/c/coreboot/+/35726/5/src/drivers/aspeed/common/a... PS5, Line 133: ast = ast_priv;
Don't you need to do this before you call set_clock() and set_data() above?
I see that too.
https://review.coreboot.org/c/coreboot/+/35726/6/src/drivers/aspeed/common/a... File src/drivers/aspeed/common/ast_mode_corebootfb.c:
https://review.coreboot.org/c/coreboot/+/35726/6/src/drivers/aspeed/common/a... PS6, Line 40: expexts expects
https://review.coreboot.org/c/coreboot/+/35726/6/src/drivers/aspeed/common/a... PS6, Line 51: dev_err(dev->pdev, "BAR0 resource not found.\n"); eh, just wasted a lot of time to figure out why this line compiles... because `dev` doesn't exist. Can we make it a function or just use printk() here?
https://review.coreboot.org/c/coreboot/+/35726/6/src/drivers/aspeed/common/a... PS6, Line 81: mode->crtc_hblank_start = edid->mode.ha + edid->mode.hso; Why add `hso`? (sync offset == front porch, which is blank too?)
I'll try to draw a picture of my EDID interpretation:
+++++++++++++++++++++++++++++++++++---------------------------------------------------, | active | blank | |<-border->|<-display->|<-border->|<-front porch->|<-sync-pulse width->|<-back porch->| |<-sync offset->|
Border is mostly ignored, though.
https://review.coreboot.org/c/coreboot/+/35726/6/src/drivers/aspeed/common/a... PS6, Line 82: mode->crtc_hblank_end = edid->mode.ha + edid->mode.hso + edid->mode.hbl; This should be just active + blank?
https://review.coreboot.org/c/coreboot/+/35726/6/src/drivers/aspeed/common/a... PS6, Line 85: mode->crtc_htotal = MAX(mode->crtc_hblank_end, mode->crtc_hsync_end); Rather bail out if something is wrong?
Nico Huber has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/35726 )
Change subject: drivers/aspeed/common: Add support for high resolution framebuffer ......................................................................
Patch Set 6:
(1 comment)
https://review.coreboot.org/c/coreboot/+/35726/6/src/drivers/aspeed/common/a... File src/drivers/aspeed/common/ast_mode_corebootfb.c:
https://review.coreboot.org/c/coreboot/+/35726/6/src/drivers/aspeed/common/a... PS6, Line 81: mode->crtc_hblank_start = edid->mode.ha + edid->mode.hso;
Why add `hso`? (sync offset == front porch, which is blank too?) […]
Update: drm_display_mode.*display seems to include the borders, so they actually become part of the framebuffer, too, and we should ignore them as usual.
Hello Julius Werner, Arthur Heymans, Michael Niewöhner, build bot (Jenkins), Patrick Georgi, Martin Roth,
I'd like you to reexamine a change. Please visit
https://review.coreboot.org/c/coreboot/+/35726
to look at the new patch set (#7).
Change subject: drivers/aspeed/common: Add support for high resolution framebuffer ......................................................................
drivers/aspeed/common: Add support for high resolution framebuffer
* Implement reading EDID over software I2C. * Fall back to VGA if no monitor connected for BMC KVM * Copy the linux kernel code and add a bunch of wrapper structs to make it compile. * Convert the EDID to a drm_display_mode, which is understood by the driver. * Properly select HAVE_LINEAR_FRAMEBUFFER and HAVE_VGA_TEXT_FRAMEBUFFER
Tested on Supermicro X11SSH-TF using FullHD VGA monitor. Initializes the graphics in about 1 second, which is twice as fast as the VGA Option ROM.
The framebuffer is advertised and working in tianocore.
Change-Id: I7803566b64158405efc04a39f80a0ec98b44e646 Signed-off-by: Patrick Rudolph patrick.rudolph@9elements.com --- M src/drivers/aspeed/ast2050/Kconfig M src/drivers/aspeed/ast2050/ast2050.c M src/drivers/aspeed/common/Kconfig M src/drivers/aspeed/common/Makefile.inc M src/drivers/aspeed/common/ast_drv.h A src/drivers/aspeed/common/ast_i2c.c A src/drivers/aspeed/common/ast_mode.c A src/drivers/aspeed/common/ast_mode_corebootfb.c M src/drivers/aspeed/common/ast_tables.h 9 files changed, 1,247 insertions(+), 85 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/26/35726/7
Patrick Rudolph has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/35726 )
Change subject: drivers/aspeed/common: Add support for high resolution framebuffer ......................................................................
Patch Set 7:
(9 comments)
https://review.coreboot.org/c/coreboot/+/35726/6/src/drivers/aspeed/common/a... File src/drivers/aspeed/common/ast_i2c.c:
https://review.coreboot.org/c/coreboot/+/35726/6/src/drivers/aspeed/common/a... PS6, Line 30: * Authors: Dave Airlie airlied@redhat.com
why not just put these two lines below the copyright above?
Done
https://review.coreboot.org/c/coreboot/+/35726/6/src/drivers/aspeed/common/a... PS6, Line 32: */ : #include
nit: newline before include
Done
https://review.coreboot.org/c/coreboot/+/35726/6/src/drivers/aspeed/common/a... File src/drivers/aspeed/common/ast_mode_corebootfb.c:
https://review.coreboot.org/c/coreboot/+/35726/6/src/drivers/aspeed/common/a... PS6, Line 28: */ : /* : * Authors: Dave Airlie airlied@redhat.com : * Authors: 9Elements Agency GmbH patrick.rudolph@9elements.com
move below Copyright?
Done
https://review.coreboot.org/c/coreboot/+/35726/6/src/drivers/aspeed/common/a... PS6, Line 32: */
newline
Done
https://review.coreboot.org/c/coreboot/+/35726/6/src/drivers/aspeed/common/a... PS6, Line 40: expexts
expects
Done
https://review.coreboot.org/c/coreboot/+/35726/6/src/drivers/aspeed/common/a... PS6, Line 51: dev_err(dev->pdev, "BAR0 resource not found.\n");
eh, just wasted a lot of time to figure out why this line compiles... […]
Done
https://review.coreboot.org/c/coreboot/+/35726/6/src/drivers/aspeed/common/a... PS6, Line 81: mode->crtc_hblank_start = edid->mode.ha + edid->mode.hso;
Update: drm_display_mode.*display seems to include the borders, so they […]
Done
https://review.coreboot.org/c/coreboot/+/35726/6/src/drivers/aspeed/common/a... PS6, Line 82: mode->crtc_hblank_end = edid->mode.ha + edid->mode.hso + edid->mode.hbl;
This should be just active + blank?
Done
https://review.coreboot.org/c/coreboot/+/35726/6/src/drivers/aspeed/common/a... PS6, Line 85: mode->crtc_htotal = MAX(mode->crtc_hblank_end, mode->crtc_hsync_end);
Rather bail out if something is wrong?
Using hblank end only
Patrick Rudolph has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/35726 )
Change subject: drivers/aspeed/common: Add support for high resolution framebuffer ......................................................................
Patch Set 7:
(6 comments)
https://review.coreboot.org/c/coreboot/+/35726/5/src/drivers/aspeed/common/a... File src/drivers/aspeed/common/ast_i2c.c:
https://review.coreboot.org/c/coreboot/+/35726/5/src/drivers/aspeed/common/a... PS5, Line 123: backup = software_i2c[ASPEED_BUS]; : : software_i2c[ASPEED_BUS] = &ast_ops; :
Well, I see what this code is doing. But it's just weird and a bad […]
I don't see a better solution
https://review.coreboot.org/c/coreboot/+/35726/5/src/drivers/aspeed/common/a... PS5, Line 133: ast = ast_priv;
I see that too.
Done
https://review.coreboot.org/c/coreboot/+/35726/6/src/drivers/aspeed/common/a... File src/drivers/aspeed/common/ast_mode.c:
https://review.coreboot.org/c/coreboot/+/35726/6/src/drivers/aspeed/common/a... PS6, Line 29: /* : * Authors: Dave Airlie airlied@redhat.com : * Authors: 9Elements Agency GmbH patrick.rudolph@9elements.com
move up below copyright?
Done
https://review.coreboot.org/c/coreboot/+/35726/6/src/drivers/aspeed/common/a... PS6, Line 34: */ : #include
newline after comment
Done
https://review.coreboot.org/c/coreboot/+/35726/6/src/drivers/aspeed/common/a... PS6, Line 37:
why two newlines?
in case one doesn't work well enough
https://review.coreboot.org/c/coreboot/+/35726/6/src/drivers/aspeed/common/a... File src/drivers/aspeed/common/ast_tables.h:
https://review.coreboot.org/c/coreboot/+/35726/6/src/drivers/aspeed/common/a... PS6, Line 147: 0x67, : {0x00, 0x03, 0x00, 0x02}, : {0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f, : 0x00, 0x4f, 0x0d, 0x0e, 0x00, 0x00, 0x00, 0x00, : 0x9c, 0x8e, 0x8f, 0x28, 0x1f, 0x96, 0xb9, 0xa3, : 0xff}, : {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, : 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, : 0x0c, 0x00, 0x0f, 0x08}, : {0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x00, : 0xff}
This is all cosmetic?
no the linter errors out if there's no whitespace
Philipp Deppenwiese has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/35726 )
Change subject: drivers/aspeed/common: Add support for high resolution framebuffer ......................................................................
Patch Set 7: Code-Review+2
Hello Julius Werner, Arthur Heymans, Michael Niewöhner, Philipp Deppenwiese, build bot (Jenkins), Patrick Georgi, Martin Roth,
I'd like you to reexamine a change. Please visit
https://review.coreboot.org/c/coreboot/+/35726
to look at the new patch set (#8).
Change subject: drivers/aspeed/common: Add support for high resolution framebuffer ......................................................................
drivers/aspeed/common: Add support for high resolution framebuffer
* Implement reading EDID over software I2C. * Fall back to VGA if no monitor connected for BMC KVM * Copy the linux kernel code and add a bunch of wrapper structs to make it compile. * Convert the EDID to a drm_display_mode, which is understood by the driver. * Properly select HAVE_LINEAR_FRAMEBUFFER and HAVE_VGA_TEXT_FRAMEBUFFER
Tested on Supermicro X11SSH-TF using FullHD VGA monitor. Initializes the graphics in about 1 second, which is twice as fast as the VGA Option ROM.
The framebuffer is advertised and working in tianocore.
Change-Id: I7803566b64158405efc04a39f80a0ec98b44e646 Signed-off-by: Patrick Rudolph patrick.rudolph@9elements.com --- M src/drivers/aspeed/ast2050/Kconfig M src/drivers/aspeed/ast2050/ast2050.c M src/drivers/aspeed/common/Kconfig M src/drivers/aspeed/common/Makefile.inc M src/drivers/aspeed/common/ast_drv.h A src/drivers/aspeed/common/ast_i2c.c A src/drivers/aspeed/common/ast_mode.c A src/drivers/aspeed/common/ast_mode_corebootfb.c M src/drivers/aspeed/common/ast_tables.h 9 files changed, 1,247 insertions(+), 85 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/26/35726/8
Philipp Deppenwiese has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/35726 )
Change subject: drivers/aspeed/common: Add support for high resolution framebuffer ......................................................................
Patch Set 12: Code-Review+2
Patrick Rudolph has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/35726 )
Change subject: drivers/aspeed/common: Add support for high resolution framebuffer ......................................................................
Patch Set 13:
(1 comment)
https://review.coreboot.org/c/coreboot/+/35726/5/src/drivers/aspeed/common/a... File src/drivers/aspeed/common/ast_i2c.c:
https://review.coreboot.org/c/coreboot/+/35726/5/src/drivers/aspeed/common/a... PS5, Line 123: backup = software_i2c[ASPEED_BUS]; : : software_i2c[ASPEED_BUS] = &ast_ops; :
I don't see a better solution
Marking as resolved until a reworked software i2c better fits the needs.
Patrick Rudolph has submitted this change. ( https://review.coreboot.org/c/coreboot/+/35726 )
Change subject: drivers/aspeed/common: Add support for high resolution framebuffer ......................................................................
drivers/aspeed/common: Add support for high resolution framebuffer
* Implement reading EDID over software I2C. * Fall back to VGA if no monitor connected for BMC KVM * Copy the linux kernel code and add a bunch of wrapper structs to make it compile. * Convert the EDID to a drm_display_mode, which is understood by the driver. * Properly select HAVE_LINEAR_FRAMEBUFFER and HAVE_VGA_TEXT_FRAMEBUFFER
Tested on Supermicro X11SSH-TF using FullHD VGA monitor. Initializes the graphics in about 1 second, which is twice as fast as the VGA Option ROM.
The framebuffer is advertised and working in tianocore.
Change-Id: I7803566b64158405efc04a39f80a0ec98b44e646 Signed-off-by: Patrick Rudolph patrick.rudolph@9elements.com Reviewed-on: https://review.coreboot.org/c/coreboot/+/35726 Reviewed-by: Philipp Deppenwiese zaolin.daisuki@gmail.com Tested-by: build bot (Jenkins) no-reply@coreboot.org --- M src/drivers/aspeed/ast2050/Kconfig M src/drivers/aspeed/ast2050/ast2050.c M src/drivers/aspeed/common/Kconfig M src/drivers/aspeed/common/Makefile.inc M src/drivers/aspeed/common/ast_drv.h A src/drivers/aspeed/common/ast_i2c.c A src/drivers/aspeed/common/ast_mode.c A src/drivers/aspeed/common/ast_mode_corebootfb.c M src/drivers/aspeed/common/ast_tables.h 9 files changed, 1,247 insertions(+), 85 deletions(-)
Approvals: build bot (Jenkins): Verified Philipp Deppenwiese: Looks good to me, approved
diff --git a/src/drivers/aspeed/ast2050/Kconfig b/src/drivers/aspeed/ast2050/Kconfig index 337b181..7d2c728 100644 --- a/src/drivers/aspeed/ast2050/Kconfig +++ b/src/drivers/aspeed/ast2050/Kconfig @@ -1,5 +1,4 @@ config DRIVERS_ASPEED_AST2050 bool select DRIVERS_ASPEED_AST_COMMON - select HAVE_VGA_TEXT_FRAMEBUFFER select MAINBOARD_HAS_NATIVE_VGA_INIT diff --git a/src/drivers/aspeed/ast2050/ast2050.c b/src/drivers/aspeed/ast2050/ast2050.c index b1bd276..67a1a80 100644 --- a/src/drivers/aspeed/ast2050/ast2050.c +++ b/src/drivers/aspeed/ast2050/ast2050.c @@ -48,13 +48,19 @@ outb(0xa6, 0x3d4); outb(0x2f, 0x3d5); outb(0xa7, 0x3d4); outb(0x3f, 0x3d5);
- /* Initialize standard VGA text mode */ - vga_io_init(); - vga_textmode_init(); - printk(BIOS_INFO, "ASpeed VGA text mode initialized\n"); + if (CONFIG(VGA_TEXT_FRAMEBUFFER)) { + /* Initialize standard VGA text mode */ + vga_io_init();
- /* if we don't have console, at least print something... */ - vga_line_write(0, "ASpeed VGA text mode initialized"); + vga_textmode_init(); + printk(BIOS_INFO, "ASpeed VGA text mode initialized\n"); + + /* if we don't have console, at least print something... */ + vga_line_write(0, "ASpeed VGA text mode initialized"); + } else if (CONFIG(GENERIC_LINEAR_FRAMEBUFFER)) { + ast_driver_framebuffer_init(&drm_dev, 0); + printk(BIOS_INFO, "ASpeed high resolution framebuffer initialized\n"); + } }
static struct device_operations aspeed_ast2050_ops = { diff --git a/src/drivers/aspeed/common/Kconfig b/src/drivers/aspeed/common/Kconfig index 653782f..79c4c75 100644 --- a/src/drivers/aspeed/common/Kconfig +++ b/src/drivers/aspeed/common/Kconfig @@ -1,3 +1,6 @@ config DRIVERS_ASPEED_AST_COMMON bool - select VGA + select HAVE_LINEAR_FRAMEBUFFER if MAINBOARD_DO_NATIVE_VGA_INIT + select HAVE_VGA_TEXT_FRAMEBUFFER if MAINBOARD_DO_NATIVE_VGA_INIT + select VGA if VGA_TEXT_FRAMEBUFFER + select SOFTWARE_I2C if GENERIC_LINEAR_FRAMEBUFFER diff --git a/src/drivers/aspeed/common/Makefile.inc b/src/drivers/aspeed/common/Makefile.inc index 75f8b48..1f4b858 100644 --- a/src/drivers/aspeed/common/Makefile.inc +++ b/src/drivers/aspeed/common/Makefile.inc @@ -1 +1,4 @@ -ramstage-$(CONFIG_DRIVERS_ASPEED_AST_COMMON) += ast_dp501.c ast_main.c ast_post.c +ifeq ($(CONFIG_DRIVERS_ASPEED_AST_COMMON),y) +ramstage-y += ast_dp501.c ast_main.c ast_post.c +ramstage-$(CONFIG_GENERIC_LINEAR_FRAMEBUFFER) += ast_mode.c ast_i2c.c ast_mode_corebootfb.c +endif diff --git a/src/drivers/aspeed/common/ast_drv.h b/src/drivers/aspeed/common/ast_drv.h index c179469..39f4943 100644 --- a/src/drivers/aspeed/common/ast_drv.h +++ b/src/drivers/aspeed/common/ast_drv.h @@ -46,6 +46,7 @@ AST2150, AST2300, AST2400, + AST2500, AST1180, };
@@ -192,6 +193,8 @@ #define AST_HWC_SIZE (AST_MAX_HWC_WIDTH*AST_MAX_HWC_HEIGHT*2) #define AST_HWC_SIGNATURE_SIZE 32
+#define EINVAL 22 /* Invalid argument */ + #define AST_DEFAULT_HWC_NUM 2 /* define for signature structure */ #define AST_HWC_SIGNATURE_CHECKSUM 0x00 @@ -202,6 +205,99 @@ #define AST_HWC_SIGNATURE_HOTSPOTX 0x14 #define AST_HWC_SIGNATURE_HOTSPOTY 0x18
+/* ast_mode.c stuff */ +struct ast_vbios_stdtable { + u8 misc; + u8 seq[4]; + u8 crtc[25]; + u8 ar[20]; + u8 gr[9]; +}; + +struct ast_vbios_enhtable { + u32 ht; + u32 hde; + u32 hfp; + u32 hsync; + u32 vt; + u32 vde; + u32 vfp; + u32 vsync; + u32 dclk_index; + u32 flags; + u32 refresh_rate; + u32 refresh_rate_index; + u32 mode_id; +}; + +struct ast_vbios_dclk_info { + u8 param1; + u8 param2; + u8 param3; +}; + +struct ast_vbios_mode_info { + const struct ast_vbios_stdtable *std_table; + const struct ast_vbios_enhtable *enh_table; +}; + +#define DRM_MODE_FLAG_NVSYNC 1 +#define DRM_MODE_FLAG_PVSYNC 2 +#define DRM_MODE_FLAG_NHSYNC 4 +#define DRM_MODE_FLAG_PHSYNC 8 + +struct drm_display_mode { + /* Proposed mode values */ + u16 vrefresh; /* in Hz */ + u32 clock; + u16 hdisplay; + u16 vdisplay; + u32 flags; + + /* Actual mode we give to hw */ + u16 crtc_hdisplay; + u16 crtc_htotal; + u16 crtc_hblank_start; + u16 crtc_hblank_end; + u16 crtc_hsync_start; + u16 crtc_hsync_end; + u16 crtc_vtotal; + u16 crtc_vsync_start; + u16 crtc_vsync_end; + u16 crtc_vdisplay; + u16 crtc_vblank_start; + u16 crtc_vblank_end; +}; + +struct drm_format { + u32 cpp[1]; /* Colors per pixel */ +}; + +struct drm_framebuffer { + u32 pitches[1]; + struct drm_format *format; + u32 mmio_addr; +}; + +struct drm_primary { + struct drm_framebuffer *fb; +}; + +struct drm_crtc { + struct drm_device *dev; + struct drm_primary *primary; + struct drm_display_mode mode; +}; + +struct drm_connector { + struct drm_device *dev; +}; + +enum drm_mode_status { + MODE_NOMODE, + MODE_OK +}; + #define AST_MM_ALIGN_SHIFT 4 #define AST_MM_ALIGN_MASK ((1 << AST_MM_ALIGN_SHIFT) - 1)
@@ -222,4 +318,23 @@ bool ast_dp501_read_edid(struct drm_device *dev, u8 *ediddata); u8 ast_get_dp501_max_clk(struct drm_device *dev); void ast_init_3rdtx(struct drm_device *dev); + +/* ast mode */ +int ast_crtc_mode_set(struct drm_crtc *crtc, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode); +enum drm_mode_status ast_mode_valid(struct drm_connector *connector, + const unsigned int hdisplay, + const unsigned int vdisplay); +void ast_hide_cursor(struct drm_crtc *crtc); +void ast_set_offset_reg(struct drm_crtc *crtc); +void ast_set_start_address_crt1(struct ast_private *ast, u32 offset); + +/* ast_mode_corebootfb */ +int ast_driver_framebuffer_init(struct drm_device *dev, int flags); +int ast_crtc_do_set_base(struct drm_crtc *crtc); + +/* ast i2c */ +int ast_software_i2c_read(struct ast_private *ast_priv, uint8_t edid[128]); + #endif diff --git a/src/drivers/aspeed/common/ast_i2c.c b/src/drivers/aspeed/common/ast_i2c.c new file mode 100644 index 0000000..0838d10 --- /dev/null +++ b/src/drivers/aspeed/common/ast_i2c.c @@ -0,0 +1,140 @@ +/* + * Copied from Linux drivers/gpu/drm/ast/ast_mode.c + * + * Copyright 2012 Red Hat Inc. + * Parts based on xf86-video-ast + * Copyright (c) 2005 ASPEED Technology Inc. + * Copyright Dave Airlie airlied@redhat.com + * Copyright 2019 9Elements Agency GmbH patrick.rudolph@9elements.com + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + */ + +#include <delay.h> +#include <device/i2c_simple.h> + +#include "ast_drv.h" + +static struct ast_private *ast; + +#define _GET_INDEX_REG(x) ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, (x)) +#define ASPEED_BUS 0 + +static int get_clock(unsigned int bus) +{ + uint32_t val, val2, count, pass; + + count = 0; + pass = 0; + val = (_GET_INDEX_REG(0x10) >> 4) & 0x01; + do { + val2 = (_GET_INDEX_REG(0x10) >> 4) & 0x01; + if (val == val2) { + pass++; + } else { + pass = 0; + val = (_GET_INDEX_REG(0x10) >> 4) & 0x01; + } + } while ((pass < 5) && (count++ < 0x10000)); + + return val & 1 ? 1 : 0; +} + +static int get_data(unsigned int bus) +{ + uint32_t val, val2, count, pass; + + count = 0; + pass = 0; + val = (_GET_INDEX_REG(0x20) >> 5) & 0x01; + do { + val2 = (_GET_INDEX_REG(0x20) >> 5) & 0x01; + if (val == val2) { + pass++; + } else { + pass = 0; + val = (_GET_INDEX_REG(0x20) >> 5) & 0x01; + } + } while ((pass < 5) && (count++ < 0x10000)); + + return val & 1 ? 1 : 0; +} + +static void set_clock(unsigned int bus, int clock) +{ + int i; + u8 ujcrb7, jtemp; + + for (i = 0; i < 0x10000; i++) { + ujcrb7 = ((clock & 0x01) ? 0 : 1); + ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0xf4, ujcrb7); + jtemp = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x01); + if (ujcrb7 == jtemp) + break; + } +} + +static void set_data(unsigned int bus, int data) +{ + int i; + u8 ujcrb7, jtemp; + + for (i = 0; i < 0x10000; i++) { + ujcrb7 = ((data & 0x01) ? 0 : 1) << 2; + ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0xf1, ujcrb7); + jtemp = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x04); + if (ujcrb7 == jtemp) + break; + } +} + +static struct software_i2c_ops ast_ops = { + .set_sda = set_data, + .set_scl = set_clock, + .get_sda = get_data, + .get_scl = get_clock, +}; + +int ast_software_i2c_read(struct ast_private *ast_priv, uint8_t edid[128]) +{ + struct software_i2c_ops *backup; + int ret; + + backup = software_i2c[ASPEED_BUS]; + + software_i2c[ASPEED_BUS] = &ast_ops; + + ast = ast_priv; + + /* Ast POST pulled SDA and SCL low, recover the bus to a known state */ + set_clock(ASPEED_BUS, 1); + set_data(ASPEED_BUS, 1); + + udelay(100); + + /* Need to reset internal EEPROM counter to 0 */ + ret = i2c_read_bytes(ASPEED_BUS, 0x50, 0, edid, 128); + + software_i2c[ASPEED_BUS] = backup; + + return ret; +} diff --git a/src/drivers/aspeed/common/ast_mode.c b/src/drivers/aspeed/common/ast_mode.c new file mode 100644 index 0000000..2b6cedae --- /dev/null +++ b/src/drivers/aspeed/common/ast_mode.c @@ -0,0 +1,601 @@ +/* + * Copied from Linux drivers/gpu/drm/ast/ast_mode.c + * + * Copyright 2012 Red Hat Inc. + * Parts based on xf86-video-ast + * Copyright (c) 2005 ASPEED Technology Inc. + * Copyright Dave Airlie airlied@redhat.com + * Copyright 2019 9Elements Agency GmbH patrick.rudolph@9elements.com + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * Please try to keep as close as possible to the upstream source. + */ + +#include "ast_drv.h" +#include "ast_tables.h" + + +static inline void ast_load_palette_index(struct ast_private *ast, + u8 index, u8 red, u8 green, + u8 blue) +{ + ast_io_write8(ast, AST_IO_DAC_INDEX_WRITE, index); + ast_io_read8(ast, AST_IO_SEQ_PORT); + ast_io_write8(ast, AST_IO_DAC_DATA, red); + ast_io_read8(ast, AST_IO_SEQ_PORT); + ast_io_write8(ast, AST_IO_DAC_DATA, green); + ast_io_read8(ast, AST_IO_SEQ_PORT); + ast_io_write8(ast, AST_IO_DAC_DATA, blue); + ast_io_read8(ast, AST_IO_SEQ_PORT); +} + +static void ast_crtc_load_lut(struct drm_crtc *crtc) +{ + struct ast_private *ast = crtc->dev->dev_private; + /* FIXME: Gamma cor 2.6 ? */ + for (int i = 0; i < 256; i++) + ast_load_palette_index(ast, i, i, i, i); + +} + +static bool ast_get_vbios_mode_info(struct drm_crtc *crtc, struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode, + struct ast_vbios_mode_info *vbios_mode) +{ + struct ast_private *ast = crtc->dev->dev_private; + const struct drm_framebuffer *fb = crtc->primary->fb; + u32 refresh_rate_index = 0, mode_id, color_index, refresh_rate; + const struct ast_vbios_enhtable *best = NULL; + u32 hborder, vborder; + bool check_sync; + + switch (fb->format->cpp[0] * 8) { + case 8: + vbios_mode->std_table = &vbios_stdtable[VGAModeIndex]; + color_index = VGAModeIndex - 1; + break; + case 16: + vbios_mode->std_table = &vbios_stdtable[HiCModeIndex]; + color_index = HiCModeIndex; + break; + case 24: + case 32: + vbios_mode->std_table = &vbios_stdtable[TrueCModeIndex]; + color_index = TrueCModeIndex; + break; + default: + return false; + } + + switch (crtc->mode.crtc_hdisplay) { + case 640: + vbios_mode->enh_table = &res_640x480[refresh_rate_index]; + break; + case 800: + vbios_mode->enh_table = &res_800x600[refresh_rate_index]; + break; + case 1024: + vbios_mode->enh_table = &res_1024x768[refresh_rate_index]; + break; + case 1280: + if (crtc->mode.crtc_vdisplay == 800) + vbios_mode->enh_table = &res_1280x800[refresh_rate_index]; + else + vbios_mode->enh_table = &res_1280x1024[refresh_rate_index]; + break; + case 1360: + vbios_mode->enh_table = &res_1360x768[refresh_rate_index]; + break; + case 1440: + vbios_mode->enh_table = &res_1440x900[refresh_rate_index]; + break; + case 1600: + if (crtc->mode.crtc_vdisplay == 900) + vbios_mode->enh_table = &res_1600x900[refresh_rate_index]; + else + vbios_mode->enh_table = &res_1600x1200[refresh_rate_index]; + break; + case 1680: + vbios_mode->enh_table = &res_1680x1050[refresh_rate_index]; + break; + case 1920: + if (crtc->mode.crtc_vdisplay == 1080) + vbios_mode->enh_table = &res_1920x1080[refresh_rate_index]; + else + vbios_mode->enh_table = &res_1920x1200[refresh_rate_index]; + break; + default: + return false; + } + + refresh_rate = mode->vrefresh; + check_sync = vbios_mode->enh_table->flags & WideScreenMode; + do { + const struct ast_vbios_enhtable *loop = vbios_mode->enh_table; + + while (loop->refresh_rate != 0xff) { + if ((check_sync) && + (((mode->flags & DRM_MODE_FLAG_NVSYNC) && + (loop->flags & PVSync)) || + ((mode->flags & DRM_MODE_FLAG_PVSYNC) && + (loop->flags & NVSync)) || + ((mode->flags & DRM_MODE_FLAG_NHSYNC) && + (loop->flags & PHSync)) || + ((mode->flags & DRM_MODE_FLAG_PHSYNC) && + (loop->flags & NHSync)))) { + loop++; + continue; + } + if (loop->refresh_rate <= refresh_rate + && (!best || loop->refresh_rate > best->refresh_rate)) + best = loop; + loop++; + } + if (best || !check_sync) + break; + check_sync = 0; + } while (1); + if (best) + vbios_mode->enh_table = best; + + hborder = (vbios_mode->enh_table->flags & HBorder) ? 8 : 0; + vborder = (vbios_mode->enh_table->flags & VBorder) ? 8 : 0; + + adjusted_mode->crtc_htotal = vbios_mode->enh_table->ht; + adjusted_mode->crtc_hblank_start = vbios_mode->enh_table->hde + hborder; + adjusted_mode->crtc_hblank_end = vbios_mode->enh_table->ht - hborder; + adjusted_mode->crtc_hsync_start = vbios_mode->enh_table->hde + hborder + + vbios_mode->enh_table->hfp; + adjusted_mode->crtc_hsync_end = (vbios_mode->enh_table->hde + hborder + + vbios_mode->enh_table->hfp + + vbios_mode->enh_table->hsync); + + adjusted_mode->crtc_vtotal = vbios_mode->enh_table->vt; + adjusted_mode->crtc_vblank_start = vbios_mode->enh_table->vde + vborder; + adjusted_mode->crtc_vblank_end = vbios_mode->enh_table->vt - vborder; + adjusted_mode->crtc_vsync_start = vbios_mode->enh_table->vde + vborder + + vbios_mode->enh_table->vfp; + adjusted_mode->crtc_vsync_end = (vbios_mode->enh_table->vde + vborder + + vbios_mode->enh_table->vfp + + vbios_mode->enh_table->vsync); + + refresh_rate_index = vbios_mode->enh_table->refresh_rate_index; + mode_id = vbios_mode->enh_table->mode_id; + + if (ast->chip == AST1180) { + /* TODO 1180 */ + } else { + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x8c, (u8)((color_index & 0xf) << 4)); + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x8d, refresh_rate_index & 0xff); + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x8e, mode_id & 0xff); + + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x91, 0x00); + if (vbios_mode->enh_table->flags & NewModeInfo) { + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x91, 0xa8); + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x92, + fb->format->cpp[0] * 8); + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x93, + adjusted_mode->clock / 1000); + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x94, + adjusted_mode->crtc_hdisplay); + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x95, + adjusted_mode->crtc_hdisplay >> 8); + + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x96, + adjusted_mode->crtc_vdisplay); + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x97, + adjusted_mode->crtc_vdisplay >> 8); + } + } + + return true; +} + +static void ast_set_std_reg(struct drm_crtc *crtc, struct drm_display_mode *mode, + struct ast_vbios_mode_info *vbios_mode) +{ + struct ast_private *ast = crtc->dev->dev_private; + const struct drm_framebuffer *fb = crtc->primary->fb; + const struct ast_vbios_stdtable *stdtable; + u32 i; + u8 jreg; + + switch (fb->format->cpp[0] * 8) { + case 8: + stdtable = &vbios_stdtable[VGAModeIndex]; + break; + case 16: + stdtable = &vbios_stdtable[HiCModeIndex]; + break; + case 24: + case 32: + stdtable = &vbios_stdtable[TrueCModeIndex]; + break; + default: + return; + } + + jreg = stdtable->misc; + ast_io_write8(ast, AST_IO_MISC_PORT_WRITE, jreg); + + /* Set SEQ */ + ast_set_index_reg(ast, AST_IO_SEQ_PORT, 0x00, 0x03); + for (i = 0; i < 4; i++) { + jreg = stdtable->seq[i]; + if (!i) + jreg |= 0x20; + ast_set_index_reg(ast, AST_IO_SEQ_PORT, (i + 1), jreg); + } + + /* Set CRTC */ + ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x11, 0x7f, 0x00); + for (i = 0; i < 25; i++) + ast_set_index_reg(ast, AST_IO_CRTC_PORT, i, stdtable->crtc[i]); + + /* set AR */ + jreg = ast_io_read8(ast, AST_IO_INPUT_STATUS1_READ); + for (i = 0; i < 20; i++) { + jreg = stdtable->ar[i]; + ast_io_write8(ast, AST_IO_AR_PORT_WRITE, (u8)i); + ast_io_write8(ast, AST_IO_AR_PORT_WRITE, jreg); + } + ast_io_write8(ast, AST_IO_AR_PORT_WRITE, 0x14); + ast_io_write8(ast, AST_IO_AR_PORT_WRITE, 0x00); + + jreg = ast_io_read8(ast, AST_IO_INPUT_STATUS1_READ); + ast_io_write8(ast, AST_IO_AR_PORT_WRITE, 0x20); + + /* Set GR */ + for (i = 0; i < 9; i++) + ast_set_index_reg(ast, AST_IO_GR_PORT, i, stdtable->gr[i]); +} + +static void ast_set_crtc_reg(struct drm_crtc *crtc, struct drm_display_mode *mode, + struct ast_vbios_mode_info *vbios_mode) +{ + struct ast_private *ast = crtc->dev->dev_private; + u8 jreg05 = 0, jreg07 = 0, jreg09 = 0, jregAC = 0, jregAD = 0, jregAE = 0; + u16 temp, precache = 0; + + if ((ast->chip == AST2500) && + (vbios_mode->enh_table->flags & AST2500PreCatchCRT)) + precache = 40; + + ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x11, 0x7f, 0x00); + + temp = (mode->crtc_htotal >> 3) - 5; + if (temp & 0x100) + jregAC |= 0x01; /* HT D[8] */ + ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x00, 0x00, temp); + + temp = (mode->crtc_hdisplay >> 3) - 1; + if (temp & 0x100) + jregAC |= 0x04; /* HDE D[8] */ + ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x01, 0x00, temp); + + temp = (mode->crtc_hblank_start >> 3) - 1; + if (temp & 0x100) + jregAC |= 0x10; /* HBS D[8] */ + ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x02, 0x00, temp); + + temp = ((mode->crtc_hblank_end >> 3) - 1) & 0x7f; + if (temp & 0x20) + jreg05 |= 0x80; /* HBE D[5] */ + if (temp & 0x40) + jregAD |= 0x01; /* HBE D[5] */ + ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x03, 0xE0, (temp & 0x1f)); + + temp = ((mode->crtc_hsync_start-precache) >> 3) - 1; + if (temp & 0x100) + jregAC |= 0x40; /* HRS D[5] */ + ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x04, 0x00, temp); + + temp = (((mode->crtc_hsync_end-precache) >> 3) - 1) & 0x3f; + if (temp & 0x20) + jregAD |= 0x04; /* HRE D[5] */ + ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x05, 0x60, (u8)((temp & 0x1f) | jreg05)); + + ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xAC, 0x00, jregAC); + ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xAD, 0x00, jregAD); + + /* vert timings */ + temp = (mode->crtc_vtotal) - 2; + if (temp & 0x100) + jreg07 |= 0x01; + if (temp & 0x200) + jreg07 |= 0x20; + if (temp & 0x400) + jregAE |= 0x01; + ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x06, 0x00, temp); + + temp = (mode->crtc_vsync_start) - 1; + if (temp & 0x100) + jreg07 |= 0x04; + if (temp & 0x200) + jreg07 |= 0x80; + if (temp & 0x400) + jregAE |= 0x08; + ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x10, 0x00, temp); + + temp = (mode->crtc_vsync_end - 1) & 0x3f; + if (temp & 0x10) + jregAE |= 0x20; + if (temp & 0x20) + jregAE |= 0x40; + ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x11, 0x70, temp & 0xf); + + temp = mode->crtc_vdisplay - 1; + if (temp & 0x100) + jreg07 |= 0x02; + if (temp & 0x200) + jreg07 |= 0x40; + if (temp & 0x400) + jregAE |= 0x02; + ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x12, 0x00, temp); + + temp = mode->crtc_vblank_start - 1; + if (temp & 0x100) + jreg07 |= 0x08; + if (temp & 0x200) + jreg09 |= 0x20; + if (temp & 0x400) + jregAE |= 0x04; + ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x15, 0x00, temp); + + temp = mode->crtc_vblank_end - 1; + if (temp & 0x100) + jregAE |= 0x10; + ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x16, 0x00, temp); + + ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x07, 0x00, jreg07); + ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x09, 0xdf, jreg09); + ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xAE, 0x00, (jregAE | 0x80)); + + if (precache) + ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0x3f, 0x80); + else + ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0x3f, 0x00); + + ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x11, 0x7f, 0x80); +} + +void ast_set_offset_reg(struct drm_crtc *crtc) +{ + struct ast_private *ast = crtc->dev->dev_private; + const struct drm_framebuffer *fb = crtc->primary->fb; + + u16 offset; + + offset = fb->pitches[0] >> 3; + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x13, (offset & 0xff)); + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xb0, (offset >> 8) & 0x3f); +} + +static void ast_set_dclk_reg(struct drm_device *dev, struct drm_display_mode *mode, + struct ast_vbios_mode_info *vbios_mode) +{ + struct ast_private *ast = dev->dev_private; + const struct ast_vbios_dclk_info *clk_info; + + if (ast->chip == AST2500) + clk_info = &dclk_table_ast2500[vbios_mode->enh_table->dclk_index]; + else + clk_info = &dclk_table[vbios_mode->enh_table->dclk_index]; + + ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xc0, 0x00, clk_info->param1); + ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xc1, 0x00, clk_info->param2); + ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xbb, 0x0f, + (clk_info->param3 & 0xc0) | + ((clk_info->param3 & 0x3) << 4)); +} + +static void ast_set_ext_reg(struct drm_crtc *crtc, struct drm_display_mode *mode, + struct ast_vbios_mode_info *vbios_mode) +{ + struct ast_private *ast = crtc->dev->dev_private; + const struct drm_framebuffer *fb = crtc->primary->fb; + u8 jregA0 = 0, jregA3 = 0, jregA8 = 0; + + switch (fb->format->cpp[0] * 8) { + case 8: + jregA0 = 0x70; + jregA3 = 0x01; + jregA8 = 0x00; + break; + case 15: + case 16: + jregA0 = 0x70; + jregA3 = 0x04; + jregA8 = 0x02; + break; + case 24: + case 32: + jregA0 = 0x70; + jregA3 = 0x08; + jregA8 = 0x02; + break; + } + + ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa0, 0x8f, jregA0); + ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa3, 0xf0, jregA3); + ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa8, 0xfd, jregA8); + + /* Set Threshold */ + if (ast->chip == AST2300 || ast->chip == AST2400 || + ast->chip == AST2500) { + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa7, 0x78); + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa6, 0x60); + } else if (ast->chip == AST2100 || + ast->chip == AST1100 || + ast->chip == AST2200 || + ast->chip == AST2150) { + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa7, 0x3f); + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa6, 0x2f); + } else { + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa7, 0x2f); + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa6, 0x1f); + } +} + +static void ast_set_sync_reg(struct drm_device *dev, struct drm_display_mode *mode, + struct ast_vbios_mode_info *vbios_mode) +{ + struct ast_private *ast = dev->dev_private; + u8 jreg; + + jreg = ast_io_read8(ast, AST_IO_MISC_PORT_READ); + jreg &= ~0xC0; + if (vbios_mode->enh_table->flags & NVSync) + jreg |= 0x80; + if (vbios_mode->enh_table->flags & NHSync) + jreg |= 0x40; + ast_io_write8(ast, AST_IO_MISC_PORT_WRITE, jreg); +} + +void ast_set_start_address_crt1(struct ast_private *ast, u32 offset) +{ + u32 addr; + + addr = offset >> 2; + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x0d, (u8)(addr & 0xff)); + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x0c, (u8)((addr >> 8) & 0xff)); + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xaf, (u8)((addr >> 16) & 0xff)); +} + +void ast_hide_cursor(struct drm_crtc *crtc) +{ + struct ast_private *ast = crtc->dev->dev_private; + ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xcb, 0xfc, 0x00); +} + +int ast_crtc_mode_set(struct drm_crtc *crtc, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + struct drm_device *dev = crtc->dev; + struct ast_private *ast = crtc->dev->dev_private; + struct ast_vbios_mode_info vbios_mode; + bool ret; + int err; + + if (ast->chip == AST1180) { + dev_err(dev->pdev, "AST 1180 modesetting not supported\n"); + return -EINVAL; + } + + /* DPMS, set on */ + ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT, 0x1, 0xdf, 0); + if (ast->tx_chip_type == AST_TX_DP501) + ast_set_dp501_video_output(crtc->dev, 1); + ast_crtc_load_lut(crtc); + + /* Get mode */ + ret = ast_get_vbios_mode_info(crtc, mode, adjusted_mode, &vbios_mode); + if (ret == false) { + dev_err(dev->pdev, "Failed to find compatible vbios mode\n"); + return -EINVAL; + } + ast_open_key(ast); + + ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa1, 0xff, 0x04); + + ast_set_std_reg(crtc, adjusted_mode, &vbios_mode); + ast_set_crtc_reg(crtc, adjusted_mode, &vbios_mode); + ast_set_offset_reg(crtc); + ast_set_dclk_reg(dev, adjusted_mode, &vbios_mode); + ast_set_ext_reg(crtc, adjusted_mode, &vbios_mode); + ast_set_sync_reg(dev, adjusted_mode, &vbios_mode); + + err = ast_crtc_do_set_base(crtc); + if (err) + return err; + + /* Commit changes */ + + ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT, 0x1, 0xdf, 0); + ast_crtc_load_lut(crtc); + + return 0; +} + +enum drm_mode_status ast_mode_valid(struct drm_connector *connector, + const unsigned int hdisplay, const unsigned int vdisplay) +{ + struct ast_private *ast = connector->dev->dev_private; + int flags = MODE_NOMODE; + uint32_t jtemp; + + if (ast->support_wide_screen) { + if ((hdisplay == 1680) && (vdisplay == 1050)) + return MODE_OK; + if ((hdisplay == 1280) && (vdisplay == 800)) + return MODE_OK; + if ((hdisplay == 1440) && (vdisplay == 900)) + return MODE_OK; + if ((hdisplay == 1360) && (vdisplay == 768)) + return MODE_OK; + if ((hdisplay == 1600) && (vdisplay == 900)) + return MODE_OK; + + if ((ast->chip == AST2100) || (ast->chip == AST2200) || + (ast->chip == AST2300) || (ast->chip == AST2400) || + (ast->chip == AST2500) || (ast->chip == AST1180)) { + if ((hdisplay == 1920) && (vdisplay == 1080)) + return MODE_OK; + + if ((hdisplay == 1920) && (vdisplay == 1200)) { + jtemp = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd1, + 0xff); + if (jtemp & 0x01) + return MODE_NOMODE; + else + return MODE_OK; + } + } + } + switch (hdisplay) { + case 640: + if (vdisplay == 480) + flags = MODE_OK; + break; + case 800: + if (vdisplay == 600) + flags = MODE_OK; + break; + case 1024: + if (vdisplay == 768) + flags = MODE_OK; + break; + case 1280: + if (vdisplay == 1024) + flags = MODE_OK; + break; + case 1600: + if (vdisplay == 1200) + flags = MODE_OK; + break; + default: + return flags; + } + + return flags; +} diff --git a/src/drivers/aspeed/common/ast_mode_corebootfb.c b/src/drivers/aspeed/common/ast_mode_corebootfb.c new file mode 100644 index 0000000..2ec85ac --- /dev/null +++ b/src/drivers/aspeed/common/ast_mode_corebootfb.c @@ -0,0 +1,256 @@ +/* + * Copied from Linux drivers/gpu/drm/ast/ast_mode.c + * + * Copyright 2012 Red Hat Inc. + * Parts based on xf86-video-ast + * Copyright (c) 2005 ASPEED Technology Inc. + * Copyright Dave Airlie airlied@redhat.com + * Copyright 2019 9Elements Agency GmbH patrick.rudolph@9elements.com + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + */ + +#include <edid.h> + +#include "ast_drv.h" + +/* + * Set framebuffer MMIO address, which must fall into BAR0 MMIO window. + * + * Complete reimplementation as the original expects multiple kernel internal + * subsystems to be present. + */ +int ast_crtc_do_set_base(struct drm_crtc *crtc) +{ + struct ast_private *ast = crtc->dev->dev_private; + struct drm_framebuffer *fb = crtc->primary->fb; + + /* PCI BAR 0 */ + struct resource *res = find_resource(crtc->dev->pdev, 0x10); + if (!res) { + printk(BIOS_ERR, "BAR0 resource not found.\n"); + return -EIO; + } + + if (res->size < fb->pitches[0] * crtc->mode.vdisplay) { + dev_err(dev->pdev, "Framebuffer doesn't fit into BAR0 MMIO window\n"); + return -ENOMEM; + } + + fb->mmio_addr = (u32)res2mmio(res, 4095, 4095); + + ast_set_offset_reg(crtc); + ast_set_start_address_crt1(ast, fb->mmio_addr); + + return 0; +} + +static void ast_edid_to_drmmode(struct edid *edid, struct drm_display_mode *mode) +{ + memset(mode, 0, sizeof(*mode)); + + mode->hdisplay = edid->mode.ha; + mode->vdisplay = edid->mode.va; + mode->crtc_hdisplay = edid->mode.ha; + mode->crtc_vdisplay = edid->mode.va; + + /* EDID clock is in 10kHz, but drm clock is in KHz */ + mode->clock = edid->mode.pixel_clock * 10; + mode->vrefresh = edid->mode.refresh; + + mode->crtc_hblank_start = edid->mode.ha; + mode->crtc_hblank_end = edid->mode.ha + edid->mode.hbl; + mode->crtc_hsync_start = edid->mode.ha + edid->mode.hso; + mode->crtc_hsync_end = edid->mode.ha + edid->mode.hso + edid->mode.hspw; + mode->crtc_htotal = mode->crtc_hblank_end; + + mode->crtc_vblank_start = edid->mode.va; + mode->crtc_vblank_end = edid->mode.va + edid->mode.vbl; + mode->crtc_vsync_start = edid->mode.va + edid->mode.vso; + mode->crtc_vsync_end = edid->mode.va + edid->mode.vso + edid->mode.vspw; + mode->crtc_vtotal = mode->crtc_vblank_end; + + mode->flags = 0; + if (edid->mode.phsync == '+') + mode->flags |= DRM_MODE_FLAG_PHSYNC; + else + mode->flags |= DRM_MODE_FLAG_NHSYNC; + + if (edid->mode.pvsync == '+') + mode->flags |= DRM_MODE_FLAG_PVSYNC; + else + mode->flags |= DRM_MODE_FLAG_NVSYNC; +} + +static int ast_select_mode(struct drm_connector *connector, + struct edid *edid) +{ + struct ast_private *ast = connector->dev->dev_private; + bool widescreen; + u8 raw[128]; + bool flags = false; + + if (ast->tx_chip_type == AST_TX_DP501) { + ast->dp501_maxclk = 0xff; + flags = ast_dp501_read_edid(connector->dev, (u8 *)raw); + if (flags) + ast->dp501_maxclk = ast_get_dp501_max_clk(connector->dev); + else + dev_err(dev->pdev, "I2C transmission error\n"); + } + + if (!flags) + ast_software_i2c_read(ast, raw); + + if (decode_edid(raw, sizeof(raw), edid) != EDID_CONFORMANT) { + dev_err(dev->pdev, "Failed to decode EDID\n"); + printk(BIOS_DEBUG, "Assuming VGA for KVM\n"); + + memset(edid, 0, sizeof(*edid)); + + edid->mode.pixel_clock = 6411; + edid->mode.refresh = 60; + edid->mode.ha = 1024; + edid->mode.hspw = 4; + edid->mode.hso = 56; + edid->mode.hbl = 264; + edid->mode.phsync = '-'; + + edid->mode.va = 768; + edid->mode.vspw = 3; + edid->mode.vso = 1; + edid->mode.vbl = 26; + edid->mode.pvsync = '+'; + } + + printk(BIOS_DEBUG, "AST: Display has %dpx x %dpx\n", edid->mode.ha, edid->mode.va); + + widescreen = !!(((edid->mode.ha * 4) % (edid->mode.va * 3))); + + while (ast_mode_valid(connector, edid->mode.ha, edid->mode.va) != MODE_OK) { + /* Select a compatible smaller mode */ + if (edid->mode.ha > 1920 && widescreen) { + edid->mode.ha = 1920; + edid->mode.va = 1080; + } else if (edid->mode.ha >= 1920 && widescreen) { + edid->mode.ha = 1680; + edid->mode.va = 1050; + } else if (edid->mode.ha >= 1680 && widescreen) { + edid->mode.ha = 1600; + edid->mode.va = 900; + } else if (edid->mode.ha >= 1680 && !widescreen) { + edid->mode.ha = 1600; + edid->mode.va = 1200; + } else if (edid->mode.ha >= 1600 && widescreen) { + edid->mode.ha = 1440; + edid->mode.va = 900; + } else if (edid->mode.ha >= 1440 && widescreen) { + edid->mode.ha = 1360; + edid->mode.va = 768; + } else if (edid->mode.ha >= 1360 && widescreen) { + edid->mode.ha = 1280; + edid->mode.va = 800; + } else if (edid->mode.ha >= 1360 && !widescreen) { + edid->mode.ha = 1280; + edid->mode.va = 1024; + } else if (edid->mode.ha >= 1280) { + edid->mode.ha = 1024; + edid->mode.va = 768; + } else if (edid->mode.ha >= 1024) { + edid->mode.ha = 800; + edid->mode.va = 600; + } else if (edid->mode.ha >= 800) { + edid->mode.ha = 640; + edid->mode.va = 480; + } else { + dev_err(dev->pdev, "No compatible mode found.\n"); + + return -EIO; + } + }; + + return 0; +} + +int ast_driver_framebuffer_init(struct drm_device *dev, int flags) +{ + struct drm_display_mode adjusted_mode; + struct drm_crtc crtc; + struct drm_format format; + struct drm_primary primary; + struct drm_framebuffer fb; + struct drm_connector connector; + struct edid edid; + int ret; + + /* Init wrapper structs */ + connector.dev = dev; + + format.cpp[0] = 4; /* 32 BPP */ + fb.format = &format; + + primary.fb = &fb; + + crtc.dev = dev; + crtc.primary = &primary; + + /* Read EDID and find mode */ + ret = ast_select_mode(&connector, &edid); + if (ret) { + dev_err(dev->pdev, "Failed to select mode.\n"); + return ret; + } + + /* Updated edid for set_vbe_mode_info_valid */ + edid.x_resolution = edid.mode.ha; + edid.y_resolution = edid.mode.va; + edid.framebuffer_bits_per_pixel = format.cpp[0] * 8; + edid.bytes_per_line = ALIGN_UP(edid.x_resolution * format.cpp[0], 8); + + /* Updated framebuffer info for ast_crtc_mode_set */ + fb.pitches[0] = edid.bytes_per_line; + + printk(BIOS_DEBUG, "Using framebuffer %dpx x %dpx pitch %d @ %d BPP\n", + edid.x_resolution, edid.y_resolution, edid.bytes_per_line, + edid.framebuffer_bits_per_pixel); + + /* Convert EDID to AST DRM mode */ + ast_edid_to_drmmode(&edid, &crtc.mode); + + memcpy(&adjusted_mode, &crtc.mode, sizeof(crtc.mode)); + + ret = ast_crtc_mode_set(&crtc, &crtc.mode, &adjusted_mode); + if (ret) { + dev_err(dev->pdev, "Failed to set mode.\n"); + return ret; + } + + ast_hide_cursor(&crtc); + + /* Advertise new mode */ + set_vbe_mode_info_valid(&edid, fb.mmio_addr); + + /* Clear display */ + memset((void *)fb.mmio_addr, 0, edid.bytes_per_line * edid.y_resolution); + + return 0; +} diff --git a/src/drivers/aspeed/common/ast_tables.h b/src/drivers/aspeed/common/ast_tables.h index ae3c6d0..27b0172 100644 --- a/src/drivers/aspeed/common/ast_tables.h +++ b/src/drivers/aspeed/common/ast_tables.h @@ -49,6 +49,7 @@ #define SyncPN (PVSync | NHSync) #define SyncNP (NVSync | PHSync) #define SyncNN (NVSync | NHSync) +#define AST2500PreCatchCRT 0x00004000
/* DCLK Index */ #define VCLK25_175 0x00 @@ -110,80 +111,110 @@ {0x3b, 0x2c, 0x81}, /* 1A: VCLK118_25 */ };
+static const struct ast_vbios_dclk_info dclk_table_ast2500[] = { + {0x2C, 0xE7, 0x03}, /* 00: VCLK25_175 */ + {0x95, 0x62, 0x03}, /* 01: VCLK28_322 */ + {0x67, 0x63, 0x01}, /* 02: VCLK31_5 */ + {0x76, 0x63, 0x01}, /* 03: VCLK36 */ + {0xEE, 0x67, 0x01}, /* 04: VCLK40 */ + {0x82, 0x62, 0x01}, /* 05: VCLK49_5 */ + {0xC6, 0x64, 0x01}, /* 06: VCLK50 */ + {0x94, 0x62, 0x01}, /* 07: VCLK56_25 */ + {0x80, 0x64, 0x00}, /* 08: VCLK65 */ + {0x7B, 0x63, 0x00}, /* 09: VCLK75 */ + {0x67, 0x62, 0x00}, /* 0A: VCLK78_75 */ + {0x7C, 0x62, 0x00}, /* 0B: VCLK94_5 */ + {0x8E, 0x62, 0x00}, /* 0C: VCLK108 */ + {0x85, 0x24, 0x00}, /* 0D: VCLK135 */ + {0x67, 0x22, 0x00}, /* 0E: VCLK157_5 */ + {0x6A, 0x22, 0x00}, /* 0F: VCLK162 */ + {0x4d, 0x4c, 0x80}, /* 10: VCLK154 */ + {0x68, 0x6f, 0x80}, /* 11: VCLK83.5 */ + {0x28, 0x49, 0x80}, /* 12: VCLK106.5 */ + {0x37, 0x49, 0x80}, /* 13: VCLK146.25 */ + {0x1f, 0x45, 0x80}, /* 14: VCLK148.5 */ + {0x47, 0x6c, 0x80}, /* 15: VCLK71 */ + {0x25, 0x65, 0x80}, /* 16: VCLK88.75 */ + {0x58, 0x01, 0x42}, /* 17: VCLK119 */ + {0x32, 0x67, 0x80}, /* 18: VCLK85_5 */ + {0x6a, 0x6d, 0x80}, /* 19: VCLK97_75 */ + {0x44, 0x20, 0x43}, /* 1A: VCLK118_25 */ +}; + static struct ast_vbios_stdtable vbios_stdtable[] = { /* MD_2_3_400 */ { 0x67, - {0x00,0x03,0x00,0x02}, - {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f, - 0x00,0x4f,0x0d,0x0e,0x00,0x00,0x00,0x00, - 0x9c,0x8e,0x8f,0x28,0x1f,0x96,0xb9,0xa3, - 0xff}, - {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07, - 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f, - 0x0c,0x00,0x0f,0x08}, - {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00, - 0xff} + {0x00, 0x03, 0x00, 0x02}, + {0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f, + 0x00, 0x4f, 0x0d, 0x0e, 0x00, 0x00, 0x00, 0x00, + 0x9c, 0x8e, 0x8f, 0x28, 0x1f, 0x96, 0xb9, 0xa3, + 0xff}, + {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x0c, 0x00, 0x0f, 0x08}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x00, + 0xff} }, /* Mode12/ExtEGATable */ { 0xe3, - {0x01,0x0f,0x00,0x06}, - {0x5f,0x4f,0x50,0x82,0x55,0x81,0x0b,0x3e, - 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00, - 0xe9,0x8b,0xdf,0x28,0x00,0xe7,0x04,0xe3, - 0xff}, - {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07, - 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f, - 0x01,0x00,0x0f,0x00}, - {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0f, - 0xff} + {0x01, 0x0f, 0x00, 0x06}, + {0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0x0b, 0x3e, + 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xe9, 0x8b, 0xdf, 0x28, 0x00, 0xe7, 0x04, 0xe3, + 0xff}, + {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x01, 0x00, 0x0f, 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0f, + 0xff} }, /* ExtVGATable */ { 0x2f, - {0x01,0x0f,0x00,0x0e}, - {0x5f,0x4f,0x50,0x82,0x54,0x80,0x0b,0x3e, - 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00, - 0xea,0x8c,0xdf,0x28,0x40,0xe7,0x04,0xa3, - 0xff}, - {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, - 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f, - 0x01,0x00,0x00,0x00}, - {0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0f, - 0xff} + {0x01, 0x0f, 0x00, 0x0e}, + {0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0x0b, 0x3e, + 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xea, 0x8c, 0xdf, 0x28, 0x40, 0xe7, 0x04, 0xa3, + 0xff}, + {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x01, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0f, + 0xff} }, /* ExtHiCTable */ { 0x2f, - {0x01,0x0f,0x00,0x0e}, - {0x5f,0x4f,0x50,0x82,0x54,0x80,0x0b,0x3e, - 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00, - 0xea,0x8c,0xdf,0x28,0x40,0xe7,0x04,0xa3, - 0xff}, - {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, - 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f, - 0x01,0x00,0x00,0x00}, - {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0f, - 0xff} + {0x01, 0x0f, 0x00, 0x0e}, + {0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0x0b, 0x3e, + 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xea, 0x8c, 0xdf, 0x28, 0x40, 0xe7, 0x04, 0xa3, + 0xff}, + {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x01, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0f, + 0xff} }, /* ExtTrueCTable */ { 0x2f, - {0x01,0x0f,0x00,0x0e}, - {0x5f,0x4f,0x50,0x82,0x54,0x80,0x0b,0x3e, - 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00, - 0xea,0x8c,0xdf,0x28,0x40,0xe7,0x04,0xa3, + {0x01, 0x0f, 0x00, 0x0e}, + {0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0x0b, 0x3e, + 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xea, 0x8c, 0xdf, 0x28, 0x40, 0xe7, 0x04, 0xa3, 0xff}, - {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, - 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f, - 0x01,0x00,0x00,0x00}, - {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0f, + {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x01, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0f, 0xff} }, };
-static struct ast_vbios_enhtable res_640x480[] = { +static const struct ast_vbios_enhtable res_640x480[] = { { 800, 640, 8, 96, 525, 480, 2, 2, VCLK25_175, /* 60Hz */ (SyncNN | HBorder | VBorder | Charx8Dot), 60, 1, 0x2E }, { 832, 640, 16, 40, 520, 480, 1, 3, VCLK31_5, /* 72Hz */ @@ -196,7 +227,7 @@ (SyncNN | Charx8Dot) , 0xFF, 4, 0x2E }, };
-static struct ast_vbios_enhtable res_800x600[] = { +static const struct ast_vbios_enhtable res_800x600[] = { {1024, 800, 24, 72, 625, 600, 1, 2, VCLK36, /* 56Hz */ (SyncPP | Charx8Dot), 56, 1, 0x30 }, {1056, 800, 40, 128, 628, 600, 1, 4, VCLK40, /* 60Hz */ @@ -212,7 +243,7 @@ };
-static struct ast_vbios_enhtable res_1024x768[] = { +static const struct ast_vbios_enhtable res_1024x768[] = { {1344, 1024, 24, 136, 806, 768, 3, 6, VCLK65, /* 60Hz */ (SyncNN | Charx8Dot), 60, 1, 0x31 }, {1328, 1024, 24, 136, 806, 768, 3, 6, VCLK75, /* 70Hz */ @@ -225,7 +256,7 @@ (SyncPP | Charx8Dot), 0xFF, 4, 0x31 }, };
-static struct ast_vbios_enhtable res_1280x1024[] = { +static const struct ast_vbios_enhtable res_1280x1024[] = { {1688, 1280, 48, 112, 1066, 1024, 1, 3, VCLK108, /* 60Hz */ (SyncPP | Charx8Dot), 60, 1, 0x32 }, {1688, 1280, 16, 144, 1066, 1024, 1, 3, VCLK135, /* 75Hz */ @@ -236,7 +267,7 @@ (SyncPP | Charx8Dot), 0xFF, 3, 0x32 }, };
-static struct ast_vbios_enhtable res_1600x1200[] = { +static const struct ast_vbios_enhtable res_1600x1200[] = { {2160, 1600, 64, 192, 1250, 1200, 1, 3, VCLK162, /* 60Hz */ (SyncPP | Charx8Dot), 60, 1, 0x33 }, {2160, 1600, 64, 192, 1250, 1200, 1, 3, VCLK162, /* end */ @@ -244,34 +275,39 @@ };
/* 16:9 */ -static struct ast_vbios_enhtable res_1360x768[] = { - {1792, 1360, 64,112, 795, 768, 3, 6, VCLK85_5, /* 60Hz */ +static const struct ast_vbios_enhtable res_1360x768[] = { + {1792, 1360, 64, 112, 795, 768, 3, 6, VCLK85_5, /* 60Hz */ (SyncPP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 60, 1, 0x39 }, - {1792, 1360, 64,112, 795, 768, 3, 6, VCLK85_5, /* end */ - (SyncPP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 0xFF, 1, 0x39 }, + {1792, 1360, 64, 112, 795, 768, 3, 6, VCLK85_5, /* end */ + (SyncPP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo | + AST2500PreCatchCRT), 0xFF, 1, 0x39 }, };
-static struct ast_vbios_enhtable res_1600x900[] = { - {1760, 1600, 48, 32, 926, 900, 3, 5, VCLK97_75, /* 60Hz CVT RB */ - (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 60, 1, 0x3A }, - {2112, 1600, 88,168, 934, 900, 3, 5, VCLK118_25, /* 60Hz CVT */ +static const struct ast_vbios_enhtable res_1600x900[] = { + {1760, 1600, 48, 32, 926, 900, 3, 5, VCLK97_75, /* 60Hz CVT RB */ + (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo | + AST2500PreCatchCRT), 60, 1, 0x3A }, + {2112, 1600, 88, 168, 934, 900, 3, 5, VCLK118_25, /* 60Hz CVT */ (SyncPN | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 60, 2, 0x3A }, - {2112, 1600, 88,168, 934, 900, 3, 5, VCLK118_25, /* 60Hz CVT */ + {2112, 1600, 88, 168, 934, 900, 3, 5, VCLK118_25, /* 60Hz CVT */ (SyncPN | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 0xFF, 2, 0x3A }, };
-static struct ast_vbios_enhtable res_1920x1080[] = { +static const struct ast_vbios_enhtable res_1920x1080[] = { {2200, 1920, 88, 44, 1125, 1080, 4, 5, VCLK148_5, /* 60Hz */ - (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 60, 1, 0x38 }, + (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo | + AST2500PreCatchCRT), 60, 1, 0x38 }, {2200, 1920, 88, 44, 1125, 1080, 4, 5, VCLK148_5, /* 60Hz */ - (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 0xFF, 1, 0x38 }, + (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo | + AST2500PreCatchCRT), 0xFF, 1, 0x38 }, };
/* 16:10 */ -static struct ast_vbios_enhtable res_1280x800[] = { +static const struct ast_vbios_enhtable res_1280x800[] = { {1440, 1280, 48, 32, 823, 800, 3, 6, VCLK71, /* 60Hz RB */ - (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 60, 1, 0x35 }, + (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo | + AST2500PreCatchCRT), 60, 1, 0x35 }, {1680, 1280, 72,128, 831, 800, 3, 6, VCLK83_5, /* 60Hz */ (SyncPN | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 60, 2, 0x35 }, {1680, 1280, 72,128, 831, 800, 3, 6, VCLK83_5, /* 60Hz */ @@ -279,29 +315,32 @@
};
-static struct ast_vbios_enhtable res_1440x900[] = { +static const struct ast_vbios_enhtable res_1440x900[] = { {1600, 1440, 48, 32, 926, 900, 3, 6, VCLK88_75, /* 60Hz RB */ - (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 60, 1, 0x36 }, + (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo | + AST2500PreCatchCRT), 60, 1, 0x36 }, {1904, 1440, 80,152, 934, 900, 3, 6, VCLK106_5, /* 60Hz */ (SyncPN | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 60, 2, 0x36 }, {1904, 1440, 80,152, 934, 900, 3, 6, VCLK106_5, /* 60Hz */ (SyncPN | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 0xFF, 2, 0x36 }, };
-static struct ast_vbios_enhtable res_1680x1050[] = { +static const struct ast_vbios_enhtable res_1680x1050[] = { {1840, 1680, 48, 32, 1080, 1050, 3, 6, VCLK119, /* 60Hz RB */ - (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 60, 1, 0x37 }, + (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo | + AST2500PreCatchCRT), 60, 1, 0x37 }, {2240, 1680,104,176, 1089, 1050, 3, 6, VCLK146_25, /* 60Hz */ (SyncPN | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 60, 2, 0x37 }, {2240, 1680,104,176, 1089, 1050, 3, 6, VCLK146_25, /* 60Hz */ (SyncPN | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 0xFF, 2, 0x37 }, };
-static struct ast_vbios_enhtable res_1920x1200[] = { +static const struct ast_vbios_enhtable res_1920x1200[] = { {2080, 1920, 48, 32, 1235, 1200, 3, 6, VCLK154, /* 60Hz RB*/ - (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 60, 1, 0x34 }, - {2080, 1920, 48, 32, 1235, 1200, 3, 6, VCLK154, /* 60Hz RB */ - (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 0xFF, 1, 0x34 }, + (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo | + AST2500PreCatchCRT), 60, 1, 0x34 }, + {2080, 1920, 48, 32, 1235, 1200, 3, 6, VCLK154, /* 60Hz RB */ + (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo | + AST2500PreCatchCRT), 0xFF, 1, 0x34 }, }; - #endif
Matt DeVillier has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/35726 )
Change subject: drivers/aspeed/common: Add support for high resolution framebuffer ......................................................................
Patch Set 14:
based on the inclusion of i2c_simple.h, this would seem to only work on boards which also offer hardware I2C, otherwise platform_i2c_transfer() remains unimplemented and causes a linking error. Can hack around it with preprocessor guards, but not exactly pretty.
Nico Huber has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/35726 )
Change subject: drivers/aspeed/common: Add support for high resolution framebuffer ......................................................................
Patch Set 14:
based on the inclusion of i2c_simple.h, this would seem to only work on boards which also offer hardware I2C, otherwise platform_i2c_transfer() remains unimplemented and causes a linking error. Can hack around it with preprocessor guards, but not exactly pretty.
Took me a moment to figure out why: The call to platform_i2c_transfer() is not garbage collected because the call to software_i2c_transfer() is runtime conditional (based on the bus number).
i2c_simple is messy and will stay that way unless we define some rules (e.g. let mainboard code assign bus numbers). The problem is that it is designed for a single chip does everything solution (and don't you dare to put another I2C controller on a board). It's just incompatible to this case. For the moment, adding more Kconfig and if's, would do. But to be scalable, it would need function pointers per bus that are registered during runtime; and that would bring it unlikely close to `i2c_bus.h`.
There is only one entity in coreboot that can glue such things properly together: the mainboard code. In the convenient case, this is done via the devicetree.
Nico Huber has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/35726 )
Change subject: drivers/aspeed/common: Add support for high resolution framebuffer ......................................................................
Patch Set 14:
based on the inclusion of i2c_simple.h, this would seem to only work on boards which also offer hardware I2C, otherwise platform_i2c_transfer() remains unimplemented and causes a linking error. Can hack around it with preprocessor guards, but not exactly pretty.
Took me a moment to figure out why: The call to platform_i2c_transfer() is not garbage collected because the call to software_i2c_transfer() is runtime conditional (based on the bus number).
i2c_simple is messy and will stay that way unless we define some rules (e.g. let mainboard code assign bus numbers). The problem is that it is designed for a single chip does everything solution (and don't you dare to put another I2C controller on a board). It's just incompatible to this case. For the moment, adding more Kconfig and if's, would do. But to be scalable, it would need function pointers per bus that are registered during runtime; and that would bring it unlikely close to `i2c_bus.h`.
There is only one entity in coreboot that can glue such things properly together: the mainboard code. In the convenient case, this is done via the devicetree.
I don't see how the call to platform_i2c_transfer() is supposed to do something useful in case `bus >= SOFTWARE_I2C_MAX_BUS`. I would expect bus numbers to overlap anyway. Maybe it's the best to never call it in case of CONFIG(SOFTWARE_I2C)?
OTOH, if that is true, we shouldn't select SOFTWARE_I2C from a driver because it disables platform_i2c_tansfer() and who knows when it is needed?
My current hunch would be to redesign software i2c so one can use it to implement i2c_bus. And deprecate i2c_simple anyway for everything that might remotely have a second controller chip on board.
Patrick Rudolph has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/35726 )
Change subject: drivers/aspeed/common: Add support for high resolution framebuffer ......................................................................
Patch Set 14:
Patch Set 14:
based on the inclusion of i2c_simple.h, this would seem to only work on boards which also offer hardware I2C, otherwise platform_i2c_transfer() remains unimplemented and causes a linking error. Can hack around it with preprocessor guards, but not exactly pretty.
Took me a moment to figure out why: The call to platform_i2c_transfer() is not garbage collected because the call to software_i2c_transfer() is runtime conditional (based on the bus number).
i2c_simple is messy and will stay that way unless we define some rules (e.g. let mainboard code assign bus numbers). The problem is that it is designed for a single chip does everything solution (and don't you dare to put another I2C controller on a board). It's just incompatible to this case. For the moment, adding more Kconfig and if's, would do. But to be scalable, it would need function pointers per bus that are registered during runtime; and that would bring it unlikely close to `i2c_bus.h`.
There is only one entity in coreboot that can glue such things properly together: the mainboard code. In the convenient case, this is done via the devicetree.
I don't see how the call to platform_i2c_transfer() is supposed to do something useful in case `bus >= SOFTWARE_I2C_MAX_BUS`. I would expect bus numbers to overlap anyway. Maybe it's the best to never call it in case of CONFIG(SOFTWARE_I2C)?
OTOH, if that is true, we shouldn't select SOFTWARE_I2C from a driver because it disables platform_i2c_tansfer() and who knows when it is needed?
My current hunch would be to redesign software i2c so one can use it to implement i2c_bus. And deprecate i2c_simple anyway for everything that might remotely have a second controller chip on board.
I'll have a look at this next year.
Julius Werner has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/35726 )
Change subject: drivers/aspeed/common: Add support for high resolution framebuffer ......................................................................
Patch Set 14:
I don't see how the call to platform_i2c_transfer() is supposed to do something useful in case `bus >= SOFTWARE_I2C_MAX_BUS`. I would expect bus numbers to overlap anyway. Maybe it's the best to never call it in case of CONFIG(SOFTWARE_I2C)?
I think the problem is just that you never know how many I2C busses a platform may have, and SOFTWARE_I2C_MAX_BUS has to be hardcoded to something. I think I just didn't want to restrict the maximum number of real I2C busses just for this feature when I wrote it. But if it makes things easier now, maybe we can just change SOFTWARE_I2C_MAX_BUS into I2C_MAX_BUS and enforce it everywhere to fix this issue (I believe 10 should be enough for all platforms I've ever seen, but I haven't seen them all).
OTOH, if that is true, we shouldn't select SOFTWARE_I2C from a driver because it disables platform_i2c_tansfer() and who knows when it is needed?
CONFIG(SOFTWARE_I2C) only says that the software I2C code is compiled in, it doesn't mean you can't still use hardware I2C controllers. The way it's designed right now it will still always use hardware by default unless you explicitly enable software I2C (by setting the software_i2c[bus] pointer to something non-NULL).
My current hunch would be to redesign software i2c so one can use it to implement i2c_bus. And deprecate i2c_simple anyway for everything that might remotely have a second controller chip on board.
I'll have a look at this next year.
i2c_simple is still used for all non-x86 devices, and we'll probably want to keep it that way since i2c_bus is specific to devicetree, which is only used on x86. Making software I2C a possible backend for i2c_bus sounds reasonable, but please don't kill i2c_simple.
Nico Huber has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/35726 )
Change subject: drivers/aspeed/common: Add support for high resolution framebuffer ......................................................................
Patch Set 14:
OTOH, if that is true, we shouldn't select SOFTWARE_I2C from a driver because it disables platform_i2c_tansfer() and who knows when it is needed?
CONFIG(SOFTWARE_I2C) only says that the software I2C code is compiled in, it doesn't mean you can't still use hardware I2C controllers. The way it's designed right now it will still always use hardware by default unless you explicitly enable software I2C (by setting the software_i2c[bus] pointer to something non-NULL).
I see, now. Missed that a software I2C bus must be registered to override a hardware one. It's just the way it's used here that confuses me too much.
My current hunch would be to redesign software i2c so one can use it to implement i2c_bus. And deprecate i2c_simple anyway for everything that might remotely have a second controller chip on board.
I'll have a look at this next year.
i2c_simple is still used for all non-x86 devices, and we'll probably want to keep it that way since i2c_bus is specific to devicetree, which is only used on x86. Making software I2C a possible backend for i2c_bus sounds reasonable, but please don't kill i2c_simple.
Yeah, that's why I wrote "for everything that might remotely have a second controller chip on board". I know there are some simple SoC based boards that don't need the devicetree complexity. But for all cases where you want to support multiple chips with one interface, dt is just the way to go, imo.