aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r--drivers/gpu/drm/i915/intel_display.c144
-rw-r--r--drivers/gpu/drm/i915/intel_drv.h8
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 @@
43bool intel_pipe_has_type (struct drm_crtc *crtc, int type); 43bool intel_pipe_has_type (struct drm_crtc *crtc, int type);
44static void intel_update_watermarks(struct drm_device *dev); 44static void intel_update_watermarks(struct drm_device *dev);
45static void intel_increase_pllclock(struct drm_crtc *crtc, bool schedule); 45static void intel_increase_pllclock(struct drm_crtc *crtc, bool schedule);
46static void intel_crtc_update_cursor(struct drm_crtc *crtc);
46 47
47typedef struct { 48typedef 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... */
4119static 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
4114static int intel_crtc_cursor_set(struct drm_crtc *crtc, 4197static 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;
4224fail_unpin: 4288fail_unpin:
@@ -4232,34 +4296,12 @@ fail:
4232 4296
4233static int intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) 4297static 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)