From patchwork Tue Dec 17 14:32:13 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Herve Codina X-Patchwork-Id: 13911935 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 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 smtp.lore.kernel.org (Postfix) with ESMTPS id C4B5DE77184 for ; Tue, 17 Dec 2024 14:39:57 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id E22A710E225; Tue, 17 Dec 2024 14:39:54 +0000 (UTC) Authentication-Results: gabe.freedesktop.org; dkim=pass (2048-bit key; unprotected) header.d=bootlin.com header.i=@bootlin.com header.b="dpgHsKj7"; dkim-atps=neutral Received: from mslow1.mail.gandi.net (mslow1.mail.gandi.net [217.70.178.240]) by gabe.freedesktop.org (Postfix) with ESMTPS id 92B0010E225 for ; Tue, 17 Dec 2024 14:39:53 +0000 (UTC) Received: from relay5-d.mail.gandi.net (unknown [IPv6:2001:4b98:dc4:8::225]) by mslow1.mail.gandi.net (Postfix) with ESMTP id 87D56C11BD for ; Tue, 17 Dec 2024 14:32:26 +0000 (UTC) Received: by mail.gandi.net (Postfix) with ESMTPA id 9FA2C1C000D; Tue, 17 Dec 2024 14:32:21 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1734445943; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Lb26UgKvvmRlT3knQ9VrHygcTFqrZLYIOsrNHKkSBeA=; b=dpgHsKj76K+QUp6DwXG7isxLkwC6GyXFnKbe4p65fYgbY+lDCzJyUfk+jp5BbhWWkMt4uy FAXLZCyt8S/8ET5PFZhDd7s/cxD2SeUjyxe3YrSZF1NZv4QTA1+e356zFQWhUzeOZEbdSC 2K3OoUf1HOlMUGkecG0FyLfrDM+axTyVRjzwUOzy1hdkP/m/2HyCUcXvU4f83xPsmBO/vK EUPjq73Xd1HTJ16kKHp0Arn4LMXoGoxPqtwUHiRrtnGYwuJfK+DzapW2z3dl2W/pbtTS+m c07/7keTq4A/44xW/XZS9+Um8h/bPW4LpEdiCgR6IzdHRsLaWnkM1aLHSv5xtA== From: Herve Codina To: Andrzej Hajda , Neil Armstrong , Robert Foss , Laurent Pinchart , Jonas Karlman , Jernej Skrabec , David Airlie , Simona Vetter , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Marek Vasut Cc: dri-devel@lists.freedesktop.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Louis Chauvet , Luca Ceresoli , Thomas Petazzoni , Herve Codina , Laurent Pinchart , Conor Dooley Subject: [PATCH v2 1/3] dt-bindings: display: bridge: sn65dsi83: Add interrupt Date: Tue, 17 Dec 2024 15:32:13 +0100 Message-ID: <20241217143216.658461-2-herve.codina@bootlin.com> X-Mailer: git-send-email 2.47.0 In-Reply-To: <20241217143216.658461-1-herve.codina@bootlin.com> References: <20241217143216.658461-1-herve.codina@bootlin.com> MIME-Version: 1.0 X-GND-Sasl: herve.codina@bootlin.com X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" Both the TI SN65DSI83 and SN65DSI84 bridges have an IRQ pin to signal errors using interrupt. This interrupt is not documented in the binding. Add the missing interrupts property. Signed-off-by: Herve Codina Reviewed-by: Laurent Pinchart Acked-by: Conor Dooley --- .../devicetree/bindings/display/bridge/ti,sn65dsi83.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Documentation/devicetree/bindings/display/bridge/ti,sn65dsi83.yaml b/Documentation/devicetree/bindings/display/bridge/ti,sn65dsi83.yaml index 48a97bb3e2e0..4505d2d83e0d 100644 --- a/Documentation/devicetree/bindings/display/bridge/ti,sn65dsi83.yaml +++ b/Documentation/devicetree/bindings/display/bridge/ti,sn65dsi83.yaml @@ -35,6 +35,9 @@ properties: vcc-supply: description: A 1.8V power supply (see regulator/regulator.yaml). + interrupts: + maxItems: 1 + ports: $ref: /schemas/graph.yaml#/properties/ports From patchwork Tue Dec 17 14:32:14 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Herve Codina X-Patchwork-Id: 13911936 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 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 smtp.lore.kernel.org (Postfix) with ESMTPS id 5C70EE7717F for ; Tue, 17 Dec 2024 14:39:59 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 32B6C10E426; Tue, 17 Dec 2024 14:39:55 +0000 (UTC) Authentication-Results: gabe.freedesktop.org; dkim=pass (2048-bit key; unprotected) header.d=bootlin.com header.i=@bootlin.com header.b="ImKvhuDn"; dkim-atps=neutral Received: from mslow1.mail.gandi.net (mslow1.mail.gandi.net [217.70.178.240]) by gabe.freedesktop.org (Postfix) with ESMTPS id 8E90110E02B for ; Tue, 17 Dec 2024 14:39:53 +0000 (UTC) Received: from relay5-d.mail.gandi.net (unknown [IPv6:2001:4b98:dc4:8::225]) by mslow1.mail.gandi.net (Postfix) with ESMTP id 93DBAC11CD for ; Tue, 17 Dec 2024 14:32:27 +0000 (UTC) Received: by mail.gandi.net (Postfix) with ESMTPA id 49B4E1C0006; Tue, 17 Dec 2024 14:32:23 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1734445944; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=rOl01A0J4zS7bD55OnoODRpUmSiylYagae5vOcM5HKw=; b=ImKvhuDnPDoKcXobBysVBrEa9VgE2Nf6ioyie6UIkaxC/XIFP46oYDbB2lvvdNMSs6p4YX 4vFvmyXI1ukivifVU/TkscmfGoLsyPBoaEmP9qyGT0kBvbfT8nIHyPIubr+mobE0MHSrhD ffQbpngYAQ0o1Ev2c+D+tS8rasnTB51lVKEeWZ6WWcAADbrRJyBQZ4/OWhKwirJPiaigKX k5g8g6hDqfZOGYsS1OW1g24mL+STytWnzPz2gcrW8BGcQHtLGRrsYt6uSjjj4FqjODUB7/ pYuMyQw/P0VbiEIYIjQ8fmEm6nkKXp9Q+H4uC7zoY2mttZAFaHclOS0mDMtQ4g== From: Herve Codina To: Andrzej Hajda , Neil Armstrong , Robert Foss , Laurent Pinchart , Jonas Karlman , Jernej Skrabec , David Airlie , Simona Vetter , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Marek Vasut Cc: dri-devel@lists.freedesktop.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Louis Chauvet , Luca Ceresoli , Thomas Petazzoni , Herve Codina Subject: [PATCH v2 2/3] drm/atomic-helpers: Introduce drm_atomic_helper_disable_connector() Date: Tue, 17 Dec 2024 15:32:14 +0100 Message-ID: <20241217143216.658461-3-herve.codina@bootlin.com> X-Mailer: git-send-email 2.47.0 In-Reply-To: <20241217143216.658461-1-herve.codina@bootlin.com> References: <20241217143216.658461-1-herve.codina@bootlin.com> MIME-Version: 1.0 X-GND-Sasl: herve.codina@bootlin.com X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" drm_atomic_helper_disable_connector() disables a connector taking care of disabling the CRTC as well if the disabled connector was the only one connector connected to the CRTC. Signed-off-by: Herve Codina --- drivers/gpu/drm/drm_atomic_helper.c | 67 +++++++++++++++++++++++++++++ include/drm/drm_atomic_helper.h | 2 + 2 files changed, 69 insertions(+) diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 8ed186ddaeaf..1d691cbb047e 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -3279,6 +3279,73 @@ int drm_atomic_helper_set_config(struct drm_mode_set *set, } EXPORT_SYMBOL(drm_atomic_helper_set_config); +/** + * drm_atomic_helper_disable_connector - disable connector + * @connector: connector to disable + * @ctx: lock acquisition context + * + * Turn off the given connector by setting its DPMS mode to off. + * Also deactivate the CRTC is this connector was the only one connected to the + * CRTC. + * + * Note that if callers haven't already acquired all modeset locks this might + * return -EDEADLK, which must be handled by calling drm_modeset_backoff(). + * + * Returns: + * 0 on success or a negative error code on failure. + */ +int drm_atomic_helper_disable_connector(struct drm_connector *connector, + struct drm_modeset_acquire_ctx *ctx) +{ + struct drm_connector_state *connector_state; + struct drm_crtc_state *crtc_state; + struct drm_atomic_state *state; + struct drm_crtc *crtc; + int ret; + + state = drm_atomic_state_alloc(connector->dev); + if (!state) + return -ENOMEM; + + state->acquire_ctx = ctx; + + connector_state = drm_atomic_get_connector_state(state, connector); + if (IS_ERR(connector_state)) { + ret = PTR_ERR(connector_state); + goto end; + } + + crtc = connector_state->crtc; + + ret = drm_atomic_set_crtc_for_connector(connector_state, NULL); + if (ret < 0) + goto end; + + crtc_state = drm_atomic_get_crtc_state(state, crtc); + if (IS_ERR(crtc_state)) { + ret = PTR_ERR(crtc_state); + goto end; + } + + if (!crtc_state->connector_mask) { + /* + * The only one connector from the crtc has + * been disabled -> Disable the CRTC too + */ + ret = drm_atomic_set_mode_prop_for_crtc(crtc_state, NULL); + if (ret < 0) + goto end; + + crtc_state->active = false; + } + + ret = drm_atomic_commit(state); +end: + drm_atomic_state_put(state); + return ret; +} +EXPORT_SYMBOL(drm_atomic_helper_disable_connector); + /** * drm_atomic_helper_disable_all - disable all currently active outputs * @dev: DRM device diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h index 9aa0a05aa072..923a354577a3 100644 --- a/include/drm/drm_atomic_helper.h +++ b/include/drm/drm_atomic_helper.h @@ -137,6 +137,8 @@ int drm_atomic_helper_disable_plane(struct drm_plane *plane, int drm_atomic_helper_set_config(struct drm_mode_set *set, struct drm_modeset_acquire_ctx *ctx); +int drm_atomic_helper_disable_connector(struct drm_connector *connector, + struct drm_modeset_acquire_ctx *ctx); int drm_atomic_helper_disable_all(struct drm_device *dev, struct drm_modeset_acquire_ctx *ctx); void drm_atomic_helper_shutdown(struct drm_device *dev); From patchwork Tue Dec 17 14:32:15 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Herve Codina X-Patchwork-Id: 13911937 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 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 smtp.lore.kernel.org (Postfix) with ESMTPS id B605EE77187 for ; Tue, 17 Dec 2024 14:40:00 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 8CC3410E994; Tue, 17 Dec 2024 14:39:55 +0000 (UTC) Authentication-Results: gabe.freedesktop.org; dkim=pass (2048-bit key; unprotected) header.d=bootlin.com header.i=@bootlin.com header.b="naLoA2o2"; dkim-atps=neutral Received: from mslow1.mail.gandi.net (mslow1.mail.gandi.net [217.70.178.240]) by gabe.freedesktop.org (Postfix) with ESMTPS id 96C5510E426 for ; Tue, 17 Dec 2024 14:39:53 +0000 (UTC) Received: from relay5-d.mail.gandi.net (unknown [IPv6:2001:4b98:dc4:8::225]) by mslow1.mail.gandi.net (Postfix) with ESMTP id CC380C0D01 for ; Tue, 17 Dec 2024 14:32:28 +0000 (UTC) Received: by mail.gandi.net (Postfix) with ESMTPA id 70C081C0002; Tue, 17 Dec 2024 14:32:24 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1734445945; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Sxaq5q+AzkKVN/8S0SNFdak5cF+ckchTn2ySvTiskYI=; b=naLoA2o2D/25hl1zIbN/iJfCiWNfdssTuxy2CEVBMp0TAaz8dwxJD+LwlZlabzBdxyUs9f rUFMosuKuCwxO9nibvg8L4sb3YnnmK+1Q7eFA2Qqxbxmkx/B8/ysNnxEiy4GuD4UPPILfT /+gmlm3uUHABRlMhOQ/GkmsaTazcTxWlVgELu8aT3CQnqb4/ESzw+Aw3BDzA8zIGGho7un /xGiKs/6uVI8IkX53VfaJdEKdnWDcdqT9e5CB29GP8/Y6vigoCA91fKd16U9oyYl6FBi3V ysxzak5JMQEL2u14QkPNMooj8TdPRic7nvvfbb/VLlW/apoPGENl8joHnYyB/A== From: Herve Codina To: Andrzej Hajda , Neil Armstrong , Robert Foss , Laurent Pinchart , Jonas Karlman , Jernej Skrabec , David Airlie , Simona Vetter , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Marek Vasut Cc: dri-devel@lists.freedesktop.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Louis Chauvet , Luca Ceresoli , Thomas Petazzoni , Herve Codina Subject: [PATCH v2 3/3] drm: bridge: ti-sn65dsi83: Add error recovery mechanism Date: Tue, 17 Dec 2024 15:32:15 +0100 Message-ID: <20241217143216.658461-4-herve.codina@bootlin.com> X-Mailer: git-send-email 2.47.0 In-Reply-To: <20241217143216.658461-1-herve.codina@bootlin.com> References: <20241217143216.658461-1-herve.codina@bootlin.com> MIME-Version: 1.0 X-GND-Sasl: herve.codina@bootlin.com X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" In some cases observed during ESD tests, the TI SN65DSI83 cannot recover from errors by itself. A full restart of the bridge is needed in those cases to have the bridge output LVDS signals again. Also, during tests, cases were observed where reading the status of the bridge was not even possible. Indeed, in those cases, the bridge stops to acknowledge I2C transactions. Only a full reset of the bridge (power off/on) brings back the bridge to a functional state. The TI SN65DSI83 has some error detection capabilities. Introduce an error recovery mechanism based on this detection. The errors detected are signaled through an interrupt. On system where this interrupt is not available, the driver uses a polling monitoring fallback to check for errors. When an error is present or when reading the bridge status leads to an I2C failure, the recovery process is launched. Restarting the bridge needs to redo the initialization sequence. This initialization sequence has to be done with the DSI data lanes driven in LP11 state. In order to do that, the recovery process resets the whole output path (i.e the path from the encoder to the connector) where the bridge is located. Signed-off-by: Herve Codina --- drivers/gpu/drm/bridge/ti-sn65dsi83.c | 142 ++++++++++++++++++++++++++ 1 file changed, 142 insertions(+) diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi83.c b/drivers/gpu/drm/bridge/ti-sn65dsi83.c index e6264514bb3f..f3d66d17f28c 100644 --- a/drivers/gpu/drm/bridge/ti-sn65dsi83.c +++ b/drivers/gpu/drm/bridge/ti-sn65dsi83.c @@ -35,9 +35,12 @@ #include #include #include +#include +#include #include #include +#include /* DRM_MODESET_LOCK_ALL_BEGIN() need drm_drv_uses_atomic_modeset() */ #include #include #include @@ -147,6 +150,9 @@ struct sn65dsi83 { struct regulator *vcc; bool lvds_dual_link; bool lvds_dual_link_even_odd_swap; + bool use_irq; + struct delayed_work monitor_work; + struct work_struct reset_work; }; static const struct regmap_range sn65dsi83_readable_ranges[] = { @@ -328,6 +334,106 @@ static u8 sn65dsi83_get_dsi_div(struct sn65dsi83 *ctx) return dsi_div - 1; } +static int sn65dsi83_reset_drm_output(struct sn65dsi83 *sn65dsi83) +{ + struct drm_atomic_state *state = ERR_PTR(-EINVAL); + struct drm_device *dev = sn65dsi83->bridge.dev; + struct drm_modeset_acquire_ctx ctx; + struct drm_connector *connector; + int err; + + /* + * Reset components available from the encoder to the connector. + * To do that, we disable then re-enable the connector linked to the + * encoder. + * + * This way, drm core will reconfigure each components. In our case, + * this will force the previous component to go back in LP11 mode and + * so allow the reconfiguration of SN64DSI83 bridge. + * + * Keep the lock during the whole operation to be atomic. + */ + + DRM_MODESET_LOCK_ALL_BEGIN(dev, ctx, 0, err); + + state = drm_atomic_helper_duplicate_state(dev, &ctx); + if (IS_ERR(state)) { + err = PTR_ERR(state); + goto unlock; + } + + connector = drm_atomic_get_old_connector_for_encoder(state, + sn65dsi83->bridge.encoder); + if (!connector) { + err = -EINVAL; + goto unlock; + } + + err = drm_atomic_helper_disable_connector(connector, &ctx); + if (err < 0) + goto unlock; + + /* Restore original state to re-enable the connector */ + err = drm_atomic_helper_commit_duplicated_state(state, &ctx); + +unlock: + DRM_MODESET_LOCK_ALL_END(dev, ctx, err); + if (!IS_ERR(state)) + drm_atomic_state_put(state); + return err; +} + +static void sn65dsi83_reset_work(struct work_struct *ws) +{ + struct sn65dsi83 *ctx = container_of(ws, struct sn65dsi83, reset_work); + int ret; + + dev_warn(ctx->dev, "reset the drm output\n"); + + /* Reset the output */ + ret = sn65dsi83_reset_drm_output(ctx); + if (ret) { + dev_err(ctx->dev, "reset drm output failed %pe\n", ERR_PTR(ret)); + return; + } +} + +static void sn65dsi83_handle_errors(struct sn65dsi83 *ctx) +{ + unsigned int irq_stat; + int ret; + + /* + * Schedule a reset in case of: + * - the bridge doesn't answer + * - the bridge signals an error + */ + + ret = regmap_read(ctx->regmap, REG_IRQ_STAT, &irq_stat); + if (ret || irq_stat) + schedule_work(&ctx->reset_work); +} + +static void sn65dsi83_monitor_work(struct work_struct *work) +{ + struct sn65dsi83 *ctx = container_of(to_delayed_work(work), + struct sn65dsi83, monitor_work); + + sn65dsi83_handle_errors(ctx); + + schedule_delayed_work(&ctx->monitor_work, msecs_to_jiffies(1000)); +} + +static void sn65dsi83_monitor_start(struct sn65dsi83 *ctx) +{ + schedule_delayed_work(&ctx->monitor_work, msecs_to_jiffies(1000)); +} + +static void sn65dsi83_monitor_stop(struct sn65dsi83 *ctx) +{ + cancel_delayed_work_sync(&ctx->monitor_work); +} + static void sn65dsi83_atomic_pre_enable(struct drm_bridge *bridge, struct drm_bridge_state *old_bridge_state) { @@ -516,6 +622,15 @@ static void sn65dsi83_atomic_enable(struct drm_bridge *bridge, regmap_read(ctx->regmap, REG_IRQ_STAT, &pval); if (pval) dev_err(ctx->dev, "Unexpected link status 0x%02x\n", pval); + + if (ctx->use_irq) { + /* Enable irq to detect errors */ + regmap_write(ctx->regmap, REG_IRQ_GLOBAL, REG_IRQ_GLOBAL_IRQ_EN); + regmap_write(ctx->regmap, REG_IRQ_EN, 0xff); + } else { + /* Use the polling task */ + sn65dsi83_monitor_start(ctx); + } } static void sn65dsi83_atomic_disable(struct drm_bridge *bridge, @@ -524,6 +639,15 @@ static void sn65dsi83_atomic_disable(struct drm_bridge *bridge, struct sn65dsi83 *ctx = bridge_to_sn65dsi83(bridge); int ret; + if (ctx->use_irq) { + /* Disable irq */ + regmap_write(ctx->regmap, REG_IRQ_EN, 0x0); + regmap_write(ctx->regmap, REG_IRQ_GLOBAL, 0x0); + } else { + /* Stop the polling task */ + sn65dsi83_monitor_stop(ctx); + } + /* Put the chip in reset, pull EN line low, and assure 10ms reset low timing. */ gpiod_set_value_cansleep(ctx->enable_gpio, 0); usleep_range(10000, 11000); @@ -681,6 +805,14 @@ static int sn65dsi83_host_attach(struct sn65dsi83 *ctx) return 0; } +static irqreturn_t sn65dsi83_irq(int irq, void *data) +{ + struct sn65dsi83 *ctx = data; + + sn65dsi83_handle_errors(ctx); + return IRQ_HANDLED; +} + static int sn65dsi83_probe(struct i2c_client *client) { const struct i2c_device_id *id = i2c_client_get_device_id(client); @@ -698,6 +830,8 @@ static int sn65dsi83_probe(struct i2c_client *client) return ret; ctx->dev = dev; + INIT_WORK(&ctx->reset_work, sn65dsi83_reset_work); + INIT_DELAYED_WORK(&ctx->monitor_work, sn65dsi83_monitor_work); if (dev->of_node) { model = (enum sn65dsi83_model)(uintptr_t) @@ -722,6 +856,14 @@ static int sn65dsi83_probe(struct i2c_client *client) if (IS_ERR(ctx->regmap)) return dev_err_probe(dev, PTR_ERR(ctx->regmap), "failed to get regmap\n"); + if (client->irq) { + ret = devm_request_threaded_irq(ctx->dev, client->irq, NULL, sn65dsi83_irq, + IRQF_ONESHOT, dev_name(ctx->dev), ctx); + if (ret) + return dev_err_probe(dev, ret, "failed to request irq\n"); + ctx->use_irq = true; + } + dev_set_drvdata(dev, ctx); i2c_set_clientdata(client, ctx);