From patchwork Fri Jan 24 13:48:43 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: sagar.a.kamble@intel.com X-Patchwork-Id: 3534751 Return-Path: X-Original-To: patchwork-intel-gfx@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 204099F2ED for ; Fri, 24 Jan 2014 13:48:09 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 26B1A2010F for ; Fri, 24 Jan 2014 13:48:04 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id A3D9C20131 for ; Fri, 24 Jan 2014 13:47:55 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 59F0AFB027; Fri, 24 Jan 2014 05:47:52 -0800 (PST) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from mga14.intel.com (mga14.intel.com [143.182.124.37]) by gabe.freedesktop.org (Postfix) with ESMTP id 1EC55FB025 for ; Fri, 24 Jan 2014 05:47:47 -0800 (PST) Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by azsmga102.ch.intel.com with ESMTP; 24 Jan 2014 05:47:46 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="4.95,712,1384329600"; d="scan'208";a="464131030" Received: from sagar-desktop.iind.intel.com ([10.223.82.31]) by fmsmga001.fm.intel.com with ESMTP; 24 Jan 2014 05:47:44 -0800 From: sagar.a.kamble@intel.com To: intel-gfx@lists.freedesktop.org Date: Fri, 24 Jan 2014 19:18:43 +0530 Message-Id: <1390571323-4885-1-git-send-email-sagar.a.kamble@intel.com> X-Mailer: git-send-email 1.8.5 Cc: Uma Shankar , Sagar Kamble Subject: [Intel-gfx] [PATCH 1/1] drm/i915: Enabling plane rotation control through sysfs X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: intel-gfx-bounces@lists.freedesktop.org Errors-To: intel-gfx-bounces@lists.freedesktop.org X-Spam-Status: No, score=-4.8 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Sagar Kamble This patch enables 180 degree rotation for primary and sprite planes through sysfs interface. Signed-off-by: Uma Shankar Signed-off-by: Sagar Kamble --- 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,