drm/rockchip: dw_hdmi: avoid direct dereference of phy->dev.of_node

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
This commit is contained in:
Vladimir Oltean 2026-05-05 13:05:07 +03:00 committed by Heiko Stuebner
parent a48bbcc7ac
commit 9392e7340b

View 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) {