From 8328041b8c82c073c2c5c43afe57b2952fc9a872 Mon Sep 17 00:00:00 2001 From: Abhinav Kumar Date: Wed, 11 Jan 2023 16:16:00 -0800 Subject: drm/msm/dsi: implement opp table based check for dsi_mgr_bridge_mode_valid() Currently there is no protection against a user trying to set an unsupported mode on DSI. Implement a check based on the opp table whether the byte clock for the mode can be supported by validating whether an opp table entry exists. For devices which have not added opp table support yet, skip this check otherwise it will break bootup on those devices. changes in v3: - make the comment shorter - handle all errors except ENODEV Closes: https://gitlab.freedesktop.org/drm/msm/-/issues/15 Reported-by: Rob Clark Signed-off-by: Abhinav Kumar Reviewed-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/518008/ Link: https://lore.kernel.org/r/20230112001600.12791-2-quic_abhinavk@quicinc.com Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/dsi/dsi_manager.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'drivers/gpu/drm/msm/dsi/dsi_manager.c') diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c index 3a1417397283..b20fddb534a7 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_manager.c +++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c @@ -450,6 +450,25 @@ static enum drm_mode_status dsi_mgr_bridge_mode_valid(struct drm_bridge *bridge, int id = dsi_mgr_bridge_get_id(bridge); struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id); struct mipi_dsi_host *host = msm_dsi->host; + struct platform_device *pdev = msm_dsi->pdev; + struct dev_pm_opp *opp; + unsigned long byte_clk_rate; + + byte_clk_rate = dsi_byte_clk_get_rate(host, IS_BONDED_DSI(), mode); + + /* + * fail all errors except -ENODEV as that could mean that opp + * table is not yet implemented + */ + opp = dev_pm_opp_find_freq_ceil(&pdev->dev, &byte_clk_rate); + if (IS_ERR(opp)) { + if (PTR_ERR(opp) == -ERANGE) + return MODE_CLOCK_RANGE; + else if (PTR_ERR(opp) != -ENODEV) + return MODE_ERROR; + } else { + dev_pm_opp_put(opp); + } return msm_dsi_host_check_dsc(host, mode); } -- cgit v1.2.3 From 2ec56b232b9775b4814c207ed6da9f065b29711c Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Tue, 24 Jan 2023 22:36:00 +0200 Subject: drm/msm/dsi: properly handle the case of empty OPP table in dsi_mgr_bridge_mode_valid It was left unnoticed during the review that even if there is no OPP table in device tree, one will be created by a call to the function devm_pm_opp_set_clkname(). This leads to dsi_mgr_bridge_mode_valid() rejecting all modes if DT contains no OPP table for the DSI host. Rework dsi_mgr_bridge_mode_valid() to handle this case by actually checking that the table is populated with frequency entries before returning an error. Fixes: 8328041b8c82 ("drm/msm/dsi: implement opp table based check for dsi_mgr_bridge_mode_valid()") Signed-off-by: Dmitry Baryshkov Reviewed-by: Abhinav Kumar Patchwork: https://patchwork.freedesktop.org/patch/520076/ Link: https://lore.kernel.org/r/20230124203600.3488766-1-dmitry.baryshkov@linaro.org Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/dsi/dsi_manager.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) (limited to 'drivers/gpu/drm/msm/dsi/dsi_manager.c') diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c index b20fddb534a7..1bbac72dad35 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_manager.c +++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c @@ -456,18 +456,19 @@ static enum drm_mode_status dsi_mgr_bridge_mode_valid(struct drm_bridge *bridge, byte_clk_rate = dsi_byte_clk_get_rate(host, IS_BONDED_DSI(), mode); - /* - * fail all errors except -ENODEV as that could mean that opp - * table is not yet implemented - */ opp = dev_pm_opp_find_freq_ceil(&pdev->dev, &byte_clk_rate); - if (IS_ERR(opp)) { - if (PTR_ERR(opp) == -ERANGE) + if (!IS_ERR(opp)) { + dev_pm_opp_put(opp); + } else if (PTR_ERR(opp) == -ERANGE) { + /* + * An empty table is created by devm_pm_opp_set_clkname() even + * if there is none. Thus find_freq_ceil will still return + * -ERANGE in such case. + */ + if (dev_pm_opp_get_opp_count(&pdev->dev) != 0) return MODE_CLOCK_RANGE; - else if (PTR_ERR(opp) != -ENODEV) - return MODE_ERROR; } else { - dev_pm_opp_put(opp); + return MODE_ERROR; } return msm_dsi_host_check_dsc(host, mode); -- cgit v1.2.3