Skip to content

Commit 131cb56

Browse files
Lin Hegregkh
authored andcommitted
drm/hisilicon/hibmc: use clock to look up the PLL value
[ Upstream commit 99ef3a4 ] In the past, we use width and height to look up our PLL value. But actually the actual clock check is also necessnary. There are some resolutions that width and height same, but its clock different. Add the clock check when using pll_table to determine the PLL value. Fixes: da52605 ("drm/hisilicon/hibmc: Add support for display engine") Signed-off-by: Lin He <helin52@huawei.com> Signed-off-by: Yongbang Shi <shiyongbang@huawei.com> Reviewed-by: Thomas Zimmermann <tzimmermann@suse.de> Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Link: https://patch.msgid.link/20260509032302.2057227-5-shiyongbang@huawei.com Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent 3e453de commit 131cb56

1 file changed

Lines changed: 45 additions & 35 deletions

File tree

drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c

Lines changed: 45 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -32,26 +32,43 @@ struct hibmc_display_panel_pll {
3232
struct hibmc_dislay_pll_config {
3333
u64 hdisplay;
3434
u64 vdisplay;
35+
int clock;
3536
u32 pll1_config_value;
3637
u32 pll2_config_value;
3738
};
3839

3940
static const struct hibmc_dislay_pll_config hibmc_pll_table[] = {
40-
{640, 480, CRT_PLL1_HS_25MHZ, CRT_PLL2_HS_25MHZ},
41-
{800, 600, CRT_PLL1_HS_40MHZ, CRT_PLL2_HS_40MHZ},
42-
{1024, 768, CRT_PLL1_HS_65MHZ, CRT_PLL2_HS_65MHZ},
43-
{1152, 864, CRT_PLL1_HS_80MHZ_1152, CRT_PLL2_HS_80MHZ},
44-
{1280, 768, CRT_PLL1_HS_80MHZ, CRT_PLL2_HS_80MHZ},
45-
{1280, 720, CRT_PLL1_HS_74MHZ, CRT_PLL2_HS_74MHZ},
46-
{1280, 960, CRT_PLL1_HS_108MHZ, CRT_PLL2_HS_108MHZ},
47-
{1280, 1024, CRT_PLL1_HS_108MHZ, CRT_PLL2_HS_108MHZ},
48-
{1440, 900, CRT_PLL1_HS_106MHZ, CRT_PLL2_HS_106MHZ},
49-
{1600, 900, CRT_PLL1_HS_108MHZ, CRT_PLL2_HS_108MHZ},
50-
{1600, 1200, CRT_PLL1_HS_162MHZ, CRT_PLL2_HS_162MHZ},
51-
{1920, 1080, CRT_PLL1_HS_148MHZ, CRT_PLL2_HS_148MHZ},
52-
{1920, 1200, CRT_PLL1_HS_193MHZ, CRT_PLL2_HS_193MHZ},
41+
{640, 480, 25000, CRT_PLL1_HS_25MHZ, CRT_PLL2_HS_25MHZ},
42+
{800, 600, 40000, CRT_PLL1_HS_40MHZ, CRT_PLL2_HS_40MHZ},
43+
{1024, 768, 65000, CRT_PLL1_HS_65MHZ, CRT_PLL2_HS_65MHZ},
44+
{1152, 864, 78750, CRT_PLL1_HS_80MHZ_1152, CRT_PLL2_HS_80MHZ},
45+
{1280, 768, 80000, CRT_PLL1_HS_80MHZ, CRT_PLL2_HS_80MHZ},
46+
{1280, 720, 74375, CRT_PLL1_HS_74MHZ, CRT_PLL2_HS_74MHZ},
47+
{1280, 960, 108000, CRT_PLL1_HS_108MHZ, CRT_PLL2_HS_108MHZ},
48+
{1280, 1024, 108000, CRT_PLL1_HS_108MHZ, CRT_PLL2_HS_108MHZ},
49+
{1440, 900, 105952, CRT_PLL1_HS_106MHZ, CRT_PLL2_HS_106MHZ},
50+
{1600, 900, 108000, CRT_PLL1_HS_108MHZ, CRT_PLL2_HS_108MHZ},
51+
{1600, 1200, 162500, CRT_PLL1_HS_162MHZ, CRT_PLL2_HS_162MHZ},
52+
{1920, 1080, 148750, CRT_PLL1_HS_148MHZ, CRT_PLL2_HS_148MHZ},
53+
{1920, 1200, 193750, CRT_PLL1_HS_193MHZ, CRT_PLL2_HS_193MHZ},
5354
};
5455

56+
static int hibmc_get_best_clock_idx(const struct drm_display_mode *mode)
57+
{
58+
int i, diff;
59+
60+
for (i = 0; i < ARRAY_SIZE(hibmc_pll_table); i++) {
61+
if (hibmc_pll_table[i].hdisplay == mode->hdisplay &&
62+
hibmc_pll_table[i].vdisplay == mode->vdisplay) {
63+
diff = abs(mode->clock - hibmc_pll_table[i].clock);
64+
if (diff < mode->clock / 100) /* tolerance 1/100 */
65+
return i;
66+
}
67+
}
68+
69+
return -MODE_CLOCK_RANGE;
70+
}
71+
5572
static int hibmc_plane_atomic_check(struct drm_plane *plane,
5673
struct drm_atomic_state *state)
5774
{
@@ -214,19 +231,15 @@ static enum drm_mode_status
214231
hibmc_crtc_mode_valid(struct drm_crtc *crtc,
215232
const struct drm_display_mode *mode)
216233
{
217-
size_t i = 0;
218234
int vrefresh = drm_mode_vrefresh(mode);
219235

220236
if (vrefresh < 59 || vrefresh > 61)
221237
return MODE_NOCLOCK;
222238

223-
for (i = 0; i < ARRAY_SIZE(hibmc_pll_table); i++) {
224-
if (hibmc_pll_table[i].hdisplay == mode->hdisplay &&
225-
hibmc_pll_table[i].vdisplay == mode->vdisplay)
226-
return MODE_OK;
227-
}
239+
if (hibmc_get_best_clock_idx(mode) >= 0)
240+
return MODE_OK;
228241

229-
return MODE_BAD;
242+
return MODE_CLOCK_RANGE;
230243
}
231244

232245
static u32 format_pll_reg(void)
@@ -281,23 +294,20 @@ static void set_vclock_hisilicon(struct drm_device *dev, u64 pll)
281294
writel(val, priv->mmio + CRT_PLL1_HS);
282295
}
283296

284-
static void get_pll_config(u64 x, u64 y, u32 *pll1, u32 *pll2)
297+
static void get_pll_config(struct drm_display_mode *mode, u32 *pll1, u32 *pll2)
285298
{
286-
size_t i;
287-
size_t count = ARRAY_SIZE(hibmc_pll_table);
288-
289-
for (i = 0; i < count; i++) {
290-
if (hibmc_pll_table[i].hdisplay == x &&
291-
hibmc_pll_table[i].vdisplay == y) {
292-
*pll1 = hibmc_pll_table[i].pll1_config_value;
293-
*pll2 = hibmc_pll_table[i].pll2_config_value;
294-
return;
295-
}
299+
int idx;
300+
301+
idx = hibmc_get_best_clock_idx(mode);
302+
if (idx < 0) {
303+
/* if found none, we use default value */
304+
*pll1 = CRT_PLL1_HS_25MHZ;
305+
*pll2 = CRT_PLL2_HS_25MHZ;
306+
return;
296307
}
297308

298-
/* if found none, we use default value */
299-
*pll1 = CRT_PLL1_HS_25MHZ;
300-
*pll2 = CRT_PLL2_HS_25MHZ;
309+
*pll1 = hibmc_pll_table[idx].pll1_config_value;
310+
*pll2 = hibmc_pll_table[idx].pll2_config_value;
301311
}
302312

303313
/*
@@ -319,7 +329,7 @@ static u32 display_ctrl_adjust(struct drm_device *dev,
319329
x = mode->hdisplay;
320330
y = mode->vdisplay;
321331

322-
get_pll_config(x, y, &pll1, &pll2);
332+
get_pll_config(mode, &pll1, &pll2);
323333
writel(pll2, priv->mmio + CRT_PLL2_HS);
324334
set_vclock_hisilicon(dev, pll1);
325335

0 commit comments

Comments
 (0)