frecon: disable non main CRTs and all but primary planes at mode switch

Frecon should only display on main CRT (built-in LCD on laptops, first display
on desktops). Also, disable all other planes and overlays, so if there is
anything left over from Chrome, like cursor or video overlay we do not
want it to obscure console.

BUG=chromium:482738,406121
TEST=with 2nd monitor connected switch to frecon (VT2)

Change-Id: I65c74b8e8dda1be65dbd09a6d18e876a18e80fd2
Signed-off-by: Dominik Behr <dbehr@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/306371
Reviewed-by: Stéphane Marchesin <marcheu@chromium.org>
Reviewed-by: Haixia Shi <hshi@chromium.org>
diff --git a/video.c b/video.c
index 8bf78e7..5a70616 100644
--- a/video.c
+++ b/video.c
@@ -105,6 +105,9 @@
 				video->driver_version.date,
 				video->driver_version.desc);
 	}
+
+	video->drm_plane_resources = drmModeGetPlaneResources(fd);
+
 	return fd;
 }
 
@@ -415,9 +418,6 @@
 		goto fail;
 	}
 
-	disable_non_main_crtcs(new_video->fd,
-			new_video->drm_resources, new_video->crtc);
-
 	new_video->crtc->mode =
 		new_video->main_monitor_connector->modes[selected_mode];
 
@@ -475,6 +475,69 @@
 	return NULL;
 }
 
+static int video_is_primary_plane(video_t* video, uint32_t plane_id)
+{
+	uint32_t p;
+	bool found = false;
+	int ret = -1;
+
+	drmModeObjectPropertiesPtr props;
+	props = drmModeObjectGetProperties(video->fd,
+					   plane_id,
+					   DRM_MODE_OBJECT_PLANE);
+	if (!props) {
+		LOG(ERROR, "Unable to get plane properties: %m");
+		return -1;
+	}
+
+	for (p = 0; p < props->count_props && !found; p++) {
+		drmModePropertyPtr prop;
+		prop = drmModeGetProperty(video->fd, props->props[p]);
+		if (prop) {
+			if (strcmp("type", prop->name) == 0) {
+				found = true;
+				ret = (props->prop_values[p] == DRM_PLANE_TYPE_PRIMARY);
+			}
+			drmModeFreeProperty(prop);
+		}
+	}
+
+	drmModeFreeObjectProperties(props);
+
+	return ret;
+}
+
+/* disable all planes except for primary on crtc we use */
+static void video_disable_non_primary_planes(video_t* video)
+{
+	uint32_t p;
+	int ret;
+
+	if (!video->drm_plane_resources)
+		return;
+
+	for (p = 0; p < video->drm_plane_resources->count_planes; p++) {
+		drmModePlanePtr plane;
+		plane = drmModeGetPlane(video->fd,
+					video->drm_plane_resources->planes[p]);
+		if (plane) {
+			int primary = video_is_primary_plane(video, plane->plane_id);
+			if (!(plane->crtc_id == video->crtc->crtc_id && primary != 0)) {
+				ret = drmModeSetPlane(video->fd, plane->plane_id, plane->crtc_id,
+						      0, 0,
+						      0, 0,
+						      0, 0,
+						      0, 0,
+						      0, 0);
+				if (ret) {
+					LOG(WARNING, "Unable to disable plane: %m");
+				}
+			}
+			drmModeFreePlane(plane);
+		}
+	}
+}
+
 
 int32_t video_setmode(video_t* video)
 {
@@ -502,8 +565,11 @@
 	if (ret)
 		LOG(ERROR, "Unable to hide cursor");
 
-done:
+	video_disable_non_primary_planes(video);
+	disable_non_main_crtcs(video->fd,
+			video->drm_resources, video->crtc);
 
+done:
 	return ret;
 }
 
@@ -551,6 +617,11 @@
 			video->crtc = NULL;
 		}
 
+		if (video->drm_plane_resources) {
+			drmModeFreePlaneResources(video->drm_plane_resources);
+			video->drm_plane_resources = NULL;
+		}
+
 		if (video->drm_resources) {
 			drmModeFreeResources(video->drm_resources);
 			video->drm_resources = NULL;
diff --git a/video.h b/video.h
index 479907d..3d29680 100644
--- a/video.h
+++ b/video.h
@@ -43,6 +43,7 @@
 	buffer_properties_t buffer_properties;
 	video_lock_t        lock;
 	drmModeRes         *drm_resources;
+	drmModePlaneResPtr  drm_plane_resources;
 	drmModeConnector   *main_monitor_connector;
 	drmModeCrtc *crtc;
 	uint32_t buffer_handle;