From patchwork Thu Feb 11 17:19:56 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Harry Wentland X-Patchwork-Id: 8283221 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 472F19F6E4 for ; Thu, 11 Feb 2016 17:21:47 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 23DEC2017E for ; Thu, 11 Feb 2016 17:21:45 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id CD9502035D for ; Thu, 11 Feb 2016 17:21:41 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 355D47A0AC; Thu, 11 Feb 2016 09:20:56 -0800 (PST) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from na01-bn1-obe.outbound.protection.outlook.com (mail-bn1on0066.outbound.protection.outlook.com [157.56.110.66]) by gabe.freedesktop.org (Postfix) with ESMTPS id 5587C7A0A8 for ; Thu, 11 Feb 2016 09:20:50 -0800 (PST) Received: from CY1PR12CA0064.namprd12.prod.outlook.com (10.163.230.32) by CY1PR12MB0716.namprd12.prod.outlook.com (10.163.238.22) with Microsoft SMTP Server (TLS) id 15.1.409.15; Thu, 11 Feb 2016 17:20:48 +0000 Received: from BY2NAM03FT017.eop-NAM03.prod.protection.outlook.com (2a01:111:f400:7e4a::203) by CY1PR12CA0064.outlook.office365.com (2a01:111:e400:c42b::32) with Microsoft SMTP Server (TLS) id 15.1.403.16 via Frontend Transport; Thu, 11 Feb 2016 17:20:48 +0000 Authentication-Results: spf=none (sender IP is 165.204.84.221) 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 atltwp01.amd.com (165.204.84.221) by BY2NAM03FT017.mail.protection.outlook.com (10.152.84.217) with Microsoft SMTP Server id 15.1.415.6 via Frontend Transport; Thu, 11 Feb 2016 17:20:47 +0000 X-WSS-ID: 0O2E86K-07-0W8-02 X-M-MSG: Received: from satlvexedge01.amd.com (satlvexedge01.amd.com [10.177.96.28]) (using TLSv1 with cipher ECDHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by atltwp01.amd.com (Axway MailGate 5.3.1) with ESMTPS id 21E9A12C1311 for ; Thu, 11 Feb 2016 12:20:44 -0500 (EST) Received: from SATLEXDAG04.amd.com (10.181.40.9) by satlvexedge01.amd.com (10.177.96.28) with Microsoft SMTP Server (TLS) id 14.3.195.1; Thu, 11 Feb 2016 11:21:14 -0600 Received: from STOREXDAG03.amd.com (10.1.13.12) by satlexdag04.amd.com (10.181.40.9) with Microsoft SMTP Server (TLS) id 14.3.266.1; Thu, 11 Feb 2016 12:20:44 -0500 Received: from cnhwentlanub.amd.com (172.29.225.36) by storexdag03.amd.com (10.1.13.12) with Microsoft SMTP Server id 14.3.266.1; Thu, 11 Feb 2016 12:20:42 -0500 From: Harry Wentland To: Subject: [PATCH 16/29] drm/amd/dal: Add surface HW programming Date: Thu, 11 Feb 2016 12:19:56 -0500 Message-ID: <1455211209-26733-17-git-send-email-harry.wentland@amd.com> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1455211209-26733-1-git-send-email-harry.wentland@amd.com> 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.221; CTRY:US; IPV:NLI; EFV:NLI; SFV:NSPM; SFS:(10009020)(6009001)(2980300002)(428002)(189002)(199003)(50226001)(36756003)(1096002)(50986999)(101416001)(189998001)(47776003)(450100001)(33646002)(53416004)(4326007)(105586002)(76176999)(2906002)(5003940100001)(50466002)(86362001)(586003)(77096005)(87936001)(2351001)(1220700001)(229853001)(5008740100001)(11100500001)(106466001)(19580395003)(19580405001)(92566002)(5003600100002)(2950100001)(48376002); DIR:OUT; SFP:1101; SCL:1; SRVR:CY1PR12MB0716; H:atltwp01.amd.com; FPR:; SPF:None; MLV:sfv; MX:1; A:1; LANG:en; X-MS-Office365-Filtering-Correlation-Id: 6df9751a-c328-4770-bbb0-08d33307aee6 X-Microsoft-Exchange-Diagnostics: 1; CY1PR12MB0716; 2:0X+PpmRdPhEQmO3RoxlwFKqa03UKpDn5Ca6fR+ljL3d+07qa5F2I9nJC+glOOe2d3YMN3KuIbwqvCzAYg32yITZrOVhN+xbVZGm8ysPMPqzXlK560Bj90GcSLgtY/8cJFlERAzTUdQV+QiTdC09rVepCuiTnR6HDtkL1AljzCTW5alwyxWNbbxZW+DRodUHA; 3:XFsybxUCgVZCpU3vKN0nTYVnuSBDCMYHgP6zvSgVF0+BnwQzXJFN/VZ3be5lL+Zc2qu0awqil5TTPVqtnsgQ+DAEU20DSrK2Lk412Cf5u+5mCnowch9tHejwiCDqOFmtswT7Ca3fcIywuKbblxKz+LuGkYE33tOsqjmcYZ20P8OOgKLtQXwfcyUoXGAIkDTTyZLpPtkY5BmOAHIQeB9rV8fx9jL5RhTm8EBuc16399Y=; 25:fq0Vrz6M5GhkTDj32+WaEAH9vJeQ1zE0eMuj+ls08oQPxntXunowrPfs/gA9eCit1yzFSqfX1dxLMp7qJM0G7NRYTVanhLPqcg+w3L3+mvQxjAMfkQ7nSPvzuDwgPXpNXKkppbTXjLHuu0jdn1mQg40ETMdvz4kasydAh6SeMq9ruu0W/g/Ax1svW+/O0Y87olxQZJd+4igycEFWUN6NBXNbAPiWmfK9lRmUJmjeGBHdyYfMJSFp+0dzzAamfB+lBEEGuMTUgc8yZ3NkzwB6ZZUfi9aiKvvouI6qgxe7NGqLKj3CHYGptqsBB8fyILYW X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:;SRVR:CY1PR12MB0716; X-Microsoft-Exchange-Diagnostics: 1; CY1PR12MB0716; 20:2uWvIPAGrll6rdOe8TLH65FWKQmITQ/2db4UHG6n87C1gc2mJtfTIeo81oVxbbFLMKrC+58Us6QFumaiOq3Pt9TO2nnjcFBAq+qgOHZJPDfx6iFO/3uNAgDqHsRNdY+DR49yXZJ1kze9KiQ5ABabLsAFX0BlrS5nZqCyBE10PDqpTg+DCIyLaAgGHD06QJ0Acl9eQu8X2sGVo97I9UtJp1k5s2LwDyfNc3rDDw8U/t2pENKstKYROwBP1THRY5pjp/4cxIWUwUkVhb6xR1eksYbpTZ5K0rGtIYfBdp0uWCT57zta/OmoAuOW4doNOuiKG0i6rMZ9IQwYpR46WUblHrYnwbEeMI12BlT8soNYfs8LyfMXTmdmOikqTesheXA/Rn5bYXB47HxuIVsHm0ICbtCXg0EeJh7xfNuHbzmzW0fzL5zIeCVfx283f2Gwj13YetRiYIkoOGCCBOzEjyfyqC6mw16ORH/Qc8ae8z7Z6oUmrQ5QMr65UN7o/ODarsku X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:(767451399110); X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(601004)(2401047)(13023025)(5005006)(13017025)(13024025)(13015025)(8121501046)(13018025)(10201501046)(3002001); SRVR:CY1PR12MB0716; BCL:0; PCL:0; RULEID:; SRVR:CY1PR12MB0716; X-Microsoft-Exchange-Diagnostics: 1; CY1PR12MB0716; 4:jeW4W+QeZQCbjK449IN1dIIAnciy5ohRYFbMTDkSd842r8ron1o2G1QSDBCIHLzGAMJlYq/X5rdmnh9IlnMVQHh2kfv8mSkh74JAbnXJkYjt2VT/cJlUCPn2K5+8neUUvCDEYTyzeez85FbINF79M74TaBfu7RMjZY4a6CMUYLnEaVaLQ63Neahr8vf2mlp3TRvd35OI2NyZR+EXMRFP1kp4FPKMyC8UwtkRtK+v13MgVMUqBscaEN3w4uFcAyohMU2ngw8qdZPz3Ra653abGEI/dzTgnyxCPkac3SIIqhjWDvRfHFCXnAGFn6O/mlXg/s/h9NFYM6RgW30i4231X1wp9/0SsY276CSzy2WknqsJWl74qrSSwYfl4ablDEdybafJOYV/D7XojEnH/4jN5u1gC0rFtttdEt9I5nGAa1///ZCsYq3wDJg8GdLTUZYBV9EiDD71q6xOOFjAJdaMT41hg2blNsrq205PM7Z5I4GZuANZ1kjvotvn95l/aqWE X-Forefront-PRVS: 08497C3D99 X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1; CY1PR12MB0716; 23:20q2vcECOTyPCyhjUmWjQowpcBFLyWfw9PwFRFMh+?= =?us-ascii?Q?LRXjdGjpkKhMJpILm6QL7/wD7Ar3Dcck6T8Z0pJneuGc4FHl/TrF2f4Y70V3?= =?us-ascii?Q?X1jQ1u4ONsGG+4T2I3V8E9irM8L4jBdan8TYY3GPAsDC4AVBxZ/k/H54iByu?= =?us-ascii?Q?gJp92jhbV80lLG7wAWOO8k4Qs9rwglXNB+cz4BTCfDdk9UftqsnQjX5AEwNE?= =?us-ascii?Q?yjR86DnNuTVVbcgC5AJ4qT8KO8YHbBdBezYqdgLdVWCpiGgTpMGiqvdYSvaZ?= =?us-ascii?Q?OVv0OIHk9a6LL7sPJ8M/UK4aeMYnF5q/2SaGdYPZVDk5fZN7LlYr5uGS+I/n?= =?us-ascii?Q?T1BAei6z4dzAcJgH96glsqsMgeVcL9LlLVPTAmTywknbJKBcdhrpR36JHHXj?= =?us-ascii?Q?qNv/ylFvcDP4lnKTWEs7m3Gh5giDPwGUKcLdJKeNnoyeP3KKs3GSP6wuS92C?= =?us-ascii?Q?KUzpKnGLroFWeKqYoGHTEeeJ/81gRNrpy38OyIQNzymQ7hCCTkHvum4B3hkY?= =?us-ascii?Q?n59M/v+ffbaKAxJXaEygD/aRz66ANzHre5DjBLTtGjeda2qMSkUaFMOa9KyH?= =?us-ascii?Q?raK8AL3FkZb2EK7LZiD7d95SyAw8oc3UG0ey2o55H9CsrRsJD7wl+G40xQDb?= =?us-ascii?Q?YOYj6zAIoosKwmmKHPka5puWTxpPxeK5yaJt57o0WOpetwhYLUbQZ8DTh4uV?= =?us-ascii?Q?TSGfGCR7DcOGDKHPkZUxEEXOlWzu4WdOS0MfoFxqrgWZ4Lk/Q9T08MIpSKed?= =?us-ascii?Q?MghXZ8o1CocBqapdNDDAHFSY+qEeRWotzRGsB+ME3B3vz+J+XksIf4nCNvhu?= =?us-ascii?Q?31GfuZIB/feDNd0LGXcXqychTTumvTWiSu1kbQ0ALdHTJDZdVl0KDelGm5L9?= =?us-ascii?Q?rEp2Iw0WufJ+BoT35Q7tj+DSdF9IlJi+Z+3hUA03tVFdTLHWMbnjwJUwpPNN?= =?us-ascii?Q?ZW1VI7mgTpjeZzvvurdamUAkSxCIiw56vn0SEnFUZoN8tV5WnWk2Qo+wDjA4?= =?us-ascii?Q?3o=3D?= X-Microsoft-Exchange-Diagnostics: 1; CY1PR12MB0716; 5:pjKGZ2KnxWmchLKQtvMK0jYQGs9GxE8k6lMZKCwpiyCtqewgZ7jlmimvzwbOWUN4EYfFnwj2WVhvXIGSP+pex8jROQRZc7O1B5t4V4Noc9lziYFhT2CUELjupHXycm5MJnWD20jWe6KrEDnEz9qOlg==; 24:fIqUf4gs833sTZtMcYwRsVBT5y40ObXSV8HM/zYY/aoC+QRIj3oP0fdGHhVw2PIwNAwM2OaD8kAJPwY/sGiIeMipT8sGRvvNbXFx6zJ6Yng=; 20:MWN0on86Fy9XtE3vElToyaOzUh/X7eNjZQ6zXx3VB/iOLmccy5f/Qsb5icMrbSWhqLyci4YDRH8zkXFrq4j0mVycBExpg63TtDzej7oPvWdGNZYpFS8bt1SYFJ32/uyFj1ffNuKz0mdW/EDPRkBdmar+fqePn7CJyw1nEG1jg4ijHMhxlaBXe63OJE65ndIYZNCEsbc3WTja7osSw2GwHbHmFBBTDfbEPDqPHIpNiLX9vAsPnB/XwUvDtTrZ2KCt SpamDiagnosticOutput: 1:23 SpamDiagnosticMetadata: NSPM X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 11 Feb 2016 17:20:47.9797 (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.221]; Helo=[atltwp01.amd.com] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: CY1PR12MB0716 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=-3.9 required=5.0 tests=BAD_ENC_HEADER,BAYES_00, RCVD_IN_DNSWL_MED,RP_MATCHES_RCVD,UNPARSEABLE_RELAY,URG_BIZ 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 watermark, DMIF, and surface programming. Signed-off-by: Harry Wentland Reviewed-by: Alex Deucher --- .../gpu/drm/amd/dal/dc/dce110/dce110_mem_input.c | 965 +++++++++++++++++++++ .../gpu/drm/amd/dal/dc/dce110/dce110_mem_input.h | 117 +++ 2 files changed, 1082 insertions(+) create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_mem_input.c create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_mem_input.h diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_mem_input.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_mem_input.c new file mode 100644 index 000000000000..3a928e63e647 --- /dev/null +++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_mem_input.c @@ -0,0 +1,965 @@ +/* + * 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 "dce/dce_11_0_d.h" +#include "dce/dce_11_0_sh_mask.h" +/* TODO: this needs to be looked at, used by Stella's workaround*/ +#include "gmc/gmc_8_2_d.h" +#include "gmc/gmc_8_2_sh_mask.h" + +#include "include/logger_interface.h" +#include "adapter_service_interface.h" +#include "inc/bandwidth_calcs.h" + +#include "dce110_mem_input.h" + +#define MAX_WATERMARK 0xFFFF +#define SAFE_NBP_MARK 0x7FFF + +#define DCP_REG(reg) (reg + mem_input110->offsets.dcp) +#define DMIF_REG(reg) (reg + mem_input110->offsets.dmif) +#define PIPE_REG(reg) (reg + mem_input110->offsets.pipe) + +static void set_flip_control( + struct dce110_mem_input *mem_input110, + bool immediate) +{ + uint32_t value = 0; + + value = dm_read_reg( + mem_input110->base.ctx, + DCP_REG(mmGRPH_FLIP_CONTROL)); + set_reg_field_value(value, 0, + GRPH_FLIP_CONTROL, + GRPH_SURFACE_UPDATE_IMMEDIATE_EN); + set_reg_field_value(value, 0, + GRPH_FLIP_CONTROL, + GRPH_SURFACE_UPDATE_H_RETRACE_EN); + if (immediate == true) + set_reg_field_value(value, 1, + GRPH_FLIP_CONTROL, + GRPH_SURFACE_UPDATE_IMMEDIATE_EN); + + dm_write_reg( + mem_input110->base.ctx, + DCP_REG(mmGRPH_FLIP_CONTROL), + value); +} + +static void program_sec_addr( + struct dce110_mem_input *mem_input110, + PHYSICAL_ADDRESS_LOC address) +{ + uint32_t value = 0; + uint32_t temp = 0; + /*high register MUST be programmed first*/ + temp = address.high_part & +GRPH_SECONDARY_SURFACE_ADDRESS_HIGH__GRPH_SECONDARY_SURFACE_ADDRESS_HIGH_MASK; + + set_reg_field_value(value, temp, + GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, + GRPH_SECONDARY_SURFACE_ADDRESS_HIGH); + + dm_write_reg( + mem_input110->base.ctx, + DCP_REG(mmGRPH_SECONDARY_SURFACE_ADDRESS_HIGH), + value); + + temp = 0; + value = 0; + temp = address.low_part >> + GRPH_SECONDARY_SURFACE_ADDRESS__GRPH_SECONDARY_SURFACE_ADDRESS__SHIFT; + + set_reg_field_value(value, temp, + GRPH_SECONDARY_SURFACE_ADDRESS, + GRPH_SECONDARY_SURFACE_ADDRESS); + + dm_write_reg( + mem_input110->base.ctx, + DCP_REG(mmGRPH_SECONDARY_SURFACE_ADDRESS), + value); +} + +static void program_pri_addr( + struct dce110_mem_input *mem_input110, + PHYSICAL_ADDRESS_LOC address) +{ + uint32_t value = 0; + uint32_t temp = 0; + + /*high register MUST be programmed first*/ + temp = address.high_part & +GRPH_PRIMARY_SURFACE_ADDRESS_HIGH__GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_MASK; + + set_reg_field_value(value, temp, + GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, + GRPH_PRIMARY_SURFACE_ADDRESS_HIGH); + + dm_write_reg( + mem_input110->base.ctx, + DCP_REG(mmGRPH_PRIMARY_SURFACE_ADDRESS_HIGH), + value); + + temp = 0; + value = 0; + temp = address.low_part >> + GRPH_PRIMARY_SURFACE_ADDRESS__GRPH_PRIMARY_SURFACE_ADDRESS__SHIFT; + + set_reg_field_value(value, temp, + GRPH_PRIMARY_SURFACE_ADDRESS, + GRPH_PRIMARY_SURFACE_ADDRESS); + + dm_write_reg( + mem_input110->base.ctx, + DCP_REG(mmGRPH_PRIMARY_SURFACE_ADDRESS), + value); +} + +static void program_addr( + struct dce110_mem_input *mem_input110, + const struct dc_plane_address *addr) +{ + switch (addr->type) { + case PLN_ADDR_TYPE_GRAPHICS: + program_pri_addr( + mem_input110, + addr->grph.addr); + break; + case PLN_ADDR_TYPE_GRPH_STEREO: + program_pri_addr( + mem_input110, + addr->grph_stereo.left_addr); + program_sec_addr( + mem_input110, + addr->grph_stereo.right_addr); + break; + case PLN_ADDR_TYPE_VIDEO_PROGRESSIVE: + default: + /* not supported */ + BREAK_TO_DEBUGGER(); + } +} + +static void enable(struct dce110_mem_input *mem_input110) +{ + uint32_t value = 0; + + value = dm_read_reg(mem_input110->base.ctx, DCP_REG(mmGRPH_ENABLE)); + set_reg_field_value(value, 1, GRPH_ENABLE, GRPH_ENABLE); + dm_write_reg(mem_input110->base.ctx, + DCP_REG(mmGRPH_ENABLE), + value); +} + +static void program_tiling( + struct dce110_mem_input *mem_input110, + const struct dc_tiling_info *info, + const enum surface_pixel_format pixel_format) +{ + uint32_t value = 0; + + value = dm_read_reg( + mem_input110->base.ctx, + DCP_REG(mmGRPH_CONTROL)); + + set_reg_field_value(value, info->num_banks, + GRPH_CONTROL, GRPH_NUM_BANKS); + + set_reg_field_value(value, info->bank_width, + GRPH_CONTROL, GRPH_BANK_WIDTH); + + set_reg_field_value(value, info->bank_height, + GRPH_CONTROL, GRPH_BANK_HEIGHT); + + set_reg_field_value(value, info->tile_aspect, + GRPH_CONTROL, GRPH_MACRO_TILE_ASPECT); + + set_reg_field_value(value, info->tile_split, + GRPH_CONTROL, GRPH_TILE_SPLIT); + + set_reg_field_value(value, info->tile_mode, + GRPH_CONTROL, GRPH_MICRO_TILE_MODE); + + set_reg_field_value(value, info->pipe_config, + GRPH_CONTROL, GRPH_PIPE_CONFIG); + + set_reg_field_value(value, info->array_mode, + GRPH_CONTROL, GRPH_ARRAY_MODE); + + set_reg_field_value(value, 1, + GRPH_CONTROL, GRPH_COLOR_EXPANSION_MODE); + + set_reg_field_value(value, 0, + GRPH_CONTROL, GRPH_Z); + + dm_write_reg( + mem_input110->base.ctx, + DCP_REG(mmGRPH_CONTROL), + value); +} + +static void program_size_and_rotation( + struct dce110_mem_input *mem_input110, + enum dc_rotation_angle rotation, + const union plane_size *plane_size) +{ + uint32_t value = 0; + union plane_size local_size = *plane_size; + + if (rotation == ROTATION_ANGLE_90 || + rotation == ROTATION_ANGLE_270) { + + uint32_t swap; + + swap = local_size.grph.surface_size.x; + local_size.grph.surface_size.x = + local_size.grph.surface_size.y; + local_size.grph.surface_size.y = swap; + + swap = local_size.grph.surface_size.width; + local_size.grph.surface_size.width = + local_size.grph.surface_size.height; + local_size.grph.surface_size.height = swap; + } + + set_reg_field_value(value, local_size.grph.surface_size.x, + GRPH_X_START, GRPH_X_START); + dm_write_reg( + mem_input110->base.ctx, + DCP_REG(mmGRPH_X_START), + value); + + value = 0; + set_reg_field_value(value, local_size.grph.surface_size.y, + GRPH_Y_START, GRPH_Y_START); + dm_write_reg( + mem_input110->base.ctx, + DCP_REG(mmGRPH_Y_START), + value); + + value = 0; + set_reg_field_value(value, local_size.grph.surface_size.width, + GRPH_X_END, GRPH_X_END); + dm_write_reg( + mem_input110->base.ctx, + DCP_REG(mmGRPH_X_END), + value); + + value = 0; + set_reg_field_value(value, local_size.grph.surface_size.height, + GRPH_Y_END, GRPH_Y_END); + dm_write_reg( + mem_input110->base.ctx, + DCP_REG(mmGRPH_Y_END), + value); + + value = 0; + set_reg_field_value(value, local_size.grph.surface_pitch, + GRPH_PITCH, GRPH_PITCH); + dm_write_reg( + mem_input110->base.ctx, + DCP_REG(mmGRPH_PITCH), + value); + + + value = 0; + switch (rotation) { + case ROTATION_ANGLE_90: + set_reg_field_value(value, 3, + HW_ROTATION, GRPH_ROTATION_ANGLE); + break; + case ROTATION_ANGLE_180: + set_reg_field_value(value, 2, + HW_ROTATION, GRPH_ROTATION_ANGLE); + break; + case ROTATION_ANGLE_270: + set_reg_field_value(value, 1, + HW_ROTATION, GRPH_ROTATION_ANGLE); + break; + default: + set_reg_field_value(value, 0, + HW_ROTATION, GRPH_ROTATION_ANGLE); + break; + } + dm_write_reg( + mem_input110->base.ctx, + DCP_REG(mmHW_ROTATION), + value); +} + +static void program_pixel_format( + struct dce110_mem_input *mem_input110, + enum surface_pixel_format format) +{ + if (format >= SURFACE_PIXEL_FORMAT_GRPH_BEGIN && + format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) { + uint32_t value = 0; + + /* handle colour twizzle formats, swapping R and B */ + if (format == SURFACE_PIXEL_FORMAT_GRPH_BGRA8888 || + format == SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010 || + format == + SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS || + format == SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F) { + set_reg_field_value( + value, 2, GRPH_SWAP_CNTL, GRPH_RED_CROSSBAR); + set_reg_field_value( + value, 2, GRPH_SWAP_CNTL, GRPH_BLUE_CROSSBAR); + } + + dm_write_reg( + mem_input110->base.ctx, + DCP_REG(mmGRPH_SWAP_CNTL), + value); + + + value = dm_read_reg( + mem_input110->base.ctx, + DCP_REG(mmGRPH_CONTROL)); + + switch (format) { + case SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS: + set_reg_field_value( + value, 0, GRPH_CONTROL, GRPH_DEPTH); + set_reg_field_value( + value, 0, GRPH_CONTROL, GRPH_FORMAT); + break; + case SURFACE_PIXEL_FORMAT_GRPH_RGB565: + set_reg_field_value( + value, 1, GRPH_CONTROL, GRPH_DEPTH); + set_reg_field_value( + value, 1, GRPH_CONTROL, GRPH_FORMAT); + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: + case SURFACE_PIXEL_FORMAT_GRPH_BGRA8888: + set_reg_field_value( + value, 2, GRPH_CONTROL, GRPH_DEPTH); + set_reg_field_value( + value, 0, GRPH_CONTROL, GRPH_FORMAT); + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS: + set_reg_field_value( + value, 2, GRPH_CONTROL, GRPH_DEPTH); + set_reg_field_value( + value, 1, GRPH_CONTROL, GRPH_FORMAT); + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F: + set_reg_field_value( + value, 3, GRPH_CONTROL, GRPH_DEPTH); + set_reg_field_value( + value, 0, GRPH_CONTROL, GRPH_FORMAT); + break; + default: + break; + } + dm_write_reg( + mem_input110->base.ctx, + DCP_REG(mmGRPH_CONTROL), + value); + + /*TODO [hwentlan] MOVE THIS TO CONTROLLER GAMMA!!!!!*/ + value = dm_read_reg( + mem_input110->base.ctx, + DCP_REG(mmPRESCALE_GRPH_CONTROL)); + + if (format == SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F) { + set_reg_field_value( + value, 1, PRESCALE_GRPH_CONTROL, + GRPH_PRESCALE_SELECT); + set_reg_field_value( + value, 1, PRESCALE_GRPH_CONTROL, + GRPH_PRESCALE_R_SIGN); + set_reg_field_value( + value, 1, PRESCALE_GRPH_CONTROL, + GRPH_PRESCALE_G_SIGN); + set_reg_field_value( + value, 1, PRESCALE_GRPH_CONTROL, + GRPH_PRESCALE_B_SIGN); + } else { + set_reg_field_value( + value, 0, PRESCALE_GRPH_CONTROL, + GRPH_PRESCALE_SELECT); + set_reg_field_value( + value, 0, PRESCALE_GRPH_CONTROL, + GRPH_PRESCALE_R_SIGN); + set_reg_field_value( + value, 0, PRESCALE_GRPH_CONTROL, + GRPH_PRESCALE_G_SIGN); + set_reg_field_value( + value, 0, PRESCALE_GRPH_CONTROL, + GRPH_PRESCALE_B_SIGN); + } + dm_write_reg( + mem_input110->base.ctx, + DCP_REG(mmPRESCALE_GRPH_CONTROL), + value); + } +} + +static void wait_for_no_surface_update_pending( + struct dce110_mem_input *mem_input110) +{ + uint32_t value; + + do { + value = dm_read_reg(mem_input110->base.ctx, + DCP_REG(mmGRPH_UPDATE)); + + } while (get_reg_field_value(value, GRPH_UPDATE, + GRPH_SURFACE_UPDATE_PENDING)); +} + +bool dce110_mem_input_program_surface_flip_and_addr( + struct mem_input *mem_input, + const struct dc_plane_address *address, + bool flip_immediate) +{ + struct dce110_mem_input *mem_input110 = TO_DCE110_MEM_INPUT(mem_input); + + set_flip_control(mem_input110, flip_immediate); + program_addr(mem_input110, + address); + + if (flip_immediate) + wait_for_no_surface_update_pending(mem_input110); + + return true; +} + +bool dce110_mem_input_program_surface_config( + struct mem_input *mem_input, + enum surface_pixel_format format, + struct dc_tiling_info *tiling_info, + union plane_size *plane_size, + enum dc_rotation_angle rotation) +{ + struct dce110_mem_input *mem_input110 = TO_DCE110_MEM_INPUT(mem_input); + + enable(mem_input110); + program_tiling(mem_input110, tiling_info, format); + program_size_and_rotation(mem_input110, rotation, plane_size); + program_pixel_format(mem_input110, format); + + return true; +} + +static void program_urgency_watermark( + const struct dc_context *ctx, + const uint32_t offset, + struct bw_watermarks marks_low, + uint32_t total_dest_line_time_ns) +{ + /* register value */ + uint32_t urgency_cntl = 0; + uint32_t wm_mask_cntl = 0; + + uint32_t urgency_addr = offset + mmDPG_PIPE_URGENCY_CONTROL; + uint32_t wm_addr = offset + mmDPG_WATERMARK_MASK_CONTROL; + + /*Write mask to enable reading/writing of watermark set A*/ + wm_mask_cntl = dm_read_reg(ctx, wm_addr); + set_reg_field_value(wm_mask_cntl, + 1, + DPG_WATERMARK_MASK_CONTROL, + URGENCY_WATERMARK_MASK); + dm_write_reg(ctx, wm_addr, wm_mask_cntl); + + urgency_cntl = dm_read_reg(ctx, urgency_addr); + + set_reg_field_value( + urgency_cntl, + marks_low.a_mark, + DPG_PIPE_URGENCY_CONTROL, + URGENCY_LOW_WATERMARK); + + set_reg_field_value( + urgency_cntl, + total_dest_line_time_ns, + DPG_PIPE_URGENCY_CONTROL, + URGENCY_HIGH_WATERMARK); + dm_write_reg(ctx, urgency_addr, urgency_cntl); + + + /*Write mask to enable reading/writing of watermark set B*/ + wm_mask_cntl = dm_read_reg(ctx, wm_addr); + set_reg_field_value(wm_mask_cntl, + 2, + DPG_WATERMARK_MASK_CONTROL, + URGENCY_WATERMARK_MASK); + dm_write_reg(ctx, wm_addr, wm_mask_cntl); + + urgency_cntl = dm_read_reg(ctx, urgency_addr); + + set_reg_field_value(urgency_cntl, + marks_low.b_mark, + DPG_PIPE_URGENCY_CONTROL, + URGENCY_LOW_WATERMARK); + + set_reg_field_value(urgency_cntl, + total_dest_line_time_ns, + DPG_PIPE_URGENCY_CONTROL, + URGENCY_HIGH_WATERMARK); + dm_write_reg(ctx, urgency_addr, urgency_cntl); +} + +static void program_stutter_watermark( + const struct dc_context *ctx, + const uint32_t offset, + struct bw_watermarks marks) +{ + /* register value */ + uint32_t stutter_cntl = 0; + uint32_t wm_mask_cntl = 0; + + uint32_t stutter_addr = offset + mmDPG_PIPE_STUTTER_CONTROL; + uint32_t wm_addr = offset + mmDPG_WATERMARK_MASK_CONTROL; + + /*Write mask to enable reading/writing of watermark set A*/ + + wm_mask_cntl = dm_read_reg(ctx, wm_addr); + set_reg_field_value(wm_mask_cntl, + 1, + DPG_WATERMARK_MASK_CONTROL, + STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK); + dm_write_reg(ctx, wm_addr, wm_mask_cntl); + + stutter_cntl = dm_read_reg(ctx, stutter_addr); + + set_reg_field_value(stutter_cntl, + 1, + DPG_PIPE_STUTTER_CONTROL, + STUTTER_ENABLE); + set_reg_field_value(stutter_cntl, + 1, + DPG_PIPE_STUTTER_CONTROL, + STUTTER_IGNORE_FBC); + + /*Write watermark set A*/ + set_reg_field_value(stutter_cntl, + marks.a_mark, + DPG_PIPE_STUTTER_CONTROL, + STUTTER_EXIT_SELF_REFRESH_WATERMARK); + dm_write_reg(ctx, stutter_addr, stutter_cntl); + + /*Write mask to enable reading/writing of watermark set B*/ + wm_mask_cntl = dm_read_reg(ctx, wm_addr); + set_reg_field_value(wm_mask_cntl, + 2, + DPG_WATERMARK_MASK_CONTROL, + STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK); + dm_write_reg(ctx, wm_addr, wm_mask_cntl); + + stutter_cntl = dm_read_reg(ctx, stutter_addr); + set_reg_field_value(stutter_cntl, + 1, + DPG_PIPE_STUTTER_CONTROL, + STUTTER_ENABLE); + set_reg_field_value(stutter_cntl, + 1, + DPG_PIPE_STUTTER_CONTROL, + STUTTER_IGNORE_FBC); + + /*Write watermark set B*/ + set_reg_field_value(stutter_cntl, + marks.b_mark, + DPG_PIPE_STUTTER_CONTROL, + STUTTER_EXIT_SELF_REFRESH_WATERMARK); + dm_write_reg(ctx, stutter_addr, stutter_cntl); +} + +static void program_nbp_watermark( + const struct dc_context *ctx, + const uint32_t offset, + struct bw_watermarks marks) +{ + uint32_t value; + uint32_t addr; + /* Write mask to enable reading/writing of watermark set A */ + addr = offset + mmDPG_WATERMARK_MASK_CONTROL; + value = dm_read_reg(ctx, addr); + set_reg_field_value( + value, + 1, + DPG_WATERMARK_MASK_CONTROL, + NB_PSTATE_CHANGE_WATERMARK_MASK); + dm_write_reg(ctx, addr, value); + + addr = offset + mmDPG_PIPE_NB_PSTATE_CHANGE_CONTROL; + value = dm_read_reg(ctx, addr); + set_reg_field_value( + value, + 1, + DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, + NB_PSTATE_CHANGE_ENABLE); + set_reg_field_value( + value, + 1, + DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, + NB_PSTATE_CHANGE_URGENT_DURING_REQUEST); + set_reg_field_value( + value, + 1, + DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, + NB_PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST); + dm_write_reg(ctx, addr, value); + + /* Write watermark set A */ + value = dm_read_reg(ctx, addr); + set_reg_field_value( + value, + marks.a_mark, + DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, + NB_PSTATE_CHANGE_WATERMARK); + dm_write_reg(ctx, addr, value); + + /* Write mask to enable reading/writing of watermark set B */ + addr = offset + mmDPG_WATERMARK_MASK_CONTROL; + value = dm_read_reg(ctx, addr); + set_reg_field_value( + value, + 2, + DPG_WATERMARK_MASK_CONTROL, + NB_PSTATE_CHANGE_WATERMARK_MASK); + dm_write_reg(ctx, addr, value); + + addr = offset + mmDPG_PIPE_NB_PSTATE_CHANGE_CONTROL; + value = dm_read_reg(ctx, addr); + set_reg_field_value( + value, + 1, + DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, + NB_PSTATE_CHANGE_ENABLE); + set_reg_field_value( + value, + 1, + DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, + NB_PSTATE_CHANGE_URGENT_DURING_REQUEST); + set_reg_field_value( + value, + 1, + DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, + NB_PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST); + dm_write_reg(ctx, addr, value); + + /* Write watermark set B */ + value = dm_read_reg(ctx, addr); + set_reg_field_value( + value, + marks.b_mark, + DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, + NB_PSTATE_CHANGE_WATERMARK); + dm_write_reg(ctx, addr, value); +} + +void dce110_mem_input_program_safe_display_marks(struct mem_input *mi) +{ + struct dce110_mem_input *bm_dce110 = TO_DCE110_MEM_INPUT(mi); + struct bw_watermarks max_marks = { MAX_WATERMARK, MAX_WATERMARK }; + struct bw_watermarks nbp_marks = { SAFE_NBP_MARK, SAFE_NBP_MARK }; + + program_urgency_watermark( + mi->ctx, bm_dce110->offsets.dmif, max_marks, MAX_WATERMARK); + program_stutter_watermark(mi->ctx, bm_dce110->offsets.dmif, max_marks); + program_nbp_watermark(mi->ctx, bm_dce110->offsets.dmif, nbp_marks); +} + +void dce110_mem_input_program_display_marks( + struct mem_input *mem_input, + struct bw_watermarks nbp, + struct bw_watermarks stutter, + struct bw_watermarks urgent, + uint32_t h_total, + uint32_t pixel_clk_in_khz, + uint32_t pstate_blackout_duration_ns) +{ + struct dce110_mem_input *bm_dce110 = TO_DCE110_MEM_INPUT(mem_input); + uint32_t total_dest_line_time_ns = 1000000UL * h_total + / pixel_clk_in_khz + pstate_blackout_duration_ns; + + program_urgency_watermark( + mem_input->ctx, + bm_dce110->offsets.dmif, + urgent, + total_dest_line_time_ns); + program_nbp_watermark( + mem_input->ctx, + bm_dce110->offsets.dmif, + nbp); + program_stutter_watermark( + mem_input->ctx, + bm_dce110->offsets.dmif, + stutter); +} + +static uint32_t get_dmif_switch_time_us(struct dc_crtc_timing *timing) +{ + uint32_t frame_time; + uint32_t pixels_per_second; + uint32_t pixels_per_frame; + uint32_t refresh_rate; + const uint32_t us_in_sec = 1000000; + const uint32_t min_single_frame_time_us = 30000; + /*return double of frame time*/ + const uint32_t single_frame_time_multiplier = 2; + + if (timing == NULL) + return single_frame_time_multiplier * min_single_frame_time_us; + + /*TODO: should we use pixel format normalized pixel clock here?*/ + pixels_per_second = timing->pix_clk_khz * 1000; + pixels_per_frame = timing->h_total * timing->v_total; + + if (!pixels_per_second || !pixels_per_frame) { + /* avoid division by zero */ + ASSERT(pixels_per_frame); + ASSERT(pixels_per_second); + return single_frame_time_multiplier * min_single_frame_time_us; + } + + refresh_rate = pixels_per_second / pixels_per_frame; + + if (!refresh_rate) { + /* avoid division by zero*/ + ASSERT(refresh_rate); + return single_frame_time_multiplier * min_single_frame_time_us; + } + + frame_time = us_in_sec / refresh_rate; + + if (frame_time < min_single_frame_time_us) + frame_time = min_single_frame_time_us; + + frame_time *= single_frame_time_multiplier; + + return frame_time; +} + +void dce110_mem_input_allocate_dmif_buffer( + struct mem_input *mi, + struct dc_crtc_timing *timing, + uint32_t paths_num) +{ + const uint32_t retry_delay = 10; + uint32_t retry_count = get_dmif_switch_time_us(timing) / retry_delay; + + struct dce110_mem_input *bm110 = TO_DCE110_MEM_INPUT(mi); + uint32_t addr = bm110->offsets.pipe + mmPIPE0_DMIF_BUFFER_CONTROL; + uint32_t value; + uint32_t field; + uint32_t pix_dur; + + if (bm110->supported_stutter_mode + & STUTTER_MODE_NO_DMIF_BUFFER_ALLOCATION) + goto register_underflow_int; + + /*Allocate DMIF buffer*/ + value = dm_read_reg(mi->ctx, addr); + field = get_reg_field_value( + value, PIPE0_DMIF_BUFFER_CONTROL, DMIF_BUFFERS_ALLOCATED); + if (field == 2) + goto register_underflow_int; + + set_reg_field_value( + value, + 2, + PIPE0_DMIF_BUFFER_CONTROL, + DMIF_BUFFERS_ALLOCATED); + + dm_write_reg(mi->ctx, addr, value); + + do { + value = dm_read_reg(mi->ctx, addr); + field = get_reg_field_value( + value, + PIPE0_DMIF_BUFFER_CONTROL, + DMIF_BUFFERS_ALLOCATION_COMPLETED); + + if (field) + break; + + dm_delay_in_microseconds(mi->ctx, retry_delay); + retry_count--; + + } while (retry_count > 0); + + if (field == 0) + dal_logger_write(mi->ctx->logger, + LOG_MAJOR_ERROR, + LOG_MINOR_COMPONENT_GPU, + "%s: DMIF allocation failed", + __func__); + + + if (timing->pix_clk_khz != 0) { + addr = mmDPG_PIPE_ARBITRATION_CONTROL1 + bm110->offsets.dmif; + value = dm_read_reg(mi->ctx, addr); + pix_dur = 1000000000ULL / timing->pix_clk_khz; + + set_reg_field_value( + value, + pix_dur, + DPG_PIPE_ARBITRATION_CONTROL1, + PIXEL_DURATION); + + dm_write_reg(mi->ctx, addr, value); + } + + /* + * Stella Wong proposed the following change + * + * Value of mcHubRdReqDmifLimit.ENABLE: + * 00 - disable DMIF rdreq limit + * 01 - enable DMIF rdreq limit, disabled by DMIF stall = 1 || urg != 0 + * 02 - enable DMIF rdreq limit, disable by DMIF stall = 1 + * 03 - force enable DMIF rdreq limit, ignore DMIF stall / urgent + */ + if (!IS_FPGA_MAXIMUS_DC(mi->ctx->dce_environment)) { + addr = mmMC_HUB_RDREQ_DMIF_LIMIT; + value = dm_read_reg(mi->ctx, addr); + + if (paths_num > 1) + set_reg_field_value(value, 0, MC_HUB_RDREQ_DMIF_LIMIT, ENABLE); + else + set_reg_field_value(value, 3, MC_HUB_RDREQ_DMIF_LIMIT, ENABLE); + dm_write_reg(mi->ctx, addr, value); + } + +register_underflow_int: + /*todo*/; + /*register_interrupt(bm110, irq_source, ctrl_id);*/ +} + +static void deallocate_dmif_buffer_helper( + struct dc_context *ctx, uint32_t offset) +{ + uint32_t value; + uint32_t count = 0xBB8; /* max retry count */ + + value = dm_read_reg(ctx, mmPIPE0_DMIF_BUFFER_CONTROL + offset); + + if (!get_reg_field_value( + value, PIPE0_DMIF_BUFFER_CONTROL, DMIF_BUFFERS_ALLOCATED)) + return; + + set_reg_field_value( + value, 0, PIPE0_DMIF_BUFFER_CONTROL, DMIF_BUFFERS_ALLOCATED); + + dm_write_reg( + ctx, mmPIPE0_DMIF_BUFFER_CONTROL + offset, value); + + do { + value = dm_read_reg(ctx, mmPIPE0_DMIF_BUFFER_CONTROL + offset); + dm_delay_in_microseconds(ctx, 10); + count--; + } while (count > 0 && + !get_reg_field_value( + value, + PIPE0_DMIF_BUFFER_CONTROL, + DMIF_BUFFERS_ALLOCATION_COMPLETED)); +} + +void dce110_mem_input_deallocate_dmif_buffer( + struct mem_input *mi, uint32_t paths_num) +{ + struct dce110_mem_input *bm_dce110 = TO_DCE110_MEM_INPUT(mi); + uint32_t value; + + if (!(bm_dce110->supported_stutter_mode & + STUTTER_MODE_NO_DMIF_BUFFER_ALLOCATION)) { + + /* De-allocate DMIF buffer first */ + if (mmPIPE0_DMIF_BUFFER_CONTROL + bm_dce110->offsets.pipe != 0) + deallocate_dmif_buffer_helper( + mi->ctx, bm_dce110->offsets.pipe); + } + + /* TODO: unregister underflow interrupt + unregisterInterrupt(); + */ + + /* Value of mcHubRdReqDmifLimit.ENABLE. + * 00 - disable dmif rdreq limit + * 01 - enable dmif rdreq limit, disable by dmif stall=1||urg!=0 + * 02 - enable dmif rdreq limit, disable by dmif stall=1 + * 03 - force enable dmif rdreq limit, ignore dmif stall/urgent + * Stella Wong proposed this change. */ + if (!IS_FPGA_MAXIMUS_DC(mi->ctx->dce_environment)) { + value = dm_read_reg(mi->ctx, mmMC_HUB_RDREQ_DMIF_LIMIT); + if (paths_num > 1) + set_reg_field_value(value, 0, MC_HUB_RDREQ_DMIF_LIMIT, ENABLE); + else + set_reg_field_value(value, 3, MC_HUB_RDREQ_DMIF_LIMIT, ENABLE); + + dm_write_reg(mi->ctx, mmMC_HUB_RDREQ_DMIF_LIMIT, value); + } +} + +static struct mem_input_funcs dce110_mem_input_funcs = { + .mem_input_program_safe_display_marks = + dce110_mem_input_program_safe_display_marks, + .mem_input_program_display_marks = + dce110_mem_input_program_display_marks, + .mem_input_allocate_dmif_buffer = dce110_mem_input_allocate_dmif_buffer, + .mem_input_deallocate_dmif_buffer = + dce110_mem_input_deallocate_dmif_buffer, + .mem_input_program_surface_flip_and_addr = + dce110_mem_input_program_surface_flip_and_addr, + .mem_input_program_surface_config = + dce110_mem_input_program_surface_config, +}; +/*****************************************/ +/* Constructor, Destructor */ +/*****************************************/ + +bool dce110_mem_input_construct( + struct dce110_mem_input *mem_input110, + struct dc_context *ctx, + uint32_t inst, + const struct dce110_mem_input_reg_offsets *offsets) +{ + mem_input110->base.funcs = &dce110_mem_input_funcs; + mem_input110->base.ctx = ctx; + + mem_input110->base.inst = inst; + + mem_input110->offsets = *offsets; + + mem_input110->supported_stutter_mode = 0; + dal_adapter_service_get_feature_value(FEATURE_STUTTER_MODE, + &(mem_input110->supported_stutter_mode), + sizeof(mem_input110->supported_stutter_mode)); + + return true; +} + +void dce110_mem_input_destroy(struct mem_input **mem_input) +{ + dm_free((*mem_input)->ctx, TO_DCE110_MEM_INPUT(*mem_input)); + *mem_input = NULL; +} diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_mem_input.h b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_mem_input.h new file mode 100644 index 000000000000..5a4e5fe33a79 --- /dev/null +++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_mem_input.h @@ -0,0 +1,117 @@ +/* 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_MEM_INPUT_DCE110_H__ +#define __DC_MEM_INPUT_DCE110_H__ + +#include "inc/mem_input.h" + +#define TO_DCE110_MEM_INPUT(mi)\ + container_of(mi, struct dce110_mem_input, base) + +struct dce110_mem_input_reg_offsets { + uint32_t dcp; + uint32_t dmif; + uint32_t pipe; +}; + +struct dce110_mem_input { + struct mem_input base; + struct dce110_mem_input_reg_offsets offsets; + uint32_t supported_stutter_mode; +}; + +bool dce110_mem_input_construct( + struct dce110_mem_input *mem_input110, + struct dc_context *ctx, + uint32_t inst, + const struct dce110_mem_input_reg_offsets *offsets); + +/* + * dce110_mem_input_program_display_marks + * + * This function will program nbp stutter and urgency watermarks to maximum + * safe values + */ +void dce110_mem_input_program_safe_display_marks(struct mem_input *mi); + +/* + * dce110_mem_input_program_display_marks + * + * This function will program nbp stutter and urgency watermarks to minimum + * allowable values + */ +void dce110_mem_input_program_display_marks( + struct mem_input *mem_input, + struct bw_watermarks nbp, + struct bw_watermarks stutter, + struct bw_watermarks urgent, + uint32_t h_total, + uint32_t pixel_clk_in_khz, + uint32_t pstate_blackout_duration_ns); + +/* + * dce110_mem_input_allocate_dmif_buffer + * + * This function will allocate a dmif buffer and program required + * pixel duration for pipe + */ +void dce110_mem_input_allocate_dmif_buffer( + struct mem_input *mem_input, + struct dc_crtc_timing *timing, + uint32_t paths_num); + +/* + * dce110_mem_input_deallocate_dmif_buffer + * + * This function will deallocate a dmif buffer from pipe + */ +void dce110_mem_input_deallocate_dmif_buffer( + struct mem_input *mem_input, uint32_t paths_num); + +/* + * dce110_mem_input_program_surface_flip_and_addr + * + * This function programs hsync/vsync mode and surface address + */ +bool dce110_mem_input_program_surface_flip_and_addr( + struct mem_input *mem_input, + const struct dc_plane_address *address, + bool flip_immediate); + +/* + * dce110_mem_input_program_surface_config + * + * This function will program surface tiling, size, rotation and pixel format + * to corresponding dcp registers. + */ +bool dce110_mem_input_program_surface_config( + struct mem_input *mem_input, + enum surface_pixel_format format, + struct dc_tiling_info *tiling_info, + union plane_size *plane_size, + enum dc_rotation_angle rotation); + + +#endif