diff options
author | Tomi Valkeinen <tomi.valkeinen@ti.com> | 2013-04-10 07:47:38 -0400 |
---|---|---|
committer | Tomi Valkeinen <tomi.valkeinen@ti.com> | 2013-04-11 06:07:54 -0400 |
commit | 648a55e1254117bd7500747a789f0b112c7af240 (patch) | |
tree | 3ec4f099ab6d2d20f743bc064cec928ffd2571f1 /drivers/video | |
parent | 77d3595b29e2289cb6f9e4cece5fca1335554d56 (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.c | 17 |
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 | ||