From patchwork Tue Feb 16 22:27: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: 8332891 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 B74439F6E7 for ; Tue, 16 Feb 2016 22:29:38 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 6DD58202F2 for ; Tue, 16 Feb 2016 22:29:36 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id 69A34202EC for ; Tue, 16 Feb 2016 22:29:33 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 6E8FC6E8E0; Tue, 16 Feb 2016 22:28:47 +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-bl2on0093.outbound.protection.outlook.com [65.55.169.93]) by gabe.freedesktop.org (Postfix) with ESMTPS id 98CEB6E8D7 for ; Tue, 16 Feb 2016 22:28:45 +0000 (UTC) Received: from BY2PR12CA0018.namprd12.prod.outlook.com (10.160.121.28) by BLUPR12MB0706.namprd12.prod.outlook.com (10.163.218.144) with Microsoft SMTP Server (TLS) id 15.1.409.15; Tue, 16 Feb 2016 22:28:43 +0000 Received: from DM3NAM03FT065.eop-NAM03.prod.protection.outlook.com (2a01:111:f400:7e49::208) by BY2PR12CA0018.outlook.office365.com (2a01:111:e400:2c84::28) with Microsoft SMTP Server (TLS) id 15.1.409.15 via Frontend Transport; Tue, 16 Feb 2016 22:28:42 +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 DM3NAM03FT065.mail.protection.outlook.com (10.152.82.254) with Microsoft SMTP Server id 15.1.415.6 via Frontend Transport; Tue, 16 Feb 2016 22:28:41 +0000 X-WSS-ID: 0O2NVRR-07-L62-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 27764CAE81A for ; Tue, 16 Feb 2016 17:28:39 -0500 (EST) Received: from SATLEXDAG02.amd.com (10.181.40.5) by satlvexedge01.amd.com (10.177.96.28) with Microsoft SMTP Server (TLS) id 14.3.195.1; Tue, 16 Feb 2016 16:28:42 -0600 Received: from STOREXDAG02.amd.com (10.1.13.11) by SATLEXDAG02.amd.com (10.181.40.5) with Microsoft SMTP Server (TLS) id 14.3.266.1; Tue, 16 Feb 2016 17:28:40 -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:38 -0500 From: Harry Wentland To: Subject: [PATCH v2 16/26] drm/amd/dal: Add surface HW programming Date: Tue, 16 Feb 2016 17:27:56 -0500 Message-ID: <5c8b0b1c11b3542f65923ddfefc9e6166390e701.1455660367.git.harry.wentland@amd.com> 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.221; CTRY:US; IPV:NLI; EFV:NLI; SFV:NSPM; SFS:(10009020)(6009001)(2980300002)(428002)(199003)(189002)(76176999)(92566002)(77096005)(50986999)(5003600100002)(48376002)(19580395003)(19580405001)(4326007)(101416001)(2950100001)(50226001)(189998001)(110136002)(86362001)(2906002)(118296001)(1096002)(36756003)(450100001)(229853001)(2351001)(33646002)(586003)(1220700001)(5008740100001)(87936001)(53416004)(106466001)(47776003)(5003940100001)(50466002)(105586002); DIR:OUT; SFP:1101; SCL:1; SRVR:BLUPR12MB0706; H:atltwp01.amd.com; FPR:; SPF:None; MLV:sfv; A:1; MX:1; LANG:en; X-MS-Office365-Filtering-Correlation-Id: 9f2f69a8-66ef-4670-6140-08d33720863a X-Microsoft-Exchange-Diagnostics: 1; BLUPR12MB0706; 2:SgQJ3I+62WpDEQgho9GHpOdiDahVMFwjmpdKgXT3EL3SRT6qHcwxpum9xJMVAwW7Yvb0BHsnUNk4+lPq/atU2KCSi9VKhgNUP/pEwzUaIWSmupFniFr45i9MywtxYbFHQQVedjO2IpYX6opdnce4ayO/5pzvQL3TuQKsBOx4S+Hz+dgbi5UMjwiJMOlp8/zm; 3:qMKZXm+covglKFHdXEaFUEMUqL7tnagmpwi7mNn0Z6THEQ+FEx5+YNbBEkLiZwjiUpgENIVk/WkPTqPtg5aiRB99Wy+uWQdU3pbi8+K/jVj92a1KvLLZueP02+vcGnzz9fejo6lx8vuT67lkprIueoMxgCcXuKoi2OYdus06uHlouGNmW5zBgD4seUjXeI9jEdeplEaTr4liKW/1Gd3PiansU7HXNiDu3x/WGqOK31I=; 25:hjJ6cHfxQj7AI3hjzzYzK2vtUoFYu7jG8zq8DyXzzgvFAn6SeZMvdUh6uiTJUTbXq/7f/gHq5/x1krKLT8Xaq4c75bwlnrQD4a4WzntYPc9epfgnNET3kuOEQF9ISFE3RjwVw2i2XnE9sfLCh0Ditg38zN3ZT/t24GQ8GPuOxiqQ9bCE4QooM5D8yvxg09XKZkdqL1q8FMmN3U7hDdu5niz2jnXkqWLjw9PUHFDZtRoEz72u1430OXLuIk1tB2obv/FdxbBF5vBsA5ZGrmhhZ2add4jlkNXNEE+c4UjgaspU1HdMRxr7CHKbTJgzsB2J X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:;SRVR:BLUPR12MB0706; X-Microsoft-Exchange-Diagnostics: 1; BLUPR12MB0706; 20:JPdRXik8h8iKnMXtNPtfkK11Fa+OvtKIbxPLG5VTRce9qrunqtL2ept/b6neS2Ks438/XdUwHbG6eY0wpaB4r3cYMBS3KkrCS2s7BATCqgRIcHmnnBEAkZdo4KXKZEneOhvaYVB8iGKACMUy3aTzG/do1dgCS43c6qbw4mIXix1hnwdTEfaZu9ZayywheK4m7BTwJHMEXb2ueMKGTawkb4Sh8aW7WDFEO1rh0FI6VqL5kU4Hk8eACnfkCXD4ymGTfUMsvYKQXoFQm6/bArkYjx0cFAMKUPhLqI0LMjc48TWUiG6VIxTKQE0jw5n6CvbVkraRhI7Whcw67m0xVrGMxaq7X0+P8j8m6RNJXil7qAtaBJ4+9cMIzly3RS0sFrZ0VAXrKRE90wg8ZxD9RVw6GOz8P3UBdlYfF79WqNbyT7Umc2XXwB+R3WsDUGsCi2PxiTvDvp4/IW/6SoyXdcDtZxanGhKS4x4scCl68UC/RZIgfzmeiRRuioMs9s5c0epI 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:BLUPR12MB0706; BCL:0; PCL:0; RULEID:; SRVR:BLUPR12MB0706; X-Microsoft-Exchange-Diagnostics: 1; BLUPR12MB0706; 4:saZTTMlqdASgpxwCx2XAjN2fEtEITukgF3ygp3eBQn+yU4h0wKSx+fk9K8COE5J2Tx/A1DsLhveg9IqYigKMowmgpDdiwOoX9/a01zfUIQQnwf8BDyfvmzNb2C1x5IYfEpsXnU5xaN6tgyg0ioEXRjKaR/yCtb6IiiIVfxWS4RCPXvFIuPvc4l71v6M9KQXYqGTVtYvj3XlvayB+t7NDruUAf0tU/ZzogMGaI3RlUOkTeshAT1rFuxpUcgRnx5M1GkRTxmD7we382TDspf0GRYrbqmSE4l76C98/cRiP2qwMBw8rkXi2G3NJPFoPlv0DV6hJSLoCc6OG5/PZAxGRl29BYjeXUaSLugO2vkLKNN91xFyBZqXusQ9qmph1Iz04IuYcsFfSf7W6vcFTQR2lRrvFwlRu5H4atWmUqbiyU0XlAFo1paZsC11T/iFtIsjeNzxsyXfMDtFDOcNzhiB/REwIMFxans1pjvgr0CwdhfBcONJIz+aIVKfdGWM7gCWy X-Forefront-PRVS: 0854128AF0 X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1; BLUPR12MB0706; 23:KE2TDguWA215ccQzZxEKR9pvxlGwIeUwpOIt3pYRY?= =?us-ascii?Q?Qaseb0y8mhyt2aqt7xzm8zTZc9wXOBdjwgC4wFAZaJOjoTpbgoFvMrj6JK7b?= =?us-ascii?Q?lBsDgC1SLsBX7lcgm1l38jQtKFozYDh+27/43rQ7Q6XEAwadZ22DTQafrscE?= =?us-ascii?Q?95Qn8dVlpRKwHQEREzQNLfq9IhPF2SvEtuJ21+bMRX0mf1es53K/T2yBdccX?= =?us-ascii?Q?lH3ES4weOTtUmleUJS7A4XY/ZDoePom71mvGazKY7yInr4Vz4/SwRKxHRE8f?= =?us-ascii?Q?QBOoS3X6PLvppVWxHzcZsy/MdFTy5xLx+zBl6OFnfL0TkpzvFhgnLKvvDAlG?= =?us-ascii?Q?h7LluFKpAyjbZ8Vvtzv1t+xiWQlypuCV9iV8T5ckjzvOyu7FHK3wO514i5aA?= =?us-ascii?Q?euILbBN9PGSzvFryuCcohHQoeLD+godn8G8CqjGEjgCKfuU8rARoDitZoKUo?= =?us-ascii?Q?9YMs8yNorg7+72NAF6XQh1N8rCTIvQUqaYi3NXD8hs+IxpzcsnY5viOOyhoc?= =?us-ascii?Q?u2mtC7wSXVj6KThCrvmHgszr21n+3eQzJxoGfX0ux3k+5Fj/gGGPzNC6A0qa?= =?us-ascii?Q?gibHgoeeZtsyf8RjrmWfROjuHzt8eN14e0GHzRZn6hpNDlvYOp/3377TpLJS?= =?us-ascii?Q?4xvxeaSQRSq6u4yIAjJxuYgMTz3FZ/S40IDxtTmvpN/runBUq3wV2VLr6nAF?= =?us-ascii?Q?Z3iQ9Q4EDL6hwobWBX7gXVD2OM53h7x2hr26ACPM5dh3OGfAP4QhdzSLUsUu?= =?us-ascii?Q?+P/GYpSuMBM9uDlff2N4F0WMGOKpo+H+hfWyCJrpRbjy4Eawfe5Tw+Vtz6B2?= =?us-ascii?Q?hJBNC5YZ5AG5C16vb6Lhr0Pt+5eBQQITsRotztb6O4r4MYmFowjXJHTS7L+V?= =?us-ascii?Q?6TRdAHUtZgq4jCYtA9i//LhF5cMRIv7m7dGsX5Z9/jLZBfy1ZlHpB/gwtqCO?= =?us-ascii?Q?hDmZYgW0Z2hzbF36SRBF6OgjP/AyCccMG8iiEaz0bkxbzcpUAmimJTkBSNjw?= =?us-ascii?Q?CtSzggen6yYMirR9fX55/bs?= X-Microsoft-Exchange-Diagnostics: 1; BLUPR12MB0706; 5:n8TEV12/d1H3Ltywf0YoWLbRkHVli5+D19tS/hzOFJ/1Ym57IZva0gTpaPn0q6fLNZHhS/HH7TASGeXbfcl5LKI1oP5rMzQ5lVgUpVYo8vpHvdCp5ey/ol7kcuoIo5j9vy40fmoAusUxsZDQlqjwDA==; 24:gBQ5iVfGIgh/yAX+Et94HKY8IN38vkMhGyKnaedi928UVSB4e3P2pOCjMY94oWQCwGkAtaaSGLH+SsM3aVxJEDj0+JYVG1e2TfgoiRk93IQ=; 20:z9vb5VKME5V9Sm1N8bU2vwKAsucMrywJB/CoML41EbLvBHIfA6zDnmJsp1w9+hwE5cXF951Wvv4wSdmt665p2OT6KjkSMTRRe1F9lFEUH2YhFVzCCgpdr6EuPNC/nmBk76CjiZ4vn5VaKPmo/mev+hSs+Idr0LSEa4Z2HGMQ2/YKplVc7I+/8oLM38LyCfMB2Hr+RtIsVATEvwy6s9sK9/alS0BycxzANoHYltmIthqOpibfpUji3Ruo2NP48qn7 SpamDiagnosticOutput: 1:23 SpamDiagnosticMetadata: NSPM X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 16 Feb 2016 22:28:41.8419 (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: BLUPR12MB0706 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.6 required=5.0 tests=BAD_ENC_HEADER,BAYES_00, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, UNPARSEABLE_RELAY, URG_BIZ autolearn=ham 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