]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
drm/rockchip: dw_hdmi: avoid direct dereference of phy->dev.of_node
authorVladimir Oltean <vladimir.oltean@nxp.com>
Tue, 5 May 2026 10:05:07 +0000 (13:05 +0300)
committerHeiko Stuebner <heiko@sntech.de>
Thu, 21 May 2026 09:35:04 +0000 (11:35 +0200)
The dw_hdmi-rockchip driver validates pixel clock rates against the
HDMI PHY's internal clock provider on certain SoCs like RK3328.
This is currently achieved by dereferencing hdmi->phy->dev.of_node
to obtain the provider node, which violates the Generic PHY API's
encapsulation (the goal is for struct phy to be an opaque pointer
with a hidden definition, to be interacted with only using API
functions or NULL pointer checks, for the case where optional variants
of phy_get() did not find a PHY).

Refactor dw_hdmi_rockchip_bind() to perform a manual phandle lookup
on the "hdmi" PHY index within the controller's DT node. This provides
a parallel path to the clock provider's OF node without relying on the
internal structure of the struct phy handle.

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: Heiko Stuebner <heiko@sntech.de>
Link: https://patch.msgid.link/20260505100523.1922388-16-vladimir.oltean@nxp.com
drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c

index 0dc1eb5d2ae390f465b6e4b2df88730fd8b75e15..7abb42e486c027d83b5f0916547ab83a156eac4a 100644 (file)
@@ -537,21 +537,22 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master,
                                 void *data)
 {
        struct platform_device *pdev = to_platform_device(dev);
+       struct device_node *np = dev_of_node(dev);
        struct dw_hdmi_plat_data *plat_data;
        const struct of_device_id *match;
        struct drm_device *drm = data;
        struct drm_encoder *encoder;
        struct rockchip_hdmi *hdmi;
-       int ret;
+       int ret, index;
 
-       if (!pdev->dev.of_node)
+       if (!np)
                return -ENODEV;
 
        hdmi = devm_kzalloc(&pdev->dev, sizeof(*hdmi), GFP_KERNEL);
        if (!hdmi)
                return -ENOMEM;
 
-       match = of_match_node(dw_hdmi_rockchip_dt_ids, pdev->dev.of_node);
+       match = of_match_node(dw_hdmi_rockchip_dt_ids, np);
        plat_data = devm_kmemdup(&pdev->dev, match->data,
                                             sizeof(*plat_data), GFP_KERNEL);
        if (!plat_data)
@@ -564,9 +565,9 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master,
        plat_data->priv_data = hdmi;
        encoder = &hdmi->encoder.encoder;
 
-       encoder->possible_crtcs = drm_of_find_possible_crtcs(drm, dev->of_node);
+       encoder->possible_crtcs = drm_of_find_possible_crtcs(drm, np);
        rockchip_drm_encoder_set_crtc_endpoint_id(&hdmi->encoder,
-                                                 dev->of_node, 0, 0);
+                                                 np, 0, 0);
 
        /*
         * If we failed to find the CRTC(s) which this encoder is
@@ -588,13 +589,17 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master,
                return dev_err_probe(hdmi->dev, ret, "failed to get phy\n");
        }
 
-       if (hdmi->phy) {
+       index = of_property_match_string(np, "phy-names", "hdmi");
+       if (index >= 0) {
                struct of_phandle_args clkspec;
 
-               clkspec.np = hdmi->phy->dev.of_node;
-               hdmi->hdmiphy_clk = of_clk_get_from_provider(&clkspec);
-               if (IS_ERR(hdmi->hdmiphy_clk))
-                       hdmi->hdmiphy_clk = NULL;
+               if (!of_parse_phandle_with_args(np, "phys", "#phy-cells", index,
+                                               &clkspec)) {
+                       hdmi->hdmiphy_clk = of_clk_get_from_provider(&clkspec);
+                       of_node_put(clkspec.np);
+                       if (IS_ERR(hdmi->hdmiphy_clk))
+                               hdmi->hdmiphy_clk = NULL;
+               }
        }
 
        if (hdmi->chip_data == &rk3568_chip_data) {