aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video
diff options
context:
space:
mode:
authorTomi Valkeinen <tomi.valkeinen@ti.com>2013-03-05 09:39:00 -0500
committerTomi Valkeinen <tomi.valkeinen@ti.com>2013-04-03 08:19:18 -0400
commit72658f0716f36efad19d37517456b4a8a7cc7840 (patch)
tree59da5d95c253151bd1aba48c981916a3ff04cf27 /drivers/video
parent43417823fd8210edb7e714bea82ea9bd77089635 (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.c69
-rw-r--r--drivers/video/omap2/dss/dss.h12
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
1283unsigned 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
1289bool 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
1313bool 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 */
1284static int dsi_calc_clock_rates(struct platform_device *dsidev, 1353static 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);
295void dsi_irq_handler(void); 295void dsi_irq_handler(void);
296u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt); 296u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt);
297 297
298unsigned long dsi_get_pll_clkin(struct platform_device *dsidev);
299
300typedef bool (*dsi_pll_calc_func)(int regn, int regm, unsigned long fint,
301 unsigned long pll, void *data);
302typedef bool (*dsi_hsdiv_calc_func)(int regm_dispc, unsigned long dispc,
303 void *data);
304bool dsi_hsdiv_calc(struct platform_device *dsidev, unsigned long pll,
305 unsigned long out_min, dsi_hsdiv_calc_func func, void *data);
306bool 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
298unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev); 310unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev);
299int dsi_pll_set_clock_div(struct platform_device *dsidev, 311int dsi_pll_set_clock_div(struct platform_device *dsidev,
300 struct dsi_clock_info *cinfo); 312 struct dsi_clock_info *cinfo);