Received: by 2002:a05:6902:102b:0:0:0:0 with SMTP id x11csp1573724ybt; Sat, 20 Jun 2020 14:44:36 -0700 (PDT) X-Google-Smtp-Source: ABdhPJzIHYecJMtaHdCsk35QM097s7rxKUJX4Z8DUXUYGtwSaNpkPi1ZEwKzgHwe/wTRZURxQh6y X-Received: by 2002:a17:906:b79a:: with SMTP id dt26mr9838490ejb.422.1592689476377; Sat, 20 Jun 2020 14:44:36 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1592689476; cv=none; d=google.com; s=arc-20160816; b=BLtAIu/kc4zb6uW+S99S3Ismv90tipkR9ZcSAceeL2wNlMPaYch4ZpKvuXB08mz34v k/d3LkWkLqjYQIilymmE7DRwZZOgzvLgvk8+F3IrIYQW+R4G2zd4jnlvUxB0QT1JSlsS DFUiHD4f88DIYA9GuHSoojT4RV1gLWg8K+hf7+ax3WiRdZkQQ72Pd1wsP0/g5r32mrFk +/c3ySQSQHSMomtj5t3RmD5u+NdmL8nv+AZq+plmX2Zg1e68L0qTjSJjEXwAZbFZn7go gleDlPg3D7503kDCs5hX/B9yCBsXaLaxK7/uKPnfhC7kcN3cEf3MDhwRSMsh8QdADIN7 Hlxw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:in-reply-to:content-disposition :mime-version:references:message-id:subject:cc:to:from:date; bh=E2Sq8McI54Y7WRytwzyU8gSTHL0KUoz5qTLzjkidxFo=; b=ZcLTMPVPPQrxytNS61YXSQxtgl0FaKp6zKRRXOZHu4az0RBgmE9u+EARqommyHp5qG raqZsb8usgJYGQ0rxnslKw/KSfQqupVCo8848kTOA0akTVicvCLDKOWPZy11zy0kgqNf 0yNRJtJt3CXb6TFAr4+Re+tiWDc1R2uXUCR/1KPN4xWKRJt6cImxsfwMhq0A5vseeDnV 2sQPcTAUUgEEyF44gT1ZKl9XDmL+xSteHx0UGydcaeIhx1qTYjq+b1oPudtZggLx/lYD JfDpExtKB1wjxSyI6k7zw6voUQCm/MmTpUqfeFkLlm/frmDCuoJ+CDG7uyo1WLWNbeZ0 gGCg== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org ([23.128.96.18]) by mx.google.com with ESMTP id a9si6485908ejk.553.2020.06.20.14.44.13; Sat, 20 Jun 2020 14:44:36 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729086AbgFTVmb (ORCPT + 99 others); Sat, 20 Jun 2020 17:42:31 -0400 Received: from asavdk3.altibox.net ([109.247.116.14]:39536 "EHLO asavdk3.altibox.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729036AbgFTVmb (ORCPT ); Sat, 20 Jun 2020 17:42:31 -0400 Received: from ravnborg.org (unknown [188.228.123.71]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by asavdk3.altibox.net (Postfix) with ESMTPS id 9C20520021; Sat, 20 Jun 2020 23:42:26 +0200 (CEST) Date: Sat, 20 Jun 2020 23:42:25 +0200 From: Sam Ravnborg To: Enric Balletbo i Serra Cc: linux-kernel@vger.kernel.org, Jernej Skrabec , drinkcat@chromium.org, Jonas Karlman , David Airlie , Neil Armstrong , dri-devel@lists.freedesktop.org, Andrzej Hajda , Laurent Pinchart , hsinyi@chromium.org, matthias.bgg@gmail.com, Collabora Kernel ML Subject: Re: [PATCH 3/3] drm/bridge: ps8640: Rework power state handling Message-ID: <20200620214225.GD74146@ravnborg.org> References: <20200615205320.790334-1-enric.balletbo@collabora.com> <20200615205320.790334-4-enric.balletbo@collabora.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20200615205320.790334-4-enric.balletbo@collabora.com> X-CMAE-Score: 0 X-CMAE-Analysis: v=2.3 cv=edQTgYMH c=1 sm=1 tr=0 a=S6zTFyMACwkrwXSdXUNehg==:117 a=S6zTFyMACwkrwXSdXUNehg==:17 a=kj9zAlcOel0A:10 a=QX4gbG5DAAAA:8 a=e5mUnYsNAAAA:8 a=gsnspH9XThcp_ju6__IA:9 a=CjuIK1q_8ugA:10 a=AbAUZ8qAyYyZVLSsDulk:22 a=Vxmtnl_E_bksehYqCbjh:22 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Hi Enric. On Mon, Jun 15, 2020 at 10:53:20PM +0200, Enric Balletbo i Serra wrote: > The get_edid() callback can be triggered anytime by an ioctl, i.e > > drm_mode_getconnector (ioctl) > -> drm_helper_probe_single_connector_modes > -> drm_bridge_connector_get_modes > -> ps8640_bridge_get_edid > > Actually if the bridge pre_enable() function was not called before > get_edid(), the driver will not be able to get the EDID properly and > display will not work until a second get_edid() call is issued and if > pre_enable() is called before. Is it correct to fix this in the driver? Why not just fail and tell user-sapce to try again later? (Dunno what error-code to use - there must be one). Then we avoid complicating drivers fro somethign we really should fix in user-space. > The side effect of this, for example, is > that you see anything when `Frecon` starts, neither the splash screen, that you do not see ... (Otherwise I do not parse the above). > until the graphical session manager starts. > > To fix this we need to make sure that all we need is enabled before > reading the EDID. This means the following: > > 1. If get_edid() is called before having the device powered we need to > power on the device. In such case, the driver will power off again the > device. > > 2. If get_edid() is called after having the device powered, all should > just work. We added a powered flag in order to avoid recurrent calls > to ps8640_bridge_poweron() and unneeded delays. > > 3. This seems to be specific for this device, but we need to make sure > the panel is powered on before do a power on cycle on this device. > Otherwise the device fails to retrieve the EDID. Step 3. looks like an ugly hack too.... > > Signed-off-by: Enric Balletbo i Serra > --- > > drivers/gpu/drm/bridge/parade-ps8640.c | 79 ++++++++++++++++++++++++-- > 1 file changed, 73 insertions(+), 6 deletions(-) > > diff --git a/drivers/gpu/drm/bridge/parade-ps8640.c b/drivers/gpu/drm/bridge/parade-ps8640.c > index 9f7b7a9c53c52..ca651480891df 100644 > --- a/drivers/gpu/drm/bridge/parade-ps8640.c > +++ b/drivers/gpu/drm/bridge/parade-ps8640.c > @@ -65,6 +65,7 @@ struct ps8640 { > struct regulator_bulk_data supplies[2]; > struct gpio_desc *gpio_reset; > struct gpio_desc *gpio_powerdown; > + bool powered; > }; > > static inline struct ps8640 *bridge_to_ps8640(struct drm_bridge *e) > @@ -91,13 +92,25 @@ static int ps8640_bridge_vdo_control(struct ps8640 *ps_bridge, > return 0; > } > > -static void ps8640_pre_enable(struct drm_bridge *bridge) > +static void ps8640_bridge_poweron(struct ps8640 *ps_bridge) > { > - struct ps8640 *ps_bridge = bridge_to_ps8640(bridge); > struct i2c_client *client = ps_bridge->page[PAGE2_TOP_CNTL]; > + struct drm_bridge *panel; > unsigned long timeout; > int ret, status; > > + if (ps_bridge->powered) > + return; > + > + /* > + * That seems to be specific to this chip, and a weird behaviour, but > + * we need to call drm_panel_prepare before issuing a poweron cycle. If > + * we don't do this, the chip is not able to read properly the EDID. > + */ > + panel = ps_bridge->panel_bridge; > + if (panel->funcs && panel->funcs->pre_enable) > + panel->funcs->pre_enable(panel); > + > ret = regulator_bulk_enable(ARRAY_SIZE(ps_bridge->supplies), > ps_bridge->supplies); > if (ret < 0) { > @@ -164,6 +177,8 @@ static void ps8640_pre_enable(struct drm_bridge *bridge) > goto err_regulators_disable; > } > > + ps_bridge->powered = true; > + > return; > > err_regulators_disable: > @@ -171,12 +186,13 @@ static void ps8640_pre_enable(struct drm_bridge *bridge) > ps_bridge->supplies); > } > > -static void ps8640_post_disable(struct drm_bridge *bridge) > +static void ps8640_bridge_poweroff(struct ps8640 *ps_bridge) > { > - struct ps8640 *ps_bridge = bridge_to_ps8640(bridge); > + struct drm_bridge *panel; > int ret; > > - ps8640_bridge_vdo_control(ps_bridge, DISABLE); > + if (!ps_bridge->powered) > + return; > > gpiod_set_value(ps_bridge->gpio_reset, 1); > gpiod_set_value(ps_bridge->gpio_powerdown, 1); > @@ -184,6 +200,32 @@ static void ps8640_post_disable(struct drm_bridge *bridge) > ps_bridge->supplies); > if (ret < 0) > DRM_ERROR("cannot disable regulators %d\n", ret); > + > + panel = ps_bridge->panel_bridge; > + if (panel->funcs && panel->funcs->post_disable) > + panel->funcs->post_disable(panel); > + > + ps_bridge->powered = false; > +} > + > +static void ps8640_pre_enable(struct drm_bridge *bridge) > +{ > + struct ps8640 *ps_bridge = bridge_to_ps8640(bridge); > + int ret; > + > + ps8640_bridge_poweron(ps_bridge); > + > + ret = ps8640_bridge_vdo_control(ps_bridge, DISABLE); > + if (ret < 0) > + ps8640_bridge_poweroff(ps_bridge); > +} > + > +static void ps8640_post_disable(struct drm_bridge *bridge) > +{ > + struct ps8640 *ps_bridge = bridge_to_ps8640(bridge); > + > + ps8640_bridge_vdo_control(ps_bridge, DISABLE); > + ps8640_bridge_poweroff(ps_bridge); > } > > static int ps8640_bridge_attach(struct drm_bridge *bridge, > @@ -249,9 +291,34 @@ static struct edid *ps8640_bridge_get_edid(struct drm_bridge *bridge, > struct drm_connector *connector) > { > struct ps8640 *ps_bridge = bridge_to_ps8640(bridge); > + bool poweroff = !ps_bridge->powered; > + struct edid *edid; > + > + /* > + * When we end calling get_edid() triggered by an ioctl, i.e > + * > + * drm_mode_getconnector (ioctl) > + * -> drm_helper_probe_single_connector_modes > + * -> drm_bridge_connector_get_modes > + * -> ps8640_bridge_get_edid > + * > + * We need to make sure that what we need is enabled before reading > + * EDID, for this chip, we need to do a full poweron, otherwise it will > + * fail. > + */ > + ps8640_bridge_poweron(ps_bridge); > > - return drm_get_edid(connector, > + edid = drm_get_edid(connector, > ps_bridge->page[PAGE0_DP_CNTL]->adapter); > + > + /* > + * If we call the get_edid() function without having enabled the chip > + * before, return the chip to its original power state. > + */ > + if (poweroff) > + ps8640_bridge_poweroff(ps_bridge); > + > + return edid; > } > > static const struct drm_bridge_funcs ps8640_bridge_funcs = { > -- > 2.27.0 > > _______________________________________________ > dri-devel mailing list > dri-devel@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/dri-devel