From patchwork Thu Nov 12 14:29:25 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Linus Walleij X-Patchwork-Id: 324198 Delivered-To: patch@linaro.org Received: by 2002:a05:6e02:5ce:0:0:0:0 with SMTP id l14csp380932ils; Thu, 12 Nov 2020 06:29:39 -0800 (PST) X-Google-Smtp-Source: ABdhPJz8xrsCQuuwdp6H/AfcfdVwjS+jl2w84zfLAuKc/VgbIMheLJsDdAOu/HlpdxTvEZqrnW61 X-Received: by 2002:a63:9508:: with SMTP id p8mr26210693pgd.189.1605191379573; Thu, 12 Nov 2020 06:29:39 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1605191379; cv=none; d=google.com; s=arc-20160816; b=iRRgOHgg96YwPIkADvdbTjLQqAk6z/xBWd61ymd5oQSYgXSzfPlMf8xgUwIXEfFXyU 1p1Ou1APgjGTxsM09b1XDl40X/kElKcDMh/37Rw944JwBxGMvMuRjoOy7WJVmqo9fxGh PAKY6ACNzn428HYArIF8R6W3SC4nYaIXGN6Xi9iertzPJGjAjFABZKFqE3sIuvZCOPgC butzvRUMN88PMrSPkFvJRWvtNJ9TGA1Ku1juhokFkYRKI92adsBzwbXY693P/KX2KAHn wOCCHBDW2hbHp2fWTN+i2Jn7amQEeMBB4vzeSiYckJzWXC+9Z8iAbKfvxtvfCMxlnryT tsrA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:cc:list-subscribe :list-help:list-post:list-archive:list-unsubscribe:list-id :precedence:mime-version:references:in-reply-to:message-id:date :subject:to:from:dkim-signature:delivered-to; bh=NLduSYROERS7GWvcsWB0tjJS6VgooasyOceA1gD6MhQ=; b=LgIVsqo9S3hjNHPX/mOFaMNWV7j3WRrRy8mJVFsFmZOSNLLFFZ3+99t00mM4QR4yBC WWegvVsiVVJ+xoBn507AaC3cJVLY14wfovcckVgOccotupxgh3GARN+opUwyNuvB7k4U ImyRDZYKlbRd0BN3AoWV1gsPmwMAOOhk/QATmPlUmIH+MvSmBjXOh278YOTIiChB4tMU xB89VWQO3VAnCG5P1pULpsaMvMj0IaVVit9zYf/NvufD3ii8FwfuOa/qnfdN9Y7jspIK PLgQWm640X8bmsoP5vFp99NiaPL6OTZkMQr2L5JOb+9pxAht+NMcEvIwZ9WvIQEQbtuu 83qw== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@linaro.org header.s=google header.b=umwtQuw8; spf=pass (google.com: best guess record for domain of dri-devel-bounces@lists.freedesktop.org designates 2610:10:20:722:a800:ff:fe36:1795 as permitted sender) smtp.mailfrom=dri-devel-bounces@lists.freedesktop.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from gabe.freedesktop.org (gabe.freedesktop.org. [2610:10:20:722:a800:ff:fe36:1795]) by mx.google.com with ESMTPS id b5si5132508plx.239.2020.11.12.06.29.39 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 12 Nov 2020 06:29:39 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of dri-devel-bounces@lists.freedesktop.org designates 2610:10:20:722:a800:ff:fe36:1795 as permitted sender) client-ip=2610:10:20:722:a800:ff:fe36:1795; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@linaro.org header.s=google header.b=umwtQuw8; spf=pass (google.com: best guess record for domain of dri-devel-bounces@lists.freedesktop.org designates 2610:10:20:722:a800:ff:fe36:1795 as permitted sender) smtp.mailfrom=dri-devel-bounces@lists.freedesktop.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 4E1566E252; Thu, 12 Nov 2020 14:29:36 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mail-lf1-x143.google.com (mail-lf1-x143.google.com [IPv6:2a00:1450:4864:20::143]) by gabe.freedesktop.org (Postfix) with ESMTPS id E5D626E252 for ; Thu, 12 Nov 2020 14:29:34 +0000 (UTC) Received: by mail-lf1-x143.google.com with SMTP id f11so8739305lfs.3 for ; Thu, 12 Nov 2020 06:29:34 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=bO5P44QyzK94T1fLdOtO7VbJWKz59UThq9+6F6aJ7Tk=; b=umwtQuw8asE5Q3MHbQhm/LpJZmFhmPLehM76xpgJhdX6mP59VM7H5A6xwjUfrqdrBF 0MtHno95RdWaYT+xPD4nIapx5u9zjD+/xVtEAbXdx3tg8PwT92kIkzyjy986ZtNSkruw ZFzkyYjaDjJlIhPpHLAxbmGthMR55kfJS8VR8m7nWcnjAKBMEiabdD6gq4eF2Qx8QbzM gh4PLXIv/0Q54p7xYvUtBCjhmIL9uj1aXDwKLUxIoVxlUNm4/roaKFID4/PZbH5frOF4 hI/RuoUoy25DO8Kg4fUo7kn5/MTJTWSbLIoy/e5Myb743KZ17c2nIVvnyxgE9CbP4VPF xJpw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=bO5P44QyzK94T1fLdOtO7VbJWKz59UThq9+6F6aJ7Tk=; b=qggk26Cbkj4xFePslYQHGyrFFA59MKDGvrGkY6sdZLxxzAURwH26iuHlJ/qdaCRyaT /iExOL9KLjpcOxskC7ZWNUQvi6zmcAwXA1m2RfXDzqfSGTbdqTXNkum3S88LNpGF+tEa X384Llas4gyvBu71mxQBfFtvauLF+h2hQQOkf83vyqfpbvuRWI8O+1pQH/tEpfeJ2YiV AMF3vAC93cAdVt3bIeheOp0MWbcLyFJ787gp1OYnTNi+p7u3bPbJ6LRJr2x5rAc1Swgb NydCo4gUsqBZk3plXNLAGtXfsvtt5+9gXZxnMRAvIGRYLV0ghdkT74yq8sW6zj3E447m bDJQ== X-Gm-Message-State: AOAM533WSbmhWlKudtaLnwjUFRzLfkyLO2ajjGWF5gtIKRtxKoUHv/w/ 5u5qOOEqAIOzIVOGZI7izv0vf2cB7gtEkQ== X-Received: by 2002:a19:c354:: with SMTP id t81mr10647348lff.283.1605191372801; Thu, 12 Nov 2020 06:29:32 -0800 (PST) Received: from localhost.bredbandsbolaget (c-92d7225c.014-348-6c756e10.bbcust.telenor.se. [92.34.215.146]) by smtp.gmail.com with ESMTPSA id o21sm206956lfg.40.2020.11.12.06.29.31 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 12 Nov 2020 06:29:32 -0800 (PST) From: Linus Walleij To: dri-devel@lists.freedesktop.org, Maarten Lankhorst , Maxime Ripard , Sean Paul Subject: [PATCH 2/2] drm/mcde: Support DPI output Date: Thu, 12 Nov 2020 15:29:25 +0100 Message-Id: <20201112142925.2571179-2-linus.walleij@linaro.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20201112142925.2571179-1-linus.walleij@linaro.org> References: <20201112142925.2571179-1-linus.walleij@linaro.org> MIME-Version: 1.0 X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: upstreaming@lists.sr.ht, phone-devel@vger.kernel.org, Stephan Gerhold , linux-arm-kernel@lists.infradead.org Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" This implements support for DPI output using the port node in the device tree to connect a DPI LCD display to the MCDE. The block also supports TV-out but we leave that for another day when we have a hardware using it. We implement parsing and handling of the "port" node, and follow that to the DPI endpoint. The clock divider used by the MCDE to divide down the "lcdclk" (this has been designed for TV-like frequencies) is represented by an ordinary clock provider internally in the MCDE. This idea was inspired by the PL111 solution by Eric Anholt: the divider also works very similar to the Pl111 clock divider. We take care to clear up some errors regarding the number of available formatters and their type. We have 6 DSI formatters and 2 DPI formatters. Tested on the Samsung GT-I9070 Janice mobile phone. Cc: Stephan Gerhold Cc: phone-devel@vger.kernel.org Cc: upstreaming@lists.sr.ht Signed-off-by: Linus Walleij --- drivers/gpu/drm/mcde/Kconfig | 1 + drivers/gpu/drm/mcde/Makefile | 2 +- drivers/gpu/drm/mcde/mcde_clk_div.c | 192 ++++++++++++++ drivers/gpu/drm/mcde/mcde_display.c | 304 ++++++++++++++++++++--- drivers/gpu/drm/mcde/mcde_display_regs.h | 87 +++++++ drivers/gpu/drm/mcde/mcde_drm.h | 10 + drivers/gpu/drm/mcde/mcde_drv.c | 46 +++- 7 files changed, 595 insertions(+), 47 deletions(-) create mode 100644 drivers/gpu/drm/mcde/mcde_clk_div.c -- 2.26.2 _______________________________________________ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel Acked-by: Sam Ravnborg diff --git a/drivers/gpu/drm/mcde/Kconfig b/drivers/gpu/drm/mcde/Kconfig index b3990126562c..71c689b573c9 100644 --- a/drivers/gpu/drm/mcde/Kconfig +++ b/drivers/gpu/drm/mcde/Kconfig @@ -4,6 +4,7 @@ config DRM_MCDE depends on CMA depends on ARM || COMPILE_TEST depends on OF + depends on COMMON_CLK select MFD_SYSCON select DRM_MIPI_DSI select DRM_BRIDGE diff --git a/drivers/gpu/drm/mcde/Makefile b/drivers/gpu/drm/mcde/Makefile index fe28f4e0fe46..15d9c89a3273 100644 --- a/drivers/gpu/drm/mcde/Makefile +++ b/drivers/gpu/drm/mcde/Makefile @@ -1,3 +1,3 @@ -mcde_drm-y += mcde_drv.o mcde_dsi.o mcde_display.o +mcde_drm-y += mcde_drv.o mcde_dsi.o mcde_clk_div.o mcde_display.o obj-$(CONFIG_DRM_MCDE) += mcde_drm.o diff --git a/drivers/gpu/drm/mcde/mcde_clk_div.c b/drivers/gpu/drm/mcde/mcde_clk_div.c new file mode 100644 index 000000000000..038821d2ef80 --- /dev/null +++ b/drivers/gpu/drm/mcde/mcde_clk_div.c @@ -0,0 +1,192 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include + +#include "mcde_drm.h" +#include "mcde_display_regs.h" + +/* The MCDE internal clock dividers for FIFO A and B */ +struct mcde_clk_div { + struct clk_hw hw; + struct mcde *mcde; + u32 cr; + u32 cr_div; +}; + +static int mcde_clk_div_enable(struct clk_hw *hw) +{ + struct mcde_clk_div *cdiv = container_of(hw, struct mcde_clk_div, hw); + struct mcde *mcde = cdiv->mcde; + u32 val; + + spin_lock(&mcde->fifo_crx1_lock); + val = readl(mcde->regs + cdiv->cr); + /* + * Select the PLL72 (LCD) clock as parent + * FIXME: implement other parents. + */ + val &= ~MCDE_CRX1_CLKSEL_MASK; + val |= MCDE_CRX1_CLKSEL_CLKPLL72 << MCDE_CRX1_CLKSEL_SHIFT; + /* Internal clock */ + val |= MCDE_CRA1_CLKTYPE_TVXCLKSEL1; + + /* Clear then set the divider */ + val &= ~(MCDE_CRX1_BCD | MCDE_CRX1_PCD_MASK); + val |= cdiv->cr_div; + + writel(val, mcde->regs + cdiv->cr); + spin_unlock(&mcde->fifo_crx1_lock); + + return 0; +} + +static int mcde_clk_div_choose_div(struct clk_hw *hw, unsigned long rate, + unsigned long *prate, bool set_parent) +{ + int best_div = 1, div; + struct clk_hw *parent = clk_hw_get_parent(hw); + unsigned long best_prate = 0; + unsigned long best_diff = ~0ul; + int max_div = (1 << MCDE_CRX1_PCD_BITS) - 1; + + for (div = 1; div < max_div; div++) { + unsigned long this_prate, div_rate, diff; + + if (set_parent) + this_prate = clk_hw_round_rate(parent, rate * div); + else + this_prate = *prate; + div_rate = DIV_ROUND_UP_ULL(this_prate, div); + diff = abs(rate - div_rate); + + if (diff < best_diff) { + best_div = div; + best_diff = diff; + best_prate = this_prate; + } + } + + *prate = best_prate; + return best_div; +} + +static long mcde_clk_div_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *prate) +{ + int div = mcde_clk_div_choose_div(hw, rate, prate, true); + + return DIV_ROUND_UP_ULL(*prate, div); +} + +static unsigned long mcde_clk_div_recalc_rate(struct clk_hw *hw, + unsigned long prate) +{ + struct mcde_clk_div *cdiv = container_of(hw, struct mcde_clk_div, hw); + struct mcde *mcde = cdiv->mcde; + u32 cr; + int div; + + /* + * If the MCDE is not powered we can't access registers. + * It will come up with 0 in the divider register bits, which + * means "divide by 2". + */ + if (!regulator_is_enabled(mcde->epod)) + return DIV_ROUND_UP_ULL(prate, 2); + + cr = readl(mcde->regs + cdiv->cr); + if (cr & MCDE_CRX1_BCD) + return prate; + + /* 0 in the PCD means "divide by 2", 1 means "divide by 3" etc */ + div = cr & MCDE_CRX1_PCD_MASK; + div += 2; + + return DIV_ROUND_UP_ULL(prate, div); +} + +static int mcde_clk_div_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long prate) +{ + struct mcde_clk_div *cdiv = container_of(hw, struct mcde_clk_div, hw); + int div = mcde_clk_div_choose_div(hw, rate, &prate, false); + u32 cr = 0; + + /* + * We cache the CR bits to set the divide in the state so that + * we can call this before we can even write to the hardware. + */ + if (div == 1) { + /* Bypass clock divider */ + cr |= MCDE_CRX1_BCD; + } else { + div -= 2; + cr |= div & MCDE_CRX1_PCD_MASK; + } + cdiv->cr_div = cr; + + return 0; +} + +static const struct clk_ops mcde_clk_div_ops = { + .enable = mcde_clk_div_enable, + .recalc_rate = mcde_clk_div_recalc_rate, + .round_rate = mcde_clk_div_round_rate, + .set_rate = mcde_clk_div_set_rate, +}; + +int mcde_init_clock_divider(struct mcde *mcde) +{ + struct device *dev = mcde->dev; + struct mcde_clk_div *fifoa; + struct mcde_clk_div *fifob; + const char *parent_name; + struct clk_init_data fifoa_init = { + .name = "fifoa", + .ops = &mcde_clk_div_ops, + .parent_names = &parent_name, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }; + struct clk_init_data fifob_init = { + .name = "fifob", + .ops = &mcde_clk_div_ops, + .parent_names = &parent_name, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }; + int ret; + + spin_lock_init(&mcde->fifo_crx1_lock); + parent_name = __clk_get_name(mcde->lcd_clk); + + /* Allocate 2 clocks */ + fifoa = devm_kzalloc(dev, sizeof(*fifoa), GFP_KERNEL); + if (!fifoa) + return -ENOMEM; + fifob = devm_kzalloc(dev, sizeof(*fifob), GFP_KERNEL); + if (!fifob) + return -ENOMEM; + + fifoa->mcde = mcde; + fifoa->cr = MCDE_CRA1; + fifoa->hw.init = &fifoa_init; + ret = devm_clk_hw_register(dev, &fifoa->hw); + if (ret) { + dev_err(dev, "error registering FIFO A clock divider\n"); + return ret; + } + mcde->fifoa_clk = fifoa->hw.clk; + + fifob->mcde = mcde; + fifob->cr = MCDE_CRB1; + fifob->hw.init = &fifob_init; + ret = devm_clk_hw_register(dev, &fifob->hw); + if (ret) { + dev_err(dev, "error registering FIFO B clock divider\n"); + return ret; + } + mcde->fifob_clk = fifob->hw.clk; + + return 0; +} diff --git a/drivers/gpu/drm/mcde/mcde_display.c b/drivers/gpu/drm/mcde/mcde_display.c index 66a07e340f8a..14c76d3a8e5a 100644 --- a/drivers/gpu/drm/mcde/mcde_display.c +++ b/drivers/gpu/drm/mcde/mcde_display.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -16,6 +17,7 @@ #include #include #include +#include #include #include