diff options
author | Tomi Valkeinen <tomi.valkeinen@nokia.com> | 2010-01-12 07:16:41 -0500 |
---|---|---|
committer | Tomi Valkeinen <tomi.valkeinen@nokia.com> | 2010-02-24 07:31:28 -0500 |
commit | 18946f62c6cc8cf051bafca8b7fa72309e8a1067 (patch) | |
tree | f1e33d76a571ebc4580b15c1b7ba1bec8e441cf6 /drivers/video/omap2/dss/rfbi.c | |
parent | 446f7bff703f5f82560afde90fb22b7a1d366bbc (diff) |
OMAP: DSS2: move update() and sync()
Move update() and sync() from omap_dss_device to omap_dss_driver.
Also, update was hardcoded to use virtual channel 0. This patch adds a
parameter that specifies the VC.
This is part of a larger patch-set, which moves the control from omapdss
driver to the display driver.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
Diffstat (limited to 'drivers/video/omap2/dss/rfbi.c')
-rw-r--r-- | drivers/video/omap2/dss/rfbi.c | 290 |
1 files changed, 29 insertions, 261 deletions
diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c index 71293876fed1..a6b33160666a 100644 --- a/drivers/video/omap2/dss/rfbi.c +++ b/drivers/video/omap2/dss/rfbi.c | |||
@@ -36,8 +36,6 @@ | |||
36 | #include <plat/display.h> | 36 | #include <plat/display.h> |
37 | #include "dss.h" | 37 | #include "dss.h" |
38 | 38 | ||
39 | /*#define MEASURE_PERF*/ | ||
40 | |||
41 | #define RFBI_BASE 0x48050800 | 39 | #define RFBI_BASE 0x48050800 |
42 | 40 | ||
43 | struct rfbi_reg { u16 idx; }; | 41 | struct rfbi_reg { u16 idx; }; |
@@ -66,8 +64,6 @@ struct rfbi_reg { u16 idx; }; | |||
66 | #define RFBI_VSYNC_WIDTH RFBI_REG(0x0090) | 64 | #define RFBI_VSYNC_WIDTH RFBI_REG(0x0090) |
67 | #define RFBI_HSYNC_WIDTH RFBI_REG(0x0094) | 65 | #define RFBI_HSYNC_WIDTH RFBI_REG(0x0094) |
68 | 66 | ||
69 | #define RFBI_CMD_FIFO_LEN_BYTES (16 * sizeof(struct update_param)) | ||
70 | |||
71 | #define REG_FLD_MOD(idx, val, start, end) \ | 67 | #define REG_FLD_MOD(idx, val, start, end) \ |
72 | rfbi_write_reg(idx, FLD_MOD(rfbi_read_reg(idx), val, start, end)) | 68 | rfbi_write_reg(idx, FLD_MOD(rfbi_read_reg(idx), val, start, end)) |
73 | 69 | ||
@@ -102,7 +98,6 @@ enum update_cmd { | |||
102 | 98 | ||
103 | static int rfbi_convert_timings(struct rfbi_timings *t); | 99 | static int rfbi_convert_timings(struct rfbi_timings *t); |
104 | static void rfbi_get_clk_info(u32 *clk_period, u32 *max_clk_div); | 100 | static void rfbi_get_clk_info(u32 *clk_period, u32 *max_clk_div); |
105 | static void process_cmd_fifo(void); | ||
106 | 101 | ||
107 | static struct { | 102 | static struct { |
108 | void __iomem *base; | 103 | void __iomem *base; |
@@ -125,11 +120,6 @@ static struct { | |||
125 | struct completion cmd_done; | 120 | struct completion cmd_done; |
126 | atomic_t cmd_fifo_full; | 121 | atomic_t cmd_fifo_full; |
127 | atomic_t cmd_pending; | 122 | atomic_t cmd_pending; |
128 | #ifdef MEASURE_PERF | ||
129 | unsigned perf_bytes; | ||
130 | ktime_t perf_setup_time; | ||
131 | ktime_t perf_start_time; | ||
132 | #endif | ||
133 | } rfbi; | 123 | } rfbi; |
134 | 124 | ||
135 | struct update_region { | 125 | struct update_region { |
@@ -139,16 +129,6 @@ struct update_region { | |||
139 | u16 h; | 129 | u16 h; |
140 | }; | 130 | }; |
141 | 131 | ||
142 | struct update_param { | ||
143 | u8 rfbi_module; | ||
144 | u8 cmd; | ||
145 | |||
146 | union { | ||
147 | struct update_region r; | ||
148 | struct completion *sync; | ||
149 | } par; | ||
150 | }; | ||
151 | |||
152 | static inline void rfbi_write_reg(const struct rfbi_reg idx, u32 val) | 132 | static inline void rfbi_write_reg(const struct rfbi_reg idx, u32 val) |
153 | { | 133 | { |
154 | __raw_writel(val, rfbi.base + idx.idx); | 134 | __raw_writel(val, rfbi.base + idx.idx); |
@@ -321,55 +301,6 @@ void omap_rfbi_write_pixels(const void __iomem *buf, int scr_width, | |||
321 | } | 301 | } |
322 | EXPORT_SYMBOL(omap_rfbi_write_pixels); | 302 | EXPORT_SYMBOL(omap_rfbi_write_pixels); |
323 | 303 | ||
324 | #ifdef MEASURE_PERF | ||
325 | static void perf_mark_setup(void) | ||
326 | { | ||
327 | rfbi.perf_setup_time = ktime_get(); | ||
328 | } | ||
329 | |||
330 | static void perf_mark_start(void) | ||
331 | { | ||
332 | rfbi.perf_start_time = ktime_get(); | ||
333 | } | ||
334 | |||
335 | static void perf_show(const char *name) | ||
336 | { | ||
337 | ktime_t t, setup_time, trans_time; | ||
338 | u32 total_bytes; | ||
339 | u32 setup_us, trans_us, total_us; | ||
340 | |||
341 | t = ktime_get(); | ||
342 | |||
343 | setup_time = ktime_sub(rfbi.perf_start_time, rfbi.perf_setup_time); | ||
344 | setup_us = (u32)ktime_to_us(setup_time); | ||
345 | if (setup_us == 0) | ||
346 | setup_us = 1; | ||
347 | |||
348 | trans_time = ktime_sub(t, rfbi.perf_start_time); | ||
349 | trans_us = (u32)ktime_to_us(trans_time); | ||
350 | if (trans_us == 0) | ||
351 | trans_us = 1; | ||
352 | |||
353 | total_us = setup_us + trans_us; | ||
354 | |||
355 | total_bytes = rfbi.perf_bytes; | ||
356 | |||
357 | DSSINFO("%s update %u us + %u us = %u us (%uHz), %u bytes, " | ||
358 | "%u kbytes/sec\n", | ||
359 | name, | ||
360 | setup_us, | ||
361 | trans_us, | ||
362 | total_us, | ||
363 | 1000*1000 / total_us, | ||
364 | total_bytes, | ||
365 | total_bytes * 1000 / total_us); | ||
366 | } | ||
367 | #else | ||
368 | #define perf_mark_setup() | ||
369 | #define perf_mark_start() | ||
370 | #define perf_show(x) | ||
371 | #endif | ||
372 | |||
373 | void rfbi_transfer_area(u16 width, u16 height, | 304 | void rfbi_transfer_area(u16 width, u16 height, |
374 | void (callback)(void *data), void *data) | 305 | void (callback)(void *data), void *data) |
375 | { | 306 | { |
@@ -396,8 +327,6 @@ void rfbi_transfer_area(u16 width, u16 height, | |||
396 | if (!rfbi.te_enabled) | 327 | if (!rfbi.te_enabled) |
397 | l = FLD_MOD(l, 1, 4, 4); /* ITE */ | 328 | l = FLD_MOD(l, 1, 4, 4); /* ITE */ |
398 | 329 | ||
399 | perf_mark_start(); | ||
400 | |||
401 | rfbi_write_reg(RFBI_CONTROL, l); | 330 | rfbi_write_reg(RFBI_CONTROL, l); |
402 | } | 331 | } |
403 | 332 | ||
@@ -407,8 +336,6 @@ static void framedone_callback(void *data, u32 mask) | |||
407 | 336 | ||
408 | DSSDBG("FRAMEDONE\n"); | 337 | DSSDBG("FRAMEDONE\n"); |
409 | 338 | ||
410 | perf_show("DISPC"); | ||
411 | |||
412 | REG_FLD_MOD(RFBI_CONTROL, 0, 0, 0); | 339 | REG_FLD_MOD(RFBI_CONTROL, 0, 0, 0); |
413 | 340 | ||
414 | rfbi_enable_clocks(0); | 341 | rfbi_enable_clocks(0); |
@@ -416,11 +343,10 @@ static void framedone_callback(void *data, u32 mask) | |||
416 | callback = rfbi.framedone_callback; | 343 | callback = rfbi.framedone_callback; |
417 | rfbi.framedone_callback = NULL; | 344 | rfbi.framedone_callback = NULL; |
418 | 345 | ||
419 | /*callback(rfbi.framedone_callback_data);*/ | 346 | if (callback != NULL) |
347 | callback(rfbi.framedone_callback_data); | ||
420 | 348 | ||
421 | atomic_set(&rfbi.cmd_pending, 0); | 349 | atomic_set(&rfbi.cmd_pending, 0); |
422 | |||
423 | process_cmd_fifo(); | ||
424 | } | 350 | } |
425 | 351 | ||
426 | #if 1 /* VERBOSE */ | 352 | #if 1 /* VERBOSE */ |
@@ -937,52 +863,43 @@ int rfbi_configure(int rfbi_module, int bpp, int lines) | |||
937 | } | 863 | } |
938 | EXPORT_SYMBOL(rfbi_configure); | 864 | EXPORT_SYMBOL(rfbi_configure); |
939 | 865 | ||
940 | static int rfbi_find_display(struct omap_dss_device *dssdev) | 866 | int omap_rfbi_prepare_update(struct omap_dss_device *dssdev, |
867 | u16 *x, u16 *y, u16 *w, u16 *h) | ||
941 | { | 868 | { |
942 | if (dssdev == rfbi.dssdev[0]) | 869 | u16 dw, dh; |
943 | return 0; | ||
944 | 870 | ||
945 | if (dssdev == rfbi.dssdev[1]) | 871 | dssdev->driver->get_resolution(dssdev, &dw, &dh); |
946 | return 1; | ||
947 | 872 | ||
948 | BUG(); | 873 | if (*x > dw || *y > dh) |
949 | return -1; | 874 | return -EINVAL; |
950 | } | ||
951 | 875 | ||
876 | if (*x + *w > dw) | ||
877 | return -EINVAL; | ||
952 | 878 | ||
953 | static void signal_fifo_waiters(void) | 879 | if (*y + *h > dh) |
954 | { | 880 | return -EINVAL; |
955 | if (atomic_read(&rfbi.cmd_fifo_full) > 0) { | ||
956 | /* DSSDBG("SIGNALING: Fifo not full for waiter!\n"); */ | ||
957 | complete(&rfbi.cmd_done); | ||
958 | atomic_dec(&rfbi.cmd_fifo_full); | ||
959 | } | ||
960 | } | ||
961 | 881 | ||
962 | /* returns 1 for async op, and 0 for sync op */ | 882 | if (*w == 1) |
963 | static int do_update(struct omap_dss_device *dssdev, struct update_region *upd) | 883 | return -EINVAL; |
964 | { | ||
965 | u16 x = upd->x; | ||
966 | u16 y = upd->y; | ||
967 | u16 w = upd->w; | ||
968 | u16 h = upd->h; | ||
969 | 884 | ||
970 | perf_mark_setup(); | 885 | if (*w == 0 || *h == 0) |
886 | return -EINVAL; | ||
971 | 887 | ||
972 | if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) { | 888 | if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) { |
973 | /*dssdev->driver->enable_te(dssdev, 1); */ | 889 | dss_setup_partial_planes(dssdev, x, y, w, h); |
974 | dss_setup_partial_planes(dssdev, &x, &y, &w, &h); | 890 | dispc_set_lcd_size(*w, *h); |
975 | } | 891 | } |
976 | 892 | ||
977 | #ifdef MEASURE_PERF | 893 | return 0; |
978 | rfbi.perf_bytes = w * h * 2; /* XXX always 16bit */ | 894 | } |
979 | #endif | 895 | EXPORT_SYMBOL(omap_rfbi_prepare_update); |
980 | |||
981 | dssdev->driver->setup_update(dssdev, x, y, w, h); | ||
982 | 896 | ||
897 | int omap_rfbi_update(struct omap_dss_device *dssdev, | ||
898 | u16 x, u16 y, u16 w, u16 h, | ||
899 | void (*callback)(void *), void *data) | ||
900 | { | ||
983 | if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) { | 901 | if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) { |
984 | rfbi_transfer_area(w, h, NULL, NULL); | 902 | rfbi_transfer_area(w, h, callback, data); |
985 | return 1; | ||
986 | } else { | 903 | } else { |
987 | struct omap_overlay *ovl; | 904 | struct omap_overlay *ovl; |
988 | void __iomem *addr; | 905 | void __iomem *addr; |
@@ -994,123 +911,12 @@ static int do_update(struct omap_dss_device *dssdev, struct update_region *upd) | |||
994 | 911 | ||
995 | omap_rfbi_write_pixels(addr, scr_width, x, y, w, h); | 912 | omap_rfbi_write_pixels(addr, scr_width, x, y, w, h); |
996 | 913 | ||
997 | perf_show("L4"); | 914 | callback(data); |
998 | |||
999 | return 0; | ||
1000 | } | ||
1001 | } | ||
1002 | |||
1003 | static void process_cmd_fifo(void) | ||
1004 | { | ||
1005 | int len; | ||
1006 | struct update_param p; | ||
1007 | struct omap_dss_device *dssdev; | ||
1008 | unsigned long flags; | ||
1009 | |||
1010 | if (atomic_inc_return(&rfbi.cmd_pending) != 1) | ||
1011 | return; | ||
1012 | |||
1013 | while (true) { | ||
1014 | spin_lock_irqsave(&rfbi.cmd_lock, flags); | ||
1015 | |||
1016 | len = kfifo_out(&rfbi.cmd_fifo, (unsigned char *)&p, | ||
1017 | sizeof(struct update_param)); | ||
1018 | if (len == 0) { | ||
1019 | DSSDBG("nothing more in fifo\n"); | ||
1020 | atomic_set(&rfbi.cmd_pending, 0); | ||
1021 | spin_unlock_irqrestore(&rfbi.cmd_lock, flags); | ||
1022 | break; | ||
1023 | } | ||
1024 | |||
1025 | /* DSSDBG("fifo full %d\n", rfbi.cmd_fifo_full.counter);*/ | ||
1026 | |||
1027 | spin_unlock_irqrestore(&rfbi.cmd_lock, flags); | ||
1028 | |||
1029 | BUG_ON(len != sizeof(struct update_param)); | ||
1030 | BUG_ON(p.rfbi_module > 1); | ||
1031 | |||
1032 | dssdev = rfbi.dssdev[p.rfbi_module]; | ||
1033 | |||
1034 | if (p.cmd == RFBI_CMD_UPDATE) { | ||
1035 | if (do_update(dssdev, &p.par.r)) | ||
1036 | break; /* async op */ | ||
1037 | } else if (p.cmd == RFBI_CMD_SYNC) { | ||
1038 | DSSDBG("Signaling SYNC done!\n"); | ||
1039 | complete(p.par.sync); | ||
1040 | } else | ||
1041 | BUG(); | ||
1042 | } | 915 | } |
1043 | 916 | ||
1044 | signal_fifo_waiters(); | 917 | return 0; |
1045 | } | ||
1046 | |||
1047 | static void rfbi_push_cmd(struct update_param *p) | ||
1048 | { | ||
1049 | int ret; | ||
1050 | |||
1051 | while (1) { | ||
1052 | unsigned long flags; | ||
1053 | int available; | ||
1054 | |||
1055 | spin_lock_irqsave(&rfbi.cmd_lock, flags); | ||
1056 | available = RFBI_CMD_FIFO_LEN_BYTES - | ||
1057 | kfifo_len(&rfbi.cmd_fifo); | ||
1058 | |||
1059 | /* DSSDBG("%d bytes left in fifo\n", available); */ | ||
1060 | if (available < sizeof(struct update_param)) { | ||
1061 | DSSDBG("Going to wait because FIFO FULL..\n"); | ||
1062 | spin_unlock_irqrestore(&rfbi.cmd_lock, flags); | ||
1063 | atomic_inc(&rfbi.cmd_fifo_full); | ||
1064 | wait_for_completion(&rfbi.cmd_done); | ||
1065 | /*DSSDBG("Woke up because fifo not full anymore\n");*/ | ||
1066 | continue; | ||
1067 | } | ||
1068 | |||
1069 | ret = kfifo_in(&rfbi.cmd_fifo, (unsigned char *)p, | ||
1070 | sizeof(struct update_param)); | ||
1071 | /* DSSDBG("pushed %d bytes\n", ret);*/ | ||
1072 | |||
1073 | spin_unlock_irqrestore(&rfbi.cmd_lock, flags); | ||
1074 | |||
1075 | BUG_ON(ret != sizeof(struct update_param)); | ||
1076 | |||
1077 | break; | ||
1078 | } | ||
1079 | } | ||
1080 | |||
1081 | static void rfbi_push_update(int rfbi_module, int x, int y, int w, int h) | ||
1082 | { | ||
1083 | struct update_param p; | ||
1084 | |||
1085 | p.rfbi_module = rfbi_module; | ||
1086 | p.cmd = RFBI_CMD_UPDATE; | ||
1087 | |||
1088 | p.par.r.x = x; | ||
1089 | p.par.r.y = y; | ||
1090 | p.par.r.w = w; | ||
1091 | p.par.r.h = h; | ||
1092 | |||
1093 | DSSDBG("RFBI pushed %d,%d %dx%d\n", x, y, w, h); | ||
1094 | |||
1095 | rfbi_push_cmd(&p); | ||
1096 | |||
1097 | process_cmd_fifo(); | ||
1098 | } | ||
1099 | |||
1100 | static void rfbi_push_sync(int rfbi_module, struct completion *sync_comp) | ||
1101 | { | ||
1102 | struct update_param p; | ||
1103 | |||
1104 | p.rfbi_module = rfbi_module; | ||
1105 | p.cmd = RFBI_CMD_SYNC; | ||
1106 | p.par.sync = sync_comp; | ||
1107 | |||
1108 | rfbi_push_cmd(&p); | ||
1109 | |||
1110 | DSSDBG("RFBI sync pushed to cmd fifo\n"); | ||
1111 | |||
1112 | process_cmd_fifo(); | ||
1113 | } | 918 | } |
919 | EXPORT_SYMBOL(omap_rfbi_update); | ||
1114 | 920 | ||
1115 | void rfbi_dump_regs(struct seq_file *s) | 921 | void rfbi_dump_regs(struct seq_file *s) |
1116 | { | 922 | { |
@@ -1155,12 +961,8 @@ int rfbi_init(void) | |||
1155 | { | 961 | { |
1156 | u32 rev; | 962 | u32 rev; |
1157 | u32 l; | 963 | u32 l; |
1158 | int r; | ||
1159 | 964 | ||
1160 | spin_lock_init(&rfbi.cmd_lock); | 965 | spin_lock_init(&rfbi.cmd_lock); |
1161 | r = kfifo_alloc(&rfbi.cmd_fifo, RFBI_CMD_FIFO_LEN_BYTES, GFP_KERNEL); | ||
1162 | if (r) | ||
1163 | return r; | ||
1164 | 966 | ||
1165 | init_completion(&rfbi.cmd_done); | 967 | init_completion(&rfbi.cmd_done); |
1166 | atomic_set(&rfbi.cmd_fifo_full, 0); | 968 | atomic_set(&rfbi.cmd_fifo_full, 0); |
@@ -1196,42 +998,10 @@ void rfbi_exit(void) | |||
1196 | { | 998 | { |
1197 | DSSDBG("rfbi_exit\n"); | 999 | DSSDBG("rfbi_exit\n"); |
1198 | 1000 | ||
1199 | kfifo_free(&rfbi.cmd_fifo); | ||
1200 | |||
1201 | iounmap(rfbi.base); | 1001 | iounmap(rfbi.base); |
1202 | } | 1002 | } |
1203 | 1003 | ||
1204 | /* struct omap_display support */ | 1004 | /* struct omap_display support */ |
1205 | static int rfbi_display_update(struct omap_dss_device *dssdev, | ||
1206 | u16 x, u16 y, u16 w, u16 h) | ||
1207 | { | ||
1208 | int rfbi_module; | ||
1209 | |||
1210 | if (w == 0 || h == 0) | ||
1211 | return 0; | ||
1212 | |||
1213 | rfbi_module = rfbi_find_display(dssdev); | ||
1214 | |||
1215 | rfbi_push_update(rfbi_module, x, y, w, h); | ||
1216 | |||
1217 | return 0; | ||
1218 | } | ||
1219 | |||
1220 | static int rfbi_display_sync(struct omap_dss_device *dssdev) | ||
1221 | { | ||
1222 | struct completion sync_comp; | ||
1223 | int rfbi_module; | ||
1224 | |||
1225 | rfbi_module = rfbi_find_display(dssdev); | ||
1226 | |||
1227 | init_completion(&sync_comp); | ||
1228 | rfbi_push_sync(rfbi_module, &sync_comp); | ||
1229 | DSSDBG("Waiting for SYNC to happen...\n"); | ||
1230 | wait_for_completion(&sync_comp); | ||
1231 | DSSDBG("Released from SYNC\n"); | ||
1232 | return 0; | ||
1233 | } | ||
1234 | |||
1235 | static int rfbi_display_enable(struct omap_dss_device *dssdev) | 1005 | static int rfbi_display_enable(struct omap_dss_device *dssdev) |
1236 | { | 1006 | { |
1237 | int r; | 1007 | int r; |
@@ -1291,8 +1061,6 @@ int rfbi_init_display(struct omap_dss_device *dssdev) | |||
1291 | { | 1061 | { |
1292 | dssdev->enable = rfbi_display_enable; | 1062 | dssdev->enable = rfbi_display_enable; |
1293 | dssdev->disable = rfbi_display_disable; | 1063 | dssdev->disable = rfbi_display_disable; |
1294 | dssdev->update = rfbi_display_update; | ||
1295 | dssdev->sync = rfbi_display_sync; | ||
1296 | 1064 | ||
1297 | rfbi.dssdev[dssdev->phy.rfbi.channel] = dssdev; | 1065 | rfbi.dssdev[dssdev->phy.rfbi.channel] = dssdev; |
1298 | 1066 | ||