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 | |
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')
-rw-r--r-- | drivers/video/omap2/displays/panel-taal.c | 76 | ||||
-rw-r--r-- | drivers/video/omap2/dss/dsi.c | 322 | ||||
-rw-r--r-- | drivers/video/omap2/dss/rfbi.c | 290 | ||||
-rw-r--r-- | drivers/video/omap2/omapfb/omapfb-ioctl.c | 10 | ||||
-rw-r--r-- | drivers/video/omap2/omapfb/omapfb-main.c | 10 |
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 | ||
728 | static void taal_setup_update(struct omap_dss_device *dssdev, | 728 | static 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 | |||
735 | static 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; | ||
765 | err: | ||
766 | dsi_bus_unlock(); | ||
767 | return r; | ||
768 | } | ||
769 | |||
770 | static 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 | ||
734 | static int taal_enable_te(struct omap_dss_device *dssdev, bool enable) | 782 | static 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 | ||
765 | static 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 | |||
783 | static int taal_rotate(struct omap_dss_device *dssdev, u8 rotate) | 813 | static 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 | ||
202 | struct dsi_update_region { | 202 | struct 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 | ||
2798 | static void dsi_framedone_irq_callback(void *data, u32 mask) | 2804 | static 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 | ||
2812 | static 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); | 2844 | static 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 | ||
2835 | static void dsi_handle_framedone(void) | 2857 | static 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 | ||
2874 | static int dsi_update_thread(void *data) | 2896 | static 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, | 2909 | int 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", | 2940 | EXPORT_SYMBOL(omap_dsi_prepare_update); |
2947 | x, y, w, h); | ||
2948 | 2941 | ||
2949 | dispc_enable_sidle(); | 2942 | int 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 | 2968 | EXPORT_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 | ||
3327 | static 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 | |||
3363 | end: | ||
3364 | mutex_unlock(&dsi.lock); | ||
3365 | |||
3366 | return r; | ||
3367 | } | ||
3368 | |||
3369 | static 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 | |||
3395 | int omapdss_dsi_enable_te(struct omap_dss_device *dssdev, bool enable) | 3323 | int 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, ¶m); | ||
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; |
3501 | err2: | 3413 | err2: |
3502 | iounmap(dsi.base); | 3414 | iounmap(dsi.base); |
3503 | err1: | 3415 | err1: |
3504 | kthread_stop(dsi.thread); | ||
3505 | err0: | ||
3506 | return r; | 3416 | return r; |
3507 | } | 3417 | } |
3508 | 3418 | ||
3509 | void dsi_exit(void) | 3419 | void 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 | ||
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 | ||
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) | |||
1254 | exit: | 1254 | exit: |
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) |