diff options
Diffstat (limited to 'drivers/video/omap2/dss/rfbi.c')
-rw-r--r-- | drivers/video/omap2/dss/rfbi.c | 222 |
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 | ||
116 | static inline void rfbi_write_reg(const struct rfbi_reg idx, u32 val) | 123 | static 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 | } |
301 | EXPORT_SYMBOL(omap_rfbi_write_pixels); | 308 | EXPORT_SYMBOL(omap_rfbi_write_pixels); |
302 | 309 | ||
303 | static int rfbi_transfer_area(struct omap_dss_device *dssdev, u16 width, | 310 | static 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 | ||
773 | int omap_rfbi_configure(struct omap_dss_device *dssdev, int pixel_size, | 773 | int 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 | } |
778 | EXPORT_SYMBOL(omap_rfbi_configure); | 778 | EXPORT_SYMBOL(omap_rfbi_configure); |
779 | 779 | ||
780 | int omap_rfbi_prepare_update(struct omap_dss_device *dssdev, | 780 | int 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, | 785 | EXPORT_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; | 787 | void 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 | } |
816 | EXPORT_SYMBOL(omap_rfbi_prepare_update); | 792 | EXPORT_SYMBOL(omapdss_rfbi_set_size); |
817 | 793 | ||
818 | int omap_rfbi_update(struct omap_dss_device *dssdev, | 794 | void 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 | } | ||
798 | EXPORT_SYMBOL(omapdss_rfbi_set_pixel_size); | ||
823 | 799 | ||
824 | r = rfbi_transfer_area(dssdev, w, h, callback, data); | 800 | void omapdss_rfbi_set_data_lines(struct omap_dss_device *dssdev, int data_lines) |
801 | { | ||
802 | rfbi.data_lines = data_lines; | ||
803 | } | ||
804 | EXPORT_SYMBOL(omapdss_rfbi_set_data_lines); | ||
825 | 805 | ||
826 | return r; | 806 | void omapdss_rfbi_set_interface_timings(struct omap_dss_device *dssdev, |
807 | struct rfbi_timings *timings) | ||
808 | { | ||
809 | rfbi.intf_timings = *timings; | ||
827 | } | 810 | } |
828 | EXPORT_SYMBOL(omap_rfbi_update); | 811 | EXPORT_SYMBOL(omapdss_rfbi_set_interface_timings); |
829 | 812 | ||
830 | static void rfbi_dump_regs(struct seq_file *s) | 813 | static 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 | ||
870 | static void rfbi_config_lcd_manager(struct omap_dss_device *dssdev) | 853 | static 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 | ||
886 | int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev) | 891 | int 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; |
923 | err1: | 926 | err1: |
@@ -941,14 +944,17 @@ EXPORT_SYMBOL(omapdss_rfbi_display_disable); | |||
941 | static int __init rfbi_init_display(struct omap_dss_device *dssdev) | 944 | static 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 | ||
948 | static void __init rfbi_probe_pdata(struct platform_device *pdev) | 950 | static 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 | |||
978 | static 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 | |||
1010 | static 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 | |||
1021 | static 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 | ||
1032 | static int __exit omap_rfbihw_remove(struct platform_device *pdev) | 1090 | static 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 | ||