Merge branch 'rmobile-latest' of git://git.kernel.org/pub/scm/linux/kernel/git/lethal...
[pandora-kernel.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 <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_CONTROL                     DSS_REG(0x0040)
49 #define DSS_SDI_CONTROL                 DSS_REG(0x0044)
50 #define DSS_PLL_CONTROL                 DSS_REG(0x0048)
51 #define DSS_SDI_STATUS                  DSS_REG(0x005C)
52
53 #define REG_GET(idx, start, end) \
54         FLD_GET(dss_read_reg(idx), start, end)
55
56 #define REG_FLD_MOD(idx, val, start, end) \
57         dss_write_reg(idx, FLD_MOD(dss_read_reg(idx), val, start, end))
58
59 static struct {
60         struct platform_device *pdev;
61         void __iomem    *base;
62         int             ctx_id;
63
64         struct clk      *dpll4_m4_ck;
65         struct clk      *dss_ick;
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
72         unsigned long   cache_req_pck;
73         unsigned long   cache_prate;
74         struct dss_clock_info cache_dss_cinfo;
75         struct dispc_clock_info cache_dispc_cinfo;
76
77         enum omap_dss_clk_source dsi_clk_source[MAX_NUM_DSI];
78         enum omap_dss_clk_source dispc_clk_source;
79         enum omap_dss_clk_source lcd_clk_source[MAX_DSS_LCD_MANAGERS];
80
81         u32             ctx[DSS_SZ_REGS / sizeof(u32)];
82 } dss;
83
84 static const char * const dss_generic_clk_source_names[] = {
85         [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC]  = "DSI_PLL_HSDIV_DISPC",
86         [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI]    = "DSI_PLL_HSDIV_DSI",
87         [OMAP_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 omap_dss_clk_source clk_src)
233 {
234         return dss_generic_clk_source_names[clk_src];
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         const char *fclk_name, *fclk_real_name;
242         unsigned long fclk_rate;
243
244         dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
245
246         seq_printf(s, "- DSS -\n");
247
248         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);
250         fclk_rate = dss_clk_get_rate(DSS_CLK_FCK);
251
252         if (dss.dpll4_m4_ck) {
253                 dpll4_ck_rate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
254                 dpll4_m4_ck_rate = clk_get_rate(dss.dpll4_m4_ck);
255
256                 seq_printf(s, "dpll4_ck %lu\n", dpll4_ck_rate);
257
258                 if (cpu_is_omap3630() || cpu_is_omap44xx())
259                         seq_printf(s, "%s (%s) = %lu / %lu  = %lu\n",
260                                         fclk_name, fclk_real_name,
261                                         dpll4_ck_rate,
262                                         dpll4_ck_rate / dpll4_m4_ck_rate,
263                                         fclk_rate);
264                 else
265                         seq_printf(s, "%s (%s) = %lu / %lu * 2 = %lu\n",
266                                         fclk_name, fclk_real_name,
267                                         dpll4_ck_rate,
268                                         dpll4_ck_rate / dpll4_m4_ck_rate,
269                                         fclk_rate);
270         } else {
271                 seq_printf(s, "%s (%s) = %lu\n",
272                                 fclk_name, fclk_real_name,
273                                 fclk_rate);
274         }
275
276         dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
277 }
278
279 void dss_dump_regs(struct seq_file *s)
280 {
281 #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dss_read_reg(r))
282
283         dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
284
285         DUMPREG(DSS_REVISION);
286         DUMPREG(DSS_SYSCONFIG);
287         DUMPREG(DSS_SYSSTATUS);
288         DUMPREG(DSS_CONTROL);
289
290         if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) &
291                         OMAP_DISPLAY_TYPE_SDI) {
292                 DUMPREG(DSS_SDI_CONTROL);
293                 DUMPREG(DSS_PLL_CONTROL);
294                 DUMPREG(DSS_SDI_STATUS);
295         }
296
297         dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
298 #undef DUMPREG
299 }
300
301 void dss_select_dispc_clk_source(enum omap_dss_clk_source clk_src)
302 {
303         struct platform_device *dsidev;
304         int b;
305         u8 start, end;
306
307         switch (clk_src) {
308         case OMAP_DSS_CLK_SRC_FCK:
309                 b = 0;
310                 break;
311         case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
312                 b = 1;
313                 dsidev = dsi_get_dsidev_from_id(0);
314                 dsi_wait_pll_hsdiv_dispc_active(dsidev);
315                 break;
316         case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC:
317                 b = 2;
318                 dsidev = dsi_get_dsidev_from_id(1);
319                 dsi_wait_pll_hsdiv_dispc_active(dsidev);
320                 break;
321         default:
322                 BUG();
323         }
324
325         dss_feat_get_reg_field(FEAT_REG_DISPC_CLK_SWITCH, &start, &end);
326
327         REG_FLD_MOD(DSS_CONTROL, b, start, end);        /* DISPC_CLK_SWITCH */
328
329         dss.dispc_clk_source = clk_src;
330 }
331
332 void dss_select_dsi_clk_source(int dsi_module,
333                 enum omap_dss_clk_source clk_src)
334 {
335         struct platform_device *dsidev;
336         int b;
337
338         switch (clk_src) {
339         case OMAP_DSS_CLK_SRC_FCK:
340                 b = 0;
341                 break;
342         case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI:
343                 BUG_ON(dsi_module != 0);
344                 b = 1;
345                 dsidev = dsi_get_dsidev_from_id(0);
346                 dsi_wait_pll_hsdiv_dsi_active(dsidev);
347                 break;
348         case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI:
349                 BUG_ON(dsi_module != 1);
350                 b = 1;
351                 dsidev = dsi_get_dsidev_from_id(1);
352                 dsi_wait_pll_hsdiv_dsi_active(dsidev);
353                 break;
354         default:
355                 BUG();
356         }
357
358         REG_FLD_MOD(DSS_CONTROL, b, 1, 1);      /* DSI_CLK_SWITCH */
359
360         dss.dsi_clk_source[dsi_module] = clk_src;
361 }
362
363 void dss_select_lcd_clk_source(enum omap_channel channel,
364                 enum omap_dss_clk_source clk_src)
365 {
366         struct platform_device *dsidev;
367         int b, ix, pos;
368
369         if (!dss_has_feature(FEAT_LCD_CLK_SRC))
370                 return;
371
372         switch (clk_src) {
373         case OMAP_DSS_CLK_SRC_FCK:
374                 b = 0;
375                 break;
376         case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
377                 BUG_ON(channel != OMAP_DSS_CHANNEL_LCD);
378                 b = 1;
379                 dsidev = dsi_get_dsidev_from_id(0);
380                 dsi_wait_pll_hsdiv_dispc_active(dsidev);
381                 break;
382         case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC:
383                 BUG_ON(channel != OMAP_DSS_CHANNEL_LCD2);
384                 b = 1;
385                 dsidev = dsi_get_dsidev_from_id(1);
386                 dsi_wait_pll_hsdiv_dispc_active(dsidev);
387                 break;
388         default:
389                 BUG();
390         }
391
392         pos = channel == OMAP_DSS_CHANNEL_LCD ? 0 : 12;
393         REG_FLD_MOD(DSS_CONTROL, b, pos, pos);  /* LCDx_CLK_SWITCH */
394
395         ix = channel == OMAP_DSS_CHANNEL_LCD ? 0 : 1;
396         dss.lcd_clk_source[ix] = clk_src;
397 }
398
399 enum omap_dss_clk_source dss_get_dispc_clk_source(void)
400 {
401         return dss.dispc_clk_source;
402 }
403
404 enum omap_dss_clk_source dss_get_dsi_clk_source(int dsi_module)
405 {
406         return dss.dsi_clk_source[dsi_module];
407 }
408
409 enum omap_dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel)
410 {
411         if (dss_has_feature(FEAT_LCD_CLK_SRC)) {
412                 int ix = channel == OMAP_DSS_CHANNEL_LCD ? 0 : 1;
413                 return dss.lcd_clk_source[ix];
414         } else {
415                 /* LCD_CLK source is the same as DISPC_FCLK source for
416                  * OMAP2 and OMAP3 */
417                 return dss.dispc_clk_source;
418         }
419 }
420
421 /* calculate clock rates using dividers in cinfo */
422 int dss_calc_clock_rates(struct dss_clock_info *cinfo)
423 {
424         if (dss.dpll4_m4_ck) {
425                 unsigned long prate;
426                 u16 fck_div_max = 16;
427
428                 if (cpu_is_omap3630() || cpu_is_omap44xx())
429                         fck_div_max = 32;
430
431                 if (cinfo->fck_div > fck_div_max || cinfo->fck_div == 0)
432                         return -EINVAL;
433
434                 prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
435
436                 cinfo->fck = prate / cinfo->fck_div;
437         } else {
438                 if (cinfo->fck_div != 0)
439                         return -EINVAL;
440                 cinfo->fck = dss_clk_get_rate(DSS_CLK_FCK);
441         }
442
443         return 0;
444 }
445
446 int dss_set_clock_div(struct dss_clock_info *cinfo)
447 {
448         if (dss.dpll4_m4_ck) {
449                 unsigned long prate;
450                 int r;
451
452                 prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
453                 DSSDBG("dpll4_m4 = %ld\n", prate);
454
455                 r = clk_set_rate(dss.dpll4_m4_ck, prate / cinfo->fck_div);
456                 if (r)
457                         return r;
458         } else {
459                 if (cinfo->fck_div != 0)
460                         return -EINVAL;
461         }
462
463         DSSDBG("fck = %ld (%d)\n", cinfo->fck, cinfo->fck_div);
464
465         return 0;
466 }
467
468 int dss_get_clock_div(struct dss_clock_info *cinfo)
469 {
470         cinfo->fck = dss_clk_get_rate(DSS_CLK_FCK);
471
472         if (dss.dpll4_m4_ck) {
473                 unsigned long prate;
474
475                 prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
476
477                 if (cpu_is_omap3630() || cpu_is_omap44xx())
478                         cinfo->fck_div = prate / (cinfo->fck);
479                 else
480                         cinfo->fck_div = prate / (cinfo->fck / 2);
481         } else {
482                 cinfo->fck_div = 0;
483         }
484
485         return 0;
486 }
487
488 unsigned long dss_get_dpll4_rate(void)
489 {
490         if (dss.dpll4_m4_ck)
491                 return clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
492         else
493                 return 0;
494 }
495
496 int dss_calc_clock_div(bool is_tft, unsigned long req_pck,
497                 struct dss_clock_info *dss_cinfo,
498                 struct dispc_clock_info *dispc_cinfo)
499 {
500         unsigned long prate;
501         struct dss_clock_info best_dss;
502         struct dispc_clock_info best_dispc;
503
504         unsigned long fck, max_dss_fck;
505
506         u16 fck_div, fck_div_max = 16;
507
508         int match = 0;
509         int min_fck_per_pck;
510
511         prate = dss_get_dpll4_rate();
512
513         max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
514
515         fck = dss_clk_get_rate(DSS_CLK_FCK);
516         if (req_pck == dss.cache_req_pck &&
517                         ((cpu_is_omap34xx() && prate == dss.cache_prate) ||
518                          dss.cache_dss_cinfo.fck == fck)) {
519                 DSSDBG("dispc clock info found from cache.\n");
520                 *dss_cinfo = dss.cache_dss_cinfo;
521                 *dispc_cinfo = dss.cache_dispc_cinfo;
522                 return 0;
523         }
524
525         min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK;
526
527         if (min_fck_per_pck &&
528                 req_pck * min_fck_per_pck > max_dss_fck) {
529                 DSSERR("Requested pixel clock not possible with the current "
530                                 "OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning "
531                                 "the constraint off.\n");
532                 min_fck_per_pck = 0;
533         }
534
535 retry:
536         memset(&best_dss, 0, sizeof(best_dss));
537         memset(&best_dispc, 0, sizeof(best_dispc));
538
539         if (dss.dpll4_m4_ck == NULL) {
540                 struct dispc_clock_info cur_dispc;
541                 /* XXX can we change the clock on omap2? */
542                 fck = dss_clk_get_rate(DSS_CLK_FCK);
543                 fck_div = 1;
544
545                 dispc_find_clk_divs(is_tft, req_pck, fck, &cur_dispc);
546                 match = 1;
547
548                 best_dss.fck = fck;
549                 best_dss.fck_div = fck_div;
550
551                 best_dispc = cur_dispc;
552
553                 goto found;
554         } else {
555                 if (cpu_is_omap3630() || cpu_is_omap44xx())
556                         fck_div_max = 32;
557
558                 for (fck_div = fck_div_max; fck_div > 0; --fck_div) {
559                         struct dispc_clock_info cur_dispc;
560
561                         if (fck_div_max == 32)
562                                 fck = prate / fck_div;
563                         else
564                                 fck = prate / fck_div * 2;
565
566                         if (fck > max_dss_fck)
567                                 continue;
568
569                         if (min_fck_per_pck &&
570                                         fck < req_pck * min_fck_per_pck)
571                                 continue;
572
573                         match = 1;
574
575                         dispc_find_clk_divs(is_tft, req_pck, fck, &cur_dispc);
576
577                         if (abs(cur_dispc.pck - req_pck) <
578                                         abs(best_dispc.pck - req_pck)) {
579
580                                 best_dss.fck = fck;
581                                 best_dss.fck_div = fck_div;
582
583                                 best_dispc = cur_dispc;
584
585                                 if (cur_dispc.pck == req_pck)
586                                         goto found;
587                         }
588                 }
589         }
590
591 found:
592         if (!match) {
593                 if (min_fck_per_pck) {
594                         DSSERR("Could not find suitable clock settings.\n"
595                                         "Turning FCK/PCK constraint off and"
596                                         "trying again.\n");
597                         min_fck_per_pck = 0;
598                         goto retry;
599                 }
600
601                 DSSERR("Could not find suitable clock settings.\n");
602
603                 return -EINVAL;
604         }
605
606         if (dss_cinfo)
607                 *dss_cinfo = best_dss;
608         if (dispc_cinfo)
609                 *dispc_cinfo = best_dispc;
610
611         dss.cache_req_pck = req_pck;
612         dss.cache_prate = prate;
613         dss.cache_dss_cinfo = best_dss;
614         dss.cache_dispc_cinfo = best_dispc;
615
616         return 0;
617 }
618
619 static 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
634 static 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
641 void dss_set_venc_output(enum omap_dss_venc_type type)
642 {
643         int l = 0;
644
645         if (type == OMAP_DSS_VENC_TYPE_COMPOSITE)
646                 l = 0;
647         else if (type == OMAP_DSS_VENC_TYPE_SVIDEO)
648                 l = 1;
649         else
650                 BUG();
651
652         /* venc out selection. 0 = comp, 1 = svideo */
653         REG_FLD_MOD(DSS_CONTROL, l, 6, 6);
654 }
655
656 void dss_set_dac_pwrdn_bgz(bool enable)
657 {
658         REG_FLD_MOD(DSS_CONTROL, enable, 5, 5); /* DAC Power-Down Control */
659 }
660
661 void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select hdmi)
662 {
663         REG_FLD_MOD(DSS_CONTROL, hdmi, 15, 15); /* VENC_HDMI_SWITCH */
664 }
665
666 static int dss_init(void)
667 {
668         int r;
669         u32 rev;
670         struct resource *dss_mem;
671         struct clk *dpll4_m4_ck;
672
673         dss_mem = platform_get_resource(dss.pdev, IORESOURCE_MEM, 0);
674         if (!dss_mem) {
675                 DSSERR("can't get IORESOURCE_MEM DSS\n");
676                 r = -EINVAL;
677                 goto fail0;
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         }
685
686         /* disable LCD and DIGIT output. This seems to fix the synclost
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
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()) {
718                 dpll4_m4_ck = clk_get(NULL, "dpll4_m4_ck");
719                 if (IS_ERR(dpll4_m4_ck)) {
720                         DSSERR("Failed to get dpll4_m4_ck\n");
721                         r = PTR_ERR(dpll4_m4_ck);
722                         goto fail1;
723                 }
724         } else if (cpu_is_omap44xx()) {
725                 dpll4_m4_ck = clk_get(NULL, "dpll_per_m5x2_ck");
726                 if (IS_ERR(dpll4_m4_ck)) {
727                         DSSERR("Failed to get dpll4_m4_ck\n");
728                         r = PTR_ERR(dpll4_m4_ck);
729                         goto fail1;
730                 }
731         } else { /* omap24xx */
732                 dpll4_m4_ck = NULL;
733         }
734
735         dss.dpll4_m4_ck = dpll4_m4_ck;
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
749         return 0;
750
751 fail1:
752         iounmap(dss.base);
753 fail0:
754         return r;
755 }
756
757 static void dss_exit(void)
758 {
759         if (dss.dpll4_m4_ck)
760                 clk_put(dss.dpll4_m4_ck);
761
762         iounmap(dss.base);
763 }
764
765 /* CONTEXT */
766 static 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
782 int 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
796 static 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
811 static 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
826 static 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
844 static 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
888 err:
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;
901 }
902
903 static void dss_put_clocks(void)
904 {
905         if (dss.dss_video_fck)
906                 clk_put(dss.dss_video_fck);
907         if (dss.dss_tv_fck)
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
915 unsigned 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
934 static 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
952 static 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
970 void 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 }
987
988 static void dss_clk_disable_no_ctx(enum dss_clock clks)
989 {
990         unsigned num_clks = count_clk_bits(clks);
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 }
1005
1006 void dss_clk_disable(enum dss_clock clks)
1007 {
1008         if (cpu_is_omap34xx()) {
1009                 unsigned num_clks = count_clk_bits(clks);
1010
1011                 BUG_ON(dss.num_clks_enabled < num_clks);
1012
1013                 if (dss.num_clks_enabled == num_clks)
1014                         save_all_ctx();
1015         }
1016
1017         dss_clk_disable_no_ctx(clks);
1018 }
1019
1020 static void dss_clk_enable_all_no_ctx(void)
1021 {
1022         enum dss_clock clks;
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
1030 static void dss_clk_disable_all_no_ctx(void)
1031 {
1032         enum dss_clock clks;
1033
1034         clks = DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_SYSCK | DSS_CLK_TVFCK;
1035         if (cpu_is_omap34xx())
1036                 clks |= DSS_CLK_VIDFCK;
1037         dss_clk_disable_no_ctx(clks);
1038 }
1039
1040 #if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
1041 /* CLOCKS */
1042 static 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 }
1077 #endif /* defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) */
1078
1079 /* DEBUGFS */
1080 #if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
1081 void dss_debug_dump_clocks(struct seq_file *s)
1082 {
1083         core_dump_clocks(s);
1084         dss_dump_clocks(s);
1085         dispc_dump_clocks(s);
1086 #ifdef CONFIG_OMAP2_DSS_DSI
1087         dsi_dump_clocks(s);
1088 #endif
1089 }
1090 #endif
1091
1092
1093 /* DSS HW IP initialisation */
1094 static int omap_dsshw_probe(struct platform_device *pdev)
1095 {
1096         int r;
1097
1098         dss.pdev = pdev;
1099
1100         r = dss_get_clocks();
1101         if (r)
1102                 goto err_clocks;
1103
1104         dss_clk_enable_all_no_ctx();
1105
1106         dss.ctx_id = dss_get_ctx_id();
1107         DSSDBG("initial ctx id %u\n", dss.ctx_id);
1108
1109         r = dss_init();
1110         if (r) {
1111                 DSSERR("Failed to initialize DSS\n");
1112                 goto err_dss;
1113         }
1114
1115         r = dpi_init();
1116         if (r) {
1117                 DSSERR("Failed to initialize DPI\n");
1118                 goto err_dpi;
1119         }
1120
1121         r = sdi_init();
1122         if (r) {
1123                 DSSERR("Failed to initialize SDI\n");
1124                 goto err_sdi;
1125         }
1126
1127         dss_clk_disable_all_no_ctx();
1128         return 0;
1129 err_sdi:
1130         dpi_exit();
1131 err_dpi:
1132         dss_exit();
1133 err_dss:
1134         dss_clk_disable_all_no_ctx();
1135         dss_put_clocks();
1136 err_clocks:
1137         return r;
1138 }
1139
1140 static int omap_dsshw_remove(struct platform_device *pdev)
1141 {
1142
1143         dss_exit();
1144
1145         /*
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
1153         dss_put_clocks();
1154         return 0;
1155 }
1156
1157 static struct platform_driver omap_dsshw_driver = {
1158         .probe          = omap_dsshw_probe,
1159         .remove         = omap_dsshw_remove,
1160         .driver         = {
1161                 .name   = "omapdss_dss",
1162                 .owner  = THIS_MODULE,
1163         },
1164 };
1165
1166 int dss_init_platform_driver(void)
1167 {
1168         return platform_driver_register(&omap_dsshw_driver);
1169 }
1170
1171 void dss_uninit_platform_driver(void)
1172 {
1173         return platform_driver_unregister(&omap_dsshw_driver);
1174 }