Reviewed-by: Sagar Kamble <sagar.a.kamble@xxxxxxxxx> On Wed, 2014-02-12 at 23:15 +0200, ville.syrjala@xxxxxxxxxxxxxxx wrote: > From: Ville Syrjälä <ville.syrjala@xxxxxxxxxxxxxxx> > > We can pretend that we can rotate the entire pipe by rotating all the > planes and adjusting their positions appropriately. Add a "rotation" > property on the crtc which will do this. > > The main upshot of doing the full pipe rotation instead of rotating all > the planes individually is that the plane positions turn out correct > automagically. So userspace doesn't need to do anything except toggle > the property and continue as if nothing had changed. > > The actual implementation is pretty much trivial thanks to drm_rect > and drm_rotation_chain() ;) > > Cc: Sagar Kamble <sagar.a.kamble@xxxxxxxxx> > Signed-off-by: Ville Syrjälä <ville.syrjala@xxxxxxxxxxxxxxx> > --- > drivers/gpu/drm/i915/i915_dma.c | 6 ++ > drivers/gpu/drm/i915/intel_display.c | 154 +++++++++++++++++++++++++++++++---- > drivers/gpu/drm/i915/intel_drv.h | 1 + > drivers/gpu/drm/i915/intel_pm.c | 6 +- > drivers/gpu/drm/i915/intel_sprite.c | 21 +++-- > 5 files changed, 164 insertions(+), 24 deletions(-) > > diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c > index 3dd9abb..b59bff1 100644 > --- a/drivers/gpu/drm/i915/i915_dma.c > +++ b/drivers/gpu/drm/i915/i915_dma.c > @@ -1914,6 +1914,12 @@ void i915_driver_lastclose(struct drm_device * dev) > dev_priv->rotation_property, > plane->rotation); > } > + list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head) { > + crtc->pipe_rotation = BIT(DRM_ROTATE_0); > + drm_object_property_set_value(&crtc->base.base, > + dev_priv->rotation_property, > + crtc->pipe_rotation); > + } > } > > if (dev_priv->cursor_rotation_property) { > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c > index e94167b..1b74d24 100644 > --- a/drivers/gpu/drm/i915/intel_display.c > +++ b/drivers/gpu/drm/i915/intel_display.c > @@ -39,6 +39,7 @@ > #include "i915_trace.h" > #include <drm/drm_dp_helper.h> > #include <drm/drm_crtc_helper.h> > +#include <drm/drm_rect.h> > #include <linux/dma_remapping.h> > > static void intel_increase_pllclock(struct drm_crtc *crtc); > @@ -2060,6 +2061,8 @@ static int i9xx_update_plane(struct drm_crtc *crtc, struct drm_framebuffer *fb, > u32 dspcntr; > u32 reg; > int pixel_size; > + unsigned int rotation = drm_rotation_chain(intel_crtc->pipe_rotation, > + intel_crtc->primary_rotation); > > switch (plane) { > case 0: > @@ -2133,7 +2136,7 @@ static int i9xx_update_plane(struct drm_crtc *crtc, struct drm_framebuffer *fb, > intel_crtc->dspaddr_offset = linear_offset; > } > > - if (intel_crtc->primary_rotation == BIT(DRM_ROTATE_180)) { > + if (rotation == BIT(DRM_ROTATE_180)) { > dspcntr |= DISPPLANE_ROTATE_180; > > x += (intel_crtc->config.pipe_src_w - 1); > @@ -2173,6 +2176,8 @@ static int ironlake_update_plane(struct drm_crtc *crtc, > u32 dspcntr; > u32 reg; > int pixel_size; > + unsigned int rotation = drm_rotation_chain(intel_crtc->pipe_rotation, > + intel_crtc->primary_rotation); > > switch (plane) { > case 0: > @@ -2238,7 +2243,7 @@ static int ironlake_update_plane(struct drm_crtc *crtc, > fb->pitches[0]); > linear_offset -= intel_crtc->dspaddr_offset; > > - if (intel_crtc->primary_rotation == BIT(DRM_ROTATE_180)) { > + if (rotation == BIT(DRM_ROTATE_180)) { > dspcntr |= DISPPLANE_ROTATE_180; > > if (!IS_HASWELL(dev) && !IS_BROADWELL(dev)) { > @@ -7468,6 +7473,8 @@ static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base, bool force) > bool visible = base != 0; > > if (force || intel_crtc->cursor_visible != visible) { > + unsigned int rotation = drm_rotation_chain(intel_crtc->pipe_rotation, > + intel_crtc->cursor_rotation); > uint32_t cntl = I915_READ(CURCNTR(pipe)); > if (base) { > cntl &= ~(CURSOR_MODE | MCURSOR_PIPE_SELECT); > @@ -7477,7 +7484,7 @@ static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base, bool force) > cntl &= ~(CURSOR_MODE | MCURSOR_GAMMA_ENABLE); > cntl |= CURSOR_MODE_DISABLE; > } > - if (intel_crtc->cursor_rotation == BIT(DRM_ROTATE_180)) > + if (rotation == BIT(DRM_ROTATE_180)) > cntl |= CURSOR_ROTATE_180; > else > cntl &= ~CURSOR_ROTATE_180; > @@ -7500,6 +7507,8 @@ static void ivb_update_cursor(struct drm_crtc *crtc, u32 base, bool force) > bool visible = base != 0; > > if (force || intel_crtc->cursor_visible != visible) { > + unsigned int rotation = drm_rotation_chain(intel_crtc->pipe_rotation, > + intel_crtc->cursor_rotation); > uint32_t cntl = I915_READ(CURCNTR_IVB(pipe)); > if (base) { > cntl &= ~CURSOR_MODE; > @@ -7512,7 +7521,7 @@ static void ivb_update_cursor(struct drm_crtc *crtc, u32 base, bool force) > cntl |= CURSOR_PIPE_CSC_ENABLE; > cntl &= ~CURSOR_TRICKLE_FEED_DISABLE; > } > - if (intel_crtc->cursor_rotation == BIT(DRM_ROTATE_180)) > + if (rotation == BIT(DRM_ROTATE_180)) > cntl |= CURSOR_ROTATE_180; > else > cntl &= ~CURSOR_ROTATE_180; > @@ -7538,10 +7547,24 @@ static void intel_crtc_update_cursor(struct drm_crtc *crtc, > int y = intel_crtc->cursor_y; > u32 base = 0, pos = 0; > bool visible; > + struct drm_rect r = { > + .x1 = x, > + .x2 = x + intel_crtc->cursor_width, > + .y1 = y, > + .y2 = y + intel_crtc->cursor_height, > + }; > > if (on) > base = intel_crtc->cursor_addr; > > + drm_rect_rotate(&r, > + intel_crtc->config.pipe_src_w, > + intel_crtc->config.pipe_src_h, > + intel_crtc->pipe_rotation); > + > + x = r.x1; > + y = r.y1; > + > if (x >= intel_crtc->config.pipe_src_w) > base = 0; > > @@ -8818,6 +8841,66 @@ free_work: > return ret; > } > > +static int intel_set_primary_plane_rotation(struct intel_crtc *crtc, > + unsigned int rotation) > +{ > + struct drm_device *dev = crtc->base.dev; > + struct drm_i915_private *dev_priv = dev->dev_private; > + unsigned int old_rotation; > + int ret = 0; > + > + old_rotation = crtc->primary_rotation; > + crtc->primary_rotation = rotation; > + > + if (!crtc->active) > + return 0; > + > + rotation = drm_rotation_chain(crtc->pipe_rotation, > + crtc->primary_rotation); > + > + intel_crtc_wait_for_pending_flips(&crtc->base); > + > + /* FBC does not work on some platforms for rotated planes */ > + if (dev_priv->fbc.plane == crtc->plane && > + INTEL_INFO(dev)->gen <= 4 && !IS_G4X(dev) && > + rotation != BIT(DRM_ROTATE_0)) > + intel_disable_fbc(dev); > + > + ret = dev_priv->display.update_plane(&crtc->base, crtc->base.fb, 0, 0); > + if (ret) > + crtc->primary_rotation = old_rotation; > + > + return ret; > +} > + > +static void intel_set_cursor_plane_rotation(struct intel_crtc *crtc, > + unsigned int rotation) > +{ > + crtc->cursor_rotation = rotation; > + > + if (crtc->active) > + intel_crtc_update_cursor(&crtc->base, true, true); > +} > + > +static int intel_update_planes(struct intel_crtc *crtc) > +{ > + struct drm_device *dev = crtc->base.dev; > + struct intel_plane *plane; > + > + list_for_each_entry(plane, &dev->mode_config.plane_list, base.head) { > + int ret; > + > + if (plane->pipe != crtc->pipe) > + continue; > + > + ret = intel_plane_restore(&plane->base); > + if (ret) > + return ret; > + } > + > + return 0; > +} > + > static int intel_crtc_set_property(struct drm_crtc *crtc, > struct drm_property *prop, > uint64_t val) > @@ -8828,27 +8911,51 @@ static int intel_crtc_set_property(struct drm_crtc *crtc, > uint64_t old_val; > int ret = -ENOENT; > > - if (prop == dev_priv->plane_rotation_property) { > + if (prop == dev_priv->rotation_property) { > /* exactly one rotation angle please */ > if (hweight32(val & 0xf) != 1) > return -EINVAL; > > - old_val = intel_crtc->primary_rotation; > - intel_crtc->primary_rotation = val; > + old_val = intel_crtc->pipe_rotation; > + intel_crtc->pipe_rotation = val; > > - if (intel_crtc->active) { > - intel_crtc_wait_for_pending_flips(crtc); > - > - /* FBC does not work on some platforms for rotated planes */ > - if (dev_priv->fbc.plane == intel_crtc->plane && > - INTEL_INFO(dev)->gen <= 4 && !IS_G4X(dev) && > - intel_crtc->primary_rotation != BIT(DRM_ROTATE_0)) > - intel_disable_fbc(dev); > + ret = intel_set_primary_plane_rotation(intel_crtc, > + intel_crtc->primary_rotation); > + if (ret) { > + intel_crtc->pipe_rotation = old_val; > + return ret; > + } > > - ret = dev_priv->display.update_plane(crtc, crtc->fb, 0, 0); > - if (ret) > - intel_crtc->primary_rotation = old_val; > + ret = intel_update_planes(intel_crtc); > + if (ret) { > + intel_crtc->pipe_rotation = old_val; > + > + if (intel_set_primary_plane_rotation(intel_crtc, > + intel_crtc->primary_rotation)) > + DRM_ERROR("failed to restore primary plane rotation\n"); > + if (intel_update_planes(intel_crtc)) > + DRM_ERROR("failed to restore sprite plane rotation\n"); > + return ret; > } > + > + intel_set_cursor_plane_rotation(intel_crtc, > + intel_crtc->cursor_rotation); > + > + return 0; > + } else if (prop == dev_priv->cursor_rotation_property) { > + /* exactly one rotation angle please */ > + if (hweight32(val & 0xf) != 1) > + return -EINVAL; > + > + intel_set_cursor_plane_rotation(intel_crtc, val); > + > + return 0; > + } else if (prop == dev_priv->plane_rotation_property) { > + /* exactly one rotation angle please */ > + if (hweight32(val & 0xf) != 1) > + return -EINVAL; > + > + return intel_set_primary_plane_rotation(intel_crtc, val); > } > > return ret; > @@ -10397,6 +10504,7 @@ static void intel_crtc_init(struct drm_device *dev, int pipe) > intel_crtc->plane = pipe; > intel_crtc->primary_rotation = BIT(DRM_ROTATE_0); > intel_crtc->cursor_rotation = BIT(DRM_ROTATE_0); > + intel_crtc->pipe_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; > @@ -10427,6 +10535,16 @@ static void intel_crtc_init(struct drm_device *dev, int pipe) > drm_object_attach_property(&intel_crtc->base.base, > dev_priv->cursor_rotation_property, > intel_crtc->cursor_rotation); > + > + if (!dev_priv->rotation_property) > + dev_priv->rotation_property = > + drm_mode_create_rotation_property(dev, "rotation", > + BIT(DRM_ROTATE_0) | > + BIT(DRM_ROTATE_180)); > + if (dev_priv->rotation_property) > + drm_object_attach_property(&intel_crtc->base.base, > + dev_priv->rotation_property, > + intel_crtc->pipe_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 4a7f4f1..f967abf 100644 > --- a/drivers/gpu/drm/i915/intel_drv.h > +++ b/drivers/gpu/drm/i915/intel_drv.h > @@ -333,6 +333,7 @@ struct intel_crtc { > 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 */ > + unsigned int pipe_rotation; /* entire pipe */ > > u8 lut_r[256], lut_g[256], lut_b[256]; > /* > diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c > index 5ebeb78..3735815 100644 > --- a/drivers/gpu/drm/i915/intel_pm.c > +++ b/drivers/gpu/drm/i915/intel_pm.c > @@ -463,6 +463,7 @@ void intel_update_fbc(struct drm_device *dev) > struct drm_i915_gem_object *obj; > const struct drm_display_mode *adjusted_mode; > unsigned int max_width, max_height; > + unsigned int rotation; > > if (!HAS_FBC(dev)) { > set_no_fbc_reason(dev_priv, FBC_UNSUPPORTED); > @@ -557,8 +558,11 @@ void intel_update_fbc(struct drm_device *dev) > goto out_disable; > } > > + rotation = drm_rotation_chain(intel_crtc->pipe_rotation, > + intel_crtc->primary_rotation); > + > if (INTEL_INFO(dev)->gen <= 4 && !IS_G4X(dev) && > - intel_crtc->primary_rotation != BIT(DRM_ROTATE_0)) { > + rotation != BIT(DRM_ROTATE_0)) { > if (set_no_fbc_reason(dev_priv, FBC_UNSUPPORTED_MODE)) > DRM_DEBUG_KMS("mode incompatible with compression, " > "disabling\n"); > diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c > index 2936007..e1d593c 100644 > --- a/drivers/gpu/drm/i915/intel_sprite.c > +++ b/drivers/gpu/drm/i915/intel_sprite.c > @@ -53,6 +53,8 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc, > u32 sprctl; > unsigned long sprsurf_offset, linear_offset; > int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0); > + unsigned int rotation = drm_rotation_chain(to_intel_crtc(crtc)->pipe_rotation, > + intel_plane->rotation); > > sprctl = I915_READ(SPCNTR(pipe, plane)); > > @@ -132,7 +134,7 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc, > fb->pitches[0]); > linear_offset -= sprsurf_offset; > > - if (intel_plane->rotation == BIT(DRM_ROTATE_180)) { > + if (rotation == BIT(DRM_ROTATE_180)) { > sprctl |= SP_ROTATE_180; > > x += src_w; > @@ -239,6 +241,8 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, > u32 sprctl, sprscale = 0; > unsigned long sprsurf_offset, linear_offset; > int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0); > + unsigned int rotation = drm_rotation_chain(to_intel_crtc(crtc)->pipe_rotation, > + intel_plane->rotation); > > sprctl = I915_READ(SPRCTL(pipe)); > > @@ -309,7 +313,7 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, > pixel_size, fb->pitches[0]); > linear_offset -= sprsurf_offset; > > - if (intel_plane->rotation == BIT(DRM_ROTATE_180)) { > + if (rotation == BIT(DRM_ROTATE_180)) { > sprctl |= SPRITE_ROTATE_180; > > /* HSW and BDW does this automagically in hardware */ > @@ -435,6 +439,8 @@ ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, > unsigned long dvssurf_offset, linear_offset; > u32 dvscntr, dvsscale; > int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0); > + unsigned int rotation = drm_rotation_chain(to_intel_crtc(crtc)->pipe_rotation, > + intel_plane->rotation); > > dvscntr = I915_READ(DVSCNTR(pipe)); > > @@ -500,7 +506,7 @@ ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, > pixel_size, fb->pitches[0]); > linear_offset -= dvssurf_offset; > > - if (intel_plane->rotation == BIT(DRM_ROTATE_180)) { > + if (rotation == BIT(DRM_ROTATE_180)) { > dvscntr |= DVS_ROTATE_180; > > x += src_w; > @@ -738,6 +744,8 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, > .src_w = src_w, > .src_h = src_h, > }; > + unsigned int rotation = drm_rotation_chain(intel_crtc->pipe_rotation, > + intel_plane->rotation); > > /* Don't modify another pipe's plane */ > if (intel_plane->pipe != intel_crtc->pipe) { > @@ -769,8 +777,11 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, > max_scale = intel_plane->max_downscale << 16; > min_scale = intel_plane->can_scale ? 1 : (1 << 16); > > + drm_rect_rotate(&dst, drm_rect_width(&clip), drm_rect_height(&clip), > + intel_crtc->pipe_rotation); > + > drm_rect_rotate(&src, fb->width << 16, fb->height << 16, > - intel_plane->rotation); > + rotation); > > hscale = drm_rect_calc_hscale_relaxed(&src, &dst, min_scale, max_scale); > BUG_ON(hscale < 0); > @@ -811,7 +822,7 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, > drm_rect_height(&dst) * vscale - drm_rect_height(&src)); > > drm_rect_rotate_inv(&src, fb->width << 16, fb->height << 16, > - intel_plane->rotation); > + rotation); > > /* sanity check to make sure the src viewport wasn't enlarged */ > WARN_ON(src.x1 < (int) src_x || _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/dri-devel