]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - drivers/video/omap/dispc.c
FB: Add support for OMAP framebuffer
[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 #include <linux/kernel.h>
24 #include <linux/dma-mapping.h>
25 #include <linux/vmalloc.h>
26 #include <linux/clk.h>
27
28 #include <asm/io.h>
29
30 #include <asm/arch/sram.h>
31 #include <asm/arch/omapfb.h>
32 #include <asm/arch/board.h>
33
34 #include "dispc.h"
35
36 #define MODULE_NAME                     "dispc"
37
38 #define DSS_BASE                        0x48050000
39 #define DSS_SYSCONFIG                   0x0010
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 RFBI_CONTROL                    0x48050040
132
133 #define MAX_PALETTE_SIZE                (256 * 16)
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 #define OMAP2_SRAM_START                0x40200000
141 /* Maximum size, in reality this is smaller if SRAM is partially locked. */
142 #define OMAP2_SRAM_SIZE                 0xa0000         /* 640k */
143
144 /* We support the SDRAM / SRAM types. See OMAPFB_PLANE_MEMTYPE_* in omapfb.h */
145 #define DISPC_MEMTYPE_NUM               2
146
147 #define RESMAP_SIZE(_page_cnt)                                          \
148         ((_page_cnt + (sizeof(unsigned long) * 8) - 1) / 8)
149 #define RESMAP_PTR(_res_map, _page_nr)                                  \
150         (((_res_map)->map) + (_page_nr) / (sizeof(unsigned long) * 8))
151 #define RESMAP_MASK(_page_nr)                                           \
152         (1 << ((_page_nr) & (sizeof(unsigned long) * 8 - 1)))
153
154 struct resmap {
155         unsigned long   start;
156         unsigned        page_cnt;
157         unsigned long   *map;
158 };
159
160 static struct {
161         u32             base;
162
163         struct omapfb_mem_desc  mem_desc;
164         struct resmap           *res_map[DISPC_MEMTYPE_NUM];
165         atomic_t                map_count[OMAPFB_PLANE_NUM];
166
167         dma_addr_t      palette_paddr;
168         void            *palette_vaddr;
169
170         int             ext_mode;
171
172         unsigned long   enabled_irqs;
173         void            (*irq_callback)(void *);
174         void            *irq_callback_data;
175         struct completion       frame_done;
176
177         int             fir_hinc[OMAPFB_PLANE_NUM];
178         int             fir_vinc[OMAPFB_PLANE_NUM];
179
180         struct clk      *dss_ick, *dss1_fck;
181         struct clk      *dss_54m_fck;
182
183         enum omapfb_update_mode update_mode;
184         struct omapfb_device    *fbdev;
185
186         struct omapfb_color_key color_key;
187 } dispc;
188
189 static void enable_lcd_clocks(int enable);
190
191 static void inline dispc_write_reg(int idx, u32 val)
192 {
193         __raw_writel(val, dispc.base + idx);
194 }
195
196 static u32 inline dispc_read_reg(int idx)
197 {
198         u32 l = __raw_readl(dispc.base + idx);
199         return l;
200 }
201
202 /* Select RFBI or bypass mode */
203 static void enable_rfbi_mode(int enable)
204 {
205         u32 l;
206
207         l = dispc_read_reg(DISPC_CONTROL);
208         /* Enable RFBI, GPIO0/1 */
209         l &= ~((1 << 11) | (1 << 15) | (1 << 16));
210         l |= enable ? (1 << 11) : 0;
211         /* RFBI En: GPIO0/1=10  RFBI Dis: GPIO0/1=11 */
212         l |= 1 << 15;
213         l |= enable ? 0 : (1 << 16);
214         dispc_write_reg(DISPC_CONTROL, l);
215
216         /* Set bypass mode in RFBI module */
217         l = __raw_readl(io_p2v(RFBI_CONTROL));
218         l |= enable ? 0 : (1 << 1);
219         __raw_writel(l, io_p2v(RFBI_CONTROL));
220 }
221
222 static void set_lcd_data_lines(int data_lines)
223 {
224         u32 l;
225         int code = 0;
226
227         switch (data_lines) {
228         case 12:
229                 code = 0;
230                 break;
231         case 16:
232                 code = 1;
233                 break;
234         case 18:
235                 code = 2;
236                 break;
237         case 24:
238                 code = 3;
239                 break;
240         default:
241                 BUG();
242         }
243
244         l = dispc_read_reg(DISPC_CONTROL);
245         l &= ~(0x03 << 8);
246         l |= code << 8;
247         dispc_write_reg(DISPC_CONTROL, l);
248 }
249
250 static void set_load_mode(int mode)
251 {
252         BUG_ON(mode & ~(DISPC_LOAD_CLUT_ONLY | DISPC_LOAD_FRAME_ONLY |
253                         DISPC_LOAD_CLUT_ONCE_FRAME));
254         MOD_REG_FLD(DISPC_CONFIG, 0x03 << 1, mode << 1);
255 }
256
257 void omap_dispc_set_lcd_size(int x, int y)
258 {
259         BUG_ON((x > (1 << 11)) || (y > (1 << 11)));
260         enable_lcd_clocks(1);
261         MOD_REG_FLD(DISPC_SIZE_LCD, FLD_MASK(16, 11) | FLD_MASK(0, 11),
262                         ((y - 1) << 16) | (x - 1));
263         enable_lcd_clocks(0);
264 }
265 EXPORT_SYMBOL(omap_dispc_set_lcd_size);
266
267 void omap_dispc_set_digit_size(int x, int y)
268 {
269         BUG_ON((x > (1 << 11)) || (y > (1 << 11)));
270         enable_lcd_clocks(1);
271         MOD_REG_FLD(DISPC_SIZE_DIG, FLD_MASK(16, 11) | FLD_MASK(0, 11),
272                         ((y - 1) << 16) | (x - 1));
273         enable_lcd_clocks(0);
274 }
275 EXPORT_SYMBOL(omap_dispc_set_digit_size);
276
277 static void setup_plane_fifo(int plane, int ext_mode)
278 {
279         const u32 ftrs_reg[] = { DISPC_GFX_FIFO_THRESHOLD,
280                                 DISPC_VID1_BASE + DISPC_VID_FIFO_THRESHOLD,
281                                 DISPC_VID2_BASE + DISPC_VID_FIFO_THRESHOLD };
282         const u32 fsz_reg[] = { DISPC_GFX_FIFO_SIZE_STATUS,
283                                 DISPC_VID1_BASE + DISPC_VID_FIFO_SIZE_STATUS,
284                                 DISPC_VID2_BASE + DISPC_VID_FIFO_SIZE_STATUS };
285         int low, high;
286         u32 l;
287
288         BUG_ON(plane > 2);
289
290         l = dispc_read_reg(fsz_reg[plane]);
291         l &= FLD_MASK(0, 9);
292         if (ext_mode) {
293                 low = l * 3 / 4;
294                 high = l;
295         } else {
296                 low = l / 4;
297                 high = l * 3 / 4;
298         }
299         MOD_REG_FLD(ftrs_reg[plane], FLD_MASK(16, 9) | FLD_MASK(0, 9),
300                         (high << 16) | low);
301 }
302
303 void omap_dispc_enable_lcd_out(int enable)
304 {
305         enable_lcd_clocks(1);
306         MOD_REG_FLD(DISPC_CONTROL, 1, enable ? 1 : 0);
307         enable_lcd_clocks(0);
308 }
309 EXPORT_SYMBOL(omap_dispc_enable_lcd_out);
310
311 void omap_dispc_enable_digit_out(int enable)
312 {
313         enable_lcd_clocks(1);
314         MOD_REG_FLD(DISPC_CONTROL, 1 << 1, enable ? 1 << 1 : 0);
315         enable_lcd_clocks(0);
316 }
317 EXPORT_SYMBOL(omap_dispc_enable_digit_out);
318
319 static inline int _setup_plane(int plane, int channel_out,
320                                   u32 paddr, int screen_width,
321                                   int pos_x, int pos_y, int width, int height,
322                                   int color_mode)
323 {
324         const u32 at_reg[] = { DISPC_GFX_ATTRIBUTES,
325                                 DISPC_VID1_BASE + DISPC_VID_ATTRIBUTES,
326                                 DISPC_VID2_BASE + DISPC_VID_ATTRIBUTES };
327         const u32 ba_reg[] = { DISPC_GFX_BA0, DISPC_VID1_BASE + DISPC_VID_BA0,
328                                 DISPC_VID2_BASE + DISPC_VID_BA0 };
329         const u32 ps_reg[] = { DISPC_GFX_POSITION,
330                                 DISPC_VID1_BASE + DISPC_VID_POSITION,
331                                 DISPC_VID2_BASE + DISPC_VID_POSITION };
332         const u32 sz_reg[] = { DISPC_GFX_SIZE,
333                                 DISPC_VID1_BASE + DISPC_VID_PICTURE_SIZE,
334                                 DISPC_VID2_BASE + DISPC_VID_PICTURE_SIZE };
335         const u32 ri_reg[] = { DISPC_GFX_ROW_INC,
336                                 DISPC_VID1_BASE + DISPC_VID_ROW_INC,
337                                 DISPC_VID2_BASE + DISPC_VID_ROW_INC };
338         const u32 vs_reg[]= { 0, DISPC_VID1_BASE + DISPC_VID_SIZE,
339                                 DISPC_VID2_BASE + DISPC_VID_SIZE };
340
341         int chout_shift, burst_shift;
342         int chout_val;
343         int color_code;
344         int bpp;
345         int cconv_en;
346         int set_vsize;
347         u32 l;
348
349 #ifdef VERBOSE
350         dev_dbg(dispc.fbdev->dev, "plane %d channel %d paddr %#08x scr_width %d "
351                     "pos_x %d pos_y %d width %d height %d color_mode %d\n",
352                     plane, channel_out, paddr, screen_width, pos_x, pos_y,
353                     width, height, color_mode);
354 #endif
355
356         set_vsize = 0;
357         switch (plane) {
358         case OMAPFB_PLANE_GFX:
359                 burst_shift = 6;
360                 chout_shift = 8;
361                 break;
362         case OMAPFB_PLANE_VID1:
363         case OMAPFB_PLANE_VID2:
364                 burst_shift = 14;
365                 chout_shift = 16;
366                 set_vsize = 1;
367                 break;
368         default:
369                 return -EINVAL;
370         }
371
372         switch (channel_out) {
373         case OMAPFB_CHANNEL_OUT_LCD:
374                 chout_val = 0;
375                 break;
376         case OMAPFB_CHANNEL_OUT_DIGIT:
377                 chout_val = 1;
378                 break;
379         default:
380                 return -EINVAL;
381         }
382
383         cconv_en = 0;
384         switch (color_mode) {
385         case OMAPFB_COLOR_RGB565:
386                 color_code = DISPC_RGB_16_BPP;
387                 bpp = 16;
388                 break;
389         case OMAPFB_COLOR_YUV422:
390                 if (plane == 0)
391                         return -EINVAL;
392                 color_code = DISPC_UYVY_422;
393                 cconv_en = 1;
394                 bpp = 16;
395                 break;
396         case OMAPFB_COLOR_YUY422:
397                 if (plane == 0)
398                         return -EINVAL;
399                 color_code = DISPC_YUV2_422;
400                 cconv_en = 1;
401                 bpp = 16;
402                 break;
403         default:
404                 return -EINVAL;
405         }
406
407         l = dispc_read_reg(at_reg[plane]);
408
409         l &= ~(0x0f << 1);
410         l |= color_code << 1;
411         l &= ~(1 << 9);
412         l |= cconv_en << 9;
413
414         l &= ~(0x03 << burst_shift);
415         l |= DISPC_BURST_8x32 << burst_shift;
416
417         l &= ~(1 << chout_shift);
418         l |= chout_val << chout_shift;
419
420         dispc_write_reg(at_reg[plane], l);
421
422         dispc_write_reg(ba_reg[plane], paddr);
423         MOD_REG_FLD(ps_reg[plane],
424                     FLD_MASK(16, 11) | FLD_MASK(0, 11), (pos_y << 16) | pos_x);
425
426         MOD_REG_FLD(sz_reg[plane], FLD_MASK(16, 11) | FLD_MASK(0, 11),
427                         ((height - 1) << 16) | (width - 1));
428
429         if (set_vsize) {
430                 /* Set video size if set_scale hasn't set it */
431                 if (!dispc.fir_vinc[plane])
432                         MOD_REG_FLD(vs_reg[plane],
433                                 FLD_MASK(16, 11), (height - 1) << 16);
434                 if (!dispc.fir_hinc[plane])
435                         MOD_REG_FLD(vs_reg[plane],
436                                 FLD_MASK(0, 11), width - 1);
437         }
438
439         dispc_write_reg(ri_reg[plane], (screen_width - width) * bpp / 8 + 1);
440
441         return height * screen_width * bpp / 8;
442 }
443
444 static int omap_dispc_setup_plane(int plane, int channel_out,
445                                   unsigned long offset,
446                                   int screen_width,
447                                   int pos_x, int pos_y, int width, int height,
448                                   int color_mode)
449 {
450         u32 paddr;
451         int r;
452
453         if ((unsigned)plane > dispc.mem_desc.region_cnt)
454                 return -EINVAL;
455         paddr = dispc.mem_desc.region[plane].paddr + offset;
456         enable_lcd_clocks(1);
457         r = _setup_plane(plane, channel_out, paddr,
458                         screen_width,
459                         pos_x, pos_y, width, height, color_mode);
460         enable_lcd_clocks(0);
461         return r;
462 }
463
464 static void write_firh_reg(int plane, int reg, u32 value)
465 {
466         u32 base;
467
468         if (plane == 1)
469                 base = DISPC_VID1_BASE + DISPC_VID_FIR_COEF_H0;
470         else
471                 base = DISPC_VID2_BASE + DISPC_VID_FIR_COEF_H0;
472         dispc_write_reg(base + reg * 8, value);
473 }
474
475 static void write_firhv_reg(int plane, int reg, u32 value)
476 {
477         u32 base;
478
479         if (plane == 1)
480                 base = DISPC_VID1_BASE + DISPC_VID_FIR_COEF_HV0;
481         else
482                 base = DISPC_VID2_BASE + DISPC_VID_FIR_COEF_HV0;
483         dispc_write_reg(base + reg * 8, value);
484 }
485
486 static void set_upsampling_coef_table(int plane)
487 {
488         const u32 coef[][2] = {
489                 { 0x00800000, 0x00800000 },
490                 { 0x0D7CF800, 0x037B02FF },
491                 { 0x1E70F5FF, 0x0C6F05FE },
492                 { 0x335FF5FE, 0x205907FB },
493                 { 0xF74949F7, 0x00404000 },
494                 { 0xF55F33FB, 0x075920FE },
495                 { 0xF5701EFE, 0x056F0CFF },
496                 { 0xF87C0DFF, 0x027B0300 },
497         };
498         int i;
499
500         for (i = 0; i < 8; i++) {
501                 write_firh_reg(plane, i, coef[i][0]);
502                 write_firhv_reg(plane, i, coef[i][1]);
503         }
504 }
505
506 static int omap_dispc_set_scale(int plane,
507                                 int orig_width, int orig_height,
508                                 int out_width, int out_height)
509 {
510         const u32 at_reg[]  = { 0, DISPC_VID1_BASE + DISPC_VID_ATTRIBUTES,
511                                    DISPC_VID2_BASE + DISPC_VID_ATTRIBUTES };
512         const u32 vs_reg[]  = { 0, DISPC_VID1_BASE + DISPC_VID_SIZE,
513                                    DISPC_VID2_BASE + DISPC_VID_SIZE };
514         const u32 fir_reg[] = { 0, DISPC_VID1_BASE + DISPC_VID_FIR,
515                                    DISPC_VID2_BASE + DISPC_VID_FIR };
516
517         u32 l;
518         int fir_hinc;
519         int fir_vinc;
520
521         if ((unsigned)plane > OMAPFB_PLANE_NUM)
522                 return -ENODEV;
523
524         if (plane == OMAPFB_PLANE_GFX &&
525             (out_width != orig_width || out_height != orig_height))
526                 return -EINVAL;
527
528         enable_lcd_clocks(1);
529         if (orig_width < out_width) {
530                 /* Upsampling.
531                  * Currently you can only scale both dimensions in one way.
532                  */
533                 if (orig_height > out_height ||
534                     orig_width * 8 < out_width ||
535                     orig_height * 8 < out_height) {
536                         enable_lcd_clocks(0);
537                         return -EINVAL;
538                 }
539                 set_upsampling_coef_table(plane);
540         } else if (orig_width > out_width) {
541                 /* Downsampling not yet supported
542                 */
543
544                 enable_lcd_clocks(0);
545                 return -EINVAL;
546         }
547         if (!orig_width || orig_width == out_width)
548                 fir_hinc = 0;
549         else
550                 fir_hinc = 1024 * orig_width / out_width;
551         if (!orig_height || orig_height == out_height)
552                 fir_vinc = 0;
553         else
554                 fir_vinc = 1024 * orig_height / out_height;
555         dispc.fir_hinc[plane] = fir_hinc;
556         dispc.fir_vinc[plane] = fir_vinc;
557
558         MOD_REG_FLD(fir_reg[plane],
559                     FLD_MASK(16, 12) | FLD_MASK(0, 12),
560                     ((fir_vinc & 4095) << 16) |
561                     (fir_hinc & 4095));
562
563         dev_dbg(dispc.fbdev->dev, "out_width %d out_height %d orig_width %d "
564                 "orig_height %d fir_hinc  %d fir_vinc %d\n",
565                 out_width, out_height, orig_width, orig_height,
566                 fir_hinc, fir_vinc);
567
568         MOD_REG_FLD(vs_reg[plane],
569                     FLD_MASK(16, 11) | FLD_MASK(0, 11),
570                     ((out_height - 1) << 16) | (out_width - 1));
571
572         l = dispc_read_reg(at_reg[plane]);
573         l &= ~(0x03 << 5);
574         l |= fir_hinc ? (1 << 5) : 0;
575         l |= fir_vinc ? (1 << 6) : 0;
576         dispc_write_reg(at_reg[plane], l);
577
578         enable_lcd_clocks(0);
579         return 0;
580 }
581
582 static int omap_dispc_enable_plane(int plane, int enable)
583 {
584         const u32 at_reg[] = { DISPC_GFX_ATTRIBUTES,
585                                 DISPC_VID1_BASE + DISPC_VID_ATTRIBUTES,
586                                 DISPC_VID2_BASE + DISPC_VID_ATTRIBUTES };
587         if ((unsigned int)plane > dispc.mem_desc.region_cnt)
588                 return -EINVAL;
589
590         enable_lcd_clocks(1);
591         MOD_REG_FLD(at_reg[plane], 1, enable ? 1 : 0);
592         enable_lcd_clocks(0);
593
594         return 0;
595 }
596
597 static int omap_dispc_set_color_key(struct omapfb_color_key *ck)
598 {
599         u32 df_reg, tr_reg;
600         int shift, val;
601
602         switch (ck->channel_out) {
603         case OMAPFB_CHANNEL_OUT_LCD:
604                 df_reg = DISPC_DEFAULT_COLOR0;
605                 tr_reg = DISPC_TRANS_COLOR0;
606                 shift = 10;
607                 break;
608         case OMAPFB_CHANNEL_OUT_DIGIT:
609                 df_reg = DISPC_DEFAULT_COLOR1;
610                 tr_reg = DISPC_TRANS_COLOR1;
611                 shift = 12;
612                 break;
613         default:
614                 return -EINVAL;
615         }
616         switch (ck->key_type) {
617         case OMAPFB_COLOR_KEY_DISABLED:
618                 val = 0;
619                 break;
620         case OMAPFB_COLOR_KEY_GFX_DST:
621                 val = 1;
622                 break;
623         case OMAPFB_COLOR_KEY_VID_SRC:
624                 val = 3;
625                 break;
626         default:
627                 return -EINVAL;
628         }
629         enable_lcd_clocks(1);
630         MOD_REG_FLD(DISPC_CONFIG, FLD_MASK(shift, 2), val << shift);
631
632         if (val != 0)
633                 dispc_write_reg(tr_reg, ck->trans_key);
634         dispc_write_reg(df_reg, ck->background);
635         enable_lcd_clocks(0);
636
637         dispc.color_key = *ck;
638
639         return 0;
640 }
641
642 static int omap_dispc_get_color_key(struct omapfb_color_key *ck)
643 {
644         *ck = dispc.color_key;
645         return 0;
646 }
647
648 static void load_palette(void)
649 {
650 }
651
652 static int omap_dispc_set_update_mode(enum omapfb_update_mode mode)
653 {
654         int r = 0;
655
656         if (mode != dispc.update_mode) {
657                 switch (mode) {
658                 case OMAPFB_AUTO_UPDATE:
659                 case OMAPFB_MANUAL_UPDATE:
660                         enable_lcd_clocks(1);
661                         omap_dispc_enable_lcd_out(1);
662                         dispc.update_mode = mode;
663                         break;
664                 case OMAPFB_UPDATE_DISABLED:
665                         init_completion(&dispc.frame_done);
666                         omap_dispc_enable_lcd_out(0);
667                         if (!wait_for_completion_timeout(&dispc.frame_done,
668                                         msecs_to_jiffies(500))) {
669                                 dev_err(dispc.fbdev->dev,
670                                          "timeout waiting for FRAME DONE\n");
671                         }
672                         dispc.update_mode = mode;
673                         enable_lcd_clocks(0);
674                         break;
675                 default:
676                         r = -EINVAL;
677                 }
678         }
679
680         return r;
681 }
682
683 static void omap_dispc_get_caps(int plane, struct omapfb_caps *caps)
684 {
685         caps->ctrl |= OMAPFB_CAPS_PLANE_RELOCATE_MEM;
686         if (plane > 0)
687                 caps->ctrl |= OMAPFB_CAPS_PLANE_SCALE;
688         caps->plane_color |= (1 << OMAPFB_COLOR_RGB565) |
689                              (1 << OMAPFB_COLOR_YUV422) |
690                              (1 << OMAPFB_COLOR_YUY422);
691         if (plane == 0)
692                 caps->plane_color |= (1 << OMAPFB_COLOR_CLUT_8BPP) |
693                                      (1 << OMAPFB_COLOR_CLUT_4BPP) |
694                                      (1 << OMAPFB_COLOR_CLUT_2BPP) |
695                                      (1 << OMAPFB_COLOR_CLUT_1BPP) |
696                                      (1 << OMAPFB_COLOR_RGB444);
697 }
698
699 static enum omapfb_update_mode omap_dispc_get_update_mode(void)
700 {
701         return dispc.update_mode;
702 }
703
704 static void setup_color_conv_coef(void)
705 {
706         u32 mask = FLD_MASK(16, 11) | FLD_MASK(0, 11);
707         int cf1_reg = DISPC_VID1_BASE + DISPC_VID_CONV_COEF0;
708         int cf2_reg = DISPC_VID2_BASE + DISPC_VID_CONV_COEF0;
709         int at1_reg = DISPC_VID1_BASE + DISPC_VID_ATTRIBUTES;
710         int at2_reg = DISPC_VID2_BASE + DISPC_VID_ATTRIBUTES;
711         const struct color_conv_coef {
712                 int  ry,  rcr,  rcb,   gy,  gcr,  gcb,   by,  bcr,  bcb;
713                 int  full_range;
714         }  ctbl_bt601_5 = {
715                     298,  409,    0,  298, -208, -100,  298,    0,  517, 0,
716         };
717 #if 0
718         const struct color_conv_coef ctbl_bt601_5_full = {
719                     256,  351,    0,  256, -179,  -86,  256,    0,  443, 1,
720         }, ctbl_bt709 = {
721                     298,  459,    0,  298, -137,  -55,  298,    0,  541, 0,
722         }, ctbl_bt709_f = {
723                     256,  394,    0,  256, -118,  -47,  256,    0,  465, 1,     },
724 #endif
725         const struct color_conv_coef *ct;
726 #define CVAL(x, y)      (((x & 2047) << 16) | (y & 2047))
727
728         ct = &ctbl_bt601_5;
729
730         MOD_REG_FLD(cf1_reg,            mask,   CVAL(ct->rcr, ct->ry));
731         MOD_REG_FLD(cf1_reg + 4,        mask,   CVAL(ct->gy,  ct->rcb));
732         MOD_REG_FLD(cf1_reg + 8,        mask,   CVAL(ct->gcb, ct->gcr));
733         MOD_REG_FLD(cf1_reg + 12,       mask,   CVAL(ct->bcr, ct->by));
734         MOD_REG_FLD(cf1_reg + 16,       mask,   CVAL(0,       ct->bcb));
735
736         MOD_REG_FLD(cf2_reg,            mask,   CVAL(ct->rcr, ct->ry));
737         MOD_REG_FLD(cf2_reg + 4,        mask,   CVAL(ct->gy,  ct->rcb));
738         MOD_REG_FLD(cf2_reg + 8,        mask,   CVAL(ct->gcb, ct->gcr));
739         MOD_REG_FLD(cf2_reg + 12,       mask,   CVAL(ct->bcr, ct->by));
740         MOD_REG_FLD(cf2_reg + 16,       mask,   CVAL(0,       ct->bcb));
741 #undef CVAL
742
743         MOD_REG_FLD(at1_reg, (1 << 11), ct->full_range);
744         MOD_REG_FLD(at2_reg, (1 << 11), ct->full_range);
745 }
746
747 static void calc_ck_div(int is_tft, int pck, int *lck_div, int *pck_div)
748 {
749         unsigned long fck, lck;
750
751         *lck_div = 1;
752         pck = max(1, pck);
753         fck = clk_get_rate(dispc.dss1_fck);
754         lck = fck;
755         *pck_div = (lck + pck - 1) / pck;
756         if (is_tft)
757                 *pck_div = max(2, *pck_div);
758         else
759                 *pck_div = max(3, *pck_div);
760         if (*pck_div > 255) {
761                 *pck_div = 255;
762                 lck = pck * *pck_div;
763                 *lck_div = fck / lck;
764                 BUG_ON(*lck_div < 1);
765                 if (*lck_div > 255) {
766                         *lck_div = 255;
767                         dev_warn(dispc.fbdev->dev, "pixclock %d kHz too low.\n",
768                                  pck / 1000);
769                 }
770         }
771 }
772
773 static void set_lcd_tft_mode(int enable)
774 {
775         u32 mask;
776
777         mask = 1 << 3;
778         MOD_REG_FLD(DISPC_CONTROL, mask, enable ? mask : 0);
779 }
780
781 static void set_lcd_timings(void)
782 {
783         u32 l;
784         int lck_div, pck_div;
785         struct lcd_panel *panel = dispc.fbdev->panel;
786         int is_tft = panel->config & OMAP_LCDC_PANEL_TFT;
787         unsigned long fck;
788
789         l = dispc_read_reg(DISPC_TIMING_H);
790         l &= ~(FLD_MASK(0, 6) | FLD_MASK(8, 8) | FLD_MASK(20, 8));
791         l |= ( max(1, (min(64,  panel->hsw))) - 1 ) << 0;
792         l |= ( max(1, (min(256, panel->hfp))) - 1 ) << 8;
793         l |= ( max(1, (min(256, panel->hbp))) - 1 ) << 20;
794         dispc_write_reg(DISPC_TIMING_H, l);
795
796         l = dispc_read_reg(DISPC_TIMING_V);
797         l &= ~(FLD_MASK(0, 6) | FLD_MASK(8, 8) | FLD_MASK(20, 8));
798         l |= ( max(1, (min(64,  panel->vsw))) - 1 ) << 0;
799         l |= ( max(0, (min(255, panel->vfp))) - 0 ) << 8;
800         l |= ( max(0, (min(255, panel->vbp))) - 0 ) << 20;
801         dispc_write_reg(DISPC_TIMING_V, l);
802
803         l = dispc_read_reg(DISPC_POL_FREQ);
804         l &= ~FLD_MASK(12, 6);
805         l |= (panel->config & OMAP_LCDC_SIGNAL_MASK) << 12;
806         l |= panel->acb & 0xff;
807         dispc_write_reg(DISPC_POL_FREQ, l);
808
809         calc_ck_div(is_tft, panel->pixel_clock * 1000, &lck_div, &pck_div);
810
811         l = dispc_read_reg(DISPC_DIVISOR);
812         l &= ~(FLD_MASK(16, 8) | FLD_MASK(0, 8));
813         l |= (lck_div << 16) | (pck_div << 0);
814         dispc_write_reg(DISPC_DIVISOR, l);
815
816         /* update panel info with the exact clock */
817         fck = clk_get_rate(dispc.dss1_fck);
818         panel->pixel_clock = fck / lck_div / pck_div / 1000;
819 }
820
821 int omap_dispc_request_irq(void (*callback)(void *data), void *data)
822 {
823         int r = 0;
824
825         BUG_ON(callback == NULL);
826
827         if (dispc.irq_callback)
828                 r = -EBUSY;
829         else {
830                 dispc.irq_callback = callback;
831                 dispc.irq_callback_data = data;
832         }
833
834         return r;
835 }
836 EXPORT_SYMBOL(omap_dispc_request_irq);
837
838 void omap_dispc_enable_irqs(int irq_mask)
839 {
840         enable_lcd_clocks(1);
841         dispc.enabled_irqs = irq_mask;
842         irq_mask |= DISPC_IRQ_MASK_ERROR;
843         MOD_REG_FLD(DISPC_IRQENABLE, 0x7fff, irq_mask);
844         enable_lcd_clocks(0);
845 }
846 EXPORT_SYMBOL(omap_dispc_enable_irqs);
847
848 void omap_dispc_disable_irqs(int irq_mask)
849 {
850         enable_lcd_clocks(1);
851         dispc.enabled_irqs &= ~irq_mask;
852         irq_mask &= ~DISPC_IRQ_MASK_ERROR;
853         MOD_REG_FLD(DISPC_IRQENABLE, 0x7fff, irq_mask);
854         enable_lcd_clocks(0);
855 }
856 EXPORT_SYMBOL(omap_dispc_disable_irqs);
857
858 void omap_dispc_free_irq(void)
859 {
860         enable_lcd_clocks(1);
861         omap_dispc_disable_irqs(DISPC_IRQ_MASK_ALL);
862         dispc.irq_callback = NULL;
863         dispc.irq_callback_data = NULL;
864         enable_lcd_clocks(0);
865 }
866 EXPORT_SYMBOL(omap_dispc_free_irq);
867
868 static irqreturn_t omap_dispc_irq_handler(int irq, void *dev)
869 {
870         u32 stat = dispc_read_reg(DISPC_IRQSTATUS);
871
872         if (stat & DISPC_IRQ_FRAMEMASK)
873                 complete(&dispc.frame_done);
874
875         if (stat & DISPC_IRQ_MASK_ERROR) {
876                 if (printk_ratelimit()) {
877                         dev_err(dispc.fbdev->dev, "irq error status %04x\n",
878                                 stat & 0x7fff);
879                 }
880         }
881
882         if ((stat & dispc.enabled_irqs) && dispc.irq_callback)
883                 dispc.irq_callback(dispc.irq_callback_data);
884
885         dispc_write_reg(DISPC_IRQSTATUS, stat);
886
887         return IRQ_HANDLED;
888 }
889
890 static int get_dss_clocks(void)
891 {
892         if (IS_ERR((dispc.dss_ick = clk_get(dispc.fbdev->dev, "dss_ick")))) {
893                 dev_err(dispc.fbdev->dev, "can't get dss_ick");
894                 return PTR_ERR(dispc.dss_ick);
895         }
896
897         if (IS_ERR((dispc.dss1_fck = clk_get(dispc.fbdev->dev, "dss1_fck")))) {
898                 dev_err(dispc.fbdev->dev, "can't get dss1_fck");
899                 clk_put(dispc.dss_ick);
900                 return PTR_ERR(dispc.dss1_fck);
901         }
902
903         if (IS_ERR((dispc.dss_54m_fck =
904                                 clk_get(dispc.fbdev->dev, "dss_54m_fck")))) {
905                 dev_err(dispc.fbdev->dev, "can't get dss_54m_fck");
906                 clk_put(dispc.dss_ick);
907                 clk_put(dispc.dss1_fck);
908                 return PTR_ERR(dispc.dss_54m_fck);
909         }
910
911         return 0;
912 }
913
914 static void put_dss_clocks(void)
915 {
916         clk_put(dispc.dss_54m_fck);
917         clk_put(dispc.dss1_fck);
918         clk_put(dispc.dss_ick);
919 }
920
921 static void enable_lcd_clocks(int enable)
922 {
923         if (enable)
924                 clk_enable(dispc.dss1_fck);
925         else
926                 clk_disable(dispc.dss1_fck);
927 }
928
929 static void enable_interface_clocks(int enable)
930 {
931         if (enable)
932                 clk_enable(dispc.dss_ick);
933         else
934                 clk_disable(dispc.dss_ick);
935 }
936
937 static void enable_digit_clocks(int enable)
938 {
939         if (enable)
940                 clk_enable(dispc.dss_54m_fck);
941         else
942                 clk_disable(dispc.dss_54m_fck);
943 }
944
945 static void omap_dispc_suspend(void)
946 {
947         if (dispc.update_mode == OMAPFB_AUTO_UPDATE) {
948                 init_completion(&dispc.frame_done);
949                 omap_dispc_enable_lcd_out(0);
950                 if (!wait_for_completion_timeout(&dispc.frame_done,
951                                 msecs_to_jiffies(500))) {
952                         dev_err(dispc.fbdev->dev,
953                                 "timeout waiting for FRAME DONE\n");
954                 }
955                 enable_lcd_clocks(0);
956         }
957 }
958
959 static void omap_dispc_resume(void)
960 {
961         if (dispc.update_mode == OMAPFB_AUTO_UPDATE) {
962                 enable_lcd_clocks(1);
963                 if (!dispc.ext_mode) {
964                         set_lcd_timings();
965                         load_palette();
966                 }
967                 omap_dispc_enable_lcd_out(1);
968         }
969 }
970
971
972 static int omap_dispc_update_window(struct fb_info *fbi,
973                                  struct omapfb_update_window *win,
974                                  void (*complete_callback)(void *arg),
975                                  void *complete_callback_data)
976 {
977         return dispc.update_mode == OMAPFB_UPDATE_DISABLED ? -ENODEV : 0;
978 }
979
980 static int mmap_kern(struct omapfb_mem_region *region)
981 {
982         struct vm_struct        *kvma;
983         struct vm_area_struct   vma;
984         pgprot_t                pgprot;
985         unsigned long           vaddr;
986
987         kvma = get_vm_area(region->size, VM_IOREMAP);
988         if (kvma == NULL) {
989                 dev_err(dispc.fbdev->dev, "can't get kernel vm area\n");
990                 return -ENOMEM;
991         }
992         vma.vm_mm = &init_mm;
993
994         vaddr = (unsigned long)kvma->addr;
995
996         pgprot = pgprot_writecombine(pgprot_kernel);
997         vma.vm_start = vaddr;
998         vma.vm_end = vaddr + region->size;
999         if (io_remap_pfn_range(&vma, vaddr, region->paddr >> PAGE_SHIFT,
1000                            region->size, pgprot) < 0) {
1001                 dev_err(dispc.fbdev->dev, "kernel mmap for FBMEM failed\n");
1002                 return -EAGAIN;
1003         }
1004         region->vaddr = (void *)vaddr;
1005
1006         return 0;
1007 }
1008
1009 static void mmap_user_open(struct vm_area_struct *vma)
1010 {
1011         int plane = (int)vma->vm_private_data;
1012
1013         atomic_inc(&dispc.map_count[plane]);
1014 }
1015
1016 static void mmap_user_close(struct vm_area_struct *vma)
1017 {
1018         int plane = (int)vma->vm_private_data;
1019
1020         atomic_dec(&dispc.map_count[plane]);
1021 }
1022
1023 static struct vm_operations_struct mmap_user_ops = {
1024         .open = mmap_user_open,
1025         .close = mmap_user_close,
1026 };
1027
1028 static int omap_dispc_mmap_user(struct fb_info *info,
1029                                 struct vm_area_struct *vma)
1030 {
1031         struct omapfb_plane_struct *plane = info->par;
1032         unsigned long off;
1033         unsigned long start;
1034         u32 len;
1035
1036         if (vma->vm_end - vma->vm_start == 0)
1037                 return 0;
1038         if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
1039                 return -EINVAL;
1040         off = vma->vm_pgoff << PAGE_SHIFT;
1041
1042         start = info->fix.smem_start;
1043         len = info->fix.smem_len;
1044         if (off >= len)
1045                 return -EINVAL;
1046         if ((vma->vm_end - vma->vm_start + off) > len)
1047                 return -EINVAL;
1048         off += start;
1049         vma->vm_pgoff = off >> PAGE_SHIFT;
1050         vma->vm_flags |= VM_IO | VM_RESERVED;
1051         vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
1052         vma->vm_ops = &mmap_user_ops;
1053         vma->vm_private_data = (void *)plane->idx;
1054         if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
1055                              vma->vm_end - vma->vm_start, vma->vm_page_prot))
1056                 return -EAGAIN;
1057         /* vm_ops.open won't be called for mmap itself. */
1058         atomic_inc(&dispc.map_count[plane->idx]);
1059         return 0;
1060 }
1061
1062 static void unmap_kern(struct omapfb_mem_region *region)
1063 {
1064         vunmap(region->vaddr);
1065 }
1066
1067 static int alloc_palette_ram(void)
1068 {
1069         dispc.palette_vaddr = dma_alloc_writecombine(dispc.fbdev->dev,
1070                 MAX_PALETTE_SIZE, &dispc.palette_paddr, GFP_KERNEL);
1071         if (dispc.palette_vaddr == NULL) {
1072                 dev_err(dispc.fbdev->dev, "failed to alloc palette memory\n");
1073                 return -ENOMEM;
1074         }
1075
1076         return 0;
1077 }
1078
1079 static void free_palette_ram(void)
1080 {
1081         dma_free_writecombine(dispc.fbdev->dev, MAX_PALETTE_SIZE,
1082                         dispc.palette_vaddr, dispc.palette_paddr);
1083 }
1084
1085 static int alloc_fbmem(struct omapfb_mem_region *region)
1086 {
1087         region->vaddr = dma_alloc_writecombine(dispc.fbdev->dev,
1088                         region->size, &region->paddr, GFP_KERNEL);
1089
1090         if (region->vaddr == NULL) {
1091                 dev_err(dispc.fbdev->dev, "unable to allocate FB DMA memory\n");
1092                 return -ENOMEM;
1093         }
1094
1095         return 0;
1096 }
1097
1098 static void free_fbmem(struct omapfb_mem_region *region)
1099 {
1100         dma_free_writecombine(dispc.fbdev->dev, region->size,
1101                               region->vaddr, region->paddr);
1102 }
1103
1104 static struct resmap *init_resmap(unsigned long start, size_t size)
1105 {
1106         unsigned page_cnt;
1107         struct resmap *res_map;
1108
1109         page_cnt = PAGE_ALIGN(size) / PAGE_SIZE;
1110         res_map =
1111             kzalloc(sizeof(struct resmap) + RESMAP_SIZE(page_cnt), GFP_KERNEL);
1112         if (res_map == NULL)
1113                 return NULL;
1114         res_map->start = start;
1115         res_map->page_cnt = page_cnt;
1116         res_map->map = (unsigned long *)(res_map + 1);
1117         return res_map;
1118 }
1119
1120 static void cleanup_resmap(struct resmap *res_map)
1121 {
1122         kfree(res_map);
1123 }
1124
1125 static inline int resmap_mem_type(unsigned long start)
1126 {
1127         if (start >= OMAP2_SRAM_START &&
1128             start < OMAP2_SRAM_START + OMAP2_SRAM_SIZE)
1129                 return OMAPFB_MEMTYPE_SRAM;
1130         else
1131                 return OMAPFB_MEMTYPE_SDRAM;
1132 }
1133
1134 static inline int resmap_page_reserved(struct resmap *res_map, unsigned page_nr)
1135 {
1136         return *RESMAP_PTR(res_map, page_nr) & RESMAP_MASK(page_nr) ? 1 : 0;
1137 }
1138
1139 static inline void resmap_reserve_page(struct resmap *res_map, unsigned page_nr)
1140 {
1141         BUG_ON(resmap_page_reserved(res_map, page_nr));
1142         *RESMAP_PTR(res_map, page_nr) |= RESMAP_MASK(page_nr);
1143 }
1144
1145 static inline void resmap_free_page(struct resmap *res_map, unsigned page_nr)
1146 {
1147         BUG_ON(!resmap_page_reserved(res_map, page_nr));
1148         *RESMAP_PTR(res_map, page_nr) &= ~RESMAP_MASK(page_nr);
1149 }
1150
1151 static void resmap_reserve_region(unsigned long start, size_t size)
1152 {
1153
1154         struct resmap   *res_map;
1155         unsigned        start_page;
1156         unsigned        end_page;
1157         int             mtype;
1158         unsigned        i;
1159
1160         mtype = resmap_mem_type(start);
1161         res_map = dispc.res_map[mtype];
1162         dev_dbg(dispc.fbdev->dev, "reserve mem type %d start %08lx size %d\n",
1163                 mtype, start, size);
1164         start_page = (start - res_map->start) / PAGE_SIZE;
1165         end_page = start_page + PAGE_ALIGN(size) / PAGE_SIZE;
1166         for (i = start_page; i < end_page; i++)
1167                 resmap_reserve_page(res_map, i);
1168 }
1169
1170 static void resmap_free_region(unsigned long start, size_t size)
1171 {
1172         struct resmap   *res_map;
1173         unsigned        start_page;
1174         unsigned        end_page;
1175         unsigned        i;
1176         int             mtype;
1177
1178         mtype = resmap_mem_type(start);
1179         res_map = dispc.res_map[mtype];
1180         dev_dbg(dispc.fbdev->dev, "free mem type %d start %08lx size %d\n",
1181                 mtype, start, size);
1182         start_page = (start - res_map->start) / PAGE_SIZE;
1183         end_page = start_page + PAGE_ALIGN(size) / PAGE_SIZE;
1184         for (i = start_page; i < end_page; i++)
1185                 resmap_free_page(res_map, i);
1186 }
1187
1188 static unsigned long resmap_alloc_region(int mtype, size_t size)
1189 {
1190         unsigned i;
1191         unsigned total;
1192         unsigned start_page;
1193         unsigned long start;
1194         struct resmap *res_map = dispc.res_map[mtype];
1195
1196         BUG_ON(mtype >= DISPC_MEMTYPE_NUM || res_map == NULL || !size);
1197
1198         size = PAGE_ALIGN(size) / PAGE_SIZE;
1199         start_page = 0;
1200         total = 0;
1201         for (i = 0; i < res_map->page_cnt; i++) {
1202                 if (resmap_page_reserved(res_map, i)) {
1203                         start_page = i + 1;
1204                         total = 0;
1205                 } else if (++total == size)
1206                         break;
1207         }
1208         if (total < size)
1209                 return 0;
1210
1211         start = res_map->start + start_page * PAGE_SIZE;
1212         resmap_reserve_region(start, size * PAGE_SIZE);
1213
1214         return start;
1215 }
1216
1217 /* Note that this will only work for user mappings, we don't deal with
1218  * kernel mappings here, so fbcon will keep using the old region.
1219  */
1220 static int omap_dispc_setup_mem(int plane, size_t size, int mem_type,
1221                                 unsigned long *paddr)
1222 {
1223         struct omapfb_mem_region *rg;
1224         unsigned long new_addr = 0;
1225
1226         if ((unsigned)plane > dispc.mem_desc.region_cnt)
1227                 return -EINVAL;
1228         if (mem_type >= DISPC_MEMTYPE_NUM)
1229                 return -EINVAL;
1230         if (dispc.res_map[mem_type] == NULL)
1231                 return -ENOMEM;
1232         rg = &dispc.mem_desc.region[plane];
1233         if (size == rg->size && mem_type == rg->type)
1234                 return 0;
1235         if (atomic_read(&dispc.map_count[plane]))
1236                 return -EBUSY;
1237         if (rg->size != 0)
1238                 resmap_free_region(rg->paddr, rg->size);
1239         if (size != 0) {
1240                 new_addr = resmap_alloc_region(mem_type, size);
1241                 if (!new_addr) {
1242                         /* Reallocate old region. */
1243                         resmap_reserve_region(rg->paddr, rg->size);
1244                         return -ENOMEM;
1245                 }
1246         }
1247         rg->paddr = new_addr;
1248         rg->size = size;
1249         rg->type = mem_type;
1250
1251         *paddr = new_addr;
1252
1253         return 0;
1254 }
1255
1256 static int setup_fbmem(struct omapfb_mem_desc *req_md)
1257 {
1258         struct omapfb_mem_region        *rg;
1259         int i;
1260         int r;
1261         unsigned long                   mem_start[DISPC_MEMTYPE_NUM];
1262         unsigned long                   mem_end[DISPC_MEMTYPE_NUM];
1263
1264         if (!req_md->region_cnt) {
1265                 dev_err(dispc.fbdev->dev, "no memory regions defined\n");
1266                 return -ENOENT;
1267         }
1268
1269         rg = &req_md->region[0];
1270         memset(mem_start, 0xff, sizeof(mem_start));
1271         memset(mem_end, 0, sizeof(mem_end));
1272
1273         for (i = 0; i < req_md->region_cnt; i++, rg++) {
1274                 int mtype;
1275                 if (rg->paddr) {
1276                         rg->alloc = 0;
1277                         if (rg->vaddr == NULL) {
1278                                 rg->map = 1;
1279                                 if ((r = mmap_kern(rg)) < 0)
1280                                         return r;
1281                         }
1282                 } else {
1283                         if (rg->type != OMAPFB_MEMTYPE_SDRAM) {
1284                                 dev_err(dispc.fbdev->dev,
1285                                         "unsupported memory type\n");
1286                                 return -EINVAL;
1287                         }
1288                         rg->alloc = rg->map = 1;
1289                         if ((r = alloc_fbmem(rg)) < 0)
1290                                 return r;
1291                 }
1292                 mtype = rg->type;
1293
1294                 if (rg->paddr < mem_start[mtype])
1295                         mem_start[mtype] = rg->paddr;
1296                 if (rg->paddr + rg->size > mem_end[mtype])
1297                         mem_end[mtype] = rg->paddr + rg->size;
1298         }
1299
1300         for (i = 0; i < DISPC_MEMTYPE_NUM; i++) {
1301                 unsigned long start;
1302                 size_t size;
1303                 if (mem_end[i] == 0)
1304                         continue;
1305                 start = mem_start[i];
1306                 size = mem_end[i] - start;
1307                 dispc.res_map[i] = init_resmap(start, size);
1308                 r = -ENOMEM;
1309                 if (dispc.res_map[i] == NULL)
1310                         goto fail;
1311                 /* Initial state is that everything is reserved. This
1312                  * includes possible holes as well, which will never be
1313                  * freed.
1314                  */
1315                 resmap_reserve_region(start, size);
1316         }
1317
1318         dispc.mem_desc = *req_md;
1319
1320         return 0;
1321 fail:
1322         for (i = 0; i < DISPC_MEMTYPE_NUM; i++) {
1323                 if (dispc.res_map[i] != NULL)
1324                         cleanup_resmap(dispc.res_map[i]);
1325         }
1326         return r;
1327 }
1328
1329 static void cleanup_fbmem(void)
1330 {
1331         struct omapfb_mem_region *rg;
1332         int i;
1333
1334         for (i = 0; i < DISPC_MEMTYPE_NUM; i++) {
1335                 if (dispc.res_map[i] != NULL)
1336                         cleanup_resmap(dispc.res_map[i]);
1337         }
1338         rg = &dispc.mem_desc.region[0];
1339         for (i = 0; i < dispc.mem_desc.region_cnt; i++, rg++) {
1340                 if (rg->alloc)
1341                         free_fbmem(rg);
1342                 else {
1343                         if (rg->map)
1344                                 unmap_kern(rg);
1345                 }
1346         }
1347 }
1348
1349 static int omap_dispc_init(struct omapfb_device *fbdev, int ext_mode,
1350                            struct omapfb_mem_desc *req_vram)
1351 {
1352         int r;
1353         u32 l;
1354         struct lcd_panel *panel = fbdev->panel;
1355         int tmo = 10000;
1356         int skip_init = 0;
1357         int i;
1358
1359         memset(&dispc, 0, sizeof(dispc));
1360
1361         dispc.base = io_p2v(DISPC_BASE);
1362         dispc.fbdev = fbdev;
1363         dispc.ext_mode = ext_mode;
1364
1365         init_completion(&dispc.frame_done);
1366
1367         if ((r = get_dss_clocks()) < 0)
1368                 return r;
1369
1370         enable_interface_clocks(1);
1371         enable_lcd_clocks(1);
1372
1373 #ifdef CONFIG_FB_OMAP_BOOTLOADER_INIT
1374         l = dispc_read_reg(DISPC_CONTROL);
1375         /* LCD enabled ? */
1376         if (l & 1) {
1377                 pr_info("omapfb: skipping hardware initialization\n");
1378                 skip_init = 1;
1379         }
1380 #endif
1381
1382         if (!skip_init) {
1383                 /* Reset monitoring works only w/ the 54M clk */
1384                 enable_digit_clocks(1);
1385
1386                 /* Soft reset */
1387                 MOD_REG_FLD(DISPC_SYSCONFIG, 1 << 1, 1 << 1);
1388
1389                 while (!(dispc_read_reg(DISPC_SYSSTATUS) & 1)) {
1390                         if (!--tmo) {
1391                                 dev_err(dispc.fbdev->dev, "soft reset failed\n");
1392                                 r = -ENODEV;
1393                                 enable_digit_clocks(0);
1394                                 goto fail1;
1395                         }
1396                 }
1397
1398                 enable_digit_clocks(0);
1399         }
1400
1401         /* Enable smart idle and autoidle */
1402         l = dispc_read_reg(DISPC_CONTROL);
1403         l &= ~((3 << 12) | (3 << 3));
1404         l |= (2 << 12) | (2 << 3) | (1 << 0);
1405         dispc_write_reg(DISPC_SYSCONFIG, l);
1406         omap_writel(1 << 0, DSS_BASE + DSS_SYSCONFIG);
1407
1408         /* Set functional clock autogating */
1409         l = dispc_read_reg(DISPC_CONFIG);
1410         l |= 1 << 9;
1411         dispc_write_reg(DISPC_CONFIG, l);
1412
1413         l = dispc_read_reg(DISPC_IRQSTATUS);
1414         dispc_write_reg(l, DISPC_IRQSTATUS);
1415
1416         /* Enable those that we handle always */
1417         omap_dispc_enable_irqs(DISPC_IRQ_FRAMEMASK);
1418
1419         if ((r = request_irq(INT_24XX_DSS_IRQ, omap_dispc_irq_handler,
1420                            0, MODULE_NAME, fbdev)) < 0) {
1421                 dev_err(dispc.fbdev->dev, "can't get DSS IRQ\n");
1422                 goto fail1;
1423         }
1424
1425         /* L3 firewall setting: enable access to OCM RAM */
1426         __raw_writel(0x402000b0, io_p2v(0x680050a0));
1427
1428         if ((r = alloc_palette_ram()) < 0)
1429                 goto fail2;
1430
1431         if ((r = setup_fbmem(req_vram)) < 0)
1432                 goto fail3;
1433
1434         if (!skip_init) {
1435                 for (i = 0; i < dispc.mem_desc.region_cnt; i++) {
1436                         memset(dispc.mem_desc.region[i].vaddr, 0,
1437                                 dispc.mem_desc.region[i].size);
1438                 }
1439
1440                 /* Set logic clock to fck, pixel clock to fck/2 for now */
1441                 MOD_REG_FLD(DISPC_DIVISOR, FLD_MASK(16, 8), 1 << 16);
1442                 MOD_REG_FLD(DISPC_DIVISOR, FLD_MASK(0, 8), 2 << 0);
1443
1444                 setup_plane_fifo(0, ext_mode);
1445                 setup_plane_fifo(1, ext_mode);
1446                 setup_plane_fifo(2, ext_mode);
1447
1448                 setup_color_conv_coef();
1449
1450                 set_lcd_tft_mode(panel->config & OMAP_LCDC_PANEL_TFT);
1451                 set_load_mode(DISPC_LOAD_FRAME_ONLY);
1452
1453                 if (!ext_mode) {
1454                         set_lcd_data_lines(panel->data_lines);
1455                         omap_dispc_set_lcd_size(panel->x_res, panel->y_res);
1456                         set_lcd_timings();
1457                 } else
1458                         set_lcd_data_lines(panel->bpp);
1459                 enable_rfbi_mode(ext_mode);
1460         }
1461
1462         l = dispc_read_reg(DISPC_REVISION);
1463         pr_info("omapfb: DISPC version %d.%d initialized\n",
1464                  l >> 4 & 0x0f, l & 0x0f);
1465         enable_lcd_clocks(0);
1466
1467         return 0;
1468 fail3:
1469         free_palette_ram();
1470 fail2:
1471         free_irq(INT_24XX_DSS_IRQ, fbdev);
1472 fail1:
1473         enable_lcd_clocks(0);
1474         enable_interface_clocks(0);
1475         put_dss_clocks();
1476
1477         return r;
1478 }
1479
1480 static void omap_dispc_cleanup(void)
1481 {
1482         int i;
1483
1484         omap_dispc_set_update_mode(OMAPFB_UPDATE_DISABLED);
1485         /* This will also disable clocks that are on */
1486         for (i = 0; i < dispc.mem_desc.region_cnt; i++)
1487                 omap_dispc_enable_plane(i, 0);
1488         cleanup_fbmem();
1489         free_palette_ram();
1490         free_irq(INT_24XX_DSS_IRQ, dispc.fbdev);
1491         enable_interface_clocks(0);
1492         put_dss_clocks();
1493 }
1494
1495 const struct lcd_ctrl omap2_int_ctrl = {
1496         .name                   = "internal",
1497         .init                   = omap_dispc_init,
1498         .cleanup                = omap_dispc_cleanup,
1499         .get_caps               = omap_dispc_get_caps,
1500         .set_update_mode        = omap_dispc_set_update_mode,
1501         .get_update_mode        = omap_dispc_get_update_mode,
1502         .update_window          = omap_dispc_update_window,
1503         .suspend                = omap_dispc_suspend,
1504         .resume                 = omap_dispc_resume,
1505         .setup_plane            = omap_dispc_setup_plane,
1506         .setup_mem              = omap_dispc_setup_mem,
1507         .set_scale              = omap_dispc_set_scale,
1508         .enable_plane           = omap_dispc_enable_plane,
1509         .set_color_key          = omap_dispc_set_color_key,
1510         .get_color_key          = omap_dispc_get_color_key,
1511         .mmap                   = omap_dispc_mmap_user,
1512 };