2 * linux/drivers/video/omap2/dss/dispc.c
4 * Copyright (C) 2009 Nokia Corporation
5 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
7 * Some code and ideas taken from drivers/video/omap/ driver
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License version 2 as published by
12 * the Free Software Foundation.
14 * This program is distributed in the hope that it will be useful, but WITHOUT
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
19 * You should have received a copy of the GNU General Public License along with
20 * this program. If not, see <http://www.gnu.org/licenses/>.
23 #define DSS_SUBSYS_NAME "DISPC"
25 #include <linux/kernel.h>
26 #include <linux/dma-mapping.h>
27 #include <linux/vmalloc.h>
28 #include <linux/clk.h>
30 #include <linux/jiffies.h>
31 #include <linux/seq_file.h>
32 #include <linux/delay.h>
33 #include <linux/workqueue.h>
35 #include <plat/sram.h>
36 #include <plat/clock.h>
38 #include <plat/display.h>
43 #define DISPC_BASE 0x48050400
45 #define DISPC_SZ_REGS SZ_1K
47 struct dispc_reg
{ u16 idx
; };
49 #define DISPC_REG(idx) ((const struct dispc_reg) { idx })
52 #define DISPC_REVISION DISPC_REG(0x0000)
53 #define DISPC_SYSCONFIG DISPC_REG(0x0010)
54 #define DISPC_SYSSTATUS DISPC_REG(0x0014)
55 #define DISPC_IRQSTATUS DISPC_REG(0x0018)
56 #define DISPC_IRQENABLE DISPC_REG(0x001C)
57 #define DISPC_CONTROL DISPC_REG(0x0040)
58 #define DISPC_CONFIG DISPC_REG(0x0044)
59 #define DISPC_CAPABLE DISPC_REG(0x0048)
60 #define DISPC_DEFAULT_COLOR0 DISPC_REG(0x004C)
61 #define DISPC_DEFAULT_COLOR1 DISPC_REG(0x0050)
62 #define DISPC_TRANS_COLOR0 DISPC_REG(0x0054)
63 #define DISPC_TRANS_COLOR1 DISPC_REG(0x0058)
64 #define DISPC_LINE_STATUS DISPC_REG(0x005C)
65 #define DISPC_LINE_NUMBER DISPC_REG(0x0060)
66 #define DISPC_TIMING_H DISPC_REG(0x0064)
67 #define DISPC_TIMING_V DISPC_REG(0x0068)
68 #define DISPC_POL_FREQ DISPC_REG(0x006C)
69 #define DISPC_DIVISOR DISPC_REG(0x0070)
70 #define DISPC_GLOBAL_ALPHA DISPC_REG(0x0074)
71 #define DISPC_SIZE_DIG DISPC_REG(0x0078)
72 #define DISPC_SIZE_LCD DISPC_REG(0x007C)
75 #define DISPC_GFX_BA0 DISPC_REG(0x0080)
76 #define DISPC_GFX_BA1 DISPC_REG(0x0084)
77 #define DISPC_GFX_POSITION DISPC_REG(0x0088)
78 #define DISPC_GFX_SIZE DISPC_REG(0x008C)
79 #define DISPC_GFX_ATTRIBUTES DISPC_REG(0x00A0)
80 #define DISPC_GFX_FIFO_THRESHOLD DISPC_REG(0x00A4)
81 #define DISPC_GFX_FIFO_SIZE_STATUS DISPC_REG(0x00A8)
82 #define DISPC_GFX_ROW_INC DISPC_REG(0x00AC)
83 #define DISPC_GFX_PIXEL_INC DISPC_REG(0x00B0)
84 #define DISPC_GFX_WINDOW_SKIP DISPC_REG(0x00B4)
85 #define DISPC_GFX_TABLE_BA DISPC_REG(0x00B8)
87 #define DISPC_DATA_CYCLE1 DISPC_REG(0x01D4)
88 #define DISPC_DATA_CYCLE2 DISPC_REG(0x01D8)
89 #define DISPC_DATA_CYCLE3 DISPC_REG(0x01DC)
91 #define DISPC_CPR_COEF_R DISPC_REG(0x0220)
92 #define DISPC_CPR_COEF_G DISPC_REG(0x0224)
93 #define DISPC_CPR_COEF_B DISPC_REG(0x0228)
95 #define DISPC_GFX_PRELOAD DISPC_REG(0x022C)
97 /* DISPC Video plane, n = 0 for VID1 and n = 1 for VID2 */
98 #define DISPC_VID_REG(n, idx) DISPC_REG(0x00BC + (n)*0x90 + idx)
100 #define DISPC_VID_BA0(n) DISPC_VID_REG(n, 0x0000)
101 #define DISPC_VID_BA1(n) DISPC_VID_REG(n, 0x0004)
102 #define DISPC_VID_POSITION(n) DISPC_VID_REG(n, 0x0008)
103 #define DISPC_VID_SIZE(n) DISPC_VID_REG(n, 0x000C)
104 #define DISPC_VID_ATTRIBUTES(n) DISPC_VID_REG(n, 0x0010)
105 #define DISPC_VID_FIFO_THRESHOLD(n) DISPC_VID_REG(n, 0x0014)
106 #define DISPC_VID_FIFO_SIZE_STATUS(n) DISPC_VID_REG(n, 0x0018)
107 #define DISPC_VID_ROW_INC(n) DISPC_VID_REG(n, 0x001C)
108 #define DISPC_VID_PIXEL_INC(n) DISPC_VID_REG(n, 0x0020)
109 #define DISPC_VID_FIR(n) DISPC_VID_REG(n, 0x0024)
110 #define DISPC_VID_PICTURE_SIZE(n) DISPC_VID_REG(n, 0x0028)
111 #define DISPC_VID_ACCU0(n) DISPC_VID_REG(n, 0x002C)
112 #define DISPC_VID_ACCU1(n) DISPC_VID_REG(n, 0x0030)
114 /* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */
115 #define DISPC_VID_FIR_COEF_H(n, i) DISPC_REG(0x00F0 + (n)*0x90 + (i)*0x8)
116 /* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */
117 #define DISPC_VID_FIR_COEF_HV(n, i) DISPC_REG(0x00F4 + (n)*0x90 + (i)*0x8)
118 /* coef index i = {0, 1, 2, 3, 4} */
119 #define DISPC_VID_CONV_COEF(n, i) DISPC_REG(0x0130 + (n)*0x90 + (i)*0x4)
120 /* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */
121 #define DISPC_VID_FIR_COEF_V(n, i) DISPC_REG(0x01E0 + (n)*0x20 + (i)*0x4)
123 #define DISPC_VID_PRELOAD(n) DISPC_REG(0x230 + (n)*0x04)
126 #define DISPC_IRQ_MASK_ERROR (DISPC_IRQ_GFX_FIFO_UNDERFLOW | \
127 DISPC_IRQ_OCP_ERR | \
128 DISPC_IRQ_VID1_FIFO_UNDERFLOW | \
129 DISPC_IRQ_VID2_FIFO_UNDERFLOW | \
130 DISPC_IRQ_SYNC_LOST | \
131 DISPC_IRQ_SYNC_LOST_DIGIT)
133 #define DISPC_MAX_NR_ISRS 8
135 struct omap_dispc_isr_data
{
136 omap_dispc_isr_t isr
;
141 #define REG_GET(idx, start, end) \
142 FLD_GET(dispc_read_reg(idx), start, end)
144 #define REG_FLD_MOD(idx, val, start, end) \
145 dispc_write_reg(idx, FLD_MOD(dispc_read_reg(idx), val, start, end))
147 static const struct dispc_reg dispc_reg_att
[] = { DISPC_GFX_ATTRIBUTES
,
148 DISPC_VID_ATTRIBUTES(0),
149 DISPC_VID_ATTRIBUTES(1) };
151 struct dispc_irq_stats
{
152 unsigned long last_reset
;
164 struct omap_dispc_isr_data registered_isr
[DISPC_MAX_NR_ISRS
];
166 struct work_struct error_work
;
168 u32 ctx
[DISPC_SZ_REGS
/ sizeof(u32
)];
170 #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
171 spinlock_t irq_stats_lock
;
172 struct dispc_irq_stats irq_stats
;
176 static void _omap_dispc_set_irqs(void);
178 static inline void dispc_write_reg(const struct dispc_reg idx
, u32 val
)
180 __raw_writel(val
, dispc
.base
+ idx
.idx
);
183 static inline u32
dispc_read_reg(const struct dispc_reg idx
)
185 return __raw_readl(dispc
.base
+ idx
.idx
);
189 dispc.ctx[(DISPC_##reg).idx / sizeof(u32)] = dispc_read_reg(DISPC_##reg)
191 dispc_write_reg(DISPC_##reg, dispc.ctx[(DISPC_##reg).idx / sizeof(u32)])
193 void dispc_save_context(void)
195 if (cpu_is_omap24xx())
220 SR(GFX_FIFO_THRESHOLD
);
241 SR(VID_ATTRIBUTES(0));
242 SR(VID_FIFO_THRESHOLD(0));
244 SR(VID_PIXEL_INC(0));
246 SR(VID_PICTURE_SIZE(0));
250 SR(VID_FIR_COEF_H(0, 0));
251 SR(VID_FIR_COEF_H(0, 1));
252 SR(VID_FIR_COEF_H(0, 2));
253 SR(VID_FIR_COEF_H(0, 3));
254 SR(VID_FIR_COEF_H(0, 4));
255 SR(VID_FIR_COEF_H(0, 5));
256 SR(VID_FIR_COEF_H(0, 6));
257 SR(VID_FIR_COEF_H(0, 7));
259 SR(VID_FIR_COEF_HV(0, 0));
260 SR(VID_FIR_COEF_HV(0, 1));
261 SR(VID_FIR_COEF_HV(0, 2));
262 SR(VID_FIR_COEF_HV(0, 3));
263 SR(VID_FIR_COEF_HV(0, 4));
264 SR(VID_FIR_COEF_HV(0, 5));
265 SR(VID_FIR_COEF_HV(0, 6));
266 SR(VID_FIR_COEF_HV(0, 7));
268 SR(VID_CONV_COEF(0, 0));
269 SR(VID_CONV_COEF(0, 1));
270 SR(VID_CONV_COEF(0, 2));
271 SR(VID_CONV_COEF(0, 3));
272 SR(VID_CONV_COEF(0, 4));
274 SR(VID_FIR_COEF_V(0, 0));
275 SR(VID_FIR_COEF_V(0, 1));
276 SR(VID_FIR_COEF_V(0, 2));
277 SR(VID_FIR_COEF_V(0, 3));
278 SR(VID_FIR_COEF_V(0, 4));
279 SR(VID_FIR_COEF_V(0, 5));
280 SR(VID_FIR_COEF_V(0, 6));
281 SR(VID_FIR_COEF_V(0, 7));
290 SR(VID_ATTRIBUTES(1));
291 SR(VID_FIFO_THRESHOLD(1));
293 SR(VID_PIXEL_INC(1));
295 SR(VID_PICTURE_SIZE(1));
299 SR(VID_FIR_COEF_H(1, 0));
300 SR(VID_FIR_COEF_H(1, 1));
301 SR(VID_FIR_COEF_H(1, 2));
302 SR(VID_FIR_COEF_H(1, 3));
303 SR(VID_FIR_COEF_H(1, 4));
304 SR(VID_FIR_COEF_H(1, 5));
305 SR(VID_FIR_COEF_H(1, 6));
306 SR(VID_FIR_COEF_H(1, 7));
308 SR(VID_FIR_COEF_HV(1, 0));
309 SR(VID_FIR_COEF_HV(1, 1));
310 SR(VID_FIR_COEF_HV(1, 2));
311 SR(VID_FIR_COEF_HV(1, 3));
312 SR(VID_FIR_COEF_HV(1, 4));
313 SR(VID_FIR_COEF_HV(1, 5));
314 SR(VID_FIR_COEF_HV(1, 6));
315 SR(VID_FIR_COEF_HV(1, 7));
317 SR(VID_CONV_COEF(1, 0));
318 SR(VID_CONV_COEF(1, 1));
319 SR(VID_CONV_COEF(1, 2));
320 SR(VID_CONV_COEF(1, 3));
321 SR(VID_CONV_COEF(1, 4));
323 SR(VID_FIR_COEF_V(1, 0));
324 SR(VID_FIR_COEF_V(1, 1));
325 SR(VID_FIR_COEF_V(1, 2));
326 SR(VID_FIR_COEF_V(1, 3));
327 SR(VID_FIR_COEF_V(1, 4));
328 SR(VID_FIR_COEF_V(1, 5));
329 SR(VID_FIR_COEF_V(1, 6));
330 SR(VID_FIR_COEF_V(1, 7));
335 void dispc_restore_context(void)
359 RR(GFX_FIFO_THRESHOLD
);
380 RR(VID_ATTRIBUTES(0));
381 RR(VID_FIFO_THRESHOLD(0));
383 RR(VID_PIXEL_INC(0));
385 RR(VID_PICTURE_SIZE(0));
389 RR(VID_FIR_COEF_H(0, 0));
390 RR(VID_FIR_COEF_H(0, 1));
391 RR(VID_FIR_COEF_H(0, 2));
392 RR(VID_FIR_COEF_H(0, 3));
393 RR(VID_FIR_COEF_H(0, 4));
394 RR(VID_FIR_COEF_H(0, 5));
395 RR(VID_FIR_COEF_H(0, 6));
396 RR(VID_FIR_COEF_H(0, 7));
398 RR(VID_FIR_COEF_HV(0, 0));
399 RR(VID_FIR_COEF_HV(0, 1));
400 RR(VID_FIR_COEF_HV(0, 2));
401 RR(VID_FIR_COEF_HV(0, 3));
402 RR(VID_FIR_COEF_HV(0, 4));
403 RR(VID_FIR_COEF_HV(0, 5));
404 RR(VID_FIR_COEF_HV(0, 6));
405 RR(VID_FIR_COEF_HV(0, 7));
407 RR(VID_CONV_COEF(0, 0));
408 RR(VID_CONV_COEF(0, 1));
409 RR(VID_CONV_COEF(0, 2));
410 RR(VID_CONV_COEF(0, 3));
411 RR(VID_CONV_COEF(0, 4));
413 RR(VID_FIR_COEF_V(0, 0));
414 RR(VID_FIR_COEF_V(0, 1));
415 RR(VID_FIR_COEF_V(0, 2));
416 RR(VID_FIR_COEF_V(0, 3));
417 RR(VID_FIR_COEF_V(0, 4));
418 RR(VID_FIR_COEF_V(0, 5));
419 RR(VID_FIR_COEF_V(0, 6));
420 RR(VID_FIR_COEF_V(0, 7));
429 RR(VID_ATTRIBUTES(1));
430 RR(VID_FIFO_THRESHOLD(1));
432 RR(VID_PIXEL_INC(1));
434 RR(VID_PICTURE_SIZE(1));
438 RR(VID_FIR_COEF_H(1, 0));
439 RR(VID_FIR_COEF_H(1, 1));
440 RR(VID_FIR_COEF_H(1, 2));
441 RR(VID_FIR_COEF_H(1, 3));
442 RR(VID_FIR_COEF_H(1, 4));
443 RR(VID_FIR_COEF_H(1, 5));
444 RR(VID_FIR_COEF_H(1, 6));
445 RR(VID_FIR_COEF_H(1, 7));
447 RR(VID_FIR_COEF_HV(1, 0));
448 RR(VID_FIR_COEF_HV(1, 1));
449 RR(VID_FIR_COEF_HV(1, 2));
450 RR(VID_FIR_COEF_HV(1, 3));
451 RR(VID_FIR_COEF_HV(1, 4));
452 RR(VID_FIR_COEF_HV(1, 5));
453 RR(VID_FIR_COEF_HV(1, 6));
454 RR(VID_FIR_COEF_HV(1, 7));
456 RR(VID_CONV_COEF(1, 0));
457 RR(VID_CONV_COEF(1, 1));
458 RR(VID_CONV_COEF(1, 2));
459 RR(VID_CONV_COEF(1, 3));
460 RR(VID_CONV_COEF(1, 4));
462 RR(VID_FIR_COEF_V(1, 0));
463 RR(VID_FIR_COEF_V(1, 1));
464 RR(VID_FIR_COEF_V(1, 2));
465 RR(VID_FIR_COEF_V(1, 3));
466 RR(VID_FIR_COEF_V(1, 4));
467 RR(VID_FIR_COEF_V(1, 5));
468 RR(VID_FIR_COEF_V(1, 6));
469 RR(VID_FIR_COEF_V(1, 7));
473 /* enable last, because LCD & DIGIT enable are here */
480 static inline void enable_clocks(bool enable
)
483 dss_clk_enable(DSS_CLK_ICK
| DSS_CLK_FCK1
);
485 dss_clk_disable(DSS_CLK_ICK
| DSS_CLK_FCK1
);
488 bool dispc_go_busy(enum omap_channel channel
)
492 if (channel
== OMAP_DSS_CHANNEL_LCD
)
495 bit
= 6; /* GODIGIT */
497 return REG_GET(DISPC_CONTROL
, bit
, bit
) == 1;
500 void dispc_go(enum omap_channel channel
)
506 if (channel
== OMAP_DSS_CHANNEL_LCD
)
507 bit
= 0; /* LCDENABLE */
509 bit
= 1; /* DIGITALENABLE */
511 /* if the channel is not enabled, we don't need GO */
512 if (REG_GET(DISPC_CONTROL
, bit
, bit
) == 0)
515 if (channel
== OMAP_DSS_CHANNEL_LCD
)
518 bit
= 6; /* GODIGIT */
520 if (REG_GET(DISPC_CONTROL
, bit
, bit
) == 1) {
521 DSSERR("GO bit not down for channel %d\n", channel
);
525 DSSDBG("GO %s\n", channel
== OMAP_DSS_CHANNEL_LCD
? "LCD" : "DIGIT");
527 REG_FLD_MOD(DISPC_CONTROL
, 1, bit
, bit
);
532 static void _dispc_write_firh_reg(enum omap_plane plane
, int reg
, u32 value
)
534 BUG_ON(plane
== OMAP_DSS_GFX
);
536 dispc_write_reg(DISPC_VID_FIR_COEF_H(plane
-1, reg
), value
);
539 static void _dispc_write_firhv_reg(enum omap_plane plane
, int reg
, u32 value
)
541 BUG_ON(plane
== OMAP_DSS_GFX
);
543 dispc_write_reg(DISPC_VID_FIR_COEF_HV(plane
-1, reg
), value
);
546 static void _dispc_write_firv_reg(enum omap_plane plane
, int reg
, u32 value
)
548 BUG_ON(plane
== OMAP_DSS_GFX
);
550 dispc_write_reg(DISPC_VID_FIR_COEF_V(plane
-1, reg
), value
);
553 static void _dispc_set_scale_coef(enum omap_plane plane
, int hscaleup
,
554 int vscaleup
, int five_taps
)
556 /* Coefficients for horizontal up-sampling */
557 static const u32 coef_hup
[8] = {
568 /* Coefficients for horizontal down-sampling */
569 static const u32 coef_hdown
[8] = {
580 /* Coefficients for horizontal and vertical up-sampling */
581 static const u32 coef_hvup
[2][8] = {
604 /* Coefficients for horizontal and vertical down-sampling */
605 static const u32 coef_hvdown
[2][8] = {
628 /* Coefficients for vertical up-sampling */
629 static const u32 coef_vup
[8] = {
641 /* Coefficients for vertical down-sampling */
642 static const u32 coef_vdown
[8] = {
655 const u32
*hv_coef_mod
;
665 hv_coef
= coef_hvup
[five_taps
];
671 hv_coef_mod
= coef_hvdown
[five_taps
];
673 hv_coef
= coef_hvdown
[five_taps
];
677 hv_coef_mod
= coef_hvup
[five_taps
];
682 for (i
= 0; i
< 8; i
++) {
691 hv
|= (hv_coef_mod
[i
] & 0xff);
694 _dispc_write_firh_reg(plane
, i
, h
);
695 _dispc_write_firhv_reg(plane
, i
, hv
);
701 for (i
= 0; i
< 8; i
++) {
704 _dispc_write_firv_reg(plane
, i
, v
);
708 static void _dispc_setup_color_conv_coef(void)
710 const struct color_conv_coef
{
711 int ry
, rcr
, rcb
, gy
, gcr
, gcb
, by
, bcr
, bcb
;
714 298, 409, 0, 298, -208, -100, 298, 0, 517, 0,
717 const struct color_conv_coef
*ct
;
719 #define CVAL(x, y) (FLD_VAL(x, 26, 16) | FLD_VAL(y, 10, 0))
723 dispc_write_reg(DISPC_VID_CONV_COEF(0, 0), CVAL(ct
->rcr
, ct
->ry
));
724 dispc_write_reg(DISPC_VID_CONV_COEF(0, 1), CVAL(ct
->gy
, ct
->rcb
));
725 dispc_write_reg(DISPC_VID_CONV_COEF(0, 2), CVAL(ct
->gcb
, ct
->gcr
));
726 dispc_write_reg(DISPC_VID_CONV_COEF(0, 3), CVAL(ct
->bcr
, ct
->by
));
727 dispc_write_reg(DISPC_VID_CONV_COEF(0, 4), CVAL(0, ct
->bcb
));
729 dispc_write_reg(DISPC_VID_CONV_COEF(1, 0), CVAL(ct
->rcr
, ct
->ry
));
730 dispc_write_reg(DISPC_VID_CONV_COEF(1, 1), CVAL(ct
->gy
, ct
->rcb
));
731 dispc_write_reg(DISPC_VID_CONV_COEF(1, 2), CVAL(ct
->gcb
, ct
->gcr
));
732 dispc_write_reg(DISPC_VID_CONV_COEF(1, 3), CVAL(ct
->bcr
, ct
->by
));
733 dispc_write_reg(DISPC_VID_CONV_COEF(1, 4), CVAL(0, ct
->bcb
));
737 REG_FLD_MOD(DISPC_VID_ATTRIBUTES(0), ct
->full_range
, 11, 11);
738 REG_FLD_MOD(DISPC_VID_ATTRIBUTES(1), ct
->full_range
, 11, 11);
742 static void _dispc_set_plane_ba0(enum omap_plane plane
, u32 paddr
)
744 const struct dispc_reg ba0_reg
[] = { DISPC_GFX_BA0
,
748 dispc_write_reg(ba0_reg
[plane
], paddr
);
751 static void _dispc_set_plane_ba1(enum omap_plane plane
, u32 paddr
)
753 const struct dispc_reg ba1_reg
[] = { DISPC_GFX_BA1
,
757 dispc_write_reg(ba1_reg
[plane
], paddr
);
760 static void _dispc_set_plane_pos(enum omap_plane plane
, int x
, int y
)
762 const struct dispc_reg pos_reg
[] = { DISPC_GFX_POSITION
,
763 DISPC_VID_POSITION(0),
764 DISPC_VID_POSITION(1) };
766 u32 val
= FLD_VAL(y
, 26, 16) | FLD_VAL(x
, 10, 0);
767 dispc_write_reg(pos_reg
[plane
], val
);
770 static void _dispc_set_pic_size(enum omap_plane plane
, int width
, int height
)
772 const struct dispc_reg siz_reg
[] = { DISPC_GFX_SIZE
,
773 DISPC_VID_PICTURE_SIZE(0),
774 DISPC_VID_PICTURE_SIZE(1) };
775 u32 val
= FLD_VAL(height
- 1, 26, 16) | FLD_VAL(width
- 1, 10, 0);
776 dispc_write_reg(siz_reg
[plane
], val
);
779 static void _dispc_set_vid_size(enum omap_plane plane
, int width
, int height
)
782 const struct dispc_reg vsi_reg
[] = { DISPC_VID_SIZE(0),
785 BUG_ON(plane
== OMAP_DSS_GFX
);
787 val
= FLD_VAL(height
- 1, 26, 16) | FLD_VAL(width
- 1, 10, 0);
788 dispc_write_reg(vsi_reg
[plane
-1], val
);
791 static void _dispc_setup_global_alpha(enum omap_plane plane
, u8 global_alpha
)
794 BUG_ON(plane
== OMAP_DSS_VIDEO1
);
796 if (cpu_is_omap24xx())
799 if (plane
== OMAP_DSS_GFX
)
800 REG_FLD_MOD(DISPC_GLOBAL_ALPHA
, global_alpha
, 7, 0);
801 else if (plane
== OMAP_DSS_VIDEO2
)
802 REG_FLD_MOD(DISPC_GLOBAL_ALPHA
, global_alpha
, 23, 16);
805 static void _dispc_set_pix_inc(enum omap_plane plane
, s32 inc
)
807 const struct dispc_reg ri_reg
[] = { DISPC_GFX_PIXEL_INC
,
808 DISPC_VID_PIXEL_INC(0),
809 DISPC_VID_PIXEL_INC(1) };
811 dispc_write_reg(ri_reg
[plane
], inc
);
814 static void _dispc_set_row_inc(enum omap_plane plane
, s32 inc
)
816 const struct dispc_reg ri_reg
[] = { DISPC_GFX_ROW_INC
,
817 DISPC_VID_ROW_INC(0),
818 DISPC_VID_ROW_INC(1) };
820 dispc_write_reg(ri_reg
[plane
], inc
);
823 static void _dispc_set_color_mode(enum omap_plane plane
,
824 enum omap_color_mode color_mode
)
828 switch (color_mode
) {
829 case OMAP_DSS_COLOR_CLUT1
:
831 case OMAP_DSS_COLOR_CLUT2
:
833 case OMAP_DSS_COLOR_CLUT4
:
835 case OMAP_DSS_COLOR_CLUT8
:
837 case OMAP_DSS_COLOR_RGB12U
:
839 case OMAP_DSS_COLOR_ARGB16
:
841 case OMAP_DSS_COLOR_RGB16
:
843 case OMAP_DSS_COLOR_RGB24U
:
845 case OMAP_DSS_COLOR_RGB24P
:
847 case OMAP_DSS_COLOR_YUV2
:
849 case OMAP_DSS_COLOR_UYVY
:
851 case OMAP_DSS_COLOR_ARGB32
:
853 case OMAP_DSS_COLOR_RGBA32
:
855 case OMAP_DSS_COLOR_RGBX32
:
861 REG_FLD_MOD(dispc_reg_att
[plane
], m
, 4, 1);
864 static void _dispc_set_channel_out(enum omap_plane plane
,
865 enum omap_channel channel
)
874 case OMAP_DSS_VIDEO1
:
875 case OMAP_DSS_VIDEO2
:
883 val
= dispc_read_reg(dispc_reg_att
[plane
]);
884 val
= FLD_MOD(val
, channel
, shift
, shift
);
885 dispc_write_reg(dispc_reg_att
[plane
], val
);
888 void dispc_set_burst_size(enum omap_plane plane
,
889 enum omap_burst_size burst_size
)
900 case OMAP_DSS_VIDEO1
:
901 case OMAP_DSS_VIDEO2
:
909 val
= dispc_read_reg(dispc_reg_att
[plane
]);
910 val
= FLD_MOD(val
, burst_size
, shift
+1, shift
);
911 dispc_write_reg(dispc_reg_att
[plane
], val
);
916 static void _dispc_set_vid_color_conv(enum omap_plane plane
, bool enable
)
920 BUG_ON(plane
== OMAP_DSS_GFX
);
922 val
= dispc_read_reg(dispc_reg_att
[plane
]);
923 val
= FLD_MOD(val
, enable
, 9, 9);
924 dispc_write_reg(dispc_reg_att
[plane
], val
);
927 void dispc_enable_replication(enum omap_plane plane
, bool enable
)
931 if (plane
== OMAP_DSS_GFX
)
937 REG_FLD_MOD(dispc_reg_att
[plane
], enable
, bit
, bit
);
941 void dispc_set_lcd_size(u16 width
, u16 height
)
944 BUG_ON((width
> (1 << 11)) || (height
> (1 << 11)));
945 val
= FLD_VAL(height
- 1, 26, 16) | FLD_VAL(width
- 1, 10, 0);
947 dispc_write_reg(DISPC_SIZE_LCD
, val
);
951 void dispc_set_digit_size(u16 width
, u16 height
)
954 BUG_ON((width
> (1 << 11)) || (height
> (1 << 11)));
955 val
= FLD_VAL(height
- 1, 26, 16) | FLD_VAL(width
- 1, 10, 0);
957 dispc_write_reg(DISPC_SIZE_DIG
, val
);
961 static void dispc_read_plane_fifo_sizes(void)
963 const struct dispc_reg fsz_reg
[] = { DISPC_GFX_FIFO_SIZE_STATUS
,
964 DISPC_VID_FIFO_SIZE_STATUS(0),
965 DISPC_VID_FIFO_SIZE_STATUS(1) };
971 for (plane
= 0; plane
< ARRAY_SIZE(dispc
.fifo_size
); ++plane
) {
972 if (cpu_is_omap24xx())
973 size
= FLD_GET(dispc_read_reg(fsz_reg
[plane
]), 8, 0);
974 else if (cpu_is_omap34xx())
975 size
= FLD_GET(dispc_read_reg(fsz_reg
[plane
]), 10, 0);
979 dispc
.fifo_size
[plane
] = size
;
985 u32
dispc_get_plane_fifo_size(enum omap_plane plane
)
987 return dispc
.fifo_size
[plane
];
990 void dispc_setup_plane_fifo(enum omap_plane plane
, u32 low
, u32 high
)
992 const struct dispc_reg ftrs_reg
[] = { DISPC_GFX_FIFO_THRESHOLD
,
993 DISPC_VID_FIFO_THRESHOLD(0),
994 DISPC_VID_FIFO_THRESHOLD(1) };
997 DSSDBG("fifo(%d) low/high old %u/%u, new %u/%u\n",
999 REG_GET(ftrs_reg
[plane
], 11, 0),
1000 REG_GET(ftrs_reg
[plane
], 27, 16),
1003 if (cpu_is_omap24xx())
1004 dispc_write_reg(ftrs_reg
[plane
],
1005 FLD_VAL(high
, 24, 16) | FLD_VAL(low
, 8, 0));
1007 dispc_write_reg(ftrs_reg
[plane
],
1008 FLD_VAL(high
, 27, 16) | FLD_VAL(low
, 11, 0));
1013 void dispc_enable_fifomerge(bool enable
)
1017 DSSDBG("FIFO merge %s\n", enable
? "enabled" : "disabled");
1018 REG_FLD_MOD(DISPC_CONFIG
, enable
? 1 : 0, 14, 14);
1023 static void _dispc_set_fir(enum omap_plane plane
, int hinc
, int vinc
)
1026 const struct dispc_reg fir_reg
[] = { DISPC_VID_FIR(0),
1029 BUG_ON(plane
== OMAP_DSS_GFX
);
1031 if (cpu_is_omap24xx())
1032 val
= FLD_VAL(vinc
, 27, 16) | FLD_VAL(hinc
, 11, 0);
1034 val
= FLD_VAL(vinc
, 28, 16) | FLD_VAL(hinc
, 12, 0);
1035 dispc_write_reg(fir_reg
[plane
-1], val
);
1038 static void _dispc_set_vid_accu0(enum omap_plane plane
, int haccu
, int vaccu
)
1041 const struct dispc_reg ac0_reg
[] = { DISPC_VID_ACCU0(0),
1042 DISPC_VID_ACCU0(1) };
1044 BUG_ON(plane
== OMAP_DSS_GFX
);
1046 val
= FLD_VAL(vaccu
, 25, 16) | FLD_VAL(haccu
, 9, 0);
1047 dispc_write_reg(ac0_reg
[plane
-1], val
);
1050 static void _dispc_set_vid_accu1(enum omap_plane plane
, int haccu
, int vaccu
)
1053 const struct dispc_reg ac1_reg
[] = { DISPC_VID_ACCU1(0),
1054 DISPC_VID_ACCU1(1) };
1056 BUG_ON(plane
== OMAP_DSS_GFX
);
1058 val
= FLD_VAL(vaccu
, 25, 16) | FLD_VAL(haccu
, 9, 0);
1059 dispc_write_reg(ac1_reg
[plane
-1], val
);
1063 static void _dispc_set_scaling(enum omap_plane plane
,
1064 u16 orig_width
, u16 orig_height
,
1065 u16 out_width
, u16 out_height
,
1066 bool ilace
, bool five_taps
,
1071 int hscaleup
, vscaleup
;
1076 BUG_ON(plane
== OMAP_DSS_GFX
);
1078 hscaleup
= orig_width
<= out_width
;
1079 vscaleup
= orig_height
<= out_height
;
1081 _dispc_set_scale_coef(plane
, hscaleup
, vscaleup
, five_taps
);
1083 if (!orig_width
|| orig_width
== out_width
)
1086 fir_hinc
= 1024 * orig_width
/ out_width
;
1088 if (!orig_height
|| orig_height
== out_height
)
1091 fir_vinc
= 1024 * orig_height
/ out_height
;
1093 _dispc_set_fir(plane
, fir_hinc
, fir_vinc
);
1095 l
= dispc_read_reg(dispc_reg_att
[plane
]);
1096 l
&= ~((0x0f << 5) | (0x3 << 21));
1098 l
|= fir_hinc
? (1 << 5) : 0;
1099 l
|= fir_vinc
? (1 << 6) : 0;
1101 l
|= hscaleup
? 0 : (1 << 7);
1102 l
|= vscaleup
? 0 : (1 << 8);
1104 l
|= five_taps
? (1 << 21) : 0;
1105 l
|= five_taps
? (1 << 22) : 0;
1107 dispc_write_reg(dispc_reg_att
[plane
], l
);
1110 * field 0 = even field = bottom field
1111 * field 1 = odd field = top field
1113 if (ilace
&& !fieldmode
) {
1115 accu0
= (fir_vinc
/ 2) & 0x3ff;
1116 if (accu0
>= 1024/2) {
1122 _dispc_set_vid_accu0(plane
, 0, accu0
);
1123 _dispc_set_vid_accu1(plane
, 0, accu1
);
1126 static void _dispc_set_rotation_attrs(enum omap_plane plane
, u8 rotation
,
1127 bool mirroring
, enum omap_color_mode color_mode
)
1129 if (color_mode
== OMAP_DSS_COLOR_YUV2
||
1130 color_mode
== OMAP_DSS_COLOR_UYVY
) {
1135 case OMAP_DSS_ROT_0
:
1138 case OMAP_DSS_ROT_90
:
1141 case OMAP_DSS_ROT_180
:
1144 case OMAP_DSS_ROT_270
:
1150 case OMAP_DSS_ROT_0
:
1153 case OMAP_DSS_ROT_90
:
1156 case OMAP_DSS_ROT_180
:
1159 case OMAP_DSS_ROT_270
:
1165 REG_FLD_MOD(dispc_reg_att
[plane
], vidrot
, 13, 12);
1167 if (rotation
== OMAP_DSS_ROT_90
|| rotation
== OMAP_DSS_ROT_270
)
1168 REG_FLD_MOD(dispc_reg_att
[plane
], 0x1, 18, 18);
1170 REG_FLD_MOD(dispc_reg_att
[plane
], 0x0, 18, 18);
1172 REG_FLD_MOD(dispc_reg_att
[plane
], 0, 13, 12);
1173 REG_FLD_MOD(dispc_reg_att
[plane
], 0, 18, 18);
1177 static int color_mode_to_bpp(enum omap_color_mode color_mode
)
1179 switch (color_mode
) {
1180 case OMAP_DSS_COLOR_CLUT1
:
1182 case OMAP_DSS_COLOR_CLUT2
:
1184 case OMAP_DSS_COLOR_CLUT4
:
1186 case OMAP_DSS_COLOR_CLUT8
:
1188 case OMAP_DSS_COLOR_RGB12U
:
1189 case OMAP_DSS_COLOR_RGB16
:
1190 case OMAP_DSS_COLOR_ARGB16
:
1191 case OMAP_DSS_COLOR_YUV2
:
1192 case OMAP_DSS_COLOR_UYVY
:
1194 case OMAP_DSS_COLOR_RGB24P
:
1196 case OMAP_DSS_COLOR_RGB24U
:
1197 case OMAP_DSS_COLOR_ARGB32
:
1198 case OMAP_DSS_COLOR_RGBA32
:
1199 case OMAP_DSS_COLOR_RGBX32
:
1206 static s32
pixinc(int pixels
, u8 ps
)
1210 else if (pixels
> 1)
1211 return 1 + (pixels
- 1) * ps
;
1212 else if (pixels
< 0)
1213 return 1 - (-pixels
+ 1) * ps
;
1218 static void calc_vrfb_rotation_offset(u8 rotation
, bool mirror
,
1220 u16 width
, u16 height
,
1221 enum omap_color_mode color_mode
, bool fieldmode
,
1222 unsigned int field_offset
,
1223 unsigned *offset0
, unsigned *offset1
,
1224 s32
*row_inc
, s32
*pix_inc
)
1228 /* FIXME CLUT formats */
1229 switch (color_mode
) {
1230 case OMAP_DSS_COLOR_CLUT1
:
1231 case OMAP_DSS_COLOR_CLUT2
:
1232 case OMAP_DSS_COLOR_CLUT4
:
1233 case OMAP_DSS_COLOR_CLUT8
:
1236 case OMAP_DSS_COLOR_YUV2
:
1237 case OMAP_DSS_COLOR_UYVY
:
1241 ps
= color_mode_to_bpp(color_mode
) / 8;
1245 DSSDBG("calc_rot(%d): scrw %d, %dx%d\n", rotation
, screen_width
,
1249 * field 0 = even field = bottom field
1250 * field 1 = odd field = top field
1252 switch (rotation
+ mirror
* 4) {
1253 case OMAP_DSS_ROT_0
:
1254 case OMAP_DSS_ROT_180
:
1256 * If the pixel format is YUV or UYVY divide the width
1257 * of the image by 2 for 0 and 180 degree rotation.
1259 if (color_mode
== OMAP_DSS_COLOR_YUV2
||
1260 color_mode
== OMAP_DSS_COLOR_UYVY
)
1262 case OMAP_DSS_ROT_90
:
1263 case OMAP_DSS_ROT_270
:
1266 *offset0
= field_offset
* screen_width
* ps
;
1270 *row_inc
= pixinc(1 + (screen_width
- width
) +
1271 (fieldmode
? screen_width
: 0),
1273 *pix_inc
= pixinc(1, ps
);
1276 case OMAP_DSS_ROT_0
+ 4:
1277 case OMAP_DSS_ROT_180
+ 4:
1278 /* If the pixel format is YUV or UYVY divide the width
1279 * of the image by 2 for 0 degree and 180 degree
1281 if (color_mode
== OMAP_DSS_COLOR_YUV2
||
1282 color_mode
== OMAP_DSS_COLOR_UYVY
)
1284 case OMAP_DSS_ROT_90
+ 4:
1285 case OMAP_DSS_ROT_270
+ 4:
1288 *offset0
= field_offset
* screen_width
* ps
;
1291 *row_inc
= pixinc(1 - (screen_width
+ width
) -
1292 (fieldmode
? screen_width
: 0),
1294 *pix_inc
= pixinc(1, ps
);
1302 static void calc_dma_rotation_offset(u8 rotation
, bool mirror
,
1304 u16 width
, u16 height
,
1305 enum omap_color_mode color_mode
, bool fieldmode
,
1306 unsigned int field_offset
,
1307 unsigned *offset0
, unsigned *offset1
,
1308 s32
*row_inc
, s32
*pix_inc
)
1313 /* FIXME CLUT formats */
1314 switch (color_mode
) {
1315 case OMAP_DSS_COLOR_CLUT1
:
1316 case OMAP_DSS_COLOR_CLUT2
:
1317 case OMAP_DSS_COLOR_CLUT4
:
1318 case OMAP_DSS_COLOR_CLUT8
:
1322 ps
= color_mode_to_bpp(color_mode
) / 8;
1326 DSSDBG("calc_rot(%d): scrw %d, %dx%d\n", rotation
, screen_width
,
1329 /* width & height are overlay sizes, convert to fb sizes */
1331 if (rotation
== OMAP_DSS_ROT_0
|| rotation
== OMAP_DSS_ROT_180
) {
1340 * field 0 = even field = bottom field
1341 * field 1 = odd field = top field
1343 switch (rotation
+ mirror
* 4) {
1344 case OMAP_DSS_ROT_0
:
1347 *offset0
= *offset1
+ field_offset
* screen_width
* ps
;
1349 *offset0
= *offset1
;
1350 *row_inc
= pixinc(1 + (screen_width
- fbw
) +
1351 (fieldmode
? screen_width
: 0),
1353 *pix_inc
= pixinc(1, ps
);
1355 case OMAP_DSS_ROT_90
:
1356 *offset1
= screen_width
* (fbh
- 1) * ps
;
1358 *offset0
= *offset1
+ field_offset
* ps
;
1360 *offset0
= *offset1
;
1361 *row_inc
= pixinc(screen_width
* (fbh
- 1) + 1 +
1362 (fieldmode
? 1 : 0), ps
);
1363 *pix_inc
= pixinc(-screen_width
, ps
);
1365 case OMAP_DSS_ROT_180
:
1366 *offset1
= (screen_width
* (fbh
- 1) + fbw
- 1) * ps
;
1368 *offset0
= *offset1
- field_offset
* screen_width
* ps
;
1370 *offset0
= *offset1
;
1371 *row_inc
= pixinc(-1 -
1372 (screen_width
- fbw
) -
1373 (fieldmode
? screen_width
: 0),
1375 *pix_inc
= pixinc(-1, ps
);
1377 case OMAP_DSS_ROT_270
:
1378 *offset1
= (fbw
- 1) * ps
;
1380 *offset0
= *offset1
- field_offset
* ps
;
1382 *offset0
= *offset1
;
1383 *row_inc
= pixinc(-screen_width
* (fbh
- 1) - 1 -
1384 (fieldmode
? 1 : 0), ps
);
1385 *pix_inc
= pixinc(screen_width
, ps
);
1389 case OMAP_DSS_ROT_0
+ 4:
1390 *offset1
= (fbw
- 1) * ps
;
1392 *offset0
= *offset1
+ field_offset
* screen_width
* ps
;
1394 *offset0
= *offset1
;
1395 *row_inc
= pixinc(screen_width
* 2 - 1 +
1396 (fieldmode
? screen_width
: 0),
1398 *pix_inc
= pixinc(-1, ps
);
1401 case OMAP_DSS_ROT_90
+ 4:
1404 *offset0
= *offset1
+ field_offset
* ps
;
1406 *offset0
= *offset1
;
1407 *row_inc
= pixinc(-screen_width
* (fbh
- 1) + 1 +
1408 (fieldmode
? 1 : 0),
1410 *pix_inc
= pixinc(screen_width
, ps
);
1413 case OMAP_DSS_ROT_180
+ 4:
1414 *offset1
= screen_width
* (fbh
- 1) * ps
;
1416 *offset0
= *offset1
- field_offset
* screen_width
* ps
;
1418 *offset0
= *offset1
;
1419 *row_inc
= pixinc(1 - screen_width
* 2 -
1420 (fieldmode
? screen_width
: 0),
1422 *pix_inc
= pixinc(1, ps
);
1425 case OMAP_DSS_ROT_270
+ 4:
1426 *offset1
= (screen_width
* (fbh
- 1) + fbw
- 1) * ps
;
1428 *offset0
= *offset1
- field_offset
* ps
;
1430 *offset0
= *offset1
;
1431 *row_inc
= pixinc(screen_width
* (fbh
- 1) - 1 -
1432 (fieldmode
? 1 : 0),
1434 *pix_inc
= pixinc(-screen_width
, ps
);
1442 static unsigned long calc_fclk_five_taps(u16 width
, u16 height
,
1443 u16 out_width
, u16 out_height
, enum omap_color_mode color_mode
)
1446 /* FIXME venc pclk? */
1447 u64 tmp
, pclk
= dispc_pclk_rate();
1449 if (height
> out_height
) {
1450 /* FIXME get real display PPL */
1451 unsigned int ppl
= 800;
1453 tmp
= pclk
* height
* out_width
;
1454 do_div(tmp
, 2 * out_height
* ppl
);
1457 if (height
> 2 * out_height
) {
1458 if (ppl
== out_width
)
1461 tmp
= pclk
* (height
- 2 * out_height
) * out_width
;
1462 do_div(tmp
, 2 * out_height
* (ppl
- out_width
));
1463 fclk
= max(fclk
, (u32
) tmp
);
1467 if (width
> out_width
) {
1469 do_div(tmp
, out_width
);
1470 fclk
= max(fclk
, (u32
) tmp
);
1472 if (color_mode
== OMAP_DSS_COLOR_RGB24U
)
1479 static unsigned long calc_fclk(u16 width
, u16 height
,
1480 u16 out_width
, u16 out_height
)
1482 unsigned int hf
, vf
;
1485 * FIXME how to determine the 'A' factor
1486 * for the no downscaling case ?
1489 if (width
> 3 * out_width
)
1491 else if (width
> 2 * out_width
)
1493 else if (width
> out_width
)
1498 if (height
> out_height
)
1503 /* FIXME venc pclk? */
1504 return dispc_pclk_rate() * vf
* hf
;
1507 void dispc_set_channel_out(enum omap_plane plane
, enum omap_channel channel_out
)
1510 _dispc_set_channel_out(plane
, channel_out
);
1514 static int _dispc_setup_plane(enum omap_plane plane
,
1515 u32 paddr
, u16 screen_width
,
1516 u16 pos_x
, u16 pos_y
,
1517 u16 width
, u16 height
,
1518 u16 out_width
, u16 out_height
,
1519 enum omap_color_mode color_mode
,
1521 enum omap_dss_rotation_type rotation_type
,
1522 u8 rotation
, int mirror
,
1525 const int maxdownscale
= cpu_is_omap34xx() ? 4 : 2;
1529 unsigned offset0
, offset1
;
1532 u16 frame_height
= height
;
1533 unsigned int field_offset
= 0;
1538 if (ilace
&& height
== out_height
)
1547 DSSDBG("adjusting for ilace: height %d, pos_y %d, "
1549 height
, pos_y
, out_height
);
1552 if (plane
== OMAP_DSS_GFX
) {
1553 if (width
!= out_width
|| height
!= out_height
)
1556 switch (color_mode
) {
1557 case OMAP_DSS_COLOR_ARGB16
:
1558 case OMAP_DSS_COLOR_ARGB32
:
1559 case OMAP_DSS_COLOR_RGBA32
:
1560 case OMAP_DSS_COLOR_RGBX32
:
1561 if (cpu_is_omap24xx())
1564 case OMAP_DSS_COLOR_RGB12U
:
1565 case OMAP_DSS_COLOR_RGB16
:
1566 case OMAP_DSS_COLOR_RGB24P
:
1567 case OMAP_DSS_COLOR_RGB24U
:
1576 unsigned long fclk
= 0;
1578 if (out_width
< width
/ maxdownscale
||
1579 out_width
> width
* 8)
1582 if (out_height
< height
/ maxdownscale
||
1583 out_height
> height
* 8)
1586 switch (color_mode
) {
1587 case OMAP_DSS_COLOR_RGBX32
:
1588 case OMAP_DSS_COLOR_RGB12U
:
1589 if (cpu_is_omap24xx())
1592 case OMAP_DSS_COLOR_RGB16
:
1593 case OMAP_DSS_COLOR_RGB24P
:
1594 case OMAP_DSS_COLOR_RGB24U
:
1597 case OMAP_DSS_COLOR_ARGB16
:
1598 case OMAP_DSS_COLOR_ARGB32
:
1599 case OMAP_DSS_COLOR_RGBA32
:
1600 if (cpu_is_omap24xx())
1602 if (plane
== OMAP_DSS_VIDEO1
)
1606 case OMAP_DSS_COLOR_YUV2
:
1607 case OMAP_DSS_COLOR_UYVY
:
1615 /* Must use 5-tap filter? */
1616 five_taps
= height
> out_height
* 2;
1619 fclk
= calc_fclk(width
, height
,
1620 out_width
, out_height
);
1622 /* Try 5-tap filter if 3-tap fclk is too high */
1623 if (cpu_is_omap34xx() && height
> out_height
&&
1624 fclk
> dispc_fclk_rate())
1628 if (width
> (2048 >> five_taps
)) {
1629 DSSERR("failed to set up scaling, fclk too low\n");
1634 fclk
= calc_fclk_five_taps(width
, height
,
1635 out_width
, out_height
, color_mode
);
1637 DSSDBG("required fclk rate = %lu Hz\n", fclk
);
1638 DSSDBG("current fclk rate = %lu Hz\n", dispc_fclk_rate());
1640 if (!fclk
|| fclk
> dispc_fclk_rate()) {
1641 DSSERR("failed to set up scaling, "
1642 "required fclk rate = %lu Hz, "
1643 "current fclk rate = %lu Hz\n",
1644 fclk
, dispc_fclk_rate());
1649 if (ilace
&& !fieldmode
) {
1651 * when downscaling the bottom field may have to start several
1652 * source lines below the top field. Unfortunately ACCUI
1653 * registers will only hold the fractional part of the offset
1654 * so the integer part must be added to the base address of the
1657 if (!height
|| height
== out_height
)
1660 field_offset
= height
/ out_height
/ 2;
1663 /* Fields are independent but interleaved in memory. */
1667 if (rotation_type
== OMAP_DSS_ROT_DMA
)
1668 calc_dma_rotation_offset(rotation
, mirror
,
1669 screen_width
, width
, frame_height
, color_mode
,
1670 fieldmode
, field_offset
,
1671 &offset0
, &offset1
, &row_inc
, &pix_inc
);
1673 calc_vrfb_rotation_offset(rotation
, mirror
,
1674 screen_width
, width
, frame_height
, color_mode
,
1675 fieldmode
, field_offset
,
1676 &offset0
, &offset1
, &row_inc
, &pix_inc
);
1678 DSSDBG("offset0 %u, offset1 %u, row_inc %d, pix_inc %d\n",
1679 offset0
, offset1
, row_inc
, pix_inc
);
1681 _dispc_set_color_mode(plane
, color_mode
);
1683 _dispc_set_plane_ba0(plane
, paddr
+ offset0
);
1684 _dispc_set_plane_ba1(plane
, paddr
+ offset1
);
1686 _dispc_set_row_inc(plane
, row_inc
);
1687 _dispc_set_pix_inc(plane
, pix_inc
);
1689 DSSDBG("%d,%d %dx%d -> %dx%d\n", pos_x
, pos_y
, width
, height
,
1690 out_width
, out_height
);
1692 _dispc_set_plane_pos(plane
, pos_x
, pos_y
);
1694 _dispc_set_pic_size(plane
, width
, height
);
1696 if (plane
!= OMAP_DSS_GFX
) {
1697 _dispc_set_scaling(plane
, width
, height
,
1698 out_width
, out_height
,
1699 ilace
, five_taps
, fieldmode
);
1700 _dispc_set_vid_size(plane
, out_width
, out_height
);
1701 _dispc_set_vid_color_conv(plane
, cconv
);
1704 _dispc_set_rotation_attrs(plane
, rotation
, mirror
, color_mode
);
1706 if (plane
!= OMAP_DSS_VIDEO1
)
1707 _dispc_setup_global_alpha(plane
, global_alpha
);
1712 static void _dispc_enable_plane(enum omap_plane plane
, bool enable
)
1714 REG_FLD_MOD(dispc_reg_att
[plane
], enable
? 1 : 0, 0, 0);
1717 static void dispc_disable_isr(void *data
, u32 mask
)
1719 struct completion
*compl = data
;
1723 static void _enable_lcd_out(bool enable
)
1725 REG_FLD_MOD(DISPC_CONTROL
, enable
? 1 : 0, 0, 0);
1728 static void dispc_enable_lcd_out(bool enable
)
1730 struct completion frame_done_completion
;
1736 /* When we disable LCD output, we need to wait until frame is done.
1737 * Otherwise the DSS is still working, and turning off the clocks
1738 * prevents DSS from going to OFF mode */
1739 is_on
= REG_GET(DISPC_CONTROL
, 0, 0);
1741 if (!enable
&& is_on
) {
1742 init_completion(&frame_done_completion
);
1744 r
= omap_dispc_register_isr(dispc_disable_isr
,
1745 &frame_done_completion
,
1746 DISPC_IRQ_FRAMEDONE
);
1749 DSSERR("failed to register FRAMEDONE isr\n");
1752 _enable_lcd_out(enable
);
1754 if (!enable
&& is_on
) {
1755 if (!wait_for_completion_timeout(&frame_done_completion
,
1756 msecs_to_jiffies(100)))
1757 DSSERR("timeout waiting for FRAME DONE\n");
1759 r
= omap_dispc_unregister_isr(dispc_disable_isr
,
1760 &frame_done_completion
,
1761 DISPC_IRQ_FRAMEDONE
);
1764 DSSERR("failed to unregister FRAMEDONE isr\n");
1770 static void _enable_digit_out(bool enable
)
1772 REG_FLD_MOD(DISPC_CONTROL
, enable
? 1 : 0, 1, 1);
1775 static void dispc_enable_digit_out(bool enable
)
1777 struct completion frame_done_completion
;
1782 if (REG_GET(DISPC_CONTROL
, 1, 1) == enable
) {
1788 unsigned long flags
;
1789 /* When we enable digit output, we'll get an extra digit
1790 * sync lost interrupt, that we need to ignore */
1791 spin_lock_irqsave(&dispc
.irq_lock
, flags
);
1792 dispc
.irq_error_mask
&= ~DISPC_IRQ_SYNC_LOST_DIGIT
;
1793 _omap_dispc_set_irqs();
1794 spin_unlock_irqrestore(&dispc
.irq_lock
, flags
);
1797 /* When we disable digit output, we need to wait until fields are done.
1798 * Otherwise the DSS is still working, and turning off the clocks
1799 * prevents DSS from going to OFF mode. And when enabling, we need to
1800 * wait for the extra sync losts */
1801 init_completion(&frame_done_completion
);
1803 r
= omap_dispc_register_isr(dispc_disable_isr
, &frame_done_completion
,
1804 DISPC_IRQ_EVSYNC_EVEN
| DISPC_IRQ_EVSYNC_ODD
);
1806 DSSERR("failed to register EVSYNC isr\n");
1808 _enable_digit_out(enable
);
1810 /* XXX I understand from TRM that we should only wait for the
1811 * current field to complete. But it seems we have to wait
1812 * for both fields */
1813 if (!wait_for_completion_timeout(&frame_done_completion
,
1814 msecs_to_jiffies(100)))
1815 DSSERR("timeout waiting for EVSYNC\n");
1817 if (!wait_for_completion_timeout(&frame_done_completion
,
1818 msecs_to_jiffies(100)))
1819 DSSERR("timeout waiting for EVSYNC\n");
1821 r
= omap_dispc_unregister_isr(dispc_disable_isr
,
1822 &frame_done_completion
,
1823 DISPC_IRQ_EVSYNC_EVEN
| DISPC_IRQ_EVSYNC_ODD
);
1825 DSSERR("failed to unregister EVSYNC isr\n");
1828 unsigned long flags
;
1829 spin_lock_irqsave(&dispc
.irq_lock
, flags
);
1830 dispc
.irq_error_mask
= DISPC_IRQ_MASK_ERROR
;
1831 dispc_write_reg(DISPC_IRQSTATUS
, DISPC_IRQ_SYNC_LOST_DIGIT
);
1832 _omap_dispc_set_irqs();
1833 spin_unlock_irqrestore(&dispc
.irq_lock
, flags
);
1839 bool dispc_is_channel_enabled(enum omap_channel channel
)
1841 if (channel
== OMAP_DSS_CHANNEL_LCD
)
1842 return !!REG_GET(DISPC_CONTROL
, 0, 0);
1843 else if (channel
== OMAP_DSS_CHANNEL_DIGIT
)
1844 return !!REG_GET(DISPC_CONTROL
, 1, 1);
1849 void dispc_enable_channel(enum omap_channel channel
, bool enable
)
1851 if (channel
== OMAP_DSS_CHANNEL_LCD
)
1852 dispc_enable_lcd_out(enable
);
1853 else if (channel
== OMAP_DSS_CHANNEL_DIGIT
)
1854 dispc_enable_digit_out(enable
);
1859 void dispc_lcd_enable_signal_polarity(bool act_high
)
1862 REG_FLD_MOD(DISPC_CONTROL
, act_high
? 1 : 0, 29, 29);
1866 void dispc_lcd_enable_signal(bool enable
)
1869 REG_FLD_MOD(DISPC_CONTROL
, enable
? 1 : 0, 28, 28);
1873 void dispc_pck_free_enable(bool enable
)
1876 REG_FLD_MOD(DISPC_CONTROL
, enable
? 1 : 0, 27, 27);
1880 void dispc_enable_fifohandcheck(bool enable
)
1883 REG_FLD_MOD(DISPC_CONFIG
, enable
? 1 : 0, 16, 16);
1888 void dispc_set_lcd_display_type(enum omap_lcd_display_type type
)
1893 case OMAP_DSS_LCD_DISPLAY_STN
:
1897 case OMAP_DSS_LCD_DISPLAY_TFT
:
1907 REG_FLD_MOD(DISPC_CONTROL
, mode
, 3, 3);
1911 void dispc_set_loadmode(enum omap_dss_load_mode mode
)
1914 REG_FLD_MOD(DISPC_CONFIG
, mode
, 2, 1);
1919 void dispc_set_default_color(enum omap_channel channel
, u32 color
)
1921 const struct dispc_reg def_reg
[] = { DISPC_DEFAULT_COLOR0
,
1922 DISPC_DEFAULT_COLOR1
};
1925 dispc_write_reg(def_reg
[channel
], color
);
1929 u32
dispc_get_default_color(enum omap_channel channel
)
1931 const struct dispc_reg def_reg
[] = { DISPC_DEFAULT_COLOR0
,
1932 DISPC_DEFAULT_COLOR1
};
1935 BUG_ON(channel
!= OMAP_DSS_CHANNEL_DIGIT
&&
1936 channel
!= OMAP_DSS_CHANNEL_LCD
);
1939 l
= dispc_read_reg(def_reg
[channel
]);
1945 void dispc_set_trans_key(enum omap_channel ch
,
1946 enum omap_dss_trans_key_type type
,
1949 const struct dispc_reg tr_reg
[] = {
1950 DISPC_TRANS_COLOR0
, DISPC_TRANS_COLOR1
};
1953 if (ch
== OMAP_DSS_CHANNEL_LCD
)
1954 REG_FLD_MOD(DISPC_CONFIG
, type
, 11, 11);
1955 else /* OMAP_DSS_CHANNEL_DIGIT */
1956 REG_FLD_MOD(DISPC_CONFIG
, type
, 13, 13);
1958 dispc_write_reg(tr_reg
[ch
], trans_key
);
1962 void dispc_get_trans_key(enum omap_channel ch
,
1963 enum omap_dss_trans_key_type
*type
,
1966 const struct dispc_reg tr_reg
[] = {
1967 DISPC_TRANS_COLOR0
, DISPC_TRANS_COLOR1
};
1971 if (ch
== OMAP_DSS_CHANNEL_LCD
)
1972 *type
= REG_GET(DISPC_CONFIG
, 11, 11);
1973 else if (ch
== OMAP_DSS_CHANNEL_DIGIT
)
1974 *type
= REG_GET(DISPC_CONFIG
, 13, 13);
1980 *trans_key
= dispc_read_reg(tr_reg
[ch
]);
1984 void dispc_enable_trans_key(enum omap_channel ch
, bool enable
)
1987 if (ch
== OMAP_DSS_CHANNEL_LCD
)
1988 REG_FLD_MOD(DISPC_CONFIG
, enable
, 10, 10);
1989 else /* OMAP_DSS_CHANNEL_DIGIT */
1990 REG_FLD_MOD(DISPC_CONFIG
, enable
, 12, 12);
1993 void dispc_enable_alpha_blending(enum omap_channel ch
, bool enable
)
1995 if (cpu_is_omap24xx())
1999 if (ch
== OMAP_DSS_CHANNEL_LCD
)
2000 REG_FLD_MOD(DISPC_CONFIG
, enable
, 18, 18);
2001 else /* OMAP_DSS_CHANNEL_DIGIT */
2002 REG_FLD_MOD(DISPC_CONFIG
, enable
, 19, 19);
2005 bool dispc_alpha_blending_enabled(enum omap_channel ch
)
2009 if (cpu_is_omap24xx())
2013 if (ch
== OMAP_DSS_CHANNEL_LCD
)
2014 enabled
= REG_GET(DISPC_CONFIG
, 18, 18);
2015 else if (ch
== OMAP_DSS_CHANNEL_DIGIT
)
2016 enabled
= REG_GET(DISPC_CONFIG
, 18, 18);
2026 bool dispc_trans_key_enabled(enum omap_channel ch
)
2031 if (ch
== OMAP_DSS_CHANNEL_LCD
)
2032 enabled
= REG_GET(DISPC_CONFIG
, 10, 10);
2033 else if (ch
== OMAP_DSS_CHANNEL_DIGIT
)
2034 enabled
= REG_GET(DISPC_CONFIG
, 12, 12);
2043 void dispc_set_tft_data_lines(u8 data_lines
)
2047 switch (data_lines
) {
2066 REG_FLD_MOD(DISPC_CONTROL
, code
, 9, 8);
2070 void dispc_set_parallel_interface_mode(enum omap_parallel_interface_mode mode
)
2078 case OMAP_DSS_PARALLELMODE_BYPASS
:
2083 case OMAP_DSS_PARALLELMODE_RFBI
:
2088 case OMAP_DSS_PARALLELMODE_DSI
:
2100 l
= dispc_read_reg(DISPC_CONTROL
);
2102 l
= FLD_MOD(l
, stallmode
, 11, 11);
2103 l
= FLD_MOD(l
, gpout0
, 15, 15);
2104 l
= FLD_MOD(l
, gpout1
, 16, 16);
2106 dispc_write_reg(DISPC_CONTROL
, l
);
2111 static bool _dispc_lcd_timings_ok(int hsw
, int hfp
, int hbp
,
2112 int vsw
, int vfp
, int vbp
)
2114 if (cpu_is_omap24xx() || omap_rev() < OMAP3430_REV_ES3_0
) {
2115 if (hsw
< 1 || hsw
> 64 ||
2116 hfp
< 1 || hfp
> 256 ||
2117 hbp
< 1 || hbp
> 256 ||
2118 vsw
< 1 || vsw
> 64 ||
2119 vfp
< 0 || vfp
> 255 ||
2120 vbp
< 0 || vbp
> 255)
2123 if (hsw
< 1 || hsw
> 256 ||
2124 hfp
< 1 || hfp
> 4096 ||
2125 hbp
< 1 || hbp
> 4096 ||
2126 vsw
< 1 || vsw
> 256 ||
2127 vfp
< 0 || vfp
> 4095 ||
2128 vbp
< 0 || vbp
> 4095)
2135 bool dispc_lcd_timings_ok(struct omap_video_timings
*timings
)
2137 return _dispc_lcd_timings_ok(timings
->hsw
, timings
->hfp
,
2138 timings
->hbp
, timings
->vsw
,
2139 timings
->vfp
, timings
->vbp
);
2142 static void _dispc_set_lcd_timings(int hsw
, int hfp
, int hbp
,
2143 int vsw
, int vfp
, int vbp
)
2145 u32 timing_h
, timing_v
;
2147 if (cpu_is_omap24xx() || omap_rev() < OMAP3430_REV_ES3_0
) {
2148 timing_h
= FLD_VAL(hsw
-1, 5, 0) | FLD_VAL(hfp
-1, 15, 8) |
2149 FLD_VAL(hbp
-1, 27, 20);
2151 timing_v
= FLD_VAL(vsw
-1, 5, 0) | FLD_VAL(vfp
, 15, 8) |
2152 FLD_VAL(vbp
, 27, 20);
2154 timing_h
= FLD_VAL(hsw
-1, 7, 0) | FLD_VAL(hfp
-1, 19, 8) |
2155 FLD_VAL(hbp
-1, 31, 20);
2157 timing_v
= FLD_VAL(vsw
-1, 7, 0) | FLD_VAL(vfp
, 19, 8) |
2158 FLD_VAL(vbp
, 31, 20);
2162 dispc_write_reg(DISPC_TIMING_H
, timing_h
);
2163 dispc_write_reg(DISPC_TIMING_V
, timing_v
);
2167 /* change name to mode? */
2168 void dispc_set_lcd_timings(struct omap_video_timings
*timings
)
2170 unsigned xtot
, ytot
;
2171 unsigned long ht
, vt
;
2173 if (!_dispc_lcd_timings_ok(timings
->hsw
, timings
->hfp
,
2174 timings
->hbp
, timings
->vsw
,
2175 timings
->vfp
, timings
->vbp
))
2178 _dispc_set_lcd_timings(timings
->hsw
, timings
->hfp
, timings
->hbp
,
2179 timings
->vsw
, timings
->vfp
, timings
->vbp
);
2181 dispc_set_lcd_size(timings
->x_res
, timings
->y_res
);
2183 xtot
= timings
->x_res
+ timings
->hfp
+ timings
->hsw
+ timings
->hbp
;
2184 ytot
= timings
->y_res
+ timings
->vfp
+ timings
->vsw
+ timings
->vbp
;
2186 ht
= (timings
->pixel_clock
* 1000) / xtot
;
2187 vt
= (timings
->pixel_clock
* 1000) / xtot
/ ytot
;
2189 DSSDBG("xres %u yres %u\n", timings
->x_res
, timings
->y_res
);
2190 DSSDBG("pck %u\n", timings
->pixel_clock
);
2191 DSSDBG("hsw %d hfp %d hbp %d vsw %d vfp %d vbp %d\n",
2192 timings
->hsw
, timings
->hfp
, timings
->hbp
,
2193 timings
->vsw
, timings
->vfp
, timings
->vbp
);
2195 DSSDBG("hsync %luHz, vsync %luHz\n", ht
, vt
);
2198 static void dispc_set_lcd_divisor(u16 lck_div
, u16 pck_div
)
2200 BUG_ON(lck_div
< 1);
2201 BUG_ON(pck_div
< 2);
2204 dispc_write_reg(DISPC_DIVISOR
,
2205 FLD_VAL(lck_div
, 23, 16) | FLD_VAL(pck_div
, 7, 0));
2209 static void dispc_get_lcd_divisor(int *lck_div
, int *pck_div
)
2212 l
= dispc_read_reg(DISPC_DIVISOR
);
2213 *lck_div
= FLD_GET(l
, 23, 16);
2214 *pck_div
= FLD_GET(l
, 7, 0);
2217 unsigned long dispc_fclk_rate(void)
2219 unsigned long r
= 0;
2221 if (dss_get_dispc_clk_source() == DSS_SRC_DSS1_ALWON_FCLK
)
2222 r
= dss_clk_get_rate(DSS_CLK_FCK1
);
2224 #ifdef CONFIG_OMAP2_DSS_DSI
2225 r
= dsi_get_dsi1_pll_rate();
2232 unsigned long dispc_lclk_rate(void)
2238 l
= dispc_read_reg(DISPC_DIVISOR
);
2240 lcd
= FLD_GET(l
, 23, 16);
2242 r
= dispc_fclk_rate();
2247 unsigned long dispc_pclk_rate(void)
2253 l
= dispc_read_reg(DISPC_DIVISOR
);
2255 lcd
= FLD_GET(l
, 23, 16);
2256 pcd
= FLD_GET(l
, 7, 0);
2258 r
= dispc_fclk_rate();
2260 return r
/ lcd
/ pcd
;
2263 void dispc_dump_clocks(struct seq_file
*s
)
2269 dispc_get_lcd_divisor(&lcd
, &pcd
);
2271 seq_printf(s
, "- DISPC -\n");
2273 seq_printf(s
, "dispc fclk source = %s\n",
2274 dss_get_dispc_clk_source() == DSS_SRC_DSS1_ALWON_FCLK
?
2275 "dss1_alwon_fclk" : "dsi1_pll_fclk");
2277 seq_printf(s
, "fck\t\t%-16lu\n", dispc_fclk_rate());
2278 seq_printf(s
, "lck\t\t%-16lulck div\t%u\n", dispc_lclk_rate(), lcd
);
2279 seq_printf(s
, "pck\t\t%-16lupck div\t%u\n", dispc_pclk_rate(), pcd
);
2284 #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
2285 void dispc_dump_irqs(struct seq_file
*s
)
2287 unsigned long flags
;
2288 struct dispc_irq_stats stats
;
2290 spin_lock_irqsave(&dispc
.irq_stats_lock
, flags
);
2292 stats
= dispc
.irq_stats
;
2293 memset(&dispc
.irq_stats
, 0, sizeof(dispc
.irq_stats
));
2294 dispc
.irq_stats
.last_reset
= jiffies
;
2296 spin_unlock_irqrestore(&dispc
.irq_stats_lock
, flags
);
2298 seq_printf(s
, "period %u ms\n",
2299 jiffies_to_msecs(jiffies
- stats
.last_reset
));
2301 seq_printf(s
, "irqs %d\n", stats
.irq_count
);
2303 seq_printf(s, "%-20s %10d\n", #x, stats.irqs[ffs(DISPC_IRQ_##x)-1]);
2309 PIS(ACBIAS_COUNT_STAT
);
2311 PIS(GFX_FIFO_UNDERFLOW
);
2313 PIS(PAL_GAMMA_MASK
);
2315 PIS(VID1_FIFO_UNDERFLOW
);
2317 PIS(VID2_FIFO_UNDERFLOW
);
2320 PIS(SYNC_LOST_DIGIT
);
2326 void dispc_dump_regs(struct seq_file
*s
)
2328 #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dispc_read_reg(r))
2330 dss_clk_enable(DSS_CLK_ICK
| DSS_CLK_FCK1
);
2332 DUMPREG(DISPC_REVISION
);
2333 DUMPREG(DISPC_SYSCONFIG
);
2334 DUMPREG(DISPC_SYSSTATUS
);
2335 DUMPREG(DISPC_IRQSTATUS
);
2336 DUMPREG(DISPC_IRQENABLE
);
2337 DUMPREG(DISPC_CONTROL
);
2338 DUMPREG(DISPC_CONFIG
);
2339 DUMPREG(DISPC_CAPABLE
);
2340 DUMPREG(DISPC_DEFAULT_COLOR0
);
2341 DUMPREG(DISPC_DEFAULT_COLOR1
);
2342 DUMPREG(DISPC_TRANS_COLOR0
);
2343 DUMPREG(DISPC_TRANS_COLOR1
);
2344 DUMPREG(DISPC_LINE_STATUS
);
2345 DUMPREG(DISPC_LINE_NUMBER
);
2346 DUMPREG(DISPC_TIMING_H
);
2347 DUMPREG(DISPC_TIMING_V
);
2348 DUMPREG(DISPC_POL_FREQ
);
2349 DUMPREG(DISPC_DIVISOR
);
2350 DUMPREG(DISPC_GLOBAL_ALPHA
);
2351 DUMPREG(DISPC_SIZE_DIG
);
2352 DUMPREG(DISPC_SIZE_LCD
);
2354 DUMPREG(DISPC_GFX_BA0
);
2355 DUMPREG(DISPC_GFX_BA1
);
2356 DUMPREG(DISPC_GFX_POSITION
);
2357 DUMPREG(DISPC_GFX_SIZE
);
2358 DUMPREG(DISPC_GFX_ATTRIBUTES
);
2359 DUMPREG(DISPC_GFX_FIFO_THRESHOLD
);
2360 DUMPREG(DISPC_GFX_FIFO_SIZE_STATUS
);
2361 DUMPREG(DISPC_GFX_ROW_INC
);
2362 DUMPREG(DISPC_GFX_PIXEL_INC
);
2363 DUMPREG(DISPC_GFX_WINDOW_SKIP
);
2364 DUMPREG(DISPC_GFX_TABLE_BA
);
2366 DUMPREG(DISPC_DATA_CYCLE1
);
2367 DUMPREG(DISPC_DATA_CYCLE2
);
2368 DUMPREG(DISPC_DATA_CYCLE3
);
2370 DUMPREG(DISPC_CPR_COEF_R
);
2371 DUMPREG(DISPC_CPR_COEF_G
);
2372 DUMPREG(DISPC_CPR_COEF_B
);
2374 DUMPREG(DISPC_GFX_PRELOAD
);
2376 DUMPREG(DISPC_VID_BA0(0));
2377 DUMPREG(DISPC_VID_BA1(0));
2378 DUMPREG(DISPC_VID_POSITION(0));
2379 DUMPREG(DISPC_VID_SIZE(0));
2380 DUMPREG(DISPC_VID_ATTRIBUTES(0));
2381 DUMPREG(DISPC_VID_FIFO_THRESHOLD(0));
2382 DUMPREG(DISPC_VID_FIFO_SIZE_STATUS(0));
2383 DUMPREG(DISPC_VID_ROW_INC(0));
2384 DUMPREG(DISPC_VID_PIXEL_INC(0));
2385 DUMPREG(DISPC_VID_FIR(0));
2386 DUMPREG(DISPC_VID_PICTURE_SIZE(0));
2387 DUMPREG(DISPC_VID_ACCU0(0));
2388 DUMPREG(DISPC_VID_ACCU1(0));
2390 DUMPREG(DISPC_VID_BA0(1));
2391 DUMPREG(DISPC_VID_BA1(1));
2392 DUMPREG(DISPC_VID_POSITION(1));
2393 DUMPREG(DISPC_VID_SIZE(1));
2394 DUMPREG(DISPC_VID_ATTRIBUTES(1));
2395 DUMPREG(DISPC_VID_FIFO_THRESHOLD(1));
2396 DUMPREG(DISPC_VID_FIFO_SIZE_STATUS(1));
2397 DUMPREG(DISPC_VID_ROW_INC(1));
2398 DUMPREG(DISPC_VID_PIXEL_INC(1));
2399 DUMPREG(DISPC_VID_FIR(1));
2400 DUMPREG(DISPC_VID_PICTURE_SIZE(1));
2401 DUMPREG(DISPC_VID_ACCU0(1));
2402 DUMPREG(DISPC_VID_ACCU1(1));
2404 DUMPREG(DISPC_VID_FIR_COEF_H(0, 0));
2405 DUMPREG(DISPC_VID_FIR_COEF_H(0, 1));
2406 DUMPREG(DISPC_VID_FIR_COEF_H(0, 2));
2407 DUMPREG(DISPC_VID_FIR_COEF_H(0, 3));
2408 DUMPREG(DISPC_VID_FIR_COEF_H(0, 4));
2409 DUMPREG(DISPC_VID_FIR_COEF_H(0, 5));
2410 DUMPREG(DISPC_VID_FIR_COEF_H(0, 6));
2411 DUMPREG(DISPC_VID_FIR_COEF_H(0, 7));
2412 DUMPREG(DISPC_VID_FIR_COEF_HV(0, 0));
2413 DUMPREG(DISPC_VID_FIR_COEF_HV(0, 1));
2414 DUMPREG(DISPC_VID_FIR_COEF_HV(0, 2));
2415 DUMPREG(DISPC_VID_FIR_COEF_HV(0, 3));
2416 DUMPREG(DISPC_VID_FIR_COEF_HV(0, 4));
2417 DUMPREG(DISPC_VID_FIR_COEF_HV(0, 5));
2418 DUMPREG(DISPC_VID_FIR_COEF_HV(0, 6));
2419 DUMPREG(DISPC_VID_FIR_COEF_HV(0, 7));
2420 DUMPREG(DISPC_VID_CONV_COEF(0, 0));
2421 DUMPREG(DISPC_VID_CONV_COEF(0, 1));
2422 DUMPREG(DISPC_VID_CONV_COEF(0, 2));
2423 DUMPREG(DISPC_VID_CONV_COEF(0, 3));
2424 DUMPREG(DISPC_VID_CONV_COEF(0, 4));
2425 DUMPREG(DISPC_VID_FIR_COEF_V(0, 0));
2426 DUMPREG(DISPC_VID_FIR_COEF_V(0, 1));
2427 DUMPREG(DISPC_VID_FIR_COEF_V(0, 2));
2428 DUMPREG(DISPC_VID_FIR_COEF_V(0, 3));
2429 DUMPREG(DISPC_VID_FIR_COEF_V(0, 4));
2430 DUMPREG(DISPC_VID_FIR_COEF_V(0, 5));
2431 DUMPREG(DISPC_VID_FIR_COEF_V(0, 6));
2432 DUMPREG(DISPC_VID_FIR_COEF_V(0, 7));
2434 DUMPREG(DISPC_VID_FIR_COEF_H(1, 0));
2435 DUMPREG(DISPC_VID_FIR_COEF_H(1, 1));
2436 DUMPREG(DISPC_VID_FIR_COEF_H(1, 2));
2437 DUMPREG(DISPC_VID_FIR_COEF_H(1, 3));
2438 DUMPREG(DISPC_VID_FIR_COEF_H(1, 4));
2439 DUMPREG(DISPC_VID_FIR_COEF_H(1, 5));
2440 DUMPREG(DISPC_VID_FIR_COEF_H(1, 6));
2441 DUMPREG(DISPC_VID_FIR_COEF_H(1, 7));
2442 DUMPREG(DISPC_VID_FIR_COEF_HV(1, 0));
2443 DUMPREG(DISPC_VID_FIR_COEF_HV(1, 1));
2444 DUMPREG(DISPC_VID_FIR_COEF_HV(1, 2));
2445 DUMPREG(DISPC_VID_FIR_COEF_HV(1, 3));
2446 DUMPREG(DISPC_VID_FIR_COEF_HV(1, 4));
2447 DUMPREG(DISPC_VID_FIR_COEF_HV(1, 5));
2448 DUMPREG(DISPC_VID_FIR_COEF_HV(1, 6));
2449 DUMPREG(DISPC_VID_FIR_COEF_HV(1, 7));
2450 DUMPREG(DISPC_VID_CONV_COEF(1, 0));
2451 DUMPREG(DISPC_VID_CONV_COEF(1, 1));
2452 DUMPREG(DISPC_VID_CONV_COEF(1, 2));
2453 DUMPREG(DISPC_VID_CONV_COEF(1, 3));
2454 DUMPREG(DISPC_VID_CONV_COEF(1, 4));
2455 DUMPREG(DISPC_VID_FIR_COEF_V(1, 0));
2456 DUMPREG(DISPC_VID_FIR_COEF_V(1, 1));
2457 DUMPREG(DISPC_VID_FIR_COEF_V(1, 2));
2458 DUMPREG(DISPC_VID_FIR_COEF_V(1, 3));
2459 DUMPREG(DISPC_VID_FIR_COEF_V(1, 4));
2460 DUMPREG(DISPC_VID_FIR_COEF_V(1, 5));
2461 DUMPREG(DISPC_VID_FIR_COEF_V(1, 6));
2462 DUMPREG(DISPC_VID_FIR_COEF_V(1, 7));
2464 DUMPREG(DISPC_VID_PRELOAD(0));
2465 DUMPREG(DISPC_VID_PRELOAD(1));
2467 dss_clk_disable(DSS_CLK_ICK
| DSS_CLK_FCK1
);
2471 static void _dispc_set_pol_freq(bool onoff
, bool rf
, bool ieo
, bool ipc
,
2472 bool ihs
, bool ivs
, u8 acbi
, u8 acb
)
2476 DSSDBG("onoff %d rf %d ieo %d ipc %d ihs %d ivs %d acbi %d acb %d\n",
2477 onoff
, rf
, ieo
, ipc
, ihs
, ivs
, acbi
, acb
);
2479 l
|= FLD_VAL(onoff
, 17, 17);
2480 l
|= FLD_VAL(rf
, 16, 16);
2481 l
|= FLD_VAL(ieo
, 15, 15);
2482 l
|= FLD_VAL(ipc
, 14, 14);
2483 l
|= FLD_VAL(ihs
, 13, 13);
2484 l
|= FLD_VAL(ivs
, 12, 12);
2485 l
|= FLD_VAL(acbi
, 11, 8);
2486 l
|= FLD_VAL(acb
, 7, 0);
2489 dispc_write_reg(DISPC_POL_FREQ
, l
);
2493 void dispc_set_pol_freq(enum omap_panel_config config
, u8 acbi
, u8 acb
)
2495 _dispc_set_pol_freq((config
& OMAP_DSS_LCD_ONOFF
) != 0,
2496 (config
& OMAP_DSS_LCD_RF
) != 0,
2497 (config
& OMAP_DSS_LCD_IEO
) != 0,
2498 (config
& OMAP_DSS_LCD_IPC
) != 0,
2499 (config
& OMAP_DSS_LCD_IHS
) != 0,
2500 (config
& OMAP_DSS_LCD_IVS
) != 0,
2504 /* with fck as input clock rate, find dispc dividers that produce req_pck */
2505 void dispc_find_clk_divs(bool is_tft
, unsigned long req_pck
, unsigned long fck
,
2506 struct dispc_clock_info
*cinfo
)
2508 u16 pcd_min
= is_tft
? 2 : 3;
2509 unsigned long best_pck
;
2510 u16 best_ld
, cur_ld
;
2511 u16 best_pd
, cur_pd
;
2517 for (cur_ld
= 1; cur_ld
<= 255; ++cur_ld
) {
2518 unsigned long lck
= fck
/ cur_ld
;
2520 for (cur_pd
= pcd_min
; cur_pd
<= 255; ++cur_pd
) {
2521 unsigned long pck
= lck
/ cur_pd
;
2522 long old_delta
= abs(best_pck
- req_pck
);
2523 long new_delta
= abs(pck
- req_pck
);
2525 if (best_pck
== 0 || new_delta
< old_delta
) {
2538 if (lck
/ pcd_min
< req_pck
)
2543 cinfo
->lck_div
= best_ld
;
2544 cinfo
->pck_div
= best_pd
;
2545 cinfo
->lck
= fck
/ cinfo
->lck_div
;
2546 cinfo
->pck
= cinfo
->lck
/ cinfo
->pck_div
;
2549 /* calculate clock rates using dividers in cinfo */
2550 int dispc_calc_clock_rates(unsigned long dispc_fclk_rate
,
2551 struct dispc_clock_info
*cinfo
)
2553 if (cinfo
->lck_div
> 255 || cinfo
->lck_div
== 0)
2555 if (cinfo
->pck_div
< 2 || cinfo
->pck_div
> 255)
2558 cinfo
->lck
= dispc_fclk_rate
/ cinfo
->lck_div
;
2559 cinfo
->pck
= cinfo
->lck
/ cinfo
->pck_div
;
2564 int dispc_set_clock_div(struct dispc_clock_info
*cinfo
)
2566 DSSDBG("lck = %lu (%u)\n", cinfo
->lck
, cinfo
->lck_div
);
2567 DSSDBG("pck = %lu (%u)\n", cinfo
->pck
, cinfo
->pck_div
);
2569 dispc_set_lcd_divisor(cinfo
->lck_div
, cinfo
->pck_div
);
2574 int dispc_get_clock_div(struct dispc_clock_info
*cinfo
)
2578 fck
= dispc_fclk_rate();
2580 cinfo
->lck_div
= REG_GET(DISPC_DIVISOR
, 23, 16);
2581 cinfo
->pck_div
= REG_GET(DISPC_DIVISOR
, 7, 0);
2583 cinfo
->lck
= fck
/ cinfo
->lck_div
;
2584 cinfo
->pck
= cinfo
->lck
/ cinfo
->pck_div
;
2589 /* dispc.irq_lock has to be locked by the caller */
2590 static void _omap_dispc_set_irqs(void)
2595 struct omap_dispc_isr_data
*isr_data
;
2597 mask
= dispc
.irq_error_mask
;
2599 for (i
= 0; i
< DISPC_MAX_NR_ISRS
; i
++) {
2600 isr_data
= &dispc
.registered_isr
[i
];
2602 if (isr_data
->isr
== NULL
)
2605 mask
|= isr_data
->mask
;
2610 old_mask
= dispc_read_reg(DISPC_IRQENABLE
);
2611 /* clear the irqstatus for newly enabled irqs */
2612 dispc_write_reg(DISPC_IRQSTATUS
, (mask
^ old_mask
) & mask
);
2614 dispc_write_reg(DISPC_IRQENABLE
, mask
);
2619 int omap_dispc_register_isr(omap_dispc_isr_t isr
, void *arg
, u32 mask
)
2623 unsigned long flags
;
2624 struct omap_dispc_isr_data
*isr_data
;
2629 spin_lock_irqsave(&dispc
.irq_lock
, flags
);
2631 /* check for duplicate entry */
2632 for (i
= 0; i
< DISPC_MAX_NR_ISRS
; i
++) {
2633 isr_data
= &dispc
.registered_isr
[i
];
2634 if (isr_data
->isr
== isr
&& isr_data
->arg
== arg
&&
2635 isr_data
->mask
== mask
) {
2644 for (i
= 0; i
< DISPC_MAX_NR_ISRS
; i
++) {
2645 isr_data
= &dispc
.registered_isr
[i
];
2647 if (isr_data
->isr
!= NULL
)
2650 isr_data
->isr
= isr
;
2651 isr_data
->arg
= arg
;
2652 isr_data
->mask
= mask
;
2658 _omap_dispc_set_irqs();
2660 spin_unlock_irqrestore(&dispc
.irq_lock
, flags
);
2664 spin_unlock_irqrestore(&dispc
.irq_lock
, flags
);
2668 EXPORT_SYMBOL(omap_dispc_register_isr
);
2670 int omap_dispc_unregister_isr(omap_dispc_isr_t isr
, void *arg
, u32 mask
)
2673 unsigned long flags
;
2675 struct omap_dispc_isr_data
*isr_data
;
2677 spin_lock_irqsave(&dispc
.irq_lock
, flags
);
2679 for (i
= 0; i
< DISPC_MAX_NR_ISRS
; i
++) {
2680 isr_data
= &dispc
.registered_isr
[i
];
2681 if (isr_data
->isr
!= isr
|| isr_data
->arg
!= arg
||
2682 isr_data
->mask
!= mask
)
2685 /* found the correct isr */
2687 isr_data
->isr
= NULL
;
2688 isr_data
->arg
= NULL
;
2696 _omap_dispc_set_irqs();
2698 spin_unlock_irqrestore(&dispc
.irq_lock
, flags
);
2702 EXPORT_SYMBOL(omap_dispc_unregister_isr
);
2705 static void print_irq_status(u32 status
)
2707 if ((status
& dispc
.irq_error_mask
) == 0)
2710 printk(KERN_DEBUG
"DISPC IRQ: 0x%x: ", status
);
2713 if (status & DISPC_IRQ_##x) \
2715 PIS(GFX_FIFO_UNDERFLOW
);
2717 PIS(VID1_FIFO_UNDERFLOW
);
2718 PIS(VID2_FIFO_UNDERFLOW
);
2720 PIS(SYNC_LOST_DIGIT
);
2727 /* Called from dss.c. Note that we don't touch clocks here,
2728 * but we presume they are on because we got an IRQ. However,
2729 * an irq handler may turn the clocks off, so we may not have
2730 * clock later in the function. */
2731 void dispc_irq_handler(void)
2735 u32 handledirqs
= 0;
2736 u32 unhandled_errors
;
2737 struct omap_dispc_isr_data
*isr_data
;
2738 struct omap_dispc_isr_data registered_isr
[DISPC_MAX_NR_ISRS
];
2740 spin_lock(&dispc
.irq_lock
);
2742 irqstatus
= dispc_read_reg(DISPC_IRQSTATUS
);
2744 #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
2745 spin_lock(&dispc
.irq_stats_lock
);
2746 dispc
.irq_stats
.irq_count
++;
2747 dss_collect_irq_stats(irqstatus
, dispc
.irq_stats
.irqs
);
2748 spin_unlock(&dispc
.irq_stats_lock
);
2753 print_irq_status(irqstatus
);
2755 /* Ack the interrupt. Do it here before clocks are possibly turned
2757 dispc_write_reg(DISPC_IRQSTATUS
, irqstatus
);
2758 /* flush posted write */
2759 dispc_read_reg(DISPC_IRQSTATUS
);
2761 /* make a copy and unlock, so that isrs can unregister
2763 memcpy(registered_isr
, dispc
.registered_isr
,
2764 sizeof(registered_isr
));
2766 spin_unlock(&dispc
.irq_lock
);
2768 for (i
= 0; i
< DISPC_MAX_NR_ISRS
; i
++) {
2769 isr_data
= ®istered_isr
[i
];
2774 if (isr_data
->mask
& irqstatus
) {
2775 isr_data
->isr(isr_data
->arg
, irqstatus
);
2776 handledirqs
|= isr_data
->mask
;
2780 spin_lock(&dispc
.irq_lock
);
2782 unhandled_errors
= irqstatus
& ~handledirqs
& dispc
.irq_error_mask
;
2784 if (unhandled_errors
) {
2785 dispc
.error_irqs
|= unhandled_errors
;
2787 dispc
.irq_error_mask
&= ~unhandled_errors
;
2788 _omap_dispc_set_irqs();
2790 schedule_work(&dispc
.error_work
);
2793 spin_unlock(&dispc
.irq_lock
);
2796 static void dispc_error_worker(struct work_struct
*work
)
2800 unsigned long flags
;
2802 spin_lock_irqsave(&dispc
.irq_lock
, flags
);
2803 errors
= dispc
.error_irqs
;
2804 dispc
.error_irqs
= 0;
2805 spin_unlock_irqrestore(&dispc
.irq_lock
, flags
);
2807 if (errors
& DISPC_IRQ_GFX_FIFO_UNDERFLOW
) {
2808 DSSERR("GFX_FIFO_UNDERFLOW, disabling GFX\n");
2809 for (i
= 0; i
< omap_dss_get_num_overlays(); ++i
) {
2810 struct omap_overlay
*ovl
;
2811 ovl
= omap_dss_get_overlay(i
);
2813 if (!(ovl
->caps
& OMAP_DSS_OVL_CAP_DISPC
))
2817 dispc_enable_plane(ovl
->id
, 0);
2818 dispc_go(ovl
->manager
->id
);
2825 if (errors
& DISPC_IRQ_VID1_FIFO_UNDERFLOW
) {
2826 DSSERR("VID1_FIFO_UNDERFLOW, disabling VID1\n");
2827 for (i
= 0; i
< omap_dss_get_num_overlays(); ++i
) {
2828 struct omap_overlay
*ovl
;
2829 ovl
= omap_dss_get_overlay(i
);
2831 if (!(ovl
->caps
& OMAP_DSS_OVL_CAP_DISPC
))
2835 dispc_enable_plane(ovl
->id
, 0);
2836 dispc_go(ovl
->manager
->id
);
2843 if (errors
& DISPC_IRQ_VID2_FIFO_UNDERFLOW
) {
2844 DSSERR("VID2_FIFO_UNDERFLOW, disabling VID2\n");
2845 for (i
= 0; i
< omap_dss_get_num_overlays(); ++i
) {
2846 struct omap_overlay
*ovl
;
2847 ovl
= omap_dss_get_overlay(i
);
2849 if (!(ovl
->caps
& OMAP_DSS_OVL_CAP_DISPC
))
2853 dispc_enable_plane(ovl
->id
, 0);
2854 dispc_go(ovl
->manager
->id
);
2861 if (errors
& DISPC_IRQ_SYNC_LOST
) {
2862 struct omap_overlay_manager
*manager
= NULL
;
2863 bool enable
= false;
2865 DSSERR("SYNC_LOST, disabling LCD\n");
2867 for (i
= 0; i
< omap_dss_get_num_overlay_managers(); ++i
) {
2868 struct omap_overlay_manager
*mgr
;
2869 mgr
= omap_dss_get_overlay_manager(i
);
2871 if (mgr
->id
== OMAP_DSS_CHANNEL_LCD
) {
2873 enable
= mgr
->device
->state
==
2874 OMAP_DSS_DISPLAY_ACTIVE
;
2875 mgr
->device
->driver
->disable(mgr
->device
);
2881 struct omap_dss_device
*dssdev
= manager
->device
;
2882 for (i
= 0; i
< omap_dss_get_num_overlays(); ++i
) {
2883 struct omap_overlay
*ovl
;
2884 ovl
= omap_dss_get_overlay(i
);
2886 if (!(ovl
->caps
& OMAP_DSS_OVL_CAP_DISPC
))
2889 if (ovl
->id
!= 0 && ovl
->manager
== manager
)
2890 dispc_enable_plane(ovl
->id
, 0);
2893 dispc_go(manager
->id
);
2896 dssdev
->driver
->enable(dssdev
);
2900 if (errors
& DISPC_IRQ_SYNC_LOST_DIGIT
) {
2901 struct omap_overlay_manager
*manager
= NULL
;
2902 bool enable
= false;
2904 DSSERR("SYNC_LOST_DIGIT, disabling TV\n");
2906 for (i
= 0; i
< omap_dss_get_num_overlay_managers(); ++i
) {
2907 struct omap_overlay_manager
*mgr
;
2908 mgr
= omap_dss_get_overlay_manager(i
);
2910 if (mgr
->id
== OMAP_DSS_CHANNEL_DIGIT
) {
2912 enable
= mgr
->device
->state
==
2913 OMAP_DSS_DISPLAY_ACTIVE
;
2914 mgr
->device
->driver
->disable(mgr
->device
);
2920 struct omap_dss_device
*dssdev
= manager
->device
;
2921 for (i
= 0; i
< omap_dss_get_num_overlays(); ++i
) {
2922 struct omap_overlay
*ovl
;
2923 ovl
= omap_dss_get_overlay(i
);
2925 if (!(ovl
->caps
& OMAP_DSS_OVL_CAP_DISPC
))
2928 if (ovl
->id
!= 0 && ovl
->manager
== manager
)
2929 dispc_enable_plane(ovl
->id
, 0);
2932 dispc_go(manager
->id
);
2935 dssdev
->driver
->enable(dssdev
);
2939 if (errors
& DISPC_IRQ_OCP_ERR
) {
2940 DSSERR("OCP_ERR\n");
2941 for (i
= 0; i
< omap_dss_get_num_overlay_managers(); ++i
) {
2942 struct omap_overlay_manager
*mgr
;
2943 mgr
= omap_dss_get_overlay_manager(i
);
2945 if (mgr
->caps
& OMAP_DSS_OVL_CAP_DISPC
)
2946 mgr
->device
->driver
->disable(mgr
->device
);
2950 spin_lock_irqsave(&dispc
.irq_lock
, flags
);
2951 dispc
.irq_error_mask
|= errors
;
2952 _omap_dispc_set_irqs();
2953 spin_unlock_irqrestore(&dispc
.irq_lock
, flags
);
2956 int omap_dispc_wait_for_irq_timeout(u32 irqmask
, unsigned long timeout
)
2958 void dispc_irq_wait_handler(void *data
, u32 mask
)
2960 complete((struct completion
*)data
);
2964 DECLARE_COMPLETION_ONSTACK(completion
);
2966 r
= omap_dispc_register_isr(dispc_irq_wait_handler
, &completion
,
2972 timeout
= wait_for_completion_timeout(&completion
, timeout
);
2974 omap_dispc_unregister_isr(dispc_irq_wait_handler
, &completion
, irqmask
);
2979 if (timeout
== -ERESTARTSYS
)
2980 return -ERESTARTSYS
;
2985 int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask
,
2986 unsigned long timeout
)
2988 void dispc_irq_wait_handler(void *data
, u32 mask
)
2990 complete((struct completion
*)data
);
2994 DECLARE_COMPLETION_ONSTACK(completion
);
2996 r
= omap_dispc_register_isr(dispc_irq_wait_handler
, &completion
,
3002 timeout
= wait_for_completion_interruptible_timeout(&completion
,
3005 omap_dispc_unregister_isr(dispc_irq_wait_handler
, &completion
, irqmask
);
3010 if (timeout
== -ERESTARTSYS
)
3011 return -ERESTARTSYS
;
3016 #ifdef CONFIG_OMAP2_DSS_FAKE_VSYNC
3017 void dispc_fake_vsync_irq(void)
3019 u32 irqstatus
= DISPC_IRQ_VSYNC
;
3022 local_irq_disable();
3024 for (i
= 0; i
< DISPC_MAX_NR_ISRS
; i
++) {
3025 struct omap_dispc_isr_data
*isr_data
;
3026 isr_data
= &dispc
.registered_isr
[i
];
3031 if (isr_data
->mask
& irqstatus
)
3032 isr_data
->isr(isr_data
->arg
, irqstatus
);
3039 static void _omap_dispc_initialize_irq(void)
3041 unsigned long flags
;
3043 spin_lock_irqsave(&dispc
.irq_lock
, flags
);
3045 memset(dispc
.registered_isr
, 0, sizeof(dispc
.registered_isr
));
3047 dispc
.irq_error_mask
= DISPC_IRQ_MASK_ERROR
;
3049 /* there's SYNC_LOST_DIGIT waiting after enabling the DSS,
3051 dispc_write_reg(DISPC_IRQSTATUS
, dispc_read_reg(DISPC_IRQSTATUS
));
3053 _omap_dispc_set_irqs();
3055 spin_unlock_irqrestore(&dispc
.irq_lock
, flags
);
3058 void dispc_enable_sidle(void)
3060 REG_FLD_MOD(DISPC_SYSCONFIG
, 2, 4, 3); /* SIDLEMODE: smart idle */
3063 void dispc_disable_sidle(void)
3065 REG_FLD_MOD(DISPC_SYSCONFIG
, 1, 4, 3); /* SIDLEMODE: no idle */
3068 static void _omap_dispc_initial_config(void)
3072 l
= dispc_read_reg(DISPC_SYSCONFIG
);
3073 l
= FLD_MOD(l
, 2, 13, 12); /* MIDLEMODE: smart standby */
3074 l
= FLD_MOD(l
, 2, 4, 3); /* SIDLEMODE: smart idle */
3075 l
= FLD_MOD(l
, 1, 2, 2); /* ENWAKEUP */
3076 l
= FLD_MOD(l
, 1, 0, 0); /* AUTOIDLE */
3077 dispc_write_reg(DISPC_SYSCONFIG
, l
);
3080 REG_FLD_MOD(DISPC_CONFIG
, 1, 9, 9);
3082 /* L3 firewall setting: enable access to OCM RAM */
3083 /* XXX this should be somewhere in plat-omap */
3084 if (cpu_is_omap24xx())
3085 __raw_writel(0x402000b0, OMAP2_L3_IO_ADDRESS(0x680050a0));
3087 _dispc_setup_color_conv_coef();
3089 dispc_set_loadmode(OMAP_DSS_LOAD_FRAME_ONLY
);
3091 dispc_read_plane_fifo_sizes();
3094 int dispc_init(void)
3098 spin_lock_init(&dispc
.irq_lock
);
3100 #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
3101 spin_lock_init(&dispc
.irq_stats_lock
);
3102 dispc
.irq_stats
.last_reset
= jiffies
;
3105 INIT_WORK(&dispc
.error_work
, dispc_error_worker
);
3107 dispc
.base
= ioremap(DISPC_BASE
, DISPC_SZ_REGS
);
3109 DSSERR("can't ioremap DISPC\n");
3115 _omap_dispc_initial_config();
3117 _omap_dispc_initialize_irq();
3119 dispc_save_context();
3121 rev
= dispc_read_reg(DISPC_REVISION
);
3122 printk(KERN_INFO
"OMAP DISPC rev %d.%d\n",
3123 FLD_GET(rev
, 7, 4), FLD_GET(rev
, 3, 0));
3130 void dispc_exit(void)
3132 iounmap(dispc
.base
);
3135 int dispc_enable_plane(enum omap_plane plane
, bool enable
)
3137 DSSDBG("dispc_enable_plane %d, %d\n", plane
, enable
);
3140 _dispc_enable_plane(plane
, enable
);
3146 int dispc_setup_plane(enum omap_plane plane
,
3147 u32 paddr
, u16 screen_width
,
3148 u16 pos_x
, u16 pos_y
,
3149 u16 width
, u16 height
,
3150 u16 out_width
, u16 out_height
,
3151 enum omap_color_mode color_mode
,
3153 enum omap_dss_rotation_type rotation_type
,
3154 u8 rotation
, bool mirror
, u8 global_alpha
)
3158 DSSDBG("dispc_setup_plane %d, pa %x, sw %d, %d,%d, %dx%d -> "
3159 "%dx%d, ilace %d, cmode %x, rot %d, mir %d\n",
3160 plane
, paddr
, screen_width
, pos_x
, pos_y
,
3162 out_width
, out_height
,
3168 r
= _dispc_setup_plane(plane
,
3169 paddr
, screen_width
,
3172 out_width
, out_height
,