Received: by 2002:a05:6a10:413:0:0:0:0 with SMTP id 19csp306330pxp; Fri, 11 Mar 2022 04:54:38 -0800 (PST) X-Google-Smtp-Source: ABdhPJyn+Y2P9UpaJQg5Iys+73L1TAcSZJU1NknrFxn6S9UXahU2Ha7KcAprgIcsUP+EkydWcs9m X-Received: by 2002:a17:902:ec81:b0:151:f1c5:2f9f with SMTP id x1-20020a170902ec8100b00151f1c52f9fmr10203345plg.123.1647003278161; Fri, 11 Mar 2022 04:54:38 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1647003278; cv=none; d=google.com; s=arc-20160816; b=lWx0Hn98sYLvDFabof+2wkpArpCoCSF+LToL3Co6ZGqSbcjjB32GNReq+7ufGOI2Px VtQRn1k2/1USMboRNaXtwStAAyPwgp+Rma2KmRAtZQGlasBya8R0ySGDUSzNmuapGXJy 9TBGfaYuJvQRX6KIqnLwhBa60gJHrqbSuWQI6nNdHS0OkOsq0mqQMKmX+FdKPvfKHIyy sGA/0mdF82ha5uko4lwzj0ywk0ogikGTmxzGxRd/CczUT01USRotZNtZjspvGEDRn9/a 3UG7gulZAchY43j9VCwqj4K5Wk3xcVZATd2hWK3ImREro4zf1V5jChLpAErlaoWFM9Ft 8ypw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:user-agent:message-id:date:to:cc:from:subject :references:in-reply-to:content-transfer-encoding:mime-version :dkim-signature; bh=BH059dMDRQK4d3qBuaNQHUwcLHx/GqUQCYmERlYl8vs=; b=RO0KJFIFYuvxllyjmwM6t+pWDcwe3UVprQ3ACNMyRa/Olo/dATu34yLwS148ztHsWi E5Oa5/UxkFja9KwhavQiyzFk9NrpAn1aftRDr+Bnlqiy0BHhSubuua+q6QszfMIVxRpf 9ma85+DPn0OocxbLNxU8zvbyvnxXT81KEPPqgRjjiVgUhmDJN0RHunlxeREl28sQ8c5D pPmFVHO/R5wXduGNrzfxK+hWfddAvg/zqRNeaYsJqXM6oTRCduFOJGpouF7yUMay1JTO reVJYek/0uZ3mx83tqvR4DoXhlFnRRqTnMo/6iUxP0JTY8TLKiTSvWJWRU6a9DtdzZld w5rw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass (test mode) header.i=@ideasonboard.com header.s=mail header.b=DHFCOygt; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id j7-20020a170903028700b001513a3bfea2si7840416plr.292.2022.03.11.04.54.25; Fri, 11 Mar 2022 04:54:38 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass (test mode) header.i=@ideasonboard.com header.s=mail header.b=DHFCOygt; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1346004AbiCKFss (ORCPT + 99 others); Fri, 11 Mar 2022 00:48:48 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45394 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S240044AbiCKFsp (ORCPT ); Fri, 11 Mar 2022 00:48:45 -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 E0D572BF6; Thu, 10 Mar 2022 21:47:26 -0800 (PST) Received: from pendragon.ideasonboard.com (cpc89244-aztw30-2-0-cust3082.18-1.cable.virginm.net [86.31.172.11]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 2FE6F488; Fri, 11 Mar 2022 06:47:25 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1646977645; bh=oockvR1LA+v9n302HI7aC2gMooUZaYtMOy6sArIIR2I=; h=In-Reply-To:References:Subject:From:Cc:To:Date:From; b=DHFCOygtdIWYDOa312BgpS/tKmOtVfjrUwPBlAjBDNa8Dku1KLiq4c2nL217+FDpI asDffEq0T0LvXow4y7D/ESM6SMGACt2+ghp5a59VfUYhFyPu0MUiTka6sY5IdhzjfT ttCRAF4JC0ihIbgIoE9i9m/u0UI+icDdw5BB2YaY= Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable In-Reply-To: References: <20220310152227.2122960-1-kieran.bingham+renesas@ideasonboard.com> <20220310152227.2122960-4-kieran.bingham+renesas@ideasonboard.com> Subject: Re: [PATCH v3 3/3] drm/bridge: ti-sn65dsi86: Support hotplug detection From: Kieran Bingham Cc: dri-devel , Linux-Renesas , Sam Ravnborg , LKML , Andrzej Hajda , Neil Armstrong , Robert Foss , Laurent Pinchart , Jonas Karlman , Jernej Skrabec , David Airlie , Daniel Vetter , Laurent Pinchart To: Doug Anderson Date: Fri, 11 Mar 2022 05:47:22 +0000 Message-ID: <164697764297.2392702.10094603553189733655@Monstersaurus> User-Agent: alot/0.10 X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_PASS,SPF_PASS, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Hi Doug, Quoting Doug Anderson (2022-03-10 23:10:12) > Hi, >=20 > On Thu, Mar 10, 2022 at 7:22 AM Kieran Bingham > wrote: > > > > @@ -1135,6 +1161,36 @@ static void ti_sn_bridge_atomic_post_disable(str= uct 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 =3D bridge_to_ti_sn65dsi86(bridge); > > + int val; > > + > > + regmap_read(pdata->regmap, SN_HPD_DISABLE_REG, &val); >=20 > Don't you need a pm_runtime_get_sync() before this and a > put_autosuspend() after? The "detect" will be used in the yes-HPD but > no-IRQ case, right? In that case there's nobody holding the pm_runtime > reference. Hrm ... I'll have to dig on this a bit. The polling is done by the DRM core, so indeed I suspect it could be done outside of a context that holds the pm runtime reference. Equally a get and put on the reference doesn't hurt even if it's already taken, so perhaps it's best to add it, but I'll try to confirm it's requirement first. > Also, a nit that it'd be great if you error checked the regmap_read(). > I know this driver isn't very good about it, but it's probably > something to get better. i2c transactions can fail. I guess another > alternative would be to init "val" to 0... It's a good point indeed. If we can't read the device we should return disconnected. >=20 >=20 > > + return val & HPD_DEBOUNCED_STATE ? connector_status_connected > > + : connector_status_disconnecte= d; > > +} > > + > > +static void ti_sn_bridge_hpd_enable(struct drm_bridge *bridge) > > +{ > > + struct ti_sn65dsi86 *pdata =3D 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 =3D bridge_to_ti_sn65dsi86(bridge); > > + > > + regmap_write(pdata->regmap, SN_IRQ_HPD_REG, 0); > > + pm_runtime_put_autosuspend(pdata->dev); >=20 > Before doing the pm_runtime_put_autosuspend() it feels like you should > ensure that the interrupt has finished. Otherwise we could be midway > through processing an interrupt and the pm_runtime reference could go > away, right? Maybe we just disable the irq which I think will wait for > anything outstanding to finish? Should the IRQ handler also call pm_runtime_get/put then? > > @@ -1223,6 +1282,34 @@ static int ti_sn_bridge_parse_dsi_host(struct ti= _sn65dsi86 *pdata) > > return 0; > > } > > > > +static irqreturn_t ti_sn65dsi86_irq_handler(int irq, void *arg) > > +{ > > + struct ti_sn65dsi86 *pdata =3D arg; > > + int ret; > > + unsigned int hpd; > > + > > + ret =3D 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 dis= play */ > > + if (hpd & IRQ_HPD_REPLUG_STATUS) > > + drm_bridge_hpd_notify(&pdata->bridge, connector_status_= disconnected); >=20 > How does the ordering work here if _both_ insertion and removal are > asserted? Is that somehow not possible? Should this be "else if" type > statements then, or give a warn if more than one bit is set, or ... ? As I understand it, that would trigger a REPLUG IRQ. However this is one part I quite disliked about the drm_bridge_hpd_notify. The values here are not taken as the hardware state anyway. A call to drm_bridge_hpd_notify= will=20 trigger a call on the detect function so a further read will occur to determine the current state using the same function as is used with polling. The IRQ handler only cuts out the polling as far as I see. > > + /* 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); >=20 > IMO this regmap_write() belongs right after the read and should be > based on what you read--you shouldn't just clear all of them. AKA: >=20 > a) Read to see what interrupt are asserted. > b) Ack the interrupts that you saw asserted. > c) Process the interrupts that you saw asserted. >=20 > If you process before acking then you can miss interrupts (in other > words if you do "a" then "c" then "b" then you can miss interrupts > that come in after "b" but before "c". Agreed, I'll respin. > > @@ -1247,9 +1342,29 @@ static int ti_sn_bridge_probe(struct auxiliary_d= evice *adev, > > pdata->bridge.type =3D pdata->next_bridge->type =3D=3D DRM_MODE= _CONNECTOR_DisplayPort > > ? DRM_MODE_CONNECTOR_DisplayPort : DRM_MODE_= CONNECTOR_eDP; > > > > - if (pdata->bridge.type =3D=3D DRM_MODE_CONNECTOR_DisplayPort) > > + if (pdata->bridge.type =3D=3D DRM_MODE_CONNECTOR_DisplayPort) { > > pdata->bridge.ops =3D DRM_BRIDGE_OP_EDID; > > > > + if (!pdata->no_hpd) > > + pdata->bridge.ops |=3D DRM_BRIDGE_OP_DETECT; > > + } > > + > > + if (!pdata->no_hpd && pdata->irq > 0) { > > + dev_err(pdata->dev, "registering IRQ %d\n", pdata->irq); > > + > > + ret =3D devm_request_threaded_irq(pdata->dev, pdata->ir= q, NULL, > > + ti_sn65dsi86_irq_handle= r, > > + IRQF_ONESHOT, "sn65dsi8= 6-irq", > > + pdata); > > + if (ret) > > + return dev_err_probe(pdata->dev, ret, > > + "Failed to register DP int= errupt\n"); > > + > > + /* Enable IRQ based HPD */ > > + regmap_write(pdata->regmap, SN_IRQ_EN_REG, IRQ_EN); >=20 > Why not put the above regmap_write() in the ti_sn_bridge_hpd_enable() cal= l? I assumed the IRQ handler may get used by other non-HPD events. Which is also why it was originally registered in the main probe(). HPD is just one feature of the interrupts. Of course it's only used for HPD now though. I guess I could have solved the bridge dependency by splitting the IRQ handler to have a dedicated HPD handler function which would return if the bridge wasn't initialised, but went with the deferred registration of the handler. I can move this and then leave it to anyone else implementing further IRQ features to refactor if needed. >=20 > -Doug