d2a00ca
From d769f1194c934ed4ff7ce6bfc502ba485d461c12 Mon Sep 17 00:00:00 2001
d2a00ca
From: Hans de Goede <hdegoede@redhat.com>
d2a00ca
Date: Sat, 20 Jan 2018 12:20:29 +0100
d2a00ca
Subject: [PATCH 5/6] drm: Reset primary plane rotation to DRM_MODE_ROTATE_0
d2a00ca
d2a00ca
On devices where the (LCD) panel is mounted upside-down in the case
d2a00ca
the kernel's drm_fb_helper code may have set up rotation on the primary
d2a00ca
plane to make the text-console (and other fbdev using apps) show the right
d2a00ca
way up.
d2a00ca
d2a00ca
We inherit this rotation from the text-mode and since we do our own rotation
d2a00ca
where necessary we end up rotating twice and showing the boot-splash
d2a00ca
upside-down again.
d2a00ca
d2a00ca
Dealing with hardware rotation may require using a specific framebuffer
d2a00ca
tiling which we do not support, so we should just disable the hardware
d2a00ca
rotation and keep using our own software rotation.
d2a00ca
d2a00ca
This commit adds code to find the primary plane and its rotation property
d2a00ca
and if it is not DRM_MODE_ROTATE_0 then sets it to DRM_MODE_ROTATE_0. fixing
d2a00ca
the double rotation issue.
d2a00ca
d2a00ca
https://bugs.freedesktop.org/show_bug.cgi?id=104714
d2a00ca
---
d2a00ca
 src/plugins/renderers/drm/plugin.c | 86 ++++++++++++++++++++++++++++++
d2a00ca
 1 file changed, 86 insertions(+)
d2a00ca
d2a00ca
diff --git a/src/plugins/renderers/drm/plugin.c b/src/plugins/renderers/drm/plugin.c
d2a00ca
index f495854..fb79aa6 100644
d2a00ca
--- a/src/plugins/renderers/drm/plugin.c
d2a00ca
+++ b/src/plugins/renderers/drm/plugin.c
d2a00ca
@@ -43,6 +43,7 @@
d2a00ca
 #include <unistd.h>
d2a00ca
 
d2a00ca
 #include <drm.h>
d2a00ca
+#include <drm_mode.h>
d2a00ca
 #include <xf86drm.h>
d2a00ca
 #include <xf86drmMode.h>
d2a00ca
 
d2a00ca
@@ -62,6 +63,11 @@
d2a00ca
 
d2a00ca
 #define BYTES_PER_PIXEL (4)
d2a00ca
 
d2a00ca
+/* For builds with libdrm < 2.4.89 */
d2a00ca
+#ifndef DRM_MODE_ROTATE_0
d2a00ca
+#define DRM_MODE_ROTATE_0 (1<<0)
d2a00ca
+#endif
d2a00ca
+
d2a00ca
 struct _ply_renderer_head
d2a00ca
 {
d2a00ca
         ply_renderer_backend_t *backend;
d2a00ca
@@ -499,6 +505,85 @@ ply_renderer_head_free (ply_renderer_head_t *head)
d2a00ca
         free (head);
d2a00ca
 }
d2a00ca
 
d2a00ca
+static void
d2a00ca
+ply_renderer_head_clear_plane_rotation (ply_renderer_backend_t *backend,
d2a00ca
+                                        ply_renderer_head_t    *head)
d2a00ca
+{
d2a00ca
+        drmModeObjectPropertiesPtr plane_props;
d2a00ca
+        drmModePlaneResPtr plane_resources;
d2a00ca
+        drmModePropertyPtr prop;
d2a00ca
+        drmModePlanePtr plane;
d2a00ca
+        uint64_t rotation;
d2a00ca
+        uint32_t i, j;
d2a00ca
+        int rotation_prop_id = -1;
d2a00ca
+        int primary_id = -1;
d2a00ca
+        int err;
d2a00ca
+
d2a00ca
+        err = drmSetClientCap (backend->device_fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
d2a00ca
+        if (err)
d2a00ca
+                return;
d2a00ca
+
d2a00ca
+        plane_resources = drmModeGetPlaneResources (backend->device_fd);
d2a00ca
+        if (!plane_resources)
d2a00ca
+                return;
d2a00ca
+
d2a00ca
+        for (i = 0; i < plane_resources->count_planes; i++) {
d2a00ca
+                plane = drmModeGetPlane (backend->device_fd,
d2a00ca
+                                         plane_resources->planes[i]);
d2a00ca
+                if (!plane)
d2a00ca
+                        continue;
d2a00ca
+
d2a00ca
+                if (plane->crtc_id != head->controller_id) {
d2a00ca
+                        drmModeFreePlane (plane);
d2a00ca
+                        continue;
d2a00ca
+                }
d2a00ca
+
d2a00ca
+                plane_props = drmModeObjectGetProperties (backend->device_fd,
d2a00ca
+                                                          plane->plane_id,
d2a00ca
+                                                          DRM_MODE_OBJECT_PLANE);
d2a00ca
+
d2a00ca
+                for (j = 0; plane_props && (j < plane_props->count_props); j++) {
d2a00ca
+                        prop = drmModeGetProperty (backend->device_fd,
d2a00ca
+                                                   plane_props->props[j]);
d2a00ca
+                        if (!prop)
d2a00ca
+                                continue;
d2a00ca
+
d2a00ca
+                        if (strcmp (prop->name, "type") == 0 &&
d2a00ca
+                            plane_props->prop_values[j] == DRM_PLANE_TYPE_PRIMARY) {
d2a00ca
+                                primary_id = plane->plane_id;
d2a00ca
+                        }
d2a00ca
+
d2a00ca
+                        if (strcmp (prop->name, "rotation") == 0) {
d2a00ca
+                                rotation_prop_id = plane_props->props[j];
d2a00ca
+                                rotation = plane_props->prop_values[j];
d2a00ca
+                        }
d2a00ca
+
d2a00ca
+                        drmModeFreeProperty (prop);
d2a00ca
+                }
d2a00ca
+
d2a00ca
+                drmModeFreeObjectProperties (plane_props);
d2a00ca
+                drmModeFreePlane (plane);
d2a00ca
+
d2a00ca
+                if (primary_id != -1)
d2a00ca
+                        break;
d2a00ca
+
d2a00ca
+                /* Not primary -> clear any found rotation property */
d2a00ca
+                rotation_prop_id = -1;
d2a00ca
+        }
d2a00ca
+
d2a00ca
+        if (primary_id != -1 && rotation_prop_id != -1 && rotation != DRM_MODE_ROTATE_0) {
d2a00ca
+                err = drmModeObjectSetProperty (backend->device_fd,
d2a00ca
+                                                primary_id,
d2a00ca
+                                                DRM_MODE_OBJECT_PLANE,
d2a00ca
+                                                rotation_prop_id,
d2a00ca
+                                                DRM_MODE_ROTATE_0);
d2a00ca
+                ply_trace ("Cleared rotation on primary plane %d result %d",
d2a00ca
+                           primary_id, err);
d2a00ca
+        }
d2a00ca
+
d2a00ca
+        drmModeFreePlaneResources (plane_resources);
d2a00ca
+}
d2a00ca
+
d2a00ca
 static bool
d2a00ca
 ply_renderer_head_set_scan_out_buffer (ply_renderer_backend_t *backend,
d2a00ca
                                        ply_renderer_head_t    *head,
d2a00ca
@@ -525,6 +610,7 @@ ply_renderer_head_set_scan_out_buffer (ply_renderer_backend_t *backend,
d2a00ca
                 return false;
d2a00ca
         }
d2a00ca
 
d2a00ca
+        ply_renderer_head_clear_plane_rotation (backend, head);
d2a00ca
         return true;
d2a00ca
 }
d2a00ca
 
d2a00ca
-- 
d2a00ca
2.17.0
d2a00ca