summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/northbridge/intel/i945/gma.c196
1 files changed, 194 insertions, 2 deletions
diff --git a/src/northbridge/intel/i945/gma.c b/src/northbridge/intel/i945/gma.c
index c92bfbff1e..2bbde4610a 100644
--- a/src/northbridge/intel/i945/gma.c
+++ b/src/northbridge/intel/i945/gma.c
@@ -77,7 +77,7 @@ static int gtt_setup(void *mmiobase)
return 0;
}
-static int intel_gma_init(struct northbridge_intel_i945_config *conf,
+static int intel_gma_init_lvds(struct northbridge_intel_i945_config *conf,
unsigned int pphysbase, unsigned int piobase,
void *pmmio, unsigned int pgfx)
{
@@ -383,6 +383,194 @@ static int intel_gma_init(struct northbridge_intel_i945_config *conf,
#endif
return 0;
}
+
+static int intel_gma_init_vga(struct northbridge_intel_i945_config *conf,
+ unsigned int pphysbase, unsigned int piobase,
+ void *pmmio, unsigned int pgfx)
+{
+ int i;
+ u32 hactive, vactive;
+ u16 reg16;
+ u32 uma_size;
+
+ printk(BIOS_SPEW, "pmmio %x addrport %x physbase %x\n",
+ (u32)pmmio, piobase, pphysbase);
+
+ gtt_setup(pmmio);
+
+ /* Disable VGA. */
+ write32(pmmio + VGACNTRL, VGA_DISP_DISABLE);
+
+ /* Disable pipes. */
+ write32(pmmio + PIPECONF(0), 0);
+ write32(pmmio + PIPECONF(1), 0);
+
+ write32(pmmio + INSTPM, 0x800);
+
+ vga_gr_write(0x18, 0);
+
+ write32(pmmio + VGA0, 0x200074);
+ write32(pmmio + VGA1, 0x200074);
+
+ write32(pmmio + DSPFW3, 0x7f3f00c1 & ~PINEVIEW_SELF_REFRESH_EN);
+ write32(pmmio + DSPCLK_GATE_D, 0);
+ write32(pmmio + FW_BLC, 0x03060106);
+ write32(pmmio + FW_BLC2, 0x00000306);
+
+ write32(pmmio + ADPA, ADPA_DAC_ENABLE
+ | ADPA_PIPE_A_SELECT
+ | ADPA_USE_VGA_HVPOLARITY
+ | ADPA_VSYNC_CNTL_ENABLE
+ | ADPA_HSYNC_CNTL_ENABLE
+ | ADPA_DPMS_ON
+ );
+
+ write32(pmmio + 0x7041c, 0x0);
+
+ write32(pmmio + DPLL_MD(0), 0x3);
+ write32(pmmio + DPLL_MD(1), 0x3);
+ write32(pmmio + DSPCNTR(1), 0x1000000);
+ write32(pmmio + PIPESRC(1), 0x027f01df);
+
+ vga_misc_write(0x67);
+ const u8 cr[] = { 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
+ };
+ vga_cr_write(0x11, 0);
+
+ for (i = 0; i <= 0x18; i++)
+ vga_cr_write(i, cr[i]);
+
+ // Disable screen memory to prevent garbage from appearing.
+ vga_sr_write(1, vga_sr_read(1) | 0x20);
+ hactive = 640;
+ vactive = 400;
+
+ mdelay(1);
+ write32(pmmio + DPLL(0),
+ DPLL_VCO_ENABLE | DPLLB_MODE_DAC_SERIAL
+ | DPLL_VGA_MODE_DIS
+ | DPLL_DAC_SERIAL_P2_CLOCK_DIV_10
+ | 0x400601
+ );
+ mdelay(1);
+ write32(pmmio + DPLL(0),
+ DPLL_VCO_ENABLE | DPLLB_MODE_DAC_SERIAL
+ | DPLL_VGA_MODE_DIS
+ | DPLL_DAC_SERIAL_P2_CLOCK_DIV_10
+ | 0x400601
+ );
+
+ write32(pmmio + ADPA, ADPA_DAC_ENABLE
+ | ADPA_PIPE_A_SELECT
+ | ADPA_USE_VGA_HVPOLARITY
+ | ADPA_VSYNC_CNTL_ENABLE
+ | ADPA_HSYNC_CNTL_ENABLE
+ | ADPA_DPMS_ON
+ );
+
+ write32(pmmio + HTOTAL(0),
+ ((hactive - 1) << 16)
+ | (hactive - 1));
+ write32(pmmio + HBLANK(0),
+ ((hactive - 1) << 16)
+ | (hactive - 1));
+ write32(pmmio + HSYNC(0),
+ ((hactive - 1) << 16)
+ | (hactive - 1));
+
+ write32(pmmio + VTOTAL(0), ((vactive - 1) << 16)
+ | (vactive - 1));
+ write32(pmmio + VBLANK(0), ((vactive - 1) << 16)
+ | (vactive - 1));
+ write32(pmmio + VSYNC(0),
+ ((vactive - 1) << 16)
+ | (vactive - 1));
+
+ write32(pmmio + PF_WIN_POS(0), 0);
+
+ write32(pmmio + PIPESRC(0), (639 << 16) | 399);
+ write32(pmmio + PF_CTL(0),PF_ENABLE | PF_FILTER_MED_3x3);
+ write32(pmmio + PF_WIN_SZ(0), vactive | (hactive << 16));
+ write32(pmmio + PFIT_CONTROL, 0x0);
+
+ mdelay(1);
+
+ write32(pmmio + FDI_RX_CTL(0), 0x00002040);
+ mdelay(1);
+ write32(pmmio + FDI_RX_CTL(0), 0x80002050);
+ write32(pmmio + FDI_TX_CTL(0), 0x00044000);
+ mdelay(1);
+ write32(pmmio + FDI_TX_CTL(0), 0x80044000);
+ write32(pmmio + PIPECONF(0), PIPECONF_ENABLE | PIPECONF_BPP_6 | PIPECONF_DITHER_EN);
+
+ write32(pmmio + VGACNTRL, 0x0);
+ write32(pmmio + DSPCNTR(0), DISPLAY_PLANE_ENABLE | DISPPLANE_BGRX888);
+ mdelay(1);
+
+ write32(pmmio + ADPA, ADPA_DAC_ENABLE
+ | ADPA_PIPE_A_SELECT
+ | ADPA_USE_VGA_HVPOLARITY
+ | ADPA_VSYNC_CNTL_ENABLE
+ | ADPA_HSYNC_CNTL_ENABLE
+ | ADPA_DPMS_ON
+ );
+
+ write32(pmmio + DSPFW3, 0x7f3f00c1);
+ write32(pmmio + MI_MODE, 0x200 | VS_TIMER_DISPATCH);
+ write32(pmmio + CACHE_MODE_0, (0x6820 | (1 << 9)) & ~(1 << 5));
+ write32(pmmio + CACHE_MODE_1, 0x380 & ~(1 << 9));
+
+ /* Set up GTT. */
+
+ reg16 = pci_read_config16(dev_find_slot(0, PCI_DEVFN(0, 0)), GGC);
+ uma_size = 0;
+ if (!(reg16 & 2)) {
+ uma_size = decode_igd_memory_size((reg16 >> 4) & 7);
+ printk(BIOS_DEBUG, "%dM UMA\n", uma_size >> 10);
+ }
+
+ for (i = 0; i < (uma_size - 256) / 4; i++)
+ {
+ outl((i << 2) | 1, piobase);
+ outl(pphysbase + (i << 12) + 1, piobase + 4);
+ }
+
+ /* Clear interrupts. */
+ write32(pmmio + DEIIR, 0xffffffff);
+ write32(pmmio + SDEIIR, 0xffffffff);
+ write32(pmmio + IIR, 0xffffffff);
+ write32(pmmio + IMR, 0xffffffff);
+ write32(pmmio + EIR, 0xffffffff);
+
+ vga_textmode_init();
+
+ /* Enable screen memory. */
+ vga_sr_write(1, vga_sr_read(1) & ~0x20);
+
+ return 0;
+
+}
+
+/* compare the header of the vga edid header */
+/* if vga is not connected it should have a correct header */
+static int vga_connected(u8 *pmmio) {
+ u8 vga_edid[128];
+ u8 header[8] = {0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00};
+ intel_gmbus_read_edid(pmmio + GMBUS0, 2, 0x50, vga_edid, 128);
+ intel_gmbus_stop(pmmio + GMBUS0);
+ for (int i = 0; i < 8; i++) {
+ if (vga_edid[i] != header[i]) {
+ printk(BIOS_DEBUG, "VGA not connected. Using LVDS display\n");
+ return 0;
+ }
+ }
+ printk(BIOS_SPEW, "VGA display connected\n");
+ return 1;
+}
+
#endif
static void gma_func0_init(struct device *dev)
@@ -424,7 +612,11 @@ static void gma_func0_init(struct device *dev)
);
int err;
- err = intel_gma_init(conf, pci_read_config32(dev, 0x5c) & ~0xf,
+ if (vga_connected(mmiobase))
+ err = intel_gma_init_vga(conf, pci_read_config32(dev, 0x5c) & ~0xf,
+ iobase, mmiobase, graphics_base);
+ else
+ err = intel_gma_init_lvds(conf, pci_read_config32(dev, 0x5c) & ~0xf,
iobase, mmiobase, graphics_base);
if (err == 0)
gfx_set_init_done(1);