Merge branch 'crestline' of git://otc-graphics.jf.intel.com/git/xorg/driver/xf86-video-intel into crestline

This commit is contained in:
Nian Wu 2007-03-21 08:55:50 +08:00
commit 300e893cec
5 changed files with 118 additions and 37 deletions

View File

@ -830,6 +830,8 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#define PFIT_CONTROL 0x61230
# define PFIT_ENABLE (1 << 31)
# define PFIT_PIPE_MASK (3 << 29)
# define PFIT_PIPE_SHIFT 29
# define VERT_INTERP_DISABLE (0 << 10)
# define VERT_INTERP_BILINEAR (1 << 10)
# define VERT_INTERP_MASK (3 << 10)
@ -1128,8 +1130,22 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#define DVO_SRCDIM_HORIZONTAL_SHIFT 12
#define DVO_SRCDIM_VERTICAL_SHIFT 0
/** @defgroup LVDS
* @{
*/
/**
* This register controls the LVDS output enable, pipe selection, and data
* format selection.
*
* All of the clock/data pairs are force powered down by power sequencing.
*/
#define LVDS 0x61180
/**
* Enables the LVDS port. This bit must be set before DPLLs are enabled, as
* the DPLL semantics change when the LVDS is assigned to that pipe.
*/
# define LVDS_PORT_EN (1 << 31)
/** Selects pipe B for LVDS data. Must be set on pre-965. */
# define LVDS_PIPEB_SELECT (1 << 30)
/* on 965, dithering is enabled in this register, not PFIT_CONTROL */
@ -1189,18 +1205,39 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
# define LVDS_POWER_DOWN_TRI_STATE (1 << 10)
/*
* Clock A control; overridden by LVDS power sequencing
/**
* Enables the A0-A2 data pairs and CLKA, containing 18 bits of color data per
* pixel.
*/
# define LVDS_A0A2_CLKA_POWER_MASK (3 << 8)
# define LVDS_A0A2_CLKA_POWER_DOWN (0 << 8)
# define LVDS_A0A2_CLKA_POWER_UP (3 << 8)
/**
* Controls the A3 data pair, which contains the additional LSBs for 24 bit
* mode. Only enabled if LVDS_A0A2_CLKA_POWER_UP also indicates it should be
* on.
*/
# define LVDS_A3_POWER_MASK (3 << 6)
# define LVDS_A3_POWER_DOWN (0 << 6)
# define LVDS_A3_POWER_UP (3 << 6)
/**
* Controls the CLKB pair. This should only be set when LVDS_B0B3_POWER_UP
* is set.
*/
# define LVDS_CLKB_POWER_MASK (3 << 4)
# define LVDS_CLKB_POWER_DOWN (0 << 4)
# define LVDS_CLKB_POWER_UP (3 << 4)
/* power down everything including A3 (0V) */
# define LVDS_CLKA_POWER_DOWN (0 << 8)
/**
* Controls the B0-B3 data pairs. This must be set to match the DPLL p2
* setting for whether we are in dual-channel mode. The B3 pair will
* additionally only be powered up when LVDS_A3_POWER_UP is set.
*/
# define LVDS_B0B3_POWER_MASK (3 << 2)
# define LVDS_B0B3_POWER_DOWN (0 << 2)
# define LVDS_B0B3_POWER_UP (3 << 2)
/* Partially active. A0, A1, A2 set to 0, timing active, clock active */
# define LVDS_CLKA_POWER_PARTIAL (1 << 8)
/* running, data and clock active */
# define LVDS_CLKA_POWER_UP (3 << 8)
/** @} */
/*
* Two channel clock control. Turn this on if you need clkb for two channel mode

View File

@ -269,8 +269,21 @@ DEBUGSTRING(i830_debug_lvds)
{
char pipe = val & LVDS_PIPEB_SELECT ? 'B' : 'A';
char *enable = val & LVDS_PORT_EN ? "enabled" : "disabled";
int depth;
char *channels;
return XNFprintf("%s, pipe %c", enable, pipe);
if ((val & LVDS_A3_POWER_MASK) == LVDS_A3_POWER_UP)
depth = 24;
else
depth = 18;
if ((val & LVDS_B0B3_POWER_MASK) == LVDS_B0B3_POWER_UP)
channels = "2 channels";
else
channels = "1 channel";
return XNFprintf("%s, pipe %c, %d bit, %s",
enable, pipe, depth, channels);
}
DEBUGSTRING(i830_debug_sdvo)

View File

@ -298,8 +298,9 @@ i830PllIsValid(xf86CrtcPtr crtc, intel_clock_t *clock)
}
/**
* Returns a set of divisors for the desired target clock with the given refclk,
* or FALSE. Divisor values are the actual divisors for
* Returns a set of divisors for the desired target clock with the given
* refclk, or FALSE. The returned values represent the clock equation:
* reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2.
*/
static Bool
i830FindBestPLL(xf86CrtcPtr crtc, int target, int refclk, intel_clock_t *best_clock)
@ -310,10 +311,23 @@ i830FindBestPLL(xf86CrtcPtr crtc, int target, int refclk, intel_clock_t *best_cl
const intel_limit_t *limit = intel_limit (crtc);
int err = target;
if (target < limit->p2.dot_limit)
clock.p2 = limit->p2.p2_slow;
else
clock.p2 = limit->p2.p2_fast;
if (IS_I9XX(pI830) && i830PipeHasType(crtc, I830_OUTPUT_LVDS) &&
(INREG(LVDS) & LVDS_PORT_EN) != 0)
{
/* For LVDS, if the panel is on, just rely on its current settings for
* dual-channel. We haven't figured out how to reliably set up
* different single/dual channel state, if we even can.
*/
if ((INREG(LVDS) & LVDS_CLKB_POWER_MASK) == LVDS_CLKB_POWER_UP)
clock.p2 = limit->p2.p2_fast;
else
clock.p2 = limit->p2.p2_slow;
} else {
if (target < limit->p2.dot_limit)
clock.p2 = limit->p2.p2_slow;
else
clock.p2 = limit->p2.p2_fast;
}
memset (best_clock, 0, sizeof (*best_clock));
@ -659,23 +673,23 @@ i830_get_core_clock_speed(ScrnInfoPtr pScrn)
* or -1 if the panel fitter is not present or not in use
*/
static int
i830_panel_fitter_pipe (I830Ptr pI830)
i830_panel_fitter_pipe(I830Ptr pI830)
{
CARD32 pfit_control;
/* i830 doesn't have a panel fitter */
if (IS_I830(pI830))
return -1;
pfit_control = INREG(PFIT_CONTROL);
/* See if the panel fitter is in use */
if ((pfit_control & PFIT_ENABLE) == 0)
return -1;
/* 965 can place panel fitter on either pipe */
if (IS_I965G(pI830))
return (pfit_control >> 29) & 0x3;
return (pfit_control & PFIT_PIPE_MASK) >> PFIT_PIPE_SHIFT;
/* older chips can only use pipe 1 */
return 1;
@ -890,22 +904,37 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode,
usleep(150);
}
/* 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.
*/
if (is_lvds)
{
CARD32 lvds = INREG(LVDS);
CARD32 lvds = INREG(LVDS);
/* 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.
lvds |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP | LVDS_PIPEB_SELECT;
/* Set the B0-B3 data pairs corresponding to whether we're going to
* set the DPLLs for dual-channel mode or not.
*/
lvds |= LVDS_PORT_EN | LVDS_PIPEB_SELECT;
if (adjusted_mode->Clock >= I9XX_P2_LVDS_SLOW_LIMIT)
lvds |= LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP;
else
lvds &= ~(LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP);
/* It would be nice to set 24 vs 18-bit mode (LVDS_A3_POWER_UP)
* appropriately here, but we need to look more thoroughly into how
* panels behave in the two modes.
*/
/* Enable dithering if we're in 18-bit mode. */
if (IS_I965G(pI830))
{
if (pI830->panel_wants_dither)
if ((lvds & LVDS_A3_POWER_MASK) == LVDS_A3_POWER_UP)
lvds |= LVDS_DITHER_ENABLE;
else
lvds &= ~LVDS_DITHER_ENABLE;
}
OUTREG(LVDS, lvds);
POSTING_READ(LVDS);
}

View File

@ -1734,6 +1734,8 @@ SaveHWState(ScrnInfoPtr pScrn)
pI830->saveSWF[15] = INREG(SWF31);
pI830->saveSWF[16] = INREG(SWF32);
if (IS_MOBILE(pI830) && !IS_I830(pI830))
pI830->saveLVDS = INREG(LVDS);
pI830->savePFIT_CONTROL = INREG(PFIT_CONTROL);
for (i = 0; i < xf86_config->num_output; i++) {
@ -1776,6 +1778,9 @@ RestoreHWState(ScrnInfoPtr pScrn)
}
i830WaitForVblank(pScrn);
if (IS_MOBILE(pI830) && !IS_I830(pI830))
OUTREG(LVDS, pI830->saveLVDS);
if (!IS_I830(pI830) && !IS_845G(pI830))
OUTREG(PFIT_CONTROL, pI830->savePFIT_CONTROL);

View File

@ -98,7 +98,7 @@ i830_lvds_dpms (xf86OutputPtr output, int mode)
else
i830SetLVDSPanelPower(pScrn, FALSE);
/* XXX: We never power down the LVDS pair. */
/* XXX: We never power down the LVDS pairs. */
}
static void
@ -109,7 +109,6 @@ i830_lvds_save (xf86OutputPtr output)
pI830->savePP_ON = INREG(LVDSPP_ON);
pI830->savePP_OFF = INREG(LVDSPP_OFF);
pI830->saveLVDS = INREG(LVDS);
pI830->savePP_CONTROL = INREG(PP_CONTROL);
pI830->savePP_CYCLE = INREG(PP_CYCLE);
pI830->saveBLC_PWM_CTL = INREG(BLC_PWM_CTL);
@ -133,7 +132,6 @@ i830_lvds_restore(xf86OutputPtr output)
OUTREG(LVDSPP_ON, pI830->savePP_ON);
OUTREG(LVDSPP_OFF, pI830->savePP_OFF);
OUTREG(PP_CYCLE, pI830->savePP_CYCLE);
OUTREG(LVDS, pI830->saveLVDS);
OUTREG(PP_CONTROL, pI830->savePP_CONTROL);
if (pI830->savePP_CONTROL & POWER_TARGET_ON)
i830SetLVDSPanelPower(pScrn, TRUE);
@ -204,11 +202,6 @@ i830_lvds_mode_fixup(xf86OutputPtr output, DisplayModePtr mode,
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.
@ -223,6 +216,7 @@ i830_lvds_mode_set(xf86OutputPtr output, DisplayModePtr mode,
{
ScrnInfoPtr pScrn = output->scrn;
I830Ptr pI830 = I830PTR(pScrn);
I830CrtcPrivatePtr intel_crtc = output->crtc->driver_private;
CARD32 pfit_control;
/* The LVDS pin pair will already have been turned on in the
@ -237,9 +231,12 @@ i830_lvds_mode_set(xf86OutputPtr output, DisplayModePtr mode,
VERT_AUTO_SCALE | HORIZ_AUTO_SCALE |
VERT_INTERP_BILINEAR | HORIZ_INTERP_BILINEAR);
if (!IS_I965G(pI830))
if (!IS_I965G(pI830)) {
if (pI830->panel_wants_dither)
pfit_control |= PANEL_8TO6_DITHER_ENABLE;
} else {
pfit_control |= intel_crtc->pipe << PFIT_PIPE_SHIFT;
}
OUTREG(PFIT_CONTROL, pfit_control);
}