aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/omap2/dss/dss.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/omap2/dss/dss.c')
-rw-r--r--drivers/video/omap2/dss/dss.c101
1 files changed, 96 insertions, 5 deletions
diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c
index 602102cebcbf..054c2a22b3f1 100644
--- a/drivers/video/omap2/dss/dss.c
+++ b/drivers/video/omap2/dss/dss.c
@@ -32,6 +32,7 @@
32#include <linux/platform_device.h> 32#include <linux/platform_device.h>
33#include <linux/pm_runtime.h> 33#include <linux/pm_runtime.h>
34#include <linux/gfp.h> 34#include <linux/gfp.h>
35#include <linux/sizes.h>
35 36
36#include <video/omapdss.h> 37#include <video/omapdss.h>
37 38
@@ -76,6 +77,7 @@ static struct {
76 77
77 struct clk *dpll4_m4_ck; 78 struct clk *dpll4_m4_ck;
78 struct clk *dss_clk; 79 struct clk *dss_clk;
80 unsigned long dss_clk_rate;
79 81
80 unsigned long cache_req_pck; 82 unsigned long cache_req_pck;
81 unsigned long cache_prate; 83 unsigned long cache_prate;
@@ -96,6 +98,8 @@ static const char * const dss_generic_clk_source_names[] = {
96 [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC] = "DSI_PLL_HSDIV_DISPC", 98 [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC] = "DSI_PLL_HSDIV_DISPC",
97 [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI] = "DSI_PLL_HSDIV_DSI", 99 [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI] = "DSI_PLL_HSDIV_DSI",
98 [OMAP_DSS_CLK_SRC_FCK] = "DSS_FCK", 100 [OMAP_DSS_CLK_SRC_FCK] = "DSS_FCK",
101 [OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC] = "DSI_PLL2_HSDIV_DISPC",
102 [OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI] = "DSI_PLL2_HSDIV_DSI",
99}; 103};
100 104
101static inline void dss_write_reg(const struct dss_reg idx, u32 val) 105static inline void dss_write_reg(const struct dss_reg idx, u32 val)
@@ -151,6 +155,21 @@ static void dss_restore_context(void)
151#undef SR 155#undef SR
152#undef RR 156#undef RR
153 157
158int dss_get_ctx_loss_count(void)
159{
160 struct omap_dss_board_info *board_data = dss.pdev->dev.platform_data;
161 int cnt;
162
163 if (!board_data->get_context_loss_count)
164 return -ENOENT;
165
166 cnt = board_data->get_context_loss_count(&dss.pdev->dev);
167
168 WARN_ONCE(cnt < 0, "get_context_loss_count failed: %d\n", cnt);
169
170 return cnt;
171}
172
154void dss_sdi_init(int datapairs) 173void dss_sdi_init(int datapairs)
155{ 174{
156 u32 l; 175 u32 l;
@@ -301,7 +320,7 @@ static void dss_dump_regs(struct seq_file *s)
301#undef DUMPREG 320#undef DUMPREG
302} 321}
303 322
304void dss_select_dispc_clk_source(enum omap_dss_clk_source clk_src) 323static void dss_select_dispc_clk_source(enum omap_dss_clk_source clk_src)
305{ 324{
306 struct platform_device *dsidev; 325 struct platform_device *dsidev;
307 int b; 326 int b;
@@ -372,8 +391,10 @@ void dss_select_lcd_clk_source(enum omap_channel channel,
372 struct platform_device *dsidev; 391 struct platform_device *dsidev;
373 int b, ix, pos; 392 int b, ix, pos;
374 393
375 if (!dss_has_feature(FEAT_LCD_CLK_SRC)) 394 if (!dss_has_feature(FEAT_LCD_CLK_SRC)) {
395 dss_select_dispc_clk_source(clk_src);
376 return; 396 return;
397 }
377 398
378 switch (clk_src) { 399 switch (clk_src) {
379 case OMAP_DSS_CLK_SRC_FCK: 400 case OMAP_DSS_CLK_SRC_FCK:
@@ -429,6 +450,29 @@ enum omap_dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel)
429 } 450 }
430} 451}
431 452
453/* calculate clock rates using dividers in cinfo */
454int dss_calc_clock_rates(struct dss_clock_info *cinfo)
455{
456 if (dss.dpll4_m4_ck) {
457 unsigned long prate;
458
459 if (cinfo->fck_div > dss.feat->fck_div_max ||
460 cinfo->fck_div == 0)
461 return -EINVAL;
462
463 prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
464
465 cinfo->fck = prate / cinfo->fck_div *
466 dss.feat->dss_fck_multiplier;
467 } else {
468 if (cinfo->fck_div != 0)
469 return -EINVAL;
470 cinfo->fck = clk_get_rate(dss.dss_clk);
471 }
472
473 return 0;
474}
475
432int dss_set_clock_div(struct dss_clock_info *cinfo) 476int dss_set_clock_div(struct dss_clock_info *cinfo)
433{ 477{
434 if (dss.dpll4_m4_ck) { 478 if (dss.dpll4_m4_ck) {
@@ -446,6 +490,10 @@ int dss_set_clock_div(struct dss_clock_info *cinfo)
446 return -EINVAL; 490 return -EINVAL;
447 } 491 }
448 492
493 dss.dss_clk_rate = clk_get_rate(dss.dss_clk);
494
495 WARN_ONCE(dss.dss_clk_rate != cinfo->fck, "clk rate mismatch");
496
449 DSSDBG("fck = %ld (%d)\n", cinfo->fck, cinfo->fck_div); 497 DSSDBG("fck = %ld (%d)\n", cinfo->fck, cinfo->fck_div);
450 498
451 return 0; 499 return 0;
@@ -459,6 +507,41 @@ unsigned long dss_get_dpll4_rate(void)
459 return 0; 507 return 0;
460} 508}
461 509
510unsigned long dss_get_dispc_clk_rate(void)
511{
512 return dss.dss_clk_rate;
513}
514
515static int dss_setup_default_clock(void)
516{
517 unsigned long max_dss_fck, prate;
518 unsigned fck_div;
519 struct dss_clock_info dss_cinfo = { 0 };
520 int r;
521
522 if (dss.dpll4_m4_ck == NULL)
523 return 0;
524
525 max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
526
527 prate = dss_get_dpll4_rate();
528
529 fck_div = DIV_ROUND_UP(prate * dss.feat->dss_fck_multiplier,
530 max_dss_fck);
531
532 dss_cinfo.fck_div = fck_div;
533
534 r = dss_calc_clock_rates(&dss_cinfo);
535 if (r)
536 return r;
537
538 r = dss_set_clock_div(&dss_cinfo);
539 if (r)
540 return r;
541
542 return 0;
543}
544
462int dss_calc_clock_div(unsigned long req_pck, struct dss_clock_info *dss_cinfo, 545int dss_calc_clock_div(unsigned long req_pck, struct dss_clock_info *dss_cinfo,
463 struct dispc_clock_info *dispc_cinfo) 546 struct dispc_clock_info *dispc_cinfo)
464{ 547{
@@ -748,7 +831,7 @@ static void dss_runtime_put(void)
748} 831}
749 832
750/* DEBUGFS */ 833/* DEBUGFS */
751#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) 834#if defined(CONFIG_OMAP2_DSS_DEBUGFS)
752void dss_debug_dump_clocks(struct seq_file *s) 835void dss_debug_dump_clocks(struct seq_file *s)
753{ 836{
754 dss_dump_clocks(s); 837 dss_dump_clocks(s);
@@ -796,7 +879,6 @@ static const struct dss_features omap54xx_dss_feats __initconst = {
796 879
797static int __init dss_init_features(struct platform_device *pdev) 880static int __init dss_init_features(struct platform_device *pdev)
798{ 881{
799 struct omap_dss_board_info *pdata = pdev->dev.platform_data;
800 const struct dss_features *src; 882 const struct dss_features *src;
801 struct dss_features *dst; 883 struct dss_features *dst;
802 884
@@ -806,7 +888,7 @@ static int __init dss_init_features(struct platform_device *pdev)
806 return -ENOMEM; 888 return -ENOMEM;
807 } 889 }
808 890
809 switch (pdata->version) { 891 switch (omapdss_get_version()) {
810 case OMAPDSS_VER_OMAP24xx: 892 case OMAPDSS_VER_OMAP24xx:
811 src = &omap24xx_dss_feats; 893 src = &omap24xx_dss_feats;
812 break; 894 break;
@@ -871,15 +953,23 @@ static int __init omap_dsshw_probe(struct platform_device *pdev)
871 if (r) 953 if (r)
872 return r; 954 return r;
873 955
956 r = dss_setup_default_clock();
957 if (r)
958 goto err_setup_clocks;
959
874 pm_runtime_enable(&pdev->dev); 960 pm_runtime_enable(&pdev->dev);
875 961
876 r = dss_runtime_get(); 962 r = dss_runtime_get();
877 if (r) 963 if (r)
878 goto err_runtime_get; 964 goto err_runtime_get;
879 965
966 dss.dss_clk_rate = clk_get_rate(dss.dss_clk);
967
880 /* Select DPLL */ 968 /* Select DPLL */
881 REG_FLD_MOD(DSS_CONTROL, 0, 0, 0); 969 REG_FLD_MOD(DSS_CONTROL, 0, 0, 0);
882 970
971 dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
972
883#ifdef CONFIG_OMAP2_DSS_VENC 973#ifdef CONFIG_OMAP2_DSS_VENC
884 REG_FLD_MOD(DSS_CONTROL, 1, 4, 4); /* venc dac demen */ 974 REG_FLD_MOD(DSS_CONTROL, 1, 4, 4); /* venc dac demen */
885 REG_FLD_MOD(DSS_CONTROL, 1, 3, 3); /* venc clock 4x enable */ 975 REG_FLD_MOD(DSS_CONTROL, 1, 3, 3); /* venc clock 4x enable */
@@ -903,6 +993,7 @@ static int __init omap_dsshw_probe(struct platform_device *pdev)
903 993
904err_runtime_get: 994err_runtime_get:
905 pm_runtime_disable(&pdev->dev); 995 pm_runtime_disable(&pdev->dev);
996err_setup_clocks:
906 dss_put_clocks(); 997 dss_put_clocks();
907 return r; 998 return r;
908} 999}