aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/omap2/dss/rfbi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/omap2/dss/rfbi.c')
-rw-r--r--drivers/video/omap2/dss/rfbi.c222
1 files changed, 142 insertions, 80 deletions
diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c
index 7c087424b634..7282e5af3e1a 100644
--- a/drivers/video/omap2/dss/rfbi.c
+++ b/drivers/video/omap2/dss/rfbi.c
@@ -111,6 +111,13 @@ static struct {
111 struct omap_dss_device *dssdev[2]; 111 struct omap_dss_device *dssdev[2];
112 112
113 struct semaphore bus_lock; 113 struct semaphore bus_lock;
114
115 struct omap_video_timings timings;
116 int pixel_size;
117 int data_lines;
118 struct rfbi_timings intf_timings;
119
120 struct omap_dss_output output;
114} rfbi; 121} rfbi;
115 122
116static inline void rfbi_write_reg(const struct rfbi_reg idx, u32 val) 123static inline void rfbi_write_reg(const struct rfbi_reg idx, u32 val)
@@ -300,30 +307,23 @@ void omap_rfbi_write_pixels(const void __iomem *buf, int scr_width,
300} 307}
301EXPORT_SYMBOL(omap_rfbi_write_pixels); 308EXPORT_SYMBOL(omap_rfbi_write_pixels);
302 309
303static int rfbi_transfer_area(struct omap_dss_device *dssdev, u16 width, 310static int rfbi_transfer_area(struct omap_dss_device *dssdev,
304 u16 height, void (*callback)(void *data), void *data) 311 void (*callback)(void *data), void *data)
305{ 312{
306 u32 l; 313 u32 l;
307 int r; 314 int r;
308 struct omap_video_timings timings = { 315 struct omap_overlay_manager *mgr = dssdev->output->manager;
309 .hsw = 1, 316 u16 width = rfbi.timings.x_res;
310 .hfp = 1, 317 u16 height = rfbi.timings.y_res;
311 .hbp = 1,
312 .vsw = 1,
313 .vfp = 0,
314 .vbp = 0,
315 .x_res = width,
316 .y_res = height,
317 };
318 318
319 /*BUG_ON(callback == 0);*/ 319 /*BUG_ON(callback == 0);*/
320 BUG_ON(rfbi.framedone_callback != NULL); 320 BUG_ON(rfbi.framedone_callback != NULL);
321 321
322 DSSDBG("rfbi_transfer_area %dx%d\n", width, height); 322 DSSDBG("rfbi_transfer_area %dx%d\n", width, height);
323 323
324 dss_mgr_set_timings(dssdev->manager, &timings); 324 dss_mgr_set_timings(mgr, &rfbi.timings);
325 325
326 r = dss_mgr_enable(dssdev->manager); 326 r = dss_mgr_enable(mgr);
327 if (r) 327 if (r)
328 return r; 328 return r;
329 329
@@ -770,62 +770,45 @@ static int rfbi_configure(int rfbi_module, int bpp, int lines)
770 return 0; 770 return 0;
771} 771}
772 772
773int omap_rfbi_configure(struct omap_dss_device *dssdev, int pixel_size, 773int omap_rfbi_configure(struct omap_dss_device *dssdev)
774 int data_lines)
775{ 774{
776 return rfbi_configure(dssdev->phy.rfbi.channel, pixel_size, data_lines); 775 return rfbi_configure(dssdev->phy.rfbi.channel, rfbi.pixel_size,
776 rfbi.data_lines);
777} 777}
778EXPORT_SYMBOL(omap_rfbi_configure); 778EXPORT_SYMBOL(omap_rfbi_configure);
779 779
780int omap_rfbi_prepare_update(struct omap_dss_device *dssdev, 780int omap_rfbi_update(struct omap_dss_device *dssdev, void (*callback)(void *),
781 u16 *x, u16 *y, u16 *w, u16 *h) 781 void *data)
782{ 782{
783 u16 dw, dh; 783 return rfbi_transfer_area(dssdev, callback, data);
784 struct omap_video_timings timings = { 784}
785 .hsw = 1, 785EXPORT_SYMBOL(omap_rfbi_update);
786 .hfp = 1,
787 .hbp = 1,
788 .vsw = 1,
789 .vfp = 0,
790 .vbp = 0,
791 .x_res = *w,
792 .y_res = *h,
793 };
794
795 dssdev->driver->get_resolution(dssdev, &dw, &dh);
796
797 if (*x > dw || *y > dh)
798 return -EINVAL;
799
800 if (*x + *w > dw)
801 return -EINVAL;
802
803 if (*y + *h > dh)
804 return -EINVAL;
805
806 if (*w == 1)
807 return -EINVAL;
808
809 if (*w == 0 || *h == 0)
810 return -EINVAL;
811
812 dss_mgr_set_timings(dssdev->manager, &timings);
813 786
814 return 0; 787void omapdss_rfbi_set_size(struct omap_dss_device *dssdev, u16 w, u16 h)
788{
789 rfbi.timings.x_res = w;
790 rfbi.timings.y_res = h;
815} 791}
816EXPORT_SYMBOL(omap_rfbi_prepare_update); 792EXPORT_SYMBOL(omapdss_rfbi_set_size);
817 793
818int omap_rfbi_update(struct omap_dss_device *dssdev, 794void omapdss_rfbi_set_pixel_size(struct omap_dss_device *dssdev, int pixel_size)
819 u16 x, u16 y, u16 w, u16 h,
820 void (*callback)(void *), void *data)
821{ 795{
822 int r; 796 rfbi.pixel_size = pixel_size;
797}
798EXPORT_SYMBOL(omapdss_rfbi_set_pixel_size);
823 799
824 r = rfbi_transfer_area(dssdev, w, h, callback, data); 800void omapdss_rfbi_set_data_lines(struct omap_dss_device *dssdev, int data_lines)
801{
802 rfbi.data_lines = data_lines;
803}
804EXPORT_SYMBOL(omapdss_rfbi_set_data_lines);
825 805
826 return r; 806void omapdss_rfbi_set_interface_timings(struct omap_dss_device *dssdev,
807 struct rfbi_timings *timings)
808{
809 rfbi.intf_timings = *timings;
827} 810}
828EXPORT_SYMBOL(omap_rfbi_update); 811EXPORT_SYMBOL(omapdss_rfbi_set_interface_timings);
829 812
830static void rfbi_dump_regs(struct seq_file *s) 813static void rfbi_dump_regs(struct seq_file *s)
831{ 814{
@@ -869,6 +852,7 @@ static void rfbi_dump_regs(struct seq_file *s)
869 852
870static void rfbi_config_lcd_manager(struct omap_dss_device *dssdev) 853static void rfbi_config_lcd_manager(struct omap_dss_device *dssdev)
871{ 854{
855 struct omap_overlay_manager *mgr = dssdev->output->manager;
872 struct dss_lcd_mgr_config mgr_config; 856 struct dss_lcd_mgr_config mgr_config;
873 857
874 mgr_config.io_pad_mode = DSS_IO_PAD_MODE_RFBI; 858 mgr_config.io_pad_mode = DSS_IO_PAD_MODE_RFBI;
@@ -877,18 +861,40 @@ static void rfbi_config_lcd_manager(struct omap_dss_device *dssdev)
877 /* Do we need fifohandcheck for RFBI? */ 861 /* Do we need fifohandcheck for RFBI? */
878 mgr_config.fifohandcheck = false; 862 mgr_config.fifohandcheck = false;
879 863
880 mgr_config.video_port_width = dssdev->ctrl.pixel_size; 864 mgr_config.video_port_width = rfbi.pixel_size;
881 mgr_config.lcden_sig_polarity = 0; 865 mgr_config.lcden_sig_polarity = 0;
882 866
883 dss_mgr_set_lcd_config(dssdev->manager, &mgr_config); 867 dss_mgr_set_lcd_config(mgr, &mgr_config);
868
869 /*
870 * Set rfbi.timings with default values, the x_res and y_res fields
871 * are expected to be already configured by the panel driver via
872 * omapdss_rfbi_set_size()
873 */
874 rfbi.timings.hsw = 1;
875 rfbi.timings.hfp = 1;
876 rfbi.timings.hbp = 1;
877 rfbi.timings.vsw = 1;
878 rfbi.timings.vfp = 0;
879 rfbi.timings.vbp = 0;
880
881 rfbi.timings.interlace = false;
882 rfbi.timings.hsync_level = OMAPDSS_SIG_ACTIVE_HIGH;
883 rfbi.timings.vsync_level = OMAPDSS_SIG_ACTIVE_HIGH;
884 rfbi.timings.data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
885 rfbi.timings.de_level = OMAPDSS_SIG_ACTIVE_HIGH;
886 rfbi.timings.sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES;
887
888 dss_mgr_set_timings(mgr, &rfbi.timings);
884} 889}
885 890
886int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev) 891int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev)
887{ 892{
893 struct omap_dss_output *out = dssdev->output;
888 int r; 894 int r;
889 895
890 if (dssdev->manager == NULL) { 896 if (out == NULL || out->manager == NULL) {
891 DSSERR("failed to enable display: no manager\n"); 897 DSSERR("failed to enable display: no output/manager\n");
892 return -ENODEV; 898 return -ENODEV;
893 } 899 }
894 900
@@ -911,13 +917,10 @@ int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev)
911 917
912 rfbi_config_lcd_manager(dssdev); 918 rfbi_config_lcd_manager(dssdev);
913 919
914 rfbi_configure(dssdev->phy.rfbi.channel, 920 rfbi_configure(dssdev->phy.rfbi.channel, rfbi.pixel_size,
915 dssdev->ctrl.pixel_size, 921 rfbi.data_lines);
916 dssdev->phy.rfbi.data_lines);
917
918 rfbi_set_timings(dssdev->phy.rfbi.channel,
919 &dssdev->ctrl.rfbi_timings);
920 922
923 rfbi_set_timings(dssdev->phy.rfbi.channel, &rfbi.intf_timings);
921 924
922 return 0; 925 return 0;
923err1: 926err1:
@@ -941,14 +944,17 @@ EXPORT_SYMBOL(omapdss_rfbi_display_disable);
941static int __init rfbi_init_display(struct omap_dss_device *dssdev) 944static int __init rfbi_init_display(struct omap_dss_device *dssdev)
942{ 945{
943 rfbi.dssdev[dssdev->phy.rfbi.channel] = dssdev; 946 rfbi.dssdev[dssdev->phy.rfbi.channel] = dssdev;
944 dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;
945 return 0; 947 return 0;
946} 948}
947 949
948static void __init rfbi_probe_pdata(struct platform_device *pdev) 950static struct omap_dss_device * __init rfbi_find_dssdev(struct platform_device *pdev)
949{ 951{
950 struct omap_dss_board_info *pdata = pdev->dev.platform_data; 952 struct omap_dss_board_info *pdata = pdev->dev.platform_data;
951 int i, r; 953 const char *def_disp_name = dss_get_default_display_name();
954 struct omap_dss_device *def_dssdev;
955 int i;
956
957 def_dssdev = NULL;
952 958
953 for (i = 0; i < pdata->num_devices; ++i) { 959 for (i = 0; i < pdata->num_devices; ++i) {
954 struct omap_dss_device *dssdev = pdata->devices[i]; 960 struct omap_dss_device *dssdev = pdata->devices[i];
@@ -956,17 +962,67 @@ static void __init rfbi_probe_pdata(struct platform_device *pdev)
956 if (dssdev->type != OMAP_DISPLAY_TYPE_DBI) 962 if (dssdev->type != OMAP_DISPLAY_TYPE_DBI)
957 continue; 963 continue;
958 964
959 r = rfbi_init_display(dssdev); 965 if (def_dssdev == NULL)
960 if (r) { 966 def_dssdev = dssdev;
961 DSSERR("device %s init failed: %d\n", dssdev->name, r); 967
962 continue; 968 if (def_disp_name != NULL &&
969 strcmp(dssdev->name, def_disp_name) == 0) {
970 def_dssdev = dssdev;
971 break;
963 } 972 }
973 }
974
975 return def_dssdev;
976}
977
978static void __init rfbi_probe_pdata(struct platform_device *rfbidev)
979{
980 struct omap_dss_device *plat_dssdev;
981 struct omap_dss_device *dssdev;
982 int r;
983
984 plat_dssdev = rfbi_find_dssdev(rfbidev);
985
986 if (!plat_dssdev)
987 return;
988
989 dssdev = dss_alloc_and_init_device(&rfbidev->dev);
990 if (!dssdev)
991 return;
992
993 dss_copy_device_pdata(dssdev, plat_dssdev);
964 994
965 r = omap_dss_register_device(dssdev, &pdev->dev, i); 995 r = rfbi_init_display(dssdev);
966 if (r) 996 if (r) {
967 DSSERR("device %s register failed: %d\n", 997 DSSERR("device %s init failed: %d\n", dssdev->name, r);
968 dssdev->name, r); 998 dss_put_device(dssdev);
999 return;
969 } 1000 }
1001
1002 r = dss_add_device(dssdev);
1003 if (r) {
1004 DSSERR("device %s register failed: %d\n", dssdev->name, r);
1005 dss_put_device(dssdev);
1006 return;
1007 }
1008}
1009
1010static void __init rfbi_init_output(struct platform_device *pdev)
1011{
1012 struct omap_dss_output *out = &rfbi.output;
1013
1014 out->pdev = pdev;
1015 out->id = OMAP_DSS_OUTPUT_DBI;
1016 out->type = OMAP_DISPLAY_TYPE_DBI;
1017
1018 dss_register_output(out);
1019}
1020
1021static void __exit rfbi_uninit_output(struct platform_device *pdev)
1022{
1023 struct omap_dss_output *out = &rfbi.output;
1024
1025 dss_unregister_output(out);
970} 1026}
971 1027
972/* RFBI HW IP initialisation */ 1028/* RFBI HW IP initialisation */
@@ -1020,6 +1076,8 @@ static int __init omap_rfbihw_probe(struct platform_device *pdev)
1020 1076
1021 dss_debugfs_create_file("rfbi", rfbi_dump_regs); 1077 dss_debugfs_create_file("rfbi", rfbi_dump_regs);
1022 1078
1079 rfbi_init_output(pdev);
1080
1023 rfbi_probe_pdata(pdev); 1081 rfbi_probe_pdata(pdev);
1024 1082
1025 return 0; 1083 return 0;
@@ -1031,8 +1089,12 @@ err_runtime_get:
1031 1089
1032static int __exit omap_rfbihw_remove(struct platform_device *pdev) 1090static int __exit omap_rfbihw_remove(struct platform_device *pdev)
1033{ 1091{
1034 omap_dss_unregister_child_devices(&pdev->dev); 1092 dss_unregister_child_devices(&pdev->dev);
1093
1094 rfbi_uninit_output(pdev);
1095
1035 pm_runtime_disable(&pdev->dev); 1096 pm_runtime_disable(&pdev->dev);
1097
1036 return 0; 1098 return 0;
1037} 1099}
1038 1100