From: Dave Airlie <airl...@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 at 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

Reply via email to