summaryrefslogtreecommitdiffstats
path: root/kernel/drivers/gpu/drm/i915/intel_overlay.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/drivers/gpu/drm/i915/intel_overlay.c')
-rw-r--r--kernel/drivers/gpu/drm/i915/intel_overlay.c131
1 files changed, 81 insertions, 50 deletions
diff --git a/kernel/drivers/gpu/drm/i915/intel_overlay.c b/kernel/drivers/gpu/drm/i915/intel_overlay.c
index dd92122ed..444542696 100644
--- a/kernel/drivers/gpu/drm/i915/intel_overlay.c
+++ b/kernel/drivers/gpu/drm/i915/intel_overlay.c
@@ -172,10 +172,11 @@ struct intel_overlay {
struct intel_crtc *crtc;
struct drm_i915_gem_object *vid_bo;
struct drm_i915_gem_object *old_vid_bo;
- int active;
- int pfit_active;
+ bool active;
+ bool pfit_active;
u32 pfit_vscale_ratio; /* shifted-point number, (1<<12) == 1.0 */
- u32 color_key;
+ u32 color_key:24;
+ u32 color_key_enabled:1;
u32 brightness, contrast, saturation;
u32 old_xscale, old_yscale;
/* register access */
@@ -209,25 +210,19 @@ static void intel_overlay_unmap_regs(struct intel_overlay *overlay,
}
static int intel_overlay_do_wait_request(struct intel_overlay *overlay,
+ struct drm_i915_gem_request *req,
void (*tail)(struct intel_overlay *))
{
- struct drm_device *dev = overlay->dev;
- struct drm_i915_private *dev_priv = dev->dev_private;
- struct intel_engine_cs *ring = &dev_priv->ring[RCS];
int ret;
- BUG_ON(overlay->last_flip_req);
- i915_gem_request_assign(&overlay->last_flip_req,
- ring->outstanding_lazy_request);
- ret = i915_add_request(ring);
- if (ret)
- return ret;
+ WARN_ON(overlay->last_flip_req);
+ i915_gem_request_assign(&overlay->last_flip_req, req);
+ i915_add_request(req);
overlay->flip_tail = tail;
ret = i915_wait_request(overlay->last_flip_req);
if (ret)
return ret;
- i915_gem_retire_requests(dev);
i915_gem_request_assign(&overlay->last_flip_req, NULL);
return 0;
@@ -239,24 +234,31 @@ static int intel_overlay_on(struct intel_overlay *overlay)
struct drm_device *dev = overlay->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_engine_cs *ring = &dev_priv->ring[RCS];
+ struct drm_i915_gem_request *req;
int ret;
- BUG_ON(overlay->active);
- overlay->active = 1;
-
+ WARN_ON(overlay->active);
WARN_ON(IS_I830(dev) && !(dev_priv->quirks & QUIRK_PIPEA_FORCE));
- ret = intel_ring_begin(ring, 4);
+ ret = i915_gem_request_alloc(ring, ring->default_context, &req);
if (ret)
return ret;
+ ret = intel_ring_begin(req, 4);
+ if (ret) {
+ i915_gem_request_cancel(req);
+ return ret;
+ }
+
+ overlay->active = true;
+
intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_ON);
intel_ring_emit(ring, overlay->flip_addr | OFC_UPDATE);
intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
intel_ring_emit(ring, MI_NOOP);
intel_ring_advance(ring);
- return intel_overlay_do_wait_request(overlay, NULL);
+ return intel_overlay_do_wait_request(overlay, req, NULL);
}
/* overlay needs to be enabled in OCMD reg */
@@ -266,11 +268,12 @@ static int intel_overlay_continue(struct intel_overlay *overlay,
struct drm_device *dev = overlay->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_engine_cs *ring = &dev_priv->ring[RCS];
+ struct drm_i915_gem_request *req;
u32 flip_addr = overlay->flip_addr;
u32 tmp;
int ret;
- BUG_ON(!overlay->active);
+ WARN_ON(!overlay->active);
if (load_polyphase_filter)
flip_addr |= OFC_UPDATE;
@@ -280,18 +283,25 @@ static int intel_overlay_continue(struct intel_overlay *overlay,
if (tmp & (1 << 17))
DRM_DEBUG("overlay underrun, DOVSTA: %x\n", tmp);
- ret = intel_ring_begin(ring, 2);
+ ret = i915_gem_request_alloc(ring, ring->default_context, &req);
if (ret)
return ret;
+ ret = intel_ring_begin(req, 2);
+ if (ret) {
+ i915_gem_request_cancel(req);
+ return ret;
+ }
+
intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE);
intel_ring_emit(ring, flip_addr);
intel_ring_advance(ring);
WARN_ON(overlay->last_flip_req);
- i915_gem_request_assign(&overlay->last_flip_req,
- ring->outstanding_lazy_request);
- return i915_add_request(ring);
+ i915_gem_request_assign(&overlay->last_flip_req, req);
+ i915_add_request(req);
+
+ return 0;
}
static void intel_overlay_release_old_vid_tail(struct intel_overlay *overlay)
@@ -309,7 +319,8 @@ static void intel_overlay_off_tail(struct intel_overlay *overlay)
struct drm_i915_gem_object *obj = overlay->vid_bo;
/* never have the overlay hw on without showing a frame */
- BUG_ON(!overlay->vid_bo);
+ if (WARN_ON(!obj))
+ return;
i915_gem_object_ggtt_unpin(obj);
drm_gem_object_unreference(&obj->base);
@@ -317,7 +328,7 @@ static void intel_overlay_off_tail(struct intel_overlay *overlay)
overlay->crtc->overlay = NULL;
overlay->crtc = NULL;
- overlay->active = 0;
+ overlay->active = false;
}
/* overlay needs to be disabled in OCMD reg */
@@ -326,10 +337,11 @@ static int intel_overlay_off(struct intel_overlay *overlay)
struct drm_device *dev = overlay->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_engine_cs *ring = &dev_priv->ring[RCS];
+ struct drm_i915_gem_request *req;
u32 flip_addr = overlay->flip_addr;
int ret;
- BUG_ON(!overlay->active);
+ WARN_ON(!overlay->active);
/* According to intel docs the overlay hw may hang (when switching
* off) without loading the filter coeffs. It is however unclear whether
@@ -337,10 +349,16 @@ static int intel_overlay_off(struct intel_overlay *overlay)
* of the hw. Do it in both cases */
flip_addr |= OFC_UPDATE;
- ret = intel_ring_begin(ring, 6);
+ ret = i915_gem_request_alloc(ring, ring->default_context, &req);
if (ret)
return ret;
+ ret = intel_ring_begin(req, 6);
+ if (ret) {
+ i915_gem_request_cancel(req);
+ return ret;
+ }
+
/* wait for overlay to go idle */
intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE);
intel_ring_emit(ring, flip_addr);
@@ -359,7 +377,7 @@ static int intel_overlay_off(struct intel_overlay *overlay)
}
intel_ring_advance(ring);
- return intel_overlay_do_wait_request(overlay, intel_overlay_off_tail);
+ return intel_overlay_do_wait_request(overlay, req, intel_overlay_off_tail);
}
/* recover from an interruption due to a signal
@@ -374,7 +392,6 @@ static int intel_overlay_recover_from_interrupt(struct intel_overlay *overlay)
ret = i915_wait_request(overlay->last_flip_req);
if (ret)
return ret;
- i915_gem_retire_requests(overlay->dev);
if (overlay->flip_tail)
overlay->flip_tail(overlay);
@@ -404,15 +421,23 @@ static int intel_overlay_release_old_vid(struct intel_overlay *overlay)
if (I915_READ(ISR) & I915_OVERLAY_PLANE_FLIP_PENDING_INTERRUPT) {
/* synchronous slowpath */
- ret = intel_ring_begin(ring, 2);
+ struct drm_i915_gem_request *req;
+
+ ret = i915_gem_request_alloc(ring, ring->default_context, &req);
if (ret)
return ret;
+ ret = intel_ring_begin(req, 2);
+ if (ret) {
+ i915_gem_request_cancel(req);
+ return ret;
+ }
+
intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
intel_ring_emit(ring, MI_NOOP);
intel_ring_advance(ring);
- ret = intel_overlay_do_wait_request(overlay,
+ ret = intel_overlay_do_wait_request(overlay, req,
intel_overlay_release_old_vid_tail);
if (ret)
return ret;
@@ -629,31 +654,36 @@ static void update_colorkey(struct intel_overlay *overlay,
struct overlay_registers __iomem *regs)
{
u32 key = overlay->color_key;
+ u32 flags;
+
+ flags = 0;
+ if (overlay->color_key_enabled)
+ flags |= DST_KEY_ENABLE;
switch (overlay->crtc->base.primary->fb->bits_per_pixel) {
case 8:
- iowrite32(0, &regs->DCLRKV);
- iowrite32(CLK_RGB8I_MASK | DST_KEY_ENABLE, &regs->DCLRKM);
+ key = 0;
+ flags |= CLK_RGB8I_MASK;
break;
case 16:
if (overlay->crtc->base.primary->fb->depth == 15) {
- iowrite32(RGB15_TO_COLORKEY(key), &regs->DCLRKV);
- iowrite32(CLK_RGB15_MASK | DST_KEY_ENABLE,
- &regs->DCLRKM);
+ key = RGB15_TO_COLORKEY(key);
+ flags |= CLK_RGB15_MASK;
} else {
- iowrite32(RGB16_TO_COLORKEY(key), &regs->DCLRKV);
- iowrite32(CLK_RGB16_MASK | DST_KEY_ENABLE,
- &regs->DCLRKM);
+ key = RGB16_TO_COLORKEY(key);
+ flags |= CLK_RGB16_MASK;
}
break;
case 24:
case 32:
- iowrite32(key, &regs->DCLRKV);
- iowrite32(CLK_RGB24_MASK | DST_KEY_ENABLE, &regs->DCLRKM);
+ flags |= CLK_RGB24_MASK;
break;
}
+
+ iowrite32(key, &regs->DCLRKV);
+ iowrite32(flags, &regs->DCLRKM);
}
static u32 overlay_cmd_reg(struct put_image_params *params)
@@ -712,15 +742,14 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay,
u32 swidth, swidthsw, sheight, ostride;
enum pipe pipe = overlay->crtc->pipe;
- BUG_ON(!mutex_is_locked(&dev->struct_mutex));
- BUG_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
- BUG_ON(!overlay);
+ WARN_ON(!mutex_is_locked(&dev->struct_mutex));
+ WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
ret = intel_overlay_release_old_vid(overlay);
if (ret != 0)
return ret;
- ret = i915_gem_object_pin_to_display_plane(new_bo, 0, NULL,
+ ret = i915_gem_object_pin_to_display_plane(new_bo, 0, NULL, NULL,
&i915_ggtt_view_normal);
if (ret != 0)
return ret;
@@ -824,8 +853,8 @@ int intel_overlay_switch_off(struct intel_overlay *overlay)
struct drm_device *dev = overlay->dev;
int ret;
- BUG_ON(!mutex_is_locked(&dev->struct_mutex));
- BUG_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
+ WARN_ON(!mutex_is_locked(&dev->struct_mutex));
+ WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
ret = intel_overlay_recover_from_interrupt(overlay);
if (ret != 0)
@@ -1131,10 +1160,10 @@ int intel_overlay_put_image(struct drm_device *dev, void *data,
/* line too wide, i.e. one-line-mode */
if (mode->hdisplay > 1024 &&
intel_panel_fitter_pipe(dev) == crtc->pipe) {
- overlay->pfit_active = 1;
+ overlay->pfit_active = true;
update_pfit_vscale_ratio(overlay);
} else
- overlay->pfit_active = 0;
+ overlay->pfit_active = false;
}
ret = check_overlay_dst(overlay, put_image_rec);
@@ -1329,6 +1358,7 @@ int intel_overlay_attrs(struct drm_device *dev, void *data,
I915_WRITE(OGAMC5, attrs->gamma5);
}
}
+ overlay->color_key_enabled = (attrs->flags & I915_OVERLAY_DISABLE_DEST_COLORKEY) == 0;
ret = 0;
out_unlock:
@@ -1392,6 +1422,7 @@ void intel_setup_overlay(struct drm_device *dev)
/* init all values */
overlay->color_key = 0x0101fe;
+ overlay->color_key_enabled = true;
overlay->brightness = -19;
overlay->contrast = 75;
overlay->saturation = 146;
@@ -1432,7 +1463,7 @@ void intel_cleanup_overlay(struct drm_device *dev)
/* The bo's should be free'd by the generic code already.
* Furthermore modesetting teardown happens beforehand so the
* hardware should be off already */
- BUG_ON(dev_priv->overlay->active);
+ WARN_ON(dev_priv->overlay->active);
drm_gem_object_unreference_unlocked(&dev_priv->overlay->reg_bo->base);
kfree(dev_priv->overlay);