Merge branch 'generic-mode-set' into modesetting
This commit is contained in:
commit
b75ecdb483
|
|
@ -762,6 +762,18 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||
|
||||
#define PP_STATUS 0x61200
|
||||
# define PP_ON (1 << 31)
|
||||
/**
|
||||
* Indicates that all dependencies of the panel are on:
|
||||
*
|
||||
* - PLL enabled
|
||||
* - pipe enabled
|
||||
* - LVDS/DVOB/DVOC on
|
||||
*/
|
||||
# define PP_READY (1 << 30)
|
||||
# define PP_SEQUENCE_NONE (0 << 28)
|
||||
# define PP_SEQUENCE_ON (1 << 28)
|
||||
# define PP_SEQUENCE_OFF (2 << 28)
|
||||
# define PP_SEQUENCE_MASK 0x30000000
|
||||
|
||||
#define PP_CONTROL 0x61204
|
||||
# define POWER_TARGET_ON (1 << 0)
|
||||
|
|
@ -796,12 +808,14 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||
# define DPLL_VGA_MODE_DIS (1 << 28)
|
||||
# define DPLLB_MODE_DAC_SERIAL (1 << 26) /* i915 */
|
||||
# define DPLLB_MODE_LVDS (2 << 26) /* i915 */
|
||||
# define DPLL_MODE_MASK (3 << 26)
|
||||
# define DPLL_DAC_SERIAL_P2_CLOCK_DIV_10 (0 << 24) /* i915 */
|
||||
# define DPLL_DAC_SERIAL_P2_CLOCK_DIV_5 (1 << 24) /* i915 */
|
||||
# define DPLLB_LVDS_P2_CLOCK_DIV_14 (0 << 24) /* i915 */
|
||||
# define DPLLB_LVDS_P2_CLOCK_DIV_7 (1 << 24) /* i915 */
|
||||
# define DPLL_P2_CLOCK_DIV_MASK 0x03000000 /* i915 */
|
||||
# define DPLL_FPA01_P1_POST_DIV_MASK 0x00ff0000 /* i915 */
|
||||
# define DPLL_FPA01_P1_POST_DIV_SHIFT 16
|
||||
# define PLL_P2_DIVIDE_BY_4 (1 << 23) /* i830, required in DVO non-gang */
|
||||
# define DPLL_FPA01_P1_POS_DIV_MASK_I830 0x001f0000 /* i830 */
|
||||
# define PLL_P1_DIVIDE_BY_TWO (1 << 21) /* i830 */
|
||||
|
|
@ -809,6 +823,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||
# define PLL_REF_INPUT_TVCLKINA (1 << 13) /* i830 */
|
||||
# define PLL_REF_INPUT_TVCLKINBC (2 << 13) /* SDVO TVCLKIN */
|
||||
# define PLLB_REF_INPUT_SPREADSPECTRUMIN (3 << 13)
|
||||
# define PLL_REF_INPUT_MASK (3 << 13)
|
||||
# define PLL_LOAD_PULSE_PHASE_SHIFT 9
|
||||
/*
|
||||
* Parallel to Serial Load Pulse phase selection.
|
||||
|
|
@ -818,6 +833,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||
*/
|
||||
# define PLL_LOAD_PULSE_PHASE_MASK (0xf << PLL_LOAD_PULSE_PHASE_SHIFT)
|
||||
# define DISPLAY_RATE_SELECT_FPA1 (1 << 8)
|
||||
|
||||
/**
|
||||
* SDVO multiplier for 945G/GM. Not used on 965.
|
||||
*
|
||||
|
|
@ -906,8 +922,11 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||
#define FPB0 0x06048
|
||||
#define FPB1 0x0604c
|
||||
# define FP_N_DIV_MASK 0x003f0000
|
||||
# define FP_N_DIV_SHIFT 16
|
||||
# define FP_M1_DIV_MASK 0x00003f00
|
||||
# define FP_M1_DIV_SHIFT 8
|
||||
# define FP_M2_DIV_MASK 0x0000003f
|
||||
# define FP_M2_DIV_SHIFT 0
|
||||
|
||||
#define PORT_HOTPLUG_EN 0x61110
|
||||
# define SDVOB_HOTPLUG_INT_EN (1 << 26)
|
||||
|
|
|
|||
13
src/i830.h
13
src/i830.h
|
|
@ -438,19 +438,8 @@ typedef struct _I830Rec {
|
|||
|
||||
int ddc2;
|
||||
|
||||
/* Panel size pulled from the BIOS */
|
||||
int PanelXRes, PanelYRes;
|
||||
|
||||
/* The BIOS's fixed timings for the LVDS */
|
||||
int panel_fixed_clock;
|
||||
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;
|
||||
DisplayModePtr panel_fixed_mode;
|
||||
|
||||
int backlight_duty_cycle; /* restore backlight to this value */
|
||||
|
||||
|
|
|
|||
|
|
@ -158,6 +158,7 @@ i830GetLVDSInfoFromBIOS(ScrnInfoPtr pScrn)
|
|||
struct lvds_bdb_2 *lvds2;
|
||||
struct lvds_bdb_2_fp_params *fpparam;
|
||||
struct lvds_bdb_2_fp_edid_dtd *fptiming;
|
||||
DisplayModePtr fixed_mode;
|
||||
CARD8 *timing_ptr;
|
||||
|
||||
id = INTEL_BIOS_8(start);
|
||||
|
|
@ -197,32 +198,37 @@ i830GetLVDSInfoFromBIOS(ScrnInfoPtr pScrn)
|
|||
continue;
|
||||
}
|
||||
|
||||
pI830->PanelXRes = fpparam->x_res;
|
||||
pI830->PanelYRes = fpparam->y_res;
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
||||
"Found panel of size %dx%d in BIOS VBT tables\n",
|
||||
pI830->PanelXRes, pI830->PanelYRes);
|
||||
fixed_mode = xnfalloc(sizeof(DisplayModeRec));
|
||||
memset(fixed_mode, 0, sizeof(*fixed_mode));
|
||||
|
||||
/* Since lvds_bdb_2_fp_edid_dtd is just an EDID detailed timing
|
||||
* block, pull the contents out using EDID macros.
|
||||
*/
|
||||
pI830->panel_fixed_clock = _PIXEL_CLOCK(timing_ptr) / 1000;
|
||||
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);
|
||||
fixed_mode->HDisplay = _H_ACTIVE(timing_ptr);
|
||||
fixed_mode->VDisplay = _V_ACTIVE(timing_ptr);
|
||||
fixed_mode->HSyncStart = fixed_mode->HDisplay +
|
||||
_H_SYNC_OFF(timing_ptr);
|
||||
fixed_mode->HSyncEnd = fixed_mode->HSyncStart +
|
||||
_H_SYNC_WIDTH(timing_ptr);
|
||||
fixed_mode->HTotal = fixed_mode->HDisplay +
|
||||
_H_BLANK(timing_ptr);
|
||||
fixed_mode->VSyncStart = fixed_mode->VDisplay +
|
||||
_V_SYNC_OFF(timing_ptr);
|
||||
fixed_mode->VSyncEnd = fixed_mode->VSyncStart +
|
||||
_V_SYNC_WIDTH(timing_ptr);
|
||||
fixed_mode->VTotal = fixed_mode->VDisplay +
|
||||
_V_BLANK(timing_ptr);
|
||||
fixed_mode->Clock = _PIXEL_CLOCK(timing_ptr) / 1000;
|
||||
fixed_mode->type = M_T_PREFERRED;
|
||||
|
||||
xf86SetModeDefaultName(fixed_mode);
|
||||
|
||||
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);
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
||||
"Panel mode h active %d blank %d rate %f v active %d blank %d rate %f\n",
|
||||
pI830->panel_fixed_hactive, pI830->panel_fixed_hblank,
|
||||
(double) pI830->panel_fixed_clock / (pI830->panel_fixed_hactive + pI830->panel_fixed_hblank),
|
||||
pI830->panel_fixed_vactive, pI830->panel_fixed_vblank,
|
||||
(double) pI830->panel_fixed_clock /
|
||||
((pI830->panel_fixed_hactive + pI830->panel_fixed_hblank) * (pI830->panel_fixed_vactive + pI830->panel_fixed_vblank)));
|
||||
"Found panel mode in BIOS VBT tables:\n");
|
||||
xf86PrintModeline(pScrn->scrnIndex, fixed_mode);
|
||||
|
||||
pI830->panel_fixed_mode = fixed_mode;
|
||||
|
||||
found_panel_info = TRUE;
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -93,13 +93,16 @@ i830_crt_mode_valid(xf86OutputPtr output, DisplayModePtr pMode)
|
|||
return MODE_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
i830_crt_pre_set_mode (xf86OutputPtr output, DisplayModePtr pMode)
|
||||
static Bool
|
||||
i830_crt_mode_fixup(xf86OutputPtr output, DisplayModePtr mode,
|
||||
DisplayModePtr adjusted_mode)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
i830_crt_post_set_mode (xf86OutputPtr output, DisplayModePtr pMode)
|
||||
i830_crt_mode_set(xf86OutputPtr output, DisplayModePtr mode,
|
||||
DisplayModePtr adjusted_mode)
|
||||
{
|
||||
ScrnInfoPtr pScrn = output->scrn;
|
||||
I830Ptr pI830 = I830PTR(pScrn);
|
||||
|
|
@ -122,11 +125,10 @@ i830_crt_post_set_mode (xf86OutputPtr output, DisplayModePtr pMode)
|
|||
OUTREG(dpll_md_reg, dpll_md & ~DPLL_MD_UDI_MULTIPLIER_MASK);
|
||||
}
|
||||
|
||||
adpa = ADPA_DAC_ENABLE;
|
||||
|
||||
if (pMode->Flags & V_PHSYNC)
|
||||
adpa = 0;
|
||||
if (adjusted_mode->Flags & V_PHSYNC)
|
||||
adpa |= ADPA_HSYNC_ACTIVE_HIGH;
|
||||
if (pMode->Flags & V_PVSYNC)
|
||||
if (adjusted_mode->Flags & V_PVSYNC)
|
||||
adpa |= ADPA_VSYNC_ACTIVE_HIGH;
|
||||
|
||||
if (i830_crtc->pipe == 0)
|
||||
|
|
@ -370,8 +372,8 @@ static const xf86OutputFuncsRec i830_crt_output_funcs = {
|
|||
.save = i830_crt_save,
|
||||
.restore = i830_crt_restore,
|
||||
.mode_valid = i830_crt_mode_valid,
|
||||
.pre_set_mode = i830_crt_pre_set_mode,
|
||||
.post_set_mode = i830_crt_post_set_mode,
|
||||
.mode_fixup = i830_crt_mode_fixup,
|
||||
.mode_set = i830_crt_mode_set,
|
||||
.detect = i830_crt_detect,
|
||||
.get_modes = i830_crt_get_modes,
|
||||
.destroy = i830_crt_destroy
|
||||
|
|
|
|||
264
src/i830_debug.c
264
src/i830_debug.c
|
|
@ -33,13 +33,163 @@
|
|||
#include "i830.h"
|
||||
#include "i830_debug.h"
|
||||
|
||||
#define DEBUGSTRING(func) static char *func(I830Ptr pI830, int reg, CARD32 val)
|
||||
|
||||
DEBUGSTRING(i830_debug_xyminus1)
|
||||
{
|
||||
return XNFprintf("%d, %d", (val & 0xffff) + 1,
|
||||
((val & 0xffff0000) >> 16) + 1);
|
||||
}
|
||||
|
||||
DEBUGSTRING(i830_debug_yxminus1)
|
||||
{
|
||||
return XNFprintf("%d, %d", ((val & 0xffff0000) >> 16) + 1,
|
||||
(val & 0xffff) + 1);
|
||||
}
|
||||
|
||||
DEBUGSTRING(i830_debug_xy)
|
||||
{
|
||||
return XNFprintf("%d, %d", (val & 0xffff),
|
||||
((val & 0xffff0000) >> 16));
|
||||
}
|
||||
|
||||
DEBUGSTRING(i830_debug_dspstride)
|
||||
{
|
||||
return XNFprintf("%d bytes", val);
|
||||
}
|
||||
|
||||
DEBUGSTRING(i830_debug_dspcntr)
|
||||
{
|
||||
char *enabled = val & DISPLAY_PLANE_ENABLE ? "enabled" : "disabled";
|
||||
char plane = val & DISPPLANE_SEL_PIPE_B ? 'B' : 'A';
|
||||
return XNFprintf("%s, pipe %c", enabled, plane);
|
||||
}
|
||||
|
||||
DEBUGSTRING(i830_debug_pipeconf)
|
||||
{
|
||||
char *enabled = val & PIPEACONF_ENABLE ? "enabled" : "disabled";
|
||||
char *wide = val & PIPEACONF_DOUBLE_WIDE ? "double-wide" : "single-wide";
|
||||
return XNFprintf("%s, %s", enabled, wide);
|
||||
}
|
||||
|
||||
DEBUGSTRING(i830_debug_hvtotal)
|
||||
{
|
||||
return XNFprintf("%d active, %d total", (val & 0xffff) + 1,
|
||||
((val & 0xffff0000) >> 16) + 1);
|
||||
}
|
||||
|
||||
DEBUGSTRING(i830_debug_hvsyncblank)
|
||||
{
|
||||
return XNFprintf("%d start, %d end", (val & 0xffff) + 1,
|
||||
((val & 0xffff0000) >> 16) + 1);
|
||||
}
|
||||
|
||||
DEBUGSTRING(i830_debug_vgacntrl)
|
||||
{
|
||||
return XNFprintf("%s", val & VGA_DISP_DISABLE ? "disabled" : "enabled");
|
||||
}
|
||||
|
||||
DEBUGSTRING(i830_debug_fp)
|
||||
{
|
||||
return XNFprintf("n = %d, m1 = %d, m2 = %d",
|
||||
((val & FP_N_DIV_MASK) >> FP_N_DIV_SHIFT),
|
||||
((val & FP_M1_DIV_MASK) >> FP_M1_DIV_SHIFT),
|
||||
((val & FP_M2_DIV_MASK) >> FP_M2_DIV_SHIFT));
|
||||
}
|
||||
|
||||
DEBUGSTRING(i830_debug_pp_status)
|
||||
{
|
||||
char *status = val & PP_ON ? "on" : "off";
|
||||
char *ready = val & PP_READY ? "ready" : "not ready";
|
||||
char *seq = "unknown";
|
||||
|
||||
switch (val & PP_SEQUENCE_MASK) {
|
||||
case PP_SEQUENCE_NONE:
|
||||
seq = "idle";
|
||||
break;
|
||||
case PP_SEQUENCE_ON:
|
||||
seq = "on";
|
||||
break;
|
||||
case PP_SEQUENCE_OFF:
|
||||
seq = "off";
|
||||
break;
|
||||
}
|
||||
|
||||
return XNFprintf("%s, %s, sequencing %s", status, ready, seq);
|
||||
}
|
||||
|
||||
DEBUGSTRING(i830_debug_pp_control)
|
||||
{
|
||||
return XNFprintf("power target: %s",
|
||||
val & POWER_TARGET_ON ? "on" : "off");
|
||||
}
|
||||
|
||||
DEBUGSTRING(i830_debug_dpll)
|
||||
{
|
||||
char *enabled = val & DPLL_VCO_ENABLE ? "enabled" : "disabled";
|
||||
char *dvomode = val & DPLL_DVO_HIGH_SPEED ? "dvo" : "non-dvo";
|
||||
char *vgamode = val & DPLL_VGA_MODE_DIS ? "" : ", VGA";
|
||||
char *mode = "unknown";
|
||||
char *clock = "unknown";
|
||||
char *fpextra = val & DISPLAY_RATE_SELECT_FPA1 ? ", using FPx1!" : "";
|
||||
char sdvoextra[3];
|
||||
int p1, p2 = 0;
|
||||
|
||||
p1 = ffs((val & DPLL_FPA01_P1_POST_DIV_MASK) >>
|
||||
DPLL_FPA01_P1_POST_DIV_SHIFT);
|
||||
switch (val & DPLL_MODE_MASK) {
|
||||
case DPLLB_MODE_DAC_SERIAL:
|
||||
mode = "dac/serial";
|
||||
p2 = val & DPLL_DAC_SERIAL_P2_CLOCK_DIV_5 ? 5 : 10;
|
||||
break;
|
||||
case DPLLB_MODE_LVDS:
|
||||
mode = "LVDS";
|
||||
p2 = val & DPLLB_LVDS_P2_CLOCK_DIV_7 ? 7 : 14;
|
||||
break;
|
||||
}
|
||||
switch (val & PLL_REF_INPUT_MASK) {
|
||||
case PLL_REF_INPUT_DREFCLK:
|
||||
clock = "default";
|
||||
break;
|
||||
case PLL_REF_INPUT_TVCLKINA:
|
||||
clock = "TV A";
|
||||
break;
|
||||
case PLL_REF_INPUT_TVCLKINBC:
|
||||
clock = "TV B/C";
|
||||
break;
|
||||
}
|
||||
if (IS_I945G(pI830) || IS_I945GM(pI830)) {
|
||||
sprintf(sdvoextra, "SDVO mult %d",
|
||||
(int)(val & SDVO_MULTIPLIER_MASK) >>
|
||||
SDVO_MULTIPLIER_SHIFT_HIRES);
|
||||
} else {
|
||||
sdvoextra[0] = '\0';
|
||||
}
|
||||
|
||||
return XNFprintf("%s, %s%s, %s mode, %s clock, p1 = %d, "
|
||||
"p2 = %d%s%s",
|
||||
enabled, dvomode, vgamode, mode, clock, p1, p2,
|
||||
fpextra, sdvoextra);
|
||||
}
|
||||
|
||||
DEBUGSTRING(i830_debug_lvds)
|
||||
{
|
||||
char pipe = val & LVDS_PIPEB_SELECT ? 'B' : 'A';
|
||||
char *enable = val & LVDS_PORT_EN ? "enabled" : "disabled";
|
||||
|
||||
return XNFprintf("%s, pipe %c", enable, pipe);
|
||||
}
|
||||
|
||||
#define DEFINEREG(reg) \
|
||||
{ reg, #reg, 0 }
|
||||
{ reg, #reg, NULL, 0 }
|
||||
#define DEFINEREG2(reg, func) \
|
||||
{ reg, #reg, func, 0 }
|
||||
|
||||
static struct i830SnapshotRec {
|
||||
int reg;
|
||||
char *name;
|
||||
CARD32 regval;
|
||||
char *(*debug_output)(I830Ptr pI830, int reg, CARD32 val);
|
||||
CARD32 val;
|
||||
} i830_snapshot[] = {
|
||||
DEFINEREG(VCLK_DIVISOR_VGA0),
|
||||
DEFINEREG(VCLK_DIVISOR_VGA1),
|
||||
|
|
@ -61,7 +211,7 @@ static struct i830SnapshotRec {
|
|||
DEFINEREG(DSPFW3),
|
||||
|
||||
DEFINEREG(ADPA),
|
||||
DEFINEREG(LVDS),
|
||||
DEFINEREG2(LVDS, i830_debug_lvds),
|
||||
DEFINEREG(DVOA),
|
||||
DEFINEREG(DVOB),
|
||||
DEFINEREG(DVOC),
|
||||
|
|
@ -69,63 +219,63 @@ static struct i830SnapshotRec {
|
|||
DEFINEREG(DVOB_SRCDIM),
|
||||
DEFINEREG(DVOC_SRCDIM),
|
||||
|
||||
DEFINEREG(PP_CONTROL),
|
||||
DEFINEREG(PP_STATUS),
|
||||
DEFINEREG2(PP_CONTROL, i830_debug_pp_control),
|
||||
DEFINEREG2(PP_STATUS, i830_debug_pp_status),
|
||||
DEFINEREG(PFIT_CONTROL),
|
||||
DEFINEREG(PFIT_PGM_RATIOS),
|
||||
DEFINEREG(PORT_HOTPLUG_EN),
|
||||
DEFINEREG(PORT_HOTPLUG_STAT),
|
||||
|
||||
DEFINEREG(DSPACNTR),
|
||||
DEFINEREG(DSPASTRIDE),
|
||||
DEFINEREG(DSPAPOS),
|
||||
DEFINEREG(DSPASIZE),
|
||||
DEFINEREG2(DSPACNTR, i830_debug_dspcntr),
|
||||
DEFINEREG2(DSPASTRIDE, i830_debug_dspstride),
|
||||
DEFINEREG2(DSPAPOS, i830_debug_xy),
|
||||
DEFINEREG2(DSPASIZE, i830_debug_xyminus1),
|
||||
DEFINEREG(DSPABASE),
|
||||
DEFINEREG(DSPASURF),
|
||||
DEFINEREG(DSPATILEOFF),
|
||||
DEFINEREG(PIPEACONF),
|
||||
DEFINEREG(PIPEASRC),
|
||||
DEFINEREG2(PIPEACONF, i830_debug_pipeconf),
|
||||
DEFINEREG2(PIPEASRC, i830_debug_yxminus1),
|
||||
|
||||
DEFINEREG(FPA0),
|
||||
DEFINEREG(FPA1),
|
||||
DEFINEREG(DPLL_A),
|
||||
DEFINEREG2(FPA0, i830_debug_fp),
|
||||
DEFINEREG2(FPA1, i830_debug_fp),
|
||||
DEFINEREG2(DPLL_A, i830_debug_dpll),
|
||||
DEFINEREG(DPLL_A_MD),
|
||||
DEFINEREG(HTOTAL_A),
|
||||
DEFINEREG(HBLANK_A),
|
||||
DEFINEREG(HSYNC_A),
|
||||
DEFINEREG(VTOTAL_A),
|
||||
DEFINEREG(VBLANK_A),
|
||||
DEFINEREG(VSYNC_A),
|
||||
DEFINEREG2(HTOTAL_A, i830_debug_hvtotal),
|
||||
DEFINEREG2(HBLANK_A, i830_debug_hvsyncblank),
|
||||
DEFINEREG2(HSYNC_A, i830_debug_hvsyncblank),
|
||||
DEFINEREG2(VTOTAL_A, i830_debug_hvtotal),
|
||||
DEFINEREG2(VBLANK_A, i830_debug_hvsyncblank),
|
||||
DEFINEREG2(VSYNC_A, i830_debug_hvsyncblank),
|
||||
DEFINEREG(BCLRPAT_A),
|
||||
DEFINEREG(VSYNCSHIFT_A),
|
||||
|
||||
DEFINEREG(DSPBCNTR),
|
||||
DEFINEREG(DSPBSTRIDE),
|
||||
DEFINEREG(DSPBPOS),
|
||||
DEFINEREG(DSPBSIZE),
|
||||
DEFINEREG2(DSPBCNTR, i830_debug_dspcntr),
|
||||
DEFINEREG2(DSPBSTRIDE, i830_debug_dspstride),
|
||||
DEFINEREG2(DSPBPOS, i830_debug_xy),
|
||||
DEFINEREG2(DSPBSIZE, i830_debug_xyminus1),
|
||||
DEFINEREG(DSPBBASE),
|
||||
DEFINEREG(DSPBSURF),
|
||||
DEFINEREG(DSPBTILEOFF),
|
||||
DEFINEREG(PIPEBCONF),
|
||||
DEFINEREG(PIPEBSRC),
|
||||
DEFINEREG2(PIPEBCONF, i830_debug_pipeconf),
|
||||
DEFINEREG2(PIPEBSRC, i830_debug_yxminus1),
|
||||
|
||||
DEFINEREG(FPB0),
|
||||
DEFINEREG(FPB1),
|
||||
DEFINEREG(DPLL_B),
|
||||
DEFINEREG2(FPB0, i830_debug_fp),
|
||||
DEFINEREG2(FPB1, i830_debug_fp),
|
||||
DEFINEREG2(DPLL_B, i830_debug_dpll),
|
||||
DEFINEREG(DPLL_B_MD),
|
||||
DEFINEREG(HTOTAL_B),
|
||||
DEFINEREG(HBLANK_B),
|
||||
DEFINEREG(HSYNC_B),
|
||||
DEFINEREG(VTOTAL_B),
|
||||
DEFINEREG(VBLANK_B),
|
||||
DEFINEREG(VSYNC_B),
|
||||
DEFINEREG2(HTOTAL_B, i830_debug_hvtotal),
|
||||
DEFINEREG2(HBLANK_B, i830_debug_hvsyncblank),
|
||||
DEFINEREG2(HSYNC_B, i830_debug_hvsyncblank),
|
||||
DEFINEREG2(VTOTAL_B, i830_debug_hvtotal),
|
||||
DEFINEREG2(VBLANK_B, i830_debug_hvsyncblank),
|
||||
DEFINEREG2(VSYNC_B, i830_debug_hvsyncblank),
|
||||
DEFINEREG(BCLRPAT_B),
|
||||
DEFINEREG(VSYNCSHIFT_B),
|
||||
|
||||
DEFINEREG(VCLK_DIVISOR_VGA0),
|
||||
DEFINEREG(VCLK_DIVISOR_VGA1),
|
||||
DEFINEREG(VCLK_POST_DIV),
|
||||
DEFINEREG(VGACNTRL),
|
||||
DEFINEREG2(VGACNTRL, i830_debug_vgacntrl),
|
||||
|
||||
DEFINEREG(TV_CTL),
|
||||
DEFINEREG(TV_DAC),
|
||||
|
|
@ -171,7 +321,7 @@ void i830TakeRegSnapshot(ScrnInfoPtr pScrn)
|
|||
int i;
|
||||
|
||||
for (i = 0; i < NUM_I830_SNAPSHOTREGS; i++) {
|
||||
i830_snapshot[i].regval = INREG(i830_snapshot[i].reg);
|
||||
i830_snapshot[i].val = INREG(i830_snapshot[i].reg);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -184,11 +334,28 @@ void i830CompareRegsToSnapshot(ScrnInfoPtr pScrn, char *where)
|
|||
"Comparing regs from server start up to %s\n", where);
|
||||
for (i = 0; i < NUM_I830_SNAPSHOTREGS; i++) {
|
||||
CARD32 val = INREG(i830_snapshot[i].reg);
|
||||
if (i830_snapshot[i].regval != val) {
|
||||
if (i830_snapshot[i].val == val)
|
||||
continue;
|
||||
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
|
||||
"Register 0x%x (%s) changed from 0x%08x to 0x%08x\n",
|
||||
i830_snapshot[i].reg, i830_snapshot[i].name,
|
||||
(int)i830_snapshot[i].val, (int)val);
|
||||
|
||||
if (i830_snapshot[i].debug_output != NULL) {
|
||||
char *before, *after;
|
||||
|
||||
before = i830_snapshot[i].debug_output(pI830,
|
||||
i830_snapshot[i].reg,
|
||||
i830_snapshot[i].val);
|
||||
after = i830_snapshot[i].debug_output(pI830,
|
||||
i830_snapshot[i].reg,
|
||||
val);
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
|
||||
"Register 0x%x (%s) changed from 0x%08x to 0x%08x\n",
|
||||
i830_snapshot[i].reg, i830_snapshot[i].name,
|
||||
(int)i830_snapshot[i].regval, (int)val);
|
||||
"%s before: %s\n", i830_snapshot[i].name, before);
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
|
||||
"%s after: %s\n", i830_snapshot[i].name, after);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -220,8 +387,19 @@ void i830DumpRegs (ScrnInfoPtr pScrn)
|
|||
|
||||
xf86DrvMsg (pScrn->scrnIndex, X_INFO, "DumpRegsBegin\n");
|
||||
for (i = 0; i < NUM_I830_SNAPSHOTREGS; i++) {
|
||||
xf86DrvMsg (pScrn->scrnIndex, X_INFO, "%20.20s: 0x%08x\n",
|
||||
i830_snapshot[i].name, (unsigned int) INREG(i830_snapshot[i].reg));
|
||||
CARD32 val = INREG(i830_snapshot[i].reg);
|
||||
|
||||
if (i830_snapshot[i].debug_output != NULL) {
|
||||
char *debug = i830_snapshot[i].debug_output(pI830,
|
||||
i830_snapshot[i].reg,
|
||||
val);
|
||||
xf86DrvMsg (pScrn->scrnIndex, X_INFO, "%20.20s: 0x%08x (%s)\n",
|
||||
i830_snapshot[i].name, (unsigned int)val, debug);
|
||||
xfree(debug);
|
||||
} else {
|
||||
xf86DrvMsg (pScrn->scrnIndex, X_INFO, "%20.20s: 0x%08x\n",
|
||||
i830_snapshot[i].name, (unsigned int)val);
|
||||
}
|
||||
}
|
||||
i830DumpIndexed (pScrn, "SR", 0x3c4, 0x3c5, 0, 7);
|
||||
msr = INREG8(0x3cc);
|
||||
|
|
|
|||
|
|
@ -478,34 +478,94 @@ i830PipeInUse (xf86CrtcPtr crtc)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the given video mode on the given pipe.
|
||||
*
|
||||
* Plane A is always output to pipe A, and plane B to pipe B. The plane
|
||||
* will not be enabled if plane_enable is FALSE, which is used for
|
||||
* load detection, when something else will be output to the pipe other than
|
||||
* display data.
|
||||
*/
|
||||
Bool
|
||||
i830PipeSetMode(xf86CrtcPtr crtc, DisplayModePtr pMode,
|
||||
Bool plane_enable)
|
||||
static void
|
||||
i830_crtc_dpms(xf86CrtcPtr crtc, int mode)
|
||||
{
|
||||
ScrnInfoPtr pScrn = crtc->scrn;
|
||||
I830Ptr pI830 = I830PTR(pScrn);
|
||||
I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
|
||||
int pipe = intel_crtc->pipe;
|
||||
intel_clock_t clock;
|
||||
CARD32 dpll = 0, fp = 0, temp;
|
||||
CARD32 htot, hblank, hsync, vtot, vblank, vsync, dspcntr;
|
||||
CARD32 pipesrc, dspsize;
|
||||
Bool ok, is_sdvo = FALSE, is_dvo = FALSE;
|
||||
Bool is_crt = FALSE, is_lvds = FALSE, is_tv = FALSE;
|
||||
int refclk, pixel_clock;
|
||||
int i;
|
||||
int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
|
||||
int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR;
|
||||
int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
|
||||
CARD32 temp;
|
||||
|
||||
/* XXX: When our outputs are all unaware of DPMS modes other than off and
|
||||
* on, we should map those modes to DPMSModeOff in the CRTC.
|
||||
*/
|
||||
switch (mode) {
|
||||
case DPMSModeOn:
|
||||
case DPMSModeStandby:
|
||||
case DPMSModeSuspend:
|
||||
/* Enable the DPLL */
|
||||
temp = INREG(dpll_reg);
|
||||
OUTREG(dpll_reg, temp | DPLL_VCO_ENABLE);
|
||||
|
||||
/* Wait for the clocks to stabilize. */
|
||||
usleep(150);
|
||||
|
||||
/* Enable the pipe */
|
||||
temp = INREG(pipeconf_reg);
|
||||
OUTREG(pipeconf_reg, temp | PIPEACONF_ENABLE);
|
||||
|
||||
/* Enable the plane */
|
||||
temp = INREG(dspcntr_reg);
|
||||
OUTREG(dspcntr_reg, temp | DISPLAY_PLANE_ENABLE);
|
||||
break;
|
||||
case DPMSModeOff:
|
||||
/* Disable display plane */
|
||||
temp = INREG(dspcntr_reg);
|
||||
OUTREG(dspcntr_reg, temp & ~DISPLAY_PLANE_ENABLE);
|
||||
|
||||
/* Disable the VGA plane that we never use */
|
||||
OUTREG(VGACNTRL, VGA_DISP_DISABLE);
|
||||
|
||||
if (!IS_I9XX(pI830)) {
|
||||
/* Wait for vblank for the disable to take effect */
|
||||
i830WaitForVblank(pScrn);
|
||||
}
|
||||
|
||||
/* Next, disable display pipes */
|
||||
temp = INREG(pipeconf_reg);
|
||||
OUTREG(pipeconf_reg, temp & ~PIPEACONF_ENABLE);
|
||||
|
||||
/* Wait for vblank for the disable to take effect. */
|
||||
i830WaitForVblank(pScrn);
|
||||
|
||||
temp = INREG(dpll_reg);
|
||||
OUTREG(dpll_reg, temp & ~DPLL_VCO_ENABLE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static Bool
|
||||
i830_crtc_mode_fixup(xf86CrtcPtr crtc, DisplayModePtr mode,
|
||||
DisplayModePtr adjusted_mode)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up registers for the given mode/adjusted_mode pair.
|
||||
*
|
||||
* The clocks, CRTCs and outputs attached to this CRTC must be off.
|
||||
*
|
||||
* This shouldn't enable any clocks, CRTCs, or outputs, but they should
|
||||
* be easily turned on/off after this.
|
||||
*/
|
||||
static void
|
||||
i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode,
|
||||
DisplayModePtr adjusted_mode)
|
||||
{
|
||||
ScrnInfoPtr pScrn = crtc->scrn;
|
||||
I830Ptr pI830 = I830PTR(pScrn);
|
||||
I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
|
||||
int pipe = intel_crtc->pipe;
|
||||
int fp_reg = (pipe == 0) ? FPA0 : FPB0;
|
||||
int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
|
||||
int dpll_md_reg = (intel_crtc->pipe == 0) ? DPLL_A_MD : DPLL_B_MD;
|
||||
int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR;
|
||||
int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
|
||||
int htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B;
|
||||
int hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B;
|
||||
int hsync_reg = (pipe == 0) ? HSYNC_A : HSYNC_B;
|
||||
|
|
@ -516,39 +576,23 @@ i830PipeSetMode(xf86CrtcPtr crtc, DisplayModePtr pMode,
|
|||
int dspstride_reg = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE;
|
||||
int dsppos_reg = (pipe == 0) ? DSPAPOS : DSPBPOS;
|
||||
int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC;
|
||||
int pipestat_reg = (pipe == 0) ? PIPEASTAT : PIPEBSTAT;
|
||||
Bool ret = FALSE;
|
||||
#ifdef XF86DRI
|
||||
Bool didLock = FALSE;
|
||||
#endif
|
||||
int i;
|
||||
int refclk;
|
||||
intel_clock_t clock;
|
||||
CARD32 dpll = 0, fp = 0, dspcntr, pipeconf;
|
||||
Bool ok, is_sdvo = FALSE, is_dvo = FALSE;
|
||||
Bool is_crt = FALSE, is_lvds = FALSE, is_tv = FALSE;
|
||||
|
||||
if (xf86ModesEqual(&crtc->curMode, pMode))
|
||||
return TRUE;
|
||||
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Requested pix clock: %d\n",
|
||||
pMode->Clock);
|
||||
|
||||
crtc->enabled = i830PipeInUse (crtc);
|
||||
|
||||
if (!crtc->enabled)
|
||||
{
|
||||
/* XXX disable crtc? */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#ifdef XF86DRI
|
||||
didLock = I830DRILock(pScrn);
|
||||
#endif
|
||||
|
||||
for (i = 0; i < pI830->xf86_config.num_output; i++)
|
||||
{
|
||||
/* Set up some convenient bools for what outputs are connected to
|
||||
* our pipe, used in DPLL setup.
|
||||
*/
|
||||
for (i = 0; i < pI830->xf86_config.num_output; i++) {
|
||||
xf86OutputPtr output = pI830->xf86_config.output[i];
|
||||
I830OutputPrivatePtr intel_output = output->driver_private;
|
||||
I830OutputPrivatePtr intel_output = output->driver_private;
|
||||
|
||||
if (output->crtc != crtc)
|
||||
continue;
|
||||
|
||||
(*output->funcs->pre_set_mode)(output, pMode);
|
||||
|
||||
switch (intel_output->type) {
|
||||
case I830_OUTPUT_LVDS:
|
||||
is_lvds = TRUE;
|
||||
|
|
@ -568,90 +612,22 @@ i830PipeSetMode(xf86CrtcPtr crtc, DisplayModePtr pMode,
|
|||
}
|
||||
}
|
||||
|
||||
if (is_lvds && (is_sdvo || is_dvo || is_tv || is_crt)) {
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
|
||||
"Can't enable LVDS and non-LVDS on the same pipe\n");
|
||||
goto done;
|
||||
}
|
||||
if (is_tv && (is_sdvo || is_dvo || is_crt || is_lvds)) {
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
|
||||
"Can't enable a TV and any other output on the same "
|
||||
"pipe\n");
|
||||
goto done;
|
||||
}
|
||||
if (pipe == 0 && is_lvds) {
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
|
||||
"Can't support LVDS on pipe A\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
htot = (pMode->CrtcHDisplay - 1) | ((pMode->CrtcHTotal - 1) << 16);
|
||||
hblank = (pMode->CrtcHBlankStart - 1) | ((pMode->CrtcHBlankEnd - 1) << 16);
|
||||
hsync = (pMode->CrtcHSyncStart - 1) | ((pMode->CrtcHSyncEnd - 1) << 16);
|
||||
vtot = (pMode->CrtcVDisplay - 1) | ((pMode->CrtcVTotal - 1) << 16);
|
||||
vblank = (pMode->CrtcVBlankStart - 1) | ((pMode->CrtcVBlankEnd - 1) << 16);
|
||||
vsync = (pMode->CrtcVSyncStart - 1) | ((pMode->CrtcVSyncEnd - 1) << 16);
|
||||
pipesrc = ((pMode->HDisplay - 1) << 16) | (pMode->VDisplay - 1);
|
||||
dspsize = ((pMode->VDisplay - 1) << 16) | (pMode->HDisplay - 1);
|
||||
pixel_clock = pMode->Clock;
|
||||
|
||||
if (is_lvds && 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, drop the timings from the
|
||||
* BIOS VBT tables here.
|
||||
*/
|
||||
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);
|
||||
pixel_clock = pI830->panel_fixed_clock;
|
||||
|
||||
if (pMode->HDisplay <= pI830->panel_fixed_hactive &&
|
||||
pMode->HDisplay <= pI830->panel_fixed_vactive)
|
||||
{
|
||||
pipesrc = ((pMode->HDisplay - 1) << 16) |
|
||||
(pMode->VDisplay - 1);
|
||||
dspsize = ((pMode->VDisplay - 1) << 16) |
|
||||
(pMode->HDisplay - 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Adjust the clock for pixel multiplication.
|
||||
* See DPLL_MD_UDI_MULTIPLIER_MASK.
|
||||
*/
|
||||
if (is_sdvo) {
|
||||
pixel_clock *= i830_sdvo_get_pixel_multiplier(pMode);
|
||||
}
|
||||
|
||||
if (IS_I9XX(pI830)) {
|
||||
refclk = 96000;
|
||||
} else {
|
||||
refclk = 48000;
|
||||
}
|
||||
|
||||
ok = i830FindBestPLL(crtc, pixel_clock, refclk, &clock);
|
||||
if (!ok) {
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
|
||||
"Couldn't find PLL settings for mode!\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
dpll = DPLL_VCO_ENABLE | DPLL_VGA_MODE_DIS;
|
||||
ok = i830FindBestPLL(crtc, adjusted_mode->Clock, refclk, &clock);
|
||||
if (!ok)
|
||||
FatalError("Couldn't find PLL settings for mode!\n");
|
||||
|
||||
fp = clock.n << 16 | clock.m1 << 8 | clock.m2;
|
||||
|
||||
i830PrintPll("chosen", &clock);
|
||||
ErrorF("clock regs: 0x%08x, 0x%08x\n", (int)dpll, (int)fp);
|
||||
|
||||
dpll = DPLL_VGA_MODE_DIS;
|
||||
if (IS_I9XX(pI830)) {
|
||||
if (is_lvds)
|
||||
dpll |= DPLLB_MODE_LVDS;
|
||||
|
|
@ -686,33 +662,15 @@ i830PipeSetMode(xf86CrtcPtr crtc, DisplayModePtr pMode,
|
|||
/* dpll |= PLL_REF_INPUT_TVCLKINBC; */
|
||||
dpll |= 3;
|
||||
}
|
||||
#if 0
|
||||
#if 0
|
||||
else if (is_lvds)
|
||||
dpll |= PLLB_REF_INPUT_SPREADSPECTRUMIN;
|
||||
#endif
|
||||
else
|
||||
else
|
||||
dpll |= PLL_REF_INPUT_DREFCLK;
|
||||
|
||||
fp = clock.n << 16 | clock.m1 << 8 | clock.m2;
|
||||
|
||||
#if 1
|
||||
ErrorF("hact: %d htot: %d hbstart: %d hbend: %d hsyncstart: %d hsyncend: %d\n",
|
||||
(int)(htot & 0xffff) + 1, (int)(htot >> 16) + 1,
|
||||
(int)(hblank & 0xffff) + 1, (int)(hblank >> 16) + 1,
|
||||
(int)(hsync & 0xffff) + 1, (int)(hsync >> 16) + 1);
|
||||
ErrorF("vact: %d vtot: %d vbstart: %d vbend: %d vsyncstart: %d vsyncend: %d\n",
|
||||
(int)(vtot & 0xffff) + 1, (int)(vtot >> 16) + 1,
|
||||
(int)(vblank & 0xffff) + 1, (int)(vblank >> 16) + 1,
|
||||
(int)(vsync & 0xffff) + 1, (int)(vsync >> 16) + 1);
|
||||
ErrorF("pipesrc: %dx%d, dspsize: %dx%d\n",
|
||||
(int)(pipesrc >> 16) + 1, (int)(pipesrc & 0xffff) + 1,
|
||||
(int)(dspsize & 0xffff) + 1, (int)(dspsize >> 16) + 1);
|
||||
#endif
|
||||
|
||||
i830PrintPll("chosen", &clock);
|
||||
ErrorF("clock regs: 0x%08x, 0x%08x\n", (int)dpll, (int)fp);
|
||||
|
||||
dspcntr = DISPLAY_PLANE_ENABLE;
|
||||
/* Set up the display plane register */
|
||||
dspcntr = 0;
|
||||
switch (pScrn->bitsPerPixel) {
|
||||
case 8:
|
||||
dspcntr |= DISPPLANE_8BPP | DISPPLANE_GAMMA_ENABLE;
|
||||
|
|
@ -739,55 +697,8 @@ i830PipeSetMode(xf86CrtcPtr crtc, DisplayModePtr pMode,
|
|||
else
|
||||
dspcntr |= DISPPLANE_SEL_PIPE_B;
|
||||
|
||||
OUTREG(VGACNTRL, VGA_DISP_DISABLE);
|
||||
|
||||
/* Finally, set the mode. */
|
||||
/* First, disable display planes */
|
||||
temp = INREG(dspcntr_reg);
|
||||
OUTREG(dspcntr_reg, temp & ~DISPLAY_PLANE_ENABLE);
|
||||
|
||||
/* Wait for vblank for the disable to take effect */
|
||||
i830WaitForVblank(pScrn);
|
||||
|
||||
/* Next, disable display pipes */
|
||||
temp = INREG(pipeconf_reg);
|
||||
OUTREG(pipeconf_reg, temp & ~PIPEACONF_ENABLE);
|
||||
|
||||
OUTREG(fp_reg, fp);
|
||||
OUTREG(dpll_reg, dpll);
|
||||
|
||||
/*
|
||||
* If the panel fitter is stuck on our pipe, turn it off.
|
||||
* The LVDS output will set it as necessary in post_set_mode.
|
||||
*/
|
||||
if (!IS_I830(pI830)) {
|
||||
if (((INREG(PFIT_CONTROL) >> 29) & 0x3) == pipe)
|
||||
OUTREG(PFIT_CONTROL, 0);
|
||||
}
|
||||
|
||||
for (i = 0; i < pI830->xf86_config.num_output; i++) {
|
||||
xf86OutputPtr output = pI830->xf86_config.output[i];
|
||||
if (output->crtc == crtc)
|
||||
(*output->funcs->post_set_mode)(output, pMode);
|
||||
}
|
||||
|
||||
OUTREG(htot_reg, htot);
|
||||
OUTREG(hblank_reg, hblank);
|
||||
OUTREG(hsync_reg, hsync);
|
||||
OUTREG(vtot_reg, vtot);
|
||||
OUTREG(vblank_reg, vblank);
|
||||
OUTREG(vsync_reg, vsync);
|
||||
OUTREG(dspstride_reg, pScrn->displayWidth * pI830->cpp);
|
||||
OUTREG(dspsize_reg, dspsize);
|
||||
OUTREG(dsppos_reg, 0);
|
||||
i830PipeSetBase(crtc, crtc->x, crtc->y);
|
||||
OUTREG(pipesrc_reg, pipesrc);
|
||||
|
||||
/* Then, turn the pipe on first */
|
||||
temp = INREG(pipeconf_reg);
|
||||
temp |= PIPEACONF_ENABLE;
|
||||
if (!IS_I9XX(pI830) && pipe == 0)
|
||||
{
|
||||
pipeconf = INREG(pipeconf_reg);
|
||||
if (!IS_I9XX(pI830) && pipe == 0) {
|
||||
/*
|
||||
* The docs say this is needed when the dot clock is > 90% of the
|
||||
* core speed. Core speeds are indicated by bits in the PCI
|
||||
|
|
@ -802,16 +713,137 @@ i830PipeSetMode(xf86CrtcPtr crtc, DisplayModePtr pMode,
|
|||
* It doesn't seem to cause any harm, although it
|
||||
* does restrict some output options.
|
||||
*/
|
||||
if (pixel_clock > 108000)
|
||||
temp |= PIPEACONF_DOUBLE_WIDE;
|
||||
if (adjusted_mode->Clock > 108000)
|
||||
pipeconf |= PIPEACONF_DOUBLE_WIDE;
|
||||
else
|
||||
temp &= ~PIPEACONF_DOUBLE_WIDE;
|
||||
pipeconf &= ~PIPEACONF_DOUBLE_WIDE;
|
||||
}
|
||||
OUTREG(pipeconf_reg, temp);
|
||||
|
||||
if (plane_enable) {
|
||||
/* And then turn the plane on */
|
||||
OUTREG(dspcntr_reg, dspcntr);
|
||||
OUTREG(fp_reg, fp);
|
||||
OUTREG(dpll_reg, dpll);
|
||||
if (IS_I965G(pI830)) {
|
||||
/* Set the SDVO multiplier/divider to 1x for the sake of analog output.
|
||||
* It will be updated by the SDVO code if SDVO had fixed up the clock
|
||||
* for a higher multiplier.
|
||||
*/
|
||||
OUTREG(dpll_md_reg, 0);
|
||||
}
|
||||
|
||||
OUTREG(htot_reg, (adjusted_mode->CrtcHDisplay - 1) |
|
||||
((adjusted_mode->CrtcHTotal - 1) << 16));
|
||||
OUTREG(hblank_reg, (adjusted_mode->CrtcHBlankStart - 1) |
|
||||
((adjusted_mode->CrtcHBlankEnd - 1) << 16));
|
||||
OUTREG(hsync_reg, (adjusted_mode->CrtcHSyncStart - 1) |
|
||||
((adjusted_mode->CrtcHSyncEnd - 1) << 16));
|
||||
OUTREG(vtot_reg, (adjusted_mode->CrtcVDisplay - 1) |
|
||||
((adjusted_mode->CrtcVTotal - 1) << 16));
|
||||
OUTREG(vblank_reg, (adjusted_mode->CrtcVBlankStart - 1) |
|
||||
((adjusted_mode->CrtcVBlankEnd - 1) << 16));
|
||||
OUTREG(vsync_reg, (adjusted_mode->CrtcVSyncStart - 1) |
|
||||
((adjusted_mode->CrtcVSyncEnd - 1) << 16));
|
||||
OUTREG(dspstride_reg, pScrn->displayWidth * pI830->cpp);
|
||||
/* pipesrc and dspsize control the size that is scaled from, which should
|
||||
* always be the user's requested size.
|
||||
*/
|
||||
OUTREG(dspsize_reg, ((mode->VDisplay - 1) << 16) | (mode->HDisplay - 1));
|
||||
OUTREG(dsppos_reg, 0);
|
||||
i830PipeSetBase(crtc, crtc->x, crtc->y);
|
||||
OUTREG(pipesrc_reg, ((mode->HDisplay - 1) << 16) | (mode->VDisplay - 1));
|
||||
OUTREG(pipeconf_reg, pipeconf);
|
||||
OUTREG(dspcntr_reg, dspcntr);
|
||||
|
||||
/* Disable the panel fitter if it was on our pipe */
|
||||
if (!IS_I830(pI830) && ((INREG(PFIT_CONTROL) >> 29) & 0x3) == pipe)
|
||||
OUTREG(PFIT_CONTROL, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the given video mode on the given pipe.
|
||||
*
|
||||
* Plane A is always output to pipe A, and plane B to pipe B. The plane
|
||||
* will not be enabled if plane_enable is FALSE, which is used for
|
||||
* load detection, when something else will be output to the pipe other than
|
||||
* display data.
|
||||
*/
|
||||
Bool
|
||||
i830PipeSetMode(xf86CrtcPtr crtc, DisplayModePtr pMode,
|
||||
Bool plane_enable)
|
||||
{
|
||||
ScrnInfoPtr pScrn = crtc->scrn;
|
||||
I830Ptr pI830 = I830PTR(pScrn);
|
||||
int i;
|
||||
Bool ret = FALSE;
|
||||
#ifdef XF86DRI
|
||||
Bool didLock = FALSE;
|
||||
#endif
|
||||
DisplayModePtr adjusted_mode;
|
||||
|
||||
/* XXX: curMode */
|
||||
|
||||
adjusted_mode = xf86DuplicateMode(pMode);
|
||||
|
||||
crtc->enabled = i830PipeInUse (crtc);
|
||||
|
||||
if (!crtc->enabled)
|
||||
{
|
||||
/* XXX disable crtc? */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#ifdef XF86DRI
|
||||
didLock = I830DRILock(pScrn);
|
||||
#endif
|
||||
|
||||
/* Pass our mode to the outputs and the CRTC to give them a chance to
|
||||
* adjust it according to limitations or output properties, and also
|
||||
* a chance to reject the mode entirely.
|
||||
*/
|
||||
for (i = 0; i < pI830->xf86_config.num_output; i++) {
|
||||
xf86OutputPtr output = pI830->xf86_config.output[i];
|
||||
|
||||
if (output->crtc != crtc)
|
||||
continue;
|
||||
|
||||
if (!output->funcs->mode_fixup(output, pMode, adjusted_mode)) {
|
||||
ret = FALSE;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
if (!crtc->funcs->mode_fixup(crtc, pMode, adjusted_mode)) {
|
||||
ret = FALSE;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Disable the outputs and CRTCs before setting the mode. */
|
||||
for (i = 0; i < pI830->xf86_config.num_output; i++) {
|
||||
xf86OutputPtr output = pI830->xf86_config.output[i];
|
||||
|
||||
if (output->crtc != crtc)
|
||||
continue;
|
||||
|
||||
/* Disable the output as the first thing we do. */
|
||||
output->funcs->dpms(output, DPMSModeOff);
|
||||
}
|
||||
|
||||
crtc->funcs->dpms(crtc, DPMSModeOff);
|
||||
|
||||
/* Set up the DPLL and any output state that needs to adjust or depend
|
||||
* on the DPLL.
|
||||
*/
|
||||
crtc->funcs->mode_set(crtc, pMode, adjusted_mode);
|
||||
for (i = 0; i < pI830->xf86_config.num_output; i++) {
|
||||
xf86OutputPtr output = pI830->xf86_config.output[i];
|
||||
if (output->crtc == crtc)
|
||||
output->funcs->mode_set(output, pMode, adjusted_mode);
|
||||
}
|
||||
|
||||
/* Now, enable the clocks, plane, pipe, and outputs that we set up. */
|
||||
crtc->funcs->dpms(crtc, DPMSModeOn);
|
||||
for (i = 0; i < pI830->xf86_config.num_output; i++) {
|
||||
xf86OutputPtr output = pI830->xf86_config.output[i];
|
||||
if (output->crtc == crtc)
|
||||
output->funcs->dpms(output, DPMSModeOn);
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
|
@ -834,6 +866,7 @@ i830PipeSetMode(xf86CrtcPtr crtc, DisplayModePtr pMode,
|
|||
|
||||
crtc->curMode = *pMode;
|
||||
|
||||
/* XXX free adjustedmode */
|
||||
ret = TRUE;
|
||||
done:
|
||||
#ifdef XF86DRI
|
||||
|
|
@ -1073,3 +1106,29 @@ i830ReleaseLoadDetectPipe(xf86OutputPtr output)
|
|||
i830DisableUnusedFunctions(pScrn);
|
||||
}
|
||||
}
|
||||
|
||||
static const xf86CrtcFuncsRec i830_crtc_funcs = {
|
||||
.dpms = i830_crtc_dpms,
|
||||
.save = NULL, /* XXX */
|
||||
.restore = NULL, /* XXX */
|
||||
.mode_fixup = i830_crtc_mode_fixup,
|
||||
.mode_set = i830_crtc_mode_set,
|
||||
.destroy = NULL, /* XXX */
|
||||
};
|
||||
|
||||
void
|
||||
i830_crtc_init(ScrnInfoPtr pScrn, int pipe)
|
||||
{
|
||||
xf86CrtcPtr crtc;
|
||||
I830CrtcPrivatePtr intel_crtc;
|
||||
|
||||
crtc = xf86CrtcCreate (pScrn, &i830_crtc_funcs);
|
||||
if (crtc == NULL)
|
||||
return;
|
||||
|
||||
intel_crtc = xnfcalloc (sizeof (I830CrtcPrivateRec), 1);
|
||||
intel_crtc->pipe = pipe;
|
||||
|
||||
crtc->driver_private = intel_crtc;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ void i830DescribeOutputConfiguration(ScrnInfoPtr pScrn);
|
|||
xf86CrtcPtr i830GetLoadDetectPipe(xf86OutputPtr output);
|
||||
void i830ReleaseLoadDetectPipe(xf86OutputPtr output);
|
||||
Bool i830PipeInUse(xf86CrtcPtr crtc);
|
||||
void i830_crtc_init(ScrnInfoPtr pScrn, int pipe);
|
||||
|
||||
/** @{
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -718,28 +718,7 @@ I830SetupOutputs(ScrnInfoPtr pScrn)
|
|||
* Setup the CRTCs
|
||||
*/
|
||||
|
||||
static const xf86CrtcFuncsRec i830_crtc_funcs = {
|
||||
};
|
||||
|
||||
static void
|
||||
I830SetupCrtcs(ScrnInfoPtr pScrn, int num_pipe)
|
||||
{
|
||||
int p;
|
||||
|
||||
for (p = 0; p < num_pipe; p++)
|
||||
{
|
||||
xf86CrtcPtr crtc = xf86CrtcCreate (pScrn, &i830_crtc_funcs);
|
||||
I830CrtcPrivatePtr intel_crtc;
|
||||
|
||||
if (!crtc)
|
||||
break;
|
||||
intel_crtc = xnfcalloc (sizeof (I830CrtcPrivateRec), 1);
|
||||
intel_crtc->pipe = p;
|
||||
|
||||
crtc->driver_private = intel_crtc;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
I830PreInitDDC(ScrnInfoPtr pScrn)
|
||||
{
|
||||
|
|
@ -1345,7 +1324,9 @@ I830PreInit(ScrnInfoPtr pScrn, int flags)
|
|||
|
||||
I830PreInitDDC(pScrn);
|
||||
I830SetupOutputs(pScrn);
|
||||
I830SetupCrtcs(pScrn, num_pipe);
|
||||
for (i = 0; i < num_pipe; i++) {
|
||||
i830_crtc_init(pScrn, i);
|
||||
}
|
||||
|
||||
if (xf86ReturnOptValBool(pI830->Options, OPTION_CLONE, FALSE)) {
|
||||
if (num_pipe == 1) {
|
||||
|
|
@ -2295,7 +2276,13 @@ RestoreHWState(ScrnInfoPtr pScrn)
|
|||
vgaHWRestore(pScrn, vgaReg, VGA_SR_FONTS);
|
||||
vgaHWLock(hwp);
|
||||
|
||||
/* First, disable display planes */
|
||||
/* Disable outputs */
|
||||
for (i = 0; i < pI830->xf86_config.num_output; i++) {
|
||||
xf86OutputPtr output = pI830->xf86_config.output[i];
|
||||
output->funcs->dpms(output, DPMSModeOff);
|
||||
}
|
||||
|
||||
/* Disable display planes */
|
||||
temp = INREG(DSPACNTR);
|
||||
OUTREG(DSPACNTR, temp & ~DISPLAY_PLANE_ENABLE);
|
||||
temp = INREG(DSPBCNTR);
|
||||
|
|
@ -2307,12 +2294,6 @@ RestoreHWState(ScrnInfoPtr pScrn)
|
|||
temp = INREG(PIPEBCONF);
|
||||
OUTREG(PIPEBCONF, temp & ~PIPEBCONF_ENABLE);
|
||||
|
||||
/* Disable outputs if necessary */
|
||||
for (i = 0; i < pI830->xf86_config.num_output; i++) {
|
||||
xf86OutputPtr output = pI830->xf86_config.output[i];
|
||||
(*output->funcs->pre_set_mode) (output, NULL);
|
||||
}
|
||||
|
||||
i830WaitForVblank(pScrn);
|
||||
|
||||
OUTREG(FPA0, pI830->saveFPA0);
|
||||
|
|
@ -2320,6 +2301,16 @@ RestoreHWState(ScrnInfoPtr pScrn)
|
|||
OUTREG(DPLL_A, pI830->saveDPLL_A);
|
||||
if (IS_I965G(pI830))
|
||||
OUTREG(DPLL_A_MD, pI830->saveDPLL_A_MD);
|
||||
if(pI830->xf86_config.num_crtc == 2) {
|
||||
OUTREG(FPB0, pI830->saveFPB0);
|
||||
OUTREG(FPB1, pI830->saveFPB1);
|
||||
OUTREG(DPLL_B, pI830->saveDPLL_B);
|
||||
if (IS_I965G(pI830))
|
||||
OUTREG(DPLL_B_MD, pI830->saveDPLL_B_MD);
|
||||
}
|
||||
/* Wait for clocks to stabilize */
|
||||
usleep(150);
|
||||
|
||||
OUTREG(HTOTAL_A, pI830->saveHTOTAL_A);
|
||||
OUTREG(HBLANK_A, pI830->saveHBLANK_A);
|
||||
OUTREG(HSYNC_A, pI830->saveHSYNC_A);
|
||||
|
|
@ -2336,11 +2327,6 @@ RestoreHWState(ScrnInfoPtr pScrn)
|
|||
}
|
||||
|
||||
if(pI830->xf86_config.num_crtc == 2) {
|
||||
OUTREG(FPB0, pI830->saveFPB0);
|
||||
OUTREG(FPB1, pI830->saveFPB1);
|
||||
OUTREG(DPLL_B, pI830->saveDPLL_B);
|
||||
if (IS_I965G(pI830))
|
||||
OUTREG(DPLL_B_MD, pI830->saveDPLL_B_MD);
|
||||
OUTREG(HTOTAL_B, pI830->saveHTOTAL_B);
|
||||
OUTREG(HBLANK_B, pI830->saveHBLANK_B);
|
||||
OUTREG(HSYNC_B, pI830->saveHSYNC_B);
|
||||
|
|
@ -2357,12 +2343,8 @@ RestoreHWState(ScrnInfoPtr pScrn)
|
|||
}
|
||||
}
|
||||
|
||||
OUTREG(PFIT_CONTROL, pI830->savePFIT_CONTROL);
|
||||
|
||||
for (i = 0; i < pI830->xf86_config.num_output; i++) {
|
||||
xf86OutputPtr output = pI830->xf86_config.output[i];
|
||||
(*output->funcs->restore) (output);
|
||||
}
|
||||
if (!IS_I830(pI830) && !IS_845G(pI830))
|
||||
OUTREG(PFIT_CONTROL, pI830->savePFIT_CONTROL);
|
||||
|
||||
if (IS_I965G(pI830)) {
|
||||
OUTREG(DSPASURF, pI830->saveDSPASURF);
|
||||
|
|
@ -2380,6 +2362,11 @@ RestoreHWState(ScrnInfoPtr pScrn)
|
|||
OUTREG(DSPACNTR, pI830->saveDSPACNTR);
|
||||
OUTREG(DSPBCNTR, pI830->saveDSPBCNTR);
|
||||
|
||||
for (i = 0; i < pI830->xf86_config.num_output; i++) {
|
||||
xf86OutputPtr output = pI830->xf86_config.output[i];
|
||||
(*output->funcs->restore) (output);
|
||||
}
|
||||
|
||||
for(i = 0; i < 7; i++) {
|
||||
OUTREG(SWF0 + (i << 2), pI830->saveSWF[i]);
|
||||
OUTREG(SWF00 + (i << 2), pI830->saveSWF[i+7]);
|
||||
|
|
|
|||
|
|
@ -59,11 +59,17 @@ struct _I830DVODriver i830_dvo_drivers[] =
|
|||
static void
|
||||
i830_dvo_dpms(xf86OutputPtr output, int mode)
|
||||
{
|
||||
ScrnInfoPtr pScrn = output->scrn;
|
||||
I830Ptr pI830 = I830PTR(pScrn);
|
||||
I830OutputPrivatePtr intel_output = output->driver_private;
|
||||
if (mode == DPMSModeOn)
|
||||
|
||||
if (mode == DPMSModeOn) {
|
||||
OUTREG(DVOC, INREG(DVOC) | DVO_ENABLE);
|
||||
(*intel_output->i2c_drv->vid_rec->Power)(intel_output->i2c_drv->dev_priv, TRUE);
|
||||
else
|
||||
} else {
|
||||
(*intel_output->i2c_drv->vid_rec->Power)(intel_output->i2c_drv->dev_priv, FALSE);
|
||||
OUTREG(DVOC, INREG(DVOC) & ~DVO_ENABLE);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -113,48 +119,51 @@ i830_dvo_mode_valid(xf86OutputPtr output, DisplayModePtr pMode)
|
|||
return MODE_BAD;
|
||||
}
|
||||
|
||||
static void
|
||||
i830_dvo_pre_set_mode(xf86OutputPtr output, DisplayModePtr pMode)
|
||||
static Bool
|
||||
i830_dvo_mode_fixup(xf86OutputPtr output, DisplayModePtr mode,
|
||||
DisplayModePtr adjusted_mode)
|
||||
{
|
||||
ScrnInfoPtr pScrn = output->scrn;
|
||||
I830Ptr pI830 = I830PTR(pScrn);
|
||||
I830OutputPrivatePtr intel_output = output->driver_private;
|
||||
/* XXX: Hook this up to a DVO driver function */
|
||||
|
||||
(*intel_output->i2c_drv->vid_rec->Mode)(intel_output->i2c_drv->dev_priv, pMode);
|
||||
|
||||
OUTREG(DVOC, INREG(DVOC) & ~DVO_ENABLE);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
i830_dvo_post_set_mode(xf86OutputPtr output, DisplayModePtr pMode)
|
||||
i830_dvo_mode_set(xf86OutputPtr output, DisplayModePtr mode,
|
||||
DisplayModePtr adjusted_mode)
|
||||
{
|
||||
ScrnInfoPtr pScrn = output->scrn;
|
||||
I830Ptr pI830 = I830PTR(pScrn);
|
||||
xf86CrtcPtr crtc = output->crtc;
|
||||
I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
|
||||
I830OutputPrivatePtr intel_output = output->driver_private;
|
||||
int pipe = intel_crtc->pipe;
|
||||
CARD32 dvo;
|
||||
int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
|
||||
|
||||
intel_output->i2c_drv->vid_rec->Mode(intel_output->i2c_drv->dev_priv,
|
||||
mode);
|
||||
|
||||
/* Save the data order, since I don't know what it should be set to. */
|
||||
dvo = INREG(DVOC) & (DVO_PRESERVE_MASK | DVO_DATA_ORDER_GBRG);
|
||||
dvo |= DVO_ENABLE;
|
||||
dvo |= DVO_DATA_ORDER_FP | DVO_BORDER_ENABLE | DVO_BLANK_ACTIVE_HIGH;
|
||||
|
||||
if (pipe == 1)
|
||||
dvo |= DVO_PIPE_B_SELECT;
|
||||
|
||||
if (pMode->Flags & V_PHSYNC)
|
||||
if (adjusted_mode->Flags & V_PHSYNC)
|
||||
dvo |= DVO_HSYNC_ACTIVE_HIGH;
|
||||
if (pMode->Flags & V_PVSYNC)
|
||||
if (adjusted_mode->Flags & V_PVSYNC)
|
||||
dvo |= DVO_VSYNC_ACTIVE_HIGH;
|
||||
|
||||
OUTREG(dpll_reg, INREG(dpll_reg) | DPLL_DVO_HIGH_SPEED);
|
||||
|
||||
/*OUTREG(DVOB_SRCDIM, (pMode->HDisplay << DVO_SRCDIM_HORIZONTAL_SHIFT) |
|
||||
(pMode->VDisplay << DVO_SRCDIM_VERTICAL_SHIFT));*/
|
||||
OUTREG(DVOC_SRCDIM, (pMode->HDisplay << DVO_SRCDIM_HORIZONTAL_SHIFT) |
|
||||
(pMode->VDisplay << DVO_SRCDIM_VERTICAL_SHIFT));
|
||||
/*OUTREG(DVOB_SRCDIM,
|
||||
(adjusted_mode->HDisplay << DVO_SRCDIM_HORIZONTAL_SHIFT) |
|
||||
(adjusted_mode->VDisplay << DVO_SRCDIM_VERTICAL_SHIFT));*/
|
||||
OUTREG(DVOC_SRCDIM,
|
||||
(adjusted_mode->HDisplay << DVO_SRCDIM_HORIZONTAL_SHIFT) |
|
||||
(adjusted_mode->VDisplay << DVO_SRCDIM_VERTICAL_SHIFT));
|
||||
/*OUTREG(DVOB, dvo);*/
|
||||
OUTREG(DVOC, dvo);
|
||||
}
|
||||
|
|
@ -222,8 +231,8 @@ static const xf86OutputFuncsRec i830_dvo_output_funcs = {
|
|||
.save = i830_dvo_save,
|
||||
.restore = i830_dvo_restore,
|
||||
.mode_valid = i830_dvo_mode_valid,
|
||||
.pre_set_mode = i830_dvo_pre_set_mode,
|
||||
.post_set_mode = i830_dvo_post_set_mode,
|
||||
.mode_fixup = i830_dvo_mode_fixup,
|
||||
.mode_set = i830_dvo_mode_set,
|
||||
.detect = i830_dvo_detect,
|
||||
.get_modes = i830_ddc_get_modes,
|
||||
.destroy = i830_dvo_destroy
|
||||
|
|
|
|||
125
src/i830_lvds.c
125
src/i830_lvds.c
|
|
@ -40,7 +40,7 @@ static void
|
|||
i830SetLVDSPanelPower(ScrnInfoPtr pScrn, Bool on)
|
||||
{
|
||||
I830Ptr pI830 = I830PTR(pScrn);
|
||||
CARD32 pp_status, pp_control;
|
||||
CARD32 pp_status;
|
||||
CARD32 blc_pwm_ctl;
|
||||
int backlight_duty_cycle;
|
||||
|
||||
|
|
@ -77,6 +77,8 @@ i830_lvds_dpms (xf86OutputPtr output, int mode)
|
|||
i830SetLVDSPanelPower(pScrn, TRUE);
|
||||
else
|
||||
i830SetLVDSPanelPower(pScrn, FALSE);
|
||||
|
||||
/* XXX: We never power down the LVDS pair. */
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -128,28 +130,80 @@ i830_lvds_mode_valid(xf86OutputPtr output, DisplayModePtr pMode)
|
|||
return MODE_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
i830_lvds_pre_set_mode(xf86OutputPtr output, DisplayModePtr pMode)
|
||||
static Bool
|
||||
i830_lvds_mode_fixup(xf86OutputPtr output, DisplayModePtr mode,
|
||||
DisplayModePtr adjusted_mode)
|
||||
{
|
||||
ScrnInfoPtr pScrn = output->scrn;
|
||||
/* Always make sure the LVDS is off before we play with DPLLs and pipe
|
||||
* configuration. We can skip this in some cases (for example, going
|
||||
* between hi-res modes with automatic panel scaling are fine), but be
|
||||
* conservative for now.
|
||||
ScrnInfoPtr pScrn = output->scrn;
|
||||
I830Ptr pI830 = I830PTR(pScrn);
|
||||
I830CrtcPrivatePtr intel_crtc = output->crtc->driver_private;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < pI830->xf86_config.num_output; i++) {
|
||||
xf86OutputPtr other_output = pI830->xf86_config.output[i];
|
||||
|
||||
if (other_output != output && other_output->crtc == output->crtc) {
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
|
||||
"Can't enable LVDS and another output on the same "
|
||||
"pipe\n");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (intel_crtc->pipe == 0) {
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
|
||||
"Can't support LVDS on pipe A\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* If we have timings from the BIOS for the panel, put them in
|
||||
* to the adjusted mode. The CRTC will be set up for this mode,
|
||||
* with the panel scaling set up to source from the H/VDisplay
|
||||
* of the original mode.
|
||||
*/
|
||||
i830SetLVDSPanelPower(pScrn, FALSE);
|
||||
if (pI830->panel_fixed_mode != NULL) {
|
||||
adjusted_mode->HDisplay = pI830->panel_fixed_mode->HDisplay;
|
||||
adjusted_mode->HSyncStart = pI830->panel_fixed_mode->HSyncStart;
|
||||
adjusted_mode->HSyncEnd = pI830->panel_fixed_mode->HSyncEnd;
|
||||
adjusted_mode->HTotal = pI830->panel_fixed_mode->HTotal;
|
||||
adjusted_mode->VDisplay = pI830->panel_fixed_mode->VDisplay;
|
||||
adjusted_mode->VSyncStart = pI830->panel_fixed_mode->VSyncStart;
|
||||
adjusted_mode->VSyncEnd = pI830->panel_fixed_mode->VSyncEnd;
|
||||
adjusted_mode->VTotal = pI830->panel_fixed_mode->VTotal;
|
||||
adjusted_mode->Clock = pI830->panel_fixed_mode->Clock;
|
||||
xf86SetModeCrtc(adjusted_mode, INTERLACE_HALVE_V);
|
||||
}
|
||||
|
||||
/* XXX: if we don't have BIOS fixed timings (or we have
|
||||
* a preferred mode from DDC, probably), we should use the
|
||||
* DDC mode as the fixed timing.
|
||||
*/
|
||||
|
||||
/* XXX: It would be nice to support lower refresh rates on the
|
||||
* panels to reduce power consumption, and perhaps match the
|
||||
* user's requested refresh rate.
|
||||
*/
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
i830_lvds_post_set_mode(xf86OutputPtr output, DisplayModePtr pMode)
|
||||
i830_lvds_mode_set(xf86OutputPtr output, DisplayModePtr mode,
|
||||
DisplayModePtr adjusted_mode)
|
||||
{
|
||||
ScrnInfoPtr pScrn = output->scrn;
|
||||
I830Ptr pI830 = I830PTR(pScrn);
|
||||
CARD32 pfit_control;
|
||||
ScrnInfoPtr pScrn = output->scrn;
|
||||
I830Ptr pI830 = I830PTR(pScrn);
|
||||
CARD32 pfit_control;
|
||||
|
||||
/* The LVDS pin pair needs to be on before the DPLLs are enabled.
|
||||
* This is an exception to the general rule that mode_set doesn't turn
|
||||
* things on.
|
||||
*/
|
||||
OUTREG(LVDS, INREG(LVDS) | LVDS_PORT_EN | LVDS_PIPEB_SELECT);
|
||||
|
||||
/* Enable automatic panel scaling so that non-native modes fill the
|
||||
* screen. Should be enabled before the pipe is enabled, according to
|
||||
* register description.
|
||||
* register description and PRM.
|
||||
*/
|
||||
pfit_control = (PFIT_ENABLE |
|
||||
VERT_AUTO_SCALE | HORIZ_AUTO_SCALE |
|
||||
|
|
@ -159,19 +213,6 @@ i830_lvds_post_set_mode(xf86OutputPtr output, DisplayModePtr pMode)
|
|||
pfit_control |= PANEL_8TO6_DITHER_ENABLE;
|
||||
|
||||
OUTREG(PFIT_CONTROL, pfit_control);
|
||||
|
||||
/* Disable the PLL before messing with LVDS enable */
|
||||
OUTREG(FPB0, INREG(FPB0) & ~DPLL_VCO_ENABLE);
|
||||
|
||||
/* LVDS must be powered on before PLL is enabled and before power
|
||||
* sequencing the panel.
|
||||
*/
|
||||
OUTREG(LVDS, INREG(LVDS) | LVDS_PORT_EN | LVDS_PIPEB_SELECT);
|
||||
|
||||
/* Re-enable the PLL */
|
||||
OUTREG(FPB0, INREG(FPB0) | DPLL_VCO_ENABLE);
|
||||
|
||||
i830SetLVDSPanelPower(pScrn, TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -194,30 +235,16 @@ i830_lvds_get_modes(xf86OutputPtr output)
|
|||
{
|
||||
ScrnInfoPtr pScrn = output->scrn;
|
||||
I830Ptr pI830 = I830PTR(pScrn);
|
||||
DisplayModePtr modes, new;
|
||||
char stmp[32];
|
||||
DisplayModePtr modes;
|
||||
|
||||
modes = i830_ddc_get_modes(output);
|
||||
if (modes != NULL)
|
||||
return modes;
|
||||
|
||||
new = xnfcalloc(1, sizeof (DisplayModeRec));
|
||||
sprintf(stmp, "%dx%d", pI830->PanelXRes, pI830->PanelYRes);
|
||||
new->name = xnfalloc(strlen(stmp) + 1);
|
||||
strcpy(new->name, stmp);
|
||||
new->HDisplay = pI830->PanelXRes;
|
||||
new->VDisplay = pI830->PanelYRes;
|
||||
new->HSyncStart = pI830->panel_fixed_hactive + pI830->panel_fixed_hsyncoff;
|
||||
new->HSyncEnd = new->HSyncStart + pI830->panel_fixed_hsyncwidth;
|
||||
new->HTotal = new->HSyncEnd + 1;
|
||||
new->VSyncStart = pI830->panel_fixed_vactive + pI830->panel_fixed_vsyncoff;
|
||||
new->VSyncEnd = new->VSyncStart + pI830->panel_fixed_vsyncwidth;
|
||||
new->VTotal = new->VSyncEnd + 1;
|
||||
new->Clock = pI830->panel_fixed_clock;
|
||||
if (pI830->panel_fixed_mode != NULL)
|
||||
return xf86DuplicateMode(pI830->panel_fixed_mode);
|
||||
|
||||
new->type = M_T_PREFERRED;
|
||||
|
||||
return new;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -234,8 +261,8 @@ static const xf86OutputFuncsRec i830_lvds_output_funcs = {
|
|||
.save = i830_lvds_save,
|
||||
.restore = i830_lvds_restore,
|
||||
.mode_valid = i830_lvds_mode_valid,
|
||||
.pre_set_mode = i830_lvds_pre_set_mode,
|
||||
.post_set_mode = i830_lvds_post_set_mode,
|
||||
.mode_fixup = i830_lvds_mode_fixup,
|
||||
.mode_set = i830_lvds_mode_set,
|
||||
.detect = i830_lvds_detect,
|
||||
.get_modes = i830_lvds_get_modes,
|
||||
.destroy = i830_lvds_destroy
|
||||
|
|
@ -274,7 +301,9 @@ i830_lvds_init(ScrnInfoPtr pScrn)
|
|||
* display.
|
||||
*/
|
||||
|
||||
if (pI830->PanelXRes == 800 && pI830->PanelYRes == 600) {
|
||||
if (pI830->panel_fixed_mode != NULL &&
|
||||
pI830->panel_fixed_mode->HDisplay == 800 &&
|
||||
pI830->panel_fixed_mode->VDisplay == 600) {
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
||||
"Suspected Mac Mini, ignoring the LVDS\n");
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@
|
|||
|
||||
#include "i830_xf86Crtc.h"
|
||||
#include "i830_randr.h"
|
||||
#include "i830_debug.h"
|
||||
#include "i830_display.h"
|
||||
#include "i830.h"
|
||||
|
||||
|
|
@ -604,6 +605,8 @@ xf86RandR12CrtcSet (ScreenPtr pScreen,
|
|||
i830PipeSetBase(crtc, x, y);
|
||||
}
|
||||
i830DisableUnusedFunctions (pScrn);
|
||||
|
||||
i830DumpRegs(pScrn);
|
||||
}
|
||||
return xf86RandR12CrtcNotify (randr_crtc);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -534,15 +534,36 @@ i830_sdvo_set_clock_rate_mult(xf86OutputPtr output, CARD8 val)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static Bool
|
||||
i830_sdvo_mode_fixup(xf86OutputPtr output, DisplayModePtr mode,
|
||||
DisplayModePtr adjusted_mode)
|
||||
{
|
||||
/* Make the CRTC code factor in the SDVO pixel multiplier. The SDVO
|
||||
* device will be told of the multiplier during mode_set.
|
||||
*/
|
||||
adjusted_mode->Clock *= i830_sdvo_get_pixel_multiplier(mode);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
i830_sdvo_pre_set_mode(xf86OutputPtr output, DisplayModePtr mode)
|
||||
i830_sdvo_mode_set(xf86OutputPtr output, DisplayModePtr mode,
|
||||
DisplayModePtr adjusted_mode)
|
||||
{
|
||||
ScrnInfoPtr pScrn = output->scrn;
|
||||
I830Ptr pI830 = I830PTR(pScrn);
|
||||
I830OutputPrivatePtr intel_output = output->driver_private;
|
||||
struct i830_sdvo_priv *dev_priv = intel_output->dev_priv;
|
||||
CARD16 width;
|
||||
CARD16 height;
|
||||
xf86CrtcPtr crtc = output->crtc;
|
||||
I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
|
||||
Bool input1, input2;
|
||||
CARD32 dpll, sdvox;
|
||||
int dpll_reg = (intel_crtc->pipe == 0) ? DPLL_A : DPLL_B;
|
||||
int dpll_md_reg = (intel_crtc->pipe == 0) ? DPLL_A_MD : DPLL_B_MD;
|
||||
int sdvo_pixel_multiply;
|
||||
int i;
|
||||
CARD8 status;
|
||||
CARD16 width, height;
|
||||
CARD16 h_blank_len, h_sync_len, v_blank_len, v_sync_len;
|
||||
CARD16 h_sync_offset, v_sync_offset;
|
||||
struct i830_sdvo_dtd output_dtd;
|
||||
|
|
@ -633,26 +654,6 @@ i830_sdvo_pre_set_mode(xf86OutputPtr output, DisplayModePtr mode)
|
|||
break;
|
||||
}
|
||||
|
||||
OUTREG(dev_priv->output_device, INREG(dev_priv->output_device) & ~SDVO_ENABLE);
|
||||
}
|
||||
|
||||
static void
|
||||
i830_sdvo_post_set_mode(xf86OutputPtr output, DisplayModePtr mode)
|
||||
{
|
||||
ScrnInfoPtr pScrn = output->scrn;
|
||||
I830OutputPrivatePtr intel_output = output->driver_private;
|
||||
struct i830_sdvo_priv *dev_priv = intel_output->dev_priv;
|
||||
xf86CrtcPtr crtc = output->crtc;
|
||||
I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
|
||||
I830Ptr pI830 = I830PTR(pScrn);
|
||||
Bool input1, input2;
|
||||
CARD32 dpll, sdvox;
|
||||
int dpll_reg = (intel_crtc->pipe == 0) ? DPLL_A : DPLL_B;
|
||||
int dpll_md_reg = (intel_crtc->pipe == 0) ? DPLL_A_MD : DPLL_B_MD;
|
||||
int sdvo_pixel_multiply;
|
||||
int i;
|
||||
CARD8 status;
|
||||
|
||||
/* Set the SDVO control regs. */
|
||||
sdvox = INREG(dev_priv->output_device);
|
||||
switch (dev_priv->output_device) {
|
||||
|
|
@ -663,7 +664,7 @@ i830_sdvo_post_set_mode(xf86OutputPtr output, DisplayModePtr mode)
|
|||
sdvox &= SDVOC_PRESERVE_MASK;
|
||||
break;
|
||||
}
|
||||
sdvox |= SDVO_ENABLE | (9 << 19) | SDVO_BORDER_ENABLE;
|
||||
sdvox |= (9 << 19) | SDVO_BORDER_ENABLE;
|
||||
if (intel_crtc->pipe == 1)
|
||||
sdvox |= SDVO_PIPE_B_SELECT;
|
||||
|
||||
|
|
@ -1014,8 +1015,8 @@ static const xf86OutputFuncsRec i830_sdvo_output_funcs = {
|
|||
.save = i830_sdvo_save,
|
||||
.restore = i830_sdvo_restore,
|
||||
.mode_valid = i830_sdvo_mode_valid,
|
||||
.pre_set_mode = i830_sdvo_pre_set_mode,
|
||||
.post_set_mode = i830_sdvo_post_set_mode,
|
||||
.mode_fixup = i830_sdvo_mode_fixup,
|
||||
.mode_set = i830_sdvo_mode_set,
|
||||
.detect = i830_sdvo_detect,
|
||||
.get_modes = i830_ddc_get_modes,
|
||||
.destroy = i830_sdvo_destroy
|
||||
|
|
|
|||
|
|
@ -295,8 +295,33 @@ static const CARD32 v_chroma[43] = {
|
|||
0x28003100, 0x28002F00, 0x00003100,
|
||||
};
|
||||
|
||||
static Bool
|
||||
i830_tv_mode_fixup(xf86OutputPtr output, DisplayModePtr mode,
|
||||
DisplayModePtr adjusted_mode)
|
||||
{
|
||||
ScrnInfoPtr pScrn = output->scrn;
|
||||
I830Ptr pI830 = I830PTR(pScrn);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < pI830->xf86_config.num_output; i++) {
|
||||
xf86OutputPtr other_output = pI830->xf86_config.output[i];
|
||||
|
||||
if (other_output != output && other_output->crtc == output->crtc) {
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
|
||||
"Can't enable TV and another output on the same "
|
||||
"pipe\n");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* XXX: fill me in */
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
i830_tv_post_set_mode(xf86OutputPtr output, DisplayModePtr pMode)
|
||||
i830_tv_mode_set(xf86OutputPtr output, DisplayModePtr mode,
|
||||
DisplayModePtr adjusted_mode)
|
||||
{
|
||||
ScrnInfoPtr pScrn = output->scrn;
|
||||
I830Ptr pI830 = I830PTR(pScrn);
|
||||
|
|
@ -359,7 +384,7 @@ i830_tv_post_set_mode(xf86OutputPtr output, DisplayModePtr pMode)
|
|||
vctl7 = (tv_mode->vburst_start_f4 << TV_VBURST_START_F4_SHIFT) |
|
||||
(tv_mode->vburst_end_f4 << TV_VBURST_END_F4_SHIFT);
|
||||
|
||||
tv_ctl = TV_ENC_ENABLE;
|
||||
tv_ctl = 0;
|
||||
if (intel_crtc->pipe == 1)
|
||||
tv_ctl |= TV_ENC_PIPEB_SELECT;
|
||||
|
||||
|
|
@ -403,7 +428,7 @@ i830_tv_post_set_mode(xf86OutputPtr output, DisplayModePtr pMode)
|
|||
tv_ctl |= TV_ENC_C0_FIX | TV_ENC_SDP_FIX;
|
||||
|
||||
tv_filter_ctl = TV_AUTO_SCALE;
|
||||
if (pMode->HDisplay > 1024)
|
||||
if (mode->HDisplay > 1024)
|
||||
tv_ctl |= TV_V_FILTER_BYPASS;
|
||||
|
||||
OUTREG(TV_H_CTL_1, hctl1);
|
||||
|
|
@ -635,8 +660,8 @@ static const xf86OutputFuncsRec i830_tv_output_funcs = {
|
|||
.save = i830_tv_save,
|
||||
.restore = i830_tv_restore,
|
||||
.mode_valid = i830_tv_mode_valid,
|
||||
.pre_set_mode = i830_tv_pre_set_mode,
|
||||
.post_set_mode = i830_tv_post_set_mode,
|
||||
.mode_fixup = i830_tv_mode_fixup,
|
||||
.mode_set = i830_tv_mode_set,
|
||||
.detect = i830_tv_detect,
|
||||
.get_modes = i830_tv_get_modes,
|
||||
.destroy = i830_tv_destroy
|
||||
|
|
|
|||
|
|
@ -27,14 +27,15 @@
|
|||
#include "i830_xf86Modes.h"
|
||||
|
||||
typedef struct _xf86Crtc xf86CrtcRec, *xf86CrtcPtr;
|
||||
typedef struct _xf86Output xf86OutputRec, *xf86OutputPtr;
|
||||
|
||||
typedef struct _xf86CrtcFuncs {
|
||||
/**
|
||||
* Turns the crtc on/off, or sets intermediate power levels if available.
|
||||
*
|
||||
* Unsupported intermediate modes drop to the lower power setting. If the
|
||||
* mode is DPMSModeOff, the crtc must be disabled, as the DPLL may be
|
||||
* disabled afterwards.
|
||||
* mode is DPMSModeOff, the crtc must be disabled sufficiently for it to
|
||||
* be safe to call mode_set.
|
||||
*/
|
||||
void
|
||||
(*dpms)(xf86CrtcPtr crtc,
|
||||
|
|
@ -52,6 +53,27 @@ typedef struct _xf86CrtcFuncs {
|
|||
void
|
||||
(*restore)(xf86CrtcPtr crtc);
|
||||
|
||||
|
||||
/**
|
||||
* Callback to adjust the mode to be set in the CRTC.
|
||||
*
|
||||
* This allows a CRTC to adjust the clock or even the entire set of
|
||||
* timings, which is used for panels with fixed timings or for
|
||||
* buses with clock limitations.
|
||||
*/
|
||||
Bool
|
||||
(*mode_fixup)(xf86CrtcPtr crtc,
|
||||
DisplayModePtr mode,
|
||||
DisplayModePtr adjusted_mode);
|
||||
|
||||
/**
|
||||
* Callback for setting up a video mode after fixups have been made.
|
||||
*/
|
||||
void
|
||||
(*mode_set)(xf86CrtcPtr crtc,
|
||||
DisplayModePtr mode,
|
||||
DisplayModePtr adjusted_mode);
|
||||
|
||||
/**
|
||||
* Clean up driver-specific bits of the crtc
|
||||
*/
|
||||
|
|
@ -127,8 +149,6 @@ struct _xf86Crtc {
|
|||
#endif
|
||||
};
|
||||
|
||||
typedef struct _xf86Output xf86OutputRec, *xf86OutputPtr;
|
||||
|
||||
typedef struct _xf86OutputFuncs {
|
||||
/**
|
||||
* Turns the output on/off, or sets intermediate power levels if available.
|
||||
|
|
@ -157,7 +177,7 @@ typedef struct _xf86OutputFuncs {
|
|||
* Callback for testing a video mode for a given output.
|
||||
*
|
||||
* This function should only check for cases where a mode can't be supported
|
||||
* on the pipe specifically, and not represent generic CRTC limitations.
|
||||
* on the output specifically, and not represent generic CRTC limitations.
|
||||
*
|
||||
* \return MODE_OK if the mode is valid, or another MODE_* otherwise.
|
||||
*/
|
||||
|
|
@ -166,22 +186,28 @@ typedef struct _xf86OutputFuncs {
|
|||
DisplayModePtr pMode);
|
||||
|
||||
/**
|
||||
* Callback for setting up a video mode before any crtc/dpll changes.
|
||||
* Callback to adjust the mode to be set in the CRTC.
|
||||
*
|
||||
* \param pMode the mode that will be set, or NULL if the mode to be set is
|
||||
* unknown (such as the restore path of VT switching).
|
||||
* This allows an output to adjust the clock or even the entire set of
|
||||
* timings, which is used for panels with fixed timings or for
|
||||
* buses with clock limitations.
|
||||
*/
|
||||
void
|
||||
(*pre_set_mode)(xf86OutputPtr output,
|
||||
DisplayModePtr pMode);
|
||||
Bool
|
||||
(*mode_fixup)(xf86OutputPtr output,
|
||||
DisplayModePtr mode,
|
||||
DisplayModePtr adjusted_mode);
|
||||
|
||||
/**
|
||||
* Callback for setting up a video mode after the DPLL update but before
|
||||
* the plane is enabled.
|
||||
* Callback for setting up a video mode after fixups have been made.
|
||||
*
|
||||
* This is only called while the output is disabled. The dpms callback
|
||||
* must be all that's necessary for the output, to turn the output on
|
||||
* after this function is called.
|
||||
*/
|
||||
void
|
||||
(*post_set_mode)(xf86OutputPtr output,
|
||||
DisplayModePtr pMode);
|
||||
(*mode_set)(xf86OutputPtr output,
|
||||
DisplayModePtr mode,
|
||||
DisplayModePtr adjusted_mode);
|
||||
|
||||
/**
|
||||
* Probe for a connected output, and return detect_status.
|
||||
|
|
|
|||
Loading…
Reference in New Issue