aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
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
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')
-rw-r--r--drivers/video/omap2/displays/panel-taal.c76
-rw-r--r--drivers/video/omap2/dss/dsi.c322
-rw-r--r--drivers/video/omap2/dss/rfbi.c290
-rw-r--r--drivers/video/omap2/omapfb/omapfb-ioctl.c10
-rw-r--r--drivers/video/omap2/omapfb/omapfb-main.c10
5 files changed, 208 insertions, 500 deletions
diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c
index 4ccb583b7b67..58293203fc05 100644
--- a/drivers/video/omap2/displays/panel-taal.c
+++ b/drivers/video/omap2/displays/panel-taal.c
@@ -725,10 +725,58 @@ static int taal_resume(struct omap_dss_device *dssdev)
725 return 0; 725 return 0;
726} 726}
727 727
728static void taal_setup_update(struct omap_dss_device *dssdev, 728static void taal_framedone_cb(int err, void *data)
729{
730 struct omap_dss_device *dssdev = data;
731 dev_dbg(&dssdev->dev, "framedone, err %d\n", err);
732 dsi_bus_unlock();
733}
734
735static int taal_update(struct omap_dss_device *dssdev,
729 u16 x, u16 y, u16 w, u16 h) 736 u16 x, u16 y, u16 w, u16 h)
730{ 737{
731 taal_set_update_window(x, y, w, h); 738 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
739 int r;
740
741 dev_dbg(&dssdev->dev, "update %d, %d, %d x %d\n", x, y, w, h);
742
743 dsi_bus_lock();
744
745 if (!td->enabled) {
746 r = 0;
747 goto err;
748 }
749
750 r = omap_dsi_prepare_update(dssdev, &x, &y, &w, &h);
751 if (r)
752 goto err;
753
754 r = taal_set_update_window(x, y, w, h);
755 if (r)
756 goto err;
757
758 r = omap_dsi_update(dssdev, TCH, x, y, w, h,
759 taal_framedone_cb, dssdev);
760 if (r)
761 goto err;
762
763 /* note: no bus_unlock here. unlock is in framedone_cb */
764 return 0;
765err:
766 dsi_bus_unlock();
767 return r;
768}
769
770static int taal_sync(struct omap_dss_device *dssdev)
771{
772 dev_dbg(&dssdev->dev, "sync\n");
773
774 dsi_bus_lock();
775 dsi_bus_unlock();
776
777 dev_dbg(&dssdev->dev, "sync done\n");
778
779 return 0;
732} 780}
733 781
734static int taal_enable_te(struct omap_dss_device *dssdev, bool enable) 782static int taal_enable_te(struct omap_dss_device *dssdev, bool enable)
@@ -762,24 +810,6 @@ static int taal_get_te(struct omap_dss_device *dssdev)
762 return td->te_enabled; 810 return td->te_enabled;
763} 811}
764 812
765static int taal_wait_te(struct omap_dss_device *dssdev)
766{
767 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
768 long wait = msecs_to_jiffies(500);
769
770 if (!td->use_ext_te || !td->te_enabled)
771 return 0;
772
773 INIT_COMPLETION(td->te_completion);
774 wait = wait_for_completion_timeout(&td->te_completion, wait);
775 if (wait == 0) {
776 dev_err(&dssdev->dev, "timeout waiting TE\n");
777 return -ETIME;
778 }
779
780 return 0;
781}
782
783static int taal_rotate(struct omap_dss_device *dssdev, u8 rotate) 813static int taal_rotate(struct omap_dss_device *dssdev, u8 rotate)
784{ 814{
785 struct taal_data *td = dev_get_drvdata(&dssdev->dev); 815 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
@@ -1018,15 +1048,17 @@ static struct omap_dss_driver taal_driver = {
1018 .suspend = taal_suspend, 1048 .suspend = taal_suspend,
1019 .resume = taal_resume, 1049 .resume = taal_resume,
1020 1050
1021 .setup_update = taal_setup_update,
1022 .set_update_mode = taal_set_update_mode, 1051 .set_update_mode = taal_set_update_mode,
1023 .get_update_mode = taal_get_update_mode, 1052 .get_update_mode = taal_get_update_mode,
1053
1054 .update = taal_update,
1055 .sync = taal_sync,
1056
1024 .get_resolution = taal_get_resolution, 1057 .get_resolution = taal_get_resolution,
1025 .get_recommended_bpp = omapdss_default_get_recommended_bpp, 1058 .get_recommended_bpp = omapdss_default_get_recommended_bpp,
1026 1059
1027 .enable_te = taal_enable_te, 1060 .enable_te = taal_enable_te,
1028 .get_te = taal_get_te, 1061 .get_te = taal_get_te,
1029 .wait_for_te = taal_wait_te,
1030 1062
1031 .set_rotate = taal_rotate, 1063 .set_rotate = taal_rotate,
1032 .get_rotate = taal_get_rotate, 1064 .get_rotate = taal_get_rotate,
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index b9fa62027f67..203b18bbddae 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -31,8 +31,8 @@
31#include <linux/seq_file.h> 31#include <linux/seq_file.h>
32#include <linux/platform_device.h> 32#include <linux/platform_device.h>
33#include <linux/regulator/consumer.h> 33#include <linux/regulator/consumer.h>
34#include <linux/kthread.h>
35#include <linux/wait.h> 34#include <linux/wait.h>
35#include <linux/workqueue.h>
36 36
37#include <plat/display.h> 37#include <plat/display.h>
38#include <plat/clock.h> 38#include <plat/clock.h>
@@ -200,7 +200,6 @@ enum dsi_vc_mode {
200}; 200};
201 201
202struct dsi_update_region { 202struct dsi_update_region {
203 bool dirty;
204 u16 x, y, w, h; 203 u16 x, y, w, h;
205 struct omap_dss_device *device; 204 struct omap_dss_device *device;
206}; 205};
@@ -234,18 +233,18 @@ static struct
234 233
235 struct completion bta_completion; 234 struct completion bta_completion;
236 235
237 struct task_struct *thread; 236 int update_channel;
238 wait_queue_head_t waitqueue;
239
240 spinlock_t update_lock;
241 bool framedone_received;
242 struct dsi_update_region update_region; 237 struct dsi_update_region update_region;
243 struct dsi_update_region active_update_region;
244 struct completion update_completion;
245 238
246 bool te_enabled; 239 bool te_enabled;
247 bool use_ext_te; 240 bool use_ext_te;
248 241
242 struct work_struct framedone_work;
243 void (*framedone_callback)(int, void *);
244 void *framedone_data;
245
246 struct delayed_work framedone_timeout_work;
247
249#ifdef DSI_CATCH_MISSING_TE 248#ifdef DSI_CATCH_MISSING_TE
250 struct timer_list te_timer; 249 struct timer_list te_timer;
251#endif 250#endif
@@ -357,9 +356,9 @@ static void dsi_perf_show(const char *name)
357 356
358 total_us = setup_us + trans_us; 357 total_us = setup_us + trans_us;
359 358
360 total_bytes = dsi.active_update_region.w * 359 total_bytes = dsi.update_region.w *
361 dsi.active_update_region.h * 360 dsi.update_region.h *
362 dsi.active_update_region.device->ctrl.pixel_size / 8; 361 dsi.update_region.device->ctrl.pixel_size / 8;
363 362
364 printk(KERN_INFO "DSI(%s): %u us + %u us = %u us (%uHz), " 363 printk(KERN_INFO "DSI(%s): %u us + %u us = %u us (%uHz), "
365 "%u bytes, %u kbytes/sec\n", 364 "%u bytes, %u kbytes/sec\n",
@@ -2725,7 +2724,7 @@ static void dsi_update_screen_dispc(struct omap_dss_device *dssdev,
2725 unsigned packet_len; 2724 unsigned packet_len;
2726 u32 l; 2725 u32 l;
2727 bool use_te_trigger; 2726 bool use_te_trigger;
2728 const unsigned channel = 0; 2727 const unsigned channel = dsi.update_channel;
2729 /* line buffer is 1024 x 24bits */ 2728 /* line buffer is 1024 x 24bits */
2730 /* XXX: for some reason using full buffer size causes considerable TX 2729 /* XXX: for some reason using full buffer size causes considerable TX
2731 * slowdown with update sizes that fill the whole buffer */ 2730 * slowdown with update sizes that fill the whole buffer */
@@ -2736,6 +2735,8 @@ static void dsi_update_screen_dispc(struct omap_dss_device *dssdev,
2736 DSSDBG("dsi_update_screen_dispc(%d,%d %dx%d)\n", 2735 DSSDBG("dsi_update_screen_dispc(%d,%d %dx%d)\n",
2737 x, y, w, h); 2736 x, y, w, h);
2738 2737
2738 dsi_vc_config_vp(channel);
2739
2739 bytespp = dssdev->ctrl.pixel_size / 8; 2740 bytespp = dssdev->ctrl.pixel_size / 8;
2740 bytespl = w * bytespp; 2741 bytespl = w * bytespp;
2741 bytespf = bytespl * h; 2742 bytespf = bytespl * h;
@@ -2773,6 +2774,11 @@ static void dsi_update_screen_dispc(struct omap_dss_device *dssdev,
2773 */ 2774 */
2774 dispc_disable_sidle(); 2775 dispc_disable_sidle();
2775 2776
2777 dsi_perf_mark_start();
2778
2779 schedule_delayed_work(&dsi.framedone_timeout_work,
2780 msecs_to_jiffies(250));
2781
2776 dss_start_update(dssdev); 2782 dss_start_update(dssdev);
2777 2783
2778 if (use_te_trigger) { 2784 if (use_te_trigger) {
@@ -2795,47 +2801,63 @@ static void dsi_te_timeout(unsigned long arg)
2795} 2801}
2796#endif 2802#endif
2797 2803
2798static void dsi_framedone_irq_callback(void *data, u32 mask) 2804static void dsi_framedone_timeout_work_callback(struct work_struct *work)
2799{ 2805{
2800 /* Note: We get FRAMEDONE when DISPC has finished sending pixels and 2806 int r;
2801 * turns itself off. However, DSI still has the pixels in its buffers, 2807 const int channel = dsi.update_channel;
2802 * and is sending the data. 2808 bool use_te_trigger;
2803 */ 2809
2810 DSSERR("Framedone not received for 250ms!\n");
2804 2811
2805 /* SIDLEMODE back to smart-idle */ 2812 /* SIDLEMODE back to smart-idle */
2806 dispc_enable_sidle(); 2813 dispc_enable_sidle();
2807 2814
2808 dsi.framedone_received = true; 2815 use_te_trigger = dsi.te_enabled && !dsi.use_ext_te;
2809 wake_up(&dsi.waitqueue);
2810}
2811 2816
2812static void dsi_set_update_region(struct omap_dss_device *dssdev, 2817 if (use_te_trigger) {
2813 u16 x, u16 y, u16 w, u16 h) 2818 /* enable LP_RX_TO again after the TE */
2814{ 2819 REG_FLD_MOD(DSI_TIMING2, 1, 15, 15); /* LP_RX_TO */
2815 spin_lock(&dsi.update_lock);
2816 if (dsi.update_region.dirty) {
2817 dsi.update_region.x = min(x, dsi.update_region.x);
2818 dsi.update_region.y = min(y, dsi.update_region.y);
2819 dsi.update_region.w = max(w, dsi.update_region.w);
2820 dsi.update_region.h = max(h, dsi.update_region.h);
2821 } else {
2822 dsi.update_region.x = x;
2823 dsi.update_region.y = y;
2824 dsi.update_region.w = w;
2825 dsi.update_region.h = h;
2826 } 2820 }
2827 2821
2828 dsi.update_region.device = dssdev; 2822 /* Send BTA after the frame. We need this for the TE to work, as TE
2829 dsi.update_region.dirty = true; 2823 * trigger is only sent for BTAs without preceding packet. Thus we need
2824 * to BTA after the pixel packets so that next BTA will cause TE
2825 * trigger.
2826 *
2827 * This is not needed when TE is not in use, but we do it anyway to
2828 * make sure that the transfer has been completed. It would be more
2829 * optimal, but more complex, to wait only just before starting next
2830 * transfer. */
2831 r = dsi_vc_send_bta_sync(channel);
2832 if (r)
2833 DSSERR("BTA after framedone failed\n");
2834
2835 /* RX_FIFO_NOT_EMPTY */
2836 if (REG_GET(DSI_VC_CTRL(channel), 20, 20)) {
2837 DSSERR("Received error during frame transfer:\n");
2838 dsi_vc_flush_receive_data(channel);
2839 }
2840
2841 dsi.framedone_callback(-ETIMEDOUT, dsi.framedone_data);
2842}
2830 2843
2831 spin_unlock(&dsi.update_lock); 2844static void dsi_framedone_irq_callback(void *data, u32 mask)
2845{
2846 /* Note: We get FRAMEDONE when DISPC has finished sending pixels and
2847 * turns itself off. However, DSI still has the pixels in its buffers,
2848 * and is sending the data.
2849 */
2850
2851 /* SIDLEMODE back to smart-idle */
2852 dispc_enable_sidle();
2832 2853
2854 schedule_work(&dsi.framedone_work);
2833} 2855}
2834 2856
2835static void dsi_handle_framedone(void) 2857static void dsi_handle_framedone(void)
2836{ 2858{
2837 int r; 2859 int r;
2838 const int channel = 0; 2860 const int channel = dsi.update_channel;
2839 bool use_te_trigger; 2861 bool use_te_trigger;
2840 2862
2841 use_te_trigger = dsi.te_enabled && !dsi.use_ext_te; 2863 use_te_trigger = dsi.te_enabled && !dsi.use_ext_te;
@@ -2871,105 +2893,79 @@ static void dsi_handle_framedone(void)
2871#endif 2893#endif
2872} 2894}
2873 2895
2874static int dsi_update_thread(void *data) 2896static void dsi_framedone_work_callback(struct work_struct *work)
2875{ 2897{
2876 unsigned long timeout; 2898 DSSDBGF();
2877 struct omap_dss_device *device;
2878 u16 x, y, w, h;
2879
2880 while (1) {
2881 wait_event_interruptible(dsi.waitqueue,
2882 dsi.update_region.dirty == true ||
2883 kthread_should_stop());
2884
2885 if (kthread_should_stop())
2886 break;
2887
2888 dsi_bus_lock();
2889
2890 if (kthread_should_stop()) {
2891 dsi_bus_unlock();
2892 break;
2893 }
2894 2899
2895 dsi_perf_mark_setup(); 2900 cancel_delayed_work_sync(&dsi.framedone_timeout_work);
2896 2901
2897 if (dsi.update_region.dirty) { 2902 dsi_handle_framedone();
2898 spin_lock(&dsi.update_lock);
2899 dsi.active_update_region = dsi.update_region;
2900 dsi.update_region.dirty = false;
2901 spin_unlock(&dsi.update_lock);
2902 }
2903 2903
2904 device = dsi.active_update_region.device; 2904 dsi_perf_show("DISPC");
2905 x = dsi.active_update_region.x;
2906 y = dsi.active_update_region.y;
2907 w = dsi.active_update_region.w;
2908 h = dsi.active_update_region.h;
2909 2905
2910 if (device->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) { 2906 dsi.framedone_callback(0, dsi.framedone_data);
2907}
2911 2908
2912 dss_setup_partial_planes(device, 2909int omap_dsi_prepare_update(struct omap_dss_device *dssdev,
2913 &x, &y, &w, &h); 2910 u16 *x, u16 *y, u16 *w, u16 *h)
2911{
2912 u16 dw, dh;
2914 2913
2915 dispc_set_lcd_size(w, h); 2914 dssdev->driver->get_resolution(dssdev, &dw, &dh);
2916 }
2917 2915
2918 if (dsi.active_update_region.dirty) { 2916 if (*x > dw || *y > dh)
2919 dsi.active_update_region.dirty = false; 2917 return -EINVAL;
2920 /* XXX TODO we don't need to send the coords, if they
2921 * are the same that are already programmed to the
2922 * panel. That should speed up manual update a bit */
2923 device->driver->setup_update(device, x, y, w, h);
2924 }
2925 2918
2926 dsi_perf_mark_start(); 2919 if (*x + *w > dw)
2920 return -EINVAL;
2927 2921
2928 if (device->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) { 2922 if (*y + *h > dh)
2929 dsi_vc_config_vp(0); 2923 return -EINVAL;
2930 2924
2931 if (dsi.te_enabled && dsi.use_ext_te) 2925 if (*w == 1)
2932 device->driver->wait_for_te(device); 2926 return -EINVAL;
2933 2927
2934 dsi.framedone_received = false; 2928 if (*w == 0 || *h == 0)
2929 return -EINVAL;
2935 2930
2936 dsi_update_screen_dispc(device, x, y, w, h); 2931 dsi_perf_mark_setup();
2937 2932
2938 /* wait for framedone */ 2933 if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
2939 timeout = msecs_to_jiffies(1000); 2934 dss_setup_partial_planes(dssdev, x, y, w, h);
2940 wait_event_timeout(dsi.waitqueue, 2935 dispc_set_lcd_size(*w, *h);
2941 dsi.framedone_received == true, 2936 }
2942 timeout);
2943 2937
2944 if (!dsi.framedone_received) { 2938 return 0;
2945 DSSERR("framedone timeout\n"); 2939}
2946 DSSERR("failed update %d,%d %dx%d\n", 2940EXPORT_SYMBOL(omap_dsi_prepare_update);
2947 x, y, w, h);
2948 2941
2949 dispc_enable_sidle(); 2942int omap_dsi_update(struct omap_dss_device *dssdev,
2950 device->manager->disable(device->manager); 2943 int channel,
2944 u16 x, u16 y, u16 w, u16 h,
2945 void (*callback)(int, void *), void *data)
2946{
2947 dsi.update_channel = channel;
2951 2948
2952 dsi_reset_tx_fifo(0); 2949 if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
2953 } else { 2950 dsi.framedone_callback = callback;
2954 dsi_handle_framedone(); 2951 dsi.framedone_data = data;
2955 dsi_perf_show("DISPC");
2956 }
2957 } else {
2958 dsi_update_screen_l4(device, x, y, w, h);
2959 dsi_perf_show("L4");
2960 }
2961 2952
2962 complete_all(&dsi.update_completion); 2953 dsi.update_region.x = x;
2954 dsi.update_region.y = y;
2955 dsi.update_region.w = w;
2956 dsi.update_region.h = h;
2957 dsi.update_region.device = dssdev;
2963 2958
2964 dsi_bus_unlock(); 2959 dsi_update_screen_dispc(dssdev, x, y, w, h);
2960 } else {
2961 dsi_update_screen_l4(dssdev, x, y, w, h);
2962 dsi_perf_show("L4");
2963 callback(0, data);
2965 } 2964 }
2966 2965
2967 DSSDBG("update thread exiting\n");
2968
2969 return 0; 2966 return 0;
2970} 2967}
2971 2968EXPORT_SYMBOL(omap_dsi_update);
2972
2973 2969
2974/* Display funcs */ 2970/* Display funcs */
2975 2971
@@ -3324,74 +3320,6 @@ err0:
3324 return r; 3320 return r;
3325} 3321}
3326 3322
3327static int dsi_display_update(struct omap_dss_device *dssdev,
3328 u16 x, u16 y, u16 w, u16 h)
3329{
3330 int r = 0;
3331 u16 dw, dh;
3332
3333 DSSDBG("dsi_display_update(%d,%d %dx%d)\n", x, y, w, h);
3334
3335 mutex_lock(&dsi.lock);
3336
3337 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
3338 goto end;
3339
3340 dssdev->driver->get_resolution(dssdev, &dw, &dh);
3341
3342 if (x > dw || y > dh)
3343 goto end;
3344
3345 if (x + w > dw)
3346 w = dw - x;
3347
3348 if (y + h > dh)
3349 h = dh - y;
3350
3351 if (w == 0 || h == 0)
3352 goto end;
3353
3354 if (w == 1) {
3355 r = -EINVAL;
3356 goto end;
3357 }
3358
3359 dsi_set_update_region(dssdev, x, y, w, h);
3360
3361 wake_up(&dsi.waitqueue);
3362
3363end:
3364 mutex_unlock(&dsi.lock);
3365
3366 return r;
3367}
3368
3369static int dsi_display_sync(struct omap_dss_device *dssdev)
3370{
3371 bool wait;
3372
3373 DSSDBG("dsi_display_sync()\n");
3374
3375 mutex_lock(&dsi.lock);
3376 dsi_bus_lock();
3377
3378 if (dsi.update_region.dirty) {
3379 INIT_COMPLETION(dsi.update_completion);
3380 wait = true;
3381 } else {
3382 wait = false;
3383 }
3384
3385 dsi_bus_unlock();
3386 mutex_unlock(&dsi.lock);
3387
3388 if (wait)
3389 wait_for_completion_interruptible(&dsi.update_completion);
3390
3391 DSSDBG("dsi_display_sync() done\n");
3392 return 0;
3393}
3394
3395int omapdss_dsi_enable_te(struct omap_dss_device *dssdev, bool enable) 3323int omapdss_dsi_enable_te(struct omap_dss_device *dssdev, bool enable)
3396{ 3324{
3397 dsi.te_enabled = enable; 3325 dsi.te_enabled = enable;
@@ -3420,8 +3348,6 @@ int dsi_init_display(struct omap_dss_device *dssdev)
3420 dssdev->disable = dsi_display_disable; 3348 dssdev->disable = dsi_display_disable;
3421 dssdev->suspend = dsi_display_suspend; 3349 dssdev->suspend = dsi_display_suspend;
3422 dssdev->resume = dsi_display_resume; 3350 dssdev->resume = dsi_display_resume;
3423 dssdev->update = dsi_display_update;
3424 dssdev->sync = dsi_display_sync;
3425 3351
3426 /* XXX these should be figured out dynamically */ 3352 /* XXX these should be figured out dynamically */
3427 dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE | 3353 dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE |
@@ -3437,9 +3363,6 @@ int dsi_init(struct platform_device *pdev)
3437{ 3363{
3438 u32 rev; 3364 u32 rev;
3439 int r; 3365 int r;
3440 struct sched_param param = {
3441 .sched_priority = MAX_USER_RT_PRIO-1
3442 };
3443 3366
3444 spin_lock_init(&dsi.errors_lock); 3367 spin_lock_init(&dsi.errors_lock);
3445 dsi.errors = 0; 3368 dsi.errors = 0;
@@ -3450,28 +3373,19 @@ int dsi_init(struct platform_device *pdev)
3450#endif 3373#endif
3451 3374
3452 init_completion(&dsi.bta_completion); 3375 init_completion(&dsi.bta_completion);
3453 init_completion(&dsi.update_completion);
3454
3455 dsi.thread = kthread_create(dsi_update_thread, NULL, "dsi");
3456 if (IS_ERR(dsi.thread)) {
3457 DSSERR("cannot create kthread\n");
3458 r = PTR_ERR(dsi.thread);
3459 goto err0;
3460 }
3461 sched_setscheduler(dsi.thread, SCHED_FIFO, &param);
3462
3463 init_waitqueue_head(&dsi.waitqueue);
3464 spin_lock_init(&dsi.update_lock);
3465 3376
3466 mutex_init(&dsi.lock); 3377 mutex_init(&dsi.lock);
3467 sema_init(&dsi.bus_lock, 1); 3378 sema_init(&dsi.bus_lock, 1);
3468 3379
3380 INIT_WORK(&dsi.framedone_work, dsi_framedone_work_callback);
3381 INIT_DELAYED_WORK_DEFERRABLE(&dsi.framedone_timeout_work,
3382 dsi_framedone_timeout_work_callback);
3383
3469#ifdef DSI_CATCH_MISSING_TE 3384#ifdef DSI_CATCH_MISSING_TE
3470 init_timer(&dsi.te_timer); 3385 init_timer(&dsi.te_timer);
3471 dsi.te_timer.function = dsi_te_timeout; 3386 dsi.te_timer.function = dsi_te_timeout;
3472 dsi.te_timer.data = 0; 3387 dsi.te_timer.data = 0;
3473#endif 3388#endif
3474
3475 dsi.base = ioremap(DSI_BASE, DSI_SZ_REGS); 3389 dsi.base = ioremap(DSI_BASE, DSI_SZ_REGS);
3476 if (!dsi.base) { 3390 if (!dsi.base) {
3477 DSSERR("can't ioremap DSI\n"); 3391 DSSERR("can't ioremap DSI\n");
@@ -3495,21 +3409,15 @@ int dsi_init(struct platform_device *pdev)
3495 3409
3496 enable_clocks(0); 3410 enable_clocks(0);
3497 3411
3498 wake_up_process(dsi.thread);
3499
3500 return 0; 3412 return 0;
3501err2: 3413err2:
3502 iounmap(dsi.base); 3414 iounmap(dsi.base);
3503err1: 3415err1:
3504 kthread_stop(dsi.thread);
3505err0:
3506 return r; 3416 return r;
3507} 3417}
3508 3418
3509void dsi_exit(void) 3419void dsi_exit(void)
3510{ 3420{
3511 kthread_stop(dsi.thread);
3512
3513 iounmap(dsi.base); 3421 iounmap(dsi.base);
3514 3422
3515 DSSDBG("omap_dsi_exit\n"); 3423 DSSDBG("omap_dsi_exit\n");
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
diff --git a/drivers/video/omap2/omapfb/omapfb-ioctl.c b/drivers/video/omap2/omapfb/omapfb-ioctl.c
index 4f68cb0d59de..1ffa760b8545 100644
--- a/drivers/video/omap2/omapfb/omapfb-ioctl.c
+++ b/drivers/video/omap2/omapfb/omapfb-ioctl.c
@@ -172,7 +172,7 @@ static int omapfb_update_window_nolock(struct fb_info *fbi,
172 if (x + w > dw || y + h > dh) 172 if (x + w > dw || y + h > dh)
173 return -EINVAL; 173 return -EINVAL;
174 174
175 return display->update(display, x, y, w, h); 175 return display->driver->update(display, x, y, w, h);
176} 176}
177 177
178/* This function is exported for SGX driver use */ 178/* This function is exported for SGX driver use */
@@ -496,18 +496,18 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
496 switch (cmd) { 496 switch (cmd) {
497 case OMAPFB_SYNC_GFX: 497 case OMAPFB_SYNC_GFX:
498 DBG("ioctl SYNC_GFX\n"); 498 DBG("ioctl SYNC_GFX\n");
499 if (!display || !display->sync) { 499 if (!display || !display->driver->sync) {
500 /* DSS1 never returns an error here, so we neither */ 500 /* DSS1 never returns an error here, so we neither */
501 /*r = -EINVAL;*/ 501 /*r = -EINVAL;*/
502 break; 502 break;
503 } 503 }
504 504
505 r = display->sync(display); 505 r = display->driver->sync(display);
506 break; 506 break;
507 507
508 case OMAPFB_UPDATE_WINDOW_OLD: 508 case OMAPFB_UPDATE_WINDOW_OLD:
509 DBG("ioctl UPDATE_WINDOW_OLD\n"); 509 DBG("ioctl UPDATE_WINDOW_OLD\n");
510 if (!display || !display->update) { 510 if (!display || !display->driver->update) {
511 r = -EINVAL; 511 r = -EINVAL;
512 break; 512 break;
513 } 513 }
@@ -525,7 +525,7 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
525 525
526 case OMAPFB_UPDATE_WINDOW: 526 case OMAPFB_UPDATE_WINDOW:
527 DBG("ioctl UPDATE_WINDOW\n"); 527 DBG("ioctl UPDATE_WINDOW\n");
528 if (!display || !display->update) { 528 if (!display || !display->driver->update) {
529 r = -EINVAL; 529 r = -EINVAL;
530 break; 530 break;
531 } 531 }
diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
index c720842341b2..3dbbddc2d51e 100644
--- a/drivers/video/omap2/omapfb/omapfb-main.c
+++ b/drivers/video/omap2/omapfb/omapfb-main.c
@@ -1254,11 +1254,11 @@ static int omapfb_blank(int blank, struct fb_info *fbi)
1254exit: 1254exit:
1255 omapfb_unlock(fbdev); 1255 omapfb_unlock(fbdev);
1256 1256
1257 if (r == 0 && do_update && display->update) { 1257 if (r == 0 && do_update && display->driver->update) {
1258 u16 w, h; 1258 u16 w, h;
1259 display->driver->get_resolution(display, &w, &h); 1259 display->driver->get_resolution(display, &w, &h);
1260 1260
1261 r = display->update(display, 0, 0, w, h); 1261 r = display->driver->update(display, 0, 0, w, h);
1262 } 1262 }
1263 1263
1264 return r; 1264 return r;
@@ -1639,8 +1639,8 @@ int omapfb_realloc_fbmem(struct fb_info *fbi, unsigned long size, int type)
1639 if (old_size == size && old_type == type) 1639 if (old_size == size && old_type == type)
1640 return 0; 1640 return 0;
1641 1641
1642 if (display && display->sync) 1642 if (display && display->driver->sync)
1643 display->sync(display); 1643 display->driver->sync(display);
1644 1644
1645 omapfb_free_fbmem(fbi); 1645 omapfb_free_fbmem(fbi);
1646 1646
@@ -2221,7 +2221,7 @@ static int omapfb_probe(struct platform_device *pdev)
2221 2221
2222 dssdrv->get_resolution(def_display, 2222 dssdrv->get_resolution(def_display,
2223 &w, &h); 2223 &w, &h);
2224 def_display->update(def_display, 0, 0, w, h); 2224 def_display->driver->update(def_display, 0, 0, w, h);
2225#endif 2225#endif
2226 } else { 2226 } else {
2227 if (dssdrv->set_update_mode) 2227 if (dssdrv->set_update_mode)