aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video
diff options
context:
space:
mode:
authorTomi Valkeinen <tomi.valkeinen@ti.com>2011-11-03 10:17:37 -0400
committerTomi Valkeinen <tomi.valkeinen@ti.com>2011-12-02 01:54:23 -0500
commit8760db5406fb7b92f900d6c98eea198695476467 (patch)
tree11010c221ad9061bc8e54ec254d40a912e94e965 /drivers/video
parent6f04e1bfc36c5865dc5679f85e25b6613be86298 (diff)
OMAPDSS: remove partial update from the overlay manager
Partial update for manual update displays has never worked quite well: * The HW has limitations on the update area, and the x and width need to be even. * Showing a part of a scaled overlay causes artifacts. * Makes the management of dispc very complex Considering the above points and the fact that partial update is not used anywhere, this and the following patches remove the partial update support. This will greatly simplify the following re-write of the apply mechanism to get proper locking and additional features like fifo-merge. This patch removes the partial update from the manager.c. Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Diffstat (limited to 'drivers/video')
-rw-r--r--drivers/video/omap2/dss/dsi.c2
-rw-r--r--drivers/video/omap2/dss/dss.h3
-rw-r--r--drivers/video/omap2/dss/manager.c333
-rw-r--r--drivers/video/omap2/dss/rfbi.c1
4 files changed, 6 insertions, 333 deletions
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index 9bcb5c2511df..773a496a2d31 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -4206,8 +4206,6 @@ int omap_dsi_prepare_update(struct omap_dss_device *dssdev,
4206 4206
4207 dsi_perf_mark_setup(dsidev); 4207 dsi_perf_mark_setup(dsidev);
4208 4208
4209 dss_setup_partial_planes(dssdev, x, y, w, h,
4210 enlarge_update_area);
4211 dispc_mgr_set_lcd_size(dssdev->manager->id, *w, *h); 4209 dispc_mgr_set_lcd_size(dssdev->manager->id, *w, *h);
4212 4210
4213 return 0; 4211 return 0;
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index 313a7cafdc9b..7f6a612bb5b6 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -182,9 +182,6 @@ void default_get_overlay_fifo_thresholds(enum omap_plane plane,
182int dss_init_overlay_managers(struct platform_device *pdev); 182int dss_init_overlay_managers(struct platform_device *pdev);
183void dss_uninit_overlay_managers(struct platform_device *pdev); 183void dss_uninit_overlay_managers(struct platform_device *pdev);
184int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl); 184int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl);
185void dss_setup_partial_planes(struct omap_dss_device *dssdev,
186 u16 *x, u16 *y, u16 *w, u16 *h,
187 bool enlarge_update_area);
188void dss_start_update(struct omap_dss_device *dssdev); 185void dss_start_update(struct omap_dss_device *dssdev);
189 186
190/* overlay */ 187/* overlay */
diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c
index 1be5f47a2114..c616f850eaf8 100644
--- a/drivers/video/omap2/dss/manager.c
+++ b/drivers/video/omap2/dss/manager.c
@@ -530,13 +530,6 @@ struct manager_cache_data {
530 530
531 bool manual_update; 531 bool manual_update;
532 bool do_manual_update; 532 bool do_manual_update;
533
534 /* manual update region */
535 u16 x, y, w, h;
536
537 /* enlarge the update area if the update area contains scaled
538 * overlays */
539 bool enlarge_update_area;
540}; 533};
541 534
542static struct { 535static struct {
@@ -762,65 +755,11 @@ static int overlay_enabled(struct omap_overlay *ovl)
762 return ovl->info.enabled && ovl->manager && ovl->manager->device; 755 return ovl->info.enabled && ovl->manager && ovl->manager->device;
763} 756}
764 757
765/* Is rect1 a subset of rect2? */
766static bool rectangle_subset(int x1, int y1, int w1, int h1,
767 int x2, int y2, int w2, int h2)
768{
769 if (x1 < x2 || y1 < y2)
770 return false;
771
772 if (x1 + w1 > x2 + w2)
773 return false;
774
775 if (y1 + h1 > y2 + h2)
776 return false;
777
778 return true;
779}
780
781/* Do rect1 and rect2 overlap? */
782static bool rectangle_intersects(int x1, int y1, int w1, int h1,
783 int x2, int y2, int w2, int h2)
784{
785 if (x1 >= x2 + w2)
786 return false;
787
788 if (x2 >= x1 + w1)
789 return false;
790
791 if (y1 >= y2 + h2)
792 return false;
793
794 if (y2 >= y1 + h1)
795 return false;
796
797 return true;
798}
799
800static bool dispc_is_overlay_scaled(struct overlay_cache_data *oc)
801{
802 struct omap_overlay_info *oi = &oc->info;
803
804 if (oi->out_width != 0 && oi->width != oi->out_width)
805 return true;
806
807 if (oi->out_height != 0 && oi->height != oi->out_height)
808 return true;
809
810 return false;
811}
812
813static int configure_overlay(enum omap_plane plane) 758static int configure_overlay(enum omap_plane plane)
814{ 759{
815 struct overlay_cache_data *c; 760 struct overlay_cache_data *c;
816 struct manager_cache_data *mc; 761 struct omap_overlay_info *oi;
817 struct omap_overlay_info *oi, new_oi;
818 struct omap_overlay_manager_info *mi;
819 u16 outw, outh;
820 u16 x, y, w, h;
821 u32 paddr;
822 int r; 762 int r;
823 u16 orig_w, orig_h, orig_outw, orig_outh;
824 763
825 DSSDBGF("%d", plane); 764 DSSDBGF("%d", plane);
826 765
@@ -832,120 +771,7 @@ static int configure_overlay(enum omap_plane plane)
832 return 0; 771 return 0;
833 } 772 }
834 773
835 mc = &dss_cache.manager_cache[c->channel]; 774 r = dispc_ovl_setup(plane, oi, c->ilace, c->channel,
836 mi = &mc->info;
837
838 x = oi->pos_x;
839 y = oi->pos_y;
840 w = oi->width;
841 h = oi->height;
842 outw = oi->out_width == 0 ? oi->width : oi->out_width;
843 outh = oi->out_height == 0 ? oi->height : oi->out_height;
844 paddr = oi->paddr;
845
846 orig_w = w;
847 orig_h = h;
848 orig_outw = outw;
849 orig_outh = outh;
850
851 if (mc->manual_update && mc->do_manual_update) {
852 unsigned bpp;
853 unsigned scale_x_m = w, scale_x_d = outw;
854 unsigned scale_y_m = h, scale_y_d = outh;
855
856 /* If the overlay is outside the update region, disable it */
857 if (!rectangle_intersects(mc->x, mc->y, mc->w, mc->h,
858 x, y, outw, outh)) {
859 dispc_ovl_enable(plane, 0);
860 return 0;
861 }
862
863 switch (oi->color_mode) {
864 case OMAP_DSS_COLOR_NV12:
865 bpp = 8;
866 break;
867 case OMAP_DSS_COLOR_RGB16:
868 case OMAP_DSS_COLOR_ARGB16:
869 case OMAP_DSS_COLOR_YUV2:
870 case OMAP_DSS_COLOR_UYVY:
871 case OMAP_DSS_COLOR_RGBA16:
872 case OMAP_DSS_COLOR_RGBX16:
873 case OMAP_DSS_COLOR_ARGB16_1555:
874 case OMAP_DSS_COLOR_XRGB16_1555:
875 bpp = 16;
876 break;
877
878 case OMAP_DSS_COLOR_RGB24P:
879 bpp = 24;
880 break;
881
882 case OMAP_DSS_COLOR_RGB24U:
883 case OMAP_DSS_COLOR_ARGB32:
884 case OMAP_DSS_COLOR_RGBA32:
885 case OMAP_DSS_COLOR_RGBX32:
886 bpp = 32;
887 break;
888
889 default:
890 BUG();
891 }
892
893 if (mc->x > oi->pos_x) {
894 x = 0;
895 outw -= (mc->x - oi->pos_x);
896 paddr += (mc->x - oi->pos_x) *
897 scale_x_m / scale_x_d * bpp / 8;
898 } else {
899 x = oi->pos_x - mc->x;
900 }
901
902 if (mc->y > oi->pos_y) {
903 y = 0;
904 outh -= (mc->y - oi->pos_y);
905 paddr += (mc->y - oi->pos_y) *
906 scale_y_m / scale_y_d *
907 oi->screen_width * bpp / 8;
908 } else {
909 y = oi->pos_y - mc->y;
910 }
911
912 if (mc->w < (x + outw))
913 outw -= (x + outw) - (mc->w);
914
915 if (mc->h < (y + outh))
916 outh -= (y + outh) - (mc->h);
917
918 w = w * outw / orig_outw;
919 h = h * outh / orig_outh;
920
921 /* YUV mode overlay's input width has to be even and the
922 * algorithm above may adjust the width to be odd.
923 *
924 * Here we adjust the width if needed, preferring to increase
925 * the width if the original width was bigger.
926 */
927 if ((w & 1) &&
928 (oi->color_mode == OMAP_DSS_COLOR_YUV2 ||
929 oi->color_mode == OMAP_DSS_COLOR_UYVY)) {
930 if (orig_w > w)
931 w += 1;
932 else
933 w -= 1;
934 }
935 }
936
937 new_oi = *oi;
938
939 /* update new_oi members which could have been possibly updated */
940 new_oi.pos_x = x;
941 new_oi.pos_y = y;
942 new_oi.width = w;
943 new_oi.height = h;
944 new_oi.out_width = outw;
945 new_oi.out_height = outh;
946 new_oi.paddr = paddr;
947
948 r = dispc_ovl_setup(plane, &new_oi, c->ilace, c->channel,
949 c->replication, c->fifo_low, c->fifo_high); 775 c->replication, c->fifo_low, c->fifo_high);
950 if (r) { 776 if (r) {
951 /* this shouldn't happen */ 777 /* this shouldn't happen */
@@ -1070,170 +896,23 @@ static int configure_dispc(void)
1070 return r; 896 return r;
1071} 897}
1072 898
1073/* Make the coordinates even. There are some strange problems with OMAP and 899void dss_start_update(struct omap_dss_device *dssdev)
1074 * partial DSI update when the update widths are odd. */
1075static void make_even(u16 *x, u16 *w)
1076{
1077 u16 x1, x2;
1078
1079 x1 = *x;
1080 x2 = *x + *w;
1081
1082 x1 &= ~1;
1083 x2 = ALIGN(x2, 2);
1084
1085 *x = x1;
1086 *w = x2 - x1;
1087}
1088
1089/* Configure dispc for partial update. Return possibly modified update
1090 * area */
1091void dss_setup_partial_planes(struct omap_dss_device *dssdev,
1092 u16 *xi, u16 *yi, u16 *wi, u16 *hi, bool enlarge_update_area)
1093{ 900{
1094 struct overlay_cache_data *oc;
1095 struct manager_cache_data *mc; 901 struct manager_cache_data *mc;
1096 struct omap_overlay_info *oi; 902 struct overlay_cache_data *oc;
1097 const int num_ovls = dss_feat_get_num_ovls(); 903 const int num_ovls = dss_feat_get_num_ovls();
904 const int num_mgrs = dss_feat_get_num_mgrs();
1098 struct omap_overlay_manager *mgr; 905 struct omap_overlay_manager *mgr;
1099 int i; 906 int i;
1100 u16 x, y, w, h;
1101 unsigned long flags;
1102 bool area_changed;
1103
1104 x = *xi;
1105 y = *yi;
1106 w = *wi;
1107 h = *hi;
1108
1109 DSSDBG("dispc_setup_partial_planes %d,%d %dx%d\n",
1110 *xi, *yi, *wi, *hi);
1111 907
1112 mgr = dssdev->manager; 908 mgr = dssdev->manager;
1113 909
1114 if (!mgr) {
1115 DSSDBG("no manager\n");
1116 return;
1117 }
1118
1119 make_even(&x, &w);
1120
1121 spin_lock_irqsave(&dss_cache.lock, flags);
1122
1123 /*
1124 * Execute the outer loop until the inner loop has completed
1125 * once without increasing the update area. This will ensure that
1126 * all scaled overlays end up completely within the update area.
1127 */
1128 do {
1129 area_changed = false;
1130
1131 /* We need to show the whole overlay if it is scaled. So look
1132 * for those, and make the update area larger if found.
1133 * Also mark the overlay cache dirty */
1134 for (i = 0; i < num_ovls; ++i) {
1135 unsigned x1, y1, x2, y2;
1136 unsigned outw, outh;
1137
1138 oc = &dss_cache.overlay_cache[i];
1139 oi = &oc->info;
1140
1141 if (oc->channel != mgr->id)
1142 continue;
1143
1144 oc->dirty = true;
1145
1146 if (!enlarge_update_area)
1147 continue;
1148
1149 if (!oc->enabled)
1150 continue;
1151
1152 if (!dispc_is_overlay_scaled(oc))
1153 continue;
1154
1155 outw = oi->out_width == 0 ?
1156 oi->width : oi->out_width;
1157 outh = oi->out_height == 0 ?
1158 oi->height : oi->out_height;
1159
1160 /* is the overlay outside the update region? */
1161 if (!rectangle_intersects(x, y, w, h,
1162 oi->pos_x, oi->pos_y,
1163 outw, outh))
1164 continue;
1165
1166 /* if the overlay totally inside the update region? */
1167 if (rectangle_subset(oi->pos_x, oi->pos_y, outw, outh,
1168 x, y, w, h))
1169 continue;
1170
1171 if (x > oi->pos_x)
1172 x1 = oi->pos_x;
1173 else
1174 x1 = x;
1175
1176 if (y > oi->pos_y)
1177 y1 = oi->pos_y;
1178 else
1179 y1 = y;
1180
1181 if ((x + w) < (oi->pos_x + outw))
1182 x2 = oi->pos_x + outw;
1183 else
1184 x2 = x + w;
1185
1186 if ((y + h) < (oi->pos_y + outh))
1187 y2 = oi->pos_y + outh;
1188 else
1189 y2 = y + h;
1190
1191 x = x1;
1192 y = y1;
1193 w = x2 - x1;
1194 h = y2 - y1;
1195
1196 make_even(&x, &w);
1197
1198 DSSDBG("changing upd area due to ovl(%d) "
1199 "scaling %d,%d %dx%d\n",
1200 i, x, y, w, h);
1201
1202 area_changed = true;
1203 }
1204 } while (area_changed);
1205
1206 mc = &dss_cache.manager_cache[mgr->id]; 910 mc = &dss_cache.manager_cache[mgr->id];
1207 mc->do_manual_update = true;
1208 mc->enlarge_update_area = enlarge_update_area;
1209 mc->x = x;
1210 mc->y = y;
1211 mc->w = w;
1212 mc->h = h;
1213 911
912 mc->do_manual_update = true;
1214 configure_dispc(); 913 configure_dispc();
1215
1216 mc->do_manual_update = false; 914 mc->do_manual_update = false;
1217 915
1218 spin_unlock_irqrestore(&dss_cache.lock, flags);
1219
1220 *xi = x;
1221 *yi = y;
1222 *wi = w;
1223 *hi = h;
1224}
1225
1226void dss_start_update(struct omap_dss_device *dssdev)
1227{
1228 struct manager_cache_data *mc;
1229 struct overlay_cache_data *oc;
1230 const int num_ovls = dss_feat_get_num_ovls();
1231 const int num_mgrs = dss_feat_get_num_mgrs();
1232 struct omap_overlay_manager *mgr;
1233 int i;
1234
1235 mgr = dssdev->manager;
1236
1237 for (i = 0; i < num_ovls; ++i) { 916 for (i = 0; i < num_ovls; ++i) {
1238 oc = &dss_cache.overlay_cache[i]; 917 oc = &dss_cache.overlay_cache[i];
1239 if (oc->channel != mgr->id) 918 if (oc->channel != mgr->id)
diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c
index 1130c608a561..814bb9500dca 100644
--- a/drivers/video/omap2/dss/rfbi.c
+++ b/drivers/video/omap2/dss/rfbi.c
@@ -784,7 +784,6 @@ int omap_rfbi_prepare_update(struct omap_dss_device *dssdev,
784 if (*w == 0 || *h == 0) 784 if (*w == 0 || *h == 0)
785 return -EINVAL; 785 return -EINVAL;
786 786
787 dss_setup_partial_planes(dssdev, x, y, w, h, true);
788 dispc_mgr_set_lcd_size(dssdev->manager->id, *w, *h); 787 dispc_mgr_set_lcd_size(dssdev->manager->id, *w, *h);
789 788
790 return 0; 789 return 0;