From patchwork Thu Feb 11 17:20:02 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Harry Wentland X-Patchwork-Id: 8283261 Return-Path: X-Original-To: patchwork-dri-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 8AC49BEEE5 for ; Thu, 11 Feb 2016 17:22:11 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 1016C2035D for ; Thu, 11 Feb 2016 17:22:08 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id 253F42017E for ; Thu, 11 Feb 2016 17:22:03 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id EEC58720FD; Thu, 11 Feb 2016 09:21:01 -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-bn1bon0095.outbound.protection.outlook.com [157.56.111.95]) by gabe.freedesktop.org (Postfix) with ESMTPS id 536A67A0B8 for ; Thu, 11 Feb 2016 09:20:59 -0800 (PST) Received: from BY2PR12CA0037.namprd12.prod.outlook.com (10.160.121.47) by BN4PR12MB0851.namprd12.prod.outlook.com (10.164.59.13) with Microsoft SMTP Server (TLS) id 15.1.409.15; Thu, 11 Feb 2016 17:20:56 +0000 Received: from BY2NAM03FT058.eop-NAM03.prod.protection.outlook.com (2a01:111:f400:7e4a::201) by BY2PR12CA0037.outlook.office365.com (2a01:111:e400:2c84::47) with Microsoft SMTP Server (TLS) id 15.1.409.15 via Frontend Transport; Thu, 11 Feb 2016 17:20:56 +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 BY2NAM03FT058.mail.protection.outlook.com (10.152.85.184) with Microsoft SMTP Server id 15.1.415.6 via Frontend Transport; Thu, 11 Feb 2016 17:20:56 +0000 X-WSS-ID: 0O2E86T-07-0WN-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 atltwp01.amd.com (Axway MailGate 5.3.1) with ESMTPS id 2950C12C130F for ; Thu, 11 Feb 2016 12:20:53 -0500 (EST) Received: from SATLEXDAG02.amd.com (10.181.40.5) by SATLVEXEDGE02.amd.com (10.177.96.29) with Microsoft SMTP Server (TLS) id 14.3.195.1; Thu, 11 Feb 2016 11:21:26 -0600 Received: from STOREXDAG03.amd.com (10.1.13.12) by SATLEXDAG02.amd.com (10.181.40.5) with Microsoft SMTP Server (TLS) id 14.3.266.1; Thu, 11 Feb 2016 12:20:54 -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:52 -0500 From: Harry Wentland To: Subject: [PATCH 22/29] drm/amd/dal: Add Tonga/Fiji HW sequencer and resource Date: Thu, 11 Feb 2016 12:20:02 -0500 Message-ID: <1455211209-26733-23-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)(36756003)(189998001)(101416001)(450100001)(5008740100001)(76176999)(2906002)(86362001)(575784001)(19580395003)(5003940100001)(50986999)(77096005)(1220700001)(33646002)(19580405001)(87936001)(1096002)(5890100001)(11100500001)(105586002)(2950100001)(50466002)(48376002)(92566002)(586003)(4326007)(47776003)(5003600100002)(106466001)(53416004)(229853001)(2351001)(50226001)(579004)(559001); DIR:OUT; SFP:1101; SCL:1; SRVR:BN4PR12MB0851; H:atltwp01.amd.com; FPR:; SPF:None; MLV:sfv; MX:1; A:1; LANG:en; X-MS-Office365-Filtering-Correlation-Id: 1181ad26-9c05-4659-d8f8-08d33307b3ae X-Microsoft-Exchange-Diagnostics: 1; BN4PR12MB0851; 2:AgiUN6ZZzpegsJzTCyZj6uJdSFavg21caNUAGPgqokQ+0UQ0wICpdlDqCTNUIwGUfKlhit9K45zlYMq/SCrxbKxcsYIPQlAVj0oAgtItBQCh1riPjFWUOY0dlJZcoiQyXrGLE/6y19ldd9I/lrh9ww5MVkba8A745+6pVQOqGKdO/2Oaw25paRZuRXOsOlsV; 3:04VX5TpshcQXCt+uUjvnYMe80wmRCb6xFu79E29kNPe6ME2ob+AIXpxGyGwOI36MqYPq2Jx3O32tAXIk2jFskXgwgl4cdZHUt/XgqxvY1Ycgh2e0KNYqHSB8qgA7HiH0gOCuH/ozytxubSCyldAnIJsnObAbHooSxiAGSdYODnsfarlOlXu97YWqxiL5KVrixLfXVTpwbPl22eK/YYsQSxpc8hyAzvuNb+CmCIBsWos=; 25:mdwPC77Z6w/eSleDHcrWj0COvDTcXzKDYhHXDJ7A8rCHZuT6e8F8vjWXmPNLKryyvxXFnuVoSFeVi1S2O6EpGF2nGQgpeNHaexy1yLV/9KRO+JbXiuFDd0bs4ZomNxwrP9CvtWjikbOKtV4FW8Fu5hva+Gb4P3vEeb5h8nLumbHDK/FRxtCxPygYeu147riOCcKmZzlxRiGgrcH8IMRcVYyHkyKUIATG48lv1tQJqxvYDPRyPrUssbsus3OUdOYvLSF3yRI230n3UCeg71IyIax4rkMBxWd8iP2xqnPW7CgKZj4+jkMqSw7rf8CTQmgX X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:;SRVR:BN4PR12MB0851; X-Microsoft-Exchange-Diagnostics: 1; BN4PR12MB0851; 20:gOT0iaOKnkgAXSxjxqA2Taf1qJKGdxFUGkVMCYoOzOMVzRbbC6i0J4RYyXtwmKt+8n9Uv++usPCcrnK8sSuq4DEluKUwSC4lTkwGFvk2uJeAPwkSqtI9db6x2JWu+jTkMbKJsFYmkb5MH1R87LE7SGwIk4LXoqG4mQbYMa3MkGjTJDOYY4zCAUgrk7T1n4J/KF9usklU59oIZRAoFo+deOfHdzEhcHh6Ot2rp7MfNi6I+InRp58Ci/4Pgs5LGyIlzgcHRozfL0sDhc62MLS37Z1fPkL+UIQlKiWOhhk44SA6zAxr+rgRqd+cK231fgip0k4wm4GX5rjIOeya8cgHw4/eq6DeSBFzKf0qBYYJYLS9duiYUoSVpodyPrix9ERqSoMPF7FL44yUMheqUjOX07+FyMzweVEdyGIwwARR4HduU1Uh7Te1mezyhXP7pTAMqOLeSZY1whIAdwZf0lxv4NG4RP1t5/e0aObsAVXyT1C58JzI1yOX3AqjkSXAm5Ye X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:(767451399110); X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(601004)(2401047)(8121501046)(13024025)(13015025)(13023025)(13017025)(13018025)(5005006)(3002001)(10201501046); SRVR:BN4PR12MB0851; BCL:0; PCL:0; RULEID:; SRVR:BN4PR12MB0851; X-Microsoft-Exchange-Diagnostics: 1; BN4PR12MB0851; 4:/2HN0J7CaVicgq+X31EOYdTobE9PU7KVAU4/dTiYT43NPI0vbHf1gh1x5zA0tI7yphzjx62p+kLryJJCUU6YMklyzRnIaxPvzPYLRBX8jYkrM9J9pDANFie82e8qSh7Ke+oZH9In4KbjHM8efEGiswAbxOlxEFYfwqbSqHH36I0mC37rnxFORFdieCFbzjME8JMsfDtT1bX0imp7oLl7kmYYWRktiwbMZoENoHTlrraZaZB3+tvxtLWEjLhERWEGuHbLtuulkFToKFbV9vZbZXjKsJj4URzewpUui3nQf9DRRPTWY/MfGeJkE5oPNRMSJiXf4JjX2j0XJkmB6eRNTtUN8sPt1rkoL88Oc/CHKT6XMq/4HuwxBINEhusRSmkAxzJPp05upnnfzEDrqHRss1L8wak57pXu3WICq6C0xOgw+DY2uc0dEUTGbd45tCF7411kdHQMzNEzQjeKQuUwnnCrZEvZ3/y3+HXuTkPDacQH46BT1BasVATHaNGiuAQK X-Forefront-PRVS: 08497C3D99 X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1; BN4PR12MB0851; 23:DuVB2UOEQakY+JJ1PibzpydDcmkCxusf656DKVJj5?= =?us-ascii?Q?cIaD3C6QCa64afH7Cce5Z/a8AXPcjiLRrac7y0GCFA+A1YLF4cajAzx/5psv?= =?us-ascii?Q?k55DcesCflP0EupnEPJkSAnHzWgQLT5qN3B7su42KELZa6w7sgln//AQPzlz?= =?us-ascii?Q?rqBoY+4P5XNR58cCxntHztFLCon9nGJe+4mC45jBK4uAfqWQcIOZ7KPcB1GM?= =?us-ascii?Q?sLx/+5WgpJpf3tFuPqycIMInnR8eNwr3x4Vvrw3thWskj6fN66ltLu4gz8xB?= =?us-ascii?Q?QdEANkIVXK5hNM3j+bXfJTxsz3iUf61pThmxj55iNB7jaqlXGhWKWbwZkrtJ?= =?us-ascii?Q?1lYHOgoDUfuZOeSX7mukMVvF9QcPZizXiEb5txphdY3erhjvyqCWVjjW/eBr?= =?us-ascii?Q?MAgkTCAXg99RXKc4ZR1m/rmt+m1ycyYSvjOquDTkNWW/yREhStPI3ue4WJ9j?= =?us-ascii?Q?fBIqHwdmA/eGyCcOnkebziIGL5D1I5fM+rkWYA+s/9uOrauayjRxJMmwtNuX?= =?us-ascii?Q?Nq74WEKHBbAk3W7AGaJjvt3JvusgTVry9t0zlOZeyfVnYR23mfR9+Z7T8UsL?= =?us-ascii?Q?43lgWnDITZ5PBuVzTANFZz7V6IZoulgT+UwM91vbRwN47VeULrxOU2J0FVUW?= =?us-ascii?Q?ZYjf7ggQKoFDIDdB6eE3fmWLR+QwKhedkXZRNZGbgF2Sllau+g+ztOKb1Qbr?= =?us-ascii?Q?ErljSDEzumq0zIS7qgT3oKfuHQnU44ImI/Ar6Je9nji6gYAI3gDMjqzC4Yq+?= =?us-ascii?Q?mGqR7JPrT+btiUbEDtLd24cQ2LFd9HfenMkT9eBTUz3P0YhOVFerBILpBnKZ?= =?us-ascii?Q?mqDaYLWtkScnHvvYNoYmQNR4a4Ja5A/Dbg5TvGWAqWASisWJwqvUs/4Nv9Ci?= =?us-ascii?Q?zARr/kpHVoPGKZbCxUCuuI2zJkZ3T+861ygS+rsjHK0tlq3hCHQy2eLbXMb8?= =?us-ascii?Q?+aGaeq/Egw2dgkec9UXP6X5bL/3eCW3hJhgPYM5YeO1RHIf3Plrb/s/2FJDO?= =?us-ascii?Q?GjGkAiy1CtvP/k3YE2U3qLMNoesUeiyHWzaUL+H6deNJai3b8JXh7CZXoKBk?= =?us-ascii?Q?jUT/S9Jl9opbsl1NRvtfhhrd5Ir?= X-Microsoft-Exchange-Diagnostics: 1; BN4PR12MB0851; 5:3B7TGbMS/H2+ehg3WuST0w+1bY50sUxya4GM6RmeWMhk+LL94/6EIPY6O3DL2DFYKI+MMRiA8V4uZfXE5cLg6LrBJc8CFC9QL5ROFkKMOj85iUrbytM9pxl/WIkJXRbBPr3YrgaKl0xWcvBFwtreyA==; 24:6MCsJEuSGe+wumj5TzzXHRm0aFkLacMJvNFPBc9J4eIke7ribqPd3ZR2DLYhmH3OmA+XPYaI4v4Zu3tMnPWXKn6XZPqW1peDIpKeKs866F0=; 20:qpmm1vX0WMxMxLG0Zh/d2WkImpGQT4xsFeYSm760IbtA59sSRYf6m5kZZgQMzuVQ1Ff98+11heGy7JscAy+MFPFqu++wLoxZ4iBpboMR/+0QxDTYn/LJ1v1q/BLTOHqB+ZiGaRv2qXoRsMBOk5n0VB4O2+/123RIWxmKnOUa4y4mcsKxYOl2Nu4eKqeXvyBlEcAlUAyFKJJ84r4bcDtTHLlM6rXlvSA4t0iLl/OzOSmGlRUd69oO0QgRtPFudyUH SpamDiagnosticOutput: 1:23 SpamDiagnosticMetadata: NSPM X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 11 Feb 2016 17:20:56.0021 (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: BN4PR12MB0851 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.4 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 Enables HW programming on Tonga and Fiji (DCE 10) ASICs. This mostly re-uses DCE 11 programming code with minor exceptions and using DCE 10 register offsets. Signed-off-by: Harry Wentland Reviewed-by: Alex Deucher --- drivers/gpu/drm/amd/dal/dc/dce100/Makefile | 23 + .../drm/amd/dal/dc/dce100/dce100_hw_sequencer.c | 388 +++++++ .../drm/amd/dal/dc/dce100/dce100_hw_sequencer.h | 36 + .../gpu/drm/amd/dal/dc/dce100/dce100_resource.c | 1134 ++++++++++++++++++++ .../gpu/drm/amd/dal/dc/dce100/dce100_resource.h | 43 + 5 files changed, 1624 insertions(+) create mode 100644 drivers/gpu/drm/amd/dal/dc/dce100/Makefile create mode 100644 drivers/gpu/drm/amd/dal/dc/dce100/dce100_hw_sequencer.c create mode 100644 drivers/gpu/drm/amd/dal/dc/dce100/dce100_hw_sequencer.h create mode 100644 drivers/gpu/drm/amd/dal/dc/dce100/dce100_resource.c create mode 100644 drivers/gpu/drm/amd/dal/dc/dce100/dce100_resource.h diff --git a/drivers/gpu/drm/amd/dal/dc/dce100/Makefile b/drivers/gpu/drm/amd/dal/dc/dce100/Makefile new file mode 100644 index 000000000000..656c38e1b0f5 --- /dev/null +++ b/drivers/gpu/drm/amd/dal/dc/dce100/Makefile @@ -0,0 +1,23 @@ +# +# Makefile for the 'controller' sub-component of DAL. +# It provides the control and status of HW CRTC block. + +DCE100 = dce100_resource.o dce100_hw_sequencer.o + +AMD_DAL_DCE100 = $(addprefix $(AMDDALPATH)/dc/dce100/,$(DCE100)) + +AMD_DAL_FILES += $(AMD_DAL_DCE100) + + +############################################################################### +# DCE 10x +############################################################################### +ifdef 0#CONFIG_DRM_AMD_DAL_DCE11_0 +TG_DCE100 = dce100_resource.o + +AMD_DAL_TG_DCE100 = $(addprefix \ + $(AMDDALPATH)/dc/dce100/,$(TG_DCE100)) + +AMD_DAL_FILES += $(AMD_DAL_TG_DCE100) +endif + diff --git a/drivers/gpu/drm/amd/dal/dc/dce100/dce100_hw_sequencer.c b/drivers/gpu/drm/amd/dal/dc/dce100/dce100_hw_sequencer.c new file mode 100644 index 000000000000..82c5e155d91a --- /dev/null +++ b/drivers/gpu/drm/amd/dal/dc/dce100/dce100_hw_sequencer.c @@ -0,0 +1,388 @@ +/* + * Copyright 2015 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 "dc.h" +#include "core_dc.h" +#include "core_types.h" +#include "hw_sequencer.h" +#include "dce100_hw_sequencer.h" +#include "dce110/dce110_hw_sequencer.h" + +/* include DCE10 register header files */ +#include "dce/dce_10_0_d.h" +#include "dce/dce_10_0_sh_mask.h" + +struct dce100_hw_seq_reg_offsets { + uint32_t blnd; + uint32_t crtc; +}; + +enum pipe_lock_control { + PIPE_LOCK_CONTROL_GRAPHICS = 1 << 0, + PIPE_LOCK_CONTROL_BLENDER = 1 << 1, + PIPE_LOCK_CONTROL_SCL = 1 << 2, + PIPE_LOCK_CONTROL_SURFACE = 1 << 3, + PIPE_LOCK_CONTROL_MODE = 1 << 4 +}; + +enum blender_mode { + BLENDER_MODE_CURRENT_PIPE = 0,/* Data from current pipe only */ + BLENDER_MODE_OTHER_PIPE, /* Data from other pipe only */ + BLENDER_MODE_BLENDING,/* Alpha blending - blend 'current' and 'other' */ + BLENDER_MODE_STEREO +}; + +static const struct dce100_hw_seq_reg_offsets reg_offsets[] = { +{ + .blnd = (mmBLND0_BLND_CONTROL - mmBLND_CONTROL), + .crtc = (mmCRTC0_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL), +}, +{ + .blnd = (mmBLND1_BLND_CONTROL - mmBLND_CONTROL), + .crtc = (mmCRTC1_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL), +}, +{ + .blnd = (mmBLND2_BLND_CONTROL - mmBLND_CONTROL), + .crtc = (mmCRTC2_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL), +} +}; + +#define HW_REG_BLND(reg, id)\ + (reg + reg_offsets[id].blnd) + +#define HW_REG_CRTC(reg, id)\ + (reg + reg_offsets[id].crtc) + + +/******************************************************************************* + * Private definitions + ******************************************************************************/ +/***************************PIPE_CONTROL***********************************/ +static void dce100_enable_fe_clock( + struct dc_context *ctx, uint8_t controller_id, bool enable) +{ + uint32_t value = 0; + uint32_t addr; + + addr = HW_REG_CRTC(mmDCFE_CLOCK_CONTROL, controller_id); + + value = dm_read_reg(ctx, addr); + + set_reg_field_value( + value, + enable, + DCFE_CLOCK_CONTROL, + DCFE_CLOCK_ENABLE); + + dm_write_reg(ctx, addr, value); +} + +static bool dce100_pipe_control_lock( + struct dc_context *ctx, + uint8_t controller_idx, + uint32_t control_mask, + bool lock) +{ + uint32_t addr = HW_REG_BLND(mmBLND_V_UPDATE_LOCK, controller_idx); + uint32_t value = dm_read_reg(ctx, addr); + bool need_to_wait = false; + + if (control_mask & PIPE_LOCK_CONTROL_GRAPHICS) + set_reg_field_value( + value, + lock, + BLND_V_UPDATE_LOCK, + BLND_DCP_GRPH_V_UPDATE_LOCK); + + if (control_mask & PIPE_LOCK_CONTROL_SCL) + set_reg_field_value( + value, + lock, + BLND_V_UPDATE_LOCK, + BLND_SCL_V_UPDATE_LOCK); + + if (control_mask & PIPE_LOCK_CONTROL_SURFACE) + set_reg_field_value( + value, + lock, + BLND_V_UPDATE_LOCK, + BLND_DCP_GRPH_SURF_V_UPDATE_LOCK); + + if (control_mask & PIPE_LOCK_CONTROL_BLENDER) { + set_reg_field_value( + value, + lock, + BLND_V_UPDATE_LOCK, + BLND_BLND_V_UPDATE_LOCK); + need_to_wait = true; + } + + if (control_mask & PIPE_LOCK_CONTROL_MODE) + set_reg_field_value( + value, + lock, + BLND_V_UPDATE_LOCK, + BLND_V_UPDATE_LOCK_MODE); + + dm_write_reg(ctx, addr, value); + + if (!lock && need_to_wait) { + uint8_t counter = 0; + const uint8_t counter_limit = 100; + const uint16_t delay_us = 1000; + + uint8_t pipe_pending; + + addr = HW_REG_BLND(mmBLND_REG_UPDATE_STATUS, + controller_idx); + + while (counter < counter_limit) { + value = dm_read_reg(ctx, addr); + + pipe_pending = 0; + + if (control_mask & PIPE_LOCK_CONTROL_BLENDER) { + pipe_pending |= + get_reg_field_value( + value, + BLND_REG_UPDATE_STATUS, + BLND_BLNDC_UPDATE_PENDING); + pipe_pending |= get_reg_field_value( + value, + BLND_REG_UPDATE_STATUS, + BLND_BLNDO_UPDATE_PENDING); + } + + if (control_mask & PIPE_LOCK_CONTROL_SCL) { + pipe_pending |= + get_reg_field_value( + value, + BLND_REG_UPDATE_STATUS, + SCL_BLNDC_UPDATE_PENDING); + pipe_pending |= + get_reg_field_value( + value, + BLND_REG_UPDATE_STATUS, + SCL_BLNDO_UPDATE_PENDING); + } + if (control_mask & PIPE_LOCK_CONTROL_GRAPHICS) { + pipe_pending |= + get_reg_field_value( + value, + BLND_REG_UPDATE_STATUS, + DCP_BLNDC_GRPH_UPDATE_PENDING); + pipe_pending |= + get_reg_field_value( + value, + BLND_REG_UPDATE_STATUS, + DCP_BLNDO_GRPH_UPDATE_PENDING); + } + if (control_mask & PIPE_LOCK_CONTROL_SURFACE) { + pipe_pending |= get_reg_field_value( + value, + BLND_REG_UPDATE_STATUS, + DCP_BLNDC_GRPH_SURF_UPDATE_PENDING); + pipe_pending |= get_reg_field_value( + value, + BLND_REG_UPDATE_STATUS, + DCP_BLNDO_GRPH_SURF_UPDATE_PENDING); + } + + if (pipe_pending == 0) + break; + + counter++; + dm_delay_in_microseconds(ctx, delay_us); + } + + if (counter == counter_limit) { + dal_logger_write( + ctx->logger, + LOG_MAJOR_WARNING, + LOG_MINOR_COMPONENT_CONTROLLER, + "%s: wait for update exceeded (wait %d us)\n", + __func__, + counter * delay_us); + dal_logger_write( + ctx->logger, + LOG_MAJOR_WARNING, + LOG_MINOR_COMPONENT_CONTROLLER, + "%s: control %d, remain value %x\n", + __func__, + control_mask, + value); + } else { + /* OK. */ + } + } + + return true; +} + +static void dce100_set_blender_mode( + struct dc_context *ctx, + uint8_t controller_id, + uint32_t mode) +{ + uint32_t value; + uint32_t addr = HW_REG_BLND(mmBLND_CONTROL, controller_id); + uint32_t blnd_mode; + uint32_t feedthrough = 0; + + switch (mode) { + case BLENDER_MODE_OTHER_PIPE: + feedthrough = 0; + blnd_mode = 1; + break; + case BLENDER_MODE_BLENDING: + feedthrough = 0; + blnd_mode = 2; + break; + case BLENDER_MODE_CURRENT_PIPE: + default: + feedthrough = 1; + blnd_mode = 0; + break; + } + + value = dm_read_reg(ctx, addr); + + set_reg_field_value( + value, + feedthrough, + BLND_CONTROL, + BLND_FEEDTHROUGH_EN); + + set_reg_field_value( + value, + blnd_mode, + BLND_CONTROL, + BLND_MODE); + + dm_write_reg(ctx, addr, value); +} + +static bool dce100_enable_display_power_gating( + struct dc_context *ctx, + uint8_t controller_id, + struct dc_bios *dcb, + enum pipe_gating_control power_gating) +{ + enum bp_result bp_result = BP_RESULT_OK; + enum bp_pipe_control_action cntl; + + if (power_gating == PIPE_GATING_CONTROL_INIT) + cntl = ASIC_PIPE_INIT; + else if (power_gating == PIPE_GATING_CONTROL_ENABLE) + cntl = ASIC_PIPE_ENABLE; + else + cntl = ASIC_PIPE_DISABLE; + + if (!(power_gating == PIPE_GATING_CONTROL_INIT && controller_id != 0)) + bp_result = dcb->funcs->enable_disp_power_gating( + dcb, controller_id + 1, cntl); + + if (bp_result == BP_RESULT_OK) + return true; + else + return false; +} + +static void enable_hw_base_light_sleep(void) +{ + /* TODO: implement */ +} + +static void disable_sw_manual_control_light_sleep(void) +{ + /* TODO: implement */ +} + +static void enable_sw_manual_control_light_sleep(void) +{ + /* TODO: implement */ +} + +static void dal_dc_clock_gating_dce100_power_up(struct dc_context *ctx, bool enable) +{ + if (enable) { + enable_hw_base_light_sleep(); + disable_sw_manual_control_light_sleep(); + } else { + enable_sw_manual_control_light_sleep(); + } +} + +/** + * Call display_engine_clock_dce80 to perform the Dclk programming. + */ +static void set_display_clock(struct validate_context *context) +{ + /* Program the display engine clock. + * Check DFS bypass mode support or not. DFSbypass feature is only when + * BIOS GPU info table reports support. */ + + if (/*dal_adapter_service_is_dfs_bypass_enabled()*/ false) { + /*TODO: set_display_clock_dfs_bypass( + hws, + path_set, + context->res_ctx.pool.display_clock, + context->res_ctx.min_clocks.min_dclk_khz);*/ + } else + dal_display_clock_set_clock(context->res_ctx.pool.display_clock, + 681000); + + /* TODO: When changing display engine clock, DMCU WaitLoop must be + * reconfigured in order to maintain the same delays within DMCU + * programming sequences. */ + + /* TODO: Start GTC counter */ +} + + +static void set_displaymarks( + const struct dc *dc, struct validate_context *context) +{ + /* Do nothing until we have proper bandwitdth calcs */ +} + +/**************************************************************************/ + +bool dce100_hw_sequencer_construct(struct dc *dc) +{ + dce110_hw_sequencer_construct(dc); + + /* TODO: dce80 is empty implementation at the moment*/ + dc->hwss.clock_gating_power_up = dal_dc_clock_gating_dce100_power_up; + + dc->hwss.enable_display_power_gating = dce100_enable_display_power_gating; + dc->hwss.enable_fe_clock = dce100_enable_fe_clock; + dc->hwss.pipe_control_lock = dce100_pipe_control_lock; + dc->hwss.set_blender_mode = dce100_set_blender_mode; + dc->hwss.set_display_clock = set_display_clock; + dc->hwss.set_displaymarks = set_displaymarks; + return true; +} + diff --git a/drivers/gpu/drm/amd/dal/dc/dce100/dce100_hw_sequencer.h b/drivers/gpu/drm/amd/dal/dc/dce100/dce100_hw_sequencer.h new file mode 100644 index 000000000000..0ce637e6bd85 --- /dev/null +++ b/drivers/gpu/drm/amd/dal/dc/dce100/dce100_hw_sequencer.h @@ -0,0 +1,36 @@ +/* +* 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_HWSS_DCE100_H__ +#define __DC_HWSS_DCE100_H__ + +#include "core_types.h" + +struct dc; + +bool dce100_hw_sequencer_construct(struct dc *dc); + +#endif /* __DC_HWSS_DCE100_H__ */ + diff --git a/drivers/gpu/drm/amd/dal/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/dal/dc/dce100/dce100_resource.c new file mode 100644 index 000000000000..e67ba81f1c85 --- /dev/null +++ b/drivers/gpu/drm/amd/dal/dc/dce100/dce100_resource.c @@ -0,0 +1,1134 @@ +/* +* 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 "link_encoder.h" +#include "stream_encoder.h" + +#include "resource.h" +#include "include/irq_service_interface.h" + +#include "../virtual/virtual_stream_encoder.h" +#include "dce110/dce110_resource.h" +#include "dce110/dce110_timing_generator.h" +#include "dce110/dce110_link_encoder.h" +#include "dce110/dce110_mem_input.h" +#include "dce110/dce110_ipp.h" +#include "dce110/dce110_transform.h" +#include "dce110/dce110_stream_encoder.h" +#include "dce110/dce110_opp.h" +#include "dce110/dce110_clock_source.h" + +#include "dce/dce_10_0_d.h" + +#ifndef mmDP_DPHY_INTERNAL_CTRL + #define mmDP_DPHY_INTERNAL_CTRL 0x4aa7 + #define mmDP0_DP_DPHY_INTERNAL_CTRL 0x4aa7 + #define mmDP1_DP_DPHY_INTERNAL_CTRL 0x4ba7 + #define mmDP2_DP_DPHY_INTERNAL_CTRL 0x4ca7 + #define mmDP3_DP_DPHY_INTERNAL_CTRL 0x4da7 + #define mmDP4_DP_DPHY_INTERNAL_CTRL 0x4ea7 + #define mmDP5_DP_DPHY_INTERNAL_CTRL 0x4fa7 + #define mmDP6_DP_DPHY_INTERNAL_CTRL 0x54a7 + #define mmDP7_DP_DPHY_INTERNAL_CTRL 0x56a7 + #define mmDP8_DP_DPHY_INTERNAL_CTRL 0x57a7 +#endif + +enum dce100_clk_src_array_id { + DCE100_CLK_SRC_PLL0 = 0, + DCE100_CLK_SRC_PLL1, + DCE100_CLK_SRC_EXT, + + DCE100_CLK_SRC_TOTAL +}; + +static const struct dce110_timing_generator_offsets dce100_tg_offsets[] = { + { + .crtc = (mmCRTC0_CRTC_CONTROL - mmCRTC_CONTROL), + .dcp = (mmDCP0_GRPH_CONTROL - mmGRPH_CONTROL), + }, + { + .crtc = (mmCRTC1_CRTC_CONTROL - mmCRTC_CONTROL), + .dcp = (mmDCP1_GRPH_CONTROL - mmGRPH_CONTROL), + }, + { + .crtc = (mmCRTC2_CRTC_CONTROL - mmCRTC_CONTROL), + .dcp = (mmDCP2_GRPH_CONTROL - mmGRPH_CONTROL), + }, + { + .crtc = (mmCRTC3_CRTC_CONTROL - mmCRTC_CONTROL), + .dcp = (mmDCP3_GRPH_CONTROL - mmGRPH_CONTROL), + }, + { + .crtc = (mmCRTC4_CRTC_CONTROL - mmCRTC_CONTROL), + .dcp = (mmDCP4_GRPH_CONTROL - mmGRPH_CONTROL), + }, + { + .crtc = (mmCRTC5_CRTC_CONTROL - mmCRTC_CONTROL), + .dcp = (mmDCP5_GRPH_CONTROL - mmGRPH_CONTROL), + } +}; + +static const struct dce110_mem_input_reg_offsets dce100_mi_reg_offsets[] = { + { + .dcp = (mmDCP0_GRPH_CONTROL - mmGRPH_CONTROL), + .dmif = (mmDMIF_PG0_DPG_WATERMARK_MASK_CONTROL + - mmDPG_WATERMARK_MASK_CONTROL), + .pipe = (mmPIPE0_DMIF_BUFFER_CONTROL + - mmPIPE0_DMIF_BUFFER_CONTROL), + }, + { + .dcp = (mmDCP1_GRPH_CONTROL - mmGRPH_CONTROL), + .dmif = (mmDMIF_PG1_DPG_WATERMARK_MASK_CONTROL + - mmDPG_WATERMARK_MASK_CONTROL), + .pipe = (mmPIPE1_DMIF_BUFFER_CONTROL + - mmPIPE0_DMIF_BUFFER_CONTROL), + }, + { + .dcp = (mmDCP2_GRPH_CONTROL - mmGRPH_CONTROL), + .dmif = (mmDMIF_PG2_DPG_WATERMARK_MASK_CONTROL + - mmDPG_WATERMARK_MASK_CONTROL), + .pipe = (mmPIPE2_DMIF_BUFFER_CONTROL + - mmPIPE0_DMIF_BUFFER_CONTROL), + }, + { + .dcp = (mmDCP3_GRPH_CONTROL - mmGRPH_CONTROL), + .dmif = (mmDMIF_PG3_DPG_WATERMARK_MASK_CONTROL + - mmDPG_WATERMARK_MASK_CONTROL), + .pipe = (mmPIPE3_DMIF_BUFFER_CONTROL + - mmPIPE0_DMIF_BUFFER_CONTROL), + }, + { + .dcp = (mmDCP4_GRPH_CONTROL - mmGRPH_CONTROL), + .dmif = (mmDMIF_PG4_DPG_WATERMARK_MASK_CONTROL + - mmDPG_WATERMARK_MASK_CONTROL), + .pipe = (mmPIPE4_DMIF_BUFFER_CONTROL + - mmPIPE0_DMIF_BUFFER_CONTROL), + }, + { + .dcp = (mmDCP5_GRPH_CONTROL - mmGRPH_CONTROL), + .dmif = (mmDMIF_PG5_DPG_WATERMARK_MASK_CONTROL + - mmDPG_WATERMARK_MASK_CONTROL), + .pipe = (mmPIPE5_DMIF_BUFFER_CONTROL + - mmPIPE0_DMIF_BUFFER_CONTROL), + } +}; + + +static const struct dce110_clk_src_reg_offsets dce100_clk_src_reg_offsets[] = { + { + .pll_cntl = mmBPHYC_PLL0_PLL_CNTL, + .pixclk_resync_cntl = mmPIXCLK0_RESYNC_CNTL + }, + { + .pll_cntl = mmBPHYC_PLL1_PLL_CNTL, + .pixclk_resync_cntl = mmPIXCLK1_RESYNC_CNTL + } +}; + +static const struct dce110_transform_reg_offsets dce100_xfm_offsets[] = { +{ + .scl_offset = (mmSCL0_SCL_CONTROL - mmSCL_CONTROL), + .dcfe_offset = (mmCRTC0_DCFE_MEM_PWR_CTRL - mmDCFE_MEM_PWR_CTRL), + .dcp_offset = (mmDCP0_GRPH_CONTROL - mmGRPH_CONTROL), + .lb_offset = (mmLB0_LB_DATA_FORMAT - mmLB_DATA_FORMAT), +}, +{ .scl_offset = (mmSCL1_SCL_CONTROL - mmSCL_CONTROL), + .dcfe_offset = (mmCRTC1_DCFE_MEM_PWR_CTRL - mmDCFE_MEM_PWR_CTRL), + .dcp_offset = (mmDCP1_GRPH_CONTROL - mmGRPH_CONTROL), + .lb_offset = (mmLB1_LB_DATA_FORMAT - mmLB_DATA_FORMAT), +}, +{ .scl_offset = (mmSCL2_SCL_CONTROL - mmSCL_CONTROL), + .dcfe_offset = (mmCRTC2_DCFE_MEM_PWR_CTRL - mmDCFE_MEM_PWR_CTRL), + .dcp_offset = (mmDCP2_GRPH_CONTROL - mmGRPH_CONTROL), + .lb_offset = (mmLB2_LB_DATA_FORMAT - mmLB_DATA_FORMAT), +}, +{ + .scl_offset = (mmSCL3_SCL_CONTROL - mmSCL_CONTROL), + .dcfe_offset = (mmCRTC3_DCFE_MEM_PWR_CTRL - mmDCFE_MEM_PWR_CTRL), + .dcp_offset = (mmDCP3_GRPH_CONTROL - mmGRPH_CONTROL), + .lb_offset = (mmLB3_LB_DATA_FORMAT - mmLB_DATA_FORMAT), +}, +{ .scl_offset = (mmSCL4_SCL_CONTROL - mmSCL_CONTROL), + .dcfe_offset = (mmCRTC4_DCFE_MEM_PWR_CTRL - mmDCFE_MEM_PWR_CTRL), + .dcp_offset = (mmDCP4_GRPH_CONTROL - mmGRPH_CONTROL), + .lb_offset = (mmLB4_LB_DATA_FORMAT - mmLB_DATA_FORMAT), +}, +{ .scl_offset = (mmSCL5_SCL_CONTROL - mmSCL_CONTROL), + .dcfe_offset = (mmCRTC5_DCFE_MEM_PWR_CTRL - mmDCFE_MEM_PWR_CTRL), + .dcp_offset = (mmDCP5_GRPH_CONTROL - mmGRPH_CONTROL), + .lb_offset = (mmLB5_LB_DATA_FORMAT - mmLB_DATA_FORMAT), +} +}; + +static const struct dce110_ipp_reg_offsets dce100_ipp_reg_offsets[] = { +{ + .dcp_offset = (mmDCP0_CUR_CONTROL - mmCUR_CONTROL), +}, +{ + .dcp_offset = (mmDCP1_CUR_CONTROL - mmCUR_CONTROL), +}, +{ + .dcp_offset = (mmDCP2_CUR_CONTROL - mmCUR_CONTROL), +}, +{ + .dcp_offset = (mmDCP3_CUR_CONTROL - mmCUR_CONTROL), +}, +{ + .dcp_offset = (mmDCP4_CUR_CONTROL - mmCUR_CONTROL), +}, +{ + .dcp_offset = (mmDCP5_CUR_CONTROL - mmCUR_CONTROL), +} +}; + + +static const struct dce110_link_enc_bl_registers link_enc_bl_regs = { + .BL_PWM_CNTL = mmBL_PWM_CNTL, + .BL_PWM_GRP1_REG_LOCK = mmBL_PWM_GRP1_REG_LOCK, + .BL_PWM_PERIOD_CNTL = mmBL_PWM_PERIOD_CNTL, + .LVTMA_PWRSEQ_CNTL = mmLVTMA_PWRSEQ_CNTL, + .LVTMA_PWRSEQ_STATE = mmLVTMA_PWRSEQ_STATE +}; + +#define aux_regs(id)\ +[id] = {\ + .AUX_CONTROL = mmDP_AUX ## id ## _AUX_CONTROL,\ + .AUX_DPHY_RX_CONTROL0 = mmDP_AUX ## id ## _AUX_DPHY_RX_CONTROL0\ +} + +static const struct dce110_link_enc_aux_registers link_enc_aux_regs[] = { + aux_regs(0), + aux_regs(1), + aux_regs(2), + aux_regs(3), + aux_regs(4), + aux_regs(5) +}; + +#define link_regs(id)\ +[id] = {\ + .DIG_BE_CNTL = mmDIG ## id ## _DIG_BE_CNTL,\ + .DIG_BE_EN_CNTL = mmDIG ## id ## _DIG_BE_EN_CNTL,\ + .DP_CONFIG = mmDP ## id ## _DP_CONFIG,\ + .DP_DPHY_CNTL = mmDP ## id ## _DP_DPHY_CNTL,\ + .DP_DPHY_INTERNAL_CTRL = mmDP ## id ## _DP_DPHY_INTERNAL_CTRL,\ + .DP_DPHY_PRBS_CNTL = mmDP ## id ## _DP_DPHY_PRBS_CNTL,\ + .DP_DPHY_SYM0 = mmDP ## id ## _DP_DPHY_SYM0,\ + .DP_DPHY_SYM1 = mmDP ## id ## _DP_DPHY_SYM1,\ + .DP_DPHY_SYM2 = mmDP ## id ## _DP_DPHY_SYM2,\ + .DP_DPHY_TRAINING_PATTERN_SEL = mmDP ## id ## _DP_DPHY_TRAINING_PATTERN_SEL,\ + .DP_LINK_CNTL = mmDP ## id ## _DP_LINK_CNTL,\ + .DP_LINK_FRAMING_CNTL = mmDP ## id ## _DP_LINK_FRAMING_CNTL,\ + .DP_MSE_SAT0 = mmDP ## id ## _DP_MSE_SAT0,\ + .DP_MSE_SAT1 = mmDP ## id ## _DP_MSE_SAT1,\ + .DP_MSE_SAT2 = mmDP ## id ## _DP_MSE_SAT2,\ + .DP_MSE_SAT_UPDATE = mmDP ## id ## _DP_MSE_SAT_UPDATE,\ + .DP_SEC_CNTL = mmDP ## id ## _DP_SEC_CNTL,\ + .DP_VID_STREAM_CNTL = mmDP ## id ## _DP_VID_STREAM_CNTL\ +} + +static const struct dce110_link_enc_registers link_enc_regs[] = { + link_regs(0), + link_regs(1), + link_regs(2), + link_regs(3), + link_regs(4), + link_regs(5), + link_regs(6) +}; + +#define stream_enc_regs(id)\ +[id] = {\ + .AFMT_AVI_INFO0 = mmDIG ## id ## _AFMT_AVI_INFO0,\ + .AFMT_AVI_INFO1 = mmDIG ## id ## _AFMT_AVI_INFO1,\ + .AFMT_AVI_INFO2 = mmDIG ## id ## _AFMT_AVI_INFO2,\ + .AFMT_AVI_INFO3 = mmDIG ## id ## _AFMT_AVI_INFO3,\ + .AFMT_GENERIC_0 = mmDIG ## id ## _AFMT_GENERIC_0,\ + .AFMT_GENERIC_7 = mmDIG ## id ## _AFMT_GENERIC_7,\ + .AFMT_GENERIC_HDR = mmDIG ## id ## _AFMT_GENERIC_HDR,\ + .AFMT_INFOFRAME_CONTROL0 = mmDIG ## id ## _AFMT_INFOFRAME_CONTROL0,\ + .AFMT_VBI_PACKET_CONTROL = mmDIG ## id ## _AFMT_VBI_PACKET_CONTROL,\ + .DIG_FE_CNTL = mmDIG ## id ## _DIG_FE_CNTL,\ + .DP_MSE_RATE_CNTL = mmDP ## id ## _DP_MSE_RATE_CNTL,\ + .DP_MSE_RATE_UPDATE = mmDP ## id ## _DP_MSE_RATE_UPDATE,\ + .DP_PIXEL_FORMAT = mmDP ## id ## _DP_PIXEL_FORMAT,\ + .DP_SEC_CNTL = mmDP ## id ## _DP_SEC_CNTL,\ + .DP_STEER_FIFO = mmDP ## id ## _DP_STEER_FIFO,\ + .DP_VID_M = mmDP ## id ## _DP_VID_M,\ + .DP_VID_N = mmDP ## id ## _DP_VID_N,\ + .DP_VID_STREAM_CNTL = mmDP ## id ## _DP_VID_STREAM_CNTL,\ + .DP_VID_TIMING = mmDP ## id ## _DP_VID_TIMING,\ + .HDMI_CONTROL = mmDIG ## id ## _HDMI_CONTROL,\ + .HDMI_GC = mmDIG ## id ## _HDMI_GC,\ + .HDMI_GENERIC_PACKET_CONTROL0 = mmDIG ## id ## _HDMI_GENERIC_PACKET_CONTROL0,\ + .HDMI_GENERIC_PACKET_CONTROL1 = mmDIG ## id ## _HDMI_GENERIC_PACKET_CONTROL1,\ + .HDMI_INFOFRAME_CONTROL0 = mmDIG ## id ## _HDMI_INFOFRAME_CONTROL0,\ + .HDMI_INFOFRAME_CONTROL1 = mmDIG ## id ## _HDMI_INFOFRAME_CONTROL1,\ + .HDMI_VBI_PACKET_CONTROL = mmDIG ## id ## _HDMI_VBI_PACKET_CONTROL,\ + .TMDS_CNTL = mmDIG ## id ## _TMDS_CNTL\ +} + +static const struct dce110_stream_enc_registers stream_enc_regs[] = { + stream_enc_regs(0), + stream_enc_regs(1), + stream_enc_regs(2), + stream_enc_regs(3), + stream_enc_regs(4), + stream_enc_regs(5), + stream_enc_regs(6) +}; + +#define DCFE_MEM_PWR_CTRL_REG_BASE 0x1b03 + +static const struct dce110_opp_reg_offsets dce100_opp_reg_offsets[] = { +{ + .fmt_offset = (mmFMT0_FMT_CONTROL - mmFMT_CONTROL), + .dcfe_offset = (mmCRTC0_DCFE_MEM_PWR_CTRL - DCFE_MEM_PWR_CTRL_REG_BASE), + .dcp_offset = (mmDCP0_GRPH_CONTROL - mmGRPH_CONTROL), +}, +{ .fmt_offset = (mmFMT1_FMT_CONTROL - mmFMT0_FMT_CONTROL), + .dcfe_offset = (mmCRTC1_DCFE_MEM_PWR_CTRL - DCFE_MEM_PWR_CTRL_REG_BASE), + .dcp_offset = (mmDCP1_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), +}, +{ .fmt_offset = (mmFMT2_FMT_CONTROL - mmFMT0_FMT_CONTROL), + .dcfe_offset = (mmCRTC2_DCFE_MEM_PWR_CTRL - DCFE_MEM_PWR_CTRL_REG_BASE), + .dcp_offset = (mmDCP2_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), +}, +{ + .fmt_offset = (mmFMT3_FMT_CONTROL - mmFMT0_FMT_CONTROL), + .dcfe_offset = (mmCRTC3_DCFE_MEM_PWR_CTRL - DCFE_MEM_PWR_CTRL_REG_BASE), + .dcp_offset = (mmDCP3_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), +}, +{ .fmt_offset = (mmFMT4_FMT_CONTROL - mmFMT0_FMT_CONTROL), + .dcfe_offset = (mmCRTC4_DCFE_MEM_PWR_CTRL - DCFE_MEM_PWR_CTRL_REG_BASE), + .dcp_offset = (mmDCP4_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), +}, +{ .fmt_offset = (mmFMT5_FMT_CONTROL - mmFMT0_FMT_CONTROL), + .dcfe_offset = (mmCRTC5_DCFE_MEM_PWR_CTRL - DCFE_MEM_PWR_CTRL_REG_BASE), + .dcp_offset = (mmDCP5_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), +} +}; + + +static struct timing_generator *dce100_timing_generator_create( + struct adapter_service *as, + struct dc_context *ctx, + uint32_t instance, + const struct dce110_timing_generator_offsets *offsets) +{ + struct dce110_timing_generator *tg110 = + dm_alloc(ctx, sizeof(struct dce110_timing_generator)); + + if (!tg110) + return NULL; + + if (dce110_timing_generator_construct(tg110, as, ctx, instance, + offsets)) + return &tg110->base; + + BREAK_TO_DEBUGGER(); + dm_free(ctx, tg110); + return NULL; +} + +static struct stream_encoder *dce100_stream_encoder_create( + enum engine_id eng_id, + struct dc_context *ctx, + struct dc_bios *bp, + const struct dce110_stream_enc_registers *regs) +{ + struct dce110_stream_encoder *enc110 = + dm_alloc(ctx, sizeof(struct dce110_stream_encoder)); + + if (!enc110) + return NULL; + + if (dce110_stream_encoder_construct(enc110, ctx, bp, eng_id, regs)) + return &enc110->base; + + BREAK_TO_DEBUGGER(); + dm_free(ctx, enc110); + return NULL; +} + +static struct mem_input *dce100_mem_input_create( + struct dc_context *ctx, + uint32_t inst, + const struct dce110_mem_input_reg_offsets *offset) +{ + struct dce110_mem_input *mem_input110 = + dm_alloc(ctx, sizeof(struct dce110_mem_input)); + + if (!mem_input110) + return NULL; + + if (dce110_mem_input_construct(mem_input110, + ctx, inst, offset)) + return &mem_input110->base; + + BREAK_TO_DEBUGGER(); + dm_free(ctx, mem_input110); + return NULL; +} + +static void dce100_transform_destroy(struct transform **xfm) +{ + dm_free((*xfm)->ctx, TO_DCE110_TRANSFORM(*xfm)); + *xfm = NULL; +} + +static struct transform *dce100_transform_create( + struct dc_context *ctx, + uint32_t inst, + const struct dce110_transform_reg_offsets *offsets) +{ + struct dce110_transform *transform = + dm_alloc(ctx, sizeof(struct dce110_transform)); + + if (!transform) + return NULL; + + if (dce110_transform_construct(transform, ctx, inst, offsets)) + return &transform->base; + + BREAK_TO_DEBUGGER(); + dm_free(ctx, transform); + return NULL; +} + +static struct input_pixel_processor *dce100_ipp_create( + struct dc_context *ctx, + uint32_t inst, + const struct dce110_ipp_reg_offsets *offsets) +{ + struct dce110_ipp *ipp = + dm_alloc(ctx, sizeof(struct dce110_ipp)); + + if (!ipp) + return NULL; + + if (dce110_ipp_construct(ipp, ctx, inst, offsets)) + return &ipp->base; + + BREAK_TO_DEBUGGER(); + dm_free(ctx, ipp); + return NULL; +} + +struct link_encoder *dce100_link_encoder_create( + const struct encoder_init_data *enc_init_data) +{ + struct dce110_link_encoder *enc110 = + dm_alloc( + enc_init_data->ctx, + sizeof(struct dce110_link_encoder)); + + if (!enc110) + return NULL; + + if (dce110_link_encoder_construct( + enc110, + enc_init_data, + &link_enc_regs[enc_init_data->transmitter], + &link_enc_aux_regs[enc_init_data->channel - 1], + &link_enc_bl_regs)) + return &enc110->base; + + BREAK_TO_DEBUGGER(); + dm_free(enc_init_data->ctx, enc110); + return NULL; +} + + +struct output_pixel_processor *dce100_opp_create( + struct dc_context *ctx, + uint32_t inst, + const struct dce110_opp_reg_offsets *offset) +{ + struct dce110_opp *opp = + dm_alloc(ctx, sizeof(struct dce110_opp)); + + if (!opp) + return NULL; + + if (dce110_opp_construct(opp, + ctx, inst, offset)) + return &opp->base; + + BREAK_TO_DEBUGGER(); + dm_free(ctx, opp); + return NULL; +} + + +void dce100_opp_destroy(struct output_pixel_processor **opp) +{ + dm_free((*opp)->ctx, FROM_DCE11_OPP(*opp)->regamma.coeff128_dx); + dm_free((*opp)->ctx, FROM_DCE11_OPP(*opp)->regamma.coeff128_oem); + dm_free((*opp)->ctx, FROM_DCE11_OPP(*opp)->regamma.coeff128); + dm_free((*opp)->ctx, FROM_DCE11_OPP(*opp)->regamma.axis_x_1025); + dm_free((*opp)->ctx, FROM_DCE11_OPP(*opp)->regamma.axis_x_256); + dm_free((*opp)->ctx, FROM_DCE11_OPP(*opp)->regamma.coordinates_x); + dm_free((*opp)->ctx, FROM_DCE11_OPP(*opp)->regamma.rgb_regamma); + dm_free((*opp)->ctx, FROM_DCE11_OPP(*opp)->regamma.rgb_resulted); + dm_free((*opp)->ctx, FROM_DCE11_OPP(*opp)->regamma.rgb_oem); + dm_free((*opp)->ctx, FROM_DCE11_OPP(*opp)->regamma.rgb_user); + dm_free((*opp)->ctx, FROM_DCE11_OPP(*opp)); + *opp = NULL; +} + +struct clock_source *dce100_clock_source_create( + struct dc_context *ctx, + struct dc_bios *bios, + enum clock_source_id id, + const struct dce110_clk_src_reg_offsets *offsets) +{ + struct dce110_clk_src *clk_src = + dm_alloc(ctx, sizeof(struct dce110_clk_src)); + + if (!clk_src) + return NULL; + + if (dce110_clk_src_construct(clk_src, ctx, bios, id, offsets)) + return &clk_src->base; + + BREAK_TO_DEBUGGER(); + return NULL; +} + +void dce100_clock_source_destroy(struct clock_source **clk_src) +{ + dm_free((*clk_src)->ctx, TO_DCE110_CLK_SRC(*clk_src)); + *clk_src = NULL; +} + +void dce100_destruct_resource_pool(struct resource_pool *pool) +{ + unsigned int i; + + for (i = 0; i < pool->controller_count; i++) { + if (pool->opps[i] != NULL) + dce100_opp_destroy(&pool->opps[i]); + + if (pool->transforms[i] != NULL) + dce100_transform_destroy(&pool->transforms[i]); + + if (pool->ipps[i] != NULL) + dce110_ipp_destroy(&pool->ipps[i]); + + if (pool->mis[i] != NULL) { + dm_free(pool->mis[i]->ctx, + TO_DCE110_MEM_INPUT(pool->mis[i])); + pool->mis[i] = NULL; + } + + if (pool->timing_generators[i] != NULL) { + dm_free(pool->timing_generators[i]->ctx, + DCE110TG_FROM_TG(pool->timing_generators[i])); + pool->timing_generators[i] = NULL; + } + } + + for (i = 0; i < pool->stream_enc_count; i++) { + if (pool->stream_enc[i] != NULL) + dm_free(pool->stream_enc[i]->ctx, + DCE110STRENC_FROM_STRENC(pool->stream_enc[i])); + } + + for (i = 0; i < pool->clk_src_count; i++) { + if (pool->clock_sources[i] != NULL) + dce100_clock_source_destroy(&pool->clock_sources[i]); + } + + for (i = 0; i < pool->audio_count; i++) { + if (pool->audios[i] != NULL) + dal_audio_destroy(&pool->audios[i]); + } + + if (pool->display_clock != NULL) + dal_display_clock_destroy(&pool->display_clock); + + if (pool->scaler_filter != NULL) + dal_scaler_filter_destroy(&pool->scaler_filter); + + if (pool->irqs != NULL) + dal_irq_service_destroy(&pool->irqs); + + if (pool->adapter_srv != NULL) + dal_adapter_service_destroy(&pool->adapter_srv); +} + +static struct clock_source *find_first_free_pll( + struct resource_context *res_ctx) +{ + if (res_ctx->clock_source_ref_count[DCE100_CLK_SRC_PLL0] == 0) + return res_ctx->pool.clock_sources[DCE100_CLK_SRC_PLL0]; + + if (res_ctx->clock_source_ref_count[DCE100_CLK_SRC_PLL1] == 0) + return res_ctx->pool.clock_sources[DCE100_CLK_SRC_PLL1]; + + return 0; +} + +static enum audio_dto_source translate_to_dto_source(enum controller_id crtc_id) +{ + switch (crtc_id) { + case CONTROLLER_ID_D0: + return DTO_SOURCE_ID0; + case CONTROLLER_ID_D1: + return DTO_SOURCE_ID1; + case CONTROLLER_ID_D2: + return DTO_SOURCE_ID2; + case CONTROLLER_ID_D3: + return DTO_SOURCE_ID3; + case CONTROLLER_ID_D4: + return DTO_SOURCE_ID4; + case CONTROLLER_ID_D5: + return DTO_SOURCE_ID5; + default: + return DTO_SOURCE_UNKNOWN; + } +} + +static void build_audio_output( + const struct core_stream *stream, + struct audio_output *audio_output) +{ + audio_output->engine_id = stream->stream_enc->id; + + audio_output->signal = stream->signal; + + /* audio_crtc_info */ + + audio_output->crtc_info.h_total = + stream->public.timing.h_total; + + /* + * Audio packets are sent during actual CRTC blank physical signal, we + * need to specify actual active signal portion + */ + audio_output->crtc_info.h_active = + stream->public.timing.h_addressable + + stream->public.timing.h_border_left + + stream->public.timing.h_border_right; + + audio_output->crtc_info.v_active = + stream->public.timing.v_addressable + + stream->public.timing.v_border_top + + stream->public.timing.v_border_bottom; + + audio_output->crtc_info.pixel_repetition = 1; + + audio_output->crtc_info.interlaced = + stream->public.timing.flags.INTERLACE; + + audio_output->crtc_info.refresh_rate = + (stream->public.timing.pix_clk_khz*1000)/ + (stream->public.timing.h_total*stream->public.timing.v_total); + + audio_output->crtc_info.color_depth = + stream->public.timing.display_color_depth; + + audio_output->crtc_info.requested_pixel_clock = + stream->pix_clk_params.requested_pix_clk; + + /* + * TODO - Investigate why calculated pixel clk has to be + * requested pixel clk + */ + audio_output->crtc_info.calculated_pixel_clock = + stream->pix_clk_params.requested_pix_clk; + + if (stream->signal == SIGNAL_TYPE_DISPLAY_PORT || + stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) { + audio_output->pll_info.dp_dto_source_clock_in_khz = + dal_display_clock_get_dp_ref_clk_frequency( + stream->dis_clk); + } + + audio_output->pll_info.feed_back_divider = + stream->pll_settings.feedback_divider; + + audio_output->pll_info.dto_source = + translate_to_dto_source( + stream->controller_idx + 1); + + /* TODO hard code to enable for now. Need get from stream */ + audio_output->pll_info.ss_enabled = true; + + audio_output->pll_info.ss_percentage = + stream->pll_settings.ss_percentage; +} + +static void get_pixel_clock_parameters( + const struct core_stream *stream, + struct pixel_clk_params *pixel_clk_params) +{ + pixel_clk_params->requested_pix_clk = stream->public.timing.pix_clk_khz; + pixel_clk_params->encoder_object_id = stream->sink->link->link_enc->id; + pixel_clk_params->signal_type = stream->sink->public.sink_signal; + pixel_clk_params->controller_id = stream->controller_idx + 1; + /* TODO: un-hardcode*/ + pixel_clk_params->requested_sym_clk = LINK_RATE_LOW * + LINK_RATE_REF_FREQ_IN_KHZ; + pixel_clk_params->flags.ENABLE_SS = 0; + pixel_clk_params->color_depth = + stream->public.timing.display_color_depth; + pixel_clk_params->flags.DISPLAY_BLANKED = 1; +} + +static enum dc_status build_stream_hw_param(struct core_stream *stream) +{ + /*TODO: unhardcode*/ + stream->max_tmds_clk_from_edid_in_mhz = 0; + stream->max_hdmi_deep_color = COLOR_DEPTH_121212; + stream->max_hdmi_pixel_clock = 600000; + + get_pixel_clock_parameters(stream, &stream->pix_clk_params); + stream->clock_source->funcs->get_pix_clk_dividers( + stream->clock_source, + &stream->pix_clk_params, + &stream->pll_settings); + + build_audio_output(stream, &stream->audio_output); + + return DC_OK; +} + +static enum dc_status validate_mapped_resource( + const struct dc *dc, + struct validate_context *context) +{ + enum dc_status status = DC_OK; + uint8_t i, j; + + for (i = 0; i < context->target_count; i++) { + struct core_target *target = context->targets[i]; + + if (context->target_flags[i].unchanged) + continue; + for (j = 0; j < target->public.stream_count; j++) { + struct core_stream *stream = + DC_STREAM_TO_CORE(target->public.streams[j]); + struct core_link *link = stream->sink->link; + + if (!stream->tg->funcs->validate_timing( + stream->tg, &stream->public.timing)) + return DC_FAIL_CONTROLLER_VALIDATE; + + if (stream->signal == SIGNAL_TYPE_VIRTUAL) + return status; + + status = build_stream_hw_param(stream); + + if (status != DC_OK) + return status; + + if (!link->link_enc->funcs->validate_output_with_stream( + link->link_enc, + stream)) + return DC_FAIL_ENC_VALIDATE; + + /* TODO: validate audio ASIC caps, encoder */ + + status = dc_link_validate_mode_timing(stream->sink, + link, + &stream->public.timing); + + if (status != DC_OK) + return status; + + build_info_frame(stream); + } + } + + return DC_OK; +} + +enum dc_status dce100_validate_bandwidth( + const struct dc *dc, + struct validate_context *context) +{ + /* TODO implement when needed */ + + return DC_OK; +} + +static void set_target_unchanged( + struct validate_context *context, + uint8_t target_idx) +{ + uint8_t i; + struct core_target *target = context->targets[target_idx]; + + context->target_flags[target_idx].unchanged = true; + for (i = 0; i < target->public.stream_count; i++) { + struct core_stream *core_stream = + DC_STREAM_TO_CORE(target->public.streams[i]); + uint8_t index = core_stream->controller_idx; + + context->res_ctx.controller_ctx[index].flags.unchanged = true; + } +} + +static enum dc_status map_clock_resources( + const struct dc *dc, + struct validate_context *context) +{ + uint8_t i, j; + + /* mark resources used for targets that are already active */ + for (i = 0; i < context->target_count; i++) { + struct core_target *target = context->targets[i]; + + if (!context->target_flags[i].unchanged) + continue; + + for (j = 0; j < target->public.stream_count; j++) { + struct core_stream *stream = + DC_STREAM_TO_CORE(target->public.streams[j]); + + reference_clock_source( + &context->res_ctx, + stream->clock_source); + } + } + + /* acquire new resources */ + for (i = 0; i < context->target_count; i++) { + struct core_target *target = context->targets[i]; + + if (context->target_flags[i].unchanged) + continue; + + for (j = 0; j < target->public.stream_count; j++) { + struct core_stream *stream = + DC_STREAM_TO_CORE(target->public.streams[j]); + + if (dc_is_dp_signal(stream->signal) + || stream->signal == SIGNAL_TYPE_VIRTUAL) + stream->clock_source = context->res_ctx. + pool.clock_sources[DCE100_CLK_SRC_EXT]; + else + stream->clock_source = + find_used_clk_src_for_sharing( + context, stream); + if (stream->clock_source == NULL) + stream->clock_source = + find_first_free_pll(&context->res_ctx); + + if (stream->clock_source == NULL) + return DC_NO_CLOCK_SOURCE_RESOURCE; + + reference_clock_source( + &context->res_ctx, + stream->clock_source); + } + } + + return DC_OK; +} + +enum dc_status dce100_validate_with_context( + const struct dc *dc, + const struct dc_validation_set set[], + uint8_t set_count, + struct validate_context *context) +{ + enum dc_status result = DC_ERROR_UNEXPECTED; + uint8_t i, j; + struct dc_context *dc_ctx = dc->ctx; + + for (i = 0; i < set_count; i++) { + context->targets[i] = DC_TARGET_TO_CORE(set[i].target); + + for (j = 0; j < dc->current_context.target_count; j++) + if (dc->current_context.targets[j] == context->targets[i]) + set_target_unchanged(context, i); + + if (!context->target_flags[i].unchanged) + if (!logical_attach_surfaces_to_target( + (struct dc_surface **)set[i].surfaces, + set[i].surface_count, + &context->targets[i]->public)) { + DC_ERROR("Failed to attach surface to target!\n"); + return DC_FAIL_ATTACH_SURFACES; + } + } + + context->target_count = set_count; + + context->res_ctx.pool = dc->res_pool; + + result = map_resources(dc, context); + + if (result == DC_OK) + result = map_clock_resources(dc, context); + + if (result == DC_OK) + result = validate_mapped_resource(dc, context); + + if (result == DC_OK) + build_scaling_params_for_context(dc, context); + + if (result == DC_OK) + result = dce100_validate_bandwidth(dc, context); + + return result; +} + +static struct resource_funcs dce100_res_pool_funcs = { + .destruct = dce100_destruct_resource_pool, + .link_enc_create = dce100_link_encoder_create, + .link_enc_destroy = dce110_link_encoder_destroy, + .validate_with_context = dce100_validate_with_context, + .validate_bandwidth = dce100_validate_bandwidth +}; + +bool dce100_construct_resource_pool( + struct adapter_service *adapter_serv, + uint8_t num_virtual_links, + struct dc *dc, + struct resource_pool *pool) +{ + unsigned int i; + struct audio_init_data audio_init_data = { 0 }; + struct dc_context *ctx = dc->ctx; + + pool->adapter_srv = adapter_serv; + pool->funcs = &dce100_res_pool_funcs; + + pool->stream_engines.engine.ENGINE_ID_DIGA = 1; + pool->stream_engines.engine.ENGINE_ID_DIGB = 1; + pool->stream_engines.engine.ENGINE_ID_DIGC = 1; + pool->stream_engines.engine.ENGINE_ID_DIGD = 1; + pool->stream_engines.engine.ENGINE_ID_DIGE = 1; + pool->stream_engines.engine.ENGINE_ID_DIGF = 1; + + pool->clock_sources[DCE100_CLK_SRC_PLL0] = dce100_clock_source_create( + ctx, dal_adapter_service_get_bios_parser(adapter_serv), + CLOCK_SOURCE_ID_PLL0, &dce100_clk_src_reg_offsets[0]); + pool->clock_sources[DCE100_CLK_SRC_PLL1] = dce100_clock_source_create( + ctx, dal_adapter_service_get_bios_parser(adapter_serv), + CLOCK_SOURCE_ID_PLL1, &dce100_clk_src_reg_offsets[1]); + pool->clock_sources[DCE100_CLK_SRC_EXT] = dce100_clock_source_create( + ctx, dal_adapter_service_get_bios_parser(adapter_serv), + CLOCK_SOURCE_ID_EXTERNAL, &dce100_clk_src_reg_offsets[0]); + pool->clk_src_count = DCE100_CLK_SRC_TOTAL; + + for (i = 0; i < pool->clk_src_count; i++) { + if (pool->clock_sources[i] == NULL) { + dm_error("DC: failed to create clock sources!\n"); + BREAK_TO_DEBUGGER(); + goto clk_src_create_fail; + } + } + + pool->display_clock = dal_display_clock_dce110_create(ctx, adapter_serv); + if (pool->display_clock == NULL) { + dm_error("DC: failed to create display clock!\n"); + BREAK_TO_DEBUGGER(); + goto disp_clk_create_fail; + } + + { + struct irq_service_init_data init_data; + + init_data.ctx = dc->ctx; + pool->irqs = dal_irq_service_create( + dal_adapter_service_get_dce_version( + dc->res_pool.adapter_srv), + &init_data); + if (!pool->irqs) + goto irqs_create_fail; + + } + + pool->controller_count = + dal_adapter_service_get_func_controllers_num(adapter_serv); + pool->stream_enc_count = dal_adapter_service_get_stream_engines_num( + adapter_serv); + pool->scaler_filter = dal_scaler_filter_create(ctx); + if (pool->scaler_filter == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create filter!\n"); + goto filter_create_fail; + } + + for (i = 0; i < pool->controller_count; i++) { + pool->timing_generators[i] = dce100_timing_generator_create( + adapter_serv, ctx, i, &dce100_tg_offsets[i]); + if (pool->timing_generators[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create tg!\n"); + goto controller_create_fail; + } + + pool->mis[i] = dce100_mem_input_create(ctx, i, + &dce100_mi_reg_offsets[i]); + if (pool->mis[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create memory input!\n"); + goto controller_create_fail; + } + + pool->ipps[i] = dce100_ipp_create(ctx, i, + &dce100_ipp_reg_offsets[i]); + if (pool->ipps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create input pixel processor!\n"); + goto controller_create_fail; + } + + pool->transforms[i] = dce100_transform_create( + ctx, i, &dce100_xfm_offsets[i]); + if (pool->transforms[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create transform!\n"); + goto controller_create_fail; + } + pool->transforms[i]->funcs->transform_set_scaler_filter( + pool->transforms[i], + pool->scaler_filter); + + pool->opps[i] = dce100_opp_create(ctx, i, &dce100_opp_reg_offsets[i]); + if (pool->opps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create output pixel processor!\n"); + goto controller_create_fail; + } + } + + audio_init_data.as = adapter_serv; + audio_init_data.ctx = ctx; + pool->audio_count = 0; + for (i = 0; i < pool->controller_count; i++) { + struct graphics_object_id obj_id; + + obj_id = dal_adapter_service_enum_audio_object(adapter_serv, i); + if (false == dal_graphics_object_id_is_valid(obj_id)) { + /* no more valid audio objects */ + break; + } + + audio_init_data.audio_stream_id = obj_id; + pool->audios[i] = dal_audio_create(&audio_init_data); + if (pool->audios[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create DPPs!\n"); + goto audio_create_fail; + } + pool->audio_count++; + } + + for (i = 0; i < pool->stream_enc_count; i++) { + /* TODO: rework fragile code*/ + if (pool->stream_engines.u_all & 1 << i) { + pool->stream_enc[i] = dce100_stream_encoder_create( + i, dc->ctx, + dal_adapter_service_get_bios_parser( + adapter_serv), + &stream_enc_regs[i]); + if (pool->stream_enc[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create stream_encoder!\n"); + goto stream_enc_create_fail; + } + } + } + + for (i = 0; i < num_virtual_links; i++) { + pool->stream_enc[pool->stream_enc_count] = + virtual_stream_encoder_create( + dc->ctx, dal_adapter_service_get_bios_parser( + adapter_serv)); + if (pool->stream_enc[pool->stream_enc_count] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create stream_encoder!\n"); + goto stream_enc_create_fail; + } + pool->stream_enc_count++; + } + + return true; + +stream_enc_create_fail: + for (i = 0; i < pool->stream_enc_count; i++) { + if (pool->stream_enc[i] != NULL) + dm_free(pool->stream_enc[i]->ctx, + DCE110STRENC_FROM_STRENC(pool->stream_enc[i])); + } + +audio_create_fail: + for (i = 0; i < pool->controller_count; i++) { + if (pool->audios[i] != NULL) + dal_audio_destroy(&pool->audios[i]); + } + +controller_create_fail: + for (i = 0; i < pool->controller_count; i++) { + if (pool->opps[i] != NULL) + dce100_opp_destroy(&pool->opps[i]); + + if (pool->transforms[i] != NULL) + dce100_transform_destroy(&pool->transforms[i]); + + if (pool->ipps[i] != NULL) + dce110_ipp_destroy(&pool->ipps[i]); + + if (pool->mis[i] != NULL) { + dm_free(pool->mis[i]->ctx, + TO_DCE110_MEM_INPUT(pool->mis[i])); + pool->mis[i] = NULL; + } + + if (pool->timing_generators[i] != NULL) { + dm_free(pool->timing_generators[i]->ctx, + DCE110TG_FROM_TG(pool->timing_generators[i])); + pool->timing_generators[i] = NULL; + } + } + +filter_create_fail: + dal_irq_service_destroy(&pool->irqs); + +irqs_create_fail: + dal_display_clock_destroy(&pool->display_clock); + +disp_clk_create_fail: +clk_src_create_fail: + for (i = 0; i < pool->clk_src_count; i++) { + if (pool->clock_sources[i] != NULL) + dce100_clock_source_destroy(&pool->clock_sources[i]); + } + + return false; +} diff --git a/drivers/gpu/drm/amd/dal/dc/dce100/dce100_resource.h b/drivers/gpu/drm/amd/dal/dc/dce100/dce100_resource.h new file mode 100644 index 000000000000..2a23d864831f --- /dev/null +++ b/drivers/gpu/drm/amd/dal/dc/dce100/dce100_resource.h @@ -0,0 +1,43 @@ +/* +* Copyright 2015 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 DCE100_RESOURCE_H_ +#define DCE100_RESOURCE_H_ + +struct adapter_service; +struct dc; +struct resource_pool; +struct dc_validation_set; + + +bool dce100_construct_resource_pool( + struct adapter_service *adapter_serv, + uint8_t num_virtual_links, + struct dc *dc, + struct resource_pool *pool); + +void dce100_destruct_resource_pool(struct resource_pool *pool); + +#endif /* DCE100_RESOURCE_H_ */