Vladimir Serbinenko (phcoder@gmail.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/5396
-gerrit
commit 1438c3f4e863ddd7f31e6005dc3f126db750ac05 Author: Vladimir Serbinenko phcoder@gmail.com Date: Sun Feb 23 00:13:56 2014 +0100
x230: Deploy VBT
Change-Id: Ide31a56bfdbc31cd3b87993dfb4ed8ef0107cdba Signed-off-by: Vladimir Serbinenko phcoder@gmail.com --- .../intel/sandybridge/gma_ivybridge_lvds.c | 142 +++++++++++++++++++++ 1 file changed, 142 insertions(+)
diff --git a/src/northbridge/intel/sandybridge/gma_ivybridge_lvds.c b/src/northbridge/intel/sandybridge/gma_ivybridge_lvds.c index 1f53a74..709a0ba 100644 --- a/src/northbridge/intel/sandybridge/gma_ivybridge_lvds.c +++ b/src/northbridge/intel/sandybridge/gma_ivybridge_lvds.c @@ -30,9 +30,118 @@ #include "chip.h" #include <pc80/vga.h> #include <pc80/vga_io.h> +#include <device/pci_def.h>
#if IS_ENABLED(CONFIG_MAINBOARD_DO_NATIVE_VGA_INIT)
+/* VBT definitions copied from Linux. */ +struct vbt_header { + u8 signature[20]; + u16 version; + u16 header_size; + u16 vbt_size; + u8 vbt_checksum; + u8 reserved0; + u32 bdb_offset; + u32 aim_offset[4]; +} __attribute__((packed)); + +struct bdb_header { + u8 signature[16]; + u16 version; + u16 header_size; + u16 bdb_size; +} __attribute__((packed)); + +#define BDB_GENERAL_FEATURES 1 + +struct bdb_general_features { + /* bits 1 */ + u8 panel_fitting:2; + u8 flexaim:1; + u8 msg_enable:1; + u8 clear_screen:3; + u8 color_flip:1; + + /* bits 2 */ + u8 download_ext_vbt:1; + u8 enable_ssc:1; + u8 ssc_freq:1; + u8 enable_lfp_on_override:1; + u8 disable_ssc_ddt:1; + u8 rsvd7:1; + u8 display_clock_mode:1; + u8 rsvd8:1; /* finish byte */ + + /* bits 3 */ + u8 disable_smooth_vision:1; + u8 single_dvi:1; + u8 rsvd9:1; + u8 fdi_rx_polarity_inverted:1; + u8 rsvd10:4; /* finish byte */ + + /* bits 4 */ + u8 legacy_monitor_detect; + + /* bits 5 */ + u8 int_crt_support:1; + u8 int_tv_support:1; + u8 int_efp_support:1; + u8 dp_ssc_enb:1; /* PCH attached eDP supports SSC */ + u8 dp_ssc_freq:1; /* SSC freq for PCH attached eDP */ + u8 rsvd11:3; /* finish byte */ +} __attribute__((packed)); + + +static size_t generate_vbt(const struct northbridge_intel_sandybridge_config *conf, + void *vbt) +{ + struct vbt_header *head = vbt; + struct bdb_header *bdb_head; + struct bdb_general_features *genfeat; + u8 *ptr; + + memset (head, 0, sizeof (*head)); + + memcpy (head->signature, "$VBT SNB/IVB-MOBILE ", 20); + head->version = 100; + head->header_size = sizeof (*head); + head->bdb_offset = sizeof (*head); + + bdb_head = (struct bdb_header *) (head + 1); + memset (bdb_head, 0, sizeof (*bdb_head)); + memcpy (bdb_head->signature, "BIOS_DATA_BLOCK ", 16); + bdb_head->version = 0xa8; + bdb_head->header_size = sizeof (*bdb_head); + + ptr = (u8 *) (bdb_head + 1); + + ptr[0] = BDB_GENERAL_FEATURES; + ptr[1] = sizeof (*genfeat); + ptr[2] = sizeof (*genfeat) >> 8; + ptr += 3; + + genfeat = (struct bdb_general_features *) ptr; + memset (genfeat, 0, sizeof (*genfeat)); + genfeat->panel_fitting = 3; + genfeat->flexaim = 1; + genfeat->download_ext_vbt = 1; + genfeat->enable_ssc = conf->gpu_use_spread_spectrum_clock; + genfeat->ssc_freq = !conf->gpu_link_frequency_270_mhz; + genfeat->rsvd10 = 0x4; + genfeat->legacy_monitor_detect = 1; + genfeat->int_crt_support = 1; + genfeat->dp_ssc_enb = 1; + + ptr += sizeof (*genfeat); + + bdb_head->bdb_size = ptr - (u8 *)bdb_head; + head->vbt_size = ptr - (u8 *)head; + head->vbt_checksum = 0; + return ptr - (u8 *)head; +} + + static void link_train(u32 mmio) { write32(mmio+0xf000c,0x40); @@ -509,6 +618,39 @@ int i915lightup(const struct northbridge_intel_sandybridge_config *info, memset ((void *) lfb, 0, edid.x_resolution * edid.y_resolution * 4); set_vbe_mode_info_valid(&edid, lfb); #endif + + /* Linux relies on VBT for panel info. */ + if (read16(0xc0000) != 0xaa55) { + optionrom_header_t *oh = (void *)0xc0000; + optionrom_pcir_t *pcir; + size_t vbt_size; + size_t fake_oprom_size; + struct device *dev; + + dev = dev_find_slot(0, PCI_DEVFN(2, 0)); + + memset(oh->reserved, 0, 8192); + + oh->signature = 0xaa55; + oh->pcir_offset = 0x40; + oh->vbt_offset = 0x80; + + pcir = (void *)0xc0040; + pcir->signature = 0x52494350; // PCIR + pcir->vendor = dev->vendor; + pcir->device = dev->device; + pcir->length = sizeof(*pcir); + pcir->revision = dev->class; + pcir->classcode[0] = dev->class >> 8; + pcir->classcode[1] = dev->class >> 16; + pcir->classcode[2] = dev->class >> 24; + pcir->indicator = 0x80; + + vbt_size = generate_vbt (info, (void *)0xc0080); + fake_oprom_size = (0x80 + vbt_size + 511) / 512; + oh->size = fake_oprom_size; + pcir->imagelength = fake_oprom_size; + } return 1; }