From: Liu Ying <victor.liu@nxp.com>
To: Biju <biju.das.au@gmail.com>,
Andrzej Hajda <andrzej.hajda@intel.com>,
Neil Armstrong <neil.armstrong@linaro.org>,
Robert Foss <rfoss@kernel.org>,
Maarten Lankhorst <maarten.lankhorst@linux.intel.com>,
Maxime Ripard <mripard@kernel.org>,
Thomas Zimmermann <tzimmermann@suse.de>,
David Airlie <airlied@gmail.com>, Simona Vetter <simona@ffwll.ch>
Cc: Biju Das <biju.das.jz@bp.renesas.com>,
Laurent Pinchart <Laurent.pinchart@ideasonboard.com>,
Jonas Karlman <jonas@kwiboo.se>,
Jernej Skrabec <jernej.skrabec@gmail.com>,
dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org,
Geert Uytterhoeven <geert+renesas@glider.be>,
Prabhakar Mahadev Lad <prabhakar.mahadev-lad.rj@bp.renesas.com>,
linux-renesas-soc@vger.kernel.org
Subject: Re: [PATCH v2] drm/bridge: ite-it6263: Add suspend/resume support
Date: Fri, 17 Apr 2026 14:05:03 +0800 [thread overview]
Message-ID: <00e2f34a-c488-4a61-bb87-0f0431990c3f@nxp.com> (raw)
In-Reply-To: <20260416082928.169347-1-biju.das.jz@bp.renesas.com>
Hi Biju,
On Thu, Apr 16, 2026 at 09:29:25AM +0100, Biju wrote:
> [You don't often get email from biju.das.au@gmail.com. Learn why this is important at https://aka.ms/LearnAboutSenderIdentification ]
>
> From: Biju Das <biju.das.jz@bp.renesas.com>
>
> On the RZ/G3L SMARC EVK using PSCI, suspend to RAM powers down the ITE
> IT6263 chip. The display controller driver's system PM callbacks invoke
> drm_mode_config_helper_{suspend,resume}, which in turn call the bridge's
> atomic_{disable,enable} callbacks can handle suspend/resume for the
> bridge without dedicated PM ops.
>
> Introduce it6263_bridge_init() and it6263_bridge_uninit() helpers to
> consolidate power sequencing, hardware reset, I2C address setup, and
> LVDS/HDMI configuration. These replace the open-coded init sequence in
> probe() and are hooked into atomic_enable/atomic_disable respectively,
> guarded by a powered flag to avoid redundant re-initialisation.
>
> Switch from devm_regulator_bulk_get_enable() to devm_regulator_bulk_get()
> so that regulators can be explicitly enabled and disabled across power
> cycles. Move reset_gpio and regulator state into the it6263 struct so they
> are accessible beyond probe time.
>
> Add a remove() callback to cleanly power down the bridge on driver unbind
> via it6263_bridge_uninit().
>
> Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
> ---
> v1->v2:
> * Dropped system PM callbacks instead using bridge's
> atomic_{disable,enable} callbacks to handle suspend/resume.
> ---
> drivers/gpu/drm/bridge/ite-it6263.c | 88 ++++++++++++++++++++++++-----
> 1 file changed, 73 insertions(+), 15 deletions(-)
"suspend/resume" in subject makes people think that this patch probably
adds runtime PM or system PM support. To avoid this, can you change the
subject to something like:
"drm/bridge: ite-it6263: Support power cycle in runtime"
?
>
> diff --git a/drivers/gpu/drm/bridge/ite-it6263.c b/drivers/gpu/drm/bridge/ite-it6263.c
> index 4f3ebb7af4d4..1954bb11f7f4 100644
> --- a/drivers/gpu/drm/bridge/ite-it6263.c
> +++ b/drivers/gpu/drm/bridge/ite-it6263.c
> @@ -200,9 +200,13 @@ struct it6263 {
> struct regmap *lvds_regmap;
> struct drm_bridge bridge;
> struct drm_bridge *next_bridge;
> + struct gpio_desc *reset_gpio;
> + struct regulator_bulk_data *supplies;
I would move it6263_supplies[] on top of struct it6263 definition and use
'struct regulator_bulk_data supplies[ARRAY_SIZE(it6263_supplies)];' here,
so that you may drop devm_kcalloc() for the supplies array in probe.
> + unsigned int num_supplies;
The above new supplies array has a known size, so this can be dropped and
you may get the number of supplies via ARRAY_SIZE(it->supplies).
> int lvds_data_mapping;
> bool lvds_dual_link;
> bool lvds_link12_swap;
> + bool powered;
> };
>
> static inline struct it6263 *bridge_to_it6263(struct drm_bridge *bridge)
> @@ -578,6 +582,41 @@ static int it6263_read_edid(void *data, u8 *buf, unsigned int block, size_t len)
> return 0;
> }
>
> +static int it6263_bridge_init(struct it6263 *it)
> +{
> + int ret;
> +
> + ret = regulator_bulk_enable(it->num_supplies, it->supplies);
> + if (ret) {
> + dev_err(it->dev, "failed to enable power supplies\n");
> + return ret;
> + }
> +
> + it6263_hw_reset(it->reset_gpio);
> +
> + ret = it6263_lvds_set_i2c_addr(it);
> + if (ret) {
> + dev_err(it->dev, "failed to set I2C addr\n");
> + regulator_bulk_disable(it->num_supplies, it->supplies);
I know that you call it6263_bridge_init() in probe, probably because you
want to enable the regulators for hotplug detect after probe(it6263_detect()
reads register HDMI_REG_SYS_STATUS to do the detection). However, an idea[1]
is to wrap the register read operation with regulator_bulk_enable() and
regulator_bulk_disable() in it6263_detect() so that you may drop
it6263_bridge_init() from probe. With that, it6263_bridge_init() is now
only called from atomic_enable, which means that the initialization code
can be open-coded and the initialization is supposed to be successful(due
to the "atomic" nature) hence no need to do the regulator disablement
bailout(error message in dmesg is sufficient).
> + return ret;
> + }
> +
> + it6263_lvds_config(it);
> + it6263_hdmi_config(it);
> +
> + it->powered = true;
If you drop it6263_bridge_init() from probe, I think 'powered' flag can be
dropped too.
> +
> + return 0;
> +}
> +
> +static int it6263_bridge_uninit(struct it6263 *it)
> +{
> + regulator_bulk_disable(it->num_supplies, it->supplies);
> + it->powered = false;
> +
> + return 0;
> +}
> +
> static void it6263_bridge_atomic_disable(struct drm_bridge *bridge,
> struct drm_atomic_state *state)
> {
> @@ -587,6 +626,8 @@ static void it6263_bridge_atomic_disable(struct drm_bridge *bridge,
> regmap_write(it->hdmi_regmap, HDMI_REG_PKT_GENERAL_CTRL, 0);
> regmap_write(it->hdmi_regmap, HDMI_REG_AFE_DRV_CTRL,
> AFE_DRV_RST | AFE_DRV_PWD);
> +
> + it6263_bridge_uninit(it);
Well, this could effectively disable the regulators and hotplug detection
won't work then. So, again, the above idea[1] helps.
> }
>
> static void it6263_bridge_atomic_enable(struct drm_bridge *bridge,
> @@ -603,6 +644,9 @@ static void it6263_bridge_atomic_enable(struct drm_bridge *bridge,
> bool pclk_high;
> int i, ret;
>
> + if (!it->powered)
> + it6263_bridge_init(it);
> +
> connector = drm_atomic_get_new_connector_for_encoder(state,
> bridge->encoder);
> crtc = drm_atomic_get_new_connector_state(state, connector)->crtc;
> @@ -840,7 +884,6 @@ static const struct drm_bridge_funcs it6263_bridge_funcs = {
> static int it6263_probe(struct i2c_client *client)
> {
> struct device *dev = &client->dev;
> - struct gpio_desc *reset_gpio;
> struct it6263 *it;
> int ret;
>
> @@ -858,13 +901,21 @@ static int it6263_probe(struct i2c_client *client)
> return dev_err_probe(dev, PTR_ERR(it->hdmi_regmap),
> "failed to init I2C regmap for HDMI\n");
>
> - reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
> - if (IS_ERR(reset_gpio))
> - return dev_err_probe(dev, PTR_ERR(reset_gpio),
> + it->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
> + if (IS_ERR(it->reset_gpio))
> + return dev_err_probe(dev, PTR_ERR(it->reset_gpio),
> "failed to get reset gpio\n");
>
> - ret = devm_regulator_bulk_get_enable(dev, ARRAY_SIZE(it6263_supplies),
> - it6263_supplies);
> + it->num_supplies = ARRAY_SIZE(it6263_supplies);
> + it->supplies = devm_kcalloc(dev, it->num_supplies,
> + sizeof(*it->supplies), GFP_KERNEL);
> + if (!it->supplies)
> + return -ENOMEM;
> +
> + for (unsigned int i = 0; i < it->num_supplies; i++)
Nit: I would define i together with the other local variables at the beginning
of this function.
> + it->supplies[i].supply = it6263_supplies[i];
> +
> + ret = devm_regulator_bulk_get(dev, it->num_supplies, it->supplies);
> if (ret)
> return dev_err_probe(dev, ret, "failed to get power supplies\n");
>
> @@ -872,12 +923,6 @@ static int it6263_probe(struct i2c_client *client)
> if (ret)
> return ret;
>
> - it6263_hw_reset(reset_gpio);
> -
> - ret = it6263_lvds_set_i2c_addr(it);
> - if (ret)
> - return dev_err_probe(dev, ret, "failed to set I2C addr\n");
> -
> it->lvds_i2c = devm_i2c_new_dummy_device(dev, client->adapter,
> LVDS_INPUT_CTRL_I2C_ADDR);
> if (IS_ERR(it->lvds_i2c))
> @@ -890,8 +935,9 @@ static int it6263_probe(struct i2c_client *client)
> return dev_err_probe(dev, PTR_ERR(it->lvds_regmap),
> "failed to init I2C regmap for LVDS\n");
>
> - it6263_lvds_config(it);
> - it6263_hdmi_config(it);
> + ret = it6263_bridge_init(it);
> + if (ret)
> + return ret;
>
> i2c_set_clientdata(client, it);
>
> @@ -903,7 +949,18 @@ static int it6263_probe(struct i2c_client *client)
> it->bridge.vendor = "ITE";
> it->bridge.product = "IT6263";
>
> - return devm_drm_bridge_add(dev, &it->bridge);
> + ret = devm_drm_bridge_add(dev, &it->bridge);
> + if (ret)
> + it6263_bridge_uninit(it);
> +
> + return ret;
> +}
> +
> +static void it6263_remove(struct i2c_client *i2c)
> +{
> + struct it6263 *it = i2c_get_clientdata(i2c);
> +
> + it6263_bridge_uninit(it);
> }
>
> static const struct of_device_id it6263_of_match[] = {
> @@ -920,6 +977,7 @@ MODULE_DEVICE_TABLE(i2c, it6263_i2c_ids);
>
> static struct i2c_driver it6263_driver = {
> .probe = it6263_probe,
> + .remove = it6263_remove,
> .driver = {
> .name = "it6263",
> .of_match_table = it6263_of_match,
> --
> 2.43.0
>
--
Regards,
Liu Ying
next prev parent reply other threads:[~2026-04-17 6:03 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-04-16 8:29 Biju
2026-04-17 6:05 ` Liu Ying [this message]
2026-04-17 10:49 ` Biju Das
2026-04-20 2:26 ` Liu Ying
2026-04-20 6:15 ` Biju Das
2026-04-21 3:20 ` Liu Ying
2026-04-21 9:24 ` Biju Das
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=00e2f34a-c488-4a61-bb87-0f0431990c3f@nxp.com \
--to=victor.liu@nxp.com \
--cc=Laurent.pinchart@ideasonboard.com \
--cc=airlied@gmail.com \
--cc=andrzej.hajda@intel.com \
--cc=biju.das.au@gmail.com \
--cc=biju.das.jz@bp.renesas.com \
--cc=dri-devel@lists.freedesktop.org \
--cc=geert+renesas@glider.be \
--cc=jernej.skrabec@gmail.com \
--cc=jonas@kwiboo.se \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-renesas-soc@vger.kernel.org \
--cc=maarten.lankhorst@linux.intel.com \
--cc=mripard@kernel.org \
--cc=neil.armstrong@linaro.org \
--cc=prabhakar.mahadev-lad.rj@bp.renesas.com \
--cc=rfoss@kernel.org \
--cc=simona@ffwll.ch \
--cc=tzimmermann@suse.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®