From patchwork Mon Mar 7 17:59:52 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kieran Bingham X-Patchwork-Id: 12772139 X-Patchwork-Delegate: kieran@bingham.xyz Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3C166C433EF for ; Mon, 7 Mar 2022 18:00:10 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S244611AbiCGSBC (ORCPT ); Mon, 7 Mar 2022 13:01:02 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51514 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S244597AbiCGSBB (ORCPT ); Mon, 7 Mar 2022 13:01:01 -0500 Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id BD9495DE5F for ; Mon, 7 Mar 2022 10:00:06 -0800 (PST) Received: from Monstersaurus.ksquared.org.uk.beta.tailscale.net (cpc89244-aztw30-2-0-cust3082.18-1.cable.virginm.net [86.31.172.11]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id AD12C8C1; Mon, 7 Mar 2022 19:00:04 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1646676005; bh=sD1oH3Anlxn9WQLfDYfbvc6dUo2C8d8M8uM9rAaJFvY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Z8f7HH5v4fb1Xq8do2kwKqjhlyEMjpn1EhZ/olS8jNu8uIzRAUvIzHBVbWsUkiwmf RBvwqAExvvuJXDIYRtbQAMVWV1eJJs80N0DG2NKv5ihv7AXSeNAjj0WhzndCOfJInX BE+60waWzp9rfy1gtlwkO1LKl0FdSlA9Oqo+5Me8= From: Kieran Bingham To: dri-devel@lists.freedesktop.org, linux-renesas-soc@vger.kernel.org Cc: Andrzej Hajda , Neil Armstrong , Robert Foss , Laurent Pinchart , Jonas Karlman , Jernej Skrabec , David Airlie , Daniel Vetter , Laurent Pinchart , Stephen Boyd , Douglas Anderson , Kieran Bingham Subject: [PATCH v2 1/4] drm/bridge: ti-sn65dsi86: Implement bridge connector operations Date: Mon, 7 Mar 2022 17:59:52 +0000 Message-Id: <20220307175955.363057-2-kieran.bingham+renesas@ideasonboard.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20220307175955.363057-1-kieran.bingham+renesas@ideasonboard.com> References: <20220307175955.363057-1-kieran.bingham+renesas@ideasonboard.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-renesas-soc@vger.kernel.org From: Laurent Pinchart Implement the bridge connector-related .get_edid() operation, and report the related bridge capabilities and type. Signed-off-by: Laurent Pinchart Reviewed-by: Stephen Boyd Reviewed-by: Douglas Anderson Signed-off-by: Kieran Bingham --- Changes since v1: - The connector .get_modes() operation doesn't rely on EDID anymore, __ti_sn_bridge_get_edid() and ti_sn_bridge_get_edid() got merged together Notes from Kieran: RB Tags collected from: https://lore.kernel.org/all/20210322030128.2283-9-laurent.pinchart+renesas@ideasonboard.com/ However this was over a year ago, so let me know if other patches now superceed this one or otherwise invalidate this update. drivers/gpu/drm/bridge/ti-sn65dsi86.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi86.c b/drivers/gpu/drm/bridge/ti-sn65dsi86.c index c55848588123..ffb6c04f6c46 100644 --- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c +++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c @@ -1154,6 +1154,19 @@ static void ti_sn_bridge_post_disable(struct drm_bridge *bridge) pm_runtime_put_sync(pdata->dev); } +static struct edid *ti_sn_bridge_get_edid(struct drm_bridge *bridge, + struct drm_connector *connector) +{ + struct ti_sn65dsi86 *pdata = bridge_to_ti_sn65dsi86(bridge); + struct edid *edid; + + pm_runtime_get_sync(pdata->dev); + edid = drm_get_edid(connector, &pdata->aux.ddc); + pm_runtime_put_autosuspend(pdata->dev); + + return edid; +} + static const struct drm_bridge_funcs ti_sn_bridge_funcs = { .attach = ti_sn_bridge_attach, .detach = ti_sn_bridge_detach, @@ -1162,6 +1175,7 @@ static const struct drm_bridge_funcs ti_sn_bridge_funcs = { .enable = ti_sn_bridge_enable, .disable = ti_sn_bridge_disable, .post_disable = ti_sn_bridge_post_disable, + .get_edid = ti_sn_bridge_get_edid, }; static void ti_sn_bridge_parse_lanes(struct ti_sn65dsi86 *pdata, @@ -1248,6 +1262,8 @@ static int ti_sn_bridge_probe(struct auxiliary_device *adev, pdata->bridge.funcs = &ti_sn_bridge_funcs; pdata->bridge.of_node = np; + pdata->bridge.ops = DRM_BRIDGE_OP_EDID; + pdata->bridge.type = DRM_MODE_CONNECTOR_eDP; drm_bridge_add(&pdata->bridge); From patchwork Mon Mar 7 17:59:53 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kieran Bingham X-Patchwork-Id: 12772140 X-Patchwork-Delegate: kieran@bingham.xyz Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 574F1C4332F for ; Mon, 7 Mar 2022 18:00:11 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S241674AbiCGSBE (ORCPT ); Mon, 7 Mar 2022 13:01:04 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51604 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S244610AbiCGSBC (ORCPT ); Mon, 7 Mar 2022 13:01:02 -0500 Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2B85F606C4 for ; Mon, 7 Mar 2022 10:00:08 -0800 (PST) Received: from Monstersaurus.ksquared.org.uk.beta.tailscale.net (cpc89244-aztw30-2-0-cust3082.18-1.cable.virginm.net [86.31.172.11]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 569778EB; Mon, 7 Mar 2022 19:00:05 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1646676005; bh=cMlE7TLxSpeyuuIFaKRoG+l9kmINH8LyAl/UsPH9YhM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=J0BYA5p3XkDykWrmQeW4UEfDkwnVk1pNPhLvikKhPRSTlOQa/SbqLNLmG1yvgbErY 4JGTjK4scKUkwLxesLp24l1q4NoCixcHtEIRpee8M7Wev7JUQDWLy+iEjXz3X3AYqi jQ6dp5951EvPxTyXodkHyNZETiYRqSO4psU772yo= From: Kieran Bingham To: dri-devel@lists.freedesktop.org, linux-renesas-soc@vger.kernel.org Cc: Andrzej Hajda , Neil Armstrong , Robert Foss , Laurent Pinchart , Jonas Karlman , Jernej Skrabec , David Airlie , Daniel Vetter , Laurent Pinchart , Kieran Bingham Subject: [PATCH v2 2/4] drm/bridge: ti-sn65dsi86: Make connector creation optional Date: Mon, 7 Mar 2022 17:59:53 +0000 Message-Id: <20220307175955.363057-3-kieran.bingham+renesas@ideasonboard.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20220307175955.363057-1-kieran.bingham+renesas@ideasonboard.com> References: <20220307175955.363057-1-kieran.bingham+renesas@ideasonboard.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-renesas-soc@vger.kernel.org From: Laurent Pinchart Now that the driver supports the connector-related bridge operations, make the connector creation optional. This enables usage of the sn65dsi86 with the DRM bridge connector helper. Signed-off-by: Laurent Pinchart Signed-off-by: Kieran Bingham --- Changes since v1: - None drivers/gpu/drm/bridge/ti-sn65dsi86.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi86.c b/drivers/gpu/drm/bridge/ti-sn65dsi86.c index ffb6c04f6c46..29f5f7123ed9 100644 --- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c +++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c @@ -745,11 +745,6 @@ static int ti_sn_bridge_attach(struct drm_bridge *bridge, struct ti_sn65dsi86 *pdata = bridge_to_ti_sn65dsi86(bridge); int ret; - if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) { - DRM_ERROR("Fix bridge driver to make connector optional!"); - return -EINVAL; - } - pdata->aux.drm_dev = bridge->dev; ret = drm_dp_aux_register(&pdata->aux); if (ret < 0) { @@ -757,12 +752,14 @@ static int ti_sn_bridge_attach(struct drm_bridge *bridge, return ret; } - ret = ti_sn_bridge_connector_init(pdata); - if (ret < 0) - goto err_conn_init; + if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)) { + ret = ti_sn_bridge_connector_init(pdata); + if (ret < 0) + goto err_conn_init; - /* We never want the next bridge to *also* create a connector: */ - flags |= DRM_BRIDGE_ATTACH_NO_CONNECTOR; + /* We never want the next bridge to *also* create a connector: */ + flags |= DRM_BRIDGE_ATTACH_NO_CONNECTOR; + } /* Attach the next bridge */ ret = drm_bridge_attach(bridge->encoder, pdata->next_bridge, From patchwork Mon Mar 7 17:59:54 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kieran Bingham X-Patchwork-Id: 12772141 X-Patchwork-Delegate: kieran@bingham.xyz Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 41233C43217 for ; Mon, 7 Mar 2022 18:00:12 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238652AbiCGSBE (ORCPT ); Mon, 7 Mar 2022 13:01:04 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51686 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236338AbiCGSBD (ORCPT ); Mon, 7 Mar 2022 13:01:03 -0500 Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 09E50606F7 for ; Mon, 7 Mar 2022 10:00:09 -0800 (PST) Received: from Monstersaurus.ksquared.org.uk.beta.tailscale.net (cpc89244-aztw30-2-0-cust3082.18-1.cable.virginm.net [86.31.172.11]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id E7C80A49; Mon, 7 Mar 2022 19:00:05 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1646676006; bh=IgcfP7PHmrGq9GErZHV8bP+/Yp5z+H6A/PAo+JqfC6w=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=t3cwr96/q1+qC5P/oYr05NrUXqns/jzO+MLJ2kIRoXPMgQUMCsKJWEW8reSb2lTY5 3AXQmsN9RIVNppiv0kQXZLmxHBPmChyPIbufES7a7QgdbGRb7WaPTD/91obZBY2og6 MR/jkU6FXfVqPY+/7K64JElWYTABHSmTrEZKnJxc= From: Kieran Bingham To: dri-devel@lists.freedesktop.org, linux-renesas-soc@vger.kernel.org Cc: Andrzej Hajda , Neil Armstrong , Robert Foss , Laurent Pinchart , Jonas Karlman , Jernej Skrabec , David Airlie , Daniel Vetter , Laurent Pinchart , Kieran Bingham Subject: [PATCH v2 3/4] drm/bridge: ti-sn65dsi86: Support DisplayPort (non-eDP) mode Date: Mon, 7 Mar 2022 17:59:54 +0000 Message-Id: <20220307175955.363057-4-kieran.bingham+renesas@ideasonboard.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20220307175955.363057-1-kieran.bingham+renesas@ideasonboard.com> References: <20220307175955.363057-1-kieran.bingham+renesas@ideasonboard.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-renesas-soc@vger.kernel.org From: Laurent Pinchart Despite the SN65DSI86 being an eDP bridge, on some systems its output is routed to a DisplayPort connector. Enable DisplayPort mode when the next component in the display pipeline is detected as a DisplayPort connector, and disable eDP features in that case. Signed-off-by: Laurent Pinchart Reworked to set bridge type based on the next bridge/connector. Signed-off-by: Kieran Bingham --- Changes since v1/RFC: - Rebased on top of "drm/bridge: ti-sn65dsi86: switch to devm_drm_of_get_bridge" - eDP/DP mode determined from the next bridge connector type. drivers/gpu/drm/bridge/ti-sn65dsi86.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi86.c b/drivers/gpu/drm/bridge/ti-sn65dsi86.c index 29f5f7123ed9..461f963faa0b 100644 --- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c +++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c @@ -60,6 +60,7 @@ #define SN_LN_ASSIGN_REG 0x59 #define LN_ASSIGN_WIDTH 2 #define SN_ENH_FRAME_REG 0x5A +#define ASSR_CONTROL BIT(0) #define VSTREAM_ENABLE BIT(3) #define LN_POLRS_OFFSET 4 #define LN_POLRS_MASK 0xf0 @@ -91,6 +92,8 @@ #define SN_DATARATE_CONFIG_REG 0x94 #define DP_DATARATE_MASK GENMASK(7, 5) #define DP_DATARATE(x) ((x) << 5) +#define SN_TRAINING_SETTING_REG 0x95 +#define SCRAMBLE_DISABLE BIT(4) #define SN_ML_TX_MODE_REG 0x96 #define ML_TX_MAIN_LINK_OFF 0 #define ML_TX_NORMAL_MODE BIT(0) @@ -1005,6 +1008,11 @@ static int ti_sn_link_training(struct ti_sn65dsi86 *pdata, int dp_rate_idx, regmap_update_bits(pdata->regmap, SN_DATARATE_CONFIG_REG, DP_DATARATE_MASK, DP_DATARATE(dp_rate_idx)); + /* For DisplayPort, use the standard DP scrambler seed. */ + if (pdata->bridge.type == DRM_MODE_CONNECTOR_DisplayPort) + regmap_update_bits(pdata->regmap, SN_ENH_FRAME_REG, + ASSR_CONTROL, 0); + /* enable DP PLL */ regmap_write(pdata->regmap, SN_PLL_ENABLE_REG, 1); @@ -1016,6 +1024,11 @@ static int ti_sn_link_training(struct ti_sn65dsi86 *pdata, int dp_rate_idx, goto exit; } + /* For DisplayPort, disable scrambling mode. */ + if (pdata->bridge.type == DRM_MODE_CONNECTOR_DisplayPort) + regmap_update_bits(pdata->regmap, SN_TRAINING_SETTING_REG, + SCRAMBLE_DISABLE, SCRAMBLE_DISABLE); + /* * We'll try to link train several times. As part of link training * the bridge chip will write DP_SET_POWER_D0 to DP_SET_POWER. If @@ -1260,7 +1273,8 @@ static int ti_sn_bridge_probe(struct auxiliary_device *adev, pdata->bridge.funcs = &ti_sn_bridge_funcs; pdata->bridge.of_node = np; pdata->bridge.ops = DRM_BRIDGE_OP_EDID; - pdata->bridge.type = DRM_MODE_CONNECTOR_eDP; + pdata->bridge.type = pdata->next_bridge->type == DRM_MODE_CONNECTOR_DisplayPort + ? DRM_MODE_CONNECTOR_DisplayPort : DRM_MODE_CONNECTOR_eDP; drm_bridge_add(&pdata->bridge); From patchwork Mon Mar 7 17:59:55 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kieran Bingham X-Patchwork-Id: 12772142 X-Patchwork-Delegate: kieran@bingham.xyz Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id C5679C433EF for ; Mon, 7 Mar 2022 18:00:13 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S244613AbiCGSBH (ORCPT ); Mon, 7 Mar 2022 13:01:07 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51896 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236338AbiCGSBG (ORCPT ); Mon, 7 Mar 2022 13:01:06 -0500 Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B24D05DE5F for ; Mon, 7 Mar 2022 10:00:10 -0800 (PST) Received: from Monstersaurus.ksquared.org.uk.beta.tailscale.net (cpc89244-aztw30-2-0-cust3082.18-1.cable.virginm.net [86.31.172.11]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 83AC8B6C; Mon, 7 Mar 2022 19:00:06 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1646676007; bh=7GnlsHeL9MDTdwZOlEToDD/Ya3nglGn1iT+wlz721dQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ogfGNwOMkHIZxJaUjQGXGW3hc0/8hVU5ccDudAo4P43J7GjAIU6XDWj9ZpXyiZme9 M3iRFhpF+4vZHo+I4iUtAjEakqhgHK0i7J/bPhpuNmBC/cA5NLyQSrCKLyCEe3NZU8 IghAyW2WG9QZcQxmLVLwLc6pSSP0i2E8G7DD1OQc= From: Kieran Bingham To: dri-devel@lists.freedesktop.org, linux-renesas-soc@vger.kernel.org Cc: Andrzej Hajda , Neil Armstrong , Robert Foss , Laurent Pinchart , Jonas Karlman , Jernej Skrabec , David Airlie , Daniel Vetter , Kieran Bingham , Laurent Pinchart Subject: [PATCH v2 4/4] drm/bridge: ti-sn65dsi86: Support hotplug detection Date: Mon, 7 Mar 2022 17:59:55 +0000 Message-Id: <20220307175955.363057-5-kieran.bingham+renesas@ideasonboard.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20220307175955.363057-1-kieran.bingham+renesas@ideasonboard.com> References: <20220307175955.363057-1-kieran.bingham+renesas@ideasonboard.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-renesas-soc@vger.kernel.org When the SN65DSI86 is used in DisplayPort mode, its output is likely routed to a DisplayPort connector, which can benefit from hotplug detection. Support it in such cases, with polling mode only for now. The implementation is limited to the bridge operations, as the connector operations are legacy and new users should use DRM_BRIDGE_ATTACH_NO_CONNECTOR. Signed-off-by: Laurent Pinchart Signed-off-by: Kieran Bingham --- Changes since v1: - Document the no_hpd field - Rely on the SN_HPD_DISABLE_REG default value in the HPD case - Add a TODO comment regarding IRQ support [Kieran] - Fix spelling s/assrted/asserted/ - Only enable HPD on DisplayPort connector. - Support IRQ based hotplug detect --- drivers/gpu/drm/bridge/ti-sn65dsi86.c | 133 +++++++++++++++++++++++--- 1 file changed, 120 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi86.c b/drivers/gpu/drm/bridge/ti-sn65dsi86.c index 461f963faa0b..febb4e672ece 100644 --- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c +++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c @@ -68,6 +68,7 @@ #define BPP_18_RGB BIT(0) #define SN_HPD_DISABLE_REG 0x5C #define HPD_DISABLE BIT(0) +#define HPD_DEBOUNCED_STATE BIT(4) #define SN_GPIO_IO_REG 0x5E #define SN_GPIO_INPUT_SHIFT 4 #define SN_GPIO_OUTPUT_SHIFT 0 @@ -104,10 +105,24 @@ #define SN_PWM_EN_INV_REG 0xA5 #define SN_PWM_INV_MASK BIT(0) #define SN_PWM_EN_MASK BIT(1) +#define SN_IRQ_EN_REG 0xE0 +#define IRQ_EN BIT(0) +#define SN_IRQ_HPD_REG 0xE6 +#define IRQ_HPD_EN BIT(0) +#define IRQ_HPD_INSERTION_EN BIT(1) +#define IRQ_HPD_REMOVAL_EN BIT(2) +#define IRQ_HPD_REPLUG_EN BIT(3) +#define IRQ_HPD_PLL_UNLOCK_EN BIT(5) #define SN_AUX_CMD_STATUS_REG 0xF4 #define AUX_IRQ_STATUS_AUX_RPLY_TOUT BIT(3) #define AUX_IRQ_STATUS_AUX_SHORT BIT(5) #define AUX_IRQ_STATUS_NAT_I2C_FAIL BIT(6) +#define SN_IRQ_HPD_STATUS_REG 0xF5 +#define IRQ_HPD_STATUS BIT(0) +#define IRQ_HPD_INSERTION_STATUS BIT(1) +#define IRQ_HPD_REMOVAL_STATUS BIT(2) +#define IRQ_HPD_REPLUG_STATUS BIT(3) +#define IRQ_PLL_UNLOCK BIT(5) #define MIN_DSI_CLK_FREQ_MHZ 40 @@ -166,6 +181,11 @@ * @pwm_enabled: Used to track if the PWM signal is currently enabled. * @pwm_pin_busy: Track if GPIO4 is currently requested for GPIO or PWM. * @pwm_refclk_freq: Cache for the reference clock input to the PWM. + * + * @no_hpd: Disable hot-plug detection as instructed by device tree (used + * for instance for eDP panels whose HPD signal won't be asserted + * until the panel is turned on, and is thus not usable for + * downstream device detection). */ struct ti_sn65dsi86 { struct auxiliary_device bridge_aux; @@ -200,6 +220,8 @@ struct ti_sn65dsi86 { atomic_t pwm_pin_busy; #endif unsigned int pwm_refclk_freq; + + bool no_hpd; }; static const struct regmap_range ti_sn65dsi86_volatile_ranges[] = { @@ -314,23 +336,25 @@ static void ti_sn65dsi86_enable_comms(struct ti_sn65dsi86 *pdata) ti_sn_bridge_set_refclk_freq(pdata); /* - * HPD on this bridge chip is a bit useless. This is an eDP bridge - * so the HPD is an internal signal that's only there to signal that - * the panel is done powering up. ...but the bridge chip debounces - * this signal by between 100 ms and 400 ms (depending on process, - * voltage, and temperate--I measured it at about 200 ms). One + * As this is an eDP bridge, the output will be connected to a fixed + * panel in most systems. HPD is in that case only an internal signal + * to signal that the panel is done powering up. The bridge chip + * debounces this signal by between 100 ms and 400 ms (depending on + * process, voltage, and temperate--I measured it at about 200 ms). One * particular panel asserted HPD 84 ms after it was powered on meaning * that we saw HPD 284 ms after power on. ...but the same panel said * that instead of looking at HPD you could just hardcode a delay of - * 200 ms. We'll assume that the panel driver will have the hardcoded - * delay in its prepare and always disable HPD. + * 200 ms. HPD is thus a bit useless. For this type of use cases, we'll + * assume that the panel driver will have the hardcoded delay in its + * prepare and always disable HPD. * - * If HPD somehow makes sense on some future panel we'll have to - * change this to be conditional on someone specifying that HPD should - * be used. + * However, on some systems, the output is connected to a DisplayPort + * connector. HPD is needed in such cases. To accommodate both use + * cases, enable HPD only when requested. */ - regmap_update_bits(pdata->regmap, SN_HPD_DISABLE_REG, HPD_DISABLE, - HPD_DISABLE); + if (pdata->no_hpd) + regmap_update_bits(pdata->regmap, SN_HPD_DISABLE_REG, + HPD_DISABLE, HPD_DISABLE); pdata->comms_enabled = true; @@ -1164,6 +1188,36 @@ static void ti_sn_bridge_post_disable(struct drm_bridge *bridge) pm_runtime_put_sync(pdata->dev); } +static enum drm_connector_status ti_sn_bridge_detect(struct drm_bridge *bridge) +{ + struct ti_sn65dsi86 *pdata = bridge_to_ti_sn65dsi86(bridge); + int val; + + regmap_read(pdata->regmap, SN_HPD_DISABLE_REG, &val); + + return val & HPD_DEBOUNCED_STATE ? connector_status_connected + : connector_status_disconnected; +} + +static void ti_sn_bridge_hpd_enable(struct drm_bridge *bridge) +{ + struct ti_sn65dsi86 *pdata = bridge_to_ti_sn65dsi86(bridge); + + /* The device must remain active for HPD to function */ + pm_runtime_get_sync(pdata->dev); + regmap_write(pdata->regmap, SN_IRQ_HPD_REG, + IRQ_HPD_EN | IRQ_HPD_INSERTION_EN | + IRQ_HPD_REMOVAL_EN | IRQ_HPD_REPLUG_EN); +} + +static void ti_sn_bridge_hpd_disable(struct drm_bridge *bridge) +{ + struct ti_sn65dsi86 *pdata = bridge_to_ti_sn65dsi86(bridge); + + regmap_write(pdata->regmap, SN_IRQ_HPD_REG, 0); + pm_runtime_put_autosuspend(pdata->dev); +} + static struct edid *ti_sn_bridge_get_edid(struct drm_bridge *bridge, struct drm_connector *connector) { @@ -1185,6 +1239,9 @@ static const struct drm_bridge_funcs ti_sn_bridge_funcs = { .enable = ti_sn_bridge_enable, .disable = ti_sn_bridge_disable, .post_disable = ti_sn_bridge_post_disable, + .detect = ti_sn_bridge_detect, + .hpd_enable = ti_sn_bridge_hpd_enable, + .hpd_disable = ti_sn_bridge_hpd_disable, .get_edid = ti_sn_bridge_get_edid, }; @@ -1264,6 +1321,14 @@ static int ti_sn_bridge_probe(struct auxiliary_device *adev, return PTR_ERR(pdata->next_bridge); } + pdata->no_hpd = of_property_read_bool(np, "no-hpd"); + if (pdata->next_bridge->type != DRM_MODE_CONNECTOR_DisplayPort && + !pdata->no_hpd) { + dev_warn(pdata->dev, + "HPD support requires a DisplayPort connector\n"); + pdata->no_hpd = true; + } + ti_sn_bridge_parse_lanes(pdata, np); ret = ti_sn_bridge_parse_dsi_host(pdata); @@ -1272,7 +1337,8 @@ static int ti_sn_bridge_probe(struct auxiliary_device *adev, pdata->bridge.funcs = &ti_sn_bridge_funcs; pdata->bridge.of_node = np; - pdata->bridge.ops = DRM_BRIDGE_OP_EDID; + pdata->bridge.ops = (pdata->no_hpd ? 0 : DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_HPD) + | DRM_BRIDGE_OP_EDID; pdata->bridge.type = pdata->next_bridge->type == DRM_MODE_CONNECTOR_DisplayPort ? DRM_MODE_CONNECTOR_DisplayPort : DRM_MODE_CONNECTOR_eDP; @@ -1840,6 +1906,34 @@ static int ti_sn65dsi86_parse_regulators(struct ti_sn65dsi86 *pdata) pdata->supplies); } +static irqreturn_t ti_sn65dsi86_irq_handler(int irq, void *arg) +{ + struct ti_sn65dsi86 *pdata = arg; + int ret; + int hpd; + + ret = regmap_read(pdata->regmap, SN_IRQ_HPD_STATUS_REG, &hpd); + if (ret || !hpd) + return IRQ_NONE; + + if (hpd & IRQ_HPD_INSERTION_STATUS) + drm_bridge_hpd_notify(&pdata->bridge, connector_status_connected); + + if (hpd & IRQ_HPD_REMOVAL_STATUS) + drm_bridge_hpd_notify(&pdata->bridge, connector_status_disconnected); + + /* When replugged, ensure we trigger a detect to update the display */ + if (hpd & IRQ_HPD_REPLUG_STATUS) + drm_bridge_hpd_notify(&pdata->bridge, connector_status_disconnected); + + /* reset the status registers */ + regmap_write(pdata->regmap, SN_IRQ_HPD_STATUS_REG, + IRQ_HPD_STATUS | IRQ_HPD_INSERTION_STATUS | + IRQ_HPD_REMOVAL_STATUS | IRQ_HPD_REPLUG_STATUS); + + return IRQ_HANDLED; +} + static int ti_sn65dsi86_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -1881,6 +1975,16 @@ static int ti_sn65dsi86_probe(struct i2c_client *client, return dev_err_probe(dev, PTR_ERR(pdata->refclk), "failed to get reference clock\n"); + if (client->irq > 0) { + ret = devm_request_threaded_irq(dev, client->irq, NULL, + ti_sn65dsi86_irq_handler, + IRQF_ONESHOT, "sn65dsi86-irq", + pdata); + if (ret) + return dev_err_probe(dev, ret, + "Failed to register DP interrupt\n"); + } + pm_runtime_enable(dev); ret = devm_add_action_or_reset(dev, ti_sn65dsi86_runtime_disable, dev); if (ret) @@ -1888,6 +1992,9 @@ static int ti_sn65dsi86_probe(struct i2c_client *client, pm_runtime_set_autosuspend_delay(pdata->dev, 500); pm_runtime_use_autosuspend(pdata->dev); + /* Enable interrupt handling */ + regmap_write(pdata->regmap, SN_IRQ_EN_REG, IRQ_EN); + ti_sn65dsi86_debugfs_init(pdata); /*