From patchwork Fri Jun 7 10:59:57 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ryan Walklin X-Patchwork-Id: 13689690 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 07D4FC27C53 for ; Fri, 7 Jun 2024 11:03:08 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 42A2010EBCB; Fri, 7 Jun 2024 11:03:07 +0000 (UTC) Authentication-Results: gabe.freedesktop.org; dkim=pass (2048-bit key; unprotected) header.d=testtoast.com header.i=@testtoast.com header.b="iTU70gkU"; dkim=pass (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.b="PHk5lWRb"; dkim-atps=neutral Received: from wfout8-smtp.messagingengine.com (wfout8-smtp.messagingengine.com [64.147.123.151]) by gabe.freedesktop.org (Postfix) with ESMTPS id E7ABF10EBCB for ; Fri, 7 Jun 2024 11:03:05 +0000 (UTC) Received: from compute1.internal (compute1.nyi.internal [10.202.2.41]) by mailfout.west.internal (Postfix) with ESMTP id 18E4C1C000FB; Fri, 7 Jun 2024 07:03:04 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute1.internal (MEProxy); Fri, 07 Jun 2024 07:03:05 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=testtoast.com; h=cc:cc:content-transfer-encoding:content-type:date:date:from :from:in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to; s=fm1; t=1717758183; x= 1717844583; bh=BY+zIofCaC7v+wzShc4ej3nFK7NEM7edW7mapbborSE=; b=i TU70gkUBAEwV7XrnWynxYLFHP1By9zArbN7L8Gi3/xQPQr7zrEBzi6swIb4LnNJ3 ASJAxrDnkvclQpfHgGM1gTTaL0IT5rgTRPQ6CFvEx6JsTR+C1ebDbnwOPxKwhQgU TgdswKlpSN34X8tw0GVmQFz1uIJOiKF7yVNBPqY1hgpCeuWQa12n3c7gnuS4KzNC r0+gble3x5ksF66LqayWoldRMouTeUv5XEbYDBH4/3UdD/8gWgT0mWyQXZg4ya89 Lt35kvYldGXmawYx+HegJ8T+AEzE3uwEs4+L/bUqBUrR/Ph3UgBEfALshYflX9A6 zkIjD+sy/wsq8DthBuPLw== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to:x-me-proxy:x-me-proxy :x-me-sender:x-me-sender:x-sasl-enc; s=fm1; t=1717758183; x= 1717844583; bh=BY+zIofCaC7v+wzShc4ej3nFK7NEM7edW7mapbborSE=; b=P Hk5lWRboc1/g7fhar4Fm+Hfty7k8rZIvQuuGod/NBeIqktc+pj0iWnXLLta+9FDL TKjZNeX5808KuJmIDt9nTiOatCH6lvRpGERmrSB8BSkyaUOlSB/ruZNTad7/d09p 3H6Fqd3t4EkF7h83bkEYLnkYUHiRa+DxHvfqfvLoVxsdtwFCwPQalZB6UuGdenvy twjM4OR0J2ASzr4xmWhnQ6I5np3DMxBr20DOR12eQb/Rv+kguAUM+4O8B1ITEojT o/GkxSYbOv9BdHctwn+YVxXCxjQyPHCnBWcqPX167DrSgO7Omz/KpCnxlo12VqML WwOU36YE4qtdn4/9ppeoQ== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvledrfedtuddgudduucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhephffvvefufffkofgjfhgggfestdekredtredttdenucfhrhhomheptfihrghn ucghrghlkhhlihhnuceorhihrghnsehtvghsthhtohgrshhtrdgtohhmqeenucggtffrrg htthgvrhhnpeffheeiffegtdfgffejteevgeefkeelieelkeevueetffetteduffevgeei ieehteenucevlhhushhtvghrufhiiigvpedtnecurfgrrhgrmhepmhgrihhlfhhrohhmpe hrhigrnhesthgvshhtthhorghsthdrtghomh X-ME-Proxy: Feedback-ID: idc0145fc:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Fri, 7 Jun 2024 07:02:57 -0400 (EDT) From: Ryan Walklin To: Maxime Ripard , Chen-Yu Tsai , Maarten Lankhorst , Thomas Zimmermann , David Airlie , Daniel Vetter , Jernej Skrabec , Samuel Holland , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Michael Turquette , Stephen Boyd Cc: Andre Przywara , Chris Morgan , John Watts , dri-devel@lists.freedesktop.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, devicetree@vger.kernel.org, linux-clk@vger.kernel.org, Ryan Walklin Subject: [PATCH RFC 1/8] dt-bindings: bus: allwinner: add H616 DE33 bindings Date: Fri, 7 Jun 2024 22:59:57 +1200 Message-ID: <20240607110227.49848-2-ryan@testtoast.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20240607110227.49848-1-ryan@testtoast.com> References: <20240607110227.49848-1-ryan@testtoast.com> 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: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" The Allwinner H616 and variants have a new display engine revision (DE33). Add display engine bus, clock and mixer bindings for the DE33. Signed-off-by: Ryan Walklin --- .../devicetree/bindings/bus/allwinner,sun50i-a64-de2.yaml | 1 + .../devicetree/bindings/clock/allwinner,sun8i-a83t-de2-clk.yaml | 1 + .../bindings/display/allwinner,sun8i-a83t-de2-mixer.yaml | 1 + 3 files changed, 3 insertions(+) diff --git a/Documentation/devicetree/bindings/bus/allwinner,sun50i-a64-de2.yaml b/Documentation/devicetree/bindings/bus/allwinner,sun50i-a64-de2.yaml index 9845a187bdf65..65f4522e79879 100644 --- a/Documentation/devicetree/bindings/bus/allwinner,sun50i-a64-de2.yaml +++ b/Documentation/devicetree/bindings/bus/allwinner,sun50i-a64-de2.yaml @@ -25,6 +25,7 @@ properties: - const: allwinner,sun50i-a64-de2 - items: - const: allwinner,sun50i-h6-de3 + - const: allwinner,sun50i-h616-de33 - const: allwinner,sun50i-a64-de2 reg: diff --git a/Documentation/devicetree/bindings/clock/allwinner,sun8i-a83t-de2-clk.yaml b/Documentation/devicetree/bindings/clock/allwinner,sun8i-a83t-de2-clk.yaml index 70369bd633e40..7fcd55d468d49 100644 --- a/Documentation/devicetree/bindings/clock/allwinner,sun8i-a83t-de2-clk.yaml +++ b/Documentation/devicetree/bindings/clock/allwinner,sun8i-a83t-de2-clk.yaml @@ -25,6 +25,7 @@ properties: - const: allwinner,sun50i-a64-de2-clk - const: allwinner,sun50i-h5-de2-clk - const: allwinner,sun50i-h6-de3-clk + - const: allwinner,sun50i-h616-de33-clk - items: - const: allwinner,sun8i-r40-de2-clk - const: allwinner,sun8i-h3-de2-clk diff --git a/Documentation/devicetree/bindings/display/allwinner,sun8i-a83t-de2-mixer.yaml b/Documentation/devicetree/bindings/display/allwinner,sun8i-a83t-de2-mixer.yaml index b75c1ec686ad2..c37eb8ae1b8ee 100644 --- a/Documentation/devicetree/bindings/display/allwinner,sun8i-a83t-de2-mixer.yaml +++ b/Documentation/devicetree/bindings/display/allwinner,sun8i-a83t-de2-mixer.yaml @@ -24,6 +24,7 @@ properties: - allwinner,sun50i-a64-de2-mixer-0 - allwinner,sun50i-a64-de2-mixer-1 - allwinner,sun50i-h6-de3-mixer-0 + - allwinner,sun50i-h616-de33-mixer-0 reg: maxItems: 1 From patchwork Fri Jun 7 10:59:58 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ryan Walklin X-Patchwork-Id: 13689691 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 1496CC27C53 for ; Fri, 7 Jun 2024 11:03:17 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 52F3110EBD9; Fri, 7 Jun 2024 11:03:16 +0000 (UTC) Authentication-Results: gabe.freedesktop.org; dkim=pass (2048-bit key; unprotected) header.d=testtoast.com header.i=@testtoast.com header.b="t+NmQxuT"; dkim=pass (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.b="bOSWt2Um"; dkim-atps=neutral Received: from wfout8-smtp.messagingengine.com (wfout8-smtp.messagingengine.com [64.147.123.151]) by gabe.freedesktop.org (Postfix) with ESMTPS id A51F310EBD9 for ; Fri, 7 Jun 2024 11:03:15 +0000 (UTC) Received: from compute6.internal (compute6.nyi.internal [10.202.2.47]) by mailfout.west.internal (Postfix) with ESMTP id 89B501C000F0; Fri, 7 Jun 2024 07:03:13 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute6.internal (MEProxy); Fri, 07 Jun 2024 07:03:15 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=testtoast.com; h=cc:cc:content-transfer-encoding:content-type:date:date:from :from:in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to; s=fm1; t=1717758193; x= 1717844593; bh=uxxj0kRytR4xUJkNxo0CSdi/jrBjbr/V1KlwzqO/4No=; b=t +NmQxuTOHWZxSmfCyflsnf4eNtvj8nQCCVi7+i1ne697tje5wW0Yq4Wscel5eiLo Ekx8VVNonz0FnoqapK6vamX0sJDU+uE/vTRdx676omgKrdlk091lUEvMXCdtO6ZN b+vbvH1ITPNrWUN2Dm0ZP8ooFECTiJ8Na+zd2IypA1qg95SuCG+jOjsdkWJdsX/+ ItUHzbxo+rQLu4JENGqsJ2l+d5UZxxGkJAmGF8vHdP9BMF1K+b0lyRbxQ3TmaPFo i4rMFyv8E+lYJW78/WZowRhqi51ENMaTmBm7FNfh8L1uhC0hVPgxoZR/KHRclP7+ 9VIev8ax/YfmdhQsGcHeQ== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to:x-me-proxy:x-me-proxy :x-me-sender:x-me-sender:x-sasl-enc; s=fm1; t=1717758193; x= 1717844593; bh=uxxj0kRytR4xUJkNxo0CSdi/jrBjbr/V1KlwzqO/4No=; b=b OSWt2UmN4v2NXNrMlrK0oRGvoY49ETpe5NnbulN9QVt5adHg8yL2MWaiomWQuP5L QwI/NtcDV54n4cP6rZesfqHa94tZXR785+eOxHUuJmFA9SfDv1MpMyUc7wn9PSip GrL2Mz1LoRpF7I19wb/IXcZ4oRNzYcwqFyjOyaLN8wup2lq9NDJlVY6T16VKNlP6 2dPrzs4hfwD1h34Gf1veuuXiJJlmwgcSt0z+48pPrWC5FaDnf22ctA92s96+b+Nm 8g3xfTZbeUxksLPIKqXaZ1r2IBGQyvgAejX7j0XFDpQXmRss5jU0GJV5IbP+ZaAX 4OMWM4vSY9rCp7RnRCUow== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvledrfedtuddgudduucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhephffvvefufffkofgjfhgggfestdekredtredttdenucfhrhhomheptfihrghn ucghrghlkhhlihhnuceorhihrghnsehtvghsthhtohgrshhtrdgtohhmqeenucggtffrrg htthgvrhhnpeffheeiffegtdfgffejteevgeefkeelieelkeevueetffetteduffevgeei ieehteenucevlhhushhtvghrufhiiigvpedtnecurfgrrhgrmhepmhgrihhlfhhrohhmpe hrhigrnhesthgvshhtthhorghsthdrtghomh X-ME-Proxy: Feedback-ID: idc0145fc:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Fri, 7 Jun 2024 07:03:05 -0400 (EDT) From: Ryan Walklin To: Maxime Ripard , Chen-Yu Tsai , Maarten Lankhorst , Thomas Zimmermann , David Airlie , Daniel Vetter , Jernej Skrabec , Samuel Holland , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Michael Turquette , Stephen Boyd Cc: Andre Przywara , Chris Morgan , John Watts , dri-devel@lists.freedesktop.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, devicetree@vger.kernel.org, linux-clk@vger.kernel.org, Jernej Skrabec , Ryan Walklin Subject: [PATCH RFC 2/8] drm: sun4i: de2/de3: Change CSC argument Date: Fri, 7 Jun 2024 22:59:58 +1200 Message-ID: <20240607110227.49848-3-ryan@testtoast.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20240607110227.49848-1-ryan@testtoast.com> References: <20240607110227.49848-1-ryan@testtoast.com> 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: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" From: Jernej Skrabec Currently, CSC module takes care only for converting YUV to RGB. However, DE3 is more suited to work in YUV color space. Change CSC mode argument to format type to be more neutral. New argument only tells layer format type and doesn't imply output type. This commit doesn't make any functional change. Signed-off-by: Jernej Skrabec Co-developed-by: Ryan Walklin Signed-off-by: Ryan Walklin --- drivers/gpu/drm/sun4i/sun8i_csc.c | 22 +++++++++++----------- drivers/gpu/drm/sun4i/sun8i_csc.h | 10 +++++----- drivers/gpu/drm/sun4i/sun8i_vi_layer.c | 16 ++++++++-------- 3 files changed, 24 insertions(+), 24 deletions(-) diff --git a/drivers/gpu/drm/sun4i/sun8i_csc.c b/drivers/gpu/drm/sun4i/sun8i_csc.c index 58480d8e4f704..6ebd1c3aa3ab5 100644 --- a/drivers/gpu/drm/sun4i/sun8i_csc.c +++ b/drivers/gpu/drm/sun4i/sun8i_csc.c @@ -108,7 +108,7 @@ static const u32 yuv2rgb_de3[2][3][12] = { }; static void sun8i_csc_set_coefficients(struct regmap *map, u32 base, - enum sun8i_csc_mode mode, + enum format_type fmt_type, enum drm_color_encoding encoding, enum drm_color_range range) { @@ -118,12 +118,12 @@ static void sun8i_csc_set_coefficients(struct regmap *map, u32 base, table = yuv2rgb[range][encoding]; - switch (mode) { - case SUN8I_CSC_MODE_YUV2RGB: + switch (fmt_type) { + case FORMAT_TYPE_YUV: base_reg = SUN8I_CSC_COEFF(base, 0); regmap_bulk_write(map, base_reg, table, 12); break; - case SUN8I_CSC_MODE_YVU2RGB: + case FORMAT_TYPE_YVU: for (i = 0; i < 12; i++) { if ((i & 3) == 1) base_reg = SUN8I_CSC_COEFF(base, i + 1); @@ -141,7 +141,7 @@ static void sun8i_csc_set_coefficients(struct regmap *map, u32 base, } static void sun8i_de3_ccsc_set_coefficients(struct regmap *map, int layer, - enum sun8i_csc_mode mode, + enum format_type fmt_type, enum drm_color_encoding encoding, enum drm_color_range range) { @@ -151,12 +151,12 @@ static void sun8i_de3_ccsc_set_coefficients(struct regmap *map, int layer, table = yuv2rgb_de3[range][encoding]; - switch (mode) { - case SUN8I_CSC_MODE_YUV2RGB: + switch (fmt_type) { + case FORMAT_TYPE_YUV: addr = SUN50I_MIXER_BLEND_CSC_COEFF(DE3_BLD_BASE, layer, 0); regmap_bulk_write(map, addr, table, 12); break; - case SUN8I_CSC_MODE_YVU2RGB: + case FORMAT_TYPE_YVU: for (i = 0; i < 12; i++) { if ((i & 3) == 1) addr = SUN50I_MIXER_BLEND_CSC_COEFF(DE3_BLD_BASE, @@ -206,7 +206,7 @@ static void sun8i_de3_ccsc_enable(struct regmap *map, int layer, bool enable) } void sun8i_csc_set_ccsc_coefficients(struct sun8i_mixer *mixer, int layer, - enum sun8i_csc_mode mode, + enum format_type fmt_type, enum drm_color_encoding encoding, enum drm_color_range range) { @@ -214,14 +214,14 @@ void sun8i_csc_set_ccsc_coefficients(struct sun8i_mixer *mixer, int layer, if (mixer->cfg->is_de3) { sun8i_de3_ccsc_set_coefficients(mixer->engine.regs, layer, - mode, encoding, range); + fmt_type, encoding, range); return; } base = ccsc_base[mixer->cfg->ccsc][layer]; sun8i_csc_set_coefficients(mixer->engine.regs, base, - mode, encoding, range); + fmt_type, encoding, range); } void sun8i_csc_enable_ccsc(struct sun8i_mixer *mixer, int layer, bool enable) diff --git a/drivers/gpu/drm/sun4i/sun8i_csc.h b/drivers/gpu/drm/sun4i/sun8i_csc.h index 828b86fd0cabb..7322770f39f03 100644 --- a/drivers/gpu/drm/sun4i/sun8i_csc.h +++ b/drivers/gpu/drm/sun4i/sun8i_csc.h @@ -22,14 +22,14 @@ struct sun8i_mixer; #define SUN8I_CSC_CTRL_EN BIT(0) -enum sun8i_csc_mode { - SUN8I_CSC_MODE_OFF, - SUN8I_CSC_MODE_YUV2RGB, - SUN8I_CSC_MODE_YVU2RGB, +enum format_type { + FORMAT_TYPE_RGB, + FORMAT_TYPE_YUV, + FORMAT_TYPE_YVU, }; void sun8i_csc_set_ccsc_coefficients(struct sun8i_mixer *mixer, int layer, - enum sun8i_csc_mode mode, + enum format_type fmt_type, enum drm_color_encoding encoding, enum drm_color_range range); void sun8i_csc_enable_ccsc(struct sun8i_mixer *mixer, int layer, bool enable); diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c index f9c0a56d3a148..76e2d3ec0a78c 100644 --- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c +++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c @@ -242,19 +242,19 @@ static int sun8i_vi_layer_update_coord(struct sun8i_mixer *mixer, int channel, return 0; } -static u32 sun8i_vi_layer_get_csc_mode(const struct drm_format_info *format) +static u32 sun8i_vi_layer_get_format_type(const struct drm_format_info *format) { if (!format->is_yuv) - return SUN8I_CSC_MODE_OFF; + return FORMAT_TYPE_RGB; switch (format->format) { case DRM_FORMAT_YVU411: case DRM_FORMAT_YVU420: case DRM_FORMAT_YVU422: case DRM_FORMAT_YVU444: - return SUN8I_CSC_MODE_YVU2RGB; + return FORMAT_TYPE_YVU; default: - return SUN8I_CSC_MODE_YUV2RGB; + return FORMAT_TYPE_YUV; } } @@ -262,7 +262,7 @@ static int sun8i_vi_layer_update_formats(struct sun8i_mixer *mixer, int channel, int overlay, struct drm_plane *plane) { struct drm_plane_state *state = plane->state; - u32 val, ch_base, csc_mode, hw_fmt; + u32 val, ch_base, fmt_type, hw_fmt; const struct drm_format_info *fmt; int ret; @@ -280,9 +280,9 @@ static int sun8i_vi_layer_update_formats(struct sun8i_mixer *mixer, int channel, SUN8I_MIXER_CHAN_VI_LAYER_ATTR(ch_base, overlay), SUN8I_MIXER_CHAN_VI_LAYER_ATTR_FBFMT_MASK, val); - csc_mode = sun8i_vi_layer_get_csc_mode(fmt); - if (csc_mode != SUN8I_CSC_MODE_OFF) { - sun8i_csc_set_ccsc_coefficients(mixer, channel, csc_mode, + fmt_type = sun8i_vi_layer_get_format_type(fmt); + if (fmt_type != FORMAT_TYPE_RGB) { + sun8i_csc_set_ccsc_coefficients(mixer, channel, fmt_type, state->color_encoding, state->color_range); sun8i_csc_enable_ccsc(mixer, channel, true); From patchwork Fri Jun 7 10:59:59 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ryan Walklin X-Patchwork-Id: 13689692 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id E7A0AC27C53 for ; Fri, 7 Jun 2024 11:03:26 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 19CE910EBDA; Fri, 7 Jun 2024 11:03:26 +0000 (UTC) Authentication-Results: gabe.freedesktop.org; dkim=pass (2048-bit key; unprotected) header.d=testtoast.com header.i=@testtoast.com header.b="Ou5oTqkO"; dkim=pass (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.b="kaBG1h5x"; dkim-atps=neutral Received: from wfhigh3-smtp.messagingengine.com (wfhigh3-smtp.messagingengine.com [64.147.123.154]) by gabe.freedesktop.org (Postfix) with ESMTPS id 2933410EBDA for ; Fri, 7 Jun 2024 11:03:25 +0000 (UTC) Received: from compute7.internal (compute7.nyi.internal [10.202.2.48]) by mailfhigh.west.internal (Postfix) with ESMTP id 1113C180012B; Fri, 7 Jun 2024 07:03:23 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute7.internal (MEProxy); Fri, 07 Jun 2024 07:03:24 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=testtoast.com; h=cc:cc:content-transfer-encoding:content-type:date:date:from :from:in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to; s=fm1; t=1717758202; x= 1717844602; bh=XaQ6cuWms6R8TH2vG68+KYXLzo+BS017qbjak5d9aoY=; b=O u5oTqkOuUcrJEv6SqnBZB88Umq/ikzqu4H8fzxGaxilde5mHXIf0oP3m8h8lj3+b ki+wVOyYH6oxtIicg9B86YZW1evCuZLAHfF48rnDfn5fcCxchKJfmUo9PgHyaEb9 VScMC+6DZf8EdBZoc1s1DQvT1CqgTuFou7rQlaoCA82koxrmj2MlTK/59ur3ri9J Iaq3EjDChzWv7yFL6PiiKkYPgYJSEvUTL8J3EVK5WQAc1/KD7clFyY8vkeDbmoJu nQgHw2aM+2EKYqNFzrn02O5VJm81Re/qsaTyfD+B83Nj7wc+K1JgMDCpySDUQfEu bTySwce3Z5OXMpn/a20NA== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to:x-me-proxy:x-me-proxy :x-me-sender:x-me-sender:x-sasl-enc; s=fm1; t=1717758202; x= 1717844602; bh=XaQ6cuWms6R8TH2vG68+KYXLzo+BS017qbjak5d9aoY=; b=k aBG1h5xNPp8sHDT3osiZ8YbvAx3ud0jMFBI3IgCDQ924t+DY2Of0ouiHsIdRTAVC nRfgczJ1xj1X9th4NUI3f6F+pwEy2gB1UopkZbzyMeMcTNMX+JfDxpvhZMkeyM34 eShI0X2PLOm4+NgXTMEu6QCT39AqdmlCyPi/+VfZy/R7Ixaj7QX0YRH+DNT9frNq Se5JAJPtc8gfdhB4BL29scZ7L9D6vnOzau2gWKgb7cfGV8KupnJRB4OMRgRjEP1s HZJRT3p9P3V+R/yz43W7mOoSxno+YsiKkkOYm8yHDbdSM+W1g04um8XkjfBqLC0k Nu39cczqTZUIhYTT/ZYiA== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvledrfedtuddgudduucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhephffvvefufffkofgjfhgggfestdekredtredttdenucfhrhhomheptfihrghn ucghrghlkhhlihhnuceorhihrghnsehtvghsthhtohgrshhtrdgtohhmqeenucggtffrrg htthgvrhhnpeffheeiffegtdfgffejteevgeefkeelieelkeevueetffetteduffevgeei ieehteenucevlhhushhtvghrufhiiigvpedtnecurfgrrhgrmhepmhgrihhlfhhrohhmpe hrhigrnhesthgvshhtthhorghsthdrtghomh X-ME-Proxy: Feedback-ID: idc0145fc:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Fri, 7 Jun 2024 07:03:15 -0400 (EDT) From: Ryan Walklin To: Maxime Ripard , Chen-Yu Tsai , Maarten Lankhorst , Thomas Zimmermann , David Airlie , Daniel Vetter , Jernej Skrabec , Samuel Holland , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Michael Turquette , Stephen Boyd Cc: Andre Przywara , Chris Morgan , John Watts , dri-devel@lists.freedesktop.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, devicetree@vger.kernel.org, linux-clk@vger.kernel.org, Jernej Skrabec , Ryan Walklin Subject: [PATCH RFC 3/8] drm/sun4i: de2/de3: Merge CSC functions into one Date: Fri, 7 Jun 2024 22:59:59 +1200 Message-ID: <20240607110227.49848-4-ryan@testtoast.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20240607110227.49848-1-ryan@testtoast.com> References: <20240607110227.49848-1-ryan@testtoast.com> 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: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" From: Jernej Skrabec Merging both function into one lets this one decide on it's own if CSC should be enabled or not. Currently heuristics for that is pretty simple - enable it for YUV formats and disable for RGB. However, DE3 can have whole pipeline in RGB or YUV format. YUV pipeline will be supported in later commits. Signed-off-by: Jernej Skrabec Co-developed-by: Ryan Walklin Signed-off-by: Ryan Walklin --- drivers/gpu/drm/sun4i/sun8i_csc.c | 89 ++++++++++---------------- drivers/gpu/drm/sun4i/sun8i_csc.h | 9 ++- drivers/gpu/drm/sun4i/sun8i_vi_layer.c | 11 +--- 3 files changed, 40 insertions(+), 69 deletions(-) diff --git a/drivers/gpu/drm/sun4i/sun8i_csc.c b/drivers/gpu/drm/sun4i/sun8i_csc.c index 6ebd1c3aa3ab5..0dcbc0866ae82 100644 --- a/drivers/gpu/drm/sun4i/sun8i_csc.c +++ b/drivers/gpu/drm/sun4i/sun8i_csc.c @@ -107,23 +107,28 @@ static const u32 yuv2rgb_de3[2][3][12] = { }, }; -static void sun8i_csc_set_coefficients(struct regmap *map, u32 base, - enum format_type fmt_type, - enum drm_color_encoding encoding, - enum drm_color_range range) +static void sun8i_csc_setup(struct regmap *map, u32 base, + enum format_type fmt_type, + enum drm_color_encoding encoding, + enum drm_color_range range) { + u32 base_reg, val; const u32 *table; - u32 base_reg; int i; table = yuv2rgb[range][encoding]; switch (fmt_type) { + case FORMAT_TYPE_RGB: + val = 0; + break; case FORMAT_TYPE_YUV: + val = SUN8I_CSC_CTRL_EN; base_reg = SUN8I_CSC_COEFF(base, 0); regmap_bulk_write(map, base_reg, table, 12); break; case FORMAT_TYPE_YVU: + val = SUN8I_CSC_CTRL_EN; for (i = 0; i < 12; i++) { if ((i & 3) == 1) base_reg = SUN8I_CSC_COEFF(base, i + 1); @@ -135,28 +140,37 @@ static void sun8i_csc_set_coefficients(struct regmap *map, u32 base, } break; default: + val = 0; DRM_WARN("Wrong CSC mode specified.\n"); return; } + + regmap_write(map, SUN8I_CSC_CTRL(base), val); } -static void sun8i_de3_ccsc_set_coefficients(struct regmap *map, int layer, - enum format_type fmt_type, - enum drm_color_encoding encoding, - enum drm_color_range range) +static void sun8i_de3_ccsc_setup(struct regmap *map, int layer, + enum format_type fmt_type, + enum drm_color_encoding encoding, + enum drm_color_range range) { + u32 addr, val, mask; const u32 *table; - u32 addr; int i; + mask = SUN50I_MIXER_BLEND_CSC_CTL_EN(layer); table = yuv2rgb_de3[range][encoding]; switch (fmt_type) { + case FORMAT_TYPE_RGB: + val = 0; + break; case FORMAT_TYPE_YUV: + val = mask; addr = SUN50I_MIXER_BLEND_CSC_COEFF(DE3_BLD_BASE, layer, 0); regmap_bulk_write(map, addr, table, 12); break; case FORMAT_TYPE_YVU: + val = mask; for (i = 0; i < 12; i++) { if ((i & 3) == 1) addr = SUN50I_MIXER_BLEND_CSC_COEFF(DE3_BLD_BASE, @@ -173,67 +187,30 @@ static void sun8i_de3_ccsc_set_coefficients(struct regmap *map, int layer, } break; default: + val = 0; DRM_WARN("Wrong CSC mode specified.\n"); return; } -} - -static void sun8i_csc_enable(struct regmap *map, u32 base, bool enable) -{ - u32 val; - - if (enable) - val = SUN8I_CSC_CTRL_EN; - else - val = 0; - - regmap_update_bits(map, SUN8I_CSC_CTRL(base), SUN8I_CSC_CTRL_EN, val); -} - -static void sun8i_de3_ccsc_enable(struct regmap *map, int layer, bool enable) -{ - u32 val, mask; - - mask = SUN50I_MIXER_BLEND_CSC_CTL_EN(layer); - - if (enable) - val = mask; - else - val = 0; regmap_update_bits(map, SUN50I_MIXER_BLEND_CSC_CTL(DE3_BLD_BASE), mask, val); } -void sun8i_csc_set_ccsc_coefficients(struct sun8i_mixer *mixer, int layer, - enum format_type fmt_type, - enum drm_color_encoding encoding, - enum drm_color_range range) -{ - u32 base; - - if (mixer->cfg->is_de3) { - sun8i_de3_ccsc_set_coefficients(mixer->engine.regs, layer, - fmt_type, encoding, range); - return; - } - - base = ccsc_base[mixer->cfg->ccsc][layer]; - - sun8i_csc_set_coefficients(mixer->engine.regs, base, - fmt_type, encoding, range); -} - -void sun8i_csc_enable_ccsc(struct sun8i_mixer *mixer, int layer, bool enable) +void sun8i_csc_set_ccsc(struct sun8i_mixer *mixer, int layer, + enum format_type fmt_type, + enum drm_color_encoding encoding, + enum drm_color_range range) { u32 base; if (mixer->cfg->is_de3) { - sun8i_de3_ccsc_enable(mixer->engine.regs, layer, enable); + sun8i_de3_ccsc_setup(mixer->engine.regs, layer, + fmt_type, encoding, range); return; } base = ccsc_base[mixer->cfg->ccsc][layer]; - sun8i_csc_enable(mixer->engine.regs, base, enable); + sun8i_csc_setup(mixer->engine.regs, base, + fmt_type, encoding, range); } diff --git a/drivers/gpu/drm/sun4i/sun8i_csc.h b/drivers/gpu/drm/sun4i/sun8i_csc.h index 7322770f39f03..b7546e06e315c 100644 --- a/drivers/gpu/drm/sun4i/sun8i_csc.h +++ b/drivers/gpu/drm/sun4i/sun8i_csc.h @@ -28,10 +28,9 @@ enum format_type { FORMAT_TYPE_YVU, }; -void sun8i_csc_set_ccsc_coefficients(struct sun8i_mixer *mixer, int layer, - enum format_type fmt_type, - enum drm_color_encoding encoding, - enum drm_color_range range); -void sun8i_csc_enable_ccsc(struct sun8i_mixer *mixer, int layer, bool enable); +void sun8i_csc_set_ccsc(struct sun8i_mixer *mixer, int layer, + enum format_type fmt_type, + enum drm_color_encoding encoding, + enum drm_color_range range); #endif diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c index 76e2d3ec0a78c..6ee3790a2a812 100644 --- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c +++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c @@ -281,14 +281,9 @@ static int sun8i_vi_layer_update_formats(struct sun8i_mixer *mixer, int channel, SUN8I_MIXER_CHAN_VI_LAYER_ATTR_FBFMT_MASK, val); fmt_type = sun8i_vi_layer_get_format_type(fmt); - if (fmt_type != FORMAT_TYPE_RGB) { - sun8i_csc_set_ccsc_coefficients(mixer, channel, fmt_type, - state->color_encoding, - state->color_range); - sun8i_csc_enable_ccsc(mixer, channel, true); - } else { - sun8i_csc_enable_ccsc(mixer, channel, false); - } + sun8i_csc_set_ccsc(mixer, channel, fmt_type, + state->color_encoding, + state->color_range); if (!fmt->is_yuv) val = SUN8I_MIXER_CHAN_VI_LAYER_ATTR_RGB_MODE; From patchwork Fri Jun 7 11:00:00 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ryan Walklin X-Patchwork-Id: 13689693 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id E3392C27C55 for ; Fri, 7 Jun 2024 11:03:35 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 0EDCC10EBDB; Fri, 7 Jun 2024 11:03:35 +0000 (UTC) Authentication-Results: gabe.freedesktop.org; dkim=pass (2048-bit key; unprotected) header.d=testtoast.com header.i=@testtoast.com header.b="vOIovY1/"; dkim=pass (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.b="CD/AibnJ"; dkim-atps=neutral Received: from wfhigh3-smtp.messagingengine.com (wfhigh3-smtp.messagingengine.com [64.147.123.154]) by gabe.freedesktop.org (Postfix) with ESMTPS id 088E710EBDB for ; Fri, 7 Jun 2024 11:03:34 +0000 (UTC) Received: from compute4.internal (compute4.nyi.internal [10.202.2.44]) by mailfhigh.west.internal (Postfix) with ESMTP id 18E07180014B; Fri, 7 Jun 2024 07:03:32 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute4.internal (MEProxy); Fri, 07 Jun 2024 07:03:33 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=testtoast.com; h=cc:cc:content-transfer-encoding:content-type:date:date:from :from:in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to; s=fm1; t=1717758211; x= 1717844611; bh=gjHFAumnKJcTZvrMARevkTtJN9PJo4wyCg8SOfOhIB0=; b=v OIovY1/ditJFJcJMhwnz7Cn8Ha5FdZWDBNjFyMJgLbjPJj8/RUK8lG/9MlwmCp2y Eq50L7FHBgkeCoEB6vcJlJyQOJ0zXw4BqO0D/od3R7mmgCCAMSxxR3W53PgRnkHi 9uD4d6Una6qaqtLRlJrtA3NLFYqT6V+exl55Bq59nyfkCBrEyGNqDBOhNIOGJtjq 1UC34qKAd3o9QDzgyd34SlcPWcECRnLWCn3IVNUz7xd4JQhvmyqH22YkMrNbLmgH pOkPcm2+cHBap7mHFg/LHrP8HW6iVhz1QV9tCB7iNLbBLkYtQWVZCVtDzkP0yHlQ MTn5fHCl8m0Q7rZ9XPPWA== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to:x-me-proxy:x-me-proxy :x-me-sender:x-me-sender:x-sasl-enc; s=fm1; t=1717758211; x= 1717844611; bh=gjHFAumnKJcTZvrMARevkTtJN9PJo4wyCg8SOfOhIB0=; b=C D/AibnJ5Hzw93UQnt2nMWXQP2gGHsN4ZbcQ5Si4wUgazfCF9QmvCUaJHPi+oUDbq eNbbj83cJFk5CI6KQyriOEp97ZZXoMTYGd3BYSTugySXzNZnRDwJ5jQkp7DsMTZz oxLv4Mgq/9vZ+Qh+jzNOCJkHW3ugmsffNzc4le/0qyNhUPLRS3+PexkLVI/qftBr eX1GGYATSOA8UE2wgl0ViDNelnfkrbrlntJKUZniEm8ga/xq0YALAc496akJ0C6H 7eIp5FJVXV86nMUcI14t0x2MmvqSTxmqJjP0aXrwe3TNSZKVqOi8fpuChTjcLXqW 2XrqoP2pVAjCRHvzz70pg== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvledrfedtuddgudduucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhephffvvefufffkofgjfhgggfestdekredtredttdenucfhrhhomheptfihrghn ucghrghlkhhlihhnuceorhihrghnsehtvghsthhtohgrshhtrdgtohhmqeenucggtffrrg htthgvrhhnpeffheeiffegtdfgffejteevgeefkeelieelkeevueetffetteduffevgeei ieehteenucevlhhushhtvghrufhiiigvpedtnecurfgrrhgrmhepmhgrihhlfhhrohhmpe hrhigrnhesthgvshhtthhorghsthdrtghomh X-ME-Proxy: Feedback-ID: idc0145fc:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Fri, 7 Jun 2024 07:03:24 -0400 (EDT) From: Ryan Walklin To: Maxime Ripard , Chen-Yu Tsai , Maarten Lankhorst , Thomas Zimmermann , David Airlie , Daniel Vetter , Jernej Skrabec , Samuel Holland , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Michael Turquette , Stephen Boyd Cc: Andre Przywara , Chris Morgan , John Watts , dri-devel@lists.freedesktop.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, devicetree@vger.kernel.org, linux-clk@vger.kernel.org, Jernej Skrabec , Ryan Walklin Subject: [PATCH RFC 4/8] drm/sun4i: de2/de3: call csc setup also for UI layer Date: Fri, 7 Jun 2024 23:00:00 +1200 Message-ID: <20240607110227.49848-5-ryan@testtoast.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20240607110227.49848-1-ryan@testtoast.com> References: <20240607110227.49848-1-ryan@testtoast.com> 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: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" From: Jernej Skrabec Currently, only VI layer calls CSC setup function. This comes from DE2 limitation, which doesn't have CSC unit for UI layers. However, DE3 has separate CSC units for each layer. This allows display pipeline to make output signal in different color spaces. To support both use cases, add a call to CSC setup function also in UI layer code. For DE2, this will be a no-op, but it will allow DE3 to output signal in multiple formats. Signed-off-by: Jernej Skrabec Co-developed-by: Ryan Walklin Signed-off-by: Ryan Walklin --- drivers/gpu/drm/sun4i/sun8i_csc.c | 8 +++++--- drivers/gpu/drm/sun4i/sun8i_ui_layer.c | 6 ++++++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/sun4i/sun8i_csc.c b/drivers/gpu/drm/sun4i/sun8i_csc.c index 0dcbc0866ae82..68d955c63b05b 100644 --- a/drivers/gpu/drm/sun4i/sun8i_csc.c +++ b/drivers/gpu/drm/sun4i/sun8i_csc.c @@ -209,8 +209,10 @@ void sun8i_csc_set_ccsc(struct sun8i_mixer *mixer, int layer, return; } - base = ccsc_base[mixer->cfg->ccsc][layer]; + if (layer < mixer->cfg->vi_num) { + base = ccsc_base[mixer->cfg->ccsc][layer]; - sun8i_csc_setup(mixer->engine.regs, base, - fmt_type, encoding, range); + sun8i_csc_setup(mixer->engine.regs, base, + fmt_type, encoding, range); + } } diff --git a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c index ca75ca0835a63..884abe3cf773a 100644 --- a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c +++ b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c @@ -20,6 +20,7 @@ #include #include +#include "sun8i_csc.h" #include "sun8i_mixer.h" #include "sun8i_ui_layer.h" #include "sun8i_ui_scaler.h" @@ -184,6 +185,11 @@ static int sun8i_ui_layer_update_formats(struct sun8i_mixer *mixer, int channel, SUN8I_MIXER_CHAN_UI_LAYER_ATTR(ch_base, overlay), SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_MASK, val); + /* Note: encoding and range arguments are ignored for RGB */ + sun8i_csc_set_ccsc(mixer, channel, FORMAT_TYPE_RGB, + DRM_COLOR_YCBCR_BT601, + DRM_COLOR_YCBCR_FULL_RANGE); + return 0; } From patchwork Fri Jun 7 11:00:01 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ryan Walklin X-Patchwork-Id: 13689694 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id B7D42C27C53 for ; Fri, 7 Jun 2024 11:03:43 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 0E36610EBDD; Fri, 7 Jun 2024 11:03:43 +0000 (UTC) Authentication-Results: gabe.freedesktop.org; dkim=pass (2048-bit key; unprotected) header.d=testtoast.com header.i=@testtoast.com header.b="MVhQlOdi"; dkim=pass (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.b="Xn8NF316"; dkim-atps=neutral Received: from wfhigh3-smtp.messagingengine.com (wfhigh3-smtp.messagingengine.com [64.147.123.154]) by gabe.freedesktop.org (Postfix) with ESMTPS id 48DAF10EBDC for ; Fri, 7 Jun 2024 11:03:42 +0000 (UTC) Received: from compute5.internal (compute5.nyi.internal [10.202.2.45]) by mailfhigh.west.internal (Postfix) with ESMTP id 673AD1800147; Fri, 7 Jun 2024 07:03:40 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute5.internal (MEProxy); Fri, 07 Jun 2024 07:03:41 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=testtoast.com; h=cc:cc:content-transfer-encoding:content-type:date:date:from :from:in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to; s=fm1; t=1717758220; x= 1717844620; bh=nWXLocCMt7EGKg67iVS/7BHF4d4/LJP7o3vbPwq3pQs=; b=M VhQlOdiOduCbARtTMY6/oLGGl07FCkTXu9PfS91iiOtugXaM6rDxtrqxb46hzTn5 io+N40jYwd6qRVZq4TffxbW0ZMisgyE0JRNctuc9C+imoo7yPKHqjdsltrXyAE/g 5YG+jMQ8yBsu5pL0jXARSPLZwQ+cOjln9f3N/shVUt+n4Tz00a4gubrq69Nc7nLB Imn25mAA4BcnYy+w69MNZpPmrruLgM6X5h7a9zWfujRl/KQxVEn8JvLD44+D9Blp tS7dATqABXrlYXc98i4da2B3i4RBuJVr+zq/V4YyA+h0hbZ5RZGvZkXmAVjaGtej ledd0uuPZ80yVbcmLq7ig== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to:x-me-proxy:x-me-proxy :x-me-sender:x-me-sender:x-sasl-enc; s=fm1; t=1717758220; x= 1717844620; bh=nWXLocCMt7EGKg67iVS/7BHF4d4/LJP7o3vbPwq3pQs=; b=X n8NF316A2olzLw6+CuSBvhkPP4lQlty+gahCsZW5GYs2L750CdDgXy3/+WelKSM8 +7wqvbb9N0Ic23cDRaO+2ViTr5frOFQD+E7MYji7ozbQepyNzXTqgj4kwBCjJTig 6YcuqdkMDTVSiS42fod7Ro42FhgDvq3WqGlNyb4Yriap1wAE2AQTktViKdLWRKaB DxydE/mSAvMpA9zqEM39YErvM+oGW3u34duHbFZRPzMYaMAopjXBZWYBRWMuZDMg kp21/Yj58Q7k1kwVINGGqpCk3lDBOGSJDKOa/g01G+AxWCan9SY+qSq7q2scltWu A+XqSgHgyddrKjgEuzqxQ== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvledrfedtuddgudduucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhephffvvefufffkofgjfhgggfestdekredtredttdenucfhrhhomheptfihrghn ucghrghlkhhlihhnuceorhihrghnsehtvghsthhtohgrshhtrdgtohhmqeenucggtffrrg htthgvrhhnpeffheeiffegtdfgffejteevgeefkeelieelkeevueetffetteduffevgeei ieehteenucevlhhushhtvghrufhiiigvpedtnecurfgrrhgrmhepmhgrihhlfhhrohhmpe hrhigrnhesthgvshhtthhorghsthdrtghomh X-ME-Proxy: Feedback-ID: idc0145fc:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Fri, 7 Jun 2024 07:03:34 -0400 (EDT) From: Ryan Walklin To: Maxime Ripard , Chen-Yu Tsai , Maarten Lankhorst , Thomas Zimmermann , David Airlie , Daniel Vetter , Jernej Skrabec , Samuel Holland , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Michael Turquette , Stephen Boyd Cc: Andre Przywara , Chris Morgan , John Watts , dri-devel@lists.freedesktop.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, devicetree@vger.kernel.org, linux-clk@vger.kernel.org, Ryan Walklin Subject: [PATCH RFC 5/8] drm/sun4i: de2: Initialize layer fields earlier Date: Fri, 7 Jun 2024 23:00:01 +1200 Message-ID: <20240607110227.49848-6-ryan@testtoast.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20240607110227.49848-1-ryan@testtoast.com> References: <20240607110227.49848-1-ryan@testtoast.com> 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: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" From: Jernej Skrabec drm_universal_plane_init() can already call some callbacks, like format_mod_supported, during initialization. Because of that, fields should be initialized beforehand. Signed-off-by: Jernej Skrabec Co-developed-by: Ryan Walklin Signed-off-by: Ryan Walklin --- drivers/gpu/drm/sun4i/sun8i_ui_layer.c | 7 ++++--- drivers/gpu/drm/sun4i/sun8i_vi_layer.c | 7 ++++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c index 884abe3cf773a..91781b5bbbbce 100644 --- a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c +++ b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c @@ -365,6 +365,10 @@ struct sun8i_ui_layer *sun8i_ui_layer_init_one(struct drm_device *drm, if (!layer) return ERR_PTR(-ENOMEM); + layer->mixer = mixer; + layer->channel = channel; + layer->overlay = 0; + if (index == 0) type = DRM_PLANE_TYPE_PRIMARY; @@ -395,9 +399,6 @@ struct sun8i_ui_layer *sun8i_ui_layer_init_one(struct drm_device *drm, } drm_plane_helper_add(&layer->plane, &sun8i_ui_layer_helper_funcs); - layer->mixer = mixer; - layer->channel = channel; - layer->overlay = 0; return layer; } diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c index 6ee3790a2a812..329e8bf8cd20d 100644 --- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c +++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c @@ -549,6 +549,10 @@ struct sun8i_vi_layer *sun8i_vi_layer_init_one(struct drm_device *drm, if (!layer) return ERR_PTR(-ENOMEM); + layer->mixer = mixer; + layer->channel = index; + layer->overlay = 0; + if (mixer->cfg->is_de3) { formats = sun8i_vi_layer_de3_formats; format_count = ARRAY_SIZE(sun8i_vi_layer_de3_formats); @@ -607,9 +611,6 @@ struct sun8i_vi_layer *sun8i_vi_layer_init_one(struct drm_device *drm, } drm_plane_helper_add(&layer->plane, &sun8i_vi_layer_helper_funcs); - layer->mixer = mixer; - layer->channel = index; - layer->overlay = 0; return layer; } From patchwork Fri Jun 7 11:00:02 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ryan Walklin X-Patchwork-Id: 13689695 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 319C7C27C55 for ; Fri, 7 Jun 2024 11:03:53 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 2F86A10EBDC; Fri, 7 Jun 2024 11:03:52 +0000 (UTC) Authentication-Results: gabe.freedesktop.org; dkim=pass (2048-bit key; unprotected) header.d=testtoast.com header.i=@testtoast.com header.b="EjL5HNBK"; dkim=pass (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.b="UWQShfvZ"; dkim-atps=neutral Received: from wfhigh3-smtp.messagingengine.com (wfhigh3-smtp.messagingengine.com [64.147.123.154]) by gabe.freedesktop.org (Postfix) with ESMTPS id C708210EBDC for ; Fri, 7 Jun 2024 11:03:50 +0000 (UTC) Received: from compute4.internal (compute4.nyi.internal [10.202.2.44]) by mailfhigh.west.internal (Postfix) with ESMTP id E77D4180014B; Fri, 7 Jun 2024 07:03:48 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute4.internal (MEProxy); Fri, 07 Jun 2024 07:03:50 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=testtoast.com; h=cc:cc:content-transfer-encoding:content-type:date:date:from :from:in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to; s=fm1; t=1717758228; x= 1717844628; bh=T6w3santYjQtmqpXHrFQ9df4u6xN2IhGzEJMMb5K/dY=; b=E jL5HNBKPTMdnrrKnU2zuX5bqWWg5o4esbZhad3GVkjpEUhf9n7RCHGQu0CvqmFOQ 0rCp6FXh/5pnDVoF/KcrSkdcSx4J7Gx01NNTBg1DeXh7cX9uN+Seid/Eg/1o0SgV 35tG5WO7NYVZnGmc7sg2xFFZT1U6TwZMOi3WlyWkgBaZoyIVKY5aFVH/YWeYPLiz alWz73aIlN6jZO2+yHKSxJfrPpwHj3cD9Tw9W+niVwTPJFVByeCFtgcEmaoNV6N7 zkNmobC0ZlFcGPyooru4vBvkVgja9NEJ2EIAPSZy+6xZAEQK1jFAjqbXZOfwggAj TmuzK3OsyADUakyhntp1Q== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to:x-me-proxy:x-me-proxy :x-me-sender:x-me-sender:x-sasl-enc; s=fm1; t=1717758228; x= 1717844628; bh=T6w3santYjQtmqpXHrFQ9df4u6xN2IhGzEJMMb5K/dY=; b=U WQShfvZZPnCFFak21OzmnaNZ9+KVS7GynG1i9/9lw9zCRya3gI0Ya/NeKu0fn+7k rr/63YwRhTqnGY8NeHRVa9i71mc60ZYnJOkjUfMivWqmd4XHUKlPepvAzlKGl6e8 N18jw2Z0bAnazv9tCDN2JQzBy+j9zuaRKuUF/5JBfaJx6b5wv+uv1uqyhKPkl/uN 2Ae62mW+Att0sXPcYusmepsORW7BJKwcg+oljGafIvZD+VgxUSxC7KPzKsUp8oMA 3M+ENcYGbQaHUH+HTfplZzEpImxMYk308aoAAyFBwf6t3Fy05kqgviQEguvOJkwh nYJf4ipMsFlF/gpS7HUsQ== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvledrfedtuddgudduucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhephffvvefufffkofgjfhgggfestdekredtredttdenucfhrhhomheptfihrghn ucghrghlkhhlihhnuceorhihrghnsehtvghsthhtohgrshhtrdgtohhmqeenucggtffrrg htthgvrhhnpeffheeiffegtdfgffejteevgeefkeelieelkeevueetffetteduffevgeei ieehteenucevlhhushhtvghrufhiiigvpedunecurfgrrhgrmhepmhgrihhlfhhrohhmpe hrhigrnhesthgvshhtthhorghsthdrtghomh X-ME-Proxy: Feedback-ID: idc0145fc:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Fri, 7 Jun 2024 07:03:42 -0400 (EDT) From: Ryan Walklin To: Maxime Ripard , Chen-Yu Tsai , Maarten Lankhorst , Thomas Zimmermann , David Airlie , Daniel Vetter , Jernej Skrabec , Samuel Holland , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Michael Turquette , Stephen Boyd Cc: Andre Przywara , Chris Morgan , John Watts , dri-devel@lists.freedesktop.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, devicetree@vger.kernel.org, linux-clk@vger.kernel.org, Ryan Walklin Subject: [PATCH RFC 6/8] drm/sun4i: de3: Add support for YUV420 output Date: Fri, 7 Jun 2024 23:00:02 +1200 Message-ID: <20240607110227.49848-7-ryan@testtoast.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20240607110227.49848-1-ryan@testtoast.com> References: <20240607110227.49848-1-ryan@testtoast.com> 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: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" Signed-off-by: Jernej Skrabec Co-developed-by: Ryan Walklin Signed-off-by: Ryan Walklin --- drivers/gpu/drm/drm_atomic_state_helper.c | 7 + drivers/gpu/drm/sun4i/Makefile | 3 +- drivers/gpu/drm/sun4i/sun4i_tcon.c | 26 +++- drivers/gpu/drm/sun4i/sun50i_fmt.c | 74 ++++++++++ drivers/gpu/drm/sun4i/sun50i_fmt.h | 30 ++++ drivers/gpu/drm/sun4i/sun8i_csc.c | 172 +++++++++++++++++++++- drivers/gpu/drm/sun4i/sun8i_mixer.c | 52 ++++++- drivers/gpu/drm/sun4i/sun8i_mixer.h | 2 + drivers/gpu/drm/sun4i/sunxi_engine.h | 34 +++++ 9 files changed, 384 insertions(+), 16 deletions(-) create mode 100644 drivers/gpu/drm/sun4i/sun50i_fmt.c create mode 100644 drivers/gpu/drm/sun4i/sun50i_fmt.h diff --git a/drivers/gpu/drm/drm_atomic_state_helper.c b/drivers/gpu/drm/drm_atomic_state_helper.c index 519228eb10953..57e2c4e788303 100644 --- a/drivers/gpu/drm/drm_atomic_state_helper.c +++ b/drivers/gpu/drm/drm_atomic_state_helper.c @@ -430,7 +430,14 @@ void __drm_atomic_helper_connector_state_reset(struct drm_connector_state *conn_state, struct drm_connector *connector) { + struct drm_property *prop; + conn_state->connector = connector; + prop = connector->max_bpc_property; + if (prop) { + conn_state->max_bpc = prop->values[1]; + conn_state->max_requested_bpc = prop->values[1]; + } } EXPORT_SYMBOL(__drm_atomic_helper_connector_state_reset); diff --git a/drivers/gpu/drm/sun4i/Makefile b/drivers/gpu/drm/sun4i/Makefile index bad7497a0d11e..3f516329f51ee 100644 --- a/drivers/gpu/drm/sun4i/Makefile +++ b/drivers/gpu/drm/sun4i/Makefile @@ -16,7 +16,8 @@ sun8i-drm-hdmi-y += sun8i_hdmi_phy_clk.o sun8i-mixer-y += sun8i_mixer.o sun8i_ui_layer.o \ sun8i_vi_layer.o sun8i_ui_scaler.o \ - sun8i_vi_scaler.o sun8i_csc.o + sun8i_vi_scaler.o sun8i_csc.o \ + sun50i_fmt.o sun4i-tcon-y += sun4i_crtc.o sun4i-tcon-y += sun4i_tcon_dclk.o diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c index a1a2c845ade0c..e39926e9f0b5d 100644 --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c @@ -598,14 +598,26 @@ static void sun4i_tcon0_mode_set_rgb(struct sun4i_tcon *tcon, static void sun4i_tcon1_mode_set(struct sun4i_tcon *tcon, const struct drm_display_mode *mode) { - unsigned int bp, hsync, vsync, vtotal; + unsigned int bp, hsync, vsync, vtotal, div; + struct sun4i_crtc *scrtc = tcon->crtc; + struct sunxi_engine *engine = scrtc->engine; u8 clk_delay; u32 val; WARN_ON(!tcon->quirks->has_channel_1); + switch (engine->format) { + case MEDIA_BUS_FMT_UYYVYY8_0_5X24: + case MEDIA_BUS_FMT_UYYVYY10_0_5X30: + div = 2; + break; + default: + div = 1; + break; + } + /* Configure the dot clock */ - clk_set_rate(tcon->sclk1, mode->crtc_clock * 1000); + clk_set_rate(tcon->sclk1, mode->crtc_clock * 1000 / div); /* Adjust clock delay */ clk_delay = sun4i_tcon_get_clk_delay(mode, 1); @@ -624,17 +636,17 @@ static void sun4i_tcon1_mode_set(struct sun4i_tcon *tcon, /* Set the input resolution */ regmap_write(tcon->regs, SUN4I_TCON1_BASIC0_REG, - SUN4I_TCON1_BASIC0_X(mode->crtc_hdisplay) | + SUN4I_TCON1_BASIC0_X(mode->crtc_hdisplay / div) | SUN4I_TCON1_BASIC0_Y(mode->crtc_vdisplay)); /* Set the upscaling resolution */ regmap_write(tcon->regs, SUN4I_TCON1_BASIC1_REG, - SUN4I_TCON1_BASIC1_X(mode->crtc_hdisplay) | + SUN4I_TCON1_BASIC1_X(mode->crtc_hdisplay / div) | SUN4I_TCON1_BASIC1_Y(mode->crtc_vdisplay)); /* Set the output resolution */ regmap_write(tcon->regs, SUN4I_TCON1_BASIC2_REG, - SUN4I_TCON1_BASIC2_X(mode->crtc_hdisplay) | + SUN4I_TCON1_BASIC2_X(mode->crtc_hdisplay / div) | SUN4I_TCON1_BASIC2_Y(mode->crtc_vdisplay)); /* Set horizontal display timings */ @@ -642,8 +654,8 @@ static void sun4i_tcon1_mode_set(struct sun4i_tcon *tcon, DRM_DEBUG_DRIVER("Setting horizontal total %d, backporch %d\n", mode->htotal, bp); regmap_write(tcon->regs, SUN4I_TCON1_BASIC3_REG, - SUN4I_TCON1_BASIC3_H_TOTAL(mode->crtc_htotal) | - SUN4I_TCON1_BASIC3_H_BACKPORCH(bp)); + SUN4I_TCON1_BASIC3_H_TOTAL(mode->crtc_htotal / div) | + SUN4I_TCON1_BASIC3_H_BACKPORCH(bp / div)); bp = mode->crtc_vtotal - mode->crtc_vsync_start; DRM_DEBUG_DRIVER("Setting vertical total %d, backporch %d\n", diff --git a/drivers/gpu/drm/sun4i/sun50i_fmt.c b/drivers/gpu/drm/sun4i/sun50i_fmt.c new file mode 100644 index 0000000000000..18a8d5032ddce --- /dev/null +++ b/drivers/gpu/drm/sun4i/sun50i_fmt.c @@ -0,0 +1,74 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) Jernej Skrabec + */ + +#include + +#include "sun50i_fmt.h" + +static bool sun50i_fmt_is_10bit(u32 format) +{ + switch (format) { + case MEDIA_BUS_FMT_RGB101010_1X30: + case MEDIA_BUS_FMT_YUV10_1X30: + case MEDIA_BUS_FMT_UYYVYY10_0_5X30: + case MEDIA_BUS_FMT_UYVY10_1X20: + return true; + default: + return false; + } +} + +static u32 sun50i_fmt_get_colorspace(u32 format) +{ + switch (format) { + case MEDIA_BUS_FMT_UYYVYY8_0_5X24: + case MEDIA_BUS_FMT_UYYVYY10_0_5X30: + return SUN50I_FMT_CS_YUV420; + case MEDIA_BUS_FMT_UYVY8_1X16: + case MEDIA_BUS_FMT_UYVY10_1X20: + return SUN50I_FMT_CS_YUV422; + default: + return SUN50I_FMT_CS_YUV444RGB; + } +} + +void sun50i_fmt_setup(struct sun8i_mixer *mixer, u16 width, + u16 height, u32 format) +{ + u32 colorspace, limit[3]; + bool bit10; + + colorspace = sun50i_fmt_get_colorspace(format); + bit10 = sun50i_fmt_is_10bit(format); + + regmap_write(mixer->engine.regs, SUN50I_FMT_CTRL, 0); + + regmap_write(mixer->engine.regs, SUN50I_FMT_SIZE, + SUN8I_MIXER_SIZE(width, height)); + regmap_write(mixer->engine.regs, SUN50I_FMT_SWAP, 0); + regmap_write(mixer->engine.regs, SUN50I_FMT_DEPTH, bit10); + regmap_write(mixer->engine.regs, SUN50I_FMT_FORMAT, colorspace); + regmap_write(mixer->engine.regs, SUN50I_FMT_COEF, 0); + + if (colorspace != SUN50I_FMT_CS_YUV444RGB) { + limit[0] = SUN50I_FMT_LIMIT(64, 940); + limit[1] = SUN50I_FMT_LIMIT(64, 960); + limit[2] = SUN50I_FMT_LIMIT(64, 960); + } else if (bit10) { + limit[0] = SUN50I_FMT_LIMIT(0, 1023); + limit[1] = SUN50I_FMT_LIMIT(0, 1023); + limit[2] = SUN50I_FMT_LIMIT(0, 1023); + } else { + limit[0] = SUN50I_FMT_LIMIT(0, 1021); + limit[1] = SUN50I_FMT_LIMIT(0, 1021); + limit[2] = SUN50I_FMT_LIMIT(0, 1021); + } + + regmap_write(mixer->engine.regs, SUN50I_FMT_LMT_Y, limit[0]); + regmap_write(mixer->engine.regs, SUN50I_FMT_LMT_C0, limit[1]); + regmap_write(mixer->engine.regs, SUN50I_FMT_LMT_C1, limit[2]); + + regmap_write(mixer->engine.regs, SUN50I_FMT_CTRL, 1); +} diff --git a/drivers/gpu/drm/sun4i/sun50i_fmt.h b/drivers/gpu/drm/sun4i/sun50i_fmt.h new file mode 100644 index 0000000000000..0fa1d2d22e592 --- /dev/null +++ b/drivers/gpu/drm/sun4i/sun50i_fmt.h @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) Jernej Skrabec + */ + +#ifndef _SUN50I_FMT_H_ +#define _SUN50I_FMT_H_ + +#include "sun8i_mixer.h" + +#define SUN50I_FMT_CTRL 0xa8000 +#define SUN50I_FMT_SIZE 0xa8004 +#define SUN50I_FMT_SWAP 0xa8008 +#define SUN50I_FMT_DEPTH 0xa800c +#define SUN50I_FMT_FORMAT 0xa8010 +#define SUN50I_FMT_COEF 0xa8014 +#define SUN50I_FMT_LMT_Y 0xa8020 +#define SUN50I_FMT_LMT_C0 0xa8024 +#define SUN50I_FMT_LMT_C1 0xa8028 + +#define SUN50I_FMT_LIMIT(low, high) (((high) << 16) | (low)) + +#define SUN50I_FMT_CS_YUV444RGB 0 +#define SUN50I_FMT_CS_YUV422 1 +#define SUN50I_FMT_CS_YUV420 2 + +void sun50i_fmt_setup(struct sun8i_mixer *mixer, u16 width, + u16 height, u32 format); + +#endif diff --git a/drivers/gpu/drm/sun4i/sun8i_csc.c b/drivers/gpu/drm/sun4i/sun8i_csc.c index 68d955c63b05b..3b022bfb85adc 100644 --- a/drivers/gpu/drm/sun4i/sun8i_csc.c +++ b/drivers/gpu/drm/sun4i/sun8i_csc.c @@ -5,6 +5,8 @@ #include +#include + #include "sun8i_csc.h" #include "sun8i_mixer.h" @@ -107,12 +109,141 @@ static const u32 yuv2rgb_de3[2][3][12] = { }, }; +/* always convert to limited mode */ +static const u32 rgb2yuv_de3[3][12] = { + [DRM_COLOR_YCBCR_BT601] = { + 0x0000837A, 0x0001021D, 0x00003221, 0x00000040, + 0xFFFFB41C, 0xFFFF6B03, 0x0000E0E1, 0x00000200, + 0x0000E0E1, 0xFFFF43B1, 0xFFFFDB6E, 0x00000200, + }, + [DRM_COLOR_YCBCR_BT709] = { + 0x00005D7C, 0x00013A7C, 0x00001FBF, 0x00000040, + 0xFFFFCC78, 0xFFFF52A7, 0x0000E0E1, 0x00000200, + 0x0000E0E1, 0xFFFF33BE, 0xFFFFEB61, 0x00000200, + }, + [DRM_COLOR_YCBCR_BT2020] = { + 0x00007384, 0x00012A21, 0x00001A13, 0x00000040, + 0xFFFFC133, 0xFFFF5DEC, 0x0000E0E1, 0x00000200, + 0x0000E0E1, 0xFFFF3135, 0xFFFFEDEA, 0x00000200, + }, +}; + +/* always convert to limited mode */ +static const u32 yuv2yuv_de3[2][3][3][12] = { + [DRM_COLOR_YCBCR_LIMITED_RANGE] = { + [DRM_COLOR_YCBCR_BT601] = { + [DRM_COLOR_YCBCR_BT601] = { + 0x00020000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00020000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00020000, 0x00000000, + }, + [DRM_COLOR_YCBCR_BT709] = { + 0x00020000, 0xFFFFC4D7, 0xFFFF9589, 0xFFC00040, + 0x00000000, 0x0002098B, 0x00003AAF, 0xFE000200, + 0x00000000, 0x0000266D, 0x00020CF8, 0xFE000200, + }, + [DRM_COLOR_YCBCR_BT2020] = { + 0x00020000, 0xFFFFBFCE, 0xFFFFC5FF, 0xFFC00040, + 0x00000000, 0x00020521, 0x00001F89, 0xFE000200, + 0x00000000, 0x00002C87, 0x00020F07, 0xFE000200, + }, + }, + [DRM_COLOR_YCBCR_BT709] = { + [DRM_COLOR_YCBCR_BT601] = { + 0x00020000, 0x000032D9, 0x00006226, 0xFFC00040, + 0x00000000, 0x0001FACE, 0xFFFFC759, 0xFE000200, + 0x00000000, 0xFFFFDAE7, 0x0001F780, 0xFE000200, + }, + [DRM_COLOR_YCBCR_BT709] = { + 0x00020000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00020000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00020000, 0x00000000, + }, + [DRM_COLOR_YCBCR_BT2020] = { + 0x00020000, 0xFFFFF782, 0x00003036, 0xFFC00040, + 0x00000000, 0x0001FD99, 0xFFFFE5CA, 0xFE000200, + 0x00000000, 0x000005E4, 0x0002015A, 0xFE000200, + }, + }, + [DRM_COLOR_YCBCR_BT2020] = { + [DRM_COLOR_YCBCR_BT601] = { + 0x00020000, 0x00003B03, 0x000034D2, 0xFFC00040, + 0x00000000, 0x0001FD8C, 0xFFFFE183, 0xFE000200, + 0x00000000, 0xFFFFD4F3, 0x0001F3FA, 0xFE000200, + }, + [DRM_COLOR_YCBCR_BT709] = { + 0x00020000, 0x00000916, 0xFFFFD061, 0xFFC00040, + 0x00000000, 0x0002021C, 0x00001A40, 0xFE000200, + 0x00000000, 0xFFFFFA19, 0x0001FE5A, 0xFE000200, + }, + [DRM_COLOR_YCBCR_BT2020] = { + 0x00020000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00020000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00020000, 0x00000000, + }, + }, + }, + [DRM_COLOR_YCBCR_FULL_RANGE] = { + [DRM_COLOR_YCBCR_BT601] = { + [DRM_COLOR_YCBCR_BT601] = { + 0x0001B7B8, 0x00000000, 0x00000000, 0x00000040, + 0x00000000, 0x0001C1C2, 0x00000000, 0xFE000200, + 0x00000000, 0x00000000, 0x0001C1C2, 0xFE000200, + }, + [DRM_COLOR_YCBCR_BT709] = { + 0x0001B7B8, 0xFFFFCC08, 0xFFFFA27B, 0x00000040, + 0x00000000, 0x0001CA24, 0x0000338D, 0xFE000200, + 0x00000000, 0x000021C1, 0x0001CD26, 0xFE000200, + }, + [DRM_COLOR_YCBCR_BT2020] = { + 0x0001B7B8, 0xFFFFC79C, 0xFFFFCD0C, 0x00000040, + 0x00000000, 0x0001C643, 0x00001BB4, 0xFE000200, + 0x00000000, 0x0000271D, 0x0001CEF5, 0xFE000200, + }, + }, + [DRM_COLOR_YCBCR_BT709] = { + [DRM_COLOR_YCBCR_BT601] = { + 0x0001B7B8, 0x00002CAB, 0x00005638, 0x00000040, + 0x00000000, 0x0001BD32, 0xFFFFCE3C, 0xFE000200, + 0x00000000, 0xFFFFDF6A, 0x0001BA4A, 0xFE000200, + }, + [DRM_COLOR_YCBCR_BT709] = { + 0x0001B7B8, 0x00000000, 0x00000000, 0x00000040, + 0x00000000, 0x0001C1C2, 0x00000000, 0xFE000200, + 0x00000000, 0x00000000, 0x0001C1C2, 0xFE000200, + }, + [DRM_COLOR_YCBCR_BT2020] = { + 0x0001B7B8, 0xFFFFF88A, 0x00002A5A, 0x00000040, + 0x00000000, 0x0001BFA5, 0xFFFFE8FA, 0xFE000200, + 0x00000000, 0x0000052D, 0x0001C2F1, 0xFE000200, + }, + }, + [DRM_COLOR_YCBCR_BT2020] = { + [DRM_COLOR_YCBCR_BT601] = { + 0x0001B7B8, 0x000033D6, 0x00002E66, 0x00000040, + 0x00000000, 0x0001BF9A, 0xFFFFE538, 0xFE000200, + 0x00000000, 0xFFFFDA2F, 0x0001B732, 0xFE000200, + }, + [DRM_COLOR_YCBCR_BT709] = { + 0x0001B7B8, 0x000007FB, 0xFFFFD62B, 0x00000040, + 0x00000000, 0x0001C39D, 0x0000170F, 0xFE000200, + 0x00000000, 0xFFFFFAD1, 0x0001C04F, 0xFE000200, + }, + [DRM_COLOR_YCBCR_BT2020] = { + 0x0001B7B8, 0x00000000, 0x00000000, 0x00000040, + 0x00000000, 0x0001C1C2, 0x00000000, 0xFE000200, + 0x00000000, 0x00000000, 0x0001C1C2, 0xFE000200, + }, + }, + }, +}; + static void sun8i_csc_setup(struct regmap *map, u32 base, enum format_type fmt_type, enum drm_color_encoding encoding, enum drm_color_range range) { - u32 base_reg, val; + u32 base_reg, val = 0; const u32 *table; int i; @@ -148,28 +279,59 @@ static void sun8i_csc_setup(struct regmap *map, u32 base, regmap_write(map, SUN8I_CSC_CTRL(base), val); } -static void sun8i_de3_ccsc_setup(struct regmap *map, int layer, +static const u32 *sun8i_csc_get_de3_yuv_table(enum drm_color_encoding in_enc, + enum drm_color_range in_range, + u32 out_format, + enum drm_color_encoding out_enc) +{ + if (out_format == MEDIA_BUS_FMT_RGB888_1X24) + return yuv2rgb_de3[in_range][in_enc]; + + /* check for identity transformation */ + if (in_range == DRM_COLOR_YCBCR_LIMITED_RANGE && out_enc == in_enc) + return NULL; + + return yuv2yuv_de3[in_range][in_enc][out_enc]; +} + +static void sun8i_de3_ccsc_setup(struct sunxi_engine *engine, int layer, enum format_type fmt_type, enum drm_color_encoding encoding, enum drm_color_range range) { - u32 addr, val, mask; + u32 addr, val = 0, mask; + struct regmap *map; const u32 *table; int i; mask = SUN50I_MIXER_BLEND_CSC_CTL_EN(layer); table = yuv2rgb_de3[range][encoding]; + map = engine->regs; switch (fmt_type) { case FORMAT_TYPE_RGB: - val = 0; + if (engine->format == MEDIA_BUS_FMT_RGB888_1X24) + break; + val = mask; + addr = SUN50I_MIXER_BLEND_CSC_COEFF(DE3_BLD_BASE, layer, 0); + regmap_bulk_write(map, addr, rgb2yuv_de3[engine->encoding], 12); break; case FORMAT_TYPE_YUV: + table = sun8i_csc_get_de3_yuv_table(encoding, range, + engine->format, + engine->encoding); + if (!table) + break; val = mask; addr = SUN50I_MIXER_BLEND_CSC_COEFF(DE3_BLD_BASE, layer, 0); regmap_bulk_write(map, addr, table, 12); break; case FORMAT_TYPE_YVU: + table = sun8i_csc_get_de3_yuv_table(encoding, range, + engine->format, + engine->encoding); + if (!table) + table = yuv2yuv_de3[range][encoding][encoding]; val = mask; for (i = 0; i < 12; i++) { if ((i & 3) == 1) @@ -204,7 +366,7 @@ void sun8i_csc_set_ccsc(struct sun8i_mixer *mixer, int layer, u32 base; if (mixer->cfg->is_de3) { - sun8i_de3_ccsc_setup(mixer->engine.regs, layer, + sun8i_de3_ccsc_setup(&mixer->engine, layer, fmt_type, encoding, range); return; } diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c index 01382860aaeea..b1525906a25d8 100644 --- a/drivers/gpu/drm/sun4i/sun8i_mixer.c +++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c @@ -22,7 +22,10 @@ #include #include +#include + #include "sun4i_drv.h" +#include "sun50i_fmt.h" #include "sun8i_mixer.h" #include "sun8i_ui_layer.h" #include "sun8i_vi_layer.h" @@ -326,12 +329,52 @@ static void sun8i_mixer_mode_set(struct sunxi_engine *engine, DRM_DEBUG_DRIVER("Switching display mixer interlaced mode %s\n", interlaced ? "on" : "off"); + + if (engine->format == MEDIA_BUS_FMT_RGB888_1X24) + val = SUN8I_MIXER_BLEND_COLOR_BLACK; + else + val = 0xff108080; + + regmap_write(mixer->engine.regs, + SUN8I_MIXER_BLEND_BKCOLOR(bld_base), val); + regmap_write(mixer->engine.regs, + SUN8I_MIXER_BLEND_ATTR_FCOLOR(bld_base, 0), val); + + if (mixer->cfg->has_formatter) + sun50i_fmt_setup(mixer, mode->hdisplay, + mode->vdisplay, mixer->engine.format); +} + +static u32 *sun8i_mixer_get_supported_fmts(struct sunxi_engine *engine, u32 *num) +{ + struct sun8i_mixer *mixer = engine_to_sun8i_mixer(engine); + u32 *formats, count; + + count = 0; + + formats = kcalloc(5, sizeof(*formats), GFP_KERNEL); + if (!formats) + return NULL; + + if (mixer->cfg->has_formatter) { + formats[count++] = MEDIA_BUS_FMT_UYYVYY10_0_5X30; + formats[count++] = MEDIA_BUS_FMT_YUV8_1X24; + formats[count++] = MEDIA_BUS_FMT_UYVY8_1X16; + formats[count++] = MEDIA_BUS_FMT_UYYVYY8_0_5X24; + } + + formats[count++] = MEDIA_BUS_FMT_RGB888_1X24; + + *num = count; + + return formats; } static const struct sunxi_engine_ops sun8i_engine_ops = { - .commit = sun8i_mixer_commit, - .layers_init = sun8i_layers_init, - .mode_set = sun8i_mixer_mode_set, + .commit = sun8i_mixer_commit, + .layers_init = sun8i_layers_init, + .mode_set = sun8i_mixer_mode_set, + .get_supported_fmts = sun8i_mixer_get_supported_fmts, }; static const struct regmap_config sun8i_mixer_regmap_config = { @@ -392,6 +435,8 @@ static int sun8i_mixer_bind(struct device *dev, struct device *master, dev_set_drvdata(dev, mixer); mixer->engine.ops = &sun8i_engine_ops; mixer->engine.node = dev->of_node; + /* default output format, supported by all mixers */ + mixer->engine.format = MEDIA_BUS_FMT_RGB888_1X24; if (of_property_present(dev->of_node, "iommus")) { /* @@ -653,6 +698,7 @@ static const struct sun8i_mixer_cfg sun50i_a64_mixer1_cfg = { static const struct sun8i_mixer_cfg sun50i_h6_mixer0_cfg = { .ccsc = CCSC_MIXER0_LAYOUT, .is_de3 = true, + .has_formatter = 1, .mod_rate = 600000000, .scaler_mask = 0xf, .scanline_yuv = 4096, diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.h b/drivers/gpu/drm/sun4i/sun8i_mixer.h index 85c94884fb9a4..13401643c7bfc 100644 --- a/drivers/gpu/drm/sun4i/sun8i_mixer.h +++ b/drivers/gpu/drm/sun4i/sun8i_mixer.h @@ -162,6 +162,7 @@ enum { * @mod_rate: module clock rate that needs to be set in order to have * a functional block. * @is_de3: true, if this is next gen display engine 3.0, false otherwise. + * @has_formatter: true, if mixer has formatter core, for 10-bit and YUV handling * @scaline_yuv: size of a scanline for VI scaler for YUV formats. */ struct sun8i_mixer_cfg { @@ -171,6 +172,7 @@ struct sun8i_mixer_cfg { int ccsc; unsigned long mod_rate; unsigned int is_de3 : 1; + unsigned int has_formatter : 1; unsigned int scanline_yuv; }; diff --git a/drivers/gpu/drm/sun4i/sunxi_engine.h b/drivers/gpu/drm/sun4i/sunxi_engine.h index ec8cf9b2bda41..608a26c3f9911 100644 --- a/drivers/gpu/drm/sun4i/sunxi_engine.h +++ b/drivers/gpu/drm/sun4i/sunxi_engine.h @@ -6,6 +6,8 @@ #ifndef _SUNXI_ENGINE_H_ #define _SUNXI_ENGINE_H_ +#include + struct drm_plane; struct drm_device; struct drm_crtc_state; @@ -120,6 +122,17 @@ struct sunxi_engine_ops { */ void (*mode_set)(struct sunxi_engine *engine, const struct drm_display_mode *mode); + + /** + * @get_supported_fmts + * + * This callback is used to enumerate all supported output + * formats by the engine. They are used for bridge format + * negotiation. + * + * This function is optional. + */ + u32 *(*get_supported_fmts)(struct sunxi_engine *engine, u32 *num); }; /** @@ -137,6 +150,9 @@ struct sunxi_engine { int id; + u32 format; + enum drm_color_encoding encoding; + /* Engine list management */ struct list_head list; }; @@ -208,4 +224,22 @@ sunxi_engine_mode_set(struct sunxi_engine *engine, if (engine->ops && engine->ops->mode_set) engine->ops->mode_set(engine, mode); } + +/** + * sunxi_engine_get_supported_formats - Provide array of supported formats + * @engine: pointer to the engine + * @num: pointer to variable, which will hold number of formats + * + * This list can be used for format negotiation by bridge. + */ +static inline u32 * +sunxi_engine_get_supported_formats(struct sunxi_engine *engine, u32 *num) +{ + if (engine->ops && engine->ops->get_supported_fmts) + return engine->ops->get_supported_fmts(engine, num); + + *num = 0; + + return NULL; +} #endif /* _SUNXI_ENGINE_H_ */ From patchwork Fri Jun 7 11:00:03 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ryan Walklin X-Patchwork-Id: 13689696 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 369F5C27C53 for ; Fri, 7 Jun 2024 11:04:01 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 5701810EBDE; Fri, 7 Jun 2024 11:04:00 +0000 (UTC) Authentication-Results: gabe.freedesktop.org; dkim=pass (2048-bit key; unprotected) header.d=testtoast.com header.i=@testtoast.com header.b="eV0VTOWO"; dkim=pass (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.b="ApSWeHOJ"; dkim-atps=neutral Received: from wfhigh3-smtp.messagingengine.com (wfhigh3-smtp.messagingengine.com [64.147.123.154]) by gabe.freedesktop.org (Postfix) with ESMTPS id 7724110EBDE for ; Fri, 7 Jun 2024 11:03:59 +0000 (UTC) Received: from compute1.internal (compute1.nyi.internal [10.202.2.41]) by mailfhigh.west.internal (Postfix) with ESMTP id 859D118000E8; Fri, 7 Jun 2024 07:03:57 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute1.internal (MEProxy); Fri, 07 Jun 2024 07:03:59 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=testtoast.com; h=cc:cc:content-transfer-encoding:content-type:date:date:from :from:in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to; s=fm1; t=1717758237; x= 1717844637; bh=qaDvV8/06/8ZVQ7R8AFDWWFJiwBPHK46CFq39AZ6C0w=; b=e V0VTOWOem6Uaic0Nb+T7N+DtkWGKsHqjtX5zDovddqjTnIMrmrYrHBqHVMp00plQ Y+yTdYImovAwlW5g/S3K0bWQoKlsAhPTiJQaKViI2Rm8KuKIKAmUg/envV3QaA5T JRjIlz+0psdh6qSkaV2qUv6DwNJ7K7gEtCBvl07gW6Mm7LnZDRU2Doqt9wfMQCzn 0Qpzouq67DQ337241CpqcUt3yVy9sTg8hpetfoAq60XBrispBVg3vqZ7ykPAAzyE zdQMyVhPWugEjsBxrWbTTdn2BJoiGO6r4TmXBvCg0zutuTiCFkQlMtiMXwFXgBgQ zBQLGOcewCA653PfoeIIA== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to:x-me-proxy:x-me-proxy :x-me-sender:x-me-sender:x-sasl-enc; s=fm1; t=1717758237; x= 1717844637; bh=qaDvV8/06/8ZVQ7R8AFDWWFJiwBPHK46CFq39AZ6C0w=; b=A pSWeHOJdTkmZkIuphFtMHdplBJozxSOrAPM3Zwuc9p/BtutTugJ8XeFuF6OdFr3I 1B9cLENduVVxYwCP9cf/CEh2K6xvJjUulIdebYnPewZKzl6Eli/TvjXBZ+Wkyd70 H8yxO7NdlnAkP5AvR+FDGvoBKgC3ygAzK0idnvECcsbo4Vt3arnn0ZF8sHgd6mFb +aqswxVJX3YSs1Ie/nIELYXvisFKoj73B5NxCoUsEeXxICw/Ok+PHlKtyHSQ4Vav Vf7dUIkqYtrBOc3aqSD7912R3Df/OrDuGTiFHgTwLVCL3mvj4EBrDvptIxFFUjl3 uZLl3+sAVQdLE8MJzDFMA== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvledrfedtuddgudduucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhephffvvefufffkofgjfhgggfestdekredtredttdenucfhrhhomheptfihrghn ucghrghlkhhlihhnuceorhihrghnsehtvghsthhtohgrshhtrdgtohhmqeenucggtffrrg htthgvrhhnpeffheeiffegtdfgffejteevgeefkeelieelkeevueetffetteduffevgeei ieehteenucevlhhushhtvghrufhiiigvpedunecurfgrrhgrmhepmhgrihhlfhhrohhmpe hrhigrnhesthgvshhtthhorghsthdrtghomh X-ME-Proxy: Feedback-ID: idc0145fc:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Fri, 7 Jun 2024 07:03:50 -0400 (EDT) From: Ryan Walklin To: Maxime Ripard , Chen-Yu Tsai , Maarten Lankhorst , Thomas Zimmermann , David Airlie , Daniel Vetter , Jernej Skrabec , Samuel Holland , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Michael Turquette , Stephen Boyd Cc: Andre Przywara , Chris Morgan , John Watts , dri-devel@lists.freedesktop.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, devicetree@vger.kernel.org, linux-clk@vger.kernel.org, Ryan Walklin Subject: [PATCH RFC 7/8] drm/sun4i: de3: Implement AFBC support Date: Fri, 7 Jun 2024 23:00:03 +1200 Message-ID: <20240607110227.49848-8-ryan@testtoast.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20240607110227.49848-1-ryan@testtoast.com> References: <20240607110227.49848-1-ryan@testtoast.com> 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: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" Buffers, compressed with AFBC, are generally more efficient for memory transfers. Add support for them. Currently it's implemented only for VI layers, but vendor code and documentation suggest UI layers can have them too. However, I haven't observed any SoC with such feature. Signed-off-by: Jernej Skrabec Co-developed-by: Ryan Walklin Signed-off-by: Ryan Walklin --- drivers/gpu/drm/sun4i/Makefile | 2 +- drivers/gpu/drm/sun4i/sun50i_afbc.c | 240 +++++++++++++++++++++++++ drivers/gpu/drm/sun4i/sun50i_afbc.h | 87 +++++++++ drivers/gpu/drm/sun4i/sun8i_vi_layer.c | 84 +++++++-- 4 files changed, 400 insertions(+), 13 deletions(-) create mode 100644 drivers/gpu/drm/sun4i/sun50i_afbc.c create mode 100644 drivers/gpu/drm/sun4i/sun50i_afbc.h diff --git a/drivers/gpu/drm/sun4i/Makefile b/drivers/gpu/drm/sun4i/Makefile index 3f516329f51ee..78290f1660fbd 100644 --- a/drivers/gpu/drm/sun4i/Makefile +++ b/drivers/gpu/drm/sun4i/Makefile @@ -17,7 +17,7 @@ sun8i-drm-hdmi-y += sun8i_hdmi_phy_clk.o sun8i-mixer-y += sun8i_mixer.o sun8i_ui_layer.o \ sun8i_vi_layer.o sun8i_ui_scaler.o \ sun8i_vi_scaler.o sun8i_csc.o \ - sun50i_fmt.o + sun50i_fmt.o sun50i_afbc.o sun4i-tcon-y += sun4i_crtc.o sun4i-tcon-y += sun4i_tcon_dclk.o diff --git a/drivers/gpu/drm/sun4i/sun50i_afbc.c b/drivers/gpu/drm/sun4i/sun50i_afbc.c new file mode 100644 index 0000000000000..27a771608eef8 --- /dev/null +++ b/drivers/gpu/drm/sun4i/sun50i_afbc.c @@ -0,0 +1,240 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) Jernej Skrabec + */ + +#include +#include +#include +#include +#include +#include + +#include "sun50i_afbc.h" +#include "sun8i_mixer.h" + +bool sun50i_afbc_format_mod_supported(struct sun8i_mixer *mixer, + u32 format, u64 modifier) +{ + u64 mode; + + if (modifier == DRM_FORMAT_MOD_INVALID) + return false; + + if (modifier == DRM_FORMAT_MOD_LINEAR) { + if (format == DRM_FORMAT_YUV420_8BIT || + format == DRM_FORMAT_YUV420_10BIT || + format == DRM_FORMAT_Y210) + return false; + return true; + } + + if (!mixer->cfg->is_de3) + return false; + + mode = AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 | + AFBC_FORMAT_MOD_SPARSE | + AFBC_FORMAT_MOD_SPLIT; + + switch (format) { + case DRM_FORMAT_RGBA8888: + case DRM_FORMAT_RGB888: + case DRM_FORMAT_RGB565: + case DRM_FORMAT_RGBA4444: + case DRM_FORMAT_RGBA5551: + case DRM_FORMAT_RGBA1010102: + mode |= AFBC_FORMAT_MOD_YTR; + break; + case DRM_FORMAT_YUYV: + case DRM_FORMAT_Y210: + case DRM_FORMAT_YUV420_8BIT: + case DRM_FORMAT_YUV420_10BIT: + break; + default: + return false; + } + + return modifier == DRM_FORMAT_MOD_ARM_AFBC(mode); +} + +void sun50i_afbc_atomic_update(struct sun8i_mixer *mixer, unsigned int channel, + struct drm_plane *plane) +{ + struct drm_plane_state *state = plane->state; + struct drm_framebuffer *fb = state->fb; + const struct drm_format_info *format = fb->format; + struct drm_gem_dma_object *gem; + u32 base, val, src_w, src_h; + u32 def_color0, def_color1; + struct regmap *regs; + dma_addr_t dma_addr; + + base = sun8i_channel_base(mixer, channel) + SUN50I_AFBC_CH_OFFSET; + regs = mixer->engine.regs; + + src_w = drm_rect_width(&state->src) >> 16; + src_h = drm_rect_height(&state->src) >> 16; + + val = SUN50I_FBD_SIZE_HEIGHT(src_h); + val |= SUN50I_FBD_SIZE_WIDTH(src_w); + regmap_write(regs, SUN50I_FBD_SIZE(base), val); + + val = SUN50I_FBD_BLK_SIZE_HEIGHT(DIV_ROUND_UP(src_h, 16)); + val = SUN50I_FBD_BLK_SIZE_WIDTH(DIV_ROUND_UP(src_w, 16)); + regmap_write(regs, SUN50I_FBD_BLK_SIZE(base), val); + + val = SUN50I_FBD_SRC_CROP_TOP(0); + val |= SUN50I_FBD_SRC_CROP_LEFT(0); + regmap_write(regs, SUN50I_FBD_SRC_CROP(base), val); + + val = SUN50I_FBD_LAY_CROP_TOP(state->src.y1 >> 16); + val |= SUN50I_FBD_LAY_CROP_LEFT(state->src.x1 >> 16); + regmap_write(regs, SUN50I_FBD_LAY_CROP(base), val); + + /* + * Default color is always set to white, in colorspace and bitness + * that coresponds to used format. If it is actually used or not + * depends on AFBC buffer. At least in Cedrus it can be turned on + * or off. + * NOTE: G and B channels are off by 1 (up). It's unclear if this + * is because HW need such value or it is due to good enough code + * in vendor driver and HW clips the value anyway. + */ + def_color0 = 0; + def_color1 = 0; + + val = 0; + switch (format->format) { + case DRM_FORMAT_YUYV: + case DRM_FORMAT_YUV420_10BIT: + val |= SUN50I_FBD_FMT_SBS1(2); + val |= SUN50I_FBD_FMT_SBS0(1); + break; + case DRM_FORMAT_Y210: + val |= SUN50I_FBD_FMT_SBS1(3); + val |= SUN50I_FBD_FMT_SBS0(2); + break; + default: + val |= SUN50I_FBD_FMT_SBS1(1); + val |= SUN50I_FBD_FMT_SBS0(1); + break; + } + switch (format->format) { + case DRM_FORMAT_RGBA8888: + val |= SUN50I_FBD_FMT_YUV_TRAN; + val |= SUN50I_FBD_FMT_IN_FMT(SUN50I_AFBC_RGBA_8888); + def_color0 = SUN50I_FBD_DEFAULT_COLOR0_ALPHA(255) | + SUN50I_FBD_DEFAULT_COLOR0_YR(255); + def_color1 = SUN50I_FBD_DEFAULT_COLOR1_UG(256) | + SUN50I_FBD_DEFAULT_COLOR1_VB(256); + break; + case DRM_FORMAT_RGB888: + val |= SUN50I_FBD_FMT_YUV_TRAN; + val |= SUN50I_FBD_FMT_IN_FMT(SUN50I_AFBC_RGB_888); + def_color0 = SUN50I_FBD_DEFAULT_COLOR0_ALPHA(0) | + SUN50I_FBD_DEFAULT_COLOR0_YR(255); + def_color1 = SUN50I_FBD_DEFAULT_COLOR1_UG(256) | + SUN50I_FBD_DEFAULT_COLOR1_VB(256); + break; + case DRM_FORMAT_RGB565: + val |= SUN50I_FBD_FMT_YUV_TRAN; + val |= SUN50I_FBD_FMT_IN_FMT(SUN50I_AFBC_RGB_565); + def_color0 = SUN50I_FBD_DEFAULT_COLOR0_ALPHA(0) | + SUN50I_FBD_DEFAULT_COLOR0_YR(31); + def_color1 = SUN50I_FBD_DEFAULT_COLOR1_UG(64) | + SUN50I_FBD_DEFAULT_COLOR1_VB(32); + break; + case DRM_FORMAT_RGBA4444: + val |= SUN50I_FBD_FMT_YUV_TRAN; + val |= SUN50I_FBD_FMT_IN_FMT(SUN50I_AFBC_RGBA_4444); + def_color0 = SUN50I_FBD_DEFAULT_COLOR0_ALPHA(15) | + SUN50I_FBD_DEFAULT_COLOR0_YR(15); + def_color1 = SUN50I_FBD_DEFAULT_COLOR1_UG(16) | + SUN50I_FBD_DEFAULT_COLOR1_VB(16); + break; + case DRM_FORMAT_RGBA5551: + val |= SUN50I_FBD_FMT_YUV_TRAN; + val |= SUN50I_FBD_FMT_IN_FMT(SUN50I_AFBC_RGBA_5551); + def_color0 = SUN50I_FBD_DEFAULT_COLOR0_ALPHA(1) | + SUN50I_FBD_DEFAULT_COLOR0_YR(31); + def_color1 = SUN50I_FBD_DEFAULT_COLOR1_UG(32) | + SUN50I_FBD_DEFAULT_COLOR1_VB(32); + break; + case DRM_FORMAT_RGBA1010102: + val |= SUN50I_FBD_FMT_YUV_TRAN; + val |= SUN50I_FBD_FMT_IN_FMT(SUN50I_AFBC_RGBA1010102); + def_color0 = SUN50I_FBD_DEFAULT_COLOR0_ALPHA(3) | + SUN50I_FBD_DEFAULT_COLOR0_YR(1023); + def_color1 = SUN50I_FBD_DEFAULT_COLOR1_UG(1024) | + SUN50I_FBD_DEFAULT_COLOR1_VB(1024); + break; + case DRM_FORMAT_YUV420_8BIT: + val |= SUN50I_FBD_FMT_IN_FMT(SUN50I_AFBC_YUV420); + def_color0 = SUN50I_FBD_DEFAULT_COLOR0_ALPHA(0) | + SUN50I_FBD_DEFAULT_COLOR0_YR(255); + def_color1 = SUN50I_FBD_DEFAULT_COLOR1_UG(128) | + SUN50I_FBD_DEFAULT_COLOR1_VB(128); + break; + case DRM_FORMAT_YUYV: + val |= SUN50I_FBD_FMT_IN_FMT(SUN50I_AFBC_YUV422); + def_color0 = SUN50I_FBD_DEFAULT_COLOR0_ALPHA(0) | + SUN50I_FBD_DEFAULT_COLOR0_YR(255); + def_color1 = SUN50I_FBD_DEFAULT_COLOR1_UG(128) | + SUN50I_FBD_DEFAULT_COLOR1_VB(128); + break; + case DRM_FORMAT_YUV420_10BIT: + val |= SUN50I_FBD_FMT_IN_FMT(SUN50I_AFBC_P010); + def_color0 = SUN50I_FBD_DEFAULT_COLOR0_ALPHA(0) | + SUN50I_FBD_DEFAULT_COLOR0_YR(1023); + def_color1 = SUN50I_FBD_DEFAULT_COLOR1_UG(512) | + SUN50I_FBD_DEFAULT_COLOR1_VB(512); + break; + case DRM_FORMAT_Y210: + val |= SUN50I_FBD_FMT_IN_FMT(SUN50I_AFBC_P210); + def_color0 = SUN50I_FBD_DEFAULT_COLOR0_ALPHA(0) | + SUN50I_FBD_DEFAULT_COLOR0_YR(1023); + def_color1 = SUN50I_FBD_DEFAULT_COLOR1_UG(512) | + SUN50I_FBD_DEFAULT_COLOR1_VB(512); + break; + } + regmap_write(regs, SUN50I_FBD_FMT(base), val); + + /* Get the physical address of the buffer in memory */ + gem = drm_fb_dma_get_gem_obj(fb, 0); + + DRM_DEBUG_DRIVER("Using GEM @ %pad\n", &gem->dma_addr); + + /* Compute the start of the displayed memory */ + dma_addr = gem->dma_addr + fb->offsets[0]; + + regmap_write(regs, SUN50I_FBD_LADDR(base), lower_32_bits(dma_addr)); + regmap_write(regs, SUN50I_FBD_HADDR(base), upper_32_bits(dma_addr)); + + val = SUN50I_FBD_OVL_SIZE_HEIGHT(src_h); + val |= SUN50I_FBD_OVL_SIZE_WIDTH(src_w); + regmap_write(regs, SUN50I_FBD_OVL_SIZE(base), val); + + val = SUN50I_FBD_OVL_COOR_Y(0); + val |= SUN50I_FBD_OVL_COOR_X(0); + regmap_write(regs, SUN50I_FBD_OVL_COOR(base), val); + + regmap_write(regs, SUN50I_FBD_OVL_BG_COLOR(base), + SUN8I_MIXER_BLEND_COLOR_BLACK); + regmap_write(regs, SUN50I_FBD_DEFAULT_COLOR0(base), def_color0); + regmap_write(regs, SUN50I_FBD_DEFAULT_COLOR1(base), def_color1); + + val = SUN50I_FBD_CTL_GLB_ALPHA(state->alpha >> 16); + val |= SUN50I_FBD_CTL_CLK_GATE; + val |= (state->alpha == DRM_BLEND_ALPHA_OPAQUE) ? + SUN50I_FBD_CTL_ALPHA_MODE_PIXEL : + SUN50I_FBD_CTL_ALPHA_MODE_COMBINED; + val |= SUN50I_FBD_CTL_FBD_EN; + regmap_write(regs, SUN50I_FBD_CTL(base), val); +} + +void sun50i_afbc_disable(struct sun8i_mixer *mixer, unsigned int channel) +{ + u32 base = sun8i_channel_base(mixer, channel) + SUN50I_AFBC_CH_OFFSET; + + regmap_write(mixer->engine.regs, SUN50I_FBD_CTL(base), 0); +} diff --git a/drivers/gpu/drm/sun4i/sun50i_afbc.h b/drivers/gpu/drm/sun4i/sun50i_afbc.h new file mode 100644 index 0000000000000..cea685c868550 --- /dev/null +++ b/drivers/gpu/drm/sun4i/sun50i_afbc.h @@ -0,0 +1,87 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) Jernej Skrabec + */ + +#ifndef _SUN50I_AFBC_H_ +#define _SUN50I_AFBC_H_ + +#include + +#define SUN50I_AFBC_CH_OFFSET 0x300 + +#define SUN50I_AFBC_RGBA_8888 0x02 +#define SUN50I_AFBC_RGB_888 0x08 +#define SUN50I_AFBC_RGB_565 0x0a +#define SUN50I_AFBC_RGBA_4444 0x0e +#define SUN50I_AFBC_RGBA_5551 0x12 +#define SUN50I_AFBC_RGBA1010102 0x16 +#define SUN50I_AFBC_YUV422 0x26 +#define SUN50I_AFBC_YUV420 0x2a +#define SUN50I_AFBC_P010 0x30 +#define SUN50I_AFBC_P210 0x32 + +#define SUN50I_FBD_CTL(base) ((base) + 0x00) +#define SUN50I_FBD_CTL_GLB_ALPHA(v) ((v) << 24) +#define SUN50I_FBD_CTL_CLK_GATE BIT(4) +#define SUN50I_FBD_CTL_ALPHA_MODE_PIXEL ((0) << 2) +#define SUN50I_FBD_CTL_ALPHA_MODE_LAYER ((1) << 2) +#define SUN50I_FBD_CTL_ALPHA_MODE_COMBINED ((2) << 2) +#define SUN50I_FBD_CTL_FBD_FCEN BIT(1) +#define SUN50I_FBD_CTL_FBD_EN BIT(0) + +#define SUN50I_FBD_SIZE(base) ((base) + 0x08) +#define SUN50I_FBD_SIZE_HEIGHT(v) (((v) - 1) << 16) +#define SUN50I_FBD_SIZE_WIDTH(v) (((v) - 1) << 0) + +#define SUN50I_FBD_BLK_SIZE(base) ((base) + 0x0c) +#define SUN50I_FBD_BLK_SIZE_HEIGHT(v) ((v) << 16) +#define SUN50I_FBD_BLK_SIZE_WIDTH(v) ((v) << 0) + +#define SUN50I_FBD_SRC_CROP(base) ((base) + 0x10) +#define SUN50I_FBD_SRC_CROP_TOP(v) ((v) << 16) +#define SUN50I_FBD_SRC_CROP_LEFT(v) ((v) << 0) + +#define SUN50I_FBD_LAY_CROP(base) ((base) + 0x14) +#define SUN50I_FBD_LAY_CROP_TOP(v) ((v) << 16) +#define SUN50I_FBD_LAY_CROP_LEFT(v) ((v) << 0) + +#define SUN50I_FBD_FMT(base) ((base) + 0x18) +#define SUN50I_FBD_FMT_SBS1(v) ((v) << 18) +#define SUN50I_FBD_FMT_SBS0(v) ((v) << 16) +#define SUN50I_FBD_FMT_YUV_TRAN BIT(7) +#define SUN50I_FBD_FMT_IN_FMT(v) ((v) << 0) + +#define SUN50I_FBD_LADDR(base) ((base) + 0x20) +#define SUN50I_FBD_HADDR(base) ((base) + 0x24) + +#define SUN50I_FBD_OVL_SIZE(base) ((base) + 0x30) +#define SUN50I_FBD_OVL_SIZE_HEIGHT(v) (((v) - 1) << 16) +#define SUN50I_FBD_OVL_SIZE_WIDTH(v) (((v) - 1) << 0) + +#define SUN50I_FBD_OVL_COOR(base) ((base) + 0x34) +#define SUN50I_FBD_OVL_COOR_Y(v) ((v) << 16) +#define SUN50I_FBD_OVL_COOR_X(v) ((v) << 0) + +#define SUN50I_FBD_OVL_BG_COLOR(base) ((base) + 0x38) +#define SUN50I_FBD_OVL_FILL_COLOR(base) ((base) + 0x3c) + +#define SUN50I_FBD_DEFAULT_COLOR0(base) ((base) + 0x50) +#define SUN50I_FBD_DEFAULT_COLOR0_ALPHA(v) ((v) << 16) +#define SUN50I_FBD_DEFAULT_COLOR0_YR(v) ((v) << 0) + +#define SUN50I_FBD_DEFAULT_COLOR1(base) ((base) + 0x54) +#define SUN50I_FBD_DEFAULT_COLOR1_VB(v) ((v) << 16) +#define SUN50I_FBD_DEFAULT_COLOR1_UG(v) ((v) << 0) + +struct sun8i_mixer; +struct drm_plane; + +bool sun50i_afbc_format_mod_supported(struct sun8i_mixer *mixer, + u32 format, u64 modifier); + +void sun50i_afbc_atomic_update(struct sun8i_mixer *mixer, unsigned int channel, + struct drm_plane *plane); +void sun50i_afbc_disable(struct sun8i_mixer *mixer, unsigned int channel); + +#endif diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c index 329e8bf8cd20d..bda91c3e2bb75 100644 --- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c +++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c @@ -11,8 +11,10 @@ #include #include #include +#include #include +#include "sun50i_afbc.h" #include "sun8i_csc.h" #include "sun8i_mixer.h" #include "sun8i_vi_layer.h" @@ -99,7 +101,7 @@ static void sun8i_vi_layer_update_alpha(struct sun8i_mixer *mixer, int channel, static int sun8i_vi_layer_update_coord(struct sun8i_mixer *mixer, int channel, int overlay, struct drm_plane *plane, - unsigned int zpos) + unsigned int zpos, bool afbc) { struct drm_plane_state *state = plane->state; const struct drm_format_info *format = state->fb->format; @@ -182,7 +184,7 @@ static int sun8i_vi_layer_update_coord(struct sun8i_mixer *mixer, int channel, required = src_h * 100 / dst_h; - if (ability < required) { + if (!afbc && ability < required) { DRM_DEBUG_DRIVER("Using vertical coarse scaling\n"); vm = src_h; vn = (u32)ability * dst_h / 100; @@ -192,7 +194,7 @@ static int sun8i_vi_layer_update_coord(struct sun8i_mixer *mixer, int channel, /* it seems that every RGB scaler has buffer for 2048 pixels */ scanline = subsampled ? mixer->cfg->scanline_yuv : 2048; - if (src_w > scanline) { + if (!afbc && src_w > scanline) { DRM_DEBUG_DRIVER("Using horizontal coarse scaling\n"); hm = src_w; hn = scanline; @@ -356,6 +358,15 @@ static int sun8i_vi_layer_update_buffer(struct sun8i_mixer *mixer, int channel, return 0; } +static void sun8i_vi_layer_prepare_non_linear(struct sun8i_mixer *mixer, + int channel, int overlay) +{ + u32 base = sun8i_channel_base(mixer, channel); + + regmap_write(mixer->engine.regs, + SUN8I_MIXER_CHAN_VI_LAYER_ATTR(base, overlay), 0); +} + static int sun8i_vi_layer_atomic_check(struct drm_plane *plane, struct drm_atomic_state *state) { @@ -399,6 +410,8 @@ static void sun8i_vi_layer_atomic_disable(struct drm_plane *plane, sun8i_vi_layer_enable(mixer, layer->channel, layer->overlay, false, 0, old_zpos); + if (mixer->cfg->is_de3) + sun50i_afbc_disable(mixer, layer->channel); } static void sun8i_vi_layer_atomic_update(struct drm_plane *plane, @@ -411,26 +424,53 @@ static void sun8i_vi_layer_atomic_update(struct drm_plane *plane, struct sun8i_vi_layer *layer = plane_to_sun8i_vi_layer(plane); unsigned int zpos = new_state->normalized_zpos; unsigned int old_zpos = old_state->normalized_zpos; + struct drm_framebuffer *fb = plane->state->fb; struct sun8i_mixer *mixer = layer->mixer; + bool afbc = drm_is_afbc(fb->modifier); if (!new_state->visible) { sun8i_vi_layer_enable(mixer, layer->channel, layer->overlay, false, 0, old_zpos); + if (mixer->cfg->is_de3) + sun50i_afbc_disable(mixer, layer->channel); return; } + if (afbc) { + u32 fmt_type; + + sun8i_vi_layer_prepare_non_linear(mixer, layer->channel, + layer->overlay); + sun50i_afbc_atomic_update(mixer, layer->channel, plane); + + fmt_type = sun8i_vi_layer_get_format_type(fb->format); + sun8i_csc_set_ccsc(mixer, layer->channel, fmt_type, + plane->state->color_encoding, + plane->state->color_range); + } else { + if (mixer->cfg->is_de3) + sun50i_afbc_disable(mixer, layer->channel); + sun8i_vi_layer_update_alpha(mixer, layer->channel, + layer->overlay, plane); + sun8i_vi_layer_update_formats(mixer, layer->channel, + layer->overlay, plane); + sun8i_vi_layer_update_buffer(mixer, layer->channel, + layer->overlay, plane); + } sun8i_vi_layer_update_coord(mixer, layer->channel, - layer->overlay, plane, zpos); - sun8i_vi_layer_update_alpha(mixer, layer->channel, - layer->overlay, plane); - sun8i_vi_layer_update_formats(mixer, layer->channel, - layer->overlay, plane); - sun8i_vi_layer_update_buffer(mixer, layer->channel, - layer->overlay, plane); + layer->overlay, plane, zpos, afbc); sun8i_vi_layer_enable(mixer, layer->channel, layer->overlay, true, zpos, old_zpos); } +static bool sun8i_vi_layer_format_mod_supported(struct drm_plane *plane, + u32 format, u64 modifier) +{ + struct sun8i_vi_layer *layer = plane_to_sun8i_vi_layer(plane); + + return sun50i_afbc_format_mod_supported(layer->mixer, format, modifier); +} + static const struct drm_plane_helper_funcs sun8i_vi_layer_helper_funcs = { .atomic_check = sun8i_vi_layer_atomic_check, .atomic_disable = sun8i_vi_layer_atomic_disable, @@ -444,6 +484,7 @@ static const struct drm_plane_funcs sun8i_vi_layer_funcs = { .disable_plane = drm_atomic_helper_disable_plane, .reset = drm_atomic_helper_plane_reset, .update_plane = drm_atomic_helper_update_plane, + .format_mod_supported = sun8i_vi_layer_format_mod_supported, }; /* @@ -527,6 +568,11 @@ static const u32 sun8i_vi_layer_de3_formats[] = { DRM_FORMAT_YVU411, DRM_FORMAT_YVU420, DRM_FORMAT_YVU422, + + /* AFBC only formats */ + DRM_FORMAT_YUV420_8BIT, + DRM_FORMAT_YUV420_10BIT, + DRM_FORMAT_Y210, }; static const uint64_t sun8i_layer_modifiers[] = { @@ -534,6 +580,18 @@ static const uint64_t sun8i_layer_modifiers[] = { DRM_FORMAT_MOD_INVALID }; +static const uint64_t sun50i_layer_de3_modifiers[] = { + DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 | + AFBC_FORMAT_MOD_SPARSE | + AFBC_FORMAT_MOD_SPLIT), + DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 | + AFBC_FORMAT_MOD_YTR | + AFBC_FORMAT_MOD_SPARSE | + AFBC_FORMAT_MOD_SPLIT), + DRM_FORMAT_MOD_LINEAR, + DRM_FORMAT_MOD_INVALID +}; + struct sun8i_vi_layer *sun8i_vi_layer_init_one(struct drm_device *drm, struct sun8i_mixer *mixer, int index) @@ -542,6 +600,7 @@ struct sun8i_vi_layer *sun8i_vi_layer_init_one(struct drm_device *drm, u32 supported_encodings, supported_ranges; unsigned int plane_cnt, format_count; struct sun8i_vi_layer *layer; + const uint64_t *modifiers; const u32 *formats; int ret; @@ -556,9 +615,11 @@ struct sun8i_vi_layer *sun8i_vi_layer_init_one(struct drm_device *drm, if (mixer->cfg->is_de3) { formats = sun8i_vi_layer_de3_formats; format_count = ARRAY_SIZE(sun8i_vi_layer_de3_formats); + modifiers = sun50i_layer_de3_modifiers; } else { formats = sun8i_vi_layer_formats; format_count = ARRAY_SIZE(sun8i_vi_layer_formats); + modifiers = sun8i_layer_modifiers; } if (!mixer->cfg->ui_num && index == 0) @@ -568,8 +629,7 @@ struct sun8i_vi_layer *sun8i_vi_layer_init_one(struct drm_device *drm, ret = drm_universal_plane_init(drm, &layer->plane, 0, &sun8i_vi_layer_funcs, formats, format_count, - sun8i_layer_modifiers, - type, NULL); + modifiers, type, NULL); if (ret) { dev_err(drm->dev, "Couldn't initialize layer\n"); return ERR_PTR(ret); From patchwork Fri Jun 7 11:00:04 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ryan Walklin X-Patchwork-Id: 13689697 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id D8DD7C27C55 for ; Fri, 7 Jun 2024 11:04:11 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id DBAFA10EBE1; Fri, 7 Jun 2024 11:04:10 +0000 (UTC) Authentication-Results: gabe.freedesktop.org; dkim=pass (2048-bit key; unprotected) header.d=testtoast.com header.i=@testtoast.com header.b="CfHqxUF7"; dkim=pass (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.b="ZfAmA4+J"; dkim-atps=neutral Received: from wfout8-smtp.messagingengine.com (wfout8-smtp.messagingengine.com [64.147.123.151]) by gabe.freedesktop.org (Postfix) with ESMTPS id C4B4A10EBE0 for ; Fri, 7 Jun 2024 11:04:08 +0000 (UTC) Received: from compute6.internal (compute6.nyi.internal [10.202.2.47]) by mailfout.west.internal (Postfix) with ESMTP id C329F1C000FA; Fri, 7 Jun 2024 07:04:06 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute6.internal (MEProxy); Fri, 07 Jun 2024 07:04:08 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=testtoast.com; h=cc:cc:content-transfer-encoding:content-type:date:date:from :from:in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to; s=fm1; t=1717758246; x= 1717844646; bh=zpI9ehufM0aDHbHqGz0gA6WO8NMW/N2RNXSC8dVQYOI=; b=C fHqxUF7Na+c62pO24unsdvE8y+ECYn8NC5++xbw+SDccXtqnk2FxJw5SGtr9H0rb NoZf7jEok3LSg8B4AoJGXKySi8VSjkmpzhHiWJWhnutQp6OyCy+gZXihAw36Aj3u nMLf2AUrgQyxJjT+jp+b3FmUK3w3mmZFF9s9+kCZsE+p74DBqbqKXS7R7WISNwv9 zDBe0bcZ8YCAT+HRksca10takfJvs6loMZg1MC5awE+UkEsu/qBEg5I7SCXSGvps aqYgS/f2mapw55TpsbpONpqf4/DyWl1xkz1nmkGHvdlZmcAlmEH9ujB3iHaSwmXX 4k82rSlO6CEvDI1AlSZ4Q== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to:x-me-proxy:x-me-proxy :x-me-sender:x-me-sender:x-sasl-enc; s=fm1; t=1717758246; x= 1717844646; bh=zpI9ehufM0aDHbHqGz0gA6WO8NMW/N2RNXSC8dVQYOI=; b=Z fAmA4+JV1plPuoWcCxFeYhow/7Km1HtgL4baizuh2pOSSrWkrHLx/EQJb0Ri3hTK NkLt2xcHeNs61B/srRJ7OG8BIs7E6HBuVYyspcMPWIdeCzD2y7lOD946uwwFYQun TpbUhMnGdtJPxGy0m3qG0IUetoTLduKaBxrO3+Jext8u/t1bGdcF941Ep/uKvdRz rWXH7Kl0eReo4u80mgmlz4NhhYLO/tTYzm/T3kuOXKagMYcogihTChd+uZ+W4zMh HXCFqLUaB7wGokLPH4Ye+IO3u/TfOXHCD5Mfs+lzCVdfMQpEisW3iDhFSZnmei6t mlpRwVyPz5d//HDo+sxgg== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvledrfedtuddgudduucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhephffvvefufffkofgjfhgggfestdekredtredttdenucfhrhhomheptfihrghn ucghrghlkhhlihhnuceorhihrghnsehtvghsthhtohgrshhtrdgtohhmqeenucggtffrrg htthgvrhhnpeffheeiffegtdfgffejteevgeefkeelieelkeevueetffetteduffevgeei ieehteenucevlhhushhtvghrufhiiigvpedunecurfgrrhgrmhepmhgrihhlfhhrohhmpe hrhigrnhesthgvshhtthhorghsthdrtghomh X-ME-Proxy: Feedback-ID: idc0145fc:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Fri, 7 Jun 2024 07:03:59 -0400 (EDT) From: Ryan Walklin To: Maxime Ripard , Chen-Yu Tsai , Maarten Lankhorst , Thomas Zimmermann , David Airlie , Daniel Vetter , Jernej Skrabec , Samuel Holland , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Michael Turquette , Stephen Boyd Cc: Andre Przywara , Chris Morgan , John Watts , dri-devel@lists.freedesktop.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, devicetree@vger.kernel.org, linux-clk@vger.kernel.org, Ryan Walklin Subject: [PATCH RFC 8/8] drm: sun4i: add Display Engine 3.3 (DE33) support Date: Fri, 7 Jun 2024 23:00:04 +1200 Message-ID: <20240607110227.49848-9-ryan@testtoast.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20240607110227.49848-1-ryan@testtoast.com> References: <20240607110227.49848-1-ryan@testtoast.com> 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: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" The DE33 is a newer version of the Allwinner Display Engine IP block, found in the H616, H618, H700 and T507 SoCs. DE2 and DE3 are already supported by the mainline driver. Notable features (from the H616 datasheet and implemented): - 4096 x 2048 (4K) output support - AFBC ARM Frame Buffer Compression support - YUV420 input support Extend the driver to support the DE33. Signed-off-by: Jernej Skrabec Co-developed-by: Ryan Walklin Signed-off-by: Ryan Walklin --- drivers/clk/sunxi-ng/Makefile | 2 +- drivers/clk/sunxi-ng/sun8i-de33.c | 185 +++++++++++++++++++++ drivers/clk/sunxi-ng/sun8i-de33.h | 19 +++ drivers/gpu/drm/sun4i/sun4i_tcon.c | 4 + drivers/gpu/drm/sun4i/sun4i_tcon.h | 1 + drivers/gpu/drm/sun4i/sun50i_afbc.c | 16 +- drivers/gpu/drm/sun4i/sun50i_fmt.c | 75 ++++++--- drivers/gpu/drm/sun4i/sun50i_fmt.h | 21 ++- drivers/gpu/drm/sun4i/sun8i_csc.c | 98 ++++++++++- drivers/gpu/drm/sun4i/sun8i_csc.h | 3 + drivers/gpu/drm/sun4i/sun8i_mixer.c | 209 +++++++++++++++++++----- drivers/gpu/drm/sun4i/sun8i_mixer.h | 31 +++- drivers/gpu/drm/sun4i/sun8i_ui_layer.c | 36 ++-- drivers/gpu/drm/sun4i/sun8i_ui_scaler.c | 2 +- drivers/gpu/drm/sun4i/sun8i_vi_layer.c | 33 ++-- drivers/gpu/drm/sun4i/sun8i_vi_scaler.c | 115 ++++++++----- drivers/gpu/drm/sun4i/sun8i_vi_scaler.h | 3 +- 17 files changed, 703 insertions(+), 150 deletions(-) create mode 100644 drivers/clk/sunxi-ng/sun8i-de33.c create mode 100644 drivers/clk/sunxi-ng/sun8i-de33.h diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile index 6b3ae2b620db6..fce8a1ce61137 100644 --- a/drivers/clk/sunxi-ng/Makefile +++ b/drivers/clk/sunxi-ng/Makefile @@ -68,7 +68,7 @@ sun8i-a83t-ccu-y += ccu-sun8i-a83t.o sun8i-h3-ccu-y += ccu-sun8i-h3.o sun8i-r40-ccu-y += ccu-sun8i-r40.o sun8i-v3s-ccu-y += ccu-sun8i-v3s.o -sun8i-de2-ccu-y += ccu-sun8i-de2.o +sun8i-de2-ccu-y += ccu-sun8i-de2.o sun8i-de33.o sun8i-r-ccu-y += ccu-sun8i-r.o sun9i-a80-ccu-y += ccu-sun9i-a80.o sun9i-a80-de-ccu-y += ccu-sun9i-a80-de.o diff --git a/drivers/clk/sunxi-ng/sun8i-de33.c b/drivers/clk/sunxi-ng/sun8i-de33.c new file mode 100644 index 0000000000000..4287dafbc26e4 --- /dev/null +++ b/drivers/clk/sunxi-ng/sun8i-de33.c @@ -0,0 +1,185 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017 Icenowy Zheng + */ + +#include +#include +#include +#include +#include +#include + +#include "ccu_common.h" +#include "ccu_div.h" +#include "ccu_gate.h" +#include "ccu_reset.h" + +#include "sun8i-de33.h" + +static SUNXI_CCU_GATE(bus_mixer0_clk, "bus-mixer0", "bus-de", + 0x04, BIT(0), 0); +static SUNXI_CCU_GATE(bus_mixer1_clk, "bus-mixer1", "bus-de", + 0x04, BIT(1), 0); +static SUNXI_CCU_GATE(bus_wb_clk, "bus-wb", "bus-de", + 0x04, BIT(2), 0); + +static SUNXI_CCU_GATE(mixer0_clk, "mixer0", "mixer0-div", + 0x00, BIT(0), CLK_SET_RATE_PARENT); +static SUNXI_CCU_GATE(mixer1_clk, "mixer1", "mixer1-div", + 0x00, BIT(1), CLK_SET_RATE_PARENT); +static SUNXI_CCU_GATE(wb_clk, "wb", "wb-div", + 0x00, BIT(2), CLK_SET_RATE_PARENT); + +static SUNXI_CCU_M(mixer0_div_clk, "mixer0-div", "de", 0x0c, 0, 4, + CLK_SET_RATE_PARENT); +static SUNXI_CCU_M(mixer1_div_clk, "mixer1-div", "de", 0x0c, 4, 4, + CLK_SET_RATE_PARENT); +static SUNXI_CCU_M(wb_div_clk, "wb-div", "de", 0x0c, 8, 4, + CLK_SET_RATE_PARENT); + +static struct ccu_common *sun50i_h616_de33_clks[] = { + &mixer0_clk.common, + &mixer1_clk.common, + &wb_clk.common, + + &bus_mixer0_clk.common, + &bus_mixer1_clk.common, + &bus_wb_clk.common, + + &mixer0_div_clk.common, + &mixer1_div_clk.common, + &wb_div_clk.common, +}; + +static struct clk_hw_onecell_data sun50i_h616_de33_hw_clks = { + .hws = { + [CLK_MIXER0] = &mixer0_clk.common.hw, + [CLK_MIXER1] = &mixer1_clk.common.hw, + [CLK_WB] = &wb_clk.common.hw, + + [CLK_BUS_MIXER0] = &bus_mixer0_clk.common.hw, + [CLK_BUS_MIXER1] = &bus_mixer1_clk.common.hw, + [CLK_BUS_WB] = &bus_wb_clk.common.hw, + + [CLK_MIXER0_DIV] = &mixer0_div_clk.common.hw, + [CLK_MIXER1_DIV] = &mixer1_div_clk.common.hw, + [CLK_WB_DIV] = &wb_div_clk.common.hw, + }, + .num = CLK_NUMBER, +}; + +static struct ccu_reset_map sun50i_h616_de33_resets[] = { + [RST_MIXER0] = { 0x08, BIT(0) }, + [RST_MIXER1] = { 0x08, BIT(1) }, + [RST_WB] = { 0x08, BIT(2) }, +}; + +static const struct sunxi_ccu_desc sun50i_h616_de33_clk_desc = { + .ccu_clks = sun50i_h616_de33_clks, + .num_ccu_clks = ARRAY_SIZE(sun50i_h616_de33_clks), + + .hw_clks = &sun50i_h616_de33_hw_clks, + + .resets = sun50i_h616_de33_resets, + .num_resets = ARRAY_SIZE(sun50i_h616_de33_resets), +}; + +static int sunxi_de33_clk_probe(struct platform_device *pdev) +{ + struct resource *res; + struct clk *bus_clk, *mod_clk; + struct reset_control *rstc; + void __iomem *reg; + const struct sunxi_ccu_desc *ccu_desc; + int ret; + + ccu_desc = of_device_get_match_data(&pdev->dev); + if (!ccu_desc) + return -EINVAL; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + reg = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(reg)) + return PTR_ERR(reg); + + bus_clk = devm_clk_get(&pdev->dev, "bus"); + if (IS_ERR(bus_clk)) { + ret = PTR_ERR(bus_clk); + if (ret != -EPROBE_DEFER) + dev_err(&pdev->dev, "Couldn't get bus clk: %d\n", ret); + return ret; + } + + mod_clk = devm_clk_get(&pdev->dev, "mod"); + if (IS_ERR(mod_clk)) { + ret = PTR_ERR(mod_clk); + if (ret != -EPROBE_DEFER) + dev_err(&pdev->dev, "Couldn't get mod clk: %d\n", ret); + return ret; + } + + rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL); + if (IS_ERR(rstc)) { + ret = PTR_ERR(rstc); + if (ret != -EPROBE_DEFER) + dev_err(&pdev->dev, + "Couldn't get reset control: %d\n", ret); + return ret; + } + + /* The clocks need to be enabled for us to access the registers */ + ret = clk_prepare_enable(bus_clk); + if (ret) { + dev_err(&pdev->dev, "Couldn't enable bus clk: %d\n", ret); + return ret; + } + + ret = clk_prepare_enable(mod_clk); + if (ret) { + dev_err(&pdev->dev, "Couldn't enable mod clk: %d\n", ret); + goto err_disable_bus_clk; + } + + /* The reset control needs to be asserted for the controls to work */ + ret = reset_control_deassert(rstc); + if (ret) { + dev_err(&pdev->dev, + "Couldn't deassert reset control: %d\n", ret); + goto err_disable_mod_clk; + } + + writel(0, reg + 0x24); + writel(0x0000A980, reg + 0x28); + + ret = devm_sunxi_ccu_probe(&pdev->dev, reg, ccu_desc); + if (ret) + goto err_assert_reset; + + return 0; + +err_assert_reset: + reset_control_assert(rstc); +err_disable_mod_clk: + clk_disable_unprepare(mod_clk); +err_disable_bus_clk: + clk_disable_unprepare(bus_clk); + return ret; +} + +static const struct of_device_id sunxi_de33_clk_ids[] = { + { + .compatible = "allwinner,sun50i-h616-de33-clk", + .data = &sun50i_h616_de33_clk_desc, + }, + { } +}; + +static struct platform_driver sunxi_de33_clk_driver = { + .probe = sunxi_de33_clk_probe, + .driver = { + .name = "sunxi-de33-clks", + .of_match_table = sunxi_de33_clk_ids, + }, +}; +builtin_platform_driver(sunxi_de33_clk_driver); diff --git a/drivers/clk/sunxi-ng/sun8i-de33.h b/drivers/clk/sunxi-ng/sun8i-de33.h new file mode 100644 index 0000000000000..83cbef5a3f76f --- /dev/null +++ b/drivers/clk/sunxi-ng/sun8i-de33.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright 2016 Icenowy Zheng + */ + +#ifndef _CCU_SUN8I_DE2_H_ +#define _CCU_SUN8I_DE2_H_ + +#include +#include + +/* Intermediary clock dividers are not exported */ +#define CLK_MIXER0_DIV 3 +#define CLK_MIXER1_DIV 4 +#define CLK_WB_DIV 5 + +#define CLK_NUMBER (CLK_WB + 1) + +#endif /* _CCU_SUN8I_DE2_H_ */ diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c index e39926e9f0b5d..12b73907788fa 100644 --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c @@ -1277,6 +1277,10 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master, goto err_free_dclk; } + regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG, + SUN4I_TCON_GCTL_PAD_SEL, + SUN4I_TCON_GCTL_PAD_SEL); + if (tcon->quirks->needs_de_be_mux) { /* * We assume there is no dynamic muxing of backends diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.h b/drivers/gpu/drm/sun4i/sun4i_tcon.h index fa23aa23fe4a4..d56c9764ff4c6 100644 --- a/drivers/gpu/drm/sun4i/sun4i_tcon.h +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.h @@ -19,6 +19,7 @@ #define SUN4I_TCON_GCTL_REG 0x0 #define SUN4I_TCON_GCTL_TCON_ENABLE BIT(31) +#define SUN4I_TCON_GCTL_PAD_SEL BIT(1) #define SUN4I_TCON_GCTL_IOMAP_MASK BIT(0) #define SUN4I_TCON_GCTL_IOMAP_TCON1 (1 << 0) #define SUN4I_TCON_GCTL_IOMAP_TCON0 (0 << 0) diff --git a/drivers/gpu/drm/sun4i/sun50i_afbc.c b/drivers/gpu/drm/sun4i/sun50i_afbc.c index 27a771608eef8..b55e1c5533714 100644 --- a/drivers/gpu/drm/sun4i/sun50i_afbc.c +++ b/drivers/gpu/drm/sun4i/sun50i_afbc.c @@ -13,6 +13,16 @@ #include "sun50i_afbc.h" #include "sun8i_mixer.h" +static u32 sun50i_afbc_get_base(struct sun8i_mixer *mixer, unsigned int channel) +{ + u32 base = sun8i_channel_base(mixer, channel); + + if (mixer->cfg->de_type == sun8i_mixer_de3) + return base + SUN50I_AFBC_CH_OFFSET; + + return base + 0x4000; +} + bool sun50i_afbc_format_mod_supported(struct sun8i_mixer *mixer, u32 format, u64 modifier) { @@ -29,7 +39,7 @@ bool sun50i_afbc_format_mod_supported(struct sun8i_mixer *mixer, return true; } - if (!mixer->cfg->is_de3) + if (mixer->cfg->de_type == sun8i_mixer_de2) return false; mode = AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 | @@ -69,7 +79,7 @@ void sun50i_afbc_atomic_update(struct sun8i_mixer *mixer, unsigned int channel, struct regmap *regs; dma_addr_t dma_addr; - base = sun8i_channel_base(mixer, channel) + SUN50I_AFBC_CH_OFFSET; + base = sun50i_afbc_get_base(mixer, channel); regs = mixer->engine.regs; src_w = drm_rect_width(&state->src) >> 16; @@ -234,7 +244,7 @@ void sun50i_afbc_atomic_update(struct sun8i_mixer *mixer, unsigned int channel, void sun50i_afbc_disable(struct sun8i_mixer *mixer, unsigned int channel) { - u32 base = sun8i_channel_base(mixer, channel) + SUN50I_AFBC_CH_OFFSET; + u32 base = sun50i_afbc_get_base(mixer, channel); regmap_write(mixer->engine.regs, SUN50I_FBD_CTL(base), 0); } diff --git a/drivers/gpu/drm/sun4i/sun50i_fmt.c b/drivers/gpu/drm/sun4i/sun50i_fmt.c index 18a8d5032ddce..39682d4e6d208 100644 --- a/drivers/gpu/drm/sun4i/sun50i_fmt.c +++ b/drivers/gpu/drm/sun4i/sun50i_fmt.c @@ -34,41 +34,66 @@ static u32 sun50i_fmt_get_colorspace(u32 format) } } +static void sun50i_fmt_de3_limits(u32 *limits, u32 colorspace, bool bit10) +{ + if (colorspace != SUN50I_FMT_CS_YUV444RGB) { + limits[0] = SUN50I_FMT_LIMIT(64, 940); + limits[1] = SUN50I_FMT_LIMIT(64, 960); + limits[2] = SUN50I_FMT_LIMIT(64, 960); + } else if (bit10) { + limits[0] = SUN50I_FMT_LIMIT(0, 1023); + limits[1] = SUN50I_FMT_LIMIT(0, 1023); + limits[2] = SUN50I_FMT_LIMIT(0, 1023); + } else { + limits[0] = SUN50I_FMT_LIMIT(0, 1021); + limits[1] = SUN50I_FMT_LIMIT(0, 1021); + limits[2] = SUN50I_FMT_LIMIT(0, 1021); + } +} + +static void sun50i_fmt_de33_limits(u32 *limits, u32 colorspace) +{ + if (colorspace == SUN50I_FMT_CS_YUV444RGB) { + limits[0] = SUN50I_FMT_LIMIT(0, 4095); + limits[1] = SUN50I_FMT_LIMIT(0, 4095); + limits[2] = SUN50I_FMT_LIMIT(0, 4095); + } else { + limits[0] = SUN50I_FMT_LIMIT(256, 3840); + limits[1] = SUN50I_FMT_LIMIT(256, 3840); + limits[2] = SUN50I_FMT_LIMIT(256, 3840); + } +} + void sun50i_fmt_setup(struct sun8i_mixer *mixer, u16 width, u16 height, u32 format) { - u32 colorspace, limit[3]; + u32 colorspace, limit[3], base; + struct regmap *regs; bool bit10; colorspace = sun50i_fmt_get_colorspace(format); bit10 = sun50i_fmt_is_10bit(format); + base = mixer->cfg->de_type == sun8i_mixer_de3 ? + SUN50I_FMT_DE3 : SUN50I_FMT_DE33; + regs = sun8i_blender_regmap(mixer); - regmap_write(mixer->engine.regs, SUN50I_FMT_CTRL, 0); + if (mixer->cfg->de_type == sun8i_mixer_de3) + sun50i_fmt_de3_limits(limit, colorspace, bit10); + else + sun50i_fmt_de33_limits(limit, colorspace); - regmap_write(mixer->engine.regs, SUN50I_FMT_SIZE, - SUN8I_MIXER_SIZE(width, height)); - regmap_write(mixer->engine.regs, SUN50I_FMT_SWAP, 0); - regmap_write(mixer->engine.regs, SUN50I_FMT_DEPTH, bit10); - regmap_write(mixer->engine.regs, SUN50I_FMT_FORMAT, colorspace); - regmap_write(mixer->engine.regs, SUN50I_FMT_COEF, 0); + regmap_write(regs, SUN50I_FMT_CTRL(base), 0); - if (colorspace != SUN50I_FMT_CS_YUV444RGB) { - limit[0] = SUN50I_FMT_LIMIT(64, 940); - limit[1] = SUN50I_FMT_LIMIT(64, 960); - limit[2] = SUN50I_FMT_LIMIT(64, 960); - } else if (bit10) { - limit[0] = SUN50I_FMT_LIMIT(0, 1023); - limit[1] = SUN50I_FMT_LIMIT(0, 1023); - limit[2] = SUN50I_FMT_LIMIT(0, 1023); - } else { - limit[0] = SUN50I_FMT_LIMIT(0, 1021); - limit[1] = SUN50I_FMT_LIMIT(0, 1021); - limit[2] = SUN50I_FMT_LIMIT(0, 1021); - } + regmap_write(regs, SUN50I_FMT_SIZE(base), + SUN8I_MIXER_SIZE(width, height)); + regmap_write(regs, SUN50I_FMT_SWAP(base), 0); + regmap_write(regs, SUN50I_FMT_DEPTH(base), bit10); + regmap_write(regs, SUN50I_FMT_FORMAT(base), colorspace); + regmap_write(regs, SUN50I_FMT_COEF(base), 0); - regmap_write(mixer->engine.regs, SUN50I_FMT_LMT_Y, limit[0]); - regmap_write(mixer->engine.regs, SUN50I_FMT_LMT_C0, limit[1]); - regmap_write(mixer->engine.regs, SUN50I_FMT_LMT_C1, limit[2]); + regmap_write(regs, SUN50I_FMT_LMT_Y(base), limit[0]); + regmap_write(regs, SUN50I_FMT_LMT_C0(base), limit[1]); + regmap_write(regs, SUN50I_FMT_LMT_C1(base), limit[2]); - regmap_write(mixer->engine.regs, SUN50I_FMT_CTRL, 1); + regmap_write(regs, SUN50I_FMT_CTRL(base), 1); } diff --git a/drivers/gpu/drm/sun4i/sun50i_fmt.h b/drivers/gpu/drm/sun4i/sun50i_fmt.h index 0fa1d2d22e592..3e60d5c788b39 100644 --- a/drivers/gpu/drm/sun4i/sun50i_fmt.h +++ b/drivers/gpu/drm/sun4i/sun50i_fmt.h @@ -8,15 +8,18 @@ #include "sun8i_mixer.h" -#define SUN50I_FMT_CTRL 0xa8000 -#define SUN50I_FMT_SIZE 0xa8004 -#define SUN50I_FMT_SWAP 0xa8008 -#define SUN50I_FMT_DEPTH 0xa800c -#define SUN50I_FMT_FORMAT 0xa8010 -#define SUN50I_FMT_COEF 0xa8014 -#define SUN50I_FMT_LMT_Y 0xa8020 -#define SUN50I_FMT_LMT_C0 0xa8024 -#define SUN50I_FMT_LMT_C1 0xa8028 +#define SUN50I_FMT_DE3 0xa8000 +#define SUN50I_FMT_DE33 0x5000 + +#define SUN50I_FMT_CTRL(base) ((base) + 0x00) +#define SUN50I_FMT_SIZE(base) ((base) + 0x04) +#define SUN50I_FMT_SWAP(base) ((base) + 0x08) +#define SUN50I_FMT_DEPTH(base) ((base) + 0x0c) +#define SUN50I_FMT_FORMAT(base) ((base) + 0x10) +#define SUN50I_FMT_COEF(base) ((base) + 0x14) +#define SUN50I_FMT_LMT_Y(base) ((base) + 0x20) +#define SUN50I_FMT_LMT_C0(base) ((base) + 0x24) +#define SUN50I_FMT_LMT_C1(base) ((base) + 0x28) #define SUN50I_FMT_LIMIT(low, high) (((high) << 16) | (low)) diff --git a/drivers/gpu/drm/sun4i/sun8i_csc.c b/drivers/gpu/drm/sun4i/sun8i_csc.c index 3b022bfb85adc..5f32c57fe7769 100644 --- a/drivers/gpu/drm/sun4i/sun8i_csc.c +++ b/drivers/gpu/drm/sun4i/sun8i_csc.c @@ -238,6 +238,14 @@ static const u32 yuv2yuv_de3[2][3][3][12] = { }, }; +static u32 sun8i_csc_base(struct sun8i_mixer *mixer, int layer) +{ + if (mixer->cfg->de_type == sun8i_mixer_de33) + return sun8i_channel_base(mixer, layer) - 0x800; + else + return ccsc_base[mixer->cfg->ccsc][layer]; +} + static void sun8i_csc_setup(struct regmap *map, u32 base, enum format_type fmt_type, enum drm_color_encoding encoding, @@ -358,6 +366,90 @@ static void sun8i_de3_ccsc_setup(struct sunxi_engine *engine, int layer, mask, val); } +/* extract constant from high word and invert sign if necessary */ +static u32 sun8i_de33_ccsc_get_constant(u32 value) +{ + value >>= 16; + + if (value & BIT(15)) + return 0x400 - (value & 0x3ff); + + return value; +} + +static void sun8i_de33_convert_table(const u32 *src, u32 *dst) +{ + dst[0] = sun8i_de33_ccsc_get_constant(src[3]); + dst[1] = sun8i_de33_ccsc_get_constant(src[7]); + dst[2] = sun8i_de33_ccsc_get_constant(src[11]); + memcpy(&dst[3], src, sizeof(u32) * 12); + dst[6] &= 0xffff; + dst[10] &= 0xffff; + dst[14] &= 0xffff; +} + +static void sun8i_de33_ccsc_setup(struct sun8i_mixer *mixer, int layer, + enum format_type fmt_type, + enum drm_color_encoding encoding, + enum drm_color_range range) +{ + u32 addr, val = 0, base, csc[15]; + struct sunxi_engine *engine; + struct regmap *map; + const u32 *table; + int i; + + table = yuv2rgb_de3[range][encoding]; + base = sun8i_csc_base(mixer, layer); + engine = &mixer->engine; + map = engine->regs; + + switch (fmt_type) { + case FORMAT_TYPE_RGB: + if (engine->format == MEDIA_BUS_FMT_RGB888_1X24) + break; + val = SUN8I_CSC_CTRL_EN; + sun8i_de33_convert_table(rgb2yuv_de3[engine->encoding], csc); + regmap_bulk_write(map, SUN50I_CSC_COEFF(base, 0), csc, 15); + break; + case FORMAT_TYPE_YUV: + table = sun8i_csc_get_de3_yuv_table(encoding, range, + engine->format, + engine->encoding); + if (!table) + break; + val = SUN8I_CSC_CTRL_EN; + sun8i_de33_convert_table(table, csc); + regmap_bulk_write(map, SUN50I_CSC_COEFF(base, 0), csc, 15); + break; + case FORMAT_TYPE_YVU: + table = sun8i_csc_get_de3_yuv_table(encoding, range, + engine->format, + engine->encoding); + if (!table) + table = yuv2yuv_de3[range][encoding][encoding]; + val = SUN8I_CSC_CTRL_EN; + sun8i_de33_convert_table(table, csc); + for (i = 0; i < 15; i++) { + addr = SUN50I_CSC_COEFF(base, i); + if (i > 3) { + if (((i - 3) & 3) == 1) + addr = SUN50I_CSC_COEFF(base, i + 1); + else if (((i - 3) & 3) == 2) + addr = SUN50I_CSC_COEFF(base, i - 1); + } + regmap_write(map, addr, csc[i]); + } + break; + default: + val = 0; + DRM_WARN("Wrong CSC mode specified.\n"); + return; + } + + regmap_write(map, SUN8I_CSC_CTRL(base), val); +} + void sun8i_csc_set_ccsc(struct sun8i_mixer *mixer, int layer, enum format_type fmt_type, enum drm_color_encoding encoding, @@ -365,10 +457,14 @@ void sun8i_csc_set_ccsc(struct sun8i_mixer *mixer, int layer, { u32 base; - if (mixer->cfg->is_de3) { + if (mixer->cfg->de_type == sun8i_mixer_de3) { sun8i_de3_ccsc_setup(&mixer->engine, layer, fmt_type, encoding, range); return; + } else if (mixer->cfg->de_type == sun8i_mixer_de33) { + sun8i_de33_ccsc_setup(mixer, layer, fmt_type, + encoding, range); + return; } if (layer < mixer->cfg->vi_num) { diff --git a/drivers/gpu/drm/sun4i/sun8i_csc.h b/drivers/gpu/drm/sun4i/sun8i_csc.h index b7546e06e315c..2b762cb79f02c 100644 --- a/drivers/gpu/drm/sun4i/sun8i_csc.h +++ b/drivers/gpu/drm/sun4i/sun8i_csc.h @@ -20,6 +20,9 @@ struct sun8i_mixer; #define SUN8I_CSC_CTRL(base) ((base) + 0x0) #define SUN8I_CSC_COEFF(base, i) ((base) + 0x10 + 4 * (i)) +#define SUN50I_CSC_COEFF(base, i) ((base) + 0x04 + 4 * (i)) +#define SUN50I_CSC_ALPHA(base) ((base) + 0x40) + #define SUN8I_CSC_CTRL_EN BIT(0) enum format_type { diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c index b1525906a25d8..65615b5f9dbab 100644 --- a/drivers/gpu/drm/sun4i/sun8i_mixer.c +++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c @@ -254,10 +254,16 @@ int sun8i_mixer_drm_format_to_hw(u32 format, u32 *hw_format) static void sun8i_mixer_commit(struct sunxi_engine *engine) { + struct sun8i_mixer *mixer = engine_to_sun8i_mixer(engine); + DRM_DEBUG_DRIVER("Committing changes\n"); - regmap_write(engine->regs, SUN8I_MIXER_GLOBAL_DBUFF, - SUN8I_MIXER_GLOBAL_DBUFF_ENABLE); + if (mixer->cfg->de_type == sun8i_mixer_de33) + regmap_write(mixer->top_regs, SUN50I_MIXER_GLOBAL_DBUFF, + SUN8I_MIXER_GLOBAL_DBUFF_ENABLE); + else + regmap_write(engine->regs, SUN8I_MIXER_GLOBAL_DBUFF, + SUN8I_MIXER_GLOBAL_DBUFF_ENABLE); } static struct drm_plane **sun8i_layers_init(struct drm_device *drm, @@ -306,25 +312,33 @@ static void sun8i_mixer_mode_set(struct sunxi_engine *engine, const struct drm_display_mode *mode) { struct sun8i_mixer *mixer = engine_to_sun8i_mixer(engine); + struct regmap *bld_regs, *disp_regs; u32 bld_base, size, val; bool interlaced; bld_base = sun8i_blender_base(mixer); + bld_regs = sun8i_blender_regmap(mixer); interlaced = !!(mode->flags & DRM_MODE_FLAG_INTERLACE); size = SUN8I_MIXER_SIZE(mode->hdisplay, mode->vdisplay); DRM_DEBUG_DRIVER("Updating global size W: %u H: %u\n", mode->hdisplay, mode->vdisplay); - regmap_write(engine->regs, SUN8I_MIXER_GLOBAL_SIZE, size); - regmap_write(engine->regs, SUN8I_MIXER_BLEND_OUTSIZE(bld_base), size); + if (mixer->cfg->de_type == sun8i_mixer_de33) { + disp_regs = mixer->disp_regs; + regmap_write(mixer->top_regs, SUN50I_MIXER_GLOBAL_SIZE, size); + } else { + disp_regs = mixer->engine.regs; + regmap_write(mixer->engine.regs, SUN8I_MIXER_GLOBAL_SIZE, size); + } + regmap_write(bld_regs, SUN8I_MIXER_BLEND_OUTSIZE(bld_base), size); if (interlaced) val = SUN8I_MIXER_BLEND_OUTCTL_INTERLACED; else val = 0; - regmap_update_bits(engine->regs, SUN8I_MIXER_BLEND_OUTCTL(bld_base), + regmap_update_bits(bld_regs, SUN8I_MIXER_BLEND_OUTCTL(bld_base), SUN8I_MIXER_BLEND_OUTCTL_INTERLACED, val); DRM_DEBUG_DRIVER("Switching display mixer interlaced mode %s\n", @@ -335,10 +349,8 @@ static void sun8i_mixer_mode_set(struct sunxi_engine *engine, else val = 0xff108080; - regmap_write(mixer->engine.regs, - SUN8I_MIXER_BLEND_BKCOLOR(bld_base), val); - regmap_write(mixer->engine.regs, - SUN8I_MIXER_BLEND_ATTR_FCOLOR(bld_base, 0), val); + regmap_write(disp_regs, SUN8I_MIXER_BLEND_BKCOLOR(bld_base), val); + regmap_write(disp_regs, SUN8I_MIXER_BLEND_ATTR_FCOLOR(bld_base, 0), val); if (mixer->cfg->has_formatter) sun50i_fmt_setup(mixer, mode->hdisplay, @@ -378,12 +390,29 @@ static const struct sunxi_engine_ops sun8i_engine_ops = { }; static const struct regmap_config sun8i_mixer_regmap_config = { + .name = "layers", .reg_bits = 32, .val_bits = 32, .reg_stride = 4, .max_register = 0xffffc, /* guessed */ }; +static const struct regmap_config sun8i_top_regmap_config = { + .name = "top", + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, + .max_register = 0x3c, +}; + +static const struct regmap_config sun8i_disp_regmap_config = { + .name = "display", + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, + .max_register = 0x20000, +}; + static int sun8i_mixer_of_get_id(struct device_node *node) { struct device_node *ep, *remote; @@ -404,6 +433,76 @@ static int sun8i_mixer_of_get_id(struct device_node *node) return of_ep.id; } +static void sun8i_mixer_de2_init(struct sun8i_mixer *mixer) +{ + unsigned int base; + int plane_cnt, i; + + base = sun8i_blender_base(mixer); + + /* Enable the mixer */ + regmap_write(mixer->engine.regs, SUN8I_MIXER_GLOBAL_CTL, + SUN8I_MIXER_GLOBAL_CTL_RT_EN); + + /* Set background color to black */ + regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_BKCOLOR(base), + SUN8I_MIXER_BLEND_COLOR_BLACK); + + /* + * Set fill color of bottom plane to black. Generally not needed + * except when VI plane is at bottom (zpos = 0) and enabled. + */ + regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_PIPE_CTL(base), + SUN8I_MIXER_BLEND_PIPE_CTL_FC_EN(0)); + regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_ATTR_FCOLOR(base, 0), + SUN8I_MIXER_BLEND_COLOR_BLACK); + + plane_cnt = mixer->cfg->vi_num + mixer->cfg->ui_num; + for (i = 0; i < plane_cnt; i++) + regmap_write(mixer->engine.regs, + SUN8I_MIXER_BLEND_MODE(base, i), + SUN8I_MIXER_BLEND_MODE_DEF); + + regmap_update_bits(mixer->engine.regs, SUN8I_MIXER_BLEND_PIPE_CTL(base), + SUN8I_MIXER_BLEND_PIPE_CTL_EN_MSK, 0); +} + +static void sun8i_mixer_de33_init(struct sun8i_mixer *mixer) +{ + unsigned int base; + int plane_cnt, i; + + base = sun8i_blender_base(mixer); + + /* Enable the mixer */ + regmap_write(mixer->top_regs, SUN50I_MIXER_GLOBAL_CTL, + SUN8I_MIXER_GLOBAL_CTL_RT_EN); + + regmap_write(mixer->top_regs, SUN50I_MIXER_GLOBAL_CLK, 1); + + /* Set background color to black */ + regmap_write(mixer->disp_regs, SUN8I_MIXER_BLEND_BKCOLOR(base), + SUN8I_MIXER_BLEND_COLOR_BLACK); + + /* + * Set fill color of bottom plane to black. Generally not needed + * except when VI plane is at bottom (zpos = 0) and enabled. + */ + regmap_write(mixer->disp_regs, SUN8I_MIXER_BLEND_PIPE_CTL(base), + SUN8I_MIXER_BLEND_PIPE_CTL_FC_EN(0)); + regmap_write(mixer->disp_regs, SUN8I_MIXER_BLEND_ATTR_FCOLOR(base, 0), + SUN8I_MIXER_BLEND_COLOR_BLACK); + + plane_cnt = mixer->cfg->vi_num + mixer->cfg->ui_num; + for (i = 0; i < plane_cnt; i++) + regmap_write(mixer->disp_regs, + SUN8I_MIXER_BLEND_MODE(base, i), + SUN8I_MIXER_BLEND_MODE_DEF); + + regmap_update_bits(mixer->disp_regs, SUN8I_MIXER_BLEND_PIPE_CTL(base), + SUN8I_MIXER_BLEND_PIPE_CTL_EN_MSK, 0); +} + static int sun8i_mixer_bind(struct device *dev, struct device *master, void *data) { @@ -412,8 +511,6 @@ static int sun8i_mixer_bind(struct device *dev, struct device *master, struct sun4i_drv *drv = drm->dev_private; struct sun8i_mixer *mixer; void __iomem *regs; - unsigned int base; - int plane_cnt; int i, ret; /* @@ -476,6 +573,30 @@ static int sun8i_mixer_bind(struct device *dev, struct device *master, return PTR_ERR(mixer->engine.regs); } + if (mixer->cfg->de_type == sun8i_mixer_de33) { + regs = devm_platform_ioremap_resource(pdev, 1); + if (IS_ERR(regs)) + return PTR_ERR(regs); + + mixer->top_regs = devm_regmap_init_mmio(dev, regs, + &sun8i_top_regmap_config); + if (IS_ERR(mixer->top_regs)) { + dev_err(dev, "Couldn't create the top regmap\n"); + return PTR_ERR(mixer->top_regs); + } + + regs = devm_platform_ioremap_resource(pdev, 2); + if (IS_ERR(regs)) + return PTR_ERR(regs); + + mixer->disp_regs = devm_regmap_init_mmio(dev, regs, + &sun8i_disp_regmap_config); + if (IS_ERR(mixer->disp_regs)) { + dev_err(dev, "Couldn't create the disp regmap\n"); + return PTR_ERR(mixer->disp_regs); + } + } + mixer->reset = devm_reset_control_get(dev, NULL); if (IS_ERR(mixer->reset)) { dev_err(dev, "Couldn't get our reset line\n"); @@ -515,10 +636,10 @@ static int sun8i_mixer_bind(struct device *dev, struct device *master, list_add_tail(&mixer->engine.list, &drv->engine_list); - base = sun8i_blender_base(mixer); - /* Reset registers and disable unused sub-engines */ - if (mixer->cfg->is_de3) { + if (mixer->cfg->de_type == sun8i_mixer_de33) { + sun8i_mixer_de33_init(mixer); + } else if (mixer->cfg->de_type == sun8i_mixer_de3) { for (i = 0; i < DE3_MIXER_UNIT_SIZE; i += 4) regmap_write(mixer->engine.regs, i, 0); @@ -532,7 +653,9 @@ static int sun8i_mixer_bind(struct device *dev, struct device *master, regmap_write(mixer->engine.regs, SUN50I_MIXER_FMT_EN, 0); regmap_write(mixer->engine.regs, SUN50I_MIXER_CDC0_EN, 0); regmap_write(mixer->engine.regs, SUN50I_MIXER_CDC1_EN, 0); - } else { + + sun8i_mixer_de2_init(mixer); + } else if (mixer->cfg->de_type == sun8i_mixer_de2) { for (i = 0; i < DE2_MIXER_UNIT_SIZE; i += 4) regmap_write(mixer->engine.regs, i, 0); @@ -543,33 +666,9 @@ static int sun8i_mixer_bind(struct device *dev, struct device *master, regmap_write(mixer->engine.regs, SUN8I_MIXER_ASE_EN, 0); regmap_write(mixer->engine.regs, SUN8I_MIXER_FCC_EN, 0); regmap_write(mixer->engine.regs, SUN8I_MIXER_DCSC_EN, 0); - } - - /* Enable the mixer */ - regmap_write(mixer->engine.regs, SUN8I_MIXER_GLOBAL_CTL, - SUN8I_MIXER_GLOBAL_CTL_RT_EN); - - /* Set background color to black */ - regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_BKCOLOR(base), - SUN8I_MIXER_BLEND_COLOR_BLACK); - - /* - * Set fill color of bottom plane to black. Generally not needed - * except when VI plane is at bottom (zpos = 0) and enabled. - */ - regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_PIPE_CTL(base), - SUN8I_MIXER_BLEND_PIPE_CTL_FC_EN(0)); - regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_ATTR_FCOLOR(base, 0), - SUN8I_MIXER_BLEND_COLOR_BLACK); - plane_cnt = mixer->cfg->vi_num + mixer->cfg->ui_num; - for (i = 0; i < plane_cnt; i++) - regmap_write(mixer->engine.regs, - SUN8I_MIXER_BLEND_MODE(base, i), - SUN8I_MIXER_BLEND_MODE_DEF); - - regmap_update_bits(mixer->engine.regs, SUN8I_MIXER_BLEND_PIPE_CTL(base), - SUN8I_MIXER_BLEND_PIPE_CTL_EN_MSK, 0); + sun8i_mixer_de2_init(mixer); + } return 0; @@ -609,6 +708,7 @@ static void sun8i_mixer_remove(struct platform_device *pdev) static const struct sun8i_mixer_cfg sun8i_a83t_mixer0_cfg = { .ccsc = CCSC_MIXER0_LAYOUT, + .de_type = sun8i_mixer_de2, .scaler_mask = 0xf, .scanline_yuv = 2048, .ui_num = 3, @@ -617,6 +717,7 @@ static const struct sun8i_mixer_cfg sun8i_a83t_mixer0_cfg = { static const struct sun8i_mixer_cfg sun8i_a83t_mixer1_cfg = { .ccsc = CCSC_MIXER1_LAYOUT, + .de_type = sun8i_mixer_de2, .scaler_mask = 0x3, .scanline_yuv = 2048, .ui_num = 1, @@ -625,6 +726,7 @@ static const struct sun8i_mixer_cfg sun8i_a83t_mixer1_cfg = { static const struct sun8i_mixer_cfg sun8i_h3_mixer0_cfg = { .ccsc = CCSC_MIXER0_LAYOUT, + .de_type = sun8i_mixer_de2, .mod_rate = 432000000, .scaler_mask = 0xf, .scanline_yuv = 2048, @@ -634,6 +736,7 @@ static const struct sun8i_mixer_cfg sun8i_h3_mixer0_cfg = { static const struct sun8i_mixer_cfg sun8i_r40_mixer0_cfg = { .ccsc = CCSC_MIXER0_LAYOUT, + .de_type = sun8i_mixer_de2, .mod_rate = 297000000, .scaler_mask = 0xf, .scanline_yuv = 2048, @@ -643,6 +746,7 @@ static const struct sun8i_mixer_cfg sun8i_r40_mixer0_cfg = { static const struct sun8i_mixer_cfg sun8i_r40_mixer1_cfg = { .ccsc = CCSC_MIXER1_LAYOUT, + .de_type = sun8i_mixer_de2, .mod_rate = 297000000, .scaler_mask = 0x3, .scanline_yuv = 2048, @@ -651,6 +755,7 @@ static const struct sun8i_mixer_cfg sun8i_r40_mixer1_cfg = { }; static const struct sun8i_mixer_cfg sun8i_v3s_mixer_cfg = { + .de_type = sun8i_mixer_de2, .vi_num = 2, .ui_num = 1, .scaler_mask = 0x3, @@ -661,6 +766,7 @@ static const struct sun8i_mixer_cfg sun8i_v3s_mixer_cfg = { static const struct sun8i_mixer_cfg sun20i_d1_mixer0_cfg = { .ccsc = CCSC_D1_MIXER0_LAYOUT, + .de_type = sun8i_mixer_de2, .mod_rate = 297000000, .scaler_mask = 0x3, .scanline_yuv = 2048, @@ -670,6 +776,7 @@ static const struct sun8i_mixer_cfg sun20i_d1_mixer0_cfg = { static const struct sun8i_mixer_cfg sun20i_d1_mixer1_cfg = { .ccsc = CCSC_MIXER1_LAYOUT, + .de_type = sun8i_mixer_de2, .mod_rate = 297000000, .scaler_mask = 0x1, .scanline_yuv = 1024, @@ -679,6 +786,7 @@ static const struct sun8i_mixer_cfg sun20i_d1_mixer1_cfg = { static const struct sun8i_mixer_cfg sun50i_a64_mixer0_cfg = { .ccsc = CCSC_MIXER0_LAYOUT, + .de_type = sun8i_mixer_de2, .mod_rate = 297000000, .scaler_mask = 0xf, .scanline_yuv = 4096, @@ -688,6 +796,7 @@ static const struct sun8i_mixer_cfg sun50i_a64_mixer0_cfg = { static const struct sun8i_mixer_cfg sun50i_a64_mixer1_cfg = { .ccsc = CCSC_MIXER1_LAYOUT, + .de_type = sun8i_mixer_de2, .mod_rate = 297000000, .scaler_mask = 0x3, .scanline_yuv = 2048, @@ -697,7 +806,7 @@ static const struct sun8i_mixer_cfg sun50i_a64_mixer1_cfg = { static const struct sun8i_mixer_cfg sun50i_h6_mixer0_cfg = { .ccsc = CCSC_MIXER0_LAYOUT, - .is_de3 = true, + .de_type = sun8i_mixer_de3, .has_formatter = 1, .mod_rate = 600000000, .scaler_mask = 0xf, @@ -706,6 +815,18 @@ static const struct sun8i_mixer_cfg sun50i_h6_mixer0_cfg = { .vi_num = 1, }; +static const struct sun8i_mixer_cfg sun50i_h616_mixer0_cfg = { + .ccsc = CCSC_MIXER0_LAYOUT, + .de_type = sun8i_mixer_de33, + .has_formatter = 1, + .mod_rate = 600000000, + .scaler_mask = 0xf, + .scanline_yuv = 4096, + .ui_num = 3, + .vi_num = 1, + .map = {0, 6, 7, 8}, +}; + static const struct of_device_id sun8i_mixer_of_table[] = { { .compatible = "allwinner,sun8i-a83t-de2-mixer-0", @@ -751,6 +872,10 @@ static const struct of_device_id sun8i_mixer_of_table[] = { .compatible = "allwinner,sun50i-h6-de3-mixer-0", .data = &sun50i_h6_mixer0_cfg, }, + { + .compatible = "allwinner,sun50i-h616-de33-mixer-0", + .data = &sun50i_h616_mixer0_cfg, + }, { } }; MODULE_DEVICE_TABLE(of, sun8i_mixer_of_table); diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.h b/drivers/gpu/drm/sun4i/sun8i_mixer.h index 13401643c7bfc..f1c2cdb88d0eb 100644 --- a/drivers/gpu/drm/sun4i/sun8i_mixer.h +++ b/drivers/gpu/drm/sun4i/sun8i_mixer.h @@ -20,6 +20,12 @@ #define SUN8I_MIXER_GLOBAL_DBUFF 0x8 #define SUN8I_MIXER_GLOBAL_SIZE 0xc +#define SUN50I_MIXER_GLOBAL_CTL 0x0 +#define SUN50I_MIXER_GLOBAL_STATUS 0x4 +#define SUN50I_MIXER_GLOBAL_SIZE 0x8 +#define SUN50I_MIXER_GLOBAL_CLK 0xc +#define SUN50I_MIXER_GLOBAL_DBUFF 0x10 + #define SUN8I_MIXER_GLOBAL_CTL_RT_EN BIT(0) #define SUN8I_MIXER_GLOBAL_DBUFF_ENABLE BIT(0) @@ -150,6 +156,12 @@ enum { CCSC_D1_MIXER0_LAYOUT, }; +enum sun8i_mixer_type { + sun8i_mixer_de2, + sun8i_mixer_de3, + sun8i_mixer_de33, +}; + /** * struct sun8i_mixer_cfg - mixer HW configuration * @vi_num: number of VI channels @@ -171,9 +183,10 @@ struct sun8i_mixer_cfg { int scaler_mask; int ccsc; unsigned long mod_rate; - unsigned int is_de3 : 1; + unsigned int de_type; unsigned int has_formatter : 1; unsigned int scanline_yuv; + unsigned int map[6]; }; struct sun8i_mixer { @@ -185,6 +198,9 @@ struct sun8i_mixer { struct clk *bus_clk; struct clk *mod_clk; + + struct regmap *top_regs; + struct regmap *disp_regs; }; static inline struct sun8i_mixer * @@ -196,13 +212,22 @@ engine_to_sun8i_mixer(struct sunxi_engine *engine) static inline u32 sun8i_blender_base(struct sun8i_mixer *mixer) { - return mixer->cfg->is_de3 ? DE3_BLD_BASE : DE2_BLD_BASE; + return mixer->cfg->de_type == sun8i_mixer_de3 ? DE3_BLD_BASE : DE2_BLD_BASE; +} + +static inline struct regmap * +sun8i_blender_regmap(struct sun8i_mixer *mixer) +{ + return mixer->cfg->de_type == sun8i_mixer_de33 ? + mixer->disp_regs : mixer->engine.regs; } static inline u32 sun8i_channel_base(struct sun8i_mixer *mixer, int channel) { - if (mixer->cfg->is_de3) + if (mixer->cfg->de_type == sun8i_mixer_de33) + return mixer->cfg->map[channel] * 0x20000 + DE2_CH_SIZE; + else if (mixer->cfg->de_type == sun8i_mixer_de3) return DE3_CH_BASE + channel * DE3_CH_SIZE; else return DE2_CH_BASE + channel * DE2_CH_SIZE; diff --git a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c index 91781b5bbbbce..1649816fe435e 100644 --- a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c +++ b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c @@ -24,14 +24,17 @@ #include "sun8i_mixer.h" #include "sun8i_ui_layer.h" #include "sun8i_ui_scaler.h" +#include "sun8i_vi_scaler.h" static void sun8i_ui_layer_enable(struct sun8i_mixer *mixer, int channel, int overlay, bool enable, unsigned int zpos, unsigned int old_zpos) { u32 val, bld_base, ch_base; + struct regmap *bld_regs; bld_base = sun8i_blender_base(mixer); + bld_regs = sun8i_blender_regmap(mixer); ch_base = sun8i_channel_base(mixer, channel); DRM_DEBUG_DRIVER("%sabling channel %d overlay %d\n", @@ -47,12 +50,12 @@ static void sun8i_ui_layer_enable(struct sun8i_mixer *mixer, int channel, SUN8I_MIXER_CHAN_UI_LAYER_ATTR_EN, val); if (!enable || zpos != old_zpos) { - regmap_update_bits(mixer->engine.regs, + regmap_update_bits(bld_regs, SUN8I_MIXER_BLEND_PIPE_CTL(bld_base), SUN8I_MIXER_BLEND_PIPE_CTL_EN(old_zpos), 0); - regmap_update_bits(mixer->engine.regs, + regmap_update_bits(bld_regs, SUN8I_MIXER_BLEND_ROUTE(bld_base), SUN8I_MIXER_BLEND_ROUTE_PIPE_MSK(old_zpos), 0); @@ -61,13 +64,13 @@ static void sun8i_ui_layer_enable(struct sun8i_mixer *mixer, int channel, if (enable) { val = SUN8I_MIXER_BLEND_PIPE_CTL_EN(zpos); - regmap_update_bits(mixer->engine.regs, + regmap_update_bits(bld_regs, SUN8I_MIXER_BLEND_PIPE_CTL(bld_base), val, val); val = channel << SUN8I_MIXER_BLEND_ROUTE_PIPE_SHIFT(zpos); - regmap_update_bits(mixer->engine.regs, + regmap_update_bits(bld_regs, SUN8I_MIXER_BLEND_ROUTE(bld_base), SUN8I_MIXER_BLEND_ROUTE_PIPE_MSK(zpos), val); @@ -101,6 +104,7 @@ static int sun8i_ui_layer_update_coord(struct sun8i_mixer *mixer, int channel, { struct drm_plane_state *state = plane->state; u32 src_w, src_h, dst_w, dst_h; + struct regmap *bld_regs; u32 bld_base, ch_base; u32 outsize, insize; u32 hphase, vphase; @@ -109,6 +113,7 @@ static int sun8i_ui_layer_update_coord(struct sun8i_mixer *mixer, int channel, channel, overlay); bld_base = sun8i_blender_base(mixer); + bld_regs = sun8i_blender_regmap(mixer); ch_base = sun8i_channel_base(mixer, channel); src_w = drm_rect_width(&state->src) >> 16; @@ -141,22 +146,33 @@ static int sun8i_ui_layer_update_coord(struct sun8i_mixer *mixer, int channel, hscale = state->src_w / state->crtc_w; vscale = state->src_h / state->crtc_h; - sun8i_ui_scaler_setup(mixer, channel, src_w, src_h, dst_w, - dst_h, hscale, vscale, hphase, vphase); - sun8i_ui_scaler_enable(mixer, channel, true); + if (mixer->cfg->de_type == sun8i_mixer_de33) { + sun8i_vi_scaler_setup(mixer, channel, src_w, src_h, + dst_w, dst_h, hscale, vscale, + hphase, vphase, + state->fb->format); + } else { + sun8i_ui_scaler_setup(mixer, channel, src_w, src_h, + dst_w, dst_h, hscale, vscale, + hphase, vphase); + sun8i_ui_scaler_enable(mixer, channel, true); + } } else { DRM_DEBUG_DRIVER("HW scaling is not needed\n"); - sun8i_ui_scaler_enable(mixer, channel, false); + if (mixer->cfg->de_type == sun8i_mixer_de33) + sun8i_vi_scaler_disable(mixer, channel); + else + sun8i_ui_scaler_enable(mixer, channel, false); } /* Set base coordinates */ DRM_DEBUG_DRIVER("Layer destination coordinates X: %d Y: %d\n", state->dst.x1, state->dst.y1); DRM_DEBUG_DRIVER("Layer destination size W: %d H: %d\n", dst_w, dst_h); - regmap_write(mixer->engine.regs, + regmap_write(bld_regs, SUN8I_MIXER_BLEND_ATTR_COORD(bld_base, zpos), SUN8I_MIXER_COORD(state->dst.x1, state->dst.y1)); - regmap_write(mixer->engine.regs, + regmap_write(bld_regs, SUN8I_MIXER_BLEND_ATTR_INSIZE(bld_base, zpos), outsize); diff --git a/drivers/gpu/drm/sun4i/sun8i_ui_scaler.c b/drivers/gpu/drm/sun4i/sun8i_ui_scaler.c index ae0806bccac7f..504ffa0971a4f 100644 --- a/drivers/gpu/drm/sun4i/sun8i_ui_scaler.c +++ b/drivers/gpu/drm/sun4i/sun8i_ui_scaler.c @@ -93,7 +93,7 @@ static u32 sun8i_ui_scaler_base(struct sun8i_mixer *mixer, int channel) { int vi_num = mixer->cfg->vi_num; - if (mixer->cfg->is_de3) + if (mixer->cfg->de_type == sun8i_mixer_de3) return DE3_VI_SCALER_UNIT_BASE + DE3_VI_SCALER_UNIT_SIZE * vi_num + DE3_UI_SCALER_UNIT_SIZE * (channel - vi_num); diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c index bda91c3e2bb75..d8a97245cfe1e 100644 --- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c +++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c @@ -25,8 +25,10 @@ static void sun8i_vi_layer_enable(struct sun8i_mixer *mixer, int channel, unsigned int old_zpos) { u32 val, bld_base, ch_base; + struct regmap *bld_regs; bld_base = sun8i_blender_base(mixer); + bld_regs = sun8i_blender_regmap(mixer); ch_base = sun8i_channel_base(mixer, channel); DRM_DEBUG_DRIVER("%sabling VI channel %d overlay %d\n", @@ -42,12 +44,12 @@ static void sun8i_vi_layer_enable(struct sun8i_mixer *mixer, int channel, SUN8I_MIXER_CHAN_VI_LAYER_ATTR_EN, val); if (!enable || zpos != old_zpos) { - regmap_update_bits(mixer->engine.regs, + regmap_update_bits(bld_regs, SUN8I_MIXER_BLEND_PIPE_CTL(bld_base), SUN8I_MIXER_BLEND_PIPE_CTL_EN(old_zpos), 0); - regmap_update_bits(mixer->engine.regs, + regmap_update_bits(bld_regs, SUN8I_MIXER_BLEND_ROUTE(bld_base), SUN8I_MIXER_BLEND_ROUTE_PIPE_MSK(old_zpos), 0); @@ -56,13 +58,13 @@ static void sun8i_vi_layer_enable(struct sun8i_mixer *mixer, int channel, if (enable) { val = SUN8I_MIXER_BLEND_PIPE_CTL_EN(zpos); - regmap_update_bits(mixer->engine.regs, + regmap_update_bits(bld_regs, SUN8I_MIXER_BLEND_PIPE_CTL(bld_base), val, val); val = channel << SUN8I_MIXER_BLEND_ROUTE_PIPE_SHIFT(zpos); - regmap_update_bits(mixer->engine.regs, + regmap_update_bits(bld_regs, SUN8I_MIXER_BLEND_ROUTE(bld_base), SUN8I_MIXER_BLEND_ROUTE_PIPE_MSK(zpos), val); @@ -76,7 +78,7 @@ static void sun8i_vi_layer_update_alpha(struct sun8i_mixer *mixer, int channel, ch_base = sun8i_channel_base(mixer, channel); - if (mixer->cfg->is_de3) { + if (mixer->cfg->de_type >= sun8i_mixer_de3) { mask = SUN50I_MIXER_CHAN_VI_LAYER_ATTR_ALPHA_MASK | SUN50I_MIXER_CHAN_VI_LAYER_ATTR_ALPHA_MODE_MASK; val = SUN50I_MIXER_CHAN_VI_LAYER_ATTR_ALPHA @@ -106,6 +108,7 @@ static int sun8i_vi_layer_update_coord(struct sun8i_mixer *mixer, int channel, struct drm_plane_state *state = plane->state; const struct drm_format_info *format = state->fb->format; u32 src_w, src_h, dst_w, dst_h; + struct regmap *bld_regs; u32 bld_base, ch_base; u32 outsize, insize; u32 hphase, vphase; @@ -117,6 +120,7 @@ static int sun8i_vi_layer_update_coord(struct sun8i_mixer *mixer, int channel, channel, overlay); bld_base = sun8i_blender_base(mixer); + bld_regs = sun8i_blender_regmap(mixer); ch_base = sun8i_channel_base(mixer, channel); src_w = drm_rect_width(&state->src) >> 16; @@ -207,10 +211,9 @@ static int sun8i_vi_layer_update_coord(struct sun8i_mixer *mixer, int channel, sun8i_vi_scaler_setup(mixer, channel, src_w, src_h, dst_w, dst_h, hscale, vscale, hphase, vphase, format); - sun8i_vi_scaler_enable(mixer, channel, true); } else { DRM_DEBUG_DRIVER("HW scaling is not needed\n"); - sun8i_vi_scaler_enable(mixer, channel, false); + sun8i_vi_scaler_disable(mixer, channel); } regmap_write(mixer->engine.regs, @@ -234,10 +237,10 @@ static int sun8i_vi_layer_update_coord(struct sun8i_mixer *mixer, int channel, DRM_DEBUG_DRIVER("Layer destination coordinates X: %d Y: %d\n", state->dst.x1, state->dst.y1); DRM_DEBUG_DRIVER("Layer destination size W: %d H: %d\n", dst_w, dst_h); - regmap_write(mixer->engine.regs, + regmap_write(bld_regs, SUN8I_MIXER_BLEND_ATTR_COORD(bld_base, zpos), SUN8I_MIXER_COORD(state->dst.x1, state->dst.y1)); - regmap_write(mixer->engine.regs, + regmap_write(bld_regs, SUN8I_MIXER_BLEND_ATTR_INSIZE(bld_base, zpos), outsize); @@ -410,7 +413,7 @@ static void sun8i_vi_layer_atomic_disable(struct drm_plane *plane, sun8i_vi_layer_enable(mixer, layer->channel, layer->overlay, false, 0, old_zpos); - if (mixer->cfg->is_de3) + if (mixer->cfg->de_type >= sun8i_mixer_de3) sun50i_afbc_disable(mixer, layer->channel); } @@ -431,7 +434,7 @@ static void sun8i_vi_layer_atomic_update(struct drm_plane *plane, if (!new_state->visible) { sun8i_vi_layer_enable(mixer, layer->channel, layer->overlay, false, 0, old_zpos); - if (mixer->cfg->is_de3) + if (mixer->cfg->de_type >= sun8i_mixer_de3) sun50i_afbc_disable(mixer, layer->channel); return; } @@ -448,7 +451,7 @@ static void sun8i_vi_layer_atomic_update(struct drm_plane *plane, plane->state->color_encoding, plane->state->color_range); } else { - if (mixer->cfg->is_de3) + if (mixer->cfg->de_type >= sun8i_mixer_de3) sun50i_afbc_disable(mixer, layer->channel); sun8i_vi_layer_update_alpha(mixer, layer->channel, layer->overlay, plane); @@ -612,7 +615,7 @@ struct sun8i_vi_layer *sun8i_vi_layer_init_one(struct drm_device *drm, layer->channel = index; layer->overlay = 0; - if (mixer->cfg->is_de3) { + if (mixer->cfg->de_type >= sun8i_mixer_de3) { formats = sun8i_vi_layer_de3_formats; format_count = ARRAY_SIZE(sun8i_vi_layer_de3_formats); modifiers = sun50i_layer_de3_modifiers; @@ -637,7 +640,7 @@ struct sun8i_vi_layer *sun8i_vi_layer_init_one(struct drm_device *drm, plane_cnt = mixer->cfg->ui_num + mixer->cfg->vi_num; - if (mixer->cfg->vi_num == 1 || mixer->cfg->is_de3) { + if (mixer->cfg->vi_num == 1 || mixer->cfg->de_type >= sun8i_mixer_de3) { ret = drm_plane_create_alpha_property(&layer->plane); if (ret) { dev_err(drm->dev, "Couldn't add alpha property\n"); @@ -654,7 +657,7 @@ struct sun8i_vi_layer *sun8i_vi_layer_init_one(struct drm_device *drm, supported_encodings = BIT(DRM_COLOR_YCBCR_BT601) | BIT(DRM_COLOR_YCBCR_BT709); - if (mixer->cfg->is_de3) + if (mixer->cfg->de_type >= sun8i_mixer_de3) supported_encodings |= BIT(DRM_COLOR_YCBCR_BT2020); supported_ranges = BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) | diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_scaler.c b/drivers/gpu/drm/sun4i/sun8i_vi_scaler.c index 7ba75011adf9f..9c7f6e7d71d50 100644 --- a/drivers/gpu/drm/sun4i/sun8i_vi_scaler.c +++ b/drivers/gpu/drm/sun4i/sun8i_vi_scaler.c @@ -835,7 +835,9 @@ static const u32 bicubic4coefftab32[480] = { static u32 sun8i_vi_scaler_base(struct sun8i_mixer *mixer, int channel) { - if (mixer->cfg->is_de3) + if (mixer->cfg->de_type == sun8i_mixer_de33) + return sun8i_channel_base(mixer, channel) + 0x3000; + else if (mixer->cfg->de_type == sun8i_mixer_de3) return DE3_VI_SCALER_UNIT_BASE + DE3_VI_SCALER_UNIT_SIZE * channel; else @@ -843,6 +845,14 @@ static u32 sun8i_vi_scaler_base(struct sun8i_mixer *mixer, int channel) DE2_VI_SCALER_UNIT_SIZE * channel; } +static bool sun8i_vi_scaler_is_vi_plane(struct sun8i_mixer *mixer, int channel) +{ + if (mixer->cfg->de_type == sun8i_mixer_de33) + return mixer->cfg->map[channel] < mixer->cfg->vi_num; + + return true; +} + static int sun8i_vi_scaler_coef_index(unsigned int step) { unsigned int scale, int_part, float_part; @@ -867,60 +877,74 @@ static int sun8i_vi_scaler_coef_index(unsigned int step) } } -static void sun8i_vi_scaler_set_coeff(struct regmap *map, u32 base, - u32 hstep, u32 vstep, - const struct drm_format_info *format) +static void sun8i_vi_scaler_set_coeff_vi(struct regmap *map, u32 base, + u32 hstep, u32 vstep, + const struct drm_format_info *format) { const u32 *ch_left, *ch_right, *cy; - int offset, i; + int offset; - if (format->hsub == 1 && format->vsub == 1) { - ch_left = lan3coefftab32_left; - ch_right = lan3coefftab32_right; - cy = lan2coefftab32; - } else { + if (format->is_yuv) { ch_left = bicubic8coefftab32_left; ch_right = bicubic8coefftab32_right; cy = bicubic4coefftab32; + } else { + ch_left = lan3coefftab32_left; + ch_right = lan3coefftab32_right; + cy = lan2coefftab32; } offset = sun8i_vi_scaler_coef_index(hstep) * SUN8I_VI_SCALER_COEFF_COUNT; - for (i = 0; i < SUN8I_VI_SCALER_COEFF_COUNT; i++) { - regmap_write(map, SUN8I_SCALER_VSU_YHCOEFF0(base, i), - lan3coefftab32_left[offset + i]); - regmap_write(map, SUN8I_SCALER_VSU_YHCOEFF1(base, i), - lan3coefftab32_right[offset + i]); - regmap_write(map, SUN8I_SCALER_VSU_CHCOEFF0(base, i), - ch_left[offset + i]); - regmap_write(map, SUN8I_SCALER_VSU_CHCOEFF1(base, i), - ch_right[offset + i]); - } + regmap_bulk_write(map, SUN8I_SCALER_VSU_YHCOEFF0(base, 0), + &lan3coefftab32_left[offset], + SUN8I_VI_SCALER_COEFF_COUNT); + regmap_bulk_write(map, SUN8I_SCALER_VSU_YHCOEFF1(base, 0), + &lan3coefftab32_right[offset], + SUN8I_VI_SCALER_COEFF_COUNT); + regmap_bulk_write(map, SUN8I_SCALER_VSU_CHCOEFF0(base, 0), + &ch_left[offset], SUN8I_VI_SCALER_COEFF_COUNT); + regmap_bulk_write(map, SUN8I_SCALER_VSU_CHCOEFF1(base, 0), + &ch_right[offset], SUN8I_VI_SCALER_COEFF_COUNT); offset = sun8i_vi_scaler_coef_index(hstep) * SUN8I_VI_SCALER_COEFF_COUNT; - for (i = 0; i < SUN8I_VI_SCALER_COEFF_COUNT; i++) { - regmap_write(map, SUN8I_SCALER_VSU_YVCOEFF(base, i), - lan2coefftab32[offset + i]); - regmap_write(map, SUN8I_SCALER_VSU_CVCOEFF(base, i), - cy[offset + i]); - } + regmap_bulk_write(map, SUN8I_SCALER_VSU_YVCOEFF(base, 0), + &lan2coefftab32[offset], SUN8I_VI_SCALER_COEFF_COUNT); + regmap_bulk_write(map, SUN8I_SCALER_VSU_CVCOEFF(base, 0), + &cy[offset], SUN8I_VI_SCALER_COEFF_COUNT); } -void sun8i_vi_scaler_enable(struct sun8i_mixer *mixer, int layer, bool enable) +static void sun8i_vi_scaler_set_coeff_ui(struct regmap *map, u32 base, + u32 hstep, u32 vstep, + const struct drm_format_info *format) { - u32 val, base; + const u32 *table; + int offset; - base = sun8i_vi_scaler_base(mixer, layer); + offset = sun8i_vi_scaler_coef_index(hstep) * + SUN8I_VI_SCALER_COEFF_COUNT; + regmap_bulk_write(map, SUN8I_SCALER_VSU_YHCOEFF0(base, 0), + &lan2coefftab32[offset], SUN8I_VI_SCALER_COEFF_COUNT); + offset = sun8i_vi_scaler_coef_index(vstep) * + SUN8I_VI_SCALER_COEFF_COUNT; + regmap_bulk_write(map, SUN8I_SCALER_VSU_YVCOEFF(base, 0), + &lan2coefftab32[offset], SUN8I_VI_SCALER_COEFF_COUNT); - if (enable) - val = SUN8I_SCALER_VSU_CTRL_EN | - SUN8I_SCALER_VSU_CTRL_COEFF_RDY; - else - val = 0; + table = format->is_yuv ? bicubic4coefftab32 : lan2coefftab32; + offset = sun8i_vi_scaler_coef_index(hstep) * + SUN8I_VI_SCALER_COEFF_COUNT; + regmap_bulk_write(map, SUN8I_SCALER_VSU_CHCOEFF0(base, 0), + &table[offset], SUN8I_VI_SCALER_COEFF_COUNT); +} - regmap_write(mixer->engine.regs, - SUN8I_SCALER_VSU_CTRL(base), val); +void sun8i_vi_scaler_disable(struct sun8i_mixer *mixer, int layer) +{ + u32 base; + + base = sun8i_vi_scaler_base(mixer, layer); + + regmap_write(mixer->engine.regs, SUN8I_SCALER_VSU_CTRL(base), 0); } void sun8i_vi_scaler_setup(struct sun8i_mixer *mixer, int layer, @@ -956,7 +980,10 @@ void sun8i_vi_scaler_setup(struct sun8i_mixer *mixer, int layer, cvphase = vphase; } - if (mixer->cfg->is_de3) { + regmap_write(mixer->engine.regs, SUN8I_SCALER_VSU_CTRL(base), + SUN8I_SCALER_VSU_CTRL_EN); + + if (mixer->cfg->de_type >= sun8i_mixer_de3) { u32 val; if (format->hsub == 1 && format->vsub == 1) @@ -994,6 +1021,16 @@ void sun8i_vi_scaler_setup(struct sun8i_mixer *mixer, int layer, SUN8I_SCALER_VSU_CHPHASE(base), chphase); regmap_write(mixer->engine.regs, SUN8I_SCALER_VSU_CVPHASE(base), cvphase); - sun8i_vi_scaler_set_coeff(mixer->engine.regs, base, - hscale, vscale, format); + + if (sun8i_vi_scaler_is_vi_plane(mixer, layer)) + sun8i_vi_scaler_set_coeff_vi(mixer->engine.regs, base, + hscale, vscale, format); + else + sun8i_vi_scaler_set_coeff_ui(mixer->engine.regs, base, + hscale, vscale, format); + + if (mixer->cfg->de_type <= sun8i_mixer_de3) + regmap_write(mixer->engine.regs, SUN8I_SCALER_VSU_CTRL(base), + SUN8I_SCALER_VSU_CTRL_EN | + SUN8I_SCALER_VSU_CTRL_COEFF_RDY); } diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_scaler.h b/drivers/gpu/drm/sun4i/sun8i_vi_scaler.h index 68f6593b369ab..9fe056a2c1c79 100644 --- a/drivers/gpu/drm/sun4i/sun8i_vi_scaler.h +++ b/drivers/gpu/drm/sun4i/sun8i_vi_scaler.h @@ -34,6 +34,7 @@ #define SUN50I_SCALER_VSU_EDSCL_CTRL(base) ((base) + 0x28) #define SUN50I_SCALER_VSU_ANGLE_THR(base) ((base) + 0x2c) #define SUN8I_SCALER_VSU_OUTSIZE(base) ((base) + 0x40) +#define SUN50I_SCALER_VSU_GLB_ALPHA(base) ((base) + 0x44) #define SUN8I_SCALER_VSU_YINSIZE(base) ((base) + 0x80) #define SUN8I_SCALER_VSU_YHSTEP(base) ((base) + 0x88) #define SUN8I_SCALER_VSU_YVSTEP(base) ((base) + 0x8c) @@ -69,7 +70,7 @@ #define SUN50I_SCALER_VSU_ANGLE_SHIFT(x) (((x) << 16) & 0xF) #define SUN50I_SCALER_VSU_ANGLE_OFFSET(x) ((x) & 0xFF) -void sun8i_vi_scaler_enable(struct sun8i_mixer *mixer, int layer, bool enable); +void sun8i_vi_scaler_disable(struct sun8i_mixer *mixer, int layer); void sun8i_vi_scaler_setup(struct sun8i_mixer *mixer, int layer, u32 src_w, u32 src_h, u32 dst_w, u32 dst_h, u32 hscale, u32 vscale, u32 hphase, u32 vphase,