@@ -32,26 +32,43 @@ struct hibmc_display_panel_pll {
3232struct 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
3940static 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+
5572static 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
214231hibmc_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
232245static 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