From patchwork Wed Dec 13 15:33:29 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maxime Ripard X-Patchwork-Id: 121786 Delivered-To: patch@linaro.org Received: by 10.140.22.227 with SMTP id 90csp5620768qgn; Wed, 13 Dec 2017 07:33:52 -0800 (PST) X-Google-Smtp-Source: ACJfBov3JraV5j+5ltGwC3s3WNpA69jYUX0Q8Ns5DFiyA/91B5ozB7n+YPp32/0Wmpu2x+wXlBIr X-Received: by 10.159.234.68 with SMTP id c4mr6210530plr.305.1513179231937; Wed, 13 Dec 2017 07:33:51 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1513179231; cv=none; d=google.com; s=arc-20160816; b=DT4GIZdZgV5ZkFenBYoeyAs366xWVV0eIHmANBjIePEafBf6XEOSQp6mRQ8g3DLm7L QVc2+Tn2UfxHm0qBaEeQlmOf4XnxSYlwcZTXza5/dFWAWCHQVPgiEnBxBrfvvTQlw6La eo66lzF97C7flOpyc5rUJ4YNNL9a1eP2Z9J8irOW0Hea1ECbwuR/f86lqSX6km/xWlAg gJJg4EO0d6gru5y9Imigr+30gh5EjBK40F2+xMT7cep825ywYc06eqUiWRMqQvVr2Uky D5IfFTvrZFpOXvo5fuURr64IIBF8x43ZzH6A3ktP/N2w7mnoN1b7NLVwhBSd3iAXsP1A RKKw== 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=AGLmn/zMLUgVffvtEP1/1IAmdhk8LC6N6kmTck1npk4=; b=B307MV8kHf0YRDe1HylF8sOTzEVhsedJg3gU9d3WOLgGzYFTMi4oKKVKWQNCEI5VfY fFLt+QIwP6ZizDIw9UQg8WLngLWAWfYUH7Pa0lLgb6KlxpinrqpWv9Hyc4a0yamPjFXH i86R50M94YyAimBCkqEW9Pe7NnSo6PU+OhxVNXqBZfHnY0O8q5S0wd4VAme/o5P0KeRn SBRd+toFwjjRIhvifTDOq6dTRS7G0HlUJV2SvkTeHDpUkW349aKCvEg/3oXb+AeKyLUY 7o1JMKo5BXgtyyILD0QYIY0QTy0ZzHPzZXXrZFvN12UfcYLkso0i/xqEmz8bwm7IDOlL 6XMA== 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 o65si1432347pga.142.2017.12.13.07.33.51; Wed, 13 Dec 2017 07:33:51 -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 S1753524AbdLMPds (ORCPT + 12 others); Wed, 13 Dec 2017 10:33:48 -0500 Received: from mail.free-electrons.com ([62.4.15.54]:37718 "EHLO mail.free-electrons.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753429AbdLMPdl (ORCPT ); Wed, 13 Dec 2017 10:33:41 -0500 Received: by mail.free-electrons.com (Postfix, from userid 110) id 7BE1E2095A; Wed, 13 Dec 2017 16:33:39 +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 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 43D8720503; Wed, 13 Dec 2017 16:33:39 +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 , thomas@vitsch.nl Subject: [PATCH 5/8] drm/sun4i: Add a driver for the display frontend Date: Wed, 13 Dec 2017 16:33:29 +0100 Message-Id: <600d29233eb0dcca3af815fbed8995e35f78b4ee.1513178989.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 The display frontend is an hardware block that can be used to implement some more advanced features like hardware scaling or colorspace conversions. It can also be used to implement the output format of the VPU. Let's create a minimal driver for it that will only enable the hardware scaling features. Signed-off-by: Maxime Ripard --- drivers/gpu/drm/sun4i/Makefile | 3 +- drivers/gpu/drm/sun4i/sun4i_backend.c | 5 +- drivers/gpu/drm/sun4i/sun4i_backend.h | 1 +- drivers/gpu/drm/sun4i/sun4i_drv.c | 16 +- drivers/gpu/drm/sun4i/sun4i_drv.h | 1 +- drivers/gpu/drm/sun4i/sun4i_frontend.c | 377 ++++++++++++++++++++++++++- drivers/gpu/drm/sun4i/sun4i_frontend.h | 102 +++++++- 7 files changed, 500 insertions(+), 5 deletions(-) create mode 100644 drivers/gpu/drm/sun4i/sun4i_frontend.c create mode 100644 drivers/gpu/drm/sun4i/sun4i_frontend.h -- git-series 0.9.1 Reviewed-by: Neil Armstrong diff --git a/drivers/gpu/drm/sun4i/Makefile b/drivers/gpu/drm/sun4i/Makefile index 0c2f8c7facae..b660d82011f4 100644 --- a/drivers/gpu/drm/sun4i/Makefile +++ b/drivers/gpu/drm/sun4i/Makefile @@ -1,5 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 sun4i-backend-y += sun4i_backend.o sun4i_layer.o +sun4i-frontend-y += sun4i_frontend.o sun4i-drm-y += sun4i_drv.o sun4i-drm-y += sun4i_framebuffer.o @@ -21,6 +22,6 @@ obj-$(CONFIG_DRM_SUN4I) += sun4i-tcon.o obj-$(CONFIG_DRM_SUN4I) += sun4i_tv.o obj-$(CONFIG_DRM_SUN4I) += sun6i_drc.o -obj-$(CONFIG_DRM_SUN4I_BACKEND) += sun4i-backend.o +obj-$(CONFIG_DRM_SUN4I_BACKEND) += sun4i-backend.o sun4i-frontend.o obj-$(CONFIG_DRM_SUN4I_HDMI) += sun4i-drm-hdmi.o obj-$(CONFIG_DRM_SUN8I_MIXER) += sun8i-mixer.o diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c b/drivers/gpu/drm/sun4i/sun4i_backend.c index f971d3fb5ee4..e83e1fe43823 100644 --- a/drivers/gpu/drm/sun4i/sun4i_backend.c +++ b/drivers/gpu/drm/sun4i/sun4i_backend.c @@ -367,6 +367,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_err(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..ba1410fd5410 100644 --- a/drivers/gpu/drm/sun4i/sun4i_backend.h +++ b/drivers/gpu/drm/sun4i/sun4i_backend.h @@ -145,6 +145,7 @@ struct sun4i_backend { struct sunxi_engine engine; + struct sun4i_frontend *frontend; struct reset_control *reset; diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c index 75c76cdd82bc..17bf9bfd98ba 100644 --- a/drivers/gpu/drm/sun4i/sun4i_drv.c +++ b/drivers/gpu/drm/sun4i/sun4i_drv.c @@ -98,6 +98,7 @@ static int sun4i_drv_bind(struct device *dev) goto free_drm; } drm->dev_private = drv; + INIT_LIST_HEAD(&drv->frontend_list); INIT_LIST_HEAD(&drv->engine_list); INIT_LIST_HEAD(&drv->tcon_list); @@ -239,9 +240,11 @@ static int sun4i_drv_add_endpoints(struct device *dev, int count = 0; /* - * We don't support the frontend for now, so we will never - * have a device bound. Just skip over it, but we still want - * the rest our pipeline to be added. + * The frontend has been disabled in all of our old device + * trees. If we find a node that is the frontend and is + * disabled, we should just follow through and parse its + * child, but without adding it to the component list. + * Otherwise, we obviously want to add it to the list. */ if (!sun4i_drv_node_is_frontend(node) && !of_device_is_available(node)) @@ -254,7 +257,12 @@ static int sun4i_drv_add_endpoints(struct device *dev, if (sun4i_drv_node_is_connector(node)) return 0; - if (!sun4i_drv_node_is_frontend(node)) { + /* + * If the device is either just a regular device, or an + * enabled frontend, we add it to our component list. + */ + if (!sun4i_drv_node_is_frontend(node) || + (sun4i_drv_node_is_frontend(node) && of_device_is_available(node))) { /* Add current component */ DRM_DEBUG_DRIVER("Adding component %pOF\n", node); drm_of_component_match_add(dev, match, compare_of, node); diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.h b/drivers/gpu/drm/sun4i/sun4i_drv.h index a960c89270cc..9c26a345f85c 100644 --- a/drivers/gpu/drm/sun4i/sun4i_drv.h +++ b/drivers/gpu/drm/sun4i/sun4i_drv.h @@ -19,6 +19,7 @@ struct sun4i_drv { struct list_head engine_list; + struct list_head frontend_list; struct list_head tcon_list; struct drm_fbdev_cma *fbdev; diff --git a/drivers/gpu/drm/sun4i/sun4i_frontend.c b/drivers/gpu/drm/sun4i/sun4i_frontend.c new file mode 100644 index 000000000000..1be0e86d1457 --- /dev/null +++ b/drivers/gpu/drm/sun4i/sun4i_frontend.c @@ -0,0 +1,377 @@ +/* + * Copyright (C) 2017 Free Electrons + * + * Maxime Ripard + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + */ +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "sun4i_drv.h" +#include "sun4i_frontend.h" + +static const u32 sun4i_frontend_vert_coef[32] = { + 0x00004000, 0x000140ff, 0x00033ffe, 0x00043ffd, + 0x00063efc, 0xff083dfc, 0x000a3bfb, 0xff0d39fb, + 0xff0f37fb, 0xff1136fa, 0xfe1433fb, 0xfe1631fb, + 0xfd192ffb, 0xfd1c2cfb, 0xfd1f29fb, 0xfc2127fc, + 0xfc2424fc, 0xfc2721fc, 0xfb291ffd, 0xfb2c1cfd, + 0xfb2f19fd, 0xfb3116fe, 0xfb3314fe, 0xfa3611ff, + 0xfb370fff, 0xfb390dff, 0xfb3b0a00, 0xfc3d08ff, + 0xfc3e0600, 0xfd3f0400, 0xfe3f0300, 0xff400100, +}; + +static const u32 sun4i_frontend_horz_coef[64] = { + 0x40000000, 0x00000000, 0x40fe0000, 0x0000ff03, + 0x3ffd0000, 0x0000ff05, 0x3ffc0000, 0x0000ff06, + 0x3efb0000, 0x0000ff08, 0x3dfb0000, 0x0000ff09, + 0x3bfa0000, 0x0000fe0d, 0x39fa0000, 0x0000fe0f, + 0x38fa0000, 0x0000fe10, 0x36fa0000, 0x0000fe12, + 0x33fa0000, 0x0000fd16, 0x31fa0000, 0x0000fd18, + 0x2ffa0000, 0x0000fd1a, 0x2cfa0000, 0x0000fc1e, + 0x29fa0000, 0x0000fc21, 0x27fb0000, 0x0000fb23, + 0x24fb0000, 0x0000fb26, 0x21fb0000, 0x0000fb29, + 0x1ffc0000, 0x0000fa2b, 0x1cfc0000, 0x0000fa2e, + 0x19fd0000, 0x0000fa30, 0x16fd0000, 0x0000fa33, + 0x14fd0000, 0x0000fa35, 0x11fe0000, 0x0000fa37, + 0x0ffe0000, 0x0000fa39, 0x0dfe0000, 0x0000fa3b, + 0x0afe0000, 0x0000fa3e, 0x08ff0000, 0x0000fb3e, + 0x06ff0000, 0x0000fb40, 0x05ff0000, 0x0000fc40, + 0x03ff0000, 0x0000fd41, 0x01ff0000, 0x0000fe42, +}; + +static void sun4i_frontend_scaler_init(struct sun4i_frontend *frontend) +{ + int i; + + for (i = 0; i < 32; i++) { + regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_HORZCOEF0_REG(i), + sun4i_frontend_horz_coef[2 * i]); + regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_HORZCOEF0_REG(i), + sun4i_frontend_horz_coef[2 * i]); + regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_HORZCOEF1_REG(i), + sun4i_frontend_horz_coef[2 * i + 1]); + regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_HORZCOEF1_REG(i), + sun4i_frontend_horz_coef[2 * i + 1]); + regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_VERTCOEF_REG(i), + sun4i_frontend_vert_coef[i]); + regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_VERTCOEF_REG(i), + sun4i_frontend_vert_coef[i]); + } + + regmap_update_bits(frontend->regs, SUN4I_FRONTEND_FRM_CTRL_REG, BIT(23), BIT(23)); +} + +int sun4i_frontend_init(struct sun4i_frontend *frontend) +{ + int ret; + + if (atomic_read(&frontend->users)) + return -EBUSY; + + ret = reset_control_deassert(frontend->reset); + if (ret) { + DRM_DEBUG_DRIVER("Couldn't deassert our reset line\n"); + return ret; + } + + clk_set_rate(frontend->mod_clk, 300000000); + + clk_prepare_enable(frontend->bus_clk); + clk_prepare_enable(frontend->mod_clk); + clk_prepare_enable(frontend->ram_clk); + + regmap_update_bits(frontend->regs, SUN4I_FRONTEND_EN_REG, + SUN4I_FRONTEND_EN_EN, + SUN4I_FRONTEND_EN_EN); + + regmap_update_bits(frontend->regs, SUN4I_FRONTEND_BYPASS_REG, + SUN4I_FRONTEND_BYPASS_CSC_EN, + SUN4I_FRONTEND_BYPASS_CSC_EN); + + sun4i_frontend_scaler_init(frontend); + + atomic_inc(&frontend->users); + + return 0; +} +EXPORT_SYMBOL(sun4i_frontend_init); + +void sun4i_frontend_exit(struct sun4i_frontend *frontend) +{ + atomic_dec(&frontend->users); + + clk_disable_unprepare(frontend->ram_clk); + clk_disable_unprepare(frontend->mod_clk); + clk_disable_unprepare(frontend->bus_clk); + reset_control_assert(frontend->reset); +} +EXPORT_SYMBOL(sun4i_frontend_exit); + +void sun4i_frontend_update_buffer(struct sun4i_frontend *frontend, + struct drm_plane *plane) +{ + struct drm_plane_state *state = plane->state; + struct drm_framebuffer *fb = state->fb; + struct drm_gem_cma_object *gem; + dma_addr_t paddr; + int bpp; + + /* Get the physical address of the buffer in memory */ + gem = drm_fb_cma_get_gem_obj(fb, 0); + + DRM_DEBUG_DRIVER("Using GEM @ %pad\n", &gem->paddr); + + /* Set the line width */ + DRM_DEBUG_DRIVER("Frontend stride: %d bytes\n", fb->pitches[0]); + regmap_write(frontend->regs, SUN4I_FRONTEND_LINESTRD0_REG, + fb->pitches[0]); + + /* Compute the start of the displayed memory */ + bpp = fb->format->cpp[0]; + paddr = gem->paddr + fb->offsets[0]; + paddr += (state->src_x >> 16) * bpp; + paddr += (state->src_y >> 16) * fb->pitches[0]; + + DRM_DEBUG_DRIVER("Setting buffer address to %pad\n", &paddr); + regmap_write(frontend->regs, SUN4I_FRONTEND_BUF_ADDR0_REG, paddr); +} + +static int sun4i_frontend_drm_format_to_input_fmt(uint32_t fmt, u32 *val) +{ + switch (fmt) { + case DRM_FORMAT_ARGB8888: + case DRM_FORMAT_XRGB8888: + *val = 3; + return 0; + + default: + return -EINVAL; + } +} + +static int sun4i_frontend_drm_format_to_output_fmt(uint32_t fmt, u32 *val) +{ + switch (fmt) { + case DRM_FORMAT_ARGB8888: + *val = 2; + return 0; + + default: + return -EINVAL; + } +} + +int sun4i_frontend_update_formats(struct sun4i_frontend *frontend, + struct drm_plane *plane, uint32_t out_fmt) +{ + struct drm_plane_state *state = plane->state; + struct drm_framebuffer *fb = state->fb; + u32 out_fmt_val; + u32 in_fmt_val; + int ret; + + ret = sun4i_frontend_drm_format_to_input_fmt(fb->format->format, + &in_fmt_val); + if (ret) { + DRM_DEBUG_DRIVER("Invalid input format\n"); + return ret; + } + + ret = sun4i_frontend_drm_format_to_output_fmt(out_fmt, &out_fmt_val); + if (ret) { + DRM_DEBUG_DRIVER("Invalid output format\n"); + return ret; + } + + regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_HORZPHASE_REG, 0x400); + regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_HORZPHASE_REG, 0x400); + + regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_VERTPHASE0_REG, 0x400); + regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_VERTPHASE0_REG, 0x400); + + regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_VERTPHASE1_REG, 0x400); + regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_VERTPHASE1_REG, 0x400); + + regmap_write(frontend->regs, SUN4I_FRONTEND_INPUT_FMT_REG, 0x151); + /* SUN4I_FRONTEND_INPUT_FMT_DATA_MOD(1) | */ + /* SUN4I_FRONTEND_INPUT_FMT_DATA_FMT(5) | */ + /* SUN4I_FRONTEND_INPUT_FMT_PS(1)); */ + regmap_write(frontend->regs, SUN4I_FRONTEND_OUTPUT_FMT_REG, 0x82); + /* SUN4I_FRONTEND_OUTPUT_FMT_DATA_FMT(1)); */ + + return 0; +} + +void sun4i_frontend_update_coord(struct sun4i_frontend *frontend, + struct drm_plane *plane) +{ + struct drm_plane_state *state = plane->state; + + /* Set height and width */ + DRM_DEBUG_DRIVER("Frontend size W: %u H: %u\n", + state->crtc_w, state->crtc_h); + regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_INSIZE_REG, + SUN4I_FRONTEND_INSIZE(state->src_h >> 16, + state->src_w >> 16)); + regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_INSIZE_REG, + SUN4I_FRONTEND_INSIZE(state->src_h >> 16, + state->src_w >> 16)); + + regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_OUTSIZE_REG, + SUN4I_FRONTEND_OUTSIZE(state->crtc_h, state->crtc_w)); + regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_OUTSIZE_REG, + SUN4I_FRONTEND_OUTSIZE(state->crtc_h, state->crtc_w)); + + DRM_DEBUG_DRIVER("Frontend horizontal scaling factor %d.%d\n", 1, 0); + regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_HORZFACT_REG, + state->src_w / state->crtc_w); + regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_HORZFACT_REG, + state->src_w / state->crtc_w); + + DRM_DEBUG_DRIVER("Frontend vertical scaling factor %d.%d\n", 1, 0); + regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_VERTFACT_REG, + state->src_h / state->crtc_h); + regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_VERTFACT_REG, + state->src_h / state->crtc_h); + + regmap_write_bits(frontend->regs, SUN4I_FRONTEND_FRM_CTRL_REG, + SUN4I_FRONTEND_FRM_CTRL_REG_RDY, + SUN4I_FRONTEND_FRM_CTRL_REG_RDY); +} +EXPORT_SYMBOL(sun4i_frontend_update_coord); + +int sun4i_frontend_enable(struct sun4i_frontend *frontend) +{ + regmap_write_bits(frontend->regs, SUN4I_FRONTEND_FRM_CTRL_REG, + SUN4I_FRONTEND_FRM_CTRL_FRM_START, + SUN4I_FRONTEND_FRM_CTRL_FRM_START); + + return 0; +} +EXPORT_SYMBOL(sun4i_frontend_enable); + +static struct regmap_config sun4i_frontend_regmap_config = { + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, + .max_register = 0x0a14, +}; + +static int sun4i_frontend_bind(struct device *dev, struct device *master, + void *data) +{ + struct platform_device *pdev = to_platform_device(dev); + struct sun4i_frontend *frontend; + struct drm_device *drm = data; + struct sun4i_drv *drv = drm->dev_private; + struct resource *res; + void __iomem *regs; + + frontend = devm_kzalloc(dev, sizeof(*frontend), GFP_KERNEL); + if (!frontend) + return -ENOMEM; + dev_set_drvdata(dev, frontend); + frontend->node = dev->of_node; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + regs = devm_ioremap_resource(dev, res); + if (IS_ERR(regs)) + return PTR_ERR(regs); + + frontend->regs = devm_regmap_init_mmio(dev, regs, + &sun4i_frontend_regmap_config); + if (IS_ERR(frontend->regs)) { + dev_err(dev, "Couldn't create the frontend regmap\n"); + return PTR_ERR(frontend->regs); + } + + frontend->reset = devm_reset_control_get(dev, NULL); + if (IS_ERR(frontend->reset)) { + dev_err(dev, "Couldn't get our reset line\n"); + return PTR_ERR(frontend->reset); + } + + frontend->bus_clk = devm_clk_get(dev, "ahb"); + if (IS_ERR(frontend->bus_clk)) { + dev_err(dev, "Couldn't get our bus clock\n"); + return PTR_ERR(frontend->bus_clk); + } + + frontend->mod_clk = devm_clk_get(dev, "mod"); + if (IS_ERR(frontend->mod_clk)) { + dev_err(dev, "Couldn't get our mod clock\n"); + return PTR_ERR(frontend->mod_clk); + } + + frontend->ram_clk = devm_clk_get(dev, "ram"); + if (IS_ERR(frontend->ram_clk)) { + dev_err(dev, "Couldn't get our ram clock\n"); + return PTR_ERR(frontend->ram_clk); + } + + list_add_tail(&frontend->list, &drv->frontend_list); + + return 0; +} + +static void sun4i_frontend_unbind(struct device *dev, struct device *master, + void *data) +{ + struct sun4i_frontend *frontend = dev_get_drvdata(dev); + + clk_disable_unprepare(frontend->mod_clk); + clk_disable_unprepare(frontend->bus_clk); + reset_control_assert(frontend->reset); +} + +static const struct component_ops sun4i_frontend_ops = { + .bind = sun4i_frontend_bind, + .unbind = sun4i_frontend_unbind, +}; + +static int sun4i_frontend_probe(struct platform_device *pdev) +{ + return component_add(&pdev->dev, &sun4i_frontend_ops); +} + +static int sun4i_frontend_remove(struct platform_device *pdev) +{ + component_del(&pdev->dev, &sun4i_frontend_ops); + + return 0; +} + +static const struct of_device_id sun4i_frontend_of_table[] = { + { .compatible = "allwinner,sun5i-a13-display-frontend" }, + { .compatible = "allwinner,sun6i-a31-display-frontend" }, + { .compatible = "allwinner,sun8i-a33-display-frontend" }, + { } +}; +MODULE_DEVICE_TABLE(of, sun4i_frontend_of_table); + +static struct platform_driver sun4i_frontend_driver = { + .probe = sun4i_frontend_probe, + .remove = sun4i_frontend_remove, + .driver = { + .name = "sun4i-frontend", + .of_match_table = sun4i_frontend_of_table, + }, +}; +module_platform_driver(sun4i_frontend_driver); + +MODULE_AUTHOR("Maxime Ripard "); +MODULE_DESCRIPTION("Allwinner A10 Display Engine Frontend Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/sun4i/sun4i_frontend.h b/drivers/gpu/drm/sun4i/sun4i_frontend.h new file mode 100644 index 000000000000..2df9f6de0f3f --- /dev/null +++ b/drivers/gpu/drm/sun4i/sun4i_frontend.h @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2017 Free Electrons + * + * Maxime Ripard + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + */ + +#ifndef _SUN4I_FRONTEND_H_ +#define _SUN4I_FRONTEND_H_ + +#include +#include + +#define SUN4I_FRONTEND_EN_REG 0x000 +#define SUN4I_FRONTEND_EN_EN BIT(0) + +#define SUN4I_FRONTEND_FRM_CTRL_REG 0x004 +#define SUN4I_FRONTEND_FRM_CTRL_FRM_START BIT(16) +#define SUN4I_FRONTEND_FRM_CTRL_COEF_RDY BIT(1) +#define SUN4I_FRONTEND_FRM_CTRL_REG_RDY BIT(0) + +#define SUN4I_FRONTEND_BYPASS_REG 0x008 +#define SUN4I_FRONTEND_BYPASS_CSC_EN BIT(1) + +#define SUN4I_FRONTEND_BUF_ADDR0_REG 0x020 + +#define SUN4I_FRONTEND_LINESTRD0_REG 0x040 + +#define SUN4I_FRONTEND_INPUT_FMT_REG 0x04c +#define SUN4I_FRONTEND_INPUT_FMT_DATA_MOD(mod) ((mod) << 8) +#define SUN4I_FRONTEND_INPUT_FMT_DATA_FMT(fmt) ((fmt) << 4) +#define SUN4I_FRONTEND_INPUT_FMT_PS(ps) (ps) + +#define SUN4I_FRONTEND_OUTPUT_FMT_REG 0x05c +#define SUN4I_FRONTEND_OUTPUT_FMT_DATA_FMT(fmt) (fmt) + +#define SUN4I_FRONTEND_CH0_INSIZE_REG 0x100 +#define SUN4I_FRONTEND_INSIZE(h, w) ((((h) - 1) << 16) | (((w) - 1))) + +#define SUN4I_FRONTEND_CH0_OUTSIZE_REG 0x104 +#define SUN4I_FRONTEND_OUTSIZE(h, w) ((((h) - 1) << 16) | (((w) - 1))) + +#define SUN4I_FRONTEND_CH0_HORZFACT_REG 0x108 +#define SUN4I_FRONTEND_HORZFACT(i, f) (((i) << 16) | (f)) + +#define SUN4I_FRONTEND_CH0_VERTFACT_REG 0x10c +#define SUN4I_FRONTEND_VERTFACT(i, f) (((i) << 16) | (f)) + +#define SUN4I_FRONTEND_CH0_HORZPHASE_REG 0x110 +#define SUN4I_FRONTEND_CH0_VERTPHASE0_REG 0x114 +#define SUN4I_FRONTEND_CH0_VERTPHASE1_REG 0x118 + +#define SUN4I_FRONTEND_CH1_INSIZE_REG 0x200 +#define SUN4I_FRONTEND_CH1_OUTSIZE_REG 0x204 +#define SUN4I_FRONTEND_CH1_HORZFACT_REG 0x208 +#define SUN4I_FRONTEND_CH1_VERTFACT_REG 0x20c + +#define SUN4I_FRONTEND_CH1_HORZPHASE_REG 0x210 +#define SUN4I_FRONTEND_CH1_VERTPHASE0_REG 0x214 +#define SUN4I_FRONTEND_CH1_VERTPHASE1_REG 0x218 + +#define SUN4I_FRONTEND_CH0_HORZCOEF0_REG(i) (0x400 + i * 4) +#define SUN4I_FRONTEND_CH0_HORZCOEF1_REG(i) (0x480 + i * 4) +#define SUN4I_FRONTEND_CH0_VERTCOEF_REG(i) (0x500 + i * 4) +#define SUN4I_FRONTEND_CH1_HORZCOEF0_REG(i) (0x600 + i * 4) +#define SUN4I_FRONTEND_CH1_HORZCOEF1_REG(i) (0x680 + i * 4) +#define SUN4I_FRONTEND_CH1_VERTCOEF_REG(i) (0x700 + i * 4) + +struct clk; +struct device_node; +struct drm_plane; +struct regmap; +struct reset_control; + +struct sun4i_frontend { + struct list_head list; + atomic_t users; + struct device_node *node; + + struct clk *bus_clk; + struct clk *mod_clk; + struct clk *ram_clk; + struct regmap *regs; + struct reset_control *reset; +}; + +int sun4i_frontend_init(struct sun4i_frontend *frontend); +void sun4i_frontend_exit(struct sun4i_frontend *frontend); +int sun4i_frontend_enable(struct sun4i_frontend *frontend); + +void sun4i_frontend_update_buffer(struct sun4i_frontend *frontend, + struct drm_plane *plane); +void sun4i_frontend_update_coord(struct sun4i_frontend *frontend, + struct drm_plane *plane); +int sun4i_frontend_update_formats(struct sun4i_frontend *frontend, + struct drm_plane *plane, uint32_t out_fmt); + +#endif /* _SUN4I_FRONTEND_H_ */ From patchwork Wed Dec 13 15:33:30 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maxime Ripard X-Patchwork-Id: 121785 Delivered-To: patch@linaro.org Received: by 10.140.22.227 with SMTP id 90csp5620715qgn; Wed, 13 Dec 2017 07:33:49 -0800 (PST) X-Google-Smtp-Source: ACJfBosagP27fsKuTJOJ0PFUC7xpGCnM1/MiCN5J7EyxDvwjyV7K5j/nGabqPoQZJaPsESPhsjjD X-Received: by 10.159.245.144 with SMTP id a16mr6319454pls.302.1513179229447; Wed, 13 Dec 2017 07:33:49 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1513179229; cv=none; d=google.com; s=arc-20160816; b=bn6Uxb1E6vuvrdNRLUnmcFTZM4ok3PQTuABhFV0UXPWiEJQwcYfJHQq+us2Hf1eExH wD2/2UZrvHpxi4/2GPXbJ/ZL0XMIwSIltT2I+oLGBCE31dhJBuoZ2nk2dhRbfe06r1nn w2ZmOEXiH+nOCfoD8RvtmCYkUVx9ucGhN0Qsp06Pr08VIiouAlFwdFEzHo6pmZUFziL4 xSOhS2YTNwBjm80WHG8uk6LhgRTYFGWy8OQ4MOeJ50/tCS86YY7WS/ohua5FuWiucJsl aYQZ9p/ZgZ4smAEIzaFIdDSL2AQZl48NNnmUEIPgKPQjzrKTMAaBMKCoZXguv2WyFC+u CWbA== 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=wlG30iLueiyDtJH7QN6/gjKY43hR8B1TMlZcPNUuzdc=; b=lvWyvhdy4HBkLQ4u3ONncWzz6FMu+JPe5ptKA+1CQZa5O4EX5GzjmqW8+7EBjL2YZv hfYl1JHOy/aydaMw0+M1xTaO0AR9gXUDaW89Tg9K8NUvACQmTdfUijkf5SsH6PWCmQAk aOU/+SbTnvm3how+CFcaoygOLt6m1e+ZGBsHCFdGDyaBN970kagJ85FiDCn1/JQIZbLe ApQq5USdGjXwzUi6yiUkwgRsPihBypGkXq24Qep6pyrViYSmDhQ4CQEjai2ZVYuEjdWD GYzG/4/ziJM6XJqV5YrH2nI67iGJ3RoxObk/02AxrzqdlIp6Hga00tgF7Sx+MZIv+/K2 0RdQ== 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 p3si1578813pfg.369.2017.12.13.07.33.49; Wed, 13 Dec 2017 07:33:49 -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 S1753498AbdLMPdq (ORCPT + 12 others); Wed, 13 Dec 2017 10:33:46 -0500 Received: from mail.free-electrons.com ([62.4.15.54]:37723 "EHLO mail.free-electrons.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753434AbdLMPdl (ORCPT ); Wed, 13 Dec 2017 10:33:41 -0500 Received: by mail.free-electrons.com (Postfix, from userid 110) id CBCBF20964; Wed, 13 Dec 2017 16:33:39 +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 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 9F31F20503; Wed, 13 Dec 2017 16:33:39 +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 , thomas@vitsch.nl Subject: [PATCH 6/8] drm/sun4i: sun4i_layer: Wire in the frontend Date: Wed, 13 Dec 2017 16:33:30 +0100 Message-Id: <0cd2570c9cbe20d094cee0e8e9918c3a0f6af2fa.1513178989.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 | 53 ++++++++++++++++++++++++++++- drivers/gpu/drm/sun4i/sun4i_backend.h | 3 ++- drivers/gpu/drm/sun4i/sun4i_layer.c | 27 ++++++++++++-- drivers/gpu/drm/sun4i/sun4i_layer.h | 1 +- 4 files changed, 81 insertions(+), 3 deletions(-) -- git-series 0.9.1 Reviewed-by: Neil Armstrong diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c b/drivers/gpu/drm/sun4i/sun4i_backend.c index e83e1fe43823..f1d19767c55d 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) { @@ -330,6 +355,34 @@ 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, diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.h b/drivers/gpu/drm/sun4i/sun4i_backend.h index ba1410fd5410..636a51521e77 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) @@ -171,5 +172,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_layer.c b/drivers/gpu/drm/sun4i/sun4i_layer.c index c3afcf888906..3b58667a06dc 100644 --- a/drivers/gpu/drm/sun4i/sun4i_layer.c +++ b/drivers/gpu/drm/sun4i/sun4i_layer.c @@ -15,6 +15,7 @@ #include #include "sun4i_backend.h" +#include "sun4i_frontend.h" #include "sun4i_layer.h" #include "sunxi_engine.h" @@ -70,21 +71,41 @@ static void sun4i_backend_layer_destroy_state(struct drm_plane *plane, static void sun4i_backend_layer_atomic_disable(struct drm_plane *plane, struct drm_plane_state *old_state) { + struct sun4i_layer_state *layer_state = state_to_sun4i_layer_state(old_state); struct sun4i_layer *layer = plane_to_sun4i_layer(plane); struct sun4i_backend *backend = layer->backend; + struct sun4i_frontend *frontend = backend->frontend; sun4i_backend_layer_enable(backend, layer->id, false); + + if (layer_state->uses_frontend) + sun4i_frontend_exit(frontend); } static void sun4i_backend_layer_atomic_update(struct drm_plane *plane, struct drm_plane_state *old_state) { + struct sun4i_layer_state *layer_state = state_to_sun4i_layer_state(plane->state); struct sun4i_layer *layer = plane_to_sun4i_layer(plane); struct sun4i_backend *backend = layer->backend; + struct sun4i_frontend *frontend = backend->frontend; + + if (layer_state->uses_frontend) { + sun4i_frontend_init(frontend); + sun4i_frontend_update_coord(frontend, plane); + sun4i_frontend_update_buffer(frontend, plane); + sun4i_frontend_update_formats(frontend, plane, + DRM_FORMAT_ARGB8888); + sun4i_backend_update_layer_frontend(backend, layer->id, + DRM_FORMAT_ARGB8888); + sun4i_backend_update_layer_coord(backend, layer->id, plane); + sun4i_frontend_enable(frontend); + } else { + sun4i_backend_update_layer_coord(backend, layer->id, plane); + sun4i_backend_update_layer_formats(backend, layer->id, plane); + sun4i_backend_update_layer_buffer(backend, layer->id, plane); + } - sun4i_backend_update_layer_coord(backend, layer->id, plane); - sun4i_backend_update_layer_formats(backend, layer->id, plane); - sun4i_backend_update_layer_buffer(backend, layer->id, plane); sun4i_backend_layer_enable(backend, layer->id, true); } diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.h b/drivers/gpu/drm/sun4i/sun4i_layer.h index d2c19348d1b0..75b4868ba87c 100644 --- a/drivers/gpu/drm/sun4i/sun4i_layer.h +++ b/drivers/gpu/drm/sun4i/sun4i_layer.h @@ -24,6 +24,7 @@ struct sun4i_layer { struct sun4i_layer_state { struct drm_plane_state state; + bool uses_frontend; }; static inline struct sun4i_layer * From patchwork Wed Dec 13 15:33:31 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maxime Ripard X-Patchwork-Id: 121788 Delivered-To: patch@linaro.org Received: by 10.140.22.227 with SMTP id 90csp5620945qgn; Wed, 13 Dec 2017 07:34:01 -0800 (PST) X-Google-Smtp-Source: ACJfBotvY9RZ8xuAzjh0fDXh6zx0x1lM50vc3EBQ4ZsQ3tq4LAVGYrt6ob0sk+sCVmHzA7lUDe8/ X-Received: by 10.84.233.207 with SMTP id m15mr6196627pln.424.1513179241444; Wed, 13 Dec 2017 07:34:01 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1513179241; cv=none; d=google.com; s=arc-20160816; b=IfS0W/NkJFkaLAflEaa5i8I09WhKVx8FItlwAcpIV2rBMZBC3orIMtEh4Dv+YN0sJH K5H7XLBOf+8odvx8YPzvNK1fH4ihIrIIPghIv7bwmkpjtnaT6eTY+a/woqiqeHUOBMSP E7LnK2+j3WlhYFTb3qcSxM+UCi9MK+Xe+FNWyIg5loQQV6yEnudwZabap0Cw9mGe1q/s q1BYe26yhGP0BEFflcEd79C19398w34W6ueumEblK0jnAcbbr0mYPj4ThLUq6ClOf93M Py2OvfLoBqYz3JOBW7NCfwxfvizkwI2JjXVM6t7+SeQ6hrBtC1qVoRYDQjqq5ustGm0k diRw== 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=P/aJhQgJbQDDuABy1QeMaQirCPJajTtY2ipxt75KdVU=; b=wB6YHQv5qFF1fLkdIeeFMmQTtCRAualOv48XAdyWrkZ5qamQKHinsDPJxMB9nC9+kL BFFq3hAJilDwnsYylzFSyQHYzwvmWBeCLTRM7bxqZFolUH0KnjbiC7oSK8+cZyf2mSgP 9Mt7Sja/3PDJuXxy590vywFG2XIbbP45HBbXPNivsrlbaB0wN1r2kQ20QsidPM6/EGVi MqEFU/jMbxED/7PjXObaTnx3BK7odViuhV+jVRegH5qjLnh+KaXzxOSdv4yO4Fr+cIWg tTR+ZxVO1ukFd56UrSVMIm9BnxpsizGfmmsASP3J4ajMRf2NWRP2SMRdVmN5cy9G30yY VLKg== 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 o65si1432347pga.142.2017.12.13.07.34.01; Wed, 13 Dec 2017 07:34:01 -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 S1753560AbdLMPd6 (ORCPT + 12 others); Wed, 13 Dec 2017 10:33:58 -0500 Received: from mail.free-electrons.com ([62.4.15.54]:37727 "EHLO mail.free-electrons.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753441AbdLMPdl (ORCPT ); Wed, 13 Dec 2017 10:33:41 -0500 Received: by mail.free-electrons.com (Postfix, from userid 110) id 1E8BB20981; Wed, 13 Dec 2017 16:33:40 +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 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 EDCAA20503; Wed, 13 Dec 2017 16:33:39 +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 , thomas@vitsch.nl Subject: [PATCH 7/8] drm/sun4i: sun4i_layer: Add a custom atomic_check for the frontend Date: Wed, 13 Dec 2017 16:33:31 +0100 Message-Id: <4fbc349e2c3aa2efeadb55ea120c64b56c707cb4.1513178989.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 everything in place, we can start enabling the frontend. This is more difficult than one would assume since there can only be one plane using the frontend per-backend. We therefore need to make sure that the userspace will not try to setup multiple planes using it, since that would be impossible. In order to prevent that, we can create an atomic_check callback that will check that only one plane will effectively make use of the frontend in a given configuration, and will toggle the switch in that plane state so that the proper setup function can do their role. Signed-off-by: Maxime Ripard --- drivers/gpu/drm/sun4i/sun4i_backend.c | 65 ++++++++++++++++++++++++++++- drivers/gpu/drm/sun4i/sun4i_backend.h | 2 +- 2 files changed, 67 insertions(+) -- git-series 0.9.1 diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c b/drivers/gpu/drm/sun4i/sun4i_backend.c index f1d19767c55d..a7b87a12990e 100644 --- a/drivers/gpu/drm/sun4i/sun4i_backend.c +++ b/drivers/gpu/drm/sun4i/sun4i_backend.c @@ -11,6 +11,7 @@ */ #include +#include #include #include #include @@ -271,6 +272,69 @@ int sun4i_backend_update_layer_buffer(struct sun4i_backend *backend, return 0; } +static bool sun4i_backend_plane_uses_scaler(struct drm_plane_state *state) +{ + u16 src_h = state->src_h >> 16; + u16 src_w = state->src_w >> 16; + + DRM_DEBUG_DRIVER("Input size %dx%d, output size %dx%d\n", + src_w, src_h, state->crtc_w, state->crtc_h); + + if ((state->crtc_h != src_h) || (state->crtc_w != src_w)) + return true; + + return false; +} + +static bool sun4i_backend_plane_uses_frontend(struct drm_plane_state *state) +{ + struct sun4i_layer *layer = plane_to_sun4i_layer(state->plane); + struct sun4i_backend *backend = layer->backend; + + if (IS_ERR(backend->frontend)) + return false; + + return sun4i_backend_plane_uses_scaler(state); +} + +static int sun4i_backend_atomic_check(struct sunxi_engine *engine, + struct drm_crtc_state *crtc_state) +{ + struct drm_atomic_state *state = crtc_state->state; + struct drm_device *drm = state->dev; + struct drm_plane *plane; + unsigned int num_frontend_planes = 0; + + DRM_DEBUG_DRIVER("Starting checking our planes\n"); + + if (!crtc_state->planes_changed) + return 0; + + drm_for_each_plane_mask(plane, drm, crtc_state->plane_mask) { + struct drm_plane_state *plane_state = + drm_atomic_get_plane_state(state, plane); + struct sun4i_layer_state *layer_state = + state_to_sun4i_layer_state(plane_state); + + if (sun4i_backend_plane_uses_frontend(plane_state)) { + DRM_DEBUG_DRIVER("Using the frontend for plane %d\n", + plane->index); + + layer_state->uses_frontend = true; + num_frontend_planes++; + } else { + layer_state->uses_frontend = false; + } + } + + if (num_frontend_planes > SUN4I_BACKEND_NUM_FRONTEND_LAYERS) { + DRM_DEBUG_DRIVER("Too many planes going through the frontend, rejecting\n"); + return -EINVAL; + } + + return 0; +} + static int sun4i_backend_init_sat(struct device *dev) { struct sun4i_backend *backend = dev_get_drvdata(dev); int ret; @@ -384,6 +448,7 @@ static struct sun4i_frontend *sun4i_backend_find_frontend(struct sun4i_drv *drv, } static const struct sunxi_engine_ops sun4i_backend_engine_ops = { + .atomic_check = sun4i_backend_atomic_check, .commit = sun4i_backend_commit, .layers_init = sun4i_layers_init, .apply_color_correction = sun4i_backend_apply_color_correction, diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.h b/drivers/gpu/drm/sun4i/sun4i_backend.h index 636a51521e77..3b5531440fa3 100644 --- a/drivers/gpu/drm/sun4i/sun4i_backend.h +++ b/drivers/gpu/drm/sun4i/sun4i_backend.h @@ -144,6 +144,8 @@ #define SUN4I_BACKEND_HWCCOLORTAB_OFF 0x4c00 #define SUN4I_BACKEND_PIPE_OFF(p) (0x5000 + (0x400 * (p))) +#define SUN4I_BACKEND_NUM_FRONTEND_LAYERS 1 + struct sun4i_backend { struct sunxi_engine engine; struct sun4i_frontend *frontend; From patchwork Wed Dec 13 15:33:32 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maxime Ripard X-Patchwork-Id: 121787 Delivered-To: patch@linaro.org Received: by 10.140.22.227 with SMTP id 90csp5620863qgn; Wed, 13 Dec 2017 07:33:56 -0800 (PST) X-Google-Smtp-Source: ACJfBosCi/ch/8tUTmmYhTVZSYGdspEj3Y5Do03tIoOsQPMsyMk9FspxFnjWgh7fMc+vsqSjW+8N X-Received: by 10.84.225.145 with SMTP id u17mr6325933plj.273.1513179236613; Wed, 13 Dec 2017 07:33:56 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1513179236; cv=none; d=google.com; s=arc-20160816; b=VfFPunMsoRSaNW+1h2nfxYWicGZHx5o7tKM57l19q983hWZ3RgIA6LchPZFIsbqzus 6TNbhGFHYdodBErZxa0zZMspLTpKU2czS6LzmSZfJMHZ8oozucQilWDliYRJ/y08A573 Y65w7pBb1MXnlNh4WJWJ4sD6egH+EWMNMObu/PP60Cx4oz7DVNodNblGkFc0p8OkQJnk 63dF6hJFD3kaUU0I5KRkaAVtpSJzGIkZtQWB9aoBRqKwTiXC40QHw/Kc55Cxn+6O0Z+n /fvkoSC0gvB1ge7nX4fOZtyqHXvlHZqrKg1Kta1lnocIrD5cf7+BGCGqtz0rxaZ82hKM jh7Q== 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=qI5eVxQ2MWzf1SGQUA8CU4el7BL99qwfUoTMAt3V1b4=; b=Slt1j+k40AA9mPeuxumIX5MiLQw8T3xiA6lXEl+JV9ey0HJwPnLwtn+lyq+pjaEL4I MbFaT/QtdJjvb1jx0hfhoBjQ+ESKo2fznqeqS77TKQo+WqgmyN0LqbMvIvHBr2evFB4q 2Qr4IbnTXu6Vv76fA2bJfbsYOvhiN0TQ7NezR2DA/rFoQh4V5OBH811HC1WM8HSacIJi OU3XKHjowSzC7rFuOSi5c77cf8gJOz1Tnf9dbDsQSAgtGJ+wRpMQ0xHamg7bg0mhkzJP 41qxLttKbVxfAZtj8M/bhgyAWIlGp0Pk9mMuHqwq3jv0LUQBpgATV7gEK/pCdaeIF6Nm f1Iw== 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 o65si1432347pga.142.2017.12.13.07.33.56; Wed, 13 Dec 2017 07:33:56 -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 S1753544AbdLMPdx (ORCPT + 12 others); Wed, 13 Dec 2017 10:33:53 -0500 Received: from mail.free-electrons.com ([62.4.15.54]:37733 "EHLO mail.free-electrons.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753462AbdLMPdm (ORCPT ); Wed, 13 Dec 2017 10:33:42 -0500 Received: by mail.free-electrons.com (Postfix, from userid 110) id 6C6D820986; Wed, 13 Dec 2017 16:33:40 +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 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 4787420503; Wed, 13 Dec 2017 16:33:40 +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 , thomas@vitsch.nl Subject: [PATCH 8/8] ARM: dts: sun8i: a33 Enable our display frontend Date: Wed, 13 Dec 2017 16:33:32 +0100 Message-Id: <9f92f61048845b9a8496476e00ba6369cb42aae5.1513178989.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 The display frontend can be used to do hardware scaling, colorspaces conversion or to implement the buffer format output by the Cedar VPU. Since we're starting to have some support for it in the DRM driver, let's enable its DT node. Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun8i-a33.dtsi | 1 - 1 file changed, 1 deletion(-) -- git-series 0.9.1 diff --git a/arch/arm/boot/dts/sun8i-a33.dtsi b/arch/arm/boot/dts/sun8i-a33.dtsi index 50eb84fa246a..a21f2ed07a52 100644 --- a/arch/arm/boot/dts/sun8i-a33.dtsi +++ b/arch/arm/boot/dts/sun8i-a33.dtsi @@ -289,7 +289,6 @@ clock-names = "ahb", "mod", "ram"; resets = <&ccu RST_BUS_DE_FE>; - status = "disabled"; ports { #address-cells = <1>;