From patchwork Mon Jul 17 14:14:28 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AngeloGioacchino Del Regno X-Patchwork-Id: 13316476 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org From: AngeloGioacchino Del Regno Subject: [PATCH v6 01/11] drm/mediatek: dp: Add missing error checks in mtk_dp_parse_capabilities Date: Mon, 17 Jul 2023 16:14:28 +0200 Message-Id: <20230717141438.274419-2-angelogioacchino.delregno@collabora.com> In-Reply-To: <20230717141438.274419-1-angelogioacchino.delregno@collabora.com> References: <20230717141438.274419-1-angelogioacchino.delregno@collabora.com> MIME-Version: 1.0 List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+lwn-linux-arm-kernel=archive.lwn.net@lists.infradead.org List-Archive: To: chunkuang.hu@kernel.org Cc: p.zabel@pengutronix.de, airlied@gmail.com, daniel@ffwll.ch, matthias.bgg@gmail.com, angelogioacchino.delregno@collabora.com, dri-devel@lists.freedesktop.org, linux-mediatek@lists.infradead.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, kernel@collabora.com, wenst@chromium.org, nfraprado@collabora.com If reading the RX capabilities fails the training pattern will be set wrongly: add error checking for drm_dp_read_dpcd_caps() and return if anything went wrong with it. While at it, also add a less critical error check when writing to clear the ESI0 IRQ vector. Fixes: f70ac097a2cf ("drm/mediatek: Add MT8195 Embedded DisplayPort driver") Signed-off-by: AngeloGioacchino Del Regno Reviewed-by: Alexandre Mergnat --- drivers/gpu/drm/mediatek/mtk_dp.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_dp.c b/drivers/gpu/drm/mediatek/mtk_dp.c index 64eee77452c0..c58b775877a3 100644 --- a/drivers/gpu/drm/mediatek/mtk_dp.c +++ b/drivers/gpu/drm/mediatek/mtk_dp.c @@ -1588,7 +1588,9 @@ static int mtk_dp_parse_capabilities(struct mtk_dp *mtk_dp) u8 val; ssize_t ret; - drm_dp_read_dpcd_caps(&mtk_dp->aux, mtk_dp->rx_cap); + ret = drm_dp_read_dpcd_caps(&mtk_dp->aux, mtk_dp->rx_cap); + if (ret < 0) + return ret; if (drm_dp_tps4_supported(mtk_dp->rx_cap)) mtk_dp->train_info.channel_eq_pattern = DP_TRAINING_PATTERN_4; @@ -1615,10 +1617,13 @@ static int mtk_dp_parse_capabilities(struct mtk_dp *mtk_dp) return ret == 0 ? -EIO : ret; } - if (val) - drm_dp_dpcd_writeb(&mtk_dp->aux, - DP_DEVICE_SERVICE_IRQ_VECTOR_ESI0, - val); + if (val) { + ret = drm_dp_dpcd_writeb(&mtk_dp->aux, + DP_DEVICE_SERVICE_IRQ_VECTOR_ESI0, + val); + if (ret < 0) + return ret; + } } return 0; From patchwork Mon Jul 17 14:14:29 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AngeloGioacchino Del Regno X-Patchwork-Id: 13316479 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org From: AngeloGioacchino Del Regno Subject: [PATCH v6 02/11] drm/mediatek: dp: Move AUX and panel poweron/off sequence to function Date: Mon, 17 Jul 2023 16:14:29 +0200 Message-Id: <20230717141438.274419-3-angelogioacchino.delregno@collabora.com> In-Reply-To: <20230717141438.274419-1-angelogioacchino.delregno@collabora.com> References: <20230717141438.274419-1-angelogioacchino.delregno@collabora.com> MIME-Version: 1.0 List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+lwn-linux-arm-kernel=archive.lwn.net@lists.infradead.org List-Archive: To: chunkuang.hu@kernel.org Cc: p.zabel@pengutronix.de, airlied@gmail.com, daniel@ffwll.ch, matthias.bgg@gmail.com, angelogioacchino.delregno@collabora.com, dri-devel@lists.freedesktop.org, linux-mediatek@lists.infradead.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, kernel@collabora.com, wenst@chromium.org, nfraprado@collabora.com Everytime we run bridge detection and/or EDID read we run a poweron and poweroff sequence for both the AUX and the panel; moreover, this is also done when enabling the bridge in the .atomic_enable() callback. Move this power on/off sequence to a new mtk_dp_aux_panel_poweron() function as to commonize it. Note that, before this commit, in mtk_dp_bridge_atomic_enable() only the AUX was getting powered on but the panel was left powered off if the DP cable wasn't plugged in while now we unconditionally send a D0 request and this is done for two reasons: - First, whether this request fails or not, it takes the same time and anyway the DP hardware won't produce any error (or, if it does, it's ignorable because it won't block further commands) - Second, training the link between a sleeping/standby/unpowered display makes little sense. Signed-off-by: AngeloGioacchino Del Regno Tested-by: Chen-Yu Tsai Reviewed-by: Alexandre Mergnat --- drivers/gpu/drm/mediatek/mtk_dp.c | 76 ++++++++++++------------------- 1 file changed, 30 insertions(+), 46 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_dp.c b/drivers/gpu/drm/mediatek/mtk_dp.c index c58b775877a3..77da0d002e9f 100644 --- a/drivers/gpu/drm/mediatek/mtk_dp.c +++ b/drivers/gpu/drm/mediatek/mtk_dp.c @@ -1251,6 +1251,29 @@ static void mtk_dp_audio_mute(struct mtk_dp *mtk_dp, bool mute) val[2], AU_TS_CFG_DP_ENC0_P0_MASK); } +static void mtk_dp_aux_panel_poweron(struct mtk_dp *mtk_dp, bool pwron) +{ + if (pwron) { + /* power on aux */ + mtk_dp_update_bits(mtk_dp, MTK_DP_TOP_PWR_STATE, + DP_PWR_STATE_BANDGAP_TPLL_LANE, + DP_PWR_STATE_MASK); + + /* power on panel */ + drm_dp_dpcd_writeb(&mtk_dp->aux, DP_SET_POWER, DP_SET_POWER_D0); + usleep_range(2000, 5000); + } else { + /* power off panel */ + drm_dp_dpcd_writeb(&mtk_dp->aux, DP_SET_POWER, DP_SET_POWER_D3); + usleep_range(2000, 3000); + + /* power off aux */ + mtk_dp_update_bits(mtk_dp, MTK_DP_TOP_PWR_STATE, + DP_PWR_STATE_BANDGAP_TPLL, + DP_PWR_STATE_MASK); + } +} + static void mtk_dp_power_enable(struct mtk_dp *mtk_dp) { mtk_dp_update_bits(mtk_dp, MTK_DP_TOP_RESET_AND_PROBE, @@ -1941,16 +1964,9 @@ static enum drm_connector_status mtk_dp_bdg_detect(struct drm_bridge *bridge) if (!mtk_dp->train_info.cable_plugged_in) return ret; - if (!enabled) { - /* power on aux */ - mtk_dp_update_bits(mtk_dp, MTK_DP_TOP_PWR_STATE, - DP_PWR_STATE_BANDGAP_TPLL_LANE, - DP_PWR_STATE_MASK); + if (!enabled) + mtk_dp_aux_panel_poweron(mtk_dp, true); - /* power on panel */ - drm_dp_dpcd_writeb(&mtk_dp->aux, DP_SET_POWER, DP_SET_POWER_D0); - usleep_range(2000, 5000); - } /* * Some dongles still source HPD when they do not connect to any * sink device. To avoid this, we need to read the sink count @@ -1962,16 +1978,8 @@ static enum drm_connector_status mtk_dp_bdg_detect(struct drm_bridge *bridge) if (DP_GET_SINK_COUNT(sink_count)) ret = connector_status_connected; - if (!enabled) { - /* power off panel */ - drm_dp_dpcd_writeb(&mtk_dp->aux, DP_SET_POWER, DP_SET_POWER_D3); - usleep_range(2000, 3000); - - /* power off aux */ - mtk_dp_update_bits(mtk_dp, MTK_DP_TOP_PWR_STATE, - DP_PWR_STATE_BANDGAP_TPLL, - DP_PWR_STATE_MASK); - } + if (!enabled) + mtk_dp_aux_panel_poweron(mtk_dp, false); return ret; } @@ -1987,15 +1995,7 @@ static struct edid *mtk_dp_get_edid(struct drm_bridge *bridge, if (!enabled) { drm_atomic_bridge_chain_pre_enable(bridge, connector->state->state); - - /* power on aux */ - mtk_dp_update_bits(mtk_dp, MTK_DP_TOP_PWR_STATE, - DP_PWR_STATE_BANDGAP_TPLL_LANE, - DP_PWR_STATE_MASK); - - /* power on panel */ - drm_dp_dpcd_writeb(&mtk_dp->aux, DP_SET_POWER, DP_SET_POWER_D0); - usleep_range(2000, 5000); + mtk_dp_aux_panel_poweron(mtk_dp, true); } new_edid = drm_get_edid(connector, &mtk_dp->aux.ddc); @@ -2015,15 +2015,7 @@ static struct edid *mtk_dp_get_edid(struct drm_bridge *bridge, } if (!enabled) { - /* power off panel */ - drm_dp_dpcd_writeb(&mtk_dp->aux, DP_SET_POWER, DP_SET_POWER_D3); - usleep_range(2000, 3000); - - /* power off aux */ - mtk_dp_update_bits(mtk_dp, MTK_DP_TOP_PWR_STATE, - DP_PWR_STATE_BANDGAP_TPLL, - DP_PWR_STATE_MASK); - + mtk_dp_aux_panel_poweron(mtk_dp, false); drm_atomic_bridge_chain_post_disable(bridge, connector->state->state); } @@ -2183,15 +2175,7 @@ static void mtk_dp_bridge_atomic_enable(struct drm_bridge *bridge, return; } - /* power on aux */ - mtk_dp_update_bits(mtk_dp, MTK_DP_TOP_PWR_STATE, - DP_PWR_STATE_BANDGAP_TPLL_LANE, - DP_PWR_STATE_MASK); - - if (mtk_dp->train_info.cable_plugged_in) { - drm_dp_dpcd_writeb(&mtk_dp->aux, DP_SET_POWER, DP_SET_POWER_D0); - usleep_range(2000, 5000); - } + mtk_dp_aux_panel_poweron(mtk_dp, true); /* Training */ ret = mtk_dp_training(mtk_dp); From patchwork Mon Jul 17 14:14:30 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AngeloGioacchino Del Regno X-Patchwork-Id: 13316477 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org From: AngeloGioacchino Del Regno Subject: [PATCH v6 03/11] drm/mediatek: dp: Change logging to dev for mtk_dp_aux_transfer() Date: Mon, 17 Jul 2023 16:14:30 +0200 Message-Id: <20230717141438.274419-4-angelogioacchino.delregno@collabora.com> In-Reply-To: <20230717141438.274419-1-angelogioacchino.delregno@collabora.com> References: <20230717141438.274419-1-angelogioacchino.delregno@collabora.com> MIME-Version: 1.0 List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+lwn-linux-arm-kernel=archive.lwn.net@lists.infradead.org List-Archive: To: chunkuang.hu@kernel.org Cc: p.zabel@pengutronix.de, airlied@gmail.com, daniel@ffwll.ch, matthias.bgg@gmail.com, angelogioacchino.delregno@collabora.com, dri-devel@lists.freedesktop.org, linux-mediatek@lists.infradead.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, kernel@collabora.com, wenst@chromium.org, nfraprado@collabora.com Change logging from drm_{err,info}() to dev_{err,info}() in functions mtk_dp_aux_transfer() and mtk_dp_aux_do_transfer(): this will be essential to avoid getting NULL pointer kernel panics if any kind of error happens during AUX transfers happening before the bridge is attached. This may potentially start happening in a later commit implementing aux-bus support, as AUX transfers will be triggered from the panel driver (for EDID) before the mtk-dp bridge gets attached, and it's done in preparation for the same. Signed-off-by: AngeloGioacchino Del Regno Tested-by: Chen-Yu Tsai Reviewed-by: Alexandre Mergnat --- drivers/gpu/drm/mediatek/mtk_dp.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_dp.c b/drivers/gpu/drm/mediatek/mtk_dp.c index 77da0d002e9f..98f63d8230e4 100644 --- a/drivers/gpu/drm/mediatek/mtk_dp.c +++ b/drivers/gpu/drm/mediatek/mtk_dp.c @@ -847,7 +847,7 @@ static int mtk_dp_aux_do_transfer(struct mtk_dp *mtk_dp, bool is_read, u8 cmd, u32 phy_status = mtk_dp_read(mtk_dp, MTK_DP_AUX_P0_3628) & AUX_RX_PHY_STATE_AUX_TX_P0_MASK; if (phy_status != AUX_RX_PHY_STATE_AUX_TX_P0_RX_IDLE) { - drm_err(mtk_dp->drm_dev, + dev_err(mtk_dp->dev, "AUX Rx Aux hang, need SW reset\n"); return -EIO; } @@ -2054,7 +2054,7 @@ static ssize_t mtk_dp_aux_transfer(struct drm_dp_aux *mtk_aux, is_read = true; break; default: - drm_err(mtk_aux->drm_dev, "invalid aux cmd = %d\n", + dev_err(mtk_dp->dev, "invalid aux cmd = %d\n", msg->request); ret = -EINVAL; goto err; @@ -2070,7 +2070,7 @@ static ssize_t mtk_dp_aux_transfer(struct drm_dp_aux *mtk_aux, to_access, &msg->reply); if (ret) { - drm_info(mtk_dp->drm_dev, + dev_info(mtk_dp->dev, "Failed to do AUX transfer: %d\n", ret); goto err; } From patchwork Mon Jul 17 14:14:31 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AngeloGioacchino Del Regno X-Patchwork-Id: 13316480 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org From: AngeloGioacchino Del Regno Subject: [PATCH v6 04/11] drm/mediatek: dp: Use devm variant of drm_bridge_add() Date: Mon, 17 Jul 2023 16:14:31 +0200 Message-Id: <20230717141438.274419-5-angelogioacchino.delregno@collabora.com> In-Reply-To: <20230717141438.274419-1-angelogioacchino.delregno@collabora.com> References: <20230717141438.274419-1-angelogioacchino.delregno@collabora.com> MIME-Version: 1.0 List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+lwn-linux-arm-kernel=archive.lwn.net@lists.infradead.org List-Archive: To: chunkuang.hu@kernel.org Cc: p.zabel@pengutronix.de, airlied@gmail.com, daniel@ffwll.ch, matthias.bgg@gmail.com, angelogioacchino.delregno@collabora.com, dri-devel@lists.freedesktop.org, linux-mediatek@lists.infradead.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, kernel@collabora.com, wenst@chromium.org, nfraprado@collabora.com In preparation for adding support for aux-bus, which will add a code path that may fail after the drm_bridge_add() call, change that to devm_drm_bridge_add() to simplify failure paths later. Signed-off-by: AngeloGioacchino Del Regno Tested-by: Chen-Yu Tsai Reviewed-by: Alexandre Mergnat --- drivers/gpu/drm/mediatek/mtk_dp.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_dp.c b/drivers/gpu/drm/mediatek/mtk_dp.c index 98f63d8230e4..fc6cabf5370b 100644 --- a/drivers/gpu/drm/mediatek/mtk_dp.c +++ b/drivers/gpu/drm/mediatek/mtk_dp.c @@ -2552,7 +2552,9 @@ static int mtk_dp_probe(struct platform_device *pdev) DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID | DRM_BRIDGE_OP_HPD; mtk_dp->bridge.type = mtk_dp->data->bridge_type; - drm_bridge_add(&mtk_dp->bridge); + ret = devm_drm_bridge_add(dev, &mtk_dp->bridge); + if (ret) + return dev_err_probe(dev, ret, "Failed to add bridge\n"); mtk_dp->need_debounce = true; timer_setup(&mtk_dp->debounce_timer, mtk_dp_debounce_timer, 0); @@ -2570,7 +2572,6 @@ static int mtk_dp_remove(struct platform_device *pdev) pm_runtime_put(&pdev->dev); pm_runtime_disable(&pdev->dev); del_timer_sync(&mtk_dp->debounce_timer); - drm_bridge_remove(&mtk_dp->bridge); platform_device_unregister(mtk_dp->phy_dev); if (mtk_dp->audio_pdev) platform_device_unregister(mtk_dp->audio_pdev); From patchwork Mon Jul 17 14:14:32 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AngeloGioacchino Del Regno X-Patchwork-Id: 13316487 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org From: AngeloGioacchino Del Regno Subject: [PATCH v6 05/11] drm/mediatek: dp: Move AUX_P0 setting to mtk_dp_initialize_aux_settings() Date: Mon, 17 Jul 2023 16:14:32 +0200 Message-Id: <20230717141438.274419-6-angelogioacchino.delregno@collabora.com> In-Reply-To: <20230717141438.274419-1-angelogioacchino.delregno@collabora.com> References: <20230717141438.274419-1-angelogioacchino.delregno@collabora.com> MIME-Version: 1.0 List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+lwn-linux-arm-kernel=archive.lwn.net@lists.infradead.org List-Archive: To: chunkuang.hu@kernel.org Cc: p.zabel@pengutronix.de, airlied@gmail.com, daniel@ffwll.ch, matthias.bgg@gmail.com, angelogioacchino.delregno@collabora.com, dri-devel@lists.freedesktop.org, linux-mediatek@lists.infradead.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, kernel@collabora.com, wenst@chromium.org, nfraprado@collabora.com Move the register write to MTK_DP_AUX_P0_3690 to set the AUX reply mode to function mtk_dp_initialize_aux_settings(), as this is effectively part of the DPTX AUX setup sequence. Signed-off-by: AngeloGioacchino Del Regno Tested-by: Chen-Yu Tsai Reviewed-by: CK Hu Reviewed-by: Alexandre Mergnat --- drivers/gpu/drm/mediatek/mtk_dp.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_dp.c b/drivers/gpu/drm/mediatek/mtk_dp.c index fc6cabf5370b..e8d3bf310608 100644 --- a/drivers/gpu/drm/mediatek/mtk_dp.c +++ b/drivers/gpu/drm/mediatek/mtk_dp.c @@ -1009,6 +1009,11 @@ static void mtk_dp_initialize_aux_settings(struct mtk_dp *mtk_dp) mtk_dp_update_bits(mtk_dp, MTK_DP_AUX_P0_37C8, MTK_ATOP_EN_AUX_TX_P0, MTK_ATOP_EN_AUX_TX_P0); + + /* Set complete reply mode for AUX */ + mtk_dp_update_bits(mtk_dp, MTK_DP_AUX_P0_3690, + RX_REPLY_COMPLETE_MODE_AUX_TX_P0, + RX_REPLY_COMPLETE_MODE_AUX_TX_P0); } static void mtk_dp_initialize_digital_settings(struct mtk_dp *mtk_dp) @@ -1826,10 +1831,6 @@ static void mtk_dp_init_port(struct mtk_dp *mtk_dp) mtk_dp_initialize_settings(mtk_dp); mtk_dp_initialize_aux_settings(mtk_dp); mtk_dp_initialize_digital_settings(mtk_dp); - - mtk_dp_update_bits(mtk_dp, MTK_DP_AUX_P0_3690, - RX_REPLY_COMPLETE_MODE_AUX_TX_P0, - RX_REPLY_COMPLETE_MODE_AUX_TX_P0); mtk_dp_initialize_hpd_detect_settings(mtk_dp); mtk_dp_digital_sw_reset(mtk_dp); From patchwork Mon Jul 17 14:14:33 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AngeloGioacchino Del Regno X-Patchwork-Id: 13316486 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org From: AngeloGioacchino Del Regno Subject: [PATCH v6 06/11] drm/mediatek: dp: Enable event interrupt only when bridge attached Date: Mon, 17 Jul 2023 16:14:33 +0200 Message-Id: <20230717141438.274419-7-angelogioacchino.delregno@collabora.com> In-Reply-To: <20230717141438.274419-1-angelogioacchino.delregno@collabora.com> References: <20230717141438.274419-1-angelogioacchino.delregno@collabora.com> MIME-Version: 1.0 List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+lwn-linux-arm-kernel=archive.lwn.net@lists.infradead.org List-Archive: To: chunkuang.hu@kernel.org Cc: p.zabel@pengutronix.de, airlied@gmail.com, daniel@ffwll.ch, matthias.bgg@gmail.com, angelogioacchino.delregno@collabora.com, dri-devel@lists.freedesktop.org, linux-mediatek@lists.infradead.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, kernel@collabora.com, wenst@chromium.org, nfraprado@collabora.com It is useless and error-prone to enable the DisplayPort event interrupt before finishing to probe and install the driver, as the DP training cannot happen before the entire pipeline is correctly set up, as the interrupt handler also requires the full hardware to be initialized by mtk_dp_bridge_attach(). Anyway, depending in which state the controller is left from the bootloader, this may cause an interrupt storm and consequently hang the kernel during boot, so, avoid enabling the interrupt until we reach a clean state by adding the IRQ_NOAUTOEN flag before requesting it at probe time and manage the enablement of the ISR in the .attach() and .detach() handlers for the DP bridge. Signed-off-by: AngeloGioacchino Del Regno Tested-by: Chen-Yu Tsai Reviewed-by: Alexandre Mergnat --- drivers/gpu/drm/mediatek/mtk_dp.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_dp.c b/drivers/gpu/drm/mediatek/mtk_dp.c index e8d3bf310608..83e55f8dc84a 100644 --- a/drivers/gpu/drm/mediatek/mtk_dp.c +++ b/drivers/gpu/drm/mediatek/mtk_dp.c @@ -100,6 +100,7 @@ struct mtk_dp_efuse_fmt { struct mtk_dp { bool enabled; bool need_debounce; + int irq; u8 max_lanes; u8 max_linkrate; u8 rx_cap[DP_RECEIVER_CAP_SIZE]; @@ -2141,6 +2142,8 @@ static int mtk_dp_bridge_attach(struct drm_bridge *bridge, mtk_dp->drm_dev = bridge->dev; + irq_clear_status_flags(mtk_dp->irq, IRQ_NOAUTOEN); + enable_irq(mtk_dp->irq); mtk_dp_hwirq_enable(mtk_dp, true); return 0; @@ -2157,6 +2160,7 @@ static void mtk_dp_bridge_detach(struct drm_bridge *bridge) struct mtk_dp *mtk_dp = mtk_dp_from_bridge(bridge); mtk_dp_hwirq_enable(mtk_dp, false); + disable_irq(mtk_dp->irq); mtk_dp->drm_dev = NULL; mtk_dp_poweroff(mtk_dp); drm_dp_aux_unregister(&mtk_dp->aux); @@ -2475,7 +2479,7 @@ static int mtk_dp_probe(struct platform_device *pdev) { struct mtk_dp *mtk_dp; struct device *dev = &pdev->dev; - int ret, irq_num; + int ret; mtk_dp = devm_kzalloc(dev, sizeof(*mtk_dp), GFP_KERNEL); if (!mtk_dp) @@ -2484,9 +2488,9 @@ static int mtk_dp_probe(struct platform_device *pdev) mtk_dp->dev = dev; mtk_dp->data = (struct mtk_dp_data *)of_device_get_match_data(dev); - irq_num = platform_get_irq(pdev, 0); - if (irq_num < 0) - return dev_err_probe(dev, irq_num, + mtk_dp->irq = platform_get_irq(pdev, 0); + if (mtk_dp->irq < 0) + return dev_err_probe(dev, mtk_dp->irq, "failed to request dp irq resource\n"); mtk_dp->next_bridge = devm_drm_of_get_bridge(dev, dev->of_node, 1, 0); @@ -2507,7 +2511,8 @@ static int mtk_dp_probe(struct platform_device *pdev) spin_lock_init(&mtk_dp->irq_thread_lock); - ret = devm_request_threaded_irq(dev, irq_num, mtk_dp_hpd_event, + irq_set_status_flags(mtk_dp->irq, IRQ_NOAUTOEN); + ret = devm_request_threaded_irq(dev, mtk_dp->irq, mtk_dp_hpd_event, mtk_dp_hpd_event_thread, IRQ_TYPE_LEVEL_HIGH, dev_name(dev), mtk_dp); From patchwork Mon Jul 17 14:14:34 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AngeloGioacchino Del Regno X-Patchwork-Id: 13316481 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org From: AngeloGioacchino Del Regno Subject: [PATCH v6 07/11] drm/mediatek: dp: Avoid mutex locks if audio is not supported/enabled Date: Mon, 17 Jul 2023 16:14:34 +0200 Message-Id: <20230717141438.274419-8-angelogioacchino.delregno@collabora.com> In-Reply-To: <20230717141438.274419-1-angelogioacchino.delregno@collabora.com> References: <20230717141438.274419-1-angelogioacchino.delregno@collabora.com> MIME-Version: 1.0 List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+lwn-linux-arm-kernel=archive.lwn.net@lists.infradead.org List-Archive: To: chunkuang.hu@kernel.org Cc: p.zabel@pengutronix.de, airlied@gmail.com, daniel@ffwll.ch, matthias.bgg@gmail.com, angelogioacchino.delregno@collabora.com, dri-devel@lists.freedesktop.org, linux-mediatek@lists.infradead.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, kernel@collabora.com, wenst@chromium.org, nfraprado@collabora.com If a controller (usually, eDP!) does not support audio, or audio is not enabled because the endpoint has no audio support, it's useless to lock a mutex only to unlock it right after because there's no .plugged_cb(). Check if the audio is supported and enabled before locking the mutex in mtk_dp_update_plugged_status(): if not, we simply return immediately. While at it, since the update_plugged_status_lock mutex would not be used if the controller doesn't support audio at all, initialize it only if `audio_supported` is true. Signed-off-by: AngeloGioacchino Del Regno Reviewed-by: Alexandre Mergnat --- drivers/gpu/drm/mediatek/mtk_dp.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_dp.c b/drivers/gpu/drm/mediatek/mtk_dp.c index 83e55f8dc84a..c1d1a882f1db 100644 --- a/drivers/gpu/drm/mediatek/mtk_dp.c +++ b/drivers/gpu/drm/mediatek/mtk_dp.c @@ -1948,6 +1948,9 @@ static int mtk_dp_dt_parse(struct mtk_dp *mtk_dp, static void mtk_dp_update_plugged_status(struct mtk_dp *mtk_dp) { + if (!mtk_dp->data->audio_supported || !mtk_dp->audio_enable) + return; + mutex_lock(&mtk_dp->update_plugged_status_lock); if (mtk_dp->plugged_cb && mtk_dp->codec_dev) mtk_dp->plugged_cb(mtk_dp->codec_dev, @@ -2520,11 +2523,11 @@ static int mtk_dp_probe(struct platform_device *pdev) return dev_err_probe(dev, ret, "failed to request mediatek dptx irq\n"); - mutex_init(&mtk_dp->update_plugged_status_lock); - platform_set_drvdata(pdev, mtk_dp); if (mtk_dp->data->audio_supported) { + mutex_init(&mtk_dp->update_plugged_status_lock); + ret = mtk_dp_register_audio_driver(dev); if (ret) { dev_err(dev, "Failed to register audio driver: %d\n", From patchwork Mon Jul 17 14:14:35 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AngeloGioacchino Del Regno X-Patchwork-Id: 13316485 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org From: AngeloGioacchino Del Regno Subject: [PATCH v6 08/11] drm/mediatek: dp: Move PHY registration to new function Date: Mon, 17 Jul 2023 16:14:35 +0200 Message-Id: <20230717141438.274419-9-angelogioacchino.delregno@collabora.com> In-Reply-To: <20230717141438.274419-1-angelogioacchino.delregno@collabora.com> References: <20230717141438.274419-1-angelogioacchino.delregno@collabora.com> MIME-Version: 1.0 List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+lwn-linux-arm-kernel=archive.lwn.net@lists.infradead.org List-Archive: To: chunkuang.hu@kernel.org Cc: p.zabel@pengutronix.de, airlied@gmail.com, daniel@ffwll.ch, matthias.bgg@gmail.com, angelogioacchino.delregno@collabora.com, dri-devel@lists.freedesktop.org, linux-mediatek@lists.infradead.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, kernel@collabora.com, wenst@chromium.org, nfraprado@collabora.com In preparation for adding support for eDP, move the PHY registration code to a new mtk_dp_register_phy() function for better readability. This commit brings no functional changes. Signed-off-by: AngeloGioacchino Del Regno Reviewed-by: Alexandre Mergnat --- drivers/gpu/drm/mediatek/mtk_dp.c | 43 +++++++++++++++++++------------ 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_dp.c b/drivers/gpu/drm/mediatek/mtk_dp.c index c1d1a882f1db..1b4219e6a00b 100644 --- a/drivers/gpu/drm/mediatek/mtk_dp.c +++ b/drivers/gpu/drm/mediatek/mtk_dp.c @@ -2478,6 +2478,29 @@ static int mtk_dp_register_audio_driver(struct device *dev) return PTR_ERR_OR_ZERO(mtk_dp->audio_pdev); } +static int mtk_dp_register_phy(struct mtk_dp *mtk_dp) +{ + struct device *dev = mtk_dp->dev; + + mtk_dp->phy_dev = platform_device_register_data(dev, "mediatek-dp-phy", + PLATFORM_DEVID_AUTO, + &mtk_dp->regs, + sizeof(struct regmap *)); + if (IS_ERR(mtk_dp->phy_dev)) + return dev_err_probe(dev, PTR_ERR(mtk_dp->phy_dev), + "Failed to create device mediatek-dp-phy\n"); + + mtk_dp_get_calibration_data(mtk_dp); + + mtk_dp->phy = devm_phy_get(&mtk_dp->phy_dev->dev, "dp"); + if (IS_ERR(mtk_dp->phy)) { + platform_device_unregister(mtk_dp->phy_dev); + return dev_err_probe(dev, PTR_ERR(mtk_dp->phy), "Failed to get phy\n"); + } + + return 0; +} + static int mtk_dp_probe(struct platform_device *pdev) { struct mtk_dp *mtk_dp; @@ -2536,23 +2559,9 @@ static int mtk_dp_probe(struct platform_device *pdev) } } - mtk_dp->phy_dev = platform_device_register_data(dev, "mediatek-dp-phy", - PLATFORM_DEVID_AUTO, - &mtk_dp->regs, - sizeof(struct regmap *)); - if (IS_ERR(mtk_dp->phy_dev)) - return dev_err_probe(dev, PTR_ERR(mtk_dp->phy_dev), - "Failed to create device mediatek-dp-phy\n"); - - mtk_dp_get_calibration_data(mtk_dp); - - mtk_dp->phy = devm_phy_get(&mtk_dp->phy_dev->dev, "dp"); - - if (IS_ERR(mtk_dp->phy)) { - platform_device_unregister(mtk_dp->phy_dev); - return dev_err_probe(dev, PTR_ERR(mtk_dp->phy), - "Failed to get phy\n"); - } + ret = mtk_dp_register_phy(mtk_dp); + if (ret) + return ret; mtk_dp->bridge.funcs = &mtk_dp_bridge_funcs; mtk_dp->bridge.of_node = dev->of_node; From patchwork Mon Jul 17 14:14:36 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AngeloGioacchino Del Regno X-Patchwork-Id: 13316483 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org From: AngeloGioacchino Del Regno Subject: [PATCH v6 09/11] drm/mediatek: dp: Add support for embedded DisplayPort aux-bus Date: Mon, 17 Jul 2023 16:14:36 +0200 Message-Id: <20230717141438.274419-10-angelogioacchino.delregno@collabora.com> In-Reply-To: <20230717141438.274419-1-angelogioacchino.delregno@collabora.com> References: <20230717141438.274419-1-angelogioacchino.delregno@collabora.com> MIME-Version: 1.0 List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+lwn-linux-arm-kernel=archive.lwn.net@lists.infradead.org List-Archive: To: chunkuang.hu@kernel.org Cc: p.zabel@pengutronix.de, airlied@gmail.com, daniel@ffwll.ch, matthias.bgg@gmail.com, angelogioacchino.delregno@collabora.com, dri-devel@lists.freedesktop.org, linux-mediatek@lists.infradead.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, kernel@collabora.com, wenst@chromium.org, nfraprado@collabora.com For the eDP case we can support using aux-bus on MediaTek DP: this gives us the possibility to declare our panel as generic "panel-edp" which will automatically configure the timings and available modes via the EDID that we read from it. To do this, move the panel parsing at the end of the probe function so that the hardware is initialized beforehand and also initialize the DPTX AUX block and power both on as, when we populate the aux-bus, the panel driver will trigger an EDID read to perform panel detection. Last but not least, since now the AUX transfers can happen in the separated aux-bus, it was necessary to add an exclusion for the cable_plugged_in check in `mtk_dp_aux_transfer()` and the easiest way to do this is to simply ignore checking that when the bridge type is eDP. Signed-off-by: AngeloGioacchino Del Regno Reviewed-by: Alexandre Mergnat --- drivers/gpu/drm/mediatek/Kconfig | 1 + drivers/gpu/drm/mediatek/mtk_dp.c | 84 ++++++++++++++++++++++++++++--- 2 files changed, 79 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/mediatek/Kconfig b/drivers/gpu/drm/mediatek/Kconfig index b451dee64d34..76cab28e010c 100644 --- a/drivers/gpu/drm/mediatek/Kconfig +++ b/drivers/gpu/drm/mediatek/Kconfig @@ -26,6 +26,7 @@ config DRM_MEDIATEK_DP select PHY_MTK_DP select DRM_DISPLAY_HELPER select DRM_DISPLAY_DP_HELPER + select DRM_DP_AUX_BUS help DRM/KMS Display Port driver for MediaTek SoCs. diff --git a/drivers/gpu/drm/mediatek/mtk_dp.c b/drivers/gpu/drm/mediatek/mtk_dp.c index 1b4219e6a00b..acdd457b5449 100644 --- a/drivers/gpu/drm/mediatek/mtk_dp.c +++ b/drivers/gpu/drm/mediatek/mtk_dp.c @@ -4,6 +4,7 @@ * Copyright (c) 2022 BayLibre */ +#include #include #include #include @@ -1313,9 +1314,11 @@ static void mtk_dp_power_disable(struct mtk_dp *mtk_dp) static void mtk_dp_initialize_priv_data(struct mtk_dp *mtk_dp) { + bool plugged_in = (mtk_dp->bridge.type == DRM_MODE_CONNECTOR_eDP); + mtk_dp->train_info.link_rate = DP_LINK_BW_5_4; mtk_dp->train_info.lane_count = mtk_dp->max_lanes; - mtk_dp->train_info.cable_plugged_in = false; + mtk_dp->train_info.cable_plugged_in = plugged_in; mtk_dp->info.format = DP_PIXELFORMAT_RGB; memset(&mtk_dp->info.vm, 0, sizeof(struct videomode)); @@ -1617,6 +1620,16 @@ static int mtk_dp_parse_capabilities(struct mtk_dp *mtk_dp) u8 val; ssize_t ret; + /* + * If we're eDP and capabilities were already parsed we can skip + * reading again because eDP panels aren't hotpluggable hence the + * caps and training information won't ever change in a boot life + */ + if (mtk_dp->bridge.type == DRM_MODE_CONNECTOR_eDP && + mtk_dp->rx_cap[DP_MAX_LINK_RATE] && + mtk_dp->train_info.sink_ssc) + return 0; + ret = drm_dp_read_dpcd_caps(&mtk_dp->aux, mtk_dp->rx_cap); if (ret < 0) return ret; @@ -2030,15 +2043,14 @@ static struct edid *mtk_dp_get_edid(struct drm_bridge *bridge, static ssize_t mtk_dp_aux_transfer(struct drm_dp_aux *mtk_aux, struct drm_dp_aux_msg *msg) { - struct mtk_dp *mtk_dp; + struct mtk_dp *mtk_dp = container_of(mtk_aux, struct mtk_dp, aux); bool is_read; u8 request; size_t accessed_bytes = 0; int ret; - mtk_dp = container_of(mtk_aux, struct mtk_dp, aux); - - if (!mtk_dp->train_info.cable_plugged_in) { + if (mtk_dp->bridge.type != DRM_MODE_CONNECTOR_eDP && + !mtk_dp->train_info.cable_plugged_in) { ret = -EAGAIN; goto err; } @@ -2501,6 +2513,28 @@ static int mtk_dp_register_phy(struct mtk_dp *mtk_dp) return 0; } +static int mtk_dp_edp_link_panel(struct drm_dp_aux *mtk_aux) +{ + struct mtk_dp *mtk_dp = container_of(mtk_aux, struct mtk_dp, aux); + struct device *dev = mtk_aux->dev; + int ret; + + mtk_dp->next_bridge = devm_drm_of_get_bridge(dev, dev->of_node, 1, 0); + + /* Power off the DP and AUX: either detection is done, or no panel present */ + mtk_dp_update_bits(mtk_dp, MTK_DP_TOP_PWR_STATE, + DP_PWR_STATE_BANDGAP_TPLL, + DP_PWR_STATE_MASK); + mtk_dp_power_disable(mtk_dp); + + if (IS_ERR(mtk_dp->next_bridge)) { + ret = PTR_ERR(mtk_dp->next_bridge); + mtk_dp->next_bridge = NULL; + return ret; + } + return 0; +} + static int mtk_dp_probe(struct platform_device *pdev) { struct mtk_dp *mtk_dp; @@ -2531,9 +2565,10 @@ static int mtk_dp_probe(struct platform_device *pdev) if (ret) return dev_err_probe(dev, ret, "Failed to parse dt\n"); - drm_dp_aux_init(&mtk_dp->aux); mtk_dp->aux.name = "aux_mtk_dp"; + mtk_dp->aux.dev = dev; mtk_dp->aux.transfer = mtk_dp_aux_transfer; + drm_dp_aux_init(&mtk_dp->aux); spin_lock_init(&mtk_dp->irq_thread_lock); @@ -2577,6 +2612,43 @@ static int mtk_dp_probe(struct platform_device *pdev) mtk_dp->need_debounce = true; timer_setup(&mtk_dp->debounce_timer, mtk_dp_debounce_timer, 0); + if (mtk_dp->bridge.type == DRM_MODE_CONNECTOR_eDP) { + /* + * Set the data lanes to idle in case the bootloader didn't + * properly close the eDP port to avoid stalls and then + * reinitialize, reset and power on the AUX block. + */ + mtk_dp_set_idle_pattern(mtk_dp, true); + mtk_dp_initialize_aux_settings(mtk_dp); + mtk_dp_power_enable(mtk_dp); + + /* + * Power on the AUX to allow reading the EDID from aux-bus: + * please note that it is necessary to call power off in the + * .done_probing() callback (mtk_dp_edp_link_panel), as only + * there we can safely assume that we finished reading EDID. + */ + mtk_dp_update_bits(mtk_dp, MTK_DP_TOP_PWR_STATE, + DP_PWR_STATE_BANDGAP_TPLL_LANE, + DP_PWR_STATE_MASK); + + ret = devm_of_dp_aux_populate_bus(&mtk_dp->aux, mtk_dp_edp_link_panel); + if (ret) { + /* -ENODEV this means that the panel is not on the aux-bus */ + if (ret == -ENODEV) { + ret = mtk_dp_edp_link_panel(&mtk_dp->aux); + if (ret) + return ret; + } else { + mtk_dp_update_bits(mtk_dp, MTK_DP_TOP_PWR_STATE, + DP_PWR_STATE_BANDGAP_TPLL, + DP_PWR_STATE_MASK); + mtk_dp_power_disable(mtk_dp); + return ret; + } + } + } + pm_runtime_enable(dev); pm_runtime_get_sync(dev); From patchwork Mon Jul 17 14:14:37 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AngeloGioacchino Del Regno X-Patchwork-Id: 13316482 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org From: AngeloGioacchino Del Regno Subject: [PATCH v6 10/11] drm/mediatek: dp: Add .wait_hpd_asserted() for AUX bus Date: Mon, 17 Jul 2023 16:14:37 +0200 Message-Id: <20230717141438.274419-11-angelogioacchino.delregno@collabora.com> In-Reply-To: <20230717141438.274419-1-angelogioacchino.delregno@collabora.com> References: <20230717141438.274419-1-angelogioacchino.delregno@collabora.com> MIME-Version: 1.0 List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+lwn-linux-arm-kernel=archive.lwn.net@lists.infradead.org List-Archive: To: chunkuang.hu@kernel.org Cc: p.zabel@pengutronix.de, airlied@gmail.com, daniel@ffwll.ch, matthias.bgg@gmail.com, angelogioacchino.delregno@collabora.com, dri-devel@lists.freedesktop.org, linux-mediatek@lists.infradead.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, kernel@collabora.com, wenst@chromium.org, nfraprado@collabora.com In order to support usecases in which the panel regulator can be switched on and off to save power, and usecases in which the panel regulator is off at boot, add a .wait_hpd_asserted() callback for the AUX bus: this will make sure to wait until the panel is fully ready after power-on before trying to communicate with it. Also, parse the eDP display capabilities in that callback, so that we can also avoid using the .get_edid() callback from this bridge. Since at this point the hpd machinery is performed in the new hpd callback and the detection and edid reading are done outside of this driver, assign the DRM_BRIDGE_OP_{DETECT, EDID, HPD} ops and register the bridge unconditionally at probe time only if we are probing full DisplayPort and not eDP while, for the latter, we register the bridge in the .done_probing() callback and only if the panel was found and triggered HPD. Signed-off-by: AngeloGioacchino Del Regno Reviewed-by: Alexandre Mergnat --- drivers/gpu/drm/mediatek/mtk_dp.c | 45 ++++++++++++++++++++++++++----- 1 file changed, 38 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_dp.c b/drivers/gpu/drm/mediatek/mtk_dp.c index acdd457b5449..e74295ba9707 100644 --- a/drivers/gpu/drm/mediatek/mtk_dp.c +++ b/drivers/gpu/drm/mediatek/mtk_dp.c @@ -1920,6 +1920,31 @@ static irqreturn_t mtk_dp_hpd_event(int hpd, void *dev) return IRQ_WAKE_THREAD; } +static int mtk_dp_wait_hpd_asserted(struct drm_dp_aux *mtk_aux, unsigned long wait_us) +{ + struct mtk_dp *mtk_dp = container_of(mtk_aux, struct mtk_dp, aux); + u32 val; + int ret; + + ret = regmap_read_poll_timeout(mtk_dp->regs, MTK_DP_TRANS_P0_3414, + val, !!(val & HPD_DB_DP_TRANS_P0_MASK), + wait_us / 100, wait_us); + if (ret) { + mtk_dp->train_info.cable_plugged_in = false; + return ret; + } + + mtk_dp->train_info.cable_plugged_in = true; + + ret = mtk_dp_parse_capabilities(mtk_dp); + if (ret) { + drm_err(mtk_dp->drm_dev, "Can't parse capabilities\n"); + return ret; + } + + return 0; +} + static int mtk_dp_dt_parse(struct mtk_dp *mtk_dp, struct platform_device *pdev) { @@ -2532,6 +2557,12 @@ static int mtk_dp_edp_link_panel(struct drm_dp_aux *mtk_aux) mtk_dp->next_bridge = NULL; return ret; } + + /* For eDP, we add the bridge only if the panel was found */ + ret = devm_drm_bridge_add(dev, &mtk_dp->bridge); + if (ret) + return ret; + return 0; } @@ -2568,6 +2599,7 @@ static int mtk_dp_probe(struct platform_device *pdev) mtk_dp->aux.name = "aux_mtk_dp"; mtk_dp->aux.dev = dev; mtk_dp->aux.transfer = mtk_dp_aux_transfer; + mtk_dp->aux.wait_hpd_asserted = mtk_dp_wait_hpd_asserted; drm_dp_aux_init(&mtk_dp->aux); spin_lock_init(&mtk_dp->irq_thread_lock); @@ -2600,15 +2632,8 @@ static int mtk_dp_probe(struct platform_device *pdev) mtk_dp->bridge.funcs = &mtk_dp_bridge_funcs; mtk_dp->bridge.of_node = dev->of_node; - - mtk_dp->bridge.ops = - DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID | DRM_BRIDGE_OP_HPD; mtk_dp->bridge.type = mtk_dp->data->bridge_type; - ret = devm_drm_bridge_add(dev, &mtk_dp->bridge); - if (ret) - return dev_err_probe(dev, ret, "Failed to add bridge\n"); - mtk_dp->need_debounce = true; timer_setup(&mtk_dp->debounce_timer, mtk_dp_debounce_timer, 0); @@ -2647,6 +2672,12 @@ static int mtk_dp_probe(struct platform_device *pdev) return ret; } } + } else { + mtk_dp->bridge.ops = DRM_BRIDGE_OP_DETECT | + DRM_BRIDGE_OP_EDID | DRM_BRIDGE_OP_HPD; + ret = devm_drm_bridge_add(dev, &mtk_dp->bridge); + if (ret) + return dev_err_probe(dev, ret, "Failed to add bridge\n"); } pm_runtime_enable(dev); From patchwork Mon Jul 17 14:14:38 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AngeloGioacchino Del Regno X-Patchwork-Id: 13316484 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org From: AngeloGioacchino Del Regno Subject: [PATCH v6 11/11] drm/mediatek: dp: Don't register HPD interrupt handler for eDP case Date: Mon, 17 Jul 2023 16:14:38 +0200 Message-Id: <20230717141438.274419-12-angelogioacchino.delregno@collabora.com> In-Reply-To: <20230717141438.274419-1-angelogioacchino.delregno@collabora.com> References: <20230717141438.274419-1-angelogioacchino.delregno@collabora.com> MIME-Version: 1.0 List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+lwn-linux-arm-kernel=archive.lwn.net@lists.infradead.org List-Archive: To: chunkuang.hu@kernel.org Cc: p.zabel@pengutronix.de, airlied@gmail.com, daniel@ffwll.ch, matthias.bgg@gmail.com, angelogioacchino.delregno@collabora.com, dri-devel@lists.freedesktop.org, linux-mediatek@lists.infradead.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, kernel@collabora.com, wenst@chromium.org, nfraprado@collabora.com The interrupt handler for HPD is useful only if a display is actually supposed to be hotpluggable, as that manages the machinery to perform cable (un)plug detection, debouncing and setup for re-training. Since eDP panels are not supposed to be hotpluggable we can avoid using the HPD interrupts altogether and rely on HPD polling only for the suspend/resume case, saving us some spinlocking action and the overhead of interrupts firing at every suspend/resume cycle, achieving a faster (even if just slightly) display resume. Signed-off-by: AngeloGioacchino Del Regno Reviewed-by: Alexandre Mergnat --- drivers/gpu/drm/mediatek/mtk_dp.c | 81 ++++++++++++++++++------------- 1 file changed, 46 insertions(+), 35 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_dp.c b/drivers/gpu/drm/mediatek/mtk_dp.c index e74295ba9707..c06fcc7318e7 100644 --- a/drivers/gpu/drm/mediatek/mtk_dp.c +++ b/drivers/gpu/drm/mediatek/mtk_dp.c @@ -2182,9 +2182,11 @@ static int mtk_dp_bridge_attach(struct drm_bridge *bridge, mtk_dp->drm_dev = bridge->dev; - irq_clear_status_flags(mtk_dp->irq, IRQ_NOAUTOEN); - enable_irq(mtk_dp->irq); - mtk_dp_hwirq_enable(mtk_dp, true); + if (mtk_dp->bridge.type != DRM_MODE_CONNECTOR_eDP) { + irq_clear_status_flags(mtk_dp->irq, IRQ_NOAUTOEN); + enable_irq(mtk_dp->irq); + mtk_dp_hwirq_enable(mtk_dp, true); + } return 0; @@ -2199,8 +2201,10 @@ static void mtk_dp_bridge_detach(struct drm_bridge *bridge) { struct mtk_dp *mtk_dp = mtk_dp_from_bridge(bridge); - mtk_dp_hwirq_enable(mtk_dp, false); - disable_irq(mtk_dp->irq); + if (mtk_dp->bridge.type != DRM_MODE_CONNECTOR_eDP) { + mtk_dp_hwirq_enable(mtk_dp, false); + disable_irq(mtk_dp->irq); + } mtk_dp->drm_dev = NULL; mtk_dp_poweroff(mtk_dp); drm_dp_aux_unregister(&mtk_dp->aux); @@ -2579,40 +2583,44 @@ static int mtk_dp_probe(struct platform_device *pdev) mtk_dp->dev = dev; mtk_dp->data = (struct mtk_dp_data *)of_device_get_match_data(dev); - mtk_dp->irq = platform_get_irq(pdev, 0); - if (mtk_dp->irq < 0) - return dev_err_probe(dev, mtk_dp->irq, - "failed to request dp irq resource\n"); - - mtk_dp->next_bridge = devm_drm_of_get_bridge(dev, dev->of_node, 1, 0); - if (IS_ERR(mtk_dp->next_bridge) && - PTR_ERR(mtk_dp->next_bridge) == -ENODEV) - mtk_dp->next_bridge = NULL; - else if (IS_ERR(mtk_dp->next_bridge)) - return dev_err_probe(dev, PTR_ERR(mtk_dp->next_bridge), - "Failed to get bridge\n"); - ret = mtk_dp_dt_parse(mtk_dp, pdev); if (ret) return dev_err_probe(dev, ret, "Failed to parse dt\n"); + /* + * Request the interrupt and install service routine only if we are + * on full DisplayPort. + * For eDP, polling the HPD instead is more convenient because we + * don't expect any (un)plug events during runtime, hence we can + * avoid some locking. + */ + if (mtk_dp->data->bridge_type != DRM_MODE_CONNECTOR_eDP) { + mtk_dp->irq = platform_get_irq(pdev, 0); + if (mtk_dp->irq < 0) + return dev_err_probe(dev, mtk_dp->irq, + "failed to request dp irq resource\n"); + + spin_lock_init(&mtk_dp->irq_thread_lock); + + irq_set_status_flags(mtk_dp->irq, IRQ_NOAUTOEN); + ret = devm_request_threaded_irq(dev, mtk_dp->irq, mtk_dp_hpd_event, + mtk_dp_hpd_event_thread, + IRQ_TYPE_LEVEL_HIGH, dev_name(dev), + mtk_dp); + if (ret) + return dev_err_probe(dev, ret, + "failed to request mediatek dptx irq\n"); + + mtk_dp->need_debounce = true; + timer_setup(&mtk_dp->debounce_timer, mtk_dp_debounce_timer, 0); + } + mtk_dp->aux.name = "aux_mtk_dp"; mtk_dp->aux.dev = dev; mtk_dp->aux.transfer = mtk_dp_aux_transfer; mtk_dp->aux.wait_hpd_asserted = mtk_dp_wait_hpd_asserted; drm_dp_aux_init(&mtk_dp->aux); - spin_lock_init(&mtk_dp->irq_thread_lock); - - irq_set_status_flags(mtk_dp->irq, IRQ_NOAUTOEN); - ret = devm_request_threaded_irq(dev, mtk_dp->irq, mtk_dp_hpd_event, - mtk_dp_hpd_event_thread, - IRQ_TYPE_LEVEL_HIGH, dev_name(dev), - mtk_dp); - if (ret) - return dev_err_probe(dev, ret, - "failed to request mediatek dptx irq\n"); - platform_set_drvdata(pdev, mtk_dp); if (mtk_dp->data->audio_supported) { @@ -2634,9 +2642,6 @@ static int mtk_dp_probe(struct platform_device *pdev) mtk_dp->bridge.of_node = dev->of_node; mtk_dp->bridge.type = mtk_dp->data->bridge_type; - mtk_dp->need_debounce = true; - timer_setup(&mtk_dp->debounce_timer, mtk_dp_debounce_timer, 0); - if (mtk_dp->bridge.type == DRM_MODE_CONNECTOR_eDP) { /* * Set the data lanes to idle in case the bootloader didn't @@ -2647,6 +2652,9 @@ static int mtk_dp_probe(struct platform_device *pdev) mtk_dp_initialize_aux_settings(mtk_dp); mtk_dp_power_enable(mtk_dp); + /* Disable HW interrupts: we don't need any for eDP */ + mtk_dp_hwirq_enable(mtk_dp, false); + /* * Power on the AUX to allow reading the EDID from aux-bus: * please note that it is necessary to call power off in the @@ -2692,7 +2700,8 @@ static int mtk_dp_remove(struct platform_device *pdev) pm_runtime_put(&pdev->dev); pm_runtime_disable(&pdev->dev); - del_timer_sync(&mtk_dp->debounce_timer); + if (mtk_dp->data->bridge_type != DRM_MODE_CONNECTOR_eDP) + del_timer_sync(&mtk_dp->debounce_timer); platform_device_unregister(mtk_dp->phy_dev); if (mtk_dp->audio_pdev) platform_device_unregister(mtk_dp->audio_pdev); @@ -2706,7 +2715,8 @@ static int mtk_dp_suspend(struct device *dev) struct mtk_dp *mtk_dp = dev_get_drvdata(dev); mtk_dp_power_disable(mtk_dp); - mtk_dp_hwirq_enable(mtk_dp, false); + if (mtk_dp->bridge.type != DRM_MODE_CONNECTOR_eDP) + mtk_dp_hwirq_enable(mtk_dp, false); pm_runtime_put_sync(dev); return 0; @@ -2718,7 +2728,8 @@ static int mtk_dp_resume(struct device *dev) pm_runtime_get_sync(dev); mtk_dp_init_port(mtk_dp); - mtk_dp_hwirq_enable(mtk_dp, true); + if (mtk_dp->bridge.type != DRM_MODE_CONNECTOR_eDP) + mtk_dp_hwirq_enable(mtk_dp, true); mtk_dp_power_enable(mtk_dp); return 0;