]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - drivers/video/omap/dispc.c
ARM: OMAP: Switch to use clk_enable/disable instead of clk_use/unuse
[linux-2.6-omap-h63xx.git] / drivers / video / omap / dispc.c
1 /*
2  * File: drivers/video/omap/omap2/dispc.c
3  *
4  * OMAP2 display controller support
5  *
6  * Copyright (C) 2005 Nokia Corporation
7  * Author: Imre Deak <imre.deak@nokia.com>
8  *
9  * This program is free software; you can redistribute it and/or modify it
10  * under the terms of the GNU General Public License as published by the
11  * Free Software Foundation; either version 2 of the License, or (at your
12  * option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful, but
15  * WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License along
20  * with this program; if not, write to the Free Software Foundation, Inc.,
21  * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  */
23
24 #include <linux/kernel.h>
25 #include <linux/dma-mapping.h>
26
27 #include <asm/io.h>
28
29 #include <asm/arch/omapfb.h>
30
31 #include <asm/hardware/clock.h>
32
33 #include "dispc.h"
34
35 /* #define OMAPFB_DBG   2 */
36
37 #include "debug.h"
38
39 #define MODULE_NAME                     "omapfb-dispc"
40
41 #define DISPC_BASE                      0x48050400
42
43 /* DISPC common */
44 #define DISPC_REVISION                  0x0000
45 #define DISPC_SYSCONFIG                 0x0010
46 #define DISPC_SYSSTATUS                 0x0014
47 #define DISPC_IRQSTATUS                 0x0018
48 #define DISPC_IRQENABLE                 0x001C
49 #define DISPC_CONTROL                   0x0040
50 #define DISPC_CONFIG                    0x0044
51 #define DISPC_CAPABLE                   0x0048
52 #define DISPC_DEFAULT_COLOR0            0x004C
53 #define DISPC_DEFAULT_COLOR1            0x0050
54 #define DISPC_TRANS_COLOR0              0x0054
55 #define DISPC_TRANS_COLOR1              0x0058
56 #define DISPC_LINE_STATUS               0x005C
57 #define DISPC_LINE_NUMBER               0x0060
58 #define DISPC_TIMING_H                  0x0064
59 #define DISPC_TIMING_V                  0x0068
60 #define DISPC_POL_FREQ                  0x006C
61 #define DISPC_DIVISOR                   0x0070
62 #define DISPC_SIZE_DIG                  0x0078
63 #define DISPC_SIZE_LCD                  0x007C
64
65 #define DISPC_DATA_CYCLE1               0x01D4
66 #define DISPC_DATA_CYCLE2               0x01D8
67 #define DISPC_DATA_CYCLE3               0x01DC
68
69 /* DISPC GFX plane */
70 #define DISPC_GFX_BA0                   0x0080
71 #define DISPC_GFX_BA1                   0x0084
72 #define DISPC_GFX_POSITION              0x0088
73 #define DISPC_GFX_SIZE                  0x008C
74 #define DISPC_GFX_ATTRIBUTES            0x00A0
75 #define DISPC_GFX_FIFO_THRESHOLD        0x00A4
76 #define DISPC_GFX_FIFO_SIZE_STATUS      0x00A8
77 #define DISPC_GFX_ROW_INC               0x00AC
78 #define DISPC_GFX_PIXEL_INC             0x00B0
79 #define DISPC_GFX_WINDOW_SKIP           0x00B4
80 #define DISPC_GFX_TABLE_BA              0x00B8
81
82 /* DISPC Video plane 1/2 */
83 #define DISPC_VID1_BASE                 0x00BC
84 #define DISPC_VID2_BASE                 0x014C
85
86 /* Offsets into DISPC_VID1/2_BASE */
87 #define DISPC_VID_BA0                   0x0000
88 #define DISPC_VID_BA1                   0x0004
89 #define DISPC_VID_POSITION              0x0008
90 #define DISPC_VID_SIZE                  0x000C
91 #define DISPC_VID_ATTRIBUTES            0x0010
92 #define DISPC_VID_FIFO_THRESHOLD        0x0014
93 #define DISPC_VID_FIFO_SIZE_STATUS      0x0018
94 #define DISPC_VID_ROW_INC               0x001C
95 #define DISPC_VID_PIXEL_INC             0x0020
96 #define DISPC_VID_FIR                   0x0024
97 #define DISPC_VID_PICTURE_SIZE          0x0028
98 #define DISPC_VID_ACCU0                 0x002C
99 #define DISPC_VID_ACCU1                 0x0030
100
101 /* 8 elements in 8 byte increments */
102 #define DISPC_VID_FIR_COEF_H0           0x0034
103 /* 8 elements in 8 byte increments */
104 #define DISPC_VID_FIR_COEF_HV0          0x0038
105 /* 5 elements in 4 byte increments */
106 #define DISPC_VID_CONV_COEF0            0x0074
107
108 #define DISPC_IRQ_FRAMEMASK             0x0001
109 #define DISPC_IRQ_VSYNC                 0x0002
110 #define DISPC_IRQ_EVSYNC_EVEN           0x0004
111 #define DISPC_IRQ_EVSYNC_ODD            0x0008
112 #define DISPC_IRQ_ACBIAS_COUNT_STAT     0x0010
113 #define DISPC_IRQ_PROG_LINE_NUM         0x0020
114 #define DISPC_IRQ_GFX_FIFO_UNDERFLOW    0x0040
115 #define DISPC_IRQ_GFX_END_WIN           0x0080
116 #define DISPC_IRQ_PAL_GAMMA_MASK        0x0100
117 #define DISPC_IRQ_OCP_ERR               0x0200
118 #define DISPC_IRQ_VID1_FIFO_UNDERFLOW   0x0400
119 #define DISPC_IRQ_VID1_END_WIN          0x0800
120 #define DISPC_IRQ_VID2_FIFO_UNDERFLOW   0x1000
121 #define DISPC_IRQ_VID2_END_WIN          0x2000
122 #define DISPC_IRQ_SYNC_LOST             0x4000
123
124 #define DISPC_IRQ_MASK_ALL              0x7fff
125
126 #define DISPC_IRQ_MASK_ERROR            (DISPC_IRQ_GFX_FIFO_UNDERFLOW | \
127                                              DISPC_IRQ_VID1_FIFO_UNDERFLOW | \
128                                              DISPC_IRQ_VID2_FIFO_UNDERFLOW | \
129                                              DISPC_IRQ_SYNC_LOST)
130
131 #define MAX_PALETTE_SIZE                (256 * 16)
132
133 #define pr_err(fmt, args...) printk(KERN_ERR MODULE_NAME ": " fmt, ## args)
134
135 #define FLD_MASK(pos, len)      (((1 << len) - 1) << pos)
136
137 #define MOD_REG_FLD(reg, mask, val) \
138         dispc_write_reg((reg), (dispc_read_reg(reg) & ~(mask)) | (val));
139
140 static struct {
141         u32             base;
142         void            *vram_virt;
143         dma_addr_t      vram_phys;
144         int             vram_size;
145
146         int             ext_mode;
147
148         unsigned long   enabled_irqs;
149         void            (*irq_callback)(void *);
150         void            *irq_callback_data;
151         struct completion       frame_done;
152
153         struct clk      *dss_ick, *dss1_fck;
154         struct clk      *dss_54m_fck;
155
156         int             active_plane_mask;
157
158         enum omapfb_update_mode update_mode;
159         struct omapfb_device    *fbdev;
160 } dispc;
161
162 static void inline dispc_write_reg(int idx, u32 val)
163 {
164         __raw_writel(val, dispc.base + idx);
165 }
166
167 static u32 inline dispc_read_reg(int idx)
168 {
169         u32 l = __raw_readl(dispc.base + idx);
170         return l;
171 }
172
173 /* Select RFBI or bypass mode */
174 static void enable_rfbi_mode(int enable)
175 {
176         u32 l;
177
178         l = dispc_read_reg(DISPC_CONTROL);
179         /* Enable RFBI, GPIO0/1 */
180         l &= ~((1 << 11) | (1 << 15) | (1 << 16));
181         l |= enable ? (1 << 11) : 0;
182         /* RFBI En: GPIO0/1=10  RFBI Dis: GPIO0/1=11 */
183         l |= 1 << 15;
184         l |= enable ? 0 : (1 << 16);
185         dispc_write_reg(DISPC_CONTROL, l);
186 }
187
188 static void set_lcd_data_lines(int data_lines)
189 {
190         u32 l;
191         int code = 0;
192
193         switch (data_lines) {
194         case 12:
195                 code = 0;
196                 break;
197         case 16:
198                 code = 1;
199                 break;
200         case 18:
201                 code = 2;
202                 break;
203         case 24:
204                 code = 3;
205                 break;
206         default:
207                 BUG();
208         }
209
210         l = dispc_read_reg(DISPC_CONTROL);
211         l &= ~(0x03 << 8);
212         l |= code << 8;
213         dispc_write_reg(DISPC_CONTROL, l);
214 }
215
216 static void set_load_mode(int mode)
217 {
218         BUG_ON(mode & ~(DISPC_LOAD_CLUT_ONLY | DISPC_LOAD_FRAME_ONLY |
219                         DISPC_LOAD_CLUT_ONCE_FRAME));
220         MOD_REG_FLD(DISPC_CONFIG, 0x03 << 1, mode << 1);
221 }
222
223 void omap_dispc_set_lcd_size(int x, int y)
224 {
225         BUG_ON((x > (1 << 11)) || (y > (1 << 11)));
226         MOD_REG_FLD(DISPC_SIZE_LCD, FLD_MASK(16, 11) | FLD_MASK(0, 11),
227                         ((y - 1) << 16) | (x - 1));
228 }
229 EXPORT_SYMBOL(omap_dispc_set_lcd_size);
230
231 void omap_dispc_set_digit_size(int x, int y)
232 {
233         BUG_ON((x > (1 << 11)) || (y > (1 << 11)));
234         MOD_REG_FLD(DISPC_SIZE_DIG, FLD_MASK(16, 11) | FLD_MASK(0, 11),
235                         ((y - 1) << 16) | (x - 1));
236 }
237 EXPORT_SYMBOL(omap_dispc_set_digit_size);
238
239 static void setup_plane_fifo(int plane)
240 {
241         const u32 ftrs_reg[] = { DISPC_GFX_FIFO_THRESHOLD,
242                                 DISPC_VID1_BASE + DISPC_VID_FIFO_THRESHOLD,
243                                 DISPC_VID2_BASE + DISPC_VID_FIFO_THRESHOLD };
244         const u32 fsz_reg[] = { DISPC_GFX_FIFO_SIZE_STATUS,
245                                 DISPC_VID1_BASE + DISPC_VID_FIFO_SIZE_STATUS,
246                                 DISPC_VID2_BASE + DISPC_VID_FIFO_SIZE_STATUS };
247
248         u32 l;
249
250         BUG_ON(plane > 2);
251
252         l = dispc_read_reg(fsz_reg[plane]);
253         l &= FLD_MASK(0, 9);
254         /* HIGH=3/4 LOW=1/4 */
255         MOD_REG_FLD(ftrs_reg[plane], FLD_MASK(16, 9) | FLD_MASK(0, 9),
256                         ((l * 3 / 4) << 16) | (l / 4));
257 }
258
259 void omap_dispc_enable_lcd_out(int enable)
260 {
261         MOD_REG_FLD(DISPC_CONTROL, 1, enable ? 1 : 0);
262 }
263 EXPORT_SYMBOL(omap_dispc_enable_lcd_out);
264
265 void omap_dispc_enable_digit_out(int enable)
266 {
267         MOD_REG_FLD(DISPC_CONTROL, 1 << 1, enable ? 1 << 1 : 0);
268 }
269 EXPORT_SYMBOL(omap_dispc_enable_digit_out);
270
271 static int omap_dispc_setup_plane(int plane, int channel_out,
272                                   unsigned long offset, int screen_width,
273                                   int pos_x, int pos_y, int width, int height,
274                                   int color_mode)
275 {
276         const u32 at_reg[] = { DISPC_GFX_ATTRIBUTES,
277                                 DISPC_VID1_BASE + DISPC_VID_ATTRIBUTES,
278                                 DISPC_VID2_BASE + DISPC_VID_ATTRIBUTES };
279         const u32 ba_reg[] = { DISPC_GFX_BA0, DISPC_VID1_BASE + DISPC_VID_BA0,
280                                 DISPC_VID2_BASE + DISPC_VID_BA0 };
281         const u32 ps_reg[] = { DISPC_GFX_POSITION,
282                                 DISPC_VID1_BASE + DISPC_VID_POSITION,
283                                 DISPC_VID2_BASE + DISPC_VID_POSITION };
284         const u32 sz_reg[] = { DISPC_GFX_SIZE, DISPC_VID1_BASE + DISPC_VID_SIZE,
285                                 DISPC_VID2_BASE + DISPC_VID_SIZE };
286         const u32 ri_reg[] = { DISPC_GFX_ROW_INC,
287                                 DISPC_VID1_BASE + DISPC_VID_ROW_INC,
288                                 DISPC_VID2_BASE + DISPC_VID_ROW_INC };
289         int chout_shift, burst_shift;
290         int chout_val;
291         int color_code;
292         int bpp;
293         u32 l;
294
295         DBGENTER(1);
296
297         switch (plane) {
298         case OMAPFB_PLANE_GFX:
299                 burst_shift = 6;
300                 chout_shift = 8;
301                 break;
302         case OMAPFB_PLANE_VID1:
303         case OMAPFB_PLANE_VID2:
304                 burst_shift = 14;
305                 chout_shift = 16;
306                 break;
307         default:
308                 return -EINVAL;
309         }
310
311         switch (channel_out) {
312         case OMAPFB_CHANNEL_OUT_LCD:
313                 chout_val = 0;
314                 break;
315         case OMAPFB_CHANNEL_OUT_DIGIT:
316                 chout_val = 1;
317                 break;
318         default:
319                 return -EINVAL;
320         }
321
322         switch (color_mode) {
323         case OMAPFB_COLOR_RGB565:
324                 color_code = DISPC_RGB_16_BPP;
325                 bpp = 16;
326                 break;
327         case OMAPFB_COLOR_YUV422:
328                 if (plane != 0)
329                         return -EINVAL;
330                 color_code = DISPC_UYVY_422;
331                 bpp = 16;
332                 break;
333         case OMAPFB_COLOR_YUV420:
334                 if (plane != 0)
335                         return -EINVAL;
336                 color_code = DISPC_YUV2_422;
337                 bpp = 12;
338                 break;
339         default:
340                 return -EINVAL;
341         }
342
343         l = dispc_read_reg(at_reg[plane]);
344
345         l &= ~(0x0f << 1);
346         l |= color_code << 1;
347
348         l &= ~(0x03 << burst_shift);
349         l |= DISPC_BURST_8x32 << burst_shift;
350
351         l &= ~(1 << chout_shift);
352         l |= chout_val << chout_shift;
353
354         dispc_write_reg(at_reg[plane], l);
355
356
357         dispc_write_reg(ba_reg[plane],
358                        dispc.vram_phys + PAGE_ALIGN(MAX_PALETTE_SIZE) + offset);
359
360         MOD_REG_FLD(ps_reg[plane],
361                     FLD_MASK(16, 11) | FLD_MASK(0, 11), (pos_y << 16) | pos_x);
362
363         MOD_REG_FLD(sz_reg[plane], FLD_MASK(16, 11) | FLD_MASK(0, 11),
364                         ((height - 1) << 16) | (width - 1));
365
366         dispc_write_reg(ri_reg[plane], (screen_width - width) * bpp / 8 + 1);
367
368         return 0;
369 }
370
371 static int omap_dispc_enable_plane(int plane, int enable)
372 {
373         const u32 at_reg[] = { DISPC_GFX_ATTRIBUTES,
374                                 DISPC_VID1_BASE + DISPC_VID_ATTRIBUTES,
375                                 DISPC_VID2_BASE + DISPC_VID_ATTRIBUTES };
376         DBGENTER(1);
377
378         if ((unsigned int)plane > 2)
379                 return -EINVAL;
380         MOD_REG_FLD(at_reg[plane], 1, enable ? 1 : 0);
381
382         return 0;
383 }
384
385 static int omap_dispc_set_color_key(struct omapfb_color_key *ck)
386 {
387         u32 df_reg, tr_reg;
388         int shift, val;
389
390         switch (ck->channel_out) {
391         case OMAPFB_CHANNEL_OUT_LCD:
392                 df_reg = DISPC_DEFAULT_COLOR0;
393                 tr_reg = DISPC_TRANS_COLOR0;
394                 shift = 10;
395                 break;
396         case OMAPFB_CHANNEL_OUT_DIGIT:
397                 df_reg = DISPC_DEFAULT_COLOR1;
398                 tr_reg = DISPC_TRANS_COLOR1;
399                 shift = 12;
400                 break;
401         default:
402                 return -EINVAL;
403         }
404         switch (ck->key_type) {
405         case OMAPFB_COLOR_KEY_DISABLED:
406                 val = 0;
407                 break;
408         case OMAPFB_COLOR_KEY_GFX_DST:
409                 val = 1;
410                 break;
411         case OMAPFB_COLOR_KEY_VID_SRC:
412                 val = 3;
413                 break;
414         default:
415                 return -EINVAL;
416         }
417         MOD_REG_FLD(DISPC_CONFIG, FLD_MASK(shift, 2), val << shift);
418
419         if (val != 0)
420                 dispc_write_reg(tr_reg, ck->trans_key);
421         dispc_write_reg(df_reg, ck->background);
422
423         return 0;
424 }
425
426 static void load_palette(void)
427 {
428 }
429
430 static int omap_dispc_set_update_mode(enum omapfb_update_mode mode)
431 {
432         int r = 0;
433
434         DBGENTER(1);
435
436         if (mode != dispc.update_mode) {
437                 switch (mode) {
438                 case OMAPFB_AUTO_UPDATE:
439                         omap_dispc_enable_lcd_out(1);
440                         dispc.update_mode = mode;
441                         break;
442                 case OMAPFB_UPDATE_DISABLED:
443                         init_completion(&dispc.frame_done);
444                         omap_dispc_enable_lcd_out(0);
445                         if (!wait_for_completion_timeout(&dispc.frame_done,
446                                         msecs_to_jiffies(500))) {
447                                 pr_err("timeout waiting for FRAME DONE\n");
448                         }
449                         dispc.update_mode = mode;
450                         break;
451                 default:
452                         r = -EINVAL;
453                 }
454         }
455
456         DBGLEAVE(1);
457
458         return r;
459 }
460
461 static enum omapfb_update_mode omap_dispc_get_update_mode(void)
462 {
463         return dispc.update_mode;
464 }
465
466 static void calc_ck_div(int is_tft, int pck, int *lck_div, int *pck_div)
467 {
468         unsigned long fck, lck;
469
470         *lck_div = 1;
471         pck = max(1, pck);
472         fck = clk_get_rate(dispc.dss1_fck);
473         lck = fck;
474         *pck_div = lck / pck;
475         if (is_tft)
476                 *pck_div = max(2, *pck_div);
477         else
478                 *pck_div = max(3, *pck_div);
479         if (*pck_div > 255) {
480                 *pck_div = 255;
481                 lck = pck * *pck_div;
482                 *lck_div = fck / lck;
483                 BUG_ON(*lck_div < 1);
484                 if (*lck_div > 255) {
485                         *lck_div = 255;
486                         printk(KERN_WARNING
487                                 MODULE_NAME ": pixclock %d kHz too low.\n",
488                                  pck / 1000);
489                 }
490         }
491 }
492
493 static void set_lcd_timings(void)
494 {
495         u32 l;
496         int lck_div, pck_div;
497         struct lcd_panel *panel = dispc.fbdev->panel;
498         int is_tft = panel->config & OMAP_LCDC_PANEL_TFT;
499         unsigned long fck;
500
501         DBGENTER(1);
502
503         /* TFT dither, TFT/STN */
504         l = (1 << 7) | (1 << 3);
505         MOD_REG_FLD(DISPC_CONTROL, l, is_tft ? l : 0);
506
507         l = dispc_read_reg(DISPC_TIMING_H);
508         l &= ~(FLD_MASK(0, 6) | FLD_MASK(8, 8) | FLD_MASK(20, 8));
509         l |= ( max(1, (min(64,  panel->hsw))) - 1 ) << 0;
510         l |= ( max(1, (min(256, panel->hfp))) - 1 ) << 8;
511         l |= ( max(1, (min(256, panel->hbp))) - 1 ) << 20;
512         dispc_write_reg(DISPC_TIMING_H, l);
513
514         l = dispc_read_reg(DISPC_TIMING_V);
515         l &= ~(FLD_MASK(0, 6) | FLD_MASK(8, 8) | FLD_MASK(20, 8));
516         l |= ( max(1, (min(64,  panel->vsw))) - 1 ) << 0;
517         l |= ( max(0, (min(255, panel->vfp))) - 0 ) << 8;
518         l |= ( max(0, (min(255, panel->vbp))) - 0 ) << 20;
519         dispc_write_reg(DISPC_TIMING_V, l);
520
521         l = dispc_read_reg(DISPC_POL_FREQ);
522         l &= ~FLD_MASK(12, 6);
523         l |= (panel->config & OMAP_LCDC_SIGNAL_MASK) << 12;
524         l |= panel->acb & 0xff;
525         dispc_write_reg(DISPC_POL_FREQ, l);
526
527         calc_ck_div(is_tft, panel->pixel_clock * 1000, &lck_div, &pck_div);
528
529         l = dispc_read_reg(DISPC_DIVISOR);
530         l &= ~(FLD_MASK(16, 8) | FLD_MASK(0, 8));
531         l |= (lck_div << 16) | (pck_div << 0);
532         dispc_write_reg(DISPC_DIVISOR, l);
533
534         /* update panel info with the exact clock */
535         fck = clk_get_rate(dispc.dss1_fck);
536         panel->pixel_clock = fck / lck_div / pck_div / 1000;
537 }
538
539 int omap_dispc_request_irq(void (*callback)(void *data), void *data)
540 {
541         int r = 0;
542
543         BUG_ON(callback == NULL);
544
545         if (dispc.irq_callback)
546                 r = -EBUSY;
547         else {
548                 dispc.irq_callback = callback;
549                 dispc.irq_callback_data = data;
550         }
551
552         return r;
553 }
554 EXPORT_SYMBOL(omap_dispc_request_irq);
555
556 void omap_dispc_enable_irqs(int irq_mask)
557 {
558         dispc.enabled_irqs = irq_mask;
559         irq_mask |= DISPC_IRQ_MASK_ERROR;
560         MOD_REG_FLD(DISPC_IRQENABLE, 0x7fff, irq_mask);
561 }
562 EXPORT_SYMBOL(omap_dispc_enable_irqs);
563
564 void omap_dispc_disable_irqs(int irq_mask)
565 {
566         dispc.enabled_irqs &= ~irq_mask;
567         irq_mask &= ~DISPC_IRQ_MASK_ERROR;
568         MOD_REG_FLD(DISPC_IRQENABLE, 0x7fff, irq_mask);
569 }
570 EXPORT_SYMBOL(omap_dispc_disable_irqs);
571
572 void omap_dispc_free_irq(void)
573 {
574         omap_dispc_disable_irqs(DISPC_IRQ_MASK_ALL);
575         dispc.irq_callback = NULL;
576         dispc.irq_callback_data = NULL;
577 }
578 EXPORT_SYMBOL(omap_dispc_free_irq);
579
580 static irqreturn_t omap_dispc_irq_handler(int irq, void *dev, struct pt_regs *regs)
581 {
582         u32 stat = dispc_read_reg(DISPC_IRQSTATUS);
583         static int jabber;
584
585         DBGENTER(2);
586
587         if (stat & DISPC_IRQ_FRAMEMASK)
588                 complete(&dispc.frame_done);
589
590         if (stat & DISPC_IRQ_MASK_ERROR) {
591                 if (jabber++ < 5) {
592                         pr_err("irq error status %04x\n", stat);
593                 } else {
594                         pr_err("disable irq\n");
595                         dispc_write_reg(DISPC_IRQENABLE, 0);
596                 }
597         }
598
599         if ((stat & dispc.enabled_irqs) && dispc.irq_callback)
600                 dispc.irq_callback(dispc.irq_callback_data);
601
602         dispc_write_reg(DISPC_IRQSTATUS, stat);
603
604         return IRQ_HANDLED;
605 }
606
607 static int get_dss_clocks(void)
608 {
609         if (IS_ERR((dispc.dss_ick = clk_get(dispc.fbdev->dev, "dss_ick")))) {
610                 pr_err("can't get dss_ick");
611                 return PTR_ERR(dispc.dss_ick);
612         }
613
614         if (IS_ERR((dispc.dss1_fck = clk_get(dispc.fbdev->dev, "dss1_fck")))) {
615                 pr_err("can't get dss1_fck");
616                 clk_put(dispc.dss_ick);
617                 return PTR_ERR(dispc.dss1_fck);
618         }
619
620         if (IS_ERR((dispc.dss_54m_fck =
621                                 clk_get(dispc.fbdev->dev, "dss_54m_fck")))) {
622                 pr_err("can't get dss_54m_fck");
623                 clk_put(dispc.dss_ick);
624                 clk_put(dispc.dss1_fck);
625                 return PTR_ERR(dispc.dss_54m_fck);
626         }
627
628         return 0;
629 }
630
631 static void put_dss_clocks(void)
632 {
633         clk_put(dispc.dss_54m_fck);
634         clk_put(dispc.dss1_fck);
635         clk_put(dispc.dss_ick);
636 }
637
638 static void enable_lcd_clocks(int enable)
639 {
640         if (enable) {
641                 clk_enable(dispc.dss_ick);
642                 clk_enable(dispc.dss1_fck);
643         } else {
644                 clk_disable(dispc.dss1_fck);
645                 clk_disable(dispc.dss_ick);
646         }
647 }
648
649 static void enable_digit_clocks(int enable)
650 {
651         if (enable)
652                 clk_enable(dispc.dss_54m_fck);
653         else
654                 clk_disable(dispc.dss_54m_fck);
655 }
656
657 static void omap_dispc_suspend(void)
658 {
659         DBGENTER(1);
660
661         if (dispc.update_mode == OMAPFB_AUTO_UPDATE) {
662                 init_completion(&dispc.frame_done);
663                 omap_dispc_enable_lcd_out(0);
664                 if (!wait_for_completion_timeout(&dispc.frame_done,
665                                 msecs_to_jiffies(500))) {
666                         pr_err("timeout waiting for FRAME DONE\n");
667                 }
668                 enable_lcd_clocks(0);
669         }
670
671         DBGLEAVE(1);
672 }
673
674 static void omap_dispc_resume(void)
675 {
676         DBGENTER(1);
677
678         if (dispc.update_mode == OMAPFB_AUTO_UPDATE) {
679                 enable_lcd_clocks(1);
680                 set_lcd_timings();
681                 load_palette();
682                 omap_dispc_enable_lcd_out(1);
683         }
684
685         DBGLEAVE(1);
686 }
687
688 /* Called when used in bypass mode */
689 static int alloc_vram(int req_size)
690 {
691         int frame_size;
692         struct lcd_panel *panel = dispc.fbdev->panel;
693
694         frame_size = PAGE_ALIGN(panel->x_res * panel->bpp / 8 * panel->y_res);
695         if (req_size > frame_size)
696                 frame_size = req_size;
697         dispc.vram_size = PAGE_ALIGN(MAX_PALETTE_SIZE) + frame_size;
698         dispc.vram_virt = dma_alloc_writecombine(dispc.fbdev->dev,
699                         dispc.vram_size, &dispc.vram_phys, GFP_KERNEL);
700
701         if (dispc.vram_virt == 0) {
702                 pr_err("unable to allocate fb DMA memory\n");
703                 return -ENOMEM;
704         }
705
706         return 0;
707 }
708
709 static void free_vram(void)
710 {
711         dma_free_writecombine(dispc.fbdev->dev, dispc.vram_size,
712                               dispc.vram_virt, dispc.vram_phys);
713 }
714
715 static void omap_dispc_get_vram_layout(unsigned long *size, void **virt,
716                                         dma_addr_t *phys)
717 {
718         *size = dispc.vram_size - PAGE_ALIGN(MAX_PALETTE_SIZE);
719         *virt = (u8 *)dispc.vram_virt + PAGE_ALIGN(MAX_PALETTE_SIZE);
720         *phys = dispc.vram_phys + PAGE_ALIGN(MAX_PALETTE_SIZE);
721 }
722
723 static int omap_dispc_init(struct omapfb_device *fbdev, int ext_mode,
724                            int req_vram_size)
725 {
726         int r;
727         u32 l;
728         struct lcd_panel *panel = fbdev->panel;
729         int tmo = 10000;
730
731         DBGENTER(1);
732
733         memset(&dispc, 0, sizeof(dispc));
734
735         dispc.base = io_p2v(DISPC_BASE);
736         dispc.fbdev = fbdev;
737         dispc.ext_mode = ext_mode;
738
739         if ((r = get_dss_clocks()) < 0)
740                 goto fail0;
741
742         enable_lcd_clocks(1);
743         /* Reset monitoring works only w/ the 54M clk */
744         enable_digit_clocks(1);
745
746         l = dispc_read_reg(DISPC_REVISION);
747         pr_info(MODULE_NAME ": version %d.%d\n", l >> 4 & 0x0f, l & 0x0f);
748
749         /* Soft reset */
750         MOD_REG_FLD(DISPC_SYSCONFIG, 1 << 1, 1 << 1);
751
752         while (!(dispc_read_reg(DISPC_SYSSTATUS) & 1)) {
753                 if (!--tmo) {
754                         pr_err("soft reset failed\n");
755                         r = -ENODEV;
756                         enable_digit_clocks(0);
757                         goto fail1;
758                 }
759         }
760
761         enable_digit_clocks(0);
762
763         if (!ext_mode && (r = alloc_vram(req_vram_size)) < 0)
764                 goto fail1;
765
766         /* Set logic clock to the fck for now */
767         MOD_REG_FLD(DISPC_DIVISOR, FLD_MASK(16, 8), 1);
768
769         setup_plane_fifo(0);
770         setup_plane_fifo(1);
771         setup_plane_fifo(2);
772
773         l = dispc_read_reg(DISPC_IRQSTATUS);
774         dispc_write_reg(l, DISPC_IRQSTATUS);
775
776         /* Enable those that we handle always */
777         omap_dispc_enable_irqs(DISPC_IRQ_FRAMEMASK);
778
779         if ((r = request_irq(INT_24XX_DSS_IRQ, omap_dispc_irq_handler,
780                            0, MODULE_NAME, NULL)) < 0) {
781                 pr_err("can't get DSS IRQ\n");
782                 goto fail2;
783         }
784
785         set_lcd_data_lines(panel->data_lines);
786         set_load_mode(DISPC_LOAD_FRAME_ONLY);
787
788         if (!ext_mode) {
789                 omap_dispc_set_lcd_size(panel->x_res, panel->y_res);
790                 set_lcd_timings();
791         }
792         enable_rfbi_mode(ext_mode);
793
794         DBGLEAVE(1);
795         return 0;
796 fail2:
797         if (ext_mode)
798                 free_vram();
799 fail1:
800         enable_lcd_clocks(0);
801         put_dss_clocks();
802 fail0:
803         DBGLEAVE(1);
804         return r;
805 }
806
807 static void omap_dispc_cleanup(void)
808 {
809         free_irq(INT_24XX_DSS_IRQ, NULL);
810         enable_lcd_clocks(0);
811         put_dss_clocks();
812         if (dispc.ext_mode)
813                 free_vram();
814 }
815
816 static unsigned long omap_dispc_get_caps(void)
817 {
818         return 0;
819 }
820
821 struct lcd_ctrl omap2_int_ctrl = {
822         .name                   = "internal",
823         .init                   = omap_dispc_init,
824         .cleanup                = omap_dispc_cleanup,
825         .get_vram_layout        = omap_dispc_get_vram_layout,
826         .get_caps               = omap_dispc_get_caps,
827         .set_update_mode        = omap_dispc_set_update_mode,
828         .get_update_mode        = omap_dispc_get_update_mode,
829         .update_window          = NULL,
830         .suspend                = omap_dispc_suspend,
831         .resume                 = omap_dispc_resume,
832         .setup_plane            = omap_dispc_setup_plane,
833         .enable_plane           = omap_dispc_enable_plane,
834         .set_color_key          = omap_dispc_set_color_key,
835 };
836
837 MODULE_DESCRIPTION("TI OMAP LCDC controller");
838 MODULE_LICENSE("GPL");