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 From 6b229c1e59e8d070e1822030f8f0c1d61140508d Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Thu, 12 Apr 2007 12:41:56 -0700 Subject: Add new function for getting a CRTC pointer given a pipe number. --- linux-core/intel_display.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'linux-core/intel_display.c') diff --git a/linux-core/intel_display.c b/linux-core/intel_display.c index aed86231..e58b31b0 100644 --- a/linux-core/intel_display.c +++ b/linux-core/intel_display.c @@ -1101,6 +1101,18 @@ void intel_crtc_init(drm_device_t *dev, int pipe) crtc->driver_private = intel_crtc; } +struct drm_crtc *intel_get_crtc_from_pipe(drm_device_t *dev, int pipe) +{ + struct drm_crtc *crtc = NULL; + + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + struct intel_crtc *intel_crtc = crtc->driver_private; + if (intel_crtc->pipe == pipe) + break; + } + return crtc; +} + int intel_output_clones(drm_device_t *dev, int type_mask) { int index_mask = 0; -- cgit v1.2.3 From cd5769c3b563048357535b24dc40783775adb227 Mon Sep 17 00:00:00 2001 From: Jakob Bornecrantz Date: Mon, 16 Apr 2007 20:54:24 +0200 Subject: Fix offset should from pci device address --- linux-core/intel_display.c | 4 ++-- 1 file changed, 2 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 e58b31b0..48239329 100644 --- a/linux-core/intel_display.c +++ b/linux-core/intel_display.c @@ -350,8 +350,8 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y) unsigned long Start, Offset; int dspbase = (pipe == 0 ? DSPABASE : DSPBBASE); int dspsurf = (pipe == 0 ? DSPASURF : DSPBSURF); - - Start = crtc->fb->offset + dev_priv->baseaddr; + + Start = crtc->fb->offset; 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); -- cgit v1.2.3 From a45fa264f2b60185ae797f85d2084d57de49bbca Mon Sep 17 00:00:00 2001 From: Jakob Bornecrantz Date: Tue, 17 Apr 2007 22:27:46 +0200 Subject: Lvds now power up backlight on commit Now saves previous power level in prepare and sets that power level in commit, should power level be 0 it will set maximum level. --- linux-core/intel_display.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'linux-core/intel_display.c') diff --git a/linux-core/intel_display.c b/linux-core/intel_display.c index 48239329..d0a3a465 100644 --- a/linux-core/intel_display.c +++ b/linux-core/intel_display.c @@ -539,11 +539,13 @@ static void intel_crtc_commit (struct drm_crtc *crtc) void intel_output_prepare (struct drm_output *output) { + /* lvds has its own version of prepare see intel_lvds_prepare */ output->funcs->dpms(output, DPMSModeOff); } void intel_output_commit (struct drm_output *output) { + /* lvds has its own version of commit see intel_lvds_commit */ output->funcs->dpms(output, DPMSModeOn); } -- cgit v1.2.3 From 9ca4932054a5bde5dda500ea346ad101bb5c80a0 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Fri, 20 Apr 2007 16:32:58 -0700 Subject: Add a mode name generation wrapper to make name format changes easier. --- linux-core/intel_display.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'linux-core/intel_display.c') diff --git a/linux-core/intel_display.c b/linux-core/intel_display.c index d0a3a465..a6f94fb1 100644 --- a/linux-core/intel_display.c +++ b/linux-core/intel_display.c @@ -1057,9 +1057,8 @@ struct drm_display_mode *intel_crtc_mode_get(drm_device_t *dev, 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_name(mode); drm_mode_set_crtcinfo(mode, 0); return mode; -- cgit v1.2.3 From 34be91fe4e9f0ad73b7c4354aea0c8ce10f45f68 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 26 Apr 2007 14:50:00 +1000 Subject: i915: fix vblank pipe setup --- linux-core/intel_display.c | 24 ++++++++++++++++++++---- 1 file changed, 20 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 a6f94fb1..7d581175 100644 --- a/linux-core/intel_display.c +++ b/linux-core/intel_display.c @@ -333,6 +333,24 @@ static bool intel_find_best_PLL(struct drm_crtc *crtc, int target, return (err != target); } +void +intel_set_vblank(drm_device_t *dev) +{ + drm_i915_private_t *dev_priv = dev->dev_private; + struct drm_crtc *crtc; + struct intel_crtc *intel_crtc; + int vbl_pipe = 0; + + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + intel_crtc = crtc->driver_private; + + if (crtc->enabled) + vbl_pipe |= (1<pipe); + } + + dev_priv->vblank_pipe = vbl_pipe; + i915_enable_interrupt(dev); +} void intel_wait_for_vblank(drm_device_t *dev) { @@ -910,10 +928,8 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc, /* Flush the plane changes */ intel_pipe_set_base(crtc, x, y); -#ifdef XF86DRI // TODO -// I830DRISetVBlankInterrupt (pScrn, TRUE); -#endif - + intel_set_vblank(dev); + intel_wait_for_vblank(dev); } -- cgit v1.2.3 From 5ce8aaae7251e60c078eda0a21894aae0e1d7a45 Mon Sep 17 00:00:00 2001 From: root Date: Thu, 17 May 2007 12:46:36 +0100 Subject: Large changes for fbdev support. Change from DIRECTCOLOR to TRUECOLOR, and enable support for PSEUDOCOLOR. DIRECTCOLOR support needs more work. Add the ability to change the mode on the fbdev device. Support depth 8, 15, 16 and 24 (and 32). Add a /dev/fbX device per CRTC, but there's some code which doesn't allocate the fbX device unless the output is actually enabled. Read the code on this as it impacts the fbcon map flags. Pick CRTC's based on the available outputs. More work could be done here to match modes, so cloning could be achieved on outputs. This fits more inline with what the X code does. --- linux-core/intel_display.c | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) (limited to 'linux-core/intel_display.c') diff --git a/linux-core/intel_display.c b/linux-core/intel_display.c index 7d581175..7879965e 100644 --- a/linux-core/intel_display.c +++ b/linux-core/intel_display.c @@ -787,6 +787,9 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc, else dpll |= PLL_REF_INPUT_DREFCLK; + /* setup pipeconf */ + pipeconf = I915_READ(pipeconf_reg); + /* Set up the display plane register */ dspcntr = DISPPLANE_GAMMA_ENABLE; @@ -814,7 +817,6 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc, 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. @@ -955,19 +957,14 @@ void intel_crtc_load_lut(struct drm_crtc *crtc) } /** 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) +static void intel_crtc_gamma_set(struct drm_crtc *crtc, u16 red, u16 green, + u16 blue, int regno) { 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); + intel_crtc->lut_r[regno] = red >> 8; + intel_crtc->lut_g[regno] = green >> 8; + intel_crtc->lut_b[regno] = blue >> 8; } /* Returns the clock of the currently programmed mode of the given pipe. */ @@ -1176,7 +1173,8 @@ static void intel_setup_outputs(drm_device_t *dev) (1 << INTEL_OUTPUT_SDVO)); break; case INTEL_OUTPUT_ANALOG: - crtc_mask = ((1 << 0)); + crtc_mask = ((1 << 0)| + (1 << 1)); clone_mask = ((1 << INTEL_OUTPUT_ANALOG) | (1 << INTEL_OUTPUT_DVO) | (1 << INTEL_OUTPUT_SDVO)); @@ -1223,7 +1221,6 @@ 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 a18b4befb9b76c4b2662ff6caa0e4f0975eb8e9c Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Thu, 17 May 2007 09:00:06 -0700 Subject: Fix FB pitch value (we had it wrong and were working around it in a few places). Add new FB hooks to the drm driver structure and make i915 use them for an Intel specific FB driver. This will allow acceleration and better handling of the command stream. --- linux-core/intel_display.c | 4 ++-- 1 file changed, 2 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 7d581175..be2db912 100644 --- a/linux-core/intel_display.c +++ b/linux-core/intel_display.c @@ -370,7 +370,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y) int dspsurf = (pipe == 0 ? DSPASURF : DSPBSURF); Start = crtc->fb->offset; - Offset = ((y * crtc->fb->pitch + x) * (crtc->fb->bits_per_pixel / 8)); + Offset = y * crtc->fb->pitch + x; DRM_DEBUG("Writing base %08lX %08lX %d %d\n", Start, Offset, x, y); if (IS_I965G(dev)) { @@ -911,7 +911,7 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc, ((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)); + I915_WRITE(dspstride_reg, crtc->fb->pitch); /* pipesrc and dspsize control the size that is scaled from, which should * always be the user's requested size. */ -- cgit v1.2.3 From d69721a14a8954420b4e0022ecf10bb040c6b807 Mon Sep 17 00:00:00 2001 From: Alan Hourihane Date: Fri, 28 Sep 2007 09:21:09 +0100 Subject: Set the fb_base, so userspace applications can actually work now instead of locking up. --- linux-core/intel_display.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'linux-core/intel_display.c') diff --git a/linux-core/intel_display.c b/linux-core/intel_display.c index 3ff9f822..a81cfe69 100644 --- a/linux-core/intel_display.c +++ b/linux-core/intel_display.c @@ -1207,6 +1207,12 @@ void intel_modeset_init(struct drm_device *dev) dev->mode_config.max_width = 4096; dev->mode_config.max_height = 4096; + /* set memory base */ + if (IS_I9XX(dev)) + dev->mode_config.fb_base = pci_resource_start(dev->pdev, 2); + else + dev->mode_config.fb_base = pci_resource_start(dev->pdev, 0); + if (IS_MOBILE(dev) || IS_I9XX(dev)) num_pipe = 2; else -- cgit v1.2.3 From 219ba5cd9aff2dc79e414bbe2e9f90406f7543df Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 21 Dec 2007 18:38:55 +1000 Subject: s/TRUE/true --- linux-core/intel_display.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'linux-core/intel_display.c') diff --git a/linux-core/intel_display.c b/linux-core/intel_display.c index a81cfe69..8a6ce440 100644 --- a/linux-core/intel_display.c +++ b/linux-core/intel_display.c @@ -461,7 +461,7 @@ static void intel_crtc_dpms(struct drm_crtc *crtc, int mode) 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 + //intel_crtc_dpms_video(crtc, true); TODO break; case DPMSModeOff: /* Give the overlay scaler a chance to disable if it's on this pipe */ @@ -699,19 +699,19 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc, switch (intel_output->type) { case INTEL_OUTPUT_LVDS: - is_lvds = TRUE; + is_lvds = true; break; case INTEL_OUTPUT_SDVO: - is_sdvo = TRUE; + is_sdvo = true; break; case INTEL_OUTPUT_DVO: - is_dvo = TRUE; + is_dvo = true; break; case INTEL_OUTPUT_TVOUT: - is_tv = TRUE; + is_tv = true; break; case INTEL_OUTPUT_ANALOG: - is_crt = TRUE; + is_crt = true; break; } } -- cgit v1.2.3 From 10937cf20b6814e4cf68114fab4619fad94eafcb Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 4 Jan 2008 16:12:24 +1100 Subject: drm: move drm_head to drm_minor and fix up users --- linux-core/intel_display.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'linux-core/intel_display.c') diff --git a/linux-core/intel_display.c b/linux-core/intel_display.c index 8a6ce440..a81cfe69 100644 --- a/linux-core/intel_display.c +++ b/linux-core/intel_display.c @@ -461,7 +461,7 @@ static void intel_crtc_dpms(struct drm_crtc *crtc, int mode) 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 + //intel_crtc_dpms_video(crtc, TRUE); TODO break; case DPMSModeOff: /* Give the overlay scaler a chance to disable if it's on this pipe */ @@ -699,19 +699,19 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc, switch (intel_output->type) { case INTEL_OUTPUT_LVDS: - is_lvds = true; + is_lvds = TRUE; break; case INTEL_OUTPUT_SDVO: - is_sdvo = true; + is_sdvo = TRUE; break; case INTEL_OUTPUT_DVO: - is_dvo = true; + is_dvo = TRUE; break; case INTEL_OUTPUT_TVOUT: - is_tv = true; + is_tv = TRUE; break; case INTEL_OUTPUT_ANALOG: - is_crt = true; + is_crt = TRUE; break; } } -- cgit v1.2.3 From f07942f74a08e4c65e3b5e5c46f543686ae30c2b Mon Sep 17 00:00:00 2001 From: Jakob Bornecrantz Date: Fri, 11 Jan 2008 17:13:48 +0100 Subject: Panning now works without modeset --- linux-core/intel_display.c | 1 + 1 file changed, 1 insertion(+) (limited to 'linux-core/intel_display.c') diff --git a/linux-core/intel_display.c b/linux-core/intel_display.c index a81cfe69..e75d3c07 100644 --- a/linux-core/intel_display.c +++ b/linux-core/intel_display.c @@ -1083,6 +1083,7 @@ static const struct drm_crtc_funcs intel_crtc_funcs = { .unlock = intel_crtc_unlock, .mode_fixup = intel_crtc_mode_fixup, .mode_set = intel_crtc_mode_set, + .mode_set_base = intel_pipe_set_base, .gamma_set = intel_crtc_gamma_set, .prepare = intel_crtc_prepare, .commit = intel_crtc_commit, -- cgit v1.2.3 From e6fc47129ffe972bbee1c08fd822a8c171f21322 Mon Sep 17 00:00:00 2001 From: Jakob Bornecrantz Date: Fri, 11 Jan 2008 17:33:00 +0100 Subject: Fix for X axis panning problem --- linux-core/intel_display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux-core/intel_display.c') diff --git a/linux-core/intel_display.c b/linux-core/intel_display.c index e75d3c07..1498a51c 100644 --- a/linux-core/intel_display.c +++ b/linux-core/intel_display.c @@ -370,7 +370,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y) int dspsurf = (pipe == 0 ? DSPASURF : DSPBSURF); Start = crtc->fb->offset; - Offset = y * crtc->fb->pitch + x; + 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)) { -- cgit v1.2.3 From a2254c5a9670a3e865f0eb5acd46e905c9b146ce Mon Sep 17 00:00:00 2001 From: Jakob Bornecrantz Date: Mon, 28 Jan 2008 03:12:29 +0100 Subject: Added cursor support --- linux-core/intel_display.c | 108 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) (limited to 'linux-core/intel_display.c') diff --git a/linux-core/intel_display.c b/linux-core/intel_display.c index 1498a51c..88cf653c 100644 --- a/linux-core/intel_display.c +++ b/linux-core/intel_display.c @@ -402,6 +402,8 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y) } } + + /** * Sets the power management mode of the pipe and plane. * @@ -956,6 +958,108 @@ void intel_crtc_load_lut(struct drm_crtc *crtc) } } +#define CURSOR_A_CONTROL 0x70080 +#define CURSOR_A_BASE 0x70084 +#define CURSOR_A_POSITION 0x70088 + +#define CURSOR_B_CONTROL 0x700C0 +#define CURSOR_B_BASE 0x700C4 +#define CURSOR_B_POSITION 0x700C8 + +#define CURSOR_MODE_DISABLE 0x00 +#define CURSOR_MODE_64_32B_AX 0x07 +#define CURSOR_MODE_64_ARGB_AX ((1 << 5) | CURSOR_MODE_64_32B_AX) +#define MCURSOR_GAMMA_ENABLE (1 << 26) + +#define CURSOR_POS_MASK 0x007FF +#define CURSOR_POS_SIGN 0x8000 +#define CURSOR_X_SHIFT 0 +#define CURSOR_Y_SHIFT 16 + +static int intel_crtc_cursor_set(struct drm_crtc *crtc, + struct drm_buffer_object *bo, + uint32_t width, uint32_t height) +{ + struct drm_device *dev = crtc->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_crtc *intel_crtc = crtc->driver_private; + int pipe = intel_crtc->pipe; + uint32_t control = (pipe == 0) ? CURSOR_A_CONTROL : CURSOR_B_CONTROL; + uint32_t temp; + size_t adder; + + DRM_DEBUG("\n"); + + /* if we want to turn of the cursor ignore width and height */ + if (!bo) { + DRM_DEBUG("cursor off\n"); + /* turn of the cursor */ + temp = 0; + temp |= CURSOR_MODE_DISABLE; + + I915_WRITE(control, temp); + return 0; + } + + /* Currently we only support 64x64 cursors */ + if (width != 64 || height != 64) { + DRM_ERROR("we currently only support 64x64 cursors\n"); + return -EINVAL; + } + + if ((bo->mem.flags & DRM_BO_MASK_MEM) != DRM_BO_FLAG_MEM_VRAM) { + DRM_ERROR("buffer needs to be in VRAM\n"); + return -ENOMEM; + } + + if (bo->mem.size < width * height * 4) { + DRM_ERROR("buffer is to small\n"); + return -ENOMEM; + } + + adder = dev_priv->stolen_base + bo->offset; + intel_crtc->cursor_adder = adder; + temp = 0; + /* set the pipe for the cursor */ + temp |= (pipe << 28); + temp |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE; + + DRM_DEBUG("cusror base %x\n", adder); + + I915_WRITE((pipe == 0) ? CURSOR_A_CONTROL : CURSOR_B_CONTROL, temp); + I915_WRITE((pipe == 0) ? CURSOR_A_BASE : CURSOR_B_BASE, adder); + + return 0; +} + +static int intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) +{ + struct drm_device *dev = crtc->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_crtc *intel_crtc = crtc->driver_private; + int pipe = intel_crtc->pipe; + uint32_t temp = 0; + uint32_t adder; + + if (x < 0) { + temp |= (CURSOR_POS_SIGN << CURSOR_X_SHIFT); + x = -x; + } + if (y < 0) { + temp |= (CURSOR_POS_SIGN << CURSOR_Y_SHIFT); + y = -y; + } + + temp |= ((x & CURSOR_POS_MASK) << CURSOR_X_SHIFT); + temp |= ((y & CURSOR_POS_MASK) << CURSOR_Y_SHIFT); + + adder = intel_crtc->cursor_adder; + I915_WRITE((pipe == 0) ? CURSOR_A_POSITION : CURSOR_B_POSITION, temp); + I915_WRITE((pipe == 0) ? CURSOR_A_BASE : CURSOR_B_BASE, adder); + + return 0; +} + /** 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 regno) @@ -1084,6 +1188,8 @@ static const struct drm_crtc_funcs intel_crtc_funcs = { .mode_fixup = intel_crtc_mode_fixup, .mode_set = intel_crtc_mode_set, .mode_set_base = intel_pipe_set_base, + .cursor_set = intel_crtc_cursor_set, + .cursor_move = intel_crtc_cursor_move, .gamma_set = intel_crtc_gamma_set, .prepare = intel_crtc_prepare, .commit = intel_crtc_commit, @@ -1113,6 +1219,8 @@ void intel_crtc_init(struct drm_device *dev, int pipe) intel_crtc->lut_b[i] = i; } + intel_crtc->cursor_adder = 0; + crtc->driver_private = intel_crtc; } -- cgit v1.2.3 From abed0995585050d5fd179958d01f14f7e430e795 Mon Sep 17 00:00:00 2001 From: Jakob Bornecrantz Date: Wed, 30 Jan 2008 16:16:10 +0100 Subject: Fix for cursor off --- linux-core/intel_display.c | 6 ++++-- 1 file changed, 4 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 88cf653c..5b7a510b 100644 --- a/linux-core/intel_display.c +++ b/linux-core/intel_display.c @@ -985,6 +985,7 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc, struct intel_crtc *intel_crtc = crtc->driver_private; int pipe = intel_crtc->pipe; uint32_t control = (pipe == 0) ? CURSOR_A_CONTROL : CURSOR_B_CONTROL; + uint32_t base = (pipe == 0) ? CURSOR_A_BASE : CURSOR_B_BASE; uint32_t temp; size_t adder; @@ -998,6 +999,7 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc, temp |= CURSOR_MODE_DISABLE; I915_WRITE(control, temp); + I915_WRITE(base, 0); return 0; } @@ -1026,8 +1028,8 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc, DRM_DEBUG("cusror base %x\n", adder); - I915_WRITE((pipe == 0) ? CURSOR_A_CONTROL : CURSOR_B_CONTROL, temp); - I915_WRITE((pipe == 0) ? CURSOR_A_BASE : CURSOR_B_BASE, adder); + I915_WRITE(control, temp); + I915_WRITE(base, adder); return 0; } -- cgit v1.2.3 From 0fbee62ec14d08714dbc558dd20cc00b9a79c042 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 13 Feb 2008 15:19:42 +1000 Subject: major port of multi-master ideas into modesetting --- linux-core/intel_display.c | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) (limited to 'linux-core/intel_display.c') diff --git a/linux-core/intel_display.c b/linux-core/intel_display.c index 5b7a510b..db3aee83 100644 --- a/linux-core/intel_display.c +++ b/linux-core/intel_display.c @@ -363,6 +363,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y) { struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_master_private *master_priv; struct intel_crtc *intel_crtc = crtc->driver_private; int pipe = intel_crtc->pipe; unsigned long Start, Offset; @@ -384,17 +385,21 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y) } - if (!dev_priv->sarea_priv) + if (!dev->primary->master) + return; + + master_priv = dev->primary->master->driver_priv; + if (!master_priv->sarea_priv) return; switch (pipe) { case 0: - dev_priv->sarea_priv->planeA_x = x; - dev_priv->sarea_priv->planeA_y = y; + master_priv->sarea_priv->planeA_x = x; + master_priv->sarea_priv->planeA_y = y; break; case 1: - dev_priv->sarea_priv->planeB_x = x; - dev_priv->sarea_priv->planeB_y = y; + master_priv->sarea_priv->planeB_x = x; + master_priv->sarea_priv->planeB_y = y; break; default: DRM_ERROR("Can't update pipe %d in SAREA\n", pipe); @@ -413,6 +418,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y) static void intel_crtc_dpms(struct drm_crtc *crtc, int mode) { struct drm_device *dev = crtc->dev; + struct drm_i915_master_private *master_priv; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = crtc->driver_private; int pipe = intel_crtc->pipe; @@ -506,21 +512,24 @@ static void intel_crtc_dpms(struct drm_crtc *crtc, int mode) udelay(150); break; } - - if (!dev_priv->sarea_priv) + if (!dev->primary->master) + return; + + master_priv = dev->primary->master->driver_priv; + if (!master_priv->sarea_priv) return; enabled = crtc->enabled && mode != DPMSModeOff; switch (pipe) { case 0: - dev_priv->sarea_priv->planeA_w = enabled ? crtc->mode.hdisplay : 0; - dev_priv->sarea_priv->planeA_h = enabled ? crtc->mode.vdisplay : 0; + master_priv->sarea_priv->planeA_w = enabled ? crtc->mode.hdisplay : 0; + master_priv->sarea_priv->planeA_h = enabled ? crtc->mode.vdisplay : 0; break; case 1: - dev_priv->sarea_priv->planeB_w = enabled ? crtc->mode.hdisplay : 0; - dev_priv->sarea_priv->planeB_h = enabled ? crtc->mode.vdisplay : 0; + master_priv->sarea_priv->planeB_w = enabled ? crtc->mode.hdisplay : 0; + master_priv->sarea_priv->planeB_h = enabled ? crtc->mode.vdisplay : 0; break; default: DRM_ERROR("Can't update pipe %d in SAREA\n", pipe); -- cgit v1.2.3 From 088b38382962a9dccca59a53af2444a1fe8bc18f Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 15 Feb 2008 16:42:44 +1000 Subject: fb: fixup the offset by getting it from the right place --- 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 db3aee83..6a9d9808 100644 --- a/linux-core/intel_display.c +++ b/linux-core/intel_display.c @@ -370,7 +370,7 @@ 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->bo->offset; 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); @@ -814,6 +814,7 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc, else dspcntr |= DISPPLANE_16BPP; break; + case 24: case 32: dspcntr |= DISPPLANE_32BPP_NO_ALPHA; break; -- cgit v1.2.3 From 2476cb209ebbb11edace4bbce0cfaff4e1599dca Mon Sep 17 00:00:00 2001 From: Alan Hourihane Date: Fri, 22 Feb 2008 11:46:22 +0000 Subject: Implement short circuit for base change only Allow mode to be set with fb_id set to -1, meaning set the mode with the current fb (if we have one bound). Allow intelfb to hook back up it's fb if modesetting clears it (maybe temporary). Move any crtc->fb related register changes to set_base in intel_fb. General intelfb cleanups. --- linux-core/intel_display.c | 54 +++++++++++++++++++++++++++------------------- 1 file changed, 32 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 6a9d9808..003739d7 100644 --- a/linux-core/intel_display.c +++ b/linux-core/intel_display.c @@ -369,10 +369,42 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y) unsigned long Start, Offset; int dspbase = (pipe == 0 ? DSPABASE : DSPBBASE); int dspsurf = (pipe == 0 ? DSPASURF : DSPBSURF); + int dspstride = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE; + int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; + u32 dspcntr; + + /* no fb bound */ + if (!crtc->fb) { + DRM_INFO("No FB bound\n"); + return; + } Start = crtc->fb->bo->offset; Offset = y * crtc->fb->pitch + x * (crtc->fb->bits_per_pixel / 8); + I915_WRITE(dspstride, crtc->fb->pitch); + + dspcntr = I915_READ(dspcntr_reg); + 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 24: + case 32: + dspcntr |= DISPPLANE_32BPP_NO_ALPHA; + break; + default: + DRM_ERROR("Unknown color depth\n"); + return; + } + I915_WRITE(dspcntr_reg, dspcntr); + DRM_DEBUG("Writing base %08lX %08lX %d %d\n", Start, Offset, x, y); if (IS_I965G(dev)) { I915_WRITE(dspbase, Offset); @@ -691,7 +723,6 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc, 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; @@ -804,26 +835,6 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc, /* 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 24: - 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 @@ -925,7 +936,6 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc, ((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); /* pipesrc and dspsize control the size that is scaled from, which should * always be the user's requested size. */ -- cgit v1.2.3 From 73cb02b5430b3881cbce5fb4852ac573c11ff831 Mon Sep 17 00:00:00 2001 From: Alan Hourihane Date: Tue, 26 Feb 2008 15:21:44 +0000 Subject: DRM_INFO -> DRM_DEBUG --- linux-core/intel_display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux-core/intel_display.c') diff --git a/linux-core/intel_display.c b/linux-core/intel_display.c index 003739d7..4b48a0b2 100644 --- a/linux-core/intel_display.c +++ b/linux-core/intel_display.c @@ -375,7 +375,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y) /* no fb bound */ if (!crtc->fb) { - DRM_INFO("No FB bound\n"); + DRM_DEBUG("No FB bound\n"); return; } -- cgit v1.2.3 From 52748d17923b7e501b707b950227864c0b64d8a1 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 11 Mar 2008 11:49:27 +1000 Subject: drm: hopefully fix cursors on 965 --- linux-core/intel_display.c | 18 +++++++++++------- 1 file changed, 11 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 4b48a0b2..fa2b9bea 100644 --- a/linux-core/intel_display.c +++ b/linux-core/intel_display.c @@ -1007,7 +1007,7 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc, uint32_t control = (pipe == 0) ? CURSOR_A_CONTROL : CURSOR_B_CONTROL; uint32_t base = (pipe == 0) ? CURSOR_A_BASE : CURSOR_B_BASE; uint32_t temp; - size_t adder; + size_t addr; DRM_DEBUG("\n"); @@ -1039,17 +1039,21 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc, return -ENOMEM; } - adder = dev_priv->stolen_base + bo->offset; - intel_crtc->cursor_adder = adder; + if (dev_priv->cursor_needs_physical) + addr = dev_priv->stolen_base + bo->offset; + else + addr = bo->offset; + + intel_crtc->cursor_addr = addr; temp = 0; /* set the pipe for the cursor */ temp |= (pipe << 28); temp |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE; - DRM_DEBUG("cusror base %x\n", adder); + DRM_DEBUG("cusror base %x\n", addr); I915_WRITE(control, temp); - I915_WRITE(base, adder); + I915_WRITE(base, addr); return 0; } @@ -1075,7 +1079,7 @@ static int intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) temp |= ((x & CURSOR_POS_MASK) << CURSOR_X_SHIFT); temp |= ((y & CURSOR_POS_MASK) << CURSOR_Y_SHIFT); - adder = intel_crtc->cursor_adder; + adder = intel_crtc->cursor_addr; I915_WRITE((pipe == 0) ? CURSOR_A_POSITION : CURSOR_B_POSITION, temp); I915_WRITE((pipe == 0) ? CURSOR_A_BASE : CURSOR_B_BASE, adder); @@ -1241,7 +1245,7 @@ void intel_crtc_init(struct drm_device *dev, int pipe) intel_crtc->lut_b[i] = i; } - intel_crtc->cursor_adder = 0; + intel_crtc->cursor_addr = 0; crtc->driver_private = intel_crtc; } -- cgit v1.2.3 From 5a3ce06f3a3dfa9412b9660c1e1f35d24c815dbb Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Tue, 8 Apr 2008 12:42:23 -0700 Subject: Improved DRM sysfs support This patch ties outputs, output properties and hotplug events into the DRM core. Each output has a corresponding directory under the primary DRM device (usually card0) containing dpms, edid, modes, and connection status files. New hotplug change events occur when outputs are added or hotplug events are detected. --- linux-core/intel_display.c | 5 ++++- 1 file changed, 4 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 fa2b9bea..0615c1c4 100644 --- a/linux-core/intel_display.c +++ b/linux-core/intel_display.c @@ -1292,7 +1292,10 @@ static void intel_setup_outputs(struct drm_device *dev) intel_sdvo_init(dev, SDVOB); intel_sdvo_init(dev, SDVOC); } - +#if 0 + if (IS_I9XX(dev) && !IS_I915G(dev)) + intel_tv_init(dev); +#endif 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; -- cgit v1.2.3 From 6c92689dcc627886c32afd4eca8f0da25bd07183 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Wed, 9 Apr 2008 14:07:55 -0700 Subject: Port pipe reservation code for load detection TV out needs to do load detection, which means we have to find an available pipe to use for the detection. Port over the pipe reservation code for this purpose. --- linux-core/intel_display.c | 130 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 128 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 0615c1c4..13936ee2 100644 --- a/linux-core/intel_display.c +++ b/linux-core/intel_display.c @@ -567,6 +567,8 @@ static void intel_crtc_dpms(struct drm_crtc *crtc, int mode) DRM_ERROR("Can't update pipe %d in SAREA\n", pipe); break; } + + intel_crtc->dpms_mode = mode; } static bool intel_crtc_lock(struct drm_crtc *crtc) @@ -1097,6 +1099,129 @@ static void intel_crtc_gamma_set(struct drm_crtc *crtc, u16 red, u16 green, intel_crtc->lut_b[regno] = blue >> 8; } +/** + * Get a pipe with a simple mode set on it for doing load-based monitor + * detection. + * + * It will be up to the load-detect code to adjust the pipe as appropriate for + * its requirements. The pipe will be connected to no other outputs. + * + * Currently this code will only succeed if there is a pipe with no outputs + * configured for it. In the future, it could choose to temporarily disable + * some outputs to free up a pipe for its use. + * + * \return crtc, or NULL if no pipes are available. + */ + +/* VESA 640x480x72Hz mode to set on the pipe */ +static struct drm_display_mode load_detect_mode = { + DRM_MODE("640x480", DRM_MODE_TYPE_DEFAULT, 31500, 640, 664, + 704, 832, 0, 480, 489, 491, 520, 0, V_NHSYNC | V_NVSYNC), +}; + +struct drm_crtc *intel_get_load_detect_pipe(struct drm_output *output, + struct drm_display_mode *mode, + int *dpms_mode) +{ + struct drm_device *dev = output->dev; + struct intel_output *intel_output = output->driver_private; + struct intel_crtc *intel_crtc; + struct drm_crtc *possible_crtc; + struct drm_crtc *supported_crtc =NULL; + struct drm_crtc *crtc = NULL; + int i = 0; + + /* + * Algorithm gets a little messy: + * - if the output already has an assigned crtc, use it (but make + * sure it's on first) + * - try to find the first unused crtc that can drive this output, + * and use that if we find one + * - if there are no unused crtcs available, try to use the first + * one we found that supports the output + */ + + /* See if we already have a CRTC for this output */ + if (output->crtc) { + crtc = output->crtc; + /* Make sure the crtc and output are running */ + intel_crtc = crtc->driver_private; + *dpms_mode = intel_crtc->dpms_mode; + if (intel_crtc->dpms_mode != DPMSModeOn) { + crtc->funcs->dpms(crtc, DPMSModeOn); + output->funcs->dpms(output, DPMSModeOn); + } + return crtc; + } + + /* Find an unused one (if possible) */ + list_for_each_entry(possible_crtc, &dev->mode_config.crtc_list, head) { + i++; + if (!(output->possible_crtcs & (1 << i))) + continue; + if (!possible_crtc->enabled) { + crtc = possible_crtc; + break; + } + if (!supported_crtc) + supported_crtc = possible_crtc; + } + + /* + * If we didn't find an unused CRTC, use the first available one + * that can drive this output. + */ + if (!crtc) { + crtc = supported_crtc; + if (!crtc) + return NULL; + } + + output->crtc = crtc; + intel_output->load_detect_temp = TRUE; + + intel_crtc = crtc->driver_private; + *dpms_mode = intel_crtc->dpms_mode; + + if (!crtc->enabled) { + if (!mode) + mode = &load_detect_mode; + drm_crtc_set_mode(crtc, mode, 0, 0); + } else { + if (intel_crtc->dpms_mode != DPMSModeOn) + crtc->funcs->dpms(crtc, DPMSModeOn); + + /* Add this output to the crtc */ + output->funcs->mode_set(output, &crtc->mode, &crtc->mode); + output->funcs->commit(output); + } + /* let the output get through one full cycle before testing */ + intel_wait_for_vblank(dev); + + return crtc; +} + +void intel_release_load_detect_pipe(struct drm_output *output, int dpms_mode) +{ + struct drm_device *dev = output->dev; + struct intel_output *intel_output = output->driver_private; + struct drm_crtc *crtc = output->crtc; + + if (intel_output->load_detect_temp) { + output->crtc = NULL; + intel_output->load_detect_temp = FALSE; + crtc->enabled = drm_crtc_in_use(crtc); + drm_disable_unused_functions(dev); + } + + /* Switch crtc and output back off if necessary */ + if (crtc->enabled && dpms_mode != DPMSModeOn) { + if (output->crtc == crtc) + output->funcs->dpms(output, dpms_mode); + crtc->funcs->dpms(crtc, dpms_mode); + } +} + /* 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) { @@ -1246,6 +1371,7 @@ void intel_crtc_init(struct drm_device *dev, int pipe) } intel_crtc->cursor_addr = 0; + intel_crtc->dpms_mode = DPMSModeOff; crtc->driver_private = intel_crtc; } @@ -1292,10 +1418,10 @@ static void intel_setup_outputs(struct drm_device *dev) intel_sdvo_init(dev, SDVOB); intel_sdvo_init(dev, SDVOC); } -#if 0 + if (IS_I9XX(dev) && !IS_I915G(dev)) intel_tv_init(dev); -#endif + 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; -- cgit v1.2.3 From ebd154497383e3bcb6b5c6284148aff3633a5d99 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Thu, 10 Apr 2008 11:27:39 -0700 Subject: Fix masking in get_load_detect_pipe Start i at -1 so that the masking works right. --- linux-core/intel_display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux-core/intel_display.c') diff --git a/linux-core/intel_display.c b/linux-core/intel_display.c index 13936ee2..5ca33f7f 100644 --- a/linux-core/intel_display.c +++ b/linux-core/intel_display.c @@ -1129,7 +1129,7 @@ struct drm_crtc *intel_get_load_detect_pipe(struct drm_output *output, struct drm_crtc *possible_crtc; struct drm_crtc *supported_crtc =NULL; struct drm_crtc *crtc = NULL; - int i = 0; + int i = -1; /* * Algorithm gets a little messy: -- cgit v1.2.3 From bee546ad696e3157b878dfa90e563786b5b5c7ac Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Thu, 10 Apr 2008 19:02:53 -0700 Subject: Remove structure fields & code Cleanup some random cruft left over from the initial port. --- linux-core/intel_display.c | 21 --------------------- 1 file changed, 21 deletions(-) (limited to 'linux-core/intel_display.c') diff --git a/linux-core/intel_display.c b/linux-core/intel_display.c index 5ca33f7f..6aa61256 100644 --- a/linux-core/intel_display.c +++ b/linux-core/intel_display.c @@ -571,25 +571,6 @@ static void intel_crtc_dpms(struct drm_crtc *crtc, int mode) intel_crtc->dpms_mode = mode; } -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); @@ -1334,8 +1315,6 @@ struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev, 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, .mode_set_base = intel_pipe_set_base, -- cgit v1.2.3 From 21a93915d8a21518c5da76a739f9459ed7f99d6a Mon Sep 17 00:00:00 2001 From: Hong Liu Date: Thu, 17 Apr 2008 16:51:00 +0800 Subject: Porting DVO stuff Ported from Xorg intel 2d driver. Changed interfaces definitions, which needed to be changed later if other device wants to use these DVO stuff. --- 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 6aa61256..46abb90c 100644 --- a/linux-core/intel_display.c +++ b/linux-core/intel_display.c @@ -1396,7 +1396,8 @@ static void intel_setup_outputs(struct drm_device *dev) if (IS_I9XX(dev)) { intel_sdvo_init(dev, SDVOB); intel_sdvo_init(dev, SDVOC); - } + } else + intel_dvo_init(dev); if (IS_I9XX(dev) && !IS_I915G(dev)) intel_tv_init(dev); -- cgit v1.2.3 From 74a49aea6104ebea7525a04760ef21646a3ffaf4 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 8 May 2008 16:10:06 +1000 Subject: intel: set correct limits on screen width/height from DDX --- linux-core/intel_display.c | 9 +++++++-- 1 file changed, 7 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 46abb90c..f66570c2 100644 --- a/linux-core/intel_display.c +++ b/linux-core/intel_display.c @@ -1448,8 +1448,13 @@ void intel_modeset_init(struct drm_device *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_I965G(dev)) { + dev->mode_config.max_width = 8192; + dev->mode_config.max_height = 8192; + } else { + dev->mode_config.max_width = 2048; + dev->mode_config.max_height = 2048; + } /* set memory base */ if (IS_I9XX(dev)) -- cgit v1.2.3 From ee631e1b8604a176b9118396998ce5bfc6475dae Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Tue, 13 May 2008 14:44:17 -0700 Subject: i915: register definition & header file cleanup It would be nice if one day the DRM driver was the canonical source for register definitions and core macros. To that end, this patch cleans things up quite a bit, removing redundant definitions (some with different names referring to the same register) and generally tidying up the header file. --- linux-core/intel_display.c | 52 +++++++++++++++------------------------------- 1 file changed, 17 insertions(+), 35 deletions(-) (limited to 'linux-core/intel_display.c') diff --git a/linux-core/intel_display.c b/linux-core/intel_display.c index f66570c2..273f76d0 100644 --- a/linux-core/intel_display.c +++ b/linux-core/intel_display.c @@ -367,7 +367,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y) struct intel_crtc *intel_crtc = crtc->driver_private; int pipe = intel_crtc->pipe; unsigned long Start, Offset; - int dspbase = (pipe == 0 ? DSPABASE : DSPBBASE); + int dspbase = (pipe == 0 ? DSPAADDR : DSPBADDR); int dspsurf = (pipe == 0 ? DSPASURF : DSPBSURF); int dspstride = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE; int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; @@ -456,7 +456,7 @@ static void intel_crtc_dpms(struct drm_crtc *crtc, int mode) 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 dspbase_reg = (pipe == 0) ? DSPAADDR : DSPBADDR; int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; u32 temp; bool enabled; @@ -617,16 +617,16 @@ static int intel_get_core_clock_speed(struct drm_device *dev) else if (IS_I915GM(dev)) { u16 gcfgc = 0; - pci_read_config_word(dev->pdev, I915_GCFGC, &gcfgc); + pci_read_config_word(dev->pdev, GCFGC, &gcfgc); - if (gcfgc & I915_LOW_FREQUENCY_ENABLE) + if (gcfgc & GC_LOW_FREQUENCY_ENABLE) return 133000; else { - switch (gcfgc & I915_DISPLAY_CLOCK_MASK) { - case I915_DISPLAY_CLOCK_333_MHZ: + switch (gcfgc & GC_DISPLAY_CLOCK_MASK) { + case GC_DISPLAY_CLOCK_333_MHZ: return 333000; default: - case I915_DISPLAY_CLOCK_190_200_MHZ: + case GC_DISPLAY_CLOCK_190_200_MHZ: return 190000; } } @@ -635,20 +635,20 @@ static int intel_get_core_clock_speed(struct drm_device *dev) 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); + u16 hpllcc = pciReadWord(bridge, 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: + switch (hpllcc & GC_CLOCK_CONTROL_MASK) { + case GC_CLOCK_133_200: + case GC_CLOCK_100_200: return 200000; - case I855_CLOCK_166_250: + case GC_CLOCK_166_250: return 250000; - case I855_CLOCK_100_133: + case GC_CLOCK_100_133: return 133000; } } else /* 852, 830 */ @@ -961,24 +961,6 @@ void intel_crtc_load_lut(struct drm_crtc *crtc) } } -#define CURSOR_A_CONTROL 0x70080 -#define CURSOR_A_BASE 0x70084 -#define CURSOR_A_POSITION 0x70088 - -#define CURSOR_B_CONTROL 0x700C0 -#define CURSOR_B_BASE 0x700C4 -#define CURSOR_B_POSITION 0x700C8 - -#define CURSOR_MODE_DISABLE 0x00 -#define CURSOR_MODE_64_32B_AX 0x07 -#define CURSOR_MODE_64_ARGB_AX ((1 << 5) | CURSOR_MODE_64_32B_AX) -#define MCURSOR_GAMMA_ENABLE (1 << 26) - -#define CURSOR_POS_MASK 0x007FF -#define CURSOR_POS_SIGN 0x8000 -#define CURSOR_X_SHIFT 0 -#define CURSOR_Y_SHIFT 16 - static int intel_crtc_cursor_set(struct drm_crtc *crtc, struct drm_buffer_object *bo, uint32_t width, uint32_t height) @@ -987,8 +969,8 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc, struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = crtc->driver_private; int pipe = intel_crtc->pipe; - uint32_t control = (pipe == 0) ? CURSOR_A_CONTROL : CURSOR_B_CONTROL; - uint32_t base = (pipe == 0) ? CURSOR_A_BASE : CURSOR_B_BASE; + uint32_t control = (pipe == 0) ? CURACNTR : CURBCNTR; + uint32_t base = (pipe == 0) ? CURABASE : CURBBASE; uint32_t temp; size_t addr; @@ -1063,8 +1045,8 @@ static int intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) temp |= ((y & CURSOR_POS_MASK) << CURSOR_Y_SHIFT); adder = intel_crtc->cursor_addr; - I915_WRITE((pipe == 0) ? CURSOR_A_POSITION : CURSOR_B_POSITION, temp); - I915_WRITE((pipe == 0) ? CURSOR_A_BASE : CURSOR_B_BASE, adder); + I915_WRITE((pipe == 0) ? CURAPOS : CURBPOS, temp); + I915_WRITE((pipe == 0) ? CURABASE : CURBBASE, adder); return 0; } -- cgit v1.2.3 From b4d8cda8e6d6ea319ab7c471d6d68b8af8693cfe Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Fri, 23 May 2008 18:41:58 -0700 Subject: drm_mode_debug_printmodeline doesn't need struct drm_device * Makes printing modelines from some routines easier. --- linux-core/intel_display.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'linux-core/intel_display.c') diff --git a/linux-core/intel_display.c b/linux-core/intel_display.c index 273f76d0..e7162c2c 100644 --- a/linux-core/intel_display.c +++ b/linux-core/intel_display.c @@ -846,7 +846,7 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc, I915_WRITE(PFIT_CONTROL, 0); DRM_DEBUG("Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B'); - drm_mode_debug_printmodeline(dev, mode); + drm_mode_debug_printmodeline(mode); #if 0 if (!xf86ModesEqual(mode, adjusted_mode)) { @@ -1015,8 +1015,6 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc, temp |= (pipe << 28); temp |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE; - DRM_DEBUG("cusror base %x\n", addr); - I915_WRITE(control, temp); I915_WRITE(base, addr); -- cgit v1.2.3 From df8cd54286fbae5903d8ede390ec4a11cb6c4b6c Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 29 May 2008 14:02:14 +1000 Subject: modesetting: reorganise code into core and helper functions. This splits a lot of the core modesetting code out into a file of helper functions, that are only called from themselves and/or the driver. The driver gets called into more often or can call these functions from itself if it is a helper using driver. I've broken framebuffer resize doing this but I didn't like the API for that in any case. --- linux-core/intel_display.c | 29 ++++++++++++++++++++++------- 1 file changed, 22 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 e7162c2c..a2307a3d 100644 --- a/linux-core/intel_display.c +++ b/linux-core/intel_display.c @@ -30,6 +30,8 @@ #include "i915_drm.h" #include "i915_drv.h" +#include "drm_crtc_helper.h" + bool intel_pipe_has_type (struct drm_crtc *crtc, int type); typedef struct { @@ -1090,6 +1092,7 @@ struct drm_crtc *intel_get_load_detect_pipe(struct drm_output *output, struct drm_crtc *possible_crtc; struct drm_crtc *supported_crtc =NULL; struct drm_crtc *crtc = NULL; + struct drm_output_helper_funcs *output_funcs; int i = -1; /* @@ -1147,14 +1150,15 @@ struct drm_crtc *intel_get_load_detect_pipe(struct drm_output *output, if (!crtc->enabled) { if (!mode) mode = &load_detect_mode; - drm_crtc_set_mode(crtc, mode, 0, 0); + drm_crtc_helper_set_mode(crtc, mode, 0, 0); } else { if (intel_crtc->dpms_mode != DPMSModeOn) crtc->funcs->dpms(crtc, DPMSModeOn); + output_funcs = output->helper_private; /* Add this output to the crtc */ - output->funcs->mode_set(output, &crtc->mode, &crtc->mode); - output->funcs->commit(output); + output_funcs->mode_set(output, &crtc->mode, &crtc->mode); + output_funcs->commit(output); } /* let the output get through one full cycle before testing */ intel_wait_for_vblank(dev); @@ -1293,16 +1297,20 @@ struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev, return mode; } -static const struct drm_crtc_funcs intel_crtc_funcs = { - .dpms = intel_crtc_dpms, +static const struct drm_crtc_helper_funcs intel_helper_funcs = { .mode_fixup = intel_crtc_mode_fixup, .mode_set = intel_crtc_mode_set, .mode_set_base = intel_pipe_set_base, + .prepare = intel_crtc_prepare, + .commit = intel_crtc_commit, +}; + +static const struct drm_crtc_funcs intel_crtc_funcs = { + .dpms = intel_crtc_dpms, .cursor_set = intel_crtc_cursor_set, .cursor_move = intel_crtc_cursor_move, .gamma_set = intel_crtc_gamma_set, - .prepare = intel_crtc_prepare, - .commit = intel_crtc_commit, + .set_config = drm_crtc_helper_set_config, }; @@ -1331,6 +1339,7 @@ void intel_crtc_init(struct drm_device *dev, int pipe) intel_crtc->cursor_addr = 0; intel_crtc->dpms_mode = DPMSModeOff; + drm_crtc_helper_add(crtc, &intel_helper_funcs); crtc->driver_private = intel_crtc; } @@ -1418,6 +1427,10 @@ static void intel_setup_outputs(struct drm_device *dev) } } +static const struct drm_mode_config_funcs intel_mode_funcs = { + .resize_fb = NULL, +}; + void intel_modeset_init(struct drm_device *dev) { int num_pipe; @@ -1428,6 +1441,8 @@ void intel_modeset_init(struct drm_device *dev) dev->mode_config.min_width = 0; dev->mode_config.min_height = 0; + dev->mode_config.funcs = (void *)&intel_mode_funcs; + if (IS_I965G(dev)) { dev->mode_config.max_width = 8192; dev->mode_config.max_height = 8192; -- cgit v1.2.3 From 98c5cf7f6fc51f1a8f5f90b3895009cd38dd8f22 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 30 May 2008 11:25:41 +1000 Subject: modesetting: reorganise out crtc/outputs are allocated. Use subclassing from the drivers to allocate the objects. This saves two objects being allocated for each crtc/output and generally makes exit paths cleaner. --- linux-core/intel_display.c | 64 ++++++++++++++++++++++++---------------------- 1 file changed, 33 insertions(+), 31 deletions(-) (limited to 'linux-core/intel_display.c') diff --git a/linux-core/intel_display.c b/linux-core/intel_display.c index a2307a3d..abcf5f5e 100644 --- a/linux-core/intel_display.c +++ b/linux-core/intel_display.c @@ -229,7 +229,7 @@ bool intel_pipe_has_type (struct drm_crtc *crtc, int type) 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; + struct intel_output *intel_output = to_intel_output(l_entry); if (intel_output->type == type) return true; } @@ -344,7 +344,7 @@ intel_set_vblank(struct drm_device *dev) int vbl_pipe = 0; list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { - intel_crtc = crtc->driver_private; + intel_crtc = to_intel_crtc(crtc); if (crtc->enabled) vbl_pipe |= (1<pipe); @@ -366,7 +366,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y) struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_master_private *master_priv; - struct intel_crtc *intel_crtc = crtc->driver_private; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); int pipe = intel_crtc->pipe; unsigned long Start, Offset; int dspbase = (pipe == 0 ? DSPAADDR : DSPBADDR); @@ -454,7 +454,7 @@ static void intel_crtc_dpms(struct drm_crtc *crtc, int mode) struct drm_device *dev = crtc->dev; struct drm_i915_master_private *master_priv; struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_crtc *intel_crtc = crtc->driver_private; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); int pipe = intel_crtc->pipe; int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B; int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; @@ -694,7 +694,7 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc, { struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_crtc *intel_crtc = crtc->driver_private; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); int pipe = intel_crtc->pipe; int fp_reg = (pipe == 0) ? FPA0 : FPB0; int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B; @@ -719,7 +719,7 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc, struct drm_output *output; list_for_each_entry(output, &mode_config->output_list, head) { - struct intel_output *intel_output = output->driver_private; + struct intel_output *intel_output = to_intel_output(output); if (output->crtc != crtc) continue; @@ -947,7 +947,7 @@ void intel_crtc_load_lut(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_crtc *intel_crtc = crtc->driver_private; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); int palreg = (intel_crtc->pipe == 0) ? PALETTE_A : PALETTE_B; int i; @@ -969,7 +969,7 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc, { struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_crtc *intel_crtc = crtc->driver_private; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); int pipe = intel_crtc->pipe; uint32_t control = (pipe == 0) ? CURACNTR : CURBCNTR; uint32_t base = (pipe == 0) ? CURABASE : CURBBASE; @@ -1027,7 +1027,7 @@ static int intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) { struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_crtc *intel_crtc = crtc->driver_private; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); int pipe = intel_crtc->pipe; uint32_t temp = 0; uint32_t adder; @@ -1055,8 +1055,8 @@ static int intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) static void intel_crtc_gamma_set(struct drm_crtc *crtc, u16 red, u16 green, u16 blue, int regno) { - struct intel_crtc *intel_crtc = crtc->driver_private; - + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + intel_crtc->lut_r[regno] = red >> 8; intel_crtc->lut_g[regno] = green >> 8; intel_crtc->lut_b[regno] = blue >> 8; @@ -1087,7 +1087,7 @@ struct drm_crtc *intel_get_load_detect_pipe(struct drm_output *output, int *dpms_mode) { struct drm_device *dev = output->dev; - struct intel_output *intel_output = output->driver_private; + struct intel_output *intel_output = to_intel_output(output); struct intel_crtc *intel_crtc; struct drm_crtc *possible_crtc; struct drm_crtc *supported_crtc =NULL; @@ -1109,7 +1109,7 @@ struct drm_crtc *intel_get_load_detect_pipe(struct drm_output *output, if (output->crtc) { crtc = output->crtc; /* Make sure the crtc and output are running */ - intel_crtc = crtc->driver_private; + intel_crtc = to_intel_crtc(crtc); *dpms_mode = intel_crtc->dpms_mode; if (intel_crtc->dpms_mode != DPMSModeOn) { crtc->funcs->dpms(crtc, DPMSModeOn); @@ -1144,7 +1144,7 @@ struct drm_crtc *intel_get_load_detect_pipe(struct drm_output *output, output->crtc = crtc; intel_output->load_detect_temp = TRUE; - intel_crtc = crtc->driver_private; + intel_crtc = to_intel_crtc(crtc); *dpms_mode = intel_crtc->dpms_mode; if (!crtc->enabled) { @@ -1169,7 +1169,7 @@ struct drm_crtc *intel_get_load_detect_pipe(struct drm_output *output, void intel_release_load_detect_pipe(struct drm_output *output, int dpms_mode) { struct drm_device *dev = output->dev; - struct intel_output *intel_output = output->driver_private; + struct intel_output *intel_output = to_intel_output(output); struct drm_crtc *crtc = output->crtc; if (intel_output->load_detect_temp) { @@ -1191,7 +1191,7 @@ void intel_release_load_detect_pipe(struct drm_output *output, int dpms_mode) static int intel_crtc_clock_get(struct drm_device *dev, struct drm_crtc *crtc) { struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_crtc *intel_crtc = crtc->driver_private; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); int pipe = intel_crtc->pipe; u32 dpll = I915_READ((pipe == 0) ? DPLL_A : DPLL_B); u32 fp; @@ -1269,7 +1269,7 @@ struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev, struct drm_crtc *crtc) { struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_crtc *intel_crtc = crtc->driver_private; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); int pipe = intel_crtc->pipe; struct drm_display_mode *mode; int htot = I915_READ((pipe == 0) ? HTOTAL_A : HTOTAL_B); @@ -1297,6 +1297,14 @@ struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev, return mode; } +static void intel_crtc_destroy(struct drm_crtc *crtc) +{ + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + + drm_crtc_cleanup(crtc); + kfree(intel_crtc); +} + static const struct drm_crtc_helper_funcs intel_helper_funcs = { .mode_fixup = intel_crtc_mode_fixup, .mode_set = intel_crtc_mode_set, @@ -1311,24 +1319,20 @@ static const struct drm_crtc_funcs intel_crtc_funcs = { .cursor_move = intel_crtc_cursor_move, .gamma_set = intel_crtc_gamma_set, .set_config = drm_crtc_helper_set_config, + .destroy = intel_crtc_destroy, }; void intel_crtc_init(struct drm_device *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 = kzalloc(sizeof(struct intel_crtc), GFP_KERNEL); - if (intel_crtc == NULL) { - kfree(crtc); + if (intel_crtc == NULL) return; - } + + drm_crtc_init(dev, &intel_crtc->base, &intel_crtc_funcs); intel_crtc->pipe = pipe; for (i = 0; i < 256; i++) { @@ -1339,9 +1343,7 @@ void intel_crtc_init(struct drm_device *dev, int pipe) intel_crtc->cursor_addr = 0; intel_crtc->dpms_mode = DPMSModeOff; - drm_crtc_helper_add(crtc, &intel_helper_funcs); - - crtc->driver_private = intel_crtc; + drm_crtc_helper_add(&intel_crtc->base, &intel_helper_funcs); } struct drm_crtc *intel_get_crtc_from_pipe(struct drm_device *dev, int pipe) @@ -1349,7 +1351,7 @@ struct drm_crtc *intel_get_crtc_from_pipe(struct drm_device *dev, int pipe) struct drm_crtc *crtc = NULL; list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { - struct intel_crtc *intel_crtc = crtc->driver_private; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); if (intel_crtc->pipe == pipe) break; } @@ -1363,7 +1365,7 @@ int intel_output_clones(struct drm_device *dev, int type_mask) int entry = 0; list_for_each_entry(output, &dev->mode_config.output_list, head) { - struct intel_output *intel_output = output->driver_private; + struct intel_output *intel_output = to_intel_output(output); if (type_mask & (1 << intel_output->type)) index_mask |= (1 << entry); entry++; @@ -1392,7 +1394,7 @@ static void intel_setup_outputs(struct drm_device *dev) intel_tv_init(dev); list_for_each_entry(output, &dev->mode_config.output_list, head) { - struct intel_output *intel_output = output->driver_private; + struct intel_output *intel_output = to_intel_output(output); int crtc_mask = 0, clone_mask = 0; /* valid crtcs */ -- cgit v1.2.3 From 9d38448ed33aaff324cc4bbe1e0878593e97d07d Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 30 May 2008 15:03:12 +1000 Subject: modesetting: the great renaming. Okay we have crtc, encoder and connectors. No more outputs exposed beyond driver internals I've broken intel tv connector stuff. Really for TV we should have one TV connector, with a sub property for the type of signal been driven over it --- linux-core/intel_display.c | 98 +++++++++++++++++++++++----------------------- 1 file changed, 49 insertions(+), 49 deletions(-) (limited to 'linux-core/intel_display.c') diff --git a/linux-core/intel_display.c b/linux-core/intel_display.c index abcf5f5e..7fb1ea5f 100644 --- a/linux-core/intel_display.c +++ b/linux-core/intel_display.c @@ -225,9 +225,9 @@ bool intel_pipe_has_type (struct drm_crtc *crtc, int type) { struct drm_device *dev = crtc->dev; struct drm_mode_config *mode_config = &dev->mode_config; - struct drm_output *l_entry; + struct drm_connector *l_entry; - list_for_each_entry(l_entry, &mode_config->output_list, head) { + list_for_each_entry(l_entry, &mode_config->connector_list, head) { if (l_entry->crtc == crtc) { struct intel_output *intel_output = to_intel_output(l_entry); if (intel_output->type == type) @@ -240,7 +240,7 @@ bool intel_pipe_has_type (struct drm_crtc *crtc, int type) #define INTELPllInvalid(s) { /* ErrorF (s) */; return false; } /** * Returns whether the given set of divisors are valid for a given refclk with - * the given outputs. + * the given connectors. */ static bool intel_PLL_is_valid(struct drm_crtc *crtc, intel_clock_t *clock) @@ -264,7 +264,7 @@ static bool intel_PLL_is_valid(struct drm_crtc *crtc, intel_clock_t *clock) 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. + * connector, etc., rather than just a single range. */ if (clock->dot < limit->dot.min || limit->dot.max < clock->dot) INTELPllInvalid ("dot out of range\n"); @@ -583,16 +583,16 @@ static void intel_crtc_commit (struct drm_crtc *crtc) crtc->funcs->dpms(crtc, DPMSModeOn); } -void intel_output_prepare (struct drm_output *output) +void intel_connector_prepare (struct drm_connector *connector) { /* lvds has its own version of prepare see intel_lvds_prepare */ - output->funcs->dpms(output, DPMSModeOff); + connector->funcs->dpms(connector, DPMSModeOff); } -void intel_output_commit (struct drm_output *output) +void intel_connector_commit (struct drm_connector *connector) { /* lvds has its own version of commit see intel_lvds_commit */ - output->funcs->dpms(output, DPMSModeOn); + connector->funcs->dpms(connector, DPMSModeOn); } static bool intel_crtc_mode_fixup(struct drm_crtc *crtc, @@ -716,12 +716,12 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc, bool ok, is_sdvo = false, is_dvo = false; bool is_crt = false, is_lvds = false, is_tv = false; struct drm_mode_config *mode_config = &dev->mode_config; - struct drm_output *output; + struct drm_connector *connector; - list_for_each_entry(output, &mode_config->output_list, head) { - struct intel_output *intel_output = to_intel_output(output); + list_for_each_entry(connector, &mode_config->connector_list, head) { + struct intel_output *intel_output = to_intel_output(connector); - if (output->crtc != crtc) + if (connector->crtc != crtc) continue; switch (intel_output->type) { @@ -1082,38 +1082,38 @@ static struct drm_display_mode load_detect_mode = { 704, 832, 0, 480, 489, 491, 520, 0, V_NHSYNC | V_NVSYNC), }; -struct drm_crtc *intel_get_load_detect_pipe(struct drm_output *output, +struct drm_crtc *intel_get_load_detect_pipe(struct drm_connector *connector, struct drm_display_mode *mode, int *dpms_mode) { - struct drm_device *dev = output->dev; - struct intel_output *intel_output = to_intel_output(output); + struct drm_device *dev = connector->dev; + struct intel_output *intel_output = to_intel_output(connector); struct intel_crtc *intel_crtc; struct drm_crtc *possible_crtc; struct drm_crtc *supported_crtc =NULL; struct drm_crtc *crtc = NULL; - struct drm_output_helper_funcs *output_funcs; + struct drm_connector_helper_funcs *connector_funcs; int i = -1; /* * Algorithm gets a little messy: - * - if the output already has an assigned crtc, use it (but make + * - if the connector already has an assigned crtc, use it (but make * sure it's on first) - * - try to find the first unused crtc that can drive this output, + * - try to find the first unused crtc that can drive this connector, * and use that if we find one * - if there are no unused crtcs available, try to use the first - * one we found that supports the output + * one we found that supports the connector */ - /* See if we already have a CRTC for this output */ - if (output->crtc) { - crtc = output->crtc; - /* Make sure the crtc and output are running */ + /* See if we already have a CRTC for this connector */ + if (connector->crtc) { + crtc = connector->crtc; + /* Make sure the crtc and connector are running */ intel_crtc = to_intel_crtc(crtc); *dpms_mode = intel_crtc->dpms_mode; if (intel_crtc->dpms_mode != DPMSModeOn) { crtc->funcs->dpms(crtc, DPMSModeOn); - output->funcs->dpms(output, DPMSModeOn); + connector->funcs->dpms(connector, DPMSModeOn); } return crtc; } @@ -1121,7 +1121,7 @@ struct drm_crtc *intel_get_load_detect_pipe(struct drm_output *output, /* Find an unused one (if possible) */ list_for_each_entry(possible_crtc, &dev->mode_config.crtc_list, head) { i++; - if (!(output->possible_crtcs & (1 << i))) + if (!(connector->possible_crtcs & (1 << i))) continue; if (!possible_crtc->enabled) { crtc = possible_crtc; @@ -1133,7 +1133,7 @@ struct drm_crtc *intel_get_load_detect_pipe(struct drm_output *output, /* * If we didn't find an unused CRTC, use the first available one - * that can drive this output. + * that can drive this connector. */ if (!crtc) { crtc = supported_crtc; @@ -1141,7 +1141,7 @@ struct drm_crtc *intel_get_load_detect_pipe(struct drm_output *output, return NULL; } - output->crtc = crtc; + connector->crtc = crtc; intel_output->load_detect_temp = TRUE; intel_crtc = to_intel_crtc(crtc); @@ -1155,25 +1155,25 @@ struct drm_crtc *intel_get_load_detect_pipe(struct drm_output *output, if (intel_crtc->dpms_mode != DPMSModeOn) crtc->funcs->dpms(crtc, DPMSModeOn); - output_funcs = output->helper_private; - /* Add this output to the crtc */ - output_funcs->mode_set(output, &crtc->mode, &crtc->mode); - output_funcs->commit(output); + connector_funcs = connector->helper_private; + /* Add this connector to the crtc */ + connector_funcs->mode_set(connector, &crtc->mode, &crtc->mode); + connector_funcs->commit(connector); } - /* let the output get through one full cycle before testing */ + /* let the connector get through one full cycle before testing */ intel_wait_for_vblank(dev); return crtc; } -void intel_release_load_detect_pipe(struct drm_output *output, int dpms_mode) +void intel_release_load_detect_pipe(struct drm_connector *connector, int dpms_mode) { - struct drm_device *dev = output->dev; - struct intel_output *intel_output = to_intel_output(output); - struct drm_crtc *crtc = output->crtc; + struct drm_device *dev = connector->dev; + struct intel_output *intel_output = to_intel_output(connector); + struct drm_crtc *crtc = connector->crtc; if (intel_output->load_detect_temp) { - output->crtc = NULL; + connector->crtc = NULL; intel_output->load_detect_temp = FALSE; crtc->enabled = drm_crtc_in_use(crtc); drm_disable_unused_functions(dev); @@ -1181,8 +1181,8 @@ void intel_release_load_detect_pipe(struct drm_output *output, int dpms_mode) /* Switch crtc and output back off if necessary */ if (crtc->enabled && dpms_mode != DPMSModeOn) { - if (output->crtc == crtc) - output->funcs->dpms(output, dpms_mode); + if (connector->crtc == crtc) + connector->funcs->dpms(connector, dpms_mode); crtc->funcs->dpms(crtc, dpms_mode); } } @@ -1257,7 +1257,7 @@ static int intel_crtc_clock_get(struct drm_device *dev, struct drm_crtc *crtc) } /* XXX: It would be nice to validate the clocks, but we can't reuse - * i830PllIsValid() because it relies on the xf86_config output + * i830PllIsValid() because it relies on the xf86_config connector * configuration being accurate, which it isn't necessarily. */ @@ -1358,14 +1358,14 @@ struct drm_crtc *intel_get_crtc_from_pipe(struct drm_device *dev, int pipe) return crtc; } -int intel_output_clones(struct drm_device *dev, int type_mask) +int intel_connector_clones(struct drm_device *dev, int type_mask) { int index_mask = 0; - struct drm_output *output; + struct drm_connector *connector; int entry = 0; - list_for_each_entry(output, &dev->mode_config.output_list, head) { - struct intel_output *intel_output = to_intel_output(output); + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + struct intel_output *intel_output = to_intel_output(connector); if (type_mask & (1 << intel_output->type)) index_mask |= (1 << entry); entry++; @@ -1376,7 +1376,7 @@ int intel_output_clones(struct drm_device *dev, int type_mask) static void intel_setup_outputs(struct drm_device *dev) { - struct drm_output *output; + struct drm_connector *connector; intel_crt_init(dev); @@ -1393,8 +1393,8 @@ static void intel_setup_outputs(struct drm_device *dev) if (IS_I9XX(dev) && !IS_I915G(dev)) intel_tv_init(dev); - list_for_each_entry(output, &dev->mode_config.output_list, head) { - struct intel_output *intel_output = to_intel_output(output); + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + struct intel_output *intel_output = to_intel_output(connector); int crtc_mask = 0, clone_mask = 0; /* valid crtcs */ @@ -1424,8 +1424,8 @@ static void intel_setup_outputs(struct drm_device *dev) clone_mask = (1 << INTEL_OUTPUT_TVOUT); break; } - output->possible_crtcs = crtc_mask; - output->possible_clones = intel_output_clones(dev, clone_mask); + connector->possible_crtcs = crtc_mask; + connector->possible_clones = intel_connector_clones(dev, clone_mask); } } -- cgit v1.2.3 From 5d47185eb69d73dd7e6ee3ddde4d0c7642c2d5b7 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 30 May 2008 15:32:58 +1000 Subject: drm: switch possible crtc/clones over to encoders --- linux-core/intel_display.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'linux-core/intel_display.c') diff --git a/linux-core/intel_display.c b/linux-core/intel_display.c index 7fb1ea5f..f0cbc385 100644 --- a/linux-core/intel_display.c +++ b/linux-core/intel_display.c @@ -1091,6 +1091,7 @@ struct drm_crtc *intel_get_load_detect_pipe(struct drm_connector *connector, struct intel_crtc *intel_crtc; struct drm_crtc *possible_crtc; struct drm_crtc *supported_crtc =NULL; + struct drm_encoder *encoder = NULL; struct drm_crtc *crtc = NULL; struct drm_connector_helper_funcs *connector_funcs; int i = -1; @@ -1118,10 +1119,14 @@ struct drm_crtc *intel_get_load_detect_pipe(struct drm_connector *connector, return crtc; } + list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) + if (encoder->id == connector->current_encoder_id) + break; + /* Find an unused one (if possible) */ list_for_each_entry(possible_crtc, &dev->mode_config.crtc_list, head) { i++; - if (!(connector->possible_crtcs & (1 << i))) + if (!(encoder->possible_crtcs & (1 << i))) continue; if (!possible_crtc->enabled) { crtc = possible_crtc; @@ -1395,6 +1400,7 @@ static void intel_setup_outputs(struct drm_device *dev) list_for_each_entry(connector, &dev->mode_config.connector_list, head) { struct intel_output *intel_output = to_intel_output(connector); + struct drm_encoder *encoder = &intel_output->enc; int crtc_mask = 0, clone_mask = 0; /* valid crtcs */ @@ -1424,8 +1430,8 @@ static void intel_setup_outputs(struct drm_device *dev) clone_mask = (1 << INTEL_OUTPUT_TVOUT); break; } - connector->possible_crtcs = crtc_mask; - connector->possible_clones = intel_connector_clones(dev, clone_mask); + encoder->possible_crtcs = crtc_mask; + encoder->possible_clones = intel_connector_clones(dev, clone_mask); } } -- cgit v1.2.3 From e439e74776b215d70d8e34e8aa9cea22179dcbc6 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 2 Jun 2008 10:05:54 +1000 Subject: drm/modesetting: another re-org of some internals. Move dpms into the helper functions. Move crtc into the encoder. Move disable unused functions into the helper. --- linux-core/intel_display.c | 78 ++++++++++++++++++++++++---------------------- 1 file changed, 41 insertions(+), 37 deletions(-) (limited to 'linux-core/intel_display.c') diff --git a/linux-core/intel_display.c b/linux-core/intel_display.c index f0cbc385..c1cb2bff 100644 --- a/linux-core/intel_display.c +++ b/linux-core/intel_display.c @@ -228,7 +228,7 @@ bool intel_pipe_has_type (struct drm_crtc *crtc, int type) struct drm_connector *l_entry; list_for_each_entry(l_entry, &mode_config->connector_list, head) { - if (l_entry->crtc == crtc) { + if (l_entry->encoder->crtc == crtc) { struct intel_output *intel_output = to_intel_output(l_entry); if (intel_output->type == type) return true; @@ -575,24 +575,28 @@ static void intel_crtc_dpms(struct drm_crtc *crtc, int mode) static void intel_crtc_prepare (struct drm_crtc *crtc) { - crtc->funcs->dpms(crtc, DPMSModeOff); + struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; + crtc_funcs->dpms(crtc, DPMSModeOff); } static void intel_crtc_commit (struct drm_crtc *crtc) { - crtc->funcs->dpms(crtc, DPMSModeOn); + struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; + crtc_funcs->dpms(crtc, DPMSModeOn); } -void intel_connector_prepare (struct drm_connector *connector) +void intel_encoder_prepare (struct drm_encoder *encoder) { + struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private; /* lvds has its own version of prepare see intel_lvds_prepare */ - connector->funcs->dpms(connector, DPMSModeOff); + encoder_funcs->dpms(encoder, DPMSModeOff); } -void intel_connector_commit (struct drm_connector *connector) +void intel_encoder_commit (struct drm_encoder *encoder) { + struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private; /* lvds has its own version of commit see intel_lvds_commit */ - connector->funcs->dpms(connector, DPMSModeOn); + encoder_funcs->dpms(encoder, DPMSModeOn); } static bool intel_crtc_mode_fixup(struct drm_crtc *crtc, @@ -721,7 +725,7 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc, list_for_each_entry(connector, &mode_config->connector_list, head) { struct intel_output *intel_output = to_intel_output(connector); - if (connector->crtc != crtc) + if (!connector->encoder || connector->encoder->crtc != crtc) continue; switch (intel_output->type) { @@ -1082,18 +1086,18 @@ static struct drm_display_mode load_detect_mode = { 704, 832, 0, 480, 489, 491, 520, 0, V_NHSYNC | V_NVSYNC), }; -struct drm_crtc *intel_get_load_detect_pipe(struct drm_connector *connector, +struct drm_crtc *intel_get_load_detect_pipe(struct intel_output *intel_output, struct drm_display_mode *mode, int *dpms_mode) { - struct drm_device *dev = connector->dev; - struct intel_output *intel_output = to_intel_output(connector); struct intel_crtc *intel_crtc; struct drm_crtc *possible_crtc; struct drm_crtc *supported_crtc =NULL; - struct drm_encoder *encoder = NULL; + struct drm_encoder *encoder = &intel_output->enc; struct drm_crtc *crtc = NULL; - struct drm_connector_helper_funcs *connector_funcs; + struct drm_device *dev = encoder->dev; + struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private; + struct drm_crtc_helper_funcs *crtc_funcs; int i = -1; /* @@ -1107,22 +1111,19 @@ struct drm_crtc *intel_get_load_detect_pipe(struct drm_connector *connector, */ /* See if we already have a CRTC for this connector */ - if (connector->crtc) { - crtc = connector->crtc; + if (encoder->crtc) { + crtc = encoder->crtc; /* Make sure the crtc and connector are running */ intel_crtc = to_intel_crtc(crtc); *dpms_mode = intel_crtc->dpms_mode; if (intel_crtc->dpms_mode != DPMSModeOn) { - crtc->funcs->dpms(crtc, DPMSModeOn); - connector->funcs->dpms(connector, DPMSModeOn); + crtc_funcs = crtc->helper_private; + crtc_funcs->dpms(crtc, DPMSModeOn); + encoder_funcs->dpms(encoder, DPMSModeOn); } return crtc; } - list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) - if (encoder->id == connector->current_encoder_id) - break; - /* Find an unused one (if possible) */ list_for_each_entry(possible_crtc, &dev->mode_config.crtc_list, head) { i++; @@ -1146,7 +1147,7 @@ struct drm_crtc *intel_get_load_detect_pipe(struct drm_connector *connector, return NULL; } - connector->crtc = crtc; + encoder->crtc = crtc; intel_output->load_detect_temp = TRUE; intel_crtc = to_intel_crtc(crtc); @@ -1157,13 +1158,14 @@ struct drm_crtc *intel_get_load_detect_pipe(struct drm_connector *connector, mode = &load_detect_mode; drm_crtc_helper_set_mode(crtc, mode, 0, 0); } else { - if (intel_crtc->dpms_mode != DPMSModeOn) - crtc->funcs->dpms(crtc, DPMSModeOn); + if (intel_crtc->dpms_mode != DPMSModeOn) { + crtc_funcs = crtc->helper_private; + crtc_funcs->dpms(crtc, DPMSModeOn); + } - connector_funcs = connector->helper_private; /* Add this connector to the crtc */ - connector_funcs->mode_set(connector, &crtc->mode, &crtc->mode); - connector_funcs->commit(connector); + encoder_funcs->mode_set(encoder, &crtc->mode, &crtc->mode); + encoder_funcs->commit(encoder); } /* let the connector get through one full cycle before testing */ intel_wait_for_vblank(dev); @@ -1171,24 +1173,26 @@ struct drm_crtc *intel_get_load_detect_pipe(struct drm_connector *connector, return crtc; } -void intel_release_load_detect_pipe(struct drm_connector *connector, int dpms_mode) +void intel_release_load_detect_pipe(struct intel_output *intel_output, int dpms_mode) { - struct drm_device *dev = connector->dev; - struct intel_output *intel_output = to_intel_output(connector); - struct drm_crtc *crtc = connector->crtc; + struct drm_encoder *encoder = &intel_output->enc; + struct drm_device *dev = encoder->dev; + struct drm_crtc *crtc = encoder->crtc; + struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private; + struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; if (intel_output->load_detect_temp) { - connector->crtc = NULL; + encoder->crtc = NULL; intel_output->load_detect_temp = FALSE; crtc->enabled = drm_crtc_in_use(crtc); - drm_disable_unused_functions(dev); + drm_helper_disable_unused_functions(dev); } /* Switch crtc and output back off if necessary */ if (crtc->enabled && dpms_mode != DPMSModeOn) { - if (connector->crtc == crtc) - connector->funcs->dpms(connector, dpms_mode); - crtc->funcs->dpms(crtc, dpms_mode); + if (encoder->crtc == crtc) + encoder_funcs->dpms(encoder, dpms_mode); + crtc_funcs->dpms(crtc, dpms_mode); } } @@ -1311,6 +1315,7 @@ static void intel_crtc_destroy(struct drm_crtc *crtc) } static const struct drm_crtc_helper_funcs intel_helper_funcs = { + .dpms = intel_crtc_dpms, .mode_fixup = intel_crtc_mode_fixup, .mode_set = intel_crtc_mode_set, .mode_set_base = intel_pipe_set_base, @@ -1319,7 +1324,6 @@ static const struct drm_crtc_helper_funcs intel_helper_funcs = { }; static const struct drm_crtc_funcs intel_crtc_funcs = { - .dpms = intel_crtc_dpms, .cursor_set = intel_crtc_cursor_set, .cursor_move = intel_crtc_cursor_move, .gamma_set = intel_crtc_gamma_set, -- cgit v1.2.3 From 0dd000b578adec6ff101c957bce7dc9a32b76713 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 2 Jun 2008 11:12:28 +1000 Subject: drm/modesetting: move some connector functions to helper. Migrated the output mode collection into the helper. --- linux-core/intel_display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux-core/intel_display.c') diff --git a/linux-core/intel_display.c b/linux-core/intel_display.c index c1cb2bff..bbaa19d1 100644 --- a/linux-core/intel_display.c +++ b/linux-core/intel_display.c @@ -1184,7 +1184,7 @@ void intel_release_load_detect_pipe(struct intel_output *intel_output, int dpms_ if (intel_output->load_detect_temp) { encoder->crtc = NULL; intel_output->load_detect_temp = FALSE; - crtc->enabled = drm_crtc_in_use(crtc); + crtc->enabled = drm_helper_crtc_in_use(crtc); drm_helper_disable_unused_functions(dev); } -- cgit v1.2.3 From 46c78a2223802b9105a87b7125fd4872ab69c4ca Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 2 Jun 2008 11:44:35 +1000 Subject: drm/modesetting: add best encoder finding for modesetting This asks the driver to suggest the best encoder for the connector during the pick crtcs stage. Need to also do this during mode setting stages --- linux-core/intel_display.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'linux-core/intel_display.c') diff --git a/linux-core/intel_display.c b/linux-core/intel_display.c index bbaa19d1..e23b3973 100644 --- a/linux-core/intel_display.c +++ b/linux-core/intel_display.c @@ -1489,3 +1489,14 @@ void intel_modeset_cleanup(struct drm_device *dev) { drm_mode_config_cleanup(dev); } + + +/* current intel driver doesn't take advantage of encoders + always give back the encoder for the connector +*/ +struct drm_encoder *intel_best_encoder(struct drm_connector *connector) +{ + struct intel_output *intel_output = to_intel_output(connector); + + return &intel_output->enc; +} -- cgit v1.2.3 From 4e7b24639808e5e1e2c05143028db1a3bc2812e9 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 2 Jun 2008 14:04:41 +1000 Subject: drm: add functions to get/set gamma ramps --- linux-core/intel_display.c | 21 ++++++++++++++++++++- 1 file changed, 20 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 e23b3973..ba9441d6 100644 --- a/linux-core/intel_display.c +++ b/linux-core/intel_display.c @@ -1056,7 +1056,7 @@ static int intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) } /** Sets the color ramps on behalf of RandR */ -static void intel_crtc_gamma_set(struct drm_crtc *crtc, u16 red, u16 green, +void intel_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green, u16 blue, int regno) { struct intel_crtc *intel_crtc = to_intel_crtc(crtc); @@ -1066,6 +1066,24 @@ static void intel_crtc_gamma_set(struct drm_crtc *crtc, u16 red, u16 green, intel_crtc->lut_b[regno] = blue >> 8; } +static void intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green, + u16 *blue, uint32_t size) +{ + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + int i; + + if (size != 256) + return; + + 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); +} + /** * Get a pipe with a simple mode set on it for doing load-based monitor * detection. @@ -1343,6 +1361,7 @@ void intel_crtc_init(struct drm_device *dev, int pipe) drm_crtc_init(dev, &intel_crtc->base, &intel_crtc_funcs); + drm_mode_crtc_set_gamma_size(&intel_crtc->base, 256); intel_crtc->pipe = pipe; for (i = 0; i < 256; i++) { intel_crtc->lut_r[i] = i; -- cgit v1.2.3 From 3ed17803d826b10f8f94d09acf12877e9738823c Mon Sep 17 00:00:00 2001 From: Alan Hourihane Date: Mon, 2 Jun 2008 10:44:29 +0100 Subject: more checks for NULL encoder so we don't segfault. --- 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 ba9441d6..8a8f4edb 100644 --- a/linux-core/intel_display.c +++ b/linux-core/intel_display.c @@ -228,7 +228,8 @@ bool intel_pipe_has_type (struct drm_crtc *crtc, int type) struct drm_connector *l_entry; list_for_each_entry(l_entry, &mode_config->connector_list, head) { - if (l_entry->encoder->crtc == crtc) { + if (l_entry->encoder && + l_entry->encoder->crtc == crtc) { struct intel_output *intel_output = to_intel_output(l_entry); if (intel_output->type == type) return true; -- cgit v1.2.3 From 76a44f14d6339e5bc0c936ef4a360f6c152511bd Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 4 Jun 2008 11:59:28 +1000 Subject: drm/modesetting: overhaul the fb create/delete. Move TTM code into the driver --- linux-core/intel_display.c | 47 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 46 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 8a8f4edb..529cae14 100644 --- a/linux-core/intel_display.c +++ b/linux-core/intel_display.c @@ -368,6 +368,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y) struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_master_private *master_priv; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + struct intel_framebuffer *intel_fb; int pipe = intel_crtc->pipe; unsigned long Start, Offset; int dspbase = (pipe == 0 ? DSPAADDR : DSPBADDR); @@ -382,7 +383,9 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y) return; } - Start = crtc->fb->bo->offset; + intel_fb = to_intel_framebuffer(crtc->fb); + + Start = intel_fb->bo->offset; Offset = y * crtc->fb->pitch + x * (crtc->fb->bits_per_pixel / 8); I915_WRITE(dspstride, crtc->fb->pitch); @@ -1459,8 +1462,50 @@ static void intel_setup_outputs(struct drm_device *dev) } } +static void intel_user_framebuffer_destroy(struct drm_framebuffer *fb) +{ + struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); + struct drm_device *dev = fb->dev; + if (fb->fbdev) + intelfb_remove(dev, fb); + + drm_framebuffer_cleanup(fb); + + kfree(intel_fb); +} + +static const struct drm_framebuffer_funcs intel_fb_funcs = { + .destroy = intel_user_framebuffer_destroy, +}; + +struct drm_framebuffer *intel_user_framebuffer_create(struct drm_device *dev, + struct drm_file *file_priv, + struct drm_mode_fb_cmd *mode_cmd) +{ + struct intel_framebuffer *intel_fb; + + intel_fb = kmalloc(sizeof(*intel_fb), GFP_KERNEL); + if (!intel_fb) + return NULL; + + drm_framebuffer_init(dev, &intel_fb->base, &intel_fb_funcs); + drm_helper_mode_fill_fb_struct(&intel_fb->base, mode_cmd); + + if (file_priv) { + mutex_lock(&dev->struct_mutex); + intel_fb->bo = drm_lookup_buffer_object(file_priv, intel_fb->base.mm_handle, 0); + mutex_unlock(&dev->struct_mutex); + if (!intel_fb->bo) { + kfree(intel_fb); + return NULL; + } + } + return &intel_fb->base; +} + static const struct drm_mode_config_funcs intel_mode_funcs = { .resize_fb = NULL, + .fb_create = intel_user_framebuffer_create, }; void intel_modeset_init(struct drm_device *dev) -- cgit v1.2.3 From fd27591c6cadd2a868f4110b8993a86c37837d3e Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 4 Jun 2008 13:00:31 +1000 Subject: drm/modesetting: pass object handle to driver !bo --- linux-core/intel_display.c | 11 +++++++++-- 1 file changed, 9 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 529cae14..3f5afac0 100644 --- a/linux-core/intel_display.c +++ b/linux-core/intel_display.c @@ -972,22 +972,24 @@ void intel_crtc_load_lut(struct drm_crtc *crtc) } static int intel_crtc_cursor_set(struct drm_crtc *crtc, - struct drm_buffer_object *bo, + uint32_t handle, uint32_t width, uint32_t height) { struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + struct drm_buffer_object *bo; int pipe = intel_crtc->pipe; uint32_t control = (pipe == 0) ? CURACNTR : CURBCNTR; uint32_t base = (pipe == 0) ? CURABASE : CURBBASE; uint32_t temp; + int ret; size_t addr; DRM_DEBUG("\n"); /* if we want to turn of the cursor ignore width and height */ - if (!bo) { + if (!handle) { DRM_DEBUG("cursor off\n"); /* turn of the cursor */ temp = 0; @@ -1004,6 +1006,11 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc, return -EINVAL; } + ret = drm_get_buffer_object(dev, &bo, handle); + if (ret) { + return -EINVAL; + } + if ((bo->mem.flags & DRM_BO_MASK_MEM) != DRM_BO_FLAG_MEM_VRAM) { DRM_ERROR("buffer needs to be in VRAM\n"); return -ENOMEM; -- cgit v1.2.3 From 8e4c61e52651c47f3d9fbbe5e80455baff0de2bb Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 4 Jun 2008 13:09:20 +1000 Subject: intel: use kzalloc --- linux-core/intel_display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux-core/intel_display.c') diff --git a/linux-core/intel_display.c b/linux-core/intel_display.c index 3f5afac0..6493af16 100644 --- a/linux-core/intel_display.c +++ b/linux-core/intel_display.c @@ -1491,7 +1491,7 @@ struct drm_framebuffer *intel_user_framebuffer_create(struct drm_device *dev, { struct intel_framebuffer *intel_fb; - intel_fb = kmalloc(sizeof(*intel_fb), GFP_KERNEL); + intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL); if (!intel_fb) return NULL; -- cgit v1.2.3 From 967bd219116a4f20aec828b890a225d2f92afd0b Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 5 Jun 2008 11:11:22 +1000 Subject: modesetting: initial attempt at debonging fb --- linux-core/intel_display.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'linux-core/intel_display.c') diff --git a/linux-core/intel_display.c b/linux-core/intel_display.c index 6493af16..8baae1b3 100644 --- a/linux-core/intel_display.c +++ b/linux-core/intel_display.c @@ -1383,6 +1383,12 @@ void intel_crtc_init(struct drm_device *dev, int pipe) intel_crtc->cursor_addr = 0; intel_crtc->dpms_mode = DPMSModeOff; drm_crtc_helper_add(&intel_crtc->base, &intel_helper_funcs); + + if (i915_fbpercrtc) { + + + + } } struct drm_crtc *intel_get_crtc_from_pipe(struct drm_device *dev, int pipe) @@ -1554,6 +1560,7 @@ void intel_modeset_init(struct drm_device *dev) intel_setup_outputs(dev); + /* setup fbs */ //drm_initial_config(dev, false); } -- cgit v1.2.3 From b31adb005afc5553fb30aa2c1710faee299bc730 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 5 Jun 2008 15:55:03 +1000 Subject: drm/modesetting: more fb interface cleanups --- linux-core/intel_display.c | 1 + 1 file changed, 1 insertion(+) (limited to 'linux-core/intel_display.c') diff --git a/linux-core/intel_display.c b/linux-core/intel_display.c index 8baae1b3..e1d9d4d0 100644 --- a/linux-core/intel_display.c +++ b/linux-core/intel_display.c @@ -1519,6 +1519,7 @@ struct drm_framebuffer *intel_user_framebuffer_create(struct drm_device *dev, static const struct drm_mode_config_funcs intel_mode_funcs = { .resize_fb = NULL, .fb_create = intel_user_framebuffer_create, + .fb_changed = intelfb_probe, }; void intel_modeset_init(struct drm_device *dev) -- cgit v1.2.3 From 5f94172f81120c56ba07843ff860a9e265dac1f8 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 6 Jun 2008 10:31:36 +1000 Subject: intel: if no spare crtc exists don't just take one. --- linux-core/intel_display.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'linux-core/intel_display.c') diff --git a/linux-core/intel_display.c b/linux-core/intel_display.c index e1d9d4d0..e2d2a5fb 100644 --- a/linux-core/intel_display.c +++ b/linux-core/intel_display.c @@ -1167,13 +1167,10 @@ struct drm_crtc *intel_get_load_detect_pipe(struct intel_output *intel_output, } /* - * If we didn't find an unused CRTC, use the first available one - * that can drive this connector. + * If we didn't find an unused CRTC, don't use any. */ if (!crtc) { - crtc = supported_crtc; - if (!crtc) - return NULL; + return NULL; } encoder->crtc = crtc; -- cgit v1.2.3 From 8387a232a3305d10c4ac4cd08f9ebd0888944e55 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 6 Jun 2008 12:02:51 +1000 Subject: intelfb: move mode sets into the intel crtcs better place to store them. --- linux-core/intel_display.c | 6 +++++- 1 file changed, 5 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 e2d2a5fb..0081b5be 100644 --- a/linux-core/intel_display.c +++ b/linux-core/intel_display.c @@ -1363,7 +1363,7 @@ void intel_crtc_init(struct drm_device *dev, int pipe) struct intel_crtc *intel_crtc; int i; - intel_crtc = kzalloc(sizeof(struct intel_crtc), GFP_KERNEL); + intel_crtc = kzalloc(sizeof(struct intel_crtc) + (INTELFB_CONN_LIMIT * sizeof(struct drm_connector *)), GFP_KERNEL); if (intel_crtc == NULL) return; @@ -1381,6 +1381,10 @@ void intel_crtc_init(struct drm_device *dev, int pipe) intel_crtc->dpms_mode = DPMSModeOff; drm_crtc_helper_add(&intel_crtc->base, &intel_helper_funcs); + intel_crtc->mode_set.crtc = &intel_crtc->base; + intel_crtc->mode_set.connectors = (struct drm_connector **)(intel_crtc + 1); + intel_crtc->mode_set.num_connectors = 0; + if (i915_fbpercrtc) { -- cgit v1.2.3 From 6d4ffd12cd8d3713067adf5fa3bdcb023b0745f1 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 6 Jun 2008 16:24:27 +1000 Subject: drm: fix up fb resize again --- linux-core/intel_display.c | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 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 0081b5be..0a2854a2 100644 --- a/linux-core/intel_display.c +++ b/linux-core/intel_display.c @@ -1517,8 +1517,38 @@ struct drm_framebuffer *intel_user_framebuffer_create(struct drm_device *dev, return &intel_fb->base; } +static int intel_insert_new_fb(struct drm_device *dev, struct drm_file *file_priv, + struct drm_framebuffer *fb, struct drm_mode_fb_cmd *mode_cmd) +{ + struct intel_framebuffer *intel_fb; + struct drm_buffer_object *bo; + struct drm_crtc *crtc; + + intel_fb = to_intel_framebuffer(fb); + + mutex_lock(&dev->struct_mutex); + bo = drm_lookup_buffer_object(file_priv, mode_cmd->handle, 0); + mutex_unlock(&dev->struct_mutex); + + if (!bo) + return -EINVAL; + drm_helper_mode_fill_fb_struct(fb, mode_cmd); + + drm_bo_usage_deref_unlocked(&intel_fb->bo); + + intel_fb->bo = bo; + + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + if (crtc->fb == fb) { + struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; + crtc_funcs->mode_set_base(crtc, crtc->x, crtc->y); + } + } + return 0; +} + static const struct drm_mode_config_funcs intel_mode_funcs = { - .resize_fb = NULL, + .resize_fb = intel_insert_new_fb, .fb_create = intel_user_framebuffer_create, .fb_changed = intelfb_probe, }; -- cgit v1.2.3 From 4a2e29bf9982165deeeabb5c585fc0a8a659f380 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Wed, 11 Jun 2008 15:59:01 -0700 Subject: Use GEM in modesetting Use GEM for ring buffer setup and framebuffer allocation. This means reworking the hardware status page stuff a bit (just use the basic range allocator for vram for now) and #ifdef'ing out the TTM & DRI2 code. Works well enough to load/unload several times and display fbcon on my T61 (though there's still some unexplained console corruption). --- linux-core/intel_display.c | 34 ++++++++++++++++++++-------------- 1 file changed, 20 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 0a2854a2..50ad1a27 100644 --- a/linux-core/intel_display.c +++ b/linux-core/intel_display.c @@ -369,6 +369,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y) struct drm_i915_master_private *master_priv; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_framebuffer *intel_fb; + struct drm_i915_gem_object *obj_priv; int pipe = intel_crtc->pipe; unsigned long Start, Offset; int dspbase = (pipe == 0 ? DSPAADDR : DSPBADDR); @@ -385,7 +386,9 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y) intel_fb = to_intel_framebuffer(crtc->fb); - Start = intel_fb->bo->offset; + obj_priv = intel_fb->obj->driver_private; + + Start = obj_priv->gtt_offset; Offset = y * crtc->fb->pitch + x * (crtc->fb->bits_per_pixel / 8); I915_WRITE(dspstride, crtc->fb->pitch); @@ -1493,7 +1496,7 @@ static const struct drm_framebuffer_funcs intel_fb_funcs = { }; struct drm_framebuffer *intel_user_framebuffer_create(struct drm_device *dev, - struct drm_file *file_priv, + struct drm_file *filp, struct drm_mode_fb_cmd *mode_cmd) { struct intel_framebuffer *intel_fb; @@ -1505,15 +1508,15 @@ struct drm_framebuffer *intel_user_framebuffer_create(struct drm_device *dev, drm_framebuffer_init(dev, &intel_fb->base, &intel_fb_funcs); drm_helper_mode_fill_fb_struct(&intel_fb->base, mode_cmd); - if (file_priv) { - mutex_lock(&dev->struct_mutex); - intel_fb->bo = drm_lookup_buffer_object(file_priv, intel_fb->base.mm_handle, 0); - mutex_unlock(&dev->struct_mutex); - if (!intel_fb->bo) { + if (filp) { + intel_fb->obj = drm_gem_object_lookup(dev, filp, + mode_cmd->handle); + if (!intel_fb->obj) { kfree(intel_fb); return NULL; } } + drm_gem_object_unreference(intel_fb->obj); return &intel_fb->base; } @@ -1521,22 +1524,25 @@ static int intel_insert_new_fb(struct drm_device *dev, struct drm_file *file_pri struct drm_framebuffer *fb, struct drm_mode_fb_cmd *mode_cmd) { struct intel_framebuffer *intel_fb; - struct drm_buffer_object *bo; + struct drm_gem_object *obj; struct drm_crtc *crtc; intel_fb = to_intel_framebuffer(fb); mutex_lock(&dev->struct_mutex); - bo = drm_lookup_buffer_object(file_priv, mode_cmd->handle, 0); - mutex_unlock(&dev->struct_mutex); + obj = drm_gem_object_lookup(dev, file_priv, mode_cmd->handle); - if (!bo) + if (!obj) { + mutex_unlock(&dev->struct_mutex); return -EINVAL; + } drm_helper_mode_fill_fb_struct(fb, mode_cmd); - - drm_bo_usage_deref_unlocked(&intel_fb->bo); - intel_fb->bo = bo; + drm_gem_object_unreference(intel_fb->obj); + drm_gem_object_unreference(obj); + mutex_unlock(&dev->struct_mutex); + + intel_fb->obj = obj; list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { if (crtc->fb == fb) { -- cgit v1.2.3 From e810cb9243fe6c4905182869d9e3272d861a14cb Mon Sep 17 00:00:00 2001 From: Maarten Maathuis Date: Sun, 6 Jul 2008 10:52:25 +0200 Subject: modesetting-101: rename modeflags, as to avoid conflicts with the xorg definitions --- linux-core/intel_display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux-core/intel_display.c') diff --git a/linux-core/intel_display.c b/linux-core/intel_display.c index 0a2854a2..b82993fc 100644 --- a/linux-core/intel_display.c +++ b/linux-core/intel_display.c @@ -1112,7 +1112,7 @@ static void intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green, /* VESA 640x480x72Hz mode to set on the pipe */ static struct drm_display_mode load_detect_mode = { DRM_MODE("640x480", DRM_MODE_TYPE_DEFAULT, 31500, 640, 664, - 704, 832, 0, 480, 489, 491, 520, 0, V_NHSYNC | V_NVSYNC), + 704, 832, 0, 480, 489, 491, 520, 0, DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC), }; struct drm_crtc *intel_get_load_detect_pipe(struct intel_output *intel_output, -- cgit v1.2.3 From 6738e7b00bf05529303ed690873495db6d83337c Mon Sep 17 00:00:00 2001 From: Maarten Maathuis Date: Sun, 6 Jul 2008 11:08:49 +0200 Subject: modesetting-101: Rename DPMS modes to avoid compatibility issues with xorg definitions. --- linux-core/intel_display.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) (limited to 'linux-core/intel_display.c') diff --git a/linux-core/intel_display.c b/linux-core/intel_display.c index b82993fc..29aae169 100644 --- a/linux-core/intel_display.c +++ b/linux-core/intel_display.c @@ -468,12 +468,12 @@ static void intel_crtc_dpms(struct drm_crtc *crtc, int mode) 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. + * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC. */ switch (mode) { - case DPMSModeOn: - case DPMSModeStandby: - case DPMSModeSuspend: + case DRM_MODE_DPMS_ON: + case DRM_MODE_DPMS_STANDBY: + case DRM_MODE_DPMS_SUSPEND: /* Enable the DPLL */ temp = I915_READ(dpll_reg); if ((temp & DPLL_VCO_ENABLE) == 0) { @@ -509,7 +509,7 @@ static void intel_crtc_dpms(struct drm_crtc *crtc, int mode) /* Give the overlay scaler a chance to enable if it's on this pipe */ //intel_crtc_dpms_video(crtc, TRUE); TODO break; - case DPMSModeOff: + case DRM_MODE_DPMS_OFF: /* Give the overlay scaler a chance to disable if it's on this pipe */ //intel_crtc_dpms_video(crtc, FALSE); TODO @@ -558,7 +558,7 @@ static void intel_crtc_dpms(struct drm_crtc *crtc, int mode) if (!master_priv->sarea_priv) return; - enabled = crtc->enabled && mode != DPMSModeOff; + enabled = crtc->enabled && mode != DRM_MODE_DPMS_OFF; switch (pipe) { case 0: @@ -580,27 +580,27 @@ static void intel_crtc_dpms(struct drm_crtc *crtc, int mode) static void intel_crtc_prepare (struct drm_crtc *crtc) { struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; - crtc_funcs->dpms(crtc, DPMSModeOff); + crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF); } static void intel_crtc_commit (struct drm_crtc *crtc) { struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; - crtc_funcs->dpms(crtc, DPMSModeOn); + crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON); } void intel_encoder_prepare (struct drm_encoder *encoder) { struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private; /* lvds has its own version of prepare see intel_lvds_prepare */ - encoder_funcs->dpms(encoder, DPMSModeOff); + encoder_funcs->dpms(encoder, DRM_MODE_DPMS_OFF); } void intel_encoder_commit (struct drm_encoder *encoder) { struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private; /* lvds has its own version of commit see intel_lvds_commit */ - encoder_funcs->dpms(encoder, DPMSModeOn); + encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON); } static bool intel_crtc_mode_fixup(struct drm_crtc *crtc, @@ -1145,10 +1145,10 @@ struct drm_crtc *intel_get_load_detect_pipe(struct intel_output *intel_output, /* Make sure the crtc and connector are running */ intel_crtc = to_intel_crtc(crtc); *dpms_mode = intel_crtc->dpms_mode; - if (intel_crtc->dpms_mode != DPMSModeOn) { + if (intel_crtc->dpms_mode != DRM_MODE_DPMS_ON) { crtc_funcs = crtc->helper_private; - crtc_funcs->dpms(crtc, DPMSModeOn); - encoder_funcs->dpms(encoder, DPMSModeOn); + crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON); + encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON); } return crtc; } @@ -1184,9 +1184,9 @@ struct drm_crtc *intel_get_load_detect_pipe(struct intel_output *intel_output, mode = &load_detect_mode; drm_crtc_helper_set_mode(crtc, mode, 0, 0); } else { - if (intel_crtc->dpms_mode != DPMSModeOn) { + if (intel_crtc->dpms_mode != DRM_MODE_DPMS_ON) { crtc_funcs = crtc->helper_private; - crtc_funcs->dpms(crtc, DPMSModeOn); + crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON); } /* Add this connector to the crtc */ @@ -1215,7 +1215,7 @@ void intel_release_load_detect_pipe(struct intel_output *intel_output, int dpms_ } /* Switch crtc and output back off if necessary */ - if (crtc->enabled && dpms_mode != DPMSModeOn) { + if (crtc->enabled && dpms_mode != DRM_MODE_DPMS_ON) { if (encoder->crtc == crtc) encoder_funcs->dpms(encoder, dpms_mode); crtc_funcs->dpms(crtc, dpms_mode); @@ -1378,7 +1378,7 @@ void intel_crtc_init(struct drm_device *dev, int pipe) } intel_crtc->cursor_addr = 0; - intel_crtc->dpms_mode = DPMSModeOff; + intel_crtc->dpms_mode = DRM_MODE_DPMS_OFF; drm_crtc_helper_add(&intel_crtc->base, &intel_helper_funcs); intel_crtc->mode_set.crtc = &intel_crtc->base; -- cgit v1.2.3 From 7fd8a5de63781f6faa053509c80e02e8f1cdbb69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Mon, 7 Jul 2008 11:56:59 -0400 Subject: Use lowercase bool constants. --- 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 50ad1a27..40cbc492 100644 --- a/linux-core/intel_display.c +++ b/linux-core/intel_display.c @@ -510,7 +510,7 @@ static void intel_crtc_dpms(struct drm_crtc *crtc, int mode) 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 + //intel_crtc_dpms_video(crtc, true); TODO break; case DPMSModeOff: /* Give the overlay scaler a chance to disable if it's on this pipe */ @@ -737,19 +737,19 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc, switch (intel_output->type) { case INTEL_OUTPUT_LVDS: - is_lvds = TRUE; + is_lvds = true; break; case INTEL_OUTPUT_SDVO: - is_sdvo = TRUE; + is_sdvo = true; break; case INTEL_OUTPUT_DVO: - is_dvo = TRUE; + is_dvo = true; break; case INTEL_OUTPUT_TVOUT: - is_tv = TRUE; + is_tv = true; break; case INTEL_OUTPUT_ANALOG: - is_crt = TRUE; + is_crt = true; break; } } @@ -1177,7 +1177,7 @@ struct drm_crtc *intel_get_load_detect_pipe(struct intel_output *intel_output, } encoder->crtc = crtc; - intel_output->load_detect_temp = TRUE; + intel_output->load_detect_temp = true; intel_crtc = to_intel_crtc(crtc); *dpms_mode = intel_crtc->dpms_mode; @@ -1212,7 +1212,7 @@ void intel_release_load_detect_pipe(struct intel_output *intel_output, int dpms_ if (intel_output->load_detect_temp) { encoder->crtc = NULL; - intel_output->load_detect_temp = FALSE; + intel_output->load_detect_temp = false; crtc->enabled = drm_helper_crtc_in_use(crtc); drm_helper_disable_unused_functions(dev); } -- cgit v1.2.3 From 11d30750873260fe19498d90831f07079dfad5d8 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Sat, 26 Jul 2008 08:41:01 +1000 Subject: modesetting: pass file_priv into cursor set functions --- linux-core/intel_display.c | 1 + 1 file changed, 1 insertion(+) (limited to 'linux-core/intel_display.c') diff --git a/linux-core/intel_display.c b/linux-core/intel_display.c index a761b61b..0236bbc9 100644 --- a/linux-core/intel_display.c +++ b/linux-core/intel_display.c @@ -975,6 +975,7 @@ void intel_crtc_load_lut(struct drm_crtc *crtc) } static int intel_crtc_cursor_set(struct drm_crtc *crtc, + struct drm_file *file_priv, uint32_t handle, uint32_t width, uint32_t height) { -- cgit v1.2.3 From 085df6491e4975681a6e17ff9a67d01268aa7553 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Tue, 12 Aug 2008 18:23:58 -0700 Subject: Add error checking to framebuffer creation Make the Intel routine return an error if needed and make the core check for it. --- linux-core/intel_display.c | 4 +++- 1 file changed, 3 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 0236bbc9..fbe06f7c 100644 --- a/linux-core/intel_display.c +++ b/linux-core/intel_display.c @@ -1506,7 +1506,9 @@ struct drm_framebuffer *intel_user_framebuffer_create(struct drm_device *dev, if (!intel_fb) return NULL; - drm_framebuffer_init(dev, &intel_fb->base, &intel_fb_funcs); + if (!drm_framebuffer_init(dev, &intel_fb->base, &intel_fb_funcs)) + return NULL; + drm_helper_mode_fill_fb_struct(&intel_fb->base, mode_cmd); if (filp) { -- cgit v1.2.3 From 5f9e4a764ac7acf1311388dd693bc4f0e6c0c4e9 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Wed, 13 Aug 2008 16:57:42 -0700 Subject: i915: update cursor handling to use GEM objects --- linux-core/intel_display.c | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) (limited to 'linux-core/intel_display.c') diff --git a/linux-core/intel_display.c b/linux-core/intel_display.c index fbe06f7c..dfc0b502 100644 --- a/linux-core/intel_display.c +++ b/linux-core/intel_display.c @@ -982,12 +982,12 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc, struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - struct drm_buffer_object *bo; + struct drm_gem_object *bo; + struct drm_i915_gem_object *obj_priv; int pipe = intel_crtc->pipe; uint32_t control = (pipe == 0) ? CURACNTR : CURBCNTR; uint32_t base = (pipe == 0) ? CURABASE : CURBBASE; uint32_t temp; - int ret; size_t addr; DRM_DEBUG("\n"); @@ -1010,25 +1010,22 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc, return -EINVAL; } - ret = drm_get_buffer_object(dev, &bo, handle); - if (ret) { - return -EINVAL; - } + bo = drm_gem_object_lookup(dev, file_priv, handle); + if (!bo) + return -ENOENT; - if ((bo->mem.flags & DRM_BO_MASK_MEM) != DRM_BO_FLAG_MEM_VRAM) { - DRM_ERROR("buffer needs to be in VRAM\n"); - return -ENOMEM; - } + obj_priv = bo->driver_private; - if (bo->mem.size < width * height * 4) { + if (bo->size < width * height * 4) { DRM_ERROR("buffer is to small\n"); return -ENOMEM; } - if (dev_priv->cursor_needs_physical) - addr = dev_priv->stolen_base + bo->offset; - else - addr = bo->offset; + if (dev_priv->cursor_needs_physical) { + addr = dev->agp->base + obj_priv->gtt_offset; + } else { + addr = obj_priv->gtt_offset; + } intel_crtc->cursor_addr = addr; temp = 0; -- cgit v1.2.3 From 840c9a305481ed59820bbd87fbcf78dd242d5702 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Tue, 23 Sep 2008 16:52:06 +1000 Subject: Update intel modesetting to use mm_private instead of mm_handle. --- linux-core/intel_display.c | 57 ++++++++++++++++++++++++++++++---------------- 1 file changed, 37 insertions(+), 20 deletions(-) (limited to 'linux-core/intel_display.c') diff --git a/linux-core/intel_display.c b/linux-core/intel_display.c index dfc0b502..5a275c6c 100644 --- a/linux-core/intel_display.c +++ b/linux-core/intel_display.c @@ -370,6 +370,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y) struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_framebuffer *intel_fb; struct drm_i915_gem_object *obj_priv; + struct drm_gem_object *obj; int pipe = intel_crtc->pipe; unsigned long Start, Offset; int dspbase = (pipe == 0 ? DSPAADDR : DSPBADDR); @@ -386,7 +387,8 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y) intel_fb = to_intel_framebuffer(crtc->fb); - obj_priv = intel_fb->obj->driver_private; + obj = intel_fb->base.mm_private; + obj_priv = obj->driver_private; Start = obj_priv->gtt_offset; Offset = y * crtc->fb->pitch + x * (crtc->fb->bits_per_pixel / 8); @@ -1481,21 +1483,34 @@ static void intel_user_framebuffer_destroy(struct drm_framebuffer *fb) { struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); struct drm_device *dev = fb->dev; + if (fb->fbdev) intelfb_remove(dev, fb); drm_framebuffer_cleanup(fb); + drm_gem_object_unreference(fb->mm_private); kfree(intel_fb); } + +static int intel_user_framebuffer_create_handle(struct drm_framebuffer *fb, + struct drm_file *file_priv, + unsigned int *handle) +{ + struct drm_gem_object *object = fb->mm_private; + + return drm_gem_handle_create(file_priv, object, handle); +} static const struct drm_framebuffer_funcs intel_fb_funcs = { .destroy = intel_user_framebuffer_destroy, + .create_handle = intel_user_framebuffer_create_handle, }; -struct drm_framebuffer *intel_user_framebuffer_create(struct drm_device *dev, - struct drm_file *filp, - struct drm_mode_fb_cmd *mode_cmd) +struct drm_framebuffer * +intel_framebuffer_create(struct drm_device *dev, + struct drm_mode_fb_cmd *mode_cmd, + void *mm_private) { struct intel_framebuffer *intel_fb; @@ -1506,20 +1521,26 @@ struct drm_framebuffer *intel_user_framebuffer_create(struct drm_device *dev, if (!drm_framebuffer_init(dev, &intel_fb->base, &intel_fb_funcs)) return NULL; - drm_helper_mode_fill_fb_struct(&intel_fb->base, mode_cmd); + drm_helper_mode_fill_fb_struct(&intel_fb->base, mode_cmd, mm_private); - if (filp) { - intel_fb->obj = drm_gem_object_lookup(dev, filp, - mode_cmd->handle); - if (!intel_fb->obj) { - kfree(intel_fb); - return NULL; - } - } - drm_gem_object_unreference(intel_fb->obj); return &intel_fb->base; } + +static struct drm_framebuffer * +intel_user_framebuffer_create(struct drm_device *dev, + struct drm_file *filp, + struct drm_mode_fb_cmd *mode_cmd) +{ + struct drm_gem_object *obj; + + obj = drm_gem_object_lookup(dev, filp, mode_cmd->handle); + if (!obj) + return NULL; + + return intel_framebuffer_create(dev, mode_cmd, obj); +} + static int intel_insert_new_fb(struct drm_device *dev, struct drm_file *file_priv, struct drm_framebuffer *fb, struct drm_mode_fb_cmd *mode_cmd) { @@ -1536,14 +1557,10 @@ static int intel_insert_new_fb(struct drm_device *dev, struct drm_file *file_pri mutex_unlock(&dev->struct_mutex); return -EINVAL; } - drm_helper_mode_fill_fb_struct(fb, mode_cmd); - - drm_gem_object_unreference(intel_fb->obj); - drm_gem_object_unreference(obj); + drm_gem_object_unreference(intel_fb->base.mm_private); + drm_helper_mode_fill_fb_struct(fb, mode_cmd, obj); mutex_unlock(&dev->struct_mutex); - intel_fb->obj = obj; - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { if (crtc->fb == fb) { struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; -- cgit v1.2.3