Skip to content

Commit

Permalink
drm/rockchip: dw_hdmi: Filter modes based on hdmiphy_clk
Browse files Browse the repository at this point in the history
RK3228 and RK3328 clock rate is being validated against a mpll config
table intended for a Synopsys phy, and not the used inno-hdmi-phy.

Instead get a reference to the hdmiphy clk and validate rates against
it to enable use of HDMI2.0 modes, e.g. 4K@60Hz, on RK3228 and RK3328.

For Synopsis phy the max_tmds_clock validation is sufficient.

Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
Tested-by: Diederik de Haas <didi.debian@cknow.org> # Rock64
Signed-off-by: Heiko Stuebner <heiko@sntech.de>
Link: https://patchwork.freedesktop.org/patch/msgid/20240908145511.3331451-2-jonas@kwiboo.se
  • Loading branch information
Jonas Karlman authored and Heiko Stuebner committed Sep 19, 2024
1 parent 87d4597 commit 3303a20
Showing 1 changed file with 17 additions and 18 deletions.
35 changes: 17 additions & 18 deletions drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ struct rockchip_hdmi {
struct rockchip_encoder encoder;
const struct rockchip_hdmi_chip_data *chip_data;
const struct dw_hdmi_plat_data *plat_data;
struct clk *hdmiphy_clk;
struct clk *ref_clk;
struct clk *grf_clk;
struct dw_hdmi *hdmi;
Expand Down Expand Up @@ -251,10 +252,7 @@ dw_hdmi_rockchip_mode_valid(struct dw_hdmi *dw_hdmi, void *data,
const struct drm_display_mode *mode)
{
struct rockchip_hdmi *hdmi = data;
const struct dw_hdmi_mpll_config *mpll_cfg = rockchip_mpll_cfg;
int pclk = mode->clock * 1000;
bool exact_match = hdmi->plat_data->phy_force_vendor;
int i;

if (hdmi->chip_data->max_tmds_clock &&
mode->clock > hdmi->chip_data->max_tmds_clock)
Expand All @@ -263,26 +261,18 @@ dw_hdmi_rockchip_mode_valid(struct dw_hdmi *dw_hdmi, void *data,
if (hdmi->ref_clk) {
int rpclk = clk_round_rate(hdmi->ref_clk, pclk);

if (abs(rpclk - pclk) > pclk / 1000)
if (rpclk < 0 || abs(rpclk - pclk) > pclk / 1000)
return MODE_NOCLOCK;
}

for (i = 0; mpll_cfg[i].mpixelclock != (~0UL); i++) {
/*
* For vendor specific phys force an exact match of the pixelclock
* to preserve the original behaviour of the driver.
*/
if (exact_match && pclk == mpll_cfg[i].mpixelclock)
return MODE_OK;
/*
* The Synopsys phy can work with pixelclocks up to the value given
* in the corresponding mpll_cfg entry.
*/
if (!exact_match && pclk <= mpll_cfg[i].mpixelclock)
return MODE_OK;
if (hdmi->hdmiphy_clk) {
int rpclk = clk_round_rate(hdmi->hdmiphy_clk, pclk);

if (rpclk < 0 || abs(rpclk - pclk) > pclk / 1000)
return MODE_NOCLOCK;
}

return MODE_BAD;
return MODE_OK;
}

static void dw_hdmi_rockchip_encoder_disable(struct drm_encoder *encoder)
Expand Down Expand Up @@ -607,6 +597,15 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master,
return ret;
}

if (hdmi->phy) {
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 (hdmi->chip_data == &rk3568_chip_data) {
regmap_write(hdmi->regmap, RK3568_GRF_VO_CON1,
HIWORD_UPDATE(RK3568_HDMI_SDAIN_MSK |
Expand Down

0 comments on commit 3303a20

Please sign in to comment.