]> Pileus Git - ~andy/linux/blob - drivers/video/omap2/dss/dss.c
OMAP: DSS2: improve clock debugfs output
[~andy/linux] / 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 <video/omapdss.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 omap_dss_clk_source dsi_clk_source;
79         enum omap_dss_clk_source dispc_clk_source;
80         enum omap_dss_clk_source lcd_clk_source[MAX_DSS_LCD_MANAGERS];
81
82         u32             ctx[DSS_SZ_REGS / sizeof(u32)];
83 } dss;
84
85 static const char * const dss_generic_clk_source_names[] = {
86         [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC]  = "DSI_PLL_HSDIV_DISPC",
87         [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI]    = "DSI_PLL_HSDIV_DSI",
88         [OMAP_DSS_CLK_SRC_FCK]                  = "DSS_FCK",
89 };
90
91 static void dss_clk_enable_all_no_ctx(void);
92 static void dss_clk_disable_all_no_ctx(void);
93 static void dss_clk_enable_no_ctx(enum dss_clock clks);
94 static void dss_clk_disable_no_ctx(enum dss_clock clks);
95
96 static int _omap_dss_wait_reset(void);
97
98 static inline void dss_write_reg(const struct dss_reg idx, u32 val)
99 {
100         __raw_writel(val, dss.base + idx.idx);
101 }
102
103 static inline u32 dss_read_reg(const struct dss_reg idx)
104 {
105         return __raw_readl(dss.base + idx.idx);
106 }
107
108 #define SR(reg) \
109         dss.ctx[(DSS_##reg).idx / sizeof(u32)] = dss_read_reg(DSS_##reg)
110 #define RR(reg) \
111         dss_write_reg(DSS_##reg, dss.ctx[(DSS_##reg).idx / sizeof(u32)])
112
113 void dss_save_context(void)
114 {
115         if (cpu_is_omap24xx())
116                 return;
117
118         SR(SYSCONFIG);
119         SR(CONTROL);
120
121         if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) &
122                         OMAP_DISPLAY_TYPE_SDI) {
123                 SR(SDI_CONTROL);
124                 SR(PLL_CONTROL);
125         }
126 }
127
128 void dss_restore_context(void)
129 {
130         if (_omap_dss_wait_reset())
131                 DSSERR("DSS not coming out of reset after sleep\n");
132
133         RR(SYSCONFIG);
134         RR(CONTROL);
135
136         if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) &
137                         OMAP_DISPLAY_TYPE_SDI) {
138                 RR(SDI_CONTROL);
139                 RR(PLL_CONTROL);
140         }
141 }
142
143 #undef SR
144 #undef RR
145
146 void dss_sdi_init(u8 datapairs)
147 {
148         u32 l;
149
150         BUG_ON(datapairs > 3 || datapairs < 1);
151
152         l = dss_read_reg(DSS_SDI_CONTROL);
153         l = FLD_MOD(l, 0xf, 19, 15);            /* SDI_PDIV */
154         l = FLD_MOD(l, datapairs-1, 3, 2);      /* SDI_PRSEL */
155         l = FLD_MOD(l, 2, 1, 0);                /* SDI_BWSEL */
156         dss_write_reg(DSS_SDI_CONTROL, l);
157
158         l = dss_read_reg(DSS_PLL_CONTROL);
159         l = FLD_MOD(l, 0x7, 25, 22);    /* SDI_PLL_FREQSEL */
160         l = FLD_MOD(l, 0xb, 16, 11);    /* SDI_PLL_REGN */
161         l = FLD_MOD(l, 0xb4, 10, 1);    /* SDI_PLL_REGM */
162         dss_write_reg(DSS_PLL_CONTROL, l);
163 }
164
165 int dss_sdi_enable(void)
166 {
167         unsigned long timeout;
168
169         dispc_pck_free_enable(1);
170
171         /* Reset SDI PLL */
172         REG_FLD_MOD(DSS_PLL_CONTROL, 1, 18, 18); /* SDI_PLL_SYSRESET */
173         udelay(1);      /* wait 2x PCLK */
174
175         /* Lock SDI PLL */
176         REG_FLD_MOD(DSS_PLL_CONTROL, 1, 28, 28); /* SDI_PLL_GOBIT */
177
178         /* Waiting for PLL lock request to complete */
179         timeout = jiffies + msecs_to_jiffies(500);
180         while (dss_read_reg(DSS_SDI_STATUS) & (1 << 6)) {
181                 if (time_after_eq(jiffies, timeout)) {
182                         DSSERR("PLL lock request timed out\n");
183                         goto err1;
184                 }
185         }
186
187         /* Clearing PLL_GO bit */
188         REG_FLD_MOD(DSS_PLL_CONTROL, 0, 28, 28);
189
190         /* Waiting for PLL to lock */
191         timeout = jiffies + msecs_to_jiffies(500);
192         while (!(dss_read_reg(DSS_SDI_STATUS) & (1 << 5))) {
193                 if (time_after_eq(jiffies, timeout)) {
194                         DSSERR("PLL lock timed out\n");
195                         goto err1;
196                 }
197         }
198
199         dispc_lcd_enable_signal(1);
200
201         /* Waiting for SDI reset to complete */
202         timeout = jiffies + msecs_to_jiffies(500);
203         while (!(dss_read_reg(DSS_SDI_STATUS) & (1 << 2))) {
204                 if (time_after_eq(jiffies, timeout)) {
205                         DSSERR("SDI reset timed out\n");
206                         goto err2;
207                 }
208         }
209
210         return 0;
211
212  err2:
213         dispc_lcd_enable_signal(0);
214  err1:
215         /* Reset SDI PLL */
216         REG_FLD_MOD(DSS_PLL_CONTROL, 0, 18, 18); /* SDI_PLL_SYSRESET */
217
218         dispc_pck_free_enable(0);
219
220         return -ETIMEDOUT;
221 }
222
223 void dss_sdi_disable(void)
224 {
225         dispc_lcd_enable_signal(0);
226
227         dispc_pck_free_enable(0);
228
229         /* Reset SDI PLL */
230         REG_FLD_MOD(DSS_PLL_CONTROL, 0, 18, 18); /* SDI_PLL_SYSRESET */
231 }
232
233 const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src)
234 {
235         return dss_generic_clk_source_names[clk_src];
236 }
237
238 void dss_dump_clocks(struct seq_file *s)
239 {
240         unsigned long dpll4_ck_rate;
241         unsigned long dpll4_m4_ck_rate;
242         const char *fclk_name, *fclk_real_name;
243         unsigned long fclk_rate;
244
245         dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
246
247         seq_printf(s, "- DSS -\n");
248
249         fclk_name = dss_get_generic_clk_source_name(OMAP_DSS_CLK_SRC_FCK);
250         fclk_real_name = dss_feat_get_clk_source_name(OMAP_DSS_CLK_SRC_FCK);
251         fclk_rate = dss_clk_get_rate(DSS_CLK_FCK);
252
253         if (dss.dpll4_m4_ck) {
254                 dpll4_ck_rate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
255                 dpll4_m4_ck_rate = clk_get_rate(dss.dpll4_m4_ck);
256
257                 seq_printf(s, "dpll4_ck %lu\n", dpll4_ck_rate);
258
259                 if (cpu_is_omap3630() || cpu_is_omap44xx())
260                         seq_printf(s, "%s (%s) = %lu / %lu  = %lu\n",
261                                         fclk_name, fclk_real_name,
262                                         dpll4_ck_rate,
263                                         dpll4_ck_rate / dpll4_m4_ck_rate,
264                                         fclk_rate);
265                 else
266                         seq_printf(s, "%s (%s) = %lu / %lu * 2 = %lu\n",
267                                         fclk_name, fclk_real_name,
268                                         dpll4_ck_rate,
269                                         dpll4_ck_rate / dpll4_m4_ck_rate,
270                                         fclk_rate);
271         } else {
272                 seq_printf(s, "%s (%s) = %lu\n",
273                                 fclk_name, fclk_real_name,
274                                 fclk_rate);
275         }
276
277         dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
278 }
279
280 void dss_dump_regs(struct seq_file *s)
281 {
282 #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dss_read_reg(r))
283
284         dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
285
286         DUMPREG(DSS_REVISION);
287         DUMPREG(DSS_SYSCONFIG);
288         DUMPREG(DSS_SYSSTATUS);
289         DUMPREG(DSS_IRQSTATUS);
290         DUMPREG(DSS_CONTROL);
291
292         if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) &
293                         OMAP_DISPLAY_TYPE_SDI) {
294                 DUMPREG(DSS_SDI_CONTROL);
295                 DUMPREG(DSS_PLL_CONTROL);
296                 DUMPREG(DSS_SDI_STATUS);
297         }
298
299         dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
300 #undef DUMPREG
301 }
302
303 void dss_select_dispc_clk_source(enum omap_dss_clk_source clk_src)
304 {
305         int b;
306         u8 start, end;
307
308         switch (clk_src) {
309         case OMAP_DSS_CLK_SRC_FCK:
310                 b = 0;
311                 break;
312         case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
313                 b = 1;
314                 dsi_wait_pll_hsdiv_dispc_active();
315                 break;
316         default:
317                 BUG();
318         }
319
320         dss_feat_get_reg_field(FEAT_REG_DISPC_CLK_SWITCH, &start, &end);
321
322         REG_FLD_MOD(DSS_CONTROL, b, start, end);        /* DISPC_CLK_SWITCH */
323
324         dss.dispc_clk_source = clk_src;
325 }
326
327 void dss_select_dsi_clk_source(enum omap_dss_clk_source clk_src)
328 {
329         int b;
330
331         switch (clk_src) {
332         case OMAP_DSS_CLK_SRC_FCK:
333                 b = 0;
334                 break;
335         case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI:
336                 b = 1;
337                 dsi_wait_pll_hsdiv_dsi_active();
338                 break;
339         default:
340                 BUG();
341         }
342
343         REG_FLD_MOD(DSS_CONTROL, b, 1, 1);      /* DSI_CLK_SWITCH */
344
345         dss.dsi_clk_source = clk_src;
346 }
347
348 void dss_select_lcd_clk_source(enum omap_channel channel,
349                 enum omap_dss_clk_source clk_src)
350 {
351         int b, ix, pos;
352
353         if (!dss_has_feature(FEAT_LCD_CLK_SRC))
354                 return;
355
356         switch (clk_src) {
357         case OMAP_DSS_CLK_SRC_FCK:
358                 b = 0;
359                 break;
360         case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
361                 BUG_ON(channel != OMAP_DSS_CHANNEL_LCD);
362                 b = 1;
363                 dsi_wait_pll_hsdiv_dispc_active();
364                 break;
365         default:
366                 BUG();
367         }
368
369         pos = channel == OMAP_DSS_CHANNEL_LCD ? 0 : 12;
370         REG_FLD_MOD(DSS_CONTROL, b, pos, pos);  /* LCDx_CLK_SWITCH */
371
372         ix = channel == OMAP_DSS_CHANNEL_LCD ? 0 : 1;
373         dss.lcd_clk_source[ix] = clk_src;
374 }
375
376 enum omap_dss_clk_source dss_get_dispc_clk_source(void)
377 {
378         return dss.dispc_clk_source;
379 }
380
381 enum omap_dss_clk_source dss_get_dsi_clk_source(void)
382 {
383         return dss.dsi_clk_source;
384 }
385
386 enum omap_dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel)
387 {
388         if (dss_has_feature(FEAT_LCD_CLK_SRC)) {
389                 int ix = channel == OMAP_DSS_CHANNEL_LCD ? 0 : 1;
390                 return dss.lcd_clk_source[ix];
391         } else {
392                 /* LCD_CLK source is the same as DISPC_FCLK source for
393                  * OMAP2 and OMAP3 */
394                 return dss.dispc_clk_source;
395         }
396 }
397
398 /* calculate clock rates using dividers in cinfo */
399 int dss_calc_clock_rates(struct dss_clock_info *cinfo)
400 {
401         if (dss.dpll4_m4_ck) {
402                 unsigned long prate;
403                 u16 fck_div_max = 16;
404
405                 if (cpu_is_omap3630() || cpu_is_omap44xx())
406                         fck_div_max = 32;
407
408                 if (cinfo->fck_div > fck_div_max || cinfo->fck_div == 0)
409                         return -EINVAL;
410
411                 prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
412
413                 cinfo->fck = prate / cinfo->fck_div;
414         } else {
415                 if (cinfo->fck_div != 0)
416                         return -EINVAL;
417                 cinfo->fck = dss_clk_get_rate(DSS_CLK_FCK);
418         }
419
420         return 0;
421 }
422
423 int dss_set_clock_div(struct dss_clock_info *cinfo)
424 {
425         if (dss.dpll4_m4_ck) {
426                 unsigned long prate;
427                 int r;
428
429                 prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
430                 DSSDBG("dpll4_m4 = %ld\n", prate);
431
432                 r = clk_set_rate(dss.dpll4_m4_ck, prate / cinfo->fck_div);
433                 if (r)
434                         return r;
435         } else {
436                 if (cinfo->fck_div != 0)
437                         return -EINVAL;
438         }
439
440         DSSDBG("fck = %ld (%d)\n", cinfo->fck, cinfo->fck_div);
441
442         return 0;
443 }
444
445 int dss_get_clock_div(struct dss_clock_info *cinfo)
446 {
447         cinfo->fck = dss_clk_get_rate(DSS_CLK_FCK);
448
449         if (dss.dpll4_m4_ck) {
450                 unsigned long prate;
451
452                 prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
453
454                 if (cpu_is_omap3630() || cpu_is_omap44xx())
455                         cinfo->fck_div = prate / (cinfo->fck);
456                 else
457                         cinfo->fck_div = prate / (cinfo->fck / 2);
458         } else {
459                 cinfo->fck_div = 0;
460         }
461
462         return 0;
463 }
464
465 unsigned long dss_get_dpll4_rate(void)
466 {
467         if (dss.dpll4_m4_ck)
468                 return clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
469         else
470                 return 0;
471 }
472
473 int dss_calc_clock_div(bool is_tft, unsigned long req_pck,
474                 struct dss_clock_info *dss_cinfo,
475                 struct dispc_clock_info *dispc_cinfo)
476 {
477         unsigned long prate;
478         struct dss_clock_info best_dss;
479         struct dispc_clock_info best_dispc;
480
481         unsigned long fck, max_dss_fck;
482
483         u16 fck_div, fck_div_max = 16;
484
485         int match = 0;
486         int min_fck_per_pck;
487
488         prate = dss_get_dpll4_rate();
489
490         max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
491
492         fck = dss_clk_get_rate(DSS_CLK_FCK);
493         if (req_pck == dss.cache_req_pck &&
494                         ((cpu_is_omap34xx() && prate == dss.cache_prate) ||
495                          dss.cache_dss_cinfo.fck == fck)) {
496                 DSSDBG("dispc clock info found from cache.\n");
497                 *dss_cinfo = dss.cache_dss_cinfo;
498                 *dispc_cinfo = dss.cache_dispc_cinfo;
499                 return 0;
500         }
501
502         min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK;
503
504         if (min_fck_per_pck &&
505                 req_pck * min_fck_per_pck > max_dss_fck) {
506                 DSSERR("Requested pixel clock not possible with the current "
507                                 "OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning "
508                                 "the constraint off.\n");
509                 min_fck_per_pck = 0;
510         }
511
512 retry:
513         memset(&best_dss, 0, sizeof(best_dss));
514         memset(&best_dispc, 0, sizeof(best_dispc));
515
516         if (dss.dpll4_m4_ck == NULL) {
517                 struct dispc_clock_info cur_dispc;
518                 /* XXX can we change the clock on omap2? */
519                 fck = dss_clk_get_rate(DSS_CLK_FCK);
520                 fck_div = 1;
521
522                 dispc_find_clk_divs(is_tft, req_pck, fck, &cur_dispc);
523                 match = 1;
524
525                 best_dss.fck = fck;
526                 best_dss.fck_div = fck_div;
527
528                 best_dispc = cur_dispc;
529
530                 goto found;
531         } else {
532                 if (cpu_is_omap3630() || cpu_is_omap44xx())
533                         fck_div_max = 32;
534
535                 for (fck_div = fck_div_max; fck_div > 0; --fck_div) {
536                         struct dispc_clock_info cur_dispc;
537
538                         if (fck_div_max == 32)
539                                 fck = prate / fck_div;
540                         else
541                                 fck = prate / fck_div * 2;
542
543                         if (fck > max_dss_fck)
544                                 continue;
545
546                         if (min_fck_per_pck &&
547                                         fck < req_pck * min_fck_per_pck)
548                                 continue;
549
550                         match = 1;
551
552                         dispc_find_clk_divs(is_tft, req_pck, fck, &cur_dispc);
553
554                         if (abs(cur_dispc.pck - req_pck) <
555                                         abs(best_dispc.pck - req_pck)) {
556
557                                 best_dss.fck = fck;
558                                 best_dss.fck_div = fck_div;
559
560                                 best_dispc = cur_dispc;
561
562                                 if (cur_dispc.pck == req_pck)
563                                         goto found;
564                         }
565                 }
566         }
567
568 found:
569         if (!match) {
570                 if (min_fck_per_pck) {
571                         DSSERR("Could not find suitable clock settings.\n"
572                                         "Turning FCK/PCK constraint off and"
573                                         "trying again.\n");
574                         min_fck_per_pck = 0;
575                         goto retry;
576                 }
577
578                 DSSERR("Could not find suitable clock settings.\n");
579
580                 return -EINVAL;
581         }
582
583         if (dss_cinfo)
584                 *dss_cinfo = best_dss;
585         if (dispc_cinfo)
586                 *dispc_cinfo = best_dispc;
587
588         dss.cache_req_pck = req_pck;
589         dss.cache_prate = prate;
590         dss.cache_dss_cinfo = best_dss;
591         dss.cache_dispc_cinfo = best_dispc;
592
593         return 0;
594 }
595
596 static int _omap_dss_wait_reset(void)
597 {
598         int t = 0;
599
600         while (REG_GET(DSS_SYSSTATUS, 0, 0) == 0) {
601                 if (++t > 1000) {
602                         DSSERR("soft reset failed\n");
603                         return -ENODEV;
604                 }
605                 udelay(1);
606         }
607
608         return 0;
609 }
610
611 static int _omap_dss_reset(void)
612 {
613         /* Soft reset */
614         REG_FLD_MOD(DSS_SYSCONFIG, 1, 1, 1);
615         return _omap_dss_wait_reset();
616 }
617
618 void dss_set_venc_output(enum omap_dss_venc_type type)
619 {
620         int l = 0;
621
622         if (type == OMAP_DSS_VENC_TYPE_COMPOSITE)
623                 l = 0;
624         else if (type == OMAP_DSS_VENC_TYPE_SVIDEO)
625                 l = 1;
626         else
627                 BUG();
628
629         /* venc out selection. 0 = comp, 1 = svideo */
630         REG_FLD_MOD(DSS_CONTROL, l, 6, 6);
631 }
632
633 void dss_set_dac_pwrdn_bgz(bool enable)
634 {
635         REG_FLD_MOD(DSS_CONTROL, enable, 5, 5); /* DAC Power-Down Control */
636 }
637
638 void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select hdmi)
639 {
640         REG_FLD_MOD(DSS_CONTROL, hdmi, 15, 15); /* VENC_HDMI_SWITCH */
641 }
642
643 static int dss_init(void)
644 {
645         int r;
646         u32 rev;
647         struct resource *dss_mem;
648         struct clk *dpll4_m4_ck;
649
650         dss_mem = platform_get_resource(dss.pdev, IORESOURCE_MEM, 0);
651         if (!dss_mem) {
652                 DSSERR("can't get IORESOURCE_MEM DSS\n");
653                 r = -EINVAL;
654                 goto fail0;
655         }
656         dss.base = ioremap(dss_mem->start, resource_size(dss_mem));
657         if (!dss.base) {
658                 DSSERR("can't ioremap DSS\n");
659                 r = -ENOMEM;
660                 goto fail0;
661         }
662
663         /* disable LCD and DIGIT output. This seems to fix the synclost
664          * problem that we get, if the bootloader starts the DSS and
665          * the kernel resets it */
666         omap_writel(omap_readl(0x48050440) & ~0x3, 0x48050440);
667
668 #ifdef CONFIG_OMAP2_DSS_SLEEP_BEFORE_RESET
669         /* We need to wait here a bit, otherwise we sometimes start to
670          * get synclost errors, and after that only power cycle will
671          * restore DSS functionality. I have no idea why this happens.
672          * And we have to wait _before_ resetting the DSS, but after
673          * enabling clocks.
674          *
675          * This bug was at least present on OMAP3430. It's unknown
676          * if it happens on OMAP2 or OMAP3630.
677          */
678         msleep(50);
679 #endif
680
681         _omap_dss_reset();
682
683         /* autoidle */
684         REG_FLD_MOD(DSS_SYSCONFIG, 1, 0, 0);
685
686         /* Select DPLL */
687         REG_FLD_MOD(DSS_CONTROL, 0, 0, 0);
688
689 #ifdef CONFIG_OMAP2_DSS_VENC
690         REG_FLD_MOD(DSS_CONTROL, 1, 4, 4);      /* venc dac demen */
691         REG_FLD_MOD(DSS_CONTROL, 1, 3, 3);      /* venc clock 4x enable */
692         REG_FLD_MOD(DSS_CONTROL, 0, 2, 2);      /* venc clock mode = normal */
693 #endif
694         if (cpu_is_omap34xx()) {
695                 dpll4_m4_ck = clk_get(NULL, "dpll4_m4_ck");
696                 if (IS_ERR(dpll4_m4_ck)) {
697                         DSSERR("Failed to get dpll4_m4_ck\n");
698                         r = PTR_ERR(dpll4_m4_ck);
699                         goto fail1;
700                 }
701         } else if (cpu_is_omap44xx()) {
702                 dpll4_m4_ck = clk_get(NULL, "dpll_per_m5x2_ck");
703                 if (IS_ERR(dpll4_m4_ck)) {
704                         DSSERR("Failed to get dpll4_m4_ck\n");
705                         r = PTR_ERR(dpll4_m4_ck);
706                         goto fail1;
707                 }
708         } else { /* omap24xx */
709                 dpll4_m4_ck = NULL;
710         }
711
712         dss.dpll4_m4_ck = dpll4_m4_ck;
713
714         dss.dsi_clk_source = OMAP_DSS_CLK_SRC_FCK;
715         dss.dispc_clk_source = OMAP_DSS_CLK_SRC_FCK;
716         dss.lcd_clk_source[0] = OMAP_DSS_CLK_SRC_FCK;
717         dss.lcd_clk_source[1] = OMAP_DSS_CLK_SRC_FCK;
718
719         dss_save_context();
720
721         rev = dss_read_reg(DSS_REVISION);
722         printk(KERN_INFO "OMAP DSS rev %d.%d\n",
723                         FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
724
725         return 0;
726
727 fail1:
728         iounmap(dss.base);
729 fail0:
730         return r;
731 }
732
733 static void dss_exit(void)
734 {
735         if (dss.dpll4_m4_ck)
736                 clk_put(dss.dpll4_m4_ck);
737
738         iounmap(dss.base);
739 }
740
741 /* CONTEXT */
742 static int dss_get_ctx_id(void)
743 {
744         struct omap_display_platform_data *pdata = dss.pdev->dev.platform_data;
745         int r;
746
747         if (!pdata->board_data->get_last_off_on_transaction_id)
748                 return 0;
749         r = pdata->board_data->get_last_off_on_transaction_id(&dss.pdev->dev);
750         if (r < 0) {
751                 dev_err(&dss.pdev->dev, "getting transaction ID failed, "
752                                 "will force context restore\n");
753                 r = -1;
754         }
755         return r;
756 }
757
758 int dss_need_ctx_restore(void)
759 {
760         int id = dss_get_ctx_id();
761
762         if (id < 0 || id != dss.ctx_id) {
763                 DSSDBG("ctx id %d -> id %d\n",
764                                 dss.ctx_id, id);
765                 dss.ctx_id = id;
766                 return 1;
767         } else {
768                 return 0;
769         }
770 }
771
772 static void save_all_ctx(void)
773 {
774         DSSDBG("save context\n");
775
776         dss_clk_enable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK);
777
778         dss_save_context();
779         dispc_save_context();
780 #ifdef CONFIG_OMAP2_DSS_DSI
781         dsi_save_context();
782 #endif
783
784         dss_clk_disable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK);
785 }
786
787 static void restore_all_ctx(void)
788 {
789         DSSDBG("restore context\n");
790
791         dss_clk_enable_all_no_ctx();
792
793         dss_restore_context();
794         dispc_restore_context();
795 #ifdef CONFIG_OMAP2_DSS_DSI
796         dsi_restore_context();
797 #endif
798
799         dss_clk_disable_all_no_ctx();
800 }
801
802 static int dss_get_clock(struct clk **clock, const char *clk_name)
803 {
804         struct clk *clk;
805
806         clk = clk_get(&dss.pdev->dev, clk_name);
807
808         if (IS_ERR(clk)) {
809                 DSSERR("can't get clock %s", clk_name);
810                 return PTR_ERR(clk);
811         }
812
813         *clock = clk;
814
815         DSSDBG("clk %s, rate %ld\n", clk_name, clk_get_rate(clk));
816
817         return 0;
818 }
819
820 static int dss_get_clocks(void)
821 {
822         int r;
823         struct omap_display_platform_data *pdata = dss.pdev->dev.platform_data;
824
825         dss.dss_ick = NULL;
826         dss.dss_fck = NULL;
827         dss.dss_sys_clk = NULL;
828         dss.dss_tv_fck = NULL;
829         dss.dss_video_fck = NULL;
830
831         r = dss_get_clock(&dss.dss_ick, "ick");
832         if (r)
833                 goto err;
834
835         r = dss_get_clock(&dss.dss_fck, "fck");
836         if (r)
837                 goto err;
838
839         if (!pdata->opt_clock_available) {
840                 r = -ENODEV;
841                 goto err;
842         }
843
844         if (pdata->opt_clock_available("sys_clk")) {
845                 r = dss_get_clock(&dss.dss_sys_clk, "sys_clk");
846                 if (r)
847                         goto err;
848         }
849
850         if (pdata->opt_clock_available("tv_clk")) {
851                 r = dss_get_clock(&dss.dss_tv_fck, "tv_clk");
852                 if (r)
853                         goto err;
854         }
855
856         if (pdata->opt_clock_available("video_clk")) {
857                 r = dss_get_clock(&dss.dss_video_fck, "video_clk");
858                 if (r)
859                         goto err;
860         }
861
862         return 0;
863
864 err:
865         if (dss.dss_ick)
866                 clk_put(dss.dss_ick);
867         if (dss.dss_fck)
868                 clk_put(dss.dss_fck);
869         if (dss.dss_sys_clk)
870                 clk_put(dss.dss_sys_clk);
871         if (dss.dss_tv_fck)
872                 clk_put(dss.dss_tv_fck);
873         if (dss.dss_video_fck)
874                 clk_put(dss.dss_video_fck);
875
876         return r;
877 }
878
879 static void dss_put_clocks(void)
880 {
881         if (dss.dss_video_fck)
882                 clk_put(dss.dss_video_fck);
883         if (dss.dss_tv_fck)
884                 clk_put(dss.dss_tv_fck);
885         if (dss.dss_sys_clk)
886                 clk_put(dss.dss_sys_clk);
887         clk_put(dss.dss_fck);
888         clk_put(dss.dss_ick);
889 }
890
891 unsigned long dss_clk_get_rate(enum dss_clock clk)
892 {
893         switch (clk) {
894         case DSS_CLK_ICK:
895                 return clk_get_rate(dss.dss_ick);
896         case DSS_CLK_FCK:
897                 return clk_get_rate(dss.dss_fck);
898         case DSS_CLK_SYSCK:
899                 return clk_get_rate(dss.dss_sys_clk);
900         case DSS_CLK_TVFCK:
901                 return clk_get_rate(dss.dss_tv_fck);
902         case DSS_CLK_VIDFCK:
903                 return clk_get_rate(dss.dss_video_fck);
904         }
905
906         BUG();
907         return 0;
908 }
909
910 static unsigned count_clk_bits(enum dss_clock clks)
911 {
912         unsigned num_clks = 0;
913
914         if (clks & DSS_CLK_ICK)
915                 ++num_clks;
916         if (clks & DSS_CLK_FCK)
917                 ++num_clks;
918         if (clks & DSS_CLK_SYSCK)
919                 ++num_clks;
920         if (clks & DSS_CLK_TVFCK)
921                 ++num_clks;
922         if (clks & DSS_CLK_VIDFCK)
923                 ++num_clks;
924
925         return num_clks;
926 }
927
928 static void dss_clk_enable_no_ctx(enum dss_clock clks)
929 {
930         unsigned num_clks = count_clk_bits(clks);
931
932         if (clks & DSS_CLK_ICK)
933                 clk_enable(dss.dss_ick);
934         if (clks & DSS_CLK_FCK)
935                 clk_enable(dss.dss_fck);
936         if ((clks & DSS_CLK_SYSCK) && dss.dss_sys_clk)
937                 clk_enable(dss.dss_sys_clk);
938         if ((clks & DSS_CLK_TVFCK) && dss.dss_tv_fck)
939                 clk_enable(dss.dss_tv_fck);
940         if ((clks & DSS_CLK_VIDFCK) && dss.dss_video_fck)
941                 clk_enable(dss.dss_video_fck);
942
943         dss.num_clks_enabled += num_clks;
944 }
945
946 void dss_clk_enable(enum dss_clock clks)
947 {
948         bool check_ctx = dss.num_clks_enabled == 0;
949
950         dss_clk_enable_no_ctx(clks);
951
952         /*
953          * HACK: On omap4 the registers may not be accessible right after
954          * enabling the clocks. At some point this will be handled by
955          * pm_runtime, but for the time begin this should make things work.
956          */
957         if (cpu_is_omap44xx() && check_ctx)
958                 udelay(10);
959
960         if (check_ctx && cpu_is_omap34xx() && dss_need_ctx_restore())
961                 restore_all_ctx();
962 }
963
964 static void dss_clk_disable_no_ctx(enum dss_clock clks)
965 {
966         unsigned num_clks = count_clk_bits(clks);
967
968         if (clks & DSS_CLK_ICK)
969                 clk_disable(dss.dss_ick);
970         if (clks & DSS_CLK_FCK)
971                 clk_disable(dss.dss_fck);
972         if ((clks & DSS_CLK_SYSCK) && dss.dss_sys_clk)
973                 clk_disable(dss.dss_sys_clk);
974         if ((clks & DSS_CLK_TVFCK) && dss.dss_tv_fck)
975                 clk_disable(dss.dss_tv_fck);
976         if ((clks & DSS_CLK_VIDFCK) && dss.dss_video_fck)
977                 clk_disable(dss.dss_video_fck);
978
979         dss.num_clks_enabled -= num_clks;
980 }
981
982 void dss_clk_disable(enum dss_clock clks)
983 {
984         if (cpu_is_omap34xx()) {
985                 unsigned num_clks = count_clk_bits(clks);
986
987                 BUG_ON(dss.num_clks_enabled < num_clks);
988
989                 if (dss.num_clks_enabled == num_clks)
990                         save_all_ctx();
991         }
992
993         dss_clk_disable_no_ctx(clks);
994 }
995
996 static void dss_clk_enable_all_no_ctx(void)
997 {
998         enum dss_clock clks;
999
1000         clks = DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_SYSCK | DSS_CLK_TVFCK;
1001         if (cpu_is_omap34xx())
1002                 clks |= DSS_CLK_VIDFCK;
1003         dss_clk_enable_no_ctx(clks);
1004 }
1005
1006 static void dss_clk_disable_all_no_ctx(void)
1007 {
1008         enum dss_clock clks;
1009
1010         clks = DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_SYSCK | DSS_CLK_TVFCK;
1011         if (cpu_is_omap34xx())
1012                 clks |= DSS_CLK_VIDFCK;
1013         dss_clk_disable_no_ctx(clks);
1014 }
1015
1016 #if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
1017 /* CLOCKS */
1018 static void core_dump_clocks(struct seq_file *s)
1019 {
1020         int i;
1021         struct clk *clocks[5] = {
1022                 dss.dss_ick,
1023                 dss.dss_fck,
1024                 dss.dss_sys_clk,
1025                 dss.dss_tv_fck,
1026                 dss.dss_video_fck
1027         };
1028
1029         const char *names[5] = {
1030                 "ick",
1031                 "fck",
1032                 "sys_clk",
1033                 "tv_fck",
1034                 "video_fck"
1035         };
1036
1037         seq_printf(s, "- CORE -\n");
1038
1039         seq_printf(s, "internal clk count\t\t%u\n", dss.num_clks_enabled);
1040
1041         for (i = 0; i < 5; i++) {
1042                 if (!clocks[i])
1043                         continue;
1044                 seq_printf(s, "%s (%s)%*s\t%lu\t%d\n",
1045                                 names[i],
1046                                 clocks[i]->name,
1047                                 24 - strlen(names[i]) - strlen(clocks[i]->name),
1048                                 "",
1049                                 clk_get_rate(clocks[i]),
1050                                 clocks[i]->usecount);
1051         }
1052 }
1053 #endif /* defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) */
1054
1055 /* DEBUGFS */
1056 #if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
1057 void dss_debug_dump_clocks(struct seq_file *s)
1058 {
1059         core_dump_clocks(s);
1060         dss_dump_clocks(s);
1061         dispc_dump_clocks(s);
1062 #ifdef CONFIG_OMAP2_DSS_DSI
1063         dsi_dump_clocks(s);
1064 #endif
1065 }
1066 #endif
1067
1068
1069 /* DSS HW IP initialisation */
1070 static int omap_dsshw_probe(struct platform_device *pdev)
1071 {
1072         int r;
1073
1074         dss.pdev = pdev;
1075
1076         r = dss_get_clocks();
1077         if (r)
1078                 goto err_clocks;
1079
1080         dss_clk_enable_all_no_ctx();
1081
1082         dss.ctx_id = dss_get_ctx_id();
1083         DSSDBG("initial ctx id %u\n", dss.ctx_id);
1084
1085         r = dss_init();
1086         if (r) {
1087                 DSSERR("Failed to initialize DSS\n");
1088                 goto err_dss;
1089         }
1090
1091         r = dpi_init();
1092         if (r) {
1093                 DSSERR("Failed to initialize DPI\n");
1094                 goto err_dpi;
1095         }
1096
1097         r = sdi_init();
1098         if (r) {
1099                 DSSERR("Failed to initialize SDI\n");
1100                 goto err_sdi;
1101         }
1102
1103         dss_clk_disable_all_no_ctx();
1104         return 0;
1105 err_sdi:
1106         dpi_exit();
1107 err_dpi:
1108         dss_exit();
1109 err_dss:
1110         dss_clk_disable_all_no_ctx();
1111         dss_put_clocks();
1112 err_clocks:
1113         return r;
1114 }
1115
1116 static int omap_dsshw_remove(struct platform_device *pdev)
1117 {
1118
1119         dss_exit();
1120
1121         /*
1122          * As part of hwmod changes, DSS is not the only controller of dss
1123          * clocks; hwmod framework itself will also enable clocks during hwmod
1124          * init for dss, and autoidle is set in h/w for DSS. Hence, there's no
1125          * need to disable clocks if their usecounts > 1.
1126          */
1127         WARN_ON(dss.num_clks_enabled > 0);
1128
1129         dss_put_clocks();
1130         return 0;
1131 }
1132
1133 static struct platform_driver omap_dsshw_driver = {
1134         .probe          = omap_dsshw_probe,
1135         .remove         = omap_dsshw_remove,
1136         .driver         = {
1137                 .name   = "omapdss_dss",
1138                 .owner  = THIS_MODULE,
1139         },
1140 };
1141
1142 int dss_init_platform_driver(void)
1143 {
1144         return platform_driver_register(&omap_dsshw_driver);
1145 }
1146
1147 void dss_uninit_platform_driver(void)
1148 {
1149         return platform_driver_unregister(&omap_dsshw_driver);
1150 }