From: Paulo Zanoni <paulo.r.zan...@intel.com>

This ioctl is used to signal the drivers that the screen is rotated,
not to make the drivers rotate the screen.
 - add a driver-specific "rotation_set" function
 - implement Intel's rotation_set by setting the right values to the
   PIPECONF registers.

The idea is that when user-space does rotation, it can call this ioctl
to inform the Kernel that we have a rotation. This feature is needed
by the KVMr feature of VPro.

Signed-off-by: Paulo Zanoni <paulo.r.zan...@intel.com>
---

Hi

We need this feature for the KVMr feature of VPro. I'm not sure how useful this
will be for the non-Intel drivers, so maybe the current approach is not the
best. I'm open to suggestions.

I also have a patch to libdrm that just implements a wrapper for the ioctl
(drmModeCrtcSetRotation) and a patch for xf86-video-intel that callss the libdrm
function whenever needed.

I already have the libdrm and xf86-video-intel patches (they're simple) but I'll
wait until I get some comments on this one before I send the others.

 drivers/gpu/drm/drm_crtc.c           |   28 ++++++++++++++++++++++++++++
 drivers/gpu/drm/drm_drv.c            |    3 ++-
 drivers/gpu/drm/i915/i915_reg.h      |    5 +++++
 drivers/gpu/drm/i915/intel_display.c |   34 ++++++++++++++++++++++++++++++++++
 include/drm/drm.h                    |    2 ++
 include/drm/drm_crtc.h               |    8 +++++++-
 include/drm/drm_mode.h               |   15 +++++++++++++++
 7 files changed, 93 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index f259a25..4a33ea1 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -3125,6 +3125,34 @@ out:
        return ret;
 }
 
+int drm_crtc_rotation_set_ioctl(struct drm_device *dev, void *data,
+                               struct drm_file *file_priv)
+{
+       struct drm_mode_crtc_rotation *rotation = data;
+       struct drm_mode_object *obj;
+       struct drm_crtc *crtc;
+       int ret = 0;
+
+       DRM_DEBUG_KMS("changing rotation to %d\n", rotation->rotation);
+
+       if (!drm_core_check_feature(dev, DRIVER_MODESET))
+               return -EINVAL;
+
+       mutex_lock(&dev->mode_config.mutex);
+       obj = drm_mode_object_find(dev, rotation->crtc_id, 
DRM_MODE_OBJECT_CRTC);
+       if (!obj) {
+               ret = -EINVAL;
+               goto out;
+       }
+       crtc = obj_to_crtc(obj);
+
+       if (crtc->funcs->rotation_set)
+               crtc->funcs->rotation_set(crtc, rotation->rotation);
+out:
+       mutex_unlock(&dev->mode_config.mutex);
+       return ret;
+}
+
 int drm_mode_page_flip_ioctl(struct drm_device *dev,
                             void *data, struct drm_file *file_priv)
 {
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index bc5febe..ba0dac1 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -159,7 +159,8 @@ static struct drm_ioctl_desc drm_ioctls[] = {
        DRM_IOCTL_DEF(DRM_IOCTL_MODE_DIRTYFB, drm_mode_dirtyfb_ioctl, 
DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
        DRM_IOCTL_DEF(DRM_IOCTL_MODE_CREATE_DUMB, drm_mode_create_dumb_ioctl, 
DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
        DRM_IOCTL_DEF(DRM_IOCTL_MODE_MAP_DUMB, drm_mode_mmap_dumb_ioctl, 
DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_IOCTL_MODE_DESTROY_DUMB, drm_mode_destroy_dumb_ioctl, 
DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED)
+       DRM_IOCTL_DEF(DRM_IOCTL_MODE_DESTROY_DUMB, drm_mode_destroy_dumb_ioctl, 
DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+       DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETROTATION, drm_crtc_rotation_set_ioctl, 
DRM_MASTER|DRM_UNLOCKED)
 };
 
 #define DRM_CORE_IOCTL_COUNT   ARRAY_SIZE( drm_ioctls )
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 194d987..3d9d46e 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -2323,6 +2323,11 @@
 #define   PIPECONF_INTERLACE_FIELD_0_ONLY              (7 << 21)
 #define   PIPECONF_INTERLACE_MASK      (7 << 21)
 #define   PIPECONF_CXSR_DOWNCLOCK      (1<<16)
+#define   PIPECONF_ROTATION_MASK       (3 << 14)
+#define   PIPECONF_ROTATION_0          (0 << 14)
+#define   PIPECONF_ROTATION_90         (1 << 14)
+#define   PIPECONF_ROTATION_180                (2 << 14)
+#define   PIPECONF_ROTATION_270                (3 << 14)
 #define   PIPECONF_BPP_MASK    (0x000000e0)
 #define   PIPECONF_BPP_8       (0<<5)
 #define   PIPECONF_BPP_10      (1<<5)
diff --git a/drivers/gpu/drm/i915/intel_display.c 
b/drivers/gpu/drm/i915/intel_display.c
index 55a5b4c..08780f5 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -6317,6 +6317,39 @@ static void intel_crtc_gamma_set(struct drm_crtc *crtc, 
u16 *red, u16 *green,
        intel_crtc_load_lut(crtc);
 }
 
+static void intel_crtc_rotation_set(struct drm_crtc *crtc,
+                                   enum drm_crtc_rotation rotation)
+{
+       struct drm_device *dev = crtc->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+       int reg = PIPECONF(intel_crtc->pipe);
+       u32 val = I915_READ(reg);
+
+       val &= ~PIPECONF_ROTATION_MASK;
+
+       switch (rotation & ~(DRM_CRTC_ROTATION_INV_X |
+                            DRM_CRTC_ROTATION_INV_Y)) {
+       case DRM_CRTC_ROTATION_0:
+               val |= PIPECONF_ROTATION_0;
+               break;
+       case DRM_CRTC_ROTATION_90:
+               val |= PIPECONF_ROTATION_90;
+               break;
+       case DRM_CRTC_ROTATION_180:
+               val |= PIPECONF_ROTATION_180;
+               break;
+       case DRM_CRTC_ROTATION_270:
+               val |= PIPECONF_ROTATION_270;
+               break;
+       default:
+               DRM_ERROR("Invalid rotation: 0x%x\n", rotation);
+               val |= PIPECONF_ROTATION_0;
+       }
+
+       I915_WRITE(reg, val);
+}
+
 /**
  * Get a pipe with a simple mode set on it for doing load-based monitor
  * detection.
@@ -7383,6 +7416,7 @@ static const struct drm_crtc_funcs intel_crtc_funcs = {
        .set_config = drm_crtc_helper_set_config,
        .destroy = intel_crtc_destroy,
        .page_flip = intel_crtc_page_flip,
+       .rotation_set = intel_crtc_rotation_set,
 };
 
 static void intel_crtc_init(struct drm_device *dev, int pipe)
diff --git a/include/drm/drm.h b/include/drm/drm.h
index 49d94ed..f33b09a 100644
--- a/include/drm/drm.h
+++ b/include/drm/drm.h
@@ -719,6 +719,8 @@ struct drm_get_cap {
 #define DRM_IOCTL_MODE_SETPLANE        DRM_IOWR(0xB7, struct 
drm_mode_set_plane)
 #define DRM_IOCTL_MODE_ADDFB2          DRM_IOWR(0xB8, struct drm_mode_fb_cmd2)
 
+#define DRM_IOCTL_MODE_SETROTATION     DRM_IOWR(0xB9, struct 
drm_mode_crtc_rotation)
+
 /**
  * Device specific ioctls should only be in their respective headers
  * The device specific ioctl range is from 0x40 to 0x99.
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 2deb6f9..3515ee7 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -297,7 +297,8 @@ struct drm_plane;
  * @mode_fixup: fixup proposed mode
  * @mode_set: set the desired mode on the CRTC
  * @gamma_set: specify color ramp for CRTC
- * @destroy: deinit and free object.
+ * @destroy: deinit and free object
+ * @rotation_set: specify the CRTC rotation
  *
  * The drm_crtc_funcs structure is the central CRTC management structure
  * in the DRM.  Each CRTC controls one or more connectors (note that the name
@@ -341,6 +342,9 @@ struct drm_crtc_funcs {
        int (*page_flip)(struct drm_crtc *crtc,
                         struct drm_framebuffer *fb,
                         struct drm_pending_vblank_event *event);
+
+       void (*rotation_set)(struct drm_crtc *crtc,
+                            enum drm_crtc_rotation rotation);
 };
 
 /**
@@ -975,6 +979,8 @@ extern int drm_mode_gamma_get_ioctl(struct drm_device *dev,
                                    void *data, struct drm_file *file_priv);
 extern int drm_mode_gamma_set_ioctl(struct drm_device *dev,
                                    void *data, struct drm_file *file_priv);
+extern int drm_crtc_rotation_set_ioctl(struct drm_device *dev,
+                                   void *data, struct drm_file *file_priv);
 extern u8 *drm_find_cea_extension(struct edid *edid);
 extern bool drm_detect_hdmi_monitor(struct edid *edid);
 extern bool drm_detect_monitor_audio(struct edid *edid);
diff --git a/include/drm/drm_mode.h b/include/drm/drm_mode.h
index 2a2acda..58200e8 100644
--- a/include/drm/drm_mode.h
+++ b/include/drm/drm_mode.h
@@ -379,6 +379,21 @@ struct drm_mode_crtc_lut {
        __u64 blue;
 };
 
+/* Matches randr.h for convenience */
+enum drm_crtc_rotation {
+       DRM_CRTC_ROTATION_0     = 1,
+       DRM_CRTC_ROTATION_90    = 2,
+       DRM_CRTC_ROTATION_180   = 4,
+       DRM_CRTC_ROTATION_270   = 8,
+       DRM_CRTC_ROTATION_INV_X = 16,
+       DRM_CRTC_ROTATION_INV_Y = 32
+};
+
+struct drm_mode_crtc_rotation {
+       __u32 crtc_id;
+       enum drm_crtc_rotation rotation;
+};
+
 #define DRM_MODE_PAGE_FLIP_EVENT 0x01
 #define DRM_MODE_PAGE_FLIP_FLAGS DRM_MODE_PAGE_FLIP_EVENT
 
-- 
1.7.7.3

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

Reply via email to