From: Dave Airlie <airlied@gmail.com>
To: dri-devel@lists.freedesktop.org, intel-gfx@lists.freedesktop.org
Subject: [PATCH 06/11] drm/tile: attempt to set tiled crtcs up
Date: Tue, 9 Sep 2014 16:28:11 +1000 [thread overview]
Message-ID: <1410244096-9854-7-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>
Using the tiling info attempt to set a mode across two crtcs
---
drivers/gpu/drm/drm_crtc.c | 100 +++++++++++++++++++++++++++++++++-
drivers/gpu/drm/drm_displayid.c | 13 ++++-
drivers/gpu/drm/drm_dp_mst_topology.c | 18 +++++-
drivers/gpu/drm/drm_edid.c | 2 +
drivers/gpu/drm/drm_probe_helper.c | 2 +-
drivers/gpu/drm/i915/intel_modes.c | 1 +
include/drm/drm_crtc.h | 8 +++
7 files changed, 140 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 90e7730..99fa259 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -2506,6 +2506,93 @@ int drm_crtc_check_viewport(const struct drm_crtc *crtc,
}
EXPORT_SYMBOL(drm_crtc_check_viewport);
+/* tiled variants */
+static int drm_mode_setcrtc_tiled(struct drm_mode_set *orig_set)
+{
+ struct drm_device *dev = orig_set->crtc->dev;
+ struct drm_mode_set set[2];
+ struct drm_crtc *crtc2, *pick_crtc = NULL;
+ struct drm_connector *connector, *pick_conn[2];
+ struct drm_display_mode *cur_mode, *pick_modes[2];
+ int ret;
+
+ /* first up we need to find another crtc to use */
+ list_for_each_entry(crtc2, &dev->mode_config.crtc_list, head) {
+ if (crtc2 == orig_set->crtc)
+ continue;
+ if (crtc2->enabled)
+ continue;
+ pick_crtc = crtc2;
+ break;
+ }
+
+ if (pick_crtc == NULL) {
+ DRM_DEBUG_KMS("unable to located second CRTC for tiling\n");
+ return -EINVAL;
+ }
+
+ pick_conn[0] = orig_set->connectors[0];
+ pick_conn[1] = NULL;
+ list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+ if (!connector->has_tile)
+ continue;
+
+ if (connector == pick_conn[0])
+ continue;
+
+ if (connector->tile_group_id != pick_conn[0]->tile_group_id)
+ continue;
+
+ pick_conn[1] = connector;
+ }
+
+ DRM_DEBUG_KMS("picked connectors %x and %x from tgid %d\n", pick_conn[0]->base.id,
+ pick_conn[1]->base.id, pick_conn[0]->tile_group_id);
+ if (pick_conn[1] == NULL) {
+ DRM_DEBUG_KMS("unable to located second connector for tiling %d\n", pick_conn[0]->tile_group_id);
+ return -EINVAL;
+ }
+
+ pick_modes[0] = pick_modes[1] = NULL;
+ list_for_each_entry(cur_mode, &pick_conn[0]->modes, head) {
+ DRM_DEBUG_KMS("trying %d %d\n", cur_mode->hdisplay, cur_mode->vdisplay);
+ if (cur_mode->hdisplay == pick_conn[1]->tile_h_size + 1 &&
+ cur_mode->vdisplay == pick_conn[1]->tile_v_size + 1) {
+ pick_modes[0] = pick_modes[1] = cur_mode;
+ break;
+ }
+ }
+ if (pick_modes[0] == NULL) {
+ DRM_DEBUG_KMS("unable to locate second mode for tiling %d %d\n", pick_conn[1]->tile_h_size, pick_conn[1]->tile_v_size);
+ return -EINVAL;
+ }
+
+ set[0].fb = set[1].fb = orig_set->fb;
+
+ set[0].crtc = orig_set->crtc;
+ set[1].crtc = pick_crtc;
+
+ set[0].connectors = &pick_conn[0];
+ set[0].num_connectors = 1;
+
+ set[1].connectors = &pick_conn[1];
+ set[1].num_connectors = 1;
+
+ set[0].x = orig_set->x;
+ set[0].y = orig_set->y;
+ 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);
+
+ /* 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]);
+
+ return ret;
+}
/**
* drm_mode_setcrtc - set CRTC configuration
* @dev: drm device for the ioctl
@@ -2532,6 +2619,7 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
uint32_t __user *set_connectors_ptr;
int ret;
int i;
+ int num_tiles = 1;
if (!drm_core_check_feature(dev, DRIVER_MODESET))
return -EINVAL;
@@ -2640,6 +2728,12 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
connector->base.id,
connector->name);
+ if (crtc_req->count_connectors == 1) {
+ if (connector->has_tile && connector->tile_is_single_monitor) {
+ if (mode->hdisplay > connector->tile_h_size || mode->vdisplay > connector->tile_v_size)
+ num_tiles = 2;
+ }
+ }
connector_set[i] = connector;
}
}
@@ -2651,7 +2745,11 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
set.connectors = connector_set;
set.num_connectors = crtc_req->count_connectors;
set.fb = fb;
- ret = drm_mode_set_config_internal(&set);
+
+ if (num_tiles > 1) {
+ ret = drm_mode_setcrtc_tiled(&set);
+ } else
+ ret = drm_mode_set_config_internal(&set);
out:
if (fb)
diff --git a/drivers/gpu/drm/drm_displayid.c b/drivers/gpu/drm/drm_displayid.c
index d434da1..63d57a6 100644
--- a/drivers/gpu/drm/drm_displayid.c
+++ b/drivers/gpu/drm/drm_displayid.c
@@ -53,7 +53,18 @@ int drm_parse_display_id(struct drm_connector *connector,
tile_v_loc = (tile->topo[1] & 0xf) | ((tile->topo[2] & 0x3) << 4);
tile_h_loc = (tile->topo[1] >> 4) | (((tile->topo[2] >> 2) & 0x3) << 4);
- printk("tile cap %d\n", tile->tile_cap);
+ connector->has_tile = true;
+ if (tile->tile_cap & 0x80)
+ connector->tile_is_single_monitor = true;
+
+ connector->num_h_tile = num_h_tile;
+ connector->num_v_tile = num_v_tile;
+ connector->tile_h_loc = tile_h_loc;
+ connector->tile_v_loc = tile_v_loc;
+ connector->tile_h_size = w;
+ connector->tile_v_size = h;
+
+ printk("tile cap 0x%x\n", tile->tile_cap);
printk("tile_size %d x %d\n", w, h);
printk("topo num tiles %dx%d, location %dx%d\n",
num_h_tile, num_v_tile, tile_h_loc, tile_v_loc);
diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c
index 5d2a08e..1f15d85 100644
--- a/drivers/gpu/drm/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/drm_dp_mst_topology.c
@@ -858,6 +858,8 @@ static void drm_dp_destroy_port(struct kref *kref)
struct drm_dp_mst_topology_mgr *mgr = port->mgr;
if (!port->input) {
port->vcpi.num_slots = 0;
+
+ kfree(port->cached_edid);
if (port->connector)
(*port->mgr->cbs->destroy_connector)(mgr, port->connector);
drm_dp_port_teardown_pdt(port, port->pdt);
@@ -1100,8 +1102,16 @@ static void drm_dp_add_port(struct drm_dp_mst_branch *mstb,
if (port->mstb) {
port->mstb->conn_base_id = port->connector->base.id;
}
- if (port->port_num >= 8)
+ if (port->port_num >= 8) {
port->cached_edid = drm_get_edid(port->connector, &port->aux.ddc);
+ if (port->cached_edid) {
+ drm_get_displayid(port->connector,
+ &port->aux.ddc,
+ port->cached_edid,
+ false);
+ }
+
+ }
}
/* put reference to this port */
@@ -2210,10 +2220,16 @@ struct edid *drm_dp_mst_get_edid(struct drm_connector *connector, struct drm_dp_
if (!port)
return NULL;
+ if (connector->has_tile && connector->tile_is_single_monitor) {
+ if (connector->tile_h_loc > 0 || connector->tile_v_loc > 0) {
+ goto out;
+ }
+ }
if (port->cached_edid)
edid = drm_edid_duplicate(port->cached_edid);
else
edid = drm_get_edid(connector, &port->aux.ddc);
+ out:
drm_dp_put_port(port);
return edid;
}
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 3d805aa..94e8a57 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -3881,6 +3881,8 @@ void drm_get_displayid(struct drm_connector *connector,
bool secondary)
{
void *displayid = NULL;
+
+ connector->has_tile = false;
displayid = drm_find_displayid_extension(edid);
if (!displayid) {
return;
diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c
index db7d250..3fa902a 100644
--- a/drivers/gpu/drm/drm_probe_helper.c
+++ b/drivers/gpu/drm/drm_probe_helper.c
@@ -139,7 +139,7 @@ static int drm_helper_probe_single_connector_modes_merge_bits(struct drm_connect
count = (*connector_funcs->get_modes)(connector);
}
- if (count == 0 && connector->status == connector_status_connected)
+ if (count == 0 && connector->status == connector_status_connected && !connector->has_tile)
count = drm_add_modes_noedid(connector, 1024, 768);
if (count == 0)
goto prune;
diff --git a/drivers/gpu/drm/i915/intel_modes.c b/drivers/gpu/drm/i915/intel_modes.c
index 35a327e..52948c6 100644
--- a/drivers/gpu/drm/i915/intel_modes.c
+++ b/drivers/gpu/drm/i915/intel_modes.c
@@ -42,6 +42,7 @@ int intel_connector_update_modes(struct drm_connector *connector,
int ret;
drm_mode_connector_update_edid_property(connector, edid);
+
ret = drm_add_edid_modes(connector, edid);
drm_edid_to_eld(connector, edid);
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 1efc007..67c06bd 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -564,6 +564,14 @@ struct drm_connector {
unsigned bad_edid_counter;
struct dentry *debugfs_entry;
+
+ /* DisplayID bits */
+ bool has_tile;
+ bool tile_is_single_monitor;
+ uint32_t tile_group_id;
+ uint8_t num_h_tile, num_v_tile;
+ uint8_t tile_h_loc, tile_v_loc;
+ uint16_t tile_h_size, tile_v_size;
};
/**
--
1.9.3
next prev 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 ` Dave Airlie [this message]
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 ` [PATCH 08/11] drm/crtc: attempt to set tiled modes from userspace Dave Airlie
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-7-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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.