diff options
author | Tomi Valkeinen <tomi.valkeinen@ti.com> | 2013-03-05 09:39:00 -0500 |
---|---|---|
committer | Tomi Valkeinen <tomi.valkeinen@ti.com> | 2013-04-03 08:19:18 -0400 |
commit | 72658f0716f36efad19d37517456b4a8a7cc7840 (patch) | |
tree | 59da5d95c253151bd1aba48c981916a3ff04cf27 /drivers/video | |
parent | 43417823fd8210edb7e714bea82ea9bd77089635 (diff) |
OMAPDSS: DSI: add new clock calculation code
Add new way to iterate over DSI PLL and HSDIV clock divisors.
dsi_pll_calc() and dss_hsdiv_calc() provide a generic way to go over
all the divisors, within given clock range. The functions 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>
Diffstat (limited to 'drivers/video')
-rw-r--r-- | drivers/video/omap2/dss/dsi.c | 69 | ||||
-rw-r--r-- | drivers/video/omap2/dss/dss.h | 12 |
2 files changed, 81 insertions, 0 deletions
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index 110a505332db..a4e0560c2799 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c | |||
@@ -1280,6 +1280,75 @@ static int dsi_pll_power(struct platform_device *dsidev, | |||
1280 | return 0; | 1280 | return 0; |
1281 | } | 1281 | } |
1282 | 1282 | ||
1283 | unsigned long dsi_get_pll_clkin(struct platform_device *dsidev) | ||
1284 | { | ||
1285 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
1286 | return clk_get_rate(dsi->sys_clk); | ||
1287 | } | ||
1288 | |||
1289 | bool dsi_hsdiv_calc(struct platform_device *dsidev, unsigned long pll, | ||
1290 | unsigned long out_min, dsi_hsdiv_calc_func func, void *data) | ||
1291 | { | ||
1292 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
1293 | int regm, regm_start, regm_stop; | ||
1294 | unsigned long out_max; | ||
1295 | unsigned long out; | ||
1296 | |||
1297 | out_min = out_min ? out_min : 1; | ||
1298 | out_max = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK); | ||
1299 | |||
1300 | regm_start = max(DIV_ROUND_UP(pll, out_max), 1ul); | ||
1301 | regm_stop = min(pll / out_min, dsi->regm_dispc_max); | ||
1302 | |||
1303 | for (regm = regm_start; regm <= regm_stop; ++regm) { | ||
1304 | out = pll / regm; | ||
1305 | |||
1306 | if (func(regm, out, data)) | ||
1307 | return true; | ||
1308 | } | ||
1309 | |||
1310 | return false; | ||
1311 | } | ||
1312 | |||
1313 | bool dsi_pll_calc(struct platform_device *dsidev, unsigned long clkin, | ||
1314 | unsigned long pll_min, unsigned long pll_max, | ||
1315 | dsi_pll_calc_func func, void *data) | ||
1316 | { | ||
1317 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
1318 | int regn, regn_start, regn_stop; | ||
1319 | int regm, regm_start, regm_stop; | ||
1320 | unsigned long fint, pll; | ||
1321 | const unsigned long pll_hw_max = 1800000000; | ||
1322 | unsigned long fint_hw_min, fint_hw_max; | ||
1323 | |||
1324 | fint_hw_min = dsi->fint_min; | ||
1325 | fint_hw_max = dsi->fint_max; | ||
1326 | |||
1327 | regn_start = max(DIV_ROUND_UP(clkin, fint_hw_max), 1ul); | ||
1328 | regn_stop = min(clkin / fint_hw_min, dsi->regn_max); | ||
1329 | |||
1330 | pll_max = pll_max ? pll_max : ULONG_MAX; | ||
1331 | |||
1332 | for (regn = regn_start; regn <= regn_stop; ++regn) { | ||
1333 | fint = clkin / regn; | ||
1334 | |||
1335 | regm_start = max(DIV_ROUND_UP(DIV_ROUND_UP(pll_min, fint), 2), | ||
1336 | 1ul); | ||
1337 | regm_stop = min3(pll_max / fint / 2, | ||
1338 | pll_hw_max / fint / 2, | ||
1339 | dsi->regm_max); | ||
1340 | |||
1341 | for (regm = regm_start; regm <= regm_stop; ++regm) { | ||
1342 | pll = 2 * regm * fint; | ||
1343 | |||
1344 | if (func(regn, regm, fint, pll, data)) | ||
1345 | return true; | ||
1346 | } | ||
1347 | } | ||
1348 | |||
1349 | return false; | ||
1350 | } | ||
1351 | |||
1283 | /* calculate clock rates using dividers in cinfo */ | 1352 | /* calculate clock rates using dividers in cinfo */ |
1284 | static int dsi_calc_clock_rates(struct platform_device *dsidev, | 1353 | static int dsi_calc_clock_rates(struct platform_device *dsidev, |
1285 | struct dsi_clock_info *cinfo) | 1354 | struct dsi_clock_info *cinfo) |
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h index 4180302a7fb3..dde6cc109480 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h | |||
@@ -295,6 +295,18 @@ void dsi_dump_clocks(struct seq_file *s); | |||
295 | void dsi_irq_handler(void); | 295 | void dsi_irq_handler(void); |
296 | u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt); | 296 | u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt); |
297 | 297 | ||
298 | unsigned long dsi_get_pll_clkin(struct platform_device *dsidev); | ||
299 | |||
300 | typedef bool (*dsi_pll_calc_func)(int regn, int regm, unsigned long fint, | ||
301 | unsigned long pll, void *data); | ||
302 | typedef bool (*dsi_hsdiv_calc_func)(int regm_dispc, unsigned long dispc, | ||
303 | void *data); | ||
304 | bool dsi_hsdiv_calc(struct platform_device *dsidev, unsigned long pll, | ||
305 | unsigned long out_min, dsi_hsdiv_calc_func func, void *data); | ||
306 | bool dsi_pll_calc(struct platform_device *dsidev, unsigned long clkin, | ||
307 | unsigned long pll_min, unsigned long pll_max, | ||
308 | dsi_pll_calc_func func, void *data); | ||
309 | |||
298 | unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev); | 310 | unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev); |
299 | int dsi_pll_set_clock_div(struct platform_device *dsidev, | 311 | int dsi_pll_set_clock_div(struct platform_device *dsidev, |
300 | struct dsi_clock_info *cinfo); | 312 | struct dsi_clock_info *cinfo); |