From patchwork Thu Aug 22 13:57:41 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Francis X-Patchwork-Id: 11109355 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 80F4114DB for ; Thu, 22 Aug 2019 13:58:08 +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 65B6C22CE3 for ; Thu, 22 Aug 2019 13:58:08 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 65B6C22CE3 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 A396E6EB46; Thu, 22 Aug 2019 13:58:07 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from NAM01-BN3-obe.outbound.protection.outlook.com (mail-eopbgr740087.outbound.protection.outlook.com [40.107.74.87]) by gabe.freedesktop.org (Postfix) with ESMTPS id 1F0E36EB44 for ; Thu, 22 Aug 2019 13:57:54 +0000 (UTC) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=bxPK5JYB/KU9FqUm1uMAN3ce6WGXgKDHKIskPRlmbNB9TX6noCcJoYlY74a45Cbz5XpvWLMXRfr9b71F8kvRiM9A8ii5jqhOBv4mFHQGT/bSu+v+fmySl6D1yqqwWFBkrFtT8fYnjm2oOk0S5yf0nAUMuihKton5o2SrHnauD7WFYOr3DeoLxAv5N9KHms7eahm6iSaSS6jy2VoGShYfoC/5i7K0eHkYxIDGWNnWBsn7ZEqqSb3XLqk6oe+iSOcL4QeTYEzUCnbkjfKouoIenPpounJvFKSS+xvA3Cm+HSRL++nu1iGubIxwF+y+ITOjyKvmUzMQRcUdQN6NYtA1XA== 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=YW17DyWPvcWSBuG1eQ4f332Eg6cWUuWuLaEmPrj9ziM=; b=aNNAV0Pde+3InHNSXu969IQhF3SkaNbNPKs9Uw6CxB2cH2RG1JV4DnUDDJdfrWOiymaSMTCTr+E9T6Kmm8x3Tpgap5tHA3r8xaCZfEmLqloXAuzr4WkfjCAhZD1M4Pt3WC0ZCImOIZ+4JYHXaouer3dH+I2FDn3asFH/8/ZSTVU/FaG1ld7VPVN4+ZJ2nL/RddmYX0SalEbpuN/qhTEbMsjfjHrBBDE+cU/EHwC6SH+R1zWhvmfARwqOXVMkq+1CZlFJDG8r1PTIKTz5JcZtKncGR9rfthBeblARCXpLJJTJzWyX7erfHPY40pOKT9iE5n5VJeWdhjNY+ddzYUPAYw== 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 DM3PR12CA0074.namprd12.prod.outlook.com (2603:10b6:0:57::18) by DM5PR12MB1274.namprd12.prod.outlook.com (2603:10b6:3:78::17) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.2178.18; Thu, 22 Aug 2019 13:57:52 +0000 Received: from CO1NAM03FT023.eop-NAM03.prod.protection.outlook.com (2a01:111:f400:7e48::203) by DM3PR12CA0074.outlook.office365.com (2603:10b6:0:57::18) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) id 15.20.2199.14 via Frontend Transport; Thu, 22 Aug 2019 13:57:52 +0000 Received-SPF: None (protection.outlook.com: amd.com does not designate permitted sender hosts) Received: from SATLEXCHOV01.amd.com (165.204.84.17) by CO1NAM03FT023.mail.protection.outlook.com (10.152.80.157) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) id 15.20.2178.16 via Frontend Transport; Thu, 22 Aug 2019 13:57:51 +0000 Received: from localhost.localdomain (10.180.168.240) by SATLEXCHOV01.amd.com (10.181.40.71) with Microsoft SMTP Server id 14.3.389.1; Thu, 22 Aug 2019 08:57:46 -0500 From: David Francis To: Subject: [PATCH v4 5/5] drm/dp-mst: Add helpers for querying and enabling MST DSC Date: Thu, 22 Aug 2019 09:57:41 -0400 Message-ID: <20190822135741.12923-6-David.Francis@amd.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190822135741.12923-1-David.Francis@amd.com> References: <20190822135741.12923-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)(136003)(39860400002)(396003)(376002)(346002)(2980300002)(428003)(199004)(189003)(486006)(50466002)(186003)(2906002)(11346002)(70206006)(4326008)(2616005)(426003)(126002)(53936002)(478600001)(336012)(476003)(50226002)(446003)(48376002)(81156014)(316002)(1076003)(81166006)(36756003)(6916009)(26005)(2351001)(5024004)(8676002)(14444005)(356004)(6666004)(305945005)(76176011)(54906003)(16586007)(8936002)(86362001)(47776003)(5660300002)(70586007)(51416003)(49486002); DIR:OUT; SFP:1101; SCL:1; SRVR:DM5PR12MB1274; H:SATLEXCHOV01.amd.com; FPR:; SPF:None; LANG:en; PTR:InfoDomainNonexistent; A:1; MX:1; X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: e9324d4e-4eb9-40c5-50a4-08d72708b920 X-Microsoft-Antispam: BCL:0; PCL:0; RULEID:(2390118)(7020095)(4652040)(8989299)(5600166)(711020)(4605104)(1401327)(4534185)(4627221)(201703031133081)(201702281549075)(8990200)(2017052603328); SRVR:DM5PR12MB1274; X-MS-TrafficTypeDiagnostic: DM5PR12MB1274: X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:9508; X-Forefront-PRVS: 01371B902F X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam-Message-Info: uLPzGbwgMUsYpYD4pb/rnvwhlOOOdWlaDxy05iJFXPEw0HXkEJIq9M7R0jMwACHPlB6YrBoBbcRy80NgmljnKOw9SiyxRkZVwz5mb5HDhcZ5fjHerxbNC6tEEBvWpNMR6ChYOsv9YQwWS5qmx1FVK3aCOWUNiby7rT35NyjVl1v3ookI4J/8pGrYlkHgDvbw2t6C6M6hs01ok3wkTEC0J2uv+gPdiw5IaM5+YMO/ZWg5G0OZ59swWVzgVwt76Rh7xXl6AE3WTEYW3eTp3Rg0ispsQeNipADl9v/LaseyodtM22G8dGqccfk1LSuU3vF61evWU1ahsheTnLeTDU1CICUGWpYNXRR+vWY6bXBE9QRrfAzjcze/uYiKpaNVxxE67tX/k9G8UDPCDPp+RBaqagskNDp8C2JP4PaPz9R6CY4= X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 22 Aug 2019 13:57:51.3507 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: e9324d4e-4eb9-40c5-50a4-08d72708b920 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=[SATLEXCHOV01.amd.com] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: DM5PR12MB1274 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=YW17DyWPvcWSBuG1eQ4f332Eg6cWUuWuLaEmPrj9ziM=; b=Roo+soJWG4XqC7WDuIZORv7hiJVL6RdXmT7UtHeowSlMN6PSF7JUrvi/Chl6e/ApznEKFcbC95FSql0CMSwm1CYUYNa6l9wNyFR9uvc6ThBDp4DR8Hc0pkudm38zzyCsnvAOAL6OTxEhKNBhD+iSgnbJrAs0XKOYmf7Bc7LAmis= 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 | 195 ++++++++++++++++++++++++++ include/drm/drm_dp_mst_helper.h | 3 + 2 files changed, 198 insertions(+) diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index af4b5cec7c84..00ddc54af65b 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -4186,3 +4186,198 @@ 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() - Test for Synaptix DSC quirk + * @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 = 0; + u8 endpoint_dsc = 0; + u8 endpoint_fec = 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, 1) < 0) + return NULL; + } + + if (drm_dp_dpcd_read(&port->aux, + DP_DSC_SUPPORT, &endpoint_dsc, 1) < 0) + return NULL; + if (drm_dp_dpcd_read(&port->aux, + DP_FEC_CAPABILITY, &endpoint_fec, 1) < 0) + return NULL; + + /* Enpoint decompression with DP-to-DP peer device */ + if (drm_dp_mst_is_virtual_dpcd(immediate_upstream_port) + && (upstream_dsc & 0x2) /* DSC passthrough */ + && (endpoint_fec & DP_FEC_CAPABLE) + && (endpoint_dsc & 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; /**