From d6baf99228e6ce78f0a7e86feee48c34309e9b1c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@linux.intel.com>
Date: Sun, 29 Nov 2015 17:56:03 +0200
Subject: [PATCH] drm/fb-helper: Inherit rotation wip
---
drivers/gpu/drm/drm_fb_helper.c | 48 ++++++++++++++++++++++++++++++++++--
drivers/gpu/drm/i915/intel_display.c | 30 +++++++++++++++++++++-
drivers/gpu/drm/i915/intel_drv.h | 1 +
include/drm/drm_fb_helper.h | 2 ++
4 files changed, 78 insertions(+), 3 deletions(-)
@@ -159,6 +159,8 @@ int drm_fb_helper_add_one_connector(struct drm_fb_helper *fb_helper, struct drm_
{
struct drm_fb_helper_connector **temp;
struct drm_fb_helper_connector *fb_helper_connector;
+ struct drm_crtc *crtc = connector->encoder ?
+ connector->encoder->crtc : NULL;
if (!drm_fbdev_emulation)
return 0;
@@ -180,6 +182,11 @@ int drm_fb_helper_add_one_connector(struct drm_fb_helper *fb_helper, struct drm_
drm_connector_reference(connector);
fb_helper_connector->connector = connector;
+ if (crtc && crtc->primary->state)
+ fb_helper_connector->rotation = crtc->primary->state->rotation;
+ if (!fb_helper_connector->rotation)
+ fb_helper_connector->rotation = DRM_ROTATE_0;
+
fb_helper->connector_info[fb_helper->connector_count++] = fb_helper_connector;
return 0;
}
@@ -333,6 +340,35 @@ int drm_fb_helper_debug_leave(struct fb_info *info)
}
EXPORT_SYMBOL(drm_fb_helper_debug_leave);
+static int fbdev_plane_index(struct drm_fb_helper *fb_helper,
+ struct drm_plane *plane)
+{
+ int i;
+
+ if (plane->type != DRM_PLANE_TYPE_PRIMARY)
+ return -ENODEV;
+
+ for (i = 0; i < fb_helper->crtc_count; i++) {
+ struct drm_crtc *crtc = fb_helper->crtc_info[i].mode_set.crtc;
+
+ if (crtc && crtc->primary == plane)
+ return i;
+ }
+
+ return -ENODEV;
+}
+
+static unsigned int fbdev_plane_rotation(struct drm_fb_helper *fb_helper,
+ struct drm_plane *plane)
+{
+ int i = fbdev_plane_index(fb_helper, plane);
+
+ if (i < 0)
+ return DRM_ROTATE_0;
+ else
+ return fb_helper->crtc_info[i].rotation;
+}
+
static int restore_fbdev_mode_atomic(struct drm_fb_helper *fb_helper)
{
struct drm_device *dev = fb_helper->dev;
@@ -357,7 +393,7 @@ static int restore_fbdev_mode_atomic(struct drm_fb_helper *fb_helper)
goto fail;
}
- plane_state->rotation = DRM_ROTATE_0;
+ plane_state->rotation = fbdev_plane_rotation(fb_helper, plane);
plane->old_fb = plane->fb;
plane_mask |= 1 << drm_plane_index(plane);
@@ -415,7 +451,7 @@ static int restore_fbdev_mode(struct drm_fb_helper *fb_helper)
if (plane->rotation_property)
drm_mode_plane_set_obj_prop(plane,
plane->rotation_property,
- DRM_ROTATE_0);
+ fbdev_plane_rotation(fb_helper, plane));
}
for (i = 0; i < fb_helper->crtc_count; i++) {
@@ -760,6 +796,7 @@ int drm_fb_helper_init(struct drm_device *dev,
if (!fb_helper->crtc_info[i].mode_set.connectors)
goto out_free;
fb_helper->crtc_info[i].mode_set.num_connectors = 0;
+ fb_helper->crtc_info[i].rotation = DRM_ROTATE_0;
}
i = 0;
@@ -2090,8 +2127,14 @@ static int drm_pick_crtcs(struct drm_fb_helper *fb_helper,
if (!drm_mode_equal(modes[o], modes[n]))
continue;
+
+ if (crtc->rotation &&
+ crtc->rotation != fb_helper_conn->rotation)
+ continue;
}
+ crtc->rotation = fb_helper_conn->rotation;
+
crtcs[n] = crtc;
memcpy(crtcs, best_crtcs, n * sizeof(struct drm_fb_helper_crtc *));
score = my_score + drm_pick_crtcs(fb_helper, crtcs, modes, n + 1,
@@ -2182,6 +2225,7 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper,
fb_crtc->desired_mode = mode;
fb_crtc->x = offset->x;
fb_crtc->y = offset->y;
+ fb_crtc->rotation = fb_helper->connector_info[i]->rotation;
modeset->mode = drm_mode_duplicate(dev,
fb_crtc->desired_mode);
drm_connector_reference(connector);
@@ -2757,6 +2757,8 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,
plane_state->crtc_w = fb->width;
plane_state->crtc_h = fb->height;
+ plane_state->rotation = plane_config->rotation;
+
intel_state->base.src = drm_plane_state_src(plane_state);
intel_state->base.dst = drm_plane_state_dest(plane_state);
@@ -7407,6 +7409,9 @@ i9xx_get_initial_plane_config(struct intel_crtc *crtc,
plane_config->tiling = I915_TILING_X;
fb->modifier = I915_FORMAT_MOD_X_TILED;
}
+
+ if (val & DISPPLANE_ROTATE_180)
+ plane_config->rotation = DRM_ROTATE_180;
}
pixel_format = val & DISPPLANE_PIXFORMAT_MASK;
@@ -8459,6 +8464,24 @@ skylake_get_initial_plane_config(struct intel_crtc *crtc,
goto error;
}
+ /*
+ * DRM_ROTATE_ is counter clockwise to stay compatible with Xrandr
+ * while i915 HW rotation is clockwise, thats why this swapping.
+ */
+ switch (val & PLANE_CTL_ROTATE_MASK) {
+ case PLANE_CTL_ROTATE_0:
+ break;
+ case PLANE_CTL_ROTATE_90:
+ plane_config->rotation = DRM_ROTATE_270;
+ break;
+ case PLANE_CTL_ROTATE_180:
+ plane_config->rotation = DRM_ROTATE_180;
+ break;
+ case PLANE_CTL_ROTATE_270:
+ plane_config->rotation = DRM_ROTATE_90;
+ break;
+ }
+
base = I915_READ(PLANE_SURF(pipe, 0)) & 0xfffff000;
plane_config->base = base;
@@ -8548,6 +8571,9 @@ ironlake_get_initial_plane_config(struct intel_crtc *crtc,
plane_config->tiling = I915_TILING_X;
fb->modifier = I915_FORMAT_MOD_X_TILED;
}
+
+ if (val & DISPPLANE_ROTATE_180)
+ plane_config->rotation = DRM_ROTATE_180;
}
pixel_format = val & DISPPLANE_PIXFORMAT_MASK;
@@ -15045,7 +15071,9 @@ int intel_modeset_init(struct drm_device *dev)
drm_modeset_unlock_all(dev);
for_each_intel_crtc(dev, crtc) {
- struct intel_initial_plane_config plane_config = {};
+ struct intel_initial_plane_config plane_config = {
+ .rotation = DRM_ROTATE_0
+ };
if (!crtc->active)
continue;
@@ -421,6 +421,7 @@ struct intel_initial_plane_config {
unsigned int tiling;
int size;
u32 base;
+ uint8_t rotation;
};
#define SKL_MIN_SRC_W 8
@@ -48,6 +48,7 @@ struct drm_fb_helper_crtc {
struct drm_mode_set mode_set;
struct drm_display_mode *desired_mode;
int x, y;
+ uint8_t rotation;
};
/**
@@ -159,6 +160,7 @@ struct drm_fb_helper_funcs {
struct drm_fb_helper_connector {
struct drm_connector *connector;
+ uint8_t rotation;
};
/**
--
2.9.3