From: Herve Codina <herve.codina@bootlin.com>
To: "Luca Ceresoli" <luca.ceresoli@bootlin.com> (by way of Kory
Maincent <kory.maincent@bootlin.com>)
Cc: "Kory Maincent (TI.com)" <kory.maincent@bootlin.com>,
"Jyri Sarha" <jyri.sarha@iki.fi>,
"Tomi Valkeinen" <tomi.valkeinen@ideasonboard.com>,
"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>,
"Rob Herring" <robh@kernel.org>,
"Krzysztof Kozlowski" <krzk+dt@kernel.org>,
"Conor Dooley" <conor+dt@kernel.org>,
"Russell King" <linux@armlinux.org.uk>,
"Bartosz Golaszewski" <brgl@bgdev.pl>,
"Tony Lindgren" <tony@atomide.com>,
"Andrzej Hajda" <andrzej.hajda@intel.com>,
"Neil Armstrong" <neil.armstrong@linaro.org>,
"Robert Foss" <rfoss@kernel.org>,
"Laurent Pinchart" <Laurent.pinchart@ideasonboard.com>,
"Jonas Karlman" <jonas@kwiboo.se>,
"Jernej Skrabec" <jernej.skrabec@gmail.com>,
"Markus Schneider-Pargmann" <msp@baylibre.com>,
"Bajjuri Praneeth" <praneeth@ti.com>,
"Louis Chauvet" <louis.chauvet@bootlin.com>,
"Thomas Petazzoni" <thomas.petazzoni@bootlin.com>,
"Miguel Gazquez" <miguel.gazquez@bootlin.com>,
<dri-devel@lists.freedesktop.org>, <devicetree@vger.kernel.org>,
<linux-kernel@vger.kernel.org>,
<linux-arm-kernel@lists.infradead.org>,
<linux-omap@vger.kernel.org>
Subject: Re: [PATCH v2 05/20] drm/tilcdc: Convert legacy panel binding via DT overlay at boot time
Date: Mon, 5 Jan 2026 17:22:20 +0100 [thread overview]
Message-ID: <20260105172220.2d2edd28@bootlin.com> (raw)
In-Reply-To: <DF0K5UFX46JA.OH85T6IPC5MW@bootlin.com>
Hi Luca, Kory,
On Wed, 17 Dec 2025 15:23:26 +0100
"Luca Ceresoli" <luca.ceresoli@bootlin.com> (by way of Kory Maincent <kory.maincent@bootlin.com>) wrote:
> Hi,
>
> Cc: Hervé, can you review the DT overlay aspects?
Yes sure.
Here is my global review.
Depending on the discussion on things I have spotted, I will go deeper in
patch details.
...
> > +
> > +static void __init
> > +tilcdc_panel_update_prop(struct device_node *node, char *name,
> > + void *val, int length)
> > +{
> > + struct property *prop;
> > +
> > + prop = kzalloc(sizeof(*prop), GFP_KERNEL);
> > + if (!prop)
> > + return;
> > +
> > + prop->name = kstrdup(name, GFP_KERNEL);
> > + prop->length = length;
> > + prop->value = kmemdup(val, length, GFP_KERNEL);
> > + of_update_property(node, prop);
I would use OF changesets to perform the modification.
OF changesets are kind of atomic. You first prepare all modifications in a
changeset and then you apply the changeset.
If something goes wrong, the changeset is removed.
Also, if something goes wrong during the changeset preparation, you can abort
without any modification on the live device-tree.
> > +}
> > +
> > +static int __init tilcdc_panel_copy_props(struct device_node *old_panel,
> > + struct device_node *new_panel)
> > +{
> > + struct device_node *child, *old_timing, *new_timing, *panel_info;
> > + u32 invert_pxl_clk = 0, sync_edge = 0;
> > + struct property *prop;
> > +
> > + /* Copy all panel properties to the new panel node */
> > + for_each_property_of_node(old_panel, prop) {
> > + if (!strncmp(prop->name, "compatible", sizeof("compatible")))
> > + continue;
> > +
> > + tilcdc_panel_update_prop(new_panel, prop->name,
> > + prop->value, prop->length);
> > + }
> > +
> > + child = of_get_child_by_name(old_panel, "display-timings");
>
> There's some housekeeping code in this function to ensure you put all the
> device_node refs. It would be simpler and less error prone to use a cleanup
> action. E.g.:
>
> - struct device_node *child, *old_timing, *new_timing, *panel_info;
>
> - child = of_get_child_by_name(old_panel, "display-timings");
> + struct device_node *child __free(device_node) = of_get_child_by_name(old_panel, "display-timings");
>
> > + if (!child)
> > + return -EINVAL;
> > +
> > + /* The default display timing is the one specified as native-mode.
> > + * If no native-mode is specified then the first node is assumed
> > + * to be the native mode.
> > + */
> > + old_timing = of_parse_phandle(child, "native-mode", 0);
> > + if (!old_timing) {
> > + old_timing = of_get_next_child(child, NULL);
> > + if (!old_timing) {
> > + of_node_put(child);
> > + return -EINVAL;
> > + }
> > + }
> > + of_node_put(child);
> > +
> > + new_timing = of_get_child_by_name(new_panel, "panel-timing");
> > + if (!new_timing)
> > + return -EINVAL;
Here, for instance, you have already modified your live tree and you abort the
operation. Your live tree is somewhat corrupted.
> > +
> > + /* Copy all panel timing property to the new panel node */
> > + for_each_property_of_node(old_timing, prop)
> > + tilcdc_panel_update_prop(new_timing, prop->name,
> > + prop->value, prop->length);
> > +
> > + panel_info = of_get_child_by_name(old_panel, "panel-info");
> > + if (!panel_info)
> > + return -EINVAL;
>
> tilcdc_panel_update_prop() has previously done various allocations which
> will not be freed if you return here. You shoudl probably do all the
> of_get_*() at the top, and if they all succeed start copying data along
> with with the needed allocations.
>
> > + /* Looked only for these two parameter as all the other are always
> > + * set to default and not related to common DRM properties.
> > + */
> > + of_property_read_u32(panel_info, "invert-pxl-clk", &invert_pxl_clk);
> > + of_property_read_u32(panel_info, "sync-edge", &sync_edge);
> > +
> > + if (!invert_pxl_clk)
> > + tilcdc_panel_update_prop(new_timing, "pixelclk-active",
> > + &(int){1}, sizeof(int));
> > +
> > + if (!sync_edge)
> > + tilcdc_panel_update_prop(new_timing, "syncclk-active",
> > + &(int){1}, sizeof(int));
> > +
> > + of_node_put(panel_info);
> > + of_node_put(old_timing);
> > + of_node_put(new_timing);
> > + return 0;
> > +}
> > +
> > +static const struct of_device_id tilcdc_panel_of_match[] __initconst = {
> > + { .compatible = "ti,tilcdc,panel", },
> > + {},
> > +};
> > +
> > +static const struct of_device_id tilcdc_of_match[] __initconst = {
> > + { .compatible = "ti,am33xx-tilcdc", },
> > + { .compatible = "ti,da850-tilcdc", },
> > + {},
> > +};
> > +
> > +static int __init tilcdc_panel_legacy_init(void)
> > +{
> > + struct device_node *panel, *lcdc, *new_panel;
> > + void *dtbo_start;
> > + u32 dtbo_size;
> > + int ovcs_id;
> > + int ret;
> > +
> > + lcdc = of_find_matching_node(NULL, tilcdc_of_match);
> > + panel = of_find_matching_node(NULL, tilcdc_panel_of_match);
> > +
> > + if (!of_device_is_available(panel) ||
> > + !of_device_is_available(lcdc)) {
> > + ret = -ENODEV;
> > + goto out;
> > + }
> > +
> > + dtbo_start = __dtbo_tilcdc_panel_legacy_begin;
> > + dtbo_size = __dtbo_tilcdc_panel_legacy_end -
> > + __dtbo_tilcdc_panel_legacy_begin;
> > +
> > + ret = of_overlay_fdt_apply(dtbo_start, dtbo_size, &ovcs_id, NULL);
> > + if (ret)
> > + goto out;
As soon as the overlay is applied, the driver handling the panel-dti node
can be probed.
Modifying some properties after applying the overlay could be not seen by the
driver.
> > +
> > + new_panel = of_find_node_by_name(NULL, "panel-dpi");
> > + if (!new_panel) {
> > + ret = -ENODEV;
> > + goto overlay_remove;
> > + }
> > +
> > + ret = tilcdc_panel_copy_props(panel, new_panel);
> > + if (ret)
> > + goto overlay_remove;
> > +
> > + /* Remove compatible property to avoid any driver compatible match */
> > + of_remove_property(panel, of_find_property(panel, "compatible",
> > + NULL));
> > +overlay_remove:
> > + of_overlay_remove(&ovcs_id);
>
> Is it correct to remove the overlay here? Won't it remove what you have
> just added?
Agreed, the overlay should not be removed here.
>
> > +out:
> > + of_node_put(new_panel);
> > + of_node_put(panel);
> > + of_node_put(lcdc);
>
> Here too you can use cleanup actions, even though the current code is
> slightly simpler than tilcdc_panel_copy_props as far as of_node_put() is
> concerned.
>
> > + return ret;
> > +}
> > +
> > +subsys_initcall(tilcdc_panel_legacy_init);
IMHO, the call to tilcdc_panel_legacy_init() will be too late.
subsys initcalls are called after arch initcalls.
During arch initcalls, of_platform_populate_init() is called
https://elixir.bootlin.com/linux/v6.19-rc3/source/drivers/of/platform.c#L599
The root node is populated and handled by the platform bus.
Later at subsys initcall, the tilcdc_panel_legacy_init() function is called.
This function starts by applying the overlay and so a new node (panel-dpi)
is added at the root node.
This trigger an OF_RECONFIG_CHANGE_ADD event handled by the platform bus.
https://elixir.bootlin.com/linux/v6.19-rc3/source/drivers/of/platform.c#L731
If the "panel-dpi" compatible driver is available, its probe() is called but
the panel-dpi DT node is not fully correct. Indeed, tilcdc_panel_copy_props()
has not be called yet.
Also, the legacy compatible string is removed after the of_platform_populate_init()
call. The legacy driver could have been already probed.
Of course, please correct me if I have misunderstood something.
Best regards,
Hervé
next prev parent reply other threads:[~2026-01-05 16:22 UTC|newest]
Thread overview: 46+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-12-11 16:38 [PATCH v2 00/20] Clean and update tilcdc driver to support DRM_BRIDGE_ATTACH_NO_CONNECTOR Kory Maincent (TI.com)
2025-12-11 16:38 ` [PATCH v2 01/20] dt-bindings: display: tilcdc: Convert to DT schema Kory Maincent (TI.com)
2025-12-16 6:01 ` Krzysztof Kozlowski
2025-12-17 11:20 ` Kory Maincent
2025-12-11 16:38 ` [PATCH v2 02/20] dt-bindings: display: tilcdc: Mark panel binding as deprecated Kory Maincent (TI.com)
2025-12-16 6:02 ` Krzysztof Kozlowski
2025-12-11 16:38 ` [PATCH v2 03/20] drm/tilcdc: Remove simulate_vesa_sync flag Kory Maincent (TI.com)
2025-12-17 14:20 ` Luca Ceresoli
2025-12-18 15:46 ` Andreas Kemnade
2025-12-11 16:38 ` [PATCH v2 04/20] drm/tilcdc: Add support for DRM bus flags and simplify panel config Kory Maincent (TI.com)
2025-12-17 14:20 ` Luca Ceresoli
2025-12-11 16:38 ` [PATCH v2 05/20] drm/tilcdc: Convert legacy panel binding via DT overlay at boot time Kory Maincent (TI.com)
2025-12-17 14:23 ` Luca Ceresoli
2026-01-05 14:29 ` Kory Maincent
2026-01-05 17:18 ` Luca Ceresoli
2026-01-05 16:22 ` Herve Codina [this message]
2026-01-05 17:18 ` Kory Maincent
2026-01-06 7:34 ` Herve Codina
2025-12-11 16:38 ` [PATCH v2 06/20] drm/tilcdc: Remove tilcdc panel driver Kory Maincent (TI.com)
2025-12-17 14:23 ` Luca Ceresoli
2025-12-11 16:38 ` [PATCH v2 07/20] drm/tilcdc: Remove component framework support Kory Maincent (TI.com)
2025-12-11 16:38 ` [PATCH v2 08/20] drm/tilcdc: Remove tilcdc_panel_info structure Kory Maincent (TI.com)
2025-12-11 16:38 ` [PATCH v2 09/20] drm/tilcdc: Remove redundant #endif/#ifdef in debugfs code Kory Maincent (TI.com)
2025-12-11 16:38 ` [PATCH v2 10/20] drm/tilcdc: Remove unused encoder and connector tracking arrays Kory Maincent (TI.com)
2025-12-17 14:24 ` Luca Ceresoli
2025-12-11 16:38 ` [PATCH v2 11/20] drm/tilcdc: Rename external_encoder and external_connector to encoder and connector Kory Maincent (TI.com)
2025-12-17 14:25 ` Luca Ceresoli
2025-12-11 16:38 ` [PATCH v2 12/20] drm/tilcdc: Rename tilcdc_external to tilcdc_encoder Kory Maincent (TI.com)
2025-12-17 14:25 ` Luca Ceresoli
2025-12-11 16:38 ` [PATCH v2 13/20] drm/tilcdc: Remove the useless module list support Kory Maincent (TI.com)
2025-12-17 14:25 ` Luca Ceresoli
2026-01-05 15:45 ` Kory Maincent
2025-12-11 16:38 ` [PATCH v2 14/20] drm/tilcdc: Modernize driver initialization and cleanup paths Kory Maincent (TI.com)
2025-12-17 14:25 ` Luca Ceresoli
2025-12-11 16:38 ` [PATCH v2 15/20] drm/tilcdc: Remove the use of drm_device private_data Kory Maincent (TI.com)
2025-12-17 14:26 ` Luca Ceresoli
2025-12-11 16:39 ` [PATCH v2 16/20] drm/bridge: tda998x: Remove component support Kory Maincent (TI.com)
2025-12-17 14:26 ` Luca Ceresoli
2025-12-11 16:39 ` [PATCH v2 17/20] drm/bridge: tda998x: Move tda998x_create/destroy into probe and remove Kory Maincent (TI.com)
2025-12-17 14:26 ` Luca Ceresoli
2025-12-11 16:39 ` [PATCH v2 18/20] drm/bridge: tda998x: Remove useless tda998x_connector_destroy wrapper Kory Maincent (TI.com)
2025-12-17 14:26 ` Luca Ceresoli
2025-12-11 16:39 ` [PATCH v2 19/20] drm/bridge: tda998x: Add support for DRM_BRIDGE_ATTACH_NO_CONNECTOR Kory Maincent (TI.com)
2025-12-17 14:26 ` Luca Ceresoli
2025-12-11 16:39 ` [PATCH v2 20/20] drm/tilcdc: " Kory Maincent (TI.com)
2025-12-17 14:26 ` Luca Ceresoli
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=20260105172220.2d2edd28@bootlin.com \
--to=herve.codina@bootlin.com \
--cc=Laurent.pinchart@ideasonboard.com \
--cc=airlied@gmail.com \
--cc=andrzej.hajda@intel.com \
--cc=brgl@bgdev.pl \
--cc=conor+dt@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=dri-devel@lists.freedesktop.org \
--cc=jernej.skrabec@gmail.com \
--cc=jonas@kwiboo.se \
--cc=jyri.sarha@iki.fi \
--cc=kory.maincent@bootlin.com \
--cc=krzk+dt@kernel.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-omap@vger.kernel.org \
--cc=linux@armlinux.org.uk \
--cc=louis.chauvet@bootlin.com \
--cc=luca.ceresoli@bootlin.com \
--cc=maarten.lankhorst@linux.intel.com \
--cc=miguel.gazquez@bootlin.com \
--cc=mripard@kernel.org \
--cc=msp@baylibre.com \
--cc=neil.armstrong@linaro.org \
--cc=praneeth@ti.com \
--cc=rfoss@kernel.org \
--cc=robh@kernel.org \
--cc=simona@ffwll.ch \
--cc=thomas.petazzoni@bootlin.com \
--cc=tomi.valkeinen@ideasonboard.com \
--cc=tony@atomide.com \
--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