2 * OMAP2 display controller support
4 * Copyright (C) 2005 Nokia Corporation
5 * Author: Imre Deak <imre.deak@nokia.com>
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 #include <linux/kernel.h>
22 #include <linux/dma-mapping.h>
24 #include <linux/vmalloc.h>
25 #include <linux/clk.h>
27 #include <linux/platform_device.h>
29 #include <plat/sram.h>
30 #include <plat/board.h>
35 #define MODULE_NAME "dispc"
37 #define DSS_BASE 0x48050000
38 #define DSS_SYSCONFIG 0x0010
40 #define DISPC_BASE 0x48050400
43 #define DISPC_REVISION 0x0000
44 #define DISPC_SYSCONFIG 0x0010
45 #define DISPC_SYSSTATUS 0x0014
46 #define DISPC_IRQSTATUS 0x0018
47 #define DISPC_IRQENABLE 0x001C
48 #define DISPC_CONTROL 0x0040
49 #define DISPC_CONFIG 0x0044
50 #define DISPC_CAPABLE 0x0048
51 #define DISPC_DEFAULT_COLOR0 0x004C
52 #define DISPC_DEFAULT_COLOR1 0x0050
53 #define DISPC_TRANS_COLOR0 0x0054
54 #define DISPC_TRANS_COLOR1 0x0058
55 #define DISPC_LINE_STATUS 0x005C
56 #define DISPC_LINE_NUMBER 0x0060
57 #define DISPC_TIMING_H 0x0064
58 #define DISPC_TIMING_V 0x0068
59 #define DISPC_POL_FREQ 0x006C
60 #define DISPC_DIVISOR 0x0070
61 #define DISPC_SIZE_DIG 0x0078
62 #define DISPC_SIZE_LCD 0x007C
64 #define DISPC_DATA_CYCLE1 0x01D4
65 #define DISPC_DATA_CYCLE2 0x01D8
66 #define DISPC_DATA_CYCLE3 0x01DC
69 #define DISPC_GFX_BA0 0x0080
70 #define DISPC_GFX_BA1 0x0084
71 #define DISPC_GFX_POSITION 0x0088
72 #define DISPC_GFX_SIZE 0x008C
73 #define DISPC_GFX_ATTRIBUTES 0x00A0
74 #define DISPC_GFX_FIFO_THRESHOLD 0x00A4
75 #define DISPC_GFX_FIFO_SIZE_STATUS 0x00A8
76 #define DISPC_GFX_ROW_INC 0x00AC
77 #define DISPC_GFX_PIXEL_INC 0x00B0
78 #define DISPC_GFX_WINDOW_SKIP 0x00B4
79 #define DISPC_GFX_TABLE_BA 0x00B8
81 /* DISPC Video plane 1/2 */
82 #define DISPC_VID1_BASE 0x00BC
83 #define DISPC_VID2_BASE 0x014C
85 /* Offsets into DISPC_VID1/2_BASE */
86 #define DISPC_VID_BA0 0x0000
87 #define DISPC_VID_BA1 0x0004
88 #define DISPC_VID_POSITION 0x0008
89 #define DISPC_VID_SIZE 0x000C
90 #define DISPC_VID_ATTRIBUTES 0x0010
91 #define DISPC_VID_FIFO_THRESHOLD 0x0014
92 #define DISPC_VID_FIFO_SIZE_STATUS 0x0018
93 #define DISPC_VID_ROW_INC 0x001C
94 #define DISPC_VID_PIXEL_INC 0x0020
95 #define DISPC_VID_FIR 0x0024
96 #define DISPC_VID_PICTURE_SIZE 0x0028
97 #define DISPC_VID_ACCU0 0x002C
98 #define DISPC_VID_ACCU1 0x0030
100 /* 8 elements in 8 byte increments */
101 #define DISPC_VID_FIR_COEF_H0 0x0034
102 /* 8 elements in 8 byte increments */
103 #define DISPC_VID_FIR_COEF_HV0 0x0038
104 /* 5 elements in 4 byte increments */
105 #define DISPC_VID_CONV_COEF0 0x0074
107 #define DISPC_IRQ_FRAMEMASK 0x0001
108 #define DISPC_IRQ_VSYNC 0x0002
109 #define DISPC_IRQ_EVSYNC_EVEN 0x0004
110 #define DISPC_IRQ_EVSYNC_ODD 0x0008
111 #define DISPC_IRQ_ACBIAS_COUNT_STAT 0x0010
112 #define DISPC_IRQ_PROG_LINE_NUM 0x0020
113 #define DISPC_IRQ_GFX_FIFO_UNDERFLOW 0x0040
114 #define DISPC_IRQ_GFX_END_WIN 0x0080
115 #define DISPC_IRQ_PAL_GAMMA_MASK 0x0100
116 #define DISPC_IRQ_OCP_ERR 0x0200
117 #define DISPC_IRQ_VID1_FIFO_UNDERFLOW 0x0400
118 #define DISPC_IRQ_VID1_END_WIN 0x0800
119 #define DISPC_IRQ_VID2_FIFO_UNDERFLOW 0x1000
120 #define DISPC_IRQ_VID2_END_WIN 0x2000
121 #define DISPC_IRQ_SYNC_LOST 0x4000
123 #define DISPC_IRQ_MASK_ALL 0x7fff
125 #define DISPC_IRQ_MASK_ERROR (DISPC_IRQ_GFX_FIFO_UNDERFLOW | \
126 DISPC_IRQ_VID1_FIFO_UNDERFLOW | \
127 DISPC_IRQ_VID2_FIFO_UNDERFLOW | \
130 #define RFBI_CONTROL 0x48050040
132 #define MAX_PALETTE_SIZE (256 * 16)
134 #define FLD_MASK(pos, len) (((1 << len) - 1) << pos)
136 #define MOD_REG_FLD(reg, mask, val) \
137 dispc_write_reg((reg), (dispc_read_reg(reg) & ~(mask)) | (val));
139 #define OMAP2_SRAM_START 0x40200000
140 /* Maximum size, in reality this is smaller if SRAM is partially locked. */
141 #define OMAP2_SRAM_SIZE 0xa0000 /* 640k */
143 /* We support the SDRAM / SRAM types. See OMAPFB_PLANE_MEMTYPE_* in omapfb.h */
144 #define DISPC_MEMTYPE_NUM 2
146 #define RESMAP_SIZE(_page_cnt) \
147 ((_page_cnt + (sizeof(unsigned long) * 8) - 1) / 8)
148 #define RESMAP_PTR(_res_map, _page_nr) \
149 (((_res_map)->map) + (_page_nr) / (sizeof(unsigned long) * 8))
150 #define RESMAP_MASK(_page_nr) \
151 (1 << ((_page_nr) & (sizeof(unsigned long) * 8 - 1)))
159 #define MAX_IRQ_HANDLERS 4
164 struct omapfb_mem_desc mem_desc
;
165 struct resmap
*res_map
[DISPC_MEMTYPE_NUM
];
166 atomic_t map_count
[OMAPFB_PLANE_NUM
];
168 dma_addr_t palette_paddr
;
175 void (*callback
)(void *);
177 } irq_handlers
[MAX_IRQ_HANDLERS
];
178 struct completion frame_done
;
180 int fir_hinc
[OMAPFB_PLANE_NUM
];
181 int fir_vinc
[OMAPFB_PLANE_NUM
];
183 struct clk
*dss_ick
, *dss1_fck
;
184 struct clk
*dss_54m_fck
;
186 enum omapfb_update_mode update_mode
;
187 struct omapfb_device
*fbdev
;
189 struct omapfb_color_key color_key
;
192 static struct platform_device omapdss_device
= {
197 static void enable_lcd_clocks(int enable
);
199 static void inline dispc_write_reg(int idx
, u32 val
)
201 __raw_writel(val
, dispc
.base
+ idx
);
204 static u32
inline dispc_read_reg(int idx
)
206 u32 l
= __raw_readl(dispc
.base
+ idx
);
210 /* Select RFBI or bypass mode */
211 static void enable_rfbi_mode(int enable
)
213 void __iomem
*rfbi_control
;
216 l
= dispc_read_reg(DISPC_CONTROL
);
217 /* Enable RFBI, GPIO0/1 */
218 l
&= ~((1 << 11) | (1 << 15) | (1 << 16));
219 l
|= enable
? (1 << 11) : 0;
220 /* RFBI En: GPIO0/1=10 RFBI Dis: GPIO0/1=11 */
222 l
|= enable
? 0 : (1 << 16);
223 dispc_write_reg(DISPC_CONTROL
, l
);
225 /* Set bypass mode in RFBI module */
226 rfbi_control
= ioremap(RFBI_CONTROL
, SZ_1K
);
228 pr_err("Unable to ioremap rfbi_control\n");
231 l
= __raw_readl(rfbi_control
);
232 l
|= enable
? 0 : (1 << 1);
233 __raw_writel(l
, rfbi_control
);
234 iounmap(rfbi_control
);
237 static void set_lcd_data_lines(int data_lines
)
242 switch (data_lines
) {
259 l
= dispc_read_reg(DISPC_CONTROL
);
262 dispc_write_reg(DISPC_CONTROL
, l
);
265 static void set_load_mode(int mode
)
267 BUG_ON(mode
& ~(DISPC_LOAD_CLUT_ONLY
| DISPC_LOAD_FRAME_ONLY
|
268 DISPC_LOAD_CLUT_ONCE_FRAME
));
269 MOD_REG_FLD(DISPC_CONFIG
, 0x03 << 1, mode
<< 1);
272 void omap_dispc_set_lcd_size(int x
, int y
)
274 BUG_ON((x
> (1 << 11)) || (y
> (1 << 11)));
275 enable_lcd_clocks(1);
276 MOD_REG_FLD(DISPC_SIZE_LCD
, FLD_MASK(16, 11) | FLD_MASK(0, 11),
277 ((y
- 1) << 16) | (x
- 1));
278 enable_lcd_clocks(0);
280 EXPORT_SYMBOL(omap_dispc_set_lcd_size
);
282 void omap_dispc_set_digit_size(int x
, int y
)
284 BUG_ON((x
> (1 << 11)) || (y
> (1 << 11)));
285 enable_lcd_clocks(1);
286 MOD_REG_FLD(DISPC_SIZE_DIG
, FLD_MASK(16, 11) | FLD_MASK(0, 11),
287 ((y
- 1) << 16) | (x
- 1));
288 enable_lcd_clocks(0);
290 EXPORT_SYMBOL(omap_dispc_set_digit_size
);
292 static void setup_plane_fifo(int plane
, int ext_mode
)
294 const u32 ftrs_reg
[] = { DISPC_GFX_FIFO_THRESHOLD
,
295 DISPC_VID1_BASE
+ DISPC_VID_FIFO_THRESHOLD
,
296 DISPC_VID2_BASE
+ DISPC_VID_FIFO_THRESHOLD
};
297 const u32 fsz_reg
[] = { DISPC_GFX_FIFO_SIZE_STATUS
,
298 DISPC_VID1_BASE
+ DISPC_VID_FIFO_SIZE_STATUS
,
299 DISPC_VID2_BASE
+ DISPC_VID_FIFO_SIZE_STATUS
};
305 l
= dispc_read_reg(fsz_reg
[plane
]);
306 l
&= FLD_MASK(0, 11);
314 MOD_REG_FLD(ftrs_reg
[plane
], FLD_MASK(16, 12) | FLD_MASK(0, 12),
318 void omap_dispc_enable_lcd_out(int enable
)
320 enable_lcd_clocks(1);
321 MOD_REG_FLD(DISPC_CONTROL
, 1, enable
? 1 : 0);
322 enable_lcd_clocks(0);
324 EXPORT_SYMBOL(omap_dispc_enable_lcd_out
);
326 void omap_dispc_enable_digit_out(int enable
)
328 enable_lcd_clocks(1);
329 MOD_REG_FLD(DISPC_CONTROL
, 1 << 1, enable
? 1 << 1 : 0);
330 enable_lcd_clocks(0);
332 EXPORT_SYMBOL(omap_dispc_enable_digit_out
);
334 static inline int _setup_plane(int plane
, int channel_out
,
335 u32 paddr
, int screen_width
,
336 int pos_x
, int pos_y
, int width
, int height
,
339 const u32 at_reg
[] = { DISPC_GFX_ATTRIBUTES
,
340 DISPC_VID1_BASE
+ DISPC_VID_ATTRIBUTES
,
341 DISPC_VID2_BASE
+ DISPC_VID_ATTRIBUTES
};
342 const u32 ba_reg
[] = { DISPC_GFX_BA0
, DISPC_VID1_BASE
+ DISPC_VID_BA0
,
343 DISPC_VID2_BASE
+ DISPC_VID_BA0
};
344 const u32 ps_reg
[] = { DISPC_GFX_POSITION
,
345 DISPC_VID1_BASE
+ DISPC_VID_POSITION
,
346 DISPC_VID2_BASE
+ DISPC_VID_POSITION
};
347 const u32 sz_reg
[] = { DISPC_GFX_SIZE
,
348 DISPC_VID1_BASE
+ DISPC_VID_PICTURE_SIZE
,
349 DISPC_VID2_BASE
+ DISPC_VID_PICTURE_SIZE
};
350 const u32 ri_reg
[] = { DISPC_GFX_ROW_INC
,
351 DISPC_VID1_BASE
+ DISPC_VID_ROW_INC
,
352 DISPC_VID2_BASE
+ DISPC_VID_ROW_INC
};
353 const u32 vs_reg
[] = { 0, DISPC_VID1_BASE
+ DISPC_VID_SIZE
,
354 DISPC_VID2_BASE
+ DISPC_VID_SIZE
};
356 int chout_shift
, burst_shift
;
365 dev_dbg(dispc
.fbdev
->dev
, "plane %d channel %d paddr %#08x scr_width %d"
366 " pos_x %d pos_y %d width %d height %d color_mode %d\n",
367 plane
, channel_out
, paddr
, screen_width
, pos_x
, pos_y
,
368 width
, height
, color_mode
);
373 case OMAPFB_PLANE_GFX
:
377 case OMAPFB_PLANE_VID1
:
378 case OMAPFB_PLANE_VID2
:
387 switch (channel_out
) {
388 case OMAPFB_CHANNEL_OUT_LCD
:
391 case OMAPFB_CHANNEL_OUT_DIGIT
:
399 switch (color_mode
) {
400 case OMAPFB_COLOR_RGB565
:
401 color_code
= DISPC_RGB_16_BPP
;
404 case OMAPFB_COLOR_YUV422
:
407 color_code
= DISPC_UYVY_422
;
411 case OMAPFB_COLOR_YUY422
:
414 color_code
= DISPC_YUV2_422
;
422 l
= dispc_read_reg(at_reg
[plane
]);
425 l
|= color_code
<< 1;
429 l
&= ~(0x03 << burst_shift
);
430 l
|= DISPC_BURST_8x32
<< burst_shift
;
432 l
&= ~(1 << chout_shift
);
433 l
|= chout_val
<< chout_shift
;
435 dispc_write_reg(at_reg
[plane
], l
);
437 dispc_write_reg(ba_reg
[plane
], paddr
);
438 MOD_REG_FLD(ps_reg
[plane
],
439 FLD_MASK(16, 11) | FLD_MASK(0, 11), (pos_y
<< 16) | pos_x
);
441 MOD_REG_FLD(sz_reg
[plane
], FLD_MASK(16, 11) | FLD_MASK(0, 11),
442 ((height
- 1) << 16) | (width
- 1));
445 /* Set video size if set_scale hasn't set it */
446 if (!dispc
.fir_vinc
[plane
])
447 MOD_REG_FLD(vs_reg
[plane
],
448 FLD_MASK(16, 11), (height
- 1) << 16);
449 if (!dispc
.fir_hinc
[plane
])
450 MOD_REG_FLD(vs_reg
[plane
],
451 FLD_MASK(0, 11), width
- 1);
454 dispc_write_reg(ri_reg
[plane
], (screen_width
- width
) * bpp
/ 8 + 1);
456 return height
* screen_width
* bpp
/ 8;
459 static int omap_dispc_setup_plane(int plane
, int channel_out
,
460 unsigned long offset
,
462 int pos_x
, int pos_y
, int width
, int height
,
468 if ((unsigned)plane
> dispc
.mem_desc
.region_cnt
)
470 paddr
= dispc
.mem_desc
.region
[plane
].paddr
+ offset
;
471 enable_lcd_clocks(1);
472 r
= _setup_plane(plane
, channel_out
, paddr
,
474 pos_x
, pos_y
, width
, height
, color_mode
);
475 enable_lcd_clocks(0);
479 static void write_firh_reg(int plane
, int reg
, u32 value
)
484 base
= DISPC_VID1_BASE
+ DISPC_VID_FIR_COEF_H0
;
486 base
= DISPC_VID2_BASE
+ DISPC_VID_FIR_COEF_H0
;
487 dispc_write_reg(base
+ reg
* 8, value
);
490 static void write_firhv_reg(int plane
, int reg
, u32 value
)
495 base
= DISPC_VID1_BASE
+ DISPC_VID_FIR_COEF_HV0
;
497 base
= DISPC_VID2_BASE
+ DISPC_VID_FIR_COEF_HV0
;
498 dispc_write_reg(base
+ reg
* 8, value
);
501 static void set_upsampling_coef_table(int plane
)
503 const u32 coef
[][2] = {
504 { 0x00800000, 0x00800000 },
505 { 0x0D7CF800, 0x037B02FF },
506 { 0x1E70F5FF, 0x0C6F05FE },
507 { 0x335FF5FE, 0x205907FB },
508 { 0xF74949F7, 0x00404000 },
509 { 0xF55F33FB, 0x075920FE },
510 { 0xF5701EFE, 0x056F0CFF },
511 { 0xF87C0DFF, 0x027B0300 },
515 for (i
= 0; i
< 8; i
++) {
516 write_firh_reg(plane
, i
, coef
[i
][0]);
517 write_firhv_reg(plane
, i
, coef
[i
][1]);
521 static int omap_dispc_set_scale(int plane
,
522 int orig_width
, int orig_height
,
523 int out_width
, int out_height
)
525 const u32 at_reg
[] = { 0, DISPC_VID1_BASE
+ DISPC_VID_ATTRIBUTES
,
526 DISPC_VID2_BASE
+ DISPC_VID_ATTRIBUTES
};
527 const u32 vs_reg
[] = { 0, DISPC_VID1_BASE
+ DISPC_VID_SIZE
,
528 DISPC_VID2_BASE
+ DISPC_VID_SIZE
};
529 const u32 fir_reg
[] = { 0, DISPC_VID1_BASE
+ DISPC_VID_FIR
,
530 DISPC_VID2_BASE
+ DISPC_VID_FIR
};
536 if ((unsigned)plane
> OMAPFB_PLANE_NUM
)
539 if (plane
== OMAPFB_PLANE_GFX
&&
540 (out_width
!= orig_width
|| out_height
!= orig_height
))
543 enable_lcd_clocks(1);
544 if (orig_width
< out_width
) {
547 * Currently you can only scale both dimensions in one way.
549 if (orig_height
> out_height
||
550 orig_width
* 8 < out_width
||
551 orig_height
* 8 < out_height
) {
552 enable_lcd_clocks(0);
555 set_upsampling_coef_table(plane
);
556 } else if (orig_width
> out_width
) {
557 /* Downsampling not yet supported
560 enable_lcd_clocks(0);
563 if (!orig_width
|| orig_width
== out_width
)
566 fir_hinc
= 1024 * orig_width
/ out_width
;
567 if (!orig_height
|| orig_height
== out_height
)
570 fir_vinc
= 1024 * orig_height
/ out_height
;
571 dispc
.fir_hinc
[plane
] = fir_hinc
;
572 dispc
.fir_vinc
[plane
] = fir_vinc
;
574 MOD_REG_FLD(fir_reg
[plane
],
575 FLD_MASK(16, 12) | FLD_MASK(0, 12),
576 ((fir_vinc
& 4095) << 16) |
579 dev_dbg(dispc
.fbdev
->dev
, "out_width %d out_height %d orig_width %d "
580 "orig_height %d fir_hinc %d fir_vinc %d\n",
581 out_width
, out_height
, orig_width
, orig_height
,
584 MOD_REG_FLD(vs_reg
[plane
],
585 FLD_MASK(16, 11) | FLD_MASK(0, 11),
586 ((out_height
- 1) << 16) | (out_width
- 1));
588 l
= dispc_read_reg(at_reg
[plane
]);
590 l
|= fir_hinc
? (1 << 5) : 0;
591 l
|= fir_vinc
? (1 << 6) : 0;
592 dispc_write_reg(at_reg
[plane
], l
);
594 enable_lcd_clocks(0);
598 static int omap_dispc_enable_plane(int plane
, int enable
)
600 const u32 at_reg
[] = { DISPC_GFX_ATTRIBUTES
,
601 DISPC_VID1_BASE
+ DISPC_VID_ATTRIBUTES
,
602 DISPC_VID2_BASE
+ DISPC_VID_ATTRIBUTES
};
603 if ((unsigned int)plane
> dispc
.mem_desc
.region_cnt
)
606 enable_lcd_clocks(1);
607 MOD_REG_FLD(at_reg
[plane
], 1, enable
? 1 : 0);
608 enable_lcd_clocks(0);
613 static int omap_dispc_set_color_key(struct omapfb_color_key
*ck
)
618 switch (ck
->channel_out
) {
619 case OMAPFB_CHANNEL_OUT_LCD
:
620 df_reg
= DISPC_DEFAULT_COLOR0
;
621 tr_reg
= DISPC_TRANS_COLOR0
;
624 case OMAPFB_CHANNEL_OUT_DIGIT
:
625 df_reg
= DISPC_DEFAULT_COLOR1
;
626 tr_reg
= DISPC_TRANS_COLOR1
;
632 switch (ck
->key_type
) {
633 case OMAPFB_COLOR_KEY_DISABLED
:
636 case OMAPFB_COLOR_KEY_GFX_DST
:
639 case OMAPFB_COLOR_KEY_VID_SRC
:
645 enable_lcd_clocks(1);
646 MOD_REG_FLD(DISPC_CONFIG
, FLD_MASK(shift
, 2), val
<< shift
);
649 dispc_write_reg(tr_reg
, ck
->trans_key
);
650 dispc_write_reg(df_reg
, ck
->background
);
651 enable_lcd_clocks(0);
653 dispc
.color_key
= *ck
;
658 static int omap_dispc_get_color_key(struct omapfb_color_key
*ck
)
660 *ck
= dispc
.color_key
;
664 static void load_palette(void)
668 static int omap_dispc_set_update_mode(enum omapfb_update_mode mode
)
672 if (mode
!= dispc
.update_mode
) {
674 case OMAPFB_AUTO_UPDATE
:
675 case OMAPFB_MANUAL_UPDATE
:
676 enable_lcd_clocks(1);
677 omap_dispc_enable_lcd_out(1);
678 dispc
.update_mode
= mode
;
680 case OMAPFB_UPDATE_DISABLED
:
681 init_completion(&dispc
.frame_done
);
682 omap_dispc_enable_lcd_out(0);
683 if (!wait_for_completion_timeout(&dispc
.frame_done
,
684 msecs_to_jiffies(500))) {
685 dev_err(dispc
.fbdev
->dev
,
686 "timeout waiting for FRAME DONE\n");
688 dispc
.update_mode
= mode
;
689 enable_lcd_clocks(0);
699 static void omap_dispc_get_caps(int plane
, struct omapfb_caps
*caps
)
701 caps
->ctrl
|= OMAPFB_CAPS_PLANE_RELOCATE_MEM
;
703 caps
->ctrl
|= OMAPFB_CAPS_PLANE_SCALE
;
704 caps
->plane_color
|= (1 << OMAPFB_COLOR_RGB565
) |
705 (1 << OMAPFB_COLOR_YUV422
) |
706 (1 << OMAPFB_COLOR_YUY422
);
708 caps
->plane_color
|= (1 << OMAPFB_COLOR_CLUT_8BPP
) |
709 (1 << OMAPFB_COLOR_CLUT_4BPP
) |
710 (1 << OMAPFB_COLOR_CLUT_2BPP
) |
711 (1 << OMAPFB_COLOR_CLUT_1BPP
) |
712 (1 << OMAPFB_COLOR_RGB444
);
715 static enum omapfb_update_mode
omap_dispc_get_update_mode(void)
717 return dispc
.update_mode
;
720 static void setup_color_conv_coef(void)
722 u32 mask
= FLD_MASK(16, 11) | FLD_MASK(0, 11);
723 int cf1_reg
= DISPC_VID1_BASE
+ DISPC_VID_CONV_COEF0
;
724 int cf2_reg
= DISPC_VID2_BASE
+ DISPC_VID_CONV_COEF0
;
725 int at1_reg
= DISPC_VID1_BASE
+ DISPC_VID_ATTRIBUTES
;
726 int at2_reg
= DISPC_VID2_BASE
+ DISPC_VID_ATTRIBUTES
;
727 const struct color_conv_coef
{
728 int ry
, rcr
, rcb
, gy
, gcr
, gcb
, by
, bcr
, bcb
;
731 298, 409, 0, 298, -208, -100, 298, 0, 517, 0,
733 const struct color_conv_coef
*ct
;
734 #define CVAL(x, y) (((x & 2047) << 16) | (y & 2047))
738 MOD_REG_FLD(cf1_reg
, mask
, CVAL(ct
->rcr
, ct
->ry
));
739 MOD_REG_FLD(cf1_reg
+ 4, mask
, CVAL(ct
->gy
, ct
->rcb
));
740 MOD_REG_FLD(cf1_reg
+ 8, mask
, CVAL(ct
->gcb
, ct
->gcr
));
741 MOD_REG_FLD(cf1_reg
+ 12, mask
, CVAL(ct
->bcr
, ct
->by
));
742 MOD_REG_FLD(cf1_reg
+ 16, mask
, CVAL(0, ct
->bcb
));
744 MOD_REG_FLD(cf2_reg
, mask
, CVAL(ct
->rcr
, ct
->ry
));
745 MOD_REG_FLD(cf2_reg
+ 4, mask
, CVAL(ct
->gy
, ct
->rcb
));
746 MOD_REG_FLD(cf2_reg
+ 8, mask
, CVAL(ct
->gcb
, ct
->gcr
));
747 MOD_REG_FLD(cf2_reg
+ 12, mask
, CVAL(ct
->bcr
, ct
->by
));
748 MOD_REG_FLD(cf2_reg
+ 16, mask
, CVAL(0, ct
->bcb
));
751 MOD_REG_FLD(at1_reg
, (1 << 11), ct
->full_range
);
752 MOD_REG_FLD(at2_reg
, (1 << 11), ct
->full_range
);
755 static void calc_ck_div(int is_tft
, int pck
, int *lck_div
, int *pck_div
)
757 unsigned long fck
, lck
;
761 fck
= clk_get_rate(dispc
.dss1_fck
);
763 *pck_div
= (lck
+ pck
- 1) / pck
;
765 *pck_div
= max(2, *pck_div
);
767 *pck_div
= max(3, *pck_div
);
768 if (*pck_div
> 255) {
770 lck
= pck
* *pck_div
;
771 *lck_div
= fck
/ lck
;
772 BUG_ON(*lck_div
< 1);
773 if (*lck_div
> 255) {
775 dev_warn(dispc
.fbdev
->dev
, "pixclock %d kHz too low.\n",
781 static void set_lcd_tft_mode(int enable
)
786 MOD_REG_FLD(DISPC_CONTROL
, mask
, enable
? mask
: 0);
789 static void set_lcd_timings(void)
792 int lck_div
, pck_div
;
793 struct lcd_panel
*panel
= dispc
.fbdev
->panel
;
794 int is_tft
= panel
->config
& OMAP_LCDC_PANEL_TFT
;
797 l
= dispc_read_reg(DISPC_TIMING_H
);
798 l
&= ~(FLD_MASK(0, 6) | FLD_MASK(8, 8) | FLD_MASK(20, 8));
799 l
|= ( max(1, (min(64, panel
->hsw
))) - 1 ) << 0;
800 l
|= ( max(1, (min(256, panel
->hfp
))) - 1 ) << 8;
801 l
|= ( max(1, (min(256, panel
->hbp
))) - 1 ) << 20;
802 dispc_write_reg(DISPC_TIMING_H
, l
);
804 l
= dispc_read_reg(DISPC_TIMING_V
);
805 l
&= ~(FLD_MASK(0, 6) | FLD_MASK(8, 8) | FLD_MASK(20, 8));
806 l
|= ( max(1, (min(64, panel
->vsw
))) - 1 ) << 0;
807 l
|= ( max(0, (min(255, panel
->vfp
))) - 0 ) << 8;
808 l
|= ( max(0, (min(255, panel
->vbp
))) - 0 ) << 20;
809 dispc_write_reg(DISPC_TIMING_V
, l
);
811 l
= dispc_read_reg(DISPC_POL_FREQ
);
812 l
&= ~FLD_MASK(12, 6);
813 l
|= (panel
->config
& OMAP_LCDC_SIGNAL_MASK
) << 12;
814 l
|= panel
->acb
& 0xff;
815 dispc_write_reg(DISPC_POL_FREQ
, l
);
817 calc_ck_div(is_tft
, panel
->pixel_clock
* 1000, &lck_div
, &pck_div
);
819 l
= dispc_read_reg(DISPC_DIVISOR
);
820 l
&= ~(FLD_MASK(16, 8) | FLD_MASK(0, 8));
821 l
|= (lck_div
<< 16) | (pck_div
<< 0);
822 dispc_write_reg(DISPC_DIVISOR
, l
);
824 /* update panel info with the exact clock */
825 fck
= clk_get_rate(dispc
.dss1_fck
);
826 panel
->pixel_clock
= fck
/ lck_div
/ pck_div
/ 1000;
829 static void recalc_irq_mask(void)
832 unsigned long irq_mask
= DISPC_IRQ_MASK_ERROR
;
834 for (i
= 0; i
< MAX_IRQ_HANDLERS
; i
++) {
835 if (!dispc
.irq_handlers
[i
].callback
)
838 irq_mask
|= dispc
.irq_handlers
[i
].irq_mask
;
841 enable_lcd_clocks(1);
842 MOD_REG_FLD(DISPC_IRQENABLE
, 0x7fff, irq_mask
);
843 enable_lcd_clocks(0);
846 int omap_dispc_request_irq(unsigned long irq_mask
, void (*callback
)(void *data
),
851 BUG_ON(callback
== NULL
);
853 for (i
= 0; i
< MAX_IRQ_HANDLERS
; i
++) {
854 if (dispc
.irq_handlers
[i
].callback
)
857 dispc
.irq_handlers
[i
].irq_mask
= irq_mask
;
858 dispc
.irq_handlers
[i
].callback
= callback
;
859 dispc
.irq_handlers
[i
].data
= data
;
867 EXPORT_SYMBOL(omap_dispc_request_irq
);
869 void omap_dispc_free_irq(unsigned long irq_mask
, void (*callback
)(void *data
),
874 for (i
= 0; i
< MAX_IRQ_HANDLERS
; i
++) {
875 if (dispc
.irq_handlers
[i
].callback
== callback
&&
876 dispc
.irq_handlers
[i
].data
== data
) {
877 dispc
.irq_handlers
[i
].irq_mask
= 0;
878 dispc
.irq_handlers
[i
].callback
= NULL
;
879 dispc
.irq_handlers
[i
].data
= NULL
;
887 EXPORT_SYMBOL(omap_dispc_free_irq
);
889 static irqreturn_t
omap_dispc_irq_handler(int irq
, void *dev
)
894 enable_lcd_clocks(1);
896 stat
= dispc_read_reg(DISPC_IRQSTATUS
);
897 if (stat
& DISPC_IRQ_FRAMEMASK
)
898 complete(&dispc
.frame_done
);
900 if (stat
& DISPC_IRQ_MASK_ERROR
) {
901 if (printk_ratelimit()) {
902 dev_err(dispc
.fbdev
->dev
, "irq error status %04x\n",
907 for (i
= 0; i
< MAX_IRQ_HANDLERS
; i
++) {
908 if (unlikely(dispc
.irq_handlers
[i
].callback
&&
909 (stat
& dispc
.irq_handlers
[i
].irq_mask
)))
910 dispc
.irq_handlers
[i
].callback(
911 dispc
.irq_handlers
[i
].data
);
914 dispc_write_reg(DISPC_IRQSTATUS
, stat
);
916 enable_lcd_clocks(0);
921 static int get_dss_clocks(void)
923 dispc
.dss_ick
= clk_get(&omapdss_device
.dev
, "ick");
924 if (IS_ERR(dispc
.dss_ick
)) {
925 dev_err(dispc
.fbdev
->dev
, "can't get ick\n");
926 return PTR_ERR(dispc
.dss_ick
);
929 dispc
.dss1_fck
= clk_get(&omapdss_device
.dev
, "dss1_fck");
930 if (IS_ERR(dispc
.dss1_fck
)) {
931 dev_err(dispc
.fbdev
->dev
, "can't get dss1_fck\n");
932 clk_put(dispc
.dss_ick
);
933 return PTR_ERR(dispc
.dss1_fck
);
936 dispc
.dss_54m_fck
= clk_get(&omapdss_device
.dev
, "tv_fck");
937 if (IS_ERR(dispc
.dss_54m_fck
)) {
938 dev_err(dispc
.fbdev
->dev
, "can't get tv_fck\n");
939 clk_put(dispc
.dss_ick
);
940 clk_put(dispc
.dss1_fck
);
941 return PTR_ERR(dispc
.dss_54m_fck
);
947 static void put_dss_clocks(void)
949 clk_put(dispc
.dss_54m_fck
);
950 clk_put(dispc
.dss1_fck
);
951 clk_put(dispc
.dss_ick
);
954 static void enable_lcd_clocks(int enable
)
957 clk_enable(dispc
.dss_ick
);
958 clk_enable(dispc
.dss1_fck
);
960 clk_disable(dispc
.dss1_fck
);
961 clk_disable(dispc
.dss_ick
);
965 static void enable_digit_clocks(int enable
)
968 clk_enable(dispc
.dss_54m_fck
);
970 clk_disable(dispc
.dss_54m_fck
);
973 static void omap_dispc_suspend(void)
975 if (dispc
.update_mode
== OMAPFB_AUTO_UPDATE
) {
976 init_completion(&dispc
.frame_done
);
977 omap_dispc_enable_lcd_out(0);
978 if (!wait_for_completion_timeout(&dispc
.frame_done
,
979 msecs_to_jiffies(500))) {
980 dev_err(dispc
.fbdev
->dev
,
981 "timeout waiting for FRAME DONE\n");
983 enable_lcd_clocks(0);
987 static void omap_dispc_resume(void)
989 if (dispc
.update_mode
== OMAPFB_AUTO_UPDATE
) {
990 enable_lcd_clocks(1);
991 if (!dispc
.ext_mode
) {
995 omap_dispc_enable_lcd_out(1);
1000 static int omap_dispc_update_window(struct fb_info
*fbi
,
1001 struct omapfb_update_window
*win
,
1002 void (*complete_callback
)(void *arg
),
1003 void *complete_callback_data
)
1005 return dispc
.update_mode
== OMAPFB_UPDATE_DISABLED
? -ENODEV
: 0;
1008 static int mmap_kern(struct omapfb_mem_region
*region
)
1010 struct vm_struct
*kvma
;
1011 struct vm_area_struct vma
;
1013 unsigned long vaddr
;
1015 kvma
= get_vm_area(region
->size
, VM_IOREMAP
);
1017 dev_err(dispc
.fbdev
->dev
, "can't get kernel vm area\n");
1020 vma
.vm_mm
= &init_mm
;
1022 vaddr
= (unsigned long)kvma
->addr
;
1024 pgprot
= pgprot_writecombine(pgprot_kernel
);
1025 vma
.vm_start
= vaddr
;
1026 vma
.vm_end
= vaddr
+ region
->size
;
1027 if (io_remap_pfn_range(&vma
, vaddr
, region
->paddr
>> PAGE_SHIFT
,
1028 region
->size
, pgprot
) < 0) {
1029 dev_err(dispc
.fbdev
->dev
, "kernel mmap for FBMEM failed\n");
1032 region
->vaddr
= (void *)vaddr
;
1037 static void mmap_user_open(struct vm_area_struct
*vma
)
1039 int plane
= (int)vma
->vm_private_data
;
1041 atomic_inc(&dispc
.map_count
[plane
]);
1044 static void mmap_user_close(struct vm_area_struct
*vma
)
1046 int plane
= (int)vma
->vm_private_data
;
1048 atomic_dec(&dispc
.map_count
[plane
]);
1051 static const struct vm_operations_struct mmap_user_ops
= {
1052 .open
= mmap_user_open
,
1053 .close
= mmap_user_close
,
1056 static int omap_dispc_mmap_user(struct fb_info
*info
,
1057 struct vm_area_struct
*vma
)
1059 struct omapfb_plane_struct
*plane
= info
->par
;
1061 unsigned long start
;
1064 if (vma
->vm_end
- vma
->vm_start
== 0)
1066 if (vma
->vm_pgoff
> (~0UL >> PAGE_SHIFT
))
1068 off
= vma
->vm_pgoff
<< PAGE_SHIFT
;
1070 start
= info
->fix
.smem_start
;
1071 len
= info
->fix
.smem_len
;
1074 if ((vma
->vm_end
- vma
->vm_start
+ off
) > len
)
1077 vma
->vm_pgoff
= off
>> PAGE_SHIFT
;
1078 vma
->vm_flags
|= VM_IO
| VM_RESERVED
;
1079 vma
->vm_page_prot
= pgprot_writecombine(vma
->vm_page_prot
);
1080 vma
->vm_ops
= &mmap_user_ops
;
1081 vma
->vm_private_data
= (void *)plane
->idx
;
1082 if (io_remap_pfn_range(vma
, vma
->vm_start
, off
>> PAGE_SHIFT
,
1083 vma
->vm_end
- vma
->vm_start
, vma
->vm_page_prot
))
1085 /* vm_ops.open won't be called for mmap itself. */
1086 atomic_inc(&dispc
.map_count
[plane
->idx
]);
1090 static void unmap_kern(struct omapfb_mem_region
*region
)
1092 vunmap(region
->vaddr
);
1095 static int alloc_palette_ram(void)
1097 dispc
.palette_vaddr
= dma_alloc_writecombine(dispc
.fbdev
->dev
,
1098 MAX_PALETTE_SIZE
, &dispc
.palette_paddr
, GFP_KERNEL
);
1099 if (dispc
.palette_vaddr
== NULL
) {
1100 dev_err(dispc
.fbdev
->dev
, "failed to alloc palette memory\n");
1107 static void free_palette_ram(void)
1109 dma_free_writecombine(dispc
.fbdev
->dev
, MAX_PALETTE_SIZE
,
1110 dispc
.palette_vaddr
, dispc
.palette_paddr
);
1113 static int alloc_fbmem(struct omapfb_mem_region
*region
)
1115 region
->vaddr
= dma_alloc_writecombine(dispc
.fbdev
->dev
,
1116 region
->size
, ®ion
->paddr
, GFP_KERNEL
);
1118 if (region
->vaddr
== NULL
) {
1119 dev_err(dispc
.fbdev
->dev
, "unable to allocate FB DMA memory\n");
1126 static void free_fbmem(struct omapfb_mem_region
*region
)
1128 dma_free_writecombine(dispc
.fbdev
->dev
, region
->size
,
1129 region
->vaddr
, region
->paddr
);
1132 static struct resmap
*init_resmap(unsigned long start
, size_t size
)
1135 struct resmap
*res_map
;
1137 page_cnt
= PAGE_ALIGN(size
) / PAGE_SIZE
;
1139 kzalloc(sizeof(struct resmap
) + RESMAP_SIZE(page_cnt
), GFP_KERNEL
);
1140 if (res_map
== NULL
)
1142 res_map
->start
= start
;
1143 res_map
->page_cnt
= page_cnt
;
1144 res_map
->map
= (unsigned long *)(res_map
+ 1);
1148 static void cleanup_resmap(struct resmap
*res_map
)
1153 static inline int resmap_mem_type(unsigned long start
)
1155 if (start
>= OMAP2_SRAM_START
&&
1156 start
< OMAP2_SRAM_START
+ OMAP2_SRAM_SIZE
)
1157 return OMAPFB_MEMTYPE_SRAM
;
1159 return OMAPFB_MEMTYPE_SDRAM
;
1162 static inline int resmap_page_reserved(struct resmap
*res_map
, unsigned page_nr
)
1164 return *RESMAP_PTR(res_map
, page_nr
) & RESMAP_MASK(page_nr
) ? 1 : 0;
1167 static inline void resmap_reserve_page(struct resmap
*res_map
, unsigned page_nr
)
1169 BUG_ON(resmap_page_reserved(res_map
, page_nr
));
1170 *RESMAP_PTR(res_map
, page_nr
) |= RESMAP_MASK(page_nr
);
1173 static inline void resmap_free_page(struct resmap
*res_map
, unsigned page_nr
)
1175 BUG_ON(!resmap_page_reserved(res_map
, page_nr
));
1176 *RESMAP_PTR(res_map
, page_nr
) &= ~RESMAP_MASK(page_nr
);
1179 static void resmap_reserve_region(unsigned long start
, size_t size
)
1182 struct resmap
*res_map
;
1183 unsigned start_page
;
1188 mtype
= resmap_mem_type(start
);
1189 res_map
= dispc
.res_map
[mtype
];
1190 dev_dbg(dispc
.fbdev
->dev
, "reserve mem type %d start %08lx size %d\n",
1191 mtype
, start
, size
);
1192 start_page
= (start
- res_map
->start
) / PAGE_SIZE
;
1193 end_page
= start_page
+ PAGE_ALIGN(size
) / PAGE_SIZE
;
1194 for (i
= start_page
; i
< end_page
; i
++)
1195 resmap_reserve_page(res_map
, i
);
1198 static void resmap_free_region(unsigned long start
, size_t size
)
1200 struct resmap
*res_map
;
1201 unsigned start_page
;
1206 mtype
= resmap_mem_type(start
);
1207 res_map
= dispc
.res_map
[mtype
];
1208 dev_dbg(dispc
.fbdev
->dev
, "free mem type %d start %08lx size %d\n",
1209 mtype
, start
, size
);
1210 start_page
= (start
- res_map
->start
) / PAGE_SIZE
;
1211 end_page
= start_page
+ PAGE_ALIGN(size
) / PAGE_SIZE
;
1212 for (i
= start_page
; i
< end_page
; i
++)
1213 resmap_free_page(res_map
, i
);
1216 static unsigned long resmap_alloc_region(int mtype
, size_t size
)
1220 unsigned start_page
;
1221 unsigned long start
;
1222 struct resmap
*res_map
= dispc
.res_map
[mtype
];
1224 BUG_ON(mtype
>= DISPC_MEMTYPE_NUM
|| res_map
== NULL
|| !size
);
1226 size
= PAGE_ALIGN(size
) / PAGE_SIZE
;
1229 for (i
= 0; i
< res_map
->page_cnt
; i
++) {
1230 if (resmap_page_reserved(res_map
, i
)) {
1233 } else if (++total
== size
)
1239 start
= res_map
->start
+ start_page
* PAGE_SIZE
;
1240 resmap_reserve_region(start
, size
* PAGE_SIZE
);
1245 /* Note that this will only work for user mappings, we don't deal with
1246 * kernel mappings here, so fbcon will keep using the old region.
1248 static int omap_dispc_setup_mem(int plane
, size_t size
, int mem_type
,
1249 unsigned long *paddr
)
1251 struct omapfb_mem_region
*rg
;
1252 unsigned long new_addr
= 0;
1254 if ((unsigned)plane
> dispc
.mem_desc
.region_cnt
)
1256 if (mem_type
>= DISPC_MEMTYPE_NUM
)
1258 if (dispc
.res_map
[mem_type
] == NULL
)
1260 rg
= &dispc
.mem_desc
.region
[plane
];
1261 if (size
== rg
->size
&& mem_type
== rg
->type
)
1263 if (atomic_read(&dispc
.map_count
[plane
]))
1266 resmap_free_region(rg
->paddr
, rg
->size
);
1268 new_addr
= resmap_alloc_region(mem_type
, size
);
1270 /* Reallocate old region. */
1271 resmap_reserve_region(rg
->paddr
, rg
->size
);
1275 rg
->paddr
= new_addr
;
1277 rg
->type
= mem_type
;
1284 static int setup_fbmem(struct omapfb_mem_desc
*req_md
)
1286 struct omapfb_mem_region
*rg
;
1289 unsigned long mem_start
[DISPC_MEMTYPE_NUM
];
1290 unsigned long mem_end
[DISPC_MEMTYPE_NUM
];
1292 if (!req_md
->region_cnt
) {
1293 dev_err(dispc
.fbdev
->dev
, "no memory regions defined\n");
1297 rg
= &req_md
->region
[0];
1298 memset(mem_start
, 0xff, sizeof(mem_start
));
1299 memset(mem_end
, 0, sizeof(mem_end
));
1301 for (i
= 0; i
< req_md
->region_cnt
; i
++, rg
++) {
1305 if (rg
->vaddr
== NULL
) {
1307 if ((r
= mmap_kern(rg
)) < 0)
1311 if (rg
->type
!= OMAPFB_MEMTYPE_SDRAM
) {
1312 dev_err(dispc
.fbdev
->dev
,
1313 "unsupported memory type\n");
1316 rg
->alloc
= rg
->map
= 1;
1317 if ((r
= alloc_fbmem(rg
)) < 0)
1322 if (rg
->paddr
< mem_start
[mtype
])
1323 mem_start
[mtype
] = rg
->paddr
;
1324 if (rg
->paddr
+ rg
->size
> mem_end
[mtype
])
1325 mem_end
[mtype
] = rg
->paddr
+ rg
->size
;
1328 for (i
= 0; i
< DISPC_MEMTYPE_NUM
; i
++) {
1329 unsigned long start
;
1331 if (mem_end
[i
] == 0)
1333 start
= mem_start
[i
];
1334 size
= mem_end
[i
] - start
;
1335 dispc
.res_map
[i
] = init_resmap(start
, size
);
1337 if (dispc
.res_map
[i
] == NULL
)
1339 /* Initial state is that everything is reserved. This
1340 * includes possible holes as well, which will never be
1343 resmap_reserve_region(start
, size
);
1346 dispc
.mem_desc
= *req_md
;
1350 for (i
= 0; i
< DISPC_MEMTYPE_NUM
; i
++) {
1351 if (dispc
.res_map
[i
] != NULL
)
1352 cleanup_resmap(dispc
.res_map
[i
]);
1357 static void cleanup_fbmem(void)
1359 struct omapfb_mem_region
*rg
;
1362 for (i
= 0; i
< DISPC_MEMTYPE_NUM
; i
++) {
1363 if (dispc
.res_map
[i
] != NULL
)
1364 cleanup_resmap(dispc
.res_map
[i
]);
1366 rg
= &dispc
.mem_desc
.region
[0];
1367 for (i
= 0; i
< dispc
.mem_desc
.region_cnt
; i
++, rg
++) {
1377 static int omap_dispc_init(struct omapfb_device
*fbdev
, int ext_mode
,
1378 struct omapfb_mem_desc
*req_vram
)
1382 struct lcd_panel
*panel
= fbdev
->panel
;
1383 void __iomem
*ram_fw_base
;
1388 r
= platform_device_register(&omapdss_device
);
1390 dev_err(fbdev
->dev
, "can't register omapdss device\n");
1394 memset(&dispc
, 0, sizeof(dispc
));
1396 dispc
.base
= ioremap(DISPC_BASE
, SZ_1K
);
1398 dev_err(fbdev
->dev
, "can't ioremap DISPC\n");
1402 dispc
.fbdev
= fbdev
;
1403 dispc
.ext_mode
= ext_mode
;
1405 init_completion(&dispc
.frame_done
);
1407 if ((r
= get_dss_clocks()) < 0)
1410 enable_lcd_clocks(1);
1412 #ifdef CONFIG_FB_OMAP_BOOTLOADER_INIT
1413 l
= dispc_read_reg(DISPC_CONTROL
);
1416 pr_info("omapfb: skipping hardware initialization\n");
1422 /* Reset monitoring works only w/ the 54M clk */
1423 enable_digit_clocks(1);
1426 MOD_REG_FLD(DISPC_SYSCONFIG
, 1 << 1, 1 << 1);
1428 while (!(dispc_read_reg(DISPC_SYSSTATUS
) & 1)) {
1430 dev_err(dispc
.fbdev
->dev
, "soft reset failed\n");
1432 enable_digit_clocks(0);
1437 enable_digit_clocks(0);
1440 /* Enable smart standby/idle, autoidle and wakeup */
1441 l
= dispc_read_reg(DISPC_SYSCONFIG
);
1442 l
&= ~((3 << 12) | (3 << 3));
1443 l
|= (2 << 12) | (2 << 3) | (1 << 2) | (1 << 0);
1444 dispc_write_reg(DISPC_SYSCONFIG
, l
);
1445 omap_writel(1 << 0, DSS_BASE
+ DSS_SYSCONFIG
);
1447 /* Set functional clock autogating */
1448 l
= dispc_read_reg(DISPC_CONFIG
);
1450 dispc_write_reg(DISPC_CONFIG
, l
);
1452 l
= dispc_read_reg(DISPC_IRQSTATUS
);
1453 dispc_write_reg(DISPC_IRQSTATUS
, l
);
1457 if ((r
= request_irq(INT_24XX_DSS_IRQ
, omap_dispc_irq_handler
,
1458 0, MODULE_NAME
, fbdev
)) < 0) {
1459 dev_err(dispc
.fbdev
->dev
, "can't get DSS IRQ\n");
1463 /* L3 firewall setting: enable access to OCM RAM */
1464 ram_fw_base
= ioremap(0x68005000, SZ_1K
);
1466 dev_err(dispc
.fbdev
->dev
, "Cannot ioremap to enable OCM RAM\n");
1469 __raw_writel(0x402000b0, ram_fw_base
+ 0xa0);
1470 iounmap(ram_fw_base
);
1472 if ((r
= alloc_palette_ram()) < 0)
1475 if ((r
= setup_fbmem(req_vram
)) < 0)
1479 for (i
= 0; i
< dispc
.mem_desc
.region_cnt
; i
++) {
1480 memset(dispc
.mem_desc
.region
[i
].vaddr
, 0,
1481 dispc
.mem_desc
.region
[i
].size
);
1484 /* Set logic clock to fck, pixel clock to fck/2 for now */
1485 MOD_REG_FLD(DISPC_DIVISOR
, FLD_MASK(16, 8), 1 << 16);
1486 MOD_REG_FLD(DISPC_DIVISOR
, FLD_MASK(0, 8), 2 << 0);
1488 setup_plane_fifo(0, ext_mode
);
1489 setup_plane_fifo(1, ext_mode
);
1490 setup_plane_fifo(2, ext_mode
);
1492 setup_color_conv_coef();
1494 set_lcd_tft_mode(panel
->config
& OMAP_LCDC_PANEL_TFT
);
1495 set_load_mode(DISPC_LOAD_FRAME_ONLY
);
1498 set_lcd_data_lines(panel
->data_lines
);
1499 omap_dispc_set_lcd_size(panel
->x_res
, panel
->y_res
);
1502 set_lcd_data_lines(panel
->bpp
);
1503 enable_rfbi_mode(ext_mode
);
1506 l
= dispc_read_reg(DISPC_REVISION
);
1507 pr_info("omapfb: DISPC version %d.%d initialized\n",
1508 l
>> 4 & 0x0f, l
& 0x0f);
1509 enable_lcd_clocks(0);
1515 free_irq(INT_24XX_DSS_IRQ
, fbdev
);
1517 enable_lcd_clocks(0);
1520 iounmap(dispc
.base
);
1524 static void omap_dispc_cleanup(void)
1528 omap_dispc_set_update_mode(OMAPFB_UPDATE_DISABLED
);
1529 /* This will also disable clocks that are on */
1530 for (i
= 0; i
< dispc
.mem_desc
.region_cnt
; i
++)
1531 omap_dispc_enable_plane(i
, 0);
1534 free_irq(INT_24XX_DSS_IRQ
, dispc
.fbdev
);
1536 iounmap(dispc
.base
);
1537 platform_device_unregister(&omapdss_device
);
1540 const struct lcd_ctrl omap2_int_ctrl
= {
1542 .init
= omap_dispc_init
,
1543 .cleanup
= omap_dispc_cleanup
,
1544 .get_caps
= omap_dispc_get_caps
,
1545 .set_update_mode
= omap_dispc_set_update_mode
,
1546 .get_update_mode
= omap_dispc_get_update_mode
,
1547 .update_window
= omap_dispc_update_window
,
1548 .suspend
= omap_dispc_suspend
,
1549 .resume
= omap_dispc_resume
,
1550 .setup_plane
= omap_dispc_setup_plane
,
1551 .setup_mem
= omap_dispc_setup_mem
,
1552 .set_scale
= omap_dispc_set_scale
,
1553 .enable_plane
= omap_dispc_enable_plane
,
1554 .set_color_key
= omap_dispc_set_color_key
,
1555 .get_color_key
= omap_dispc_get_color_key
,
1556 .mmap
= omap_dispc_mmap_user
,