public inbox for intel-gfx@lists.freedesktop.org
 help / color / mirror / Atom feed
From: Dave Airlie <airlied@gmail.com>
To: dri-devel@lists.freedesktop.org, intel-gfx@lists.freedesktop.org
Subject: [PATCH 08/11] drm/crtc: attempt to set tiled modes from userspace
Date: Tue,  9 Sep 2014 16:28:13 +1000	[thread overview]
Message-ID: <1410244096-9854-9-git-send-email-airlied@gmail.com> (raw)
In-Reply-To: <1410244096-9854-1-git-send-email-airlied@gmail.com>

From: Dave Airlie <airlied@redhat.com>

So when userspace asks us to set a mode on a tiled crtc,
split it up and find the actual modes and attempt to set them.

Also disable crtcs when no longer in tiled group.

Signed-off-by: Dave Airlie <airlied@redhat.com>
---
 drivers/gpu/drm/drm_crtc.c            | 51 ++++++++++++++++++++++++++++++++---
 drivers/gpu/drm/drm_dp_mst_topology.c |  6 +++++
 include/drm/drm_crtc.h                |  8 ++++++
 3 files changed, 61 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 99fa259..628f3af 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -764,6 +764,9 @@ int drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc,
 	crtc->funcs = funcs;
 	crtc->invert_dimensions = false;
 
+	INIT_LIST_HEAD(&crtc->tile_crtc_list);
+	crtc->tile_master = NULL;
+
 	drm_modeset_lock_all(dev);
 	drm_modeset_lock_init(&crtc->mutex);
 	/* dropped by _unlock_all(): */
@@ -2520,7 +2523,7 @@ static int drm_mode_setcrtc_tiled(struct drm_mode_set *orig_set)
 	list_for_each_entry(crtc2, &dev->mode_config.crtc_list, head) {
 		if (crtc2 == orig_set->crtc)
 			continue;
-		if (crtc2->enabled)
+		if (crtc2->enabled && !crtc2->tile_master)
 			continue;
 		pick_crtc = crtc2;
 		break;
@@ -2583,14 +2586,26 @@ static int drm_mode_setcrtc_tiled(struct drm_mode_set *orig_set)
 	set[1].x = orig_set->x + ((pick_conn[1]->tile_h_loc == 1) ? pick_conn[0]->tile_h_size + 1 : 0);
 	set[1].y = orig_set->y + ((pick_conn[1]->tile_v_loc == 1) ? pick_conn[0]->tile_v_size + 1 : 0);
 
+	if (set[1].crtc->tile_master) {
+		list_del(&set[1].crtc->tile);
+		set[1].crtc->tile_master = NULL;
+	}
+	list_add_tail(&set[1].crtc->tile, &set[0].crtc->tile_crtc_list);
+	set[1].crtc->tile_master = set[0].crtc;
 	/* find a mode to use on each head */
 	set[0].mode = pick_modes[0];
 	set[1].mode = pick_modes[1];
 
 	ret = drm_mode_set_config_internal(&set[0]);
 
-	ret = drm_mode_set_config_internal(&set[1]);
+	if (!ret) {
+		ret = drm_mode_set_config_internal(&set[1]);
+	}
 
+	if (ret) {
+		set[1].crtc->tile_master = NULL;
+		list_del(&set[1].crtc->tile);
+	}
 	return ret;
 }
 /**
@@ -2637,6 +2652,15 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
 	}
 	DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id);
 
+	if (crtc->tile_master) {
+		if (crtc_req->mode_valid)
+			ret = -EBUSY;
+		else
+			ret = 0;
+		DRM_DEBUG_KMS("[CRTC:%d] refused due to tile %d\n", crtc->base.id, ret);
+		goto out;
+	}
+
 	if (crtc_req->mode_valid) {
 		/* If we have a mode we need a framebuffer. */
 		/* If we pass -1, set the mode with the currently bound fb */
@@ -2748,9 +2772,25 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
 
 	if (num_tiles > 1) {
 		ret = drm_mode_setcrtc_tiled(&set);
-	} else
-		ret = drm_mode_set_config_internal(&set);
+	} else {
+		if (!list_empty(&crtc->tile_crtc_list)) {
+			struct drm_crtc *tile_crtc, *t;
+
+			list_for_each_entry_safe(tile_crtc, t, &crtc->tile_crtc_list, tile) {
+				struct drm_mode_set set2;
+
+				tile_crtc->tile_master = NULL;
+				list_del(&tile_crtc->tile);
 
+				DRM_DEBUG_KMS("disabling crtc %p due to no longer needing tiling %p\n", tile_crtc, tile_crtc->primary);
+				memset(&set2, 0, sizeof(struct drm_mode_set));
+				set2.crtc = tile_crtc;
+				set2.fb = NULL;
+				ret = drm_mode_set_config_internal(&set2);
+			}
+		}
+		ret = drm_mode_set_config_internal(&set);
+	}
 out:
 	if (fb)
 		drm_framebuffer_unreference(fb);
@@ -4226,6 +4266,9 @@ static int drm_mode_connector_set_obj_prop(struct drm_mode_object *obj,
 	int ret = -EINVAL;
 	struct drm_connector *connector = obj_to_connector(obj);
 
+	if (connector->has_tile && connector->tile_is_single_monitor &&
+	    (connector->tile_h_loc || connector->tile_v_loc))
+		return 0;
 	/* Do DPMS ourselves */
 	if (property == connector->dev->mode_config.dpms_property) {
 		if (connector->funcs->dpms)
diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c
index 08b7140..ca5eee6 100644
--- a/drivers/gpu/drm/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/drm_dp_mst_topology.c
@@ -2190,6 +2190,12 @@ enum drm_connector_status drm_dp_mst_detect_port(struct drm_connector *connector
 		if (port->port_num >= 8 && !port->cached_edid) {
 			port->cached_edid = drm_get_edid(connector, &port->aux.ddc);
 		}
+
+		if (connector->has_tile && connector->tile_group_id == 0)
+			connector->tile_group_id = port->parent->conn_base_id;
+		if (connector->has_tile && (connector->tile_h_loc || connector->tile_v_loc))
+			status = connector_status_disconnected;
+
 		break;
 	case DP_PEER_DEVICE_DP_LEGACY_CONV:
 		if (port->ldps)
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 67c06bd..6041acd 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -375,6 +375,14 @@ struct drm_crtc {
 	void *helper_private;
 
 	struct drm_object_properties properties;
+
+	/* crtcs this one is using for tiling */
+	struct list_head tile_crtc_list;
+
+	/* tile list entry */
+	struct list_head tile;
+
+	struct drm_crtc *tile_master;
 };
 
 
-- 
1.9.3

  parent reply	other threads:[~2014-09-09  6:28 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-09-09  6:28 [RFC] attempting to hide 30" monitor in kernel (raw) Dave Airlie
2014-09-09  6:28 ` [PATCH 01/11] drm/mst: rework payload table allocation to conform better Dave Airlie
2014-09-09  6:28 ` [PATCH 02/11] drm/i915: add config option to enable/disable DP MST Dave Airlie
2014-09-09  7:51   ` Jani Nikula
2014-09-09  6:28 ` [PATCH 03/11] drm/mst: start caching edid for logical ports Dave Airlie
2014-09-09  6:28 ` [PATCH 04/11] drm/displayid: add some DisplayID related defines/structs Dave Airlie
2014-09-09  6:28 ` [PATCH 05/11] drm/dp/mst: add concept of base connector id Dave Airlie
2014-09-09  6:28 ` [PATCH 06/11] drm/tile: attempt to set tiled crtcs up Dave Airlie
2014-09-09  6:28 ` [PATCH 07/11] drm/edid: allow patching the EDID to report monster mode Dave Airlie
2014-09-09  6:28 ` Dave Airlie [this message]
2014-09-09  6:28 ` [PATCH 09/11] drm/crtc: workaround userspace trying to derail crtc stealing Dave Airlie
2014-09-09  6:28 ` [PATCH 10/11] drm/tiled: add page_flip support for multi-crtc monitors Dave Airlie
2014-09-09  6:28 ` [PATCH 11/11] drm/tiled: vague attempt at waving at cursors Dave Airlie
2014-09-09  8:54 ` [RFC] attempting to hide 30" monitor in kernel (raw) Daniel Vetter

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1410244096-9854-9-git-send-email-airlied@gmail.com \
    --to=airlied@gmail.com \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=intel-gfx@lists.freedesktop.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox