diff options
author | Jesse Barnes <jbarnes@virtuousgeek.org> | 2009-09-10 18:28:06 -0400 |
---|---|---|
committer | Eric Anholt <eric@anholt.net> | 2009-09-10 22:46:07 -0400 |
commit | 8082400327d8d2ca54254b593644942bed0edd25 (patch) | |
tree | 43a32ac4e56e985341e2109d2c4d545d3d6df6cb /drivers/gpu/drm/i915/intel_display.c | |
parent | 06324194eee97a51b5f172270df49ec39192d6cc (diff) |
drm/i915: framebuffer compression for pre-GM45
This patch adds framebuffer compression (good for about ~0.5W power
savings in the best case) support for pre-GM45 chips. GM45+ have a new,
more flexible FBC scheme that will be added in a separate patch.
FBC can't always be enabled: the compressed buffer must be physically
contiguous and reside in stolen space. So if you have a large display
and a small amount of stolen memory, you may not be able to take
advantage of FBC. In some cases, a BIOS setting controls how much
stolen space is available. Increasing this to 8 or 16M can help.
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Diffstat (limited to 'drivers/gpu/drm/i915/intel_display.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 222 |
1 files changed, 209 insertions, 13 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 92e0aae7070a..cadb9efdfb1b 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
@@ -954,6 +954,174 @@ intel_wait_for_vblank(struct drm_device *dev) | |||
954 | mdelay(20); | 954 | mdelay(20); |
955 | } | 955 | } |
956 | 956 | ||
957 | /* Parameters have changed, update FBC info */ | ||
958 | static void i8xx_enable_fbc(struct drm_crtc *crtc, unsigned long interval) | ||
959 | { | ||
960 | struct drm_device *dev = crtc->dev; | ||
961 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
962 | struct drm_framebuffer *fb = crtc->fb; | ||
963 | struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); | ||
964 | struct drm_i915_gem_object *obj_priv = intel_fb->obj->driver_private; | ||
965 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | ||
966 | int plane, i; | ||
967 | u32 fbc_ctl, fbc_ctl2; | ||
968 | |||
969 | dev_priv->cfb_pitch = dev_priv->cfb_size / FBC_LL_SIZE; | ||
970 | |||
971 | if (fb->pitch < dev_priv->cfb_pitch) | ||
972 | dev_priv->cfb_pitch = fb->pitch; | ||
973 | |||
974 | /* FBC_CTL wants 64B units */ | ||
975 | dev_priv->cfb_pitch = (dev_priv->cfb_pitch / 64) - 1; | ||
976 | dev_priv->cfb_fence = obj_priv->fence_reg; | ||
977 | dev_priv->cfb_plane = intel_crtc->plane; | ||
978 | plane = dev_priv->cfb_plane == 0 ? FBC_CTL_PLANEA : FBC_CTL_PLANEB; | ||
979 | |||
980 | /* Clear old tags */ | ||
981 | for (i = 0; i < (FBC_LL_SIZE / 32) + 1; i++) | ||
982 | I915_WRITE(FBC_TAG + (i * 4), 0); | ||
983 | |||
984 | /* Set it up... */ | ||
985 | fbc_ctl2 = FBC_CTL_FENCE_DBL | FBC_CTL_IDLE_IMM | plane; | ||
986 | if (obj_priv->tiling_mode != I915_TILING_NONE) | ||
987 | fbc_ctl2 |= FBC_CTL_CPU_FENCE; | ||
988 | I915_WRITE(FBC_CONTROL2, fbc_ctl2); | ||
989 | I915_WRITE(FBC_FENCE_OFF, crtc->y); | ||
990 | |||
991 | /* enable it... */ | ||
992 | fbc_ctl = FBC_CTL_EN | FBC_CTL_PERIODIC; | ||
993 | fbc_ctl |= (dev_priv->cfb_pitch & 0xff) << FBC_CTL_STRIDE_SHIFT; | ||
994 | fbc_ctl |= (interval & 0x2fff) << FBC_CTL_INTERVAL_SHIFT; | ||
995 | if (obj_priv->tiling_mode != I915_TILING_NONE) | ||
996 | fbc_ctl |= dev_priv->cfb_fence; | ||
997 | I915_WRITE(FBC_CONTROL, fbc_ctl); | ||
998 | |||
999 | DRM_DEBUG("enabled FBC, pitch %ld, yoff %d, plane %d, ", | ||
1000 | dev_priv->cfb_pitch, crtc->y, dev_priv->cfb_plane); | ||
1001 | } | ||
1002 | |||
1003 | void i8xx_disable_fbc(struct drm_device *dev) | ||
1004 | { | ||
1005 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
1006 | u32 fbc_ctl; | ||
1007 | |||
1008 | /* Disable compression */ | ||
1009 | fbc_ctl = I915_READ(FBC_CONTROL); | ||
1010 | fbc_ctl &= ~FBC_CTL_EN; | ||
1011 | I915_WRITE(FBC_CONTROL, fbc_ctl); | ||
1012 | |||
1013 | /* Wait for compressing bit to clear */ | ||
1014 | while (I915_READ(FBC_STATUS) & FBC_STAT_COMPRESSING) | ||
1015 | ; /* nothing */ | ||
1016 | |||
1017 | intel_wait_for_vblank(dev); | ||
1018 | |||
1019 | DRM_DEBUG("disabled FBC\n"); | ||
1020 | } | ||
1021 | |||
1022 | static bool i8xx_fbc_enabled(struct drm_crtc *crtc) | ||
1023 | { | ||
1024 | struct drm_device *dev = crtc->dev; | ||
1025 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
1026 | |||
1027 | return I915_READ(FBC_CONTROL) & FBC_CTL_EN; | ||
1028 | } | ||
1029 | |||
1030 | /** | ||
1031 | * intel_update_fbc - enable/disable FBC as needed | ||
1032 | * @crtc: CRTC to point the compressor at | ||
1033 | * @mode: mode in use | ||
1034 | * | ||
1035 | * Set up the framebuffer compression hardware at mode set time. We | ||
1036 | * enable it if possible: | ||
1037 | * - plane A only (on pre-965) | ||
1038 | * - no pixel mulitply/line duplication | ||
1039 | * - no alpha buffer discard | ||
1040 | * - no dual wide | ||
1041 | * - framebuffer <= 2048 in width, 1536 in height | ||
1042 | * | ||
1043 | * We can't assume that any compression will take place (worst case), | ||
1044 | * so the compressed buffer has to be the same size as the uncompressed | ||
1045 | * one. It also must reside (along with the line length buffer) in | ||
1046 | * stolen memory. | ||
1047 | * | ||
1048 | * We need to enable/disable FBC on a global basis. | ||
1049 | */ | ||
1050 | static void intel_update_fbc(struct drm_crtc *crtc, | ||
1051 | struct drm_display_mode *mode) | ||
1052 | { | ||
1053 | struct drm_device *dev = crtc->dev; | ||
1054 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
1055 | struct drm_framebuffer *fb = crtc->fb; | ||
1056 | struct intel_framebuffer *intel_fb; | ||
1057 | struct drm_i915_gem_object *obj_priv; | ||
1058 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | ||
1059 | int plane = intel_crtc->plane; | ||
1060 | |||
1061 | if (!i915_powersave) | ||
1062 | return; | ||
1063 | |||
1064 | if (!crtc->fb) | ||
1065 | return; | ||
1066 | |||
1067 | intel_fb = to_intel_framebuffer(fb); | ||
1068 | obj_priv = intel_fb->obj->driver_private; | ||
1069 | |||
1070 | /* | ||
1071 | * If FBC is already on, we just have to verify that we can | ||
1072 | * keep it that way... | ||
1073 | * Need to disable if: | ||
1074 | * - changing FBC params (stride, fence, mode) | ||
1075 | * - new fb is too large to fit in compressed buffer | ||
1076 | * - going to an unsupported config (interlace, pixel multiply, etc.) | ||
1077 | */ | ||
1078 | if (intel_fb->obj->size > dev_priv->cfb_size) { | ||
1079 | DRM_DEBUG("framebuffer too large, disabling compression\n"); | ||
1080 | goto out_disable; | ||
1081 | } | ||
1082 | if ((mode->flags & DRM_MODE_FLAG_INTERLACE) || | ||
1083 | (mode->flags & DRM_MODE_FLAG_DBLSCAN)) { | ||
1084 | DRM_DEBUG("mode incompatible with compression, disabling\n"); | ||
1085 | goto out_disable; | ||
1086 | } | ||
1087 | if ((mode->hdisplay > 2048) || | ||
1088 | (mode->vdisplay > 1536)) { | ||
1089 | DRM_DEBUG("mode too large for compression, disabling\n"); | ||
1090 | goto out_disable; | ||
1091 | } | ||
1092 | if (IS_I9XX(dev) && plane != 0) { | ||
1093 | DRM_DEBUG("plane not 0, disabling compression\n"); | ||
1094 | goto out_disable; | ||
1095 | } | ||
1096 | if (obj_priv->tiling_mode != I915_TILING_X) { | ||
1097 | DRM_DEBUG("framebuffer not tiled, disabling compression\n"); | ||
1098 | goto out_disable; | ||
1099 | } | ||
1100 | |||
1101 | if (i8xx_fbc_enabled(crtc)) { | ||
1102 | /* We can re-enable it in this case, but need to update pitch */ | ||
1103 | if (fb->pitch > dev_priv->cfb_pitch) | ||
1104 | i8xx_disable_fbc(dev); | ||
1105 | if (obj_priv->fence_reg != dev_priv->cfb_fence) | ||
1106 | i8xx_disable_fbc(dev); | ||
1107 | if (plane != dev_priv->cfb_plane) | ||
1108 | i8xx_disable_fbc(dev); | ||
1109 | } | ||
1110 | |||
1111 | if (!i8xx_fbc_enabled(crtc)) { | ||
1112 | /* Now try to turn it back on if possible */ | ||
1113 | i8xx_enable_fbc(crtc, 500); | ||
1114 | } | ||
1115 | |||
1116 | return; | ||
1117 | |||
1118 | out_disable: | ||
1119 | DRM_DEBUG("unsupported config, disabling FBC\n"); | ||
1120 | /* Multiple disables should be harmless */ | ||
1121 | if (i8xx_fbc_enabled(crtc)) | ||
1122 | i8xx_disable_fbc(dev); | ||
1123 | } | ||
1124 | |||
957 | static int | 1125 | static int |
958 | intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, | 1126 | intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, |
959 | struct drm_framebuffer *old_fb) | 1127 | struct drm_framebuffer *old_fb) |
@@ -966,12 +1134,13 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, | |||
966 | struct drm_i915_gem_object *obj_priv; | 1134 | struct drm_i915_gem_object *obj_priv; |
967 | struct drm_gem_object *obj; | 1135 | struct drm_gem_object *obj; |
968 | int pipe = intel_crtc->pipe; | 1136 | int pipe = intel_crtc->pipe; |
1137 | int plane = intel_crtc->plane; | ||
969 | unsigned long Start, Offset; | 1138 | unsigned long Start, Offset; |
970 | int dspbase = (pipe == 0 ? DSPAADDR : DSPBADDR); | 1139 | int dspbase = (plane == 0 ? DSPAADDR : DSPBADDR); |
971 | int dspsurf = (pipe == 0 ? DSPASURF : DSPBSURF); | 1140 | int dspsurf = (plane == 0 ? DSPASURF : DSPBSURF); |
972 | int dspstride = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE; | 1141 | int dspstride = (plane == 0) ? DSPASTRIDE : DSPBSTRIDE; |
973 | int dsptileoff = (pipe == 0 ? DSPATILEOFF : DSPBTILEOFF); | 1142 | int dsptileoff = (plane == 0 ? DSPATILEOFF : DSPBTILEOFF); |
974 | int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; | 1143 | int dspcntr_reg = (plane == 0) ? DSPACNTR : DSPBCNTR; |
975 | u32 dspcntr, alignment; | 1144 | u32 dspcntr, alignment; |
976 | int ret; | 1145 | int ret; |
977 | 1146 | ||
@@ -981,12 +1150,12 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, | |||
981 | return 0; | 1150 | return 0; |
982 | } | 1151 | } |
983 | 1152 | ||
984 | switch (pipe) { | 1153 | switch (plane) { |
985 | case 0: | 1154 | case 0: |
986 | case 1: | 1155 | case 1: |
987 | break; | 1156 | break; |
988 | default: | 1157 | default: |
989 | DRM_ERROR("Can't update pipe %d in SAREA\n", pipe); | 1158 | DRM_ERROR("Can't update plane %d in SAREA\n", plane); |
990 | return -EINVAL; | 1159 | return -EINVAL; |
991 | } | 1160 | } |
992 | 1161 | ||
@@ -1114,6 +1283,9 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, | |||
1114 | master_priv->sarea_priv->pipeA_y = y; | 1283 | master_priv->sarea_priv->pipeA_y = y; |
1115 | } | 1284 | } |
1116 | 1285 | ||
1286 | if (I915_HAS_FBC(dev) && (IS_I965G(dev) || plane == 0)) | ||
1287 | intel_update_fbc(crtc, &crtc->mode); | ||
1288 | |||
1117 | return 0; | 1289 | return 0; |
1118 | } | 1290 | } |
1119 | 1291 | ||
@@ -1534,9 +1706,10 @@ static void i9xx_crtc_dpms(struct drm_crtc *crtc, int mode) | |||
1534 | struct drm_i915_private *dev_priv = dev->dev_private; | 1706 | struct drm_i915_private *dev_priv = dev->dev_private; |
1535 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 1707 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
1536 | int pipe = intel_crtc->pipe; | 1708 | int pipe = intel_crtc->pipe; |
1709 | int plane = intel_crtc->plane; | ||
1537 | int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B; | 1710 | int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B; |
1538 | int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; | 1711 | int dspcntr_reg = (plane == 0) ? DSPACNTR : DSPBCNTR; |
1539 | int dspbase_reg = (pipe == 0) ? DSPAADDR : DSPBADDR; | 1712 | int dspbase_reg = (plane == 0) ? DSPAADDR : DSPBADDR; |
1540 | int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; | 1713 | int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; |
1541 | u32 temp; | 1714 | u32 temp; |
1542 | 1715 | ||
@@ -1579,6 +1752,9 @@ static void i9xx_crtc_dpms(struct drm_crtc *crtc, int mode) | |||
1579 | 1752 | ||
1580 | intel_crtc_load_lut(crtc); | 1753 | intel_crtc_load_lut(crtc); |
1581 | 1754 | ||
1755 | if (I915_HAS_FBC(dev) && (IS_I965G(dev) || plane == 0)) | ||
1756 | intel_update_fbc(crtc, &crtc->mode); | ||
1757 | |||
1582 | /* Give the overlay scaler a chance to enable if it's on this pipe */ | 1758 | /* Give the overlay scaler a chance to enable if it's on this pipe */ |
1583 | //intel_crtc_dpms_video(crtc, true); TODO | 1759 | //intel_crtc_dpms_video(crtc, true); TODO |
1584 | intel_update_watermarks(dev); | 1760 | intel_update_watermarks(dev); |
@@ -1588,6 +1764,9 @@ static void i9xx_crtc_dpms(struct drm_crtc *crtc, int mode) | |||
1588 | /* Give the overlay scaler a chance to disable if it's on this pipe */ | 1764 | /* Give the overlay scaler a chance to disable if it's on this pipe */ |
1589 | //intel_crtc_dpms_video(crtc, FALSE); TODO | 1765 | //intel_crtc_dpms_video(crtc, FALSE); TODO |
1590 | 1766 | ||
1767 | if (dev_priv->cfb_plane == plane) | ||
1768 | i8xx_disable_fbc(dev); | ||
1769 | |||
1591 | /* Disable the VGA plane that we never use */ | 1770 | /* Disable the VGA plane that we never use */ |
1592 | i915_disable_vga(dev); | 1771 | i915_disable_vga(dev); |
1593 | 1772 | ||
@@ -2325,10 +2504,11 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
2325 | struct drm_i915_private *dev_priv = dev->dev_private; | 2504 | struct drm_i915_private *dev_priv = dev->dev_private; |
2326 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 2505 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
2327 | int pipe = intel_crtc->pipe; | 2506 | int pipe = intel_crtc->pipe; |
2507 | int plane = intel_crtc->plane; | ||
2328 | int fp_reg = (pipe == 0) ? FPA0 : FPB0; | 2508 | int fp_reg = (pipe == 0) ? FPA0 : FPB0; |
2329 | int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B; | 2509 | int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B; |
2330 | int dpll_md_reg = (intel_crtc->pipe == 0) ? DPLL_A_MD : DPLL_B_MD; | 2510 | int dpll_md_reg = (intel_crtc->pipe == 0) ? DPLL_A_MD : DPLL_B_MD; |
2331 | int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; | 2511 | int dspcntr_reg = (plane == 0) ? DSPACNTR : DSPBCNTR; |
2332 | int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; | 2512 | int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; |
2333 | int htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B; | 2513 | int htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B; |
2334 | int hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B; | 2514 | int hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B; |
@@ -2336,8 +2516,8 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
2336 | int vtot_reg = (pipe == 0) ? VTOTAL_A : VTOTAL_B; | 2516 | int vtot_reg = (pipe == 0) ? VTOTAL_A : VTOTAL_B; |
2337 | int vblank_reg = (pipe == 0) ? VBLANK_A : VBLANK_B; | 2517 | int vblank_reg = (pipe == 0) ? VBLANK_A : VBLANK_B; |
2338 | int vsync_reg = (pipe == 0) ? VSYNC_A : VSYNC_B; | 2518 | int vsync_reg = (pipe == 0) ? VSYNC_A : VSYNC_B; |
2339 | int dspsize_reg = (pipe == 0) ? DSPASIZE : DSPBSIZE; | 2519 | int dspsize_reg = (plane == 0) ? DSPASIZE : DSPBSIZE; |
2340 | int dsppos_reg = (pipe == 0) ? DSPAPOS : DSPBPOS; | 2520 | int dsppos_reg = (plane == 0) ? DSPAPOS : DSPBPOS; |
2341 | int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC; | 2521 | int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC; |
2342 | int refclk, num_outputs = 0; | 2522 | int refclk, num_outputs = 0; |
2343 | intel_clock_t clock, reduced_clock; | 2523 | intel_clock_t clock, reduced_clock; |
@@ -2570,7 +2750,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
2570 | enable color space conversion */ | 2750 | enable color space conversion */ |
2571 | if (!IS_IGDNG(dev)) { | 2751 | if (!IS_IGDNG(dev)) { |
2572 | if (pipe == 0) | 2752 | if (pipe == 0) |
2573 | dspcntr |= DISPPLANE_SEL_PIPE_A; | 2753 | dspcntr &= ~DISPPLANE_SEL_PIPE_MASK; |
2574 | else | 2754 | else |
2575 | dspcntr |= DISPPLANE_SEL_PIPE_B; | 2755 | dspcntr |= DISPPLANE_SEL_PIPE_B; |
2576 | } | 2756 | } |
@@ -2739,6 +2919,8 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
2739 | /* Flush the plane changes */ | 2919 | /* Flush the plane changes */ |
2740 | ret = intel_pipe_set_base(crtc, x, y, old_fb); | 2920 | ret = intel_pipe_set_base(crtc, x, y, old_fb); |
2741 | 2921 | ||
2922 | if (I915_HAS_FBC(dev) && (IS_I965G(dev) || plane == 0)) | ||
2923 | intel_update_fbc(crtc, &crtc->mode); | ||
2742 | intel_update_watermarks(dev); | 2924 | intel_update_watermarks(dev); |
2743 | 2925 | ||
2744 | drm_vblank_post_modeset(dev, pipe); | 2926 | drm_vblank_post_modeset(dev, pipe); |
@@ -2783,6 +2965,7 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc, | |||
2783 | struct drm_gem_object *bo; | 2965 | struct drm_gem_object *bo; |
2784 | struct drm_i915_gem_object *obj_priv; | 2966 | struct drm_i915_gem_object *obj_priv; |
2785 | int pipe = intel_crtc->pipe; | 2967 | int pipe = intel_crtc->pipe; |
2968 | int plane = intel_crtc->plane; | ||
2786 | uint32_t control = (pipe == 0) ? CURACNTR : CURBCNTR; | 2969 | uint32_t control = (pipe == 0) ? CURACNTR : CURBCNTR; |
2787 | uint32_t base = (pipe == 0) ? CURABASE : CURBBASE; | 2970 | uint32_t base = (pipe == 0) ? CURABASE : CURBBASE; |
2788 | uint32_t temp = I915_READ(control); | 2971 | uint32_t temp = I915_READ(control); |
@@ -2868,6 +3051,10 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc, | |||
2868 | i915_gem_object_unpin(intel_crtc->cursor_bo); | 3051 | i915_gem_object_unpin(intel_crtc->cursor_bo); |
2869 | drm_gem_object_unreference(intel_crtc->cursor_bo); | 3052 | drm_gem_object_unreference(intel_crtc->cursor_bo); |
2870 | } | 3053 | } |
3054 | |||
3055 | if (I915_HAS_FBC(dev) && (IS_I965G(dev) || plane == 0)) | ||
3056 | intel_update_fbc(crtc, &crtc->mode); | ||
3057 | |||
2871 | mutex_unlock(&dev->struct_mutex); | 3058 | mutex_unlock(&dev->struct_mutex); |
2872 | 3059 | ||
2873 | intel_crtc->cursor_addr = addr; | 3060 | intel_crtc->cursor_addr = addr; |
@@ -3549,6 +3736,14 @@ static void intel_crtc_init(struct drm_device *dev, int pipe) | |||
3549 | intel_crtc->lut_b[i] = i; | 3736 | intel_crtc->lut_b[i] = i; |
3550 | } | 3737 | } |
3551 | 3738 | ||
3739 | /* Swap pipes & planes for FBC on pre-965 */ | ||
3740 | intel_crtc->pipe = pipe; | ||
3741 | intel_crtc->plane = pipe; | ||
3742 | if (IS_MOBILE(dev) && (IS_I9XX(dev) && !IS_I965G(dev))) { | ||
3743 | DRM_DEBUG("swapping pipes & planes for FBC\n"); | ||
3744 | intel_crtc->plane = ((pipe == 0) ? 1 : 0); | ||
3745 | } | ||
3746 | |||
3552 | intel_crtc->cursor_addr = 0; | 3747 | intel_crtc->cursor_addr = 0; |
3553 | intel_crtc->dpms_mode = DRM_MODE_DPMS_OFF; | 3748 | intel_crtc->dpms_mode = DRM_MODE_DPMS_OFF; |
3554 | drm_crtc_helper_add(&intel_crtc->base, &intel_helper_funcs); | 3749 | drm_crtc_helper_add(&intel_crtc->base, &intel_helper_funcs); |
@@ -3909,6 +4104,7 @@ void intel_modeset_cleanup(struct drm_device *dev) | |||
3909 | 4104 | ||
3910 | mutex_unlock(&dev->struct_mutex); | 4105 | mutex_unlock(&dev->struct_mutex); |
3911 | 4106 | ||
4107 | i8xx_disable_fbc(dev); | ||
3912 | drm_mode_config_cleanup(dev); | 4108 | drm_mode_config_cleanup(dev); |
3913 | } | 4109 | } |
3914 | 4110 | ||