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 | ||
