From patchwork Tue Sep 9 06:28:11 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dave Airlie X-Patchwork-Id: 4866291 Return-Path: X-Original-To: patchwork-intel-gfx@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 2F91AC033C for ; Tue, 9 Sep 2014 06:28:34 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 2272920149 for ; Tue, 9 Sep 2014 06:28:33 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id 19729200E7 for ; Tue, 9 Sep 2014 06:28:32 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id C37BD6E39F; Mon, 8 Sep 2014 23:28:30 -0700 (PDT) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by gabe.freedesktop.org (Postfix) with ESMTP id 9E6F06E39F; Mon, 8 Sep 2014 23:28:29 -0700 (PDT) Received: from int-mx14.intmail.prod.int.phx2.redhat.com (int-mx14.intmail.prod.int.phx2.redhat.com [10.5.11.27]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id s896STD7028958 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Tue, 9 Sep 2014 02:28:29 -0400 Received: from tyrion-bne-redhat-com.bne.redhat.com (dhcp-41-68.bne.redhat.com [10.64.41.68]) by int-mx14.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id s896SIOw023257; Tue, 9 Sep 2014 02:28:28 -0400 From: Dave Airlie To: dri-devel@lists.freedesktop.org, intel-gfx@lists.freedesktop.org Date: Tue, 9 Sep 2014 16:28:11 +1000 Message-Id: <1410244096-9854-7-git-send-email-airlied@gmail.com> In-Reply-To: <1410244096-9854-1-git-send-email-airlied@gmail.com> References: <1410244096-9854-1-git-send-email-airlied@gmail.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.27 Subject: [Intel-gfx] [PATCH 06/11] drm/tile: attempt to set tiled crtcs up X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Spam-Status: No, score=-6.7 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, FREEMAIL_FROM,RCVD_IN_DNSWL_MED,RP_MATCHES_RCVD,UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Dave Airlie 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; }; /**