diff options
| -rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 144 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/intel_drv.h | 8 |
2 files changed, 99 insertions, 53 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 132314e2bf21..ca3b8a8933c6 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
| @@ -43,6 +43,7 @@ | |||
| 43 | bool intel_pipe_has_type (struct drm_crtc *crtc, int type); | 43 | bool intel_pipe_has_type (struct drm_crtc *crtc, int type); |
| 44 | static void intel_update_watermarks(struct drm_device *dev); | 44 | static void intel_update_watermarks(struct drm_device *dev); |
| 45 | static void intel_increase_pllclock(struct drm_crtc *crtc, bool schedule); | 45 | static void intel_increase_pllclock(struct drm_crtc *crtc, bool schedule); |
| 46 | static void intel_crtc_update_cursor(struct drm_crtc *crtc); | ||
| 46 | 47 | ||
| 47 | typedef struct { | 48 | typedef struct { |
| 48 | /* given values */ | 49 | /* given values */ |
| @@ -3575,6 +3576,9 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
| 3575 | return -EINVAL; | 3576 | return -EINVAL; |
| 3576 | } | 3577 | } |
| 3577 | 3578 | ||
| 3579 | /* Ensure that the cursor is valid for the new mode before changing... */ | ||
| 3580 | intel_crtc_update_cursor(crtc); | ||
| 3581 | |||
| 3578 | if (is_lvds && dev_priv->lvds_downclock_avail) { | 3582 | if (is_lvds && dev_priv->lvds_downclock_avail) { |
| 3579 | has_reduced_clock = limit->find_pll(limit, crtc, | 3583 | has_reduced_clock = limit->find_pll(limit, crtc, |
| 3580 | dev_priv->lvds_downclock, | 3584 | dev_priv->lvds_downclock, |
| @@ -4111,6 +4115,85 @@ void intel_crtc_load_lut(struct drm_crtc *crtc) | |||
| 4111 | } | 4115 | } |
| 4112 | } | 4116 | } |
| 4113 | 4117 | ||
| 4118 | /* If no-part of the cursor is visible on the framebuffer, then the GPU may hang... */ | ||
| 4119 | static void intel_crtc_update_cursor(struct drm_crtc *crtc) | ||
| 4120 | { | ||
| 4121 | struct drm_device *dev = crtc->dev; | ||
| 4122 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 4123 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | ||
| 4124 | int pipe = intel_crtc->pipe; | ||
| 4125 | int x = intel_crtc->cursor_x; | ||
| 4126 | int y = intel_crtc->cursor_y; | ||
| 4127 | uint32_t base, pos; | ||
| 4128 | bool visible; | ||
| 4129 | |||
| 4130 | pos = 0; | ||
| 4131 | |||
| 4132 | if (crtc->fb) { | ||
| 4133 | base = intel_crtc->cursor_addr; | ||
| 4134 | if (x > (int) crtc->fb->width) | ||
| 4135 | base = 0; | ||
| 4136 | |||
| 4137 | if (y > (int) crtc->fb->height) | ||
| 4138 | base = 0; | ||
| 4139 | } else | ||
| 4140 | base = 0; | ||
| 4141 | |||
| 4142 | if (x < 0) { | ||
| 4143 | if (x + intel_crtc->cursor_width < 0) | ||
| 4144 | base = 0; | ||
| 4145 | |||
| 4146 | pos |= CURSOR_POS_SIGN << CURSOR_X_SHIFT; | ||
| 4147 | x = -x; | ||
| 4148 | } | ||
| 4149 | pos |= x << CURSOR_X_SHIFT; | ||
| 4150 | |||
| 4151 | if (y < 0) { | ||
| 4152 | if (y + intel_crtc->cursor_height < 0) | ||
| 4153 | base = 0; | ||
| 4154 | |||
| 4155 | pos |= CURSOR_POS_SIGN << CURSOR_Y_SHIFT; | ||
| 4156 | y = -y; | ||
| 4157 | } | ||
| 4158 | pos |= y << CURSOR_Y_SHIFT; | ||
| 4159 | |||
| 4160 | visible = base != 0; | ||
| 4161 | if (!visible && !intel_crtc->cursor_visble) | ||
| 4162 | return; | ||
| 4163 | |||
| 4164 | I915_WRITE(pipe == 0 ? CURAPOS : CURBPOS, pos); | ||
| 4165 | if (intel_crtc->cursor_visble != visible) { | ||
| 4166 | uint32_t cntl = I915_READ(pipe == 0 ? CURACNTR : CURBCNTR); | ||
| 4167 | if (base) { | ||
| 4168 | /* Hooray for CUR*CNTR differences */ | ||
| 4169 | if (IS_MOBILE(dev) || IS_I9XX(dev)) { | ||
| 4170 | cntl &= ~(CURSOR_MODE | MCURSOR_PIPE_SELECT); | ||
| 4171 | cntl |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE; | ||
| 4172 | cntl |= pipe << 28; /* Connect to correct pipe */ | ||
| 4173 | } else { | ||
| 4174 | cntl &= ~(CURSOR_FORMAT_MASK); | ||
| 4175 | cntl |= CURSOR_ENABLE; | ||
| 4176 | cntl |= CURSOR_FORMAT_ARGB | CURSOR_GAMMA_ENABLE; | ||
| 4177 | } | ||
| 4178 | } else { | ||
| 4179 | if (IS_MOBILE(dev) || IS_I9XX(dev)) { | ||
| 4180 | cntl &= ~(CURSOR_MODE | MCURSOR_GAMMA_ENABLE); | ||
| 4181 | cntl |= CURSOR_MODE_DISABLE; | ||
| 4182 | } else { | ||
| 4183 | cntl &= ~(CURSOR_ENABLE | CURSOR_GAMMA_ENABLE); | ||
| 4184 | } | ||
| 4185 | } | ||
| 4186 | I915_WRITE(pipe == 0 ? CURACNTR : CURBCNTR, cntl); | ||
| 4187 | |||
| 4188 | intel_crtc->cursor_visble = visible; | ||
| 4189 | } | ||
| 4190 | /* and commit changes on next vblank */ | ||
| 4191 | I915_WRITE(pipe == 0 ? CURABASE : CURBBASE, base); | ||
| 4192 | |||
| 4193 | if (visible) | ||
| 4194 | intel_mark_busy(dev, to_intel_framebuffer(crtc->fb)->obj); | ||
| 4195 | } | ||
| 4196 | |||
| 4114 | static int intel_crtc_cursor_set(struct drm_crtc *crtc, | 4197 | static int intel_crtc_cursor_set(struct drm_crtc *crtc, |
| 4115 | struct drm_file *file_priv, | 4198 | struct drm_file *file_priv, |
| 4116 | uint32_t handle, | 4199 | uint32_t handle, |
| @@ -4121,11 +4204,7 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc, | |||
| 4121 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 4204 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
| 4122 | struct drm_gem_object *bo; | 4205 | struct drm_gem_object *bo; |
| 4123 | struct drm_i915_gem_object *obj_priv; | 4206 | struct drm_i915_gem_object *obj_priv; |
| 4124 | int pipe = intel_crtc->pipe; | 4207 | uint32_t addr; |
| 4125 | uint32_t control = (pipe == 0) ? CURACNTR : CURBCNTR; | ||
| 4126 | uint32_t base = (pipe == 0) ? CURABASE : CURBBASE; | ||
| 4127 | uint32_t temp = I915_READ(control); | ||
| 4128 | size_t addr; | ||
| 4129 | int ret; | 4208 | int ret; |
| 4130 | 4209 | ||
| 4131 | DRM_DEBUG_KMS("\n"); | 4210 | DRM_DEBUG_KMS("\n"); |
| @@ -4133,12 +4212,6 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc, | |||
| 4133 | /* if we want to turn off the cursor ignore width and height */ | 4212 | /* if we want to turn off the cursor ignore width and height */ |
| 4134 | if (!handle) { | 4213 | if (!handle) { |
| 4135 | DRM_DEBUG_KMS("cursor off\n"); | 4214 | DRM_DEBUG_KMS("cursor off\n"); |
| 4136 | if (IS_MOBILE(dev) || IS_I9XX(dev)) { | ||
| 4137 | temp &= ~(CURSOR_MODE | MCURSOR_GAMMA_ENABLE); | ||
| 4138 | temp |= CURSOR_MODE_DISABLE; | ||
| 4139 | } else { | ||
| 4140 | temp &= ~(CURSOR_ENABLE | CURSOR_GAMMA_ENABLE); | ||
| 4141 | } | ||
| 4142 | addr = 0; | 4215 | addr = 0; |
| 4143 | bo = NULL; | 4216 | bo = NULL; |
| 4144 | mutex_lock(&dev->struct_mutex); | 4217 | mutex_lock(&dev->struct_mutex); |
| @@ -4180,7 +4253,8 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc, | |||
| 4180 | 4253 | ||
| 4181 | addr = obj_priv->gtt_offset; | 4254 | addr = obj_priv->gtt_offset; |
| 4182 | } else { | 4255 | } else { |
| 4183 | ret = i915_gem_attach_phys_object(dev, bo, (pipe == 0) ? I915_GEM_PHYS_CURSOR_0 : I915_GEM_PHYS_CURSOR_1); | 4256 | ret = i915_gem_attach_phys_object(dev, bo, |
| 4257 | (intel_crtc->pipe == 0) ? I915_GEM_PHYS_CURSOR_0 : I915_GEM_PHYS_CURSOR_1); | ||
| 4184 | if (ret) { | 4258 | if (ret) { |
| 4185 | DRM_ERROR("failed to attach phys object\n"); | 4259 | DRM_ERROR("failed to attach phys object\n"); |
| 4186 | goto fail_locked; | 4260 | goto fail_locked; |
| @@ -4191,21 +4265,7 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc, | |||
| 4191 | if (!IS_I9XX(dev)) | 4265 | if (!IS_I9XX(dev)) |
| 4192 | I915_WRITE(CURSIZE, (height << 12) | width); | 4266 | I915_WRITE(CURSIZE, (height << 12) | width); |
| 4193 | 4267 | ||
| 4194 | /* Hooray for CUR*CNTR differences */ | ||
| 4195 | if (IS_MOBILE(dev) || IS_I9XX(dev)) { | ||
| 4196 | temp &= ~(CURSOR_MODE | MCURSOR_PIPE_SELECT); | ||
| 4197 | temp |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE; | ||
| 4198 | temp |= (pipe << 28); /* Connect to correct pipe */ | ||
| 4199 | } else { | ||
| 4200 | temp &= ~(CURSOR_FORMAT_MASK); | ||
| 4201 | temp |= CURSOR_ENABLE; | ||
| 4202 | temp |= CURSOR_FORMAT_ARGB | CURSOR_GAMMA_ENABLE; | ||
| 4203 | } | ||
| 4204 | |||
| 4205 | finish: | 4268 | finish: |
| 4206 | I915_WRITE(control, temp); | ||
| 4207 | I915_WRITE(base, addr); | ||
| 4208 | |||
| 4209 | if (intel_crtc->cursor_bo) { | 4269 | if (intel_crtc->cursor_bo) { |
| 4210 | if (dev_priv->info->cursor_needs_physical) { | 4270 | if (dev_priv->info->cursor_needs_physical) { |
| 4211 | if (intel_crtc->cursor_bo != bo) | 4271 | if (intel_crtc->cursor_bo != bo) |
| @@ -4219,6 +4279,10 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc, | |||
| 4219 | 4279 | ||
| 4220 | intel_crtc->cursor_addr = addr; | 4280 | intel_crtc->cursor_addr = addr; |
| 4221 | intel_crtc->cursor_bo = bo; | 4281 | intel_crtc->cursor_bo = bo; |
| 4282 | intel_crtc->cursor_width = width; | ||
| 4283 | intel_crtc->cursor_height = height; | ||
| 4284 | |||
| 4285 | intel_crtc_update_cursor(crtc); | ||
| 4222 | 4286 | ||
| 4223 | return 0; | 4287 | return 0; |
| 4224 | fail_unpin: | 4288 | fail_unpin: |
| @@ -4232,34 +4296,12 @@ fail: | |||
| 4232 | 4296 | ||
| 4233 | static int intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) | 4297 | static int intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) |
| 4234 | { | 4298 | { |
| 4235 | struct drm_device *dev = crtc->dev; | ||
| 4236 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 4237 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 4299 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
| 4238 | struct intel_framebuffer *intel_fb; | ||
| 4239 | int pipe = intel_crtc->pipe; | ||
| 4240 | uint32_t temp = 0; | ||
| 4241 | uint32_t adder; | ||
| 4242 | |||
| 4243 | if (crtc->fb) { | ||
| 4244 | intel_fb = to_intel_framebuffer(crtc->fb); | ||
| 4245 | intel_mark_busy(dev, intel_fb->obj); | ||
| 4246 | } | ||
| 4247 | |||
| 4248 | if (x < 0) { | ||
| 4249 | temp |= CURSOR_POS_SIGN << CURSOR_X_SHIFT; | ||
| 4250 | x = -x; | ||
| 4251 | } | ||
| 4252 | if (y < 0) { | ||
| 4253 | temp |= CURSOR_POS_SIGN << CURSOR_Y_SHIFT; | ||
| 4254 | y = -y; | ||
| 4255 | } | ||
| 4256 | 4300 | ||
| 4257 | temp |= x << CURSOR_X_SHIFT; | 4301 | intel_crtc->cursor_x = x; |
| 4258 | temp |= y << CURSOR_Y_SHIFT; | 4302 | intel_crtc->cursor_y = y; |
| 4259 | 4303 | ||
| 4260 | adder = intel_crtc->cursor_addr; | 4304 | intel_crtc_update_cursor(crtc); |
| 4261 | I915_WRITE((pipe == 0) ? CURAPOS : CURBPOS, temp); | ||
| 4262 | I915_WRITE((pipe == 0) ? CURABASE : CURBBASE, adder); | ||
| 4263 | 4305 | ||
| 4264 | return 0; | 4306 | return 0; |
| 4265 | } | 4307 | } |
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 296933a8d395..b2190148703a 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h | |||
| @@ -143,8 +143,6 @@ struct intel_crtc { | |||
| 143 | struct drm_crtc base; | 143 | struct drm_crtc base; |
| 144 | enum pipe pipe; | 144 | enum pipe pipe; |
| 145 | enum plane plane; | 145 | enum plane plane; |
| 146 | struct drm_gem_object *cursor_bo; | ||
| 147 | uint32_t cursor_addr; | ||
| 148 | u8 lut_r[256], lut_g[256], lut_b[256]; | 146 | u8 lut_r[256], lut_g[256], lut_b[256]; |
| 149 | int dpms_mode; | 147 | int dpms_mode; |
| 150 | bool busy; /* is scanout buffer being updated frequently? */ | 148 | bool busy; /* is scanout buffer being updated frequently? */ |
| @@ -153,6 +151,12 @@ struct intel_crtc { | |||
| 153 | struct intel_overlay *overlay; | 151 | struct intel_overlay *overlay; |
| 154 | struct intel_unpin_work *unpin_work; | 152 | struct intel_unpin_work *unpin_work; |
| 155 | int fdi_lanes; | 153 | int fdi_lanes; |
| 154 | |||
| 155 | struct drm_gem_object *cursor_bo; | ||
| 156 | uint32_t cursor_addr; | ||
| 157 | int16_t cursor_x, cursor_y; | ||
| 158 | int16_t cursor_width, cursor_height; | ||
| 159 | bool cursor_visble; | ||
| 156 | }; | 160 | }; |
| 157 | 161 | ||
| 158 | #define to_intel_crtc(x) container_of(x, struct intel_crtc, base) | 162 | #define to_intel_crtc(x) container_of(x, struct intel_crtc, base) |
