From 52f9028c84baea81230dc673b756552e8e90aecd Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 5 Apr 2007 11:21:06 +1000 Subject: Initial import of modesetting for intel driver in DRM --- linux-core/intel_display.c | 1087 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1087 insertions(+) create mode 100644 linux-core/intel_display.c (limited to 'linux-core/intel_display.c') diff --git a/linux-core/intel_display.c b/linux-core/intel_display.c new file mode 100644 index 00000000..495f4704 --- /dev/null +++ b/linux-core/intel_display.c @@ -0,0 +1,1087 @@ +#include +#include "drmP.h" +#include "drm.h" +#include "drm_crtc.h" +#include "intel_drv.h" +#include "i915_drm.h" +#include "i915_drv.h" + +bool intel_pipe_has_type (struct drm_crtc *crtc, int type); + +typedef struct { + /* given values */ + int n; + int m1, m2; + int p1, p2; + /* derived values */ + int dot; + int vco; + int m; + int p; +} intel_clock_t; + +typedef struct { + int min, max; +} intel_range_t; + +typedef struct { + int dot_limit; + int p2_slow, p2_fast; +} intel_p2_t; + +#define INTEL_P2_NUM 2 + +typedef struct { + intel_range_t dot, vco, n, m, m1, m2, p, p1; + intel_p2_t p2; +} intel_limit_t; + +#define I8XX_DOT_MIN 25000 +#define I8XX_DOT_MAX 350000 +#define I8XX_VCO_MIN 930000 +#define I8XX_VCO_MAX 1400000 +#define I8XX_N_MIN 3 +#define I8XX_N_MAX 16 +#define I8XX_M_MIN 96 +#define I8XX_M_MAX 140 +#define I8XX_M1_MIN 18 +#define I8XX_M1_MAX 26 +#define I8XX_M2_MIN 6 +#define I8XX_M2_MAX 16 +#define I8XX_P_MIN 4 +#define I8XX_P_MAX 128 +#define I8XX_P1_MIN 2 +#define I8XX_P1_MAX 33 +#define I8XX_P1_LVDS_MIN 1 +#define I8XX_P1_LVDS_MAX 6 +#define I8XX_P2_SLOW 4 +#define I8XX_P2_FAST 2 +#define I8XX_P2_LVDS_SLOW 14 +#define I8XX_P2_LVDS_FAST 14 /* No fast option */ +#define I8XX_P2_SLOW_LIMIT 165000 + +#define I9XX_DOT_MIN 20000 +#define I9XX_DOT_MAX 400000 +#define I9XX_VCO_MIN 1400000 +#define I9XX_VCO_MAX 2800000 +#define I9XX_N_MIN 3 +#define I9XX_N_MAX 8 +#define I9XX_M_MIN 70 +#define I9XX_M_MAX 120 +#define I9XX_M1_MIN 10 +#define I9XX_M1_MAX 20 +#define I9XX_M2_MIN 5 +#define I9XX_M2_MAX 9 +#define I9XX_P_SDVO_DAC_MIN 5 +#define I9XX_P_SDVO_DAC_MAX 80 +#define I9XX_P_LVDS_MIN 7 +#define I9XX_P_LVDS_MAX 98 +#define I9XX_P1_MIN 1 +#define I9XX_P1_MAX 8 +#define I9XX_P2_SDVO_DAC_SLOW 10 +#define I9XX_P2_SDVO_DAC_FAST 5 +#define I9XX_P2_SDVO_DAC_SLOW_LIMIT 200000 +#define I9XX_P2_LVDS_SLOW 14 +#define I9XX_P2_LVDS_FAST 7 +#define I9XX_P2_LVDS_SLOW_LIMIT 112000 + +#define INTEL_LIMIT_I8XX_DVO_DAC 0 +#define INTEL_LIMIT_I8XX_LVDS 1 +#define INTEL_LIMIT_I9XX_SDVO_DAC 2 +#define INTEL_LIMIT_I9XX_LVDS 3 + +static const intel_limit_t intel_limits[] = { + { /* INTEL_LIMIT_I8XX_DVO_DAC */ + .dot = { .min = I8XX_DOT_MIN, .max = I8XX_DOT_MAX }, + .vco = { .min = I8XX_VCO_MIN, .max = I8XX_VCO_MAX }, + .n = { .min = I8XX_N_MIN, .max = I8XX_N_MAX }, + .m = { .min = I8XX_M_MIN, .max = I8XX_M_MAX }, + .m1 = { .min = I8XX_M1_MIN, .max = I8XX_M1_MAX }, + .m2 = { .min = I8XX_M2_MIN, .max = I8XX_M2_MAX }, + .p = { .min = I8XX_P_MIN, .max = I8XX_P_MAX }, + .p1 = { .min = I8XX_P1_MIN, .max = I8XX_P1_MAX }, + .p2 = { .dot_limit = I8XX_P2_SLOW_LIMIT, + .p2_slow = I8XX_P2_SLOW, .p2_fast = I8XX_P2_FAST }, + }, + { /* INTEL_LIMIT_I8XX_LVDS */ + .dot = { .min = I8XX_DOT_MIN, .max = I8XX_DOT_MAX }, + .vco = { .min = I8XX_VCO_MIN, .max = I8XX_VCO_MAX }, + .n = { .min = I8XX_N_MIN, .max = I8XX_N_MAX }, + .m = { .min = I8XX_M_MIN, .max = I8XX_M_MAX }, + .m1 = { .min = I8XX_M1_MIN, .max = I8XX_M1_MAX }, + .m2 = { .min = I8XX_M2_MIN, .max = I8XX_M2_MAX }, + .p = { .min = I8XX_P_MIN, .max = I8XX_P_MAX }, + .p1 = { .min = I8XX_P1_LVDS_MIN, .max = I8XX_P1_LVDS_MAX }, + .p2 = { .dot_limit = I8XX_P2_SLOW_LIMIT, + .p2_slow = I8XX_P2_LVDS_SLOW, .p2_fast = I8XX_P2_LVDS_FAST }, + }, + { /* INTEL_LIMIT_I9XX_SDVO_DAC */ + .dot = { .min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX }, + .vco = { .min = I9XX_VCO_MIN, .max = I9XX_VCO_MAX }, + .n = { .min = I9XX_N_MIN, .max = I9XX_N_MAX }, + .m = { .min = I9XX_M_MIN, .max = I9XX_M_MAX }, + .m1 = { .min = I9XX_M1_MIN, .max = I9XX_M1_MAX }, + .m2 = { .min = I9XX_M2_MIN, .max = I9XX_M2_MAX }, + .p = { .min = I9XX_P_SDVO_DAC_MIN, .max = I9XX_P_SDVO_DAC_MAX }, + .p1 = { .min = I9XX_P1_MIN, .max = I9XX_P1_MAX }, + .p2 = { .dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT, + .p2_slow = I9XX_P2_SDVO_DAC_SLOW, .p2_fast = I9XX_P2_SDVO_DAC_FAST }, + }, + { /* INTEL_LIMIT_I9XX_LVDS */ + .dot = { .min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX }, + .vco = { .min = I9XX_VCO_MIN, .max = I9XX_VCO_MAX }, + .n = { .min = I9XX_N_MIN, .max = I9XX_N_MAX }, + .m = { .min = I9XX_M_MIN, .max = I9XX_M_MAX }, + .m1 = { .min = I9XX_M1_MIN, .max = I9XX_M1_MAX }, + .m2 = { .min = I9XX_M2_MIN, .max = I9XX_M2_MAX }, + .p = { .min = I9XX_P_LVDS_MIN, .max = I9XX_P_LVDS_MAX }, + .p1 = { .min = I9XX_P1_MIN, .max = I9XX_P1_MAX }, + /* The single-channel range is 25-112Mhz, and dual-channel + * is 80-224Mhz. Prefer single channel as much as possible. + */ + .p2 = { .dot_limit = I9XX_P2_LVDS_SLOW_LIMIT, + .p2_slow = I9XX_P2_LVDS_SLOW, .p2_fast = I9XX_P2_LVDS_FAST }, + }, +}; + +static const intel_limit_t *intel_limit (struct drm_crtc *crtc) +{ + drm_device_t *dev = crtc->dev; + const intel_limit_t *limit; + + if (IS_I9XX(dev)) { + if (intel_pipe_has_type (crtc, INTEL_OUTPUT_LVDS)) + limit = &intel_limits[INTEL_LIMIT_I9XX_LVDS]; + else + limit = &intel_limits[INTEL_LIMIT_I9XX_SDVO_DAC]; + } else { + if (intel_pipe_has_type (crtc, INTEL_OUTPUT_LVDS)) + limit = &intel_limits[INTEL_LIMIT_I8XX_LVDS]; + else + limit = &intel_limits[INTEL_LIMIT_I8XX_DVO_DAC]; + } + return limit; +} + +/** Derive the pixel clock for the given refclk and divisors for 8xx chips. */ + +static void i8xx_clock(int refclk, intel_clock_t *clock) +{ + clock->m = 5 * (clock->m1 + 2) + (clock->m2 + 2); + clock->p = clock->p1 * clock->p2; + clock->vco = refclk * clock->m / (clock->n + 2); + clock->dot = clock->vco / clock->p; +} + +/** Derive the pixel clock for the given refclk and divisors for 9xx chips. */ + +static void i9xx_clock(int refclk, intel_clock_t *clock) +{ + clock->m = 5 * (clock->m1 + 2) + (clock->m2 + 2); + clock->p = clock->p1 * clock->p2; + clock->vco = refclk * clock->m / (clock->n + 2); + clock->dot = clock->vco / clock->p; +} + +static void intel_clock(struct drm_device *dev, int refclk, + intel_clock_t *clock) +{ + if (IS_I9XX(dev)) + return i9xx_clock (refclk, clock); + else + return i8xx_clock (refclk, clock); +} + +/** + * Returns whether any output on the specified pipe is of the specified type + */ +bool intel_pipe_has_type (struct drm_crtc *crtc, int type) +{ + struct drm_device *dev = crtc->dev; + struct drm_crtc_config *crtc_config = &dev->crtc_config; + struct drm_output *l_entry; + + list_for_each_entry(l_entry, &crtc_config->output_list, head) { + if (l_entry->crtc == crtc) { + struct intel_output *intel_output = l_entry->driver_private; + if (intel_output->type == type) + return true; + } + } + return false; +} + +#define INTELPllInvalid(s) { /* ErrorF (s) */; return false; } +/** + * Returns whether the given set of divisors are valid for a given refclk with + * the given outputs. + */ + +static bool intel_PLL_is_valid(struct drm_crtc *crtc, intel_clock_t *clock) +{ + const intel_limit_t *limit = intel_limit (crtc); + + if (clock->p1 < limit->p1.min || limit->p1.max < clock->p1) + INTELPllInvalid ("p1 out of range\n"); + if (clock->p < limit->p.min || limit->p.max < clock->p) + INTELPllInvalid ("p out of range\n"); + if (clock->m2 < limit->m2.min || limit->m2.max < clock->m2) + INTELPllInvalid ("m2 out of range\n"); + if (clock->m1 < limit->m1.min || limit->m1.max < clock->m1) + INTELPllInvalid ("m1 out of range\n"); + if (clock->m1 <= clock->m2) + INTELPllInvalid ("m1 <= m2\n"); + if (clock->m < limit->m.min || limit->m.max < clock->m) + INTELPllInvalid ("m out of range\n"); + if (clock->n < limit->n.min || limit->n.max < clock->n) + INTELPllInvalid ("n out of range\n"); + if (clock->vco < limit->vco.min || limit->vco.max < clock->vco) + INTELPllInvalid ("vco out of range\n"); + /* XXX: We may need to be checking "Dot clock" depending on the multiplier, + * output, etc., rather than just a single range. + */ + if (clock->dot < limit->dot.min || limit->dot.max < clock->dot) + INTELPllInvalid ("dot out of range\n"); + + return true; +} + +/** + * 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 intel_find_best_PLL(struct drm_crtc *crtc, int target, + int refclk, intel_clock_t *best_clock) +{ + drm_device_t *dev = crtc->dev; + drm_i915_private_t *dev_priv = dev->dev_private; + intel_clock_t clock; + const intel_limit_t *limit = intel_limit (crtc); + int err = target; + + if (IS_I9XX(dev)& intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) && + (I915_READ(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 ((I915_READ(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)); + + for (clock.m1 = limit->m1.min; clock.m1 <= limit->m1.max; clock.m1++) + { + for (clock.m2 = limit->m2.min; clock.m2 < clock.m1 && clock.m2 <= limit->m2.max; clock.m2++) + { + for (clock.n = limit->n.min; clock.n <= limit->n.max; clock.n++) + { + for (clock.p1 = limit->p1.min; clock.p1 <= limit->p1.max; clock.p1++) + { + int this_err; + + intel_clock (dev, refclk, &clock); + + if (!intel_PLL_is_valid(crtc, &clock)) + continue; + + this_err = abs(clock.dot - target); + if (this_err < err) { + *best_clock = clock; + err = this_err; + } + } + } + } + } + return (err != target); +} + +void +intel_wait_for_vblank(drm_device_t *dev) +{ + /* Wait for 20ms, i.e. one cycle at 50hz. */ + udelay(20000); +} + +void +intel_pipe_set_base(struct drm_crtc *crtc, int x, int y) +{ + drm_device_t *dev = crtc->dev; + drm_i915_private_t *dev_priv = dev->dev_private; + struct intel_crtc *intel_crtc = crtc->driver_private; + int pipe = intel_crtc->pipe; + unsigned long Start, Offset; + int dspbase = (pipe == 0 ? DSPABASE : DSPBBASE); + int dspsurf = (pipe == 0 ? DSPASURF : DSPBSURF); + + Start = crtc->fb->offset; + Offset = ((y * crtc->fb->width + x) * (crtc->fb->bits_per_pixel / 8)); + + if (IS_I965G(dev)) { + I915_WRITE(dspbase, Offset); + I915_READ(dspbase); + I915_WRITE(dspsurf, Start); + I915_READ(dspsurf); + } else { + I915_WRITE(dspbase, Start + Offset); + I915_READ(dspbase); + } + + +#if 0 + drmI830Sarea *sPriv = (drmI830Sarea *) DRIGetSAREAPrivate(pScrn->pScreen); + + if (!sPriv) + return; + + switch (pipe) { + case 0: + sPriv->pipeA_x = x; + sPriv->pipeA_y = y; + break; + case 1: + sPriv->pipeB_x = x; + sPriv->pipeB_y = y; + break; + default: + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Can't update pipe %d in SAREA\n", pipe); + break; + } +#endif +} + +/** + * Sets the power management mode of the pipe and plane. + * + * This code should probably grow support for turning the cursor off and back + * on appropriately at the same time as we're turning the pipe off/on. + */ +static void intel_crtc_dpms(struct drm_crtc *crtc, int mode) +{ + drm_device_t *dev = crtc->dev; + drm_i915_private_t *dev_priv = dev->dev_private; + struct intel_crtc *intel_crtc = crtc->driver_private; + int pipe = intel_crtc->pipe; + int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B; + int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; + int dspbase_reg = (pipe == 0) ? DSPABASE : DSPBBASE; + int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; + u32 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 = I915_READ(dpll_reg); + if ((temp & DPLL_VCO_ENABLE) == 0) + { + I915_WRITE(dpll_reg, temp); + I915_READ(dpll_reg); + /* Wait for the clocks to stabilize. */ + udelay(150); + I915_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE); + I915_READ(dpll_reg); + /* Wait for the clocks to stabilize. */ + udelay(150); + I915_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE); + I915_READ(dpll_reg); + /* Wait for the clocks to stabilize. */ + udelay(150); + } + + /* Enable the pipe */ + temp = I915_READ(pipeconf_reg); + if ((temp & PIPEACONF_ENABLE) == 0) + I915_WRITE(pipeconf_reg, temp | PIPEACONF_ENABLE); + + /* Enable the plane */ + temp = I915_READ(dspcntr_reg); + if ((temp & DISPLAY_PLANE_ENABLE) == 0) + { + I915_WRITE(dspcntr_reg, temp | DISPLAY_PLANE_ENABLE); + /* Flush the plane changes */ + I915_WRITE(dspbase_reg, I915_READ(dspbase_reg)); + } + + intel_crtc_load_lut(crtc); + + /* Give the overlay scaler a chance to enable if it's on this pipe */ + //intel_crtc_dpms_video(crtc, TRUE); TODO + break; + case DPMSModeOff: + /* Give the overlay scaler a chance to disable if it's on this pipe */ + //intel_crtc_dpms_video(crtc, FALSE); TODO + + /* Disable the VGA plane that we never use */ + I915_WRITE(VGACNTRL, VGA_DISP_DISABLE); + + /* Disable display plane */ + temp = I915_READ(dspcntr_reg); + if ((temp & DISPLAY_PLANE_ENABLE) != 0) + { + I915_WRITE(dspcntr_reg, temp & ~DISPLAY_PLANE_ENABLE); + /* Flush the plane changes */ + I915_WRITE(dspbase_reg, I915_READ(dspbase_reg)); + I915_READ(dspbase_reg); + } + + if (!IS_I9XX(dev)) { + /* Wait for vblank for the disable to take effect */ + intel_wait_for_vblank(dev); + } + + /* Next, disable display pipes */ + temp = I915_READ(pipeconf_reg); + if ((temp & PIPEACONF_ENABLE) != 0) { + I915_WRITE(pipeconf_reg, temp & ~PIPEACONF_ENABLE); + I915_READ(pipeconf_reg); + } + + /* Wait for vblank for the disable to take effect. */ + intel_wait_for_vblank(dev); + + temp = I915_READ(dpll_reg); + if ((temp & DPLL_VCO_ENABLE) != 0) { + I915_WRITE(dpll_reg, temp & ~DPLL_VCO_ENABLE); + I915_READ(dpll_reg); + } + + /* Wait for the clocks to turn off. */ + udelay(150); + break; + } + +#if 0 //TODO + if (pI830->directRenderingEnabled) { + drmI830Sarea *sPriv = (drmI830Sarea *) DRIGetSAREAPrivate(pScrn->pScreen); + Bool enabled = crtc->enabled && mode != DPMSModeOff; + + if (!sPriv) + return; + + switch (pipe) { + case 0: + sPriv->pipeA_w = enabled ? crtc->mode.HDisplay : 0; + sPriv->pipeA_h = enabled ? crtc->mode.VDisplay : 0; + break; + case 1: + sPriv->pipeB_w = enabled ? crtc->mode.HDisplay : 0; + sPriv->pipeB_h = enabled ? crtc->mode.VDisplay : 0; + break; + default: + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Can't update pipe %d in SAREA\n", pipe); + break; + } + } +#endif +} + +static bool intel_crtc_lock(struct drm_crtc *crtc) +{ + /* Sync the engine before mode switch */ +// i830WaitSync(crtc->scrn); + +#if 0 // TODO def XF86DRI + return I830DRILock(crtc->scrn); +#else + return FALSE; +#endif +} + +static void intel_crtc_unlock (struct drm_crtc *crtc) +{ +#if 0 // TODO def XF86DRI + I830DRIUnlock (crtc->scrn); +#endif +} + +static void intel_crtc_prepare (struct drm_crtc *crtc) +{ + crtc->funcs->dpms (crtc, DPMSModeOff); +} + +static void intel_crtc_commit (struct drm_crtc *crtc) +{ + crtc->funcs->dpms (crtc, DPMSModeOn); +// if (crtc->scrn->pScreen != NULL) +// xf86_reload_cursors (crtc->scrn->pScreen); +} + +void intel_output_prepare (struct drm_output *output) +{ + output->funcs->dpms (output, DPMSModeOff); +} + +void intel_output_commit (struct drm_output *output) +{ + output->funcs->dpms (output, DPMSModeOn); +} + +static bool intel_crtc_mode_fixup(struct drm_crtc *crtc, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + return true; +} + + +/** Returns the core display clock speed for i830 - i945 */ +static int intel_get_core_clock_speed(drm_device_t *dev) +{ + + /* Core clock values taken from the published datasheets. + * The 830 may go up to 166 Mhz, which we should check. + */ + if (IS_I945G(dev)) + return 400000; + else if (IS_I915G(dev)) + return 333000; + else if (IS_I945GM(dev) || IS_845G(dev)) + return 200000; + else if (IS_I915GM(dev)) { +#if 0 + u16 gcfgc = pciReadWord(dev->PciTag, I915_GCFGC); + + if (gcfgc & I915_LOW_FREQUENCY_ENABLE) + return 133000; + else { + switch (gcfgc & I915_DISPLAY_CLOCK_MASK) { + case I915_DISPLAY_CLOCK_333_MHZ: + return 333000; + default: + case I915_DISPLAY_CLOCK_190_200_MHZ: + return 190000; + } + } +#endif + } else if (IS_I865G(dev)) + return 266000; + else if (IS_I855(dev)) { +#if 0 + PCITAG bridge = pciTag(0, 0, 0); /* This is always the host bridge */ + u16 hpllcc = pciReadWord(bridge, I855_HPLLCC); + +#endif + u16 hpllcc = 0; + /* Assume that the hardware is in the high speed state. This + * should be the default. + */ + switch (hpllcc & I855_CLOCK_CONTROL_MASK) { + case I855_CLOCK_133_200: + case I855_CLOCK_100_200: + return 200000; + case I855_CLOCK_166_250: + return 250000; + case I855_CLOCK_100_133: + return 133000; + } + } else /* 852, 830 */ + return 133000; + + return 0; /* Silence gcc warning */ +} + + +/** + * Return the pipe currently connected to the panel fitter, + * or -1 if the panel fitter is not present or not in use + */ +static int intel_panel_fitter_pipe (drm_device_t *dev) +{ + drm_i915_private_t *dev_priv = dev->dev_private; + u32 pfit_control; + + /* i830 doesn't have a panel fitter */ + if (IS_I830(dev)) + return -1; + + pfit_control = I915_READ(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(dev)) + return (pfit_control >> 29) & 0x3; + + /* older chips can only use pipe 1 */ + return 1; +} + +static void intel_crtc_mode_set(struct drm_crtc *crtc, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode, + int x, int y) +{ + drm_device_t *dev = crtc->dev; + drm_i915_private_t *dev_priv = dev->dev_private; + struct intel_crtc *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; + int vtot_reg = (pipe == 0) ? VTOTAL_A : VTOTAL_B; + int vblank_reg = (pipe == 0) ? VBLANK_A : VBLANK_B; + int vsync_reg = (pipe == 0) ? VSYNC_A : VSYNC_B; + int dspsize_reg = (pipe == 0) ? DSPASIZE : DSPBSIZE; + int dspstride_reg = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE; + int dsppos_reg = (pipe == 0) ? DSPAPOS : DSPBPOS; + int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC; + int refclk; + intel_clock_t clock; + u32 dpll = 0, fp = 0, dspcntr, pipeconf; + bool ok, is_sdvo = false, is_dvo = false; + bool is_crt = false, is_lvds = false, is_tv = false; + struct drm_crtc_config *crtc_config = &dev->crtc_config; + struct drm_output *output; + + list_for_each_entry(output, &crtc_config->output_list, head) { + struct intel_output *intel_output = output->driver_private; + + if (output->crtc != crtc) + continue; + + switch (intel_output->type) { + case INTEL_OUTPUT_LVDS: + is_lvds = TRUE; + break; + case INTEL_OUTPUT_SDVO: + is_sdvo = TRUE; + break; + case INTEL_OUTPUT_DVO: + is_dvo = TRUE; + break; + case INTEL_OUTPUT_TVOUT: + is_tv = TRUE; + break; + case INTEL_OUTPUT_ANALOG: + is_crt = TRUE; + break; + } + } + + if (IS_I9XX(dev)) { + refclk = 96000; + } else { + refclk = 48000; + } + + ok = intel_find_best_PLL(crtc, adjusted_mode->clock, refclk, &clock); + if (!ok) { + DRM_ERROR("Couldn't find PLL settings for mode!\n"); + return; + } + + fp = clock.n << 16 | clock.m1 << 8 | clock.m2; + + dpll = DPLL_VGA_MODE_DIS; + if (IS_I9XX(dev)) { + if (is_lvds) + dpll |= DPLLB_MODE_LVDS; + else + dpll |= DPLLB_MODE_DAC_SERIAL; + if (is_sdvo) + { + dpll |= DPLL_DVO_HIGH_SPEED; + if (IS_I945G(dev) || IS_I945GM(dev)) + { + int sdvo_pixel_multiply = adjusted_mode->clock / mode->clock; + dpll |= (sdvo_pixel_multiply - 1) << SDVO_MULTIPLIER_SHIFT_HIRES; + } + } + + /* compute bitmask from p1 value */ + dpll |= (1 << (clock.p1 - 1)) << 16; + switch (clock.p2) { + case 5: + dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_5; + break; + case 7: + dpll |= DPLLB_LVDS_P2_CLOCK_DIV_7; + break; + case 10: + dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_10; + break; + case 14: + dpll |= DPLLB_LVDS_P2_CLOCK_DIV_14; + break; + } + if (IS_I965G(dev)) + dpll |= (6 << PLL_LOAD_PULSE_PHASE_SHIFT); + } else { + if (is_lvds) { + dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT; + } else { + if (clock.p1 == 2) + dpll |= PLL_P1_DIVIDE_BY_TWO; + else + dpll |= (clock.p1 - 2) << DPLL_FPA01_P1_POST_DIV_SHIFT; + if (clock.p2 == 4) + dpll |= PLL_P2_DIVIDE_BY_4; + } + } + + if (is_tv) + { + /* XXX: just matching BIOS for now */ +/* dpll |= PLL_REF_INPUT_TVCLKINBC; */ + dpll |= 3; + } +#if 0 + else if (is_lvds) + dpll |= PLLB_REF_INPUT_SPREADSPECTRUMIN; +#endif + else + dpll |= PLL_REF_INPUT_DREFCLK; + + /* Set up the display plane register */ + dspcntr = DISPPLANE_GAMMA_ENABLE; + + switch (crtc->fb->bits_per_pixel) { + case 8: + dspcntr |= DISPPLANE_8BPP; + break; + case 16: + if (crtc->fb->depth == 15) + dspcntr |= DISPPLANE_15_16BPP; + else + dspcntr |= DISPPLANE_16BPP; + break; + case 32: + dspcntr |= DISPPLANE_32BPP_NO_ALPHA; + break; + default: + DRM_ERROR("Unknown color depth\n"); + return; + } + + + if (pipe == 0) + dspcntr |= DISPPLANE_SEL_PIPE_A; + else + dspcntr |= DISPPLANE_SEL_PIPE_B; + + pipeconf = I915_READ(pipeconf_reg); + if (pipe == 0 && !IS_I965G(dev)) + { + /* Enable pixel doubling when the dot clock is > 90% of the (display) + * core speed. + * + * XXX: No double-wide on 915GM pipe B. Is that the only reason for the + * pipe == 0 check? + */ + if (mode->clock > intel_get_core_clock_speed(dev) * 9 / 10) + pipeconf |= PIPEACONF_DOUBLE_WIDE; + else + pipeconf &= ~PIPEACONF_DOUBLE_WIDE; + } + + dspcntr |= DISPLAY_PLANE_ENABLE; + pipeconf |= PIPEACONF_ENABLE; + dpll |= DPLL_VCO_ENABLE; + + + /* Disable the panel fitter if it was on our pipe */ + if (intel_panel_fitter_pipe(dev) == pipe) + I915_WRITE(PFIT_CONTROL, 0); + +#if 0 + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B'); + xf86PrintModeline(pScrn->scrnIndex, mode); + if (!xf86ModesEqual(mode, adjusted_mode)) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Adjusted mode for pipe %c:\n", pipe == 0 ? 'A' : 'B'); + xf86PrintModeline(pScrn->scrnIndex, mode); + } + i830PrintPll("chosen", &clock); +#endif + + if (dpll & DPLL_VCO_ENABLE) + { + I915_WRITE(fp_reg, fp); + I915_WRITE(dpll_reg, dpll & ~DPLL_VCO_ENABLE); + I915_READ(dpll_reg); + udelay(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) + { + u32 lvds = I915_READ(LVDS); + + 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. + */ + if (clock.p2 == 7) + 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. + */ + + I915_WRITE(LVDS, lvds); + I915_READ(LVDS); + } + + I915_WRITE(fp_reg, fp); + I915_WRITE(dpll_reg, dpll); + I915_READ(dpll_reg); + /* Wait for the clocks to stabilize. */ + udelay(150); + + if (IS_I965G(dev)) { + int sdvo_pixel_multiply = adjusted_mode->clock / mode->clock; + I915_WRITE(dpll_md_reg, (0 << DPLL_MD_UDI_DIVIDER_SHIFT) | + ((sdvo_pixel_multiply - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT)); + } else { + /* write it again -- the BIOS does, after all */ + I915_WRITE(dpll_reg, dpll); + } + I915_READ(dpll_reg); + /* Wait for the clocks to stabilize. */ + udelay(150); + + I915_WRITE(htot_reg, (adjusted_mode->crtc_hdisplay - 1) | + ((adjusted_mode->crtc_htotal - 1) << 16)); + I915_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - 1) | + ((adjusted_mode->crtc_hblank_end - 1) << 16)); + I915_WRITE(hsync_reg, (adjusted_mode->crtc_hsync_start - 1) | + ((adjusted_mode->crtc_hsync_end - 1) << 16)); + I915_WRITE(vtot_reg, (adjusted_mode->crtc_vdisplay - 1) | + ((adjusted_mode->crtc_vtotal - 1) << 16)); + I915_WRITE(vblank_reg, (adjusted_mode->crtc_vblank_start - 1) | + ((adjusted_mode->crtc_vblank_end - 1) << 16)); + I915_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start - 1) | + ((adjusted_mode->crtc_vsync_end - 1) << 16)); + I915_WRITE(dspstride_reg, crtc->fb->pitch * (crtc->fb->bits_per_pixel / 8)); + /* pipesrc and dspsize control the size that is scaled from, which should + * always be the user's requested size. + */ + I915_WRITE(dspsize_reg, ((mode->vdisplay - 1) << 16) | (mode->hdisplay - 1)); + I915_WRITE(dsppos_reg, 0); + I915_WRITE(pipesrc_reg, ((mode->hdisplay - 1) << 16) | (mode->vdisplay - 1)); + I915_WRITE(pipeconf_reg, pipeconf); + I915_READ(pipeconf_reg); + + intel_wait_for_vblank(dev); + + I915_WRITE(dspcntr_reg, dspcntr); + + /* Flush the plane changes */ + intel_pipe_set_base(crtc, x, y); + +#ifdef XF86DRI // TODO +// I830DRISetVBlankInterrupt (pScrn, TRUE); +#endif + + intel_wait_for_vblank(dev); + + +} + +/** Loads the palette/gamma unit for the CRTC with the prepared values */ +void intel_crtc_load_lut(struct drm_crtc *crtc) +{ + drm_device_t *dev = crtc->dev; + drm_i915_private_t *dev_priv = dev->dev_private; + struct intel_crtc *intel_crtc = crtc->driver_private; + int palreg = (intel_crtc->pipe == 0) ? PALETTE_A : PALETTE_B; + int i; + + /* The clocks have to be on to load the palette. */ + if (!crtc->enabled) + return; + + for (i = 0; i < 256; i++) { + I915_WRITE(palreg + 4 * i, + (intel_crtc->lut_r[i] << 16) | + (intel_crtc->lut_g[i] << 8) | + intel_crtc->lut_b[i]); + } +} + +/** Sets the color ramps on behalf of RandR */ +static void intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green, + u16 *blue, int size) +{ + struct intel_crtc *intel_crtc = crtc->driver_private; + int i; + + for (i = 0; i < 256; i++) { + intel_crtc->lut_r[i] = red[i] >> 8; + intel_crtc->lut_g[i] = green[i] >> 8; + intel_crtc->lut_b[i] = blue[i] >> 8; + } + + intel_crtc_load_lut(crtc); +} + +struct drm_display_mode *intel_crtc_mode_get(drm_device_t *dev, + struct drm_crtc *crtc) +{ + return NULL; +} + +static const struct drm_crtc_funcs intel_crtc_funcs = { + .dpms = intel_crtc_dpms, + .lock = intel_crtc_lock, + .unlock = intel_crtc_unlock, + .mode_fixup = intel_crtc_mode_fixup, + .mode_set = intel_crtc_mode_set, + .gamma_set = intel_crtc_gamma_set, + .prepare = intel_crtc_prepare, + .commit = intel_crtc_commit, +}; + + +void intel_crtc_init(drm_device_t *dev, int pipe) +{ + struct drm_crtc *crtc; + struct intel_crtc *intel_crtc; + int i; + + crtc = drm_crtc_create(dev, &intel_crtc_funcs); + if (crtc == NULL) + return; + + intel_crtc = kmalloc(sizeof(struct intel_crtc), GFP_KERNEL); + if (intel_crtc == NULL) { + kfree(crtc); + return; + } + + intel_crtc->pipe = pipe; + for (i = 0; i < 256; i++) { + intel_crtc->lut_r[i] = i; + intel_crtc->lut_g[i] = i; + intel_crtc->lut_b[i] = i; + } + + crtc->driver_private = intel_crtc; +} + +int intel_output_clones (drm_device_t *dev, int type_mask) +{ + int index_mask = 0; + struct drm_output *output; + int entry = 0; + + list_for_each_entry(output, &dev->crtc_config.output_list, head) { + struct intel_output *intel_output = output->driver_private; + if (type_mask & (1 << intel_output->type)) + index_mask |= (1 << entry); + entry++; + } + return index_mask; +} + + +static void intel_setup_outputs(drm_device_t *dev) +{ + struct drm_output *output; + + intel_crt_init(dev); + + /* Set up integrated LVDS */ + if (IS_MOBILE(dev) && !IS_I830(dev)) + intel_lvds_init(dev); + + if (IS_I9XX(dev)) { + intel_sdvo_init(dev, SDVOB); + intel_sdvo_init(dev, SDVOC); + } + + list_for_each_entry(output, &dev->crtc_config.output_list, head) { + struct intel_output *intel_output = output->driver_private; + int crtc_mask = 0, clone_mask = 0; + + /* valid crtcs */ + switch(intel_output->type) { + case INTEL_OUTPUT_DVO: + case INTEL_OUTPUT_SDVO: + crtc_mask = ((1 << 0)| + (1 << 1)); + clone_mask = ((1 << INTEL_OUTPUT_ANALOG) | + (1 << INTEL_OUTPUT_DVO) | + (1 << INTEL_OUTPUT_SDVO)); + break; + case INTEL_OUTPUT_ANALOG: + crtc_mask = ((1 << 0)); + clone_mask = ((1 << INTEL_OUTPUT_ANALOG) | + (1 << INTEL_OUTPUT_DVO) | + (1 << INTEL_OUTPUT_SDVO)); + break; + case INTEL_OUTPUT_LVDS: + crtc_mask = (1 << 1); + clone_mask = (1 << INTEL_OUTPUT_LVDS); + break; + case INTEL_OUTPUT_TVOUT: + crtc_mask = ((1 << 0) | + (1 << 1)); + clone_mask = (1 << INTEL_OUTPUT_TVOUT); + break; + } + output->possible_crtcs = crtc_mask; + output->possible_clones = intel_output_clones(dev, clone_mask); + } +} + +void intel_modeset_init(drm_device_t *dev) +{ + int num_pipe; + int i; + + drm_crtc_config_init(dev); + + + if (IS_MOBILE(dev) || IS_I9XX(dev)) + num_pipe = 2; + else + num_pipe = 1; + DRM_DEBUG("%d display pipe%s available.\n", + num_pipe, num_pipe > 1 ? "s" : ""); + + for (i = 0; i < num_pipe; i++) { + intel_crtc_init(dev, i); + } + + intel_setup_outputs(dev); + + drm_initial_config(dev, false); +} + +void intel_modeset_cleanup(drm_device_t *dev) +{ + drm_crtc_config_cleanup(dev); +} -- cgit v1.2.3 From 6f3534a13abb0c8afb157511d0871dbc35bc403d Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Thu, 5 Apr 2007 09:21:31 -0700 Subject: Add copyrights before I forget --- linux-core/intel_display.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'linux-core/intel_display.c') diff --git a/linux-core/intel_display.c b/linux-core/intel_display.c index 495f4704..67d7c7d5 100644 --- a/linux-core/intel_display.c +++ b/linux-core/intel_display.c @@ -1,3 +1,7 @@ +/* + * Copyright (c) 2006-2007 Intel Corporation + * Eric Anholt + */ #include #include "drmP.h" #include "drm.h" -- cgit v1.2.3 From 1c9ba24c2f37ca78965f8aa57ece02ef5bdb9b06 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 5 Apr 2007 11:34:11 -0700 Subject: Add required permission notices for code copied from X.Org source. --- linux-core/intel_display.c | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) (limited to 'linux-core/intel_display.c') diff --git a/linux-core/intel_display.c b/linux-core/intel_display.c index 67d7c7d5..58d66987 100644 --- a/linux-core/intel_display.c +++ b/linux-core/intel_display.c @@ -1,7 +1,29 @@ /* - * Copyright (c) 2006-2007 Intel Corporation - * Eric Anholt + * Copyright © 2006-2007 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Eric Anholt */ + #include #include "drmP.h" #include "drm.h" -- cgit v1.2.3 From ed0ebd9d3da2e5c4e8053b6e7a7d2898b184f857 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 10 Apr 2007 18:56:02 +1000 Subject: make crtc_config be named mode_config X.org calls this crtc_config but this is a bad name and will confuse ppl later (and me now :-) --- linux-core/intel_display.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'linux-core/intel_display.c') diff --git a/linux-core/intel_display.c b/linux-core/intel_display.c index 58d66987..e8d15ce5 100644 --- a/linux-core/intel_display.c +++ b/linux-core/intel_display.c @@ -224,10 +224,10 @@ static void intel_clock(struct drm_device *dev, int refclk, bool intel_pipe_has_type (struct drm_crtc *crtc, int type) { struct drm_device *dev = crtc->dev; - struct drm_crtc_config *crtc_config = &dev->crtc_config; + struct drm_mode_config *mode_config = &dev->mode_config; struct drm_output *l_entry; - list_for_each_entry(l_entry, &crtc_config->output_list, head) { + list_for_each_entry(l_entry, &mode_config->output_list, head) { if (l_entry->crtc == crtc) { struct intel_output *intel_output = l_entry->driver_private; if (intel_output->type == type) @@ -681,10 +681,10 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc, u32 dpll = 0, fp = 0, dspcntr, pipeconf; bool ok, is_sdvo = false, is_dvo = false; bool is_crt = false, is_lvds = false, is_tv = false; - struct drm_crtc_config *crtc_config = &dev->crtc_config; + struct drm_mode_config *mode_config = &dev->mode_config; struct drm_output *output; - list_for_each_entry(output, &crtc_config->output_list, head) { + list_for_each_entry(output, &mode_config->output_list, head) { struct intel_output *intel_output = output->driver_private; if (output->crtc != crtc) @@ -1023,7 +1023,7 @@ int intel_output_clones (drm_device_t *dev, int type_mask) struct drm_output *output; int entry = 0; - list_for_each_entry(output, &dev->crtc_config.output_list, head) { + list_for_each_entry(output, &dev->mode_config.output_list, head) { struct intel_output *intel_output = output->driver_private; if (type_mask & (1 << intel_output->type)) index_mask |= (1 << entry); @@ -1048,7 +1048,7 @@ static void intel_setup_outputs(drm_device_t *dev) intel_sdvo_init(dev, SDVOC); } - list_for_each_entry(output, &dev->crtc_config.output_list, head) { + list_for_each_entry(output, &dev->mode_config.output_list, head) { struct intel_output *intel_output = output->driver_private; int crtc_mask = 0, clone_mask = 0; @@ -1088,7 +1088,7 @@ void intel_modeset_init(drm_device_t *dev) int num_pipe; int i; - drm_crtc_config_init(dev); + drm_mode_config_init(dev); if (IS_MOBILE(dev) || IS_I9XX(dev)) @@ -1109,5 +1109,5 @@ void intel_modeset_init(drm_device_t *dev) void intel_modeset_cleanup(drm_device_t *dev) { - drm_crtc_config_cleanup(dev); + drm_mode_config_cleanup(dev); } -- cgit v1.2.3 From eb9bdc27879d1aa307b234bbdb0f81494dcf7095 Mon Sep 17 00:00:00 2001 From: David Airlie Date: Tue, 10 Apr 2007 11:51:31 +1000 Subject: mode: fixup problems with framebuffer add function --- linux-core/intel_display.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'linux-core/intel_display.c') diff --git a/linux-core/intel_display.c b/linux-core/intel_display.c index e8d15ce5..fce0fafd 100644 --- a/linux-core/intel_display.c +++ b/linux-core/intel_display.c @@ -1090,6 +1090,11 @@ void intel_modeset_init(drm_device_t *dev) drm_mode_config_init(dev); + dev->mode_config.min_width = 0; + dev->mode_config.min_height = 0; + + dev->mode_config.max_width = 4096; + dev->mode_config.max_height = 4096; if (IS_MOBILE(dev) || IS_I9XX(dev)) num_pipe = 2; @@ -1104,7 +1109,7 @@ void intel_modeset_init(drm_device_t *dev) intel_setup_outputs(dev); - drm_initial_config(dev, false); + //drm_initial_config(dev, false); } void intel_modeset_cleanup(drm_device_t *dev) -- cgit v1.2.3 From 40bd6dcd86d554ca426deccd4fbada693c4be8a6 Mon Sep 17 00:00:00 2001 From: David Airlie Date: Tue, 10 Apr 2007 15:20:50 +1000 Subject: set the base address of the CRTC correctly --- linux-core/intel_display.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'linux-core/intel_display.c') diff --git a/linux-core/intel_display.c b/linux-core/intel_display.c index fce0fafd..92b39406 100644 --- a/linux-core/intel_display.c +++ b/linux-core/intel_display.c @@ -351,9 +351,10 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y) int dspbase = (pipe == 0 ? DSPABASE : DSPBBASE); int dspsurf = (pipe == 0 ? DSPASURF : DSPBSURF); - Start = crtc->fb->offset; + Start = crtc->fb->offset + dev_priv->baseaddr; Offset = ((y * crtc->fb->width + x) * (crtc->fb->bits_per_pixel / 8)); + DRM_DEBUG("Writing base %08X %08X %d %d\n", Start, Offset, x, y); if (IS_I965G(dev)) { I915_WRITE(dspbase, Offset); I915_READ(dspbase); -- cgit v1.2.3 From f1476e4e5cefd4aa8c487b4e651a26056110e2f0 Mon Sep 17 00:00:00 2001 From: David Airlie Date: Tue, 10 Apr 2007 16:25:52 +1000 Subject: re-tab and fixup the i915GM get core clock function to actually work --- linux-core/intel_display.c | 186 ++++++++++++++++++++++----------------------- 1 file changed, 91 insertions(+), 95 deletions(-) (limited to 'linux-core/intel_display.c') diff --git a/linux-core/intel_display.c b/linux-core/intel_display.c index 92b39406..75d7359f 100644 --- a/linux-core/intel_display.c +++ b/linux-core/intel_display.c @@ -583,8 +583,9 @@ static int intel_get_core_clock_speed(drm_device_t *dev) else if (IS_I945GM(dev) || IS_845G(dev)) return 200000; else if (IS_I915GM(dev)) { -#if 0 - u16 gcfgc = pciReadWord(dev->PciTag, I915_GCFGC); + u16 gcfgc = 0; + + pci_read_config_word(dev->pdev, I915_GCFGC, &gcfgc); if (gcfgc & I915_LOW_FREQUENCY_ENABLE) return 133000; @@ -597,7 +598,6 @@ static int intel_get_core_clock_speed(drm_device_t *dev) return 190000; } } -#endif } else if (IS_I865G(dev)) return 266000; else if (IS_I855(dev)) { @@ -835,106 +835,102 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc, if (intel_panel_fitter_pipe(dev) == pipe) I915_WRITE(PFIT_CONTROL, 0); + DRM_DEBUG("Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B'); + drm_mode_debug_printmodeline(dev, mode); + #if 0 - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B'); - xf86PrintModeline(pScrn->scrnIndex, mode); - if (!xf86ModesEqual(mode, adjusted_mode)) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Adjusted mode for pipe %c:\n", pipe == 0 ? 'A' : 'B'); - xf86PrintModeline(pScrn->scrnIndex, mode); - } - i830PrintPll("chosen", &clock); + if (!xf86ModesEqual(mode, adjusted_mode)) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Adjusted mode for pipe %c:\n", pipe == 0 ? 'A' : 'B'); + xf86PrintModeline(pScrn->scrnIndex, mode); + } + i830PrintPll("chosen", &clock); #endif - if (dpll & DPLL_VCO_ENABLE) - { + if (dpll & DPLL_VCO_ENABLE) { + I915_WRITE(fp_reg, fp); + I915_WRITE(dpll_reg, dpll & ~DPLL_VCO_ENABLE); + I915_READ(dpll_reg); + udelay(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) { + u32 lvds = I915_READ(LVDS); + + 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. + */ + if (clock.p2 == 7) + 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. + */ + + I915_WRITE(LVDS, lvds); + I915_READ(LVDS); + } + I915_WRITE(fp_reg, fp); - I915_WRITE(dpll_reg, dpll & ~DPLL_VCO_ENABLE); + I915_WRITE(dpll_reg, dpll); I915_READ(dpll_reg); + /* Wait for the clocks to stabilize. */ udelay(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) - { - u32 lvds = I915_READ(LVDS); - - 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. - */ - if (clock.p2 == 7) - 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. - */ - - I915_WRITE(LVDS, lvds); - I915_READ(LVDS); - } - - I915_WRITE(fp_reg, fp); - I915_WRITE(dpll_reg, dpll); - I915_READ(dpll_reg); - /* Wait for the clocks to stabilize. */ - udelay(150); - - if (IS_I965G(dev)) { - int sdvo_pixel_multiply = adjusted_mode->clock / mode->clock; - I915_WRITE(dpll_md_reg, (0 << DPLL_MD_UDI_DIVIDER_SHIFT) | - ((sdvo_pixel_multiply - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT)); - } else { - /* write it again -- the BIOS does, after all */ - I915_WRITE(dpll_reg, dpll); - } - I915_READ(dpll_reg); - /* Wait for the clocks to stabilize. */ - udelay(150); - - I915_WRITE(htot_reg, (adjusted_mode->crtc_hdisplay - 1) | - ((adjusted_mode->crtc_htotal - 1) << 16)); - I915_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - 1) | - ((adjusted_mode->crtc_hblank_end - 1) << 16)); - I915_WRITE(hsync_reg, (adjusted_mode->crtc_hsync_start - 1) | - ((adjusted_mode->crtc_hsync_end - 1) << 16)); - I915_WRITE(vtot_reg, (adjusted_mode->crtc_vdisplay - 1) | - ((adjusted_mode->crtc_vtotal - 1) << 16)); - I915_WRITE(vblank_reg, (adjusted_mode->crtc_vblank_start - 1) | - ((adjusted_mode->crtc_vblank_end - 1) << 16)); - I915_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start - 1) | - ((adjusted_mode->crtc_vsync_end - 1) << 16)); - I915_WRITE(dspstride_reg, crtc->fb->pitch * (crtc->fb->bits_per_pixel / 8)); - /* pipesrc and dspsize control the size that is scaled from, which should - * always be the user's requested size. - */ - I915_WRITE(dspsize_reg, ((mode->vdisplay - 1) << 16) | (mode->hdisplay - 1)); - I915_WRITE(dsppos_reg, 0); - I915_WRITE(pipesrc_reg, ((mode->hdisplay - 1) << 16) | (mode->vdisplay - 1)); - I915_WRITE(pipeconf_reg, pipeconf); - I915_READ(pipeconf_reg); - - intel_wait_for_vblank(dev); - - I915_WRITE(dspcntr_reg, dspcntr); - - /* Flush the plane changes */ - intel_pipe_set_base(crtc, x, y); - + + if (IS_I965G(dev)) { + int sdvo_pixel_multiply = adjusted_mode->clock / mode->clock; + I915_WRITE(dpll_md_reg, (0 << DPLL_MD_UDI_DIVIDER_SHIFT) | + ((sdvo_pixel_multiply - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT)); + } else { + /* write it again -- the BIOS does, after all */ + I915_WRITE(dpll_reg, dpll); + } + I915_READ(dpll_reg); + /* Wait for the clocks to stabilize. */ + udelay(150); + + I915_WRITE(htot_reg, (adjusted_mode->crtc_hdisplay - 1) | + ((adjusted_mode->crtc_htotal - 1) << 16)); + I915_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - 1) | + ((adjusted_mode->crtc_hblank_end - 1) << 16)); + I915_WRITE(hsync_reg, (adjusted_mode->crtc_hsync_start - 1) | + ((adjusted_mode->crtc_hsync_end - 1) << 16)); + I915_WRITE(vtot_reg, (adjusted_mode->crtc_vdisplay - 1) | + ((adjusted_mode->crtc_vtotal - 1) << 16)); + I915_WRITE(vblank_reg, (adjusted_mode->crtc_vblank_start - 1) | + ((adjusted_mode->crtc_vblank_end - 1) << 16)); + I915_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start - 1) | + ((adjusted_mode->crtc_vsync_end - 1) << 16)); + I915_WRITE(dspstride_reg, crtc->fb->pitch * (crtc->fb->bits_per_pixel / 8)); + /* pipesrc and dspsize control the size that is scaled from, which should + * always be the user's requested size. + */ + I915_WRITE(dspsize_reg, ((mode->vdisplay - 1) << 16) | (mode->hdisplay - 1)); + I915_WRITE(dsppos_reg, 0); + I915_WRITE(pipesrc_reg, ((mode->hdisplay - 1) << 16) | (mode->vdisplay - 1)); + I915_WRITE(pipeconf_reg, pipeconf); + I915_READ(pipeconf_reg); + + intel_wait_for_vblank(dev); + + I915_WRITE(dspcntr_reg, dspcntr); + + /* Flush the plane changes */ + intel_pipe_set_base(crtc, x, y); + #ifdef XF86DRI // TODO // I830DRISetVBlankInterrupt (pScrn, TRUE); #endif - - intel_wait_for_vblank(dev); - - + + intel_wait_for_vblank(dev); } /** Loads the palette/gamma unit for the CRTC with the prepared values */ @@ -1002,7 +998,7 @@ void intel_crtc_init(drm_device_t *dev, int pipe) if (crtc == NULL) return; - intel_crtc = kmalloc(sizeof(struct intel_crtc), GFP_KERNEL); + intel_crtc = kzalloc(sizeof(struct intel_crtc), GFP_KERNEL); if (intel_crtc == NULL) { kfree(crtc); return; -- cgit v1.2.3 From b9c7fa55e2c6685c4c533613ab14f305f033c353 Mon Sep 17 00:00:00 2001 From: David Airlie Date: Tue, 10 Apr 2007 16:32:17 +1000 Subject: fixup sarea writes for set pipe base and dpms --- linux-core/intel_display.c | 63 ++++++++++++++++++++-------------------------- 1 file changed, 27 insertions(+), 36 deletions(-) (limited to 'linux-core/intel_display.c') diff --git a/linux-core/intel_display.c b/linux-core/intel_display.c index 75d7359f..9fb497dd 100644 --- a/linux-core/intel_display.c +++ b/linux-core/intel_display.c @@ -366,27 +366,22 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y) } -#if 0 - drmI830Sarea *sPriv = (drmI830Sarea *) DRIGetSAREAPrivate(pScrn->pScreen); - - if (!sPriv) + if (!dev_priv->sarea_priv) return; switch (pipe) { - case 0: - sPriv->pipeA_x = x; - sPriv->pipeA_y = y; - break; + case 0: + dev_priv->sarea_priv->pipeA_x = x; + dev_priv->sarea_priv->pipeA_y = y; + break; case 1: - sPriv->pipeB_x = x; - sPriv->pipeB_y = y; + dev_priv->sarea_priv->pipeB_x = x; + dev_priv->sarea_priv->pipeB_y = y; break; default: - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Can't update pipe %d in SAREA\n", pipe); + DRM_ERROR("Can't update pipe %d in SAREA\n", pipe); break; } -#endif } /** @@ -406,6 +401,7 @@ static void intel_crtc_dpms(struct drm_crtc *crtc, int mode) int dspbase_reg = (pipe == 0) ? DSPABASE : DSPBBASE; int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; u32 temp; + bool enabled; /* 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. @@ -494,30 +490,25 @@ static void intel_crtc_dpms(struct drm_crtc *crtc, int mode) break; } -#if 0 //TODO - if (pI830->directRenderingEnabled) { - drmI830Sarea *sPriv = (drmI830Sarea *) DRIGetSAREAPrivate(pScrn->pScreen); - Bool enabled = crtc->enabled && mode != DPMSModeOff; - - if (!sPriv) - return; - - switch (pipe) { - case 0: - sPriv->pipeA_w = enabled ? crtc->mode.HDisplay : 0; - sPriv->pipeA_h = enabled ? crtc->mode.VDisplay : 0; - break; - case 1: - sPriv->pipeB_w = enabled ? crtc->mode.HDisplay : 0; - sPriv->pipeB_h = enabled ? crtc->mode.VDisplay : 0; - break; - default: - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Can't update pipe %d in SAREA\n", pipe); - break; - } + + if (!dev_priv->sarea_priv) + return; + + enabled = crtc->enabled && mode != DPMSModeOff; + + switch (pipe) { + case 0: + dev_priv->sarea_priv->pipeA_w = enabled ? crtc->mode.hdisplay : 0; + dev_priv->sarea_priv->pipeA_h = enabled ? crtc->mode.vdisplay : 0; + break; + case 1: + dev_priv->sarea_priv->pipeB_w = enabled ? crtc->mode.hdisplay : 0; + dev_priv->sarea_priv->pipeB_h = enabled ? crtc->mode.vdisplay : 0; + break; + default: + DRM_ERROR("Can't update pipe %d in SAREA\n", pipe); + break; } -#endif } static bool intel_crtc_lock(struct drm_crtc *crtc) -- cgit v1.2.3 From 183cbd92dd016f8935f9b58ef9345fde1391173e Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Tue, 10 Apr 2007 09:47:37 -0700 Subject: Finish bringing in LVDS code, re-add to Makefile. Needed other changes too: - move EDID structures to drm_edid.h - add EDID info structure to drm_output - add a few routines to intel_display for getting current mode info - add some prototypes to intel_drv.h and drm_crtc.h --- linux-core/intel_display.c | 114 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 110 insertions(+), 4 deletions(-) (limited to 'linux-core/intel_display.c') diff --git a/linux-core/intel_display.c b/linux-core/intel_display.c index 58d66987..90c894ee 100644 --- a/linux-core/intel_display.c +++ b/linux-core/intel_display.c @@ -26,8 +26,6 @@ #include #include "drmP.h" -#include "drm.h" -#include "drm_crtc.h" #include "intel_drv.h" #include "i915_drm.h" #include "i915_drv.h" @@ -973,10 +971,115 @@ static void intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green, intel_crtc_load_lut(crtc); } +/* Returns the clock of the currently programmed mode of the given pipe. */ +static int intel_crtc_clock_get(struct drm_device *dev, struct drm_crtc *crtc) +{ + drm_i915_private_t *dev_priv = dev->dev_private; + struct intel_crtc *intel_crtc = crtc->driver_private; + int pipe = intel_crtc->pipe; + u32 dpll = I915_READ((pipe == 0) ? DPLL_A : DPLL_B); + u32 fp; + intel_clock_t clock; + + if ((dpll & DISPLAY_RATE_SELECT_FPA1) == 0) + fp = I915_READ((pipe == 0) ? FPA0 : FPB0); + else + fp = I915_READ((pipe == 0) ? FPA1 : FPB1); + + clock.m1 = (fp & FP_M1_DIV_MASK) >> FP_M1_DIV_SHIFT; + clock.m2 = (fp & FP_M2_DIV_MASK) >> FP_M2_DIV_SHIFT; + clock.n = (fp & FP_N_DIV_MASK) >> FP_N_DIV_SHIFT; + if (IS_I9XX(dev)) { + clock.p1 = ffs((dpll & DPLL_FPA01_P1_POST_DIV_MASK) >> + DPLL_FPA01_P1_POST_DIV_SHIFT); + + switch (dpll & DPLL_MODE_MASK) { + case DPLLB_MODE_DAC_SERIAL: + clock.p2 = dpll & DPLL_DAC_SERIAL_P2_CLOCK_DIV_5 ? + 5 : 10; + break; + case DPLLB_MODE_LVDS: + clock.p2 = dpll & DPLLB_LVDS_P2_CLOCK_DIV_7 ? + 7 : 14; + break; + default: + DRM_DEBUG("Unknown DPLL mode %08x in programmed " + "mode\n", (int)(dpll & DPLL_MODE_MASK)); + return 0; + } + + /* XXX: Handle the 100Mhz refclk */ + i9xx_clock(96000, &clock); + } else { + bool is_lvds = (pipe == 1) && (I915_READ(LVDS) & LVDS_PORT_EN); + + if (is_lvds) { + clock.p1 = ffs((dpll & DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS) >> + DPLL_FPA01_P1_POST_DIV_SHIFT); + clock.p2 = 14; + + if ((dpll & PLL_REF_INPUT_MASK) == + PLLB_REF_INPUT_SPREADSPECTRUMIN) { + /* XXX: might not be 66MHz */ + i8xx_clock(66000, &clock); + } else + i8xx_clock(48000, &clock); + } else { + if (dpll & PLL_P1_DIVIDE_BY_TWO) + clock.p1 = 2; + else { + clock.p1 = ((dpll & DPLL_FPA01_P1_POST_DIV_MASK_I830) >> + DPLL_FPA01_P1_POST_DIV_SHIFT) + 2; + } + if (dpll & PLL_P2_DIVIDE_BY_4) + clock.p2 = 4; + else + clock.p2 = 2; + + i8xx_clock(48000, &clock); + } + } + + /* XXX: It would be nice to validate the clocks, but we can't reuse + * i830PllIsValid() because it relies on the xf86_config output + * configuration being accurate, which it isn't necessarily. + */ + + return clock.dot; +} + +/** Returns the currently programmed mode of the given pipe. */ struct drm_display_mode *intel_crtc_mode_get(drm_device_t *dev, struct drm_crtc *crtc) { - return NULL; + drm_i915_private_t *dev_priv = dev->dev_private; + struct intel_crtc *intel_crtc = crtc->driver_private; + int pipe = intel_crtc->pipe; + struct drm_display_mode *mode; + int htot = I915_READ((pipe == 0) ? HTOTAL_A : HTOTAL_B); + int hsync = I915_READ((pipe == 0) ? HSYNC_A : HSYNC_B); + int vtot = I915_READ((pipe == 0) ? VTOTAL_A : VTOTAL_B); + int vsync = I915_READ((pipe == 0) ? VSYNC_A : VSYNC_B); + + mode = kzalloc(sizeof(*mode), GFP_KERNEL); + if (!mode) + return NULL; + + mode->clock = intel_crtc_clock_get(dev, crtc); + mode->hdisplay = (htot & 0xffff) + 1; + mode->htotal = ((htot & 0xffff0000) >> 16) + 1; + mode->hsync_start = (hsync & 0xffff) + 1; + mode->hsync_end = ((hsync & 0xffff0000) >> 16) + 1; + mode->vdisplay = (vtot & 0xffff) + 1; + mode->vtotal = ((vtot & 0xffff0000) >> 16) + 1; + mode->vsync_start = (vsync & 0xffff) + 1; + mode->vsync_end = ((vsync & 0xffff0000) >> 16) + 1; + /* FIXME: pull name generation into a common routine */ + snprintf(mode->name, DRM_DISPLAY_MODE_LEN, "%dx%d", mode->hdisplay, + mode->vdisplay); + drm_mode_set_crtcinfo(mode, 0); + + return mode; } static const struct drm_crtc_funcs intel_crtc_funcs = { @@ -1017,7 +1120,7 @@ void intel_crtc_init(drm_device_t *dev, int pipe) crtc->driver_private = intel_crtc; } -int intel_output_clones (drm_device_t *dev, int type_mask) +int intel_output_clones(drm_device_t *dev, int type_mask) { int index_mask = 0; struct drm_output *output; @@ -1039,9 +1142,11 @@ static void intel_setup_outputs(drm_device_t *dev) intel_crt_init(dev); +#if 0 /* Set up integrated LVDS */ if (IS_MOBILE(dev) && !IS_I830(dev)) intel_lvds_init(dev); +#endif if (IS_I9XX(dev)) { intel_sdvo_init(dev, SDVOB); @@ -1105,6 +1210,7 @@ void intel_modeset_init(drm_device_t *dev) intel_setup_outputs(dev); drm_initial_config(dev, false); + drm_set_desired_modes(dev); } void intel_modeset_cleanup(drm_device_t *dev) -- cgit v1.2.3 From 3e994a56be1bfc633e49434c9e4a3e3262070248 Mon Sep 17 00:00:00 2001 From: David Airlie Date: Wed, 11 Apr 2007 13:18:49 +1000 Subject: use fb pitch and fix up some whitespace --- linux-core/intel_display.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'linux-core/intel_display.c') diff --git a/linux-core/intel_display.c b/linux-core/intel_display.c index 1eed71f0..04a6e086 100644 --- a/linux-core/intel_display.c +++ b/linux-core/intel_display.c @@ -350,7 +350,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y) int dspsurf = (pipe == 0 ? DSPASURF : DSPBSURF); Start = crtc->fb->offset + dev_priv->baseaddr; - Offset = ((y * crtc->fb->width + x) * (crtc->fb->bits_per_pixel / 8)); + Offset = ((y * crtc->fb->pitch + x) * (crtc->fb->bits_per_pixel / 8)); DRM_DEBUG("Writing base %08lX %08lX %d %d\n", Start, Offset, x, y); if (IS_I965G(dev)) { @@ -530,24 +530,22 @@ static void intel_crtc_unlock (struct drm_crtc *crtc) static void intel_crtc_prepare (struct drm_crtc *crtc) { - crtc->funcs->dpms (crtc, DPMSModeOff); + crtc->funcs->dpms(crtc, DPMSModeOff); } static void intel_crtc_commit (struct drm_crtc *crtc) { - crtc->funcs->dpms (crtc, DPMSModeOn); -// if (crtc->scrn->pScreen != NULL) -// xf86_reload_cursors (crtc->scrn->pScreen); + crtc->funcs->dpms(crtc, DPMSModeOn); } void intel_output_prepare (struct drm_output *output) { - output->funcs->dpms (output, DPMSModeOff); + output->funcs->dpms(output, DPMSModeOff); } void intel_output_commit (struct drm_output *output) { - output->funcs->dpms (output, DPMSModeOn); + output->funcs->dpms(output, DPMSModeOn); } static bool intel_crtc_mode_fixup(struct drm_crtc *crtc, -- cgit v1.2.3 From 78598fdaa8b23a199880a63b79f17cfd7f14cb0f Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Wed, 11 Apr 2007 07:07:54 -0700 Subject: Various changes for in-kernel modesetting: - allow drm_buffer_object_create to be called w/o dev_mapping - fixup i915 init code to allocate memory, fb and set modes right - pass fb to drm_initial_config for setup - change some debug output to make it easier to spot - fixup lvds code to use DDC probing correctly --- linux-core/intel_display.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'linux-core/intel_display.c') diff --git a/linux-core/intel_display.c b/linux-core/intel_display.c index 04a6e086..bb6f7f23 100644 --- a/linux-core/intel_display.c +++ b/linux-core/intel_display.c @@ -1128,11 +1128,9 @@ static void intel_setup_outputs(drm_device_t *dev) intel_crt_init(dev); -#if 0 /* Set up integrated LVDS */ if (IS_MOBILE(dev) && !IS_I830(dev)) intel_lvds_init(dev); -#endif if (IS_I9XX(dev)) { intel_sdvo_init(dev, SDVOB); -- cgit v1.2.3 From 425da42e95606fec19cc87fad9329d48f93dfe6b Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Wed, 11 Apr 2007 11:44:54 -0700 Subject: Whitespace cleanups. --- linux-core/intel_display.c | 46 ++++++++++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 22 deletions(-) (limited to 'linux-core/intel_display.c') diff --git a/linux-core/intel_display.c b/linux-core/intel_display.c index bb6f7f23..396f4cfa 100644 --- a/linux-core/intel_display.c +++ b/linux-core/intel_display.c @@ -168,18 +168,18 @@ static const intel_limit_t intel_limits[] = { }, }; -static const intel_limit_t *intel_limit (struct drm_crtc *crtc) +static const intel_limit_t *intel_limit(struct drm_crtc *crtc) { drm_device_t *dev = crtc->dev; const intel_limit_t *limit; if (IS_I9XX(dev)) { - if (intel_pipe_has_type (crtc, INTEL_OUTPUT_LVDS)) + if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) limit = &intel_limits[INTEL_LIMIT_I9XX_LVDS]; else limit = &intel_limits[INTEL_LIMIT_I9XX_SDVO_DAC]; } else { - if (intel_pipe_has_type (crtc, INTEL_OUTPUT_LVDS)) + if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) limit = &intel_limits[INTEL_LIMIT_I8XX_LVDS]; else limit = &intel_limits[INTEL_LIMIT_I8XX_DVO_DAC]; @@ -280,18 +280,20 @@ static bool intel_find_best_PLL(struct drm_crtc *crtc, int target, { drm_device_t *dev = crtc->dev; drm_i915_private_t *dev_priv = dev->dev_private; - intel_clock_t clock; - const intel_limit_t *limit = intel_limit (crtc); + intel_clock_t clock; + const intel_limit_t *limit = intel_limit(crtc); int err = target; - if (IS_I9XX(dev)& intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) && - (I915_READ(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 ((I915_READ(LVDS) & LVDS_CLKB_POWER_MASK) == LVDS_CLKB_POWER_UP) + if (IS_I9XX(dev) && intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) && + (I915_READ(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 ((I915_READ(LVDS) & LVDS_CLKB_POWER_MASK) == + LVDS_CLKB_POWER_UP) clock.p2 = limit->p2.p2_fast; else clock.p2 = limit->p2.p2_slow; @@ -304,17 +306,16 @@ static bool intel_find_best_PLL(struct drm_crtc *crtc, int target, memset (best_clock, 0, sizeof (*best_clock)); - for (clock.m1 = limit->m1.min; clock.m1 <= limit->m1.max; clock.m1++) - { - for (clock.m2 = limit->m2.min; clock.m2 < clock.m1 && clock.m2 <= limit->m2.max; clock.m2++) - { - for (clock.n = limit->n.min; clock.n <= limit->n.max; clock.n++) - { - for (clock.p1 = limit->p1.min; clock.p1 <= limit->p1.max; clock.p1++) - { + for (clock.m1 = limit->m1.min; clock.m1 <= limit->m1.max; clock.m1++) { + for (clock.m2 = limit->m2.min; clock.m2 < clock.m1 && + clock.m2 <= limit->m2.max; clock.m2++) { + for (clock.n = limit->n.min; clock.n <= limit->n.max; + clock.n++) { + for (clock.p1 = limit->p1.min; + clock.p1 <= limit->p1.max; clock.p1++) { int this_err; - intel_clock (dev, refclk, &clock); + intel_clock(dev, refclk, &clock); if (!intel_PLL_is_valid(crtc, &clock)) continue; @@ -328,6 +329,7 @@ static bool intel_find_best_PLL(struct drm_crtc *crtc, int target, } } } + return (err != target); } -- cgit v1.2.3 From b49b3ba4c1aad0d3f34f06013f2ffa67fc8d82c9 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 12 Apr 2007 11:43:13 +1000 Subject: set bracing style like Linux --- linux-core/intel_display.c | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) (limited to 'linux-core/intel_display.c') diff --git a/linux-core/intel_display.c b/linux-core/intel_display.c index 396f4cfa..aed86231 100644 --- a/linux-core/intel_display.c +++ b/linux-core/intel_display.c @@ -412,8 +412,7 @@ static void intel_crtc_dpms(struct drm_crtc *crtc, int mode) case DPMSModeSuspend: /* Enable the DPLL */ temp = I915_READ(dpll_reg); - if ((temp & DPLL_VCO_ENABLE) == 0) - { + if ((temp & DPLL_VCO_ENABLE) == 0) { I915_WRITE(dpll_reg, temp); I915_READ(dpll_reg); /* Wait for the clocks to stabilize. */ @@ -435,8 +434,7 @@ static void intel_crtc_dpms(struct drm_crtc *crtc, int mode) /* Enable the plane */ temp = I915_READ(dspcntr_reg); - if ((temp & DISPLAY_PLANE_ENABLE) == 0) - { + if ((temp & DISPLAY_PLANE_ENABLE) == 0) { I915_WRITE(dspcntr_reg, temp | DISPLAY_PLANE_ENABLE); /* Flush the plane changes */ I915_WRITE(dspbase_reg, I915_READ(dspbase_reg)); @@ -456,8 +454,7 @@ static void intel_crtc_dpms(struct drm_crtc *crtc, int mode) /* Disable display plane */ temp = I915_READ(dspcntr_reg); - if ((temp & DISPLAY_PLANE_ENABLE) != 0) - { + if ((temp & DISPLAY_PLANE_ENABLE) != 0) { I915_WRITE(dspcntr_reg, temp & ~DISPLAY_PLANE_ENABLE); /* Flush the plane changes */ I915_WRITE(dspbase_reg, I915_READ(dspbase_reg)); @@ -719,11 +716,9 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc, dpll |= DPLLB_MODE_LVDS; else dpll |= DPLLB_MODE_DAC_SERIAL; - if (is_sdvo) - { + if (is_sdvo) { dpll |= DPLL_DVO_HIGH_SPEED; - if (IS_I945G(dev) || IS_I945GM(dev)) - { + if (IS_I945G(dev) || IS_I945GM(dev)) { int sdvo_pixel_multiply = adjusted_mode->clock / mode->clock; dpll |= (sdvo_pixel_multiply - 1) << SDVO_MULTIPLIER_SHIFT_HIRES; } @@ -760,8 +755,7 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc, } } - if (is_tv) - { + if (is_tv) { /* XXX: just matching BIOS for now */ /* dpll |= PLL_REF_INPUT_TVCLKINBC; */ dpll |= 3; @@ -801,8 +795,7 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc, dspcntr |= DISPPLANE_SEL_PIPE_B; pipeconf = I915_READ(pipeconf_reg); - if (pipe == 0 && !IS_I965G(dev)) - { + if (pipe == 0 && !IS_I965G(dev)) { /* Enable pixel doubling when the dot clock is > 90% of the (display) * core speed. * -- cgit v1.2.3