From patchwork Tue Jan 9 10:09:22 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maxime Ripard X-Patchwork-Id: 123857 Delivered-To: patch@linaro.org Received: by 10.80.140.226 with SMTP id r31csp266815edr; Tue, 9 Jan 2018 02:10:21 -0800 (PST) X-Google-Smtp-Source: ACJfBotl+i4yGzZE5WXUEMtyCpVJV/l6ZF/CkYe/EkI1dapGvKlSrKHWOuiGjhHkbxHGCdUDJBGd X-Received: by 10.98.130.5 with SMTP id w5mr716698pfd.117.1515492620880; Tue, 09 Jan 2018 02:10:20 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1515492620; cv=none; d=google.com; s=arc-20160816; b=qG5V44XTPhp/Moyx4O8/aEnQM5dWN93nxBAcXYPh1wXCnDiyTYy3k5+WEXMHsL2U2a 4RYZfP5tLSJhNGHl08J5Xz8fcDgZI2NxNyMtnZ/WcS3/GJHqrcWgCyN0roV5vJnpEeTc dj/6hn38qPlgyFvz7mFtS84IdvMnOak1d4Xfx/WnJqUg9uJGT4LrB6Esj2dePUkryz5k xC+kkx8jo2L2pWYJW0Y3SDSLl/5997eWgnwEL8ul3WUVJXTGEGEB1q0kTQLr8sKNkKAt FnE8nsRUK4T9yS8zP/DViTArFxBZ12d8xSStgnb+6VtRKbQFz65V70cDDbKNspD0szu2 n3Yw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:references :in-reply-to:message-id:date:subject:cc:to:from :arc-authentication-results; bh=q51qNpVhvaAi9PbnFKmra8NcBo8pfIjnYm7ynlk99tU=; b=fPxFe5mtFwYAw6tnZ35CNdDROg31BRMgDDhkR54cFitcV+BNU1IYunClvSDLcWUB15 StJ45DOmeYUTm6crWgPG2rdnjDJYojPT84yeV76v9qsWlVB6Fddg6kDMrHyxX2Ww1M/3 /3c7hrjFrkXp+78s3BlKyufd8WaN1X3ubbGXjCWrthIiu6PAiZpyrwbANbGtlIIOUh49 34O5qne2QxSFzfSCm34KyU19xZqna+y5iMQFMBLltgk1eQy3ZqE4EbwL8OGMzqnjVEcg ltZuwpXDa9itg3S9xnEEiO8M6BXsvkVYDDbIbnXzmWk3dEH2D7lZIxxTCcKYyLjYCyga ciCg== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id n3si8838670pgr.696.2018.01.09.02.10.20; Tue, 09 Jan 2018 02:10:20 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754071AbeAIKKS (ORCPT + 28 others); Tue, 9 Jan 2018 05:10:18 -0500 Received: from mail.free-electrons.com ([62.4.15.54]:48475 "EHLO mail.free-electrons.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753319AbeAIKJw (ORCPT ); Tue, 9 Jan 2018 05:09:52 -0500 Received: by mail.free-electrons.com (Postfix, from userid 110) id 695D520741; Tue, 9 Jan 2018 11:09:49 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on mail.free-electrons.com X-Spam-Level: X-Spam-Status: No, score=-1.0 required=5.0 tests=ALL_TRUSTED,SHORTCIRCUIT, URIBL_BLOCKED shortcircuit=ham autolearn=disabled version=3.4.0 Received: from localhost (LStLambert-657-1-97-87.w90-63.abo.wanadoo.fr [90.63.216.87]) by mail.free-electrons.com (Postfix) with ESMTPSA id 1CE002074A; Tue, 9 Jan 2018 11:09:32 +0100 (CET) From: Maxime Ripard To: Daniel Vetter , David Airlie , Chen-Yu Tsai , Maxime Ripard Cc: dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, Thomas Petazzoni , narmstrong@baylibre.com, thomas@vitsch.nl Subject: [PATCH v3 09/13] drm/sun4i: backend: Wire in the frontend Date: Tue, 9 Jan 2018 11:09:22 +0100 Message-Id: <936ca493795fe9a223f2958bdf8e7b6c874522ec.1515492513.git-series.maxime.ripard@free-electrons.com> X-Mailer: git-send-email 2.14.3 In-Reply-To: References: In-Reply-To: References: Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Now that we have a driver, we can make use of it. This is done by adding a flag to our custom plane state that will trigger whether we should use the frontend on that particular plane or not. The rest is just plumbing to set up the backend to not perform the DMA but receive its data from the frontend. Note that we're still not making any use of the frontend itself, as no one is setting the flag yet. Signed-off-by: Maxime Ripard --- drivers/gpu/drm/sun4i/sun4i_backend.c | 90 ++++++++++++++++++++++++++++- drivers/gpu/drm/sun4i/sun4i_backend.h | 8 ++- drivers/gpu/drm/sun4i/sun4i_crtc.c | 1 +- drivers/gpu/drm/sun4i/sun4i_layer.c | 33 +++++++++- drivers/gpu/drm/sun4i/sun4i_layer.h | 1 +- 5 files changed, 130 insertions(+), 3 deletions(-) -- git-series 0.9.1 diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c b/drivers/gpu/drm/sun4i/sun4i_backend.c index f971d3fb5ee4..29e1ca7e01fe 100644 --- a/drivers/gpu/drm/sun4i/sun4i_backend.c +++ b/drivers/gpu/drm/sun4i/sun4i_backend.c @@ -26,6 +26,7 @@ #include "sun4i_backend.h" #include "sun4i_drv.h" +#include "sun4i_frontend.h" #include "sun4i_layer.h" #include "sunxi_engine.h" @@ -203,6 +204,30 @@ int sun4i_backend_update_layer_formats(struct sun4i_backend *backend, return 0; } +int sun4i_backend_update_layer_frontend(struct sun4i_backend *backend, + int layer, uint32_t fmt) +{ + u32 val; + int ret; + + ret = sun4i_backend_drm_format_to_layer(NULL, fmt, &val); + if (ret) { + DRM_DEBUG_DRIVER("Invalid format\n"); + return ret; + } + + regmap_update_bits(backend->engine.regs, + SUN4I_BACKEND_ATTCTL_REG0(layer), + SUN4I_BACKEND_ATTCTL_REG0_LAY_VDOEN, + SUN4I_BACKEND_ATTCTL_REG0_LAY_VDOEN); + + regmap_update_bits(backend->engine.regs, + SUN4I_BACKEND_ATTCTL_REG1(layer), + SUN4I_BACKEND_ATTCTL_REG1_LAY_FBFMT, val); + + return 0; +} + int sun4i_backend_update_layer_buffer(struct sun4i_backend *backend, int layer, struct drm_plane *plane) { @@ -246,6 +271,36 @@ int sun4i_backend_update_layer_buffer(struct sun4i_backend *backend, return 0; } +static void sun4i_backend_vblank_quirk(struct sunxi_engine *engine) +{ + struct sun4i_backend *backend = engine_to_sun4i_backend(engine); + struct sun4i_frontend *frontend = backend->frontend; + + if (!frontend) + return; + + /* + * In a teardown scenario with the frontend involved, we have + * to keep the frontend enabled until the next vblank, and + * only then disable it. + * + * This is due to the fact that the backend will not take into + * account the new configuration (with the plane that used to + * be fed by the frontend now disabled) until we write to the + * commit bit and the hardware fetches the new configuration + * during the next vblank. + * + * So we keep the frontend around in order to prevent any + * visual artifacts. + */ + spin_lock(&backend->frontend_lock); + if (backend->frontend_teardown) { + sun4i_frontend_exit(frontend); + backend->frontend_teardown = false; + } + spin_unlock(&backend->frontend_lock); +}; + static int sun4i_backend_init_sat(struct device *dev) { struct sun4i_backend *backend = dev_get_drvdata(dev); int ret; @@ -330,11 +385,40 @@ static int sun4i_backend_of_get_id(struct device_node *node) return ret; } +static struct sun4i_frontend *sun4i_backend_find_frontend(struct sun4i_drv *drv, + struct device_node *node) +{ + struct device_node *port, *ep, *remote; + struct sun4i_frontend *frontend; + + port = of_graph_get_port_by_id(node, 0); + if (!port) + return ERR_PTR(-EINVAL); + + for_each_available_child_of_node(port, ep) { + remote = of_graph_get_remote_port_parent(ep); + if (!remote) + continue; + + /* does this node match any registered engines? */ + list_for_each_entry(frontend, &drv->frontend_list, list) { + if (remote == frontend->node) { + of_node_put(remote); + of_node_put(port); + return frontend; + } + } + } + + return ERR_PTR(-EINVAL); +} + static const struct sunxi_engine_ops sun4i_backend_engine_ops = { .commit = sun4i_backend_commit, .layers_init = sun4i_layers_init, .apply_color_correction = sun4i_backend_apply_color_correction, .disable_color_correction = sun4i_backend_disable_color_correction, + .vblank_quirk = sun4i_backend_vblank_quirk, }; static struct regmap_config sun4i_backend_regmap_config = { @@ -360,6 +444,7 @@ static int sun4i_backend_bind(struct device *dev, struct device *master, if (!backend) return -ENOMEM; dev_set_drvdata(dev, backend); + spin_lock_init(&backend->frontend_lock); backend->engine.node = dev->of_node; backend->engine.ops = &sun4i_backend_engine_ops; @@ -367,6 +452,11 @@ static int sun4i_backend_bind(struct device *dev, struct device *master, if (backend->engine.id < 0) return backend->engine.id; + backend->frontend = sun4i_backend_find_frontend(drv, dev->of_node); + if (IS_ERR(backend->frontend)) { + dev_warn(dev, "Couldn't find matching frontend, frontend features disabled\n"); + } + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); regs = devm_ioremap_resource(dev, res); if (IS_ERR(regs)) diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.h b/drivers/gpu/drm/sun4i/sun4i_backend.h index ac3cc029f5cd..350a2dbde31a 100644 --- a/drivers/gpu/drm/sun4i/sun4i_backend.h +++ b/drivers/gpu/drm/sun4i/sun4i_backend.h @@ -72,6 +72,7 @@ #define SUN4I_BACKEND_ATTCTL_REG0_LAY_PIPESEL(x) ((x) << 15) #define SUN4I_BACKEND_ATTCTL_REG0_LAY_PRISEL_MASK GENMASK(11, 10) #define SUN4I_BACKEND_ATTCTL_REG0_LAY_PRISEL(x) ((x) << 10) +#define SUN4I_BACKEND_ATTCTL_REG0_LAY_VDOEN BIT(1) #define SUN4I_BACKEND_ATTCTL_REG1(l) (0x8a0 + (0x4 * (l))) #define SUN4I_BACKEND_ATTCTL_REG1_LAY_HSCAFCT GENMASK(15, 14) @@ -145,6 +146,7 @@ struct sun4i_backend { struct sunxi_engine engine; + struct sun4i_frontend *frontend; struct reset_control *reset; @@ -154,6 +156,10 @@ struct sun4i_backend { struct clk *sat_clk; struct reset_control *sat_reset; + + /* Protects against races in the frontend teardown */ + spinlock_t frontend_lock; + bool frontend_teardown; }; static inline struct sun4i_backend * @@ -170,5 +176,7 @@ int sun4i_backend_update_layer_formats(struct sun4i_backend *backend, int layer, struct drm_plane *plane); int sun4i_backend_update_layer_buffer(struct sun4i_backend *backend, int layer, struct drm_plane *plane); +int sun4i_backend_update_layer_frontend(struct sun4i_backend *backend, + int layer, uint32_t in_fmt); #endif /* _SUN4I_BACKEND_H_ */ diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.c b/drivers/gpu/drm/sun4i/sun4i_crtc.c index f549f2874353..3b2d11b675e8 100644 --- a/drivers/gpu/drm/sun4i/sun4i_crtc.c +++ b/drivers/gpu/drm/sun4i/sun4i_crtc.c @@ -25,6 +25,7 @@ #include