OMAP2PLUS: DSS2: DSI: Generalize DSI PLL Clock Naming
[firefly-linux-kernel-4.4.55.git] / drivers / video / omap2 / dss / dss.c
1 /*
2  * linux/drivers/video/omap2/dss/dss.c
3  *
4  * Copyright (C) 2009 Nokia Corporation
5  * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
6  *
7  * Some code and ideas taken from drivers/video/omap/ driver
8  * by Imre Deak.
9  *
10  * This program is free software; you can redistribute it and/or modify it
11  * under the terms of the GNU General Public License version 2 as published by
12  * the Free Software Foundation.
13  *
14  * This program is distributed in the hope that it will be useful, but WITHOUT
15  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
17  * more details.
18  *
19  * You should have received a copy of the GNU General Public License along with
20  * this program.  If not, see <http://www.gnu.org/licenses/>.
21  */
22
23 #define DSS_SUBSYS_NAME "DSS"
24
25 #include <linux/kernel.h>
26 #include <linux/io.h>
27 #include <linux/err.h>
28 #include <linux/delay.h>
29 #include <linux/seq_file.h>
30 #include <linux/clk.h>
31
32 #include <plat/display.h>
33 #include <plat/clock.h>
34 #include "dss.h"
35 #include "dss_features.h"
36
37 #define DSS_SZ_REGS                     SZ_512
38
39 struct dss_reg {
40         u16 idx;
41 };
42
43 #define DSS_REG(idx)                    ((const struct dss_reg) { idx })
44
45 #define DSS_REVISION                    DSS_REG(0x0000)
46 #define DSS_SYSCONFIG                   DSS_REG(0x0010)
47 #define DSS_SYSSTATUS                   DSS_REG(0x0014)
48 #define DSS_IRQSTATUS                   DSS_REG(0x0018)
49 #define DSS_CONTROL                     DSS_REG(0x0040)
50 #define DSS_SDI_CONTROL                 DSS_REG(0x0044)
51 #define DSS_PLL_CONTROL                 DSS_REG(0x0048)
52 #define DSS_SDI_STATUS                  DSS_REG(0x005C)
53
54 #define REG_GET(idx, start, end) \
55         FLD_GET(dss_read_reg(idx), start, end)
56
57 #define REG_FLD_MOD(idx, val, start, end) \
58         dss_write_reg(idx, FLD_MOD(dss_read_reg(idx), val, start, end))
59
60 static struct {
61         struct platform_device *pdev;
62         void __iomem    *base;
63         int             ctx_id;
64
65         struct clk      *dpll4_m4_ck;
66         struct clk      *dss_ick;
67         struct clk      *dss_fck;
68         struct clk      *dss_sys_clk;
69         struct clk      *dss_tv_fck;
70         struct clk      *dss_video_fck;
71         unsigned        num_clks_enabled;
72
73         unsigned long   cache_req_pck;
74         unsigned long   cache_prate;
75         struct dss_clock_info cache_dss_cinfo;
76         struct dispc_clock_info cache_dispc_cinfo;
77
78         enum dss_clk_source dsi_clk_source;
79         enum dss_clk_source dispc_clk_source;
80
81         u32             ctx[DSS_SZ_REGS / sizeof(u32)];
82 } dss;
83
84 static const struct dss_clk_source_name dss_generic_clk_source_names[] = {
85         { DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC, "DSI_PLL_HSDIV_DISPC" },
86         { DSS_CLK_SRC_DSI_PLL_HSDIV_DSI, "DSI_PLL_HSDIV_DSI" },
87         { DSS_CLK_SRC_FCK, "DSS_FCK" },
88 };
89
90 static void dss_clk_enable_all_no_ctx(void);
91 static void dss_clk_disable_all_no_ctx(void);
92 static void dss_clk_enable_no_ctx(enum dss_clock clks);
93 static void dss_clk_disable_no_ctx(enum dss_clock clks);
94
95 static int _omap_dss_wait_reset(void);
96
97 static inline void dss_write_reg(const struct dss_reg idx, u32 val)
98 {
99         __raw_writel(val, dss.base + idx.idx);
100 }
101
102 static inline u32 dss_read_reg(const struct dss_reg idx)
103 {
104         return __raw_readl(dss.base + idx.idx);
105 }
106
107 #define SR(reg) \
108         dss.ctx[(DSS_##reg).idx / sizeof(u32)] = dss_read_reg(DSS_##reg)
109 #define RR(reg) \
110         dss_write_reg(DSS_##reg, dss.ctx[(DSS_##reg).idx / sizeof(u32)])
111
112 void dss_save_context(void)
113 {
114         if (cpu_is_omap24xx())
115                 return;
116
117         SR(SYSCONFIG);
118         SR(CONTROL);
119
120         if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) &
121                         OMAP_DISPLAY_TYPE_SDI) {
122                 SR(SDI_CONTROL);
123                 SR(PLL_CONTROL);
124         }
125 }
126
127 void dss_restore_context(void)
128 {
129         if (_omap_dss_wait_reset())
130                 DSSERR("DSS not coming out of reset after sleep\n");
131
132         RR(SYSCONFIG);
133         RR(CONTROL);
134
135         if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) &
136                         OMAP_DISPLAY_TYPE_SDI) {
137                 RR(SDI_CONTROL);
138                 RR(PLL_CONTROL);
139         }
140 }
141
142 #undef SR
143 #undef RR
144
145 void dss_sdi_init(u8 datapairs)
146 {
147         u32 l;
148
149         BUG_ON(datapairs > 3 || datapairs < 1);
150
151         l = dss_read_reg(DSS_SDI_CONTROL);
152         l = FLD_MOD(l, 0xf, 19, 15);            /* SDI_PDIV */
153         l = FLD_MOD(l, datapairs-1, 3, 2);      /* SDI_PRSEL */
154         l = FLD_MOD(l, 2, 1, 0);                /* SDI_BWSEL */
155         dss_write_reg(DSS_SDI_CONTROL, l);
156
157         l = dss_read_reg(DSS_PLL_CONTROL);
158         l = FLD_MOD(l, 0x7, 25, 22);    /* SDI_PLL_FREQSEL */
159         l = FLD_MOD(l, 0xb, 16, 11);    /* SDI_PLL_REGN */
160         l = FLD_MOD(l, 0xb4, 10, 1);    /* SDI_PLL_REGM */
161         dss_write_reg(DSS_PLL_CONTROL, l);
162 }
163
164 int dss_sdi_enable(void)
165 {
166         unsigned long timeout;
167
168         dispc_pck_free_enable(1);
169
170         /* Reset SDI PLL */
171         REG_FLD_MOD(DSS_PLL_CONTROL, 1, 18, 18); /* SDI_PLL_SYSRESET */
172         udelay(1);      /* wait 2x PCLK */
173
174         /* Lock SDI PLL */
175         REG_FLD_MOD(DSS_PLL_CONTROL, 1, 28, 28); /* SDI_PLL_GOBIT */
176
177         /* Waiting for PLL lock request to complete */
178         timeout = jiffies + msecs_to_jiffies(500);
179         while (dss_read_reg(DSS_SDI_STATUS) & (1 << 6)) {
180                 if (time_after_eq(jiffies, timeout)) {
181                         DSSERR("PLL lock request timed out\n");
182                         goto err1;
183                 }
184         }
185
186         /* Clearing PLL_GO bit */
187         REG_FLD_MOD(DSS_PLL_CONTROL, 0, 28, 28);
188
189         /* Waiting for PLL to lock */
190         timeout = jiffies + msecs_to_jiffies(500);
191         while (!(dss_read_reg(DSS_SDI_STATUS) & (1 << 5))) {
192                 if (time_after_eq(jiffies, timeout)) {
193                         DSSERR("PLL lock timed out\n");
194                         goto err1;
195                 }
196         }
197
198         dispc_lcd_enable_signal(1);
199
200         /* Waiting for SDI reset to complete */
201         timeout = jiffies + msecs_to_jiffies(500);
202         while (!(dss_read_reg(DSS_SDI_STATUS) & (1 << 2))) {
203                 if (time_after_eq(jiffies, timeout)) {
204                         DSSERR("SDI reset timed out\n");
205                         goto err2;
206                 }
207         }
208
209         return 0;
210
211  err2:
212         dispc_lcd_enable_signal(0);
213  err1:
214         /* Reset SDI PLL */
215         REG_FLD_MOD(DSS_PLL_CONTROL, 0, 18, 18); /* SDI_PLL_SYSRESET */
216
217         dispc_pck_free_enable(0);
218
219         return -ETIMEDOUT;
220 }
221
222 void dss_sdi_disable(void)
223 {
224         dispc_lcd_enable_signal(0);
225
226         dispc_pck_free_enable(0);
227
228         /* Reset SDI PLL */
229         REG_FLD_MOD(DSS_PLL_CONTROL, 0, 18, 18); /* SDI_PLL_SYSRESET */
230 }
231
232 const char *dss_get_generic_clk_source_name(enum dss_clk_source clk_src)
233 {
234         return dss_generic_clk_source_names[clk_src].clksrc_name;
235 }
236
237 void dss_dump_clocks(struct seq_file *s)
238 {
239         unsigned long dpll4_ck_rate;
240         unsigned long dpll4_m4_ck_rate;
241
242         dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
243
244         dpll4_ck_rate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
245         dpll4_m4_ck_rate = clk_get_rate(dss.dpll4_m4_ck);
246
247         seq_printf(s, "- DSS -\n");
248
249         seq_printf(s, "dpll4_ck %lu\n", dpll4_ck_rate);
250
251         if (cpu_is_omap3630())
252                 seq_printf(s, "%s (%s) = %lu / %lu  = %lu\n",
253                         dss_get_generic_clk_source_name(DSS_CLK_SRC_FCK),
254                         dss_feat_get_clk_source_name(DSS_CLK_SRC_FCK),
255                         dpll4_ck_rate,
256                         dpll4_ck_rate / dpll4_m4_ck_rate,
257                         dss_clk_get_rate(DSS_CLK_FCK));
258         else
259                 seq_printf(s, "%s (%s) = %lu / %lu * 2 = %lu\n",
260                         dss_get_generic_clk_source_name(DSS_CLK_SRC_FCK),
261                         dss_feat_get_clk_source_name(DSS_CLK_SRC_FCK),
262                         dpll4_ck_rate,
263                         dpll4_ck_rate / dpll4_m4_ck_rate,
264                         dss_clk_get_rate(DSS_CLK_FCK));
265
266         dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
267 }
268
269 void dss_dump_regs(struct seq_file *s)
270 {
271 #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dss_read_reg(r))
272
273         dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
274
275         DUMPREG(DSS_REVISION);
276         DUMPREG(DSS_SYSCONFIG);
277         DUMPREG(DSS_SYSSTATUS);
278         DUMPREG(DSS_IRQSTATUS);
279         DUMPREG(DSS_CONTROL);
280
281         if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) &
282                         OMAP_DISPLAY_TYPE_SDI) {
283                 DUMPREG(DSS_SDI_CONTROL);
284                 DUMPREG(DSS_PLL_CONTROL);
285                 DUMPREG(DSS_SDI_STATUS);
286         }
287
288         dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
289 #undef DUMPREG
290 }
291
292 void dss_select_dispc_clk_source(enum dss_clk_source clk_src)
293 {
294         int b;
295
296         BUG_ON(clk_src != DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC &&
297                         clk_src != DSS_CLK_SRC_FCK);
298
299         b = clk_src == DSS_CLK_SRC_FCK ? 0 : 1;
300
301         if (clk_src == DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC)
302                 dsi_wait_pll_hsdiv_dispc_active();
303
304         REG_FLD_MOD(DSS_CONTROL, b, 0, 0);      /* DISPC_CLK_SWITCH */
305
306         dss.dispc_clk_source = clk_src;
307 }
308
309 void dss_select_dsi_clk_source(enum dss_clk_source clk_src)
310 {
311         int b;
312
313         BUG_ON(clk_src != DSS_CLK_SRC_DSI_PLL_HSDIV_DSI &&
314                         clk_src != DSS_CLK_SRC_FCK);
315
316         b = clk_src == DSS_CLK_SRC_FCK ? 0 : 1;
317
318         if (clk_src == DSS_CLK_SRC_DSI_PLL_HSDIV_DSI)
319                 dsi_wait_pll_hsdiv_dsi_active();
320
321         REG_FLD_MOD(DSS_CONTROL, b, 1, 1);      /* DSI_CLK_SWITCH */
322
323         dss.dsi_clk_source = clk_src;
324 }
325
326 enum dss_clk_source dss_get_dispc_clk_source(void)
327 {
328         return dss.dispc_clk_source;
329 }
330
331 enum dss_clk_source dss_get_dsi_clk_source(void)
332 {
333         return dss.dsi_clk_source;
334 }
335
336 /* calculate clock rates using dividers in cinfo */
337 int dss_calc_clock_rates(struct dss_clock_info *cinfo)
338 {
339         unsigned long prate;
340
341         if (cinfo->fck_div > (cpu_is_omap3630() ? 32 : 16) ||
342                                                 cinfo->fck_div == 0)
343                 return -EINVAL;
344
345         prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
346
347         cinfo->fck = prate / cinfo->fck_div;
348
349         return 0;
350 }
351
352 int dss_set_clock_div(struct dss_clock_info *cinfo)
353 {
354         unsigned long prate;
355         int r;
356
357         if (cpu_is_omap34xx()) {
358                 prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
359                 DSSDBG("dpll4_m4 = %ld\n", prate);
360
361                 r = clk_set_rate(dss.dpll4_m4_ck, prate / cinfo->fck_div);
362                 if (r)
363                         return r;
364         }
365
366         DSSDBG("fck = %ld (%d)\n", cinfo->fck, cinfo->fck_div);
367
368         return 0;
369 }
370
371 int dss_get_clock_div(struct dss_clock_info *cinfo)
372 {
373         cinfo->fck = dss_clk_get_rate(DSS_CLK_FCK);
374
375         if (cpu_is_omap34xx()) {
376                 unsigned long prate;
377                 prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
378                 if (cpu_is_omap3630())
379                         cinfo->fck_div = prate / (cinfo->fck);
380                 else
381                         cinfo->fck_div = prate / (cinfo->fck / 2);
382         } else {
383                 cinfo->fck_div = 0;
384         }
385
386         return 0;
387 }
388
389 unsigned long dss_get_dpll4_rate(void)
390 {
391         if (cpu_is_omap34xx())
392                 return clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
393         else
394                 return 0;
395 }
396
397 int dss_calc_clock_div(bool is_tft, unsigned long req_pck,
398                 struct dss_clock_info *dss_cinfo,
399                 struct dispc_clock_info *dispc_cinfo)
400 {
401         unsigned long prate;
402         struct dss_clock_info best_dss;
403         struct dispc_clock_info best_dispc;
404
405         unsigned long fck, max_dss_fck;
406
407         u16 fck_div;
408
409         int match = 0;
410         int min_fck_per_pck;
411
412         prate = dss_get_dpll4_rate();
413
414         max_dss_fck = dss_feat_get_max_dss_fck();
415
416         fck = dss_clk_get_rate(DSS_CLK_FCK);
417         if (req_pck == dss.cache_req_pck &&
418                         ((cpu_is_omap34xx() && prate == dss.cache_prate) ||
419                          dss.cache_dss_cinfo.fck == fck)) {
420                 DSSDBG("dispc clock info found from cache.\n");
421                 *dss_cinfo = dss.cache_dss_cinfo;
422                 *dispc_cinfo = dss.cache_dispc_cinfo;
423                 return 0;
424         }
425
426         min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK;
427
428         if (min_fck_per_pck &&
429                 req_pck * min_fck_per_pck > max_dss_fck) {
430                 DSSERR("Requested pixel clock not possible with the current "
431                                 "OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning "
432                                 "the constraint off.\n");
433                 min_fck_per_pck = 0;
434         }
435
436 retry:
437         memset(&best_dss, 0, sizeof(best_dss));
438         memset(&best_dispc, 0, sizeof(best_dispc));
439
440         if (cpu_is_omap24xx()) {
441                 struct dispc_clock_info cur_dispc;
442                 /* XXX can we change the clock on omap2? */
443                 fck = dss_clk_get_rate(DSS_CLK_FCK);
444                 fck_div = 1;
445
446                 dispc_find_clk_divs(is_tft, req_pck, fck, &cur_dispc);
447                 match = 1;
448
449                 best_dss.fck = fck;
450                 best_dss.fck_div = fck_div;
451
452                 best_dispc = cur_dispc;
453
454                 goto found;
455         } else if (cpu_is_omap34xx()) {
456                 for (fck_div = (cpu_is_omap3630() ? 32 : 16);
457                                         fck_div > 0; --fck_div) {
458                         struct dispc_clock_info cur_dispc;
459
460                         if (cpu_is_omap3630())
461                                 fck = prate / fck_div;
462                         else
463                                 fck = prate / fck_div * 2;
464
465                         if (fck > max_dss_fck)
466                                 continue;
467
468                         if (min_fck_per_pck &&
469                                         fck < req_pck * min_fck_per_pck)
470                                 continue;
471
472                         match = 1;
473
474                         dispc_find_clk_divs(is_tft, req_pck, fck, &cur_dispc);
475
476                         if (abs(cur_dispc.pck - req_pck) <
477                                         abs(best_dispc.pck - req_pck)) {
478
479                                 best_dss.fck = fck;
480                                 best_dss.fck_div = fck_div;
481
482                                 best_dispc = cur_dispc;
483
484                                 if (cur_dispc.pck == req_pck)
485                                         goto found;
486                         }
487                 }
488         } else {
489                 BUG();
490         }
491
492 found:
493         if (!match) {
494                 if (min_fck_per_pck) {
495                         DSSERR("Could not find suitable clock settings.\n"
496                                         "Turning FCK/PCK constraint off and"
497                                         "trying again.\n");
498                         min_fck_per_pck = 0;
499                         goto retry;
500                 }
501
502                 DSSERR("Could not find suitable clock settings.\n");
503
504                 return -EINVAL;
505         }
506
507         if (dss_cinfo)
508                 *dss_cinfo = best_dss;
509         if (dispc_cinfo)
510                 *dispc_cinfo = best_dispc;
511
512         dss.cache_req_pck = req_pck;
513         dss.cache_prate = prate;
514         dss.cache_dss_cinfo = best_dss;
515         dss.cache_dispc_cinfo = best_dispc;
516
517         return 0;
518 }
519
520 static int _omap_dss_wait_reset(void)
521 {
522         int t = 0;
523
524         while (REG_GET(DSS_SYSSTATUS, 0, 0) == 0) {
525                 if (++t > 1000) {
526                         DSSERR("soft reset failed\n");
527                         return -ENODEV;
528                 }
529                 udelay(1);
530         }
531
532         return 0;
533 }
534
535 static int _omap_dss_reset(void)
536 {
537         /* Soft reset */
538         REG_FLD_MOD(DSS_SYSCONFIG, 1, 1, 1);
539         return _omap_dss_wait_reset();
540 }
541
542 void dss_set_venc_output(enum omap_dss_venc_type type)
543 {
544         int l = 0;
545
546         if (type == OMAP_DSS_VENC_TYPE_COMPOSITE)
547                 l = 0;
548         else if (type == OMAP_DSS_VENC_TYPE_SVIDEO)
549                 l = 1;
550         else
551                 BUG();
552
553         /* venc out selection. 0 = comp, 1 = svideo */
554         REG_FLD_MOD(DSS_CONTROL, l, 6, 6);
555 }
556
557 void dss_set_dac_pwrdn_bgz(bool enable)
558 {
559         REG_FLD_MOD(DSS_CONTROL, enable, 5, 5); /* DAC Power-Down Control */
560 }
561
562 static int dss_init(bool skip_init)
563 {
564         int r;
565         u32 rev;
566         struct resource *dss_mem;
567
568         dss_mem = platform_get_resource(dss.pdev, IORESOURCE_MEM, 0);
569         if (!dss_mem) {
570                 DSSERR("can't get IORESOURCE_MEM DSS\n");
571                 r = -EINVAL;
572                 goto fail0;
573         }
574         dss.base = ioremap(dss_mem->start, resource_size(dss_mem));
575         if (!dss.base) {
576                 DSSERR("can't ioremap DSS\n");
577                 r = -ENOMEM;
578                 goto fail0;
579         }
580
581         if (!skip_init) {
582                 /* disable LCD and DIGIT output. This seems to fix the synclost
583                  * problem that we get, if the bootloader starts the DSS and
584                  * the kernel resets it */
585                 omap_writel(omap_readl(0x48050440) & ~0x3, 0x48050440);
586
587                 /* We need to wait here a bit, otherwise we sometimes start to
588                  * get synclost errors, and after that only power cycle will
589                  * restore DSS functionality. I have no idea why this happens.
590                  * And we have to wait _before_ resetting the DSS, but after
591                  * enabling clocks.
592                  */
593                 msleep(50);
594
595                 _omap_dss_reset();
596         }
597
598         /* autoidle */
599         REG_FLD_MOD(DSS_SYSCONFIG, 1, 0, 0);
600
601         /* Select DPLL */
602         REG_FLD_MOD(DSS_CONTROL, 0, 0, 0);
603
604 #ifdef CONFIG_OMAP2_DSS_VENC
605         REG_FLD_MOD(DSS_CONTROL, 1, 4, 4);      /* venc dac demen */
606         REG_FLD_MOD(DSS_CONTROL, 1, 3, 3);      /* venc clock 4x enable */
607         REG_FLD_MOD(DSS_CONTROL, 0, 2, 2);      /* venc clock mode = normal */
608 #endif
609
610         if (cpu_is_omap34xx()) {
611                 dss.dpll4_m4_ck = clk_get(NULL, "dpll4_m4_ck");
612                 if (IS_ERR(dss.dpll4_m4_ck)) {
613                         DSSERR("Failed to get dpll4_m4_ck\n");
614                         r = PTR_ERR(dss.dpll4_m4_ck);
615                         goto fail1;
616                 }
617         }
618
619         dss.dsi_clk_source = DSS_CLK_SRC_FCK;
620         dss.dispc_clk_source = DSS_CLK_SRC_FCK;
621
622         dss_save_context();
623
624         rev = dss_read_reg(DSS_REVISION);
625         printk(KERN_INFO "OMAP DSS rev %d.%d\n",
626                         FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
627
628         return 0;
629
630 fail1:
631         iounmap(dss.base);
632 fail0:
633         return r;
634 }
635
636 static void dss_exit(void)
637 {
638         if (cpu_is_omap34xx())
639                 clk_put(dss.dpll4_m4_ck);
640
641         iounmap(dss.base);
642 }
643
644 /* CONTEXT */
645 static int dss_get_ctx_id(void)
646 {
647         struct omap_display_platform_data *pdata = dss.pdev->dev.platform_data;
648         int r;
649
650         if (!pdata->board_data->get_last_off_on_transaction_id)
651                 return 0;
652         r = pdata->board_data->get_last_off_on_transaction_id(&dss.pdev->dev);
653         if (r < 0) {
654                 dev_err(&dss.pdev->dev, "getting transaction ID failed, "
655                                 "will force context restore\n");
656                 r = -1;
657         }
658         return r;
659 }
660
661 int dss_need_ctx_restore(void)
662 {
663         int id = dss_get_ctx_id();
664
665         if (id < 0 || id != dss.ctx_id) {
666                 DSSDBG("ctx id %d -> id %d\n",
667                                 dss.ctx_id, id);
668                 dss.ctx_id = id;
669                 return 1;
670         } else {
671                 return 0;
672         }
673 }
674
675 static void save_all_ctx(void)
676 {
677         DSSDBG("save context\n");
678
679         dss_clk_enable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK);
680
681         dss_save_context();
682         dispc_save_context();
683 #ifdef CONFIG_OMAP2_DSS_DSI
684         dsi_save_context();
685 #endif
686
687         dss_clk_disable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK);
688 }
689
690 static void restore_all_ctx(void)
691 {
692         DSSDBG("restore context\n");
693
694         dss_clk_enable_all_no_ctx();
695
696         dss_restore_context();
697         dispc_restore_context();
698 #ifdef CONFIG_OMAP2_DSS_DSI
699         dsi_restore_context();
700 #endif
701
702         dss_clk_disable_all_no_ctx();
703 }
704
705 static int dss_get_clock(struct clk **clock, const char *clk_name)
706 {
707         struct clk *clk;
708
709         clk = clk_get(&dss.pdev->dev, clk_name);
710
711         if (IS_ERR(clk)) {
712                 DSSERR("can't get clock %s", clk_name);
713                 return PTR_ERR(clk);
714         }
715
716         *clock = clk;
717
718         DSSDBG("clk %s, rate %ld\n", clk_name, clk_get_rate(clk));
719
720         return 0;
721 }
722
723 static int dss_get_clocks(void)
724 {
725         int r;
726         struct omap_display_platform_data *pdata = dss.pdev->dev.platform_data;
727
728         dss.dss_ick = NULL;
729         dss.dss_fck = NULL;
730         dss.dss_sys_clk = NULL;
731         dss.dss_tv_fck = NULL;
732         dss.dss_video_fck = NULL;
733
734         r = dss_get_clock(&dss.dss_ick, "ick");
735         if (r)
736                 goto err;
737
738         r = dss_get_clock(&dss.dss_fck, "fck");
739         if (r)
740                 goto err;
741
742         if (!pdata->opt_clock_available) {
743                 r = -ENODEV;
744                 goto err;
745         }
746
747         if (pdata->opt_clock_available("sys_clk")) {
748                 r = dss_get_clock(&dss.dss_sys_clk, "sys_clk");
749                 if (r)
750                         goto err;
751         }
752
753         if (pdata->opt_clock_available("tv_clk")) {
754                 r = dss_get_clock(&dss.dss_tv_fck, "tv_clk");
755                 if (r)
756                         goto err;
757         }
758
759         if (pdata->opt_clock_available("video_clk")) {
760                 r = dss_get_clock(&dss.dss_video_fck, "video_clk");
761                 if (r)
762                         goto err;
763         }
764
765         return 0;
766
767 err:
768         if (dss.dss_ick)
769                 clk_put(dss.dss_ick);
770         if (dss.dss_fck)
771                 clk_put(dss.dss_fck);
772         if (dss.dss_sys_clk)
773                 clk_put(dss.dss_sys_clk);
774         if (dss.dss_tv_fck)
775                 clk_put(dss.dss_tv_fck);
776         if (dss.dss_video_fck)
777                 clk_put(dss.dss_video_fck);
778
779         return r;
780 }
781
782 static void dss_put_clocks(void)
783 {
784         if (dss.dss_video_fck)
785                 clk_put(dss.dss_video_fck);
786         if (dss.dss_tv_fck)
787                 clk_put(dss.dss_tv_fck);
788         if (dss.dss_sys_clk)
789                 clk_put(dss.dss_sys_clk);
790         clk_put(dss.dss_fck);
791         clk_put(dss.dss_ick);
792 }
793
794 unsigned long dss_clk_get_rate(enum dss_clock clk)
795 {
796         switch (clk) {
797         case DSS_CLK_ICK:
798                 return clk_get_rate(dss.dss_ick);
799         case DSS_CLK_FCK:
800                 return clk_get_rate(dss.dss_fck);
801         case DSS_CLK_SYSCK:
802                 return clk_get_rate(dss.dss_sys_clk);
803         case DSS_CLK_TVFCK:
804                 return clk_get_rate(dss.dss_tv_fck);
805         case DSS_CLK_VIDFCK:
806                 return clk_get_rate(dss.dss_video_fck);
807         }
808
809         BUG();
810         return 0;
811 }
812
813 static unsigned count_clk_bits(enum dss_clock clks)
814 {
815         unsigned num_clks = 0;
816
817         if (clks & DSS_CLK_ICK)
818                 ++num_clks;
819         if (clks & DSS_CLK_FCK)
820                 ++num_clks;
821         if (clks & DSS_CLK_SYSCK)
822                 ++num_clks;
823         if (clks & DSS_CLK_TVFCK)
824                 ++num_clks;
825         if (clks & DSS_CLK_VIDFCK)
826                 ++num_clks;
827
828         return num_clks;
829 }
830
831 static void dss_clk_enable_no_ctx(enum dss_clock clks)
832 {
833         unsigned num_clks = count_clk_bits(clks);
834
835         if (clks & DSS_CLK_ICK)
836                 clk_enable(dss.dss_ick);
837         if (clks & DSS_CLK_FCK)
838                 clk_enable(dss.dss_fck);
839         if ((clks & DSS_CLK_SYSCK) && dss.dss_sys_clk)
840                 clk_enable(dss.dss_sys_clk);
841         if ((clks & DSS_CLK_TVFCK) && dss.dss_tv_fck)
842                 clk_enable(dss.dss_tv_fck);
843         if ((clks & DSS_CLK_VIDFCK) && dss.dss_video_fck)
844                 clk_enable(dss.dss_video_fck);
845
846         dss.num_clks_enabled += num_clks;
847 }
848
849 void dss_clk_enable(enum dss_clock clks)
850 {
851         bool check_ctx = dss.num_clks_enabled == 0;
852
853         dss_clk_enable_no_ctx(clks);
854
855         if (check_ctx && cpu_is_omap34xx() && dss_need_ctx_restore())
856                 restore_all_ctx();
857 }
858
859 static void dss_clk_disable_no_ctx(enum dss_clock clks)
860 {
861         unsigned num_clks = count_clk_bits(clks);
862
863         if (clks & DSS_CLK_ICK)
864                 clk_disable(dss.dss_ick);
865         if (clks & DSS_CLK_FCK)
866                 clk_disable(dss.dss_fck);
867         if ((clks & DSS_CLK_SYSCK) && dss.dss_sys_clk)
868                 clk_disable(dss.dss_sys_clk);
869         if ((clks & DSS_CLK_TVFCK) && dss.dss_tv_fck)
870                 clk_disable(dss.dss_tv_fck);
871         if ((clks & DSS_CLK_VIDFCK) && dss.dss_video_fck)
872                 clk_disable(dss.dss_video_fck);
873
874         dss.num_clks_enabled -= num_clks;
875 }
876
877 void dss_clk_disable(enum dss_clock clks)
878 {
879         if (cpu_is_omap34xx()) {
880                 unsigned num_clks = count_clk_bits(clks);
881
882                 BUG_ON(dss.num_clks_enabled < num_clks);
883
884                 if (dss.num_clks_enabled == num_clks)
885                         save_all_ctx();
886         }
887
888         dss_clk_disable_no_ctx(clks);
889 }
890
891 static void dss_clk_enable_all_no_ctx(void)
892 {
893         enum dss_clock clks;
894
895         clks = DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_SYSCK | DSS_CLK_TVFCK;
896         if (cpu_is_omap34xx())
897                 clks |= DSS_CLK_VIDFCK;
898         dss_clk_enable_no_ctx(clks);
899 }
900
901 static void dss_clk_disable_all_no_ctx(void)
902 {
903         enum dss_clock clks;
904
905         clks = DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_SYSCK | DSS_CLK_TVFCK;
906         if (cpu_is_omap34xx())
907                 clks |= DSS_CLK_VIDFCK;
908         dss_clk_disable_no_ctx(clks);
909 }
910
911 #if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
912 /* CLOCKS */
913 static void core_dump_clocks(struct seq_file *s)
914 {
915         int i;
916         struct clk *clocks[5] = {
917                 dss.dss_ick,
918                 dss.dss_fck,
919                 dss.dss_sys_clk,
920                 dss.dss_tv_fck,
921                 dss.dss_video_fck
922         };
923
924         seq_printf(s, "- CORE -\n");
925
926         seq_printf(s, "internal clk count\t\t%u\n", dss.num_clks_enabled);
927
928         for (i = 0; i < 5; i++) {
929                 if (!clocks[i])
930                         continue;
931                 seq_printf(s, "%-15s\t%lu\t%d\n",
932                                 clocks[i]->name,
933                                 clk_get_rate(clocks[i]),
934                                 clocks[i]->usecount);
935         }
936 }
937 #endif /* defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) */
938
939 /* DEBUGFS */
940 #if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
941 void dss_debug_dump_clocks(struct seq_file *s)
942 {
943         core_dump_clocks(s);
944         dss_dump_clocks(s);
945         dispc_dump_clocks(s);
946 #ifdef CONFIG_OMAP2_DSS_DSI
947         dsi_dump_clocks(s);
948 #endif
949 }
950 #endif
951
952
953 /* DSS HW IP initialisation */
954 static int omap_dsshw_probe(struct platform_device *pdev)
955 {
956         int r;
957         int skip_init = 0;
958
959         dss.pdev = pdev;
960
961         r = dss_get_clocks();
962         if (r)
963                 goto err_clocks;
964
965         dss_clk_enable_all_no_ctx();
966
967         dss.ctx_id = dss_get_ctx_id();
968         DSSDBG("initial ctx id %u\n", dss.ctx_id);
969
970 #ifdef CONFIG_FB_OMAP_BOOTLOADER_INIT
971         /* DISPC_CONTROL */
972         if (omap_readl(0x48050440) & 1) /* LCD enabled? */
973                 skip_init = 1;
974 #endif
975
976         r = dss_init(skip_init);
977         if (r) {
978                 DSSERR("Failed to initialize DSS\n");
979                 goto err_dss;
980         }
981
982         dss_clk_disable_all_no_ctx();
983         return 0;
984
985 err_dss:
986         dss_clk_disable_all_no_ctx();
987         dss_put_clocks();
988 err_clocks:
989         return r;
990 }
991
992 static int omap_dsshw_remove(struct platform_device *pdev)
993 {
994
995         dss_exit();
996
997         /*
998          * As part of hwmod changes, DSS is not the only controller of dss
999          * clocks; hwmod framework itself will also enable clocks during hwmod
1000          * init for dss, and autoidle is set in h/w for DSS. Hence, there's no
1001          * need to disable clocks if their usecounts > 1.
1002          */
1003         WARN_ON(dss.num_clks_enabled > 0);
1004
1005         dss_put_clocks();
1006         return 0;
1007 }
1008
1009 static struct platform_driver omap_dsshw_driver = {
1010         .probe          = omap_dsshw_probe,
1011         .remove         = omap_dsshw_remove,
1012         .driver         = {
1013                 .name   = "omapdss_dss",
1014                 .owner  = THIS_MODULE,
1015         },
1016 };
1017
1018 int dss_init_platform_driver(void)
1019 {
1020         return platform_driver_register(&omap_dsshw_driver);
1021 }
1022
1023 void dss_uninit_platform_driver(void)
1024 {
1025         return platform_driver_unregister(&omap_dsshw_driver);
1026 }