diff options
Diffstat (limited to 'drivers/gpu/drm')
-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) |