On Fri, Jan 24, 2014 at 07:18:43PM +0530, sagar.a.kam...@intel.com wrote:
> From: Sagar Kamble <sagar.a.kam...@intel.com>
> 
> This patch enables 180 degree rotation for primary and sprite planes
> through sysfs interface.

NAK.

See here for the right apporach:
http://lists.freedesktop.org/archives/intel-gfx/2013-September/033951.html

> 
> Signed-off-by: Uma Shankar <uma.shan...@intel.com>
> Signed-off-by: Sagar Kamble <sagar.a.kam...@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_reg.h      |   1 +
>  drivers/gpu/drm/i915/i915_sysfs.c    | 124 
> +++++++++++++++++++++++++++++++++++
>  drivers/gpu/drm/i915/intel_display.c |  28 +++++++-
>  drivers/gpu/drm/i915/intel_drv.h     |   8 +++
>  drivers/gpu/drm/i915/intel_sprite.c  |  38 +++++++++--
>  5 files changed, 191 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index 5d06ad6..92fa3d2 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -3555,6 +3555,7 @@
>  #define   DISPPLANE_STEREO_POLARITY_SECOND   (1<<18)
>  #define   DISPPLANE_TRICKLE_FEED_DISABLE     (1<<14) /* Ironlake */
>  #define   DISPPLANE_TILED                    (1<<10)
> +#define   DISPPLANE_180_ROTATION_ENABLE              (1<<15)
>  #define _DSPAADDR            (dev_priv->info->display_mmio_offset + 0x70184)
>  #define _DSPASTRIDE          (dev_priv->info->display_mmio_offset + 0x70188)
>  #define _DSPAPOS             (dev_priv->info->display_mmio_offset + 0x7018C) 
> /* reserved */
> diff --git a/drivers/gpu/drm/i915/i915_sysfs.c 
> b/drivers/gpu/drm/i915/i915_sysfs.c
> index 33bcae3..12a214c 100644
> --- a/drivers/gpu/drm/i915/i915_sysfs.c
> +++ b/drivers/gpu/drm/i915/i915_sysfs.c
> @@ -127,6 +127,122 @@ static struct attribute_group rc6_attr_group = {
>  };
>  #endif
>  
> +int i915_set_180_rotation(struct drm_device *dev,
> +                             struct i915_180_rotation *rotation)
> +{
> +     struct drm_mode_object *obj;
> +     struct drm_crtc *crtc;
> +     struct intel_crtc *intel_crtc;
> +     struct drm_plane *plane;
> +     struct intel_plane *intel_plane;
> +     struct drm_i915_private *dev_priv = dev->dev_private;
> +     int ret = 0;
> +
> +     if (rotation->obj_type == DRM_MODE_OBJECT_PLANE) {
> +             obj = drm_mode_object_find(dev, rotation->obj_id,
> +                                             DRM_MODE_OBJECT_PLANE);
> +             if (!obj) {
> +                     DRM_DEBUG_DRIVER("Unknown PLANE ID %d\n",
> +                                     rotation->obj_id);
> +                     return -EINVAL;
> +             }
> +
> +             plane = obj_to_plane(obj);
> +             intel_plane = to_intel_plane(plane);
> +             DRM_DEBUG_DRIVER("[SPRITE:%d] rotation set\n",
> +                                             intel_plane->base.base.id);
> +             intel_plane->rotate180 = (rotation->rotate & 0x1) ?
> +                                                     true : false;
> +             ret = 1;
> +     } else if (rotation->obj_type == DRM_MODE_OBJECT_CRTC) {
> +             obj = drm_mode_object_find(dev, rotation->obj_id,
> +                                             DRM_MODE_OBJECT_CRTC);
> +             if (!obj) {
> +                     DRM_DEBUG_DRIVER("Unknown CRTC ID %d\n",
> +                                             rotation->obj_id);
> +                     return -EINVAL;
> +             }
> +
> +             crtc = obj_to_crtc(obj);
> +             if (!crtc->enabled) {
> +                     DRM_DEBUG_DRIVER("[CRTC:%d] not active\n", 
> crtc->base.id);
> +                     return ret;
> +             }
> +             DRM_DEBUG_DRIVER("[CRTC:%d] rotation set\n", crtc->base.id);
> +             intel_crtc = to_intel_crtc(crtc);
> +             intel_crtc->rotate180 = (rotation->rotate & 0x1) ?
> +                                                     true : false;
> +             dev_priv->display.update_plane(crtc, crtc->fb, 0, 0);
> +             ret = 1;
> +     }
> +
> +     return ret;
> +}
> +
> +static ssize_t
> +i915_180_rotation_store(struct device *kdev,
> +                          struct device_attribute *attr,
> +                          const char *buf, size_t count)
> +{
> +     struct drm_minor *minor = dev_to_drm_minor(kdev);
> +     struct drm_device *dev = minor->dev;
> +     struct i915_180_rotation rotation;
> +     char buf1[30], id[11], type[11], val[2], format[18];
> +     int len = 0, ret, no_of_tokens;
> +     u32 rotate;
> +
> +     if (count == 0)
> +             return -EINVAL;
> +
> +     /* Reset the string */
> +     memset(buf1, 0, 30);
> +     if (count > 0) {
> +             if (count > sizeof(buf1) - 1)
> +                     return -EINVAL;
> +             memcpy(buf1, buf, count);
> +     }
> +
> +     scnprintf(format, sizeof(format), "%%%zus %%%zus %%%zus",
> +                     sizeof(id), sizeof(type), sizeof(val));
> +
> +     no_of_tokens = sscanf(buf1, format, id, type, val);
> +     if (no_of_tokens < 3)
> +             return len;
> +
> +     ret = kstrtou32(id, 0, &(rotation.obj_id));
> +     if (ret)
> +             return ret;
> +
> +     ret = kstrtou32(type, 0, &(rotation.obj_type));
> +     if (ret)
> +             return ret;
> +
> +     ret = kstrtou32(val, 0, &rotate);
> +     if (ret)
> +             return ret;
> +
> +     rotation.rotate = rotate ? true : false;
> +
> +     if (!i915_set_180_rotation(dev, &rotation))
> +             return -EINVAL;
> +
> +     return count;
> +}
> +
> +static DEVICE_ATTR(i915_180_rotation, S_IWUSR,
> +                             NULL,
> +                             i915_180_rotation_store);
> +
> +static struct attribute *display_attrs[] = {
> +     &dev_attr_i915_180_rotation.attr,
> +     NULL
> +};
> +
> +static struct attribute_group display_attr_group = {
> +     .name = "display",
> +     .attrs =  display_attrs
> +};
> +
>  static int l3_access_valid(struct drm_device *dev, loff_t offset)
>  {
>       if (!HAS_L3_DPF(dev))
> @@ -568,6 +684,13 @@ void i915_setup_sysfs(struct drm_device *dev)
>                       DRM_ERROR("RC6 residency sysfs setup failed\n");
>       }
>  #endif
> +     if (INTEL_INFO(dev)->gen >= 6) {
> +             ret = sysfs_create_group(&dev->primary->kdev->kobj,
> +                                     &display_attr_group);
> +             if (ret)
> +                     DRM_ERROR("Display sysfs setup failed\n");
> +     }
> +
>       if (HAS_L3_DPF(dev)) {
>               ret = device_create_bin_file(dev->primary->kdev, &dpf_attrs);
>               if (ret)
> @@ -607,4 +730,5 @@ void i915_teardown_sysfs(struct drm_device *dev)
>  #ifdef CONFIG_PM
>       sysfs_unmerge_group(&dev->primary->kdev->kobj, &rc6_attr_group);
>  #endif
> +     sysfs_unmerge_group(&dev->primary->kdev->kobj, &display_attr_group);
>  }
> diff --git a/drivers/gpu/drm/i915/intel_display.c 
> b/drivers/gpu/drm/i915/intel_display.c
> index ec96002..5a1dc0b 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -52,7 +52,6 @@ static void ironlake_pch_clock_get(struct intel_crtc *crtc,
>  static int intel_set_mode(struct drm_crtc *crtc, struct drm_display_mode 
> *mode,
>                         int x, int y, struct drm_framebuffer *old_fb);
>  
> -
>  typedef struct {
>       int     min, max;
>  } intel_range_t;
> @@ -2034,7 +2033,10 @@ static int i9xx_update_plane(struct drm_crtc *crtc, 
> struct drm_framebuffer *fb,
>       struct intel_framebuffer *intel_fb;
>       struct drm_i915_gem_object *obj;
>       int plane = intel_crtc->plane;
> +     int pipe = intel_crtc->pipe;
>       unsigned long linear_offset;
> +     bool rotate = false;
> +     int pixel_size = 0;
>       u32 dspcntr;
>       u32 reg;
>  
> @@ -2047,6 +2049,7 @@ static int i9xx_update_plane(struct drm_crtc *crtc, 
> struct drm_framebuffer *fb,
>               return -EINVAL;
>       }
>  
> +     pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
>       intel_fb = to_intel_framebuffer(fb);
>       obj = intel_fb->obj;
>  
> @@ -2085,6 +2088,9 @@ static int i9xx_update_plane(struct drm_crtc *crtc, 
> struct drm_framebuffer *fb,
>               BUG();
>       }
>  
> +     if (intel_crtc->rotate180 && (pipe == 0))
> +             rotate = true;
> +
>       if (INTEL_INFO(dev)->gen >= 4) {
>               if (obj->tiling_mode != I915_TILING_NONE)
>                       dspcntr |= DISPPLANE_TILED;
> @@ -2095,6 +2101,11 @@ static int i9xx_update_plane(struct drm_crtc *crtc, 
> struct drm_framebuffer *fb,
>       if (IS_G4X(dev))
>               dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE;
>  
> +     if (rotate)
> +             dspcntr |= DISPPLANE_180_ROTATION_ENABLE;
> +     else
> +             dspcntr &= ~DISPPLANE_180_ROTATION_ENABLE;
> +
>       I915_WRITE(reg, dspcntr);
>  
>       linear_offset = y * fb->pitches[0] + x * (fb->bits_per_pixel / 8);
> @@ -2116,8 +2127,18 @@ static int i9xx_update_plane(struct drm_crtc *crtc, 
> struct drm_framebuffer *fb,
>       if (INTEL_INFO(dev)->gen >= 4) {
>               I915_MODIFY_DISPBASE(DSPSURF(plane),
>                                    i915_gem_obj_ggtt_offset(obj) + 
> intel_crtc->dspaddr_offset);
> -             I915_WRITE(DSPTILEOFF(plane), (y << 16) | x);
> -             I915_WRITE(DSPLINOFF(plane), linear_offset);
> +             if (rotate) {
> +                     I915_WRITE(DSPTILEOFF(plane),
> +                                (((y + fb->height - 1) << 16) |
> +                                 (x + fb->width - 1)));
> +                     I915_WRITE(DSPLINOFF(plane),
> +                                linear_offset +
> +                                (fb->height - 1) * fb->pitches[0] +
> +                                fb->width * pixel_size);
> +             } else {
> +                     I915_WRITE(DSPTILEOFF(plane), (y << 16) | x);
> +                     I915_WRITE(DSPLINOFF(plane), linear_offset);
> +             }
>       } else
>               I915_WRITE(DSPADDR(plane), i915_gem_obj_ggtt_offset(obj) + 
> linear_offset);
>       POSTING_READ(reg);
> @@ -10317,6 +10338,7 @@ static void intel_crtc_init(struct drm_device *dev, 
> int pipe)
>       dev_priv->plane_to_crtc_mapping[intel_crtc->plane] = &intel_crtc->base;
>       dev_priv->pipe_to_crtc_mapping[intel_crtc->pipe] = &intel_crtc->base;
>  
> +     intel_crtc->rotate180 = false;
>       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 7b3c209..1c199fd 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -327,10 +327,17 @@ struct intel_pipe_wm {
>       bool fbc_wm_enabled;
>  };
>  
> +struct i915_180_rotation {
> +     u32 obj_id;
> +     u32 obj_type;
> +     bool rotate;
> +};
> +
>  struct intel_crtc {
>       struct drm_crtc base;
>       enum pipe pipe;
>       enum plane plane;
> +     bool rotate180;
>       u8 lut_r[256], lut_g[256], lut_b[256];
>       /*
>        * Whether the crtc and the connected output pipeline is active. Implies
> @@ -392,6 +399,7 @@ struct intel_plane {
>       struct drm_i915_gem_object *obj;
>       bool can_scale;
>       int max_downscale;
> +     bool rotate180;
>       u32 lut_r[1024], lut_g[1024], lut_b[1024];
>       int crtc_x, crtc_y;
>       unsigned int crtc_w, crtc_h;
> diff --git a/drivers/gpu/drm/i915/intel_sprite.c 
> b/drivers/gpu/drm/i915/intel_sprite.c
> index ed9fa7c..f3224fa 100644
> --- a/drivers/gpu/drm/i915/intel_sprite.c
> +++ b/drivers/gpu/drm/i915/intel_sprite.c
> @@ -51,6 +51,7 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_crtc 
> *crtc,
>       int pipe = intel_plane->pipe;
>       int plane = intel_plane->plane;
>       u32 sprctl;
> +     bool rotate = false;
>       unsigned long sprsurf_offset, linear_offset;
>       int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
>  
> @@ -118,6 +119,9 @@ vlv_update_plane(struct drm_plane *dplane, struct 
> drm_crtc *crtc,
>       intel_update_sprite_watermarks(dplane, crtc, src_w, pixel_size, true,
>                                      src_w != crtc_w || src_h != crtc_h);
>  
> +     if (intel_plane->rotate180  && (pipe == 0))
> +             rotate = true;
> +
>       /* Sizes are 0 based */
>       src_w--;
>       src_h--;
> @@ -132,14 +136,37 @@ vlv_update_plane(struct drm_plane *dplane, struct 
> drm_crtc *crtc,
>       linear_offset -= sprsurf_offset;
>  
>       I915_WRITE(SPSTRIDE(pipe, plane), fb->pitches[0]);
> -     I915_WRITE(SPPOS(pipe, plane), (crtc_y << 16) | crtc_x);
> -
> -     if (obj->tiling_mode != I915_TILING_NONE)
> -             I915_WRITE(SPTILEOFF(pipe, plane), (y << 16) | x);
> +     if (rotate)
> +             I915_WRITE(SPPOS(pipe, plane),
> +                     ((crtc->hwmode.vdisplay - (crtc_y + crtc_h + 1))
> +                     << 16) |
> +                     (crtc->hwmode.hdisplay - (crtc_x + crtc_w + 1)));
>       else
> -             I915_WRITE(SPLINOFF(pipe, plane), linear_offset);
> +             I915_WRITE(SPPOS(pipe, plane), (crtc_y << 16) | crtc_x);
>  
> +     if (obj->tiling_mode != I915_TILING_NONE) {
> +             if (rotate)
> +                     I915_WRITE(SPTILEOFF(pipe, plane),
> +                             ((y + crtc_h) << 16) | (x + crtc_w));
> +             else
> +                     I915_WRITE(SPTILEOFF(pipe, plane), (y << 16) | x);
> +     } else {
> +             if (rotate) {
> +                     int rot_linoff = linear_offset +
> +                                      crtc_h * fb->pitches[0] +
> +                                      (crtc_w + 1) * pixel_size;
> +                     I915_WRITE(SPLINOFF(pipe, plane), rot_linoff);
> +
> +             } else
> +                     I915_WRITE(SPLINOFF(pipe, plane), linear_offset);
> +     }
>       I915_WRITE(SPSIZE(pipe, plane), (crtc_h << 16) | crtc_w);
> +
> +     if (rotate)
> +             sprctl |= DISPPLANE_180_ROTATION_ENABLE;
> +     else
> +             sprctl &= ~DISPPLANE_180_ROTATION_ENABLE;
> +
>       I915_WRITE(SPCNTR(pipe, plane), sprctl);
>       I915_MODIFY_DISPBASE(SPSURF(pipe, plane), i915_gem_obj_ggtt_offset(obj) 
> +
>                            sprsurf_offset);
> @@ -1141,6 +1168,7 @@ intel_plane_init(struct drm_device *dev, enum pipe 
> pipe, int plane)
>  
>       intel_plane->pipe = pipe;
>       intel_plane->plane = plane;
> +     intel_plane->rotate180 = false;
>       possible_crtcs = (1 << pipe);
>       ret = drm_plane_init(dev, &intel_plane->base, possible_crtcs,
>                            &intel_plane_funcs,
> -- 
> 1.8.5
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to