From patchwork Wed Aug 21 20:01:25 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Francis, David" X-Patchwork-Id: 11108103 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 668AF1395 for ; Wed, 21 Aug 2019 20:02:21 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 4F2002339E for ; Wed, 21 Aug 2019 20:02:21 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 4F2002339E Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=amd.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=dri-devel-bounces@lists.freedesktop.org Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id EC0216E9F6; Wed, 21 Aug 2019 20:02:18 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from NAM02-CY1-obe.outbound.protection.outlook.com (mail-cys01nam02on060b.outbound.protection.outlook.com [IPv6:2a01:111:f400:fe45::60b]) by gabe.freedesktop.org (Postfix) with ESMTPS id 424AE6E9F1; Wed, 21 Aug 2019 20:02:10 +0000 (UTC) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=Ivvmkhg/D1Yqn0IlCrnea0KabpUdpHrk+DXxJzogkKQ5FizBmXLLPxP2gpTTZT/dPDFJ64G6N5H0tBWDZz9UaM7uyF7BYOW9oENfgniJPwRo7hBUm58eRlXT+LSCUVskSsleqOzkEtelMdlsLm/0eXf62yrieKVayQaxMcWSCp7gEO2cfWvn+GcYMgOtoDuUxZhd/NYgST+kiPvWwBKm3031QV7ErKLly86eSx2mEZB1MKO2xWDz1gAONMSdAcpzTso85DQvWq5dbqmdnIsfdtIbjuUaY7+/BuIXPql4r9/idlGJl2XpyHdNz2NmLmEljaSopspqIDIDUVv/8mX+Ew== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=7jCTuqg753zcG2DWqF+rNOfZS/xoldEwEFDIOrkqB8s=; b=DokeGWYFBTv2taAOucH5pNyaXa1tL7+Gkck3R33yzs1Y06tByECap55+bjreadlUkYaxF1PoZpIrV1NOxNPgE1FO0h6oOAiq+2AmZIxvjPhdJxs8yupJqxt19JZzPaJu2+F/K7/WO8+c59mLTogGmgBqrQB0ql4Qayk9NtI554NVmz5r7Je25usU2PSQL/VmMhCL4YrhsqmE7ceU2XB7w2fatbOh/dtdxe/+6Gi66N6cDpBh900NbKm9hv4bcKdoFtSdS+UnxUk5Ci0zJvHt6alr+pBYfJviD/fbotO3Vy3iyG9xKWAPUMI2U9bFhFaiRpjsuw+Hmj6ahxD8FtoXxw== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=none (sender ip is 165.204.84.17) smtp.rcpttodomain=redhat.com smtp.mailfrom=amd.com; dmarc=permerror action=none header.from=amd.com; dkim=none (message not signed); arc=none Received: from BN4PR12CA0009.namprd12.prod.outlook.com (10.164.241.19) by BN6PR12MB1267.namprd12.prod.outlook.com (10.168.224.141) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.2178.16; Wed, 21 Aug 2019 20:02:06 +0000 Received: from CO1NAM03FT063.eop-NAM03.prod.protection.outlook.com (2a01:111:f400:7e48::208) by BN4PR12CA0009.outlook.office365.com (2603:10b6:403:2::19) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) id 15.20.2178.16 via Frontend Transport; Wed, 21 Aug 2019 20:02:06 +0000 Received-SPF: None (protection.outlook.com: amd.com does not designate permitted sender hosts) Received: from SATLEXCHOV02.amd.com (165.204.84.17) by CO1NAM03FT063.mail.protection.outlook.com (10.152.81.61) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) id 15.20.2178.16 via Frontend Transport; Wed, 21 Aug 2019 20:02:04 +0000 Received: from localhost.localdomain (10.180.168.240) by SATLEXCHOV02.amd.com (10.181.40.72) with Microsoft SMTP Server id 14.3.389.1; Wed, 21 Aug 2019 15:01:42 -0500 From: David Francis To: , Subject: [PATCH v3 12/16] drm/dp-mst: Add helpers for querying and enabling MST DSC Date: Wed, 21 Aug 2019 16:01:25 -0400 Message-ID: <20190821200129.11575-13-David.Francis@amd.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190821200129.11575-1-David.Francis@amd.com> References: <20190821200129.11575-1-David.Francis@amd.com> MIME-Version: 1.0 X-EOPAttributedMessage: 0 X-MS-Office365-Filtering-HT: Tenant X-Forefront-Antispam-Report: CIP:165.204.84.17; IPV:NLI; CTRY:US; EFV:NLI; SFV:NSPM; SFS:(10009020)(4636009)(39860400002)(376002)(136003)(396003)(346002)(2980300002)(428003)(189003)(199004)(81156014)(70206006)(50226002)(6666004)(356004)(54906003)(110136005)(476003)(5024004)(14444005)(478600001)(36756003)(70586007)(5660300002)(486006)(86362001)(126002)(11346002)(446003)(316002)(53936002)(2616005)(16586007)(186003)(8936002)(51416003)(49486002)(50466002)(426003)(8676002)(305945005)(4326008)(2906002)(1076003)(48376002)(26005)(81166006)(76176011)(336012)(47776003); DIR:OUT; SFP:1101; SCL:1; SRVR:BN6PR12MB1267; H:SATLEXCHOV02.amd.com; FPR:; SPF:None; LANG:en; PTR:InfoDomainNonexistent; MX:1; A:1; X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 4148f11e-a464-4822-cb4d-08d726727076 X-Microsoft-Antispam: BCL:0; PCL:0; RULEID:(2390118)(7020095)(4652040)(8989299)(5600148)(711020)(4605104)(1401327)(4534185)(4627221)(201703031133081)(201702281549075)(8990200)(2017052603328); SRVR:BN6PR12MB1267; X-MS-TrafficTypeDiagnostic: BN6PR12MB1267: X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:9508; X-Forefront-PRVS: 0136C1DDA4 X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam-Message-Info: uakFFQofUXVwPv50pku880OTjffwMVHeiQh9BtucPekHXkvDtnJoIUHryCCBgv/+xsx41T7RL7rWPjvgL6SQLj8/f7NsEirHMUQZWJXhDBIm6XIsrm2648N959e2R2tzcm9d38gtRQ6tgXOEqtum9kFPC4SxwMuOe7xaeAG+szJiLRKL0Qase6VKJmK5RprwHCCU+S+wyLWdNmXMT4K46bM+HMOwQHP75TR5b1ICfn51H7f7YUmVUV7HPPuw1k+Aw7T0GtRpjtHg/4c1p3Ilqpyi05wZfZqynGqTw5+PrWQC7TkPeIT4HNToORPUpfgEG1DlwWLCP4C7xEvWgTqCEoBd9Ajp14A1O2lg0bMO2lD8/Ocd8jK+NqBXSVmNSGSGWfO6VNuJ0Q8dhdO/vYZLS56SH5W7blFivNzDnJbZBwM= X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 21 Aug 2019 20:02:04.9043 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 4148f11e-a464-4822-cb4d-08d726727076 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.17]; Helo=[SATLEXCHOV02.amd.com] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: BN6PR12MB1267 X-Mailman-Original-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amdcloud.onmicrosoft.com; s=selector2-amdcloud-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=7jCTuqg753zcG2DWqF+rNOfZS/xoldEwEFDIOrkqB8s=; b=SFbl8WZajH6KWfoMYhNqPn435AjgBlSwhOaWxbKJE1L5TgL0KoPzv/ssoik5EYcfE36Mp+OUX7E30nAj6fLNgjQ/Y/aq04FvHUrUAcQUk+igsNcgdsKB4cMMOOJo627PNc19DZG3qD9e7xGYQw5x/qnw9CdAgkhoartwrztHGco= X-Mailman-Original-Authentication-Results: spf=none (sender IP is 165.204.84.17) smtp.mailfrom=amd.com; redhat.com; dkim=none (message not signed) header.d=none;redhat.com; dmarc=permerror action=none header.from=amd.com; X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Wenjing Liu , David Francis , Nikola Cornij Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" Add drm_dp_mst_dsc_caps_for_port and drm_dp_mst_dsc_enable, two helper functions for MST DSC The former, given a port, returns the raw DPCD DSC caps off that port. The latter, given a port, enables or disables DSC on that port. In both cases, the port given as input should be a leaf of the MST tree with an attached display. The logic for this is somewhat complicated, as DSC can be enabled in 4 different ways. Case 1: DP-to-DP peer device if the branch immediately upstream has - PDT = DP_PEER_DEVICE_DP_MST_BRANCHING (2) - DPCD rev. >= DP 1.4 - Exactly one input and one output - The output has PDT = DP_PEER_DEVICE_SST_SINK (3) In this case, DSC could be possible either on the endpoint or the peer device. Prefer the endpoint, which is possible if - The endpoint has DP_DSC_DECOMPRESSION_IS_SUPPORTED bit set - The endpoint has DP_FEC_CAPABLE bit set - The peer device has DSC_PASSTHROUGH_CAPABILITY bit set (from DP v2.0) Otherwise, use the peer device Case 2: DP-to-HDMI peer device If the output port has - PDT = DP_PEER_DEVICE_DP_LEGACY_CONV (4) - DPCD rev. >= DP 1.4 - LDPS = true - MCS = false In this case, DSC can only be attempted on the peer device (the output port) Case 3: Virtual DP Sink (Internal Display Panel) If the output port has - DPCD rev. >= DP 1.4 - port_num >= 8 In this case, DSC can only be attempted on the peer device (the output port) Case 4: Synaptix Workaround If the output has - link DPCD rev. >= DP 1.4 - link branch_dev_id = 0x90CC24 (Synaptix) - There is exactly one branch device between the link and output In this case, DSC can be attempted, but only using the *link* aux device's caps. This is a quirk. Cc: Lyude Paul Cc: Wenjing Liu Cc: Nikola Cornij Signed-off-by: David Francis --- drivers/gpu/drm/drm_dp_mst_topology.c | 192 ++++++++++++++++++++++++++ include/drm/drm_dp_mst_helper.h | 3 + 2 files changed, 195 insertions(+) diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index 7decb5bef062..94742538551e 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -4183,3 +4183,195 @@ static void drm_dp_mst_unregister_i2c_bus(struct drm_dp_aux *aux) { i2c_del_adapter(&aux->ddc); } + +/** + * drm_dp_mst_is_virtual_dpcd() - Is the given port a virtual DPCD device? + * @port: The port to check + * + * Returns: + * true if the port is a virtual DPCD peer device, false otherwise + */ +static bool drm_dp_mst_is_virtual_dpcd(struct drm_dp_mst_port *port) +{ + struct drm_dp_mst_port *downstream_port; + + if (!port) + return false; + + /* Virtual DP Sink (Internal Display Panel) */ + if (port->port_num >= 8 && port->dpcd_rev >= DP_DPCD_REV_14) + return true; + + /* DP-to-HDMI Protocol Converter */ + if (port->pdt == DP_PEER_DEVICE_DP_LEGACY_CONV && + !port->mcs && + port->ldps && + port->dpcd_rev >= DP_DPCD_REV_14) + return true; + + /* DP-to-DP */ + if (port->pdt == DP_PEER_DEVICE_MST_BRANCHING && + port->mstb && + port->dpcd_rev >= DP_DPCD_REV_14 && + port->mstb->num_ports == 2) { + list_for_each_entry(downstream_port, &port->mstb->ports, next) { + if (!downstream_port->input && + downstream_port->pdt == DP_PEER_DEVICE_SST_SINK) + return true; + } + } + + return false; +} + +/** + * drm_dp_mst_is_virtual_dpcd() - Does this port require Synaptix DSC workaround? + * @port: The port to check + * + * Some Synaptix MST hubs support DSC even though they do not support virtual + * DPCD. This is a quirk. + * + * Returns: + * true if the Synaptix workaround is required, false otherwise + */ +static bool drm_dp_mst_dsc_synaptix_workaround(struct drm_dp_mst_port *port) +{ + u8 data[3] = { 0 }; + u32 dev_id; + struct drm_dp_aux *phys_aux; + + /* The hub must be directly connected to the connector */ + if (port->mgr->mst_primary != port->parent) + return false; + + phys_aux = port->mgr->aux; + if (drm_dp_dpcd_read(phys_aux, DP_BRANCH_OUI, data, 3) < 0) + return false; + dev_id = (data[0] << 16) & (data[1] << 8) & data[3]; + /* Synaptix device ID */ + if (dev_id != 0x90CC24) + return false; + + if (drm_dp_dpcd_read(phys_aux, DP_DPCD_REV, data, 1) < 0) + return false; + /* Must be DPCD rev. 1.4 or later */ + if (data[0] < DP_DPCD_REV_14) + return false; + + if (drm_dp_dpcd_read(&port->aux, DP_DOWNSTREAMPORT_PRESENT, data, 1) < 0) + return false; + /* Must not be a VGA converter */ + if ((data[0] & 7) == 3) + return false; + + return true; +} + +/** + * drm_dp_mst_dsc_aux_for_port() - Find the correct aux for DSC + * @port: The port to check. A leaf of the MST tree with an attached display. + * + * Depending on the situation, DSC may be enabled via the endpoint aux, + * the immediately upstream aux, or the connector's physical aux. + * + * Returns: + * NULL if DSC cannot be enabled on this port, otherwise the aux device + */ +struct drm_dp_aux *drm_dp_mst_dsc_aux_for_port(struct drm_dp_mst_port *port) +{ + u8 upstream_dsc_caps = 0; + u8 endpoint_dsc_caps = 0; + u8 endpoint_fec_caps = 0; + struct drm_dp_mst_port *immediate_upstream_port; + struct drm_dp_mst_port *fec_port; + + if (port && port->parent) + immediate_upstream_port = port->parent->port_parent; + else + immediate_upstream_port = NULL; + + fec_port = immediate_upstream_port; + while (fec_port) { + if (!fec_port->fec_capable) + return NULL; + + fec_port = fec_port->parent->port_parent; + } + + if (immediate_upstream_port) { + if (drm_dp_dpcd_read(&immediate_upstream_port->aux, + DP_DSC_SUPPORT, &upstream_dsc_caps, 1) < 0) + return NULL; + } + + if (drm_dp_dpcd_read(&port->aux, DP_DSC_SUPPORT, &endpoint_dsc_caps, 1) < 0) + return NULL; + if (drm_dp_dpcd_read(&port->aux, DP_FEC_CAPABILITY, &endpoint_fec_caps, 1) < 0) + return NULL; + + /* Enpoint decompression with DP-to-DP peer device */ + if (drm_dp_mst_is_virtual_dpcd(immediate_upstream_port) + && (upstream_dsc_caps & 0x2) /* DSC passthrough capability */ + && (endpoint_fec_caps & DP_FEC_CAPABLE) + && (endpoint_dsc_caps & DP_DSC_DECOMPRESSION_IS_SUPPORTED)) + return &port->aux; + + /* Virtual DPCD decompression with DP-to-DP peer device */ + if (drm_dp_mst_is_virtual_dpcd(immediate_upstream_port)) + return &immediate_upstream_port->aux; + + /* Virtual DPCD decompression with DP-to-HDMI or Virtual DP Sink */ + if (drm_dp_mst_is_virtual_dpcd(port)) + return &port->aux; + + /* Synaptix workaround */ + if (drm_dp_mst_dsc_synaptix_workaround(port)) + return port->mgr->aux; + + return NULL; +} + +/** + * drm_dp_mst_dsc_aux_for_port() - Retrieve the DSC capability registers + * @port: The port to check. A leaf of the MST tree with an attached display. + * @caps: Output. A pointer to an array at least 16 bytes long + * + * Reads the DSC capability registers (DSC_SUPPORT through + * BITS_PER_PIXEL_INCREMENT) and store them in the given pointer. Use + * the correct aux for DSC on the given port. + * + * Returns: + * The number of bytes read on success, or a negative error code on failure + */ +int drm_dp_mst_dsc_caps_for_port(struct drm_dp_mst_port *port, u8 *caps) +{ + struct drm_dp_aux *aux = drm_dp_mst_dsc_aux_for_port(port); + + if (!aux) + return -EINVAL; + + return drm_dp_dpcd_read(aux, DP_DSC_SUPPORT, caps, 16); +} +EXPORT_SYMBOL(drm_dp_mst_dsc_caps_for_port); + +/** + * drm_dp_mst_dsc_aux_for_port() - Enable DSC on an MST endpoint + * @port: The port to check. A leaf of the MST tree with an attached display. + * @enable: true for turn on DSC, false for turn off DSC + * + * Writes DP_DSC_ENABLE on the correct aux for the given port. + * + * Returns: + * The number of bytes written on success, or a negative error code on failure + */ +int drm_dp_mst_dsc_enable(struct drm_dp_mst_port *port, bool enable) +{ + struct drm_dp_aux *aux = drm_dp_mst_dsc_aux_for_port(port); + u8 enable_dsc = enable ? 1 : 0; + + if (!aux) + return -EINVAL; + + return drm_dp_dpcd_write(aux, DP_DSC_ENABLE, &enable_dsc, 1); +} +EXPORT_SYMBOL(drm_dp_mst_dsc_enable); diff --git a/include/drm/drm_dp_mst_helper.h b/include/drm/drm_dp_mst_helper.h index fa973773a4a7..0f70dc8dfbeb 100644 --- a/include/drm/drm_dp_mst_helper.h +++ b/include/drm/drm_dp_mst_helper.h @@ -674,6 +674,9 @@ int __must_check drm_dp_mst_atomic_check(struct drm_atomic_state *state); void drm_dp_mst_get_port_malloc(struct drm_dp_mst_port *port); void drm_dp_mst_put_port_malloc(struct drm_dp_mst_port *port); +int drm_dp_mst_dsc_caps_for_port(struct drm_dp_mst_port *port, u8 *caps); +int drm_dp_mst_dsc_enable(struct drm_dp_mst_port *port, bool enable); + extern const struct drm_private_state_funcs drm_dp_mst_topology_state_funcs; /**