From patchwork Tue Mar 26 17:55:31 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Noralf_Tr=C3=B8nnes?= X-Patchwork-Id: 10871803 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 92CAA922 for ; Tue, 26 Mar 2019 17:56:14 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 8068E28D63 for ; Tue, 26 Mar 2019 17:56:14 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 7410728D6A; Tue, 26 Mar 2019 17:56:14 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED autolearn=unavailable version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 3600228D63 for ; Tue, 26 Mar 2019 17:56:14 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 612AE6E051; Tue, 26 Mar 2019 17:56:06 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from smtp.domeneshop.no (smtp.domeneshop.no [IPv6:2a01:5b40:0:3005::1]) by gabe.freedesktop.org (Postfix) with ESMTPS id F2A2D6E03B; Tue, 26 Mar 2019 17:56:04 +0000 (UTC) Received: from 211.81-166-168.customer.lyse.net ([81.166.168.211]:46322 helo=localhost.localdomain) by smtp.domeneshop.no with esmtpsa (TLS1.2:ECDHE_RSA_AES_128_CBC_SHA1:128) (Exim 4.84_2) (envelope-from ) id 1h8qIt-0006Mj-3L; Tue, 26 Mar 2019 18:56:03 +0100 From: =?utf-8?q?Noralf_Tr=C3=B8nnes?= To: dri-devel@lists.freedesktop.org Subject: [PATCH 01/16] drm/fb-helper: Remove unused gamma_size variable Date: Tue, 26 Mar 2019 18:55:31 +0100 Message-Id: <20190326175546.18126-2-noralf@tronnes.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190326175546.18126-1-noralf@tronnes.org> References: <20190326175546.18126-1-noralf@tronnes.org> MIME-Version: 1.0 X-Mailman-Original-DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=tronnes.org; s=ds201810; h=Content-Transfer-Encoding:Content-Type:MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From; bh=dPYhYVuGaGvu7pHIvkobwW7/H+fZvBowvsESRQCvrEQ=; b=bxe3ZVIVGVv/TbB/1vz7ZrjhpiMMzIxuuy9cDIRRQKg0eB7G8IN7fEhCFdFS+CfGCFh5kKHhmFqb2N9fZHvZj53+k+1QHIoJhC/gTZrTCDa9gcu9OehrPsR1Dqy7pMGZtKcOrzB0NRX35eS1MNz8ymO4W6oi1Xbju/SUPGilQfEjnwe9638GEHp1SbwudiV7TTH7dJAFH34Z+lVmRKxZDNAfKzEhw2psQZV4ThrK85UjyjL381oliZmWxAduOdIg7pc4s3zDUAnGlQzmVXeSRg/v+iWdyDbqVoHTDpM2Nwzf4c1vqIF5Db1ub3Is9BnQCylWsnRDugHcd8KV0etJ4w==; X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: intel-gfx@lists.freedesktop.org, mstaudt@suse.de Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Virus-Scanned: ClamAV using ClamSMTP The gamma_size variable has not been used since commit 4abe35204af8 ("drm/kms/fb: use slow work mechanism for normal hotplug also.") While in the area move a comment back to its code block. They got separated by commit d50ba256b5f1 ("drm/kms: start adding command line interface using fb."). Signed-off-by: Noralf Trønnes Reviewed-by: Daniel Vetter --- drivers/gpu/drm/drm_fb_helper.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 04d23cb430bf..eea15465da7a 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -1873,7 +1873,6 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper, int crtc_count = 0; int i; struct drm_fb_helper_surface_size sizes; - int gamma_size = 0; int best_depth = 0; memset(&sizes, 0, sizeof(struct drm_fb_helper_surface_size)); @@ -1889,7 +1888,6 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper, if (preferred_bpp != sizes.surface_bpp) sizes.surface_depth = sizes.surface_bpp = preferred_bpp; - /* first up get a count of crtcs now in use and new min/maxes width/heights */ drm_fb_helper_for_each_connector(fb_helper, i) { struct drm_fb_helper_connector *fb_helper_conn = fb_helper->connector_info[i]; struct drm_cmdline_mode *cmdline_mode; @@ -1969,6 +1967,7 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper, sizes.surface_depth = best_depth; } + /* first up get a count of crtcs now in use and new min/maxes width/heights */ crtc_count = 0; for (i = 0; i < fb_helper->crtc_count; i++) { struct drm_display_mode *desired_mode; @@ -1991,9 +1990,6 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper, x = fb_helper->crtc_info[i].x; y = fb_helper->crtc_info[i].y; - if (gamma_size == 0) - gamma_size = fb_helper->crtc_info[i].mode_set.crtc->gamma_size; - sizes.surface_width = max_t(u32, desired_mode->hdisplay + x, sizes.surface_width); sizes.surface_height = max_t(u32, desired_mode->vdisplay + y, sizes.surface_height); From patchwork Tue Mar 26 17:55:32 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Noralf_Tr=C3=B8nnes?= X-Patchwork-Id: 10871805 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 68672922 for ; Tue, 26 Mar 2019 17:56:17 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 57CDD28D66 for ; Tue, 26 Mar 2019 17:56:17 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 4C80728D6B; Tue, 26 Mar 2019 17:56:17 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 06D8928D66 for ; Tue, 26 Mar 2019 17:56:17 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 29A3C6E04C; Tue, 26 Mar 2019 17:56:06 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from smtp.domeneshop.no (smtp.domeneshop.no [IPv6:2a01:5b40:0:3005::1]) by gabe.freedesktop.org (Postfix) with ESMTPS id 0ECDE6E04C; Tue, 26 Mar 2019 17:56:05 +0000 (UTC) Received: from 211.81-166-168.customer.lyse.net ([81.166.168.211]:46322 helo=localhost.localdomain) by smtp.domeneshop.no with esmtpsa (TLS1.2:ECDHE_RSA_AES_128_CBC_SHA1:128) (Exim 4.84_2) (envelope-from ) id 1h8qIt-0006Mj-9D; Tue, 26 Mar 2019 18:56:03 +0100 From: =?utf-8?q?Noralf_Tr=C3=B8nnes?= To: dri-devel@lists.freedesktop.org Subject: [PATCH 02/16] drm/fb-helper: dpms_legacy(): Only set on connectors in use Date: Tue, 26 Mar 2019 18:55:32 +0100 Message-Id: <20190326175546.18126-3-noralf@tronnes.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190326175546.18126-1-noralf@tronnes.org> References: <20190326175546.18126-1-noralf@tronnes.org> MIME-Version: 1.0 X-Mailman-Original-DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=tronnes.org; s=ds201810; h=Content-Transfer-Encoding:Content-Type:MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From; bh=2yGNwPMmQs1FYcHtJQu9iDJ3KAuE9KtJ/ikIqFnYZTs=; b=dUahnWm0HhlnBZKMMxV9Eu+l5KtyuvMmGnyb/7IBZhU3ny3XU0QARnunIjgPo6AOOzJk6AbYHEWA18y4C912wXX6KlWZDcpiuf2szWayJ2VvG3D+WYYSTtJsSyV16jNPtBBUOwPmZSHaZrLbIVYEFgNvdVuNQsSiMw9X9XOF8PJoRnMsCxk2Q7KRQ2TEatLbzz0C6MnjYk2q3h3VIj6R7Q5yOg5RcpssbtiUXBTtA/hZvmXrVcq+qIdt3Pu0wpeIIAfUX16yFH0M27776P0IzlMQ9B9WQdrXW5vG7TTgJiFCnUKxtmaphdGm++F1I1ryfO0j6/pNMTC1zlH+Ganc2w==; X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: intel-gfx@lists.freedesktop.org, mstaudt@suse.de Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Virus-Scanned: ClamAV using ClamSMTP For each enabled crtc the functions sets dpms on all registered connectors. Limit this to only doing it once and on the connectors actually in use. Signed-off-by: Noralf Trønnes Reviewed-by: Daniel Vetter --- drivers/gpu/drm/drm_fb_helper.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index eea15465da7a..b91df658db59 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -639,20 +639,19 @@ static struct sysrq_key_op sysrq_drm_fb_helper_restore_op = { }; static void dpms_legacy(struct drm_fb_helper *fb_helper, int dpms_mode) { struct drm_device *dev = fb_helper->dev; - struct drm_crtc *crtc; struct drm_connector *connector; + struct drm_mode_set *modeset; int i, j; drm_modeset_lock_all(dev); for (i = 0; i < fb_helper->crtc_count; i++) { - crtc = fb_helper->crtc_info[i].mode_set.crtc; + modeset = &fb_helper->crtc_info[i].mode_set; - if (!crtc->enabled) + if (!modeset->crtc->enabled) continue; - /* Walk the connectors & encoders on this fb turning them on/off */ - drm_fb_helper_for_each_connector(fb_helper, j) { - connector = fb_helper->connector_info[j]->connector; + for (j = 0; j < modeset->num_connectors; j++) { + connector = modeset->connectors[j]; connector->funcs->dpms(connector, dpms_mode); drm_object_property_set_value(&connector->base, dev->mode_config.dpms_property, dpms_mode); From patchwork Tue Mar 26 17:55:33 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Noralf_Tr=C3=B8nnes?= X-Patchwork-Id: 10871817 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id ED907922 for ; Tue, 26 Mar 2019 17:56:25 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id DB6B628D54 for ; Tue, 26 Mar 2019 17:56:25 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id CFF0328D6A; Tue, 26 Mar 2019 17:56:25 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED autolearn=unavailable version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 2E22F28D54 for ; Tue, 26 Mar 2019 17:56:25 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 0AA896E067; Tue, 26 Mar 2019 17:56:08 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from smtp.domeneshop.no (smtp.domeneshop.no [IPv6:2a01:5b40:0:3005::1]) by gabe.freedesktop.org (Postfix) with ESMTPS id 3BFCC6E036; Tue, 26 Mar 2019 17:56:05 +0000 (UTC) Received: from 211.81-166-168.customer.lyse.net ([81.166.168.211]:46322 helo=localhost.localdomain) by smtp.domeneshop.no with esmtpsa (TLS1.2:ECDHE_RSA_AES_128_CBC_SHA1:128) (Exim 4.84_2) (envelope-from ) id 1h8qIt-0006Mj-EM; Tue, 26 Mar 2019 18:56:03 +0100 From: =?utf-8?q?Noralf_Tr=C3=B8nnes?= To: dri-devel@lists.freedesktop.org Subject: [PATCH 03/16] drm/atomic: Move __drm_atomic_helper_disable_plane/set_config() Date: Tue, 26 Mar 2019 18:55:33 +0100 Message-Id: <20190326175546.18126-4-noralf@tronnes.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190326175546.18126-1-noralf@tronnes.org> References: <20190326175546.18126-1-noralf@tronnes.org> MIME-Version: 1.0 X-Mailman-Original-DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=tronnes.org; s=ds201810; h=Content-Transfer-Encoding:Content-Type:MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From; bh=eTEgWsFvyg+4l98PnTFcdDVcGXGzm5khsy9e0NibOio=; b=rK7Lu14pTmN2xQLI0T9IFmVpyJypY3Xr3oFzyLNuzuxCw939ka7UQcUbpYwWkP2kj/3QBDfSWCIDoQgYsBC4HHtKvFOYxPUrGy24JFjSlQ2GnYAOaAkyDmVx5Le+l+DRnpOJVbSMJSGUjhywGXFBfVjwTZvI5JOsvZmaZQBJBM/tEU693N+UWqFs6cokcBBIwKsfrb1qNMFpYTZXqv27VY2ED5hI+Xo9ij7XNYVg0Fmz9fzE6zsMdHfRusKPxkSjagm2qO27gr5o+fokX0FAnsccMOk4OUq5VkotwbL7LfLKMQKQEVagVb6fA8wFmVTJHh19oqMOhDN1DRo40aDR5Q==; X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: intel-gfx@lists.freedesktop.org, mstaudt@suse.de Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Virus-Scanned: ClamAV using ClamSMTP Prepare for moving drm_fb_helper modesetting code to drm_client. drm_client will be linked to drm.ko, so move __drm_atomic_helper_disable_plane() and __drm_atomic_helper_set_config() out of drm_kms_helper.ko. While at it, fix two checkpatch complaints: - WARNING: Block comments use a trailing */ on a separate line - CHECK: Alignment should match open parenthesis Signed-off-by: Noralf Trønnes Reviewed-by: Daniel Vetter --- drivers/gpu/drm/drm_atomic.c | 168 ++++++++++++++++++++++++++++ drivers/gpu/drm/drm_atomic_helper.c | 164 --------------------------- drivers/gpu/drm/drm_crtc_internal.h | 5 + include/drm/drm_atomic_helper.h | 4 - 4 files changed, 173 insertions(+), 168 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 5eb40130fafb..c3a9ffbf2310 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -1130,6 +1130,174 @@ int drm_atomic_nonblocking_commit(struct drm_atomic_state *state) } EXPORT_SYMBOL(drm_atomic_nonblocking_commit); +/* just used from drm-client and atomic-helper: */ +int __drm_atomic_helper_disable_plane(struct drm_plane *plane, + struct drm_plane_state *plane_state) +{ + int ret; + + ret = drm_atomic_set_crtc_for_plane(plane_state, NULL); + if (ret != 0) + return ret; + + drm_atomic_set_fb_for_plane(plane_state, NULL); + plane_state->crtc_x = 0; + plane_state->crtc_y = 0; + plane_state->crtc_w = 0; + plane_state->crtc_h = 0; + plane_state->src_x = 0; + plane_state->src_y = 0; + plane_state->src_w = 0; + plane_state->src_h = 0; + + return 0; +} +EXPORT_SYMBOL(__drm_atomic_helper_disable_plane); + +static int update_output_state(struct drm_atomic_state *state, + struct drm_mode_set *set) +{ + struct drm_device *dev = set->crtc->dev; + struct drm_crtc *crtc; + struct drm_crtc_state *new_crtc_state; + struct drm_connector *connector; + struct drm_connector_state *new_conn_state; + int ret, i; + + ret = drm_modeset_lock(&dev->mode_config.connection_mutex, + state->acquire_ctx); + if (ret) + return ret; + + /* First disable all connectors on the target crtc. */ + ret = drm_atomic_add_affected_connectors(state, set->crtc); + if (ret) + return ret; + + for_each_new_connector_in_state(state, connector, new_conn_state, i) { + if (new_conn_state->crtc == set->crtc) { + ret = drm_atomic_set_crtc_for_connector(new_conn_state, + NULL); + if (ret) + return ret; + + /* Make sure legacy setCrtc always re-trains */ + new_conn_state->link_status = DRM_LINK_STATUS_GOOD; + } + } + + /* Then set all connectors from set->connectors on the target crtc */ + for (i = 0; i < set->num_connectors; i++) { + new_conn_state = drm_atomic_get_connector_state(state, + set->connectors[i]); + if (IS_ERR(new_conn_state)) + return PTR_ERR(new_conn_state); + + ret = drm_atomic_set_crtc_for_connector(new_conn_state, + set->crtc); + if (ret) + return ret; + } + + for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) { + /* + * Don't update ->enable for the CRTC in the set_config request, + * since a mismatch would indicate a bug in the upper layers. + * The actual modeset code later on will catch any + * inconsistencies here. + */ + if (crtc == set->crtc) + continue; + + if (!new_crtc_state->connector_mask) { + ret = drm_atomic_set_mode_prop_for_crtc(new_crtc_state, + NULL); + if (ret < 0) + return ret; + + new_crtc_state->active = false; + } + } + + return 0; +} + +/* just used from drm-client and atomic-helper: */ +int __drm_atomic_helper_set_config(struct drm_mode_set *set, + struct drm_atomic_state *state) +{ + struct drm_crtc_state *crtc_state; + struct drm_plane_state *primary_state; + struct drm_crtc *crtc = set->crtc; + int hdisplay, vdisplay; + int ret; + + crtc_state = drm_atomic_get_crtc_state(state, crtc); + if (IS_ERR(crtc_state)) + return PTR_ERR(crtc_state); + + primary_state = drm_atomic_get_plane_state(state, crtc->primary); + if (IS_ERR(primary_state)) + return PTR_ERR(primary_state); + + if (!set->mode) { + WARN_ON(set->fb); + WARN_ON(set->num_connectors); + + ret = drm_atomic_set_mode_for_crtc(crtc_state, NULL); + if (ret != 0) + return ret; + + crtc_state->active = false; + + ret = drm_atomic_set_crtc_for_plane(primary_state, NULL); + if (ret != 0) + return ret; + + drm_atomic_set_fb_for_plane(primary_state, NULL); + + goto commit; + } + + WARN_ON(!set->fb); + WARN_ON(!set->num_connectors); + + ret = drm_atomic_set_mode_for_crtc(crtc_state, set->mode); + if (ret != 0) + return ret; + + crtc_state->active = true; + + ret = drm_atomic_set_crtc_for_plane(primary_state, crtc); + if (ret != 0) + return ret; + + drm_mode_get_hv_timing(set->mode, &hdisplay, &vdisplay); + + drm_atomic_set_fb_for_plane(primary_state, set->fb); + primary_state->crtc_x = 0; + primary_state->crtc_y = 0; + primary_state->crtc_w = hdisplay; + primary_state->crtc_h = vdisplay; + primary_state->src_x = set->x << 16; + primary_state->src_y = set->y << 16; + if (drm_rotation_90_or_270(primary_state->rotation)) { + primary_state->src_w = vdisplay << 16; + primary_state->src_h = hdisplay << 16; + } else { + primary_state->src_w = hdisplay << 16; + primary_state->src_h = vdisplay << 16; + } + +commit: + ret = update_output_state(state, set); + if (ret) + return ret; + + return 0; +} +EXPORT_SYMBOL(__drm_atomic_helper_set_config); + void drm_atomic_print_state(const struct drm_atomic_state *state) { struct drm_printer p = drm_info_printer(state->dev->dev); diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 2453678d1186..b0d960da53cb 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -2831,95 +2831,6 @@ int drm_atomic_helper_disable_plane(struct drm_plane *plane, } EXPORT_SYMBOL(drm_atomic_helper_disable_plane); -/* just used from fb-helper and atomic-helper: */ -int __drm_atomic_helper_disable_plane(struct drm_plane *plane, - struct drm_plane_state *plane_state) -{ - int ret; - - ret = drm_atomic_set_crtc_for_plane(plane_state, NULL); - if (ret != 0) - return ret; - - drm_atomic_set_fb_for_plane(plane_state, NULL); - plane_state->crtc_x = 0; - plane_state->crtc_y = 0; - plane_state->crtc_w = 0; - plane_state->crtc_h = 0; - plane_state->src_x = 0; - plane_state->src_y = 0; - plane_state->src_w = 0; - plane_state->src_h = 0; - - return 0; -} - -static int update_output_state(struct drm_atomic_state *state, - struct drm_mode_set *set) -{ - struct drm_device *dev = set->crtc->dev; - struct drm_crtc *crtc; - struct drm_crtc_state *new_crtc_state; - struct drm_connector *connector; - struct drm_connector_state *new_conn_state; - int ret, i; - - ret = drm_modeset_lock(&dev->mode_config.connection_mutex, - state->acquire_ctx); - if (ret) - return ret; - - /* First disable all connectors on the target crtc. */ - ret = drm_atomic_add_affected_connectors(state, set->crtc); - if (ret) - return ret; - - for_each_new_connector_in_state(state, connector, new_conn_state, i) { - if (new_conn_state->crtc == set->crtc) { - ret = drm_atomic_set_crtc_for_connector(new_conn_state, - NULL); - if (ret) - return ret; - - /* Make sure legacy setCrtc always re-trains */ - new_conn_state->link_status = DRM_LINK_STATUS_GOOD; - } - } - - /* Then set all connectors from set->connectors on the target crtc */ - for (i = 0; i < set->num_connectors; i++) { - new_conn_state = drm_atomic_get_connector_state(state, - set->connectors[i]); - if (IS_ERR(new_conn_state)) - return PTR_ERR(new_conn_state); - - ret = drm_atomic_set_crtc_for_connector(new_conn_state, - set->crtc); - if (ret) - return ret; - } - - for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) { - /* Don't update ->enable for the CRTC in the set_config request, - * since a mismatch would indicate a bug in the upper layers. - * The actual modeset code later on will catch any - * inconsistencies here. */ - if (crtc == set->crtc) - continue; - - if (!new_crtc_state->connector_mask) { - ret = drm_atomic_set_mode_prop_for_crtc(new_crtc_state, - NULL); - if (ret < 0) - return ret; - - new_crtc_state->active = false; - } - } - - return 0; -} - /** * drm_atomic_helper_set_config - set a new config from userspace * @set: mode set configuration @@ -2964,81 +2875,6 @@ int drm_atomic_helper_set_config(struct drm_mode_set *set, } EXPORT_SYMBOL(drm_atomic_helper_set_config); -/* just used from fb-helper and atomic-helper: */ -int __drm_atomic_helper_set_config(struct drm_mode_set *set, - struct drm_atomic_state *state) -{ - struct drm_crtc_state *crtc_state; - struct drm_plane_state *primary_state; - struct drm_crtc *crtc = set->crtc; - int hdisplay, vdisplay; - int ret; - - crtc_state = drm_atomic_get_crtc_state(state, crtc); - if (IS_ERR(crtc_state)) - return PTR_ERR(crtc_state); - - primary_state = drm_atomic_get_plane_state(state, crtc->primary); - if (IS_ERR(primary_state)) - return PTR_ERR(primary_state); - - if (!set->mode) { - WARN_ON(set->fb); - WARN_ON(set->num_connectors); - - ret = drm_atomic_set_mode_for_crtc(crtc_state, NULL); - if (ret != 0) - return ret; - - crtc_state->active = false; - - ret = drm_atomic_set_crtc_for_plane(primary_state, NULL); - if (ret != 0) - return ret; - - drm_atomic_set_fb_for_plane(primary_state, NULL); - - goto commit; - } - - WARN_ON(!set->fb); - WARN_ON(!set->num_connectors); - - ret = drm_atomic_set_mode_for_crtc(crtc_state, set->mode); - if (ret != 0) - return ret; - - crtc_state->active = true; - - ret = drm_atomic_set_crtc_for_plane(primary_state, crtc); - if (ret != 0) - return ret; - - drm_mode_get_hv_timing(set->mode, &hdisplay, &vdisplay); - - drm_atomic_set_fb_for_plane(primary_state, set->fb); - primary_state->crtc_x = 0; - primary_state->crtc_y = 0; - primary_state->crtc_w = hdisplay; - primary_state->crtc_h = vdisplay; - primary_state->src_x = set->x << 16; - primary_state->src_y = set->y << 16; - if (drm_rotation_90_or_270(primary_state->rotation)) { - primary_state->src_w = vdisplay << 16; - primary_state->src_h = hdisplay << 16; - } else { - primary_state->src_w = hdisplay << 16; - primary_state->src_h = vdisplay << 16; - } - -commit: - ret = update_output_state(state, set); - if (ret) - return ret; - - return 0; -} - static int __drm_atomic_helper_disable_all(struct drm_device *dev, struct drm_modeset_acquire_ctx *ctx, bool clean_old_fbs) diff --git a/drivers/gpu/drm/drm_crtc_internal.h b/drivers/gpu/drm/drm_crtc_internal.h index 216f2a9ee3d4..22a63a544ec7 100644 --- a/drivers/gpu/drm/drm_crtc_internal.h +++ b/drivers/gpu/drm/drm_crtc_internal.h @@ -207,6 +207,11 @@ struct drm_minor; int drm_atomic_debugfs_init(struct drm_minor *minor); #endif +int __drm_atomic_helper_disable_plane(struct drm_plane *plane, + struct drm_plane_state *plane_state); +int __drm_atomic_helper_set_config(struct drm_mode_set *set, + struct drm_atomic_state *state); + void drm_atomic_print_state(const struct drm_atomic_state *state); /* drm_atomic_uapi.c */ diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h index 58214be3bf3d..bf4e07141d81 100644 --- a/include/drm/drm_atomic_helper.h +++ b/include/drm/drm_atomic_helper.h @@ -117,12 +117,8 @@ int drm_atomic_helper_update_plane(struct drm_plane *plane, struct drm_modeset_acquire_ctx *ctx); int drm_atomic_helper_disable_plane(struct drm_plane *plane, struct drm_modeset_acquire_ctx *ctx); -int __drm_atomic_helper_disable_plane(struct drm_plane *plane, - struct drm_plane_state *plane_state); int drm_atomic_helper_set_config(struct drm_mode_set *set, struct drm_modeset_acquire_ctx *ctx); -int __drm_atomic_helper_set_config(struct drm_mode_set *set, - struct drm_atomic_state *state); int drm_atomic_helper_disable_all(struct drm_device *dev, struct drm_modeset_acquire_ctx *ctx); From patchwork Tue Mar 26 17:55:34 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Noralf_Tr=C3=B8nnes?= X-Patchwork-Id: 10871807 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 5206B1669 for ; Tue, 26 Mar 2019 17:56:19 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3FBE728D63 for ; Tue, 26 Mar 2019 17:56:19 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 3440128D6B; Tue, 26 Mar 2019 17:56:19 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 9F61C28D6A for ; Tue, 26 Mar 2019 17:56:18 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 203966E065; Tue, 26 Mar 2019 17:56:07 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from smtp.domeneshop.no (smtp.domeneshop.no [IPv6:2a01:5b40:0:3005::1]) by gabe.freedesktop.org (Postfix) with ESMTPS id 940B06E03B; Tue, 26 Mar 2019 17:56:05 +0000 (UTC) Received: from 211.81-166-168.customer.lyse.net ([81.166.168.211]:46322 helo=localhost.localdomain) by smtp.domeneshop.no with esmtpsa (TLS1.2:ECDHE_RSA_AES_128_CBC_SHA1:128) (Exim 4.84_2) (envelope-from ) id 1h8qIt-0006Mj-PO; Tue, 26 Mar 2019 18:56:03 +0100 From: =?utf-8?q?Noralf_Tr=C3=B8nnes?= To: dri-devel@lists.freedesktop.org Subject: [PATCH 04/16] drm/fb-helper: No need to cache rotation and sw_rotations Date: Tue, 26 Mar 2019 18:55:34 +0100 Message-Id: <20190326175546.18126-5-noralf@tronnes.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190326175546.18126-1-noralf@tronnes.org> References: <20190326175546.18126-1-noralf@tronnes.org> MIME-Version: 1.0 X-Mailman-Original-DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=tronnes.org; s=ds201810; h=Content-Transfer-Encoding:Content-Type:MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From; bh=5yZ9rsps6QBRJX6fZnZanwyeqXXftxIlXoWf7d5Fodw=; b=HCisSa5e+OP5mpRwWy1q1Wvm5fnpsltG0abZeECFXlQJXed8u3ZWE97OVohWIS3zKJnmL2GpVP1hjr74yeX7PuJIFJy9lz+8bO1myPrjWmzjvAB4P1S/UYeYr2fhrmdulUE4dEUECHrnUMIpKBmho0y38DN/V8vdXezPYDst9AaU3HtXvq/FRca9rVy5RIH25eoe0/9h2sPowvxFY+4cMW3B58Lir29Ufbrmm7vNnqpHfnI2Zhx1Eidrvk9fzz5rGDKtGjdEGZGCJYz9twaaI6y4YwdmGRuHg4I1dP+kZ7BYJ5A58o50GbNWxFaJJKSvYT7svcHQJg05uqRMcK8IGA==; X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Hans de Goede , intel-gfx@lists.freedesktop.org, mstaudt@suse.de Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Virus-Scanned: ClamAV using ClamSMTP Getting rotation info is cheap so we can do it on demand. This is done in preparation for the removal of struct drm_fb_helper_crtc. Cc: Hans de Goede Signed-off-by: Noralf Trønnes Acked-by: Daniel Vetter --- Hans, You had this comment inline in restore_fbdev_mode_atomic() the last time I sent this out: We want plane_state->rotation to be set to DRM_MODE_ROTATE_0 in the else case, AFAIK new_plane_state starts with the current state and rotation may have a different value there. Otherwise this looks good to me. Rotation is reset for each plane in the code section above the one I'm changing. Noralf. drivers/gpu/drm/drm_fb_helper.c | 131 ++++++++++++++++---------------- include/drm/drm_fb_helper.h | 8 -- 2 files changed, 65 insertions(+), 74 deletions(-) diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index b91df658db59..e1b147fdd3f9 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -387,6 +387,49 @@ int drm_fb_helper_debug_leave(struct fb_info *info) } EXPORT_SYMBOL(drm_fb_helper_debug_leave); +/* Check if the plane can hw rotate to match panel orientation */ +static bool drm_fb_helper_panel_rotation(struct drm_mode_set *modeset, + unsigned int *rotation) +{ + struct drm_connector *connector = modeset->connectors[0]; + struct drm_plane *plane = modeset->crtc->primary; + u64 valid_mask = 0; + unsigned int i; + + if (!modeset->num_connectors) + return false; + + switch (connector->display_info.panel_orientation) { + case DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP: + *rotation = DRM_MODE_ROTATE_180; + break; + case DRM_MODE_PANEL_ORIENTATION_LEFT_UP: + *rotation = DRM_MODE_ROTATE_90; + break; + case DRM_MODE_PANEL_ORIENTATION_RIGHT_UP: + *rotation = DRM_MODE_ROTATE_270; + break; + default: + *rotation = DRM_MODE_ROTATE_0; + } + + /* + * TODO: support 90 / 270 degree hardware rotation, + * depending on the hardware this may require the framebuffer + * to be in a specific tiling format. + */ + if (*rotation != DRM_MODE_ROTATE_180 || !plane->rotation_property) + return false; + + for (i = 0; i < plane->rotation_property->num_values; i++) + valid_mask |= (1ULL << plane->rotation_property->values[i]); + + if (!(*rotation & valid_mask)) + return false; + + return true; +} + static int restore_fbdev_mode_atomic(struct drm_fb_helper *fb_helper, bool active) { struct drm_device *dev = fb_helper->dev; @@ -427,10 +470,13 @@ static int restore_fbdev_mode_atomic(struct drm_fb_helper *fb_helper, bool activ for (i = 0; i < fb_helper->crtc_count; i++) { struct drm_mode_set *mode_set = &fb_helper->crtc_info[i].mode_set; struct drm_plane *primary = mode_set->crtc->primary; + unsigned int rotation; - /* Cannot fail as we've already gotten the plane state above */ - plane_state = drm_atomic_get_new_plane_state(state, primary); - plane_state->rotation = fb_helper->crtc_info[i].rotation; + if (drm_fb_helper_panel_rotation(mode_set, &rotation)) { + /* Cannot fail as we've already gotten the plane state above */ + plane_state = drm_atomic_get_new_plane_state(state, primary); + plane_state->rotation = rotation; + } ret = __drm_atomic_helper_set_config(mode_set, state); if (ret != 0) @@ -881,7 +927,6 @@ int drm_fb_helper_init(struct drm_device *dev, if (!fb_helper->crtc_info[i].mode_set.connectors) goto out_free; fb_helper->crtc_info[i].mode_set.num_connectors = 0; - fb_helper->crtc_info[i].rotation = DRM_MODE_ROTATE_0; } i = 0; @@ -2500,62 +2545,6 @@ static int drm_pick_crtcs(struct drm_fb_helper *fb_helper, return best_score; } -/* - * This function checks if rotation is necessary because of panel orientation - * and if it is, if it is supported. - * If rotation is necessary and supported, it gets set in fb_crtc.rotation. - * If rotation is necessary but not supported, a DRM_MODE_ROTATE_* flag gets - * or-ed into fb_helper->sw_rotations. In drm_setup_crtcs_fb() we check if only - * one bit is set and then we set fb_info.fbcon_rotate_hint to make fbcon do - * the unsupported rotation. - */ -static void drm_setup_crtc_rotation(struct drm_fb_helper *fb_helper, - struct drm_fb_helper_crtc *fb_crtc, - struct drm_connector *connector) -{ - struct drm_plane *plane = fb_crtc->mode_set.crtc->primary; - uint64_t valid_mask = 0; - int i, rotation; - - fb_crtc->rotation = DRM_MODE_ROTATE_0; - - switch (connector->display_info.panel_orientation) { - case DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP: - rotation = DRM_MODE_ROTATE_180; - break; - case DRM_MODE_PANEL_ORIENTATION_LEFT_UP: - rotation = DRM_MODE_ROTATE_90; - break; - case DRM_MODE_PANEL_ORIENTATION_RIGHT_UP: - rotation = DRM_MODE_ROTATE_270; - break; - default: - rotation = DRM_MODE_ROTATE_0; - } - - /* - * TODO: support 90 / 270 degree hardware rotation, - * depending on the hardware this may require the framebuffer - * to be in a specific tiling format. - */ - if (rotation != DRM_MODE_ROTATE_180 || !plane->rotation_property) { - fb_helper->sw_rotations |= rotation; - return; - } - - for (i = 0; i < plane->rotation_property->num_values; i++) - valid_mask |= (1ULL << plane->rotation_property->values[i]); - - if (!(rotation & valid_mask)) { - fb_helper->sw_rotations |= rotation; - return; - } - - fb_crtc->rotation = rotation; - /* Rotating in hardware, fbcon should not rotate */ - fb_helper->sw_rotations |= DRM_MODE_ROTATE_0; -} - static void drm_setup_crtcs(struct drm_fb_helper *fb_helper, u32 width, u32 height) { @@ -2615,7 +2604,6 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper, drm_fb_helper_modeset_release(fb_helper, &fb_helper->crtc_info[i].mode_set); - fb_helper->sw_rotations = 0; drm_fb_helper_for_each_connector(fb_helper, i) { struct drm_display_mode *mode = modes[i]; struct drm_fb_helper_crtc *fb_crtc = crtcs[i]; @@ -2635,7 +2623,6 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper, modeset->mode = drm_mode_duplicate(dev, fb_crtc->desired_mode); drm_connector_get(connector); - drm_setup_crtc_rotation(fb_helper, fb_crtc, connector); modeset->connectors[modeset->num_connectors++] = connector; modeset->x = offset->x; modeset->y = offset->y; @@ -2658,11 +2645,23 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper, static void drm_setup_crtcs_fb(struct drm_fb_helper *fb_helper) { struct fb_info *info = fb_helper->fbdev; + unsigned int rotation, sw_rotations = 0; int i; - for (i = 0; i < fb_helper->crtc_count; i++) - if (fb_helper->crtc_info[i].mode_set.num_connectors) - fb_helper->crtc_info[i].mode_set.fb = fb_helper->fb; + for (i = 0; i < fb_helper->crtc_count; i++) { + struct drm_mode_set *modeset = &fb_helper->crtc_info[i].mode_set; + + if (!modeset->num_connectors) + continue; + + modeset->fb = fb_helper->fb; + + if (drm_fb_helper_panel_rotation(modeset, &rotation)) + /* Rotating in hardware, fbcon should not rotate */ + sw_rotations |= DRM_MODE_ROTATE_0; + else + sw_rotations |= rotation; + } mutex_lock(&fb_helper->dev->mode_config.mutex); drm_fb_helper_for_each_connector(fb_helper, i) { @@ -2678,7 +2677,7 @@ static void drm_setup_crtcs_fb(struct drm_fb_helper *fb_helper) } mutex_unlock(&fb_helper->dev->mode_config.mutex); - switch (fb_helper->sw_rotations) { + switch (sw_rotations) { case DRM_MODE_ROTATE_0: info->fbcon_rotate_hint = FB_ROTATE_UR; break; diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h index bb9acea61369..cff1aa222886 100644 --- a/include/drm/drm_fb_helper.h +++ b/include/drm/drm_fb_helper.h @@ -50,7 +50,6 @@ struct drm_fb_helper_crtc { struct drm_mode_set mode_set; struct drm_display_mode *desired_mode; int x, y; - int rotation; }; /** @@ -175,13 +174,6 @@ struct drm_fb_helper { struct drm_fb_helper_crtc *crtc_info; int connector_count; int connector_info_alloc_count; - /** - * @sw_rotations: - * Bitmask of all rotations requested for panel-orientation which - * could not be handled in hardware. If only one bit is set - * fbdev->fbcon_rotate_hint gets set to the requested rotation. - */ - int sw_rotations; /** * @connector_info: * From patchwork Tue Mar 26 17:55:35 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Noralf_Tr=C3=B8nnes?= X-Patchwork-Id: 10871819 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 603D51669 for ; Tue, 26 Mar 2019 17:56:27 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 4E9B628D54 for ; Tue, 26 Mar 2019 17:56:27 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 4302D28D6A; Tue, 26 Mar 2019 17:56:27 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED autolearn=unavailable version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 08EEF28D54 for ; Tue, 26 Mar 2019 17:56:27 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 8B3396E070; Tue, 26 Mar 2019 17:56:08 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from smtp.domeneshop.no (smtp.domeneshop.no [IPv6:2a01:5b40:0:3005::1]) by gabe.freedesktop.org (Postfix) with ESMTPS id A962D6E04C; Tue, 26 Mar 2019 17:56:05 +0000 (UTC) Received: from 211.81-166-168.customer.lyse.net ([81.166.168.211]:46322 helo=localhost.localdomain) by smtp.domeneshop.no with esmtpsa (TLS1.2:ECDHE_RSA_AES_128_CBC_SHA1:128) (Exim 4.84_2) (envelope-from ) id 1h8qIt-0006Mj-Un; Tue, 26 Mar 2019 18:56:03 +0100 From: =?utf-8?q?Noralf_Tr=C3=B8nnes?= To: dri-devel@lists.freedesktop.org Subject: [PATCH 05/16] drm/fb-helper: Remove drm_fb_helper_crtc->{x, y, desired_mode} Date: Tue, 26 Mar 2019 18:55:35 +0100 Message-Id: <20190326175546.18126-6-noralf@tronnes.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190326175546.18126-1-noralf@tronnes.org> References: <20190326175546.18126-1-noralf@tronnes.org> MIME-Version: 1.0 X-Mailman-Original-DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=tronnes.org; s=ds201810; h=Content-Transfer-Encoding:Content-Type:MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From; bh=TIhmZXUBJjhDjxlMqaG8IGV9XwhM25lru1KikReFF0Y=; b=hSlMLWpJ0i/vbaUUZUub6P1CB85/01uFIHhHCp/PSrbpA36ltotkZaR3hMsDe6AT5uEr6s7Ac/ki5SpRiNj9iIEBRILseDdgld8v8HY3ILLXbBlgGaOlIjiIvwWxGqetjUfJfZHh3EIyQqD1Xw3hW7gAYn3bTH6hiMazFK0l0YnGAqNC7dkN21dNEWUED4R/jiRrSwhWGp2SzqrPYFFblm77WU4hMCUzs5HIwoR0EeU42DPxJMOGjl4TgQxj1hRrBIE3denJ//btD5cwPdKRNWKOb5kUG1DRV9s7egiLSfUQVRb4LG2Zqr4pzlWAEvywV5HbYU3fHdHbKf3sg7BjEg==; X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: intel-gfx@lists.freedesktop.org, mstaudt@suse.de Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Virus-Scanned: ClamAV using ClamSMTP The values are already present in the modeset. This is done in preparation for the removal of struct drm_fb_helper_crtc. Signed-off-by: Noralf Trønnes Reviewed-by: Daniel Vetter --- drivers/gpu/drm/drm_fb_helper.c | 12 ++++-------- include/drm/drm_fb_helper.h | 2 -- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index e1b147fdd3f9..36310901e935 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -2023,16 +2023,16 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper, */ bool lastv = true, lasth = true; - desired_mode = fb_helper->crtc_info[i].desired_mode; mode_set = &fb_helper->crtc_info[i].mode_set; + desired_mode = mode_set->mode; if (!desired_mode) continue; crtc_count++; - x = fb_helper->crtc_info[i].x; - y = fb_helper->crtc_info[i].y; + x = mode_set->x; + y = mode_set->y; sizes.surface_width = max_t(u32, desired_mode->hdisplay + x, sizes.surface_width); sizes.surface_height = max_t(u32, desired_mode->vdisplay + y, sizes.surface_height); @@ -2617,11 +2617,7 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper, DRM_DEBUG_KMS("desired mode %s set on crtc %d (%d,%d)\n", mode->name, fb_crtc->mode_set.crtc->base.id, offset->x, offset->y); - fb_crtc->desired_mode = mode; - fb_crtc->x = offset->x; - fb_crtc->y = offset->y; - modeset->mode = drm_mode_duplicate(dev, - fb_crtc->desired_mode); + modeset->mode = drm_mode_duplicate(dev, mode); drm_connector_get(connector); modeset->connectors[modeset->num_connectors++] = connector; modeset->x = offset->x; diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h index cff1aa222886..7a095964f6b2 100644 --- a/include/drm/drm_fb_helper.h +++ b/include/drm/drm_fb_helper.h @@ -48,8 +48,6 @@ struct drm_fb_offset { struct drm_fb_helper_crtc { struct drm_mode_set mode_set; - struct drm_display_mode *desired_mode; - int x, y; }; /** From patchwork Tue Mar 26 17:55:36 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Noralf_Tr=C3=B8nnes?= X-Patchwork-Id: 10871835 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id D54AF922 for ; Tue, 26 Mar 2019 17:56:37 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C218E28D54 for ; Tue, 26 Mar 2019 17:56:37 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id B68C128D66; Tue, 26 Mar 2019 17:56:37 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED autolearn=unavailable version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id DC8D928D54 for ; Tue, 26 Mar 2019 17:56:36 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id E0BA56E071; Tue, 26 Mar 2019 17:56:20 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from smtp.domeneshop.no (smtp.domeneshop.no [IPv6:2a01:5b40:0:3005::1]) by gabe.freedesktop.org (Postfix) with ESMTPS id 857156E06C; Tue, 26 Mar 2019 17:56:08 +0000 (UTC) Received: from 211.81-166-168.customer.lyse.net ([81.166.168.211]:46322 helo=localhost.localdomain) by smtp.domeneshop.no with esmtpsa (TLS1.2:ECDHE_RSA_AES_128_CBC_SHA1:128) (Exim 4.84_2) (envelope-from ) id 1h8qIw-0006Mj-3L; Tue, 26 Mar 2019 18:56:06 +0100 From: =?utf-8?q?Noralf_Tr=C3=B8nnes?= To: dri-devel@lists.freedesktop.org Subject: [PATCH 06/16] drm/i915/fbdev: Move intel_fb_initial_config() to fbdev helper Date: Tue, 26 Mar 2019 18:55:36 +0100 Message-Id: <20190326175546.18126-7-noralf@tronnes.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190326175546.18126-1-noralf@tronnes.org> References: <20190326175546.18126-1-noralf@tronnes.org> MIME-Version: 1.0 X-Mailman-Original-DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=tronnes.org; s=ds201810; h=Content-Transfer-Encoding:Content-Type:MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From; bh=z72ufDsSc3B/+8cqKZfzG4DUMyWjMVJ8WvjRyAX3ZjI=; b=dHByBq5i/jobauWfpXFC78Uz1R83e2u46i0NHKSS73m/t2eEhhZCqmfEFkChNjg9lTwbCOrne/iQg1L8S853Dk6MEboJOIjDL/vnWBFB3BAewfK8WKj7SUgoLALIWWyuY9suT7yMgUIGQglEuwU8+4UKZPMOhxHdd4nrs3LJ5wI/dVyWuXIqrIaP3Nj1sEklrbZsUHC8QixsPGBjRisbeOgedWJxFeOOHBOkAIurCE+YPPM05Z5ee6MhIHehF21f9Y+WmI5MZMKQgApbVHdeE7sw1VVLDJcE3NTFERSsYNm53QVzNV5/4WjQJy8hXbc/7iFl34XNTXJA67NnzHqU+Q==; X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Daniel Vetter , intel-gfx@lists.freedesktop.org, mstaudt@suse.de, Rodrigo Vivi Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Virus-Scanned: ClamAV using ClamSMTP It is generic code and having it in the helper will let other drivers benefit from it. One change was necessary assuming this to be true: INTEL_INFO(dev_priv)->num_pipes == dev->mode_config.num_crtc Suggested-by: Daniel Vetter Cc: Jani Nikula Cc: Joonas Lahtinen Cc: Rodrigo Vivi Cc: intel-gfx@lists.freedesktop.org Signed-off-by: Noralf Trønnes Reviewed-by: Jani Nikula Acked-by: Jani Nikula --- drivers/gpu/drm/drm_fb_helper.c | 194 ++++++++++++++++++++++++- drivers/gpu/drm/i915/intel_fbdev.c | 218 ----------------------------- include/drm/drm_fb_helper.h | 23 --- 3 files changed, 190 insertions(+), 245 deletions(-) diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 36310901e935..634f4dcf0c41 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -2545,6 +2545,194 @@ static int drm_pick_crtcs(struct drm_fb_helper *fb_helper, return best_score; } +static struct drm_fb_helper_crtc * +drm_fb_helper_crtc(struct drm_fb_helper *fb_helper, struct drm_crtc *crtc) +{ + int i; + + for (i = 0; i < fb_helper->crtc_count; i++) + if (fb_helper->crtc_info[i].mode_set.crtc == crtc) + return &fb_helper->crtc_info[i]; + + return NULL; +} + +/* Try to read the BIOS display configuration and use it for the initial config */ +static bool drm_fb_helper_firmware_config(struct drm_fb_helper *fb_helper, + struct drm_fb_helper_crtc **crtcs, + struct drm_display_mode **modes, + struct drm_fb_offset *offsets, + bool *enabled, int width, int height) +{ + struct drm_device *dev = fb_helper->dev; + unsigned int count = min(fb_helper->connector_count, BITS_PER_LONG); + unsigned long conn_configured, conn_seq; + int i, j; + bool *save_enabled; + bool fallback = true, ret = true; + int num_connectors_enabled = 0; + int num_connectors_detected = 0; + struct drm_modeset_acquire_ctx ctx; + + save_enabled = kcalloc(count, sizeof(bool), GFP_KERNEL); + if (!save_enabled) + return false; + + drm_modeset_acquire_init(&ctx, 0); + + while (drm_modeset_lock_all_ctx(dev, &ctx) != 0) + drm_modeset_backoff(&ctx); + + memcpy(save_enabled, enabled, count); + conn_seq = GENMASK(count - 1, 0); + conn_configured = 0; +retry: + for (i = 0; i < count; i++) { + struct drm_fb_helper_connector *fb_conn; + struct drm_connector *connector; + struct drm_encoder *encoder; + struct drm_fb_helper_crtc *new_crtc; + + fb_conn = fb_helper->connector_info[i]; + connector = fb_conn->connector; + + if (conn_configured & BIT(i)) + continue; + + /* First pass, only consider tiled connectors */ + if (conn_seq == GENMASK(count - 1, 0) && !connector->has_tile) + continue; + + if (connector->status == connector_status_connected) + num_connectors_detected++; + + if (!enabled[i]) { + DRM_DEBUG_KMS("connector %s not enabled, skipping\n", + connector->name); + conn_configured |= BIT(i); + continue; + } + + if (connector->force == DRM_FORCE_OFF) { + DRM_DEBUG_KMS("connector %s is disabled by user, skipping\n", + connector->name); + enabled[i] = false; + continue; + } + + encoder = connector->state->best_encoder; + if (!encoder || WARN_ON(!connector->state->crtc)) { + if (connector->force > DRM_FORCE_OFF) + goto bail; + + DRM_DEBUG_KMS("connector %s has no encoder or crtc, skipping\n", + connector->name); + enabled[i] = false; + conn_configured |= BIT(i); + continue; + } + + num_connectors_enabled++; + + new_crtc = drm_fb_helper_crtc(fb_helper, connector->state->crtc); + + /* + * Make sure we're not trying to drive multiple connectors + * with a single CRTC, since our cloning support may not + * match the BIOS. + */ + for (j = 0; j < count; j++) { + if (crtcs[j] == new_crtc) { + DRM_DEBUG_KMS("fallback: cloned configuration\n"); + goto bail; + } + } + + DRM_DEBUG_KMS("looking for cmdline mode on connector %s\n", + connector->name); + + /* go for command line mode first */ + modes[i] = drm_pick_cmdline_mode(fb_conn); + + /* try for preferred next */ + if (!modes[i]) { + DRM_DEBUG_KMS("looking for preferred mode on connector %s %d\n", + connector->name, connector->has_tile); + modes[i] = drm_has_preferred_mode(fb_conn, width, + height); + } + + /* No preferred mode marked by the EDID? Are there any modes? */ + if (!modes[i] && !list_empty(&connector->modes)) { + DRM_DEBUG_KMS("using first mode listed on connector %s\n", + connector->name); + modes[i] = list_first_entry(&connector->modes, + struct drm_display_mode, + head); + } + + /* last resort: use current mode */ + if (!modes[i]) { + /* + * IMPORTANT: We want to use the adjusted mode (i.e. + * after the panel fitter upscaling) as the initial + * config, not the input mode, which is what crtc->mode + * usually contains. But since our current + * code puts a mode derived from the post-pfit timings + * into crtc->mode this works out correctly. + * + * This is crtc->mode and not crtc->state->mode for the + * fastboot check to work correctly. + */ + DRM_DEBUG_KMS("looking for current mode on connector %s\n", + connector->name); + modes[i] = &connector->state->crtc->mode; + } + crtcs[i] = new_crtc; + + DRM_DEBUG_KMS("connector %s on [CRTC:%d:%s]: %dx%d%s\n", + connector->name, + connector->state->crtc->base.id, + connector->state->crtc->name, + modes[i]->hdisplay, modes[i]->vdisplay, + modes[i]->flags & DRM_MODE_FLAG_INTERLACE ? "i" : ""); + + fallback = false; + conn_configured |= BIT(i); + } + + if (conn_configured != conn_seq) { /* repeat until no more are found */ + conn_seq = conn_configured; + goto retry; + } + + /* + * If the BIOS didn't enable everything it could, fall back to have the + * same user experiencing of lighting up as much as possible like the + * fbdev helper library. + */ + if (num_connectors_enabled != num_connectors_detected && + num_connectors_enabled < dev->mode_config.num_crtc) { + DRM_DEBUG_KMS("fallback: Not all outputs enabled\n"); + DRM_DEBUG_KMS("Enabled: %i, detected: %i\n", num_connectors_enabled, + num_connectors_detected); + fallback = true; + } + + if (fallback) { +bail: + DRM_DEBUG_KMS("Not using firmware configuration\n"); + memcpy(enabled, save_enabled, count); + ret = false; + } + + drm_modeset_drop_locks(&ctx); + drm_modeset_acquire_fini(&ctx); + + kfree(save_enabled); + return ret; +} + static void drm_setup_crtcs(struct drm_fb_helper *fb_helper, u32 width, u32 height) { @@ -2577,10 +2765,8 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper, DRM_DEBUG_KMS("No connectors reported connected with modes\n"); drm_enable_connectors(fb_helper, enabled); - if (!(fb_helper->funcs->initial_config && - fb_helper->funcs->initial_config(fb_helper, crtcs, modes, - offsets, - enabled, width, height))) { + if (!drm_fb_helper_firmware_config(fb_helper, crtcs, modes, offsets, + enabled, width, height)) { memset(modes, 0, fb_helper->connector_count*sizeof(modes[0])); memset(crtcs, 0, fb_helper->connector_count*sizeof(crtcs[0])); memset(offsets, 0, fb_helper->connector_count*sizeof(offsets[0])); diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c index e8f694b57b8a..20e91600cf71 100644 --- a/drivers/gpu/drm/i915/intel_fbdev.c +++ b/drivers/gpu/drm/i915/intel_fbdev.c @@ -292,225 +292,7 @@ static int intelfb_create(struct drm_fb_helper *helper, return ret; } -static struct drm_fb_helper_crtc * -intel_fb_helper_crtc(struct drm_fb_helper *fb_helper, struct drm_crtc *crtc) -{ - int i; - - for (i = 0; i < fb_helper->crtc_count; i++) - if (fb_helper->crtc_info[i].mode_set.crtc == crtc) - return &fb_helper->crtc_info[i]; - - return NULL; -} - -/* - * Try to read the BIOS display configuration and use it for the initial - * fb configuration. - * - * The BIOS or boot loader will generally create an initial display - * configuration for us that includes some set of active pipes and displays. - * This routine tries to figure out which pipes and connectors are active - * and stuffs them into the crtcs and modes array given to us by the - * drm_fb_helper code. - * - * The overall sequence is: - * intel_fbdev_init - from driver load - * intel_fbdev_init_bios - initialize the intel_fbdev using BIOS data - * drm_fb_helper_init - build fb helper structs - * drm_fb_helper_single_add_all_connectors - more fb helper structs - * intel_fbdev_initial_config - apply the config - * drm_fb_helper_initial_config - call ->probe then register_framebuffer() - * drm_setup_crtcs - build crtc config for fbdev - * intel_fb_initial_config - find active connectors etc - * drm_fb_helper_single_fb_probe - set up fbdev - * intelfb_create - re-use or alloc fb, build out fbdev structs - * - * Note that we don't make special consideration whether we could actually - * switch to the selected modes without a full modeset. E.g. when the display - * is in VGA mode we need to recalculate watermarks and set a new high-res - * framebuffer anyway. - */ -static bool intel_fb_initial_config(struct drm_fb_helper *fb_helper, - struct drm_fb_helper_crtc **crtcs, - struct drm_display_mode **modes, - struct drm_fb_offset *offsets, - bool *enabled, int width, int height) -{ - struct drm_i915_private *dev_priv = to_i915(fb_helper->dev); - unsigned int count = min(fb_helper->connector_count, BITS_PER_LONG); - unsigned long conn_configured, conn_seq; - int i, j; - bool *save_enabled; - bool fallback = true, ret = true; - int num_connectors_enabled = 0; - int num_connectors_detected = 0; - struct drm_modeset_acquire_ctx ctx; - - save_enabled = kcalloc(count, sizeof(bool), GFP_KERNEL); - if (!save_enabled) - return false; - - drm_modeset_acquire_init(&ctx, 0); - - while (drm_modeset_lock_all_ctx(fb_helper->dev, &ctx) != 0) - drm_modeset_backoff(&ctx); - - memcpy(save_enabled, enabled, count); - conn_seq = GENMASK(count - 1, 0); - conn_configured = 0; -retry: - for (i = 0; i < count; i++) { - struct drm_fb_helper_connector *fb_conn; - struct drm_connector *connector; - struct drm_encoder *encoder; - struct drm_fb_helper_crtc *new_crtc; - - fb_conn = fb_helper->connector_info[i]; - connector = fb_conn->connector; - - if (conn_configured & BIT(i)) - continue; - - /* First pass, only consider tiled connectors */ - if (conn_seq == GENMASK(count - 1, 0) && !connector->has_tile) - continue; - - if (connector->status == connector_status_connected) - num_connectors_detected++; - - if (!enabled[i]) { - DRM_DEBUG_KMS("connector %s not enabled, skipping\n", - connector->name); - conn_configured |= BIT(i); - continue; - } - - if (connector->force == DRM_FORCE_OFF) { - DRM_DEBUG_KMS("connector %s is disabled by user, skipping\n", - connector->name); - enabled[i] = false; - continue; - } - - encoder = connector->state->best_encoder; - if (!encoder || WARN_ON(!connector->state->crtc)) { - if (connector->force > DRM_FORCE_OFF) - goto bail; - - DRM_DEBUG_KMS("connector %s has no encoder or crtc, skipping\n", - connector->name); - enabled[i] = false; - conn_configured |= BIT(i); - continue; - } - - num_connectors_enabled++; - - new_crtc = intel_fb_helper_crtc(fb_helper, - connector->state->crtc); - - /* - * Make sure we're not trying to drive multiple connectors - * with a single CRTC, since our cloning support may not - * match the BIOS. - */ - for (j = 0; j < count; j++) { - if (crtcs[j] == new_crtc) { - DRM_DEBUG_KMS("fallback: cloned configuration\n"); - goto bail; - } - } - - DRM_DEBUG_KMS("looking for cmdline mode on connector %s\n", - connector->name); - - /* go for command line mode first */ - modes[i] = drm_pick_cmdline_mode(fb_conn); - - /* try for preferred next */ - if (!modes[i]) { - DRM_DEBUG_KMS("looking for preferred mode on connector %s %d\n", - connector->name, connector->has_tile); - modes[i] = drm_has_preferred_mode(fb_conn, width, - height); - } - - /* No preferred mode marked by the EDID? Are there any modes? */ - if (!modes[i] && !list_empty(&connector->modes)) { - DRM_DEBUG_KMS("using first mode listed on connector %s\n", - connector->name); - modes[i] = list_first_entry(&connector->modes, - struct drm_display_mode, - head); - } - - /* last resort: use current mode */ - if (!modes[i]) { - /* - * IMPORTANT: We want to use the adjusted mode (i.e. - * after the panel fitter upscaling) as the initial - * config, not the input mode, which is what crtc->mode - * usually contains. But since our current - * code puts a mode derived from the post-pfit timings - * into crtc->mode this works out correctly. - * - * This is crtc->mode and not crtc->state->mode for the - * fastboot check to work correctly. crtc_state->mode has - * I915_MODE_FLAG_INHERITED, which we clear to force check - * state. - */ - DRM_DEBUG_KMS("looking for current mode on connector %s\n", - connector->name); - modes[i] = &connector->state->crtc->mode; - } - crtcs[i] = new_crtc; - - DRM_DEBUG_KMS("connector %s on [CRTC:%d:%s]: %dx%d%s\n", - connector->name, - connector->state->crtc->base.id, - connector->state->crtc->name, - modes[i]->hdisplay, modes[i]->vdisplay, - modes[i]->flags & DRM_MODE_FLAG_INTERLACE ? "i" :""); - - fallback = false; - conn_configured |= BIT(i); - } - - if (conn_configured != conn_seq) { /* repeat until no more are found */ - conn_seq = conn_configured; - goto retry; - } - - /* - * If the BIOS didn't enable everything it could, fall back to have the - * same user experiencing of lighting up as much as possible like the - * fbdev helper library. - */ - if (num_connectors_enabled != num_connectors_detected && - num_connectors_enabled < INTEL_INFO(dev_priv)->num_pipes) { - DRM_DEBUG_KMS("fallback: Not all outputs enabled\n"); - DRM_DEBUG_KMS("Enabled: %i, detected: %i\n", num_connectors_enabled, - num_connectors_detected); - fallback = true; - } - - if (fallback) { -bail: - DRM_DEBUG_KMS("Not using firmware configuration\n"); - memcpy(enabled, save_enabled, count); - ret = false; - } - - drm_modeset_drop_locks(&ctx); - drm_modeset_acquire_fini(&ctx); - - kfree(save_enabled); - return ret; -} - static const struct drm_fb_helper_funcs intel_fb_helper_funcs = { - .initial_config = intel_fb_initial_config, .fb_probe = intelfb_create, }; diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h index 7a095964f6b2..bca4b34dc93b 100644 --- a/include/drm/drm_fb_helper.h +++ b/include/drm/drm_fb_helper.h @@ -100,29 +100,6 @@ struct drm_fb_helper_funcs { */ int (*fb_probe)(struct drm_fb_helper *helper, struct drm_fb_helper_surface_size *sizes); - - /** - * @initial_config: - * - * Driver callback to setup an initial fbdev display configuration. - * Drivers can use this callback to tell the fbdev emulation what the - * preferred initial configuration is. This is useful to implement - * smooth booting where the fbdev (and subsequently all userspace) never - * changes the mode, but always inherits the existing configuration. - * - * This callback is optional. - * - * RETURNS: - * - * The driver should return true if a suitable initial configuration has - * been filled out and false when the fbdev helper should fall back to - * the default probing logic. - */ - bool (*initial_config)(struct drm_fb_helper *fb_helper, - struct drm_fb_helper_crtc **crtcs, - struct drm_display_mode **modes, - struct drm_fb_offset *offsets, - bool *enabled, int width, int height); }; struct drm_fb_helper_connector { From patchwork Tue Mar 26 17:55:37 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Noralf_Tr=C3=B8nnes?= X-Patchwork-Id: 10871833 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id B403C922 for ; Tue, 26 Mar 2019 17:56:36 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A066028D54 for ; Tue, 26 Mar 2019 17:56:36 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 93FAB28D66; Tue, 26 Mar 2019 17:56:36 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED autolearn=unavailable version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 3E42D28D54 for ; Tue, 26 Mar 2019 17:56:35 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 185AF6E077; Tue, 26 Mar 2019 17:56:21 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from smtp.domeneshop.no (smtp.domeneshop.no [IPv6:2a01:5b40:0:3005::1]) by gabe.freedesktop.org (Postfix) with ESMTPS id 639B36E06A; Tue, 26 Mar 2019 17:56:08 +0000 (UTC) Received: from 211.81-166-168.customer.lyse.net ([81.166.168.211]:46322 helo=localhost.localdomain) by smtp.domeneshop.no with esmtpsa (TLS1.2:ECDHE_RSA_AES_128_CBC_SHA1:128) (Exim 4.84_2) (envelope-from ) id 1h8qIw-0006Mj-B0; Tue, 26 Mar 2019 18:56:06 +0100 From: =?utf-8?q?Noralf_Tr=C3=B8nnes?= To: dri-devel@lists.freedesktop.org Subject: [PATCH 07/16] drm/fb-helper: Remove drm_fb_helper_crtc Date: Tue, 26 Mar 2019 18:55:37 +0100 Message-Id: <20190326175546.18126-8-noralf@tronnes.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190326175546.18126-1-noralf@tronnes.org> References: <20190326175546.18126-1-noralf@tronnes.org> MIME-Version: 1.0 X-Mailman-Original-DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=tronnes.org; s=ds201810; h=Content-Transfer-Encoding:Content-Type:MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From; bh=YvRCGjpIAy+GzW8jhoE52FoDunZa5it2Ey9vcDe+qMA=; b=soVYIJ7xY2eWjVnUp7ELsIOKSoshhTdWbP7UESRSdgCR1ZfCAjw6/jaxo2QLZ5pHz8v7oV+NrdXXwUprD3WQfTtdRE1nSd8j1WZLQd/0+oK7Pt4KH5bmW15Bw4gEpARpxrxfPwIg1H77d938HsfOiCPeqbivUJV22NHMySU4zTrpsH9kUjHgGLjIGCql8fA8VhMNgJgxt/Z6QiZaomX/yXGW3X9VkOUkDwHF+x58jZCflDIctvJBuUtVHevCCwBBdVwWWWSeFsuud5r/LQlGegXaHelDlO3UOOcaZkUlpG/ohbOli9Uwy3juSTpZeiWa27Ef6JD1LpR3mNy6m8QHlQ==; X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: intel-gfx@lists.freedesktop.org, mstaudt@suse.de Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Virus-Scanned: ClamAV using ClamSMTP It now only contains the modeset so use that directly instead. The modeset code will be moved to drm_client, so add code there. The modeset connector array size is hardcoded for the cloned case to avoid having to pass in a value from the driver. A value of 8 is chosen to err on the safe side. This means that the max connector argument for drm_fb_helper_init() and drm_fb_helper_fbdev_setup() isn't used anymore, a todo entry for this is added. Signed-off-by: Noralf Trønnes --- Documentation/gpu/todo.rst | 7 + drivers/gpu/drm/drm_client.c | 93 ++++++++++++ drivers/gpu/drm/drm_fb_helper.c | 262 +++++++++++--------------------- include/drm/drm_client.h | 16 ++ include/drm/drm_fb_helper.h | 14 +- 5 files changed, 207 insertions(+), 185 deletions(-) diff --git a/Documentation/gpu/todo.rst b/Documentation/gpu/todo.rst index 1528ad2d598b..8fa08b5feab7 100644 --- a/Documentation/gpu/todo.rst +++ b/Documentation/gpu/todo.rst @@ -300,6 +300,13 @@ it to use drm_mode_hsync() instead. Contact: Sean Paul +drm_fb_helper cleanup tasks +--------------------------- + +- The max connector argument for drm_fb_helper_init() and + drm_fb_helper_fbdev_setup() isn't used anymore and can be removed. + + Core refactorings ================= diff --git a/drivers/gpu/drm/drm_client.c b/drivers/gpu/drm/drm_client.c index 9b2bd28dde0a..84f848f21679 100644 --- a/drivers/gpu/drm/drm_client.c +++ b/drivers/gpu/drm/drm_client.c @@ -392,6 +392,99 @@ void drm_client_framebuffer_delete(struct drm_client_buffer *buffer) } EXPORT_SYMBOL(drm_client_framebuffer_delete); +/** + * drm_client_modesets_create() - Create modeset array + * @dev: DRM device + * + * This function creates a &drm_mode_set array, one entry per CRTC. + * + * Returns: + * A &drm_mode_set array or an error pointer on allocation failure. + */ +struct drm_mode_set *drm_client_modesets_create(struct drm_device *dev) +{ + unsigned int num_crtc = dev->mode_config.num_crtc; + struct drm_mode_set *modeset, *modesets; + unsigned int max_connector_count = 1; + struct drm_crtc *crtc; + unsigned int i = 0; + + /* Add terminating zero entry to enable index less iteration */ + modesets = kcalloc(num_crtc + 1, sizeof(*modesets), GFP_KERNEL); + if (!modesets) + return ERR_PTR(-ENOMEM); + + drm_for_each_crtc(crtc, dev) + modesets[i++].crtc = crtc; + + /* Cloning is only supported in the single crtc case. */ + if (num_crtc == 1) + max_connector_count = DRM_CLIENT_MAX_CLONED_CONNECTORS; + + drm_client_for_each_modeset(modeset, modesets) { + modeset->connectors = kcalloc(max_connector_count, + sizeof(*modeset->connectors), GFP_KERNEL); + if (!modeset->connectors) + goto err_free; + } + + return modesets; + +err_free: + drm_client_modesets_release(modesets); + + return ERR_PTR(-ENOMEM); +} +EXPORT_SYMBOL(drm_client_modesets_create); + +/** + * drm_client_modesets_release() - Free modesets + * @modesets: Modeset array (can be NULL or error pointer) + * + * This function destroys any attached display modes, puts connectors and frees + * the modeset array. + */ +void drm_client_modesets_release(struct drm_mode_set *modesets) +{ + struct drm_mode_set *modeset; + unsigned int i; + + if (IS_ERR_OR_NULL(modesets)) + return; + + drm_client_for_each_modeset(modeset, modesets) { + drm_mode_destroy(modeset->crtc->dev, modeset->mode); + + for (i = 0; i < modeset->num_connectors; i++) + drm_connector_put(modeset->connectors[i]); + kfree(modeset->connectors); + } + kfree(modesets); +} +EXPORT_SYMBOL(drm_client_modesets_release); + +/** + * drm_client_find_modeset() - Find modeset matching a CRTC + * @modesets: Modeset array + * @crtc: CRTC + * + * This function looks up the modeset connected to @crtc. + * + * Returns: + * A &drm_mode_set or NULL. + */ +struct drm_mode_set *drm_client_find_modeset(struct drm_mode_set *modesets, struct drm_crtc *crtc) +{ + struct drm_mode_set *modeset; + + drm_client_for_each_modeset(modeset, modesets) + if (modeset->crtc == crtc) + return modeset; + + return NULL; +} +EXPORT_SYMBOL(drm_client_find_modeset); + #ifdef CONFIG_DEBUG_FS static int drm_client_debugfs_internal_clients(struct seq_file *m, void *data) { diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 634f4dcf0c41..85bea51e2072 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -316,13 +316,10 @@ int drm_fb_helper_debug_enter(struct fb_info *info) { struct drm_fb_helper *helper = info->par; const struct drm_crtc_helper_funcs *funcs; - int i; + struct drm_mode_set *mode_set; list_for_each_entry(helper, &kernel_fb_helper_list, kernel_fb_list) { - for (i = 0; i < helper->crtc_count; i++) { - struct drm_mode_set *mode_set = - &helper->crtc_info[i].mode_set; - + drm_client_for_each_modeset(mode_set, helper->modesets) { if (!mode_set->crtc->enabled) continue; @@ -354,12 +351,10 @@ int drm_fb_helper_debug_leave(struct fb_info *info) struct drm_fb_helper *helper = info->par; struct drm_crtc *crtc; const struct drm_crtc_helper_funcs *funcs; + struct drm_mode_set *mode_set; struct drm_framebuffer *fb; - int i; - - for (i = 0; i < helper->crtc_count; i++) { - struct drm_mode_set *mode_set = &helper->crtc_info[i].mode_set; + drm_client_for_each_modeset(mode_set, helper->modesets) { crtc = mode_set->crtc; if (drm_drv_uses_atomic_modeset(crtc->dev)) continue; @@ -436,8 +431,9 @@ static int restore_fbdev_mode_atomic(struct drm_fb_helper *fb_helper, bool activ struct drm_plane_state *plane_state; struct drm_plane *plane; struct drm_atomic_state *state; - int i, ret; struct drm_modeset_acquire_ctx ctx; + struct drm_mode_set *mode_set; + int ret; drm_modeset_acquire_init(&ctx, 0); @@ -467,8 +463,7 @@ static int restore_fbdev_mode_atomic(struct drm_fb_helper *fb_helper, bool activ goto out_state; } - for (i = 0; i < fb_helper->crtc_count; i++) { - struct drm_mode_set *mode_set = &fb_helper->crtc_info[i].mode_set; + drm_client_for_each_modeset(mode_set, fb_helper->modesets) { struct drm_plane *primary = mode_set->crtc->primary; unsigned int rotation; @@ -517,8 +512,9 @@ static int restore_fbdev_mode_atomic(struct drm_fb_helper *fb_helper, bool activ static int restore_fbdev_mode_legacy(struct drm_fb_helper *fb_helper) { struct drm_device *dev = fb_helper->dev; + struct drm_mode_set *mode_set; struct drm_plane *plane; - int i, ret = 0; + int ret = 0; drm_modeset_lock_all(fb_helper->dev); drm_for_each_plane(plane, dev) { @@ -531,8 +527,7 @@ static int restore_fbdev_mode_legacy(struct drm_fb_helper *fb_helper) DRM_MODE_ROTATE_0); } - for (i = 0; i < fb_helper->crtc_count; i++) { - struct drm_mode_set *mode_set = &fb_helper->crtc_info[i].mode_set; + drm_client_for_each_modeset(mode_set, fb_helper->modesets) { struct drm_crtc *crtc = mode_set->crtc; if (crtc->funcs->cursor_set2) { @@ -687,12 +682,10 @@ static void dpms_legacy(struct drm_fb_helper *fb_helper, int dpms_mode) struct drm_device *dev = fb_helper->dev; struct drm_connector *connector; struct drm_mode_set *modeset; - int i, j; + int j; drm_modeset_lock_all(dev); - for (i = 0; i < fb_helper->crtc_count; i++) { - modeset = &fb_helper->crtc_info[i].mode_set; - + drm_client_for_each_modeset(modeset, fb_helper->modesets) { if (!modeset->crtc->enabled) continue; @@ -762,43 +755,6 @@ int drm_fb_helper_blank(int blank, struct fb_info *info) } EXPORT_SYMBOL(drm_fb_helper_blank); -static void drm_fb_helper_modeset_release(struct drm_fb_helper *helper, - struct drm_mode_set *modeset) -{ - int i; - - for (i = 0; i < modeset->num_connectors; i++) { - drm_connector_put(modeset->connectors[i]); - modeset->connectors[i] = NULL; - } - modeset->num_connectors = 0; - - drm_mode_destroy(helper->dev, modeset->mode); - modeset->mode = NULL; - - /* FIXME should hold a ref? */ - modeset->fb = NULL; -} - -static void drm_fb_helper_crtc_free(struct drm_fb_helper *helper) -{ - int i; - - for (i = 0; i < helper->connector_count; i++) { - drm_connector_put(helper->connector_info[i]->connector); - kfree(helper->connector_info[i]); - } - kfree(helper->connector_info); - - for (i = 0; i < helper->crtc_count; i++) { - struct drm_mode_set *modeset = &helper->crtc_info[i].mode_set; - - drm_fb_helper_modeset_release(helper, modeset); - kfree(modeset->connectors); - } - kfree(helper->crtc_info); -} - static void drm_fb_helper_resume_worker(struct work_struct *work) { struct drm_fb_helper *helper = container_of(work, struct drm_fb_helper, @@ -877,7 +833,7 @@ EXPORT_SYMBOL(drm_fb_helper_prepare); * drm_fb_helper_init - initialize a &struct drm_fb_helper * @dev: drm device * @fb_helper: driver-allocated fbdev helper structure to initialize - * @max_conn_count: max connector count + * @max_conn_count: max connector count (not used) * * This allocates the structures for the fbdev helper with the given limits. * Note that this won't yet touch the hardware (through the driver interfaces) @@ -893,53 +849,28 @@ int drm_fb_helper_init(struct drm_device *dev, struct drm_fb_helper *fb_helper, int max_conn_count) { - struct drm_crtc *crtc; - struct drm_mode_config *config = &dev->mode_config; - int i; - if (!drm_fbdev_emulation) { dev->fb_helper = fb_helper; return 0; } - if (!max_conn_count) - return -EINVAL; - - fb_helper->crtc_info = kcalloc(config->num_crtc, sizeof(struct drm_fb_helper_crtc), GFP_KERNEL); - if (!fb_helper->crtc_info) + fb_helper->modesets = drm_client_modesets_create(dev); + if (IS_ERR(fb_helper->modesets)) return -ENOMEM; - fb_helper->crtc_count = config->num_crtc; fb_helper->connector_info = kcalloc(dev->mode_config.num_connector, sizeof(struct drm_fb_helper_connector *), GFP_KERNEL); - if (!fb_helper->connector_info) { - kfree(fb_helper->crtc_info); - return -ENOMEM; - } + if (!fb_helper->connector_info) + goto out_free; + fb_helper->connector_info_alloc_count = dev->mode_config.num_connector; fb_helper->connector_count = 0; - for (i = 0; i < fb_helper->crtc_count; i++) { - fb_helper->crtc_info[i].mode_set.connectors = - kcalloc(max_conn_count, - sizeof(struct drm_connector *), - GFP_KERNEL); - - if (!fb_helper->crtc_info[i].mode_set.connectors) - goto out_free; - fb_helper->crtc_info[i].mode_set.num_connectors = 0; - } - - i = 0; - drm_for_each_crtc(crtc, dev) { - fb_helper->crtc_info[i].mode_set.crtc = crtc; - i++; - } - dev->fb_helper = fb_helper; return 0; out_free: - drm_fb_helper_crtc_free(fb_helper); + drm_client_modesets_release(fb_helper->modesets); + return -ENOMEM; } EXPORT_SYMBOL(drm_fb_helper_init); @@ -1014,6 +945,7 @@ EXPORT_SYMBOL(drm_fb_helper_unregister_fbi); void drm_fb_helper_fini(struct drm_fb_helper *fb_helper) { struct fb_info *info; + int i; if (!fb_helper) return; @@ -1043,8 +975,13 @@ void drm_fb_helper_fini(struct drm_fb_helper *fb_helper) mutex_unlock(&kernel_fb_helper_lock); mutex_destroy(&fb_helper->lock); - drm_fb_helper_crtc_free(fb_helper); + drm_client_modesets_release(fb_helper->modesets); + for (i = 0; i < fb_helper->connector_count; i++) { + drm_connector_put(fb_helper->connector_info[i]->connector); + kfree(fb_helper->connector_info[i]); + } + kfree(fb_helper->connector_info); } EXPORT_SYMBOL(drm_fb_helper_fini); @@ -1389,13 +1326,14 @@ static int setcmap_pseudo_palette(struct fb_cmap *cmap, struct fb_info *info) static int setcmap_legacy(struct fb_cmap *cmap, struct fb_info *info) { struct drm_fb_helper *fb_helper = info->par; + struct drm_mode_set *modeset; struct drm_crtc *crtc; u16 *r, *g, *b; - int i, ret = 0; + int ret = 0; drm_modeset_lock_all(fb_helper->dev); - for (i = 0; i < fb_helper->crtc_count; i++) { - crtc = fb_helper->crtc_info[i].mode_set.crtc; + drm_client_for_each_modeset(modeset, fb_helper->modesets) { + crtc = modeset->crtc; if (!crtc->funcs->gamma_set || !crtc->gamma_size) return -EINVAL; @@ -1471,10 +1409,11 @@ static int setcmap_atomic(struct fb_cmap *cmap, struct fb_info *info) struct drm_modeset_acquire_ctx ctx; struct drm_crtc_state *crtc_state; struct drm_atomic_state *state; + struct drm_mode_set *modeset; struct drm_crtc *crtc; u16 *r, *g, *b; - int i, ret = 0; bool replaced; + int ret = 0; drm_modeset_acquire_init(&ctx, 0); @@ -1486,8 +1425,8 @@ static int setcmap_atomic(struct fb_cmap *cmap, struct fb_info *info) state->acquire_ctx = &ctx; retry: - for (i = 0; i < fb_helper->crtc_count; i++) { - crtc = fb_helper->crtc_info[i].mode_set.crtc; + drm_client_for_each_modeset(modeset, fb_helper->modesets) { + crtc = modeset->crtc; if (!gamma_lut) gamma_lut = setcmap_new_gamma_lut(crtc, cmap); @@ -1515,8 +1454,8 @@ static int setcmap_atomic(struct fb_cmap *cmap, struct fb_info *info) if (ret) goto out_state; - for (i = 0; i < fb_helper->crtc_count; i++) { - crtc = fb_helper->crtc_info[i].mode_set.crtc; + drm_client_for_each_modeset(modeset, fb_helper->modesets) { + crtc = modeset->crtc; r = crtc->gamma_store; g = r + crtc->gamma_size; @@ -1592,7 +1531,6 @@ int drm_fb_helper_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) { struct drm_fb_helper *fb_helper = info->par; - struct drm_mode_set *mode_set; struct drm_crtc *crtc; int ret = 0; @@ -1620,8 +1558,7 @@ int drm_fb_helper_ioctl(struct fb_info *info, unsigned int cmd, * make. If we're not smart enough here, one should * just consider switch the userspace to KMS. */ - mode_set = &fb_helper->crtc_info[0].mode_set; - crtc = mode_set->crtc; + crtc = fb_helper->modesets[0].crtc; /* * Only wait for a vblank event if the CRTC is @@ -1817,13 +1754,9 @@ EXPORT_SYMBOL(drm_fb_helper_set_par); static void pan_set(struct drm_fb_helper *fb_helper, int x, int y) { - int i; - - for (i = 0; i < fb_helper->crtc_count; i++) { - struct drm_mode_set *mode_set; - - mode_set = &fb_helper->crtc_info[i].mode_set; + struct drm_mode_set *mode_set; + drm_client_for_each_modeset(mode_set, fb_helper->modesets) { mode_set->x = x; mode_set->y = y; } @@ -1853,12 +1786,9 @@ static int pan_display_legacy(struct fb_var_screeninfo *var, struct drm_fb_helper *fb_helper = info->par; struct drm_mode_set *modeset; int ret = 0; - int i; drm_modeset_lock_all(fb_helper->dev); - for (i = 0; i < fb_helper->crtc_count; i++) { - modeset = &fb_helper->crtc_info[i].mode_set; - + drm_client_for_each_modeset(modeset, fb_helper->modesets) { modeset->x = var->xoffset; modeset->y = var->yoffset; @@ -1917,6 +1847,7 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper, int crtc_count = 0; int i; struct drm_fb_helper_surface_size sizes; + struct drm_mode_set *mode_set; int best_depth = 0; memset(&sizes, 0, sizeof(struct drm_fb_helper_surface_size)); @@ -1967,13 +1898,12 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper, * supports RGBA5551 (16 bpp, depth 15) but not RGB565 (16 bpp, depth * 16) we need to scale down the depth of the sizes we request. */ - for (i = 0; i < fb_helper->crtc_count; i++) { - struct drm_mode_set *mode_set = &fb_helper->crtc_info[i].mode_set; + drm_client_for_each_modeset(mode_set, fb_helper->modesets) { struct drm_crtc *crtc = mode_set->crtc; struct drm_plane *plane = crtc->primary; int j; - DRM_DEBUG("test CRTC %d primary plane\n", i); + DRM_DEBUG("test CRTC %u primary plane\n", drm_crtc_index(crtc)); for (j = 0; j < plane->format_count; j++) { const struct drm_format_info *fmt; @@ -2013,9 +1943,8 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper, /* first up get a count of crtcs now in use and new min/maxes width/heights */ crtc_count = 0; - for (i = 0; i < fb_helper->crtc_count; i++) { + drm_client_for_each_modeset(mode_set, fb_helper->modesets) { struct drm_display_mode *desired_mode; - struct drm_mode_set *mode_set; int x, y, j; /* in case of tile group, are we the last tile vert or horiz? * If no tile group you are always the last one both vertically @@ -2023,7 +1952,6 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper, */ bool lastv = true, lasth = true; - mode_set = &fb_helper->crtc_info[i].mode_set; desired_mode = mode_set->mode; if (!desired_mode) @@ -2282,7 +2210,7 @@ static bool drm_target_cloned(struct drm_fb_helper *fb_helper, struct drm_display_mode *dmt_mode, *mode; /* only contemplate cloning in the single crtc case */ - if (fb_helper->crtc_count > 1) + if (fb_helper->dev->mode_config.num_crtc > 1) return false; count = 0; @@ -2471,15 +2399,17 @@ static bool connector_has_possible_crtc(struct drm_connector *connector, } static int drm_pick_crtcs(struct drm_fb_helper *fb_helper, - struct drm_fb_helper_crtc **best_crtcs, + struct drm_mode_set *modesets, + struct drm_crtc **best_crtcs, struct drm_display_mode **modes, int n, int width, int height) { - int c, o; struct drm_connector *connector; int my_score, best_score, score; - struct drm_fb_helper_crtc **crtcs, *crtc; + struct drm_crtc **crtcs, *crtc; + struct drm_mode_set *modeset; struct drm_fb_helper_connector *fb_helper_conn; + int o; if (n == fb_helper->connector_count) return 0; @@ -2488,12 +2418,11 @@ static int drm_pick_crtcs(struct drm_fb_helper *fb_helper, connector = fb_helper_conn->connector; best_crtcs[n] = NULL; - best_score = drm_pick_crtcs(fb_helper, best_crtcs, modes, n+1, width, height); + best_score = drm_pick_crtcs(fb_helper, modesets, best_crtcs, modes, n + 1, width, height); if (modes[n] == NULL) return best_score; - crtcs = kcalloc(fb_helper->connector_count, - sizeof(struct drm_fb_helper_crtc *), GFP_KERNEL); + crtcs = kcalloc(fb_helper->connector_count, sizeof(*crtcs), GFP_KERNEL); if (!crtcs) return best_score; @@ -2509,11 +2438,10 @@ static int drm_pick_crtcs(struct drm_fb_helper *fb_helper, * select a crtc for this connector and then attempt to configure * remaining connectors */ - for (c = 0; c < fb_helper->crtc_count; c++) { - crtc = &fb_helper->crtc_info[c]; + drm_client_for_each_modeset(modeset, modesets) { + crtc = modeset->crtc; - if (!connector_has_possible_crtc(connector, - crtc->mode_set.crtc)) + if (!connector_has_possible_crtc(connector, crtc)) continue; for (o = 0; o < n; o++) @@ -2522,7 +2450,7 @@ static int drm_pick_crtcs(struct drm_fb_helper *fb_helper, if (o < n) { /* ignore cloning unless only a single crtc */ - if (fb_helper->crtc_count > 1) + if (fb_helper->dev->mode_config.num_crtc > 1) continue; if (!drm_mode_equal(modes[o], modes[n])) @@ -2530,14 +2458,13 @@ static int drm_pick_crtcs(struct drm_fb_helper *fb_helper, } crtcs[n] = crtc; - memcpy(crtcs, best_crtcs, n * sizeof(struct drm_fb_helper_crtc *)); - score = my_score + drm_pick_crtcs(fb_helper, crtcs, modes, n + 1, + memcpy(crtcs, best_crtcs, n * sizeof(*crtcs)); + score = my_score + drm_pick_crtcs(fb_helper, modesets, crtcs, modes, n + 1, width, height); if (score > best_score) { best_score = score; memcpy(best_crtcs, crtcs, - fb_helper->connector_count * - sizeof(struct drm_fb_helper_crtc *)); + fb_helper->connector_count * sizeof(*crtcs)); } } @@ -2545,21 +2472,9 @@ static int drm_pick_crtcs(struct drm_fb_helper *fb_helper, return best_score; } -static struct drm_fb_helper_crtc * -drm_fb_helper_crtc(struct drm_fb_helper *fb_helper, struct drm_crtc *crtc) -{ - int i; - - for (i = 0; i < fb_helper->crtc_count; i++) - if (fb_helper->crtc_info[i].mode_set.crtc == crtc) - return &fb_helper->crtc_info[i]; - - return NULL; -} - /* Try to read the BIOS display configuration and use it for the initial config */ static bool drm_fb_helper_firmware_config(struct drm_fb_helper *fb_helper, - struct drm_fb_helper_crtc **crtcs, + struct drm_crtc **crtcs, struct drm_display_mode **modes, struct drm_fb_offset *offsets, bool *enabled, int width, int height) @@ -2591,7 +2506,7 @@ static bool drm_fb_helper_firmware_config(struct drm_fb_helper *fb_helper, struct drm_fb_helper_connector *fb_conn; struct drm_connector *connector; struct drm_encoder *encoder; - struct drm_fb_helper_crtc *new_crtc; + struct drm_crtc *new_crtc; fb_conn = fb_helper->connector_info[i]; connector = fb_conn->connector; @@ -2634,7 +2549,7 @@ static bool drm_fb_helper_firmware_config(struct drm_fb_helper *fb_helper, num_connectors_enabled++; - new_crtc = drm_fb_helper_crtc(fb_helper, connector->state->crtc); + new_crtc = connector->state->crtc; /* * Make sure we're not trying to drive multiple connectors @@ -2737,9 +2652,10 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper, u32 width, u32 height) { struct drm_device *dev = fb_helper->dev; - struct drm_fb_helper_crtc **crtcs; struct drm_display_mode **modes; struct drm_fb_offset *offsets; + struct drm_mode_set *modesets; + struct drm_crtc **crtcs; bool *enabled; int i; @@ -2747,15 +2663,15 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper, /* prevent concurrent modification of connector_count by hotplug */ lockdep_assert_held(&fb_helper->lock); - crtcs = kcalloc(fb_helper->connector_count, - sizeof(struct drm_fb_helper_crtc *), GFP_KERNEL); + modesets = drm_client_modesets_create(dev); + crtcs = kcalloc(fb_helper->connector_count, sizeof(*crtcs), GFP_KERNEL); modes = kcalloc(fb_helper->connector_count, sizeof(struct drm_display_mode *), GFP_KERNEL); offsets = kcalloc(fb_helper->connector_count, sizeof(struct drm_fb_offset), GFP_KERNEL); enabled = kcalloc(fb_helper->connector_count, sizeof(bool), GFP_KERNEL); - if (!crtcs || !modes || !enabled || !offsets) { + if (IS_ERR(modesets) || !crtcs || !modes || !enabled || !offsets) { DRM_ERROR("Memory allocation failed\n"); goto out; } @@ -2780,28 +2696,26 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper, DRM_DEBUG_KMS("picking CRTCs for %dx%d config\n", width, height); - drm_pick_crtcs(fb_helper, crtcs, modes, 0, width, height); + drm_pick_crtcs(fb_helper, modesets, crtcs, modes, 0, width, height); } mutex_unlock(&fb_helper->dev->mode_config.mutex); - /* need to set the modesets up here for use later */ - /* fill out the connector<->crtc mappings into the modesets */ - for (i = 0; i < fb_helper->crtc_count; i++) - drm_fb_helper_modeset_release(fb_helper, - &fb_helper->crtc_info[i].mode_set); - drm_fb_helper_for_each_connector(fb_helper, i) { struct drm_display_mode *mode = modes[i]; - struct drm_fb_helper_crtc *fb_crtc = crtcs[i]; + struct drm_crtc *crtc = crtcs[i]; struct drm_fb_offset *offset = &offsets[i]; - if (mode && fb_crtc) { - struct drm_mode_set *modeset = &fb_crtc->mode_set; + if (mode && crtc) { + struct drm_mode_set *modeset = drm_client_find_modeset(modesets, crtc); struct drm_connector *connector = fb_helper->connector_info[i]->connector; DRM_DEBUG_KMS("desired mode %s set on crtc %d (%d,%d)\n", - mode->name, fb_crtc->mode_set.crtc->base.id, offset->x, offset->y); + mode->name, crtc->base.id, offset->x, offset->y); + + if (WARN_ON_ONCE(modeset->num_connectors == DRM_CLIENT_MAX_CLONED_CONNECTORS || + (dev->mode_config.num_crtc > 1 && modeset->num_connectors == 1))) + break; modeset->mode = drm_mode_duplicate(dev, mode); drm_connector_get(connector); @@ -2810,11 +2724,14 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper, modeset->y = offset->y; } } + + swap(fb_helper->modesets, modesets); out: kfree(crtcs); kfree(modes); kfree(offsets); kfree(enabled); + drm_client_modesets_release(modesets); } /* @@ -2828,11 +2745,10 @@ static void drm_setup_crtcs_fb(struct drm_fb_helper *fb_helper) { struct fb_info *info = fb_helper->fbdev; unsigned int rotation, sw_rotations = 0; + struct drm_mode_set *modeset; int i; - for (i = 0; i < fb_helper->crtc_count; i++) { - struct drm_mode_set *modeset = &fb_helper->crtc_info[i].mode_set; - + drm_client_for_each_modeset(modeset, fb_helper->modesets) { if (!modeset->num_connectors) continue; @@ -3058,8 +2974,7 @@ EXPORT_SYMBOL(drm_fb_helper_hotplug_event); * @funcs: fbdev helper functions * @preferred_bpp: Preferred bits per pixel for the device. * @dev->mode_config.preferred_depth is used if this is zero. - * @max_conn_count: Maximum number of connectors. - * @dev->mode_config.num_connector is used if this is zero. + * @max_conn_count: Maximum number of connectors (not used) * * This function sets up fbdev emulation and registers fbdev for access by * userspace. If all connectors are disconnected, setup is deferred to the next @@ -3087,16 +3002,9 @@ int drm_fb_helper_fbdev_setup(struct drm_device *dev, if (!preferred_bpp) preferred_bpp = 32; - if (!max_conn_count) - max_conn_count = dev->mode_config.num_connector; - if (!max_conn_count) { - DRM_DEV_ERROR(dev->dev, "fbdev: No connectors\n"); - return -EINVAL; - } - drm_fb_helper_prepare(dev, fb_helper, funcs); - ret = drm_fb_helper_init(dev, fb_helper, max_conn_count); + ret = drm_fb_helper_init(dev, fb_helper, 0); if (ret < 0) { DRM_DEV_ERROR(dev->dev, "fbdev: Failed to initialize (ret=%d)\n", ret); return ret; @@ -3413,7 +3321,7 @@ static int drm_fbdev_client_hotplug(struct drm_client_dev *client) drm_fb_helper_prepare(dev, fb_helper, &drm_fb_helper_generic_funcs); - ret = drm_fb_helper_init(dev, fb_helper, dev->mode_config.num_connector); + ret = drm_fb_helper_init(dev, fb_helper, 0); if (ret) goto err; diff --git a/include/drm/drm_client.h b/include/drm/drm_client.h index 8b552b1a6ce9..b2efce3f7781 100644 --- a/include/drm/drm_client.h +++ b/include/drm/drm_client.h @@ -5,6 +5,8 @@ #include +#include + struct drm_client_dev; struct drm_device; struct drm_file; @@ -13,6 +15,8 @@ struct drm_gem_object; struct drm_minor; struct module; +#define DRM_CLIENT_MAX_CLONED_CONNECTORS 8 + /** * struct drm_client_funcs - DRM client callbacks */ @@ -135,6 +139,18 @@ struct drm_client_buffer * drm_client_framebuffer_create(struct drm_client_dev *client, u32 width, u32 height, u32 format); void drm_client_framebuffer_delete(struct drm_client_buffer *buffer); +struct drm_mode_set *drm_client_modesets_create(struct drm_device *dev); +void drm_client_modesets_release(struct drm_mode_set *modesets); +struct drm_mode_set *drm_client_find_modeset(struct drm_mode_set *modesets, struct drm_crtc *crtc); + +/** + * drm_client_for_each_modeset() - Iterate over modesets + * @modeset: &drm_mode_set loop cursor + * @modesets: Modeset array to iterate over + */ +#define drm_client_for_each_modeset(modeset, modesets) \ + for (modeset = modesets; modeset->crtc; modeset++) + int drm_client_debugfs_init(struct drm_minor *minor); #endif diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h index bca4b34dc93b..905697c37c5b 100644 --- a/include/drm/drm_fb_helper.h +++ b/include/drm/drm_fb_helper.h @@ -46,10 +46,6 @@ struct drm_fb_offset { int x, y; }; -struct drm_fb_helper_crtc { - struct drm_mode_set mode_set; -}; - /** * struct drm_fb_helper_surface_size - describes fbdev size and scanout surface size * @fb_width: fbdev width @@ -110,8 +106,6 @@ struct drm_fb_helper_connector { * struct drm_fb_helper - main structure to emulate fbdev on top of KMS * @fb: Scanout framebuffer object * @dev: DRM device - * @crtc_count: number of possible CRTCs - * @crtc_info: per-CRTC helper state (mode, x/y offset, etc) * @connector_count: number of connected connectors * @connector_info_alloc_count: size of connector_info * @funcs: driver callbacks for fb helper @@ -145,8 +139,12 @@ struct drm_fb_helper { struct drm_framebuffer *fb; struct drm_device *dev; - int crtc_count; - struct drm_fb_helper_crtc *crtc_info; + + /** + * @modesets: CRTC configurations + */ + struct drm_mode_set *modesets; + int connector_count; int connector_info_alloc_count; /** From patchwork Tue Mar 26 17:55:38 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Noralf_Tr=C3=B8nnes?= X-Patchwork-Id: 10871823 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 23D5B922 for ; Tue, 26 Mar 2019 17:56:31 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 121A328D54 for ; Tue, 26 Mar 2019 17:56:31 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 0684C28D66; Tue, 26 Mar 2019 17:56:31 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 74B2128D54 for ; Tue, 26 Mar 2019 17:56:30 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 7FF056E06A; Tue, 26 Mar 2019 17:56:11 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from smtp.domeneshop.no (smtp.domeneshop.no [IPv6:2a01:5b40:0:3005::1]) by gabe.freedesktop.org (Postfix) with ESMTPS id C6EA66E078; Tue, 26 Mar 2019 17:56:08 +0000 (UTC) Received: from 211.81-166-168.customer.lyse.net ([81.166.168.211]:46322 helo=localhost.localdomain) by smtp.domeneshop.no with esmtpsa (TLS1.2:ECDHE_RSA_AES_128_CBC_SHA1:128) (Exim 4.84_2) (envelope-from ) id 1h8qIw-0006Mj-KN; Tue, 26 Mar 2019 18:56:06 +0100 From: =?utf-8?q?Noralf_Tr=C3=B8nnes?= To: dri-devel@lists.freedesktop.org Subject: [PATCH 08/16] drm/fb-helper: Prepare to move out commit code Date: Tue, 26 Mar 2019 18:55:38 +0100 Message-Id: <20190326175546.18126-9-noralf@tronnes.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190326175546.18126-1-noralf@tronnes.org> References: <20190326175546.18126-1-noralf@tronnes.org> MIME-Version: 1.0 X-Mailman-Original-DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=tronnes.org; s=ds201810; h=Content-Transfer-Encoding:Content-Type:MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From; bh=rJbMQ+/JiAGoikRwVZ8VKPWFoeY/oXrkNX5+oRfmmV0=; b=FOTtMCfbGgQ6WYPLqoyzON/0PKAtKyRCbjUY42GqU8p5xHmU2sNfOSA7DNHqqDdcRkSKbzUgVbV6RjI03HK5iGGfvP0S9DbPROssalVfp7Uu8jJO796dph5ZB8/Pc9TKWaJ4XE44Pw9kxHm9mwiS8qcXcwDn4oX+VHXDwPLQHSFQ9f5W7oF5QRMkR4sJlpQTyAE0/0QjOJERxxHHQDOk+NmYvK6ug5dsQ5UF9vsKhCRo78kqLU5unj/aSidc2H82dkvDbVkgC5UYW0kSv4DSRTTma1BeU02Sa1G/N3w+o+MLRLoNl8SnJQhQtBRj+LCi8N9CuLS45y7N/2rDonghGQ==; X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: intel-gfx@lists.freedesktop.org, mstaudt@suse.de Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Virus-Scanned: ClamAV using ClamSMTP This makes the necessary changes so the commit code can be moved out to drm_client as-is in the next patch. It's split up to ease review. Signed-off-by: Noralf Trønnes --- drivers/gpu/drm/drm_fb_helper.c | 93 +++++++++++++++++++++------------ 1 file changed, 59 insertions(+), 34 deletions(-) diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 85bea51e2072..9dcb77dfff0a 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -382,9 +382,20 @@ int drm_fb_helper_debug_leave(struct fb_info *info) } EXPORT_SYMBOL(drm_fb_helper_debug_leave); -/* Check if the plane can hw rotate to match panel orientation */ -static bool drm_fb_helper_panel_rotation(struct drm_mode_set *modeset, - unsigned int *rotation) +/** + * drm_client_panel_rotation() - Check panel orientation + * @modeset: DRM modeset + * @rotation: Returned rotation value + * + * This function checks if the primary plane in @modeset can hw rotate to match + * the panel orientation on its connector. + * + * Note: Currently only 0 and 180 degrees are supported. + * + * Return: + * True if the plane can do the rotation, false otherwise. + */ +bool drm_client_panel_rotation(struct drm_mode_set *modeset, unsigned int *rotation) { struct drm_connector *connector = modeset->connectors[0]; struct drm_plane *plane = modeset->crtc->primary; @@ -425,9 +436,9 @@ static bool drm_fb_helper_panel_rotation(struct drm_mode_set *modeset, return true; } -static int restore_fbdev_mode_atomic(struct drm_fb_helper *fb_helper, bool active) +static int drm_client_modesets_commit_atomic(struct drm_device *dev, struct drm_mode_set *modesets, + bool active) { - struct drm_device *dev = fb_helper->dev; struct drm_plane_state *plane_state; struct drm_plane *plane; struct drm_atomic_state *state; @@ -463,11 +474,11 @@ static int restore_fbdev_mode_atomic(struct drm_fb_helper *fb_helper, bool activ goto out_state; } - drm_client_for_each_modeset(mode_set, fb_helper->modesets) { + drm_client_for_each_modeset(mode_set, modesets) { struct drm_plane *primary = mode_set->crtc->primary; unsigned int rotation; - if (drm_fb_helper_panel_rotation(mode_set, &rotation)) { + if (drm_client_panel_rotation(mode_set, &rotation)) { /* Cannot fail as we've already gotten the plane state above */ plane_state = drm_atomic_get_new_plane_state(state, primary); plane_state->rotation = rotation; @@ -509,14 +520,13 @@ static int restore_fbdev_mode_atomic(struct drm_fb_helper *fb_helper, bool activ goto retry; } -static int restore_fbdev_mode_legacy(struct drm_fb_helper *fb_helper) +static int drm_client_modesets_commit_legacy(struct drm_device *dev, struct drm_mode_set *modesets) { - struct drm_device *dev = fb_helper->dev; struct drm_mode_set *mode_set; struct drm_plane *plane; int ret = 0; - drm_modeset_lock_all(fb_helper->dev); + drm_modeset_lock_all(dev); drm_for_each_plane(plane, dev) { if (plane->type != DRM_PLANE_TYPE_PRIMARY) drm_plane_force_disable(plane); @@ -527,7 +537,7 @@ static int restore_fbdev_mode_legacy(struct drm_fb_helper *fb_helper) DRM_MODE_ROTATE_0); } - drm_client_for_each_modeset(mode_set, fb_helper->modesets) { + drm_client_for_each_modeset(mode_set, modesets) { struct drm_crtc *crtc = mode_set->crtc; if (crtc->funcs->cursor_set2) { @@ -545,19 +555,25 @@ static int restore_fbdev_mode_legacy(struct drm_fb_helper *fb_helper) goto out; } out: - drm_modeset_unlock_all(fb_helper->dev); + drm_modeset_unlock_all(dev); return ret; } -static int restore_fbdev_mode(struct drm_fb_helper *fb_helper) +/** + * drm_client_modesets_commit() - Commit CRTC configuration + * @dev: DRM device + * @modesets: Modeset array + * + * Returns: + * Zero on success or negative error code on failure. + */ +int drm_client_modesets_commit(struct drm_device *dev, struct drm_mode_set *modesets) { - struct drm_device *dev = fb_helper->dev; - if (drm_drv_uses_atomic_modeset(dev)) - return restore_fbdev_mode_atomic(fb_helper, true); + return drm_client_modesets_commit_atomic(dev, modesets, true); else - return restore_fbdev_mode_legacy(fb_helper); + return drm_client_modesets_commit_legacy(dev, modesets); } /** @@ -583,7 +599,7 @@ int drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper) return 0; mutex_lock(&fb_helper->lock); - ret = restore_fbdev_mode(fb_helper); + ret = drm_client_modesets_commit(fb_helper->dev, fb_helper->modesets); do_delayed = fb_helper->delayed_hotplug; if (do_delayed) @@ -645,7 +661,7 @@ static bool drm_fb_helper_force_kernel_mode(void) continue; mutex_lock(&helper->lock); - ret = restore_fbdev_mode(helper); + ret = drm_client_modesets_commit(dev, helper->modesets); if (ret) error = true; mutex_unlock(&helper->lock); @@ -677,15 +693,15 @@ static struct sysrq_key_op sysrq_drm_fb_helper_restore_op = { static struct sysrq_key_op sysrq_drm_fb_helper_restore_op = { }; #endif -static void dpms_legacy(struct drm_fb_helper *fb_helper, int dpms_mode) +static void drm_client_modesets_dpms_legacy(struct drm_device *dev, struct drm_mode_set *modesets, + int dpms_mode) { - struct drm_device *dev = fb_helper->dev; struct drm_connector *connector; struct drm_mode_set *modeset; int j; drm_modeset_lock_all(dev); - drm_client_for_each_modeset(modeset, fb_helper->modesets) { + drm_client_for_each_modeset(modeset, modesets) { if (!modeset->crtc->enabled) continue; @@ -699,6 +715,22 @@ static void dpms_legacy(struct drm_fb_helper *fb_helper, int dpms_mode) drm_modeset_unlock_all(dev); } +/** + * drm_client_modesets_dpms() - Set DPMS mode + * @dev: DRM device + * @modesets: Modeset array + * @mode: DPMS mode + * + * Note: For atomic drivers @mode is reduced to on/off. + */ +void drm_client_modesets_dpms(struct drm_device *dev, struct drm_mode_set *modesets, int mode) +{ + if (drm_drv_uses_atomic_modeset(dev)) + drm_client_modesets_commit_atomic(dev, modesets, mode == DRM_MODE_DPMS_ON); + else + drm_client_modesets_dpms_legacy(dev, modesets, mode); +} + static void drm_fb_helper_dpms(struct fb_info *info, int dpms_mode) { struct drm_fb_helper *fb_helper = info->par; @@ -707,15 +739,8 @@ static void drm_fb_helper_dpms(struct fb_info *info, int dpms_mode) * For each CRTC in this fb, turn the connectors on/off. */ mutex_lock(&fb_helper->lock); - if (!drm_fb_helper_is_bound(fb_helper)) { - mutex_unlock(&fb_helper->lock); - return; - } - - if (drm_drv_uses_atomic_modeset(fb_helper->dev)) - restore_fbdev_mode_atomic(fb_helper, dpms_mode == DRM_MODE_DPMS_ON); - else - dpms_legacy(fb_helper, dpms_mode); + if (drm_fb_helper_is_bound(fb_helper)) + drm_client_modesets_dpms(fb_helper->dev, fb_helper->modesets, dpms_mode); mutex_unlock(&fb_helper->lock); } @@ -1770,7 +1795,7 @@ static int pan_display_atomic(struct fb_var_screeninfo *var, pan_set(fb_helper, var->xoffset, var->yoffset); - ret = restore_fbdev_mode_atomic(fb_helper, true); + ret = drm_client_modesets_commit(fb_helper->dev, fb_helper->modesets); if (!ret) { info->var.xoffset = var->xoffset; info->var.yoffset = var->yoffset; @@ -1987,7 +2012,7 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper, /* First time: disable all crtc's.. */ if (!fb_helper->deferred_setup && !READ_ONCE(fb_helper->dev->master)) - restore_fbdev_mode(fb_helper); + drm_client_modesets_commit(fb_helper->dev, fb_helper->modesets); return -EAGAIN; } @@ -2754,7 +2779,7 @@ static void drm_setup_crtcs_fb(struct drm_fb_helper *fb_helper) modeset->fb = fb_helper->fb; - if (drm_fb_helper_panel_rotation(modeset, &rotation)) + if (drm_client_panel_rotation(modeset, &rotation)) /* Rotating in hardware, fbcon should not rotate */ sw_rotations |= DRM_MODE_ROTATE_0; else From patchwork Tue Mar 26 17:55:39 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Noralf_Tr=C3=B8nnes?= X-Patchwork-Id: 10871821 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id E31281669 for ; Tue, 26 Mar 2019 17:56:29 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id CEBAB28D54 for ; Tue, 26 Mar 2019 17:56:29 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id BFC9528D66; Tue, 26 Mar 2019 17:56:29 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id D69B628D54 for ; Tue, 26 Mar 2019 17:56:28 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 8EC566E06C; Tue, 26 Mar 2019 17:56:11 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from smtp.domeneshop.no (smtp.domeneshop.no [IPv6:2a01:5b40:0:3005::1]) by gabe.freedesktop.org (Postfix) with ESMTPS id C05F06E075; Tue, 26 Mar 2019 17:56:08 +0000 (UTC) Received: from 211.81-166-168.customer.lyse.net ([81.166.168.211]:46322 helo=localhost.localdomain) by smtp.domeneshop.no with esmtpsa (TLS1.2:ECDHE_RSA_AES_128_CBC_SHA1:128) (Exim 4.84_2) (envelope-from ) id 1h8qIw-0006Mj-RN; Tue, 26 Mar 2019 18:56:06 +0100 From: =?utf-8?q?Noralf_Tr=C3=B8nnes?= To: dri-devel@lists.freedesktop.org Subject: [PATCH 09/16] drm/fb-helper: Move out commit code Date: Tue, 26 Mar 2019 18:55:39 +0100 Message-Id: <20190326175546.18126-10-noralf@tronnes.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190326175546.18126-1-noralf@tronnes.org> References: <20190326175546.18126-1-noralf@tronnes.org> MIME-Version: 1.0 X-Mailman-Original-DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=tronnes.org; s=ds201810; h=Content-Transfer-Encoding:Content-Type:MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From; bh=oLfGyN9o8dKvbFYefpq6NwM/H9qqwOci9HCVOgB0K1Y=; b=mqfmcJIXJ8J9Dg+eRMXvhiaZCfG/Q8o2SZjB5APQai0zpEFSTU41QD3Xw1y0lqbeQC+2S8I9Gp3GE93RtZum4i3rnOMEQwXC2HU42nBMC4GhObTsk06+gfdHJuWZ8aGsGtpZm5c8ibeX13SKGTuDbxqfKP2VdHXSY0Rp/3uCv89V6ug3bDzYCu2hKQMux69sfsyKwTpa0KgpiCfQz+swrSR/4GnKWJR1kxdbgUvMWYKTzQsdQL0pwNddLVLNP4DSCeAQoRcgt7k0lYcRaJAe/GFBdXTyravEiHVcBFXSuN20dcpX+/sE0aMQ2Z4KrPO4iGXtE7OQypvDwFxiLdCXeA==; X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: intel-gfx@lists.freedesktop.org, mstaudt@suse.de Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Virus-Scanned: ClamAV using ClamSMTP Move the modeset commit code to drm_client. No changes except exporting API. Signed-off-by: Noralf Trønnes --- drivers/gpu/drm/drm_client.c | 236 ++++++++++++++++++++++++++++++++ drivers/gpu/drm/drm_fb_helper.c | 232 ------------------------------- include/drm/drm_client.h | 3 + 3 files changed, 239 insertions(+), 232 deletions(-) diff --git a/drivers/gpu/drm/drm_client.c b/drivers/gpu/drm/drm_client.c index 84f848f21679..5b199c051960 100644 --- a/drivers/gpu/drm/drm_client.c +++ b/drivers/gpu/drm/drm_client.c @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -485,6 +486,241 @@ struct drm_mode_set *drm_client_find_modeset(struct drm_mode_set *modesets, stru } EXPORT_SYMBOL(drm_client_find_modeset); +/** + * drm_client_panel_rotation() - Check panel orientation + * @modeset: DRM modeset + * @rotation: Returned rotation value + * + * This function checks if the primary plane in @modeset can hw rotate to match + * the panel orientation on its connector. + * + * Note: Currently only 0 and 180 degrees are supported. + * + * Return: + * True if the plane can do the rotation, false otherwise. + */ +bool drm_client_panel_rotation(struct drm_mode_set *modeset, unsigned int *rotation) +{ + struct drm_connector *connector = modeset->connectors[0]; + struct drm_plane *plane = modeset->crtc->primary; + u64 valid_mask = 0; + unsigned int i; + + if (!modeset->num_connectors) + return false; + + switch (connector->display_info.panel_orientation) { + case DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP: + *rotation = DRM_MODE_ROTATE_180; + break; + case DRM_MODE_PANEL_ORIENTATION_LEFT_UP: + *rotation = DRM_MODE_ROTATE_90; + break; + case DRM_MODE_PANEL_ORIENTATION_RIGHT_UP: + *rotation = DRM_MODE_ROTATE_270; + break; + default: + *rotation = DRM_MODE_ROTATE_0; + } + + /* + * TODO: support 90 / 270 degree hardware rotation, + * depending on the hardware this may require the framebuffer + * to be in a specific tiling format. + */ + if (*rotation != DRM_MODE_ROTATE_180 || !plane->rotation_property) + return false; + + for (i = 0; i < plane->rotation_property->num_values; i++) + valid_mask |= (1ULL << plane->rotation_property->values[i]); + + if (!(*rotation & valid_mask)) + return false; + + return true; +} +EXPORT_SYMBOL(drm_client_panel_rotation); + +static int drm_client_modesets_commit_atomic(struct drm_device *dev, struct drm_mode_set *modesets, + bool active) +{ + struct drm_plane_state *plane_state; + struct drm_plane *plane; + struct drm_atomic_state *state; + struct drm_modeset_acquire_ctx ctx; + struct drm_mode_set *mode_set; + int ret; + + drm_modeset_acquire_init(&ctx, 0); + + state = drm_atomic_state_alloc(dev); + if (!state) { + ret = -ENOMEM; + goto out_ctx; + } + + state->acquire_ctx = &ctx; +retry: + drm_for_each_plane(plane, dev) { + plane_state = drm_atomic_get_plane_state(state, plane); + if (IS_ERR(plane_state)) { + ret = PTR_ERR(plane_state); + goto out_state; + } + + plane_state->rotation = DRM_MODE_ROTATE_0; + + /* disable non-primary: */ + if (plane->type == DRM_PLANE_TYPE_PRIMARY) + continue; + + ret = __drm_atomic_helper_disable_plane(plane, plane_state); + if (ret != 0) + goto out_state; + } + + drm_client_for_each_modeset(mode_set, modesets) { + struct drm_plane *primary = mode_set->crtc->primary; + unsigned int rotation; + + if (drm_client_panel_rotation(mode_set, &rotation)) { + /* Cannot fail as we've already gotten the plane state above */ + plane_state = drm_atomic_get_new_plane_state(state, primary); + plane_state->rotation = rotation; + } + + ret = __drm_atomic_helper_set_config(mode_set, state); + if (ret != 0) + goto out_state; + + /* + * __drm_atomic_helper_set_config() sets active when a + * mode is set, unconditionally clear it if we force DPMS off + */ + if (!active) { + struct drm_crtc *crtc = mode_set->crtc; + struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc); + + crtc_state->active = false; + } + } + + ret = drm_atomic_commit(state); + +out_state: + if (ret == -EDEADLK) + goto backoff; + + drm_atomic_state_put(state); +out_ctx: + drm_modeset_drop_locks(&ctx); + drm_modeset_acquire_fini(&ctx); + + return ret; + +backoff: + drm_atomic_state_clear(state); + drm_modeset_backoff(&ctx); + + goto retry; +} + +static int drm_client_modesets_commit_legacy(struct drm_device *dev, struct drm_mode_set *modesets) +{ + struct drm_mode_set *mode_set; + struct drm_plane *plane; + int ret = 0; + + drm_modeset_lock_all(dev); + drm_for_each_plane(plane, dev) { + if (plane->type != DRM_PLANE_TYPE_PRIMARY) + drm_plane_force_disable(plane); + + if (plane->rotation_property) + drm_mode_plane_set_obj_prop(plane, + plane->rotation_property, + DRM_MODE_ROTATE_0); + } + + drm_client_for_each_modeset(mode_set, modesets) { + struct drm_crtc *crtc = mode_set->crtc; + + if (crtc->funcs->cursor_set2) { + ret = crtc->funcs->cursor_set2(crtc, NULL, 0, 0, 0, 0, 0); + if (ret) + goto out; + } else if (crtc->funcs->cursor_set) { + ret = crtc->funcs->cursor_set(crtc, NULL, 0, 0, 0); + if (ret) + goto out; + } + + ret = drm_mode_set_config_internal(mode_set); + if (ret) + goto out; + } +out: + drm_modeset_unlock_all(dev); + + return ret; +} + +/** + * drm_client_modesets_commit() - Commit CRTC configuration + * @dev: DRM device + * @modesets: Modeset array + * + * Returns: + * Zero on success or negative error code on failure. + */ +int drm_client_modesets_commit(struct drm_device *dev, struct drm_mode_set *modesets) +{ + if (drm_drv_uses_atomic_modeset(dev)) + return drm_client_modesets_commit_atomic(dev, modesets, true); + else + return drm_client_modesets_commit_legacy(dev, modesets); +} +EXPORT_SYMBOL(drm_client_modesets_commit); + +static void drm_client_modesets_dpms_legacy(struct drm_device *dev, struct drm_mode_set *modesets, + int dpms_mode) +{ + struct drm_connector *connector; + struct drm_mode_set *modeset; + int j; + + drm_modeset_lock_all(dev); + drm_client_for_each_modeset(modeset, modesets) { + if (!modeset->crtc->enabled) + continue; + + for (j = 0; j < modeset->num_connectors; j++) { + connector = modeset->connectors[j]; + connector->funcs->dpms(connector, dpms_mode); + drm_object_property_set_value(&connector->base, + dev->mode_config.dpms_property, dpms_mode); + } + } + drm_modeset_unlock_all(dev); +} + +/** + * drm_client_modesets_dpms() - Set DPMS mode + * @dev: DRM device + * @modesets: Modeset array + * @mode: DPMS mode + * + * Note: For atomic drivers @mode is reduced to on/off. + */ +void drm_client_modesets_dpms(struct drm_device *dev, struct drm_mode_set *modesets, int mode) +{ + if (drm_drv_uses_atomic_modeset(dev)) + drm_client_modesets_commit_atomic(dev, modesets, mode == DRM_MODE_DPMS_ON); + else + drm_client_modesets_dpms_legacy(dev, modesets, mode); +} +EXPORT_SYMBOL(drm_client_modesets_dpms); + #ifdef CONFIG_DEBUG_FS static int drm_client_debugfs_internal_clients(struct seq_file *m, void *data) { diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 9dcb77dfff0a..be946d702019 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -382,200 +382,6 @@ int drm_fb_helper_debug_leave(struct fb_info *info) } EXPORT_SYMBOL(drm_fb_helper_debug_leave); -/** - * drm_client_panel_rotation() - Check panel orientation - * @modeset: DRM modeset - * @rotation: Returned rotation value - * - * This function checks if the primary plane in @modeset can hw rotate to match - * the panel orientation on its connector. - * - * Note: Currently only 0 and 180 degrees are supported. - * - * Return: - * True if the plane can do the rotation, false otherwise. - */ -bool drm_client_panel_rotation(struct drm_mode_set *modeset, unsigned int *rotation) -{ - struct drm_connector *connector = modeset->connectors[0]; - struct drm_plane *plane = modeset->crtc->primary; - u64 valid_mask = 0; - unsigned int i; - - if (!modeset->num_connectors) - return false; - - switch (connector->display_info.panel_orientation) { - case DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP: - *rotation = DRM_MODE_ROTATE_180; - break; - case DRM_MODE_PANEL_ORIENTATION_LEFT_UP: - *rotation = DRM_MODE_ROTATE_90; - break; - case DRM_MODE_PANEL_ORIENTATION_RIGHT_UP: - *rotation = DRM_MODE_ROTATE_270; - break; - default: - *rotation = DRM_MODE_ROTATE_0; - } - - /* - * TODO: support 90 / 270 degree hardware rotation, - * depending on the hardware this may require the framebuffer - * to be in a specific tiling format. - */ - if (*rotation != DRM_MODE_ROTATE_180 || !plane->rotation_property) - return false; - - for (i = 0; i < plane->rotation_property->num_values; i++) - valid_mask |= (1ULL << plane->rotation_property->values[i]); - - if (!(*rotation & valid_mask)) - return false; - - return true; -} - -static int drm_client_modesets_commit_atomic(struct drm_device *dev, struct drm_mode_set *modesets, - bool active) -{ - struct drm_plane_state *plane_state; - struct drm_plane *plane; - struct drm_atomic_state *state; - struct drm_modeset_acquire_ctx ctx; - struct drm_mode_set *mode_set; - int ret; - - drm_modeset_acquire_init(&ctx, 0); - - state = drm_atomic_state_alloc(dev); - if (!state) { - ret = -ENOMEM; - goto out_ctx; - } - - state->acquire_ctx = &ctx; -retry: - drm_for_each_plane(plane, dev) { - plane_state = drm_atomic_get_plane_state(state, plane); - if (IS_ERR(plane_state)) { - ret = PTR_ERR(plane_state); - goto out_state; - } - - plane_state->rotation = DRM_MODE_ROTATE_0; - - /* disable non-primary: */ - if (plane->type == DRM_PLANE_TYPE_PRIMARY) - continue; - - ret = __drm_atomic_helper_disable_plane(plane, plane_state); - if (ret != 0) - goto out_state; - } - - drm_client_for_each_modeset(mode_set, modesets) { - struct drm_plane *primary = mode_set->crtc->primary; - unsigned int rotation; - - if (drm_client_panel_rotation(mode_set, &rotation)) { - /* Cannot fail as we've already gotten the plane state above */ - plane_state = drm_atomic_get_new_plane_state(state, primary); - plane_state->rotation = rotation; - } - - ret = __drm_atomic_helper_set_config(mode_set, state); - if (ret != 0) - goto out_state; - - /* - * __drm_atomic_helper_set_config() sets active when a - * mode is set, unconditionally clear it if we force DPMS off - */ - if (!active) { - struct drm_crtc *crtc = mode_set->crtc; - struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc); - - crtc_state->active = false; - } - } - - ret = drm_atomic_commit(state); - -out_state: - if (ret == -EDEADLK) - goto backoff; - - drm_atomic_state_put(state); -out_ctx: - drm_modeset_drop_locks(&ctx); - drm_modeset_acquire_fini(&ctx); - - return ret; - -backoff: - drm_atomic_state_clear(state); - drm_modeset_backoff(&ctx); - - goto retry; -} - -static int drm_client_modesets_commit_legacy(struct drm_device *dev, struct drm_mode_set *modesets) -{ - struct drm_mode_set *mode_set; - struct drm_plane *plane; - int ret = 0; - - drm_modeset_lock_all(dev); - drm_for_each_plane(plane, dev) { - if (plane->type != DRM_PLANE_TYPE_PRIMARY) - drm_plane_force_disable(plane); - - if (plane->rotation_property) - drm_mode_plane_set_obj_prop(plane, - plane->rotation_property, - DRM_MODE_ROTATE_0); - } - - drm_client_for_each_modeset(mode_set, modesets) { - struct drm_crtc *crtc = mode_set->crtc; - - if (crtc->funcs->cursor_set2) { - ret = crtc->funcs->cursor_set2(crtc, NULL, 0, 0, 0, 0, 0); - if (ret) - goto out; - } else if (crtc->funcs->cursor_set) { - ret = crtc->funcs->cursor_set(crtc, NULL, 0, 0, 0); - if (ret) - goto out; - } - - ret = drm_mode_set_config_internal(mode_set); - if (ret) - goto out; - } -out: - drm_modeset_unlock_all(dev); - - return ret; -} - -/** - * drm_client_modesets_commit() - Commit CRTC configuration - * @dev: DRM device - * @modesets: Modeset array - * - * Returns: - * Zero on success or negative error code on failure. - */ -int drm_client_modesets_commit(struct drm_device *dev, struct drm_mode_set *modesets) -{ - if (drm_drv_uses_atomic_modeset(dev)) - return drm_client_modesets_commit_atomic(dev, modesets, true); - else - return drm_client_modesets_commit_legacy(dev, modesets); -} - /** * drm_fb_helper_restore_fbdev_mode_unlocked - restore fbdev configuration * @fb_helper: driver-allocated fbdev helper, can be NULL @@ -693,44 +499,6 @@ static struct sysrq_key_op sysrq_drm_fb_helper_restore_op = { static struct sysrq_key_op sysrq_drm_fb_helper_restore_op = { }; #endif -static void drm_client_modesets_dpms_legacy(struct drm_device *dev, struct drm_mode_set *modesets, - int dpms_mode) -{ - struct drm_connector *connector; - struct drm_mode_set *modeset; - int j; - - drm_modeset_lock_all(dev); - drm_client_for_each_modeset(modeset, modesets) { - if (!modeset->crtc->enabled) - continue; - - for (j = 0; j < modeset->num_connectors; j++) { - connector = modeset->connectors[j]; - connector->funcs->dpms(connector, dpms_mode); - drm_object_property_set_value(&connector->base, - dev->mode_config.dpms_property, dpms_mode); - } - } - drm_modeset_unlock_all(dev); -} - -/** - * drm_client_modesets_dpms() - Set DPMS mode - * @dev: DRM device - * @modesets: Modeset array - * @mode: DPMS mode - * - * Note: For atomic drivers @mode is reduced to on/off. - */ -void drm_client_modesets_dpms(struct drm_device *dev, struct drm_mode_set *modesets, int mode) -{ - if (drm_drv_uses_atomic_modeset(dev)) - drm_client_modesets_commit_atomic(dev, modesets, mode == DRM_MODE_DPMS_ON); - else - drm_client_modesets_dpms_legacy(dev, modesets, mode); -} - static void drm_fb_helper_dpms(struct fb_info *info, int dpms_mode) { struct drm_fb_helper *fb_helper = info->par; diff --git a/include/drm/drm_client.h b/include/drm/drm_client.h index b2efce3f7781..01e787f8bc12 100644 --- a/include/drm/drm_client.h +++ b/include/drm/drm_client.h @@ -142,6 +142,9 @@ void drm_client_framebuffer_delete(struct drm_client_buffer *buffer); struct drm_mode_set *drm_client_modesets_create(struct drm_device *dev); void drm_client_modesets_release(struct drm_mode_set *modesets); struct drm_mode_set *drm_client_find_modeset(struct drm_mode_set *modesets, struct drm_crtc *crtc); +bool drm_client_panel_rotation(struct drm_mode_set *modeset, unsigned int *rotation); +int drm_client_modesets_commit(struct drm_device *dev, struct drm_mode_set *modesets); +void drm_client_modesets_dpms(struct drm_device *dev, struct drm_mode_set *modesets, int mode); /** * drm_client_for_each_modeset() - Iterate over modesets From patchwork Tue Mar 26 17:55:40 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Noralf_Tr=C3=B8nnes?= X-Patchwork-Id: 10871849 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 26546139A for ; Tue, 26 Mar 2019 18:02:42 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 10DB01FF3E for ; Tue, 26 Mar 2019 18:02:42 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 046A42862A; Tue, 26 Mar 2019 18:02:42 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED autolearn=unavailable version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 410951FF3E for ; Tue, 26 Mar 2019 18:02:40 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 9287C6E05F; Tue, 26 Mar 2019 18:02:38 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from smtp.domeneshop.no (smtp.domeneshop.no [IPv6:2a01:5b40:0:3005::1]) by gabe.freedesktop.org (Postfix) with ESMTPS id 66ADA6E05F; Tue, 26 Mar 2019 18:02:34 +0000 (UTC) Received: from 211.81-166-168.customer.lyse.net ([81.166.168.211]:46322 helo=localhost.localdomain) by smtp.domeneshop.no with esmtpsa (TLS1.2:ECDHE_RSA_AES_128_CBC_SHA1:128) (Exim 4.84_2) (envelope-from ) id 1h8qIx-0006Mj-26; Tue, 26 Mar 2019 18:56:07 +0100 From: =?utf-8?q?Noralf_Tr=C3=B8nnes?= To: dri-devel@lists.freedesktop.org Subject: [PATCH 10/16] drm/fb-helper: Remove drm_fb_helper_connector Date: Tue, 26 Mar 2019 18:55:40 +0100 Message-Id: <20190326175546.18126-11-noralf@tronnes.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190326175546.18126-1-noralf@tronnes.org> References: <20190326175546.18126-1-noralf@tronnes.org> MIME-Version: 1.0 X-Mailman-Original-DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=tronnes.org; s=ds201810; h=Content-Transfer-Encoding:Content-Type:MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From; bh=hqf4nle+wXCfYjLnMpv1CRpK80dLsFhNZfn+gJP8OnU=; b=g3908v5bf2E2tFoVJET5a9i06fxzvq3toXJVh8MQvQ8303c69+jOpDdzJDN6TJa4KGBd1r6Cn7yor4uqksWC/X3E+3tm1BpwijYkwVket8hfR+f+b5QTeZ+UzWMbf2CT9OfyG9T3EKkn3GvuWDa3X4k5xXapSUosgcFi3NFR5FpJj7n2sWKMr13rZbUnoeE4vrYcVNxwqiqsK0Wi7P2MKcnUmpPW/Tq1kUKbI7Om1wm05hPgrwschXYVACgYXRoGj6mXKKPqcPxixqjoC8wP5yqdukSWNVBRBrCUFvU4fRSbnr1wh1OHVbyQ5xMRChPwy0xQju1nVwsUicixWO5G1g==; X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: intel-gfx@lists.freedesktop.org, mstaudt@suse.de Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Virus-Scanned: ClamAV using ClamSMTP All drivers add all their connectors so there's no need to keep around an array of available connectors. Rename functions which signature is changed since they will be moved to drm_client in a later patch. Signed-off-by: Noralf Trønnes --- checkpatch complains, but I'm unable to satisfy it: ERROR: Macros with complex values should be enclosed in parentheses #939: FILE: include/drm/drm_client.h:160: +#define drm_client_for_each_connector_iter(connector, iter) \ + drm_for_each_connector_iter(connector, iter) \ + if (connector->connector_type != DRM_MODE_CONNECTOR_WRITEBACK) Documentation/gpu/todo.rst | 3 + drivers/gpu/drm/drm_fb_helper.c | 499 ++++++++++---------------------- include/drm/drm_client.h | 15 + include/drm/drm_fb_helper.h | 80 ++--- 4 files changed, 194 insertions(+), 403 deletions(-) diff --git a/Documentation/gpu/todo.rst b/Documentation/gpu/todo.rst index 8fa08b5feab7..f6cdd1c26788 100644 --- a/Documentation/gpu/todo.rst +++ b/Documentation/gpu/todo.rst @@ -306,6 +306,9 @@ drm_fb_helper cleanup tasks - The max connector argument for drm_fb_helper_init() and drm_fb_helper_fbdev_setup() isn't used anymore and can be removed. +- The helper doesn't keep an array of connectors anymore so these can be + removed: drm_fb_helper_single_add_all_connectors(), + drm_fb_helper_add_one_connector() and drm_fb_helper_remove_one_connector(). Core refactorings ================= diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index be946d702019..de805956849d 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -92,12 +92,6 @@ static DEFINE_MUTEX(kernel_fb_helper_lock); * Setup fbdev emulation by calling drm_fb_helper_fbdev_setup() and tear it * down by calling drm_fb_helper_fbdev_teardown(). * - * Drivers that need to handle connector hotplugging (e.g. dp mst) can't use - * the setup helper and will need to do the whole four-step setup process with - * drm_fb_helper_prepare(), drm_fb_helper_init(), - * drm_fb_helper_single_add_all_connectors(), enable hotplugging and - * drm_fb_helper_initial_config() to avoid a possible race window. - * * At runtime drivers should restore the fbdev console by using * drm_fb_helper_lastclose() as their &drm_driver.lastclose callback. * They should also notify the fb helper code from updates to the output @@ -120,8 +114,7 @@ static DEFINE_MUTEX(kernel_fb_helper_lock); * encoders and connectors. To finish up the fbdev helper initialization, the * drm_fb_helper_init() function is called. To probe for all attached displays * and set up an initial configuration using the detected hardware, drivers - * should call drm_fb_helper_single_add_all_connectors() followed by - * drm_fb_helper_initial_config(). + * should call drm_fb_helper_initial_config(). * * If &drm_framebuffer_funcs.dirty is set, the * drm_fb_helper_{cfb,sys}_{write,fillrect,copyarea,imageblit} functions will @@ -134,165 +127,6 @@ static DEFINE_MUTEX(kernel_fb_helper_lock); * deferred I/O (coupled with drm_fb_helper_fbdev_teardown()). */ -#define drm_fb_helper_for_each_connector(fbh, i__) \ - for (({ lockdep_assert_held(&(fbh)->lock); }), \ - i__ = 0; i__ < (fbh)->connector_count; i__++) - -static int __drm_fb_helper_add_one_connector(struct drm_fb_helper *fb_helper, - struct drm_connector *connector) -{ - struct drm_fb_helper_connector *fb_conn; - struct drm_fb_helper_connector **temp; - unsigned int count; - - if (!drm_fbdev_emulation) - return 0; - - lockdep_assert_held(&fb_helper->lock); - - count = fb_helper->connector_count + 1; - - if (count > fb_helper->connector_info_alloc_count) { - size_t size = count * sizeof(fb_conn); - - temp = krealloc(fb_helper->connector_info, size, GFP_KERNEL); - if (!temp) - return -ENOMEM; - - fb_helper->connector_info_alloc_count = count; - fb_helper->connector_info = temp; - } - - fb_conn = kzalloc(sizeof(*fb_conn), GFP_KERNEL); - if (!fb_conn) - return -ENOMEM; - - drm_connector_get(connector); - fb_conn->connector = connector; - fb_helper->connector_info[fb_helper->connector_count++] = fb_conn; - - return 0; -} - -int drm_fb_helper_add_one_connector(struct drm_fb_helper *fb_helper, - struct drm_connector *connector) -{ - int err; - - if (!fb_helper) - return 0; - - mutex_lock(&fb_helper->lock); - err = __drm_fb_helper_add_one_connector(fb_helper, connector); - mutex_unlock(&fb_helper->lock); - - return err; -} -EXPORT_SYMBOL(drm_fb_helper_add_one_connector); - -/** - * drm_fb_helper_single_add_all_connectors() - add all connectors to fbdev - * emulation helper - * @fb_helper: fbdev initialized with drm_fb_helper_init, can be NULL - * - * This functions adds all the available connectors for use with the given - * fb_helper. This is a separate step to allow drivers to freely assign - * connectors to the fbdev, e.g. if some are reserved for special purposes or - * not adequate to be used for the fbcon. - * - * This function is protected against concurrent connector hotadds/removals - * using drm_fb_helper_add_one_connector() and - * drm_fb_helper_remove_one_connector(). - */ -int drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper) -{ - struct drm_device *dev; - struct drm_connector *connector; - struct drm_connector_list_iter conn_iter; - int i, ret = 0; - - if (!drm_fbdev_emulation || !fb_helper) - return 0; - - dev = fb_helper->dev; - - mutex_lock(&fb_helper->lock); - drm_connector_list_iter_begin(dev, &conn_iter); - drm_for_each_connector_iter(connector, &conn_iter) { - if (connector->connector_type == DRM_MODE_CONNECTOR_WRITEBACK) - continue; - - ret = __drm_fb_helper_add_one_connector(fb_helper, connector); - if (ret) - goto fail; - } - goto out; - -fail: - drm_fb_helper_for_each_connector(fb_helper, i) { - struct drm_fb_helper_connector *fb_helper_connector = - fb_helper->connector_info[i]; - - drm_connector_put(fb_helper_connector->connector); - - kfree(fb_helper_connector); - fb_helper->connector_info[i] = NULL; - } - fb_helper->connector_count = 0; -out: - drm_connector_list_iter_end(&conn_iter); - mutex_unlock(&fb_helper->lock); - - return ret; -} -EXPORT_SYMBOL(drm_fb_helper_single_add_all_connectors); - -static int __drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper, - struct drm_connector *connector) -{ - struct drm_fb_helper_connector *fb_helper_connector; - int i, j; - - if (!drm_fbdev_emulation) - return 0; - - lockdep_assert_held(&fb_helper->lock); - - drm_fb_helper_for_each_connector(fb_helper, i) { - if (fb_helper->connector_info[i]->connector == connector) - break; - } - - if (i == fb_helper->connector_count) - return -EINVAL; - fb_helper_connector = fb_helper->connector_info[i]; - drm_connector_put(fb_helper_connector->connector); - - for (j = i + 1; j < fb_helper->connector_count; j++) - fb_helper->connector_info[j - 1] = fb_helper->connector_info[j]; - - fb_helper->connector_count--; - kfree(fb_helper_connector); - - return 0; -} - -int drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper, - struct drm_connector *connector) -{ - int err; - - if (!fb_helper) - return 0; - - mutex_lock(&fb_helper->lock); - err = __drm_fb_helper_remove_one_connector(fb_helper, connector); - mutex_unlock(&fb_helper->lock); - - return err; -} -EXPORT_SYMBOL(drm_fb_helper_remove_one_connector); - static void drm_fb_helper_restore_lut_atomic(struct drm_crtc *crtc) { uint16_t *r_base, *g_base, *b_base; @@ -651,20 +485,9 @@ int drm_fb_helper_init(struct drm_device *dev, if (IS_ERR(fb_helper->modesets)) return -ENOMEM; - fb_helper->connector_info = kcalloc(dev->mode_config.num_connector, sizeof(struct drm_fb_helper_connector *), GFP_KERNEL); - if (!fb_helper->connector_info) - goto out_free; - - fb_helper->connector_info_alloc_count = dev->mode_config.num_connector; - fb_helper->connector_count = 0; - dev->fb_helper = fb_helper; return 0; -out_free: - drm_client_modesets_release(fb_helper->modesets); - - return -ENOMEM; } EXPORT_SYMBOL(drm_fb_helper_init); @@ -738,7 +561,6 @@ EXPORT_SYMBOL(drm_fb_helper_unregister_fbi); void drm_fb_helper_fini(struct drm_fb_helper *fb_helper) { struct fb_info *info; - int i; if (!fb_helper) return; @@ -769,12 +591,6 @@ void drm_fb_helper_fini(struct drm_fb_helper *fb_helper) mutex_destroy(&fb_helper->lock); drm_client_modesets_release(fb_helper->modesets); - - for (i = 0; i < fb_helper->connector_count; i++) { - drm_connector_put(fb_helper->connector_info[i]->connector); - kfree(fb_helper->connector_info[i]); - } - kfree(fb_helper->connector_info); } EXPORT_SYMBOL(drm_fb_helper_fini); @@ -1638,8 +1454,9 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper, { int ret = 0; int crtc_count = 0; - int i; + struct drm_connector_list_iter conn_iter; struct drm_fb_helper_surface_size sizes; + struct drm_connector *connector; struct drm_mode_set *mode_set; int best_depth = 0; @@ -1656,11 +1473,11 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper, if (preferred_bpp != sizes.surface_bpp) sizes.surface_depth = sizes.surface_bpp = preferred_bpp; - drm_fb_helper_for_each_connector(fb_helper, i) { - struct drm_fb_helper_connector *fb_helper_conn = fb_helper->connector_info[i]; + drm_connector_list_iter_begin(fb_helper->dev, &conn_iter); + drm_client_for_each_connector_iter(connector, &conn_iter) { struct drm_cmdline_mode *cmdline_mode; - cmdline_mode = &fb_helper_conn->connector->cmdline_mode; + cmdline_mode = &connector->cmdline_mode; if (cmdline_mode->bpp_specified) { switch (cmdline_mode->bpp) { @@ -1685,6 +1502,7 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper, break; } } + drm_connector_list_iter_end(&conn_iter); /* * If we run into a situation where, for example, the primary plane @@ -1865,26 +1683,12 @@ void drm_fb_helper_fill_var(struct fb_info *info, struct drm_fb_helper *fb_helpe } EXPORT_SYMBOL(drm_fb_helper_fill_var); -static int drm_fb_helper_probe_connector_modes(struct drm_fb_helper *fb_helper, - uint32_t maxX, - uint32_t maxY) -{ - struct drm_connector *connector; - int i, count = 0; - - drm_fb_helper_for_each_connector(fb_helper, i) { - connector = fb_helper->connector_info[i]->connector; - count += connector->funcs->fill_modes(connector, maxX, maxY); - } - - return count; -} - -struct drm_display_mode *drm_has_preferred_mode(struct drm_fb_helper_connector *fb_connector, int width, int height) +static struct drm_display_mode * +drm_connector_has_preferred_mode(struct drm_connector *connector, int width, int height) { struct drm_display_mode *mode; - list_for_each_entry(mode, &fb_connector->connector->modes, head) { + list_for_each_entry(mode, &connector->modes, head) { if (mode->hdisplay > width || mode->vdisplay > height) continue; @@ -1893,20 +1697,15 @@ struct drm_display_mode *drm_has_preferred_mode(struct drm_fb_helper_connector * } return NULL; } -EXPORT_SYMBOL(drm_has_preferred_mode); -static bool drm_has_cmdline_mode(struct drm_fb_helper_connector *fb_connector) -{ - return fb_connector->connector->cmdline_mode.specified; -} - -struct drm_display_mode *drm_pick_cmdline_mode(struct drm_fb_helper_connector *fb_helper_conn) +static struct drm_display_mode * +drm_connector_pick_cmdline_mode(struct drm_connector *connector) { struct drm_cmdline_mode *cmdline_mode; struct drm_display_mode *mode; bool prefer_non_interlace; - cmdline_mode = &fb_helper_conn->connector->cmdline_mode; + cmdline_mode = &connector->cmdline_mode; if (cmdline_mode->specified == false) return NULL; @@ -1918,7 +1717,7 @@ struct drm_display_mode *drm_pick_cmdline_mode(struct drm_fb_helper_connector *f prefer_non_interlace = !cmdline_mode->interlace; again: - list_for_each_entry(mode, &fb_helper_conn->connector->modes, head) { + list_for_each_entry(mode, &connector->modes, head) { /* check width/height */ if (mode->hdisplay != cmdline_mode->xres || mode->vdisplay != cmdline_mode->yres) @@ -1945,12 +1744,10 @@ struct drm_display_mode *drm_pick_cmdline_mode(struct drm_fb_helper_connector *f } create_mode: - mode = drm_mode_create_from_cmdline_mode(fb_helper_conn->connector->dev, - cmdline_mode); - list_add(&mode->head, &fb_helper_conn->connector->modes); + mode = drm_mode_create_from_cmdline_mode(connector->dev, cmdline_mode); + list_add(&mode->head, &connector->modes); return mode; } -EXPORT_SYMBOL(drm_pick_cmdline_mode); static bool drm_connector_enabled(struct drm_connector *connector, bool strict) { @@ -1967,15 +1764,16 @@ static bool drm_connector_enabled(struct drm_connector *connector, bool strict) return enable; } -static void drm_enable_connectors(struct drm_fb_helper *fb_helper, - bool *enabled) +static void drm_client_connectors_enabled(struct drm_connector **connectors, + unsigned int connector_count, + bool *enabled) { bool any_enabled = false; struct drm_connector *connector; int i = 0; - drm_fb_helper_for_each_connector(fb_helper, i) { - connector = fb_helper->connector_info[i]->connector; + for (i = 0; i < connector_count; i++) { + connector = connectors[i]; enabled[i] = drm_connector_enabled(connector, true); DRM_DEBUG_KMS("connector %d enabled? %s\n", connector->base.id, connector->display_info.non_desktop ? "non desktop" : enabled[i] ? "yes" : "no"); @@ -1986,28 +1784,27 @@ static void drm_enable_connectors(struct drm_fb_helper *fb_helper, if (any_enabled) return; - drm_fb_helper_for_each_connector(fb_helper, i) { - connector = fb_helper->connector_info[i]->connector; - enabled[i] = drm_connector_enabled(connector, false); - } + for (i = 0; i < connector_count; i++) + enabled[i] = drm_connector_enabled(connectors[i], false); } -static bool drm_target_cloned(struct drm_fb_helper *fb_helper, - struct drm_display_mode **modes, - struct drm_fb_offset *offsets, - bool *enabled, int width, int height) +static bool drm_client_target_cloned(struct drm_device *dev, + struct drm_connector **connectors, + unsigned int connector_count, + struct drm_display_mode **modes, + struct drm_fb_offset *offsets, + bool *enabled, int width, int height) { int count, i, j; bool can_clone = false; - struct drm_fb_helper_connector *fb_helper_conn; struct drm_display_mode *dmt_mode, *mode; /* only contemplate cloning in the single crtc case */ - if (fb_helper->dev->mode_config.num_crtc > 1) + if (dev->mode_config.num_crtc > 1) return false; count = 0; - drm_fb_helper_for_each_connector(fb_helper, i) { + for (i = 0; i < connector_count; i++) { if (enabled[i]) count++; } @@ -2018,11 +1815,10 @@ static bool drm_target_cloned(struct drm_fb_helper *fb_helper, /* check the command line or if nothing common pick 1024x768 */ can_clone = true; - drm_fb_helper_for_each_connector(fb_helper, i) { + for (i = 0; i < connector_count; i++) { if (!enabled[i]) continue; - fb_helper_conn = fb_helper->connector_info[i]; - modes[i] = drm_pick_cmdline_mode(fb_helper_conn); + modes[i] = drm_connector_pick_cmdline_mode(connectors[i]); if (!modes[i]) { can_clone = false; break; @@ -2046,14 +1842,13 @@ static bool drm_target_cloned(struct drm_fb_helper *fb_helper, /* try and find a 1024x768 mode on each connector */ can_clone = true; - dmt_mode = drm_mode_find_dmt(fb_helper->dev, 1024, 768, 60, false); + dmt_mode = drm_mode_find_dmt(dev, 1024, 768, 60, false); - drm_fb_helper_for_each_connector(fb_helper, i) { + for (i = 0; i < connector_count; i++) { if (!enabled[i]) continue; - fb_helper_conn = fb_helper->connector_info[i]; - list_for_each_entry(mode, &fb_helper_conn->connector->modes, head) { + list_for_each_entry(mode, &connectors[i]->modes, head) { if (drm_mode_match(mode, dmt_mode, DRM_MODE_MATCH_TIMINGS | DRM_MODE_MATCH_CLOCK | @@ -2073,30 +1868,31 @@ static bool drm_target_cloned(struct drm_fb_helper *fb_helper, return false; } -static int drm_get_tile_offsets(struct drm_fb_helper *fb_helper, - struct drm_display_mode **modes, - struct drm_fb_offset *offsets, - int idx, - int h_idx, int v_idx) +static int drm_client_get_tile_offsets(struct drm_connector **connectors, + unsigned int connector_count, + struct drm_display_mode **modes, + struct drm_fb_offset *offsets, + int idx, + int h_idx, int v_idx) { - struct drm_fb_helper_connector *fb_helper_conn; + struct drm_connector *connector; int i; int hoffset = 0, voffset = 0; - drm_fb_helper_for_each_connector(fb_helper, i) { - fb_helper_conn = fb_helper->connector_info[i]; - if (!fb_helper_conn->connector->has_tile) + for (i = 0; i < connector_count; i++) { + connector = connectors[i]; + if (!connector->has_tile) continue; if (!modes[i] && (h_idx || v_idx)) { DRM_DEBUG_KMS("no modes for connector tiled %d %d\n", i, - fb_helper_conn->connector->base.id); + connector->base.id); continue; } - if (fb_helper_conn->connector->tile_h_loc < h_idx) + if (connector->tile_h_loc < h_idx) hoffset += modes[i]->hdisplay; - if (fb_helper_conn->connector->tile_v_loc < v_idx) + if (connector->tile_v_loc < v_idx) voffset += modes[i]->vdisplay; } offsets[idx].x = hoffset; @@ -2105,20 +1901,21 @@ static int drm_get_tile_offsets(struct drm_fb_helper *fb_helper, return 0; } -static bool drm_target_preferred(struct drm_fb_helper *fb_helper, - struct drm_display_mode **modes, - struct drm_fb_offset *offsets, - bool *enabled, int width, int height) +static bool drm_client_target_preferred(struct drm_connector **connectors, + unsigned int connector_count, + struct drm_display_mode **modes, + struct drm_fb_offset *offsets, + bool *enabled, int width, int height) { - struct drm_fb_helper_connector *fb_helper_conn; - const u64 mask = BIT_ULL(fb_helper->connector_count) - 1; + const u64 mask = BIT_ULL(connector_count) - 1; + struct drm_connector *connector; u64 conn_configured = 0; int tile_pass = 0; int i; retry: - drm_fb_helper_for_each_connector(fb_helper, i) { - fb_helper_conn = fb_helper->connector_info[i]; + for (i = 0; i < connector_count; i++) { + connector = connectors[i]; if (conn_configured & BIT_ULL(i)) continue; @@ -2129,17 +1926,17 @@ static bool drm_target_preferred(struct drm_fb_helper *fb_helper, } /* first pass over all the untiled connectors */ - if (tile_pass == 0 && fb_helper_conn->connector->has_tile) + if (tile_pass == 0 && connector->has_tile) continue; if (tile_pass == 1) { - if (fb_helper_conn->connector->tile_h_loc != 0 || - fb_helper_conn->connector->tile_v_loc != 0) + if (connector->tile_h_loc != 0 || + connector->tile_v_loc != 0) continue; } else { - if (fb_helper_conn->connector->tile_h_loc != tile_pass - 1 && - fb_helper_conn->connector->tile_v_loc != tile_pass - 1) + if (connector->tile_h_loc != tile_pass - 1 && + connector->tile_v_loc != tile_pass - 1) /* if this tile_pass doesn't cover any of the tiles - keep going */ continue; @@ -2147,22 +1944,22 @@ static bool drm_target_preferred(struct drm_fb_helper *fb_helper, * find the tile offsets for this pass - need to find * all tiles left and above */ - drm_get_tile_offsets(fb_helper, modes, offsets, - i, fb_helper_conn->connector->tile_h_loc, fb_helper_conn->connector->tile_v_loc); + drm_client_get_tile_offsets(connectors, connector_count, modes, offsets, i, + connector->tile_h_loc, connector->tile_v_loc); } DRM_DEBUG_KMS("looking for cmdline mode on connector %d\n", - fb_helper_conn->connector->base.id); + connector->base.id); /* got for command line mode first */ - modes[i] = drm_pick_cmdline_mode(fb_helper_conn); + modes[i] = drm_connector_pick_cmdline_mode(connector); if (!modes[i]) { DRM_DEBUG_KMS("looking for preferred mode on connector %d %d\n", - fb_helper_conn->connector->base.id, fb_helper_conn->connector->tile_group ? fb_helper_conn->connector->tile_group->id : 0); - modes[i] = drm_has_preferred_mode(fb_helper_conn, width, height); + connector->base.id, connector->tile_group ? connector->tile_group->id : 0); + modes[i] = drm_connector_has_preferred_mode(connector, width, height); } /* No preferred modes, pick one off the list */ - if (!modes[i] && !list_empty(&fb_helper_conn->connector->modes)) { - list_for_each_entry(modes[i], &fb_helper_conn->connector->modes, head) + if (!modes[i] && !list_empty(&connector->modes)) { + list_for_each_entry(modes[i], &connector->modes, head) break; } DRM_DEBUG_KMS("found mode %s\n", modes[i] ? modes[i]->name : @@ -2191,40 +1988,41 @@ static bool connector_has_possible_crtc(struct drm_connector *connector, return false; } -static int drm_pick_crtcs(struct drm_fb_helper *fb_helper, - struct drm_mode_set *modesets, - struct drm_crtc **best_crtcs, - struct drm_display_mode **modes, - int n, int width, int height) +static int drm_client_pick_crtcs(struct drm_device *dev, + struct drm_mode_set *modesets, + struct drm_connector **connectors, + unsigned int connector_count, + struct drm_crtc **best_crtcs, + struct drm_display_mode **modes, + int n, int width, int height) { struct drm_connector *connector; int my_score, best_score, score; struct drm_crtc **crtcs, *crtc; struct drm_mode_set *modeset; - struct drm_fb_helper_connector *fb_helper_conn; int o; - if (n == fb_helper->connector_count) + if (n == connector_count) return 0; - fb_helper_conn = fb_helper->connector_info[n]; - connector = fb_helper_conn->connector; + connector = connectors[n]; best_crtcs[n] = NULL; - best_score = drm_pick_crtcs(fb_helper, modesets, best_crtcs, modes, n + 1, width, height); + best_score = drm_client_pick_crtcs(dev, modesets, connectors, connector_count, + best_crtcs, modes, n + 1, width, height); if (modes[n] == NULL) return best_score; - crtcs = kcalloc(fb_helper->connector_count, sizeof(*crtcs), GFP_KERNEL); + crtcs = kcalloc(connector_count, sizeof(*crtcs), GFP_KERNEL); if (!crtcs) return best_score; my_score = 1; if (connector->status == connector_status_connected) my_score++; - if (drm_has_cmdline_mode(fb_helper_conn)) + if (connector->cmdline_mode.specified) my_score++; - if (drm_has_preferred_mode(fb_helper_conn, width, height)) + if (drm_connector_has_preferred_mode(connector, width, height)) my_score++; /* @@ -2243,7 +2041,7 @@ static int drm_pick_crtcs(struct drm_fb_helper *fb_helper, if (o < n) { /* ignore cloning unless only a single crtc */ - if (fb_helper->dev->mode_config.num_crtc > 1) + if (dev->mode_config.num_crtc > 1) continue; if (!drm_mode_equal(modes[o], modes[n])) @@ -2252,12 +2050,11 @@ static int drm_pick_crtcs(struct drm_fb_helper *fb_helper, crtcs[n] = crtc; memcpy(crtcs, best_crtcs, n * sizeof(*crtcs)); - score = my_score + drm_pick_crtcs(fb_helper, modesets, crtcs, modes, n + 1, - width, height); + score = my_score + drm_client_pick_crtcs(dev, modesets, connectors, connector_count, + crtcs, modes, n + 1, width, height); if (score > best_score) { best_score = score; - memcpy(best_crtcs, crtcs, - fb_helper->connector_count * sizeof(*crtcs)); + memcpy(best_crtcs, crtcs, connector_count * sizeof(*crtcs)); } } @@ -2266,14 +2063,15 @@ static int drm_pick_crtcs(struct drm_fb_helper *fb_helper, } /* Try to read the BIOS display configuration and use it for the initial config */ -static bool drm_fb_helper_firmware_config(struct drm_fb_helper *fb_helper, - struct drm_crtc **crtcs, - struct drm_display_mode **modes, - struct drm_fb_offset *offsets, - bool *enabled, int width, int height) +static bool drm_client_firmware_config(struct drm_device *dev, + struct drm_connector **connectors, + unsigned int connector_count, + struct drm_crtc **crtcs, + struct drm_display_mode **modes, + struct drm_fb_offset *offsets, + bool *enabled, int width, int height) { - struct drm_device *dev = fb_helper->dev; - unsigned int count = min(fb_helper->connector_count, BITS_PER_LONG); + unsigned int count = min_t(unsigned int, connector_count, BITS_PER_LONG); unsigned long conn_configured, conn_seq; int i, j; bool *save_enabled; @@ -2296,13 +2094,11 @@ static bool drm_fb_helper_firmware_config(struct drm_fb_helper *fb_helper, conn_configured = 0; retry: for (i = 0; i < count; i++) { - struct drm_fb_helper_connector *fb_conn; struct drm_connector *connector; struct drm_encoder *encoder; struct drm_crtc *new_crtc; - fb_conn = fb_helper->connector_info[i]; - connector = fb_conn->connector; + connector = connectors[i]; if (conn_configured & BIT(i)) continue; @@ -2360,14 +2156,13 @@ static bool drm_fb_helper_firmware_config(struct drm_fb_helper *fb_helper, connector->name); /* go for command line mode first */ - modes[i] = drm_pick_cmdline_mode(fb_conn); + modes[i] = drm_connector_pick_cmdline_mode(connector); /* try for preferred next */ if (!modes[i]) { DRM_DEBUG_KMS("looking for preferred mode on connector %s %d\n", connector->name, connector->has_tile); - modes[i] = drm_has_preferred_mode(fb_conn, width, - height); + modes[i] = drm_connector_has_preferred_mode(connector, width, height); } /* No preferred mode marked by the EDID? Are there any modes? */ @@ -2444,10 +2239,14 @@ static bool drm_fb_helper_firmware_config(struct drm_fb_helper *fb_helper, static void drm_setup_crtcs(struct drm_fb_helper *fb_helper, u32 width, u32 height) { + struct drm_connector *connector, **connectors = NULL; + struct drm_connector_list_iter conn_iter; struct drm_device *dev = fb_helper->dev; + struct drm_mode_set *modesets = NULL; + unsigned int total_modes_count = 0; + unsigned int connector_count = 0; struct drm_display_mode **modes; struct drm_fb_offset *offsets; - struct drm_mode_set *modesets; struct drm_crtc **crtcs; bool *enabled; int i; @@ -2456,52 +2255,68 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper, /* prevent concurrent modification of connector_count by hotplug */ lockdep_assert_held(&fb_helper->lock); + drm_connector_list_iter_begin(dev, &conn_iter); + drm_client_for_each_connector_iter(connector, &conn_iter) { + struct drm_connector **tmp; + + tmp = krealloc(connectors, (connector_count + 1) * sizeof(*connectors), GFP_KERNEL); + if (!tmp) + goto free_connectors; + + connectors = tmp; + drm_connector_get(connector); + connectors[connector_count++] = connector; + } + drm_connector_list_iter_end(&conn_iter); + + if (!connector_count) + return; + modesets = drm_client_modesets_create(dev); - crtcs = kcalloc(fb_helper->connector_count, sizeof(*crtcs), GFP_KERNEL); - modes = kcalloc(fb_helper->connector_count, - sizeof(struct drm_display_mode *), GFP_KERNEL); - offsets = kcalloc(fb_helper->connector_count, - sizeof(struct drm_fb_offset), GFP_KERNEL); - enabled = kcalloc(fb_helper->connector_count, - sizeof(bool), GFP_KERNEL); + crtcs = kcalloc(connector_count, sizeof(*crtcs), GFP_KERNEL); + modes = kcalloc(connector_count, sizeof(*modes), GFP_KERNEL); + offsets = kcalloc(connector_count, sizeof(*offsets), GFP_KERNEL); + enabled = kcalloc(connector_count, sizeof(bool), GFP_KERNEL); if (IS_ERR(modesets) || !crtcs || !modes || !enabled || !offsets) { DRM_ERROR("Memory allocation failed\n"); goto out; } mutex_lock(&fb_helper->dev->mode_config.mutex); - if (drm_fb_helper_probe_connector_modes(fb_helper, width, height) == 0) + for (i = 0; i < connector_count; i++) + total_modes_count += connectors[i]->funcs->fill_modes(connectors[i], width, height); + if (!total_modes_count) DRM_DEBUG_KMS("No connectors reported connected with modes\n"); - drm_enable_connectors(fb_helper, enabled); + drm_client_connectors_enabled(connectors, connector_count, enabled); - if (!drm_fb_helper_firmware_config(fb_helper, crtcs, modes, offsets, - enabled, width, height)) { - memset(modes, 0, fb_helper->connector_count*sizeof(modes[0])); - memset(crtcs, 0, fb_helper->connector_count*sizeof(crtcs[0])); - memset(offsets, 0, fb_helper->connector_count*sizeof(offsets[0])); + if (!drm_client_firmware_config(dev, connectors, connector_count, crtcs, + modes, offsets, enabled, width, height)) { + memset(modes, 0, connector_count * sizeof(*modes)); + memset(crtcs, 0, connector_count * sizeof(*crtcs)); + memset(offsets, 0, connector_count * sizeof(*offsets)); - if (!drm_target_cloned(fb_helper, modes, offsets, - enabled, width, height) && - !drm_target_preferred(fb_helper, modes, offsets, - enabled, width, height)) + if (!drm_client_target_cloned(dev, connectors, connector_count, modes, + offsets, enabled, width, height) && + !drm_client_target_preferred(connectors, connector_count, modes, + offsets, enabled, width, height)) DRM_ERROR("Unable to find initial modes\n"); DRM_DEBUG_KMS("picking CRTCs for %dx%d config\n", width, height); - drm_pick_crtcs(fb_helper, modesets, crtcs, modes, 0, width, height); + drm_client_pick_crtcs(dev, modesets, connectors, connector_count, + crtcs, modes, 0, width, height); } mutex_unlock(&fb_helper->dev->mode_config.mutex); - drm_fb_helper_for_each_connector(fb_helper, i) { + for (i = 0; i < connector_count; i++) { struct drm_display_mode *mode = modes[i]; struct drm_crtc *crtc = crtcs[i]; struct drm_fb_offset *offset = &offsets[i]; if (mode && crtc) { struct drm_mode_set *modeset = drm_client_find_modeset(modesets, crtc); - struct drm_connector *connector = - fb_helper->connector_info[i]->connector; + struct drm_connector *connector = connectors[i]; DRM_DEBUG_KMS("desired mode %s set on crtc %d (%d,%d)\n", mode->name, crtc->base.id, offset->x, offset->y); @@ -2524,6 +2339,13 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper, kfree(modes); kfree(offsets); kfree(enabled); +free_connectors: + if (connectors) { + for (i = 0; i < connector_count; i++) + drm_connector_put(connectors[i]); + kfree(connectors); + } + drm_client_modesets_release(modesets); } @@ -2536,10 +2358,11 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper, */ static void drm_setup_crtcs_fb(struct drm_fb_helper *fb_helper) { + struct drm_connector_list_iter conn_iter; struct fb_info *info = fb_helper->fbdev; unsigned int rotation, sw_rotations = 0; + struct drm_connector *connector; struct drm_mode_set *modeset; - int i; drm_client_for_each_modeset(modeset, fb_helper->modesets) { if (!modeset->num_connectors) @@ -2554,10 +2377,8 @@ static void drm_setup_crtcs_fb(struct drm_fb_helper *fb_helper) sw_rotations |= rotation; } - mutex_lock(&fb_helper->dev->mode_config.mutex); - drm_fb_helper_for_each_connector(fb_helper, i) { - struct drm_connector *connector = - fb_helper->connector_info[i]->connector; + drm_connector_list_iter_begin(fb_helper->dev, &conn_iter); + drm_client_for_each_connector_iter(connector, &conn_iter) { /* use first connected connector for the physical dimensions */ if (connector->status == connector_status_connected) { @@ -2566,7 +2387,7 @@ static void drm_setup_crtcs_fb(struct drm_fb_helper *fb_helper) break; } } - mutex_unlock(&fb_helper->dev->mode_config.mutex); + drm_connector_list_iter_end(&conn_iter); switch (sw_rotations) { case DRM_MODE_ROTATE_0: @@ -2803,12 +2624,6 @@ int drm_fb_helper_fbdev_setup(struct drm_device *dev, return ret; } - ret = drm_fb_helper_single_add_all_connectors(fb_helper); - if (ret < 0) { - DRM_DEV_ERROR(dev->dev, "fbdev: Failed to add connectors (ret=%d)\n", ret); - goto err_drm_fb_helper_fini; - } - if (!drm_drv_uses_atomic_modeset(dev)) drm_helper_disable_unused_functions(dev); @@ -3118,10 +2933,6 @@ static int drm_fbdev_client_hotplug(struct drm_client_dev *client) if (ret) goto err; - ret = drm_fb_helper_single_add_all_connectors(fb_helper); - if (ret) - goto err_cleanup; - if (!drm_drv_uses_atomic_modeset(dev)) drm_helper_disable_unused_functions(dev); diff --git a/include/drm/drm_client.h b/include/drm/drm_client.h index 01e787f8bc12..a55f5ecae64a 100644 --- a/include/drm/drm_client.h +++ b/include/drm/drm_client.h @@ -5,6 +5,7 @@ #include +#include #include struct drm_client_dev; @@ -146,6 +147,20 @@ bool drm_client_panel_rotation(struct drm_mode_set *modeset, unsigned int *rotat int drm_client_modesets_commit(struct drm_device *dev, struct drm_mode_set *modesets); void drm_client_modesets_dpms(struct drm_device *dev, struct drm_mode_set *modesets, int mode); +/** + * drm_client_for_each_connector_iter - connector_list iterator macro + * @connector: &struct drm_connector pointer used as cursor + * @iter: &struct drm_connector_list_iter + * + * This iterates the connectors that are useable for internal clients (excludes + * writeback connectors). + * + * For more info see drm_for_each_connector_iter(). + */ +#define drm_client_for_each_connector_iter(connector, iter) \ + drm_for_each_connector_iter(connector, iter) \ + if (connector->connector_type != DRM_MODE_CONNECTOR_WRITEBACK) + /** * drm_client_for_each_modeset() - Iterate over modesets * @modeset: &drm_mode_set loop cursor diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h index 905697c37c5b..946bf179e96e 100644 --- a/include/drm/drm_fb_helper.h +++ b/include/drm/drm_fb_helper.h @@ -98,16 +98,10 @@ struct drm_fb_helper_funcs { struct drm_fb_helper_surface_size *sizes); }; -struct drm_fb_helper_connector { - struct drm_connector *connector; -}; - /** * struct drm_fb_helper - main structure to emulate fbdev on top of KMS * @fb: Scanout framebuffer object * @dev: DRM device - * @connector_count: number of connected connectors - * @connector_info_alloc_count: size of connector_info * @funcs: driver callbacks for fb helper * @fbdev: emulated fbdev device info struct * @pseudo_palette: fake palette of 16 colors @@ -145,15 +139,6 @@ struct drm_fb_helper { */ struct drm_mode_set *modesets; - int connector_count; - int connector_info_alloc_count; - /** - * @connector_info: - * - * Array of per-connector information. Do not iterate directly, but use - * drm_fb_helper_for_each_connector. - */ - struct drm_fb_helper_connector **connector_info; const struct drm_fb_helper_funcs *funcs; struct fb_info *fbdev; u32 pseudo_palette[17]; @@ -294,18 +279,8 @@ int drm_fb_helper_ioctl(struct fb_info *info, unsigned int cmd, int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper); int drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, int bpp_sel); -int drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper); int drm_fb_helper_debug_enter(struct fb_info *info); int drm_fb_helper_debug_leave(struct fb_info *info); -struct drm_display_mode * -drm_has_preferred_mode(struct drm_fb_helper_connector *fb_connector, - int width, int height); -struct drm_display_mode * -drm_pick_cmdline_mode(struct drm_fb_helper_connector *fb_helper_conn); - -int drm_fb_helper_add_one_connector(struct drm_fb_helper *fb_helper, struct drm_connector *connector); -int drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper, - struct drm_connector *connector); int drm_fb_helper_fbdev_setup(struct drm_device *dev, struct drm_fb_helper *fb_helper, @@ -484,12 +459,6 @@ static inline int drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, return 0; } -static inline int -drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper) -{ - return 0; -} - static inline int drm_fb_helper_debug_enter(struct fb_info *info) { return 0; @@ -500,34 +469,6 @@ static inline int drm_fb_helper_debug_leave(struct fb_info *info) return 0; } -static inline struct drm_display_mode * -drm_has_preferred_mode(struct drm_fb_helper_connector *fb_connector, - int width, int height) -{ - return NULL; -} - -static inline struct drm_display_mode * -drm_pick_cmdline_mode(struct drm_fb_helper_connector *fb_helper_conn, - int width, int height) -{ - return NULL; -} - -static inline int -drm_fb_helper_add_one_connector(struct drm_fb_helper *fb_helper, - struct drm_connector *connector) -{ - return 0; -} - -static inline int -drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper, - struct drm_connector *connector) -{ - return 0; -} - static inline int drm_fb_helper_fbdev_setup(struct drm_device *dev, struct drm_fb_helper *fb_helper, @@ -569,6 +510,27 @@ drm_fbdev_generic_setup(struct drm_device *dev, unsigned int preferred_bpp) #endif +/* TODO: There's a todo entry to remove these three */ +static inline int +drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper) +{ + return 0; +} + +static inline int +drm_fb_helper_add_one_connector(struct drm_fb_helper *fb_helper, + struct drm_connector *connector) +{ + return 0; +} + +static inline int +drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper, + struct drm_connector *connector) +{ + return 0; +} + /** * drm_fb_helper_remove_conflicting_framebuffers - remove firmware-configured framebuffers * @a: memory range, users of which are to be removed From patchwork Tue Mar 26 17:55:41 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Noralf_Tr=C3=B8nnes?= X-Patchwork-Id: 10871853 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id E073E922 for ; Tue, 26 Mar 2019 18:02:47 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id CF4C41FF3E for ; Tue, 26 Mar 2019 18:02:47 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id C2E0B2862A; Tue, 26 Mar 2019 18:02:47 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED autolearn=unavailable version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 56DA51FF3E for ; Tue, 26 Mar 2019 18:02:47 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 8E48E6E075; Tue, 26 Mar 2019 18:02:46 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from smtp.domeneshop.no (smtp.domeneshop.no [IPv6:2a01:5b40:0:3005::1]) by gabe.freedesktop.org (Postfix) with ESMTPS id B7C636E075; Tue, 26 Mar 2019 18:02:37 +0000 (UTC) Received: from 211.81-166-168.customer.lyse.net ([81.166.168.211]:46322 helo=localhost.localdomain) by smtp.domeneshop.no with esmtpsa (TLS1.2:ECDHE_RSA_AES_128_CBC_SHA1:128) (Exim 4.84_2) (envelope-from ) id 1h8qIx-0006Mj-9a; Tue, 26 Mar 2019 18:56:07 +0100 From: =?utf-8?q?Noralf_Tr=C3=B8nnes?= To: dri-devel@lists.freedesktop.org Subject: [PATCH 11/16] drm/fb-helper: Prepare to move out modeset config code Date: Tue, 26 Mar 2019 18:55:41 +0100 Message-Id: <20190326175546.18126-12-noralf@tronnes.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190326175546.18126-1-noralf@tronnes.org> References: <20190326175546.18126-1-noralf@tronnes.org> MIME-Version: 1.0 X-Mailman-Original-DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=tronnes.org; s=ds201810; h=Content-Transfer-Encoding:Content-Type:MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From; bh=f2t6yK0nAg9QjgNUMJyvCkLbW9SCqvwQIfbUuW1QlvA=; b=fLinQ1i16RenaWQMS0KBBSb4v2gmGhr1CjSzpbExRAkEt0dNHqo7gl5hSSCNddVzAQydTorO0Lz/df/UpW9KN+Yf2tlIwTtNG8MQLzjuwcARrPdpar/BBGyYEz4SVLhWdEbQ9U8qTUTBe3lE3rgTHXcscCmCBuJkFmMUbuC4bqPx4gxiJVw+/f5v04zOs0Ey5ip+7lxIu9fwqkZDQCySdUoAbXHpgTFJUetOkmK54mHwIGgPKzDLsxYTjufxF2LYW7YeOTjIkfm2YNYS2q7iS20uLE2KuAzgNbiSlfdBPzEErldwGS3mEp5mz5blov6lHLTA6UQPj7jQS1EprNAZ0Q==; X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: intel-gfx@lists.freedesktop.org, mstaudt@suse.de Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Virus-Scanned: ClamAV using ClamSMTP This prepares the modeset code so it can be moved out as-is in the next patch. Signed-off-by: Noralf Trønnes --- drivers/gpu/drm/drm_fb_helper.c | 75 +++++++++++++++++++++++++-------- include/drm/drm_fb_helper.h | 4 -- 2 files changed, 57 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index de805956849d..afe4d4220e4d 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -45,6 +45,10 @@ #include "drm_crtc_internal.h" #include "drm_crtc_helper_internal.h" +struct drm_client_offset { + int x, y; +}; + static bool drm_fbdev_emulation = true; module_param_named(fbdev_emulation, drm_fbdev_emulation, bool, 0600); MODULE_PARM_DESC(fbdev_emulation, @@ -1792,7 +1796,7 @@ static bool drm_client_target_cloned(struct drm_device *dev, struct drm_connector **connectors, unsigned int connector_count, struct drm_display_mode **modes, - struct drm_fb_offset *offsets, + struct drm_client_offset *offsets, bool *enabled, int width, int height) { int count, i, j; @@ -1871,7 +1875,7 @@ static bool drm_client_target_cloned(struct drm_device *dev, static int drm_client_get_tile_offsets(struct drm_connector **connectors, unsigned int connector_count, struct drm_display_mode **modes, - struct drm_fb_offset *offsets, + struct drm_client_offset *offsets, int idx, int h_idx, int v_idx) { @@ -1904,7 +1908,7 @@ static int drm_client_get_tile_offsets(struct drm_connector **connectors, static bool drm_client_target_preferred(struct drm_connector **connectors, unsigned int connector_count, struct drm_display_mode **modes, - struct drm_fb_offset *offsets, + struct drm_client_offset *offsets, bool *enabled, int width, int height) { const u64 mask = BIT_ULL(connector_count) - 1; @@ -2068,7 +2072,7 @@ static bool drm_client_firmware_config(struct drm_device *dev, unsigned int connector_count, struct drm_crtc **crtcs, struct drm_display_mode **modes, - struct drm_fb_offset *offsets, + struct drm_client_offset *offsets, bool *enabled, int width, int height) { unsigned int count = min_t(unsigned int, connector_count, BITS_PER_LONG); @@ -2236,32 +2240,51 @@ static bool drm_client_firmware_config(struct drm_device *dev, return ret; } -static void drm_setup_crtcs(struct drm_fb_helper *fb_helper, - u32 width, u32 height) +/** + * drm_client_modesets_probe() - Probe for displays + * @dev: DRM device + * @width: Maximum display mode width (optional) + * @height: Maximum display mode height (optional) + * + * This function tries to set up pipelines for enabled connectors and returns + * the CRTC config as a &drm_mode_set array. + * + * Use drm_client_modesets_release() to free the array and its resources. + * + * Returns: + * A &drm_mode_set array on success, NULL if no connectors are found + * or error pointer on failure. + */ +struct drm_mode_set * +drm_client_modesets_probe(struct drm_device *dev, unsigned int width, unsigned int height) { struct drm_connector *connector, **connectors = NULL; struct drm_connector_list_iter conn_iter; - struct drm_device *dev = fb_helper->dev; struct drm_mode_set *modesets = NULL; unsigned int total_modes_count = 0; + struct drm_client_offset *offsets; unsigned int connector_count = 0; struct drm_display_mode **modes; - struct drm_fb_offset *offsets; struct drm_crtc **crtcs; + int i, ret = 0; bool *enabled; - int i; DRM_DEBUG_KMS("\n"); - /* prevent concurrent modification of connector_count by hotplug */ - lockdep_assert_held(&fb_helper->lock); + + if (!width) + width = dev->mode_config.max_width; + if (!height) + height = dev->mode_config.max_height; drm_connector_list_iter_begin(dev, &conn_iter); drm_client_for_each_connector_iter(connector, &conn_iter) { struct drm_connector **tmp; tmp = krealloc(connectors, (connector_count + 1) * sizeof(*connectors), GFP_KERNEL); - if (!tmp) + if (!tmp) { + ret = -ENOMEM; goto free_connectors; + } connectors = tmp; drm_connector_get(connector); @@ -2270,7 +2293,7 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper, drm_connector_list_iter_end(&conn_iter); if (!connector_count) - return; + return NULL; modesets = drm_client_modesets_create(dev); crtcs = kcalloc(connector_count, sizeof(*crtcs), GFP_KERNEL); @@ -2279,10 +2302,11 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper, enabled = kcalloc(connector_count, sizeof(bool), GFP_KERNEL); if (IS_ERR(modesets) || !crtcs || !modes || !enabled || !offsets) { DRM_ERROR("Memory allocation failed\n"); + ret = -ENOMEM; goto out; } - mutex_lock(&fb_helper->dev->mode_config.mutex); + mutex_lock(&dev->mode_config.mutex); for (i = 0; i < connector_count; i++) total_modes_count += connectors[i]->funcs->fill_modes(connectors[i], width, height); if (!total_modes_count) @@ -2307,12 +2331,12 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper, drm_client_pick_crtcs(dev, modesets, connectors, connector_count, crtcs, modes, 0, width, height); } - mutex_unlock(&fb_helper->dev->mode_config.mutex); + mutex_unlock(&dev->mode_config.mutex); for (i = 0; i < connector_count; i++) { struct drm_display_mode *mode = modes[i]; struct drm_crtc *crtc = crtcs[i]; - struct drm_fb_offset *offset = &offsets[i]; + struct drm_client_offset *offset = &offsets[i]; if (mode && crtc) { struct drm_mode_set *modeset = drm_client_find_modeset(modesets, crtc); @@ -2332,8 +2356,6 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper, modeset->y = offset->y; } } - - swap(fb_helper->modesets, modesets); out: kfree(crtcs); kfree(modes); @@ -2346,6 +2368,23 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper, kfree(connectors); } + if (ret) { + drm_client_modesets_release(modesets); + return ERR_PTR(ret); + } + + return modesets; +} + +static void drm_setup_crtcs(struct drm_fb_helper *fb_helper, u32 width, u32 height) +{ + struct drm_mode_set *modesets; + + modesets = drm_client_modesets_probe(fb_helper->dev, width, height); + if (IS_ERR_OR_NULL(modesets)) + return; + + swap(fb_helper->modesets, modesets); drm_client_modesets_release(modesets); } diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h index 946bf179e96e..bd38d5c85c92 100644 --- a/include/drm/drm_fb_helper.h +++ b/include/drm/drm_fb_helper.h @@ -42,10 +42,6 @@ enum mode_set_atomic { ENTER_ATOMIC_MODE_SET, }; -struct drm_fb_offset { - int x, y; -}; - /** * struct drm_fb_helper_surface_size - describes fbdev size and scanout surface size * @fb_width: fbdev width From patchwork Tue Mar 26 17:55:42 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Noralf_Tr=C3=B8nnes?= X-Patchwork-Id: 10871839 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 274F9922 for ; Tue, 26 Mar 2019 18:02:34 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 10A961FF3E for ; Tue, 26 Mar 2019 18:02:34 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 04582284B9; Tue, 26 Mar 2019 18:02:34 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id EEEDC1FF3E for ; Tue, 26 Mar 2019 18:02:31 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id ED4E96E03B; Tue, 26 Mar 2019 18:02:28 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from smtp.domeneshop.no (smtp.domeneshop.no [IPv6:2a01:5b40:0:3005::1]) by gabe.freedesktop.org (Postfix) with ESMTPS id 0BD9F6E03B; Tue, 26 Mar 2019 18:02:28 +0000 (UTC) Received: from 211.81-166-168.customer.lyse.net ([81.166.168.211]:46322 helo=localhost.localdomain) by smtp.domeneshop.no with esmtpsa (TLS1.2:ECDHE_RSA_AES_128_CBC_SHA1:128) (Exim 4.84_2) (envelope-from ) id 1h8qIx-0006Mj-Ex; Tue, 26 Mar 2019 18:56:07 +0100 From: =?utf-8?q?Noralf_Tr=C3=B8nnes?= To: dri-devel@lists.freedesktop.org Subject: [PATCH 12/16] drm/fb-helper: Move out modeset config code Date: Tue, 26 Mar 2019 18:55:42 +0100 Message-Id: <20190326175546.18126-13-noralf@tronnes.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190326175546.18126-1-noralf@tronnes.org> References: <20190326175546.18126-1-noralf@tronnes.org> MIME-Version: 1.0 X-Mailman-Original-DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=tronnes.org; s=ds201810; h=Content-Transfer-Encoding:Content-Type:MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From; bh=RPoir3zN4/d5CRjI4UXHkYc47N/ozVPRksaoTxVIS98=; b=OvqANgl5/glIh1nZOW3nKkbpltuMCmTxnXnKeSQB1VhwhhV2qvw/Cj5VkE5qf7XNfYkP6kS5Ks2GKtNQ2AYcoxx/nqJT+iHugUpVt6Ad8swZX/wrECVyBa6pletIkTMZVUkU/5OzLTHSL30FtNTLesbxOAtzQYIvVcZ9jTSh7YNQ9J7AOd3RUEvS3xDchYdxYoy0RcKOHwmMh3JWWvA6TIQKuTn/+OiMFD59In95ZsGhtZXO0nFaHWjCrjlXceD6H2oZlSroW1STOacwKjGRM+OXLAs+QU1gViW+GUHxnzdLQbS5AbDzF2aX73AeNC0O1CV3M3bShnYYz8tyardTYw==; X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: intel-gfx@lists.freedesktop.org, mstaudt@suse.de Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Virus-Scanned: ClamAV using ClamSMTP No functional changes, just moving code as-is and fixing includes. There is one addition and that is exporting drm_client_modesets_probe(). Signed-off-by: Noralf Trønnes --- drivers/gpu/drm/drm_client.c | 698 ++++++++++++++++++++++++++++++++ drivers/gpu/drm/drm_fb_helper.c | 697 ------------------------------- include/drm/drm_client.h | 4 +- 3 files changed, 700 insertions(+), 699 deletions(-) diff --git a/drivers/gpu/drm/drm_client.c b/drivers/gpu/drm/drm_client.c index 5b199c051960..3bc96b0b30ec 100644 --- a/drivers/gpu/drm/drm_client.c +++ b/drivers/gpu/drm/drm_client.c @@ -11,9 +11,11 @@ #include #include +#include #include #include #include +#include #include #include #include @@ -24,6 +26,12 @@ #include "drm_crtc_internal.h" #include "drm_internal.h" +#define DRM_CLIENT_MAX_CLONED_CONNECTORS 8 + +struct drm_client_offset { + int x, y; +}; + /** * DOC: overview * @@ -486,6 +494,696 @@ struct drm_mode_set *drm_client_find_modeset(struct drm_mode_set *modesets, stru } EXPORT_SYMBOL(drm_client_find_modeset); +static struct drm_display_mode * +drm_connector_has_preferred_mode(struct drm_connector *connector, int width, int height) +{ + struct drm_display_mode *mode; + + list_for_each_entry(mode, &connector->modes, head) { + if (mode->hdisplay > width || + mode->vdisplay > height) + continue; + if (mode->type & DRM_MODE_TYPE_PREFERRED) + return mode; + } + return NULL; +} + +static struct drm_display_mode * +drm_connector_pick_cmdline_mode(struct drm_connector *connector) +{ + struct drm_cmdline_mode *cmdline_mode; + struct drm_display_mode *mode; + bool prefer_non_interlace; + + cmdline_mode = &connector->cmdline_mode; + if (cmdline_mode->specified == false) + return NULL; + + /* attempt to find a matching mode in the list of modes + * we have gotten so far, if not add a CVT mode that conforms + */ + if (cmdline_mode->rb || cmdline_mode->margins) + goto create_mode; + + prefer_non_interlace = !cmdline_mode->interlace; +again: + list_for_each_entry(mode, &connector->modes, head) { + /* check width/height */ + if (mode->hdisplay != cmdline_mode->xres || + mode->vdisplay != cmdline_mode->yres) + continue; + + if (cmdline_mode->refresh_specified) { + if (mode->vrefresh != cmdline_mode->refresh) + continue; + } + + if (cmdline_mode->interlace) { + if (!(mode->flags & DRM_MODE_FLAG_INTERLACE)) + continue; + } else if (prefer_non_interlace) { + if (mode->flags & DRM_MODE_FLAG_INTERLACE) + continue; + } + return mode; + } + + if (prefer_non_interlace) { + prefer_non_interlace = false; + goto again; + } + +create_mode: + mode = drm_mode_create_from_cmdline_mode(connector->dev, cmdline_mode); + list_add(&mode->head, &connector->modes); + return mode; +} + +static bool drm_connector_enabled(struct drm_connector *connector, bool strict) +{ + bool enable; + + if (connector->display_info.non_desktop) + return false; + + if (strict) + enable = connector->status == connector_status_connected; + else + enable = connector->status != connector_status_disconnected; + + return enable; +} + +static void drm_client_connectors_enabled(struct drm_connector **connectors, + unsigned int connector_count, + bool *enabled) +{ + bool any_enabled = false; + struct drm_connector *connector; + int i = 0; + + for (i = 0; i < connector_count; i++) { + connector = connectors[i]; + enabled[i] = drm_connector_enabled(connector, true); + DRM_DEBUG_KMS("connector %d enabled? %s\n", connector->base.id, + connector->display_info.non_desktop ? "non desktop" : enabled[i] ? "yes" : "no"); + + any_enabled |= enabled[i]; + } + + if (any_enabled) + return; + + for (i = 0; i < connector_count; i++) + enabled[i] = drm_connector_enabled(connectors[i], false); +} + +static bool drm_client_target_cloned(struct drm_device *dev, + struct drm_connector **connectors, + unsigned int connector_count, + struct drm_display_mode **modes, + struct drm_client_offset *offsets, + bool *enabled, int width, int height) +{ + int count, i, j; + bool can_clone = false; + struct drm_display_mode *dmt_mode, *mode; + + /* only contemplate cloning in the single crtc case */ + if (dev->mode_config.num_crtc > 1) + return false; + + count = 0; + for (i = 0; i < connector_count; i++) { + if (enabled[i]) + count++; + } + + /* only contemplate cloning if more than one connector is enabled */ + if (count <= 1) + return false; + + /* check the command line or if nothing common pick 1024x768 */ + can_clone = true; + for (i = 0; i < connector_count; i++) { + if (!enabled[i]) + continue; + modes[i] = drm_connector_pick_cmdline_mode(connectors[i]); + if (!modes[i]) { + can_clone = false; + break; + } + for (j = 0; j < i; j++) { + if (!enabled[j]) + continue; + if (!drm_mode_match(modes[j], modes[i], + DRM_MODE_MATCH_TIMINGS | + DRM_MODE_MATCH_CLOCK | + DRM_MODE_MATCH_FLAGS | + DRM_MODE_MATCH_3D_FLAGS)) + can_clone = false; + } + } + + if (can_clone) { + DRM_DEBUG_KMS("can clone using command line\n"); + return true; + } + + /* try and find a 1024x768 mode on each connector */ + can_clone = true; + dmt_mode = drm_mode_find_dmt(dev, 1024, 768, 60, false); + + for (i = 0; i < connector_count; i++) { + if (!enabled[i]) + continue; + + list_for_each_entry(mode, &connectors[i]->modes, head) { + if (drm_mode_match(mode, dmt_mode, + DRM_MODE_MATCH_TIMINGS | + DRM_MODE_MATCH_CLOCK | + DRM_MODE_MATCH_FLAGS | + DRM_MODE_MATCH_3D_FLAGS)) + modes[i] = mode; + } + if (!modes[i]) + can_clone = false; + } + + if (can_clone) { + DRM_DEBUG_KMS("can clone using 1024x768\n"); + return true; + } + DRM_INFO("kms: can't enable cloning when we probably wanted to.\n"); + return false; +} + +static int drm_client_get_tile_offsets(struct drm_connector **connectors, + unsigned int connector_count, + struct drm_display_mode **modes, + struct drm_client_offset *offsets, + int idx, + int h_idx, int v_idx) +{ + struct drm_connector *connector; + int i; + int hoffset = 0, voffset = 0; + + for (i = 0; i < connector_count; i++) { + connector = connectors[i]; + if (!connector->has_tile) + continue; + + if (!modes[i] && (h_idx || v_idx)) { + DRM_DEBUG_KMS("no modes for connector tiled %d %d\n", i, + connector->base.id); + continue; + } + if (connector->tile_h_loc < h_idx) + hoffset += modes[i]->hdisplay; + + if (connector->tile_v_loc < v_idx) + voffset += modes[i]->vdisplay; + } + offsets[idx].x = hoffset; + offsets[idx].y = voffset; + DRM_DEBUG_KMS("returned %d %d for %d %d\n", hoffset, voffset, h_idx, v_idx); + return 0; +} + +static bool drm_client_target_preferred(struct drm_connector **connectors, + unsigned int connector_count, + struct drm_display_mode **modes, + struct drm_client_offset *offsets, + bool *enabled, int width, int height) +{ + const u64 mask = BIT_ULL(connector_count) - 1; + struct drm_connector *connector; + u64 conn_configured = 0; + int tile_pass = 0; + int i; + +retry: + for (i = 0; i < connector_count; i++) { + connector = connectors[i]; + + if (conn_configured & BIT_ULL(i)) + continue; + + if (enabled[i] == false) { + conn_configured |= BIT_ULL(i); + continue; + } + + /* first pass over all the untiled connectors */ + if (tile_pass == 0 && connector->has_tile) + continue; + + if (tile_pass == 1) { + if (connector->tile_h_loc != 0 || + connector->tile_v_loc != 0) + continue; + + } else { + if (connector->tile_h_loc != tile_pass - 1 && + connector->tile_v_loc != tile_pass - 1) + /* if this tile_pass doesn't cover any of the tiles - keep going */ + continue; + + /* + * find the tile offsets for this pass - need to find + * all tiles left and above + */ + drm_client_get_tile_offsets(connectors, connector_count, modes, offsets, i, + connector->tile_h_loc, connector->tile_v_loc); + } + DRM_DEBUG_KMS("looking for cmdline mode on connector %d\n", + connector->base.id); + + /* got for command line mode first */ + modes[i] = drm_connector_pick_cmdline_mode(connector); + if (!modes[i]) { + DRM_DEBUG_KMS("looking for preferred mode on connector %d %d\n", + connector->base.id, connector->tile_group ? connector->tile_group->id : 0); + modes[i] = drm_connector_has_preferred_mode(connector, width, height); + } + /* No preferred modes, pick one off the list */ + if (!modes[i] && !list_empty(&connector->modes)) { + list_for_each_entry(modes[i], &connector->modes, head) + break; + } + DRM_DEBUG_KMS("found mode %s\n", modes[i] ? modes[i]->name : + "none"); + conn_configured |= BIT_ULL(i); + } + + if ((conn_configured & mask) != mask) { + tile_pass++; + goto retry; + } + return true; +} + +static bool connector_has_possible_crtc(struct drm_connector *connector, + struct drm_crtc *crtc) +{ + struct drm_encoder *encoder; + int i; + + drm_connector_for_each_possible_encoder(connector, encoder, i) { + if (encoder->possible_crtcs & drm_crtc_mask(crtc)) + return true; + } + + return false; +} + +static int drm_client_pick_crtcs(struct drm_device *dev, + struct drm_mode_set *modesets, + struct drm_connector **connectors, + unsigned int connector_count, + struct drm_crtc **best_crtcs, + struct drm_display_mode **modes, + int n, int width, int height) +{ + struct drm_connector *connector; + int my_score, best_score, score; + struct drm_crtc **crtcs, *crtc; + struct drm_mode_set *modeset; + int o; + + if (n == connector_count) + return 0; + + connector = connectors[n]; + + best_crtcs[n] = NULL; + best_score = drm_client_pick_crtcs(dev, modesets, connectors, connector_count, + best_crtcs, modes, n + 1, width, height); + if (modes[n] == NULL) + return best_score; + + crtcs = kcalloc(connector_count, sizeof(*crtcs), GFP_KERNEL); + if (!crtcs) + return best_score; + + my_score = 1; + if (connector->status == connector_status_connected) + my_score++; + if (connector->cmdline_mode.specified) + my_score++; + if (drm_connector_has_preferred_mode(connector, width, height)) + my_score++; + + /* + * select a crtc for this connector and then attempt to configure + * remaining connectors + */ + drm_client_for_each_modeset(modeset, modesets) { + crtc = modeset->crtc; + + if (!connector_has_possible_crtc(connector, crtc)) + continue; + + for (o = 0; o < n; o++) + if (best_crtcs[o] == crtc) + break; + + if (o < n) { + /* ignore cloning unless only a single crtc */ + if (dev->mode_config.num_crtc > 1) + continue; + + if (!drm_mode_equal(modes[o], modes[n])) + continue; + } + + crtcs[n] = crtc; + memcpy(crtcs, best_crtcs, n * sizeof(*crtcs)); + score = my_score + drm_client_pick_crtcs(dev, modesets, connectors, connector_count, + crtcs, modes, n + 1, width, height); + if (score > best_score) { + best_score = score; + memcpy(best_crtcs, crtcs, connector_count * sizeof(*crtcs)); + } + } + + kfree(crtcs); + return best_score; +} + +/* Try to read the BIOS display configuration and use it for the initial config */ +static bool drm_client_firmware_config(struct drm_device *dev, + struct drm_connector **connectors, + unsigned int connector_count, + struct drm_crtc **crtcs, + struct drm_display_mode **modes, + struct drm_client_offset *offsets, + bool *enabled, int width, int height) +{ + unsigned int count = min_t(unsigned int, connector_count, BITS_PER_LONG); + unsigned long conn_configured, conn_seq; + int i, j; + bool *save_enabled; + bool fallback = true, ret = true; + int num_connectors_enabled = 0; + int num_connectors_detected = 0; + struct drm_modeset_acquire_ctx ctx; + + save_enabled = kcalloc(count, sizeof(bool), GFP_KERNEL); + if (!save_enabled) + return false; + + drm_modeset_acquire_init(&ctx, 0); + + while (drm_modeset_lock_all_ctx(dev, &ctx) != 0) + drm_modeset_backoff(&ctx); + + memcpy(save_enabled, enabled, count); + conn_seq = GENMASK(count - 1, 0); + conn_configured = 0; +retry: + for (i = 0; i < count; i++) { + struct drm_connector *connector; + struct drm_encoder *encoder; + struct drm_crtc *new_crtc; + + connector = connectors[i]; + + if (conn_configured & BIT(i)) + continue; + + /* First pass, only consider tiled connectors */ + if (conn_seq == GENMASK(count - 1, 0) && !connector->has_tile) + continue; + + if (connector->status == connector_status_connected) + num_connectors_detected++; + + if (!enabled[i]) { + DRM_DEBUG_KMS("connector %s not enabled, skipping\n", + connector->name); + conn_configured |= BIT(i); + continue; + } + + if (connector->force == DRM_FORCE_OFF) { + DRM_DEBUG_KMS("connector %s is disabled by user, skipping\n", + connector->name); + enabled[i] = false; + continue; + } + + encoder = connector->state->best_encoder; + if (!encoder || WARN_ON(!connector->state->crtc)) { + if (connector->force > DRM_FORCE_OFF) + goto bail; + + DRM_DEBUG_KMS("connector %s has no encoder or crtc, skipping\n", + connector->name); + enabled[i] = false; + conn_configured |= BIT(i); + continue; + } + + num_connectors_enabled++; + + new_crtc = connector->state->crtc; + + /* + * Make sure we're not trying to drive multiple connectors + * with a single CRTC, since our cloning support may not + * match the BIOS. + */ + for (j = 0; j < count; j++) { + if (crtcs[j] == new_crtc) { + DRM_DEBUG_KMS("fallback: cloned configuration\n"); + goto bail; + } + } + + DRM_DEBUG_KMS("looking for cmdline mode on connector %s\n", + connector->name); + + /* go for command line mode first */ + modes[i] = drm_connector_pick_cmdline_mode(connector); + + /* try for preferred next */ + if (!modes[i]) { + DRM_DEBUG_KMS("looking for preferred mode on connector %s %d\n", + connector->name, connector->has_tile); + modes[i] = drm_connector_has_preferred_mode(connector, width, height); + } + + /* No preferred mode marked by the EDID? Are there any modes? */ + if (!modes[i] && !list_empty(&connector->modes)) { + DRM_DEBUG_KMS("using first mode listed on connector %s\n", + connector->name); + modes[i] = list_first_entry(&connector->modes, + struct drm_display_mode, + head); + } + + /* last resort: use current mode */ + if (!modes[i]) { + /* + * IMPORTANT: We want to use the adjusted mode (i.e. + * after the panel fitter upscaling) as the initial + * config, not the input mode, which is what crtc->mode + * usually contains. But since our current + * code puts a mode derived from the post-pfit timings + * into crtc->mode this works out correctly. + * + * This is crtc->mode and not crtc->state->mode for the + * fastboot check to work correctly. + */ + DRM_DEBUG_KMS("looking for current mode on connector %s\n", + connector->name); + modes[i] = &connector->state->crtc->mode; + } + crtcs[i] = new_crtc; + + DRM_DEBUG_KMS("connector %s on [CRTC:%d:%s]: %dx%d%s\n", + connector->name, + connector->state->crtc->base.id, + connector->state->crtc->name, + modes[i]->hdisplay, modes[i]->vdisplay, + modes[i]->flags & DRM_MODE_FLAG_INTERLACE ? "i" : ""); + + fallback = false; + conn_configured |= BIT(i); + } + + if (conn_configured != conn_seq) { /* repeat until no more are found */ + conn_seq = conn_configured; + goto retry; + } + + /* + * If the BIOS didn't enable everything it could, fall back to have the + * same user experiencing of lighting up as much as possible like the + * fbdev helper library. + */ + if (num_connectors_enabled != num_connectors_detected && + num_connectors_enabled < dev->mode_config.num_crtc) { + DRM_DEBUG_KMS("fallback: Not all outputs enabled\n"); + DRM_DEBUG_KMS("Enabled: %i, detected: %i\n", num_connectors_enabled, + num_connectors_detected); + fallback = true; + } + + if (fallback) { +bail: + DRM_DEBUG_KMS("Not using firmware configuration\n"); + memcpy(enabled, save_enabled, count); + ret = false; + } + + drm_modeset_drop_locks(&ctx); + drm_modeset_acquire_fini(&ctx); + + kfree(save_enabled); + return ret; +} + +/** + * drm_client_modesets_probe() - Probe for displays + * @dev: DRM device + * @width: Maximum display mode width (optional) + * @height: Maximum display mode height (optional) + * + * This function tries to set up pipelines for enabled connectors and returns + * the CRTC config as a &drm_mode_set array. + * + * Use drm_client_modesets_release() to free the array and its resources. + * + * Returns: + * A &drm_mode_set array on success, NULL if no connectors are found + * or error pointer on failure. + */ +struct drm_mode_set * +drm_client_modesets_probe(struct drm_device *dev, unsigned int width, unsigned int height) +{ + struct drm_connector *connector, **connectors = NULL; + struct drm_connector_list_iter conn_iter; + struct drm_mode_set *modesets = NULL; + unsigned int total_modes_count = 0; + struct drm_client_offset *offsets; + unsigned int connector_count = 0; + struct drm_display_mode **modes; + struct drm_crtc **crtcs; + int i, ret = 0; + bool *enabled; + + DRM_DEBUG_KMS("\n"); + + if (!width) + width = dev->mode_config.max_width; + if (!height) + height = dev->mode_config.max_height; + + drm_connector_list_iter_begin(dev, &conn_iter); + drm_client_for_each_connector_iter(connector, &conn_iter) { + struct drm_connector **tmp; + + tmp = krealloc(connectors, (connector_count + 1) * sizeof(*connectors), GFP_KERNEL); + if (!tmp) { + ret = -ENOMEM; + goto free_connectors; + } + + connectors = tmp; + drm_connector_get(connector); + connectors[connector_count++] = connector; + } + drm_connector_list_iter_end(&conn_iter); + + if (!connector_count) + return NULL; + + modesets = drm_client_modesets_create(dev); + crtcs = kcalloc(connector_count, sizeof(*crtcs), GFP_KERNEL); + modes = kcalloc(connector_count, sizeof(*modes), GFP_KERNEL); + offsets = kcalloc(connector_count, sizeof(*offsets), GFP_KERNEL); + enabled = kcalloc(connector_count, sizeof(bool), GFP_KERNEL); + if (IS_ERR(modesets) || !crtcs || !modes || !enabled || !offsets) { + DRM_ERROR("Memory allocation failed\n"); + ret = -ENOMEM; + goto out; + } + + mutex_lock(&dev->mode_config.mutex); + for (i = 0; i < connector_count; i++) + total_modes_count += connectors[i]->funcs->fill_modes(connectors[i], width, height); + if (!total_modes_count) + DRM_DEBUG_KMS("No connectors reported connected with modes\n"); + drm_client_connectors_enabled(connectors, connector_count, enabled); + + if (!drm_client_firmware_config(dev, connectors, connector_count, crtcs, + modes, offsets, enabled, width, height)) { + memset(modes, 0, connector_count * sizeof(*modes)); + memset(crtcs, 0, connector_count * sizeof(*crtcs)); + memset(offsets, 0, connector_count * sizeof(*offsets)); + + if (!drm_client_target_cloned(dev, connectors, connector_count, modes, + offsets, enabled, width, height) && + !drm_client_target_preferred(connectors, connector_count, modes, + offsets, enabled, width, height)) + DRM_ERROR("Unable to find initial modes\n"); + + DRM_DEBUG_KMS("picking CRTCs for %dx%d config\n", + width, height); + + drm_client_pick_crtcs(dev, modesets, connectors, connector_count, + crtcs, modes, 0, width, height); + } + mutex_unlock(&dev->mode_config.mutex); + + for (i = 0; i < connector_count; i++) { + struct drm_display_mode *mode = modes[i]; + struct drm_crtc *crtc = crtcs[i]; + struct drm_client_offset *offset = &offsets[i]; + + if (mode && crtc) { + struct drm_mode_set *modeset = drm_client_find_modeset(modesets, crtc); + struct drm_connector *connector = connectors[i]; + + DRM_DEBUG_KMS("desired mode %s set on crtc %d (%d,%d)\n", + mode->name, crtc->base.id, offset->x, offset->y); + + if (WARN_ON_ONCE(modeset->num_connectors == DRM_CLIENT_MAX_CLONED_CONNECTORS || + (dev->mode_config.num_crtc > 1 && modeset->num_connectors == 1))) + break; + + modeset->mode = drm_mode_duplicate(dev, mode); + drm_connector_get(connector); + modeset->connectors[modeset->num_connectors++] = connector; + modeset->x = offset->x; + modeset->y = offset->y; + } + } +out: + kfree(crtcs); + kfree(modes); + kfree(offsets); + kfree(enabled); +free_connectors: + if (connectors) { + for (i = 0; i < connector_count; i++) + drm_connector_put(connectors[i]); + kfree(connectors); + } + + if (ret) { + drm_client_modesets_release(modesets); + return ERR_PTR(ret); + } + + return modesets; +} +EXPORT_SYMBOL(drm_client_modesets_probe); + /** * drm_client_panel_rotation() - Check panel orientation * @modeset: DRM modeset diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index afe4d4220e4d..4a073cd4e423 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -40,14 +40,6 @@ #include #include #include -#include - -#include "drm_crtc_internal.h" -#include "drm_crtc_helper_internal.h" - -struct drm_client_offset { - int x, y; -}; static bool drm_fbdev_emulation = true; module_param_named(fbdev_emulation, drm_fbdev_emulation, bool, 0600); @@ -1687,695 +1679,6 @@ void drm_fb_helper_fill_var(struct fb_info *info, struct drm_fb_helper *fb_helpe } EXPORT_SYMBOL(drm_fb_helper_fill_var); -static struct drm_display_mode * -drm_connector_has_preferred_mode(struct drm_connector *connector, int width, int height) -{ - struct drm_display_mode *mode; - - list_for_each_entry(mode, &connector->modes, head) { - if (mode->hdisplay > width || - mode->vdisplay > height) - continue; - if (mode->type & DRM_MODE_TYPE_PREFERRED) - return mode; - } - return NULL; -} - -static struct drm_display_mode * -drm_connector_pick_cmdline_mode(struct drm_connector *connector) -{ - struct drm_cmdline_mode *cmdline_mode; - struct drm_display_mode *mode; - bool prefer_non_interlace; - - cmdline_mode = &connector->cmdline_mode; - if (cmdline_mode->specified == false) - return NULL; - - /* attempt to find a matching mode in the list of modes - * we have gotten so far, if not add a CVT mode that conforms - */ - if (cmdline_mode->rb || cmdline_mode->margins) - goto create_mode; - - prefer_non_interlace = !cmdline_mode->interlace; -again: - list_for_each_entry(mode, &connector->modes, head) { - /* check width/height */ - if (mode->hdisplay != cmdline_mode->xres || - mode->vdisplay != cmdline_mode->yres) - continue; - - if (cmdline_mode->refresh_specified) { - if (mode->vrefresh != cmdline_mode->refresh) - continue; - } - - if (cmdline_mode->interlace) { - if (!(mode->flags & DRM_MODE_FLAG_INTERLACE)) - continue; - } else if (prefer_non_interlace) { - if (mode->flags & DRM_MODE_FLAG_INTERLACE) - continue; - } - return mode; - } - - if (prefer_non_interlace) { - prefer_non_interlace = false; - goto again; - } - -create_mode: - mode = drm_mode_create_from_cmdline_mode(connector->dev, cmdline_mode); - list_add(&mode->head, &connector->modes); - return mode; -} - -static bool drm_connector_enabled(struct drm_connector *connector, bool strict) -{ - bool enable; - - if (connector->display_info.non_desktop) - return false; - - if (strict) - enable = connector->status == connector_status_connected; - else - enable = connector->status != connector_status_disconnected; - - return enable; -} - -static void drm_client_connectors_enabled(struct drm_connector **connectors, - unsigned int connector_count, - bool *enabled) -{ - bool any_enabled = false; - struct drm_connector *connector; - int i = 0; - - for (i = 0; i < connector_count; i++) { - connector = connectors[i]; - enabled[i] = drm_connector_enabled(connector, true); - DRM_DEBUG_KMS("connector %d enabled? %s\n", connector->base.id, - connector->display_info.non_desktop ? "non desktop" : enabled[i] ? "yes" : "no"); - - any_enabled |= enabled[i]; - } - - if (any_enabled) - return; - - for (i = 0; i < connector_count; i++) - enabled[i] = drm_connector_enabled(connectors[i], false); -} - -static bool drm_client_target_cloned(struct drm_device *dev, - struct drm_connector **connectors, - unsigned int connector_count, - struct drm_display_mode **modes, - struct drm_client_offset *offsets, - bool *enabled, int width, int height) -{ - int count, i, j; - bool can_clone = false; - struct drm_display_mode *dmt_mode, *mode; - - /* only contemplate cloning in the single crtc case */ - if (dev->mode_config.num_crtc > 1) - return false; - - count = 0; - for (i = 0; i < connector_count; i++) { - if (enabled[i]) - count++; - } - - /* only contemplate cloning if more than one connector is enabled */ - if (count <= 1) - return false; - - /* check the command line or if nothing common pick 1024x768 */ - can_clone = true; - for (i = 0; i < connector_count; i++) { - if (!enabled[i]) - continue; - modes[i] = drm_connector_pick_cmdline_mode(connectors[i]); - if (!modes[i]) { - can_clone = false; - break; - } - for (j = 0; j < i; j++) { - if (!enabled[j]) - continue; - if (!drm_mode_match(modes[j], modes[i], - DRM_MODE_MATCH_TIMINGS | - DRM_MODE_MATCH_CLOCK | - DRM_MODE_MATCH_FLAGS | - DRM_MODE_MATCH_3D_FLAGS)) - can_clone = false; - } - } - - if (can_clone) { - DRM_DEBUG_KMS("can clone using command line\n"); - return true; - } - - /* try and find a 1024x768 mode on each connector */ - can_clone = true; - dmt_mode = drm_mode_find_dmt(dev, 1024, 768, 60, false); - - for (i = 0; i < connector_count; i++) { - if (!enabled[i]) - continue; - - list_for_each_entry(mode, &connectors[i]->modes, head) { - if (drm_mode_match(mode, dmt_mode, - DRM_MODE_MATCH_TIMINGS | - DRM_MODE_MATCH_CLOCK | - DRM_MODE_MATCH_FLAGS | - DRM_MODE_MATCH_3D_FLAGS)) - modes[i] = mode; - } - if (!modes[i]) - can_clone = false; - } - - if (can_clone) { - DRM_DEBUG_KMS("can clone using 1024x768\n"); - return true; - } - DRM_INFO("kms: can't enable cloning when we probably wanted to.\n"); - return false; -} - -static int drm_client_get_tile_offsets(struct drm_connector **connectors, - unsigned int connector_count, - struct drm_display_mode **modes, - struct drm_client_offset *offsets, - int idx, - int h_idx, int v_idx) -{ - struct drm_connector *connector; - int i; - int hoffset = 0, voffset = 0; - - for (i = 0; i < connector_count; i++) { - connector = connectors[i]; - if (!connector->has_tile) - continue; - - if (!modes[i] && (h_idx || v_idx)) { - DRM_DEBUG_KMS("no modes for connector tiled %d %d\n", i, - connector->base.id); - continue; - } - if (connector->tile_h_loc < h_idx) - hoffset += modes[i]->hdisplay; - - if (connector->tile_v_loc < v_idx) - voffset += modes[i]->vdisplay; - } - offsets[idx].x = hoffset; - offsets[idx].y = voffset; - DRM_DEBUG_KMS("returned %d %d for %d %d\n", hoffset, voffset, h_idx, v_idx); - return 0; -} - -static bool drm_client_target_preferred(struct drm_connector **connectors, - unsigned int connector_count, - struct drm_display_mode **modes, - struct drm_client_offset *offsets, - bool *enabled, int width, int height) -{ - const u64 mask = BIT_ULL(connector_count) - 1; - struct drm_connector *connector; - u64 conn_configured = 0; - int tile_pass = 0; - int i; - -retry: - for (i = 0; i < connector_count; i++) { - connector = connectors[i]; - - if (conn_configured & BIT_ULL(i)) - continue; - - if (enabled[i] == false) { - conn_configured |= BIT_ULL(i); - continue; - } - - /* first pass over all the untiled connectors */ - if (tile_pass == 0 && connector->has_tile) - continue; - - if (tile_pass == 1) { - if (connector->tile_h_loc != 0 || - connector->tile_v_loc != 0) - continue; - - } else { - if (connector->tile_h_loc != tile_pass - 1 && - connector->tile_v_loc != tile_pass - 1) - /* if this tile_pass doesn't cover any of the tiles - keep going */ - continue; - - /* - * find the tile offsets for this pass - need to find - * all tiles left and above - */ - drm_client_get_tile_offsets(connectors, connector_count, modes, offsets, i, - connector->tile_h_loc, connector->tile_v_loc); - } - DRM_DEBUG_KMS("looking for cmdline mode on connector %d\n", - connector->base.id); - - /* got for command line mode first */ - modes[i] = drm_connector_pick_cmdline_mode(connector); - if (!modes[i]) { - DRM_DEBUG_KMS("looking for preferred mode on connector %d %d\n", - connector->base.id, connector->tile_group ? connector->tile_group->id : 0); - modes[i] = drm_connector_has_preferred_mode(connector, width, height); - } - /* No preferred modes, pick one off the list */ - if (!modes[i] && !list_empty(&connector->modes)) { - list_for_each_entry(modes[i], &connector->modes, head) - break; - } - DRM_DEBUG_KMS("found mode %s\n", modes[i] ? modes[i]->name : - "none"); - conn_configured |= BIT_ULL(i); - } - - if ((conn_configured & mask) != mask) { - tile_pass++; - goto retry; - } - return true; -} - -static bool connector_has_possible_crtc(struct drm_connector *connector, - struct drm_crtc *crtc) -{ - struct drm_encoder *encoder; - int i; - - drm_connector_for_each_possible_encoder(connector, encoder, i) { - if (encoder->possible_crtcs & drm_crtc_mask(crtc)) - return true; - } - - return false; -} - -static int drm_client_pick_crtcs(struct drm_device *dev, - struct drm_mode_set *modesets, - struct drm_connector **connectors, - unsigned int connector_count, - struct drm_crtc **best_crtcs, - struct drm_display_mode **modes, - int n, int width, int height) -{ - struct drm_connector *connector; - int my_score, best_score, score; - struct drm_crtc **crtcs, *crtc; - struct drm_mode_set *modeset; - int o; - - if (n == connector_count) - return 0; - - connector = connectors[n]; - - best_crtcs[n] = NULL; - best_score = drm_client_pick_crtcs(dev, modesets, connectors, connector_count, - best_crtcs, modes, n + 1, width, height); - if (modes[n] == NULL) - return best_score; - - crtcs = kcalloc(connector_count, sizeof(*crtcs), GFP_KERNEL); - if (!crtcs) - return best_score; - - my_score = 1; - if (connector->status == connector_status_connected) - my_score++; - if (connector->cmdline_mode.specified) - my_score++; - if (drm_connector_has_preferred_mode(connector, width, height)) - my_score++; - - /* - * select a crtc for this connector and then attempt to configure - * remaining connectors - */ - drm_client_for_each_modeset(modeset, modesets) { - crtc = modeset->crtc; - - if (!connector_has_possible_crtc(connector, crtc)) - continue; - - for (o = 0; o < n; o++) - if (best_crtcs[o] == crtc) - break; - - if (o < n) { - /* ignore cloning unless only a single crtc */ - if (dev->mode_config.num_crtc > 1) - continue; - - if (!drm_mode_equal(modes[o], modes[n])) - continue; - } - - crtcs[n] = crtc; - memcpy(crtcs, best_crtcs, n * sizeof(*crtcs)); - score = my_score + drm_client_pick_crtcs(dev, modesets, connectors, connector_count, - crtcs, modes, n + 1, width, height); - if (score > best_score) { - best_score = score; - memcpy(best_crtcs, crtcs, connector_count * sizeof(*crtcs)); - } - } - - kfree(crtcs); - return best_score; -} - -/* Try to read the BIOS display configuration and use it for the initial config */ -static bool drm_client_firmware_config(struct drm_device *dev, - struct drm_connector **connectors, - unsigned int connector_count, - struct drm_crtc **crtcs, - struct drm_display_mode **modes, - struct drm_client_offset *offsets, - bool *enabled, int width, int height) -{ - unsigned int count = min_t(unsigned int, connector_count, BITS_PER_LONG); - unsigned long conn_configured, conn_seq; - int i, j; - bool *save_enabled; - bool fallback = true, ret = true; - int num_connectors_enabled = 0; - int num_connectors_detected = 0; - struct drm_modeset_acquire_ctx ctx; - - save_enabled = kcalloc(count, sizeof(bool), GFP_KERNEL); - if (!save_enabled) - return false; - - drm_modeset_acquire_init(&ctx, 0); - - while (drm_modeset_lock_all_ctx(dev, &ctx) != 0) - drm_modeset_backoff(&ctx); - - memcpy(save_enabled, enabled, count); - conn_seq = GENMASK(count - 1, 0); - conn_configured = 0; -retry: - for (i = 0; i < count; i++) { - struct drm_connector *connector; - struct drm_encoder *encoder; - struct drm_crtc *new_crtc; - - connector = connectors[i]; - - if (conn_configured & BIT(i)) - continue; - - /* First pass, only consider tiled connectors */ - if (conn_seq == GENMASK(count - 1, 0) && !connector->has_tile) - continue; - - if (connector->status == connector_status_connected) - num_connectors_detected++; - - if (!enabled[i]) { - DRM_DEBUG_KMS("connector %s not enabled, skipping\n", - connector->name); - conn_configured |= BIT(i); - continue; - } - - if (connector->force == DRM_FORCE_OFF) { - DRM_DEBUG_KMS("connector %s is disabled by user, skipping\n", - connector->name); - enabled[i] = false; - continue; - } - - encoder = connector->state->best_encoder; - if (!encoder || WARN_ON(!connector->state->crtc)) { - if (connector->force > DRM_FORCE_OFF) - goto bail; - - DRM_DEBUG_KMS("connector %s has no encoder or crtc, skipping\n", - connector->name); - enabled[i] = false; - conn_configured |= BIT(i); - continue; - } - - num_connectors_enabled++; - - new_crtc = connector->state->crtc; - - /* - * Make sure we're not trying to drive multiple connectors - * with a single CRTC, since our cloning support may not - * match the BIOS. - */ - for (j = 0; j < count; j++) { - if (crtcs[j] == new_crtc) { - DRM_DEBUG_KMS("fallback: cloned configuration\n"); - goto bail; - } - } - - DRM_DEBUG_KMS("looking for cmdline mode on connector %s\n", - connector->name); - - /* go for command line mode first */ - modes[i] = drm_connector_pick_cmdline_mode(connector); - - /* try for preferred next */ - if (!modes[i]) { - DRM_DEBUG_KMS("looking for preferred mode on connector %s %d\n", - connector->name, connector->has_tile); - modes[i] = drm_connector_has_preferred_mode(connector, width, height); - } - - /* No preferred mode marked by the EDID? Are there any modes? */ - if (!modes[i] && !list_empty(&connector->modes)) { - DRM_DEBUG_KMS("using first mode listed on connector %s\n", - connector->name); - modes[i] = list_first_entry(&connector->modes, - struct drm_display_mode, - head); - } - - /* last resort: use current mode */ - if (!modes[i]) { - /* - * IMPORTANT: We want to use the adjusted mode (i.e. - * after the panel fitter upscaling) as the initial - * config, not the input mode, which is what crtc->mode - * usually contains. But since our current - * code puts a mode derived from the post-pfit timings - * into crtc->mode this works out correctly. - * - * This is crtc->mode and not crtc->state->mode for the - * fastboot check to work correctly. - */ - DRM_DEBUG_KMS("looking for current mode on connector %s\n", - connector->name); - modes[i] = &connector->state->crtc->mode; - } - crtcs[i] = new_crtc; - - DRM_DEBUG_KMS("connector %s on [CRTC:%d:%s]: %dx%d%s\n", - connector->name, - connector->state->crtc->base.id, - connector->state->crtc->name, - modes[i]->hdisplay, modes[i]->vdisplay, - modes[i]->flags & DRM_MODE_FLAG_INTERLACE ? "i" : ""); - - fallback = false; - conn_configured |= BIT(i); - } - - if (conn_configured != conn_seq) { /* repeat until no more are found */ - conn_seq = conn_configured; - goto retry; - } - - /* - * If the BIOS didn't enable everything it could, fall back to have the - * same user experiencing of lighting up as much as possible like the - * fbdev helper library. - */ - if (num_connectors_enabled != num_connectors_detected && - num_connectors_enabled < dev->mode_config.num_crtc) { - DRM_DEBUG_KMS("fallback: Not all outputs enabled\n"); - DRM_DEBUG_KMS("Enabled: %i, detected: %i\n", num_connectors_enabled, - num_connectors_detected); - fallback = true; - } - - if (fallback) { -bail: - DRM_DEBUG_KMS("Not using firmware configuration\n"); - memcpy(enabled, save_enabled, count); - ret = false; - } - - drm_modeset_drop_locks(&ctx); - drm_modeset_acquire_fini(&ctx); - - kfree(save_enabled); - return ret; -} - -/** - * drm_client_modesets_probe() - Probe for displays - * @dev: DRM device - * @width: Maximum display mode width (optional) - * @height: Maximum display mode height (optional) - * - * This function tries to set up pipelines for enabled connectors and returns - * the CRTC config as a &drm_mode_set array. - * - * Use drm_client_modesets_release() to free the array and its resources. - * - * Returns: - * A &drm_mode_set array on success, NULL if no connectors are found - * or error pointer on failure. - */ -struct drm_mode_set * -drm_client_modesets_probe(struct drm_device *dev, unsigned int width, unsigned int height) -{ - struct drm_connector *connector, **connectors = NULL; - struct drm_connector_list_iter conn_iter; - struct drm_mode_set *modesets = NULL; - unsigned int total_modes_count = 0; - struct drm_client_offset *offsets; - unsigned int connector_count = 0; - struct drm_display_mode **modes; - struct drm_crtc **crtcs; - int i, ret = 0; - bool *enabled; - - DRM_DEBUG_KMS("\n"); - - if (!width) - width = dev->mode_config.max_width; - if (!height) - height = dev->mode_config.max_height; - - drm_connector_list_iter_begin(dev, &conn_iter); - drm_client_for_each_connector_iter(connector, &conn_iter) { - struct drm_connector **tmp; - - tmp = krealloc(connectors, (connector_count + 1) * sizeof(*connectors), GFP_KERNEL); - if (!tmp) { - ret = -ENOMEM; - goto free_connectors; - } - - connectors = tmp; - drm_connector_get(connector); - connectors[connector_count++] = connector; - } - drm_connector_list_iter_end(&conn_iter); - - if (!connector_count) - return NULL; - - modesets = drm_client_modesets_create(dev); - crtcs = kcalloc(connector_count, sizeof(*crtcs), GFP_KERNEL); - modes = kcalloc(connector_count, sizeof(*modes), GFP_KERNEL); - offsets = kcalloc(connector_count, sizeof(*offsets), GFP_KERNEL); - enabled = kcalloc(connector_count, sizeof(bool), GFP_KERNEL); - if (IS_ERR(modesets) || !crtcs || !modes || !enabled || !offsets) { - DRM_ERROR("Memory allocation failed\n"); - ret = -ENOMEM; - goto out; - } - - mutex_lock(&dev->mode_config.mutex); - for (i = 0; i < connector_count; i++) - total_modes_count += connectors[i]->funcs->fill_modes(connectors[i], width, height); - if (!total_modes_count) - DRM_DEBUG_KMS("No connectors reported connected with modes\n"); - drm_client_connectors_enabled(connectors, connector_count, enabled); - - if (!drm_client_firmware_config(dev, connectors, connector_count, crtcs, - modes, offsets, enabled, width, height)) { - memset(modes, 0, connector_count * sizeof(*modes)); - memset(crtcs, 0, connector_count * sizeof(*crtcs)); - memset(offsets, 0, connector_count * sizeof(*offsets)); - - if (!drm_client_target_cloned(dev, connectors, connector_count, modes, - offsets, enabled, width, height) && - !drm_client_target_preferred(connectors, connector_count, modes, - offsets, enabled, width, height)) - DRM_ERROR("Unable to find initial modes\n"); - - DRM_DEBUG_KMS("picking CRTCs for %dx%d config\n", - width, height); - - drm_client_pick_crtcs(dev, modesets, connectors, connector_count, - crtcs, modes, 0, width, height); - } - mutex_unlock(&dev->mode_config.mutex); - - for (i = 0; i < connector_count; i++) { - struct drm_display_mode *mode = modes[i]; - struct drm_crtc *crtc = crtcs[i]; - struct drm_client_offset *offset = &offsets[i]; - - if (mode && crtc) { - struct drm_mode_set *modeset = drm_client_find_modeset(modesets, crtc); - struct drm_connector *connector = connectors[i]; - - DRM_DEBUG_KMS("desired mode %s set on crtc %d (%d,%d)\n", - mode->name, crtc->base.id, offset->x, offset->y); - - if (WARN_ON_ONCE(modeset->num_connectors == DRM_CLIENT_MAX_CLONED_CONNECTORS || - (dev->mode_config.num_crtc > 1 && modeset->num_connectors == 1))) - break; - - modeset->mode = drm_mode_duplicate(dev, mode); - drm_connector_get(connector); - modeset->connectors[modeset->num_connectors++] = connector; - modeset->x = offset->x; - modeset->y = offset->y; - } - } -out: - kfree(crtcs); - kfree(modes); - kfree(offsets); - kfree(enabled); -free_connectors: - if (connectors) { - for (i = 0; i < connector_count; i++) - drm_connector_put(connectors[i]); - kfree(connectors); - } - - if (ret) { - drm_client_modesets_release(modesets); - return ERR_PTR(ret); - } - - return modesets; -} - static void drm_setup_crtcs(struct drm_fb_helper *fb_helper, u32 width, u32 height) { struct drm_mode_set *modesets; diff --git a/include/drm/drm_client.h b/include/drm/drm_client.h index a55f5ecae64a..78fb82bd8371 100644 --- a/include/drm/drm_client.h +++ b/include/drm/drm_client.h @@ -16,8 +16,6 @@ struct drm_gem_object; struct drm_minor; struct module; -#define DRM_CLIENT_MAX_CLONED_CONNECTORS 8 - /** * struct drm_client_funcs - DRM client callbacks */ @@ -143,6 +141,8 @@ void drm_client_framebuffer_delete(struct drm_client_buffer *buffer); struct drm_mode_set *drm_client_modesets_create(struct drm_device *dev); void drm_client_modesets_release(struct drm_mode_set *modesets); struct drm_mode_set *drm_client_find_modeset(struct drm_mode_set *modesets, struct drm_crtc *crtc); +struct drm_mode_set * +drm_client_modesets_probe(struct drm_device *dev, unsigned int width, unsigned int height); bool drm_client_panel_rotation(struct drm_mode_set *modeset, unsigned int *rotation); int drm_client_modesets_commit(struct drm_device *dev, struct drm_mode_set *modesets); void drm_client_modesets_dpms(struct drm_device *dev, struct drm_mode_set *modesets, int mode); From patchwork Tue Mar 26 17:55:43 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Noralf_Tr=C3=B8nnes?= X-Patchwork-Id: 10871845 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 178EA922 for ; Tue, 26 Mar 2019 18:02:37 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 069DD1FF3E for ; Tue, 26 Mar 2019 18:02:37 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id EEE572862A; Tue, 26 Mar 2019 18:02:36 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED autolearn=unavailable version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 7EEF21FF3E for ; Tue, 26 Mar 2019 18:02:36 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 293C46E055; Tue, 26 Mar 2019 18:02:33 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from smtp.domeneshop.no (smtp.domeneshop.no [IPv6:2a01:5b40:0:3005::1]) by gabe.freedesktop.org (Postfix) with ESMTPS id 5DA866E051; Tue, 26 Mar 2019 18:02:31 +0000 (UTC) Received: from 211.81-166-168.customer.lyse.net ([81.166.168.211]:46322 helo=localhost.localdomain) by smtp.domeneshop.no with esmtpsa (TLS1.2:ECDHE_RSA_AES_128_CBC_SHA1:128) (Exim 4.84_2) (envelope-from ) id 1h8qIx-0006Mj-Pw; Tue, 26 Mar 2019 18:56:07 +0100 From: =?utf-8?q?Noralf_Tr=C3=B8nnes?= To: dri-devel@lists.freedesktop.org Subject: [PATCH 13/16] drm/fb-helper: Avoid race with DRM userspace Date: Tue, 26 Mar 2019 18:55:43 +0100 Message-Id: <20190326175546.18126-14-noralf@tronnes.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190326175546.18126-1-noralf@tronnes.org> References: <20190326175546.18126-1-noralf@tronnes.org> MIME-Version: 1.0 X-Mailman-Original-DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=tronnes.org; s=ds201810; h=Content-Transfer-Encoding:Content-Type:MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From; bh=4YPTzmfwcWyDRxsAnGQVSnKvbnxobHUqs6DITHOQpZg=; b=AiGrH5Vxzpfg9giHSGaRwXoRwWhArFGXQ2+Jc5ctAgj8MXbK/fUN6kpK41aTfwGGdUx45w25azoTGLR5+WBxh0EdWO+dPIQl5k2hiPSaiXQIQa4U/UukO8X3cGf19LTxQ/vJ/WuPm9+H2nxSdtj7IHXB1/W/KD5GzY0fJTsMqpdVEDvU1oxgHx1PCl2HseYX7/hwNiZfHyC7jkHNkDqU3JvxqGjK7buxe+FCCuzafCUi9HpVgOuBNGnn6SF2xhayj/R5UV9DHOv4BMAZuPX368sksWLnq2xSNVAhiDCR+gGwtbkMxPaWIZ4GZotQhEVSTWPyuVRfvtwft9jhe9FYxA==; X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Daniel Vetter , intel-gfx@lists.freedesktop.org, mstaudt@suse.de Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Virus-Scanned: ClamAV using ClamSMTP drm_fb_helper_is_bound() is used to check if DRM userspace is in control. This is done by looking at the fb on the primary plane. By the time fb-helper gets around to committing, it's possible that the facts have changed. Avoid this race by holding the drm_device->master_mutex lock while committing. When DRM userspace does its first open, it will now wait until fb-helper is done. The helper will stay away if there's a master. Locking rule: Always take the fb-helper lock first. Suggested-by: Daniel Vetter Signed-off-by: Noralf Trønnes --- drivers/gpu/drm/drm_auth.c | 20 ++++++++++++++ drivers/gpu/drm/drm_fb_helper.c | 49 ++++++++++++++++++++++++--------- drivers/gpu/drm/drm_internal.h | 2 ++ 3 files changed, 58 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/drm_auth.c b/drivers/gpu/drm/drm_auth.c index 1669c42c40ed..db199807b7dc 100644 --- a/drivers/gpu/drm/drm_auth.c +++ b/drivers/gpu/drm/drm_auth.c @@ -368,3 +368,23 @@ void drm_master_put(struct drm_master **master) *master = NULL; } EXPORT_SYMBOL(drm_master_put); + +/* Used by drm_client and drm_fb_helper */ +bool drm_master_internal_acquire(struct drm_device *dev) +{ + mutex_lock(&dev->master_mutex); + if (dev->master) { + mutex_unlock(&dev->master_mutex); + return false; + } + + return true; +} +EXPORT_SYMBOL(drm_master_internal_acquire); + +/* Used by drm_client and drm_fb_helper */ +void drm_master_internal_release(struct drm_device *dev) +{ + mutex_unlock(&dev->master_mutex); +} +EXPORT_SYMBOL(drm_master_internal_release); diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 4a073cd4e423..9f253fcf3f79 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -41,6 +41,8 @@ #include #include +#include "drm_internal.h" + static bool drm_fbdev_emulation = true; module_param_named(fbdev_emulation, drm_fbdev_emulation, bool, 0600); MODULE_PARM_DESC(fbdev_emulation, @@ -235,7 +237,12 @@ int drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper) return 0; mutex_lock(&fb_helper->lock); - ret = drm_client_modesets_commit(fb_helper->dev, fb_helper->modesets); + if (drm_master_internal_acquire(fb_helper->dev)) { + ret = drm_client_modesets_commit(fb_helper->dev, fb_helper->modesets); + drm_master_internal_release(fb_helper->dev); + } else { + ret = -EBUSY; + } do_delayed = fb_helper->delayed_hotplug; if (do_delayed) @@ -332,13 +339,16 @@ static struct sysrq_key_op sysrq_drm_fb_helper_restore_op = { }; static void drm_fb_helper_dpms(struct fb_info *info, int dpms_mode) { struct drm_fb_helper *fb_helper = info->par; + struct drm_device *dev = fb_helper->dev; /* * For each CRTC in this fb, turn the connectors on/off. */ mutex_lock(&fb_helper->lock); - if (drm_fb_helper_is_bound(fb_helper)) - drm_client_modesets_dpms(fb_helper->dev, fb_helper->modesets, dpms_mode); + if (drm_master_internal_acquire(dev)) { + drm_client_modesets_dpms(dev, fb_helper->modesets, dpms_mode); + drm_master_internal_release(dev); + } mutex_unlock(&fb_helper->lock); } @@ -1097,6 +1107,7 @@ static int setcmap_atomic(struct fb_cmap *cmap, struct fb_info *info) int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info) { struct drm_fb_helper *fb_helper = info->par; + struct drm_device *dev = fb_helper->dev; int ret; if (oops_in_progress) @@ -1104,9 +1115,9 @@ int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info) mutex_lock(&fb_helper->lock); - if (!drm_fb_helper_is_bound(fb_helper)) { + if (!drm_master_internal_acquire(dev)) { ret = -EBUSY; - goto out; + goto unlock; } if (info->fix.visual == FB_VISUAL_TRUECOLOR) @@ -1116,7 +1127,8 @@ int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info) else ret = setcmap_legacy(cmap, info); -out: + drm_master_internal_release(dev); +unlock: mutex_unlock(&fb_helper->lock); return ret; @@ -1136,11 +1148,13 @@ int drm_fb_helper_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) { struct drm_fb_helper *fb_helper = info->par; + struct drm_device *dev = fb_helper->dev; struct drm_crtc *crtc; int ret = 0; mutex_lock(&fb_helper->lock); - if (!drm_fb_helper_is_bound(fb_helper)) { + + if (!drm_master_internal_acquire(dev)) { ret = -EBUSY; goto unlock; } @@ -1177,13 +1191,15 @@ int drm_fb_helper_ioctl(struct fb_info *info, unsigned int cmd, } ret = 0; - goto unlock; + break; default: ret = -ENOTTY; } + drm_master_internal_release(dev); unlock: mutex_unlock(&fb_helper->lock); + return ret; } EXPORT_SYMBOL(drm_fb_helper_ioctl); @@ -1426,15 +1442,19 @@ int drm_fb_helper_pan_display(struct fb_var_screeninfo *var, return -EBUSY; mutex_lock(&fb_helper->lock); - if (!drm_fb_helper_is_bound(fb_helper)) { - mutex_unlock(&fb_helper->lock); - return -EBUSY; + + if (!drm_master_internal_acquire(dev)) { + ret = -EBUSY; + goto unlock; } if (drm_drv_uses_atomic_modeset(dev)) ret = pan_display_atomic(var, info); else ret = pan_display_legacy(var, info); + + drm_master_internal_release(dev); +unlock: mutex_unlock(&fb_helper->lock); return ret; @@ -1451,6 +1471,7 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper, int ret = 0; int crtc_count = 0; struct drm_connector_list_iter conn_iter; + struct drm_device *dev = fb_helper->dev; struct drm_fb_helper_surface_size sizes; struct drm_connector *connector; struct drm_mode_set *mode_set; @@ -1593,8 +1614,10 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper, DRM_INFO("Cannot find any crtc or sizes\n"); /* First time: disable all crtc's.. */ - if (!fb_helper->deferred_setup && !READ_ONCE(fb_helper->dev->master)) - drm_client_modesets_commit(fb_helper->dev, fb_helper->modesets); + if (!fb_helper->deferred_setup && drm_master_internal_acquire(dev)) { + drm_client_modesets_commit(dev, fb_helper->modesets); + drm_master_internal_release(dev); + } return -EAGAIN; } diff --git a/drivers/gpu/drm/drm_internal.h b/drivers/gpu/drm/drm_internal.h index 251d67e04c2d..6d5d1184c084 100644 --- a/drivers/gpu/drm/drm_internal.h +++ b/drivers/gpu/drm/drm_internal.h @@ -91,6 +91,8 @@ int drm_dropmaster_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); int drm_master_open(struct drm_file *file_priv); void drm_master_release(struct drm_file *file_priv); +bool drm_master_internal_acquire(struct drm_device *dev); +void drm_master_internal_release(struct drm_device *dev); /* drm_sysfs.c */ extern struct class *drm_class; From patchwork Tue Mar 26 17:55:44 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Noralf_Tr=C3=B8nnes?= X-Patchwork-Id: 10871865 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 7350117E0 for ; Tue, 26 Mar 2019 18:04:47 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 60EE6212D9 for ; Tue, 26 Mar 2019 18:04:47 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 547E928BFE; Tue, 26 Mar 2019 18:04:47 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED autolearn=unavailable version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 88656212D9 for ; Tue, 26 Mar 2019 18:04:46 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id AB72189D66; Tue, 26 Mar 2019 18:04:45 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from smtp.domeneshop.no (smtp.domeneshop.no [IPv6:2a01:5b40:0:3005::1]) by gabe.freedesktop.org (Postfix) with ESMTPS id 1940C88CBF; Tue, 26 Mar 2019 18:04:37 +0000 (UTC) Received: from 211.81-166-168.customer.lyse.net ([81.166.168.211]:46322 helo=localhost.localdomain) by smtp.domeneshop.no with esmtpsa (TLS1.2:ECDHE_RSA_AES_128_CBC_SHA1:128) (Exim 4.84_2) (envelope-from ) id 1h8qIy-0006Mj-09; Tue, 26 Mar 2019 18:56:08 +0100 From: =?utf-8?q?Noralf_Tr=C3=B8nnes?= To: dri-devel@lists.freedesktop.org Subject: [PATCH 14/16] drm/client: Add display abstraction Date: Tue, 26 Mar 2019 18:55:44 +0100 Message-Id: <20190326175546.18126-15-noralf@tronnes.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190326175546.18126-1-noralf@tronnes.org> References: <20190326175546.18126-1-noralf@tronnes.org> MIME-Version: 1.0 X-Mailman-Original-DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=tronnes.org; s=ds201810; h=Content-Transfer-Encoding:Content-Type:MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From; bh=9i04bfSOphlWJW+XwsuWaWw9/UaM8Di2rLDwlctN6tE=; b=paVYCfEU77MHvvzZKWVAdYdlr3J9c5+f/cYpKMlDETRJe4vHlwQl0F4Hx4CyR3lVoQ7K37uSN7M5qtpAv2xu32UcI/pSbbJS70qYDu+xneXE084lCmuFPTxda2WszPBTe1Cg6Jds3um/CnRcpAQAIV2N9Nmar5+bgfJ6M/U4OniJYRA8ayl1oYJo0d1QxM6tjxwt4gV1N4VFUM71+iZAra9H2udTTzyc73EZFKylqpSGmKuBLnlfeO++ub/AcKKPPASlBA4jYFhyast92XMCL2Dgr9hgISvBlAN5BuLyKCOZW0dDBVU4CjxOCd7x7HBJuyhNxBN+NVf6j1yYtCtznQ==; X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: intel-gfx@lists.freedesktop.org, mstaudt@suse.de Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Virus-Scanned: ClamAV using ClamSMTP Add display abstraction and helpers to probe for displays and commit modesets. TODO: If the bootsplash client doesn't need to subclass drm_client_display, the callbacks can be removed. Signed-off-by: Noralf Trønnes --- drivers/gpu/drm/drm_client.c | 415 +++++++++++++++++++++++++++++++++++ include/drm/drm_client.h | 80 +++++++ 2 files changed, 495 insertions(+) diff --git a/drivers/gpu/drm/drm_client.c b/drivers/gpu/drm/drm_client.c index 3bc96b0b30ec..ef01a31a9dbe 100644 --- a/drivers/gpu/drm/drm_client.c +++ b/drivers/gpu/drm/drm_client.c @@ -4,6 +4,7 @@ */ #include +#include #include #include #include @@ -106,6 +107,9 @@ int drm_client_init(struct drm_device *dev, struct drm_client_dev *client, drm_dev_get(dev); + mutex_init(&client->displaylist_mutex); + INIT_LIST_HEAD(&client->displaylist); + return 0; err_put_module: @@ -156,6 +160,9 @@ void drm_client_release(struct drm_client_dev *client) DRM_DEV_DEBUG_KMS(dev->dev, "%s\n", client->name); + drm_client_release_displays(client); + mutex_destroy(&client->displaylist_mutex); + drm_client_close(client); drm_dev_put(dev); if (client->funcs) @@ -1419,6 +1426,414 @@ void drm_client_modesets_dpms(struct drm_device *dev, struct drm_mode_set *modes } EXPORT_SYMBOL(drm_client_modesets_dpms); +static struct drm_client_display * +drm_client_display_alloc(struct drm_client_dev *client, unsigned int num_modesets) +{ + struct drm_client_display *display; + struct drm_mode_set *modesets; + + modesets = kcalloc(num_modesets + 1, sizeof(*modesets), GFP_KERNEL); + if (!modesets) + return ERR_PTR(-ENOMEM); + + if (client->funcs && client->funcs->display_alloc) + display = client->funcs->display_alloc(client); + else + display = kzalloc(sizeof(*display), GFP_KERNEL); + if (!display) + display = ERR_PTR(-ENOMEM); + + if (IS_ERR(display)) { + kfree(modesets); + return display; + } + + display->client = client; + display->modesets = modesets; + + return display; +} + +static void drm_client_display_release(struct drm_client_display *display) +{ + unsigned int i; + + if (!display) + return; + + for (i = 0; i < display->num_buffers; i++) + drm_client_framebuffer_delete(display->buffers[i]); + kfree(display->buffers); + + drm_mode_destroy(display->client->dev, display->mode); + + drm_client_modesets_release(display->modesets); + + if (display->client->funcs && display->client->funcs->display_free) + display->client->funcs->display_free(display); + else + kfree(display); +} + +static void drm_client_display_debugprint(struct drm_client_display *display) +{ + struct drm_display_mode *mode = display->mode; + struct drm_mode_set *modeset; + unsigned int i; + + DRM_DEBUG_KMS(" %dx%d %dHz\n", mode->hdisplay, mode->vdisplay, mode->vrefresh); + + drm_client_for_each_modeset(modeset, display->modesets) { + DRM_DEBUG_KMS(" crtc=%d, connectors:", modeset->crtc->base.id); + for (i = 0; i < modeset->num_connectors; i++) + DRM_DEBUG_KMS(" %s\n", modeset->connectors[i]->name); + } +} + +static bool drm_client_modeset_equal(struct drm_mode_set *modeset1, struct drm_mode_set *modeset2) +{ + unsigned int i; + + if (modeset1->crtc != modeset2->crtc || + !drm_mode_equal(modeset1->mode, modeset2->mode) || + modeset1->x != modeset2->x || modeset1->y != modeset2->y || + modeset1->num_connectors != modeset2->num_connectors) + return false; + + for (i = 0; i < modeset1->num_connectors; i++) { + if (modeset1->connectors[i] != modeset2->connectors[i]) + return false; + } + + return true; +} + +static bool drm_client_display_equal(struct drm_client_display *display1, + struct drm_client_display *display2) +{ + struct drm_mode_set *modeset1, *modeset2; + + if (!display1 || !display2) + return false; + + if (display1 == display2) + return true; + + if (!drm_mode_equal(display1->mode, display2->mode)) + return false; + + for (modeset1 = display1->modesets, modeset2 = display2->modesets; + modeset1->crtc && modeset2->crtc; modeset1++, modeset2++) + if (!drm_client_modeset_equal(modeset1, modeset2)) + return false; + + return !modeset1->crtc && !modeset2->crtc; +} + +static int drm_client_display_framebuffer_create(struct drm_client_display *display, + unsigned int num_buffers, u32 format) +{ + struct drm_client_buffer **buffers; + struct drm_mode_set *modeset; + unsigned int i; + int ret; + + if (!display || !display->mode) + return -EINVAL; + + if (display->num_buffers && display->num_buffers != num_buffers) + return -EINVAL; + + if (display->num_buffers == num_buffers) + return 0; + + buffers = kcalloc(num_buffers, sizeof(*buffers), GFP_KERNEL); + if (!buffers) + return -ENOMEM; + + for (i = 0; i < num_buffers; i++) { + buffers[i] = drm_client_framebuffer_create(display->client, display->mode->hdisplay, + display->mode->vdisplay, format); + if (IS_ERR(buffers[i])) { + ret = PTR_ERR(buffers[i]); + goto err_free; + } + } + + display->buffers = buffers; + display->num_buffers = num_buffers; + + drm_client_for_each_modeset(modeset, display->modesets) + modeset->fb = display->buffers[0]->fb; + + return 0; + +err_free: + for (i = 0; i < num_buffers; i++) { + if (!IS_ERR_OR_NULL(buffers[i])) + drm_client_framebuffer_delete(buffers[i]); + } + kfree(buffers); + + return ret; +} + +static int drm_client_find_displays(struct drm_client_dev *client, struct list_head *displaylist) +{ + struct drm_mode_set *modeset, *modesets; + struct drm_device *dev = client->dev; + struct drm_client_display *display; + unsigned int num_modesets = 0; + int ret = 0; + + modesets = drm_client_modesets_probe(dev, 0, 0); + if (IS_ERR_OR_NULL(modesets)) + return PTR_ERR_OR_ZERO(modesets); + + /* TODO: Support more than one tiled monitor? */ + display = NULL; + drm_client_for_each_modeset(modeset, modesets) { + if (!modeset->mode || !modeset->connectors[0]->has_tile) + continue; + + if (!display) { + display = drm_client_display_alloc(client, dev->mode_config.num_crtc); + if (IS_ERR(display)) { + ret = PTR_ERR(display); + goto err_free; + } + + list_add(&display->list, displaylist); + } + + display->modesets[num_modesets++] = *modeset; + modeset->num_connectors = 0; + modeset->connectors = NULL; + modeset->mode = NULL; + } + + /* Contruct a mode for the tiled monitor */ + if (display) { + int hdisplay = 0, vdisplay = 0, vrefresh = 0; + + drm_client_for_each_modeset(modeset, display->modesets) { + if (!modeset->y) + hdisplay += modeset->mode->hdisplay; + if (!modeset->x) + vdisplay += modeset->mode->vdisplay; + vrefresh = modeset->mode->vrefresh; + } + + display->mode = drm_cvt_mode(dev, hdisplay, vdisplay, vrefresh, false, false, false); + if (!display->mode) { + ret = -ENOMEM; + goto err_free; + } + } + + /* The rest have one display per modeset */ + drm_client_for_each_modeset(modeset, modesets) { + if (!modeset->mode || modeset->connectors[0]->has_tile) + continue; + + display = drm_client_display_alloc(client, 1); + if (IS_ERR(display)) { + ret = PTR_ERR(display); + goto err_free; + } + + list_add(&display->list, displaylist); + display->modesets[0] = *modeset; + modeset->num_connectors = 0; + modeset->connectors = NULL; + modeset->mode = NULL; + + display->mode = drm_mode_duplicate(dev, display->modesets[0].mode); + if (!display->mode) { + ret = -ENOMEM; + goto err_free; + } + } + + goto out; + +err_free: + list_for_each_entry(display, displaylist, list) + drm_client_display_release(display); +out: + drm_client_modesets_release(modesets); + + return ret; +} + +static int drm_client_displays_compare(void *priv, struct list_head *lh_a, struct list_head *lh_b) +{ + struct drm_client_display *a = list_entry(lh_a, struct drm_client_display, list); + struct drm_client_display *b = list_entry(lh_b, struct drm_client_display, list); + + return b->mode->hdisplay * b->mode->vdisplay - a->mode->hdisplay * a->mode->vdisplay; +} + +static void drm_client_displays_sort(struct list_head *displaylist) +{ + list_sort(NULL, displaylist, drm_client_displays_compare); +} + +/** + * drm_client_probe_displays() - Probe for displays + * @client: DRM client + * @num_buffers: Number of buffers to attach (optional) + * @format: Buffer format + * + * This function probes for connected displays and updates the clients list of displays. + * The list is sorted from largest to smallest. + * + * Returns: + * Number of displays or negative error code on failure. + */ +int drm_client_probe_displays(struct drm_client_dev *client, unsigned int num_buffers, u32 format) +{ + struct drm_client_display *display, *tmp; + LIST_HEAD(displaylist); + bool changed = false; + int ret; + + ret = drm_client_find_displays(client, &displaylist); + if (ret < 0) + return ret; + + if (list_empty(&displaylist)) { + drm_client_release_displays(client); + return 0; + } + + mutex_lock(&client->displaylist_mutex); + + /* If a display hasn't changed, keep it to avoid reallocating buffers */ + list_for_each_entry_safe(display, tmp, &client->displaylist, list) { + struct drm_client_display *display2, *tmp2; + bool found = false; + + list_for_each_entry_safe(display2, tmp2, &displaylist, list) { + if (drm_client_display_equal(display, display2)) { + list_del(&display2->list); + drm_client_display_release(display2); + found = true; + break; + } + } + + if (!found) { + list_del(&display->list); + drm_client_display_release(display); + changed = true; + } + } + + if (!list_empty(&displaylist)) + changed = true; + + list_splice(&displaylist, &client->displaylist); + + /* Sort from largest to smallest */ + drm_client_displays_sort(&client->displaylist); + + if (changed) { + DRM_DEBUG_KMS("Displays:\n"); + drm_client_for_each_display(display, client) + drm_client_display_debugprint(display); + } + + if (num_buffers) { + drm_client_for_each_display(display, client) { + ret = drm_client_display_framebuffer_create(display, num_buffers, format); + if (ret) + goto out_unlock; + } + } + + ret = 0; + drm_client_for_each_display(display, client) + ret++; + +out_unlock: + mutex_unlock(&client->displaylist_mutex); + + return ret; +} +EXPORT_SYMBOL(drm_client_probe_displays); + +/** + * drm_client_release_displays() - Release displays + * @client: DRM client + * + * This function releases all the clients displays. + */ +void drm_client_release_displays(struct drm_client_dev *client) +{ + struct drm_client_display *display, *tmp; + + mutex_lock(&client->displaylist_mutex); + list_for_each_entry_safe(display, tmp, &client->displaylist, list) { + list_del(&display->list); + drm_client_display_release(display); + } + mutex_unlock(&client->displaylist_mutex); +} +EXPORT_SYMBOL(drm_client_release_displays); + +static int drm_client_display_set_buffer(struct drm_client_display *display, unsigned int buffer) +{ + struct drm_mode_set *modeset; + + if (!display || buffer >= display->num_buffers) + return -EINVAL; + + drm_client_for_each_modeset(modeset, display->modesets) + modeset->fb = display->buffers[buffer]->fb; + + return 0; +} + +static int drm_client_display_commit(struct drm_client_display *display) +{ + int ret; + + if (!display) + return -EINVAL; + + if (!drm_master_internal_acquire(display->client->dev)) + return -EBUSY; + + ret = drm_client_modesets_commit(display->client->dev, display->modesets); + + drm_master_internal_release(display->client->dev); + + return ret; +} + +/** + * drm_client_display_commit_buffer() - Commit display modeset(s) with buffer + * @display: Client display + * @buffer: Buffer index + * + * This function sets the framebuffer to @buffer and commits the modeset(s). + * + * Returns: + * Zero on success or negative error code on failure. + */ +int drm_client_display_commit_buffer(struct drm_client_display *display, unsigned int buffer) +{ + int ret; + + ret = drm_client_display_set_buffer(display, buffer); + if (ret) + return ret; + + return drm_client_display_commit(display); +} +EXPORT_SYMBOL(drm_client_display_commit_buffer); + #ifdef CONFIG_DEBUG_FS static int drm_client_debugfs_internal_clients(struct seq_file *m, void *data) { diff --git a/include/drm/drm_client.h b/include/drm/drm_client.h index 78fb82bd8371..ef7a9bd07b3c 100644 --- a/include/drm/drm_client.h +++ b/include/drm/drm_client.h @@ -3,12 +3,15 @@ #ifndef _DRM_CLIENT_H_ #define _DRM_CLIENT_H_ +#include +#include #include #include #include struct drm_client_dev; +struct drm_client_display; struct drm_device; struct drm_file; struct drm_framebuffer; @@ -55,6 +58,25 @@ struct drm_client_funcs { * This callback is optional. */ int (*hotplug)(struct drm_client_dev *client); + + /** + * @display_alloc: + * + * Called when allocating a &drm_client_display. It can be use to + * subclass the structure. + * + * This callback is optional. + */ + struct drm_client_display *(*display_alloc)(struct drm_client_dev *client); + + /** + * @display_free: + * + * Called when releasing a &drm_client_display. + * + * This callback is optional. + */ + void (*display_free)(struct drm_client_display *display); }; /** @@ -88,6 +110,19 @@ struct drm_client_dev { * @file: DRM file */ struct drm_file *file; + + /** + * @displaylist_mutex: Protects @displaylist. + */ + struct mutex displaylist_mutex; + + /** + * @displaylist: + * + * List of displays, linked through &drm_client_display.list. + */ + struct list_head displaylist; + }; int drm_client_init(struct drm_device *dev, struct drm_client_dev *client, @@ -169,6 +204,51 @@ void drm_client_modesets_dpms(struct drm_device *dev, struct drm_mode_set *modes #define drm_client_for_each_modeset(modeset, modesets) \ for (modeset = modesets; modeset->crtc; modeset++) +/** + * struct drm_client_display - DRM client display + */ +struct drm_client_display { + /** + * @client: DRM client. + */ + struct drm_client_dev *client; + + /** + * @list: + * + * List of all displays for a client, linked into + * &drm_client_dev.displaylist. Protected by &drm_client_dev.displaylist_mutex. + */ + struct list_head list; + + /** + * @mode: Current display mode. + */ + struct drm_display_mode *mode; + + /** + * @modesets: Per CRTC array of modeset configurations. + */ + struct drm_mode_set *modesets; + + /** + * @buffers: Display buffers (optional). + */ + struct drm_client_buffer **buffers; + + /** + * @num_buffers: Number of backing buffers. + */ + unsigned int num_buffers; +}; + +int drm_client_probe_displays(struct drm_client_dev *client, unsigned int num_buffers, u32 format); +void drm_client_release_displays(struct drm_client_dev *client); +int drm_client_display_commit_buffer(struct drm_client_display *display, unsigned int buffer); + +#define drm_client_for_each_display(display, client) \ + list_for_each_entry(display, &(client)->displaylist, list) + int drm_client_debugfs_init(struct drm_minor *minor); #endif From patchwork Tue Mar 26 17:55:45 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Noralf_Tr=C3=B8nnes?= X-Patchwork-Id: 10871861 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 7AB4C922 for ; Tue, 26 Mar 2019 18:04:43 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 65CC128A71 for ; Tue, 26 Mar 2019 18:04:43 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 5A29528C3D; Tue, 26 Mar 2019 18:04:43 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id B5CCE28A71 for ; Tue, 26 Mar 2019 18:04:42 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 0583589AAD; Tue, 26 Mar 2019 18:04:42 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from smtp.domeneshop.no (smtp.domeneshop.no [IPv6:2a01:5b40:0:3005::1]) by gabe.freedesktop.org (Postfix) with ESMTPS id 5109D88D18; Tue, 26 Mar 2019 18:04:40 +0000 (UTC) Received: from 211.81-166-168.customer.lyse.net ([81.166.168.211]:46322 helo=localhost.localdomain) by smtp.domeneshop.no with esmtpsa (TLS1.2:ECDHE_RSA_AES_128_CBC_SHA1:128) (Exim 4.84_2) (envelope-from ) id 1h8qIy-0006Mj-9O; Tue, 26 Mar 2019 18:56:08 +0100 From: =?utf-8?q?Noralf_Tr=C3=B8nnes?= To: dri-devel@lists.freedesktop.org Subject: [PATCH 15/16] drm/client: Hack: Add bootsplash example Date: Tue, 26 Mar 2019 18:55:45 +0100 Message-Id: <20190326175546.18126-16-noralf@tronnes.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190326175546.18126-1-noralf@tronnes.org> References: <20190326175546.18126-1-noralf@tronnes.org> MIME-Version: 1.0 X-Mailman-Original-DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=tronnes.org; s=ds201810; h=Content-Transfer-Encoding:Content-Type:MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From; bh=WCaILc8La8OaVkYEFHcJJdHeo6lbsbgALm4B4/pLXxg=; b=GZa754AiqHIZSGZKwgWqiefEUfE67NCkb4Dw1QZL0OLIGgNZ9h+DtKAgD7XS+7pZwzbTOlZ7NAE9KmMwtX6cnH47072jUCI0OVE49Ibz/mayCO4yufnGIzW6GugX5uL9wZikr2A6Y0JtO5HBdtlpw3HxtqQZB5AYC8716LqwwMrWrX8uctDuZ/egvtRpdS9iv5uh0075JlEMHLbvFkFeBWcevrF/rPqhDtgz0Ie/lAZGeEN88yCO+hClqRJEeSkm7BqmTSJsS86Uvm28cMav5sR305ORSuN/q4IBx+klkyTbD4P8kt+mfR6haXXVx2eheE2YlKHgIoZynYdBGcukJQ==; X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: intel-gfx@lists.freedesktop.org, mstaudt@suse.de Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Virus-Scanned: ClamAV using ClamSMTP An example to showcase the client API. TODO: A bootsplash client needs a way to tell drm_fb_helper to stay away, otherwise it will chime in on setup and hotplug. Most DRM drivers register fbdev before calling drm_dev_register() (the generic emulation is an exception). This have to be reversed for bootsplash to fend off fbdev. Signed-off-by: Noralf Trønnes --- drivers/gpu/drm/Kconfig | 5 + drivers/gpu/drm/Makefile | 1 + drivers/gpu/drm/drm_bootsplash.c | 216 +++++++++++++++++++++++++++++++ drivers/gpu/drm/drm_client.c | 7 + drivers/gpu/drm/drm_drv.c | 4 + include/drm/drm_client.h | 3 + 6 files changed, 236 insertions(+) create mode 100644 drivers/gpu/drm/drm_bootsplash.c diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index 5e1bc630b885..a7019c54e2a2 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -65,6 +65,11 @@ config DRM_DEBUG_SELFTEST If in doubt, say "N". +config DRM_CLIENT_BOOTSPLASH + bool "DRM Bootsplash" + help + DRM Bootsplash + config DRM_KMS_HELPER tristate depends on DRM diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index e630eccb951c..ac0573023842 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -32,6 +32,7 @@ drm-$(CONFIG_OF) += drm_of.o drm-$(CONFIG_AGP) += drm_agpsupport.o drm-$(CONFIG_DEBUG_FS) += drm_debugfs.o drm_debugfs_crc.o drm-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o +drm-$(CONFIG_DRM_CLIENT_BOOTSPLASH) += drm_bootsplash.o drm_kms_helper-y := drm_crtc_helper.o drm_dp_helper.o drm_dsc.o drm_probe_helper.o \ drm_plane_helper.o drm_dp_mst_topology.o drm_atomic_helper.o \ diff --git a/drivers/gpu/drm/drm_bootsplash.c b/drivers/gpu/drm/drm_bootsplash.c new file mode 100644 index 000000000000..fdc3349a2496 --- /dev/null +++ b/drivers/gpu/drm/drm_bootsplash.c @@ -0,0 +1,216 @@ +/* DRM internal client example */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +// drm_lastclose() +#include "drm_internal.h" + +static bool drm_bootsplash_enabled = true; +module_param_named(bootsplash_enabled, drm_bootsplash_enabled, bool, 0600); +MODULE_PARM_DESC(bootsplash_enabled, "Enable bootsplash client [default=true]"); + +struct drm_bootsplash { + struct drm_client_dev client; + struct mutex lock; + struct work_struct worker; + bool started; + bool stop; +}; + +static bool drm_bootsplash_key_pressed; + +static int drm_bootsplash_keyboard_notifier_call(struct notifier_block *blk, + unsigned long code, void *_param) +{ + /* Any key is good */ + drm_bootsplash_key_pressed = true; + + return NOTIFY_OK; +} + +static struct notifier_block drm_bootsplash_keyboard_notifier_block = { + .notifier_call = drm_bootsplash_keyboard_notifier_call, +}; + +static u32 drm_bootsplash_color_table[3] = { + 0x00ff0000, 0x0000ff00, 0x000000ff, +}; + +/* Draw a box with changing colors */ +static void drm_bootsplash_draw(struct drm_client_buffer *buffer, unsigned int sequence) +{ + unsigned int width = buffer->fb->width; + unsigned int height = buffer->fb->height; + unsigned int x, y; + u32 *pix; + + pix = buffer->vaddr; + pix += ((height / 2) - 50) * width; + pix += (width / 2) - 50; + + for (y = 0; y < 100; y++) { + for (x = 0; x < 100; x++) + *pix++ = drm_bootsplash_color_table[sequence]; + pix += width - 100; + } +} + +static void drm_bootsplash_worker(struct work_struct *work) +{ + struct drm_bootsplash *splash = container_of(work, struct drm_bootsplash, worker); + struct drm_client_dev *client = &splash->client; + struct drm_device *dev = client->dev; + struct drm_client_display *display; + unsigned int buffer_num = 0, sequence = 0, i; + bool stop; + int ret = 0; + + while (!drm_bootsplash_key_pressed) { + mutex_lock(&splash->lock); + stop = splash->stop; + mutex_unlock(&splash->lock); + if (stop) + break; + + buffer_num = !buffer_num; + + mutex_lock(&client->displaylist_mutex); + + ret = -ENOENT; + + i = 0; + drm_client_for_each_display(display, client) { + DRM_DEBUG_KMS("draw: i=%u, buffer_num=%u, sequence=%u\n", i++, buffer_num, sequence); + + drm_bootsplash_draw(display->buffers[buffer_num], sequence); + + ret = drm_client_display_commit_buffer(display, buffer_num); + if (ret == -EBUSY) + break; + + } + mutex_unlock(&client->displaylist_mutex); + + if (ret == -ENOENT || ret == -EBUSY) + break; + + if (++sequence == 3) + sequence = 0; + + msleep(500); + } + + /* Restore fbdev (or other) on key press. */ + /* TODO: Check if it's OK to call drm_lastclose here. */ + if (drm_bootsplash_key_pressed && !splash->stop) + drm_lastclose(dev); + + drm_client_release_displays(client); + + DRM_DEV_DEBUG_KMS(dev->dev, "Bootsplash has stopped (key=%u stop=%u, ret=%d).\n", + drm_bootsplash_key_pressed, splash->stop, ret); +} + +static int drm_bootsplash_client_hotplug(struct drm_client_dev *client) +{ + struct drm_bootsplash *splash = container_of(client, struct drm_bootsplash, client); + int ret; + + if (drm_bootsplash_key_pressed) + return 0; + + mutex_lock(&splash->lock); + + ret = drm_client_probe_displays(client, 2, DRM_FORMAT_XRGB8888); + if (!ret) + ret = -ENOENT; + if (ret < 0) + goto out_unlock; + + /* + * TODO: Deal with rotated panels, might have to sw rotate + if (drm_client_panel_rotation(...)) + */ + + if (!splash->started) { + splash->started = true; + schedule_work(&splash->worker); + } + +out_unlock: + mutex_unlock(&splash->lock); + + return ret; +} + +static void drm_bootsplash_client_unregister(struct drm_client_dev *client) +{ + struct drm_bootsplash *splash = container_of(client, struct drm_bootsplash, client); + + DRM_DEBUG_KMS("%s: IN\n", __func__); + + mutex_lock(&splash->lock); + splash->stop = true; + mutex_unlock(&splash->lock); + + flush_work(&splash->worker); + + drm_client_release(client); + kfree(splash); + + unregister_keyboard_notifier(&drm_bootsplash_keyboard_notifier_block); + + DRM_DEBUG_KMS("%s: OUT\n", __func__); +} + +static const struct drm_client_funcs drm_bootsplash_client_funcs = { + .owner = THIS_MODULE, + .unregister = drm_bootsplash_client_unregister, + .hotplug = drm_bootsplash_client_hotplug, +}; + +void drm_bootsplash_client_register(struct drm_device *dev) +{ + struct drm_bootsplash *splash; + int ret; + + if (!drm_bootsplash_enabled) + return; + + splash = kzalloc(sizeof(*splash), GFP_KERNEL); + if (!splash) + return; + + ret = drm_client_init(dev, &splash->client, "bootsplash", &drm_bootsplash_client_funcs); + if (ret) { + DRM_DEV_ERROR(dev->dev, "Failed to create client, ret=%d\n", ret); + kfree(splash); + return; + } + + /* For this simple example only allow the first */ + drm_bootsplash_enabled = false; + + mutex_init(&splash->lock); + + INIT_WORK(&splash->worker, drm_bootsplash_worker); + + drm_client_add(&splash->client); + + register_keyboard_notifier(&drm_bootsplash_keyboard_notifier_block); + + drm_bootsplash_client_hotplug(&splash->client); +} diff --git a/drivers/gpu/drm/drm_client.c b/drivers/gpu/drm/drm_client.c index ef01a31a9dbe..b7458fac0863 100644 --- a/drivers/gpu/drm/drm_client.c +++ b/drivers/gpu/drm/drm_client.c @@ -170,6 +170,13 @@ void drm_client_release(struct drm_client_dev *client) } EXPORT_SYMBOL(drm_client_release); +void drm_client_dev_register(struct drm_device *dev) +{ +#if CONFIG_DRM_CLIENT_BOOTSPLASH + drm_bootsplash_client_register(dev); +#endif +} + void drm_client_dev_unregister(struct drm_device *dev) { struct drm_client_dev *client, *tmp; diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index 50d849d1bc6e..fbbb5f998baf 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -1018,6 +1018,10 @@ int drm_dev_register(struct drm_device *dev, unsigned long flags) drm_minor_unregister(dev, DRM_MINOR_RENDER); out_unlock: mutex_unlock(&drm_global_mutex); + + if (!ret) + drm_client_dev_register(dev); + return ret; } EXPORT_SYMBOL(drm_dev_register); diff --git a/include/drm/drm_client.h b/include/drm/drm_client.h index ef7a9bd07b3c..cabd3055ba8a 100644 --- a/include/drm/drm_client.h +++ b/include/drm/drm_client.h @@ -130,6 +130,7 @@ int drm_client_init(struct drm_device *dev, struct drm_client_dev *client, void drm_client_release(struct drm_client_dev *client); void drm_client_add(struct drm_client_dev *client); +void drm_client_dev_register(struct drm_device *dev); void drm_client_dev_unregister(struct drm_device *dev); void drm_client_dev_hotplug(struct drm_device *dev); void drm_client_dev_restore(struct drm_device *dev); @@ -251,4 +252,6 @@ int drm_client_display_commit_buffer(struct drm_client_display *display, unsigne int drm_client_debugfs_init(struct drm_minor *minor); +void drm_bootsplash_client_register(struct drm_device *dev); + #endif From patchwork Tue Mar 26 17:55:46 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Noralf_Tr=C3=B8nnes?= X-Patchwork-Id: 10871857 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 7733017E0 for ; Tue, 26 Mar 2019 18:04:37 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 649F127FAC for ; Tue, 26 Mar 2019 18:04:37 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 58E4A2871A; Tue, 26 Mar 2019 18:04:37 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED autolearn=unavailable version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 280CA27FAC for ; Tue, 26 Mar 2019 18:04:37 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id D51CB88CE4; Tue, 26 Mar 2019 18:04:34 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from smtp.domeneshop.no (smtp.domeneshop.no [IPv6:2a01:5b40:0:3005::1]) by gabe.freedesktop.org (Postfix) with ESMTPS id 43E8688C90; Tue, 26 Mar 2019 18:04:33 +0000 (UTC) Received: from 211.81-166-168.customer.lyse.net ([81.166.168.211]:46322 helo=localhost.localdomain) by smtp.domeneshop.no with esmtpsa (TLS1.2:ECDHE_RSA_AES_128_CBC_SHA1:128) (Exim 4.84_2) (envelope-from ) id 1h8qIy-0006Mj-Tz; Tue, 26 Mar 2019 18:56:08 +0100 From: =?utf-8?q?Noralf_Tr=C3=B8nnes?= To: dri-devel@lists.freedesktop.org Subject: [PATCH 16/16] drm/vc4: Call drm_dev_register() after all setup is done Date: Tue, 26 Mar 2019 18:55:46 +0100 Message-Id: <20190326175546.18126-17-noralf@tronnes.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190326175546.18126-1-noralf@tronnes.org> References: <20190326175546.18126-1-noralf@tronnes.org> MIME-Version: 1.0 X-Mailman-Original-DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=tronnes.org; s=ds201810; h=Content-Transfer-Encoding:Content-Type:MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From; bh=shrSmZ0eK+F5cRyzvrotBh6ywSBdB49p4QMPlMtge9c=; b=goc2PmR5G/pdVHrfcDsLvurCcvWPWmjUO1hMLiZdeTA25mTarI2U6ovcQs4YHAl821Sb6OQg7eEZvh+ZSBU994CNWK2Yyd6XCXdDB2XDM/70xsYvhGUazO8pZBZfpZ+7qEeMmLpoPiKtaKppEt2Du4Z4WnHtbxGdA8CGgp2dRkIhogXO0TQ+QWQKVekQ/r4RuxQLtbsMLA3yOJJsqUbMLXuLqgpKQEB2Ege9TfQEjMT9cVMY/EA/NeOkkNUCr4/iwKV+5vCzPidyWjyuI31E4Z2McclAXyURunpwsU+pZp81YNkW7hWqBA8GeUjWhjmHxSPk0D2EbMe3WR8RA3uO+A==; X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: intel-gfx@lists.freedesktop.org, mstaudt@suse.de Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Virus-Scanned: ClamAV using ClamSMTP drm_dev_register() initializes internal clients like bootsplash as the last thing it does, so all setup needs to be done at this point. Fix by calling vc4_kms_load() before registering. Also check the error code returned from that function. Cc: Eric Anholt Signed-off-by: Noralf Trønnes Reviewed-by: Daniel Vetter Reviewed-by: Eric Anholt --- drivers/gpu/drm/vc4/vc4_drv.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c index 4daf44fd4548..ba87b2dfa767 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.c +++ b/drivers/gpu/drm/vc4/vc4_drv.c @@ -280,11 +280,13 @@ static int vc4_drm_bind(struct device *dev) drm_fb_helper_remove_conflicting_framebuffers(NULL, "vc4drmfb", false); - ret = drm_dev_register(drm, 0); + ret = vc4_kms_load(drm); if (ret < 0) goto unbind_all; - vc4_kms_load(drm); + ret = drm_dev_register(drm, 0); + if (ret < 0) + goto unbind_all; drm_fbdev_generic_setup(drm, 16);