[RFC] drm: implement DRM_IOCTL_MODE_SETROTATION
przanoni at gmail.com
przanoni at gmail.com
Thu Jan 5 08:16:23 PST 2012
From: Paulo Zanoni <paulo.r.zanoni at 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.zanoni at 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
More information about the dri-devel
mailing list