aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video
diff options
context:
space:
mode:
authorTomi Valkeinen <tomi.valkeinen@ti.com>2012-09-26 09:48:55 -0400
committerTomi Valkeinen <tomi.valkeinen@ti.com>2012-09-26 09:48:55 -0400
commit69036f0ccd9d48b4e999be4e98fa459430ec93b4 (patch)
treee09e075957c7e9b8299e57883d50eb3cff6ee3b2 /drivers/video
parent866f0956cba7d28432f20f8a696e5c1a2b40b915 (diff)
parent6e5264b0380593efda8157406ec40f00daac9f2d (diff)
Merge branch 'archit/wb-dispc-for-3.7'
Merge omapdss writeback work. These patches implement the low level writeback features in the DISPC, but do not yet add a way to actually use the writeback from the userspace. * archit/wb-dispc-for-3.7: OMAPDSS: DISPC: Configure color conversion coefficients for writeback OMAPDSS: DISPC: Add manager like functions for writeback OMAPDSS: DISPC: Configure writeback FIFOs OMAPDSS: DISPC: Configure writeback specific parameters in dispc_wb_setup() OMAPDSS: DISPC: Configure overlay-like parameters in dispc_wb_setup OMAPDSS: DISPC: Add function to set channel in for writeback OMAPDSS: DISPC: Don't set chroma resampling bit for writeback OMAPDSS: DISPC: Downscale chroma if plane is writeback OMAPDSS: DISPC: Configure input and output sizes for writeback OMAPDSS: DISPC: Add writeback register offsets and dss features structs OMAPDSS: DISPC: Allow both upscaling and downscaling of chroma OMAPDSS: DIPSC: Relax scaling limitations when in memory to memory mode OMAPDSS: DISPC: Don't pass channel out when configuring overlays OMAPDSS: DISPC: Make dispc_ovl_setup call dispc_ovl_setup_common OMAPDSS: OVERLAY: Add position and replication as overlay caps OMAPDSS: DISPC: Pass overlay caps as a parameter to dispc plane functions OMAPDSS: DISPC: Simplify function names for setting pipeline input and output sizes OMAPDSS: DISPC: Constify omap_overlay_info in dispc_ovl_setup()
Diffstat (limited to 'drivers/video')
-rw-r--r--drivers/video/omap2/dss/apply.c2
-rw-r--r--drivers/video/omap2/dss/dispc.c562
-rw-r--r--drivers/video/omap2/dss/dispc.h33
-rw-r--r--drivers/video/omap2/dss/dss.h25
-rw-r--r--drivers/video/omap2/dss/dss_features.c57
-rw-r--r--drivers/video/omap2/dss/dss_features.h1
6 files changed, 495 insertions, 185 deletions
diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c
index 2b1fa851a8b9..19d66f471b4b 100644
--- a/drivers/video/omap2/dss/apply.c
+++ b/drivers/video/omap2/dss/apply.c
@@ -584,7 +584,7 @@ static void dss_ovl_write_regs(struct omap_overlay *ovl)
584 584
585 replication = dss_ovl_use_replication(mp->lcd_config, oi->color_mode); 585 replication = dss_ovl_use_replication(mp->lcd_config, oi->color_mode);
586 586
587 r = dispc_ovl_setup(ovl->id, oi, replication, &mp->timings); 587 r = dispc_ovl_setup(ovl->id, oi, replication, &mp->timings, false);
588 if (r) { 588 if (r) {
589 /* 589 /*
590 * We can't do much here, as this function can be called from 590 * We can't do much here, as this function can be called from
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index 811fe381aaea..a173a9481a23 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -86,14 +86,15 @@ struct dispc_features {
86 u16 sw_max; 86 u16 sw_max;
87 u16 vp_max; 87 u16 vp_max;
88 u16 hp_max; 88 u16 hp_max;
89 int (*calc_scaling) (enum omap_channel channel, 89 int (*calc_scaling) (enum omap_plane plane,
90 const struct omap_video_timings *mgr_timings, 90 const struct omap_video_timings *mgr_timings,
91 u16 width, u16 height, u16 out_width, u16 out_height, 91 u16 width, u16 height, u16 out_width, u16 out_height,
92 enum omap_color_mode color_mode, bool *five_taps, 92 enum omap_color_mode color_mode, bool *five_taps,
93 int *x_predecim, int *y_predecim, int *decim_x, int *decim_y, 93 int *x_predecim, int *y_predecim, int *decim_x, int *decim_y,
94 u16 pos_x, unsigned long *core_clk); 94 u16 pos_x, unsigned long *core_clk, bool mem_to_mem);
95 unsigned long (*calc_core_clk) (enum omap_channel channel, 95 unsigned long (*calc_core_clk) (enum omap_plane plane,
96 u16 width, u16 height, u16 out_width, u16 out_height); 96 u16 width, u16 height, u16 out_width, u16 out_height,
97 bool mem_to_mem);
97 u8 num_fifos; 98 u8 num_fifos;
98 99
99 /* swap GFX & WB fifos */ 100 /* swap GFX & WB fifos */
@@ -235,7 +236,14 @@ static const struct {
235 }, 236 },
236}; 237};
237 238
239struct color_conv_coef {
240 int ry, rcr, rcb, gy, gcr, gcb, by, bcr, bcb;
241 int full_range;
242};
243
238static void _omap_dispc_set_irqs(void); 244static void _omap_dispc_set_irqs(void);
245static unsigned long dispc_plane_pclk_rate(enum omap_plane plane);
246static unsigned long dispc_plane_lclk_rate(enum omap_plane plane);
239 247
240static inline void dispc_write_reg(const u16 idx, u32 val) 248static inline void dispc_write_reg(const u16 idx, u32 val)
241{ 249{
@@ -533,6 +541,11 @@ u32 dispc_mgr_get_framedone_irq(enum omap_channel channel)
533 return mgr_desc[channel].framedone_irq; 541 return mgr_desc[channel].framedone_irq;
534} 542}
535 543
544u32 dispc_wb_get_framedone_irq(void)
545{
546 return DISPC_IRQ_FRAMEDONEWB;
547}
548
536bool dispc_mgr_go_busy(enum omap_channel channel) 549bool dispc_mgr_go_busy(enum omap_channel channel)
537{ 550{
538 return mgr_fld_read(channel, DISPC_MGR_FLD_GO) == 1; 551 return mgr_fld_read(channel, DISPC_MGR_FLD_GO) == 1;
@@ -560,6 +573,30 @@ void dispc_mgr_go(enum omap_channel channel)
560 mgr_fld_write(channel, DISPC_MGR_FLD_GO, 1); 573 mgr_fld_write(channel, DISPC_MGR_FLD_GO, 1);
561} 574}
562 575
576bool dispc_wb_go_busy(void)
577{
578 return REG_GET(DISPC_CONTROL2, 6, 6) == 1;
579}
580
581void dispc_wb_go(void)
582{
583 enum omap_plane plane = OMAP_DSS_WB;
584 bool enable, go;
585
586 enable = REG_GET(DISPC_OVL_ATTRIBUTES(plane), 0, 0) == 1;
587
588 if (!enable)
589 return;
590
591 go = REG_GET(DISPC_CONTROL2, 6, 6) == 1;
592 if (go) {
593 DSSERR("GO bit not down for WB\n");
594 return;
595 }
596
597 REG_FLD_MOD(DISPC_CONTROL2, 1, 6, 6);
598}
599
563static void dispc_ovl_write_firh_reg(enum omap_plane plane, int reg, u32 value) 600static void dispc_ovl_write_firh_reg(enum omap_plane plane, int reg, u32 value)
564{ 601{
565 dispc_write_reg(DISPC_OVL_FIR_COEF_H(plane, reg), value); 602 dispc_write_reg(DISPC_OVL_FIR_COEF_H(plane, reg), value);
@@ -642,41 +679,41 @@ static void dispc_ovl_set_scale_coef(enum omap_plane plane, int fir_hinc,
642 } 679 }
643} 680}
644 681
645static void _dispc_setup_color_conv_coef(void)
646{
647 int i;
648 const struct color_conv_coef {
649 int ry, rcr, rcb, gy, gcr, gcb, by, bcr, bcb;
650 int full_range;
651 } ctbl_bt601_5 = {
652 298, 409, 0, 298, -208, -100, 298, 0, 517, 0,
653 };
654
655 const struct color_conv_coef *ct;
656 682
683static void dispc_ovl_write_color_conv_coef(enum omap_plane plane,
684 const struct color_conv_coef *ct)
685{
657#define CVAL(x, y) (FLD_VAL(x, 26, 16) | FLD_VAL(y, 10, 0)) 686#define CVAL(x, y) (FLD_VAL(x, 26, 16) | FLD_VAL(y, 10, 0))
658 687
659 ct = &ctbl_bt601_5; 688 dispc_write_reg(DISPC_OVL_CONV_COEF(plane, 0), CVAL(ct->rcr, ct->ry));
689 dispc_write_reg(DISPC_OVL_CONV_COEF(plane, 1), CVAL(ct->gy, ct->rcb));
690 dispc_write_reg(DISPC_OVL_CONV_COEF(plane, 2), CVAL(ct->gcb, ct->gcr));
691 dispc_write_reg(DISPC_OVL_CONV_COEF(plane, 3), CVAL(ct->bcr, ct->by));
692 dispc_write_reg(DISPC_OVL_CONV_COEF(plane, 4), CVAL(0, ct->bcb));
660 693
661 for (i = 1; i < dss_feat_get_num_ovls(); i++) { 694 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), ct->full_range, 11, 11);
662 dispc_write_reg(DISPC_OVL_CONV_COEF(i, 0),
663 CVAL(ct->rcr, ct->ry));
664 dispc_write_reg(DISPC_OVL_CONV_COEF(i, 1),
665 CVAL(ct->gy, ct->rcb));
666 dispc_write_reg(DISPC_OVL_CONV_COEF(i, 2),
667 CVAL(ct->gcb, ct->gcr));
668 dispc_write_reg(DISPC_OVL_CONV_COEF(i, 3),
669 CVAL(ct->bcr, ct->by));
670 dispc_write_reg(DISPC_OVL_CONV_COEF(i, 4),
671 CVAL(0, ct->bcb));
672
673 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(i), ct->full_range,
674 11, 11);
675 }
676 695
677#undef CVAL 696#undef CVAL
678} 697}
679 698
699static void dispc_setup_color_conv_coef(void)
700{
701 int i;
702 int num_ovl = dss_feat_get_num_ovls();
703 int num_wb = dss_feat_get_num_wbs();
704 const struct color_conv_coef ctbl_bt601_5_ovl = {
705 298, 409, 0, 298, -208, -100, 298, 0, 517, 0,
706 };
707 const struct color_conv_coef ctbl_bt601_5_wb = {
708 66, 112, -38, 129, -94, -74, 25, -18, 112, 0,
709 };
710
711 for (i = 1; i < num_ovl; i++)
712 dispc_ovl_write_color_conv_coef(i, &ctbl_bt601_5_ovl);
713
714 for (; i < num_wb; i++)
715 dispc_ovl_write_color_conv_coef(i, &ctbl_bt601_5_wb);
716}
680 717
681static void dispc_ovl_set_ba0(enum omap_plane plane, u32 paddr) 718static void dispc_ovl_set_ba0(enum omap_plane plane, u32 paddr)
682{ 719{
@@ -698,24 +735,32 @@ static void dispc_ovl_set_ba1_uv(enum omap_plane plane, u32 paddr)
698 dispc_write_reg(DISPC_OVL_BA1_UV(plane), paddr); 735 dispc_write_reg(DISPC_OVL_BA1_UV(plane), paddr);
699} 736}
700 737
701static void dispc_ovl_set_pos(enum omap_plane plane, int x, int y) 738static void dispc_ovl_set_pos(enum omap_plane plane,
739 enum omap_overlay_caps caps, int x, int y)
702{ 740{
703 u32 val = FLD_VAL(y, 26, 16) | FLD_VAL(x, 10, 0); 741 u32 val;
742
743 if ((caps & OMAP_DSS_OVL_CAP_POS) == 0)
744 return;
745
746 val = FLD_VAL(y, 26, 16) | FLD_VAL(x, 10, 0);
704 747
705 dispc_write_reg(DISPC_OVL_POSITION(plane), val); 748 dispc_write_reg(DISPC_OVL_POSITION(plane), val);
706} 749}
707 750
708static void dispc_ovl_set_pic_size(enum omap_plane plane, int width, int height) 751static void dispc_ovl_set_input_size(enum omap_plane plane, int width,
752 int height)
709{ 753{
710 u32 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0); 754 u32 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
711 755
712 if (plane == OMAP_DSS_GFX) 756 if (plane == OMAP_DSS_GFX || plane == OMAP_DSS_WB)
713 dispc_write_reg(DISPC_OVL_SIZE(plane), val); 757 dispc_write_reg(DISPC_OVL_SIZE(plane), val);
714 else 758 else
715 dispc_write_reg(DISPC_OVL_PICTURE_SIZE(plane), val); 759 dispc_write_reg(DISPC_OVL_PICTURE_SIZE(plane), val);
716} 760}
717 761
718static void dispc_ovl_set_vid_size(enum omap_plane plane, int width, int height) 762static void dispc_ovl_set_output_size(enum omap_plane plane, int width,
763 int height)
719{ 764{
720 u32 val; 765 u32 val;
721 766
@@ -723,14 +768,16 @@ static void dispc_ovl_set_vid_size(enum omap_plane plane, int width, int height)
723 768
724 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0); 769 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
725 770
726 dispc_write_reg(DISPC_OVL_SIZE(plane), val); 771 if (plane == OMAP_DSS_WB)
772 dispc_write_reg(DISPC_OVL_PICTURE_SIZE(plane), val);
773 else
774 dispc_write_reg(DISPC_OVL_SIZE(plane), val);
727} 775}
728 776
729static void dispc_ovl_set_zorder(enum omap_plane plane, u8 zorder) 777static void dispc_ovl_set_zorder(enum omap_plane plane,
778 enum omap_overlay_caps caps, u8 zorder)
730{ 779{
731 struct omap_overlay *ovl = omap_dss_get_overlay(plane); 780 if ((caps & OMAP_DSS_OVL_CAP_ZORDER) == 0)
732
733 if ((ovl->caps & OMAP_DSS_OVL_CAP_ZORDER) == 0)
734 return; 781 return;
735 782
736 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), zorder, 27, 26); 783 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), zorder, 27, 26);
@@ -747,23 +794,22 @@ static void dispc_ovl_enable_zorder_planes(void)
747 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(i), 1, 25, 25); 794 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(i), 1, 25, 25);
748} 795}
749 796
750static void dispc_ovl_set_pre_mult_alpha(enum omap_plane plane, bool enable) 797static void dispc_ovl_set_pre_mult_alpha(enum omap_plane plane,
798 enum omap_overlay_caps caps, bool enable)
751{ 799{
752 struct omap_overlay *ovl = omap_dss_get_overlay(plane); 800 if ((caps & OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA) == 0)
753
754 if ((ovl->caps & OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA) == 0)
755 return; 801 return;
756 802
757 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable ? 1 : 0, 28, 28); 803 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable ? 1 : 0, 28, 28);
758} 804}
759 805
760static void dispc_ovl_setup_global_alpha(enum omap_plane plane, u8 global_alpha) 806static void dispc_ovl_setup_global_alpha(enum omap_plane plane,
807 enum omap_overlay_caps caps, u8 global_alpha)
761{ 808{
762 static const unsigned shifts[] = { 0, 8, 16, 24, }; 809 static const unsigned shifts[] = { 0, 8, 16, 24, };
763 int shift; 810 int shift;
764 struct omap_overlay *ovl = omap_dss_get_overlay(plane);
765 811
766 if ((ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) == 0) 812 if ((caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) == 0)
767 return; 813 return;
768 814
769 shift = shifts[plane]; 815 shift = shifts[plane];
@@ -971,10 +1017,17 @@ static enum omap_channel dispc_ovl_get_channel_out(enum omap_plane plane)
971 return channel; 1017 return channel;
972} 1018}
973 1019
1020void dispc_wb_set_channel_in(enum dss_writeback_channel channel)
1021{
1022 enum omap_plane plane = OMAP_DSS_WB;
1023
1024 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), channel, 18, 16);
1025}
1026
974static void dispc_ovl_set_burst_size(enum omap_plane plane, 1027static void dispc_ovl_set_burst_size(enum omap_plane plane,
975 enum omap_burst_size burst_size) 1028 enum omap_burst_size burst_size)
976{ 1029{
977 static const unsigned shifts[] = { 6, 14, 14, 14, }; 1030 static const unsigned shifts[] = { 6, 14, 14, 14, 14, };
978 int shift; 1031 int shift;
979 1032
980 shift = shifts[plane]; 1033 shift = shifts[plane];
@@ -1051,11 +1104,15 @@ static void dispc_ovl_set_vid_color_conv(enum omap_plane plane, bool enable)
1051 dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val); 1104 dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val);
1052} 1105}
1053 1106
1054static void dispc_ovl_enable_replication(enum omap_plane plane, bool enable) 1107static void dispc_ovl_enable_replication(enum omap_plane plane,
1108 enum omap_overlay_caps caps, bool enable)
1055{ 1109{
1056 static const unsigned shifts[] = { 5, 10, 10, 10 }; 1110 static const unsigned shifts[] = { 5, 10, 10, 10 };
1057 int shift; 1111 int shift;
1058 1112
1113 if ((caps & OMAP_DSS_OVL_CAP_REPLICATION) == 0)
1114 return;
1115
1059 shift = shifts[plane]; 1116 shift = shifts[plane];
1060 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable, shift, shift); 1117 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable, shift, shift);
1061} 1118}
@@ -1202,6 +1259,14 @@ void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane,
1202 if (manual_update && dss_has_feature(FEAT_OMAP3_DSI_FIFO_BUG)) { 1259 if (manual_update && dss_has_feature(FEAT_OMAP3_DSI_FIFO_BUG)) {
1203 *fifo_low = ovl_fifo_size - burst_size * 2; 1260 *fifo_low = ovl_fifo_size - burst_size * 2;
1204 *fifo_high = total_fifo_size - burst_size; 1261 *fifo_high = total_fifo_size - burst_size;
1262 } else if (plane == OMAP_DSS_WB) {
1263 /*
1264 * Most optimal configuration for writeback is to push out data
1265 * to the interconnect the moment writeback pushes enough pixels
1266 * in the FIFO to form a burst
1267 */
1268 *fifo_low = 0;
1269 *fifo_high = burst_size;
1205 } else { 1270 } else {
1206 *fifo_low = ovl_fifo_size - burst_size; 1271 *fifo_low = ovl_fifo_size - burst_size;
1207 *fifo_high = total_fifo_size - buf_unit; 1272 *fifo_high = total_fifo_size - buf_unit;
@@ -1444,6 +1509,7 @@ static void dispc_ovl_set_scaling_uv(enum omap_plane plane,
1444{ 1509{
1445 int scale_x = out_width != orig_width; 1510 int scale_x = out_width != orig_width;
1446 int scale_y = out_height != orig_height; 1511 int scale_y = out_height != orig_height;
1512 bool chroma_upscale = plane != OMAP_DSS_WB ? true : false;
1447 1513
1448 if (!dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) 1514 if (!dss_has_feature(FEAT_HANDLE_UV_SEPARATE))
1449 return; 1515 return;
@@ -1451,7 +1517,8 @@ static void dispc_ovl_set_scaling_uv(enum omap_plane plane,
1451 color_mode != OMAP_DSS_COLOR_UYVY && 1517 color_mode != OMAP_DSS_COLOR_UYVY &&
1452 color_mode != OMAP_DSS_COLOR_NV12)) { 1518 color_mode != OMAP_DSS_COLOR_NV12)) {
1453 /* reset chroma resampling for RGB formats */ 1519 /* reset chroma resampling for RGB formats */
1454 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES2(plane), 0, 8, 8); 1520 if (plane != OMAP_DSS_WB)
1521 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES2(plane), 0, 8, 8);
1455 return; 1522 return;
1456 } 1523 }
1457 1524
@@ -1460,23 +1527,34 @@ static void dispc_ovl_set_scaling_uv(enum omap_plane plane,
1460 1527
1461 switch (color_mode) { 1528 switch (color_mode) {
1462 case OMAP_DSS_COLOR_NV12: 1529 case OMAP_DSS_COLOR_NV12:
1463 /* UV is subsampled by 2 vertically*/ 1530 if (chroma_upscale) {
1464 orig_height >>= 1; 1531 /* UV is subsampled by 2 horizontally and vertically */
1465 /* UV is subsampled by 2 horz.*/ 1532 orig_height >>= 1;
1466 orig_width >>= 1; 1533 orig_width >>= 1;
1534 } else {
1535 /* UV is downsampled by 2 horizontally and vertically */
1536 orig_height <<= 1;
1537 orig_width <<= 1;
1538 }
1539
1467 break; 1540 break;
1468 case OMAP_DSS_COLOR_YUV2: 1541 case OMAP_DSS_COLOR_YUV2:
1469 case OMAP_DSS_COLOR_UYVY: 1542 case OMAP_DSS_COLOR_UYVY:
1470 /*For YUV422 with 90/270 rotation, 1543 /* For YUV422 with 90/270 rotation, we don't upsample chroma */
1471 *we don't upsample chroma
1472 */
1473 if (rotation == OMAP_DSS_ROT_0 || 1544 if (rotation == OMAP_DSS_ROT_0 ||
1474 rotation == OMAP_DSS_ROT_180) 1545 rotation == OMAP_DSS_ROT_180) {
1475 /* UV is subsampled by 2 hrz*/ 1546 if (chroma_upscale)
1476 orig_width >>= 1; 1547 /* UV is subsampled by 2 horizontally */
1548 orig_width >>= 1;
1549 else
1550 /* UV is downsampled by 2 horizontally */
1551 orig_width <<= 1;
1552 }
1553
1477 /* must use FIR for YUV422 if rotated */ 1554 /* must use FIR for YUV422 if rotated */
1478 if (rotation != OMAP_DSS_ROT_0) 1555 if (rotation != OMAP_DSS_ROT_0)
1479 scale_x = scale_y = true; 1556 scale_x = scale_y = true;
1557
1480 break; 1558 break;
1481 default: 1559 default:
1482 BUG(); 1560 BUG();
@@ -1492,8 +1570,10 @@ static void dispc_ovl_set_scaling_uv(enum omap_plane plane,
1492 out_width, out_height, five_taps, 1570 out_width, out_height, five_taps,
1493 rotation, DISPC_COLOR_COMPONENT_UV); 1571 rotation, DISPC_COLOR_COMPONENT_UV);
1494 1572
1495 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES2(plane), 1573 if (plane != OMAP_DSS_WB)
1496 (scale_x || scale_y) ? 1 : 0, 8, 8); 1574 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES2(plane),
1575 (scale_x || scale_y) ? 1 : 0, 8, 8);
1576
1497 /* set H scaling */ 1577 /* set H scaling */
1498 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), scale_x ? 1 : 0, 5, 5); 1578 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), scale_x ? 1 : 0, 5, 5);
1499 /* set V scaling */ 1579 /* set V scaling */
@@ -1909,22 +1989,19 @@ static void calc_tiler_rotation_offset(u16 screen_width, u16 width,
1909 * This function is used to avoid synclosts in OMAP3, because of some 1989 * This function is used to avoid synclosts in OMAP3, because of some
1910 * undocumented horizontal position and timing related limitations. 1990 * undocumented horizontal position and timing related limitations.
1911 */ 1991 */
1912static int check_horiz_timing_omap3(enum omap_channel channel, 1992static int check_horiz_timing_omap3(enum omap_plane plane,
1913 const struct omap_video_timings *t, u16 pos_x, 1993 const struct omap_video_timings *t, u16 pos_x,
1914 u16 width, u16 height, u16 out_width, u16 out_height) 1994 u16 width, u16 height, u16 out_width, u16 out_height)
1915{ 1995{
1916 int DS = DIV_ROUND_UP(height, out_height); 1996 int DS = DIV_ROUND_UP(height, out_height);
1917 unsigned long nonactive, lclk, pclk; 1997 unsigned long nonactive;
1918 static const u8 limits[3] = { 8, 10, 20 }; 1998 static const u8 limits[3] = { 8, 10, 20 };
1919 u64 val, blank; 1999 u64 val, blank;
2000 unsigned long pclk = dispc_plane_pclk_rate(plane);
2001 unsigned long lclk = dispc_plane_lclk_rate(plane);
1920 int i; 2002 int i;
1921 2003
1922 nonactive = t->x_res + t->hfp + t->hsw + t->hbp - out_width; 2004 nonactive = t->x_res + t->hfp + t->hsw + t->hbp - out_width;
1923 pclk = dispc_mgr_pclk_rate(channel);
1924 if (dss_mgr_is_lcd(channel))
1925 lclk = dispc_mgr_lclk_rate(channel);
1926 else
1927 lclk = dispc_fclk_rate();
1928 2005
1929 i = 0; 2006 i = 0;
1930 if (out_height < height) 2007 if (out_height < height)
@@ -1961,13 +2038,14 @@ static int check_horiz_timing_omap3(enum omap_channel channel,
1961 return 0; 2038 return 0;
1962} 2039}
1963 2040
1964static unsigned long calc_core_clk_five_taps(enum omap_channel channel, 2041static unsigned long calc_core_clk_five_taps(enum omap_plane plane,
1965 const struct omap_video_timings *mgr_timings, u16 width, 2042 const struct omap_video_timings *mgr_timings, u16 width,
1966 u16 height, u16 out_width, u16 out_height, 2043 u16 height, u16 out_width, u16 out_height,
1967 enum omap_color_mode color_mode) 2044 enum omap_color_mode color_mode)
1968{ 2045{
1969 u32 core_clk = 0; 2046 u32 core_clk = 0;
1970 u64 tmp, pclk = dispc_mgr_pclk_rate(channel); 2047 u64 tmp;
2048 unsigned long pclk = dispc_plane_pclk_rate(plane);
1971 2049
1972 if (height <= out_height && width <= out_width) 2050 if (height <= out_height && width <= out_width)
1973 return (unsigned long) pclk; 2051 return (unsigned long) pclk;
@@ -2001,10 +2079,10 @@ static unsigned long calc_core_clk_five_taps(enum omap_channel channel,
2001 return core_clk; 2079 return core_clk;
2002} 2080}
2003 2081
2004static unsigned long calc_core_clk_24xx(enum omap_channel channel, u16 width, 2082static unsigned long calc_core_clk_24xx(enum omap_plane plane, u16 width,
2005 u16 height, u16 out_width, u16 out_height) 2083 u16 height, u16 out_width, u16 out_height, bool mem_to_mem)
2006{ 2084{
2007 unsigned long pclk = dispc_mgr_pclk_rate(channel); 2085 unsigned long pclk = dispc_plane_pclk_rate(plane);
2008 2086
2009 if (height > out_height && width > out_width) 2087 if (height > out_height && width > out_width)
2010 return pclk * 4; 2088 return pclk * 4;
@@ -2012,11 +2090,11 @@ static unsigned long calc_core_clk_24xx(enum omap_channel channel, u16 width,
2012 return pclk * 2; 2090 return pclk * 2;
2013} 2091}
2014 2092
2015static unsigned long calc_core_clk_34xx(enum omap_channel channel, u16 width, 2093static unsigned long calc_core_clk_34xx(enum omap_plane plane, u16 width,
2016 u16 height, u16 out_width, u16 out_height) 2094 u16 height, u16 out_width, u16 out_height, bool mem_to_mem)
2017{ 2095{
2018 unsigned int hf, vf; 2096 unsigned int hf, vf;
2019 unsigned long pclk = dispc_mgr_pclk_rate(channel); 2097 unsigned long pclk = dispc_plane_pclk_rate(plane);
2020 2098
2021 /* 2099 /*
2022 * FIXME how to determine the 'A' factor 2100 * FIXME how to determine the 'A' factor
@@ -2039,10 +2117,21 @@ static unsigned long calc_core_clk_34xx(enum omap_channel channel, u16 width,
2039 return pclk * vf * hf; 2117 return pclk * vf * hf;
2040} 2118}
2041 2119
2042static unsigned long calc_core_clk_44xx(enum omap_channel channel, u16 width, 2120static unsigned long calc_core_clk_44xx(enum omap_plane plane, u16 width,
2043 u16 height, u16 out_width, u16 out_height) 2121 u16 height, u16 out_width, u16 out_height, bool mem_to_mem)
2044{ 2122{
2045 unsigned long pclk = dispc_mgr_pclk_rate(channel); 2123 unsigned long pclk;
2124
2125 /*
2126 * If the overlay/writeback is in mem to mem mode, there are no
2127 * downscaling limitations with respect to pixel clock, return 1 as
2128 * required core clock to represent that we have sufficient enough
2129 * core clock to do maximum downscaling
2130 */
2131 if (mem_to_mem)
2132 return 1;
2133
2134 pclk = dispc_plane_pclk_rate(plane);
2046 2135
2047 if (width > out_width) 2136 if (width > out_width)
2048 return DIV_ROUND_UP(pclk, out_width) * width; 2137 return DIV_ROUND_UP(pclk, out_width) * width;
@@ -2050,25 +2139,26 @@ static unsigned long calc_core_clk_44xx(enum omap_channel channel, u16 width,
2050 return pclk; 2139 return pclk;
2051} 2140}
2052 2141
2053static int dispc_ovl_calc_scaling_24xx(enum omap_channel channel, 2142static int dispc_ovl_calc_scaling_24xx(enum omap_plane plane,
2054 const struct omap_video_timings *mgr_timings, 2143 const struct omap_video_timings *mgr_timings,
2055 u16 width, u16 height, u16 out_width, u16 out_height, 2144 u16 width, u16 height, u16 out_width, u16 out_height,
2056 enum omap_color_mode color_mode, bool *five_taps, 2145 enum omap_color_mode color_mode, bool *five_taps,
2057 int *x_predecim, int *y_predecim, int *decim_x, int *decim_y, 2146 int *x_predecim, int *y_predecim, int *decim_x, int *decim_y,
2058 u16 pos_x, unsigned long *core_clk) 2147 u16 pos_x, unsigned long *core_clk, bool mem_to_mem)
2059{ 2148{
2060 int error; 2149 int error;
2061 u16 in_width, in_height; 2150 u16 in_width, in_height;
2062 int min_factor = min(*decim_x, *decim_y); 2151 int min_factor = min(*decim_x, *decim_y);
2063 const int maxsinglelinewidth = 2152 const int maxsinglelinewidth =
2064 dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH); 2153 dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH);
2154
2065 *five_taps = false; 2155 *five_taps = false;
2066 2156
2067 do { 2157 do {
2068 in_height = DIV_ROUND_UP(height, *decim_y); 2158 in_height = DIV_ROUND_UP(height, *decim_y);
2069 in_width = DIV_ROUND_UP(width, *decim_x); 2159 in_width = DIV_ROUND_UP(width, *decim_x);
2070 *core_clk = dispc.feat->calc_core_clk(channel, in_width, 2160 *core_clk = dispc.feat->calc_core_clk(plane, in_width,
2071 in_height, out_width, out_height); 2161 in_height, out_width, out_height, mem_to_mem);
2072 error = (in_width > maxsinglelinewidth || !*core_clk || 2162 error = (in_width > maxsinglelinewidth || !*core_clk ||
2073 *core_clk > dispc_core_clk_rate()); 2163 *core_clk > dispc_core_clk_rate());
2074 if (error) { 2164 if (error) {
@@ -2090,12 +2180,12 @@ static int dispc_ovl_calc_scaling_24xx(enum omap_channel channel,
2090 return 0; 2180 return 0;
2091} 2181}
2092 2182
2093static int dispc_ovl_calc_scaling_34xx(enum omap_channel channel, 2183static int dispc_ovl_calc_scaling_34xx(enum omap_plane plane,
2094 const struct omap_video_timings *mgr_timings, 2184 const struct omap_video_timings *mgr_timings,
2095 u16 width, u16 height, u16 out_width, u16 out_height, 2185 u16 width, u16 height, u16 out_width, u16 out_height,
2096 enum omap_color_mode color_mode, bool *five_taps, 2186 enum omap_color_mode color_mode, bool *five_taps,
2097 int *x_predecim, int *y_predecim, int *decim_x, int *decim_y, 2187 int *x_predecim, int *y_predecim, int *decim_x, int *decim_y,
2098 u16 pos_x, unsigned long *core_clk) 2188 u16 pos_x, unsigned long *core_clk, bool mem_to_mem)
2099{ 2189{
2100 int error; 2190 int error;
2101 u16 in_width, in_height; 2191 u16 in_width, in_height;
@@ -2106,19 +2196,21 @@ static int dispc_ovl_calc_scaling_34xx(enum omap_channel channel,
2106 do { 2196 do {
2107 in_height = DIV_ROUND_UP(height, *decim_y); 2197 in_height = DIV_ROUND_UP(height, *decim_y);
2108 in_width = DIV_ROUND_UP(width, *decim_x); 2198 in_width = DIV_ROUND_UP(width, *decim_x);
2109 *core_clk = calc_core_clk_five_taps(channel, mgr_timings, 2199 *core_clk = calc_core_clk_five_taps(plane, mgr_timings,
2110 in_width, in_height, out_width, out_height, color_mode); 2200 in_width, in_height, out_width, out_height, color_mode);
2111 2201
2112 error = check_horiz_timing_omap3(channel, mgr_timings, pos_x, 2202 error = check_horiz_timing_omap3(plane, mgr_timings,
2113 in_width, in_height, out_width, out_height); 2203 pos_x, in_width, in_height, out_width,
2204 out_height);
2114 2205
2115 if (in_width > maxsinglelinewidth) 2206 if (in_width > maxsinglelinewidth)
2116 if (in_height > out_height && 2207 if (in_height > out_height &&
2117 in_height < out_height * 2) 2208 in_height < out_height * 2)
2118 *five_taps = false; 2209 *five_taps = false;
2119 if (!*five_taps) 2210 if (!*five_taps)
2120 *core_clk = dispc.feat->calc_core_clk(channel, in_width, 2211 *core_clk = dispc.feat->calc_core_clk(plane, in_width,
2121 in_height, out_width, out_height); 2212 in_height, out_width, out_height,
2213 mem_to_mem);
2122 2214
2123 error = (error || in_width > maxsinglelinewidth * 2 || 2215 error = (error || in_width > maxsinglelinewidth * 2 ||
2124 (in_width > maxsinglelinewidth && *five_taps) || 2216 (in_width > maxsinglelinewidth && *five_taps) ||
@@ -2135,7 +2227,7 @@ static int dispc_ovl_calc_scaling_34xx(enum omap_channel channel,
2135 } 2227 }
2136 } while (*decim_x <= *x_predecim && *decim_y <= *y_predecim && error); 2228 } while (*decim_x <= *x_predecim && *decim_y <= *y_predecim && error);
2137 2229
2138 if (check_horiz_timing_omap3(channel, mgr_timings, pos_x, width, height, 2230 if (check_horiz_timing_omap3(plane, mgr_timings, pos_x, width, height,
2139 out_width, out_height)){ 2231 out_width, out_height)){
2140 DSSERR("horizontal timing too tight\n"); 2232 DSSERR("horizontal timing too tight\n");
2141 return -EINVAL; 2233 return -EINVAL;
@@ -2154,21 +2246,27 @@ static int dispc_ovl_calc_scaling_34xx(enum omap_channel channel,
2154 return 0; 2246 return 0;
2155} 2247}
2156 2248
2157static int dispc_ovl_calc_scaling_44xx(enum omap_channel channel, 2249static int dispc_ovl_calc_scaling_44xx(enum omap_plane plane,
2158 const struct omap_video_timings *mgr_timings, 2250 const struct omap_video_timings *mgr_timings,
2159 u16 width, u16 height, u16 out_width, u16 out_height, 2251 u16 width, u16 height, u16 out_width, u16 out_height,
2160 enum omap_color_mode color_mode, bool *five_taps, 2252 enum omap_color_mode color_mode, bool *five_taps,
2161 int *x_predecim, int *y_predecim, int *decim_x, int *decim_y, 2253 int *x_predecim, int *y_predecim, int *decim_x, int *decim_y,
2162 u16 pos_x, unsigned long *core_clk) 2254 u16 pos_x, unsigned long *core_clk, bool mem_to_mem)
2163{ 2255{
2164 u16 in_width, in_width_max; 2256 u16 in_width, in_width_max;
2165 int decim_x_min = *decim_x; 2257 int decim_x_min = *decim_x;
2166 u16 in_height = DIV_ROUND_UP(height, *decim_y); 2258 u16 in_height = DIV_ROUND_UP(height, *decim_y);
2167 const int maxsinglelinewidth = 2259 const int maxsinglelinewidth =
2168 dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH); 2260 dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH);
2261 unsigned long pclk = dispc_plane_pclk_rate(plane);
2262 const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE);
2263
2264 if (mem_to_mem)
2265 in_width_max = DIV_ROUND_UP(out_width, maxdownscale);
2266 else
2267 in_width_max = dispc_core_clk_rate() /
2268 DIV_ROUND_UP(pclk, out_width);
2169 2269
2170 in_width_max = dispc_core_clk_rate() /
2171 DIV_ROUND_UP(dispc_mgr_pclk_rate(channel), out_width);
2172 *decim_x = DIV_ROUND_UP(width, in_width_max); 2270 *decim_x = DIV_ROUND_UP(width, in_width_max);
2173 2271
2174 *decim_x = *decim_x > decim_x_min ? *decim_x : decim_x_min; 2272 *decim_x = *decim_x > decim_x_min ? *decim_x : decim_x_min;
@@ -2185,20 +2283,19 @@ static int dispc_ovl_calc_scaling_44xx(enum omap_channel channel,
2185 return -EINVAL; 2283 return -EINVAL;
2186 } 2284 }
2187 2285
2188 *core_clk = dispc.feat->calc_core_clk(channel, in_width, in_height, 2286 *core_clk = dispc.feat->calc_core_clk(plane, in_width, in_height,
2189 out_width, out_height); 2287 out_width, out_height, mem_to_mem);
2190 return 0; 2288 return 0;
2191} 2289}
2192 2290
2193static int dispc_ovl_calc_scaling(enum omap_plane plane, 2291static int dispc_ovl_calc_scaling(enum omap_plane plane,
2194 enum omap_channel channel, 2292 enum omap_overlay_caps caps,
2195 const struct omap_video_timings *mgr_timings, 2293 const struct omap_video_timings *mgr_timings,
2196 u16 width, u16 height, u16 out_width, u16 out_height, 2294 u16 width, u16 height, u16 out_width, u16 out_height,
2197 enum omap_color_mode color_mode, bool *five_taps, 2295 enum omap_color_mode color_mode, bool *five_taps,
2198 int *x_predecim, int *y_predecim, u16 pos_x, 2296 int *x_predecim, int *y_predecim, u16 pos_x,
2199 enum omap_dss_rotation_type rotation_type) 2297 enum omap_dss_rotation_type rotation_type, bool mem_to_mem)
2200{ 2298{
2201 struct omap_overlay *ovl = omap_dss_get_overlay(plane);
2202 const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE); 2299 const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE);
2203 const int max_decim_limit = 16; 2300 const int max_decim_limit = 16;
2204 unsigned long core_clk = 0; 2301 unsigned long core_clk = 0;
@@ -2207,7 +2304,7 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane,
2207 if (width == out_width && height == out_height) 2304 if (width == out_width && height == out_height)
2208 return 0; 2305 return 0;
2209 2306
2210 if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) 2307 if ((caps & OMAP_DSS_OVL_CAP_SCALE) == 0)
2211 return -EINVAL; 2308 return -EINVAL;
2212 2309
2213 *x_predecim = max_decim_limit; 2310 *x_predecim = max_decim_limit;
@@ -2233,9 +2330,10 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane,
2233 if (decim_y > *y_predecim || out_height > height * 8) 2330 if (decim_y > *y_predecim || out_height > height * 8)
2234 return -EINVAL; 2331 return -EINVAL;
2235 2332
2236 ret = dispc.feat->calc_scaling(channel, mgr_timings, width, height, 2333 ret = dispc.feat->calc_scaling(plane, mgr_timings, width, height,
2237 out_width, out_height, color_mode, five_taps, x_predecim, 2334 out_width, out_height, color_mode, five_taps,
2238 y_predecim, &decim_x, &decim_y, pos_x, &core_clk); 2335 x_predecim, y_predecim, &decim_x, &decim_y, pos_x, &core_clk,
2336 mem_to_mem);
2239 if (ret) 2337 if (ret)
2240 return ret; 2338 return ret;
2241 2339
@@ -2255,70 +2353,64 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane,
2255 return 0; 2353 return 0;
2256} 2354}
2257 2355
2258int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi, 2356static int dispc_ovl_setup_common(enum omap_plane plane,
2259 bool replication, const struct omap_video_timings *mgr_timings) 2357 enum omap_overlay_caps caps, u32 paddr, u32 p_uv_addr,
2358 u16 screen_width, int pos_x, int pos_y, u16 width, u16 height,
2359 u16 out_width, u16 out_height, enum omap_color_mode color_mode,
2360 u8 rotation, bool mirror, u8 zorder, u8 pre_mult_alpha,
2361 u8 global_alpha, enum omap_dss_rotation_type rotation_type,
2362 bool replication, const struct omap_video_timings *mgr_timings,
2363 bool mem_to_mem)
2260{ 2364{
2261 struct omap_overlay *ovl = omap_dss_get_overlay(plane);
2262 bool five_taps = true; 2365 bool five_taps = true;
2263 bool fieldmode = 0; 2366 bool fieldmode = 0;
2264 int r, cconv = 0; 2367 int r, cconv = 0;
2265 unsigned offset0, offset1; 2368 unsigned offset0, offset1;
2266 s32 row_inc; 2369 s32 row_inc;
2267 s32 pix_inc; 2370 s32 pix_inc;
2268 u16 frame_height = oi->height; 2371 u16 frame_height = height;
2269 unsigned int field_offset = 0; 2372 unsigned int field_offset = 0;
2270 u16 in_height = oi->height; 2373 u16 in_height = height;
2271 u16 in_width = oi->width; 2374 u16 in_width = width;
2272 u16 out_width, out_height;
2273 enum omap_channel channel;
2274 int x_predecim = 1, y_predecim = 1; 2375 int x_predecim = 1, y_predecim = 1;
2275 bool ilace = mgr_timings->interlace; 2376 bool ilace = mgr_timings->interlace;
2276 2377
2277 channel = dispc_ovl_get_channel_out(plane); 2378 if (paddr == 0)
2278
2279 DSSDBG("dispc_ovl_setup %d, pa %x, pa_uv %x, sw %d, %d,%d, %dx%d -> "
2280 "%dx%d, cmode %x, rot %d, mir %d, ilace %d chan %d repl %d\n",
2281 plane, oi->paddr, oi->p_uv_addr,
2282 oi->screen_width, oi->pos_x, oi->pos_y, oi->width, oi->height,
2283 oi->out_width, oi->out_height, oi->color_mode, oi->rotation,
2284 oi->mirror, ilace, channel, replication);
2285
2286 if (oi->paddr == 0)
2287 return -EINVAL; 2379 return -EINVAL;
2288 2380
2289 out_width = oi->out_width == 0 ? oi->width : oi->out_width; 2381 out_width = out_width == 0 ? width : out_width;
2290 out_height = oi->out_height == 0 ? oi->height : oi->out_height; 2382 out_height = out_height == 0 ? height : out_height;
2291 2383
2292 if (ilace && oi->height == out_height) 2384 if (ilace && height == out_height)
2293 fieldmode = 1; 2385 fieldmode = 1;
2294 2386
2295 if (ilace) { 2387 if (ilace) {
2296 if (fieldmode) 2388 if (fieldmode)
2297 in_height /= 2; 2389 in_height /= 2;
2298 oi->pos_y /= 2; 2390 pos_y /= 2;
2299 out_height /= 2; 2391 out_height /= 2;
2300 2392
2301 DSSDBG("adjusting for ilace: height %d, pos_y %d, " 2393 DSSDBG("adjusting for ilace: height %d, pos_y %d, "
2302 "out_height %d\n", 2394 "out_height %d\n", in_height, pos_y,
2303 in_height, oi->pos_y, out_height); 2395 out_height);
2304 } 2396 }
2305 2397
2306 if (!dss_feat_color_mode_supported(plane, oi->color_mode)) 2398 if (!dss_feat_color_mode_supported(plane, color_mode))
2307 return -EINVAL; 2399 return -EINVAL;
2308 2400
2309 r = dispc_ovl_calc_scaling(plane, channel, mgr_timings, in_width, 2401 r = dispc_ovl_calc_scaling(plane, caps, mgr_timings, in_width,
2310 in_height, out_width, out_height, oi->color_mode, 2402 in_height, out_width, out_height, color_mode,
2311 &five_taps, &x_predecim, &y_predecim, oi->pos_x, 2403 &five_taps, &x_predecim, &y_predecim, pos_x,
2312 oi->rotation_type); 2404 rotation_type, mem_to_mem);
2313 if (r) 2405 if (r)
2314 return r; 2406 return r;
2315 2407
2316 in_width = DIV_ROUND_UP(in_width, x_predecim); 2408 in_width = DIV_ROUND_UP(in_width, x_predecim);
2317 in_height = DIV_ROUND_UP(in_height, y_predecim); 2409 in_height = DIV_ROUND_UP(in_height, y_predecim);
2318 2410
2319 if (oi->color_mode == OMAP_DSS_COLOR_YUV2 || 2411 if (color_mode == OMAP_DSS_COLOR_YUV2 ||
2320 oi->color_mode == OMAP_DSS_COLOR_UYVY || 2412 color_mode == OMAP_DSS_COLOR_UYVY ||
2321 oi->color_mode == OMAP_DSS_COLOR_NV12) 2413 color_mode == OMAP_DSS_COLOR_NV12)
2322 cconv = 1; 2414 cconv = 1;
2323 2415
2324 if (ilace && !fieldmode) { 2416 if (ilace && !fieldmode) {
@@ -2344,70 +2436,144 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
2344 row_inc = 0; 2436 row_inc = 0;
2345 pix_inc = 0; 2437 pix_inc = 0;
2346 2438
2347 if (oi->rotation_type == OMAP_DSS_ROT_TILER) 2439 if (rotation_type == OMAP_DSS_ROT_TILER)
2348 calc_tiler_rotation_offset(oi->screen_width, in_width, 2440 calc_tiler_rotation_offset(screen_width, in_width,
2349 oi->color_mode, fieldmode, field_offset, 2441 color_mode, fieldmode, field_offset,
2350 &offset0, &offset1, &row_inc, &pix_inc, 2442 &offset0, &offset1, &row_inc, &pix_inc,
2351 x_predecim, y_predecim); 2443 x_predecim, y_predecim);
2352 else if (oi->rotation_type == OMAP_DSS_ROT_DMA) 2444 else if (rotation_type == OMAP_DSS_ROT_DMA)
2353 calc_dma_rotation_offset(oi->rotation, oi->mirror, 2445 calc_dma_rotation_offset(rotation, mirror,
2354 oi->screen_width, in_width, frame_height, 2446 screen_width, in_width, frame_height,
2355 oi->color_mode, fieldmode, field_offset, 2447 color_mode, fieldmode, field_offset,
2356 &offset0, &offset1, &row_inc, &pix_inc, 2448 &offset0, &offset1, &row_inc, &pix_inc,
2357 x_predecim, y_predecim); 2449 x_predecim, y_predecim);
2358 else 2450 else
2359 calc_vrfb_rotation_offset(oi->rotation, oi->mirror, 2451 calc_vrfb_rotation_offset(rotation, mirror,
2360 oi->screen_width, in_width, frame_height, 2452 screen_width, in_width, frame_height,
2361 oi->color_mode, fieldmode, field_offset, 2453 color_mode, fieldmode, field_offset,
2362 &offset0, &offset1, &row_inc, &pix_inc, 2454 &offset0, &offset1, &row_inc, &pix_inc,
2363 x_predecim, y_predecim); 2455 x_predecim, y_predecim);
2364 2456
2365 DSSDBG("offset0 %u, offset1 %u, row_inc %d, pix_inc %d\n", 2457 DSSDBG("offset0 %u, offset1 %u, row_inc %d, pix_inc %d\n",
2366 offset0, offset1, row_inc, pix_inc); 2458 offset0, offset1, row_inc, pix_inc);
2367 2459
2368 dispc_ovl_set_color_mode(plane, oi->color_mode); 2460 dispc_ovl_set_color_mode(plane, color_mode);
2369 2461
2370 dispc_ovl_configure_burst_type(plane, oi->rotation_type); 2462 dispc_ovl_configure_burst_type(plane, rotation_type);
2371 2463
2372 dispc_ovl_set_ba0(plane, oi->paddr + offset0); 2464 dispc_ovl_set_ba0(plane, paddr + offset0);
2373 dispc_ovl_set_ba1(plane, oi->paddr + offset1); 2465 dispc_ovl_set_ba1(plane, paddr + offset1);
2374 2466
2375 if (OMAP_DSS_COLOR_NV12 == oi->color_mode) { 2467 if (OMAP_DSS_COLOR_NV12 == color_mode) {
2376 dispc_ovl_set_ba0_uv(plane, oi->p_uv_addr + offset0); 2468 dispc_ovl_set_ba0_uv(plane, p_uv_addr + offset0);
2377 dispc_ovl_set_ba1_uv(plane, oi->p_uv_addr + offset1); 2469 dispc_ovl_set_ba1_uv(plane, p_uv_addr + offset1);
2378 } 2470 }
2379 2471
2380
2381 dispc_ovl_set_row_inc(plane, row_inc); 2472 dispc_ovl_set_row_inc(plane, row_inc);
2382 dispc_ovl_set_pix_inc(plane, pix_inc); 2473 dispc_ovl_set_pix_inc(plane, pix_inc);
2383 2474
2384 DSSDBG("%d,%d %dx%d -> %dx%d\n", oi->pos_x, oi->pos_y, in_width, 2475 DSSDBG("%d,%d %dx%d -> %dx%d\n", pos_x, pos_y, in_width,
2385 in_height, out_width, out_height); 2476 in_height, out_width, out_height);
2386 2477
2387 dispc_ovl_set_pos(plane, oi->pos_x, oi->pos_y); 2478 dispc_ovl_set_pos(plane, caps, pos_x, pos_y);
2388 2479
2389 dispc_ovl_set_pic_size(plane, in_width, in_height); 2480 dispc_ovl_set_input_size(plane, in_width, in_height);
2390 2481
2391 if (ovl->caps & OMAP_DSS_OVL_CAP_SCALE) { 2482 if (caps & OMAP_DSS_OVL_CAP_SCALE) {
2392 dispc_ovl_set_scaling(plane, in_width, in_height, out_width, 2483 dispc_ovl_set_scaling(plane, in_width, in_height, out_width,
2393 out_height, ilace, five_taps, fieldmode, 2484 out_height, ilace, five_taps, fieldmode,
2394 oi->color_mode, oi->rotation); 2485 color_mode, rotation);
2395 dispc_ovl_set_vid_size(plane, out_width, out_height); 2486 dispc_ovl_set_output_size(plane, out_width, out_height);
2396 dispc_ovl_set_vid_color_conv(plane, cconv); 2487 dispc_ovl_set_vid_color_conv(plane, cconv);
2397 } 2488 }
2398 2489
2399 dispc_ovl_set_rotation_attrs(plane, oi->rotation, oi->mirror, 2490 dispc_ovl_set_rotation_attrs(plane, rotation, mirror, color_mode);
2400 oi->color_mode);
2401 2491
2402 dispc_ovl_set_zorder(plane, oi->zorder); 2492 dispc_ovl_set_zorder(plane, caps, zorder);
2403 dispc_ovl_set_pre_mult_alpha(plane, oi->pre_mult_alpha); 2493 dispc_ovl_set_pre_mult_alpha(plane, caps, pre_mult_alpha);
2404 dispc_ovl_setup_global_alpha(plane, oi->global_alpha); 2494 dispc_ovl_setup_global_alpha(plane, caps, global_alpha);
2405 2495
2406 dispc_ovl_enable_replication(plane, replication); 2496 dispc_ovl_enable_replication(plane, caps, replication);
2407 2497
2408 return 0; 2498 return 0;
2409} 2499}
2410 2500
2501int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi,
2502 bool replication, const struct omap_video_timings *mgr_timings,
2503 bool mem_to_mem)
2504{
2505 int r;
2506 struct omap_overlay *ovl = omap_dss_get_overlay(plane);
2507 enum omap_channel channel;
2508
2509 channel = dispc_ovl_get_channel_out(plane);
2510
2511 DSSDBG("dispc_ovl_setup %d, pa %x, pa_uv %x, sw %d, %d,%d, %dx%d -> "
2512 "%dx%d, cmode %x, rot %d, mir %d, chan %d repl %d\n",
2513 plane, oi->paddr, oi->p_uv_addr, oi->screen_width, oi->pos_x,
2514 oi->pos_y, oi->width, oi->height, oi->out_width, oi->out_height,
2515 oi->color_mode, oi->rotation, oi->mirror, channel, replication);
2516
2517 r = dispc_ovl_setup_common(plane, ovl->caps, oi->paddr, oi->p_uv_addr,
2518 oi->screen_width, oi->pos_x, oi->pos_y, oi->width, oi->height,
2519 oi->out_width, oi->out_height, oi->color_mode, oi->rotation,
2520 oi->mirror, oi->zorder, oi->pre_mult_alpha, oi->global_alpha,
2521 oi->rotation_type, replication, mgr_timings, mem_to_mem);
2522
2523 return r;
2524}
2525
2526int dispc_wb_setup(const struct omap_dss_writeback_info *wi,
2527 bool mem_to_mem, const struct omap_video_timings *mgr_timings)
2528{
2529 int r;
2530 u32 l;
2531 enum omap_plane plane = OMAP_DSS_WB;
2532 const int pos_x = 0, pos_y = 0;
2533 const u8 zorder = 0, global_alpha = 0;
2534 const bool replication = false;
2535 bool truncation;
2536 int in_width = mgr_timings->x_res;
2537 int in_height = mgr_timings->y_res;
2538 enum omap_overlay_caps caps =
2539 OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA;
2540
2541 DSSDBG("dispc_wb_setup, pa %x, pa_uv %x, %d,%d -> %dx%d, cmode %x, "
2542 "rot %d, mir %d\n", wi->paddr, wi->p_uv_addr, in_width,
2543 in_height, wi->width, wi->height, wi->color_mode, wi->rotation,
2544 wi->mirror);
2545
2546 r = dispc_ovl_setup_common(plane, caps, wi->paddr, wi->p_uv_addr,
2547 wi->buf_width, pos_x, pos_y, in_width, in_height, wi->width,
2548 wi->height, wi->color_mode, wi->rotation, wi->mirror, zorder,
2549 wi->pre_mult_alpha, global_alpha, wi->rotation_type,
2550 replication, mgr_timings, mem_to_mem);
2551
2552 switch (wi->color_mode) {
2553 case OMAP_DSS_COLOR_RGB16:
2554 case OMAP_DSS_COLOR_RGB24P:
2555 case OMAP_DSS_COLOR_ARGB16:
2556 case OMAP_DSS_COLOR_RGBA16:
2557 case OMAP_DSS_COLOR_RGB12U:
2558 case OMAP_DSS_COLOR_ARGB16_1555:
2559 case OMAP_DSS_COLOR_XRGB16_1555:
2560 case OMAP_DSS_COLOR_RGBX16:
2561 truncation = true;
2562 break;
2563 default:
2564 truncation = false;
2565 break;
2566 }
2567
2568 /* setup extra DISPC_WB_ATTRIBUTES */
2569 l = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane));
2570 l = FLD_MOD(l, truncation, 10, 10); /* TRUNCATIONENABLE */
2571 l = FLD_MOD(l, mem_to_mem, 19, 19); /* WRITEBACKMODE */
2572 dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), l);
2573
2574 return r;
2575}
2576
2411int dispc_ovl_enable(enum omap_plane plane, bool enable) 2577int dispc_ovl_enable(enum omap_plane plane, bool enable)
2412{ 2578{
2413 DSSDBG("dispc_enable_plane %d, %d\n", plane, enable); 2579 DSSDBG("dispc_enable_plane %d, %d\n", plane, enable);
@@ -2560,6 +2726,47 @@ void dispc_mgr_enable(enum omap_channel channel, bool enable)
2560 BUG(); 2726 BUG();
2561} 2727}
2562 2728
2729void dispc_wb_enable(bool enable)
2730{
2731 enum omap_plane plane = OMAP_DSS_WB;
2732 struct completion frame_done_completion;
2733 bool is_on;
2734 int r;
2735 u32 irq;
2736
2737 is_on = REG_GET(DISPC_OVL_ATTRIBUTES(plane), 0, 0);
2738 irq = DISPC_IRQ_FRAMEDONEWB;
2739
2740 if (!enable && is_on) {
2741 init_completion(&frame_done_completion);
2742
2743 r = omap_dispc_register_isr(dispc_disable_isr,
2744 &frame_done_completion, irq);
2745 if (r)
2746 DSSERR("failed to register FRAMEDONEWB isr\n");
2747 }
2748
2749 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable ? 1 : 0, 0, 0);
2750
2751 if (!enable && is_on) {
2752 if (!wait_for_completion_timeout(&frame_done_completion,
2753 msecs_to_jiffies(100)))
2754 DSSERR("timeout waiting for FRAMEDONEWB\n");
2755
2756 r = omap_dispc_unregister_isr(dispc_disable_isr,
2757 &frame_done_completion, irq);
2758 if (r)
2759 DSSERR("failed to unregister FRAMEDONEWB isr\n");
2760 }
2761}
2762
2763bool dispc_wb_is_enabled(void)
2764{
2765 enum omap_plane plane = OMAP_DSS_WB;
2766
2767 return REG_GET(DISPC_OVL_ATTRIBUTES(plane), 0, 0);
2768}
2769
2563void dispc_lcd_enable_signal_polarity(bool act_high) 2770void dispc_lcd_enable_signal_polarity(bool act_high)
2564{ 2771{
2565 if (!dss_has_feature(FEAT_LCDENABLEPOL)) 2772 if (!dss_has_feature(FEAT_LCDENABLEPOL))
@@ -2963,6 +3170,23 @@ unsigned long dispc_core_clk_rate(void)
2963 return fclk / lcd; 3170 return fclk / lcd;
2964} 3171}
2965 3172
3173static unsigned long dispc_plane_pclk_rate(enum omap_plane plane)
3174{
3175 enum omap_channel channel = dispc_ovl_get_channel_out(plane);
3176
3177 return dispc_mgr_pclk_rate(channel);
3178}
3179
3180static unsigned long dispc_plane_lclk_rate(enum omap_plane plane)
3181{
3182 enum omap_channel channel = dispc_ovl_get_channel_out(plane);
3183
3184 if (dss_mgr_is_lcd(channel))
3185 return dispc_mgr_lclk_rate(channel);
3186 else
3187 return dispc_fclk_rate();
3188
3189}
2966static void dispc_dump_clocks_channel(struct seq_file *s, enum omap_channel channel) 3190static void dispc_dump_clocks_channel(struct seq_file *s, enum omap_channel channel)
2967{ 3191{
2968 int lcd, pcd; 3192 int lcd, pcd;
@@ -3756,7 +3980,7 @@ static void _omap_dispc_initial_config(void)
3756 if (dss_has_feature(FEAT_FUNCGATED)) 3980 if (dss_has_feature(FEAT_FUNCGATED))
3757 REG_FLD_MOD(DISPC_CONFIG, 1, 9, 9); 3981 REG_FLD_MOD(DISPC_CONFIG, 1, 9, 9);
3758 3982
3759 _dispc_setup_color_conv_coef(); 3983 dispc_setup_color_conv_coef();
3760 3984
3761 dispc_set_loadmode(OMAP_DSS_LOAD_FRAME_ONLY); 3985 dispc_set_loadmode(OMAP_DSS_LOAD_FRAME_ONLY);
3762 3986
diff --git a/drivers/video/omap2/dss/dispc.h b/drivers/video/omap2/dss/dispc.h
index 42e56cc7cdbc..222363c6e623 100644
--- a/drivers/video/omap2/dss/dispc.h
+++ b/drivers/video/omap2/dss/dispc.h
@@ -373,6 +373,7 @@ static inline u16 DISPC_BA0_OFFSET(enum omap_plane plane)
373 case OMAP_DSS_VIDEO2: 373 case OMAP_DSS_VIDEO2:
374 return 0x0000; 374 return 0x0000;
375 case OMAP_DSS_VIDEO3: 375 case OMAP_DSS_VIDEO3:
376 case OMAP_DSS_WB:
376 return 0x0008; 377 return 0x0008;
377 default: 378 default:
378 BUG(); 379 BUG();
@@ -388,6 +389,7 @@ static inline u16 DISPC_BA1_OFFSET(enum omap_plane plane)
388 case OMAP_DSS_VIDEO2: 389 case OMAP_DSS_VIDEO2:
389 return 0x0004; 390 return 0x0004;
390 case OMAP_DSS_VIDEO3: 391 case OMAP_DSS_VIDEO3:
392 case OMAP_DSS_WB:
391 return 0x000C; 393 return 0x000C;
392 default: 394 default:
393 BUG(); 395 BUG();
@@ -407,6 +409,8 @@ static inline u16 DISPC_BA0_UV_OFFSET(enum omap_plane plane)
407 return 0x04BC; 409 return 0x04BC;
408 case OMAP_DSS_VIDEO3: 410 case OMAP_DSS_VIDEO3:
409 return 0x0310; 411 return 0x0310;
412 case OMAP_DSS_WB:
413 return 0x0118;
410 default: 414 default:
411 BUG(); 415 BUG();
412 return 0; 416 return 0;
@@ -425,6 +429,8 @@ static inline u16 DISPC_BA1_UV_OFFSET(enum omap_plane plane)
425 return 0x04C0; 429 return 0x04C0;
426 case OMAP_DSS_VIDEO3: 430 case OMAP_DSS_VIDEO3:
427 return 0x0314; 431 return 0x0314;
432 case OMAP_DSS_WB:
433 return 0x011C;
428 default: 434 default:
429 BUG(); 435 BUG();
430 return 0; 436 return 0;
@@ -454,6 +460,7 @@ static inline u16 DISPC_SIZE_OFFSET(enum omap_plane plane)
454 case OMAP_DSS_VIDEO2: 460 case OMAP_DSS_VIDEO2:
455 return 0x000C; 461 return 0x000C;
456 case OMAP_DSS_VIDEO3: 462 case OMAP_DSS_VIDEO3:
463 case OMAP_DSS_WB:
457 return 0x00A8; 464 return 0x00A8;
458 default: 465 default:
459 BUG(); 466 BUG();
@@ -470,6 +477,7 @@ static inline u16 DISPC_ATTR_OFFSET(enum omap_plane plane)
470 case OMAP_DSS_VIDEO2: 477 case OMAP_DSS_VIDEO2:
471 return 0x0010; 478 return 0x0010;
472 case OMAP_DSS_VIDEO3: 479 case OMAP_DSS_VIDEO3:
480 case OMAP_DSS_WB:
473 return 0x0070; 481 return 0x0070;
474 default: 482 default:
475 BUG(); 483 BUG();
@@ -489,6 +497,8 @@ static inline u16 DISPC_ATTR2_OFFSET(enum omap_plane plane)
489 return 0x04DC; 497 return 0x04DC;
490 case OMAP_DSS_VIDEO3: 498 case OMAP_DSS_VIDEO3:
491 return 0x032C; 499 return 0x032C;
500 case OMAP_DSS_WB:
501 return 0x0310;
492 default: 502 default:
493 BUG(); 503 BUG();
494 return 0; 504 return 0;
@@ -504,6 +514,7 @@ static inline u16 DISPC_FIFO_THRESH_OFFSET(enum omap_plane plane)
504 case OMAP_DSS_VIDEO2: 514 case OMAP_DSS_VIDEO2:
505 return 0x0014; 515 return 0x0014;
506 case OMAP_DSS_VIDEO3: 516 case OMAP_DSS_VIDEO3:
517 case OMAP_DSS_WB:
507 return 0x008C; 518 return 0x008C;
508 default: 519 default:
509 BUG(); 520 BUG();
@@ -537,6 +548,7 @@ static inline u16 DISPC_ROW_INC_OFFSET(enum omap_plane plane)
537 case OMAP_DSS_VIDEO2: 548 case OMAP_DSS_VIDEO2:
538 return 0x001C; 549 return 0x001C;
539 case OMAP_DSS_VIDEO3: 550 case OMAP_DSS_VIDEO3:
551 case OMAP_DSS_WB:
540 return 0x00A4; 552 return 0x00A4;
541 default: 553 default:
542 BUG(); 554 BUG();
@@ -553,6 +565,7 @@ static inline u16 DISPC_PIX_INC_OFFSET(enum omap_plane plane)
553 case OMAP_DSS_VIDEO2: 565 case OMAP_DSS_VIDEO2:
554 return 0x0020; 566 return 0x0020;
555 case OMAP_DSS_VIDEO3: 567 case OMAP_DSS_VIDEO3:
568 case OMAP_DSS_WB:
556 return 0x0098; 569 return 0x0098;
557 default: 570 default:
558 BUG(); 571 BUG();
@@ -602,6 +615,7 @@ static inline u16 DISPC_FIR_OFFSET(enum omap_plane plane)
602 case OMAP_DSS_VIDEO2: 615 case OMAP_DSS_VIDEO2:
603 return 0x0024; 616 return 0x0024;
604 case OMAP_DSS_VIDEO3: 617 case OMAP_DSS_VIDEO3:
618 case OMAP_DSS_WB:
605 return 0x0090; 619 return 0x0090;
606 default: 620 default:
607 BUG(); 621 BUG();
@@ -621,6 +635,8 @@ static inline u16 DISPC_FIR2_OFFSET(enum omap_plane plane)
621 return 0x055C; 635 return 0x055C;
622 case OMAP_DSS_VIDEO3: 636 case OMAP_DSS_VIDEO3:
623 return 0x0424; 637 return 0x0424;
638 case OMAP_DSS_WB:
639 return 0x290;
624 default: 640 default:
625 BUG(); 641 BUG();
626 return 0; 642 return 0;
@@ -637,6 +653,7 @@ static inline u16 DISPC_PIC_SIZE_OFFSET(enum omap_plane plane)
637 case OMAP_DSS_VIDEO2: 653 case OMAP_DSS_VIDEO2:
638 return 0x0028; 654 return 0x0028;
639 case OMAP_DSS_VIDEO3: 655 case OMAP_DSS_VIDEO3:
656 case OMAP_DSS_WB:
640 return 0x0094; 657 return 0x0094;
641 default: 658 default:
642 BUG(); 659 BUG();
@@ -655,6 +672,7 @@ static inline u16 DISPC_ACCU0_OFFSET(enum omap_plane plane)
655 case OMAP_DSS_VIDEO2: 672 case OMAP_DSS_VIDEO2:
656 return 0x002C; 673 return 0x002C;
657 case OMAP_DSS_VIDEO3: 674 case OMAP_DSS_VIDEO3:
675 case OMAP_DSS_WB:
658 return 0x0000; 676 return 0x0000;
659 default: 677 default:
660 BUG(); 678 BUG();
@@ -674,6 +692,8 @@ static inline u16 DISPC_ACCU2_0_OFFSET(enum omap_plane plane)
674 return 0x0560; 692 return 0x0560;
675 case OMAP_DSS_VIDEO3: 693 case OMAP_DSS_VIDEO3:
676 return 0x0428; 694 return 0x0428;
695 case OMAP_DSS_WB:
696 return 0x0294;
677 default: 697 default:
678 BUG(); 698 BUG();
679 return 0; 699 return 0;
@@ -690,6 +710,7 @@ static inline u16 DISPC_ACCU1_OFFSET(enum omap_plane plane)
690 case OMAP_DSS_VIDEO2: 710 case OMAP_DSS_VIDEO2:
691 return 0x0030; 711 return 0x0030;
692 case OMAP_DSS_VIDEO3: 712 case OMAP_DSS_VIDEO3:
713 case OMAP_DSS_WB:
693 return 0x0004; 714 return 0x0004;
694 default: 715 default:
695 BUG(); 716 BUG();
@@ -709,6 +730,8 @@ static inline u16 DISPC_ACCU2_1_OFFSET(enum omap_plane plane)
709 return 0x0564; 730 return 0x0564;
710 case OMAP_DSS_VIDEO3: 731 case OMAP_DSS_VIDEO3:
711 return 0x042C; 732 return 0x042C;
733 case OMAP_DSS_WB:
734 return 0x0298;
712 default: 735 default:
713 BUG(); 736 BUG();
714 return 0; 737 return 0;
@@ -726,6 +749,7 @@ static inline u16 DISPC_FIR_COEF_H_OFFSET(enum omap_plane plane, u16 i)
726 case OMAP_DSS_VIDEO2: 749 case OMAP_DSS_VIDEO2:
727 return 0x0034 + i * 0x8; 750 return 0x0034 + i * 0x8;
728 case OMAP_DSS_VIDEO3: 751 case OMAP_DSS_VIDEO3:
752 case OMAP_DSS_WB:
729 return 0x0010 + i * 0x8; 753 return 0x0010 + i * 0x8;
730 default: 754 default:
731 BUG(); 755 BUG();
@@ -746,6 +770,8 @@ static inline u16 DISPC_FIR_COEF_H2_OFFSET(enum omap_plane plane, u16 i)
746 return 0x0568 + i * 0x8; 770 return 0x0568 + i * 0x8;
747 case OMAP_DSS_VIDEO3: 771 case OMAP_DSS_VIDEO3:
748 return 0x0430 + i * 0x8; 772 return 0x0430 + i * 0x8;
773 case OMAP_DSS_WB:
774 return 0x02A0 + i * 0x8;
749 default: 775 default:
750 BUG(); 776 BUG();
751 return 0; 777 return 0;
@@ -763,6 +789,7 @@ static inline u16 DISPC_FIR_COEF_HV_OFFSET(enum omap_plane plane, u16 i)
763 case OMAP_DSS_VIDEO2: 789 case OMAP_DSS_VIDEO2:
764 return 0x0038 + i * 0x8; 790 return 0x0038 + i * 0x8;
765 case OMAP_DSS_VIDEO3: 791 case OMAP_DSS_VIDEO3:
792 case OMAP_DSS_WB:
766 return 0x0014 + i * 0x8; 793 return 0x0014 + i * 0x8;
767 default: 794 default:
768 BUG(); 795 BUG();
@@ -783,6 +810,8 @@ static inline u16 DISPC_FIR_COEF_HV2_OFFSET(enum omap_plane plane, u16 i)
783 return 0x056C + i * 0x8; 810 return 0x056C + i * 0x8;
784 case OMAP_DSS_VIDEO3: 811 case OMAP_DSS_VIDEO3:
785 return 0x0434 + i * 0x8; 812 return 0x0434 + i * 0x8;
813 case OMAP_DSS_WB:
814 return 0x02A4 + i * 0x8;
786 default: 815 default:
787 BUG(); 816 BUG();
788 return 0; 817 return 0;
@@ -799,6 +828,7 @@ static inline u16 DISPC_CONV_COEF_OFFSET(enum omap_plane plane, u16 i)
799 case OMAP_DSS_VIDEO1: 828 case OMAP_DSS_VIDEO1:
800 case OMAP_DSS_VIDEO2: 829 case OMAP_DSS_VIDEO2:
801 case OMAP_DSS_VIDEO3: 830 case OMAP_DSS_VIDEO3:
831 case OMAP_DSS_WB:
802 return 0x0074 + i * 0x4; 832 return 0x0074 + i * 0x4;
803 default: 833 default:
804 BUG(); 834 BUG();
@@ -818,6 +848,7 @@ static inline u16 DISPC_FIR_COEF_V_OFFSET(enum omap_plane plane, u16 i)
818 case OMAP_DSS_VIDEO2: 848 case OMAP_DSS_VIDEO2:
819 return 0x00B4 + i * 0x4; 849 return 0x00B4 + i * 0x4;
820 case OMAP_DSS_VIDEO3: 850 case OMAP_DSS_VIDEO3:
851 case OMAP_DSS_WB:
821 return 0x0050 + i * 0x4; 852 return 0x0050 + i * 0x4;
822 default: 853 default:
823 BUG(); 854 BUG();
@@ -838,6 +869,8 @@ static inline u16 DISPC_FIR_COEF_V2_OFFSET(enum omap_plane plane, u16 i)
838 return 0x05A8 + i * 0x4; 869 return 0x05A8 + i * 0x4;
839 case OMAP_DSS_VIDEO3: 870 case OMAP_DSS_VIDEO3:
840 return 0x0470 + i * 0x4; 871 return 0x0470 + i * 0x4;
872 case OMAP_DSS_WB:
873 return 0x02E0 + i * 0x4;
841 default: 874 default:
842 BUG(); 875 BUG();
843 return 0; 876 return 0;
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index a14528bcfeab..6728892f9dad 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -113,6 +113,17 @@ enum dss_dsi_content_type {
113 DSS_DSI_CONTENT_GENERIC, 113 DSS_DSI_CONTENT_GENERIC,
114}; 114};
115 115
116enum dss_writeback_channel {
117 DSS_WB_LCD1_MGR = 0,
118 DSS_WB_LCD2_MGR = 1,
119 DSS_WB_TV_MGR = 2,
120 DSS_WB_OVL0 = 3,
121 DSS_WB_OVL1 = 4,
122 DSS_WB_OVL2 = 5,
123 DSS_WB_OVL3 = 6,
124 DSS_WB_LCD3_MGR = 7,
125};
126
116struct dss_clock_info { 127struct dss_clock_info {
117 /* rates that we get with dividers below */ 128 /* rates that we get with dividers below */
118 unsigned long fck; 129 unsigned long fck;
@@ -444,8 +455,9 @@ void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high);
444void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane, 455void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane,
445 u32 *fifo_low, u32 *fifo_high, bool use_fifomerge, 456 u32 *fifo_low, u32 *fifo_high, bool use_fifomerge,
446 bool manual_update); 457 bool manual_update);
447int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi, 458int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi,
448 bool replication, const struct omap_video_timings *mgr_timings); 459 bool replication, const struct omap_video_timings *mgr_timings,
460 bool mem_to_mem);
449int dispc_ovl_enable(enum omap_plane plane, bool enable); 461int dispc_ovl_enable(enum omap_plane plane, bool enable);
450void dispc_ovl_set_channel_out(enum omap_plane plane, 462void dispc_ovl_set_channel_out(enum omap_plane plane,
451 enum omap_channel channel); 463 enum omap_channel channel);
@@ -474,6 +486,15 @@ int dispc_mgr_get_clock_div(enum omap_channel channel,
474void dispc_mgr_setup(enum omap_channel channel, 486void dispc_mgr_setup(enum omap_channel channel,
475 struct omap_overlay_manager_info *info); 487 struct omap_overlay_manager_info *info);
476 488
489u32 dispc_wb_get_framedone_irq(void);
490bool dispc_wb_go_busy(void);
491void dispc_wb_go(void);
492void dispc_wb_enable(bool enable);
493bool dispc_wb_is_enabled(void);
494void dispc_wb_set_channel_in(enum dss_writeback_channel channel);
495int dispc_wb_setup(const struct omap_dss_writeback_info *wi,
496 bool mem_to_mem, const struct omap_video_timings *timings);
497
477/* VENC */ 498/* VENC */
478#ifdef CONFIG_OMAP2_DSS_VENC 499#ifdef CONFIG_OMAP2_DSS_VENC
479int venc_init_platform_driver(void) __init; 500int venc_init_platform_driver(void) __init;
diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c
index bfe7fc7b8593..acbc1e1efba3 100644
--- a/drivers/video/omap2/dss/dss_features.c
+++ b/drivers/video/omap2/dss/dss_features.c
@@ -46,6 +46,7 @@ struct omap_dss_features {
46 46
47 const int num_mgrs; 47 const int num_mgrs;
48 const int num_ovls; 48 const int num_ovls;
49 const int num_wbs;
49 const enum omap_display_type *supported_displays; 50 const enum omap_display_type *supported_displays;
50 const enum omap_dss_output_id *supported_outputs; 51 const enum omap_dss_output_id *supported_outputs;
51 const enum omap_color_mode *supported_color_modes; 52 const enum omap_color_mode *supported_color_modes;
@@ -310,58 +311,80 @@ static const enum omap_color_mode omap4_dss_supported_color_modes[] = {
310 OMAP_DSS_COLOR_ARGB16 | OMAP_DSS_COLOR_XRGB16_1555 | 311 OMAP_DSS_COLOR_ARGB16 | OMAP_DSS_COLOR_XRGB16_1555 |
311 OMAP_DSS_COLOR_ARGB32 | OMAP_DSS_COLOR_RGBX16 | 312 OMAP_DSS_COLOR_ARGB32 | OMAP_DSS_COLOR_RGBX16 |
312 OMAP_DSS_COLOR_RGBX32, 313 OMAP_DSS_COLOR_RGBX32,
314
315 /* OMAP_DSS_WB */
316 OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB12U |
317 OMAP_DSS_COLOR_YUV2 | OMAP_DSS_COLOR_ARGB16_1555 |
318 OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_NV12 |
319 OMAP_DSS_COLOR_RGBA16 | OMAP_DSS_COLOR_RGB24U |
320 OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_UYVY |
321 OMAP_DSS_COLOR_ARGB16 | OMAP_DSS_COLOR_XRGB16_1555 |
322 OMAP_DSS_COLOR_ARGB32 | OMAP_DSS_COLOR_RGBX16 |
323 OMAP_DSS_COLOR_RGBX32,
313}; 324};
314 325
315static const enum omap_overlay_caps omap2_dss_overlay_caps[] = { 326static const enum omap_overlay_caps omap2_dss_overlay_caps[] = {
316 /* OMAP_DSS_GFX */ 327 /* OMAP_DSS_GFX */
317 0, 328 OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION,
318 329
319 /* OMAP_DSS_VIDEO1 */ 330 /* OMAP_DSS_VIDEO1 */
320 OMAP_DSS_OVL_CAP_SCALE, 331 OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_POS |
332 OMAP_DSS_OVL_CAP_REPLICATION,
321 333
322 /* OMAP_DSS_VIDEO2 */ 334 /* OMAP_DSS_VIDEO2 */
323 OMAP_DSS_OVL_CAP_SCALE, 335 OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_POS |
336 OMAP_DSS_OVL_CAP_REPLICATION,
324}; 337};
325 338
326static const enum omap_overlay_caps omap3430_dss_overlay_caps[] = { 339static const enum omap_overlay_caps omap3430_dss_overlay_caps[] = {
327 /* OMAP_DSS_GFX */ 340 /* OMAP_DSS_GFX */
328 OMAP_DSS_OVL_CAP_GLOBAL_ALPHA, 341 OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | OMAP_DSS_OVL_CAP_POS |
342 OMAP_DSS_OVL_CAP_REPLICATION,
329 343
330 /* OMAP_DSS_VIDEO1 */ 344 /* OMAP_DSS_VIDEO1 */
331 OMAP_DSS_OVL_CAP_SCALE, 345 OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_POS |
346 OMAP_DSS_OVL_CAP_REPLICATION,
332 347
333 /* OMAP_DSS_VIDEO2 */ 348 /* OMAP_DSS_VIDEO2 */
334 OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA, 349 OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA |
350 OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION,
335}; 351};
336 352
337static const enum omap_overlay_caps omap3630_dss_overlay_caps[] = { 353static const enum omap_overlay_caps omap3630_dss_overlay_caps[] = {
338 /* OMAP_DSS_GFX */ 354 /* OMAP_DSS_GFX */
339 OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA, 355 OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA |
356 OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION,
340 357
341 /* OMAP_DSS_VIDEO1 */ 358 /* OMAP_DSS_VIDEO1 */
342 OMAP_DSS_OVL_CAP_SCALE, 359 OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_POS |
360 OMAP_DSS_OVL_CAP_REPLICATION,
343 361
344 /* OMAP_DSS_VIDEO2 */ 362 /* OMAP_DSS_VIDEO2 */
345 OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | 363 OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA |
346 OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA, 364 OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_POS |
365 OMAP_DSS_OVL_CAP_REPLICATION,
347}; 366};
348 367
349static const enum omap_overlay_caps omap4_dss_overlay_caps[] = { 368static const enum omap_overlay_caps omap4_dss_overlay_caps[] = {
350 /* OMAP_DSS_GFX */ 369 /* OMAP_DSS_GFX */
351 OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | 370 OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA |
352 OMAP_DSS_OVL_CAP_ZORDER, 371 OMAP_DSS_OVL_CAP_ZORDER | OMAP_DSS_OVL_CAP_POS |
372 OMAP_DSS_OVL_CAP_REPLICATION,
353 373
354 /* OMAP_DSS_VIDEO1 */ 374 /* OMAP_DSS_VIDEO1 */
355 OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | 375 OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA |
356 OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_ZORDER, 376 OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_ZORDER |
377 OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION,
357 378
358 /* OMAP_DSS_VIDEO2 */ 379 /* OMAP_DSS_VIDEO2 */
359 OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | 380 OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA |
360 OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_ZORDER, 381 OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_ZORDER |
382 OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION,
361 383
362 /* OMAP_DSS_VIDEO3 */ 384 /* OMAP_DSS_VIDEO3 */
363 OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | 385 OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA |
364 OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_ZORDER, 386 OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_ZORDER |
387 OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION,
365}; 388};
366 389
367static const char * const omap2_dss_clk_source_names[] = { 390static const char * const omap2_dss_clk_source_names[] = {
@@ -698,6 +721,7 @@ static const struct omap_dss_features omap4430_es1_0_dss_features = {
698 721
699 .num_mgrs = 3, 722 .num_mgrs = 3,
700 .num_ovls = 4, 723 .num_ovls = 4,
724 .num_wbs = 1,
701 .supported_displays = omap4_dss_supported_displays, 725 .supported_displays = omap4_dss_supported_displays,
702 .supported_outputs = omap4_dss_supported_outputs, 726 .supported_outputs = omap4_dss_supported_outputs,
703 .supported_color_modes = omap4_dss_supported_color_modes, 727 .supported_color_modes = omap4_dss_supported_color_modes,
@@ -719,6 +743,7 @@ static const struct omap_dss_features omap4430_es2_0_1_2_dss_features = {
719 743
720 .num_mgrs = 3, 744 .num_mgrs = 3,
721 .num_ovls = 4, 745 .num_ovls = 4,
746 .num_wbs = 1,
722 .supported_displays = omap4_dss_supported_displays, 747 .supported_displays = omap4_dss_supported_displays,
723 .supported_outputs = omap4_dss_supported_outputs, 748 .supported_outputs = omap4_dss_supported_outputs,
724 .supported_color_modes = omap4_dss_supported_color_modes, 749 .supported_color_modes = omap4_dss_supported_color_modes,
@@ -740,6 +765,7 @@ static const struct omap_dss_features omap4_dss_features = {
740 765
741 .num_mgrs = 3, 766 .num_mgrs = 3,
742 .num_ovls = 4, 767 .num_ovls = 4,
768 .num_wbs = 1,
743 .supported_displays = omap4_dss_supported_displays, 769 .supported_displays = omap4_dss_supported_displays,
744 .supported_outputs = omap4_dss_supported_outputs, 770 .supported_outputs = omap4_dss_supported_outputs,
745 .supported_color_modes = omap4_dss_supported_color_modes, 771 .supported_color_modes = omap4_dss_supported_color_modes,
@@ -817,6 +843,11 @@ int dss_feat_get_num_ovls(void)
817 return omap_current_dss_features->num_ovls; 843 return omap_current_dss_features->num_ovls;
818} 844}
819 845
846int dss_feat_get_num_wbs(void)
847{
848 return omap_current_dss_features->num_wbs;
849}
850
820unsigned long dss_feat_get_param_min(enum dss_range_param param) 851unsigned long dss_feat_get_param_min(enum dss_range_param param)
821{ 852{
822 return omap_current_dss_features->dss_params[param].min; 853 return omap_current_dss_features->dss_params[param].min;
diff --git a/drivers/video/omap2/dss/dss_features.h b/drivers/video/omap2/dss/dss_features.h
index 89df2aa860d4..9218113b5e88 100644
--- a/drivers/video/omap2/dss/dss_features.h
+++ b/drivers/video/omap2/dss/dss_features.h
@@ -105,6 +105,7 @@ enum dss_range_param {
105/* DSS Feature Functions */ 105/* DSS Feature Functions */
106int dss_feat_get_num_mgrs(void); 106int dss_feat_get_num_mgrs(void);
107int dss_feat_get_num_ovls(void); 107int dss_feat_get_num_ovls(void);
108int dss_feat_get_num_wbs(void);
108unsigned long dss_feat_get_param_min(enum dss_range_param param); 109unsigned long dss_feat_get_param_min(enum dss_range_param param);
109unsigned long dss_feat_get_param_max(enum dss_range_param param); 110unsigned long dss_feat_get_param_max(enum dss_range_param param);
110enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel); 111enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel);