diff options
| author | Tomi Valkeinen <tomi.valkeinen@ti.com> | 2013-03-05 09:32:08 -0500 |
|---|---|---|
| committer | Tomi Valkeinen <tomi.valkeinen@ti.com> | 2013-04-03 08:19:17 -0400 |
| commit | 7c284e6ee3710e96bf246e6b52032f3d766fa094 (patch) | |
| tree | a713a5d43b0920912a66d666dd8e786704513a6a | |
| parent | 4ce9e33c0f6abc4203f25f5fc287bf072de32513 (diff) | |
OMAPDSS: DISPC: add new clock calculation code
Add new way to iterate over DISPC clock divisors. dispc_div_calc()
provides a generic way to go over all the divisors, within given pixel
clock range. dispc_div_calc() will call a callback function for each
divider set, making the function reusable for all use cases.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
| -rw-r--r-- | drivers/video/omap2/dss/dispc.c | 60 | ||||
| -rw-r--r-- | drivers/video/omap2/dss/dss.h | 6 |
2 files changed, 66 insertions, 0 deletions
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index f564955ddd9e..cd54e8fe2d58 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c | |||
| @@ -3374,6 +3374,66 @@ int dispc_calc_clock_rates(unsigned long dispc_fclk_rate, | |||
| 3374 | return 0; | 3374 | return 0; |
| 3375 | } | 3375 | } |
| 3376 | 3376 | ||
| 3377 | bool dispc_div_calc(unsigned long dispc, | ||
| 3378 | unsigned long pck_min, unsigned long pck_max, | ||
| 3379 | dispc_div_calc_func func, void *data) | ||
| 3380 | { | ||
| 3381 | int lckd, lckd_start, lckd_stop; | ||
| 3382 | int pckd, pckd_start, pckd_stop; | ||
| 3383 | unsigned long pck, lck; | ||
| 3384 | unsigned long lck_max; | ||
| 3385 | unsigned long pckd_hw_min, pckd_hw_max; | ||
| 3386 | unsigned min_fck_per_pck; | ||
| 3387 | unsigned long fck; | ||
| 3388 | |||
| 3389 | #ifdef CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK | ||
| 3390 | min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK; | ||
| 3391 | #else | ||
| 3392 | min_fck_per_pck = 0; | ||
| 3393 | #endif | ||
| 3394 | |||
| 3395 | pckd_hw_min = dss_feat_get_param_min(FEAT_PARAM_DSS_PCD); | ||
| 3396 | pckd_hw_max = dss_feat_get_param_max(FEAT_PARAM_DSS_PCD); | ||
| 3397 | |||
| 3398 | lck_max = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK); | ||
| 3399 | |||
| 3400 | pck_min = pck_min ? pck_min : 1; | ||
| 3401 | pck_max = pck_max ? pck_max : ULONG_MAX; | ||
| 3402 | |||
| 3403 | lckd_start = max(DIV_ROUND_UP(dispc, lck_max), 1ul); | ||
| 3404 | lckd_stop = min(dispc / pck_min, 255ul); | ||
| 3405 | |||
| 3406 | for (lckd = lckd_start; lckd <= lckd_stop; ++lckd) { | ||
| 3407 | lck = dispc / lckd; | ||
| 3408 | |||
| 3409 | pckd_start = max(DIV_ROUND_UP(lck, pck_max), pckd_hw_min); | ||
| 3410 | pckd_stop = min(lck / pck_min, pckd_hw_max); | ||
| 3411 | |||
| 3412 | for (pckd = pckd_start; pckd <= pckd_stop; ++pckd) { | ||
| 3413 | pck = lck / pckd; | ||
| 3414 | |||
| 3415 | /* | ||
| 3416 | * For OMAP2/3 the DISPC fclk is the same as LCD's logic | ||
| 3417 | * clock, which means we're configuring DISPC fclk here | ||
| 3418 | * also. Thus we need to use the calculated lck. For | ||
| 3419 | * OMAP4+ the DISPC fclk is a separate clock. | ||
| 3420 | */ | ||
| 3421 | if (dss_has_feature(FEAT_CORE_CLK_DIV)) | ||
| 3422 | fck = dispc_core_clk_rate(); | ||
| 3423 | else | ||
| 3424 | fck = lck; | ||
| 3425 | |||
| 3426 | if (fck < pck * min_fck_per_pck) | ||
| 3427 | continue; | ||
| 3428 | |||
| 3429 | if (func(lckd, pckd, lck, pck, data)) | ||
| 3430 | return true; | ||
| 3431 | } | ||
| 3432 | } | ||
| 3433 | |||
| 3434 | return false; | ||
| 3435 | } | ||
| 3436 | |||
| 3377 | void dispc_mgr_set_clock_div(enum omap_channel channel, | 3437 | void dispc_mgr_set_clock_div(enum omap_channel channel, |
| 3378 | const struct dispc_clock_info *cinfo) | 3438 | const struct dispc_clock_info *cinfo) |
| 3379 | { | 3439 | { |
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h index 610c8e563daa..0ff41dd8f3c5 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h | |||
| @@ -376,6 +376,12 @@ void dispc_enable_fifomerge(bool enable); | |||
| 376 | void dispc_enable_gamma_table(bool enable); | 376 | void dispc_enable_gamma_table(bool enable); |
| 377 | void dispc_set_loadmode(enum omap_dss_load_mode mode); | 377 | void dispc_set_loadmode(enum omap_dss_load_mode mode); |
| 378 | 378 | ||
| 379 | typedef bool (*dispc_div_calc_func)(int lckd, int pckd, unsigned long lck, | ||
| 380 | unsigned long pck, void *data); | ||
| 381 | bool dispc_div_calc(unsigned long dispc, | ||
| 382 | unsigned long pck_min, unsigned long pck_max, | ||
| 383 | dispc_div_calc_func func, void *data); | ||
| 384 | |||
| 379 | bool dispc_mgr_timings_ok(enum omap_channel channel, | 385 | bool dispc_mgr_timings_ok(enum omap_channel channel, |
| 380 | const struct omap_video_timings *timings); | 386 | const struct omap_video_timings *timings); |
| 381 | unsigned long dispc_fclk_rate(void); | 387 | unsigned long dispc_fclk_rate(void); |
