From patchwork Tue Feb 16 22:27:42 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Harry Wentland X-Patchwork-Id: 8332791 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 3FFDCC02AA for ; Tue, 16 Feb 2016 22:28:37 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 98A98202EB for ; Tue, 16 Feb 2016 22:28:33 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id 3A02C202F2 for ; Tue, 16 Feb 2016 22:28:25 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id AC4C56E8B3; Tue, 16 Feb 2016 22:28:23 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from na01-by2-obe.outbound.protection.outlook.com (mail-by2on0064.outbound.protection.outlook.com [207.46.100.64]) by gabe.freedesktop.org (Postfix) with ESMTPS id 7B8346E8B5 for ; Tue, 16 Feb 2016 22:28:22 +0000 (UTC) Received: from BN1PR12CA0033.namprd12.prod.outlook.com (10.160.77.43) by BN4PR12MB0851.namprd12.prod.outlook.com (10.164.59.13) with Microsoft SMTP Server (TLS) id 15.1.409.15; Tue, 16 Feb 2016 22:28:20 +0000 Received: from DM3NAM03FT017.eop-NAM03.prod.protection.outlook.com (2a01:111:f400:7e49::205) by BN1PR12CA0033.outlook.office365.com (2a01:111:e400:49::43) with Microsoft SMTP Server (TLS) id 15.1.409.15 via Frontend Transport; Tue, 16 Feb 2016 22:28:20 +0000 Authentication-Results: spf=none (sender IP is 165.204.84.222) smtp.mailfrom=amd.com; lists.freedesktop.org; dkim=none (message not signed) header.d=none;lists.freedesktop.org; dmarc=permerror action=none header.from=amd.com; Received-SPF: None (protection.outlook.com: amd.com does not designate permitted sender hosts) Received: from atltwp02.amd.com (165.204.84.222) by DM3NAM03FT017.mail.protection.outlook.com (10.152.82.201) with Microsoft SMTP Server id 15.1.415.6 via Frontend Transport; Tue, 16 Feb 2016 22:28:19 +0000 X-WSS-ID: 0O2NVR3-08-5TW-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 atltwp02.amd.com (Axway MailGate 5.3.1) with ESMTPS id 270BCBD8971 for ; Tue, 16 Feb 2016 17:28:15 -0500 (EST) Received: from SATLEXDAG04.amd.com (10.181.40.9) by satlvexedge01.amd.com (10.177.96.28) with Microsoft SMTP Server (TLS) id 14.3.195.1; Tue, 16 Feb 2016 16:28:21 -0600 Received: from STOREXDAG02.amd.com (10.1.13.11) by satlexdag04.amd.com (10.181.40.9) with Microsoft SMTP Server (TLS) id 14.3.266.1; Tue, 16 Feb 2016 17:28:16 -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:16 -0500 From: Harry Wentland To: Subject: [PATCH v2 02/26] drm/amd/dal: Add DAL Basic Types and Logger Date: Tue, 16 Feb 2016 17:27:42 -0500 Message-ID: <51cecb97fcf271e004e73b2e69264c4babfafecc.1455660366.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.222; CTRY:US; IPV:NLI; EFV:NLI; SFV:NSPM; SFS:(10009020)(6009001)(2980300002)(428002)(199003)(189002)(189998001)(101416001)(11100500001)(50986999)(5008740100001)(2906002)(19580395003)(76176999)(33646002)(5003940100001)(575784001)(36756003)(1220700001)(450100001)(110136002)(86362001)(105586002)(87936001)(50466002)(77096005)(106466001)(5003600100002)(2950100001)(50226001)(19580405001)(586003)(118296001)(4326007)(92566002)(2351001)(229853001)(53416004)(1096002)(47776003)(48376002)(551934003)(579004)(559001); DIR:OUT; SFP:1101; SCL:1; SRVR:BN4PR12MB0851; H:atltwp02.amd.com; FPR:; SPF:None; MLV:sfv; A:1; MX:1; LANG:en; X-MS-Office365-Filtering-Correlation-Id: 48745439-66e8-4e77-4569-08d337207909 X-Microsoft-Exchange-Diagnostics: 1; BN4PR12MB0851; 2:qjIq1njcTqX97bitG10Qiuubm+UJQQF7QbwLzfK+KkkexipSZeMXbXlVhWYR+Dc99JZp8H2ONoo38W5GwzfXRe7z4q0EgTMu2qjclIyjBhEciFnrGFPMk5BH2IpJrbI6pnlGVkmH1ERGXPE02OWYZjfTfRNe9eagNlFfwrsS5MZMrLW8GK2h4jUziuIuP+8S; 3:EsPCeZ5zj1h7CtKzi6RGBlTp9/pDFmrZVBjQk5Lr4TzmY1NWMiR8XjQ5bu5qijVhOgXlIYsI3R2D26i4+u1AcVUaxVJ/J+T8XjWc6M1Tx1YdQ1S0FYHk5AJcj3Ikmbu5jJOeaX3ESdMwI6uVD24wxkNPvGG8O/6UPJFqpoyRQ+e76/m0Uls5UIwcV7KrHr0W8sANnSeDzb3VyXchLt8FAW1LS45hthqY8A4699M8+PM=; 25:bGp8TsHssVRzzML52iQ5fe5N0UTuTLAoBL8y6FT/iJGop3eb0yKo4PTro9/4WajS7rYyKQRdiZIg2vZA2ZvUyBZsl92NWeG8afyxbiYfRHeWZConb9RSK7r46DU90vTdNNlvRpSbBbH+cZOfbcM+8QlRcp4bbSiY0UwjFBywobzrgk7s8Q9sCZzzbRjlzxoPTBTAx1CWZ8/I7T/vI/wSX4TqBkUWpbKa+LTZ3/qPmp+6D0Jjz0ylPbkU6L3JMR0FkUVTaz3ie7/y7VTDx9cpSlxH9j+h7907Lg7DRZ2d6E2LF6pDVMr76MYTzg92zNKX X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:;SRVR:BN4PR12MB0851; X-Microsoft-Exchange-Diagnostics: 1; BN4PR12MB0851; 20:e2hKRrBW4VMSrtASpScoKedFVEA9rx3ND0Nw9mSxGFPZZL0F58Fo15DeLf6BoM6nL8zlOxRSvl4+9Gn0FSIjGNV707xatzLyeQpFAlpxc8YL9D8t3TWZKQ9BQMJOKqH5UX4oMiVVr/931VRTVUWlEmuRDniX8fmV+wHyHbHmsM8uqO6NRN51+A4QFXmd7mFK3YhQRnbdpZNrUO+ZZtnbiQlK1hYkZPancvneGKUWezkXIhLhpjM8l9VAH/0Cin6oVP/ZTe1EnFaErV6EC9+cjv8nPJHOEPqpaPe61cw2xt3UcHRPn1xp7rSw9L1IVKlUmFCD717FLKV3E3ufrd67knxo7vLjU4HlrqQwX3sCV6+3Z1Xw1VmYFEfbNjogpAD/i+mvM3kotsigOVo1LCSTwAaXrGEkg0WshjItRePnfpQ0AXLNT7SgrznKRjsnIN4MKI4sI1FtBI5lm06EilKciPrv4gG4WLlptAlV9LyaUEQzDrWqnThtOjudZiSCkVTB 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)(5005006)(13023025)(13017025)(13018025)(10201501046)(3002001); SRVR:BN4PR12MB0851; BCL:0; PCL:0; RULEID:; SRVR:BN4PR12MB0851; X-Microsoft-Exchange-Diagnostics: 1; BN4PR12MB0851; 4:G3zHG3vTad2/lFGr9djJOQ1NDW/zJIuxJyDebzMsk4pZjpUtjR/euDUYgl4trGYwvDvX5xxfdDDb3uSVRxQY4dHSivzKODnl1bPdGl0vq+uJ0yLmoUVNLXtR4+Hi9KzG24mCBvVMDiY9eWuEF++bH3NSwmNW6x0dq1aNJOKCen8r/HoVMIhWEZvdVPbvTM0hRKd5pz2DvZshgATk/ewuo66opX1Jr83gF1mNDQqEfgKe9znwSh05xq+y8HTqeblgcvbc2GXGPHnQjaUaj4vHxj1bXadH/fI6NZqNfBKSrjngfjmK7hSBygBixDR2taMME95nXlf/tMCavMxJN5BFSvlNUTCY7GDlniIRZWkUAvAAPeiq6DpCUNQZ2rly+kxx47TO6P8ILNJA3ckW1WxVrWjFYgCzMmutG4kaq6vA1A19cAaSm4DTTZCgUVpfGuww8wSutQboQKhnz2MPkkuFIrdRzivK8FLAqI/pz5AA+rC0iNVnQ226E+gSnXoy6u5z X-Forefront-PRVS: 0854128AF0 X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1; BN4PR12MB0851; 23:TeIL4QK77hpksOn2gHnoWbwTJF8KSIzDgiXLwydcz?= =?us-ascii?Q?qu+r/t9s//Hc4yKOAxw1/uDYzlbmPSHpir1oB/ulqdLIlKTi5teBufOuxh7v?= =?us-ascii?Q?CJqotRo5bsqNNLkI0gE4cMohA3KSRdkux6y1/o7pGOBUws6OVrWT+RkpVi3n?= =?us-ascii?Q?w9eWlj3jn3fKKI2lCpbzMNRjW4sf4CwIDozKRykb0itn+iNBojk8lqsbjBjg?= =?us-ascii?Q?ziaLIIWaksAfaCIg/RJBjtIaVj2rrV9DktRKz3ZGHSX6f5eekbX7Oqo4eFao?= =?us-ascii?Q?YU9jclw5issfVHkliGs2tSEh7az88H/JvNLBgQMdPKWM4Jfkd3kdXZk/Jwac?= =?us-ascii?Q?iLxZToaWpRaRLH+vHYc5U15LCrSx0pHEjafDBpfoQMFm3e4iAOeklVaI9fRn?= =?us-ascii?Q?wWrVkgvfeeDQIgE5eHgrtFm4IHOCAyDi+xgladYxKSMEhNkfe3YMovuwZXad?= =?us-ascii?Q?68APttXqJB/sjH9ysNhYVchdqC74WMGnZB9p35T26Diak1qaWmWhDP1o6NI5?= =?us-ascii?Q?DHKj86Bqr9ZWpW6niQDoXQ1lqqGZFXQpy46PfkImmuF5MbUVbvWVqk+USF/Y?= =?us-ascii?Q?/arbKREJec6vxc5WS1qmalq657TxSlTdwKWPZuD/Fxy8wK8Ln0ogAJoefZ0M?= =?us-ascii?Q?loTyvF8+UEcozewI9N7I5TsqGy/uS2VIDLSuqX0aCUBeTbelKJZg0WjQRoH2?= =?us-ascii?Q?xH8jw2ehdqOZpbqOWofUZC2PwuyQyL+VboV7DilrN14RSgpYLHbdMZpfphfH?= =?us-ascii?Q?0twAYLRuhxTBqz4jYh46jGTz+MSsJDPOVu1zVFrQKC8DBi2gwfyW/ZJYyG3F?= =?us-ascii?Q?tt+8SCRbXfQ/qR6uIU0FcVN9S82oIwXlTm8tYUGWOGfZ4iVZ26EShdqAkyem?= =?us-ascii?Q?mcBtx/sxJdFYP2gCwf1qZDuSFKsdf9dS9QKV0Hupr8C5Z41TzYqd/GwyNh2J?= =?us-ascii?Q?tG9c5OA615OcRSxSzFTU/uOrxHt38QmkAE4VRWn2am4SOFtCbJHVabD8FmMi?= =?us-ascii?Q?WuHqwOCTdYGJiNCul61JZ3q0sQ7ZOm62OQyecnkJ/G2zXiZSkmcZrsb3tNxG?= =?us-ascii?Q?eunnM1dcp1dBz0nLPOFoz5CyCZ8J1VLisUYeWYr6l/Adaxi5nblbUSh6EyL5?= =?us-ascii?Q?npBHGThjto=3D?= X-Microsoft-Exchange-Diagnostics: 1; BN4PR12MB0851; 5:SxDESUvmdH+xfVKym/04rhlqVLOC3QDCE5tyTABqhnBpX6VR09gZmYn4yGxWbhDYsWAUdHhZs2ucuEha3EGApKcR0UAazARRApyKMH0lHkRi5yVadXGMsNPyPFFqDRwQPHgnmDYwc+L9uUWF3pqOJw==; 24:IlrfbQxYk4ph72Gr6hjI78ekXd+Osqn96Z8SrYEYgBrza/ov1XoNHBZCujBB98ItqED7nCG2PyzKkzbbrPk3WTDohaDREV6BQBZeEhnwsgE=; 20:VZFrfEdiOtXbloTNPBpg5oUV3eVt1nfbDr2n6haqvWcBRzjinmo/C0baVpdrlzepRLZwYMk0AiuawVIhhHsRhAOO07gmkmeDUQwebtHr+XC+S9vlIChQ627LtZoP5kj1Sito3aSRgeFQXU3wO30ocH+skPTXjdeUhZCamch8IO48Vcq0PT+JsrP5MsMRoetXGWelFWFmjbRokm5TmsDV15suEoPRl4w3SObj1F9BuVMhldReEBTZufdbGa94ab80 SpamDiagnosticOutput: 1:23 SpamDiagnosticMetadata: NSPM X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 16 Feb 2016 22:28:19.7097 (UTC) X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=3dd8961f-e488-4e60-8e11-a82d994e183d; Ip=[165.204.84.222]; Helo=[atltwp02.amd.com] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: 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.2 required=5.0 tests=BAD_ENC_HEADER,BAYES_00, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Laying the groundwork for the AMD DAL display driver. This patch includes the basic services and defines basic types required by the display driver, such as: - ASIC register access - VBIOS access - Vector and flat_set data structures - Display signal types - ASIC versions and IDs - HW IDs - Logging functionality This patch adds Kconfig options to enable the DAL display driver. - DRM_AMD_DAL - DRM_AMD_DAL_VBIOS_PRESENT - DRM_AMD_DAL_DCE11_0 - DRM_AMD_DAL_DCE10_0 - DEBUG_KERNEL_DAL Signed-off-by: Harry Wentland Reviewed-by: Alex Deucher --- drivers/gpu/drm/amd/dal/Kconfig | 48 ++ drivers/gpu/drm/amd/dal/Makefile | 21 + drivers/gpu/drm/amd/dal/dc/basics/Makefile | 10 + drivers/gpu/drm/amd/dal/dc/basics/conversion.c | 224 +++++ drivers/gpu/drm/amd/dal/dc/basics/conversion.h | 49 ++ drivers/gpu/drm/amd/dal/dc/basics/grph_object_id.c | 134 +++ drivers/gpu/drm/amd/dal/dc/basics/logger.c | 954 +++++++++++++++++++++ drivers/gpu/drm/amd/dal/dc/basics/logger.h | 64 ++ .../gpu/drm/amd/dal/dc/basics/register_logger.c | 197 +++++ drivers/gpu/drm/amd/dal/dc/basics/signal_types.c | 116 +++ drivers/gpu/drm/amd/dal/dc/basics/vector.c | 309 +++++++ 11 files changed, 2126 insertions(+) create mode 100644 drivers/gpu/drm/amd/dal/Kconfig create mode 100644 drivers/gpu/drm/amd/dal/Makefile create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/Makefile create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/conversion.c create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/conversion.h create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/grph_object_id.c create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/logger.c create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/logger.h create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/register_logger.c create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/signal_types.c create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/vector.c diff --git a/drivers/gpu/drm/amd/dal/Kconfig b/drivers/gpu/drm/amd/dal/Kconfig new file mode 100644 index 000000000000..2289c0b10dae --- /dev/null +++ b/drivers/gpu/drm/amd/dal/Kconfig @@ -0,0 +1,48 @@ +menu "Display Engine Configuration" + depends on DRM && (DRM_AMDSOC || DRM_AMDGPU) + +config DRM_AMD_DAL + bool "AMD DAL - Enable new display engine + help + Choose this option if you want to use the new display engine + support for AMD SOC. + + Will be deprecated when the DAL component becomes stable and + AMDSOC will fully switch to it. + +config DRM_AMD_DAL_VBIOS_PRESENT + bool "Video Bios available on board" + depends on DRM_AMD_DAL + help + This option is needed to allow a full range of feature + support when working on + x86 platforms and there is a VBIOS + present in the system + +config DRM_AMD_DAL_DCE11_0 + bool "Carrizo family" + depends on DRM_AMD_DAL + help + Choose this option + if you want to have + CZ family + for display engine + +config DRM_AMD_DAL_DCE10_0 + bool "VI family" + depends on DRM_AMD_DAL + help + Choose this option + if you want to have + VI family for display + engine. + +config DEBUG_KERNEL_DAL + bool "Enable kgdb break in DAL" + depends on DRM_AMD_DAL + help + Choose this option + if you want to hit + kdgb_break in assert. + +endmenu diff --git a/drivers/gpu/drm/amd/dal/Makefile b/drivers/gpu/drm/amd/dal/Makefile new file mode 100644 index 000000000000..25ae4646c4d3 --- /dev/null +++ b/drivers/gpu/drm/amd/dal/Makefile @@ -0,0 +1,21 @@ +# +# Makefile for the DAL (Display Abstract Layer), which is a sub-component +# of the AMDGPU drm driver. +# It provides the HW control for display related functionalities. + +AMDDALPATH = $(RELATIVE_AMD_DAL_PATH) + +subdir-ccflags-y += -Werror + +subdir-ccflags-y += -I$(AMDDALPATH)/ -I$(AMDDALPATH)/include + +subdir-ccflags-y += -I$(FULL_AMD_DAL_PATH)/dc/inc/ + +#TODO: remove when Timing Sync feature is complete +subdir-ccflags-y += -DBUILD_FEATURE_TIMING_SYNC=0 + +DAL_LIBS = amdgpu_dm dc + +AMD_DAL = $(addsuffix /Makefile, $(addprefix $(FULL_AMD_DAL_PATH)/,$(DAL_LIBS))) + +include $(AMD_DAL) diff --git a/drivers/gpu/drm/amd/dal/dc/basics/Makefile b/drivers/gpu/drm/amd/dal/dc/basics/Makefile new file mode 100644 index 000000000000..6f382812fae3 --- /dev/null +++ b/drivers/gpu/drm/amd/dal/dc/basics/Makefile @@ -0,0 +1,10 @@ +# +# Makefile for the 'utils' sub-component of DAL. +# It provides the general basic services required by other DAL +# subcomponents. + +BASICS = conversion.o grph_object_id.o logger.o register_logger.o signal_types.o vector.o + +AMD_DAL_BASICS = $(addprefix $(AMDDALPATH)/dc/basics/,$(BASICS)) + +AMD_DAL_FILES += $(AMD_DAL_BASICS) diff --git a/drivers/gpu/drm/amd/dal/dc/basics/conversion.c b/drivers/gpu/drm/amd/dal/dc/basics/conversion.c new file mode 100644 index 000000000000..2f1f3d4ff96b --- /dev/null +++ b/drivers/gpu/drm/amd/dal/dc/basics/conversion.c @@ -0,0 +1,224 @@ +/* + * 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" + +#define DIVIDER 10000 + +/* S2D13 value in [-3.00...0.9999] */ +#define S2D13_MIN (-3 * DIVIDER) +#define S2D13_MAX (3 * DIVIDER) + +uint16_t fixed_point_to_int_frac( + struct fixed31_32 arg, + uint8_t integer_bits, + uint8_t fractional_bits) +{ + int32_t numerator; + int32_t divisor = 1 << fractional_bits; + + uint16_t result; + + uint16_t d = (uint16_t)dal_fixed31_32_floor( + dal_fixed31_32_abs( + arg)); + + if (d <= (uint16_t)(1 << integer_bits) - (1 / (uint16_t)divisor)) + numerator = (uint16_t)dal_fixed31_32_floor( + dal_fixed31_32_mul_int( + arg, + divisor)); + else { + numerator = dal_fixed31_32_floor( + dal_fixed31_32_sub( + dal_fixed31_32_from_int( + 1LL << integer_bits), + dal_fixed31_32_recip( + dal_fixed31_32_from_int( + divisor)))); + } + + if (numerator >= 0) + result = (uint16_t)numerator; + else + result = (uint16_t)( + (1 << (integer_bits + fractional_bits + 1)) + numerator); + + if ((result != 0) && dal_fixed31_32_lt( + arg, dal_fixed31_32_zero)) + result |= 1 << (integer_bits + fractional_bits); + + return result; +} +/** +* convert_float_matrix +* This converts a double into HW register spec defined format S2D13. +* @param : +* @return None +*/ +void convert_float_matrix( + uint16_t *matrix, + struct fixed31_32 *flt, + uint32_t buffer_size) +{ + const struct fixed31_32 min_2_13 = + dal_fixed31_32_from_fraction(S2D13_MIN, DIVIDER); + const struct fixed31_32 max_2_13 = + dal_fixed31_32_from_fraction(S2D13_MAX, DIVIDER); + uint32_t i; + + for (i = 0; i < buffer_size; ++i) { + uint32_t reg_value = + fixed_point_to_int_frac( + dal_fixed31_32_clamp( + flt[i], + min_2_13, + max_2_13), + 2, + 13); + + matrix[i] = (uint16_t)reg_value; + } +} + +static void calculate_adjustments_common( + const struct fixed31_32 *ideal_matrix, + const struct dc_csc_adjustments *adjustments, + struct fixed31_32 *matrix) +{ + const struct fixed31_32 sin_hue = + dal_fixed31_32_sin(adjustments->hue); + const struct fixed31_32 cos_hue = + dal_fixed31_32_cos(adjustments->hue); + + const struct fixed31_32 multiplier = + dal_fixed31_32_mul( + adjustments->contrast, + adjustments->saturation); + + matrix[0] = dal_fixed31_32_mul( + ideal_matrix[0], + adjustments->contrast); + + matrix[1] = dal_fixed31_32_mul( + ideal_matrix[1], + adjustments->contrast); + + matrix[2] = dal_fixed31_32_mul( + ideal_matrix[2], + adjustments->contrast); + + matrix[4] = dal_fixed31_32_mul( + multiplier, + dal_fixed31_32_add( + dal_fixed31_32_mul( + ideal_matrix[8], + sin_hue), + dal_fixed31_32_mul( + ideal_matrix[4], + cos_hue))); + + matrix[5] = dal_fixed31_32_mul( + multiplier, + dal_fixed31_32_add( + dal_fixed31_32_mul( + ideal_matrix[9], + sin_hue), + dal_fixed31_32_mul( + ideal_matrix[5], + cos_hue))); + + matrix[6] = dal_fixed31_32_mul( + multiplier, + dal_fixed31_32_add( + dal_fixed31_32_mul( + ideal_matrix[10], + sin_hue), + dal_fixed31_32_mul( + ideal_matrix[6], + cos_hue))); + + matrix[7] = ideal_matrix[7]; + + matrix[8] = dal_fixed31_32_mul( + multiplier, + dal_fixed31_32_sub( + dal_fixed31_32_mul( + ideal_matrix[8], + cos_hue), + dal_fixed31_32_mul( + ideal_matrix[4], + sin_hue))); + + matrix[9] = dal_fixed31_32_mul( + multiplier, + dal_fixed31_32_sub( + dal_fixed31_32_mul( + ideal_matrix[9], + cos_hue), + dal_fixed31_32_mul( + ideal_matrix[5], + sin_hue))); + + matrix[10] = dal_fixed31_32_mul( + multiplier, + dal_fixed31_32_sub( + dal_fixed31_32_mul( + ideal_matrix[10], + cos_hue), + dal_fixed31_32_mul( + ideal_matrix[6], + sin_hue))); + + matrix[11] = ideal_matrix[11]; +} + +void calculate_adjustments( + const struct fixed31_32 *ideal_matrix, + const struct dc_csc_adjustments *adjustments, + struct fixed31_32 *matrix) +{ + calculate_adjustments_common(ideal_matrix, adjustments, matrix); + + matrix[3] = dal_fixed31_32_add( + ideal_matrix[3], + dal_fixed31_32_mul( + adjustments->brightness, + dal_fixed31_32_from_fraction(86, 100))); +} + +void calculate_adjustments_y_only( + const struct fixed31_32 *ideal_matrix, + const struct dc_csc_adjustments *adjustments, + struct fixed31_32 *matrix) +{ + calculate_adjustments_common(ideal_matrix, adjustments, matrix); + + matrix[3] = dal_fixed31_32_add( + ideal_matrix[3], + adjustments->brightness); +} + diff --git a/drivers/gpu/drm/amd/dal/dc/basics/conversion.h b/drivers/gpu/drm/amd/dal/dc/basics/conversion.h new file mode 100644 index 000000000000..24ff47352688 --- /dev/null +++ b/drivers/gpu/drm/amd/dal/dc/basics/conversion.h @@ -0,0 +1,49 @@ +/* + * 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 __DAL_CONVERSION_H__ +#define __DAL_CONVERSION_H__ + +uint16_t fixed_point_to_int_frac( + struct fixed31_32 arg, + uint8_t integer_bits, + uint8_t fractional_bits); + +void convert_float_matrix( + uint16_t *matrix, + struct fixed31_32 *flt, + uint32_t buffer_size); + +void calculate_adjustments( + const struct fixed31_32 *ideal_matrix, + const struct dc_csc_adjustments *adjustments, + struct fixed31_32 *matrix); + +void calculate_adjustments_y_only( + const struct fixed31_32 *ideal_matrix, + const struct dc_csc_adjustments *adjustments, + struct fixed31_32 *matrix); + +#endif diff --git a/drivers/gpu/drm/amd/dal/dc/basics/grph_object_id.c b/drivers/gpu/drm/amd/dal/dc/basics/grph_object_id.c new file mode 100644 index 000000000000..9c80847d03a9 --- /dev/null +++ b/drivers/gpu/drm/amd/dal/dc/basics/grph_object_id.c @@ -0,0 +1,134 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "include/grph_object_id.h" + +bool dal_graphics_object_id_is_valid(struct graphics_object_id id) +{ + bool rc = true; + + switch (id.type) { + case OBJECT_TYPE_UNKNOWN: + rc = false; + break; + case OBJECT_TYPE_GPU: + case OBJECT_TYPE_ENGINE: + /* do NOT check for id.id == 0 */ + if (id.enum_id == ENUM_ID_UNKNOWN) + rc = false; + break; + default: + if (id.id == 0 || id.enum_id == ENUM_ID_UNKNOWN) + rc = false; + break; + } + + return rc; +} + +bool dal_graphics_object_id_is_equal( + struct graphics_object_id id1, + struct graphics_object_id id2) +{ + if (false == dal_graphics_object_id_is_valid(id1)) { + dm_output_to_console( + "%s: Warning: comparing invalid object 'id1'!\n", __func__); + return false; + } + + if (false == dal_graphics_object_id_is_valid(id2)) { + dm_output_to_console( + "%s: Warning: comparing invalid object 'id2'!\n", __func__); + return false; + } + + if (id1.id == id2.id && id1.enum_id == id2.enum_id + && id1.type == id2.type) + return true; + + return false; +} + +/* Based on internal data members memory layout */ +uint32_t dal_graphics_object_id_to_uint(struct graphics_object_id id) +{ + uint32_t object_id = 0; + + object_id = id.id + (id.enum_id << 0x8) + (id.type << 0xc); + return object_id; +} + +/* + * ******* get specific ID - internal safe cast into specific type ******* + */ + +enum controller_id dal_graphics_object_id_get_controller_id( + struct graphics_object_id id) +{ + if (id.type == OBJECT_TYPE_CONTROLLER) + return id.id; + return CONTROLLER_ID_UNDEFINED; +} + +enum clock_source_id dal_graphics_object_id_get_clock_source_id( + struct graphics_object_id id) +{ + if (id.type == OBJECT_TYPE_CLOCK_SOURCE) + return id.id; + return CLOCK_SOURCE_ID_UNDEFINED; +} + +enum encoder_id dal_graphics_object_id_get_encoder_id( + struct graphics_object_id id) +{ + if (id.type == OBJECT_TYPE_ENCODER) + return id.id; + return ENCODER_ID_UNKNOWN; +} + +enum connector_id dal_graphics_object_id_get_connector_id( + struct graphics_object_id id) +{ + if (id.type == OBJECT_TYPE_CONNECTOR) + return id.id; + return CONNECTOR_ID_UNKNOWN; +} + +enum audio_id dal_graphics_object_id_get_audio_id(struct graphics_object_id id) +{ + if (id.type == OBJECT_TYPE_AUDIO) + return id.id; + return AUDIO_ID_UNKNOWN; +} + +enum engine_id dal_graphics_object_id_get_engine_id( + struct graphics_object_id id) +{ + if (id.type == OBJECT_TYPE_ENGINE) + return id.id; + return ENGINE_ID_UNKNOWN; +} + diff --git a/drivers/gpu/drm/amd/dal/dc/basics/logger.c b/drivers/gpu/drm/amd/dal/dc/basics/logger.c new file mode 100644 index 000000000000..e7938ec9bb7c --- /dev/null +++ b/drivers/gpu/drm/amd/dal/dc/basics/logger.c @@ -0,0 +1,954 @@ +/* + * 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 +#include "dm_services.h" +#include "include/dal_types.h" +#include "include/logger_interface.h" +#include "logger.h" + +/* TODO: for now - empty, use DRM defines from dal services. + Need to define appropriate levels of prints, and implement + this component +void dal_log(const char *format, ...) +{ +} +*/ + +/* ----------- Logging Major/Minor names ------------ */ + +#define NUM_ELEMENTS(a) (sizeof(a) / sizeof((a)[0])) + +static const struct log_minor_info component_minor_info_tbl[] = { + {LOG_MINOR_COMPONENT_LINK_SERVICE, "LS"}, + {LOG_MINOR_COMPONENT_DAL_INTERFACE, "DalIf"}, + {LOG_MINOR_COMPONENT_HWSS, "HWSS"}, + {LOG_MINOR_COMPONENT_ADAPTER_SERVICE, "AS"}, + {LOG_MINOR_COMPONENT_DISPLAY_SERVICE, "DS"}, + {LOG_MINOR_COMPONENT_TOPOLOGY_MANAGER, "TM"}, + {LOG_MINOR_COMPONENT_ENCODER, "Encoder"}, + {LOG_MINOR_COMPONENT_I2C_AUX, "I2cAux"}, + {LOG_MINOR_COMPONENT_AUDIO, "Audio"}, + {LOG_MINOR_COMPONENT_DISPLAY_CAPABILITY_SERVICE, "Dcs"}, + {LOG_MINOR_COMPONENT_DMCU, "Dmcu"}, + {LOG_MINOR_COMPONENT_GPU, "GPU"}, + {LOG_MINOR_COMPONENT_CONTROLLER, "Cntrlr"}, + {LOG_MINOR_COMPONENT_ISR, "ISR"}, + {LOG_MINOR_COMPONENT_BIOS, "BIOS"}, + {LOG_MINOR_COMPONENT_DC, "DC"}, + {LOG_MINOR_COMPONENT_IRQ_SERVICE, "IRQ SERVICE"}, + +}; + +static const struct log_minor_info hw_trace_minor_info_tbl[] = { + {LOG_MINOR_HW_TRACE_MST, "Mst" }, + {LOG_MINOR_HW_TRACE_TRAVIS, "Travis" }, + {LOG_MINOR_HW_TRACE_HOTPLUG, "Hotplug" }, + {LOG_MINOR_HW_TRACE_LINK_TRAINING, "LinkTraining" }, + {LOG_MINOR_HW_TRACE_SET_MODE, "SetMode" }, + {LOG_MINOR_HW_TRACE_RESUME_S3, "ResumeS3" }, + {LOG_MINOR_HW_TRACE_RESUME_S4, "ResumeS4" }, + {LOG_MINOR_HW_TRACE_BOOTUP, "BootUp" }, + {LOG_MINOR_HW_TRACE_AUDIO, "Audio"}, + {LOG_MINOR_HW_TRACE_HPD_IRQ, "HpdIrq" }, + {LOG_MINOR_HW_TRACE_INTERRUPT, "Interrupt" }, + {LOG_MINOR_HW_TRACE_MPO, "Planes" }, +}; + +static const struct log_minor_info mst_minor_info_tbl[] = { + {LOG_MINOR_MST_IRQ_HPD_RX, "IrqHpdRx"}, + {LOG_MINOR_MST_IRQ_TIMER, "IrqTimer"}, + {LOG_MINOR_MST_NATIVE_AUX, "NativeAux"}, + {LOG_MINOR_MST_SIDEBAND_MSG, "SB"}, + {LOG_MINOR_MST_MSG_TRANSACTION, "MT"}, + {LOG_MINOR_MST_SIDEBAND_MSG_PARSED, "SB Parsed"}, + {LOG_MINOR_MST_MSG_TRANSACTION_PARSED, "MT Parsed"}, + {LOG_MINOR_MST_AUX_MSG_DPCD_ACCESS, "AuxMsgDpcdAccess"}, + {LOG_MINOR_MST_PROGRAMMING, "Programming"}, + {LOG_MINOR_MST_TOPOLOGY_DISCOVERY, "TopologyDiscovery"}, + {LOG_MINOR_MST_CONVERTER_CAPS, "ConverterCaps"}, +}; + +static const struct log_minor_info dcs_minor_info_tbl[] = { + {LOG_MINOR_DCS_EDID_EMULATOR, "EdidEmul"}, + {LOG_MINOR_DCS_DONGLE_DETECTION, "DongleDetect"}, +}; + +static const struct log_minor_info dcp_minor_info_tbl[] = { + { LOG_MINOR_DCP_GAMMA_GRPH, "GammaGrph"}, + { LOG_MINOR_DCP_GAMMA_OVL, "GammaOvl"}, + { LOG_MINOR_DCP_CSC_GRPH, "CscGrph"}, + { LOG_MINOR_DCP_CSC_OVL, "CscOvl"}, + { LOG_MINOR_DCP_SCALER, "Scaler"}, + { LOG_MINOR_DCP_SCALER_TABLES, "ScalerTables"}, +}; + +static const struct log_minor_info bios_minor_info_tbl[] = { + {LOG_MINOR_BIOS_CMD_TABLE, "CmdTbl"}, +}; + +static const struct log_minor_info reg_minor_info_tbl[] = { + {LOG_MINOR_REGISTER_INDEX, "Index"}, +}; + +static const struct log_minor_info info_packet_minor_info_tbl[] = { + {LOG_MINOR_INFO_PACKETS_HDMI, "Hdmi"}, +}; + + +static const struct log_minor_info dsat_minor_info_tbl[] = { + {LOG_MINOR_DSAT_LOGGER, "Logger"}, + {LOG_MINOR_DSAT_EDID_OVERRIDE, "EDID_Override"}, +}; + +static const struct log_minor_info ec_minor_info_tbl[] = { + {LOG_MINOR_EC_PPLIB_NOTIFY, "PPLib_Notify" }, /* PPLib notifies DAL */ + {LOG_MINOR_EC_PPLIB_QUERY, "PPLib_Query" } /* DAL requested info from + PPLib */ +}; + +static const struct log_minor_info bwm_minor_info_tbl[] = { + {LOG_MINOR_BWM_MODE_VALIDATION, "ModeValidation"}, + {LOG_MINOR_BWM_REQUIRED_BANDWIDTH_CALCS, "Req_Bandw_Calcs"} +}; + +static const struct log_minor_info mode_enum_minor_info_tbl[] = { + {LOG_MINOR_MODE_ENUM_BEST_VIEW_CANDIDATES, "BestviewCandidates"}, + {LOG_MINOR_MODE_ENUM_VIEW_SOLUTION, "ViewSolution"}, + {LOG_MINOR_MODE_ENUM_TS_LIST_BUILD, "TsListBuild"}, + {LOG_MINOR_MODE_ENUM_TS_LIST, "TsList"}, + {LOG_MINOR_MODE_ENUM_MASTER_VIEW_LIST, "MasterViewList"}, + {LOG_MINOR_MODE_ENUM_MASTER_VIEW_LIST_UPDATE, "MasterViewListUpdate"}, +}; + +static const struct log_minor_info i2caux_minor_info_tbl[] = { + {LOG_MINOR_I2C_AUX_LOG, "Log"}, + {LOG_MINOR_I2C_AUX_AUX_TIMESTAMP, "Timestamp"}, + {LOG_MINOR_I2C_AUX_CFG, "Config"} +}; + +static const struct log_minor_info line_buffer_minor_info_tbl[] = { + {LOG_MINOR_LINE_BUFFER_POWERGATING, "PowerGating"} +}; + +static const struct log_minor_info hwss_minor_info_tbl[] = { + {LOG_MINOR_HWSS_TAPS_VALIDATION, "HWSS Taps"} +}; + +static const struct log_minor_info optimization_minor_info_tbl[] = { + {LOG_MINOR_OPTMZ_GENERAL, "General Optimizations"}, + {LOG_MINOR_OPTMZ_DO_NOT_TURN_OFF_VCC_DURING_SET_MODE, + "Skip Vcc Off During Set Mode"} +}; + +static const struct log_minor_info perf_measure_minor_info_tbl[] = { + {LOG_MINOR_PERF_MEASURE_GENERAL, "General Performance Measurement"}, + {LOG_MINOR_PERF_MEASURE_HEAP_MEMORY, "Heap Memory Management"} +}; + +static const struct log_minor_info sync_minor_info_tbl[] = { + {LOG_MINOR_SYNC_HW_CLOCK_ADJUST, "Pixel Rate Tune-up"}, + {LOG_MINOR_SYNC_TIMING, "Timing"} +}; + +static const struct log_minor_info backlight_minor_info_tbl[] = { + {LOG_MINOR_BACKLIGHT_BRIGHTESS_CAPS, "Caps"}, + {LOG_MINOR_BACKLIGHT_DMCU_DELTALUT, "DMCU Delta LUT"}, + {LOG_MINOR_BACKLIGHT_DMCU_BUILD_DELTALUT, "Build DMCU Delta LUT"}, + {LOG_MINOR_BACKLIGHT_INTERFACE, "Interface"}, + {LOG_MINOR_BACKLIGHT_LID, "Lid Status"} +}; + + +static const struct log_minor_info override_feature_minor_info_tbl[] = { + {LOG_MINOR_FEATURE_OVERRIDE, "overriden feature"}, +}; + +static const struct log_minor_info detection_minor_info_tbl[] = { + {LOG_MINOR_DETECTION_EDID_PARSER, "EDID Parser"}, + {LOG_MINOR_DETECTION_DP_CAPS, "DP caps"}, +}; + +static const struct log_minor_info tm_minor_info_tbl[] = { + {LOG_MINOR_TM_INFO, "INFO"}, + {LOG_MINOR_TM_IFACE_TRACE, "IFACE_TRACE"}, + {LOG_MINOR_TM_RESOURCES, "RESOURCES"}, + {LOG_MINOR_TM_ENCODER_CTL, "ENCODER_CTL"}, + {LOG_MINOR_TM_ENG_ASN, "ENG_ASN"}, + {LOG_MINOR_TM_CONTROLLER_ASN, "CONTROLLER_ASN"}, + {LOG_MINOR_TM_PWR_GATING, "PWR_GATING"}, + {LOG_MINOR_TM_BUILD_DSP_PATH, "BUILD_PATH"}, + {LOG_MINOR_TM_DISPLAY_DETECT, "DISPLAY_DETECT"}, + {LOG_MINOR_TM_LINK_SRV, "LINK_SRV"}, + {LOG_MINOR_TM_NOT_IMPLEMENTED, "NOT_IMPL"}, + {LOG_MINOR_TM_COFUNC_PATH, "COFUNC_PATH"} +}; + +static const struct log_minor_info ds_minor_info_tbl[] = { + {LOG_MINOR_DS_MODE_SETTING, "Mode_Setting"}, +}; + + +struct log_major_mask_info { + struct log_major_info major_info; + uint32_t default_mask; + const struct log_minor_info *minor_tbl; + uint32_t tbl_element_cnt; +}; + +/* A mask for each Major. + * Use a mask or zero. */ +#define LG_ERR_MSK 0xffffffff +#define LG_WRN_MSK 0xffffffff +#define LG_TM_MSK (1 << LOG_MINOR_TM_INFO) +#define LG_FO_MSK (1 << LOG_MINOR_FEATURE_OVERRIDE) +#define LG_EC_MSK ((1 << LOG_MINOR_EC_PPLIB_NOTIFY) | \ + (1 << LOG_MINOR_EC_PPLIB_QUERY)) +#define LG_DSAT_MSK (1 << LOG_MINOR_DSAT_EDID_OVERRIDE) +#define LG_DT_MSK (1 << LOG_MINOR_DETECTION_EDID_PARSER) + +/* IFT - InterFaceTrace */ +#define LG_IFT_MSK (1 << LOG_MINOR_COMPONENT_DC) + + +#define LG_HW_TR_AUD_MSK (1 << LOG_MINOR_HW_TRACE_AUDIO) +#define LG_HW_TR_INTERRUPT_MSK (1 << LOG_MINOR_HW_TRACE_INTERRUPT) | \ + (1 << LOG_MINOR_HW_TRACE_HPD_IRQ) +#define LG_HW_TR_PLANES_MSK (1 << LOG_MINOR_HW_TRACE_MPO) +#define LG_ALL_MSK 0xffffffff +#define LG_DCP_MSK ~(1 << LOG_MINOR_DCP_SCALER) + +#define LG_SYNC_MSK (1 << LOG_MINOR_SYNC_TIMING) + +#define LG_BWM_MSK (1 << LOG_MINOR_BWM_MODE_VALIDATION) + +static const struct log_major_mask_info log_major_mask_info_tbl[] = { + /* LogMajor major name default MinorTble tblElementCnt */ + {{LOG_MAJOR_ERROR, "Error" }, LG_ALL_MSK, component_minor_info_tbl, NUM_ELEMENTS(component_minor_info_tbl)}, + {{LOG_MAJOR_WARNING, "Warning" }, LG_ALL_MSK, component_minor_info_tbl, NUM_ELEMENTS(component_minor_info_tbl)}, + {{LOG_MAJOR_INTERFACE_TRACE, "IfTrace" }, LG_ALL_MSK, component_minor_info_tbl, NUM_ELEMENTS(component_minor_info_tbl)}, + {{LOG_MAJOR_HW_TRACE, "HwTrace" }, (LG_ALL_MSK & + ~((1 << LOG_MINOR_HW_TRACE_LINK_TRAINING) | + (1 << LOG_MINOR_HW_TRACE_AUDIO))), + hw_trace_minor_info_tbl, NUM_ELEMENTS(hw_trace_minor_info_tbl)}, + {{LOG_MAJOR_MST, "MST" }, LG_ALL_MSK, mst_minor_info_tbl, NUM_ELEMENTS(mst_minor_info_tbl)}, + {{LOG_MAJOR_DCS, "DCS" }, LG_ALL_MSK, dcs_minor_info_tbl, NUM_ELEMENTS(dcs_minor_info_tbl)}, + {{LOG_MAJOR_DCP, "DCP" }, LG_DCP_MSK, dcp_minor_info_tbl, NUM_ELEMENTS(dcp_minor_info_tbl)}, + {{LOG_MAJOR_BIOS, "Bios" }, LG_ALL_MSK, bios_minor_info_tbl, NUM_ELEMENTS(bios_minor_info_tbl)}, + {{LOG_MAJOR_REGISTER, "Register" }, LG_ALL_MSK, reg_minor_info_tbl, NUM_ELEMENTS(reg_minor_info_tbl)}, + {{LOG_MAJOR_INFO_PACKETS, "InfoPacket" }, LG_ALL_MSK, info_packet_minor_info_tbl, NUM_ELEMENTS(info_packet_minor_info_tbl)}, + {{LOG_MAJOR_DSAT, "DSAT" }, LG_ALL_MSK, dsat_minor_info_tbl, NUM_ELEMENTS(dsat_minor_info_tbl)}, + {{LOG_MAJOR_EC, "EC" }, LG_ALL_MSK, ec_minor_info_tbl, NUM_ELEMENTS(ec_minor_info_tbl)}, + {{LOG_MAJOR_BWM, "BWM" }, LG_BWM_MSK, bwm_minor_info_tbl, NUM_ELEMENTS(bwm_minor_info_tbl)}, + {{LOG_MAJOR_MODE_ENUM, "ModeEnum" }, LG_ALL_MSK, mode_enum_minor_info_tbl, NUM_ELEMENTS(mode_enum_minor_info_tbl)}, + {{LOG_MAJOR_I2C_AUX, "I2cAux" }, LG_ALL_MSK, i2caux_minor_info_tbl, NUM_ELEMENTS(i2caux_minor_info_tbl)}, + {{LOG_MAJOR_LINE_BUFFER, "LineBuffer" }, LG_ALL_MSK, line_buffer_minor_info_tbl, NUM_ELEMENTS(line_buffer_minor_info_tbl)}, + {{LOG_MAJOR_HWSS, "HWSS" }, LG_ALL_MSK, hwss_minor_info_tbl, NUM_ELEMENTS(hwss_minor_info_tbl)}, + {{LOG_MAJOR_OPTIMIZATION, "Optimization"}, LG_ALL_MSK, optimization_minor_info_tbl, NUM_ELEMENTS(optimization_minor_info_tbl)}, + {{LOG_MAJOR_PERF_MEASURE, "PerfMeasure" }, LG_ALL_MSK, perf_measure_minor_info_tbl, NUM_ELEMENTS(perf_measure_minor_info_tbl)}, + {{LOG_MAJOR_SYNC, "Sync" }, LG_SYNC_MSK,sync_minor_info_tbl, NUM_ELEMENTS(sync_minor_info_tbl)}, + {{LOG_MAJOR_BACKLIGHT, "Backlight" }, LG_ALL_MSK, backlight_minor_info_tbl, NUM_ELEMENTS(backlight_minor_info_tbl)}, + {{LOG_MAJOR_INTERRUPTS, "Interrupts" }, LG_ALL_MSK, component_minor_info_tbl, NUM_ELEMENTS(component_minor_info_tbl)}, + {{LOG_MAJOR_TM, "TM" }, 0, tm_minor_info_tbl, NUM_ELEMENTS(tm_minor_info_tbl)}, + {{LOG_MAJOR_DISPLAY_SERVICE, "DS" }, LG_ALL_MSK, ds_minor_info_tbl, NUM_ELEMENTS(ds_minor_info_tbl)}, + {{LOG_MAJOR_FEATURE_OVERRIDE, "FeatureOverride" }, LG_ALL_MSK, override_feature_minor_info_tbl, NUM_ELEMENTS(override_feature_minor_info_tbl)}, + {{LOG_MAJOR_DETECTION, "Detection" }, LG_ALL_MSK, detection_minor_info_tbl, NUM_ELEMENTS(detection_minor_info_tbl)}, +}; + +/* ----------- Object init and destruction ----------- */ +static bool construct(struct dc_context *ctx, struct dal_logger *logger) +{ + uint32_t i; + /* malloc buffer and init offsets */ + + logger->log_buffer_size = DAL_LOGGER_BUFFER_MAX_SIZE; + logger->log_buffer = (char *)dm_alloc(ctx, + logger->log_buffer_size * + sizeof(char)); + + if (!logger->log_buffer) + return false; + + /* todo: Fill buffer with \0 if not done by dal_alloc */ + + /* Initialize both offsets to start of buffer (empty) */ + logger->buffer_read_offset = 0; + logger->buffer_write_offset = 0; + + logger->write_wrap_count = 0; + logger->read_wrap_count = 0; + logger->open_count = 0; + + logger->flags.bits.ENABLE_CONSOLE = 1; + logger->flags.bits.ENABLE_BUFFER = 0; + + logger->ctx = ctx; + + /* malloc and init minor mask array */ + logger->log_enable_mask_minors = + (uint32_t *)dm_alloc( + ctx, + NUM_ELEMENTS(log_major_mask_info_tbl) + * sizeof(uint32_t)); + if (!logger->log_enable_mask_minors) + return false; + + + /* Set default values for mask */ + for (i = 0; i < NUM_ELEMENTS(log_major_mask_info_tbl); i++) { + + uint32_t dflt_mask = log_major_mask_info_tbl[i].default_mask; + + logger->log_enable_mask_minors[i] = dflt_mask; + } + + return true; +} + +static void destruct(struct dal_logger *logger) +{ + if (logger->log_buffer) { + dm_free(logger->ctx, logger->log_buffer); + logger->log_buffer = NULL; + } + + if (logger->log_enable_mask_minors) { + dm_free(logger->ctx, logger->log_enable_mask_minors); + logger->log_enable_mask_minors = NULL; + } +} + +struct dal_logger *dal_logger_create(struct dc_context *ctx) +{ + /* malloc struct */ + struct dal_logger *logger = dm_alloc(ctx, sizeof(struct dal_logger)); + + if (!logger) + return NULL; + if (!construct(ctx, logger)) { + dm_free(ctx, logger); + return NULL; + } + + return logger; +} + +uint32_t dal_logger_destroy(struct dal_logger **logger) +{ + if (logger == NULL || *logger == NULL) + return 1; + destruct(*logger); + dm_free((*logger)->ctx, *logger); + *logger = NULL; + + return 0; +} + +/* ------------------------------------------------------------------------ */ + +static void lock(struct dal_logger *logger) +{ + /* Todo: lock mutex? */ +} + +static void unlock(struct dal_logger *logger) +{ + /* Todo: unlock mutex */ +} + +bool dal_logger_should_log( + struct dal_logger *logger, + enum log_major major, + enum log_minor minor) +{ + if (major < LOG_MAJOR_COUNT) { + + uint32_t minor_mask = logger->log_enable_mask_minors[major]; + + if ((minor_mask & (1 << minor)) != 0) + return true; + } + + return false; +} + +static void log_to_debug_console(struct log_entry *entry) +{ + struct dal_logger *logger = entry->logger; + + if (logger->flags.bits.ENABLE_CONSOLE == 0) + return; + + if (entry->buf_offset) { + switch (entry->major) { + case LOG_MAJOR_ERROR: + dm_error("%s", entry->buf); + break; + default: + dm_output_to_console("%s", entry->buf); + break; + } + } +} + +/* Print everything unread existing in log_buffer to debug console*/ +static void flush_to_debug_console(struct dal_logger *logger) +{ + int i = logger->buffer_read_offset; + char *string_start = &logger->log_buffer[i]; + + dm_output_to_console( + "---------------- FLUSHING LOG BUFFER ----------------\n"); + while (i < logger->buffer_write_offset) { + + if (logger->log_buffer[i] == '\0') { + dm_output_to_console("%s", string_start); + string_start = (char *)logger->log_buffer + i + 1; + } + i++; + } + dm_output_to_console( + "-------------- END FLUSHING LOG BUFFER --------------\n\n"); +} + +static void log_to_internal_buffer(struct log_entry *entry) +{ + + uint32_t size = entry->buf_offset; + struct dal_logger *logger = entry->logger; + + if (logger->flags.bits.ENABLE_BUFFER == 0) + return; + + if (logger->log_buffer == NULL) + return; + + if (size > 0 && size < logger->log_buffer_size) { + + int total_free_space = 0; + int space_before_wrap = 0; + + if (logger->buffer_write_offset > logger->buffer_read_offset) { + total_free_space = logger->log_buffer_size - + logger->buffer_write_offset + + logger->buffer_read_offset; + space_before_wrap = logger->log_buffer_size - + logger->buffer_write_offset; + } else if (logger->buffer_write_offset < + logger->buffer_read_offset) { + total_free_space = logger->log_buffer_size - + logger->buffer_read_offset + + logger->buffer_write_offset; + space_before_wrap = total_free_space; + } else if (logger->write_wrap_count != + logger->read_wrap_count) { + /* Buffer is completely full already */ + total_free_space = 0; + space_before_wrap = 0; + } else { + /* Buffer is empty, start writing at beginning */ + total_free_space = logger->log_buffer_size; + space_before_wrap = logger->log_buffer_size; + logger->buffer_write_offset = 0; + logger->buffer_read_offset = 0; + } + + + + + if (space_before_wrap > size) { + /* No wrap around, copy 'size' bytes + * from 'entry->buf' to 'log_buffer' + */ + dm_memmove(logger->log_buffer + + logger->buffer_write_offset, + entry->buf, size); + logger->buffer_write_offset += size; + + } else if (total_free_space > size) { + /* We have enough room without flushing, + * but need to wrap around */ + + int space_after_wrap = total_free_space - + space_before_wrap; + + dm_memmove(logger->log_buffer + + logger->buffer_write_offset, + entry->buf, space_before_wrap); + dm_memmove(logger->log_buffer, entry->buf + + space_before_wrap, space_after_wrap); + + logger->buffer_write_offset = space_after_wrap; + logger->write_wrap_count++; + + } else { + /* Not enough room remaining, we should flush + * existing logs */ + + /* Flush existing unread logs to console */ + flush_to_debug_console(logger); + + /* Start writing to beginning of buffer */ + dm_memmove(logger->log_buffer, entry->buf, size); + logger->buffer_write_offset = size; + logger->buffer_read_offset = 0; + } + + } + + unlock(logger); +} + + +static void log_timestamp(struct log_entry *entry) +{ + dal_logger_append(entry, "00:00:00 "); +} + +static void log_major_minor(struct log_entry *entry) +{ + uint32_t i; + enum log_major major = entry->major; + enum log_minor minor = entry->minor; + + for (i = 0; i < NUM_ELEMENTS(log_major_mask_info_tbl); i++) { + + const struct log_major_mask_info *maj_mask_info = + &log_major_mask_info_tbl[i]; + + if (maj_mask_info->major_info.major == major) { + + dal_logger_append(entry, "[%s_", + maj_mask_info->major_info.major_name); + + if (maj_mask_info->minor_tbl != NULL) { + uint32_t j; + + for (j = 0; j < maj_mask_info->tbl_element_cnt; j++) { + + const struct log_minor_info *min_info = &maj_mask_info->minor_tbl[j]; + + if (min_info->minor == minor) + dal_logger_append(entry, "%s]\t", min_info->minor_name); + } + } + + break; + } + } +} + +static void log_heading(struct log_entry *entry, + enum log_major major, + enum log_minor minor) +{ + log_timestamp(entry); + log_major_minor(entry); +} + + +static void append_entry( + struct log_entry *entry, + char *buffer, + uint32_t buf_size) +{ + if (!entry->buf || + entry->buf_offset + buf_size > entry->max_buf_bytes + ) { + BREAK_TO_DEBUGGER(); + return; + } + + /* Todo: check if off by 1 byte due to \0 anywhere */ + dm_memmove(entry->buf + entry->buf_offset, buffer, buf_size); + entry->buf_offset += buf_size; +} + +/* ------------------------------------------------------------------------ */ + +/* Warning: Be careful that 'msg' is null terminated and the total size is + * less than DAL_LOGGER_BUFFER_MAX_LOG_LINE_SIZE (256) including '\0' + */ +void dal_logger_write( + struct dal_logger *logger, + enum log_major major, + enum log_minor minor, + const char *msg, + ...) +{ + + if (logger && dal_logger_should_log(logger, major, minor)) { + + uint32_t size; + va_list args; + char buffer[DAL_LOGGER_BUFFER_MAX_LOG_LINE_SIZE]; + struct log_entry entry; + + va_start(args, msg); + dal_logger_open(logger, &entry, major, minor); + + + size = dm_log_to_buffer( + buffer, DAL_LOGGER_BUFFER_MAX_LOG_LINE_SIZE, msg, args); + + if (size > 0 && size < + DAL_LOGGER_BUFFER_MAX_LOG_LINE_SIZE - 1) { + + if (buffer[size] == '\0') + size++; /* Add one for null terminator */ + + /* Concatenate onto end of entry buffer */ + append_entry(&entry, buffer, size); + } else { + append_entry(&entry, + "LOG_ERROR, line too long or null\n", 35); + } + + dal_logger_close(&entry); + va_end(args); + + } +} + + +/* Same as dal_logger_write, except without open() and close(), which must + * be done separately. + */ +void dal_logger_append( + struct log_entry *entry, + const char *msg, + ...) +{ + struct dal_logger *logger; + + if (!entry) { + BREAK_TO_DEBUGGER(); + return; + } + + logger = entry->logger; + + if (logger && logger->open_count > 0 && + dal_logger_should_log(logger, entry->major, entry->minor)) { + + uint32_t size; + va_list args; + char buffer[DAL_LOGGER_BUFFER_MAX_LOG_LINE_SIZE]; + + va_start(args, msg); + + size = dm_log_to_buffer( + buffer, DAL_LOGGER_BUFFER_MAX_LOG_LINE_SIZE, msg, args); + + if (size < DAL_LOGGER_BUFFER_MAX_LOG_LINE_SIZE - 1) { + append_entry(entry, buffer, size); + } else { + append_entry(entry, "LOG_ERROR, line too long\n", 27); + } + + va_end(args); + } +} + + +uint32_t dal_logger_read( + struct dal_logger *logger, /* <[in] */ + uint32_t output_buffer_size, /* <[in] */ + char *output_buffer, /* >[out] */ + uint32_t *bytes_read, /* >[out] */ + bool single_line) +{ + uint32_t bytes_remaining = 0; + uint32_t bytes_read_count = 0; + bool keep_reading = true; + + if (!logger || output_buffer == NULL || output_buffer_size == 0) { + BREAK_TO_DEBUGGER(); + *bytes_read = 0; + return 0; + } + + lock(logger); + + /* Read until null terminator (if single_line==true, + * max buffer size, or until we've read everything new + */ + + do { + char cur; + + /* Stop when we've read everything */ + if (logger->buffer_read_offset == + logger->buffer_write_offset) { + + break; + } + + cur = logger->log_buffer[logger->buffer_read_offset]; + logger->buffer_read_offset++; + + /* Wrap read pointer if at end */ + if (logger->buffer_read_offset == logger->log_buffer_size) { + + logger->buffer_read_offset = 0; + logger->read_wrap_count++; + } + + /* Don't send null terminators to buffer */ + if (cur != '\0') { + output_buffer[bytes_read_count] = cur; + bytes_read_count++; + } else if (single_line) { + keep_reading = false; + } + + } while (bytes_read_count <= output_buffer_size && keep_reading); + + /* We assume that reading can never be ahead of writing */ + if (logger->write_wrap_count > logger->read_wrap_count) { + bytes_remaining = logger->log_buffer_size - + logger->buffer_read_offset + + logger->buffer_write_offset; + } else { + bytes_remaining = logger->buffer_write_offset - + logger->buffer_read_offset; + } + + /* reset write/read wrap count to 0 if we've read everything */ + if (bytes_remaining == 0) { + + logger->write_wrap_count = 0; + logger->read_wrap_count = 0; + } + + *bytes_read = bytes_read_count; + unlock(logger); + + return bytes_remaining; +} + +void dal_logger_open( + struct dal_logger *logger, + struct log_entry *entry, /* out */ + enum log_major major, + enum log_minor minor) +{ + if (!entry) { + BREAK_TO_DEBUGGER(); + return; + } + + entry->major = LOG_MAJOR_COUNT; + entry->minor = 0; + entry->logger = logger; + + entry->buf = dm_alloc( + logger->ctx, + DAL_LOGGER_BUFFER_MAX_SIZE * sizeof(char)); + + entry->buf_offset = 0; + entry->max_buf_bytes = DAL_LOGGER_BUFFER_MAX_SIZE * sizeof(char); + + logger->open_count++; + entry->major = major; + entry->minor = minor; + + log_heading(entry, major, minor); +} + +void dal_logger_close(struct log_entry *entry) +{ + struct dal_logger *logger = entry->logger; + + + if (logger && logger->open_count > 0) { + logger->open_count--; + } else { + BREAK_TO_DEBUGGER(); + goto cleanup; + } + + /* --Flush log_entry buffer-- */ + /* print to kernel console */ + log_to_debug_console(entry); + /* log internally for dsat */ + log_to_internal_buffer(entry); + + /* TODO: Write end heading */ + +cleanup: + if (entry->buf) { + dm_free(entry->logger->ctx, entry->buf); + entry->buf = NULL; + entry->buf_offset = 0; + entry->max_buf_bytes = 0; + } +} + +uint32_t dal_logger_get_mask( + struct dal_logger *logger, + enum log_major lvl_major, enum log_minor lvl_minor) +{ + uint32_t log_mask = 0; + + if (logger && lvl_major < LOG_MAJOR_COUNT) + log_mask = logger->log_enable_mask_minors[lvl_major]; + + log_mask &= 1 << lvl_minor; + return log_mask; +} + +uint32_t dal_logger_set_mask( + struct dal_logger *logger, + enum log_major lvl_major, enum log_minor lvl_minor) +{ + + if (logger && lvl_major < LOG_MAJOR_COUNT) { + if (lvl_minor == LOG_MINOR_MASK_ALL) { + logger->log_enable_mask_minors[lvl_major] = 0xFFFFFFFF; + } else { + logger->log_enable_mask_minors[lvl_major] |= + (1 << lvl_minor); + } + return 0; + } + return 1; +} + +uint32_t dal_logger_get_masks( + struct dal_logger *logger, + enum log_major lvl_major) +{ + uint32_t log_mask = 0; + + if (logger && lvl_major < LOG_MAJOR_COUNT) + log_mask = logger->log_enable_mask_minors[lvl_major]; + + return log_mask; +} + +void dal_logger_set_masks( + struct dal_logger *logger, + enum log_major lvl_major, uint32_t log_mask) +{ + if (logger && lvl_major < LOG_MAJOR_COUNT) + logger->log_enable_mask_minors[lvl_major] = log_mask; +} + +uint32_t dal_logger_unset_mask( + struct dal_logger *logger, + enum log_major lvl_major, enum log_minor lvl_minor) +{ + + if (lvl_major < LOG_MAJOR_COUNT) { + if (lvl_minor == LOG_MINOR_MASK_ALL) { + logger->log_enable_mask_minors[lvl_major] = 0; + } else { + logger->log_enable_mask_minors[lvl_major] &= + ~(1 << lvl_minor); + } + return 0; + } + return 1; +} + +uint32_t dal_logger_get_flags( + struct dal_logger *logger) +{ + + return logger->flags.value; +} + +void dal_logger_set_flags( + struct dal_logger *logger, + union logger_flags flags) +{ + + logger->flags = flags; +} + + +uint32_t dal_logger_get_buffer_size(struct dal_logger *logger) +{ + return DAL_LOGGER_BUFFER_MAX_SIZE; +} + +uint32_t dal_logger_set_buffer_size( + struct dal_logger *logger, + uint32_t new_size) +{ + /* ToDo: implement dynamic size */ + + /* return new size */ + return DAL_LOGGER_BUFFER_MAX_SIZE; +} + + +const struct log_major_info *dal_logger_enum_log_major_info( + struct dal_logger *logger, + unsigned int enum_index) +{ + const struct log_major_info *major_info; + + if (enum_index >= NUM_ELEMENTS(log_major_mask_info_tbl)) + return NULL; + + major_info = &log_major_mask_info_tbl[enum_index].major_info; + return major_info; +} + +const struct log_minor_info *dal_logger_enum_log_minor_info( + struct dal_logger *logger, + enum log_major major, + unsigned int enum_index) +{ + const struct log_minor_info *minor_info = NULL; + uint32_t i; + + for (i = 0; i < NUM_ELEMENTS(log_major_mask_info_tbl); i++) { + + const struct log_major_mask_info *maj_mask_info = + &log_major_mask_info_tbl[i]; + + if (maj_mask_info->major_info.major == major) { + + if (maj_mask_info->minor_tbl != NULL) { + uint32_t j; + + for (j = 0; j < maj_mask_info->tbl_element_cnt; j++) { + + minor_info = &maj_mask_info->minor_tbl[j]; + + if (minor_info->minor == enum_index) + return minor_info; + } + } + + break; + } + } + return NULL; + +} + diff --git a/drivers/gpu/drm/amd/dal/dc/basics/logger.h b/drivers/gpu/drm/amd/dal/dc/basics/logger.h new file mode 100644 index 000000000000..fba5ec3264b6 --- /dev/null +++ b/drivers/gpu/drm/amd/dal/dc/basics/logger.h @@ -0,0 +1,64 @@ +/* + * 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 __DAL_LOGGER_H__ +#define __DAL_LOGGER_H__ + +/* Structure for keeping track of offsets, buffer, etc */ + +#define DAL_LOGGER_BUFFER_MAX_SIZE 2048 +#define DAL_LOGGER_BUFFER_MAX_LOG_LINE_SIZE 256 + + +#include "include/logger_types.h" + +struct dal_logger { + + /* How far into the circular buffer has been read by dsat + * Read offset should never cross write offset. Write \0's to + * read data just to be sure? + */ + uint32_t buffer_read_offset; + + /* How far into the circular buffer we have written + * Write offset should never cross read offset + */ + uint32_t buffer_write_offset; + + uint32_t write_wrap_count; + uint32_t read_wrap_count; + + uint32_t open_count; + + char *log_buffer; /* Pointer to malloc'ed buffer */ + uint32_t log_buffer_size; /* Size of circular buffer */ + + uint32_t *log_enable_mask_minors; /*array of masks for major elements*/ + + union logger_flags flags; + struct dc_context *ctx; +}; + +#endif /* __DAL_LOGGER_H__ */ diff --git a/drivers/gpu/drm/amd/dal/dc/basics/register_logger.c b/drivers/gpu/drm/amd/dal/dc/basics/register_logger.c new file mode 100644 index 000000000000..6d32b1bdf35c --- /dev/null +++ b/drivers/gpu/drm/amd/dal/dc/basics/register_logger.c @@ -0,0 +1,197 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "include/dal_types.h" +#include "include/logger_interface.h" +#include "logger.h" + +/****************************************************************************** + * Register Logger. + * A facility to create register R/W logs. + * Currently used for DAL Test. + *****************************************************************************/ + +/****************************************************************************** + * Private structures + *****************************************************************************/ +struct dal_reg_dump_stack_location { + const char *current_caller_func; + long current_pid; + long current_tgid; + uint32_t rw_count;/* register access counter for current function. */ +}; + +/* This the maximum number of nested calls to the 'reg_dump' facility. */ +#define DAL_REG_DUMP_STACK_MAX_SIZE 32 + +struct dal_reg_dump_stack { + int32_t stack_pointer; + struct dal_reg_dump_stack_location + stack_locations[DAL_REG_DUMP_STACK_MAX_SIZE]; + uint32_t total_rw_count; /* Total count for *all* functions. */ +}; + +static struct dal_reg_dump_stack reg_dump_stack = {0}; + +/****************************************************************************** + * Private functions + *****************************************************************************/ + +/* Check if current process is the one which requested register dump. + * The reason for the check: + * mmCRTC_STATUS_FRAME_COUNT is accessed by dal_controller_get_vblank_counter(). + * Which runs all the time when at least one display is connected. + * (Triggered by drm_mode_page_flip_ioctl()). */ +static bool is_reg_dump_process(void) +{ + uint32_t i; + + /* walk the list of our processes */ + for (i = 0; i < reg_dump_stack.stack_pointer; i++) { + struct dal_reg_dump_stack_location *stack_location + = ®_dump_stack.stack_locations[i]; + + if (stack_location->current_pid == dm_get_pid() + && stack_location->current_tgid == dm_get_tgid()) + return true; + } + + return false; +} + +static bool dal_reg_dump_stack_is_empty(void) +{ + if (reg_dump_stack.stack_pointer <= 0) + return true; + else + return false; +} + +static struct dal_reg_dump_stack_location *dal_reg_dump_stack_push(void) +{ + struct dal_reg_dump_stack_location *current_location = NULL; + + if (reg_dump_stack.stack_pointer >= DAL_REG_DUMP_STACK_MAX_SIZE) { + /* stack is full */ + dm_output_to_console("[REG_DUMP]: %s: stack is full!\n", + __func__); + } else { + current_location = + ®_dump_stack.stack_locations[reg_dump_stack.stack_pointer]; + ++reg_dump_stack.stack_pointer; + } + + return current_location; +} + +static struct dal_reg_dump_stack_location *dal_reg_dump_stack_pop(void) +{ + struct dal_reg_dump_stack_location *current_location = NULL; + + if (dal_reg_dump_stack_is_empty()) { + /* stack is empty */ + dm_output_to_console("[REG_DUMP]: %s: stack is empty!\n", + __func__); + } else { + --reg_dump_stack.stack_pointer; + current_location = + ®_dump_stack.stack_locations[reg_dump_stack.stack_pointer]; + } + + return current_location; +} + +/****************************************************************************** + * Public functions + *****************************************************************************/ + +void dal_reg_logger_push(const char *caller_func) +{ + struct dal_reg_dump_stack_location *free_stack_location; + + free_stack_location = dal_reg_dump_stack_push(); + + if (NULL == free_stack_location) + return; + + dm_memset(free_stack_location, 0, sizeof(*free_stack_location)); + + free_stack_location->current_caller_func = caller_func; + free_stack_location->current_pid = dm_get_pid(); + free_stack_location->current_tgid = dm_get_tgid(); + + dm_output_to_console("[REG_DUMP]:%s - start (pid:%ld, tgid:%ld)\n", + caller_func, + free_stack_location->current_pid, + free_stack_location->current_tgid); +} + +void dal_reg_logger_pop(void) +{ + struct dal_reg_dump_stack_location *top_stack_location; + + top_stack_location = dal_reg_dump_stack_pop(); + + if (NULL == top_stack_location) { + dm_output_to_console("[REG_DUMP]:%s - Stack is Empty!\n", + __func__); + return; + } + + dm_output_to_console( + "[REG_DUMP]:%s - end."\ + " Reg R/W Count: Total=%d Function=%d. (pid:%ld, tgid:%ld)\n", + top_stack_location->current_caller_func, + reg_dump_stack.total_rw_count, + top_stack_location->rw_count, + dm_get_pid(), + dm_get_tgid()); + + dm_memset(top_stack_location, 0, sizeof(*top_stack_location)); +} + +void dal_reg_logger_rw_count_increment(void) +{ + ++reg_dump_stack.total_rw_count; + + ++reg_dump_stack.stack_locations + [reg_dump_stack.stack_pointer - 1].rw_count; +} + +bool dal_reg_logger_should_dump_register(void) +{ + if (true == dal_reg_dump_stack_is_empty()) + return false; + + if (false == is_reg_dump_process()) + return false; + + return true; +} + +/****************************************************************************** + * End of File. + *****************************************************************************/ diff --git a/drivers/gpu/drm/amd/dal/dc/basics/signal_types.c b/drivers/gpu/drm/amd/dal/dc/basics/signal_types.c new file mode 100644 index 000000000000..44447e07803a --- /dev/null +++ b/drivers/gpu/drm/amd/dal/dc/basics/signal_types.c @@ -0,0 +1,116 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "include/signal_types.h" + +bool dc_is_hdmi_signal(enum signal_type signal) +{ + return (signal == SIGNAL_TYPE_HDMI_TYPE_A); +} + +bool dc_is_dp_sst_signal(enum signal_type signal) +{ + return (signal == SIGNAL_TYPE_DISPLAY_PORT || + signal == SIGNAL_TYPE_EDP); +} + +bool dc_is_dp_signal(enum signal_type signal) +{ + return (signal == SIGNAL_TYPE_DISPLAY_PORT || + signal == SIGNAL_TYPE_EDP || + signal == SIGNAL_TYPE_DISPLAY_PORT_MST); +} + +bool dc_is_dp_external_signal(enum signal_type signal) +{ + return (signal == SIGNAL_TYPE_DISPLAY_PORT || + signal == SIGNAL_TYPE_DISPLAY_PORT_MST); +} + +bool dc_is_analog_signal(enum signal_type signal) +{ + switch (signal) { + case SIGNAL_TYPE_RGB: + return true; + break; + default: + return false; + } +} + +bool dc_is_embedded_signal(enum signal_type signal) +{ + return (signal == SIGNAL_TYPE_EDP || signal == SIGNAL_TYPE_LVDS); +} + +bool dc_is_dvi_signal(enum signal_type signal) +{ + switch (signal) { + case SIGNAL_TYPE_DVI_SINGLE_LINK: + case SIGNAL_TYPE_DVI_DUAL_LINK: + return true; + break; + default: + return false; + } +} + +bool dc_is_dvi_single_link_signal(enum signal_type signal) +{ + return (signal == SIGNAL_TYPE_DVI_SINGLE_LINK); +} + +bool dc_is_dual_link_signal(enum signal_type signal) +{ + return (signal == SIGNAL_TYPE_DVI_DUAL_LINK); +} + +bool dc_is_audio_capable_signal(enum signal_type signal) +{ + return (signal == SIGNAL_TYPE_DISPLAY_PORT || + signal == SIGNAL_TYPE_DISPLAY_PORT_MST || + dc_is_hdmi_signal(signal) || + signal == SIGNAL_TYPE_WIRELESS); +} + +/* + * @brief + * Returns whether the signal is compatible + * with other digital encoder signal types. + * This is true for DVI, LVDS, and HDMI signal types. + */ +bool dc_is_digital_encoder_compatible_signal(enum signal_type signal) +{ + switch (signal) { + case SIGNAL_TYPE_DVI_SINGLE_LINK: + case SIGNAL_TYPE_DVI_DUAL_LINK: + case SIGNAL_TYPE_HDMI_TYPE_A: + case SIGNAL_TYPE_LVDS: + return true; + default: + return false; + } +} diff --git a/drivers/gpu/drm/amd/dal/dc/basics/vector.c b/drivers/gpu/drm/amd/dal/dc/basics/vector.c new file mode 100644 index 000000000000..32ca6b13a3bd --- /dev/null +++ b/drivers/gpu/drm/amd/dal/dc/basics/vector.c @@ -0,0 +1,309 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "include/vector.h" + +bool dal_vector_construct( + struct vector *vector, + struct dc_context *ctx, + uint32_t capacity, + uint32_t struct_size) +{ + vector->container = NULL; + + if (!struct_size || !capacity) { + /* Container must be non-zero size*/ + BREAK_TO_DEBUGGER(); + return false; + } + + vector->container = dm_alloc(ctx, struct_size * capacity); + if (vector->container == NULL) + return false; + vector->capacity = capacity; + vector->struct_size = struct_size; + vector->count = 0; + vector->ctx = ctx; + return true; +} + +bool dal_vector_presized_costruct( + struct vector *vector, + struct dc_context *ctx, + uint32_t count, + void *initial_value, + uint32_t struct_size) +{ + uint32_t i; + + vector->container = NULL; + + if (!struct_size || !count) { + /* Container must be non-zero size*/ + BREAK_TO_DEBUGGER(); + return false; + } + + vector->container = dm_alloc(ctx, struct_size * count); + + if (vector->container == NULL) + return false; + + /* If caller didn't supply initial value then the default + * of all zeros is expected, which is exactly what dal_alloc() + * initialises the memory to. */ + if (NULL != initial_value) { + for (i = 0; i < count; ++i) + dm_memmove( + vector->container + i * struct_size, + initial_value, + struct_size); + } + + vector->capacity = count; + vector->struct_size = struct_size; + vector->count = count; + return true; +} + +struct vector *dal_vector_presized_create( + struct dc_context *ctx, + uint32_t size, + void *initial_value, + uint32_t struct_size) +{ + struct vector *vector = dm_alloc(ctx, sizeof(struct vector)); + + if (vector == NULL) + return NULL; + + if (dal_vector_presized_costruct( + vector, ctx, size, initial_value, struct_size)) + return vector; + + BREAK_TO_DEBUGGER(); + dm_free(ctx, vector); + return NULL; +} + +struct vector *dal_vector_create( + struct dc_context *ctx, + uint32_t capacity, + uint32_t struct_size) +{ + struct vector *vector = dm_alloc(ctx, sizeof(struct vector)); + + if (vector == NULL) + return NULL; + + if (dal_vector_construct(vector, ctx, capacity, struct_size)) + return vector; + + + BREAK_TO_DEBUGGER(); + dm_free(ctx, vector); + return NULL; +} + +void dal_vector_destruct( + struct vector *vector) +{ + if (vector->container != NULL) + dm_free(vector->ctx, vector->container); + vector->count = 0; + vector->capacity = 0; +} + +void dal_vector_destroy( + struct vector **vector) +{ + if (vector == NULL || *vector == NULL) + return; + dal_vector_destruct(*vector); + dm_free((*vector)->ctx, *vector); + *vector = NULL; +} + +uint32_t dal_vector_get_count( + const struct vector *vector) +{ + return vector->count; +} + +void *dal_vector_at_index( + const struct vector *vector, + uint32_t index) +{ + if (vector->container == NULL || index >= vector->count) + return NULL; + return vector->container + (index * vector->struct_size); +} + +bool dal_vector_remove_at_index( + struct vector *vector, + uint32_t index) +{ + if (index >= vector->count) + return false; + + if (index != vector->count - 1) + dm_memmove( + vector->container + (index * vector->struct_size), + vector->container + ((index + 1) * vector->struct_size), + (vector->count - index - 1) * vector->struct_size); + vector->count -= 1; + + return true; +} + +void dal_vector_set_at_index( + const struct vector *vector, + const void *what, + uint32_t index) +{ + void *where = dal_vector_at_index(vector, index); + + if (!where) { + BREAK_TO_DEBUGGER(); + return; + } + dm_memmove( + where, + what, + vector->struct_size); +} + +static inline uint32_t calc_increased_capacity( + uint32_t old_capacity) +{ + return old_capacity * 2; +} + +bool dal_vector_insert_at( + struct vector *vector, + const void *what, + uint32_t position) +{ + uint8_t *insert_address; + + if (vector->count == vector->capacity) { + if (!dal_vector_reserve( + vector, + calc_increased_capacity(vector->capacity))) + return false; + } + + insert_address = vector->container + (vector->struct_size * position); + + if (vector->count && position < vector->count) + dm_memmove( + insert_address + vector->struct_size, + insert_address, + vector->struct_size * (vector->count - position)); + + dm_memmove( + insert_address, + what, + vector->struct_size); + + vector->count++; + + return true; +} + +bool dal_vector_append( + struct vector *vector, + const void *item) +{ + return dal_vector_insert_at(vector, item, vector->count); +} + +struct vector *dal_vector_clone( + const struct vector *vector) +{ + struct vector *vec_cloned; + uint32_t count; + + /* create new vector */ + count = dal_vector_get_count(vector); + + if (count == 0) + /* when count is 0 we still want to create clone of the vector + */ + vec_cloned = dal_vector_create( + vector->ctx, + vector->capacity, + vector->struct_size); + else + /* Call "presized create" version, independently of how the + * original vector was created. + * The owner of original vector must know how to treat the new + * vector - as "presized" or as "regular". + * But from vector point of view it doesn't matter. */ + vec_cloned = dal_vector_presized_create(vector->ctx, count, + NULL,/* no initial value */ + vector->struct_size); + + if (NULL == vec_cloned) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + /* copy vector's data */ + dm_memmove(vec_cloned->container, vector->container, + vec_cloned->struct_size * vec_cloned->capacity); + + return vec_cloned; +} + +uint32_t dal_vector_capacity(const struct vector *vector) +{ + return vector->capacity; +} + +bool dal_vector_reserve(struct vector *vector, uint32_t capacity) +{ + void *new_container; + + if (capacity <= vector->capacity) + return true; + + new_container = dm_realloc(vector->ctx, vector->container, + capacity * vector->struct_size); + + if (new_container) { + vector->container = new_container; + vector->capacity = capacity; + return true; + } + + return false; +} + +void dal_vector_clear(struct vector *vector) +{ + vector->count = 0; +}