diff options
Diffstat (limited to 'src/northbridge/intel')
-rw-r--r-- | src/northbridge/intel/sandybridge/gma.c | 1 | ||||
-rw-r--r-- | src/northbridge/intel/sandybridge/gma_ivybridge_lvds.c | 82 |
2 files changed, 83 insertions, 0 deletions
diff --git a/src/northbridge/intel/sandybridge/gma.c b/src/northbridge/intel/sandybridge/gma.c index d271a1afcb..a01fe9f771 100644 --- a/src/northbridge/intel/sandybridge/gma.c +++ b/src/northbridge/intel/sandybridge/gma.c @@ -21,6 +21,7 @@ #include <console/console.h> #include <bootmode.h> #include <delay.h> +#include <string.h> #include <device/device.h> #include <device/pci.h> #include <device/pci_ids.h> diff --git a/src/northbridge/intel/sandybridge/gma_ivybridge_lvds.c b/src/northbridge/intel/sandybridge/gma_ivybridge_lvds.c index 1f53a74b5f..ff877ffcb6 100644 --- a/src/northbridge/intel/sandybridge/gma_ivybridge_lvds.c +++ b/src/northbridge/intel/sandybridge/gma_ivybridge_lvds.c @@ -26,13 +26,64 @@ #include <drivers/intel/gma/edid.h> #include <drivers/intel/gma/i915.h> +#include <drivers/intel/gma/intel_bios.h> #include "gma.h" #include "chip.h" #include <pc80/vga.h> #include <pc80/vga_io.h> +#include <device/pci_def.h> +#include <device/pci_rom.h> #if IS_ENABLED(CONFIG_MAINBOARD_DO_NATIVE_VGA_INIT) +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 +560,37 @@ 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. */ + optionrom_header_t *oh = (void *)PCI_VGA_RAM_IMAGE_START; + 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, 0, 8192); + + oh->signature = OPROM_SIGNATURE; + oh->pcir_offset = 0x40; + oh->vbt_offset = 0x80; + + pcir = (void *)(PCI_VGA_RAM_IMAGE_START + 0x40); + 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 *)(PCI_VGA_RAM_IMAGE_START + 0x80)); + fake_oprom_size = (0x80 + vbt_size + 511) / 512; + oh->size = fake_oprom_size; + pcir->imagelength = fake_oprom_size; return 1; } |