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) };
158 struct omap_dispc_isr_data registered_isr
[DISPC_MAX_NR_ISRS
];
160 struct work_struct error_work
;
162 u32 ctx
[DISPC_SZ_REGS
/ sizeof(u32
)];
165 static void _omap_dispc_set_irqs(void);
167 static inline void dispc_write_reg(const struct dispc_reg idx
, u32 val
)
169 __raw_writel(val
, dispc
.base
+ idx
.idx
);
172 static inline u32
dispc_read_reg(const struct dispc_reg idx
)
174 return __raw_readl(dispc
.base
+ idx
.idx
);
178 dispc.ctx[(DISPC_##reg).idx / sizeof(u32)] = dispc_read_reg(DISPC_##reg)
180 dispc_write_reg(DISPC_##reg, dispc.ctx[(DISPC_##reg).idx / sizeof(u32)])
182 void dispc_save_context(void)
184 if (cpu_is_omap24xx())
209 SR(GFX_FIFO_THRESHOLD
);
230 SR(VID_ATTRIBUTES(0));
231 SR(VID_FIFO_THRESHOLD(0));
233 SR(VID_PIXEL_INC(0));
235 SR(VID_PICTURE_SIZE(0));
239 SR(VID_FIR_COEF_H(0, 0));
240 SR(VID_FIR_COEF_H(0, 1));
241 SR(VID_FIR_COEF_H(0, 2));
242 SR(VID_FIR_COEF_H(0, 3));
243 SR(VID_FIR_COEF_H(0, 4));
244 SR(VID_FIR_COEF_H(0, 5));
245 SR(VID_FIR_COEF_H(0, 6));
246 SR(VID_FIR_COEF_H(0, 7));
248 SR(VID_FIR_COEF_HV(0, 0));
249 SR(VID_FIR_COEF_HV(0, 1));
250 SR(VID_FIR_COEF_HV(0, 2));
251 SR(VID_FIR_COEF_HV(0, 3));
252 SR(VID_FIR_COEF_HV(0, 4));
253 SR(VID_FIR_COEF_HV(0, 5));
254 SR(VID_FIR_COEF_HV(0, 6));
255 SR(VID_FIR_COEF_HV(0, 7));
257 SR(VID_CONV_COEF(0, 0));
258 SR(VID_CONV_COEF(0, 1));
259 SR(VID_CONV_COEF(0, 2));
260 SR(VID_CONV_COEF(0, 3));
261 SR(VID_CONV_COEF(0, 4));
263 SR(VID_FIR_COEF_V(0, 0));
264 SR(VID_FIR_COEF_V(0, 1));
265 SR(VID_FIR_COEF_V(0, 2));
266 SR(VID_FIR_COEF_V(0, 3));
267 SR(VID_FIR_COEF_V(0, 4));
268 SR(VID_FIR_COEF_V(0, 5));
269 SR(VID_FIR_COEF_V(0, 6));
270 SR(VID_FIR_COEF_V(0, 7));
279 SR(VID_ATTRIBUTES(1));
280 SR(VID_FIFO_THRESHOLD(1));
282 SR(VID_PIXEL_INC(1));
284 SR(VID_PICTURE_SIZE(1));
288 SR(VID_FIR_COEF_H(1, 0));
289 SR(VID_FIR_COEF_H(1, 1));
290 SR(VID_FIR_COEF_H(1, 2));
291 SR(VID_FIR_COEF_H(1, 3));
292 SR(VID_FIR_COEF_H(1, 4));
293 SR(VID_FIR_COEF_H(1, 5));
294 SR(VID_FIR_COEF_H(1, 6));
295 SR(VID_FIR_COEF_H(1, 7));
297 SR(VID_FIR_COEF_HV(1, 0));
298 SR(VID_FIR_COEF_HV(1, 1));
299 SR(VID_FIR_COEF_HV(1, 2));
300 SR(VID_FIR_COEF_HV(1, 3));
301 SR(VID_FIR_COEF_HV(1, 4));
302 SR(VID_FIR_COEF_HV(1, 5));
303 SR(VID_FIR_COEF_HV(1, 6));
304 SR(VID_FIR_COEF_HV(1, 7));
306 SR(VID_CONV_COEF(1, 0));
307 SR(VID_CONV_COEF(1, 1));
308 SR(VID_CONV_COEF(1, 2));
309 SR(VID_CONV_COEF(1, 3));
310 SR(VID_CONV_COEF(1, 4));
312 SR(VID_FIR_COEF_V(1, 0));
313 SR(VID_FIR_COEF_V(1, 1));
314 SR(VID_FIR_COEF_V(1, 2));
315 SR(VID_FIR_COEF_V(1, 3));
316 SR(VID_FIR_COEF_V(1, 4));
317 SR(VID_FIR_COEF_V(1, 5));
318 SR(VID_FIR_COEF_V(1, 6));
319 SR(VID_FIR_COEF_V(1, 7));
324 void dispc_restore_context(void)
348 RR(GFX_FIFO_THRESHOLD
);
369 RR(VID_ATTRIBUTES(0));
370 RR(VID_FIFO_THRESHOLD(0));
372 RR(VID_PIXEL_INC(0));
374 RR(VID_PICTURE_SIZE(0));
378 RR(VID_FIR_COEF_H(0, 0));
379 RR(VID_FIR_COEF_H(0, 1));
380 RR(VID_FIR_COEF_H(0, 2));
381 RR(VID_FIR_COEF_H(0, 3));
382 RR(VID_FIR_COEF_H(0, 4));
383 RR(VID_FIR_COEF_H(0, 5));
384 RR(VID_FIR_COEF_H(0, 6));
385 RR(VID_FIR_COEF_H(0, 7));
387 RR(VID_FIR_COEF_HV(0, 0));
388 RR(VID_FIR_COEF_HV(0, 1));
389 RR(VID_FIR_COEF_HV(0, 2));
390 RR(VID_FIR_COEF_HV(0, 3));
391 RR(VID_FIR_COEF_HV(0, 4));
392 RR(VID_FIR_COEF_HV(0, 5));
393 RR(VID_FIR_COEF_HV(0, 6));
394 RR(VID_FIR_COEF_HV(0, 7));
396 RR(VID_CONV_COEF(0, 0));
397 RR(VID_CONV_COEF(0, 1));
398 RR(VID_CONV_COEF(0, 2));
399 RR(VID_CONV_COEF(0, 3));
400 RR(VID_CONV_COEF(0, 4));
402 RR(VID_FIR_COEF_V(0, 0));
403 RR(VID_FIR_COEF_V(0, 1));
404 RR(VID_FIR_COEF_V(0, 2));
405 RR(VID_FIR_COEF_V(0, 3));
406 RR(VID_FIR_COEF_V(0, 4));
407 RR(VID_FIR_COEF_V(0, 5));
408 RR(VID_FIR_COEF_V(0, 6));
409 RR(VID_FIR_COEF_V(0, 7));
418 RR(VID_ATTRIBUTES(1));
419 RR(VID_FIFO_THRESHOLD(1));
421 RR(VID_PIXEL_INC(1));
423 RR(VID_PICTURE_SIZE(1));
427 RR(VID_FIR_COEF_H(1, 0));
428 RR(VID_FIR_COEF_H(1, 1));
429 RR(VID_FIR_COEF_H(1, 2));
430 RR(VID_FIR_COEF_H(1, 3));
431 RR(VID_FIR_COEF_H(1, 4));
432 RR(VID_FIR_COEF_H(1, 5));
433 RR(VID_FIR_COEF_H(1, 6));
434 RR(VID_FIR_COEF_H(1, 7));
436 RR(VID_FIR_COEF_HV(1, 0));
437 RR(VID_FIR_COEF_HV(1, 1));
438 RR(VID_FIR_COEF_HV(1, 2));
439 RR(VID_FIR_COEF_HV(1, 3));
440 RR(VID_FIR_COEF_HV(1, 4));
441 RR(VID_FIR_COEF_HV(1, 5));
442 RR(VID_FIR_COEF_HV(1, 6));
443 RR(VID_FIR_COEF_HV(1, 7));
445 RR(VID_CONV_COEF(1, 0));
446 RR(VID_CONV_COEF(1, 1));
447 RR(VID_CONV_COEF(1, 2));
448 RR(VID_CONV_COEF(1, 3));
449 RR(VID_CONV_COEF(1, 4));
451 RR(VID_FIR_COEF_V(1, 0));
452 RR(VID_FIR_COEF_V(1, 1));
453 RR(VID_FIR_COEF_V(1, 2));
454 RR(VID_FIR_COEF_V(1, 3));
455 RR(VID_FIR_COEF_V(1, 4));
456 RR(VID_FIR_COEF_V(1, 5));
457 RR(VID_FIR_COEF_V(1, 6));
458 RR(VID_FIR_COEF_V(1, 7));
462 /* enable last, because LCD & DIGIT enable are here */
469 static inline void enable_clocks(bool enable
)
472 dss_clk_enable(DSS_CLK_ICK
| DSS_CLK_FCK1
);
474 dss_clk_disable(DSS_CLK_ICK
| DSS_CLK_FCK1
);
477 bool dispc_go_busy(enum omap_channel channel
)
481 if (channel
== OMAP_DSS_CHANNEL_LCD
)
484 bit
= 6; /* GODIGIT */
486 return REG_GET(DISPC_CONTROL
, bit
, bit
) == 1;
489 void dispc_go(enum omap_channel channel
)
495 if (channel
== OMAP_DSS_CHANNEL_LCD
)
496 bit
= 0; /* LCDENABLE */
498 bit
= 1; /* DIGITALENABLE */
500 /* if the channel is not enabled, we don't need GO */
501 if (REG_GET(DISPC_CONTROL
, bit
, bit
) == 0)
504 if (channel
== OMAP_DSS_CHANNEL_LCD
)
507 bit
= 6; /* GODIGIT */
509 if (REG_GET(DISPC_CONTROL
, bit
, bit
) == 1) {
510 DSSERR("GO bit not down for channel %d\n", channel
);
514 DSSDBG("GO %s\n", channel
== OMAP_DSS_CHANNEL_LCD
? "LCD" : "DIGIT");
516 REG_FLD_MOD(DISPC_CONTROL
, 1, bit
, bit
);
521 static void _dispc_write_firh_reg(enum omap_plane plane
, int reg
, u32 value
)
523 BUG_ON(plane
== OMAP_DSS_GFX
);
525 dispc_write_reg(DISPC_VID_FIR_COEF_H(plane
-1, reg
), value
);
528 static void _dispc_write_firhv_reg(enum omap_plane plane
, int reg
, u32 value
)
530 BUG_ON(plane
== OMAP_DSS_GFX
);
532 dispc_write_reg(DISPC_VID_FIR_COEF_HV(plane
-1, reg
), value
);
535 static void _dispc_write_firv_reg(enum omap_plane plane
, int reg
, u32 value
)
537 BUG_ON(plane
== OMAP_DSS_GFX
);
539 dispc_write_reg(DISPC_VID_FIR_COEF_V(plane
-1, reg
), value
);
542 static void _dispc_set_scale_coef(enum omap_plane plane
, int hscaleup
,
543 int vscaleup
, int five_taps
)
545 /* Coefficients for horizontal up-sampling */
546 static const u32 coef_hup
[8] = {
557 /* Coefficients for horizontal down-sampling */
558 static const u32 coef_hdown
[8] = {
569 /* Coefficients for horizontal and vertical up-sampling */
570 static const u32 coef_hvup
[2][8] = {
593 /* Coefficients for horizontal and vertical down-sampling */
594 static const u32 coef_hvdown
[2][8] = {
617 /* Coefficients for vertical up-sampling */
618 static const u32 coef_vup
[8] = {
630 /* Coefficients for vertical down-sampling */
631 static const u32 coef_vdown
[8] = {
644 const u32
*hv_coef_mod
;
654 hv_coef
= coef_hvup
[five_taps
];
660 hv_coef_mod
= coef_hvdown
[five_taps
];
662 hv_coef
= coef_hvdown
[five_taps
];
666 hv_coef_mod
= coef_hvup
[five_taps
];
671 for (i
= 0; i
< 8; i
++) {
680 hv
|= (hv_coef_mod
[i
] & 0xff);
683 _dispc_write_firh_reg(plane
, i
, h
);
684 _dispc_write_firhv_reg(plane
, i
, hv
);
690 for (i
= 0; i
< 8; i
++) {
693 _dispc_write_firv_reg(plane
, i
, v
);
697 static void _dispc_setup_color_conv_coef(void)
699 const struct color_conv_coef
{
700 int ry
, rcr
, rcb
, gy
, gcr
, gcb
, by
, bcr
, bcb
;
703 298, 409, 0, 298, -208, -100, 298, 0, 517, 0,
706 const struct color_conv_coef
*ct
;
708 #define CVAL(x, y) (FLD_VAL(x, 26, 16) | FLD_VAL(y, 10, 0))
712 dispc_write_reg(DISPC_VID_CONV_COEF(0, 0), CVAL(ct
->rcr
, ct
->ry
));
713 dispc_write_reg(DISPC_VID_CONV_COEF(0, 1), CVAL(ct
->gy
, ct
->rcb
));
714 dispc_write_reg(DISPC_VID_CONV_COEF(0, 2), CVAL(ct
->gcb
, ct
->gcr
));
715 dispc_write_reg(DISPC_VID_CONV_COEF(0, 3), CVAL(ct
->bcr
, ct
->by
));
716 dispc_write_reg(DISPC_VID_CONV_COEF(0, 4), CVAL(0, ct
->bcb
));
718 dispc_write_reg(DISPC_VID_CONV_COEF(1, 0), CVAL(ct
->rcr
, ct
->ry
));
719 dispc_write_reg(DISPC_VID_CONV_COEF(1, 1), CVAL(ct
->gy
, ct
->rcb
));
720 dispc_write_reg(DISPC_VID_CONV_COEF(1, 2), CVAL(ct
->gcb
, ct
->gcr
));
721 dispc_write_reg(DISPC_VID_CONV_COEF(1, 3), CVAL(ct
->bcr
, ct
->by
));
722 dispc_write_reg(DISPC_VID_CONV_COEF(1, 4), CVAL(0, ct
->bcb
));
726 REG_FLD_MOD(DISPC_VID_ATTRIBUTES(0), ct
->full_range
, 11, 11);
727 REG_FLD_MOD(DISPC_VID_ATTRIBUTES(1), ct
->full_range
, 11, 11);
731 static void _dispc_set_plane_ba0(enum omap_plane plane
, u32 paddr
)
733 const struct dispc_reg ba0_reg
[] = { DISPC_GFX_BA0
,
737 dispc_write_reg(ba0_reg
[plane
], paddr
);
740 static void _dispc_set_plane_ba1(enum omap_plane plane
, u32 paddr
)
742 const struct dispc_reg ba1_reg
[] = { DISPC_GFX_BA1
,
746 dispc_write_reg(ba1_reg
[plane
], paddr
);
749 static void _dispc_set_plane_pos(enum omap_plane plane
, int x
, int y
)
751 const struct dispc_reg pos_reg
[] = { DISPC_GFX_POSITION
,
752 DISPC_VID_POSITION(0),
753 DISPC_VID_POSITION(1) };
755 u32 val
= FLD_VAL(y
, 26, 16) | FLD_VAL(x
, 10, 0);
756 dispc_write_reg(pos_reg
[plane
], val
);
759 static void _dispc_set_pic_size(enum omap_plane plane
, int width
, int height
)
761 const struct dispc_reg siz_reg
[] = { DISPC_GFX_SIZE
,
762 DISPC_VID_PICTURE_SIZE(0),
763 DISPC_VID_PICTURE_SIZE(1) };
764 u32 val
= FLD_VAL(height
- 1, 26, 16) | FLD_VAL(width
- 1, 10, 0);
765 dispc_write_reg(siz_reg
[plane
], val
);
768 static void _dispc_set_vid_size(enum omap_plane plane
, int width
, int height
)
771 const struct dispc_reg vsi_reg
[] = { DISPC_VID_SIZE(0),
774 BUG_ON(plane
== OMAP_DSS_GFX
);
776 val
= FLD_VAL(height
- 1, 26, 16) | FLD_VAL(width
- 1, 10, 0);
777 dispc_write_reg(vsi_reg
[plane
-1], val
);
780 static void _dispc_setup_global_alpha(enum omap_plane plane
, u8 global_alpha
)
783 BUG_ON(plane
== OMAP_DSS_VIDEO1
);
785 if (cpu_is_omap24xx())
788 if (plane
== OMAP_DSS_GFX
)
789 REG_FLD_MOD(DISPC_GLOBAL_ALPHA
, global_alpha
, 7, 0);
790 else if (plane
== OMAP_DSS_VIDEO2
)
791 REG_FLD_MOD(DISPC_GLOBAL_ALPHA
, global_alpha
, 23, 16);
794 static void _dispc_set_pix_inc(enum omap_plane plane
, s32 inc
)
796 const struct dispc_reg ri_reg
[] = { DISPC_GFX_PIXEL_INC
,
797 DISPC_VID_PIXEL_INC(0),
798 DISPC_VID_PIXEL_INC(1) };
800 dispc_write_reg(ri_reg
[plane
], inc
);
803 static void _dispc_set_row_inc(enum omap_plane plane
, s32 inc
)
805 const struct dispc_reg ri_reg
[] = { DISPC_GFX_ROW_INC
,
806 DISPC_VID_ROW_INC(0),
807 DISPC_VID_ROW_INC(1) };
809 dispc_write_reg(ri_reg
[plane
], inc
);
812 static void _dispc_set_color_mode(enum omap_plane plane
,
813 enum omap_color_mode color_mode
)
817 switch (color_mode
) {
818 case OMAP_DSS_COLOR_CLUT1
:
820 case OMAP_DSS_COLOR_CLUT2
:
822 case OMAP_DSS_COLOR_CLUT4
:
824 case OMAP_DSS_COLOR_CLUT8
:
826 case OMAP_DSS_COLOR_RGB12U
:
828 case OMAP_DSS_COLOR_ARGB16
:
830 case OMAP_DSS_COLOR_RGB16
:
832 case OMAP_DSS_COLOR_RGB24U
:
834 case OMAP_DSS_COLOR_RGB24P
:
836 case OMAP_DSS_COLOR_YUV2
:
838 case OMAP_DSS_COLOR_UYVY
:
840 case OMAP_DSS_COLOR_ARGB32
:
842 case OMAP_DSS_COLOR_RGBA32
:
844 case OMAP_DSS_COLOR_RGBX32
:
850 REG_FLD_MOD(dispc_reg_att
[plane
], m
, 4, 1);
853 static void _dispc_set_channel_out(enum omap_plane plane
,
854 enum omap_channel channel
)
863 case OMAP_DSS_VIDEO1
:
864 case OMAP_DSS_VIDEO2
:
872 val
= dispc_read_reg(dispc_reg_att
[plane
]);
873 val
= FLD_MOD(val
, channel
, shift
, shift
);
874 dispc_write_reg(dispc_reg_att
[plane
], val
);
877 void dispc_set_burst_size(enum omap_plane plane
,
878 enum omap_burst_size burst_size
)
889 case OMAP_DSS_VIDEO1
:
890 case OMAP_DSS_VIDEO2
:
898 val
= dispc_read_reg(dispc_reg_att
[plane
]);
899 val
= FLD_MOD(val
, burst_size
, shift
+1, shift
);
900 dispc_write_reg(dispc_reg_att
[plane
], val
);
905 static void _dispc_set_vid_color_conv(enum omap_plane plane
, bool enable
)
909 BUG_ON(plane
== OMAP_DSS_GFX
);
911 val
= dispc_read_reg(dispc_reg_att
[plane
]);
912 val
= FLD_MOD(val
, enable
, 9, 9);
913 dispc_write_reg(dispc_reg_att
[plane
], val
);
916 void dispc_enable_replication(enum omap_plane plane
, bool enable
)
920 if (plane
== OMAP_DSS_GFX
)
926 REG_FLD_MOD(dispc_reg_att
[plane
], enable
, bit
, bit
);
930 void dispc_set_lcd_size(u16 width
, u16 height
)
933 BUG_ON((width
> (1 << 11)) || (height
> (1 << 11)));
934 val
= FLD_VAL(height
- 1, 26, 16) | FLD_VAL(width
- 1, 10, 0);
936 dispc_write_reg(DISPC_SIZE_LCD
, val
);
940 void dispc_set_digit_size(u16 width
, u16 height
)
943 BUG_ON((width
> (1 << 11)) || (height
> (1 << 11)));
944 val
= FLD_VAL(height
- 1, 26, 16) | FLD_VAL(width
- 1, 10, 0);
946 dispc_write_reg(DISPC_SIZE_DIG
, val
);
950 static void dispc_read_plane_fifo_sizes(void)
952 const struct dispc_reg fsz_reg
[] = { DISPC_GFX_FIFO_SIZE_STATUS
,
953 DISPC_VID_FIFO_SIZE_STATUS(0),
954 DISPC_VID_FIFO_SIZE_STATUS(1) };
960 for (plane
= 0; plane
< ARRAY_SIZE(dispc
.fifo_size
); ++plane
) {
961 if (cpu_is_omap24xx())
962 size
= FLD_GET(dispc_read_reg(fsz_reg
[plane
]), 8, 0);
963 else if (cpu_is_omap34xx())
964 size
= FLD_GET(dispc_read_reg(fsz_reg
[plane
]), 10, 0);
968 dispc
.fifo_size
[plane
] = size
;
974 u32
dispc_get_plane_fifo_size(enum omap_plane plane
)
976 return dispc
.fifo_size
[plane
];
979 void dispc_setup_plane_fifo(enum omap_plane plane
, u32 low
, u32 high
)
981 const struct dispc_reg ftrs_reg
[] = { DISPC_GFX_FIFO_THRESHOLD
,
982 DISPC_VID_FIFO_THRESHOLD(0),
983 DISPC_VID_FIFO_THRESHOLD(1) };
986 DSSDBG("fifo(%d) low/high old %u/%u, new %u/%u\n",
988 REG_GET(ftrs_reg
[plane
], 11, 0),
989 REG_GET(ftrs_reg
[plane
], 27, 16),
992 if (cpu_is_omap24xx())
993 dispc_write_reg(ftrs_reg
[plane
],
994 FLD_VAL(high
, 24, 16) | FLD_VAL(low
, 8, 0));
996 dispc_write_reg(ftrs_reg
[plane
],
997 FLD_VAL(high
, 27, 16) | FLD_VAL(low
, 11, 0));
1002 void dispc_enable_fifomerge(bool enable
)
1006 DSSDBG("FIFO merge %s\n", enable
? "enabled" : "disabled");
1007 REG_FLD_MOD(DISPC_CONFIG
, enable
? 1 : 0, 14, 14);
1012 static void _dispc_set_fir(enum omap_plane plane
, int hinc
, int vinc
)
1015 const struct dispc_reg fir_reg
[] = { DISPC_VID_FIR(0),
1018 BUG_ON(plane
== OMAP_DSS_GFX
);
1020 if (cpu_is_omap24xx())
1021 val
= FLD_VAL(vinc
, 27, 16) | FLD_VAL(hinc
, 11, 0);
1023 val
= FLD_VAL(vinc
, 28, 16) | FLD_VAL(hinc
, 12, 0);
1024 dispc_write_reg(fir_reg
[plane
-1], val
);
1027 static void _dispc_set_vid_accu0(enum omap_plane plane
, int haccu
, int vaccu
)
1030 const struct dispc_reg ac0_reg
[] = { DISPC_VID_ACCU0(0),
1031 DISPC_VID_ACCU0(1) };
1033 BUG_ON(plane
== OMAP_DSS_GFX
);
1035 val
= FLD_VAL(vaccu
, 25, 16) | FLD_VAL(haccu
, 9, 0);
1036 dispc_write_reg(ac0_reg
[plane
-1], val
);
1039 static void _dispc_set_vid_accu1(enum omap_plane plane
, int haccu
, int vaccu
)
1042 const struct dispc_reg ac1_reg
[] = { DISPC_VID_ACCU1(0),
1043 DISPC_VID_ACCU1(1) };
1045 BUG_ON(plane
== OMAP_DSS_GFX
);
1047 val
= FLD_VAL(vaccu
, 25, 16) | FLD_VAL(haccu
, 9, 0);
1048 dispc_write_reg(ac1_reg
[plane
-1], val
);
1052 static void _dispc_set_scaling(enum omap_plane plane
,
1053 u16 orig_width
, u16 orig_height
,
1054 u16 out_width
, u16 out_height
,
1055 bool ilace
, bool five_taps
,
1060 int hscaleup
, vscaleup
;
1065 BUG_ON(plane
== OMAP_DSS_GFX
);
1067 hscaleup
= orig_width
<= out_width
;
1068 vscaleup
= orig_height
<= out_height
;
1070 _dispc_set_scale_coef(plane
, hscaleup
, vscaleup
, five_taps
);
1072 if (!orig_width
|| orig_width
== out_width
)
1075 fir_hinc
= 1024 * orig_width
/ out_width
;
1077 if (!orig_height
|| orig_height
== out_height
)
1080 fir_vinc
= 1024 * orig_height
/ out_height
;
1082 _dispc_set_fir(plane
, fir_hinc
, fir_vinc
);
1084 l
= dispc_read_reg(dispc_reg_att
[plane
]);
1085 l
&= ~((0x0f << 5) | (0x3 << 21));
1087 l
|= fir_hinc
? (1 << 5) : 0;
1088 l
|= fir_vinc
? (1 << 6) : 0;
1090 l
|= hscaleup
? 0 : (1 << 7);
1091 l
|= vscaleup
? 0 : (1 << 8);
1093 l
|= five_taps
? (1 << 21) : 0;
1094 l
|= five_taps
? (1 << 22) : 0;
1096 dispc_write_reg(dispc_reg_att
[plane
], l
);
1099 * field 0 = even field = bottom field
1100 * field 1 = odd field = top field
1102 if (ilace
&& !fieldmode
) {
1104 accu0
= (fir_vinc
/ 2) & 0x3ff;
1105 if (accu0
>= 1024/2) {
1111 _dispc_set_vid_accu0(plane
, 0, accu0
);
1112 _dispc_set_vid_accu1(plane
, 0, accu1
);
1115 static void _dispc_set_rotation_attrs(enum omap_plane plane
, u8 rotation
,
1116 bool mirroring
, enum omap_color_mode color_mode
)
1118 if (color_mode
== OMAP_DSS_COLOR_YUV2
||
1119 color_mode
== OMAP_DSS_COLOR_UYVY
) {
1124 case OMAP_DSS_ROT_0
:
1127 case OMAP_DSS_ROT_90
:
1130 case OMAP_DSS_ROT_180
:
1133 case OMAP_DSS_ROT_270
:
1139 case OMAP_DSS_ROT_0
:
1142 case OMAP_DSS_ROT_90
:
1145 case OMAP_DSS_ROT_180
:
1148 case OMAP_DSS_ROT_270
:
1154 REG_FLD_MOD(dispc_reg_att
[plane
], vidrot
, 13, 12);
1156 if (rotation
== OMAP_DSS_ROT_90
|| rotation
== OMAP_DSS_ROT_270
)
1157 REG_FLD_MOD(dispc_reg_att
[plane
], 0x1, 18, 18);
1159 REG_FLD_MOD(dispc_reg_att
[plane
], 0x0, 18, 18);
1161 REG_FLD_MOD(dispc_reg_att
[plane
], 0, 13, 12);
1162 REG_FLD_MOD(dispc_reg_att
[plane
], 0, 18, 18);
1166 static int color_mode_to_bpp(enum omap_color_mode color_mode
)
1168 switch (color_mode
) {
1169 case OMAP_DSS_COLOR_CLUT1
:
1171 case OMAP_DSS_COLOR_CLUT2
:
1173 case OMAP_DSS_COLOR_CLUT4
:
1175 case OMAP_DSS_COLOR_CLUT8
:
1177 case OMAP_DSS_COLOR_RGB12U
:
1178 case OMAP_DSS_COLOR_RGB16
:
1179 case OMAP_DSS_COLOR_ARGB16
:
1180 case OMAP_DSS_COLOR_YUV2
:
1181 case OMAP_DSS_COLOR_UYVY
:
1183 case OMAP_DSS_COLOR_RGB24P
:
1185 case OMAP_DSS_COLOR_RGB24U
:
1186 case OMAP_DSS_COLOR_ARGB32
:
1187 case OMAP_DSS_COLOR_RGBA32
:
1188 case OMAP_DSS_COLOR_RGBX32
:
1195 static s32
pixinc(int pixels
, u8 ps
)
1199 else if (pixels
> 1)
1200 return 1 + (pixels
- 1) * ps
;
1201 else if (pixels
< 0)
1202 return 1 - (-pixels
+ 1) * ps
;
1207 static void calc_vrfb_rotation_offset(u8 rotation
, bool mirror
,
1209 u16 width
, u16 height
,
1210 enum omap_color_mode color_mode
, bool fieldmode
,
1211 unsigned int field_offset
,
1212 unsigned *offset0
, unsigned *offset1
,
1213 s32
*row_inc
, s32
*pix_inc
)
1217 /* FIXME CLUT formats */
1218 switch (color_mode
) {
1219 case OMAP_DSS_COLOR_CLUT1
:
1220 case OMAP_DSS_COLOR_CLUT2
:
1221 case OMAP_DSS_COLOR_CLUT4
:
1222 case OMAP_DSS_COLOR_CLUT8
:
1225 case OMAP_DSS_COLOR_YUV2
:
1226 case OMAP_DSS_COLOR_UYVY
:
1230 ps
= color_mode_to_bpp(color_mode
) / 8;
1234 DSSDBG("calc_rot(%d): scrw %d, %dx%d\n", rotation
, screen_width
,
1238 * field 0 = even field = bottom field
1239 * field 1 = odd field = top field
1241 switch (rotation
+ mirror
* 4) {
1242 case OMAP_DSS_ROT_0
:
1243 case OMAP_DSS_ROT_180
:
1245 * If the pixel format is YUV or UYVY divide the width
1246 * of the image by 2 for 0 and 180 degree rotation.
1248 if (color_mode
== OMAP_DSS_COLOR_YUV2
||
1249 color_mode
== OMAP_DSS_COLOR_UYVY
)
1251 case OMAP_DSS_ROT_90
:
1252 case OMAP_DSS_ROT_270
:
1255 *offset0
= field_offset
* screen_width
* ps
;
1259 *row_inc
= pixinc(1 + (screen_width
- width
) +
1260 (fieldmode
? screen_width
: 0),
1262 *pix_inc
= pixinc(1, ps
);
1265 case OMAP_DSS_ROT_0
+ 4:
1266 case OMAP_DSS_ROT_180
+ 4:
1267 /* If the pixel format is YUV or UYVY divide the width
1268 * of the image by 2 for 0 degree and 180 degree
1270 if (color_mode
== OMAP_DSS_COLOR_YUV2
||
1271 color_mode
== OMAP_DSS_COLOR_UYVY
)
1273 case OMAP_DSS_ROT_90
+ 4:
1274 case OMAP_DSS_ROT_270
+ 4:
1277 *offset0
= field_offset
* screen_width
* ps
;
1280 *row_inc
= pixinc(1 - (screen_width
+ width
) -
1281 (fieldmode
? screen_width
: 0),
1283 *pix_inc
= pixinc(1, ps
);
1291 static void calc_dma_rotation_offset(u8 rotation
, bool mirror
,
1293 u16 width
, u16 height
,
1294 enum omap_color_mode color_mode
, bool fieldmode
,
1295 unsigned int field_offset
,
1296 unsigned *offset0
, unsigned *offset1
,
1297 s32
*row_inc
, s32
*pix_inc
)
1302 /* FIXME CLUT formats */
1303 switch (color_mode
) {
1304 case OMAP_DSS_COLOR_CLUT1
:
1305 case OMAP_DSS_COLOR_CLUT2
:
1306 case OMAP_DSS_COLOR_CLUT4
:
1307 case OMAP_DSS_COLOR_CLUT8
:
1311 ps
= color_mode_to_bpp(color_mode
) / 8;
1315 DSSDBG("calc_rot(%d): scrw %d, %dx%d\n", rotation
, screen_width
,
1318 /* width & height are overlay sizes, convert to fb sizes */
1320 if (rotation
== OMAP_DSS_ROT_0
|| rotation
== OMAP_DSS_ROT_180
) {
1329 * field 0 = even field = bottom field
1330 * field 1 = odd field = top field
1332 switch (rotation
+ mirror
* 4) {
1333 case OMAP_DSS_ROT_0
:
1336 *offset0
= *offset1
+ field_offset
* screen_width
* ps
;
1338 *offset0
= *offset1
;
1339 *row_inc
= pixinc(1 + (screen_width
- fbw
) +
1340 (fieldmode
? screen_width
: 0),
1342 *pix_inc
= pixinc(1, ps
);
1344 case OMAP_DSS_ROT_90
:
1345 *offset1
= screen_width
* (fbh
- 1) * ps
;
1347 *offset0
= *offset1
+ field_offset
* ps
;
1349 *offset0
= *offset1
;
1350 *row_inc
= pixinc(screen_width
* (fbh
- 1) + 1 +
1351 (fieldmode
? 1 : 0), ps
);
1352 *pix_inc
= pixinc(-screen_width
, ps
);
1354 case OMAP_DSS_ROT_180
:
1355 *offset1
= (screen_width
* (fbh
- 1) + fbw
- 1) * ps
;
1357 *offset0
= *offset1
- field_offset
* screen_width
* ps
;
1359 *offset0
= *offset1
;
1360 *row_inc
= pixinc(-1 -
1361 (screen_width
- fbw
) -
1362 (fieldmode
? screen_width
: 0),
1364 *pix_inc
= pixinc(-1, ps
);
1366 case OMAP_DSS_ROT_270
:
1367 *offset1
= (fbw
- 1) * ps
;
1369 *offset0
= *offset1
- field_offset
* ps
;
1371 *offset0
= *offset1
;
1372 *row_inc
= pixinc(-screen_width
* (fbh
- 1) - 1 -
1373 (fieldmode
? 1 : 0), ps
);
1374 *pix_inc
= pixinc(screen_width
, ps
);
1378 case OMAP_DSS_ROT_0
+ 4:
1379 *offset1
= (fbw
- 1) * ps
;
1381 *offset0
= *offset1
+ field_offset
* screen_width
* ps
;
1383 *offset0
= *offset1
;
1384 *row_inc
= pixinc(screen_width
* 2 - 1 +
1385 (fieldmode
? screen_width
: 0),
1387 *pix_inc
= pixinc(-1, ps
);
1390 case OMAP_DSS_ROT_90
+ 4:
1393 *offset0
= *offset1
+ field_offset
* ps
;
1395 *offset0
= *offset1
;
1396 *row_inc
= pixinc(-screen_width
* (fbh
- 1) + 1 +
1397 (fieldmode
? 1 : 0),
1399 *pix_inc
= pixinc(screen_width
, ps
);
1402 case OMAP_DSS_ROT_180
+ 4:
1403 *offset1
= screen_width
* (fbh
- 1) * ps
;
1405 *offset0
= *offset1
- field_offset
* screen_width
* ps
;
1407 *offset0
= *offset1
;
1408 *row_inc
= pixinc(1 - screen_width
* 2 -
1409 (fieldmode
? screen_width
: 0),
1411 *pix_inc
= pixinc(1, ps
);
1414 case OMAP_DSS_ROT_270
+ 4:
1415 *offset1
= (screen_width
* (fbh
- 1) + fbw
- 1) * ps
;
1417 *offset0
= *offset1
- field_offset
* ps
;
1419 *offset0
= *offset1
;
1420 *row_inc
= pixinc(screen_width
* (fbh
- 1) - 1 -
1421 (fieldmode
? 1 : 0),
1423 *pix_inc
= pixinc(-screen_width
, ps
);
1431 static unsigned long calc_fclk_five_taps(u16 width
, u16 height
,
1432 u16 out_width
, u16 out_height
, enum omap_color_mode color_mode
)
1435 /* FIXME venc pclk? */
1436 u64 tmp
, pclk
= dispc_pclk_rate();
1438 if (height
> out_height
) {
1439 /* FIXME get real display PPL */
1440 unsigned int ppl
= 800;
1442 tmp
= pclk
* height
* out_width
;
1443 do_div(tmp
, 2 * out_height
* ppl
);
1446 if (height
> 2 * out_height
&& ppl
!= out_width
) {
1447 tmp
= pclk
* (height
- 2 * out_height
) * out_width
;
1448 do_div(tmp
, 2 * out_height
* (ppl
- out_width
));
1449 fclk
= max(fclk
, (u32
) tmp
);
1453 if (width
> out_width
) {
1455 do_div(tmp
, out_width
);
1456 fclk
= max(fclk
, (u32
) tmp
);
1458 if (color_mode
== OMAP_DSS_COLOR_RGB24U
)
1465 static unsigned long calc_fclk(u16 width
, u16 height
,
1466 u16 out_width
, u16 out_height
)
1468 unsigned int hf
, vf
;
1471 * FIXME how to determine the 'A' factor
1472 * for the no downscaling case ?
1475 if (width
> 3 * out_width
)
1477 else if (width
> 2 * out_width
)
1479 else if (width
> out_width
)
1484 if (height
> out_height
)
1489 /* FIXME venc pclk? */
1490 return dispc_pclk_rate() * vf
* hf
;
1493 void dispc_set_channel_out(enum omap_plane plane
, enum omap_channel channel_out
)
1496 _dispc_set_channel_out(plane
, channel_out
);
1500 static int _dispc_setup_plane(enum omap_plane plane
,
1501 u32 paddr
, u16 screen_width
,
1502 u16 pos_x
, u16 pos_y
,
1503 u16 width
, u16 height
,
1504 u16 out_width
, u16 out_height
,
1505 enum omap_color_mode color_mode
,
1507 enum omap_dss_rotation_type rotation_type
,
1508 u8 rotation
, int mirror
,
1511 const int maxdownscale
= cpu_is_omap34xx() ? 4 : 2;
1515 unsigned offset0
, offset1
;
1518 u16 frame_height
= height
;
1519 unsigned int field_offset
= 0;
1524 if (ilace
&& height
== out_height
)
1533 DSSDBG("adjusting for ilace: height %d, pos_y %d, "
1535 height
, pos_y
, out_height
);
1538 if (plane
== OMAP_DSS_GFX
) {
1539 if (width
!= out_width
|| height
!= out_height
)
1542 switch (color_mode
) {
1543 case OMAP_DSS_COLOR_ARGB16
:
1544 case OMAP_DSS_COLOR_ARGB32
:
1545 case OMAP_DSS_COLOR_RGBA32
:
1546 case OMAP_DSS_COLOR_RGBX32
:
1547 if (cpu_is_omap24xx())
1550 case OMAP_DSS_COLOR_RGB12U
:
1551 case OMAP_DSS_COLOR_RGB16
:
1552 case OMAP_DSS_COLOR_RGB24P
:
1553 case OMAP_DSS_COLOR_RGB24U
:
1562 unsigned long fclk
= 0;
1564 if (out_width
< width
/ maxdownscale
||
1565 out_width
> width
* 8)
1568 if (out_height
< height
/ maxdownscale
||
1569 out_height
> height
* 8)
1572 switch (color_mode
) {
1573 case OMAP_DSS_COLOR_RGBX32
:
1574 case OMAP_DSS_COLOR_RGB12U
:
1575 if (cpu_is_omap24xx())
1578 case OMAP_DSS_COLOR_RGB16
:
1579 case OMAP_DSS_COLOR_RGB24P
:
1580 case OMAP_DSS_COLOR_RGB24U
:
1583 case OMAP_DSS_COLOR_ARGB16
:
1584 case OMAP_DSS_COLOR_ARGB32
:
1585 case OMAP_DSS_COLOR_RGBA32
:
1586 if (cpu_is_omap24xx())
1588 if (plane
== OMAP_DSS_VIDEO1
)
1592 case OMAP_DSS_COLOR_YUV2
:
1593 case OMAP_DSS_COLOR_UYVY
:
1601 /* Must use 5-tap filter? */
1602 five_taps
= height
> out_height
* 2;
1605 fclk
= calc_fclk(width
, height
,
1606 out_width
, out_height
);
1608 /* Try 5-tap filter if 3-tap fclk is too high */
1609 if (cpu_is_omap34xx() && height
> out_height
&&
1610 fclk
> dispc_fclk_rate())
1614 if (width
> (2048 >> five_taps
)) {
1615 DSSERR("failed to set up scaling, fclk too low\n");
1620 fclk
= calc_fclk_five_taps(width
, height
,
1621 out_width
, out_height
, color_mode
);
1623 DSSDBG("required fclk rate = %lu Hz\n", fclk
);
1624 DSSDBG("current fclk rate = %lu Hz\n", dispc_fclk_rate());
1626 if (fclk
> dispc_fclk_rate()) {
1627 DSSERR("failed to set up scaling, "
1628 "required fclk rate = %lu Hz, "
1629 "current fclk rate = %lu Hz\n",
1630 fclk
, dispc_fclk_rate());
1635 if (ilace
&& !fieldmode
) {
1637 * when downscaling the bottom field may have to start several
1638 * source lines below the top field. Unfortunately ACCUI
1639 * registers will only hold the fractional part of the offset
1640 * so the integer part must be added to the base address of the
1643 if (!height
|| height
== out_height
)
1646 field_offset
= height
/ out_height
/ 2;
1649 /* Fields are independent but interleaved in memory. */
1653 if (rotation_type
== OMAP_DSS_ROT_DMA
)
1654 calc_dma_rotation_offset(rotation
, mirror
,
1655 screen_width
, width
, frame_height
, color_mode
,
1656 fieldmode
, field_offset
,
1657 &offset0
, &offset1
, &row_inc
, &pix_inc
);
1659 calc_vrfb_rotation_offset(rotation
, mirror
,
1660 screen_width
, width
, frame_height
, color_mode
,
1661 fieldmode
, field_offset
,
1662 &offset0
, &offset1
, &row_inc
, &pix_inc
);
1664 DSSDBG("offset0 %u, offset1 %u, row_inc %d, pix_inc %d\n",
1665 offset0
, offset1
, row_inc
, pix_inc
);
1667 _dispc_set_color_mode(plane
, color_mode
);
1669 _dispc_set_plane_ba0(plane
, paddr
+ offset0
);
1670 _dispc_set_plane_ba1(plane
, paddr
+ offset1
);
1672 _dispc_set_row_inc(plane
, row_inc
);
1673 _dispc_set_pix_inc(plane
, pix_inc
);
1675 DSSDBG("%d,%d %dx%d -> %dx%d\n", pos_x
, pos_y
, width
, height
,
1676 out_width
, out_height
);
1678 _dispc_set_plane_pos(plane
, pos_x
, pos_y
);
1680 _dispc_set_pic_size(plane
, width
, height
);
1682 if (plane
!= OMAP_DSS_GFX
) {
1683 _dispc_set_scaling(plane
, width
, height
,
1684 out_width
, out_height
,
1685 ilace
, five_taps
, fieldmode
);
1686 _dispc_set_vid_size(plane
, out_width
, out_height
);
1687 _dispc_set_vid_color_conv(plane
, cconv
);
1690 _dispc_set_rotation_attrs(plane
, rotation
, mirror
, color_mode
);
1692 if (plane
!= OMAP_DSS_VIDEO1
)
1693 _dispc_setup_global_alpha(plane
, global_alpha
);
1698 static void _dispc_enable_plane(enum omap_plane plane
, bool enable
)
1700 REG_FLD_MOD(dispc_reg_att
[plane
], enable
? 1 : 0, 0, 0);
1703 static void dispc_disable_isr(void *data
, u32 mask
)
1705 struct completion
*compl = data
;
1709 static void _enable_lcd_out(bool enable
)
1711 REG_FLD_MOD(DISPC_CONTROL
, enable
? 1 : 0, 0, 0);
1714 void dispc_enable_lcd_out(bool enable
)
1716 struct completion frame_done_completion
;
1722 /* When we disable LCD output, we need to wait until frame is done.
1723 * Otherwise the DSS is still working, and turning off the clocks
1724 * prevents DSS from going to OFF mode */
1725 is_on
= REG_GET(DISPC_CONTROL
, 0, 0);
1727 if (!enable
&& is_on
) {
1728 init_completion(&frame_done_completion
);
1730 r
= omap_dispc_register_isr(dispc_disable_isr
,
1731 &frame_done_completion
,
1732 DISPC_IRQ_FRAMEDONE
);
1735 DSSERR("failed to register FRAMEDONE isr\n");
1738 _enable_lcd_out(enable
);
1740 if (!enable
&& is_on
) {
1741 if (!wait_for_completion_timeout(&frame_done_completion
,
1742 msecs_to_jiffies(100)))
1743 DSSERR("timeout waiting for FRAME DONE\n");
1745 r
= omap_dispc_unregister_isr(dispc_disable_isr
,
1746 &frame_done_completion
,
1747 DISPC_IRQ_FRAMEDONE
);
1750 DSSERR("failed to unregister FRAMEDONE isr\n");
1756 static void _enable_digit_out(bool enable
)
1758 REG_FLD_MOD(DISPC_CONTROL
, enable
? 1 : 0, 1, 1);
1761 void dispc_enable_digit_out(bool enable
)
1763 struct completion frame_done_completion
;
1768 if (REG_GET(DISPC_CONTROL
, 1, 1) == enable
) {
1774 unsigned long flags
;
1775 /* When we enable digit output, we'll get an extra digit
1776 * sync lost interrupt, that we need to ignore */
1777 spin_lock_irqsave(&dispc
.irq_lock
, flags
);
1778 dispc
.irq_error_mask
&= ~DISPC_IRQ_SYNC_LOST_DIGIT
;
1779 _omap_dispc_set_irqs();
1780 spin_unlock_irqrestore(&dispc
.irq_lock
, flags
);
1783 /* When we disable digit output, we need to wait until fields are done.
1784 * Otherwise the DSS is still working, and turning off the clocks
1785 * prevents DSS from going to OFF mode. And when enabling, we need to
1786 * wait for the extra sync losts */
1787 init_completion(&frame_done_completion
);
1789 r
= omap_dispc_register_isr(dispc_disable_isr
, &frame_done_completion
,
1790 DISPC_IRQ_EVSYNC_EVEN
| DISPC_IRQ_EVSYNC_ODD
);
1792 DSSERR("failed to register EVSYNC isr\n");
1794 _enable_digit_out(enable
);
1796 /* XXX I understand from TRM that we should only wait for the
1797 * current field to complete. But it seems we have to wait
1798 * for both fields */
1799 if (!wait_for_completion_timeout(&frame_done_completion
,
1800 msecs_to_jiffies(100)))
1801 DSSERR("timeout waiting for EVSYNC\n");
1803 if (!wait_for_completion_timeout(&frame_done_completion
,
1804 msecs_to_jiffies(100)))
1805 DSSERR("timeout waiting for EVSYNC\n");
1807 r
= omap_dispc_unregister_isr(dispc_disable_isr
,
1808 &frame_done_completion
,
1809 DISPC_IRQ_EVSYNC_EVEN
| DISPC_IRQ_EVSYNC_ODD
);
1811 DSSERR("failed to unregister EVSYNC isr\n");
1814 unsigned long flags
;
1815 spin_lock_irqsave(&dispc
.irq_lock
, flags
);
1816 dispc
.irq_error_mask
= DISPC_IRQ_MASK_ERROR
;
1817 dispc_write_reg(DISPC_IRQSTATUS
, DISPC_IRQ_SYNC_LOST_DIGIT
);
1818 _omap_dispc_set_irqs();
1819 spin_unlock_irqrestore(&dispc
.irq_lock
, flags
);
1825 void dispc_lcd_enable_signal_polarity(bool act_high
)
1828 REG_FLD_MOD(DISPC_CONTROL
, act_high
? 1 : 0, 29, 29);
1832 void dispc_lcd_enable_signal(bool enable
)
1835 REG_FLD_MOD(DISPC_CONTROL
, enable
? 1 : 0, 28, 28);
1839 void dispc_pck_free_enable(bool enable
)
1842 REG_FLD_MOD(DISPC_CONTROL
, enable
? 1 : 0, 27, 27);
1846 void dispc_enable_fifohandcheck(bool enable
)
1849 REG_FLD_MOD(DISPC_CONFIG
, enable
? 1 : 0, 16, 16);
1854 void dispc_set_lcd_display_type(enum omap_lcd_display_type type
)
1859 case OMAP_DSS_LCD_DISPLAY_STN
:
1863 case OMAP_DSS_LCD_DISPLAY_TFT
:
1873 REG_FLD_MOD(DISPC_CONTROL
, mode
, 3, 3);
1877 void dispc_set_loadmode(enum omap_dss_load_mode mode
)
1880 REG_FLD_MOD(DISPC_CONFIG
, mode
, 2, 1);
1885 void dispc_set_default_color(enum omap_channel channel
, u32 color
)
1887 const struct dispc_reg def_reg
[] = { DISPC_DEFAULT_COLOR0
,
1888 DISPC_DEFAULT_COLOR1
};
1891 dispc_write_reg(def_reg
[channel
], color
);
1895 u32
dispc_get_default_color(enum omap_channel channel
)
1897 const struct dispc_reg def_reg
[] = { DISPC_DEFAULT_COLOR0
,
1898 DISPC_DEFAULT_COLOR1
};
1901 BUG_ON(channel
!= OMAP_DSS_CHANNEL_DIGIT
&&
1902 channel
!= OMAP_DSS_CHANNEL_LCD
);
1905 l
= dispc_read_reg(def_reg
[channel
]);
1911 void dispc_set_trans_key(enum omap_channel ch
,
1912 enum omap_dss_trans_key_type type
,
1915 const struct dispc_reg tr_reg
[] = {
1916 DISPC_TRANS_COLOR0
, DISPC_TRANS_COLOR1
};
1919 if (ch
== OMAP_DSS_CHANNEL_LCD
)
1920 REG_FLD_MOD(DISPC_CONFIG
, type
, 11, 11);
1921 else /* OMAP_DSS_CHANNEL_DIGIT */
1922 REG_FLD_MOD(DISPC_CONFIG
, type
, 13, 13);
1924 dispc_write_reg(tr_reg
[ch
], trans_key
);
1928 void dispc_get_trans_key(enum omap_channel ch
,
1929 enum omap_dss_trans_key_type
*type
,
1932 const struct dispc_reg tr_reg
[] = {
1933 DISPC_TRANS_COLOR0
, DISPC_TRANS_COLOR1
};
1937 if (ch
== OMAP_DSS_CHANNEL_LCD
)
1938 *type
= REG_GET(DISPC_CONFIG
, 11, 11);
1939 else if (ch
== OMAP_DSS_CHANNEL_DIGIT
)
1940 *type
= REG_GET(DISPC_CONFIG
, 13, 13);
1946 *trans_key
= dispc_read_reg(tr_reg
[ch
]);
1950 void dispc_enable_trans_key(enum omap_channel ch
, bool enable
)
1953 if (ch
== OMAP_DSS_CHANNEL_LCD
)
1954 REG_FLD_MOD(DISPC_CONFIG
, enable
, 10, 10);
1955 else /* OMAP_DSS_CHANNEL_DIGIT */
1956 REG_FLD_MOD(DISPC_CONFIG
, enable
, 12, 12);
1959 void dispc_enable_alpha_blending(enum omap_channel ch
, bool enable
)
1961 if (cpu_is_omap24xx())
1965 if (ch
== OMAP_DSS_CHANNEL_LCD
)
1966 REG_FLD_MOD(DISPC_CONFIG
, enable
, 18, 18);
1967 else /* OMAP_DSS_CHANNEL_DIGIT */
1968 REG_FLD_MOD(DISPC_CONFIG
, enable
, 19, 19);
1971 bool dispc_alpha_blending_enabled(enum omap_channel ch
)
1975 if (cpu_is_omap24xx())
1979 if (ch
== OMAP_DSS_CHANNEL_LCD
)
1980 enabled
= REG_GET(DISPC_CONFIG
, 18, 18);
1981 else if (ch
== OMAP_DSS_CHANNEL_DIGIT
)
1982 enabled
= REG_GET(DISPC_CONFIG
, 18, 18);
1992 bool dispc_trans_key_enabled(enum omap_channel ch
)
1997 if (ch
== OMAP_DSS_CHANNEL_LCD
)
1998 enabled
= REG_GET(DISPC_CONFIG
, 10, 10);
1999 else if (ch
== OMAP_DSS_CHANNEL_DIGIT
)
2000 enabled
= REG_GET(DISPC_CONFIG
, 12, 12);
2009 void dispc_set_tft_data_lines(u8 data_lines
)
2013 switch (data_lines
) {
2032 REG_FLD_MOD(DISPC_CONTROL
, code
, 9, 8);
2036 void dispc_set_parallel_interface_mode(enum omap_parallel_interface_mode mode
)
2044 case OMAP_DSS_PARALLELMODE_BYPASS
:
2049 case OMAP_DSS_PARALLELMODE_RFBI
:
2054 case OMAP_DSS_PARALLELMODE_DSI
:
2066 l
= dispc_read_reg(DISPC_CONTROL
);
2068 l
= FLD_MOD(l
, stallmode
, 11, 11);
2069 l
= FLD_MOD(l
, gpout0
, 15, 15);
2070 l
= FLD_MOD(l
, gpout1
, 16, 16);
2072 dispc_write_reg(DISPC_CONTROL
, l
);
2077 static bool _dispc_lcd_timings_ok(int hsw
, int hfp
, int hbp
,
2078 int vsw
, int vfp
, int vbp
)
2080 if (cpu_is_omap24xx() || omap_rev() < OMAP3430_REV_ES3_0
) {
2081 if (hsw
< 1 || hsw
> 64 ||
2082 hfp
< 1 || hfp
> 256 ||
2083 hbp
< 1 || hbp
> 256 ||
2084 vsw
< 1 || vsw
> 64 ||
2085 vfp
< 0 || vfp
> 255 ||
2086 vbp
< 0 || vbp
> 255)
2089 if (hsw
< 1 || hsw
> 256 ||
2090 hfp
< 1 || hfp
> 4096 ||
2091 hbp
< 1 || hbp
> 4096 ||
2092 vsw
< 1 || vsw
> 256 ||
2093 vfp
< 0 || vfp
> 4095 ||
2094 vbp
< 0 || vbp
> 4095)
2101 bool dispc_lcd_timings_ok(struct omap_video_timings
*timings
)
2103 return _dispc_lcd_timings_ok(timings
->hsw
, timings
->hfp
,
2104 timings
->hbp
, timings
->vsw
,
2105 timings
->vfp
, timings
->vbp
);
2108 static void _dispc_set_lcd_timings(int hsw
, int hfp
, int hbp
,
2109 int vsw
, int vfp
, int vbp
)
2111 u32 timing_h
, timing_v
;
2113 if (cpu_is_omap24xx() || omap_rev() < OMAP3430_REV_ES3_0
) {
2114 timing_h
= FLD_VAL(hsw
-1, 5, 0) | FLD_VAL(hfp
-1, 15, 8) |
2115 FLD_VAL(hbp
-1, 27, 20);
2117 timing_v
= FLD_VAL(vsw
-1, 5, 0) | FLD_VAL(vfp
, 15, 8) |
2118 FLD_VAL(vbp
, 27, 20);
2120 timing_h
= FLD_VAL(hsw
-1, 7, 0) | FLD_VAL(hfp
-1, 19, 8) |
2121 FLD_VAL(hbp
-1, 31, 20);
2123 timing_v
= FLD_VAL(vsw
-1, 7, 0) | FLD_VAL(vfp
, 19, 8) |
2124 FLD_VAL(vbp
, 31, 20);
2128 dispc_write_reg(DISPC_TIMING_H
, timing_h
);
2129 dispc_write_reg(DISPC_TIMING_V
, timing_v
);
2133 /* change name to mode? */
2134 void dispc_set_lcd_timings(struct omap_video_timings
*timings
)
2136 unsigned xtot
, ytot
;
2137 unsigned long ht
, vt
;
2139 if (!_dispc_lcd_timings_ok(timings
->hsw
, timings
->hfp
,
2140 timings
->hbp
, timings
->vsw
,
2141 timings
->vfp
, timings
->vbp
))
2144 _dispc_set_lcd_timings(timings
->hsw
, timings
->hfp
, timings
->hbp
,
2145 timings
->vsw
, timings
->vfp
, timings
->vbp
);
2147 dispc_set_lcd_size(timings
->x_res
, timings
->y_res
);
2149 xtot
= timings
->x_res
+ timings
->hfp
+ timings
->hsw
+ timings
->hbp
;
2150 ytot
= timings
->y_res
+ timings
->vfp
+ timings
->vsw
+ timings
->vbp
;
2152 ht
= (timings
->pixel_clock
* 1000) / xtot
;
2153 vt
= (timings
->pixel_clock
* 1000) / xtot
/ ytot
;
2155 DSSDBG("xres %u yres %u\n", timings
->x_res
, timings
->y_res
);
2156 DSSDBG("pck %u\n", timings
->pixel_clock
);
2157 DSSDBG("hsw %d hfp %d hbp %d vsw %d vfp %d vbp %d\n",
2158 timings
->hsw
, timings
->hfp
, timings
->hbp
,
2159 timings
->vsw
, timings
->vfp
, timings
->vbp
);
2161 DSSDBG("hsync %luHz, vsync %luHz\n", ht
, vt
);
2164 static void dispc_set_lcd_divisor(u16 lck_div
, u16 pck_div
)
2166 BUG_ON(lck_div
< 1);
2167 BUG_ON(pck_div
< 2);
2170 dispc_write_reg(DISPC_DIVISOR
,
2171 FLD_VAL(lck_div
, 23, 16) | FLD_VAL(pck_div
, 7, 0));
2175 static void dispc_get_lcd_divisor(int *lck_div
, int *pck_div
)
2178 l
= dispc_read_reg(DISPC_DIVISOR
);
2179 *lck_div
= FLD_GET(l
, 23, 16);
2180 *pck_div
= FLD_GET(l
, 7, 0);
2183 unsigned long dispc_fclk_rate(void)
2185 unsigned long r
= 0;
2187 if (dss_get_dispc_clk_source() == 0)
2188 r
= dss_clk_get_rate(DSS_CLK_FCK1
);
2190 #ifdef CONFIG_OMAP2_DSS_DSI
2191 r
= dsi_get_dsi1_pll_rate();
2198 unsigned long dispc_lclk_rate(void)
2204 l
= dispc_read_reg(DISPC_DIVISOR
);
2206 lcd
= FLD_GET(l
, 23, 16);
2208 r
= dispc_fclk_rate();
2213 unsigned long dispc_pclk_rate(void)
2219 l
= dispc_read_reg(DISPC_DIVISOR
);
2221 lcd
= FLD_GET(l
, 23, 16);
2222 pcd
= FLD_GET(l
, 7, 0);
2224 r
= dispc_fclk_rate();
2226 return r
/ lcd
/ pcd
;
2229 void dispc_dump_clocks(struct seq_file
*s
)
2235 dispc_get_lcd_divisor(&lcd
, &pcd
);
2237 seq_printf(s
, "- DISPC -\n");
2239 seq_printf(s
, "dispc fclk source = %s\n",
2240 dss_get_dispc_clk_source() == 0 ?
2241 "dss1_alwon_fclk" : "dsi1_pll_fclk");
2243 seq_printf(s
, "fck\t\t%-16lu\n", dispc_fclk_rate());
2244 seq_printf(s
, "lck\t\t%-16lulck div\t%u\n", dispc_lclk_rate(), lcd
);
2245 seq_printf(s
, "pck\t\t%-16lupck div\t%u\n", dispc_pclk_rate(), pcd
);
2250 void dispc_dump_regs(struct seq_file
*s
)
2252 #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dispc_read_reg(r))
2254 dss_clk_enable(DSS_CLK_ICK
| DSS_CLK_FCK1
);
2256 DUMPREG(DISPC_REVISION
);
2257 DUMPREG(DISPC_SYSCONFIG
);
2258 DUMPREG(DISPC_SYSSTATUS
);
2259 DUMPREG(DISPC_IRQSTATUS
);
2260 DUMPREG(DISPC_IRQENABLE
);
2261 DUMPREG(DISPC_CONTROL
);
2262 DUMPREG(DISPC_CONFIG
);
2263 DUMPREG(DISPC_CAPABLE
);
2264 DUMPREG(DISPC_DEFAULT_COLOR0
);
2265 DUMPREG(DISPC_DEFAULT_COLOR1
);
2266 DUMPREG(DISPC_TRANS_COLOR0
);
2267 DUMPREG(DISPC_TRANS_COLOR1
);
2268 DUMPREG(DISPC_LINE_STATUS
);
2269 DUMPREG(DISPC_LINE_NUMBER
);
2270 DUMPREG(DISPC_TIMING_H
);
2271 DUMPREG(DISPC_TIMING_V
);
2272 DUMPREG(DISPC_POL_FREQ
);
2273 DUMPREG(DISPC_DIVISOR
);
2274 DUMPREG(DISPC_GLOBAL_ALPHA
);
2275 DUMPREG(DISPC_SIZE_DIG
);
2276 DUMPREG(DISPC_SIZE_LCD
);
2278 DUMPREG(DISPC_GFX_BA0
);
2279 DUMPREG(DISPC_GFX_BA1
);
2280 DUMPREG(DISPC_GFX_POSITION
);
2281 DUMPREG(DISPC_GFX_SIZE
);
2282 DUMPREG(DISPC_GFX_ATTRIBUTES
);
2283 DUMPREG(DISPC_GFX_FIFO_THRESHOLD
);
2284 DUMPREG(DISPC_GFX_FIFO_SIZE_STATUS
);
2285 DUMPREG(DISPC_GFX_ROW_INC
);
2286 DUMPREG(DISPC_GFX_PIXEL_INC
);
2287 DUMPREG(DISPC_GFX_WINDOW_SKIP
);
2288 DUMPREG(DISPC_GFX_TABLE_BA
);
2290 DUMPREG(DISPC_DATA_CYCLE1
);
2291 DUMPREG(DISPC_DATA_CYCLE2
);
2292 DUMPREG(DISPC_DATA_CYCLE3
);
2294 DUMPREG(DISPC_CPR_COEF_R
);
2295 DUMPREG(DISPC_CPR_COEF_G
);
2296 DUMPREG(DISPC_CPR_COEF_B
);
2298 DUMPREG(DISPC_GFX_PRELOAD
);
2300 DUMPREG(DISPC_VID_BA0(0));
2301 DUMPREG(DISPC_VID_BA1(0));
2302 DUMPREG(DISPC_VID_POSITION(0));
2303 DUMPREG(DISPC_VID_SIZE(0));
2304 DUMPREG(DISPC_VID_ATTRIBUTES(0));
2305 DUMPREG(DISPC_VID_FIFO_THRESHOLD(0));
2306 DUMPREG(DISPC_VID_FIFO_SIZE_STATUS(0));
2307 DUMPREG(DISPC_VID_ROW_INC(0));
2308 DUMPREG(DISPC_VID_PIXEL_INC(0));
2309 DUMPREG(DISPC_VID_FIR(0));
2310 DUMPREG(DISPC_VID_PICTURE_SIZE(0));
2311 DUMPREG(DISPC_VID_ACCU0(0));
2312 DUMPREG(DISPC_VID_ACCU1(0));
2314 DUMPREG(DISPC_VID_BA0(1));
2315 DUMPREG(DISPC_VID_BA1(1));
2316 DUMPREG(DISPC_VID_POSITION(1));
2317 DUMPREG(DISPC_VID_SIZE(1));
2318 DUMPREG(DISPC_VID_ATTRIBUTES(1));
2319 DUMPREG(DISPC_VID_FIFO_THRESHOLD(1));
2320 DUMPREG(DISPC_VID_FIFO_SIZE_STATUS(1));
2321 DUMPREG(DISPC_VID_ROW_INC(1));
2322 DUMPREG(DISPC_VID_PIXEL_INC(1));
2323 DUMPREG(DISPC_VID_FIR(1));
2324 DUMPREG(DISPC_VID_PICTURE_SIZE(1));
2325 DUMPREG(DISPC_VID_ACCU0(1));
2326 DUMPREG(DISPC_VID_ACCU1(1));
2328 DUMPREG(DISPC_VID_FIR_COEF_H(0, 0));
2329 DUMPREG(DISPC_VID_FIR_COEF_H(0, 1));
2330 DUMPREG(DISPC_VID_FIR_COEF_H(0, 2));
2331 DUMPREG(DISPC_VID_FIR_COEF_H(0, 3));
2332 DUMPREG(DISPC_VID_FIR_COEF_H(0, 4));
2333 DUMPREG(DISPC_VID_FIR_COEF_H(0, 5));
2334 DUMPREG(DISPC_VID_FIR_COEF_H(0, 6));
2335 DUMPREG(DISPC_VID_FIR_COEF_H(0, 7));
2336 DUMPREG(DISPC_VID_FIR_COEF_HV(0, 0));
2337 DUMPREG(DISPC_VID_FIR_COEF_HV(0, 1));
2338 DUMPREG(DISPC_VID_FIR_COEF_HV(0, 2));
2339 DUMPREG(DISPC_VID_FIR_COEF_HV(0, 3));
2340 DUMPREG(DISPC_VID_FIR_COEF_HV(0, 4));
2341 DUMPREG(DISPC_VID_FIR_COEF_HV(0, 5));
2342 DUMPREG(DISPC_VID_FIR_COEF_HV(0, 6));
2343 DUMPREG(DISPC_VID_FIR_COEF_HV(0, 7));
2344 DUMPREG(DISPC_VID_CONV_COEF(0, 0));
2345 DUMPREG(DISPC_VID_CONV_COEF(0, 1));
2346 DUMPREG(DISPC_VID_CONV_COEF(0, 2));
2347 DUMPREG(DISPC_VID_CONV_COEF(0, 3));
2348 DUMPREG(DISPC_VID_CONV_COEF(0, 4));
2349 DUMPREG(DISPC_VID_FIR_COEF_V(0, 0));
2350 DUMPREG(DISPC_VID_FIR_COEF_V(0, 1));
2351 DUMPREG(DISPC_VID_FIR_COEF_V(0, 2));
2352 DUMPREG(DISPC_VID_FIR_COEF_V(0, 3));
2353 DUMPREG(DISPC_VID_FIR_COEF_V(0, 4));
2354 DUMPREG(DISPC_VID_FIR_COEF_V(0, 5));
2355 DUMPREG(DISPC_VID_FIR_COEF_V(0, 6));
2356 DUMPREG(DISPC_VID_FIR_COEF_V(0, 7));
2358 DUMPREG(DISPC_VID_FIR_COEF_H(1, 0));
2359 DUMPREG(DISPC_VID_FIR_COEF_H(1, 1));
2360 DUMPREG(DISPC_VID_FIR_COEF_H(1, 2));
2361 DUMPREG(DISPC_VID_FIR_COEF_H(1, 3));
2362 DUMPREG(DISPC_VID_FIR_COEF_H(1, 4));
2363 DUMPREG(DISPC_VID_FIR_COEF_H(1, 5));
2364 DUMPREG(DISPC_VID_FIR_COEF_H(1, 6));
2365 DUMPREG(DISPC_VID_FIR_COEF_H(1, 7));
2366 DUMPREG(DISPC_VID_FIR_COEF_HV(1, 0));
2367 DUMPREG(DISPC_VID_FIR_COEF_HV(1, 1));
2368 DUMPREG(DISPC_VID_FIR_COEF_HV(1, 2));
2369 DUMPREG(DISPC_VID_FIR_COEF_HV(1, 3));
2370 DUMPREG(DISPC_VID_FIR_COEF_HV(1, 4));
2371 DUMPREG(DISPC_VID_FIR_COEF_HV(1, 5));
2372 DUMPREG(DISPC_VID_FIR_COEF_HV(1, 6));
2373 DUMPREG(DISPC_VID_FIR_COEF_HV(1, 7));
2374 DUMPREG(DISPC_VID_CONV_COEF(1, 0));
2375 DUMPREG(DISPC_VID_CONV_COEF(1, 1));
2376 DUMPREG(DISPC_VID_CONV_COEF(1, 2));
2377 DUMPREG(DISPC_VID_CONV_COEF(1, 3));
2378 DUMPREG(DISPC_VID_CONV_COEF(1, 4));
2379 DUMPREG(DISPC_VID_FIR_COEF_V(1, 0));
2380 DUMPREG(DISPC_VID_FIR_COEF_V(1, 1));
2381 DUMPREG(DISPC_VID_FIR_COEF_V(1, 2));
2382 DUMPREG(DISPC_VID_FIR_COEF_V(1, 3));
2383 DUMPREG(DISPC_VID_FIR_COEF_V(1, 4));
2384 DUMPREG(DISPC_VID_FIR_COEF_V(1, 5));
2385 DUMPREG(DISPC_VID_FIR_COEF_V(1, 6));
2386 DUMPREG(DISPC_VID_FIR_COEF_V(1, 7));
2388 DUMPREG(DISPC_VID_PRELOAD(0));
2389 DUMPREG(DISPC_VID_PRELOAD(1));
2391 dss_clk_disable(DSS_CLK_ICK
| DSS_CLK_FCK1
);
2395 static void _dispc_set_pol_freq(bool onoff
, bool rf
, bool ieo
, bool ipc
,
2396 bool ihs
, bool ivs
, u8 acbi
, u8 acb
)
2400 DSSDBG("onoff %d rf %d ieo %d ipc %d ihs %d ivs %d acbi %d acb %d\n",
2401 onoff
, rf
, ieo
, ipc
, ihs
, ivs
, acbi
, acb
);
2403 l
|= FLD_VAL(onoff
, 17, 17);
2404 l
|= FLD_VAL(rf
, 16, 16);
2405 l
|= FLD_VAL(ieo
, 15, 15);
2406 l
|= FLD_VAL(ipc
, 14, 14);
2407 l
|= FLD_VAL(ihs
, 13, 13);
2408 l
|= FLD_VAL(ivs
, 12, 12);
2409 l
|= FLD_VAL(acbi
, 11, 8);
2410 l
|= FLD_VAL(acb
, 7, 0);
2413 dispc_write_reg(DISPC_POL_FREQ
, l
);
2417 void dispc_set_pol_freq(enum omap_panel_config config
, u8 acbi
, u8 acb
)
2419 _dispc_set_pol_freq((config
& OMAP_DSS_LCD_ONOFF
) != 0,
2420 (config
& OMAP_DSS_LCD_RF
) != 0,
2421 (config
& OMAP_DSS_LCD_IEO
) != 0,
2422 (config
& OMAP_DSS_LCD_IPC
) != 0,
2423 (config
& OMAP_DSS_LCD_IHS
) != 0,
2424 (config
& OMAP_DSS_LCD_IVS
) != 0,
2428 /* with fck as input clock rate, find dispc dividers that produce req_pck */
2429 void dispc_find_clk_divs(bool is_tft
, unsigned long req_pck
, unsigned long fck
,
2430 struct dispc_clock_info
*cinfo
)
2432 u16 pcd_min
= is_tft
? 2 : 3;
2433 unsigned long best_pck
;
2434 u16 best_ld
, cur_ld
;
2435 u16 best_pd
, cur_pd
;
2441 for (cur_ld
= 1; cur_ld
<= 255; ++cur_ld
) {
2442 unsigned long lck
= fck
/ cur_ld
;
2444 for (cur_pd
= pcd_min
; cur_pd
<= 255; ++cur_pd
) {
2445 unsigned long pck
= lck
/ cur_pd
;
2446 long old_delta
= abs(best_pck
- req_pck
);
2447 long new_delta
= abs(pck
- req_pck
);
2449 if (best_pck
== 0 || new_delta
< old_delta
) {
2462 if (lck
/ pcd_min
< req_pck
)
2467 cinfo
->lck_div
= best_ld
;
2468 cinfo
->pck_div
= best_pd
;
2469 cinfo
->lck
= fck
/ cinfo
->lck_div
;
2470 cinfo
->pck
= cinfo
->lck
/ cinfo
->pck_div
;
2473 /* calculate clock rates using dividers in cinfo */
2474 int dispc_calc_clock_rates(unsigned long dispc_fclk_rate
,
2475 struct dispc_clock_info
*cinfo
)
2477 if (cinfo
->lck_div
> 255 || cinfo
->lck_div
== 0)
2479 if (cinfo
->pck_div
< 2 || cinfo
->pck_div
> 255)
2482 cinfo
->lck
= dispc_fclk_rate
/ cinfo
->lck_div
;
2483 cinfo
->pck
= cinfo
->lck
/ cinfo
->pck_div
;
2488 int dispc_set_clock_div(struct dispc_clock_info
*cinfo
)
2490 DSSDBG("lck = %ld (%d)\n", cinfo
->lck
, cinfo
->lck_div
);
2491 DSSDBG("pck = %ld (%d)\n", cinfo
->pck
, cinfo
->pck_div
);
2493 dispc_set_lcd_divisor(cinfo
->lck_div
, cinfo
->pck_div
);
2498 int dispc_get_clock_div(struct dispc_clock_info
*cinfo
)
2502 fck
= dispc_fclk_rate();
2504 cinfo
->lck_div
= REG_GET(DISPC_DIVISOR
, 23, 16);
2505 cinfo
->pck_div
= REG_GET(DISPC_DIVISOR
, 7, 0);
2507 cinfo
->lck
= fck
/ cinfo
->lck_div
;
2508 cinfo
->pck
= cinfo
->lck
/ cinfo
->pck_div
;
2513 /* dispc.irq_lock has to be locked by the caller */
2514 static void _omap_dispc_set_irqs(void)
2519 struct omap_dispc_isr_data
*isr_data
;
2521 mask
= dispc
.irq_error_mask
;
2523 for (i
= 0; i
< DISPC_MAX_NR_ISRS
; i
++) {
2524 isr_data
= &dispc
.registered_isr
[i
];
2526 if (isr_data
->isr
== NULL
)
2529 mask
|= isr_data
->mask
;
2534 old_mask
= dispc_read_reg(DISPC_IRQENABLE
);
2535 /* clear the irqstatus for newly enabled irqs */
2536 dispc_write_reg(DISPC_IRQSTATUS
, (mask
^ old_mask
) & mask
);
2538 dispc_write_reg(DISPC_IRQENABLE
, mask
);
2543 int omap_dispc_register_isr(omap_dispc_isr_t isr
, void *arg
, u32 mask
)
2547 unsigned long flags
;
2548 struct omap_dispc_isr_data
*isr_data
;
2553 spin_lock_irqsave(&dispc
.irq_lock
, flags
);
2555 /* check for duplicate entry */
2556 for (i
= 0; i
< DISPC_MAX_NR_ISRS
; i
++) {
2557 isr_data
= &dispc
.registered_isr
[i
];
2558 if (isr_data
->isr
== isr
&& isr_data
->arg
== arg
&&
2559 isr_data
->mask
== mask
) {
2568 for (i
= 0; i
< DISPC_MAX_NR_ISRS
; i
++) {
2569 isr_data
= &dispc
.registered_isr
[i
];
2571 if (isr_data
->isr
!= NULL
)
2574 isr_data
->isr
= isr
;
2575 isr_data
->arg
= arg
;
2576 isr_data
->mask
= mask
;
2582 _omap_dispc_set_irqs();
2584 spin_unlock_irqrestore(&dispc
.irq_lock
, flags
);
2588 spin_unlock_irqrestore(&dispc
.irq_lock
, flags
);
2592 EXPORT_SYMBOL(omap_dispc_register_isr
);
2594 int omap_dispc_unregister_isr(omap_dispc_isr_t isr
, void *arg
, u32 mask
)
2597 unsigned long flags
;
2599 struct omap_dispc_isr_data
*isr_data
;
2601 spin_lock_irqsave(&dispc
.irq_lock
, flags
);
2603 for (i
= 0; i
< DISPC_MAX_NR_ISRS
; i
++) {
2604 isr_data
= &dispc
.registered_isr
[i
];
2605 if (isr_data
->isr
!= isr
|| isr_data
->arg
!= arg
||
2606 isr_data
->mask
!= mask
)
2609 /* found the correct isr */
2611 isr_data
->isr
= NULL
;
2612 isr_data
->arg
= NULL
;
2620 _omap_dispc_set_irqs();
2622 spin_unlock_irqrestore(&dispc
.irq_lock
, flags
);
2626 EXPORT_SYMBOL(omap_dispc_unregister_isr
);
2629 static void print_irq_status(u32 status
)
2631 if ((status
& dispc
.irq_error_mask
) == 0)
2634 printk(KERN_DEBUG
"DISPC IRQ: 0x%x: ", status
);
2637 if (status & DISPC_IRQ_##x) \
2639 PIS(GFX_FIFO_UNDERFLOW
);
2641 PIS(VID1_FIFO_UNDERFLOW
);
2642 PIS(VID2_FIFO_UNDERFLOW
);
2644 PIS(SYNC_LOST_DIGIT
);
2651 /* Called from dss.c. Note that we don't touch clocks here,
2652 * but we presume they are on because we got an IRQ. However,
2653 * an irq handler may turn the clocks off, so we may not have
2654 * clock later in the function. */
2655 void dispc_irq_handler(void)
2659 u32 handledirqs
= 0;
2660 u32 unhandled_errors
;
2661 struct omap_dispc_isr_data
*isr_data
;
2662 struct omap_dispc_isr_data registered_isr
[DISPC_MAX_NR_ISRS
];
2664 spin_lock(&dispc
.irq_lock
);
2666 irqstatus
= dispc_read_reg(DISPC_IRQSTATUS
);
2670 print_irq_status(irqstatus
);
2672 /* Ack the interrupt. Do it here before clocks are possibly turned
2674 dispc_write_reg(DISPC_IRQSTATUS
, irqstatus
);
2675 /* flush posted write */
2676 dispc_read_reg(DISPC_IRQSTATUS
);
2678 /* make a copy and unlock, so that isrs can unregister
2680 memcpy(registered_isr
, dispc
.registered_isr
,
2681 sizeof(registered_isr
));
2683 spin_unlock(&dispc
.irq_lock
);
2685 for (i
= 0; i
< DISPC_MAX_NR_ISRS
; i
++) {
2686 isr_data
= ®istered_isr
[i
];
2691 if (isr_data
->mask
& irqstatus
) {
2692 isr_data
->isr(isr_data
->arg
, irqstatus
);
2693 handledirqs
|= isr_data
->mask
;
2697 spin_lock(&dispc
.irq_lock
);
2699 unhandled_errors
= irqstatus
& ~handledirqs
& dispc
.irq_error_mask
;
2701 if (unhandled_errors
) {
2702 dispc
.error_irqs
|= unhandled_errors
;
2704 dispc
.irq_error_mask
&= ~unhandled_errors
;
2705 _omap_dispc_set_irqs();
2707 schedule_work(&dispc
.error_work
);
2710 spin_unlock(&dispc
.irq_lock
);
2713 static void dispc_error_worker(struct work_struct
*work
)
2717 unsigned long flags
;
2719 spin_lock_irqsave(&dispc
.irq_lock
, flags
);
2720 errors
= dispc
.error_irqs
;
2721 dispc
.error_irqs
= 0;
2722 spin_unlock_irqrestore(&dispc
.irq_lock
, flags
);
2724 if (errors
& DISPC_IRQ_GFX_FIFO_UNDERFLOW
) {
2725 DSSERR("GFX_FIFO_UNDERFLOW, disabling GFX\n");
2726 for (i
= 0; i
< omap_dss_get_num_overlays(); ++i
) {
2727 struct omap_overlay
*ovl
;
2728 ovl
= omap_dss_get_overlay(i
);
2730 if (!(ovl
->caps
& OMAP_DSS_OVL_CAP_DISPC
))
2734 dispc_enable_plane(ovl
->id
, 0);
2735 dispc_go(ovl
->manager
->id
);
2742 if (errors
& DISPC_IRQ_VID1_FIFO_UNDERFLOW
) {
2743 DSSERR("VID1_FIFO_UNDERFLOW, disabling VID1\n");
2744 for (i
= 0; i
< omap_dss_get_num_overlays(); ++i
) {
2745 struct omap_overlay
*ovl
;
2746 ovl
= omap_dss_get_overlay(i
);
2748 if (!(ovl
->caps
& OMAP_DSS_OVL_CAP_DISPC
))
2752 dispc_enable_plane(ovl
->id
, 0);
2753 dispc_go(ovl
->manager
->id
);
2760 if (errors
& DISPC_IRQ_VID2_FIFO_UNDERFLOW
) {
2761 DSSERR("VID2_FIFO_UNDERFLOW, disabling VID2\n");
2762 for (i
= 0; i
< omap_dss_get_num_overlays(); ++i
) {
2763 struct omap_overlay
*ovl
;
2764 ovl
= omap_dss_get_overlay(i
);
2766 if (!(ovl
->caps
& OMAP_DSS_OVL_CAP_DISPC
))
2770 dispc_enable_plane(ovl
->id
, 0);
2771 dispc_go(ovl
->manager
->id
);
2778 if (errors
& DISPC_IRQ_SYNC_LOST
) {
2779 struct omap_overlay_manager
*manager
= NULL
;
2780 bool enable
= false;
2782 DSSERR("SYNC_LOST, disabling LCD\n");
2784 for (i
= 0; i
< omap_dss_get_num_overlay_managers(); ++i
) {
2785 struct omap_overlay_manager
*mgr
;
2786 mgr
= omap_dss_get_overlay_manager(i
);
2788 if (mgr
->id
== OMAP_DSS_CHANNEL_LCD
) {
2790 enable
= mgr
->device
->state
==
2791 OMAP_DSS_DISPLAY_ACTIVE
;
2792 mgr
->device
->disable(mgr
->device
);
2798 for (i
= 0; i
< omap_dss_get_num_overlays(); ++i
) {
2799 struct omap_overlay
*ovl
;
2800 ovl
= omap_dss_get_overlay(i
);
2802 if (!(ovl
->caps
& OMAP_DSS_OVL_CAP_DISPC
))
2805 if (ovl
->id
!= 0 && ovl
->manager
== manager
)
2806 dispc_enable_plane(ovl
->id
, 0);
2809 dispc_go(manager
->id
);
2812 manager
->device
->enable(manager
->device
);
2816 if (errors
& DISPC_IRQ_SYNC_LOST_DIGIT
) {
2817 struct omap_overlay_manager
*manager
= NULL
;
2818 bool enable
= false;
2820 DSSERR("SYNC_LOST_DIGIT, disabling TV\n");
2822 for (i
= 0; i
< omap_dss_get_num_overlay_managers(); ++i
) {
2823 struct omap_overlay_manager
*mgr
;
2824 mgr
= omap_dss_get_overlay_manager(i
);
2826 if (mgr
->id
== OMAP_DSS_CHANNEL_DIGIT
) {
2828 enable
= mgr
->device
->state
==
2829 OMAP_DSS_DISPLAY_ACTIVE
;
2830 mgr
->device
->disable(mgr
->device
);
2836 for (i
= 0; i
< omap_dss_get_num_overlays(); ++i
) {
2837 struct omap_overlay
*ovl
;
2838 ovl
= omap_dss_get_overlay(i
);
2840 if (!(ovl
->caps
& OMAP_DSS_OVL_CAP_DISPC
))
2843 if (ovl
->id
!= 0 && ovl
->manager
== manager
)
2844 dispc_enable_plane(ovl
->id
, 0);
2847 dispc_go(manager
->id
);
2850 manager
->device
->enable(manager
->device
);
2854 if (errors
& DISPC_IRQ_OCP_ERR
) {
2855 DSSERR("OCP_ERR\n");
2856 for (i
= 0; i
< omap_dss_get_num_overlay_managers(); ++i
) {
2857 struct omap_overlay_manager
*mgr
;
2858 mgr
= omap_dss_get_overlay_manager(i
);
2860 if (mgr
->caps
& OMAP_DSS_OVL_CAP_DISPC
)
2861 mgr
->device
->disable(mgr
->device
);
2865 spin_lock_irqsave(&dispc
.irq_lock
, flags
);
2866 dispc
.irq_error_mask
|= errors
;
2867 _omap_dispc_set_irqs();
2868 spin_unlock_irqrestore(&dispc
.irq_lock
, flags
);
2871 int omap_dispc_wait_for_irq_timeout(u32 irqmask
, unsigned long timeout
)
2873 void dispc_irq_wait_handler(void *data
, u32 mask
)
2875 complete((struct completion
*)data
);
2879 DECLARE_COMPLETION_ONSTACK(completion
);
2881 r
= omap_dispc_register_isr(dispc_irq_wait_handler
, &completion
,
2887 timeout
= wait_for_completion_timeout(&completion
, timeout
);
2889 omap_dispc_unregister_isr(dispc_irq_wait_handler
, &completion
, irqmask
);
2894 if (timeout
== -ERESTARTSYS
)
2895 return -ERESTARTSYS
;
2900 int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask
,
2901 unsigned long timeout
)
2903 void dispc_irq_wait_handler(void *data
, u32 mask
)
2905 complete((struct completion
*)data
);
2909 DECLARE_COMPLETION_ONSTACK(completion
);
2911 r
= omap_dispc_register_isr(dispc_irq_wait_handler
, &completion
,
2917 timeout
= wait_for_completion_interruptible_timeout(&completion
,
2920 omap_dispc_unregister_isr(dispc_irq_wait_handler
, &completion
, irqmask
);
2925 if (timeout
== -ERESTARTSYS
)
2926 return -ERESTARTSYS
;
2931 #ifdef CONFIG_OMAP2_DSS_FAKE_VSYNC
2932 void dispc_fake_vsync_irq(void)
2934 u32 irqstatus
= DISPC_IRQ_VSYNC
;
2937 for (i
= 0; i
< DISPC_MAX_NR_ISRS
; i
++) {
2938 struct omap_dispc_isr_data
*isr_data
;
2939 isr_data
= &dispc
.registered_isr
[i
];
2944 if (isr_data
->mask
& irqstatus
)
2945 isr_data
->isr(isr_data
->arg
, irqstatus
);
2950 static void _omap_dispc_initialize_irq(void)
2952 unsigned long flags
;
2954 spin_lock_irqsave(&dispc
.irq_lock
, flags
);
2956 memset(dispc
.registered_isr
, 0, sizeof(dispc
.registered_isr
));
2958 dispc
.irq_error_mask
= DISPC_IRQ_MASK_ERROR
;
2960 /* there's SYNC_LOST_DIGIT waiting after enabling the DSS,
2962 dispc_write_reg(DISPC_IRQSTATUS
, dispc_read_reg(DISPC_IRQSTATUS
));
2964 _omap_dispc_set_irqs();
2966 spin_unlock_irqrestore(&dispc
.irq_lock
, flags
);
2969 void dispc_enable_sidle(void)
2971 REG_FLD_MOD(DISPC_SYSCONFIG
, 2, 4, 3); /* SIDLEMODE: smart idle */
2974 void dispc_disable_sidle(void)
2976 REG_FLD_MOD(DISPC_SYSCONFIG
, 1, 4, 3); /* SIDLEMODE: no idle */
2979 static void _omap_dispc_initial_config(void)
2983 l
= dispc_read_reg(DISPC_SYSCONFIG
);
2984 l
= FLD_MOD(l
, 2, 13, 12); /* MIDLEMODE: smart standby */
2985 l
= FLD_MOD(l
, 2, 4, 3); /* SIDLEMODE: smart idle */
2986 l
= FLD_MOD(l
, 1, 2, 2); /* ENWAKEUP */
2987 l
= FLD_MOD(l
, 1, 0, 0); /* AUTOIDLE */
2988 dispc_write_reg(DISPC_SYSCONFIG
, l
);
2991 REG_FLD_MOD(DISPC_CONFIG
, 1, 9, 9);
2993 /* L3 firewall setting: enable access to OCM RAM */
2994 /* XXX this should be somewhere in plat-omap */
2995 if (cpu_is_omap24xx())
2996 __raw_writel(0x402000b0, OMAP2_L3_IO_ADDRESS(0x680050a0));
2998 _dispc_setup_color_conv_coef();
3000 dispc_set_loadmode(OMAP_DSS_LOAD_FRAME_ONLY
);
3002 dispc_read_plane_fifo_sizes();
3005 int dispc_init(void)
3009 spin_lock_init(&dispc
.irq_lock
);
3011 INIT_WORK(&dispc
.error_work
, dispc_error_worker
);
3013 dispc
.base
= ioremap(DISPC_BASE
, DISPC_SZ_REGS
);
3015 DSSERR("can't ioremap DISPC\n");
3021 _omap_dispc_initial_config();
3023 _omap_dispc_initialize_irq();
3025 dispc_save_context();
3027 rev
= dispc_read_reg(DISPC_REVISION
);
3028 printk(KERN_INFO
"OMAP DISPC rev %d.%d\n",
3029 FLD_GET(rev
, 7, 4), FLD_GET(rev
, 3, 0));
3036 void dispc_exit(void)
3038 iounmap(dispc
.base
);
3041 int dispc_enable_plane(enum omap_plane plane
, bool enable
)
3043 DSSDBG("dispc_enable_plane %d, %d\n", plane
, enable
);
3046 _dispc_enable_plane(plane
, enable
);
3052 int dispc_setup_plane(enum omap_plane plane
,
3053 u32 paddr
, u16 screen_width
,
3054 u16 pos_x
, u16 pos_y
,
3055 u16 width
, u16 height
,
3056 u16 out_width
, u16 out_height
,
3057 enum omap_color_mode color_mode
,
3059 enum omap_dss_rotation_type rotation_type
,
3060 u8 rotation
, bool mirror
, u8 global_alpha
)
3064 DSSDBG("dispc_setup_plane %d, pa %x, sw %d, %d,%d, %dx%d -> "
3065 "%dx%d, ilace %d, cmode %x, rot %d, mir %d\n",
3066 plane
, paddr
, screen_width
, pos_x
, pos_y
,
3068 out_width
, out_height
,
3074 r
= _dispc_setup_plane(plane
,
3075 paddr
, screen_width
,
3078 out_width
, out_height
,