drm/rockchip: vop: use rockchip_drm_dclk_set_rate() for some special pll

In addition, fix the version check process to switch
for efficiency and readability.

Change-Id: I372e528f61403a72ea574de5aae28174ef3f95fa
Signed-off-by: Elaine Zhang <zhangqing@rock-chips.com>
Signed-off-by: Damon Ding <damon.ding@rock-chips.com>
This commit is contained in:
Damon Ding
2024-03-15 10:13:44 +08:00
parent a24880f2a4
commit bbeca6dfc2
3 changed files with 111 additions and 12 deletions

View File

@@ -64,6 +64,33 @@ static long rockchip_rk3568_drm_dclk_round_rate(struct clk *dclk, unsigned long
return round_rate;
}
static long rockchip_rk3576_vopl_drm_dclk_round_rate(struct clk *dclk, unsigned long rate)
{
struct clk_hw *hw;
struct clk_hw *p_hw;
unsigned long round_rate;
const char *name;
hw = __clk_get_hw(dclk);
if (!hw)
return -EINVAL;
p_hw = clk_hw_get_parent(hw);
if (!p_hw)
return -EINVAL;
name = clk_hw_get_name(p_hw);
if (!strcmp(name, "vpll"))
round_rate = rate;
else if (!strcmp(name, "dclk_ebc_frac_src"))
round_rate = rate;
else
round_rate = clk_round_rate(dclk, rate);
return round_rate;
}
static long rockchip_rk3576_drm_dclk_round_rate(struct clk *dclk, unsigned long rate)
{
struct clk_hw *hw;
@@ -218,6 +245,57 @@ static int rockchip_rk3568_drm_dclk_set_rate(struct clk *dclk, unsigned long rat
return 0;
}
/*
* The rk3576 ebc setting clk rule.
* The dclk_ebc can select vpll, the vpll is ebc exclusive.
* The dclk_ebc can select dclk_ebc_frac_src, use digital decimal divider, the recommended frequency is less than 60M.
* The dclk_ebc can select gpll or cpll, can only choose the nearest frequency division(gpll:1188M,cpll:1000M),
* and can't support accurate frequency setting.
*
*/
static int rockchip_rk3576_vopl_drm_dclk_set_rate(struct clk *dclk, unsigned long rate)
{
struct clk_hw *hw;
struct clk_hw *p_hw;
unsigned long pll_rate;
const char *name;
int div = 0;
hw = __clk_get_hw(dclk);
if (!hw)
return -EINVAL;
p_hw = clk_hw_get_parent(hw);
if (!p_hw)
return -EINVAL;
name = clk_hw_get_name(p_hw);
if (!strcmp(name, "vpll")) {
pll_rate = clk_hw_get_rate(p_hw);
if (pll_rate >= VOP2_PLL_LIMIT_FREQ && pll_rate % rate == 0) {
clk_set_rate(dclk, rate);
} else {
div = DIV_ROUND_UP(VOP2_PLL_LIMIT_FREQ, rate);
if (div % 2)
div += 1;
clk_set_rate(p_hw->clk, rate * div);
clk_set_rate(dclk, rate);
}
} else if (!strcmp(name, "dclk_ebc_frac_src")) {
clk_set_rate(p_hw->clk, rate);
clk_set_rate(dclk, rate);
} else {
clk_set_rate(dclk, rate);
}
pr_debug("%s:request rate = %ld, %s = %ld %s = %ld\n", __func__, rate,
clk_hw_get_name(hw), clk_hw_get_rate(hw),
clk_hw_get_name(p_hw), clk_hw_get_rate(p_hw));
return 0;
}
/*
* The rk3576 has three ports, dclk_vp0\1\2.
* The dclk_vp0\1\2 can select 1 port specified on clk_hdmiphy_pixelx.
@@ -330,16 +408,26 @@ long rockchip_drm_dclk_round_rate(u32 version, struct clk *dclk, unsigned long r
{
long round_rate;
if (version == VOP_VERSION_RK3562)
switch (version) {
case VOP_VERSION_RK3562:
round_rate = rockchip_rk3562_drm_dclk_round_rate(dclk, rate);
else if (version == VOP_VERSION_RK3568)
break;
case VOP_VERSION_RK3568:
round_rate = rockchip_rk3568_drm_dclk_round_rate(dclk, rate);
else if (version == VOP_VERSION_RK3576)
break;
case VOP_VERSION_RK3576:
round_rate = rockchip_rk3576_drm_dclk_round_rate(dclk, rate);
else if (version == VOP_VERSION_RK3588)
break;
case VOP_VERSION_RK3576_LITE:
round_rate = rockchip_rk3576_vopl_drm_dclk_round_rate(dclk, rate);
break;
case VOP_VERSION_RK3588:
round_rate = rockchip_rk3588_drm_dclk_round_rate(dclk, rate);
else
break;
default:
round_rate = clk_round_rate(dclk, rate);
break;
}
if (round_rate < 0)
pr_warn("%s:the clk_hw of dclk or parent of dclk may be NULL\n", __func__);
@@ -351,16 +439,26 @@ int rockchip_drm_dclk_set_rate(u32 version, struct clk *dclk, unsigned long rate
{
int ret;
if (version == VOP_VERSION_RK3562)
switch (version) {
case VOP_VERSION_RK3562:
ret = rockchip_rk3562_drm_dclk_set_rate(dclk, rate);
else if (version == VOP_VERSION_RK3568)
break;
case VOP_VERSION_RK3568:
ret = rockchip_rk3568_drm_dclk_set_rate(dclk, rate);
else if (version == VOP_VERSION_RK3576)
break;
case VOP_VERSION_RK3576:
ret = rockchip_rk3576_drm_dclk_set_rate(dclk, rate);
else if (version == VOP_VERSION_RK3588)
break;
case VOP_VERSION_RK3576_LITE:
ret = rockchip_rk3576_vopl_drm_dclk_set_rate(dclk, rate);
break;
case VOP_VERSION_RK3588:
ret = rockchip_rk3588_drm_dclk_set_rate(dclk, rate);
else
break;
default:
ret = clk_set_rate(dclk, rate);
break;
}
if (ret < 0)
pr_warn("%s:the clk_hw of dclk or parent of dclk may be NULL\n", __func__);

View File

@@ -3687,8 +3687,7 @@ static void vop_crtc_atomic_enable(struct drm_crtc *crtc,
VOP_CTRL_SET(vop, win_csc_mode_sel, 1);
clk_set_rate(vop->dclk, adjusted_mode->crtc_clock * 1000);
rockchip_drm_dclk_set_rate(vop->version, vop->dclk, adjusted_mode->crtc_clock * 1000);
vop_cfg_done(vop);

View File

@@ -21,6 +21,8 @@
#define VOP_MAJOR(version) ((version) >> 8)
#define VOP_MINOR(version) ((version) & 0xff)
#define VOP_VERSION_RK3576_LITE VOP_VERSION(0x2, 0xd)
#define VOP2_VERSION(major, minor, build) ((major) << 24 | (minor) << 16 | (build))
#define VOP2_MAJOR(version) (((version) >> 24) & 0xff)
#define VOP2_MINOR(version) (((version) >> 16) & 0xff)