diff options
-rw-r--r-- | src/i830.h | 10 | ||||
-rw-r--r-- | src/i830_bios.c | 29 | ||||
-rw-r--r-- | src/i830_display.c | 36 |
3 files changed, 66 insertions, 9 deletions
@@ -430,6 +430,16 @@ typedef struct _I830Rec { struct _I830OutputRec output[MAX_OUTPUTS]; I830SDVOPtr sdvo; + /* The BIOS's fixed timings for the LVDS */ + int panel_fixed_hactive; + int panel_fixed_hblank; + int panel_fixed_hsyncoff; + int panel_fixed_hsyncwidth; + int panel_fixed_vactive; + int panel_fixed_vblank; + int panel_fixed_vsyncoff; + int panel_fixed_vsyncwidth; + unsigned char *VBIOS; CARD32 saveDSPACNTR; diff --git a/src/i830_bios.c b/src/i830_bios.c index cae76c81..31e89b59 100644 --- a/src/i830_bios.c +++ b/src/i830_bios.c @@ -28,10 +28,12 @@ #include "config.h" #endif +#define _PARSE_EDID_ #include "xf86.h" #include "xf86_ansic.h" #include "i830.h" #include "i830_bios.h" +#include "edid.h" #define INTEL_BIOS_8(_addr) (pI830->VBIOS[_addr]) #define INTEL_BIOS_16(_addr) (pI830->VBIOS[_addr] | \ @@ -121,7 +123,9 @@ i830GetLVDSInfoFromBIOS(ScrnInfoPtr pScrn) int id; struct lvds_bdb_1 *lvds1; struct lvds_bdb_2 *lvds2; - struct lvds_bdb_2_fp_params *lvds2fpparam; + struct lvds_bdb_2_fp_params *fpparam; + struct lvds_bdb_2_fp_edid_dtd *fptiming; + CARD8 *timing_ptr; id = INTEL_BIOS_8(start); block_size = INTEL_BIOS_16(start + 1) + 3; @@ -134,12 +138,31 @@ i830GetLVDSInfoFromBIOS(ScrnInfoPtr pScrn) case 41: if (panel_type == -1) break; + lvds2 = (struct lvds_bdb_2 *)(pI830->VBIOS + start); - lvds2fpparam = (struct lvds_bdb_2_fp_params *)(pI830->VBIOS + + fpparam = (struct lvds_bdb_2_fp_params *)(pI830->VBIOS + bdb_off + lvds2->panels[panel_type].fp_params_offset); + fptiming = (struct lvds_bdb_2_fp_edid_dtd *)(pI830->VBIOS + + bdb_off + lvds2->panels[panel_type].fp_edid_dtd_offset); + timing_ptr = pI830->VBIOS + bdb_off + + lvds2->panels[panel_type].fp_edid_dtd_offset; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Found panel of size %dx%d in BIOS VBT tables\n", - lvds2fpparam->x_res, lvds2fpparam->y_res); + fpparam->x_res, fpparam->y_res); + + /* Since lvds_bdb_2_fp_edid_dtd is just an EDID detailed timing + * block, pull the contents out using EDID macros. + */ + pI830->panel_fixed_hactive = _H_ACTIVE(timing_ptr); + pI830->panel_fixed_hblank = _H_BLANK(timing_ptr); + pI830->panel_fixed_hsyncoff = _H_SYNC_OFF(timing_ptr); + pI830->panel_fixed_hsyncwidth = _H_SYNC_WIDTH(timing_ptr); + + pI830->panel_fixed_vactive = _V_ACTIVE(timing_ptr); + pI830->panel_fixed_vblank = _V_BLANK(timing_ptr); + pI830->panel_fixed_vsyncoff = _V_SYNC_OFF(timing_ptr); + pI830->panel_fixed_vsyncwidth = _V_SYNC_WIDTH(timing_ptr); break; } } diff --git a/src/i830_display.c b/src/i830_display.c index 57038df1..f9f596f1 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -340,13 +340,37 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) vsync = (pMode->CrtcVSyncStart - 1) | ((pMode->CrtcVSyncEnd - 1) << 16); pipesrc = ((pMode->HDisplay - 1) << 16) | (pMode->VDisplay - 1); dspsize = ((pMode->VDisplay - 1) << 16) | (pMode->HDisplay - 1); - if (outputs & PIPE_LCD_ACTIVE) { + if (outputs & PIPE_LCD_ACTIVE && i830GetLVDSInfoFromBIOS(pScrn) && + pI830->panel_fixed_hactive != 0) + { /* To enable panel fitting, we need to set the pipe timings to that of - * the screen at its full resolution. So, pull the timings out of the - * BIOS tables and drop them in here. + * the screen at its full resolution. So, drop the timings from the + * BIOS VBT tables here. */ - i830GetLVDSInfoFromBIOS(pScrn); + htot = (pI830->panel_fixed_hactive - 1) | + ((pI830->panel_fixed_hactive + pI830->panel_fixed_hblank - 1) + << 16); + hblank = (pI830->panel_fixed_hactive - 1) | + ((pI830->panel_fixed_hactive + pI830->panel_fixed_hblank - 1) + << 16); + hsync = (pI830->panel_fixed_hactive + pI830->panel_fixed_hsyncoff - 1) | + ((pI830->panel_fixed_hactive + pI830->panel_fixed_hsyncoff + + pI830->panel_fixed_hsyncwidth - 1) << 16); + + vtot = (pI830->panel_fixed_vactive - 1) | + ((pI830->panel_fixed_vactive + pI830->panel_fixed_vblank - 1) + << 16); + vblank = (pI830->panel_fixed_vactive - 1) | + ((pI830->panel_fixed_vactive + pI830->panel_fixed_vblank - 1) + << 16); + vsync = (pI830->panel_fixed_vactive + pI830->panel_fixed_vsyncoff - 1) | + ((pI830->panel_fixed_vactive + pI830->panel_fixed_vsyncoff + + pI830->panel_fixed_vsyncwidth - 1) << 16); } +#if 0 + ErrorF("htot: 0x%08x, hblank: 0x%08x, hsync: 0x%08x\n", htot, hblank, hsync); + ErrorF("vtot: 0x%08x, vblank: 0x%08x, vsync: 0x%08x\n", vtot, vblank, vsync); +#endif adpa = INREG(ADPA); adpa &= ~(ADPA_HSYNC_ACTIVE_HIGH | ADPA_VSYNC_ACTIVE_HIGH); @@ -475,9 +499,9 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) * screen. */ /* XXX: Allow (auto-?) enabling of 8-to-6 dithering */ - OUTREG(PFIT_CONTROL, PFIT_ENABLE /*| + OUTREG(PFIT_CONTROL, PFIT_ENABLE | VERT_AUTO_SCALE | HORIZ_AUTO_SCALE | - VERT_INTERP_BILINEAR | HORIZ_INTERP_BILINEAR*/); + VERT_INTERP_BILINEAR | HORIZ_INTERP_BILINEAR); } /* Then, turn the pipe on first */ |