aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/omap2/dss/rfbi.c
diff options
context:
space:
mode:
authorTomi Valkeinen <tomi.valkeinen@nokia.com>2010-01-12 07:16:41 -0500
committerTomi Valkeinen <tomi.valkeinen@nokia.com>2010-02-24 07:31:28 -0500
commit18946f62c6cc8cf051bafca8b7fa72309e8a1067 (patch)
treef1e33d76a571ebc4580b15c1b7ba1bec8e441cf6 /drivers/video/omap2/dss/rfbi.c
parent446f7bff703f5f82560afde90fb22b7a1d366bbc (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.c290
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
43struct rfbi_reg { u16 idx; }; 41struct 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
103static int rfbi_convert_timings(struct rfbi_timings *t); 99static int rfbi_convert_timings(struct rfbi_timings *t);
104static void rfbi_get_clk_info(u32 *clk_period, u32 *max_clk_div); 100static void rfbi_get_clk_info(u32 *clk_period, u32 *max_clk_div);
105static void process_cmd_fifo(void);
106 101
107static struct { 102static 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
135struct update_region { 125struct update_region {
@@ -139,16 +129,6 @@ struct update_region {
139 u16 h; 129 u16 h;
140}; 130};
141 131
142struct 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
152static inline void rfbi_write_reg(const struct rfbi_reg idx, u32 val) 132static 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}
322EXPORT_SYMBOL(omap_rfbi_write_pixels); 302EXPORT_SYMBOL(omap_rfbi_write_pixels);
323 303
324#ifdef MEASURE_PERF
325static void perf_mark_setup(void)
326{
327 rfbi.perf_setup_time = ktime_get();
328}
329
330static void perf_mark_start(void)
331{
332 rfbi.perf_start_time = ktime_get();
333}
334
335static 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
373void rfbi_transfer_area(u16 width, u16 height, 304void 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}
938EXPORT_SYMBOL(rfbi_configure); 864EXPORT_SYMBOL(rfbi_configure);
939 865
940static int rfbi_find_display(struct omap_dss_device *dssdev) 866int 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
953static 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)
963static 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 895EXPORT_SYMBOL(omap_rfbi_prepare_update);
980
981 dssdev->driver->setup_update(dssdev, x, y, w, h);
982 896
897int 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
1003static 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
1047static 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
1081static 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
1100static 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}
919EXPORT_SYMBOL(omap_rfbi_update);
1114 920
1115void rfbi_dump_regs(struct seq_file *s) 921void 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 */
1205static 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
1220static 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
1235static int rfbi_display_enable(struct omap_dss_device *dssdev) 1005static 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