Commit 5eddb70b authored by Chris Wilson's avatar Chris Wilson

drm/i915: Use macros to switch between equivalent pipe registers

The purpose is to make the code much easier to read and therefore reduce
the possibility for bugs.

A side effect is that it also makes it much easier for the compiler,
reducing the object size by 4k -- from just a few functions!
Signed-off-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
parent 4ed765f9
...@@ -191,12 +191,7 @@ static int ...@@ -191,12 +191,7 @@ static int
i915_pipe_enabled(struct drm_device *dev, int pipe) i915_pipe_enabled(struct drm_device *dev, int pipe)
{ {
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
unsigned long pipeconf = pipe ? PIPEBCONF : PIPEACONF; return I915_READ(PIPECONF(pipe)) & PIPECONF_ENABLE;
if (I915_READ(pipeconf) & PIPEACONF_ENABLE)
return 1;
return 0;
} }
/* Called from drm generic code, passed a 'crtc', which /* Called from drm generic code, passed a 'crtc', which
...@@ -207,10 +202,7 @@ u32 i915_get_vblank_counter(struct drm_device *dev, int pipe) ...@@ -207,10 +202,7 @@ u32 i915_get_vblank_counter(struct drm_device *dev, int pipe)
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
unsigned long high_frame; unsigned long high_frame;
unsigned long low_frame; unsigned long low_frame;
u32 high1, high2, low, count; u32 high1, high2, low;
high_frame = pipe ? PIPEBFRAMEHIGH : PIPEAFRAMEHIGH;
low_frame = pipe ? PIPEBFRAMEPIXEL : PIPEAFRAMEPIXEL;
if (!i915_pipe_enabled(dev, pipe)) { if (!i915_pipe_enabled(dev, pipe)) {
DRM_DEBUG_DRIVER("trying to get vblank count for disabled " DRM_DEBUG_DRIVER("trying to get vblank count for disabled "
...@@ -218,23 +210,23 @@ u32 i915_get_vblank_counter(struct drm_device *dev, int pipe) ...@@ -218,23 +210,23 @@ u32 i915_get_vblank_counter(struct drm_device *dev, int pipe)
return 0; return 0;
} }
high_frame = pipe ? PIPEBFRAMEHIGH : PIPEAFRAMEHIGH;
low_frame = pipe ? PIPEBFRAMEPIXEL : PIPEAFRAMEPIXEL;
/* /*
* High & low register fields aren't synchronized, so make sure * High & low register fields aren't synchronized, so make sure
* we get a low value that's stable across two reads of the high * we get a low value that's stable across two reads of the high
* register. * register.
*/ */
do { do {
high1 = ((I915_READ(high_frame) & PIPE_FRAME_HIGH_MASK) >> high1 = I915_READ(high_frame) & PIPE_FRAME_HIGH_MASK;
PIPE_FRAME_HIGH_SHIFT); low = I915_READ(low_frame) & PIPE_FRAME_LOW_MASK;
low = ((I915_READ(low_frame) & PIPE_FRAME_LOW_MASK) >> high2 = I915_READ(high_frame) & PIPE_FRAME_HIGH_MASK;
PIPE_FRAME_LOW_SHIFT);
high2 = ((I915_READ(high_frame) & PIPE_FRAME_HIGH_MASK) >>
PIPE_FRAME_HIGH_SHIFT);
} while (high1 != high2); } while (high1 != high2);
count = (high1 << 8) | low; high1 >>= PIPE_FRAME_HIGH_SHIFT;
low >>= PIPE_FRAME_LOW_SHIFT;
return count; return (high1 << 8) | low;
} }
u32 gm45_get_vblank_counter(struct drm_device *dev, int pipe) u32 gm45_get_vblank_counter(struct drm_device *dev, int pipe)
...@@ -1207,11 +1199,8 @@ int i915_enable_vblank(struct drm_device *dev, int pipe) ...@@ -1207,11 +1199,8 @@ int i915_enable_vblank(struct drm_device *dev, int pipe)
{ {
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
unsigned long irqflags; unsigned long irqflags;
int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
u32 pipeconf;
pipeconf = I915_READ(pipeconf_reg); if (!i915_pipe_enabled(dev, pipe))
if (!(pipeconf & PIPEACONF_ENABLE))
return -EINVAL; return -EINVAL;
spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags); spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
......
...@@ -25,6 +25,8 @@ ...@@ -25,6 +25,8 @@
#ifndef _I915_REG_H_ #ifndef _I915_REG_H_
#define _I915_REG_H_ #define _I915_REG_H_
#define _PIPE(pipe, a, b) ((a) + (pipe)*((b)-(a)))
/* /*
* The Bridge device's PCI config space has information about the * The Bridge device's PCI config space has information about the
* fb aperture size and the amount of pre-reserved memory. * fb aperture size and the amount of pre-reserved memory.
...@@ -605,6 +607,7 @@ ...@@ -605,6 +607,7 @@
#define VGA1_PD_P1_MASK (0x1f << 8) #define VGA1_PD_P1_MASK (0x1f << 8)
#define DPLL_A 0x06014 #define DPLL_A 0x06014
#define DPLL_B 0x06018 #define DPLL_B 0x06018
#define DPLL(pipe) _PIPE(pipe, DPLL_A, DPLL_B)
#define DPLL_VCO_ENABLE (1 << 31) #define DPLL_VCO_ENABLE (1 << 31)
#define DPLL_DVO_HIGH_SPEED (1 << 30) #define DPLL_DVO_HIGH_SPEED (1 << 30)
#define DPLL_SYNCLOCK_ENABLE (1 << 29) #define DPLL_SYNCLOCK_ENABLE (1 << 29)
...@@ -738,10 +741,13 @@ ...@@ -738,10 +741,13 @@
#define DPLL_MD_VGA_UDI_MULTIPLIER_MASK 0x0000003f #define DPLL_MD_VGA_UDI_MULTIPLIER_MASK 0x0000003f
#define DPLL_MD_VGA_UDI_MULTIPLIER_SHIFT 0 #define DPLL_MD_VGA_UDI_MULTIPLIER_SHIFT 0
#define DPLL_B_MD 0x06020 /* 965+ only */ #define DPLL_B_MD 0x06020 /* 965+ only */
#define DPLL_MD(pipe) _PIPE(pipe, DPLL_A_MD, DPLL_B_MD)
#define FPA0 0x06040 #define FPA0 0x06040
#define FPA1 0x06044 #define FPA1 0x06044
#define FPB0 0x06048 #define FPB0 0x06048
#define FPB1 0x0604c #define FPB1 0x0604c
#define FP0(pipe) _PIPE(pipe, FPA0, FPB0)
#define FP1(pipe) _PIPE(pipe, FPA1, FPB1)
#define FP_N_DIV_MASK 0x003f0000 #define FP_N_DIV_MASK 0x003f0000
#define FP_N_PINEVIEW_DIV_MASK 0x00ff0000 #define FP_N_PINEVIEW_DIV_MASK 0x00ff0000
#define FP_N_DIV_SHIFT 16 #define FP_N_DIV_SHIFT 16
...@@ -1156,6 +1162,15 @@ ...@@ -1156,6 +1162,15 @@
#define PIPEBSRC 0x6101c #define PIPEBSRC 0x6101c
#define BCLRPAT_B 0x61020 #define BCLRPAT_B 0x61020
#define HTOTAL(pipe) _PIPE(pipe, HTOTAL_A, HTOTAL_B)
#define HBLANK(pipe) _PIPE(pipe, HBLANK_A, HBLANK_B)
#define HSYNC(pipe) _PIPE(pipe, HSYNC_A, HSYNC_B)
#define VTOTAL(pipe) _PIPE(pipe, VTOTAL_A, VTOTAL_B)
#define VBLANK(pipe) _PIPE(pipe, VBLANK_A, VBLANK_B)
#define VSYNC(pipe) _PIPE(pipe, VSYNC_A, VSYNC_B)
#define PIPESRC(pipe) _PIPE(pipe, PIPEASRC, PIPEBSRC)
#define BCLRPAT(pipe) _PIPE(pipe, BCLRPAT_A, BCLRPAT_B)
/* VGA port control */ /* VGA port control */
#define ADPA 0x61100 #define ADPA 0x61100
#define ADPA_DAC_ENABLE (1<<31) #define ADPA_DAC_ENABLE (1<<31)
...@@ -2086,15 +2101,15 @@ ...@@ -2086,15 +2101,15 @@
#define PIPEADSL 0x70000 #define PIPEADSL 0x70000
#define DSL_LINEMASK 0x00000fff #define DSL_LINEMASK 0x00000fff
#define PIPEACONF 0x70008 #define PIPEACONF 0x70008
#define PIPEACONF_ENABLE (1<<31) #define PIPECONF_ENABLE (1<<31)
#define PIPEACONF_DISABLE 0 #define PIPECONF_DISABLE 0
#define PIPEACONF_DOUBLE_WIDE (1<<30) #define PIPECONF_DOUBLE_WIDE (1<<30)
#define I965_PIPECONF_ACTIVE (1<<30) #define I965_PIPECONF_ACTIVE (1<<30)
#define PIPEACONF_SINGLE_WIDE 0 #define PIPECONF_SINGLE_WIDE 0
#define PIPEACONF_PIPE_UNLOCKED 0 #define PIPECONF_PIPE_UNLOCKED 0
#define PIPEACONF_PIPE_LOCKED (1<<25) #define PIPECONF_PIPE_LOCKED (1<<25)
#define PIPEACONF_PALETTE 0 #define PIPECONF_PALETTE 0
#define PIPEACONF_GAMMA (1<<24) #define PIPECONF_GAMMA (1<<24)
#define PIPECONF_FORCE_BORDER (1<<25) #define PIPECONF_FORCE_BORDER (1<<25)
#define PIPECONF_PROGRESSIVE (0 << 21) #define PIPECONF_PROGRESSIVE (0 << 21)
#define PIPECONF_INTERLACE_W_FIELD_INDICATION (6 << 21) #define PIPECONF_INTERLACE_W_FIELD_INDICATION (6 << 21)
...@@ -2147,6 +2162,8 @@ ...@@ -2147,6 +2162,8 @@
#define PIPE_6BPC (2 << 5) #define PIPE_6BPC (2 << 5)
#define PIPE_12BPC (3 << 5) #define PIPE_12BPC (3 << 5)
#define PIPECONF(pipe) _PIPE(pipe, PIPEACONF, PIPEBCONF)
#define DSPARB 0x70030 #define DSPARB 0x70030
#define DSPARB_CSTART_MASK (0x7f << 7) #define DSPARB_CSTART_MASK (0x7f << 7)
#define DSPARB_CSTART_SHIFT 7 #define DSPARB_CSTART_SHIFT 7
...@@ -2346,6 +2363,14 @@ ...@@ -2346,6 +2363,14 @@
#define DSPASURF 0x7019C /* 965+ only */ #define DSPASURF 0x7019C /* 965+ only */
#define DSPATILEOFF 0x701A4 /* 965+ only */ #define DSPATILEOFF 0x701A4 /* 965+ only */
#define DSPCNTR(plane) _PIPE(plane, DSPACNTR, DSPBCNTR)
#define DSPADDR(plane) _PIPE(plane, DSPAADDR, DSPBADDR)
#define DSPSTRIDE(plane) _PIPE(plane, DSPASTRIDE, DSPBSTRIDE)
#define DSPPOS(plane) _PIPE(plane, DSPAPOS, DSPBPOS)
#define DSPSIZE(plane) _PIPE(plane, DSPASIZE, DSPBSIZE)
#define DSPSURF(plane) _PIPE(plane, DSPASURF, DSPBSURF)
#define DSPTILEOFF(plane) _PIPE(plane, DSPATILEOFF, DSPBTILEOFF)
/* VBIOS flags */ /* VBIOS flags */
#define SWF00 0x71410 #define SWF00 0x71410
#define SWF01 0x71414 #define SWF01 0x71414
...@@ -2434,46 +2459,47 @@ ...@@ -2434,46 +2459,47 @@
#define PIPEA_DATA_M1 0x60030 #define PIPEA_DATA_M1 0x60030
#define TU_SIZE(x) (((x)-1) << 25) /* default size 64 */ #define TU_SIZE(x) (((x)-1) << 25) /* default size 64 */
#define TU_SIZE_MASK 0x7e000000 #define TU_SIZE_MASK 0x7e000000
#define PIPEA_DATA_M1_OFFSET 0 #define PIPE_DATA_M1_OFFSET 0
#define PIPEA_DATA_N1 0x60034 #define PIPEA_DATA_N1 0x60034
#define PIPEA_DATA_N1_OFFSET 0 #define PIPE_DATA_N1_OFFSET 0
#define PIPEA_DATA_M2 0x60038 #define PIPEA_DATA_M2 0x60038
#define PIPEA_DATA_M2_OFFSET 0 #define PIPE_DATA_M2_OFFSET 0
#define PIPEA_DATA_N2 0x6003c #define PIPEA_DATA_N2 0x6003c
#define PIPEA_DATA_N2_OFFSET 0 #define PIPE_DATA_N2_OFFSET 0
#define PIPEA_LINK_M1 0x60040 #define PIPEA_LINK_M1 0x60040
#define PIPEA_LINK_M1_OFFSET 0 #define PIPE_LINK_M1_OFFSET 0
#define PIPEA_LINK_N1 0x60044 #define PIPEA_LINK_N1 0x60044
#define PIPEA_LINK_N1_OFFSET 0 #define PIPE_LINK_N1_OFFSET 0
#define PIPEA_LINK_M2 0x60048 #define PIPEA_LINK_M2 0x60048
#define PIPEA_LINK_M2_OFFSET 0 #define PIPE_LINK_M2_OFFSET 0
#define PIPEA_LINK_N2 0x6004c #define PIPEA_LINK_N2 0x6004c
#define PIPEA_LINK_N2_OFFSET 0 #define PIPE_LINK_N2_OFFSET 0
/* PIPEB timing regs are same start from 0x61000 */ /* PIPEB timing regs are same start from 0x61000 */
#define PIPEB_DATA_M1 0x61030 #define PIPEB_DATA_M1 0x61030
#define PIPEB_DATA_M1_OFFSET 0
#define PIPEB_DATA_N1 0x61034 #define PIPEB_DATA_N1 0x61034
#define PIPEB_DATA_N1_OFFSET 0
#define PIPEB_DATA_M2 0x61038 #define PIPEB_DATA_M2 0x61038
#define PIPEB_DATA_M2_OFFSET 0
#define PIPEB_DATA_N2 0x6103c #define PIPEB_DATA_N2 0x6103c
#define PIPEB_DATA_N2_OFFSET 0
#define PIPEB_LINK_M1 0x61040 #define PIPEB_LINK_M1 0x61040
#define PIPEB_LINK_M1_OFFSET 0
#define PIPEB_LINK_N1 0x61044 #define PIPEB_LINK_N1 0x61044
#define PIPEB_LINK_N1_OFFSET 0
#define PIPEB_LINK_M2 0x61048 #define PIPEB_LINK_M2 0x61048
#define PIPEB_LINK_M2_OFFSET 0
#define PIPEB_LINK_N2 0x6104c #define PIPEB_LINK_N2 0x6104c
#define PIPEB_LINK_N2_OFFSET 0
#define PIPE_DATA_M1(pipe) _PIPE(pipe, PIPEA_DATA_M1, PIPEB_DATA_M1)
#define PIPE_DATA_N1(pipe) _PIPE(pipe, PIPEA_DATA_N1, PIPEB_DATA_N1)
#define PIPE_DATA_M2(pipe) _PIPE(pipe, PIPEA_DATA_M2, PIPEB_DATA_M2)
#define PIPE_DATA_N2(pipe) _PIPE(pipe, PIPEA_DATA_N2, PIPEB_DATA_N2)
#define PIPE_LINK_M1(pipe) _PIPE(pipe, PIPEA_LINK_M1, PIPEB_LINK_M1)
#define PIPE_LINK_N1(pipe) _PIPE(pipe, PIPEA_LINK_N1, PIPEB_LINK_N1)
#define PIPE_LINK_M2(pipe) _PIPE(pipe, PIPEA_LINK_M2, PIPEB_LINK_M2)
#define PIPE_LINK_N2(pipe) _PIPE(pipe, PIPEA_LINK_N2, PIPEB_LINK_N2)
/* CPU panel fitter */ /* CPU panel fitter */
#define PFA_CTL_1 0x68080 #define PFA_CTL_1 0x68080
...@@ -2614,11 +2640,14 @@ ...@@ -2614,11 +2640,14 @@
#define PCH_DPLL_A 0xc6014 #define PCH_DPLL_A 0xc6014
#define PCH_DPLL_B 0xc6018 #define PCH_DPLL_B 0xc6018
#define PCH_DPLL(pipe) _PIPE(pipe, PCH_DPLL_A, PCH_DPLL_B)
#define PCH_FPA0 0xc6040 #define PCH_FPA0 0xc6040
#define PCH_FPA1 0xc6044 #define PCH_FPA1 0xc6044
#define PCH_FPB0 0xc6048 #define PCH_FPB0 0xc6048
#define PCH_FPB1 0xc604c #define PCH_FPB1 0xc604c
#define PCH_FP0(pipe) _PIPE(pipe, PCH_FPA0, PCH_FPB0)
#define PCH_FP1(pipe) _PIPE(pipe, PCH_FPA1, PCH_FPB1)
#define PCH_DPLL_TEST 0xc606c #define PCH_DPLL_TEST 0xc606c
...@@ -2704,6 +2733,13 @@ ...@@ -2704,6 +2733,13 @@
#define TRANS_VBLANK_B 0xe1010 #define TRANS_VBLANK_B 0xe1010
#define TRANS_VSYNC_B 0xe1014 #define TRANS_VSYNC_B 0xe1014
#define TRANS_HTOTAL(pipe) _PIPE(pipe, TRANS_HTOTAL_A, TRANS_HTOTAL_B)
#define TRANS_HBLANK(pipe) _PIPE(pipe, TRANS_HBLANK_A, TRANS_HBLANK_B)
#define TRANS_HSYNC(pipe) _PIPE(pipe, TRANS_HSYNC_A, TRANS_HSYNC_B)
#define TRANS_VTOTAL(pipe) _PIPE(pipe, TRANS_VTOTAL_A, TRANS_VTOTAL_B)
#define TRANS_VBLANK(pipe) _PIPE(pipe, TRANS_VBLANK_A, TRANS_VBLANK_B)
#define TRANS_VSYNC(pipe) _PIPE(pipe, TRANS_VSYNC_A, TRANS_VSYNC_B)
#define TRANSB_DATA_M1 0xe1030 #define TRANSB_DATA_M1 0xe1030
#define TRANSB_DATA_N1 0xe1034 #define TRANSB_DATA_N1 0xe1034
#define TRANSB_DATA_M2 0xe1038 #define TRANSB_DATA_M2 0xe1038
...@@ -2715,6 +2751,7 @@ ...@@ -2715,6 +2751,7 @@
#define TRANSACONF 0xf0008 #define TRANSACONF 0xf0008
#define TRANSBCONF 0xf1008 #define TRANSBCONF 0xf1008
#define TRANSCONF(plane) _PIPE(plane, TRANSACONF, TRANSBCONF)
#define TRANS_DISABLE (0<<31) #define TRANS_DISABLE (0<<31)
#define TRANS_ENABLE (1<<31) #define TRANS_ENABLE (1<<31)
#define TRANS_STATE_MASK (1<<30) #define TRANS_STATE_MASK (1<<30)
...@@ -2739,6 +2776,7 @@ ...@@ -2739,6 +2776,7 @@
/* CPU: FDI_TX */ /* CPU: FDI_TX */
#define FDI_TXA_CTL 0x60100 #define FDI_TXA_CTL 0x60100
#define FDI_TXB_CTL 0x61100 #define FDI_TXB_CTL 0x61100
#define FDI_TX_CTL(pipe) _PIPE(pipe, FDI_TXA_CTL, FDI_TXB_CTL)
#define FDI_TX_DISABLE (0<<31) #define FDI_TX_DISABLE (0<<31)
#define FDI_TX_ENABLE (1<<31) #define FDI_TX_ENABLE (1<<31)
#define FDI_LINK_TRAIN_PATTERN_1 (0<<28) #define FDI_LINK_TRAIN_PATTERN_1 (0<<28)
...@@ -2780,8 +2818,8 @@ ...@@ -2780,8 +2818,8 @@
/* FDI_RX, FDI_X is hard-wired to Transcoder_X */ /* FDI_RX, FDI_X is hard-wired to Transcoder_X */
#define FDI_RXA_CTL 0xf000c #define FDI_RXA_CTL 0xf000c
#define FDI_RXB_CTL 0xf100c #define FDI_RXB_CTL 0xf100c
#define FDI_RX_CTL(pipe) _PIPE(pipe, FDI_RXA_CTL, FDI_RXB_CTL)
#define FDI_RX_ENABLE (1<<31) #define FDI_RX_ENABLE (1<<31)
#define FDI_RX_DISABLE (0<<31)
/* train, dp width same as FDI_TX */ /* train, dp width same as FDI_TX */
#define FDI_DP_PORT_WIDTH_X8 (7<<19) #define FDI_DP_PORT_WIDTH_X8 (7<<19)
#define FDI_8BPC (0<<16) #define FDI_8BPC (0<<16)
...@@ -2796,8 +2834,7 @@ ...@@ -2796,8 +2834,7 @@
#define FDI_FS_ERR_REPORT_ENABLE (1<<9) #define FDI_FS_ERR_REPORT_ENABLE (1<<9)
#define FDI_FE_ERR_REPORT_ENABLE (1<<8) #define FDI_FE_ERR_REPORT_ENABLE (1<<8)
#define FDI_RX_ENHANCE_FRAME_ENABLE (1<<6) #define FDI_RX_ENHANCE_FRAME_ENABLE (1<<6)
#define FDI_SEL_RAWCLK (0<<4) #define FDI_PCDCLK (1<<4)
#define FDI_SEL_PCDCLK (1<<4)
/* CPT */ /* CPT */
#define FDI_AUTO_TRAINING (1<<10) #define FDI_AUTO_TRAINING (1<<10)
#define FDI_LINK_TRAIN_PATTERN_1_CPT (0<<8) #define FDI_LINK_TRAIN_PATTERN_1_CPT (0<<8)
...@@ -2812,6 +2849,9 @@ ...@@ -2812,6 +2849,9 @@
#define FDI_RXA_TUSIZE2 0xf0038 #define FDI_RXA_TUSIZE2 0xf0038
#define FDI_RXB_TUSIZE1 0xf1030 #define FDI_RXB_TUSIZE1 0xf1030
#define FDI_RXB_TUSIZE2 0xf1038 #define FDI_RXB_TUSIZE2 0xf1038
#define FDI_RX_MISC(pipe) _PIPE(pipe, FDI_RXA_MISC, FDI_RXB_MISC)
#define FDI_RX_TUSIZE1(pipe) _PIPE(pipe, FDI_RXA_TUSIZE1, FDI_RXB_TUSIZE1)
#define FDI_RX_TUSIZE2(pipe) _PIPE(pipe, FDI_RXA_TUSIZE2, FDI_RXB_TUSIZE2)
/* FDI_RX interrupt register format */ /* FDI_RX interrupt register format */
#define FDI_RX_INTER_LANE_ALIGN (1<<10) #define FDI_RX_INTER_LANE_ALIGN (1<<10)
...@@ -2830,6 +2870,8 @@ ...@@ -2830,6 +2870,8 @@
#define FDI_RXA_IMR 0xf0018 #define FDI_RXA_IMR 0xf0018
#define FDI_RXB_IIR 0xf1014 #define FDI_RXB_IIR 0xf1014
#define FDI_RXB_IMR 0xf1018 #define FDI_RXB_IMR 0xf1018
#define FDI_RX_IIR(pipe) _PIPE(pipe, FDI_RXA_IIR, FDI_RXB_IIR)
#define FDI_RX_IMR(pipe) _PIPE(pipe, FDI_RXA_IMR, FDI_RXB_IMR)
#define FDI_PLL_CTL_1 0xfe000 #define FDI_PLL_CTL_1 0xfe000
#define FDI_PLL_CTL_2 0xfe004 #define FDI_PLL_CTL_2 0xfe004
...@@ -2949,6 +2991,7 @@ ...@@ -2949,6 +2991,7 @@
#define TRANS_DP_CTL_A 0xe0300 #define TRANS_DP_CTL_A 0xe0300
#define TRANS_DP_CTL_B 0xe1300 #define TRANS_DP_CTL_B 0xe1300
#define TRANS_DP_CTL_C 0xe2300 #define TRANS_DP_CTL_C 0xe2300
#define TRANS_DP_CTL(pipe) (TRANS_DP_CTL_A + (pipe) * 0x01000)
#define TRANS_DP_OUTPUT_ENABLE (1<<31) #define TRANS_DP_OUTPUT_ENABLE (1<<31)
#define TRANS_DP_PORT_SEL_B (0<<29) #define TRANS_DP_PORT_SEL_B (0<<29)
#define TRANS_DP_PORT_SEL_C (1<<29) #define TRANS_DP_PORT_SEL_C (1<<29)
......
...@@ -959,26 +959,26 @@ static bool ...@@ -959,26 +959,26 @@ static bool
intel_find_pll_g4x_dp(const intel_limit_t *limit, struct drm_crtc *crtc, intel_find_pll_g4x_dp(const intel_limit_t *limit, struct drm_crtc *crtc,
int target, int refclk, intel_clock_t *best_clock) int target, int refclk, intel_clock_t *best_clock)
{ {
intel_clock_t clock; intel_clock_t clock;
if (target < 200000) { if (target < 200000) {
clock.p1 = 2; clock.p1 = 2;
clock.p2 = 10; clock.p2 = 10;
clock.n = 2; clock.n = 2;
clock.m1 = 23; clock.m1 = 23;
clock.m2 = 8; clock.m2 = 8;
} else { } else {
clock.p1 = 1; clock.p1 = 1;
clock.p2 = 10; clock.p2 = 10;
clock.n = 1; clock.n = 1;
clock.m1 = 14; clock.m1 = 14;
clock.m2 = 2; clock.m2 = 2;
} }
clock.m = 5 * (clock.m1 + 2) + (clock.m2 + 2); clock.m = 5 * (clock.m1 + 2) + (clock.m2 + 2);
clock.p = (clock.p1 * clock.p2); clock.p = (clock.p1 * clock.p2);
clock.dot = 96000 * clock.m / (clock.n + 2) / clock.p; clock.dot = 96000 * clock.m / (clock.n + 2) / clock.p;
clock.vco = 0; clock.vco = 0;
memcpy(best_clock, &clock, sizeof(intel_clock_t)); memcpy(best_clock, &clock, sizeof(intel_clock_t));
return true; return true;
} }
/** /**
...@@ -1099,7 +1099,7 @@ static void i8xx_enable_fbc(struct drm_crtc *crtc, unsigned long interval) ...@@ -1099,7 +1099,7 @@ static void i8xx_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
I915_WRITE(FBC_CONTROL, fbc_ctl); I915_WRITE(FBC_CONTROL, fbc_ctl);
DRM_DEBUG_KMS("enabled FBC, pitch %ld, yoff %d, plane %d, ", DRM_DEBUG_KMS("enabled FBC, pitch %ld, yoff %d, plane %d, ",
dev_priv->cfb_pitch, crtc->y, dev_priv->cfb_plane); dev_priv->cfb_pitch, crtc->y, dev_priv->cfb_plane);
} }
void i8xx_disable_fbc(struct drm_device *dev) void i8xx_disable_fbc(struct drm_device *dev)
...@@ -1136,8 +1136,7 @@ static void g4x_enable_fbc(struct drm_crtc *crtc, unsigned long interval) ...@@ -1136,8 +1136,7 @@ static void g4x_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
struct drm_i915_gem_object *obj_priv = to_intel_bo(intel_fb->obj); struct drm_i915_gem_object *obj_priv = to_intel_bo(intel_fb->obj);
struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
int plane = (intel_crtc->plane == 0 ? DPFC_CTL_PLANEA : int plane = intel_crtc->plane == 0 ? DPFC_CTL_PLANEA : DPFC_CTL_PLANEB;
DPFC_CTL_PLANEB);
unsigned long stall_watermark = 200; unsigned long stall_watermark = 200;
u32 dpfc_ctl; u32 dpfc_ctl;
...@@ -1208,8 +1207,7 @@ static void ironlake_enable_fbc(struct drm_crtc *crtc, unsigned long interval) ...@@ -1208,8 +1207,7 @@ static void ironlake_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
struct drm_i915_gem_object *obj_priv = to_intel_bo(intel_fb->obj); struct drm_i915_gem_object *obj_priv = to_intel_bo(intel_fb->obj);
struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
int plane = (intel_crtc->plane == 0) ? DPFC_CTL_PLANEA : int plane = intel_crtc->plane == 0 ? DPFC_CTL_PLANEA : DPFC_CTL_PLANEB;
DPFC_CTL_PLANEB;
unsigned long stall_watermark = 200; unsigned long stall_watermark = 200;
u32 dpfc_ctl; u32 dpfc_ctl;
...@@ -1374,14 +1372,14 @@ static void intel_update_fbc(struct drm_device *dev) ...@@ -1374,14 +1372,14 @@ static void intel_update_fbc(struct drm_device *dev)
if (intel_fb->obj->size > dev_priv->cfb_size) { if (intel_fb->obj->size > dev_priv->cfb_size) {
DRM_DEBUG_KMS("framebuffer too large, disabling " DRM_DEBUG_KMS("framebuffer too large, disabling "
"compression\n"); "compression\n");
dev_priv->no_fbc_reason = FBC_STOLEN_TOO_SMALL; dev_priv->no_fbc_reason = FBC_STOLEN_TOO_SMALL;
goto out_disable; goto out_disable;
} }
if ((crtc->mode.flags & DRM_MODE_FLAG_INTERLACE) || if ((crtc->mode.flags & DRM_MODE_FLAG_INTERLACE) ||
(crtc->mode.flags & DRM_MODE_FLAG_DBLSCAN)) { (crtc->mode.flags & DRM_MODE_FLAG_DBLSCAN)) {
DRM_DEBUG_KMS("mode incompatible with compression, " DRM_DEBUG_KMS("mode incompatible with compression, "
"disabling\n"); "disabling\n");
dev_priv->no_fbc_reason = FBC_UNSUPPORTED_MODE; dev_priv->no_fbc_reason = FBC_UNSUPPORTED_MODE;
goto out_disable; goto out_disable;
} }
...@@ -1479,12 +1477,8 @@ intel_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb, ...@@ -1479,12 +1477,8 @@ intel_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb,
struct drm_gem_object *obj; struct drm_gem_object *obj;
int plane = intel_crtc->plane; int plane = intel_crtc->plane;
unsigned long Start, Offset; unsigned long Start, Offset;
int dspbase = (plane == 0 ? DSPAADDR : DSPBADDR);
int dspsurf = (plane == 0 ? DSPASURF : DSPBSURF);
int dspstride = (plane == 0) ? DSPASTRIDE : DSPBSTRIDE;
int dsptileoff = (plane == 0 ? DSPATILEOFF : DSPBTILEOFF);
int dspcntr_reg = (plane == 0) ? DSPACNTR : DSPBCNTR;
u32 dspcntr; u32 dspcntr;
u32 reg;
switch (plane) { switch (plane) {
case 0: case 0:
...@@ -1499,7 +1493,8 @@ intel_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb, ...@@ -1499,7 +1493,8 @@ intel_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb,
obj = intel_fb->obj; obj = intel_fb->obj;
obj_priv = to_intel_bo(obj); obj_priv = to_intel_bo(obj);
dspcntr = I915_READ(dspcntr_reg); reg = DSPCNTR(plane);
dspcntr = I915_READ(reg);
/* Mask out pixel format bits in case we change it */ /* Mask out pixel format bits in case we change it */
dspcntr &= ~DISPPLANE_PIXFORMAT_MASK; dspcntr &= ~DISPPLANE_PIXFORMAT_MASK;
switch (fb->bits_per_pixel) { switch (fb->bits_per_pixel) {
...@@ -1531,22 +1526,21 @@ intel_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb, ...@@ -1531,22 +1526,21 @@ intel_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb,
/* must disable */ /* must disable */
dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE; dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE;
I915_WRITE(dspcntr_reg, dspcntr); I915_WRITE(reg, dspcntr);
Start = obj_priv->gtt_offset; Start = obj_priv->gtt_offset;
Offset = y * fb->pitch + x * (fb->bits_per_pixel / 8); Offset = y * fb->pitch + x * (fb->bits_per_pixel / 8);
DRM_DEBUG_KMS("Writing base %08lX %08lX %d %d %d\n", DRM_DEBUG_KMS("Writing base %08lX %08lX %d %d %d\n",
Start, Offset, x, y, fb->pitch); Start, Offset, x, y, fb->pitch);
I915_WRITE(dspstride, fb->pitch); I915_WRITE(DSPSTRIDE(plane), fb->pitch);
if (IS_I965G(dev)) { if (IS_I965G(dev)) {
I915_WRITE(dspsurf, Start); I915_WRITE(DSPSURF(plane), Start);
I915_WRITE(dsptileoff, (y << 16) | x); I915_WRITE(DSPTILEOFF(plane), (y << 16) | x);
I915_WRITE(dspbase, Offset); I915_WRITE(DSPADDR(plane), Offset);
} else { } else
I915_WRITE(dspbase, Start + Offset); I915_WRITE(DSPADDR(plane), Start + Offset);
} POSTING_READ(reg);
POSTING_READ(dspbase);
intel_update_fbc(dev); intel_update_fbc(dev);
intel_increase_pllclock(crtc); intel_increase_pllclock(crtc);
...@@ -1634,7 +1628,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, ...@@ -1634,7 +1628,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
return 0; return 0;
} }
static void ironlake_set_pll_edp (struct drm_crtc *crtc, int clock) static void ironlake_set_pll_edp(struct drm_crtc *crtc, int clock)
{ {
struct drm_device *dev = crtc->dev; struct drm_device *dev = crtc->dev;
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
...@@ -1666,8 +1660,8 @@ static void ironlake_set_pll_edp (struct drm_crtc *crtc, int clock) ...@@ -1666,8 +1660,8 @@ static void ironlake_set_pll_edp (struct drm_crtc *crtc, int clock)
dpa_ctl |= DP_PLL_FREQ_270MHZ; dpa_ctl |= DP_PLL_FREQ_270MHZ;
} }
I915_WRITE(DP_A, dpa_ctl); I915_WRITE(DP_A, dpa_ctl);
POSTING_READ(DP_A);
POSTING_READ(DP_A);
udelay(500); udelay(500);
} }
...@@ -1678,85 +1672,84 @@ static void ironlake_fdi_link_train(struct drm_crtc *crtc) ...@@ -1678,85 +1672,84 @@ static void ironlake_fdi_link_train(struct drm_crtc *crtc)
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
int pipe = intel_crtc->pipe; int pipe = intel_crtc->pipe;
int fdi_tx_reg = (pipe == 0) ? FDI_TXA_CTL : FDI_TXB_CTL; u32 reg, temp, tries;
int fdi_rx_reg = (pipe == 0) ? FDI_RXA_CTL : FDI_RXB_CTL;
int fdi_rx_iir_reg = (pipe == 0) ? FDI_RXA_IIR : FDI_RXB_IIR;
int fdi_rx_imr_reg = (pipe == 0) ? FDI_RXA_IMR : FDI_RXB_IMR;
u32 temp, tries = 0;
/* Train 1: umask FDI RX Interrupt symbol_lock and bit_lock bit /* Train 1: umask FDI RX Interrupt symbol_lock and bit_lock bit
for train result */ for train result */
temp = I915_READ(fdi_rx_imr_reg); reg = FDI_RX_IMR(pipe);
temp = I915_READ(reg);
temp &= ~FDI_RX_SYMBOL_LOCK; temp &= ~FDI_RX_SYMBOL_LOCK;
temp &= ~FDI_RX_BIT_LOCK; temp &= ~FDI_RX_BIT_LOCK;
I915_WRITE(fdi_rx_imr_reg, temp); I915_WRITE(reg, temp);
I915_READ(fdi_rx_imr_reg); I915_READ(reg);
udelay(150); udelay(150);
/* enable CPU FDI TX and PCH FDI RX */ /* enable CPU FDI TX and PCH FDI RX */
temp = I915_READ(fdi_tx_reg); reg = FDI_TX_CTL(pipe);
temp |= FDI_TX_ENABLE; temp = I915_READ(reg);
temp &= ~(7 << 19); temp &= ~(7 << 19);
temp |= (intel_crtc->fdi_lanes - 1) << 19; temp |= (intel_crtc->fdi_lanes - 1) << 19;
temp &= ~FDI_LINK_TRAIN_NONE; temp &= ~FDI_LINK_TRAIN_NONE;
temp |= FDI_LINK_TRAIN_PATTERN_1; temp |= FDI_LINK_TRAIN_PATTERN_1;
I915_WRITE(fdi_tx_reg, temp); I915_WRITE(reg, temp | FDI_TX_ENABLE);
I915_READ(fdi_tx_reg);
temp = I915_READ(fdi_rx_reg); reg = FDI_RX_CTL(pipe);
temp = I915_READ(reg);
temp &= ~FDI_LINK_TRAIN_NONE; temp &= ~FDI_LINK_TRAIN_NONE;
temp |= FDI_LINK_TRAIN_PATTERN_1; temp |= FDI_LINK_TRAIN_PATTERN_1;
I915_WRITE(fdi_rx_reg, temp | FDI_RX_ENABLE); I915_WRITE(reg, temp | FDI_RX_ENABLE);
I915_READ(fdi_rx_reg);
POSTING_READ(reg);
udelay(150); udelay(150);
reg = FDI_RX_IIR(pipe);
for (tries = 0; tries < 5; tries++) { for (tries = 0; tries < 5; tries++) {
temp = I915_READ(fdi_rx_iir_reg); temp = I915_READ(reg);
DRM_DEBUG_KMS("FDI_RX_IIR 0x%x\n", temp); DRM_DEBUG_KMS("FDI_RX_IIR 0x%x\n", temp);
if ((temp & FDI_RX_BIT_LOCK)) { if ((temp & FDI_RX_BIT_LOCK)) {
DRM_DEBUG_KMS("FDI train 1 done.\n"); DRM_DEBUG_KMS("FDI train 1 done.\n");
I915_WRITE(fdi_rx_iir_reg, I915_WRITE(reg, temp | FDI_RX_BIT_LOCK);
temp | FDI_RX_BIT_LOCK);
break; break;
} }
} }
if (tries == 5) if (tries == 5)
DRM_DEBUG_KMS("FDI train 1 fail!\n"); DRM_ERROR("FDI train 1 fail!\n");
/* Train 2 */ /* Train 2 */
temp = I915_READ(fdi_tx_reg); reg = FDI_TX_CTL(pipe);
temp = I915_READ(reg);
temp &= ~FDI_LINK_TRAIN_NONE; temp &= ~FDI_LINK_TRAIN_NONE;
temp |= FDI_LINK_TRAIN_PATTERN_2; temp |= FDI_LINK_TRAIN_PATTERN_2;
I915_WRITE(fdi_tx_reg, temp); I915_WRITE(reg, temp);
temp = I915_READ(fdi_rx_reg); reg = FDI_RX_CTL(pipe);
temp = I915_READ(reg);
temp &= ~FDI_LINK_TRAIN_NONE; temp &= ~FDI_LINK_TRAIN_NONE;
temp |= FDI_LINK_TRAIN_PATTERN_2; temp |= FDI_LINK_TRAIN_PATTERN_2;
I915_WRITE(fdi_rx_reg, temp); I915_WRITE(reg, temp);
POSTING_READ(fdi_rx_reg);
udelay(150);
tries = 0; POSTING_READ(reg);
udelay(150);
reg = FDI_RX_IIR(pipe);
for (tries = 0; tries < 5; tries++) { for (tries = 0; tries < 5; tries++) {
temp = I915_READ(fdi_rx_iir_reg); temp = I915_READ(reg);
DRM_DEBUG_KMS("FDI_RX_IIR 0x%x\n", temp); DRM_DEBUG_KMS("FDI_RX_IIR 0x%x\n", temp);
if (temp & FDI_RX_SYMBOL_LOCK) { if (temp & FDI_RX_SYMBOL_LOCK) {
I915_WRITE(fdi_rx_iir_reg, I915_WRITE(reg, temp | FDI_RX_SYMBOL_LOCK);
temp | FDI_RX_SYMBOL_LOCK);
DRM_DEBUG_KMS("FDI train 2 done.\n"); DRM_DEBUG_KMS("FDI train 2 done.\n");
break; break;
} }
} }
if (tries == 5) if (tries == 5)
DRM_DEBUG_KMS("FDI train 2 fail!\n"); DRM_ERROR("FDI train 2 fail!\n");
DRM_DEBUG_KMS("FDI train done\n"); DRM_DEBUG_KMS("FDI train done\n");
} }
static int snb_b_fdi_train_param [] = { static const int const snb_b_fdi_train_param [] = {
FDI_LINK_TRAIN_400MV_0DB_SNB_B, FDI_LINK_TRAIN_400MV_0DB_SNB_B,
FDI_LINK_TRAIN_400MV_6DB_SNB_B, FDI_LINK_TRAIN_400MV_6DB_SNB_B,
FDI_LINK_TRAIN_600MV_3_5DB_SNB_B, FDI_LINK_TRAIN_600MV_3_5DB_SNB_B,
...@@ -1770,24 +1763,22 @@ static void gen6_fdi_link_train(struct drm_crtc *crtc) ...@@ -1770,24 +1763,22 @@ static void gen6_fdi_link_train(struct drm_crtc *crtc)
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
int pipe = intel_crtc->pipe; int pipe = intel_crtc->pipe;
int fdi_tx_reg = (pipe == 0) ? FDI_TXA_CTL : FDI_TXB_CTL; u32 reg, temp, i;
int fdi_rx_reg = (pipe == 0) ? FDI_RXA_CTL : FDI_RXB_CTL;
int fdi_rx_iir_reg = (pipe == 0) ? FDI_RXA_IIR : FDI_RXB_IIR;
int fdi_rx_imr_reg = (pipe == 0) ? FDI_RXA_IMR : FDI_RXB_IMR;
u32 temp, i;
/* Train 1: umask FDI RX Interrupt symbol_lock and bit_lock bit /* Train 1: umask FDI RX Interrupt symbol_lock and bit_lock bit
for train result */ for train result */
temp = I915_READ(fdi_rx_imr_reg); reg = FDI_RX_IMR(pipe);
temp = I915_READ(reg);
temp &= ~FDI_RX_SYMBOL_LOCK; temp &= ~FDI_RX_SYMBOL_LOCK;
temp &= ~FDI_RX_BIT_LOCK; temp &= ~FDI_RX_BIT_LOCK;
I915_WRITE(fdi_rx_imr_reg, temp); I915_WRITE(reg, temp);
I915_READ(fdi_rx_imr_reg);
POSTING_READ(reg);
udelay(150); udelay(150);
/* enable CPU FDI TX and PCH FDI RX */ /* enable CPU FDI TX and PCH FDI RX */
temp = I915_READ(fdi_tx_reg); reg = FDI_TX_CTL(pipe);
temp |= FDI_TX_ENABLE; temp = I915_READ(reg);
temp &= ~(7 << 19); temp &= ~(7 << 19);
temp |= (intel_crtc->fdi_lanes - 1) << 19; temp |= (intel_crtc->fdi_lanes - 1) << 19;
temp &= ~FDI_LINK_TRAIN_NONE; temp &= ~FDI_LINK_TRAIN_NONE;
...@@ -1795,10 +1786,10 @@ static void gen6_fdi_link_train(struct drm_crtc *crtc) ...@@ -1795,10 +1786,10 @@ static void gen6_fdi_link_train(struct drm_crtc *crtc)
temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK; temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK;
/* SNB-B */ /* SNB-B */
temp |= FDI_LINK_TRAIN_400MV_0DB_SNB_B; temp |= FDI_LINK_TRAIN_400MV_0DB_SNB_B;
I915_WRITE(fdi_tx_reg, temp); I915_WRITE(reg, temp | FDI_TX_ENABLE);
I915_READ(fdi_tx_reg);
temp = I915_READ(fdi_rx_reg); reg = FDI_RX_CTL(pipe);
temp = I915_READ(reg);
if (HAS_PCH_CPT(dev)) { if (HAS_PCH_CPT(dev)) {
temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT; temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT;
temp |= FDI_LINK_TRAIN_PATTERN_1_CPT; temp |= FDI_LINK_TRAIN_PATTERN_1_CPT;
...@@ -1806,33 +1797,37 @@ static void gen6_fdi_link_train(struct drm_crtc *crtc) ...@@ -1806,33 +1797,37 @@ static void gen6_fdi_link_train(struct drm_crtc *crtc)
temp &= ~FDI_LINK_TRAIN_NONE; temp &= ~FDI_LINK_TRAIN_NONE;
temp |= FDI_LINK_TRAIN_PATTERN_1; temp |= FDI_LINK_TRAIN_PATTERN_1;
} }
I915_WRITE(fdi_rx_reg, temp | FDI_RX_ENABLE); I915_WRITE(reg, temp | FDI_RX_ENABLE);
I915_READ(fdi_rx_reg);
POSTING_READ(reg);
udelay(150); udelay(150);
for (i = 0; i < 4; i++ ) { for (i = 0; i < 4; i++ ) {
temp = I915_READ(fdi_tx_reg); reg = FDI_TX_CTL(pipe);
temp = I915_READ(reg);
temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK; temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK;
temp |= snb_b_fdi_train_param[i]; temp |= snb_b_fdi_train_param[i];
I915_WRITE(fdi_tx_reg, temp); I915_WRITE(reg, temp);
POSTING_READ(fdi_tx_reg);
POSTING_READ(reg);
udelay(500); udelay(500);
temp = I915_READ(fdi_rx_iir_reg); reg = FDI_RX_IIR(pipe);
temp = I915_READ(reg);
DRM_DEBUG_KMS("FDI_RX_IIR 0x%x\n", temp); DRM_DEBUG_KMS("FDI_RX_IIR 0x%x\n", temp);
if (temp & FDI_RX_BIT_LOCK) { if (temp & FDI_RX_BIT_LOCK) {
I915_WRITE(fdi_rx_iir_reg, I915_WRITE(reg, temp | FDI_RX_BIT_LOCK);
temp | FDI_RX_BIT_LOCK);
DRM_DEBUG_KMS("FDI train 1 done.\n"); DRM_DEBUG_KMS("FDI train 1 done.\n");
break; break;
} }
} }
if (i == 4) if (i == 4)
DRM_DEBUG_KMS("FDI train 1 fail!\n"); DRM_ERROR("FDI train 1 fail!\n");
/* Train 2 */ /* Train 2 */
temp = I915_READ(fdi_tx_reg); reg = FDI_TX_CTL(pipe);
temp = I915_READ(reg);
temp &= ~FDI_LINK_TRAIN_NONE; temp &= ~FDI_LINK_TRAIN_NONE;
temp |= FDI_LINK_TRAIN_PATTERN_2; temp |= FDI_LINK_TRAIN_PATTERN_2;
if (IS_GEN6(dev)) { if (IS_GEN6(dev)) {
...@@ -1840,9 +1835,10 @@ static void gen6_fdi_link_train(struct drm_crtc *crtc) ...@@ -1840,9 +1835,10 @@ static void gen6_fdi_link_train(struct drm_crtc *crtc)
/* SNB-B */ /* SNB-B */
temp |= FDI_LINK_TRAIN_400MV_0DB_SNB_B; temp |= FDI_LINK_TRAIN_400MV_0DB_SNB_B;
} }
I915_WRITE(fdi_tx_reg, temp); I915_WRITE(reg, temp);
temp = I915_READ(fdi_rx_reg); reg = FDI_RX_CTL(pipe);
temp = I915_READ(reg);
if (HAS_PCH_CPT(dev)) { if (HAS_PCH_CPT(dev)) {
temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT; temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT;
temp |= FDI_LINK_TRAIN_PATTERN_2_CPT; temp |= FDI_LINK_TRAIN_PATTERN_2_CPT;
...@@ -1850,30 +1846,33 @@ static void gen6_fdi_link_train(struct drm_crtc *crtc) ...@@ -1850,30 +1846,33 @@ static void gen6_fdi_link_train(struct drm_crtc *crtc)
temp &= ~FDI_LINK_TRAIN_NONE; temp &= ~FDI_LINK_TRAIN_NONE;
temp |= FDI_LINK_TRAIN_PATTERN_2; temp |= FDI_LINK_TRAIN_PATTERN_2;
} }
I915_WRITE(fdi_rx_reg, temp); I915_WRITE(reg, temp);
POSTING_READ(fdi_rx_reg);
POSTING_READ(reg);
udelay(150); udelay(150);
for (i = 0; i < 4; i++ ) { for (i = 0; i < 4; i++ ) {
temp = I915_READ(fdi_tx_reg); reg = FDI_TX_CTL(pipe);
temp = I915_READ(reg);
temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK; temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK;
temp |= snb_b_fdi_train_param[i]; temp |= snb_b_fdi_train_param[i];
I915_WRITE(fdi_tx_reg, temp); I915_WRITE(reg, temp);
POSTING_READ(fdi_tx_reg);
POSTING_READ(reg);
udelay(500); udelay(500);
temp = I915_READ(fdi_rx_iir_reg); reg = FDI_RX_IIR(pipe);
temp = I915_READ(reg);
DRM_DEBUG_KMS("FDI_RX_IIR 0x%x\n", temp); DRM_DEBUG_KMS("FDI_RX_IIR 0x%x\n", temp);
if (temp & FDI_RX_SYMBOL_LOCK) { if (temp & FDI_RX_SYMBOL_LOCK) {
I915_WRITE(fdi_rx_iir_reg, I915_WRITE(reg, temp | FDI_RX_SYMBOL_LOCK);
temp | FDI_RX_SYMBOL_LOCK);
DRM_DEBUG_KMS("FDI train 2 done.\n"); DRM_DEBUG_KMS("FDI train 2 done.\n");
break; break;
} }
} }
if (i == 4) if (i == 4)
DRM_DEBUG_KMS("FDI train 2 fail!\n"); DRM_ERROR("FDI train 2 fail!\n");
DRM_DEBUG_KMS("FDI train done.\n"); DRM_DEBUG_KMS("FDI train done.\n");
} }
...@@ -1884,50 +1883,49 @@ static void ironlake_fdi_enable(struct drm_crtc *crtc) ...@@ -1884,50 +1883,49 @@ static void ironlake_fdi_enable(struct drm_crtc *crtc)
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
int pipe = intel_crtc->pipe; int pipe = intel_crtc->pipe;
int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; u32 reg, temp;
int fdi_tx_reg = (pipe == 0) ? FDI_TXA_CTL : FDI_TXB_CTL;
int fdi_rx_reg = (pipe == 0) ? FDI_RXA_CTL : FDI_RXB_CTL;
int data_m1_reg = (pipe == 0) ? PIPEA_DATA_M1 : PIPEB_DATA_M1;
u32 temp;
u32 pipe_bpc;
u32 tx_size;
temp = I915_READ(pipeconf_reg);
pipe_bpc = temp & PIPE_BPC_MASK;
/* Write the TU size bits so error detection works */ /* Write the TU size bits so error detection works */
tx_size = I915_READ(data_m1_reg) & TU_SIZE_MASK; I915_WRITE(FDI_RX_TUSIZE1(pipe),
I915_WRITE(FDI_RXA_TUSIZE1, tx_size); I915_READ(PIPE_DATA_M1(pipe)) & TU_SIZE_MASK);
/* enable PCH FDI RX PLL, wait warmup plus DMI latency */ /* enable PCH FDI RX PLL, wait warmup plus DMI latency */
temp = I915_READ(fdi_rx_reg); reg = FDI_RX_CTL(pipe);
/* temp = I915_READ(reg);
* make the BPC in FDI Rx be consistent with that in temp &= ~((0x7 << 19) | (0x7 << 16));
* pipeconf reg.
*/
temp &= ~(0x7 << 16);
temp |= (pipe_bpc << 11);
temp &= ~(7 << 19);
temp |= (intel_crtc->fdi_lanes - 1) << 19; temp |= (intel_crtc->fdi_lanes - 1) << 19;
I915_WRITE(fdi_rx_reg, temp | FDI_RX_PLL_ENABLE); temp |= (I915_READ(PIPECONF(pipe)) & PIPE_BPC_MASK) << 11;
I915_READ(fdi_rx_reg); I915_WRITE(reg, temp | FDI_RX_PLL_ENABLE);
POSTING_READ(reg);
udelay(200); udelay(200);
/* Switch from Rawclk to PCDclk */ /* Switch from Rawclk to PCDclk */
temp = I915_READ(fdi_rx_reg); temp = I915_READ(reg);
I915_WRITE(fdi_rx_reg, temp | FDI_SEL_PCDCLK); I915_WRITE(reg, temp | FDI_PCDCLK);
I915_READ(fdi_rx_reg);
POSTING_READ(reg);
udelay(200); udelay(200);
/* Enable CPU FDI TX PLL, always on for Ironlake */ /* Enable CPU FDI TX PLL, always on for Ironlake */
temp = I915_READ(fdi_tx_reg); reg = FDI_TX_CTL(pipe);
temp = I915_READ(reg);
if ((temp & FDI_TX_PLL_ENABLE) == 0) { if ((temp & FDI_TX_PLL_ENABLE) == 0) {
I915_WRITE(fdi_tx_reg, temp | FDI_TX_PLL_ENABLE); I915_WRITE(reg, temp | FDI_TX_PLL_ENABLE);
I915_READ(fdi_tx_reg);
POSTING_READ(reg);
udelay(100); udelay(100);
} }
} }
static void intel_flush_display_plane(struct drm_device *dev,
int plane)
{
struct drm_i915_private *dev_priv = dev->dev_private;
u32 reg = DSPADDR(plane);
I915_WRITE(reg, I915_READ(reg));
}
static void ironlake_crtc_enable(struct drm_crtc *crtc) static void ironlake_crtc_enable(struct drm_crtc *crtc)
{ {
struct drm_device *dev = crtc->dev; struct drm_device *dev = crtc->dev;
...@@ -1935,38 +1933,12 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc) ...@@ -1935,38 +1933,12 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
int pipe = intel_crtc->pipe; int pipe = intel_crtc->pipe;
int plane = intel_crtc->plane; int plane = intel_crtc->plane;
int pch_dpll_reg = (pipe == 0) ? PCH_DPLL_A : PCH_DPLL_B; u32 reg, temp;
int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
int dspcntr_reg = (plane == 0) ? DSPACNTR : DSPBCNTR;
int dspbase_reg = (plane == 0) ? DSPAADDR : DSPBADDR;
int fdi_tx_reg = (pipe == 0) ? FDI_TXA_CTL : FDI_TXB_CTL;
int fdi_rx_reg = (pipe == 0) ? FDI_RXA_CTL : FDI_RXB_CTL;
int transconf_reg = (pipe == 0) ? TRANSACONF : TRANSBCONF;
int cpu_htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B;
int cpu_hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B;
int cpu_hsync_reg = (pipe == 0) ? HSYNC_A : HSYNC_B;
int cpu_vtot_reg = (pipe == 0) ? VTOTAL_A : VTOTAL_B;
int cpu_vblank_reg = (pipe == 0) ? VBLANK_A : VBLANK_B;
int cpu_vsync_reg = (pipe == 0) ? VSYNC_A : VSYNC_B;
int trans_htot_reg = (pipe == 0) ? TRANS_HTOTAL_A : TRANS_HTOTAL_B;
int trans_hblank_reg = (pipe == 0) ? TRANS_HBLANK_A : TRANS_HBLANK_B;
int trans_hsync_reg = (pipe == 0) ? TRANS_HSYNC_A : TRANS_HSYNC_B;
int trans_vtot_reg = (pipe == 0) ? TRANS_VTOTAL_A : TRANS_VTOTAL_B;
int trans_vblank_reg = (pipe == 0) ? TRANS_VBLANK_A : TRANS_VBLANK_B;
int trans_vsync_reg = (pipe == 0) ? TRANS_VSYNC_A : TRANS_VSYNC_B;
int trans_dpll_sel = (pipe == 0) ? 0 : 1;
u32 temp;
u32 pipe_bpc;
temp = I915_READ(pipeconf_reg);
pipe_bpc = temp & PIPE_BPC_MASK;
if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) { if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
temp = I915_READ(PCH_LVDS); temp = I915_READ(PCH_LVDS);
if ((temp & LVDS_PORT_EN) == 0) { if ((temp & LVDS_PORT_EN) == 0)
I915_WRITE(PCH_LVDS, temp | LVDS_PORT_EN); I915_WRITE(PCH_LVDS, temp | LVDS_PORT_EN);
POSTING_READ(PCH_LVDS);
}
} }
ironlake_fdi_enable(crtc); ironlake_fdi_enable(crtc);
...@@ -1988,19 +1960,20 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc) ...@@ -1988,19 +1960,20 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
} }
/* Enable CPU pipe */ /* Enable CPU pipe */
temp = I915_READ(pipeconf_reg); reg = PIPECONF(pipe);
if ((temp & PIPEACONF_ENABLE) == 0) { temp = I915_READ(reg);
I915_WRITE(pipeconf_reg, temp | PIPEACONF_ENABLE); if ((temp & PIPECONF_ENABLE) == 0) {
I915_READ(pipeconf_reg); I915_WRITE(reg, temp | PIPECONF_ENABLE);
POSTING_READ(reg);
udelay(100); udelay(100);
} }
/* configure and enable CPU plane */ /* configure and enable CPU plane */
temp = I915_READ(dspcntr_reg); reg = DSPCNTR(plane);
temp = I915_READ(reg);
if ((temp & DISPLAY_PLANE_ENABLE) == 0) { if ((temp & DISPLAY_PLANE_ENABLE) == 0) {
I915_WRITE(dspcntr_reg, temp | DISPLAY_PLANE_ENABLE); I915_WRITE(reg, temp | DISPLAY_PLANE_ENABLE);
/* Flush the plane changes */ intel_flush_display_plane(dev, plane);
I915_WRITE(dspbase_reg, I915_READ(dspbase_reg));
} }
/* For PCH output, training FDI link */ /* For PCH output, training FDI link */
...@@ -2010,42 +1983,42 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc) ...@@ -2010,42 +1983,42 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
ironlake_fdi_link_train(crtc); ironlake_fdi_link_train(crtc);
/* enable PCH DPLL */ /* enable PCH DPLL */
temp = I915_READ(pch_dpll_reg); reg = PCH_DPLL(pipe);
temp = I915_READ(reg);
if ((temp & DPLL_VCO_ENABLE) == 0) { if ((temp & DPLL_VCO_ENABLE) == 0) {
I915_WRITE(pch_dpll_reg, temp | DPLL_VCO_ENABLE); I915_WRITE(reg, temp | DPLL_VCO_ENABLE);
I915_READ(pch_dpll_reg); POSTING_READ(reg);
udelay(200); udelay(200);
} }
if (HAS_PCH_CPT(dev)) { if (HAS_PCH_CPT(dev)) {
/* Be sure PCH DPLL SEL is set */ /* Be sure PCH DPLL SEL is set */
temp = I915_READ(PCH_DPLL_SEL); temp = I915_READ(PCH_DPLL_SEL);
if (trans_dpll_sel == 0 && if (pipe == 0 && (temp & TRANSA_DPLL_ENABLE) == 0)
(temp & TRANSA_DPLL_ENABLE) == 0)
temp |= (TRANSA_DPLL_ENABLE | TRANSA_DPLLA_SEL); temp |= (TRANSA_DPLL_ENABLE | TRANSA_DPLLA_SEL);
else if (trans_dpll_sel == 1 && else if (pipe == 1 && (temp & TRANSB_DPLL_ENABLE) == 0)
(temp & TRANSB_DPLL_ENABLE) == 0)
temp |= (TRANSB_DPLL_ENABLE | TRANSB_DPLLB_SEL); temp |= (TRANSB_DPLL_ENABLE | TRANSB_DPLLB_SEL);
I915_WRITE(PCH_DPLL_SEL, temp); I915_WRITE(PCH_DPLL_SEL, temp);
I915_READ(PCH_DPLL_SEL);
} }
/* set transcoder timing */ /* set transcoder timing */
I915_WRITE(trans_htot_reg, I915_READ(cpu_htot_reg)); I915_WRITE(TRANS_HTOTAL(pipe), I915_READ(HTOTAL(pipe)));
I915_WRITE(trans_hblank_reg, I915_READ(cpu_hblank_reg)); I915_WRITE(TRANS_HBLANK(pipe), I915_READ(HBLANK(pipe)));
I915_WRITE(trans_hsync_reg, I915_READ(cpu_hsync_reg)); I915_WRITE(TRANS_HSYNC(pipe), I915_READ(HSYNC(pipe)));
I915_WRITE(trans_vtot_reg, I915_READ(cpu_vtot_reg)); I915_WRITE(TRANS_VTOTAL(pipe), I915_READ(VTOTAL(pipe)));
I915_WRITE(trans_vblank_reg, I915_READ(cpu_vblank_reg)); I915_WRITE(TRANS_VBLANK(pipe), I915_READ(VBLANK(pipe)));
I915_WRITE(trans_vsync_reg, I915_READ(cpu_vsync_reg)); I915_WRITE(TRANS_VSYNC(pipe), I915_READ(VSYNC(pipe)));
/* enable normal train */ /* enable normal train */
temp = I915_READ(fdi_tx_reg); reg = FDI_TX_CTL(pipe);
temp = I915_READ(reg);
temp &= ~FDI_LINK_TRAIN_NONE; temp &= ~FDI_LINK_TRAIN_NONE;
I915_WRITE(fdi_tx_reg, temp | FDI_LINK_TRAIN_NONE | temp |= FDI_LINK_TRAIN_NONE | FDI_TX_ENHANCE_FRAME_ENABLE;
FDI_TX_ENHANCE_FRAME_ENABLE); I915_WRITE(reg, temp);
I915_READ(fdi_tx_reg);
temp = I915_READ(fdi_rx_reg); reg = FDI_RX_CTL(pipe);
temp = I915_READ(reg);
if (HAS_PCH_CPT(dev)) { if (HAS_PCH_CPT(dev)) {
temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT; temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT;
temp |= FDI_LINK_TRAIN_NORMAL_CPT; temp |= FDI_LINK_TRAIN_NORMAL_CPT;
...@@ -2053,61 +2026,57 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc) ...@@ -2053,61 +2026,57 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
temp &= ~FDI_LINK_TRAIN_NONE; temp &= ~FDI_LINK_TRAIN_NONE;
temp |= FDI_LINK_TRAIN_NONE; temp |= FDI_LINK_TRAIN_NONE;
} }
I915_WRITE(fdi_rx_reg, temp | FDI_RX_ENHANCE_FRAME_ENABLE); I915_WRITE(reg, temp | FDI_RX_ENHANCE_FRAME_ENABLE);
I915_READ(fdi_rx_reg);
/* wait one idle pattern time */ /* wait one idle pattern time */
POSTING_READ(reg);
udelay(100); udelay(100);
/* For PCH DP, enable TRANS_DP_CTL */ /* For PCH DP, enable TRANS_DP_CTL */
if (HAS_PCH_CPT(dev) && if (HAS_PCH_CPT(dev) &&
intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT)) { intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT)) {
int trans_dp_ctl = (pipe == 0) ? TRANS_DP_CTL_A : TRANS_DP_CTL_B; reg = TRANS_DP_CTL(pipe);
int reg; temp = I915_READ(reg);
temp &= ~(TRANS_DP_PORT_SEL_MASK |
reg = I915_READ(trans_dp_ctl); TRANS_DP_SYNC_MASK);
reg &= ~(TRANS_DP_PORT_SEL_MASK | temp |= (TRANS_DP_OUTPUT_ENABLE |
TRANS_DP_SYNC_MASK); TRANS_DP_ENH_FRAMING);
reg |= (TRANS_DP_OUTPUT_ENABLE |
TRANS_DP_ENH_FRAMING);
if (crtc->mode.flags & DRM_MODE_FLAG_PHSYNC) if (crtc->mode.flags & DRM_MODE_FLAG_PHSYNC)
reg |= TRANS_DP_HSYNC_ACTIVE_HIGH; temp |= TRANS_DP_HSYNC_ACTIVE_HIGH;
if (crtc->mode.flags & DRM_MODE_FLAG_PVSYNC) if (crtc->mode.flags & DRM_MODE_FLAG_PVSYNC)
reg |= TRANS_DP_VSYNC_ACTIVE_HIGH; temp |= TRANS_DP_VSYNC_ACTIVE_HIGH;
switch (intel_trans_dp_port_sel(crtc)) { switch (intel_trans_dp_port_sel(crtc)) {
case PCH_DP_B: case PCH_DP_B:
reg |= TRANS_DP_PORT_SEL_B; temp |= TRANS_DP_PORT_SEL_B;
break; break;
case PCH_DP_C: case PCH_DP_C:
reg |= TRANS_DP_PORT_SEL_C; temp |= TRANS_DP_PORT_SEL_C;
break; break;
case PCH_DP_D: case PCH_DP_D:
reg |= TRANS_DP_PORT_SEL_D; temp |= TRANS_DP_PORT_SEL_D;
break; break;
default: default:
DRM_DEBUG_KMS("Wrong PCH DP port return. Guess port B\n"); DRM_DEBUG_KMS("Wrong PCH DP port return. Guess port B\n");
reg |= TRANS_DP_PORT_SEL_B; temp |= TRANS_DP_PORT_SEL_B;
break; break;
} }
I915_WRITE(trans_dp_ctl, reg); I915_WRITE(reg, temp);
POSTING_READ(trans_dp_ctl);
} }
/* enable PCH transcoder */ /* enable PCH transcoder */
temp = I915_READ(transconf_reg); reg = TRANSCONF(pipe);
temp = I915_READ(reg);
/* /*
* make the BPC in transcoder be consistent with * make the BPC in transcoder be consistent with
* that in pipeconf reg. * that in pipeconf reg.
*/ */
temp &= ~PIPE_BPC_MASK; temp &= ~PIPE_BPC_MASK;
temp |= pipe_bpc; temp |= I915_READ(PIPECONF(pipe)) & PIPE_BPC_MASK;
I915_WRITE(transconf_reg, temp | TRANS_ENABLE); I915_WRITE(reg, temp | TRANS_ENABLE);
I915_READ(transconf_reg); if (wait_for(I915_READ(reg) & TRANS_STATE_ENABLE, 100))
if (wait_for(I915_READ(transconf_reg) & TRANS_STATE_ENABLE, 100))
DRM_ERROR("failed to enable transcoder\n"); DRM_ERROR("failed to enable transcoder\n");
intel_crtc_load_lut(crtc); intel_crtc_load_lut(crtc);
...@@ -2121,28 +2090,16 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc) ...@@ -2121,28 +2090,16 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
int pipe = intel_crtc->pipe; int pipe = intel_crtc->pipe;
int plane = intel_crtc->plane; int plane = intel_crtc->plane;
int pch_dpll_reg = (pipe == 0) ? PCH_DPLL_A : PCH_DPLL_B; u32 reg, temp;
int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
int dspcntr_reg = (plane == 0) ? DSPACNTR : DSPBCNTR;
int dspbase_reg = (plane == 0) ? DSPAADDR : DSPBADDR;
int fdi_tx_reg = (pipe == 0) ? FDI_TXA_CTL : FDI_TXB_CTL;
int fdi_rx_reg = (pipe == 0) ? FDI_RXA_CTL : FDI_RXB_CTL;
int transconf_reg = (pipe == 0) ? TRANSACONF : TRANSBCONF;
int trans_dpll_sel = (pipe == 0) ? 0 : 1;
u32 temp;
u32 pipe_bpc;
temp = I915_READ(pipeconf_reg);
pipe_bpc = temp & PIPE_BPC_MASK;
drm_vblank_off(dev, pipe); drm_vblank_off(dev, pipe);
/* Disable display plane */ /* Disable display plane */
temp = I915_READ(dspcntr_reg); reg = DSPCNTR(plane);
if ((temp & DISPLAY_PLANE_ENABLE) != 0) { temp = I915_READ(reg);
I915_WRITE(dspcntr_reg, temp & ~DISPLAY_PLANE_ENABLE); if (temp & DISPLAY_PLANE_ENABLE) {
/* Flush the plane changes */ I915_WRITE(reg, temp & ~DISPLAY_PLANE_ENABLE);
I915_WRITE(dspbase_reg, I915_READ(dspbase_reg)); intel_flush_display_plane(dev, plane);
I915_READ(dspbase_reg);
} }
if (dev_priv->cfb_plane == plane && if (dev_priv->cfb_plane == plane &&
...@@ -2150,42 +2107,43 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc) ...@@ -2150,42 +2107,43 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
dev_priv->display.disable_fbc(dev); dev_priv->display.disable_fbc(dev);
/* disable cpu pipe, disable after all planes disabled */ /* disable cpu pipe, disable after all planes disabled */
temp = I915_READ(pipeconf_reg); reg = PIPECONF(pipe);
if ((temp & PIPEACONF_ENABLE) != 0) { temp = I915_READ(reg);
I915_WRITE(pipeconf_reg, temp & ~PIPEACONF_ENABLE); if (temp & PIPECONF_ENABLE) {
I915_WRITE(reg, temp & ~PIPECONF_ENABLE);
/* wait for cpu pipe off, pipe state */ /* wait for cpu pipe off, pipe state */
if (wait_for((I915_READ(pipeconf_reg) & I965_PIPECONF_ACTIVE) == 0, 50)) if (wait_for((I915_READ(reg) & I965_PIPECONF_ACTIVE) == 0, 50))
DRM_ERROR("failed to turn off cpu pipe\n"); DRM_ERROR("failed to turn off cpu pipe\n");
} else }
DRM_DEBUG_KMS("crtc %d is disabled\n", pipe);
/* Disable PF */ /* Disable PF */
I915_WRITE(pipe ? PFB_CTL_1 : PFA_CTL_1, 0); I915_WRITE(pipe ? PFB_CTL_1 : PFA_CTL_1, 0);
I915_WRITE(pipe ? PFB_WIN_SZ : PFA_WIN_SZ, 0); I915_WRITE(pipe ? PFB_WIN_SZ : PFA_WIN_SZ, 0);
/* disable CPU FDI tx and PCH FDI rx */ /* disable CPU FDI tx and PCH FDI rx */
temp = I915_READ(fdi_tx_reg); reg = FDI_TX_CTL(pipe);
I915_WRITE(fdi_tx_reg, temp & ~FDI_TX_ENABLE); temp = I915_READ(reg);
I915_READ(fdi_tx_reg); I915_WRITE(reg, temp & ~FDI_TX_ENABLE);
POSTING_READ(reg);
temp = I915_READ(fdi_rx_reg); reg = FDI_RX_CTL(pipe);
/* BPC in FDI rx is consistent with that in pipeconf */ temp = I915_READ(reg);
temp &= ~(0x07 << 16); temp &= ~(0x7 << 16);
temp |= (pipe_bpc << 11); temp |= (I915_READ(PIPECONF(pipe)) & PIPE_BPC_MASK) << 11;
I915_WRITE(fdi_rx_reg, temp & ~FDI_RX_ENABLE); I915_WRITE(reg, temp & ~FDI_RX_ENABLE);
I915_READ(fdi_rx_reg);
POSTING_READ(reg);
udelay(100); udelay(100);
/* still set train pattern 1 */ /* still set train pattern 1 */
temp = I915_READ(fdi_tx_reg); reg = FDI_TX_CTL(pipe);
temp = I915_READ(reg);
temp &= ~FDI_LINK_TRAIN_NONE; temp &= ~FDI_LINK_TRAIN_NONE;
temp |= FDI_LINK_TRAIN_PATTERN_1; temp |= FDI_LINK_TRAIN_PATTERN_1;
I915_WRITE(fdi_tx_reg, temp); I915_WRITE(reg, temp);
POSTING_READ(fdi_tx_reg);
temp = I915_READ(fdi_rx_reg); reg = FDI_RX_CTL(pipe);
temp = I915_READ(reg);
if (HAS_PCH_CPT(dev)) { if (HAS_PCH_CPT(dev)) {
temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT; temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT;
temp |= FDI_LINK_TRAIN_PATTERN_1_CPT; temp |= FDI_LINK_TRAIN_PATTERN_1_CPT;
...@@ -2193,80 +2151,73 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc) ...@@ -2193,80 +2151,73 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
temp &= ~FDI_LINK_TRAIN_NONE; temp &= ~FDI_LINK_TRAIN_NONE;
temp |= FDI_LINK_TRAIN_PATTERN_1; temp |= FDI_LINK_TRAIN_PATTERN_1;
} }
I915_WRITE(fdi_rx_reg, temp); /* BPC in FDI rx is consistent with that in PIPECONF */
POSTING_READ(fdi_rx_reg); temp &= ~(0x07 << 16);
temp |= (I915_READ(PIPECONF(pipe)) & PIPE_BPC_MASK) << 11;
I915_WRITE(reg, temp);
POSTING_READ(reg);
udelay(100); udelay(100);
if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) { if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
temp = I915_READ(PCH_LVDS); temp = I915_READ(PCH_LVDS);
I915_WRITE(PCH_LVDS, temp & ~LVDS_PORT_EN); if (temp & LVDS_PORT_EN) {
I915_READ(PCH_LVDS); I915_WRITE(PCH_LVDS, temp & ~LVDS_PORT_EN);
udelay(100); POSTING_READ(PCH_LVDS);
udelay(100);
}
} }
/* disable PCH transcoder */ /* disable PCH transcoder */
temp = I915_READ(transconf_reg); reg = TRANSCONF(plane);
if ((temp & TRANS_ENABLE) != 0) { temp = I915_READ(reg);
I915_WRITE(transconf_reg, temp & ~TRANS_ENABLE); if (temp & TRANS_ENABLE) {
I915_WRITE(reg, temp & ~TRANS_ENABLE);
/* wait for PCH transcoder off, transcoder state */ /* wait for PCH transcoder off, transcoder state */
if (wait_for((I915_READ(transconf_reg) & TRANS_STATE_ENABLE) == 0, 50)) if (wait_for((I915_READ(reg) & TRANS_STATE_ENABLE) == 0, 50))
DRM_ERROR("failed to disable transcoder\n"); DRM_ERROR("failed to disable transcoder\n");
} }
temp = I915_READ(transconf_reg);
/* BPC in transcoder is consistent with that in pipeconf */
temp &= ~PIPE_BPC_MASK;
temp |= pipe_bpc;
I915_WRITE(transconf_reg, temp);
I915_READ(transconf_reg);
udelay(100);
if (HAS_PCH_CPT(dev)) { if (HAS_PCH_CPT(dev)) {
/* disable TRANS_DP_CTL */ /* disable TRANS_DP_CTL */
int trans_dp_ctl = (pipe == 0) ? TRANS_DP_CTL_A : TRANS_DP_CTL_B; reg = TRANS_DP_CTL(pipe);
int reg; temp = I915_READ(reg);
temp &= ~(TRANS_DP_OUTPUT_ENABLE | TRANS_DP_PORT_SEL_MASK);
reg = I915_READ(trans_dp_ctl); I915_WRITE(reg, temp);
reg &= ~(TRANS_DP_OUTPUT_ENABLE | TRANS_DP_PORT_SEL_MASK);
I915_WRITE(trans_dp_ctl, reg);
POSTING_READ(trans_dp_ctl);
/* disable DPLL_SEL */ /* disable DPLL_SEL */
temp = I915_READ(PCH_DPLL_SEL); temp = I915_READ(PCH_DPLL_SEL);
if (trans_dpll_sel == 0) if (pipe == 0)
temp &= ~(TRANSA_DPLL_ENABLE | TRANSA_DPLLB_SEL); temp &= ~(TRANSA_DPLL_ENABLE | TRANSA_DPLLB_SEL);
else else
temp &= ~(TRANSB_DPLL_ENABLE | TRANSB_DPLLB_SEL); temp &= ~(TRANSB_DPLL_ENABLE | TRANSB_DPLLB_SEL);
I915_WRITE(PCH_DPLL_SEL, temp); I915_WRITE(PCH_DPLL_SEL, temp);
I915_READ(PCH_DPLL_SEL);
} }
/* disable PCH DPLL */ /* disable PCH DPLL */
temp = I915_READ(pch_dpll_reg); reg = PCH_DPLL(pipe);
I915_WRITE(pch_dpll_reg, temp & ~DPLL_VCO_ENABLE); temp = I915_READ(reg);
I915_READ(pch_dpll_reg); I915_WRITE(reg, temp & ~DPLL_VCO_ENABLE);
/* Switch from PCDclk to Rawclk */ /* Switch from PCDclk to Rawclk */
temp = I915_READ(fdi_rx_reg); reg = FDI_RX_CTL(pipe);
temp &= ~FDI_SEL_PCDCLK; temp = I915_READ(reg);
I915_WRITE(fdi_rx_reg, temp); I915_WRITE(reg, temp & ~FDI_PCDCLK);
I915_READ(fdi_rx_reg);
/* Disable CPU FDI TX PLL */ /* Disable CPU FDI TX PLL */
temp = I915_READ(fdi_tx_reg); reg = FDI_TX_CTL(pipe);
I915_WRITE(fdi_tx_reg, temp & ~FDI_TX_PLL_ENABLE); temp = I915_READ(reg);
I915_READ(fdi_tx_reg); I915_WRITE(reg, temp & ~FDI_TX_PLL_ENABLE);
POSTING_READ(reg);
udelay(100); udelay(100);
temp = I915_READ(fdi_rx_reg); reg = FDI_RX_CTL(pipe);
temp &= ~FDI_RX_PLL_ENABLE; temp = I915_READ(reg);
I915_WRITE(fdi_rx_reg, temp); I915_WRITE(reg, temp & ~FDI_RX_PLL_ENABLE);
I915_READ(fdi_rx_reg);
/* Wait for the clocks to turn off. */ /* Wait for the clocks to turn off. */
POSTING_READ(reg);
udelay(100); udelay(100);
} }
...@@ -2316,40 +2267,43 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc) ...@@ -2316,40 +2267,43 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc)
struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
int pipe = intel_crtc->pipe; int pipe = intel_crtc->pipe;
int plane = intel_crtc->plane; int plane = intel_crtc->plane;
int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B; u32 reg, temp;
int dspcntr_reg = (plane == 0) ? DSPACNTR : DSPBCNTR;
int dspbase_reg = (plane == 0) ? DSPAADDR : DSPBADDR;
int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
u32 temp;
/* Enable the DPLL */ /* Enable the DPLL */
temp = I915_READ(dpll_reg); reg = DPLL(pipe);
temp = I915_READ(reg);
if ((temp & DPLL_VCO_ENABLE) == 0) { if ((temp & DPLL_VCO_ENABLE) == 0) {
I915_WRITE(dpll_reg, temp); I915_WRITE(reg, temp);
I915_READ(dpll_reg);
/* Wait for the clocks to stabilize. */ /* Wait for the clocks to stabilize. */
POSTING_READ(reg);
udelay(150); udelay(150);
I915_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE);
I915_READ(dpll_reg); I915_WRITE(reg, temp | DPLL_VCO_ENABLE);
/* Wait for the clocks to stabilize. */ /* Wait for the clocks to stabilize. */
POSTING_READ(reg);
udelay(150); udelay(150);
I915_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE);
I915_READ(dpll_reg); I915_WRITE(reg, temp | DPLL_VCO_ENABLE);
/* Wait for the clocks to stabilize. */ /* Wait for the clocks to stabilize. */
POSTING_READ(reg);
udelay(150); udelay(150);
} }
/* Enable the pipe */ /* Enable the pipe */
temp = I915_READ(pipeconf_reg); reg = PIPECONF(pipe);
if ((temp & PIPEACONF_ENABLE) == 0) temp = I915_READ(reg);
I915_WRITE(pipeconf_reg, temp | PIPEACONF_ENABLE); if ((temp & PIPECONF_ENABLE) == 0)
I915_WRITE(reg, temp | PIPECONF_ENABLE);
/* Enable the plane */ /* Enable the plane */
temp = I915_READ(dspcntr_reg); reg = DSPCNTR(plane);
temp = I915_READ(reg);
if ((temp & DISPLAY_PLANE_ENABLE) == 0) { if ((temp & DISPLAY_PLANE_ENABLE) == 0) {
I915_WRITE(dspcntr_reg, temp | DISPLAY_PLANE_ENABLE); I915_WRITE(reg, temp | DISPLAY_PLANE_ENABLE);
/* Flush the plane changes */ intel_flush_display_plane(dev, plane);
I915_WRITE(dspbase_reg, I915_READ(dspbase_reg));
} }
intel_crtc_load_lut(crtc); intel_crtc_load_lut(crtc);
...@@ -2366,11 +2320,7 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc) ...@@ -2366,11 +2320,7 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc)
struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
int pipe = intel_crtc->pipe; int pipe = intel_crtc->pipe;
int plane = intel_crtc->plane; int plane = intel_crtc->plane;
int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B; u32 reg, temp;
int dspcntr_reg = (plane == 0) ? DSPACNTR : DSPBCNTR;
int dspbase_reg = (plane == 0) ? DSPAADDR : DSPBADDR;
int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
u32 temp;
/* Give the overlay scaler a chance to disable if it's on this pipe */ /* Give the overlay scaler a chance to disable if it's on this pipe */
intel_crtc_dpms_overlay(intel_crtc, false); intel_crtc_dpms_overlay(intel_crtc, false);
...@@ -2381,42 +2331,42 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc) ...@@ -2381,42 +2331,42 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc)
dev_priv->display.disable_fbc(dev); dev_priv->display.disable_fbc(dev);
/* Disable display plane */ /* Disable display plane */
temp = I915_READ(dspcntr_reg); reg = DSPCNTR(plane);
if ((temp & DISPLAY_PLANE_ENABLE) != 0) { temp = I915_READ(reg);
I915_WRITE(dspcntr_reg, temp & ~DISPLAY_PLANE_ENABLE); if (temp & DISPLAY_PLANE_ENABLE) {
I915_WRITE(reg, temp & ~DISPLAY_PLANE_ENABLE);
/* Flush the plane changes */ /* Flush the plane changes */
I915_WRITE(dspbase_reg, I915_READ(dspbase_reg)); intel_flush_display_plane(dev, plane);
I915_READ(dspbase_reg);
}
if (!IS_I9XX(dev)) {
/* Wait for vblank for the disable to take effect */ /* Wait for vblank for the disable to take effect */
intel_wait_for_vblank_off(dev, pipe); if (!IS_I9XX(dev))
intel_wait_for_vblank_off(dev, pipe);
} }
/* Don't disable pipe A or pipe A PLLs if needed */ /* Don't disable pipe A or pipe A PLLs if needed */
if (pipeconf_reg == PIPEACONF && if (pipe == 0 && (dev_priv->quirks & QUIRK_PIPEA_FORCE))
(dev_priv->quirks & QUIRK_PIPEA_FORCE)) return;
goto skip_pipe_off;
/* Next, disable display pipes */ /* Next, disable display pipes */
temp = I915_READ(pipeconf_reg); reg = PIPECONF(pipe);
if ((temp & PIPEACONF_ENABLE) != 0) { temp = I915_READ(reg);
I915_WRITE(pipeconf_reg, temp & ~PIPEACONF_ENABLE); if (temp & PIPECONF_ENABLE) {
I915_READ(pipeconf_reg); I915_WRITE(reg, temp & ~PIPECONF_ENABLE);
/* Wait for vblank for the disable to take effect. */
POSTING_READ(reg);
intel_wait_for_vblank_off(dev, pipe);
} }
/* Wait for vblank for the disable to take effect. */ reg = DPLL(pipe);
intel_wait_for_vblank_off(dev, pipe); temp = I915_READ(reg);
if (temp & DPLL_VCO_ENABLE) {
I915_WRITE(reg, temp & ~DPLL_VCO_ENABLE);
temp = I915_READ(dpll_reg); /* Wait for the clocks to turn off. */
if ((temp & DPLL_VCO_ENABLE) != 0) { POSTING_READ(reg);
I915_WRITE(dpll_reg, temp & ~DPLL_VCO_ENABLE); udelay(150);
I915_READ(dpll_reg);
} }
skip_pipe_off:
/* Wait for the clocks to turn off. */
udelay(150);
} }
static void i9xx_crtc_dpms(struct drm_crtc *crtc, int mode) static void i9xx_crtc_dpms(struct drm_crtc *crtc, int mode)
...@@ -3030,7 +2980,7 @@ static int i9xx_get_fifo_size(struct drm_device *dev, int plane) ...@@ -3030,7 +2980,7 @@ static int i9xx_get_fifo_size(struct drm_device *dev, int plane)
size = ((dsparb >> DSPARB_CSTART_SHIFT) & 0x7f) - size; size = ((dsparb >> DSPARB_CSTART_SHIFT) & 0x7f) - size;
DRM_DEBUG_KMS("FIFO size - (0x%08x) %s: %d\n", dsparb, DRM_DEBUG_KMS("FIFO size - (0x%08x) %s: %d\n", dsparb,
plane ? "B" : "A", size); plane ? "B" : "A", size);
return size; return size;
} }
...@@ -3047,7 +2997,7 @@ static int i85x_get_fifo_size(struct drm_device *dev, int plane) ...@@ -3047,7 +2997,7 @@ static int i85x_get_fifo_size(struct drm_device *dev, int plane)
size >>= 1; /* Convert to cachelines */ size >>= 1; /* Convert to cachelines */
DRM_DEBUG_KMS("FIFO size - (0x%08x) %s: %d\n", dsparb, DRM_DEBUG_KMS("FIFO size - (0x%08x) %s: %d\n", dsparb,
plane ? "B" : "A", size); plane ? "B" : "A", size);
return size; return size;
} }
...@@ -3062,8 +3012,8 @@ static int i845_get_fifo_size(struct drm_device *dev, int plane) ...@@ -3062,8 +3012,8 @@ static int i845_get_fifo_size(struct drm_device *dev, int plane)
size >>= 2; /* Convert to cachelines */ size >>= 2; /* Convert to cachelines */
DRM_DEBUG_KMS("FIFO size - (0x%08x) %s: %d\n", dsparb, DRM_DEBUG_KMS("FIFO size - (0x%08x) %s: %d\n", dsparb,
plane ? "B" : "A", plane ? "B" : "A",
size); size);
return size; return size;
} }
...@@ -3078,14 +3028,14 @@ static int i830_get_fifo_size(struct drm_device *dev, int plane) ...@@ -3078,14 +3028,14 @@ static int i830_get_fifo_size(struct drm_device *dev, int plane)
size >>= 1; /* Convert to cachelines */ size >>= 1; /* Convert to cachelines */
DRM_DEBUG_KMS("FIFO size - (0x%08x) %s: %d\n", dsparb, DRM_DEBUG_KMS("FIFO size - (0x%08x) %s: %d\n", dsparb,
plane ? "B" : "A", size); plane ? "B" : "A", size);
return size; return size;
} }
static void pineview_update_wm(struct drm_device *dev, int planea_clock, static void pineview_update_wm(struct drm_device *dev, int planea_clock,
int planeb_clock, int sr_hdisplay, int unused, int planeb_clock, int sr_hdisplay, int unused,
int pixel_size) int pixel_size)
{ {
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
const struct cxsr_latency *latency; const struct cxsr_latency *latency;
...@@ -3197,13 +3147,13 @@ static void g4x_update_wm(struct drm_device *dev, int planea_clock, ...@@ -3197,13 +3147,13 @@ static void g4x_update_wm(struct drm_device *dev, int planea_clock,
/* Use ns/us then divide to preserve precision */ /* Use ns/us then divide to preserve precision */
sr_entries = (((sr_latency_ns / line_time_us) + 1000) / 1000) * sr_entries = (((sr_latency_ns / line_time_us) + 1000) / 1000) *
pixel_size * sr_hdisplay; pixel_size * sr_hdisplay;
sr_entries = DIV_ROUND_UP(sr_entries, cacheline_size); sr_entries = DIV_ROUND_UP(sr_entries, cacheline_size);
entries_required = (((sr_latency_ns / line_time_us) + entries_required = (((sr_latency_ns / line_time_us) +
1000) / 1000) * pixel_size * 64; 1000) / 1000) * pixel_size * 64;
entries_required = DIV_ROUND_UP(entries_required, entries_required = DIV_ROUND_UP(entries_required,
g4x_cursor_wm_info.cacheline_size); g4x_cursor_wm_info.cacheline_size);
cursor_sr = entries_required + g4x_cursor_wm_info.guard_size; cursor_sr = entries_required + g4x_cursor_wm_info.guard_size;
if (cursor_sr > g4x_cursor_wm_info.max_wm) if (cursor_sr > g4x_cursor_wm_info.max_wm)
...@@ -3215,7 +3165,7 @@ static void g4x_update_wm(struct drm_device *dev, int planea_clock, ...@@ -3215,7 +3165,7 @@ static void g4x_update_wm(struct drm_device *dev, int planea_clock,
} else { } else {
/* Turn off self refresh if both pipes are enabled */ /* Turn off self refresh if both pipes are enabled */
I915_WRITE(FW_BLC_SELF, I915_READ(FW_BLC_SELF) I915_WRITE(FW_BLC_SELF, I915_READ(FW_BLC_SELF)
& ~FW_BLC_SELF_EN); & ~FW_BLC_SELF_EN);
} }
DRM_DEBUG("Setting FIFO watermarks - A: %d, B: %d, SR %d\n", DRM_DEBUG("Setting FIFO watermarks - A: %d, B: %d, SR %d\n",
...@@ -3253,7 +3203,7 @@ static void i965_update_wm(struct drm_device *dev, int planea_clock, ...@@ -3253,7 +3203,7 @@ static void i965_update_wm(struct drm_device *dev, int planea_clock,
/* Use ns/us then divide to preserve precision */ /* Use ns/us then divide to preserve precision */
sr_entries = (((sr_latency_ns / line_time_us) + 1000) / 1000) * sr_entries = (((sr_latency_ns / line_time_us) + 1000) / 1000) *
pixel_size * sr_hdisplay; pixel_size * sr_hdisplay;
sr_entries = DIV_ROUND_UP(sr_entries, I915_FIFO_LINE_SIZE); sr_entries = DIV_ROUND_UP(sr_entries, I915_FIFO_LINE_SIZE);
DRM_DEBUG("self-refresh entries: %d\n", sr_entries); DRM_DEBUG("self-refresh entries: %d\n", sr_entries);
srwm = I965_FIFO_SIZE - sr_entries; srwm = I965_FIFO_SIZE - sr_entries;
...@@ -3262,11 +3212,11 @@ static void i965_update_wm(struct drm_device *dev, int planea_clock, ...@@ -3262,11 +3212,11 @@ static void i965_update_wm(struct drm_device *dev, int planea_clock,
srwm &= 0x1ff; srwm &= 0x1ff;
sr_entries = (((sr_latency_ns / line_time_us) + 1000) / 1000) * sr_entries = (((sr_latency_ns / line_time_us) + 1000) / 1000) *
pixel_size * 64; pixel_size * 64;
sr_entries = DIV_ROUND_UP(sr_entries, sr_entries = DIV_ROUND_UP(sr_entries,
i965_cursor_wm_info.cacheline_size); i965_cursor_wm_info.cacheline_size);
cursor_sr = i965_cursor_wm_info.fifo_size - cursor_sr = i965_cursor_wm_info.fifo_size -
(sr_entries + i965_cursor_wm_info.guard_size); (sr_entries + i965_cursor_wm_info.guard_size);
if (cursor_sr > i965_cursor_wm_info.max_wm) if (cursor_sr > i965_cursor_wm_info.max_wm)
cursor_sr = i965_cursor_wm_info.max_wm; cursor_sr = i965_cursor_wm_info.max_wm;
...@@ -3345,7 +3295,7 @@ static void i9xx_update_wm(struct drm_device *dev, int planea_clock, ...@@ -3345,7 +3295,7 @@ static void i9xx_update_wm(struct drm_device *dev, int planea_clock,
/* Use ns/us then divide to preserve precision */ /* Use ns/us then divide to preserve precision */
sr_entries = (((sr_latency_ns / line_time_us) + 1000) / 1000) * sr_entries = (((sr_latency_ns / line_time_us) + 1000) / 1000) *
pixel_size * sr_hdisplay; pixel_size * sr_hdisplay;
sr_entries = DIV_ROUND_UP(sr_entries, cacheline_size); sr_entries = DIV_ROUND_UP(sr_entries, cacheline_size);
DRM_DEBUG_KMS("self-refresh entries: %d\n", sr_entries); DRM_DEBUG_KMS("self-refresh entries: %d\n", sr_entries);
srwm = total_size - sr_entries; srwm = total_size - sr_entries;
...@@ -3370,7 +3320,7 @@ static void i9xx_update_wm(struct drm_device *dev, int planea_clock, ...@@ -3370,7 +3320,7 @@ static void i9xx_update_wm(struct drm_device *dev, int planea_clock,
} }
DRM_DEBUG_KMS("Setting FIFO watermarks - A: %d, B: %d, C: %d, SR %d\n", DRM_DEBUG_KMS("Setting FIFO watermarks - A: %d, B: %d, C: %d, SR %d\n",
planea_wm, planeb_wm, cwm, srwm); planea_wm, planeb_wm, cwm, srwm);
fwater_lo = ((planeb_wm & 0x3f) << 16) | (planea_wm & 0x3f); fwater_lo = ((planeb_wm & 0x3f) << 16) | (planea_wm & 0x3f);
fwater_hi = (cwm & 0x1f); fwater_hi = (cwm & 0x1f);
...@@ -3489,7 +3439,7 @@ static void ironlake_update_wm(struct drm_device *dev, ...@@ -3489,7 +3439,7 @@ static void ironlake_update_wm(struct drm_device *dev,
/* Use ns/us then divide to preserve precision */ /* Use ns/us then divide to preserve precision */
line_count = ((ilk_sr_latency * 500) / line_time_us + 1000) line_count = ((ilk_sr_latency * 500) / line_time_us + 1000)
/ 1000; / 1000;
line_size = sr_hdisplay * pixel_size; line_size = sr_hdisplay * pixel_size;
/* Use the minimum of the small and large buffer method for primary */ /* Use the minimum of the small and large buffer method for primary */
...@@ -3559,7 +3509,7 @@ static void ironlake_update_wm(struct drm_device *dev, ...@@ -3559,7 +3509,7 @@ static void ironlake_update_wm(struct drm_device *dev,
* *
* We don't use the sprite, so we can ignore that. And on Crestline we have * We don't use the sprite, so we can ignore that. And on Crestline we have
* to set the non-SR watermarks to 8. * to set the non-SR watermarks to 8.
*/ */
static void intel_update_watermarks(struct drm_device *dev) static void intel_update_watermarks(struct drm_device *dev)
{ {
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
...@@ -3579,11 +3529,11 @@ static void intel_update_watermarks(struct drm_device *dev) ...@@ -3579,11 +3529,11 @@ static void intel_update_watermarks(struct drm_device *dev)
enabled++; enabled++;
if (intel_crtc->plane == 0) { if (intel_crtc->plane == 0) {
DRM_DEBUG_KMS("plane A (pipe %d) clock: %d\n", DRM_DEBUG_KMS("plane A (pipe %d) clock: %d\n",
intel_crtc->pipe, crtc->mode.clock); intel_crtc->pipe, crtc->mode.clock);
planea_clock = crtc->mode.clock; planea_clock = crtc->mode.clock;
} else { } else {
DRM_DEBUG_KMS("plane B (pipe %d) clock: %d\n", DRM_DEBUG_KMS("plane B (pipe %d) clock: %d\n",
intel_crtc->pipe, crtc->mode.clock); intel_crtc->pipe, crtc->mode.clock);
planeb_clock = crtc->mode.clock; planeb_clock = crtc->mode.clock;
} }
sr_hdisplay = crtc->mode.hdisplay; sr_hdisplay = crtc->mode.hdisplay;
...@@ -3614,61 +3564,35 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, ...@@ -3614,61 +3564,35 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
int pipe = intel_crtc->pipe; int pipe = intel_crtc->pipe;
int plane = intel_crtc->plane; int plane = intel_crtc->plane;
int fp_reg = (pipe == 0) ? FPA0 : FPB0; u32 fp_reg, dpll_reg;
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 = (plane == 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 = (plane == 0) ? DSPASIZE : DSPBSIZE;
int dsppos_reg = (plane == 0) ? DSPAPOS : DSPBPOS;
int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC;
int refclk, num_connectors = 0; int refclk, num_connectors = 0;
intel_clock_t clock, reduced_clock; intel_clock_t clock, reduced_clock;
u32 dpll = 0, fp = 0, fp2 = 0, dspcntr, pipeconf; u32 dpll, fp = 0, fp2 = 0, dspcntr, pipeconf;
bool ok, has_reduced_clock = false, is_sdvo = false, is_dvo = false; bool ok, has_reduced_clock = false, is_sdvo = false, is_dvo = false;
bool is_crt = false, is_lvds = false, is_tv = false, is_dp = false; bool is_crt = false, is_lvds = false, is_tv = false, is_dp = false;
struct intel_encoder *has_edp_encoder = NULL; struct intel_encoder *has_edp_encoder = NULL;
struct drm_mode_config *mode_config = &dev->mode_config; struct drm_mode_config *mode_config = &dev->mode_config;
struct drm_encoder *encoder; struct intel_encoder *encoder;
const intel_limit_t *limit; const intel_limit_t *limit;
int ret; int ret;
struct fdi_m_n m_n = {0}; struct fdi_m_n m_n = {0};
int data_m1_reg = (pipe == 0) ? PIPEA_DATA_M1 : PIPEB_DATA_M1; u32 reg, temp;
int data_n1_reg = (pipe == 0) ? PIPEA_DATA_N1 : PIPEB_DATA_N1;
int link_m1_reg = (pipe == 0) ? PIPEA_LINK_M1 : PIPEB_LINK_M1;
int link_n1_reg = (pipe == 0) ? PIPEA_LINK_N1 : PIPEB_LINK_N1;
int pch_fp_reg = (pipe == 0) ? PCH_FPA0 : PCH_FPB0;
int pch_dpll_reg = (pipe == 0) ? PCH_DPLL_A : PCH_DPLL_B;
int fdi_rx_reg = (pipe == 0) ? FDI_RXA_CTL : FDI_RXB_CTL;
int fdi_tx_reg = (pipe == 0) ? FDI_TXA_CTL : FDI_TXB_CTL;
int trans_dpll_sel = (pipe == 0) ? 0 : 1;
int lvds_reg = LVDS;
u32 temp;
int target_clock; int target_clock;
drm_vblank_pre_modeset(dev, pipe); drm_vblank_pre_modeset(dev, pipe);
list_for_each_entry(encoder, &mode_config->encoder_list, head) { list_for_each_entry(encoder, &mode_config->encoder_list, base.head) {
struct intel_encoder *intel_encoder; if (encoder->base.crtc != crtc)
if (encoder->crtc != crtc)
continue; continue;
intel_encoder = to_intel_encoder(encoder); switch (encoder->type) {
switch (intel_encoder->type) {
case INTEL_OUTPUT_LVDS: case INTEL_OUTPUT_LVDS:
is_lvds = true; is_lvds = true;
break; break;
case INTEL_OUTPUT_SDVO: case INTEL_OUTPUT_SDVO:
case INTEL_OUTPUT_HDMI: case INTEL_OUTPUT_HDMI:
is_sdvo = true; is_sdvo = true;
if (intel_encoder->needs_tv_clock) if (encoder->needs_tv_clock)
is_tv = true; is_tv = true;
break; break;
case INTEL_OUTPUT_DVO: case INTEL_OUTPUT_DVO:
...@@ -3684,7 +3608,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, ...@@ -3684,7 +3608,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
is_dp = true; is_dp = true;
break; break;
case INTEL_OUTPUT_EDP: case INTEL_OUTPUT_EDP:
has_edp_encoder = intel_encoder; has_edp_encoder = encoder;
break; break;
} }
...@@ -3694,7 +3618,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, ...@@ -3694,7 +3618,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
if (is_lvds && dev_priv->lvds_use_ssc && num_connectors < 2) { if (is_lvds && dev_priv->lvds_use_ssc && num_connectors < 2) {
refclk = dev_priv->lvds_ssc_freq * 1000; refclk = dev_priv->lvds_ssc_freq * 1000;
DRM_DEBUG_KMS("using SSC reference clock of %d MHz\n", DRM_DEBUG_KMS("using SSC reference clock of %d MHz\n",
refclk / 1000); refclk / 1000);
} else if (IS_I9XX(dev)) { } else if (IS_I9XX(dev)) {
refclk = 96000; refclk = 96000;
if (HAS_PCH_SPLIT(dev)) if (HAS_PCH_SPLIT(dev))
...@@ -3702,7 +3626,6 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, ...@@ -3702,7 +3626,6 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
} else { } else {
refclk = 48000; refclk = 48000;
} }
/* /*
* Returns a set of divisors for the desired target clock with the given * Returns a set of divisors for the desired target clock with the given
...@@ -3722,9 +3645,9 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, ...@@ -3722,9 +3645,9 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
if (is_lvds && dev_priv->lvds_downclock_avail) { if (is_lvds && dev_priv->lvds_downclock_avail) {
has_reduced_clock = limit->find_pll(limit, crtc, has_reduced_clock = limit->find_pll(limit, crtc,
dev_priv->lvds_downclock, dev_priv->lvds_downclock,
refclk, refclk,
&reduced_clock); &reduced_clock);
if (has_reduced_clock && (clock.p != reduced_clock.p)) { if (has_reduced_clock && (clock.p != reduced_clock.p)) {
/* /*
* If the different P is found, it means that we can't * If the different P is found, it means that we can't
...@@ -3733,7 +3656,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, ...@@ -3733,7 +3656,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
* feature. * feature.
*/ */
DRM_DEBUG_KMS("Different P is found for " DRM_DEBUG_KMS("Different P is found for "
"LVDS clock/downclock\n"); "LVDS clock/downclock\n");
has_reduced_clock = 0; has_reduced_clock = 0;
} }
} }
...@@ -3741,14 +3664,14 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, ...@@ -3741,14 +3664,14 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
this mirrors vbios setting. */ this mirrors vbios setting. */
if (is_sdvo && is_tv) { if (is_sdvo && is_tv) {
if (adjusted_mode->clock >= 100000 if (adjusted_mode->clock >= 100000
&& adjusted_mode->clock < 140500) { && adjusted_mode->clock < 140500) {
clock.p1 = 2; clock.p1 = 2;
clock.p2 = 10; clock.p2 = 10;
clock.n = 3; clock.n = 3;
clock.m1 = 16; clock.m1 = 16;
clock.m2 = 8; clock.m2 = 8;
} else if (adjusted_mode->clock >= 140500 } else if (adjusted_mode->clock >= 140500
&& adjusted_mode->clock <= 200000) { && adjusted_mode->clock <= 200000) {
clock.p1 = 1; clock.p1 = 1;
clock.p2 = 10; clock.p2 = 10;
clock.n = 6; clock.n = 6;
...@@ -3785,12 +3708,11 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, ...@@ -3785,12 +3708,11 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
} }
/* determine panel color depth */ /* determine panel color depth */
temp = I915_READ(pipeconf_reg); temp = I915_READ(PIPECONF(pipe));
temp &= ~PIPE_BPC_MASK; temp &= ~PIPE_BPC_MASK;
if (is_lvds) { if (is_lvds) {
int lvds_reg = I915_READ(PCH_LVDS);
/* the BPC will be 6 if it is 18-bit LVDS panel */ /* the BPC will be 6 if it is 18-bit LVDS panel */
if ((lvds_reg & LVDS_A3_POWER_MASK) == LVDS_A3_POWER_UP) if ((I915_READ(PCH_LVDS) & LVDS_A3_POWER_MASK) == LVDS_A3_POWER_UP)
temp |= PIPE_8BPC; temp |= PIPE_8BPC;
else else
temp |= PIPE_6BPC; temp |= PIPE_6BPC;
...@@ -3811,8 +3733,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, ...@@ -3811,8 +3733,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
} }
} else } else
temp |= PIPE_8BPC; temp |= PIPE_8BPC;
I915_WRITE(pipeconf_reg, temp); I915_WRITE(PIPECONF(pipe), temp);
I915_READ(pipeconf_reg);
switch (temp & PIPE_BPC_MASK) { switch (temp & PIPE_BPC_MASK) {
case PIPE_8BPC: case PIPE_8BPC:
...@@ -3857,33 +3778,27 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, ...@@ -3857,33 +3778,27 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
/* Always enable nonspread source */ /* Always enable nonspread source */
temp &= ~DREF_NONSPREAD_SOURCE_MASK; temp &= ~DREF_NONSPREAD_SOURCE_MASK;
temp |= DREF_NONSPREAD_SOURCE_ENABLE; temp |= DREF_NONSPREAD_SOURCE_ENABLE;
I915_WRITE(PCH_DREF_CONTROL, temp);
POSTING_READ(PCH_DREF_CONTROL);
temp &= ~DREF_SSC_SOURCE_MASK; temp &= ~DREF_SSC_SOURCE_MASK;
temp |= DREF_SSC_SOURCE_ENABLE; temp |= DREF_SSC_SOURCE_ENABLE;
I915_WRITE(PCH_DREF_CONTROL, temp); I915_WRITE(PCH_DREF_CONTROL, temp);
POSTING_READ(PCH_DREF_CONTROL);
POSTING_READ(PCH_DREF_CONTROL);
udelay(200); udelay(200);
if (has_edp_encoder) { if (has_edp_encoder) {
if (dev_priv->lvds_use_ssc) { if (dev_priv->lvds_use_ssc) {
temp |= DREF_SSC1_ENABLE; temp |= DREF_SSC1_ENABLE;
I915_WRITE(PCH_DREF_CONTROL, temp); I915_WRITE(PCH_DREF_CONTROL, temp);
POSTING_READ(PCH_DREF_CONTROL);
POSTING_READ(PCH_DREF_CONTROL);
udelay(200); udelay(200);
temp &= ~DREF_CPU_SOURCE_OUTPUT_MASK; temp &= ~DREF_CPU_SOURCE_OUTPUT_MASK;
temp |= DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD; temp |= DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD;
I915_WRITE(PCH_DREF_CONTROL, temp);
POSTING_READ(PCH_DREF_CONTROL);
} else { } else {
temp |= DREF_CPU_SOURCE_OUTPUT_NONSPREAD; temp |= DREF_CPU_SOURCE_OUTPUT_NONSPREAD;
I915_WRITE(PCH_DREF_CONTROL, temp);
POSTING_READ(PCH_DREF_CONTROL);
} }
I915_WRITE(PCH_DREF_CONTROL, temp);
} }
} }
...@@ -3899,6 +3814,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, ...@@ -3899,6 +3814,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
reduced_clock.m2; reduced_clock.m2;
} }
dpll = 0;
if (!HAS_PCH_SPLIT(dev)) if (!HAS_PCH_SPLIT(dev))
dpll = DPLL_VGA_MODE_DIS; dpll = DPLL_VGA_MODE_DIS;
...@@ -3972,7 +3888,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, ...@@ -3972,7 +3888,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
dpll |= PLL_REF_INPUT_DREFCLK; dpll |= PLL_REF_INPUT_DREFCLK;
/* setup pipeconf */ /* setup pipeconf */
pipeconf = I915_READ(pipeconf_reg); pipeconf = I915_READ(PIPECONF(pipe));
/* Set up the display plane register */ /* Set up the display plane register */
dspcntr = DISPPLANE_GAMMA_ENABLE; dspcntr = DISPPLANE_GAMMA_ENABLE;
...@@ -3995,16 +3911,15 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, ...@@ -3995,16 +3911,15 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
*/ */
if (mode->clock > if (mode->clock >
dev_priv->display.get_display_clock_speed(dev) * 9 / 10) dev_priv->display.get_display_clock_speed(dev) * 9 / 10)
pipeconf |= PIPEACONF_DOUBLE_WIDE; pipeconf |= PIPECONF_DOUBLE_WIDE;
else else
pipeconf &= ~PIPEACONF_DOUBLE_WIDE; pipeconf &= ~PIPECONF_DOUBLE_WIDE;
} }
dspcntr |= DISPLAY_PLANE_ENABLE; dspcntr |= DISPLAY_PLANE_ENABLE;
pipeconf |= PIPEACONF_ENABLE; pipeconf |= PIPECONF_ENABLE;
dpll |= DPLL_VCO_ENABLE; dpll |= DPLL_VCO_ENABLE;
/* Disable the panel fitter if it was on our pipe */ /* Disable the panel fitter if it was on our pipe */
if (!HAS_PCH_SPLIT(dev) && intel_panel_fitter_pipe(dev) == pipe) if (!HAS_PCH_SPLIT(dev) && intel_panel_fitter_pipe(dev) == pipe)
I915_WRITE(PFIT_CONTROL, 0); I915_WRITE(PFIT_CONTROL, 0);
...@@ -4014,26 +3929,31 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, ...@@ -4014,26 +3929,31 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
/* assign to Ironlake registers */ /* assign to Ironlake registers */
if (HAS_PCH_SPLIT(dev)) { if (HAS_PCH_SPLIT(dev)) {
fp_reg = pch_fp_reg; fp_reg = PCH_FP0(pipe);
dpll_reg = pch_dpll_reg; dpll_reg = PCH_DPLL(pipe);
} else {
fp_reg = FP0(pipe);
dpll_reg = DPLL(pipe);
} }
if (!has_edp_encoder) { if (!has_edp_encoder) {
I915_WRITE(fp_reg, fp); I915_WRITE(fp_reg, fp);
I915_WRITE(dpll_reg, dpll & ~DPLL_VCO_ENABLE); I915_WRITE(dpll_reg, dpll & ~DPLL_VCO_ENABLE);
I915_READ(dpll_reg);
POSTING_READ(dpll_reg);
udelay(150); udelay(150);
} }
/* enable transcoder DPLL */ /* enable transcoder DPLL */
if (HAS_PCH_CPT(dev)) { if (HAS_PCH_CPT(dev)) {
temp = I915_READ(PCH_DPLL_SEL); temp = I915_READ(PCH_DPLL_SEL);
if (trans_dpll_sel == 0) if (pipe == 0)
temp |= (TRANSA_DPLL_ENABLE | TRANSA_DPLLA_SEL); temp |= TRANSA_DPLL_ENABLE | TRANSA_DPLLA_SEL;
else else
temp |= (TRANSB_DPLL_ENABLE | TRANSB_DPLLB_SEL); temp |= TRANSB_DPLL_ENABLE | TRANSB_DPLLB_SEL;
I915_WRITE(PCH_DPLL_SEL, temp); I915_WRITE(PCH_DPLL_SEL, temp);
I915_READ(PCH_DPLL_SEL);
POSTING_READ(PCH_DPLL_SEL);
udelay(150); udelay(150);
} }
...@@ -4042,33 +3962,32 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, ...@@ -4042,33 +3962,32 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
* things on. * things on.
*/ */
if (is_lvds) { if (is_lvds) {
u32 lvds; reg = LVDS;
if (HAS_PCH_SPLIT(dev)) if (HAS_PCH_SPLIT(dev))
lvds_reg = PCH_LVDS; reg = PCH_LVDS;
lvds = I915_READ(lvds_reg); temp = I915_READ(reg);
lvds |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP; temp |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP;
if (pipe == 1) { if (pipe == 1) {
if (HAS_PCH_CPT(dev)) if (HAS_PCH_CPT(dev))
lvds |= PORT_TRANS_B_SEL_CPT; temp |= PORT_TRANS_B_SEL_CPT;
else else
lvds |= LVDS_PIPEB_SELECT; temp |= LVDS_PIPEB_SELECT;
} else { } else {
if (HAS_PCH_CPT(dev)) if (HAS_PCH_CPT(dev))
lvds &= ~PORT_TRANS_SEL_MASK; temp &= ~PORT_TRANS_SEL_MASK;
else else
lvds &= ~LVDS_PIPEB_SELECT; temp &= ~LVDS_PIPEB_SELECT;
} }
/* set the corresponsding LVDS_BORDER bit */ /* set the corresponsding LVDS_BORDER bit */
lvds |= dev_priv->lvds_border_bits; temp |= dev_priv->lvds_border_bits;
/* Set the B0-B3 data pairs corresponding to whether we're going to /* Set the B0-B3 data pairs corresponding to whether we're going to
* set the DPLLs for dual-channel mode or not. * set the DPLLs for dual-channel mode or not.
*/ */
if (clock.p2 == 7) if (clock.p2 == 7)
lvds |= LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP; temp |= LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP;
else else
lvds &= ~(LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP); temp &= ~(LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP);
/* It would be nice to set 24 vs 18-bit mode (LVDS_A3_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 * appropriately here, but we need to look more thoroughly into how
...@@ -4077,12 +3996,11 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, ...@@ -4077,12 +3996,11 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
/* set the dithering flag on non-PCH LVDS as needed */ /* set the dithering flag on non-PCH LVDS as needed */
if (IS_I965G(dev) && !HAS_PCH_SPLIT(dev)) { if (IS_I965G(dev) && !HAS_PCH_SPLIT(dev)) {
if (dev_priv->lvds_dither) if (dev_priv->lvds_dither)
lvds |= LVDS_ENABLE_DITHER; temp |= LVDS_ENABLE_DITHER;
else else
lvds &= ~LVDS_ENABLE_DITHER; temp &= ~LVDS_ENABLE_DITHER;
} }
I915_WRITE(lvds_reg, lvds); I915_WRITE(reg, temp);
I915_READ(lvds_reg);
} }
/* set the dithering flag and clear for anything other than a panel. */ /* set the dithering flag and clear for anything other than a panel. */
...@@ -4115,32 +4033,32 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, ...@@ -4115,32 +4033,32 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
if (!has_edp_encoder) { if (!has_edp_encoder) {
I915_WRITE(fp_reg, fp); I915_WRITE(fp_reg, fp);
I915_WRITE(dpll_reg, dpll); I915_WRITE(dpll_reg, dpll);
I915_READ(dpll_reg);
/* Wait for the clocks to stabilize. */ /* Wait for the clocks to stabilize. */
POSTING_READ(dpll_reg);
udelay(150); udelay(150);
if (IS_I965G(dev) && !HAS_PCH_SPLIT(dev)) { if (IS_I965G(dev) && !HAS_PCH_SPLIT(dev)) {
temp = 0;
if (is_sdvo) { if (is_sdvo) {
int pixel_multiplier = intel_mode_get_pixel_multiplier(adjusted_mode); temp = intel_mode_get_pixel_multiplier(adjusted_mode);
if (pixel_multiplier > 1) if (temp > 1)
pixel_multiplier = (pixel_multiplier - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT; temp = (temp - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT;
else else
pixel_multiplier = 0; temp = 0;
}
I915_WRITE(dpll_md_reg, I915_WRITE(DPLL_MD(pipe), temp);
(0 << DPLL_MD_UDI_DIVIDER_SHIFT) |
pixel_multiplier);
} else
I915_WRITE(dpll_md_reg, 0);
} else { } else {
/* write it again -- the BIOS does, after all */ /* write it again -- the BIOS does, after all */
I915_WRITE(dpll_reg, dpll); I915_WRITE(dpll_reg, dpll);
} }
I915_READ(dpll_reg);
/* Wait for the clocks to stabilize. */ /* Wait for the clocks to stabilize. */
POSTING_READ(dpll_reg);
udelay(150); udelay(150);
} }
intel_crtc->lowfreq_avail = false;
if (is_lvds && has_reduced_clock && i915_powersave) { if (is_lvds && has_reduced_clock && i915_powersave) {
I915_WRITE(fp_reg + 4, fp2); I915_WRITE(fp_reg + 4, fp2);
intel_crtc->lowfreq_avail = true; intel_crtc->lowfreq_avail = true;
...@@ -4150,7 +4068,6 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, ...@@ -4150,7 +4068,6 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
} }
} else { } else {
I915_WRITE(fp_reg + 4, fp); I915_WRITE(fp_reg + 4, fp);
intel_crtc->lowfreq_avail = false;
if (HAS_PIPE_CXSR(dev)) { if (HAS_PIPE_CXSR(dev)) {
DRM_DEBUG_KMS("disabling CxSR downclocking\n"); DRM_DEBUG_KMS("disabling CxSR downclocking\n");
pipeconf &= ~PIPECONF_CXSR_DOWNCLOCK; pipeconf &= ~PIPECONF_CXSR_DOWNCLOCK;
...@@ -4169,58 +4086,72 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, ...@@ -4169,58 +4086,72 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
} else } else
pipeconf &= ~PIPECONF_INTERLACE_W_FIELD_INDICATION; /* progressive */ pipeconf &= ~PIPECONF_INTERLACE_W_FIELD_INDICATION; /* progressive */
I915_WRITE(htot_reg, (adjusted_mode->crtc_hdisplay - 1) | I915_WRITE(HTOTAL(pipe),
(adjusted_mode->crtc_hdisplay - 1) |
((adjusted_mode->crtc_htotal - 1) << 16)); ((adjusted_mode->crtc_htotal - 1) << 16));
I915_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - 1) | I915_WRITE(HBLANK(pipe),
(adjusted_mode->crtc_hblank_start - 1) |
((adjusted_mode->crtc_hblank_end - 1) << 16)); ((adjusted_mode->crtc_hblank_end - 1) << 16));
I915_WRITE(hsync_reg, (adjusted_mode->crtc_hsync_start - 1) | I915_WRITE(HSYNC(pipe),
(adjusted_mode->crtc_hsync_start - 1) |
((adjusted_mode->crtc_hsync_end - 1) << 16)); ((adjusted_mode->crtc_hsync_end - 1) << 16));
I915_WRITE(vtot_reg, (adjusted_mode->crtc_vdisplay - 1) |
I915_WRITE(VTOTAL(pipe),
(adjusted_mode->crtc_vdisplay - 1) |
((adjusted_mode->crtc_vtotal - 1) << 16)); ((adjusted_mode->crtc_vtotal - 1) << 16));
I915_WRITE(vblank_reg, (adjusted_mode->crtc_vblank_start - 1) | I915_WRITE(VBLANK(pipe),
(adjusted_mode->crtc_vblank_start - 1) |
((adjusted_mode->crtc_vblank_end - 1) << 16)); ((adjusted_mode->crtc_vblank_end - 1) << 16));
I915_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start - 1) | I915_WRITE(VSYNC(pipe),
(adjusted_mode->crtc_vsync_start - 1) |
((adjusted_mode->crtc_vsync_end - 1) << 16)); ((adjusted_mode->crtc_vsync_end - 1) << 16));
/* pipesrc and dspsize control the size that is scaled from, which should
* always be the user's requested size. /* pipesrc and dspsize control the size that is scaled from,
* which should always be the user's requested size.
*/ */
if (!HAS_PCH_SPLIT(dev)) { if (!HAS_PCH_SPLIT(dev)) {
I915_WRITE(dspsize_reg, ((mode->vdisplay - 1) << 16) | I915_WRITE(DSPSIZE(plane),
(mode->hdisplay - 1)); ((mode->vdisplay - 1) << 16) |
I915_WRITE(dsppos_reg, 0); (mode->hdisplay - 1));
I915_WRITE(DSPPOS(plane), 0);
} }
I915_WRITE(pipesrc_reg, ((mode->hdisplay - 1) << 16) | (mode->vdisplay - 1)); I915_WRITE(PIPESRC(pipe),
((mode->hdisplay - 1) << 16) | (mode->vdisplay - 1));
if (HAS_PCH_SPLIT(dev)) { if (HAS_PCH_SPLIT(dev)) {
I915_WRITE(data_m1_reg, TU_SIZE(m_n.tu) | m_n.gmch_m); I915_WRITE(PIPE_DATA_M1(pipe), TU_SIZE(m_n.tu) | m_n.gmch_m);
I915_WRITE(data_n1_reg, m_n.gmch_n); I915_WRITE(PIPE_DATA_N1(pipe), m_n.gmch_n);
I915_WRITE(link_m1_reg, m_n.link_m); I915_WRITE(PIPE_LINK_M1(pipe), m_n.link_m);
I915_WRITE(link_n1_reg, m_n.link_n); I915_WRITE(PIPE_LINK_N1(pipe), m_n.link_n);
if (has_edp_encoder) { if (has_edp_encoder) {
ironlake_set_pll_edp(crtc, adjusted_mode->clock); ironlake_set_pll_edp(crtc, adjusted_mode->clock);
} else { } else {
/* enable FDI RX PLL too */ /* enable FDI RX PLL too */
temp = I915_READ(fdi_rx_reg); reg = FDI_RX_CTL(pipe);
I915_WRITE(fdi_rx_reg, temp | FDI_RX_PLL_ENABLE); temp = I915_READ(reg);
I915_READ(fdi_rx_reg); I915_WRITE(reg, temp | FDI_RX_PLL_ENABLE);
POSTING_READ(reg);
udelay(200); udelay(200);
/* enable FDI TX PLL too */ /* enable FDI TX PLL too */
temp = I915_READ(fdi_tx_reg); reg = FDI_TX_CTL(pipe);
I915_WRITE(fdi_tx_reg, temp | FDI_TX_PLL_ENABLE); temp = I915_READ(reg);
I915_READ(fdi_tx_reg); I915_WRITE(reg, temp | FDI_TX_PLL_ENABLE);
/* enable FDI RX PCDCLK */ /* enable FDI RX PCDCLK */
temp = I915_READ(fdi_rx_reg); reg = FDI_RX_CTL(pipe);
I915_WRITE(fdi_rx_reg, temp | FDI_SEL_PCDCLK); temp = I915_READ(reg);
I915_READ(fdi_rx_reg); I915_WRITE(reg, temp | FDI_PCDCLK);
POSTING_READ(reg);
udelay(200); udelay(200);
} }
} }
I915_WRITE(pipeconf_reg, pipeconf); I915_WRITE(PIPECONF(pipe), pipeconf);
I915_READ(pipeconf_reg); POSTING_READ(PIPECONF(pipe));
intel_wait_for_vblank(dev, pipe); intel_wait_for_vblank(dev, pipe);
...@@ -4230,9 +4161,8 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, ...@@ -4230,9 +4161,8 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
I915_WRITE(DISP_ARB_CTL, temp | DISP_TILE_SURFACE_SWIZZLING); I915_WRITE(DISP_ARB_CTL, temp | DISP_TILE_SURFACE_SWIZZLING);
} }
I915_WRITE(dspcntr_reg, dspcntr); I915_WRITE(DSPCNTR(plane), dspcntr);
/* Flush the plane changes */
ret = intel_pipe_set_base(crtc, x, y, old_fb); ret = intel_pipe_set_base(crtc, x, y, old_fb);
intel_update_watermarks(dev); intel_update_watermarks(dev);
......
...@@ -255,7 +255,7 @@ i830_activate_pipe_a(struct drm_device *dev) ...@@ -255,7 +255,7 @@ i830_activate_pipe_a(struct drm_device *dev)
return 0; return 0;
/* most i8xx have pipe a forced on, so don't trust dpms mode */ /* most i8xx have pipe a forced on, so don't trust dpms mode */
if (I915_READ(PIPEACONF) & PIPEACONF_ENABLE) if (I915_READ(PIPEACONF) & PIPECONF_ENABLE)
return 0; return 0;
crtc_funcs = crtc->base.helper_private; crtc_funcs = crtc->base.helper_private;
...@@ -876,15 +876,14 @@ static int check_overlay_possible_on_crtc(struct intel_overlay *overlay, ...@@ -876,15 +876,14 @@ static int check_overlay_possible_on_crtc(struct intel_overlay *overlay,
{ {
drm_i915_private_t *dev_priv = overlay->dev->dev_private; drm_i915_private_t *dev_priv = overlay->dev->dev_private;
u32 pipeconf; u32 pipeconf;
int pipeconf_reg = (crtc->pipe == 0) ? PIPEACONF : PIPEBCONF;
if (!crtc->base.enabled || crtc->dpms_mode != DRM_MODE_DPMS_ON) if (!crtc->base.enabled || crtc->dpms_mode != DRM_MODE_DPMS_ON)
return -EINVAL; return -EINVAL;
pipeconf = I915_READ(pipeconf_reg); pipeconf = I915_READ(PIPECONF(crtc->pipe));
/* can't use the overlay with double wide pipe */ /* can't use the overlay with double wide pipe */
if (!IS_I965G(overlay->dev) && pipeconf & PIPEACONF_DOUBLE_WIDE) if (!IS_I965G(overlay->dev) && pipeconf & PIPECONF_DOUBLE_WIDE)
return -EINVAL; return -EINVAL;
return 0; return 0;
......
...@@ -1168,7 +1168,7 @@ intel_tv_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, ...@@ -1168,7 +1168,7 @@ intel_tv_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
if (!IS_I9XX(dev)) if (!IS_I9XX(dev))
intel_wait_for_vblank(dev, intel_crtc->pipe); intel_wait_for_vblank(dev, intel_crtc->pipe);
I915_WRITE(pipeconf_reg, pipeconf & ~PIPEACONF_ENABLE); I915_WRITE(pipeconf_reg, pipeconf & ~PIPECONF_ENABLE);
/* Wait for vblank for the disable to take effect. */ /* Wait for vblank for the disable to take effect. */
intel_wait_for_vblank_off(dev, intel_crtc->pipe); intel_wait_for_vblank_off(dev, intel_crtc->pipe);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment