aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video
diff options
context:
space:
mode:
authorTomi Valkeinen <tomi.valkeinen@ti.com>2013-04-10 07:47:38 -0400
committerTomi Valkeinen <tomi.valkeinen@ti.com>2013-04-11 06:07:54 -0400
commit648a55e1254117bd7500747a789f0b112c7af240 (patch)
tree3ec4f099ab6d2d20f743bc064cec928ffd2571f1 /drivers/video
parent77d3595b29e2289cb6f9e4cece5fca1335554d56 (diff)
OMAPDSS: fix dss_fck clock rate rounding
DSS func clock is calculated with prate / div * m. However, the current omapdss code calculates it with prate * m / div, which yields a slightly different result when there's a remainder. For example, 432000000 / 14 * 2 = 61714284, but 432000000 * 2 / 14 = 61714285. In addition to that, the clock framework wants the clock rate given with clk_set_rate to be higher than the actual (truncated) end result. So, if prate is 432000000, and div is 14, the real result is 30857142.8571... We need to call clk_set_rate with 30857143, which gives us a clock of 30857142. That's why we need to use DIV_ROUND_UP() when calling clk_set_rate. This patch fixes the clock calculation. Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Diffstat (limited to 'drivers/video')
-rw-r--r--drivers/video/omap2/dss/dss.c17
1 files changed, 11 insertions, 6 deletions
diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c
index fdd32e8d9212..b9f6f245d4a1 100644
--- a/drivers/video/omap2/dss/dss.c
+++ b/drivers/video/omap2/dss/dss.c
@@ -480,6 +480,7 @@ bool dss_div_calc(unsigned long fck_min, dss_div_calc_func func, void *data)
480 unsigned long fck_hw_max; 480 unsigned long fck_hw_max;
481 unsigned long fckd_hw_max; 481 unsigned long fckd_hw_max;
482 unsigned long prate; 482 unsigned long prate;
483 unsigned m;
483 484
484 if (dss.dpll4_m4_ck == NULL) { 485 if (dss.dpll4_m4_ck == NULL) {
485 /* 486 /*
@@ -495,15 +496,16 @@ bool dss_div_calc(unsigned long fck_min, dss_div_calc_func func, void *data)
495 fck_hw_max = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK); 496 fck_hw_max = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
496 fckd_hw_max = dss.feat->fck_div_max; 497 fckd_hw_max = dss.feat->fck_div_max;
497 498
498 prate = dss_get_dpll4_rate() * dss.feat->dss_fck_multiplier; 499 m = dss.feat->dss_fck_multiplier;
500 prate = dss_get_dpll4_rate();
499 501
500 fck_min = fck_min ? fck_min : 1; 502 fck_min = fck_min ? fck_min : 1;
501 503
502 fckd_start = min(prate / fck_min, fckd_hw_max); 504 fckd_start = min(prate * m / fck_min, fckd_hw_max);
503 fckd_stop = max(DIV_ROUND_UP(prate, fck_hw_max), 1ul); 505 fckd_stop = max(DIV_ROUND_UP(prate * m, fck_hw_max), 1ul);
504 506
505 for (fckd = fckd_start; fckd >= fckd_stop; --fckd) { 507 for (fckd = fckd_start; fckd >= fckd_stop; --fckd) {
506 fck = prate / fckd; 508 fck = prate / fckd * m;
507 509
508 if (func(fckd, fck, data)) 510 if (func(fckd, fck, data))
509 return true; 511 return true;
@@ -521,7 +523,8 @@ int dss_set_clock_div(struct dss_clock_info *cinfo)
521 prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck)); 523 prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
522 DSSDBG("dpll4_m4 = %ld\n", prate); 524 DSSDBG("dpll4_m4 = %ld\n", prate);
523 525
524 r = clk_set_rate(dss.dpll4_m4_ck, prate / cinfo->fck_div); 526 r = clk_set_rate(dss.dpll4_m4_ck,
527 DIV_ROUND_UP(prate, cinfo->fck_div));
525 if (r) 528 if (r)
526 return r; 529 return r;
527 } else { 530 } else {
@@ -531,7 +534,9 @@ int dss_set_clock_div(struct dss_clock_info *cinfo)
531 534
532 dss.dss_clk_rate = clk_get_rate(dss.dss_clk); 535 dss.dss_clk_rate = clk_get_rate(dss.dss_clk);
533 536
534 WARN_ONCE(dss.dss_clk_rate != cinfo->fck, "clk rate mismatch"); 537 WARN_ONCE(dss.dss_clk_rate != cinfo->fck,
538 "clk rate mismatch: %lu != %lu", dss.dss_clk_rate,
539 cinfo->fck);
535 540
536 DSSDBG("fck = %ld (%d)\n", cinfo->fck, cinfo->fck_div); 541 DSSDBG("fck = %ld (%d)\n", cinfo->fck, cinfo->fck_div);
537 542