From patchwork Wed Feb 1 14:48:50 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mihail Atanassov X-Patchwork-Id: 9549885 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 1B1D460424 for ; Wed, 1 Feb 2017 14:49:05 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 078B1283E8 for ; Wed, 1 Feb 2017 14:49:05 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id ED08728435; Wed, 1 Feb 2017 14:49:04 +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 DB606283E8 for ; Wed, 1 Feb 2017 14:49:03 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id DB98A6E801; Wed, 1 Feb 2017 14:49:01 +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-db5eur01on0047.outbound.protection.outlook.com [104.47.2.47]) by gabe.freedesktop.org (Postfix) with ESMTPS id 6E8AE6E7F8 for ; Wed, 1 Feb 2017 14:49:00 +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=uESeSIIIhKXMWLIsPXtfaXAXJdfNDlUUPr9TKPI+dII=; b=oC0Osgt+l4XvCCgcxxYOrfcNe6nKRHSr2eFuQVbgQQ/NWaFiMEKAgETBNr0AVGvfgcHH1gTFyFkYwfiYQlSPQ2zU2s0YDkKJp5RpmoMSDWPSxsOoT25iH58rVl0G5sowclWz5ylAMb6lGN/DuoM6+DFykeUpy/TS9bddqATXAs0= 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.860.13; Wed, 1 Feb 2017 14:48:56 +0000 From: Mihail Atanassov To: Subject: [PATCH v2 2/2] drm: mali-dp: enable gamma support Date: Wed, 1 Feb 2017 14:48:50 +0000 Message-ID: <1485960530-22728-2-git-send-email-mihail.atanassov@arm.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1485960530-22728-1-git-send-email-mihail.atanassov@arm.com> References: <1485960530-22728-1-git-send-email-mihail.atanassov@arm.com> MIME-Version: 1.0 X-Originating-IP: [217.140.96.140] X-ClientProxiedBy: HE1PR0701CA0046.eurprd07.prod.outlook.com (10.168.191.14) To AM4PR08MB0884.eurprd08.prod.outlook.com (10.164.83.30) X-MS-Office365-Filtering-Correlation-Id: 34806173-5e59-469d-8312-08d44ab1733c 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:0dDE1sSQQVlvmIKGeP69+Be76/RLjJ9eqGfNs9At+4EEXLYHagsemVVymyDaCSTnvpusbcmXhOfLbSZ3M7Y0366/a8HXCbySMwBzpw5hwEhLVdLXu+Hwl1k2Kxt0Km4Lukbb5TNs3tOjYSSmFGlQ7pL5Srte66ne5shUZD2DE+FdQ837zTFMH9aQDKa2TZTC4s6i6CVwhODu5MQ+om/2fh5LevPZavCbCoKxVhdUc+yp9vTem6l+WoCLSxHyT/mgjbkRI1ork6pxIqJ19oKRNTVErw2UM/4LDSeJtvRtaII= X-Microsoft-Exchange-Diagnostics: 1; AM4PR08MB0884; 25:qOVaanNRznbJq6j0zwRzxLIPsKsYUHTlV0M0A/MtJ1yNgfm4xNGDjcHdMVgwW/1GHO9xPJnyJ4Y9OOes5C4dqIfiHmT7ZNYs1OpA3kyaePXqcs3HMY7l2Hb3m0AHwAEVmBps70ZZTiEeb7SkdD5MtHehwK2Q74uDjQJKDxQffFhNA1lSMNclj/ORF1Qk8Hz0FJSc2sSyRwtM/HYQ1V3tZyga3w3gdpY5oaOjT4h6B5tImLIHqi8+pIGkqBY4CekgILxY5kS41MEwOBXKJ1rjW13xYhd3WbG/kE0JxB6QAszGmSkfzXokWWH1HIKMbWqQ+gV4Z2amke0E6pQorUZ4VOZYHUkIb5VQt4RIOl7hun19AJO/ZoQTOVTDt/sJvp+nxBFT4eui3xHtKu3U4wR0HzowlTs6N20n4wrmEGpoD9/5Blp9ou0anaNINzhz05EJA2UW1kJzuqJ9vOG7ZbFLBHbuhRm37shx1jpJjGv/4kX/gOTlY4HRTXSwjxtsplUJwyYpj3dmkwz3RxOfXvTMM9HOGq7qkyRayuP4FPGrlkzkSFKmDsWyA8+H0wJ01RQT2es/rfWpXbjHYb5Mjy/pXwF6+tvuf7S8Xw6jSqpAbGCygh9udY5VZRXcj2phFzcwhWg0tmhYZMhsLa8MSzOlMGcHzPs6kGssvxVnkTyJkZIy4HySKU8sMPDDJ6vs8Bdy7mdlk4Fl/6qXEqyzXjHOqQ== X-Microsoft-Exchange-Diagnostics: 1; AM4PR08MB0884; 31:oOLg6vV3kAt4+Gs/GnAcJFWqcZV9ndOLA+LD4XSuKqLNtxAsi6AHnoMcgUbKqG+7mVJJy2oXd5Q1rE6thzNrJadDmbTPclIwk5JTKNXUzYdrhfYZY9AGntFWTCJRuuhcqQVfvfR7J1eQODh/Ky5tM2D7DBv6T+a7l+d6KAwHVl8EH/PcDVXS8193mvERtg/S67q/aqCkvggUVqlKVyDxmbeMko4vk1Wi6oUTbem5qDoba1UaKNMWI+ybYwUTF0Y46yyxhJGQke56ztMJiYRohQ==; 20:5OxwozuPU7jbGT14+1oLKZ7AeiPegxZ8Wo50gFqyXNL5NXafxJXJv4QbQyjJZwGhr5LFyT2VJfA16BZpvpf4MEaWnL7pWG9qvOZ4YcpqjH+jyQCuzA9CLnvnDtYyN2z4GaPs3D04+LEom5GwKEpy2GoRkl55EsgjZH1FcSR7Z+w= 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)(8121501046)(10201501046)(3002001)(6055026)(6041248)(20161123562025)(20161123564025)(20161123555025)(20161123560025)(20161123558025)(6072148); SRVR:AM4PR08MB0884; BCL:0; PCL:0; RULEID:; SRVR:AM4PR08MB0884; X-Microsoft-Exchange-Diagnostics: 1; AM4PR08MB0884; 4:YPkVCeaQTEZKFqxmBG4B5CJEV/X4whx/ah/FqFbfXjb7/xv5HQDshhpKqKvZx/XBxryyqnsOM6Bsohr2zOXfQ9HvzdxVQovvYcw9R+9nl1/PUXphACshL/KpAVq5p3xkFO699Hmxtyv3NatKjaKw+zO5JfcSihDrdIEFbKYbvJXf7gXoCvMzzAu9c5J8W8k7e7SzUgKtzVgPPhQvHVcfmT3Ome4TNInLxoeV3TEAUpx2jPG8ZVapvw/K9cYO+6/MHjJ5GHWTv2+m8UJRO1T1GbrRBEzACI0sXQp1rek9aaEEDjxl4XbCPDyku6hvDV+fEwMiQmEEVYUWowaOHze2UKhu2451IyBK/eJPQXC49osLPBxqUMl/CXhE4wx0OZApjqIUJtyC0L3mChGWqEb6dLpsR7nrickf+SiuJ3/G3qeQUqTD9P86QRgu7SWK3ZzNha44BCOjE6cIO4UkCX2fsmRt6t/U7RmGESChAmyB+1pX8MVkj2tH028OvDls8DhaFy8zlxu0IwZfftdFaeACB7jXD1Ik5Y5YCPFwFyKwyquIQgnON4Z0fKBtoobtTw2YY14PzvZc/9cXTSadzzmE0OH7ourynZgMrYwHhpQ0dPQtddQacsf5TdtHULs2w4VWlr3UMwQMt9jSxcdM6aj8Xw1+unETEidz6mltMxlcnuY= X-Forefront-PRVS: 0205EDCD76 X-Forefront-Antispam-Report: SFV:NSPM; SFS:(10009020)(4630300001)(6009001)(7916002)(39450400003)(39840400002)(39860400002)(39410400002)(39850400002)(189002)(199003)(2950100002)(189998001)(97736004)(2906002)(38730400001)(5660300001)(50466002)(6486002)(4326007)(7736002)(50986999)(50226002)(54906002)(47776003)(5003940100001)(305945005)(92566002)(66066001)(110136003)(6666003)(33646002)(81166006)(6116002)(105586002)(3846002)(101416001)(42186005)(76176999)(2351001)(36756003)(106356001)(81156014)(6916009)(25786008)(86362001)(68736007)(8676002)(48376002)(53936002); DIR:OUT; SFP:1101; SCL:1; SRVR:AM4PR08MB0884; H:e110433-lin.cambridge.arm.com; FPR:; SPF:None; PTR:InfoNoRecords; MX:1; A: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:khLvecnRUk24yOzaQtPRoVvUWXF0vIXC0cc3bfgiK?= =?us-ascii?Q?y2WKwAgZeohGLAM74b3yUoBTPnmGt+y9gw98hZKDByA9C5en1G1NexcU7boQ?= =?us-ascii?Q?K8cqjobzAsdI9qCR9MeYk0KIr67V63mQkbxkCSB+VlaVKgntlklJvjbESkJG?= =?us-ascii?Q?do8ymzjd/GMxKuFgpZ9Aq6jqjgT/WS+M6QNa6pti5Avig1rqPKXAq+5Uc9co?= =?us-ascii?Q?ULuK+c2+Vj5OzUEtCYl5fTV7kRKG4DGsjF1/TNgndE/fYQSn96ksCejEJugu?= =?us-ascii?Q?4yh51N9KwokoW7xzYwqzMbwXfy7Pt9lOKbH/ojO1XmsXBB9gX0/Y9EVqnjbL?= =?us-ascii?Q?nQ+XSrJ3MCBs6gVBm/McpUj+ATOhVmDqmf4HxK5GMa5XoUFIw24BUQkvx83s?= =?us-ascii?Q?RJI/3Ot31uI4+lkPdqWR1WTcXX7d9+qHb3AyLX9+f/9Pnd7YX2JHhc1ufmRl?= =?us-ascii?Q?4cNizZBFpe/A1M5mxkhrrlwqn4/8L9fE8AA0ZlGbsnk2HHwMkY0RhmIkJLR1?= =?us-ascii?Q?EW+JWOT4AWqg9YmFOuKXD+FbMCepxJjKbBCFMsV+lraRW009/EvriLX1Zauy?= =?us-ascii?Q?FbT9JNek5LdymtswVh9cdRXajZLRi1Rwq1Tp1od2AF6+SQduVpj9eJQNFYnd?= =?us-ascii?Q?XkZxW+1GC/zlOwGYOJIkyKlrm6LQGuis5SLbUxHkL6v87ve9WixJy4J2Rv5F?= =?us-ascii?Q?nt4VgFIzc6qaUnYDHK3sNYuHCI5f/b93AEQjzb3feggpDr0EdH/SoXLhyTcI?= =?us-ascii?Q?yBHWcGpygW9WZ3dmOXWkg+zmb8qw6H99iFaQVgDtcLpRDh6BaDiY49Uspbhv?= =?us-ascii?Q?XvnHRoTZEMqpC+a5WZsECGLD9cqN/1uqdHFHKEtzjoBRMHaQ8bg+bwjRAC1A?= =?us-ascii?Q?vaAsynELeLOtAn0DhjkLXBvMR2/dhuPebqdhOWP/6p0kZwXaCD0u3H+hz3Oi?= =?us-ascii?Q?ekPyYXljec/NaCLX8hFPQxiEd5U9oT5KmV74jQh4DOegjXaNZ+h1IEZM7ZRG?= =?us-ascii?Q?wJgklqfg2gL5YDvmArPh4AtQj34gssZtWY28kIjpb/SboGWEknWzuBSe9T/Y?= =?us-ascii?Q?HVL8FfAP0Wzx5EdTchdfwH/kuMWV0haBUxvfluEavbHHbcJPtXuvRRIpIt30?= =?us-ascii?Q?kJYHCfbsSwFja4LBr9COl6Ef+0PTdrBv+NzhK+m++UWMTmzGm9+B/P1sWc3W?= =?us-ascii?Q?/lYNlAk+xK03Zi8QKHvNCmVqIYY0pVAlwFf?= X-Microsoft-Exchange-Diagnostics: 1; AM4PR08MB0884; 6:OZAPsMyidLWjp8lCPZ5tRnjcz6ziSw3whDR1WeCmOjd6CmtcbV/ETgHtdDe4AuU4VF7CvI3bnnGUqbSFP8Xb6TdR8MPyZVR3yviUD31/eyrwNxQ1YKH/rSOSLlupXQHWW4Ok9DBs0xOeYP8Hgnnp2pTm9BZxJfh8hxKz88C5Joer9aSrxaWohNmJv7o5Bpl8wTkuD1e6lXOytJDs02YqbXAMqVvG4XU5vjlDiTXfprYdqoCymBkMADIN1a1xjK6Pvv8tbMI8qELvlkwN4XVRTpFdHD1OUkEUJuc58tu8kzv0OTRd+cgJlqCJD9Gk5egqOphIZ9cK287agl8Bd4zGyHuPCRISRgf2qRlUtokx3R415DB1iqyHsmoNnO4yhDeTBUDG6l7hhvT990lBCSSJsdbYXMUO8i3dAPaosY4n/AVCv6HMxU8CzmMcQlBfLtaD; 5:GGyzeGuNSZxcIpc91hgtocRWwuRORpWFI1scIk/6xMx/CGhAU2LPBG3/dNPWhHN2KC7Ac0PqIVwTwUSvExijXx0Ifvapl5d4cQIIAhq+9W13Oj0zKH6IXdyxTfQ9v/CpmPACBBKr8+hwexYMfRYOTlxXMdGuaDkrm/tP/zfZxJQ=; 24:2W5W5eob2xMbhL010j1ia/w8PL1m4AeLm7nDAJ7J7ZWi9UpuWOBOytFl4xwDgLrxrpN20Y7xNrmij+wPXe+Red4T76F0tPGxb+PEqyCRNaI= SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-Microsoft-Exchange-Diagnostics: 1; AM4PR08MB0884; 7:NWFzOJGJ5ge7HnIpewCSgEq4yuwjSAksAM7VpfOZ7NN11Q0Fa3HskXvpNr24BtdzJUlWdZxLnO3d2whZ97/IXAtrZaoQkIBIf9erDoy5QsXFyNu9yDyeN8O9pT1ssmwdC4BA7DDKW+688Wc97qAml1qx3x7hINtCBRU8uUiDNup+DnfdxIa2uUu62x1zFgSK22Ec9mO4YkXZEUGTHs3lu+bEjg3ewh2mxvwImY8C7cuCKMchuAYOxbyiW3ruVOqBATThUPRMjdUqa7puXYj8sX+/nxuzSJdKh5SdbNJuH0Cn7JVehQervSx/kaCLB35I+S93MZpFWjbB1BauI/XUtEqqMwlJHSUtGmCTiHKMm431KodtDT3KBntsBUJQl0QVuoMINjmU66czW+VkWxY5rLcdB/MLsuX5Zom1lATTsSpQEjaTx1Sv14oV+0Z4cKcTJAM8jLZ9ryJ+Ek5NvNr68Uj6LbRqqxb1iF83CU4KBB7PID2MLCKyysRBiEa5yMfmThvwxs5XOvaWlXuCox5/Go3NPWzHv6SLPKQ4Kc+8r82tCEhegOnsVfvQSIEHI3na X-OriginatorOrg: arm.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 01 Feb 2017 14:48:56.1619 (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 | 132 ++++++++++++++++++++++++++++++++++++-- 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, 199 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/arm/malidp_crtc.c b/drivers/gpu/drm/arm/malidp_crtc.c index ebf57e6..10f79b6 100644 --- a/drivers/gpu/drm/arm/malidp_crtc.c +++ b/drivers/gpu/drm/arm/malidp_crtc.c @@ -82,6 +82,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 != 4096) + 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 +199,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 +266,29 @@ static int malidp_crtc_atomic_check(struct drm_crtc *crtc, } } + ret = malidp_crtc_atomic_check_gamma(crtc, state); + if (ret) + return ret; + return 0; } 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 +318,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 +354,17 @@ 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, 4096); + /* No inverse-gamma and color adjustments yet. */ + drm_crtc_enable_color_mgmt(&malidp->crtc, + 0, + false, + 4096); + 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 32f746e..a9f787d 100644 --- a/drivers/gpu/drm/arm/malidp_drv.c +++ b/drivers/gpu/drm/arm/malidp_drv.c @@ -33,6 +33,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_GAM, + 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_GAM, + MALIDP_DE_DISPLAY_FUNC); + } +} + /* * set the "config valid" bit and wait until the hardware acts on it */ @@ -89,8 +134,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 c7a69ae..374d43e 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 4bdf531..5ceca17 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, @@ -450,6 +451,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, @@ -483,6 +485,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 087e1202..ecff7d4 100644 --- a/drivers/gpu/drm/arm/malidp_hw.h +++ b/drivers/gpu/drm/arm/malidp_hw.h @@ -66,6 +66,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 73fecb3..2e213c3 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_GAM (1 << 0) #define MALIDP_DISP_FUNC_ILACED (1 << 8) /* register offsets for IRQ management */ @@ -92,6 +93,12 @@ #define MALIDP_DE_H_ACTIVE(x) (((x) & 0x1fff) << 0) #define MALIDP_DE_V_ACTIVE(x) (((x) & 0x1fff) << 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_DC_BASE 0x00000 #define MALIDP500_DC_CONTROL 0x0000c @@ -109,9 +116,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 @@ -136,9 +145,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