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.c583
1 files changed, 135 insertions, 448 deletions
diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c
index d9489d5c4f08..0f9c3a6457a5 100644
--- a/drivers/video/omap2/dss/dss.c
+++ b/drivers/video/omap2/dss/dss.c
@@ -28,6 +28,8 @@
28#include <linux/delay.h> 28#include <linux/delay.h>
29#include <linux/seq_file.h> 29#include <linux/seq_file.h>
30#include <linux/clk.h> 30#include <linux/clk.h>
31#include <linux/platform_device.h>
32#include <linux/pm_runtime.h>
31 33
32#include <video/omapdss.h> 34#include <video/omapdss.h>
33#include <plat/clock.h> 35#include <plat/clock.h>
@@ -59,15 +61,9 @@ struct dss_reg {
59static struct { 61static struct {
60 struct platform_device *pdev; 62 struct platform_device *pdev;
61 void __iomem *base; 63 void __iomem *base;
62 int ctx_id;
63 64
64 struct clk *dpll4_m4_ck; 65 struct clk *dpll4_m4_ck;
65 struct clk *dss_ick; 66 struct clk *dss_clk;
66 struct clk *dss_fck;
67 struct clk *dss_sys_clk;
68 struct clk *dss_tv_fck;
69 struct clk *dss_video_fck;
70 unsigned num_clks_enabled;
71 67
72 unsigned long cache_req_pck; 68 unsigned long cache_req_pck;
73 unsigned long cache_prate; 69 unsigned long cache_prate;
@@ -78,6 +74,7 @@ static struct {
78 enum omap_dss_clk_source dispc_clk_source; 74 enum omap_dss_clk_source dispc_clk_source;
79 enum omap_dss_clk_source lcd_clk_source[MAX_DSS_LCD_MANAGERS]; 75 enum omap_dss_clk_source lcd_clk_source[MAX_DSS_LCD_MANAGERS];
80 76
77 bool ctx_valid;
81 u32 ctx[DSS_SZ_REGS / sizeof(u32)]; 78 u32 ctx[DSS_SZ_REGS / sizeof(u32)];
82} dss; 79} dss;
83 80
@@ -87,13 +84,6 @@ static const char * const dss_generic_clk_source_names[] = {
87 [OMAP_DSS_CLK_SRC_FCK] = "DSS_FCK", 84 [OMAP_DSS_CLK_SRC_FCK] = "DSS_FCK",
88}; 85};
89 86
90static void dss_clk_enable_all_no_ctx(void);
91static void dss_clk_disable_all_no_ctx(void);
92static void dss_clk_enable_no_ctx(enum dss_clock clks);
93static void dss_clk_disable_no_ctx(enum dss_clock clks);
94
95static int _omap_dss_wait_reset(void);
96
97static inline void dss_write_reg(const struct dss_reg idx, u32 val) 87static inline void dss_write_reg(const struct dss_reg idx, u32 val)
98{ 88{
99 __raw_writel(val, dss.base + idx.idx); 89 __raw_writel(val, dss.base + idx.idx);
@@ -109,12 +99,10 @@ static inline u32 dss_read_reg(const struct dss_reg idx)
109#define RR(reg) \ 99#define RR(reg) \
110 dss_write_reg(DSS_##reg, dss.ctx[(DSS_##reg).idx / sizeof(u32)]) 100 dss_write_reg(DSS_##reg, dss.ctx[(DSS_##reg).idx / sizeof(u32)])
111 101
112void dss_save_context(void) 102static void dss_save_context(void)
113{ 103{
114 if (cpu_is_omap24xx()) 104 DSSDBG("dss_save_context\n");
115 return;
116 105
117 SR(SYSCONFIG);
118 SR(CONTROL); 106 SR(CONTROL);
119 107
120 if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) & 108 if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) &
@@ -122,14 +110,19 @@ void dss_save_context(void)
122 SR(SDI_CONTROL); 110 SR(SDI_CONTROL);
123 SR(PLL_CONTROL); 111 SR(PLL_CONTROL);
124 } 112 }
113
114 dss.ctx_valid = true;
115
116 DSSDBG("context saved\n");
125} 117}
126 118
127void dss_restore_context(void) 119static void dss_restore_context(void)
128{ 120{
129 if (_omap_dss_wait_reset()) 121 DSSDBG("dss_restore_context\n");
130 DSSERR("DSS not coming out of reset after sleep\n"); 122
123 if (!dss.ctx_valid)
124 return;
131 125
132 RR(SYSCONFIG);
133 RR(CONTROL); 126 RR(CONTROL);
134 127
135 if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) & 128 if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) &
@@ -137,6 +130,8 @@ void dss_restore_context(void)
137 RR(SDI_CONTROL); 130 RR(SDI_CONTROL);
138 RR(PLL_CONTROL); 131 RR(PLL_CONTROL);
139 } 132 }
133
134 DSSDBG("context restored\n");
140} 135}
141 136
142#undef SR 137#undef SR
@@ -234,6 +229,7 @@ const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src)
234 return dss_generic_clk_source_names[clk_src]; 229 return dss_generic_clk_source_names[clk_src];
235} 230}
236 231
232
237void dss_dump_clocks(struct seq_file *s) 233void dss_dump_clocks(struct seq_file *s)
238{ 234{
239 unsigned long dpll4_ck_rate; 235 unsigned long dpll4_ck_rate;
@@ -241,13 +237,14 @@ void dss_dump_clocks(struct seq_file *s)
241 const char *fclk_name, *fclk_real_name; 237 const char *fclk_name, *fclk_real_name;
242 unsigned long fclk_rate; 238 unsigned long fclk_rate;
243 239
244 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); 240 if (dss_runtime_get())
241 return;
245 242
246 seq_printf(s, "- DSS -\n"); 243 seq_printf(s, "- DSS -\n");
247 244
248 fclk_name = dss_get_generic_clk_source_name(OMAP_DSS_CLK_SRC_FCK); 245 fclk_name = dss_get_generic_clk_source_name(OMAP_DSS_CLK_SRC_FCK);
249 fclk_real_name = dss_feat_get_clk_source_name(OMAP_DSS_CLK_SRC_FCK); 246 fclk_real_name = dss_feat_get_clk_source_name(OMAP_DSS_CLK_SRC_FCK);
250 fclk_rate = dss_clk_get_rate(DSS_CLK_FCK); 247 fclk_rate = clk_get_rate(dss.dss_clk);
251 248
252 if (dss.dpll4_m4_ck) { 249 if (dss.dpll4_m4_ck) {
253 dpll4_ck_rate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck)); 250 dpll4_ck_rate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
@@ -273,14 +270,15 @@ void dss_dump_clocks(struct seq_file *s)
273 fclk_rate); 270 fclk_rate);
274 } 271 }
275 272
276 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); 273 dss_runtime_put();
277} 274}
278 275
279void dss_dump_regs(struct seq_file *s) 276void dss_dump_regs(struct seq_file *s)
280{ 277{
281#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dss_read_reg(r)) 278#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dss_read_reg(r))
282 279
283 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); 280 if (dss_runtime_get())
281 return;
284 282
285 DUMPREG(DSS_REVISION); 283 DUMPREG(DSS_REVISION);
286 DUMPREG(DSS_SYSCONFIG); 284 DUMPREG(DSS_SYSCONFIG);
@@ -294,7 +292,7 @@ void dss_dump_regs(struct seq_file *s)
294 DUMPREG(DSS_SDI_STATUS); 292 DUMPREG(DSS_SDI_STATUS);
295 } 293 }
296 294
297 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); 295 dss_runtime_put();
298#undef DUMPREG 296#undef DUMPREG
299} 297}
300 298
@@ -437,7 +435,7 @@ int dss_calc_clock_rates(struct dss_clock_info *cinfo)
437 } else { 435 } else {
438 if (cinfo->fck_div != 0) 436 if (cinfo->fck_div != 0)
439 return -EINVAL; 437 return -EINVAL;
440 cinfo->fck = dss_clk_get_rate(DSS_CLK_FCK); 438 cinfo->fck = clk_get_rate(dss.dss_clk);
441 } 439 }
442 440
443 return 0; 441 return 0;
@@ -467,7 +465,7 @@ int dss_set_clock_div(struct dss_clock_info *cinfo)
467 465
468int dss_get_clock_div(struct dss_clock_info *cinfo) 466int dss_get_clock_div(struct dss_clock_info *cinfo)
469{ 467{
470 cinfo->fck = dss_clk_get_rate(DSS_CLK_FCK); 468 cinfo->fck = clk_get_rate(dss.dss_clk);
471 469
472 if (dss.dpll4_m4_ck) { 470 if (dss.dpll4_m4_ck) {
473 unsigned long prate; 471 unsigned long prate;
@@ -512,7 +510,7 @@ int dss_calc_clock_div(bool is_tft, unsigned long req_pck,
512 510
513 max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK); 511 max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
514 512
515 fck = dss_clk_get_rate(DSS_CLK_FCK); 513 fck = clk_get_rate(dss.dss_clk);
516 if (req_pck == dss.cache_req_pck && 514 if (req_pck == dss.cache_req_pck &&
517 ((cpu_is_omap34xx() && prate == dss.cache_prate) || 515 ((cpu_is_omap34xx() && prate == dss.cache_prate) ||
518 dss.cache_dss_cinfo.fck == fck)) { 516 dss.cache_dss_cinfo.fck == fck)) {
@@ -539,7 +537,7 @@ retry:
539 if (dss.dpll4_m4_ck == NULL) { 537 if (dss.dpll4_m4_ck == NULL) {
540 struct dispc_clock_info cur_dispc; 538 struct dispc_clock_info cur_dispc;
541 /* XXX can we change the clock on omap2? */ 539 /* XXX can we change the clock on omap2? */
542 fck = dss_clk_get_rate(DSS_CLK_FCK); 540 fck = clk_get_rate(dss.dss_clk);
543 fck_div = 1; 541 fck_div = 1;
544 542
545 dispc_find_clk_divs(is_tft, req_pck, fck, &cur_dispc); 543 dispc_find_clk_divs(is_tft, req_pck, fck, &cur_dispc);
@@ -616,28 +614,6 @@ found:
616 return 0; 614 return 0;
617} 615}
618 616
619static int _omap_dss_wait_reset(void)
620{
621 int t = 0;
622
623 while (REG_GET(DSS_SYSSTATUS, 0, 0) == 0) {
624 if (++t > 1000) {
625 DSSERR("soft reset failed\n");
626 return -ENODEV;
627 }
628 udelay(1);
629 }
630
631 return 0;
632}
633
634static int _omap_dss_reset(void)
635{
636 /* Soft reset */
637 REG_FLD_MOD(DSS_SYSCONFIG, 1, 1, 1);
638 return _omap_dss_wait_reset();
639}
640
641void dss_set_venc_output(enum omap_dss_venc_type type) 617void dss_set_venc_output(enum omap_dss_venc_type type)
642{ 618{
643 int l = 0; 619 int l = 0;
@@ -663,424 +639,88 @@ void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select hdmi)
663 REG_FLD_MOD(DSS_CONTROL, hdmi, 15, 15); /* VENC_HDMI_SWITCH */ 639 REG_FLD_MOD(DSS_CONTROL, hdmi, 15, 15); /* VENC_HDMI_SWITCH */
664} 640}
665 641
666static int dss_init(void) 642static int dss_get_clocks(void)
667{ 643{
644 struct clk *clk;
668 int r; 645 int r;
669 u32 rev;
670 struct resource *dss_mem;
671 struct clk *dpll4_m4_ck;
672 646
673 dss_mem = platform_get_resource(dss.pdev, IORESOURCE_MEM, 0); 647 clk = clk_get(&dss.pdev->dev, "fck");
674 if (!dss_mem) { 648 if (IS_ERR(clk)) {
675 DSSERR("can't get IORESOURCE_MEM DSS\n"); 649 DSSERR("can't get clock fck\n");
676 r = -EINVAL; 650 r = PTR_ERR(clk);
677 goto fail0; 651 goto err;
678 }
679 dss.base = ioremap(dss_mem->start, resource_size(dss_mem));
680 if (!dss.base) {
681 DSSERR("can't ioremap DSS\n");
682 r = -ENOMEM;
683 goto fail0;
684 } 652 }
685 653
686 /* disable LCD and DIGIT output. This seems to fix the synclost 654 dss.dss_clk = clk;
687 * problem that we get, if the bootloader starts the DSS and
688 * the kernel resets it */
689 omap_writel(omap_readl(0x48050440) & ~0x3, 0x48050440);
690
691#ifdef CONFIG_OMAP2_DSS_SLEEP_BEFORE_RESET
692 /* We need to wait here a bit, otherwise we sometimes start to
693 * get synclost errors, and after that only power cycle will
694 * restore DSS functionality. I have no idea why this happens.
695 * And we have to wait _before_ resetting the DSS, but after
696 * enabling clocks.
697 *
698 * This bug was at least present on OMAP3430. It's unknown
699 * if it happens on OMAP2 or OMAP3630.
700 */
701 msleep(50);
702#endif
703
704 _omap_dss_reset();
705 655
706 /* autoidle */
707 REG_FLD_MOD(DSS_SYSCONFIG, 1, 0, 0);
708
709 /* Select DPLL */
710 REG_FLD_MOD(DSS_CONTROL, 0, 0, 0);
711
712#ifdef CONFIG_OMAP2_DSS_VENC
713 REG_FLD_MOD(DSS_CONTROL, 1, 4, 4); /* venc dac demen */
714 REG_FLD_MOD(DSS_CONTROL, 1, 3, 3); /* venc clock 4x enable */
715 REG_FLD_MOD(DSS_CONTROL, 0, 2, 2); /* venc clock mode = normal */
716#endif
717 if (cpu_is_omap34xx()) { 656 if (cpu_is_omap34xx()) {
718 dpll4_m4_ck = clk_get(NULL, "dpll4_m4_ck"); 657 clk = clk_get(NULL, "dpll4_m4_ck");
719 if (IS_ERR(dpll4_m4_ck)) { 658 if (IS_ERR(clk)) {
720 DSSERR("Failed to get dpll4_m4_ck\n"); 659 DSSERR("Failed to get dpll4_m4_ck\n");
721 r = PTR_ERR(dpll4_m4_ck); 660 r = PTR_ERR(clk);
722 goto fail1; 661 goto err;
723 } 662 }
724 } else if (cpu_is_omap44xx()) { 663 } else if (cpu_is_omap44xx()) {
725 dpll4_m4_ck = clk_get(NULL, "dpll_per_m5x2_ck"); 664 clk = clk_get(NULL, "dpll_per_m5x2_ck");
726 if (IS_ERR(dpll4_m4_ck)) { 665 if (IS_ERR(clk)) {
727 DSSERR("Failed to get dpll4_m4_ck\n"); 666 DSSERR("Failed to get dpll_per_m5x2_ck\n");
728 r = PTR_ERR(dpll4_m4_ck); 667 r = PTR_ERR(clk);
729 goto fail1; 668 goto err;
730 } 669 }
731 } else { /* omap24xx */ 670 } else { /* omap24xx */
732 dpll4_m4_ck = NULL; 671 clk = NULL;
733 } 672 }
734 673
735 dss.dpll4_m4_ck = dpll4_m4_ck; 674 dss.dpll4_m4_ck = clk;
736
737 dss.dsi_clk_source[0] = OMAP_DSS_CLK_SRC_FCK;
738 dss.dsi_clk_source[1] = OMAP_DSS_CLK_SRC_FCK;
739 dss.dispc_clk_source = OMAP_DSS_CLK_SRC_FCK;
740 dss.lcd_clk_source[0] = OMAP_DSS_CLK_SRC_FCK;
741 dss.lcd_clk_source[1] = OMAP_DSS_CLK_SRC_FCK;
742
743 dss_save_context();
744
745 rev = dss_read_reg(DSS_REVISION);
746 printk(KERN_INFO "OMAP DSS rev %d.%d\n",
747 FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
748 675
749 return 0; 676 return 0;
750 677
751fail1: 678err:
752 iounmap(dss.base); 679 if (dss.dss_clk)
753fail0: 680 clk_put(dss.dss_clk);
754 return r;
755}
756
757static void dss_exit(void)
758{
759 if (dss.dpll4_m4_ck) 681 if (dss.dpll4_m4_ck)
760 clk_put(dss.dpll4_m4_ck); 682 clk_put(dss.dpll4_m4_ck);
761 683
762 iounmap(dss.base);
763}
764
765/* CONTEXT */
766static int dss_get_ctx_id(void)
767{
768 struct omap_display_platform_data *pdata = dss.pdev->dev.platform_data;
769 int r;
770
771 if (!pdata->board_data->get_last_off_on_transaction_id)
772 return 0;
773 r = pdata->board_data->get_last_off_on_transaction_id(&dss.pdev->dev);
774 if (r < 0) {
775 dev_err(&dss.pdev->dev, "getting transaction ID failed, "
776 "will force context restore\n");
777 r = -1;
778 }
779 return r;
780}
781
782int dss_need_ctx_restore(void)
783{
784 int id = dss_get_ctx_id();
785
786 if (id < 0 || id != dss.ctx_id) {
787 DSSDBG("ctx id %d -> id %d\n",
788 dss.ctx_id, id);
789 dss.ctx_id = id;
790 return 1;
791 } else {
792 return 0;
793 }
794}
795
796static void save_all_ctx(void)
797{
798 DSSDBG("save context\n");
799
800 dss_clk_enable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK);
801
802 dss_save_context();
803 dispc_save_context();
804#ifdef CONFIG_OMAP2_DSS_DSI
805 dsi_save_context();
806#endif
807
808 dss_clk_disable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK);
809}
810
811static void restore_all_ctx(void)
812{
813 DSSDBG("restore context\n");
814
815 dss_clk_enable_all_no_ctx();
816
817 dss_restore_context();
818 dispc_restore_context();
819#ifdef CONFIG_OMAP2_DSS_DSI
820 dsi_restore_context();
821#endif
822
823 dss_clk_disable_all_no_ctx();
824}
825
826static int dss_get_clock(struct clk **clock, const char *clk_name)
827{
828 struct clk *clk;
829
830 clk = clk_get(&dss.pdev->dev, clk_name);
831
832 if (IS_ERR(clk)) {
833 DSSERR("can't get clock %s", clk_name);
834 return PTR_ERR(clk);
835 }
836
837 *clock = clk;
838
839 DSSDBG("clk %s, rate %ld\n", clk_name, clk_get_rate(clk));
840
841 return 0;
842}
843
844static int dss_get_clocks(void)
845{
846 int r;
847 struct omap_display_platform_data *pdata = dss.pdev->dev.platform_data;
848
849 dss.dss_ick = NULL;
850 dss.dss_fck = NULL;
851 dss.dss_sys_clk = NULL;
852 dss.dss_tv_fck = NULL;
853 dss.dss_video_fck = NULL;
854
855 r = dss_get_clock(&dss.dss_ick, "ick");
856 if (r)
857 goto err;
858
859 r = dss_get_clock(&dss.dss_fck, "fck");
860 if (r)
861 goto err;
862
863 if (!pdata->opt_clock_available) {
864 r = -ENODEV;
865 goto err;
866 }
867
868 if (pdata->opt_clock_available("sys_clk")) {
869 r = dss_get_clock(&dss.dss_sys_clk, "sys_clk");
870 if (r)
871 goto err;
872 }
873
874 if (pdata->opt_clock_available("tv_clk")) {
875 r = dss_get_clock(&dss.dss_tv_fck, "tv_clk");
876 if (r)
877 goto err;
878 }
879
880 if (pdata->opt_clock_available("video_clk")) {
881 r = dss_get_clock(&dss.dss_video_fck, "video_clk");
882 if (r)
883 goto err;
884 }
885
886 return 0;
887
888err:
889 if (dss.dss_ick)
890 clk_put(dss.dss_ick);
891 if (dss.dss_fck)
892 clk_put(dss.dss_fck);
893 if (dss.dss_sys_clk)
894 clk_put(dss.dss_sys_clk);
895 if (dss.dss_tv_fck)
896 clk_put(dss.dss_tv_fck);
897 if (dss.dss_video_fck)
898 clk_put(dss.dss_video_fck);
899
900 return r; 684 return r;
901} 685}
902 686
903static void dss_put_clocks(void) 687static void dss_put_clocks(void)
904{ 688{
905 if (dss.dss_video_fck) 689 if (dss.dpll4_m4_ck)
906 clk_put(dss.dss_video_fck); 690 clk_put(dss.dpll4_m4_ck);
907 if (dss.dss_tv_fck) 691 clk_put(dss.dss_clk);
908 clk_put(dss.dss_tv_fck);
909 if (dss.dss_sys_clk)
910 clk_put(dss.dss_sys_clk);
911 clk_put(dss.dss_fck);
912 clk_put(dss.dss_ick);
913}
914
915unsigned long dss_clk_get_rate(enum dss_clock clk)
916{
917 switch (clk) {
918 case DSS_CLK_ICK:
919 return clk_get_rate(dss.dss_ick);
920 case DSS_CLK_FCK:
921 return clk_get_rate(dss.dss_fck);
922 case DSS_CLK_SYSCK:
923 return clk_get_rate(dss.dss_sys_clk);
924 case DSS_CLK_TVFCK:
925 return clk_get_rate(dss.dss_tv_fck);
926 case DSS_CLK_VIDFCK:
927 return clk_get_rate(dss.dss_video_fck);
928 }
929
930 BUG();
931 return 0;
932}
933
934static unsigned count_clk_bits(enum dss_clock clks)
935{
936 unsigned num_clks = 0;
937
938 if (clks & DSS_CLK_ICK)
939 ++num_clks;
940 if (clks & DSS_CLK_FCK)
941 ++num_clks;
942 if (clks & DSS_CLK_SYSCK)
943 ++num_clks;
944 if (clks & DSS_CLK_TVFCK)
945 ++num_clks;
946 if (clks & DSS_CLK_VIDFCK)
947 ++num_clks;
948
949 return num_clks;
950}
951
952static void dss_clk_enable_no_ctx(enum dss_clock clks)
953{
954 unsigned num_clks = count_clk_bits(clks);
955
956 if (clks & DSS_CLK_ICK)
957 clk_enable(dss.dss_ick);
958 if (clks & DSS_CLK_FCK)
959 clk_enable(dss.dss_fck);
960 if ((clks & DSS_CLK_SYSCK) && dss.dss_sys_clk)
961 clk_enable(dss.dss_sys_clk);
962 if ((clks & DSS_CLK_TVFCK) && dss.dss_tv_fck)
963 clk_enable(dss.dss_tv_fck);
964 if ((clks & DSS_CLK_VIDFCK) && dss.dss_video_fck)
965 clk_enable(dss.dss_video_fck);
966
967 dss.num_clks_enabled += num_clks;
968}
969
970void dss_clk_enable(enum dss_clock clks)
971{
972 bool check_ctx = dss.num_clks_enabled == 0;
973
974 dss_clk_enable_no_ctx(clks);
975
976 /*
977 * HACK: On omap4 the registers may not be accessible right after
978 * enabling the clocks. At some point this will be handled by
979 * pm_runtime, but for the time begin this should make things work.
980 */
981 if (cpu_is_omap44xx() && check_ctx)
982 udelay(10);
983
984 if (check_ctx && cpu_is_omap34xx() && dss_need_ctx_restore())
985 restore_all_ctx();
986} 692}
987 693
988static void dss_clk_disable_no_ctx(enum dss_clock clks) 694struct clk *dss_get_ick(void)
989{ 695{
990 unsigned num_clks = count_clk_bits(clks); 696 return clk_get(&dss.pdev->dev, "ick");
991
992 if (clks & DSS_CLK_ICK)
993 clk_disable(dss.dss_ick);
994 if (clks & DSS_CLK_FCK)
995 clk_disable(dss.dss_fck);
996 if ((clks & DSS_CLK_SYSCK) && dss.dss_sys_clk)
997 clk_disable(dss.dss_sys_clk);
998 if ((clks & DSS_CLK_TVFCK) && dss.dss_tv_fck)
999 clk_disable(dss.dss_tv_fck);
1000 if ((clks & DSS_CLK_VIDFCK) && dss.dss_video_fck)
1001 clk_disable(dss.dss_video_fck);
1002
1003 dss.num_clks_enabled -= num_clks;
1004} 697}
1005 698
1006void dss_clk_disable(enum dss_clock clks) 699int dss_runtime_get(void)
1007{ 700{
1008 if (cpu_is_omap34xx()) { 701 int r;
1009 unsigned num_clks = count_clk_bits(clks);
1010
1011 BUG_ON(dss.num_clks_enabled < num_clks);
1012 702
1013 if (dss.num_clks_enabled == num_clks) 703 DSSDBG("dss_runtime_get\n");
1014 save_all_ctx();
1015 }
1016 704
1017 dss_clk_disable_no_ctx(clks); 705 r = pm_runtime_get_sync(&dss.pdev->dev);
706 WARN_ON(r < 0);
707 return r < 0 ? r : 0;
1018} 708}
1019 709
1020static void dss_clk_enable_all_no_ctx(void) 710void dss_runtime_put(void)
1021{ 711{
1022 enum dss_clock clks; 712 int r;
1023
1024 clks = DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_SYSCK | DSS_CLK_TVFCK;
1025 if (cpu_is_omap34xx())
1026 clks |= DSS_CLK_VIDFCK;
1027 dss_clk_enable_no_ctx(clks);
1028}
1029
1030static void dss_clk_disable_all_no_ctx(void)
1031{
1032 enum dss_clock clks;
1033 713
1034 clks = DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_SYSCK | DSS_CLK_TVFCK; 714 DSSDBG("dss_runtime_put\n");
1035 if (cpu_is_omap34xx())
1036 clks |= DSS_CLK_VIDFCK;
1037 dss_clk_disable_no_ctx(clks);
1038}
1039 715
1040#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) 716 r = pm_runtime_put(&dss.pdev->dev);
1041/* CLOCKS */ 717 WARN_ON(r < 0);
1042static void core_dump_clocks(struct seq_file *s)
1043{
1044 int i;
1045 struct clk *clocks[5] = {
1046 dss.dss_ick,
1047 dss.dss_fck,
1048 dss.dss_sys_clk,
1049 dss.dss_tv_fck,
1050 dss.dss_video_fck
1051 };
1052
1053 const char *names[5] = {
1054 "ick",
1055 "fck",
1056 "sys_clk",
1057 "tv_fck",
1058 "video_fck"
1059 };
1060
1061 seq_printf(s, "- CORE -\n");
1062
1063 seq_printf(s, "internal clk count\t\t%u\n", dss.num_clks_enabled);
1064
1065 for (i = 0; i < 5; i++) {
1066 if (!clocks[i])
1067 continue;
1068 seq_printf(s, "%s (%s)%*s\t%lu\t%d\n",
1069 names[i],
1070 clocks[i]->name,
1071 24 - strlen(names[i]) - strlen(clocks[i]->name),
1072 "",
1073 clk_get_rate(clocks[i]),
1074 clocks[i]->usecount);
1075 }
1076} 718}
1077#endif /* defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) */
1078 719
1079/* DEBUGFS */ 720/* DEBUGFS */
1080#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) 721#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
1081void dss_debug_dump_clocks(struct seq_file *s) 722void dss_debug_dump_clocks(struct seq_file *s)
1082{ 723{
1083 core_dump_clocks(s);
1084 dss_dump_clocks(s); 724 dss_dump_clocks(s);
1085 dispc_dump_clocks(s); 725 dispc_dump_clocks(s);
1086#ifdef CONFIG_OMAP2_DSS_DSI 726#ifdef CONFIG_OMAP2_DSS_DSI
@@ -1089,28 +729,51 @@ void dss_debug_dump_clocks(struct seq_file *s)
1089} 729}
1090#endif 730#endif
1091 731
1092
1093/* DSS HW IP initialisation */ 732/* DSS HW IP initialisation */
1094static int omap_dsshw_probe(struct platform_device *pdev) 733static int omap_dsshw_probe(struct platform_device *pdev)
1095{ 734{
735 struct resource *dss_mem;
736 u32 rev;
1096 int r; 737 int r;
1097 738
1098 dss.pdev = pdev; 739 dss.pdev = pdev;
1099 740
741 dss_mem = platform_get_resource(dss.pdev, IORESOURCE_MEM, 0);
742 if (!dss_mem) {
743 DSSERR("can't get IORESOURCE_MEM DSS\n");
744 r = -EINVAL;
745 goto err_ioremap;
746 }
747 dss.base = ioremap(dss_mem->start, resource_size(dss_mem));
748 if (!dss.base) {
749 DSSERR("can't ioremap DSS\n");
750 r = -ENOMEM;
751 goto err_ioremap;
752 }
753
1100 r = dss_get_clocks(); 754 r = dss_get_clocks();
1101 if (r) 755 if (r)
1102 goto err_clocks; 756 goto err_clocks;
1103 757
1104 dss_clk_enable_all_no_ctx(); 758 pm_runtime_enable(&pdev->dev);
1105 759
1106 dss.ctx_id = dss_get_ctx_id(); 760 r = dss_runtime_get();
1107 DSSDBG("initial ctx id %u\n", dss.ctx_id); 761 if (r)
762 goto err_runtime_get;
1108 763
1109 r = dss_init(); 764 /* Select DPLL */
1110 if (r) { 765 REG_FLD_MOD(DSS_CONTROL, 0, 0, 0);
1111 DSSERR("Failed to initialize DSS\n"); 766
1112 goto err_dss; 767#ifdef CONFIG_OMAP2_DSS_VENC
1113 } 768 REG_FLD_MOD(DSS_CONTROL, 1, 4, 4); /* venc dac demen */
769 REG_FLD_MOD(DSS_CONTROL, 1, 3, 3); /* venc clock 4x enable */
770 REG_FLD_MOD(DSS_CONTROL, 0, 2, 2); /* venc clock mode = normal */
771#endif
772 dss.dsi_clk_source[0] = OMAP_DSS_CLK_SRC_FCK;
773 dss.dsi_clk_source[1] = OMAP_DSS_CLK_SRC_FCK;
774 dss.dispc_clk_source = OMAP_DSS_CLK_SRC_FCK;
775 dss.lcd_clk_source[0] = OMAP_DSS_CLK_SRC_FCK;
776 dss.lcd_clk_source[1] = OMAP_DSS_CLK_SRC_FCK;
1114 777
1115 r = dpi_init(); 778 r = dpi_init();
1116 if (r) { 779 if (r) {
@@ -1124,42 +787,66 @@ static int omap_dsshw_probe(struct platform_device *pdev)
1124 goto err_sdi; 787 goto err_sdi;
1125 } 788 }
1126 789
1127 dss_clk_disable_all_no_ctx(); 790 rev = dss_read_reg(DSS_REVISION);
791 printk(KERN_INFO "OMAP DSS rev %d.%d\n",
792 FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
793
794 dss_runtime_put();
795
1128 return 0; 796 return 0;
1129err_sdi: 797err_sdi:
1130 dpi_exit(); 798 dpi_exit();
1131err_dpi: 799err_dpi:
1132 dss_exit(); 800 dss_runtime_put();
1133err_dss: 801err_runtime_get:
1134 dss_clk_disable_all_no_ctx(); 802 pm_runtime_disable(&pdev->dev);
1135 dss_put_clocks(); 803 dss_put_clocks();
1136err_clocks: 804err_clocks:
805 iounmap(dss.base);
806err_ioremap:
1137 return r; 807 return r;
1138} 808}
1139 809
1140static int omap_dsshw_remove(struct platform_device *pdev) 810static int omap_dsshw_remove(struct platform_device *pdev)
1141{ 811{
812 dpi_exit();
813 sdi_exit();
1142 814
1143 dss_exit(); 815 iounmap(dss.base);
1144 816
1145 /* 817 pm_runtime_disable(&pdev->dev);
1146 * As part of hwmod changes, DSS is not the only controller of dss
1147 * clocks; hwmod framework itself will also enable clocks during hwmod
1148 * init for dss, and autoidle is set in h/w for DSS. Hence, there's no
1149 * need to disable clocks if their usecounts > 1.
1150 */
1151 WARN_ON(dss.num_clks_enabled > 0);
1152 818
1153 dss_put_clocks(); 819 dss_put_clocks();
820
821 return 0;
822}
823
824static int dss_runtime_suspend(struct device *dev)
825{
826 dss_save_context();
827 clk_disable(dss.dss_clk);
1154 return 0; 828 return 0;
1155} 829}
1156 830
831static int dss_runtime_resume(struct device *dev)
832{
833 clk_enable(dss.dss_clk);
834 dss_restore_context();
835 return 0;
836}
837
838static const struct dev_pm_ops dss_pm_ops = {
839 .runtime_suspend = dss_runtime_suspend,
840 .runtime_resume = dss_runtime_resume,
841};
842
1157static struct platform_driver omap_dsshw_driver = { 843static struct platform_driver omap_dsshw_driver = {
1158 .probe = omap_dsshw_probe, 844 .probe = omap_dsshw_probe,
1159 .remove = omap_dsshw_remove, 845 .remove = omap_dsshw_remove,
1160 .driver = { 846 .driver = {
1161 .name = "omapdss_dss", 847 .name = "omapdss_dss",
1162 .owner = THIS_MODULE, 848 .owner = THIS_MODULE,
849 .pm = &dss_pm_ops,
1163 }, 850 },
1164}; 851};
1165 852