From patchwork Thu Apr 12 16:12:30 2018 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: 10338957 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id AA6D6600D0 for ; Thu, 12 Apr 2018 16:13:44 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 9A6FA26220 for ; Thu, 12 Apr 2018 16:13:44 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 8F06F26247; Thu, 12 Apr 2018 16:13:44 +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 D093226220 for ; Thu, 12 Apr 2018 16:13:43 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 2598C6EA9D; Thu, 12 Apr 2018 16:13:06 +0000 (UTC) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@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 91B8C6E995; Thu, 12 Apr 2018 16:13:00 +0000 (UTC) Received: from 211.81-166-168.customer.lyse.net ([81.166.168.211]:54390 helo=localhost.localdomain) by smtp.domeneshop.no with esmtpsa (TLS1.2:ECDHE_RSA_AES_128_CBC_SHA256:128) (Exim 4.84_2) (envelope-from ) id 1f6eqI-0002mh-3S; Thu, 12 Apr 2018 18:12:58 +0200 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= To: dri-devel@lists.freedesktop.org Date: Thu, 12 Apr 2018 18:12:30 +0200 Message-Id: <20180412161237.9314-7-noralf@tronnes.org> X-Mailer: git-send-email 2.15.1 In-Reply-To: <20180412161237.9314-1-noralf@tronnes.org> References: <20180412161237.9314-1-noralf@tronnes.org> MIME-Version: 1.0 Subject: [Intel-gfx] [RFC v4 18/25] drm/client: Make the display modes available to clients X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: daniel.vetter@ffwll.ch, intel-gfx@lists.freedesktop.org, =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= , laurent.pinchart@ideasonboard.com, mstaudt@suse.de, dh.herrmann@gmail.com Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Virus-Scanned: ClamAV using ClamSMTP Give clients easy access to the display modes. Signed-off-by: Noralf Trønnes --- drivers/gpu/drm/drm_client.c | 159 +++++++++++++++++++++++++++++++++---------- include/drm/drm_client.h | 25 +++++++ 2 files changed, 148 insertions(+), 36 deletions(-) diff --git a/drivers/gpu/drm/drm_client.c b/drivers/gpu/drm/drm_client.c index 764c556630b8..bce1630a0db2 100644 --- a/drivers/gpu/drm/drm_client.c +++ b/drivers/gpu/drm/drm_client.c @@ -8,6 +8,7 @@ * Copyright (c) 2007 Dave Airlie */ +#include #include #include @@ -54,6 +55,7 @@ struct drm_client_display *drm_client_display_create(struct drm_device *dev) } display->dev = dev; + INIT_LIST_HEAD(&display->modes); display->modeset_count = num_crtc; drm_for_each_crtc(crtc, dev) @@ -84,12 +86,16 @@ EXPORT_SYMBOL(drm_client_display_create); */ void drm_client_display_free(struct drm_client_display *display) { + struct drm_display_mode *mode, *tmp; struct drm_mode_set *modeset; unsigned int i; if (!display) return; + list_for_each_entry_safe(mode, tmp, &display->modes, head) + drm_mode_destroy(display->dev, mode); + drm_client_display_for_each_modeset(modeset, display) { if (modeset->mode) drm_mode_destroy(display->dev, modeset->mode); @@ -670,22 +676,70 @@ static int drm_pick_crtcs(struct drm_client_display *display, return best_score; } -/** - * drm_client_find_display() - Find display - * @dev: DRM device - * @width: Maximum display mode width (optional) - * @height: Maximum display mode height (optional) - * - * This function returns a display the client can use if available. - * - * Free resources by calling drm_client_display_free(). - * - * Returns: - * A &drm_client_display on success, NULL if no connectors are found - * or error pointer on failure. - */ -struct drm_client_display * -drm_client_find_display(struct drm_device *dev, unsigned int width, unsigned int height) +/* Give the client a static list of display modes */ +static int drm_client_display_copy_modes(struct drm_client_display *display) +{ + int hdisplay = 0, vdisplay = 0, vrefresh; + struct drm_device *dev = display->dev; + struct drm_display_mode *mode, *copy; + struct drm_connector *connector; + struct drm_mode_set *modeset; + unsigned int count = 0; + + drm_client_display_for_each_modeset(modeset, display) { + if (!modeset->num_connectors || !modeset->mode) + continue; + + connector = modeset->connectors[0]; + mode = modeset->mode; + count++; + + if (modeset->num_connectors == 2) { + /* Cloned output */ + copy = drm_mode_duplicate(dev, modeset->mode); + if (!copy) + return -ENOMEM; + list_add_tail(©->head, &display->modes); + display->mode = copy; + + return 0; + } + + if (!modeset->y) + hdisplay += modeset->mode->hdisplay; + if (!modeset->x) + vdisplay += modeset->mode->vdisplay; + vrefresh = modeset->mode->vrefresh; + } + + if (!count) + return 0; + + if (count == 1) { + struct drm_display_mode *iter; + + list_for_each_entry(iter, &connector->modes, head) { + copy = drm_mode_duplicate(dev, iter); + if (!copy) + return -ENOMEM; + list_add_tail(©->head, &display->modes); + if (!display->mode && drm_mode_equal(iter, mode)) + display->mode = copy; + } + } else { + /* Combined tile mode. Only the default one for now */ + copy = drm_cvt_mode(dev, hdisplay, vdisplay, vrefresh, false, false, false); + if (!copy) + return -ENOMEM; + list_add_tail(©->head, &display->modes); + display->mode = copy; + } + + return 0; +} + +static struct drm_client_display * +drm_client_find_display_default(struct drm_device *dev, unsigned int width, unsigned int height) { struct drm_client_display_offset *offsets; struct drm_client_display *display; @@ -695,25 +749,6 @@ drm_client_find_display(struct drm_device *dev, unsigned int width, unsigned int int i, connector_count; bool *enabled; - DRM_DEBUG_KMS("\n"); - - if (!width) - width = dev->mode_config.max_width; - if (!height) - height = dev->mode_config.max_height; - - mutex_lock(&dev->mode_config.mutex); - if (!drm_client_probe_connector_modes(dev, width, height)) - DRM_DEBUG_KMS("No connectors reported connected with modes\n"); - - if (dev->driver->initial_client_display) { - display = dev->driver->initial_client_display(dev, width, height); - if (display) { - mutex_unlock(&dev->mode_config.mutex); - return display; - } - } - connector_count = drm_connector_get_all(dev, &connectors); if (connector_count < 1) return NULL; @@ -772,7 +807,6 @@ drm_client_find_display(struct drm_device *dev, unsigned int width, unsigned int } } out: - mutex_unlock(&dev->mode_config.mutex); drm_connector_put_all(connectors, connector_count); kfree(crtcs); kfree(modes); @@ -781,4 +815,57 @@ drm_client_find_display(struct drm_device *dev, unsigned int width, unsigned int return display; } + +/** + * drm_client_find_display() - Find display + * @dev: DRM device + * @width: Maximum display mode width (optional) + * @height: Maximum display mode height (optional) + * + * This function returns a display the client can use if one is found. + * + * Free resources by calling drm_client_display_free(). + * + * Returns: + * A &drm_client_display on success, NULL if no connectors are found + * or error pointer on failure. + */ +struct drm_client_display * +drm_client_find_display(struct drm_device *dev, unsigned int width, unsigned int height) +{ + struct drm_client_display *display = NULL; + int ret; + + DRM_DEBUG_KMS("\n"); + + if (!width) + width = dev->mode_config.max_width; + if (!height) + height = dev->mode_config.max_height; + + mutex_lock(&dev->mode_config.mutex); + + if (!drm_client_probe_connector_modes(dev, width, height)) + DRM_DEBUG_KMS("No connectors reported connected with modes\n"); + + if (dev->driver->initial_client_display) + display = dev->driver->initial_client_display(dev, width, height); + + if (!display) + display = drm_client_find_display_default(dev, width, height); + + if (IS_ERR_OR_NULL(display)) + goto out_unlock; + + ret = drm_client_display_copy_modes(display); + if (ret) { + drm_client_display_free(display); + display = ERR_PTR(ret); + } + +out_unlock: + mutex_unlock(&dev->mode_config.mutex); + + return display; +} EXPORT_SYMBOL(drm_client_find_display); diff --git a/include/drm/drm_client.h b/include/drm/drm_client.h index 3befd879a0b0..524f793d6e7b 100644 --- a/include/drm/drm_client.h +++ b/include/drm/drm_client.h @@ -3,9 +3,12 @@ #ifndef _DRM_CLIENT_H_ #define _DRM_CLIENT_H_ +#include + struct drm_connector; struct drm_crtc; struct drm_device; +struct drm_display_mode; struct drm_mode_set; struct drm_plane; @@ -33,6 +36,20 @@ struct drm_client_display { * Number of modesets */ unsigned int modeset_count; + + /** + * @modes: + * + * Display modes available on this display. + */ + struct list_head modes; + + /** + * @mode: + * + * The current display mode. + */ + struct drm_display_mode *mode; }; struct drm_client_display *drm_client_display_create(struct drm_device *dev); @@ -51,4 +68,12 @@ int drm_client_display_dpms(struct drm_client_display *display, int mode); struct drm_client_display * drm_client_find_display(struct drm_device *dev, unsigned int width, unsigned int height); +/** + * drm_client_display_for_each_mode - Iterate over the available display modes + * @mode: A @drm_display_mode loop cursor + * @display: Client display + */ +#define drm_client_display_for_each_mode(mode, display) \ + list_for_each_entry(mode, &display->modes, head) + #endif