From patchwork Tue Feb 16 22:27:58 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Harry Wentland X-Patchwork-Id: 8332921 Return-Path: X-Original-To: patchwork-dri-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 896949F6E7 for ; Tue, 16 Feb 2016 22:29:55 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 2732220320 for ; Tue, 16 Feb 2016 22:29:53 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id 1E965202EC for ; Tue, 16 Feb 2016 22:29:49 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 7C5456E8BB; Tue, 16 Feb 2016 22:28:54 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from na01-bl2-obe.outbound.protection.outlook.com (mail-bl2on0088.outbound.protection.outlook.com [65.55.169.88]) by gabe.freedesktop.org (Postfix) with ESMTPS id 7A9196E8C2 for ; Tue, 16 Feb 2016 22:28:50 +0000 (UTC) Received: from CY1PR12CA0008.namprd12.prod.outlook.com (10.160.137.18) by BY2PR12MB0709.namprd12.prod.outlook.com (10.163.113.19) with Microsoft SMTP Server (TLS) id 15.1.409.15; Tue, 16 Feb 2016 22:28:47 +0000 Received: from BY2NAM03FT030.eop-NAM03.prod.protection.outlook.com (2a01:111:f400:7e4a::201) by CY1PR12CA0008.outlook.office365.com (2a01:111:e400:4c1f::18) with Microsoft SMTP Server (TLS) id 15.1.409.15 via Frontend Transport; Tue, 16 Feb 2016 22:28:47 +0000 Authentication-Results: spf=none (sender IP is 165.204.84.222) smtp.mailfrom=amd.com; lists.freedesktop.org; dkim=none (message not signed) header.d=none;lists.freedesktop.org; dmarc=permerror action=none header.from=amd.com; Received-SPF: None (protection.outlook.com: amd.com does not designate permitted sender hosts) Received: from atltwp02.amd.com (165.204.84.222) by BY2NAM03FT030.mail.protection.outlook.com (10.152.84.214) with Microsoft SMTP Server id 15.1.415.6 via Frontend Transport; Tue, 16 Feb 2016 22:28:46 +0000 X-WSS-ID: 0O2NVRS-08-5UA-02 X-M-MSG: Received: from satlvexedge02.amd.com (satlvexedge02.amd.com [10.177.96.29]) (using TLSv1 with cipher ECDHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by atltwp02.amd.com (Axway MailGate 5.3.1) with ESMTPS id 2319DBD8976 for ; Tue, 16 Feb 2016 17:28:39 -0500 (EST) Received: from SATLEXDAG04.amd.com (10.181.40.9) by SATLVEXEDGE02.amd.com (10.177.96.29) with Microsoft SMTP Server (TLS) id 14.3.195.1; Tue, 16 Feb 2016 16:28:46 -0600 Received: from STOREXDAG02.amd.com (10.1.13.11) by satlexdag04.amd.com (10.181.40.9) with Microsoft SMTP Server (TLS) id 14.3.266.1; Tue, 16 Feb 2016 17:28:41 -0500 Received: from cnhwentlanub.amd.com (172.29.225.36) by storexdag02.amd.com (10.1.13.11) with Microsoft SMTP Server id 14.3.266.1; Tue, 16 Feb 2016 17:28:41 -0500 From: Harry Wentland To: Subject: [PATCH v2 18/26] drm/amd/dal: Add input pixel processing HW programming Date: Tue, 16 Feb 2016 17:27:58 -0500 Message-ID: X-Mailer: git-send-email 2.1.4 In-Reply-To: References: <1455211209-26733-1-git-send-email-harry.wentland@amd.com> MIME-Version: 1.0 X-EOPAttributedMessage: 0 X-Forefront-Antispam-Report: CIP:165.204.84.222; CTRY:US; IPV:NLI; EFV:NLI; SFV:NSPM; SFS:(10009020)(6009001)(2980300002)(428002)(199003)(189002)(105586002)(118296001)(5003600100002)(586003)(1096002)(86362001)(50226001)(1220700001)(87936001)(36756003)(2906002)(92566002)(5003940100001)(5008740100001)(229853001)(11100500001)(2351001)(4326007)(33646002)(106466001)(2950100001)(450100001)(47776003)(50466002)(77096005)(50986999)(101416001)(53416004)(48376002)(76176999)(110136002)(189998001)(19580405001)(19580395003); DIR:OUT; SFP:1101; SCL:1; SRVR:BY2PR12MB0709; H:atltwp02.amd.com; FPR:; SPF:None; MLV:sfv; A:1; MX:1; LANG:en; X-MS-Office365-Filtering-Correlation-Id: 0443f45a-ca4d-41e8-fe01-08d33720891e X-Microsoft-Exchange-Diagnostics: 1; BY2PR12MB0709; 2:8XehPbOX1OcVha/C6BpR79yCZyT0v3qAlYPRA5f2mqVmhHJr5Re93IbPonXQAFDkpAm9MdehUq9Da0ATtgLVReKw/J3GC87aBoKTu568u+OgH7oUP+oA+km3b2ZdmwLm/8LSFSRdGEv/97syHgNAiqv42O2N7UHGNAHYfk23VtqFjw+EKP59btm8HVq3b1oh; 3:treGsxebpJxciEfzUHudd9CCfQNxCSADuJX6nCLheICRuGYI3XOEYg7YQFADziU8Fi64AYo0SN6V7ym0ghBElcfa4Gwjk9iq44QHRIwZekv8jzyjGrAym+P3QYoRHATNNuFhm5LkWhl3NAyr1BHyUJ29nHguepbw74fH1ov2oOc93UhpNXGtn8uam76SNlNCO4VQXqU1KHECRrIwwrxcAqGoz1gz9yv7HbtocRWPm24=; 25:b1EqCKndlURd3TMWvHMGaej/7koY0cM5M0mck4lpLb0YIIDYz4dkL6pZM9K3yE9mMUwqaxRrQniNwciKdECFGZRCZ+smDSeN5qfIhtBKxsBq9j3Jjr6tuIq4PIG4I09HO5z5/kJ/+66iuLfrvVETHwBtiFycWSpgK1PZnJzbj4akLIWArKL5//YJ4cxfpb0K0AtArAtAWV/OMDMdebryIq+J4C3Vy3Xpcy2baZiAhUG8pLZbEedTCE53HpbNtRmrcQGvmaQZxGgVN13Dz+ks+i5TjoUsT2iDoQE1oFTyFK5HmRSWlXDcokjxa6K8BkQs X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:;SRVR:BY2PR12MB0709; X-Microsoft-Exchange-Diagnostics: 1; BY2PR12MB0709; 20:P+ds9pohPITb1EvPnyz/70fOKVDl8tB6RfeXzT6fL+GNfiylRhf1BbMwvQFTfxfidPsVRwCorkOsqUKN9LMNQ/1dPXs8X/H2cT19fGlravs81O4153zv4l0mhGcwJ/X1xbSW6uP7/YzX9x8WJ9sZMkFGd1xBuKGvoYLbizvD5qX/RBO3KADlJ/Oxnu4LvNAg+dV43XEqM5deiQYarJtmWSSC1QgF3PxmDOAzNVULqY4VhTVvUI45MGx8bI5PwT4x+VGIzod6y7Xe0IJ6OcjVGzH/BUtOH2oI+I1QBMAeE2oWEZl2JmEml20cWps3XKKrYu6SsKT71BI8YOY6+N20Ve5wuY3czCQqhtzJntYLM1S63mkChCGswZK2PMs13dK0FBcAelL+OHh2xxHrCyKuAnO8V7NNd6SD8evrrtcmAS4uH1yEO+56qwvB6udgfi61BQtvTczeJ5PnMkV+vZirstecEEVhXw0XPCGDv5LpB6h6CXKm8imdgBmZT+BgJ7GA X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:(767451399110); X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(601004)(2401047)(13017025)(13015025)(5005006)(13018025)(13023025)(13024025)(8121501046)(10201501046)(3002001); SRVR:BY2PR12MB0709; BCL:0; PCL:0; RULEID:; SRVR:BY2PR12MB0709; X-Microsoft-Exchange-Diagnostics: 1; BY2PR12MB0709; 4:0+ssRI48me5XPzNev/8asDV2SjsC4sJxOJla4tqVGItDzuC/lCFApFuccUcv9uy1BFQDvpo/RprBQOjHXGeg4QBmrJjU1aeifIlq6Cw0MGgyhhDCI0cunTw+Bd4t7QBsPPRXH1OZz0W9SFxKNiiGCnIiG3eLe7yzu6gsWnIsJ8IAMgz8hCqROL7XeI0tDP/51YQuRW3f9elnAB0Zap+fk4Ya80ufg4bTq2zvRMEPkC5occ8jG2ZbNm4iobs50ZX8bnNlFkjwY1dXR3EOTa5GnaMTmfmurlE9BSlRh8Au1mG8tw+O9N6qohoI73A/sjOswgJ3PhKQsqG0WF0K2kbWtFx6pBRGppVesNZdTjV/vjEaB3pcnv1IjXq/cczRKDeEuvOkqAyi0qHjXMOCpgBAviwF6uZIfO/C0ckWF4sDuMpWIJuSwG6a64lfzJBXFHWIHC6RitGU47GAQ98a35TIvbVY3vz9PilDkOtQ7ggBEI1ilYH7USAcBqJnzQMOo4YD X-Forefront-PRVS: 0854128AF0 X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1; BY2PR12MB0709; 23:Enyf3BTY/j8lyiqwwWoUq2EtiC8Z1pPcj82Pu9p6L?= =?us-ascii?Q?ZvvJRHXkvMKCHjgQkOuJrI4XkE2+rXCbDoWij8VI/Zg73G5QaXMPhXO5z/t7?= =?us-ascii?Q?eswK2tmY3oH4Om5d0xBzJIVYWg0211M7ogV1pxYot7NIO6ZLmIiOObOIc1V8?= =?us-ascii?Q?4SI6c+0a4oweybWdEiOf4DiaZ67jjQoqMmDpBqRYSQVsFkMYx2Ect+sG8YkZ?= =?us-ascii?Q?lOYDUOmQ8SA8v57M1+6seYVeMjwTKit1VNsC+Bw3QrPa2l3+Cy2SgbHT2mOH?= =?us-ascii?Q?rWLgm+j/jHL2bUOFYKzGUvE5RmcJWYbSV4ssOJK9cB5rAP+Prte8VbMcsOeN?= =?us-ascii?Q?3cSuhR0dzzgAFD36pbDY2TX75VDAl+oBnP64WEX8qdpIf7ChtXM+tm/0TwzI?= =?us-ascii?Q?017ZNpi0orJ6TJJnJxeBymCkacrNyv/Zd9+kp3UnpG85jlTp+Uuu5qynmfJ1?= =?us-ascii?Q?ux1CIvFvoWSx2h53DDb0w+ZCL0lS2bnKklsoSNueybECIEEnz+lmSmx1l8VU?= =?us-ascii?Q?OaDGuoqMEcX5u3ZkSN4hkkjMM3qArcYx6Oqg3H6nnE2GiQ+0Or0Sdu9mqEKP?= =?us-ascii?Q?EgLnfojoQcHnuV7pRZYUix3Lrr3GjDvxsr7sldMCBOaOyAUkqIEjAV2Y54op?= =?us-ascii?Q?To1PGqO+HM4zQaeL80QrvrjNJAxcf6C2BMrMKNAupq59w8xO2gORO1BcyMMg?= =?us-ascii?Q?SL2/yB1YSRIGEzDFtBkWukFXVJlh7cT6q2MO6psauI0Woh6YCStYByC62F3q?= =?us-ascii?Q?NAJ86PVF7Q2wI8zIjHlvYwKxNEmG8ez69PmugVdUJ8ScK35KRoZ2Zzswz3Mi?= =?us-ascii?Q?IprbbCzXVAJFSYNDlL3IMHpGUN6lqYKdcM79BiBM/pJYc8puvASvDYY5b2Bw?= =?us-ascii?Q?QJMvDWE0J8ji9W0h3MUJuIK/y0t+tmrqMgHEE70vC87fV9K75Z4YcFOPmciF?= =?us-ascii?Q?sQg5HqtdbHVOZAcAKM77PBlOF1U6p7FYelfdB3hK8ik2gOXlmObHbZPvCSZ4?= =?us-ascii?Q?D/JnVuVp2EZnbp8phvdLbk1oFvxM45Qj1lkdGjGmimLlA=3D=3D?= X-Microsoft-Exchange-Diagnostics: 1; BY2PR12MB0709; 5:cfWHPY4PauVjIG6YCE/0HNT2T7EcwD9re/fe5CmOJRghd9XdzUb3+pWsCjBaRk2OIO4V81sg3c15orUhbQI2Z/JVP3XlJg2P+SUA2MTzOxGaS73VAN003Rt+uhTa5a4zX2jIAvTqRkGsFW9ZIYMskg==; 24:wbkGODq7m+6L4kSaDeuCj4kJiXVGqH1jyQs9YgPpCSEMMPdd6sNPHp0QZc9Ybt4iYiSffO1noFJcp0fCeBEJKrDHK35zV8YsFoHNaewcofI=; 20:6L661ni3+fJx/l+cdeYPddtWjhRhflG70i6ZVpzGBqdoc77O4RlpQ6L/E7dX3YTgtC9SgJuRBZ5UALlujyf3WrEgsw6Tvxpx2LdmBt3S7CVlnC/QpArJVU1vzLIs0oWk9csEASjZrxZ1bpJgycaufZXu5oecsWDtAiDdSjAYDPI7ngN3N1W2sncg+hNK5eKXwplWr4Zbp+BXmi21AwMJOAS92B16lfApfNMwMI3h9OeI8Ud+GdCfrJm3xDskZkxb SpamDiagnosticOutput: 1:23 SpamDiagnosticMetadata: NSPM X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 16 Feb 2016 22:28:46.3050 (UTC) X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=3dd8961f-e488-4e60-8e11-a82d994e183d; Ip=[165.204.84.222]; Helo=[atltwp02.amd.com] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: BY2PR12MB0709 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-Spam-Status: No, score=-4.2 required=5.0 tests=BAD_ENC_HEADER,BAYES_00, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Adds programming of cursor and input gamma. Signed-off-by: Harry Wentland Reviewed-by: Alex Deucher --- drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp.c | 65 ++ drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp.h | 100 +++ .../gpu/drm/amd/dal/dc/dce110/dce110_ipp_cursor.c | 256 ++++++ .../gpu/drm/amd/dal/dc/dce110/dce110_ipp_gamma.c | 872 +++++++++++++++++++++ 4 files changed, 1293 insertions(+) create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp.c create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp.h create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp_cursor.c create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp_gamma.c diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp.c new file mode 100644 index 000000000000..6ab35272f979 --- /dev/null +++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp.c @@ -0,0 +1,65 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "include/logger_interface.h" + +#include "dce/dce_11_0_d.h" +#include "dce/dce_11_0_sh_mask.h" + +#include "dce110_ipp.h" + +static struct ipp_funcs funcs = { + .ipp_cursor_set_attributes = dce110_ipp_cursor_set_attributes, + .ipp_cursor_set_position = dce110_ipp_cursor_set_position, + .ipp_program_prescale = dce110_ipp_program_prescale, + .ipp_set_degamma = dce110_ipp_set_degamma, + .ipp_set_legacy_input_gamma_mode = dce110_ipp_set_legacy_input_gamma_mode, + .ipp_set_legacy_input_gamma_ramp = dce110_ipp_set_legacy_input_gamma_ramp, + .ipp_set_palette = dce110_ipp_set_palette, +}; + +bool dce110_ipp_construct( + struct dce110_ipp* ipp, + struct dc_context *ctx, + uint32_t inst, + const struct dce110_ipp_reg_offsets *offset) +{ + ipp->base.ctx = ctx; + + ipp->base.inst = inst; + + ipp->offsets = *offset; + + ipp->base.funcs = &funcs; + + return true; +} + +void dce110_ipp_destroy(struct input_pixel_processor **ipp) +{ + dm_free((*ipp)->ctx, TO_DCE110_IPP(*ipp)); + *ipp = NULL; +} diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp.h b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp.h new file mode 100644 index 000000000000..709906face3f --- /dev/null +++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp.h @@ -0,0 +1,100 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_IPP_DCE110_H__ +#define __DC_IPP_DCE110_H__ + +#include "inc/ipp.h" + + +struct gamma_parameters; +struct dev_c_lut; + +#define TO_DCE110_IPP(input_pixel_processor)\ + container_of(input_pixel_processor, struct dce110_ipp, base) + +struct dce110_ipp_reg_offsets { + uint32_t dcp_offset; +}; + +struct dce110_ipp { + struct input_pixel_processor base; + struct dce110_ipp_reg_offsets offsets; + struct dev_c_lut saved_palette[RGB_256X3X16]; +}; + +bool dce110_ipp_construct( + struct dce110_ipp* ipp, + struct dc_context *ctx, + enum controller_id id, + const struct dce110_ipp_reg_offsets *offset); + +void dce110_ipp_destroy(struct input_pixel_processor **ipp); + +/* CURSOR RELATED */ +bool dce110_ipp_cursor_set_position( + struct input_pixel_processor *ipp, + const struct dc_cursor_position *position); + +bool dce110_ipp_cursor_set_attributes( + struct input_pixel_processor *ipp, + const struct dc_cursor_attributes *attributes); + +/* DEGAMMA RELATED */ +bool dce110_ipp_set_degamma( + struct input_pixel_processor *ipp, + const struct gamma_parameters *params, + bool force_bypass); + +void dce110_ipp_program_prescale( + struct input_pixel_processor *ipp, + enum pixel_format pixel_format); + +void dce110_ipp_set_legacy_input_gamma_mode( + struct input_pixel_processor *ipp, + bool is_legacy); + +bool dce110_ipp_set_legacy_input_gamma_ramp( + struct input_pixel_processor *ipp, + const struct gamma_ramp *gamma_ramp, + const struct gamma_parameters *params); + +bool dce110_ipp_set_palette( + struct input_pixel_processor *ipp, + const struct dev_c_lut *palette, + uint32_t start, + uint32_t length, + enum pixel_format surface_pixel_format); + +/* + * Helper functions to be resused in other ASICs + */ +void dce110_helper_select_lut(struct dce110_ipp *ipp110); + +void dce110_helper_program_black_white_offset( + struct dce110_ipp *ipp110, + enum pixel_format surface_pixel_format); + +#endif /*__DC_IPP_DCE110_H__*/ diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp_cursor.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp_cursor.c new file mode 100644 index 000000000000..ef91f2db24e3 --- /dev/null +++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp_cursor.c @@ -0,0 +1,256 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "include/logger_interface.h" + +#include "dce/dce_11_0_d.h" +#include "dce/dce_11_0_sh_mask.h" + +#include "dce110_ipp.h" + +#define CURSOR_COLOR_BLACK 0x00000000 +#define CURSOR_COLOR_WHITE 0xFFFFFFFF + +#define DCP_REG(reg)\ + (reg + ipp110->offsets.dcp_offset) + +static void enable( + struct dce110_ipp *ipp110, + bool enable); + +static void lock( + struct dce110_ipp *ipp110, + bool enable); + +static void program_position( + struct dce110_ipp *ipp110, + uint32_t x, + uint32_t y); + +static bool program_control( + struct dce110_ipp *ipp110, + enum dc_cursor_color_format color_format, + bool enable_magnification, + bool inverse_transparent_clamping); + +static void program_hotspot( + struct dce110_ipp *ipp110, + uint32_t x, + uint32_t y); + +static void program_size( + struct dce110_ipp *ipp110, + uint32_t width, + uint32_t height); + +static void program_address( + struct dce110_ipp *ipp110, + PHYSICAL_ADDRESS_LOC address); + + +bool dce110_ipp_cursor_set_position( + struct input_pixel_processor *ipp, + const struct dc_cursor_position *position) +{ + struct dce110_ipp *ipp110 = TO_DCE110_IPP(ipp); + + /* lock cursor registers */ + lock(ipp110, true); + + /* Flag passed in structure differentiates cursor enable/disable. */ + /* Update if it differs from cached state. */ + enable(ipp110, position->enable); + + program_position(ipp110, position->x, position->y); + + if (position->hot_spot_enable) + program_hotspot( + ipp110, + position->x_origin, + position->y_origin); + + /* unlock cursor registers */ + lock(ipp110, false); + + return true; +} + +bool dce110_ipp_cursor_set_attributes( + struct input_pixel_processor *ipp, + const struct dc_cursor_attributes *attributes) +{ + struct dce110_ipp *ipp110 = TO_DCE110_IPP(ipp); + /* Lock cursor registers */ + lock(ipp110, true); + + /* Program cursor control */ + program_control( + ipp110, + attributes->color_format, + attributes->attribute_flags.bits.ENABLE_MAGNIFICATION, + attributes->attribute_flags.bits.INVERSE_TRANSPARENT_CLAMPING); + + /* Program hot spot coordinates */ + program_hotspot(ipp110, attributes->x_hot, attributes->y_hot); + + /* + * Program cursor size -- NOTE: HW spec specifies that HW register + * stores size as (height - 1, width - 1) + */ + program_size(ipp110, attributes->width, attributes->height); + + /* Program cursor surface address */ + program_address(ipp110, attributes->address); + + /* Unlock Cursor registers. */ + lock(ipp110, false); + + return true; +} + +static void enable( + struct dce110_ipp *ipp110, bool enable) +{ + uint32_t value = 0; + uint32_t addr = DCP_REG(mmCUR_CONTROL); + + value = dm_read_reg(ipp110->base.ctx, addr); + set_reg_field_value(value, enable, CUR_CONTROL, CURSOR_EN); + dm_write_reg(ipp110->base.ctx, addr, value); +} + +static void lock( + struct dce110_ipp *ipp110, bool lock) +{ + uint32_t value = 0; + uint32_t addr = DCP_REG(mmCUR_UPDATE); + + value = dm_read_reg(ipp110->base.ctx, addr); + set_reg_field_value(value, lock, CUR_UPDATE, CURSOR_UPDATE_LOCK); + dm_write_reg(ipp110->base.ctx, addr, value); +} + +static void program_position( + struct dce110_ipp *ipp110, + uint32_t x, + uint32_t y) +{ + uint32_t value = 0; + uint32_t addr = DCP_REG(mmCUR_POSITION); + + value = dm_read_reg(ipp110->base.ctx, addr); + set_reg_field_value(value, x, CUR_POSITION, CURSOR_X_POSITION); + set_reg_field_value(value, y, CUR_POSITION, CURSOR_Y_POSITION); + dm_write_reg(ipp110->base.ctx, addr, value); +} + +static bool program_control( + struct dce110_ipp *ipp110, + enum dc_cursor_color_format color_format, + bool enable_magnification, + bool inverse_transparent_clamping) +{ + uint32_t value = 0; + uint32_t addr = DCP_REG(mmCUR_CONTROL); + uint32_t mode = 0; + + switch (color_format) { + case CURSOR_MODE_MONO: + mode = 0; + break; + case CURSOR_MODE_COLOR_1BIT_AND: + mode = 1; + break; + case CURSOR_MODE_COLOR_PRE_MULTIPLIED_ALPHA: + mode = 2; + break; + case CURSOR_MODE_COLOR_UN_PRE_MULTIPLIED_ALPHA: + mode = 3; + break; + default: + return false; + } + + set_reg_field_value(value, mode, CUR_CONTROL, CURSOR_MODE); + set_reg_field_value(value, enable_magnification, + CUR_CONTROL, CURSOR_2X_MAGNIFY); + set_reg_field_value(value, inverse_transparent_clamping, + CUR_CONTROL, CUR_INV_TRANS_CLAMP); + dm_write_reg(ipp110->base.ctx, addr, value); + + if (color_format == CURSOR_MODE_MONO) { + addr = DCP_REG(mmCUR_COLOR1); + dm_write_reg(ipp110->base.ctx, addr, CURSOR_COLOR_BLACK); + addr = DCP_REG(mmCUR_COLOR2); + dm_write_reg(ipp110->base.ctx, addr, CURSOR_COLOR_WHITE); + } + return true; +} + +static void program_hotspot( + struct dce110_ipp *ipp110, + uint32_t x, + uint32_t y) +{ + uint32_t value = 0; + uint32_t addr = DCP_REG(mmCUR_HOT_SPOT); + + value = dm_read_reg(ipp110->base.ctx, addr); + set_reg_field_value(value, x, CUR_HOT_SPOT, CURSOR_HOT_SPOT_X); + set_reg_field_value(value, y, CUR_HOT_SPOT, CURSOR_HOT_SPOT_Y); + dm_write_reg(ipp110->base.ctx, addr, value); +} + +static void program_size( + struct dce110_ipp *ipp110, + uint32_t width, + uint32_t height) +{ + uint32_t value = 0; + uint32_t addr = DCP_REG(mmCUR_SIZE); + + value = dm_read_reg(ipp110->base.ctx, addr); + set_reg_field_value(value, width, CUR_SIZE, CURSOR_WIDTH); + set_reg_field_value(value, height, CUR_SIZE, CURSOR_HEIGHT); + dm_write_reg(ipp110->base.ctx, addr, value); +} + +static void program_address( + struct dce110_ipp *ipp110, + PHYSICAL_ADDRESS_LOC address) +{ + uint32_t addr = DCP_REG(mmCUR_SURFACE_ADDRESS_HIGH); + /* SURFACE_ADDRESS_HIGH: Higher order bits (39:32) of hardware cursor + * surface base address in byte. It is 4K byte aligned. + * The correct way to program cursor surface address is to first write + * to CUR_SURFACE_ADDRESS_HIGH, and then write to CUR_SURFACE_ADDRESS */ + + dm_write_reg(ipp110->base.ctx, addr, address.high_part); + + addr = DCP_REG(mmCUR_SURFACE_ADDRESS); + dm_write_reg(ipp110->base.ctx, addr, address.low_part); +} + diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp_gamma.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp_gamma.c new file mode 100644 index 000000000000..fcf65f119af4 --- /dev/null +++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp_gamma.c @@ -0,0 +1,872 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "include/logger_interface.h" +#include "include/fixed31_32.h" +#include "basics/conversion.h" + +#include "dce/dce_11_0_d.h" +#include "dce/dce_11_0_sh_mask.h" + +#include "dce110_ipp.h" +#include "gamma_types.h" + +#define DCP_REG(reg)\ + (reg + ipp110->offsets.dcp_offset) + +enum { + MAX_INPUT_LUT_ENTRY = 256 +}; + +/* CALCULATION OPERATIONS*/ +static void convert_256_lut_entries_to_gxo_format( + const struct gamma_ramp_rgb256x3x16 *lut, + struct dev_c_lut16 *gamma) +{ + uint32_t i = 0; + + ASSERT(lut); + ASSERT(gamma); + + do { + gamma->red = lut->red[i]; + gamma->green = lut->green[i]; + gamma->blue = lut->blue[i]; + + ++gamma; + ++i; + } while (i != MAX_INPUT_LUT_ENTRY); +} + +static void convert_udx_gamma_entries_to_gxo_format( + const struct gamma_ramp_dxgi_1 *lut, + struct dev_c_lut16 *gamma) +{ + /* TODO here we deal with DXGI gamma table, + * originally, values was expressed as 'float', + * now values expressed as 'dal_fixed20_12'. */ +} + +/*PROTOTYPE DECLARATIONS*/ +static void set_lut_inc( + struct dce110_ipp *ipp110, + uint8_t inc, + bool is_float, + bool is_signed); + +static void program_black_offsets( + struct dce110_ipp *ipp110, + struct dev_c_lut16 *offset); + +static void program_white_offsets( + struct dce110_ipp *ipp110, + struct dev_c_lut16 *offset); + +static void program_lut_gamma( + struct dce110_ipp *ipp110, + const struct dev_c_lut16 *gamma, + const struct gamma_parameters *params); + +static void program_prescale( + struct dce110_ipp *ipp110, + enum pixel_format pixel_format); + +static void set_legacy_input_gamma_mode( + struct dce110_ipp *ipp110, + bool is_legacy); + +static bool set_legacy_input_gamma_ramp_rgb256x3x16( + struct dce110_ipp *ipp110, + const struct gamma_ramp *gamma_ramp, + const struct gamma_parameters *params); + +static bool set_legacy_input_gamma_ramp_dxgi1( + struct dce110_ipp *ipp110, + const struct gamma_ramp *gamma_ramp, + const struct gamma_parameters *params); + +static bool set_default_gamma( + struct dce110_ipp *ipp110, + enum pixel_format surface_pixel_format); + +static void set_degamma( + struct dce110_ipp *ipp110, + const struct gamma_parameters *params, + bool force_bypass); + +bool dce110_ipp_set_legacy_input_gamma_ramp( + struct input_pixel_processor *ipp, + const struct gamma_ramp *gamma_ramp, + const struct gamma_parameters *params) +{ + struct dce110_ipp *ipp110 = TO_DCE110_IPP(ipp); + + switch (gamma_ramp->type) { + case GAMMA_RAMP_RBG256X3X16: + return set_legacy_input_gamma_ramp_rgb256x3x16( + ipp110, gamma_ramp, params); + case GAMMA_RAMP_DXGI_1: + return set_legacy_input_gamma_ramp_dxgi1( + ipp110, gamma_ramp, params); + default: + ASSERT_CRITICAL(false); + return false; + } +} + +bool dce110_ipp_set_palette( + struct input_pixel_processor *ipp, + const struct dev_c_lut *palette, + uint32_t start, + uint32_t length, + enum pixel_format surface_pixel_format) +{ + struct dce110_ipp *ipp110 = TO_DCE110_IPP(ipp); + uint32_t i; + + if (((start + length) > MAX_INPUT_LUT_ENTRY) || (NULL == palette)) { + BREAK_TO_DEBUGGER(); + /* wrong input */ + return false; + } + + for (i = start; i < start + length; i++) { + ipp110->saved_palette[i] = palette[i]; + ipp110->saved_palette[i] = palette[i]; + ipp110->saved_palette[i] = palette[i]; + } + + return set_default_gamma(ipp110, surface_pixel_format); +} + +bool dce110_ipp_set_degamma( + struct input_pixel_processor *ipp, + const struct gamma_parameters *params, + bool force_bypass) +{ + struct dce110_ipp *ipp110 = TO_DCE110_IPP(ipp); + + set_degamma(ipp110, params, force_bypass); + + return true; +} + +void dce110_ipp_program_prescale( + struct input_pixel_processor *ipp, + enum pixel_format pixel_format) +{ + struct dce110_ipp *ipp110 = TO_DCE110_IPP(ipp); + + program_prescale(ipp110, pixel_format); +} + +void dce110_ipp_set_legacy_input_gamma_mode( + struct input_pixel_processor *ipp, + bool is_legacy) +{ + struct dce110_ipp *ipp110 = TO_DCE110_IPP(ipp); + + set_legacy_input_gamma_mode(ipp110, is_legacy); +} + +static void set_lut_inc( + struct dce110_ipp *ipp110, + uint8_t inc, + bool is_float, + bool is_signed) +{ + const uint32_t addr = DCP_REG(mmDC_LUT_CONTROL); + + uint32_t value = dm_read_reg(ipp110->base.ctx, addr); + + set_reg_field_value( + value, + inc, + DC_LUT_CONTROL, + DC_LUT_INC_R); + + set_reg_field_value( + value, + inc, + DC_LUT_CONTROL, + DC_LUT_INC_G); + + set_reg_field_value( + value, + inc, + DC_LUT_CONTROL, + DC_LUT_INC_B); + + set_reg_field_value( + value, + is_float, + DC_LUT_CONTROL, + DC_LUT_DATA_R_FLOAT_POINT_EN); + + set_reg_field_value( + value, + is_float, + DC_LUT_CONTROL, + DC_LUT_DATA_G_FLOAT_POINT_EN); + + set_reg_field_value( + value, + is_float, + DC_LUT_CONTROL, + DC_LUT_DATA_B_FLOAT_POINT_EN); + + set_reg_field_value( + value, + is_signed, + DC_LUT_CONTROL, + DC_LUT_DATA_R_SIGNED_EN); + + set_reg_field_value( + value, + is_signed, + DC_LUT_CONTROL, + DC_LUT_DATA_G_SIGNED_EN); + + set_reg_field_value( + value, + is_signed, + DC_LUT_CONTROL, + DC_LUT_DATA_B_SIGNED_EN); + + dm_write_reg(ipp110->base.ctx, addr, value); +} + +void dce110_helper_select_lut(struct dce110_ipp *ipp110) +{ + uint32_t value = 0; + + set_lut_inc(ipp110, 0, false, false); + + { + const uint32_t addr = DCP_REG(mmDC_LUT_WRITE_EN_MASK); + + value = dm_read_reg(ipp110->base.ctx, addr); + + /* enable all */ + set_reg_field_value( + value, + 0x7, + DC_LUT_WRITE_EN_MASK, + DC_LUT_WRITE_EN_MASK); + + dm_write_reg(ipp110->base.ctx, addr, value); + } + + { + const uint32_t addr = DCP_REG(mmDC_LUT_RW_MODE); + + value = dm_read_reg(ipp110->base.ctx, addr); + + set_reg_field_value( + value, + 0, + DC_LUT_RW_MODE, + DC_LUT_RW_MODE); + + dm_write_reg(ipp110->base.ctx, addr, value); + } + + { + const uint32_t addr = DCP_REG(mmDC_LUT_CONTROL); + + value = dm_read_reg(ipp110->base.ctx, addr); + + /* 00 - new u0.12 */ + set_reg_field_value( + value, + 3, + DC_LUT_CONTROL, + DC_LUT_DATA_R_FORMAT); + + set_reg_field_value( + value, + 3, + DC_LUT_CONTROL, + DC_LUT_DATA_G_FORMAT); + + set_reg_field_value( + value, + 3, + DC_LUT_CONTROL, + DC_LUT_DATA_B_FORMAT); + + dm_write_reg(ipp110->base.ctx, addr, value); + } + + { + const uint32_t addr = DCP_REG(mmDC_LUT_RW_INDEX); + + value = dm_read_reg(ipp110->base.ctx, addr); + + set_reg_field_value( + value, + 0, + DC_LUT_RW_INDEX, + DC_LUT_RW_INDEX); + + dm_write_reg(ipp110->base.ctx, addr, value); + } +} + +static void program_black_offsets( + struct dce110_ipp *ipp110, + struct dev_c_lut16 *offset) +{ + dm_write_reg(ipp110->base.ctx, + DCP_REG(mmDC_LUT_BLACK_OFFSET_RED), + offset->red); + dm_write_reg(ipp110->base.ctx, + DCP_REG(mmDC_LUT_BLACK_OFFSET_GREEN), + offset->green); + dm_write_reg(ipp110->base.ctx, + DCP_REG(mmDC_LUT_BLACK_OFFSET_BLUE), + offset->blue); +} + +static void program_white_offsets( + struct dce110_ipp *ipp110, + struct dev_c_lut16 *offset) +{ + dm_write_reg(ipp110->base.ctx, + DCP_REG(mmDC_LUT_WHITE_OFFSET_RED), + offset->red); + dm_write_reg(ipp110->base.ctx, + DCP_REG(mmDC_LUT_WHITE_OFFSET_GREEN), + offset->green); + dm_write_reg(ipp110->base.ctx, + DCP_REG(mmDC_LUT_WHITE_OFFSET_BLUE), + offset->blue); +} + +void dce110_helper_program_black_white_offset( + struct dce110_ipp *ipp110, + enum pixel_format surface_pixel_format) +{ + struct dev_c_lut16 black_offset; + struct dev_c_lut16 white_offset; + + /* get black offset */ + + switch (surface_pixel_format) { + case PIXEL_FORMAT_FP16: + /* sRGB gamut, [0.0...1.0] */ + black_offset.red = 0; + black_offset.green = 0; + black_offset.blue = 0; + break; + + case PIXEL_FORMAT_ARGB2101010_XRBIAS: + /* [-1.0...3.0] */ + black_offset.red = 0x100; + black_offset.green = 0x100; + black_offset.blue = 0x100; + break; + + default: + black_offset.red = 0; + black_offset.green = 0; + black_offset.blue = 0; + } + + /* get white offset */ + + switch (surface_pixel_format) { + case PIXEL_FORMAT_FP16: + white_offset.red = 0x3BFF; + white_offset.green = 0x3BFF; + white_offset.blue = 0x3BFF; + break; + + case PIXEL_FORMAT_ARGB2101010_XRBIAS: + white_offset.red = 0x37E; + white_offset.green = 0x37E; + white_offset.blue = 0x37E; + break; + + case PIXEL_FORMAT_ARGB8888: + white_offset.red = 0xFF; + white_offset.green = 0xFF; + white_offset.blue = 0xFF; + break; + + default: + white_offset.red = 0x3FF; + white_offset.green = 0x3FF; + white_offset.blue = 0x3FF; + } + + program_black_offsets(ipp110, &black_offset); + program_white_offsets(ipp110, &white_offset); +} + +static void program_lut_gamma( + struct dce110_ipp *ipp110, + const struct dev_c_lut16 *gamma, + const struct gamma_parameters *params) +{ + uint32_t i = 0; + uint32_t value = 0; + uint32_t addr; + + { + uint8_t max_tries = 10; + uint8_t counter = 0; + + /* Power on LUT memory */ + value = dm_read_reg( + ipp110->base.ctx, DCP_REG(mmDCFE_MEM_PWR_CTRL)); + + set_reg_field_value( + value, + 1, + DCFE_MEM_PWR_CTRL, + DCP_REGAMMA_MEM_PWR_DIS); + + dm_write_reg( + ipp110->base.ctx, DCP_REG(mmDCFE_MEM_PWR_CTRL), value); + + while (counter < max_tries) { + value = + dm_read_reg( + ipp110->base.ctx, + DCP_REG(mmDCFE_MEM_PWR_STATUS)); + + if (get_reg_field_value( + value, + DCFE_MEM_PWR_STATUS, + DCP_REGAMMA_MEM_PWR_STATE) == 0) + break; + + ++counter; + } + + if (counter == max_tries) { + dal_logger_write(ipp110->base.ctx->logger, + LOG_MAJOR_WARNING, + LOG_MINOR_COMPONENT_CONTROLLER, + "%s: regamma lut was not powered on in a timely manner, programming still proceeds\n", + __func__); + } + } + + dce110_helper_program_black_white_offset(ipp110, params->surface_pixel_format); + + dce110_helper_select_lut(ipp110); + + if (params->surface_pixel_format == PIXEL_FORMAT_INDEX8) { + addr = DCP_REG(mmDC_LUT_SEQ_COLOR); + + do { + struct dev_c_lut *index = + ipp110->saved_palette + i; + + set_reg_field_value( + value, + gamma[index->red].red, + DC_LUT_SEQ_COLOR, + DC_LUT_SEQ_COLOR); + dm_write_reg(ipp110->base.ctx, addr, value); + + + set_reg_field_value( + value, + gamma[index->green].green, + DC_LUT_SEQ_COLOR, + DC_LUT_SEQ_COLOR); + dm_write_reg(ipp110->base.ctx, addr, value); + + + set_reg_field_value( + value, + gamma[index->blue].blue, + DC_LUT_SEQ_COLOR, + DC_LUT_SEQ_COLOR); + dm_write_reg(ipp110->base.ctx, addr, value); + + ++i; + } while (i != RGB_256X3X16); + } else { + addr = DCP_REG(mmDC_LUT_SEQ_COLOR); + + do { + set_reg_field_value( + value, + gamma[i].red, + DC_LUT_SEQ_COLOR, + DC_LUT_SEQ_COLOR); + dm_write_reg(ipp110->base.ctx, addr, value); + + + set_reg_field_value( + value, + gamma[i].green, + DC_LUT_SEQ_COLOR, + DC_LUT_SEQ_COLOR); + dm_write_reg(ipp110->base.ctx, addr, value); + + + set_reg_field_value( + value, + gamma[i].blue, + DC_LUT_SEQ_COLOR, + DC_LUT_SEQ_COLOR); + dm_write_reg(ipp110->base.ctx, addr, value); + + ++i; + } while (i != RGB_256X3X16); + } + + /* we are done with DCP LUT memory; re-enable low power mode */ + value = dm_read_reg(ipp110->base.ctx, DCP_REG(mmDCFE_MEM_PWR_CTRL)); + + set_reg_field_value( + value, + 0, + DCFE_MEM_PWR_CTRL, + DCP_REGAMMA_MEM_PWR_DIS); + + dm_write_reg(ipp110->base.ctx, DCP_REG(mmDCFE_MEM_PWR_CTRL), value); +} + +static void program_prescale( + struct dce110_ipp *ipp110, + enum pixel_format pixel_format) +{ + uint32_t prescale_control; + uint32_t prescale_values_grph_r = 0; + uint32_t prescale_values_grph_g = 0; + uint32_t prescale_values_grph_b = 0; + + uint32_t prescale_num; + uint32_t prescale_denom = 1; + uint16_t prescale_hw; + uint32_t bias_num = 0; + uint32_t bias_denom = 1; + uint16_t bias_hw; + + const uint32_t addr_control = DCP_REG(mmPRESCALE_GRPH_CONTROL); + + prescale_control = dm_read_reg(ipp110->base.ctx, addr_control); + + set_reg_field_value( + prescale_control, + 0, + PRESCALE_GRPH_CONTROL, + GRPH_PRESCALE_BYPASS); + + switch (pixel_format) { + case PIXEL_FORMAT_RGB565: + prescale_num = 64; + prescale_denom = 63; + break; + + case PIXEL_FORMAT_ARGB8888: + /* This function should only be called when using regamma + * and bypassing legacy INPUT GAMMA LUT (function name is + * misleading) + */ + prescale_num = 256; + prescale_denom = 255; + break; + + case PIXEL_FORMAT_ARGB2101010: + prescale_num = 1024; + prescale_denom = 1023; + break; + + case PIXEL_FORMAT_ARGB2101010_XRBIAS: + prescale_num = 1024; + prescale_denom = 510; + bias_num = 384; + bias_denom = 1024; + break; + + case PIXEL_FORMAT_FP16: + prescale_num = 1; + break; + + default: + prescale_num = 1; + + set_reg_field_value( + prescale_control, + 1, + PRESCALE_GRPH_CONTROL, + GRPH_PRESCALE_BYPASS); + } + + prescale_hw = fixed_point_to_int_frac( + dal_fixed31_32_from_fraction(prescale_num, prescale_denom), + 2, 13); + + bias_hw = fixed_point_to_int_frac( + dal_fixed31_32_from_fraction(bias_num, bias_denom), + 2, 13); + + + set_reg_field_value( + prescale_values_grph_r, + prescale_hw, + PRESCALE_VALUES_GRPH_R, + GRPH_PRESCALE_SCALE_R); + + set_reg_field_value( + prescale_values_grph_r, + bias_hw, + PRESCALE_VALUES_GRPH_R, + GRPH_PRESCALE_BIAS_R); + + + set_reg_field_value( + prescale_values_grph_g, + prescale_hw, + PRESCALE_VALUES_GRPH_G, + GRPH_PRESCALE_SCALE_G); + + set_reg_field_value( + prescale_values_grph_g, + bias_hw, + PRESCALE_VALUES_GRPH_G, + GRPH_PRESCALE_BIAS_G); + + + set_reg_field_value( + prescale_values_grph_b, + prescale_hw, + PRESCALE_VALUES_GRPH_B, + GRPH_PRESCALE_SCALE_B); + + set_reg_field_value( + prescale_values_grph_b, + bias_hw, + PRESCALE_VALUES_GRPH_B, + GRPH_PRESCALE_BIAS_B); + + dm_write_reg(ipp110->base.ctx, + addr_control, prescale_control); + + { + dm_write_reg(ipp110->base.ctx, + DCP_REG(mmPRESCALE_VALUES_GRPH_R), + prescale_values_grph_r); + } + + { + dm_write_reg(ipp110->base.ctx, + DCP_REG(mmPRESCALE_VALUES_GRPH_G), + prescale_values_grph_g); + } + + { + dm_write_reg(ipp110->base.ctx, + DCP_REG(mmPRESCALE_VALUES_GRPH_B), + prescale_values_grph_b); + } +} + +static void set_legacy_input_gamma_mode( + struct dce110_ipp *ipp110, + bool is_legacy) +{ + const uint32_t addr = DCP_REG(mmINPUT_GAMMA_CONTROL); + uint32_t value = dm_read_reg(ipp110->base.ctx, addr); + + set_reg_field_value( + value, + !is_legacy, + INPUT_GAMMA_CONTROL, + GRPH_INPUT_GAMMA_MODE); + + dm_write_reg(ipp110->base.ctx, addr, value); +} + +static bool set_legacy_input_gamma_ramp_rgb256x3x16( + struct dce110_ipp *ipp110, + const struct gamma_ramp *gamma_ramp, + const struct gamma_parameters *params) +{ + struct dev_c_lut16 *gamma16 = + dm_alloc( + ipp110->base.ctx, + sizeof(struct dev_c_lut16) * MAX_INPUT_LUT_ENTRY); + + if (!gamma16) + return false; + + convert_256_lut_entries_to_gxo_format( + &gamma_ramp->gamma_ramp_rgb256x3x16, gamma16); + + if ((params->surface_pixel_format != PIXEL_FORMAT_ARGB2101010) && + (params->surface_pixel_format != + PIXEL_FORMAT_ARGB2101010_XRBIAS) && + (params->surface_pixel_format != PIXEL_FORMAT_FP16)) { + program_lut_gamma(ipp110, gamma16, params); + dm_free(ipp110->base.ctx, gamma16); + return true; + } + + /* TODO process DirectX-specific formats*/ + dm_free(ipp110->base.ctx, gamma16); + return false; +} + +static bool set_legacy_input_gamma_ramp_dxgi1( + struct dce110_ipp *ipp110, + const struct gamma_ramp *gamma_ramp, + const struct gamma_parameters *params) +{ + struct dev_c_lut16 *gamma16 = + dm_alloc( + ipp110->base.ctx, + sizeof(struct dev_c_lut16) * MAX_INPUT_LUT_ENTRY); + + if (!gamma16) + return false; + + convert_udx_gamma_entries_to_gxo_format( + &gamma_ramp->gamma_ramp_dxgi1, gamma16); + + if ((params->surface_pixel_format != PIXEL_FORMAT_ARGB2101010) && + (params->surface_pixel_format != + PIXEL_FORMAT_ARGB2101010_XRBIAS) && + (params->surface_pixel_format != PIXEL_FORMAT_FP16)) { + program_lut_gamma(ipp110, gamma16, params); + dm_free(ipp110->base.ctx, gamma16); + return true; + } + + /* TODO process DirectX-specific formats*/ + dm_free(ipp110->base.ctx, gamma16); + return false; +} + +static bool set_default_gamma( + struct dce110_ipp *ipp110, + enum pixel_format surface_pixel_format) +{ + uint32_t i; + + struct dev_c_lut16 *gamma16 = NULL; + struct gamma_parameters *params = NULL; + + gamma16 = dm_alloc( + ipp110->base.ctx, + sizeof(struct dev_c_lut16) * MAX_INPUT_LUT_ENTRY); + + if (!gamma16) + return false; + + params = dm_alloc(ipp110->base.ctx, sizeof(*params)); + + if (!params) { + dm_free(ipp110->base.ctx, gamma16); + return false; + } + + for (i = 0; i < MAX_INPUT_LUT_ENTRY; i++) { + gamma16[i].red = gamma16[i].green = + gamma16[i].blue = (uint16_t) (i << 8); + } + + params->surface_pixel_format = surface_pixel_format; + params->regamma_adjust_type = GRAPHICS_REGAMMA_ADJUST_HW; + params->degamma_adjust_type = GRAPHICS_DEGAMMA_ADJUST_HW; + params->selected_gamma_lut = GRAPHICS_GAMMA_LUT_REGAMMA; + params->disable_adjustments = false; + + params->regamma.features.value = 0; + + params->regamma.features.bits.GAMMA_RAMP_ARRAY = 0; + params->regamma.features.bits.GRAPHICS_DEGAMMA_SRGB = 1; + params->regamma.features.bits.OVERLAY_DEGAMMA_SRGB = 1; + + for (i = 0; i < 3; i++) { + params->regamma.gamma_coeff.a0[i] = 31308; + params->regamma.gamma_coeff.a1[i] = 12920; + params->regamma.gamma_coeff.a2[i] = 55; + params->regamma.gamma_coeff.a3[i] = 55; + params->regamma.gamma_coeff.gamma[i] = 2400; + + } + + program_lut_gamma(ipp110, gamma16, params); + + dm_free(ipp110->base.ctx, gamma16); + dm_free(ipp110->base.ctx, params); + + return true; +} + +static void set_degamma( + struct dce110_ipp *ipp110, + const struct gamma_parameters *params, + bool force_bypass) +{ + uint32_t value; + const uint32_t addr = DCP_REG(mmDEGAMMA_CONTROL); + uint32_t degamma_type = + params->regamma.features.bits.GRAPHICS_DEGAMMA_SRGB == 1 ? + 1 : 2; + + value = dm_read_reg(ipp110->base.ctx, addr); + + /* if by pass - no degamma + * when legacy and regamma LUT's we do degamma */ + if (params->degamma_adjust_type == GRAPHICS_DEGAMMA_ADJUST_BYPASS || + (params->surface_pixel_format == PIXEL_FORMAT_FP16 && + params->selected_gamma_lut == + GRAPHICS_GAMMA_LUT_REGAMMA)) + degamma_type = 0; + + if (force_bypass) + degamma_type = 0; + + set_reg_field_value( + value, + degamma_type, + DEGAMMA_CONTROL, + GRPH_DEGAMMA_MODE); + + set_reg_field_value( + value, + degamma_type, + DEGAMMA_CONTROL, + CURSOR_DEGAMMA_MODE); + + set_reg_field_value( + value, + degamma_type, + DEGAMMA_CONTROL, + CURSOR2_DEGAMMA_MODE); + + dm_write_reg(ipp110->base.ctx, addr, value); +} +