From: Ville Syrjälä <ville.syrjala@xxxxxxxxxxxxxxx> The cursor plane also supports 180 degree rotation. Add a new "cursor-rotation" property on the crtc which controls this. Unlike sprites, the cursor has a fixed size, so if you have a small cursor image with the rest of the bo filled by transparent pixels, simply flipping the rotation property will cause the visible part of the cursor to shift. This is something to keep in mind when using cursor rotation. Cc: Sagar Kamble <sagar.a.kamble@xxxxxxxxx> Signed-off-by: Ville Syrjälä <ville.syrjala@xxxxxxxxxxxxxxx> --- drivers/gpu/drm/i915/i915_dma.c | 9 ++++++ drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/i915_reg.h | 1 + drivers/gpu/drm/i915/intel_display.c | 59 ++++++++++++++++++++++++------------ drivers/gpu/drm/i915/intel_drv.h | 1 + 5 files changed, 51 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 4a3ef34..3dd9abb 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1916,6 +1916,15 @@ void i915_driver_lastclose(struct drm_device * dev) } } + if (dev_priv->cursor_rotation_property) { + list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head) { + crtc->cursor_rotation = BIT(DRM_ROTATE_0); + drm_object_property_set_value(&crtc->base.base, + dev_priv->cursor_rotation_property, + crtc->cursor_rotation); + } + } + if (drm_core_check_feature(dev, DRIVER_MODESET)) { intel_fbdev_restore_mode(dev); vga_switcheroo_process_delayed_switch(); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 6af78ee..8ecd3bb 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1562,6 +1562,7 @@ typedef struct drm_i915_private { struct drm_property *force_audio_property; struct drm_property *rotation_property; /* "rotation" */ struct drm_property *plane_rotation_property; /* "plane-rotation" */ + struct drm_property *cursor_rotation_property; /* "cursor-rotation" */ uint32_t hw_context_size; struct list_head context_list; diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index ab1aeb82..fee068a 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -3534,6 +3534,7 @@ #define MCURSOR_PIPE_A 0x00 #define MCURSOR_PIPE_B (1 << 28) #define MCURSOR_GAMMA_ENABLE (1 << 26) +#define CURSOR_ROTATE_180 (1<<15) #define CURSOR_TRICKLE_FEED_DISABLE (1 << 14) #define _CURABASE (dev_priv->info.display_mmio_offset + 0x70084) #define _CURAPOS (dev_priv->info.display_mmio_offset + 0x70088) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 37b23d1..e94167b 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -42,7 +42,7 @@ #include <linux/dma_remapping.h> static void intel_increase_pllclock(struct drm_crtc *crtc); -static void intel_crtc_update_cursor(struct drm_crtc *crtc, bool on); +static void intel_crtc_update_cursor(struct drm_crtc *crtc, bool on, bool force); static void i9xx_crtc_clock_get(struct intel_crtc *crtc, struct intel_crtc_config *pipe_config); @@ -3640,7 +3640,7 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc) intel_enable_pipe(intel_crtc); intel_enable_primary_plane(dev_priv, plane, pipe); intel_enable_planes(crtc); - intel_crtc_update_cursor(crtc, true); + intel_crtc_update_cursor(crtc, true, false); if (intel_crtc->config.has_pch_encoder) ironlake_pch_enable(crtc); @@ -3682,7 +3682,7 @@ static void haswell_crtc_enable_planes(struct drm_crtc *crtc) intel_enable_primary_plane(dev_priv, plane, pipe); intel_enable_planes(crtc); - intel_crtc_update_cursor(crtc, true); + intel_crtc_update_cursor(crtc, true, false); hsw_enable_ips(intel_crtc); @@ -3708,7 +3708,7 @@ static void haswell_crtc_disable_planes(struct drm_crtc *crtc) hsw_disable_ips(intel_crtc); - intel_crtc_update_cursor(crtc, false); + intel_crtc_update_cursor(crtc, false, false); intel_disable_planes(crtc); intel_disable_primary_plane(dev_priv, plane, pipe); } @@ -3836,7 +3836,7 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc) if (dev_priv->fbc.plane == plane) intel_disable_fbc(dev); - intel_crtc_update_cursor(crtc, false); + intel_crtc_update_cursor(crtc, false, false); intel_disable_planes(crtc); intel_disable_primary_plane(dev_priv, plane, pipe); @@ -4211,7 +4211,7 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc) intel_set_cpu_fifo_underrun_reporting(dev, pipe, true); intel_enable_primary_plane(dev_priv, plane, pipe); intel_enable_planes(crtc); - intel_crtc_update_cursor(crtc, true); + intel_crtc_update_cursor(crtc, true, false); intel_update_fbc(dev); @@ -4253,7 +4253,7 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc) /* The fixup needs to happen before cursor is enabled */ if (IS_G4X(dev)) g4x_fixup_plane(dev_priv, pipe); - intel_crtc_update_cursor(crtc, true); + intel_crtc_update_cursor(crtc, true, false); /* Give the overlay scaler a chance to enable if it's on this pipe */ intel_crtc_dpms_overlay(intel_crtc, true); @@ -4302,7 +4302,7 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc) intel_disable_fbc(dev); intel_crtc_dpms_overlay(intel_crtc, false); - intel_crtc_update_cursor(crtc, false); + intel_crtc_update_cursor(crtc, false, false); intel_disable_planes(crtc); intel_disable_primary_plane(dev_priv, plane, pipe); @@ -7429,7 +7429,7 @@ void intel_write_eld(struct drm_encoder *encoder, dev_priv->display.write_eld(connector, crtc, mode); } -static void i845_update_cursor(struct drm_crtc *crtc, u32 base) +static void i845_update_cursor(struct drm_crtc *crtc, u32 base, bool force) { struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; @@ -7437,7 +7437,7 @@ static void i845_update_cursor(struct drm_crtc *crtc, u32 base) bool visible = base != 0; u32 cntl; - if (intel_crtc->cursor_visible == visible) + if (!force && intel_crtc->cursor_visible == visible) return; cntl = I915_READ(_CURACNTR); @@ -7459,7 +7459,7 @@ static void i845_update_cursor(struct drm_crtc *crtc, u32 base) intel_crtc->cursor_visible = visible; } -static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base) +static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base, bool force) { struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; @@ -7467,7 +7467,7 @@ static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base) int pipe = intel_crtc->pipe; bool visible = base != 0; - if (intel_crtc->cursor_visible != visible) { + if (force || intel_crtc->cursor_visible != visible) { uint32_t cntl = I915_READ(CURCNTR(pipe)); if (base) { cntl &= ~(CURSOR_MODE | MCURSOR_PIPE_SELECT); @@ -7477,6 +7477,10 @@ static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base) cntl &= ~(CURSOR_MODE | MCURSOR_GAMMA_ENABLE); cntl |= CURSOR_MODE_DISABLE; } + if (intel_crtc->cursor_rotation == BIT(DRM_ROTATE_180)) + cntl |= CURSOR_ROTATE_180; + else + cntl &= ~CURSOR_ROTATE_180; I915_WRITE(CURCNTR(pipe), cntl); intel_crtc->cursor_visible = visible; @@ -7487,7 +7491,7 @@ static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base) POSTING_READ(CURBASE(pipe)); } -static void ivb_update_cursor(struct drm_crtc *crtc, u32 base) +static void ivb_update_cursor(struct drm_crtc *crtc, u32 base, bool force) { struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; @@ -7495,7 +7499,7 @@ static void ivb_update_cursor(struct drm_crtc *crtc, u32 base) int pipe = intel_crtc->pipe; bool visible = base != 0; - if (intel_crtc->cursor_visible != visible) { + if (force || intel_crtc->cursor_visible != visible) { uint32_t cntl = I915_READ(CURCNTR_IVB(pipe)); if (base) { cntl &= ~CURSOR_MODE; @@ -7508,6 +7512,10 @@ static void ivb_update_cursor(struct drm_crtc *crtc, u32 base) cntl |= CURSOR_PIPE_CSC_ENABLE; cntl &= ~CURSOR_TRICKLE_FEED_DISABLE; } + if (intel_crtc->cursor_rotation == BIT(DRM_ROTATE_180)) + cntl |= CURSOR_ROTATE_180; + else + cntl &= ~CURSOR_ROTATE_180; I915_WRITE(CURCNTR_IVB(pipe), cntl); intel_crtc->cursor_visible = visible; @@ -7520,7 +7528,7 @@ static void ivb_update_cursor(struct drm_crtc *crtc, u32 base) /* If no-part of the cursor is visible on the framebuffer, then the GPU may hang... */ static void intel_crtc_update_cursor(struct drm_crtc *crtc, - bool on) + bool on, bool force) { struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; @@ -7564,13 +7572,13 @@ static void intel_crtc_update_cursor(struct drm_crtc *crtc, if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev) || IS_BROADWELL(dev)) { I915_WRITE(CURPOS_IVB(pipe), pos); - ivb_update_cursor(crtc, base); + ivb_update_cursor(crtc, base, force); } else { I915_WRITE(CURPOS(pipe), pos); if (IS_845G(dev) || IS_I865G(dev)) - i845_update_cursor(crtc, base); + i845_update_cursor(crtc, base, force); else - i9xx_update_cursor(crtc, base); + i9xx_update_cursor(crtc, base, force); } } @@ -7677,7 +7685,7 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc, intel_crtc->cursor_height = height; if (intel_crtc->active) - intel_crtc_update_cursor(crtc, intel_crtc->cursor_bo != NULL); + intel_crtc_update_cursor(crtc, intel_crtc->cursor_bo != NULL, false); return 0; fail_unpin: @@ -7697,7 +7705,7 @@ static int intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) intel_crtc->cursor_y = clamp_t(int, y, SHRT_MIN, SHRT_MAX); if (intel_crtc->active) - intel_crtc_update_cursor(crtc, intel_crtc->cursor_bo != NULL); + intel_crtc_update_cursor(crtc, intel_crtc->cursor_bo != NULL, false); return 0; } @@ -10388,6 +10396,7 @@ static void intel_crtc_init(struct drm_device *dev, int pipe) intel_crtc->pipe = pipe; intel_crtc->plane = pipe; intel_crtc->primary_rotation = BIT(DRM_ROTATE_0); + intel_crtc->cursor_rotation = BIT(DRM_ROTATE_0); if (HAS_FBC(dev) && INTEL_INFO(dev)->gen < 4) { DRM_DEBUG_KMS("swapping pipes & planes for FBC\n"); intel_crtc->plane = !pipe; @@ -10408,6 +10417,16 @@ static void intel_crtc_init(struct drm_device *dev, int pipe) drm_object_attach_property(&intel_crtc->base.base, dev_priv->plane_rotation_property, intel_crtc->primary_rotation); + + if (!dev_priv->cursor_rotation_property) + dev_priv->cursor_rotation_property = + drm_mode_create_rotation_property(dev, "cursor-rotation", + BIT(DRM_ROTATE_0) | + BIT(DRM_ROTATE_180)); + if (dev_priv->cursor_rotation_property) + drm_object_attach_property(&intel_crtc->base.base, + dev_priv->cursor_rotation_property, + intel_crtc->cursor_rotation); } drm_crtc_helper_add(&intel_crtc->base, &intel_helper_funcs); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 8c17a82..4a7f4f1 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -332,6 +332,7 @@ struct intel_crtc { enum pipe pipe; enum plane plane; unsigned int primary_rotation; /* primary plane in relation to the pipe */ + unsigned int cursor_rotation; /* cursor plane in relation to the pipe */ u8 lut_r[256], lut_g[256], lut_b[256]; /* -- 1.8.3.2 _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/dri-devel