diff options
Diffstat (limited to 'drivers/video/omap2/dss/dispc.c')
-rw-r--r-- | drivers/video/omap2/dss/dispc.c | 747 |
1 files changed, 534 insertions, 213 deletions
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index ee30937482e1..4749ac356469 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c | |||
@@ -131,23 +131,6 @@ static inline u32 dispc_read_reg(const u16 idx) | |||
131 | return __raw_readl(dispc.base + idx); | 131 | return __raw_readl(dispc.base + idx); |
132 | } | 132 | } |
133 | 133 | ||
134 | static int dispc_get_ctx_loss_count(void) | ||
135 | { | ||
136 | struct device *dev = &dispc.pdev->dev; | ||
137 | struct omap_display_platform_data *pdata = dev->platform_data; | ||
138 | struct omap_dss_board_info *board_data = pdata->board_data; | ||
139 | int cnt; | ||
140 | |||
141 | if (!board_data->get_context_loss_count) | ||
142 | return -ENOENT; | ||
143 | |||
144 | cnt = board_data->get_context_loss_count(dev); | ||
145 | |||
146 | WARN_ONCE(cnt < 0, "get_context_loss_count failed: %d\n", cnt); | ||
147 | |||
148 | return cnt; | ||
149 | } | ||
150 | |||
151 | #define SR(reg) \ | 134 | #define SR(reg) \ |
152 | dispc.ctx[DISPC_##reg / sizeof(u32)] = dispc_read_reg(DISPC_##reg) | 135 | dispc.ctx[DISPC_##reg / sizeof(u32)] = dispc_read_reg(DISPC_##reg) |
153 | #define RR(reg) \ | 136 | #define RR(reg) \ |
@@ -251,7 +234,7 @@ static void dispc_save_context(void) | |||
251 | if (dss_has_feature(FEAT_CORE_CLK_DIV)) | 234 | if (dss_has_feature(FEAT_CORE_CLK_DIV)) |
252 | SR(DIVISOR); | 235 | SR(DIVISOR); |
253 | 236 | ||
254 | dispc.ctx_loss_cnt = dispc_get_ctx_loss_count(); | 237 | dispc.ctx_loss_cnt = dss_get_ctx_loss_count(&dispc.pdev->dev); |
255 | dispc.ctx_valid = true; | 238 | dispc.ctx_valid = true; |
256 | 239 | ||
257 | DSSDBG("context saved, ctx_loss_count %d\n", dispc.ctx_loss_cnt); | 240 | DSSDBG("context saved, ctx_loss_count %d\n", dispc.ctx_loss_cnt); |
@@ -266,7 +249,7 @@ static void dispc_restore_context(void) | |||
266 | if (!dispc.ctx_valid) | 249 | if (!dispc.ctx_valid) |
267 | return; | 250 | return; |
268 | 251 | ||
269 | ctx = dispc_get_ctx_loss_count(); | 252 | ctx = dss_get_ctx_loss_count(&dispc.pdev->dev); |
270 | 253 | ||
271 | if (ctx >= 0 && ctx == dispc.ctx_loss_cnt) | 254 | if (ctx >= 0 && ctx == dispc.ctx_loss_cnt) |
272 | return; | 255 | return; |
@@ -413,14 +396,6 @@ static inline bool dispc_mgr_is_lcd(enum omap_channel channel) | |||
413 | return false; | 396 | return false; |
414 | } | 397 | } |
415 | 398 | ||
416 | static struct omap_dss_device *dispc_mgr_get_device(enum omap_channel channel) | ||
417 | { | ||
418 | struct omap_overlay_manager *mgr = | ||
419 | omap_dss_get_overlay_manager(channel); | ||
420 | |||
421 | return mgr ? mgr->device : NULL; | ||
422 | } | ||
423 | |||
424 | u32 dispc_mgr_get_vsync_irq(enum omap_channel channel) | 399 | u32 dispc_mgr_get_vsync_irq(enum omap_channel channel) |
425 | { | 400 | { |
426 | switch (channel) { | 401 | switch (channel) { |
@@ -432,6 +407,7 @@ u32 dispc_mgr_get_vsync_irq(enum omap_channel channel) | |||
432 | return DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN; | 407 | return DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN; |
433 | default: | 408 | default: |
434 | BUG(); | 409 | BUG(); |
410 | return 0; | ||
435 | } | 411 | } |
436 | } | 412 | } |
437 | 413 | ||
@@ -446,6 +422,7 @@ u32 dispc_mgr_get_framedone_irq(enum omap_channel channel) | |||
446 | return 0; | 422 | return 0; |
447 | default: | 423 | default: |
448 | BUG(); | 424 | BUG(); |
425 | return 0; | ||
449 | } | 426 | } |
450 | } | 427 | } |
451 | 428 | ||
@@ -764,7 +741,7 @@ static void dispc_ovl_set_color_mode(enum omap_plane plane, | |||
764 | case OMAP_DSS_COLOR_XRGB16_1555: | 741 | case OMAP_DSS_COLOR_XRGB16_1555: |
765 | m = 0xf; break; | 742 | m = 0xf; break; |
766 | default: | 743 | default: |
767 | BUG(); break; | 744 | BUG(); return; |
768 | } | 745 | } |
769 | } else { | 746 | } else { |
770 | switch (color_mode) { | 747 | switch (color_mode) { |
@@ -801,13 +778,25 @@ static void dispc_ovl_set_color_mode(enum omap_plane plane, | |||
801 | case OMAP_DSS_COLOR_XRGB16_1555: | 778 | case OMAP_DSS_COLOR_XRGB16_1555: |
802 | m = 0xf; break; | 779 | m = 0xf; break; |
803 | default: | 780 | default: |
804 | BUG(); break; | 781 | BUG(); return; |
805 | } | 782 | } |
806 | } | 783 | } |
807 | 784 | ||
808 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), m, 4, 1); | 785 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), m, 4, 1); |
809 | } | 786 | } |
810 | 787 | ||
788 | static void dispc_ovl_configure_burst_type(enum omap_plane plane, | ||
789 | enum omap_dss_rotation_type rotation_type) | ||
790 | { | ||
791 | if (dss_has_feature(FEAT_BURST_2D) == 0) | ||
792 | return; | ||
793 | |||
794 | if (rotation_type == OMAP_DSS_ROT_TILER) | ||
795 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), 1, 29, 29); | ||
796 | else | ||
797 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), 0, 29, 29); | ||
798 | } | ||
799 | |||
811 | void dispc_ovl_set_channel_out(enum omap_plane plane, enum omap_channel channel) | 800 | void dispc_ovl_set_channel_out(enum omap_plane plane, enum omap_channel channel) |
812 | { | 801 | { |
813 | int shift; | 802 | int shift; |
@@ -845,6 +834,7 @@ void dispc_ovl_set_channel_out(enum omap_plane plane, enum omap_channel channel) | |||
845 | break; | 834 | break; |
846 | default: | 835 | default: |
847 | BUG(); | 836 | BUG(); |
837 | return; | ||
848 | } | 838 | } |
849 | 839 | ||
850 | val = FLD_MOD(val, chan, shift, shift); | 840 | val = FLD_MOD(val, chan, shift, shift); |
@@ -872,6 +862,7 @@ static enum omap_channel dispc_ovl_get_channel_out(enum omap_plane plane) | |||
872 | break; | 862 | break; |
873 | default: | 863 | default: |
874 | BUG(); | 864 | BUG(); |
865 | return 0; | ||
875 | } | 866 | } |
876 | 867 | ||
877 | val = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane)); | 868 | val = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane)); |
@@ -983,20 +974,13 @@ static void dispc_ovl_enable_replication(enum omap_plane plane, bool enable) | |||
983 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable, shift, shift); | 974 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable, shift, shift); |
984 | } | 975 | } |
985 | 976 | ||
986 | void dispc_mgr_set_lcd_size(enum omap_channel channel, u16 width, u16 height) | 977 | static void dispc_mgr_set_size(enum omap_channel channel, u16 width, |
978 | u16 height) | ||
987 | { | 979 | { |
988 | u32 val; | 980 | u32 val; |
989 | BUG_ON((width > (1 << 11)) || (height > (1 << 11))); | ||
990 | val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0); | ||
991 | dispc_write_reg(DISPC_SIZE_MGR(channel), val); | ||
992 | } | ||
993 | 981 | ||
994 | void dispc_set_digit_size(u16 width, u16 height) | ||
995 | { | ||
996 | u32 val; | ||
997 | BUG_ON((width > (1 << 11)) || (height > (1 << 11))); | ||
998 | val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0); | 982 | val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0); |
999 | dispc_write_reg(DISPC_SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT), val); | 983 | dispc_write_reg(DISPC_SIZE_MGR(channel), val); |
1000 | } | 984 | } |
1001 | 985 | ||
1002 | static void dispc_read_plane_fifo_sizes(void) | 986 | static void dispc_read_plane_fifo_sizes(void) |
@@ -1063,7 +1047,8 @@ void dispc_enable_fifomerge(bool enable) | |||
1063 | } | 1047 | } |
1064 | 1048 | ||
1065 | void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane, | 1049 | void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane, |
1066 | u32 *fifo_low, u32 *fifo_high, bool use_fifomerge) | 1050 | u32 *fifo_low, u32 *fifo_high, bool use_fifomerge, |
1051 | bool manual_update) | ||
1067 | { | 1052 | { |
1068 | /* | 1053 | /* |
1069 | * All sizes are in bytes. Both the buffer and burst are made of | 1054 | * All sizes are in bytes. Both the buffer and burst are made of |
@@ -1091,7 +1076,7 @@ void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane, | |||
1091 | * combined fifo size | 1076 | * combined fifo size |
1092 | */ | 1077 | */ |
1093 | 1078 | ||
1094 | if (dss_has_feature(FEAT_OMAP3_DSI_FIFO_BUG)) { | 1079 | if (manual_update && dss_has_feature(FEAT_OMAP3_DSI_FIFO_BUG)) { |
1095 | *fifo_low = ovl_fifo_size - burst_size * 2; | 1080 | *fifo_low = ovl_fifo_size - burst_size * 2; |
1096 | *fifo_high = total_fifo_size - burst_size; | 1081 | *fifo_high = total_fifo_size - burst_size; |
1097 | } else { | 1082 | } else { |
@@ -1185,6 +1170,94 @@ static void dispc_ovl_set_scale_param(enum omap_plane plane, | |||
1185 | dispc_ovl_set_fir(plane, fir_hinc, fir_vinc, color_comp); | 1170 | dispc_ovl_set_fir(plane, fir_hinc, fir_vinc, color_comp); |
1186 | } | 1171 | } |
1187 | 1172 | ||
1173 | static void dispc_ovl_set_accu_uv(enum omap_plane plane, | ||
1174 | u16 orig_width, u16 orig_height, u16 out_width, u16 out_height, | ||
1175 | bool ilace, enum omap_color_mode color_mode, u8 rotation) | ||
1176 | { | ||
1177 | int h_accu2_0, h_accu2_1; | ||
1178 | int v_accu2_0, v_accu2_1; | ||
1179 | int chroma_hinc, chroma_vinc; | ||
1180 | int idx; | ||
1181 | |||
1182 | struct accu { | ||
1183 | s8 h0_m, h0_n; | ||
1184 | s8 h1_m, h1_n; | ||
1185 | s8 v0_m, v0_n; | ||
1186 | s8 v1_m, v1_n; | ||
1187 | }; | ||
1188 | |||
1189 | const struct accu *accu_table; | ||
1190 | const struct accu *accu_val; | ||
1191 | |||
1192 | static const struct accu accu_nv12[4] = { | ||
1193 | { 0, 1, 0, 1 , -1, 2, 0, 1 }, | ||
1194 | { 1, 2, -3, 4 , 0, 1, 0, 1 }, | ||
1195 | { -1, 1, 0, 1 , -1, 2, 0, 1 }, | ||
1196 | { -1, 2, -1, 2 , -1, 1, 0, 1 }, | ||
1197 | }; | ||
1198 | |||
1199 | static const struct accu accu_nv12_ilace[4] = { | ||
1200 | { 0, 1, 0, 1 , -3, 4, -1, 4 }, | ||
1201 | { -1, 4, -3, 4 , 0, 1, 0, 1 }, | ||
1202 | { -1, 1, 0, 1 , -1, 4, -3, 4 }, | ||
1203 | { -3, 4, -3, 4 , -1, 1, 0, 1 }, | ||
1204 | }; | ||
1205 | |||
1206 | static const struct accu accu_yuv[4] = { | ||
1207 | { 0, 1, 0, 1, 0, 1, 0, 1 }, | ||
1208 | { 0, 1, 0, 1, 0, 1, 0, 1 }, | ||
1209 | { -1, 1, 0, 1, 0, 1, 0, 1 }, | ||
1210 | { 0, 1, 0, 1, -1, 1, 0, 1 }, | ||
1211 | }; | ||
1212 | |||
1213 | switch (rotation) { | ||
1214 | case OMAP_DSS_ROT_0: | ||
1215 | idx = 0; | ||
1216 | break; | ||
1217 | case OMAP_DSS_ROT_90: | ||
1218 | idx = 1; | ||
1219 | break; | ||
1220 | case OMAP_DSS_ROT_180: | ||
1221 | idx = 2; | ||
1222 | break; | ||
1223 | case OMAP_DSS_ROT_270: | ||
1224 | idx = 3; | ||
1225 | break; | ||
1226 | default: | ||
1227 | BUG(); | ||
1228 | return; | ||
1229 | } | ||
1230 | |||
1231 | switch (color_mode) { | ||
1232 | case OMAP_DSS_COLOR_NV12: | ||
1233 | if (ilace) | ||
1234 | accu_table = accu_nv12_ilace; | ||
1235 | else | ||
1236 | accu_table = accu_nv12; | ||
1237 | break; | ||
1238 | case OMAP_DSS_COLOR_YUV2: | ||
1239 | case OMAP_DSS_COLOR_UYVY: | ||
1240 | accu_table = accu_yuv; | ||
1241 | break; | ||
1242 | default: | ||
1243 | BUG(); | ||
1244 | return; | ||
1245 | } | ||
1246 | |||
1247 | accu_val = &accu_table[idx]; | ||
1248 | |||
1249 | chroma_hinc = 1024 * orig_width / out_width; | ||
1250 | chroma_vinc = 1024 * orig_height / out_height; | ||
1251 | |||
1252 | h_accu2_0 = (accu_val->h0_m * chroma_hinc / accu_val->h0_n) % 1024; | ||
1253 | h_accu2_1 = (accu_val->h1_m * chroma_hinc / accu_val->h1_n) % 1024; | ||
1254 | v_accu2_0 = (accu_val->v0_m * chroma_vinc / accu_val->v0_n) % 1024; | ||
1255 | v_accu2_1 = (accu_val->v1_m * chroma_vinc / accu_val->v1_n) % 1024; | ||
1256 | |||
1257 | dispc_ovl_set_vid_accu2_0(plane, h_accu2_0, v_accu2_0); | ||
1258 | dispc_ovl_set_vid_accu2_1(plane, h_accu2_1, v_accu2_1); | ||
1259 | } | ||
1260 | |||
1188 | static void dispc_ovl_set_scaling_common(enum omap_plane plane, | 1261 | static void dispc_ovl_set_scaling_common(enum omap_plane plane, |
1189 | u16 orig_width, u16 orig_height, | 1262 | u16 orig_width, u16 orig_height, |
1190 | u16 out_width, u16 out_height, | 1263 | u16 out_width, u16 out_height, |
@@ -1258,6 +1331,10 @@ static void dispc_ovl_set_scaling_uv(enum omap_plane plane, | |||
1258 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES2(plane), 0, 8, 8); | 1331 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES2(plane), 0, 8, 8); |
1259 | return; | 1332 | return; |
1260 | } | 1333 | } |
1334 | |||
1335 | dispc_ovl_set_accu_uv(plane, orig_width, orig_height, out_width, | ||
1336 | out_height, ilace, color_mode, rotation); | ||
1337 | |||
1261 | switch (color_mode) { | 1338 | switch (color_mode) { |
1262 | case OMAP_DSS_COLOR_NV12: | 1339 | case OMAP_DSS_COLOR_NV12: |
1263 | /* UV is subsampled by 2 vertically*/ | 1340 | /* UV is subsampled by 2 vertically*/ |
@@ -1280,6 +1357,7 @@ static void dispc_ovl_set_scaling_uv(enum omap_plane plane, | |||
1280 | break; | 1357 | break; |
1281 | default: | 1358 | default: |
1282 | BUG(); | 1359 | BUG(); |
1360 | return; | ||
1283 | } | 1361 | } |
1284 | 1362 | ||
1285 | if (out_width != orig_width) | 1363 | if (out_width != orig_width) |
@@ -1297,9 +1375,6 @@ static void dispc_ovl_set_scaling_uv(enum omap_plane plane, | |||
1297 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), scale_x ? 1 : 0, 5, 5); | 1375 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), scale_x ? 1 : 0, 5, 5); |
1298 | /* set V scaling */ | 1376 | /* set V scaling */ |
1299 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), scale_y ? 1 : 0, 6, 6); | 1377 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), scale_y ? 1 : 0, 6, 6); |
1300 | |||
1301 | dispc_ovl_set_vid_accu2_0(plane, 0x80, 0); | ||
1302 | dispc_ovl_set_vid_accu2_1(plane, 0x80, 0); | ||
1303 | } | 1378 | } |
1304 | 1379 | ||
1305 | static void dispc_ovl_set_scaling(enum omap_plane plane, | 1380 | static void dispc_ovl_set_scaling(enum omap_plane plane, |
@@ -1410,6 +1485,7 @@ static int color_mode_to_bpp(enum omap_color_mode color_mode) | |||
1410 | return 32; | 1485 | return 32; |
1411 | default: | 1486 | default: |
1412 | BUG(); | 1487 | BUG(); |
1488 | return 0; | ||
1413 | } | 1489 | } |
1414 | } | 1490 | } |
1415 | 1491 | ||
@@ -1423,6 +1499,7 @@ static s32 pixinc(int pixels, u8 ps) | |||
1423 | return 1 - (-pixels + 1) * ps; | 1499 | return 1 - (-pixels + 1) * ps; |
1424 | else | 1500 | else |
1425 | BUG(); | 1501 | BUG(); |
1502 | return 0; | ||
1426 | } | 1503 | } |
1427 | 1504 | ||
1428 | static void calc_vrfb_rotation_offset(u8 rotation, bool mirror, | 1505 | static void calc_vrfb_rotation_offset(u8 rotation, bool mirror, |
@@ -1431,7 +1508,7 @@ static void calc_vrfb_rotation_offset(u8 rotation, bool mirror, | |||
1431 | enum omap_color_mode color_mode, bool fieldmode, | 1508 | enum omap_color_mode color_mode, bool fieldmode, |
1432 | unsigned int field_offset, | 1509 | unsigned int field_offset, |
1433 | unsigned *offset0, unsigned *offset1, | 1510 | unsigned *offset0, unsigned *offset1, |
1434 | s32 *row_inc, s32 *pix_inc) | 1511 | s32 *row_inc, s32 *pix_inc, int x_predecim, int y_predecim) |
1435 | { | 1512 | { |
1436 | u8 ps; | 1513 | u8 ps; |
1437 | 1514 | ||
@@ -1477,10 +1554,10 @@ static void calc_vrfb_rotation_offset(u8 rotation, bool mirror, | |||
1477 | else | 1554 | else |
1478 | *offset0 = 0; | 1555 | *offset0 = 0; |
1479 | 1556 | ||
1480 | *row_inc = pixinc(1 + (screen_width - width) + | 1557 | *row_inc = pixinc(1 + |
1481 | (fieldmode ? screen_width : 0), | 1558 | (y_predecim * screen_width - x_predecim * width) + |
1482 | ps); | 1559 | (fieldmode ? screen_width : 0), ps); |
1483 | *pix_inc = pixinc(1, ps); | 1560 | *pix_inc = pixinc(x_predecim, ps); |
1484 | break; | 1561 | break; |
1485 | 1562 | ||
1486 | case OMAP_DSS_ROT_0 + 4: | 1563 | case OMAP_DSS_ROT_0 + 4: |
@@ -1498,14 +1575,15 @@ static void calc_vrfb_rotation_offset(u8 rotation, bool mirror, | |||
1498 | *offset0 = field_offset * screen_width * ps; | 1575 | *offset0 = field_offset * screen_width * ps; |
1499 | else | 1576 | else |
1500 | *offset0 = 0; | 1577 | *offset0 = 0; |
1501 | *row_inc = pixinc(1 - (screen_width + width) - | 1578 | *row_inc = pixinc(1 - |
1502 | (fieldmode ? screen_width : 0), | 1579 | (y_predecim * screen_width + x_predecim * width) - |
1503 | ps); | 1580 | (fieldmode ? screen_width : 0), ps); |
1504 | *pix_inc = pixinc(1, ps); | 1581 | *pix_inc = pixinc(x_predecim, ps); |
1505 | break; | 1582 | break; |
1506 | 1583 | ||
1507 | default: | 1584 | default: |
1508 | BUG(); | 1585 | BUG(); |
1586 | return; | ||
1509 | } | 1587 | } |
1510 | } | 1588 | } |
1511 | 1589 | ||
@@ -1515,7 +1593,7 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror, | |||
1515 | enum omap_color_mode color_mode, bool fieldmode, | 1593 | enum omap_color_mode color_mode, bool fieldmode, |
1516 | unsigned int field_offset, | 1594 | unsigned int field_offset, |
1517 | unsigned *offset0, unsigned *offset1, | 1595 | unsigned *offset0, unsigned *offset1, |
1518 | s32 *row_inc, s32 *pix_inc) | 1596 | s32 *row_inc, s32 *pix_inc, int x_predecim, int y_predecim) |
1519 | { | 1597 | { |
1520 | u8 ps; | 1598 | u8 ps; |
1521 | u16 fbw, fbh; | 1599 | u16 fbw, fbh; |
@@ -1557,10 +1635,14 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror, | |||
1557 | *offset0 = *offset1 + field_offset * screen_width * ps; | 1635 | *offset0 = *offset1 + field_offset * screen_width * ps; |
1558 | else | 1636 | else |
1559 | *offset0 = *offset1; | 1637 | *offset0 = *offset1; |
1560 | *row_inc = pixinc(1 + (screen_width - fbw) + | 1638 | *row_inc = pixinc(1 + |
1561 | (fieldmode ? screen_width : 0), | 1639 | (y_predecim * screen_width - fbw * x_predecim) + |
1562 | ps); | 1640 | (fieldmode ? screen_width : 0), ps); |
1563 | *pix_inc = pixinc(1, ps); | 1641 | if (color_mode == OMAP_DSS_COLOR_YUV2 || |
1642 | color_mode == OMAP_DSS_COLOR_UYVY) | ||
1643 | *pix_inc = pixinc(x_predecim, 2 * ps); | ||
1644 | else | ||
1645 | *pix_inc = pixinc(x_predecim, ps); | ||
1564 | break; | 1646 | break; |
1565 | case OMAP_DSS_ROT_90: | 1647 | case OMAP_DSS_ROT_90: |
1566 | *offset1 = screen_width * (fbh - 1) * ps; | 1648 | *offset1 = screen_width * (fbh - 1) * ps; |
@@ -1568,9 +1650,9 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror, | |||
1568 | *offset0 = *offset1 + field_offset * ps; | 1650 | *offset0 = *offset1 + field_offset * ps; |
1569 | else | 1651 | else |
1570 | *offset0 = *offset1; | 1652 | *offset0 = *offset1; |
1571 | *row_inc = pixinc(screen_width * (fbh - 1) + 1 + | 1653 | *row_inc = pixinc(screen_width * (fbh * x_predecim - 1) + |
1572 | (fieldmode ? 1 : 0), ps); | 1654 | y_predecim + (fieldmode ? 1 : 0), ps); |
1573 | *pix_inc = pixinc(-screen_width, ps); | 1655 | *pix_inc = pixinc(-x_predecim * screen_width, ps); |
1574 | break; | 1656 | break; |
1575 | case OMAP_DSS_ROT_180: | 1657 | case OMAP_DSS_ROT_180: |
1576 | *offset1 = (screen_width * (fbh - 1) + fbw - 1) * ps; | 1658 | *offset1 = (screen_width * (fbh - 1) + fbw - 1) * ps; |
@@ -1579,10 +1661,13 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror, | |||
1579 | else | 1661 | else |
1580 | *offset0 = *offset1; | 1662 | *offset0 = *offset1; |
1581 | *row_inc = pixinc(-1 - | 1663 | *row_inc = pixinc(-1 - |
1582 | (screen_width - fbw) - | 1664 | (y_predecim * screen_width - fbw * x_predecim) - |
1583 | (fieldmode ? screen_width : 0), | 1665 | (fieldmode ? screen_width : 0), ps); |
1584 | ps); | 1666 | if (color_mode == OMAP_DSS_COLOR_YUV2 || |
1585 | *pix_inc = pixinc(-1, ps); | 1667 | color_mode == OMAP_DSS_COLOR_UYVY) |
1668 | *pix_inc = pixinc(-x_predecim, 2 * ps); | ||
1669 | else | ||
1670 | *pix_inc = pixinc(-x_predecim, ps); | ||
1586 | break; | 1671 | break; |
1587 | case OMAP_DSS_ROT_270: | 1672 | case OMAP_DSS_ROT_270: |
1588 | *offset1 = (fbw - 1) * ps; | 1673 | *offset1 = (fbw - 1) * ps; |
@@ -1590,9 +1675,9 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror, | |||
1590 | *offset0 = *offset1 - field_offset * ps; | 1675 | *offset0 = *offset1 - field_offset * ps; |
1591 | else | 1676 | else |
1592 | *offset0 = *offset1; | 1677 | *offset0 = *offset1; |
1593 | *row_inc = pixinc(-screen_width * (fbh - 1) - 1 - | 1678 | *row_inc = pixinc(-screen_width * (fbh * x_predecim - 1) - |
1594 | (fieldmode ? 1 : 0), ps); | 1679 | y_predecim - (fieldmode ? 1 : 0), ps); |
1595 | *pix_inc = pixinc(screen_width, ps); | 1680 | *pix_inc = pixinc(x_predecim * screen_width, ps); |
1596 | break; | 1681 | break; |
1597 | 1682 | ||
1598 | /* mirroring */ | 1683 | /* mirroring */ |
@@ -1602,10 +1687,14 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror, | |||
1602 | *offset0 = *offset1 + field_offset * screen_width * ps; | 1687 | *offset0 = *offset1 + field_offset * screen_width * ps; |
1603 | else | 1688 | else |
1604 | *offset0 = *offset1; | 1689 | *offset0 = *offset1; |
1605 | *row_inc = pixinc(screen_width * 2 - 1 + | 1690 | *row_inc = pixinc(y_predecim * screen_width * 2 - 1 + |
1606 | (fieldmode ? screen_width : 0), | 1691 | (fieldmode ? screen_width : 0), |
1607 | ps); | 1692 | ps); |
1608 | *pix_inc = pixinc(-1, ps); | 1693 | if (color_mode == OMAP_DSS_COLOR_YUV2 || |
1694 | color_mode == OMAP_DSS_COLOR_UYVY) | ||
1695 | *pix_inc = pixinc(-x_predecim, 2 * ps); | ||
1696 | else | ||
1697 | *pix_inc = pixinc(-x_predecim, ps); | ||
1609 | break; | 1698 | break; |
1610 | 1699 | ||
1611 | case OMAP_DSS_ROT_90 + 4: | 1700 | case OMAP_DSS_ROT_90 + 4: |
@@ -1614,10 +1703,10 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror, | |||
1614 | *offset0 = *offset1 + field_offset * ps; | 1703 | *offset0 = *offset1 + field_offset * ps; |
1615 | else | 1704 | else |
1616 | *offset0 = *offset1; | 1705 | *offset0 = *offset1; |
1617 | *row_inc = pixinc(-screen_width * (fbh - 1) + 1 + | 1706 | *row_inc = pixinc(-screen_width * (fbh * x_predecim - 1) + |
1618 | (fieldmode ? 1 : 0), | 1707 | y_predecim + (fieldmode ? 1 : 0), |
1619 | ps); | 1708 | ps); |
1620 | *pix_inc = pixinc(screen_width, ps); | 1709 | *pix_inc = pixinc(x_predecim * screen_width, ps); |
1621 | break; | 1710 | break; |
1622 | 1711 | ||
1623 | case OMAP_DSS_ROT_180 + 4: | 1712 | case OMAP_DSS_ROT_180 + 4: |
@@ -1626,10 +1715,14 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror, | |||
1626 | *offset0 = *offset1 - field_offset * screen_width * ps; | 1715 | *offset0 = *offset1 - field_offset * screen_width * ps; |
1627 | else | 1716 | else |
1628 | *offset0 = *offset1; | 1717 | *offset0 = *offset1; |
1629 | *row_inc = pixinc(1 - screen_width * 2 - | 1718 | *row_inc = pixinc(1 - y_predecim * screen_width * 2 - |
1630 | (fieldmode ? screen_width : 0), | 1719 | (fieldmode ? screen_width : 0), |
1631 | ps); | 1720 | ps); |
1632 | *pix_inc = pixinc(1, ps); | 1721 | if (color_mode == OMAP_DSS_COLOR_YUV2 || |
1722 | color_mode == OMAP_DSS_COLOR_UYVY) | ||
1723 | *pix_inc = pixinc(x_predecim, 2 * ps); | ||
1724 | else | ||
1725 | *pix_inc = pixinc(x_predecim, ps); | ||
1633 | break; | 1726 | break; |
1634 | 1727 | ||
1635 | case OMAP_DSS_ROT_270 + 4: | 1728 | case OMAP_DSS_ROT_270 + 4: |
@@ -1638,34 +1731,130 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror, | |||
1638 | *offset0 = *offset1 - field_offset * ps; | 1731 | *offset0 = *offset1 - field_offset * ps; |
1639 | else | 1732 | else |
1640 | *offset0 = *offset1; | 1733 | *offset0 = *offset1; |
1641 | *row_inc = pixinc(screen_width * (fbh - 1) - 1 - | 1734 | *row_inc = pixinc(screen_width * (fbh * x_predecim - 1) - |
1642 | (fieldmode ? 1 : 0), | 1735 | y_predecim - (fieldmode ? 1 : 0), |
1643 | ps); | 1736 | ps); |
1644 | *pix_inc = pixinc(-screen_width, ps); | 1737 | *pix_inc = pixinc(-x_predecim * screen_width, ps); |
1645 | break; | 1738 | break; |
1646 | 1739 | ||
1647 | default: | 1740 | default: |
1648 | BUG(); | 1741 | BUG(); |
1742 | return; | ||
1743 | } | ||
1744 | } | ||
1745 | |||
1746 | static void calc_tiler_rotation_offset(u16 screen_width, u16 width, | ||
1747 | enum omap_color_mode color_mode, bool fieldmode, | ||
1748 | unsigned int field_offset, unsigned *offset0, unsigned *offset1, | ||
1749 | s32 *row_inc, s32 *pix_inc, int x_predecim, int y_predecim) | ||
1750 | { | ||
1751 | u8 ps; | ||
1752 | |||
1753 | switch (color_mode) { | ||
1754 | case OMAP_DSS_COLOR_CLUT1: | ||
1755 | case OMAP_DSS_COLOR_CLUT2: | ||
1756 | case OMAP_DSS_COLOR_CLUT4: | ||
1757 | case OMAP_DSS_COLOR_CLUT8: | ||
1758 | BUG(); | ||
1759 | return; | ||
1760 | default: | ||
1761 | ps = color_mode_to_bpp(color_mode) / 8; | ||
1762 | break; | ||
1649 | } | 1763 | } |
1764 | |||
1765 | DSSDBG("scrw %d, width %d\n", screen_width, width); | ||
1766 | |||
1767 | /* | ||
1768 | * field 0 = even field = bottom field | ||
1769 | * field 1 = odd field = top field | ||
1770 | */ | ||
1771 | *offset1 = 0; | ||
1772 | if (field_offset) | ||
1773 | *offset0 = *offset1 + field_offset * screen_width * ps; | ||
1774 | else | ||
1775 | *offset0 = *offset1; | ||
1776 | *row_inc = pixinc(1 + (y_predecim * screen_width - width * x_predecim) + | ||
1777 | (fieldmode ? screen_width : 0), ps); | ||
1778 | if (color_mode == OMAP_DSS_COLOR_YUV2 || | ||
1779 | color_mode == OMAP_DSS_COLOR_UYVY) | ||
1780 | *pix_inc = pixinc(x_predecim, 2 * ps); | ||
1781 | else | ||
1782 | *pix_inc = pixinc(x_predecim, ps); | ||
1650 | } | 1783 | } |
1651 | 1784 | ||
1652 | static unsigned long calc_fclk_five_taps(enum omap_channel channel, u16 width, | 1785 | /* |
1786 | * This function is used to avoid synclosts in OMAP3, because of some | ||
1787 | * undocumented horizontal position and timing related limitations. | ||
1788 | */ | ||
1789 | static int check_horiz_timing_omap3(enum omap_channel channel, | ||
1790 | const struct omap_video_timings *t, u16 pos_x, | ||
1791 | u16 width, u16 height, u16 out_width, u16 out_height) | ||
1792 | { | ||
1793 | int DS = DIV_ROUND_UP(height, out_height); | ||
1794 | unsigned long nonactive, lclk, pclk; | ||
1795 | static const u8 limits[3] = { 8, 10, 20 }; | ||
1796 | u64 val, blank; | ||
1797 | int i; | ||
1798 | |||
1799 | nonactive = t->x_res + t->hfp + t->hsw + t->hbp - out_width; | ||
1800 | pclk = dispc_mgr_pclk_rate(channel); | ||
1801 | if (dispc_mgr_is_lcd(channel)) | ||
1802 | lclk = dispc_mgr_lclk_rate(channel); | ||
1803 | else | ||
1804 | lclk = dispc_fclk_rate(); | ||
1805 | |||
1806 | i = 0; | ||
1807 | if (out_height < height) | ||
1808 | i++; | ||
1809 | if (out_width < width) | ||
1810 | i++; | ||
1811 | blank = div_u64((u64)(t->hbp + t->hsw + t->hfp) * lclk, pclk); | ||
1812 | DSSDBG("blanking period + ppl = %llu (limit = %u)\n", blank, limits[i]); | ||
1813 | if (blank <= limits[i]) | ||
1814 | return -EINVAL; | ||
1815 | |||
1816 | /* | ||
1817 | * Pixel data should be prepared before visible display point starts. | ||
1818 | * So, atleast DS-2 lines must have already been fetched by DISPC | ||
1819 | * during nonactive - pos_x period. | ||
1820 | */ | ||
1821 | val = div_u64((u64)(nonactive - pos_x) * lclk, pclk); | ||
1822 | DSSDBG("(nonactive - pos_x) * pcd = %llu max(0, DS - 2) * width = %d\n", | ||
1823 | val, max(0, DS - 2) * width); | ||
1824 | if (val < max(0, DS - 2) * width) | ||
1825 | return -EINVAL; | ||
1826 | |||
1827 | /* | ||
1828 | * All lines need to be refilled during the nonactive period of which | ||
1829 | * only one line can be loaded during the active period. So, atleast | ||
1830 | * DS - 1 lines should be loaded during nonactive period. | ||
1831 | */ | ||
1832 | val = div_u64((u64)nonactive * lclk, pclk); | ||
1833 | DSSDBG("nonactive * pcd = %llu, max(0, DS - 1) * width = %d\n", | ||
1834 | val, max(0, DS - 1) * width); | ||
1835 | if (val < max(0, DS - 1) * width) | ||
1836 | return -EINVAL; | ||
1837 | |||
1838 | return 0; | ||
1839 | } | ||
1840 | |||
1841 | static unsigned long calc_core_clk_five_taps(enum omap_channel channel, | ||
1842 | const struct omap_video_timings *mgr_timings, u16 width, | ||
1653 | u16 height, u16 out_width, u16 out_height, | 1843 | u16 height, u16 out_width, u16 out_height, |
1654 | enum omap_color_mode color_mode) | 1844 | enum omap_color_mode color_mode) |
1655 | { | 1845 | { |
1656 | u32 fclk = 0; | 1846 | u32 core_clk = 0; |
1657 | u64 tmp, pclk = dispc_mgr_pclk_rate(channel); | 1847 | u64 tmp, pclk = dispc_mgr_pclk_rate(channel); |
1658 | 1848 | ||
1659 | if (height <= out_height && width <= out_width) | 1849 | if (height <= out_height && width <= out_width) |
1660 | return (unsigned long) pclk; | 1850 | return (unsigned long) pclk; |
1661 | 1851 | ||
1662 | if (height > out_height) { | 1852 | if (height > out_height) { |
1663 | struct omap_dss_device *dssdev = dispc_mgr_get_device(channel); | 1853 | unsigned int ppl = mgr_timings->x_res; |
1664 | unsigned int ppl = dssdev->panel.timings.x_res; | ||
1665 | 1854 | ||
1666 | tmp = pclk * height * out_width; | 1855 | tmp = pclk * height * out_width; |
1667 | do_div(tmp, 2 * out_height * ppl); | 1856 | do_div(tmp, 2 * out_height * ppl); |
1668 | fclk = tmp; | 1857 | core_clk = tmp; |
1669 | 1858 | ||
1670 | if (height > 2 * out_height) { | 1859 | if (height > 2 * out_height) { |
1671 | if (ppl == out_width) | 1860 | if (ppl == out_width) |
@@ -1673,23 +1862,23 @@ static unsigned long calc_fclk_five_taps(enum omap_channel channel, u16 width, | |||
1673 | 1862 | ||
1674 | tmp = pclk * (height - 2 * out_height) * out_width; | 1863 | tmp = pclk * (height - 2 * out_height) * out_width; |
1675 | do_div(tmp, 2 * out_height * (ppl - out_width)); | 1864 | do_div(tmp, 2 * out_height * (ppl - out_width)); |
1676 | fclk = max(fclk, (u32) tmp); | 1865 | core_clk = max_t(u32, core_clk, tmp); |
1677 | } | 1866 | } |
1678 | } | 1867 | } |
1679 | 1868 | ||
1680 | if (width > out_width) { | 1869 | if (width > out_width) { |
1681 | tmp = pclk * width; | 1870 | tmp = pclk * width; |
1682 | do_div(tmp, out_width); | 1871 | do_div(tmp, out_width); |
1683 | fclk = max(fclk, (u32) tmp); | 1872 | core_clk = max_t(u32, core_clk, tmp); |
1684 | 1873 | ||
1685 | if (color_mode == OMAP_DSS_COLOR_RGB24U) | 1874 | if (color_mode == OMAP_DSS_COLOR_RGB24U) |
1686 | fclk <<= 1; | 1875 | core_clk <<= 1; |
1687 | } | 1876 | } |
1688 | 1877 | ||
1689 | return fclk; | 1878 | return core_clk; |
1690 | } | 1879 | } |
1691 | 1880 | ||
1692 | static unsigned long calc_fclk(enum omap_channel channel, u16 width, | 1881 | static unsigned long calc_core_clk(enum omap_channel channel, u16 width, |
1693 | u16 height, u16 out_width, u16 out_height) | 1882 | u16 height, u16 out_width, u16 out_height) |
1694 | { | 1883 | { |
1695 | unsigned int hf, vf; | 1884 | unsigned int hf, vf; |
@@ -1730,15 +1919,20 @@ static unsigned long calc_fclk(enum omap_channel channel, u16 width, | |||
1730 | } | 1919 | } |
1731 | 1920 | ||
1732 | static int dispc_ovl_calc_scaling(enum omap_plane plane, | 1921 | static int dispc_ovl_calc_scaling(enum omap_plane plane, |
1733 | enum omap_channel channel, u16 width, u16 height, | 1922 | enum omap_channel channel, |
1734 | u16 out_width, u16 out_height, | 1923 | const struct omap_video_timings *mgr_timings, |
1735 | enum omap_color_mode color_mode, bool *five_taps) | 1924 | u16 width, u16 height, u16 out_width, u16 out_height, |
1925 | enum omap_color_mode color_mode, bool *five_taps, | ||
1926 | int *x_predecim, int *y_predecim, u16 pos_x) | ||
1736 | { | 1927 | { |
1737 | struct omap_overlay *ovl = omap_dss_get_overlay(plane); | 1928 | struct omap_overlay *ovl = omap_dss_get_overlay(plane); |
1738 | const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE); | 1929 | const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE); |
1739 | const int maxsinglelinewidth = | 1930 | const int maxsinglelinewidth = |
1740 | dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH); | 1931 | dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH); |
1741 | unsigned long fclk = 0; | 1932 | const int max_decim_limit = 16; |
1933 | unsigned long core_clk = 0; | ||
1934 | int decim_x, decim_y, error, min_factor; | ||
1935 | u16 in_width, in_height, in_width_max = 0; | ||
1742 | 1936 | ||
1743 | if (width == out_width && height == out_height) | 1937 | if (width == out_width && height == out_height) |
1744 | return 0; | 1938 | return 0; |
@@ -1746,64 +1940,154 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane, | |||
1746 | if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) | 1940 | if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) |
1747 | return -EINVAL; | 1941 | return -EINVAL; |
1748 | 1942 | ||
1749 | if (out_width < width / maxdownscale || | 1943 | *x_predecim = max_decim_limit; |
1750 | out_width > width * 8) | 1944 | *y_predecim = max_decim_limit; |
1945 | |||
1946 | if (color_mode == OMAP_DSS_COLOR_CLUT1 || | ||
1947 | color_mode == OMAP_DSS_COLOR_CLUT2 || | ||
1948 | color_mode == OMAP_DSS_COLOR_CLUT4 || | ||
1949 | color_mode == OMAP_DSS_COLOR_CLUT8) { | ||
1950 | *x_predecim = 1; | ||
1951 | *y_predecim = 1; | ||
1952 | *five_taps = false; | ||
1953 | return 0; | ||
1954 | } | ||
1955 | |||
1956 | decim_x = DIV_ROUND_UP(DIV_ROUND_UP(width, out_width), maxdownscale); | ||
1957 | decim_y = DIV_ROUND_UP(DIV_ROUND_UP(height, out_height), maxdownscale); | ||
1958 | |||
1959 | min_factor = min(decim_x, decim_y); | ||
1960 | |||
1961 | if (decim_x > *x_predecim || out_width > width * 8) | ||
1751 | return -EINVAL; | 1962 | return -EINVAL; |
1752 | 1963 | ||
1753 | if (out_height < height / maxdownscale || | 1964 | if (decim_y > *y_predecim || out_height > height * 8) |
1754 | out_height > height * 8) | ||
1755 | return -EINVAL; | 1965 | return -EINVAL; |
1756 | 1966 | ||
1757 | if (cpu_is_omap24xx()) { | 1967 | if (cpu_is_omap24xx()) { |
1758 | if (width > maxsinglelinewidth) | ||
1759 | DSSERR("Cannot scale max input width exceeded"); | ||
1760 | *five_taps = false; | 1968 | *five_taps = false; |
1761 | fclk = calc_fclk(channel, width, height, out_width, | 1969 | |
1762 | out_height); | 1970 | do { |
1971 | in_height = DIV_ROUND_UP(height, decim_y); | ||
1972 | in_width = DIV_ROUND_UP(width, decim_x); | ||
1973 | core_clk = calc_core_clk(channel, in_width, in_height, | ||
1974 | out_width, out_height); | ||
1975 | error = (in_width > maxsinglelinewidth || !core_clk || | ||
1976 | core_clk > dispc_core_clk_rate()); | ||
1977 | if (error) { | ||
1978 | if (decim_x == decim_y) { | ||
1979 | decim_x = min_factor; | ||
1980 | decim_y++; | ||
1981 | } else { | ||
1982 | swap(decim_x, decim_y); | ||
1983 | if (decim_x < decim_y) | ||
1984 | decim_x++; | ||
1985 | } | ||
1986 | } | ||
1987 | } while (decim_x <= *x_predecim && decim_y <= *y_predecim && | ||
1988 | error); | ||
1989 | |||
1990 | if (in_width > maxsinglelinewidth) { | ||
1991 | DSSERR("Cannot scale max input width exceeded"); | ||
1992 | return -EINVAL; | ||
1993 | } | ||
1763 | } else if (cpu_is_omap34xx()) { | 1994 | } else if (cpu_is_omap34xx()) { |
1764 | if (width > (maxsinglelinewidth * 2)) { | 1995 | |
1996 | do { | ||
1997 | in_height = DIV_ROUND_UP(height, decim_y); | ||
1998 | in_width = DIV_ROUND_UP(width, decim_x); | ||
1999 | core_clk = calc_core_clk_five_taps(channel, mgr_timings, | ||
2000 | in_width, in_height, out_width, out_height, | ||
2001 | color_mode); | ||
2002 | |||
2003 | error = check_horiz_timing_omap3(channel, mgr_timings, | ||
2004 | pos_x, in_width, in_height, out_width, | ||
2005 | out_height); | ||
2006 | |||
2007 | if (in_width > maxsinglelinewidth) | ||
2008 | if (in_height > out_height && | ||
2009 | in_height < out_height * 2) | ||
2010 | *five_taps = false; | ||
2011 | if (!*five_taps) | ||
2012 | core_clk = calc_core_clk(channel, in_width, | ||
2013 | in_height, out_width, out_height); | ||
2014 | error = (error || in_width > maxsinglelinewidth * 2 || | ||
2015 | (in_width > maxsinglelinewidth && *five_taps) || | ||
2016 | !core_clk || core_clk > dispc_core_clk_rate()); | ||
2017 | if (error) { | ||
2018 | if (decim_x == decim_y) { | ||
2019 | decim_x = min_factor; | ||
2020 | decim_y++; | ||
2021 | } else { | ||
2022 | swap(decim_x, decim_y); | ||
2023 | if (decim_x < decim_y) | ||
2024 | decim_x++; | ||
2025 | } | ||
2026 | } | ||
2027 | } while (decim_x <= *x_predecim && decim_y <= *y_predecim | ||
2028 | && error); | ||
2029 | |||
2030 | if (check_horiz_timing_omap3(channel, mgr_timings, pos_x, width, | ||
2031 | height, out_width, out_height)){ | ||
2032 | DSSERR("horizontal timing too tight\n"); | ||
2033 | return -EINVAL; | ||
2034 | } | ||
2035 | |||
2036 | if (in_width > (maxsinglelinewidth * 2)) { | ||
1765 | DSSERR("Cannot setup scaling"); | 2037 | DSSERR("Cannot setup scaling"); |
1766 | DSSERR("width exceeds maximum width possible"); | 2038 | DSSERR("width exceeds maximum width possible"); |
1767 | return -EINVAL; | 2039 | return -EINVAL; |
1768 | } | 2040 | } |
1769 | fclk = calc_fclk_five_taps(channel, width, height, out_width, | 2041 | |
1770 | out_height, color_mode); | 2042 | if (in_width > maxsinglelinewidth && *five_taps) { |
1771 | if (width > maxsinglelinewidth) { | 2043 | DSSERR("cannot setup scaling with five taps"); |
1772 | if (height > out_height && height < out_height * 2) | 2044 | return -EINVAL; |
1773 | *five_taps = false; | ||
1774 | else { | ||
1775 | DSSERR("cannot setup scaling with five taps"); | ||
1776 | return -EINVAL; | ||
1777 | } | ||
1778 | } | 2045 | } |
1779 | if (!*five_taps) | ||
1780 | fclk = calc_fclk(channel, width, height, out_width, | ||
1781 | out_height); | ||
1782 | } else { | 2046 | } else { |
1783 | if (width > maxsinglelinewidth) { | 2047 | int decim_x_min = decim_x; |
2048 | in_height = DIV_ROUND_UP(height, decim_y); | ||
2049 | in_width_max = dispc_core_clk_rate() / | ||
2050 | DIV_ROUND_UP(dispc_mgr_pclk_rate(channel), | ||
2051 | out_width); | ||
2052 | decim_x = DIV_ROUND_UP(width, in_width_max); | ||
2053 | |||
2054 | decim_x = decim_x > decim_x_min ? decim_x : decim_x_min; | ||
2055 | if (decim_x > *x_predecim) | ||
2056 | return -EINVAL; | ||
2057 | |||
2058 | do { | ||
2059 | in_width = DIV_ROUND_UP(width, decim_x); | ||
2060 | } while (decim_x <= *x_predecim && | ||
2061 | in_width > maxsinglelinewidth && decim_x++); | ||
2062 | |||
2063 | if (in_width > maxsinglelinewidth) { | ||
1784 | DSSERR("Cannot scale width exceeds max line width"); | 2064 | DSSERR("Cannot scale width exceeds max line width"); |
1785 | return -EINVAL; | 2065 | return -EINVAL; |
1786 | } | 2066 | } |
1787 | fclk = calc_fclk(channel, width, height, out_width, | 2067 | |
1788 | out_height); | 2068 | core_clk = calc_core_clk(channel, in_width, in_height, |
2069 | out_width, out_height); | ||
1789 | } | 2070 | } |
1790 | 2071 | ||
1791 | DSSDBG("required fclk rate = %lu Hz\n", fclk); | 2072 | DSSDBG("required core clk rate = %lu Hz\n", core_clk); |
1792 | DSSDBG("current fclk rate = %lu Hz\n", dispc_fclk_rate()); | 2073 | DSSDBG("current core clk rate = %lu Hz\n", dispc_core_clk_rate()); |
1793 | 2074 | ||
1794 | if (!fclk || fclk > dispc_fclk_rate()) { | 2075 | if (!core_clk || core_clk > dispc_core_clk_rate()) { |
1795 | DSSERR("failed to set up scaling, " | 2076 | DSSERR("failed to set up scaling, " |
1796 | "required fclk rate = %lu Hz, " | 2077 | "required core clk rate = %lu Hz, " |
1797 | "current fclk rate = %lu Hz\n", | 2078 | "current core clk rate = %lu Hz\n", |
1798 | fclk, dispc_fclk_rate()); | 2079 | core_clk, dispc_core_clk_rate()); |
1799 | return -EINVAL; | 2080 | return -EINVAL; |
1800 | } | 2081 | } |
1801 | 2082 | ||
2083 | *x_predecim = decim_x; | ||
2084 | *y_predecim = decim_y; | ||
1802 | return 0; | 2085 | return 0; |
1803 | } | 2086 | } |
1804 | 2087 | ||
1805 | int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi, | 2088 | int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi, |
1806 | bool ilace, bool replication) | 2089 | bool ilace, bool replication, |
2090 | const struct omap_video_timings *mgr_timings) | ||
1807 | { | 2091 | { |
1808 | struct omap_overlay *ovl = omap_dss_get_overlay(plane); | 2092 | struct omap_overlay *ovl = omap_dss_get_overlay(plane); |
1809 | bool five_taps = true; | 2093 | bool five_taps = true; |
@@ -1814,8 +2098,11 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi, | |||
1814 | s32 pix_inc; | 2098 | s32 pix_inc; |
1815 | u16 frame_height = oi->height; | 2099 | u16 frame_height = oi->height; |
1816 | unsigned int field_offset = 0; | 2100 | unsigned int field_offset = 0; |
1817 | u16 outw, outh; | 2101 | u16 in_height = oi->height; |
2102 | u16 in_width = oi->width; | ||
2103 | u16 out_width, out_height; | ||
1818 | enum omap_channel channel; | 2104 | enum omap_channel channel; |
2105 | int x_predecim = 1, y_predecim = 1; | ||
1819 | 2106 | ||
1820 | channel = dispc_ovl_get_channel_out(plane); | 2107 | channel = dispc_ovl_get_channel_out(plane); |
1821 | 2108 | ||
@@ -1829,32 +2116,35 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi, | |||
1829 | if (oi->paddr == 0) | 2116 | if (oi->paddr == 0) |
1830 | return -EINVAL; | 2117 | return -EINVAL; |
1831 | 2118 | ||
1832 | outw = oi->out_width == 0 ? oi->width : oi->out_width; | 2119 | out_width = oi->out_width == 0 ? oi->width : oi->out_width; |
1833 | outh = oi->out_height == 0 ? oi->height : oi->out_height; | 2120 | out_height = oi->out_height == 0 ? oi->height : oi->out_height; |
1834 | 2121 | ||
1835 | if (ilace && oi->height == outh) | 2122 | if (ilace && oi->height == out_height) |
1836 | fieldmode = 1; | 2123 | fieldmode = 1; |
1837 | 2124 | ||
1838 | if (ilace) { | 2125 | if (ilace) { |
1839 | if (fieldmode) | 2126 | if (fieldmode) |
1840 | oi->height /= 2; | 2127 | in_height /= 2; |
1841 | oi->pos_y /= 2; | 2128 | oi->pos_y /= 2; |
1842 | outh /= 2; | 2129 | out_height /= 2; |
1843 | 2130 | ||
1844 | DSSDBG("adjusting for ilace: height %d, pos_y %d, " | 2131 | DSSDBG("adjusting for ilace: height %d, pos_y %d, " |
1845 | "out_height %d\n", | 2132 | "out_height %d\n", |
1846 | oi->height, oi->pos_y, outh); | 2133 | in_height, oi->pos_y, out_height); |
1847 | } | 2134 | } |
1848 | 2135 | ||
1849 | if (!dss_feat_color_mode_supported(plane, oi->color_mode)) | 2136 | if (!dss_feat_color_mode_supported(plane, oi->color_mode)) |
1850 | return -EINVAL; | 2137 | return -EINVAL; |
1851 | 2138 | ||
1852 | r = dispc_ovl_calc_scaling(plane, channel, oi->width, oi->height, | 2139 | r = dispc_ovl_calc_scaling(plane, channel, mgr_timings, in_width, |
1853 | outw, outh, oi->color_mode, | 2140 | in_height, out_width, out_height, oi->color_mode, |
1854 | &five_taps); | 2141 | &five_taps, &x_predecim, &y_predecim, oi->pos_x); |
1855 | if (r) | 2142 | if (r) |
1856 | return r; | 2143 | return r; |
1857 | 2144 | ||
2145 | in_width = DIV_ROUND_UP(in_width, x_predecim); | ||
2146 | in_height = DIV_ROUND_UP(in_height, y_predecim); | ||
2147 | |||
1858 | if (oi->color_mode == OMAP_DSS_COLOR_YUV2 || | 2148 | if (oi->color_mode == OMAP_DSS_COLOR_YUV2 || |
1859 | oi->color_mode == OMAP_DSS_COLOR_UYVY || | 2149 | oi->color_mode == OMAP_DSS_COLOR_UYVY || |
1860 | oi->color_mode == OMAP_DSS_COLOR_NV12) | 2150 | oi->color_mode == OMAP_DSS_COLOR_NV12) |
@@ -1868,32 +2158,46 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi, | |||
1868 | * so the integer part must be added to the base address of the | 2158 | * so the integer part must be added to the base address of the |
1869 | * bottom field. | 2159 | * bottom field. |
1870 | */ | 2160 | */ |
1871 | if (!oi->height || oi->height == outh) | 2161 | if (!in_height || in_height == out_height) |
1872 | field_offset = 0; | 2162 | field_offset = 0; |
1873 | else | 2163 | else |
1874 | field_offset = oi->height / outh / 2; | 2164 | field_offset = in_height / out_height / 2; |
1875 | } | 2165 | } |
1876 | 2166 | ||
1877 | /* Fields are independent but interleaved in memory. */ | 2167 | /* Fields are independent but interleaved in memory. */ |
1878 | if (fieldmode) | 2168 | if (fieldmode) |
1879 | field_offset = 1; | 2169 | field_offset = 1; |
1880 | 2170 | ||
1881 | if (oi->rotation_type == OMAP_DSS_ROT_DMA) | 2171 | offset0 = 0; |
2172 | offset1 = 0; | ||
2173 | row_inc = 0; | ||
2174 | pix_inc = 0; | ||
2175 | |||
2176 | if (oi->rotation_type == OMAP_DSS_ROT_TILER) | ||
2177 | calc_tiler_rotation_offset(oi->screen_width, in_width, | ||
2178 | oi->color_mode, fieldmode, field_offset, | ||
2179 | &offset0, &offset1, &row_inc, &pix_inc, | ||
2180 | x_predecim, y_predecim); | ||
2181 | else if (oi->rotation_type == OMAP_DSS_ROT_DMA) | ||
1882 | calc_dma_rotation_offset(oi->rotation, oi->mirror, | 2182 | calc_dma_rotation_offset(oi->rotation, oi->mirror, |
1883 | oi->screen_width, oi->width, frame_height, | 2183 | oi->screen_width, in_width, frame_height, |
1884 | oi->color_mode, fieldmode, field_offset, | 2184 | oi->color_mode, fieldmode, field_offset, |
1885 | &offset0, &offset1, &row_inc, &pix_inc); | 2185 | &offset0, &offset1, &row_inc, &pix_inc, |
2186 | x_predecim, y_predecim); | ||
1886 | else | 2187 | else |
1887 | calc_vrfb_rotation_offset(oi->rotation, oi->mirror, | 2188 | calc_vrfb_rotation_offset(oi->rotation, oi->mirror, |
1888 | oi->screen_width, oi->width, frame_height, | 2189 | oi->screen_width, in_width, frame_height, |
1889 | oi->color_mode, fieldmode, field_offset, | 2190 | oi->color_mode, fieldmode, field_offset, |
1890 | &offset0, &offset1, &row_inc, &pix_inc); | 2191 | &offset0, &offset1, &row_inc, &pix_inc, |
2192 | x_predecim, y_predecim); | ||
1891 | 2193 | ||
1892 | DSSDBG("offset0 %u, offset1 %u, row_inc %d, pix_inc %d\n", | 2194 | DSSDBG("offset0 %u, offset1 %u, row_inc %d, pix_inc %d\n", |
1893 | offset0, offset1, row_inc, pix_inc); | 2195 | offset0, offset1, row_inc, pix_inc); |
1894 | 2196 | ||
1895 | dispc_ovl_set_color_mode(plane, oi->color_mode); | 2197 | dispc_ovl_set_color_mode(plane, oi->color_mode); |
1896 | 2198 | ||
2199 | dispc_ovl_configure_burst_type(plane, oi->rotation_type); | ||
2200 | |||
1897 | dispc_ovl_set_ba0(plane, oi->paddr + offset0); | 2201 | dispc_ovl_set_ba0(plane, oi->paddr + offset0); |
1898 | dispc_ovl_set_ba1(plane, oi->paddr + offset1); | 2202 | dispc_ovl_set_ba1(plane, oi->paddr + offset1); |
1899 | 2203 | ||
@@ -1906,19 +2210,18 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi, | |||
1906 | dispc_ovl_set_row_inc(plane, row_inc); | 2210 | dispc_ovl_set_row_inc(plane, row_inc); |
1907 | dispc_ovl_set_pix_inc(plane, pix_inc); | 2211 | dispc_ovl_set_pix_inc(plane, pix_inc); |
1908 | 2212 | ||
1909 | DSSDBG("%d,%d %dx%d -> %dx%d\n", oi->pos_x, oi->pos_y, oi->width, | 2213 | DSSDBG("%d,%d %dx%d -> %dx%d\n", oi->pos_x, oi->pos_y, in_width, |
1910 | oi->height, outw, outh); | 2214 | in_height, out_width, out_height); |
1911 | 2215 | ||
1912 | dispc_ovl_set_pos(plane, oi->pos_x, oi->pos_y); | 2216 | dispc_ovl_set_pos(plane, oi->pos_x, oi->pos_y); |
1913 | 2217 | ||
1914 | dispc_ovl_set_pic_size(plane, oi->width, oi->height); | 2218 | dispc_ovl_set_pic_size(plane, in_width, in_height); |
1915 | 2219 | ||
1916 | if (ovl->caps & OMAP_DSS_OVL_CAP_SCALE) { | 2220 | if (ovl->caps & OMAP_DSS_OVL_CAP_SCALE) { |
1917 | dispc_ovl_set_scaling(plane, oi->width, oi->height, | 2221 | dispc_ovl_set_scaling(plane, in_width, in_height, out_width, |
1918 | outw, outh, | 2222 | out_height, ilace, five_taps, fieldmode, |
1919 | ilace, five_taps, fieldmode, | ||
1920 | oi->color_mode, oi->rotation); | 2223 | oi->color_mode, oi->rotation); |
1921 | dispc_ovl_set_vid_size(plane, outw, outh); | 2224 | dispc_ovl_set_vid_size(plane, out_width, out_height); |
1922 | dispc_ovl_set_vid_color_conv(plane, cconv); | 2225 | dispc_ovl_set_vid_color_conv(plane, cconv); |
1923 | } | 2226 | } |
1924 | 2227 | ||
@@ -2087,8 +2390,10 @@ bool dispc_mgr_is_enabled(enum omap_channel channel) | |||
2087 | return !!REG_GET(DISPC_CONTROL, 1, 1); | 2390 | return !!REG_GET(DISPC_CONTROL, 1, 1); |
2088 | else if (channel == OMAP_DSS_CHANNEL_LCD2) | 2391 | else if (channel == OMAP_DSS_CHANNEL_LCD2) |
2089 | return !!REG_GET(DISPC_CONTROL2, 0, 0); | 2392 | return !!REG_GET(DISPC_CONTROL2, 0, 0); |
2090 | else | 2393 | else { |
2091 | BUG(); | 2394 | BUG(); |
2395 | return false; | ||
2396 | } | ||
2092 | } | 2397 | } |
2093 | 2398 | ||
2094 | void dispc_mgr_enable(enum omap_channel channel, bool enable) | 2399 | void dispc_mgr_enable(enum omap_channel channel, bool enable) |
@@ -2285,6 +2590,12 @@ void dispc_mgr_enable_stallmode(enum omap_channel channel, bool enable) | |||
2285 | REG_FLD_MOD(DISPC_CONTROL, enable, 11, 11); | 2590 | REG_FLD_MOD(DISPC_CONTROL, enable, 11, 11); |
2286 | } | 2591 | } |
2287 | 2592 | ||
2593 | static bool _dispc_mgr_size_ok(u16 width, u16 height) | ||
2594 | { | ||
2595 | return width <= dss_feat_get_param_max(FEAT_PARAM_MGR_WIDTH) && | ||
2596 | height <= dss_feat_get_param_max(FEAT_PARAM_MGR_HEIGHT); | ||
2597 | } | ||
2598 | |||
2288 | static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp, | 2599 | static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp, |
2289 | int vsw, int vfp, int vbp) | 2600 | int vsw, int vfp, int vbp) |
2290 | { | 2601 | { |
@@ -2309,11 +2620,20 @@ static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp, | |||
2309 | return true; | 2620 | return true; |
2310 | } | 2621 | } |
2311 | 2622 | ||
2312 | bool dispc_lcd_timings_ok(struct omap_video_timings *timings) | 2623 | bool dispc_mgr_timings_ok(enum omap_channel channel, |
2624 | const struct omap_video_timings *timings) | ||
2313 | { | 2625 | { |
2314 | return _dispc_lcd_timings_ok(timings->hsw, timings->hfp, | 2626 | bool timings_ok; |
2315 | timings->hbp, timings->vsw, | 2627 | |
2316 | timings->vfp, timings->vbp); | 2628 | timings_ok = _dispc_mgr_size_ok(timings->x_res, timings->y_res); |
2629 | |||
2630 | if (dispc_mgr_is_lcd(channel)) | ||
2631 | timings_ok = timings_ok && _dispc_lcd_timings_ok(timings->hsw, | ||
2632 | timings->hfp, timings->hbp, | ||
2633 | timings->vsw, timings->vfp, | ||
2634 | timings->vbp); | ||
2635 | |||
2636 | return timings_ok; | ||
2317 | } | 2637 | } |
2318 | 2638 | ||
2319 | static void _dispc_mgr_set_lcd_timings(enum omap_channel channel, int hsw, | 2639 | static void _dispc_mgr_set_lcd_timings(enum omap_channel channel, int hsw, |
@@ -2340,37 +2660,45 @@ static void _dispc_mgr_set_lcd_timings(enum omap_channel channel, int hsw, | |||
2340 | } | 2660 | } |
2341 | 2661 | ||
2342 | /* change name to mode? */ | 2662 | /* change name to mode? */ |
2343 | void dispc_mgr_set_lcd_timings(enum omap_channel channel, | 2663 | void dispc_mgr_set_timings(enum omap_channel channel, |
2344 | struct omap_video_timings *timings) | 2664 | struct omap_video_timings *timings) |
2345 | { | 2665 | { |
2346 | unsigned xtot, ytot; | 2666 | unsigned xtot, ytot; |
2347 | unsigned long ht, vt; | 2667 | unsigned long ht, vt; |
2668 | struct omap_video_timings t = *timings; | ||
2669 | |||
2670 | DSSDBG("channel %d xres %u yres %u\n", channel, t.x_res, t.y_res); | ||
2348 | 2671 | ||
2349 | if (!_dispc_lcd_timings_ok(timings->hsw, timings->hfp, | 2672 | if (!dispc_mgr_timings_ok(channel, &t)) { |
2350 | timings->hbp, timings->vsw, | ||
2351 | timings->vfp, timings->vbp)) | ||
2352 | BUG(); | 2673 | BUG(); |
2674 | return; | ||
2675 | } | ||
2676 | |||
2677 | if (dispc_mgr_is_lcd(channel)) { | ||
2678 | _dispc_mgr_set_lcd_timings(channel, t.hsw, t.hfp, t.hbp, t.vsw, | ||
2679 | t.vfp, t.vbp); | ||
2680 | |||
2681 | xtot = t.x_res + t.hfp + t.hsw + t.hbp; | ||
2682 | ytot = t.y_res + t.vfp + t.vsw + t.vbp; | ||
2353 | 2683 | ||
2354 | _dispc_mgr_set_lcd_timings(channel, timings->hsw, timings->hfp, | 2684 | ht = (timings->pixel_clock * 1000) / xtot; |
2355 | timings->hbp, timings->vsw, timings->vfp, | 2685 | vt = (timings->pixel_clock * 1000) / xtot / ytot; |
2356 | timings->vbp); | ||
2357 | 2686 | ||
2358 | dispc_mgr_set_lcd_size(channel, timings->x_res, timings->y_res); | 2687 | DSSDBG("pck %u\n", timings->pixel_clock); |
2688 | DSSDBG("hsw %d hfp %d hbp %d vsw %d vfp %d vbp %d\n", | ||
2689 | t.hsw, t.hfp, t.hbp, t.vsw, t.vfp, t.vbp); | ||
2359 | 2690 | ||
2360 | xtot = timings->x_res + timings->hfp + timings->hsw + timings->hbp; | 2691 | DSSDBG("hsync %luHz, vsync %luHz\n", ht, vt); |
2361 | ytot = timings->y_res + timings->vfp + timings->vsw + timings->vbp; | 2692 | } else { |
2693 | enum dss_hdmi_venc_clk_source_select source; | ||
2362 | 2694 | ||
2363 | ht = (timings->pixel_clock * 1000) / xtot; | 2695 | source = dss_get_hdmi_venc_clk_source(); |
2364 | vt = (timings->pixel_clock * 1000) / xtot / ytot; | ||
2365 | 2696 | ||
2366 | DSSDBG("channel %d xres %u yres %u\n", channel, timings->x_res, | 2697 | if (source == DSS_VENC_TV_CLK) |
2367 | timings->y_res); | 2698 | t.y_res /= 2; |
2368 | DSSDBG("pck %u\n", timings->pixel_clock); | 2699 | } |
2369 | DSSDBG("hsw %d hfp %d hbp %d vsw %d vfp %d vbp %d\n", | ||
2370 | timings->hsw, timings->hfp, timings->hbp, | ||
2371 | timings->vsw, timings->vfp, timings->vbp); | ||
2372 | 2700 | ||
2373 | DSSDBG("hsync %luHz, vsync %luHz\n", ht, vt); | 2701 | dispc_mgr_set_size(channel, t.x_res, t.y_res); |
2374 | } | 2702 | } |
2375 | 2703 | ||
2376 | static void dispc_mgr_set_lcd_divisor(enum omap_channel channel, u16 lck_div, | 2704 | static void dispc_mgr_set_lcd_divisor(enum omap_channel channel, u16 lck_div, |
@@ -2411,6 +2739,7 @@ unsigned long dispc_fclk_rate(void) | |||
2411 | break; | 2739 | break; |
2412 | default: | 2740 | default: |
2413 | BUG(); | 2741 | BUG(); |
2742 | return 0; | ||
2414 | } | 2743 | } |
2415 | 2744 | ||
2416 | return r; | 2745 | return r; |
@@ -2441,6 +2770,7 @@ unsigned long dispc_mgr_lclk_rate(enum omap_channel channel) | |||
2441 | break; | 2770 | break; |
2442 | default: | 2771 | default: |
2443 | BUG(); | 2772 | BUG(); |
2773 | return 0; | ||
2444 | } | 2774 | } |
2445 | 2775 | ||
2446 | return r / lcd; | 2776 | return r / lcd; |
@@ -2462,20 +2792,35 @@ unsigned long dispc_mgr_pclk_rate(enum omap_channel channel) | |||
2462 | 2792 | ||
2463 | return r / pcd; | 2793 | return r / pcd; |
2464 | } else { | 2794 | } else { |
2465 | struct omap_dss_device *dssdev = | 2795 | enum dss_hdmi_venc_clk_source_select source; |
2466 | dispc_mgr_get_device(channel); | ||
2467 | 2796 | ||
2468 | switch (dssdev->type) { | 2797 | source = dss_get_hdmi_venc_clk_source(); |
2469 | case OMAP_DISPLAY_TYPE_VENC: | 2798 | |
2799 | switch (source) { | ||
2800 | case DSS_VENC_TV_CLK: | ||
2470 | return venc_get_pixel_clock(); | 2801 | return venc_get_pixel_clock(); |
2471 | case OMAP_DISPLAY_TYPE_HDMI: | 2802 | case DSS_HDMI_M_PCLK: |
2472 | return hdmi_get_pixel_clock(); | 2803 | return hdmi_get_pixel_clock(); |
2473 | default: | 2804 | default: |
2474 | BUG(); | 2805 | BUG(); |
2806 | return 0; | ||
2475 | } | 2807 | } |
2476 | } | 2808 | } |
2477 | } | 2809 | } |
2478 | 2810 | ||
2811 | unsigned long dispc_core_clk_rate(void) | ||
2812 | { | ||
2813 | int lcd; | ||
2814 | unsigned long fclk = dispc_fclk_rate(); | ||
2815 | |||
2816 | if (dss_has_feature(FEAT_CORE_CLK_DIV)) | ||
2817 | lcd = REG_GET(DISPC_DIVISOR, 23, 16); | ||
2818 | else | ||
2819 | lcd = REG_GET(DISPC_DIVISORo(OMAP_DSS_CHANNEL_LCD), 23, 16); | ||
2820 | |||
2821 | return fclk / lcd; | ||
2822 | } | ||
2823 | |||
2479 | void dispc_dump_clocks(struct seq_file *s) | 2824 | void dispc_dump_clocks(struct seq_file *s) |
2480 | { | 2825 | { |
2481 | int lcd, pcd; | 2826 | int lcd, pcd; |
@@ -2588,7 +2933,7 @@ void dispc_dump_irqs(struct seq_file *s) | |||
2588 | } | 2933 | } |
2589 | #endif | 2934 | #endif |
2590 | 2935 | ||
2591 | void dispc_dump_regs(struct seq_file *s) | 2936 | static void dispc_dump_regs(struct seq_file *s) |
2592 | { | 2937 | { |
2593 | int i, j; | 2938 | int i, j; |
2594 | const char *mgr_names[] = { | 2939 | const char *mgr_names[] = { |
@@ -3247,27 +3592,6 @@ int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask, | |||
3247 | return 0; | 3592 | return 0; |
3248 | } | 3593 | } |
3249 | 3594 | ||
3250 | #ifdef CONFIG_OMAP2_DSS_FAKE_VSYNC | ||
3251 | void dispc_fake_vsync_irq(void) | ||
3252 | { | ||
3253 | u32 irqstatus = DISPC_IRQ_VSYNC; | ||
3254 | int i; | ||
3255 | |||
3256 | WARN_ON(!in_interrupt()); | ||
3257 | |||
3258 | for (i = 0; i < DISPC_MAX_NR_ISRS; i++) { | ||
3259 | struct omap_dispc_isr_data *isr_data; | ||
3260 | isr_data = &dispc.registered_isr[i]; | ||
3261 | |||
3262 | if (!isr_data->isr) | ||
3263 | continue; | ||
3264 | |||
3265 | if (isr_data->mask & irqstatus) | ||
3266 | isr_data->isr(isr_data->arg, irqstatus); | ||
3267 | } | ||
3268 | } | ||
3269 | #endif | ||
3270 | |||
3271 | static void _omap_dispc_initialize_irq(void) | 3595 | static void _omap_dispc_initialize_irq(void) |
3272 | { | 3596 | { |
3273 | unsigned long flags; | 3597 | unsigned long flags; |
@@ -3330,7 +3654,7 @@ static void _omap_dispc_initial_config(void) | |||
3330 | } | 3654 | } |
3331 | 3655 | ||
3332 | /* DISPC HW IP initialisation */ | 3656 | /* DISPC HW IP initialisation */ |
3333 | static int omap_dispchw_probe(struct platform_device *pdev) | 3657 | static int __init omap_dispchw_probe(struct platform_device *pdev) |
3334 | { | 3658 | { |
3335 | u32 rev; | 3659 | u32 rev; |
3336 | int r = 0; | 3660 | int r = 0; |
@@ -3399,6 +3723,11 @@ static int omap_dispchw_probe(struct platform_device *pdev) | |||
3399 | 3723 | ||
3400 | dispc_runtime_put(); | 3724 | dispc_runtime_put(); |
3401 | 3725 | ||
3726 | dss_debugfs_create_file("dispc", dispc_dump_regs); | ||
3727 | |||
3728 | #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS | ||
3729 | dss_debugfs_create_file("dispc_irq", dispc_dump_irqs); | ||
3730 | #endif | ||
3402 | return 0; | 3731 | return 0; |
3403 | 3732 | ||
3404 | err_runtime_get: | 3733 | err_runtime_get: |
@@ -3407,7 +3736,7 @@ err_runtime_get: | |||
3407 | return r; | 3736 | return r; |
3408 | } | 3737 | } |
3409 | 3738 | ||
3410 | static int omap_dispchw_remove(struct platform_device *pdev) | 3739 | static int __exit omap_dispchw_remove(struct platform_device *pdev) |
3411 | { | 3740 | { |
3412 | pm_runtime_disable(&pdev->dev); | 3741 | pm_runtime_disable(&pdev->dev); |
3413 | 3742 | ||
@@ -3419,19 +3748,12 @@ static int omap_dispchw_remove(struct platform_device *pdev) | |||
3419 | static int dispc_runtime_suspend(struct device *dev) | 3748 | static int dispc_runtime_suspend(struct device *dev) |
3420 | { | 3749 | { |
3421 | dispc_save_context(); | 3750 | dispc_save_context(); |
3422 | dss_runtime_put(); | ||
3423 | 3751 | ||
3424 | return 0; | 3752 | return 0; |
3425 | } | 3753 | } |
3426 | 3754 | ||
3427 | static int dispc_runtime_resume(struct device *dev) | 3755 | static int dispc_runtime_resume(struct device *dev) |
3428 | { | 3756 | { |
3429 | int r; | ||
3430 | |||
3431 | r = dss_runtime_get(); | ||
3432 | if (r < 0) | ||
3433 | return r; | ||
3434 | |||
3435 | dispc_restore_context(); | 3757 | dispc_restore_context(); |
3436 | 3758 | ||
3437 | return 0; | 3759 | return 0; |
@@ -3443,8 +3765,7 @@ static const struct dev_pm_ops dispc_pm_ops = { | |||
3443 | }; | 3765 | }; |
3444 | 3766 | ||
3445 | static struct platform_driver omap_dispchw_driver = { | 3767 | static struct platform_driver omap_dispchw_driver = { |
3446 | .probe = omap_dispchw_probe, | 3768 | .remove = __exit_p(omap_dispchw_remove), |
3447 | .remove = omap_dispchw_remove, | ||
3448 | .driver = { | 3769 | .driver = { |
3449 | .name = "omapdss_dispc", | 3770 | .name = "omapdss_dispc", |
3450 | .owner = THIS_MODULE, | 3771 | .owner = THIS_MODULE, |
@@ -3452,12 +3773,12 @@ static struct platform_driver omap_dispchw_driver = { | |||
3452 | }, | 3773 | }, |
3453 | }; | 3774 | }; |
3454 | 3775 | ||
3455 | int dispc_init_platform_driver(void) | 3776 | int __init dispc_init_platform_driver(void) |
3456 | { | 3777 | { |
3457 | return platform_driver_register(&omap_dispchw_driver); | 3778 | return platform_driver_probe(&omap_dispchw_driver, omap_dispchw_probe); |
3458 | } | 3779 | } |
3459 | 3780 | ||
3460 | void dispc_uninit_platform_driver(void) | 3781 | void __exit dispc_uninit_platform_driver(void) |
3461 | { | 3782 | { |
3462 | return platform_driver_unregister(&omap_dispchw_driver); | 3783 | platform_driver_unregister(&omap_dispchw_driver); |
3463 | } | 3784 | } |