From patchwork Tue Feb 7 16:49:46 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mihail Atanassov X-Patchwork-Id: 9560641 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id ACEE260434 for ; Tue, 7 Feb 2017 16:49:56 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 9DAC128425 for ; Tue, 7 Feb 2017 16:49:56 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 916B128427; Tue, 7 Feb 2017 16:49:56 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.1 required=2.0 tests=BAD_ENC_HEADER,BAYES_00, DKIM_SIGNED, RCVD_IN_DNSWL_MED, T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id A579A28425 for ; Tue, 7 Feb 2017 16:49:55 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id E145D89B67; Tue, 7 Feb 2017 16:49:53 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from EUR01-DB5-obe.outbound.protection.outlook.com (mail-db5eur01on0087.outbound.protection.outlook.com [104.47.2.87]) by gabe.freedesktop.org (Postfix) with ESMTPS id B668E89B67 for ; Tue, 7 Feb 2017 16:49:52 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=armh.onmicrosoft.com; s=selector1-arm-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version; bh=XtpHnCGnMKCOuCONJwkEUsCvHsXUUohj7nPOyYJiy6E=; b=czmQZOsVSbX6ofRQNVnzUC4CGs7bjMb2IJNApOO7xYG3kgkKFFXkMtl8VQTEgcKD6eQE23Co+MmWesZo24Xzeh2CYkY2O0MZDTnXp2zlpvJNRsW0jXP2GX+HXVgQLJAnCuKFmVHVcnnls0ZOJ2S3r1FGx8m9q8k+vdXAGVXzc44= Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=Mihail.Atanassov@arm.com; Received: from e110433-lin.cambridge.arm.com (217.140.96.140) by AM4PR08MB0884.eurprd08.prod.outlook.com (10.164.83.30) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P384) id 15.1.888.16; Tue, 7 Feb 2017 16:49:49 +0000 From: Mihail Atanassov To: Subject: [PATCH v3 2/2] drm: mali-dp: enable gamma support Date: Tue, 7 Feb 2017 16:49:46 +0000 Message-ID: <1486486186-29545-2-git-send-email-mihail.atanassov@arm.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1486486186-29545-1-git-send-email-mihail.atanassov@arm.com> References: <1486486186-29545-1-git-send-email-mihail.atanassov@arm.com> MIME-Version: 1.0 X-Originating-IP: [217.140.96.140] X-ClientProxiedBy: DB5PR08CA0029.eurprd08.prod.outlook.com (10.163.102.167) To AM4PR08MB0884.eurprd08.prod.outlook.com (10.164.83.30) X-MS-Office365-Filtering-Correlation-Id: bae6da0f-e395-4bb6-3146-08d44f7954ea X-MS-Office365-Filtering-HT: Tenant X-Microsoft-Antispam: UriScan:; BCL:0; PCL:0; RULEID:(22001)(48565401081); SRVR:AM4PR08MB0884; X-Microsoft-Exchange-Diagnostics: 1; AM4PR08MB0884; 3:R8Pa8KkakWXSLwEANPKPUgSKgrnQ8EjFGgeE31OmQ9Qr9GReTplvTz59aNX9gWwIk58+u4LR4rWeO+FoE0EHa3160p4EV44gF6MythdCa5syPI5gzlY4TV2g4NZHQQemwGoFQf6SazGXJJzDUPl4jp1QNMBonrlA/HktJCVNavY4TPFUGYVCzFqdi1+KbBBuF3m6lAOPGYLlSD/qLEkaBXAf9CK9742ZVkXJFYrZ/ugSmkx/NnUA+uyEALY+yJKbfFzB6qYrtKHpy7779FdDHpRquqF4tl0iOt7Z5PUK/mE=; 25:V4FeZymnGbFqiAZWQ/T5mh+YNUY4EzqELP+4hrgutbsJ2aZ068rt4MzjG5hFaEnP+NPPgD/0q756D3zlrZv5R2WW659qK2YcHFW4HogkOiYhf/Lw7psmjHeEPrisKEr7sy3HAeb5/bSDlsgtWPrYfoBBJdhW9XfuWQJjNHnq+4wiP1sQVWhONYg+h4EP5M7jiF2UQlemDMR58ktCz1YmkpVInH9Li1aGUynvLg5m4V+9wAdaK5ZjwcvORMsDLm+WjpwYijF2ptz7Q1c7CFvv0pvnkj9zTRoBtYy068cXrcxW2ACEQ6pGIocxj17nbx8UtCqt3D4NAkRaRBnQ2NblXu1U2P5uDocRZd0JGRXH5/FL9ZQaNaPnofXlx/dqi+9q7xXzT4WppVHG0ArRwAHqx7tD9llHQUre5f3W1yovopoY7llp+3AOnf5pxrPUDfeteb4M9KsfWCQJM5Ad+Koj+Q== X-Microsoft-Exchange-Diagnostics: 1; AM4PR08MB0884; 31:PRfs7DXMfRkj3UcSXq/jxzCI/K3zobDPy/2F30xyXwtLGvrl0hBEROhJ2lsNfbDBnNUrCy8/IDFGsK/Zkfii3dIg44BNDjzNpaLzCQMlkQf+qIjHQWtKilQ5YmwwRyE7h0waTQTTUL5BCMgXDggu3KSrKNSedrlbOTpmrg2U4S8uk7ZB2nKjz8RP+SxrY19sOulHvNUpmFdoibHaJBkTyXjPI2h8W0Ocf0mrde2HGywiq4F18R3M/sbB5G/tgnfLu/i39VE67Z41bliIY7suBg==; 20:8SPLz4OfxQ5CTsBw0T837HsWYADpplwln5WE0veZAhEHRd+pdhRNrsAcUQDf9ToptMrIh/TJ41u+dBfINRLW088AGScErG927bbZ+qhdMVL33d07p+i2lGlzXTnn0th06Ra8z68oHdFWSsy260hJKlbXSWXp8tY1UL5QSrM7mi8= NoDisclaimer: True X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:(180628864354917); X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(6040375)(601004)(2401047)(5005006)(2017020603029)(20170203043)(8121501046)(3002001)(10201501046)(6055026)(6041248)(20161123558025)(20161123564025)(20161123560025)(20161123555025)(20161123562025)(6072148); SRVR:AM4PR08MB0884; BCL:0; PCL:0; RULEID:; SRVR:AM4PR08MB0884; X-Microsoft-Exchange-Diagnostics: 1; AM4PR08MB0884; 4:mEf3lklZ0rc5rml3Q9EMrVtF6ukEsuH+ibRX2CugE9dockbt/k2XkRQh9esZVf8yGnKcYh7gL6zbrW66uVUA+ddvNWovhf9wDKiCeNrN6oqgwkGcaoPo71/q6uTtyp8KxOfH7sd7Sp0ac7XizRY2nS7Jx7NqMaoZSQVJC69xf6ijfnoN0w4PqpHDILy9eYup1Br7AeyfY6nO0qymtmpmwMOyqIN1IjPUFw7uetms8lsYm4RNT6kqLtabT85fQYjeTfn5364eiWed3kzZDU1Tk4ecbc9lv5V5CD7vwNpGI2q+4TEBfFxEkOb0KVnCmkWxyf9SoytZ6yg6jDiUyJhIQsGc5rSYZtkc5sPFFalwX8V83ZHoaw8bJqYhR/4j92bmwpdVe3jaxHxl20cAeA4QWfma+MEtgv59kiMM/VqLRIgZbXR0ur5f26GuiR2O82ey7u2MvcJlWTE19Q0p1GHdZ3HD9IIeUOJ9XgMXcXSGT52dMqrGIt6JHica78+wwutOCiPh+pAzZgtti1REQ3x5gSDRAdd+/uh9QtD2N77PTkb/xsSacPHfvnIki6Iq/a/8vndrX6gD645EhqaUUrRojYNhN3FfpDD9DniyElSNHSYxcGL+Kay3r4I3FWDSOATFSzjYI+crJjPgWnVSTVayf3quPSOm0bdlfIHOMBN6ib8Dtho38Cpx5HfwtUbumej9XBFYGvWfXS8v2wKV6SmdnCcyBhOADb9MeeX99o1ygdI= X-Forefront-PRVS: 0211965D06 X-Forefront-Antispam-Report: SFV:NSPM; SFS:(10009020)(4630300001)(6009001)(7916002)(39850400002)(39840400002)(39860400002)(39450400003)(39410400002)(199003)(189002)(25786008)(66066001)(50466002)(6486002)(86362001)(101416001)(76176999)(47776003)(50986999)(54906002)(36756003)(53936002)(68736007)(50226002)(106356001)(48376002)(110136004)(105586002)(2351001)(42186005)(8676002)(92566002)(4326007)(81156014)(6916009)(38730400002)(2950100002)(6666003)(81166006)(189998001)(305945005)(3846002)(6116002)(7736002)(5003940100001)(33646002)(2906002)(97736004)(5660300001); DIR:OUT; SFP:1101; SCL:1; SRVR:AM4PR08MB0884; H:e110433-lin.cambridge.arm.com; FPR:; SPF:None; PTR:InfoNoRecords; A:1; MX:1; LANG:en; Received-SPF: None (protection.outlook.com: arm.com does not designate permitted sender hosts) X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1; AM4PR08MB0884; 23:I85Q+4ShNHif1Y5p2uopiLAP9/fCbpk1pmKsbemKm?= =?us-ascii?Q?VDxnRe56uSB2qbnH6ZMKfrzbLaEn2pAii87fXM4k2oa5c7yZ5AgyOb98Bh4k?= =?us-ascii?Q?nzQ34V8b0xU0Xu4VT7qR+z3afkkDINsBrXLRZdfKXVW+6wWZu5+tBc55jHB/?= =?us-ascii?Q?obWUTpZsLP5pM2KUAATZEJJeH7K7KIoCTIE4LyiNP3dqplQuzyvDVXV28COX?= =?us-ascii?Q?KCTqn+HelaJINRISzaBOMrH5Ixigd6kgveeN687PB/HVfNis5drNT7nNYgiC?= =?us-ascii?Q?4k1O23fcWLAQ0KfDGVOGBq+xDoTe8s7drWEF+Y1mtBN31UqCz0Z//ikMR+GI?= =?us-ascii?Q?DlYWfzOjViShxWmAirMEQ2raJzLjJRD7Z+dqagU9k7KJhbwsL35brCRS+l+A?= =?us-ascii?Q?gcwC0qnSRZp3+wr5UQTlwDg7SiN4KPEN/VxOJ1MSHTNAUXFE06kucbpLrtzY?= =?us-ascii?Q?VyhX1ANEtJ9Styrc/xtb9XMIhreoS9uLqqRKD8t1vkQ2SfXFVOaLQqmElhvD?= =?us-ascii?Q?hdrXhOgGyf0828rvNkbi4kfpCyTtord186ZxSH0L0Z65Usos9hoOiIa2A7gx?= =?us-ascii?Q?klE57vutZKsFfohqtWeWDpM3mYWidxjoFrAWvA5poGdJ2aSrAGDo3IzwlHkd?= =?us-ascii?Q?o178MbxBl8lm8Hk35hUQiXL8LJChTFB9Xub+BJUoY18q9ZHvSBS9YaimeByG?= =?us-ascii?Q?8nghmkm49dVKlxy3kEzrpd6URUXFaeb6yxirpZMYjQIO9WhEAU716r+w2zOn?= =?us-ascii?Q?ahMdwwIaleEtw99SNkYGjcNmKKFqk6v6j3L8svHxGXJmmgno8kG8h5gg2J8f?= =?us-ascii?Q?W6woLUiSkhvgwLPyf9mlBnvihmugvFqhl15R/ONwdAAbUdvXl1/pKOWesV90?= =?us-ascii?Q?dywCUppcOnyOlbvR+tofgSd+JWLsrecmooJhL/nDZ8tzOXKz3kfWpKzVFKVz?= =?us-ascii?Q?a3mot4EsW6oN1j9tQ82/AIFV2IFTaoOnLSXG3eyxSs828J9afPuVUJKNCQkB?= =?us-ascii?Q?hxW5NsUWmRE6BRsg3LicBUQX6vQRT7hK0mo4JiCfU48l+MxZACnUY2exE/xH?= =?us-ascii?Q?lJZZHStvEt0/q8sTGSVVK+KTH36gQ1eYcG9GW1bilZ3PgcO5L9rFccWDMOAz?= =?us-ascii?Q?ffVgnDwKMuwS69JSWz6BO6d5JrYpVe3j6cTUM4MEGoO67yfDCvkcPkV9Gb9a?= =?us-ascii?Q?nS8Qs8jPGXh1wUp4B0+alRaJL2vcJ6q9pvh?= X-Microsoft-Exchange-Diagnostics: 1; AM4PR08MB0884; 6:u2/k0JEd6OIE1v6fyhgRg20wPeQK3XLrGslvVPxIfoiWu2IILJnC0x13hy9RSyS3KBDuFzhttT+pyNL3zkKM87mP3ef/nAR/cT6nUH+T8judIIuY/UeDDJ6TO4IK4vcvo2ycoWJcCHEIXplbLIAUTaPSwlLapZsNhVkSDgfksTGs8/+hamAirEGPnaf4LraatJkPgV+FYRDoaJGcPZ4NzvlQwhl7Q8YvDurb3D7OW584qn6trp+5jybJfeUAcbs2T/ImajT45bqSRqGcAcHmaVCn+tRft1jy1vQ6DY8+di4wHQNFEQ9DXwFhrrPn550KKNjDszdZdzxnwe5p1IXt1iRvqW1Sc5WydDwoLzmZG1aEqhRcbq824BsvXBJ04RD4LJB35uj+s9afGLGlBAG9fejuGkSmVyyAl9ZI46Fz+9I=; 5:1euda0Qtqdwya6rbgBBQtrDQJwHen0hKOaZi5mjinGzTnacCkfWD7hhYOtuQmp7yQJAEWT8cEUMbrqPhy5sRzvbhozOUar4moVPhtITUr8Wh1gVHnA6Eda2rahP1ao8qkIkqDWKs9I/rmFLcYbHP374eDYofQ2TYV+SXB+/CqOs=; 24:fvGxEsN+wsMpMuHfO/nIvSg+pIto6TSmCyHI9lYNY4J/IIF+HHUswnI0D9yWqYkXZfux5PAiEA+tLCV4BlX8qVpEyhPcA8C4cBsiLeevL1s= SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-Microsoft-Exchange-Diagnostics: 1; AM4PR08MB0884; 7:a3zxCEgWK6AP3lv+IAAcWpTkN0qMfCYIDcezw2a++ujwY9x5fBFEatGf7oQdYIOvP/0bIp6HVOWl5JvJrmKs27NTckvs3vXkA2YQIYxWdAJpIdCAbiA05jGIYWQJQPUMK7BT++2iHf+lTScRVtdmRWZS+k3OILbSv1XyZJV3ctab44DhZ0JvpgcNUsowief72iCJ/NoMby5h6KM9kl8TRCi5Eio2iKHQuao0hRyb7enaQUzIdTCY9Wj23bTk7niXeMghHvLdG9XTWcRELypaCaWkEB2rtIuxF6kd7MTcJDjMZBeacUKQN3g/KVGsgHsz31Aex9iRv5I5qSviLLeuzsgNNoS41scAVIa3bbfzlPLdwHIBX4o25/NdE/7rRz2TNVwSh4eVTD1/QLZiFMzDz8EQ403G7IM3zDthazGIBw9mXc4ejwHIz7hXgj9Aqpp/LclE8Dt/MX2M1gZ56ohWVNis0i1I0pmfKm4lXC1cyZ1uZs/BnKjFGwdkwkifbJW9PIk4VwyHuGvkwPWQJmD/CA== X-OriginatorOrg: arm.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 07 Feb 2017 16:49:49.6447 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-Transport-CrossTenantHeadersStamped: AM4PR08MB0884 Cc: Liviu Dudau , linux-kernel@vger.kernel.org, Mali DP Maintainers , nd@arm.com X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.18 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" X-Virus-Scanned: ClamAV using ClamSMTP Add gamma via the DRM GAMMA_LUT/GAMMA_LUT_SIZE CRTC properties. The expected LUT size is 4096 in order to produce as accurate a set of segments as possible. This version uses only the green channel's gamma curve to set the hardware curve on DP550/650. For the sake of simplicity, it uses the same table of coefficients for all 3 curves on DP500. Signed-off-by: Mihail Atanassov Reviewed-by: Brian Starkey Acked-by: Liviu Dudau --- drivers/gpu/drm/arm/malidp_crtc.c | 130 ++++++++++++++++++++++++++++++++++++-- drivers/gpu/drm/arm/malidp_drv.c | 52 +++++++++++++++ drivers/gpu/drm/arm/malidp_drv.h | 1 + drivers/gpu/drm/arm/malidp_hw.c | 3 + drivers/gpu/drm/arm/malidp_hw.h | 2 + drivers/gpu/drm/arm/malidp_regs.h | 19 ++++-- 6 files changed, 196 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/arm/malidp_crtc.c b/drivers/gpu/drm/arm/malidp_crtc.c index ebf57e6..6a46520 100644 --- a/drivers/gpu/drm/arm/malidp_crtc.c +++ b/drivers/gpu/drm/arm/malidp_crtc.c @@ -21,6 +21,8 @@ #include "malidp_drv.h" #include "malidp_hw.h" +#define MALIDP_GAMMA_LUT_SIZE 4096 + static bool malidp_crtc_mode_fixup(struct drm_crtc *crtc, const struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) @@ -82,6 +84,114 @@ static void malidp_crtc_disable(struct drm_crtc *crtc) clk_disable_unprepare(hwdev->pxlclk); } +static const struct gamma_curve_segment { + u16 start; + u16 end; +} segments[MALIDP_COEFFTAB_NUM_COEFFS] = { + /* sector 0 */ + { 0, 0 }, { 1, 1 }, { 2, 2 }, { 3, 3 }, + { 4, 4 }, { 5, 5 }, { 6, 6 }, { 7, 7 }, + { 8, 8 }, { 9, 9 }, { 10, 10 }, { 11, 11 }, + { 12, 12 }, { 13, 13 }, { 14, 14 }, { 15, 15 }, + /* sector 1 */ + { 16, 19 }, { 20, 23 }, { 24, 27 }, { 28, 31 }, + /* sector 2 */ + { 32, 39 }, { 40, 47 }, { 48, 55 }, { 56, 63 }, + /* sector 3 */ + { 64, 79 }, { 80, 95 }, { 96, 111 }, { 112, 127 }, + /* sector 4 */ + { 128, 159 }, { 160, 191 }, { 192, 223 }, { 224, 255 }, + /* sector 5 */ + { 256, 319 }, { 320, 383 }, { 384, 447 }, { 448, 511 }, + /* sector 6 */ + { 512, 639 }, { 640, 767 }, { 768, 895 }, { 896, 1023 }, + { 1024, 1151 }, { 1152, 1279 }, { 1280, 1407 }, { 1408, 1535 }, + { 1536, 1663 }, { 1664, 1791 }, { 1792, 1919 }, { 1920, 2047 }, + { 2048, 2175 }, { 2176, 2303 }, { 2304, 2431 }, { 2432, 2559 }, + { 2560, 2687 }, { 2688, 2815 }, { 2816, 2943 }, { 2944, 3071 }, + { 3072, 3199 }, { 3200, 3327 }, { 3328, 3455 }, { 3456, 3583 }, + { 3584, 3711 }, { 3712, 3839 }, { 3840, 3967 }, { 3968, 4095 }, +}; + +#define DE_COEFTAB_DATA(a, b) ((((a) & 0xfff) << 16) | (((b) & 0xfff))) + +static void malidp_generate_gamma_table(struct drm_property_blob *lut_blob, + u32 coeffs[MALIDP_COEFFTAB_NUM_COEFFS]) +{ + struct drm_color_lut *lut = (struct drm_color_lut *)lut_blob->data; + int i; + + for (i = 0; i < MALIDP_COEFFTAB_NUM_COEFFS; ++i) { + u32 a, b; + u32 delta_in; + u32 out_start, out_end; + + delta_in = segments[i].end - segments[i].start; + /* DP has 12-bit internal precision for its LUTs. */ + out_start = drm_color_lut_extract(lut[segments[i].start].green, + 12); + out_end = drm_color_lut_extract(lut[segments[i].end].green, 12); + a = (delta_in == 0) ? + 0 : ((out_end - out_start) * 256) / delta_in; + b = out_start; + coeffs[i] = DE_COEFTAB_DATA(a, b); + } +} + +/* + * Check if there is a new gamma LUT and if it is of an acceptable size. Also, + * reject any LUTs that use distinct red, green, and blue curves. + */ +static int malidp_crtc_atomic_check_gamma(struct drm_crtc *crtc, + struct drm_crtc_state *state) +{ + struct malidp_crtc_state *mc = to_malidp_crtc_state(state); + struct drm_color_lut *lut; + size_t lut_size; + int i; + + if (!state->color_mgmt_changed) + return 0; + + if (!state->gamma_lut) + return 0; + + if (crtc->state->gamma_lut && (crtc->state->gamma_lut->base.id == + state->gamma_lut->base.id)) + return 0; + + if (state->gamma_lut->length % sizeof(struct drm_color_lut)) + return -EINVAL; + + lut_size = state->gamma_lut->length / sizeof(struct drm_color_lut); + if (lut_size != MALIDP_GAMMA_LUT_SIZE) + return -EINVAL; + + lut = (struct drm_color_lut *)state->gamma_lut->data; + for (i = 0; i < lut_size; ++i) + if (!((lut[i].red == lut[i].green) && + (lut[i].red == lut[i].blue))) + return -EINVAL; + + if (!state->mode_changed) { + int ret; + + state->mode_changed = true; + /* + * Kerneldoc for drm_atomic_helper_check_modeset mandates that + * it be invoked when the driver sets ->mode_changed. Since + * changing the gamma LUT Doesn't depend on any external + * resources, it is safe to call it only once. + */ + ret = drm_atomic_helper_check_modeset(crtc->dev, state->state); + if (ret) + return ret; + } + + malidp_generate_gamma_table(state->gamma_lut, mc->gamma_coeffs); + return 0; +} + static int malidp_crtc_atomic_check(struct drm_crtc *crtc, struct drm_crtc_state *state) { @@ -91,6 +201,7 @@ static int malidp_crtc_atomic_check(struct drm_crtc *crtc, const struct drm_plane_state *pstate; u32 rot_mem_free, rot_mem_usable; int rotated_planes = 0; + int ret; /* * check if there is enough rotation memory available for planes @@ -157,21 +268,26 @@ static int malidp_crtc_atomic_check(struct drm_crtc *crtc, } } - return 0; + ret = malidp_crtc_atomic_check_gamma(crtc, state); + + return ret; } static struct drm_crtc_state *malidp_crtc_duplicate_state(struct drm_crtc *crtc) { + struct malidp_crtc_state *cs; struct malidp_crtc_state *state; if (WARN_ON(!crtc->state)) return NULL; + cs = to_malidp_crtc_state(crtc->state); state = kmalloc(sizeof(*state), GFP_KERNEL); if (!state) return NULL; __drm_atomic_helper_crtc_duplicate_state(crtc, &state->base); + memcpy(state->gamma_coeffs, cs->gamma_coeffs, sizeof(state->gamma_coeffs)); return &state->base; } @@ -201,6 +317,7 @@ static void malidp_crtc_reset(struct drm_crtc *crtc) }; static const struct drm_crtc_funcs malidp_crtc_funcs = { + .gamma_set = drm_atomic_helper_legacy_gamma_set, .destroy = drm_crtc_cleanup, .set_config = drm_atomic_helper_set_config, .page_flip = drm_atomic_helper_page_flip, @@ -236,11 +353,14 @@ int malidp_crtc_init(struct drm_device *drm) ret = drm_crtc_init_with_planes(drm, &malidp->crtc, primary, NULL, &malidp_crtc_funcs, NULL); + if (ret) + goto crtc_cleanup_planes; - if (!ret) { - drm_crtc_helper_add(&malidp->crtc, &malidp_crtc_helper_funcs); - return 0; - } + drm_crtc_helper_add(&malidp->crtc, &malidp_crtc_helper_funcs); + drm_mode_crtc_set_gamma_size(&malidp->crtc, MALIDP_GAMMA_LUT_SIZE); + /* No inverse-gamma and color adjustments yet. */ + drm_crtc_enable_color_mgmt(&malidp->crtc, 0, false, MALIDP_GAMMA_LUT_SIZE); + return 0; crtc_cleanup_planes: malidp_de_planes_destroy(drm); diff --git a/drivers/gpu/drm/arm/malidp_drv.c b/drivers/gpu/drm/arm/malidp_drv.c index 8b0672d..ce741c3 100644 --- a/drivers/gpu/drm/arm/malidp_drv.c +++ b/drivers/gpu/drm/arm/malidp_drv.c @@ -32,6 +32,51 @@ #define MALIDP_CONF_VALID_TIMEOUT 250 +static void malidp_write_gamma_table(struct malidp_hw_device *hwdev, + u32 data[MALIDP_COEFFTAB_NUM_COEFFS]) +{ + int i; + /* Update all channels with a single gamma curve. */ + const u32 gamma_write_mask = GENMASK(18, 16); + /* + * Always write an entire table, so the address field in + * DE_COEFFTAB_ADDR is 0 and we can use the gamma_write_mask bitmask + * directly. + */ + malidp_hw_write(hwdev, gamma_write_mask, + hwdev->map.coeffs_base + MALIDP_COEF_TABLE_ADDR); + for (i = 0; i < MALIDP_COEFFTAB_NUM_COEFFS; ++i) + malidp_hw_write(hwdev, data[i], + hwdev->map.coeffs_base + + MALIDP_COEF_TABLE_DATA); +} + +static void malidp_atomic_commit_update_gamma(struct drm_crtc *crtc, + struct drm_crtc_state *old_state) +{ + struct malidp_drm *malidp = crtc_to_malidp_device(crtc); + struct malidp_hw_device *hwdev = malidp->dev; + + if (!crtc->state->color_mgmt_changed) + return; + + if (!crtc->state->gamma_lut) { + malidp_hw_clearbits(hwdev, + MALIDP_DISP_FUNC_GAMMA, + MALIDP_DE_DISPLAY_FUNC); + } else { + struct malidp_crtc_state *mc = + to_malidp_crtc_state(crtc->state); + + if (!old_state->gamma_lut || (crtc->state->gamma_lut->base.id != + old_state->gamma_lut->base.id)) + malidp_write_gamma_table(hwdev, mc->gamma_coeffs); + + malidp_hw_setbits(hwdev, MALIDP_DISP_FUNC_GAMMA, + MALIDP_DE_DISPLAY_FUNC); + } +} + /* * set the "config valid" bit and wait until the hardware acts on it */ @@ -88,8 +133,15 @@ static void malidp_atomic_commit_hw_done(struct drm_atomic_state *state) static void malidp_atomic_commit_tail(struct drm_atomic_state *state) { struct drm_device *drm = state->dev; + struct drm_crtc *crtc; + struct drm_crtc_state *old_crtc_state; + int i; drm_atomic_helper_commit_modeset_disables(drm, state); + + for_each_crtc_in_state(state, crtc, old_crtc_state, i) + malidp_atomic_commit_update_gamma(crtc, old_crtc_state); + drm_atomic_helper_commit_modeset_enables(drm, state); drm_atomic_helper_commit_planes(drm, state, 0); diff --git a/drivers/gpu/drm/arm/malidp_drv.h b/drivers/gpu/drm/arm/malidp_drv.h index 558f4bf..fbf6187 100644 --- a/drivers/gpu/drm/arm/malidp_drv.h +++ b/drivers/gpu/drm/arm/malidp_drv.h @@ -49,6 +49,7 @@ struct malidp_plane_state { struct malidp_crtc_state { struct drm_crtc_state base; + u32 gamma_coeffs[MALIDP_COEFFTAB_NUM_COEFFS]; }; #define to_malidp_crtc_state(x) container_of(x, struct malidp_crtc_state, base) diff --git a/drivers/gpu/drm/arm/malidp_hw.c b/drivers/gpu/drm/arm/malidp_hw.c index 488aedf..9bd35a2 100644 --- a/drivers/gpu/drm/arm/malidp_hw.c +++ b/drivers/gpu/drm/arm/malidp_hw.c @@ -415,6 +415,7 @@ static int malidp650_query_hw(struct malidp_hw_device *hwdev) const struct malidp_hw_device malidp_device[MALIDP_MAX_DEVICES] = { [MALIDP_500] = { .map = { + .coeffs_base = MALIDP500_COEFFS_BASE, .se_base = MALIDP500_SE_BASE, .dc_base = MALIDP500_DC_BASE, .out_depth_base = MALIDP500_OUTPUT_DEPTH, @@ -451,6 +452,7 @@ static int malidp650_query_hw(struct malidp_hw_device *hwdev) }, [MALIDP_550] = { .map = { + .coeffs_base = MALIDP550_COEFFS_BASE, .se_base = MALIDP550_SE_BASE, .dc_base = MALIDP550_DC_BASE, .out_depth_base = MALIDP550_DE_OUTPUT_DEPTH, @@ -485,6 +487,7 @@ static int malidp650_query_hw(struct malidp_hw_device *hwdev) }, [MALIDP_650] = { .map = { + .coeffs_base = MALIDP550_COEFFS_BASE, .se_base = MALIDP550_SE_BASE, .dc_base = MALIDP550_DC_BASE, .out_depth_base = MALIDP550_DE_OUTPUT_DEPTH, diff --git a/drivers/gpu/drm/arm/malidp_hw.h b/drivers/gpu/drm/arm/malidp_hw.h index 00974b5..73520ba 100644 --- a/drivers/gpu/drm/arm/malidp_hw.h +++ b/drivers/gpu/drm/arm/malidp_hw.h @@ -67,6 +67,8 @@ struct malidp_layer { struct malidp_hw_regmap { /* address offset of the DE register bank */ /* is always 0x0000 */ + /* address offset of the DE coefficients registers */ + const u16 coeffs_base; /* address offset of the SE registers bank */ const u16 se_base; /* address offset of the DC registers bank */ diff --git a/drivers/gpu/drm/arm/malidp_regs.h b/drivers/gpu/drm/arm/malidp_regs.h index aff6d4a..eeba027 100644 --- a/drivers/gpu/drm/arm/malidp_regs.h +++ b/drivers/gpu/drm/arm/malidp_regs.h @@ -63,6 +63,7 @@ /* bit masks that are common between products */ #define MALIDP_CFG_VALID (1 << 0) +#define MALIDP_DISP_FUNC_GAMMA (1 << 0) #define MALIDP_DISP_FUNC_ILACED (1 << 8) /* register offsets for IRQ management */ @@ -98,6 +99,12 @@ #define MALIDP_PRODUCT_ID(__core_id) ((u32)(__core_id) >> 16) +#define MALIDP_COEFFTAB_NUM_COEFFS 64 +/* register offsets relative to MALIDP5x0_COEFFS_BASE */ +#define MALIDP_COLOR_ADJ_COEF 0x00000 +#define MALIDP_COEF_TABLE_ADDR 0x00030 +#define MALIDP_COEF_TABLE_DATA 0x00034 + /* register offsets and bits specific to DP500 */ #define MALIDP500_ADDR_SPACE_SIZE 0x01000 #define MALIDP500_DC_BASE 0x00000 @@ -116,9 +123,11 @@ #define MALIDP500_BGND_COLOR 0x0003c #define MALIDP500_OUTPUT_DEPTH 0x00044 #define MALIDP500_YUV_RGB_COEF 0x00048 -#define MALIDP500_COLOR_ADJ_COEF 0x00078 -#define MALIDP500_COEF_TABLE_ADDR 0x000a8 -#define MALIDP500_COEF_TABLE_DATA 0x000ac +/* + * To match DP550/650, the start of the coeffs registers is + * at COLORADJ_COEFF0 instead of at YUV_RGB_COEF1. + */ +#define MALIDP500_COEFFS_BASE 0x00078 #define MALIDP500_DE_LV_BASE 0x00100 #define MALIDP500_DE_LV_PTR_BASE 0x00124 #define MALIDP500_DE_LG1_BASE 0x00200 @@ -144,9 +153,7 @@ #define MALIDP550_DE_DISP_SIDEBAND 0x00040 #define MALIDP550_DE_BGND_COLOR 0x00044 #define MALIDP550_DE_OUTPUT_DEPTH 0x0004c -#define MALIDP550_DE_COLOR_COEF 0x00050 -#define MALIDP550_DE_COEF_TABLE_ADDR 0x00080 -#define MALIDP550_DE_COEF_TABLE_DATA 0x00084 +#define MALIDP550_COEFFS_BASE 0x00050 #define MALIDP550_DE_LV1_BASE 0x00100 #define MALIDP550_DE_LV1_PTR_BASE 0x00124 #define MALIDP550_DE_LV2_BASE 0x00200