diff options
163 files changed, 12023 insertions, 7620 deletions
diff --git a/Documentation/fb/udlfb.txt b/Documentation/fb/udlfb.txt index 7fdde2a02a27..57d2f2908b12 100644 --- a/Documentation/fb/udlfb.txt +++ b/Documentation/fb/udlfb.txt | |||
@@ -87,23 +87,38 @@ Special configuration for udlfb is usually unnecessary. There are a few | |||
87 | options, however. | 87 | options, however. |
88 | 88 | ||
89 | From the command line, pass options to modprobe | 89 | From the command line, pass options to modprobe |
90 | modprobe udlfb defio=1 console=1 | 90 | modprobe udlfb fb_defio=0 console=1 shadow=1 |
91 | 91 | ||
92 | Or for permanent option, create file like /etc/modprobe.d/options with text | 92 | Or modify options on the fly at /sys/module/udlfb/parameters directory via |
93 | options udlfb defio=1 console=1 | 93 | sudo nano fb_defio |
94 | change the parameter in place, and save the file. | ||
94 | 95 | ||
95 | Accepted options: | 96 | Unplug/replug USB device to apply with new settings |
97 | |||
98 | Or for permanent option, create file like /etc/modprobe.d/udlfb.conf with text | ||
99 | options udlfb fb_defio=0 console=1 shadow=1 | ||
100 | |||
101 | Accepted boolean options: | ||
96 | 102 | ||
97 | fb_defio Make use of the fb_defio (CONFIG_FB_DEFERRED_IO) kernel | 103 | fb_defio Make use of the fb_defio (CONFIG_FB_DEFERRED_IO) kernel |
98 | module to track changed areas of the framebuffer by page faults. | 104 | module to track changed areas of the framebuffer by page faults. |
99 | Standard fbdev applications that use mmap but that do not | 105 | Standard fbdev applications that use mmap but that do not |
100 | report damage, may be able to work with this enabled. | 106 | report damage, should be able to work with this enabled. |
101 | Disabled by default because of overhead and other issues. | 107 | Disable when running with X server that supports reporting |
102 | 108 | changed regions via ioctl, as this method is simpler, | |
103 | console Allow fbcon to attach to udlfb provided framebuffers. This | 109 | more stable, and higher performance. |
104 | is disabled by default because fbcon will aggressively consume | 110 | default: fb_defio=1 |
105 | the first framebuffer it finds, which isn't usually what the | 111 | |
106 | user wants in the case of USB displays. | 112 | console Allow fbcon to attach to udlfb provided framebuffers. |
113 | Can be disabled if fbcon and other clients | ||
114 | (e.g. X with --shared-vt) are in conflict. | ||
115 | default: console=1 | ||
116 | |||
117 | shadow Allocate a 2nd framebuffer to shadow what's currently across | ||
118 | the USB bus in device memory. If any pixels are unchanged, | ||
119 | do not transmit. Spends host memory to save USB transfers. | ||
120 | Enabled by default. Only disable on very low memory systems. | ||
121 | default: shadow=1 | ||
107 | 122 | ||
108 | Sysfs Attributes | 123 | Sysfs Attributes |
109 | ================ | 124 | ================ |
diff --git a/MAINTAINERS b/MAINTAINERS index 07e5dbd14273..2014c1ff8197 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -5970,6 +5970,12 @@ L: netdev@vger.kernel.org | |||
5970 | S: Supported | 5970 | S: Supported |
5971 | F: drivers/net/ethernet/smsc/smsc9420.* | 5971 | F: drivers/net/ethernet/smsc/smsc9420.* |
5972 | 5972 | ||
5973 | SMSC UFX6000 and UFX7000 USB to VGA DRIVER | ||
5974 | M: Steve Glendinning <steve.glendinning@smsc.com> | ||
5975 | L: linux-fbdev@vger.kernel.org | ||
5976 | S: Supported | ||
5977 | F: drivers/video/smscufx.c | ||
5978 | |||
5973 | SN-IA64 (Itanium) SUB-PLATFORM | 5979 | SN-IA64 (Itanium) SUB-PLATFORM |
5974 | M: Jes Sorensen <jes@sgi.com> | 5980 | M: Jes Sorensen <jes@sgi.com> |
5975 | L: linux-altix@sgi.com | 5981 | L: linux-altix@sgi.com |
diff --git a/arch/arm/mach-omap2/board-2430sdp.c b/arch/arm/mach-omap2/board-2430sdp.c index 87f43ade4405..f8ce84b69eb1 100644 --- a/arch/arm/mach-omap2/board-2430sdp.c +++ b/arch/arm/mach-omap2/board-2430sdp.c | |||
@@ -39,6 +39,9 @@ | |||
39 | #include <plat/usb.h> | 39 | #include <plat/usb.h> |
40 | #include <plat/gpmc-smc91x.h> | 40 | #include <plat/gpmc-smc91x.h> |
41 | 41 | ||
42 | #include <video/omapdss.h> | ||
43 | #include <video/omap-panel-generic-dpi.h> | ||
44 | |||
42 | #include "mux.h" | 45 | #include "mux.h" |
43 | #include "hsmmc.h" | 46 | #include "hsmmc.h" |
44 | #include "common-board-devices.h" | 47 | #include "common-board-devices.h" |
@@ -99,20 +102,72 @@ static struct platform_device sdp2430_flash_device = { | |||
99 | .resource = &sdp2430_flash_resource, | 102 | .resource = &sdp2430_flash_resource, |
100 | }; | 103 | }; |
101 | 104 | ||
102 | static struct platform_device sdp2430_lcd_device = { | ||
103 | .name = "sdp2430_lcd", | ||
104 | .id = -1, | ||
105 | }; | ||
106 | |||
107 | static struct platform_device *sdp2430_devices[] __initdata = { | 105 | static struct platform_device *sdp2430_devices[] __initdata = { |
108 | &sdp2430_flash_device, | 106 | &sdp2430_flash_device, |
107 | }; | ||
108 | |||
109 | /* LCD */ | ||
110 | #define SDP2430_LCD_PANEL_BACKLIGHT_GPIO 91 | ||
111 | #define SDP2430_LCD_PANEL_ENABLE_GPIO 154 | ||
112 | |||
113 | static int sdp2430_panel_enable_lcd(struct omap_dss_device *dssdev) | ||
114 | { | ||
115 | gpio_direction_output(SDP2430_LCD_PANEL_ENABLE_GPIO, 1); | ||
116 | gpio_direction_output(SDP2430_LCD_PANEL_BACKLIGHT_GPIO, 1); | ||
117 | |||
118 | return 0; | ||
119 | } | ||
120 | |||
121 | static void sdp2430_panel_disable_lcd(struct omap_dss_device *dssdev) | ||
122 | { | ||
123 | gpio_direction_output(SDP2430_LCD_PANEL_ENABLE_GPIO, 0); | ||
124 | gpio_direction_output(SDP2430_LCD_PANEL_BACKLIGHT_GPIO, 0); | ||
125 | } | ||
126 | |||
127 | static struct panel_generic_dpi_data sdp2430_panel_data = { | ||
128 | .name = "nec_nl2432dr22-11b", | ||
129 | .platform_enable = sdp2430_panel_enable_lcd, | ||
130 | .platform_disable = sdp2430_panel_disable_lcd, | ||
131 | }; | ||
132 | |||
133 | static struct omap_dss_device sdp2430_lcd_device = { | ||
134 | .name = "lcd", | ||
135 | .driver_name = "generic_dpi_panel", | ||
136 | .type = OMAP_DISPLAY_TYPE_DPI, | ||
137 | .phy.dpi.data_lines = 16, | ||
138 | .data = &sdp2430_panel_data, | ||
139 | }; | ||
140 | |||
141 | static struct omap_dss_device *sdp2430_dss_devices[] = { | ||
109 | &sdp2430_lcd_device, | 142 | &sdp2430_lcd_device, |
110 | }; | 143 | }; |
111 | 144 | ||
112 | static struct omap_lcd_config sdp2430_lcd_config __initdata = { | 145 | static struct omap_dss_board_info sdp2430_dss_data = { |
113 | .ctrl_name = "internal", | 146 | .num_devices = ARRAY_SIZE(sdp2430_dss_devices), |
147 | .devices = sdp2430_dss_devices, | ||
148 | .default_device = &sdp2430_lcd_device, | ||
114 | }; | 149 | }; |
115 | 150 | ||
151 | static void __init sdp2430_display_init(void) | ||
152 | { | ||
153 | int r; | ||
154 | |||
155 | static struct gpio gpios[] __initdata = { | ||
156 | { SDP2430_LCD_PANEL_ENABLE_GPIO, GPIOF_OUT_INIT_LOW, | ||
157 | "LCD reset" }, | ||
158 | { SDP2430_LCD_PANEL_BACKLIGHT_GPIO, GPIOF_OUT_INIT_LOW, | ||
159 | "LCD Backlight" }, | ||
160 | }; | ||
161 | |||
162 | r = gpio_request_array(gpios, ARRAY_SIZE(gpios)); | ||
163 | if (r) { | ||
164 | pr_err("Cannot request LCD GPIOs, error %d\n", r); | ||
165 | return; | ||
166 | } | ||
167 | |||
168 | omap_display_init(&sdp2430_dss_data); | ||
169 | } | ||
170 | |||
116 | #if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91x_MODULE) | 171 | #if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91x_MODULE) |
117 | 172 | ||
118 | static struct omap_smc91x_platform_data board_smc91x_data = { | 173 | static struct omap_smc91x_platform_data board_smc91x_data = { |
@@ -137,10 +192,6 @@ static inline void board_smc91x_init(void) | |||
137 | 192 | ||
138 | #endif | 193 | #endif |
139 | 194 | ||
140 | static struct omap_board_config_kernel sdp2430_config[] __initdata = { | ||
141 | {OMAP_TAG_LCD, &sdp2430_lcd_config}, | ||
142 | }; | ||
143 | |||
144 | static void __init omap_2430sdp_init_early(void) | 195 | static void __init omap_2430sdp_init_early(void) |
145 | { | 196 | { |
146 | omap2_init_common_infrastructure(); | 197 | omap2_init_common_infrastructure(); |
@@ -229,9 +280,6 @@ static void __init omap_2430sdp_init(void) | |||
229 | { | 280 | { |
230 | omap2430_mux_init(board_mux, OMAP_PACKAGE_ZAC); | 281 | omap2430_mux_init(board_mux, OMAP_PACKAGE_ZAC); |
231 | 282 | ||
232 | omap_board_config = sdp2430_config; | ||
233 | omap_board_config_size = ARRAY_SIZE(sdp2430_config); | ||
234 | |||
235 | omap2430_i2c_init(); | 283 | omap2430_i2c_init(); |
236 | 284 | ||
237 | platform_add_devices(sdp2430_devices, ARRAY_SIZE(sdp2430_devices)); | 285 | platform_add_devices(sdp2430_devices, ARRAY_SIZE(sdp2430_devices)); |
@@ -247,6 +295,8 @@ static void __init omap_2430sdp_init(void) | |||
247 | /* Turn off secondary LCD backlight */ | 295 | /* Turn off secondary LCD backlight */ |
248 | gpio_request_one(SECONDARY_LCD_GPIO, GPIOF_OUT_INIT_LOW, | 296 | gpio_request_one(SECONDARY_LCD_GPIO, GPIOF_OUT_INIT_LOW, |
249 | "Secondary LCD backlight"); | 297 | "Secondary LCD backlight"); |
298 | |||
299 | sdp2430_display_init(); | ||
250 | } | 300 | } |
251 | 301 | ||
252 | static void __init omap_2430sdp_map_io(void) | 302 | static void __init omap_2430sdp_map_io(void) |
diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c index 2430531b2239..204beddcb949 100644 --- a/arch/arm/mach-omap2/board-3430sdp.c +++ b/arch/arm/mach-omap2/board-3430sdp.c | |||
@@ -37,7 +37,7 @@ | |||
37 | #include <plat/dma.h> | 37 | #include <plat/dma.h> |
38 | #include <plat/gpmc.h> | 38 | #include <plat/gpmc.h> |
39 | #include <video/omapdss.h> | 39 | #include <video/omapdss.h> |
40 | #include <video/omap-panel-generic-dpi.h> | 40 | #include <video/omap-panel-dvi.h> |
41 | 41 | ||
42 | #include <plat/gpmc-smc91x.h> | 42 | #include <plat/gpmc-smc91x.h> |
43 | 43 | ||
@@ -186,8 +186,7 @@ static struct omap_dss_device sdp3430_lcd_device = { | |||
186 | .platform_disable = sdp3430_panel_disable_lcd, | 186 | .platform_disable = sdp3430_panel_disable_lcd, |
187 | }; | 187 | }; |
188 | 188 | ||
189 | static struct panel_generic_dpi_data dvi_panel = { | 189 | static struct panel_dvi_platform_data dvi_panel = { |
190 | .name = "generic", | ||
191 | .platform_enable = sdp3430_panel_enable_dvi, | 190 | .platform_enable = sdp3430_panel_enable_dvi, |
192 | .platform_disable = sdp3430_panel_disable_dvi, | 191 | .platform_disable = sdp3430_panel_disable_dvi, |
193 | }; | 192 | }; |
@@ -195,7 +194,7 @@ static struct panel_generic_dpi_data dvi_panel = { | |||
195 | static struct omap_dss_device sdp3430_dvi_device = { | 194 | static struct omap_dss_device sdp3430_dvi_device = { |
196 | .name = "dvi", | 195 | .name = "dvi", |
197 | .type = OMAP_DISPLAY_TYPE_DPI, | 196 | .type = OMAP_DISPLAY_TYPE_DPI, |
198 | .driver_name = "generic_dpi_panel", | 197 | .driver_name = "dvi", |
199 | .data = &dvi_panel, | 198 | .data = &dvi_panel, |
200 | .phy.dpi.data_lines = 24, | 199 | .phy.dpi.data_lines = 24, |
201 | }; | 200 | }; |
diff --git a/arch/arm/mach-omap2/board-4430sdp.c b/arch/arm/mach-omap2/board-4430sdp.c index be931105d681..484cec54882a 100644 --- a/arch/arm/mach-omap2/board-4430sdp.c +++ b/arch/arm/mach-omap2/board-4430sdp.c | |||
@@ -38,6 +38,8 @@ | |||
38 | #include <plat/mmc.h> | 38 | #include <plat/mmc.h> |
39 | #include <plat/omap4-keypad.h> | 39 | #include <plat/omap4-keypad.h> |
40 | #include <video/omapdss.h> | 40 | #include <video/omapdss.h> |
41 | #include <video/omap-panel-nokia-dsi.h> | ||
42 | #include <video/omap-panel-picodlp.h> | ||
41 | #include <linux/wl12xx.h> | 43 | #include <linux/wl12xx.h> |
42 | 44 | ||
43 | #include "mux.h" | 45 | #include "mux.h" |
@@ -52,6 +54,8 @@ | |||
52 | #define OMAP4_SFH7741_ENABLE_GPIO 188 | 54 | #define OMAP4_SFH7741_ENABLE_GPIO 188 |
53 | #define HDMI_GPIO_HPD 60 /* Hot plug pin for HDMI */ | 55 | #define HDMI_GPIO_HPD 60 /* Hot plug pin for HDMI */ |
54 | #define HDMI_GPIO_LS_OE 41 /* Level shifter for HDMI */ | 56 | #define HDMI_GPIO_LS_OE 41 /* Level shifter for HDMI */ |
57 | #define DISPLAY_SEL_GPIO 59 /* LCD2/PicoDLP switch */ | ||
58 | #define DLP_POWER_ON_GPIO 40 | ||
55 | 59 | ||
56 | #define GPIO_WIFI_PMENA 54 | 60 | #define GPIO_WIFI_PMENA 54 |
57 | #define GPIO_WIFI_IRQ 53 | 61 | #define GPIO_WIFI_IRQ 53 |
@@ -340,11 +344,6 @@ static int __init omap_ethernet_init(void) | |||
340 | return status; | 344 | return status; |
341 | } | 345 | } |
342 | 346 | ||
343 | static struct platform_device sdp4430_lcd_device = { | ||
344 | .name = "sdp4430_lcd", | ||
345 | .id = -1, | ||
346 | }; | ||
347 | |||
348 | static struct regulator_consumer_supply sdp4430_vbat_supply[] = { | 347 | static struct regulator_consumer_supply sdp4430_vbat_supply[] = { |
349 | REGULATOR_SUPPLY("vddvibl", "twl6040-vibra"), | 348 | REGULATOR_SUPPLY("vddvibl", "twl6040-vibra"), |
350 | REGULATOR_SUPPLY("vddvibr", "twl6040-vibra"), | 349 | REGULATOR_SUPPLY("vddvibr", "twl6040-vibra"), |
@@ -374,21 +373,12 @@ static struct platform_device sdp4430_vbat = { | |||
374 | }; | 373 | }; |
375 | 374 | ||
376 | static struct platform_device *sdp4430_devices[] __initdata = { | 375 | static struct platform_device *sdp4430_devices[] __initdata = { |
377 | &sdp4430_lcd_device, | ||
378 | &sdp4430_gpio_keys_device, | 376 | &sdp4430_gpio_keys_device, |
379 | &sdp4430_leds_gpio, | 377 | &sdp4430_leds_gpio, |
380 | &sdp4430_leds_pwm, | 378 | &sdp4430_leds_pwm, |
381 | &sdp4430_vbat, | 379 | &sdp4430_vbat, |
382 | }; | 380 | }; |
383 | 381 | ||
384 | static struct omap_lcd_config sdp4430_lcd_config __initdata = { | ||
385 | .ctrl_name = "internal", | ||
386 | }; | ||
387 | |||
388 | static struct omap_board_config_kernel sdp4430_config[] __initdata = { | ||
389 | { OMAP_TAG_LCD, &sdp4430_lcd_config }, | ||
390 | }; | ||
391 | |||
392 | static void __init omap_4430sdp_init_early(void) | 382 | static void __init omap_4430sdp_init_early(void) |
393 | { | 383 | { |
394 | omap2_init_common_infrastructure(); | 384 | omap2_init_common_infrastructure(); |
@@ -648,37 +638,202 @@ static void sdp4430_panel_disable_hdmi(struct omap_dss_device *dssdev) | |||
648 | gpio_free(HDMI_GPIO_HPD); | 638 | gpio_free(HDMI_GPIO_HPD); |
649 | } | 639 | } |
650 | 640 | ||
651 | static struct omap_dss_device sdp4430_hdmi_device = { | 641 | static struct nokia_dsi_panel_data dsi1_panel = { |
652 | .name = "hdmi", | 642 | .name = "taal", |
653 | .driver_name = "hdmi_panel", | 643 | .reset_gpio = 102, |
654 | .type = OMAP_DISPLAY_TYPE_HDMI, | 644 | .use_ext_te = false, |
655 | .clocks = { | 645 | .ext_te_gpio = 101, |
656 | .dispc = { | 646 | .esd_interval = 0, |
647 | }; | ||
648 | |||
649 | static struct omap_dss_device sdp4430_lcd_device = { | ||
650 | .name = "lcd", | ||
651 | .driver_name = "taal", | ||
652 | .type = OMAP_DISPLAY_TYPE_DSI, | ||
653 | .data = &dsi1_panel, | ||
654 | .phy.dsi = { | ||
655 | .clk_lane = 1, | ||
656 | .clk_pol = 0, | ||
657 | .data1_lane = 2, | ||
658 | .data1_pol = 0, | ||
659 | .data2_lane = 3, | ||
660 | .data2_pol = 0, | ||
661 | |||
662 | .module = 0, | ||
663 | }, | ||
664 | |||
665 | .clocks = { | ||
666 | .dispc = { | ||
667 | .channel = { | ||
668 | /* Logic Clock = 172.8 MHz */ | ||
669 | .lck_div = 1, | ||
670 | /* Pixel Clock = 34.56 MHz */ | ||
671 | .pck_div = 5, | ||
672 | .lcd_clk_src = OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC, | ||
673 | }, | ||
657 | .dispc_fclk_src = OMAP_DSS_CLK_SRC_FCK, | 674 | .dispc_fclk_src = OMAP_DSS_CLK_SRC_FCK, |
658 | }, | 675 | }, |
659 | .hdmi = { | 676 | |
660 | .regn = 15, | 677 | .dsi = { |
661 | .regm2 = 1, | 678 | .regn = 16, /* Fint = 2.4 MHz */ |
679 | .regm = 180, /* DDR Clock = 216 MHz */ | ||
680 | .regm_dispc = 5, /* PLL1_CLK1 = 172.8 MHz */ | ||
681 | .regm_dsi = 5, /* PLL1_CLK2 = 172.8 MHz */ | ||
682 | |||
683 | .lp_clk_div = 10, /* LP Clock = 8.64 MHz */ | ||
684 | .dsi_fclk_src = OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI, | ||
685 | }, | ||
686 | }, | ||
687 | .channel = OMAP_DSS_CHANNEL_LCD, | ||
688 | }; | ||
689 | |||
690 | static struct nokia_dsi_panel_data dsi2_panel = { | ||
691 | .name = "taal", | ||
692 | .reset_gpio = 104, | ||
693 | .use_ext_te = false, | ||
694 | .ext_te_gpio = 103, | ||
695 | .esd_interval = 0, | ||
696 | }; | ||
697 | |||
698 | static struct omap_dss_device sdp4430_lcd2_device = { | ||
699 | .name = "lcd2", | ||
700 | .driver_name = "taal", | ||
701 | .type = OMAP_DISPLAY_TYPE_DSI, | ||
702 | .data = &dsi2_panel, | ||
703 | .phy.dsi = { | ||
704 | .clk_lane = 1, | ||
705 | .clk_pol = 0, | ||
706 | .data1_lane = 2, | ||
707 | .data1_pol = 0, | ||
708 | .data2_lane = 3, | ||
709 | .data2_pol = 0, | ||
710 | |||
711 | .module = 1, | ||
712 | }, | ||
713 | |||
714 | .clocks = { | ||
715 | .dispc = { | ||
716 | .channel = { | ||
717 | /* Logic Clock = 172.8 MHz */ | ||
718 | .lck_div = 1, | ||
719 | /* Pixel Clock = 34.56 MHz */ | ||
720 | .pck_div = 5, | ||
721 | .lcd_clk_src = OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC, | ||
722 | }, | ||
723 | .dispc_fclk_src = OMAP_DSS_CLK_SRC_FCK, | ||
724 | }, | ||
725 | |||
726 | .dsi = { | ||
727 | .regn = 16, /* Fint = 2.4 MHz */ | ||
728 | .regm = 180, /* DDR Clock = 216 MHz */ | ||
729 | .regm_dispc = 5, /* PLL1_CLK1 = 172.8 MHz */ | ||
730 | .regm_dsi = 5, /* PLL1_CLK2 = 172.8 MHz */ | ||
731 | |||
732 | .lp_clk_div = 10, /* LP Clock = 8.64 MHz */ | ||
733 | .dsi_fclk_src = OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI, | ||
662 | }, | 734 | }, |
663 | }, | 735 | }, |
736 | .channel = OMAP_DSS_CHANNEL_LCD2, | ||
737 | }; | ||
738 | |||
739 | static void sdp4430_lcd_init(void) | ||
740 | { | ||
741 | int r; | ||
742 | |||
743 | r = gpio_request_one(dsi1_panel.reset_gpio, GPIOF_DIR_OUT, | ||
744 | "lcd1_reset_gpio"); | ||
745 | if (r) | ||
746 | pr_err("%s: Could not get lcd1_reset_gpio\n", __func__); | ||
747 | |||
748 | r = gpio_request_one(dsi2_panel.reset_gpio, GPIOF_DIR_OUT, | ||
749 | "lcd2_reset_gpio"); | ||
750 | if (r) | ||
751 | pr_err("%s: Could not get lcd2_reset_gpio\n", __func__); | ||
752 | } | ||
753 | |||
754 | static struct omap_dss_device sdp4430_hdmi_device = { | ||
755 | .name = "hdmi", | ||
756 | .driver_name = "hdmi_panel", | ||
757 | .type = OMAP_DISPLAY_TYPE_HDMI, | ||
664 | .platform_enable = sdp4430_panel_enable_hdmi, | 758 | .platform_enable = sdp4430_panel_enable_hdmi, |
665 | .platform_disable = sdp4430_panel_disable_hdmi, | 759 | .platform_disable = sdp4430_panel_disable_hdmi, |
666 | .channel = OMAP_DSS_CHANNEL_DIGIT, | 760 | .channel = OMAP_DSS_CHANNEL_DIGIT, |
667 | }; | 761 | }; |
668 | 762 | ||
763 | static struct picodlp_panel_data sdp4430_picodlp_pdata = { | ||
764 | .picodlp_adapter_id = 2, | ||
765 | .emu_done_gpio = 44, | ||
766 | .pwrgood_gpio = 45, | ||
767 | }; | ||
768 | |||
769 | static void sdp4430_picodlp_init(void) | ||
770 | { | ||
771 | int r; | ||
772 | const struct gpio picodlp_gpios[] = { | ||
773 | {DLP_POWER_ON_GPIO, GPIOF_OUT_INIT_LOW, | ||
774 | "DLP POWER ON"}, | ||
775 | {sdp4430_picodlp_pdata.emu_done_gpio, GPIOF_IN, | ||
776 | "DLP EMU DONE"}, | ||
777 | {sdp4430_picodlp_pdata.pwrgood_gpio, GPIOF_OUT_INIT_LOW, | ||
778 | "DLP PWRGOOD"}, | ||
779 | }; | ||
780 | |||
781 | r = gpio_request_array(picodlp_gpios, ARRAY_SIZE(picodlp_gpios)); | ||
782 | if (r) | ||
783 | pr_err("Cannot request PicoDLP GPIOs, error %d\n", r); | ||
784 | } | ||
785 | |||
786 | static int sdp4430_panel_enable_picodlp(struct omap_dss_device *dssdev) | ||
787 | { | ||
788 | gpio_set_value(DISPLAY_SEL_GPIO, 0); | ||
789 | gpio_set_value(DLP_POWER_ON_GPIO, 1); | ||
790 | |||
791 | return 0; | ||
792 | } | ||
793 | |||
794 | static void sdp4430_panel_disable_picodlp(struct omap_dss_device *dssdev) | ||
795 | { | ||
796 | gpio_set_value(DLP_POWER_ON_GPIO, 0); | ||
797 | gpio_set_value(DISPLAY_SEL_GPIO, 1); | ||
798 | } | ||
799 | |||
800 | static struct omap_dss_device sdp4430_picodlp_device = { | ||
801 | .name = "picodlp", | ||
802 | .driver_name = "picodlp_panel", | ||
803 | .type = OMAP_DISPLAY_TYPE_DPI, | ||
804 | .phy.dpi.data_lines = 24, | ||
805 | .channel = OMAP_DSS_CHANNEL_LCD2, | ||
806 | .platform_enable = sdp4430_panel_enable_picodlp, | ||
807 | .platform_disable = sdp4430_panel_disable_picodlp, | ||
808 | .data = &sdp4430_picodlp_pdata, | ||
809 | }; | ||
810 | |||
669 | static struct omap_dss_device *sdp4430_dss_devices[] = { | 811 | static struct omap_dss_device *sdp4430_dss_devices[] = { |
812 | &sdp4430_lcd_device, | ||
813 | &sdp4430_lcd2_device, | ||
670 | &sdp4430_hdmi_device, | 814 | &sdp4430_hdmi_device, |
815 | &sdp4430_picodlp_device, | ||
671 | }; | 816 | }; |
672 | 817 | ||
673 | static struct omap_dss_board_info sdp4430_dss_data = { | 818 | static struct omap_dss_board_info sdp4430_dss_data = { |
674 | .num_devices = ARRAY_SIZE(sdp4430_dss_devices), | 819 | .num_devices = ARRAY_SIZE(sdp4430_dss_devices), |
675 | .devices = sdp4430_dss_devices, | 820 | .devices = sdp4430_dss_devices, |
676 | .default_device = &sdp4430_hdmi_device, | 821 | .default_device = &sdp4430_lcd_device, |
677 | }; | 822 | }; |
678 | 823 | ||
679 | void omap_4430sdp_display_init(void) | 824 | static void omap_4430sdp_display_init(void) |
680 | { | 825 | { |
826 | int r; | ||
827 | |||
828 | /* Enable LCD2 by default (instead of Pico DLP) */ | ||
829 | r = gpio_request_one(DISPLAY_SEL_GPIO, GPIOF_OUT_INIT_HIGH, | ||
830 | "display_sel"); | ||
831 | if (r) | ||
832 | pr_err("%s: Could not get display_sel GPIO\n", __func__); | ||
833 | |||
834 | sdp4430_lcd_init(); | ||
681 | sdp4430_hdmi_mux_init(); | 835 | sdp4430_hdmi_mux_init(); |
836 | sdp4430_picodlp_init(); | ||
682 | omap_display_init(&sdp4430_dss_data); | 837 | omap_display_init(&sdp4430_dss_data); |
683 | } | 838 | } |
684 | 839 | ||
@@ -802,9 +957,6 @@ static void __init omap_4430sdp_init(void) | |||
802 | package = OMAP_PACKAGE_CBL; | 957 | package = OMAP_PACKAGE_CBL; |
803 | omap4_mux_init(board_mux, NULL, package); | 958 | omap4_mux_init(board_mux, NULL, package); |
804 | 959 | ||
805 | omap_board_config = sdp4430_config; | ||
806 | omap_board_config_size = ARRAY_SIZE(sdp4430_config); | ||
807 | |||
808 | omap4_i2c_init(); | 960 | omap4_i2c_init(); |
809 | omap_sfh7741prox_init(); | 961 | omap_sfh7741prox_init(); |
810 | platform_add_devices(sdp4430_devices, ARRAY_SIZE(sdp4430_devices)); | 962 | platform_add_devices(sdp4430_devices, ARRAY_SIZE(sdp4430_devices)); |
diff --git a/arch/arm/mach-omap2/board-am3517evm.c b/arch/arm/mach-omap2/board-am3517evm.c index 1325085e453d..ab10f75984d8 100644 --- a/arch/arm/mach-omap2/board-am3517evm.c +++ b/arch/arm/mach-omap2/board-am3517evm.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <plat/usb.h> | 36 | #include <plat/usb.h> |
37 | #include <video/omapdss.h> | 37 | #include <video/omapdss.h> |
38 | #include <video/omap-panel-generic-dpi.h> | 38 | #include <video/omap-panel-generic-dpi.h> |
39 | #include <video/omap-panel-dvi.h> | ||
39 | 40 | ||
40 | #include "mux.h" | 41 | #include "mux.h" |
41 | #include "control.h" | 42 | #include "control.h" |
@@ -333,8 +334,7 @@ static void am3517_evm_panel_disable_dvi(struct omap_dss_device *dssdev) | |||
333 | dvi_enabled = 0; | 334 | dvi_enabled = 0; |
334 | } | 335 | } |
335 | 336 | ||
336 | static struct panel_generic_dpi_data dvi_panel = { | 337 | static struct panel_dvi_platform_data dvi_panel = { |
337 | .name = "generic", | ||
338 | .platform_enable = am3517_evm_panel_enable_dvi, | 338 | .platform_enable = am3517_evm_panel_enable_dvi, |
339 | .platform_disable = am3517_evm_panel_disable_dvi, | 339 | .platform_disable = am3517_evm_panel_disable_dvi, |
340 | }; | 340 | }; |
@@ -342,7 +342,7 @@ static struct panel_generic_dpi_data dvi_panel = { | |||
342 | static struct omap_dss_device am3517_evm_dvi_device = { | 342 | static struct omap_dss_device am3517_evm_dvi_device = { |
343 | .type = OMAP_DISPLAY_TYPE_DPI, | 343 | .type = OMAP_DISPLAY_TYPE_DPI, |
344 | .name = "dvi", | 344 | .name = "dvi", |
345 | .driver_name = "generic_dpi_panel", | 345 | .driver_name = "dvi", |
346 | .data = &dvi_panel, | 346 | .data = &dvi_panel, |
347 | .phy.dpi.data_lines = 24, | 347 | .phy.dpi.data_lines = 24, |
348 | }; | 348 | }; |
diff --git a/arch/arm/mach-omap2/board-apollon.c b/arch/arm/mach-omap2/board-apollon.c index 67800e647d7a..ad55351e0cab 100644 --- a/arch/arm/mach-omap2/board-apollon.c +++ b/arch/arm/mach-omap2/board-apollon.c | |||
@@ -40,6 +40,9 @@ | |||
40 | #include <plat/common.h> | 40 | #include <plat/common.h> |
41 | #include <plat/gpmc.h> | 41 | #include <plat/gpmc.h> |
42 | 42 | ||
43 | #include <video/omapdss.h> | ||
44 | #include <video/omap-panel-generic-dpi.h> | ||
45 | |||
43 | #include "mux.h" | 46 | #include "mux.h" |
44 | #include "control.h" | 47 | #include "control.h" |
45 | 48 | ||
@@ -149,11 +152,6 @@ static struct platform_device apollon_smc91x_device = { | |||
149 | .resource = apollon_smc91x_resources, | 152 | .resource = apollon_smc91x_resources, |
150 | }; | 153 | }; |
151 | 154 | ||
152 | static struct platform_device apollon_lcd_device = { | ||
153 | .name = "apollon_lcd", | ||
154 | .id = -1, | ||
155 | }; | ||
156 | |||
157 | static struct omap_led_config apollon_led_config[] = { | 155 | static struct omap_led_config apollon_led_config[] = { |
158 | { | 156 | { |
159 | .cdev = { | 157 | .cdev = { |
@@ -191,7 +189,6 @@ static struct platform_device apollon_led_device = { | |||
191 | static struct platform_device *apollon_devices[] __initdata = { | 189 | static struct platform_device *apollon_devices[] __initdata = { |
192 | &apollon_onenand_device, | 190 | &apollon_onenand_device, |
193 | &apollon_smc91x_device, | 191 | &apollon_smc91x_device, |
194 | &apollon_lcd_device, | ||
195 | &apollon_led_device, | 192 | &apollon_led_device, |
196 | }; | 193 | }; |
197 | 194 | ||
@@ -265,12 +262,26 @@ static struct omap_usb_config apollon_usb_config __initdata = { | |||
265 | .pins[0] = 6, | 262 | .pins[0] = 6, |
266 | }; | 263 | }; |
267 | 264 | ||
268 | static struct omap_lcd_config apollon_lcd_config __initdata = { | 265 | static struct panel_generic_dpi_data apollon_panel_data = { |
269 | .ctrl_name = "internal", | 266 | .name = "apollon", |
270 | }; | 267 | }; |
271 | 268 | ||
272 | static struct omap_board_config_kernel apollon_config[] __initdata = { | 269 | static struct omap_dss_device apollon_lcd_device = { |
273 | { OMAP_TAG_LCD, &apollon_lcd_config }, | 270 | .name = "lcd", |
271 | .driver_name = "generic_dpi_panel", | ||
272 | .type = OMAP_DISPLAY_TYPE_DPI, | ||
273 | .phy.dpi.data_lines = 18, | ||
274 | .data = &apollon_panel_data, | ||
275 | }; | ||
276 | |||
277 | static struct omap_dss_device *apollon_dss_devices[] = { | ||
278 | &apollon_lcd_device, | ||
279 | }; | ||
280 | |||
281 | static struct omap_dss_board_info apollon_dss_data = { | ||
282 | .num_devices = ARRAY_SIZE(apollon_dss_devices), | ||
283 | .devices = apollon_dss_devices, | ||
284 | .default_device = &apollon_lcd_device, | ||
274 | }; | 285 | }; |
275 | 286 | ||
276 | static void __init omap_apollon_init_early(void) | 287 | static void __init omap_apollon_init_early(void) |
@@ -314,8 +325,6 @@ static void __init omap_apollon_init(void) | |||
314 | u32 v; | 325 | u32 v; |
315 | 326 | ||
316 | omap2420_mux_init(board_mux, OMAP_PACKAGE_ZAC); | 327 | omap2420_mux_init(board_mux, OMAP_PACKAGE_ZAC); |
317 | omap_board_config = apollon_config; | ||
318 | omap_board_config_size = ARRAY_SIZE(apollon_config); | ||
319 | 328 | ||
320 | apollon_init_smc91x(); | 329 | apollon_init_smc91x(); |
321 | apollon_led_init(); | 330 | apollon_led_init(); |
@@ -340,6 +349,8 @@ static void __init omap_apollon_init(void) | |||
340 | */ | 349 | */ |
341 | platform_add_devices(apollon_devices, ARRAY_SIZE(apollon_devices)); | 350 | platform_add_devices(apollon_devices, ARRAY_SIZE(apollon_devices)); |
342 | omap_serial_init(); | 351 | omap_serial_init(); |
352 | |||
353 | omap_display_init(&apollon_dss_data); | ||
343 | } | 354 | } |
344 | 355 | ||
345 | static void __init omap_apollon_map_io(void) | 356 | static void __init omap_apollon_map_io(void) |
diff --git a/arch/arm/mach-omap2/board-cm-t35.c b/arch/arm/mach-omap2/board-cm-t35.c index 38179c175503..6e0f0d2e39bc 100644 --- a/arch/arm/mach-omap2/board-cm-t35.c +++ b/arch/arm/mach-omap2/board-cm-t35.c | |||
@@ -43,6 +43,7 @@ | |||
43 | #include <plat/usb.h> | 43 | #include <plat/usb.h> |
44 | #include <video/omapdss.h> | 44 | #include <video/omapdss.h> |
45 | #include <video/omap-panel-generic-dpi.h> | 45 | #include <video/omap-panel-generic-dpi.h> |
46 | #include <video/omap-panel-dvi.h> | ||
46 | #include <plat/mcspi.h> | 47 | #include <plat/mcspi.h> |
47 | 48 | ||
48 | #include <mach/hardware.h> | 49 | #include <mach/hardware.h> |
@@ -242,8 +243,7 @@ static struct omap_dss_device cm_t35_lcd_device = { | |||
242 | .phy.dpi.data_lines = 18, | 243 | .phy.dpi.data_lines = 18, |
243 | }; | 244 | }; |
244 | 245 | ||
245 | static struct panel_generic_dpi_data dvi_panel = { | 246 | static struct panel_dvi_platform_data dvi_panel = { |
246 | .name = "generic", | ||
247 | .platform_enable = cm_t35_panel_enable_dvi, | 247 | .platform_enable = cm_t35_panel_enable_dvi, |
248 | .platform_disable = cm_t35_panel_disable_dvi, | 248 | .platform_disable = cm_t35_panel_disable_dvi, |
249 | }; | 249 | }; |
@@ -251,7 +251,7 @@ static struct panel_generic_dpi_data dvi_panel = { | |||
251 | static struct omap_dss_device cm_t35_dvi_device = { | 251 | static struct omap_dss_device cm_t35_dvi_device = { |
252 | .name = "dvi", | 252 | .name = "dvi", |
253 | .type = OMAP_DISPLAY_TYPE_DPI, | 253 | .type = OMAP_DISPLAY_TYPE_DPI, |
254 | .driver_name = "generic_dpi_panel", | 254 | .driver_name = "dvi", |
255 | .data = &dvi_panel, | 255 | .data = &dvi_panel, |
256 | .phy.dpi.data_lines = 24, | 256 | .phy.dpi.data_lines = 24, |
257 | }; | 257 | }; |
diff --git a/arch/arm/mach-omap2/board-devkit8000.c b/arch/arm/mach-omap2/board-devkit8000.c index 99a42432ac93..d9bfe54917e4 100644 --- a/arch/arm/mach-omap2/board-devkit8000.c +++ b/arch/arm/mach-omap2/board-devkit8000.c | |||
@@ -47,6 +47,7 @@ | |||
47 | #include <plat/usb.h> | 47 | #include <plat/usb.h> |
48 | #include <video/omapdss.h> | 48 | #include <video/omapdss.h> |
49 | #include <video/omap-panel-generic-dpi.h> | 49 | #include <video/omap-panel-generic-dpi.h> |
50 | #include <video/omap-panel-dvi.h> | ||
50 | 51 | ||
51 | #include <plat/mcspi.h> | 52 | #include <plat/mcspi.h> |
52 | #include <linux/input/matrix_keypad.h> | 53 | #include <linux/input/matrix_keypad.h> |
@@ -139,7 +140,7 @@ static struct regulator_consumer_supply devkit8000_vio_supply[] = { | |||
139 | }; | 140 | }; |
140 | 141 | ||
141 | static struct panel_generic_dpi_data lcd_panel = { | 142 | static struct panel_generic_dpi_data lcd_panel = { |
142 | .name = "generic", | 143 | .name = "innolux_at070tn83", |
143 | .platform_enable = devkit8000_panel_enable_lcd, | 144 | .platform_enable = devkit8000_panel_enable_lcd, |
144 | .platform_disable = devkit8000_panel_disable_lcd, | 145 | .platform_disable = devkit8000_panel_disable_lcd, |
145 | }; | 146 | }; |
@@ -152,8 +153,7 @@ static struct omap_dss_device devkit8000_lcd_device = { | |||
152 | .phy.dpi.data_lines = 24, | 153 | .phy.dpi.data_lines = 24, |
153 | }; | 154 | }; |
154 | 155 | ||
155 | static struct panel_generic_dpi_data dvi_panel = { | 156 | static struct panel_dvi_platform_data dvi_panel = { |
156 | .name = "generic", | ||
157 | .platform_enable = devkit8000_panel_enable_dvi, | 157 | .platform_enable = devkit8000_panel_enable_dvi, |
158 | .platform_disable = devkit8000_panel_disable_dvi, | 158 | .platform_disable = devkit8000_panel_disable_dvi, |
159 | }; | 159 | }; |
@@ -161,7 +161,7 @@ static struct panel_generic_dpi_data dvi_panel = { | |||
161 | static struct omap_dss_device devkit8000_dvi_device = { | 161 | static struct omap_dss_device devkit8000_dvi_device = { |
162 | .name = "dvi", | 162 | .name = "dvi", |
163 | .type = OMAP_DISPLAY_TYPE_DPI, | 163 | .type = OMAP_DISPLAY_TYPE_DPI, |
164 | .driver_name = "generic_dpi_panel", | 164 | .driver_name = "dvi", |
165 | .data = &dvi_panel, | 165 | .data = &dvi_panel, |
166 | .phy.dpi.data_lines = 24, | 166 | .phy.dpi.data_lines = 24, |
167 | }; | 167 | }; |
@@ -267,7 +267,7 @@ static struct twl4030_gpio_platform_data devkit8000_gpio_data = { | |||
267 | 267 | ||
268 | static struct regulator_consumer_supply devkit8000_vpll1_supplies[] = { | 268 | static struct regulator_consumer_supply devkit8000_vpll1_supplies[] = { |
269 | REGULATOR_SUPPLY("vdds_dsi", "omapdss"), | 269 | REGULATOR_SUPPLY("vdds_dsi", "omapdss"), |
270 | REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi1"), | 270 | REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi.0"), |
271 | }; | 271 | }; |
272 | 272 | ||
273 | /* VMMC1 for MMC1 pins CMD, CLK, DAT0..DAT3 (20 mA, plus card == max 220 mA) */ | 273 | /* VMMC1 for MMC1 pins CMD, CLK, DAT0..DAT3 (20 mA, plus card == max 220 mA) */ |
diff --git a/arch/arm/mach-omap2/board-h4.c b/arch/arm/mach-omap2/board-h4.c index 82421a4cfa92..8fcf79628ca1 100644 --- a/arch/arm/mach-omap2/board-h4.c +++ b/arch/arm/mach-omap2/board-h4.c | |||
@@ -39,6 +39,9 @@ | |||
39 | #include <plat/dma.h> | 39 | #include <plat/dma.h> |
40 | #include <plat/gpmc.h> | 40 | #include <plat/gpmc.h> |
41 | 41 | ||
42 | #include <video/omapdss.h> | ||
43 | #include <video/omap-panel-generic-dpi.h> | ||
44 | |||
42 | #include "mux.h" | 45 | #include "mux.h" |
43 | #include "control.h" | 46 | #include "control.h" |
44 | 47 | ||
@@ -156,17 +159,33 @@ static struct platform_device h4_kp_device = { | |||
156 | }, | 159 | }, |
157 | }; | 160 | }; |
158 | 161 | ||
159 | static struct platform_device h4_lcd_device = { | ||
160 | .name = "lcd_h4", | ||
161 | .id = -1, | ||
162 | }; | ||
163 | |||
164 | static struct platform_device *h4_devices[] __initdata = { | 162 | static struct platform_device *h4_devices[] __initdata = { |
165 | &h4_flash_device, | 163 | &h4_flash_device, |
166 | &h4_kp_device, | 164 | &h4_kp_device, |
165 | }; | ||
166 | |||
167 | static struct panel_generic_dpi_data h4_panel_data = { | ||
168 | .name = "h4", | ||
169 | }; | ||
170 | |||
171 | static struct omap_dss_device h4_lcd_device = { | ||
172 | .name = "lcd", | ||
173 | .driver_name = "generic_dpi_panel", | ||
174 | .type = OMAP_DISPLAY_TYPE_DPI, | ||
175 | .phy.dpi.data_lines = 16, | ||
176 | .data = &h4_panel_data, | ||
177 | }; | ||
178 | |||
179 | static struct omap_dss_device *h4_dss_devices[] = { | ||
167 | &h4_lcd_device, | 180 | &h4_lcd_device, |
168 | }; | 181 | }; |
169 | 182 | ||
183 | static struct omap_dss_board_info h4_dss_data = { | ||
184 | .num_devices = ARRAY_SIZE(h4_dss_devices), | ||
185 | .devices = h4_dss_devices, | ||
186 | .default_device = &h4_lcd_device, | ||
187 | }; | ||
188 | |||
170 | /* 2420 Sysboot setup (2430 is different) */ | 189 | /* 2420 Sysboot setup (2430 is different) */ |
171 | static u32 get_sysboot_value(void) | 190 | static u32 get_sysboot_value(void) |
172 | { | 191 | { |
@@ -270,10 +289,6 @@ static void __init h4_init_flash(void) | |||
270 | h4_flash_resource.end = base + SZ_64M - 1; | 289 | h4_flash_resource.end = base + SZ_64M - 1; |
271 | } | 290 | } |
272 | 291 | ||
273 | static struct omap_lcd_config h4_lcd_config __initdata = { | ||
274 | .ctrl_name = "internal", | ||
275 | }; | ||
276 | |||
277 | static struct omap_usb_config h4_usb_config __initdata = { | 292 | static struct omap_usb_config h4_usb_config __initdata = { |
278 | /* S1.10 OFF -- usb "download port" | 293 | /* S1.10 OFF -- usb "download port" |
279 | * usb0 switched to Mini-B port and isp1105 transceiver; | 294 | * usb0 switched to Mini-B port and isp1105 transceiver; |
@@ -285,10 +300,6 @@ static struct omap_usb_config h4_usb_config __initdata = { | |||
285 | .hmc_mode = 0x00, /* 0:dev|otg 1:disable 2:disable */ | 300 | .hmc_mode = 0x00, /* 0:dev|otg 1:disable 2:disable */ |
286 | }; | 301 | }; |
287 | 302 | ||
288 | static struct omap_board_config_kernel h4_config[] __initdata = { | ||
289 | { OMAP_TAG_LCD, &h4_lcd_config }, | ||
290 | }; | ||
291 | |||
292 | static void __init omap_h4_init_early(void) | 303 | static void __init omap_h4_init_early(void) |
293 | { | 304 | { |
294 | omap2_init_common_infrastructure(); | 305 | omap2_init_common_infrastructure(); |
@@ -330,9 +341,6 @@ static void __init omap_h4_init(void) | |||
330 | { | 341 | { |
331 | omap2420_mux_init(board_mux, OMAP_PACKAGE_ZAF); | 342 | omap2420_mux_init(board_mux, OMAP_PACKAGE_ZAF); |
332 | 343 | ||
333 | omap_board_config = h4_config; | ||
334 | omap_board_config_size = ARRAY_SIZE(h4_config); | ||
335 | |||
336 | /* | 344 | /* |
337 | * Make sure the serial ports are muxed on at this point. | 345 | * Make sure the serial ports are muxed on at this point. |
338 | * You have to mux them off in device drivers later on | 346 | * You have to mux them off in device drivers later on |
@@ -371,6 +379,8 @@ static void __init omap_h4_init(void) | |||
371 | omap2_usbfs_init(&h4_usb_config); | 379 | omap2_usbfs_init(&h4_usb_config); |
372 | omap_serial_init(); | 380 | omap_serial_init(); |
373 | h4_init_flash(); | 381 | h4_init_flash(); |
382 | |||
383 | omap_display_init(&h4_dss_data); | ||
374 | } | 384 | } |
375 | 385 | ||
376 | static void __init omap_h4_map_io(void) | 386 | static void __init omap_h4_map_io(void) |
diff --git a/arch/arm/mach-omap2/board-igep0020.c b/arch/arm/mach-omap2/board-igep0020.c index 7040352b16b4..96f9ef34d2fb 100644 --- a/arch/arm/mach-omap2/board-igep0020.c +++ b/arch/arm/mach-omap2/board-igep0020.c | |||
@@ -32,7 +32,7 @@ | |||
32 | #include <plat/gpmc.h> | 32 | #include <plat/gpmc.h> |
33 | #include <plat/usb.h> | 33 | #include <plat/usb.h> |
34 | #include <video/omapdss.h> | 34 | #include <video/omapdss.h> |
35 | #include <video/omap-panel-generic-dpi.h> | 35 | #include <video/omap-panel-dvi.h> |
36 | #include <plat/onenand.h> | 36 | #include <plat/onenand.h> |
37 | 37 | ||
38 | #include "mux.h" | 38 | #include "mux.h" |
@@ -455,16 +455,16 @@ static void igep2_disable_dvi(struct omap_dss_device *dssdev) | |||
455 | gpio_direction_output(IGEP2_GPIO_DVI_PUP, 0); | 455 | gpio_direction_output(IGEP2_GPIO_DVI_PUP, 0); |
456 | } | 456 | } |
457 | 457 | ||
458 | static struct panel_generic_dpi_data dvi_panel = { | 458 | static struct panel_dvi_platform_data dvi_panel = { |
459 | .name = "generic", | ||
460 | .platform_enable = igep2_enable_dvi, | 459 | .platform_enable = igep2_enable_dvi, |
461 | .platform_disable = igep2_disable_dvi, | 460 | .platform_disable = igep2_disable_dvi, |
461 | .i2c_bus_num = 3, | ||
462 | }; | 462 | }; |
463 | 463 | ||
464 | static struct omap_dss_device igep2_dvi_device = { | 464 | static struct omap_dss_device igep2_dvi_device = { |
465 | .type = OMAP_DISPLAY_TYPE_DPI, | 465 | .type = OMAP_DISPLAY_TYPE_DPI, |
466 | .name = "dvi", | 466 | .name = "dvi", |
467 | .driver_name = "generic_dpi_panel", | 467 | .driver_name = "dvi", |
468 | .data = &dvi_panel, | 468 | .data = &dvi_panel, |
469 | .phy.dpi.data_lines = 24, | 469 | .phy.dpi.data_lines = 24, |
470 | }; | 470 | }; |
diff --git a/arch/arm/mach-omap2/board-ldp.c b/arch/arm/mach-omap2/board-ldp.c index abe8c7e496a2..f8f8a68a4899 100644 --- a/arch/arm/mach-omap2/board-ldp.c +++ b/arch/arm/mach-omap2/board-ldp.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/io.h> | 27 | #include <linux/io.h> |
28 | #include <linux/smsc911x.h> | 28 | #include <linux/smsc911x.h> |
29 | #include <linux/mmc/host.h> | 29 | #include <linux/mmc/host.h> |
30 | #include <linux/gpio.h> | ||
30 | 31 | ||
31 | #include <mach/hardware.h> | 32 | #include <mach/hardware.h> |
32 | #include <asm/mach-types.h> | 33 | #include <asm/mach-types.h> |
@@ -43,6 +44,9 @@ | |||
43 | #include <plat/usb.h> | 44 | #include <plat/usb.h> |
44 | #include <plat/gpmc-smsc911x.h> | 45 | #include <plat/gpmc-smsc911x.h> |
45 | 46 | ||
47 | #include <video/omapdss.h> | ||
48 | #include <video/omap-panel-generic-dpi.h> | ||
49 | |||
46 | #include "board-flash.h" | 50 | #include "board-flash.h" |
47 | #include "mux.h" | 51 | #include "mux.h" |
48 | #include "hsmmc.h" | 52 | #include "hsmmc.h" |
@@ -179,29 +183,108 @@ static inline void __init ldp_init_smsc911x(void) | |||
179 | gpmc_smsc911x_init(&smsc911x_cfg); | 183 | gpmc_smsc911x_init(&smsc911x_cfg); |
180 | } | 184 | } |
181 | 185 | ||
182 | static struct platform_device ldp_lcd_device = { | 186 | /* LCD */ |
183 | .name = "ldp_lcd", | 187 | |
184 | .id = -1, | 188 | static int ldp_backlight_gpio; |
189 | static int ldp_lcd_enable_gpio; | ||
190 | |||
191 | #define LCD_PANEL_RESET_GPIO 55 | ||
192 | #define LCD_PANEL_QVGA_GPIO 56 | ||
193 | |||
194 | static int ldp_panel_enable_lcd(struct omap_dss_device *dssdev) | ||
195 | { | ||
196 | if (gpio_is_valid(ldp_lcd_enable_gpio)) | ||
197 | gpio_direction_output(ldp_lcd_enable_gpio, 1); | ||
198 | if (gpio_is_valid(ldp_backlight_gpio)) | ||
199 | gpio_direction_output(ldp_backlight_gpio, 1); | ||
200 | |||
201 | return 0; | ||
202 | } | ||
203 | |||
204 | static void ldp_panel_disable_lcd(struct omap_dss_device *dssdev) | ||
205 | { | ||
206 | if (gpio_is_valid(ldp_lcd_enable_gpio)) | ||
207 | gpio_direction_output(ldp_lcd_enable_gpio, 0); | ||
208 | if (gpio_is_valid(ldp_backlight_gpio)) | ||
209 | gpio_direction_output(ldp_backlight_gpio, 0); | ||
210 | } | ||
211 | |||
212 | static struct panel_generic_dpi_data ldp_panel_data = { | ||
213 | .name = "nec_nl2432dr22-11b", | ||
214 | .platform_enable = ldp_panel_enable_lcd, | ||
215 | .platform_disable = ldp_panel_disable_lcd, | ||
185 | }; | 216 | }; |
186 | 217 | ||
187 | static struct omap_lcd_config ldp_lcd_config __initdata = { | 218 | static struct omap_dss_device ldp_lcd_device = { |
188 | .ctrl_name = "internal", | 219 | .name = "lcd", |
220 | .driver_name = "generic_dpi_panel", | ||
221 | .type = OMAP_DISPLAY_TYPE_DPI, | ||
222 | .phy.dpi.data_lines = 18, | ||
223 | .data = &ldp_panel_data, | ||
224 | }; | ||
225 | |||
226 | static struct omap_dss_device *ldp_dss_devices[] = { | ||
227 | &ldp_lcd_device, | ||
189 | }; | 228 | }; |
190 | 229 | ||
191 | static struct omap_board_config_kernel ldp_config[] __initdata = { | 230 | static struct omap_dss_board_info ldp_dss_data = { |
192 | { OMAP_TAG_LCD, &ldp_lcd_config }, | 231 | .num_devices = ARRAY_SIZE(ldp_dss_devices), |
232 | .devices = ldp_dss_devices, | ||
233 | .default_device = &ldp_lcd_device, | ||
193 | }; | 234 | }; |
194 | 235 | ||
236 | static void __init ldp_display_init(void) | ||
237 | { | ||
238 | int r; | ||
239 | |||
240 | static struct gpio gpios[] __initdata = { | ||
241 | {LCD_PANEL_RESET_GPIO, GPIOF_OUT_INIT_HIGH, "LCD RESET"}, | ||
242 | {LCD_PANEL_QVGA_GPIO, GPIOF_OUT_INIT_HIGH, "LCD QVGA"}, | ||
243 | }; | ||
244 | |||
245 | r = gpio_request_array(gpios, ARRAY_SIZE(gpios)); | ||
246 | if (r) { | ||
247 | pr_err("Cannot request LCD GPIOs, error %d\n", r); | ||
248 | return; | ||
249 | } | ||
250 | |||
251 | omap_display_init(&ldp_dss_data); | ||
252 | } | ||
253 | |||
195 | static void __init omap_ldp_init_early(void) | 254 | static void __init omap_ldp_init_early(void) |
196 | { | 255 | { |
197 | omap2_init_common_infrastructure(); | 256 | omap2_init_common_infrastructure(); |
198 | omap2_init_common_devices(NULL, NULL); | 257 | omap2_init_common_devices(NULL, NULL); |
199 | } | 258 | } |
200 | 259 | ||
260 | static int ldp_twl_gpio_setup(struct device *dev, unsigned gpio, unsigned ngpio) | ||
261 | { | ||
262 | int r; | ||
263 | |||
264 | struct gpio gpios[] = { | ||
265 | {gpio + 7 , GPIOF_OUT_INIT_LOW, "LCD ENABLE"}, | ||
266 | {gpio + 15, GPIOF_OUT_INIT_LOW, "LCD BACKLIGHT"}, | ||
267 | }; | ||
268 | |||
269 | r = gpio_request_array(gpios, ARRAY_SIZE(gpios)); | ||
270 | if (r) { | ||
271 | pr_err("Cannot request LCD GPIOs, error %d\n", r); | ||
272 | ldp_backlight_gpio = -EINVAL; | ||
273 | ldp_lcd_enable_gpio = -EINVAL; | ||
274 | return r; | ||
275 | } | ||
276 | |||
277 | ldp_backlight_gpio = gpio + 15; | ||
278 | ldp_lcd_enable_gpio = gpio + 7; | ||
279 | |||
280 | return 0; | ||
281 | } | ||
282 | |||
201 | static struct twl4030_gpio_platform_data ldp_gpio_data = { | 283 | static struct twl4030_gpio_platform_data ldp_gpio_data = { |
202 | .gpio_base = OMAP_MAX_GPIO_LINES, | 284 | .gpio_base = OMAP_MAX_GPIO_LINES, |
203 | .irq_base = TWL4030_GPIO_IRQ_BASE, | 285 | .irq_base = TWL4030_GPIO_IRQ_BASE, |
204 | .irq_end = TWL4030_GPIO_IRQ_END, | 286 | .irq_end = TWL4030_GPIO_IRQ_END, |
287 | .setup = ldp_twl_gpio_setup, | ||
205 | }; | 288 | }; |
206 | 289 | ||
207 | static struct regulator_consumer_supply ldp_vmmc1_supply[] = { | 290 | static struct regulator_consumer_supply ldp_vmmc1_supply[] = { |
@@ -243,10 +326,31 @@ static struct regulator_init_data ldp_vaux1 = { | |||
243 | .consumer_supplies = ldp_vaux1_supplies, | 326 | .consumer_supplies = ldp_vaux1_supplies, |
244 | }; | 327 | }; |
245 | 328 | ||
329 | static struct regulator_consumer_supply ldp_vpll2_supplies[] = { | ||
330 | REGULATOR_SUPPLY("vdds_dsi", "omapdss"), | ||
331 | REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi1"), | ||
332 | }; | ||
333 | |||
334 | static struct regulator_init_data ldp_vpll2 = { | ||
335 | .constraints = { | ||
336 | .name = "VDVI", | ||
337 | .min_uV = 1800000, | ||
338 | .max_uV = 1800000, | ||
339 | .apply_uV = true, | ||
340 | .valid_modes_mask = REGULATOR_MODE_NORMAL | ||
341 | | REGULATOR_MODE_STANDBY, | ||
342 | .valid_ops_mask = REGULATOR_CHANGE_MODE | ||
343 | | REGULATOR_CHANGE_STATUS, | ||
344 | }, | ||
345 | .num_consumer_supplies = ARRAY_SIZE(ldp_vpll2_supplies), | ||
346 | .consumer_supplies = ldp_vpll2_supplies, | ||
347 | }; | ||
348 | |||
246 | static struct twl4030_platform_data ldp_twldata = { | 349 | static struct twl4030_platform_data ldp_twldata = { |
247 | /* platform_data for children goes here */ | 350 | /* platform_data for children goes here */ |
248 | .vmmc1 = &ldp_vmmc1, | 351 | .vmmc1 = &ldp_vmmc1, |
249 | .vaux1 = &ldp_vaux1, | 352 | .vaux1 = &ldp_vaux1, |
353 | .vpll2 = &ldp_vpll2, | ||
250 | .gpio = &ldp_gpio_data, | 354 | .gpio = &ldp_gpio_data, |
251 | .keypad = &ldp_kp_twl4030_data, | 355 | .keypad = &ldp_kp_twl4030_data, |
252 | }; | 356 | }; |
@@ -272,7 +376,6 @@ static struct omap2_hsmmc_info mmc[] __initdata = { | |||
272 | }; | 376 | }; |
273 | 377 | ||
274 | static struct platform_device *ldp_devices[] __initdata = { | 378 | static struct platform_device *ldp_devices[] __initdata = { |
275 | &ldp_lcd_device, | ||
276 | &ldp_gpio_keys_device, | 379 | &ldp_gpio_keys_device, |
277 | }; | 380 | }; |
278 | 381 | ||
@@ -317,8 +420,6 @@ static struct mtd_partition ldp_nand_partitions[] = { | |||
317 | static void __init omap_ldp_init(void) | 420 | static void __init omap_ldp_init(void) |
318 | { | 421 | { |
319 | omap3_mux_init(board_mux, OMAP_PACKAGE_CBB); | 422 | omap3_mux_init(board_mux, OMAP_PACKAGE_CBB); |
320 | omap_board_config = ldp_config; | ||
321 | omap_board_config_size = ARRAY_SIZE(ldp_config); | ||
322 | ldp_init_smsc911x(); | 423 | ldp_init_smsc911x(); |
323 | omap_i2c_init(); | 424 | omap_i2c_init(); |
324 | platform_add_devices(ldp_devices, ARRAY_SIZE(ldp_devices)); | 425 | platform_add_devices(ldp_devices, ARRAY_SIZE(ldp_devices)); |
@@ -329,6 +430,7 @@ static void __init omap_ldp_init(void) | |||
329 | ARRAY_SIZE(ldp_nand_partitions), ZOOM_NAND_CS, 0); | 430 | ARRAY_SIZE(ldp_nand_partitions), ZOOM_NAND_CS, 0); |
330 | 431 | ||
331 | omap2_hsmmc_init(mmc); | 432 | omap2_hsmmc_init(mmc); |
433 | ldp_display_init(); | ||
332 | } | 434 | } |
333 | 435 | ||
334 | MACHINE_START(OMAP_LDP, "OMAP LDP board") | 436 | MACHINE_START(OMAP_LDP, "OMAP LDP board") |
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c index 1fde8a0474bb..928933ba28ce 100644 --- a/arch/arm/mach-omap2/board-omap3beagle.c +++ b/arch/arm/mach-omap2/board-omap3beagle.c | |||
@@ -42,7 +42,7 @@ | |||
42 | #include <plat/board.h> | 42 | #include <plat/board.h> |
43 | #include <plat/common.h> | 43 | #include <plat/common.h> |
44 | #include <video/omapdss.h> | 44 | #include <video/omapdss.h> |
45 | #include <video/omap-panel-generic-dpi.h> | 45 | #include <video/omap-panel-dvi.h> |
46 | #include <plat/gpmc.h> | 46 | #include <plat/gpmc.h> |
47 | #include <plat/nand.h> | 47 | #include <plat/nand.h> |
48 | #include <plat/usb.h> | 48 | #include <plat/usb.h> |
@@ -203,16 +203,16 @@ static void beagle_disable_dvi(struct omap_dss_device *dssdev) | |||
203 | gpio_set_value(dssdev->reset_gpio, 0); | 203 | gpio_set_value(dssdev->reset_gpio, 0); |
204 | } | 204 | } |
205 | 205 | ||
206 | static struct panel_generic_dpi_data dvi_panel = { | 206 | static struct panel_dvi_platform_data dvi_panel = { |
207 | .name = "generic", | ||
208 | .platform_enable = beagle_enable_dvi, | 207 | .platform_enable = beagle_enable_dvi, |
209 | .platform_disable = beagle_disable_dvi, | 208 | .platform_disable = beagle_disable_dvi, |
209 | .i2c_bus_num = 3, | ||
210 | }; | 210 | }; |
211 | 211 | ||
212 | static struct omap_dss_device beagle_dvi_device = { | 212 | static struct omap_dss_device beagle_dvi_device = { |
213 | .type = OMAP_DISPLAY_TYPE_DPI, | 213 | .type = OMAP_DISPLAY_TYPE_DPI, |
214 | .name = "dvi", | 214 | .name = "dvi", |
215 | .driver_name = "generic_dpi_panel", | 215 | .driver_name = "dvi", |
216 | .data = &dvi_panel, | 216 | .data = &dvi_panel, |
217 | .phy.dpi.data_lines = 24, | 217 | .phy.dpi.data_lines = 24, |
218 | .reset_gpio = -EINVAL, | 218 | .reset_gpio = -EINVAL, |
diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c index 15c69a0c1ce5..0d5a9e46a6af 100644 --- a/arch/arm/mach-omap2/board-omap3evm.c +++ b/arch/arm/mach-omap2/board-omap3evm.c | |||
@@ -45,7 +45,7 @@ | |||
45 | #include <plat/common.h> | 45 | #include <plat/common.h> |
46 | #include <plat/mcspi.h> | 46 | #include <plat/mcspi.h> |
47 | #include <video/omapdss.h> | 47 | #include <video/omapdss.h> |
48 | #include <video/omap-panel-generic-dpi.h> | 48 | #include <video/omap-panel-dvi.h> |
49 | 49 | ||
50 | #include "mux.h" | 50 | #include "mux.h" |
51 | #include "sdram-micron-mt46h32m32lf-6.h" | 51 | #include "sdram-micron-mt46h32m32lf-6.h" |
@@ -247,8 +247,7 @@ static void omap3_evm_disable_dvi(struct omap_dss_device *dssdev) | |||
247 | dvi_enabled = 0; | 247 | dvi_enabled = 0; |
248 | } | 248 | } |
249 | 249 | ||
250 | static struct panel_generic_dpi_data dvi_panel = { | 250 | static struct panel_dvi_platform_data dvi_panel = { |
251 | .name = "generic", | ||
252 | .platform_enable = omap3_evm_enable_dvi, | 251 | .platform_enable = omap3_evm_enable_dvi, |
253 | .platform_disable = omap3_evm_disable_dvi, | 252 | .platform_disable = omap3_evm_disable_dvi, |
254 | }; | 253 | }; |
@@ -256,7 +255,7 @@ static struct panel_generic_dpi_data dvi_panel = { | |||
256 | static struct omap_dss_device omap3_evm_dvi_device = { | 255 | static struct omap_dss_device omap3_evm_dvi_device = { |
257 | .name = "dvi", | 256 | .name = "dvi", |
258 | .type = OMAP_DISPLAY_TYPE_DPI, | 257 | .type = OMAP_DISPLAY_TYPE_DPI, |
259 | .driver_name = "generic_dpi_panel", | 258 | .driver_name = "dvi", |
260 | .data = &dvi_panel, | 259 | .data = &dvi_panel, |
261 | .phy.dpi.data_lines = 24, | 260 | .phy.dpi.data_lines = 24, |
262 | }; | 261 | }; |
diff --git a/arch/arm/mach-omap2/board-omap3pandora.c b/arch/arm/mach-omap2/board-omap3pandora.c index ace56938dd3b..cca523eb73b4 100644 --- a/arch/arm/mach-omap2/board-omap3pandora.c +++ b/arch/arm/mach-omap2/board-omap3pandora.c | |||
@@ -335,7 +335,7 @@ static struct regulator_consumer_supply pandora_vmmc3_supply[] = { | |||
335 | static struct regulator_consumer_supply pandora_vdds_supplies[] = { | 335 | static struct regulator_consumer_supply pandora_vdds_supplies[] = { |
336 | REGULATOR_SUPPLY("vdds_sdi", "omapdss"), | 336 | REGULATOR_SUPPLY("vdds_sdi", "omapdss"), |
337 | REGULATOR_SUPPLY("vdds_dsi", "omapdss"), | 337 | REGULATOR_SUPPLY("vdds_dsi", "omapdss"), |
338 | REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi1"), | 338 | REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi.0"), |
339 | }; | 339 | }; |
340 | 340 | ||
341 | static struct regulator_consumer_supply pandora_vcc_lcd_supply[] = { | 341 | static struct regulator_consumer_supply pandora_vcc_lcd_supply[] = { |
diff --git a/arch/arm/mach-omap2/board-omap3stalker.c b/arch/arm/mach-omap2/board-omap3stalker.c index ba13e1d5d0ab..4732589ad97e 100644 --- a/arch/arm/mach-omap2/board-omap3stalker.c +++ b/arch/arm/mach-omap2/board-omap3stalker.c | |||
@@ -41,6 +41,7 @@ | |||
41 | #include <plat/usb.h> | 41 | #include <plat/usb.h> |
42 | #include <video/omapdss.h> | 42 | #include <video/omapdss.h> |
43 | #include <video/omap-panel-generic-dpi.h> | 43 | #include <video/omap-panel-generic-dpi.h> |
44 | #include <video/omap-panel-dvi.h> | ||
44 | 45 | ||
45 | #include <plat/mcspi.h> | 46 | #include <plat/mcspi.h> |
46 | #include <linux/input/matrix_keypad.h> | 47 | #include <linux/input/matrix_keypad.h> |
@@ -107,39 +108,6 @@ static void __init omap3_stalker_display_init(void) | |||
107 | return; | 108 | return; |
108 | } | 109 | } |
109 | 110 | ||
110 | static int omap3_stalker_enable_lcd(struct omap_dss_device *dssdev) | ||
111 | { | ||
112 | if (dvi_enabled) { | ||
113 | printk(KERN_ERR "cannot enable LCD, DVI is enabled\n"); | ||
114 | return -EINVAL; | ||
115 | } | ||
116 | gpio_set_value(DSS_ENABLE_GPIO, 1); | ||
117 | gpio_set_value(LCD_PANEL_BKLIGHT_GPIO, 1); | ||
118 | lcd_enabled = 1; | ||
119 | return 0; | ||
120 | } | ||
121 | |||
122 | static void omap3_stalker_disable_lcd(struct omap_dss_device *dssdev) | ||
123 | { | ||
124 | gpio_set_value(DSS_ENABLE_GPIO, 0); | ||
125 | gpio_set_value(LCD_PANEL_BKLIGHT_GPIO, 0); | ||
126 | lcd_enabled = 0; | ||
127 | } | ||
128 | |||
129 | static struct panel_generic_dpi_data lcd_panel = { | ||
130 | .name = "generic", | ||
131 | .platform_enable = omap3_stalker_enable_lcd, | ||
132 | .platform_disable = omap3_stalker_disable_lcd, | ||
133 | }; | ||
134 | |||
135 | static struct omap_dss_device omap3_stalker_lcd_device = { | ||
136 | .name = "lcd", | ||
137 | .driver_name = "generic_dpi_panel", | ||
138 | .data = &lcd_panel, | ||
139 | .phy.dpi.data_lines = 24, | ||
140 | .type = OMAP_DISPLAY_TYPE_DPI, | ||
141 | }; | ||
142 | |||
143 | static int omap3_stalker_enable_tv(struct omap_dss_device *dssdev) | 111 | static int omap3_stalker_enable_tv(struct omap_dss_device *dssdev) |
144 | { | 112 | { |
145 | return 0; | 113 | return 0; |
@@ -179,8 +147,7 @@ static void omap3_stalker_disable_dvi(struct omap_dss_device *dssdev) | |||
179 | dvi_enabled = 0; | 147 | dvi_enabled = 0; |
180 | } | 148 | } |
181 | 149 | ||
182 | static struct panel_generic_dpi_data dvi_panel = { | 150 | static struct panel_dvi_platform_data dvi_panel = { |
183 | .name = "generic", | ||
184 | .platform_enable = omap3_stalker_enable_dvi, | 151 | .platform_enable = omap3_stalker_enable_dvi, |
185 | .platform_disable = omap3_stalker_disable_dvi, | 152 | .platform_disable = omap3_stalker_disable_dvi, |
186 | }; | 153 | }; |
@@ -188,13 +155,12 @@ static struct panel_generic_dpi_data dvi_panel = { | |||
188 | static struct omap_dss_device omap3_stalker_dvi_device = { | 155 | static struct omap_dss_device omap3_stalker_dvi_device = { |
189 | .name = "dvi", | 156 | .name = "dvi", |
190 | .type = OMAP_DISPLAY_TYPE_DPI, | 157 | .type = OMAP_DISPLAY_TYPE_DPI, |
191 | .driver_name = "generic_dpi_panel", | 158 | .driver_name = "dvi", |
192 | .data = &dvi_panel, | 159 | .data = &dvi_panel, |
193 | .phy.dpi.data_lines = 24, | 160 | .phy.dpi.data_lines = 24, |
194 | }; | 161 | }; |
195 | 162 | ||
196 | static struct omap_dss_device *omap3_stalker_dss_devices[] = { | 163 | static struct omap_dss_device *omap3_stalker_dss_devices[] = { |
197 | &omap3_stalker_lcd_device, | ||
198 | &omap3_stalker_tv_device, | 164 | &omap3_stalker_tv_device, |
199 | &omap3_stalker_dvi_device, | 165 | &omap3_stalker_dvi_device, |
200 | }; | 166 | }; |
diff --git a/arch/arm/mach-omap2/board-omap3touchbook.c b/arch/arm/mach-omap2/board-omap3touchbook.c index 49e4bd207cb6..abb68913e047 100644 --- a/arch/arm/mach-omap2/board-omap3touchbook.c +++ b/arch/arm/mach-omap2/board-omap3touchbook.c | |||
@@ -104,15 +104,6 @@ static struct omap2_hsmmc_info mmc[] = { | |||
104 | {} /* Terminator */ | 104 | {} /* Terminator */ |
105 | }; | 105 | }; |
106 | 106 | ||
107 | static struct platform_device omap3_touchbook_lcd_device = { | ||
108 | .name = "omap3touchbook_lcd", | ||
109 | .id = -1, | ||
110 | }; | ||
111 | |||
112 | static struct omap_lcd_config omap3_touchbook_lcd_config __initdata = { | ||
113 | .ctrl_name = "internal", | ||
114 | }; | ||
115 | |||
116 | static struct regulator_consumer_supply touchbook_vmmc1_supply[] = { | 107 | static struct regulator_consumer_supply touchbook_vmmc1_supply[] = { |
117 | REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0"), | 108 | REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0"), |
118 | }; | 109 | }; |
@@ -165,14 +156,12 @@ static struct twl4030_gpio_platform_data touchbook_gpio_data = { | |||
165 | static struct regulator_consumer_supply touchbook_vdac_supply[] = { | 156 | static struct regulator_consumer_supply touchbook_vdac_supply[] = { |
166 | { | 157 | { |
167 | .supply = "vdac", | 158 | .supply = "vdac", |
168 | .dev = &omap3_touchbook_lcd_device.dev, | ||
169 | }, | 159 | }, |
170 | }; | 160 | }; |
171 | 161 | ||
172 | static struct regulator_consumer_supply touchbook_vdvi_supply[] = { | 162 | static struct regulator_consumer_supply touchbook_vdvi_supply[] = { |
173 | { | 163 | { |
174 | .supply = "vdvi", | 164 | .supply = "vdvi", |
175 | .dev = &omap3_touchbook_lcd_device.dev, | ||
176 | }, | 165 | }, |
177 | }; | 166 | }; |
178 | 167 | ||
@@ -316,10 +305,6 @@ static struct platform_device keys_gpio = { | |||
316 | }, | 305 | }, |
317 | }; | 306 | }; |
318 | 307 | ||
319 | static struct omap_board_config_kernel omap3_touchbook_config[] __initdata = { | ||
320 | { OMAP_TAG_LCD, &omap3_touchbook_lcd_config }, | ||
321 | }; | ||
322 | |||
323 | #ifdef CONFIG_OMAP_MUX | 308 | #ifdef CONFIG_OMAP_MUX |
324 | static struct omap_board_mux board_mux[] __initdata = { | 309 | static struct omap_board_mux board_mux[] __initdata = { |
325 | { .reg_offset = OMAP_MUX_TERMINATOR }, | 310 | { .reg_offset = OMAP_MUX_TERMINATOR }, |
@@ -339,7 +324,6 @@ static void __init omap3_touchbook_init_irq(void) | |||
339 | } | 324 | } |
340 | 325 | ||
341 | static struct platform_device *omap3_touchbook_devices[] __initdata = { | 326 | static struct platform_device *omap3_touchbook_devices[] __initdata = { |
342 | &omap3_touchbook_lcd_device, | ||
343 | &leds_gpio, | 327 | &leds_gpio, |
344 | &keys_gpio, | 328 | &keys_gpio, |
345 | }; | 329 | }; |
@@ -376,8 +360,6 @@ early_param("tbr", early_touchbook_revision); | |||
376 | static void __init omap3_touchbook_init(void) | 360 | static void __init omap3_touchbook_init(void) |
377 | { | 361 | { |
378 | omap3_mux_init(board_mux, OMAP_PACKAGE_CBB); | 362 | omap3_mux_init(board_mux, OMAP_PACKAGE_CBB); |
379 | omap_board_config = omap3_touchbook_config; | ||
380 | omap_board_config_size = ARRAY_SIZE(omap3_touchbook_config); | ||
381 | 363 | ||
382 | pm_power_off = omap3_touchbook_poweroff; | 364 | pm_power_off = omap3_touchbook_poweroff; |
383 | 365 | ||
diff --git a/arch/arm/mach-omap2/board-omap4panda.c b/arch/arm/mach-omap2/board-omap4panda.c index 683bede73d54..ed38d8fd090f 100644 --- a/arch/arm/mach-omap2/board-omap4panda.c +++ b/arch/arm/mach-omap2/board-omap4panda.c | |||
@@ -40,7 +40,7 @@ | |||
40 | #include <plat/common.h> | 40 | #include <plat/common.h> |
41 | #include <plat/usb.h> | 41 | #include <plat/usb.h> |
42 | #include <plat/mmc.h> | 42 | #include <plat/mmc.h> |
43 | #include <video/omap-panel-generic-dpi.h> | 43 | #include <video/omap-panel-dvi.h> |
44 | 44 | ||
45 | #include "hsmmc.h" | 45 | #include "hsmmc.h" |
46 | #include "control.h" | 46 | #include "control.h" |
@@ -455,16 +455,16 @@ static void omap4_panda_disable_dvi(struct omap_dss_device *dssdev) | |||
455 | } | 455 | } |
456 | 456 | ||
457 | /* Using generic display panel */ | 457 | /* Using generic display panel */ |
458 | static struct panel_generic_dpi_data omap4_dvi_panel = { | 458 | static struct panel_dvi_platform_data omap4_dvi_panel = { |
459 | .name = "generic", | ||
460 | .platform_enable = omap4_panda_enable_dvi, | 459 | .platform_enable = omap4_panda_enable_dvi, |
461 | .platform_disable = omap4_panda_disable_dvi, | 460 | .platform_disable = omap4_panda_disable_dvi, |
461 | .i2c_bus_num = 3, | ||
462 | }; | 462 | }; |
463 | 463 | ||
464 | struct omap_dss_device omap4_panda_dvi_device = { | 464 | struct omap_dss_device omap4_panda_dvi_device = { |
465 | .type = OMAP_DISPLAY_TYPE_DPI, | 465 | .type = OMAP_DISPLAY_TYPE_DPI, |
466 | .name = "dvi", | 466 | .name = "dvi", |
467 | .driver_name = "generic_dpi_panel", | 467 | .driver_name = "dvi", |
468 | .data = &omap4_dvi_panel, | 468 | .data = &omap4_dvi_panel, |
469 | .phy.dpi.data_lines = 24, | 469 | .phy.dpi.data_lines = 24, |
470 | .reset_gpio = PANDA_DVI_TFP410_POWER_DOWN_GPIO, | 470 | .reset_gpio = PANDA_DVI_TFP410_POWER_DOWN_GPIO, |
diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c index e592fb134c4e..ec0f60c1cb7c 100644 --- a/arch/arm/mach-omap2/board-overo.c +++ b/arch/arm/mach-omap2/board-overo.c | |||
@@ -46,6 +46,7 @@ | |||
46 | #include <plat/common.h> | 46 | #include <plat/common.h> |
47 | #include <video/omapdss.h> | 47 | #include <video/omapdss.h> |
48 | #include <video/omap-panel-generic-dpi.h> | 48 | #include <video/omap-panel-generic-dpi.h> |
49 | #include <video/omap-panel-dvi.h> | ||
49 | #include <plat/gpmc.h> | 50 | #include <plat/gpmc.h> |
50 | #include <mach/hardware.h> | 51 | #include <mach/hardware.h> |
51 | #include <plat/nand.h> | 52 | #include <plat/nand.h> |
@@ -182,16 +183,16 @@ static void overo_panel_disable_dvi(struct omap_dss_device *dssdev) | |||
182 | dvi_enabled = 0; | 183 | dvi_enabled = 0; |
183 | } | 184 | } |
184 | 185 | ||
185 | static struct panel_generic_dpi_data dvi_panel = { | 186 | static struct panel_dvi_platform_data dvi_panel = { |
186 | .name = "generic", | ||
187 | .platform_enable = overo_panel_enable_dvi, | 187 | .platform_enable = overo_panel_enable_dvi, |
188 | .platform_disable = overo_panel_disable_dvi, | 188 | .platform_disable = overo_panel_disable_dvi, |
189 | .i2c_bus_num = 3, | ||
189 | }; | 190 | }; |
190 | 191 | ||
191 | static struct omap_dss_device overo_dvi_device = { | 192 | static struct omap_dss_device overo_dvi_device = { |
192 | .name = "dvi", | 193 | .name = "dvi", |
193 | .type = OMAP_DISPLAY_TYPE_DPI, | 194 | .type = OMAP_DISPLAY_TYPE_DPI, |
194 | .driver_name = "generic_dpi_panel", | 195 | .driver_name = "dvi", |
195 | .data = &dvi_panel, | 196 | .data = &dvi_panel, |
196 | .phy.dpi.data_lines = 24, | 197 | .phy.dpi.data_lines = 24, |
197 | }; | 198 | }; |
diff --git a/arch/arm/mach-omap2/board-rx51.c b/arch/arm/mach-omap2/board-rx51.c index a6c473bbb3d6..faa2a8e28de5 100644 --- a/arch/arm/mach-omap2/board-rx51.c +++ b/arch/arm/mach-omap2/board-rx51.c | |||
@@ -79,29 +79,6 @@ static struct cpuidle_params rx51_cpuidle_params[] = { | |||
79 | {7505 + 15274, 484329, 1}, | 79 | {7505 + 15274, 484329, 1}, |
80 | }; | 80 | }; |
81 | 81 | ||
82 | static struct omap_lcd_config rx51_lcd_config = { | ||
83 | .ctrl_name = "internal", | ||
84 | }; | ||
85 | |||
86 | static struct omap_fbmem_config rx51_fbmem0_config = { | ||
87 | .size = 752 * 1024, | ||
88 | }; | ||
89 | |||
90 | static struct omap_fbmem_config rx51_fbmem1_config = { | ||
91 | .size = 752 * 1024, | ||
92 | }; | ||
93 | |||
94 | static struct omap_fbmem_config rx51_fbmem2_config = { | ||
95 | .size = 752 * 1024, | ||
96 | }; | ||
97 | |||
98 | static struct omap_board_config_kernel rx51_config[] = { | ||
99 | { OMAP_TAG_FBMEM, &rx51_fbmem0_config }, | ||
100 | { OMAP_TAG_FBMEM, &rx51_fbmem1_config }, | ||
101 | { OMAP_TAG_FBMEM, &rx51_fbmem2_config }, | ||
102 | { OMAP_TAG_LCD, &rx51_lcd_config }, | ||
103 | }; | ||
104 | |||
105 | static void __init rx51_init_early(void) | 82 | static void __init rx51_init_early(void) |
106 | { | 83 | { |
107 | struct omap_sdrc_params *sdrc_params; | 84 | struct omap_sdrc_params *sdrc_params; |
@@ -128,8 +105,6 @@ static struct omap_musb_board_data musb_board_data = { | |||
128 | static void __init rx51_init(void) | 105 | static void __init rx51_init(void) |
129 | { | 106 | { |
130 | omap3_mux_init(board_mux, OMAP_PACKAGE_CBB); | 107 | omap3_mux_init(board_mux, OMAP_PACKAGE_CBB); |
131 | omap_board_config = rx51_config; | ||
132 | omap_board_config_size = ARRAY_SIZE(rx51_config); | ||
133 | omap3_pm_init_cpuidle(rx51_cpuidle_params); | 108 | omap3_pm_init_cpuidle(rx51_cpuidle_params); |
134 | omap_serial_init(); | 109 | omap_serial_init(); |
135 | usb_musb_init(&musb_board_data); | 110 | usb_musb_init(&musb_board_data); |
diff --git a/arch/arm/mach-omap2/display.c b/arch/arm/mach-omap2/display.c index a5b7a236aa5b..62510ec863c6 100644 --- a/arch/arm/mach-omap2/display.c +++ b/arch/arm/mach-omap2/display.c | |||
@@ -27,6 +27,8 @@ | |||
27 | #include <plat/omap_device.h> | 27 | #include <plat/omap_device.h> |
28 | #include <plat/omap-pm.h> | 28 | #include <plat/omap-pm.h> |
29 | 29 | ||
30 | #include "control.h" | ||
31 | |||
30 | static struct platform_device omap_display_device = { | 32 | static struct platform_device omap_display_device = { |
31 | .name = "omapdss", | 33 | .name = "omapdss", |
32 | .id = -1, | 34 | .id = -1, |
@@ -61,7 +63,7 @@ static const struct omap_dss_hwmod_data omap3_dss_hwmod_data[] __initdata = { | |||
61 | { "dss_dispc", "omapdss_dispc", -1 }, | 63 | { "dss_dispc", "omapdss_dispc", -1 }, |
62 | { "dss_rfbi", "omapdss_rfbi", -1 }, | 64 | { "dss_rfbi", "omapdss_rfbi", -1 }, |
63 | { "dss_venc", "omapdss_venc", -1 }, | 65 | { "dss_venc", "omapdss_venc", -1 }, |
64 | { "dss_dsi1", "omapdss_dsi1", -1 }, | 66 | { "dss_dsi1", "omapdss_dsi", 0 }, |
65 | }; | 67 | }; |
66 | 68 | ||
67 | static const struct omap_dss_hwmod_data omap4_dss_hwmod_data[] __initdata = { | 69 | static const struct omap_dss_hwmod_data omap4_dss_hwmod_data[] __initdata = { |
@@ -69,11 +71,58 @@ static const struct omap_dss_hwmod_data omap4_dss_hwmod_data[] __initdata = { | |||
69 | { "dss_dispc", "omapdss_dispc", -1 }, | 71 | { "dss_dispc", "omapdss_dispc", -1 }, |
70 | { "dss_rfbi", "omapdss_rfbi", -1 }, | 72 | { "dss_rfbi", "omapdss_rfbi", -1 }, |
71 | { "dss_venc", "omapdss_venc", -1 }, | 73 | { "dss_venc", "omapdss_venc", -1 }, |
72 | { "dss_dsi1", "omapdss_dsi1", -1 }, | 74 | { "dss_dsi1", "omapdss_dsi", 0 }, |
73 | { "dss_dsi2", "omapdss_dsi2", -1 }, | 75 | { "dss_dsi2", "omapdss_dsi", 1 }, |
74 | { "dss_hdmi", "omapdss_hdmi", -1 }, | 76 | { "dss_hdmi", "omapdss_hdmi", -1 }, |
75 | }; | 77 | }; |
76 | 78 | ||
79 | static int omap4_dsi_mux_pads(int dsi_id, unsigned lanes) | ||
80 | { | ||
81 | u32 enable_mask, enable_shift; | ||
82 | u32 pipd_mask, pipd_shift; | ||
83 | u32 reg; | ||
84 | |||
85 | if (dsi_id == 0) { | ||
86 | enable_mask = OMAP4_DSI1_LANEENABLE_MASK; | ||
87 | enable_shift = OMAP4_DSI1_LANEENABLE_SHIFT; | ||
88 | pipd_mask = OMAP4_DSI1_PIPD_MASK; | ||
89 | pipd_shift = OMAP4_DSI1_PIPD_SHIFT; | ||
90 | } else if (dsi_id == 1) { | ||
91 | enable_mask = OMAP4_DSI2_LANEENABLE_MASK; | ||
92 | enable_shift = OMAP4_DSI2_LANEENABLE_SHIFT; | ||
93 | pipd_mask = OMAP4_DSI2_PIPD_MASK; | ||
94 | pipd_shift = OMAP4_DSI2_PIPD_SHIFT; | ||
95 | } else { | ||
96 | return -ENODEV; | ||
97 | } | ||
98 | |||
99 | reg = omap4_ctrl_pad_readl(OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_DSIPHY); | ||
100 | |||
101 | reg &= ~enable_mask; | ||
102 | reg &= ~pipd_mask; | ||
103 | |||
104 | reg |= (lanes << enable_shift) & enable_mask; | ||
105 | reg |= (lanes << pipd_shift) & pipd_mask; | ||
106 | |||
107 | omap4_ctrl_pad_writel(reg, OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_DSIPHY); | ||
108 | |||
109 | return 0; | ||
110 | } | ||
111 | |||
112 | static int omap_dsi_enable_pads(int dsi_id, unsigned lane_mask) | ||
113 | { | ||
114 | if (cpu_is_omap44xx()) | ||
115 | return omap4_dsi_mux_pads(dsi_id, lane_mask); | ||
116 | |||
117 | return 0; | ||
118 | } | ||
119 | |||
120 | static void omap_dsi_disable_pads(int dsi_id, unsigned lane_mask) | ||
121 | { | ||
122 | if (cpu_is_omap44xx()) | ||
123 | omap4_dsi_mux_pads(dsi_id, 0); | ||
124 | } | ||
125 | |||
77 | int __init omap_display_init(struct omap_dss_board_info *board_data) | 126 | int __init omap_display_init(struct omap_dss_board_info *board_data) |
78 | { | 127 | { |
79 | int r = 0; | 128 | int r = 0; |
@@ -96,6 +145,11 @@ int __init omap_display_init(struct omap_dss_board_info *board_data) | |||
96 | oh_count = ARRAY_SIZE(omap4_dss_hwmod_data); | 145 | oh_count = ARRAY_SIZE(omap4_dss_hwmod_data); |
97 | } | 146 | } |
98 | 147 | ||
148 | if (board_data->dsi_enable_pads == NULL) | ||
149 | board_data->dsi_enable_pads = omap_dsi_enable_pads; | ||
150 | if (board_data->dsi_disable_pads == NULL) | ||
151 | board_data->dsi_disable_pads = omap_dsi_disable_pads; | ||
152 | |||
99 | pdata.board_data = board_data; | 153 | pdata.board_data = board_data; |
100 | pdata.board_data->get_context_loss_count = | 154 | pdata.board_data->get_context_loss_count = |
101 | omap_pm_get_dev_context_loss_count; | 155 | omap_pm_get_dev_context_loss_count; |
diff --git a/arch/arm/mach-omap2/twl-common.c b/arch/arm/mach-omap2/twl-common.c index daa056ed8738..522435772168 100644 --- a/arch/arm/mach-omap2/twl-common.c +++ b/arch/arm/mach-omap2/twl-common.c | |||
@@ -99,7 +99,7 @@ static struct regulator_init_data omap3_vdac_idata = { | |||
99 | 99 | ||
100 | static struct regulator_consumer_supply omap3_vpll2_supplies[] = { | 100 | static struct regulator_consumer_supply omap3_vpll2_supplies[] = { |
101 | REGULATOR_SUPPLY("vdds_dsi", "omapdss"), | 101 | REGULATOR_SUPPLY("vdds_dsi", "omapdss"), |
102 | REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi1"), | 102 | REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi.0"), |
103 | }; | 103 | }; |
104 | 104 | ||
105 | static struct regulator_init_data omap3_vpll2_idata = { | 105 | static struct regulator_init_data omap3_vpll2_idata = { |
@@ -235,6 +235,12 @@ static struct regulator_init_data omap4_vana_idata = { | |||
235 | }, | 235 | }, |
236 | }; | 236 | }; |
237 | 237 | ||
238 | static struct regulator_consumer_supply omap4_vcxio_supply[] = { | ||
239 | REGULATOR_SUPPLY("vdds_dsi", "omapdss_dss"), | ||
240 | REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi.0"), | ||
241 | REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi.1"), | ||
242 | }; | ||
243 | |||
238 | static struct regulator_init_data omap4_vcxio_idata = { | 244 | static struct regulator_init_data omap4_vcxio_idata = { |
239 | .constraints = { | 245 | .constraints = { |
240 | .min_uV = 1800000, | 246 | .min_uV = 1800000, |
@@ -243,7 +249,10 @@ static struct regulator_init_data omap4_vcxio_idata = { | |||
243 | | REGULATOR_MODE_STANDBY, | 249 | | REGULATOR_MODE_STANDBY, |
244 | .valid_ops_mask = REGULATOR_CHANGE_MODE | 250 | .valid_ops_mask = REGULATOR_CHANGE_MODE |
245 | | REGULATOR_CHANGE_STATUS, | 251 | | REGULATOR_CHANGE_STATUS, |
252 | .always_on = true, | ||
246 | }, | 253 | }, |
254 | .num_consumer_supplies = ARRAY_SIZE(omap4_vcxio_supply), | ||
255 | .consumer_supplies = omap4_vcxio_supply, | ||
247 | }; | 256 | }; |
248 | 257 | ||
249 | static struct regulator_init_data omap4_vusb_idata = { | 258 | static struct regulator_init_data omap4_vusb_idata = { |
diff --git a/arch/arm/mach-shmobile/board-mackerel.c b/arch/arm/mach-shmobile/board-mackerel.c index 4de92dc570b0..3689ad2e9156 100644 --- a/arch/arm/mach-shmobile/board-mackerel.c +++ b/arch/arm/mach-shmobile/board-mackerel.c | |||
@@ -1597,6 +1597,7 @@ static void __init mackerel_init(void) | |||
1597 | 1597 | ||
1598 | sh7372_add_device_to_domain(&sh7372_a4lc, &lcdc_device); | 1598 | sh7372_add_device_to_domain(&sh7372_a4lc, &lcdc_device); |
1599 | sh7372_add_device_to_domain(&sh7372_a4lc, &hdmi_lcdc_device); | 1599 | sh7372_add_device_to_domain(&sh7372_a4lc, &hdmi_lcdc_device); |
1600 | sh7372_add_device_to_domain(&sh7372_a4lc, &meram_device); | ||
1600 | sh7372_add_device_to_domain(&sh7372_a4mp, &fsi_device); | 1601 | sh7372_add_device_to_domain(&sh7372_a4mp, &fsi_device); |
1601 | sh7372_add_device_to_domain(&sh7372_a3sp, &usbhs0_device); | 1602 | sh7372_add_device_to_domain(&sh7372_a3sp, &usbhs0_device); |
1602 | sh7372_add_device_to_domain(&sh7372_a3sp, &usbhs1_device); | 1603 | sh7372_add_device_to_domain(&sh7372_a3sp, &usbhs1_device); |
diff --git a/arch/powerpc/platforms/512x/mpc512x_shared.c b/arch/powerpc/platforms/512x/mpc512x_shared.c index e41ebbdb3e12..cfe958e94e1e 100644 --- a/arch/powerpc/platforms/512x/mpc512x_shared.c +++ b/arch/powerpc/platforms/512x/mpc512x_shared.c | |||
@@ -66,8 +66,8 @@ struct fsl_diu_shared_fb { | |||
66 | bool in_use; | 66 | bool in_use; |
67 | }; | 67 | }; |
68 | 68 | ||
69 | unsigned int mpc512x_get_pixel_format(unsigned int bits_per_pixel, | 69 | u32 mpc512x_get_pixel_format(enum fsl_diu_monitor_port port, |
70 | int monitor_port) | 70 | unsigned int bits_per_pixel) |
71 | { | 71 | { |
72 | switch (bits_per_pixel) { | 72 | switch (bits_per_pixel) { |
73 | case 32: | 73 | case 32: |
@@ -80,11 +80,12 @@ unsigned int mpc512x_get_pixel_format(unsigned int bits_per_pixel, | |||
80 | return 0x00000400; | 80 | return 0x00000400; |
81 | } | 81 | } |
82 | 82 | ||
83 | void mpc512x_set_gamma_table(int monitor_port, char *gamma_table_base) | 83 | void mpc512x_set_gamma_table(enum fsl_diu_monitor_port port, |
84 | char *gamma_table_base) | ||
84 | { | 85 | { |
85 | } | 86 | } |
86 | 87 | ||
87 | void mpc512x_set_monitor_port(int monitor_port) | 88 | void mpc512x_set_monitor_port(enum fsl_diu_monitor_port port) |
88 | { | 89 | { |
89 | } | 90 | } |
90 | 91 | ||
@@ -182,14 +183,10 @@ void mpc512x_set_pixel_clock(unsigned int pixclock) | |||
182 | iounmap(ccm); | 183 | iounmap(ccm); |
183 | } | 184 | } |
184 | 185 | ||
185 | ssize_t mpc512x_show_monitor_port(int monitor_port, char *buf) | 186 | enum fsl_diu_monitor_port |
187 | mpc512x_valid_monitor_port(enum fsl_diu_monitor_port port) | ||
186 | { | 188 | { |
187 | return sprintf(buf, "0 - 5121 LCD\n"); | 189 | return FSL_DIU_PORT_DVI; |
188 | } | ||
189 | |||
190 | int mpc512x_set_sysfs_monitor_port(int val) | ||
191 | { | ||
192 | return 0; | ||
193 | } | 190 | } |
194 | 191 | ||
195 | static struct fsl_diu_shared_fb __attribute__ ((__aligned__(8))) diu_shared_fb; | 192 | static struct fsl_diu_shared_fb __attribute__ ((__aligned__(8))) diu_shared_fb; |
@@ -256,7 +253,7 @@ void __init mpc512x_init_diu(void) | |||
256 | } | 253 | } |
257 | 254 | ||
258 | mode = in_be32(&diu_reg->diu_mode); | 255 | mode = in_be32(&diu_reg->diu_mode); |
259 | if (mode != MFB_MODE1) { | 256 | if (mode == MFB_MODE0) { |
260 | pr_info("%s: DIU OFF\n", __func__); | 257 | pr_info("%s: DIU OFF\n", __func__); |
261 | goto out; | 258 | goto out; |
262 | } | 259 | } |
@@ -332,8 +329,7 @@ void __init mpc512x_setup_diu(void) | |||
332 | diu_ops.set_gamma_table = mpc512x_set_gamma_table; | 329 | diu_ops.set_gamma_table = mpc512x_set_gamma_table; |
333 | diu_ops.set_monitor_port = mpc512x_set_monitor_port; | 330 | diu_ops.set_monitor_port = mpc512x_set_monitor_port; |
334 | diu_ops.set_pixel_clock = mpc512x_set_pixel_clock; | 331 | diu_ops.set_pixel_clock = mpc512x_set_pixel_clock; |
335 | diu_ops.show_monitor_port = mpc512x_show_monitor_port; | 332 | diu_ops.valid_monitor_port = mpc512x_valid_monitor_port; |
336 | diu_ops.set_sysfs_monitor_port = mpc512x_set_sysfs_monitor_port; | ||
337 | diu_ops.release_bootmem = mpc512x_release_bootmem; | 333 | diu_ops.release_bootmem = mpc512x_release_bootmem; |
338 | #endif | 334 | #endif |
339 | } | 335 | } |
diff --git a/arch/powerpc/platforms/85xx/p1022_ds.c b/arch/powerpc/platforms/85xx/p1022_ds.c index 266b3aadfe5e..c01c7277888c 100644 --- a/arch/powerpc/platforms/85xx/p1022_ds.c +++ b/arch/powerpc/platforms/85xx/p1022_ds.c | |||
@@ -93,8 +93,8 @@ | |||
93 | * The Area Descriptor is a 32-bit value that determine which bits in each | 93 | * The Area Descriptor is a 32-bit value that determine which bits in each |
94 | * pixel are to be used for each color. | 94 | * pixel are to be used for each color. |
95 | */ | 95 | */ |
96 | static unsigned int p1022ds_get_pixel_format(unsigned int bits_per_pixel, | 96 | static u32 p1022ds_get_pixel_format(enum fsl_diu_monitor_port port, |
97 | int monitor_port) | 97 | unsigned int bits_per_pixel) |
98 | { | 98 | { |
99 | switch (bits_per_pixel) { | 99 | switch (bits_per_pixel) { |
100 | case 32: | 100 | case 32: |
@@ -118,7 +118,8 @@ static unsigned int p1022ds_get_pixel_format(unsigned int bits_per_pixel, | |||
118 | * On some boards, the gamma table for some ports may need to be modified. | 118 | * On some boards, the gamma table for some ports may need to be modified. |
119 | * This is not the case on the P1022DS, so we do nothing. | 119 | * This is not the case on the P1022DS, so we do nothing. |
120 | */ | 120 | */ |
121 | static void p1022ds_set_gamma_table(int monitor_port, char *gamma_table_base) | 121 | static void p1022ds_set_gamma_table(enum fsl_diu_monitor_port port, |
122 | char *gamma_table_base) | ||
122 | { | 123 | { |
123 | } | 124 | } |
124 | 125 | ||
@@ -126,7 +127,7 @@ static void p1022ds_set_gamma_table(int monitor_port, char *gamma_table_base) | |||
126 | * p1022ds_set_monitor_port: switch the output to a different monitor port | 127 | * p1022ds_set_monitor_port: switch the output to a different monitor port |
127 | * | 128 | * |
128 | */ | 129 | */ |
129 | static void p1022ds_set_monitor_port(int monitor_port) | 130 | static void p1022ds_set_monitor_port(enum fsl_diu_monitor_port port) |
130 | { | 131 | { |
131 | struct device_node *pixis_node; | 132 | struct device_node *pixis_node; |
132 | void __iomem *pixis; | 133 | void __iomem *pixis; |
@@ -145,19 +146,21 @@ static void p1022ds_set_monitor_port(int monitor_port) | |||
145 | } | 146 | } |
146 | brdcfg1 = pixis + 9; /* BRDCFG1 is at offset 9 in the ngPIXIS */ | 147 | brdcfg1 = pixis + 9; /* BRDCFG1 is at offset 9 in the ngPIXIS */ |
147 | 148 | ||
148 | switch (monitor_port) { | 149 | switch (port) { |
149 | case 0: /* DVI */ | 150 | case FSL_DIU_PORT_DVI: |
151 | printk(KERN_INFO "%s:%u\n", __func__, __LINE__); | ||
150 | /* Enable the DVI port, disable the DFP and the backlight */ | 152 | /* Enable the DVI port, disable the DFP and the backlight */ |
151 | clrsetbits_8(brdcfg1, PX_BRDCFG1_DFPEN | PX_BRDCFG1_BACKLIGHT, | 153 | clrsetbits_8(brdcfg1, PX_BRDCFG1_DFPEN | PX_BRDCFG1_BACKLIGHT, |
152 | PX_BRDCFG1_DVIEN); | 154 | PX_BRDCFG1_DVIEN); |
153 | break; | 155 | break; |
154 | case 1: /* Single link LVDS */ | 156 | case FSL_DIU_PORT_LVDS: |
157 | printk(KERN_INFO "%s:%u\n", __func__, __LINE__); | ||
155 | /* Enable the DFP port, disable the DVI and the backlight */ | 158 | /* Enable the DFP port, disable the DVI and the backlight */ |
156 | clrsetbits_8(brdcfg1, PX_BRDCFG1_DVIEN | PX_BRDCFG1_BACKLIGHT, | 159 | clrsetbits_8(brdcfg1, PX_BRDCFG1_DVIEN | PX_BRDCFG1_BACKLIGHT, |
157 | PX_BRDCFG1_DFPEN); | 160 | PX_BRDCFG1_DFPEN); |
158 | break; | 161 | break; |
159 | default: | 162 | default: |
160 | pr_err("p1022ds: unsupported monitor port %i\n", monitor_port); | 163 | pr_err("p1022ds: unsupported monitor port %i\n", port); |
161 | } | 164 | } |
162 | 165 | ||
163 | iounmap(pixis); | 166 | iounmap(pixis); |
@@ -214,23 +217,18 @@ void p1022ds_set_pixel_clock(unsigned int pixclock) | |||
214 | } | 217 | } |
215 | 218 | ||
216 | /** | 219 | /** |
217 | * p1022ds_show_monitor_port: show the current monitor | 220 | * p1022ds_valid_monitor_port: set the monitor port for sysfs |
218 | * | ||
219 | * This function returns a string indicating whether the current monitor is | ||
220 | * set to DVI or LVDS. | ||
221 | */ | ||
222 | ssize_t p1022ds_show_monitor_port(int monitor_port, char *buf) | ||
223 | { | ||
224 | return sprintf(buf, "%c0 - DVI\n%c1 - Single link LVDS\n", | ||
225 | monitor_port == 0 ? '*' : ' ', monitor_port == 1 ? '*' : ' '); | ||
226 | } | ||
227 | |||
228 | /** | ||
229 | * p1022ds_set_sysfs_monitor_port: set the monitor port for sysfs | ||
230 | */ | 221 | */ |
231 | int p1022ds_set_sysfs_monitor_port(int val) | 222 | enum fsl_diu_monitor_port |
223 | p1022ds_valid_monitor_port(enum fsl_diu_monitor_port port) | ||
232 | { | 224 | { |
233 | return val < 2 ? val : 0; | 225 | switch (port) { |
226 | case FSL_DIU_PORT_DVI: | ||
227 | case FSL_DIU_PORT_LVDS: | ||
228 | return port; | ||
229 | default: | ||
230 | return FSL_DIU_PORT_DVI; /* Dual-link LVDS is not supported */ | ||
231 | } | ||
234 | } | 232 | } |
235 | 233 | ||
236 | #endif | 234 | #endif |
@@ -305,8 +303,7 @@ static void __init p1022_ds_setup_arch(void) | |||
305 | diu_ops.set_gamma_table = p1022ds_set_gamma_table; | 303 | diu_ops.set_gamma_table = p1022ds_set_gamma_table; |
306 | diu_ops.set_monitor_port = p1022ds_set_monitor_port; | 304 | diu_ops.set_monitor_port = p1022ds_set_monitor_port; |
307 | diu_ops.set_pixel_clock = p1022ds_set_pixel_clock; | 305 | diu_ops.set_pixel_clock = p1022ds_set_pixel_clock; |
308 | diu_ops.show_monitor_port = p1022ds_show_monitor_port; | 306 | diu_ops.valid_monitor_port = p1022ds_valid_monitor_port; |
309 | diu_ops.set_sysfs_monitor_port = p1022ds_set_sysfs_monitor_port; | ||
310 | #endif | 307 | #endif |
311 | 308 | ||
312 | #ifdef CONFIG_SMP | 309 | #ifdef CONFIG_SMP |
diff --git a/arch/powerpc/platforms/86xx/mpc8610_hpcd.c b/arch/powerpc/platforms/86xx/mpc8610_hpcd.c index 74e018ef724b..13fa9a6403e6 100644 --- a/arch/powerpc/platforms/86xx/mpc8610_hpcd.c +++ b/arch/powerpc/platforms/86xx/mpc8610_hpcd.c | |||
@@ -152,10 +152,10 @@ machine_device_initcall(mpc86xx_hpcd, mpc8610_declare_of_platform_devices); | |||
152 | (c2 << AD_COMP_2_SHIFT) | (c1 << AD_COMP_1_SHIFT) | \ | 152 | (c2 << AD_COMP_2_SHIFT) | (c1 << AD_COMP_1_SHIFT) | \ |
153 | (c0 << AD_COMP_0_SHIFT) | (size << AD_PIXEL_S_SHIFT)) | 153 | (c0 << AD_COMP_0_SHIFT) | (size << AD_PIXEL_S_SHIFT)) |
154 | 154 | ||
155 | unsigned int mpc8610hpcd_get_pixel_format(unsigned int bits_per_pixel, | 155 | u32 mpc8610hpcd_get_pixel_format(enum fsl_diu_monitor_port port, |
156 | int monitor_port) | 156 | unsigned int bits_per_pixel) |
157 | { | 157 | { |
158 | static const unsigned long pixelformat[][3] = { | 158 | static const u32 pixelformat[][3] = { |
159 | { | 159 | { |
160 | MAKE_AD(3, 0, 2, 1, 3, 8, 8, 8, 8), | 160 | MAKE_AD(3, 0, 2, 1, 3, 8, 8, 8, 8), |
161 | MAKE_AD(4, 2, 0, 1, 2, 8, 8, 8, 0), | 161 | MAKE_AD(4, 2, 0, 1, 2, 8, 8, 8, 0), |
@@ -170,7 +170,8 @@ unsigned int mpc8610hpcd_get_pixel_format(unsigned int bits_per_pixel, | |||
170 | unsigned int arch_monitor; | 170 | unsigned int arch_monitor; |
171 | 171 | ||
172 | /* The DVI port is mis-wired on revision 1 of this board. */ | 172 | /* The DVI port is mis-wired on revision 1 of this board. */ |
173 | arch_monitor = ((*pixis_arch == 0x01) && (monitor_port == 0))? 0 : 1; | 173 | arch_monitor = |
174 | ((*pixis_arch == 0x01) && (port == FSL_DIU_PORT_DVI)) ? 0 : 1; | ||
174 | 175 | ||
175 | switch (bits_per_pixel) { | 176 | switch (bits_per_pixel) { |
176 | case 32: | 177 | case 32: |
@@ -185,10 +186,11 @@ unsigned int mpc8610hpcd_get_pixel_format(unsigned int bits_per_pixel, | |||
185 | } | 186 | } |
186 | } | 187 | } |
187 | 188 | ||
188 | void mpc8610hpcd_set_gamma_table(int monitor_port, char *gamma_table_base) | 189 | void mpc8610hpcd_set_gamma_table(enum fsl_diu_monitor_port port, |
190 | char *gamma_table_base) | ||
189 | { | 191 | { |
190 | int i; | 192 | int i; |
191 | if (monitor_port == 2) { /* dual link LVDS */ | 193 | if (port == FSL_DIU_PORT_DLVDS) { |
192 | for (i = 0; i < 256*3; i++) | 194 | for (i = 0; i < 256*3; i++) |
193 | gamma_table_base[i] = (gamma_table_base[i] << 2) | | 195 | gamma_table_base[i] = (gamma_table_base[i] << 2) | |
194 | ((gamma_table_base[i] >> 6) & 0x03); | 196 | ((gamma_table_base[i] >> 6) & 0x03); |
@@ -199,17 +201,21 @@ void mpc8610hpcd_set_gamma_table(int monitor_port, char *gamma_table_base) | |||
199 | #define PX_BRDCFG0_DLINK (1 << 4) | 201 | #define PX_BRDCFG0_DLINK (1 << 4) |
200 | #define PX_BRDCFG0_DIU_MASK (PX_BRDCFG0_DVISEL | PX_BRDCFG0_DLINK) | 202 | #define PX_BRDCFG0_DIU_MASK (PX_BRDCFG0_DVISEL | PX_BRDCFG0_DLINK) |
201 | 203 | ||
202 | void mpc8610hpcd_set_monitor_port(int monitor_port) | 204 | void mpc8610hpcd_set_monitor_port(enum fsl_diu_monitor_port port) |
203 | { | 205 | { |
204 | static const u8 bdcfg[] = { | 206 | switch (port) { |
205 | PX_BRDCFG0_DVISEL | PX_BRDCFG0_DLINK, | 207 | case FSL_DIU_PORT_DVI: |
206 | PX_BRDCFG0_DLINK, | ||
207 | 0, | ||
208 | }; | ||
209 | |||
210 | if (monitor_port < 3) | ||
211 | clrsetbits_8(pixis_bdcfg0, PX_BRDCFG0_DIU_MASK, | 208 | clrsetbits_8(pixis_bdcfg0, PX_BRDCFG0_DIU_MASK, |
212 | bdcfg[monitor_port]); | 209 | PX_BRDCFG0_DVISEL | PX_BRDCFG0_DLINK); |
210 | break; | ||
211 | case FSL_DIU_PORT_LVDS: | ||
212 | clrsetbits_8(pixis_bdcfg0, PX_BRDCFG0_DIU_MASK, | ||
213 | PX_BRDCFG0_DLINK); | ||
214 | break; | ||
215 | case FSL_DIU_PORT_DLVDS: | ||
216 | clrbits8(pixis_bdcfg0, PX_BRDCFG0_DIU_MASK); | ||
217 | break; | ||
218 | } | ||
213 | } | 219 | } |
214 | 220 | ||
215 | /** | 221 | /** |
@@ -262,20 +268,10 @@ void mpc8610hpcd_set_pixel_clock(unsigned int pixclock) | |||
262 | iounmap(guts); | 268 | iounmap(guts); |
263 | } | 269 | } |
264 | 270 | ||
265 | ssize_t mpc8610hpcd_show_monitor_port(int monitor_port, char *buf) | 271 | enum fsl_diu_monitor_port |
266 | { | 272 | mpc8610hpcd_valid_monitor_port(enum fsl_diu_monitor_port port) |
267 | return snprintf(buf, PAGE_SIZE, | ||
268 | "%c0 - DVI\n" | ||
269 | "%c1 - Single link LVDS\n" | ||
270 | "%c2 - Dual link LVDS\n", | ||
271 | monitor_port == 0 ? '*' : ' ', | ||
272 | monitor_port == 1 ? '*' : ' ', | ||
273 | monitor_port == 2 ? '*' : ' '); | ||
274 | } | ||
275 | |||
276 | int mpc8610hpcd_set_sysfs_monitor_port(int val) | ||
277 | { | 273 | { |
278 | return val < 3 ? val : 0; | 274 | return port; |
279 | } | 275 | } |
280 | 276 | ||
281 | #endif | 277 | #endif |
@@ -307,8 +303,7 @@ static void __init mpc86xx_hpcd_setup_arch(void) | |||
307 | diu_ops.set_gamma_table = mpc8610hpcd_set_gamma_table; | 303 | diu_ops.set_gamma_table = mpc8610hpcd_set_gamma_table; |
308 | diu_ops.set_monitor_port = mpc8610hpcd_set_monitor_port; | 304 | diu_ops.set_monitor_port = mpc8610hpcd_set_monitor_port; |
309 | diu_ops.set_pixel_clock = mpc8610hpcd_set_pixel_clock; | 305 | diu_ops.set_pixel_clock = mpc8610hpcd_set_pixel_clock; |
310 | diu_ops.show_monitor_port = mpc8610hpcd_show_monitor_port; | 306 | diu_ops.valid_monitor_port = mpc8610hpcd_valid_monitor_port; |
311 | diu_ops.set_sysfs_monitor_port = mpc8610hpcd_set_sysfs_monitor_port; | ||
312 | #endif | 307 | #endif |
313 | 308 | ||
314 | pixis_node = of_find_compatible_node(NULL, NULL, "fsl,fpga-pixis"); | 309 | pixis_node = of_find_compatible_node(NULL, NULL, "fsl,fpga-pixis"); |
diff --git a/arch/powerpc/sysdev/fsl_soc.h b/arch/powerpc/sysdev/fsl_soc.h index 2ece02beb8ff..c6d00736f07f 100644 --- a/arch/powerpc/sysdev/fsl_soc.h +++ b/arch/powerpc/sysdev/fsl_soc.h | |||
@@ -22,15 +22,24 @@ struct device_node; | |||
22 | extern void fsl_rstcr_restart(char *cmd); | 22 | extern void fsl_rstcr_restart(char *cmd); |
23 | 23 | ||
24 | #if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE) | 24 | #if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE) |
25 | |||
26 | /* The different ports that the DIU can be connected to */ | ||
27 | enum fsl_diu_monitor_port { | ||
28 | FSL_DIU_PORT_DVI, /* DVI */ | ||
29 | FSL_DIU_PORT_LVDS, /* Single-link LVDS */ | ||
30 | FSL_DIU_PORT_DLVDS /* Dual-link LVDS */ | ||
31 | }; | ||
32 | |||
25 | struct platform_diu_data_ops { | 33 | struct platform_diu_data_ops { |
26 | unsigned int (*get_pixel_format) (unsigned int bits_per_pixel, | 34 | u32 (*get_pixel_format)(enum fsl_diu_monitor_port port, |
27 | int monitor_port); | 35 | unsigned int bpp); |
28 | void (*set_gamma_table) (int monitor_port, char *gamma_table_base); | 36 | void (*set_gamma_table)(enum fsl_diu_monitor_port port, |
29 | void (*set_monitor_port) (int monitor_port); | 37 | char *gamma_table_base); |
30 | void (*set_pixel_clock) (unsigned int pixclock); | 38 | void (*set_monitor_port)(enum fsl_diu_monitor_port port); |
31 | ssize_t (*show_monitor_port) (int monitor_port, char *buf); | 39 | void (*set_pixel_clock)(unsigned int pixclock); |
32 | int (*set_sysfs_monitor_port) (int val); | 40 | enum fsl_diu_monitor_port (*valid_monitor_port) |
33 | void (*release_bootmem) (void); | 41 | (enum fsl_diu_monitor_port port); |
42 | void (*release_bootmem)(void); | ||
34 | }; | 43 | }; |
35 | 44 | ||
36 | extern struct platform_diu_data_ops diu_ops; | 45 | extern struct platform_diu_data_ops diu_ops; |
diff --git a/drivers/media/video/omap/omap_vout.c b/drivers/media/video/omap/omap_vout.c index b3a5ecdb33ac..30d8896bb710 100644 --- a/drivers/media/video/omap/omap_vout.c +++ b/drivers/media/video/omap/omap_vout.c | |||
@@ -400,7 +400,6 @@ static int omapvid_setup_overlay(struct omap_vout_device *vout, | |||
400 | 400 | ||
401 | ovl->get_overlay_info(ovl, &info); | 401 | ovl->get_overlay_info(ovl, &info); |
402 | info.paddr = addr; | 402 | info.paddr = addr; |
403 | info.vaddr = NULL; | ||
404 | info.width = cropwidth; | 403 | info.width = cropwidth; |
405 | info.height = cropheight; | 404 | info.height = cropheight; |
406 | info.color_mode = vout->dss_mode; | 405 | info.color_mode = vout->dss_mode; |
@@ -1165,12 +1164,17 @@ static int vidioc_try_fmt_vid_overlay(struct file *file, void *fh, | |||
1165 | { | 1164 | { |
1166 | int ret = 0; | 1165 | int ret = 0; |
1167 | struct omap_vout_device *vout = fh; | 1166 | struct omap_vout_device *vout = fh; |
1167 | struct omap_overlay *ovl; | ||
1168 | struct omapvideo_info *ovid; | ||
1168 | struct v4l2_window *win = &f->fmt.win; | 1169 | struct v4l2_window *win = &f->fmt.win; |
1169 | 1170 | ||
1171 | ovid = &vout->vid_info; | ||
1172 | ovl = ovid->overlays[0]; | ||
1173 | |||
1170 | ret = omap_vout_try_window(&vout->fbuf, win); | 1174 | ret = omap_vout_try_window(&vout->fbuf, win); |
1171 | 1175 | ||
1172 | if (!ret) { | 1176 | if (!ret) { |
1173 | if (vout->vid == OMAP_VIDEO1) | 1177 | if ((ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) == 0) |
1174 | win->global_alpha = 255; | 1178 | win->global_alpha = 255; |
1175 | else | 1179 | else |
1176 | win->global_alpha = f->fmt.win.global_alpha; | 1180 | win->global_alpha = f->fmt.win.global_alpha; |
@@ -1194,8 +1198,8 @@ static int vidioc_s_fmt_vid_overlay(struct file *file, void *fh, | |||
1194 | 1198 | ||
1195 | ret = omap_vout_new_window(&vout->crop, &vout->win, &vout->fbuf, win); | 1199 | ret = omap_vout_new_window(&vout->crop, &vout->win, &vout->fbuf, win); |
1196 | if (!ret) { | 1200 | if (!ret) { |
1197 | /* Video1 plane does not support global alpha */ | 1201 | /* Video1 plane does not support global alpha on OMAP3 */ |
1198 | if (ovl->id == OMAP_DSS_VIDEO1) | 1202 | if ((ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) == 0) |
1199 | vout->win.global_alpha = 255; | 1203 | vout->win.global_alpha = 255; |
1200 | else | 1204 | else |
1201 | vout->win.global_alpha = f->fmt.win.global_alpha; | 1205 | vout->win.global_alpha = f->fmt.win.global_alpha; |
@@ -1788,7 +1792,9 @@ static int vidioc_s_fbuf(struct file *file, void *fh, | |||
1788 | if (ovl->manager && ovl->manager->get_manager_info && | 1792 | if (ovl->manager && ovl->manager->get_manager_info && |
1789 | ovl->manager->set_manager_info) { | 1793 | ovl->manager->set_manager_info) { |
1790 | ovl->manager->get_manager_info(ovl->manager, &info); | 1794 | ovl->manager->get_manager_info(ovl->manager, &info); |
1791 | info.alpha_enabled = enable; | 1795 | /* enable this only if there is no zorder cap */ |
1796 | if ((ovl->caps & OMAP_DSS_OVL_CAP_ZORDER) == 0) | ||
1797 | info.partial_alpha_enabled = enable; | ||
1792 | if (ovl->manager->set_manager_info(ovl->manager, &info)) | 1798 | if (ovl->manager->set_manager_info(ovl->manager, &info)) |
1793 | return -EINVAL; | 1799 | return -EINVAL; |
1794 | } | 1800 | } |
@@ -1820,7 +1826,7 @@ static int vidioc_g_fbuf(struct file *file, void *fh, | |||
1820 | } | 1826 | } |
1821 | if (ovl->manager && ovl->manager->get_manager_info) { | 1827 | if (ovl->manager && ovl->manager->get_manager_info) { |
1822 | ovl->manager->get_manager_info(ovl->manager, &info); | 1828 | ovl->manager->get_manager_info(ovl->manager, &info); |
1823 | if (info.alpha_enabled) | 1829 | if (info.partial_alpha_enabled) |
1824 | a->flags |= V4L2_FBUF_FLAG_LOCAL_ALPHA; | 1830 | a->flags |= V4L2_FBUF_FLAG_LOCAL_ALPHA; |
1825 | } | 1831 | } |
1826 | 1832 | ||
diff --git a/drivers/staging/xgifb/XGI_main_26.c b/drivers/staging/xgifb/XGI_main_26.c index 36db231cd804..277e408c39c5 100644 --- a/drivers/staging/xgifb/XGI_main_26.c +++ b/drivers/staging/xgifb/XGI_main_26.c | |||
@@ -1300,27 +1300,17 @@ static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive, | |||
1300 | return 0; | 1300 | return 0; |
1301 | } | 1301 | } |
1302 | 1302 | ||
1303 | static int XGIfb_pan_var(struct xgifb_video_info *xgifb_info, | 1303 | static int XGIfb_pan_var(struct fb_var_screeninfo *var, struct fb_info *info) |
1304 | struct fb_var_screeninfo *var) | ||
1305 | { | 1304 | { |
1305 | struct xgifb_video_info *xgifb_info = info->par; | ||
1306 | unsigned int base; | 1306 | unsigned int base; |
1307 | 1307 | ||
1308 | /* printk("Inside pan_var"); */ | 1308 | /* printk("Inside pan_var"); */ |
1309 | 1309 | ||
1310 | if (var->xoffset > (var->xres_virtual - var->xres)) { | 1310 | base = var->yoffset * info->var.xres_virtual + var->xoffset; |
1311 | /* printk("Pan: xo: %d xv %d xr %d\n", | ||
1312 | var->xoffset, var->xres_virtual, var->xres); */ | ||
1313 | return -EINVAL; | ||
1314 | } | ||
1315 | if (var->yoffset > (var->yres_virtual - var->yres)) { | ||
1316 | /* printk("Pan: yo: %d yv %d yr %d\n", | ||
1317 | var->yoffset, var->yres_virtual, var->yres); */ | ||
1318 | return -EINVAL; | ||
1319 | } | ||
1320 | base = var->yoffset * var->xres_virtual + var->xoffset; | ||
1321 | 1311 | ||
1322 | /* calculate base bpp dep. */ | 1312 | /* calculate base bpp dep. */ |
1323 | switch (var->bits_per_pixel) { | 1313 | switch (info->var.bits_per_pixel) { |
1324 | case 16: | 1314 | case 16: |
1325 | base >>= 1; | 1315 | base >>= 1; |
1326 | break; | 1316 | break; |
@@ -1615,13 +1605,12 @@ static int XGIfb_pan_display(struct fb_var_screeninfo *var, | |||
1615 | struct fb_info *info) | 1605 | struct fb_info *info) |
1616 | { | 1606 | { |
1617 | int err; | 1607 | int err; |
1618 | struct xgifb_video_info *xgifb_info = info->par; | ||
1619 | 1608 | ||
1620 | /* printk("\nInside pan_display:\n"); */ | 1609 | /* printk("\nInside pan_display:\n"); */ |
1621 | 1610 | ||
1622 | if (var->xoffset > (var->xres_virtual - var->xres)) | 1611 | if (var->xoffset > (info->var.xres_virtual - info->var.xres)) |
1623 | return -EINVAL; | 1612 | return -EINVAL; |
1624 | if (var->yoffset > (var->yres_virtual - var->yres)) | 1613 | if (var->yoffset > (info->var.yres_virtual - info->var.yres)) |
1625 | return -EINVAL; | 1614 | return -EINVAL; |
1626 | 1615 | ||
1627 | if (var->vmode & FB_VMODE_YWRAP) { | 1616 | if (var->vmode & FB_VMODE_YWRAP) { |
@@ -1634,7 +1623,7 @@ static int XGIfb_pan_display(struct fb_var_screeninfo *var, | |||
1634 | > info->var.yres_virtual) | 1623 | > info->var.yres_virtual) |
1635 | return -EINVAL; | 1624 | return -EINVAL; |
1636 | } | 1625 | } |
1637 | err = XGIfb_pan_var(xgifb_info, var); | 1626 | err = XGIfb_pan_var(var, info); |
1638 | if (err < 0) | 1627 | if (err < 0) |
1639 | return err; | 1628 | return err; |
1640 | 1629 | ||
diff --git a/drivers/video/68328fb.c b/drivers/video/68328fb.c index 75a39eab70c3..a425d65d5ba2 100644 --- a/drivers/video/68328fb.c +++ b/drivers/video/68328fb.c | |||
@@ -378,8 +378,8 @@ static int mc68x328fb_pan_display(struct fb_var_screeninfo *var, | |||
378 | || var->xoffset) | 378 | || var->xoffset) |
379 | return -EINVAL; | 379 | return -EINVAL; |
380 | } else { | 380 | } else { |
381 | if (var->xoffset + var->xres > info->var.xres_virtual || | 381 | if (var->xoffset + info->var.xres > info->var.xres_virtual || |
382 | var->yoffset + var->yres > info->var.yres_virtual) | 382 | var->yoffset + info->var.yres > info->var.yres_virtual) |
383 | return -EINVAL; | 383 | return -EINVAL; |
384 | } | 384 | } |
385 | info->var.xoffset = var->xoffset; | 385 | info->var.xoffset = var->xoffset; |
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 549b960667c8..8165c5577d71 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig | |||
@@ -259,6 +259,15 @@ config FB_TILEBLITTING | |||
259 | comment "Frame buffer hardware drivers" | 259 | comment "Frame buffer hardware drivers" |
260 | depends on FB | 260 | depends on FB |
261 | 261 | ||
262 | config FB_GRVGA | ||
263 | tristate "Aeroflex Gaisler framebuffer support" | ||
264 | depends on FB && SPARC | ||
265 | select FB_CFB_FILLRECT | ||
266 | select FB_CFB_COPYAREA | ||
267 | select FB_CFB_IMAGEBLIT | ||
268 | ---help--- | ||
269 | This enables support for the SVGACTRL framebuffer in the GRLIB IP library from Aeroflex Gaisler. | ||
270 | |||
262 | config FB_CIRRUS | 271 | config FB_CIRRUS |
263 | tristate "Cirrus Logic support" | 272 | tristate "Cirrus Logic support" |
264 | depends on FB && (ZORRO || PCI) | 273 | depends on FB && (ZORRO || PCI) |
@@ -1756,9 +1765,10 @@ config FB_AU1100 | |||
1756 | config FB_AU1200 | 1765 | config FB_AU1200 |
1757 | bool "Au1200 LCD Driver" | 1766 | bool "Au1200 LCD Driver" |
1758 | depends on (FB = y) && MIPS && SOC_AU1200 | 1767 | depends on (FB = y) && MIPS && SOC_AU1200 |
1759 | select FB_CFB_FILLRECT | 1768 | select FB_SYS_FILLRECT |
1760 | select FB_CFB_COPYAREA | 1769 | select FB_SYS_COPYAREA |
1761 | select FB_CFB_IMAGEBLIT | 1770 | select FB_SYS_IMAGEBLIT |
1771 | select FB_SYS_FOPS | ||
1762 | help | 1772 | help |
1763 | This is the framebuffer driver for the AMD Au1200 SOC. It can drive | 1773 | This is the framebuffer driver for the AMD Au1200 SOC. It can drive |
1764 | various panels and CRTs by passing in kernel cmd line option | 1774 | various panels and CRTs by passing in kernel cmd line option |
@@ -2027,7 +2037,7 @@ config FB_TMIO_ACCELL | |||
2027 | 2037 | ||
2028 | config FB_S3C | 2038 | config FB_S3C |
2029 | tristate "Samsung S3C framebuffer support" | 2039 | tristate "Samsung S3C framebuffer support" |
2030 | depends on FB && S3C_DEV_FB | 2040 | depends on FB && (S3C_DEV_FB || S5P_DEV_FIMD0) |
2031 | select FB_CFB_FILLRECT | 2041 | select FB_CFB_FILLRECT |
2032 | select FB_CFB_COPYAREA | 2042 | select FB_CFB_COPYAREA |
2033 | select FB_CFB_IMAGEBLIT | 2043 | select FB_CFB_IMAGEBLIT |
@@ -2110,6 +2120,22 @@ config FB_SM501 | |||
2110 | 2120 | ||
2111 | If unsure, say N. | 2121 | If unsure, say N. |
2112 | 2122 | ||
2123 | config FB_SMSCUFX | ||
2124 | tristate "SMSC UFX6000/7000 USB Framebuffer support" | ||
2125 | depends on FB && USB | ||
2126 | select FB_MODE_HELPERS | ||
2127 | select FB_SYS_FILLRECT | ||
2128 | select FB_SYS_COPYAREA | ||
2129 | select FB_SYS_IMAGEBLIT | ||
2130 | select FB_SYS_FOPS | ||
2131 | select FB_DEFERRED_IO | ||
2132 | ---help--- | ||
2133 | This is a kernel framebuffer driver for SMSC UFX USB devices. | ||
2134 | Supports fbdev clients like xf86-video-fbdev, kdrive, fbi, and | ||
2135 | mplayer -vo fbdev. Supports both UFX6000 (USB 2.0) and UFX7000 | ||
2136 | (USB 3.0) devices. | ||
2137 | To compile as a module, choose M here: the module name is smscufx. | ||
2138 | |||
2113 | config FB_UDL | 2139 | config FB_UDL |
2114 | tristate "Displaylink USB Framebuffer support" | 2140 | tristate "Displaylink USB Framebuffer support" |
2115 | depends on FB && USB | 2141 | depends on FB && USB |
diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 8b83129e209c..9b9d8fff7732 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile | |||
@@ -33,6 +33,7 @@ obj-$(CONFIG_FB_AMIGA) += amifb.o c2p_planar.o | |||
33 | obj-$(CONFIG_FB_ARC) += arcfb.o | 33 | obj-$(CONFIG_FB_ARC) += arcfb.o |
34 | obj-$(CONFIG_FB_CLPS711X) += clps711xfb.o | 34 | obj-$(CONFIG_FB_CLPS711X) += clps711xfb.o |
35 | obj-$(CONFIG_FB_CYBER2000) += cyber2000fb.o | 35 | obj-$(CONFIG_FB_CYBER2000) += cyber2000fb.o |
36 | obj-$(CONFIG_FB_GRVGA) += grvga.o | ||
36 | obj-$(CONFIG_FB_PM2) += pm2fb.o | 37 | obj-$(CONFIG_FB_PM2) += pm2fb.o |
37 | obj-$(CONFIG_FB_PM3) += pm3fb.o | 38 | obj-$(CONFIG_FB_PM3) += pm3fb.o |
38 | 39 | ||
@@ -127,6 +128,7 @@ obj-$(CONFIG_FB_IBM_GXT4500) += gxt4500.o | |||
127 | obj-$(CONFIG_FB_PS3) += ps3fb.o | 128 | obj-$(CONFIG_FB_PS3) += ps3fb.o |
128 | obj-$(CONFIG_FB_SM501) += sm501fb.o | 129 | obj-$(CONFIG_FB_SM501) += sm501fb.o |
129 | obj-$(CONFIG_FB_UDL) += udlfb.o | 130 | obj-$(CONFIG_FB_UDL) += udlfb.o |
131 | obj-$(CONFIG_FB_SMSCUFX) += smscufx.o | ||
130 | obj-$(CONFIG_FB_XILINX) += xilinxfb.o | 132 | obj-$(CONFIG_FB_XILINX) += xilinxfb.o |
131 | obj-$(CONFIG_SH_MIPI_DSI) += sh_mipi_dsi.o | 133 | obj-$(CONFIG_SH_MIPI_DSI) += sh_mipi_dsi.o |
132 | obj-$(CONFIG_FB_SH_MOBILE_HDMI) += sh_mobile_hdmi.o | 134 | obj-$(CONFIG_FB_SH_MOBILE_HDMI) += sh_mobile_hdmi.o |
diff --git a/drivers/video/acornfb.c b/drivers/video/acornfb.c index 6183a57eb69d..b303f1715065 100644 --- a/drivers/video/acornfb.c +++ b/drivers/video/acornfb.c | |||
@@ -850,9 +850,10 @@ acornfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) | |||
850 | u_int y_bottom = var->yoffset; | 850 | u_int y_bottom = var->yoffset; |
851 | 851 | ||
852 | if (!(var->vmode & FB_VMODE_YWRAP)) | 852 | if (!(var->vmode & FB_VMODE_YWRAP)) |
853 | y_bottom += var->yres; | 853 | y_bottom += info->var.yres; |
854 | 854 | ||
855 | BUG_ON(y_bottom > var->yres_virtual); | 855 | if (y_bottom > info->var.yres_virtual) |
856 | return -EINVAL; | ||
856 | 857 | ||
857 | acornfb_update_dma(info, var); | 858 | acornfb_update_dma(info, var); |
858 | 859 | ||
diff --git a/drivers/video/arkfb.c b/drivers/video/arkfb.c index 8686429cbdf0..555dd4c64f5b 100644 --- a/drivers/video/arkfb.c +++ b/drivers/video/arkfb.c | |||
@@ -908,13 +908,14 @@ static int arkfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info | |||
908 | unsigned int offset; | 908 | unsigned int offset; |
909 | 909 | ||
910 | /* Calculate the offset */ | 910 | /* Calculate the offset */ |
911 | if (var->bits_per_pixel == 0) { | 911 | if (info->var.bits_per_pixel == 0) { |
912 | offset = (var->yoffset / 16) * (var->xres_virtual / 2) + (var->xoffset / 2); | 912 | offset = (var->yoffset / 16) * (info->var.xres_virtual / 2) |
913 | + (var->xoffset / 2); | ||
913 | offset = offset >> 2; | 914 | offset = offset >> 2; |
914 | } else { | 915 | } else { |
915 | offset = (var->yoffset * info->fix.line_length) + | 916 | offset = (var->yoffset * info->fix.line_length) + |
916 | (var->xoffset * var->bits_per_pixel / 8); | 917 | (var->xoffset * info->var.bits_per_pixel / 8); |
917 | offset = offset >> ((var->bits_per_pixel == 4) ? 2 : 3); | 918 | offset = offset >> ((info->var.bits_per_pixel == 4) ? 2 : 3); |
918 | } | 919 | } |
919 | 920 | ||
920 | /* Set the offset */ | 921 | /* Set the offset */ |
diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c index dda920623c6a..4ac48d9ee665 100644 --- a/drivers/video/atmel_lcdfb.c +++ b/drivers/video/atmel_lcdfb.c | |||
@@ -39,7 +39,8 @@ | |||
39 | | FBINFO_HWACCEL_YPAN) | 39 | | FBINFO_HWACCEL_YPAN) |
40 | 40 | ||
41 | static inline void atmel_lcdfb_update_dma2d(struct atmel_lcdfb_info *sinfo, | 41 | static inline void atmel_lcdfb_update_dma2d(struct atmel_lcdfb_info *sinfo, |
42 | struct fb_var_screeninfo *var) | 42 | struct fb_var_screeninfo *var, |
43 | struct fb_info *info) | ||
43 | { | 44 | { |
44 | 45 | ||
45 | } | 46 | } |
@@ -50,14 +51,16 @@ static inline void atmel_lcdfb_update_dma2d(struct atmel_lcdfb_info *sinfo, | |||
50 | | FBINFO_HWACCEL_YPAN) | 51 | | FBINFO_HWACCEL_YPAN) |
51 | 52 | ||
52 | static void atmel_lcdfb_update_dma2d(struct atmel_lcdfb_info *sinfo, | 53 | static void atmel_lcdfb_update_dma2d(struct atmel_lcdfb_info *sinfo, |
53 | struct fb_var_screeninfo *var) | 54 | struct fb_var_screeninfo *var, |
55 | struct fb_info *info) | ||
54 | { | 56 | { |
55 | u32 dma2dcfg; | 57 | u32 dma2dcfg; |
56 | u32 pixeloff; | 58 | u32 pixeloff; |
57 | 59 | ||
58 | pixeloff = (var->xoffset * var->bits_per_pixel) & 0x1f; | 60 | pixeloff = (var->xoffset * info->var.bits_per_pixel) & 0x1f; |
59 | 61 | ||
60 | dma2dcfg = ((var->xres_virtual - var->xres) * var->bits_per_pixel) / 8; | 62 | dma2dcfg = (info->var.xres_virtual - info->var.xres) |
63 | * info->var.bits_per_pixel / 8; | ||
61 | dma2dcfg |= pixeloff << ATMEL_LCDC_PIXELOFF_OFFSET; | 64 | dma2dcfg |= pixeloff << ATMEL_LCDC_PIXELOFF_OFFSET; |
62 | lcdc_writel(sinfo, ATMEL_LCDC_DMA2DCFG, dma2dcfg); | 65 | lcdc_writel(sinfo, ATMEL_LCDC_DMA2DCFG, dma2dcfg); |
63 | 66 | ||
@@ -249,14 +252,14 @@ static void atmel_lcdfb_update_dma(struct fb_info *info, | |||
249 | unsigned long dma_addr; | 252 | unsigned long dma_addr; |
250 | 253 | ||
251 | dma_addr = (fix->smem_start + var->yoffset * fix->line_length | 254 | dma_addr = (fix->smem_start + var->yoffset * fix->line_length |
252 | + var->xoffset * var->bits_per_pixel / 8); | 255 | + var->xoffset * info->var.bits_per_pixel / 8); |
253 | 256 | ||
254 | dma_addr &= ~3UL; | 257 | dma_addr &= ~3UL; |
255 | 258 | ||
256 | /* Set framebuffer DMA base address and pixel offset */ | 259 | /* Set framebuffer DMA base address and pixel offset */ |
257 | lcdc_writel(sinfo, ATMEL_LCDC_DMABADDR1, dma_addr); | 260 | lcdc_writel(sinfo, ATMEL_LCDC_DMABADDR1, dma_addr); |
258 | 261 | ||
259 | atmel_lcdfb_update_dma2d(sinfo, var); | 262 | atmel_lcdfb_update_dma2d(sinfo, var, info); |
260 | } | 263 | } |
261 | 264 | ||
262 | static inline void atmel_lcdfb_free_video_memory(struct atmel_lcdfb_info *sinfo) | 265 | static inline void atmel_lcdfb_free_video_memory(struct atmel_lcdfb_info *sinfo) |
diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c index 32f8cf6200a7..150684882ef7 100644 --- a/drivers/video/aty/radeon_base.c +++ b/drivers/video/aty/radeon_base.c | |||
@@ -845,16 +845,16 @@ static int radeonfb_pan_display (struct fb_var_screeninfo *var, | |||
845 | { | 845 | { |
846 | struct radeonfb_info *rinfo = info->par; | 846 | struct radeonfb_info *rinfo = info->par; |
847 | 847 | ||
848 | if ((var->xoffset + var->xres > var->xres_virtual) | 848 | if ((var->xoffset + info->var.xres > info->var.xres_virtual) |
849 | || (var->yoffset + var->yres > var->yres_virtual)) | 849 | || (var->yoffset + info->var.yres > info->var.yres_virtual)) |
850 | return -EINVAL; | 850 | return -EINVAL; |
851 | 851 | ||
852 | if (rinfo->asleep) | 852 | if (rinfo->asleep) |
853 | return 0; | 853 | return 0; |
854 | 854 | ||
855 | radeon_fifo_wait(2); | 855 | radeon_fifo_wait(2); |
856 | OUTREG(CRTC_OFFSET, ((var->yoffset * var->xres_virtual + var->xoffset) | 856 | OUTREG(CRTC_OFFSET, (var->yoffset * info->fix.line_length + |
857 | * var->bits_per_pixel / 8) & ~7); | 857 | var->xoffset * info->var.bits_per_pixel / 8) & ~7); |
858 | return 0; | 858 | return 0; |
859 | } | 859 | } |
860 | 860 | ||
diff --git a/drivers/video/au1100fb.c b/drivers/video/au1100fb.c index 01a8fde67f20..649cb35de4ed 100644 --- a/drivers/video/au1100fb.c +++ b/drivers/video/au1100fb.c | |||
@@ -110,12 +110,6 @@ static struct fb_var_screeninfo au1100fb_var __devinitdata = { | |||
110 | .vmode = FB_VMODE_NONINTERLACED, | 110 | .vmode = FB_VMODE_NONINTERLACED, |
111 | }; | 111 | }; |
112 | 112 | ||
113 | static struct au1100fb_drv_info drv_info; | ||
114 | |||
115 | static int nocursor = 0; | ||
116 | module_param(nocursor, int, 0644); | ||
117 | MODULE_PARM_DESC(nocursor, "cursor enable/disable"); | ||
118 | |||
119 | /* fb_blank | 113 | /* fb_blank |
120 | * Blank the screen. Depending on the mode, the screen will be | 114 | * Blank the screen. Depending on the mode, the screen will be |
121 | * activated with the backlight color, or desactivated | 115 | * activated with the backlight color, or desactivated |
@@ -132,7 +126,7 @@ static int au1100fb_fb_blank(int blank_mode, struct fb_info *fbi) | |||
132 | /* Turn on panel */ | 126 | /* Turn on panel */ |
133 | fbdev->regs->lcd_control |= LCD_CONTROL_GO; | 127 | fbdev->regs->lcd_control |= LCD_CONTROL_GO; |
134 | #ifdef CONFIG_MIPS_PB1100 | 128 | #ifdef CONFIG_MIPS_PB1100 |
135 | if (drv_info.panel_idx == 1) { | 129 | if (fbdev->panel_idx == 1) { |
136 | au_writew(au_readw(PB1100_G_CONTROL) | 130 | au_writew(au_readw(PB1100_G_CONTROL) |
137 | | (PB1100_G_CONTROL_BL | PB1100_G_CONTROL_VDD), | 131 | | (PB1100_G_CONTROL_BL | PB1100_G_CONTROL_VDD), |
138 | PB1100_G_CONTROL); | 132 | PB1100_G_CONTROL); |
@@ -147,7 +141,7 @@ static int au1100fb_fb_blank(int blank_mode, struct fb_info *fbi) | |||
147 | /* Turn off panel */ | 141 | /* Turn off panel */ |
148 | fbdev->regs->lcd_control &= ~LCD_CONTROL_GO; | 142 | fbdev->regs->lcd_control &= ~LCD_CONTROL_GO; |
149 | #ifdef CONFIG_MIPS_PB1100 | 143 | #ifdef CONFIG_MIPS_PB1100 |
150 | if (drv_info.panel_idx == 1) { | 144 | if (fbdev->panel_idx == 1) { |
151 | au_writew(au_readw(PB1100_G_CONTROL) | 145 | au_writew(au_readw(PB1100_G_CONTROL) |
152 | & ~(PB1100_G_CONTROL_BL | PB1100_G_CONTROL_VDD), | 146 | & ~(PB1100_G_CONTROL_BL | PB1100_G_CONTROL_VDD), |
153 | PB1100_G_CONTROL); | 147 | PB1100_G_CONTROL); |
@@ -428,17 +422,6 @@ int au1100fb_fb_mmap(struct fb_info *fbi, struct vm_area_struct *vma) | |||
428 | return 0; | 422 | return 0; |
429 | } | 423 | } |
430 | 424 | ||
431 | /* fb_cursor | ||
432 | * Used to disable cursor drawing... | ||
433 | */ | ||
434 | int au1100fb_fb_cursor(struct fb_info *info, struct fb_cursor *cursor) | ||
435 | { | ||
436 | if (nocursor) | ||
437 | return 0; | ||
438 | else | ||
439 | return -EINVAL; /* just to force soft_cursor() call */ | ||
440 | } | ||
441 | |||
442 | static struct fb_ops au1100fb_ops = | 425 | static struct fb_ops au1100fb_ops = |
443 | { | 426 | { |
444 | .owner = THIS_MODULE, | 427 | .owner = THIS_MODULE, |
@@ -450,13 +433,53 @@ static struct fb_ops au1100fb_ops = | |||
450 | .fb_imageblit = cfb_imageblit, | 433 | .fb_imageblit = cfb_imageblit, |
451 | .fb_rotate = au1100fb_fb_rotate, | 434 | .fb_rotate = au1100fb_fb_rotate, |
452 | .fb_mmap = au1100fb_fb_mmap, | 435 | .fb_mmap = au1100fb_fb_mmap, |
453 | .fb_cursor = au1100fb_fb_cursor, | ||
454 | }; | 436 | }; |
455 | 437 | ||
456 | 438 | ||
457 | /*-------------------------------------------------------------------------*/ | 439 | /*-------------------------------------------------------------------------*/ |
458 | 440 | ||
459 | /* AU1100 LCD controller device driver */ | 441 | static int au1100fb_setup(struct au1100fb_device *fbdev) |
442 | { | ||
443 | char *this_opt, *options; | ||
444 | int num_panels = ARRAY_SIZE(known_lcd_panels); | ||
445 | |||
446 | if (num_panels <= 0) { | ||
447 | print_err("No LCD panels supported by driver!"); | ||
448 | return -ENODEV; | ||
449 | } | ||
450 | |||
451 | if (fb_get_options(DRIVER_NAME, &options)) | ||
452 | return -ENODEV; | ||
453 | if (!options) | ||
454 | return -ENODEV; | ||
455 | |||
456 | while ((this_opt = strsep(&options, ",")) != NULL) { | ||
457 | /* Panel option */ | ||
458 | if (!strncmp(this_opt, "panel:", 6)) { | ||
459 | int i; | ||
460 | this_opt += 6; | ||
461 | for (i = 0; i < num_panels; i++) { | ||
462 | if (!strncmp(this_opt, known_lcd_panels[i].name, | ||
463 | strlen(this_opt))) { | ||
464 | fbdev->panel = &known_lcd_panels[i]; | ||
465 | fbdev->panel_idx = i; | ||
466 | break; | ||
467 | } | ||
468 | } | ||
469 | if (i >= num_panels) { | ||
470 | print_warn("Panel '%s' not supported!", this_opt); | ||
471 | return -ENODEV; | ||
472 | } | ||
473 | } | ||
474 | /* Unsupported option */ | ||
475 | else | ||
476 | print_warn("Unsupported option \"%s\"", this_opt); | ||
477 | } | ||
478 | |||
479 | print_info("Panel=%s", fbdev->panel->name); | ||
480 | |||
481 | return 0; | ||
482 | } | ||
460 | 483 | ||
461 | static int __devinit au1100fb_drv_probe(struct platform_device *dev) | 484 | static int __devinit au1100fb_drv_probe(struct platform_device *dev) |
462 | { | 485 | { |
@@ -465,22 +488,21 @@ static int __devinit au1100fb_drv_probe(struct platform_device *dev) | |||
465 | unsigned long page; | 488 | unsigned long page; |
466 | u32 sys_clksrc; | 489 | u32 sys_clksrc; |
467 | 490 | ||
468 | if (!dev) | ||
469 | return -EINVAL; | ||
470 | |||
471 | /* Allocate new device private */ | 491 | /* Allocate new device private */ |
472 | if (!(fbdev = kzalloc(sizeof(struct au1100fb_device), GFP_KERNEL))) { | 492 | fbdev = kzalloc(sizeof(struct au1100fb_device), GFP_KERNEL); |
493 | if (!fbdev) { | ||
473 | print_err("fail to allocate device private record"); | 494 | print_err("fail to allocate device private record"); |
474 | return -ENOMEM; | 495 | return -ENOMEM; |
475 | } | 496 | } |
476 | 497 | ||
477 | fbdev->panel = &known_lcd_panels[drv_info.panel_idx]; | 498 | if (au1100fb_setup(fbdev)) |
499 | goto failed; | ||
478 | 500 | ||
479 | platform_set_drvdata(dev, (void *)fbdev); | 501 | platform_set_drvdata(dev, (void *)fbdev); |
480 | 502 | ||
481 | /* Allocate region for our registers and map them */ | 503 | /* Allocate region for our registers and map them */ |
482 | if (!(regs_res = platform_get_resource(to_platform_device(dev), | 504 | regs_res = platform_get_resource(dev, IORESOURCE_MEM, 0); |
483 | IORESOURCE_MEM, 0))) { | 505 | if (!regs_res) { |
484 | print_err("fail to retrieve registers resource"); | 506 | print_err("fail to retrieve registers resource"); |
485 | return -EFAULT; | 507 | return -EFAULT; |
486 | } | 508 | } |
@@ -500,13 +522,11 @@ static int __devinit au1100fb_drv_probe(struct platform_device *dev) | |||
500 | print_dbg("Register memory map at %p", fbdev->regs); | 522 | print_dbg("Register memory map at %p", fbdev->regs); |
501 | print_dbg("phys=0x%08x, size=%d", fbdev->regs_phys, fbdev->regs_len); | 523 | print_dbg("phys=0x%08x, size=%d", fbdev->regs_phys, fbdev->regs_len); |
502 | 524 | ||
503 | |||
504 | |||
505 | /* Allocate the framebuffer to the maximum screen size * nbr of video buffers */ | 525 | /* Allocate the framebuffer to the maximum screen size * nbr of video buffers */ |
506 | fbdev->fb_len = fbdev->panel->xres * fbdev->panel->yres * | 526 | fbdev->fb_len = fbdev->panel->xres * fbdev->panel->yres * |
507 | (fbdev->panel->bpp >> 3) * AU1100FB_NBR_VIDEO_BUFFERS; | 527 | (fbdev->panel->bpp >> 3) * AU1100FB_NBR_VIDEO_BUFFERS; |
508 | 528 | ||
509 | fbdev->fb_mem = dma_alloc_coherent(dev, PAGE_ALIGN(fbdev->fb_len), | 529 | fbdev->fb_mem = dma_alloc_coherent(&dev->dev, PAGE_ALIGN(fbdev->fb_len), |
510 | &fbdev->fb_phys, GFP_KERNEL); | 530 | &fbdev->fb_phys, GFP_KERNEL); |
511 | if (!fbdev->fb_mem) { | 531 | if (!fbdev->fb_mem) { |
512 | print_err("fail to allocate frambuffer (size: %dK))", | 532 | print_err("fail to allocate frambuffer (size: %dK))", |
@@ -525,7 +545,7 @@ static int __devinit au1100fb_drv_probe(struct platform_device *dev) | |||
525 | page < PAGE_ALIGN((unsigned long)fbdev->fb_mem + fbdev->fb_len); | 545 | page < PAGE_ALIGN((unsigned long)fbdev->fb_mem + fbdev->fb_len); |
526 | page += PAGE_SIZE) { | 546 | page += PAGE_SIZE) { |
527 | #if CONFIG_DMA_NONCOHERENT | 547 | #if CONFIG_DMA_NONCOHERENT |
528 | SetPageReserved(virt_to_page(CAC_ADDR(page))); | 548 | SetPageReserved(virt_to_page(CAC_ADDR((void *)page))); |
529 | #else | 549 | #else |
530 | SetPageReserved(virt_to_page(page)); | 550 | SetPageReserved(virt_to_page(page)); |
531 | #endif | 551 | #endif |
@@ -578,7 +598,8 @@ failed: | |||
578 | release_mem_region(fbdev->regs_phys, fbdev->regs_len); | 598 | release_mem_region(fbdev->regs_phys, fbdev->regs_len); |
579 | } | 599 | } |
580 | if (fbdev->fb_mem) { | 600 | if (fbdev->fb_mem) { |
581 | dma_free_noncoherent(dev, fbdev->fb_len, fbdev->fb_mem, fbdev->fb_phys); | 601 | dma_free_noncoherent(&dev->dev, fbdev->fb_len, fbdev->fb_mem, |
602 | fbdev->fb_phys); | ||
582 | } | 603 | } |
583 | if (fbdev->info.cmap.len != 0) { | 604 | if (fbdev->info.cmap.len != 0) { |
584 | fb_dealloc_cmap(&fbdev->info.cmap); | 605 | fb_dealloc_cmap(&fbdev->info.cmap); |
@@ -608,7 +629,8 @@ int au1100fb_drv_remove(struct platform_device *dev) | |||
608 | 629 | ||
609 | release_mem_region(fbdev->regs_phys, fbdev->regs_len); | 630 | release_mem_region(fbdev->regs_phys, fbdev->regs_len); |
610 | 631 | ||
611 | dma_free_coherent(dev, PAGE_ALIGN(fbdev->fb_len), fbdev->fb_mem, fbdev->fb_phys); | 632 | dma_free_coherent(&dev->dev, PAGE_ALIGN(fbdev->fb_len), fbdev->fb_mem, |
633 | fbdev->fb_phys); | ||
612 | 634 | ||
613 | fb_dealloc_cmap(&fbdev->info.cmap); | 635 | fb_dealloc_cmap(&fbdev->info.cmap); |
614 | kfree(fbdev->info.pseudo_palette); | 636 | kfree(fbdev->info.pseudo_palette); |
@@ -675,101 +697,18 @@ static struct platform_driver au1100fb_driver = { | |||
675 | .resume = au1100fb_drv_resume, | 697 | .resume = au1100fb_drv_resume, |
676 | }; | 698 | }; |
677 | 699 | ||
678 | /*-------------------------------------------------------------------------*/ | 700 | static int __init au1100fb_load(void) |
679 | |||
680 | /* Kernel driver */ | ||
681 | |||
682 | int au1100fb_setup(char *options) | ||
683 | { | ||
684 | char* this_opt; | ||
685 | int num_panels = ARRAY_SIZE(known_lcd_panels); | ||
686 | char* mode = NULL; | ||
687 | int panel_idx = 0; | ||
688 | |||
689 | if (num_panels <= 0) { | ||
690 | print_err("No LCD panels supported by driver!"); | ||
691 | return -EFAULT; | ||
692 | } | ||
693 | |||
694 | if (options) { | ||
695 | while ((this_opt = strsep(&options,",")) != NULL) { | ||
696 | /* Panel option */ | ||
697 | if (!strncmp(this_opt, "panel:", 6)) { | ||
698 | int i; | ||
699 | this_opt += 6; | ||
700 | for (i = 0; i < num_panels; i++) { | ||
701 | if (!strncmp(this_opt, | ||
702 | known_lcd_panels[i].name, | ||
703 | strlen(this_opt))) { | ||
704 | panel_idx = i; | ||
705 | break; | ||
706 | } | ||
707 | } | ||
708 | if (i >= num_panels) { | ||
709 | print_warn("Panel %s not supported!", this_opt); | ||
710 | } | ||
711 | } | ||
712 | if (!strncmp(this_opt, "nocursor", 8)) { | ||
713 | this_opt += 8; | ||
714 | nocursor = 1; | ||
715 | print_info("Cursor disabled"); | ||
716 | } | ||
717 | /* Mode option (only option that start with digit) */ | ||
718 | else if (isdigit(this_opt[0])) { | ||
719 | mode = kstrdup(this_opt, GFP_KERNEL); | ||
720 | if (!mode) { | ||
721 | print_err("memory allocation failed"); | ||
722 | return -ENOMEM; | ||
723 | } | ||
724 | } | ||
725 | /* Unsupported option */ | ||
726 | else { | ||
727 | print_warn("Unsupported option \"%s\"", this_opt); | ||
728 | } | ||
729 | } | ||
730 | } | ||
731 | |||
732 | drv_info.panel_idx = panel_idx; | ||
733 | drv_info.opt_mode = mode; | ||
734 | |||
735 | print_info("Panel=%s Mode=%s", | ||
736 | known_lcd_panels[drv_info.panel_idx].name, | ||
737 | drv_info.opt_mode ? drv_info.opt_mode : "default"); | ||
738 | |||
739 | return 0; | ||
740 | } | ||
741 | |||
742 | int __init au1100fb_init(void) | ||
743 | { | 701 | { |
744 | char* options; | ||
745 | int ret; | ||
746 | |||
747 | print_info("" DRIVER_DESC ""); | ||
748 | |||
749 | memset(&drv_info, 0, sizeof(drv_info)); | ||
750 | |||
751 | if (fb_get_options(DRIVER_NAME, &options)) | ||
752 | return -ENODEV; | ||
753 | |||
754 | /* Setup driver with options */ | ||
755 | ret = au1100fb_setup(options); | ||
756 | if (ret < 0) { | ||
757 | print_err("Fail to setup driver"); | ||
758 | return ret; | ||
759 | } | ||
760 | |||
761 | return platform_driver_register(&au1100fb_driver); | 702 | return platform_driver_register(&au1100fb_driver); |
762 | } | 703 | } |
763 | 704 | ||
764 | void __exit au1100fb_cleanup(void) | 705 | static void __exit au1100fb_unload(void) |
765 | { | 706 | { |
766 | platform_driver_unregister(&au1100fb_driver); | 707 | platform_driver_unregister(&au1100fb_driver); |
767 | |||
768 | kfree(drv_info.opt_mode); | ||
769 | } | 708 | } |
770 | 709 | ||
771 | module_init(au1100fb_init); | 710 | module_init(au1100fb_load); |
772 | module_exit(au1100fb_cleanup); | 711 | module_exit(au1100fb_unload); |
773 | 712 | ||
774 | MODULE_DESCRIPTION(DRIVER_DESC); | 713 | MODULE_DESCRIPTION(DRIVER_DESC); |
775 | MODULE_LICENSE("GPL"); | 714 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/video/au1100fb.h b/drivers/video/au1100fb.h index 164fe2f231ec..12d9642d5465 100644 --- a/drivers/video/au1100fb.h +++ b/drivers/video/au1100fb.h | |||
@@ -108,6 +108,7 @@ struct au1100fb_device { | |||
108 | unsigned char* fb_mem; /* FrameBuffer memory map */ | 108 | unsigned char* fb_mem; /* FrameBuffer memory map */ |
109 | size_t fb_len; | 109 | size_t fb_len; |
110 | dma_addr_t fb_phys; | 110 | dma_addr_t fb_phys; |
111 | int panel_idx; | ||
111 | }; | 112 | }; |
112 | 113 | ||
113 | /********************************************************************/ | 114 | /********************************************************************/ |
@@ -364,11 +365,6 @@ static struct au1100fb_panel known_lcd_panels[] = | |||
364 | }, | 365 | }, |
365 | }; | 366 | }; |
366 | 367 | ||
367 | struct au1100fb_drv_info { | ||
368 | int panel_idx; | ||
369 | char *opt_mode; | ||
370 | }; | ||
371 | |||
372 | /********************************************************************/ | 368 | /********************************************************************/ |
373 | 369 | ||
374 | /* Inline helpers */ | 370 | /* Inline helpers */ |
diff --git a/drivers/video/au1200fb.c b/drivers/video/au1200fb.c index 5dff32ac8044..72005598040f 100644 --- a/drivers/video/au1200fb.c +++ b/drivers/video/au1200fb.c | |||
@@ -46,18 +46,10 @@ | |||
46 | #include <asm/mach-au1x00/au1000.h> | 46 | #include <asm/mach-au1x00/au1000.h> |
47 | #include "au1200fb.h" | 47 | #include "au1200fb.h" |
48 | 48 | ||
49 | #ifdef CONFIG_PM | ||
50 | #include <asm/mach-au1x00/au1xxx_pm.h> | ||
51 | #endif | ||
52 | |||
53 | #ifndef CONFIG_FB_AU1200_DEVS | ||
54 | #define CONFIG_FB_AU1200_DEVS 4 | ||
55 | #endif | ||
56 | |||
57 | #define DRIVER_NAME "au1200fb" | 49 | #define DRIVER_NAME "au1200fb" |
58 | #define DRIVER_DESC "LCD controller driver for AU1200 processors" | 50 | #define DRIVER_DESC "LCD controller driver for AU1200 processors" |
59 | 51 | ||
60 | #define DEBUG 1 | 52 | #define DEBUG 0 |
61 | 53 | ||
62 | #define print_err(f, arg...) printk(KERN_ERR DRIVER_NAME ": " f "\n", ## arg) | 54 | #define print_err(f, arg...) printk(KERN_ERR DRIVER_NAME ": " f "\n", ## arg) |
63 | #define print_warn(f, arg...) printk(KERN_WARNING DRIVER_NAME ": " f "\n", ## arg) | 55 | #define print_warn(f, arg...) printk(KERN_WARNING DRIVER_NAME ": " f "\n", ## arg) |
@@ -150,7 +142,7 @@ struct au1200_lcd_iodata_t { | |||
150 | 142 | ||
151 | /* Private, per-framebuffer management information (independent of the panel itself) */ | 143 | /* Private, per-framebuffer management information (independent of the panel itself) */ |
152 | struct au1200fb_device { | 144 | struct au1200fb_device { |
153 | struct fb_info fb_info; /* FB driver info record */ | 145 | struct fb_info *fb_info; /* FB driver info record */ |
154 | 146 | ||
155 | int plane; | 147 | int plane; |
156 | unsigned char* fb_mem; /* FrameBuffer memory map */ | 148 | unsigned char* fb_mem; /* FrameBuffer memory map */ |
@@ -158,7 +150,6 @@ struct au1200fb_device { | |||
158 | dma_addr_t fb_phys; | 150 | dma_addr_t fb_phys; |
159 | }; | 151 | }; |
160 | 152 | ||
161 | static struct au1200fb_device _au1200fb_devices[CONFIG_FB_AU1200_DEVS]; | ||
162 | /********************************************************************/ | 153 | /********************************************************************/ |
163 | 154 | ||
164 | /* LCD controller restrictions */ | 155 | /* LCD controller restrictions */ |
@@ -171,10 +162,18 @@ static struct au1200fb_device _au1200fb_devices[CONFIG_FB_AU1200_DEVS]; | |||
171 | /* Default number of visible screen buffer to allocate */ | 162 | /* Default number of visible screen buffer to allocate */ |
172 | #define AU1200FB_NBR_VIDEO_BUFFERS 1 | 163 | #define AU1200FB_NBR_VIDEO_BUFFERS 1 |
173 | 164 | ||
165 | /* Default maximum number of fb devices to create */ | ||
166 | #define MAX_DEVICE_COUNT 4 | ||
167 | |||
168 | /* Default window configuration entry to use (see windows[]) */ | ||
169 | #define DEFAULT_WINDOW_INDEX 2 | ||
170 | |||
174 | /********************************************************************/ | 171 | /********************************************************************/ |
175 | 172 | ||
173 | static struct fb_info *_au1200fb_infos[MAX_DEVICE_COUNT]; | ||
176 | static struct au1200_lcd *lcd = (struct au1200_lcd *) AU1200_LCD_ADDR; | 174 | static struct au1200_lcd *lcd = (struct au1200_lcd *) AU1200_LCD_ADDR; |
177 | static int window_index = 2; /* default is zero */ | 175 | static int device_count = MAX_DEVICE_COUNT; |
176 | static int window_index = DEFAULT_WINDOW_INDEX; /* default is zero */ | ||
178 | static int panel_index = 2; /* default is zero */ | 177 | static int panel_index = 2; /* default is zero */ |
179 | static struct window_settings *win; | 178 | static struct window_settings *win; |
180 | static struct panel_settings *panel; | 179 | static struct panel_settings *panel; |
@@ -205,12 +204,6 @@ struct window_settings { | |||
205 | extern int board_au1200fb_panel_init (void); | 204 | extern int board_au1200fb_panel_init (void); |
206 | extern int board_au1200fb_panel_shutdown (void); | 205 | extern int board_au1200fb_panel_shutdown (void); |
207 | 206 | ||
208 | #ifdef CONFIG_PM | ||
209 | int au1200fb_pm_callback(au1xxx_power_dev_t *dev, | ||
210 | au1xxx_request_t request, void *data); | ||
211 | au1xxx_power_dev_t *LCD_pm_dev; | ||
212 | #endif | ||
213 | |||
214 | /* | 207 | /* |
215 | * Default window configurations | 208 | * Default window configurations |
216 | */ | 209 | */ |
@@ -652,25 +645,6 @@ static struct panel_settings known_lcd_panels[] = | |||
652 | 645 | ||
653 | /********************************************************************/ | 646 | /********************************************************************/ |
654 | 647 | ||
655 | #ifdef CONFIG_PM | ||
656 | static int set_brightness(unsigned int brightness) | ||
657 | { | ||
658 | unsigned int hi1, divider; | ||
659 | |||
660 | /* limit brightness pwm duty to >= 30/1600 */ | ||
661 | if (brightness < 30) { | ||
662 | brightness = 30; | ||
663 | } | ||
664 | divider = (lcd->pwmdiv & 0x3FFFF) + 1; | ||
665 | hi1 = (lcd->pwmhi >> 16) + 1; | ||
666 | hi1 = (((brightness & 0xFF) + 1) * divider >> 8); | ||
667 | lcd->pwmhi &= 0xFFFF; | ||
668 | lcd->pwmhi |= (hi1 << 16); | ||
669 | |||
670 | return brightness; | ||
671 | } | ||
672 | #endif /* CONFIG_PM */ | ||
673 | |||
674 | static int winbpp (unsigned int winctrl1) | 648 | static int winbpp (unsigned int winctrl1) |
675 | { | 649 | { |
676 | int bits = 0; | 650 | int bits = 0; |
@@ -712,8 +686,8 @@ static int fbinfo2index (struct fb_info *fb_info) | |||
712 | { | 686 | { |
713 | int i; | 687 | int i; |
714 | 688 | ||
715 | for (i = 0; i < CONFIG_FB_AU1200_DEVS; ++i) { | 689 | for (i = 0; i < device_count; ++i) { |
716 | if (fb_info == (struct fb_info *)(&_au1200fb_devices[i].fb_info)) | 690 | if (fb_info == _au1200fb_infos[i]) |
717 | return i; | 691 | return i; |
718 | } | 692 | } |
719 | printk("au1200fb: ERROR: fbinfo2index failed!\n"); | 693 | printk("au1200fb: ERROR: fbinfo2index failed!\n"); |
@@ -962,7 +936,7 @@ static void au1200_setmode(struct au1200fb_device *fbdev) | |||
962 | lcd->window[plane].winctrl2 = ( 0 | 936 | lcd->window[plane].winctrl2 = ( 0 |
963 | | LCD_WINCTRL2_CKMODE_00 | 937 | | LCD_WINCTRL2_CKMODE_00 |
964 | | LCD_WINCTRL2_DBM | 938 | | LCD_WINCTRL2_DBM |
965 | | LCD_WINCTRL2_BX_N( fbdev->fb_info.fix.line_length) | 939 | | LCD_WINCTRL2_BX_N(fbdev->fb_info->fix.line_length) |
966 | | LCD_WINCTRL2_SCX_1 | 940 | | LCD_WINCTRL2_SCX_1 |
967 | | LCD_WINCTRL2_SCY_1 | 941 | | LCD_WINCTRL2_SCY_1 |
968 | ) ; | 942 | ) ; |
@@ -1050,7 +1024,7 @@ static void au1200fb_update_fbinfo(struct fb_info *fbi) | |||
1050 | static int au1200fb_fb_check_var(struct fb_var_screeninfo *var, | 1024 | static int au1200fb_fb_check_var(struct fb_var_screeninfo *var, |
1051 | struct fb_info *fbi) | 1025 | struct fb_info *fbi) |
1052 | { | 1026 | { |
1053 | struct au1200fb_device *fbdev = (struct au1200fb_device *)fbi; | 1027 | struct au1200fb_device *fbdev = fbi->par; |
1054 | u32 pixclock; | 1028 | u32 pixclock; |
1055 | int screen_size, plane; | 1029 | int screen_size, plane; |
1056 | 1030 | ||
@@ -1142,7 +1116,7 @@ static int au1200fb_fb_check_var(struct fb_var_screeninfo *var, | |||
1142 | */ | 1116 | */ |
1143 | static int au1200fb_fb_set_par(struct fb_info *fbi) | 1117 | static int au1200fb_fb_set_par(struct fb_info *fbi) |
1144 | { | 1118 | { |
1145 | struct au1200fb_device *fbdev = (struct au1200fb_device *)fbi; | 1119 | struct au1200fb_device *fbdev = fbi->par; |
1146 | 1120 | ||
1147 | au1200fb_update_fbinfo(fbi); | 1121 | au1200fb_update_fbinfo(fbi); |
1148 | au1200_setmode(fbdev); | 1122 | au1200_setmode(fbdev); |
@@ -1246,11 +1220,7 @@ static int au1200fb_fb_mmap(struct fb_info *info, struct vm_area_struct *vma) | |||
1246 | { | 1220 | { |
1247 | unsigned int len; | 1221 | unsigned int len; |
1248 | unsigned long start=0, off; | 1222 | unsigned long start=0, off; |
1249 | struct au1200fb_device *fbdev = (struct au1200fb_device *) info; | 1223 | struct au1200fb_device *fbdev = info->par; |
1250 | |||
1251 | #ifdef CONFIG_PM | ||
1252 | au1xxx_pm_access(LCD_pm_dev); | ||
1253 | #endif | ||
1254 | 1224 | ||
1255 | if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) { | 1225 | if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) { |
1256 | return -EINVAL; | 1226 | return -EINVAL; |
@@ -1461,10 +1431,6 @@ static int au1200fb_ioctl(struct fb_info *info, unsigned int cmd, | |||
1461 | int plane; | 1431 | int plane; |
1462 | int val; | 1432 | int val; |
1463 | 1433 | ||
1464 | #ifdef CONFIG_PM | ||
1465 | au1xxx_pm_access(LCD_pm_dev); | ||
1466 | #endif | ||
1467 | |||
1468 | plane = fbinfo2index(info); | 1434 | plane = fbinfo2index(info); |
1469 | print_dbg("au1200fb: ioctl %d on plane %d\n", cmd, plane); | 1435 | print_dbg("au1200fb: ioctl %d on plane %d\n", cmd, plane); |
1470 | 1436 | ||
@@ -1536,9 +1502,11 @@ static struct fb_ops au1200fb_fb_ops = { | |||
1536 | .fb_set_par = au1200fb_fb_set_par, | 1502 | .fb_set_par = au1200fb_fb_set_par, |
1537 | .fb_setcolreg = au1200fb_fb_setcolreg, | 1503 | .fb_setcolreg = au1200fb_fb_setcolreg, |
1538 | .fb_blank = au1200fb_fb_blank, | 1504 | .fb_blank = au1200fb_fb_blank, |
1539 | .fb_fillrect = cfb_fillrect, | 1505 | .fb_fillrect = sys_fillrect, |
1540 | .fb_copyarea = cfb_copyarea, | 1506 | .fb_copyarea = sys_copyarea, |
1541 | .fb_imageblit = cfb_imageblit, | 1507 | .fb_imageblit = sys_imageblit, |
1508 | .fb_read = fb_sys_read, | ||
1509 | .fb_write = fb_sys_write, | ||
1542 | .fb_sync = NULL, | 1510 | .fb_sync = NULL, |
1543 | .fb_ioctl = au1200fb_ioctl, | 1511 | .fb_ioctl = au1200fb_ioctl, |
1544 | .fb_mmap = au1200fb_fb_mmap, | 1512 | .fb_mmap = au1200fb_fb_mmap, |
@@ -1561,10 +1529,9 @@ static irqreturn_t au1200fb_handle_irq(int irq, void* dev_id) | |||
1561 | 1529 | ||
1562 | static int au1200fb_init_fbinfo(struct au1200fb_device *fbdev) | 1530 | static int au1200fb_init_fbinfo(struct au1200fb_device *fbdev) |
1563 | { | 1531 | { |
1564 | struct fb_info *fbi = &fbdev->fb_info; | 1532 | struct fb_info *fbi = fbdev->fb_info; |
1565 | int bpp; | 1533 | int bpp; |
1566 | 1534 | ||
1567 | memset(fbi, 0, sizeof(struct fb_info)); | ||
1568 | fbi->fbops = &au1200fb_fb_ops; | 1535 | fbi->fbops = &au1200fb_fb_ops; |
1569 | 1536 | ||
1570 | bpp = winbpp(win->w[fbdev->plane].mode_winctrl1); | 1537 | bpp = winbpp(win->w[fbdev->plane].mode_winctrl1); |
@@ -1623,24 +1590,36 @@ static int au1200fb_init_fbinfo(struct au1200fb_device *fbdev) | |||
1623 | 1590 | ||
1624 | /* AU1200 LCD controller device driver */ | 1591 | /* AU1200 LCD controller device driver */ |
1625 | 1592 | ||
1626 | static int au1200fb_drv_probe(struct platform_device *dev) | 1593 | static int __devinit au1200fb_drv_probe(struct platform_device *dev) |
1627 | { | 1594 | { |
1628 | struct au1200fb_device *fbdev; | 1595 | struct au1200fb_device *fbdev; |
1596 | struct fb_info *fbi = NULL; | ||
1629 | unsigned long page; | 1597 | unsigned long page; |
1630 | int bpp, plane, ret; | 1598 | int bpp, plane, ret, irq; |
1631 | 1599 | ||
1632 | if (!dev) | 1600 | /* shut gcc up */ |
1633 | return -EINVAL; | 1601 | ret = 0; |
1602 | fbdev = NULL; | ||
1603 | |||
1604 | /* Kickstart the panel */ | ||
1605 | au1200_setpanel(panel); | ||
1634 | 1606 | ||
1635 | for (plane = 0; plane < CONFIG_FB_AU1200_DEVS; ++plane) { | 1607 | for (plane = 0; plane < device_count; ++plane) { |
1636 | bpp = winbpp(win->w[plane].mode_winctrl1); | 1608 | bpp = winbpp(win->w[plane].mode_winctrl1); |
1637 | if (win->w[plane].xres == 0) | 1609 | if (win->w[plane].xres == 0) |
1638 | win->w[plane].xres = panel->Xres; | 1610 | win->w[plane].xres = panel->Xres; |
1639 | if (win->w[plane].yres == 0) | 1611 | if (win->w[plane].yres == 0) |
1640 | win->w[plane].yres = panel->Yres; | 1612 | win->w[plane].yres = panel->Yres; |
1641 | 1613 | ||
1642 | fbdev = &_au1200fb_devices[plane]; | 1614 | fbi = framebuffer_alloc(sizeof(struct au1200fb_device), |
1643 | memset(fbdev, 0, sizeof(struct au1200fb_device)); | 1615 | &dev->dev); |
1616 | if (!fbi) | ||
1617 | goto failed; | ||
1618 | |||
1619 | _au1200fb_infos[plane] = fbi; | ||
1620 | fbdev = fbi->par; | ||
1621 | fbdev->fb_info = fbi; | ||
1622 | |||
1644 | fbdev->plane = plane; | 1623 | fbdev->plane = plane; |
1645 | 1624 | ||
1646 | /* Allocate the framebuffer to the maximum screen size */ | 1625 | /* Allocate the framebuffer to the maximum screen size */ |
@@ -1673,30 +1652,31 @@ static int au1200fb_drv_probe(struct platform_device *dev) | |||
1673 | goto failed; | 1652 | goto failed; |
1674 | 1653 | ||
1675 | /* Register new framebuffer */ | 1654 | /* Register new framebuffer */ |
1676 | if ((ret = register_framebuffer(&fbdev->fb_info)) < 0) { | 1655 | ret = register_framebuffer(fbi); |
1656 | if (ret < 0) { | ||
1677 | print_err("cannot register new framebuffer"); | 1657 | print_err("cannot register new framebuffer"); |
1678 | goto failed; | 1658 | goto failed; |
1679 | } | 1659 | } |
1680 | 1660 | ||
1681 | au1200fb_fb_set_par(&fbdev->fb_info); | 1661 | au1200fb_fb_set_par(fbi); |
1682 | 1662 | ||
1683 | #if !defined(CONFIG_FRAMEBUFFER_CONSOLE) && defined(CONFIG_LOGO) | 1663 | #if !defined(CONFIG_FRAMEBUFFER_CONSOLE) && defined(CONFIG_LOGO) |
1684 | if (plane == 0) | 1664 | if (plane == 0) |
1685 | if (fb_prepare_logo(&fbdev->fb_info, FB_ROTATE_UR)) { | 1665 | if (fb_prepare_logo(fbi, FB_ROTATE_UR)) { |
1686 | /* Start display and show logo on boot */ | 1666 | /* Start display and show logo on boot */ |
1687 | fb_set_cmap(&fbdev->fb_info.cmap, | 1667 | fb_set_cmap(&fbi->cmap, fbi); |
1688 | &fbdev->fb_info); | 1668 | fb_show_logo(fbi, FB_ROTATE_UR); |
1689 | |||
1690 | fb_show_logo(&fbdev->fb_info, FB_ROTATE_UR); | ||
1691 | } | 1669 | } |
1692 | #endif | 1670 | #endif |
1693 | } | 1671 | } |
1694 | 1672 | ||
1695 | /* Now hook interrupt too */ | 1673 | /* Now hook interrupt too */ |
1696 | if ((ret = request_irq(AU1200_LCD_INT, au1200fb_handle_irq, | 1674 | irq = platform_get_irq(dev, 0); |
1697 | IRQF_DISABLED | IRQF_SHARED, "lcd", (void *)dev)) < 0) { | 1675 | ret = request_irq(irq, au1200fb_handle_irq, |
1676 | IRQF_SHARED, "lcd", (void *)dev); | ||
1677 | if (ret) { | ||
1698 | print_err("fail to request interrupt line %d (err: %d)", | 1678 | print_err("fail to request interrupt line %d (err: %d)", |
1699 | AU1200_LCD_INT, ret); | 1679 | irq, ret); |
1700 | goto failed; | 1680 | goto failed; |
1701 | } | 1681 | } |
1702 | 1682 | ||
@@ -1705,84 +1685,108 @@ static int au1200fb_drv_probe(struct platform_device *dev) | |||
1705 | failed: | 1685 | failed: |
1706 | /* NOTE: This only does the current plane/window that failed; others are still active */ | 1686 | /* NOTE: This only does the current plane/window that failed; others are still active */ |
1707 | if (fbdev->fb_mem) | 1687 | if (fbdev->fb_mem) |
1708 | dma_free_noncoherent(dev, PAGE_ALIGN(fbdev->fb_len), | 1688 | dma_free_noncoherent(&dev->dev, PAGE_ALIGN(fbdev->fb_len), |
1709 | fbdev->fb_mem, fbdev->fb_phys); | 1689 | fbdev->fb_mem, fbdev->fb_phys); |
1710 | if (fbdev->fb_info.cmap.len != 0) | 1690 | if (fbi) { |
1711 | fb_dealloc_cmap(&fbdev->fb_info.cmap); | 1691 | if (fbi->cmap.len != 0) |
1712 | if (fbdev->fb_info.pseudo_palette) | 1692 | fb_dealloc_cmap(&fbi->cmap); |
1713 | kfree(fbdev->fb_info.pseudo_palette); | 1693 | kfree(fbi->pseudo_palette); |
1694 | } | ||
1714 | if (plane == 0) | 1695 | if (plane == 0) |
1715 | free_irq(AU1200_LCD_INT, (void*)dev); | 1696 | free_irq(AU1200_LCD_INT, (void*)dev); |
1716 | return ret; | 1697 | return ret; |
1717 | } | 1698 | } |
1718 | 1699 | ||
1719 | static int au1200fb_drv_remove(struct platform_device *dev) | 1700 | static int __devexit au1200fb_drv_remove(struct platform_device *dev) |
1720 | { | 1701 | { |
1721 | struct au1200fb_device *fbdev; | 1702 | struct au1200fb_device *fbdev; |
1703 | struct fb_info *fbi; | ||
1722 | int plane; | 1704 | int plane; |
1723 | 1705 | ||
1724 | if (!dev) | ||
1725 | return -ENODEV; | ||
1726 | |||
1727 | /* Turn off the panel */ | 1706 | /* Turn off the panel */ |
1728 | au1200_setpanel(NULL); | 1707 | au1200_setpanel(NULL); |
1729 | 1708 | ||
1730 | for (plane = 0; plane < CONFIG_FB_AU1200_DEVS; ++plane) | 1709 | for (plane = 0; plane < device_count; ++plane) { |
1731 | { | 1710 | fbi = _au1200fb_infos[plane]; |
1732 | fbdev = &_au1200fb_devices[plane]; | 1711 | fbdev = fbi->par; |
1733 | 1712 | ||
1734 | /* Clean up all probe data */ | 1713 | /* Clean up all probe data */ |
1735 | unregister_framebuffer(&fbdev->fb_info); | 1714 | unregister_framebuffer(fbi); |
1736 | if (fbdev->fb_mem) | 1715 | if (fbdev->fb_mem) |
1737 | dma_free_noncoherent(&dev->dev, | 1716 | dma_free_noncoherent(&dev->dev, |
1738 | PAGE_ALIGN(fbdev->fb_len), | 1717 | PAGE_ALIGN(fbdev->fb_len), |
1739 | fbdev->fb_mem, fbdev->fb_phys); | 1718 | fbdev->fb_mem, fbdev->fb_phys); |
1740 | if (fbdev->fb_info.cmap.len != 0) | 1719 | if (fbi->cmap.len != 0) |
1741 | fb_dealloc_cmap(&fbdev->fb_info.cmap); | 1720 | fb_dealloc_cmap(&fbi->cmap); |
1742 | if (fbdev->fb_info.pseudo_palette) | 1721 | kfree(fbi->pseudo_palette); |
1743 | kfree(fbdev->fb_info.pseudo_palette); | 1722 | |
1723 | framebuffer_release(fbi); | ||
1724 | _au1200fb_infos[plane] = NULL; | ||
1744 | } | 1725 | } |
1745 | 1726 | ||
1746 | free_irq(AU1200_LCD_INT, (void *)dev); | 1727 | free_irq(platform_get_irq(dev, 0), (void *)dev); |
1747 | 1728 | ||
1748 | return 0; | 1729 | return 0; |
1749 | } | 1730 | } |
1750 | 1731 | ||
1751 | #ifdef CONFIG_PM | 1732 | #ifdef CONFIG_PM |
1752 | static int au1200fb_drv_suspend(struct platform_device *dev, u32 state) | 1733 | static int au1200fb_drv_suspend(struct device *dev) |
1753 | { | 1734 | { |
1754 | /* TODO */ | 1735 | au1200_setpanel(NULL); |
1736 | |||
1737 | lcd->outmask = 0; | ||
1738 | au_sync(); | ||
1739 | |||
1755 | return 0; | 1740 | return 0; |
1756 | } | 1741 | } |
1757 | 1742 | ||
1758 | static int au1200fb_drv_resume(struct platform_device *dev) | 1743 | static int au1200fb_drv_resume(struct device *dev) |
1759 | { | 1744 | { |
1760 | /* TODO */ | 1745 | struct fb_info *fbi; |
1746 | int i; | ||
1747 | |||
1748 | /* Kickstart the panel */ | ||
1749 | au1200_setpanel(panel); | ||
1750 | |||
1751 | for (i = 0; i < device_count; i++) { | ||
1752 | fbi = _au1200fb_infos[i]; | ||
1753 | au1200fb_fb_set_par(fbi); | ||
1754 | } | ||
1755 | |||
1761 | return 0; | 1756 | return 0; |
1762 | } | 1757 | } |
1758 | |||
1759 | static const struct dev_pm_ops au1200fb_pmops = { | ||
1760 | .suspend = au1200fb_drv_suspend, | ||
1761 | .resume = au1200fb_drv_resume, | ||
1762 | .freeze = au1200fb_drv_suspend, | ||
1763 | .thaw = au1200fb_drv_resume, | ||
1764 | }; | ||
1765 | |||
1766 | #define AU1200FB_PMOPS (&au1200fb_pmops) | ||
1767 | |||
1768 | #else | ||
1769 | #define AU1200FB_PMOPS NULL | ||
1763 | #endif /* CONFIG_PM */ | 1770 | #endif /* CONFIG_PM */ |
1764 | 1771 | ||
1765 | static struct platform_driver au1200fb_driver = { | 1772 | static struct platform_driver au1200fb_driver = { |
1766 | .driver = { | 1773 | .driver = { |
1767 | .name = "au1200-lcd", | 1774 | .name = "au1200-lcd", |
1768 | .owner = THIS_MODULE, | 1775 | .owner = THIS_MODULE, |
1776 | .pm = AU1200FB_PMOPS, | ||
1769 | }, | 1777 | }, |
1770 | .probe = au1200fb_drv_probe, | 1778 | .probe = au1200fb_drv_probe, |
1771 | .remove = au1200fb_drv_remove, | 1779 | .remove = __devexit_p(au1200fb_drv_remove), |
1772 | #ifdef CONFIG_PM | ||
1773 | .suspend = au1200fb_drv_suspend, | ||
1774 | .resume = au1200fb_drv_resume, | ||
1775 | #endif | ||
1776 | }; | 1780 | }; |
1777 | 1781 | ||
1778 | /*-------------------------------------------------------------------------*/ | 1782 | /*-------------------------------------------------------------------------*/ |
1779 | 1783 | ||
1780 | /* Kernel driver */ | 1784 | /* Kernel driver */ |
1781 | 1785 | ||
1782 | static void au1200fb_setup(void) | 1786 | static int au1200fb_setup(void) |
1783 | { | 1787 | { |
1784 | char* options = NULL; | 1788 | char *options = NULL; |
1785 | char* this_opt; | 1789 | char *this_opt, *endptr; |
1786 | int num_panels = ARRAY_SIZE(known_lcd_panels); | 1790 | int num_panels = ARRAY_SIZE(known_lcd_panels); |
1787 | int panel_idx = -1; | 1791 | int panel_idx = -1; |
1788 | 1792 | ||
@@ -1827,70 +1831,42 @@ static void au1200fb_setup(void) | |||
1827 | nohwcursor = 1; | 1831 | nohwcursor = 1; |
1828 | } | 1832 | } |
1829 | 1833 | ||
1830 | /* Unsupported option */ | 1834 | else if (strncmp(this_opt, "devices:", 8) == 0) { |
1831 | else { | 1835 | this_opt += 8; |
1832 | print_warn("Unsupported option \"%s\"", this_opt); | 1836 | device_count = simple_strtol(this_opt, |
1837 | &endptr, 0); | ||
1838 | if ((device_count < 0) || | ||
1839 | (device_count > MAX_DEVICE_COUNT)) | ||
1840 | device_count = MAX_DEVICE_COUNT; | ||
1833 | } | 1841 | } |
1834 | } | ||
1835 | } | ||
1836 | } | ||
1837 | 1842 | ||
1838 | #ifdef CONFIG_PM | 1843 | else if (strncmp(this_opt, "wincfg:", 7) == 0) { |
1839 | static int au1200fb_pm_callback(au1xxx_power_dev_t *dev, | 1844 | this_opt += 7; |
1840 | au1xxx_request_t request, void *data) { | 1845 | window_index = simple_strtol(this_opt, |
1841 | int retval = -1; | 1846 | &endptr, 0); |
1842 | unsigned int d = 0; | 1847 | if ((window_index < 0) || |
1843 | unsigned int brightness = 0; | 1848 | (window_index >= ARRAY_SIZE(windows))) |
1844 | 1849 | window_index = DEFAULT_WINDOW_INDEX; | |
1845 | if (request == AU1XXX_PM_SLEEP) { | ||
1846 | board_au1200fb_panel_shutdown(); | ||
1847 | } | ||
1848 | else if (request == AU1XXX_PM_WAKEUP) { | ||
1849 | if(dev->prev_state == SLEEP_STATE) | ||
1850 | { | ||
1851 | int plane; | ||
1852 | au1200_setpanel(panel); | ||
1853 | for (plane = 0; plane < CONFIG_FB_AU1200_DEVS; ++plane) { | ||
1854 | struct au1200fb_device *fbdev; | ||
1855 | fbdev = &_au1200fb_devices[plane]; | ||
1856 | au1200fb_fb_set_par(&fbdev->fb_info); | ||
1857 | } | 1850 | } |
1858 | } | ||
1859 | 1851 | ||
1860 | d = *((unsigned int*)data); | 1852 | else if (strncmp(this_opt, "off", 3) == 0) |
1861 | if(d <=10) brightness = 26; | 1853 | return 1; |
1862 | else if(d<=20) brightness = 51; | 1854 | /* Unsupported option */ |
1863 | else if(d<=30) brightness = 77; | 1855 | else { |
1864 | else if(d<=40) brightness = 102; | 1856 | print_warn("Unsupported option \"%s\"", this_opt); |
1865 | else if(d<=50) brightness = 128; | 1857 | } |
1866 | else if(d<=60) brightness = 153; | ||
1867 | else if(d<=70) brightness = 179; | ||
1868 | else if(d<=80) brightness = 204; | ||
1869 | else if(d<=90) brightness = 230; | ||
1870 | else brightness = 255; | ||
1871 | set_brightness(brightness); | ||
1872 | } else if (request == AU1XXX_PM_GETSTATUS) { | ||
1873 | return dev->cur_state; | ||
1874 | } else if (request == AU1XXX_PM_ACCESS) { | ||
1875 | if (dev->cur_state != SLEEP_STATE) | ||
1876 | return retval; | ||
1877 | else { | ||
1878 | au1200_setpanel(panel); | ||
1879 | } | 1858 | } |
1880 | } else if (request == AU1XXX_PM_IDLE) { | ||
1881 | } else if (request == AU1XXX_PM_CLEANUP) { | ||
1882 | } | 1859 | } |
1883 | 1860 | return 0; | |
1884 | return retval; | ||
1885 | } | 1861 | } |
1886 | #endif | ||
1887 | 1862 | ||
1888 | static int __init au1200fb_init(void) | 1863 | static int __init au1200fb_init(void) |
1889 | { | 1864 | { |
1890 | print_info("" DRIVER_DESC ""); | 1865 | print_info("" DRIVER_DESC ""); |
1891 | 1866 | ||
1892 | /* Setup driver with options */ | 1867 | /* Setup driver with options */ |
1893 | au1200fb_setup(); | 1868 | if (au1200fb_setup()) |
1869 | return -ENODEV; | ||
1894 | 1870 | ||
1895 | /* Point to the panel selected */ | 1871 | /* Point to the panel selected */ |
1896 | panel = &known_lcd_panels[panel_index]; | 1872 | panel = &known_lcd_panels[panel_index]; |
@@ -1899,17 +1875,6 @@ static int __init au1200fb_init(void) | |||
1899 | printk(DRIVER_NAME ": Panel %d %s\n", panel_index, panel->name); | 1875 | printk(DRIVER_NAME ": Panel %d %s\n", panel_index, panel->name); |
1900 | printk(DRIVER_NAME ": Win %d %s\n", window_index, win->name); | 1876 | printk(DRIVER_NAME ": Win %d %s\n", window_index, win->name); |
1901 | 1877 | ||
1902 | /* Kickstart the panel, the framebuffers/windows come soon enough */ | ||
1903 | au1200_setpanel(panel); | ||
1904 | |||
1905 | #ifdef CONFIG_PM | ||
1906 | LCD_pm_dev = new_au1xxx_power_device("LCD", &au1200fb_pm_callback, NULL); | ||
1907 | if ( LCD_pm_dev == NULL) | ||
1908 | printk(KERN_INFO "Unable to create a power management device entry for the au1200fb.\n"); | ||
1909 | else | ||
1910 | printk(KERN_INFO "Power management device entry for the au1200fb loaded.\n"); | ||
1911 | #endif | ||
1912 | |||
1913 | return platform_driver_register(&au1200fb_driver); | 1878 | return platform_driver_register(&au1200fb_driver); |
1914 | } | 1879 | } |
1915 | 1880 | ||
diff --git a/drivers/video/backlight/adp8860_bl.c b/drivers/video/backlight/adp8860_bl.c index 183b6f639852..66bc74d9ce2a 100644 --- a/drivers/video/backlight/adp8860_bl.c +++ b/drivers/video/backlight/adp8860_bl.c | |||
@@ -7,7 +7,6 @@ | |||
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include <linux/module.h> | 9 | #include <linux/module.h> |
10 | #include <linux/version.h> | ||
11 | #include <linux/init.h> | 10 | #include <linux/init.h> |
12 | #include <linux/errno.h> | 11 | #include <linux/errno.h> |
13 | #include <linux/pm.h> | 12 | #include <linux/pm.h> |
diff --git a/drivers/video/backlight/adp8870_bl.c b/drivers/video/backlight/adp8870_bl.c index d06886a2bfb5..98e0304deeaf 100644 --- a/drivers/video/backlight/adp8870_bl.c +++ b/drivers/video/backlight/adp8870_bl.c | |||
@@ -7,7 +7,6 @@ | |||
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include <linux/module.h> | 9 | #include <linux/module.h> |
10 | #include <linux/version.h> | ||
11 | #include <linux/init.h> | 10 | #include <linux/init.h> |
12 | #include <linux/errno.h> | 11 | #include <linux/errno.h> |
13 | #include <linux/pm.h> | 12 | #include <linux/pm.h> |
diff --git a/drivers/video/bf54x-lq043fb.c b/drivers/video/bf54x-lq043fb.c index 2464b910b590..56720fb476b3 100644 --- a/drivers/video/bf54x-lq043fb.c +++ b/drivers/video/bf54x-lq043fb.c | |||
@@ -633,7 +633,7 @@ static int __devinit bfin_bf54x_probe(struct platform_device *pdev) | |||
633 | goto out7; | 633 | goto out7; |
634 | } | 634 | } |
635 | 635 | ||
636 | if (request_irq(info->irq, bfin_bf54x_irq_error, IRQF_DISABLED, | 636 | if (request_irq(info->irq, bfin_bf54x_irq_error, 0, |
637 | "PPI ERROR", info) < 0) { | 637 | "PPI ERROR", info) < 0) { |
638 | printk(KERN_ERR DRIVER_NAME | 638 | printk(KERN_ERR DRIVER_NAME |
639 | ": unable to request PPI ERROR IRQ\n"); | 639 | ": unable to request PPI ERROR IRQ\n"); |
diff --git a/drivers/video/bfin-lq035q1-fb.c b/drivers/video/bfin-lq035q1-fb.c index 23b6c4b62c78..c633068372c9 100644 --- a/drivers/video/bfin-lq035q1-fb.c +++ b/drivers/video/bfin-lq035q1-fb.c | |||
@@ -695,7 +695,7 @@ static int __devinit bfin_lq035q1_probe(struct platform_device *pdev) | |||
695 | goto out7; | 695 | goto out7; |
696 | } | 696 | } |
697 | 697 | ||
698 | ret = request_irq(info->irq, bfin_lq035q1_irq_error, IRQF_DISABLED, | 698 | ret = request_irq(info->irq, bfin_lq035q1_irq_error, 0, |
699 | DRIVER_NAME" PPI ERROR", info); | 699 | DRIVER_NAME" PPI ERROR", info); |
700 | if (ret < 0) { | 700 | if (ret < 0) { |
701 | dev_err(&pdev->dev, "unable to request PPI ERROR IRQ\n"); | 701 | dev_err(&pdev->dev, "unable to request PPI ERROR IRQ\n"); |
diff --git a/drivers/video/bfin-t350mcqb-fb.c b/drivers/video/bfin-t350mcqb-fb.c index d8de29f0dd8d..d5e126759612 100644 --- a/drivers/video/bfin-t350mcqb-fb.c +++ b/drivers/video/bfin-t350mcqb-fb.c | |||
@@ -529,7 +529,7 @@ static int __devinit bfin_t350mcqb_probe(struct platform_device *pdev) | |||
529 | goto out7; | 529 | goto out7; |
530 | } | 530 | } |
531 | 531 | ||
532 | ret = request_irq(info->irq, bfin_t350mcqb_irq_error, IRQF_DISABLED, | 532 | ret = request_irq(info->irq, bfin_t350mcqb_irq_error, 0, |
533 | "PPI ERROR", info); | 533 | "PPI ERROR", info); |
534 | if (ret < 0) { | 534 | if (ret < 0) { |
535 | printk(KERN_ERR DRIVER_NAME | 535 | printk(KERN_ERR DRIVER_NAME |
diff --git a/drivers/video/bfin_adv7393fb.c b/drivers/video/bfin_adv7393fb.c index 8486f541156b..811dd7f6aa41 100644 --- a/drivers/video/bfin_adv7393fb.c +++ b/drivers/video/bfin_adv7393fb.c | |||
@@ -481,7 +481,7 @@ static int __devinit bfin_adv7393_fb_probe(struct i2c_client *client, | |||
481 | goto out_4; | 481 | goto out_4; |
482 | } | 482 | } |
483 | 483 | ||
484 | if (request_irq(IRQ_PPI_ERROR, ppi_irq_error, IRQF_DISABLED, | 484 | if (request_irq(IRQ_PPI_ERROR, ppi_irq_error, 0, |
485 | "PPI ERROR", fbdev) < 0) { | 485 | "PPI ERROR", fbdev) < 0) { |
486 | dev_err(&client->dev, "unable to request PPI ERROR IRQ\n"); | 486 | dev_err(&client->dev, "unable to request PPI ERROR IRQ\n"); |
487 | ret = -EFAULT; | 487 | ret = -EFAULT; |
diff --git a/drivers/video/carminefb.c b/drivers/video/carminefb.c index caaa27d4a46a..cb09aa1fa138 100644 --- a/drivers/video/carminefb.c +++ b/drivers/video/carminefb.c | |||
@@ -32,11 +32,11 @@ | |||
32 | #define CARMINEFB_DEFAULT_VIDEO_MODE 1 | 32 | #define CARMINEFB_DEFAULT_VIDEO_MODE 1 |
33 | 33 | ||
34 | static unsigned int fb_mode = CARMINEFB_DEFAULT_VIDEO_MODE; | 34 | static unsigned int fb_mode = CARMINEFB_DEFAULT_VIDEO_MODE; |
35 | module_param(fb_mode, uint, 444); | 35 | module_param(fb_mode, uint, 0444); |
36 | MODULE_PARM_DESC(fb_mode, "Initial video mode as integer."); | 36 | MODULE_PARM_DESC(fb_mode, "Initial video mode as integer."); |
37 | 37 | ||
38 | static char *fb_mode_str; | 38 | static char *fb_mode_str; |
39 | module_param(fb_mode_str, charp, 444); | 39 | module_param(fb_mode_str, charp, 0444); |
40 | MODULE_PARM_DESC(fb_mode_str, "Initial video mode in characters."); | 40 | MODULE_PARM_DESC(fb_mode_str, "Initial video mode in characters."); |
41 | 41 | ||
42 | /* | 42 | /* |
@@ -46,7 +46,7 @@ MODULE_PARM_DESC(fb_mode_str, "Initial video mode in characters."); | |||
46 | * 0b010 Display 1 | 46 | * 0b010 Display 1 |
47 | */ | 47 | */ |
48 | static int fb_displays = CARMINE_USE_DISPLAY0 | CARMINE_USE_DISPLAY1; | 48 | static int fb_displays = CARMINE_USE_DISPLAY0 | CARMINE_USE_DISPLAY1; |
49 | module_param(fb_displays, int, 444); | 49 | module_param(fb_displays, int, 0444); |
50 | MODULE_PARM_DESC(fb_displays, "Bit mode, which displays are used"); | 50 | MODULE_PARM_DESC(fb_displays, "Bit mode, which displays are used"); |
51 | 51 | ||
52 | struct carmine_hw { | 52 | struct carmine_hw { |
diff --git a/drivers/video/controlfb.c b/drivers/video/controlfb.c index 9075bea55879..7b2c40abae15 100644 --- a/drivers/video/controlfb.c +++ b/drivers/video/controlfb.c | |||
@@ -550,7 +550,7 @@ static void control_set_hardware(struct fb_info_control *p, struct fb_par_contro | |||
550 | 550 | ||
551 | 551 | ||
552 | /* | 552 | /* |
553 | * Parse user speficied options (`video=controlfb:') | 553 | * Parse user specified options (`video=controlfb:') |
554 | */ | 554 | */ |
555 | static void __init control_setup(char *options) | 555 | static void __init control_setup(char *options) |
556 | { | 556 | { |
diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c index fcdac872522d..55f91d9ab00b 100644 --- a/drivers/video/da8xx-fb.c +++ b/drivers/video/da8xx-fb.c | |||
@@ -35,6 +35,9 @@ | |||
35 | 35 | ||
36 | #define DRIVER_NAME "da8xx_lcdc" | 36 | #define DRIVER_NAME "da8xx_lcdc" |
37 | 37 | ||
38 | #define LCD_VERSION_1 1 | ||
39 | #define LCD_VERSION_2 2 | ||
40 | |||
38 | /* LCD Status Register */ | 41 | /* LCD Status Register */ |
39 | #define LCD_END_OF_FRAME1 BIT(9) | 42 | #define LCD_END_OF_FRAME1 BIT(9) |
40 | #define LCD_END_OF_FRAME0 BIT(8) | 43 | #define LCD_END_OF_FRAME0 BIT(8) |
@@ -49,7 +52,9 @@ | |||
49 | #define LCD_DMA_BURST_4 0x2 | 52 | #define LCD_DMA_BURST_4 0x2 |
50 | #define LCD_DMA_BURST_8 0x3 | 53 | #define LCD_DMA_BURST_8 0x3 |
51 | #define LCD_DMA_BURST_16 0x4 | 54 | #define LCD_DMA_BURST_16 0x4 |
52 | #define LCD_END_OF_FRAME_INT_ENA BIT(2) | 55 | #define LCD_V1_END_OF_FRAME_INT_ENA BIT(2) |
56 | #define LCD_V2_END_OF_FRAME0_INT_ENA BIT(8) | ||
57 | #define LCD_V2_END_OF_FRAME1_INT_ENA BIT(9) | ||
53 | #define LCD_DUAL_FRAME_BUFFER_ENABLE BIT(0) | 58 | #define LCD_DUAL_FRAME_BUFFER_ENABLE BIT(0) |
54 | 59 | ||
55 | /* LCD Control Register */ | 60 | /* LCD Control Register */ |
@@ -65,12 +70,18 @@ | |||
65 | #define LCD_MONO_8BIT_MODE BIT(9) | 70 | #define LCD_MONO_8BIT_MODE BIT(9) |
66 | #define LCD_RASTER_ORDER BIT(8) | 71 | #define LCD_RASTER_ORDER BIT(8) |
67 | #define LCD_TFT_MODE BIT(7) | 72 | #define LCD_TFT_MODE BIT(7) |
68 | #define LCD_UNDERFLOW_INT_ENA BIT(6) | 73 | #define LCD_V1_UNDERFLOW_INT_ENA BIT(6) |
69 | #define LCD_PL_ENABLE BIT(4) | 74 | #define LCD_V2_UNDERFLOW_INT_ENA BIT(5) |
75 | #define LCD_V1_PL_INT_ENA BIT(4) | ||
76 | #define LCD_V2_PL_INT_ENA BIT(6) | ||
70 | #define LCD_MONOCHROME_MODE BIT(1) | 77 | #define LCD_MONOCHROME_MODE BIT(1) |
71 | #define LCD_RASTER_ENABLE BIT(0) | 78 | #define LCD_RASTER_ENABLE BIT(0) |
72 | #define LCD_TFT_ALT_ENABLE BIT(23) | 79 | #define LCD_TFT_ALT_ENABLE BIT(23) |
73 | #define LCD_STN_565_ENABLE BIT(24) | 80 | #define LCD_STN_565_ENABLE BIT(24) |
81 | #define LCD_V2_DMA_CLK_EN BIT(2) | ||
82 | #define LCD_V2_LIDD_CLK_EN BIT(1) | ||
83 | #define LCD_V2_CORE_CLK_EN BIT(0) | ||
84 | #define LCD_V2_LPP_B10 26 | ||
74 | 85 | ||
75 | /* LCD Raster Timing 2 Register */ | 86 | /* LCD Raster Timing 2 Register */ |
76 | #define LCD_AC_BIAS_TRANSITIONS_PER_INT(x) ((x) << 16) | 87 | #define LCD_AC_BIAS_TRANSITIONS_PER_INT(x) ((x) << 16) |
@@ -82,6 +93,7 @@ | |||
82 | #define LCD_INVERT_FRAME_CLOCK BIT(20) | 93 | #define LCD_INVERT_FRAME_CLOCK BIT(20) |
83 | 94 | ||
84 | /* LCD Block */ | 95 | /* LCD Block */ |
96 | #define LCD_PID_REG 0x0 | ||
85 | #define LCD_CTRL_REG 0x4 | 97 | #define LCD_CTRL_REG 0x4 |
86 | #define LCD_STAT_REG 0x8 | 98 | #define LCD_STAT_REG 0x8 |
87 | #define LCD_RASTER_CTRL_REG 0x28 | 99 | #define LCD_RASTER_CTRL_REG 0x28 |
@@ -94,6 +106,17 @@ | |||
94 | #define LCD_DMA_FRM_BUF_BASE_ADDR_1_REG 0x4C | 106 | #define LCD_DMA_FRM_BUF_BASE_ADDR_1_REG 0x4C |
95 | #define LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG 0x50 | 107 | #define LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG 0x50 |
96 | 108 | ||
109 | /* Interrupt Registers available only in Version 2 */ | ||
110 | #define LCD_RAW_STAT_REG 0x58 | ||
111 | #define LCD_MASKED_STAT_REG 0x5c | ||
112 | #define LCD_INT_ENABLE_SET_REG 0x60 | ||
113 | #define LCD_INT_ENABLE_CLR_REG 0x64 | ||
114 | #define LCD_END_OF_INT_IND_REG 0x68 | ||
115 | |||
116 | /* Clock registers available only on Version 2 */ | ||
117 | #define LCD_CLK_ENABLE_REG 0x6c | ||
118 | #define LCD_CLK_RESET_REG 0x70 | ||
119 | |||
97 | #define LCD_NUM_BUFFERS 2 | 120 | #define LCD_NUM_BUFFERS 2 |
98 | 121 | ||
99 | #define WSI_TIMEOUT 50 | 122 | #define WSI_TIMEOUT 50 |
@@ -105,6 +128,8 @@ | |||
105 | 128 | ||
106 | static resource_size_t da8xx_fb_reg_base; | 129 | static resource_size_t da8xx_fb_reg_base; |
107 | static struct resource *lcdc_regs; | 130 | static struct resource *lcdc_regs; |
131 | static unsigned int lcd_revision; | ||
132 | static irq_handler_t lcdc_irq_handler; | ||
108 | 133 | ||
109 | static inline unsigned int lcdc_read(unsigned int addr) | 134 | static inline unsigned int lcdc_read(unsigned int addr) |
110 | { | 135 | { |
@@ -240,6 +265,7 @@ static void lcd_blit(int load_mode, struct da8xx_fb_par *par) | |||
240 | u32 end; | 265 | u32 end; |
241 | u32 reg_ras; | 266 | u32 reg_ras; |
242 | u32 reg_dma; | 267 | u32 reg_dma; |
268 | u32 reg_int; | ||
243 | 269 | ||
244 | /* init reg to clear PLM (loading mode) fields */ | 270 | /* init reg to clear PLM (loading mode) fields */ |
245 | reg_ras = lcdc_read(LCD_RASTER_CTRL_REG); | 271 | reg_ras = lcdc_read(LCD_RASTER_CTRL_REG); |
@@ -252,7 +278,14 @@ static void lcd_blit(int load_mode, struct da8xx_fb_par *par) | |||
252 | end = par->dma_end; | 278 | end = par->dma_end; |
253 | 279 | ||
254 | reg_ras |= LCD_PALETTE_LOAD_MODE(DATA_ONLY); | 280 | reg_ras |= LCD_PALETTE_LOAD_MODE(DATA_ONLY); |
255 | reg_dma |= LCD_END_OF_FRAME_INT_ENA; | 281 | if (lcd_revision == LCD_VERSION_1) { |
282 | reg_dma |= LCD_V1_END_OF_FRAME_INT_ENA; | ||
283 | } else { | ||
284 | reg_int = lcdc_read(LCD_INT_ENABLE_SET_REG) | | ||
285 | LCD_V2_END_OF_FRAME0_INT_ENA | | ||
286 | LCD_V2_END_OF_FRAME1_INT_ENA; | ||
287 | lcdc_write(reg_int, LCD_INT_ENABLE_SET_REG); | ||
288 | } | ||
256 | reg_dma |= LCD_DUAL_FRAME_BUFFER_ENABLE; | 289 | reg_dma |= LCD_DUAL_FRAME_BUFFER_ENABLE; |
257 | 290 | ||
258 | lcdc_write(start, LCD_DMA_FRM_BUF_BASE_ADDR_0_REG); | 291 | lcdc_write(start, LCD_DMA_FRM_BUF_BASE_ADDR_0_REG); |
@@ -264,7 +297,14 @@ static void lcd_blit(int load_mode, struct da8xx_fb_par *par) | |||
264 | end = start + par->palette_sz - 1; | 297 | end = start + par->palette_sz - 1; |
265 | 298 | ||
266 | reg_ras |= LCD_PALETTE_LOAD_MODE(PALETTE_ONLY); | 299 | reg_ras |= LCD_PALETTE_LOAD_MODE(PALETTE_ONLY); |
267 | reg_ras |= LCD_PL_ENABLE; | 300 | |
301 | if (lcd_revision == LCD_VERSION_1) { | ||
302 | reg_ras |= LCD_V1_PL_INT_ENA; | ||
303 | } else { | ||
304 | reg_int = lcdc_read(LCD_INT_ENABLE_SET_REG) | | ||
305 | LCD_V2_PL_INT_ENA; | ||
306 | lcdc_write(reg_int, LCD_INT_ENABLE_SET_REG); | ||
307 | } | ||
268 | 308 | ||
269 | lcdc_write(start, LCD_DMA_FRM_BUF_BASE_ADDR_0_REG); | 309 | lcdc_write(start, LCD_DMA_FRM_BUF_BASE_ADDR_0_REG); |
270 | lcdc_write(end, LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG); | 310 | lcdc_write(end, LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG); |
@@ -348,6 +388,7 @@ static void lcd_cfg_vertical_sync(int back_porch, int pulse_width, | |||
348 | static int lcd_cfg_display(const struct lcd_ctrl_config *cfg) | 388 | static int lcd_cfg_display(const struct lcd_ctrl_config *cfg) |
349 | { | 389 | { |
350 | u32 reg; | 390 | u32 reg; |
391 | u32 reg_int; | ||
351 | 392 | ||
352 | reg = lcdc_read(LCD_RASTER_CTRL_REG) & ~(LCD_TFT_MODE | | 393 | reg = lcdc_read(LCD_RASTER_CTRL_REG) & ~(LCD_TFT_MODE | |
353 | LCD_MONO_8BIT_MODE | | 394 | LCD_MONO_8BIT_MODE | |
@@ -375,7 +416,13 @@ static int lcd_cfg_display(const struct lcd_ctrl_config *cfg) | |||
375 | } | 416 | } |
376 | 417 | ||
377 | /* enable additional interrupts here */ | 418 | /* enable additional interrupts here */ |
378 | reg |= LCD_UNDERFLOW_INT_ENA; | 419 | if (lcd_revision == LCD_VERSION_1) { |
420 | reg |= LCD_V1_UNDERFLOW_INT_ENA; | ||
421 | } else { | ||
422 | reg_int = lcdc_read(LCD_INT_ENABLE_SET_REG) | | ||
423 | LCD_V2_UNDERFLOW_INT_ENA; | ||
424 | lcdc_write(reg_int, LCD_INT_ENABLE_SET_REG); | ||
425 | } | ||
379 | 426 | ||
380 | lcdc_write(reg, LCD_RASTER_CTRL_REG); | 427 | lcdc_write(reg, LCD_RASTER_CTRL_REG); |
381 | 428 | ||
@@ -413,18 +460,43 @@ static int lcd_cfg_frame_buffer(struct da8xx_fb_par *par, u32 width, u32 height, | |||
413 | 460 | ||
414 | /* Set the Panel Width */ | 461 | /* Set the Panel Width */ |
415 | /* Pixels per line = (PPL + 1)*16 */ | 462 | /* Pixels per line = (PPL + 1)*16 */ |
416 | /*0x3F in bits 4..9 gives max horisontal resolution = 1024 pixels*/ | 463 | if (lcd_revision == LCD_VERSION_1) { |
417 | width &= 0x3f0; | 464 | /* |
465 | * 0x3F in bits 4..9 gives max horizontal resolution = 1024 | ||
466 | * pixels. | ||
467 | */ | ||
468 | width &= 0x3f0; | ||
469 | } else { | ||
470 | /* | ||
471 | * 0x7F in bits 4..10 gives max horizontal resolution = 2048 | ||
472 | * pixels. | ||
473 | */ | ||
474 | width &= 0x7f0; | ||
475 | } | ||
476 | |||
418 | reg = lcdc_read(LCD_RASTER_TIMING_0_REG); | 477 | reg = lcdc_read(LCD_RASTER_TIMING_0_REG); |
419 | reg &= 0xfffffc00; | 478 | reg &= 0xfffffc00; |
420 | reg |= ((width >> 4) - 1) << 4; | 479 | if (lcd_revision == LCD_VERSION_1) { |
480 | reg |= ((width >> 4) - 1) << 4; | ||
481 | } else { | ||
482 | width = (width >> 4) - 1; | ||
483 | reg |= ((width & 0x3f) << 4) | ((width & 0x40) >> 3); | ||
484 | } | ||
421 | lcdc_write(reg, LCD_RASTER_TIMING_0_REG); | 485 | lcdc_write(reg, LCD_RASTER_TIMING_0_REG); |
422 | 486 | ||
423 | /* Set the Panel Height */ | 487 | /* Set the Panel Height */ |
488 | /* Set bits 9:0 of Lines Per Pixel */ | ||
424 | reg = lcdc_read(LCD_RASTER_TIMING_1_REG); | 489 | reg = lcdc_read(LCD_RASTER_TIMING_1_REG); |
425 | reg = ((height - 1) & 0x3ff) | (reg & 0xfffffc00); | 490 | reg = ((height - 1) & 0x3ff) | (reg & 0xfffffc00); |
426 | lcdc_write(reg, LCD_RASTER_TIMING_1_REG); | 491 | lcdc_write(reg, LCD_RASTER_TIMING_1_REG); |
427 | 492 | ||
493 | /* Set bit 10 of Lines Per Pixel */ | ||
494 | if (lcd_revision == LCD_VERSION_2) { | ||
495 | reg = lcdc_read(LCD_RASTER_TIMING_2_REG); | ||
496 | reg |= ((height - 1) & 0x400) << 16; | ||
497 | lcdc_write(reg, LCD_RASTER_TIMING_2_REG); | ||
498 | } | ||
499 | |||
428 | /* Set the Raster Order of the Frame Buffer */ | 500 | /* Set the Raster Order of the Frame Buffer */ |
429 | reg = lcdc_read(LCD_RASTER_CTRL_REG) & ~(1 << 8); | 501 | reg = lcdc_read(LCD_RASTER_CTRL_REG) & ~(1 << 8); |
430 | if (raster_order) | 502 | if (raster_order) |
@@ -511,6 +583,9 @@ static void lcd_reset(struct da8xx_fb_par *par) | |||
511 | /* DMA has to be disabled */ | 583 | /* DMA has to be disabled */ |
512 | lcdc_write(0, LCD_DMA_CTRL_REG); | 584 | lcdc_write(0, LCD_DMA_CTRL_REG); |
513 | lcdc_write(0, LCD_RASTER_CTRL_REG); | 585 | lcdc_write(0, LCD_RASTER_CTRL_REG); |
586 | |||
587 | if (lcd_revision == LCD_VERSION_2) | ||
588 | lcdc_write(0, LCD_INT_ENABLE_SET_REG); | ||
514 | } | 589 | } |
515 | 590 | ||
516 | static void lcd_calc_clk_divider(struct da8xx_fb_par *par) | 591 | static void lcd_calc_clk_divider(struct da8xx_fb_par *par) |
@@ -523,6 +598,11 @@ static void lcd_calc_clk_divider(struct da8xx_fb_par *par) | |||
523 | /* Configure the LCD clock divisor. */ | 598 | /* Configure the LCD clock divisor. */ |
524 | lcdc_write(LCD_CLK_DIVISOR(div) | | 599 | lcdc_write(LCD_CLK_DIVISOR(div) | |
525 | (LCD_RASTER_MODE & 0x1), LCD_CTRL_REG); | 600 | (LCD_RASTER_MODE & 0x1), LCD_CTRL_REG); |
601 | |||
602 | if (lcd_revision == LCD_VERSION_2) | ||
603 | lcdc_write(LCD_V2_DMA_CLK_EN | LCD_V2_LIDD_CLK_EN | | ||
604 | LCD_V2_CORE_CLK_EN, LCD_CLK_ENABLE_REG); | ||
605 | |||
526 | } | 606 | } |
527 | 607 | ||
528 | static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg, | 608 | static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg, |
@@ -583,7 +663,63 @@ static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg, | |||
583 | return 0; | 663 | return 0; |
584 | } | 664 | } |
585 | 665 | ||
586 | static irqreturn_t lcdc_irq_handler(int irq, void *arg) | 666 | /* IRQ handler for version 2 of LCDC */ |
667 | static irqreturn_t lcdc_irq_handler_rev02(int irq, void *arg) | ||
668 | { | ||
669 | struct da8xx_fb_par *par = arg; | ||
670 | u32 stat = lcdc_read(LCD_MASKED_STAT_REG); | ||
671 | u32 reg_int; | ||
672 | |||
673 | if ((stat & LCD_SYNC_LOST) && (stat & LCD_FIFO_UNDERFLOW)) { | ||
674 | lcd_disable_raster(); | ||
675 | lcdc_write(stat, LCD_MASKED_STAT_REG); | ||
676 | lcd_enable_raster(); | ||
677 | } else if (stat & LCD_PL_LOAD_DONE) { | ||
678 | /* | ||
679 | * Must disable raster before changing state of any control bit. | ||
680 | * And also must be disabled before clearing the PL loading | ||
681 | * interrupt via the following write to the status register. If | ||
682 | * this is done after then one gets multiple PL done interrupts. | ||
683 | */ | ||
684 | lcd_disable_raster(); | ||
685 | |||
686 | lcdc_write(stat, LCD_MASKED_STAT_REG); | ||
687 | |||
688 | /* Disable PL completion inerrupt */ | ||
689 | reg_int = lcdc_read(LCD_INT_ENABLE_CLR_REG) | | ||
690 | (LCD_V2_PL_INT_ENA); | ||
691 | lcdc_write(reg_int, LCD_INT_ENABLE_CLR_REG); | ||
692 | |||
693 | /* Setup and start data loading mode */ | ||
694 | lcd_blit(LOAD_DATA, par); | ||
695 | } else { | ||
696 | lcdc_write(stat, LCD_MASKED_STAT_REG); | ||
697 | |||
698 | if (stat & LCD_END_OF_FRAME0) { | ||
699 | lcdc_write(par->dma_start, | ||
700 | LCD_DMA_FRM_BUF_BASE_ADDR_0_REG); | ||
701 | lcdc_write(par->dma_end, | ||
702 | LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG); | ||
703 | par->vsync_flag = 1; | ||
704 | wake_up_interruptible(&par->vsync_wait); | ||
705 | } | ||
706 | |||
707 | if (stat & LCD_END_OF_FRAME1) { | ||
708 | lcdc_write(par->dma_start, | ||
709 | LCD_DMA_FRM_BUF_BASE_ADDR_1_REG); | ||
710 | lcdc_write(par->dma_end, | ||
711 | LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG); | ||
712 | par->vsync_flag = 1; | ||
713 | wake_up_interruptible(&par->vsync_wait); | ||
714 | } | ||
715 | } | ||
716 | |||
717 | lcdc_write(0, LCD_END_OF_INT_IND_REG); | ||
718 | return IRQ_HANDLED; | ||
719 | } | ||
720 | |||
721 | /* IRQ handler for version 1 LCDC */ | ||
722 | static irqreturn_t lcdc_irq_handler_rev01(int irq, void *arg) | ||
587 | { | 723 | { |
588 | struct da8xx_fb_par *par = arg; | 724 | struct da8xx_fb_par *par = arg; |
589 | u32 stat = lcdc_read(LCD_STAT_REG); | 725 | u32 stat = lcdc_read(LCD_STAT_REG); |
@@ -606,7 +742,7 @@ static irqreturn_t lcdc_irq_handler(int irq, void *arg) | |||
606 | 742 | ||
607 | /* Disable PL completion inerrupt */ | 743 | /* Disable PL completion inerrupt */ |
608 | reg_ras = lcdc_read(LCD_RASTER_CTRL_REG); | 744 | reg_ras = lcdc_read(LCD_RASTER_CTRL_REG); |
609 | reg_ras &= ~LCD_PL_ENABLE; | 745 | reg_ras &= ~LCD_V1_PL_INT_ENA; |
610 | lcdc_write(reg_ras, LCD_RASTER_CTRL_REG); | 746 | lcdc_write(reg_ras, LCD_RASTER_CTRL_REG); |
611 | 747 | ||
612 | /* Setup and start data loading mode */ | 748 | /* Setup and start data loading mode */ |
@@ -877,8 +1013,8 @@ static int da8xx_pan_display(struct fb_var_screeninfo *var, | |||
877 | 1013 | ||
878 | start = fix->smem_start + | 1014 | start = fix->smem_start + |
879 | new_var.yoffset * fix->line_length + | 1015 | new_var.yoffset * fix->line_length + |
880 | new_var.xoffset * var->bits_per_pixel / 8; | 1016 | new_var.xoffset * fbi->var.bits_per_pixel / 8; |
881 | end = start + var->yres * fix->line_length - 1; | 1017 | end = start + fbi->var.yres * fix->line_length - 1; |
882 | par->dma_start = start; | 1018 | par->dma_start = start; |
883 | par->dma_end = end; | 1019 | par->dma_end = end; |
884 | } | 1020 | } |
@@ -945,6 +1081,22 @@ static int __devinit fb_probe(struct platform_device *device) | |||
945 | if (ret) | 1081 | if (ret) |
946 | goto err_clk_put; | 1082 | goto err_clk_put; |
947 | 1083 | ||
1084 | /* Determine LCD IP Version */ | ||
1085 | switch (lcdc_read(LCD_PID_REG)) { | ||
1086 | case 0x4C100102: | ||
1087 | lcd_revision = LCD_VERSION_1; | ||
1088 | break; | ||
1089 | case 0x4F200800: | ||
1090 | lcd_revision = LCD_VERSION_2; | ||
1091 | break; | ||
1092 | default: | ||
1093 | dev_warn(&device->dev, "Unknown PID Reg value 0x%x, " | ||
1094 | "defaulting to LCD revision 1\n", | ||
1095 | lcdc_read(LCD_PID_REG)); | ||
1096 | lcd_revision = LCD_VERSION_1; | ||
1097 | break; | ||
1098 | } | ||
1099 | |||
948 | for (i = 0, lcdc_info = known_lcd_panels; | 1100 | for (i = 0, lcdc_info = known_lcd_panels; |
949 | i < ARRAY_SIZE(known_lcd_panels); | 1101 | i < ARRAY_SIZE(known_lcd_panels); |
950 | i++, lcdc_info++) { | 1102 | i++, lcdc_info++) { |
@@ -1085,7 +1237,13 @@ static int __devinit fb_probe(struct platform_device *device) | |||
1085 | } | 1237 | } |
1086 | #endif | 1238 | #endif |
1087 | 1239 | ||
1088 | ret = request_irq(par->irq, lcdc_irq_handler, 0, DRIVER_NAME, par); | 1240 | if (lcd_revision == LCD_VERSION_1) |
1241 | lcdc_irq_handler = lcdc_irq_handler_rev01; | ||
1242 | else | ||
1243 | lcdc_irq_handler = lcdc_irq_handler_rev02; | ||
1244 | |||
1245 | ret = request_irq(par->irq, lcdc_irq_handler, 0, | ||
1246 | DRIVER_NAME, par); | ||
1089 | if (ret) | 1247 | if (ret) |
1090 | goto irq_freq; | 1248 | goto irq_freq; |
1091 | return 0; | 1249 | return 0; |
diff --git a/drivers/video/fb-puv3.c b/drivers/video/fb-puv3.c index 27f2c57e06e9..60a787fa32cf 100644 --- a/drivers/video/fb-puv3.c +++ b/drivers/video/fb-puv3.c | |||
@@ -624,8 +624,8 @@ static int unifb_pan_display(struct fb_var_screeninfo *var, | |||
624 | || var->xoffset) | 624 | || var->xoffset) |
625 | return -EINVAL; | 625 | return -EINVAL; |
626 | } else { | 626 | } else { |
627 | if (var->xoffset + var->xres > info->var.xres_virtual || | 627 | if (var->xoffset + info->var.xres > info->var.xres_virtual || |
628 | var->yoffset + var->yres > info->var.yres_virtual) | 628 | var->yoffset + info->var.yres > info->var.yres_virtual) |
629 | return -EINVAL; | 629 | return -EINVAL; |
630 | } | 630 | } |
631 | info->var.xoffset = var->xoffset; | 631 | info->var.xoffset = var->xoffset; |
diff --git a/drivers/video/fb_defio.c b/drivers/video/fb_defio.c index 32814e8800e0..c27e153d8882 100644 --- a/drivers/video/fb_defio.c +++ b/drivers/video/fb_defio.c | |||
@@ -223,8 +223,7 @@ void fb_deferred_io_cleanup(struct fb_info *info) | |||
223 | int i; | 223 | int i; |
224 | 224 | ||
225 | BUG_ON(!fbdefio); | 225 | BUG_ON(!fbdefio); |
226 | cancel_delayed_work(&info->deferred_work); | 226 | cancel_delayed_work_sync(&info->deferred_work); |
227 | flush_scheduled_work(); | ||
228 | 227 | ||
229 | /* clear out the mapping that we setup */ | 228 | /* clear out the mapping that we setup */ |
230 | for (i = 0 ; i < info->fix.smem_len; i += PAGE_SIZE) { | 229 | for (i = 0 ; i < info->fix.smem_len; i += PAGE_SIZE) { |
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index 5aac00eb1830..ad936295d8f4 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c | |||
@@ -1738,8 +1738,6 @@ void fb_set_suspend(struct fb_info *info, int state) | |||
1738 | { | 1738 | { |
1739 | struct fb_event event; | 1739 | struct fb_event event; |
1740 | 1740 | ||
1741 | if (!lock_fb_info(info)) | ||
1742 | return; | ||
1743 | event.info = info; | 1741 | event.info = info; |
1744 | if (state) { | 1742 | if (state) { |
1745 | fb_notifier_call_chain(FB_EVENT_SUSPEND, &event); | 1743 | fb_notifier_call_chain(FB_EVENT_SUSPEND, &event); |
@@ -1748,7 +1746,6 @@ void fb_set_suspend(struct fb_info *info, int state) | |||
1748 | info->state = FBINFO_STATE_RUNNING; | 1746 | info->state = FBINFO_STATE_RUNNING; |
1749 | fb_notifier_call_chain(FB_EVENT_RESUME, &event); | 1747 | fb_notifier_call_chain(FB_EVENT_RESUME, &event); |
1750 | } | 1748 | } |
1751 | unlock_fb_info(info); | ||
1752 | } | 1749 | } |
1753 | 1750 | ||
1754 | /** | 1751 | /** |
diff --git a/drivers/video/fbmon.c b/drivers/video/fbmon.c index 4f57485f8c54..cef65574db6c 100644 --- a/drivers/video/fbmon.c +++ b/drivers/video/fbmon.c | |||
@@ -493,7 +493,8 @@ static int get_est_timing(unsigned char *block, struct fb_videomode *mode) | |||
493 | return num; | 493 | return num; |
494 | } | 494 | } |
495 | 495 | ||
496 | static int get_std_timing(unsigned char *block, struct fb_videomode *mode) | 496 | static int get_std_timing(unsigned char *block, struct fb_videomode *mode, |
497 | int ver, int rev) | ||
497 | { | 498 | { |
498 | int xres, yres = 0, refresh, ratio, i; | 499 | int xres, yres = 0, refresh, ratio, i; |
499 | 500 | ||
@@ -504,7 +505,11 @@ static int get_std_timing(unsigned char *block, struct fb_videomode *mode) | |||
504 | ratio = (block[1] & 0xc0) >> 6; | 505 | ratio = (block[1] & 0xc0) >> 6; |
505 | switch (ratio) { | 506 | switch (ratio) { |
506 | case 0: | 507 | case 0: |
507 | yres = xres; | 508 | /* in EDID 1.3 the meaning of 0 changed to 16:10 (prior 1:1) */ |
509 | if (ver < 1 || (ver == 1 && rev < 3)) | ||
510 | yres = xres; | ||
511 | else | ||
512 | yres = (xres * 10)/16; | ||
508 | break; | 513 | break; |
509 | case 1: | 514 | case 1: |
510 | yres = (xres * 3)/4; | 515 | yres = (xres * 3)/4; |
@@ -533,12 +538,12 @@ static int get_std_timing(unsigned char *block, struct fb_videomode *mode) | |||
533 | } | 538 | } |
534 | 539 | ||
535 | static int get_dst_timing(unsigned char *block, | 540 | static int get_dst_timing(unsigned char *block, |
536 | struct fb_videomode *mode) | 541 | struct fb_videomode *mode, int ver, int rev) |
537 | { | 542 | { |
538 | int j, num = 0; | 543 | int j, num = 0; |
539 | 544 | ||
540 | for (j = 0; j < 6; j++, block += STD_TIMING_DESCRIPTION_SIZE) | 545 | for (j = 0; j < 6; j++, block += STD_TIMING_DESCRIPTION_SIZE) |
541 | num += get_std_timing(block, &mode[num]); | 546 | num += get_std_timing(block, &mode[num], ver, rev); |
542 | 547 | ||
543 | return num; | 548 | return num; |
544 | } | 549 | } |
@@ -599,6 +604,10 @@ static struct fb_videomode *fb_create_modedb(unsigned char *edid, int *dbsize) | |||
599 | struct fb_videomode *mode, *m; | 604 | struct fb_videomode *mode, *m; |
600 | unsigned char *block; | 605 | unsigned char *block; |
601 | int num = 0, i, first = 1; | 606 | int num = 0, i, first = 1; |
607 | int ver, rev; | ||
608 | |||
609 | ver = edid[EDID_STRUCT_VERSION]; | ||
610 | rev = edid[EDID_STRUCT_REVISION]; | ||
602 | 611 | ||
603 | mode = kzalloc(50 * sizeof(struct fb_videomode), GFP_KERNEL); | 612 | mode = kzalloc(50 * sizeof(struct fb_videomode), GFP_KERNEL); |
604 | if (mode == NULL) | 613 | if (mode == NULL) |
@@ -632,12 +641,12 @@ static struct fb_videomode *fb_create_modedb(unsigned char *edid, int *dbsize) | |||
632 | DPRINTK(" Standard Timings\n"); | 641 | DPRINTK(" Standard Timings\n"); |
633 | block = edid + STD_TIMING_DESCRIPTIONS_START; | 642 | block = edid + STD_TIMING_DESCRIPTIONS_START; |
634 | for (i = 0; i < STD_TIMING; i++, block += STD_TIMING_DESCRIPTION_SIZE) | 643 | for (i = 0; i < STD_TIMING; i++, block += STD_TIMING_DESCRIPTION_SIZE) |
635 | num += get_std_timing(block, &mode[num]); | 644 | num += get_std_timing(block, &mode[num], ver, rev); |
636 | 645 | ||
637 | block = edid + DETAILED_TIMING_DESCRIPTIONS_START; | 646 | block = edid + DETAILED_TIMING_DESCRIPTIONS_START; |
638 | for (i = 0; i < 4; i++, block+= DETAILED_TIMING_DESCRIPTION_SIZE) { | 647 | for (i = 0; i < 4; i++, block+= DETAILED_TIMING_DESCRIPTION_SIZE) { |
639 | if (block[0] == 0x00 && block[1] == 0x00 && block[3] == 0xfa) | 648 | if (block[0] == 0x00 && block[1] == 0x00 && block[3] == 0xfa) |
640 | num += get_dst_timing(block + 5, &mode[num]); | 649 | num += get_dst_timing(block + 5, &mode[num], ver, rev); |
641 | } | 650 | } |
642 | 651 | ||
643 | /* Yikes, EDID data is totally useless */ | 652 | /* Yikes, EDID data is totally useless */ |
diff --git a/drivers/video/fbsysfs.c b/drivers/video/fbsysfs.c index 04251ce89184..67afa9c2289d 100644 --- a/drivers/video/fbsysfs.c +++ b/drivers/video/fbsysfs.c | |||
@@ -399,9 +399,12 @@ static ssize_t store_fbstate(struct device *device, | |||
399 | 399 | ||
400 | state = simple_strtoul(buf, &last, 0); | 400 | state = simple_strtoul(buf, &last, 0); |
401 | 401 | ||
402 | if (!lock_fb_info(fb_info)) | ||
403 | return -ENODEV; | ||
402 | console_lock(); | 404 | console_lock(); |
403 | fb_set_suspend(fb_info, (int)state); | 405 | fb_set_suspend(fb_info, (int)state); |
404 | console_unlock(); | 406 | console_unlock(); |
407 | unlock_fb_info(fb_info); | ||
405 | 408 | ||
406 | return count; | 409 | return count; |
407 | } | 410 | } |
diff --git a/drivers/video/fsl-diu-fb.c b/drivers/video/fsl-diu-fb.c index 0acc7d65aeaa..a16beeb5f548 100644 --- a/drivers/video/fsl-diu-fb.c +++ b/drivers/video/fsl-diu-fb.c | |||
@@ -30,37 +30,40 @@ | |||
30 | #include <linux/clk.h> | 30 | #include <linux/clk.h> |
31 | #include <linux/uaccess.h> | 31 | #include <linux/uaccess.h> |
32 | #include <linux/vmalloc.h> | 32 | #include <linux/vmalloc.h> |
33 | 33 | #include <linux/spinlock.h> | |
34 | #include <linux/of_platform.h> | ||
35 | 34 | ||
36 | #include <sysdev/fsl_soc.h> | 35 | #include <sysdev/fsl_soc.h> |
37 | #include <linux/fsl-diu-fb.h> | 36 | #include <linux/fsl-diu-fb.h> |
38 | #include "edid.h" | 37 | #include "edid.h" |
39 | 38 | ||
40 | /* | 39 | #define FSL_AOI_NUM 6 /* 5 AOIs and one dummy AOI */ |
41 | * These parameters give default parameters | 40 | /* 1 for plane 0, 2 for plane 1&2 each */ |
42 | * for video output 1024x768, | 41 | |
43 | * FIXME - change timing to proper amounts | 42 | /* HW cursor parameters */ |
44 | * hsync 31.5kHz, vsync 60Hz | 43 | #define MAX_CURS 32 |
45 | */ | 44 | |
46 | static struct fb_videomode __devinitdata fsl_diu_default_mode = { | 45 | /* INT_STATUS/INT_MASK field descriptions */ |
47 | .refresh = 60, | 46 | #define INT_VSYNC 0x01 /* Vsync interrupt */ |
48 | .xres = 1024, | 47 | #define INT_VSYNC_WB 0x02 /* Vsync interrupt for write back operation */ |
49 | .yres = 768, | 48 | #define INT_UNDRUN 0x04 /* Under run exception interrupt */ |
50 | .pixclock = 15385, | 49 | #define INT_PARERR 0x08 /* Display parameters error interrupt */ |
51 | .left_margin = 160, | 50 | #define INT_LS_BF_VS 0x10 /* Lines before vsync. interrupt */ |
52 | .right_margin = 24, | 51 | |
53 | .upper_margin = 29, | 52 | struct diu_addr { |
54 | .lower_margin = 3, | 53 | void *vaddr; /* Virtual address */ |
55 | .hsync_len = 136, | 54 | dma_addr_t paddr; /* Physical address */ |
56 | .vsync_len = 6, | 55 | __u32 offset; |
57 | .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, | ||
58 | .vmode = FB_VMODE_NONINTERLACED | ||
59 | }; | 56 | }; |
60 | 57 | ||
58 | /* | ||
59 | * List of supported video modes | ||
60 | * | ||
61 | * The first entry is the default video mode. The remain entries are in | ||
62 | * order if increasing resolution and frequency. The 320x240-60 mode is | ||
63 | * the initial AOI for the second and third planes. | ||
64 | */ | ||
61 | static struct fb_videomode __devinitdata fsl_diu_mode_db[] = { | 65 | static struct fb_videomode __devinitdata fsl_diu_mode_db[] = { |
62 | { | 66 | { |
63 | .name = "1024x768-60", | ||
64 | .refresh = 60, | 67 | .refresh = 60, |
65 | .xres = 1024, | 68 | .xres = 1024, |
66 | .yres = 768, | 69 | .yres = 768, |
@@ -75,7 +78,132 @@ static struct fb_videomode __devinitdata fsl_diu_mode_db[] = { | |||
75 | .vmode = FB_VMODE_NONINTERLACED | 78 | .vmode = FB_VMODE_NONINTERLACED |
76 | }, | 79 | }, |
77 | { | 80 | { |
78 | .name = "1024x768-70", | 81 | .refresh = 60, |
82 | .xres = 320, | ||
83 | .yres = 240, | ||
84 | .pixclock = 79440, | ||
85 | .left_margin = 16, | ||
86 | .right_margin = 16, | ||
87 | .upper_margin = 16, | ||
88 | .lower_margin = 5, | ||
89 | .hsync_len = 48, | ||
90 | .vsync_len = 1, | ||
91 | .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, | ||
92 | .vmode = FB_VMODE_NONINTERLACED | ||
93 | }, | ||
94 | { | ||
95 | .refresh = 60, | ||
96 | .xres = 640, | ||
97 | .yres = 480, | ||
98 | .pixclock = 39722, | ||
99 | .left_margin = 48, | ||
100 | .right_margin = 16, | ||
101 | .upper_margin = 33, | ||
102 | .lower_margin = 10, | ||
103 | .hsync_len = 96, | ||
104 | .vsync_len = 2, | ||
105 | .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, | ||
106 | .vmode = FB_VMODE_NONINTERLACED | ||
107 | }, | ||
108 | { | ||
109 | .refresh = 72, | ||
110 | .xres = 640, | ||
111 | .yres = 480, | ||
112 | .pixclock = 32052, | ||
113 | .left_margin = 128, | ||
114 | .right_margin = 24, | ||
115 | .upper_margin = 28, | ||
116 | .lower_margin = 9, | ||
117 | .hsync_len = 40, | ||
118 | .vsync_len = 3, | ||
119 | .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, | ||
120 | .vmode = FB_VMODE_NONINTERLACED | ||
121 | }, | ||
122 | { | ||
123 | .refresh = 75, | ||
124 | .xres = 640, | ||
125 | .yres = 480, | ||
126 | .pixclock = 31747, | ||
127 | .left_margin = 120, | ||
128 | .right_margin = 16, | ||
129 | .upper_margin = 16, | ||
130 | .lower_margin = 1, | ||
131 | .hsync_len = 64, | ||
132 | .vsync_len = 3, | ||
133 | .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, | ||
134 | .vmode = FB_VMODE_NONINTERLACED | ||
135 | }, | ||
136 | { | ||
137 | .refresh = 90, | ||
138 | .xres = 640, | ||
139 | .yres = 480, | ||
140 | .pixclock = 25057, | ||
141 | .left_margin = 120, | ||
142 | .right_margin = 32, | ||
143 | .upper_margin = 14, | ||
144 | .lower_margin = 25, | ||
145 | .hsync_len = 40, | ||
146 | .vsync_len = 14, | ||
147 | .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, | ||
148 | .vmode = FB_VMODE_NONINTERLACED | ||
149 | }, | ||
150 | { | ||
151 | .refresh = 100, | ||
152 | .xres = 640, | ||
153 | .yres = 480, | ||
154 | .pixclock = 22272, | ||
155 | .left_margin = 48, | ||
156 | .right_margin = 32, | ||
157 | .upper_margin = 17, | ||
158 | .lower_margin = 22, | ||
159 | .hsync_len = 128, | ||
160 | .vsync_len = 12, | ||
161 | .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, | ||
162 | .vmode = FB_VMODE_NONINTERLACED | ||
163 | }, | ||
164 | { | ||
165 | .refresh = 60, | ||
166 | .xres = 800, | ||
167 | .yres = 480, | ||
168 | .pixclock = 33805, | ||
169 | .left_margin = 96, | ||
170 | .right_margin = 24, | ||
171 | .upper_margin = 10, | ||
172 | .lower_margin = 3, | ||
173 | .hsync_len = 72, | ||
174 | .vsync_len = 7, | ||
175 | .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, | ||
176 | .vmode = FB_VMODE_NONINTERLACED | ||
177 | }, | ||
178 | { | ||
179 | .refresh = 60, | ||
180 | .xres = 800, | ||
181 | .yres = 600, | ||
182 | .pixclock = 25000, | ||
183 | .left_margin = 88, | ||
184 | .right_margin = 40, | ||
185 | .upper_margin = 23, | ||
186 | .lower_margin = 1, | ||
187 | .hsync_len = 128, | ||
188 | .vsync_len = 4, | ||
189 | .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, | ||
190 | .vmode = FB_VMODE_NONINTERLACED | ||
191 | }, | ||
192 | { | ||
193 | .refresh = 60, | ||
194 | .xres = 854, | ||
195 | .yres = 480, | ||
196 | .pixclock = 31518, | ||
197 | .left_margin = 104, | ||
198 | .right_margin = 16, | ||
199 | .upper_margin = 13, | ||
200 | .lower_margin = 1, | ||
201 | .hsync_len = 88, | ||
202 | .vsync_len = 3, | ||
203 | .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, | ||
204 | .vmode = FB_VMODE_NONINTERLACED | ||
205 | }, | ||
206 | { | ||
79 | .refresh = 70, | 207 | .refresh = 70, |
80 | .xres = 1024, | 208 | .xres = 1024, |
81 | .yres = 768, | 209 | .yres = 768, |
@@ -90,7 +218,6 @@ static struct fb_videomode __devinitdata fsl_diu_mode_db[] = { | |||
90 | .vmode = FB_VMODE_NONINTERLACED | 218 | .vmode = FB_VMODE_NONINTERLACED |
91 | }, | 219 | }, |
92 | { | 220 | { |
93 | .name = "1024x768-75", | ||
94 | .refresh = 75, | 221 | .refresh = 75, |
95 | .xres = 1024, | 222 | .xres = 1024, |
96 | .yres = 768, | 223 | .yres = 768, |
@@ -105,7 +232,34 @@ static struct fb_videomode __devinitdata fsl_diu_mode_db[] = { | |||
105 | .vmode = FB_VMODE_NONINTERLACED | 232 | .vmode = FB_VMODE_NONINTERLACED |
106 | }, | 233 | }, |
107 | { | 234 | { |
108 | .name = "1280x1024-60", | 235 | .refresh = 60, |
236 | .xres = 1280, | ||
237 | .yres = 480, | ||
238 | .pixclock = 18939, | ||
239 | .left_margin = 353, | ||
240 | .right_margin = 47, | ||
241 | .upper_margin = 39, | ||
242 | .lower_margin = 4, | ||
243 | .hsync_len = 8, | ||
244 | .vsync_len = 2, | ||
245 | .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, | ||
246 | .vmode = FB_VMODE_NONINTERLACED | ||
247 | }, | ||
248 | { | ||
249 | .refresh = 60, | ||
250 | .xres = 1280, | ||
251 | .yres = 720, | ||
252 | .pixclock = 13426, | ||
253 | .left_margin = 192, | ||
254 | .right_margin = 64, | ||
255 | .upper_margin = 22, | ||
256 | .lower_margin = 1, | ||
257 | .hsync_len = 136, | ||
258 | .vsync_len = 3, | ||
259 | .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, | ||
260 | .vmode = FB_VMODE_NONINTERLACED | ||
261 | }, | ||
262 | { | ||
109 | .refresh = 60, | 263 | .refresh = 60, |
110 | .xres = 1280, | 264 | .xres = 1280, |
111 | .yres = 1024, | 265 | .yres = 1024, |
@@ -120,7 +274,6 @@ static struct fb_videomode __devinitdata fsl_diu_mode_db[] = { | |||
120 | .vmode = FB_VMODE_NONINTERLACED | 274 | .vmode = FB_VMODE_NONINTERLACED |
121 | }, | 275 | }, |
122 | { | 276 | { |
123 | .name = "1280x1024-70", | ||
124 | .refresh = 70, | 277 | .refresh = 70, |
125 | .xres = 1280, | 278 | .xres = 1280, |
126 | .yres = 1024, | 279 | .yres = 1024, |
@@ -135,7 +288,6 @@ static struct fb_videomode __devinitdata fsl_diu_mode_db[] = { | |||
135 | .vmode = FB_VMODE_NONINTERLACED | 288 | .vmode = FB_VMODE_NONINTERLACED |
136 | }, | 289 | }, |
137 | { | 290 | { |
138 | .name = "1280x1024-75", | ||
139 | .refresh = 75, | 291 | .refresh = 75, |
140 | .xres = 1280, | 292 | .xres = 1280, |
141 | .yres = 1024, | 293 | .yres = 1024, |
@@ -150,40 +302,25 @@ static struct fb_videomode __devinitdata fsl_diu_mode_db[] = { | |||
150 | .vmode = FB_VMODE_NONINTERLACED | 302 | .vmode = FB_VMODE_NONINTERLACED |
151 | }, | 303 | }, |
152 | { | 304 | { |
153 | .name = "320x240", /* for AOI only */ | ||
154 | .refresh = 60, | 305 | .refresh = 60, |
155 | .xres = 320, | 306 | .xres = 1920, |
156 | .yres = 240, | 307 | .yres = 1080, |
157 | .pixclock = 15385, | 308 | .pixclock = 5787, |
158 | .left_margin = 0, | 309 | .left_margin = 328, |
159 | .right_margin = 0, | 310 | .right_margin = 120, |
160 | .upper_margin = 0, | 311 | .upper_margin = 34, |
161 | .lower_margin = 0, | 312 | .lower_margin = 1, |
162 | .hsync_len = 0, | 313 | .hsync_len = 208, |
163 | .vsync_len = 0, | 314 | .vsync_len = 3, |
164 | .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, | ||
165 | .vmode = FB_VMODE_NONINTERLACED | ||
166 | }, | ||
167 | { | ||
168 | .name = "1280x480-60", | ||
169 | .refresh = 60, | ||
170 | .xres = 1280, | ||
171 | .yres = 480, | ||
172 | .pixclock = 18939, | ||
173 | .left_margin = 353, | ||
174 | .right_margin = 47, | ||
175 | .upper_margin = 39, | ||
176 | .lower_margin = 4, | ||
177 | .hsync_len = 8, | ||
178 | .vsync_len = 2, | ||
179 | .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, | 315 | .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, |
180 | .vmode = FB_VMODE_NONINTERLACED | 316 | .vmode = FB_VMODE_NONINTERLACED |
181 | }, | 317 | }, |
182 | }; | 318 | }; |
183 | 319 | ||
184 | static char *fb_mode = "1024x768-32@60"; | 320 | static char *fb_mode; |
185 | static unsigned long default_bpp = 32; | 321 | static unsigned long default_bpp = 32; |
186 | static int monitor_port; | 322 | static enum fsl_diu_monitor_port monitor_port; |
323 | static char *monitor_string; | ||
187 | 324 | ||
188 | #if defined(CONFIG_NOT_COHERENT_CACHE) | 325 | #if defined(CONFIG_NOT_COHERENT_CACHE) |
189 | static u8 *coherence_data; | 326 | static u8 *coherence_data; |
@@ -201,15 +338,27 @@ struct fsl_diu_data { | |||
201 | void *dummy_aoi_virt; | 338 | void *dummy_aoi_virt; |
202 | unsigned int irq; | 339 | unsigned int irq; |
203 | int fb_enabled; | 340 | int fb_enabled; |
204 | int monitor_port; | 341 | enum fsl_diu_monitor_port monitor_port; |
342 | struct diu __iomem *diu_reg; | ||
343 | spinlock_t reg_lock; | ||
344 | struct diu_addr ad; | ||
345 | struct diu_addr gamma; | ||
346 | struct diu_addr pallete; | ||
347 | struct diu_addr cursor; | ||
348 | }; | ||
349 | |||
350 | enum mfb_index { | ||
351 | PLANE0 = 0, /* Plane 0, only one AOI that fills the screen */ | ||
352 | PLANE1_AOI0, /* Plane 1, first AOI */ | ||
353 | PLANE1_AOI1, /* Plane 1, second AOI */ | ||
354 | PLANE2_AOI0, /* Plane 2, first AOI */ | ||
355 | PLANE2_AOI1, /* Plane 2, second AOI */ | ||
205 | }; | 356 | }; |
206 | 357 | ||
207 | struct mfb_info { | 358 | struct mfb_info { |
208 | int index; | 359 | enum mfb_index index; |
209 | int type; | ||
210 | char *id; | 360 | char *id; |
211 | int registered; | 361 | int registered; |
212 | int blank; | ||
213 | unsigned long pseudo_palette[16]; | 362 | unsigned long pseudo_palette[16]; |
214 | struct diu_ad *ad; | 363 | struct diu_ad *ad; |
215 | int cursor_reset; | 364 | int cursor_reset; |
@@ -223,63 +372,82 @@ struct mfb_info { | |||
223 | 372 | ||
224 | 373 | ||
225 | static struct mfb_info mfb_template[] = { | 374 | static struct mfb_info mfb_template[] = { |
226 | { /* AOI 0 for plane 0 */ | 375 | { |
227 | .index = 0, | 376 | .index = PLANE0, |
228 | .type = MFB_TYPE_OUTPUT, | 377 | .id = "Panel0", |
229 | .id = "Panel0", | 378 | .registered = 0, |
230 | .registered = 0, | 379 | .count = 0, |
231 | .count = 0, | 380 | .x_aoi_d = 0, |
232 | .x_aoi_d = 0, | 381 | .y_aoi_d = 0, |
233 | .y_aoi_d = 0, | ||
234 | }, | 382 | }, |
235 | { /* AOI 0 for plane 1 */ | 383 | { |
236 | .index = 1, | 384 | .index = PLANE1_AOI0, |
237 | .type = MFB_TYPE_OUTPUT, | 385 | .id = "Panel1 AOI0", |
238 | .id = "Panel1 AOI0", | 386 | .registered = 0, |
239 | .registered = 0, | 387 | .g_alpha = 0xff, |
240 | .g_alpha = 0xff, | 388 | .count = 0, |
241 | .count = 0, | 389 | .x_aoi_d = 0, |
242 | .x_aoi_d = 0, | 390 | .y_aoi_d = 0, |
243 | .y_aoi_d = 0, | ||
244 | }, | 391 | }, |
245 | { /* AOI 1 for plane 1 */ | 392 | { |
246 | .index = 2, | 393 | .index = PLANE1_AOI1, |
247 | .type = MFB_TYPE_OUTPUT, | 394 | .id = "Panel1 AOI1", |
248 | .id = "Panel1 AOI1", | 395 | .registered = 0, |
249 | .registered = 0, | 396 | .g_alpha = 0xff, |
250 | .g_alpha = 0xff, | 397 | .count = 0, |
251 | .count = 0, | 398 | .x_aoi_d = 0, |
252 | .x_aoi_d = 0, | 399 | .y_aoi_d = 480, |
253 | .y_aoi_d = 480, | ||
254 | }, | 400 | }, |
255 | { /* AOI 0 for plane 2 */ | 401 | { |
256 | .index = 3, | 402 | .index = PLANE2_AOI0, |
257 | .type = MFB_TYPE_OUTPUT, | 403 | .id = "Panel2 AOI0", |
258 | .id = "Panel2 AOI0", | 404 | .registered = 0, |
259 | .registered = 0, | 405 | .g_alpha = 0xff, |
260 | .g_alpha = 0xff, | 406 | .count = 0, |
261 | .count = 0, | 407 | .x_aoi_d = 640, |
262 | .x_aoi_d = 640, | 408 | .y_aoi_d = 0, |
263 | .y_aoi_d = 0, | ||
264 | }, | 409 | }, |
265 | { /* AOI 1 for plane 2 */ | 410 | { |
266 | .index = 4, | 411 | .index = PLANE2_AOI1, |
267 | .type = MFB_TYPE_OUTPUT, | 412 | .id = "Panel2 AOI1", |
268 | .id = "Panel2 AOI1", | 413 | .registered = 0, |
269 | .registered = 0, | 414 | .g_alpha = 0xff, |
270 | .g_alpha = 0xff, | 415 | .count = 0, |
271 | .count = 0, | 416 | .x_aoi_d = 640, |
272 | .x_aoi_d = 640, | 417 | .y_aoi_d = 480, |
273 | .y_aoi_d = 480, | ||
274 | }, | 418 | }, |
275 | }; | 419 | }; |
276 | 420 | ||
277 | static struct diu_hw dr = { | 421 | /** |
278 | .mode = MFB_MODE1, | 422 | * fsl_diu_name_to_port - convert a port name to a monitor port enum |
279 | .reg_lock = __SPIN_LOCK_UNLOCKED(diu_hw.reg_lock), | 423 | * |
280 | }; | 424 | * Takes the name of a monitor port ("dvi", "lvds", or "dlvds") and returns |
425 | * the enum fsl_diu_monitor_port that corresponds to that string. | ||
426 | * | ||
427 | * For compatibility with older versions, a number ("0", "1", or "2") is also | ||
428 | * supported. | ||
429 | * | ||
430 | * If the string is unknown, DVI is assumed. | ||
431 | * | ||
432 | * If the particular port is not supported by the platform, another port | ||
433 | * (platform-specific) is chosen instead. | ||
434 | */ | ||
435 | static enum fsl_diu_monitor_port fsl_diu_name_to_port(const char *s) | ||
436 | { | ||
437 | enum fsl_diu_monitor_port port = FSL_DIU_PORT_DVI; | ||
438 | unsigned long val; | ||
281 | 439 | ||
282 | static struct diu_pool pool; | 440 | if (s) { |
441 | if (!strict_strtoul(s, 10, &val) && (val <= 2)) | ||
442 | port = (enum fsl_diu_monitor_port) val; | ||
443 | else if (strncmp(s, "lvds", 4) == 0) | ||
444 | port = FSL_DIU_PORT_LVDS; | ||
445 | else if (strncmp(s, "dlvds", 5) == 0) | ||
446 | port = FSL_DIU_PORT_DLVDS; | ||
447 | } | ||
448 | |||
449 | return diu_ops.valid_monitor_port(port); | ||
450 | } | ||
283 | 451 | ||
284 | /** | 452 | /** |
285 | * fsl_diu_alloc - allocate memory for the DIU | 453 | * fsl_diu_alloc - allocate memory for the DIU |
@@ -292,14 +460,9 @@ static void *fsl_diu_alloc(size_t size, phys_addr_t *phys) | |||
292 | { | 460 | { |
293 | void *virt; | 461 | void *virt; |
294 | 462 | ||
295 | pr_debug("size=%zu\n", size); | ||
296 | |||
297 | virt = alloc_pages_exact(size, GFP_DMA | __GFP_ZERO); | 463 | virt = alloc_pages_exact(size, GFP_DMA | __GFP_ZERO); |
298 | if (virt) { | 464 | if (virt) |
299 | *phys = virt_to_phys(virt); | 465 | *phys = virt_to_phys(virt); |
300 | pr_debug("virt=%p phys=%llx\n", virt, | ||
301 | (unsigned long long)*phys); | ||
302 | } | ||
303 | 466 | ||
304 | return virt; | 467 | return virt; |
305 | } | 468 | } |
@@ -313,8 +476,6 @@ static void *fsl_diu_alloc(size_t size, phys_addr_t *phys) | |||
313 | */ | 476 | */ |
314 | static void fsl_diu_free(void *virt, size_t size) | 477 | static void fsl_diu_free(void *virt, size_t size) |
315 | { | 478 | { |
316 | pr_debug("virt=%p size=%zu\n", virt, size); | ||
317 | |||
318 | if (virt && size) | 479 | if (virt && size) |
319 | free_pages_exact(virt, size); | 480 | free_pages_exact(virt, size); |
320 | } | 481 | } |
@@ -330,82 +491,72 @@ void wr_reg_wa(u32 *reg, u32 val) | |||
330 | } while (in_be32(reg) != val); | 491 | } while (in_be32(reg) != val); |
331 | } | 492 | } |
332 | 493 | ||
333 | static int fsl_diu_enable_panel(struct fb_info *info) | 494 | static void fsl_diu_enable_panel(struct fb_info *info) |
334 | { | 495 | { |
335 | struct mfb_info *pmfbi, *cmfbi, *mfbi = info->par; | 496 | struct mfb_info *pmfbi, *cmfbi, *mfbi = info->par; |
336 | struct diu *hw = dr.diu_reg; | ||
337 | struct diu_ad *ad = mfbi->ad; | 497 | struct diu_ad *ad = mfbi->ad; |
338 | struct fsl_diu_data *machine_data = mfbi->parent; | 498 | struct fsl_diu_data *machine_data = mfbi->parent; |
339 | int res = 0; | 499 | struct diu __iomem *hw = machine_data->diu_reg; |
340 | 500 | ||
341 | pr_debug("enable_panel index %d\n", mfbi->index); | 501 | switch (mfbi->index) { |
342 | if (mfbi->type != MFB_TYPE_OFF) { | 502 | case PLANE0: |
343 | switch (mfbi->index) { | 503 | if (hw->desc[0] != ad->paddr) |
344 | case 0: /* plane 0 */ | 504 | wr_reg_wa(&hw->desc[0], ad->paddr); |
345 | if (hw->desc[0] != ad->paddr) | 505 | break; |
346 | wr_reg_wa(&hw->desc[0], ad->paddr); | 506 | case PLANE1_AOI0: |
347 | break; | 507 | cmfbi = machine_data->fsl_diu_info[2]->par; |
348 | case 1: /* plane 1 AOI 0 */ | 508 | if (hw->desc[1] != ad->paddr) { /* AOI0 closed */ |
349 | cmfbi = machine_data->fsl_diu_info[2]->par; | 509 | if (cmfbi->count > 0) /* AOI1 open */ |
350 | if (hw->desc[1] != ad->paddr) { /* AOI0 closed */ | 510 | ad->next_ad = |
351 | if (cmfbi->count > 0) /* AOI1 open */ | 511 | cpu_to_le32(cmfbi->ad->paddr); |
352 | ad->next_ad = | 512 | else |
353 | cpu_to_le32(cmfbi->ad->paddr); | 513 | ad->next_ad = 0; |
354 | else | 514 | wr_reg_wa(&hw->desc[1], ad->paddr); |
355 | ad->next_ad = 0; | ||
356 | wr_reg_wa(&hw->desc[1], ad->paddr); | ||
357 | } | ||
358 | break; | ||
359 | case 3: /* plane 2 AOI 0 */ | ||
360 | cmfbi = machine_data->fsl_diu_info[4]->par; | ||
361 | if (hw->desc[2] != ad->paddr) { /* AOI0 closed */ | ||
362 | if (cmfbi->count > 0) /* AOI1 open */ | ||
363 | ad->next_ad = | ||
364 | cpu_to_le32(cmfbi->ad->paddr); | ||
365 | else | ||
366 | ad->next_ad = 0; | ||
367 | wr_reg_wa(&hw->desc[2], ad->paddr); | ||
368 | } | ||
369 | break; | ||
370 | case 2: /* plane 1 AOI 1 */ | ||
371 | pmfbi = machine_data->fsl_diu_info[1]->par; | ||
372 | ad->next_ad = 0; | ||
373 | if (hw->desc[1] == machine_data->dummy_ad->paddr) | ||
374 | wr_reg_wa(&hw->desc[1], ad->paddr); | ||
375 | else /* AOI0 open */ | ||
376 | pmfbi->ad->next_ad = cpu_to_le32(ad->paddr); | ||
377 | break; | ||
378 | case 4: /* plane 2 AOI 1 */ | ||
379 | pmfbi = machine_data->fsl_diu_info[3]->par; | ||
380 | ad->next_ad = 0; | ||
381 | if (hw->desc[2] == machine_data->dummy_ad->paddr) | ||
382 | wr_reg_wa(&hw->desc[2], ad->paddr); | ||
383 | else /* AOI0 was open */ | ||
384 | pmfbi->ad->next_ad = cpu_to_le32(ad->paddr); | ||
385 | break; | ||
386 | default: | ||
387 | res = -EINVAL; | ||
388 | break; | ||
389 | } | 515 | } |
390 | } else | 516 | break; |
391 | res = -EINVAL; | 517 | case PLANE2_AOI0: |
392 | return res; | 518 | cmfbi = machine_data->fsl_diu_info[4]->par; |
519 | if (hw->desc[2] != ad->paddr) { /* AOI0 closed */ | ||
520 | if (cmfbi->count > 0) /* AOI1 open */ | ||
521 | ad->next_ad = | ||
522 | cpu_to_le32(cmfbi->ad->paddr); | ||
523 | else | ||
524 | ad->next_ad = 0; | ||
525 | wr_reg_wa(&hw->desc[2], ad->paddr); | ||
526 | } | ||
527 | break; | ||
528 | case PLANE1_AOI1: | ||
529 | pmfbi = machine_data->fsl_diu_info[1]->par; | ||
530 | ad->next_ad = 0; | ||
531 | if (hw->desc[1] == machine_data->dummy_ad->paddr) | ||
532 | wr_reg_wa(&hw->desc[1], ad->paddr); | ||
533 | else /* AOI0 open */ | ||
534 | pmfbi->ad->next_ad = cpu_to_le32(ad->paddr); | ||
535 | break; | ||
536 | case PLANE2_AOI1: | ||
537 | pmfbi = machine_data->fsl_diu_info[3]->par; | ||
538 | ad->next_ad = 0; | ||
539 | if (hw->desc[2] == machine_data->dummy_ad->paddr) | ||
540 | wr_reg_wa(&hw->desc[2], ad->paddr); | ||
541 | else /* AOI0 was open */ | ||
542 | pmfbi->ad->next_ad = cpu_to_le32(ad->paddr); | ||
543 | break; | ||
544 | } | ||
393 | } | 545 | } |
394 | 546 | ||
395 | static int fsl_diu_disable_panel(struct fb_info *info) | 547 | static void fsl_diu_disable_panel(struct fb_info *info) |
396 | { | 548 | { |
397 | struct mfb_info *pmfbi, *cmfbi, *mfbi = info->par; | 549 | struct mfb_info *pmfbi, *cmfbi, *mfbi = info->par; |
398 | struct diu *hw = dr.diu_reg; | ||
399 | struct diu_ad *ad = mfbi->ad; | 550 | struct diu_ad *ad = mfbi->ad; |
400 | struct fsl_diu_data *machine_data = mfbi->parent; | 551 | struct fsl_diu_data *machine_data = mfbi->parent; |
401 | int res = 0; | 552 | struct diu __iomem *hw = machine_data->diu_reg; |
402 | 553 | ||
403 | switch (mfbi->index) { | 554 | switch (mfbi->index) { |
404 | case 0: /* plane 0 */ | 555 | case PLANE0: |
405 | if (hw->desc[0] != machine_data->dummy_ad->paddr) | 556 | if (hw->desc[0] != machine_data->dummy_ad->paddr) |
406 | wr_reg_wa(&hw->desc[0], machine_data->dummy_ad->paddr); | 557 | wr_reg_wa(&hw->desc[0], machine_data->dummy_ad->paddr); |
407 | break; | 558 | break; |
408 | case 1: /* plane 1 AOI 0 */ | 559 | case PLANE1_AOI0: |
409 | cmfbi = machine_data->fsl_diu_info[2]->par; | 560 | cmfbi = machine_data->fsl_diu_info[2]->par; |
410 | if (cmfbi->count > 0) /* AOI1 is open */ | 561 | if (cmfbi->count > 0) /* AOI1 is open */ |
411 | wr_reg_wa(&hw->desc[1], cmfbi->ad->paddr); | 562 | wr_reg_wa(&hw->desc[1], cmfbi->ad->paddr); |
@@ -414,7 +565,7 @@ static int fsl_diu_disable_panel(struct fb_info *info) | |||
414 | wr_reg_wa(&hw->desc[1], machine_data->dummy_ad->paddr); | 565 | wr_reg_wa(&hw->desc[1], machine_data->dummy_ad->paddr); |
415 | /* close AOI 0 */ | 566 | /* close AOI 0 */ |
416 | break; | 567 | break; |
417 | case 3: /* plane 2 AOI 0 */ | 568 | case PLANE2_AOI0: |
418 | cmfbi = machine_data->fsl_diu_info[4]->par; | 569 | cmfbi = machine_data->fsl_diu_info[4]->par; |
419 | if (cmfbi->count > 0) /* AOI1 is open */ | 570 | if (cmfbi->count > 0) /* AOI1 is open */ |
420 | wr_reg_wa(&hw->desc[2], cmfbi->ad->paddr); | 571 | wr_reg_wa(&hw->desc[2], cmfbi->ad->paddr); |
@@ -423,7 +574,7 @@ static int fsl_diu_disable_panel(struct fb_info *info) | |||
423 | wr_reg_wa(&hw->desc[2], machine_data->dummy_ad->paddr); | 574 | wr_reg_wa(&hw->desc[2], machine_data->dummy_ad->paddr); |
424 | /* close AOI 0 */ | 575 | /* close AOI 0 */ |
425 | break; | 576 | break; |
426 | case 2: /* plane 1 AOI 1 */ | 577 | case PLANE1_AOI1: |
427 | pmfbi = machine_data->fsl_diu_info[1]->par; | 578 | pmfbi = machine_data->fsl_diu_info[1]->par; |
428 | if (hw->desc[1] != ad->paddr) { | 579 | if (hw->desc[1] != ad->paddr) { |
429 | /* AOI1 is not the first in the chain */ | 580 | /* AOI1 is not the first in the chain */ |
@@ -434,7 +585,7 @@ static int fsl_diu_disable_panel(struct fb_info *info) | |||
434 | wr_reg_wa(&hw->desc[1], machine_data->dummy_ad->paddr); | 585 | wr_reg_wa(&hw->desc[1], machine_data->dummy_ad->paddr); |
435 | /* close AOI 1 */ | 586 | /* close AOI 1 */ |
436 | break; | 587 | break; |
437 | case 4: /* plane 2 AOI 1 */ | 588 | case PLANE2_AOI1: |
438 | pmfbi = machine_data->fsl_diu_info[3]->par; | 589 | pmfbi = machine_data->fsl_diu_info[3]->par; |
439 | if (hw->desc[2] != ad->paddr) { | 590 | if (hw->desc[2] != ad->paddr) { |
440 | /* AOI1 is not the first in the chain */ | 591 | /* AOI1 is not the first in the chain */ |
@@ -445,31 +596,26 @@ static int fsl_diu_disable_panel(struct fb_info *info) | |||
445 | wr_reg_wa(&hw->desc[2], machine_data->dummy_ad->paddr); | 596 | wr_reg_wa(&hw->desc[2], machine_data->dummy_ad->paddr); |
446 | /* close AOI 1 */ | 597 | /* close AOI 1 */ |
447 | break; | 598 | break; |
448 | default: | ||
449 | res = -EINVAL; | ||
450 | break; | ||
451 | } | 599 | } |
452 | |||
453 | return res; | ||
454 | } | 600 | } |
455 | 601 | ||
456 | static void enable_lcdc(struct fb_info *info) | 602 | static void enable_lcdc(struct fb_info *info) |
457 | { | 603 | { |
458 | struct diu *hw = dr.diu_reg; | ||
459 | struct mfb_info *mfbi = info->par; | 604 | struct mfb_info *mfbi = info->par; |
460 | struct fsl_diu_data *machine_data = mfbi->parent; | 605 | struct fsl_diu_data *machine_data = mfbi->parent; |
606 | struct diu __iomem *hw = machine_data->diu_reg; | ||
461 | 607 | ||
462 | if (!machine_data->fb_enabled) { | 608 | if (!machine_data->fb_enabled) { |
463 | out_be32(&hw->diu_mode, dr.mode); | 609 | out_be32(&hw->diu_mode, MFB_MODE1); |
464 | machine_data->fb_enabled++; | 610 | machine_data->fb_enabled++; |
465 | } | 611 | } |
466 | } | 612 | } |
467 | 613 | ||
468 | static void disable_lcdc(struct fb_info *info) | 614 | static void disable_lcdc(struct fb_info *info) |
469 | { | 615 | { |
470 | struct diu *hw = dr.diu_reg; | ||
471 | struct mfb_info *mfbi = info->par; | 616 | struct mfb_info *mfbi = info->par; |
472 | struct fsl_diu_data *machine_data = mfbi->parent; | 617 | struct fsl_diu_data *machine_data = mfbi->parent; |
618 | struct diu __iomem *hw = machine_data->diu_reg; | ||
473 | 619 | ||
474 | if (machine_data->fb_enabled) { | 620 | if (machine_data->fb_enabled) { |
475 | out_be32(&hw->diu_mode, 0); | 621 | out_be32(&hw->diu_mode, 0); |
@@ -482,7 +628,8 @@ static void adjust_aoi_size_position(struct fb_var_screeninfo *var, | |||
482 | { | 628 | { |
483 | struct mfb_info *lower_aoi_mfbi, *upper_aoi_mfbi, *mfbi = info->par; | 629 | struct mfb_info *lower_aoi_mfbi, *upper_aoi_mfbi, *mfbi = info->par; |
484 | struct fsl_diu_data *machine_data = mfbi->parent; | 630 | struct fsl_diu_data *machine_data = mfbi->parent; |
485 | int available_height, upper_aoi_bottom, index = mfbi->index; | 631 | int available_height, upper_aoi_bottom; |
632 | enum mfb_index index = mfbi->index; | ||
486 | int lower_aoi_is_open, upper_aoi_is_open; | 633 | int lower_aoi_is_open, upper_aoi_is_open; |
487 | __u32 base_plane_width, base_plane_height, upper_aoi_height; | 634 | __u32 base_plane_width, base_plane_height, upper_aoi_height; |
488 | 635 | ||
@@ -494,14 +641,14 @@ static void adjust_aoi_size_position(struct fb_var_screeninfo *var, | |||
494 | if (mfbi->y_aoi_d < 0) | 641 | if (mfbi->y_aoi_d < 0) |
495 | mfbi->y_aoi_d = 0; | 642 | mfbi->y_aoi_d = 0; |
496 | switch (index) { | 643 | switch (index) { |
497 | case 0: | 644 | case PLANE0: |
498 | if (mfbi->x_aoi_d != 0) | 645 | if (mfbi->x_aoi_d != 0) |
499 | mfbi->x_aoi_d = 0; | 646 | mfbi->x_aoi_d = 0; |
500 | if (mfbi->y_aoi_d != 0) | 647 | if (mfbi->y_aoi_d != 0) |
501 | mfbi->y_aoi_d = 0; | 648 | mfbi->y_aoi_d = 0; |
502 | break; | 649 | break; |
503 | case 1: /* AOI 0 */ | 650 | case PLANE1_AOI0: |
504 | case 3: | 651 | case PLANE2_AOI0: |
505 | lower_aoi_mfbi = machine_data->fsl_diu_info[index+1]->par; | 652 | lower_aoi_mfbi = machine_data->fsl_diu_info[index+1]->par; |
506 | lower_aoi_is_open = lower_aoi_mfbi->count > 0 ? 1 : 0; | 653 | lower_aoi_is_open = lower_aoi_mfbi->count > 0 ? 1 : 0; |
507 | if (var->xres > base_plane_width) | 654 | if (var->xres > base_plane_width) |
@@ -518,8 +665,8 @@ static void adjust_aoi_size_position(struct fb_var_screeninfo *var, | |||
518 | if ((mfbi->y_aoi_d + var->yres) > available_height) | 665 | if ((mfbi->y_aoi_d + var->yres) > available_height) |
519 | mfbi->y_aoi_d = available_height - var->yres; | 666 | mfbi->y_aoi_d = available_height - var->yres; |
520 | break; | 667 | break; |
521 | case 2: /* AOI 1 */ | 668 | case PLANE1_AOI1: |
522 | case 4: | 669 | case PLANE2_AOI1: |
523 | upper_aoi_mfbi = machine_data->fsl_diu_info[index-1]->par; | 670 | upper_aoi_mfbi = machine_data->fsl_diu_info[index-1]->par; |
524 | upper_aoi_height = | 671 | upper_aoi_height = |
525 | machine_data->fsl_diu_info[index-1]->var.yres; | 672 | machine_data->fsl_diu_info[index-1]->var.yres; |
@@ -555,9 +702,6 @@ static void adjust_aoi_size_position(struct fb_var_screeninfo *var, | |||
555 | static int fsl_diu_check_var(struct fb_var_screeninfo *var, | 702 | static int fsl_diu_check_var(struct fb_var_screeninfo *var, |
556 | struct fb_info *info) | 703 | struct fb_info *info) |
557 | { | 704 | { |
558 | pr_debug("check_var xres: %d\n", var->xres); | ||
559 | pr_debug("check_var yres: %d\n", var->yres); | ||
560 | |||
561 | if (var->xres_virtual < var->xres) | 705 | if (var->xres_virtual < var->xres) |
562 | var->xres_virtual = var->xres; | 706 | var->xres_virtual = var->xres; |
563 | if (var->yres_virtual < var->yres) | 707 | if (var->yres_virtual < var->yres) |
@@ -652,7 +796,7 @@ static void set_fix(struct fb_info *info) | |||
652 | struct fb_var_screeninfo *var = &info->var; | 796 | struct fb_var_screeninfo *var = &info->var; |
653 | struct mfb_info *mfbi = info->par; | 797 | struct mfb_info *mfbi = info->par; |
654 | 798 | ||
655 | strncpy(fix->id, mfbi->id, strlen(mfbi->id)); | 799 | strncpy(fix->id, mfbi->id, sizeof(fix->id)); |
656 | fix->line_length = var->xres_virtual * var->bits_per_pixel / 8; | 800 | fix->line_length = var->xres_virtual * var->bits_per_pixel / 8; |
657 | fix->type = FB_TYPE_PACKED_PIXELS; | 801 | fix->type = FB_TYPE_PACKED_PIXELS; |
658 | fix->accel = FB_ACCEL_NONE; | 802 | fix->accel = FB_ACCEL_NONE; |
@@ -666,45 +810,37 @@ static void update_lcdc(struct fb_info *info) | |||
666 | struct fb_var_screeninfo *var = &info->var; | 810 | struct fb_var_screeninfo *var = &info->var; |
667 | struct mfb_info *mfbi = info->par; | 811 | struct mfb_info *mfbi = info->par; |
668 | struct fsl_diu_data *machine_data = mfbi->parent; | 812 | struct fsl_diu_data *machine_data = mfbi->parent; |
669 | struct diu *hw; | 813 | struct diu __iomem *hw; |
670 | int i, j; | 814 | int i, j; |
671 | char __iomem *cursor_base, *gamma_table_base; | 815 | char __iomem *cursor_base, *gamma_table_base; |
672 | 816 | ||
673 | u32 temp; | 817 | u32 temp; |
674 | 818 | ||
675 | hw = dr.diu_reg; | 819 | hw = machine_data->diu_reg; |
676 | |||
677 | if (mfbi->type == MFB_TYPE_OFF) { | ||
678 | fsl_diu_disable_panel(info); | ||
679 | return; | ||
680 | } | ||
681 | 820 | ||
682 | diu_ops.set_monitor_port(machine_data->monitor_port); | 821 | diu_ops.set_monitor_port(machine_data->monitor_port); |
683 | gamma_table_base = pool.gamma.vaddr; | 822 | gamma_table_base = machine_data->gamma.vaddr; |
684 | cursor_base = pool.cursor.vaddr; | 823 | cursor_base = machine_data->cursor.vaddr; |
685 | /* Prep for DIU init - gamma table, cursor table */ | 824 | /* Prep for DIU init - gamma table, cursor table */ |
686 | 825 | ||
687 | for (i = 0; i <= 2; i++) | 826 | for (i = 0; i <= 2; i++) |
688 | for (j = 0; j <= 255; j++) | 827 | for (j = 0; j <= 255; j++) |
689 | *gamma_table_base++ = j; | 828 | *gamma_table_base++ = j; |
690 | 829 | ||
691 | diu_ops.set_gamma_table(machine_data->monitor_port, pool.gamma.vaddr); | 830 | diu_ops.set_gamma_table(machine_data->monitor_port, |
831 | machine_data->gamma.vaddr); | ||
692 | 832 | ||
693 | pr_debug("update-lcdc: HW - %p\n Disabling DIU\n", hw); | ||
694 | disable_lcdc(info); | 833 | disable_lcdc(info); |
695 | 834 | ||
696 | /* Program DIU registers */ | 835 | /* Program DIU registers */ |
697 | 836 | ||
698 | out_be32(&hw->gamma, pool.gamma.paddr); | 837 | out_be32(&hw->gamma, machine_data->gamma.paddr); |
699 | out_be32(&hw->cursor, pool.cursor.paddr); | 838 | out_be32(&hw->cursor, machine_data->cursor.paddr); |
700 | 839 | ||
701 | out_be32(&hw->bgnd, 0x007F7F7F); /* BGND */ | 840 | out_be32(&hw->bgnd, 0x007F7F7F); /* BGND */ |
702 | out_be32(&hw->bgnd_wb, 0); /* BGND_WB */ | 841 | out_be32(&hw->bgnd_wb, 0); /* BGND_WB */ |
703 | out_be32(&hw->disp_size, (var->yres << 16 | var->xres)); | 842 | out_be32(&hw->disp_size, (var->yres << 16 | var->xres)); |
704 | /* DISP SIZE */ | 843 | /* DISP SIZE */ |
705 | pr_debug("DIU xres: %d\n", var->xres); | ||
706 | pr_debug("DIU yres: %d\n", var->yres); | ||
707 | |||
708 | out_be32(&hw->wb_size, 0); /* WB SIZE */ | 844 | out_be32(&hw->wb_size, 0); /* WB SIZE */ |
709 | out_be32(&hw->wb_mem_addr, 0); /* WB MEM ADDR */ | 845 | out_be32(&hw->wb_mem_addr, 0); /* WB MEM ADDR */ |
710 | 846 | ||
@@ -721,15 +857,6 @@ static void update_lcdc(struct fb_info *info) | |||
721 | 857 | ||
722 | out_be32(&hw->vsyn_para, temp); | 858 | out_be32(&hw->vsyn_para, temp); |
723 | 859 | ||
724 | pr_debug("DIU right_margin - %d\n", var->right_margin); | ||
725 | pr_debug("DIU left_margin - %d\n", var->left_margin); | ||
726 | pr_debug("DIU hsync_len - %d\n", var->hsync_len); | ||
727 | pr_debug("DIU upper_margin - %d\n", var->upper_margin); | ||
728 | pr_debug("DIU lower_margin - %d\n", var->lower_margin); | ||
729 | pr_debug("DIU vsync_len - %d\n", var->vsync_len); | ||
730 | pr_debug("DIU HSYNC - 0x%08x\n", hw->hsyn_para); | ||
731 | pr_debug("DIU VSYNC - 0x%08x\n", hw->vsyn_para); | ||
732 | |||
733 | diu_ops.set_pixel_clock(var->pixclock); | 860 | diu_ops.set_pixel_clock(var->pixclock); |
734 | 861 | ||
735 | out_be32(&hw->syn_pol, 0); /* SYNC SIGNALS POLARITY */ | 862 | out_be32(&hw->syn_pol, 0); /* SYNC SIGNALS POLARITY */ |
@@ -746,14 +873,9 @@ static int map_video_memory(struct fb_info *info) | |||
746 | phys_addr_t phys; | 873 | phys_addr_t phys; |
747 | u32 smem_len = info->fix.line_length * info->var.yres_virtual; | 874 | u32 smem_len = info->fix.line_length * info->var.yres_virtual; |
748 | 875 | ||
749 | pr_debug("info->var.xres_virtual = %d\n", info->var.xres_virtual); | ||
750 | pr_debug("info->var.yres_virtual = %d\n", info->var.yres_virtual); | ||
751 | pr_debug("info->fix.line_length = %d\n", info->fix.line_length); | ||
752 | pr_debug("MAP_VIDEO_MEMORY: smem_len = %u\n", smem_len); | ||
753 | |||
754 | info->screen_base = fsl_diu_alloc(smem_len, &phys); | 876 | info->screen_base = fsl_diu_alloc(smem_len, &phys); |
755 | if (info->screen_base == NULL) { | 877 | if (info->screen_base == NULL) { |
756 | printk(KERN_ERR "Unable to allocate fb memory\n"); | 878 | dev_err(info->dev, "unable to allocate fb memory\n"); |
757 | return -ENOMEM; | 879 | return -ENOMEM; |
758 | } | 880 | } |
759 | mutex_lock(&info->mm_lock); | 881 | mutex_lock(&info->mm_lock); |
@@ -762,10 +884,6 @@ static int map_video_memory(struct fb_info *info) | |||
762 | mutex_unlock(&info->mm_lock); | 884 | mutex_unlock(&info->mm_lock); |
763 | info->screen_size = info->fix.smem_len; | 885 | info->screen_size = info->fix.smem_len; |
764 | 886 | ||
765 | pr_debug("Allocated fb @ paddr=0x%08lx, size=%d.\n", | ||
766 | info->fix.smem_start, info->fix.smem_len); | ||
767 | pr_debug("screen base %p\n", info->screen_base); | ||
768 | |||
769 | return 0; | 887 | return 0; |
770 | } | 888 | } |
771 | 889 | ||
@@ -810,9 +928,9 @@ static int fsl_diu_set_par(struct fb_info *info) | |||
810 | struct mfb_info *mfbi = info->par; | 928 | struct mfb_info *mfbi = info->par; |
811 | struct fsl_diu_data *machine_data = mfbi->parent; | 929 | struct fsl_diu_data *machine_data = mfbi->parent; |
812 | struct diu_ad *ad = mfbi->ad; | 930 | struct diu_ad *ad = mfbi->ad; |
813 | struct diu *hw; | 931 | struct diu __iomem *hw; |
814 | 932 | ||
815 | hw = dr.diu_reg; | 933 | hw = machine_data->diu_reg; |
816 | 934 | ||
817 | set_fix(info); | 935 | set_fix(info); |
818 | mfbi->cursor_reset = 1; | 936 | mfbi->cursor_reset = 1; |
@@ -822,18 +940,16 @@ static int fsl_diu_set_par(struct fb_info *info) | |||
822 | if (len != info->fix.smem_len) { | 940 | if (len != info->fix.smem_len) { |
823 | if (info->fix.smem_start) | 941 | if (info->fix.smem_start) |
824 | unmap_video_memory(info); | 942 | unmap_video_memory(info); |
825 | pr_debug("SET PAR: smem_len = %d\n", info->fix.smem_len); | ||
826 | 943 | ||
827 | /* Memory allocation for framebuffer */ | 944 | /* Memory allocation for framebuffer */ |
828 | if (map_video_memory(info)) { | 945 | if (map_video_memory(info)) { |
829 | printk(KERN_ERR "Unable to allocate fb memory 1\n"); | 946 | dev_err(info->dev, "unable to allocate fb memory 1\n"); |
830 | return -ENOMEM; | 947 | return -ENOMEM; |
831 | } | 948 | } |
832 | } | 949 | } |
833 | 950 | ||
834 | ad->pix_fmt = | 951 | ad->pix_fmt = diu_ops.get_pixel_format(machine_data->monitor_port, |
835 | diu_ops.get_pixel_format(var->bits_per_pixel, | 952 | var->bits_per_pixel); |
836 | machine_data->monitor_port); | ||
837 | ad->addr = cpu_to_le32(info->fix.smem_start); | 953 | ad->addr = cpu_to_le32(info->fix.smem_start); |
838 | ad->src_size_g_alpha = cpu_to_le32((var->yres_virtual << 12) | | 954 | ad->src_size_g_alpha = cpu_to_le32((var->yres_virtual << 12) | |
839 | var->xres_virtual) | mfbi->g_alpha; | 955 | var->xres_virtual) | mfbi->g_alpha; |
@@ -851,14 +967,14 @@ static int fsl_diu_set_par(struct fb_info *info) | |||
851 | ad->ckmin_g = 255; | 967 | ad->ckmin_g = 255; |
852 | ad->ckmin_b = 255; | 968 | ad->ckmin_b = 255; |
853 | 969 | ||
854 | if (mfbi->index == 0) | 970 | if (mfbi->index == PLANE0) |
855 | update_lcdc(info); | 971 | update_lcdc(info); |
856 | return 0; | 972 | return 0; |
857 | } | 973 | } |
858 | 974 | ||
859 | static inline __u32 CNVT_TOHW(__u32 val, __u32 width) | 975 | static inline __u32 CNVT_TOHW(__u32 val, __u32 width) |
860 | { | 976 | { |
861 | return ((val<<width) + 0x7FFF - val)>>16; | 977 | return ((val << width) + 0x7FFF - val) >> 16; |
862 | } | 978 | } |
863 | 979 | ||
864 | /* | 980 | /* |
@@ -870,8 +986,9 @@ static inline __u32 CNVT_TOHW(__u32 val, __u32 width) | |||
870 | * pseudo_palette in struct fb_info. For pseudocolor mode we have a limited | 986 | * pseudo_palette in struct fb_info. For pseudocolor mode we have a limited |
871 | * color palette. | 987 | * color palette. |
872 | */ | 988 | */ |
873 | static int fsl_diu_setcolreg(unsigned regno, unsigned red, unsigned green, | 989 | static int fsl_diu_setcolreg(unsigned int regno, unsigned int red, |
874 | unsigned blue, unsigned transp, struct fb_info *info) | 990 | unsigned int green, unsigned int blue, |
991 | unsigned int transp, struct fb_info *info) | ||
875 | { | 992 | { |
876 | int ret = 1; | 993 | int ret = 1; |
877 | 994 | ||
@@ -906,9 +1023,6 @@ static int fsl_diu_setcolreg(unsigned regno, unsigned red, unsigned green, | |||
906 | ret = 0; | 1023 | ret = 0; |
907 | } | 1024 | } |
908 | break; | 1025 | break; |
909 | case FB_VISUAL_STATIC_PSEUDOCOLOR: | ||
910 | case FB_VISUAL_PSEUDOCOLOR: | ||
911 | break; | ||
912 | } | 1026 | } |
913 | 1027 | ||
914 | return ret; | 1028 | return ret; |
@@ -944,37 +1058,6 @@ static int fsl_diu_pan_display(struct fb_var_screeninfo *var, | |||
944 | return 0; | 1058 | return 0; |
945 | } | 1059 | } |
946 | 1060 | ||
947 | /* | ||
948 | * Blank the screen if blank_mode != 0, else unblank. Return 0 if blanking | ||
949 | * succeeded, != 0 if un-/blanking failed. | ||
950 | * blank_mode == 2: suspend vsync | ||
951 | * blank_mode == 3: suspend hsync | ||
952 | * blank_mode == 4: powerdown | ||
953 | */ | ||
954 | static int fsl_diu_blank(int blank_mode, struct fb_info *info) | ||
955 | { | ||
956 | struct mfb_info *mfbi = info->par; | ||
957 | |||
958 | mfbi->blank = blank_mode; | ||
959 | |||
960 | switch (blank_mode) { | ||
961 | case FB_BLANK_VSYNC_SUSPEND: | ||
962 | case FB_BLANK_HSYNC_SUSPEND: | ||
963 | /* FIXME: fixes to enable_panel and enable lcdc needed */ | ||
964 | case FB_BLANK_NORMAL: | ||
965 | /* fsl_diu_disable_panel(info);*/ | ||
966 | break; | ||
967 | case FB_BLANK_POWERDOWN: | ||
968 | /* disable_lcdc(info); */ | ||
969 | break; | ||
970 | case FB_BLANK_UNBLANK: | ||
971 | /* fsl_diu_enable_panel(info);*/ | ||
972 | break; | ||
973 | } | ||
974 | |||
975 | return 0; | ||
976 | } | ||
977 | |||
978 | static int fsl_diu_ioctl(struct fb_info *info, unsigned int cmd, | 1061 | static int fsl_diu_ioctl(struct fb_info *info, unsigned int cmd, |
979 | unsigned long arg) | 1062 | unsigned long arg) |
980 | { | 1063 | { |
@@ -989,25 +1072,29 @@ static int fsl_diu_ioctl(struct fb_info *info, unsigned int cmd, | |||
989 | if (!arg) | 1072 | if (!arg) |
990 | return -EINVAL; | 1073 | return -EINVAL; |
991 | switch (cmd) { | 1074 | switch (cmd) { |
1075 | case MFB_SET_PIXFMT_OLD: | ||
1076 | dev_warn(info->dev, | ||
1077 | "MFB_SET_PIXFMT value of 0x%08x is deprecated.\n", | ||
1078 | MFB_SET_PIXFMT_OLD); | ||
992 | case MFB_SET_PIXFMT: | 1079 | case MFB_SET_PIXFMT: |
993 | if (copy_from_user(&pix_fmt, buf, sizeof(pix_fmt))) | 1080 | if (copy_from_user(&pix_fmt, buf, sizeof(pix_fmt))) |
994 | return -EFAULT; | 1081 | return -EFAULT; |
995 | ad->pix_fmt = pix_fmt; | 1082 | ad->pix_fmt = pix_fmt; |
996 | pr_debug("Set pixel format to 0x%08x\n", ad->pix_fmt); | ||
997 | break; | 1083 | break; |
1084 | case MFB_GET_PIXFMT_OLD: | ||
1085 | dev_warn(info->dev, | ||
1086 | "MFB_GET_PIXFMT value of 0x%08x is deprecated.\n", | ||
1087 | MFB_GET_PIXFMT_OLD); | ||
998 | case MFB_GET_PIXFMT: | 1088 | case MFB_GET_PIXFMT: |
999 | pix_fmt = ad->pix_fmt; | 1089 | pix_fmt = ad->pix_fmt; |
1000 | if (copy_to_user(buf, &pix_fmt, sizeof(pix_fmt))) | 1090 | if (copy_to_user(buf, &pix_fmt, sizeof(pix_fmt))) |
1001 | return -EFAULT; | 1091 | return -EFAULT; |
1002 | pr_debug("get pixel format 0x%08x\n", ad->pix_fmt); | ||
1003 | break; | 1092 | break; |
1004 | case MFB_SET_AOID: | 1093 | case MFB_SET_AOID: |
1005 | if (copy_from_user(&aoi_d, buf, sizeof(aoi_d))) | 1094 | if (copy_from_user(&aoi_d, buf, sizeof(aoi_d))) |
1006 | return -EFAULT; | 1095 | return -EFAULT; |
1007 | mfbi->x_aoi_d = aoi_d.x_aoi_d; | 1096 | mfbi->x_aoi_d = aoi_d.x_aoi_d; |
1008 | mfbi->y_aoi_d = aoi_d.y_aoi_d; | 1097 | mfbi->y_aoi_d = aoi_d.y_aoi_d; |
1009 | pr_debug("set AOI display offset of index %d to (%d,%d)\n", | ||
1010 | mfbi->index, aoi_d.x_aoi_d, aoi_d.y_aoi_d); | ||
1011 | fsl_diu_check_var(&info->var, info); | 1098 | fsl_diu_check_var(&info->var, info); |
1012 | fsl_diu_set_aoi(info); | 1099 | fsl_diu_set_aoi(info); |
1013 | break; | 1100 | break; |
@@ -1016,14 +1103,11 @@ static int fsl_diu_ioctl(struct fb_info *info, unsigned int cmd, | |||
1016 | aoi_d.y_aoi_d = mfbi->y_aoi_d; | 1103 | aoi_d.y_aoi_d = mfbi->y_aoi_d; |
1017 | if (copy_to_user(buf, &aoi_d, sizeof(aoi_d))) | 1104 | if (copy_to_user(buf, &aoi_d, sizeof(aoi_d))) |
1018 | return -EFAULT; | 1105 | return -EFAULT; |
1019 | pr_debug("get AOI display offset of index %d (%d,%d)\n", | ||
1020 | mfbi->index, aoi_d.x_aoi_d, aoi_d.y_aoi_d); | ||
1021 | break; | 1106 | break; |
1022 | case MFB_GET_ALPHA: | 1107 | case MFB_GET_ALPHA: |
1023 | global_alpha = mfbi->g_alpha; | 1108 | global_alpha = mfbi->g_alpha; |
1024 | if (copy_to_user(buf, &global_alpha, sizeof(global_alpha))) | 1109 | if (copy_to_user(buf, &global_alpha, sizeof(global_alpha))) |
1025 | return -EFAULT; | 1110 | return -EFAULT; |
1026 | pr_debug("get global alpha of index %d\n", mfbi->index); | ||
1027 | break; | 1111 | break; |
1028 | case MFB_SET_ALPHA: | 1112 | case MFB_SET_ALPHA: |
1029 | /* set panel information */ | 1113 | /* set panel information */ |
@@ -1032,7 +1116,6 @@ static int fsl_diu_ioctl(struct fb_info *info, unsigned int cmd, | |||
1032 | ad->src_size_g_alpha = (ad->src_size_g_alpha & (~0xff)) | | 1116 | ad->src_size_g_alpha = (ad->src_size_g_alpha & (~0xff)) | |
1033 | (global_alpha & 0xff); | 1117 | (global_alpha & 0xff); |
1034 | mfbi->g_alpha = global_alpha; | 1118 | mfbi->g_alpha = global_alpha; |
1035 | pr_debug("set global alpha for index %d\n", mfbi->index); | ||
1036 | break; | 1119 | break; |
1037 | case MFB_SET_CHROMA_KEY: | 1120 | case MFB_SET_CHROMA_KEY: |
1038 | /* set panel winformation */ | 1121 | /* set panel winformation */ |
@@ -1060,27 +1143,9 @@ static int fsl_diu_ioctl(struct fb_info *info, unsigned int cmd, | |||
1060 | ad->ckmin_g = ck.green_min; | 1143 | ad->ckmin_g = ck.green_min; |
1061 | ad->ckmin_b = ck.blue_min; | 1144 | ad->ckmin_b = ck.blue_min; |
1062 | } | 1145 | } |
1063 | pr_debug("set chroma key\n"); | ||
1064 | break; | 1146 | break; |
1065 | case FBIOGET_GWINFO: | ||
1066 | if (mfbi->type == MFB_TYPE_OFF) | ||
1067 | return -ENODEV; | ||
1068 | /* get graphic window information */ | ||
1069 | if (copy_to_user(buf, ad, sizeof(*ad))) | ||
1070 | return -EFAULT; | ||
1071 | break; | ||
1072 | case FBIOGET_HWCINFO: | ||
1073 | pr_debug("FBIOGET_HWCINFO:0x%08x\n", FBIOGET_HWCINFO); | ||
1074 | break; | ||
1075 | case FBIOPUT_MODEINFO: | ||
1076 | pr_debug("FBIOPUT_MODEINFO:0x%08x\n", FBIOPUT_MODEINFO); | ||
1077 | break; | ||
1078 | case FBIOGET_DISPINFO: | ||
1079 | pr_debug("FBIOGET_DISPINFO:0x%08x\n", FBIOGET_DISPINFO); | ||
1080 | break; | ||
1081 | |||
1082 | default: | 1147 | default: |
1083 | printk(KERN_ERR "Unknown ioctl command (0x%08X)\n", cmd); | 1148 | dev_err(info->dev, "unknown ioctl command (0x%08X)\n", cmd); |
1084 | return -ENOIOCTLCMD; | 1149 | return -ENOIOCTLCMD; |
1085 | } | 1150 | } |
1086 | 1151 | ||
@@ -1095,22 +1160,18 @@ static int fsl_diu_open(struct fb_info *info, int user) | |||
1095 | int res = 0; | 1160 | int res = 0; |
1096 | 1161 | ||
1097 | /* free boot splash memory on first /dev/fb0 open */ | 1162 | /* free boot splash memory on first /dev/fb0 open */ |
1098 | if (!mfbi->index && diu_ops.release_bootmem) | 1163 | if ((mfbi->index == PLANE0) && diu_ops.release_bootmem) |
1099 | diu_ops.release_bootmem(); | 1164 | diu_ops.release_bootmem(); |
1100 | 1165 | ||
1101 | spin_lock(&diu_lock); | 1166 | spin_lock(&diu_lock); |
1102 | mfbi->count++; | 1167 | mfbi->count++; |
1103 | if (mfbi->count == 1) { | 1168 | if (mfbi->count == 1) { |
1104 | pr_debug("open plane index %d\n", mfbi->index); | ||
1105 | fsl_diu_check_var(&info->var, info); | 1169 | fsl_diu_check_var(&info->var, info); |
1106 | res = fsl_diu_set_par(info); | 1170 | res = fsl_diu_set_par(info); |
1107 | if (res < 0) | 1171 | if (res < 0) |
1108 | mfbi->count--; | 1172 | mfbi->count--; |
1109 | else { | 1173 | else |
1110 | res = fsl_diu_enable_panel(info); | 1174 | fsl_diu_enable_panel(info); |
1111 | if (res < 0) | ||
1112 | mfbi->count--; | ||
1113 | } | ||
1114 | } | 1175 | } |
1115 | 1176 | ||
1116 | spin_unlock(&diu_lock); | 1177 | spin_unlock(&diu_lock); |
@@ -1126,12 +1187,9 @@ static int fsl_diu_release(struct fb_info *info, int user) | |||
1126 | 1187 | ||
1127 | spin_lock(&diu_lock); | 1188 | spin_lock(&diu_lock); |
1128 | mfbi->count--; | 1189 | mfbi->count--; |
1129 | if (mfbi->count == 0) { | 1190 | if (mfbi->count == 0) |
1130 | pr_debug("release plane index %d\n", mfbi->index); | 1191 | fsl_diu_disable_panel(info); |
1131 | res = fsl_diu_disable_panel(info); | 1192 | |
1132 | if (res < 0) | ||
1133 | mfbi->count++; | ||
1134 | } | ||
1135 | spin_unlock(&diu_lock); | 1193 | spin_unlock(&diu_lock); |
1136 | return res; | 1194 | return res; |
1137 | } | 1195 | } |
@@ -1141,7 +1199,6 @@ static struct fb_ops fsl_diu_ops = { | |||
1141 | .fb_check_var = fsl_diu_check_var, | 1199 | .fb_check_var = fsl_diu_check_var, |
1142 | .fb_set_par = fsl_diu_set_par, | 1200 | .fb_set_par = fsl_diu_set_par, |
1143 | .fb_setcolreg = fsl_diu_setcolreg, | 1201 | .fb_setcolreg = fsl_diu_setcolreg, |
1144 | .fb_blank = fsl_diu_blank, | ||
1145 | .fb_pan_display = fsl_diu_pan_display, | 1202 | .fb_pan_display = fsl_diu_pan_display, |
1146 | .fb_fillrect = cfb_fillrect, | 1203 | .fb_fillrect = cfb_fillrect, |
1147 | .fb_copyarea = cfb_copyarea, | 1204 | .fb_copyarea = cfb_copyarea, |
@@ -1178,7 +1235,7 @@ static int __devinit install_fb(struct fb_info *info) | |||
1178 | if (init_fbinfo(info)) | 1235 | if (init_fbinfo(info)) |
1179 | return -EINVAL; | 1236 | return -EINVAL; |
1180 | 1237 | ||
1181 | if (mfbi->index == 0) { /* plane 0 */ | 1238 | if (mfbi->index == PLANE0) { |
1182 | if (mfbi->edid_data) { | 1239 | if (mfbi->edid_data) { |
1183 | /* Now build modedb from EDID */ | 1240 | /* Now build modedb from EDID */ |
1184 | fb_edid_to_monspecs(mfbi->edid_data, &info->monspecs); | 1241 | fb_edid_to_monspecs(mfbi->edid_data, &info->monspecs); |
@@ -1192,43 +1249,23 @@ static int __devinit install_fb(struct fb_info *info) | |||
1192 | } else { | 1249 | } else { |
1193 | aoi_mode = init_aoi_mode; | 1250 | aoi_mode = init_aoi_mode; |
1194 | } | 1251 | } |
1195 | pr_debug("mode used = %s\n", aoi_mode); | 1252 | rc = fb_find_mode(&info->var, info, aoi_mode, db, dbsize, NULL, |
1196 | rc = fb_find_mode(&info->var, info, aoi_mode, db, dbsize, | 1253 | default_bpp); |
1197 | &fsl_diu_default_mode, default_bpp); | 1254 | if (!rc) { |
1198 | switch (rc) { | ||
1199 | case 1: | ||
1200 | pr_debug("using mode specified in @mode\n"); | ||
1201 | break; | ||
1202 | case 2: | ||
1203 | pr_debug("using mode specified in @mode " | ||
1204 | "with ignored refresh rate\n"); | ||
1205 | break; | ||
1206 | case 3: | ||
1207 | pr_debug("using mode default mode\n"); | ||
1208 | break; | ||
1209 | case 4: | ||
1210 | pr_debug("using mode from list\n"); | ||
1211 | break; | ||
1212 | default: | ||
1213 | pr_debug("rc = %d\n", rc); | ||
1214 | pr_debug("failed to find mode\n"); | ||
1215 | /* | 1255 | /* |
1216 | * For plane 0 we continue and look into | 1256 | * For plane 0 we continue and look into |
1217 | * driver's internal modedb. | 1257 | * driver's internal modedb. |
1218 | */ | 1258 | */ |
1219 | if (mfbi->index == 0 && mfbi->edid_data) | 1259 | if ((mfbi->index == PLANE0) && mfbi->edid_data) |
1220 | has_default_mode = 0; | 1260 | has_default_mode = 0; |
1221 | else | 1261 | else |
1222 | return -EINVAL; | 1262 | return -EINVAL; |
1223 | break; | ||
1224 | } | 1263 | } |
1225 | 1264 | ||
1226 | if (!has_default_mode) { | 1265 | if (!has_default_mode) { |
1227 | rc = fb_find_mode(&info->var, info, aoi_mode, fsl_diu_mode_db, | 1266 | rc = fb_find_mode(&info->var, info, aoi_mode, fsl_diu_mode_db, |
1228 | ARRAY_SIZE(fsl_diu_mode_db), | 1267 | ARRAY_SIZE(fsl_diu_mode_db), NULL, default_bpp); |
1229 | &fsl_diu_default_mode, | 1268 | if (rc) |
1230 | default_bpp); | ||
1231 | if (rc > 0 && rc < 5) | ||
1232 | has_default_mode = 1; | 1269 | has_default_mode = 1; |
1233 | } | 1270 | } |
1234 | 1271 | ||
@@ -1256,33 +1293,22 @@ static int __devinit install_fb(struct fb_info *info) | |||
1256 | fb_videomode_to_var(&info->var, modedb); | 1293 | fb_videomode_to_var(&info->var, modedb); |
1257 | } | 1294 | } |
1258 | 1295 | ||
1259 | pr_debug("xres_virtual %d\n", info->var.xres_virtual); | ||
1260 | pr_debug("bits_per_pixel %d\n", info->var.bits_per_pixel); | ||
1261 | |||
1262 | pr_debug("info->var.yres_virtual = %d\n", info->var.yres_virtual); | ||
1263 | pr_debug("info->fix.line_length = %d\n", info->fix.line_length); | ||
1264 | |||
1265 | if (mfbi->type == MFB_TYPE_OFF) | ||
1266 | mfbi->blank = FB_BLANK_NORMAL; | ||
1267 | else | ||
1268 | mfbi->blank = FB_BLANK_UNBLANK; | ||
1269 | |||
1270 | if (fsl_diu_check_var(&info->var, info)) { | 1296 | if (fsl_diu_check_var(&info->var, info)) { |
1271 | printk(KERN_ERR "fb_check_var failed"); | 1297 | dev_err(info->dev, "fsl_diu_check_var failed\n"); |
1298 | unmap_video_memory(info); | ||
1272 | fb_dealloc_cmap(&info->cmap); | 1299 | fb_dealloc_cmap(&info->cmap); |
1273 | return -EINVAL; | 1300 | return -EINVAL; |
1274 | } | 1301 | } |
1275 | 1302 | ||
1276 | if (register_framebuffer(info) < 0) { | 1303 | if (register_framebuffer(info) < 0) { |
1277 | printk(KERN_ERR "register_framebuffer failed"); | 1304 | dev_err(info->dev, "register_framebuffer failed\n"); |
1278 | unmap_video_memory(info); | 1305 | unmap_video_memory(info); |
1279 | fb_dealloc_cmap(&info->cmap); | 1306 | fb_dealloc_cmap(&info->cmap); |
1280 | return -EINVAL; | 1307 | return -EINVAL; |
1281 | } | 1308 | } |
1282 | 1309 | ||
1283 | mfbi->registered = 1; | 1310 | mfbi->registered = 1; |
1284 | printk(KERN_INFO "fb%d: %s fb device registered successfully.\n", | 1311 | dev_info(info->dev, "%s registered successfully\n", mfbi->id); |
1285 | info->node, info->fix.id); | ||
1286 | 1312 | ||
1287 | return 0; | 1313 | return 0; |
1288 | } | 1314 | } |
@@ -1294,7 +1320,7 @@ static void uninstall_fb(struct fb_info *info) | |||
1294 | if (!mfbi->registered) | 1320 | if (!mfbi->registered) |
1295 | return; | 1321 | return; |
1296 | 1322 | ||
1297 | if (mfbi->index == 0) | 1323 | if (mfbi->index == PLANE0) |
1298 | kfree(mfbi->edid_data); | 1324 | kfree(mfbi->edid_data); |
1299 | 1325 | ||
1300 | unregister_framebuffer(info); | 1326 | unregister_framebuffer(info); |
@@ -1307,20 +1333,20 @@ static void uninstall_fb(struct fb_info *info) | |||
1307 | 1333 | ||
1308 | static irqreturn_t fsl_diu_isr(int irq, void *dev_id) | 1334 | static irqreturn_t fsl_diu_isr(int irq, void *dev_id) |
1309 | { | 1335 | { |
1310 | struct diu *hw = dr.diu_reg; | 1336 | struct diu __iomem *hw = dev_id; |
1311 | unsigned int status = in_be32(&hw->int_status); | 1337 | unsigned int status = in_be32(&hw->int_status); |
1312 | 1338 | ||
1313 | if (status) { | 1339 | if (status) { |
1314 | /* This is the workaround for underrun */ | 1340 | /* This is the workaround for underrun */ |
1315 | if (status & INT_UNDRUN) { | 1341 | if (status & INT_UNDRUN) { |
1316 | out_be32(&hw->diu_mode, 0); | 1342 | out_be32(&hw->diu_mode, 0); |
1317 | pr_debug("Err: DIU occurs underrun!\n"); | ||
1318 | udelay(1); | 1343 | udelay(1); |
1319 | out_be32(&hw->diu_mode, 1); | 1344 | out_be32(&hw->diu_mode, 1); |
1320 | } | 1345 | } |
1321 | #if defined(CONFIG_NOT_COHERENT_CACHE) | 1346 | #if defined(CONFIG_NOT_COHERENT_CACHE) |
1322 | else if (status & INT_VSYNC) { | 1347 | else if (status & INT_VSYNC) { |
1323 | unsigned int i; | 1348 | unsigned int i; |
1349 | |||
1324 | for (i = 0; i < coherence_data_size; | 1350 | for (i = 0; i < coherence_data_size; |
1325 | i += d_cache_line_size) | 1351 | i += d_cache_line_size) |
1326 | __asm__ __volatile__ ( | 1352 | __asm__ __volatile__ ( |
@@ -1333,43 +1359,38 @@ static irqreturn_t fsl_diu_isr(int irq, void *dev_id) | |||
1333 | return IRQ_NONE; | 1359 | return IRQ_NONE; |
1334 | } | 1360 | } |
1335 | 1361 | ||
1336 | static int request_irq_local(int irq) | 1362 | static int request_irq_local(struct fsl_diu_data *machine_data) |
1337 | { | 1363 | { |
1338 | unsigned long status, ints; | 1364 | struct diu __iomem *hw = machine_data->diu_reg; |
1339 | struct diu *hw; | 1365 | u32 ints; |
1340 | int ret; | 1366 | int ret; |
1341 | 1367 | ||
1342 | hw = dr.diu_reg; | ||
1343 | |||
1344 | /* Read to clear the status */ | 1368 | /* Read to clear the status */ |
1345 | status = in_be32(&hw->int_status); | 1369 | in_be32(&hw->int_status); |
1346 | 1370 | ||
1347 | ret = request_irq(irq, fsl_diu_isr, 0, "diu", NULL); | 1371 | ret = request_irq(machine_data->irq, fsl_diu_isr, 0, "fsl-diu-fb", hw); |
1348 | if (ret) | 1372 | if (!ret) { |
1349 | pr_info("Request diu IRQ failed.\n"); | ||
1350 | else { | ||
1351 | ints = INT_PARERR | INT_LS_BF_VS; | 1373 | ints = INT_PARERR | INT_LS_BF_VS; |
1352 | #if !defined(CONFIG_NOT_COHERENT_CACHE) | 1374 | #if !defined(CONFIG_NOT_COHERENT_CACHE) |
1353 | ints |= INT_VSYNC; | 1375 | ints |= INT_VSYNC; |
1354 | #endif | 1376 | #endif |
1355 | if (dr.mode == MFB_MODE2 || dr.mode == MFB_MODE3) | ||
1356 | ints |= INT_VSYNC_WB; | ||
1357 | 1377 | ||
1358 | /* Read to clear the status */ | 1378 | /* Read to clear the status */ |
1359 | status = in_be32(&hw->int_status); | 1379 | in_be32(&hw->int_status); |
1360 | out_be32(&hw->int_mask, ints); | 1380 | out_be32(&hw->int_mask, ints); |
1361 | } | 1381 | } |
1382 | |||
1362 | return ret; | 1383 | return ret; |
1363 | } | 1384 | } |
1364 | 1385 | ||
1365 | static void free_irq_local(int irq) | 1386 | static void free_irq_local(struct fsl_diu_data *machine_data) |
1366 | { | 1387 | { |
1367 | struct diu *hw = dr.diu_reg; | 1388 | struct diu __iomem *hw = machine_data->diu_reg; |
1368 | 1389 | ||
1369 | /* Disable all LCDC interrupt */ | 1390 | /* Disable all LCDC interrupt */ |
1370 | out_be32(&hw->int_mask, 0x1f); | 1391 | out_be32(&hw->int_mask, 0x1f); |
1371 | 1392 | ||
1372 | free_irq(irq, NULL); | 1393 | free_irq(machine_data->irq, NULL); |
1373 | } | 1394 | } |
1374 | 1395 | ||
1375 | #ifdef CONFIG_PM | 1396 | #ifdef CONFIG_PM |
@@ -1406,49 +1427,42 @@ static int fsl_diu_resume(struct platform_device *ofdev) | |||
1406 | static int allocate_buf(struct device *dev, struct diu_addr *buf, u32 size, | 1427 | static int allocate_buf(struct device *dev, struct diu_addr *buf, u32 size, |
1407 | u32 bytes_align) | 1428 | u32 bytes_align) |
1408 | { | 1429 | { |
1409 | u32 offset, ssize; | 1430 | u32 offset; |
1410 | u32 mask; | 1431 | dma_addr_t mask; |
1411 | dma_addr_t paddr = 0; | ||
1412 | 1432 | ||
1413 | ssize = size + bytes_align; | 1433 | buf->vaddr = |
1414 | buf->vaddr = dma_alloc_coherent(dev, ssize, &paddr, GFP_DMA | | 1434 | dma_alloc_coherent(dev, size + bytes_align, &buf->paddr, |
1415 | __GFP_ZERO); | 1435 | GFP_DMA | __GFP_ZERO); |
1416 | if (!buf->vaddr) | 1436 | if (!buf->vaddr) |
1417 | return -ENOMEM; | 1437 | return -ENOMEM; |
1418 | 1438 | ||
1419 | buf->paddr = (__u32) paddr; | ||
1420 | |||
1421 | mask = bytes_align - 1; | 1439 | mask = bytes_align - 1; |
1422 | offset = (u32)buf->paddr & mask; | 1440 | offset = buf->paddr & mask; |
1423 | if (offset) { | 1441 | if (offset) { |
1424 | buf->offset = bytes_align - offset; | 1442 | buf->offset = bytes_align - offset; |
1425 | buf->paddr = (u32)buf->paddr + offset; | 1443 | buf->paddr = buf->paddr + offset; |
1426 | } else | 1444 | } else |
1427 | buf->offset = 0; | 1445 | buf->offset = 0; |
1446 | |||
1428 | return 0; | 1447 | return 0; |
1429 | } | 1448 | } |
1430 | 1449 | ||
1431 | static void free_buf(struct device *dev, struct diu_addr *buf, u32 size, | 1450 | static void free_buf(struct device *dev, struct diu_addr *buf, u32 size, |
1432 | u32 bytes_align) | 1451 | u32 bytes_align) |
1433 | { | 1452 | { |
1434 | dma_free_coherent(dev, size + bytes_align, | 1453 | dma_free_coherent(dev, size + bytes_align, buf->vaddr, |
1435 | buf->vaddr, (buf->paddr - buf->offset)); | 1454 | buf->paddr - buf->offset); |
1436 | return; | ||
1437 | } | 1455 | } |
1438 | 1456 | ||
1439 | static ssize_t store_monitor(struct device *device, | 1457 | static ssize_t store_monitor(struct device *device, |
1440 | struct device_attribute *attr, const char *buf, size_t count) | 1458 | struct device_attribute *attr, const char *buf, size_t count) |
1441 | { | 1459 | { |
1442 | int old_monitor_port; | 1460 | enum fsl_diu_monitor_port old_monitor_port; |
1443 | unsigned long val; | ||
1444 | struct fsl_diu_data *machine_data = | 1461 | struct fsl_diu_data *machine_data = |
1445 | container_of(attr, struct fsl_diu_data, dev_attr); | 1462 | container_of(attr, struct fsl_diu_data, dev_attr); |
1446 | 1463 | ||
1447 | if (strict_strtoul(buf, 10, &val)) | ||
1448 | return 0; | ||
1449 | |||
1450 | old_monitor_port = machine_data->monitor_port; | 1464 | old_monitor_port = machine_data->monitor_port; |
1451 | machine_data->monitor_port = diu_ops.set_sysfs_monitor_port(val); | 1465 | machine_data->monitor_port = fsl_diu_name_to_port(buf); |
1452 | 1466 | ||
1453 | if (old_monitor_port != machine_data->monitor_port) { | 1467 | if (old_monitor_port != machine_data->monitor_port) { |
1454 | /* All AOIs need adjust pixel format | 1468 | /* All AOIs need adjust pixel format |
@@ -1468,16 +1482,25 @@ static ssize_t show_monitor(struct device *device, | |||
1468 | { | 1482 | { |
1469 | struct fsl_diu_data *machine_data = | 1483 | struct fsl_diu_data *machine_data = |
1470 | container_of(attr, struct fsl_diu_data, dev_attr); | 1484 | container_of(attr, struct fsl_diu_data, dev_attr); |
1471 | return diu_ops.show_monitor_port(machine_data->monitor_port, buf); | 1485 | |
1486 | switch (machine_data->monitor_port) { | ||
1487 | case FSL_DIU_PORT_DVI: | ||
1488 | return sprintf(buf, "DVI\n"); | ||
1489 | case FSL_DIU_PORT_LVDS: | ||
1490 | return sprintf(buf, "Single-link LVDS\n"); | ||
1491 | case FSL_DIU_PORT_DLVDS: | ||
1492 | return sprintf(buf, "Dual-link LVDS\n"); | ||
1493 | } | ||
1494 | |||
1495 | return 0; | ||
1472 | } | 1496 | } |
1473 | 1497 | ||
1474 | static int __devinit fsl_diu_probe(struct platform_device *ofdev) | 1498 | static int __devinit fsl_diu_probe(struct platform_device *pdev) |
1475 | { | 1499 | { |
1476 | struct device_node *np = ofdev->dev.of_node; | 1500 | struct device_node *np = pdev->dev.of_node; |
1477 | struct mfb_info *mfbi; | 1501 | struct mfb_info *mfbi; |
1478 | phys_addr_t dummy_ad_addr; | 1502 | phys_addr_t dummy_ad_addr = 0; |
1479 | int ret, i, error = 0; | 1503 | int ret, i, error = 0; |
1480 | struct resource res; | ||
1481 | struct fsl_diu_data *machine_data; | 1504 | struct fsl_diu_data *machine_data; |
1482 | int diu_mode; | 1505 | int diu_mode; |
1483 | 1506 | ||
@@ -1485,11 +1508,13 @@ static int __devinit fsl_diu_probe(struct platform_device *ofdev) | |||
1485 | if (!machine_data) | 1508 | if (!machine_data) |
1486 | return -ENOMEM; | 1509 | return -ENOMEM; |
1487 | 1510 | ||
1511 | spin_lock_init(&machine_data->reg_lock); | ||
1512 | |||
1488 | for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++) { | 1513 | for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++) { |
1489 | machine_data->fsl_diu_info[i] = | 1514 | machine_data->fsl_diu_info[i] = |
1490 | framebuffer_alloc(sizeof(struct mfb_info), &ofdev->dev); | 1515 | framebuffer_alloc(sizeof(struct mfb_info), &pdev->dev); |
1491 | if (!machine_data->fsl_diu_info[i]) { | 1516 | if (!machine_data->fsl_diu_info[i]) { |
1492 | dev_err(&ofdev->dev, "cannot allocate memory\n"); | 1517 | dev_err(&pdev->dev, "cannot allocate memory\n"); |
1493 | ret = -ENOMEM; | 1518 | ret = -ENOMEM; |
1494 | goto error2; | 1519 | goto error2; |
1495 | } | 1520 | } |
@@ -1497,7 +1522,7 @@ static int __devinit fsl_diu_probe(struct platform_device *ofdev) | |||
1497 | memcpy(mfbi, &mfb_template[i], sizeof(struct mfb_info)); | 1522 | memcpy(mfbi, &mfb_template[i], sizeof(struct mfb_info)); |
1498 | mfbi->parent = machine_data; | 1523 | mfbi->parent = machine_data; |
1499 | 1524 | ||
1500 | if (mfbi->index == 0) { | 1525 | if (mfbi->index == PLANE0) { |
1501 | const u8 *prop; | 1526 | const u8 *prop; |
1502 | int len; | 1527 | int len; |
1503 | 1528 | ||
@@ -1509,60 +1534,49 @@ static int __devinit fsl_diu_probe(struct platform_device *ofdev) | |||
1509 | } | 1534 | } |
1510 | } | 1535 | } |
1511 | 1536 | ||
1512 | ret = of_address_to_resource(np, 0, &res); | 1537 | machine_data->diu_reg = of_iomap(np, 0); |
1513 | if (ret) { | 1538 | if (!machine_data->diu_reg) { |
1514 | dev_err(&ofdev->dev, "could not obtain DIU address\n"); | 1539 | dev_err(&pdev->dev, "cannot map DIU registers\n"); |
1515 | goto error; | ||
1516 | } | ||
1517 | if (!res.start) { | ||
1518 | dev_err(&ofdev->dev, "invalid DIU address\n"); | ||
1519 | goto error; | ||
1520 | } | ||
1521 | dev_dbg(&ofdev->dev, "%s, res.start: 0x%08x\n", __func__, res.start); | ||
1522 | |||
1523 | dr.diu_reg = ioremap(res.start, sizeof(struct diu)); | ||
1524 | if (!dr.diu_reg) { | ||
1525 | dev_err(&ofdev->dev, "Err: can't map DIU registers!\n"); | ||
1526 | ret = -EFAULT; | 1540 | ret = -EFAULT; |
1527 | goto error2; | 1541 | goto error2; |
1528 | } | 1542 | } |
1529 | 1543 | ||
1530 | diu_mode = in_be32(&dr.diu_reg->diu_mode); | 1544 | diu_mode = in_be32(&machine_data->diu_reg->diu_mode); |
1531 | if (diu_mode != MFB_MODE1) | 1545 | if (diu_mode == MFB_MODE0) |
1532 | out_be32(&dr.diu_reg->diu_mode, 0); /* disable DIU */ | 1546 | out_be32(&machine_data->diu_reg->diu_mode, 0); /* disable DIU */ |
1533 | 1547 | ||
1534 | /* Get the IRQ of the DIU */ | 1548 | /* Get the IRQ of the DIU */ |
1535 | machine_data->irq = irq_of_parse_and_map(np, 0); | 1549 | machine_data->irq = irq_of_parse_and_map(np, 0); |
1536 | 1550 | ||
1537 | if (!machine_data->irq) { | 1551 | if (!machine_data->irq) { |
1538 | dev_err(&ofdev->dev, "could not get DIU IRQ\n"); | 1552 | dev_err(&pdev->dev, "could not get DIU IRQ\n"); |
1539 | ret = -EINVAL; | 1553 | ret = -EINVAL; |
1540 | goto error; | 1554 | goto error; |
1541 | } | 1555 | } |
1542 | machine_data->monitor_port = monitor_port; | 1556 | machine_data->monitor_port = monitor_port; |
1543 | 1557 | ||
1544 | /* Area descriptor memory pool aligns to 64-bit boundary */ | 1558 | /* Area descriptor memory pool aligns to 64-bit boundary */ |
1545 | if (allocate_buf(&ofdev->dev, &pool.ad, | 1559 | if (allocate_buf(&pdev->dev, &machine_data->ad, |
1546 | sizeof(struct diu_ad) * FSL_AOI_NUM, 8)) | 1560 | sizeof(struct diu_ad) * FSL_AOI_NUM, 8)) |
1547 | return -ENOMEM; | 1561 | return -ENOMEM; |
1548 | 1562 | ||
1549 | /* Get memory for Gamma Table - 32-byte aligned memory */ | 1563 | /* Get memory for Gamma Table - 32-byte aligned memory */ |
1550 | if (allocate_buf(&ofdev->dev, &pool.gamma, 768, 32)) { | 1564 | if (allocate_buf(&pdev->dev, &machine_data->gamma, 768, 32)) { |
1551 | ret = -ENOMEM; | 1565 | ret = -ENOMEM; |
1552 | goto error; | 1566 | goto error; |
1553 | } | 1567 | } |
1554 | 1568 | ||
1555 | /* For performance, cursor bitmap buffer aligns to 32-byte boundary */ | 1569 | /* For performance, cursor bitmap buffer aligns to 32-byte boundary */ |
1556 | if (allocate_buf(&ofdev->dev, &pool.cursor, MAX_CURS * MAX_CURS * 2, | 1570 | if (allocate_buf(&pdev->dev, &machine_data->cursor, |
1557 | 32)) { | 1571 | MAX_CURS * MAX_CURS * 2, 32)) { |
1558 | ret = -ENOMEM; | 1572 | ret = -ENOMEM; |
1559 | goto error; | 1573 | goto error; |
1560 | } | 1574 | } |
1561 | 1575 | ||
1562 | i = ARRAY_SIZE(machine_data->fsl_diu_info); | 1576 | i = ARRAY_SIZE(machine_data->fsl_diu_info); |
1563 | machine_data->dummy_ad = (struct diu_ad *) | 1577 | machine_data->dummy_ad = (struct diu_ad *)((u32)machine_data->ad.vaddr + |
1564 | ((u32)pool.ad.vaddr + pool.ad.offset) + i; | 1578 | machine_data->ad.offset) + i; |
1565 | machine_data->dummy_ad->paddr = pool.ad.paddr + | 1579 | machine_data->dummy_ad->paddr = machine_data->ad.paddr + |
1566 | i * sizeof(struct diu_ad); | 1580 | i * sizeof(struct diu_ad); |
1567 | machine_data->dummy_aoi_virt = fsl_diu_alloc(64, &dummy_ad_addr); | 1581 | machine_data->dummy_aoi_virt = fsl_diu_alloc(64, &dummy_ad_addr); |
1568 | if (!machine_data->dummy_aoi_virt) { | 1582 | if (!machine_data->dummy_aoi_virt) { |
@@ -1581,30 +1595,29 @@ static int __devinit fsl_diu_probe(struct platform_device *ofdev) | |||
1581 | * Let DIU display splash screen if it was pre-initialized | 1595 | * Let DIU display splash screen if it was pre-initialized |
1582 | * by the bootloader, set dummy area descriptor otherwise. | 1596 | * by the bootloader, set dummy area descriptor otherwise. |
1583 | */ | 1597 | */ |
1584 | if (diu_mode != MFB_MODE1) | 1598 | if (diu_mode == MFB_MODE0) |
1585 | out_be32(&dr.diu_reg->desc[0], machine_data->dummy_ad->paddr); | 1599 | out_be32(&machine_data->diu_reg->desc[0], |
1600 | machine_data->dummy_ad->paddr); | ||
1586 | 1601 | ||
1587 | out_be32(&dr.diu_reg->desc[1], machine_data->dummy_ad->paddr); | 1602 | out_be32(&machine_data->diu_reg->desc[1], machine_data->dummy_ad->paddr); |
1588 | out_be32(&dr.diu_reg->desc[2], machine_data->dummy_ad->paddr); | 1603 | out_be32(&machine_data->diu_reg->desc[2], machine_data->dummy_ad->paddr); |
1589 | 1604 | ||
1590 | for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++) { | 1605 | for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++) { |
1591 | machine_data->fsl_diu_info[i]->fix.smem_start = 0; | 1606 | machine_data->fsl_diu_info[i]->fix.smem_start = 0; |
1592 | mfbi = machine_data->fsl_diu_info[i]->par; | 1607 | mfbi = machine_data->fsl_diu_info[i]->par; |
1593 | mfbi->ad = (struct diu_ad *)((u32)pool.ad.vaddr | 1608 | mfbi->ad = (struct diu_ad *)((u32)machine_data->ad.vaddr |
1594 | + pool.ad.offset) + i; | 1609 | + machine_data->ad.offset) + i; |
1595 | mfbi->ad->paddr = pool.ad.paddr + i * sizeof(struct diu_ad); | 1610 | mfbi->ad->paddr = |
1611 | machine_data->ad.paddr + i * sizeof(struct diu_ad); | ||
1596 | ret = install_fb(machine_data->fsl_diu_info[i]); | 1612 | ret = install_fb(machine_data->fsl_diu_info[i]); |
1597 | if (ret) { | 1613 | if (ret) { |
1598 | dev_err(&ofdev->dev, | 1614 | dev_err(&pdev->dev, "could not register fb %d\n", i); |
1599 | "Failed to register framebuffer %d\n", | ||
1600 | i); | ||
1601 | goto error; | 1615 | goto error; |
1602 | } | 1616 | } |
1603 | } | 1617 | } |
1604 | 1618 | ||
1605 | if (request_irq_local(machine_data->irq)) { | 1619 | if (request_irq_local(machine_data)) { |
1606 | dev_err(machine_data->fsl_diu_info[0]->dev, | 1620 | dev_err(&pdev->dev, "could not claim irq\n"); |
1607 | "could not request irq for diu."); | ||
1608 | goto error; | 1621 | goto error; |
1609 | } | 1622 | } |
1610 | 1623 | ||
@@ -1616,29 +1629,28 @@ static int __devinit fsl_diu_probe(struct platform_device *ofdev) | |||
1616 | error = device_create_file(machine_data->fsl_diu_info[0]->dev, | 1629 | error = device_create_file(machine_data->fsl_diu_info[0]->dev, |
1617 | &machine_data->dev_attr); | 1630 | &machine_data->dev_attr); |
1618 | if (error) { | 1631 | if (error) { |
1619 | dev_err(machine_data->fsl_diu_info[0]->dev, | 1632 | dev_err(&pdev->dev, "could not create sysfs file %s\n", |
1620 | "could not create sysfs %s file\n", | ||
1621 | machine_data->dev_attr.attr.name); | 1633 | machine_data->dev_attr.attr.name); |
1622 | } | 1634 | } |
1623 | 1635 | ||
1624 | dev_set_drvdata(&ofdev->dev, machine_data); | 1636 | dev_set_drvdata(&pdev->dev, machine_data); |
1625 | return 0; | 1637 | return 0; |
1626 | 1638 | ||
1627 | error: | 1639 | error: |
1628 | for (i = ARRAY_SIZE(machine_data->fsl_diu_info); | 1640 | for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++) |
1629 | i > 0; i--) | 1641 | uninstall_fb(machine_data->fsl_diu_info[i]); |
1630 | uninstall_fb(machine_data->fsl_diu_info[i - 1]); | 1642 | |
1631 | if (pool.ad.vaddr) | 1643 | if (machine_data->ad.vaddr) |
1632 | free_buf(&ofdev->dev, &pool.ad, | 1644 | free_buf(&pdev->dev, &machine_data->ad, |
1633 | sizeof(struct diu_ad) * FSL_AOI_NUM, 8); | 1645 | sizeof(struct diu_ad) * FSL_AOI_NUM, 8); |
1634 | if (pool.gamma.vaddr) | 1646 | if (machine_data->gamma.vaddr) |
1635 | free_buf(&ofdev->dev, &pool.gamma, 768, 32); | 1647 | free_buf(&pdev->dev, &machine_data->gamma, 768, 32); |
1636 | if (pool.cursor.vaddr) | 1648 | if (machine_data->cursor.vaddr) |
1637 | free_buf(&ofdev->dev, &pool.cursor, MAX_CURS * MAX_CURS * 2, | 1649 | free_buf(&pdev->dev, &machine_data->cursor, |
1638 | 32); | 1650 | MAX_CURS * MAX_CURS * 2, 32); |
1639 | if (machine_data->dummy_aoi_virt) | 1651 | if (machine_data->dummy_aoi_virt) |
1640 | fsl_diu_free(machine_data->dummy_aoi_virt, 64); | 1652 | fsl_diu_free(machine_data->dummy_aoi_virt, 64); |
1641 | iounmap(dr.diu_reg); | 1653 | iounmap(machine_data->diu_reg); |
1642 | 1654 | ||
1643 | error2: | 1655 | error2: |
1644 | for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++) | 1656 | for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++) |
@@ -1649,28 +1661,27 @@ error2: | |||
1649 | return ret; | 1661 | return ret; |
1650 | } | 1662 | } |
1651 | 1663 | ||
1652 | 1664 | static int fsl_diu_remove(struct platform_device *pdev) | |
1653 | static int fsl_diu_remove(struct platform_device *ofdev) | ||
1654 | { | 1665 | { |
1655 | struct fsl_diu_data *machine_data; | 1666 | struct fsl_diu_data *machine_data; |
1656 | int i; | 1667 | int i; |
1657 | 1668 | ||
1658 | machine_data = dev_get_drvdata(&ofdev->dev); | 1669 | machine_data = dev_get_drvdata(&pdev->dev); |
1659 | disable_lcdc(machine_data->fsl_diu_info[0]); | 1670 | disable_lcdc(machine_data->fsl_diu_info[0]); |
1660 | free_irq_local(machine_data->irq); | 1671 | free_irq_local(machine_data); |
1661 | for (i = ARRAY_SIZE(machine_data->fsl_diu_info); i > 0; i--) | 1672 | for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++) |
1662 | uninstall_fb(machine_data->fsl_diu_info[i - 1]); | 1673 | uninstall_fb(machine_data->fsl_diu_info[i]); |
1663 | if (pool.ad.vaddr) | 1674 | if (machine_data->ad.vaddr) |
1664 | free_buf(&ofdev->dev, &pool.ad, | 1675 | free_buf(&pdev->dev, &machine_data->ad, |
1665 | sizeof(struct diu_ad) * FSL_AOI_NUM, 8); | 1676 | sizeof(struct diu_ad) * FSL_AOI_NUM, 8); |
1666 | if (pool.gamma.vaddr) | 1677 | if (machine_data->gamma.vaddr) |
1667 | free_buf(&ofdev->dev, &pool.gamma, 768, 32); | 1678 | free_buf(&pdev->dev, &machine_data->gamma, 768, 32); |
1668 | if (pool.cursor.vaddr) | 1679 | if (machine_data->cursor.vaddr) |
1669 | free_buf(&ofdev->dev, &pool.cursor, MAX_CURS * MAX_CURS * 2, | 1680 | free_buf(&pdev->dev, &machine_data->cursor, |
1670 | 32); | 1681 | MAX_CURS * MAX_CURS * 2, 32); |
1671 | if (machine_data->dummy_aoi_virt) | 1682 | if (machine_data->dummy_aoi_virt) |
1672 | fsl_diu_free(machine_data->dummy_aoi_virt, 64); | 1683 | fsl_diu_free(machine_data->dummy_aoi_virt, 64); |
1673 | iounmap(dr.diu_reg); | 1684 | iounmap(machine_data->diu_reg); |
1674 | for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++) | 1685 | for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++) |
1675 | if (machine_data->fsl_diu_info[i]) | 1686 | if (machine_data->fsl_diu_info[i]) |
1676 | framebuffer_release(machine_data->fsl_diu_info[i]); | 1687 | framebuffer_release(machine_data->fsl_diu_info[i]); |
@@ -1692,8 +1703,7 @@ static int __init fsl_diu_setup(char *options) | |||
1692 | if (!*opt) | 1703 | if (!*opt) |
1693 | continue; | 1704 | continue; |
1694 | if (!strncmp(opt, "monitor=", 8)) { | 1705 | if (!strncmp(opt, "monitor=", 8)) { |
1695 | if (!strict_strtoul(opt + 8, 10, &val) && (val <= 2)) | 1706 | monitor_port = fsl_diu_name_to_port(opt + 8); |
1696 | monitor_port = val; | ||
1697 | } else if (!strncmp(opt, "bpp=", 4)) { | 1707 | } else if (!strncmp(opt, "bpp=", 4)) { |
1698 | if (!strict_strtoul(opt + 4, 10, &val)) | 1708 | if (!strict_strtoul(opt + 4, 10, &val)) |
1699 | default_bpp = val; | 1709 | default_bpp = val; |
@@ -1720,7 +1730,7 @@ MODULE_DEVICE_TABLE(of, fsl_diu_match); | |||
1720 | 1730 | ||
1721 | static struct platform_driver fsl_diu_driver = { | 1731 | static struct platform_driver fsl_diu_driver = { |
1722 | .driver = { | 1732 | .driver = { |
1723 | .name = "fsl_diu", | 1733 | .name = "fsl-diu-fb", |
1724 | .owner = THIS_MODULE, | 1734 | .owner = THIS_MODULE, |
1725 | .of_match_table = fsl_diu_match, | 1735 | .of_match_table = fsl_diu_match, |
1726 | }, | 1736 | }, |
@@ -1746,48 +1756,54 @@ static int __init fsl_diu_init(void) | |||
1746 | if (fb_get_options("fslfb", &option)) | 1756 | if (fb_get_options("fslfb", &option)) |
1747 | return -ENODEV; | 1757 | return -ENODEV; |
1748 | fsl_diu_setup(option); | 1758 | fsl_diu_setup(option); |
1759 | #else | ||
1760 | monitor_port = fsl_diu_name_to_port(monitor_string); | ||
1749 | #endif | 1761 | #endif |
1750 | printk(KERN_INFO "Freescale DIU driver\n"); | 1762 | pr_info("Freescale Display Interface Unit (DIU) framebuffer driver\n"); |
1751 | 1763 | ||
1752 | #ifdef CONFIG_NOT_COHERENT_CACHE | 1764 | #ifdef CONFIG_NOT_COHERENT_CACHE |
1753 | np = of_find_node_by_type(NULL, "cpu"); | 1765 | np = of_find_node_by_type(NULL, "cpu"); |
1754 | if (!np) { | 1766 | if (!np) { |
1755 | printk(KERN_ERR "Err: can't find device node 'cpu'\n"); | 1767 | pr_err("fsl-diu-fb: can't find 'cpu' device node\n"); |
1756 | return -ENODEV; | 1768 | return -ENODEV; |
1757 | } | 1769 | } |
1758 | 1770 | ||
1759 | prop = of_get_property(np, "d-cache-size", NULL); | 1771 | prop = of_get_property(np, "d-cache-size", NULL); |
1760 | if (prop == NULL) { | 1772 | if (prop == NULL) { |
1773 | pr_err("fsl-diu-fb: missing 'd-cache-size' property' " | ||
1774 | "in 'cpu' node\n"); | ||
1761 | of_node_put(np); | 1775 | of_node_put(np); |
1762 | return -ENODEV; | 1776 | return -ENODEV; |
1763 | } | 1777 | } |
1764 | 1778 | ||
1765 | /* Freescale PLRU requires 13/8 times the cache size to do a proper | 1779 | /* |
1766 | displacement flush | 1780 | * Freescale PLRU requires 13/8 times the cache size to do a proper |
1781 | * displacement flush | ||
1767 | */ | 1782 | */ |
1768 | coherence_data_size = *prop * 13; | 1783 | coherence_data_size = be32_to_cpup(prop) * 13; |
1769 | coherence_data_size /= 8; | 1784 | coherence_data_size /= 8; |
1770 | 1785 | ||
1771 | prop = of_get_property(np, "d-cache-line-size", NULL); | 1786 | prop = of_get_property(np, "d-cache-line-size", NULL); |
1772 | if (prop == NULL) { | 1787 | if (prop == NULL) { |
1788 | pr_err("fsl-diu-fb: missing 'd-cache-line-size' property' " | ||
1789 | "in 'cpu' node\n"); | ||
1773 | of_node_put(np); | 1790 | of_node_put(np); |
1774 | return -ENODEV; | 1791 | return -ENODEV; |
1775 | } | 1792 | } |
1776 | d_cache_line_size = *prop; | 1793 | d_cache_line_size = be32_to_cpup(prop); |
1777 | 1794 | ||
1778 | of_node_put(np); | 1795 | of_node_put(np); |
1779 | coherence_data = vmalloc(coherence_data_size); | 1796 | coherence_data = vmalloc(coherence_data_size); |
1780 | if (!coherence_data) | 1797 | if (!coherence_data) |
1781 | return -ENOMEM; | 1798 | return -ENOMEM; |
1782 | #endif | 1799 | #endif |
1800 | |||
1783 | ret = platform_driver_register(&fsl_diu_driver); | 1801 | ret = platform_driver_register(&fsl_diu_driver); |
1784 | if (ret) { | 1802 | if (ret) { |
1785 | printk(KERN_ERR | 1803 | pr_err("fsl-diu-fb: failed to register platform driver\n"); |
1786 | "fsl-diu: failed to register platform driver\n"); | ||
1787 | #if defined(CONFIG_NOT_COHERENT_CACHE) | 1804 | #if defined(CONFIG_NOT_COHERENT_CACHE) |
1788 | vfree(coherence_data); | 1805 | vfree(coherence_data); |
1789 | #endif | 1806 | #endif |
1790 | iounmap(dr.diu_reg); | ||
1791 | } | 1807 | } |
1792 | return ret; | 1808 | return ret; |
1793 | } | 1809 | } |
@@ -1811,8 +1827,8 @@ module_param_named(mode, fb_mode, charp, 0); | |||
1811 | MODULE_PARM_DESC(mode, | 1827 | MODULE_PARM_DESC(mode, |
1812 | "Specify resolution as \"<xres>x<yres>[-<bpp>][@<refresh>]\" "); | 1828 | "Specify resolution as \"<xres>x<yres>[-<bpp>][@<refresh>]\" "); |
1813 | module_param_named(bpp, default_bpp, ulong, 0); | 1829 | module_param_named(bpp, default_bpp, ulong, 0); |
1814 | MODULE_PARM_DESC(bpp, "Specify bit-per-pixel if not specified mode"); | 1830 | MODULE_PARM_DESC(bpp, "Specify bit-per-pixel if not specified in 'mode'"); |
1815 | module_param_named(monitor, monitor_port, int, 0); | 1831 | module_param_named(monitor, monitor_string, charp, 0); |
1816 | MODULE_PARM_DESC(monitor, | 1832 | MODULE_PARM_DESC(monitor, "Specify the monitor port " |
1817 | "Specify the monitor port (0, 1 or 2) if supported by the platform"); | 1833 | "(\"dvi\", \"lvds\", or \"dlvds\") if supported by the platform"); |
1818 | 1834 | ||
diff --git a/drivers/video/g364fb.c b/drivers/video/g364fb.c index d662317d85e3..223896cc5f7d 100644 --- a/drivers/video/g364fb.c +++ b/drivers/video/g364fb.c | |||
@@ -149,10 +149,11 @@ int g364fb_cursor(struct fb_info *info, struct fb_cursor *cursor) | |||
149 | static int g364fb_pan_display(struct fb_var_screeninfo *var, | 149 | static int g364fb_pan_display(struct fb_var_screeninfo *var, |
150 | struct fb_info *info) | 150 | struct fb_info *info) |
151 | { | 151 | { |
152 | if (var->xoffset || var->yoffset + var->yres > var->yres_virtual) | 152 | if (var->xoffset || |
153 | var->yoffset + info->var.yres > info->var.yres_virtual) | ||
153 | return -EINVAL; | 154 | return -EINVAL; |
154 | 155 | ||
155 | *(unsigned int *) TOP_REG = var->yoffset * var->xres; | 156 | *(unsigned int *) TOP_REG = var->yoffset * info->var.xres; |
156 | return 0; | 157 | return 0; |
157 | } | 158 | } |
158 | 159 | ||
diff --git a/drivers/video/grvga.c b/drivers/video/grvga.c new file mode 100644 index 000000000000..f37e02538203 --- /dev/null +++ b/drivers/video/grvga.c | |||
@@ -0,0 +1,579 @@ | |||
1 | /* | ||
2 | * Driver for Aeroflex Gaisler SVGACTRL framebuffer device. | ||
3 | * | ||
4 | * 2011 (c) Aeroflex Gaisler AB | ||
5 | * | ||
6 | * Full documentation of the core can be found here: | ||
7 | * http://www.gaisler.com/products/grlib/grip.pdf | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License as published by the | ||
11 | * Free Software Foundation; either version 2 of the License, or (at your | ||
12 | * option) any later version. | ||
13 | * | ||
14 | * Contributors: Kristoffer Glembo <kristoffer@gaisler.com> | ||
15 | * | ||
16 | */ | ||
17 | |||
18 | #include <linux/platform_device.h> | ||
19 | #include <linux/dma-mapping.h> | ||
20 | #include <linux/of_platform.h> | ||
21 | #include <linux/of_device.h> | ||
22 | #include <linux/module.h> | ||
23 | #include <linux/kernel.h> | ||
24 | #include <linux/string.h> | ||
25 | #include <linux/delay.h> | ||
26 | #include <linux/errno.h> | ||
27 | #include <linux/init.h> | ||
28 | #include <linux/slab.h> | ||
29 | #include <linux/tty.h> | ||
30 | #include <linux/mm.h> | ||
31 | #include <linux/fb.h> | ||
32 | #include <linux/io.h> | ||
33 | |||
34 | struct grvga_regs { | ||
35 | u32 status; /* 0x00 */ | ||
36 | u32 video_length; /* 0x04 */ | ||
37 | u32 front_porch; /* 0x08 */ | ||
38 | u32 sync_length; /* 0x0C */ | ||
39 | u32 line_length; /* 0x10 */ | ||
40 | u32 fb_pos; /* 0x14 */ | ||
41 | u32 clk_vector[4]; /* 0x18 */ | ||
42 | u32 clut; /* 0x20 */ | ||
43 | }; | ||
44 | |||
45 | struct grvga_par { | ||
46 | struct grvga_regs *regs; | ||
47 | u32 color_palette[16]; /* 16 entry pseudo palette used by fbcon in true color mode */ | ||
48 | int clk_sel; | ||
49 | int fb_alloced; /* = 1 if framebuffer is allocated in main memory */ | ||
50 | }; | ||
51 | |||
52 | |||
53 | static const struct fb_videomode grvga_modedb[] = { | ||
54 | { | ||
55 | /* 640x480 @ 60 Hz */ | ||
56 | NULL, 60, 640, 480, 40000, 48, 16, 39, 11, 96, 2, | ||
57 | 0, FB_VMODE_NONINTERLACED | ||
58 | }, { | ||
59 | /* 800x600 @ 60 Hz */ | ||
60 | NULL, 60, 800, 600, 25000, 88, 40, 23, 1, 128, 4, | ||
61 | 0, FB_VMODE_NONINTERLACED | ||
62 | }, { | ||
63 | /* 800x600 @ 72 Hz */ | ||
64 | NULL, 72, 800, 600, 20000, 64, 56, 23, 37, 120, 6, | ||
65 | 0, FB_VMODE_NONINTERLACED | ||
66 | }, { | ||
67 | /* 1024x768 @ 60 Hz */ | ||
68 | NULL, 60, 1024, 768, 15385, 160, 24, 29, 3, 136, 6, | ||
69 | 0, FB_VMODE_NONINTERLACED | ||
70 | } | ||
71 | }; | ||
72 | |||
73 | static struct fb_fix_screeninfo grvga_fix __initdata = { | ||
74 | .id = "AG SVGACTRL", | ||
75 | .type = FB_TYPE_PACKED_PIXELS, | ||
76 | .visual = FB_VISUAL_PSEUDOCOLOR, | ||
77 | .xpanstep = 0, | ||
78 | .ypanstep = 1, | ||
79 | .ywrapstep = 0, | ||
80 | .accel = FB_ACCEL_NONE, | ||
81 | }; | ||
82 | |||
83 | static int grvga_check_var(struct fb_var_screeninfo *var, | ||
84 | struct fb_info *info) | ||
85 | { | ||
86 | struct grvga_par *par = info->par; | ||
87 | int i; | ||
88 | |||
89 | if (!var->xres) | ||
90 | var->xres = 1; | ||
91 | if (!var->yres) | ||
92 | var->yres = 1; | ||
93 | if (var->bits_per_pixel <= 8) | ||
94 | var->bits_per_pixel = 8; | ||
95 | else if (var->bits_per_pixel <= 16) | ||
96 | var->bits_per_pixel = 16; | ||
97 | else if (var->bits_per_pixel <= 24) | ||
98 | var->bits_per_pixel = 24; | ||
99 | else if (var->bits_per_pixel <= 32) | ||
100 | var->bits_per_pixel = 32; | ||
101 | else | ||
102 | return -EINVAL; | ||
103 | |||
104 | var->xres_virtual = var->xres; | ||
105 | var->yres_virtual = 2*var->yres; | ||
106 | |||
107 | if (info->fix.smem_len) { | ||
108 | if ((var->yres_virtual*var->xres_virtual*var->bits_per_pixel/8) > info->fix.smem_len) | ||
109 | return -ENOMEM; | ||
110 | } | ||
111 | |||
112 | /* Which clocks that are available can be read out in these registers */ | ||
113 | for (i = 0; i <= 3 ; i++) { | ||
114 | if (var->pixclock == par->regs->clk_vector[i]) | ||
115 | break; | ||
116 | } | ||
117 | if (i <= 3) | ||
118 | par->clk_sel = i; | ||
119 | else | ||
120 | return -EINVAL; | ||
121 | |||
122 | switch (info->var.bits_per_pixel) { | ||
123 | case 8: | ||
124 | var->red = (struct fb_bitfield) {0, 8, 0}; /* offset, length, msb-right */ | ||
125 | var->green = (struct fb_bitfield) {0, 8, 0}; | ||
126 | var->blue = (struct fb_bitfield) {0, 8, 0}; | ||
127 | var->transp = (struct fb_bitfield) {0, 0, 0}; | ||
128 | break; | ||
129 | case 16: | ||
130 | var->red = (struct fb_bitfield) {11, 5, 0}; | ||
131 | var->green = (struct fb_bitfield) {5, 6, 0}; | ||
132 | var->blue = (struct fb_bitfield) {0, 5, 0}; | ||
133 | var->transp = (struct fb_bitfield) {0, 0, 0}; | ||
134 | break; | ||
135 | case 24: | ||
136 | case 32: | ||
137 | var->red = (struct fb_bitfield) {16, 8, 0}; | ||
138 | var->green = (struct fb_bitfield) {8, 8, 0}; | ||
139 | var->blue = (struct fb_bitfield) {0, 8, 0}; | ||
140 | var->transp = (struct fb_bitfield) {24, 8, 0}; | ||
141 | break; | ||
142 | default: | ||
143 | return -EINVAL; | ||
144 | } | ||
145 | |||
146 | return 0; | ||
147 | } | ||
148 | |||
149 | static int grvga_set_par(struct fb_info *info) | ||
150 | { | ||
151 | |||
152 | u32 func = 0; | ||
153 | struct grvga_par *par = info->par; | ||
154 | |||
155 | __raw_writel(((info->var.yres - 1) << 16) | (info->var.xres - 1), | ||
156 | &par->regs->video_length); | ||
157 | |||
158 | __raw_writel((info->var.lower_margin << 16) | (info->var.right_margin), | ||
159 | &par->regs->front_porch); | ||
160 | |||
161 | __raw_writel((info->var.vsync_len << 16) | (info->var.hsync_len), | ||
162 | &par->regs->sync_length); | ||
163 | |||
164 | __raw_writel(((info->var.yres + info->var.lower_margin + info->var.upper_margin + info->var.vsync_len - 1) << 16) | | ||
165 | (info->var.xres + info->var.right_margin + info->var.left_margin + info->var.hsync_len - 1), | ||
166 | &par->regs->line_length); | ||
167 | |||
168 | switch (info->var.bits_per_pixel) { | ||
169 | case 8: | ||
170 | info->fix.visual = FB_VISUAL_PSEUDOCOLOR; | ||
171 | func = 1; | ||
172 | break; | ||
173 | case 16: | ||
174 | info->fix.visual = FB_VISUAL_TRUECOLOR; | ||
175 | func = 2; | ||
176 | break; | ||
177 | case 24: | ||
178 | case 32: | ||
179 | info->fix.visual = FB_VISUAL_TRUECOLOR; | ||
180 | func = 3; | ||
181 | break; | ||
182 | default: | ||
183 | return -EINVAL; | ||
184 | } | ||
185 | |||
186 | __raw_writel((par->clk_sel << 6) | (func << 4) | 1, | ||
187 | &par->regs->status); | ||
188 | |||
189 | info->fix.line_length = (info->var.xres_virtual*info->var.bits_per_pixel)/8; | ||
190 | return 0; | ||
191 | } | ||
192 | |||
193 | static int grvga_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *info) | ||
194 | { | ||
195 | struct grvga_par *par; | ||
196 | par = info->par; | ||
197 | |||
198 | if (regno >= 256) /* Size of CLUT */ | ||
199 | return -EINVAL; | ||
200 | |||
201 | if (info->var.grayscale) { | ||
202 | /* grayscale = 0.30*R + 0.59*G + 0.11*B */ | ||
203 | red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8; | ||
204 | } | ||
205 | |||
206 | |||
207 | |||
208 | #define CNVT_TOHW(val, width) ((((val)<<(width))+0x7FFF-(val))>>16) | ||
209 | |||
210 | red = CNVT_TOHW(red, info->var.red.length); | ||
211 | green = CNVT_TOHW(green, info->var.green.length); | ||
212 | blue = CNVT_TOHW(blue, info->var.blue.length); | ||
213 | transp = CNVT_TOHW(transp, info->var.transp.length); | ||
214 | |||
215 | #undef CNVT_TOHW | ||
216 | |||
217 | /* In PSEUDOCOLOR we use the hardware CLUT */ | ||
218 | if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR) | ||
219 | __raw_writel((regno << 24) | (red << 16) | (green << 8) | blue, | ||
220 | &par->regs->clut); | ||
221 | |||
222 | /* Truecolor uses the pseudo palette */ | ||
223 | else if (info->fix.visual == FB_VISUAL_TRUECOLOR) { | ||
224 | u32 v; | ||
225 | if (regno >= 16) | ||
226 | return -EINVAL; | ||
227 | |||
228 | |||
229 | v = (red << info->var.red.offset) | | ||
230 | (green << info->var.green.offset) | | ||
231 | (blue << info->var.blue.offset) | | ||
232 | (transp << info->var.transp.offset); | ||
233 | |||
234 | ((u32 *) (info->pseudo_palette))[regno] = v; | ||
235 | } | ||
236 | return 0; | ||
237 | } | ||
238 | |||
239 | static int grvga_pan_display(struct fb_var_screeninfo *var, | ||
240 | struct fb_info *info) | ||
241 | { | ||
242 | struct grvga_par *par = info->par; | ||
243 | struct fb_fix_screeninfo *fix = &info->fix; | ||
244 | u32 base_addr; | ||
245 | |||
246 | if (var->xoffset != 0) | ||
247 | return -EINVAL; | ||
248 | |||
249 | base_addr = fix->smem_start + (var->yoffset * fix->line_length); | ||
250 | base_addr &= ~3UL; | ||
251 | |||
252 | /* Set framebuffer base address */ | ||
253 | __raw_writel(base_addr, | ||
254 | &par->regs->fb_pos); | ||
255 | |||
256 | return 0; | ||
257 | } | ||
258 | |||
259 | static struct fb_ops grvga_ops = { | ||
260 | .owner = THIS_MODULE, | ||
261 | .fb_check_var = grvga_check_var, | ||
262 | .fb_set_par = grvga_set_par, | ||
263 | .fb_setcolreg = grvga_setcolreg, | ||
264 | .fb_pan_display = grvga_pan_display, | ||
265 | .fb_fillrect = cfb_fillrect, | ||
266 | .fb_copyarea = cfb_copyarea, | ||
267 | .fb_imageblit = cfb_imageblit | ||
268 | }; | ||
269 | |||
270 | static int __init grvga_parse_custom(char *options, | ||
271 | struct fb_var_screeninfo *screendata) | ||
272 | { | ||
273 | char *this_opt; | ||
274 | int count = 0; | ||
275 | if (!options || !*options) | ||
276 | return -1; | ||
277 | |||
278 | while ((this_opt = strsep(&options, " ")) != NULL) { | ||
279 | if (!*this_opt) | ||
280 | continue; | ||
281 | |||
282 | switch (count) { | ||
283 | case 0: | ||
284 | screendata->pixclock = simple_strtoul(this_opt, NULL, 0); | ||
285 | count++; | ||
286 | break; | ||
287 | case 1: | ||
288 | screendata->xres = screendata->xres_virtual = simple_strtoul(this_opt, NULL, 0); | ||
289 | count++; | ||
290 | break; | ||
291 | case 2: | ||
292 | screendata->right_margin = simple_strtoul(this_opt, NULL, 0); | ||
293 | count++; | ||
294 | break; | ||
295 | case 3: | ||
296 | screendata->hsync_len = simple_strtoul(this_opt, NULL, 0); | ||
297 | count++; | ||
298 | break; | ||
299 | case 4: | ||
300 | screendata->left_margin = simple_strtoul(this_opt, NULL, 0); | ||
301 | count++; | ||
302 | break; | ||
303 | case 5: | ||
304 | screendata->yres = screendata->yres_virtual = simple_strtoul(this_opt, NULL, 0); | ||
305 | count++; | ||
306 | break; | ||
307 | case 6: | ||
308 | screendata->lower_margin = simple_strtoul(this_opt, NULL, 0); | ||
309 | count++; | ||
310 | break; | ||
311 | case 7: | ||
312 | screendata->vsync_len = simple_strtoul(this_opt, NULL, 0); | ||
313 | count++; | ||
314 | break; | ||
315 | case 8: | ||
316 | screendata->upper_margin = simple_strtoul(this_opt, NULL, 0); | ||
317 | count++; | ||
318 | break; | ||
319 | case 9: | ||
320 | screendata->bits_per_pixel = simple_strtoul(this_opt, NULL, 0); | ||
321 | count++; | ||
322 | break; | ||
323 | default: | ||
324 | return -1; | ||
325 | } | ||
326 | } | ||
327 | screendata->activate = FB_ACTIVATE_NOW; | ||
328 | screendata->vmode = FB_VMODE_NONINTERLACED; | ||
329 | return 0; | ||
330 | } | ||
331 | |||
332 | static int __devinit grvga_probe(struct platform_device *dev) | ||
333 | { | ||
334 | struct fb_info *info; | ||
335 | int retval = -ENOMEM; | ||
336 | unsigned long virtual_start; | ||
337 | unsigned long grvga_fix_addr = 0; | ||
338 | unsigned long physical_start = 0; | ||
339 | unsigned long grvga_mem_size = 0; | ||
340 | struct grvga_par *par = NULL; | ||
341 | char *options = NULL, *mode_opt = NULL; | ||
342 | |||
343 | info = framebuffer_alloc(sizeof(struct grvga_par), &dev->dev); | ||
344 | if (!info) { | ||
345 | dev_err(&dev->dev, "framebuffer_alloc failed\n"); | ||
346 | return -ENOMEM; | ||
347 | } | ||
348 | |||
349 | /* Expecting: "grvga: modestring, [addr:<framebuffer physical address>], [size:<framebuffer size>] | ||
350 | * | ||
351 | * If modestring is custom:<custom mode string> we parse the string which then contains all videoparameters | ||
352 | * If address is left out, we allocate memory, | ||
353 | * if size is left out we only allocate enough to support the given mode. | ||
354 | */ | ||
355 | if (fb_get_options("grvga", &options)) { | ||
356 | retval = -ENODEV; | ||
357 | goto err; | ||
358 | } | ||
359 | |||
360 | if (!options || !*options) | ||
361 | options = "640x480-8@60"; | ||
362 | |||
363 | while (1) { | ||
364 | char *this_opt = strsep(&options, ","); | ||
365 | |||
366 | if (!this_opt) | ||
367 | break; | ||
368 | |||
369 | if (!strncmp(this_opt, "custom", 6)) { | ||
370 | if (grvga_parse_custom(this_opt, &info->var) < 0) { | ||
371 | dev_err(&dev->dev, "Failed to parse custom mode (%s).\n", this_opt); | ||
372 | retval = -EINVAL; | ||
373 | goto err1; | ||
374 | } | ||
375 | } else if (!strncmp(this_opt, "addr", 4)) | ||
376 | grvga_fix_addr = simple_strtoul(this_opt + 5, NULL, 16); | ||
377 | else if (!strncmp(this_opt, "size", 4)) | ||
378 | grvga_mem_size = simple_strtoul(this_opt + 5, NULL, 0); | ||
379 | else | ||
380 | mode_opt = this_opt; | ||
381 | } | ||
382 | |||
383 | par = info->par; | ||
384 | info->fbops = &grvga_ops; | ||
385 | info->fix = grvga_fix; | ||
386 | info->pseudo_palette = par->color_palette; | ||
387 | info->flags = FBINFO_DEFAULT | FBINFO_PARTIAL_PAN_OK | FBINFO_HWACCEL_YPAN; | ||
388 | info->fix.smem_len = grvga_mem_size; | ||
389 | |||
390 | if (!request_mem_region(dev->resource[0].start, resource_size(&dev->resource[0]), "grlib-svgactrl regs")) { | ||
391 | dev_err(&dev->dev, "registers already mapped\n"); | ||
392 | retval = -EBUSY; | ||
393 | goto err; | ||
394 | } | ||
395 | |||
396 | par->regs = of_ioremap(&dev->resource[0], 0, | ||
397 | resource_size(&dev->resource[0]), | ||
398 | "grlib-svgactrl regs"); | ||
399 | |||
400 | if (!par->regs) { | ||
401 | dev_err(&dev->dev, "failed to map registers\n"); | ||
402 | retval = -ENOMEM; | ||
403 | goto err1; | ||
404 | } | ||
405 | |||
406 | retval = fb_alloc_cmap(&info->cmap, 256, 0); | ||
407 | if (retval < 0) { | ||
408 | dev_err(&dev->dev, "failed to allocate mem with fb_alloc_cmap\n"); | ||
409 | retval = -ENOMEM; | ||
410 | goto err2; | ||
411 | } | ||
412 | |||
413 | if (mode_opt) { | ||
414 | retval = fb_find_mode(&info->var, info, mode_opt, | ||
415 | grvga_modedb, sizeof(grvga_modedb), &grvga_modedb[0], 8); | ||
416 | if (!retval || retval == 4) { | ||
417 | retval = -EINVAL; | ||
418 | goto err3; | ||
419 | } | ||
420 | } | ||
421 | |||
422 | if (!grvga_mem_size) | ||
423 | grvga_mem_size = info->var.xres_virtual * info->var.yres_virtual * info->var.bits_per_pixel/8; | ||
424 | |||
425 | if (grvga_fix_addr) { | ||
426 | /* Got framebuffer base address from argument list */ | ||
427 | |||
428 | physical_start = grvga_fix_addr; | ||
429 | |||
430 | if (!request_mem_region(physical_start, grvga_mem_size, dev->name)) { | ||
431 | dev_err(&dev->dev, "failed to request memory region\n"); | ||
432 | retval = -ENOMEM; | ||
433 | goto err3; | ||
434 | } | ||
435 | |||
436 | virtual_start = (unsigned long) ioremap(physical_start, grvga_mem_size); | ||
437 | |||
438 | if (!virtual_start) { | ||
439 | dev_err(&dev->dev, "error mapping framebuffer memory\n"); | ||
440 | retval = -ENOMEM; | ||
441 | goto err4; | ||
442 | } | ||
443 | } else { /* Allocate frambuffer memory */ | ||
444 | |||
445 | unsigned long page; | ||
446 | |||
447 | virtual_start = (unsigned long) __get_free_pages(GFP_DMA, | ||
448 | get_order(grvga_mem_size)); | ||
449 | if (!virtual_start) { | ||
450 | dev_err(&dev->dev, | ||
451 | "unable to allocate framebuffer memory (%lu bytes)\n", | ||
452 | grvga_mem_size); | ||
453 | retval = -ENOMEM; | ||
454 | goto err3; | ||
455 | } | ||
456 | |||
457 | physical_start = dma_map_single(&dev->dev, (void *)virtual_start, grvga_mem_size, DMA_TO_DEVICE); | ||
458 | |||
459 | /* Set page reserved so that mmap will work. This is necessary | ||
460 | * since we'll be remapping normal memory. | ||
461 | */ | ||
462 | for (page = virtual_start; | ||
463 | page < PAGE_ALIGN(virtual_start + grvga_mem_size); | ||
464 | page += PAGE_SIZE) { | ||
465 | SetPageReserved(virt_to_page(page)); | ||
466 | } | ||
467 | |||
468 | par->fb_alloced = 1; | ||
469 | } | ||
470 | |||
471 | memset((unsigned long *) virtual_start, 0, grvga_mem_size); | ||
472 | |||
473 | info->screen_base = (char __iomem *) virtual_start; | ||
474 | info->fix.smem_start = physical_start; | ||
475 | info->fix.smem_len = grvga_mem_size; | ||
476 | |||
477 | dev_set_drvdata(&dev->dev, info); | ||
478 | |||
479 | dev_info(&dev->dev, | ||
480 | "Aeroflex Gaisler framebuffer device (fb%d), %dx%d-%d, using %luK of video memory @ %p\n", | ||
481 | info->node, info->var.xres, info->var.yres, info->var.bits_per_pixel, | ||
482 | grvga_mem_size >> 10, info->screen_base); | ||
483 | |||
484 | retval = register_framebuffer(info); | ||
485 | if (retval < 0) { | ||
486 | dev_err(&dev->dev, "failed to register framebuffer\n"); | ||
487 | goto err4; | ||
488 | } | ||
489 | |||
490 | __raw_writel(physical_start, &par->regs->fb_pos); | ||
491 | __raw_writel(__raw_readl(&par->regs->status) | 1, /* Enable framebuffer */ | ||
492 | &par->regs->status); | ||
493 | |||
494 | return 0; | ||
495 | |||
496 | err4: | ||
497 | dev_set_drvdata(&dev->dev, NULL); | ||
498 | if (grvga_fix_addr) { | ||
499 | release_mem_region(physical_start, grvga_mem_size); | ||
500 | iounmap((void *)virtual_start); | ||
501 | } else | ||
502 | kfree((void *)virtual_start); | ||
503 | err3: | ||
504 | fb_dealloc_cmap(&info->cmap); | ||
505 | err2: | ||
506 | of_iounmap(&dev->resource[0], par->regs, | ||
507 | resource_size(&dev->resource[0])); | ||
508 | err1: | ||
509 | release_mem_region(dev->resource[0].start, resource_size(&dev->resource[0])); | ||
510 | err: | ||
511 | framebuffer_release(info); | ||
512 | |||
513 | return retval; | ||
514 | } | ||
515 | |||
516 | static int __devexit grvga_remove(struct platform_device *device) | ||
517 | { | ||
518 | struct fb_info *info = dev_get_drvdata(&device->dev); | ||
519 | struct grvga_par *par = info->par; | ||
520 | |||
521 | if (info) { | ||
522 | unregister_framebuffer(info); | ||
523 | fb_dealloc_cmap(&info->cmap); | ||
524 | |||
525 | of_iounmap(&device->resource[0], par->regs, | ||
526 | resource_size(&device->resource[0])); | ||
527 | release_mem_region(device->resource[0].start, resource_size(&device->resource[0])); | ||
528 | |||
529 | if (!par->fb_alloced) { | ||
530 | release_mem_region(info->fix.smem_start, info->fix.smem_len); | ||
531 | iounmap(info->screen_base); | ||
532 | } else | ||
533 | kfree((void *)info->screen_base); | ||
534 | |||
535 | framebuffer_release(info); | ||
536 | dev_set_drvdata(&device->dev, NULL); | ||
537 | } | ||
538 | |||
539 | return 0; | ||
540 | } | ||
541 | |||
542 | static struct of_device_id svgactrl_of_match[] = { | ||
543 | { | ||
544 | .name = "GAISLER_SVGACTRL", | ||
545 | }, | ||
546 | { | ||
547 | .name = "01_063", | ||
548 | }, | ||
549 | {}, | ||
550 | }; | ||
551 | MODULE_DEVICE_TABLE(of, svgactrl_of_match); | ||
552 | |||
553 | static struct platform_driver grvga_driver = { | ||
554 | .driver = { | ||
555 | .name = "grlib-svgactrl", | ||
556 | .owner = THIS_MODULE, | ||
557 | .of_match_table = svgactrl_of_match, | ||
558 | }, | ||
559 | .probe = grvga_probe, | ||
560 | .remove = __devexit_p(grvga_remove), | ||
561 | }; | ||
562 | |||
563 | |||
564 | static int __init grvga_init(void) | ||
565 | { | ||
566 | return platform_driver_register(&grvga_driver); | ||
567 | } | ||
568 | |||
569 | static void __exit grvga_exit(void) | ||
570 | { | ||
571 | platform_driver_unregister(&grvga_driver); | ||
572 | } | ||
573 | |||
574 | module_init(grvga_init); | ||
575 | module_exit(grvga_exit); | ||
576 | |||
577 | MODULE_LICENSE("GPL"); | ||
578 | MODULE_AUTHOR("Aeroflex Gaisler"); | ||
579 | MODULE_DESCRIPTION("Aeroflex Gaisler framebuffer device driver"); | ||
diff --git a/drivers/video/gxt4500.c b/drivers/video/gxt4500.c index 896e53dea906..0fad23f810a3 100644 --- a/drivers/video/gxt4500.c +++ b/drivers/video/gxt4500.c | |||
@@ -543,8 +543,8 @@ static int gxt4500_pan_display(struct fb_var_screeninfo *var, | |||
543 | 543 | ||
544 | if (var->xoffset & 7) | 544 | if (var->xoffset & 7) |
545 | return -EINVAL; | 545 | return -EINVAL; |
546 | if (var->xoffset + var->xres > var->xres_virtual || | 546 | if (var->xoffset + info->var.xres > info->var.xres_virtual || |
547 | var->yoffset + var->yres > var->yres_virtual) | 547 | var->yoffset + info->var.yres > info->var.yres_virtual) |
548 | return -EINVAL; | 548 | return -EINVAL; |
549 | 549 | ||
550 | writereg(par, REFRESH_START, (var->xoffset << 16) | var->yoffset); | 550 | writereg(par, REFRESH_START, (var->xoffset << 16) | var->yoffset); |
diff --git a/drivers/video/hgafb.c b/drivers/video/hgafb.c index 4052718eefaa..4394389caf68 100644 --- a/drivers/video/hgafb.c +++ b/drivers/video/hgafb.c | |||
@@ -422,8 +422,8 @@ static int hgafb_pan_display(struct fb_var_screeninfo *var, | |||
422 | var->xoffset) | 422 | var->xoffset) |
423 | return -EINVAL; | 423 | return -EINVAL; |
424 | } else { | 424 | } else { |
425 | if (var->xoffset + var->xres > info->var.xres_virtual | 425 | if (var->xoffset + info->var.xres > info->var.xres_virtual |
426 | || var->yoffset + var->yres > info->var.yres_virtual | 426 | || var->yoffset + info->var.yres > info->var.yres_virtual |
427 | || var->yoffset % 8) | 427 | || var->yoffset % 8) |
428 | return -EINVAL; | 428 | return -EINVAL; |
429 | } | 429 | } |
diff --git a/drivers/video/imsttfb.c b/drivers/video/imsttfb.c index efb2c10656b0..8149356471e4 100644 --- a/drivers/video/imsttfb.c +++ b/drivers/video/imsttfb.c | |||
@@ -749,7 +749,7 @@ set_offset (struct fb_var_screeninfo *var, struct fb_info *info) | |||
749 | { | 749 | { |
750 | struct imstt_par *par = info->par; | 750 | struct imstt_par *par = info->par; |
751 | __u32 off = var->yoffset * (info->fix.line_length >> 3) | 751 | __u32 off = var->yoffset * (info->fix.line_length >> 3) |
752 | + ((var->xoffset * (var->bits_per_pixel >> 3)) >> 3); | 752 | + ((var->xoffset * (info->var.bits_per_pixel >> 3)) >> 3); |
753 | write_reg_le32(par->dc_regs, SSR, off); | 753 | write_reg_le32(par->dc_regs, SSR, off); |
754 | } | 754 | } |
755 | 755 | ||
diff --git a/drivers/video/intelfb/intelfbhw.c b/drivers/video/intelfb/intelfbhw.c index 38065cf94ac4..fbad61da359f 100644 --- a/drivers/video/intelfb/intelfbhw.c +++ b/drivers/video/intelfb/intelfbhw.c | |||
@@ -390,12 +390,12 @@ int intelfbhw_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) | |||
390 | xoffset = ROUND_DOWN_TO(var->xoffset, 8); | 390 | xoffset = ROUND_DOWN_TO(var->xoffset, 8); |
391 | yoffset = var->yoffset; | 391 | yoffset = var->yoffset; |
392 | 392 | ||
393 | if ((xoffset + var->xres > var->xres_virtual) || | 393 | if ((xoffset + info->var.xres > info->var.xres_virtual) || |
394 | (yoffset + var->yres > var->yres_virtual)) | 394 | (yoffset + info->var.yres > info->var.yres_virtual)) |
395 | return -EINVAL; | 395 | return -EINVAL; |
396 | 396 | ||
397 | offset = (yoffset * dinfo->pitch) + | 397 | offset = (yoffset * dinfo->pitch) + |
398 | (xoffset * var->bits_per_pixel) / 8; | 398 | (xoffset * info->var.bits_per_pixel) / 8; |
399 | 399 | ||
400 | offset += dinfo->fb.offset << 12; | 400 | offset += dinfo->fb.offset << 12; |
401 | 401 | ||
diff --git a/drivers/video/mb862xx/mb862xx-i2c.c b/drivers/video/mb862xx/mb862xx-i2c.c index b953099edd8e..934081d2b7ae 100644 --- a/drivers/video/mb862xx/mb862xx-i2c.c +++ b/drivers/video/mb862xx/mb862xx-i2c.c | |||
@@ -23,7 +23,7 @@ static int mb862xx_i2c_wait_event(struct i2c_adapter *adap) | |||
23 | u32 reg; | 23 | u32 reg; |
24 | 24 | ||
25 | do { | 25 | do { |
26 | udelay(1); | 26 | udelay(10); |
27 | reg = inreg(i2c, GC_I2C_BCR); | 27 | reg = inreg(i2c, GC_I2C_BCR); |
28 | if (reg & (I2C_INT | I2C_BER)) | 28 | if (reg & (I2C_INT | I2C_BER)) |
29 | break; | 29 | break; |
diff --git a/drivers/video/mb862xx/mb862xxfbdrv.c b/drivers/video/mb862xx/mb862xxfbdrv.c index ee1de3e26dec..c16ff1d62e91 100644 --- a/drivers/video/mb862xx/mb862xxfbdrv.c +++ b/drivers/video/mb862xx/mb862xxfbdrv.c | |||
@@ -278,7 +278,7 @@ static int mb862xxfb_pan(struct fb_var_screeninfo *var, | |||
278 | reg = pack(var->yoffset, var->xoffset); | 278 | reg = pack(var->yoffset, var->xoffset); |
279 | outreg(disp, GC_L0WY_L0WX, reg); | 279 | outreg(disp, GC_L0WY_L0WX, reg); |
280 | 280 | ||
281 | reg = pack(var->yres_virtual, var->xres_virtual); | 281 | reg = pack(info->var.yres_virtual, info->var.xres_virtual); |
282 | outreg(disp, GC_L0WH_L0WW, reg); | 282 | outreg(disp, GC_L0WH_L0WW, reg); |
283 | return 0; | 283 | return 0; |
284 | } | 284 | } |
@@ -737,7 +737,7 @@ static int __devinit of_platform_mb862xx_probe(struct platform_device *ofdev) | |||
737 | if (mb862xx_gdc_init(par)) | 737 | if (mb862xx_gdc_init(par)) |
738 | goto io_unmap; | 738 | goto io_unmap; |
739 | 739 | ||
740 | if (request_irq(par->irq, mb862xx_intr, IRQF_DISABLED, | 740 | if (request_irq(par->irq, mb862xx_intr, 0, |
741 | DRV_NAME, (void *)par)) { | 741 | DRV_NAME, (void *)par)) { |
742 | dev_err(dev, "Cannot request irq\n"); | 742 | dev_err(dev, "Cannot request irq\n"); |
743 | goto io_unmap; | 743 | goto io_unmap; |
@@ -1073,7 +1073,7 @@ static int __devinit mb862xx_pci_probe(struct pci_dev *pdev, | |||
1073 | if (mb862xx_pci_gdc_init(par)) | 1073 | if (mb862xx_pci_gdc_init(par)) |
1074 | goto io_unmap; | 1074 | goto io_unmap; |
1075 | 1075 | ||
1076 | if (request_irq(par->irq, mb862xx_intr, IRQF_DISABLED | IRQF_SHARED, | 1076 | if (request_irq(par->irq, mb862xx_intr, IRQF_SHARED, |
1077 | DRV_NAME, (void *)par)) { | 1077 | DRV_NAME, (void *)par)) { |
1078 | dev_err(dev, "Cannot request irq\n"); | 1078 | dev_err(dev, "Cannot request irq\n"); |
1079 | goto io_unmap; | 1079 | goto io_unmap; |
diff --git a/drivers/video/modedb.c b/drivers/video/modedb.c index cb175fe7abc0..a9a907c440d7 100644 --- a/drivers/video/modedb.c +++ b/drivers/video/modedb.c | |||
@@ -491,55 +491,56 @@ EXPORT_SYMBOL(vesa_modes); | |||
491 | static int fb_try_mode(struct fb_var_screeninfo *var, struct fb_info *info, | 491 | static int fb_try_mode(struct fb_var_screeninfo *var, struct fb_info *info, |
492 | const struct fb_videomode *mode, unsigned int bpp) | 492 | const struct fb_videomode *mode, unsigned int bpp) |
493 | { | 493 | { |
494 | int err = 0; | 494 | int err = 0; |
495 | 495 | ||
496 | DPRINTK("Trying mode %s %dx%d-%d@%d\n", mode->name ? mode->name : "noname", | 496 | DPRINTK("Trying mode %s %dx%d-%d@%d\n", |
497 | mode->xres, mode->yres, bpp, mode->refresh); | 497 | mode->name ? mode->name : "noname", |
498 | var->xres = mode->xres; | 498 | mode->xres, mode->yres, bpp, mode->refresh); |
499 | var->yres = mode->yres; | 499 | var->xres = mode->xres; |
500 | var->xres_virtual = mode->xres; | 500 | var->yres = mode->yres; |
501 | var->yres_virtual = mode->yres; | 501 | var->xres_virtual = mode->xres; |
502 | var->xoffset = 0; | 502 | var->yres_virtual = mode->yres; |
503 | var->yoffset = 0; | 503 | var->xoffset = 0; |
504 | var->bits_per_pixel = bpp; | 504 | var->yoffset = 0; |
505 | var->activate |= FB_ACTIVATE_TEST; | 505 | var->bits_per_pixel = bpp; |
506 | var->pixclock = mode->pixclock; | 506 | var->activate |= FB_ACTIVATE_TEST; |
507 | var->left_margin = mode->left_margin; | 507 | var->pixclock = mode->pixclock; |
508 | var->right_margin = mode->right_margin; | 508 | var->left_margin = mode->left_margin; |
509 | var->upper_margin = mode->upper_margin; | 509 | var->right_margin = mode->right_margin; |
510 | var->lower_margin = mode->lower_margin; | 510 | var->upper_margin = mode->upper_margin; |
511 | var->hsync_len = mode->hsync_len; | 511 | var->lower_margin = mode->lower_margin; |
512 | var->vsync_len = mode->vsync_len; | 512 | var->hsync_len = mode->hsync_len; |
513 | var->sync = mode->sync; | 513 | var->vsync_len = mode->vsync_len; |
514 | var->vmode = mode->vmode; | 514 | var->sync = mode->sync; |
515 | if (info->fbops->fb_check_var) | 515 | var->vmode = mode->vmode; |
516 | err = info->fbops->fb_check_var(var, info); | 516 | if (info->fbops->fb_check_var) |
517 | var->activate &= ~FB_ACTIVATE_TEST; | 517 | err = info->fbops->fb_check_var(var, info); |
518 | return err; | 518 | var->activate &= ~FB_ACTIVATE_TEST; |
519 | return err; | ||
519 | } | 520 | } |
520 | 521 | ||
521 | /** | 522 | /** |
522 | * fb_find_mode - finds a valid video mode | 523 | * fb_find_mode - finds a valid video mode |
523 | * @var: frame buffer user defined part of display | 524 | * @var: frame buffer user defined part of display |
524 | * @info: frame buffer info structure | 525 | * @info: frame buffer info structure |
525 | * @mode_option: string video mode to find | 526 | * @mode_option: string video mode to find |
526 | * @db: video mode database | 527 | * @db: video mode database |
527 | * @dbsize: size of @db | 528 | * @dbsize: size of @db |
528 | * @default_mode: default video mode to fall back to | 529 | * @default_mode: default video mode to fall back to |
529 | * @default_bpp: default color depth in bits per pixel | 530 | * @default_bpp: default color depth in bits per pixel |
530 | * | 531 | * |
531 | * Finds a suitable video mode, starting with the specified mode | 532 | * Finds a suitable video mode, starting with the specified mode |
532 | * in @mode_option with fallback to @default_mode. If | 533 | * in @mode_option with fallback to @default_mode. If |
533 | * @default_mode fails, all modes in the video mode database will | 534 | * @default_mode fails, all modes in the video mode database will |
534 | * be tried. | 535 | * be tried. |
535 | * | 536 | * |
536 | * Valid mode specifiers for @mode_option: | 537 | * Valid mode specifiers for @mode_option: |
537 | * | 538 | * |
538 | * <xres>x<yres>[M][R][-<bpp>][@<refresh>][i][m] or | 539 | * <xres>x<yres>[M][R][-<bpp>][@<refresh>][i][m] or |
539 | * <name>[-<bpp>][@<refresh>] | 540 | * <name>[-<bpp>][@<refresh>] |
540 | * | 541 | * |
541 | * with <xres>, <yres>, <bpp> and <refresh> decimal numbers and | 542 | * with <xres>, <yres>, <bpp> and <refresh> decimal numbers and |
542 | * <name> a string. | 543 | * <name> a string. |
543 | * | 544 | * |
544 | * If 'M' is present after yres (and before refresh/bpp if present), | 545 | * If 'M' is present after yres (and before refresh/bpp if present), |
545 | * the function will compute the timings using VESA(tm) Coordinated | 546 | * the function will compute the timings using VESA(tm) Coordinated |
@@ -551,12 +552,12 @@ static int fb_try_mode(struct fb_var_screeninfo *var, struct fb_info *info, | |||
551 | * | 552 | * |
552 | * 1024x768MR-8@60m - Reduced blank with margins at 60Hz. | 553 | * 1024x768MR-8@60m - Reduced blank with margins at 60Hz. |
553 | * | 554 | * |
554 | * NOTE: The passed struct @var is _not_ cleared! This allows you | 555 | * NOTE: The passed struct @var is _not_ cleared! This allows you |
555 | * to supply values for e.g. the grayscale and accel_flags fields. | 556 | * to supply values for e.g. the grayscale and accel_flags fields. |
556 | * | 557 | * |
557 | * Returns zero for failure, 1 if using specified @mode_option, | 558 | * Returns zero for failure, 1 if using specified @mode_option, |
558 | * 2 if using specified @mode_option with an ignored refresh rate, | 559 | * 2 if using specified @mode_option with an ignored refresh rate, |
559 | * 3 if default mode is used, 4 if fall back to any valid mode. | 560 | * 3 if default mode is used, 4 if fall back to any valid mode. |
560 | * | 561 | * |
561 | */ | 562 | */ |
562 | 563 | ||
@@ -566,198 +567,203 @@ int fb_find_mode(struct fb_var_screeninfo *var, | |||
566 | const struct fb_videomode *default_mode, | 567 | const struct fb_videomode *default_mode, |
567 | unsigned int default_bpp) | 568 | unsigned int default_bpp) |
568 | { | 569 | { |
569 | int i; | 570 | int i; |
570 | |||
571 | /* Set up defaults */ | ||
572 | if (!db) { | ||
573 | db = modedb; | ||
574 | dbsize = ARRAY_SIZE(modedb); | ||
575 | } | ||
576 | |||
577 | if (!default_mode) | ||
578 | default_mode = &db[0]; | ||
579 | |||
580 | if (!default_bpp) | ||
581 | default_bpp = 8; | ||
582 | |||
583 | /* Did the user specify a video mode? */ | ||
584 | if (!mode_option) | ||
585 | mode_option = fb_mode_option; | ||
586 | if (mode_option) { | ||
587 | const char *name = mode_option; | ||
588 | unsigned int namelen = strlen(name); | ||
589 | int res_specified = 0, bpp_specified = 0, refresh_specified = 0; | ||
590 | unsigned int xres = 0, yres = 0, bpp = default_bpp, refresh = 0; | ||
591 | int yres_specified = 0, cvt = 0, rb = 0, interlace = 0, margins = 0; | ||
592 | u32 best, diff, tdiff; | ||
593 | |||
594 | for (i = namelen-1; i >= 0; i--) { | ||
595 | switch (name[i]) { | ||
596 | case '@': | ||
597 | namelen = i; | ||
598 | if (!refresh_specified && !bpp_specified && | ||
599 | !yres_specified) { | ||
600 | refresh = simple_strtol(&name[i+1], NULL, 10); | ||
601 | refresh_specified = 1; | ||
602 | if (cvt || rb) | ||
603 | cvt = 0; | ||
604 | } else | ||
605 | goto done; | ||
606 | break; | ||
607 | case '-': | ||
608 | namelen = i; | ||
609 | if (!bpp_specified && !yres_specified) { | ||
610 | bpp = simple_strtol(&name[i+1], NULL, 10); | ||
611 | bpp_specified = 1; | ||
612 | if (cvt || rb) | ||
613 | cvt = 0; | ||
614 | } else | ||
615 | goto done; | ||
616 | break; | ||
617 | case 'x': | ||
618 | if (!yres_specified) { | ||
619 | yres = simple_strtol(&name[i+1], NULL, 10); | ||
620 | yres_specified = 1; | ||
621 | } else | ||
622 | goto done; | ||
623 | break; | ||
624 | case '0' ... '9': | ||
625 | break; | ||
626 | case 'M': | ||
627 | if (!yres_specified) | ||
628 | cvt = 1; | ||
629 | break; | ||
630 | case 'R': | ||
631 | if (!cvt) | ||
632 | rb = 1; | ||
633 | break; | ||
634 | case 'm': | ||
635 | if (!cvt) | ||
636 | margins = 1; | ||
637 | break; | ||
638 | case 'i': | ||
639 | if (!cvt) | ||
640 | interlace = 1; | ||
641 | break; | ||
642 | default: | ||
643 | goto done; | ||
644 | } | ||
645 | } | ||
646 | if (i < 0 && yres_specified) { | ||
647 | xres = simple_strtol(name, NULL, 10); | ||
648 | res_specified = 1; | ||
649 | } | ||
650 | done: | ||
651 | if (cvt) { | ||
652 | struct fb_videomode cvt_mode; | ||
653 | int ret; | ||
654 | |||
655 | DPRINTK("CVT mode %dx%d@%dHz%s%s%s\n", xres, yres, | ||
656 | (refresh) ? refresh : 60, (rb) ? " reduced blanking" : | ||
657 | "", (margins) ? " with margins" : "", (interlace) ? | ||
658 | " interlaced" : ""); | ||
659 | |||
660 | memset(&cvt_mode, 0, sizeof(cvt_mode)); | ||
661 | cvt_mode.xres = xres; | ||
662 | cvt_mode.yres = yres; | ||
663 | cvt_mode.refresh = (refresh) ? refresh : 60; | ||
664 | 571 | ||
665 | if (interlace) | 572 | /* Set up defaults */ |
666 | cvt_mode.vmode |= FB_VMODE_INTERLACED; | 573 | if (!db) { |
667 | else | 574 | db = modedb; |
668 | cvt_mode.vmode &= ~FB_VMODE_INTERLACED; | 575 | dbsize = ARRAY_SIZE(modedb); |
576 | } | ||
669 | 577 | ||
670 | ret = fb_find_mode_cvt(&cvt_mode, margins, rb); | 578 | if (!default_mode) |
579 | default_mode = &db[0]; | ||
580 | |||
581 | if (!default_bpp) | ||
582 | default_bpp = 8; | ||
583 | |||
584 | /* Did the user specify a video mode? */ | ||
585 | if (!mode_option) | ||
586 | mode_option = fb_mode_option; | ||
587 | if (mode_option) { | ||
588 | const char *name = mode_option; | ||
589 | unsigned int namelen = strlen(name); | ||
590 | int res_specified = 0, bpp_specified = 0, refresh_specified = 0; | ||
591 | unsigned int xres = 0, yres = 0, bpp = default_bpp, refresh = 0; | ||
592 | int yres_specified = 0, cvt = 0, rb = 0, interlace = 0; | ||
593 | int margins = 0; | ||
594 | u32 best, diff, tdiff; | ||
595 | |||
596 | for (i = namelen-1; i >= 0; i--) { | ||
597 | switch (name[i]) { | ||
598 | case '@': | ||
599 | namelen = i; | ||
600 | if (!refresh_specified && !bpp_specified && | ||
601 | !yres_specified) { | ||
602 | refresh = simple_strtol(&name[i+1], NULL, | ||
603 | 10); | ||
604 | refresh_specified = 1; | ||
605 | if (cvt || rb) | ||
606 | cvt = 0; | ||
607 | } else | ||
608 | goto done; | ||
609 | break; | ||
610 | case '-': | ||
611 | namelen = i; | ||
612 | if (!bpp_specified && !yres_specified) { | ||
613 | bpp = simple_strtol(&name[i+1], NULL, | ||
614 | 10); | ||
615 | bpp_specified = 1; | ||
616 | if (cvt || rb) | ||
617 | cvt = 0; | ||
618 | } else | ||
619 | goto done; | ||
620 | break; | ||
621 | case 'x': | ||
622 | if (!yres_specified) { | ||
623 | yres = simple_strtol(&name[i+1], NULL, | ||
624 | 10); | ||
625 | yres_specified = 1; | ||
626 | } else | ||
627 | goto done; | ||
628 | break; | ||
629 | case '0' ... '9': | ||
630 | break; | ||
631 | case 'M': | ||
632 | if (!yres_specified) | ||
633 | cvt = 1; | ||
634 | break; | ||
635 | case 'R': | ||
636 | if (!cvt) | ||
637 | rb = 1; | ||
638 | break; | ||
639 | case 'm': | ||
640 | if (!cvt) | ||
641 | margins = 1; | ||
642 | break; | ||
643 | case 'i': | ||
644 | if (!cvt) | ||
645 | interlace = 1; | ||
646 | break; | ||
647 | default: | ||
648 | goto done; | ||
649 | } | ||
650 | } | ||
651 | if (i < 0 && yres_specified) { | ||
652 | xres = simple_strtol(name, NULL, 10); | ||
653 | res_specified = 1; | ||
654 | } | ||
655 | done: | ||
656 | if (cvt) { | ||
657 | struct fb_videomode cvt_mode; | ||
658 | int ret; | ||
659 | |||
660 | DPRINTK("CVT mode %dx%d@%dHz%s%s%s\n", xres, yres, | ||
661 | (refresh) ? refresh : 60, | ||
662 | (rb) ? " reduced blanking" : "", | ||
663 | (margins) ? " with margins" : "", | ||
664 | (interlace) ? " interlaced" : ""); | ||
665 | |||
666 | memset(&cvt_mode, 0, sizeof(cvt_mode)); | ||
667 | cvt_mode.xres = xres; | ||
668 | cvt_mode.yres = yres; | ||
669 | cvt_mode.refresh = (refresh) ? refresh : 60; | ||
670 | |||
671 | if (interlace) | ||
672 | cvt_mode.vmode |= FB_VMODE_INTERLACED; | ||
673 | else | ||
674 | cvt_mode.vmode &= ~FB_VMODE_INTERLACED; | ||
675 | |||
676 | ret = fb_find_mode_cvt(&cvt_mode, margins, rb); | ||
677 | |||
678 | if (!ret && !fb_try_mode(var, info, &cvt_mode, bpp)) { | ||
679 | DPRINTK("modedb CVT: CVT mode ok\n"); | ||
680 | return 1; | ||
681 | } | ||
671 | 682 | ||
672 | if (!ret && !fb_try_mode(var, info, &cvt_mode, bpp)) { | 683 | DPRINTK("CVT mode invalid, getting mode from database\n"); |
673 | DPRINTK("modedb CVT: CVT mode ok\n"); | 684 | } |
674 | return 1; | ||
675 | } | ||
676 | 685 | ||
677 | DPRINTK("CVT mode invalid, getting mode from database\n"); | 686 | DPRINTK("Trying specified video mode%s %ix%i\n", |
678 | } | 687 | refresh_specified ? "" : " (ignoring refresh rate)", |
688 | xres, yres); | ||
679 | 689 | ||
680 | DPRINTK("Trying specified video mode%s %ix%i\n", | 690 | if (!refresh_specified) { |
681 | refresh_specified ? "" : " (ignoring refresh rate)", xres, yres); | 691 | /* |
682 | 692 | * If the caller has provided a custom mode database and | |
683 | if (!refresh_specified) { | 693 | * a valid monspecs structure, we look for the mode with |
684 | /* | 694 | * the highest refresh rate. Otherwise we play it safe |
685 | * If the caller has provided a custom mode database and a | 695 | * it and try to find a mode with a refresh rate closest |
686 | * valid monspecs structure, we look for the mode with the | 696 | * to the standard 60 Hz. |
687 | * highest refresh rate. Otherwise we play it safe it and | 697 | */ |
688 | * try to find a mode with a refresh rate closest to the | 698 | if (db != modedb && |
689 | * standard 60 Hz. | 699 | info->monspecs.vfmin && info->monspecs.vfmax && |
690 | */ | 700 | info->monspecs.hfmin && info->monspecs.hfmax && |
691 | if (db != modedb && | 701 | info->monspecs.dclkmax) { |
692 | info->monspecs.vfmin && info->monspecs.vfmax && | 702 | refresh = 1000; |
693 | info->monspecs.hfmin && info->monspecs.hfmax && | 703 | } else { |
694 | info->monspecs.dclkmax) { | 704 | refresh = 60; |
695 | refresh = 1000; | 705 | } |
696 | } else { | ||
697 | refresh = 60; | ||
698 | } | 706 | } |
699 | } | ||
700 | 707 | ||
701 | diff = -1; | 708 | diff = -1; |
702 | best = -1; | 709 | best = -1; |
703 | for (i = 0; i < dbsize; i++) { | 710 | for (i = 0; i < dbsize; i++) { |
704 | if ((name_matches(db[i], name, namelen) || | 711 | if ((name_matches(db[i], name, namelen) || |
705 | (res_specified && res_matches(db[i], xres, yres))) && | 712 | (res_specified && res_matches(db[i], xres, yres))) && |
706 | !fb_try_mode(var, info, &db[i], bpp)) { | 713 | !fb_try_mode(var, info, &db[i], bpp)) { |
707 | if (refresh_specified && db[i].refresh == refresh) { | 714 | if (refresh_specified && db[i].refresh == refresh) |
708 | return 1; | 715 | return 1; |
709 | } else { | 716 | |
710 | if (abs(db[i].refresh - refresh) < diff) { | 717 | if (abs(db[i].refresh - refresh) < diff) { |
711 | diff = abs(db[i].refresh - refresh); | 718 | diff = abs(db[i].refresh - refresh); |
712 | best = i; | 719 | best = i; |
713 | } | 720 | } |
714 | } | 721 | } |
715 | } | 722 | } |
716 | } | 723 | if (best != -1) { |
717 | if (best != -1) { | 724 | fb_try_mode(var, info, &db[best], bpp); |
718 | fb_try_mode(var, info, &db[best], bpp); | 725 | return (refresh_specified) ? 2 : 1; |
719 | return (refresh_specified) ? 2 : 1; | 726 | } |
720 | } | ||
721 | |||
722 | diff = 2 * (xres + yres); | ||
723 | best = -1; | ||
724 | DPRINTK("Trying best-fit modes\n"); | ||
725 | for (i = 0; i < dbsize; i++) { | ||
726 | DPRINTK("Trying %ix%i\n", db[i].xres, db[i].yres); | ||
727 | if (!fb_try_mode(var, info, &db[i], bpp)) { | ||
728 | tdiff = abs(db[i].xres - xres) + | ||
729 | abs(db[i].yres - yres); | ||
730 | |||
731 | /* | ||
732 | * Penalize modes with resolutions smaller | ||
733 | * than requested. | ||
734 | */ | ||
735 | if (xres > db[i].xres || yres > db[i].yres) | ||
736 | tdiff += xres + yres; | ||
737 | 727 | ||
738 | if (diff > tdiff) { | 728 | diff = 2 * (xres + yres); |
739 | diff = tdiff; | 729 | best = -1; |
740 | best = i; | 730 | DPRINTK("Trying best-fit modes\n"); |
731 | for (i = 0; i < dbsize; i++) { | ||
732 | DPRINTK("Trying %ix%i\n", db[i].xres, db[i].yres); | ||
733 | if (!fb_try_mode(var, info, &db[i], bpp)) { | ||
734 | tdiff = abs(db[i].xres - xres) + | ||
735 | abs(db[i].yres - yres); | ||
736 | |||
737 | /* | ||
738 | * Penalize modes with resolutions smaller | ||
739 | * than requested. | ||
740 | */ | ||
741 | if (xres > db[i].xres || yres > db[i].yres) | ||
742 | tdiff += xres + yres; | ||
743 | |||
744 | if (diff > tdiff) { | ||
745 | diff = tdiff; | ||
746 | best = i; | ||
747 | } | ||
741 | } | 748 | } |
742 | } | 749 | } |
750 | if (best != -1) { | ||
751 | fb_try_mode(var, info, &db[best], bpp); | ||
752 | return 5; | ||
753 | } | ||
743 | } | 754 | } |
744 | if (best != -1) { | ||
745 | fb_try_mode(var, info, &db[best], bpp); | ||
746 | return 5; | ||
747 | } | ||
748 | } | ||
749 | 755 | ||
750 | DPRINTK("Trying default video mode\n"); | 756 | DPRINTK("Trying default video mode\n"); |
751 | if (!fb_try_mode(var, info, default_mode, default_bpp)) | 757 | if (!fb_try_mode(var, info, default_mode, default_bpp)) |
752 | return 3; | 758 | return 3; |
753 | 759 | ||
754 | DPRINTK("Trying all modes\n"); | 760 | DPRINTK("Trying all modes\n"); |
755 | for (i = 0; i < dbsize; i++) | 761 | for (i = 0; i < dbsize; i++) |
756 | if (!fb_try_mode(var, info, &db[i], default_bpp)) | 762 | if (!fb_try_mode(var, info, &db[i], default_bpp)) |
757 | return 4; | 763 | return 4; |
758 | 764 | ||
759 | DPRINTK("No valid mode found\n"); | 765 | DPRINTK("No valid mode found\n"); |
760 | return 0; | 766 | return 0; |
761 | } | 767 | } |
762 | 768 | ||
763 | /** | 769 | /** |
diff --git a/drivers/video/msm/mddi.c b/drivers/video/msm/mddi.c index 178b0720bd79..4527cbf0a4ec 100644 --- a/drivers/video/msm/mddi.c +++ b/drivers/video/msm/mddi.c | |||
@@ -715,7 +715,7 @@ static int __devinit mddi_probe(struct platform_device *pdev) | |||
715 | 715 | ||
716 | mddi->int_enable = 0; | 716 | mddi->int_enable = 0; |
717 | mddi_writel(mddi->int_enable, INTEN); | 717 | mddi_writel(mddi->int_enable, INTEN); |
718 | ret = request_irq(mddi->irq, mddi_isr, IRQF_DISABLED, "mddi", | 718 | ret = request_irq(mddi->irq, mddi_isr, 0, "mddi", |
719 | &mddi->client_data); | 719 | &mddi->client_data); |
720 | if (ret) { | 720 | if (ret) { |
721 | printk(KERN_ERR "mddi: failed to request enable irq!\n"); | 721 | printk(KERN_ERR "mddi: failed to request enable irq!\n"); |
diff --git a/drivers/video/msm/mdp.c b/drivers/video/msm/mdp.c index 243d16f09b8a..b9344772bac9 100644 --- a/drivers/video/msm/mdp.c +++ b/drivers/video/msm/mdp.c | |||
@@ -421,10 +421,11 @@ int mdp_probe(struct platform_device *pdev) | |||
421 | clk = clk_get(&pdev->dev, "mdp_clk"); | 421 | clk = clk_get(&pdev->dev, "mdp_clk"); |
422 | if (IS_ERR(clk)) { | 422 | if (IS_ERR(clk)) { |
423 | printk(KERN_INFO "mdp: failed to get mdp clk"); | 423 | printk(KERN_INFO "mdp: failed to get mdp clk"); |
424 | return PTR_ERR(clk); | 424 | ret = PTR_ERR(clk); |
425 | goto error_get_clk; | ||
425 | } | 426 | } |
426 | 427 | ||
427 | ret = request_irq(mdp->irq, mdp_isr, IRQF_DISABLED, "msm_mdp", mdp); | 428 | ret = request_irq(mdp->irq, mdp_isr, 0, "msm_mdp", mdp); |
428 | if (ret) | 429 | if (ret) |
429 | goto error_request_irq; | 430 | goto error_request_irq; |
430 | disable_irq(mdp->irq); | 431 | disable_irq(mdp->irq); |
@@ -495,6 +496,7 @@ int mdp_probe(struct platform_device *pdev) | |||
495 | error_device_register: | 496 | error_device_register: |
496 | free_irq(mdp->irq, mdp); | 497 | free_irq(mdp->irq, mdp); |
497 | error_request_irq: | 498 | error_request_irq: |
499 | error_get_clk: | ||
498 | iounmap(mdp->base); | 500 | iounmap(mdp->base); |
499 | error_get_irq: | 501 | error_get_irq: |
500 | error_ioremap: | 502 | error_ioremap: |
diff --git a/drivers/video/mx3fb.c b/drivers/video/mx3fb.c index 7e3a490e8d76..e3406ab31305 100644 --- a/drivers/video/mx3fb.c +++ b/drivers/video/mx3fb.c | |||
@@ -382,6 +382,9 @@ static void sdc_disable_channel(struct mx3fb_info *mx3_fbi) | |||
382 | uint32_t enabled; | 382 | uint32_t enabled; |
383 | unsigned long flags; | 383 | unsigned long flags; |
384 | 384 | ||
385 | if (mx3_fbi->txd == NULL) | ||
386 | return; | ||
387 | |||
385 | spin_lock_irqsave(&mx3fb->lock, flags); | 388 | spin_lock_irqsave(&mx3fb->lock, flags); |
386 | 389 | ||
387 | enabled = sdc_fb_uninit(mx3_fbi); | 390 | enabled = sdc_fb_uninit(mx3_fbi); |
@@ -986,9 +989,19 @@ static void __blank(int blank, struct fb_info *fbi) | |||
986 | { | 989 | { |
987 | struct mx3fb_info *mx3_fbi = fbi->par; | 990 | struct mx3fb_info *mx3_fbi = fbi->par; |
988 | struct mx3fb_data *mx3fb = mx3_fbi->mx3fb; | 991 | struct mx3fb_data *mx3fb = mx3_fbi->mx3fb; |
992 | int was_blank = mx3_fbi->blank; | ||
989 | 993 | ||
990 | mx3_fbi->blank = blank; | 994 | mx3_fbi->blank = blank; |
991 | 995 | ||
996 | /* Attention! | ||
997 | * Do not call sdc_disable_channel() for a channel that is disabled | ||
998 | * already! This will result in a kernel NULL pointer dereference | ||
999 | * (mx3_fbi->txd is NULL). Hide the fact, that all blank modes are | ||
1000 | * handled equally by this driver. | ||
1001 | */ | ||
1002 | if (blank > FB_BLANK_UNBLANK && was_blank > FB_BLANK_UNBLANK) | ||
1003 | return; | ||
1004 | |||
992 | switch (blank) { | 1005 | switch (blank) { |
993 | case FB_BLANK_POWERDOWN: | 1006 | case FB_BLANK_POWERDOWN: |
994 | case FB_BLANK_VSYNC_SUSPEND: | 1007 | case FB_BLANK_VSYNC_SUSPEND: |
@@ -1062,15 +1075,15 @@ static int mx3fb_pan_display(struct fb_var_screeninfo *var, | |||
1062 | y_bottom = var->yoffset; | 1075 | y_bottom = var->yoffset; |
1063 | 1076 | ||
1064 | if (!(var->vmode & FB_VMODE_YWRAP)) | 1077 | if (!(var->vmode & FB_VMODE_YWRAP)) |
1065 | y_bottom += var->yres; | 1078 | y_bottom += fbi->var.yres; |
1066 | 1079 | ||
1067 | if (y_bottom > fbi->var.yres_virtual) | 1080 | if (y_bottom > fbi->var.yres_virtual) |
1068 | return -EINVAL; | 1081 | return -EINVAL; |
1069 | 1082 | ||
1070 | mutex_lock(&mx3_fbi->mutex); | 1083 | mutex_lock(&mx3_fbi->mutex); |
1071 | 1084 | ||
1072 | offset = (var->yoffset * var->xres_virtual + var->xoffset) * | 1085 | offset = var->yoffset * fbi->fix.line_length |
1073 | (var->bits_per_pixel / 8); | 1086 | + var->xoffset * (fbi->var.bits_per_pixel / 8); |
1074 | base = fbi->fix.smem_start + offset; | 1087 | base = fbi->fix.smem_start + offset; |
1075 | 1088 | ||
1076 | dev_dbg(fbi->device, "Updating SDC BG buf %d address=0x%08lX\n", | 1089 | dev_dbg(fbi->device, "Updating SDC BG buf %d address=0x%08lX\n", |
diff --git a/drivers/video/mxsfb.c b/drivers/video/mxsfb.c index 0b2f2dd41416..d837d63c456f 100644 --- a/drivers/video/mxsfb.c +++ b/drivers/video/mxsfb.c | |||
@@ -39,6 +39,7 @@ | |||
39 | * the required value in the imx_fb_videomode structure. | 39 | * the required value in the imx_fb_videomode structure. |
40 | */ | 40 | */ |
41 | 41 | ||
42 | #include <linux/module.h> | ||
42 | #include <linux/kernel.h> | 43 | #include <linux/kernel.h> |
43 | #include <linux/platform_device.h> | 44 | #include <linux/platform_device.h> |
44 | #include <linux/clk.h> | 45 | #include <linux/clk.h> |
diff --git a/drivers/video/neofb.c b/drivers/video/neofb.c index 588527a254c2..feea7b1dc386 100644 --- a/drivers/video/neofb.c +++ b/drivers/video/neofb.c | |||
@@ -1185,8 +1185,8 @@ static int neofb_pan_display(struct fb_var_screeninfo *var, | |||
1185 | 1185 | ||
1186 | DBG("neofb_update_start"); | 1186 | DBG("neofb_update_start"); |
1187 | 1187 | ||
1188 | Base = (var->yoffset * var->xres_virtual + var->xoffset) >> 2; | 1188 | Base = (var->yoffset * info->var.xres_virtual + var->xoffset) >> 2; |
1189 | Base *= (var->bits_per_pixel + 7) / 8; | 1189 | Base *= (info->var.bits_per_pixel + 7) / 8; |
1190 | 1190 | ||
1191 | neoUnlock(); | 1191 | neoUnlock(); |
1192 | 1192 | ||
diff --git a/drivers/video/nuc900fb.c b/drivers/video/nuc900fb.c index 0fff59782e45..d1fbbd888cf4 100644 --- a/drivers/video/nuc900fb.c +++ b/drivers/video/nuc900fb.c | |||
@@ -39,7 +39,6 @@ | |||
39 | #include <mach/regs-clock.h> | 39 | #include <mach/regs-clock.h> |
40 | #include <mach/regs-ldm.h> | 40 | #include <mach/regs-ldm.h> |
41 | #include <mach/fb.h> | 41 | #include <mach/fb.h> |
42 | #include <mach/clkdev.h> | ||
43 | 42 | ||
44 | #include "nuc900fb.h" | 43 | #include "nuc900fb.h" |
45 | 44 | ||
@@ -588,7 +587,7 @@ static int __devinit nuc900fb_probe(struct platform_device *pdev) | |||
588 | fbinfo->flags = FBINFO_FLAG_DEFAULT; | 587 | fbinfo->flags = FBINFO_FLAG_DEFAULT; |
589 | fbinfo->pseudo_palette = &fbi->pseudo_pal; | 588 | fbinfo->pseudo_palette = &fbi->pseudo_pal; |
590 | 589 | ||
591 | ret = request_irq(irq, nuc900fb_irqhandler, IRQF_DISABLED, | 590 | ret = request_irq(irq, nuc900fb_irqhandler, 0, |
592 | pdev->name, fbinfo); | 591 | pdev->name, fbinfo); |
593 | if (ret) { | 592 | if (ret) { |
594 | dev_err(&pdev->dev, "cannot register irq handler %d -err %d\n", | 593 | dev_err(&pdev->dev, "cannot register irq handler %d -err %d\n", |
diff --git a/drivers/video/omap/Kconfig b/drivers/video/omap/Kconfig index 196fa2e7f438..84ff23208c25 100644 --- a/drivers/video/omap/Kconfig +++ b/drivers/video/omap/Kconfig | |||
@@ -9,35 +9,6 @@ config FB_OMAP | |||
9 | help | 9 | help |
10 | Frame buffer driver for OMAP based boards. | 10 | Frame buffer driver for OMAP based boards. |
11 | 11 | ||
12 | config FB_OMAP_LCD_VGA | ||
13 | bool "Use LCD in VGA mode" | ||
14 | depends on MACH_OMAP_3430SDP || MACH_OMAP_LDP | ||
15 | help | ||
16 | Set LCD resolution as VGA (640 X 480). | ||
17 | Default resolution without this option is QVGA(320 X 240). | ||
18 | Please take a look at drivers/video/omap/lcd_ldp.c file | ||
19 | for lcd driver code. | ||
20 | choice | ||
21 | depends on FB_OMAP && MACH_OVERO | ||
22 | prompt "Screen resolution" | ||
23 | default FB_OMAP_079M3R | ||
24 | help | ||
25 | Selected desired screen resolution | ||
26 | |||
27 | config FB_OMAP_031M3R | ||
28 | boolean "640 x 480 @ 60 Hz Reduced blanking" | ||
29 | |||
30 | config FB_OMAP_048M3R | ||
31 | boolean "800 x 600 @ 60 Hz Reduced blanking" | ||
32 | |||
33 | config FB_OMAP_079M3R | ||
34 | boolean "1024 x 768 @ 60 Hz Reduced blanking" | ||
35 | |||
36 | config FB_OMAP_092M9R | ||
37 | boolean "1280 x 720 @ 60 Hz Reduced blanking" | ||
38 | |||
39 | endchoice | ||
40 | |||
41 | config FB_OMAP_LCDC_EXTERNAL | 12 | config FB_OMAP_LCDC_EXTERNAL |
42 | bool "External LCD controller support" | 13 | bool "External LCD controller support" |
43 | depends on FB_OMAP | 14 | depends on FB_OMAP |
diff --git a/drivers/video/omap/Makefile b/drivers/video/omap/Makefile index 25db55696e14..ef78550917ff 100644 --- a/drivers/video/omap/Makefile +++ b/drivers/video/omap/Makefile | |||
@@ -17,7 +17,6 @@ objs-y$(CONFIG_FB_OMAP_LCDC_HWA742) += hwa742.o | |||
17 | objs-y$(CONFIG_FB_OMAP_LCDC_BLIZZARD) += blizzard.o | 17 | objs-y$(CONFIG_FB_OMAP_LCDC_BLIZZARD) += blizzard.o |
18 | 18 | ||
19 | objs-y$(CONFIG_MACH_AMS_DELTA) += lcd_ams_delta.o | 19 | objs-y$(CONFIG_MACH_AMS_DELTA) += lcd_ams_delta.o |
20 | objs-y$(CONFIG_MACH_OMAP_H4) += lcd_h4.o | ||
21 | objs-y$(CONFIG_MACH_OMAP_H3) += lcd_h3.o | 20 | objs-y$(CONFIG_MACH_OMAP_H3) += lcd_h3.o |
22 | objs-y$(CONFIG_MACH_OMAP_PALMTE) += lcd_palmte.o | 21 | objs-y$(CONFIG_MACH_OMAP_PALMTE) += lcd_palmte.o |
23 | objs-y$(CONFIG_MACH_OMAP_PALMTT) += lcd_palmtt.o | 22 | objs-y$(CONFIG_MACH_OMAP_PALMTT) += lcd_palmtt.o |
@@ -26,14 +25,7 @@ objs-$(CONFIG_ARCH_OMAP16XX)$(CONFIG_MACH_OMAP_INNOVATOR) += lcd_inn1610.o | |||
26 | objs-$(CONFIG_ARCH_OMAP15XX)$(CONFIG_MACH_OMAP_INNOVATOR) += lcd_inn1510.o | 25 | objs-$(CONFIG_ARCH_OMAP15XX)$(CONFIG_MACH_OMAP_INNOVATOR) += lcd_inn1510.o |
27 | objs-y$(CONFIG_MACH_OMAP_OSK) += lcd_osk.o | 26 | objs-y$(CONFIG_MACH_OMAP_OSK) += lcd_osk.o |
28 | 27 | ||
29 | objs-y$(CONFIG_MACH_OMAP_APOLLON) += lcd_apollon.o | ||
30 | objs-y$(CONFIG_MACH_OMAP_2430SDP) += lcd_2430sdp.o | ||
31 | objs-y$(CONFIG_MACH_OMAP_3430SDP) += lcd_2430sdp.o | ||
32 | objs-y$(CONFIG_MACH_OMAP_LDP) += lcd_ldp.o | ||
33 | objs-y$(CONFIG_MACH_OMAP3EVM) += lcd_omap3evm.o | ||
34 | objs-y$(CONFIG_MACH_OMAP3_BEAGLE) += lcd_omap3beagle.o | ||
35 | objs-y$(CONFIG_FB_OMAP_LCD_MIPID) += lcd_mipid.o | 28 | objs-y$(CONFIG_FB_OMAP_LCD_MIPID) += lcd_mipid.o |
36 | objs-y$(CONFIG_MACH_OVERO) += lcd_overo.o | ||
37 | objs-y$(CONFIG_MACH_HERALD) += lcd_htcherald.o | 29 | objs-y$(CONFIG_MACH_HERALD) += lcd_htcherald.o |
38 | 30 | ||
39 | omapfb-objs := $(objs-yy) | 31 | omapfb-objs := $(objs-yy) |
diff --git a/drivers/video/omap/lcd_2430sdp.c b/drivers/video/omap/lcd_2430sdp.c deleted file mode 100644 index e3eccc9af78e..000000000000 --- a/drivers/video/omap/lcd_2430sdp.c +++ /dev/null | |||
@@ -1,203 +0,0 @@ | |||
1 | /* | ||
2 | * LCD panel support for the TI 2430SDP board | ||
3 | * | ||
4 | * Copyright (C) 2007 MontaVista | ||
5 | * Author: Hunyue Yau <hyau@mvista.com> | ||
6 | * | ||
7 | * Derived from drivers/video/omap/lcd-apollon.c | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License as published by the | ||
11 | * Free Software Foundation; either version 2 of the License, or (at your | ||
12 | * option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License along | ||
20 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
21 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
22 | */ | ||
23 | |||
24 | #include <linux/module.h> | ||
25 | #include <linux/platform_device.h> | ||
26 | #include <linux/delay.h> | ||
27 | #include <linux/gpio.h> | ||
28 | #include <linux/i2c/twl.h> | ||
29 | |||
30 | #include <plat/mux.h> | ||
31 | #include <asm/mach-types.h> | ||
32 | |||
33 | #include "omapfb.h" | ||
34 | |||
35 | #define SDP2430_LCD_PANEL_BACKLIGHT_GPIO 91 | ||
36 | #define SDP2430_LCD_PANEL_ENABLE_GPIO 154 | ||
37 | #define SDP3430_LCD_PANEL_BACKLIGHT_GPIO 24 | ||
38 | #define SDP3430_LCD_PANEL_ENABLE_GPIO 28 | ||
39 | |||
40 | static unsigned backlight_gpio; | ||
41 | static unsigned enable_gpio; | ||
42 | |||
43 | #define LCD_PIXCLOCK_MAX 5400 /* freq 5.4 MHz */ | ||
44 | #define PM_RECEIVER TWL4030_MODULE_PM_RECEIVER | ||
45 | #define ENABLE_VAUX2_DEDICATED 0x09 | ||
46 | #define ENABLE_VAUX2_DEV_GRP 0x20 | ||
47 | #define ENABLE_VAUX3_DEDICATED 0x03 | ||
48 | #define ENABLE_VAUX3_DEV_GRP 0x20 | ||
49 | |||
50 | #define ENABLE_VPLL2_DEDICATED 0x05 | ||
51 | #define ENABLE_VPLL2_DEV_GRP 0xE0 | ||
52 | #define TWL4030_VPLL2_DEV_GRP 0x33 | ||
53 | #define TWL4030_VPLL2_DEDICATED 0x36 | ||
54 | |||
55 | #define t2_out(c, r, v) twl_i2c_write_u8(c, r, v) | ||
56 | |||
57 | |||
58 | static int sdp2430_panel_init(struct lcd_panel *panel, | ||
59 | struct omapfb_device *fbdev) | ||
60 | { | ||
61 | if (machine_is_omap_3430sdp()) { | ||
62 | enable_gpio = SDP3430_LCD_PANEL_ENABLE_GPIO; | ||
63 | backlight_gpio = SDP3430_LCD_PANEL_BACKLIGHT_GPIO; | ||
64 | } else { | ||
65 | enable_gpio = SDP2430_LCD_PANEL_ENABLE_GPIO; | ||
66 | backlight_gpio = SDP2430_LCD_PANEL_BACKLIGHT_GPIO; | ||
67 | } | ||
68 | |||
69 | gpio_request(enable_gpio, "LCD enable"); /* LCD panel */ | ||
70 | gpio_request(backlight_gpio, "LCD bl"); /* LCD backlight */ | ||
71 | gpio_direction_output(enable_gpio, 0); | ||
72 | gpio_direction_output(backlight_gpio, 0); | ||
73 | |||
74 | return 0; | ||
75 | } | ||
76 | |||
77 | static void sdp2430_panel_cleanup(struct lcd_panel *panel) | ||
78 | { | ||
79 | gpio_free(backlight_gpio); | ||
80 | gpio_free(enable_gpio); | ||
81 | } | ||
82 | |||
83 | static int sdp2430_panel_enable(struct lcd_panel *panel) | ||
84 | { | ||
85 | u8 ded_val, ded_reg; | ||
86 | u8 grp_val, grp_reg; | ||
87 | |||
88 | if (machine_is_omap_3430sdp()) { | ||
89 | ded_reg = TWL4030_VAUX3_DEDICATED; | ||
90 | ded_val = ENABLE_VAUX3_DEDICATED; | ||
91 | grp_reg = TWL4030_VAUX3_DEV_GRP; | ||
92 | grp_val = ENABLE_VAUX3_DEV_GRP; | ||
93 | |||
94 | if (omap_rev() > OMAP3430_REV_ES1_0) { | ||
95 | t2_out(PM_RECEIVER, ENABLE_VPLL2_DEDICATED, | ||
96 | TWL4030_VPLL2_DEDICATED); | ||
97 | t2_out(PM_RECEIVER, ENABLE_VPLL2_DEV_GRP, | ||
98 | TWL4030_VPLL2_DEV_GRP); | ||
99 | } | ||
100 | } else { | ||
101 | ded_reg = TWL4030_VAUX2_DEDICATED; | ||
102 | ded_val = ENABLE_VAUX2_DEDICATED; | ||
103 | grp_reg = TWL4030_VAUX2_DEV_GRP; | ||
104 | grp_val = ENABLE_VAUX2_DEV_GRP; | ||
105 | } | ||
106 | |||
107 | gpio_set_value(enable_gpio, 1); | ||
108 | gpio_set_value(backlight_gpio, 1); | ||
109 | |||
110 | if (0 != t2_out(PM_RECEIVER, ded_val, ded_reg)) | ||
111 | return -EIO; | ||
112 | if (0 != t2_out(PM_RECEIVER, grp_val, grp_reg)) | ||
113 | return -EIO; | ||
114 | |||
115 | return 0; | ||
116 | } | ||
117 | |||
118 | static void sdp2430_panel_disable(struct lcd_panel *panel) | ||
119 | { | ||
120 | gpio_set_value(enable_gpio, 0); | ||
121 | gpio_set_value(backlight_gpio, 0); | ||
122 | if (omap_rev() > OMAP3430_REV_ES1_0) { | ||
123 | t2_out(PM_RECEIVER, 0x0, TWL4030_VPLL2_DEDICATED); | ||
124 | t2_out(PM_RECEIVER, 0x0, TWL4030_VPLL2_DEV_GRP); | ||
125 | msleep(4); | ||
126 | } | ||
127 | } | ||
128 | |||
129 | static unsigned long sdp2430_panel_get_caps(struct lcd_panel *panel) | ||
130 | { | ||
131 | return 0; | ||
132 | } | ||
133 | |||
134 | struct lcd_panel sdp2430_panel = { | ||
135 | .name = "sdp2430", | ||
136 | .config = OMAP_LCDC_PANEL_TFT | OMAP_LCDC_INV_VSYNC | | ||
137 | OMAP_LCDC_INV_HSYNC, | ||
138 | |||
139 | .bpp = 16, | ||
140 | .data_lines = 16, | ||
141 | .x_res = 240, | ||
142 | .y_res = 320, | ||
143 | .hsw = 3, /* hsync_len (4) - 1 */ | ||
144 | .hfp = 3, /* right_margin (4) - 1 */ | ||
145 | .hbp = 39, /* left_margin (40) - 1 */ | ||
146 | .vsw = 1, /* vsync_len (2) - 1 */ | ||
147 | .vfp = 2, /* lower_margin */ | ||
148 | .vbp = 7, /* upper_margin (8) - 1 */ | ||
149 | |||
150 | .pixel_clock = LCD_PIXCLOCK_MAX, | ||
151 | |||
152 | .init = sdp2430_panel_init, | ||
153 | .cleanup = sdp2430_panel_cleanup, | ||
154 | .enable = sdp2430_panel_enable, | ||
155 | .disable = sdp2430_panel_disable, | ||
156 | .get_caps = sdp2430_panel_get_caps, | ||
157 | }; | ||
158 | |||
159 | static int sdp2430_panel_probe(struct platform_device *pdev) | ||
160 | { | ||
161 | omapfb_register_panel(&sdp2430_panel); | ||
162 | return 0; | ||
163 | } | ||
164 | |||
165 | static int sdp2430_panel_remove(struct platform_device *pdev) | ||
166 | { | ||
167 | return 0; | ||
168 | } | ||
169 | |||
170 | static int sdp2430_panel_suspend(struct platform_device *pdev, | ||
171 | pm_message_t mesg) | ||
172 | { | ||
173 | return 0; | ||
174 | } | ||
175 | |||
176 | static int sdp2430_panel_resume(struct platform_device *pdev) | ||
177 | { | ||
178 | return 0; | ||
179 | } | ||
180 | |||
181 | struct platform_driver sdp2430_panel_driver = { | ||
182 | .probe = sdp2430_panel_probe, | ||
183 | .remove = sdp2430_panel_remove, | ||
184 | .suspend = sdp2430_panel_suspend, | ||
185 | .resume = sdp2430_panel_resume, | ||
186 | .driver = { | ||
187 | .name = "sdp2430_lcd", | ||
188 | .owner = THIS_MODULE, | ||
189 | }, | ||
190 | }; | ||
191 | |||
192 | static int __init sdp2430_panel_drv_init(void) | ||
193 | { | ||
194 | return platform_driver_register(&sdp2430_panel_driver); | ||
195 | } | ||
196 | |||
197 | static void __exit sdp2430_panel_drv_exit(void) | ||
198 | { | ||
199 | platform_driver_unregister(&sdp2430_panel_driver); | ||
200 | } | ||
201 | |||
202 | module_init(sdp2430_panel_drv_init); | ||
203 | module_exit(sdp2430_panel_drv_exit); | ||
diff --git a/drivers/video/omap/lcd_apollon.c b/drivers/video/omap/lcd_apollon.c deleted file mode 100644 index 4b24f549f9b9..000000000000 --- a/drivers/video/omap/lcd_apollon.c +++ /dev/null | |||
@@ -1,136 +0,0 @@ | |||
1 | /* | ||
2 | * LCD panel support for the Samsung OMAP2 Apollon board | ||
3 | * | ||
4 | * Copyright (C) 2005,2006 Samsung Electronics | ||
5 | * Author: Kyungmin Park <kyungmin.park@samsung.com> | ||
6 | * | ||
7 | * Derived from drivers/video/omap/lcd-h4.c | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License as published by the | ||
11 | * Free Software Foundation; either version 2 of the License, or (at your | ||
12 | * option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License along | ||
20 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
21 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
22 | */ | ||
23 | |||
24 | #include <linux/module.h> | ||
25 | #include <linux/platform_device.h> | ||
26 | |||
27 | #include <asm/gpio.h> | ||
28 | |||
29 | #include "omapfb.h" | ||
30 | |||
31 | /* #define USE_35INCH_LCD 1 */ | ||
32 | |||
33 | static int apollon_panel_init(struct lcd_panel *panel, | ||
34 | struct omapfb_device *fbdev) | ||
35 | { | ||
36 | return 0; | ||
37 | } | ||
38 | |||
39 | static void apollon_panel_cleanup(struct lcd_panel *panel) | ||
40 | { | ||
41 | } | ||
42 | |||
43 | static int apollon_panel_enable(struct lcd_panel *panel) | ||
44 | { | ||
45 | return 0; | ||
46 | } | ||
47 | |||
48 | static void apollon_panel_disable(struct lcd_panel *panel) | ||
49 | { | ||
50 | } | ||
51 | |||
52 | static unsigned long apollon_panel_get_caps(struct lcd_panel *panel) | ||
53 | { | ||
54 | return 0; | ||
55 | } | ||
56 | |||
57 | struct lcd_panel apollon_panel = { | ||
58 | .name = "apollon", | ||
59 | .config = OMAP_LCDC_PANEL_TFT | OMAP_LCDC_INV_VSYNC | | ||
60 | OMAP_LCDC_INV_HSYNC, | ||
61 | |||
62 | .bpp = 16, | ||
63 | .data_lines = 18, | ||
64 | #ifdef USE_35INCH_LCD | ||
65 | .x_res = 240, | ||
66 | .y_res = 320, | ||
67 | .hsw = 2, | ||
68 | .hfp = 3, | ||
69 | .hbp = 9, | ||
70 | .vsw = 4, | ||
71 | .vfp = 3, | ||
72 | .vbp = 5, | ||
73 | #else | ||
74 | .x_res = 480, | ||
75 | .y_res = 272, | ||
76 | .hsw = 41, | ||
77 | .hfp = 2, | ||
78 | .hbp = 2, | ||
79 | .vsw = 10, | ||
80 | .vfp = 2, | ||
81 | .vbp = 2, | ||
82 | #endif | ||
83 | .pixel_clock = 6250, | ||
84 | |||
85 | .init = apollon_panel_init, | ||
86 | .cleanup = apollon_panel_cleanup, | ||
87 | .enable = apollon_panel_enable, | ||
88 | .disable = apollon_panel_disable, | ||
89 | .get_caps = apollon_panel_get_caps, | ||
90 | }; | ||
91 | |||
92 | static int apollon_panel_probe(struct platform_device *pdev) | ||
93 | { | ||
94 | omapfb_register_panel(&apollon_panel); | ||
95 | return 0; | ||
96 | } | ||
97 | |||
98 | static int apollon_panel_remove(struct platform_device *pdev) | ||
99 | { | ||
100 | return 0; | ||
101 | } | ||
102 | |||
103 | static int apollon_panel_suspend(struct platform_device *pdev, | ||
104 | pm_message_t mesg) | ||
105 | { | ||
106 | return 0; | ||
107 | } | ||
108 | |||
109 | static int apollon_panel_resume(struct platform_device *pdev) | ||
110 | { | ||
111 | return 0; | ||
112 | } | ||
113 | |||
114 | struct platform_driver apollon_panel_driver = { | ||
115 | .probe = apollon_panel_probe, | ||
116 | .remove = apollon_panel_remove, | ||
117 | .suspend = apollon_panel_suspend, | ||
118 | .resume = apollon_panel_resume, | ||
119 | .driver = { | ||
120 | .name = "apollon_lcd", | ||
121 | .owner = THIS_MODULE, | ||
122 | }, | ||
123 | }; | ||
124 | |||
125 | static int __init apollon_panel_drv_init(void) | ||
126 | { | ||
127 | return platform_driver_register(&apollon_panel_driver); | ||
128 | } | ||
129 | |||
130 | static void __exit apollon_panel_drv_exit(void) | ||
131 | { | ||
132 | platform_driver_unregister(&apollon_panel_driver); | ||
133 | } | ||
134 | |||
135 | module_init(apollon_panel_drv_init); | ||
136 | module_exit(apollon_panel_drv_exit); | ||
diff --git a/drivers/video/omap/lcd_h4.c b/drivers/video/omap/lcd_h4.c deleted file mode 100644 index 03a06a982750..000000000000 --- a/drivers/video/omap/lcd_h4.c +++ /dev/null | |||
@@ -1,117 +0,0 @@ | |||
1 | /* | ||
2 | * LCD panel support for the TI OMAP H4 board | ||
3 | * | ||
4 | * Copyright (C) 2004 Nokia Corporation | ||
5 | * Author: Imre Deak <imre.deak@nokia.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify it | ||
8 | * under the terms of the GNU General Public License as published by the | ||
9 | * Free Software Foundation; either version 2 of the License, or (at your | ||
10 | * option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but | ||
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License along | ||
18 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
19 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
20 | */ | ||
21 | |||
22 | #include <linux/module.h> | ||
23 | #include <linux/platform_device.h> | ||
24 | |||
25 | #include "omapfb.h" | ||
26 | |||
27 | static int h4_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev) | ||
28 | { | ||
29 | return 0; | ||
30 | } | ||
31 | |||
32 | static void h4_panel_cleanup(struct lcd_panel *panel) | ||
33 | { | ||
34 | } | ||
35 | |||
36 | static int h4_panel_enable(struct lcd_panel *panel) | ||
37 | { | ||
38 | return 0; | ||
39 | } | ||
40 | |||
41 | static void h4_panel_disable(struct lcd_panel *panel) | ||
42 | { | ||
43 | } | ||
44 | |||
45 | static unsigned long h4_panel_get_caps(struct lcd_panel *panel) | ||
46 | { | ||
47 | return 0; | ||
48 | } | ||
49 | |||
50 | static struct lcd_panel h4_panel = { | ||
51 | .name = "h4", | ||
52 | .config = OMAP_LCDC_PANEL_TFT, | ||
53 | |||
54 | .bpp = 16, | ||
55 | .data_lines = 16, | ||
56 | .x_res = 240, | ||
57 | .y_res = 320, | ||
58 | .pixel_clock = 6250, | ||
59 | .hsw = 15, | ||
60 | .hfp = 15, | ||
61 | .hbp = 60, | ||
62 | .vsw = 1, | ||
63 | .vfp = 1, | ||
64 | .vbp = 1, | ||
65 | |||
66 | .init = h4_panel_init, | ||
67 | .cleanup = h4_panel_cleanup, | ||
68 | .enable = h4_panel_enable, | ||
69 | .disable = h4_panel_disable, | ||
70 | .get_caps = h4_panel_get_caps, | ||
71 | }; | ||
72 | |||
73 | static int h4_panel_probe(struct platform_device *pdev) | ||
74 | { | ||
75 | omapfb_register_panel(&h4_panel); | ||
76 | return 0; | ||
77 | } | ||
78 | |||
79 | static int h4_panel_remove(struct platform_device *pdev) | ||
80 | { | ||
81 | return 0; | ||
82 | } | ||
83 | |||
84 | static int h4_panel_suspend(struct platform_device *pdev, pm_message_t mesg) | ||
85 | { | ||
86 | return 0; | ||
87 | } | ||
88 | |||
89 | static int h4_panel_resume(struct platform_device *pdev) | ||
90 | { | ||
91 | return 0; | ||
92 | } | ||
93 | |||
94 | static struct platform_driver h4_panel_driver = { | ||
95 | .probe = h4_panel_probe, | ||
96 | .remove = h4_panel_remove, | ||
97 | .suspend = h4_panel_suspend, | ||
98 | .resume = h4_panel_resume, | ||
99 | .driver = { | ||
100 | .name = "lcd_h4", | ||
101 | .owner = THIS_MODULE, | ||
102 | }, | ||
103 | }; | ||
104 | |||
105 | static int __init h4_panel_drv_init(void) | ||
106 | { | ||
107 | return platform_driver_register(&h4_panel_driver); | ||
108 | } | ||
109 | |||
110 | static void __exit h4_panel_drv_cleanup(void) | ||
111 | { | ||
112 | platform_driver_unregister(&h4_panel_driver); | ||
113 | } | ||
114 | |||
115 | module_init(h4_panel_drv_init); | ||
116 | module_exit(h4_panel_drv_cleanup); | ||
117 | |||
diff --git a/drivers/video/omap/lcd_ldp.c b/drivers/video/omap/lcd_ldp.c deleted file mode 100644 index 062466402c0e..000000000000 --- a/drivers/video/omap/lcd_ldp.c +++ /dev/null | |||
@@ -1,201 +0,0 @@ | |||
1 | /* | ||
2 | * LCD panel support for the TI LDP board | ||
3 | * | ||
4 | * Copyright (C) 2007 WindRiver | ||
5 | * Author: Stanley Miao <stanley.miao@windriver.com> | ||
6 | * | ||
7 | * Derived from drivers/video/omap/lcd-2430sdp.c | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License as published by the | ||
11 | * Free Software Foundation; either version 2 of the License, or (at your | ||
12 | * option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License along | ||
20 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
21 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
22 | */ | ||
23 | |||
24 | #include <linux/module.h> | ||
25 | #include <linux/platform_device.h> | ||
26 | #include <linux/delay.h> | ||
27 | #include <linux/i2c/twl.h> | ||
28 | |||
29 | #include <asm/gpio.h> | ||
30 | #include <plat/mux.h> | ||
31 | #include <asm/mach-types.h> | ||
32 | |||
33 | #include "omapfb.h" | ||
34 | |||
35 | #define LCD_PANEL_BACKLIGHT_GPIO (15 + OMAP_MAX_GPIO_LINES) | ||
36 | #define LCD_PANEL_ENABLE_GPIO (7 + OMAP_MAX_GPIO_LINES) | ||
37 | |||
38 | #define LCD_PANEL_RESET_GPIO 55 | ||
39 | #define LCD_PANEL_QVGA_GPIO 56 | ||
40 | |||
41 | #ifdef CONFIG_FB_OMAP_LCD_VGA | ||
42 | #define LCD_XRES 480 | ||
43 | #define LCD_YRES 640 | ||
44 | #define LCD_PIXCLOCK_MAX 41700 | ||
45 | #else | ||
46 | #define LCD_XRES 240 | ||
47 | #define LCD_YRES 320 | ||
48 | #define LCD_PIXCLOCK_MAX 185186 | ||
49 | #endif | ||
50 | |||
51 | #define PM_RECEIVER TWL4030_MODULE_PM_RECEIVER | ||
52 | #define ENABLE_VAUX2_DEDICATED 0x09 | ||
53 | #define ENABLE_VAUX2_DEV_GRP 0x20 | ||
54 | #define ENABLE_VAUX3_DEDICATED 0x03 | ||
55 | #define ENABLE_VAUX3_DEV_GRP 0x20 | ||
56 | |||
57 | #define ENABLE_VPLL2_DEDICATED 0x05 | ||
58 | #define ENABLE_VPLL2_DEV_GRP 0xE0 | ||
59 | #define TWL4030_VPLL2_DEV_GRP 0x33 | ||
60 | #define TWL4030_VPLL2_DEDICATED 0x36 | ||
61 | |||
62 | #define t2_out(c, r, v) twl_i2c_write_u8(c, r, v) | ||
63 | |||
64 | |||
65 | static int ldp_panel_init(struct lcd_panel *panel, | ||
66 | struct omapfb_device *fbdev) | ||
67 | { | ||
68 | gpio_request(LCD_PANEL_RESET_GPIO, "lcd reset"); | ||
69 | gpio_request(LCD_PANEL_QVGA_GPIO, "lcd qvga"); | ||
70 | gpio_request(LCD_PANEL_ENABLE_GPIO, "lcd panel"); | ||
71 | gpio_request(LCD_PANEL_BACKLIGHT_GPIO, "lcd backlight"); | ||
72 | |||
73 | gpio_direction_output(LCD_PANEL_QVGA_GPIO, 0); | ||
74 | gpio_direction_output(LCD_PANEL_RESET_GPIO, 0); | ||
75 | gpio_direction_output(LCD_PANEL_ENABLE_GPIO, 0); | ||
76 | gpio_direction_output(LCD_PANEL_BACKLIGHT_GPIO, 0); | ||
77 | |||
78 | #ifdef CONFIG_FB_OMAP_LCD_VGA | ||
79 | gpio_set_value(LCD_PANEL_QVGA_GPIO, 0); | ||
80 | #else | ||
81 | gpio_set_value(LCD_PANEL_QVGA_GPIO, 1); | ||
82 | #endif | ||
83 | gpio_set_value(LCD_PANEL_RESET_GPIO, 1); | ||
84 | |||
85 | return 0; | ||
86 | } | ||
87 | |||
88 | static void ldp_panel_cleanup(struct lcd_panel *panel) | ||
89 | { | ||
90 | gpio_free(LCD_PANEL_BACKLIGHT_GPIO); | ||
91 | gpio_free(LCD_PANEL_ENABLE_GPIO); | ||
92 | gpio_free(LCD_PANEL_QVGA_GPIO); | ||
93 | gpio_free(LCD_PANEL_RESET_GPIO); | ||
94 | } | ||
95 | |||
96 | static int ldp_panel_enable(struct lcd_panel *panel) | ||
97 | { | ||
98 | if (0 != t2_out(PM_RECEIVER, ENABLE_VPLL2_DEDICATED, | ||
99 | TWL4030_VPLL2_DEDICATED)) | ||
100 | return -EIO; | ||
101 | if (0 != t2_out(PM_RECEIVER, ENABLE_VPLL2_DEV_GRP, | ||
102 | TWL4030_VPLL2_DEV_GRP)) | ||
103 | return -EIO; | ||
104 | |||
105 | gpio_direction_output(LCD_PANEL_ENABLE_GPIO, 1); | ||
106 | gpio_direction_output(LCD_PANEL_BACKLIGHT_GPIO, 1); | ||
107 | |||
108 | if (0 != t2_out(PM_RECEIVER, ENABLE_VAUX3_DEDICATED, | ||
109 | TWL4030_VAUX3_DEDICATED)) | ||
110 | return -EIO; | ||
111 | if (0 != t2_out(PM_RECEIVER, ENABLE_VAUX3_DEV_GRP, | ||
112 | TWL4030_VAUX3_DEV_GRP)) | ||
113 | return -EIO; | ||
114 | |||
115 | return 0; | ||
116 | } | ||
117 | |||
118 | static void ldp_panel_disable(struct lcd_panel *panel) | ||
119 | { | ||
120 | gpio_direction_output(LCD_PANEL_ENABLE_GPIO, 0); | ||
121 | gpio_direction_output(LCD_PANEL_BACKLIGHT_GPIO, 0); | ||
122 | |||
123 | t2_out(PM_RECEIVER, 0x0, TWL4030_VPLL2_DEDICATED); | ||
124 | t2_out(PM_RECEIVER, 0x0, TWL4030_VPLL2_DEV_GRP); | ||
125 | msleep(4); | ||
126 | } | ||
127 | |||
128 | static unsigned long ldp_panel_get_caps(struct lcd_panel *panel) | ||
129 | { | ||
130 | return 0; | ||
131 | } | ||
132 | |||
133 | struct lcd_panel ldp_panel = { | ||
134 | .name = "ldp", | ||
135 | .config = OMAP_LCDC_PANEL_TFT | OMAP_LCDC_INV_VSYNC | | ||
136 | OMAP_LCDC_INV_HSYNC, | ||
137 | |||
138 | .bpp = 16, | ||
139 | .data_lines = 18, | ||
140 | .x_res = LCD_XRES, | ||
141 | .y_res = LCD_YRES, | ||
142 | .hsw = 3, /* hsync_len (4) - 1 */ | ||
143 | .hfp = 3, /* right_margin (4) - 1 */ | ||
144 | .hbp = 39, /* left_margin (40) - 1 */ | ||
145 | .vsw = 1, /* vsync_len (2) - 1 */ | ||
146 | .vfp = 2, /* lower_margin */ | ||
147 | .vbp = 7, /* upper_margin (8) - 1 */ | ||
148 | |||
149 | .pixel_clock = LCD_PIXCLOCK_MAX, | ||
150 | |||
151 | .init = ldp_panel_init, | ||
152 | .cleanup = ldp_panel_cleanup, | ||
153 | .enable = ldp_panel_enable, | ||
154 | .disable = ldp_panel_disable, | ||
155 | .get_caps = ldp_panel_get_caps, | ||
156 | }; | ||
157 | |||
158 | static int ldp_panel_probe(struct platform_device *pdev) | ||
159 | { | ||
160 | omapfb_register_panel(&ldp_panel); | ||
161 | return 0; | ||
162 | } | ||
163 | |||
164 | static int ldp_panel_remove(struct platform_device *pdev) | ||
165 | { | ||
166 | return 0; | ||
167 | } | ||
168 | |||
169 | static int ldp_panel_suspend(struct platform_device *pdev, pm_message_t mesg) | ||
170 | { | ||
171 | return 0; | ||
172 | } | ||
173 | |||
174 | static int ldp_panel_resume(struct platform_device *pdev) | ||
175 | { | ||
176 | return 0; | ||
177 | } | ||
178 | |||
179 | struct platform_driver ldp_panel_driver = { | ||
180 | .probe = ldp_panel_probe, | ||
181 | .remove = ldp_panel_remove, | ||
182 | .suspend = ldp_panel_suspend, | ||
183 | .resume = ldp_panel_resume, | ||
184 | .driver = { | ||
185 | .name = "ldp_lcd", | ||
186 | .owner = THIS_MODULE, | ||
187 | }, | ||
188 | }; | ||
189 | |||
190 | static int __init ldp_panel_drv_init(void) | ||
191 | { | ||
192 | return platform_driver_register(&ldp_panel_driver); | ||
193 | } | ||
194 | |||
195 | static void __exit ldp_panel_drv_exit(void) | ||
196 | { | ||
197 | platform_driver_unregister(&ldp_panel_driver); | ||
198 | } | ||
199 | |||
200 | module_init(ldp_panel_drv_init); | ||
201 | module_exit(ldp_panel_drv_exit); | ||
diff --git a/drivers/video/omap/lcd_omap3beagle.c b/drivers/video/omap/lcd_omap3beagle.c deleted file mode 100644 index d7c6c3e0afc6..000000000000 --- a/drivers/video/omap/lcd_omap3beagle.c +++ /dev/null | |||
@@ -1,130 +0,0 @@ | |||
1 | /* | ||
2 | * LCD panel support for the TI OMAP3 Beagle board | ||
3 | * | ||
4 | * Author: Koen Kooi <koen@openembedded.org> | ||
5 | * | ||
6 | * Derived from drivers/video/omap/lcd-omap3evm.c | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License along | ||
19 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
20 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
21 | */ | ||
22 | |||
23 | #include <linux/module.h> | ||
24 | #include <linux/platform_device.h> | ||
25 | #include <linux/gpio.h> | ||
26 | #include <linux/i2c/twl.h> | ||
27 | |||
28 | #include <asm/mach-types.h> | ||
29 | |||
30 | #include "omapfb.h" | ||
31 | |||
32 | #define LCD_PANEL_ENABLE_GPIO 170 | ||
33 | |||
34 | static int omap3beagle_panel_init(struct lcd_panel *panel, | ||
35 | struct omapfb_device *fbdev) | ||
36 | { | ||
37 | gpio_request(LCD_PANEL_ENABLE_GPIO, "LCD enable"); | ||
38 | return 0; | ||
39 | } | ||
40 | |||
41 | static void omap3beagle_panel_cleanup(struct lcd_panel *panel) | ||
42 | { | ||
43 | gpio_free(LCD_PANEL_ENABLE_GPIO); | ||
44 | } | ||
45 | |||
46 | static int omap3beagle_panel_enable(struct lcd_panel *panel) | ||
47 | { | ||
48 | gpio_set_value(LCD_PANEL_ENABLE_GPIO, 1); | ||
49 | return 0; | ||
50 | } | ||
51 | |||
52 | static void omap3beagle_panel_disable(struct lcd_panel *panel) | ||
53 | { | ||
54 | gpio_set_value(LCD_PANEL_ENABLE_GPIO, 0); | ||
55 | } | ||
56 | |||
57 | static unsigned long omap3beagle_panel_get_caps(struct lcd_panel *panel) | ||
58 | { | ||
59 | return 0; | ||
60 | } | ||
61 | |||
62 | struct lcd_panel omap3beagle_panel = { | ||
63 | .name = "omap3beagle", | ||
64 | .config = OMAP_LCDC_PANEL_TFT, | ||
65 | |||
66 | .bpp = 16, | ||
67 | .data_lines = 24, | ||
68 | .x_res = 1024, | ||
69 | .y_res = 768, | ||
70 | .hsw = 3, /* hsync_len (4) - 1 */ | ||
71 | .hfp = 3, /* right_margin (4) - 1 */ | ||
72 | .hbp = 39, /* left_margin (40) - 1 */ | ||
73 | .vsw = 1, /* vsync_len (2) - 1 */ | ||
74 | .vfp = 2, /* lower_margin */ | ||
75 | .vbp = 7, /* upper_margin (8) - 1 */ | ||
76 | |||
77 | .pixel_clock = 64000, | ||
78 | |||
79 | .init = omap3beagle_panel_init, | ||
80 | .cleanup = omap3beagle_panel_cleanup, | ||
81 | .enable = omap3beagle_panel_enable, | ||
82 | .disable = omap3beagle_panel_disable, | ||
83 | .get_caps = omap3beagle_panel_get_caps, | ||
84 | }; | ||
85 | |||
86 | static int omap3beagle_panel_probe(struct platform_device *pdev) | ||
87 | { | ||
88 | omapfb_register_panel(&omap3beagle_panel); | ||
89 | return 0; | ||
90 | } | ||
91 | |||
92 | static int omap3beagle_panel_remove(struct platform_device *pdev) | ||
93 | { | ||
94 | return 0; | ||
95 | } | ||
96 | |||
97 | static int omap3beagle_panel_suspend(struct platform_device *pdev, | ||
98 | pm_message_t mesg) | ||
99 | { | ||
100 | return 0; | ||
101 | } | ||
102 | |||
103 | static int omap3beagle_panel_resume(struct platform_device *pdev) | ||
104 | { | ||
105 | return 0; | ||
106 | } | ||
107 | |||
108 | struct platform_driver omap3beagle_panel_driver = { | ||
109 | .probe = omap3beagle_panel_probe, | ||
110 | .remove = omap3beagle_panel_remove, | ||
111 | .suspend = omap3beagle_panel_suspend, | ||
112 | .resume = omap3beagle_panel_resume, | ||
113 | .driver = { | ||
114 | .name = "omap3beagle_lcd", | ||
115 | .owner = THIS_MODULE, | ||
116 | }, | ||
117 | }; | ||
118 | |||
119 | static int __init omap3beagle_panel_drv_init(void) | ||
120 | { | ||
121 | return platform_driver_register(&omap3beagle_panel_driver); | ||
122 | } | ||
123 | |||
124 | static void __exit omap3beagle_panel_drv_exit(void) | ||
125 | { | ||
126 | platform_driver_unregister(&omap3beagle_panel_driver); | ||
127 | } | ||
128 | |||
129 | module_init(omap3beagle_panel_drv_init); | ||
130 | module_exit(omap3beagle_panel_drv_exit); | ||
diff --git a/drivers/video/omap/lcd_omap3evm.c b/drivers/video/omap/lcd_omap3evm.c deleted file mode 100644 index 06840da0b094..000000000000 --- a/drivers/video/omap/lcd_omap3evm.c +++ /dev/null | |||
@@ -1,193 +0,0 @@ | |||
1 | /* | ||
2 | * LCD panel support for the TI OMAP3 EVM board | ||
3 | * | ||
4 | * Author: Steve Sakoman <steve@sakoman.com> | ||
5 | * | ||
6 | * Derived from drivers/video/omap/lcd-apollon.c | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License along | ||
19 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
20 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
21 | */ | ||
22 | |||
23 | #include <linux/module.h> | ||
24 | #include <linux/platform_device.h> | ||
25 | #include <linux/gpio.h> | ||
26 | #include <linux/i2c/twl.h> | ||
27 | |||
28 | #include <plat/mux.h> | ||
29 | #include <asm/mach-types.h> | ||
30 | |||
31 | #include "omapfb.h" | ||
32 | |||
33 | #define LCD_PANEL_ENABLE_GPIO 153 | ||
34 | #define LCD_PANEL_LR 2 | ||
35 | #define LCD_PANEL_UD 3 | ||
36 | #define LCD_PANEL_INI 152 | ||
37 | #define LCD_PANEL_QVGA 154 | ||
38 | #define LCD_PANEL_RESB 155 | ||
39 | |||
40 | #define ENABLE_VDAC_DEDICATED 0x03 | ||
41 | #define ENABLE_VDAC_DEV_GRP 0x20 | ||
42 | #define ENABLE_VPLL2_DEDICATED 0x05 | ||
43 | #define ENABLE_VPLL2_DEV_GRP 0xE0 | ||
44 | |||
45 | #define TWL_LED_LEDEN 0x00 | ||
46 | #define TWL_PWMA_PWMAON 0x00 | ||
47 | #define TWL_PWMA_PWMAOFF 0x01 | ||
48 | |||
49 | static unsigned int bklight_level; | ||
50 | |||
51 | static int omap3evm_panel_init(struct lcd_panel *panel, | ||
52 | struct omapfb_device *fbdev) | ||
53 | { | ||
54 | gpio_request(LCD_PANEL_LR, "LCD lr"); | ||
55 | gpio_request(LCD_PANEL_UD, "LCD ud"); | ||
56 | gpio_request(LCD_PANEL_INI, "LCD ini"); | ||
57 | gpio_request(LCD_PANEL_RESB, "LCD resb"); | ||
58 | gpio_request(LCD_PANEL_QVGA, "LCD qvga"); | ||
59 | |||
60 | gpio_direction_output(LCD_PANEL_RESB, 1); | ||
61 | gpio_direction_output(LCD_PANEL_INI, 1); | ||
62 | gpio_direction_output(LCD_PANEL_QVGA, 0); | ||
63 | gpio_direction_output(LCD_PANEL_LR, 1); | ||
64 | gpio_direction_output(LCD_PANEL_UD, 1); | ||
65 | |||
66 | twl_i2c_write_u8(TWL4030_MODULE_LED, 0x11, TWL_LED_LEDEN); | ||
67 | twl_i2c_write_u8(TWL4030_MODULE_PWMA, 0x01, TWL_PWMA_PWMAON); | ||
68 | twl_i2c_write_u8(TWL4030_MODULE_PWMA, 0x02, TWL_PWMA_PWMAOFF); | ||
69 | bklight_level = 100; | ||
70 | |||
71 | return 0; | ||
72 | } | ||
73 | |||
74 | static void omap3evm_panel_cleanup(struct lcd_panel *panel) | ||
75 | { | ||
76 | gpio_free(LCD_PANEL_QVGA); | ||
77 | gpio_free(LCD_PANEL_RESB); | ||
78 | gpio_free(LCD_PANEL_INI); | ||
79 | gpio_free(LCD_PANEL_UD); | ||
80 | gpio_free(LCD_PANEL_LR); | ||
81 | } | ||
82 | |||
83 | static int omap3evm_panel_enable(struct lcd_panel *panel) | ||
84 | { | ||
85 | gpio_set_value(LCD_PANEL_ENABLE_GPIO, 0); | ||
86 | return 0; | ||
87 | } | ||
88 | |||
89 | static void omap3evm_panel_disable(struct lcd_panel *panel) | ||
90 | { | ||
91 | gpio_set_value(LCD_PANEL_ENABLE_GPIO, 1); | ||
92 | } | ||
93 | |||
94 | static unsigned long omap3evm_panel_get_caps(struct lcd_panel *panel) | ||
95 | { | ||
96 | return 0; | ||
97 | } | ||
98 | |||
99 | static int omap3evm_bklight_setlevel(struct lcd_panel *panel, | ||
100 | unsigned int level) | ||
101 | { | ||
102 | u8 c; | ||
103 | if ((level >= 0) && (level <= 100)) { | ||
104 | c = (125 * (100 - level)) / 100 + 2; | ||
105 | twl_i2c_write_u8(TWL4030_MODULE_PWMA, c, TWL_PWMA_PWMAOFF); | ||
106 | bklight_level = level; | ||
107 | } | ||
108 | return 0; | ||
109 | } | ||
110 | |||
111 | static unsigned int omap3evm_bklight_getlevel(struct lcd_panel *panel) | ||
112 | { | ||
113 | return bklight_level; | ||
114 | } | ||
115 | |||
116 | static unsigned int omap3evm_bklight_getmaxlevel(struct lcd_panel *panel) | ||
117 | { | ||
118 | return 100; | ||
119 | } | ||
120 | |||
121 | struct lcd_panel omap3evm_panel = { | ||
122 | .name = "omap3evm", | ||
123 | .config = OMAP_LCDC_PANEL_TFT | OMAP_LCDC_INV_VSYNC | | ||
124 | OMAP_LCDC_INV_HSYNC, | ||
125 | |||
126 | .bpp = 16, | ||
127 | .data_lines = 18, | ||
128 | .x_res = 480, | ||
129 | .y_res = 640, | ||
130 | .hsw = 3, /* hsync_len (4) - 1 */ | ||
131 | .hfp = 3, /* right_margin (4) - 1 */ | ||
132 | .hbp = 39, /* left_margin (40) - 1 */ | ||
133 | .vsw = 1, /* vsync_len (2) - 1 */ | ||
134 | .vfp = 2, /* lower_margin */ | ||
135 | .vbp = 7, /* upper_margin (8) - 1 */ | ||
136 | |||
137 | .pixel_clock = 26000, | ||
138 | |||
139 | .init = omap3evm_panel_init, | ||
140 | .cleanup = omap3evm_panel_cleanup, | ||
141 | .enable = omap3evm_panel_enable, | ||
142 | .disable = omap3evm_panel_disable, | ||
143 | .get_caps = omap3evm_panel_get_caps, | ||
144 | .set_bklight_level = omap3evm_bklight_setlevel, | ||
145 | .get_bklight_level = omap3evm_bklight_getlevel, | ||
146 | .get_bklight_max = omap3evm_bklight_getmaxlevel, | ||
147 | }; | ||
148 | |||
149 | static int omap3evm_panel_probe(struct platform_device *pdev) | ||
150 | { | ||
151 | omapfb_register_panel(&omap3evm_panel); | ||
152 | return 0; | ||
153 | } | ||
154 | |||
155 | static int omap3evm_panel_remove(struct platform_device *pdev) | ||
156 | { | ||
157 | return 0; | ||
158 | } | ||
159 | |||
160 | static int omap3evm_panel_suspend(struct platform_device *pdev, | ||
161 | pm_message_t mesg) | ||
162 | { | ||
163 | return 0; | ||
164 | } | ||
165 | |||
166 | static int omap3evm_panel_resume(struct platform_device *pdev) | ||
167 | { | ||
168 | return 0; | ||
169 | } | ||
170 | |||
171 | struct platform_driver omap3evm_panel_driver = { | ||
172 | .probe = omap3evm_panel_probe, | ||
173 | .remove = omap3evm_panel_remove, | ||
174 | .suspend = omap3evm_panel_suspend, | ||
175 | .resume = omap3evm_panel_resume, | ||
176 | .driver = { | ||
177 | .name = "omap3evm_lcd", | ||
178 | .owner = THIS_MODULE, | ||
179 | }, | ||
180 | }; | ||
181 | |||
182 | static int __init omap3evm_panel_drv_init(void) | ||
183 | { | ||
184 | return platform_driver_register(&omap3evm_panel_driver); | ||
185 | } | ||
186 | |||
187 | static void __exit omap3evm_panel_drv_exit(void) | ||
188 | { | ||
189 | platform_driver_unregister(&omap3evm_panel_driver); | ||
190 | } | ||
191 | |||
192 | module_init(omap3evm_panel_drv_init); | ||
193 | module_exit(omap3evm_panel_drv_exit); | ||
diff --git a/drivers/video/omap/lcd_overo.c b/drivers/video/omap/lcd_overo.c deleted file mode 100644 index b8fd5b2ec29c..000000000000 --- a/drivers/video/omap/lcd_overo.c +++ /dev/null | |||
@@ -1,180 +0,0 @@ | |||
1 | /* | ||
2 | * LCD panel support for the Gumstix Overo | ||
3 | * | ||
4 | * Author: Steve Sakoman <steve@sakoman.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License as published by the | ||
8 | * Free Software Foundation; either version 2 of the License, or (at your | ||
9 | * option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, but | ||
12 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | * General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License along | ||
17 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
18 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
19 | * | ||
20 | */ | ||
21 | |||
22 | #include <linux/module.h> | ||
23 | #include <linux/platform_device.h> | ||
24 | #include <linux/i2c/twl.h> | ||
25 | |||
26 | #include <asm/gpio.h> | ||
27 | #include <plat/mux.h> | ||
28 | #include <asm/mach-types.h> | ||
29 | |||
30 | #include "omapfb.h" | ||
31 | |||
32 | #define LCD_ENABLE 144 | ||
33 | |||
34 | static int overo_panel_init(struct lcd_panel *panel, | ||
35 | struct omapfb_device *fbdev) | ||
36 | { | ||
37 | if ((gpio_request(LCD_ENABLE, "LCD_ENABLE") == 0) && | ||
38 | (gpio_direction_output(LCD_ENABLE, 1) == 0)) | ||
39 | gpio_export(LCD_ENABLE, 0); | ||
40 | else | ||
41 | printk(KERN_ERR "could not obtain gpio for LCD_ENABLE\n"); | ||
42 | |||
43 | return 0; | ||
44 | } | ||
45 | |||
46 | static void overo_panel_cleanup(struct lcd_panel *panel) | ||
47 | { | ||
48 | gpio_free(LCD_ENABLE); | ||
49 | } | ||
50 | |||
51 | static int overo_panel_enable(struct lcd_panel *panel) | ||
52 | { | ||
53 | gpio_set_value(LCD_ENABLE, 1); | ||
54 | return 0; | ||
55 | } | ||
56 | |||
57 | static void overo_panel_disable(struct lcd_panel *panel) | ||
58 | { | ||
59 | gpio_set_value(LCD_ENABLE, 0); | ||
60 | } | ||
61 | |||
62 | static unsigned long overo_panel_get_caps(struct lcd_panel *panel) | ||
63 | { | ||
64 | return 0; | ||
65 | } | ||
66 | |||
67 | struct lcd_panel overo_panel = { | ||
68 | .name = "overo", | ||
69 | .config = OMAP_LCDC_PANEL_TFT, | ||
70 | .bpp = 16, | ||
71 | .data_lines = 24, | ||
72 | |||
73 | #if defined CONFIG_FB_OMAP_031M3R | ||
74 | |||
75 | /* 640 x 480 @ 60 Hz Reduced blanking VESA CVT 0.31M3-R */ | ||
76 | .x_res = 640, | ||
77 | .y_res = 480, | ||
78 | .hfp = 48, | ||
79 | .hsw = 32, | ||
80 | .hbp = 80, | ||
81 | .vfp = 3, | ||
82 | .vsw = 4, | ||
83 | .vbp = 7, | ||
84 | .pixel_clock = 23500, | ||
85 | |||
86 | #elif defined CONFIG_FB_OMAP_048M3R | ||
87 | |||
88 | /* 800 x 600 @ 60 Hz Reduced blanking VESA CVT 0.48M3-R */ | ||
89 | .x_res = 800, | ||
90 | .y_res = 600, | ||
91 | .hfp = 48, | ||
92 | .hsw = 32, | ||
93 | .hbp = 80, | ||
94 | .vfp = 3, | ||
95 | .vsw = 4, | ||
96 | .vbp = 11, | ||
97 | .pixel_clock = 35500, | ||
98 | |||
99 | #elif defined CONFIG_FB_OMAP_079M3R | ||
100 | |||
101 | /* 1024 x 768 @ 60 Hz Reduced blanking VESA CVT 0.79M3-R */ | ||
102 | .x_res = 1024, | ||
103 | .y_res = 768, | ||
104 | .hfp = 48, | ||
105 | .hsw = 32, | ||
106 | .hbp = 80, | ||
107 | .vfp = 3, | ||
108 | .vsw = 4, | ||
109 | .vbp = 15, | ||
110 | .pixel_clock = 56000, | ||
111 | |||
112 | #elif defined CONFIG_FB_OMAP_092M9R | ||
113 | |||
114 | /* 1280 x 720 @ 60 Hz Reduced blanking VESA CVT 0.92M9-R */ | ||
115 | .x_res = 1280, | ||
116 | .y_res = 720, | ||
117 | .hfp = 48, | ||
118 | .hsw = 32, | ||
119 | .hbp = 80, | ||
120 | .vfp = 3, | ||
121 | .vsw = 5, | ||
122 | .vbp = 13, | ||
123 | .pixel_clock = 64000, | ||
124 | |||
125 | #else | ||
126 | |||
127 | /* use 640 x 480 if no config option */ | ||
128 | /* 640 x 480 @ 60 Hz Reduced blanking VESA CVT 0.31M3-R */ | ||
129 | .x_res = 640, | ||
130 | .y_res = 480, | ||
131 | .hfp = 48, | ||
132 | .hsw = 32, | ||
133 | .hbp = 80, | ||
134 | .vfp = 3, | ||
135 | .vsw = 4, | ||
136 | .vbp = 7, | ||
137 | .pixel_clock = 23500, | ||
138 | |||
139 | #endif | ||
140 | |||
141 | .init = overo_panel_init, | ||
142 | .cleanup = overo_panel_cleanup, | ||
143 | .enable = overo_panel_enable, | ||
144 | .disable = overo_panel_disable, | ||
145 | .get_caps = overo_panel_get_caps, | ||
146 | }; | ||
147 | |||
148 | static int overo_panel_probe(struct platform_device *pdev) | ||
149 | { | ||
150 | omapfb_register_panel(&overo_panel); | ||
151 | return 0; | ||
152 | } | ||
153 | |||
154 | static int overo_panel_remove(struct platform_device *pdev) | ||
155 | { | ||
156 | /* omapfb does not have unregister_panel */ | ||
157 | return 0; | ||
158 | } | ||
159 | |||
160 | static struct platform_driver overo_panel_driver = { | ||
161 | .probe = overo_panel_probe, | ||
162 | .remove = overo_panel_remove, | ||
163 | .driver = { | ||
164 | .name = "overo_lcd", | ||
165 | .owner = THIS_MODULE, | ||
166 | }, | ||
167 | }; | ||
168 | |||
169 | static int __init overo_panel_drv_init(void) | ||
170 | { | ||
171 | return platform_driver_register(&overo_panel_driver); | ||
172 | } | ||
173 | |||
174 | static void __exit overo_panel_drv_exit(void) | ||
175 | { | ||
176 | platform_driver_unregister(&overo_panel_driver); | ||
177 | } | ||
178 | |||
179 | module_init(overo_panel_drv_init); | ||
180 | module_exit(overo_panel_drv_exit); | ||
diff --git a/drivers/video/omap2/displays/Kconfig b/drivers/video/omap2/displays/Kconfig index 609a28073178..8d8e1fe1901c 100644 --- a/drivers/video/omap2/displays/Kconfig +++ b/drivers/video/omap2/displays/Kconfig | |||
@@ -10,6 +10,13 @@ config PANEL_GENERIC_DPI | |||
10 | Supports LCD Panel used in TI SDP3430 and EVM boards, | 10 | Supports LCD Panel used in TI SDP3430 and EVM boards, |
11 | OMAP3517 EVM boards and CM-T35. | 11 | OMAP3517 EVM boards and CM-T35. |
12 | 12 | ||
13 | config PANEL_DVI | ||
14 | tristate "DVI output" | ||
15 | depends on OMAP2_DSS_DPI | ||
16 | help | ||
17 | Driver for external monitors, connected via DVI. The driver uses i2c | ||
18 | to read EDID information from the monitor. | ||
19 | |||
13 | config PANEL_LGPHILIPS_LB035Q02 | 20 | config PANEL_LGPHILIPS_LB035Q02 |
14 | tristate "LG.Philips LB035Q02 LCD Panel" | 21 | tristate "LG.Philips LB035Q02 LCD Panel" |
15 | depends on OMAP2_DSS_DPI && SPI | 22 | depends on OMAP2_DSS_DPI && SPI |
@@ -19,20 +26,30 @@ config PANEL_LGPHILIPS_LB035Q02 | |||
19 | config PANEL_SHARP_LS037V7DW01 | 26 | config PANEL_SHARP_LS037V7DW01 |
20 | tristate "Sharp LS037V7DW01 LCD Panel" | 27 | tristate "Sharp LS037V7DW01 LCD Panel" |
21 | depends on OMAP2_DSS_DPI | 28 | depends on OMAP2_DSS_DPI |
22 | select BACKLIGHT_CLASS_DEVICE | 29 | depends on BACKLIGHT_CLASS_DEVICE |
23 | help | 30 | help |
24 | LCD Panel used in TI's SDP3430 and EVM boards | 31 | LCD Panel used in TI's SDP3430 and EVM boards |
25 | 32 | ||
26 | config PANEL_NEC_NL8048HL11_01B | 33 | config PANEL_NEC_NL8048HL11_01B |
27 | tristate "NEC NL8048HL11-01B Panel" | 34 | tristate "NEC NL8048HL11-01B Panel" |
28 | depends on OMAP2_DSS_DPI | 35 | depends on OMAP2_DSS_DPI |
36 | depends on SPI | ||
37 | depends on BACKLIGHT_CLASS_DEVICE | ||
29 | help | 38 | help |
30 | This NEC NL8048HL11-01B panel is TFT LCD | 39 | This NEC NL8048HL11-01B panel is TFT LCD |
31 | used in the Zoom2/3/3630 sdp boards. | 40 | used in the Zoom2/3/3630 sdp boards. |
32 | 41 | ||
42 | config PANEL_PICODLP | ||
43 | tristate "TI PICO DLP mini-projector" | ||
44 | depends on OMAP2_DSS && I2C | ||
45 | help | ||
46 | A mini-projector used in TI's SDP4430 and EVM boards | ||
47 | For more info please visit http://www.dlp.com/projector/ | ||
48 | |||
33 | config PANEL_TAAL | 49 | config PANEL_TAAL |
34 | tristate "Taal DSI Panel" | 50 | tristate "Taal DSI Panel" |
35 | depends on OMAP2_DSS_DSI | 51 | depends on OMAP2_DSS_DSI |
52 | depends on BACKLIGHT_CLASS_DEVICE | ||
36 | help | 53 | help |
37 | Taal DSI command mode panel from TPO. | 54 | Taal DSI command mode panel from TPO. |
38 | 55 | ||
@@ -45,7 +62,14 @@ config PANEL_TPO_TD043MTEA1 | |||
45 | config PANEL_ACX565AKM | 62 | config PANEL_ACX565AKM |
46 | tristate "ACX565AKM Panel" | 63 | tristate "ACX565AKM Panel" |
47 | depends on OMAP2_DSS_SDI && SPI | 64 | depends on OMAP2_DSS_SDI && SPI |
48 | select BACKLIGHT_CLASS_DEVICE | 65 | depends on BACKLIGHT_CLASS_DEVICE |
49 | help | 66 | help |
50 | This is the LCD panel used on Nokia N900 | 67 | This is the LCD panel used on Nokia N900 |
68 | |||
69 | config PANEL_N8X0 | ||
70 | tristate "N8X0 Panel" | ||
71 | depends on OMAP2_DSS_RFBI && SPI | ||
72 | depends on BACKLIGHT_CLASS_DEVICE | ||
73 | help | ||
74 | This is the LCD panel used on Nokia N8x0 | ||
51 | endmenu | 75 | endmenu |
diff --git a/drivers/video/omap2/displays/Makefile b/drivers/video/omap2/displays/Makefile index 0f601ab3abf4..fbfafc6eebb4 100644 --- a/drivers/video/omap2/displays/Makefile +++ b/drivers/video/omap2/displays/Makefile | |||
@@ -1,8 +1,11 @@ | |||
1 | obj-$(CONFIG_PANEL_GENERIC_DPI) += panel-generic-dpi.o | 1 | obj-$(CONFIG_PANEL_GENERIC_DPI) += panel-generic-dpi.o |
2 | obj-$(CONFIG_PANEL_DVI) += panel-dvi.o | ||
2 | obj-$(CONFIG_PANEL_LGPHILIPS_LB035Q02) += panel-lgphilips-lb035q02.o | 3 | obj-$(CONFIG_PANEL_LGPHILIPS_LB035Q02) += panel-lgphilips-lb035q02.o |
3 | obj-$(CONFIG_PANEL_SHARP_LS037V7DW01) += panel-sharp-ls037v7dw01.o | 4 | obj-$(CONFIG_PANEL_SHARP_LS037V7DW01) += panel-sharp-ls037v7dw01.o |
4 | obj-$(CONFIG_PANEL_NEC_NL8048HL11_01B) += panel-nec-nl8048hl11-01b.o | 5 | obj-$(CONFIG_PANEL_NEC_NL8048HL11_01B) += panel-nec-nl8048hl11-01b.o |
5 | 6 | ||
6 | obj-$(CONFIG_PANEL_TAAL) += panel-taal.o | 7 | obj-$(CONFIG_PANEL_TAAL) += panel-taal.o |
8 | obj-$(CONFIG_PANEL_PICODLP) += panel-picodlp.o | ||
7 | obj-$(CONFIG_PANEL_TPO_TD043MTEA1) += panel-tpo-td043mtea1.o | 9 | obj-$(CONFIG_PANEL_TPO_TD043MTEA1) += panel-tpo-td043mtea1.o |
8 | obj-$(CONFIG_PANEL_ACX565AKM) += panel-acx565akm.o | 10 | obj-$(CONFIG_PANEL_ACX565AKM) += panel-acx565akm.o |
11 | obj-$(CONFIG_PANEL_N8X0) += panel-n8x0.o | ||
diff --git a/drivers/video/omap2/displays/panel-dvi.c b/drivers/video/omap2/displays/panel-dvi.c new file mode 100644 index 000000000000..03eb14af33e0 --- /dev/null +++ b/drivers/video/omap2/displays/panel-dvi.c | |||
@@ -0,0 +1,363 @@ | |||
1 | /* | ||
2 | * DVI output support | ||
3 | * | ||
4 | * Copyright (C) 2011 Texas Instruments Inc | ||
5 | * Author: Tomi Valkeinen <tomi.valkeinen@ti.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify it | ||
8 | * under the terms of the GNU General Public License version 2 as published by | ||
9 | * the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
14 | * more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License along with | ||
17 | * this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | #include <linux/module.h> | ||
21 | #include <linux/slab.h> | ||
22 | #include <video/omapdss.h> | ||
23 | #include <linux/i2c.h> | ||
24 | #include <drm/drm_edid.h> | ||
25 | |||
26 | #include <video/omap-panel-dvi.h> | ||
27 | |||
28 | static const struct omap_video_timings panel_dvi_default_timings = { | ||
29 | .x_res = 640, | ||
30 | .y_res = 480, | ||
31 | |||
32 | .pixel_clock = 23500, | ||
33 | |||
34 | .hfp = 48, | ||
35 | .hsw = 32, | ||
36 | .hbp = 80, | ||
37 | |||
38 | .vfp = 3, | ||
39 | .vsw = 4, | ||
40 | .vbp = 7, | ||
41 | }; | ||
42 | |||
43 | struct panel_drv_data { | ||
44 | struct omap_dss_device *dssdev; | ||
45 | |||
46 | struct mutex lock; | ||
47 | }; | ||
48 | |||
49 | static inline struct panel_dvi_platform_data | ||
50 | *get_pdata(const struct omap_dss_device *dssdev) | ||
51 | { | ||
52 | return dssdev->data; | ||
53 | } | ||
54 | |||
55 | static int panel_dvi_power_on(struct omap_dss_device *dssdev) | ||
56 | { | ||
57 | struct panel_dvi_platform_data *pdata = get_pdata(dssdev); | ||
58 | int r; | ||
59 | |||
60 | if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) | ||
61 | return 0; | ||
62 | |||
63 | r = omapdss_dpi_display_enable(dssdev); | ||
64 | if (r) | ||
65 | goto err0; | ||
66 | |||
67 | if (pdata->platform_enable) { | ||
68 | r = pdata->platform_enable(dssdev); | ||
69 | if (r) | ||
70 | goto err1; | ||
71 | } | ||
72 | |||
73 | return 0; | ||
74 | err1: | ||
75 | omapdss_dpi_display_disable(dssdev); | ||
76 | err0: | ||
77 | return r; | ||
78 | } | ||
79 | |||
80 | static void panel_dvi_power_off(struct omap_dss_device *dssdev) | ||
81 | { | ||
82 | struct panel_dvi_platform_data *pdata = get_pdata(dssdev); | ||
83 | |||
84 | if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) | ||
85 | return; | ||
86 | |||
87 | if (pdata->platform_disable) | ||
88 | pdata->platform_disable(dssdev); | ||
89 | |||
90 | omapdss_dpi_display_disable(dssdev); | ||
91 | } | ||
92 | |||
93 | static int panel_dvi_probe(struct omap_dss_device *dssdev) | ||
94 | { | ||
95 | struct panel_drv_data *ddata; | ||
96 | |||
97 | ddata = kzalloc(sizeof(*ddata), GFP_KERNEL); | ||
98 | if (!ddata) | ||
99 | return -ENOMEM; | ||
100 | |||
101 | dssdev->panel.timings = panel_dvi_default_timings; | ||
102 | dssdev->panel.config = OMAP_DSS_LCD_TFT; | ||
103 | |||
104 | ddata->dssdev = dssdev; | ||
105 | mutex_init(&ddata->lock); | ||
106 | |||
107 | dev_set_drvdata(&dssdev->dev, ddata); | ||
108 | |||
109 | return 0; | ||
110 | } | ||
111 | |||
112 | static void __exit panel_dvi_remove(struct omap_dss_device *dssdev) | ||
113 | { | ||
114 | struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev); | ||
115 | |||
116 | mutex_lock(&ddata->lock); | ||
117 | |||
118 | dev_set_drvdata(&dssdev->dev, NULL); | ||
119 | |||
120 | mutex_unlock(&ddata->lock); | ||
121 | |||
122 | kfree(ddata); | ||
123 | } | ||
124 | |||
125 | static int panel_dvi_enable(struct omap_dss_device *dssdev) | ||
126 | { | ||
127 | struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev); | ||
128 | int r; | ||
129 | |||
130 | mutex_lock(&ddata->lock); | ||
131 | |||
132 | r = panel_dvi_power_on(dssdev); | ||
133 | if (r == 0) | ||
134 | dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; | ||
135 | |||
136 | mutex_unlock(&ddata->lock); | ||
137 | |||
138 | return r; | ||
139 | } | ||
140 | |||
141 | static void panel_dvi_disable(struct omap_dss_device *dssdev) | ||
142 | { | ||
143 | struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev); | ||
144 | |||
145 | mutex_lock(&ddata->lock); | ||
146 | |||
147 | panel_dvi_power_off(dssdev); | ||
148 | |||
149 | dssdev->state = OMAP_DSS_DISPLAY_DISABLED; | ||
150 | |||
151 | mutex_unlock(&ddata->lock); | ||
152 | } | ||
153 | |||
154 | static int panel_dvi_suspend(struct omap_dss_device *dssdev) | ||
155 | { | ||
156 | struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev); | ||
157 | |||
158 | mutex_lock(&ddata->lock); | ||
159 | |||
160 | panel_dvi_power_off(dssdev); | ||
161 | |||
162 | dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED; | ||
163 | |||
164 | mutex_unlock(&ddata->lock); | ||
165 | |||
166 | return 0; | ||
167 | } | ||
168 | |||
169 | static int panel_dvi_resume(struct omap_dss_device *dssdev) | ||
170 | { | ||
171 | struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev); | ||
172 | int r; | ||
173 | |||
174 | mutex_lock(&ddata->lock); | ||
175 | |||
176 | r = panel_dvi_power_on(dssdev); | ||
177 | if (r == 0) | ||
178 | dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; | ||
179 | |||
180 | mutex_unlock(&ddata->lock); | ||
181 | |||
182 | return r; | ||
183 | } | ||
184 | |||
185 | static void panel_dvi_set_timings(struct omap_dss_device *dssdev, | ||
186 | struct omap_video_timings *timings) | ||
187 | { | ||
188 | struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev); | ||
189 | |||
190 | mutex_lock(&ddata->lock); | ||
191 | dpi_set_timings(dssdev, timings); | ||
192 | mutex_unlock(&ddata->lock); | ||
193 | } | ||
194 | |||
195 | static void panel_dvi_get_timings(struct omap_dss_device *dssdev, | ||
196 | struct omap_video_timings *timings) | ||
197 | { | ||
198 | struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev); | ||
199 | |||
200 | mutex_lock(&ddata->lock); | ||
201 | *timings = dssdev->panel.timings; | ||
202 | mutex_unlock(&ddata->lock); | ||
203 | } | ||
204 | |||
205 | static int panel_dvi_check_timings(struct omap_dss_device *dssdev, | ||
206 | struct omap_video_timings *timings) | ||
207 | { | ||
208 | struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev); | ||
209 | int r; | ||
210 | |||
211 | mutex_lock(&ddata->lock); | ||
212 | r = dpi_check_timings(dssdev, timings); | ||
213 | mutex_unlock(&ddata->lock); | ||
214 | |||
215 | return r; | ||
216 | } | ||
217 | |||
218 | |||
219 | static int panel_dvi_ddc_read(struct i2c_adapter *adapter, | ||
220 | unsigned char *buf, u16 count, u8 offset) | ||
221 | { | ||
222 | int r, retries; | ||
223 | |||
224 | for (retries = 3; retries > 0; retries--) { | ||
225 | struct i2c_msg msgs[] = { | ||
226 | { | ||
227 | .addr = DDC_ADDR, | ||
228 | .flags = 0, | ||
229 | .len = 1, | ||
230 | .buf = &offset, | ||
231 | }, { | ||
232 | .addr = DDC_ADDR, | ||
233 | .flags = I2C_M_RD, | ||
234 | .len = count, | ||
235 | .buf = buf, | ||
236 | } | ||
237 | }; | ||
238 | |||
239 | r = i2c_transfer(adapter, msgs, 2); | ||
240 | if (r == 2) | ||
241 | return 0; | ||
242 | |||
243 | if (r != -EAGAIN) | ||
244 | break; | ||
245 | } | ||
246 | |||
247 | return r < 0 ? r : -EIO; | ||
248 | } | ||
249 | |||
250 | static int panel_dvi_read_edid(struct omap_dss_device *dssdev, | ||
251 | u8 *edid, int len) | ||
252 | { | ||
253 | struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev); | ||
254 | struct panel_dvi_platform_data *pdata = get_pdata(dssdev); | ||
255 | struct i2c_adapter *adapter; | ||
256 | int r, l, bytes_read; | ||
257 | |||
258 | mutex_lock(&ddata->lock); | ||
259 | |||
260 | if (pdata->i2c_bus_num == 0) { | ||
261 | r = -ENODEV; | ||
262 | goto err; | ||
263 | } | ||
264 | |||
265 | adapter = i2c_get_adapter(pdata->i2c_bus_num); | ||
266 | if (!adapter) { | ||
267 | dev_err(&dssdev->dev, "Failed to get I2C adapter, bus %d\n", | ||
268 | pdata->i2c_bus_num); | ||
269 | r = -EINVAL; | ||
270 | goto err; | ||
271 | } | ||
272 | |||
273 | l = min(EDID_LENGTH, len); | ||
274 | r = panel_dvi_ddc_read(adapter, edid, l, 0); | ||
275 | if (r) | ||
276 | goto err; | ||
277 | |||
278 | bytes_read = l; | ||
279 | |||
280 | /* if there are extensions, read second block */ | ||
281 | if (len > EDID_LENGTH && edid[0x7e] > 0) { | ||
282 | l = min(EDID_LENGTH, len - EDID_LENGTH); | ||
283 | |||
284 | r = panel_dvi_ddc_read(adapter, edid + EDID_LENGTH, | ||
285 | l, EDID_LENGTH); | ||
286 | if (r) | ||
287 | goto err; | ||
288 | |||
289 | bytes_read += l; | ||
290 | } | ||
291 | |||
292 | mutex_unlock(&ddata->lock); | ||
293 | |||
294 | return bytes_read; | ||
295 | |||
296 | err: | ||
297 | mutex_unlock(&ddata->lock); | ||
298 | return r; | ||
299 | } | ||
300 | |||
301 | static bool panel_dvi_detect(struct omap_dss_device *dssdev) | ||
302 | { | ||
303 | struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev); | ||
304 | struct panel_dvi_platform_data *pdata = get_pdata(dssdev); | ||
305 | struct i2c_adapter *adapter; | ||
306 | unsigned char out; | ||
307 | int r; | ||
308 | |||
309 | mutex_lock(&ddata->lock); | ||
310 | |||
311 | if (pdata->i2c_bus_num == 0) | ||
312 | goto out; | ||
313 | |||
314 | adapter = i2c_get_adapter(pdata->i2c_bus_num); | ||
315 | if (!adapter) | ||
316 | goto out; | ||
317 | |||
318 | r = panel_dvi_ddc_read(adapter, &out, 1, 0); | ||
319 | |||
320 | mutex_unlock(&ddata->lock); | ||
321 | |||
322 | return r == 0; | ||
323 | |||
324 | out: | ||
325 | mutex_unlock(&ddata->lock); | ||
326 | return true; | ||
327 | } | ||
328 | |||
329 | static struct omap_dss_driver panel_dvi_driver = { | ||
330 | .probe = panel_dvi_probe, | ||
331 | .remove = __exit_p(panel_dvi_remove), | ||
332 | |||
333 | .enable = panel_dvi_enable, | ||
334 | .disable = panel_dvi_disable, | ||
335 | .suspend = panel_dvi_suspend, | ||
336 | .resume = panel_dvi_resume, | ||
337 | |||
338 | .set_timings = panel_dvi_set_timings, | ||
339 | .get_timings = panel_dvi_get_timings, | ||
340 | .check_timings = panel_dvi_check_timings, | ||
341 | |||
342 | .read_edid = panel_dvi_read_edid, | ||
343 | .detect = panel_dvi_detect, | ||
344 | |||
345 | .driver = { | ||
346 | .name = "dvi", | ||
347 | .owner = THIS_MODULE, | ||
348 | }, | ||
349 | }; | ||
350 | |||
351 | static int __init panel_dvi_init(void) | ||
352 | { | ||
353 | return omap_dss_register_driver(&panel_dvi_driver); | ||
354 | } | ||
355 | |||
356 | static void __exit panel_dvi_exit(void) | ||
357 | { | ||
358 | omap_dss_unregister_driver(&panel_dvi_driver); | ||
359 | } | ||
360 | |||
361 | module_init(panel_dvi_init); | ||
362 | module_exit(panel_dvi_exit); | ||
363 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/video/omap2/displays/panel-generic-dpi.c b/drivers/video/omap2/displays/panel-generic-dpi.c index 9c90f75653fb..519c47d2057f 100644 --- a/drivers/video/omap2/displays/panel-generic-dpi.c +++ b/drivers/video/omap2/displays/panel-generic-dpi.c | |||
@@ -58,30 +58,6 @@ struct panel_config { | |||
58 | 58 | ||
59 | /* Panel configurations */ | 59 | /* Panel configurations */ |
60 | static struct panel_config generic_dpi_panels[] = { | 60 | static struct panel_config generic_dpi_panels[] = { |
61 | /* Generic Panel */ | ||
62 | { | ||
63 | { | ||
64 | .x_res = 640, | ||
65 | .y_res = 480, | ||
66 | |||
67 | .pixel_clock = 23500, | ||
68 | |||
69 | .hfp = 48, | ||
70 | .hsw = 32, | ||
71 | .hbp = 80, | ||
72 | |||
73 | .vfp = 3, | ||
74 | .vsw = 4, | ||
75 | .vbp = 7, | ||
76 | }, | ||
77 | .acbi = 0x0, | ||
78 | .acb = 0x0, | ||
79 | .config = OMAP_DSS_LCD_TFT, | ||
80 | .power_on_delay = 0, | ||
81 | .power_off_delay = 0, | ||
82 | .name = "generic", | ||
83 | }, | ||
84 | |||
85 | /* Sharp LQ043T1DG01 */ | 61 | /* Sharp LQ043T1DG01 */ |
86 | { | 62 | { |
87 | { | 63 | { |
@@ -232,6 +208,95 @@ static struct panel_config generic_dpi_panels[] = { | |||
232 | .power_off_delay = 0, | 208 | .power_off_delay = 0, |
233 | .name = "powertip_ph480272t", | 209 | .name = "powertip_ph480272t", |
234 | }, | 210 | }, |
211 | |||
212 | /* Innolux AT070TN83 */ | ||
213 | { | ||
214 | { | ||
215 | .x_res = 800, | ||
216 | .y_res = 480, | ||
217 | |||
218 | .pixel_clock = 40000, | ||
219 | |||
220 | .hsw = 48, | ||
221 | .hfp = 1, | ||
222 | .hbp = 1, | ||
223 | |||
224 | .vsw = 3, | ||
225 | .vfp = 12, | ||
226 | .vbp = 25, | ||
227 | }, | ||
228 | .acbi = 0x0, | ||
229 | .acb = 0x28, | ||
230 | .config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS | | ||
231 | OMAP_DSS_LCD_IHS, | ||
232 | .power_on_delay = 0, | ||
233 | .power_off_delay = 0, | ||
234 | .name = "innolux_at070tn83", | ||
235 | }, | ||
236 | |||
237 | /* NEC NL2432DR22-11B */ | ||
238 | { | ||
239 | { | ||
240 | .x_res = 240, | ||
241 | .y_res = 320, | ||
242 | |||
243 | .pixel_clock = 5400, | ||
244 | |||
245 | .hsw = 3, | ||
246 | .hfp = 3, | ||
247 | .hbp = 39, | ||
248 | |||
249 | .vsw = 1, | ||
250 | .vfp = 2, | ||
251 | .vbp = 7, | ||
252 | }, | ||
253 | .config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS | | ||
254 | OMAP_DSS_LCD_IHS, | ||
255 | .name = "nec_nl2432dr22-11b", | ||
256 | }, | ||
257 | |||
258 | /* Unknown panel used in OMAP H4 */ | ||
259 | { | ||
260 | { | ||
261 | .x_res = 240, | ||
262 | .y_res = 320, | ||
263 | |||
264 | .pixel_clock = 6250, | ||
265 | |||
266 | .hsw = 15, | ||
267 | .hfp = 15, | ||
268 | .hbp = 60, | ||
269 | |||
270 | .vsw = 1, | ||
271 | .vfp = 1, | ||
272 | .vbp = 1, | ||
273 | }, | ||
274 | .config = OMAP_DSS_LCD_TFT, | ||
275 | |||
276 | .name = "h4", | ||
277 | }, | ||
278 | |||
279 | /* Unknown panel used in Samsung OMAP2 Apollon */ | ||
280 | { | ||
281 | { | ||
282 | .x_res = 480, | ||
283 | .y_res = 272, | ||
284 | |||
285 | .pixel_clock = 6250, | ||
286 | |||
287 | .hsw = 41, | ||
288 | .hfp = 2, | ||
289 | .hbp = 2, | ||
290 | |||
291 | .vsw = 10, | ||
292 | .vfp = 2, | ||
293 | .vbp = 2, | ||
294 | }, | ||
295 | .config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS | | ||
296 | OMAP_DSS_LCD_IHS, | ||
297 | |||
298 | .name = "apollon", | ||
299 | }, | ||
235 | }; | 300 | }; |
236 | 301 | ||
237 | struct panel_drv_data { | 302 | struct panel_drv_data { |
diff --git a/drivers/video/omap2/displays/panel-n8x0.c b/drivers/video/omap2/displays/panel-n8x0.c new file mode 100644 index 000000000000..150e8bae35a1 --- /dev/null +++ b/drivers/video/omap2/displays/panel-n8x0.c | |||
@@ -0,0 +1,747 @@ | |||
1 | /* #define DEBUG */ | ||
2 | |||
3 | #include <linux/module.h> | ||
4 | #include <linux/delay.h> | ||
5 | #include <linux/slab.h> | ||
6 | #include <linux/gpio.h> | ||
7 | #include <linux/spi/spi.h> | ||
8 | #include <linux/backlight.h> | ||
9 | #include <linux/fb.h> | ||
10 | |||
11 | #include <video/omapdss.h> | ||
12 | #include <video/omap-panel-n8x0.h> | ||
13 | |||
14 | #define BLIZZARD_REV_CODE 0x00 | ||
15 | #define BLIZZARD_CONFIG 0x02 | ||
16 | #define BLIZZARD_PLL_DIV 0x04 | ||
17 | #define BLIZZARD_PLL_LOCK_RANGE 0x06 | ||
18 | #define BLIZZARD_PLL_CLOCK_SYNTH_0 0x08 | ||
19 | #define BLIZZARD_PLL_CLOCK_SYNTH_1 0x0a | ||
20 | #define BLIZZARD_PLL_MODE 0x0c | ||
21 | #define BLIZZARD_CLK_SRC 0x0e | ||
22 | #define BLIZZARD_MEM_BANK0_ACTIVATE 0x10 | ||
23 | #define BLIZZARD_MEM_BANK0_STATUS 0x14 | ||
24 | #define BLIZZARD_PANEL_CONFIGURATION 0x28 | ||
25 | #define BLIZZARD_HDISP 0x2a | ||
26 | #define BLIZZARD_HNDP 0x2c | ||
27 | #define BLIZZARD_VDISP0 0x2e | ||
28 | #define BLIZZARD_VDISP1 0x30 | ||
29 | #define BLIZZARD_VNDP 0x32 | ||
30 | #define BLIZZARD_HSW 0x34 | ||
31 | #define BLIZZARD_VSW 0x38 | ||
32 | #define BLIZZARD_DISPLAY_MODE 0x68 | ||
33 | #define BLIZZARD_INPUT_WIN_X_START_0 0x6c | ||
34 | #define BLIZZARD_DATA_SOURCE_SELECT 0x8e | ||
35 | #define BLIZZARD_DISP_MEM_DATA_PORT 0x90 | ||
36 | #define BLIZZARD_DISP_MEM_READ_ADDR0 0x92 | ||
37 | #define BLIZZARD_POWER_SAVE 0xE6 | ||
38 | #define BLIZZARD_NDISP_CTRL_STATUS 0xE8 | ||
39 | |||
40 | /* Data source select */ | ||
41 | /* For S1D13745 */ | ||
42 | #define BLIZZARD_SRC_WRITE_LCD_BACKGROUND 0x00 | ||
43 | #define BLIZZARD_SRC_WRITE_LCD_DESTRUCTIVE 0x01 | ||
44 | #define BLIZZARD_SRC_WRITE_OVERLAY_ENABLE 0x04 | ||
45 | #define BLIZZARD_SRC_DISABLE_OVERLAY 0x05 | ||
46 | /* For S1D13744 */ | ||
47 | #define BLIZZARD_SRC_WRITE_LCD 0x00 | ||
48 | #define BLIZZARD_SRC_BLT_LCD 0x06 | ||
49 | |||
50 | #define BLIZZARD_COLOR_RGB565 0x01 | ||
51 | #define BLIZZARD_COLOR_YUV420 0x09 | ||
52 | |||
53 | #define BLIZZARD_VERSION_S1D13745 0x01 /* Hailstorm */ | ||
54 | #define BLIZZARD_VERSION_S1D13744 0x02 /* Blizzard */ | ||
55 | |||
56 | #define MIPID_CMD_READ_DISP_ID 0x04 | ||
57 | #define MIPID_CMD_READ_RED 0x06 | ||
58 | #define MIPID_CMD_READ_GREEN 0x07 | ||
59 | #define MIPID_CMD_READ_BLUE 0x08 | ||
60 | #define MIPID_CMD_READ_DISP_STATUS 0x09 | ||
61 | #define MIPID_CMD_RDDSDR 0x0F | ||
62 | #define MIPID_CMD_SLEEP_IN 0x10 | ||
63 | #define MIPID_CMD_SLEEP_OUT 0x11 | ||
64 | #define MIPID_CMD_DISP_OFF 0x28 | ||
65 | #define MIPID_CMD_DISP_ON 0x29 | ||
66 | |||
67 | static struct panel_drv_data { | ||
68 | struct mutex lock; | ||
69 | |||
70 | struct omap_dss_device *dssdev; | ||
71 | struct spi_device *spidev; | ||
72 | struct backlight_device *bldev; | ||
73 | |||
74 | int blizzard_ver; | ||
75 | } s_drv_data; | ||
76 | |||
77 | |||
78 | static inline | ||
79 | struct panel_n8x0_data *get_board_data(const struct omap_dss_device *dssdev) | ||
80 | { | ||
81 | return dssdev->data; | ||
82 | } | ||
83 | |||
84 | static inline | ||
85 | struct panel_drv_data *get_drv_data(const struct omap_dss_device *dssdev) | ||
86 | { | ||
87 | return &s_drv_data; | ||
88 | } | ||
89 | |||
90 | |||
91 | static inline void blizzard_cmd(u8 cmd) | ||
92 | { | ||
93 | omap_rfbi_write_command(&cmd, 1); | ||
94 | } | ||
95 | |||
96 | static inline void blizzard_write(u8 cmd, const u8 *buf, int len) | ||
97 | { | ||
98 | omap_rfbi_write_command(&cmd, 1); | ||
99 | omap_rfbi_write_data(buf, len); | ||
100 | } | ||
101 | |||
102 | static inline void blizzard_read(u8 cmd, u8 *buf, int len) | ||
103 | { | ||
104 | omap_rfbi_write_command(&cmd, 1); | ||
105 | omap_rfbi_read_data(buf, len); | ||
106 | } | ||
107 | |||
108 | static u8 blizzard_read_reg(u8 cmd) | ||
109 | { | ||
110 | u8 data; | ||
111 | blizzard_read(cmd, &data, 1); | ||
112 | return data; | ||
113 | } | ||
114 | |||
115 | static void blizzard_ctrl_setup_update(struct omap_dss_device *dssdev, | ||
116 | int x, int y, int w, int h) | ||
117 | { | ||
118 | struct panel_drv_data *ddata = get_drv_data(dssdev); | ||
119 | u8 tmp[18]; | ||
120 | int x_end, y_end; | ||
121 | |||
122 | x_end = x + w - 1; | ||
123 | y_end = y + h - 1; | ||
124 | |||
125 | tmp[0] = x; | ||
126 | tmp[1] = x >> 8; | ||
127 | tmp[2] = y; | ||
128 | tmp[3] = y >> 8; | ||
129 | tmp[4] = x_end; | ||
130 | tmp[5] = x_end >> 8; | ||
131 | tmp[6] = y_end; | ||
132 | tmp[7] = y_end >> 8; | ||
133 | |||
134 | /* scaling? */ | ||
135 | tmp[8] = x; | ||
136 | tmp[9] = x >> 8; | ||
137 | tmp[10] = y; | ||
138 | tmp[11] = y >> 8; | ||
139 | tmp[12] = x_end; | ||
140 | tmp[13] = x_end >> 8; | ||
141 | tmp[14] = y_end; | ||
142 | tmp[15] = y_end >> 8; | ||
143 | |||
144 | tmp[16] = BLIZZARD_COLOR_RGB565; | ||
145 | |||
146 | if (ddata->blizzard_ver == BLIZZARD_VERSION_S1D13745) | ||
147 | tmp[17] = BLIZZARD_SRC_WRITE_LCD_BACKGROUND; | ||
148 | else | ||
149 | tmp[17] = ddata->blizzard_ver == BLIZZARD_VERSION_S1D13744 ? | ||
150 | BLIZZARD_SRC_WRITE_LCD : | ||
151 | BLIZZARD_SRC_WRITE_LCD_DESTRUCTIVE; | ||
152 | |||
153 | omap_rfbi_configure(dssdev, 16, 8); | ||
154 | |||
155 | blizzard_write(BLIZZARD_INPUT_WIN_X_START_0, tmp, 18); | ||
156 | |||
157 | omap_rfbi_configure(dssdev, 16, 16); | ||
158 | } | ||
159 | |||
160 | static void mipid_transfer(struct spi_device *spi, int cmd, const u8 *wbuf, | ||
161 | int wlen, u8 *rbuf, int rlen) | ||
162 | { | ||
163 | struct spi_message m; | ||
164 | struct spi_transfer *x, xfer[4]; | ||
165 | u16 w; | ||
166 | int r; | ||
167 | |||
168 | spi_message_init(&m); | ||
169 | |||
170 | memset(xfer, 0, sizeof(xfer)); | ||
171 | x = &xfer[0]; | ||
172 | |||
173 | cmd &= 0xff; | ||
174 | x->tx_buf = &cmd; | ||
175 | x->bits_per_word = 9; | ||
176 | x->len = 2; | ||
177 | spi_message_add_tail(x, &m); | ||
178 | |||
179 | if (wlen) { | ||
180 | x++; | ||
181 | x->tx_buf = wbuf; | ||
182 | x->len = wlen; | ||
183 | x->bits_per_word = 9; | ||
184 | spi_message_add_tail(x, &m); | ||
185 | } | ||
186 | |||
187 | if (rlen) { | ||
188 | x++; | ||
189 | x->rx_buf = &w; | ||
190 | x->len = 1; | ||
191 | spi_message_add_tail(x, &m); | ||
192 | |||
193 | if (rlen > 1) { | ||
194 | /* Arrange for the extra clock before the first | ||
195 | * data bit. | ||
196 | */ | ||
197 | x->bits_per_word = 9; | ||
198 | x->len = 2; | ||
199 | |||
200 | x++; | ||
201 | x->rx_buf = &rbuf[1]; | ||
202 | x->len = rlen - 1; | ||
203 | spi_message_add_tail(x, &m); | ||
204 | } | ||
205 | } | ||
206 | |||
207 | r = spi_sync(spi, &m); | ||
208 | if (r < 0) | ||
209 | dev_dbg(&spi->dev, "spi_sync %d\n", r); | ||
210 | |||
211 | if (rlen) | ||
212 | rbuf[0] = w & 0xff; | ||
213 | } | ||
214 | |||
215 | static inline void mipid_cmd(struct spi_device *spi, int cmd) | ||
216 | { | ||
217 | mipid_transfer(spi, cmd, NULL, 0, NULL, 0); | ||
218 | } | ||
219 | |||
220 | static inline void mipid_write(struct spi_device *spi, | ||
221 | int reg, const u8 *buf, int len) | ||
222 | { | ||
223 | mipid_transfer(spi, reg, buf, len, NULL, 0); | ||
224 | } | ||
225 | |||
226 | static inline void mipid_read(struct spi_device *spi, | ||
227 | int reg, u8 *buf, int len) | ||
228 | { | ||
229 | mipid_transfer(spi, reg, NULL, 0, buf, len); | ||
230 | } | ||
231 | |||
232 | static void set_data_lines(struct spi_device *spi, int data_lines) | ||
233 | { | ||
234 | u16 par; | ||
235 | |||
236 | switch (data_lines) { | ||
237 | case 16: | ||
238 | par = 0x150; | ||
239 | break; | ||
240 | case 18: | ||
241 | par = 0x160; | ||
242 | break; | ||
243 | case 24: | ||
244 | par = 0x170; | ||
245 | break; | ||
246 | } | ||
247 | |||
248 | mipid_write(spi, 0x3a, (u8 *)&par, 2); | ||
249 | } | ||
250 | |||
251 | static void send_init_string(struct spi_device *spi) | ||
252 | { | ||
253 | u16 initpar[] = { 0x0102, 0x0100, 0x0100 }; | ||
254 | mipid_write(spi, 0xc2, (u8 *)initpar, sizeof(initpar)); | ||
255 | } | ||
256 | |||
257 | static void send_display_on(struct spi_device *spi) | ||
258 | { | ||
259 | mipid_cmd(spi, MIPID_CMD_DISP_ON); | ||
260 | } | ||
261 | |||
262 | static void send_display_off(struct spi_device *spi) | ||
263 | { | ||
264 | mipid_cmd(spi, MIPID_CMD_DISP_OFF); | ||
265 | } | ||
266 | |||
267 | static void send_sleep_out(struct spi_device *spi) | ||
268 | { | ||
269 | mipid_cmd(spi, MIPID_CMD_SLEEP_OUT); | ||
270 | msleep(120); | ||
271 | } | ||
272 | |||
273 | static void send_sleep_in(struct spi_device *spi) | ||
274 | { | ||
275 | mipid_cmd(spi, MIPID_CMD_SLEEP_IN); | ||
276 | msleep(50); | ||
277 | } | ||
278 | |||
279 | static int n8x0_panel_power_on(struct omap_dss_device *dssdev) | ||
280 | { | ||
281 | int r; | ||
282 | struct panel_n8x0_data *bdata = get_board_data(dssdev); | ||
283 | struct panel_drv_data *ddata = get_drv_data(dssdev); | ||
284 | struct spi_device *spi = ddata->spidev; | ||
285 | u8 rev, conf; | ||
286 | u8 display_id[3]; | ||
287 | const char *panel_name; | ||
288 | |||
289 | if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) | ||
290 | return 0; | ||
291 | |||
292 | gpio_direction_output(bdata->ctrl_pwrdown, 1); | ||
293 | |||
294 | if (bdata->platform_enable) { | ||
295 | r = bdata->platform_enable(dssdev); | ||
296 | if (r) | ||
297 | goto err_plat_en; | ||
298 | } | ||
299 | |||
300 | r = omapdss_rfbi_display_enable(dssdev); | ||
301 | if (r) | ||
302 | goto err_rfbi_en; | ||
303 | |||
304 | rev = blizzard_read_reg(BLIZZARD_REV_CODE); | ||
305 | conf = blizzard_read_reg(BLIZZARD_CONFIG); | ||
306 | |||
307 | switch (rev & 0xfc) { | ||
308 | case 0x9c: | ||
309 | ddata->blizzard_ver = BLIZZARD_VERSION_S1D13744; | ||
310 | dev_info(&dssdev->dev, "s1d13744 LCD controller rev %d " | ||
311 | "initialized (CNF pins %x)\n", rev & 0x03, conf & 0x07); | ||
312 | break; | ||
313 | case 0xa4: | ||
314 | ddata->blizzard_ver = BLIZZARD_VERSION_S1D13745; | ||
315 | dev_info(&dssdev->dev, "s1d13745 LCD controller rev %d " | ||
316 | "initialized (CNF pins %x)\n", rev & 0x03, conf & 0x07); | ||
317 | break; | ||
318 | default: | ||
319 | dev_err(&dssdev->dev, "invalid s1d1374x revision %02x\n", rev); | ||
320 | r = -ENODEV; | ||
321 | goto err_inv_chip; | ||
322 | } | ||
323 | |||
324 | /* panel */ | ||
325 | |||
326 | gpio_direction_output(bdata->panel_reset, 1); | ||
327 | |||
328 | mipid_read(spi, MIPID_CMD_READ_DISP_ID, display_id, 3); | ||
329 | dev_dbg(&spi->dev, "MIPI display ID: %02x%02x%02x\n", | ||
330 | display_id[0], display_id[1], display_id[2]); | ||
331 | |||
332 | switch (display_id[0]) { | ||
333 | case 0x45: | ||
334 | panel_name = "lph8923"; | ||
335 | break; | ||
336 | case 0x83: | ||
337 | panel_name = "ls041y3"; | ||
338 | break; | ||
339 | default: | ||
340 | dev_err(&dssdev->dev, "invalid display ID 0x%x\n", | ||
341 | display_id[0]); | ||
342 | r = -ENODEV; | ||
343 | goto err_inv_panel; | ||
344 | } | ||
345 | |||
346 | dev_info(&dssdev->dev, "%s rev %02x LCD detected\n", | ||
347 | panel_name, display_id[1]); | ||
348 | |||
349 | send_sleep_out(spi); | ||
350 | send_init_string(spi); | ||
351 | set_data_lines(spi, 24); | ||
352 | send_display_on(spi); | ||
353 | |||
354 | return 0; | ||
355 | |||
356 | err_inv_panel: | ||
357 | /* | ||
358 | * HACK: we should turn off the panel here, but there is some problem | ||
359 | * with the initialization sequence, and we fail to init the panel if we | ||
360 | * have turned it off | ||
361 | */ | ||
362 | /* gpio_direction_output(bdata->panel_reset, 0); */ | ||
363 | err_inv_chip: | ||
364 | omapdss_rfbi_display_disable(dssdev); | ||
365 | err_rfbi_en: | ||
366 | if (bdata->platform_disable) | ||
367 | bdata->platform_disable(dssdev); | ||
368 | err_plat_en: | ||
369 | gpio_direction_output(bdata->ctrl_pwrdown, 0); | ||
370 | return r; | ||
371 | } | ||
372 | |||
373 | static void n8x0_panel_power_off(struct omap_dss_device *dssdev) | ||
374 | { | ||
375 | struct panel_n8x0_data *bdata = get_board_data(dssdev); | ||
376 | struct panel_drv_data *ddata = get_drv_data(dssdev); | ||
377 | struct spi_device *spi = ddata->spidev; | ||
378 | |||
379 | if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) | ||
380 | return; | ||
381 | |||
382 | send_display_off(spi); | ||
383 | send_sleep_in(spi); | ||
384 | |||
385 | if (bdata->platform_disable) | ||
386 | bdata->platform_disable(dssdev); | ||
387 | |||
388 | /* | ||
389 | * HACK: we should turn off the panel here, but there is some problem | ||
390 | * with the initialization sequence, and we fail to init the panel if we | ||
391 | * have turned it off | ||
392 | */ | ||
393 | /* gpio_direction_output(bdata->panel_reset, 0); */ | ||
394 | gpio_direction_output(bdata->ctrl_pwrdown, 0); | ||
395 | omapdss_rfbi_display_disable(dssdev); | ||
396 | } | ||
397 | |||
398 | static const struct rfbi_timings n8x0_panel_timings = { | ||
399 | .cs_on_time = 0, | ||
400 | |||
401 | .we_on_time = 9000, | ||
402 | .we_off_time = 18000, | ||
403 | .we_cycle_time = 36000, | ||
404 | |||
405 | .re_on_time = 9000, | ||
406 | .re_off_time = 27000, | ||
407 | .re_cycle_time = 36000, | ||
408 | |||
409 | .access_time = 27000, | ||
410 | .cs_off_time = 36000, | ||
411 | |||
412 | .cs_pulse_width = 0, | ||
413 | }; | ||
414 | |||
415 | static int n8x0_bl_update_status(struct backlight_device *dev) | ||
416 | { | ||
417 | struct omap_dss_device *dssdev = dev_get_drvdata(&dev->dev); | ||
418 | struct panel_n8x0_data *bdata = get_board_data(dssdev); | ||
419 | struct panel_drv_data *ddata = get_drv_data(dssdev); | ||
420 | int r; | ||
421 | int level; | ||
422 | |||
423 | mutex_lock(&ddata->lock); | ||
424 | |||
425 | if (dev->props.fb_blank == FB_BLANK_UNBLANK && | ||
426 | dev->props.power == FB_BLANK_UNBLANK) | ||
427 | level = dev->props.brightness; | ||
428 | else | ||
429 | level = 0; | ||
430 | |||
431 | dev_dbg(&dssdev->dev, "update brightness to %d\n", level); | ||
432 | |||
433 | if (!bdata->set_backlight) | ||
434 | r = -EINVAL; | ||
435 | else | ||
436 | r = bdata->set_backlight(dssdev, level); | ||
437 | |||
438 | mutex_unlock(&ddata->lock); | ||
439 | |||
440 | return r; | ||
441 | } | ||
442 | |||
443 | static int n8x0_bl_get_intensity(struct backlight_device *dev) | ||
444 | { | ||
445 | if (dev->props.fb_blank == FB_BLANK_UNBLANK && | ||
446 | dev->props.power == FB_BLANK_UNBLANK) | ||
447 | return dev->props.brightness; | ||
448 | |||
449 | return 0; | ||
450 | } | ||
451 | |||
452 | static const struct backlight_ops n8x0_bl_ops = { | ||
453 | .get_brightness = n8x0_bl_get_intensity, | ||
454 | .update_status = n8x0_bl_update_status, | ||
455 | }; | ||
456 | |||
457 | static int n8x0_panel_probe(struct omap_dss_device *dssdev) | ||
458 | { | ||
459 | struct panel_n8x0_data *bdata = get_board_data(dssdev); | ||
460 | struct panel_drv_data *ddata; | ||
461 | struct backlight_device *bldev; | ||
462 | struct backlight_properties props; | ||
463 | int r; | ||
464 | |||
465 | dev_dbg(&dssdev->dev, "probe\n"); | ||
466 | |||
467 | if (!bdata) | ||
468 | return -EINVAL; | ||
469 | |||
470 | s_drv_data.dssdev = dssdev; | ||
471 | |||
472 | ddata = &s_drv_data; | ||
473 | |||
474 | mutex_init(&ddata->lock); | ||
475 | |||
476 | dssdev->panel.config = OMAP_DSS_LCD_TFT; | ||
477 | dssdev->panel.timings.x_res = 800; | ||
478 | dssdev->panel.timings.y_res = 480; | ||
479 | dssdev->ctrl.pixel_size = 16; | ||
480 | dssdev->ctrl.rfbi_timings = n8x0_panel_timings; | ||
481 | |||
482 | memset(&props, 0, sizeof(props)); | ||
483 | props.max_brightness = 127; | ||
484 | props.type = BACKLIGHT_PLATFORM; | ||
485 | bldev = backlight_device_register(dev_name(&dssdev->dev), &dssdev->dev, | ||
486 | dssdev, &n8x0_bl_ops, &props); | ||
487 | if (IS_ERR(bldev)) { | ||
488 | r = PTR_ERR(bldev); | ||
489 | dev_err(&dssdev->dev, "register backlight failed\n"); | ||
490 | return r; | ||
491 | } | ||
492 | |||
493 | ddata->bldev = bldev; | ||
494 | |||
495 | bldev->props.fb_blank = FB_BLANK_UNBLANK; | ||
496 | bldev->props.power = FB_BLANK_UNBLANK; | ||
497 | bldev->props.brightness = 127; | ||
498 | |||
499 | n8x0_bl_update_status(bldev); | ||
500 | |||
501 | return 0; | ||
502 | } | ||
503 | |||
504 | static void n8x0_panel_remove(struct omap_dss_device *dssdev) | ||
505 | { | ||
506 | struct panel_drv_data *ddata = get_drv_data(dssdev); | ||
507 | struct backlight_device *bldev; | ||
508 | |||
509 | dev_dbg(&dssdev->dev, "remove\n"); | ||
510 | |||
511 | bldev = ddata->bldev; | ||
512 | bldev->props.power = FB_BLANK_POWERDOWN; | ||
513 | n8x0_bl_update_status(bldev); | ||
514 | backlight_device_unregister(bldev); | ||
515 | |||
516 | dev_set_drvdata(&dssdev->dev, NULL); | ||
517 | } | ||
518 | |||
519 | static int n8x0_panel_enable(struct omap_dss_device *dssdev) | ||
520 | { | ||
521 | struct panel_drv_data *ddata = get_drv_data(dssdev); | ||
522 | int r; | ||
523 | |||
524 | dev_dbg(&dssdev->dev, "enable\n"); | ||
525 | |||
526 | mutex_lock(&ddata->lock); | ||
527 | |||
528 | rfbi_bus_lock(); | ||
529 | |||
530 | r = n8x0_panel_power_on(dssdev); | ||
531 | |||
532 | rfbi_bus_unlock(); | ||
533 | |||
534 | if (r) { | ||
535 | mutex_unlock(&ddata->lock); | ||
536 | return r; | ||
537 | } | ||
538 | |||
539 | dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; | ||
540 | |||
541 | mutex_unlock(&ddata->lock); | ||
542 | |||
543 | return 0; | ||
544 | } | ||
545 | |||
546 | static void n8x0_panel_disable(struct omap_dss_device *dssdev) | ||
547 | { | ||
548 | struct panel_drv_data *ddata = get_drv_data(dssdev); | ||
549 | |||
550 | dev_dbg(&dssdev->dev, "disable\n"); | ||
551 | |||
552 | mutex_lock(&ddata->lock); | ||
553 | |||
554 | rfbi_bus_lock(); | ||
555 | |||
556 | n8x0_panel_power_off(dssdev); | ||
557 | |||
558 | rfbi_bus_unlock(); | ||
559 | |||
560 | dssdev->state = OMAP_DSS_DISPLAY_DISABLED; | ||
561 | |||
562 | mutex_unlock(&ddata->lock); | ||
563 | } | ||
564 | |||
565 | static int n8x0_panel_suspend(struct omap_dss_device *dssdev) | ||
566 | { | ||
567 | struct panel_drv_data *ddata = get_drv_data(dssdev); | ||
568 | |||
569 | dev_dbg(&dssdev->dev, "suspend\n"); | ||
570 | |||
571 | mutex_lock(&ddata->lock); | ||
572 | |||
573 | rfbi_bus_lock(); | ||
574 | |||
575 | n8x0_panel_power_off(dssdev); | ||
576 | |||
577 | rfbi_bus_unlock(); | ||
578 | |||
579 | dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED; | ||
580 | |||
581 | mutex_unlock(&ddata->lock); | ||
582 | |||
583 | return 0; | ||
584 | } | ||
585 | |||
586 | static int n8x0_panel_resume(struct omap_dss_device *dssdev) | ||
587 | { | ||
588 | struct panel_drv_data *ddata = get_drv_data(dssdev); | ||
589 | int r; | ||
590 | |||
591 | dev_dbg(&dssdev->dev, "resume\n"); | ||
592 | |||
593 | mutex_lock(&ddata->lock); | ||
594 | |||
595 | rfbi_bus_lock(); | ||
596 | |||
597 | r = n8x0_panel_power_on(dssdev); | ||
598 | |||
599 | rfbi_bus_unlock(); | ||
600 | |||
601 | if (r) { | ||
602 | mutex_unlock(&ddata->lock); | ||
603 | return r; | ||
604 | } | ||
605 | |||
606 | dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; | ||
607 | |||
608 | mutex_unlock(&ddata->lock); | ||
609 | |||
610 | return 0; | ||
611 | } | ||
612 | |||
613 | static void n8x0_panel_get_timings(struct omap_dss_device *dssdev, | ||
614 | struct omap_video_timings *timings) | ||
615 | { | ||
616 | *timings = dssdev->panel.timings; | ||
617 | } | ||
618 | |||
619 | static void n8x0_panel_get_resolution(struct omap_dss_device *dssdev, | ||
620 | u16 *xres, u16 *yres) | ||
621 | { | ||
622 | *xres = dssdev->panel.timings.x_res; | ||
623 | *yres = dssdev->panel.timings.y_res; | ||
624 | } | ||
625 | |||
626 | static void update_done(void *data) | ||
627 | { | ||
628 | rfbi_bus_unlock(); | ||
629 | } | ||
630 | |||
631 | static int n8x0_panel_update(struct omap_dss_device *dssdev, | ||
632 | u16 x, u16 y, u16 w, u16 h) | ||
633 | { | ||
634 | struct panel_drv_data *ddata = get_drv_data(dssdev); | ||
635 | |||
636 | dev_dbg(&dssdev->dev, "update\n"); | ||
637 | |||
638 | mutex_lock(&ddata->lock); | ||
639 | rfbi_bus_lock(); | ||
640 | |||
641 | omap_rfbi_prepare_update(dssdev, &x, &y, &w, &h); | ||
642 | |||
643 | blizzard_ctrl_setup_update(dssdev, x, y, w, h); | ||
644 | |||
645 | omap_rfbi_update(dssdev, x, y, w, h, update_done, NULL); | ||
646 | |||
647 | mutex_unlock(&ddata->lock); | ||
648 | |||
649 | return 0; | ||
650 | } | ||
651 | |||
652 | static int n8x0_panel_sync(struct omap_dss_device *dssdev) | ||
653 | { | ||
654 | struct panel_drv_data *ddata = get_drv_data(dssdev); | ||
655 | |||
656 | dev_dbg(&dssdev->dev, "sync\n"); | ||
657 | |||
658 | mutex_lock(&ddata->lock); | ||
659 | rfbi_bus_lock(); | ||
660 | rfbi_bus_unlock(); | ||
661 | mutex_unlock(&ddata->lock); | ||
662 | |||
663 | return 0; | ||
664 | } | ||
665 | |||
666 | static struct omap_dss_driver n8x0_panel_driver = { | ||
667 | .probe = n8x0_panel_probe, | ||
668 | .remove = n8x0_panel_remove, | ||
669 | |||
670 | .enable = n8x0_panel_enable, | ||
671 | .disable = n8x0_panel_disable, | ||
672 | .suspend = n8x0_panel_suspend, | ||
673 | .resume = n8x0_panel_resume, | ||
674 | |||
675 | .update = n8x0_panel_update, | ||
676 | .sync = n8x0_panel_sync, | ||
677 | |||
678 | .get_resolution = n8x0_panel_get_resolution, | ||
679 | .get_recommended_bpp = omapdss_default_get_recommended_bpp, | ||
680 | |||
681 | .get_timings = n8x0_panel_get_timings, | ||
682 | |||
683 | .driver = { | ||
684 | .name = "n8x0_panel", | ||
685 | .owner = THIS_MODULE, | ||
686 | }, | ||
687 | }; | ||
688 | |||
689 | /* PANEL */ | ||
690 | |||
691 | static int mipid_spi_probe(struct spi_device *spi) | ||
692 | { | ||
693 | dev_dbg(&spi->dev, "mipid_spi_probe\n"); | ||
694 | |||
695 | spi->mode = SPI_MODE_0; | ||
696 | |||
697 | s_drv_data.spidev = spi; | ||
698 | |||
699 | return 0; | ||
700 | } | ||
701 | |||
702 | static int mipid_spi_remove(struct spi_device *spi) | ||
703 | { | ||
704 | dev_dbg(&spi->dev, "mipid_spi_remove\n"); | ||
705 | return 0; | ||
706 | } | ||
707 | |||
708 | static struct spi_driver mipid_spi_driver = { | ||
709 | .driver = { | ||
710 | .name = "lcd_mipid", | ||
711 | .bus = &spi_bus_type, | ||
712 | .owner = THIS_MODULE, | ||
713 | }, | ||
714 | .probe = mipid_spi_probe, | ||
715 | .remove = __devexit_p(mipid_spi_remove), | ||
716 | }; | ||
717 | |||
718 | static int __init n8x0_panel_drv_init(void) | ||
719 | { | ||
720 | int r; | ||
721 | |||
722 | r = spi_register_driver(&mipid_spi_driver); | ||
723 | if (r) { | ||
724 | pr_err("n8x0_panel: spi driver registration failed\n"); | ||
725 | return r; | ||
726 | } | ||
727 | |||
728 | r = omap_dss_register_driver(&n8x0_panel_driver); | ||
729 | if (r) { | ||
730 | pr_err("n8x0_panel: dss driver registration failed\n"); | ||
731 | spi_unregister_driver(&mipid_spi_driver); | ||
732 | return r; | ||
733 | } | ||
734 | |||
735 | return 0; | ||
736 | } | ||
737 | |||
738 | static void __exit n8x0_panel_drv_exit(void) | ||
739 | { | ||
740 | spi_unregister_driver(&mipid_spi_driver); | ||
741 | |||
742 | omap_dss_unregister_driver(&n8x0_panel_driver); | ||
743 | } | ||
744 | |||
745 | module_init(n8x0_panel_drv_init); | ||
746 | module_exit(n8x0_panel_drv_exit); | ||
747 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/video/omap2/displays/panel-picodlp.c b/drivers/video/omap2/displays/panel-picodlp.c new file mode 100644 index 000000000000..98ebdaddab5a --- /dev/null +++ b/drivers/video/omap2/displays/panel-picodlp.c | |||
@@ -0,0 +1,594 @@ | |||
1 | /* | ||
2 | * picodlp panel driver | ||
3 | * picodlp_i2c_driver: i2c_client driver | ||
4 | * | ||
5 | * Copyright (C) 2009-2011 Texas Instruments | ||
6 | * Author: Mythri P K <mythripk@ti.com> | ||
7 | * Mayuresh Janorkar <mayur@ti.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License version 2 as published by | ||
11 | * the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
14 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
15 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
16 | * more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License along with | ||
19 | * this program. If not, see <http://www.gnu.org/licenses/>. | ||
20 | */ | ||
21 | |||
22 | #include <linux/module.h> | ||
23 | #include <linux/input.h> | ||
24 | #include <linux/platform_device.h> | ||
25 | #include <linux/interrupt.h> | ||
26 | #include <linux/firmware.h> | ||
27 | #include <linux/slab.h> | ||
28 | #include <linux/mutex.h> | ||
29 | #include <linux/i2c.h> | ||
30 | #include <linux/delay.h> | ||
31 | #include <linux/gpio.h> | ||
32 | |||
33 | #include <video/omapdss.h> | ||
34 | #include <video/omap-panel-picodlp.h> | ||
35 | |||
36 | #include "panel-picodlp.h" | ||
37 | |||
38 | struct picodlp_data { | ||
39 | struct mutex lock; | ||
40 | struct i2c_client *picodlp_i2c_client; | ||
41 | }; | ||
42 | |||
43 | static struct i2c_board_info picodlp_i2c_board_info = { | ||
44 | I2C_BOARD_INFO("picodlp_i2c_driver", 0x1b), | ||
45 | }; | ||
46 | |||
47 | struct picodlp_i2c_data { | ||
48 | struct mutex xfer_lock; | ||
49 | }; | ||
50 | |||
51 | static struct i2c_device_id picodlp_i2c_id[] = { | ||
52 | { "picodlp_i2c_driver", 0 }, | ||
53 | }; | ||
54 | |||
55 | struct picodlp_i2c_command { | ||
56 | u8 reg; | ||
57 | u32 value; | ||
58 | }; | ||
59 | |||
60 | static struct omap_video_timings pico_ls_timings = { | ||
61 | .x_res = 864, | ||
62 | .y_res = 480, | ||
63 | .hsw = 7, | ||
64 | .hfp = 11, | ||
65 | .hbp = 7, | ||
66 | |||
67 | .pixel_clock = 19200, | ||
68 | |||
69 | .vsw = 2, | ||
70 | .vfp = 3, | ||
71 | .vbp = 14, | ||
72 | }; | ||
73 | |||
74 | static inline struct picodlp_panel_data | ||
75 | *get_panel_data(const struct omap_dss_device *dssdev) | ||
76 | { | ||
77 | return (struct picodlp_panel_data *) dssdev->data; | ||
78 | } | ||
79 | |||
80 | static u32 picodlp_i2c_read(struct i2c_client *client, u8 reg) | ||
81 | { | ||
82 | u8 read_cmd[] = {READ_REG_SELECT, reg}, data[4]; | ||
83 | struct picodlp_i2c_data *picodlp_i2c_data = i2c_get_clientdata(client); | ||
84 | struct i2c_msg msg[2]; | ||
85 | |||
86 | mutex_lock(&picodlp_i2c_data->xfer_lock); | ||
87 | |||
88 | msg[0].addr = client->addr; | ||
89 | msg[0].flags = 0; | ||
90 | msg[0].len = 2; | ||
91 | msg[0].buf = read_cmd; | ||
92 | |||
93 | msg[1].addr = client->addr; | ||
94 | msg[1].flags = I2C_M_RD; | ||
95 | msg[1].len = 4; | ||
96 | msg[1].buf = data; | ||
97 | |||
98 | i2c_transfer(client->adapter, msg, 2); | ||
99 | mutex_unlock(&picodlp_i2c_data->xfer_lock); | ||
100 | return (data[3] | (data[2] << 8) | (data[1] << 16) | (data[0] << 24)); | ||
101 | } | ||
102 | |||
103 | static int picodlp_i2c_write_block(struct i2c_client *client, | ||
104 | u8 *data, int len) | ||
105 | { | ||
106 | struct i2c_msg msg; | ||
107 | int i, r, msg_count = 1; | ||
108 | |||
109 | struct picodlp_i2c_data *picodlp_i2c_data = i2c_get_clientdata(client); | ||
110 | |||
111 | if (len < 1 || len > 32) { | ||
112 | dev_err(&client->dev, | ||
113 | "too long syn_write_block len %d\n", len); | ||
114 | return -EIO; | ||
115 | } | ||
116 | mutex_lock(&picodlp_i2c_data->xfer_lock); | ||
117 | |||
118 | msg.addr = client->addr; | ||
119 | msg.flags = 0; | ||
120 | msg.len = len; | ||
121 | msg.buf = data; | ||
122 | r = i2c_transfer(client->adapter, &msg, msg_count); | ||
123 | mutex_unlock(&picodlp_i2c_data->xfer_lock); | ||
124 | |||
125 | /* | ||
126 | * i2c_transfer returns: | ||
127 | * number of messages sent in case of success | ||
128 | * a negative error number in case of failure | ||
129 | */ | ||
130 | if (r != msg_count) | ||
131 | goto err; | ||
132 | |||
133 | /* In case of success */ | ||
134 | for (i = 0; i < len; i++) | ||
135 | dev_dbg(&client->dev, | ||
136 | "addr %x bw 0x%02x[%d]: 0x%02x\n", | ||
137 | client->addr, data[0] + i, i, data[i]); | ||
138 | |||
139 | return 0; | ||
140 | err: | ||
141 | dev_err(&client->dev, "picodlp_i2c_write error\n"); | ||
142 | return r; | ||
143 | } | ||
144 | |||
145 | static int picodlp_i2c_write(struct i2c_client *client, u8 reg, u32 value) | ||
146 | { | ||
147 | u8 data[5]; | ||
148 | int i; | ||
149 | |||
150 | data[0] = reg; | ||
151 | for (i = 1; i < 5; i++) | ||
152 | data[i] = (value >> (32 - (i) * 8)) & 0xFF; | ||
153 | |||
154 | return picodlp_i2c_write_block(client, data, 5); | ||
155 | } | ||
156 | |||
157 | static int picodlp_i2c_write_array(struct i2c_client *client, | ||
158 | const struct picodlp_i2c_command commands[], | ||
159 | int count) | ||
160 | { | ||
161 | int i, r = 0; | ||
162 | for (i = 0; i < count; i++) { | ||
163 | r = picodlp_i2c_write(client, commands[i].reg, | ||
164 | commands[i].value); | ||
165 | if (r) | ||
166 | return r; | ||
167 | } | ||
168 | return r; | ||
169 | } | ||
170 | |||
171 | static int picodlp_wait_for_dma_done(struct i2c_client *client) | ||
172 | { | ||
173 | u8 trial = 100; | ||
174 | |||
175 | do { | ||
176 | msleep(1); | ||
177 | if (!trial--) | ||
178 | return -ETIMEDOUT; | ||
179 | } while (picodlp_i2c_read(client, MAIN_STATUS) & DMA_STATUS); | ||
180 | |||
181 | return 0; | ||
182 | } | ||
183 | |||
184 | /** | ||
185 | * picodlp_i2c_init: i2c_initialization routine | ||
186 | * client: i2c_client for communication | ||
187 | * | ||
188 | * return | ||
189 | * 0 : Success, no error | ||
190 | * error code : Failure | ||
191 | */ | ||
192 | static int picodlp_i2c_init(struct i2c_client *client) | ||
193 | { | ||
194 | int r; | ||
195 | static const struct picodlp_i2c_command init_cmd_set1[] = { | ||
196 | {SOFT_RESET, 1}, | ||
197 | {DMD_PARK_TRIGGER, 1}, | ||
198 | {MISC_REG, 5}, | ||
199 | {SEQ_CONTROL, 0}, | ||
200 | {SEQ_VECTOR, 0x100}, | ||
201 | {DMD_BLOCK_COUNT, 7}, | ||
202 | {DMD_VCC_CONTROL, 0x109}, | ||
203 | {DMD_PARK_PULSE_COUNT, 0xA}, | ||
204 | {DMD_PARK_PULSE_WIDTH, 0xB}, | ||
205 | {DMD_PARK_DELAY, 0x2ED}, | ||
206 | {DMD_SHADOW_ENABLE, 0}, | ||
207 | {FLASH_OPCODE, 0xB}, | ||
208 | {FLASH_DUMMY_BYTES, 1}, | ||
209 | {FLASH_ADDR_BYTES, 3}, | ||
210 | {PBC_CONTROL, 0}, | ||
211 | {FLASH_START_ADDR, CMT_LUT_0_START_ADDR}, | ||
212 | {FLASH_READ_BYTES, CMT_LUT_0_SIZE}, | ||
213 | {CMT_SPLASH_LUT_START_ADDR, 0}, | ||
214 | {CMT_SPLASH_LUT_DEST_SELECT, CMT_LUT_ALL}, | ||
215 | {PBC_CONTROL, 1}, | ||
216 | }; | ||
217 | |||
218 | static const struct picodlp_i2c_command init_cmd_set2[] = { | ||
219 | {PBC_CONTROL, 0}, | ||
220 | {CMT_SPLASH_LUT_DEST_SELECT, 0}, | ||
221 | {PBC_CONTROL, 0}, | ||
222 | {FLASH_START_ADDR, SEQUENCE_0_START_ADDR}, | ||
223 | {FLASH_READ_BYTES, SEQUENCE_0_SIZE}, | ||
224 | {SEQ_RESET_LUT_START_ADDR, 0}, | ||
225 | {SEQ_RESET_LUT_DEST_SELECT, SEQ_SEQ_LUT}, | ||
226 | {PBC_CONTROL, 1}, | ||
227 | }; | ||
228 | |||
229 | static const struct picodlp_i2c_command init_cmd_set3[] = { | ||
230 | {PBC_CONTROL, 0}, | ||
231 | {SEQ_RESET_LUT_DEST_SELECT, 0}, | ||
232 | {PBC_CONTROL, 0}, | ||
233 | {FLASH_START_ADDR, DRC_TABLE_0_START_ADDR}, | ||
234 | {FLASH_READ_BYTES, DRC_TABLE_0_SIZE}, | ||
235 | {SEQ_RESET_LUT_START_ADDR, 0}, | ||
236 | {SEQ_RESET_LUT_DEST_SELECT, SEQ_DRC_LUT_ALL}, | ||
237 | {PBC_CONTROL, 1}, | ||
238 | }; | ||
239 | |||
240 | static const struct picodlp_i2c_command init_cmd_set4[] = { | ||
241 | {PBC_CONTROL, 0}, | ||
242 | {SEQ_RESET_LUT_DEST_SELECT, 0}, | ||
243 | {SDC_ENABLE, 1}, | ||
244 | {AGC_CTRL, 7}, | ||
245 | {CCA_C1A, 0x100}, | ||
246 | {CCA_C1B, 0x0}, | ||
247 | {CCA_C1C, 0x0}, | ||
248 | {CCA_C2A, 0x0}, | ||
249 | {CCA_C2B, 0x100}, | ||
250 | {CCA_C2C, 0x0}, | ||
251 | {CCA_C3A, 0x0}, | ||
252 | {CCA_C3B, 0x0}, | ||
253 | {CCA_C3C, 0x100}, | ||
254 | {CCA_C7A, 0x100}, | ||
255 | {CCA_C7B, 0x100}, | ||
256 | {CCA_C7C, 0x100}, | ||
257 | {CCA_ENABLE, 1}, | ||
258 | {CPU_IF_MODE, 1}, | ||
259 | {SHORT_FLIP, 1}, | ||
260 | {CURTAIN_CONTROL, 0}, | ||
261 | {DMD_PARK_TRIGGER, 0}, | ||
262 | {R_DRIVE_CURRENT, 0x298}, | ||
263 | {G_DRIVE_CURRENT, 0x298}, | ||
264 | {B_DRIVE_CURRENT, 0x298}, | ||
265 | {RGB_DRIVER_ENABLE, 7}, | ||
266 | {SEQ_CONTROL, 0}, | ||
267 | {ACTGEN_CONTROL, 0x10}, | ||
268 | {SEQUENCE_MODE, SEQ_LOCK}, | ||
269 | {DATA_FORMAT, RGB888}, | ||
270 | {INPUT_RESOLUTION, WVGA_864_LANDSCAPE}, | ||
271 | {INPUT_SOURCE, PARALLEL_RGB}, | ||
272 | {CPU_IF_SYNC_METHOD, 1}, | ||
273 | {SEQ_CONTROL, 1} | ||
274 | }; | ||
275 | |||
276 | r = picodlp_i2c_write_array(client, init_cmd_set1, | ||
277 | ARRAY_SIZE(init_cmd_set1)); | ||
278 | if (r) | ||
279 | return r; | ||
280 | |||
281 | r = picodlp_wait_for_dma_done(client); | ||
282 | if (r) | ||
283 | return r; | ||
284 | |||
285 | r = picodlp_i2c_write_array(client, init_cmd_set2, | ||
286 | ARRAY_SIZE(init_cmd_set2)); | ||
287 | if (r) | ||
288 | return r; | ||
289 | |||
290 | r = picodlp_wait_for_dma_done(client); | ||
291 | if (r) | ||
292 | return r; | ||
293 | |||
294 | r = picodlp_i2c_write_array(client, init_cmd_set3, | ||
295 | ARRAY_SIZE(init_cmd_set3)); | ||
296 | if (r) | ||
297 | return r; | ||
298 | |||
299 | r = picodlp_wait_for_dma_done(client); | ||
300 | if (r) | ||
301 | return r; | ||
302 | |||
303 | r = picodlp_i2c_write_array(client, init_cmd_set4, | ||
304 | ARRAY_SIZE(init_cmd_set4)); | ||
305 | if (r) | ||
306 | return r; | ||
307 | |||
308 | return 0; | ||
309 | } | ||
310 | |||
311 | static int picodlp_i2c_probe(struct i2c_client *client, | ||
312 | const struct i2c_device_id *id) | ||
313 | { | ||
314 | struct picodlp_i2c_data *picodlp_i2c_data; | ||
315 | |||
316 | picodlp_i2c_data = kzalloc(sizeof(struct picodlp_i2c_data), GFP_KERNEL); | ||
317 | |||
318 | if (!picodlp_i2c_data) | ||
319 | return -ENOMEM; | ||
320 | |||
321 | mutex_init(&picodlp_i2c_data->xfer_lock); | ||
322 | i2c_set_clientdata(client, picodlp_i2c_data); | ||
323 | |||
324 | return 0; | ||
325 | } | ||
326 | |||
327 | static int picodlp_i2c_remove(struct i2c_client *client) | ||
328 | { | ||
329 | struct picodlp_i2c_data *picodlp_i2c_data = | ||
330 | i2c_get_clientdata(client); | ||
331 | kfree(picodlp_i2c_data); | ||
332 | return 0; | ||
333 | } | ||
334 | |||
335 | static struct i2c_driver picodlp_i2c_driver = { | ||
336 | .driver = { | ||
337 | .name = "picodlp_i2c_driver", | ||
338 | }, | ||
339 | .probe = picodlp_i2c_probe, | ||
340 | .remove = picodlp_i2c_remove, | ||
341 | .id_table = picodlp_i2c_id, | ||
342 | }; | ||
343 | |||
344 | static int picodlp_panel_power_on(struct omap_dss_device *dssdev) | ||
345 | { | ||
346 | int r, trial = 100; | ||
347 | struct picodlp_data *picod = dev_get_drvdata(&dssdev->dev); | ||
348 | struct picodlp_panel_data *picodlp_pdata = get_panel_data(dssdev); | ||
349 | |||
350 | if (dssdev->platform_enable) { | ||
351 | r = dssdev->platform_enable(dssdev); | ||
352 | if (r) | ||
353 | return r; | ||
354 | } | ||
355 | |||
356 | gpio_set_value(picodlp_pdata->pwrgood_gpio, 0); | ||
357 | msleep(1); | ||
358 | gpio_set_value(picodlp_pdata->pwrgood_gpio, 1); | ||
359 | |||
360 | while (!gpio_get_value(picodlp_pdata->emu_done_gpio)) { | ||
361 | if (!trial--) { | ||
362 | dev_err(&dssdev->dev, "emu_done signal not" | ||
363 | " going high\n"); | ||
364 | return -ETIMEDOUT; | ||
365 | } | ||
366 | msleep(5); | ||
367 | } | ||
368 | /* | ||
369 | * As per dpp2600 programming guide, | ||
370 | * it is required to sleep for 1000ms after emu_done signal goes high | ||
371 | * then only i2c commands can be successfully sent to dpp2600 | ||
372 | */ | ||
373 | msleep(1000); | ||
374 | r = omapdss_dpi_display_enable(dssdev); | ||
375 | if (r) { | ||
376 | dev_err(&dssdev->dev, "failed to enable DPI\n"); | ||
377 | goto err1; | ||
378 | } | ||
379 | |||
380 | r = picodlp_i2c_init(picod->picodlp_i2c_client); | ||
381 | if (r) | ||
382 | goto err; | ||
383 | |||
384 | dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; | ||
385 | |||
386 | return r; | ||
387 | err: | ||
388 | omapdss_dpi_display_disable(dssdev); | ||
389 | err1: | ||
390 | if (dssdev->platform_disable) | ||
391 | dssdev->platform_disable(dssdev); | ||
392 | |||
393 | return r; | ||
394 | } | ||
395 | |||
396 | static void picodlp_panel_power_off(struct omap_dss_device *dssdev) | ||
397 | { | ||
398 | struct picodlp_panel_data *picodlp_pdata = get_panel_data(dssdev); | ||
399 | |||
400 | omapdss_dpi_display_disable(dssdev); | ||
401 | |||
402 | gpio_set_value(picodlp_pdata->emu_done_gpio, 0); | ||
403 | gpio_set_value(picodlp_pdata->pwrgood_gpio, 0); | ||
404 | |||
405 | if (dssdev->platform_disable) | ||
406 | dssdev->platform_disable(dssdev); | ||
407 | } | ||
408 | |||
409 | static int picodlp_panel_probe(struct omap_dss_device *dssdev) | ||
410 | { | ||
411 | struct picodlp_data *picod; | ||
412 | struct picodlp_panel_data *picodlp_pdata = get_panel_data(dssdev); | ||
413 | struct i2c_adapter *adapter; | ||
414 | struct i2c_client *picodlp_i2c_client; | ||
415 | int r = 0, picodlp_adapter_id; | ||
416 | |||
417 | dssdev->panel.config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_ONOFF | | ||
418 | OMAP_DSS_LCD_IHS | OMAP_DSS_LCD_IVS; | ||
419 | dssdev->panel.acb = 0x0; | ||
420 | dssdev->panel.timings = pico_ls_timings; | ||
421 | |||
422 | picod = kzalloc(sizeof(struct picodlp_data), GFP_KERNEL); | ||
423 | if (!picod) | ||
424 | return -ENOMEM; | ||
425 | |||
426 | mutex_init(&picod->lock); | ||
427 | |||
428 | picodlp_adapter_id = picodlp_pdata->picodlp_adapter_id; | ||
429 | |||
430 | adapter = i2c_get_adapter(picodlp_adapter_id); | ||
431 | if (!adapter) { | ||
432 | dev_err(&dssdev->dev, "can't get i2c adapter\n"); | ||
433 | r = -ENODEV; | ||
434 | goto err; | ||
435 | } | ||
436 | |||
437 | picodlp_i2c_client = i2c_new_device(adapter, &picodlp_i2c_board_info); | ||
438 | if (!picodlp_i2c_client) { | ||
439 | dev_err(&dssdev->dev, "can't add i2c device::" | ||
440 | " picodlp_i2c_client is NULL\n"); | ||
441 | r = -ENODEV; | ||
442 | goto err; | ||
443 | } | ||
444 | |||
445 | picod->picodlp_i2c_client = picodlp_i2c_client; | ||
446 | |||
447 | dev_set_drvdata(&dssdev->dev, picod); | ||
448 | return r; | ||
449 | err: | ||
450 | kfree(picod); | ||
451 | return r; | ||
452 | } | ||
453 | |||
454 | static void picodlp_panel_remove(struct omap_dss_device *dssdev) | ||
455 | { | ||
456 | struct picodlp_data *picod = dev_get_drvdata(&dssdev->dev); | ||
457 | |||
458 | i2c_unregister_device(picod->picodlp_i2c_client); | ||
459 | dev_set_drvdata(&dssdev->dev, NULL); | ||
460 | dev_dbg(&dssdev->dev, "removing picodlp panel\n"); | ||
461 | |||
462 | kfree(picod); | ||
463 | } | ||
464 | |||
465 | static int picodlp_panel_enable(struct omap_dss_device *dssdev) | ||
466 | { | ||
467 | struct picodlp_data *picod = dev_get_drvdata(&dssdev->dev); | ||
468 | int r; | ||
469 | |||
470 | dev_dbg(&dssdev->dev, "enabling picodlp panel\n"); | ||
471 | |||
472 | mutex_lock(&picod->lock); | ||
473 | if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) { | ||
474 | mutex_unlock(&picod->lock); | ||
475 | return -EINVAL; | ||
476 | } | ||
477 | |||
478 | r = picodlp_panel_power_on(dssdev); | ||
479 | mutex_unlock(&picod->lock); | ||
480 | |||
481 | return r; | ||
482 | } | ||
483 | |||
484 | static void picodlp_panel_disable(struct omap_dss_device *dssdev) | ||
485 | { | ||
486 | struct picodlp_data *picod = dev_get_drvdata(&dssdev->dev); | ||
487 | |||
488 | mutex_lock(&picod->lock); | ||
489 | /* Turn off DLP Power */ | ||
490 | if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) | ||
491 | picodlp_panel_power_off(dssdev); | ||
492 | |||
493 | dssdev->state = OMAP_DSS_DISPLAY_DISABLED; | ||
494 | mutex_unlock(&picod->lock); | ||
495 | |||
496 | dev_dbg(&dssdev->dev, "disabling picodlp panel\n"); | ||
497 | } | ||
498 | |||
499 | static int picodlp_panel_suspend(struct omap_dss_device *dssdev) | ||
500 | { | ||
501 | struct picodlp_data *picod = dev_get_drvdata(&dssdev->dev); | ||
502 | |||
503 | mutex_lock(&picod->lock); | ||
504 | /* Turn off DLP Power */ | ||
505 | if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) { | ||
506 | mutex_unlock(&picod->lock); | ||
507 | dev_err(&dssdev->dev, "unable to suspend picodlp panel," | ||
508 | " panel is not ACTIVE\n"); | ||
509 | return -EINVAL; | ||
510 | } | ||
511 | |||
512 | picodlp_panel_power_off(dssdev); | ||
513 | |||
514 | dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED; | ||
515 | mutex_unlock(&picod->lock); | ||
516 | |||
517 | dev_dbg(&dssdev->dev, "suspending picodlp panel\n"); | ||
518 | return 0; | ||
519 | } | ||
520 | |||
521 | static int picodlp_panel_resume(struct omap_dss_device *dssdev) | ||
522 | { | ||
523 | struct picodlp_data *picod = dev_get_drvdata(&dssdev->dev); | ||
524 | int r; | ||
525 | |||
526 | mutex_lock(&picod->lock); | ||
527 | if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED) { | ||
528 | mutex_unlock(&picod->lock); | ||
529 | dev_err(&dssdev->dev, "unable to resume picodlp panel," | ||
530 | " panel is not ACTIVE\n"); | ||
531 | return -EINVAL; | ||
532 | } | ||
533 | |||
534 | r = picodlp_panel_power_on(dssdev); | ||
535 | mutex_unlock(&picod->lock); | ||
536 | dev_dbg(&dssdev->dev, "resuming picodlp panel\n"); | ||
537 | return r; | ||
538 | } | ||
539 | |||
540 | static void picodlp_get_resolution(struct omap_dss_device *dssdev, | ||
541 | u16 *xres, u16 *yres) | ||
542 | { | ||
543 | *xres = dssdev->panel.timings.x_res; | ||
544 | *yres = dssdev->panel.timings.y_res; | ||
545 | } | ||
546 | |||
547 | static struct omap_dss_driver picodlp_driver = { | ||
548 | .probe = picodlp_panel_probe, | ||
549 | .remove = picodlp_panel_remove, | ||
550 | |||
551 | .enable = picodlp_panel_enable, | ||
552 | .disable = picodlp_panel_disable, | ||
553 | |||
554 | .get_resolution = picodlp_get_resolution, | ||
555 | |||
556 | .suspend = picodlp_panel_suspend, | ||
557 | .resume = picodlp_panel_resume, | ||
558 | |||
559 | .driver = { | ||
560 | .name = "picodlp_panel", | ||
561 | .owner = THIS_MODULE, | ||
562 | }, | ||
563 | }; | ||
564 | |||
565 | static int __init picodlp_init(void) | ||
566 | { | ||
567 | int r = 0; | ||
568 | |||
569 | r = i2c_add_driver(&picodlp_i2c_driver); | ||
570 | if (r) { | ||
571 | printk(KERN_WARNING "picodlp_i2c_driver" \ | ||
572 | " registration failed\n"); | ||
573 | return r; | ||
574 | } | ||
575 | |||
576 | r = omap_dss_register_driver(&picodlp_driver); | ||
577 | if (r) | ||
578 | i2c_del_driver(&picodlp_i2c_driver); | ||
579 | |||
580 | return r; | ||
581 | } | ||
582 | |||
583 | static void __exit picodlp_exit(void) | ||
584 | { | ||
585 | i2c_del_driver(&picodlp_i2c_driver); | ||
586 | omap_dss_unregister_driver(&picodlp_driver); | ||
587 | } | ||
588 | |||
589 | module_init(picodlp_init); | ||
590 | module_exit(picodlp_exit); | ||
591 | |||
592 | MODULE_AUTHOR("Mythri P K <mythripk@ti.com>"); | ||
593 | MODULE_DESCRIPTION("picodlp driver"); | ||
594 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/video/omap2/displays/panel-picodlp.h b/drivers/video/omap2/displays/panel-picodlp.h new file mode 100644 index 000000000000..a34b431a7267 --- /dev/null +++ b/drivers/video/omap2/displays/panel-picodlp.h | |||
@@ -0,0 +1,288 @@ | |||
1 | /* | ||
2 | * Header file required by picodlp panel driver | ||
3 | * | ||
4 | * Copyright (C) 2009-2011 Texas Instruments | ||
5 | * Author: Mythri P K <mythripk@ti.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify it | ||
8 | * under the terms of the GNU General Public License version 2 as published by | ||
9 | * the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
14 | * more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License along with | ||
17 | * this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | #ifndef __OMAP2_DISPLAY_PANEL_PICODLP_H | ||
21 | #define __OMAP2_DISPLAY_PANEL_PICODLP_H | ||
22 | |||
23 | /* Commands used for configuring picodlp panel */ | ||
24 | |||
25 | #define MAIN_STATUS 0x03 | ||
26 | #define PBC_CONTROL 0x08 | ||
27 | #define INPUT_SOURCE 0x0B | ||
28 | #define INPUT_RESOLUTION 0x0C | ||
29 | #define DATA_FORMAT 0x0D | ||
30 | #define IMG_ROTATION 0x0E | ||
31 | #define LONG_FLIP 0x0F | ||
32 | #define SHORT_FLIP 0x10 | ||
33 | #define TEST_PAT_SELECT 0x11 | ||
34 | #define R_DRIVE_CURRENT 0x12 | ||
35 | #define G_DRIVE_CURRENT 0x13 | ||
36 | #define B_DRIVE_CURRENT 0x14 | ||
37 | #define READ_REG_SELECT 0x15 | ||
38 | #define RGB_DRIVER_ENABLE 0x16 | ||
39 | |||
40 | #define CPU_IF_MODE 0x18 | ||
41 | #define FRAME_RATE 0x19 | ||
42 | #define CPU_IF_SYNC_METHOD 0x1A | ||
43 | #define CPU_IF_SOF 0x1B | ||
44 | #define CPU_IF_EOF 0x1C | ||
45 | #define CPU_IF_SLEEP 0x1D | ||
46 | |||
47 | #define SEQUENCE_MODE 0x1E | ||
48 | #define SOFT_RESET 0x1F | ||
49 | #define FRONT_END_RESET 0x21 | ||
50 | #define AUTO_PWR_ENABLE 0x22 | ||
51 | |||
52 | #define VSYNC_LINE_DELAY 0x23 | ||
53 | #define CPU_PI_HORIZ_START 0x24 | ||
54 | #define CPU_PI_VERT_START 0x25 | ||
55 | #define CPU_PI_HORIZ_WIDTH 0x26 | ||
56 | #define CPU_PI_VERT_HEIGHT 0x27 | ||
57 | |||
58 | #define PIXEL_MASK_CROP 0x28 | ||
59 | #define CROP_FIRST_LINE 0x29 | ||
60 | #define CROP_LAST_LINE 0x2A | ||
61 | #define CROP_FIRST_PIXEL 0x2B | ||
62 | #define CROP_LAST_PIXEL 0x2C | ||
63 | #define DMD_PARK_TRIGGER 0x2D | ||
64 | |||
65 | #define MISC_REG 0x30 | ||
66 | |||
67 | /* AGC registers */ | ||
68 | #define AGC_CTRL 0x50 | ||
69 | #define AGC_CLIPPED_PIXS 0x55 | ||
70 | #define AGC_BRIGHT_PIXS 0x56 | ||
71 | #define AGC_BG_PIXS 0x57 | ||
72 | #define AGC_SAFETY_MARGIN 0x17 | ||
73 | |||
74 | /* Color Coordinate Adjustment registers */ | ||
75 | #define CCA_ENABLE 0x5E | ||
76 | #define CCA_C1A 0x5F | ||
77 | #define CCA_C1B 0x60 | ||
78 | #define CCA_C1C 0x61 | ||
79 | #define CCA_C2A 0x62 | ||
80 | #define CCA_C2B 0x63 | ||
81 | #define CCA_C2C 0x64 | ||
82 | #define CCA_C3A 0x65 | ||
83 | #define CCA_C3B 0x66 | ||
84 | #define CCA_C3C 0x67 | ||
85 | #define CCA_C7A 0x71 | ||
86 | #define CCA_C7B 0x72 | ||
87 | #define CCA_C7C 0x73 | ||
88 | |||
89 | /** | ||
90 | * DLP Pico Processor 2600 comes with flash | ||
91 | * We can do DMA operations from flash for accessing Look Up Tables | ||
92 | */ | ||
93 | #define DMA_STATUS 0x100 | ||
94 | #define FLASH_ADDR_BYTES 0x74 | ||
95 | #define FLASH_DUMMY_BYTES 0x75 | ||
96 | #define FLASH_WRITE_BYTES 0x76 | ||
97 | #define FLASH_READ_BYTES 0x77 | ||
98 | #define FLASH_OPCODE 0x78 | ||
99 | #define FLASH_START_ADDR 0x79 | ||
100 | #define FLASH_DUMMY2 0x7A | ||
101 | #define FLASH_WRITE_DATA 0x7B | ||
102 | |||
103 | #define TEMPORAL_DITH_DISABLE 0x7E | ||
104 | #define SEQ_CONTROL 0x82 | ||
105 | #define SEQ_VECTOR 0x83 | ||
106 | |||
107 | /* DMD is Digital Micromirror Device */ | ||
108 | #define DMD_BLOCK_COUNT 0x84 | ||
109 | #define DMD_VCC_CONTROL 0x86 | ||
110 | #define DMD_PARK_PULSE_COUNT 0x87 | ||
111 | #define DMD_PARK_PULSE_WIDTH 0x88 | ||
112 | #define DMD_PARK_DELAY 0x89 | ||
113 | #define DMD_SHADOW_ENABLE 0x8E | ||
114 | #define SEQ_STATUS 0x8F | ||
115 | #define FLASH_CLOCK_CONTROL 0x98 | ||
116 | #define DMD_PARK 0x2D | ||
117 | |||
118 | #define SDRAM_BIST_ENABLE 0x46 | ||
119 | #define DDR_DRIVER_STRENGTH 0x9A | ||
120 | #define SDC_ENABLE 0x9D | ||
121 | #define SDC_BUFF_SWAP_DISABLE 0xA3 | ||
122 | #define CURTAIN_CONTROL 0xA6 | ||
123 | #define DDR_BUS_SWAP_ENABLE 0xA7 | ||
124 | #define DMD_TRC_ENABLE 0xA8 | ||
125 | #define DMD_BUS_SWAP_ENABLE 0xA9 | ||
126 | |||
127 | #define ACTGEN_ENABLE 0xAE | ||
128 | #define ACTGEN_CONTROL 0xAF | ||
129 | #define ACTGEN_HORIZ_BP 0xB0 | ||
130 | #define ACTGEN_VERT_BP 0xB1 | ||
131 | |||
132 | /* Look Up Table access */ | ||
133 | #define CMT_SPLASH_LUT_START_ADDR 0xFA | ||
134 | #define CMT_SPLASH_LUT_DEST_SELECT 0xFB | ||
135 | #define CMT_SPLASH_LUT_DATA 0xFC | ||
136 | #define SEQ_RESET_LUT_START_ADDR 0xFD | ||
137 | #define SEQ_RESET_LUT_DEST_SELECT 0xFE | ||
138 | #define SEQ_RESET_LUT_DATA 0xFF | ||
139 | |||
140 | /* Input source definitions */ | ||
141 | #define PARALLEL_RGB 0 | ||
142 | #define INT_TEST_PATTERN 1 | ||
143 | #define SPLASH_SCREEN 2 | ||
144 | #define CPU_INTF 3 | ||
145 | #define BT656 4 | ||
146 | |||
147 | /* Standard input resolution definitions */ | ||
148 | #define QWVGA_LANDSCAPE 3 /* (427h*240v) */ | ||
149 | #define WVGA_864_LANDSCAPE 21 /* (864h*480v) */ | ||
150 | #define WVGA_DMD_OPTICAL_TEST 35 /* (608h*684v) */ | ||
151 | |||
152 | /* Standard data format definitions */ | ||
153 | #define RGB565 0 | ||
154 | #define RGB666 1 | ||
155 | #define RGB888 2 | ||
156 | |||
157 | /* Test Pattern definitions */ | ||
158 | #define TPG_CHECKERBOARD 0 | ||
159 | #define TPG_BLACK 1 | ||
160 | #define TPG_WHITE 2 | ||
161 | #define TPG_RED 3 | ||
162 | #define TPG_BLUE 4 | ||
163 | #define TPG_GREEN 5 | ||
164 | #define TPG_VLINES_BLACK 6 | ||
165 | #define TPG_HLINES_BLACK 7 | ||
166 | #define TPG_VLINES_ALT 8 | ||
167 | #define TPG_HLINES_ALT 9 | ||
168 | #define TPG_DIAG_LINES 10 | ||
169 | #define TPG_GREYRAMP_VERT 11 | ||
170 | #define TPG_GREYRAMP_HORIZ 12 | ||
171 | #define TPG_ANSI_CHECKERBOARD 13 | ||
172 | |||
173 | /* sequence mode definitions */ | ||
174 | #define SEQ_FREE_RUN 0 | ||
175 | #define SEQ_LOCK 1 | ||
176 | |||
177 | /* curtain color definitions */ | ||
178 | #define CURTAIN_BLACK 0 | ||
179 | #define CURTAIN_RED 1 | ||
180 | #define CURTAIN_GREEN 2 | ||
181 | #define CURTAIN_BLUE 3 | ||
182 | #define CURTAIN_YELLOW 4 | ||
183 | #define CURTAIN_MAGENTA 5 | ||
184 | #define CURTAIN_CYAN 6 | ||
185 | #define CURTAIN_WHITE 7 | ||
186 | |||
187 | /* LUT definitions */ | ||
188 | #define CMT_LUT_NONE 0 | ||
189 | #define CMT_LUT_GREEN 1 | ||
190 | #define CMT_LUT_RED 2 | ||
191 | #define CMT_LUT_BLUE 3 | ||
192 | #define CMT_LUT_ALL 4 | ||
193 | #define SPLASH_LUT 5 | ||
194 | |||
195 | #define SEQ_LUT_NONE 0 | ||
196 | #define SEQ_DRC_LUT_0 1 | ||
197 | #define SEQ_DRC_LUT_1 2 | ||
198 | #define SEQ_DRC_LUT_2 3 | ||
199 | #define SEQ_DRC_LUT_3 4 | ||
200 | #define SEQ_SEQ_LUT 5 | ||
201 | #define SEQ_DRC_LUT_ALL 6 | ||
202 | #define WPC_PROGRAM_LUT 7 | ||
203 | |||
204 | #define BITSTREAM_START_ADDR 0x00000000 | ||
205 | #define BITSTREAM_SIZE 0x00040000 | ||
206 | |||
207 | #define WPC_FW_0_START_ADDR 0x00040000 | ||
208 | #define WPC_FW_0_SIZE 0x00000ce8 | ||
209 | |||
210 | #define SEQUENCE_0_START_ADDR 0x00044000 | ||
211 | #define SEQUENCE_0_SIZE 0x00001000 | ||
212 | |||
213 | #define SEQUENCE_1_START_ADDR 0x00045000 | ||
214 | #define SEQUENCE_1_SIZE 0x00000d10 | ||
215 | |||
216 | #define SEQUENCE_2_START_ADDR 0x00046000 | ||
217 | #define SEQUENCE_2_SIZE 0x00000d10 | ||
218 | |||
219 | #define SEQUENCE_3_START_ADDR 0x00047000 | ||
220 | #define SEQUENCE_3_SIZE 0x00000d10 | ||
221 | |||
222 | #define SEQUENCE_4_START_ADDR 0x00048000 | ||
223 | #define SEQUENCE_4_SIZE 0x00000d10 | ||
224 | |||
225 | #define SEQUENCE_5_START_ADDR 0x00049000 | ||
226 | #define SEQUENCE_5_SIZE 0x00000d10 | ||
227 | |||
228 | #define SEQUENCE_6_START_ADDR 0x0004a000 | ||
229 | #define SEQUENCE_6_SIZE 0x00000d10 | ||
230 | |||
231 | #define CMT_LUT_0_START_ADDR 0x0004b200 | ||
232 | #define CMT_LUT_0_SIZE 0x00000600 | ||
233 | |||
234 | #define CMT_LUT_1_START_ADDR 0x0004b800 | ||
235 | #define CMT_LUT_1_SIZE 0x00000600 | ||
236 | |||
237 | #define CMT_LUT_2_START_ADDR 0x0004be00 | ||
238 | #define CMT_LUT_2_SIZE 0x00000600 | ||
239 | |||
240 | #define CMT_LUT_3_START_ADDR 0x0004c400 | ||
241 | #define CMT_LUT_3_SIZE 0x00000600 | ||
242 | |||
243 | #define CMT_LUT_4_START_ADDR 0x0004ca00 | ||
244 | #define CMT_LUT_4_SIZE 0x00000600 | ||
245 | |||
246 | #define CMT_LUT_5_START_ADDR 0x0004d000 | ||
247 | #define CMT_LUT_5_SIZE 0x00000600 | ||
248 | |||
249 | #define CMT_LUT_6_START_ADDR 0x0004d600 | ||
250 | #define CMT_LUT_6_SIZE 0x00000600 | ||
251 | |||
252 | #define DRC_TABLE_0_START_ADDR 0x0004dc00 | ||
253 | #define DRC_TABLE_0_SIZE 0x00000100 | ||
254 | |||
255 | #define SPLASH_0_START_ADDR 0x0004dd00 | ||
256 | #define SPLASH_0_SIZE 0x00032280 | ||
257 | |||
258 | #define SEQUENCE_7_START_ADDR 0x00080000 | ||
259 | #define SEQUENCE_7_SIZE 0x00000d10 | ||
260 | |||
261 | #define SEQUENCE_8_START_ADDR 0x00081800 | ||
262 | #define SEQUENCE_8_SIZE 0x00000d10 | ||
263 | |||
264 | #define SEQUENCE_9_START_ADDR 0x00083000 | ||
265 | #define SEQUENCE_9_SIZE 0x00000d10 | ||
266 | |||
267 | #define CMT_LUT_7_START_ADDR 0x0008e000 | ||
268 | #define CMT_LUT_7_SIZE 0x00000600 | ||
269 | |||
270 | #define CMT_LUT_8_START_ADDR 0x0008e800 | ||
271 | #define CMT_LUT_8_SIZE 0x00000600 | ||
272 | |||
273 | #define CMT_LUT_9_START_ADDR 0x0008f000 | ||
274 | #define CMT_LUT_9_SIZE 0x00000600 | ||
275 | |||
276 | #define SPLASH_1_START_ADDR 0x0009a000 | ||
277 | #define SPLASH_1_SIZE 0x00032280 | ||
278 | |||
279 | #define SPLASH_2_START_ADDR 0x000cd000 | ||
280 | #define SPLASH_2_SIZE 0x00032280 | ||
281 | |||
282 | #define SPLASH_3_START_ADDR 0x00100000 | ||
283 | #define SPLASH_3_SIZE 0x00032280 | ||
284 | |||
285 | #define OPT_SPLASH_0_START_ADDR 0x00134000 | ||
286 | #define OPT_SPLASH_0_SIZE 0x000cb100 | ||
287 | |||
288 | #endif | ||
diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c index 4e888ac09b3f..80c3f6ab1a94 100644 --- a/drivers/video/omap2/displays/panel-taal.c +++ b/drivers/video/omap2/displays/panel-taal.c | |||
@@ -35,26 +35,12 @@ | |||
35 | 35 | ||
36 | #include <video/omapdss.h> | 36 | #include <video/omapdss.h> |
37 | #include <video/omap-panel-nokia-dsi.h> | 37 | #include <video/omap-panel-nokia-dsi.h> |
38 | #include <video/mipi_display.h> | ||
38 | 39 | ||
39 | /* DSI Virtual channel. Hardcoded for now. */ | 40 | /* DSI Virtual channel. Hardcoded for now. */ |
40 | #define TCH 0 | 41 | #define TCH 0 |
41 | 42 | ||
42 | #define DCS_READ_NUM_ERRORS 0x05 | 43 | #define DCS_READ_NUM_ERRORS 0x05 |
43 | #define DCS_READ_POWER_MODE 0x0a | ||
44 | #define DCS_READ_MADCTL 0x0b | ||
45 | #define DCS_READ_PIXEL_FORMAT 0x0c | ||
46 | #define DCS_RDDSDR 0x0f | ||
47 | #define DCS_SLEEP_IN 0x10 | ||
48 | #define DCS_SLEEP_OUT 0x11 | ||
49 | #define DCS_DISPLAY_OFF 0x28 | ||
50 | #define DCS_DISPLAY_ON 0x29 | ||
51 | #define DCS_COLUMN_ADDR 0x2a | ||
52 | #define DCS_PAGE_ADDR 0x2b | ||
53 | #define DCS_MEMORY_WRITE 0x2c | ||
54 | #define DCS_TEAR_OFF 0x34 | ||
55 | #define DCS_TEAR_ON 0x35 | ||
56 | #define DCS_MEM_ACC_CTRL 0x36 | ||
57 | #define DCS_PIXEL_FORMAT 0x3a | ||
58 | #define DCS_BRIGHTNESS 0x51 | 44 | #define DCS_BRIGHTNESS 0x51 |
59 | #define DCS_CTRL_DISPLAY 0x53 | 45 | #define DCS_CTRL_DISPLAY 0x53 |
60 | #define DCS_WRITE_CABC 0x55 | 46 | #define DCS_WRITE_CABC 0x55 |
@@ -222,8 +208,6 @@ struct taal_data { | |||
222 | 208 | ||
223 | struct delayed_work te_timeout_work; | 209 | struct delayed_work te_timeout_work; |
224 | 210 | ||
225 | bool use_dsi_bl; | ||
226 | |||
227 | bool cabc_broken; | 211 | bool cabc_broken; |
228 | unsigned cabc_mode; | 212 | unsigned cabc_mode; |
229 | 213 | ||
@@ -302,7 +286,7 @@ static int taal_sleep_in(struct taal_data *td) | |||
302 | 286 | ||
303 | hw_guard_wait(td); | 287 | hw_guard_wait(td); |
304 | 288 | ||
305 | cmd = DCS_SLEEP_IN; | 289 | cmd = MIPI_DCS_ENTER_SLEEP_MODE; |
306 | r = dsi_vc_dcs_write_nosync(td->dssdev, td->channel, &cmd, 1); | 290 | r = dsi_vc_dcs_write_nosync(td->dssdev, td->channel, &cmd, 1); |
307 | if (r) | 291 | if (r) |
308 | return r; | 292 | return r; |
@@ -321,7 +305,7 @@ static int taal_sleep_out(struct taal_data *td) | |||
321 | 305 | ||
322 | hw_guard_wait(td); | 306 | hw_guard_wait(td); |
323 | 307 | ||
324 | r = taal_dcs_write_0(td, DCS_SLEEP_OUT); | 308 | r = taal_dcs_write_0(td, MIPI_DCS_EXIT_SLEEP_MODE); |
325 | if (r) | 309 | if (r) |
326 | return r; | 310 | return r; |
327 | 311 | ||
@@ -356,7 +340,7 @@ static int taal_set_addr_mode(struct taal_data *td, u8 rotate, bool mirror) | |||
356 | u8 mode; | 340 | u8 mode; |
357 | int b5, b6, b7; | 341 | int b5, b6, b7; |
358 | 342 | ||
359 | r = taal_dcs_read_1(td, DCS_READ_MADCTL, &mode); | 343 | r = taal_dcs_read_1(td, MIPI_DCS_GET_ADDRESS_MODE, &mode); |
360 | if (r) | 344 | if (r) |
361 | return r; | 345 | return r; |
362 | 346 | ||
@@ -390,7 +374,7 @@ static int taal_set_addr_mode(struct taal_data *td, u8 rotate, bool mirror) | |||
390 | mode &= ~((1<<7) | (1<<6) | (1<<5)); | 374 | mode &= ~((1<<7) | (1<<6) | (1<<5)); |
391 | mode |= (b7 << 7) | (b6 << 6) | (b5 << 5); | 375 | mode |= (b7 << 7) | (b6 << 6) | (b5 << 5); |
392 | 376 | ||
393 | return taal_dcs_write_1(td, DCS_MEM_ACC_CTRL, mode); | 377 | return taal_dcs_write_1(td, MIPI_DCS_SET_ADDRESS_MODE, mode); |
394 | } | 378 | } |
395 | 379 | ||
396 | static int taal_set_update_window(struct taal_data *td, | 380 | static int taal_set_update_window(struct taal_data *td, |
@@ -403,7 +387,7 @@ static int taal_set_update_window(struct taal_data *td, | |||
403 | u16 y2 = y + h - 1; | 387 | u16 y2 = y + h - 1; |
404 | 388 | ||
405 | u8 buf[5]; | 389 | u8 buf[5]; |
406 | buf[0] = DCS_COLUMN_ADDR; | 390 | buf[0] = MIPI_DCS_SET_COLUMN_ADDRESS; |
407 | buf[1] = (x1 >> 8) & 0xff; | 391 | buf[1] = (x1 >> 8) & 0xff; |
408 | buf[2] = (x1 >> 0) & 0xff; | 392 | buf[2] = (x1 >> 0) & 0xff; |
409 | buf[3] = (x2 >> 8) & 0xff; | 393 | buf[3] = (x2 >> 8) & 0xff; |
@@ -413,7 +397,7 @@ static int taal_set_update_window(struct taal_data *td, | |||
413 | if (r) | 397 | if (r) |
414 | return r; | 398 | return r; |
415 | 399 | ||
416 | buf[0] = DCS_PAGE_ADDR; | 400 | buf[0] = MIPI_DCS_SET_PAGE_ADDRESS; |
417 | buf[1] = (y1 >> 8) & 0xff; | 401 | buf[1] = (y1 >> 8) & 0xff; |
418 | buf[2] = (y1 >> 0) & 0xff; | 402 | buf[2] = (y1 >> 0) & 0xff; |
419 | buf[3] = (y2 >> 8) & 0xff; | 403 | buf[3] = (y2 >> 8) & 0xff; |
@@ -555,7 +539,6 @@ static int taal_bl_update_status(struct backlight_device *dev) | |||
555 | { | 539 | { |
556 | struct omap_dss_device *dssdev = dev_get_drvdata(&dev->dev); | 540 | struct omap_dss_device *dssdev = dev_get_drvdata(&dev->dev); |
557 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); | 541 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); |
558 | struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev); | ||
559 | int r; | 542 | int r; |
560 | int level; | 543 | int level; |
561 | 544 | ||
@@ -569,23 +552,16 @@ static int taal_bl_update_status(struct backlight_device *dev) | |||
569 | 552 | ||
570 | mutex_lock(&td->lock); | 553 | mutex_lock(&td->lock); |
571 | 554 | ||
572 | if (td->use_dsi_bl) { | 555 | if (td->enabled) { |
573 | if (td->enabled) { | 556 | dsi_bus_lock(dssdev); |
574 | dsi_bus_lock(dssdev); | ||
575 | 557 | ||
576 | r = taal_wake_up(dssdev); | 558 | r = taal_wake_up(dssdev); |
577 | if (!r) | 559 | if (!r) |
578 | r = taal_dcs_write_1(td, DCS_BRIGHTNESS, level); | 560 | r = taal_dcs_write_1(td, DCS_BRIGHTNESS, level); |
579 | 561 | ||
580 | dsi_bus_unlock(dssdev); | 562 | dsi_bus_unlock(dssdev); |
581 | } else { | ||
582 | r = 0; | ||
583 | } | ||
584 | } else { | 563 | } else { |
585 | if (!panel_data->set_backlight) | 564 | r = 0; |
586 | r = -EINVAL; | ||
587 | else | ||
588 | r = panel_data->set_backlight(dssdev, level); | ||
589 | } | 565 | } |
590 | 566 | ||
591 | mutex_unlock(&td->lock); | 567 | mutex_unlock(&td->lock); |
@@ -964,7 +940,7 @@ static int taal_probe(struct omap_dss_device *dssdev) | |||
964 | { | 940 | { |
965 | struct backlight_properties props; | 941 | struct backlight_properties props; |
966 | struct taal_data *td; | 942 | struct taal_data *td; |
967 | struct backlight_device *bldev; | 943 | struct backlight_device *bldev = NULL; |
968 | struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev); | 944 | struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev); |
969 | struct panel_config *panel_config = NULL; | 945 | struct panel_config *panel_config = NULL; |
970 | int r, i; | 946 | int r, i; |
@@ -990,7 +966,7 @@ static int taal_probe(struct omap_dss_device *dssdev) | |||
990 | 966 | ||
991 | dssdev->panel.config = OMAP_DSS_LCD_TFT; | 967 | dssdev->panel.config = OMAP_DSS_LCD_TFT; |
992 | dssdev->panel.timings = panel_config->timings; | 968 | dssdev->panel.timings = panel_config->timings; |
993 | dssdev->ctrl.pixel_size = 24; | 969 | dssdev->panel.dsi_pix_fmt = OMAP_DSS_DSI_FMT_RGB888; |
994 | 970 | ||
995 | td = kzalloc(sizeof(*td), GFP_KERNEL); | 971 | td = kzalloc(sizeof(*td), GFP_KERNEL); |
996 | if (!td) { | 972 | if (!td) { |
@@ -1025,35 +1001,26 @@ static int taal_probe(struct omap_dss_device *dssdev) | |||
1025 | 1001 | ||
1026 | taal_hw_reset(dssdev); | 1002 | taal_hw_reset(dssdev); |
1027 | 1003 | ||
1028 | /* if no platform set_backlight() defined, presume DSI backlight | 1004 | if (panel_data->use_dsi_backlight) { |
1029 | * control */ | 1005 | memset(&props, 0, sizeof(struct backlight_properties)); |
1030 | memset(&props, 0, sizeof(struct backlight_properties)); | ||
1031 | if (!panel_data->set_backlight) | ||
1032 | td->use_dsi_bl = true; | ||
1033 | |||
1034 | if (td->use_dsi_bl) | ||
1035 | props.max_brightness = 255; | 1006 | props.max_brightness = 255; |
1036 | else | ||
1037 | props.max_brightness = 127; | ||
1038 | |||
1039 | props.type = BACKLIGHT_RAW; | ||
1040 | bldev = backlight_device_register(dev_name(&dssdev->dev), &dssdev->dev, | ||
1041 | dssdev, &taal_bl_ops, &props); | ||
1042 | if (IS_ERR(bldev)) { | ||
1043 | r = PTR_ERR(bldev); | ||
1044 | goto err_bl; | ||
1045 | } | ||
1046 | 1007 | ||
1047 | td->bldev = bldev; | 1008 | props.type = BACKLIGHT_RAW; |
1009 | bldev = backlight_device_register(dev_name(&dssdev->dev), | ||
1010 | &dssdev->dev, dssdev, &taal_bl_ops, &props); | ||
1011 | if (IS_ERR(bldev)) { | ||
1012 | r = PTR_ERR(bldev); | ||
1013 | goto err_bl; | ||
1014 | } | ||
1015 | |||
1016 | td->bldev = bldev; | ||
1048 | 1017 | ||
1049 | bldev->props.fb_blank = FB_BLANK_UNBLANK; | 1018 | bldev->props.fb_blank = FB_BLANK_UNBLANK; |
1050 | bldev->props.power = FB_BLANK_UNBLANK; | 1019 | bldev->props.power = FB_BLANK_UNBLANK; |
1051 | if (td->use_dsi_bl) | ||
1052 | bldev->props.brightness = 255; | 1020 | bldev->props.brightness = 255; |
1053 | else | ||
1054 | bldev->props.brightness = 127; | ||
1055 | 1021 | ||
1056 | taal_bl_update_status(bldev); | 1022 | taal_bl_update_status(bldev); |
1023 | } | ||
1057 | 1024 | ||
1058 | if (panel_data->use_ext_te) { | 1025 | if (panel_data->use_ext_te) { |
1059 | int gpio = panel_data->ext_te_gpio; | 1026 | int gpio = panel_data->ext_te_gpio; |
@@ -1067,7 +1034,7 @@ static int taal_probe(struct omap_dss_device *dssdev) | |||
1067 | gpio_direction_input(gpio); | 1034 | gpio_direction_input(gpio); |
1068 | 1035 | ||
1069 | r = request_irq(gpio_to_irq(gpio), taal_te_isr, | 1036 | r = request_irq(gpio_to_irq(gpio), taal_te_isr, |
1070 | IRQF_DISABLED | IRQF_TRIGGER_RISING, | 1037 | IRQF_TRIGGER_RISING, |
1071 | "taal vsync", dssdev); | 1038 | "taal vsync", dssdev); |
1072 | 1039 | ||
1073 | if (r) { | 1040 | if (r) { |
@@ -1111,7 +1078,8 @@ err_irq: | |||
1111 | if (panel_data->use_ext_te) | 1078 | if (panel_data->use_ext_te) |
1112 | gpio_free(panel_data->ext_te_gpio); | 1079 | gpio_free(panel_data->ext_te_gpio); |
1113 | err_gpio: | 1080 | err_gpio: |
1114 | backlight_device_unregister(bldev); | 1081 | if (bldev != NULL) |
1082 | backlight_device_unregister(bldev); | ||
1115 | err_bl: | 1083 | err_bl: |
1116 | destroy_workqueue(td->workqueue); | 1084 | destroy_workqueue(td->workqueue); |
1117 | err_wq: | 1085 | err_wq: |
@@ -1140,9 +1108,11 @@ static void __exit taal_remove(struct omap_dss_device *dssdev) | |||
1140 | } | 1108 | } |
1141 | 1109 | ||
1142 | bldev = td->bldev; | 1110 | bldev = td->bldev; |
1143 | bldev->props.power = FB_BLANK_POWERDOWN; | 1111 | if (bldev != NULL) { |
1144 | taal_bl_update_status(bldev); | 1112 | bldev->props.power = FB_BLANK_POWERDOWN; |
1145 | backlight_device_unregister(bldev); | 1113 | taal_bl_update_status(bldev); |
1114 | backlight_device_unregister(bldev); | ||
1115 | } | ||
1146 | 1116 | ||
1147 | taal_cancel_ulps_work(dssdev); | 1117 | taal_cancel_ulps_work(dssdev); |
1148 | taal_cancel_esd_work(dssdev); | 1118 | taal_cancel_esd_work(dssdev); |
@@ -1195,7 +1165,8 @@ static int taal_power_on(struct omap_dss_device *dssdev) | |||
1195 | if (r) | 1165 | if (r) |
1196 | goto err; | 1166 | goto err; |
1197 | 1167 | ||
1198 | r = taal_dcs_write_1(td, DCS_PIXEL_FORMAT, 0x7); /* 24bit/pixel */ | 1168 | r = taal_dcs_write_1(td, MIPI_DCS_SET_PIXEL_FORMAT, |
1169 | MIPI_DCS_PIXEL_FMT_24BIT); | ||
1199 | if (r) | 1170 | if (r) |
1200 | goto err; | 1171 | goto err; |
1201 | 1172 | ||
@@ -1209,7 +1180,7 @@ static int taal_power_on(struct omap_dss_device *dssdev) | |||
1209 | goto err; | 1180 | goto err; |
1210 | } | 1181 | } |
1211 | 1182 | ||
1212 | r = taal_dcs_write_0(td, DCS_DISPLAY_ON); | 1183 | r = taal_dcs_write_0(td, MIPI_DCS_SET_DISPLAY_ON); |
1213 | if (r) | 1184 | if (r) |
1214 | goto err; | 1185 | goto err; |
1215 | 1186 | ||
@@ -1246,7 +1217,7 @@ static void taal_power_off(struct omap_dss_device *dssdev) | |||
1246 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); | 1217 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); |
1247 | int r; | 1218 | int r; |
1248 | 1219 | ||
1249 | r = taal_dcs_write_0(td, DCS_DISPLAY_OFF); | 1220 | r = taal_dcs_write_0(td, MIPI_DCS_SET_DISPLAY_OFF); |
1250 | if (!r) | 1221 | if (!r) |
1251 | r = taal_sleep_in(td); | 1222 | r = taal_sleep_in(td); |
1252 | 1223 | ||
@@ -1529,9 +1500,9 @@ static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable) | |||
1529 | int r; | 1500 | int r; |
1530 | 1501 | ||
1531 | if (enable) | 1502 | if (enable) |
1532 | r = taal_dcs_write_1(td, DCS_TEAR_ON, 0); | 1503 | r = taal_dcs_write_1(td, MIPI_DCS_SET_TEAR_ON, 0); |
1533 | else | 1504 | else |
1534 | r = taal_dcs_write_0(td, DCS_TEAR_OFF); | 1505 | r = taal_dcs_write_0(td, MIPI_DCS_SET_TEAR_OFF); |
1535 | 1506 | ||
1536 | if (!panel_data->use_ext_te) | 1507 | if (!panel_data->use_ext_te) |
1537 | omapdss_dsi_enable_te(dssdev, enable); | 1508 | omapdss_dsi_enable_te(dssdev, enable); |
@@ -1851,7 +1822,7 @@ static void taal_esd_work(struct work_struct *work) | |||
1851 | goto err; | 1822 | goto err; |
1852 | } | 1823 | } |
1853 | 1824 | ||
1854 | r = taal_dcs_read_1(td, DCS_RDDSDR, &state1); | 1825 | r = taal_dcs_read_1(td, MIPI_DCS_GET_DIAGNOSTIC_RESULT, &state1); |
1855 | if (r) { | 1826 | if (r) { |
1856 | dev_err(&dssdev->dev, "failed to read Taal status\n"); | 1827 | dev_err(&dssdev->dev, "failed to read Taal status\n"); |
1857 | goto err; | 1828 | goto err; |
@@ -1864,7 +1835,7 @@ static void taal_esd_work(struct work_struct *work) | |||
1864 | goto err; | 1835 | goto err; |
1865 | } | 1836 | } |
1866 | 1837 | ||
1867 | r = taal_dcs_read_1(td, DCS_RDDSDR, &state2); | 1838 | r = taal_dcs_read_1(td, MIPI_DCS_GET_DIAGNOSTIC_RESULT, &state2); |
1868 | if (r) { | 1839 | if (r) { |
1869 | dev_err(&dssdev->dev, "failed to read Taal status\n"); | 1840 | dev_err(&dssdev->dev, "failed to read Taal status\n"); |
1870 | goto err; | 1841 | goto err; |
@@ -1880,7 +1851,7 @@ static void taal_esd_work(struct work_struct *work) | |||
1880 | /* Self-diagnostics result is also shown on TE GPIO line. We need | 1851 | /* Self-diagnostics result is also shown on TE GPIO line. We need |
1881 | * to re-enable TE after self diagnostics */ | 1852 | * to re-enable TE after self diagnostics */ |
1882 | if (td->te_enabled && panel_data->use_ext_te) { | 1853 | if (td->te_enabled && panel_data->use_ext_te) { |
1883 | r = taal_dcs_write_1(td, DCS_TEAR_ON, 0); | 1854 | r = taal_dcs_write_1(td, MIPI_DCS_SET_TEAR_ON, 0); |
1884 | if (r) | 1855 | if (r) |
1885 | goto err; | 1856 | goto err; |
1886 | } | 1857 | } |
diff --git a/drivers/video/omap2/dss/Kconfig b/drivers/video/omap2/dss/Kconfig index 0d12524db14b..7be7c06a249e 100644 --- a/drivers/video/omap2/dss/Kconfig +++ b/drivers/video/omap2/dss/Kconfig | |||
@@ -1,5 +1,5 @@ | |||
1 | menuconfig OMAP2_DSS | 1 | menuconfig OMAP2_DSS |
2 | tristate "OMAP2+ Display Subsystem support (EXPERIMENTAL)" | 2 | tristate "OMAP2+ Display Subsystem support" |
3 | depends on ARCH_OMAP2PLUS | 3 | depends on ARCH_OMAP2PLUS |
4 | help | 4 | help |
5 | OMAP2+ Display Subsystem support. | 5 | OMAP2+ Display Subsystem support. |
diff --git a/drivers/video/omap2/dss/Makefile b/drivers/video/omap2/dss/Makefile index 10d9d3bb3e24..bd34ac5b2026 100644 --- a/drivers/video/omap2/dss/Makefile +++ b/drivers/video/omap2/dss/Makefile | |||
@@ -6,4 +6,4 @@ omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o | |||
6 | omapdss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o | 6 | omapdss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o |
7 | omapdss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o | 7 | omapdss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o |
8 | omapdss-$(CONFIG_OMAP4_DSS_HDMI) += hdmi.o \ | 8 | omapdss-$(CONFIG_OMAP4_DSS_HDMI) += hdmi.o \ |
9 | hdmi_omap4_panel.o | 9 | hdmi_panel.o ti_hdmi_4xxx_ip.o |
diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c index 76821fefce9a..86ec12e16c7c 100644 --- a/drivers/video/omap2/dss/core.c +++ b/drivers/video/omap2/dss/core.c | |||
@@ -145,6 +145,10 @@ static int dss_initialize_debugfs(void) | |||
145 | debugfs_create_file("venc", S_IRUGO, dss_debugfs_dir, | 145 | debugfs_create_file("venc", S_IRUGO, dss_debugfs_dir, |
146 | &venc_dump_regs, &dss_debug_fops); | 146 | &venc_dump_regs, &dss_debug_fops); |
147 | #endif | 147 | #endif |
148 | #ifdef CONFIG_OMAP4_DSS_HDMI | ||
149 | debugfs_create_file("hdmi", S_IRUGO, dss_debugfs_dir, | ||
150 | &hdmi_dump_regs, &dss_debug_fops); | ||
151 | #endif | ||
148 | return 0; | 152 | return 0; |
149 | } | 153 | } |
150 | 154 | ||
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index 0f3961a1ce26..6892cfd2e3b7 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c | |||
@@ -106,7 +106,7 @@ static struct { | |||
106 | int irq; | 106 | int irq; |
107 | struct clk *dss_clk; | 107 | struct clk *dss_clk; |
108 | 108 | ||
109 | u32 fifo_size[3]; | 109 | u32 fifo_size[MAX_DSS_OVERLAYS]; |
110 | 110 | ||
111 | spinlock_t irq_lock; | 111 | spinlock_t irq_lock; |
112 | u32 irq_error_mask; | 112 | u32 irq_error_mask; |
@@ -171,172 +171,98 @@ static int dispc_get_ctx_loss_count(void) | |||
171 | 171 | ||
172 | static void dispc_save_context(void) | 172 | static void dispc_save_context(void) |
173 | { | 173 | { |
174 | int i; | 174 | int i, j; |
175 | 175 | ||
176 | DSSDBG("dispc_save_context\n"); | 176 | DSSDBG("dispc_save_context\n"); |
177 | 177 | ||
178 | SR(IRQENABLE); | 178 | SR(IRQENABLE); |
179 | SR(CONTROL); | 179 | SR(CONTROL); |
180 | SR(CONFIG); | 180 | SR(CONFIG); |
181 | SR(DEFAULT_COLOR(OMAP_DSS_CHANNEL_LCD)); | ||
182 | SR(DEFAULT_COLOR(OMAP_DSS_CHANNEL_DIGIT)); | ||
183 | SR(TRANS_COLOR(OMAP_DSS_CHANNEL_LCD)); | ||
184 | SR(TRANS_COLOR(OMAP_DSS_CHANNEL_DIGIT)); | ||
185 | SR(LINE_NUMBER); | 181 | SR(LINE_NUMBER); |
186 | SR(TIMING_H(OMAP_DSS_CHANNEL_LCD)); | 182 | if (dss_has_feature(FEAT_ALPHA_FIXED_ZORDER) || |
187 | SR(TIMING_V(OMAP_DSS_CHANNEL_LCD)); | 183 | dss_has_feature(FEAT_ALPHA_FREE_ZORDER)) |
188 | SR(POL_FREQ(OMAP_DSS_CHANNEL_LCD)); | ||
189 | SR(DIVISORo(OMAP_DSS_CHANNEL_LCD)); | ||
190 | if (dss_has_feature(FEAT_GLOBAL_ALPHA)) | ||
191 | SR(GLOBAL_ALPHA); | 184 | SR(GLOBAL_ALPHA); |
192 | SR(SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT)); | ||
193 | SR(SIZE_MGR(OMAP_DSS_CHANNEL_LCD)); | ||
194 | if (dss_has_feature(FEAT_MGR_LCD2)) { | 185 | if (dss_has_feature(FEAT_MGR_LCD2)) { |
195 | SR(CONTROL2); | 186 | SR(CONTROL2); |
196 | SR(DEFAULT_COLOR(OMAP_DSS_CHANNEL_LCD2)); | ||
197 | SR(TRANS_COLOR(OMAP_DSS_CHANNEL_LCD2)); | ||
198 | SR(SIZE_MGR(OMAP_DSS_CHANNEL_LCD2)); | ||
199 | SR(TIMING_H(OMAP_DSS_CHANNEL_LCD2)); | ||
200 | SR(TIMING_V(OMAP_DSS_CHANNEL_LCD2)); | ||
201 | SR(POL_FREQ(OMAP_DSS_CHANNEL_LCD2)); | ||
202 | SR(DIVISORo(OMAP_DSS_CHANNEL_LCD2)); | ||
203 | SR(CONFIG2); | 187 | SR(CONFIG2); |
204 | } | 188 | } |
205 | 189 | ||
206 | SR(OVL_BA0(OMAP_DSS_GFX)); | 190 | for (i = 0; i < dss_feat_get_num_mgrs(); i++) { |
207 | SR(OVL_BA1(OMAP_DSS_GFX)); | 191 | SR(DEFAULT_COLOR(i)); |
208 | SR(OVL_POSITION(OMAP_DSS_GFX)); | 192 | SR(TRANS_COLOR(i)); |
209 | SR(OVL_SIZE(OMAP_DSS_GFX)); | 193 | SR(SIZE_MGR(i)); |
210 | SR(OVL_ATTRIBUTES(OMAP_DSS_GFX)); | 194 | if (i == OMAP_DSS_CHANNEL_DIGIT) |
211 | SR(OVL_FIFO_THRESHOLD(OMAP_DSS_GFX)); | 195 | continue; |
212 | SR(OVL_ROW_INC(OMAP_DSS_GFX)); | 196 | SR(TIMING_H(i)); |
213 | SR(OVL_PIXEL_INC(OMAP_DSS_GFX)); | 197 | SR(TIMING_V(i)); |
214 | SR(OVL_WINDOW_SKIP(OMAP_DSS_GFX)); | 198 | SR(POL_FREQ(i)); |
215 | SR(OVL_TABLE_BA(OMAP_DSS_GFX)); | 199 | SR(DIVISORo(i)); |
216 | 200 | ||
217 | SR(DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD)); | 201 | SR(DATA_CYCLE1(i)); |
218 | SR(DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD)); | 202 | SR(DATA_CYCLE2(i)); |
219 | SR(DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD)); | 203 | SR(DATA_CYCLE3(i)); |
220 | 204 | ||
221 | if (dss_has_feature(FEAT_CPR)) { | ||
222 | SR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD)); | ||
223 | SR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD)); | ||
224 | SR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD)); | ||
225 | } | ||
226 | if (dss_has_feature(FEAT_MGR_LCD2)) { | ||
227 | if (dss_has_feature(FEAT_CPR)) { | 205 | if (dss_has_feature(FEAT_CPR)) { |
228 | SR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD2)); | 206 | SR(CPR_COEF_R(i)); |
229 | SR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD2)); | 207 | SR(CPR_COEF_G(i)); |
230 | SR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD2)); | 208 | SR(CPR_COEF_B(i)); |
231 | } | 209 | } |
232 | |||
233 | SR(DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD2)); | ||
234 | SR(DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD2)); | ||
235 | SR(DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD2)); | ||
236 | } | 210 | } |
237 | 211 | ||
238 | if (dss_has_feature(FEAT_PRELOAD)) | 212 | for (i = 0; i < dss_feat_get_num_ovls(); i++) { |
239 | SR(OVL_PRELOAD(OMAP_DSS_GFX)); | 213 | SR(OVL_BA0(i)); |
240 | 214 | SR(OVL_BA1(i)); | |
241 | /* VID1 */ | 215 | SR(OVL_POSITION(i)); |
242 | SR(OVL_BA0(OMAP_DSS_VIDEO1)); | 216 | SR(OVL_SIZE(i)); |
243 | SR(OVL_BA1(OMAP_DSS_VIDEO1)); | 217 | SR(OVL_ATTRIBUTES(i)); |
244 | SR(OVL_POSITION(OMAP_DSS_VIDEO1)); | 218 | SR(OVL_FIFO_THRESHOLD(i)); |
245 | SR(OVL_SIZE(OMAP_DSS_VIDEO1)); | 219 | SR(OVL_ROW_INC(i)); |
246 | SR(OVL_ATTRIBUTES(OMAP_DSS_VIDEO1)); | 220 | SR(OVL_PIXEL_INC(i)); |
247 | SR(OVL_FIFO_THRESHOLD(OMAP_DSS_VIDEO1)); | 221 | if (dss_has_feature(FEAT_PRELOAD)) |
248 | SR(OVL_ROW_INC(OMAP_DSS_VIDEO1)); | 222 | SR(OVL_PRELOAD(i)); |
249 | SR(OVL_PIXEL_INC(OMAP_DSS_VIDEO1)); | 223 | if (i == OMAP_DSS_GFX) { |
250 | SR(OVL_FIR(OMAP_DSS_VIDEO1)); | 224 | SR(OVL_WINDOW_SKIP(i)); |
251 | SR(OVL_PICTURE_SIZE(OMAP_DSS_VIDEO1)); | 225 | SR(OVL_TABLE_BA(i)); |
252 | SR(OVL_ACCU0(OMAP_DSS_VIDEO1)); | 226 | continue; |
253 | SR(OVL_ACCU1(OMAP_DSS_VIDEO1)); | 227 | } |
254 | 228 | SR(OVL_FIR(i)); | |
255 | for (i = 0; i < 8; i++) | 229 | SR(OVL_PICTURE_SIZE(i)); |
256 | SR(OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, i)); | 230 | SR(OVL_ACCU0(i)); |
257 | 231 | SR(OVL_ACCU1(i)); | |
258 | for (i = 0; i < 8; i++) | ||
259 | SR(OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, i)); | ||
260 | |||
261 | for (i = 0; i < 5; i++) | ||
262 | SR(OVL_CONV_COEF(OMAP_DSS_VIDEO1, i)); | ||
263 | |||
264 | if (dss_has_feature(FEAT_FIR_COEF_V)) { | ||
265 | for (i = 0; i < 8; i++) | ||
266 | SR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, i)); | ||
267 | } | ||
268 | |||
269 | if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) { | ||
270 | SR(OVL_BA0_UV(OMAP_DSS_VIDEO1)); | ||
271 | SR(OVL_BA1_UV(OMAP_DSS_VIDEO1)); | ||
272 | SR(OVL_FIR2(OMAP_DSS_VIDEO1)); | ||
273 | SR(OVL_ACCU2_0(OMAP_DSS_VIDEO1)); | ||
274 | SR(OVL_ACCU2_1(OMAP_DSS_VIDEO1)); | ||
275 | |||
276 | for (i = 0; i < 8; i++) | ||
277 | SR(OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, i)); | ||
278 | |||
279 | for (i = 0; i < 8; i++) | ||
280 | SR(OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, i)); | ||
281 | |||
282 | for (i = 0; i < 8; i++) | ||
283 | SR(OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, i)); | ||
284 | } | ||
285 | if (dss_has_feature(FEAT_ATTR2)) | ||
286 | SR(OVL_ATTRIBUTES2(OMAP_DSS_VIDEO1)); | ||
287 | |||
288 | if (dss_has_feature(FEAT_PRELOAD)) | ||
289 | SR(OVL_PRELOAD(OMAP_DSS_VIDEO1)); | ||
290 | |||
291 | /* VID2 */ | ||
292 | SR(OVL_BA0(OMAP_DSS_VIDEO2)); | ||
293 | SR(OVL_BA1(OMAP_DSS_VIDEO2)); | ||
294 | SR(OVL_POSITION(OMAP_DSS_VIDEO2)); | ||
295 | SR(OVL_SIZE(OMAP_DSS_VIDEO2)); | ||
296 | SR(OVL_ATTRIBUTES(OMAP_DSS_VIDEO2)); | ||
297 | SR(OVL_FIFO_THRESHOLD(OMAP_DSS_VIDEO2)); | ||
298 | SR(OVL_ROW_INC(OMAP_DSS_VIDEO2)); | ||
299 | SR(OVL_PIXEL_INC(OMAP_DSS_VIDEO2)); | ||
300 | SR(OVL_FIR(OMAP_DSS_VIDEO2)); | ||
301 | SR(OVL_PICTURE_SIZE(OMAP_DSS_VIDEO2)); | ||
302 | SR(OVL_ACCU0(OMAP_DSS_VIDEO2)); | ||
303 | SR(OVL_ACCU1(OMAP_DSS_VIDEO2)); | ||
304 | 232 | ||
305 | for (i = 0; i < 8; i++) | 233 | for (j = 0; j < 8; j++) |
306 | SR(OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, i)); | 234 | SR(OVL_FIR_COEF_H(i, j)); |
307 | 235 | ||
308 | for (i = 0; i < 8; i++) | 236 | for (j = 0; j < 8; j++) |
309 | SR(OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, i)); | 237 | SR(OVL_FIR_COEF_HV(i, j)); |
310 | 238 | ||
311 | for (i = 0; i < 5; i++) | 239 | for (j = 0; j < 5; j++) |
312 | SR(OVL_CONV_COEF(OMAP_DSS_VIDEO2, i)); | 240 | SR(OVL_CONV_COEF(i, j)); |
313 | 241 | ||
314 | if (dss_has_feature(FEAT_FIR_COEF_V)) { | 242 | if (dss_has_feature(FEAT_FIR_COEF_V)) { |
315 | for (i = 0; i < 8; i++) | 243 | for (j = 0; j < 8; j++) |
316 | SR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, i)); | 244 | SR(OVL_FIR_COEF_V(i, j)); |
317 | } | 245 | } |
318 | 246 | ||
319 | if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) { | 247 | if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) { |
320 | SR(OVL_BA0_UV(OMAP_DSS_VIDEO2)); | 248 | SR(OVL_BA0_UV(i)); |
321 | SR(OVL_BA1_UV(OMAP_DSS_VIDEO2)); | 249 | SR(OVL_BA1_UV(i)); |
322 | SR(OVL_FIR2(OMAP_DSS_VIDEO2)); | 250 | SR(OVL_FIR2(i)); |
323 | SR(OVL_ACCU2_0(OMAP_DSS_VIDEO2)); | 251 | SR(OVL_ACCU2_0(i)); |
324 | SR(OVL_ACCU2_1(OMAP_DSS_VIDEO2)); | 252 | SR(OVL_ACCU2_1(i)); |
325 | 253 | ||
326 | for (i = 0; i < 8; i++) | 254 | for (j = 0; j < 8; j++) |
327 | SR(OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, i)); | 255 | SR(OVL_FIR_COEF_H2(i, j)); |
328 | 256 | ||
329 | for (i = 0; i < 8; i++) | 257 | for (j = 0; j < 8; j++) |
330 | SR(OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, i)); | 258 | SR(OVL_FIR_COEF_HV2(i, j)); |
331 | 259 | ||
332 | for (i = 0; i < 8; i++) | 260 | for (j = 0; j < 8; j++) |
333 | SR(OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, i)); | 261 | SR(OVL_FIR_COEF_V2(i, j)); |
262 | } | ||
263 | if (dss_has_feature(FEAT_ATTR2)) | ||
264 | SR(OVL_ATTRIBUTES2(i)); | ||
334 | } | 265 | } |
335 | if (dss_has_feature(FEAT_ATTR2)) | ||
336 | SR(OVL_ATTRIBUTES2(OMAP_DSS_VIDEO2)); | ||
337 | |||
338 | if (dss_has_feature(FEAT_PRELOAD)) | ||
339 | SR(OVL_PRELOAD(OMAP_DSS_VIDEO2)); | ||
340 | 266 | ||
341 | if (dss_has_feature(FEAT_CORE_CLK_DIV)) | 267 | if (dss_has_feature(FEAT_CORE_CLK_DIV)) |
342 | SR(DIVISOR); | 268 | SR(DIVISOR); |
@@ -349,7 +275,7 @@ static void dispc_save_context(void) | |||
349 | 275 | ||
350 | static void dispc_restore_context(void) | 276 | static void dispc_restore_context(void) |
351 | { | 277 | { |
352 | int i, ctx; | 278 | int i, j, ctx; |
353 | 279 | ||
354 | DSSDBG("dispc_restore_context\n"); | 280 | DSSDBG("dispc_restore_context\n"); |
355 | 281 | ||
@@ -367,165 +293,89 @@ static void dispc_restore_context(void) | |||
367 | /*RR(IRQENABLE);*/ | 293 | /*RR(IRQENABLE);*/ |
368 | /*RR(CONTROL);*/ | 294 | /*RR(CONTROL);*/ |
369 | RR(CONFIG); | 295 | RR(CONFIG); |
370 | RR(DEFAULT_COLOR(OMAP_DSS_CHANNEL_LCD)); | ||
371 | RR(DEFAULT_COLOR(OMAP_DSS_CHANNEL_DIGIT)); | ||
372 | RR(TRANS_COLOR(OMAP_DSS_CHANNEL_LCD)); | ||
373 | RR(TRANS_COLOR(OMAP_DSS_CHANNEL_DIGIT)); | ||
374 | RR(LINE_NUMBER); | 296 | RR(LINE_NUMBER); |
375 | RR(TIMING_H(OMAP_DSS_CHANNEL_LCD)); | 297 | if (dss_has_feature(FEAT_ALPHA_FIXED_ZORDER) || |
376 | RR(TIMING_V(OMAP_DSS_CHANNEL_LCD)); | 298 | dss_has_feature(FEAT_ALPHA_FREE_ZORDER)) |
377 | RR(POL_FREQ(OMAP_DSS_CHANNEL_LCD)); | ||
378 | RR(DIVISORo(OMAP_DSS_CHANNEL_LCD)); | ||
379 | if (dss_has_feature(FEAT_GLOBAL_ALPHA)) | ||
380 | RR(GLOBAL_ALPHA); | 299 | RR(GLOBAL_ALPHA); |
381 | RR(SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT)); | 300 | if (dss_has_feature(FEAT_MGR_LCD2)) |
382 | RR(SIZE_MGR(OMAP_DSS_CHANNEL_LCD)); | ||
383 | if (dss_has_feature(FEAT_MGR_LCD2)) { | ||
384 | RR(DEFAULT_COLOR(OMAP_DSS_CHANNEL_LCD2)); | ||
385 | RR(TRANS_COLOR(OMAP_DSS_CHANNEL_LCD2)); | ||
386 | RR(SIZE_MGR(OMAP_DSS_CHANNEL_LCD2)); | ||
387 | RR(TIMING_H(OMAP_DSS_CHANNEL_LCD2)); | ||
388 | RR(TIMING_V(OMAP_DSS_CHANNEL_LCD2)); | ||
389 | RR(POL_FREQ(OMAP_DSS_CHANNEL_LCD2)); | ||
390 | RR(DIVISORo(OMAP_DSS_CHANNEL_LCD2)); | ||
391 | RR(CONFIG2); | 301 | RR(CONFIG2); |
392 | } | ||
393 | |||
394 | RR(OVL_BA0(OMAP_DSS_GFX)); | ||
395 | RR(OVL_BA1(OMAP_DSS_GFX)); | ||
396 | RR(OVL_POSITION(OMAP_DSS_GFX)); | ||
397 | RR(OVL_SIZE(OMAP_DSS_GFX)); | ||
398 | RR(OVL_ATTRIBUTES(OMAP_DSS_GFX)); | ||
399 | RR(OVL_FIFO_THRESHOLD(OMAP_DSS_GFX)); | ||
400 | RR(OVL_ROW_INC(OMAP_DSS_GFX)); | ||
401 | RR(OVL_PIXEL_INC(OMAP_DSS_GFX)); | ||
402 | RR(OVL_WINDOW_SKIP(OMAP_DSS_GFX)); | ||
403 | RR(OVL_TABLE_BA(OMAP_DSS_GFX)); | ||
404 | |||
405 | 302 | ||
406 | RR(DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD)); | 303 | for (i = 0; i < dss_feat_get_num_mgrs(); i++) { |
407 | RR(DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD)); | 304 | RR(DEFAULT_COLOR(i)); |
408 | RR(DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD)); | 305 | RR(TRANS_COLOR(i)); |
306 | RR(SIZE_MGR(i)); | ||
307 | if (i == OMAP_DSS_CHANNEL_DIGIT) | ||
308 | continue; | ||
309 | RR(TIMING_H(i)); | ||
310 | RR(TIMING_V(i)); | ||
311 | RR(POL_FREQ(i)); | ||
312 | RR(DIVISORo(i)); | ||
409 | 313 | ||
410 | if (dss_has_feature(FEAT_CPR)) { | 314 | RR(DATA_CYCLE1(i)); |
411 | RR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD)); | 315 | RR(DATA_CYCLE2(i)); |
412 | RR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD)); | 316 | RR(DATA_CYCLE3(i)); |
413 | RR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD)); | ||
414 | } | ||
415 | if (dss_has_feature(FEAT_MGR_LCD2)) { | ||
416 | RR(DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD2)); | ||
417 | RR(DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD2)); | ||
418 | RR(DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD2)); | ||
419 | 317 | ||
420 | if (dss_has_feature(FEAT_CPR)) { | 318 | if (dss_has_feature(FEAT_CPR)) { |
421 | RR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD2)); | 319 | RR(CPR_COEF_R(i)); |
422 | RR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD2)); | 320 | RR(CPR_COEF_G(i)); |
423 | RR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD2)); | 321 | RR(CPR_COEF_B(i)); |
424 | } | 322 | } |
425 | } | 323 | } |
426 | 324 | ||
427 | if (dss_has_feature(FEAT_PRELOAD)) | 325 | for (i = 0; i < dss_feat_get_num_ovls(); i++) { |
428 | RR(OVL_PRELOAD(OMAP_DSS_GFX)); | 326 | RR(OVL_BA0(i)); |
429 | 327 | RR(OVL_BA1(i)); | |
430 | /* VID1 */ | 328 | RR(OVL_POSITION(i)); |
431 | RR(OVL_BA0(OMAP_DSS_VIDEO1)); | 329 | RR(OVL_SIZE(i)); |
432 | RR(OVL_BA1(OMAP_DSS_VIDEO1)); | 330 | RR(OVL_ATTRIBUTES(i)); |
433 | RR(OVL_POSITION(OMAP_DSS_VIDEO1)); | 331 | RR(OVL_FIFO_THRESHOLD(i)); |
434 | RR(OVL_SIZE(OMAP_DSS_VIDEO1)); | 332 | RR(OVL_ROW_INC(i)); |
435 | RR(OVL_ATTRIBUTES(OMAP_DSS_VIDEO1)); | 333 | RR(OVL_PIXEL_INC(i)); |
436 | RR(OVL_FIFO_THRESHOLD(OMAP_DSS_VIDEO1)); | 334 | if (dss_has_feature(FEAT_PRELOAD)) |
437 | RR(OVL_ROW_INC(OMAP_DSS_VIDEO1)); | 335 | RR(OVL_PRELOAD(i)); |
438 | RR(OVL_PIXEL_INC(OMAP_DSS_VIDEO1)); | 336 | if (i == OMAP_DSS_GFX) { |
439 | RR(OVL_FIR(OMAP_DSS_VIDEO1)); | 337 | RR(OVL_WINDOW_SKIP(i)); |
440 | RR(OVL_PICTURE_SIZE(OMAP_DSS_VIDEO1)); | 338 | RR(OVL_TABLE_BA(i)); |
441 | RR(OVL_ACCU0(OMAP_DSS_VIDEO1)); | 339 | continue; |
442 | RR(OVL_ACCU1(OMAP_DSS_VIDEO1)); | 340 | } |
443 | 341 | RR(OVL_FIR(i)); | |
444 | for (i = 0; i < 8; i++) | 342 | RR(OVL_PICTURE_SIZE(i)); |
445 | RR(OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, i)); | 343 | RR(OVL_ACCU0(i)); |
446 | 344 | RR(OVL_ACCU1(i)); | |
447 | for (i = 0; i < 8; i++) | ||
448 | RR(OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, i)); | ||
449 | |||
450 | for (i = 0; i < 5; i++) | ||
451 | RR(OVL_CONV_COEF(OMAP_DSS_VIDEO1, i)); | ||
452 | |||
453 | if (dss_has_feature(FEAT_FIR_COEF_V)) { | ||
454 | for (i = 0; i < 8; i++) | ||
455 | RR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, i)); | ||
456 | } | ||
457 | |||
458 | if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) { | ||
459 | RR(OVL_BA0_UV(OMAP_DSS_VIDEO1)); | ||
460 | RR(OVL_BA1_UV(OMAP_DSS_VIDEO1)); | ||
461 | RR(OVL_FIR2(OMAP_DSS_VIDEO1)); | ||
462 | RR(OVL_ACCU2_0(OMAP_DSS_VIDEO1)); | ||
463 | RR(OVL_ACCU2_1(OMAP_DSS_VIDEO1)); | ||
464 | |||
465 | for (i = 0; i < 8; i++) | ||
466 | RR(OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, i)); | ||
467 | |||
468 | for (i = 0; i < 8; i++) | ||
469 | RR(OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, i)); | ||
470 | |||
471 | for (i = 0; i < 8; i++) | ||
472 | RR(OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, i)); | ||
473 | } | ||
474 | if (dss_has_feature(FEAT_ATTR2)) | ||
475 | RR(OVL_ATTRIBUTES2(OMAP_DSS_VIDEO1)); | ||
476 | |||
477 | if (dss_has_feature(FEAT_PRELOAD)) | ||
478 | RR(OVL_PRELOAD(OMAP_DSS_VIDEO1)); | ||
479 | |||
480 | /* VID2 */ | ||
481 | RR(OVL_BA0(OMAP_DSS_VIDEO2)); | ||
482 | RR(OVL_BA1(OMAP_DSS_VIDEO2)); | ||
483 | RR(OVL_POSITION(OMAP_DSS_VIDEO2)); | ||
484 | RR(OVL_SIZE(OMAP_DSS_VIDEO2)); | ||
485 | RR(OVL_ATTRIBUTES(OMAP_DSS_VIDEO2)); | ||
486 | RR(OVL_FIFO_THRESHOLD(OMAP_DSS_VIDEO2)); | ||
487 | RR(OVL_ROW_INC(OMAP_DSS_VIDEO2)); | ||
488 | RR(OVL_PIXEL_INC(OMAP_DSS_VIDEO2)); | ||
489 | RR(OVL_FIR(OMAP_DSS_VIDEO2)); | ||
490 | RR(OVL_PICTURE_SIZE(OMAP_DSS_VIDEO2)); | ||
491 | RR(OVL_ACCU0(OMAP_DSS_VIDEO2)); | ||
492 | RR(OVL_ACCU1(OMAP_DSS_VIDEO2)); | ||
493 | 345 | ||
494 | for (i = 0; i < 8; i++) | 346 | for (j = 0; j < 8; j++) |
495 | RR(OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, i)); | 347 | RR(OVL_FIR_COEF_H(i, j)); |
496 | 348 | ||
497 | for (i = 0; i < 8; i++) | 349 | for (j = 0; j < 8; j++) |
498 | RR(OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, i)); | 350 | RR(OVL_FIR_COEF_HV(i, j)); |
499 | 351 | ||
500 | for (i = 0; i < 5; i++) | 352 | for (j = 0; j < 5; j++) |
501 | RR(OVL_CONV_COEF(OMAP_DSS_VIDEO2, i)); | 353 | RR(OVL_CONV_COEF(i, j)); |
502 | 354 | ||
503 | if (dss_has_feature(FEAT_FIR_COEF_V)) { | 355 | if (dss_has_feature(FEAT_FIR_COEF_V)) { |
504 | for (i = 0; i < 8; i++) | 356 | for (j = 0; j < 8; j++) |
505 | RR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, i)); | 357 | RR(OVL_FIR_COEF_V(i, j)); |
506 | } | 358 | } |
507 | 359 | ||
508 | if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) { | 360 | if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) { |
509 | RR(OVL_BA0_UV(OMAP_DSS_VIDEO2)); | 361 | RR(OVL_BA0_UV(i)); |
510 | RR(OVL_BA1_UV(OMAP_DSS_VIDEO2)); | 362 | RR(OVL_BA1_UV(i)); |
511 | RR(OVL_FIR2(OMAP_DSS_VIDEO2)); | 363 | RR(OVL_FIR2(i)); |
512 | RR(OVL_ACCU2_0(OMAP_DSS_VIDEO2)); | 364 | RR(OVL_ACCU2_0(i)); |
513 | RR(OVL_ACCU2_1(OMAP_DSS_VIDEO2)); | 365 | RR(OVL_ACCU2_1(i)); |
514 | 366 | ||
515 | for (i = 0; i < 8; i++) | 367 | for (j = 0; j < 8; j++) |
516 | RR(OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, i)); | 368 | RR(OVL_FIR_COEF_H2(i, j)); |
517 | 369 | ||
518 | for (i = 0; i < 8; i++) | 370 | for (j = 0; j < 8; j++) |
519 | RR(OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, i)); | 371 | RR(OVL_FIR_COEF_HV2(i, j)); |
520 | 372 | ||
521 | for (i = 0; i < 8; i++) | 373 | for (j = 0; j < 8; j++) |
522 | RR(OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, i)); | 374 | RR(OVL_FIR_COEF_V2(i, j)); |
375 | } | ||
376 | if (dss_has_feature(FEAT_ATTR2)) | ||
377 | RR(OVL_ATTRIBUTES2(i)); | ||
523 | } | 378 | } |
524 | if (dss_has_feature(FEAT_ATTR2)) | ||
525 | RR(OVL_ATTRIBUTES2(OMAP_DSS_VIDEO2)); | ||
526 | |||
527 | if (dss_has_feature(FEAT_PRELOAD)) | ||
528 | RR(OVL_PRELOAD(OMAP_DSS_VIDEO2)); | ||
529 | 379 | ||
530 | if (dss_has_feature(FEAT_CORE_CLK_DIV)) | 380 | if (dss_has_feature(FEAT_CORE_CLK_DIV)) |
531 | RR(DIVISOR); | 381 | RR(DIVISOR); |
@@ -570,13 +420,28 @@ void dispc_runtime_put(void) | |||
570 | WARN_ON(r < 0); | 420 | WARN_ON(r < 0); |
571 | } | 421 | } |
572 | 422 | ||
423 | static inline bool dispc_mgr_is_lcd(enum omap_channel channel) | ||
424 | { | ||
425 | if (channel == OMAP_DSS_CHANNEL_LCD || | ||
426 | channel == OMAP_DSS_CHANNEL_LCD2) | ||
427 | return true; | ||
428 | else | ||
429 | return false; | ||
430 | } | ||
431 | |||
432 | static struct omap_dss_device *dispc_mgr_get_device(enum omap_channel channel) | ||
433 | { | ||
434 | struct omap_overlay_manager *mgr = | ||
435 | omap_dss_get_overlay_manager(channel); | ||
573 | 436 | ||
574 | bool dispc_go_busy(enum omap_channel channel) | 437 | return mgr ? mgr->device : NULL; |
438 | } | ||
439 | |||
440 | bool dispc_mgr_go_busy(enum omap_channel channel) | ||
575 | { | 441 | { |
576 | int bit; | 442 | int bit; |
577 | 443 | ||
578 | if (channel == OMAP_DSS_CHANNEL_LCD || | 444 | if (dispc_mgr_is_lcd(channel)) |
579 | channel == OMAP_DSS_CHANNEL_LCD2) | ||
580 | bit = 5; /* GOLCD */ | 445 | bit = 5; /* GOLCD */ |
581 | else | 446 | else |
582 | bit = 6; /* GODIGIT */ | 447 | bit = 6; /* GODIGIT */ |
@@ -587,13 +452,12 @@ bool dispc_go_busy(enum omap_channel channel) | |||
587 | return REG_GET(DISPC_CONTROL, bit, bit) == 1; | 452 | return REG_GET(DISPC_CONTROL, bit, bit) == 1; |
588 | } | 453 | } |
589 | 454 | ||
590 | void dispc_go(enum omap_channel channel) | 455 | void dispc_mgr_go(enum omap_channel channel) |
591 | { | 456 | { |
592 | int bit; | 457 | int bit; |
593 | bool enable_bit, go_bit; | 458 | bool enable_bit, go_bit; |
594 | 459 | ||
595 | if (channel == OMAP_DSS_CHANNEL_LCD || | 460 | if (dispc_mgr_is_lcd(channel)) |
596 | channel == OMAP_DSS_CHANNEL_LCD2) | ||
597 | bit = 0; /* LCDENABLE */ | 461 | bit = 0; /* LCDENABLE */ |
598 | else | 462 | else |
599 | bit = 1; /* DIGITALENABLE */ | 463 | bit = 1; /* DIGITALENABLE */ |
@@ -607,8 +471,7 @@ void dispc_go(enum omap_channel channel) | |||
607 | if (!enable_bit) | 471 | if (!enable_bit) |
608 | return; | 472 | return; |
609 | 473 | ||
610 | if (channel == OMAP_DSS_CHANNEL_LCD || | 474 | if (dispc_mgr_is_lcd(channel)) |
611 | channel == OMAP_DSS_CHANNEL_LCD2) | ||
612 | bit = 5; /* GOLCD */ | 475 | bit = 5; /* GOLCD */ |
613 | else | 476 | else |
614 | bit = 6; /* GODIGIT */ | 477 | bit = 6; /* GODIGIT */ |
@@ -632,43 +495,44 @@ void dispc_go(enum omap_channel channel) | |||
632 | REG_FLD_MOD(DISPC_CONTROL, 1, bit, bit); | 495 | REG_FLD_MOD(DISPC_CONTROL, 1, bit, bit); |
633 | } | 496 | } |
634 | 497 | ||
635 | static void _dispc_write_firh_reg(enum omap_plane plane, int reg, u32 value) | 498 | static void dispc_ovl_write_firh_reg(enum omap_plane plane, int reg, u32 value) |
636 | { | 499 | { |
637 | dispc_write_reg(DISPC_OVL_FIR_COEF_H(plane, reg), value); | 500 | dispc_write_reg(DISPC_OVL_FIR_COEF_H(plane, reg), value); |
638 | } | 501 | } |
639 | 502 | ||
640 | static void _dispc_write_firhv_reg(enum omap_plane plane, int reg, u32 value) | 503 | static void dispc_ovl_write_firhv_reg(enum omap_plane plane, int reg, u32 value) |
641 | { | 504 | { |
642 | dispc_write_reg(DISPC_OVL_FIR_COEF_HV(plane, reg), value); | 505 | dispc_write_reg(DISPC_OVL_FIR_COEF_HV(plane, reg), value); |
643 | } | 506 | } |
644 | 507 | ||
645 | static void _dispc_write_firv_reg(enum omap_plane plane, int reg, u32 value) | 508 | static void dispc_ovl_write_firv_reg(enum omap_plane plane, int reg, u32 value) |
646 | { | 509 | { |
647 | dispc_write_reg(DISPC_OVL_FIR_COEF_V(plane, reg), value); | 510 | dispc_write_reg(DISPC_OVL_FIR_COEF_V(plane, reg), value); |
648 | } | 511 | } |
649 | 512 | ||
650 | static void _dispc_write_firh2_reg(enum omap_plane plane, int reg, u32 value) | 513 | static void dispc_ovl_write_firh2_reg(enum omap_plane plane, int reg, u32 value) |
651 | { | 514 | { |
652 | BUG_ON(plane == OMAP_DSS_GFX); | 515 | BUG_ON(plane == OMAP_DSS_GFX); |
653 | 516 | ||
654 | dispc_write_reg(DISPC_OVL_FIR_COEF_H2(plane, reg), value); | 517 | dispc_write_reg(DISPC_OVL_FIR_COEF_H2(plane, reg), value); |
655 | } | 518 | } |
656 | 519 | ||
657 | static void _dispc_write_firhv2_reg(enum omap_plane plane, int reg, u32 value) | 520 | static void dispc_ovl_write_firhv2_reg(enum omap_plane plane, int reg, |
521 | u32 value) | ||
658 | { | 522 | { |
659 | BUG_ON(plane == OMAP_DSS_GFX); | 523 | BUG_ON(plane == OMAP_DSS_GFX); |
660 | 524 | ||
661 | dispc_write_reg(DISPC_OVL_FIR_COEF_HV2(plane, reg), value); | 525 | dispc_write_reg(DISPC_OVL_FIR_COEF_HV2(plane, reg), value); |
662 | } | 526 | } |
663 | 527 | ||
664 | static void _dispc_write_firv2_reg(enum omap_plane plane, int reg, u32 value) | 528 | static void dispc_ovl_write_firv2_reg(enum omap_plane plane, int reg, u32 value) |
665 | { | 529 | { |
666 | BUG_ON(plane == OMAP_DSS_GFX); | 530 | BUG_ON(plane == OMAP_DSS_GFX); |
667 | 531 | ||
668 | dispc_write_reg(DISPC_OVL_FIR_COEF_V2(plane, reg), value); | 532 | dispc_write_reg(DISPC_OVL_FIR_COEF_V2(plane, reg), value); |
669 | } | 533 | } |
670 | 534 | ||
671 | static void _dispc_set_scale_coef(enum omap_plane plane, int hscaleup, | 535 | static void dispc_ovl_set_scale_coef(enum omap_plane plane, int hscaleup, |
672 | int vscaleup, int five_taps, | 536 | int vscaleup, int five_taps, |
673 | enum omap_color_component color_comp) | 537 | enum omap_color_component color_comp) |
674 | { | 538 | { |
@@ -769,11 +633,11 @@ static void _dispc_set_scale_coef(enum omap_plane plane, int hscaleup, | |||
769 | | FLD_VAL(v_coef[i].vc2, 31, 24); | 633 | | FLD_VAL(v_coef[i].vc2, 31, 24); |
770 | 634 | ||
771 | if (color_comp == DISPC_COLOR_COMPONENT_RGB_Y) { | 635 | if (color_comp == DISPC_COLOR_COMPONENT_RGB_Y) { |
772 | _dispc_write_firh_reg(plane, i, h); | 636 | dispc_ovl_write_firh_reg(plane, i, h); |
773 | _dispc_write_firhv_reg(plane, i, hv); | 637 | dispc_ovl_write_firhv_reg(plane, i, hv); |
774 | } else { | 638 | } else { |
775 | _dispc_write_firh2_reg(plane, i, h); | 639 | dispc_ovl_write_firh2_reg(plane, i, h); |
776 | _dispc_write_firhv2_reg(plane, i, hv); | 640 | dispc_ovl_write_firhv2_reg(plane, i, hv); |
777 | } | 641 | } |
778 | 642 | ||
779 | } | 643 | } |
@@ -784,15 +648,16 @@ static void _dispc_set_scale_coef(enum omap_plane plane, int hscaleup, | |||
784 | v = FLD_VAL(v_coef[i].vc00, 7, 0) | 648 | v = FLD_VAL(v_coef[i].vc00, 7, 0) |
785 | | FLD_VAL(v_coef[i].vc22, 15, 8); | 649 | | FLD_VAL(v_coef[i].vc22, 15, 8); |
786 | if (color_comp == DISPC_COLOR_COMPONENT_RGB_Y) | 650 | if (color_comp == DISPC_COLOR_COMPONENT_RGB_Y) |
787 | _dispc_write_firv_reg(plane, i, v); | 651 | dispc_ovl_write_firv_reg(plane, i, v); |
788 | else | 652 | else |
789 | _dispc_write_firv2_reg(plane, i, v); | 653 | dispc_ovl_write_firv2_reg(plane, i, v); |
790 | } | 654 | } |
791 | } | 655 | } |
792 | } | 656 | } |
793 | 657 | ||
794 | static void _dispc_setup_color_conv_coef(void) | 658 | static void _dispc_setup_color_conv_coef(void) |
795 | { | 659 | { |
660 | int i; | ||
796 | const struct color_conv_coef { | 661 | const struct color_conv_coef { |
797 | int ry, rcr, rcb, gy, gcr, gcb, by, bcr, bcb; | 662 | int ry, rcr, rcb, gy, gcr, gcb, by, bcr, bcb; |
798 | int full_range; | 663 | int full_range; |
@@ -806,65 +671,54 @@ static void _dispc_setup_color_conv_coef(void) | |||
806 | 671 | ||
807 | ct = &ctbl_bt601_5; | 672 | ct = &ctbl_bt601_5; |
808 | 673 | ||
809 | dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 0), | 674 | for (i = 1; i < dss_feat_get_num_ovls(); i++) { |
810 | CVAL(ct->rcr, ct->ry)); | 675 | dispc_write_reg(DISPC_OVL_CONV_COEF(i, 0), |
811 | dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 1), | 676 | CVAL(ct->rcr, ct->ry)); |
812 | CVAL(ct->gy, ct->rcb)); | 677 | dispc_write_reg(DISPC_OVL_CONV_COEF(i, 1), |
813 | dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 2), | 678 | CVAL(ct->gy, ct->rcb)); |
814 | CVAL(ct->gcb, ct->gcr)); | 679 | dispc_write_reg(DISPC_OVL_CONV_COEF(i, 2), |
815 | dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 3), | 680 | CVAL(ct->gcb, ct->gcr)); |
816 | CVAL(ct->bcr, ct->by)); | 681 | dispc_write_reg(DISPC_OVL_CONV_COEF(i, 3), |
817 | dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 4), | 682 | CVAL(ct->bcr, ct->by)); |
818 | CVAL(0, ct->bcb)); | 683 | dispc_write_reg(DISPC_OVL_CONV_COEF(i, 4), |
819 | 684 | CVAL(0, ct->bcb)); | |
820 | dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 0), | ||
821 | CVAL(ct->rcr, ct->ry)); | ||
822 | dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 1), | ||
823 | CVAL(ct->gy, ct->rcb)); | ||
824 | dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 2), | ||
825 | CVAL(ct->gcb, ct->gcr)); | ||
826 | dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 3), | ||
827 | CVAL(ct->bcr, ct->by)); | ||
828 | dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 4), | ||
829 | CVAL(0, ct->bcb)); | ||
830 | 685 | ||
831 | #undef CVAL | 686 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(i), ct->full_range, |
687 | 11, 11); | ||
688 | } | ||
832 | 689 | ||
833 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(OMAP_DSS_VIDEO1), | 690 | #undef CVAL |
834 | ct->full_range, 11, 11); | ||
835 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(OMAP_DSS_VIDEO2), | ||
836 | ct->full_range, 11, 11); | ||
837 | } | 691 | } |
838 | 692 | ||
839 | 693 | ||
840 | static void _dispc_set_plane_ba0(enum omap_plane plane, u32 paddr) | 694 | static void dispc_ovl_set_ba0(enum omap_plane plane, u32 paddr) |
841 | { | 695 | { |
842 | dispc_write_reg(DISPC_OVL_BA0(plane), paddr); | 696 | dispc_write_reg(DISPC_OVL_BA0(plane), paddr); |
843 | } | 697 | } |
844 | 698 | ||
845 | static void _dispc_set_plane_ba1(enum omap_plane plane, u32 paddr) | 699 | static void dispc_ovl_set_ba1(enum omap_plane plane, u32 paddr) |
846 | { | 700 | { |
847 | dispc_write_reg(DISPC_OVL_BA1(plane), paddr); | 701 | dispc_write_reg(DISPC_OVL_BA1(plane), paddr); |
848 | } | 702 | } |
849 | 703 | ||
850 | static void _dispc_set_plane_ba0_uv(enum omap_plane plane, u32 paddr) | 704 | static void dispc_ovl_set_ba0_uv(enum omap_plane plane, u32 paddr) |
851 | { | 705 | { |
852 | dispc_write_reg(DISPC_OVL_BA0_UV(plane), paddr); | 706 | dispc_write_reg(DISPC_OVL_BA0_UV(plane), paddr); |
853 | } | 707 | } |
854 | 708 | ||
855 | static void _dispc_set_plane_ba1_uv(enum omap_plane plane, u32 paddr) | 709 | static void dispc_ovl_set_ba1_uv(enum omap_plane plane, u32 paddr) |
856 | { | 710 | { |
857 | dispc_write_reg(DISPC_OVL_BA1_UV(plane), paddr); | 711 | dispc_write_reg(DISPC_OVL_BA1_UV(plane), paddr); |
858 | } | 712 | } |
859 | 713 | ||
860 | static void _dispc_set_plane_pos(enum omap_plane plane, int x, int y) | 714 | static void dispc_ovl_set_pos(enum omap_plane plane, int x, int y) |
861 | { | 715 | { |
862 | u32 val = FLD_VAL(y, 26, 16) | FLD_VAL(x, 10, 0); | 716 | u32 val = FLD_VAL(y, 26, 16) | FLD_VAL(x, 10, 0); |
863 | 717 | ||
864 | dispc_write_reg(DISPC_OVL_POSITION(plane), val); | 718 | dispc_write_reg(DISPC_OVL_POSITION(plane), val); |
865 | } | 719 | } |
866 | 720 | ||
867 | static void _dispc_set_pic_size(enum omap_plane plane, int width, int height) | 721 | static void dispc_ovl_set_pic_size(enum omap_plane plane, int width, int height) |
868 | { | 722 | { |
869 | u32 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0); | 723 | u32 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0); |
870 | 724 | ||
@@ -874,7 +728,7 @@ static void _dispc_set_pic_size(enum omap_plane plane, int width, int height) | |||
874 | dispc_write_reg(DISPC_OVL_PICTURE_SIZE(plane), val); | 728 | dispc_write_reg(DISPC_OVL_PICTURE_SIZE(plane), val); |
875 | } | 729 | } |
876 | 730 | ||
877 | static void _dispc_set_vid_size(enum omap_plane plane, int width, int height) | 731 | static void dispc_ovl_set_vid_size(enum omap_plane plane, int width, int height) |
878 | { | 732 | { |
879 | u32 val; | 733 | u32 val; |
880 | 734 | ||
@@ -885,44 +739,61 @@ static void _dispc_set_vid_size(enum omap_plane plane, int width, int height) | |||
885 | dispc_write_reg(DISPC_OVL_SIZE(plane), val); | 739 | dispc_write_reg(DISPC_OVL_SIZE(plane), val); |
886 | } | 740 | } |
887 | 741 | ||
888 | static void _dispc_set_pre_mult_alpha(enum omap_plane plane, bool enable) | 742 | static void dispc_ovl_set_zorder(enum omap_plane plane, u8 zorder) |
889 | { | 743 | { |
890 | if (!dss_has_feature(FEAT_PRE_MULT_ALPHA)) | 744 | struct omap_overlay *ovl = omap_dss_get_overlay(plane); |
745 | |||
746 | if ((ovl->caps & OMAP_DSS_OVL_CAP_ZORDER) == 0) | ||
891 | return; | 747 | return; |
892 | 748 | ||
893 | if (!dss_has_feature(FEAT_GLOBAL_ALPHA_VID1) && | 749 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), zorder, 27, 26); |
894 | plane == OMAP_DSS_VIDEO1) | 750 | } |
751 | |||
752 | static void dispc_ovl_enable_zorder_planes(void) | ||
753 | { | ||
754 | int i; | ||
755 | |||
756 | if (!dss_has_feature(FEAT_ALPHA_FREE_ZORDER)) | ||
895 | return; | 757 | return; |
896 | 758 | ||
897 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable ? 1 : 0, 28, 28); | 759 | for (i = 0; i < dss_feat_get_num_ovls(); i++) |
760 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(i), 1, 25, 25); | ||
898 | } | 761 | } |
899 | 762 | ||
900 | static void _dispc_setup_global_alpha(enum omap_plane plane, u8 global_alpha) | 763 | static void dispc_ovl_set_pre_mult_alpha(enum omap_plane plane, bool enable) |
901 | { | 764 | { |
902 | if (!dss_has_feature(FEAT_GLOBAL_ALPHA)) | 765 | struct omap_overlay *ovl = omap_dss_get_overlay(plane); |
766 | |||
767 | if ((ovl->caps & OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA) == 0) | ||
903 | return; | 768 | return; |
904 | 769 | ||
905 | if (!dss_has_feature(FEAT_GLOBAL_ALPHA_VID1) && | 770 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable ? 1 : 0, 28, 28); |
906 | plane == OMAP_DSS_VIDEO1) | 771 | } |
772 | |||
773 | static void dispc_ovl_setup_global_alpha(enum omap_plane plane, u8 global_alpha) | ||
774 | { | ||
775 | static const unsigned shifts[] = { 0, 8, 16, 24, }; | ||
776 | int shift; | ||
777 | struct omap_overlay *ovl = omap_dss_get_overlay(plane); | ||
778 | |||
779 | if ((ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) == 0) | ||
907 | return; | 780 | return; |
908 | 781 | ||
909 | if (plane == OMAP_DSS_GFX) | 782 | shift = shifts[plane]; |
910 | REG_FLD_MOD(DISPC_GLOBAL_ALPHA, global_alpha, 7, 0); | 783 | REG_FLD_MOD(DISPC_GLOBAL_ALPHA, global_alpha, shift + 7, shift); |
911 | else if (plane == OMAP_DSS_VIDEO2) | ||
912 | REG_FLD_MOD(DISPC_GLOBAL_ALPHA, global_alpha, 23, 16); | ||
913 | } | 784 | } |
914 | 785 | ||
915 | static void _dispc_set_pix_inc(enum omap_plane plane, s32 inc) | 786 | static void dispc_ovl_set_pix_inc(enum omap_plane plane, s32 inc) |
916 | { | 787 | { |
917 | dispc_write_reg(DISPC_OVL_PIXEL_INC(plane), inc); | 788 | dispc_write_reg(DISPC_OVL_PIXEL_INC(plane), inc); |
918 | } | 789 | } |
919 | 790 | ||
920 | static void _dispc_set_row_inc(enum omap_plane plane, s32 inc) | 791 | static void dispc_ovl_set_row_inc(enum omap_plane plane, s32 inc) |
921 | { | 792 | { |
922 | dispc_write_reg(DISPC_OVL_ROW_INC(plane), inc); | 793 | dispc_write_reg(DISPC_OVL_ROW_INC(plane), inc); |
923 | } | 794 | } |
924 | 795 | ||
925 | static void _dispc_set_color_mode(enum omap_plane plane, | 796 | static void dispc_ovl_set_color_mode(enum omap_plane plane, |
926 | enum omap_color_mode color_mode) | 797 | enum omap_color_mode color_mode) |
927 | { | 798 | { |
928 | u32 m = 0; | 799 | u32 m = 0; |
@@ -1003,7 +874,7 @@ static void _dispc_set_color_mode(enum omap_plane plane, | |||
1003 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), m, 4, 1); | 874 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), m, 4, 1); |
1004 | } | 875 | } |
1005 | 876 | ||
1006 | void dispc_set_channel_out(enum omap_plane plane, | 877 | static void dispc_ovl_set_channel_out(enum omap_plane plane, |
1007 | enum omap_channel channel) | 878 | enum omap_channel channel) |
1008 | { | 879 | { |
1009 | int shift; | 880 | int shift; |
@@ -1016,6 +887,7 @@ void dispc_set_channel_out(enum omap_plane plane, | |||
1016 | break; | 887 | break; |
1017 | case OMAP_DSS_VIDEO1: | 888 | case OMAP_DSS_VIDEO1: |
1018 | case OMAP_DSS_VIDEO2: | 889 | case OMAP_DSS_VIDEO2: |
890 | case OMAP_DSS_VIDEO3: | ||
1019 | shift = 16; | 891 | shift = 16; |
1020 | break; | 892 | break; |
1021 | default: | 893 | default: |
@@ -1050,24 +922,13 @@ void dispc_set_channel_out(enum omap_plane plane, | |||
1050 | dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val); | 922 | dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val); |
1051 | } | 923 | } |
1052 | 924 | ||
1053 | static void dispc_set_burst_size(enum omap_plane plane, | 925 | static void dispc_ovl_set_burst_size(enum omap_plane plane, |
1054 | enum omap_burst_size burst_size) | 926 | enum omap_burst_size burst_size) |
1055 | { | 927 | { |
928 | static const unsigned shifts[] = { 6, 14, 14, 14, }; | ||
1056 | int shift; | 929 | int shift; |
1057 | 930 | ||
1058 | switch (plane) { | 931 | shift = shifts[plane]; |
1059 | case OMAP_DSS_GFX: | ||
1060 | shift = 6; | ||
1061 | break; | ||
1062 | case OMAP_DSS_VIDEO1: | ||
1063 | case OMAP_DSS_VIDEO2: | ||
1064 | shift = 14; | ||
1065 | break; | ||
1066 | default: | ||
1067 | BUG(); | ||
1068 | return; | ||
1069 | } | ||
1070 | |||
1071 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), burst_size, shift + 1, shift); | 932 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), burst_size, shift + 1, shift); |
1072 | } | 933 | } |
1073 | 934 | ||
@@ -1078,10 +939,10 @@ static void dispc_configure_burst_sizes(void) | |||
1078 | 939 | ||
1079 | /* Configure burst size always to maximum size */ | 940 | /* Configure burst size always to maximum size */ |
1080 | for (i = 0; i < omap_dss_get_num_overlays(); ++i) | 941 | for (i = 0; i < omap_dss_get_num_overlays(); ++i) |
1081 | dispc_set_burst_size(i, burst_size); | 942 | dispc_ovl_set_burst_size(i, burst_size); |
1082 | } | 943 | } |
1083 | 944 | ||
1084 | u32 dispc_get_burst_size(enum omap_plane plane) | 945 | u32 dispc_ovl_get_burst_size(enum omap_plane plane) |
1085 | { | 946 | { |
1086 | unsigned unit = dss_feat_get_burst_size_unit(); | 947 | unsigned unit = dss_feat_get_burst_size_unit(); |
1087 | /* burst multiplier is always x8 (see dispc_configure_burst_sizes()) */ | 948 | /* burst multiplier is always x8 (see dispc_configure_burst_sizes()) */ |
@@ -1102,7 +963,7 @@ void dispc_enable_gamma_table(bool enable) | |||
1102 | REG_FLD_MOD(DISPC_CONFIG, enable, 9, 9); | 963 | REG_FLD_MOD(DISPC_CONFIG, enable, 9, 9); |
1103 | } | 964 | } |
1104 | 965 | ||
1105 | void dispc_enable_cpr(enum omap_channel channel, bool enable) | 966 | void dispc_mgr_enable_cpr(enum omap_channel channel, bool enable) |
1106 | { | 967 | { |
1107 | u16 reg; | 968 | u16 reg; |
1108 | 969 | ||
@@ -1116,12 +977,12 @@ void dispc_enable_cpr(enum omap_channel channel, bool enable) | |||
1116 | REG_FLD_MOD(reg, enable, 15, 15); | 977 | REG_FLD_MOD(reg, enable, 15, 15); |
1117 | } | 978 | } |
1118 | 979 | ||
1119 | void dispc_set_cpr_coef(enum omap_channel channel, | 980 | void dispc_mgr_set_cpr_coef(enum omap_channel channel, |
1120 | struct omap_dss_cpr_coefs *coefs) | 981 | struct omap_dss_cpr_coefs *coefs) |
1121 | { | 982 | { |
1122 | u32 coef_r, coef_g, coef_b; | 983 | u32 coef_r, coef_g, coef_b; |
1123 | 984 | ||
1124 | if (channel != OMAP_DSS_CHANNEL_LCD && channel != OMAP_DSS_CHANNEL_LCD2) | 985 | if (!dispc_mgr_is_lcd(channel)) |
1125 | return; | 986 | return; |
1126 | 987 | ||
1127 | coef_r = FLD_VAL(coefs->rr, 31, 22) | FLD_VAL(coefs->rg, 20, 11) | | 988 | coef_r = FLD_VAL(coefs->rr, 31, 22) | FLD_VAL(coefs->rg, 20, 11) | |
@@ -1136,7 +997,7 @@ void dispc_set_cpr_coef(enum omap_channel channel, | |||
1136 | dispc_write_reg(DISPC_CPR_COEF_B(channel), coef_b); | 997 | dispc_write_reg(DISPC_CPR_COEF_B(channel), coef_b); |
1137 | } | 998 | } |
1138 | 999 | ||
1139 | static void _dispc_set_vid_color_conv(enum omap_plane plane, bool enable) | 1000 | static void dispc_ovl_set_vid_color_conv(enum omap_plane plane, bool enable) |
1140 | { | 1001 | { |
1141 | u32 val; | 1002 | u32 val; |
1142 | 1003 | ||
@@ -1147,19 +1008,16 @@ static void _dispc_set_vid_color_conv(enum omap_plane plane, bool enable) | |||
1147 | dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val); | 1008 | dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val); |
1148 | } | 1009 | } |
1149 | 1010 | ||
1150 | void dispc_enable_replication(enum omap_plane plane, bool enable) | 1011 | static void dispc_ovl_enable_replication(enum omap_plane plane, bool enable) |
1151 | { | 1012 | { |
1152 | int bit; | 1013 | static const unsigned shifts[] = { 5, 10, 10, 10 }; |
1153 | 1014 | int shift; | |
1154 | if (plane == OMAP_DSS_GFX) | ||
1155 | bit = 5; | ||
1156 | else | ||
1157 | bit = 10; | ||
1158 | 1015 | ||
1159 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable, bit, bit); | 1016 | shift = shifts[plane]; |
1017 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable, shift, shift); | ||
1160 | } | 1018 | } |
1161 | 1019 | ||
1162 | void dispc_set_lcd_size(enum omap_channel channel, u16 width, u16 height) | 1020 | void dispc_mgr_set_lcd_size(enum omap_channel channel, u16 width, u16 height) |
1163 | { | 1021 | { |
1164 | u32 val; | 1022 | u32 val; |
1165 | BUG_ON((width > (1 << 11)) || (height > (1 << 11))); | 1023 | BUG_ON((width > (1 << 11)) || (height > (1 << 11))); |
@@ -1186,19 +1044,20 @@ static void dispc_read_plane_fifo_sizes(void) | |||
1186 | 1044 | ||
1187 | dss_feat_get_reg_field(FEAT_REG_FIFOSIZE, &start, &end); | 1045 | dss_feat_get_reg_field(FEAT_REG_FIFOSIZE, &start, &end); |
1188 | 1046 | ||
1189 | for (plane = 0; plane < ARRAY_SIZE(dispc.fifo_size); ++plane) { | 1047 | for (plane = 0; plane < dss_feat_get_num_ovls(); ++plane) { |
1190 | size = REG_GET(DISPC_OVL_FIFO_SIZE_STATUS(plane), start, end); | 1048 | size = REG_GET(DISPC_OVL_FIFO_SIZE_STATUS(plane), start, end); |
1191 | size *= unit; | 1049 | size *= unit; |
1192 | dispc.fifo_size[plane] = size; | 1050 | dispc.fifo_size[plane] = size; |
1193 | } | 1051 | } |
1194 | } | 1052 | } |
1195 | 1053 | ||
1196 | u32 dispc_get_plane_fifo_size(enum omap_plane plane) | 1054 | u32 dispc_ovl_get_fifo_size(enum omap_plane plane) |
1197 | { | 1055 | { |
1198 | return dispc.fifo_size[plane]; | 1056 | return dispc.fifo_size[plane]; |
1199 | } | 1057 | } |
1200 | 1058 | ||
1201 | void dispc_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high) | 1059 | static void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low, |
1060 | u32 high) | ||
1202 | { | 1061 | { |
1203 | u8 hi_start, hi_end, lo_start, lo_end; | 1062 | u8 hi_start, hi_end, lo_start, lo_end; |
1204 | u32 unit; | 1063 | u32 unit; |
@@ -1233,7 +1092,7 @@ void dispc_enable_fifomerge(bool enable) | |||
1233 | REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 14, 14); | 1092 | REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 14, 14); |
1234 | } | 1093 | } |
1235 | 1094 | ||
1236 | static void _dispc_set_fir(enum omap_plane plane, | 1095 | static void dispc_ovl_set_fir(enum omap_plane plane, |
1237 | int hinc, int vinc, | 1096 | int hinc, int vinc, |
1238 | enum omap_color_component color_comp) | 1097 | enum omap_color_component color_comp) |
1239 | { | 1098 | { |
@@ -1256,7 +1115,7 @@ static void _dispc_set_fir(enum omap_plane plane, | |||
1256 | } | 1115 | } |
1257 | } | 1116 | } |
1258 | 1117 | ||
1259 | static void _dispc_set_vid_accu0(enum omap_plane plane, int haccu, int vaccu) | 1118 | static void dispc_ovl_set_vid_accu0(enum omap_plane plane, int haccu, int vaccu) |
1260 | { | 1119 | { |
1261 | u32 val; | 1120 | u32 val; |
1262 | u8 hor_start, hor_end, vert_start, vert_end; | 1121 | u8 hor_start, hor_end, vert_start, vert_end; |
@@ -1270,7 +1129,7 @@ static void _dispc_set_vid_accu0(enum omap_plane plane, int haccu, int vaccu) | |||
1270 | dispc_write_reg(DISPC_OVL_ACCU0(plane), val); | 1129 | dispc_write_reg(DISPC_OVL_ACCU0(plane), val); |
1271 | } | 1130 | } |
1272 | 1131 | ||
1273 | static void _dispc_set_vid_accu1(enum omap_plane plane, int haccu, int vaccu) | 1132 | static void dispc_ovl_set_vid_accu1(enum omap_plane plane, int haccu, int vaccu) |
1274 | { | 1133 | { |
1275 | u32 val; | 1134 | u32 val; |
1276 | u8 hor_start, hor_end, vert_start, vert_end; | 1135 | u8 hor_start, hor_end, vert_start, vert_end; |
@@ -1284,7 +1143,8 @@ static void _dispc_set_vid_accu1(enum omap_plane plane, int haccu, int vaccu) | |||
1284 | dispc_write_reg(DISPC_OVL_ACCU1(plane), val); | 1143 | dispc_write_reg(DISPC_OVL_ACCU1(plane), val); |
1285 | } | 1144 | } |
1286 | 1145 | ||
1287 | static void _dispc_set_vid_accu2_0(enum omap_plane plane, int haccu, int vaccu) | 1146 | static void dispc_ovl_set_vid_accu2_0(enum omap_plane plane, int haccu, |
1147 | int vaccu) | ||
1288 | { | 1148 | { |
1289 | u32 val; | 1149 | u32 val; |
1290 | 1150 | ||
@@ -1292,7 +1152,8 @@ static void _dispc_set_vid_accu2_0(enum omap_plane plane, int haccu, int vaccu) | |||
1292 | dispc_write_reg(DISPC_OVL_ACCU2_0(plane), val); | 1152 | dispc_write_reg(DISPC_OVL_ACCU2_0(plane), val); |
1293 | } | 1153 | } |
1294 | 1154 | ||
1295 | static void _dispc_set_vid_accu2_1(enum omap_plane plane, int haccu, int vaccu) | 1155 | static void dispc_ovl_set_vid_accu2_1(enum omap_plane plane, int haccu, |
1156 | int vaccu) | ||
1296 | { | 1157 | { |
1297 | u32 val; | 1158 | u32 val; |
1298 | 1159 | ||
@@ -1300,7 +1161,7 @@ static void _dispc_set_vid_accu2_1(enum omap_plane plane, int haccu, int vaccu) | |||
1300 | dispc_write_reg(DISPC_OVL_ACCU2_1(plane), val); | 1161 | dispc_write_reg(DISPC_OVL_ACCU2_1(plane), val); |
1301 | } | 1162 | } |
1302 | 1163 | ||
1303 | static void _dispc_set_scale_param(enum omap_plane plane, | 1164 | static void dispc_ovl_set_scale_param(enum omap_plane plane, |
1304 | u16 orig_width, u16 orig_height, | 1165 | u16 orig_width, u16 orig_height, |
1305 | u16 out_width, u16 out_height, | 1166 | u16 out_width, u16 out_height, |
1306 | bool five_taps, u8 rotation, | 1167 | bool five_taps, u8 rotation, |
@@ -1312,15 +1173,16 @@ static void _dispc_set_scale_param(enum omap_plane plane, | |||
1312 | hscaleup = orig_width <= out_width; | 1173 | hscaleup = orig_width <= out_width; |
1313 | vscaleup = orig_height <= out_height; | 1174 | vscaleup = orig_height <= out_height; |
1314 | 1175 | ||
1315 | _dispc_set_scale_coef(plane, hscaleup, vscaleup, five_taps, color_comp); | 1176 | dispc_ovl_set_scale_coef(plane, hscaleup, vscaleup, five_taps, |
1177 | color_comp); | ||
1316 | 1178 | ||
1317 | fir_hinc = 1024 * orig_width / out_width; | 1179 | fir_hinc = 1024 * orig_width / out_width; |
1318 | fir_vinc = 1024 * orig_height / out_height; | 1180 | fir_vinc = 1024 * orig_height / out_height; |
1319 | 1181 | ||
1320 | _dispc_set_fir(plane, fir_hinc, fir_vinc, color_comp); | 1182 | dispc_ovl_set_fir(plane, fir_hinc, fir_vinc, color_comp); |
1321 | } | 1183 | } |
1322 | 1184 | ||
1323 | static void _dispc_set_scaling_common(enum omap_plane plane, | 1185 | static void dispc_ovl_set_scaling_common(enum omap_plane plane, |
1324 | u16 orig_width, u16 orig_height, | 1186 | u16 orig_width, u16 orig_height, |
1325 | u16 out_width, u16 out_height, | 1187 | u16 out_width, u16 out_height, |
1326 | bool ilace, bool five_taps, | 1188 | bool ilace, bool five_taps, |
@@ -1331,7 +1193,7 @@ static void _dispc_set_scaling_common(enum omap_plane plane, | |||
1331 | int accu1 = 0; | 1193 | int accu1 = 0; |
1332 | u32 l; | 1194 | u32 l; |
1333 | 1195 | ||
1334 | _dispc_set_scale_param(plane, orig_width, orig_height, | 1196 | dispc_ovl_set_scale_param(plane, orig_width, orig_height, |
1335 | out_width, out_height, five_taps, | 1197 | out_width, out_height, five_taps, |
1336 | rotation, DISPC_COLOR_COMPONENT_RGB_Y); | 1198 | rotation, DISPC_COLOR_COMPONENT_RGB_Y); |
1337 | l = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane)); | 1199 | l = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane)); |
@@ -1370,11 +1232,11 @@ static void _dispc_set_scaling_common(enum omap_plane plane, | |||
1370 | } | 1232 | } |
1371 | } | 1233 | } |
1372 | 1234 | ||
1373 | _dispc_set_vid_accu0(plane, 0, accu0); | 1235 | dispc_ovl_set_vid_accu0(plane, 0, accu0); |
1374 | _dispc_set_vid_accu1(plane, 0, accu1); | 1236 | dispc_ovl_set_vid_accu1(plane, 0, accu1); |
1375 | } | 1237 | } |
1376 | 1238 | ||
1377 | static void _dispc_set_scaling_uv(enum omap_plane plane, | 1239 | static void dispc_ovl_set_scaling_uv(enum omap_plane plane, |
1378 | u16 orig_width, u16 orig_height, | 1240 | u16 orig_width, u16 orig_height, |
1379 | u16 out_width, u16 out_height, | 1241 | u16 out_width, u16 out_height, |
1380 | bool ilace, bool five_taps, | 1242 | bool ilace, bool five_taps, |
@@ -1422,7 +1284,7 @@ static void _dispc_set_scaling_uv(enum omap_plane plane, | |||
1422 | if (out_height != orig_height) | 1284 | if (out_height != orig_height) |
1423 | scale_y = true; | 1285 | scale_y = true; |
1424 | 1286 | ||
1425 | _dispc_set_scale_param(plane, orig_width, orig_height, | 1287 | dispc_ovl_set_scale_param(plane, orig_width, orig_height, |
1426 | out_width, out_height, five_taps, | 1288 | out_width, out_height, five_taps, |
1427 | rotation, DISPC_COLOR_COMPONENT_UV); | 1289 | rotation, DISPC_COLOR_COMPONENT_UV); |
1428 | 1290 | ||
@@ -1433,11 +1295,11 @@ static void _dispc_set_scaling_uv(enum omap_plane plane, | |||
1433 | /* set V scaling */ | 1295 | /* set V scaling */ |
1434 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), scale_y ? 1 : 0, 6, 6); | 1296 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), scale_y ? 1 : 0, 6, 6); |
1435 | 1297 | ||
1436 | _dispc_set_vid_accu2_0(plane, 0x80, 0); | 1298 | dispc_ovl_set_vid_accu2_0(plane, 0x80, 0); |
1437 | _dispc_set_vid_accu2_1(plane, 0x80, 0); | 1299 | dispc_ovl_set_vid_accu2_1(plane, 0x80, 0); |
1438 | } | 1300 | } |
1439 | 1301 | ||
1440 | static void _dispc_set_scaling(enum omap_plane plane, | 1302 | static void dispc_ovl_set_scaling(enum omap_plane plane, |
1441 | u16 orig_width, u16 orig_height, | 1303 | u16 orig_width, u16 orig_height, |
1442 | u16 out_width, u16 out_height, | 1304 | u16 out_width, u16 out_height, |
1443 | bool ilace, bool five_taps, | 1305 | bool ilace, bool five_taps, |
@@ -1446,14 +1308,14 @@ static void _dispc_set_scaling(enum omap_plane plane, | |||
1446 | { | 1308 | { |
1447 | BUG_ON(plane == OMAP_DSS_GFX); | 1309 | BUG_ON(plane == OMAP_DSS_GFX); |
1448 | 1310 | ||
1449 | _dispc_set_scaling_common(plane, | 1311 | dispc_ovl_set_scaling_common(plane, |
1450 | orig_width, orig_height, | 1312 | orig_width, orig_height, |
1451 | out_width, out_height, | 1313 | out_width, out_height, |
1452 | ilace, five_taps, | 1314 | ilace, five_taps, |
1453 | fieldmode, color_mode, | 1315 | fieldmode, color_mode, |
1454 | rotation); | 1316 | rotation); |
1455 | 1317 | ||
1456 | _dispc_set_scaling_uv(plane, | 1318 | dispc_ovl_set_scaling_uv(plane, |
1457 | orig_width, orig_height, | 1319 | orig_width, orig_height, |
1458 | out_width, out_height, | 1320 | out_width, out_height, |
1459 | ilace, five_taps, | 1321 | ilace, five_taps, |
@@ -1461,7 +1323,7 @@ static void _dispc_set_scaling(enum omap_plane plane, | |||
1461 | rotation); | 1323 | rotation); |
1462 | } | 1324 | } |
1463 | 1325 | ||
1464 | static void _dispc_set_rotation_attrs(enum omap_plane plane, u8 rotation, | 1326 | static void dispc_ovl_set_rotation_attrs(enum omap_plane plane, u8 rotation, |
1465 | bool mirroring, enum omap_color_mode color_mode) | 1327 | bool mirroring, enum omap_color_mode color_mode) |
1466 | { | 1328 | { |
1467 | bool row_repeat = false; | 1329 | bool row_repeat = false; |
@@ -1789,12 +1651,11 @@ static unsigned long calc_fclk_five_taps(enum omap_channel channel, u16 width, | |||
1789 | enum omap_color_mode color_mode) | 1651 | enum omap_color_mode color_mode) |
1790 | { | 1652 | { |
1791 | u32 fclk = 0; | 1653 | u32 fclk = 0; |
1792 | /* FIXME venc pclk? */ | 1654 | u64 tmp, pclk = dispc_mgr_pclk_rate(channel); |
1793 | u64 tmp, pclk = dispc_pclk_rate(channel); | ||
1794 | 1655 | ||
1795 | if (height > out_height) { | 1656 | if (height > out_height) { |
1796 | /* FIXME get real display PPL */ | 1657 | struct omap_dss_device *dssdev = dispc_mgr_get_device(channel); |
1797 | unsigned int ppl = 800; | 1658 | unsigned int ppl = dssdev->panel.timings.x_res; |
1798 | 1659 | ||
1799 | tmp = pclk * height * out_width; | 1660 | tmp = pclk * height * out_width; |
1800 | do_div(tmp, 2 * out_height * ppl); | 1661 | do_div(tmp, 2 * out_height * ppl); |
@@ -1846,114 +1707,120 @@ static unsigned long calc_fclk(enum omap_channel channel, u16 width, | |||
1846 | else | 1707 | else |
1847 | vf = 1; | 1708 | vf = 1; |
1848 | 1709 | ||
1849 | /* FIXME venc pclk? */ | 1710 | return dispc_mgr_pclk_rate(channel) * vf * hf; |
1850 | return dispc_pclk_rate(channel) * vf * hf; | ||
1851 | } | 1711 | } |
1852 | 1712 | ||
1853 | int dispc_setup_plane(enum omap_plane plane, | 1713 | static int dispc_ovl_calc_scaling(enum omap_plane plane, |
1854 | u32 paddr, u16 screen_width, | 1714 | enum omap_channel channel, u16 width, u16 height, |
1855 | u16 pos_x, u16 pos_y, | ||
1856 | u16 width, u16 height, | ||
1857 | u16 out_width, u16 out_height, | 1715 | u16 out_width, u16 out_height, |
1858 | enum omap_color_mode color_mode, | 1716 | enum omap_color_mode color_mode, bool *five_taps) |
1859 | bool ilace, | 1717 | { |
1860 | enum omap_dss_rotation_type rotation_type, | 1718 | struct omap_overlay *ovl = omap_dss_get_overlay(plane); |
1861 | u8 rotation, bool mirror, | 1719 | const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE); |
1862 | u8 global_alpha, u8 pre_mult_alpha, | 1720 | unsigned long fclk = 0; |
1863 | enum omap_channel channel, u32 puv_addr) | ||
1864 | { | ||
1865 | const int maxdownscale = cpu_is_omap34xx() ? 4 : 2; | ||
1866 | bool five_taps = 0; | ||
1867 | bool fieldmode = 0; | ||
1868 | int cconv = 0; | ||
1869 | unsigned offset0, offset1; | ||
1870 | s32 row_inc; | ||
1871 | s32 pix_inc; | ||
1872 | u16 frame_height = height; | ||
1873 | unsigned int field_offset = 0; | ||
1874 | 1721 | ||
1875 | DSSDBG("dispc_setup_plane %d, pa %x, sw %d, %d,%d, %dx%d -> " | 1722 | if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) { |
1876 | "%dx%d, ilace %d, cmode %x, rot %d, mir %d chan %d\n", | 1723 | if (width != out_width || height != out_height) |
1877 | plane, paddr, screen_width, pos_x, pos_y, | 1724 | return -EINVAL; |
1878 | width, height, | 1725 | else |
1879 | out_width, out_height, | 1726 | return 0; |
1880 | ilace, color_mode, | 1727 | } |
1881 | rotation, mirror, channel); | ||
1882 | 1728 | ||
1883 | if (paddr == 0) | 1729 | if (out_width < width / maxdownscale || |
1730 | out_width > width * 8) | ||
1884 | return -EINVAL; | 1731 | return -EINVAL; |
1885 | 1732 | ||
1886 | if (ilace && height == out_height) | 1733 | if (out_height < height / maxdownscale || |
1887 | fieldmode = 1; | 1734 | out_height > height * 8) |
1735 | return -EINVAL; | ||
1888 | 1736 | ||
1889 | if (ilace) { | 1737 | /* Must use 5-tap filter? */ |
1890 | if (fieldmode) | 1738 | *five_taps = height > out_height * 2; |
1891 | height /= 2; | ||
1892 | pos_y /= 2; | ||
1893 | out_height /= 2; | ||
1894 | 1739 | ||
1895 | DSSDBG("adjusting for ilace: height %d, pos_y %d, " | 1740 | if (!*five_taps) { |
1896 | "out_height %d\n", | 1741 | fclk = calc_fclk(channel, width, height, out_width, |
1897 | height, pos_y, out_height); | 1742 | out_height); |
1743 | |||
1744 | /* Try 5-tap filter if 3-tap fclk is too high */ | ||
1745 | if (cpu_is_omap34xx() && height > out_height && | ||
1746 | fclk > dispc_fclk_rate()) | ||
1747 | *five_taps = true; | ||
1898 | } | 1748 | } |
1899 | 1749 | ||
1900 | if (!dss_feat_color_mode_supported(plane, color_mode)) | 1750 | if (width > (2048 >> *five_taps)) { |
1751 | DSSERR("failed to set up scaling, fclk too low\n"); | ||
1901 | return -EINVAL; | 1752 | return -EINVAL; |
1753 | } | ||
1902 | 1754 | ||
1903 | if (plane == OMAP_DSS_GFX) { | 1755 | if (*five_taps) |
1904 | if (width != out_width || height != out_height) | 1756 | fclk = calc_fclk_five_taps(channel, width, height, |
1905 | return -EINVAL; | 1757 | out_width, out_height, color_mode); |
1906 | } else { | ||
1907 | /* video plane */ | ||
1908 | 1758 | ||
1909 | unsigned long fclk = 0; | 1759 | DSSDBG("required fclk rate = %lu Hz\n", fclk); |
1760 | DSSDBG("current fclk rate = %lu Hz\n", dispc_fclk_rate()); | ||
1910 | 1761 | ||
1911 | if (out_width < width / maxdownscale || | 1762 | if (!fclk || fclk > dispc_fclk_rate()) { |
1912 | out_width > width * 8) | 1763 | DSSERR("failed to set up scaling, " |
1913 | return -EINVAL; | 1764 | "required fclk rate = %lu Hz, " |
1765 | "current fclk rate = %lu Hz\n", | ||
1766 | fclk, dispc_fclk_rate()); | ||
1767 | return -EINVAL; | ||
1768 | } | ||
1914 | 1769 | ||
1915 | if (out_height < height / maxdownscale || | 1770 | return 0; |
1916 | out_height > height * 8) | 1771 | } |
1917 | return -EINVAL; | ||
1918 | 1772 | ||
1919 | if (color_mode == OMAP_DSS_COLOR_YUV2 || | 1773 | int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi, |
1920 | color_mode == OMAP_DSS_COLOR_UYVY || | 1774 | bool ilace, enum omap_channel channel, bool replication, |
1921 | color_mode == OMAP_DSS_COLOR_NV12) | 1775 | u32 fifo_low, u32 fifo_high) |
1922 | cconv = 1; | 1776 | { |
1777 | struct omap_overlay *ovl = omap_dss_get_overlay(plane); | ||
1778 | bool five_taps = false; | ||
1779 | bool fieldmode = 0; | ||
1780 | int r, cconv = 0; | ||
1781 | unsigned offset0, offset1; | ||
1782 | s32 row_inc; | ||
1783 | s32 pix_inc; | ||
1784 | u16 frame_height = oi->height; | ||
1785 | unsigned int field_offset = 0; | ||
1923 | 1786 | ||
1924 | /* Must use 5-tap filter? */ | 1787 | DSSDBG("dispc_ovl_setup %d, pa %x, pa_uv %x, sw %d, %d,%d, %dx%d -> " |
1925 | five_taps = height > out_height * 2; | 1788 | "%dx%d, cmode %x, rot %d, mir %d, ilace %d chan %d repl %d " |
1789 | "fifo_low %d fifo high %d\n", plane, oi->paddr, oi->p_uv_addr, | ||
1790 | oi->screen_width, oi->pos_x, oi->pos_y, oi->width, oi->height, | ||
1791 | oi->out_width, oi->out_height, oi->color_mode, oi->rotation, | ||
1792 | oi->mirror, ilace, channel, replication, fifo_low, fifo_high); | ||
1926 | 1793 | ||
1927 | if (!five_taps) { | 1794 | if (oi->paddr == 0) |
1928 | fclk = calc_fclk(channel, width, height, out_width, | 1795 | return -EINVAL; |
1929 | out_height); | ||
1930 | 1796 | ||
1931 | /* Try 5-tap filter if 3-tap fclk is too high */ | 1797 | if (ilace && oi->height == oi->out_height) |
1932 | if (cpu_is_omap34xx() && height > out_height && | 1798 | fieldmode = 1; |
1933 | fclk > dispc_fclk_rate()) | ||
1934 | five_taps = true; | ||
1935 | } | ||
1936 | 1799 | ||
1937 | if (width > (2048 >> five_taps)) { | 1800 | if (ilace) { |
1938 | DSSERR("failed to set up scaling, fclk too low\n"); | 1801 | if (fieldmode) |
1939 | return -EINVAL; | 1802 | oi->height /= 2; |
1940 | } | 1803 | oi->pos_y /= 2; |
1804 | oi->out_height /= 2; | ||
1941 | 1805 | ||
1942 | if (five_taps) | 1806 | DSSDBG("adjusting for ilace: height %d, pos_y %d, " |
1943 | fclk = calc_fclk_five_taps(channel, width, height, | 1807 | "out_height %d\n", |
1944 | out_width, out_height, color_mode); | 1808 | oi->height, oi->pos_y, oi->out_height); |
1809 | } | ||
1945 | 1810 | ||
1946 | DSSDBG("required fclk rate = %lu Hz\n", fclk); | 1811 | if (!dss_feat_color_mode_supported(plane, oi->color_mode)) |
1947 | DSSDBG("current fclk rate = %lu Hz\n", dispc_fclk_rate()); | 1812 | return -EINVAL; |
1948 | 1813 | ||
1949 | if (!fclk || fclk > dispc_fclk_rate()) { | 1814 | r = dispc_ovl_calc_scaling(plane, channel, oi->width, oi->height, |
1950 | DSSERR("failed to set up scaling, " | 1815 | oi->out_width, oi->out_height, oi->color_mode, |
1951 | "required fclk rate = %lu Hz, " | 1816 | &five_taps); |
1952 | "current fclk rate = %lu Hz\n", | 1817 | if (r) |
1953 | fclk, dispc_fclk_rate()); | 1818 | return r; |
1954 | return -EINVAL; | 1819 | |
1955 | } | 1820 | if (oi->color_mode == OMAP_DSS_COLOR_YUV2 || |
1956 | } | 1821 | oi->color_mode == OMAP_DSS_COLOR_UYVY || |
1822 | oi->color_mode == OMAP_DSS_COLOR_NV12) | ||
1823 | cconv = 1; | ||
1957 | 1824 | ||
1958 | if (ilace && !fieldmode) { | 1825 | if (ilace && !fieldmode) { |
1959 | /* | 1826 | /* |
@@ -1963,69 +1830,76 @@ int dispc_setup_plane(enum omap_plane plane, | |||
1963 | * so the integer part must be added to the base address of the | 1830 | * so the integer part must be added to the base address of the |
1964 | * bottom field. | 1831 | * bottom field. |
1965 | */ | 1832 | */ |
1966 | if (!height || height == out_height) | 1833 | if (!oi->height || oi->height == oi->out_height) |
1967 | field_offset = 0; | 1834 | field_offset = 0; |
1968 | else | 1835 | else |
1969 | field_offset = height / out_height / 2; | 1836 | field_offset = oi->height / oi->out_height / 2; |
1970 | } | 1837 | } |
1971 | 1838 | ||
1972 | /* Fields are independent but interleaved in memory. */ | 1839 | /* Fields are independent but interleaved in memory. */ |
1973 | if (fieldmode) | 1840 | if (fieldmode) |
1974 | field_offset = 1; | 1841 | field_offset = 1; |
1975 | 1842 | ||
1976 | if (rotation_type == OMAP_DSS_ROT_DMA) | 1843 | if (oi->rotation_type == OMAP_DSS_ROT_DMA) |
1977 | calc_dma_rotation_offset(rotation, mirror, | 1844 | calc_dma_rotation_offset(oi->rotation, oi->mirror, |
1978 | screen_width, width, frame_height, color_mode, | 1845 | oi->screen_width, oi->width, frame_height, |
1979 | fieldmode, field_offset, | 1846 | oi->color_mode, fieldmode, field_offset, |
1980 | &offset0, &offset1, &row_inc, &pix_inc); | 1847 | &offset0, &offset1, &row_inc, &pix_inc); |
1981 | else | 1848 | else |
1982 | calc_vrfb_rotation_offset(rotation, mirror, | 1849 | calc_vrfb_rotation_offset(oi->rotation, oi->mirror, |
1983 | screen_width, width, frame_height, color_mode, | 1850 | oi->screen_width, oi->width, frame_height, |
1984 | fieldmode, field_offset, | 1851 | oi->color_mode, fieldmode, field_offset, |
1985 | &offset0, &offset1, &row_inc, &pix_inc); | 1852 | &offset0, &offset1, &row_inc, &pix_inc); |
1986 | 1853 | ||
1987 | DSSDBG("offset0 %u, offset1 %u, row_inc %d, pix_inc %d\n", | 1854 | DSSDBG("offset0 %u, offset1 %u, row_inc %d, pix_inc %d\n", |
1988 | offset0, offset1, row_inc, pix_inc); | 1855 | offset0, offset1, row_inc, pix_inc); |
1989 | 1856 | ||
1990 | _dispc_set_color_mode(plane, color_mode); | 1857 | dispc_ovl_set_color_mode(plane, oi->color_mode); |
1991 | 1858 | ||
1992 | _dispc_set_plane_ba0(plane, paddr + offset0); | 1859 | dispc_ovl_set_ba0(plane, oi->paddr + offset0); |
1993 | _dispc_set_plane_ba1(plane, paddr + offset1); | 1860 | dispc_ovl_set_ba1(plane, oi->paddr + offset1); |
1994 | 1861 | ||
1995 | if (OMAP_DSS_COLOR_NV12 == color_mode) { | 1862 | if (OMAP_DSS_COLOR_NV12 == oi->color_mode) { |
1996 | _dispc_set_plane_ba0_uv(plane, puv_addr + offset0); | 1863 | dispc_ovl_set_ba0_uv(plane, oi->p_uv_addr + offset0); |
1997 | _dispc_set_plane_ba1_uv(plane, puv_addr + offset1); | 1864 | dispc_ovl_set_ba1_uv(plane, oi->p_uv_addr + offset1); |
1998 | } | 1865 | } |
1999 | 1866 | ||
2000 | 1867 | ||
2001 | _dispc_set_row_inc(plane, row_inc); | 1868 | dispc_ovl_set_row_inc(plane, row_inc); |
2002 | _dispc_set_pix_inc(plane, pix_inc); | 1869 | dispc_ovl_set_pix_inc(plane, pix_inc); |
2003 | 1870 | ||
2004 | DSSDBG("%d,%d %dx%d -> %dx%d\n", pos_x, pos_y, width, height, | 1871 | DSSDBG("%d,%d %dx%d -> %dx%d\n", oi->pos_x, oi->pos_y, oi->width, |
2005 | out_width, out_height); | 1872 | oi->height, oi->out_width, oi->out_height); |
2006 | 1873 | ||
2007 | _dispc_set_plane_pos(plane, pos_x, pos_y); | 1874 | dispc_ovl_set_pos(plane, oi->pos_x, oi->pos_y); |
2008 | 1875 | ||
2009 | _dispc_set_pic_size(plane, width, height); | 1876 | dispc_ovl_set_pic_size(plane, oi->width, oi->height); |
2010 | 1877 | ||
2011 | if (plane != OMAP_DSS_GFX) { | 1878 | if (ovl->caps & OMAP_DSS_OVL_CAP_SCALE) { |
2012 | _dispc_set_scaling(plane, width, height, | 1879 | dispc_ovl_set_scaling(plane, oi->width, oi->height, |
2013 | out_width, out_height, | 1880 | oi->out_width, oi->out_height, |
2014 | ilace, five_taps, fieldmode, | 1881 | ilace, five_taps, fieldmode, |
2015 | color_mode, rotation); | 1882 | oi->color_mode, oi->rotation); |
2016 | _dispc_set_vid_size(plane, out_width, out_height); | 1883 | dispc_ovl_set_vid_size(plane, oi->out_width, oi->out_height); |
2017 | _dispc_set_vid_color_conv(plane, cconv); | 1884 | dispc_ovl_set_vid_color_conv(plane, cconv); |
2018 | } | 1885 | } |
2019 | 1886 | ||
2020 | _dispc_set_rotation_attrs(plane, rotation, mirror, color_mode); | 1887 | dispc_ovl_set_rotation_attrs(plane, oi->rotation, oi->mirror, |
1888 | oi->color_mode); | ||
1889 | |||
1890 | dispc_ovl_set_zorder(plane, oi->zorder); | ||
1891 | dispc_ovl_set_pre_mult_alpha(plane, oi->pre_mult_alpha); | ||
1892 | dispc_ovl_setup_global_alpha(plane, oi->global_alpha); | ||
2021 | 1893 | ||
2022 | _dispc_set_pre_mult_alpha(plane, pre_mult_alpha); | 1894 | dispc_ovl_set_channel_out(plane, channel); |
2023 | _dispc_setup_global_alpha(plane, global_alpha); | 1895 | |
1896 | dispc_ovl_enable_replication(plane, replication); | ||
1897 | dispc_ovl_set_fifo_threshold(plane, fifo_low, fifo_high); | ||
2024 | 1898 | ||
2025 | return 0; | 1899 | return 0; |
2026 | } | 1900 | } |
2027 | 1901 | ||
2028 | int dispc_enable_plane(enum omap_plane plane, bool enable) | 1902 | int dispc_ovl_enable(enum omap_plane plane, bool enable) |
2029 | { | 1903 | { |
2030 | DSSDBG("dispc_enable_plane %d, %d\n", plane, enable); | 1904 | DSSDBG("dispc_enable_plane %d, %d\n", plane, enable); |
2031 | 1905 | ||
@@ -2048,7 +1922,7 @@ static void _enable_lcd_out(enum omap_channel channel, bool enable) | |||
2048 | REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 0, 0); | 1922 | REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 0, 0); |
2049 | } | 1923 | } |
2050 | 1924 | ||
2051 | static void dispc_enable_lcd_out(enum omap_channel channel, bool enable) | 1925 | static void dispc_mgr_enable_lcd_out(enum omap_channel channel, bool enable) |
2052 | { | 1926 | { |
2053 | struct completion frame_done_completion; | 1927 | struct completion frame_done_completion; |
2054 | bool is_on; | 1928 | bool is_on; |
@@ -2095,14 +1969,19 @@ static void _enable_digit_out(bool enable) | |||
2095 | REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 1, 1); | 1969 | REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 1, 1); |
2096 | } | 1970 | } |
2097 | 1971 | ||
2098 | static void dispc_enable_digit_out(bool enable) | 1972 | static void dispc_mgr_enable_digit_out(bool enable) |
2099 | { | 1973 | { |
2100 | struct completion frame_done_completion; | 1974 | struct completion frame_done_completion; |
2101 | int r; | 1975 | enum dss_hdmi_venc_clk_source_select src; |
1976 | int r, i; | ||
1977 | u32 irq_mask; | ||
1978 | int num_irqs; | ||
2102 | 1979 | ||
2103 | if (REG_GET(DISPC_CONTROL, 1, 1) == enable) | 1980 | if (REG_GET(DISPC_CONTROL, 1, 1) == enable) |
2104 | return; | 1981 | return; |
2105 | 1982 | ||
1983 | src = dss_get_hdmi_venc_clk_source(); | ||
1984 | |||
2106 | if (enable) { | 1985 | if (enable) { |
2107 | unsigned long flags; | 1986 | unsigned long flags; |
2108 | /* When we enable digit output, we'll get an extra digit | 1987 | /* When we enable digit output, we'll get an extra digit |
@@ -2119,43 +1998,47 @@ static void dispc_enable_digit_out(bool enable) | |||
2119 | * wait for the extra sync losts */ | 1998 | * wait for the extra sync losts */ |
2120 | init_completion(&frame_done_completion); | 1999 | init_completion(&frame_done_completion); |
2121 | 2000 | ||
2001 | if (src == DSS_HDMI_M_PCLK && enable == false) { | ||
2002 | irq_mask = DISPC_IRQ_FRAMEDONETV; | ||
2003 | num_irqs = 1; | ||
2004 | } else { | ||
2005 | irq_mask = DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD; | ||
2006 | /* XXX I understand from TRM that we should only wait for the | ||
2007 | * current field to complete. But it seems we have to wait for | ||
2008 | * both fields */ | ||
2009 | num_irqs = 2; | ||
2010 | } | ||
2011 | |||
2122 | r = omap_dispc_register_isr(dispc_disable_isr, &frame_done_completion, | 2012 | r = omap_dispc_register_isr(dispc_disable_isr, &frame_done_completion, |
2123 | DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD); | 2013 | irq_mask); |
2124 | if (r) | 2014 | if (r) |
2125 | DSSERR("failed to register EVSYNC isr\n"); | 2015 | DSSERR("failed to register %x isr\n", irq_mask); |
2126 | 2016 | ||
2127 | _enable_digit_out(enable); | 2017 | _enable_digit_out(enable); |
2128 | 2018 | ||
2129 | /* XXX I understand from TRM that we should only wait for the | 2019 | for (i = 0; i < num_irqs; ++i) { |
2130 | * current field to complete. But it seems we have to wait | 2020 | if (!wait_for_completion_timeout(&frame_done_completion, |
2131 | * for both fields */ | 2021 | msecs_to_jiffies(100))) |
2132 | if (!wait_for_completion_timeout(&frame_done_completion, | 2022 | DSSERR("timeout waiting for digit out to %s\n", |
2133 | msecs_to_jiffies(100))) | 2023 | enable ? "start" : "stop"); |
2134 | DSSERR("timeout waiting for EVSYNC\n"); | 2024 | } |
2135 | |||
2136 | if (!wait_for_completion_timeout(&frame_done_completion, | ||
2137 | msecs_to_jiffies(100))) | ||
2138 | DSSERR("timeout waiting for EVSYNC\n"); | ||
2139 | 2025 | ||
2140 | r = omap_dispc_unregister_isr(dispc_disable_isr, | 2026 | r = omap_dispc_unregister_isr(dispc_disable_isr, &frame_done_completion, |
2141 | &frame_done_completion, | 2027 | irq_mask); |
2142 | DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD); | ||
2143 | if (r) | 2028 | if (r) |
2144 | DSSERR("failed to unregister EVSYNC isr\n"); | 2029 | DSSERR("failed to unregister %x isr\n", irq_mask); |
2145 | 2030 | ||
2146 | if (enable) { | 2031 | if (enable) { |
2147 | unsigned long flags; | 2032 | unsigned long flags; |
2148 | spin_lock_irqsave(&dispc.irq_lock, flags); | 2033 | spin_lock_irqsave(&dispc.irq_lock, flags); |
2149 | dispc.irq_error_mask = DISPC_IRQ_MASK_ERROR; | 2034 | dispc.irq_error_mask |= DISPC_IRQ_SYNC_LOST_DIGIT; |
2150 | if (dss_has_feature(FEAT_MGR_LCD2)) | ||
2151 | dispc.irq_error_mask |= DISPC_IRQ_SYNC_LOST2; | ||
2152 | dispc_write_reg(DISPC_IRQSTATUS, DISPC_IRQ_SYNC_LOST_DIGIT); | 2035 | dispc_write_reg(DISPC_IRQSTATUS, DISPC_IRQ_SYNC_LOST_DIGIT); |
2153 | _omap_dispc_set_irqs(); | 2036 | _omap_dispc_set_irqs(); |
2154 | spin_unlock_irqrestore(&dispc.irq_lock, flags); | 2037 | spin_unlock_irqrestore(&dispc.irq_lock, flags); |
2155 | } | 2038 | } |
2156 | } | 2039 | } |
2157 | 2040 | ||
2158 | bool dispc_is_channel_enabled(enum omap_channel channel) | 2041 | bool dispc_mgr_is_enabled(enum omap_channel channel) |
2159 | { | 2042 | { |
2160 | if (channel == OMAP_DSS_CHANNEL_LCD) | 2043 | if (channel == OMAP_DSS_CHANNEL_LCD) |
2161 | return !!REG_GET(DISPC_CONTROL, 0, 0); | 2044 | return !!REG_GET(DISPC_CONTROL, 0, 0); |
@@ -2167,13 +2050,12 @@ bool dispc_is_channel_enabled(enum omap_channel channel) | |||
2167 | BUG(); | 2050 | BUG(); |
2168 | } | 2051 | } |
2169 | 2052 | ||
2170 | void dispc_enable_channel(enum omap_channel channel, bool enable) | 2053 | void dispc_mgr_enable(enum omap_channel channel, bool enable) |
2171 | { | 2054 | { |
2172 | if (channel == OMAP_DSS_CHANNEL_LCD || | 2055 | if (dispc_mgr_is_lcd(channel)) |
2173 | channel == OMAP_DSS_CHANNEL_LCD2) | 2056 | dispc_mgr_enable_lcd_out(channel, enable); |
2174 | dispc_enable_lcd_out(channel, enable); | ||
2175 | else if (channel == OMAP_DSS_CHANNEL_DIGIT) | 2057 | else if (channel == OMAP_DSS_CHANNEL_DIGIT) |
2176 | dispc_enable_digit_out(enable); | 2058 | dispc_mgr_enable_digit_out(enable); |
2177 | else | 2059 | else |
2178 | BUG(); | 2060 | BUG(); |
2179 | } | 2061 | } |
@@ -2202,7 +2084,7 @@ void dispc_pck_free_enable(bool enable) | |||
2202 | REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 27, 27); | 2084 | REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 27, 27); |
2203 | } | 2085 | } |
2204 | 2086 | ||
2205 | void dispc_enable_fifohandcheck(enum omap_channel channel, bool enable) | 2087 | void dispc_mgr_enable_fifohandcheck(enum omap_channel channel, bool enable) |
2206 | { | 2088 | { |
2207 | if (channel == OMAP_DSS_CHANNEL_LCD2) | 2089 | if (channel == OMAP_DSS_CHANNEL_LCD2) |
2208 | REG_FLD_MOD(DISPC_CONFIG2, enable ? 1 : 0, 16, 16); | 2090 | REG_FLD_MOD(DISPC_CONFIG2, enable ? 1 : 0, 16, 16); |
@@ -2211,7 +2093,7 @@ void dispc_enable_fifohandcheck(enum omap_channel channel, bool enable) | |||
2211 | } | 2093 | } |
2212 | 2094 | ||
2213 | 2095 | ||
2214 | void dispc_set_lcd_display_type(enum omap_channel channel, | 2096 | void dispc_mgr_set_lcd_display_type(enum omap_channel channel, |
2215 | enum omap_lcd_display_type type) | 2097 | enum omap_lcd_display_type type) |
2216 | { | 2098 | { |
2217 | int mode; | 2099 | int mode; |
@@ -2242,12 +2124,12 @@ void dispc_set_loadmode(enum omap_dss_load_mode mode) | |||
2242 | } | 2124 | } |
2243 | 2125 | ||
2244 | 2126 | ||
2245 | void dispc_set_default_color(enum omap_channel channel, u32 color) | 2127 | void dispc_mgr_set_default_color(enum omap_channel channel, u32 color) |
2246 | { | 2128 | { |
2247 | dispc_write_reg(DISPC_DEFAULT_COLOR(channel), color); | 2129 | dispc_write_reg(DISPC_DEFAULT_COLOR(channel), color); |
2248 | } | 2130 | } |
2249 | 2131 | ||
2250 | u32 dispc_get_default_color(enum omap_channel channel) | 2132 | u32 dispc_mgr_get_default_color(enum omap_channel channel) |
2251 | { | 2133 | { |
2252 | u32 l; | 2134 | u32 l; |
2253 | 2135 | ||
@@ -2260,7 +2142,7 @@ u32 dispc_get_default_color(enum omap_channel channel) | |||
2260 | return l; | 2142 | return l; |
2261 | } | 2143 | } |
2262 | 2144 | ||
2263 | void dispc_set_trans_key(enum omap_channel ch, | 2145 | void dispc_mgr_set_trans_key(enum omap_channel ch, |
2264 | enum omap_dss_trans_key_type type, | 2146 | enum omap_dss_trans_key_type type, |
2265 | u32 trans_key) | 2147 | u32 trans_key) |
2266 | { | 2148 | { |
@@ -2274,7 +2156,7 @@ void dispc_set_trans_key(enum omap_channel ch, | |||
2274 | dispc_write_reg(DISPC_TRANS_COLOR(ch), trans_key); | 2156 | dispc_write_reg(DISPC_TRANS_COLOR(ch), trans_key); |
2275 | } | 2157 | } |
2276 | 2158 | ||
2277 | void dispc_get_trans_key(enum omap_channel ch, | 2159 | void dispc_mgr_get_trans_key(enum omap_channel ch, |
2278 | enum omap_dss_trans_key_type *type, | 2160 | enum omap_dss_trans_key_type *type, |
2279 | u32 *trans_key) | 2161 | u32 *trans_key) |
2280 | { | 2162 | { |
@@ -2293,7 +2175,7 @@ void dispc_get_trans_key(enum omap_channel ch, | |||
2293 | *trans_key = dispc_read_reg(DISPC_TRANS_COLOR(ch)); | 2175 | *trans_key = dispc_read_reg(DISPC_TRANS_COLOR(ch)); |
2294 | } | 2176 | } |
2295 | 2177 | ||
2296 | void dispc_enable_trans_key(enum omap_channel ch, bool enable) | 2178 | void dispc_mgr_enable_trans_key(enum omap_channel ch, bool enable) |
2297 | { | 2179 | { |
2298 | if (ch == OMAP_DSS_CHANNEL_LCD) | 2180 | if (ch == OMAP_DSS_CHANNEL_LCD) |
2299 | REG_FLD_MOD(DISPC_CONFIG, enable, 10, 10); | 2181 | REG_FLD_MOD(DISPC_CONFIG, enable, 10, 10); |
@@ -2302,39 +2184,36 @@ void dispc_enable_trans_key(enum omap_channel ch, bool enable) | |||
2302 | else /* OMAP_DSS_CHANNEL_LCD2 */ | 2184 | else /* OMAP_DSS_CHANNEL_LCD2 */ |
2303 | REG_FLD_MOD(DISPC_CONFIG2, enable, 10, 10); | 2185 | REG_FLD_MOD(DISPC_CONFIG2, enable, 10, 10); |
2304 | } | 2186 | } |
2305 | void dispc_enable_alpha_blending(enum omap_channel ch, bool enable) | 2187 | |
2188 | void dispc_mgr_enable_alpha_fixed_zorder(enum omap_channel ch, bool enable) | ||
2306 | { | 2189 | { |
2307 | if (!dss_has_feature(FEAT_GLOBAL_ALPHA)) | 2190 | if (!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER)) |
2308 | return; | 2191 | return; |
2309 | 2192 | ||
2310 | if (ch == OMAP_DSS_CHANNEL_LCD) | 2193 | if (ch == OMAP_DSS_CHANNEL_LCD) |
2311 | REG_FLD_MOD(DISPC_CONFIG, enable, 18, 18); | 2194 | REG_FLD_MOD(DISPC_CONFIG, enable, 18, 18); |
2312 | else if (ch == OMAP_DSS_CHANNEL_DIGIT) | 2195 | else if (ch == OMAP_DSS_CHANNEL_DIGIT) |
2313 | REG_FLD_MOD(DISPC_CONFIG, enable, 19, 19); | 2196 | REG_FLD_MOD(DISPC_CONFIG, enable, 19, 19); |
2314 | else /* OMAP_DSS_CHANNEL_LCD2 */ | ||
2315 | REG_FLD_MOD(DISPC_CONFIG2, enable, 18, 18); | ||
2316 | } | 2197 | } |
2317 | bool dispc_alpha_blending_enabled(enum omap_channel ch) | 2198 | |
2199 | bool dispc_mgr_alpha_fixed_zorder_enabled(enum omap_channel ch) | ||
2318 | { | 2200 | { |
2319 | bool enabled; | 2201 | bool enabled; |
2320 | 2202 | ||
2321 | if (!dss_has_feature(FEAT_GLOBAL_ALPHA)) | 2203 | if (!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER)) |
2322 | return false; | 2204 | return false; |
2323 | 2205 | ||
2324 | if (ch == OMAP_DSS_CHANNEL_LCD) | 2206 | if (ch == OMAP_DSS_CHANNEL_LCD) |
2325 | enabled = REG_GET(DISPC_CONFIG, 18, 18); | 2207 | enabled = REG_GET(DISPC_CONFIG, 18, 18); |
2326 | else if (ch == OMAP_DSS_CHANNEL_DIGIT) | 2208 | else if (ch == OMAP_DSS_CHANNEL_DIGIT) |
2327 | enabled = REG_GET(DISPC_CONFIG, 19, 19); | 2209 | enabled = REG_GET(DISPC_CONFIG, 19, 19); |
2328 | else if (ch == OMAP_DSS_CHANNEL_LCD2) | ||
2329 | enabled = REG_GET(DISPC_CONFIG2, 18, 18); | ||
2330 | else | 2210 | else |
2331 | BUG(); | 2211 | BUG(); |
2332 | 2212 | ||
2333 | return enabled; | 2213 | return enabled; |
2334 | } | 2214 | } |
2335 | 2215 | ||
2336 | 2216 | bool dispc_mgr_trans_key_enabled(enum omap_channel ch) | |
2337 | bool dispc_trans_key_enabled(enum omap_channel ch) | ||
2338 | { | 2217 | { |
2339 | bool enabled; | 2218 | bool enabled; |
2340 | 2219 | ||
@@ -2351,7 +2230,7 @@ bool dispc_trans_key_enabled(enum omap_channel ch) | |||
2351 | } | 2230 | } |
2352 | 2231 | ||
2353 | 2232 | ||
2354 | void dispc_set_tft_data_lines(enum omap_channel channel, u8 data_lines) | 2233 | void dispc_mgr_set_tft_data_lines(enum omap_channel channel, u8 data_lines) |
2355 | { | 2234 | { |
2356 | int code; | 2235 | int code; |
2357 | 2236 | ||
@@ -2379,46 +2258,41 @@ void dispc_set_tft_data_lines(enum omap_channel channel, u8 data_lines) | |||
2379 | REG_FLD_MOD(DISPC_CONTROL, code, 9, 8); | 2258 | REG_FLD_MOD(DISPC_CONTROL, code, 9, 8); |
2380 | } | 2259 | } |
2381 | 2260 | ||
2382 | void dispc_set_parallel_interface_mode(enum omap_channel channel, | 2261 | void dispc_mgr_set_io_pad_mode(enum dss_io_pad_mode mode) |
2383 | enum omap_parallel_interface_mode mode) | ||
2384 | { | 2262 | { |
2385 | u32 l; | 2263 | u32 l; |
2386 | int stallmode; | 2264 | int gpout0, gpout1; |
2387 | int gpout0 = 1; | ||
2388 | int gpout1; | ||
2389 | 2265 | ||
2390 | switch (mode) { | 2266 | switch (mode) { |
2391 | case OMAP_DSS_PARALLELMODE_BYPASS: | 2267 | case DSS_IO_PAD_MODE_RESET: |
2392 | stallmode = 0; | 2268 | gpout0 = 0; |
2393 | gpout1 = 1; | 2269 | gpout1 = 0; |
2394 | break; | 2270 | break; |
2395 | 2271 | case DSS_IO_PAD_MODE_RFBI: | |
2396 | case OMAP_DSS_PARALLELMODE_RFBI: | 2272 | gpout0 = 1; |
2397 | stallmode = 1; | ||
2398 | gpout1 = 0; | 2273 | gpout1 = 0; |
2399 | break; | 2274 | break; |
2400 | 2275 | case DSS_IO_PAD_MODE_BYPASS: | |
2401 | case OMAP_DSS_PARALLELMODE_DSI: | 2276 | gpout0 = 1; |
2402 | stallmode = 1; | ||
2403 | gpout1 = 1; | 2277 | gpout1 = 1; |
2404 | break; | 2278 | break; |
2405 | |||
2406 | default: | 2279 | default: |
2407 | BUG(); | 2280 | BUG(); |
2408 | return; | 2281 | return; |
2409 | } | 2282 | } |
2410 | 2283 | ||
2411 | if (channel == OMAP_DSS_CHANNEL_LCD2) { | 2284 | l = dispc_read_reg(DISPC_CONTROL); |
2412 | l = dispc_read_reg(DISPC_CONTROL2); | 2285 | l = FLD_MOD(l, gpout0, 15, 15); |
2413 | l = FLD_MOD(l, stallmode, 11, 11); | 2286 | l = FLD_MOD(l, gpout1, 16, 16); |
2414 | dispc_write_reg(DISPC_CONTROL2, l); | 2287 | dispc_write_reg(DISPC_CONTROL, l); |
2415 | } else { | 2288 | } |
2416 | l = dispc_read_reg(DISPC_CONTROL); | 2289 | |
2417 | l = FLD_MOD(l, stallmode, 11, 11); | 2290 | void dispc_mgr_enable_stallmode(enum omap_channel channel, bool enable) |
2418 | l = FLD_MOD(l, gpout0, 15, 15); | 2291 | { |
2419 | l = FLD_MOD(l, gpout1, 16, 16); | 2292 | if (channel == OMAP_DSS_CHANNEL_LCD2) |
2420 | dispc_write_reg(DISPC_CONTROL, l); | 2293 | REG_FLD_MOD(DISPC_CONTROL2, enable, 11, 11); |
2421 | } | 2294 | else |
2295 | REG_FLD_MOD(DISPC_CONTROL, enable, 11, 11); | ||
2422 | } | 2296 | } |
2423 | 2297 | ||
2424 | static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp, | 2298 | static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp, |
@@ -2452,7 +2326,7 @@ bool dispc_lcd_timings_ok(struct omap_video_timings *timings) | |||
2452 | timings->vfp, timings->vbp); | 2326 | timings->vfp, timings->vbp); |
2453 | } | 2327 | } |
2454 | 2328 | ||
2455 | static void _dispc_set_lcd_timings(enum omap_channel channel, int hsw, | 2329 | static void _dispc_mgr_set_lcd_timings(enum omap_channel channel, int hsw, |
2456 | int hfp, int hbp, int vsw, int vfp, int vbp) | 2330 | int hfp, int hbp, int vsw, int vfp, int vbp) |
2457 | { | 2331 | { |
2458 | u32 timing_h, timing_v; | 2332 | u32 timing_h, timing_v; |
@@ -2476,7 +2350,7 @@ static void _dispc_set_lcd_timings(enum omap_channel channel, int hsw, | |||
2476 | } | 2350 | } |
2477 | 2351 | ||
2478 | /* change name to mode? */ | 2352 | /* change name to mode? */ |
2479 | void dispc_set_lcd_timings(enum omap_channel channel, | 2353 | void dispc_mgr_set_lcd_timings(enum omap_channel channel, |
2480 | struct omap_video_timings *timings) | 2354 | struct omap_video_timings *timings) |
2481 | { | 2355 | { |
2482 | unsigned xtot, ytot; | 2356 | unsigned xtot, ytot; |
@@ -2487,11 +2361,11 @@ void dispc_set_lcd_timings(enum omap_channel channel, | |||
2487 | timings->vfp, timings->vbp)) | 2361 | timings->vfp, timings->vbp)) |
2488 | BUG(); | 2362 | BUG(); |
2489 | 2363 | ||
2490 | _dispc_set_lcd_timings(channel, timings->hsw, timings->hfp, | 2364 | _dispc_mgr_set_lcd_timings(channel, timings->hsw, timings->hfp, |
2491 | timings->hbp, timings->vsw, timings->vfp, | 2365 | timings->hbp, timings->vsw, timings->vfp, |
2492 | timings->vbp); | 2366 | timings->vbp); |
2493 | 2367 | ||
2494 | dispc_set_lcd_size(channel, timings->x_res, timings->y_res); | 2368 | dispc_mgr_set_lcd_size(channel, timings->x_res, timings->y_res); |
2495 | 2369 | ||
2496 | xtot = timings->x_res + timings->hfp + timings->hsw + timings->hbp; | 2370 | xtot = timings->x_res + timings->hfp + timings->hsw + timings->hbp; |
2497 | ytot = timings->y_res + timings->vfp + timings->vsw + timings->vbp; | 2371 | ytot = timings->y_res + timings->vfp + timings->vsw + timings->vbp; |
@@ -2509,17 +2383,17 @@ void dispc_set_lcd_timings(enum omap_channel channel, | |||
2509 | DSSDBG("hsync %luHz, vsync %luHz\n", ht, vt); | 2383 | DSSDBG("hsync %luHz, vsync %luHz\n", ht, vt); |
2510 | } | 2384 | } |
2511 | 2385 | ||
2512 | static void dispc_set_lcd_divisor(enum omap_channel channel, u16 lck_div, | 2386 | static void dispc_mgr_set_lcd_divisor(enum omap_channel channel, u16 lck_div, |
2513 | u16 pck_div) | 2387 | u16 pck_div) |
2514 | { | 2388 | { |
2515 | BUG_ON(lck_div < 1); | 2389 | BUG_ON(lck_div < 1); |
2516 | BUG_ON(pck_div < 2); | 2390 | BUG_ON(pck_div < 1); |
2517 | 2391 | ||
2518 | dispc_write_reg(DISPC_DIVISORo(channel), | 2392 | dispc_write_reg(DISPC_DIVISORo(channel), |
2519 | FLD_VAL(lck_div, 23, 16) | FLD_VAL(pck_div, 7, 0)); | 2393 | FLD_VAL(lck_div, 23, 16) | FLD_VAL(pck_div, 7, 0)); |
2520 | } | 2394 | } |
2521 | 2395 | ||
2522 | static void dispc_get_lcd_divisor(enum omap_channel channel, int *lck_div, | 2396 | static void dispc_mgr_get_lcd_divisor(enum omap_channel channel, int *lck_div, |
2523 | int *pck_div) | 2397 | int *pck_div) |
2524 | { | 2398 | { |
2525 | u32 l; | 2399 | u32 l; |
@@ -2552,7 +2426,7 @@ unsigned long dispc_fclk_rate(void) | |||
2552 | return r; | 2426 | return r; |
2553 | } | 2427 | } |
2554 | 2428 | ||
2555 | unsigned long dispc_lclk_rate(enum omap_channel channel) | 2429 | unsigned long dispc_mgr_lclk_rate(enum omap_channel channel) |
2556 | { | 2430 | { |
2557 | struct platform_device *dsidev; | 2431 | struct platform_device *dsidev; |
2558 | int lcd; | 2432 | int lcd; |
@@ -2582,19 +2456,34 @@ unsigned long dispc_lclk_rate(enum omap_channel channel) | |||
2582 | return r / lcd; | 2456 | return r / lcd; |
2583 | } | 2457 | } |
2584 | 2458 | ||
2585 | unsigned long dispc_pclk_rate(enum omap_channel channel) | 2459 | unsigned long dispc_mgr_pclk_rate(enum omap_channel channel) |
2586 | { | 2460 | { |
2587 | int pcd; | ||
2588 | unsigned long r; | 2461 | unsigned long r; |
2589 | u32 l; | ||
2590 | 2462 | ||
2591 | l = dispc_read_reg(DISPC_DIVISORo(channel)); | 2463 | if (dispc_mgr_is_lcd(channel)) { |
2464 | int pcd; | ||
2465 | u32 l; | ||
2592 | 2466 | ||
2593 | pcd = FLD_GET(l, 7, 0); | 2467 | l = dispc_read_reg(DISPC_DIVISORo(channel)); |
2594 | 2468 | ||
2595 | r = dispc_lclk_rate(channel); | 2469 | pcd = FLD_GET(l, 7, 0); |
2596 | 2470 | ||
2597 | return r / pcd; | 2471 | r = dispc_mgr_lclk_rate(channel); |
2472 | |||
2473 | return r / pcd; | ||
2474 | } else { | ||
2475 | struct omap_dss_device *dssdev = | ||
2476 | dispc_mgr_get_device(channel); | ||
2477 | |||
2478 | switch (dssdev->type) { | ||
2479 | case OMAP_DISPLAY_TYPE_VENC: | ||
2480 | return venc_get_pixel_clock(); | ||
2481 | case OMAP_DISPLAY_TYPE_HDMI: | ||
2482 | return hdmi_get_pixel_clock(); | ||
2483 | default: | ||
2484 | BUG(); | ||
2485 | } | ||
2486 | } | ||
2598 | } | 2487 | } |
2599 | 2488 | ||
2600 | void dispc_dump_clocks(struct seq_file *s) | 2489 | void dispc_dump_clocks(struct seq_file *s) |
@@ -2631,12 +2520,12 @@ void dispc_dump_clocks(struct seq_file *s) | |||
2631 | dss_get_generic_clk_source_name(lcd_clk_src), | 2520 | dss_get_generic_clk_source_name(lcd_clk_src), |
2632 | dss_feat_get_clk_source_name(lcd_clk_src)); | 2521 | dss_feat_get_clk_source_name(lcd_clk_src)); |
2633 | 2522 | ||
2634 | dispc_get_lcd_divisor(OMAP_DSS_CHANNEL_LCD, &lcd, &pcd); | 2523 | dispc_mgr_get_lcd_divisor(OMAP_DSS_CHANNEL_LCD, &lcd, &pcd); |
2635 | 2524 | ||
2636 | seq_printf(s, "lck\t\t%-16lulck div\t%u\n", | 2525 | seq_printf(s, "lck\t\t%-16lulck div\t%u\n", |
2637 | dispc_lclk_rate(OMAP_DSS_CHANNEL_LCD), lcd); | 2526 | dispc_mgr_lclk_rate(OMAP_DSS_CHANNEL_LCD), lcd); |
2638 | seq_printf(s, "pck\t\t%-16lupck div\t%u\n", | 2527 | seq_printf(s, "pck\t\t%-16lupck div\t%u\n", |
2639 | dispc_pclk_rate(OMAP_DSS_CHANNEL_LCD), pcd); | 2528 | dispc_mgr_pclk_rate(OMAP_DSS_CHANNEL_LCD), pcd); |
2640 | if (dss_has_feature(FEAT_MGR_LCD2)) { | 2529 | if (dss_has_feature(FEAT_MGR_LCD2)) { |
2641 | seq_printf(s, "- LCD2 -\n"); | 2530 | seq_printf(s, "- LCD2 -\n"); |
2642 | 2531 | ||
@@ -2646,12 +2535,12 @@ void dispc_dump_clocks(struct seq_file *s) | |||
2646 | dss_get_generic_clk_source_name(lcd_clk_src), | 2535 | dss_get_generic_clk_source_name(lcd_clk_src), |
2647 | dss_feat_get_clk_source_name(lcd_clk_src)); | 2536 | dss_feat_get_clk_source_name(lcd_clk_src)); |
2648 | 2537 | ||
2649 | dispc_get_lcd_divisor(OMAP_DSS_CHANNEL_LCD2, &lcd, &pcd); | 2538 | dispc_mgr_get_lcd_divisor(OMAP_DSS_CHANNEL_LCD2, &lcd, &pcd); |
2650 | 2539 | ||
2651 | seq_printf(s, "lck\t\t%-16lulck div\t%u\n", | 2540 | seq_printf(s, "lck\t\t%-16lulck div\t%u\n", |
2652 | dispc_lclk_rate(OMAP_DSS_CHANNEL_LCD2), lcd); | 2541 | dispc_mgr_lclk_rate(OMAP_DSS_CHANNEL_LCD2), lcd); |
2653 | seq_printf(s, "pck\t\t%-16lupck div\t%u\n", | 2542 | seq_printf(s, "pck\t\t%-16lupck div\t%u\n", |
2654 | dispc_pclk_rate(OMAP_DSS_CHANNEL_LCD2), pcd); | 2543 | dispc_mgr_pclk_rate(OMAP_DSS_CHANNEL_LCD2), pcd); |
2655 | } | 2544 | } |
2656 | 2545 | ||
2657 | dispc_runtime_put(); | 2546 | dispc_runtime_put(); |
@@ -2692,6 +2581,10 @@ void dispc_dump_irqs(struct seq_file *s) | |||
2692 | PIS(VID1_END_WIN); | 2581 | PIS(VID1_END_WIN); |
2693 | PIS(VID2_FIFO_UNDERFLOW); | 2582 | PIS(VID2_FIFO_UNDERFLOW); |
2694 | PIS(VID2_END_WIN); | 2583 | PIS(VID2_END_WIN); |
2584 | if (dss_feat_get_num_ovls() > 3) { | ||
2585 | PIS(VID3_FIFO_UNDERFLOW); | ||
2586 | PIS(VID3_END_WIN); | ||
2587 | } | ||
2695 | PIS(SYNC_LOST); | 2588 | PIS(SYNC_LOST); |
2696 | PIS(SYNC_LOST_DIGIT); | 2589 | PIS(SYNC_LOST_DIGIT); |
2697 | PIS(WAKEUP); | 2590 | PIS(WAKEUP); |
@@ -2707,11 +2600,26 @@ void dispc_dump_irqs(struct seq_file *s) | |||
2707 | 2600 | ||
2708 | void dispc_dump_regs(struct seq_file *s) | 2601 | void dispc_dump_regs(struct seq_file *s) |
2709 | { | 2602 | { |
2603 | int i, j; | ||
2604 | const char *mgr_names[] = { | ||
2605 | [OMAP_DSS_CHANNEL_LCD] = "LCD", | ||
2606 | [OMAP_DSS_CHANNEL_DIGIT] = "TV", | ||
2607 | [OMAP_DSS_CHANNEL_LCD2] = "LCD2", | ||
2608 | }; | ||
2609 | const char *ovl_names[] = { | ||
2610 | [OMAP_DSS_GFX] = "GFX", | ||
2611 | [OMAP_DSS_VIDEO1] = "VID1", | ||
2612 | [OMAP_DSS_VIDEO2] = "VID2", | ||
2613 | [OMAP_DSS_VIDEO3] = "VID3", | ||
2614 | }; | ||
2615 | const char **p_names; | ||
2616 | |||
2710 | #define DUMPREG(r) seq_printf(s, "%-50s %08x\n", #r, dispc_read_reg(r)) | 2617 | #define DUMPREG(r) seq_printf(s, "%-50s %08x\n", #r, dispc_read_reg(r)) |
2711 | 2618 | ||
2712 | if (dispc_runtime_get()) | 2619 | if (dispc_runtime_get()) |
2713 | return; | 2620 | return; |
2714 | 2621 | ||
2622 | /* DISPC common registers */ | ||
2715 | DUMPREG(DISPC_REVISION); | 2623 | DUMPREG(DISPC_REVISION); |
2716 | DUMPREG(DISPC_SYSCONFIG); | 2624 | DUMPREG(DISPC_SYSCONFIG); |
2717 | DUMPREG(DISPC_SYSSTATUS); | 2625 | DUMPREG(DISPC_SYSSTATUS); |
@@ -2720,247 +2628,139 @@ void dispc_dump_regs(struct seq_file *s) | |||
2720 | DUMPREG(DISPC_CONTROL); | 2628 | DUMPREG(DISPC_CONTROL); |
2721 | DUMPREG(DISPC_CONFIG); | 2629 | DUMPREG(DISPC_CONFIG); |
2722 | DUMPREG(DISPC_CAPABLE); | 2630 | DUMPREG(DISPC_CAPABLE); |
2723 | DUMPREG(DISPC_DEFAULT_COLOR(OMAP_DSS_CHANNEL_LCD)); | ||
2724 | DUMPREG(DISPC_DEFAULT_COLOR(OMAP_DSS_CHANNEL_DIGIT)); | ||
2725 | DUMPREG(DISPC_TRANS_COLOR(OMAP_DSS_CHANNEL_LCD)); | ||
2726 | DUMPREG(DISPC_TRANS_COLOR(OMAP_DSS_CHANNEL_DIGIT)); | ||
2727 | DUMPREG(DISPC_LINE_STATUS); | 2631 | DUMPREG(DISPC_LINE_STATUS); |
2728 | DUMPREG(DISPC_LINE_NUMBER); | 2632 | DUMPREG(DISPC_LINE_NUMBER); |
2729 | DUMPREG(DISPC_TIMING_H(OMAP_DSS_CHANNEL_LCD)); | 2633 | if (dss_has_feature(FEAT_ALPHA_FIXED_ZORDER) || |
2730 | DUMPREG(DISPC_TIMING_V(OMAP_DSS_CHANNEL_LCD)); | 2634 | dss_has_feature(FEAT_ALPHA_FREE_ZORDER)) |
2731 | DUMPREG(DISPC_POL_FREQ(OMAP_DSS_CHANNEL_LCD)); | ||
2732 | DUMPREG(DISPC_DIVISORo(OMAP_DSS_CHANNEL_LCD)); | ||
2733 | if (dss_has_feature(FEAT_GLOBAL_ALPHA)) | ||
2734 | DUMPREG(DISPC_GLOBAL_ALPHA); | 2635 | DUMPREG(DISPC_GLOBAL_ALPHA); |
2735 | DUMPREG(DISPC_SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT)); | ||
2736 | DUMPREG(DISPC_SIZE_MGR(OMAP_DSS_CHANNEL_LCD)); | ||
2737 | if (dss_has_feature(FEAT_MGR_LCD2)) { | 2636 | if (dss_has_feature(FEAT_MGR_LCD2)) { |
2738 | DUMPREG(DISPC_CONTROL2); | 2637 | DUMPREG(DISPC_CONTROL2); |
2739 | DUMPREG(DISPC_CONFIG2); | 2638 | DUMPREG(DISPC_CONFIG2); |
2740 | DUMPREG(DISPC_DEFAULT_COLOR(OMAP_DSS_CHANNEL_LCD2)); | ||
2741 | DUMPREG(DISPC_TRANS_COLOR(OMAP_DSS_CHANNEL_LCD2)); | ||
2742 | DUMPREG(DISPC_TIMING_H(OMAP_DSS_CHANNEL_LCD2)); | ||
2743 | DUMPREG(DISPC_TIMING_V(OMAP_DSS_CHANNEL_LCD2)); | ||
2744 | DUMPREG(DISPC_POL_FREQ(OMAP_DSS_CHANNEL_LCD2)); | ||
2745 | DUMPREG(DISPC_DIVISORo(OMAP_DSS_CHANNEL_LCD2)); | ||
2746 | DUMPREG(DISPC_SIZE_MGR(OMAP_DSS_CHANNEL_LCD2)); | ||
2747 | } | ||
2748 | |||
2749 | DUMPREG(DISPC_OVL_BA0(OMAP_DSS_GFX)); | ||
2750 | DUMPREG(DISPC_OVL_BA1(OMAP_DSS_GFX)); | ||
2751 | DUMPREG(DISPC_OVL_POSITION(OMAP_DSS_GFX)); | ||
2752 | DUMPREG(DISPC_OVL_SIZE(OMAP_DSS_GFX)); | ||
2753 | DUMPREG(DISPC_OVL_ATTRIBUTES(OMAP_DSS_GFX)); | ||
2754 | DUMPREG(DISPC_OVL_FIFO_THRESHOLD(OMAP_DSS_GFX)); | ||
2755 | DUMPREG(DISPC_OVL_FIFO_SIZE_STATUS(OMAP_DSS_GFX)); | ||
2756 | DUMPREG(DISPC_OVL_ROW_INC(OMAP_DSS_GFX)); | ||
2757 | DUMPREG(DISPC_OVL_PIXEL_INC(OMAP_DSS_GFX)); | ||
2758 | DUMPREG(DISPC_OVL_WINDOW_SKIP(OMAP_DSS_GFX)); | ||
2759 | DUMPREG(DISPC_OVL_TABLE_BA(OMAP_DSS_GFX)); | ||
2760 | |||
2761 | DUMPREG(DISPC_DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD)); | ||
2762 | DUMPREG(DISPC_DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD)); | ||
2763 | DUMPREG(DISPC_DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD)); | ||
2764 | |||
2765 | if (dss_has_feature(FEAT_CPR)) { | ||
2766 | DUMPREG(DISPC_CPR_COEF_R(OMAP_DSS_CHANNEL_LCD)); | ||
2767 | DUMPREG(DISPC_CPR_COEF_G(OMAP_DSS_CHANNEL_LCD)); | ||
2768 | DUMPREG(DISPC_CPR_COEF_B(OMAP_DSS_CHANNEL_LCD)); | ||
2769 | } | 2639 | } |
2770 | if (dss_has_feature(FEAT_MGR_LCD2)) { | 2640 | |
2771 | DUMPREG(DISPC_DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD2)); | 2641 | #undef DUMPREG |
2772 | DUMPREG(DISPC_DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD2)); | 2642 | |
2773 | DUMPREG(DISPC_DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD2)); | 2643 | #define DISPC_REG(i, name) name(i) |
2644 | #define DUMPREG(i, r) seq_printf(s, "%s(%s)%*s %08x\n", #r, p_names[i], \ | ||
2645 | 48 - strlen(#r) - strlen(p_names[i]), " ", \ | ||
2646 | dispc_read_reg(DISPC_REG(i, r))) | ||
2647 | |||
2648 | p_names = mgr_names; | ||
2649 | |||
2650 | /* DISPC channel specific registers */ | ||
2651 | for (i = 0; i < dss_feat_get_num_mgrs(); i++) { | ||
2652 | DUMPREG(i, DISPC_DEFAULT_COLOR); | ||
2653 | DUMPREG(i, DISPC_TRANS_COLOR); | ||
2654 | DUMPREG(i, DISPC_SIZE_MGR); | ||
2655 | |||
2656 | if (i == OMAP_DSS_CHANNEL_DIGIT) | ||
2657 | continue; | ||
2658 | |||
2659 | DUMPREG(i, DISPC_DEFAULT_COLOR); | ||
2660 | DUMPREG(i, DISPC_TRANS_COLOR); | ||
2661 | DUMPREG(i, DISPC_TIMING_H); | ||
2662 | DUMPREG(i, DISPC_TIMING_V); | ||
2663 | DUMPREG(i, DISPC_POL_FREQ); | ||
2664 | DUMPREG(i, DISPC_DIVISORo); | ||
2665 | DUMPREG(i, DISPC_SIZE_MGR); | ||
2666 | |||
2667 | DUMPREG(i, DISPC_DATA_CYCLE1); | ||
2668 | DUMPREG(i, DISPC_DATA_CYCLE2); | ||
2669 | DUMPREG(i, DISPC_DATA_CYCLE3); | ||
2774 | 2670 | ||
2775 | if (dss_has_feature(FEAT_CPR)) { | 2671 | if (dss_has_feature(FEAT_CPR)) { |
2776 | DUMPREG(DISPC_CPR_COEF_R(OMAP_DSS_CHANNEL_LCD2)); | 2672 | DUMPREG(i, DISPC_CPR_COEF_R); |
2777 | DUMPREG(DISPC_CPR_COEF_G(OMAP_DSS_CHANNEL_LCD2)); | 2673 | DUMPREG(i, DISPC_CPR_COEF_G); |
2778 | DUMPREG(DISPC_CPR_COEF_B(OMAP_DSS_CHANNEL_LCD2)); | 2674 | DUMPREG(i, DISPC_CPR_COEF_B); |
2675 | } | ||
2676 | } | ||
2677 | |||
2678 | p_names = ovl_names; | ||
2679 | |||
2680 | for (i = 0; i < dss_feat_get_num_ovls(); i++) { | ||
2681 | DUMPREG(i, DISPC_OVL_BA0); | ||
2682 | DUMPREG(i, DISPC_OVL_BA1); | ||
2683 | DUMPREG(i, DISPC_OVL_POSITION); | ||
2684 | DUMPREG(i, DISPC_OVL_SIZE); | ||
2685 | DUMPREG(i, DISPC_OVL_ATTRIBUTES); | ||
2686 | DUMPREG(i, DISPC_OVL_FIFO_THRESHOLD); | ||
2687 | DUMPREG(i, DISPC_OVL_FIFO_SIZE_STATUS); | ||
2688 | DUMPREG(i, DISPC_OVL_ROW_INC); | ||
2689 | DUMPREG(i, DISPC_OVL_PIXEL_INC); | ||
2690 | if (dss_has_feature(FEAT_PRELOAD)) | ||
2691 | DUMPREG(i, DISPC_OVL_PRELOAD); | ||
2692 | |||
2693 | if (i == OMAP_DSS_GFX) { | ||
2694 | DUMPREG(i, DISPC_OVL_WINDOW_SKIP); | ||
2695 | DUMPREG(i, DISPC_OVL_TABLE_BA); | ||
2696 | continue; | ||
2697 | } | ||
2698 | |||
2699 | DUMPREG(i, DISPC_OVL_FIR); | ||
2700 | DUMPREG(i, DISPC_OVL_PICTURE_SIZE); | ||
2701 | DUMPREG(i, DISPC_OVL_ACCU0); | ||
2702 | DUMPREG(i, DISPC_OVL_ACCU1); | ||
2703 | if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) { | ||
2704 | DUMPREG(i, DISPC_OVL_BA0_UV); | ||
2705 | DUMPREG(i, DISPC_OVL_BA1_UV); | ||
2706 | DUMPREG(i, DISPC_OVL_FIR2); | ||
2707 | DUMPREG(i, DISPC_OVL_ACCU2_0); | ||
2708 | DUMPREG(i, DISPC_OVL_ACCU2_1); | ||
2779 | } | 2709 | } |
2710 | if (dss_has_feature(FEAT_ATTR2)) | ||
2711 | DUMPREG(i, DISPC_OVL_ATTRIBUTES2); | ||
2712 | if (dss_has_feature(FEAT_PRELOAD)) | ||
2713 | DUMPREG(i, DISPC_OVL_PRELOAD); | ||
2780 | } | 2714 | } |
2781 | 2715 | ||
2782 | if (dss_has_feature(FEAT_PRELOAD)) | 2716 | #undef DISPC_REG |
2783 | DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_GFX)); | 2717 | #undef DUMPREG |
2784 | 2718 | ||
2785 | DUMPREG(DISPC_OVL_BA0(OMAP_DSS_VIDEO1)); | 2719 | #define DISPC_REG(plane, name, i) name(plane, i) |
2786 | DUMPREG(DISPC_OVL_BA1(OMAP_DSS_VIDEO1)); | 2720 | #define DUMPREG(plane, name, i) \ |
2787 | DUMPREG(DISPC_OVL_POSITION(OMAP_DSS_VIDEO1)); | 2721 | seq_printf(s, "%s_%d(%s)%*s %08x\n", #name, i, p_names[plane], \ |
2788 | DUMPREG(DISPC_OVL_SIZE(OMAP_DSS_VIDEO1)); | 2722 | 46 - strlen(#name) - strlen(p_names[plane]), " ", \ |
2789 | DUMPREG(DISPC_OVL_ATTRIBUTES(OMAP_DSS_VIDEO1)); | 2723 | dispc_read_reg(DISPC_REG(plane, name, i))) |
2790 | DUMPREG(DISPC_OVL_FIFO_THRESHOLD(OMAP_DSS_VIDEO1)); | 2724 | |
2791 | DUMPREG(DISPC_OVL_FIFO_SIZE_STATUS(OMAP_DSS_VIDEO1)); | 2725 | /* Video pipeline coefficient registers */ |
2792 | DUMPREG(DISPC_OVL_ROW_INC(OMAP_DSS_VIDEO1)); | 2726 | |
2793 | DUMPREG(DISPC_OVL_PIXEL_INC(OMAP_DSS_VIDEO1)); | 2727 | /* start from OMAP_DSS_VIDEO1 */ |
2794 | DUMPREG(DISPC_OVL_FIR(OMAP_DSS_VIDEO1)); | 2728 | for (i = 1; i < dss_feat_get_num_ovls(); i++) { |
2795 | DUMPREG(DISPC_OVL_PICTURE_SIZE(OMAP_DSS_VIDEO1)); | 2729 | for (j = 0; j < 8; j++) |
2796 | DUMPREG(DISPC_OVL_ACCU0(OMAP_DSS_VIDEO1)); | 2730 | DUMPREG(i, DISPC_OVL_FIR_COEF_H, j); |
2797 | DUMPREG(DISPC_OVL_ACCU1(OMAP_DSS_VIDEO1)); | 2731 | |
2798 | 2732 | for (j = 0; j < 8; j++) | |
2799 | DUMPREG(DISPC_OVL_BA0(OMAP_DSS_VIDEO2)); | 2733 | DUMPREG(i, DISPC_OVL_FIR_COEF_HV, j); |
2800 | DUMPREG(DISPC_OVL_BA1(OMAP_DSS_VIDEO2)); | 2734 | |
2801 | DUMPREG(DISPC_OVL_POSITION(OMAP_DSS_VIDEO2)); | 2735 | for (j = 0; j < 5; j++) |
2802 | DUMPREG(DISPC_OVL_SIZE(OMAP_DSS_VIDEO2)); | 2736 | DUMPREG(i, DISPC_OVL_CONV_COEF, j); |
2803 | DUMPREG(DISPC_OVL_ATTRIBUTES(OMAP_DSS_VIDEO2)); | 2737 | |
2804 | DUMPREG(DISPC_OVL_FIFO_THRESHOLD(OMAP_DSS_VIDEO2)); | 2738 | if (dss_has_feature(FEAT_FIR_COEF_V)) { |
2805 | DUMPREG(DISPC_OVL_FIFO_SIZE_STATUS(OMAP_DSS_VIDEO2)); | 2739 | for (j = 0; j < 8; j++) |
2806 | DUMPREG(DISPC_OVL_ROW_INC(OMAP_DSS_VIDEO2)); | 2740 | DUMPREG(i, DISPC_OVL_FIR_COEF_V, j); |
2807 | DUMPREG(DISPC_OVL_PIXEL_INC(OMAP_DSS_VIDEO2)); | 2741 | } |
2808 | DUMPREG(DISPC_OVL_FIR(OMAP_DSS_VIDEO2)); | 2742 | |
2809 | DUMPREG(DISPC_OVL_PICTURE_SIZE(OMAP_DSS_VIDEO2)); | 2743 | if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) { |
2810 | DUMPREG(DISPC_OVL_ACCU0(OMAP_DSS_VIDEO2)); | 2744 | for (j = 0; j < 8; j++) |
2811 | DUMPREG(DISPC_OVL_ACCU1(OMAP_DSS_VIDEO2)); | 2745 | DUMPREG(i, DISPC_OVL_FIR_COEF_H2, j); |
2812 | 2746 | ||
2813 | DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 0)); | 2747 | for (j = 0; j < 8; j++) |
2814 | DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 1)); | 2748 | DUMPREG(i, DISPC_OVL_FIR_COEF_HV2, j); |
2815 | DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 2)); | 2749 | |
2816 | DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 3)); | 2750 | for (j = 0; j < 8; j++) |
2817 | DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 4)); | 2751 | DUMPREG(i, DISPC_OVL_FIR_COEF_V2, j); |
2818 | DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 5)); | 2752 | } |
2819 | DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 6)); | ||
2820 | DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 7)); | ||
2821 | DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 0)); | ||
2822 | DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 1)); | ||
2823 | DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 2)); | ||
2824 | DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 3)); | ||
2825 | DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 4)); | ||
2826 | DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 5)); | ||
2827 | DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 6)); | ||
2828 | DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 7)); | ||
2829 | DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 0)); | ||
2830 | DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 1)); | ||
2831 | DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 2)); | ||
2832 | DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 3)); | ||
2833 | DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 4)); | ||
2834 | if (dss_has_feature(FEAT_FIR_COEF_V)) { | ||
2835 | DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 0)); | ||
2836 | DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 1)); | ||
2837 | DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 2)); | ||
2838 | DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 3)); | ||
2839 | DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 4)); | ||
2840 | DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 5)); | ||
2841 | DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 6)); | ||
2842 | DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 7)); | ||
2843 | } | ||
2844 | |||
2845 | if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) { | ||
2846 | DUMPREG(DISPC_OVL_BA0_UV(OMAP_DSS_VIDEO1)); | ||
2847 | DUMPREG(DISPC_OVL_BA1_UV(OMAP_DSS_VIDEO1)); | ||
2848 | DUMPREG(DISPC_OVL_FIR2(OMAP_DSS_VIDEO1)); | ||
2849 | DUMPREG(DISPC_OVL_ACCU2_0(OMAP_DSS_VIDEO1)); | ||
2850 | DUMPREG(DISPC_OVL_ACCU2_1(OMAP_DSS_VIDEO1)); | ||
2851 | |||
2852 | DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, 0)); | ||
2853 | DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, 1)); | ||
2854 | DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, 2)); | ||
2855 | DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, 3)); | ||
2856 | DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, 4)); | ||
2857 | DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, 5)); | ||
2858 | DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, 6)); | ||
2859 | DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, 7)); | ||
2860 | |||
2861 | DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, 0)); | ||
2862 | DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, 1)); | ||
2863 | DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, 2)); | ||
2864 | DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, 3)); | ||
2865 | DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, 4)); | ||
2866 | DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, 5)); | ||
2867 | DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, 6)); | ||
2868 | DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, 7)); | ||
2869 | |||
2870 | DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, 0)); | ||
2871 | DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, 1)); | ||
2872 | DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, 2)); | ||
2873 | DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, 3)); | ||
2874 | DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, 4)); | ||
2875 | DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, 5)); | ||
2876 | DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, 6)); | ||
2877 | DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, 7)); | ||
2878 | } | ||
2879 | if (dss_has_feature(FEAT_ATTR2)) | ||
2880 | DUMPREG(DISPC_OVL_ATTRIBUTES2(OMAP_DSS_VIDEO1)); | ||
2881 | |||
2882 | |||
2883 | DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 0)); | ||
2884 | DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 1)); | ||
2885 | DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 2)); | ||
2886 | DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 3)); | ||
2887 | DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 4)); | ||
2888 | DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 5)); | ||
2889 | DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 6)); | ||
2890 | DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 7)); | ||
2891 | DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 0)); | ||
2892 | DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 1)); | ||
2893 | DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 2)); | ||
2894 | DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 3)); | ||
2895 | DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 4)); | ||
2896 | DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 5)); | ||
2897 | DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 6)); | ||
2898 | DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 7)); | ||
2899 | DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 0)); | ||
2900 | DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 1)); | ||
2901 | DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 2)); | ||
2902 | DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 3)); | ||
2903 | DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 4)); | ||
2904 | |||
2905 | if (dss_has_feature(FEAT_FIR_COEF_V)) { | ||
2906 | DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 0)); | ||
2907 | DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 1)); | ||
2908 | DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 2)); | ||
2909 | DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 3)); | ||
2910 | DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 4)); | ||
2911 | DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 5)); | ||
2912 | DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 6)); | ||
2913 | DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 7)); | ||
2914 | } | ||
2915 | |||
2916 | if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) { | ||
2917 | DUMPREG(DISPC_OVL_BA0_UV(OMAP_DSS_VIDEO2)); | ||
2918 | DUMPREG(DISPC_OVL_BA1_UV(OMAP_DSS_VIDEO2)); | ||
2919 | DUMPREG(DISPC_OVL_FIR2(OMAP_DSS_VIDEO2)); | ||
2920 | DUMPREG(DISPC_OVL_ACCU2_0(OMAP_DSS_VIDEO2)); | ||
2921 | DUMPREG(DISPC_OVL_ACCU2_1(OMAP_DSS_VIDEO2)); | ||
2922 | |||
2923 | DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, 0)); | ||
2924 | DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, 1)); | ||
2925 | DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, 2)); | ||
2926 | DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, 3)); | ||
2927 | DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, 4)); | ||
2928 | DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, 5)); | ||
2929 | DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, 6)); | ||
2930 | DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, 7)); | ||
2931 | |||
2932 | DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, 0)); | ||
2933 | DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, 1)); | ||
2934 | DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, 2)); | ||
2935 | DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, 3)); | ||
2936 | DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, 4)); | ||
2937 | DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, 5)); | ||
2938 | DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, 6)); | ||
2939 | DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, 7)); | ||
2940 | |||
2941 | DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, 0)); | ||
2942 | DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, 1)); | ||
2943 | DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, 2)); | ||
2944 | DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, 3)); | ||
2945 | DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, 4)); | ||
2946 | DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, 5)); | ||
2947 | DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, 6)); | ||
2948 | DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, 7)); | ||
2949 | } | ||
2950 | if (dss_has_feature(FEAT_ATTR2)) | ||
2951 | DUMPREG(DISPC_OVL_ATTRIBUTES2(OMAP_DSS_VIDEO2)); | ||
2952 | |||
2953 | if (dss_has_feature(FEAT_PRELOAD)) { | ||
2954 | DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_VIDEO1)); | ||
2955 | DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_VIDEO2)); | ||
2956 | } | 2753 | } |
2957 | 2754 | ||
2958 | dispc_runtime_put(); | 2755 | dispc_runtime_put(); |
2756 | |||
2757 | #undef DISPC_REG | ||
2959 | #undef DUMPREG | 2758 | #undef DUMPREG |
2960 | } | 2759 | } |
2961 | 2760 | ||
2962 | static void _dispc_set_pol_freq(enum omap_channel channel, bool onoff, bool rf, | 2761 | static void _dispc_mgr_set_pol_freq(enum omap_channel channel, bool onoff, |
2963 | bool ieo, bool ipc, bool ihs, bool ivs, u8 acbi, u8 acb) | 2762 | bool rf, bool ieo, bool ipc, bool ihs, bool ivs, u8 acbi, |
2763 | u8 acb) | ||
2964 | { | 2764 | { |
2965 | u32 l = 0; | 2765 | u32 l = 0; |
2966 | 2766 | ||
@@ -2979,10 +2779,10 @@ static void _dispc_set_pol_freq(enum omap_channel channel, bool onoff, bool rf, | |||
2979 | dispc_write_reg(DISPC_POL_FREQ(channel), l); | 2779 | dispc_write_reg(DISPC_POL_FREQ(channel), l); |
2980 | } | 2780 | } |
2981 | 2781 | ||
2982 | void dispc_set_pol_freq(enum omap_channel channel, | 2782 | void dispc_mgr_set_pol_freq(enum omap_channel channel, |
2983 | enum omap_panel_config config, u8 acbi, u8 acb) | 2783 | enum omap_panel_config config, u8 acbi, u8 acb) |
2984 | { | 2784 | { |
2985 | _dispc_set_pol_freq(channel, (config & OMAP_DSS_LCD_ONOFF) != 0, | 2785 | _dispc_mgr_set_pol_freq(channel, (config & OMAP_DSS_LCD_ONOFF) != 0, |
2986 | (config & OMAP_DSS_LCD_RF) != 0, | 2786 | (config & OMAP_DSS_LCD_RF) != 0, |
2987 | (config & OMAP_DSS_LCD_IEO) != 0, | 2787 | (config & OMAP_DSS_LCD_IEO) != 0, |
2988 | (config & OMAP_DSS_LCD_IPC) != 0, | 2788 | (config & OMAP_DSS_LCD_IPC) != 0, |
@@ -2995,11 +2795,17 @@ void dispc_set_pol_freq(enum omap_channel channel, | |||
2995 | void dispc_find_clk_divs(bool is_tft, unsigned long req_pck, unsigned long fck, | 2795 | void dispc_find_clk_divs(bool is_tft, unsigned long req_pck, unsigned long fck, |
2996 | struct dispc_clock_info *cinfo) | 2796 | struct dispc_clock_info *cinfo) |
2997 | { | 2797 | { |
2998 | u16 pcd_min = is_tft ? 2 : 3; | 2798 | u16 pcd_min, pcd_max; |
2999 | unsigned long best_pck; | 2799 | unsigned long best_pck; |
3000 | u16 best_ld, cur_ld; | 2800 | u16 best_ld, cur_ld; |
3001 | u16 best_pd, cur_pd; | 2801 | u16 best_pd, cur_pd; |
3002 | 2802 | ||
2803 | pcd_min = dss_feat_get_param_min(FEAT_PARAM_DSS_PCD); | ||
2804 | pcd_max = dss_feat_get_param_max(FEAT_PARAM_DSS_PCD); | ||
2805 | |||
2806 | if (!is_tft) | ||
2807 | pcd_min = 3; | ||
2808 | |||
3003 | best_pck = 0; | 2809 | best_pck = 0; |
3004 | best_ld = 0; | 2810 | best_ld = 0; |
3005 | best_pd = 0; | 2811 | best_pd = 0; |
@@ -3007,7 +2813,7 @@ void dispc_find_clk_divs(bool is_tft, unsigned long req_pck, unsigned long fck, | |||
3007 | for (cur_ld = 1; cur_ld <= 255; ++cur_ld) { | 2813 | for (cur_ld = 1; cur_ld <= 255; ++cur_ld) { |
3008 | unsigned long lck = fck / cur_ld; | 2814 | unsigned long lck = fck / cur_ld; |
3009 | 2815 | ||
3010 | for (cur_pd = pcd_min; cur_pd <= 255; ++cur_pd) { | 2816 | for (cur_pd = pcd_min; cur_pd <= pcd_max; ++cur_pd) { |
3011 | unsigned long pck = lck / cur_pd; | 2817 | unsigned long pck = lck / cur_pd; |
3012 | long old_delta = abs(best_pck - req_pck); | 2818 | long old_delta = abs(best_pck - req_pck); |
3013 | long new_delta = abs(pck - req_pck); | 2819 | long new_delta = abs(pck - req_pck); |
@@ -3042,7 +2848,7 @@ int dispc_calc_clock_rates(unsigned long dispc_fclk_rate, | |||
3042 | { | 2848 | { |
3043 | if (cinfo->lck_div > 255 || cinfo->lck_div == 0) | 2849 | if (cinfo->lck_div > 255 || cinfo->lck_div == 0) |
3044 | return -EINVAL; | 2850 | return -EINVAL; |
3045 | if (cinfo->pck_div < 2 || cinfo->pck_div > 255) | 2851 | if (cinfo->pck_div < 1 || cinfo->pck_div > 255) |
3046 | return -EINVAL; | 2852 | return -EINVAL; |
3047 | 2853 | ||
3048 | cinfo->lck = dispc_fclk_rate / cinfo->lck_div; | 2854 | cinfo->lck = dispc_fclk_rate / cinfo->lck_div; |
@@ -3051,18 +2857,18 @@ int dispc_calc_clock_rates(unsigned long dispc_fclk_rate, | |||
3051 | return 0; | 2857 | return 0; |
3052 | } | 2858 | } |
3053 | 2859 | ||
3054 | int dispc_set_clock_div(enum omap_channel channel, | 2860 | int dispc_mgr_set_clock_div(enum omap_channel channel, |
3055 | struct dispc_clock_info *cinfo) | 2861 | struct dispc_clock_info *cinfo) |
3056 | { | 2862 | { |
3057 | DSSDBG("lck = %lu (%u)\n", cinfo->lck, cinfo->lck_div); | 2863 | DSSDBG("lck = %lu (%u)\n", cinfo->lck, cinfo->lck_div); |
3058 | DSSDBG("pck = %lu (%u)\n", cinfo->pck, cinfo->pck_div); | 2864 | DSSDBG("pck = %lu (%u)\n", cinfo->pck, cinfo->pck_div); |
3059 | 2865 | ||
3060 | dispc_set_lcd_divisor(channel, cinfo->lck_div, cinfo->pck_div); | 2866 | dispc_mgr_set_lcd_divisor(channel, cinfo->lck_div, cinfo->pck_div); |
3061 | 2867 | ||
3062 | return 0; | 2868 | return 0; |
3063 | } | 2869 | } |
3064 | 2870 | ||
3065 | int dispc_get_clock_div(enum omap_channel channel, | 2871 | int dispc_mgr_get_clock_div(enum omap_channel channel, |
3066 | struct dispc_clock_info *cinfo) | 2872 | struct dispc_clock_info *cinfo) |
3067 | { | 2873 | { |
3068 | unsigned long fck; | 2874 | unsigned long fck; |
@@ -3207,6 +3013,8 @@ static void print_irq_status(u32 status) | |||
3207 | PIS(OCP_ERR); | 3013 | PIS(OCP_ERR); |
3208 | PIS(VID1_FIFO_UNDERFLOW); | 3014 | PIS(VID1_FIFO_UNDERFLOW); |
3209 | PIS(VID2_FIFO_UNDERFLOW); | 3015 | PIS(VID2_FIFO_UNDERFLOW); |
3016 | if (dss_feat_get_num_ovls() > 3) | ||
3017 | PIS(VID3_FIFO_UNDERFLOW); | ||
3210 | PIS(SYNC_LOST); | 3018 | PIS(SYNC_LOST); |
3211 | PIS(SYNC_LOST_DIGIT); | 3019 | PIS(SYNC_LOST_DIGIT); |
3212 | if (dss_has_feature(FEAT_MGR_LCD2)) | 3020 | if (dss_has_feature(FEAT_MGR_LCD2)) |
@@ -3300,178 +3108,72 @@ static void dispc_error_worker(struct work_struct *work) | |||
3300 | int i; | 3108 | int i; |
3301 | u32 errors; | 3109 | u32 errors; |
3302 | unsigned long flags; | 3110 | unsigned long flags; |
3111 | static const unsigned fifo_underflow_bits[] = { | ||
3112 | DISPC_IRQ_GFX_FIFO_UNDERFLOW, | ||
3113 | DISPC_IRQ_VID1_FIFO_UNDERFLOW, | ||
3114 | DISPC_IRQ_VID2_FIFO_UNDERFLOW, | ||
3115 | DISPC_IRQ_VID3_FIFO_UNDERFLOW, | ||
3116 | }; | ||
3117 | |||
3118 | static const unsigned sync_lost_bits[] = { | ||
3119 | DISPC_IRQ_SYNC_LOST, | ||
3120 | DISPC_IRQ_SYNC_LOST_DIGIT, | ||
3121 | DISPC_IRQ_SYNC_LOST2, | ||
3122 | }; | ||
3303 | 3123 | ||
3304 | spin_lock_irqsave(&dispc.irq_lock, flags); | 3124 | spin_lock_irqsave(&dispc.irq_lock, flags); |
3305 | errors = dispc.error_irqs; | 3125 | errors = dispc.error_irqs; |
3306 | dispc.error_irqs = 0; | 3126 | dispc.error_irqs = 0; |
3307 | spin_unlock_irqrestore(&dispc.irq_lock, flags); | 3127 | spin_unlock_irqrestore(&dispc.irq_lock, flags); |
3308 | 3128 | ||
3309 | if (errors & DISPC_IRQ_GFX_FIFO_UNDERFLOW) { | 3129 | dispc_runtime_get(); |
3310 | DSSERR("GFX_FIFO_UNDERFLOW, disabling GFX\n"); | ||
3311 | for (i = 0; i < omap_dss_get_num_overlays(); ++i) { | ||
3312 | struct omap_overlay *ovl; | ||
3313 | ovl = omap_dss_get_overlay(i); | ||
3314 | |||
3315 | if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC)) | ||
3316 | continue; | ||
3317 | |||
3318 | if (ovl->id == 0) { | ||
3319 | dispc_enable_plane(ovl->id, 0); | ||
3320 | dispc_go(ovl->manager->id); | ||
3321 | mdelay(50); | ||
3322 | break; | ||
3323 | } | ||
3324 | } | ||
3325 | } | ||
3326 | |||
3327 | if (errors & DISPC_IRQ_VID1_FIFO_UNDERFLOW) { | ||
3328 | DSSERR("VID1_FIFO_UNDERFLOW, disabling VID1\n"); | ||
3329 | for (i = 0; i < omap_dss_get_num_overlays(); ++i) { | ||
3330 | struct omap_overlay *ovl; | ||
3331 | ovl = omap_dss_get_overlay(i); | ||
3332 | |||
3333 | if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC)) | ||
3334 | continue; | ||
3335 | |||
3336 | if (ovl->id == 1) { | ||
3337 | dispc_enable_plane(ovl->id, 0); | ||
3338 | dispc_go(ovl->manager->id); | ||
3339 | mdelay(50); | ||
3340 | break; | ||
3341 | } | ||
3342 | } | ||
3343 | } | ||
3344 | |||
3345 | if (errors & DISPC_IRQ_VID2_FIFO_UNDERFLOW) { | ||
3346 | DSSERR("VID2_FIFO_UNDERFLOW, disabling VID2\n"); | ||
3347 | for (i = 0; i < omap_dss_get_num_overlays(); ++i) { | ||
3348 | struct omap_overlay *ovl; | ||
3349 | ovl = omap_dss_get_overlay(i); | ||
3350 | |||
3351 | if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC)) | ||
3352 | continue; | ||
3353 | 3130 | ||
3354 | if (ovl->id == 2) { | 3131 | for (i = 0; i < omap_dss_get_num_overlays(); ++i) { |
3355 | dispc_enable_plane(ovl->id, 0); | 3132 | struct omap_overlay *ovl; |
3356 | dispc_go(ovl->manager->id); | 3133 | unsigned bit; |
3357 | mdelay(50); | ||
3358 | break; | ||
3359 | } | ||
3360 | } | ||
3361 | } | ||
3362 | |||
3363 | if (errors & DISPC_IRQ_SYNC_LOST) { | ||
3364 | struct omap_overlay_manager *manager = NULL; | ||
3365 | bool enable = false; | ||
3366 | 3134 | ||
3367 | DSSERR("SYNC_LOST, disabling LCD\n"); | 3135 | ovl = omap_dss_get_overlay(i); |
3136 | bit = fifo_underflow_bits[i]; | ||
3368 | 3137 | ||
3369 | for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) { | 3138 | if (bit & errors) { |
3370 | struct omap_overlay_manager *mgr; | 3139 | DSSERR("FIFO UNDERFLOW on %s, disabling the overlay\n", |
3371 | mgr = omap_dss_get_overlay_manager(i); | 3140 | ovl->name); |
3372 | 3141 | dispc_ovl_enable(ovl->id, false); | |
3373 | if (mgr->id == OMAP_DSS_CHANNEL_LCD) { | 3142 | dispc_mgr_go(ovl->manager->id); |
3374 | manager = mgr; | ||
3375 | enable = mgr->device->state == | ||
3376 | OMAP_DSS_DISPLAY_ACTIVE; | ||
3377 | mgr->device->driver->disable(mgr->device); | ||
3378 | break; | ||
3379 | } | ||
3380 | } | ||
3381 | |||
3382 | if (manager) { | ||
3383 | struct omap_dss_device *dssdev = manager->device; | ||
3384 | for (i = 0; i < omap_dss_get_num_overlays(); ++i) { | ||
3385 | struct omap_overlay *ovl; | ||
3386 | ovl = omap_dss_get_overlay(i); | ||
3387 | |||
3388 | if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC)) | ||
3389 | continue; | ||
3390 | |||
3391 | if (ovl->id != 0 && ovl->manager == manager) | ||
3392 | dispc_enable_plane(ovl->id, 0); | ||
3393 | } | ||
3394 | |||
3395 | dispc_go(manager->id); | ||
3396 | mdelay(50); | 3143 | mdelay(50); |
3397 | if (enable) | ||
3398 | dssdev->driver->enable(dssdev); | ||
3399 | } | 3144 | } |
3400 | } | 3145 | } |
3401 | 3146 | ||
3402 | if (errors & DISPC_IRQ_SYNC_LOST_DIGIT) { | 3147 | for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) { |
3403 | struct omap_overlay_manager *manager = NULL; | 3148 | struct omap_overlay_manager *mgr; |
3404 | bool enable = false; | 3149 | unsigned bit; |
3405 | 3150 | ||
3406 | DSSERR("SYNC_LOST_DIGIT, disabling TV\n"); | 3151 | mgr = omap_dss_get_overlay_manager(i); |
3152 | bit = sync_lost_bits[i]; | ||
3407 | 3153 | ||
3408 | for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) { | 3154 | if (bit & errors) { |
3409 | struct omap_overlay_manager *mgr; | 3155 | struct omap_dss_device *dssdev = mgr->device; |
3410 | mgr = omap_dss_get_overlay_manager(i); | 3156 | bool enable; |
3411 | 3157 | ||
3412 | if (mgr->id == OMAP_DSS_CHANNEL_DIGIT) { | 3158 | DSSERR("SYNC_LOST on channel %s, restarting the output " |
3413 | manager = mgr; | 3159 | "with video overlays disabled\n", |
3414 | enable = mgr->device->state == | 3160 | mgr->name); |
3415 | OMAP_DSS_DISPLAY_ACTIVE; | ||
3416 | mgr->device->driver->disable(mgr->device); | ||
3417 | break; | ||
3418 | } | ||
3419 | } | ||
3420 | 3161 | ||
3421 | if (manager) { | 3162 | enable = dssdev->state == OMAP_DSS_DISPLAY_ACTIVE; |
3422 | struct omap_dss_device *dssdev = manager->device; | 3163 | dssdev->driver->disable(dssdev); |
3423 | for (i = 0; i < omap_dss_get_num_overlays(); ++i) { | ||
3424 | struct omap_overlay *ovl; | ||
3425 | ovl = omap_dss_get_overlay(i); | ||
3426 | |||
3427 | if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC)) | ||
3428 | continue; | ||
3429 | |||
3430 | if (ovl->id != 0 && ovl->manager == manager) | ||
3431 | dispc_enable_plane(ovl->id, 0); | ||
3432 | } | ||
3433 | 3164 | ||
3434 | dispc_go(manager->id); | ||
3435 | mdelay(50); | ||
3436 | if (enable) | ||
3437 | dssdev->driver->enable(dssdev); | ||
3438 | } | ||
3439 | } | ||
3440 | |||
3441 | if (errors & DISPC_IRQ_SYNC_LOST2) { | ||
3442 | struct omap_overlay_manager *manager = NULL; | ||
3443 | bool enable = false; | ||
3444 | |||
3445 | DSSERR("SYNC_LOST for LCD2, disabling LCD2\n"); | ||
3446 | |||
3447 | for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) { | ||
3448 | struct omap_overlay_manager *mgr; | ||
3449 | mgr = omap_dss_get_overlay_manager(i); | ||
3450 | |||
3451 | if (mgr->id == OMAP_DSS_CHANNEL_LCD2) { | ||
3452 | manager = mgr; | ||
3453 | enable = mgr->device->state == | ||
3454 | OMAP_DSS_DISPLAY_ACTIVE; | ||
3455 | mgr->device->driver->disable(mgr->device); | ||
3456 | break; | ||
3457 | } | ||
3458 | } | ||
3459 | |||
3460 | if (manager) { | ||
3461 | struct omap_dss_device *dssdev = manager->device; | ||
3462 | for (i = 0; i < omap_dss_get_num_overlays(); ++i) { | 3165 | for (i = 0; i < omap_dss_get_num_overlays(); ++i) { |
3463 | struct omap_overlay *ovl; | 3166 | struct omap_overlay *ovl; |
3464 | ovl = omap_dss_get_overlay(i); | 3167 | ovl = omap_dss_get_overlay(i); |
3465 | 3168 | ||
3466 | if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC)) | 3169 | if (ovl->id != OMAP_DSS_GFX && |
3467 | continue; | 3170 | ovl->manager == mgr) |
3468 | 3171 | dispc_ovl_enable(ovl->id, false); | |
3469 | if (ovl->id != 0 && ovl->manager == manager) | ||
3470 | dispc_enable_plane(ovl->id, 0); | ||
3471 | } | 3172 | } |
3472 | 3173 | ||
3473 | dispc_go(manager->id); | 3174 | dispc_mgr_go(mgr->id); |
3474 | mdelay(50); | 3175 | mdelay(50); |
3176 | |||
3475 | if (enable) | 3177 | if (enable) |
3476 | dssdev->driver->enable(dssdev); | 3178 | dssdev->driver->enable(dssdev); |
3477 | } | 3179 | } |
@@ -3482,9 +3184,7 @@ static void dispc_error_worker(struct work_struct *work) | |||
3482 | for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) { | 3184 | for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) { |
3483 | struct omap_overlay_manager *mgr; | 3185 | struct omap_overlay_manager *mgr; |
3484 | mgr = omap_dss_get_overlay_manager(i); | 3186 | mgr = omap_dss_get_overlay_manager(i); |
3485 | 3187 | mgr->device->driver->disable(mgr->device); | |
3486 | if (mgr->caps & OMAP_DSS_OVL_CAP_DISPC) | ||
3487 | mgr->device->driver->disable(mgr->device); | ||
3488 | } | 3188 | } |
3489 | } | 3189 | } |
3490 | 3190 | ||
@@ -3492,6 +3192,8 @@ static void dispc_error_worker(struct work_struct *work) | |||
3492 | dispc.irq_error_mask |= errors; | 3192 | dispc.irq_error_mask |= errors; |
3493 | _omap_dispc_set_irqs(); | 3193 | _omap_dispc_set_irqs(); |
3494 | spin_unlock_irqrestore(&dispc.irq_lock, flags); | 3194 | spin_unlock_irqrestore(&dispc.irq_lock, flags); |
3195 | |||
3196 | dispc_runtime_put(); | ||
3495 | } | 3197 | } |
3496 | 3198 | ||
3497 | int omap_dispc_wait_for_irq_timeout(u32 irqmask, unsigned long timeout) | 3199 | int omap_dispc_wait_for_irq_timeout(u32 irqmask, unsigned long timeout) |
@@ -3586,6 +3288,8 @@ static void _omap_dispc_initialize_irq(void) | |||
3586 | dispc.irq_error_mask = DISPC_IRQ_MASK_ERROR; | 3288 | dispc.irq_error_mask = DISPC_IRQ_MASK_ERROR; |
3587 | if (dss_has_feature(FEAT_MGR_LCD2)) | 3289 | if (dss_has_feature(FEAT_MGR_LCD2)) |
3588 | dispc.irq_error_mask |= DISPC_IRQ_SYNC_LOST2; | 3290 | dispc.irq_error_mask |= DISPC_IRQ_SYNC_LOST2; |
3291 | if (dss_feat_get_num_ovls() > 3) | ||
3292 | dispc.irq_error_mask |= DISPC_IRQ_VID3_FIFO_UNDERFLOW; | ||
3589 | 3293 | ||
3590 | /* there's SYNC_LOST_DIGIT waiting after enabling the DSS, | 3294 | /* there's SYNC_LOST_DIGIT waiting after enabling the DSS, |
3591 | * so clear it */ | 3295 | * so clear it */ |
@@ -3635,6 +3339,8 @@ static void _omap_dispc_initial_config(void) | |||
3635 | dispc_read_plane_fifo_sizes(); | 3339 | dispc_read_plane_fifo_sizes(); |
3636 | 3340 | ||
3637 | dispc_configure_burst_sizes(); | 3341 | dispc_configure_burst_sizes(); |
3342 | |||
3343 | dispc_ovl_enable_zorder_planes(); | ||
3638 | } | 3344 | } |
3639 | 3345 | ||
3640 | /* DISPC HW IP initialisation */ | 3346 | /* DISPC HW IP initialisation */ |
@@ -3734,7 +3440,6 @@ static int omap_dispchw_remove(struct platform_device *pdev) | |||
3734 | static int dispc_runtime_suspend(struct device *dev) | 3440 | static int dispc_runtime_suspend(struct device *dev) |
3735 | { | 3441 | { |
3736 | dispc_save_context(); | 3442 | dispc_save_context(); |
3737 | clk_disable(dispc.dss_clk); | ||
3738 | dss_runtime_put(); | 3443 | dss_runtime_put(); |
3739 | 3444 | ||
3740 | return 0; | 3445 | return 0; |
@@ -3748,7 +3453,6 @@ static int dispc_runtime_resume(struct device *dev) | |||
3748 | if (r < 0) | 3453 | if (r < 0) |
3749 | return r; | 3454 | return r; |
3750 | 3455 | ||
3751 | clk_enable(dispc.dss_clk); | ||
3752 | dispc_restore_context(); | 3456 | dispc_restore_context(); |
3753 | 3457 | ||
3754 | return 0; | 3458 | return 0; |
diff --git a/drivers/video/omap2/dss/dispc.h b/drivers/video/omap2/dss/dispc.h index 6c9ee0a0efb3..c06efc38983e 100644 --- a/drivers/video/omap2/dss/dispc.h +++ b/drivers/video/omap2/dss/dispc.h | |||
@@ -291,6 +291,8 @@ static inline u16 DISPC_OVL_BASE(enum omap_plane plane) | |||
291 | return 0x00BC; | 291 | return 0x00BC; |
292 | case OMAP_DSS_VIDEO2: | 292 | case OMAP_DSS_VIDEO2: |
293 | return 0x014C; | 293 | return 0x014C; |
294 | case OMAP_DSS_VIDEO3: | ||
295 | return 0x0300; | ||
294 | default: | 296 | default: |
295 | BUG(); | 297 | BUG(); |
296 | } | 298 | } |
@@ -304,6 +306,8 @@ static inline u16 DISPC_BA0_OFFSET(enum omap_plane plane) | |||
304 | case OMAP_DSS_VIDEO1: | 306 | case OMAP_DSS_VIDEO1: |
305 | case OMAP_DSS_VIDEO2: | 307 | case OMAP_DSS_VIDEO2: |
306 | return 0x0000; | 308 | return 0x0000; |
309 | case OMAP_DSS_VIDEO3: | ||
310 | return 0x0008; | ||
307 | default: | 311 | default: |
308 | BUG(); | 312 | BUG(); |
309 | } | 313 | } |
@@ -316,6 +320,8 @@ static inline u16 DISPC_BA1_OFFSET(enum omap_plane plane) | |||
316 | case OMAP_DSS_VIDEO1: | 320 | case OMAP_DSS_VIDEO1: |
317 | case OMAP_DSS_VIDEO2: | 321 | case OMAP_DSS_VIDEO2: |
318 | return 0x0004; | 322 | return 0x0004; |
323 | case OMAP_DSS_VIDEO3: | ||
324 | return 0x000C; | ||
319 | default: | 325 | default: |
320 | BUG(); | 326 | BUG(); |
321 | } | 327 | } |
@@ -330,6 +336,8 @@ static inline u16 DISPC_BA0_UV_OFFSET(enum omap_plane plane) | |||
330 | return 0x0544; | 336 | return 0x0544; |
331 | case OMAP_DSS_VIDEO2: | 337 | case OMAP_DSS_VIDEO2: |
332 | return 0x04BC; | 338 | return 0x04BC; |
339 | case OMAP_DSS_VIDEO3: | ||
340 | return 0x0310; | ||
333 | default: | 341 | default: |
334 | BUG(); | 342 | BUG(); |
335 | } | 343 | } |
@@ -344,6 +352,8 @@ static inline u16 DISPC_BA1_UV_OFFSET(enum omap_plane plane) | |||
344 | return 0x0548; | 352 | return 0x0548; |
345 | case OMAP_DSS_VIDEO2: | 353 | case OMAP_DSS_VIDEO2: |
346 | return 0x04C0; | 354 | return 0x04C0; |
355 | case OMAP_DSS_VIDEO3: | ||
356 | return 0x0314; | ||
347 | default: | 357 | default: |
348 | BUG(); | 358 | BUG(); |
349 | } | 359 | } |
@@ -356,6 +366,8 @@ static inline u16 DISPC_POS_OFFSET(enum omap_plane plane) | |||
356 | case OMAP_DSS_VIDEO1: | 366 | case OMAP_DSS_VIDEO1: |
357 | case OMAP_DSS_VIDEO2: | 367 | case OMAP_DSS_VIDEO2: |
358 | return 0x0008; | 368 | return 0x0008; |
369 | case OMAP_DSS_VIDEO3: | ||
370 | return 0x009C; | ||
359 | default: | 371 | default: |
360 | BUG(); | 372 | BUG(); |
361 | } | 373 | } |
@@ -368,6 +380,8 @@ static inline u16 DISPC_SIZE_OFFSET(enum omap_plane plane) | |||
368 | case OMAP_DSS_VIDEO1: | 380 | case OMAP_DSS_VIDEO1: |
369 | case OMAP_DSS_VIDEO2: | 381 | case OMAP_DSS_VIDEO2: |
370 | return 0x000C; | 382 | return 0x000C; |
383 | case OMAP_DSS_VIDEO3: | ||
384 | return 0x00A8; | ||
371 | default: | 385 | default: |
372 | BUG(); | 386 | BUG(); |
373 | } | 387 | } |
@@ -381,6 +395,8 @@ static inline u16 DISPC_ATTR_OFFSET(enum omap_plane plane) | |||
381 | case OMAP_DSS_VIDEO1: | 395 | case OMAP_DSS_VIDEO1: |
382 | case OMAP_DSS_VIDEO2: | 396 | case OMAP_DSS_VIDEO2: |
383 | return 0x0010; | 397 | return 0x0010; |
398 | case OMAP_DSS_VIDEO3: | ||
399 | return 0x0070; | ||
384 | default: | 400 | default: |
385 | BUG(); | 401 | BUG(); |
386 | } | 402 | } |
@@ -395,6 +411,8 @@ static inline u16 DISPC_ATTR2_OFFSET(enum omap_plane plane) | |||
395 | return 0x0568; | 411 | return 0x0568; |
396 | case OMAP_DSS_VIDEO2: | 412 | case OMAP_DSS_VIDEO2: |
397 | return 0x04DC; | 413 | return 0x04DC; |
414 | case OMAP_DSS_VIDEO3: | ||
415 | return 0x032C; | ||
398 | default: | 416 | default: |
399 | BUG(); | 417 | BUG(); |
400 | } | 418 | } |
@@ -408,6 +426,8 @@ static inline u16 DISPC_FIFO_THRESH_OFFSET(enum omap_plane plane) | |||
408 | case OMAP_DSS_VIDEO1: | 426 | case OMAP_DSS_VIDEO1: |
409 | case OMAP_DSS_VIDEO2: | 427 | case OMAP_DSS_VIDEO2: |
410 | return 0x0014; | 428 | return 0x0014; |
429 | case OMAP_DSS_VIDEO3: | ||
430 | return 0x008C; | ||
411 | default: | 431 | default: |
412 | BUG(); | 432 | BUG(); |
413 | } | 433 | } |
@@ -421,6 +441,8 @@ static inline u16 DISPC_FIFO_SIZE_STATUS_OFFSET(enum omap_plane plane) | |||
421 | case OMAP_DSS_VIDEO1: | 441 | case OMAP_DSS_VIDEO1: |
422 | case OMAP_DSS_VIDEO2: | 442 | case OMAP_DSS_VIDEO2: |
423 | return 0x0018; | 443 | return 0x0018; |
444 | case OMAP_DSS_VIDEO3: | ||
445 | return 0x0088; | ||
424 | default: | 446 | default: |
425 | BUG(); | 447 | BUG(); |
426 | } | 448 | } |
@@ -434,6 +456,8 @@ static inline u16 DISPC_ROW_INC_OFFSET(enum omap_plane plane) | |||
434 | case OMAP_DSS_VIDEO1: | 456 | case OMAP_DSS_VIDEO1: |
435 | case OMAP_DSS_VIDEO2: | 457 | case OMAP_DSS_VIDEO2: |
436 | return 0x001C; | 458 | return 0x001C; |
459 | case OMAP_DSS_VIDEO3: | ||
460 | return 0x00A4; | ||
437 | default: | 461 | default: |
438 | BUG(); | 462 | BUG(); |
439 | } | 463 | } |
@@ -447,6 +471,8 @@ static inline u16 DISPC_PIX_INC_OFFSET(enum omap_plane plane) | |||
447 | case OMAP_DSS_VIDEO1: | 471 | case OMAP_DSS_VIDEO1: |
448 | case OMAP_DSS_VIDEO2: | 472 | case OMAP_DSS_VIDEO2: |
449 | return 0x0020; | 473 | return 0x0020; |
474 | case OMAP_DSS_VIDEO3: | ||
475 | return 0x0098; | ||
450 | default: | 476 | default: |
451 | BUG(); | 477 | BUG(); |
452 | } | 478 | } |
@@ -459,6 +485,7 @@ static inline u16 DISPC_WINDOW_SKIP_OFFSET(enum omap_plane plane) | |||
459 | return 0x0034; | 485 | return 0x0034; |
460 | case OMAP_DSS_VIDEO1: | 486 | case OMAP_DSS_VIDEO1: |
461 | case OMAP_DSS_VIDEO2: | 487 | case OMAP_DSS_VIDEO2: |
488 | case OMAP_DSS_VIDEO3: | ||
462 | BUG(); | 489 | BUG(); |
463 | default: | 490 | default: |
464 | BUG(); | 491 | BUG(); |
@@ -472,6 +499,7 @@ static inline u16 DISPC_TABLE_BA_OFFSET(enum omap_plane plane) | |||
472 | return 0x0038; | 499 | return 0x0038; |
473 | case OMAP_DSS_VIDEO1: | 500 | case OMAP_DSS_VIDEO1: |
474 | case OMAP_DSS_VIDEO2: | 501 | case OMAP_DSS_VIDEO2: |
502 | case OMAP_DSS_VIDEO3: | ||
475 | BUG(); | 503 | BUG(); |
476 | default: | 504 | default: |
477 | BUG(); | 505 | BUG(); |
@@ -486,6 +514,8 @@ static inline u16 DISPC_FIR_OFFSET(enum omap_plane plane) | |||
486 | case OMAP_DSS_VIDEO1: | 514 | case OMAP_DSS_VIDEO1: |
487 | case OMAP_DSS_VIDEO2: | 515 | case OMAP_DSS_VIDEO2: |
488 | return 0x0024; | 516 | return 0x0024; |
517 | case OMAP_DSS_VIDEO3: | ||
518 | return 0x0090; | ||
489 | default: | 519 | default: |
490 | BUG(); | 520 | BUG(); |
491 | } | 521 | } |
@@ -500,6 +530,8 @@ static inline u16 DISPC_FIR2_OFFSET(enum omap_plane plane) | |||
500 | return 0x0580; | 530 | return 0x0580; |
501 | case OMAP_DSS_VIDEO2: | 531 | case OMAP_DSS_VIDEO2: |
502 | return 0x055C; | 532 | return 0x055C; |
533 | case OMAP_DSS_VIDEO3: | ||
534 | return 0x0424; | ||
503 | default: | 535 | default: |
504 | BUG(); | 536 | BUG(); |
505 | } | 537 | } |
@@ -513,6 +545,8 @@ static inline u16 DISPC_PIC_SIZE_OFFSET(enum omap_plane plane) | |||
513 | case OMAP_DSS_VIDEO1: | 545 | case OMAP_DSS_VIDEO1: |
514 | case OMAP_DSS_VIDEO2: | 546 | case OMAP_DSS_VIDEO2: |
515 | return 0x0028; | 547 | return 0x0028; |
548 | case OMAP_DSS_VIDEO3: | ||
549 | return 0x0094; | ||
516 | default: | 550 | default: |
517 | BUG(); | 551 | BUG(); |
518 | } | 552 | } |
@@ -527,6 +561,8 @@ static inline u16 DISPC_ACCU0_OFFSET(enum omap_plane plane) | |||
527 | case OMAP_DSS_VIDEO1: | 561 | case OMAP_DSS_VIDEO1: |
528 | case OMAP_DSS_VIDEO2: | 562 | case OMAP_DSS_VIDEO2: |
529 | return 0x002C; | 563 | return 0x002C; |
564 | case OMAP_DSS_VIDEO3: | ||
565 | return 0x0000; | ||
530 | default: | 566 | default: |
531 | BUG(); | 567 | BUG(); |
532 | } | 568 | } |
@@ -541,6 +577,8 @@ static inline u16 DISPC_ACCU2_0_OFFSET(enum omap_plane plane) | |||
541 | return 0x0584; | 577 | return 0x0584; |
542 | case OMAP_DSS_VIDEO2: | 578 | case OMAP_DSS_VIDEO2: |
543 | return 0x0560; | 579 | return 0x0560; |
580 | case OMAP_DSS_VIDEO3: | ||
581 | return 0x0428; | ||
544 | default: | 582 | default: |
545 | BUG(); | 583 | BUG(); |
546 | } | 584 | } |
@@ -554,6 +592,8 @@ static inline u16 DISPC_ACCU1_OFFSET(enum omap_plane plane) | |||
554 | case OMAP_DSS_VIDEO1: | 592 | case OMAP_DSS_VIDEO1: |
555 | case OMAP_DSS_VIDEO2: | 593 | case OMAP_DSS_VIDEO2: |
556 | return 0x0030; | 594 | return 0x0030; |
595 | case OMAP_DSS_VIDEO3: | ||
596 | return 0x0004; | ||
557 | default: | 597 | default: |
558 | BUG(); | 598 | BUG(); |
559 | } | 599 | } |
@@ -568,6 +608,8 @@ static inline u16 DISPC_ACCU2_1_OFFSET(enum omap_plane plane) | |||
568 | return 0x0588; | 608 | return 0x0588; |
569 | case OMAP_DSS_VIDEO2: | 609 | case OMAP_DSS_VIDEO2: |
570 | return 0x0564; | 610 | return 0x0564; |
611 | case OMAP_DSS_VIDEO3: | ||
612 | return 0x042C; | ||
571 | default: | 613 | default: |
572 | BUG(); | 614 | BUG(); |
573 | } | 615 | } |
@@ -582,6 +624,8 @@ static inline u16 DISPC_FIR_COEF_H_OFFSET(enum omap_plane plane, u16 i) | |||
582 | case OMAP_DSS_VIDEO1: | 624 | case OMAP_DSS_VIDEO1: |
583 | case OMAP_DSS_VIDEO2: | 625 | case OMAP_DSS_VIDEO2: |
584 | return 0x0034 + i * 0x8; | 626 | return 0x0034 + i * 0x8; |
627 | case OMAP_DSS_VIDEO3: | ||
628 | return 0x0010 + i * 0x8; | ||
585 | default: | 629 | default: |
586 | BUG(); | 630 | BUG(); |
587 | } | 631 | } |
@@ -597,6 +641,8 @@ static inline u16 DISPC_FIR_COEF_H2_OFFSET(enum omap_plane plane, u16 i) | |||
597 | return 0x058C + i * 0x8; | 641 | return 0x058C + i * 0x8; |
598 | case OMAP_DSS_VIDEO2: | 642 | case OMAP_DSS_VIDEO2: |
599 | return 0x0568 + i * 0x8; | 643 | return 0x0568 + i * 0x8; |
644 | case OMAP_DSS_VIDEO3: | ||
645 | return 0x0430 + i * 0x8; | ||
600 | default: | 646 | default: |
601 | BUG(); | 647 | BUG(); |
602 | } | 648 | } |
@@ -611,6 +657,8 @@ static inline u16 DISPC_FIR_COEF_HV_OFFSET(enum omap_plane plane, u16 i) | |||
611 | case OMAP_DSS_VIDEO1: | 657 | case OMAP_DSS_VIDEO1: |
612 | case OMAP_DSS_VIDEO2: | 658 | case OMAP_DSS_VIDEO2: |
613 | return 0x0038 + i * 0x8; | 659 | return 0x0038 + i * 0x8; |
660 | case OMAP_DSS_VIDEO3: | ||
661 | return 0x0014 + i * 0x8; | ||
614 | default: | 662 | default: |
615 | BUG(); | 663 | BUG(); |
616 | } | 664 | } |
@@ -626,6 +674,8 @@ static inline u16 DISPC_FIR_COEF_HV2_OFFSET(enum omap_plane plane, u16 i) | |||
626 | return 0x0590 + i * 8; | 674 | return 0x0590 + i * 8; |
627 | case OMAP_DSS_VIDEO2: | 675 | case OMAP_DSS_VIDEO2: |
628 | return 0x056C + i * 0x8; | 676 | return 0x056C + i * 0x8; |
677 | case OMAP_DSS_VIDEO3: | ||
678 | return 0x0434 + i * 0x8; | ||
629 | default: | 679 | default: |
630 | BUG(); | 680 | BUG(); |
631 | } | 681 | } |
@@ -639,6 +689,7 @@ static inline u16 DISPC_CONV_COEF_OFFSET(enum omap_plane plane, u16 i) | |||
639 | BUG(); | 689 | BUG(); |
640 | case OMAP_DSS_VIDEO1: | 690 | case OMAP_DSS_VIDEO1: |
641 | case OMAP_DSS_VIDEO2: | 691 | case OMAP_DSS_VIDEO2: |
692 | case OMAP_DSS_VIDEO3: | ||
642 | return 0x0074 + i * 0x4; | 693 | return 0x0074 + i * 0x4; |
643 | default: | 694 | default: |
644 | BUG(); | 695 | BUG(); |
@@ -655,6 +706,8 @@ static inline u16 DISPC_FIR_COEF_V_OFFSET(enum omap_plane plane, u16 i) | |||
655 | return 0x0124 + i * 0x4; | 706 | return 0x0124 + i * 0x4; |
656 | case OMAP_DSS_VIDEO2: | 707 | case OMAP_DSS_VIDEO2: |
657 | return 0x00B4 + i * 0x4; | 708 | return 0x00B4 + i * 0x4; |
709 | case OMAP_DSS_VIDEO3: | ||
710 | return 0x0050 + i * 0x4; | ||
658 | default: | 711 | default: |
659 | BUG(); | 712 | BUG(); |
660 | } | 713 | } |
@@ -670,6 +723,8 @@ static inline u16 DISPC_FIR_COEF_V2_OFFSET(enum omap_plane plane, u16 i) | |||
670 | return 0x05CC + i * 0x4; | 723 | return 0x05CC + i * 0x4; |
671 | case OMAP_DSS_VIDEO2: | 724 | case OMAP_DSS_VIDEO2: |
672 | return 0x05A8 + i * 0x4; | 725 | return 0x05A8 + i * 0x4; |
726 | case OMAP_DSS_VIDEO3: | ||
727 | return 0x0470 + i * 0x4; | ||
673 | default: | 728 | default: |
674 | BUG(); | 729 | BUG(); |
675 | } | 730 | } |
@@ -684,6 +739,8 @@ static inline u16 DISPC_PRELOAD_OFFSET(enum omap_plane plane) | |||
684 | return 0x0174; | 739 | return 0x0174; |
685 | case OMAP_DSS_VIDEO2: | 740 | case OMAP_DSS_VIDEO2: |
686 | return 0x00E8; | 741 | return 0x00E8; |
742 | case OMAP_DSS_VIDEO3: | ||
743 | return 0x00A0; | ||
687 | default: | 744 | default: |
688 | BUG(); | 745 | BUG(); |
689 | } | 746 | } |
diff --git a/drivers/video/omap2/dss/display.c b/drivers/video/omap2/dss/display.c index 94495e45ec5a..be331dc5a61b 100644 --- a/drivers/video/omap2/dss/display.c +++ b/drivers/video/omap2/dss/display.c | |||
@@ -45,14 +45,13 @@ static ssize_t display_enabled_store(struct device *dev, | |||
45 | const char *buf, size_t size) | 45 | const char *buf, size_t size) |
46 | { | 46 | { |
47 | struct omap_dss_device *dssdev = to_dss_device(dev); | 47 | struct omap_dss_device *dssdev = to_dss_device(dev); |
48 | int r, enabled; | 48 | int r; |
49 | bool enabled; | ||
49 | 50 | ||
50 | r = kstrtoint(buf, 0, &enabled); | 51 | r = strtobool(buf, &enabled); |
51 | if (r) | 52 | if (r) |
52 | return r; | 53 | return r; |
53 | 54 | ||
54 | enabled = !!enabled; | ||
55 | |||
56 | if (enabled != (dssdev->state != OMAP_DSS_DISPLAY_DISABLED)) { | 55 | if (enabled != (dssdev->state != OMAP_DSS_DISPLAY_DISABLED)) { |
57 | if (enabled) { | 56 | if (enabled) { |
58 | r = dssdev->driver->enable(dssdev); | 57 | r = dssdev->driver->enable(dssdev); |
@@ -79,17 +78,16 @@ static ssize_t display_tear_store(struct device *dev, | |||
79 | struct device_attribute *attr, const char *buf, size_t size) | 78 | struct device_attribute *attr, const char *buf, size_t size) |
80 | { | 79 | { |
81 | struct omap_dss_device *dssdev = to_dss_device(dev); | 80 | struct omap_dss_device *dssdev = to_dss_device(dev); |
82 | int te, r; | 81 | int r; |
82 | bool te; | ||
83 | 83 | ||
84 | if (!dssdev->driver->enable_te || !dssdev->driver->get_te) | 84 | if (!dssdev->driver->enable_te || !dssdev->driver->get_te) |
85 | return -ENOENT; | 85 | return -ENOENT; |
86 | 86 | ||
87 | r = kstrtoint(buf, 0, &te); | 87 | r = strtobool(buf, &te); |
88 | if (r) | 88 | if (r) |
89 | return r; | 89 | return r; |
90 | 90 | ||
91 | te = !!te; | ||
92 | |||
93 | r = dssdev->driver->enable_te(dssdev, te); | 91 | r = dssdev->driver->enable_te(dssdev, te); |
94 | if (r) | 92 | if (r) |
95 | return r; | 93 | return r; |
@@ -195,17 +193,16 @@ static ssize_t display_mirror_store(struct device *dev, | |||
195 | struct device_attribute *attr, const char *buf, size_t size) | 193 | struct device_attribute *attr, const char *buf, size_t size) |
196 | { | 194 | { |
197 | struct omap_dss_device *dssdev = to_dss_device(dev); | 195 | struct omap_dss_device *dssdev = to_dss_device(dev); |
198 | int mirror, r; | 196 | int r; |
197 | bool mirror; | ||
199 | 198 | ||
200 | if (!dssdev->driver->set_mirror || !dssdev->driver->get_mirror) | 199 | if (!dssdev->driver->set_mirror || !dssdev->driver->get_mirror) |
201 | return -ENOENT; | 200 | return -ENOENT; |
202 | 201 | ||
203 | r = kstrtoint(buf, 0, &mirror); | 202 | r = strtobool(buf, &mirror); |
204 | if (r) | 203 | if (r) |
205 | return r; | 204 | return r; |
206 | 205 | ||
207 | mirror = !!mirror; | ||
208 | |||
209 | r = dssdev->driver->set_mirror(dssdev, mirror); | 206 | r = dssdev->driver->set_mirror(dssdev, mirror); |
210 | if (r) | 207 | if (r) |
211 | return r; | 208 | return r; |
@@ -302,11 +299,15 @@ int omapdss_default_get_recommended_bpp(struct omap_dss_device *dssdev) | |||
302 | return 16; | 299 | return 16; |
303 | 300 | ||
304 | case OMAP_DISPLAY_TYPE_DBI: | 301 | case OMAP_DISPLAY_TYPE_DBI: |
305 | case OMAP_DISPLAY_TYPE_DSI: | ||
306 | if (dssdev->ctrl.pixel_size == 24) | 302 | if (dssdev->ctrl.pixel_size == 24) |
307 | return 24; | 303 | return 24; |
308 | else | 304 | else |
309 | return 16; | 305 | return 16; |
306 | case OMAP_DISPLAY_TYPE_DSI: | ||
307 | if (dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt) > 16) | ||
308 | return 24; | ||
309 | else | ||
310 | return 16; | ||
310 | case OMAP_DISPLAY_TYPE_VENC: | 311 | case OMAP_DISPLAY_TYPE_VENC: |
311 | case OMAP_DISPLAY_TYPE_SDI: | 312 | case OMAP_DISPLAY_TYPE_SDI: |
312 | case OMAP_DISPLAY_TYPE_HDMI: | 313 | case OMAP_DISPLAY_TYPE_HDMI: |
@@ -342,9 +343,11 @@ bool dss_use_replication(struct omap_dss_device *dssdev, | |||
342 | bpp = 24; | 343 | bpp = 24; |
343 | break; | 344 | break; |
344 | case OMAP_DISPLAY_TYPE_DBI: | 345 | case OMAP_DISPLAY_TYPE_DBI: |
345 | case OMAP_DISPLAY_TYPE_DSI: | ||
346 | bpp = dssdev->ctrl.pixel_size; | 346 | bpp = dssdev->ctrl.pixel_size; |
347 | break; | 347 | break; |
348 | case OMAP_DISPLAY_TYPE_DSI: | ||
349 | bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt); | ||
350 | break; | ||
348 | default: | 351 | default: |
349 | BUG(); | 352 | BUG(); |
350 | } | 353 | } |
diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c index f053b180ecd7..483888a85cfd 100644 --- a/drivers/video/omap2/dss/dpi.c +++ b/drivers/video/omap2/dss/dpi.c | |||
@@ -82,9 +82,11 @@ static int dpi_set_dsi_clk(struct omap_dss_device *dssdev, bool is_tft, | |||
82 | 82 | ||
83 | dss_select_dispc_clk_source(dssdev->clocks.dispc.dispc_fclk_src); | 83 | dss_select_dispc_clk_source(dssdev->clocks.dispc.dispc_fclk_src); |
84 | 84 | ||
85 | r = dispc_set_clock_div(dssdev->manager->id, &dispc_cinfo); | 85 | r = dispc_mgr_set_clock_div(dssdev->manager->id, &dispc_cinfo); |
86 | if (r) | 86 | if (r) { |
87 | dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK); | ||
87 | return r; | 88 | return r; |
89 | } | ||
88 | 90 | ||
89 | *fck = dsi_cinfo.dsi_pll_hsdiv_dispc_clk; | 91 | *fck = dsi_cinfo.dsi_pll_hsdiv_dispc_clk; |
90 | *lck_div = dispc_cinfo.lck_div; | 92 | *lck_div = dispc_cinfo.lck_div; |
@@ -109,7 +111,7 @@ static int dpi_set_dispc_clk(struct omap_dss_device *dssdev, bool is_tft, | |||
109 | if (r) | 111 | if (r) |
110 | return r; | 112 | return r; |
111 | 113 | ||
112 | r = dispc_set_clock_div(dssdev->manager->id, &dispc_cinfo); | 114 | r = dispc_mgr_set_clock_div(dssdev->manager->id, &dispc_cinfo); |
113 | if (r) | 115 | if (r) |
114 | return r; | 116 | return r; |
115 | 117 | ||
@@ -129,7 +131,7 @@ static int dpi_set_mode(struct omap_dss_device *dssdev) | |||
129 | bool is_tft; | 131 | bool is_tft; |
130 | int r = 0; | 132 | int r = 0; |
131 | 133 | ||
132 | dispc_set_pol_freq(dssdev->manager->id, dssdev->panel.config, | 134 | dispc_mgr_set_pol_freq(dssdev->manager->id, dssdev->panel.config, |
133 | dssdev->panel.acbi, dssdev->panel.acb); | 135 | dssdev->panel.acbi, dssdev->panel.acb); |
134 | 136 | ||
135 | is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0; | 137 | is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0; |
@@ -153,7 +155,7 @@ static int dpi_set_mode(struct omap_dss_device *dssdev) | |||
153 | t->pixel_clock = pck; | 155 | t->pixel_clock = pck; |
154 | } | 156 | } |
155 | 157 | ||
156 | dispc_set_lcd_timings(dssdev->manager->id, t); | 158 | dispc_mgr_set_lcd_timings(dssdev->manager->id, t); |
157 | 159 | ||
158 | return 0; | 160 | return 0; |
159 | } | 161 | } |
@@ -164,11 +166,12 @@ static void dpi_basic_init(struct omap_dss_device *dssdev) | |||
164 | 166 | ||
165 | is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0; | 167 | is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0; |
166 | 168 | ||
167 | dispc_set_parallel_interface_mode(dssdev->manager->id, | 169 | dispc_mgr_set_io_pad_mode(DSS_IO_PAD_MODE_BYPASS); |
168 | OMAP_DSS_PARALLELMODE_BYPASS); | 170 | dispc_mgr_enable_stallmode(dssdev->manager->id, false); |
169 | dispc_set_lcd_display_type(dssdev->manager->id, is_tft ? | 171 | |
172 | dispc_mgr_set_lcd_display_type(dssdev->manager->id, is_tft ? | ||
170 | OMAP_DSS_LCD_DISPLAY_TFT : OMAP_DSS_LCD_DISPLAY_STN); | 173 | OMAP_DSS_LCD_DISPLAY_TFT : OMAP_DSS_LCD_DISPLAY_STN); |
171 | dispc_set_tft_data_lines(dssdev->manager->id, | 174 | dispc_mgr_set_tft_data_lines(dssdev->manager->id, |
172 | dssdev->phy.dpi.data_lines); | 175 | dssdev->phy.dpi.data_lines); |
173 | } | 176 | } |
174 | 177 | ||
@@ -176,6 +179,11 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev) | |||
176 | { | 179 | { |
177 | int r; | 180 | int r; |
178 | 181 | ||
182 | if (dssdev->manager == NULL) { | ||
183 | DSSERR("failed to enable display: no manager\n"); | ||
184 | return -ENODEV; | ||
185 | } | ||
186 | |||
179 | r = omap_dss_start_device(dssdev); | 187 | r = omap_dss_start_device(dssdev); |
180 | if (r) { | 188 | if (r) { |
181 | DSSERR("failed to start device\n"); | 189 | DSSERR("failed to start device\n"); |
@@ -277,7 +285,7 @@ void dpi_set_timings(struct omap_dss_device *dssdev, | |||
277 | } | 285 | } |
278 | 286 | ||
279 | dpi_set_mode(dssdev); | 287 | dpi_set_mode(dssdev); |
280 | dispc_go(dssdev->manager->id); | 288 | dispc_mgr_go(dssdev->manager->id); |
281 | 289 | ||
282 | dispc_runtime_put(); | 290 | dispc_runtime_put(); |
283 | dss_runtime_put(); | 291 | dss_runtime_put(); |
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index 7adbbeb84334..43c04a9889c4 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c | |||
@@ -39,6 +39,7 @@ | |||
39 | #include <linux/pm_runtime.h> | 39 | #include <linux/pm_runtime.h> |
40 | 40 | ||
41 | #include <video/omapdss.h> | 41 | #include <video/omapdss.h> |
42 | #include <video/mipi_display.h> | ||
42 | #include <plat/clock.h> | 43 | #include <plat/clock.h> |
43 | 44 | ||
44 | #include "dss.h" | 45 | #include "dss.h" |
@@ -131,7 +132,7 @@ struct dsi_reg { u16 idx; }; | |||
131 | #define DSI_IRQ_TA_TIMEOUT (1 << 20) | 132 | #define DSI_IRQ_TA_TIMEOUT (1 << 20) |
132 | #define DSI_IRQ_ERROR_MASK \ | 133 | #define DSI_IRQ_ERROR_MASK \ |
133 | (DSI_IRQ_HS_TX_TIMEOUT | DSI_IRQ_LP_RX_TIMEOUT | DSI_IRQ_SYNC_LOST | \ | 134 | (DSI_IRQ_HS_TX_TIMEOUT | DSI_IRQ_LP_RX_TIMEOUT | DSI_IRQ_SYNC_LOST | \ |
134 | DSI_IRQ_TA_TIMEOUT) | 135 | DSI_IRQ_TA_TIMEOUT | DSI_IRQ_SYNC_LOST) |
135 | #define DSI_IRQ_CHANNEL_MASK 0xf | 136 | #define DSI_IRQ_CHANNEL_MASK 0xf |
136 | 137 | ||
137 | /* Virtual channel interrupts */ | 138 | /* Virtual channel interrupts */ |
@@ -198,18 +199,6 @@ struct dsi_reg { u16 idx; }; | |||
198 | DSI_CIO_IRQ_ERRCONTENTIONLP0_4 | DSI_CIO_IRQ_ERRCONTENTIONLP1_4 | \ | 199 | DSI_CIO_IRQ_ERRCONTENTIONLP0_4 | DSI_CIO_IRQ_ERRCONTENTIONLP1_4 | \ |
199 | DSI_CIO_IRQ_ERRCONTENTIONLP0_5 | DSI_CIO_IRQ_ERRCONTENTIONLP1_5) | 200 | DSI_CIO_IRQ_ERRCONTENTIONLP0_5 | DSI_CIO_IRQ_ERRCONTENTIONLP1_5) |
200 | 201 | ||
201 | #define DSI_DT_DCS_SHORT_WRITE_0 0x05 | ||
202 | #define DSI_DT_DCS_SHORT_WRITE_1 0x15 | ||
203 | #define DSI_DT_DCS_READ 0x06 | ||
204 | #define DSI_DT_SET_MAX_RET_PKG_SIZE 0x37 | ||
205 | #define DSI_DT_NULL_PACKET 0x09 | ||
206 | #define DSI_DT_DCS_LONG_WRITE 0x39 | ||
207 | |||
208 | #define DSI_DT_RX_ACK_WITH_ERR 0x02 | ||
209 | #define DSI_DT_RX_DCS_LONG_READ 0x1c | ||
210 | #define DSI_DT_RX_SHORT_READ_1 0x21 | ||
211 | #define DSI_DT_RX_SHORT_READ_2 0x22 | ||
212 | |||
213 | typedef void (*omap_dsi_isr_t) (void *arg, u32 mask); | 202 | typedef void (*omap_dsi_isr_t) (void *arg, u32 mask); |
214 | 203 | ||
215 | #define DSI_MAX_NR_ISRS 2 | 204 | #define DSI_MAX_NR_ISRS 2 |
@@ -228,9 +217,9 @@ enum fifo_size { | |||
228 | DSI_FIFO_SIZE_128 = 4, | 217 | DSI_FIFO_SIZE_128 = 4, |
229 | }; | 218 | }; |
230 | 219 | ||
231 | enum dsi_vc_mode { | 220 | enum dsi_vc_source { |
232 | DSI_VC_MODE_L4 = 0, | 221 | DSI_VC_SOURCE_L4 = 0, |
233 | DSI_VC_MODE_VP, | 222 | DSI_VC_SOURCE_VP, |
234 | }; | 223 | }; |
235 | 224 | ||
236 | enum dsi_lane { | 225 | enum dsi_lane { |
@@ -274,7 +263,8 @@ struct dsi_data { | |||
274 | struct clk *dss_clk; | 263 | struct clk *dss_clk; |
275 | struct clk *sys_clk; | 264 | struct clk *sys_clk; |
276 | 265 | ||
277 | void (*dsi_mux_pads)(bool enable); | 266 | int (*enable_pads)(int dsi_id, unsigned lane_mask); |
267 | void (*disable_pads)(int dsi_id, unsigned lane_mask); | ||
278 | 268 | ||
279 | struct dsi_clock_info current_cinfo; | 269 | struct dsi_clock_info current_cinfo; |
280 | 270 | ||
@@ -282,7 +272,7 @@ struct dsi_data { | |||
282 | struct regulator *vdds_dsi_reg; | 272 | struct regulator *vdds_dsi_reg; |
283 | 273 | ||
284 | struct { | 274 | struct { |
285 | enum dsi_vc_mode mode; | 275 | enum dsi_vc_source source; |
286 | struct omap_dss_device *dssdev; | 276 | struct omap_dss_device *dssdev; |
287 | enum fifo_size fifo_size; | 277 | enum fifo_size fifo_size; |
288 | int vc_id; | 278 | int vc_id; |
@@ -368,14 +358,9 @@ struct platform_device *dsi_get_dsidev_from_id(int module) | |||
368 | return dsi_pdev_map[module]; | 358 | return dsi_pdev_map[module]; |
369 | } | 359 | } |
370 | 360 | ||
371 | static int dsi_get_dsidev_id(struct platform_device *dsidev) | 361 | static inline int dsi_get_dsidev_id(struct platform_device *dsidev) |
372 | { | 362 | { |
373 | /* TEMP: Pass 0 as the dsi module index till the time the dsi platform | 363 | return dsidev->id; |
374 | * device names aren't changed to the form "omapdss_dsi.0", | ||
375 | * "omapdss_dsi.1" and so on */ | ||
376 | BUG_ON(dsidev->id != -1); | ||
377 | |||
378 | return 0; | ||
379 | } | 364 | } |
380 | 365 | ||
381 | static inline void dsi_write_reg(struct platform_device *dsidev, | 366 | static inline void dsi_write_reg(struct platform_device *dsidev, |
@@ -437,6 +422,21 @@ static inline int wait_for_bit_change(struct platform_device *dsidev, | |||
437 | return value; | 422 | return value; |
438 | } | 423 | } |
439 | 424 | ||
425 | u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt) | ||
426 | { | ||
427 | switch (fmt) { | ||
428 | case OMAP_DSS_DSI_FMT_RGB888: | ||
429 | case OMAP_DSS_DSI_FMT_RGB666: | ||
430 | return 24; | ||
431 | case OMAP_DSS_DSI_FMT_RGB666_PACKED: | ||
432 | return 18; | ||
433 | case OMAP_DSS_DSI_FMT_RGB565: | ||
434 | return 16; | ||
435 | default: | ||
436 | BUG(); | ||
437 | } | ||
438 | } | ||
439 | |||
440 | #ifdef DEBUG | 440 | #ifdef DEBUG |
441 | static void dsi_perf_mark_setup(struct platform_device *dsidev) | 441 | static void dsi_perf_mark_setup(struct platform_device *dsidev) |
442 | { | 442 | { |
@@ -453,6 +453,7 @@ static void dsi_perf_mark_start(struct platform_device *dsidev) | |||
453 | static void dsi_perf_show(struct platform_device *dsidev, const char *name) | 453 | static void dsi_perf_show(struct platform_device *dsidev, const char *name) |
454 | { | 454 | { |
455 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | 455 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
456 | struct omap_dss_device *dssdev = dsi->update_region.device; | ||
456 | ktime_t t, setup_time, trans_time; | 457 | ktime_t t, setup_time, trans_time; |
457 | u32 total_bytes; | 458 | u32 total_bytes; |
458 | u32 setup_us, trans_us, total_us; | 459 | u32 setup_us, trans_us, total_us; |
@@ -476,7 +477,7 @@ static void dsi_perf_show(struct platform_device *dsidev, const char *name) | |||
476 | 477 | ||
477 | total_bytes = dsi->update_region.w * | 478 | total_bytes = dsi->update_region.w * |
478 | dsi->update_region.h * | 479 | dsi->update_region.h * |
479 | dsi->update_region.device->ctrl.pixel_size / 8; | 480 | dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt) / 8; |
480 | 481 | ||
481 | printk(KERN_INFO "DSI(%s): %u us + %u us = %u us (%uHz), " | 482 | printk(KERN_INFO "DSI(%s): %u us + %u us = %u us (%uHz), " |
482 | "%u bytes, %u kbytes/sec\n", | 483 | "%u bytes, %u kbytes/sec\n", |
@@ -1287,7 +1288,7 @@ static int dsi_calc_clock_rates(struct omap_dss_device *dssdev, | |||
1287 | * with DSS_SYS_CLK source also */ | 1288 | * with DSS_SYS_CLK source also */ |
1288 | cinfo->highfreq = 0; | 1289 | cinfo->highfreq = 0; |
1289 | } else { | 1290 | } else { |
1290 | cinfo->clkin = dispc_pclk_rate(dssdev->manager->id); | 1291 | cinfo->clkin = dispc_mgr_pclk_rate(dssdev->manager->id); |
1291 | 1292 | ||
1292 | if (cinfo->clkin < 32000000) | 1293 | if (cinfo->clkin < 32000000) |
1293 | cinfo->highfreq = 0; | 1294 | cinfo->highfreq = 0; |
@@ -2360,6 +2361,24 @@ static int dsi_cio_wait_tx_clk_esc_reset(struct omap_dss_device *dssdev) | |||
2360 | return 0; | 2361 | return 0; |
2361 | } | 2362 | } |
2362 | 2363 | ||
2364 | static unsigned dsi_get_lane_mask(struct omap_dss_device *dssdev) | ||
2365 | { | ||
2366 | unsigned lanes = 0; | ||
2367 | |||
2368 | if (dssdev->phy.dsi.clk_lane != 0) | ||
2369 | lanes |= 1 << (dssdev->phy.dsi.clk_lane - 1); | ||
2370 | if (dssdev->phy.dsi.data1_lane != 0) | ||
2371 | lanes |= 1 << (dssdev->phy.dsi.data1_lane - 1); | ||
2372 | if (dssdev->phy.dsi.data2_lane != 0) | ||
2373 | lanes |= 1 << (dssdev->phy.dsi.data2_lane - 1); | ||
2374 | if (dssdev->phy.dsi.data3_lane != 0) | ||
2375 | lanes |= 1 << (dssdev->phy.dsi.data3_lane - 1); | ||
2376 | if (dssdev->phy.dsi.data4_lane != 0) | ||
2377 | lanes |= 1 << (dssdev->phy.dsi.data4_lane - 1); | ||
2378 | |||
2379 | return lanes; | ||
2380 | } | ||
2381 | |||
2363 | static int dsi_cio_init(struct omap_dss_device *dssdev) | 2382 | static int dsi_cio_init(struct omap_dss_device *dssdev) |
2364 | { | 2383 | { |
2365 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | 2384 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); |
@@ -2370,8 +2389,9 @@ static int dsi_cio_init(struct omap_dss_device *dssdev) | |||
2370 | 2389 | ||
2371 | DSSDBGF(); | 2390 | DSSDBGF(); |
2372 | 2391 | ||
2373 | if (dsi->dsi_mux_pads) | 2392 | r = dsi->enable_pads(dsidev->id, dsi_get_lane_mask(dssdev)); |
2374 | dsi->dsi_mux_pads(true); | 2393 | if (r) |
2394 | return r; | ||
2375 | 2395 | ||
2376 | dsi_enable_scp_clk(dsidev); | 2396 | dsi_enable_scp_clk(dsidev); |
2377 | 2397 | ||
@@ -2452,6 +2472,12 @@ static int dsi_cio_init(struct omap_dss_device *dssdev) | |||
2452 | 2472 | ||
2453 | dsi_cio_timings(dsidev); | 2473 | dsi_cio_timings(dsidev); |
2454 | 2474 | ||
2475 | if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) { | ||
2476 | /* DDR_CLK_ALWAYS_ON */ | ||
2477 | REG_FLD_MOD(dsidev, DSI_CLK_CTRL, | ||
2478 | dssdev->panel.dsi_vm_data.ddr_clk_always_on, 13, 13); | ||
2479 | } | ||
2480 | |||
2455 | dsi->ulps_enabled = false; | 2481 | dsi->ulps_enabled = false; |
2456 | 2482 | ||
2457 | DSSDBG("CIO init done\n"); | 2483 | DSSDBG("CIO init done\n"); |
@@ -2467,19 +2493,21 @@ err_cio_pwr: | |||
2467 | dsi_cio_disable_lane_override(dsidev); | 2493 | dsi_cio_disable_lane_override(dsidev); |
2468 | err_scp_clk_dom: | 2494 | err_scp_clk_dom: |
2469 | dsi_disable_scp_clk(dsidev); | 2495 | dsi_disable_scp_clk(dsidev); |
2470 | if (dsi->dsi_mux_pads) | 2496 | dsi->disable_pads(dsidev->id, dsi_get_lane_mask(dssdev)); |
2471 | dsi->dsi_mux_pads(false); | ||
2472 | return r; | 2497 | return r; |
2473 | } | 2498 | } |
2474 | 2499 | ||
2475 | static void dsi_cio_uninit(struct platform_device *dsidev) | 2500 | static void dsi_cio_uninit(struct omap_dss_device *dssdev) |
2476 | { | 2501 | { |
2502 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | ||
2477 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | 2503 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
2478 | 2504 | ||
2505 | /* DDR_CLK_ALWAYS_ON */ | ||
2506 | REG_FLD_MOD(dsidev, DSI_CLK_CTRL, 0, 13, 13); | ||
2507 | |||
2479 | dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_OFF); | 2508 | dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_OFF); |
2480 | dsi_disable_scp_clk(dsidev); | 2509 | dsi_disable_scp_clk(dsidev); |
2481 | if (dsi->dsi_mux_pads) | 2510 | dsi->disable_pads(dsidev->id, dsi_get_lane_mask(dssdev)); |
2482 | dsi->dsi_mux_pads(false); | ||
2483 | } | 2511 | } |
2484 | 2512 | ||
2485 | static void dsi_config_tx_fifo(struct platform_device *dsidev, | 2513 | static void dsi_config_tx_fifo(struct platform_device *dsidev, |
@@ -2669,10 +2697,10 @@ static int dsi_sync_vc(struct platform_device *dsidev, int channel) | |||
2669 | if (!dsi_vc_is_enabled(dsidev, channel)) | 2697 | if (!dsi_vc_is_enabled(dsidev, channel)) |
2670 | return 0; | 2698 | return 0; |
2671 | 2699 | ||
2672 | switch (dsi->vc[channel].mode) { | 2700 | switch (dsi->vc[channel].source) { |
2673 | case DSI_VC_MODE_VP: | 2701 | case DSI_VC_SOURCE_VP: |
2674 | return dsi_sync_vc_vp(dsidev, channel); | 2702 | return dsi_sync_vc_vp(dsidev, channel); |
2675 | case DSI_VC_MODE_L4: | 2703 | case DSI_VC_SOURCE_L4: |
2676 | return dsi_sync_vc_l4(dsidev, channel); | 2704 | return dsi_sync_vc_l4(dsidev, channel); |
2677 | default: | 2705 | default: |
2678 | BUG(); | 2706 | BUG(); |
@@ -2726,43 +2754,12 @@ static void dsi_vc_initial_config(struct platform_device *dsidev, int channel) | |||
2726 | dsi_write_reg(dsidev, DSI_VC_CTRL(channel), r); | 2754 | dsi_write_reg(dsidev, DSI_VC_CTRL(channel), r); |
2727 | } | 2755 | } |
2728 | 2756 | ||
2729 | static int dsi_vc_config_l4(struct platform_device *dsidev, int channel) | 2757 | static int dsi_vc_config_source(struct platform_device *dsidev, int channel, |
2758 | enum dsi_vc_source source) | ||
2730 | { | 2759 | { |
2731 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | 2760 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
2732 | 2761 | ||
2733 | if (dsi->vc[channel].mode == DSI_VC_MODE_L4) | 2762 | if (dsi->vc[channel].source == source) |
2734 | return 0; | ||
2735 | |||
2736 | DSSDBGF("%d", channel); | ||
2737 | |||
2738 | dsi_sync_vc(dsidev, channel); | ||
2739 | |||
2740 | dsi_vc_enable(dsidev, channel, 0); | ||
2741 | |||
2742 | /* VC_BUSY */ | ||
2743 | if (wait_for_bit_change(dsidev, DSI_VC_CTRL(channel), 15, 0) != 0) { | ||
2744 | DSSERR("vc(%d) busy when trying to config for L4\n", channel); | ||
2745 | return -EIO; | ||
2746 | } | ||
2747 | |||
2748 | REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 0, 1, 1); /* SOURCE, 0 = L4 */ | ||
2749 | |||
2750 | /* DCS_CMD_ENABLE */ | ||
2751 | if (dss_has_feature(FEAT_DSI_DCS_CMD_CONFIG_VC)) | ||
2752 | REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 0, 30, 30); | ||
2753 | |||
2754 | dsi_vc_enable(dsidev, channel, 1); | ||
2755 | |||
2756 | dsi->vc[channel].mode = DSI_VC_MODE_L4; | ||
2757 | |||
2758 | return 0; | ||
2759 | } | ||
2760 | |||
2761 | static int dsi_vc_config_vp(struct platform_device *dsidev, int channel) | ||
2762 | { | ||
2763 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
2764 | |||
2765 | if (dsi->vc[channel].mode == DSI_VC_MODE_VP) | ||
2766 | return 0; | 2763 | return 0; |
2767 | 2764 | ||
2768 | DSSDBGF("%d", channel); | 2765 | DSSDBGF("%d", channel); |
@@ -2777,21 +2774,22 @@ static int dsi_vc_config_vp(struct platform_device *dsidev, int channel) | |||
2777 | return -EIO; | 2774 | return -EIO; |
2778 | } | 2775 | } |
2779 | 2776 | ||
2780 | /* SOURCE, 1 = video port */ | 2777 | /* SOURCE, 0 = L4, 1 = video port */ |
2781 | REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 1, 1, 1); | 2778 | REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), source, 1, 1); |
2782 | 2779 | ||
2783 | /* DCS_CMD_ENABLE */ | 2780 | /* DCS_CMD_ENABLE */ |
2784 | if (dss_has_feature(FEAT_DSI_DCS_CMD_CONFIG_VC)) | 2781 | if (dss_has_feature(FEAT_DSI_DCS_CMD_CONFIG_VC)) { |
2785 | REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 1, 30, 30); | 2782 | bool enable = source == DSI_VC_SOURCE_VP; |
2783 | REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), enable, 30, 30); | ||
2784 | } | ||
2786 | 2785 | ||
2787 | dsi_vc_enable(dsidev, channel, 1); | 2786 | dsi_vc_enable(dsidev, channel, 1); |
2788 | 2787 | ||
2789 | dsi->vc[channel].mode = DSI_VC_MODE_VP; | 2788 | dsi->vc[channel].source = source; |
2790 | 2789 | ||
2791 | return 0; | 2790 | return 0; |
2792 | } | 2791 | } |
2793 | 2792 | ||
2794 | |||
2795 | void omapdss_dsi_vc_enable_hs(struct omap_dss_device *dssdev, int channel, | 2793 | void omapdss_dsi_vc_enable_hs(struct omap_dss_device *dssdev, int channel, |
2796 | bool enable) | 2794 | bool enable) |
2797 | { | 2795 | { |
@@ -2810,6 +2808,10 @@ void omapdss_dsi_vc_enable_hs(struct omap_dss_device *dssdev, int channel, | |||
2810 | dsi_if_enable(dsidev, 1); | 2808 | dsi_if_enable(dsidev, 1); |
2811 | 2809 | ||
2812 | dsi_force_tx_stop_mode_io(dsidev); | 2810 | dsi_force_tx_stop_mode_io(dsidev); |
2811 | |||
2812 | /* start the DDR clock by sending a NULL packet */ | ||
2813 | if (dssdev->panel.dsi_vm_data.ddr_clk_always_on && enable) | ||
2814 | dsi_vc_send_null(dssdev, channel); | ||
2813 | } | 2815 | } |
2814 | EXPORT_SYMBOL(omapdss_dsi_vc_enable_hs); | 2816 | EXPORT_SYMBOL(omapdss_dsi_vc_enable_hs); |
2815 | 2817 | ||
@@ -2873,16 +2875,16 @@ static u16 dsi_vc_flush_receive_data(struct platform_device *dsidev, | |||
2873 | val = dsi_read_reg(dsidev, DSI_VC_SHORT_PACKET_HEADER(channel)); | 2875 | val = dsi_read_reg(dsidev, DSI_VC_SHORT_PACKET_HEADER(channel)); |
2874 | DSSERR("\trawval %#08x\n", val); | 2876 | DSSERR("\trawval %#08x\n", val); |
2875 | dt = FLD_GET(val, 5, 0); | 2877 | dt = FLD_GET(val, 5, 0); |
2876 | if (dt == DSI_DT_RX_ACK_WITH_ERR) { | 2878 | if (dt == MIPI_DSI_RX_ACKNOWLEDGE_AND_ERROR_REPORT) { |
2877 | u16 err = FLD_GET(val, 23, 8); | 2879 | u16 err = FLD_GET(val, 23, 8); |
2878 | dsi_show_rx_ack_with_err(err); | 2880 | dsi_show_rx_ack_with_err(err); |
2879 | } else if (dt == DSI_DT_RX_SHORT_READ_1) { | 2881 | } else if (dt == MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_1BYTE) { |
2880 | DSSERR("\tDCS short response, 1 byte: %#x\n", | 2882 | DSSERR("\tDCS short response, 1 byte: %#x\n", |
2881 | FLD_GET(val, 23, 8)); | 2883 | FLD_GET(val, 23, 8)); |
2882 | } else if (dt == DSI_DT_RX_SHORT_READ_2) { | 2884 | } else if (dt == MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_2BYTE) { |
2883 | DSSERR("\tDCS short response, 2 byte: %#x\n", | 2885 | DSSERR("\tDCS short response, 2 byte: %#x\n", |
2884 | FLD_GET(val, 23, 8)); | 2886 | FLD_GET(val, 23, 8)); |
2885 | } else if (dt == DSI_DT_RX_DCS_LONG_READ) { | 2887 | } else if (dt == MIPI_DSI_RX_DCS_LONG_READ_RESPONSE) { |
2886 | DSSERR("\tDCS long response, len %d\n", | 2888 | DSSERR("\tDCS long response, len %d\n", |
2887 | FLD_GET(val, 23, 8)); | 2889 | FLD_GET(val, 23, 8)); |
2888 | dsi_vc_flush_long_data(dsidev, channel); | 2890 | dsi_vc_flush_long_data(dsidev, channel); |
@@ -3007,7 +3009,7 @@ static int dsi_vc_send_long(struct platform_device *dsidev, int channel, | |||
3007 | return -EINVAL; | 3009 | return -EINVAL; |
3008 | } | 3010 | } |
3009 | 3011 | ||
3010 | dsi_vc_config_l4(dsidev, channel); | 3012 | dsi_vc_config_source(dsidev, channel, DSI_VC_SOURCE_L4); |
3011 | 3013 | ||
3012 | dsi_vc_write_long_header(dsidev, channel, data_type, len, ecc); | 3014 | dsi_vc_write_long_header(dsidev, channel, data_type, len, ecc); |
3013 | 3015 | ||
@@ -3066,7 +3068,7 @@ static int dsi_vc_send_short(struct platform_device *dsidev, int channel, | |||
3066 | channel, | 3068 | channel, |
3067 | data_type, data & 0xff, (data >> 8) & 0xff); | 3069 | data_type, data & 0xff, (data >> 8) & 0xff); |
3068 | 3070 | ||
3069 | dsi_vc_config_l4(dsidev, channel); | 3071 | dsi_vc_config_source(dsidev, channel, DSI_VC_SOURCE_L4); |
3070 | 3072 | ||
3071 | if (FLD_GET(dsi_read_reg(dsidev, DSI_VC_CTRL(channel)), 16, 16)) { | 3073 | if (FLD_GET(dsi_read_reg(dsidev, DSI_VC_CTRL(channel)), 16, 16)) { |
3072 | DSSERR("ERROR FIFO FULL, aborting transfer\n"); | 3074 | DSSERR("ERROR FIFO FULL, aborting transfer\n"); |
@@ -3085,44 +3087,66 @@ static int dsi_vc_send_short(struct platform_device *dsidev, int channel, | |||
3085 | int dsi_vc_send_null(struct omap_dss_device *dssdev, int channel) | 3087 | int dsi_vc_send_null(struct omap_dss_device *dssdev, int channel) |
3086 | { | 3088 | { |
3087 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | 3089 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); |
3088 | u8 nullpkg[] = {0, 0, 0, 0}; | ||
3089 | 3090 | ||
3090 | return dsi_vc_send_long(dsidev, channel, DSI_DT_NULL_PACKET, nullpkg, | 3091 | return dsi_vc_send_long(dsidev, channel, MIPI_DSI_NULL_PACKET, NULL, |
3091 | 4, 0); | 3092 | 0, 0); |
3092 | } | 3093 | } |
3093 | EXPORT_SYMBOL(dsi_vc_send_null); | 3094 | EXPORT_SYMBOL(dsi_vc_send_null); |
3094 | 3095 | ||
3095 | int dsi_vc_dcs_write_nosync(struct omap_dss_device *dssdev, int channel, | 3096 | static int dsi_vc_write_nosync_common(struct omap_dss_device *dssdev, |
3096 | u8 *data, int len) | 3097 | int channel, u8 *data, int len, enum dss_dsi_content_type type) |
3097 | { | 3098 | { |
3098 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | 3099 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); |
3099 | int r; | 3100 | int r; |
3100 | 3101 | ||
3101 | BUG_ON(len == 0); | 3102 | if (len == 0) { |
3102 | 3103 | BUG_ON(type == DSS_DSI_CONTENT_DCS); | |
3103 | if (len == 1) { | 3104 | r = dsi_vc_send_short(dsidev, channel, |
3104 | r = dsi_vc_send_short(dsidev, channel, DSI_DT_DCS_SHORT_WRITE_0, | 3105 | MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM, 0, 0); |
3105 | data[0], 0); | 3106 | } else if (len == 1) { |
3107 | r = dsi_vc_send_short(dsidev, channel, | ||
3108 | type == DSS_DSI_CONTENT_GENERIC ? | ||
3109 | MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM : | ||
3110 | MIPI_DSI_DCS_SHORT_WRITE, data[0], 0); | ||
3106 | } else if (len == 2) { | 3111 | } else if (len == 2) { |
3107 | r = dsi_vc_send_short(dsidev, channel, DSI_DT_DCS_SHORT_WRITE_1, | 3112 | r = dsi_vc_send_short(dsidev, channel, |
3113 | type == DSS_DSI_CONTENT_GENERIC ? | ||
3114 | MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM : | ||
3115 | MIPI_DSI_DCS_SHORT_WRITE_PARAM, | ||
3108 | data[0] | (data[1] << 8), 0); | 3116 | data[0] | (data[1] << 8), 0); |
3109 | } else { | 3117 | } else { |
3110 | /* 0x39 = DCS Long Write */ | 3118 | r = dsi_vc_send_long(dsidev, channel, |
3111 | r = dsi_vc_send_long(dsidev, channel, DSI_DT_DCS_LONG_WRITE, | 3119 | type == DSS_DSI_CONTENT_GENERIC ? |
3112 | data, len, 0); | 3120 | MIPI_DSI_GENERIC_LONG_WRITE : |
3121 | MIPI_DSI_DCS_LONG_WRITE, data, len, 0); | ||
3113 | } | 3122 | } |
3114 | 3123 | ||
3115 | return r; | 3124 | return r; |
3116 | } | 3125 | } |
3126 | |||
3127 | int dsi_vc_dcs_write_nosync(struct omap_dss_device *dssdev, int channel, | ||
3128 | u8 *data, int len) | ||
3129 | { | ||
3130 | return dsi_vc_write_nosync_common(dssdev, channel, data, len, | ||
3131 | DSS_DSI_CONTENT_DCS); | ||
3132 | } | ||
3117 | EXPORT_SYMBOL(dsi_vc_dcs_write_nosync); | 3133 | EXPORT_SYMBOL(dsi_vc_dcs_write_nosync); |
3118 | 3134 | ||
3119 | int dsi_vc_dcs_write(struct omap_dss_device *dssdev, int channel, u8 *data, | 3135 | int dsi_vc_generic_write_nosync(struct omap_dss_device *dssdev, int channel, |
3120 | int len) | 3136 | u8 *data, int len) |
3137 | { | ||
3138 | return dsi_vc_write_nosync_common(dssdev, channel, data, len, | ||
3139 | DSS_DSI_CONTENT_GENERIC); | ||
3140 | } | ||
3141 | EXPORT_SYMBOL(dsi_vc_generic_write_nosync); | ||
3142 | |||
3143 | static int dsi_vc_write_common(struct omap_dss_device *dssdev, int channel, | ||
3144 | u8 *data, int len, enum dss_dsi_content_type type) | ||
3121 | { | 3145 | { |
3122 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | 3146 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); |
3123 | int r; | 3147 | int r; |
3124 | 3148 | ||
3125 | r = dsi_vc_dcs_write_nosync(dssdev, channel, data, len); | 3149 | r = dsi_vc_write_nosync_common(dssdev, channel, data, len, type); |
3126 | if (r) | 3150 | if (r) |
3127 | goto err; | 3151 | goto err; |
3128 | 3152 | ||
@@ -3140,18 +3164,39 @@ int dsi_vc_dcs_write(struct omap_dss_device *dssdev, int channel, u8 *data, | |||
3140 | 3164 | ||
3141 | return 0; | 3165 | return 0; |
3142 | err: | 3166 | err: |
3143 | DSSERR("dsi_vc_dcs_write(ch %d, cmd 0x%02x, len %d) failed\n", | 3167 | DSSERR("dsi_vc_write_common(ch %d, cmd 0x%02x, len %d) failed\n", |
3144 | channel, data[0], len); | 3168 | channel, data[0], len); |
3145 | return r; | 3169 | return r; |
3146 | } | 3170 | } |
3171 | |||
3172 | int dsi_vc_dcs_write(struct omap_dss_device *dssdev, int channel, u8 *data, | ||
3173 | int len) | ||
3174 | { | ||
3175 | return dsi_vc_write_common(dssdev, channel, data, len, | ||
3176 | DSS_DSI_CONTENT_DCS); | ||
3177 | } | ||
3147 | EXPORT_SYMBOL(dsi_vc_dcs_write); | 3178 | EXPORT_SYMBOL(dsi_vc_dcs_write); |
3148 | 3179 | ||
3180 | int dsi_vc_generic_write(struct omap_dss_device *dssdev, int channel, u8 *data, | ||
3181 | int len) | ||
3182 | { | ||
3183 | return dsi_vc_write_common(dssdev, channel, data, len, | ||
3184 | DSS_DSI_CONTENT_GENERIC); | ||
3185 | } | ||
3186 | EXPORT_SYMBOL(dsi_vc_generic_write); | ||
3187 | |||
3149 | int dsi_vc_dcs_write_0(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd) | 3188 | int dsi_vc_dcs_write_0(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd) |
3150 | { | 3189 | { |
3151 | return dsi_vc_dcs_write(dssdev, channel, &dcs_cmd, 1); | 3190 | return dsi_vc_dcs_write(dssdev, channel, &dcs_cmd, 1); |
3152 | } | 3191 | } |
3153 | EXPORT_SYMBOL(dsi_vc_dcs_write_0); | 3192 | EXPORT_SYMBOL(dsi_vc_dcs_write_0); |
3154 | 3193 | ||
3194 | int dsi_vc_generic_write_0(struct omap_dss_device *dssdev, int channel) | ||
3195 | { | ||
3196 | return dsi_vc_generic_write(dssdev, channel, NULL, 0); | ||
3197 | } | ||
3198 | EXPORT_SYMBOL(dsi_vc_generic_write_0); | ||
3199 | |||
3155 | int dsi_vc_dcs_write_1(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd, | 3200 | int dsi_vc_dcs_write_1(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd, |
3156 | u8 param) | 3201 | u8 param) |
3157 | { | 3202 | { |
@@ -3162,25 +3207,87 @@ int dsi_vc_dcs_write_1(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd, | |||
3162 | } | 3207 | } |
3163 | EXPORT_SYMBOL(dsi_vc_dcs_write_1); | 3208 | EXPORT_SYMBOL(dsi_vc_dcs_write_1); |
3164 | 3209 | ||
3165 | int dsi_vc_dcs_read(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd, | 3210 | int dsi_vc_generic_write_1(struct omap_dss_device *dssdev, int channel, |
3166 | u8 *buf, int buflen) | 3211 | u8 param) |
3212 | { | ||
3213 | return dsi_vc_generic_write(dssdev, channel, ¶m, 1); | ||
3214 | } | ||
3215 | EXPORT_SYMBOL(dsi_vc_generic_write_1); | ||
3216 | |||
3217 | int dsi_vc_generic_write_2(struct omap_dss_device *dssdev, int channel, | ||
3218 | u8 param1, u8 param2) | ||
3219 | { | ||
3220 | u8 buf[2]; | ||
3221 | buf[0] = param1; | ||
3222 | buf[1] = param2; | ||
3223 | return dsi_vc_generic_write(dssdev, channel, buf, 2); | ||
3224 | } | ||
3225 | EXPORT_SYMBOL(dsi_vc_generic_write_2); | ||
3226 | |||
3227 | static int dsi_vc_dcs_send_read_request(struct omap_dss_device *dssdev, | ||
3228 | int channel, u8 dcs_cmd) | ||
3167 | { | 3229 | { |
3168 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | 3230 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); |
3169 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | 3231 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
3170 | u32 val; | ||
3171 | u8 dt; | ||
3172 | int r; | 3232 | int r; |
3173 | 3233 | ||
3174 | if (dsi->debug_read) | 3234 | if (dsi->debug_read) |
3175 | DSSDBG("dsi_vc_dcs_read(ch%d, dcs_cmd %x)\n", channel, dcs_cmd); | 3235 | DSSDBG("dsi_vc_dcs_send_read_request(ch%d, dcs_cmd %x)\n", |
3236 | channel, dcs_cmd); | ||
3176 | 3237 | ||
3177 | r = dsi_vc_send_short(dsidev, channel, DSI_DT_DCS_READ, dcs_cmd, 0); | 3238 | r = dsi_vc_send_short(dsidev, channel, MIPI_DSI_DCS_READ, dcs_cmd, 0); |
3178 | if (r) | 3239 | if (r) { |
3179 | goto err; | 3240 | DSSERR("dsi_vc_dcs_send_read_request(ch %d, cmd 0x%02x)" |
3241 | " failed\n", channel, dcs_cmd); | ||
3242 | return r; | ||
3243 | } | ||
3180 | 3244 | ||
3181 | r = dsi_vc_send_bta_sync(dssdev, channel); | 3245 | return 0; |
3182 | if (r) | 3246 | } |
3183 | goto err; | 3247 | |
3248 | static int dsi_vc_generic_send_read_request(struct omap_dss_device *dssdev, | ||
3249 | int channel, u8 *reqdata, int reqlen) | ||
3250 | { | ||
3251 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | ||
3252 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
3253 | u16 data; | ||
3254 | u8 data_type; | ||
3255 | int r; | ||
3256 | |||
3257 | if (dsi->debug_read) | ||
3258 | DSSDBG("dsi_vc_generic_send_read_request(ch %d, reqlen %d)\n", | ||
3259 | channel, reqlen); | ||
3260 | |||
3261 | if (reqlen == 0) { | ||
3262 | data_type = MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM; | ||
3263 | data = 0; | ||
3264 | } else if (reqlen == 1) { | ||
3265 | data_type = MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM; | ||
3266 | data = reqdata[0]; | ||
3267 | } else if (reqlen == 2) { | ||
3268 | data_type = MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM; | ||
3269 | data = reqdata[0] | (reqdata[1] << 8); | ||
3270 | } else { | ||
3271 | BUG(); | ||
3272 | } | ||
3273 | |||
3274 | r = dsi_vc_send_short(dsidev, channel, data_type, data, 0); | ||
3275 | if (r) { | ||
3276 | DSSERR("dsi_vc_generic_send_read_request(ch %d, reqlen %d)" | ||
3277 | " failed\n", channel, reqlen); | ||
3278 | return r; | ||
3279 | } | ||
3280 | |||
3281 | return 0; | ||
3282 | } | ||
3283 | |||
3284 | static int dsi_vc_read_rx_fifo(struct platform_device *dsidev, int channel, | ||
3285 | u8 *buf, int buflen, enum dss_dsi_content_type type) | ||
3286 | { | ||
3287 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
3288 | u32 val; | ||
3289 | u8 dt; | ||
3290 | int r; | ||
3184 | 3291 | ||
3185 | /* RX_FIFO_NOT_EMPTY */ | 3292 | /* RX_FIFO_NOT_EMPTY */ |
3186 | if (REG_GET(dsidev, DSI_VC_CTRL(channel), 20, 20) == 0) { | 3293 | if (REG_GET(dsidev, DSI_VC_CTRL(channel), 20, 20) == 0) { |
@@ -3193,16 +3300,20 @@ int dsi_vc_dcs_read(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd, | |||
3193 | if (dsi->debug_read) | 3300 | if (dsi->debug_read) |
3194 | DSSDBG("\theader: %08x\n", val); | 3301 | DSSDBG("\theader: %08x\n", val); |
3195 | dt = FLD_GET(val, 5, 0); | 3302 | dt = FLD_GET(val, 5, 0); |
3196 | if (dt == DSI_DT_RX_ACK_WITH_ERR) { | 3303 | if (dt == MIPI_DSI_RX_ACKNOWLEDGE_AND_ERROR_REPORT) { |
3197 | u16 err = FLD_GET(val, 23, 8); | 3304 | u16 err = FLD_GET(val, 23, 8); |
3198 | dsi_show_rx_ack_with_err(err); | 3305 | dsi_show_rx_ack_with_err(err); |
3199 | r = -EIO; | 3306 | r = -EIO; |
3200 | goto err; | 3307 | goto err; |
3201 | 3308 | ||
3202 | } else if (dt == DSI_DT_RX_SHORT_READ_1) { | 3309 | } else if (dt == (type == DSS_DSI_CONTENT_GENERIC ? |
3310 | MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_1BYTE : | ||
3311 | MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_1BYTE)) { | ||
3203 | u8 data = FLD_GET(val, 15, 8); | 3312 | u8 data = FLD_GET(val, 15, 8); |
3204 | if (dsi->debug_read) | 3313 | if (dsi->debug_read) |
3205 | DSSDBG("\tDCS short response, 1 byte: %02x\n", data); | 3314 | DSSDBG("\t%s short response, 1 byte: %02x\n", |
3315 | type == DSS_DSI_CONTENT_GENERIC ? "GENERIC" : | ||
3316 | "DCS", data); | ||
3206 | 3317 | ||
3207 | if (buflen < 1) { | 3318 | if (buflen < 1) { |
3208 | r = -EIO; | 3319 | r = -EIO; |
@@ -3212,10 +3323,14 @@ int dsi_vc_dcs_read(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd, | |||
3212 | buf[0] = data; | 3323 | buf[0] = data; |
3213 | 3324 | ||
3214 | return 1; | 3325 | return 1; |
3215 | } else if (dt == DSI_DT_RX_SHORT_READ_2) { | 3326 | } else if (dt == (type == DSS_DSI_CONTENT_GENERIC ? |
3327 | MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_2BYTE : | ||
3328 | MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_2BYTE)) { | ||
3216 | u16 data = FLD_GET(val, 23, 8); | 3329 | u16 data = FLD_GET(val, 23, 8); |
3217 | if (dsi->debug_read) | 3330 | if (dsi->debug_read) |
3218 | DSSDBG("\tDCS short response, 2 byte: %04x\n", data); | 3331 | DSSDBG("\t%s short response, 2 byte: %04x\n", |
3332 | type == DSS_DSI_CONTENT_GENERIC ? "GENERIC" : | ||
3333 | "DCS", data); | ||
3219 | 3334 | ||
3220 | if (buflen < 2) { | 3335 | if (buflen < 2) { |
3221 | r = -EIO; | 3336 | r = -EIO; |
@@ -3226,11 +3341,15 @@ int dsi_vc_dcs_read(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd, | |||
3226 | buf[1] = (data >> 8) & 0xff; | 3341 | buf[1] = (data >> 8) & 0xff; |
3227 | 3342 | ||
3228 | return 2; | 3343 | return 2; |
3229 | } else if (dt == DSI_DT_RX_DCS_LONG_READ) { | 3344 | } else if (dt == (type == DSS_DSI_CONTENT_GENERIC ? |
3345 | MIPI_DSI_RX_GENERIC_LONG_READ_RESPONSE : | ||
3346 | MIPI_DSI_RX_DCS_LONG_READ_RESPONSE)) { | ||
3230 | int w; | 3347 | int w; |
3231 | int len = FLD_GET(val, 23, 8); | 3348 | int len = FLD_GET(val, 23, 8); |
3232 | if (dsi->debug_read) | 3349 | if (dsi->debug_read) |
3233 | DSSDBG("\tDCS long response, len %d\n", len); | 3350 | DSSDBG("\t%s long response, len %d\n", |
3351 | type == DSS_DSI_CONTENT_GENERIC ? "GENERIC" : | ||
3352 | "DCS", len); | ||
3234 | 3353 | ||
3235 | if (len > buflen) { | 3354 | if (len > buflen) { |
3236 | r = -EIO; | 3355 | r = -EIO; |
@@ -3266,58 +3385,126 @@ int dsi_vc_dcs_read(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd, | |||
3266 | 3385 | ||
3267 | BUG(); | 3386 | BUG(); |
3268 | err: | 3387 | err: |
3269 | DSSERR("dsi_vc_dcs_read(ch %d, cmd 0x%02x) failed\n", | 3388 | DSSERR("dsi_vc_read_rx_fifo(ch %d type %s) failed\n", channel, |
3270 | channel, dcs_cmd); | 3389 | type == DSS_DSI_CONTENT_GENERIC ? "GENERIC" : "DCS"); |
3390 | |||
3271 | return r; | 3391 | return r; |
3392 | } | ||
3272 | 3393 | ||
3394 | int dsi_vc_dcs_read(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd, | ||
3395 | u8 *buf, int buflen) | ||
3396 | { | ||
3397 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | ||
3398 | int r; | ||
3399 | |||
3400 | r = dsi_vc_dcs_send_read_request(dssdev, channel, dcs_cmd); | ||
3401 | if (r) | ||
3402 | goto err; | ||
3403 | |||
3404 | r = dsi_vc_send_bta_sync(dssdev, channel); | ||
3405 | if (r) | ||
3406 | goto err; | ||
3407 | |||
3408 | r = dsi_vc_read_rx_fifo(dsidev, channel, buf, buflen, | ||
3409 | DSS_DSI_CONTENT_DCS); | ||
3410 | if (r < 0) | ||
3411 | goto err; | ||
3412 | |||
3413 | if (r != buflen) { | ||
3414 | r = -EIO; | ||
3415 | goto err; | ||
3416 | } | ||
3417 | |||
3418 | return 0; | ||
3419 | err: | ||
3420 | DSSERR("dsi_vc_dcs_read(ch %d, cmd 0x%02x) failed\n", channel, dcs_cmd); | ||
3421 | return r; | ||
3273 | } | 3422 | } |
3274 | EXPORT_SYMBOL(dsi_vc_dcs_read); | 3423 | EXPORT_SYMBOL(dsi_vc_dcs_read); |
3275 | 3424 | ||
3276 | int dsi_vc_dcs_read_1(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd, | 3425 | static int dsi_vc_generic_read(struct omap_dss_device *dssdev, int channel, |
3277 | u8 *data) | 3426 | u8 *reqdata, int reqlen, u8 *buf, int buflen) |
3278 | { | 3427 | { |
3428 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | ||
3279 | int r; | 3429 | int r; |
3280 | 3430 | ||
3281 | r = dsi_vc_dcs_read(dssdev, channel, dcs_cmd, data, 1); | 3431 | r = dsi_vc_generic_send_read_request(dssdev, channel, reqdata, reqlen); |
3432 | if (r) | ||
3433 | return r; | ||
3434 | |||
3435 | r = dsi_vc_send_bta_sync(dssdev, channel); | ||
3436 | if (r) | ||
3437 | return r; | ||
3282 | 3438 | ||
3439 | r = dsi_vc_read_rx_fifo(dsidev, channel, buf, buflen, | ||
3440 | DSS_DSI_CONTENT_GENERIC); | ||
3283 | if (r < 0) | 3441 | if (r < 0) |
3284 | return r; | 3442 | return r; |
3285 | 3443 | ||
3286 | if (r != 1) | 3444 | if (r != buflen) { |
3287 | return -EIO; | 3445 | r = -EIO; |
3446 | return r; | ||
3447 | } | ||
3288 | 3448 | ||
3289 | return 0; | 3449 | return 0; |
3290 | } | 3450 | } |
3291 | EXPORT_SYMBOL(dsi_vc_dcs_read_1); | ||
3292 | 3451 | ||
3293 | int dsi_vc_dcs_read_2(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd, | 3452 | int dsi_vc_generic_read_0(struct omap_dss_device *dssdev, int channel, u8 *buf, |
3294 | u8 *data1, u8 *data2) | 3453 | int buflen) |
3295 | { | 3454 | { |
3296 | u8 buf[2]; | ||
3297 | int r; | 3455 | int r; |
3298 | 3456 | ||
3299 | r = dsi_vc_dcs_read(dssdev, channel, dcs_cmd, buf, 2); | 3457 | r = dsi_vc_generic_read(dssdev, channel, NULL, 0, buf, buflen); |
3458 | if (r) { | ||
3459 | DSSERR("dsi_vc_generic_read_0(ch %d) failed\n", channel); | ||
3460 | return r; | ||
3461 | } | ||
3300 | 3462 | ||
3301 | if (r < 0) | 3463 | return 0; |
3464 | } | ||
3465 | EXPORT_SYMBOL(dsi_vc_generic_read_0); | ||
3466 | |||
3467 | int dsi_vc_generic_read_1(struct omap_dss_device *dssdev, int channel, u8 param, | ||
3468 | u8 *buf, int buflen) | ||
3469 | { | ||
3470 | int r; | ||
3471 | |||
3472 | r = dsi_vc_generic_read(dssdev, channel, ¶m, 1, buf, buflen); | ||
3473 | if (r) { | ||
3474 | DSSERR("dsi_vc_generic_read_1(ch %d) failed\n", channel); | ||
3302 | return r; | 3475 | return r; |
3476 | } | ||
3303 | 3477 | ||
3304 | if (r != 2) | 3478 | return 0; |
3305 | return -EIO; | 3479 | } |
3480 | EXPORT_SYMBOL(dsi_vc_generic_read_1); | ||
3306 | 3481 | ||
3307 | *data1 = buf[0]; | 3482 | int dsi_vc_generic_read_2(struct omap_dss_device *dssdev, int channel, |
3308 | *data2 = buf[1]; | 3483 | u8 param1, u8 param2, u8 *buf, int buflen) |
3484 | { | ||
3485 | int r; | ||
3486 | u8 reqdata[2]; | ||
3487 | |||
3488 | reqdata[0] = param1; | ||
3489 | reqdata[1] = param2; | ||
3490 | |||
3491 | r = dsi_vc_generic_read(dssdev, channel, reqdata, 2, buf, buflen); | ||
3492 | if (r) { | ||
3493 | DSSERR("dsi_vc_generic_read_2(ch %d) failed\n", channel); | ||
3494 | return r; | ||
3495 | } | ||
3309 | 3496 | ||
3310 | return 0; | 3497 | return 0; |
3311 | } | 3498 | } |
3312 | EXPORT_SYMBOL(dsi_vc_dcs_read_2); | 3499 | EXPORT_SYMBOL(dsi_vc_generic_read_2); |
3313 | 3500 | ||
3314 | int dsi_vc_set_max_rx_packet_size(struct omap_dss_device *dssdev, int channel, | 3501 | int dsi_vc_set_max_rx_packet_size(struct omap_dss_device *dssdev, int channel, |
3315 | u16 len) | 3502 | u16 len) |
3316 | { | 3503 | { |
3317 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | 3504 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); |
3318 | 3505 | ||
3319 | return dsi_vc_send_short(dsidev, channel, DSI_DT_SET_MAX_RET_PKG_SIZE, | 3506 | return dsi_vc_send_short(dsidev, channel, |
3320 | len, 0); | 3507 | MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE, len, 0); |
3321 | } | 3508 | } |
3322 | EXPORT_SYMBOL(dsi_vc_set_max_rx_packet_size); | 3509 | EXPORT_SYMBOL(dsi_vc_set_max_rx_packet_size); |
3323 | 3510 | ||
@@ -3508,6 +3695,75 @@ static void dsi_set_hs_tx_timeout(struct platform_device *dsidev, | |||
3508 | ticks, x4 ? " x4" : "", x16 ? " x16" : "", | 3695 | ticks, x4 ? " x4" : "", x16 ? " x16" : "", |
3509 | (total_ticks * 1000) / (fck / 1000 / 1000)); | 3696 | (total_ticks * 1000) / (fck / 1000 / 1000)); |
3510 | } | 3697 | } |
3698 | |||
3699 | static void dsi_config_vp_num_line_buffers(struct omap_dss_device *dssdev) | ||
3700 | { | ||
3701 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | ||
3702 | int num_line_buffers; | ||
3703 | |||
3704 | if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) { | ||
3705 | int bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt); | ||
3706 | unsigned line_buf_size = dsi_get_line_buf_size(dsidev); | ||
3707 | struct omap_video_timings *timings = &dssdev->panel.timings; | ||
3708 | /* | ||
3709 | * Don't use line buffers if width is greater than the video | ||
3710 | * port's line buffer size | ||
3711 | */ | ||
3712 | if (line_buf_size <= timings->x_res * bpp / 8) | ||
3713 | num_line_buffers = 0; | ||
3714 | else | ||
3715 | num_line_buffers = 2; | ||
3716 | } else { | ||
3717 | /* Use maximum number of line buffers in command mode */ | ||
3718 | num_line_buffers = 2; | ||
3719 | } | ||
3720 | |||
3721 | /* LINE_BUFFER */ | ||
3722 | REG_FLD_MOD(dsidev, DSI_CTRL, num_line_buffers, 13, 12); | ||
3723 | } | ||
3724 | |||
3725 | static void dsi_config_vp_sync_events(struct omap_dss_device *dssdev) | ||
3726 | { | ||
3727 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | ||
3728 | int de_pol = dssdev->panel.dsi_vm_data.vp_de_pol; | ||
3729 | int hsync_pol = dssdev->panel.dsi_vm_data.vp_hsync_pol; | ||
3730 | int vsync_pol = dssdev->panel.dsi_vm_data.vp_vsync_pol; | ||
3731 | bool vsync_end = dssdev->panel.dsi_vm_data.vp_vsync_end; | ||
3732 | bool hsync_end = dssdev->panel.dsi_vm_data.vp_hsync_end; | ||
3733 | u32 r; | ||
3734 | |||
3735 | r = dsi_read_reg(dsidev, DSI_CTRL); | ||
3736 | r = FLD_MOD(r, de_pol, 9, 9); /* VP_DE_POL */ | ||
3737 | r = FLD_MOD(r, hsync_pol, 10, 10); /* VP_HSYNC_POL */ | ||
3738 | r = FLD_MOD(r, vsync_pol, 11, 11); /* VP_VSYNC_POL */ | ||
3739 | r = FLD_MOD(r, 1, 15, 15); /* VP_VSYNC_START */ | ||
3740 | r = FLD_MOD(r, vsync_end, 16, 16); /* VP_VSYNC_END */ | ||
3741 | r = FLD_MOD(r, 1, 17, 17); /* VP_HSYNC_START */ | ||
3742 | r = FLD_MOD(r, hsync_end, 18, 18); /* VP_HSYNC_END */ | ||
3743 | dsi_write_reg(dsidev, DSI_CTRL, r); | ||
3744 | } | ||
3745 | |||
3746 | static void dsi_config_blanking_modes(struct omap_dss_device *dssdev) | ||
3747 | { | ||
3748 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | ||
3749 | int blanking_mode = dssdev->panel.dsi_vm_data.blanking_mode; | ||
3750 | int hfp_blanking_mode = dssdev->panel.dsi_vm_data.hfp_blanking_mode; | ||
3751 | int hbp_blanking_mode = dssdev->panel.dsi_vm_data.hbp_blanking_mode; | ||
3752 | int hsa_blanking_mode = dssdev->panel.dsi_vm_data.hsa_blanking_mode; | ||
3753 | u32 r; | ||
3754 | |||
3755 | /* | ||
3756 | * 0 = TX FIFO packets sent or LPS in corresponding blanking periods | ||
3757 | * 1 = Long blanking packets are sent in corresponding blanking periods | ||
3758 | */ | ||
3759 | r = dsi_read_reg(dsidev, DSI_CTRL); | ||
3760 | r = FLD_MOD(r, blanking_mode, 20, 20); /* BLANKING_MODE */ | ||
3761 | r = FLD_MOD(r, hfp_blanking_mode, 21, 21); /* HFP_BLANKING */ | ||
3762 | r = FLD_MOD(r, hbp_blanking_mode, 22, 22); /* HBP_BLANKING */ | ||
3763 | r = FLD_MOD(r, hsa_blanking_mode, 23, 23); /* HSA_BLANKING */ | ||
3764 | dsi_write_reg(dsidev, DSI_CTRL, r); | ||
3765 | } | ||
3766 | |||
3511 | static int dsi_proto_config(struct omap_dss_device *dssdev) | 3767 | static int dsi_proto_config(struct omap_dss_device *dssdev) |
3512 | { | 3768 | { |
3513 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | 3769 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); |
@@ -3530,7 +3786,7 @@ static int dsi_proto_config(struct omap_dss_device *dssdev) | |||
3530 | dsi_set_lp_rx_timeout(dsidev, 0x1fff, true, true); | 3786 | dsi_set_lp_rx_timeout(dsidev, 0x1fff, true, true); |
3531 | dsi_set_hs_tx_timeout(dsidev, 0x1fff, true, true); | 3787 | dsi_set_hs_tx_timeout(dsidev, 0x1fff, true, true); |
3532 | 3788 | ||
3533 | switch (dssdev->ctrl.pixel_size) { | 3789 | switch (dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt)) { |
3534 | case 16: | 3790 | case 16: |
3535 | buswidth = 0; | 3791 | buswidth = 0; |
3536 | break; | 3792 | break; |
@@ -3551,7 +3807,6 @@ static int dsi_proto_config(struct omap_dss_device *dssdev) | |||
3551 | r = FLD_MOD(r, 1, 4, 4); /* VP_CLK_RATIO, always 1, see errata*/ | 3807 | r = FLD_MOD(r, 1, 4, 4); /* VP_CLK_RATIO, always 1, see errata*/ |
3552 | r = FLD_MOD(r, buswidth, 7, 6); /* VP_DATA_BUS_WIDTH */ | 3808 | r = FLD_MOD(r, buswidth, 7, 6); /* VP_DATA_BUS_WIDTH */ |
3553 | r = FLD_MOD(r, 0, 8, 8); /* VP_CLK_POL */ | 3809 | r = FLD_MOD(r, 0, 8, 8); /* VP_CLK_POL */ |
3554 | r = FLD_MOD(r, 2, 13, 12); /* LINE_BUFFER, 2 lines */ | ||
3555 | r = FLD_MOD(r, 1, 14, 14); /* TRIGGER_RESET_MODE */ | 3810 | r = FLD_MOD(r, 1, 14, 14); /* TRIGGER_RESET_MODE */ |
3556 | r = FLD_MOD(r, 1, 19, 19); /* EOT_ENABLE */ | 3811 | r = FLD_MOD(r, 1, 19, 19); /* EOT_ENABLE */ |
3557 | if (!dss_has_feature(FEAT_DSI_DCS_CMD_CONFIG_VC)) { | 3812 | if (!dss_has_feature(FEAT_DSI_DCS_CMD_CONFIG_VC)) { |
@@ -3562,6 +3817,13 @@ static int dsi_proto_config(struct omap_dss_device *dssdev) | |||
3562 | 3817 | ||
3563 | dsi_write_reg(dsidev, DSI_CTRL, r); | 3818 | dsi_write_reg(dsidev, DSI_CTRL, r); |
3564 | 3819 | ||
3820 | dsi_config_vp_num_line_buffers(dssdev); | ||
3821 | |||
3822 | if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) { | ||
3823 | dsi_config_vp_sync_events(dssdev); | ||
3824 | dsi_config_blanking_modes(dssdev); | ||
3825 | } | ||
3826 | |||
3565 | dsi_vc_initial_config(dsidev, 0); | 3827 | dsi_vc_initial_config(dsidev, 0); |
3566 | dsi_vc_initial_config(dsidev, 1); | 3828 | dsi_vc_initial_config(dsidev, 1); |
3567 | dsi_vc_initial_config(dsidev, 2); | 3829 | dsi_vc_initial_config(dsidev, 2); |
@@ -3580,6 +3842,7 @@ static void dsi_proto_timings(struct omap_dss_device *dssdev) | |||
3580 | unsigned ddr_clk_pre, ddr_clk_post; | 3842 | unsigned ddr_clk_pre, ddr_clk_post; |
3581 | unsigned enter_hs_mode_lat, exit_hs_mode_lat; | 3843 | unsigned enter_hs_mode_lat, exit_hs_mode_lat; |
3582 | unsigned ths_eot; | 3844 | unsigned ths_eot; |
3845 | int ndl = dsi_get_num_data_lanes_dssdev(dssdev); | ||
3583 | u32 r; | 3846 | u32 r; |
3584 | 3847 | ||
3585 | r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG0); | 3848 | r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG0); |
@@ -3602,7 +3865,7 @@ static void dsi_proto_timings(struct omap_dss_device *dssdev) | |||
3602 | /* min 60ns + 52*UI */ | 3865 | /* min 60ns + 52*UI */ |
3603 | tclk_post = ns2ddr(dsidev, 60) + 26; | 3866 | tclk_post = ns2ddr(dsidev, 60) + 26; |
3604 | 3867 | ||
3605 | ths_eot = DIV_ROUND_UP(4, dsi_get_num_data_lanes_dssdev(dssdev)); | 3868 | ths_eot = DIV_ROUND_UP(4, ndl); |
3606 | 3869 | ||
3607 | ddr_clk_pre = DIV_ROUND_UP(tclk_pre + tlpx + tclk_zero + tclk_prepare, | 3870 | ddr_clk_pre = DIV_ROUND_UP(tclk_pre + tlpx + tclk_zero + tclk_prepare, |
3608 | 4); | 3871 | 4); |
@@ -3632,162 +3895,114 @@ static void dsi_proto_timings(struct omap_dss_device *dssdev) | |||
3632 | 3895 | ||
3633 | DSSDBG("enter_hs_mode_lat %u, exit_hs_mode_lat %u\n", | 3896 | DSSDBG("enter_hs_mode_lat %u, exit_hs_mode_lat %u\n", |
3634 | enter_hs_mode_lat, exit_hs_mode_lat); | 3897 | enter_hs_mode_lat, exit_hs_mode_lat); |
3635 | } | ||
3636 | |||
3637 | |||
3638 | #define DSI_DECL_VARS \ | ||
3639 | int __dsi_cb = 0; u32 __dsi_cv = 0; | ||
3640 | 3898 | ||
3641 | #define DSI_FLUSH(dsidev, ch) \ | 3899 | if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) { |
3642 | if (__dsi_cb > 0) { \ | 3900 | /* TODO: Implement a video mode check_timings function */ |
3643 | /*DSSDBG("sending long packet %#010x\n", __dsi_cv);*/ \ | 3901 | int hsa = dssdev->panel.dsi_vm_data.hsa; |
3644 | dsi_write_reg(dsidev, DSI_VC_LONG_PACKET_PAYLOAD(ch), __dsi_cv); \ | 3902 | int hfp = dssdev->panel.dsi_vm_data.hfp; |
3645 | __dsi_cb = __dsi_cv = 0; \ | 3903 | int hbp = dssdev->panel.dsi_vm_data.hbp; |
3904 | int vsa = dssdev->panel.dsi_vm_data.vsa; | ||
3905 | int vfp = dssdev->panel.dsi_vm_data.vfp; | ||
3906 | int vbp = dssdev->panel.dsi_vm_data.vbp; | ||
3907 | int window_sync = dssdev->panel.dsi_vm_data.window_sync; | ||
3908 | bool hsync_end = dssdev->panel.dsi_vm_data.vp_hsync_end; | ||
3909 | struct omap_video_timings *timings = &dssdev->panel.timings; | ||
3910 | int bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt); | ||
3911 | int tl, t_he, width_bytes; | ||
3912 | |||
3913 | t_he = hsync_end ? | ||
3914 | ((hsa == 0 && ndl == 3) ? 1 : DIV_ROUND_UP(4, ndl)) : 0; | ||
3915 | |||
3916 | width_bytes = DIV_ROUND_UP(timings->x_res * bpp, 8); | ||
3917 | |||
3918 | /* TL = t_HS + HSA + t_HE + HFP + ceil((WC + 6) / NDL) + HBP */ | ||
3919 | tl = DIV_ROUND_UP(4, ndl) + (hsync_end ? hsa : 0) + t_he + hfp + | ||
3920 | DIV_ROUND_UP(width_bytes + 6, ndl) + hbp; | ||
3921 | |||
3922 | DSSDBG("HBP: %d, HFP: %d, HSA: %d, TL: %d TXBYTECLKHS\n", hbp, | ||
3923 | hfp, hsync_end ? hsa : 0, tl); | ||
3924 | DSSDBG("VBP: %d, VFP: %d, VSA: %d, VACT: %d lines\n", vbp, vfp, | ||
3925 | vsa, timings->y_res); | ||
3926 | |||
3927 | r = dsi_read_reg(dsidev, DSI_VM_TIMING1); | ||
3928 | r = FLD_MOD(r, hbp, 11, 0); /* HBP */ | ||
3929 | r = FLD_MOD(r, hfp, 23, 12); /* HFP */ | ||
3930 | r = FLD_MOD(r, hsync_end ? hsa : 0, 31, 24); /* HSA */ | ||
3931 | dsi_write_reg(dsidev, DSI_VM_TIMING1, r); | ||
3932 | |||
3933 | r = dsi_read_reg(dsidev, DSI_VM_TIMING2); | ||
3934 | r = FLD_MOD(r, vbp, 7, 0); /* VBP */ | ||
3935 | r = FLD_MOD(r, vfp, 15, 8); /* VFP */ | ||
3936 | r = FLD_MOD(r, vsa, 23, 16); /* VSA */ | ||
3937 | r = FLD_MOD(r, window_sync, 27, 24); /* WINDOW_SYNC */ | ||
3938 | dsi_write_reg(dsidev, DSI_VM_TIMING2, r); | ||
3939 | |||
3940 | r = dsi_read_reg(dsidev, DSI_VM_TIMING3); | ||
3941 | r = FLD_MOD(r, timings->y_res, 14, 0); /* VACT */ | ||
3942 | r = FLD_MOD(r, tl, 31, 16); /* TL */ | ||
3943 | dsi_write_reg(dsidev, DSI_VM_TIMING3, r); | ||
3646 | } | 3944 | } |
3945 | } | ||
3647 | 3946 | ||
3648 | #define DSI_PUSH(dsidev, ch, data) \ | 3947 | int dsi_video_mode_enable(struct omap_dss_device *dssdev, int channel) |
3649 | do { \ | ||
3650 | __dsi_cv |= (data) << (__dsi_cb * 8); \ | ||
3651 | /*DSSDBG("cv = %#010x, cb = %d\n", __dsi_cv, __dsi_cb);*/ \ | ||
3652 | if (++__dsi_cb > 3) \ | ||
3653 | DSI_FLUSH(dsidev, ch); \ | ||
3654 | } while (0) | ||
3655 | |||
3656 | static int dsi_update_screen_l4(struct omap_dss_device *dssdev, | ||
3657 | int x, int y, int w, int h) | ||
3658 | { | 3948 | { |
3659 | /* Note: supports only 24bit colors in 32bit container */ | ||
3660 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | 3949 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); |
3661 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | 3950 | int bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt); |
3662 | int first = 1; | 3951 | u8 data_type; |
3663 | int fifo_stalls = 0; | 3952 | u16 word_count; |
3664 | int max_dsi_packet_size; | ||
3665 | int max_data_per_packet; | ||
3666 | int max_pixels_per_packet; | ||
3667 | int pixels_left; | ||
3668 | int bytespp = dssdev->ctrl.pixel_size / 8; | ||
3669 | int scr_width; | ||
3670 | u32 __iomem *data; | ||
3671 | int start_offset; | ||
3672 | int horiz_inc; | ||
3673 | int current_x; | ||
3674 | struct omap_overlay *ovl; | ||
3675 | |||
3676 | debug_irq = 0; | ||
3677 | |||
3678 | DSSDBG("dsi_update_screen_l4 (%d,%d %dx%d)\n", | ||
3679 | x, y, w, h); | ||
3680 | 3953 | ||
3681 | ovl = dssdev->manager->overlays[0]; | 3954 | switch (dssdev->panel.dsi_pix_fmt) { |
3682 | 3955 | case OMAP_DSS_DSI_FMT_RGB888: | |
3683 | if (ovl->info.color_mode != OMAP_DSS_COLOR_RGB24U) | 3956 | data_type = MIPI_DSI_PACKED_PIXEL_STREAM_24; |
3684 | return -EINVAL; | 3957 | break; |
3685 | 3958 | case OMAP_DSS_DSI_FMT_RGB666: | |
3686 | if (dssdev->ctrl.pixel_size != 24) | 3959 | data_type = MIPI_DSI_PIXEL_STREAM_3BYTE_18; |
3687 | return -EINVAL; | 3960 | break; |
3688 | 3961 | case OMAP_DSS_DSI_FMT_RGB666_PACKED: | |
3689 | scr_width = ovl->info.screen_width; | 3962 | data_type = MIPI_DSI_PACKED_PIXEL_STREAM_18; |
3690 | data = ovl->info.vaddr; | 3963 | break; |
3691 | 3964 | case OMAP_DSS_DSI_FMT_RGB565: | |
3692 | start_offset = scr_width * y + x; | 3965 | data_type = MIPI_DSI_PACKED_PIXEL_STREAM_16; |
3693 | horiz_inc = scr_width - w; | 3966 | break; |
3694 | current_x = x; | 3967 | default: |
3695 | 3968 | BUG(); | |
3696 | /* We need header(4) + DCSCMD(1) + pixels(numpix*bytespp) bytes | 3969 | }; |
3697 | * in fifo */ | ||
3698 | |||
3699 | /* When using CPU, max long packet size is TX buffer size */ | ||
3700 | max_dsi_packet_size = dsi->vc[0].fifo_size * 32 * 4; | ||
3701 | |||
3702 | /* we seem to get better perf if we divide the tx fifo to half, | ||
3703 | and while the other half is being sent, we fill the other half | ||
3704 | max_dsi_packet_size /= 2; */ | ||
3705 | |||
3706 | max_data_per_packet = max_dsi_packet_size - 4 - 1; | ||
3707 | |||
3708 | max_pixels_per_packet = max_data_per_packet / bytespp; | ||
3709 | |||
3710 | DSSDBG("max_pixels_per_packet %d\n", max_pixels_per_packet); | ||
3711 | |||
3712 | pixels_left = w * h; | ||
3713 | 3970 | ||
3714 | DSSDBG("total pixels %d\n", pixels_left); | 3971 | dsi_if_enable(dsidev, false); |
3972 | dsi_vc_enable(dsidev, channel, false); | ||
3715 | 3973 | ||
3716 | data += start_offset; | 3974 | /* MODE, 1 = video mode */ |
3975 | REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 1, 4, 4); | ||
3717 | 3976 | ||
3718 | while (pixels_left > 0) { | 3977 | word_count = DIV_ROUND_UP(dssdev->panel.timings.x_res * bpp, 8); |
3719 | /* 0x2c = write_memory_start */ | ||
3720 | /* 0x3c = write_memory_continue */ | ||
3721 | u8 dcs_cmd = first ? 0x2c : 0x3c; | ||
3722 | int pixels; | ||
3723 | DSI_DECL_VARS; | ||
3724 | first = 0; | ||
3725 | 3978 | ||
3726 | #if 1 | 3979 | dsi_vc_write_long_header(dsidev, channel, data_type, word_count, 0); |
3727 | /* using fifo not empty */ | ||
3728 | /* TX_FIFO_NOT_EMPTY */ | ||
3729 | while (FLD_GET(dsi_read_reg(dsidev, DSI_VC_CTRL(0)), 5, 5)) { | ||
3730 | fifo_stalls++; | ||
3731 | if (fifo_stalls > 0xfffff) { | ||
3732 | DSSERR("fifo stalls overflow, pixels left %d\n", | ||
3733 | pixels_left); | ||
3734 | dsi_if_enable(dsidev, 0); | ||
3735 | return -EIO; | ||
3736 | } | ||
3737 | udelay(1); | ||
3738 | } | ||
3739 | #elif 1 | ||
3740 | /* using fifo emptiness */ | ||
3741 | while ((REG_GET(dsidev, DSI_TX_FIFO_VC_EMPTINESS, 7, 0)+1)*4 < | ||
3742 | max_dsi_packet_size) { | ||
3743 | fifo_stalls++; | ||
3744 | if (fifo_stalls > 0xfffff) { | ||
3745 | DSSERR("fifo stalls overflow, pixels left %d\n", | ||
3746 | pixels_left); | ||
3747 | dsi_if_enable(dsidev, 0); | ||
3748 | return -EIO; | ||
3749 | } | ||
3750 | } | ||
3751 | #else | ||
3752 | while ((REG_GET(dsidev, DSI_TX_FIFO_VC_EMPTINESS, | ||
3753 | 7, 0) + 1) * 4 == 0) { | ||
3754 | fifo_stalls++; | ||
3755 | if (fifo_stalls > 0xfffff) { | ||
3756 | DSSERR("fifo stalls overflow, pixels left %d\n", | ||
3757 | pixels_left); | ||
3758 | dsi_if_enable(dsidev, 0); | ||
3759 | return -EIO; | ||
3760 | } | ||
3761 | } | ||
3762 | #endif | ||
3763 | pixels = min(max_pixels_per_packet, pixels_left); | ||
3764 | 3980 | ||
3765 | pixels_left -= pixels; | 3981 | dsi_vc_enable(dsidev, channel, true); |
3982 | dsi_if_enable(dsidev, true); | ||
3766 | 3983 | ||
3767 | dsi_vc_write_long_header(dsidev, 0, DSI_DT_DCS_LONG_WRITE, | 3984 | dssdev->manager->enable(dssdev->manager); |
3768 | 1 + pixels * bytespp, 0); | ||
3769 | 3985 | ||
3770 | DSI_PUSH(dsidev, 0, dcs_cmd); | 3986 | return 0; |
3987 | } | ||
3988 | EXPORT_SYMBOL(dsi_video_mode_enable); | ||
3771 | 3989 | ||
3772 | while (pixels-- > 0) { | 3990 | void dsi_video_mode_disable(struct omap_dss_device *dssdev, int channel) |
3773 | u32 pix = __raw_readl(data++); | 3991 | { |
3992 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | ||
3774 | 3993 | ||
3775 | DSI_PUSH(dsidev, 0, (pix >> 16) & 0xff); | 3994 | dsi_if_enable(dsidev, false); |
3776 | DSI_PUSH(dsidev, 0, (pix >> 8) & 0xff); | 3995 | dsi_vc_enable(dsidev, channel, false); |
3777 | DSI_PUSH(dsidev, 0, (pix >> 0) & 0xff); | ||
3778 | 3996 | ||
3779 | current_x++; | 3997 | /* MODE, 0 = command mode */ |
3780 | if (current_x == x+w) { | 3998 | REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 0, 4, 4); |
3781 | current_x = x; | ||
3782 | data += horiz_inc; | ||
3783 | } | ||
3784 | } | ||
3785 | 3999 | ||
3786 | DSI_FLUSH(dsidev, 0); | 4000 | dsi_vc_enable(dsidev, channel, true); |
3787 | } | 4001 | dsi_if_enable(dsidev, true); |
3788 | 4002 | ||
3789 | return 0; | 4003 | dssdev->manager->disable(dssdev->manager); |
3790 | } | 4004 | } |
4005 | EXPORT_SYMBOL(dsi_video_mode_disable); | ||
3791 | 4006 | ||
3792 | static void dsi_update_screen_dispc(struct omap_dss_device *dssdev, | 4007 | static void dsi_update_screen_dispc(struct omap_dss_device *dssdev, |
3793 | u16 x, u16 y, u16 w, u16 h) | 4008 | u16 x, u16 y, u16 w, u16 h) |
@@ -3808,9 +4023,9 @@ static void dsi_update_screen_dispc(struct omap_dss_device *dssdev, | |||
3808 | DSSDBG("dsi_update_screen_dispc(%d,%d %dx%d)\n", | 4023 | DSSDBG("dsi_update_screen_dispc(%d,%d %dx%d)\n", |
3809 | x, y, w, h); | 4024 | x, y, w, h); |
3810 | 4025 | ||
3811 | dsi_vc_config_vp(dsidev, channel); | 4026 | dsi_vc_config_source(dsidev, channel, DSI_VC_SOURCE_VP); |
3812 | 4027 | ||
3813 | bytespp = dssdev->ctrl.pixel_size / 8; | 4028 | bytespp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt) / 8; |
3814 | bytespl = w * bytespp; | 4029 | bytespl = w * bytespp; |
3815 | bytespf = bytespl * h; | 4030 | bytespf = bytespl * h; |
3816 | 4031 | ||
@@ -3831,7 +4046,7 @@ static void dsi_update_screen_dispc(struct omap_dss_device *dssdev, | |||
3831 | l = FLD_VAL(total_len, 23, 0); /* TE_SIZE */ | 4046 | l = FLD_VAL(total_len, 23, 0); /* TE_SIZE */ |
3832 | dsi_write_reg(dsidev, DSI_VC_TE(channel), l); | 4047 | dsi_write_reg(dsidev, DSI_VC_TE(channel), l); |
3833 | 4048 | ||
3834 | dsi_vc_write_long_header(dsidev, channel, DSI_DT_DCS_LONG_WRITE, | 4049 | dsi_vc_write_long_header(dsidev, channel, MIPI_DSI_DCS_LONG_WRITE, |
3835 | packet_len, 0); | 4050 | packet_len, 0); |
3836 | 4051 | ||
3837 | if (dsi->te_enabled) | 4052 | if (dsi->te_enabled) |
@@ -3956,11 +4171,9 @@ int omap_dsi_prepare_update(struct omap_dss_device *dssdev, | |||
3956 | 4171 | ||
3957 | dsi_perf_mark_setup(dsidev); | 4172 | dsi_perf_mark_setup(dsidev); |
3958 | 4173 | ||
3959 | if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) { | 4174 | dss_setup_partial_planes(dssdev, x, y, w, h, |
3960 | dss_setup_partial_planes(dssdev, x, y, w, h, | 4175 | enlarge_update_area); |
3961 | enlarge_update_area); | 4176 | dispc_mgr_set_lcd_size(dssdev->manager->id, *w, *h); |
3962 | dispc_set_lcd_size(dssdev->manager->id, *w, *h); | ||
3963 | } | ||
3964 | 4177 | ||
3965 | return 0; | 4178 | return 0; |
3966 | } | 4179 | } |
@@ -3982,27 +4195,16 @@ int omap_dsi_update(struct omap_dss_device *dssdev, | |||
3982 | * see rather obscure HW error happening, as DSS halts. */ | 4195 | * see rather obscure HW error happening, as DSS halts. */ |
3983 | BUG_ON(x % 2 == 1); | 4196 | BUG_ON(x % 2 == 1); |
3984 | 4197 | ||
3985 | if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) { | 4198 | dsi->framedone_callback = callback; |
3986 | dsi->framedone_callback = callback; | 4199 | dsi->framedone_data = data; |
3987 | dsi->framedone_data = data; | ||
3988 | |||
3989 | dsi->update_region.x = x; | ||
3990 | dsi->update_region.y = y; | ||
3991 | dsi->update_region.w = w; | ||
3992 | dsi->update_region.h = h; | ||
3993 | dsi->update_region.device = dssdev; | ||
3994 | |||
3995 | dsi_update_screen_dispc(dssdev, x, y, w, h); | ||
3996 | } else { | ||
3997 | int r; | ||
3998 | 4200 | ||
3999 | r = dsi_update_screen_l4(dssdev, x, y, w, h); | 4201 | dsi->update_region.x = x; |
4000 | if (r) | 4202 | dsi->update_region.y = y; |
4001 | return r; | 4203 | dsi->update_region.w = w; |
4204 | dsi->update_region.h = h; | ||
4205 | dsi->update_region.device = dssdev; | ||
4002 | 4206 | ||
4003 | dsi_perf_show(dsidev, "L4"); | 4207 | dsi_update_screen_dispc(dssdev, x, y, w, h); |
4004 | callback(0, data); | ||
4005 | } | ||
4006 | 4208 | ||
4007 | return 0; | 4209 | return 0; |
4008 | } | 4210 | } |
@@ -4013,28 +4215,9 @@ EXPORT_SYMBOL(omap_dsi_update); | |||
4013 | static int dsi_display_init_dispc(struct omap_dss_device *dssdev) | 4215 | static int dsi_display_init_dispc(struct omap_dss_device *dssdev) |
4014 | { | 4216 | { |
4015 | int r; | 4217 | int r; |
4016 | u32 irq; | ||
4017 | |||
4018 | irq = dssdev->manager->id == OMAP_DSS_CHANNEL_LCD ? | ||
4019 | DISPC_IRQ_FRAMEDONE : DISPC_IRQ_FRAMEDONE2; | ||
4020 | 4218 | ||
4021 | r = omap_dispc_register_isr(dsi_framedone_irq_callback, (void *) dssdev, | 4219 | if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_CMD_MODE) { |
4022 | irq); | 4220 | u32 irq; |
4023 | if (r) { | ||
4024 | DSSERR("can't get FRAMEDONE irq\n"); | ||
4025 | return r; | ||
4026 | } | ||
4027 | |||
4028 | dispc_set_lcd_display_type(dssdev->manager->id, | ||
4029 | OMAP_DSS_LCD_DISPLAY_TFT); | ||
4030 | |||
4031 | dispc_set_parallel_interface_mode(dssdev->manager->id, | ||
4032 | OMAP_DSS_PARALLELMODE_DSI); | ||
4033 | dispc_enable_fifohandcheck(dssdev->manager->id, 1); | ||
4034 | |||
4035 | dispc_set_tft_data_lines(dssdev->manager->id, dssdev->ctrl.pixel_size); | ||
4036 | |||
4037 | { | ||
4038 | struct omap_video_timings timings = { | 4221 | struct omap_video_timings timings = { |
4039 | .hsw = 1, | 4222 | .hsw = 1, |
4040 | .hfp = 1, | 4223 | .hfp = 1, |
@@ -4044,21 +4227,46 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev) | |||
4044 | .vbp = 0, | 4227 | .vbp = 0, |
4045 | }; | 4228 | }; |
4046 | 4229 | ||
4047 | dispc_set_lcd_timings(dssdev->manager->id, &timings); | 4230 | irq = dssdev->manager->id == OMAP_DSS_CHANNEL_LCD ? |
4231 | DISPC_IRQ_FRAMEDONE : DISPC_IRQ_FRAMEDONE2; | ||
4232 | |||
4233 | r = omap_dispc_register_isr(dsi_framedone_irq_callback, | ||
4234 | (void *) dssdev, irq); | ||
4235 | if (r) { | ||
4236 | DSSERR("can't get FRAMEDONE irq\n"); | ||
4237 | return r; | ||
4238 | } | ||
4239 | |||
4240 | dispc_mgr_enable_stallmode(dssdev->manager->id, true); | ||
4241 | dispc_mgr_enable_fifohandcheck(dssdev->manager->id, 1); | ||
4242 | |||
4243 | dispc_mgr_set_lcd_timings(dssdev->manager->id, &timings); | ||
4244 | } else { | ||
4245 | dispc_mgr_enable_stallmode(dssdev->manager->id, false); | ||
4246 | dispc_mgr_enable_fifohandcheck(dssdev->manager->id, 0); | ||
4247 | |||
4248 | dispc_mgr_set_lcd_timings(dssdev->manager->id, | ||
4249 | &dssdev->panel.timings); | ||
4048 | } | 4250 | } |
4049 | 4251 | ||
4252 | dispc_mgr_set_lcd_display_type(dssdev->manager->id, | ||
4253 | OMAP_DSS_LCD_DISPLAY_TFT); | ||
4254 | dispc_mgr_set_tft_data_lines(dssdev->manager->id, | ||
4255 | dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt)); | ||
4050 | return 0; | 4256 | return 0; |
4051 | } | 4257 | } |
4052 | 4258 | ||
4053 | static void dsi_display_uninit_dispc(struct omap_dss_device *dssdev) | 4259 | static void dsi_display_uninit_dispc(struct omap_dss_device *dssdev) |
4054 | { | 4260 | { |
4055 | u32 irq; | 4261 | if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_CMD_MODE) { |
4262 | u32 irq; | ||
4056 | 4263 | ||
4057 | irq = dssdev->manager->id == OMAP_DSS_CHANNEL_LCD ? | 4264 | irq = dssdev->manager->id == OMAP_DSS_CHANNEL_LCD ? |
4058 | DISPC_IRQ_FRAMEDONE : DISPC_IRQ_FRAMEDONE2; | 4265 | DISPC_IRQ_FRAMEDONE : DISPC_IRQ_FRAMEDONE2; |
4059 | 4266 | ||
4060 | omap_dispc_unregister_isr(dsi_framedone_irq_callback, (void *) dssdev, | 4267 | omap_dispc_unregister_isr(dsi_framedone_irq_callback, |
4061 | irq); | 4268 | (void *) dssdev, irq); |
4269 | } | ||
4062 | } | 4270 | } |
4063 | 4271 | ||
4064 | static int dsi_configure_dsi_clocks(struct omap_dss_device *dssdev) | 4272 | static int dsi_configure_dsi_clocks(struct omap_dss_device *dssdev) |
@@ -4106,7 +4314,7 @@ static int dsi_configure_dispc_clocks(struct omap_dss_device *dssdev) | |||
4106 | return r; | 4314 | return r; |
4107 | } | 4315 | } |
4108 | 4316 | ||
4109 | r = dispc_set_clock_div(dssdev->manager->id, &dispc_cinfo); | 4317 | r = dispc_mgr_set_clock_div(dssdev->manager->id, &dispc_cinfo); |
4110 | if (r) { | 4318 | if (r) { |
4111 | DSSERR("Failed to set dispc clocks\n"); | 4319 | DSSERR("Failed to set dispc clocks\n"); |
4112 | return r; | 4320 | return r; |
@@ -4166,10 +4374,12 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev) | |||
4166 | 4374 | ||
4167 | return 0; | 4375 | return 0; |
4168 | err3: | 4376 | err3: |
4169 | dsi_cio_uninit(dsidev); | 4377 | dsi_cio_uninit(dssdev); |
4170 | err2: | 4378 | err2: |
4171 | dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK); | 4379 | dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK); |
4172 | dss_select_dsi_clk_source(dsi_module, OMAP_DSS_CLK_SRC_FCK); | 4380 | dss_select_dsi_clk_source(dsi_module, OMAP_DSS_CLK_SRC_FCK); |
4381 | dss_select_lcd_clk_source(dssdev->manager->id, OMAP_DSS_CLK_SRC_FCK); | ||
4382 | |||
4173 | err1: | 4383 | err1: |
4174 | dsi_pll_uninit(dsidev, true); | 4384 | dsi_pll_uninit(dsidev, true); |
4175 | err0: | 4385 | err0: |
@@ -4195,7 +4405,8 @@ static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev, | |||
4195 | 4405 | ||
4196 | dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK); | 4406 | dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK); |
4197 | dss_select_dsi_clk_source(dsi_module, OMAP_DSS_CLK_SRC_FCK); | 4407 | dss_select_dsi_clk_source(dsi_module, OMAP_DSS_CLK_SRC_FCK); |
4198 | dsi_cio_uninit(dsidev); | 4408 | dss_select_lcd_clk_source(dssdev->manager->id, OMAP_DSS_CLK_SRC_FCK); |
4409 | dsi_cio_uninit(dssdev); | ||
4199 | dsi_pll_uninit(dsidev, disconnect_lanes); | 4410 | dsi_pll_uninit(dsidev, disconnect_lanes); |
4200 | } | 4411 | } |
4201 | 4412 | ||
@@ -4211,6 +4422,12 @@ int omapdss_dsi_display_enable(struct omap_dss_device *dssdev) | |||
4211 | 4422 | ||
4212 | mutex_lock(&dsi->lock); | 4423 | mutex_lock(&dsi->lock); |
4213 | 4424 | ||
4425 | if (dssdev->manager == NULL) { | ||
4426 | DSSERR("failed to enable display: no manager\n"); | ||
4427 | r = -ENODEV; | ||
4428 | goto err_start_dev; | ||
4429 | } | ||
4430 | |||
4214 | r = omap_dss_start_device(dssdev); | 4431 | r = omap_dss_start_device(dssdev); |
4215 | if (r) { | 4432 | if (r) { |
4216 | DSSERR("failed to start device\n"); | 4433 | DSSERR("failed to start device\n"); |
@@ -4307,9 +4524,10 @@ int dsi_init_display(struct omap_dss_device *dssdev) | |||
4307 | 4524 | ||
4308 | DSSDBG("DSI init\n"); | 4525 | DSSDBG("DSI init\n"); |
4309 | 4526 | ||
4310 | /* XXX these should be figured out dynamically */ | 4527 | if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_CMD_MODE) { |
4311 | dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE | | 4528 | dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE | |
4312 | OMAP_DSS_DISPLAY_CAP_TEAR_ELIM; | 4529 | OMAP_DSS_DISPLAY_CAP_TEAR_ELIM; |
4530 | } | ||
4313 | 4531 | ||
4314 | if (dsi->vdds_dsi_reg == NULL) { | 4532 | if (dsi->vdds_dsi_reg == NULL) { |
4315 | struct regulator *vdds_dsi; | 4533 | struct regulator *vdds_dsi; |
@@ -4435,10 +4653,7 @@ static int dsi_get_clocks(struct platform_device *dsidev) | |||
4435 | 4653 | ||
4436 | dsi->dss_clk = clk; | 4654 | dsi->dss_clk = clk; |
4437 | 4655 | ||
4438 | if (cpu_is_omap34xx() || cpu_is_omap3630()) | 4656 | clk = clk_get(&dsidev->dev, "sys_clk"); |
4439 | clk = clk_get(&dsidev->dev, "dss2_alwon_fck"); | ||
4440 | else | ||
4441 | clk = clk_get(&dsidev->dev, "sys_clk"); | ||
4442 | if (IS_ERR(clk)) { | 4657 | if (IS_ERR(clk)) { |
4443 | DSSERR("can't get sys_clk\n"); | 4658 | DSSERR("can't get sys_clk\n"); |
4444 | clk_put(dsi->dss_clk); | 4659 | clk_put(dsi->dss_clk); |
@@ -4462,7 +4677,7 @@ static void dsi_put_clocks(struct platform_device *dsidev) | |||
4462 | } | 4677 | } |
4463 | 4678 | ||
4464 | /* DSI1 HW IP initialisation */ | 4679 | /* DSI1 HW IP initialisation */ |
4465 | static int omap_dsi1hw_probe(struct platform_device *dsidev) | 4680 | static int omap_dsihw_probe(struct platform_device *dsidev) |
4466 | { | 4681 | { |
4467 | struct omap_display_platform_data *dss_plat_data; | 4682 | struct omap_display_platform_data *dss_plat_data; |
4468 | struct omap_dss_board_info *board_info; | 4683 | struct omap_dss_board_info *board_info; |
@@ -4483,7 +4698,8 @@ static int omap_dsi1hw_probe(struct platform_device *dsidev) | |||
4483 | 4698 | ||
4484 | dss_plat_data = dsidev->dev.platform_data; | 4699 | dss_plat_data = dsidev->dev.platform_data; |
4485 | board_info = dss_plat_data->board_data; | 4700 | board_info = dss_plat_data->board_data; |
4486 | dsi->dsi_mux_pads = board_info->dsi_mux_pads; | 4701 | dsi->enable_pads = board_info->dsi_enable_pads; |
4702 | dsi->disable_pads = board_info->dsi_disable_pads; | ||
4487 | 4703 | ||
4488 | spin_lock_init(&dsi->irq_lock); | 4704 | spin_lock_init(&dsi->irq_lock); |
4489 | spin_lock_init(&dsi->errors_lock); | 4705 | spin_lock_init(&dsi->errors_lock); |
@@ -4539,7 +4755,7 @@ static int omap_dsi1hw_probe(struct platform_device *dsidev) | |||
4539 | 4755 | ||
4540 | /* DSI VCs initialization */ | 4756 | /* DSI VCs initialization */ |
4541 | for (i = 0; i < ARRAY_SIZE(dsi->vc); i++) { | 4757 | for (i = 0; i < ARRAY_SIZE(dsi->vc); i++) { |
4542 | dsi->vc[i].mode = DSI_VC_MODE_L4; | 4758 | dsi->vc[i].source = DSI_VC_SOURCE_L4; |
4543 | dsi->vc[i].dssdev = NULL; | 4759 | dsi->vc[i].dssdev = NULL; |
4544 | dsi->vc[i].vc_id = 0; | 4760 | dsi->vc[i].vc_id = 0; |
4545 | } | 4761 | } |
@@ -4572,7 +4788,7 @@ err_alloc: | |||
4572 | return r; | 4788 | return r; |
4573 | } | 4789 | } |
4574 | 4790 | ||
4575 | static int omap_dsi1hw_remove(struct platform_device *dsidev) | 4791 | static int omap_dsihw_remove(struct platform_device *dsidev) |
4576 | { | 4792 | { |
4577 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | 4793 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
4578 | 4794 | ||
@@ -4602,10 +4818,6 @@ static int omap_dsi1hw_remove(struct platform_device *dsidev) | |||
4602 | 4818 | ||
4603 | static int dsi_runtime_suspend(struct device *dev) | 4819 | static int dsi_runtime_suspend(struct device *dev) |
4604 | { | 4820 | { |
4605 | struct dsi_data *dsi = dsi_get_dsidrv_data(to_platform_device(dev)); | ||
4606 | |||
4607 | clk_disable(dsi->dss_clk); | ||
4608 | |||
4609 | dispc_runtime_put(); | 4821 | dispc_runtime_put(); |
4610 | dss_runtime_put(); | 4822 | dss_runtime_put(); |
4611 | 4823 | ||
@@ -4614,7 +4826,6 @@ static int dsi_runtime_suspend(struct device *dev) | |||
4614 | 4826 | ||
4615 | static int dsi_runtime_resume(struct device *dev) | 4827 | static int dsi_runtime_resume(struct device *dev) |
4616 | { | 4828 | { |
4617 | struct dsi_data *dsi = dsi_get_dsidrv_data(to_platform_device(dev)); | ||
4618 | int r; | 4829 | int r; |
4619 | 4830 | ||
4620 | r = dss_runtime_get(); | 4831 | r = dss_runtime_get(); |
@@ -4625,8 +4836,6 @@ static int dsi_runtime_resume(struct device *dev) | |||
4625 | if (r) | 4836 | if (r) |
4626 | goto err_get_dispc; | 4837 | goto err_get_dispc; |
4627 | 4838 | ||
4628 | clk_enable(dsi->dss_clk); | ||
4629 | |||
4630 | return 0; | 4839 | return 0; |
4631 | 4840 | ||
4632 | err_get_dispc: | 4841 | err_get_dispc: |
@@ -4640,11 +4849,11 @@ static const struct dev_pm_ops dsi_pm_ops = { | |||
4640 | .runtime_resume = dsi_runtime_resume, | 4849 | .runtime_resume = dsi_runtime_resume, |
4641 | }; | 4850 | }; |
4642 | 4851 | ||
4643 | static struct platform_driver omap_dsi1hw_driver = { | 4852 | static struct platform_driver omap_dsihw_driver = { |
4644 | .probe = omap_dsi1hw_probe, | 4853 | .probe = omap_dsihw_probe, |
4645 | .remove = omap_dsi1hw_remove, | 4854 | .remove = omap_dsihw_remove, |
4646 | .driver = { | 4855 | .driver = { |
4647 | .name = "omapdss_dsi1", | 4856 | .name = "omapdss_dsi", |
4648 | .owner = THIS_MODULE, | 4857 | .owner = THIS_MODULE, |
4649 | .pm = &dsi_pm_ops, | 4858 | .pm = &dsi_pm_ops, |
4650 | }, | 4859 | }, |
@@ -4652,10 +4861,10 @@ static struct platform_driver omap_dsi1hw_driver = { | |||
4652 | 4861 | ||
4653 | int dsi_init_platform_driver(void) | 4862 | int dsi_init_platform_driver(void) |
4654 | { | 4863 | { |
4655 | return platform_driver_register(&omap_dsi1hw_driver); | 4864 | return platform_driver_register(&omap_dsihw_driver); |
4656 | } | 4865 | } |
4657 | 4866 | ||
4658 | void dsi_uninit_platform_driver(void) | 4867 | void dsi_uninit_platform_driver(void) |
4659 | { | 4868 | { |
4660 | return platform_driver_unregister(&omap_dsi1hw_driver); | 4869 | return platform_driver_unregister(&omap_dsihw_driver); |
4661 | } | 4870 | } |
diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c index 0f9c3a6457a5..3e09726d32c7 100644 --- a/drivers/video/omap2/dss/dss.c +++ b/drivers/video/omap2/dss/dss.c | |||
@@ -639,6 +639,17 @@ void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select hdmi) | |||
639 | REG_FLD_MOD(DSS_CONTROL, hdmi, 15, 15); /* VENC_HDMI_SWITCH */ | 639 | REG_FLD_MOD(DSS_CONTROL, hdmi, 15, 15); /* VENC_HDMI_SWITCH */ |
640 | } | 640 | } |
641 | 641 | ||
642 | enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void) | ||
643 | { | ||
644 | enum omap_display_type displays; | ||
645 | |||
646 | displays = dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_DIGIT); | ||
647 | if ((displays & OMAP_DISPLAY_TYPE_HDMI) == 0) | ||
648 | return DSS_VENC_TV_CLK; | ||
649 | |||
650 | return REG_GET(DSS_CONTROL, 15, 15); | ||
651 | } | ||
652 | |||
642 | static int dss_get_clocks(void) | 653 | static int dss_get_clocks(void) |
643 | { | 654 | { |
644 | struct clk *clk; | 655 | struct clk *clk; |
@@ -691,11 +702,6 @@ static void dss_put_clocks(void) | |||
691 | clk_put(dss.dss_clk); | 702 | clk_put(dss.dss_clk); |
692 | } | 703 | } |
693 | 704 | ||
694 | struct clk *dss_get_ick(void) | ||
695 | { | ||
696 | return clk_get(&dss.pdev->dev, "ick"); | ||
697 | } | ||
698 | |||
699 | int dss_runtime_get(void) | 705 | int dss_runtime_get(void) |
700 | { | 706 | { |
701 | int r; | 707 | int r; |
@@ -824,13 +830,11 @@ static int omap_dsshw_remove(struct platform_device *pdev) | |||
824 | static int dss_runtime_suspend(struct device *dev) | 830 | static int dss_runtime_suspend(struct device *dev) |
825 | { | 831 | { |
826 | dss_save_context(); | 832 | dss_save_context(); |
827 | clk_disable(dss.dss_clk); | ||
828 | return 0; | 833 | return 0; |
829 | } | 834 | } |
830 | 835 | ||
831 | static int dss_runtime_resume(struct device *dev) | 836 | static int dss_runtime_resume(struct device *dev) |
832 | { | 837 | { |
833 | clk_enable(dss.dss_clk); | ||
834 | dss_restore_context(); | 838 | dss_restore_context(); |
835 | return 0; | 839 | return 0; |
836 | } | 840 | } |
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h index 9c94b1152c20..6308fc59fc9e 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h | |||
@@ -97,10 +97,10 @@ extern unsigned int dss_debug; | |||
97 | #define FLD_MOD(orig, val, start, end) \ | 97 | #define FLD_MOD(orig, val, start, end) \ |
98 | (((orig) & ~FLD_MASK(start, end)) | FLD_VAL(val, start, end)) | 98 | (((orig) & ~FLD_MASK(start, end)) | FLD_VAL(val, start, end)) |
99 | 99 | ||
100 | enum omap_parallel_interface_mode { | 100 | enum dss_io_pad_mode { |
101 | OMAP_DSS_PARALLELMODE_BYPASS, /* MIPI DPI */ | 101 | DSS_IO_PAD_MODE_RESET, |
102 | OMAP_DSS_PARALLELMODE_RFBI, /* MIPI DBI */ | 102 | DSS_IO_PAD_MODE_RFBI, |
103 | OMAP_DSS_PARALLELMODE_DSI, | 103 | DSS_IO_PAD_MODE_BYPASS, |
104 | }; | 104 | }; |
105 | 105 | ||
106 | enum dss_hdmi_venc_clk_source_select { | 106 | enum dss_hdmi_venc_clk_source_select { |
@@ -108,6 +108,11 @@ enum dss_hdmi_venc_clk_source_select { | |||
108 | DSS_HDMI_M_PCLK = 1, | 108 | DSS_HDMI_M_PCLK = 1, |
109 | }; | 109 | }; |
110 | 110 | ||
111 | enum dss_dsi_content_type { | ||
112 | DSS_DSI_CONTENT_DCS, | ||
113 | DSS_DSI_CONTENT_GENERIC, | ||
114 | }; | ||
115 | |||
111 | struct dss_clock_info { | 116 | struct dss_clock_info { |
112 | /* rates that we get with dividers below */ | 117 | /* rates that we get with dividers below */ |
113 | unsigned long fck; | 118 | unsigned long fck; |
@@ -150,16 +155,6 @@ struct dsi_clock_info { | |||
150 | bool use_sys_clk; | 155 | bool use_sys_clk; |
151 | }; | 156 | }; |
152 | 157 | ||
153 | /* HDMI PLL structure */ | ||
154 | struct hdmi_pll_info { | ||
155 | u16 regn; | ||
156 | u16 regm; | ||
157 | u32 regmf; | ||
158 | u16 regm2; | ||
159 | u16 regsd; | ||
160 | u16 dcofreq; | ||
161 | }; | ||
162 | |||
163 | struct seq_file; | 158 | struct seq_file; |
164 | struct platform_device; | 159 | struct platform_device; |
165 | 160 | ||
@@ -209,9 +204,8 @@ void dss_uninit_platform_driver(void); | |||
209 | int dss_runtime_get(void); | 204 | int dss_runtime_get(void); |
210 | void dss_runtime_put(void); | 205 | void dss_runtime_put(void); |
211 | 206 | ||
212 | struct clk *dss_get_ick(void); | ||
213 | |||
214 | void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select); | 207 | void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select); |
208 | enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void); | ||
215 | const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src); | 209 | const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src); |
216 | void dss_dump_clocks(struct seq_file *s); | 210 | void dss_dump_clocks(struct seq_file *s); |
217 | 211 | ||
@@ -279,6 +273,8 @@ void dsi_create_debugfs_files_reg(struct dentry *debugfs_dir, | |||
279 | 273 | ||
280 | int dsi_init_display(struct omap_dss_device *display); | 274 | int dsi_init_display(struct omap_dss_device *display); |
281 | void dsi_irq_handler(void); | 275 | void dsi_irq_handler(void); |
276 | u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt); | ||
277 | |||
282 | unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev); | 278 | unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev); |
283 | int dsi_pll_set_clock_div(struct platform_device *dsidev, | 279 | int dsi_pll_set_clock_div(struct platform_device *dsidev, |
284 | struct dsi_clock_info *cinfo); | 280 | struct dsi_clock_info *cinfo); |
@@ -309,6 +305,11 @@ static inline int dsi_runtime_get(struct platform_device *dsidev) | |||
309 | static inline void dsi_runtime_put(struct platform_device *dsidev) | 305 | static inline void dsi_runtime_put(struct platform_device *dsidev) |
310 | { | 306 | { |
311 | } | 307 | } |
308 | static inline u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt) | ||
309 | { | ||
310 | WARN("%s: DSI not compiled in, returning pixel_size as 0\n", __func__); | ||
311 | return 0; | ||
312 | } | ||
312 | static inline unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev) | 313 | static inline unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev) |
313 | { | 314 | { |
314 | WARN("%s: DSI not compiled in, returning rate as 0\n", __func__); | 315 | WARN("%s: DSI not compiled in, returning rate as 0\n", __func__); |
@@ -385,90 +386,71 @@ void dispc_disable_sidle(void); | |||
385 | void dispc_lcd_enable_signal_polarity(bool act_high); | 386 | void dispc_lcd_enable_signal_polarity(bool act_high); |
386 | void dispc_lcd_enable_signal(bool enable); | 387 | void dispc_lcd_enable_signal(bool enable); |
387 | void dispc_pck_free_enable(bool enable); | 388 | void dispc_pck_free_enable(bool enable); |
388 | void dispc_enable_fifohandcheck(enum omap_channel channel, bool enable); | ||
389 | |||
390 | void dispc_set_lcd_size(enum omap_channel channel, u16 width, u16 height); | ||
391 | void dispc_set_digit_size(u16 width, u16 height); | 389 | void dispc_set_digit_size(u16 width, u16 height); |
392 | u32 dispc_get_plane_fifo_size(enum omap_plane plane); | ||
393 | void dispc_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high); | ||
394 | void dispc_enable_fifomerge(bool enable); | 390 | void dispc_enable_fifomerge(bool enable); |
395 | u32 dispc_get_burst_size(enum omap_plane plane); | ||
396 | void dispc_enable_cpr(enum omap_channel channel, bool enable); | ||
397 | void dispc_set_cpr_coef(enum omap_channel channel, | ||
398 | struct omap_dss_cpr_coefs *coefs); | ||
399 | |||
400 | void dispc_set_plane_ba0(enum omap_plane plane, u32 paddr); | ||
401 | void dispc_set_plane_ba1(enum omap_plane plane, u32 paddr); | ||
402 | void dispc_set_plane_pos(enum omap_plane plane, u16 x, u16 y); | ||
403 | void dispc_set_plane_size(enum omap_plane plane, u16 width, u16 height); | ||
404 | void dispc_set_channel_out(enum omap_plane plane, | ||
405 | enum omap_channel channel_out); | ||
406 | |||
407 | void dispc_enable_gamma_table(bool enable); | 391 | void dispc_enable_gamma_table(bool enable); |
408 | int dispc_setup_plane(enum omap_plane plane, | ||
409 | u32 paddr, u16 screen_width, | ||
410 | u16 pos_x, u16 pos_y, | ||
411 | u16 width, u16 height, | ||
412 | u16 out_width, u16 out_height, | ||
413 | enum omap_color_mode color_mode, | ||
414 | bool ilace, | ||
415 | enum omap_dss_rotation_type rotation_type, | ||
416 | u8 rotation, bool mirror, | ||
417 | u8 global_alpha, u8 pre_mult_alpha, | ||
418 | enum omap_channel channel, | ||
419 | u32 puv_addr); | ||
420 | |||
421 | bool dispc_go_busy(enum omap_channel channel); | ||
422 | void dispc_go(enum omap_channel channel); | ||
423 | void dispc_enable_channel(enum omap_channel channel, bool enable); | ||
424 | bool dispc_is_channel_enabled(enum omap_channel channel); | ||
425 | int dispc_enable_plane(enum omap_plane plane, bool enable); | ||
426 | void dispc_enable_replication(enum omap_plane plane, bool enable); | ||
427 | |||
428 | void dispc_set_parallel_interface_mode(enum omap_channel channel, | ||
429 | enum omap_parallel_interface_mode mode); | ||
430 | void dispc_set_tft_data_lines(enum omap_channel channel, u8 data_lines); | ||
431 | void dispc_set_lcd_display_type(enum omap_channel channel, | ||
432 | enum omap_lcd_display_type type); | ||
433 | void dispc_set_loadmode(enum omap_dss_load_mode mode); | 392 | void dispc_set_loadmode(enum omap_dss_load_mode mode); |
434 | 393 | ||
435 | void dispc_set_default_color(enum omap_channel channel, u32 color); | ||
436 | u32 dispc_get_default_color(enum omap_channel channel); | ||
437 | void dispc_set_trans_key(enum omap_channel ch, | ||
438 | enum omap_dss_trans_key_type type, | ||
439 | u32 trans_key); | ||
440 | void dispc_get_trans_key(enum omap_channel ch, | ||
441 | enum omap_dss_trans_key_type *type, | ||
442 | u32 *trans_key); | ||
443 | void dispc_enable_trans_key(enum omap_channel ch, bool enable); | ||
444 | void dispc_enable_alpha_blending(enum omap_channel ch, bool enable); | ||
445 | bool dispc_trans_key_enabled(enum omap_channel ch); | ||
446 | bool dispc_alpha_blending_enabled(enum omap_channel ch); | ||
447 | |||
448 | bool dispc_lcd_timings_ok(struct omap_video_timings *timings); | 394 | bool dispc_lcd_timings_ok(struct omap_video_timings *timings); |
449 | void dispc_set_lcd_timings(enum omap_channel channel, | ||
450 | struct omap_video_timings *timings); | ||
451 | unsigned long dispc_fclk_rate(void); | 395 | unsigned long dispc_fclk_rate(void); |
452 | unsigned long dispc_lclk_rate(enum omap_channel channel); | ||
453 | unsigned long dispc_pclk_rate(enum omap_channel channel); | ||
454 | void dispc_set_pol_freq(enum omap_channel channel, | ||
455 | enum omap_panel_config config, u8 acbi, u8 acb); | ||
456 | void dispc_find_clk_divs(bool is_tft, unsigned long req_pck, unsigned long fck, | 396 | void dispc_find_clk_divs(bool is_tft, unsigned long req_pck, unsigned long fck, |
457 | struct dispc_clock_info *cinfo); | 397 | struct dispc_clock_info *cinfo); |
458 | int dispc_calc_clock_rates(unsigned long dispc_fclk_rate, | 398 | int dispc_calc_clock_rates(unsigned long dispc_fclk_rate, |
459 | struct dispc_clock_info *cinfo); | 399 | struct dispc_clock_info *cinfo); |
460 | int dispc_set_clock_div(enum omap_channel channel, | 400 | |
401 | |||
402 | u32 dispc_ovl_get_fifo_size(enum omap_plane plane); | ||
403 | u32 dispc_ovl_get_burst_size(enum omap_plane plane); | ||
404 | int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi, | ||
405 | bool ilace, enum omap_channel channel, bool replication, | ||
406 | u32 fifo_low, u32 fifo_high); | ||
407 | int dispc_ovl_enable(enum omap_plane plane, bool enable); | ||
408 | |||
409 | |||
410 | void dispc_mgr_enable_fifohandcheck(enum omap_channel channel, bool enable); | ||
411 | void dispc_mgr_set_lcd_size(enum omap_channel channel, u16 width, u16 height); | ||
412 | void dispc_mgr_enable_cpr(enum omap_channel channel, bool enable); | ||
413 | void dispc_mgr_set_cpr_coef(enum omap_channel channel, | ||
414 | struct omap_dss_cpr_coefs *coefs); | ||
415 | bool dispc_mgr_go_busy(enum omap_channel channel); | ||
416 | void dispc_mgr_go(enum omap_channel channel); | ||
417 | void dispc_mgr_enable(enum omap_channel channel, bool enable); | ||
418 | bool dispc_mgr_is_channel_enabled(enum omap_channel channel); | ||
419 | void dispc_mgr_set_io_pad_mode(enum dss_io_pad_mode mode); | ||
420 | void dispc_mgr_enable_stallmode(enum omap_channel channel, bool enable); | ||
421 | void dispc_mgr_set_tft_data_lines(enum omap_channel channel, u8 data_lines); | ||
422 | void dispc_mgr_set_lcd_display_type(enum omap_channel channel, | ||
423 | enum omap_lcd_display_type type); | ||
424 | void dispc_mgr_set_default_color(enum omap_channel channel, u32 color); | ||
425 | u32 dispc_mgr_get_default_color(enum omap_channel channel); | ||
426 | void dispc_mgr_set_trans_key(enum omap_channel ch, | ||
427 | enum omap_dss_trans_key_type type, | ||
428 | u32 trans_key); | ||
429 | void dispc_mgr_get_trans_key(enum omap_channel ch, | ||
430 | enum omap_dss_trans_key_type *type, | ||
431 | u32 *trans_key); | ||
432 | void dispc_mgr_enable_trans_key(enum omap_channel ch, bool enable); | ||
433 | void dispc_mgr_enable_alpha_fixed_zorder(enum omap_channel ch, bool enable); | ||
434 | bool dispc_mgr_trans_key_enabled(enum omap_channel ch); | ||
435 | bool dispc_mgr_alpha_fixed_zorder_enabled(enum omap_channel ch); | ||
436 | void dispc_mgr_set_lcd_timings(enum omap_channel channel, | ||
437 | struct omap_video_timings *timings); | ||
438 | void dispc_mgr_set_pol_freq(enum omap_channel channel, | ||
439 | enum omap_panel_config config, u8 acbi, u8 acb); | ||
440 | unsigned long dispc_mgr_lclk_rate(enum omap_channel channel); | ||
441 | unsigned long dispc_mgr_pclk_rate(enum omap_channel channel); | ||
442 | int dispc_mgr_set_clock_div(enum omap_channel channel, | ||
461 | struct dispc_clock_info *cinfo); | 443 | struct dispc_clock_info *cinfo); |
462 | int dispc_get_clock_div(enum omap_channel channel, | 444 | int dispc_mgr_get_clock_div(enum omap_channel channel, |
463 | struct dispc_clock_info *cinfo); | 445 | struct dispc_clock_info *cinfo); |
464 | 446 | ||
465 | |||
466 | /* VENC */ | 447 | /* VENC */ |
467 | #ifdef CONFIG_OMAP2_DSS_VENC | 448 | #ifdef CONFIG_OMAP2_DSS_VENC |
468 | int venc_init_platform_driver(void); | 449 | int venc_init_platform_driver(void); |
469 | void venc_uninit_platform_driver(void); | 450 | void venc_uninit_platform_driver(void); |
470 | void venc_dump_regs(struct seq_file *s); | 451 | void venc_dump_regs(struct seq_file *s); |
471 | int venc_init_display(struct omap_dss_device *display); | 452 | int venc_init_display(struct omap_dss_device *display); |
453 | unsigned long venc_get_pixel_clock(void); | ||
472 | #else | 454 | #else |
473 | static inline int venc_init_platform_driver(void) | 455 | static inline int venc_init_platform_driver(void) |
474 | { | 456 | { |
@@ -477,6 +459,11 @@ static inline int venc_init_platform_driver(void) | |||
477 | static inline void venc_uninit_platform_driver(void) | 459 | static inline void venc_uninit_platform_driver(void) |
478 | { | 460 | { |
479 | } | 461 | } |
462 | static inline unsigned long venc_get_pixel_clock(void) | ||
463 | { | ||
464 | WARN("%s: VENC not compiled in, returning pclk as 0\n", __func__); | ||
465 | return 0; | ||
466 | } | ||
480 | #endif | 467 | #endif |
481 | 468 | ||
482 | /* HDMI */ | 469 | /* HDMI */ |
@@ -484,6 +471,8 @@ static inline void venc_uninit_platform_driver(void) | |||
484 | int hdmi_init_platform_driver(void); | 471 | int hdmi_init_platform_driver(void); |
485 | void hdmi_uninit_platform_driver(void); | 472 | void hdmi_uninit_platform_driver(void); |
486 | int hdmi_init_display(struct omap_dss_device *dssdev); | 473 | int hdmi_init_display(struct omap_dss_device *dssdev); |
474 | unsigned long hdmi_get_pixel_clock(void); | ||
475 | void hdmi_dump_regs(struct seq_file *s); | ||
487 | #else | 476 | #else |
488 | static inline int hdmi_init_display(struct omap_dss_device *dssdev) | 477 | static inline int hdmi_init_display(struct omap_dss_device *dssdev) |
489 | { | 478 | { |
@@ -496,12 +485,19 @@ static inline int hdmi_init_platform_driver(void) | |||
496 | static inline void hdmi_uninit_platform_driver(void) | 485 | static inline void hdmi_uninit_platform_driver(void) |
497 | { | 486 | { |
498 | } | 487 | } |
488 | static inline unsigned long hdmi_get_pixel_clock(void) | ||
489 | { | ||
490 | WARN("%s: HDMI not compiled in, returning pclk as 0\n", __func__); | ||
491 | return 0; | ||
492 | } | ||
499 | #endif | 493 | #endif |
500 | int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev); | 494 | int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev); |
501 | void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev); | 495 | void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev); |
502 | void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev); | 496 | void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev); |
503 | int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev, | 497 | int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev, |
504 | struct omap_video_timings *timings); | 498 | struct omap_video_timings *timings); |
499 | int omapdss_hdmi_read_edid(u8 *buf, int len); | ||
500 | bool omapdss_hdmi_detect(void); | ||
505 | int hdmi_panel_init(void); | 501 | int hdmi_panel_init(void); |
506 | void hdmi_panel_exit(void); | 502 | void hdmi_panel_exit(void); |
507 | 503 | ||
diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c index b415c4ee621d..b402699168a5 100644 --- a/drivers/video/omap2/dss/dss_features.c +++ b/drivers/video/omap2/dss/dss_features.c | |||
@@ -47,6 +47,7 @@ struct omap_dss_features { | |||
47 | const int num_ovls; | 47 | const int num_ovls; |
48 | const enum omap_display_type *supported_displays; | 48 | const enum omap_display_type *supported_displays; |
49 | const enum omap_color_mode *supported_color_modes; | 49 | const enum omap_color_mode *supported_color_modes; |
50 | const enum omap_overlay_caps *overlay_caps; | ||
50 | const char * const *clksrc_names; | 51 | const char * const *clksrc_names; |
51 | const struct dss_param_range *dss_params; | 52 | const struct dss_param_range *dss_params; |
52 | 53 | ||
@@ -209,6 +210,68 @@ static const enum omap_color_mode omap4_dss_supported_color_modes[] = { | |||
209 | OMAP_DSS_COLOR_ARGB16 | OMAP_DSS_COLOR_XRGB16_1555 | | 210 | OMAP_DSS_COLOR_ARGB16 | OMAP_DSS_COLOR_XRGB16_1555 | |
210 | OMAP_DSS_COLOR_ARGB32 | OMAP_DSS_COLOR_RGBX16 | | 211 | OMAP_DSS_COLOR_ARGB32 | OMAP_DSS_COLOR_RGBX16 | |
211 | OMAP_DSS_COLOR_RGBX32, | 212 | OMAP_DSS_COLOR_RGBX32, |
213 | |||
214 | /* OMAP_DSS_VIDEO3 */ | ||
215 | OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB12U | | ||
216 | OMAP_DSS_COLOR_YUV2 | OMAP_DSS_COLOR_ARGB16_1555 | | ||
217 | OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_NV12 | | ||
218 | OMAP_DSS_COLOR_RGBA16 | OMAP_DSS_COLOR_RGB24U | | ||
219 | OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_UYVY | | ||
220 | OMAP_DSS_COLOR_ARGB16 | OMAP_DSS_COLOR_XRGB16_1555 | | ||
221 | OMAP_DSS_COLOR_ARGB32 | OMAP_DSS_COLOR_RGBX16 | | ||
222 | OMAP_DSS_COLOR_RGBX32, | ||
223 | }; | ||
224 | |||
225 | static const enum omap_overlay_caps omap2_dss_overlay_caps[] = { | ||
226 | /* OMAP_DSS_GFX */ | ||
227 | 0, | ||
228 | |||
229 | /* OMAP_DSS_VIDEO1 */ | ||
230 | OMAP_DSS_OVL_CAP_SCALE, | ||
231 | |||
232 | /* OMAP_DSS_VIDEO2 */ | ||
233 | OMAP_DSS_OVL_CAP_SCALE, | ||
234 | }; | ||
235 | |||
236 | static const enum omap_overlay_caps omap3430_dss_overlay_caps[] = { | ||
237 | /* OMAP_DSS_GFX */ | ||
238 | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA, | ||
239 | |||
240 | /* OMAP_DSS_VIDEO1 */ | ||
241 | OMAP_DSS_OVL_CAP_SCALE, | ||
242 | |||
243 | /* OMAP_DSS_VIDEO2 */ | ||
244 | OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA, | ||
245 | }; | ||
246 | |||
247 | static const enum omap_overlay_caps omap3630_dss_overlay_caps[] = { | ||
248 | /* OMAP_DSS_GFX */ | ||
249 | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA, | ||
250 | |||
251 | /* OMAP_DSS_VIDEO1 */ | ||
252 | OMAP_DSS_OVL_CAP_SCALE, | ||
253 | |||
254 | /* OMAP_DSS_VIDEO2 */ | ||
255 | OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | | ||
256 | OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA, | ||
257 | }; | ||
258 | |||
259 | static const enum omap_overlay_caps omap4_dss_overlay_caps[] = { | ||
260 | /* OMAP_DSS_GFX */ | ||
261 | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | | ||
262 | OMAP_DSS_OVL_CAP_ZORDER, | ||
263 | |||
264 | /* OMAP_DSS_VIDEO1 */ | ||
265 | OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | | ||
266 | OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_ZORDER, | ||
267 | |||
268 | /* OMAP_DSS_VIDEO2 */ | ||
269 | OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | | ||
270 | OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_ZORDER, | ||
271 | |||
272 | /* OMAP_DSS_VIDEO3 */ | ||
273 | OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | | ||
274 | OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_ZORDER, | ||
212 | }; | 275 | }; |
213 | 276 | ||
214 | static const char * const omap2_dss_clk_source_names[] = { | 277 | static const char * const omap2_dss_clk_source_names[] = { |
@@ -233,32 +296,38 @@ static const char * const omap4_dss_clk_source_names[] = { | |||
233 | 296 | ||
234 | static const struct dss_param_range omap2_dss_param_range[] = { | 297 | static const struct dss_param_range omap2_dss_param_range[] = { |
235 | [FEAT_PARAM_DSS_FCK] = { 0, 173000000 }, | 298 | [FEAT_PARAM_DSS_FCK] = { 0, 173000000 }, |
299 | [FEAT_PARAM_DSS_PCD] = { 2, 255 }, | ||
236 | [FEAT_PARAM_DSIPLL_REGN] = { 0, 0 }, | 300 | [FEAT_PARAM_DSIPLL_REGN] = { 0, 0 }, |
237 | [FEAT_PARAM_DSIPLL_REGM] = { 0, 0 }, | 301 | [FEAT_PARAM_DSIPLL_REGM] = { 0, 0 }, |
238 | [FEAT_PARAM_DSIPLL_REGM_DISPC] = { 0, 0 }, | 302 | [FEAT_PARAM_DSIPLL_REGM_DISPC] = { 0, 0 }, |
239 | [FEAT_PARAM_DSIPLL_REGM_DSI] = { 0, 0 }, | 303 | [FEAT_PARAM_DSIPLL_REGM_DSI] = { 0, 0 }, |
240 | [FEAT_PARAM_DSIPLL_FINT] = { 0, 0 }, | 304 | [FEAT_PARAM_DSIPLL_FINT] = { 0, 0 }, |
241 | [FEAT_PARAM_DSIPLL_LPDIV] = { 0, 0 }, | 305 | [FEAT_PARAM_DSIPLL_LPDIV] = { 0, 0 }, |
306 | [FEAT_PARAM_DOWNSCALE] = { 1, 2 }, | ||
242 | }; | 307 | }; |
243 | 308 | ||
244 | static const struct dss_param_range omap3_dss_param_range[] = { | 309 | static const struct dss_param_range omap3_dss_param_range[] = { |
245 | [FEAT_PARAM_DSS_FCK] = { 0, 173000000 }, | 310 | [FEAT_PARAM_DSS_FCK] = { 0, 173000000 }, |
311 | [FEAT_PARAM_DSS_PCD] = { 1, 255 }, | ||
246 | [FEAT_PARAM_DSIPLL_REGN] = { 0, (1 << 7) - 1 }, | 312 | [FEAT_PARAM_DSIPLL_REGN] = { 0, (1 << 7) - 1 }, |
247 | [FEAT_PARAM_DSIPLL_REGM] = { 0, (1 << 11) - 1 }, | 313 | [FEAT_PARAM_DSIPLL_REGM] = { 0, (1 << 11) - 1 }, |
248 | [FEAT_PARAM_DSIPLL_REGM_DISPC] = { 0, (1 << 4) - 1 }, | 314 | [FEAT_PARAM_DSIPLL_REGM_DISPC] = { 0, (1 << 4) - 1 }, |
249 | [FEAT_PARAM_DSIPLL_REGM_DSI] = { 0, (1 << 4) - 1 }, | 315 | [FEAT_PARAM_DSIPLL_REGM_DSI] = { 0, (1 << 4) - 1 }, |
250 | [FEAT_PARAM_DSIPLL_FINT] = { 750000, 2100000 }, | 316 | [FEAT_PARAM_DSIPLL_FINT] = { 750000, 2100000 }, |
251 | [FEAT_PARAM_DSIPLL_LPDIV] = { 1, (1 << 13) - 1}, | 317 | [FEAT_PARAM_DSIPLL_LPDIV] = { 1, (1 << 13) - 1}, |
318 | [FEAT_PARAM_DOWNSCALE] = { 1, 4 }, | ||
252 | }; | 319 | }; |
253 | 320 | ||
254 | static const struct dss_param_range omap4_dss_param_range[] = { | 321 | static const struct dss_param_range omap4_dss_param_range[] = { |
255 | [FEAT_PARAM_DSS_FCK] = { 0, 186000000 }, | 322 | [FEAT_PARAM_DSS_FCK] = { 0, 186000000 }, |
323 | [FEAT_PARAM_DSS_PCD] = { 1, 255 }, | ||
256 | [FEAT_PARAM_DSIPLL_REGN] = { 0, (1 << 8) - 1 }, | 324 | [FEAT_PARAM_DSIPLL_REGN] = { 0, (1 << 8) - 1 }, |
257 | [FEAT_PARAM_DSIPLL_REGM] = { 0, (1 << 12) - 1 }, | 325 | [FEAT_PARAM_DSIPLL_REGM] = { 0, (1 << 12) - 1 }, |
258 | [FEAT_PARAM_DSIPLL_REGM_DISPC] = { 0, (1 << 5) - 1 }, | 326 | [FEAT_PARAM_DSIPLL_REGM_DISPC] = { 0, (1 << 5) - 1 }, |
259 | [FEAT_PARAM_DSIPLL_REGM_DSI] = { 0, (1 << 5) - 1 }, | 327 | [FEAT_PARAM_DSIPLL_REGM_DSI] = { 0, (1 << 5) - 1 }, |
260 | [FEAT_PARAM_DSIPLL_FINT] = { 500000, 2500000 }, | 328 | [FEAT_PARAM_DSIPLL_FINT] = { 500000, 2500000 }, |
261 | [FEAT_PARAM_DSIPLL_LPDIV] = { 0, (1 << 13) - 1 }, | 329 | [FEAT_PARAM_DSIPLL_LPDIV] = { 0, (1 << 13) - 1 }, |
330 | [FEAT_PARAM_DOWNSCALE] = { 1, 4 }, | ||
262 | }; | 331 | }; |
263 | 332 | ||
264 | /* OMAP2 DSS Features */ | 333 | /* OMAP2 DSS Features */ |
@@ -275,6 +344,7 @@ static const struct omap_dss_features omap2_dss_features = { | |||
275 | .num_ovls = 3, | 344 | .num_ovls = 3, |
276 | .supported_displays = omap2_dss_supported_displays, | 345 | .supported_displays = omap2_dss_supported_displays, |
277 | .supported_color_modes = omap2_dss_supported_color_modes, | 346 | .supported_color_modes = omap2_dss_supported_color_modes, |
347 | .overlay_caps = omap2_dss_overlay_caps, | ||
278 | .clksrc_names = omap2_dss_clk_source_names, | 348 | .clksrc_names = omap2_dss_clk_source_names, |
279 | .dss_params = omap2_dss_param_range, | 349 | .dss_params = omap2_dss_param_range, |
280 | .buffer_size_unit = 1, | 350 | .buffer_size_unit = 1, |
@@ -287,18 +357,19 @@ static const struct omap_dss_features omap3430_dss_features = { | |||
287 | .num_reg_fields = ARRAY_SIZE(omap3_dss_reg_fields), | 357 | .num_reg_fields = ARRAY_SIZE(omap3_dss_reg_fields), |
288 | 358 | ||
289 | .has_feature = | 359 | .has_feature = |
290 | FEAT_GLOBAL_ALPHA | FEAT_LCDENABLEPOL | | 360 | FEAT_LCDENABLEPOL | |
291 | FEAT_LCDENABLESIGNAL | FEAT_PCKFREEENABLE | | 361 | FEAT_LCDENABLESIGNAL | FEAT_PCKFREEENABLE | |
292 | FEAT_FUNCGATED | FEAT_ROWREPEATENABLE | | 362 | FEAT_FUNCGATED | FEAT_ROWREPEATENABLE | |
293 | FEAT_LINEBUFFERSPLIT | FEAT_RESIZECONF | | 363 | FEAT_LINEBUFFERSPLIT | FEAT_RESIZECONF | |
294 | FEAT_DSI_PLL_FREQSEL | FEAT_DSI_REVERSE_TXCLKESC | | 364 | FEAT_DSI_PLL_FREQSEL | FEAT_DSI_REVERSE_TXCLKESC | |
295 | FEAT_VENC_REQUIRES_TV_DAC_CLK | FEAT_CPR | FEAT_PRELOAD | | 365 | FEAT_VENC_REQUIRES_TV_DAC_CLK | FEAT_CPR | FEAT_PRELOAD | |
296 | FEAT_FIR_COEF_V, | 366 | FEAT_FIR_COEF_V | FEAT_ALPHA_FIXED_ZORDER, |
297 | 367 | ||
298 | .num_mgrs = 2, | 368 | .num_mgrs = 2, |
299 | .num_ovls = 3, | 369 | .num_ovls = 3, |
300 | .supported_displays = omap3430_dss_supported_displays, | 370 | .supported_displays = omap3430_dss_supported_displays, |
301 | .supported_color_modes = omap3_dss_supported_color_modes, | 371 | .supported_color_modes = omap3_dss_supported_color_modes, |
372 | .overlay_caps = omap3430_dss_overlay_caps, | ||
302 | .clksrc_names = omap3_dss_clk_source_names, | 373 | .clksrc_names = omap3_dss_clk_source_names, |
303 | .dss_params = omap3_dss_param_range, | 374 | .dss_params = omap3_dss_param_range, |
304 | .buffer_size_unit = 1, | 375 | .buffer_size_unit = 1, |
@@ -310,18 +381,19 @@ static const struct omap_dss_features omap3630_dss_features = { | |||
310 | .num_reg_fields = ARRAY_SIZE(omap3_dss_reg_fields), | 381 | .num_reg_fields = ARRAY_SIZE(omap3_dss_reg_fields), |
311 | 382 | ||
312 | .has_feature = | 383 | .has_feature = |
313 | FEAT_GLOBAL_ALPHA | FEAT_LCDENABLEPOL | | 384 | FEAT_LCDENABLEPOL | |
314 | FEAT_LCDENABLESIGNAL | FEAT_PCKFREEENABLE | | 385 | FEAT_LCDENABLESIGNAL | FEAT_PCKFREEENABLE | |
315 | FEAT_PRE_MULT_ALPHA | FEAT_FUNCGATED | | 386 | FEAT_FUNCGATED | |
316 | FEAT_ROWREPEATENABLE | FEAT_LINEBUFFERSPLIT | | 387 | FEAT_ROWREPEATENABLE | FEAT_LINEBUFFERSPLIT | |
317 | FEAT_RESIZECONF | FEAT_DSI_PLL_PWR_BUG | | 388 | FEAT_RESIZECONF | FEAT_DSI_PLL_PWR_BUG | |
318 | FEAT_DSI_PLL_FREQSEL | FEAT_CPR | FEAT_PRELOAD | | 389 | FEAT_DSI_PLL_FREQSEL | FEAT_CPR | FEAT_PRELOAD | |
319 | FEAT_FIR_COEF_V, | 390 | FEAT_FIR_COEF_V | FEAT_ALPHA_FIXED_ZORDER, |
320 | 391 | ||
321 | .num_mgrs = 2, | 392 | .num_mgrs = 2, |
322 | .num_ovls = 3, | 393 | .num_ovls = 3, |
323 | .supported_displays = omap3630_dss_supported_displays, | 394 | .supported_displays = omap3630_dss_supported_displays, |
324 | .supported_color_modes = omap3_dss_supported_color_modes, | 395 | .supported_color_modes = omap3_dss_supported_color_modes, |
396 | .overlay_caps = omap3630_dss_overlay_caps, | ||
325 | .clksrc_names = omap3_dss_clk_source_names, | 397 | .clksrc_names = omap3_dss_clk_source_names, |
326 | .dss_params = omap3_dss_param_range, | 398 | .dss_params = omap3_dss_param_range, |
327 | .buffer_size_unit = 1, | 399 | .buffer_size_unit = 1, |
@@ -335,17 +407,18 @@ static const struct omap_dss_features omap4430_es1_0_dss_features = { | |||
335 | .num_reg_fields = ARRAY_SIZE(omap4_dss_reg_fields), | 407 | .num_reg_fields = ARRAY_SIZE(omap4_dss_reg_fields), |
336 | 408 | ||
337 | .has_feature = | 409 | .has_feature = |
338 | FEAT_GLOBAL_ALPHA | FEAT_PRE_MULT_ALPHA | | 410 | FEAT_MGR_LCD2 | |
339 | FEAT_MGR_LCD2 | FEAT_GLOBAL_ALPHA_VID1 | | ||
340 | FEAT_CORE_CLK_DIV | FEAT_LCD_CLK_SRC | | 411 | FEAT_CORE_CLK_DIV | FEAT_LCD_CLK_SRC | |
341 | FEAT_DSI_DCS_CMD_CONFIG_VC | FEAT_DSI_VC_OCP_WIDTH | | 412 | FEAT_DSI_DCS_CMD_CONFIG_VC | FEAT_DSI_VC_OCP_WIDTH | |
342 | FEAT_DSI_GNQ | FEAT_HANDLE_UV_SEPARATE | FEAT_ATTR2 | | 413 | FEAT_DSI_GNQ | FEAT_HANDLE_UV_SEPARATE | FEAT_ATTR2 | |
343 | FEAT_CPR | FEAT_PRELOAD | FEAT_FIR_COEF_V, | 414 | FEAT_CPR | FEAT_PRELOAD | FEAT_FIR_COEF_V | |
415 | FEAT_ALPHA_FREE_ZORDER, | ||
344 | 416 | ||
345 | .num_mgrs = 3, | 417 | .num_mgrs = 3, |
346 | .num_ovls = 3, | 418 | .num_ovls = 4, |
347 | .supported_displays = omap4_dss_supported_displays, | 419 | .supported_displays = omap4_dss_supported_displays, |
348 | .supported_color_modes = omap4_dss_supported_color_modes, | 420 | .supported_color_modes = omap4_dss_supported_color_modes, |
421 | .overlay_caps = omap4_dss_overlay_caps, | ||
349 | .clksrc_names = omap4_dss_clk_source_names, | 422 | .clksrc_names = omap4_dss_clk_source_names, |
350 | .dss_params = omap4_dss_param_range, | 423 | .dss_params = omap4_dss_param_range, |
351 | .buffer_size_unit = 16, | 424 | .buffer_size_unit = 16, |
@@ -358,24 +431,50 @@ static const struct omap_dss_features omap4_dss_features = { | |||
358 | .num_reg_fields = ARRAY_SIZE(omap4_dss_reg_fields), | 431 | .num_reg_fields = ARRAY_SIZE(omap4_dss_reg_fields), |
359 | 432 | ||
360 | .has_feature = | 433 | .has_feature = |
361 | FEAT_GLOBAL_ALPHA | FEAT_PRE_MULT_ALPHA | | 434 | FEAT_MGR_LCD2 | |
362 | FEAT_MGR_LCD2 | FEAT_GLOBAL_ALPHA_VID1 | | ||
363 | FEAT_CORE_CLK_DIV | FEAT_LCD_CLK_SRC | | 435 | FEAT_CORE_CLK_DIV | FEAT_LCD_CLK_SRC | |
364 | FEAT_DSI_DCS_CMD_CONFIG_VC | FEAT_DSI_VC_OCP_WIDTH | | 436 | FEAT_DSI_DCS_CMD_CONFIG_VC | FEAT_DSI_VC_OCP_WIDTH | |
365 | FEAT_DSI_GNQ | FEAT_HDMI_CTS_SWMODE | | 437 | FEAT_DSI_GNQ | FEAT_HDMI_CTS_SWMODE | |
366 | FEAT_HANDLE_UV_SEPARATE | FEAT_ATTR2 | FEAT_CPR | | 438 | FEAT_HANDLE_UV_SEPARATE | FEAT_ATTR2 | FEAT_CPR | |
367 | FEAT_PRELOAD | FEAT_FIR_COEF_V, | 439 | FEAT_PRELOAD | FEAT_FIR_COEF_V | FEAT_ALPHA_FREE_ZORDER, |
368 | 440 | ||
369 | .num_mgrs = 3, | 441 | .num_mgrs = 3, |
370 | .num_ovls = 3, | 442 | .num_ovls = 4, |
371 | .supported_displays = omap4_dss_supported_displays, | 443 | .supported_displays = omap4_dss_supported_displays, |
372 | .supported_color_modes = omap4_dss_supported_color_modes, | 444 | .supported_color_modes = omap4_dss_supported_color_modes, |
445 | .overlay_caps = omap4_dss_overlay_caps, | ||
373 | .clksrc_names = omap4_dss_clk_source_names, | 446 | .clksrc_names = omap4_dss_clk_source_names, |
374 | .dss_params = omap4_dss_param_range, | 447 | .dss_params = omap4_dss_param_range, |
375 | .buffer_size_unit = 16, | 448 | .buffer_size_unit = 16, |
376 | .burst_size_unit = 16, | 449 | .burst_size_unit = 16, |
377 | }; | 450 | }; |
378 | 451 | ||
452 | #if defined(CONFIG_OMAP4_DSS_HDMI) | ||
453 | /* HDMI OMAP4 Functions*/ | ||
454 | static const struct ti_hdmi_ip_ops omap4_hdmi_functions = { | ||
455 | |||
456 | .video_configure = ti_hdmi_4xxx_basic_configure, | ||
457 | .phy_enable = ti_hdmi_4xxx_phy_enable, | ||
458 | .phy_disable = ti_hdmi_4xxx_phy_disable, | ||
459 | .read_edid = ti_hdmi_4xxx_read_edid, | ||
460 | .detect = ti_hdmi_4xxx_detect, | ||
461 | .pll_enable = ti_hdmi_4xxx_pll_enable, | ||
462 | .pll_disable = ti_hdmi_4xxx_pll_disable, | ||
463 | .video_enable = ti_hdmi_4xxx_wp_video_start, | ||
464 | .dump_wrapper = ti_hdmi_4xxx_wp_dump, | ||
465 | .dump_core = ti_hdmi_4xxx_core_dump, | ||
466 | .dump_pll = ti_hdmi_4xxx_pll_dump, | ||
467 | .dump_phy = ti_hdmi_4xxx_phy_dump, | ||
468 | |||
469 | }; | ||
470 | |||
471 | void dss_init_hdmi_ip_ops(struct hdmi_ip_data *ip_data) | ||
472 | { | ||
473 | if (cpu_is_omap44xx()) | ||
474 | ip_data->ops = &omap4_hdmi_functions; | ||
475 | } | ||
476 | #endif | ||
477 | |||
379 | /* Functions returning values related to a DSS feature */ | 478 | /* Functions returning values related to a DSS feature */ |
380 | int dss_feat_get_num_mgrs(void) | 479 | int dss_feat_get_num_mgrs(void) |
381 | { | 480 | { |
@@ -407,6 +506,11 @@ enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane) | |||
407 | return omap_current_dss_features->supported_color_modes[plane]; | 506 | return omap_current_dss_features->supported_color_modes[plane]; |
408 | } | 507 | } |
409 | 508 | ||
509 | enum omap_overlay_caps dss_feat_get_overlay_caps(enum omap_plane plane) | ||
510 | { | ||
511 | return omap_current_dss_features->overlay_caps[plane]; | ||
512 | } | ||
513 | |||
410 | bool dss_feat_color_mode_supported(enum omap_plane plane, | 514 | bool dss_feat_color_mode_supported(enum omap_plane plane, |
411 | enum omap_color_mode color_mode) | 515 | enum omap_color_mode color_mode) |
412 | { | 516 | { |
diff --git a/drivers/video/omap2/dss/dss_features.h b/drivers/video/omap2/dss/dss_features.h index b7398cbcda5f..6a6c05dd45ce 100644 --- a/drivers/video/omap2/dss/dss_features.h +++ b/drivers/video/omap2/dss/dss_features.h | |||
@@ -20,16 +20,17 @@ | |||
20 | #ifndef __OMAP2_DSS_FEATURES_H | 20 | #ifndef __OMAP2_DSS_FEATURES_H |
21 | #define __OMAP2_DSS_FEATURES_H | 21 | #define __OMAP2_DSS_FEATURES_H |
22 | 22 | ||
23 | #if defined(CONFIG_OMAP4_DSS_HDMI) | ||
24 | #include "ti_hdmi.h" | ||
25 | #endif | ||
26 | |||
23 | #define MAX_DSS_MANAGERS 3 | 27 | #define MAX_DSS_MANAGERS 3 |
24 | #define MAX_DSS_OVERLAYS 3 | 28 | #define MAX_DSS_OVERLAYS 4 |
25 | #define MAX_DSS_LCD_MANAGERS 2 | 29 | #define MAX_DSS_LCD_MANAGERS 2 |
26 | #define MAX_NUM_DSI 2 | 30 | #define MAX_NUM_DSI 2 |
27 | 31 | ||
28 | /* DSS has feature id */ | 32 | /* DSS has feature id */ |
29 | enum dss_feat_id { | 33 | enum dss_feat_id { |
30 | FEAT_GLOBAL_ALPHA = 1 << 0, | ||
31 | FEAT_GLOBAL_ALPHA_VID1 = 1 << 1, | ||
32 | FEAT_PRE_MULT_ALPHA = 1 << 2, | ||
33 | FEAT_LCDENABLEPOL = 1 << 3, | 34 | FEAT_LCDENABLEPOL = 1 << 3, |
34 | FEAT_LCDENABLESIGNAL = 1 << 4, | 35 | FEAT_LCDENABLESIGNAL = 1 << 4, |
35 | FEAT_PCKFREEENABLE = 1 << 5, | 36 | FEAT_PCKFREEENABLE = 1 << 5, |
@@ -55,6 +56,8 @@ enum dss_feat_id { | |||
55 | FEAT_CPR = 1 << 23, | 56 | FEAT_CPR = 1 << 23, |
56 | FEAT_PRELOAD = 1 << 24, | 57 | FEAT_PRELOAD = 1 << 24, |
57 | FEAT_FIR_COEF_V = 1 << 25, | 58 | FEAT_FIR_COEF_V = 1 << 25, |
59 | FEAT_ALPHA_FIXED_ZORDER = 1 << 26, | ||
60 | FEAT_ALPHA_FREE_ZORDER = 1 << 27, | ||
58 | }; | 61 | }; |
59 | 62 | ||
60 | /* DSS register field id */ | 63 | /* DSS register field id */ |
@@ -75,12 +78,14 @@ enum dss_feat_reg_field { | |||
75 | 78 | ||
76 | enum dss_range_param { | 79 | enum dss_range_param { |
77 | FEAT_PARAM_DSS_FCK, | 80 | FEAT_PARAM_DSS_FCK, |
81 | FEAT_PARAM_DSS_PCD, | ||
78 | FEAT_PARAM_DSIPLL_REGN, | 82 | FEAT_PARAM_DSIPLL_REGN, |
79 | FEAT_PARAM_DSIPLL_REGM, | 83 | FEAT_PARAM_DSIPLL_REGM, |
80 | FEAT_PARAM_DSIPLL_REGM_DISPC, | 84 | FEAT_PARAM_DSIPLL_REGM_DISPC, |
81 | FEAT_PARAM_DSIPLL_REGM_DSI, | 85 | FEAT_PARAM_DSIPLL_REGM_DSI, |
82 | FEAT_PARAM_DSIPLL_FINT, | 86 | FEAT_PARAM_DSIPLL_FINT, |
83 | FEAT_PARAM_DSIPLL_LPDIV, | 87 | FEAT_PARAM_DSIPLL_LPDIV, |
88 | FEAT_PARAM_DOWNSCALE, | ||
84 | }; | 89 | }; |
85 | 90 | ||
86 | /* DSS Feature Functions */ | 91 | /* DSS Feature Functions */ |
@@ -90,6 +95,7 @@ unsigned long dss_feat_get_param_min(enum dss_range_param param); | |||
90 | unsigned long dss_feat_get_param_max(enum dss_range_param param); | 95 | unsigned long dss_feat_get_param_max(enum dss_range_param param); |
91 | enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel); | 96 | enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel); |
92 | enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane); | 97 | enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane); |
98 | enum omap_overlay_caps dss_feat_get_overlay_caps(enum omap_plane plane); | ||
93 | bool dss_feat_color_mode_supported(enum omap_plane plane, | 99 | bool dss_feat_color_mode_supported(enum omap_plane plane, |
94 | enum omap_color_mode color_mode); | 100 | enum omap_color_mode color_mode); |
95 | const char *dss_feat_get_clk_source_name(enum omap_dss_clk_source id); | 101 | const char *dss_feat_get_clk_source_name(enum omap_dss_clk_source id); |
@@ -100,4 +106,7 @@ u32 dss_feat_get_burst_size_unit(void); /* in bytes */ | |||
100 | bool dss_has_feature(enum dss_feat_id id); | 106 | bool dss_has_feature(enum dss_feat_id id); |
101 | void dss_feat_get_reg_field(enum dss_feat_reg_field id, u8 *start, u8 *end); | 107 | void dss_feat_get_reg_field(enum dss_feat_reg_field id, u8 *start, u8 *end); |
102 | void dss_features_init(void); | 108 | void dss_features_init(void); |
109 | #if defined(CONFIG_OMAP4_DSS_HDMI) | ||
110 | void dss_init_hdmi_ip_ops(struct hdmi_ip_data *ip_data); | ||
111 | #endif | ||
103 | #endif | 112 | #endif |
diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c index 256f27a9064a..3262f0f1fa35 100644 --- a/drivers/video/omap2/dss/hdmi.c +++ b/drivers/video/omap2/dss/hdmi.c | |||
@@ -37,26 +37,41 @@ | |||
37 | defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE) | 37 | defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE) |
38 | #include <sound/soc.h> | 38 | #include <sound/soc.h> |
39 | #include <sound/pcm_params.h> | 39 | #include <sound/pcm_params.h> |
40 | #include "ti_hdmi_4xxx_ip.h" | ||
40 | #endif | 41 | #endif |
41 | 42 | ||
43 | #include "ti_hdmi.h" | ||
42 | #include "dss.h" | 44 | #include "dss.h" |
43 | #include "hdmi.h" | ||
44 | #include "dss_features.h" | 45 | #include "dss_features.h" |
45 | 46 | ||
47 | #define HDMI_WP 0x0 | ||
48 | #define HDMI_CORE_SYS 0x400 | ||
49 | #define HDMI_CORE_AV 0x900 | ||
50 | #define HDMI_PLLCTRL 0x200 | ||
51 | #define HDMI_PHY 0x300 | ||
52 | |||
53 | /* HDMI EDID Length move this */ | ||
54 | #define HDMI_EDID_MAX_LENGTH 256 | ||
55 | #define EDID_TIMING_DESCRIPTOR_SIZE 0x12 | ||
56 | #define EDID_DESCRIPTOR_BLOCK0_ADDRESS 0x36 | ||
57 | #define EDID_DESCRIPTOR_BLOCK1_ADDRESS 0x80 | ||
58 | #define EDID_SIZE_BLOCK0_TIMING_DESCRIPTOR 4 | ||
59 | #define EDID_SIZE_BLOCK1_TIMING_DESCRIPTOR 4 | ||
60 | |||
61 | #define OMAP_HDMI_TIMINGS_NB 34 | ||
62 | |||
63 | #define HDMI_DEFAULT_REGN 16 | ||
64 | #define HDMI_DEFAULT_REGM2 1 | ||
65 | |||
46 | static struct { | 66 | static struct { |
47 | struct mutex lock; | 67 | struct mutex lock; |
48 | struct omap_display_platform_data *pdata; | 68 | struct omap_display_platform_data *pdata; |
49 | struct platform_device *pdev; | 69 | struct platform_device *pdev; |
50 | void __iomem *base_wp; /* HDMI wrapper */ | 70 | struct hdmi_ip_data ip_data; |
51 | int code; | 71 | int code; |
52 | int mode; | 72 | int mode; |
53 | u8 edid[HDMI_EDID_MAX_LENGTH]; | ||
54 | u8 edid_set; | ||
55 | bool custom_set; | ||
56 | struct hdmi_config cfg; | ||
57 | 73 | ||
58 | struct clk *sys_clk; | 74 | struct clk *sys_clk; |
59 | struct clk *hdmi_clk; | ||
60 | } hdmi; | 75 | } hdmi; |
61 | 76 | ||
62 | /* | 77 | /* |
@@ -144,30 +159,6 @@ static const int code_vesa[85] = { | |||
144 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | 159 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
145 | -1, 27, 28, -1, 33}; | 160 | -1, 27, 28, -1, 33}; |
146 | 161 | ||
147 | static const u8 edid_header[8] = {0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0}; | ||
148 | |||
149 | static inline void hdmi_write_reg(const struct hdmi_reg idx, u32 val) | ||
150 | { | ||
151 | __raw_writel(val, hdmi.base_wp + idx.idx); | ||
152 | } | ||
153 | |||
154 | static inline u32 hdmi_read_reg(const struct hdmi_reg idx) | ||
155 | { | ||
156 | return __raw_readl(hdmi.base_wp + idx.idx); | ||
157 | } | ||
158 | |||
159 | static inline int hdmi_wait_for_bit_change(const struct hdmi_reg idx, | ||
160 | int b2, int b1, u32 val) | ||
161 | { | ||
162 | u32 t = 0; | ||
163 | while (val != REG_GET(idx, b2, b1)) { | ||
164 | udelay(1); | ||
165 | if (t++ > 10000) | ||
166 | return !val; | ||
167 | } | ||
168 | return val; | ||
169 | } | ||
170 | |||
171 | static int hdmi_runtime_get(void) | 162 | static int hdmi_runtime_get(void) |
172 | { | 163 | { |
173 | int r; | 164 | int r; |
@@ -193,304 +184,7 @@ int hdmi_init_display(struct omap_dss_device *dssdev) | |||
193 | { | 184 | { |
194 | DSSDBG("init_display\n"); | 185 | DSSDBG("init_display\n"); |
195 | 186 | ||
196 | return 0; | 187 | dss_init_hdmi_ip_ops(&hdmi.ip_data); |
197 | } | ||
198 | |||
199 | static int hdmi_pll_init(enum hdmi_clk_refsel refsel, int dcofreq, | ||
200 | struct hdmi_pll_info *fmt, u16 sd) | ||
201 | { | ||
202 | u32 r; | ||
203 | |||
204 | /* PLL start always use manual mode */ | ||
205 | REG_FLD_MOD(PLLCTRL_PLL_CONTROL, 0x0, 0, 0); | ||
206 | |||
207 | r = hdmi_read_reg(PLLCTRL_CFG1); | ||
208 | r = FLD_MOD(r, fmt->regm, 20, 9); /* CFG1_PLL_REGM */ | ||
209 | r = FLD_MOD(r, fmt->regn, 8, 1); /* CFG1_PLL_REGN */ | ||
210 | |||
211 | hdmi_write_reg(PLLCTRL_CFG1, r); | ||
212 | |||
213 | r = hdmi_read_reg(PLLCTRL_CFG2); | ||
214 | |||
215 | r = FLD_MOD(r, 0x0, 12, 12); /* PLL_HIGHFREQ divide by 2 */ | ||
216 | r = FLD_MOD(r, 0x1, 13, 13); /* PLL_REFEN */ | ||
217 | r = FLD_MOD(r, 0x0, 14, 14); /* PHY_CLKINEN de-assert during locking */ | ||
218 | |||
219 | if (dcofreq) { | ||
220 | /* divider programming for frequency beyond 1000Mhz */ | ||
221 | REG_FLD_MOD(PLLCTRL_CFG3, sd, 17, 10); | ||
222 | r = FLD_MOD(r, 0x4, 3, 1); /* 1000MHz and 2000MHz */ | ||
223 | } else { | ||
224 | r = FLD_MOD(r, 0x2, 3, 1); /* 500MHz and 1000MHz */ | ||
225 | } | ||
226 | |||
227 | hdmi_write_reg(PLLCTRL_CFG2, r); | ||
228 | |||
229 | r = hdmi_read_reg(PLLCTRL_CFG4); | ||
230 | r = FLD_MOD(r, fmt->regm2, 24, 18); | ||
231 | r = FLD_MOD(r, fmt->regmf, 17, 0); | ||
232 | |||
233 | hdmi_write_reg(PLLCTRL_CFG4, r); | ||
234 | |||
235 | /* go now */ | ||
236 | REG_FLD_MOD(PLLCTRL_PLL_GO, 0x1, 0, 0); | ||
237 | |||
238 | /* wait for bit change */ | ||
239 | if (hdmi_wait_for_bit_change(PLLCTRL_PLL_GO, 0, 0, 1) != 1) { | ||
240 | DSSERR("PLL GO bit not set\n"); | ||
241 | return -ETIMEDOUT; | ||
242 | } | ||
243 | |||
244 | /* Wait till the lock bit is set in PLL status */ | ||
245 | if (hdmi_wait_for_bit_change(PLLCTRL_PLL_STATUS, 1, 1, 1) != 1) { | ||
246 | DSSWARN("cannot lock PLL\n"); | ||
247 | DSSWARN("CFG1 0x%x\n", | ||
248 | hdmi_read_reg(PLLCTRL_CFG1)); | ||
249 | DSSWARN("CFG2 0x%x\n", | ||
250 | hdmi_read_reg(PLLCTRL_CFG2)); | ||
251 | DSSWARN("CFG4 0x%x\n", | ||
252 | hdmi_read_reg(PLLCTRL_CFG4)); | ||
253 | return -ETIMEDOUT; | ||
254 | } | ||
255 | |||
256 | DSSDBG("PLL locked!\n"); | ||
257 | |||
258 | return 0; | ||
259 | } | ||
260 | |||
261 | /* PHY_PWR_CMD */ | ||
262 | static int hdmi_set_phy_pwr(enum hdmi_phy_pwr val) | ||
263 | { | ||
264 | /* Command for power control of HDMI PHY */ | ||
265 | REG_FLD_MOD(HDMI_WP_PWR_CTRL, val, 7, 6); | ||
266 | |||
267 | /* Status of the power control of HDMI PHY */ | ||
268 | if (hdmi_wait_for_bit_change(HDMI_WP_PWR_CTRL, 5, 4, val) != val) { | ||
269 | DSSERR("Failed to set PHY power mode to %d\n", val); | ||
270 | return -ETIMEDOUT; | ||
271 | } | ||
272 | |||
273 | return 0; | ||
274 | } | ||
275 | |||
276 | /* PLL_PWR_CMD */ | ||
277 | static int hdmi_set_pll_pwr(enum hdmi_pll_pwr val) | ||
278 | { | ||
279 | /* Command for power control of HDMI PLL */ | ||
280 | REG_FLD_MOD(HDMI_WP_PWR_CTRL, val, 3, 2); | ||
281 | |||
282 | /* wait till PHY_PWR_STATUS is set */ | ||
283 | if (hdmi_wait_for_bit_change(HDMI_WP_PWR_CTRL, 1, 0, val) != val) { | ||
284 | DSSERR("Failed to set PHY_PWR_STATUS\n"); | ||
285 | return -ETIMEDOUT; | ||
286 | } | ||
287 | |||
288 | return 0; | ||
289 | } | ||
290 | |||
291 | static int hdmi_pll_reset(void) | ||
292 | { | ||
293 | /* SYSRESET controlled by power FSM */ | ||
294 | REG_FLD_MOD(PLLCTRL_PLL_CONTROL, 0x0, 3, 3); | ||
295 | |||
296 | /* READ 0x0 reset is in progress */ | ||
297 | if (hdmi_wait_for_bit_change(PLLCTRL_PLL_STATUS, 0, 0, 1) != 1) { | ||
298 | DSSERR("Failed to sysreset PLL\n"); | ||
299 | return -ETIMEDOUT; | ||
300 | } | ||
301 | |||
302 | return 0; | ||
303 | } | ||
304 | |||
305 | static int hdmi_phy_init(void) | ||
306 | { | ||
307 | u16 r = 0; | ||
308 | |||
309 | r = hdmi_set_phy_pwr(HDMI_PHYPWRCMD_LDOON); | ||
310 | if (r) | ||
311 | return r; | ||
312 | |||
313 | r = hdmi_set_phy_pwr(HDMI_PHYPWRCMD_TXON); | ||
314 | if (r) | ||
315 | return r; | ||
316 | |||
317 | /* | ||
318 | * Read address 0 in order to get the SCP reset done completed | ||
319 | * Dummy access performed to make sure reset is done | ||
320 | */ | ||
321 | hdmi_read_reg(HDMI_TXPHY_TX_CTRL); | ||
322 | |||
323 | /* | ||
324 | * Write to phy address 0 to configure the clock | ||
325 | * use HFBITCLK write HDMI_TXPHY_TX_CONTROL_FREQOUT field | ||
326 | */ | ||
327 | REG_FLD_MOD(HDMI_TXPHY_TX_CTRL, 0x1, 31, 30); | ||
328 | |||
329 | /* Write to phy address 1 to start HDMI line (TXVALID and TMDSCLKEN) */ | ||
330 | hdmi_write_reg(HDMI_TXPHY_DIGITAL_CTRL, 0xF0000000); | ||
331 | |||
332 | /* Setup max LDO voltage */ | ||
333 | REG_FLD_MOD(HDMI_TXPHY_POWER_CTRL, 0xB, 3, 0); | ||
334 | |||
335 | /* Write to phy address 3 to change the polarity control */ | ||
336 | REG_FLD_MOD(HDMI_TXPHY_PAD_CFG_CTRL, 0x1, 27, 27); | ||
337 | |||
338 | return 0; | ||
339 | } | ||
340 | |||
341 | static int hdmi_pll_program(struct hdmi_pll_info *fmt) | ||
342 | { | ||
343 | u16 r = 0; | ||
344 | enum hdmi_clk_refsel refsel; | ||
345 | |||
346 | r = hdmi_set_pll_pwr(HDMI_PLLPWRCMD_ALLOFF); | ||
347 | if (r) | ||
348 | return r; | ||
349 | |||
350 | r = hdmi_set_pll_pwr(HDMI_PLLPWRCMD_BOTHON_ALLCLKS); | ||
351 | if (r) | ||
352 | return r; | ||
353 | |||
354 | r = hdmi_pll_reset(); | ||
355 | if (r) | ||
356 | return r; | ||
357 | |||
358 | refsel = HDMI_REFSEL_SYSCLK; | ||
359 | |||
360 | r = hdmi_pll_init(refsel, fmt->dcofreq, fmt, fmt->regsd); | ||
361 | if (r) | ||
362 | return r; | ||
363 | |||
364 | return 0; | ||
365 | } | ||
366 | |||
367 | static void hdmi_phy_off(void) | ||
368 | { | ||
369 | hdmi_set_phy_pwr(HDMI_PHYPWRCMD_OFF); | ||
370 | } | ||
371 | |||
372 | static int hdmi_core_ddc_edid(u8 *pedid, int ext) | ||
373 | { | ||
374 | u32 i, j; | ||
375 | char checksum = 0; | ||
376 | u32 offset = 0; | ||
377 | |||
378 | /* Turn on CLK for DDC */ | ||
379 | REG_FLD_MOD(HDMI_CORE_AV_DPD, 0x7, 2, 0); | ||
380 | |||
381 | /* | ||
382 | * SW HACK : Without the Delay DDC(i2c bus) reads 0 values / | ||
383 | * right shifted values( The behavior is not consistent and seen only | ||
384 | * with some TV's) | ||
385 | */ | ||
386 | usleep_range(800, 1000); | ||
387 | |||
388 | if (!ext) { | ||
389 | /* Clk SCL Devices */ | ||
390 | REG_FLD_MOD(HDMI_CORE_DDC_CMD, 0xA, 3, 0); | ||
391 | |||
392 | /* HDMI_CORE_DDC_STATUS_IN_PROG */ | ||
393 | if (hdmi_wait_for_bit_change(HDMI_CORE_DDC_STATUS, | ||
394 | 4, 4, 0) != 0) { | ||
395 | DSSERR("Failed to program DDC\n"); | ||
396 | return -ETIMEDOUT; | ||
397 | } | ||
398 | |||
399 | /* Clear FIFO */ | ||
400 | REG_FLD_MOD(HDMI_CORE_DDC_CMD, 0x9, 3, 0); | ||
401 | |||
402 | /* HDMI_CORE_DDC_STATUS_IN_PROG */ | ||
403 | if (hdmi_wait_for_bit_change(HDMI_CORE_DDC_STATUS, | ||
404 | 4, 4, 0) != 0) { | ||
405 | DSSERR("Failed to program DDC\n"); | ||
406 | return -ETIMEDOUT; | ||
407 | } | ||
408 | |||
409 | } else { | ||
410 | if (ext % 2 != 0) | ||
411 | offset = 0x80; | ||
412 | } | ||
413 | |||
414 | /* Load Segment Address Register */ | ||
415 | REG_FLD_MOD(HDMI_CORE_DDC_SEGM, ext/2, 7, 0); | ||
416 | |||
417 | /* Load Slave Address Register */ | ||
418 | REG_FLD_MOD(HDMI_CORE_DDC_ADDR, 0xA0 >> 1, 7, 1); | ||
419 | |||
420 | /* Load Offset Address Register */ | ||
421 | REG_FLD_MOD(HDMI_CORE_DDC_OFFSET, offset, 7, 0); | ||
422 | |||
423 | /* Load Byte Count */ | ||
424 | REG_FLD_MOD(HDMI_CORE_DDC_COUNT1, 0x80, 7, 0); | ||
425 | REG_FLD_MOD(HDMI_CORE_DDC_COUNT2, 0x0, 1, 0); | ||
426 | |||
427 | /* Set DDC_CMD */ | ||
428 | if (ext) | ||
429 | REG_FLD_MOD(HDMI_CORE_DDC_CMD, 0x4, 3, 0); | ||
430 | else | ||
431 | REG_FLD_MOD(HDMI_CORE_DDC_CMD, 0x2, 3, 0); | ||
432 | |||
433 | /* HDMI_CORE_DDC_STATUS_BUS_LOW */ | ||
434 | if (REG_GET(HDMI_CORE_DDC_STATUS, 6, 6) == 1) { | ||
435 | DSSWARN("I2C Bus Low?\n"); | ||
436 | return -EIO; | ||
437 | } | ||
438 | /* HDMI_CORE_DDC_STATUS_NO_ACK */ | ||
439 | if (REG_GET(HDMI_CORE_DDC_STATUS, 5, 5) == 1) { | ||
440 | DSSWARN("I2C No Ack\n"); | ||
441 | return -EIO; | ||
442 | } | ||
443 | |||
444 | i = ext * 128; | ||
445 | j = 0; | ||
446 | while (((REG_GET(HDMI_CORE_DDC_STATUS, 4, 4) == 1) || | ||
447 | (REG_GET(HDMI_CORE_DDC_STATUS, 2, 2) == 0)) && | ||
448 | j < 128) { | ||
449 | |||
450 | if (REG_GET(HDMI_CORE_DDC_STATUS, 2, 2) == 0) { | ||
451 | /* FIFO not empty */ | ||
452 | pedid[i++] = REG_GET(HDMI_CORE_DDC_DATA, 7, 0); | ||
453 | j++; | ||
454 | } | ||
455 | } | ||
456 | |||
457 | for (j = 0; j < 128; j++) | ||
458 | checksum += pedid[j]; | ||
459 | |||
460 | if (checksum != 0) { | ||
461 | DSSERR("E-EDID checksum failed!!\n"); | ||
462 | return -EIO; | ||
463 | } | ||
464 | |||
465 | return 0; | ||
466 | } | ||
467 | |||
468 | static int read_edid(u8 *pedid, u16 max_length) | ||
469 | { | ||
470 | int r = 0, n = 0, i = 0; | ||
471 | int max_ext_blocks = (max_length / 128) - 1; | ||
472 | |||
473 | r = hdmi_core_ddc_edid(pedid, 0); | ||
474 | if (r) { | ||
475 | return r; | ||
476 | } else { | ||
477 | n = pedid[0x7e]; | ||
478 | |||
479 | /* | ||
480 | * README: need to comply with max_length set by the caller. | ||
481 | * Better implementation should be to allocate necessary | ||
482 | * memory to store EDID according to nb_block field found | ||
483 | * in first block | ||
484 | */ | ||
485 | if (n > max_ext_blocks) | ||
486 | n = max_ext_blocks; | ||
487 | |||
488 | for (i = 1; i <= n; i++) { | ||
489 | r = hdmi_core_ddc_edid(pedid, i); | ||
490 | if (r) | ||
491 | return r; | ||
492 | } | ||
493 | } | ||
494 | return 0; | 188 | return 0; |
495 | } | 189 | } |
496 | 190 | ||
@@ -518,7 +212,7 @@ static struct hdmi_cm hdmi_get_code(struct omap_video_timings *timing) | |||
518 | { | 212 | { |
519 | int i = 0, code = -1, temp_vsync = 0, temp_hsync = 0; | 213 | int i = 0, code = -1, temp_vsync = 0, temp_hsync = 0; |
520 | int timing_vsync = 0, timing_hsync = 0; | 214 | int timing_vsync = 0, timing_hsync = 0; |
521 | struct omap_video_timings temp; | 215 | struct hdmi_video_timings temp; |
522 | struct hdmi_cm cm = {-1}; | 216 | struct hdmi_cm cm = {-1}; |
523 | DSSDBG("hdmi_get_code\n"); | 217 | DSSDBG("hdmi_get_code\n"); |
524 | 218 | ||
@@ -556,500 +250,6 @@ static struct hdmi_cm hdmi_get_code(struct omap_video_timings *timing) | |||
556 | return cm; | 250 | return cm; |
557 | } | 251 | } |
558 | 252 | ||
559 | static void get_horz_vert_timing_info(int current_descriptor_addrs, u8 *edid , | ||
560 | struct omap_video_timings *timings) | ||
561 | { | ||
562 | /* X and Y resolution */ | ||
563 | timings->x_res = (((edid[current_descriptor_addrs + 4] & 0xF0) << 4) | | ||
564 | edid[current_descriptor_addrs + 2]); | ||
565 | timings->y_res = (((edid[current_descriptor_addrs + 7] & 0xF0) << 4) | | ||
566 | edid[current_descriptor_addrs + 5]); | ||
567 | |||
568 | timings->pixel_clock = ((edid[current_descriptor_addrs + 1] << 8) | | ||
569 | edid[current_descriptor_addrs]); | ||
570 | |||
571 | timings->pixel_clock = 10 * timings->pixel_clock; | ||
572 | |||
573 | /* HORIZONTAL FRONT PORCH */ | ||
574 | timings->hfp = edid[current_descriptor_addrs + 8] | | ||
575 | ((edid[current_descriptor_addrs + 11] & 0xc0) << 2); | ||
576 | /* HORIZONTAL SYNC WIDTH */ | ||
577 | timings->hsw = edid[current_descriptor_addrs + 9] | | ||
578 | ((edid[current_descriptor_addrs + 11] & 0x30) << 4); | ||
579 | /* HORIZONTAL BACK PORCH */ | ||
580 | timings->hbp = (((edid[current_descriptor_addrs + 4] & 0x0F) << 8) | | ||
581 | edid[current_descriptor_addrs + 3]) - | ||
582 | (timings->hfp + timings->hsw); | ||
583 | /* VERTICAL FRONT PORCH */ | ||
584 | timings->vfp = ((edid[current_descriptor_addrs + 10] & 0xF0) >> 4) | | ||
585 | ((edid[current_descriptor_addrs + 11] & 0x0f) << 2); | ||
586 | /* VERTICAL SYNC WIDTH */ | ||
587 | timings->vsw = (edid[current_descriptor_addrs + 10] & 0x0F) | | ||
588 | ((edid[current_descriptor_addrs + 11] & 0x03) << 4); | ||
589 | /* VERTICAL BACK PORCH */ | ||
590 | timings->vbp = (((edid[current_descriptor_addrs + 7] & 0x0F) << 8) | | ||
591 | edid[current_descriptor_addrs + 6]) - | ||
592 | (timings->vfp + timings->vsw); | ||
593 | |||
594 | } | ||
595 | |||
596 | /* Description : This function gets the resolution information from EDID */ | ||
597 | static void get_edid_timing_data(u8 *edid) | ||
598 | { | ||
599 | u8 count; | ||
600 | u16 current_descriptor_addrs; | ||
601 | struct hdmi_cm cm; | ||
602 | struct omap_video_timings edid_timings; | ||
603 | |||
604 | /* search block 0, there are 4 DTDs arranged in priority order */ | ||
605 | for (count = 0; count < EDID_SIZE_BLOCK0_TIMING_DESCRIPTOR; count++) { | ||
606 | current_descriptor_addrs = | ||
607 | EDID_DESCRIPTOR_BLOCK0_ADDRESS + | ||
608 | count * EDID_TIMING_DESCRIPTOR_SIZE; | ||
609 | get_horz_vert_timing_info(current_descriptor_addrs, | ||
610 | edid, &edid_timings); | ||
611 | cm = hdmi_get_code(&edid_timings); | ||
612 | DSSDBG("Block0[%d] value matches code = %d , mode = %d\n", | ||
613 | count, cm.code, cm.mode); | ||
614 | if (cm.code == -1) { | ||
615 | continue; | ||
616 | } else { | ||
617 | hdmi.code = cm.code; | ||
618 | hdmi.mode = cm.mode; | ||
619 | DSSDBG("code = %d , mode = %d\n", | ||
620 | hdmi.code, hdmi.mode); | ||
621 | return; | ||
622 | } | ||
623 | } | ||
624 | if (edid[0x7e] != 0x00) { | ||
625 | for (count = 0; count < EDID_SIZE_BLOCK1_TIMING_DESCRIPTOR; | ||
626 | count++) { | ||
627 | current_descriptor_addrs = | ||
628 | EDID_DESCRIPTOR_BLOCK1_ADDRESS + | ||
629 | count * EDID_TIMING_DESCRIPTOR_SIZE; | ||
630 | get_horz_vert_timing_info(current_descriptor_addrs, | ||
631 | edid, &edid_timings); | ||
632 | cm = hdmi_get_code(&edid_timings); | ||
633 | DSSDBG("Block1[%d] value matches code = %d, mode = %d", | ||
634 | count, cm.code, cm.mode); | ||
635 | if (cm.code == -1) { | ||
636 | continue; | ||
637 | } else { | ||
638 | hdmi.code = cm.code; | ||
639 | hdmi.mode = cm.mode; | ||
640 | DSSDBG("code = %d , mode = %d\n", | ||
641 | hdmi.code, hdmi.mode); | ||
642 | return; | ||
643 | } | ||
644 | } | ||
645 | } | ||
646 | |||
647 | DSSINFO("no valid timing found , falling back to VGA\n"); | ||
648 | hdmi.code = 4; /* setting default value of 640 480 VGA */ | ||
649 | hdmi.mode = HDMI_DVI; | ||
650 | } | ||
651 | |||
652 | static void hdmi_read_edid(struct omap_video_timings *dp) | ||
653 | { | ||
654 | int ret = 0, code; | ||
655 | |||
656 | memset(hdmi.edid, 0, HDMI_EDID_MAX_LENGTH); | ||
657 | |||
658 | if (!hdmi.edid_set) | ||
659 | ret = read_edid(hdmi.edid, HDMI_EDID_MAX_LENGTH); | ||
660 | |||
661 | if (!ret) { | ||
662 | if (!memcmp(hdmi.edid, edid_header, sizeof(edid_header))) { | ||
663 | /* search for timings of default resolution */ | ||
664 | get_edid_timing_data(hdmi.edid); | ||
665 | hdmi.edid_set = true; | ||
666 | } | ||
667 | } else { | ||
668 | DSSWARN("failed to read E-EDID\n"); | ||
669 | } | ||
670 | |||
671 | if (!hdmi.edid_set) { | ||
672 | DSSINFO("fallback to VGA\n"); | ||
673 | hdmi.code = 4; /* setting default value of 640 480 VGA */ | ||
674 | hdmi.mode = HDMI_DVI; | ||
675 | } | ||
676 | |||
677 | code = get_timings_index(); | ||
678 | |||
679 | *dp = cea_vesa_timings[code].timings; | ||
680 | } | ||
681 | |||
682 | static void hdmi_core_init(struct hdmi_core_video_config *video_cfg, | ||
683 | struct hdmi_core_infoframe_avi *avi_cfg, | ||
684 | struct hdmi_core_packet_enable_repeat *repeat_cfg) | ||
685 | { | ||
686 | DSSDBG("Enter hdmi_core_init\n"); | ||
687 | |||
688 | /* video core */ | ||
689 | video_cfg->ip_bus_width = HDMI_INPUT_8BIT; | ||
690 | video_cfg->op_dither_truc = HDMI_OUTPUTTRUNCATION_8BIT; | ||
691 | video_cfg->deep_color_pkt = HDMI_DEEPCOLORPACKECTDISABLE; | ||
692 | video_cfg->pkt_mode = HDMI_PACKETMODERESERVEDVALUE; | ||
693 | video_cfg->hdmi_dvi = HDMI_DVI; | ||
694 | video_cfg->tclk_sel_clkmult = HDMI_FPLL10IDCK; | ||
695 | |||
696 | /* info frame */ | ||
697 | avi_cfg->db1_format = 0; | ||
698 | avi_cfg->db1_active_info = 0; | ||
699 | avi_cfg->db1_bar_info_dv = 0; | ||
700 | avi_cfg->db1_scan_info = 0; | ||
701 | avi_cfg->db2_colorimetry = 0; | ||
702 | avi_cfg->db2_aspect_ratio = 0; | ||
703 | avi_cfg->db2_active_fmt_ar = 0; | ||
704 | avi_cfg->db3_itc = 0; | ||
705 | avi_cfg->db3_ec = 0; | ||
706 | avi_cfg->db3_q_range = 0; | ||
707 | avi_cfg->db3_nup_scaling = 0; | ||
708 | avi_cfg->db4_videocode = 0; | ||
709 | avi_cfg->db5_pixel_repeat = 0; | ||
710 | avi_cfg->db6_7_line_eoftop = 0 ; | ||
711 | avi_cfg->db8_9_line_sofbottom = 0; | ||
712 | avi_cfg->db10_11_pixel_eofleft = 0; | ||
713 | avi_cfg->db12_13_pixel_sofright = 0; | ||
714 | |||
715 | /* packet enable and repeat */ | ||
716 | repeat_cfg->audio_pkt = 0; | ||
717 | repeat_cfg->audio_pkt_repeat = 0; | ||
718 | repeat_cfg->avi_infoframe = 0; | ||
719 | repeat_cfg->avi_infoframe_repeat = 0; | ||
720 | repeat_cfg->gen_cntrl_pkt = 0; | ||
721 | repeat_cfg->gen_cntrl_pkt_repeat = 0; | ||
722 | repeat_cfg->generic_pkt = 0; | ||
723 | repeat_cfg->generic_pkt_repeat = 0; | ||
724 | } | ||
725 | |||
726 | static void hdmi_core_powerdown_disable(void) | ||
727 | { | ||
728 | DSSDBG("Enter hdmi_core_powerdown_disable\n"); | ||
729 | REG_FLD_MOD(HDMI_CORE_CTRL1, 0x0, 0, 0); | ||
730 | } | ||
731 | |||
732 | static void hdmi_core_swreset_release(void) | ||
733 | { | ||
734 | DSSDBG("Enter hdmi_core_swreset_release\n"); | ||
735 | REG_FLD_MOD(HDMI_CORE_SYS_SRST, 0x0, 0, 0); | ||
736 | } | ||
737 | |||
738 | static void hdmi_core_swreset_assert(void) | ||
739 | { | ||
740 | DSSDBG("Enter hdmi_core_swreset_assert\n"); | ||
741 | REG_FLD_MOD(HDMI_CORE_SYS_SRST, 0x1, 0, 0); | ||
742 | } | ||
743 | |||
744 | /* DSS_HDMI_CORE_VIDEO_CONFIG */ | ||
745 | static void hdmi_core_video_config(struct hdmi_core_video_config *cfg) | ||
746 | { | ||
747 | u32 r = 0; | ||
748 | |||
749 | /* sys_ctrl1 default configuration not tunable */ | ||
750 | r = hdmi_read_reg(HDMI_CORE_CTRL1); | ||
751 | r = FLD_MOD(r, HDMI_CORE_CTRL1_VEN_FOLLOWVSYNC, 5, 5); | ||
752 | r = FLD_MOD(r, HDMI_CORE_CTRL1_HEN_FOLLOWHSYNC, 4, 4); | ||
753 | r = FLD_MOD(r, HDMI_CORE_CTRL1_BSEL_24BITBUS, 2, 2); | ||
754 | r = FLD_MOD(r, HDMI_CORE_CTRL1_EDGE_RISINGEDGE, 1, 1); | ||
755 | hdmi_write_reg(HDMI_CORE_CTRL1, r); | ||
756 | |||
757 | REG_FLD_MOD(HDMI_CORE_SYS_VID_ACEN, cfg->ip_bus_width, 7, 6); | ||
758 | |||
759 | /* Vid_Mode */ | ||
760 | r = hdmi_read_reg(HDMI_CORE_SYS_VID_MODE); | ||
761 | |||
762 | /* dither truncation configuration */ | ||
763 | if (cfg->op_dither_truc > HDMI_OUTPUTTRUNCATION_12BIT) { | ||
764 | r = FLD_MOD(r, cfg->op_dither_truc - 3, 7, 6); | ||
765 | r = FLD_MOD(r, 1, 5, 5); | ||
766 | } else { | ||
767 | r = FLD_MOD(r, cfg->op_dither_truc, 7, 6); | ||
768 | r = FLD_MOD(r, 0, 5, 5); | ||
769 | } | ||
770 | hdmi_write_reg(HDMI_CORE_SYS_VID_MODE, r); | ||
771 | |||
772 | /* HDMI_Ctrl */ | ||
773 | r = hdmi_read_reg(HDMI_CORE_AV_HDMI_CTRL); | ||
774 | r = FLD_MOD(r, cfg->deep_color_pkt, 6, 6); | ||
775 | r = FLD_MOD(r, cfg->pkt_mode, 5, 3); | ||
776 | r = FLD_MOD(r, cfg->hdmi_dvi, 0, 0); | ||
777 | hdmi_write_reg(HDMI_CORE_AV_HDMI_CTRL, r); | ||
778 | |||
779 | /* TMDS_CTRL */ | ||
780 | REG_FLD_MOD(HDMI_CORE_SYS_TMDS_CTRL, | ||
781 | cfg->tclk_sel_clkmult, 6, 5); | ||
782 | } | ||
783 | |||
784 | static void hdmi_core_aux_infoframe_avi_config( | ||
785 | struct hdmi_core_infoframe_avi info_avi) | ||
786 | { | ||
787 | u32 val; | ||
788 | char sum = 0, checksum = 0; | ||
789 | |||
790 | sum += 0x82 + 0x002 + 0x00D; | ||
791 | hdmi_write_reg(HDMI_CORE_AV_AVI_TYPE, 0x082); | ||
792 | hdmi_write_reg(HDMI_CORE_AV_AVI_VERS, 0x002); | ||
793 | hdmi_write_reg(HDMI_CORE_AV_AVI_LEN, 0x00D); | ||
794 | |||
795 | val = (info_avi.db1_format << 5) | | ||
796 | (info_avi.db1_active_info << 4) | | ||
797 | (info_avi.db1_bar_info_dv << 2) | | ||
798 | (info_avi.db1_scan_info); | ||
799 | hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(0), val); | ||
800 | sum += val; | ||
801 | |||
802 | val = (info_avi.db2_colorimetry << 6) | | ||
803 | (info_avi.db2_aspect_ratio << 4) | | ||
804 | (info_avi.db2_active_fmt_ar); | ||
805 | hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(1), val); | ||
806 | sum += val; | ||
807 | |||
808 | val = (info_avi.db3_itc << 7) | | ||
809 | (info_avi.db3_ec << 4) | | ||
810 | (info_avi.db3_q_range << 2) | | ||
811 | (info_avi.db3_nup_scaling); | ||
812 | hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(2), val); | ||
813 | sum += val; | ||
814 | |||
815 | hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(3), info_avi.db4_videocode); | ||
816 | sum += info_avi.db4_videocode; | ||
817 | |||
818 | val = info_avi.db5_pixel_repeat; | ||
819 | hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(4), val); | ||
820 | sum += val; | ||
821 | |||
822 | val = info_avi.db6_7_line_eoftop & 0x00FF; | ||
823 | hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(5), val); | ||
824 | sum += val; | ||
825 | |||
826 | val = ((info_avi.db6_7_line_eoftop >> 8) & 0x00FF); | ||
827 | hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(6), val); | ||
828 | sum += val; | ||
829 | |||
830 | val = info_avi.db8_9_line_sofbottom & 0x00FF; | ||
831 | hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(7), val); | ||
832 | sum += val; | ||
833 | |||
834 | val = ((info_avi.db8_9_line_sofbottom >> 8) & 0x00FF); | ||
835 | hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(8), val); | ||
836 | sum += val; | ||
837 | |||
838 | val = info_avi.db10_11_pixel_eofleft & 0x00FF; | ||
839 | hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(9), val); | ||
840 | sum += val; | ||
841 | |||
842 | val = ((info_avi.db10_11_pixel_eofleft >> 8) & 0x00FF); | ||
843 | hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(10), val); | ||
844 | sum += val; | ||
845 | |||
846 | val = info_avi.db12_13_pixel_sofright & 0x00FF; | ||
847 | hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(11), val); | ||
848 | sum += val; | ||
849 | |||
850 | val = ((info_avi.db12_13_pixel_sofright >> 8) & 0x00FF); | ||
851 | hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(12), val); | ||
852 | sum += val; | ||
853 | |||
854 | checksum = 0x100 - sum; | ||
855 | hdmi_write_reg(HDMI_CORE_AV_AVI_CHSUM, checksum); | ||
856 | } | ||
857 | |||
858 | static void hdmi_core_av_packet_config( | ||
859 | struct hdmi_core_packet_enable_repeat repeat_cfg) | ||
860 | { | ||
861 | /* enable/repeat the infoframe */ | ||
862 | hdmi_write_reg(HDMI_CORE_AV_PB_CTRL1, | ||
863 | (repeat_cfg.audio_pkt << 5) | | ||
864 | (repeat_cfg.audio_pkt_repeat << 4) | | ||
865 | (repeat_cfg.avi_infoframe << 1) | | ||
866 | (repeat_cfg.avi_infoframe_repeat)); | ||
867 | |||
868 | /* enable/repeat the packet */ | ||
869 | hdmi_write_reg(HDMI_CORE_AV_PB_CTRL2, | ||
870 | (repeat_cfg.gen_cntrl_pkt << 3) | | ||
871 | (repeat_cfg.gen_cntrl_pkt_repeat << 2) | | ||
872 | (repeat_cfg.generic_pkt << 1) | | ||
873 | (repeat_cfg.generic_pkt_repeat)); | ||
874 | } | ||
875 | |||
876 | static void hdmi_wp_init(struct omap_video_timings *timings, | ||
877 | struct hdmi_video_format *video_fmt, | ||
878 | struct hdmi_video_interface *video_int) | ||
879 | { | ||
880 | DSSDBG("Enter hdmi_wp_init\n"); | ||
881 | |||
882 | timings->hbp = 0; | ||
883 | timings->hfp = 0; | ||
884 | timings->hsw = 0; | ||
885 | timings->vbp = 0; | ||
886 | timings->vfp = 0; | ||
887 | timings->vsw = 0; | ||
888 | |||
889 | video_fmt->packing_mode = HDMI_PACK_10b_RGB_YUV444; | ||
890 | video_fmt->y_res = 0; | ||
891 | video_fmt->x_res = 0; | ||
892 | |||
893 | video_int->vsp = 0; | ||
894 | video_int->hsp = 0; | ||
895 | |||
896 | video_int->interlacing = 0; | ||
897 | video_int->tm = 0; /* HDMI_TIMING_SLAVE */ | ||
898 | |||
899 | } | ||
900 | |||
901 | static void hdmi_wp_video_start(bool start) | ||
902 | { | ||
903 | REG_FLD_MOD(HDMI_WP_VIDEO_CFG, start, 31, 31); | ||
904 | } | ||
905 | |||
906 | static void hdmi_wp_video_init_format(struct hdmi_video_format *video_fmt, | ||
907 | struct omap_video_timings *timings, struct hdmi_config *param) | ||
908 | { | ||
909 | DSSDBG("Enter hdmi_wp_video_init_format\n"); | ||
910 | |||
911 | video_fmt->y_res = param->timings.timings.y_res; | ||
912 | video_fmt->x_res = param->timings.timings.x_res; | ||
913 | |||
914 | timings->hbp = param->timings.timings.hbp; | ||
915 | timings->hfp = param->timings.timings.hfp; | ||
916 | timings->hsw = param->timings.timings.hsw; | ||
917 | timings->vbp = param->timings.timings.vbp; | ||
918 | timings->vfp = param->timings.timings.vfp; | ||
919 | timings->vsw = param->timings.timings.vsw; | ||
920 | } | ||
921 | |||
922 | static void hdmi_wp_video_config_format( | ||
923 | struct hdmi_video_format *video_fmt) | ||
924 | { | ||
925 | u32 l = 0; | ||
926 | |||
927 | REG_FLD_MOD(HDMI_WP_VIDEO_CFG, video_fmt->packing_mode, 10, 8); | ||
928 | |||
929 | l |= FLD_VAL(video_fmt->y_res, 31, 16); | ||
930 | l |= FLD_VAL(video_fmt->x_res, 15, 0); | ||
931 | hdmi_write_reg(HDMI_WP_VIDEO_SIZE, l); | ||
932 | } | ||
933 | |||
934 | static void hdmi_wp_video_config_interface( | ||
935 | struct hdmi_video_interface *video_int) | ||
936 | { | ||
937 | u32 r; | ||
938 | DSSDBG("Enter hdmi_wp_video_config_interface\n"); | ||
939 | |||
940 | r = hdmi_read_reg(HDMI_WP_VIDEO_CFG); | ||
941 | r = FLD_MOD(r, video_int->vsp, 7, 7); | ||
942 | r = FLD_MOD(r, video_int->hsp, 6, 6); | ||
943 | r = FLD_MOD(r, video_int->interlacing, 3, 3); | ||
944 | r = FLD_MOD(r, video_int->tm, 1, 0); | ||
945 | hdmi_write_reg(HDMI_WP_VIDEO_CFG, r); | ||
946 | } | ||
947 | |||
948 | static void hdmi_wp_video_config_timing( | ||
949 | struct omap_video_timings *timings) | ||
950 | { | ||
951 | u32 timing_h = 0; | ||
952 | u32 timing_v = 0; | ||
953 | |||
954 | DSSDBG("Enter hdmi_wp_video_config_timing\n"); | ||
955 | |||
956 | timing_h |= FLD_VAL(timings->hbp, 31, 20); | ||
957 | timing_h |= FLD_VAL(timings->hfp, 19, 8); | ||
958 | timing_h |= FLD_VAL(timings->hsw, 7, 0); | ||
959 | hdmi_write_reg(HDMI_WP_VIDEO_TIMING_H, timing_h); | ||
960 | |||
961 | timing_v |= FLD_VAL(timings->vbp, 31, 20); | ||
962 | timing_v |= FLD_VAL(timings->vfp, 19, 8); | ||
963 | timing_v |= FLD_VAL(timings->vsw, 7, 0); | ||
964 | hdmi_write_reg(HDMI_WP_VIDEO_TIMING_V, timing_v); | ||
965 | } | ||
966 | |||
967 | static void hdmi_basic_configure(struct hdmi_config *cfg) | ||
968 | { | ||
969 | /* HDMI */ | ||
970 | struct omap_video_timings video_timing; | ||
971 | struct hdmi_video_format video_format; | ||
972 | struct hdmi_video_interface video_interface; | ||
973 | /* HDMI core */ | ||
974 | struct hdmi_core_infoframe_avi avi_cfg; | ||
975 | struct hdmi_core_video_config v_core_cfg; | ||
976 | struct hdmi_core_packet_enable_repeat repeat_cfg; | ||
977 | |||
978 | hdmi_wp_init(&video_timing, &video_format, | ||
979 | &video_interface); | ||
980 | |||
981 | hdmi_core_init(&v_core_cfg, | ||
982 | &avi_cfg, | ||
983 | &repeat_cfg); | ||
984 | |||
985 | hdmi_wp_video_init_format(&video_format, | ||
986 | &video_timing, cfg); | ||
987 | |||
988 | hdmi_wp_video_config_timing(&video_timing); | ||
989 | |||
990 | /* video config */ | ||
991 | video_format.packing_mode = HDMI_PACK_24b_RGB_YUV444_YUV422; | ||
992 | |||
993 | hdmi_wp_video_config_format(&video_format); | ||
994 | |||
995 | video_interface.vsp = cfg->timings.vsync_pol; | ||
996 | video_interface.hsp = cfg->timings.hsync_pol; | ||
997 | video_interface.interlacing = cfg->interlace; | ||
998 | video_interface.tm = 1 ; /* HDMI_TIMING_MASTER_24BIT */ | ||
999 | |||
1000 | hdmi_wp_video_config_interface(&video_interface); | ||
1001 | |||
1002 | /* | ||
1003 | * configure core video part | ||
1004 | * set software reset in the core | ||
1005 | */ | ||
1006 | hdmi_core_swreset_assert(); | ||
1007 | |||
1008 | /* power down off */ | ||
1009 | hdmi_core_powerdown_disable(); | ||
1010 | |||
1011 | v_core_cfg.pkt_mode = HDMI_PACKETMODE24BITPERPIXEL; | ||
1012 | v_core_cfg.hdmi_dvi = cfg->cm.mode; | ||
1013 | |||
1014 | hdmi_core_video_config(&v_core_cfg); | ||
1015 | |||
1016 | /* release software reset in the core */ | ||
1017 | hdmi_core_swreset_release(); | ||
1018 | |||
1019 | /* | ||
1020 | * configure packet | ||
1021 | * info frame video see doc CEA861-D page 65 | ||
1022 | */ | ||
1023 | avi_cfg.db1_format = HDMI_INFOFRAME_AVI_DB1Y_RGB; | ||
1024 | avi_cfg.db1_active_info = | ||
1025 | HDMI_INFOFRAME_AVI_DB1A_ACTIVE_FORMAT_OFF; | ||
1026 | avi_cfg.db1_bar_info_dv = HDMI_INFOFRAME_AVI_DB1B_NO; | ||
1027 | avi_cfg.db1_scan_info = HDMI_INFOFRAME_AVI_DB1S_0; | ||
1028 | avi_cfg.db2_colorimetry = HDMI_INFOFRAME_AVI_DB2C_NO; | ||
1029 | avi_cfg.db2_aspect_ratio = HDMI_INFOFRAME_AVI_DB2M_NO; | ||
1030 | avi_cfg.db2_active_fmt_ar = HDMI_INFOFRAME_AVI_DB2R_SAME; | ||
1031 | avi_cfg.db3_itc = HDMI_INFOFRAME_AVI_DB3ITC_NO; | ||
1032 | avi_cfg.db3_ec = HDMI_INFOFRAME_AVI_DB3EC_XVYUV601; | ||
1033 | avi_cfg.db3_q_range = HDMI_INFOFRAME_AVI_DB3Q_DEFAULT; | ||
1034 | avi_cfg.db3_nup_scaling = HDMI_INFOFRAME_AVI_DB3SC_NO; | ||
1035 | avi_cfg.db4_videocode = cfg->cm.code; | ||
1036 | avi_cfg.db5_pixel_repeat = HDMI_INFOFRAME_AVI_DB5PR_NO; | ||
1037 | avi_cfg.db6_7_line_eoftop = 0; | ||
1038 | avi_cfg.db8_9_line_sofbottom = 0; | ||
1039 | avi_cfg.db10_11_pixel_eofleft = 0; | ||
1040 | avi_cfg.db12_13_pixel_sofright = 0; | ||
1041 | |||
1042 | hdmi_core_aux_infoframe_avi_config(avi_cfg); | ||
1043 | |||
1044 | /* enable/repeat the infoframe */ | ||
1045 | repeat_cfg.avi_infoframe = HDMI_PACKETENABLE; | ||
1046 | repeat_cfg.avi_infoframe_repeat = HDMI_PACKETREPEATON; | ||
1047 | /* wakeup */ | ||
1048 | repeat_cfg.audio_pkt = HDMI_PACKETENABLE; | ||
1049 | repeat_cfg.audio_pkt_repeat = HDMI_PACKETREPEATON; | ||
1050 | hdmi_core_av_packet_config(repeat_cfg); | ||
1051 | } | ||
1052 | |||
1053 | static void update_hdmi_timings(struct hdmi_config *cfg, | 253 | static void update_hdmi_timings(struct hdmi_config *cfg, |
1054 | struct omap_video_timings *timings, int code) | 254 | struct omap_video_timings *timings, int code) |
1055 | { | 255 | { |
@@ -1066,6 +266,12 @@ static void update_hdmi_timings(struct hdmi_config *cfg, | |||
1066 | cfg->timings.hsync_pol = cea_vesa_timings[code].hsync_pol; | 266 | cfg->timings.hsync_pol = cea_vesa_timings[code].hsync_pol; |
1067 | } | 267 | } |
1068 | 268 | ||
269 | unsigned long hdmi_get_pixel_clock(void) | ||
270 | { | ||
271 | /* HDMI Pixel Clock in Mhz */ | ||
272 | return hdmi.ip_data.cfg.timings.timings.pixel_clock * 10000; | ||
273 | } | ||
274 | |||
1069 | static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy, | 275 | static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy, |
1070 | struct hdmi_pll_info *pi) | 276 | struct hdmi_pll_info *pi) |
1071 | { | 277 | { |
@@ -1077,15 +283,23 @@ static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy, | |||
1077 | * Input clock is predivided by N + 1 | 283 | * Input clock is predivided by N + 1 |
1078 | * out put of which is reference clk | 284 | * out put of which is reference clk |
1079 | */ | 285 | */ |
1080 | pi->regn = dssdev->clocks.hdmi.regn; | 286 | if (dssdev->clocks.hdmi.regn == 0) |
1081 | refclk = clkin / (pi->regn + 1); | 287 | pi->regn = HDMI_DEFAULT_REGN; |
288 | else | ||
289 | pi->regn = dssdev->clocks.hdmi.regn; | ||
290 | |||
291 | refclk = clkin / pi->regn; | ||
1082 | 292 | ||
1083 | /* | 293 | /* |
1084 | * multiplier is pixel_clk/ref_clk | 294 | * multiplier is pixel_clk/ref_clk |
1085 | * Multiplying by 100 to avoid fractional part removal | 295 | * Multiplying by 100 to avoid fractional part removal |
1086 | */ | 296 | */ |
1087 | pi->regm = (phy * 100 / (refclk)) / 100; | 297 | pi->regm = (phy * 100 / (refclk)) / 100; |
1088 | pi->regm2 = dssdev->clocks.hdmi.regm2; | 298 | |
299 | if (dssdev->clocks.hdmi.regm2 == 0) | ||
300 | pi->regm2 = HDMI_DEFAULT_REGM2; | ||
301 | else | ||
302 | pi->regm2 = dssdev->clocks.hdmi.regm2; | ||
1089 | 303 | ||
1090 | /* | 304 | /* |
1091 | * fractional multiplier is remainder of the difference between | 305 | * fractional multiplier is remainder of the difference between |
@@ -1100,7 +314,10 @@ static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy, | |||
1100 | * is greater than 1000MHz | 314 | * is greater than 1000MHz |
1101 | */ | 315 | */ |
1102 | pi->dcofreq = phy > 1000 * 100; | 316 | pi->dcofreq = phy > 1000 * 100; |
1103 | pi->regsd = ((pi->regm * clkin / 10) / ((pi->regn + 1) * 250) + 5) / 10; | 317 | pi->regsd = ((pi->regm * clkin / 10) / (pi->regn * 250) + 5) / 10; |
318 | |||
319 | /* Set the reference clock to sysclk reference */ | ||
320 | pi->refsel = HDMI_REFSEL_SYSCLK; | ||
1104 | 321 | ||
1105 | DSSDBG("M = %d Mf = %d\n", pi->regm, pi->regmf); | 322 | DSSDBG("M = %d Mf = %d\n", pi->regm, pi->regmf); |
1106 | DSSDBG("range = %d sd = %d\n", pi->dcofreq, pi->regsd); | 323 | DSSDBG("range = %d sd = %d\n", pi->dcofreq, pi->regsd); |
@@ -1109,7 +326,6 @@ static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy, | |||
1109 | static int hdmi_power_on(struct omap_dss_device *dssdev) | 326 | static int hdmi_power_on(struct omap_dss_device *dssdev) |
1110 | { | 327 | { |
1111 | int r, code = 0; | 328 | int r, code = 0; |
1112 | struct hdmi_pll_info pll_data; | ||
1113 | struct omap_video_timings *p; | 329 | struct omap_video_timings *p; |
1114 | unsigned long phy; | 330 | unsigned long phy; |
1115 | 331 | ||
@@ -1117,7 +333,7 @@ static int hdmi_power_on(struct omap_dss_device *dssdev) | |||
1117 | if (r) | 333 | if (r) |
1118 | return r; | 334 | return r; |
1119 | 335 | ||
1120 | dispc_enable_channel(OMAP_DSS_CHANNEL_DIGIT, 0); | 336 | dispc_mgr_enable(OMAP_DSS_CHANNEL_DIGIT, 0); |
1121 | 337 | ||
1122 | p = &dssdev->panel.timings; | 338 | p = &dssdev->panel.timings; |
1123 | 339 | ||
@@ -1125,36 +341,31 @@ static int hdmi_power_on(struct omap_dss_device *dssdev) | |||
1125 | dssdev->panel.timings.x_res, | 341 | dssdev->panel.timings.x_res, |
1126 | dssdev->panel.timings.y_res); | 342 | dssdev->panel.timings.y_res); |
1127 | 343 | ||
1128 | if (!hdmi.custom_set) { | ||
1129 | DSSDBG("Read EDID as no EDID is not set on poweron\n"); | ||
1130 | hdmi_read_edid(p); | ||
1131 | } | ||
1132 | code = get_timings_index(); | 344 | code = get_timings_index(); |
1133 | dssdev->panel.timings = cea_vesa_timings[code].timings; | 345 | update_hdmi_timings(&hdmi.ip_data.cfg, p, code); |
1134 | update_hdmi_timings(&hdmi.cfg, p, code); | ||
1135 | 346 | ||
1136 | phy = p->pixel_clock; | 347 | phy = p->pixel_clock; |
1137 | 348 | ||
1138 | hdmi_compute_pll(dssdev, phy, &pll_data); | 349 | hdmi_compute_pll(dssdev, phy, &hdmi.ip_data.pll_data); |
1139 | 350 | ||
1140 | hdmi_wp_video_start(0); | 351 | hdmi.ip_data.ops->video_enable(&hdmi.ip_data, 0); |
1141 | 352 | ||
1142 | /* config the PLL and PHY first */ | 353 | /* config the PLL and PHY hdmi_set_pll_pwrfirst */ |
1143 | r = hdmi_pll_program(&pll_data); | 354 | r = hdmi.ip_data.ops->pll_enable(&hdmi.ip_data); |
1144 | if (r) { | 355 | if (r) { |
1145 | DSSDBG("Failed to lock PLL\n"); | 356 | DSSDBG("Failed to lock PLL\n"); |
1146 | goto err; | 357 | goto err; |
1147 | } | 358 | } |
1148 | 359 | ||
1149 | r = hdmi_phy_init(); | 360 | r = hdmi.ip_data.ops->phy_enable(&hdmi.ip_data); |
1150 | if (r) { | 361 | if (r) { |
1151 | DSSDBG("Failed to start PHY\n"); | 362 | DSSDBG("Failed to start PHY\n"); |
1152 | goto err; | 363 | goto err; |
1153 | } | 364 | } |
1154 | 365 | ||
1155 | hdmi.cfg.cm.mode = hdmi.mode; | 366 | hdmi.ip_data.cfg.cm.mode = hdmi.mode; |
1156 | hdmi.cfg.cm.code = hdmi.code; | 367 | hdmi.ip_data.cfg.cm.code = hdmi.code; |
1157 | hdmi_basic_configure(&hdmi.cfg); | 368 | hdmi.ip_data.ops->video_configure(&hdmi.ip_data); |
1158 | 369 | ||
1159 | /* Make selection of HDMI in DSS */ | 370 | /* Make selection of HDMI in DSS */ |
1160 | dss_select_hdmi_venc_clk_source(DSS_HDMI_M_PCLK); | 371 | dss_select_hdmi_venc_clk_source(DSS_HDMI_M_PCLK); |
@@ -1174,9 +385,9 @@ static int hdmi_power_on(struct omap_dss_device *dssdev) | |||
1174 | dispc_set_digit_size(dssdev->panel.timings.x_res, | 385 | dispc_set_digit_size(dssdev->panel.timings.x_res, |
1175 | dssdev->panel.timings.y_res); | 386 | dssdev->panel.timings.y_res); |
1176 | 387 | ||
1177 | dispc_enable_channel(OMAP_DSS_CHANNEL_DIGIT, 1); | 388 | hdmi.ip_data.ops->video_enable(&hdmi.ip_data, 1); |
1178 | 389 | ||
1179 | hdmi_wp_video_start(1); | 390 | dispc_mgr_enable(OMAP_DSS_CHANNEL_DIGIT, 1); |
1180 | 391 | ||
1181 | return 0; | 392 | return 0; |
1182 | err: | 393 | err: |
@@ -1186,14 +397,12 @@ err: | |||
1186 | 397 | ||
1187 | static void hdmi_power_off(struct omap_dss_device *dssdev) | 398 | static void hdmi_power_off(struct omap_dss_device *dssdev) |
1188 | { | 399 | { |
1189 | dispc_enable_channel(OMAP_DSS_CHANNEL_DIGIT, 0); | 400 | dispc_mgr_enable(OMAP_DSS_CHANNEL_DIGIT, 0); |
1190 | 401 | ||
1191 | hdmi_wp_video_start(0); | 402 | hdmi.ip_data.ops->video_enable(&hdmi.ip_data, 0); |
1192 | hdmi_phy_off(); | 403 | hdmi.ip_data.ops->phy_disable(&hdmi.ip_data); |
1193 | hdmi_set_pll_pwr(HDMI_PLLPWRCMD_ALLOFF); | 404 | hdmi.ip_data.ops->pll_disable(&hdmi.ip_data); |
1194 | hdmi_runtime_put(); | 405 | hdmi_runtime_put(); |
1195 | |||
1196 | hdmi.edid_set = 0; | ||
1197 | } | 406 | } |
1198 | 407 | ||
1199 | int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev, | 408 | int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev, |
@@ -1203,7 +412,6 @@ int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev, | |||
1203 | 412 | ||
1204 | cm = hdmi_get_code(timings); | 413 | cm = hdmi_get_code(timings); |
1205 | if (cm.code == -1) { | 414 | if (cm.code == -1) { |
1206 | DSSERR("Invalid timing entered\n"); | ||
1207 | return -EINVAL; | 415 | return -EINVAL; |
1208 | } | 416 | } |
1209 | 417 | ||
@@ -1215,12 +423,69 @@ void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev) | |||
1215 | { | 423 | { |
1216 | struct hdmi_cm cm; | 424 | struct hdmi_cm cm; |
1217 | 425 | ||
1218 | hdmi.custom_set = 1; | ||
1219 | cm = hdmi_get_code(&dssdev->panel.timings); | 426 | cm = hdmi_get_code(&dssdev->panel.timings); |
1220 | hdmi.code = cm.code; | 427 | hdmi.code = cm.code; |
1221 | hdmi.mode = cm.mode; | 428 | hdmi.mode = cm.mode; |
1222 | omapdss_hdmi_display_enable(dssdev); | 429 | |
1223 | hdmi.custom_set = 0; | 430 | if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) { |
431 | int r; | ||
432 | |||
433 | hdmi_power_off(dssdev); | ||
434 | |||
435 | r = hdmi_power_on(dssdev); | ||
436 | if (r) | ||
437 | DSSERR("failed to power on device\n"); | ||
438 | } | ||
439 | } | ||
440 | |||
441 | void hdmi_dump_regs(struct seq_file *s) | ||
442 | { | ||
443 | mutex_lock(&hdmi.lock); | ||
444 | |||
445 | if (hdmi_runtime_get()) | ||
446 | return; | ||
447 | |||
448 | hdmi.ip_data.ops->dump_wrapper(&hdmi.ip_data, s); | ||
449 | hdmi.ip_data.ops->dump_pll(&hdmi.ip_data, s); | ||
450 | hdmi.ip_data.ops->dump_phy(&hdmi.ip_data, s); | ||
451 | hdmi.ip_data.ops->dump_core(&hdmi.ip_data, s); | ||
452 | |||
453 | hdmi_runtime_put(); | ||
454 | mutex_unlock(&hdmi.lock); | ||
455 | } | ||
456 | |||
457 | int omapdss_hdmi_read_edid(u8 *buf, int len) | ||
458 | { | ||
459 | int r; | ||
460 | |||
461 | mutex_lock(&hdmi.lock); | ||
462 | |||
463 | r = hdmi_runtime_get(); | ||
464 | BUG_ON(r); | ||
465 | |||
466 | r = hdmi.ip_data.ops->read_edid(&hdmi.ip_data, buf, len); | ||
467 | |||
468 | hdmi_runtime_put(); | ||
469 | mutex_unlock(&hdmi.lock); | ||
470 | |||
471 | return r; | ||
472 | } | ||
473 | |||
474 | bool omapdss_hdmi_detect(void) | ||
475 | { | ||
476 | int r; | ||
477 | |||
478 | mutex_lock(&hdmi.lock); | ||
479 | |||
480 | r = hdmi_runtime_get(); | ||
481 | BUG_ON(r); | ||
482 | |||
483 | r = hdmi.ip_data.ops->detect(&hdmi.ip_data); | ||
484 | |||
485 | hdmi_runtime_put(); | ||
486 | mutex_unlock(&hdmi.lock); | ||
487 | |||
488 | return r == 1; | ||
1224 | } | 489 | } |
1225 | 490 | ||
1226 | int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev) | 491 | int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev) |
@@ -1231,6 +496,12 @@ int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev) | |||
1231 | 496 | ||
1232 | mutex_lock(&hdmi.lock); | 497 | mutex_lock(&hdmi.lock); |
1233 | 498 | ||
499 | if (dssdev->manager == NULL) { | ||
500 | DSSERR("failed to enable display: no manager\n"); | ||
501 | r = -ENODEV; | ||
502 | goto err0; | ||
503 | } | ||
504 | |||
1234 | r = omap_dss_start_device(dssdev); | 505 | r = omap_dss_start_device(dssdev); |
1235 | if (r) { | 506 | if (r) { |
1236 | DSSERR("failed to start device\n"); | 507 | DSSERR("failed to start device\n"); |
@@ -1282,219 +553,9 @@ void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev) | |||
1282 | 553 | ||
1283 | #if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \ | 554 | #if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \ |
1284 | defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE) | 555 | defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE) |
1285 | static void hdmi_wp_audio_config_format( | ||
1286 | struct hdmi_audio_format *aud_fmt) | ||
1287 | { | ||
1288 | u32 r; | ||
1289 | |||
1290 | DSSDBG("Enter hdmi_wp_audio_config_format\n"); | ||
1291 | |||
1292 | r = hdmi_read_reg(HDMI_WP_AUDIO_CFG); | ||
1293 | r = FLD_MOD(r, aud_fmt->stereo_channels, 26, 24); | ||
1294 | r = FLD_MOD(r, aud_fmt->active_chnnls_msk, 23, 16); | ||
1295 | r = FLD_MOD(r, aud_fmt->en_sig_blk_strt_end, 5, 5); | ||
1296 | r = FLD_MOD(r, aud_fmt->type, 4, 4); | ||
1297 | r = FLD_MOD(r, aud_fmt->justification, 3, 3); | ||
1298 | r = FLD_MOD(r, aud_fmt->sample_order, 2, 2); | ||
1299 | r = FLD_MOD(r, aud_fmt->samples_per_word, 1, 1); | ||
1300 | r = FLD_MOD(r, aud_fmt->sample_size, 0, 0); | ||
1301 | hdmi_write_reg(HDMI_WP_AUDIO_CFG, r); | ||
1302 | } | ||
1303 | |||
1304 | static void hdmi_wp_audio_config_dma(struct hdmi_audio_dma *aud_dma) | ||
1305 | { | ||
1306 | u32 r; | ||
1307 | |||
1308 | DSSDBG("Enter hdmi_wp_audio_config_dma\n"); | ||
1309 | |||
1310 | r = hdmi_read_reg(HDMI_WP_AUDIO_CFG2); | ||
1311 | r = FLD_MOD(r, aud_dma->transfer_size, 15, 8); | ||
1312 | r = FLD_MOD(r, aud_dma->block_size, 7, 0); | ||
1313 | hdmi_write_reg(HDMI_WP_AUDIO_CFG2, r); | ||
1314 | |||
1315 | r = hdmi_read_reg(HDMI_WP_AUDIO_CTRL); | ||
1316 | r = FLD_MOD(r, aud_dma->mode, 9, 9); | ||
1317 | r = FLD_MOD(r, aud_dma->fifo_threshold, 8, 0); | ||
1318 | hdmi_write_reg(HDMI_WP_AUDIO_CTRL, r); | ||
1319 | } | ||
1320 | |||
1321 | static void hdmi_core_audio_config(struct hdmi_core_audio_config *cfg) | ||
1322 | { | ||
1323 | u32 r; | ||
1324 | |||
1325 | /* audio clock recovery parameters */ | ||
1326 | r = hdmi_read_reg(HDMI_CORE_AV_ACR_CTRL); | ||
1327 | r = FLD_MOD(r, cfg->use_mclk, 2, 2); | ||
1328 | r = FLD_MOD(r, cfg->en_acr_pkt, 1, 1); | ||
1329 | r = FLD_MOD(r, cfg->cts_mode, 0, 0); | ||
1330 | hdmi_write_reg(HDMI_CORE_AV_ACR_CTRL, r); | ||
1331 | |||
1332 | REG_FLD_MOD(HDMI_CORE_AV_N_SVAL1, cfg->n, 7, 0); | ||
1333 | REG_FLD_MOD(HDMI_CORE_AV_N_SVAL2, cfg->n >> 8, 7, 0); | ||
1334 | REG_FLD_MOD(HDMI_CORE_AV_N_SVAL3, cfg->n >> 16, 7, 0); | ||
1335 | |||
1336 | if (cfg->cts_mode == HDMI_AUDIO_CTS_MODE_SW) { | ||
1337 | REG_FLD_MOD(HDMI_CORE_AV_CTS_SVAL1, cfg->cts, 7, 0); | ||
1338 | REG_FLD_MOD(HDMI_CORE_AV_CTS_SVAL2, cfg->cts >> 8, 7, 0); | ||
1339 | REG_FLD_MOD(HDMI_CORE_AV_CTS_SVAL3, cfg->cts >> 16, 7, 0); | ||
1340 | } else { | ||
1341 | /* | ||
1342 | * HDMI IP uses this configuration to divide the MCLK to | ||
1343 | * update CTS value. | ||
1344 | */ | ||
1345 | REG_FLD_MOD(HDMI_CORE_AV_FREQ_SVAL, cfg->mclk_mode, 2, 0); | ||
1346 | |||
1347 | /* Configure clock for audio packets */ | ||
1348 | REG_FLD_MOD(HDMI_CORE_AV_AUD_PAR_BUSCLK_1, | ||
1349 | cfg->aud_par_busclk, 7, 0); | ||
1350 | REG_FLD_MOD(HDMI_CORE_AV_AUD_PAR_BUSCLK_2, | ||
1351 | (cfg->aud_par_busclk >> 8), 7, 0); | ||
1352 | REG_FLD_MOD(HDMI_CORE_AV_AUD_PAR_BUSCLK_3, | ||
1353 | (cfg->aud_par_busclk >> 16), 7, 0); | ||
1354 | } | ||
1355 | |||
1356 | /* Override of SPDIF sample frequency with value in I2S_CHST4 */ | ||
1357 | REG_FLD_MOD(HDMI_CORE_AV_SPDIF_CTRL, cfg->fs_override, 1, 1); | ||
1358 | |||
1359 | /* I2S parameters */ | ||
1360 | REG_FLD_MOD(HDMI_CORE_AV_I2S_CHST4, cfg->freq_sample, 3, 0); | ||
1361 | |||
1362 | r = hdmi_read_reg(HDMI_CORE_AV_I2S_IN_CTRL); | ||
1363 | r = FLD_MOD(r, cfg->i2s_cfg.en_high_bitrate_aud, 7, 7); | ||
1364 | r = FLD_MOD(r, cfg->i2s_cfg.sck_edge_mode, 6, 6); | ||
1365 | r = FLD_MOD(r, cfg->i2s_cfg.cbit_order, 5, 5); | ||
1366 | r = FLD_MOD(r, cfg->i2s_cfg.vbit, 4, 4); | ||
1367 | r = FLD_MOD(r, cfg->i2s_cfg.ws_polarity, 3, 3); | ||
1368 | r = FLD_MOD(r, cfg->i2s_cfg.justification, 2, 2); | ||
1369 | r = FLD_MOD(r, cfg->i2s_cfg.direction, 1, 1); | ||
1370 | r = FLD_MOD(r, cfg->i2s_cfg.shift, 0, 0); | ||
1371 | hdmi_write_reg(HDMI_CORE_AV_I2S_IN_CTRL, r); | ||
1372 | |||
1373 | r = hdmi_read_reg(HDMI_CORE_AV_I2S_CHST5); | ||
1374 | r = FLD_MOD(r, cfg->freq_sample, 7, 4); | ||
1375 | r = FLD_MOD(r, cfg->i2s_cfg.word_length, 3, 1); | ||
1376 | r = FLD_MOD(r, cfg->i2s_cfg.word_max_length, 0, 0); | ||
1377 | hdmi_write_reg(HDMI_CORE_AV_I2S_CHST5, r); | ||
1378 | |||
1379 | REG_FLD_MOD(HDMI_CORE_AV_I2S_IN_LEN, cfg->i2s_cfg.in_length_bits, 3, 0); | ||
1380 | |||
1381 | /* Audio channels and mode parameters */ | ||
1382 | REG_FLD_MOD(HDMI_CORE_AV_HDMI_CTRL, cfg->layout, 2, 1); | ||
1383 | r = hdmi_read_reg(HDMI_CORE_AV_AUD_MODE); | ||
1384 | r = FLD_MOD(r, cfg->i2s_cfg.active_sds, 7, 4); | ||
1385 | r = FLD_MOD(r, cfg->en_dsd_audio, 3, 3); | ||
1386 | r = FLD_MOD(r, cfg->en_parallel_aud_input, 2, 2); | ||
1387 | r = FLD_MOD(r, cfg->en_spdif, 1, 1); | ||
1388 | hdmi_write_reg(HDMI_CORE_AV_AUD_MODE, r); | ||
1389 | } | ||
1390 | |||
1391 | static void hdmi_core_audio_infoframe_config( | ||
1392 | struct hdmi_core_infoframe_audio *info_aud) | ||
1393 | { | ||
1394 | u8 val; | ||
1395 | u8 sum = 0, checksum = 0; | ||
1396 | |||
1397 | /* | ||
1398 | * Set audio info frame type, version and length as | ||
1399 | * described in HDMI 1.4a Section 8.2.2 specification. | ||
1400 | * Checksum calculation is defined in Section 5.3.5. | ||
1401 | */ | ||
1402 | hdmi_write_reg(HDMI_CORE_AV_AUDIO_TYPE, 0x84); | ||
1403 | hdmi_write_reg(HDMI_CORE_AV_AUDIO_VERS, 0x01); | ||
1404 | hdmi_write_reg(HDMI_CORE_AV_AUDIO_LEN, 0x0a); | ||
1405 | sum += 0x84 + 0x001 + 0x00a; | ||
1406 | |||
1407 | val = (info_aud->db1_coding_type << 4) | ||
1408 | | (info_aud->db1_channel_count - 1); | ||
1409 | hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(0), val); | ||
1410 | sum += val; | ||
1411 | |||
1412 | val = (info_aud->db2_sample_freq << 2) | info_aud->db2_sample_size; | ||
1413 | hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(1), val); | ||
1414 | sum += val; | ||
1415 | |||
1416 | hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(2), 0x00); | ||
1417 | |||
1418 | val = info_aud->db4_channel_alloc; | ||
1419 | hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(3), val); | ||
1420 | sum += val; | ||
1421 | |||
1422 | val = (info_aud->db5_downmix_inh << 7) | (info_aud->db5_lsv << 3); | ||
1423 | hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(4), val); | ||
1424 | sum += val; | ||
1425 | |||
1426 | hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(5), 0x00); | ||
1427 | hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(6), 0x00); | ||
1428 | hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(7), 0x00); | ||
1429 | hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(8), 0x00); | ||
1430 | hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(9), 0x00); | ||
1431 | 556 | ||
1432 | checksum = 0x100 - sum; | 557 | static int hdmi_audio_hw_params(struct hdmi_ip_data *ip_data, |
1433 | hdmi_write_reg(HDMI_CORE_AV_AUDIO_CHSUM, checksum); | 558 | struct snd_pcm_substream *substream, |
1434 | |||
1435 | /* | ||
1436 | * TODO: Add MPEG and SPD enable and repeat cfg when EDID parsing | ||
1437 | * is available. | ||
1438 | */ | ||
1439 | } | ||
1440 | |||
1441 | static int hdmi_config_audio_acr(u32 sample_freq, u32 *n, u32 *cts) | ||
1442 | { | ||
1443 | u32 r; | ||
1444 | u32 deep_color = 0; | ||
1445 | u32 pclk = hdmi.cfg.timings.timings.pixel_clock; | ||
1446 | |||
1447 | if (n == NULL || cts == NULL) | ||
1448 | return -EINVAL; | ||
1449 | /* | ||
1450 | * Obtain current deep color configuration. This needed | ||
1451 | * to calculate the TMDS clock based on the pixel clock. | ||
1452 | */ | ||
1453 | r = REG_GET(HDMI_WP_VIDEO_CFG, 1, 0); | ||
1454 | switch (r) { | ||
1455 | case 1: /* No deep color selected */ | ||
1456 | deep_color = 100; | ||
1457 | break; | ||
1458 | case 2: /* 10-bit deep color selected */ | ||
1459 | deep_color = 125; | ||
1460 | break; | ||
1461 | case 3: /* 12-bit deep color selected */ | ||
1462 | deep_color = 150; | ||
1463 | break; | ||
1464 | default: | ||
1465 | return -EINVAL; | ||
1466 | } | ||
1467 | |||
1468 | switch (sample_freq) { | ||
1469 | case 32000: | ||
1470 | if ((deep_color == 125) && ((pclk == 54054) | ||
1471 | || (pclk == 74250))) | ||
1472 | *n = 8192; | ||
1473 | else | ||
1474 | *n = 4096; | ||
1475 | break; | ||
1476 | case 44100: | ||
1477 | *n = 6272; | ||
1478 | break; | ||
1479 | case 48000: | ||
1480 | if ((deep_color == 125) && ((pclk == 54054) | ||
1481 | || (pclk == 74250))) | ||
1482 | *n = 8192; | ||
1483 | else | ||
1484 | *n = 6144; | ||
1485 | break; | ||
1486 | default: | ||
1487 | *n = 0; | ||
1488 | return -EINVAL; | ||
1489 | } | ||
1490 | |||
1491 | /* Calculate CTS. See HDMI 1.3a or 1.4a specifications */ | ||
1492 | *cts = pclk * (*n / 128) * deep_color / (sample_freq / 10); | ||
1493 | |||
1494 | return 0; | ||
1495 | } | ||
1496 | |||
1497 | static int hdmi_audio_hw_params(struct snd_pcm_substream *substream, | ||
1498 | struct snd_pcm_hw_params *params, | 559 | struct snd_pcm_hw_params *params, |
1499 | struct snd_soc_dai *dai) | 560 | struct snd_soc_dai *dai) |
1500 | { | 561 | { |
@@ -1548,7 +609,7 @@ static int hdmi_audio_hw_params(struct snd_pcm_substream *substream, | |||
1548 | return -EINVAL; | 609 | return -EINVAL; |
1549 | } | 610 | } |
1550 | 611 | ||
1551 | err = hdmi_config_audio_acr(params_rate(params), &n, &cts); | 612 | err = hdmi_config_audio_acr(ip_data, params_rate(params), &n, &cts); |
1552 | if (err < 0) | 613 | if (err < 0) |
1553 | return err; | 614 | return err; |
1554 | 615 | ||
@@ -1564,8 +625,8 @@ static int hdmi_audio_hw_params(struct snd_pcm_substream *substream, | |||
1564 | audio_dma.mode = HDMI_AUDIO_TRANSF_DMA; | 625 | audio_dma.mode = HDMI_AUDIO_TRANSF_DMA; |
1565 | audio_dma.fifo_threshold = 0x20; /* in number of samples */ | 626 | audio_dma.fifo_threshold = 0x20; /* in number of samples */ |
1566 | 627 | ||
1567 | hdmi_wp_audio_config_dma(&audio_dma); | 628 | hdmi_wp_audio_config_dma(ip_data, &audio_dma); |
1568 | hdmi_wp_audio_config_format(&audio_format); | 629 | hdmi_wp_audio_config_format(ip_data, &audio_format); |
1569 | 630 | ||
1570 | /* | 631 | /* |
1571 | * I2S config | 632 | * I2S config |
@@ -1609,7 +670,7 @@ static int hdmi_audio_hw_params(struct snd_pcm_substream *substream, | |||
1609 | /* Use parallel audio interface */ | 670 | /* Use parallel audio interface */ |
1610 | core_cfg.en_parallel_aud_input = true; | 671 | core_cfg.en_parallel_aud_input = true; |
1611 | 672 | ||
1612 | hdmi_core_audio_config(&core_cfg); | 673 | hdmi_core_audio_config(ip_data, &core_cfg); |
1613 | 674 | ||
1614 | /* | 675 | /* |
1615 | * Configure packet | 676 | * Configure packet |
@@ -1623,36 +684,10 @@ static int hdmi_audio_hw_params(struct snd_pcm_substream *substream, | |||
1623 | aud_if_cfg.db5_downmix_inh = false; | 684 | aud_if_cfg.db5_downmix_inh = false; |
1624 | aud_if_cfg.db5_lsv = 0; | 685 | aud_if_cfg.db5_lsv = 0; |
1625 | 686 | ||
1626 | hdmi_core_audio_infoframe_config(&aud_if_cfg); | 687 | hdmi_core_audio_infoframe_config(ip_data, &aud_if_cfg); |
1627 | return 0; | 688 | return 0; |
1628 | } | 689 | } |
1629 | 690 | ||
1630 | static int hdmi_audio_trigger(struct snd_pcm_substream *substream, int cmd, | ||
1631 | struct snd_soc_dai *dai) | ||
1632 | { | ||
1633 | int err = 0; | ||
1634 | switch (cmd) { | ||
1635 | case SNDRV_PCM_TRIGGER_START: | ||
1636 | case SNDRV_PCM_TRIGGER_RESUME: | ||
1637 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
1638 | REG_FLD_MOD(HDMI_CORE_AV_AUD_MODE, 1, 0, 0); | ||
1639 | REG_FLD_MOD(HDMI_WP_AUDIO_CTRL, 1, 31, 31); | ||
1640 | REG_FLD_MOD(HDMI_WP_AUDIO_CTRL, 1, 30, 30); | ||
1641 | break; | ||
1642 | |||
1643 | case SNDRV_PCM_TRIGGER_STOP: | ||
1644 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
1645 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
1646 | REG_FLD_MOD(HDMI_CORE_AV_AUD_MODE, 0, 0, 0); | ||
1647 | REG_FLD_MOD(HDMI_WP_AUDIO_CTRL, 0, 30, 30); | ||
1648 | REG_FLD_MOD(HDMI_WP_AUDIO_CTRL, 0, 31, 31); | ||
1649 | break; | ||
1650 | default: | ||
1651 | err = -EINVAL; | ||
1652 | } | ||
1653 | return err; | ||
1654 | } | ||
1655 | |||
1656 | static int hdmi_audio_startup(struct snd_pcm_substream *substream, | 691 | static int hdmi_audio_startup(struct snd_pcm_substream *substream, |
1657 | struct snd_soc_dai *dai) | 692 | struct snd_soc_dai *dai) |
1658 | { | 693 | { |
@@ -1698,15 +733,6 @@ static int hdmi_get_clocks(struct platform_device *pdev) | |||
1698 | 733 | ||
1699 | hdmi.sys_clk = clk; | 734 | hdmi.sys_clk = clk; |
1700 | 735 | ||
1701 | clk = clk_get(&pdev->dev, "dss_48mhz_clk"); | ||
1702 | if (IS_ERR(clk)) { | ||
1703 | DSSERR("can't get hdmi_clk\n"); | ||
1704 | clk_put(hdmi.sys_clk); | ||
1705 | return PTR_ERR(clk); | ||
1706 | } | ||
1707 | |||
1708 | hdmi.hdmi_clk = clk; | ||
1709 | |||
1710 | return 0; | 736 | return 0; |
1711 | } | 737 | } |
1712 | 738 | ||
@@ -1714,8 +740,6 @@ static void hdmi_put_clocks(void) | |||
1714 | { | 740 | { |
1715 | if (hdmi.sys_clk) | 741 | if (hdmi.sys_clk) |
1716 | clk_put(hdmi.sys_clk); | 742 | clk_put(hdmi.sys_clk); |
1717 | if (hdmi.hdmi_clk) | ||
1718 | clk_put(hdmi.hdmi_clk); | ||
1719 | } | 743 | } |
1720 | 744 | ||
1721 | /* HDMI HW IP initialisation */ | 745 | /* HDMI HW IP initialisation */ |
@@ -1736,20 +760,26 @@ static int omapdss_hdmihw_probe(struct platform_device *pdev) | |||
1736 | } | 760 | } |
1737 | 761 | ||
1738 | /* Base address taken from platform */ | 762 | /* Base address taken from platform */ |
1739 | hdmi.base_wp = ioremap(hdmi_mem->start, resource_size(hdmi_mem)); | 763 | hdmi.ip_data.base_wp = ioremap(hdmi_mem->start, |
1740 | if (!hdmi.base_wp) { | 764 | resource_size(hdmi_mem)); |
765 | if (!hdmi.ip_data.base_wp) { | ||
1741 | DSSERR("can't ioremap WP\n"); | 766 | DSSERR("can't ioremap WP\n"); |
1742 | return -ENOMEM; | 767 | return -ENOMEM; |
1743 | } | 768 | } |
1744 | 769 | ||
1745 | r = hdmi_get_clocks(pdev); | 770 | r = hdmi_get_clocks(pdev); |
1746 | if (r) { | 771 | if (r) { |
1747 | iounmap(hdmi.base_wp); | 772 | iounmap(hdmi.ip_data.base_wp); |
1748 | return r; | 773 | return r; |
1749 | } | 774 | } |
1750 | 775 | ||
1751 | pm_runtime_enable(&pdev->dev); | 776 | pm_runtime_enable(&pdev->dev); |
1752 | 777 | ||
778 | hdmi.ip_data.core_sys_offset = HDMI_CORE_SYS; | ||
779 | hdmi.ip_data.core_av_offset = HDMI_CORE_AV; | ||
780 | hdmi.ip_data.pll_offset = HDMI_PLLCTRL; | ||
781 | hdmi.ip_data.phy_offset = HDMI_PHY; | ||
782 | |||
1753 | hdmi_panel_init(); | 783 | hdmi_panel_init(); |
1754 | 784 | ||
1755 | #if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \ | 785 | #if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \ |
@@ -1779,14 +809,13 @@ static int omapdss_hdmihw_remove(struct platform_device *pdev) | |||
1779 | 809 | ||
1780 | hdmi_put_clocks(); | 810 | hdmi_put_clocks(); |
1781 | 811 | ||
1782 | iounmap(hdmi.base_wp); | 812 | iounmap(hdmi.ip_data.base_wp); |
1783 | 813 | ||
1784 | return 0; | 814 | return 0; |
1785 | } | 815 | } |
1786 | 816 | ||
1787 | static int hdmi_runtime_suspend(struct device *dev) | 817 | static int hdmi_runtime_suspend(struct device *dev) |
1788 | { | 818 | { |
1789 | clk_disable(hdmi.hdmi_clk); | ||
1790 | clk_disable(hdmi.sys_clk); | 819 | clk_disable(hdmi.sys_clk); |
1791 | 820 | ||
1792 | dispc_runtime_put(); | 821 | dispc_runtime_put(); |
@@ -1809,7 +838,6 @@ static int hdmi_runtime_resume(struct device *dev) | |||
1809 | 838 | ||
1810 | 839 | ||
1811 | clk_enable(hdmi.sys_clk); | 840 | clk_enable(hdmi.sys_clk); |
1812 | clk_enable(hdmi.hdmi_clk); | ||
1813 | 841 | ||
1814 | return 0; | 842 | return 0; |
1815 | 843 | ||
diff --git a/drivers/video/omap2/dss/hdmi_omap4_panel.c b/drivers/video/omap2/dss/hdmi_panel.c index 7d4f2bd7c506..533d5dc634d2 100644 --- a/drivers/video/omap2/dss/hdmi_omap4_panel.c +++ b/drivers/video/omap2/dss/hdmi_panel.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * hdmi_omap4_panel.c | 2 | * hdmi_panel.c |
3 | * | 3 | * |
4 | * HDMI library support functions for TI OMAP4 processors. | 4 | * HDMI library support functions for TI OMAP4 processors. |
5 | * | 5 | * |
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/mutex.h> | 25 | #include <linux/mutex.h> |
26 | #include <linux/module.h> | 26 | #include <linux/module.h> |
27 | #include <video/omapdss.h> | 27 | #include <video/omapdss.h> |
28 | #include <linux/slab.h> | ||
28 | 29 | ||
29 | #include "dss.h" | 30 | #include "dss.h" |
30 | 31 | ||
@@ -40,13 +41,7 @@ static int hdmi_panel_probe(struct omap_dss_device *dssdev) | |||
40 | dssdev->panel.config = OMAP_DSS_LCD_TFT | | 41 | dssdev->panel.config = OMAP_DSS_LCD_TFT | |
41 | OMAP_DSS_LCD_IVS | OMAP_DSS_LCD_IHS; | 42 | OMAP_DSS_LCD_IVS | OMAP_DSS_LCD_IHS; |
42 | 43 | ||
43 | /* | 44 | dssdev->panel.timings = (struct omap_video_timings){640, 480, 25175, 96, 16, 48, 2 , 11, 31}; |
44 | * Initialize the timings to 640 * 480 | ||
45 | * This is only for framebuffer update not for TV timing setting | ||
46 | * Setting TV timing will be done only on enable | ||
47 | */ | ||
48 | dssdev->panel.timings.x_res = 640; | ||
49 | dssdev->panel.timings.y_res = 480; | ||
50 | 45 | ||
51 | DSSDBG("hdmi_panel_probe x_res= %d y_res = %d\n", | 46 | DSSDBG("hdmi_panel_probe x_res= %d y_res = %d\n", |
52 | dssdev->panel.timings.x_res, | 47 | dssdev->panel.timings.x_res, |
@@ -161,12 +156,7 @@ static void hdmi_set_timings(struct omap_dss_device *dssdev, | |||
161 | mutex_lock(&hdmi.hdmi_lock); | 156 | mutex_lock(&hdmi.hdmi_lock); |
162 | 157 | ||
163 | dssdev->panel.timings = *timings; | 158 | dssdev->panel.timings = *timings; |
164 | 159 | omapdss_hdmi_display_set_timing(dssdev); | |
165 | if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) { | ||
166 | /* turn the hdmi off and on to get new timings to use */ | ||
167 | omapdss_hdmi_display_disable(dssdev); | ||
168 | omapdss_hdmi_display_set_timing(dssdev); | ||
169 | } | ||
170 | 160 | ||
171 | mutex_unlock(&hdmi.hdmi_lock); | 161 | mutex_unlock(&hdmi.hdmi_lock); |
172 | } | 162 | } |
@@ -181,12 +171,54 @@ static int hdmi_check_timings(struct omap_dss_device *dssdev, | |||
181 | mutex_lock(&hdmi.hdmi_lock); | 171 | mutex_lock(&hdmi.hdmi_lock); |
182 | 172 | ||
183 | r = omapdss_hdmi_display_check_timing(dssdev, timings); | 173 | r = omapdss_hdmi_display_check_timing(dssdev, timings); |
184 | if (r) { | 174 | |
185 | DSSERR("Timing cannot be applied\n"); | 175 | mutex_unlock(&hdmi.hdmi_lock); |
186 | goto err; | 176 | return r; |
177 | } | ||
178 | |||
179 | static int hdmi_read_edid(struct omap_dss_device *dssdev, u8 *buf, int len) | ||
180 | { | ||
181 | int r; | ||
182 | |||
183 | mutex_lock(&hdmi.hdmi_lock); | ||
184 | |||
185 | if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) { | ||
186 | r = omapdss_hdmi_display_enable(dssdev); | ||
187 | if (r) | ||
188 | goto err; | ||
189 | } | ||
190 | |||
191 | r = omapdss_hdmi_read_edid(buf, len); | ||
192 | |||
193 | if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED || | ||
194 | dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED) | ||
195 | omapdss_hdmi_display_disable(dssdev); | ||
196 | err: | ||
197 | mutex_unlock(&hdmi.hdmi_lock); | ||
198 | |||
199 | return r; | ||
200 | } | ||
201 | |||
202 | static bool hdmi_detect(struct omap_dss_device *dssdev) | ||
203 | { | ||
204 | int r; | ||
205 | |||
206 | mutex_lock(&hdmi.hdmi_lock); | ||
207 | |||
208 | if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) { | ||
209 | r = omapdss_hdmi_display_enable(dssdev); | ||
210 | if (r) | ||
211 | goto err; | ||
187 | } | 212 | } |
213 | |||
214 | r = omapdss_hdmi_detect(); | ||
215 | |||
216 | if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED || | ||
217 | dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED) | ||
218 | omapdss_hdmi_display_disable(dssdev); | ||
188 | err: | 219 | err: |
189 | mutex_unlock(&hdmi.hdmi_lock); | 220 | mutex_unlock(&hdmi.hdmi_lock); |
221 | |||
190 | return r; | 222 | return r; |
191 | } | 223 | } |
192 | 224 | ||
@@ -200,6 +232,8 @@ static struct omap_dss_driver hdmi_driver = { | |||
200 | .get_timings = hdmi_get_timings, | 232 | .get_timings = hdmi_get_timings, |
201 | .set_timings = hdmi_set_timings, | 233 | .set_timings = hdmi_set_timings, |
202 | .check_timings = hdmi_check_timings, | 234 | .check_timings = hdmi_check_timings, |
235 | .read_edid = hdmi_read_edid, | ||
236 | .detect = hdmi_detect, | ||
203 | .driver = { | 237 | .driver = { |
204 | .name = "hdmi_panel", | 238 | .name = "hdmi_panel", |
205 | .owner = THIS_MODULE, | 239 | .owner = THIS_MODULE, |
diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c index 13d72d5c714b..6e63845cc7d7 100644 --- a/drivers/video/omap2/dss/manager.c +++ b/drivers/video/omap2/dss/manager.c | |||
@@ -106,7 +106,7 @@ put_device: | |||
106 | static ssize_t manager_default_color_show(struct omap_overlay_manager *mgr, | 106 | static ssize_t manager_default_color_show(struct omap_overlay_manager *mgr, |
107 | char *buf) | 107 | char *buf) |
108 | { | 108 | { |
109 | return snprintf(buf, PAGE_SIZE, "%d\n", mgr->info.default_color); | 109 | return snprintf(buf, PAGE_SIZE, "%#x\n", mgr->info.default_color); |
110 | } | 110 | } |
111 | 111 | ||
112 | static ssize_t manager_default_color_store(struct omap_overlay_manager *mgr, | 112 | static ssize_t manager_default_color_store(struct omap_overlay_manager *mgr, |
@@ -116,8 +116,9 @@ static ssize_t manager_default_color_store(struct omap_overlay_manager *mgr, | |||
116 | u32 color; | 116 | u32 color; |
117 | int r; | 117 | int r; |
118 | 118 | ||
119 | if (sscanf(buf, "%d", &color) != 1) | 119 | r = kstrtouint(buf, 0, &color); |
120 | return -EINVAL; | 120 | if (r) |
121 | return r; | ||
121 | 122 | ||
122 | mgr->get_manager_info(mgr, &info); | 123 | mgr->get_manager_info(mgr, &info); |
123 | 124 | ||
@@ -184,7 +185,7 @@ static ssize_t manager_trans_key_type_store(struct omap_overlay_manager *mgr, | |||
184 | static ssize_t manager_trans_key_value_show(struct omap_overlay_manager *mgr, | 185 | static ssize_t manager_trans_key_value_show(struct omap_overlay_manager *mgr, |
185 | char *buf) | 186 | char *buf) |
186 | { | 187 | { |
187 | return snprintf(buf, PAGE_SIZE, "%d\n", mgr->info.trans_key); | 188 | return snprintf(buf, PAGE_SIZE, "%#x\n", mgr->info.trans_key); |
188 | } | 189 | } |
189 | 190 | ||
190 | static ssize_t manager_trans_key_value_store(struct omap_overlay_manager *mgr, | 191 | static ssize_t manager_trans_key_value_store(struct omap_overlay_manager *mgr, |
@@ -194,8 +195,9 @@ static ssize_t manager_trans_key_value_store(struct omap_overlay_manager *mgr, | |||
194 | u32 key_value; | 195 | u32 key_value; |
195 | int r; | 196 | int r; |
196 | 197 | ||
197 | if (sscanf(buf, "%d", &key_value) != 1) | 198 | r = kstrtouint(buf, 0, &key_value); |
198 | return -EINVAL; | 199 | if (r) |
200 | return r; | ||
199 | 201 | ||
200 | mgr->get_manager_info(mgr, &info); | 202 | mgr->get_manager_info(mgr, &info); |
201 | 203 | ||
@@ -222,15 +224,16 @@ static ssize_t manager_trans_key_enabled_store(struct omap_overlay_manager *mgr, | |||
222 | const char *buf, size_t size) | 224 | const char *buf, size_t size) |
223 | { | 225 | { |
224 | struct omap_overlay_manager_info info; | 226 | struct omap_overlay_manager_info info; |
225 | int enable; | 227 | bool enable; |
226 | int r; | 228 | int r; |
227 | 229 | ||
228 | if (sscanf(buf, "%d", &enable) != 1) | 230 | r = strtobool(buf, &enable); |
229 | return -EINVAL; | 231 | if (r) |
232 | return r; | ||
230 | 233 | ||
231 | mgr->get_manager_info(mgr, &info); | 234 | mgr->get_manager_info(mgr, &info); |
232 | 235 | ||
233 | info.trans_enabled = enable ? true : false; | 236 | info.trans_enabled = enable; |
234 | 237 | ||
235 | r = mgr->set_manager_info(mgr, &info); | 238 | r = mgr->set_manager_info(mgr, &info); |
236 | if (r) | 239 | if (r) |
@@ -246,7 +249,10 @@ static ssize_t manager_trans_key_enabled_store(struct omap_overlay_manager *mgr, | |||
246 | static ssize_t manager_alpha_blending_enabled_show( | 249 | static ssize_t manager_alpha_blending_enabled_show( |
247 | struct omap_overlay_manager *mgr, char *buf) | 250 | struct omap_overlay_manager *mgr, char *buf) |
248 | { | 251 | { |
249 | return snprintf(buf, PAGE_SIZE, "%d\n", mgr->info.alpha_enabled); | 252 | WARN_ON(!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER)); |
253 | |||
254 | return snprintf(buf, PAGE_SIZE, "%d\n", | ||
255 | mgr->info.partial_alpha_enabled); | ||
250 | } | 256 | } |
251 | 257 | ||
252 | static ssize_t manager_alpha_blending_enabled_store( | 258 | static ssize_t manager_alpha_blending_enabled_store( |
@@ -254,15 +260,18 @@ static ssize_t manager_alpha_blending_enabled_store( | |||
254 | const char *buf, size_t size) | 260 | const char *buf, size_t size) |
255 | { | 261 | { |
256 | struct omap_overlay_manager_info info; | 262 | struct omap_overlay_manager_info info; |
257 | int enable; | 263 | bool enable; |
258 | int r; | 264 | int r; |
259 | 265 | ||
260 | if (sscanf(buf, "%d", &enable) != 1) | 266 | WARN_ON(!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER)); |
261 | return -EINVAL; | 267 | |
268 | r = strtobool(buf, &enable); | ||
269 | if (r) | ||
270 | return r; | ||
262 | 271 | ||
263 | mgr->get_manager_info(mgr, &info); | 272 | mgr->get_manager_info(mgr, &info); |
264 | 273 | ||
265 | info.alpha_enabled = enable ? true : false; | 274 | info.partial_alpha_enabled = enable; |
266 | 275 | ||
267 | r = mgr->set_manager_info(mgr, &info); | 276 | r = mgr->set_manager_info(mgr, &info); |
268 | if (r) | 277 | if (r) |
@@ -285,19 +294,16 @@ static ssize_t manager_cpr_enable_store(struct omap_overlay_manager *mgr, | |||
285 | const char *buf, size_t size) | 294 | const char *buf, size_t size) |
286 | { | 295 | { |
287 | struct omap_overlay_manager_info info; | 296 | struct omap_overlay_manager_info info; |
288 | int v; | ||
289 | int r; | 297 | int r; |
290 | bool enable; | 298 | bool enable; |
291 | 299 | ||
292 | if (!dss_has_feature(FEAT_CPR)) | 300 | if (!dss_has_feature(FEAT_CPR)) |
293 | return -ENODEV; | 301 | return -ENODEV; |
294 | 302 | ||
295 | r = kstrtoint(buf, 0, &v); | 303 | r = strtobool(buf, &enable); |
296 | if (r) | 304 | if (r) |
297 | return r; | 305 | return r; |
298 | 306 | ||
299 | enable = !!v; | ||
300 | |||
301 | mgr->get_manager_info(mgr, &info); | 307 | mgr->get_manager_info(mgr, &info); |
302 | 308 | ||
303 | if (info.cpr_enable == enable) | 309 | if (info.cpr_enable == enable) |
@@ -586,6 +592,13 @@ static int omap_dss_unset_device(struct omap_overlay_manager *mgr) | |||
586 | return -EINVAL; | 592 | return -EINVAL; |
587 | } | 593 | } |
588 | 594 | ||
595 | /* | ||
596 | * Don't allow currently enabled displays to have the overlay manager | ||
597 | * pulled out from underneath them | ||
598 | */ | ||
599 | if (mgr->device->state != OMAP_DSS_DISPLAY_DISABLED) | ||
600 | return -EINVAL; | ||
601 | |||
589 | mgr->device->manager = NULL; | 602 | mgr->device->manager = NULL; |
590 | mgr->device = NULL; | 603 | mgr->device = NULL; |
591 | mgr->device_changed = true; | 604 | mgr->device_changed = true; |
@@ -801,7 +814,7 @@ static int configure_overlay(enum omap_plane plane) | |||
801 | { | 814 | { |
802 | struct overlay_cache_data *c; | 815 | struct overlay_cache_data *c; |
803 | struct manager_cache_data *mc; | 816 | struct manager_cache_data *mc; |
804 | struct omap_overlay_info *oi; | 817 | struct omap_overlay_info *oi, new_oi; |
805 | struct omap_overlay_manager_info *mi; | 818 | struct omap_overlay_manager_info *mi; |
806 | u16 outw, outh; | 819 | u16 outw, outh; |
807 | u16 x, y, w, h; | 820 | u16 x, y, w, h; |
@@ -815,7 +828,7 @@ static int configure_overlay(enum omap_plane plane) | |||
815 | oi = &c->info; | 828 | oi = &c->info; |
816 | 829 | ||
817 | if (!c->enabled) { | 830 | if (!c->enabled) { |
818 | dispc_enable_plane(plane, 0); | 831 | dispc_ovl_enable(plane, 0); |
819 | return 0; | 832 | return 0; |
820 | } | 833 | } |
821 | 834 | ||
@@ -843,7 +856,7 @@ static int configure_overlay(enum omap_plane plane) | |||
843 | /* If the overlay is outside the update region, disable it */ | 856 | /* If the overlay is outside the update region, disable it */ |
844 | if (!rectangle_intersects(mc->x, mc->y, mc->w, mc->h, | 857 | if (!rectangle_intersects(mc->x, mc->y, mc->w, mc->h, |
845 | x, y, outw, outh)) { | 858 | x, y, outw, outh)) { |
846 | dispc_enable_plane(plane, 0); | 859 | dispc_ovl_enable(plane, 0); |
847 | return 0; | 860 | return 0; |
848 | } | 861 | } |
849 | 862 | ||
@@ -921,34 +934,27 @@ static int configure_overlay(enum omap_plane plane) | |||
921 | } | 934 | } |
922 | } | 935 | } |
923 | 936 | ||
924 | r = dispc_setup_plane(plane, | 937 | new_oi = *oi; |
925 | paddr, | 938 | |
926 | oi->screen_width, | 939 | /* update new_oi members which could have been possibly updated */ |
927 | x, y, | 940 | new_oi.pos_x = x; |
928 | w, h, | 941 | new_oi.pos_y = y; |
929 | outw, outh, | 942 | new_oi.width = w; |
930 | oi->color_mode, | 943 | new_oi.height = h; |
931 | c->ilace, | 944 | new_oi.out_width = outw; |
932 | oi->rotation_type, | 945 | new_oi.out_height = outh; |
933 | oi->rotation, | 946 | new_oi.paddr = paddr; |
934 | oi->mirror, | ||
935 | oi->global_alpha, | ||
936 | oi->pre_mult_alpha, | ||
937 | c->channel, | ||
938 | oi->p_uv_addr); | ||
939 | 947 | ||
948 | r = dispc_ovl_setup(plane, &new_oi, c->ilace, c->channel, | ||
949 | c->replication, c->fifo_low, c->fifo_high); | ||
940 | if (r) { | 950 | if (r) { |
941 | /* this shouldn't happen */ | 951 | /* this shouldn't happen */ |
942 | DSSERR("dispc_setup_plane failed for ovl %d\n", plane); | 952 | DSSERR("dispc_ovl_setup failed for ovl %d\n", plane); |
943 | dispc_enable_plane(plane, 0); | 953 | dispc_ovl_enable(plane, 0); |
944 | return r; | 954 | return r; |
945 | } | 955 | } |
946 | 956 | ||
947 | dispc_enable_replication(plane, c->replication); | 957 | dispc_ovl_enable(plane, 1); |
948 | |||
949 | dispc_set_fifo_threshold(plane, c->fifo_low, c->fifo_high); | ||
950 | |||
951 | dispc_enable_plane(plane, 1); | ||
952 | 958 | ||
953 | return 0; | 959 | return 0; |
954 | } | 960 | } |
@@ -962,13 +968,13 @@ static void configure_manager(enum omap_channel channel) | |||
962 | /* picking info from the cache */ | 968 | /* picking info from the cache */ |
963 | mi = &dss_cache.manager_cache[channel].info; | 969 | mi = &dss_cache.manager_cache[channel].info; |
964 | 970 | ||
965 | dispc_set_default_color(channel, mi->default_color); | 971 | dispc_mgr_set_default_color(channel, mi->default_color); |
966 | dispc_set_trans_key(channel, mi->trans_key_type, mi->trans_key); | 972 | dispc_mgr_set_trans_key(channel, mi->trans_key_type, mi->trans_key); |
967 | dispc_enable_trans_key(channel, mi->trans_enabled); | 973 | dispc_mgr_enable_trans_key(channel, mi->trans_enabled); |
968 | dispc_enable_alpha_blending(channel, mi->alpha_enabled); | 974 | dispc_mgr_enable_alpha_fixed_zorder(channel, mi->partial_alpha_enabled); |
969 | if (dss_has_feature(FEAT_CPR)) { | 975 | if (dss_has_feature(FEAT_CPR)) { |
970 | dispc_enable_cpr(channel, mi->cpr_enable); | 976 | dispc_mgr_enable_cpr(channel, mi->cpr_enable); |
971 | dispc_set_cpr_coef(channel, &mi->cpr_coefs); | 977 | dispc_mgr_set_cpr_coef(channel, &mi->cpr_coefs); |
972 | } | 978 | } |
973 | } | 979 | } |
974 | 980 | ||
@@ -992,7 +998,7 @@ static int configure_dispc(void) | |||
992 | busy = false; | 998 | busy = false; |
993 | 999 | ||
994 | for (i = 0; i < num_mgrs; i++) { | 1000 | for (i = 0; i < num_mgrs; i++) { |
995 | mgr_busy[i] = dispc_go_busy(i); | 1001 | mgr_busy[i] = dispc_mgr_go_busy(i); |
996 | mgr_go[i] = false; | 1002 | mgr_go[i] = false; |
997 | } | 1003 | } |
998 | 1004 | ||
@@ -1053,7 +1059,7 @@ static int configure_dispc(void) | |||
1053 | * always be turned off after frame, and new settings will be | 1059 | * always be turned off after frame, and new settings will be |
1054 | * taken in to use at next update */ | 1060 | * taken in to use at next update */ |
1055 | if (!mc->manual_update) | 1061 | if (!mc->manual_update) |
1056 | dispc_go(i); | 1062 | dispc_mgr_go(i); |
1057 | } | 1063 | } |
1058 | 1064 | ||
1059 | if (busy) | 1065 | if (busy) |
@@ -1258,7 +1264,7 @@ static void dss_apply_irq_handler(void *data, u32 mask) | |||
1258 | u32 irq_mask; | 1264 | u32 irq_mask; |
1259 | 1265 | ||
1260 | for (i = 0; i < num_mgrs; i++) | 1266 | for (i = 0; i < num_mgrs; i++) |
1261 | mgr_busy[i] = dispc_go_busy(i); | 1267 | mgr_busy[i] = dispc_mgr_go_busy(i); |
1262 | 1268 | ||
1263 | spin_lock(&dss_cache.lock); | 1269 | spin_lock(&dss_cache.lock); |
1264 | 1270 | ||
@@ -1280,7 +1286,7 @@ static void dss_apply_irq_handler(void *data, u32 mask) | |||
1280 | 1286 | ||
1281 | /* re-read busy flags */ | 1287 | /* re-read busy flags */ |
1282 | for (i = 0; i < num_mgrs; i++) | 1288 | for (i = 0; i < num_mgrs; i++) |
1283 | mgr_busy[i] = dispc_go_busy(i); | 1289 | mgr_busy[i] = dispc_mgr_go_busy(i); |
1284 | 1290 | ||
1285 | /* keep running as long as there are busy managers, so that | 1291 | /* keep running as long as there are busy managers, so that |
1286 | * we can collect overlay-applied information */ | 1292 | * we can collect overlay-applied information */ |
@@ -1326,11 +1332,13 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr) | |||
1326 | 1332 | ||
1327 | ovl = omap_dss_get_overlay(i); | 1333 | ovl = omap_dss_get_overlay(i); |
1328 | 1334 | ||
1329 | if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC)) | ||
1330 | continue; | ||
1331 | |||
1332 | oc = &dss_cache.overlay_cache[ovl->id]; | 1335 | oc = &dss_cache.overlay_cache[ovl->id]; |
1333 | 1336 | ||
1337 | if (ovl->manager_changed) { | ||
1338 | ovl->manager_changed = false; | ||
1339 | ovl->info_dirty = true; | ||
1340 | } | ||
1341 | |||
1334 | if (!overlay_enabled(ovl)) { | 1342 | if (!overlay_enabled(ovl)) { |
1335 | if (oc->enabled) { | 1343 | if (oc->enabled) { |
1336 | oc->enabled = false; | 1344 | oc->enabled = false; |
@@ -1375,9 +1383,6 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr) | |||
1375 | list_for_each_entry(mgr, &manager_list, list) { | 1383 | list_for_each_entry(mgr, &manager_list, list) { |
1376 | struct omap_dss_device *dssdev; | 1384 | struct omap_dss_device *dssdev; |
1377 | 1385 | ||
1378 | if (!(mgr->caps & OMAP_DSS_OVL_MGR_CAP_DISPC)) | ||
1379 | continue; | ||
1380 | |||
1381 | mc = &dss_cache.manager_cache[mgr->id]; | 1386 | mc = &dss_cache.manager_cache[mgr->id]; |
1382 | 1387 | ||
1383 | if (mgr->device_changed) { | 1388 | if (mgr->device_changed) { |
@@ -1423,9 +1428,6 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr) | |||
1423 | 1428 | ||
1424 | ovl = omap_dss_get_overlay(i); | 1429 | ovl = omap_dss_get_overlay(i); |
1425 | 1430 | ||
1426 | if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC)) | ||
1427 | continue; | ||
1428 | |||
1429 | oc = &dss_cache.overlay_cache[ovl->id]; | 1431 | oc = &dss_cache.overlay_cache[ovl->id]; |
1430 | 1432 | ||
1431 | if (!oc->enabled) | 1433 | if (!oc->enabled) |
@@ -1433,11 +1435,11 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr) | |||
1433 | 1435 | ||
1434 | dssdev = ovl->manager->device; | 1436 | dssdev = ovl->manager->device; |
1435 | 1437 | ||
1436 | size = dispc_get_plane_fifo_size(ovl->id); | 1438 | size = dispc_ovl_get_fifo_size(ovl->id); |
1437 | if (use_fifomerge) | 1439 | if (use_fifomerge) |
1438 | size *= 3; | 1440 | size *= 3; |
1439 | 1441 | ||
1440 | burst_size = dispc_get_burst_size(ovl->id); | 1442 | burst_size = dispc_ovl_get_burst_size(ovl->id); |
1441 | 1443 | ||
1442 | switch (dssdev->type) { | 1444 | switch (dssdev->type) { |
1443 | case OMAP_DISPLAY_TYPE_DPI: | 1445 | case OMAP_DISPLAY_TYPE_DPI: |
@@ -1484,12 +1486,17 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr) | |||
1484 | 1486 | ||
1485 | static int dss_check_manager(struct omap_overlay_manager *mgr) | 1487 | static int dss_check_manager(struct omap_overlay_manager *mgr) |
1486 | { | 1488 | { |
1487 | /* OMAP supports only graphics source transparency color key and alpha | 1489 | if (dss_has_feature(FEAT_ALPHA_FIXED_ZORDER)) { |
1488 | * blending simultaneously. See TRM 15.4.2.4.2.2 Alpha Mode */ | 1490 | /* |
1489 | 1491 | * OMAP3 supports only graphics source transparency color key | |
1490 | if (mgr->info.alpha_enabled && mgr->info.trans_enabled && | 1492 | * and alpha blending simultaneously. See TRM 15.4.2.4.2.2 |
1491 | mgr->info.trans_key_type != OMAP_DSS_COLOR_KEY_GFX_DST) | 1493 | * Alpha Mode |
1492 | return -EINVAL; | 1494 | */ |
1495 | if (mgr->info.partial_alpha_enabled && mgr->info.trans_enabled | ||
1496 | && mgr->info.trans_key_type != | ||
1497 | OMAP_DSS_COLOR_KEY_GFX_DST) | ||
1498 | return -EINVAL; | ||
1499 | } | ||
1493 | 1500 | ||
1494 | return 0; | 1501 | return 0; |
1495 | } | 1502 | } |
@@ -1522,13 +1529,13 @@ static void omap_dss_mgr_get_info(struct omap_overlay_manager *mgr, | |||
1522 | 1529 | ||
1523 | static int dss_mgr_enable(struct omap_overlay_manager *mgr) | 1530 | static int dss_mgr_enable(struct omap_overlay_manager *mgr) |
1524 | { | 1531 | { |
1525 | dispc_enable_channel(mgr->id, 1); | 1532 | dispc_mgr_enable(mgr->id, 1); |
1526 | return 0; | 1533 | return 0; |
1527 | } | 1534 | } |
1528 | 1535 | ||
1529 | static int dss_mgr_disable(struct omap_overlay_manager *mgr) | 1536 | static int dss_mgr_disable(struct omap_overlay_manager *mgr) |
1530 | { | 1537 | { |
1531 | dispc_enable_channel(mgr->id, 0); | 1538 | dispc_mgr_enable(mgr->id, 0); |
1532 | return 0; | 1539 | return 0; |
1533 | } | 1540 | } |
1534 | 1541 | ||
@@ -1580,7 +1587,7 @@ int dss_init_overlay_managers(struct platform_device *pdev) | |||
1580 | mgr->enable = &dss_mgr_enable; | 1587 | mgr->enable = &dss_mgr_enable; |
1581 | mgr->disable = &dss_mgr_disable; | 1588 | mgr->disable = &dss_mgr_disable; |
1582 | 1589 | ||
1583 | mgr->caps = OMAP_DSS_OVL_MGR_CAP_DISPC; | 1590 | mgr->caps = 0; |
1584 | mgr->supported_displays = | 1591 | mgr->supported_displays = |
1585 | dss_feat_get_supported_displays(mgr->id); | 1592 | dss_feat_get_supported_displays(mgr->id); |
1586 | 1593 | ||
@@ -1597,42 +1604,6 @@ int dss_init_overlay_managers(struct platform_device *pdev) | |||
1597 | } | 1604 | } |
1598 | } | 1605 | } |
1599 | 1606 | ||
1600 | #ifdef L4_EXAMPLE | ||
1601 | { | ||
1602 | int omap_dss_mgr_apply_l4(struct omap_overlay_manager *mgr) | ||
1603 | { | ||
1604 | DSSDBG("omap_dss_mgr_apply_l4(%s)\n", mgr->name); | ||
1605 | |||
1606 | return 0; | ||
1607 | } | ||
1608 | |||
1609 | struct omap_overlay_manager *mgr; | ||
1610 | mgr = kzalloc(sizeof(*mgr), GFP_KERNEL); | ||
1611 | |||
1612 | BUG_ON(mgr == NULL); | ||
1613 | |||
1614 | mgr->name = "l4"; | ||
1615 | mgr->supported_displays = | ||
1616 | OMAP_DISPLAY_TYPE_DBI | OMAP_DISPLAY_TYPE_DSI; | ||
1617 | |||
1618 | mgr->set_device = &omap_dss_set_device; | ||
1619 | mgr->unset_device = &omap_dss_unset_device; | ||
1620 | mgr->apply = &omap_dss_mgr_apply_l4; | ||
1621 | mgr->set_manager_info = &omap_dss_mgr_set_info; | ||
1622 | mgr->get_manager_info = &omap_dss_mgr_get_info; | ||
1623 | |||
1624 | dss_overlay_setup_l4_manager(mgr); | ||
1625 | |||
1626 | omap_dss_add_overlay_manager(mgr); | ||
1627 | |||
1628 | r = kobject_init_and_add(&mgr->kobj, &manager_ktype, | ||
1629 | &pdev->dev.kobj, "managerl4"); | ||
1630 | |||
1631 | if (r) | ||
1632 | DSSERR("failed to create sysfs file\n"); | ||
1633 | } | ||
1634 | #endif | ||
1635 | |||
1636 | return 0; | 1607 | return 0; |
1637 | } | 1608 | } |
1638 | 1609 | ||
diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c index c84380c53c39..ab8e40e48759 100644 --- a/drivers/video/omap2/dss/overlay.c +++ b/drivers/video/omap2/dss/overlay.c | |||
@@ -211,16 +211,17 @@ static ssize_t overlay_enabled_show(struct omap_overlay *ovl, char *buf) | |||
211 | static ssize_t overlay_enabled_store(struct omap_overlay *ovl, const char *buf, | 211 | static ssize_t overlay_enabled_store(struct omap_overlay *ovl, const char *buf, |
212 | size_t size) | 212 | size_t size) |
213 | { | 213 | { |
214 | int r, enable; | 214 | int r; |
215 | bool enable; | ||
215 | struct omap_overlay_info info; | 216 | struct omap_overlay_info info; |
216 | 217 | ||
217 | ovl->get_overlay_info(ovl, &info); | 218 | ovl->get_overlay_info(ovl, &info); |
218 | 219 | ||
219 | r = kstrtoint(buf, 0, &enable); | 220 | r = strtobool(buf, &enable); |
220 | if (r) | 221 | if (r) |
221 | return r; | 222 | return r; |
222 | 223 | ||
223 | info.enabled = !!enable; | 224 | info.enabled = enable; |
224 | 225 | ||
225 | r = ovl->set_overlay_info(ovl, &info); | 226 | r = ovl->set_overlay_info(ovl, &info); |
226 | if (r) | 227 | if (r) |
@@ -248,7 +249,7 @@ static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl, | |||
248 | u8 alpha; | 249 | u8 alpha; |
249 | struct omap_overlay_info info; | 250 | struct omap_overlay_info info; |
250 | 251 | ||
251 | if (!dss_has_feature(FEAT_GLOBAL_ALPHA)) | 252 | if ((ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) == 0) |
252 | return -ENODEV; | 253 | return -ENODEV; |
253 | 254 | ||
254 | r = kstrtou8(buf, 0, &alpha); | 255 | r = kstrtou8(buf, 0, &alpha); |
@@ -257,14 +258,7 @@ static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl, | |||
257 | 258 | ||
258 | ovl->get_overlay_info(ovl, &info); | 259 | ovl->get_overlay_info(ovl, &info); |
259 | 260 | ||
260 | /* Video1 plane does not support global alpha | 261 | info.global_alpha = alpha; |
261 | * to always make it 255 completely opaque | ||
262 | */ | ||
263 | if (!dss_has_feature(FEAT_GLOBAL_ALPHA_VID1) && | ||
264 | ovl->id == OMAP_DSS_VIDEO1) | ||
265 | info.global_alpha = 255; | ||
266 | else | ||
267 | info.global_alpha = alpha; | ||
268 | 262 | ||
269 | r = ovl->set_overlay_info(ovl, &info); | 263 | r = ovl->set_overlay_info(ovl, &info); |
270 | if (r) | 264 | if (r) |
@@ -293,20 +287,52 @@ static ssize_t overlay_pre_mult_alpha_store(struct omap_overlay *ovl, | |||
293 | u8 alpha; | 287 | u8 alpha; |
294 | struct omap_overlay_info info; | 288 | struct omap_overlay_info info; |
295 | 289 | ||
290 | if ((ovl->caps & OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA) == 0) | ||
291 | return -ENODEV; | ||
292 | |||
296 | r = kstrtou8(buf, 0, &alpha); | 293 | r = kstrtou8(buf, 0, &alpha); |
297 | if (r) | 294 | if (r) |
298 | return r; | 295 | return r; |
299 | 296 | ||
300 | ovl->get_overlay_info(ovl, &info); | 297 | ovl->get_overlay_info(ovl, &info); |
301 | 298 | ||
302 | /* only GFX and Video2 plane support pre alpha multiplied | 299 | info.pre_mult_alpha = alpha; |
303 | * set zero for Video1 plane | 300 | |
304 | */ | 301 | r = ovl->set_overlay_info(ovl, &info); |
305 | if (!dss_has_feature(FEAT_GLOBAL_ALPHA_VID1) && | 302 | if (r) |
306 | ovl->id == OMAP_DSS_VIDEO1) | 303 | return r; |
307 | info.pre_mult_alpha = 0; | 304 | |
308 | else | 305 | if (ovl->manager) { |
309 | info.pre_mult_alpha = alpha; | 306 | r = ovl->manager->apply(ovl->manager); |
307 | if (r) | ||
308 | return r; | ||
309 | } | ||
310 | |||
311 | return size; | ||
312 | } | ||
313 | |||
314 | static ssize_t overlay_zorder_show(struct omap_overlay *ovl, char *buf) | ||
315 | { | ||
316 | return snprintf(buf, PAGE_SIZE, "%d\n", ovl->info.zorder); | ||
317 | } | ||
318 | |||
319 | static ssize_t overlay_zorder_store(struct omap_overlay *ovl, | ||
320 | const char *buf, size_t size) | ||
321 | { | ||
322 | int r; | ||
323 | u8 zorder; | ||
324 | struct omap_overlay_info info; | ||
325 | |||
326 | if ((ovl->caps & OMAP_DSS_OVL_CAP_ZORDER) == 0) | ||
327 | return -ENODEV; | ||
328 | |||
329 | r = kstrtou8(buf, 0, &zorder); | ||
330 | if (r) | ||
331 | return r; | ||
332 | |||
333 | ovl->get_overlay_info(ovl, &info); | ||
334 | |||
335 | info.zorder = zorder; | ||
310 | 336 | ||
311 | r = ovl->set_overlay_info(ovl, &info); | 337 | r = ovl->set_overlay_info(ovl, &info); |
312 | if (r) | 338 | if (r) |
@@ -347,6 +373,8 @@ static OVERLAY_ATTR(global_alpha, S_IRUGO|S_IWUSR, | |||
347 | static OVERLAY_ATTR(pre_mult_alpha, S_IRUGO|S_IWUSR, | 373 | static OVERLAY_ATTR(pre_mult_alpha, S_IRUGO|S_IWUSR, |
348 | overlay_pre_mult_alpha_show, | 374 | overlay_pre_mult_alpha_show, |
349 | overlay_pre_mult_alpha_store); | 375 | overlay_pre_mult_alpha_store); |
376 | static OVERLAY_ATTR(zorder, S_IRUGO|S_IWUSR, | ||
377 | overlay_zorder_show, overlay_zorder_store); | ||
350 | 378 | ||
351 | static struct attribute *overlay_sysfs_attrs[] = { | 379 | static struct attribute *overlay_sysfs_attrs[] = { |
352 | &overlay_attr_name.attr, | 380 | &overlay_attr_name.attr, |
@@ -358,6 +386,7 @@ static struct attribute *overlay_sysfs_attrs[] = { | |||
358 | &overlay_attr_enabled.attr, | 386 | &overlay_attr_enabled.attr, |
359 | &overlay_attr_global_alpha.attr, | 387 | &overlay_attr_global_alpha.attr, |
360 | &overlay_attr_pre_mult_alpha.attr, | 388 | &overlay_attr_pre_mult_alpha.attr, |
389 | &overlay_attr_zorder.attr, | ||
361 | NULL | 390 | NULL |
362 | }; | 391 | }; |
363 | 392 | ||
@@ -407,6 +436,7 @@ int dss_check_overlay(struct omap_overlay *ovl, struct omap_dss_device *dssdev) | |||
407 | struct omap_overlay_info *info; | 436 | struct omap_overlay_info *info; |
408 | u16 outw, outh; | 437 | u16 outw, outh; |
409 | u16 dw, dh; | 438 | u16 dw, dh; |
439 | int i; | ||
410 | 440 | ||
411 | if (!dssdev) | 441 | if (!dssdev) |
412 | return 0; | 442 | return 0; |
@@ -462,6 +492,31 @@ int dss_check_overlay(struct omap_overlay *ovl, struct omap_dss_device *dssdev) | |||
462 | return -EINVAL; | 492 | return -EINVAL; |
463 | } | 493 | } |
464 | 494 | ||
495 | if (ovl->caps & OMAP_DSS_OVL_CAP_ZORDER) { | ||
496 | if (info->zorder < 0 || info->zorder > 3) { | ||
497 | DSSERR("zorder out of range: %d\n", | ||
498 | info->zorder); | ||
499 | return -EINVAL; | ||
500 | } | ||
501 | /* | ||
502 | * Check that zorder doesn't match with zorder of any other | ||
503 | * overlay which is enabled and is also connected to the same | ||
504 | * manager | ||
505 | */ | ||
506 | for (i = 0; i < omap_dss_get_num_overlays(); i++) { | ||
507 | struct omap_overlay *tmp_ovl = omap_dss_get_overlay(i); | ||
508 | |||
509 | if (tmp_ovl->id != ovl->id && | ||
510 | tmp_ovl->manager == ovl->manager && | ||
511 | tmp_ovl->info.enabled == true && | ||
512 | tmp_ovl->info.zorder == info->zorder) { | ||
513 | DSSERR("%s and %s have same zorder: %d\n", | ||
514 | ovl->name, tmp_ovl->name, info->zorder); | ||
515 | return -EINVAL; | ||
516 | } | ||
517 | } | ||
518 | } | ||
519 | |||
465 | return 0; | 520 | return 0; |
466 | } | 521 | } |
467 | 522 | ||
@@ -516,6 +571,7 @@ static int omap_dss_set_manager(struct omap_overlay *ovl, | |||
516 | } | 571 | } |
517 | 572 | ||
518 | ovl->manager = mgr; | 573 | ovl->manager = mgr; |
574 | ovl->manager_changed = true; | ||
519 | 575 | ||
520 | /* XXX: When there is an overlay on a DSI manual update display, and | 576 | /* XXX: When there is an overlay on a DSI manual update display, and |
521 | * the overlay is first disabled, then moved to tv, and enabled, we | 577 | * the overlay is first disabled, then moved to tv, and enabled, we |
@@ -529,15 +585,12 @@ static int omap_dss_set_manager(struct omap_overlay *ovl, | |||
529 | * Userspace workaround for this is to update the LCD after disabling | 585 | * Userspace workaround for this is to update the LCD after disabling |
530 | * the overlay, but before moving the overlay to TV. | 586 | * the overlay, but before moving the overlay to TV. |
531 | */ | 587 | */ |
532 | dispc_set_channel_out(ovl->id, mgr->id); | ||
533 | 588 | ||
534 | return 0; | 589 | return 0; |
535 | } | 590 | } |
536 | 591 | ||
537 | static int omap_dss_unset_manager(struct omap_overlay *ovl) | 592 | static int omap_dss_unset_manager(struct omap_overlay *ovl) |
538 | { | 593 | { |
539 | int r; | ||
540 | |||
541 | if (!ovl->manager) { | 594 | if (!ovl->manager) { |
542 | DSSERR("failed to detach overlay: manager not set\n"); | 595 | DSSERR("failed to detach overlay: manager not set\n"); |
543 | return -EINVAL; | 596 | return -EINVAL; |
@@ -548,11 +601,8 @@ static int omap_dss_unset_manager(struct omap_overlay *ovl) | |||
548 | return -EINVAL; | 601 | return -EINVAL; |
549 | } | 602 | } |
550 | 603 | ||
551 | r = ovl->wait_for_go(ovl); | ||
552 | if (r) | ||
553 | return r; | ||
554 | |||
555 | ovl->manager = NULL; | 604 | ovl->manager = NULL; |
605 | ovl->manager_changed = true; | ||
556 | 606 | ||
557 | return 0; | 607 | return 0; |
558 | } | 608 | } |
@@ -618,22 +668,29 @@ void dss_init_overlays(struct platform_device *pdev) | |||
618 | case 0: | 668 | case 0: |
619 | ovl->name = "gfx"; | 669 | ovl->name = "gfx"; |
620 | ovl->id = OMAP_DSS_GFX; | 670 | ovl->id = OMAP_DSS_GFX; |
621 | ovl->caps = OMAP_DSS_OVL_CAP_DISPC; | ||
622 | ovl->info.global_alpha = 255; | 671 | ovl->info.global_alpha = 255; |
672 | ovl->info.zorder = 0; | ||
623 | break; | 673 | break; |
624 | case 1: | 674 | case 1: |
625 | ovl->name = "vid1"; | 675 | ovl->name = "vid1"; |
626 | ovl->id = OMAP_DSS_VIDEO1; | 676 | ovl->id = OMAP_DSS_VIDEO1; |
627 | ovl->caps = OMAP_DSS_OVL_CAP_SCALE | | ||
628 | OMAP_DSS_OVL_CAP_DISPC; | ||
629 | ovl->info.global_alpha = 255; | 677 | ovl->info.global_alpha = 255; |
678 | ovl->info.zorder = | ||
679 | dss_has_feature(FEAT_ALPHA_FREE_ZORDER) ? 3 : 0; | ||
630 | break; | 680 | break; |
631 | case 2: | 681 | case 2: |
632 | ovl->name = "vid2"; | 682 | ovl->name = "vid2"; |
633 | ovl->id = OMAP_DSS_VIDEO2; | 683 | ovl->id = OMAP_DSS_VIDEO2; |
634 | ovl->caps = OMAP_DSS_OVL_CAP_SCALE | | ||
635 | OMAP_DSS_OVL_CAP_DISPC; | ||
636 | ovl->info.global_alpha = 255; | 684 | ovl->info.global_alpha = 255; |
685 | ovl->info.zorder = | ||
686 | dss_has_feature(FEAT_ALPHA_FREE_ZORDER) ? 2 : 0; | ||
687 | break; | ||
688 | case 3: | ||
689 | ovl->name = "vid3"; | ||
690 | ovl->id = OMAP_DSS_VIDEO3; | ||
691 | ovl->info.global_alpha = 255; | ||
692 | ovl->info.zorder = | ||
693 | dss_has_feature(FEAT_ALPHA_FREE_ZORDER) ? 1 : 0; | ||
637 | break; | 694 | break; |
638 | } | 695 | } |
639 | 696 | ||
@@ -643,6 +700,7 @@ void dss_init_overlays(struct platform_device *pdev) | |||
643 | ovl->get_overlay_info = &dss_ovl_get_overlay_info; | 700 | ovl->get_overlay_info = &dss_ovl_get_overlay_info; |
644 | ovl->wait_for_go = &dss_ovl_wait_for_go; | 701 | ovl->wait_for_go = &dss_ovl_wait_for_go; |
645 | 702 | ||
703 | ovl->caps = dss_feat_get_overlay_caps(ovl->id); | ||
646 | ovl->supported_modes = | 704 | ovl->supported_modes = |
647 | dss_feat_get_supported_color_modes(ovl->id); | 705 | dss_feat_get_supported_color_modes(ovl->id); |
648 | 706 | ||
diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c index 39f4c597026a..1bd3703e42ff 100644 --- a/drivers/video/omap2/dss/rfbi.c +++ b/drivers/video/omap2/dss/rfbi.c | |||
@@ -309,9 +309,9 @@ static void rfbi_transfer_area(struct omap_dss_device *dssdev, u16 width, | |||
309 | 309 | ||
310 | DSSDBG("rfbi_transfer_area %dx%d\n", width, height); | 310 | DSSDBG("rfbi_transfer_area %dx%d\n", width, height); |
311 | 311 | ||
312 | dispc_set_lcd_size(dssdev->manager->id, width, height); | 312 | dispc_mgr_set_lcd_size(dssdev->manager->id, width, height); |
313 | 313 | ||
314 | dispc_enable_channel(dssdev->manager->id, true); | 314 | dispc_mgr_enable(dssdev->manager->id, true); |
315 | 315 | ||
316 | rfbi.framedone_callback = callback; | 316 | rfbi.framedone_callback = callback; |
317 | rfbi.framedone_callback_data = data; | 317 | rfbi.framedone_callback_data = data; |
@@ -783,10 +783,8 @@ int omap_rfbi_prepare_update(struct omap_dss_device *dssdev, | |||
783 | if (*w == 0 || *h == 0) | 783 | if (*w == 0 || *h == 0) |
784 | return -EINVAL; | 784 | return -EINVAL; |
785 | 785 | ||
786 | if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) { | 786 | dss_setup_partial_planes(dssdev, x, y, w, h, true); |
787 | dss_setup_partial_planes(dssdev, x, y, w, h, true); | 787 | dispc_mgr_set_lcd_size(dssdev->manager->id, *w, *h); |
788 | dispc_set_lcd_size(dssdev->manager->id, *w, *h); | ||
789 | } | ||
790 | 788 | ||
791 | return 0; | 789 | return 0; |
792 | } | 790 | } |
@@ -796,22 +794,7 @@ int omap_rfbi_update(struct omap_dss_device *dssdev, | |||
796 | u16 x, u16 y, u16 w, u16 h, | 794 | u16 x, u16 y, u16 w, u16 h, |
797 | void (*callback)(void *), void *data) | 795 | void (*callback)(void *), void *data) |
798 | { | 796 | { |
799 | if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) { | 797 | rfbi_transfer_area(dssdev, w, h, callback, data); |
800 | rfbi_transfer_area(dssdev, w, h, callback, data); | ||
801 | } else { | ||
802 | struct omap_overlay *ovl; | ||
803 | void __iomem *addr; | ||
804 | int scr_width; | ||
805 | |||
806 | ovl = dssdev->manager->overlays[0]; | ||
807 | scr_width = ovl->info.screen_width; | ||
808 | addr = ovl->info.vaddr; | ||
809 | |||
810 | omap_rfbi_write_pixels(addr, scr_width, x, y, w, h); | ||
811 | |||
812 | callback(data); | ||
813 | } | ||
814 | |||
815 | return 0; | 798 | return 0; |
816 | } | 799 | } |
817 | EXPORT_SYMBOL(omap_rfbi_update); | 800 | EXPORT_SYMBOL(omap_rfbi_update); |
@@ -860,6 +843,11 @@ int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev) | |||
860 | { | 843 | { |
861 | int r; | 844 | int r; |
862 | 845 | ||
846 | if (dssdev->manager == NULL) { | ||
847 | DSSERR("failed to enable display: no manager\n"); | ||
848 | return -ENODEV; | ||
849 | } | ||
850 | |||
863 | r = rfbi_runtime_get(); | 851 | r = rfbi_runtime_get(); |
864 | if (r) | 852 | if (r) |
865 | return r; | 853 | return r; |
@@ -877,13 +865,13 @@ int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev) | |||
877 | goto err1; | 865 | goto err1; |
878 | } | 866 | } |
879 | 867 | ||
880 | dispc_set_lcd_display_type(dssdev->manager->id, | 868 | dispc_mgr_set_lcd_display_type(dssdev->manager->id, |
881 | OMAP_DSS_LCD_DISPLAY_TFT); | 869 | OMAP_DSS_LCD_DISPLAY_TFT); |
882 | 870 | ||
883 | dispc_set_parallel_interface_mode(dssdev->manager->id, | 871 | dispc_mgr_set_io_pad_mode(DSS_IO_PAD_MODE_RFBI); |
884 | OMAP_DSS_PARALLELMODE_RFBI); | 872 | dispc_mgr_enable_stallmode(dssdev->manager->id, true); |
885 | 873 | ||
886 | dispc_set_tft_data_lines(dssdev->manager->id, dssdev->ctrl.pixel_size); | 874 | dispc_mgr_set_tft_data_lines(dssdev->manager->id, dssdev->ctrl.pixel_size); |
887 | 875 | ||
888 | rfbi_configure(dssdev->phy.rfbi.channel, | 876 | rfbi_configure(dssdev->phy.rfbi.channel, |
889 | dssdev->ctrl.pixel_size, | 877 | dssdev->ctrl.pixel_size, |
@@ -952,10 +940,7 @@ static int omap_rfbihw_probe(struct platform_device *pdev) | |||
952 | 940 | ||
953 | msleep(10); | 941 | msleep(10); |
954 | 942 | ||
955 | if (cpu_is_omap24xx() || cpu_is_omap34xx() || cpu_is_omap3630()) | 943 | clk = clk_get(&pdev->dev, "ick"); |
956 | clk = dss_get_ick(); | ||
957 | else | ||
958 | clk = clk_get(&pdev->dev, "ick"); | ||
959 | if (IS_ERR(clk)) { | 944 | if (IS_ERR(clk)) { |
960 | DSSERR("can't get ick\n"); | 945 | DSSERR("can't get ick\n"); |
961 | r = PTR_ERR(clk); | 946 | r = PTR_ERR(clk); |
diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c index 3a688c871a45..695dc04cabba 100644 --- a/drivers/video/omap2/dss/sdi.c +++ b/drivers/video/omap2/dss/sdi.c | |||
@@ -35,13 +35,13 @@ static struct { | |||
35 | static void sdi_basic_init(struct omap_dss_device *dssdev) | 35 | static void sdi_basic_init(struct omap_dss_device *dssdev) |
36 | 36 | ||
37 | { | 37 | { |
38 | dispc_set_parallel_interface_mode(dssdev->manager->id, | 38 | dispc_mgr_set_io_pad_mode(DSS_IO_PAD_MODE_BYPASS); |
39 | OMAP_DSS_PARALLELMODE_BYPASS); | 39 | dispc_mgr_enable_stallmode(dssdev->manager->id, false); |
40 | 40 | ||
41 | dispc_set_lcd_display_type(dssdev->manager->id, | 41 | dispc_mgr_set_lcd_display_type(dssdev->manager->id, |
42 | OMAP_DSS_LCD_DISPLAY_TFT); | 42 | OMAP_DSS_LCD_DISPLAY_TFT); |
43 | 43 | ||
44 | dispc_set_tft_data_lines(dssdev->manager->id, 24); | 44 | dispc_mgr_set_tft_data_lines(dssdev->manager->id, 24); |
45 | dispc_lcd_enable_signal_polarity(1); | 45 | dispc_lcd_enable_signal_polarity(1); |
46 | } | 46 | } |
47 | 47 | ||
@@ -55,6 +55,11 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev) | |||
55 | unsigned long pck; | 55 | unsigned long pck; |
56 | int r; | 56 | int r; |
57 | 57 | ||
58 | if (dssdev->manager == NULL) { | ||
59 | DSSERR("failed to enable display: no manager\n"); | ||
60 | return -ENODEV; | ||
61 | } | ||
62 | |||
58 | r = omap_dss_start_device(dssdev); | 63 | r = omap_dss_start_device(dssdev); |
59 | if (r) { | 64 | if (r) { |
60 | DSSERR("failed to start device\n"); | 65 | DSSERR("failed to start device\n"); |
@@ -78,7 +83,7 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev) | |||
78 | /* 15.5.9.1.2 */ | 83 | /* 15.5.9.1.2 */ |
79 | dssdev->panel.config |= OMAP_DSS_LCD_RF | OMAP_DSS_LCD_ONOFF; | 84 | dssdev->panel.config |= OMAP_DSS_LCD_RF | OMAP_DSS_LCD_ONOFF; |
80 | 85 | ||
81 | dispc_set_pol_freq(dssdev->manager->id, dssdev->panel.config, | 86 | dispc_mgr_set_pol_freq(dssdev->manager->id, dssdev->panel.config, |
82 | dssdev->panel.acbi, dssdev->panel.acb); | 87 | dssdev->panel.acbi, dssdev->panel.acb); |
83 | 88 | ||
84 | r = dss_calc_clock_div(1, t->pixel_clock * 1000, | 89 | r = dss_calc_clock_div(1, t->pixel_clock * 1000, |
@@ -101,13 +106,13 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev) | |||
101 | } | 106 | } |
102 | 107 | ||
103 | 108 | ||
104 | dispc_set_lcd_timings(dssdev->manager->id, t); | 109 | dispc_mgr_set_lcd_timings(dssdev->manager->id, t); |
105 | 110 | ||
106 | r = dss_set_clock_div(&dss_cinfo); | 111 | r = dss_set_clock_div(&dss_cinfo); |
107 | if (r) | 112 | if (r) |
108 | goto err_set_dss_clock_div; | 113 | goto err_set_dss_clock_div; |
109 | 114 | ||
110 | r = dispc_set_clock_div(dssdev->manager->id, &dispc_cinfo); | 115 | r = dispc_mgr_set_clock_div(dssdev->manager->id, &dispc_cinfo); |
111 | if (r) | 116 | if (r) |
112 | goto err_set_dispc_clock_div; | 117 | goto err_set_dispc_clock_div; |
113 | 118 | ||
diff --git a/drivers/video/omap2/dss/ti_hdmi.h b/drivers/video/omap2/dss/ti_hdmi.h new file mode 100644 index 000000000000..2c3443dabb14 --- /dev/null +++ b/drivers/video/omap2/dss/ti_hdmi.h | |||
@@ -0,0 +1,138 @@ | |||
1 | /* | ||
2 | * ti_hdmi.h | ||
3 | * | ||
4 | * HDMI driver definition for TI OMAP4, DM81xx, DM38xx Processor. | ||
5 | * | ||
6 | * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/ | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License version 2 as published by | ||
10 | * the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
15 | * more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License along with | ||
18 | * this program. If not, see <http://www.gnu.org/licenses/>. | ||
19 | */ | ||
20 | |||
21 | #ifndef _TI_HDMI_H | ||
22 | #define _TI_HDMI_H | ||
23 | |||
24 | struct hdmi_ip_data; | ||
25 | |||
26 | enum hdmi_pll_pwr { | ||
27 | HDMI_PLLPWRCMD_ALLOFF = 0, | ||
28 | HDMI_PLLPWRCMD_PLLONLY = 1, | ||
29 | HDMI_PLLPWRCMD_BOTHON_ALLCLKS = 2, | ||
30 | HDMI_PLLPWRCMD_BOTHON_NOPHYCLK = 3 | ||
31 | }; | ||
32 | |||
33 | enum hdmi_core_hdmi_dvi { | ||
34 | HDMI_DVI = 0, | ||
35 | HDMI_HDMI = 1 | ||
36 | }; | ||
37 | |||
38 | enum hdmi_clk_refsel { | ||
39 | HDMI_REFSEL_PCLK = 0, | ||
40 | HDMI_REFSEL_REF1 = 1, | ||
41 | HDMI_REFSEL_REF2 = 2, | ||
42 | HDMI_REFSEL_SYSCLK = 3 | ||
43 | }; | ||
44 | |||
45 | struct hdmi_video_timings { | ||
46 | u16 x_res; | ||
47 | u16 y_res; | ||
48 | /* Unit: KHz */ | ||
49 | u32 pixel_clock; | ||
50 | u16 hsw; | ||
51 | u16 hfp; | ||
52 | u16 hbp; | ||
53 | u16 vsw; | ||
54 | u16 vfp; | ||
55 | u16 vbp; | ||
56 | }; | ||
57 | |||
58 | /* HDMI timing structure */ | ||
59 | struct hdmi_timings { | ||
60 | struct hdmi_video_timings timings; | ||
61 | int vsync_pol; | ||
62 | int hsync_pol; | ||
63 | }; | ||
64 | |||
65 | struct hdmi_cm { | ||
66 | int code; | ||
67 | int mode; | ||
68 | }; | ||
69 | |||
70 | struct hdmi_config { | ||
71 | struct hdmi_timings timings; | ||
72 | u16 interlace; | ||
73 | struct hdmi_cm cm; | ||
74 | }; | ||
75 | |||
76 | /* HDMI PLL structure */ | ||
77 | struct hdmi_pll_info { | ||
78 | u16 regn; | ||
79 | u16 regm; | ||
80 | u32 regmf; | ||
81 | u16 regm2; | ||
82 | u16 regsd; | ||
83 | u16 dcofreq; | ||
84 | enum hdmi_clk_refsel refsel; | ||
85 | }; | ||
86 | |||
87 | struct ti_hdmi_ip_ops { | ||
88 | |||
89 | void (*video_configure)(struct hdmi_ip_data *ip_data); | ||
90 | |||
91 | int (*phy_enable)(struct hdmi_ip_data *ip_data); | ||
92 | |||
93 | void (*phy_disable)(struct hdmi_ip_data *ip_data); | ||
94 | |||
95 | int (*read_edid)(struct hdmi_ip_data *ip_data, u8 *edid, int len); | ||
96 | |||
97 | bool (*detect)(struct hdmi_ip_data *ip_data); | ||
98 | |||
99 | int (*pll_enable)(struct hdmi_ip_data *ip_data); | ||
100 | |||
101 | void (*pll_disable)(struct hdmi_ip_data *ip_data); | ||
102 | |||
103 | void (*video_enable)(struct hdmi_ip_data *ip_data, bool start); | ||
104 | |||
105 | void (*dump_wrapper)(struct hdmi_ip_data *ip_data, struct seq_file *s); | ||
106 | |||
107 | void (*dump_core)(struct hdmi_ip_data *ip_data, struct seq_file *s); | ||
108 | |||
109 | void (*dump_pll)(struct hdmi_ip_data *ip_data, struct seq_file *s); | ||
110 | |||
111 | void (*dump_phy)(struct hdmi_ip_data *ip_data, struct seq_file *s); | ||
112 | |||
113 | }; | ||
114 | |||
115 | struct hdmi_ip_data { | ||
116 | void __iomem *base_wp; /* HDMI wrapper */ | ||
117 | unsigned long core_sys_offset; | ||
118 | unsigned long core_av_offset; | ||
119 | unsigned long pll_offset; | ||
120 | unsigned long phy_offset; | ||
121 | const struct ti_hdmi_ip_ops *ops; | ||
122 | struct hdmi_config cfg; | ||
123 | struct hdmi_pll_info pll_data; | ||
124 | }; | ||
125 | int ti_hdmi_4xxx_phy_enable(struct hdmi_ip_data *ip_data); | ||
126 | void ti_hdmi_4xxx_phy_disable(struct hdmi_ip_data *ip_data); | ||
127 | int ti_hdmi_4xxx_read_edid(struct hdmi_ip_data *ip_data, u8 *edid, int len); | ||
128 | bool ti_hdmi_4xxx_detect(struct hdmi_ip_data *ip_data); | ||
129 | void ti_hdmi_4xxx_wp_video_start(struct hdmi_ip_data *ip_data, bool start); | ||
130 | int ti_hdmi_4xxx_pll_enable(struct hdmi_ip_data *ip_data); | ||
131 | void ti_hdmi_4xxx_pll_disable(struct hdmi_ip_data *ip_data); | ||
132 | void ti_hdmi_4xxx_basic_configure(struct hdmi_ip_data *ip_data); | ||
133 | void ti_hdmi_4xxx_wp_dump(struct hdmi_ip_data *ip_data, struct seq_file *s); | ||
134 | void ti_hdmi_4xxx_pll_dump(struct hdmi_ip_data *ip_data, struct seq_file *s); | ||
135 | void ti_hdmi_4xxx_core_dump(struct hdmi_ip_data *ip_data, struct seq_file *s); | ||
136 | void ti_hdmi_4xxx_phy_dump(struct hdmi_ip_data *ip_data, struct seq_file *s); | ||
137 | |||
138 | #endif | ||
diff --git a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c new file mode 100644 index 000000000000..e1a6ce518af6 --- /dev/null +++ b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c | |||
@@ -0,0 +1,1239 @@ | |||
1 | /* | ||
2 | * ti_hdmi_4xxx_ip.c | ||
3 | * | ||
4 | * HDMI TI81xx, TI38xx, TI OMAP4 etc IP driver Library | ||
5 | * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/ | ||
6 | * Authors: Yong Zhi | ||
7 | * Mythri pk <mythripk@ti.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License version 2 as published by | ||
11 | * the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
14 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
15 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
16 | * more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License along with | ||
19 | * this program. If not, see <http://www.gnu.org/licenses/>. | ||
20 | */ | ||
21 | |||
22 | #include <linux/kernel.h> | ||
23 | #include <linux/module.h> | ||
24 | #include <linux/err.h> | ||
25 | #include <linux/io.h> | ||
26 | #include <linux/interrupt.h> | ||
27 | #include <linux/mutex.h> | ||
28 | #include <linux/delay.h> | ||
29 | #include <linux/string.h> | ||
30 | #include <linux/seq_file.h> | ||
31 | |||
32 | #include "ti_hdmi_4xxx_ip.h" | ||
33 | #include "dss.h" | ||
34 | |||
35 | static inline void hdmi_write_reg(void __iomem *base_addr, | ||
36 | const u16 idx, u32 val) | ||
37 | { | ||
38 | __raw_writel(val, base_addr + idx); | ||
39 | } | ||
40 | |||
41 | static inline u32 hdmi_read_reg(void __iomem *base_addr, | ||
42 | const u16 idx) | ||
43 | { | ||
44 | return __raw_readl(base_addr + idx); | ||
45 | } | ||
46 | |||
47 | static inline void __iomem *hdmi_wp_base(struct hdmi_ip_data *ip_data) | ||
48 | { | ||
49 | return ip_data->base_wp; | ||
50 | } | ||
51 | |||
52 | static inline void __iomem *hdmi_phy_base(struct hdmi_ip_data *ip_data) | ||
53 | { | ||
54 | return ip_data->base_wp + ip_data->phy_offset; | ||
55 | } | ||
56 | |||
57 | static inline void __iomem *hdmi_pll_base(struct hdmi_ip_data *ip_data) | ||
58 | { | ||
59 | return ip_data->base_wp + ip_data->pll_offset; | ||
60 | } | ||
61 | |||
62 | static inline void __iomem *hdmi_av_base(struct hdmi_ip_data *ip_data) | ||
63 | { | ||
64 | return ip_data->base_wp + ip_data->core_av_offset; | ||
65 | } | ||
66 | |||
67 | static inline void __iomem *hdmi_core_sys_base(struct hdmi_ip_data *ip_data) | ||
68 | { | ||
69 | return ip_data->base_wp + ip_data->core_sys_offset; | ||
70 | } | ||
71 | |||
72 | static inline int hdmi_wait_for_bit_change(void __iomem *base_addr, | ||
73 | const u16 idx, | ||
74 | int b2, int b1, u32 val) | ||
75 | { | ||
76 | u32 t = 0; | ||
77 | while (val != REG_GET(base_addr, idx, b2, b1)) { | ||
78 | udelay(1); | ||
79 | if (t++ > 10000) | ||
80 | return !val; | ||
81 | } | ||
82 | return val; | ||
83 | } | ||
84 | |||
85 | static int hdmi_pll_init(struct hdmi_ip_data *ip_data) | ||
86 | { | ||
87 | u32 r; | ||
88 | void __iomem *pll_base = hdmi_pll_base(ip_data); | ||
89 | struct hdmi_pll_info *fmt = &ip_data->pll_data; | ||
90 | |||
91 | /* PLL start always use manual mode */ | ||
92 | REG_FLD_MOD(pll_base, PLLCTRL_PLL_CONTROL, 0x0, 0, 0); | ||
93 | |||
94 | r = hdmi_read_reg(pll_base, PLLCTRL_CFG1); | ||
95 | r = FLD_MOD(r, fmt->regm, 20, 9); /* CFG1_PLL_REGM */ | ||
96 | r = FLD_MOD(r, fmt->regn - 1, 8, 1); /* CFG1_PLL_REGN */ | ||
97 | |||
98 | hdmi_write_reg(pll_base, PLLCTRL_CFG1, r); | ||
99 | |||
100 | r = hdmi_read_reg(pll_base, PLLCTRL_CFG2); | ||
101 | |||
102 | r = FLD_MOD(r, 0x0, 12, 12); /* PLL_HIGHFREQ divide by 2 */ | ||
103 | r = FLD_MOD(r, 0x1, 13, 13); /* PLL_REFEN */ | ||
104 | r = FLD_MOD(r, 0x0, 14, 14); /* PHY_CLKINEN de-assert during locking */ | ||
105 | r = FLD_MOD(r, fmt->refsel, 22, 21); /* REFSEL */ | ||
106 | |||
107 | if (fmt->dcofreq) { | ||
108 | /* divider programming for frequency beyond 1000Mhz */ | ||
109 | REG_FLD_MOD(pll_base, PLLCTRL_CFG3, fmt->regsd, 17, 10); | ||
110 | r = FLD_MOD(r, 0x4, 3, 1); /* 1000MHz and 2000MHz */ | ||
111 | } else { | ||
112 | r = FLD_MOD(r, 0x2, 3, 1); /* 500MHz and 1000MHz */ | ||
113 | } | ||
114 | |||
115 | hdmi_write_reg(pll_base, PLLCTRL_CFG2, r); | ||
116 | |||
117 | r = hdmi_read_reg(pll_base, PLLCTRL_CFG4); | ||
118 | r = FLD_MOD(r, fmt->regm2, 24, 18); | ||
119 | r = FLD_MOD(r, fmt->regmf, 17, 0); | ||
120 | |||
121 | hdmi_write_reg(pll_base, PLLCTRL_CFG4, r); | ||
122 | |||
123 | /* go now */ | ||
124 | REG_FLD_MOD(pll_base, PLLCTRL_PLL_GO, 0x1, 0, 0); | ||
125 | |||
126 | /* wait for bit change */ | ||
127 | if (hdmi_wait_for_bit_change(pll_base, PLLCTRL_PLL_GO, | ||
128 | 0, 0, 1) != 1) { | ||
129 | pr_err("PLL GO bit not set\n"); | ||
130 | return -ETIMEDOUT; | ||
131 | } | ||
132 | |||
133 | /* Wait till the lock bit is set in PLL status */ | ||
134 | if (hdmi_wait_for_bit_change(pll_base, | ||
135 | PLLCTRL_PLL_STATUS, 1, 1, 1) != 1) { | ||
136 | pr_err("cannot lock PLL\n"); | ||
137 | pr_err("CFG1 0x%x\n", | ||
138 | hdmi_read_reg(pll_base, PLLCTRL_CFG1)); | ||
139 | pr_err("CFG2 0x%x\n", | ||
140 | hdmi_read_reg(pll_base, PLLCTRL_CFG2)); | ||
141 | pr_err("CFG4 0x%x\n", | ||
142 | hdmi_read_reg(pll_base, PLLCTRL_CFG4)); | ||
143 | return -ETIMEDOUT; | ||
144 | } | ||
145 | |||
146 | pr_debug("PLL locked!\n"); | ||
147 | |||
148 | return 0; | ||
149 | } | ||
150 | |||
151 | /* PHY_PWR_CMD */ | ||
152 | static int hdmi_set_phy_pwr(struct hdmi_ip_data *ip_data, enum hdmi_phy_pwr val) | ||
153 | { | ||
154 | /* Command for power control of HDMI PHY */ | ||
155 | REG_FLD_MOD(hdmi_wp_base(ip_data), HDMI_WP_PWR_CTRL, val, 7, 6); | ||
156 | |||
157 | /* Status of the power control of HDMI PHY */ | ||
158 | if (hdmi_wait_for_bit_change(hdmi_wp_base(ip_data), | ||
159 | HDMI_WP_PWR_CTRL, 5, 4, val) != val) { | ||
160 | pr_err("Failed to set PHY power mode to %d\n", val); | ||
161 | return -ETIMEDOUT; | ||
162 | } | ||
163 | |||
164 | return 0; | ||
165 | } | ||
166 | |||
167 | /* PLL_PWR_CMD */ | ||
168 | static int hdmi_set_pll_pwr(struct hdmi_ip_data *ip_data, enum hdmi_pll_pwr val) | ||
169 | { | ||
170 | /* Command for power control of HDMI PLL */ | ||
171 | REG_FLD_MOD(hdmi_wp_base(ip_data), HDMI_WP_PWR_CTRL, val, 3, 2); | ||
172 | |||
173 | /* wait till PHY_PWR_STATUS is set */ | ||
174 | if (hdmi_wait_for_bit_change(hdmi_wp_base(ip_data), HDMI_WP_PWR_CTRL, | ||
175 | 1, 0, val) != val) { | ||
176 | pr_err("Failed to set PLL_PWR_STATUS\n"); | ||
177 | return -ETIMEDOUT; | ||
178 | } | ||
179 | |||
180 | return 0; | ||
181 | } | ||
182 | |||
183 | static int hdmi_pll_reset(struct hdmi_ip_data *ip_data) | ||
184 | { | ||
185 | /* SYSRESET controlled by power FSM */ | ||
186 | REG_FLD_MOD(hdmi_pll_base(ip_data), PLLCTRL_PLL_CONTROL, 0x0, 3, 3); | ||
187 | |||
188 | /* READ 0x0 reset is in progress */ | ||
189 | if (hdmi_wait_for_bit_change(hdmi_pll_base(ip_data), | ||
190 | PLLCTRL_PLL_STATUS, 0, 0, 1) != 1) { | ||
191 | pr_err("Failed to sysreset PLL\n"); | ||
192 | return -ETIMEDOUT; | ||
193 | } | ||
194 | |||
195 | return 0; | ||
196 | } | ||
197 | |||
198 | int ti_hdmi_4xxx_pll_enable(struct hdmi_ip_data *ip_data) | ||
199 | { | ||
200 | u16 r = 0; | ||
201 | |||
202 | r = hdmi_set_pll_pwr(ip_data, HDMI_PLLPWRCMD_ALLOFF); | ||
203 | if (r) | ||
204 | return r; | ||
205 | |||
206 | r = hdmi_set_pll_pwr(ip_data, HDMI_PLLPWRCMD_BOTHON_ALLCLKS); | ||
207 | if (r) | ||
208 | return r; | ||
209 | |||
210 | r = hdmi_pll_reset(ip_data); | ||
211 | if (r) | ||
212 | return r; | ||
213 | |||
214 | r = hdmi_pll_init(ip_data); | ||
215 | if (r) | ||
216 | return r; | ||
217 | |||
218 | return 0; | ||
219 | } | ||
220 | |||
221 | void ti_hdmi_4xxx_pll_disable(struct hdmi_ip_data *ip_data) | ||
222 | { | ||
223 | hdmi_set_pll_pwr(ip_data, HDMI_PLLPWRCMD_ALLOFF); | ||
224 | } | ||
225 | |||
226 | int ti_hdmi_4xxx_phy_enable(struct hdmi_ip_data *ip_data) | ||
227 | { | ||
228 | u16 r = 0; | ||
229 | void __iomem *phy_base = hdmi_phy_base(ip_data); | ||
230 | |||
231 | r = hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_LDOON); | ||
232 | if (r) | ||
233 | return r; | ||
234 | |||
235 | r = hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_TXON); | ||
236 | if (r) | ||
237 | return r; | ||
238 | |||
239 | /* | ||
240 | * Read address 0 in order to get the SCP reset done completed | ||
241 | * Dummy access performed to make sure reset is done | ||
242 | */ | ||
243 | hdmi_read_reg(phy_base, HDMI_TXPHY_TX_CTRL); | ||
244 | |||
245 | /* | ||
246 | * Write to phy address 0 to configure the clock | ||
247 | * use HFBITCLK write HDMI_TXPHY_TX_CONTROL_FREQOUT field | ||
248 | */ | ||
249 | REG_FLD_MOD(phy_base, HDMI_TXPHY_TX_CTRL, 0x1, 31, 30); | ||
250 | |||
251 | /* Write to phy address 1 to start HDMI line (TXVALID and TMDSCLKEN) */ | ||
252 | hdmi_write_reg(phy_base, HDMI_TXPHY_DIGITAL_CTRL, 0xF0000000); | ||
253 | |||
254 | /* Setup max LDO voltage */ | ||
255 | REG_FLD_MOD(phy_base, HDMI_TXPHY_POWER_CTRL, 0xB, 3, 0); | ||
256 | |||
257 | /* Write to phy address 3 to change the polarity control */ | ||
258 | REG_FLD_MOD(phy_base, HDMI_TXPHY_PAD_CFG_CTRL, 0x1, 27, 27); | ||
259 | |||
260 | return 0; | ||
261 | } | ||
262 | |||
263 | void ti_hdmi_4xxx_phy_disable(struct hdmi_ip_data *ip_data) | ||
264 | { | ||
265 | hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_OFF); | ||
266 | } | ||
267 | |||
268 | static int hdmi_core_ddc_init(struct hdmi_ip_data *ip_data) | ||
269 | { | ||
270 | void __iomem *base = hdmi_core_sys_base(ip_data); | ||
271 | |||
272 | /* Turn on CLK for DDC */ | ||
273 | REG_FLD_MOD(base, HDMI_CORE_AV_DPD, 0x7, 2, 0); | ||
274 | |||
275 | /* IN_PROG */ | ||
276 | if (REG_GET(base, HDMI_CORE_DDC_STATUS, 4, 4) == 1) { | ||
277 | /* Abort transaction */ | ||
278 | REG_FLD_MOD(base, HDMI_CORE_DDC_CMD, 0xf, 3, 0); | ||
279 | /* IN_PROG */ | ||
280 | if (hdmi_wait_for_bit_change(base, HDMI_CORE_DDC_STATUS, | ||
281 | 4, 4, 0) != 0) { | ||
282 | DSSERR("Timeout aborting DDC transaction\n"); | ||
283 | return -ETIMEDOUT; | ||
284 | } | ||
285 | } | ||
286 | |||
287 | /* Clk SCL Devices */ | ||
288 | REG_FLD_MOD(base, HDMI_CORE_DDC_CMD, 0xA, 3, 0); | ||
289 | |||
290 | /* HDMI_CORE_DDC_STATUS_IN_PROG */ | ||
291 | if (hdmi_wait_for_bit_change(base, HDMI_CORE_DDC_STATUS, | ||
292 | 4, 4, 0) != 0) { | ||
293 | DSSERR("Timeout starting SCL clock\n"); | ||
294 | return -ETIMEDOUT; | ||
295 | } | ||
296 | |||
297 | /* Clear FIFO */ | ||
298 | REG_FLD_MOD(base, HDMI_CORE_DDC_CMD, 0x9, 3, 0); | ||
299 | |||
300 | /* HDMI_CORE_DDC_STATUS_IN_PROG */ | ||
301 | if (hdmi_wait_for_bit_change(base, HDMI_CORE_DDC_STATUS, | ||
302 | 4, 4, 0) != 0) { | ||
303 | DSSERR("Timeout clearing DDC fifo\n"); | ||
304 | return -ETIMEDOUT; | ||
305 | } | ||
306 | |||
307 | return 0; | ||
308 | } | ||
309 | |||
310 | static int hdmi_core_ddc_edid(struct hdmi_ip_data *ip_data, | ||
311 | u8 *pedid, int ext) | ||
312 | { | ||
313 | void __iomem *base = hdmi_core_sys_base(ip_data); | ||
314 | u32 i; | ||
315 | char checksum; | ||
316 | u32 offset = 0; | ||
317 | |||
318 | /* HDMI_CORE_DDC_STATUS_IN_PROG */ | ||
319 | if (hdmi_wait_for_bit_change(base, HDMI_CORE_DDC_STATUS, | ||
320 | 4, 4, 0) != 0) { | ||
321 | DSSERR("Timeout waiting DDC to be ready\n"); | ||
322 | return -ETIMEDOUT; | ||
323 | } | ||
324 | |||
325 | if (ext % 2 != 0) | ||
326 | offset = 0x80; | ||
327 | |||
328 | /* Load Segment Address Register */ | ||
329 | REG_FLD_MOD(base, HDMI_CORE_DDC_SEGM, ext / 2, 7, 0); | ||
330 | |||
331 | /* Load Slave Address Register */ | ||
332 | REG_FLD_MOD(base, HDMI_CORE_DDC_ADDR, 0xA0 >> 1, 7, 1); | ||
333 | |||
334 | /* Load Offset Address Register */ | ||
335 | REG_FLD_MOD(base, HDMI_CORE_DDC_OFFSET, offset, 7, 0); | ||
336 | |||
337 | /* Load Byte Count */ | ||
338 | REG_FLD_MOD(base, HDMI_CORE_DDC_COUNT1, 0x80, 7, 0); | ||
339 | REG_FLD_MOD(base, HDMI_CORE_DDC_COUNT2, 0x0, 1, 0); | ||
340 | |||
341 | /* Set DDC_CMD */ | ||
342 | if (ext) | ||
343 | REG_FLD_MOD(base, HDMI_CORE_DDC_CMD, 0x4, 3, 0); | ||
344 | else | ||
345 | REG_FLD_MOD(base, HDMI_CORE_DDC_CMD, 0x2, 3, 0); | ||
346 | |||
347 | /* HDMI_CORE_DDC_STATUS_BUS_LOW */ | ||
348 | if (REG_GET(base, HDMI_CORE_DDC_STATUS, 6, 6) == 1) { | ||
349 | pr_err("I2C Bus Low?\n"); | ||
350 | return -EIO; | ||
351 | } | ||
352 | /* HDMI_CORE_DDC_STATUS_NO_ACK */ | ||
353 | if (REG_GET(base, HDMI_CORE_DDC_STATUS, 5, 5) == 1) { | ||
354 | pr_err("I2C No Ack\n"); | ||
355 | return -EIO; | ||
356 | } | ||
357 | |||
358 | for (i = 0; i < 0x80; ++i) { | ||
359 | int t; | ||
360 | |||
361 | /* IN_PROG */ | ||
362 | if (REG_GET(base, HDMI_CORE_DDC_STATUS, 4, 4) == 0) { | ||
363 | DSSERR("operation stopped when reading edid\n"); | ||
364 | return -EIO; | ||
365 | } | ||
366 | |||
367 | t = 0; | ||
368 | /* FIFO_EMPTY */ | ||
369 | while (REG_GET(base, HDMI_CORE_DDC_STATUS, 2, 2) == 1) { | ||
370 | if (t++ > 10000) { | ||
371 | DSSERR("timeout reading edid\n"); | ||
372 | return -ETIMEDOUT; | ||
373 | } | ||
374 | udelay(1); | ||
375 | } | ||
376 | |||
377 | pedid[i] = REG_GET(base, HDMI_CORE_DDC_DATA, 7, 0); | ||
378 | } | ||
379 | |||
380 | checksum = 0; | ||
381 | for (i = 0; i < 0x80; ++i) | ||
382 | checksum += pedid[i]; | ||
383 | |||
384 | if (checksum != 0) { | ||
385 | pr_err("E-EDID checksum failed!!\n"); | ||
386 | return -EIO; | ||
387 | } | ||
388 | |||
389 | return 0; | ||
390 | } | ||
391 | |||
392 | int ti_hdmi_4xxx_read_edid(struct hdmi_ip_data *ip_data, | ||
393 | u8 *edid, int len) | ||
394 | { | ||
395 | int r, l; | ||
396 | |||
397 | if (len < 128) | ||
398 | return -EINVAL; | ||
399 | |||
400 | r = hdmi_core_ddc_init(ip_data); | ||
401 | if (r) | ||
402 | return r; | ||
403 | |||
404 | r = hdmi_core_ddc_edid(ip_data, edid, 0); | ||
405 | if (r) | ||
406 | return r; | ||
407 | |||
408 | l = 128; | ||
409 | |||
410 | if (len >= 128 * 2 && edid[0x7e] > 0) { | ||
411 | r = hdmi_core_ddc_edid(ip_data, edid + 0x80, 1); | ||
412 | if (r) | ||
413 | return r; | ||
414 | l += 128; | ||
415 | } | ||
416 | |||
417 | return l; | ||
418 | } | ||
419 | |||
420 | bool ti_hdmi_4xxx_detect(struct hdmi_ip_data *ip_data) | ||
421 | { | ||
422 | int r; | ||
423 | |||
424 | void __iomem *base = hdmi_core_sys_base(ip_data); | ||
425 | |||
426 | /* HPD */ | ||
427 | r = REG_GET(base, HDMI_CORE_SYS_SYS_STAT, 1, 1); | ||
428 | |||
429 | return r == 1; | ||
430 | } | ||
431 | |||
432 | static void hdmi_core_init(struct hdmi_core_video_config *video_cfg, | ||
433 | struct hdmi_core_infoframe_avi *avi_cfg, | ||
434 | struct hdmi_core_packet_enable_repeat *repeat_cfg) | ||
435 | { | ||
436 | pr_debug("Enter hdmi_core_init\n"); | ||
437 | |||
438 | /* video core */ | ||
439 | video_cfg->ip_bus_width = HDMI_INPUT_8BIT; | ||
440 | video_cfg->op_dither_truc = HDMI_OUTPUTTRUNCATION_8BIT; | ||
441 | video_cfg->deep_color_pkt = HDMI_DEEPCOLORPACKECTDISABLE; | ||
442 | video_cfg->pkt_mode = HDMI_PACKETMODERESERVEDVALUE; | ||
443 | video_cfg->hdmi_dvi = HDMI_DVI; | ||
444 | video_cfg->tclk_sel_clkmult = HDMI_FPLL10IDCK; | ||
445 | |||
446 | /* info frame */ | ||
447 | avi_cfg->db1_format = 0; | ||
448 | avi_cfg->db1_active_info = 0; | ||
449 | avi_cfg->db1_bar_info_dv = 0; | ||
450 | avi_cfg->db1_scan_info = 0; | ||
451 | avi_cfg->db2_colorimetry = 0; | ||
452 | avi_cfg->db2_aspect_ratio = 0; | ||
453 | avi_cfg->db2_active_fmt_ar = 0; | ||
454 | avi_cfg->db3_itc = 0; | ||
455 | avi_cfg->db3_ec = 0; | ||
456 | avi_cfg->db3_q_range = 0; | ||
457 | avi_cfg->db3_nup_scaling = 0; | ||
458 | avi_cfg->db4_videocode = 0; | ||
459 | avi_cfg->db5_pixel_repeat = 0; | ||
460 | avi_cfg->db6_7_line_eoftop = 0 ; | ||
461 | avi_cfg->db8_9_line_sofbottom = 0; | ||
462 | avi_cfg->db10_11_pixel_eofleft = 0; | ||
463 | avi_cfg->db12_13_pixel_sofright = 0; | ||
464 | |||
465 | /* packet enable and repeat */ | ||
466 | repeat_cfg->audio_pkt = 0; | ||
467 | repeat_cfg->audio_pkt_repeat = 0; | ||
468 | repeat_cfg->avi_infoframe = 0; | ||
469 | repeat_cfg->avi_infoframe_repeat = 0; | ||
470 | repeat_cfg->gen_cntrl_pkt = 0; | ||
471 | repeat_cfg->gen_cntrl_pkt_repeat = 0; | ||
472 | repeat_cfg->generic_pkt = 0; | ||
473 | repeat_cfg->generic_pkt_repeat = 0; | ||
474 | } | ||
475 | |||
476 | static void hdmi_core_powerdown_disable(struct hdmi_ip_data *ip_data) | ||
477 | { | ||
478 | pr_debug("Enter hdmi_core_powerdown_disable\n"); | ||
479 | REG_FLD_MOD(hdmi_core_sys_base(ip_data), HDMI_CORE_CTRL1, 0x0, 0, 0); | ||
480 | } | ||
481 | |||
482 | static void hdmi_core_swreset_release(struct hdmi_ip_data *ip_data) | ||
483 | { | ||
484 | pr_debug("Enter hdmi_core_swreset_release\n"); | ||
485 | REG_FLD_MOD(hdmi_core_sys_base(ip_data), HDMI_CORE_SYS_SRST, 0x0, 0, 0); | ||
486 | } | ||
487 | |||
488 | static void hdmi_core_swreset_assert(struct hdmi_ip_data *ip_data) | ||
489 | { | ||
490 | pr_debug("Enter hdmi_core_swreset_assert\n"); | ||
491 | REG_FLD_MOD(hdmi_core_sys_base(ip_data), HDMI_CORE_SYS_SRST, 0x1, 0, 0); | ||
492 | } | ||
493 | |||
494 | /* HDMI_CORE_VIDEO_CONFIG */ | ||
495 | static void hdmi_core_video_config(struct hdmi_ip_data *ip_data, | ||
496 | struct hdmi_core_video_config *cfg) | ||
497 | { | ||
498 | u32 r = 0; | ||
499 | void __iomem *core_sys_base = hdmi_core_sys_base(ip_data); | ||
500 | |||
501 | /* sys_ctrl1 default configuration not tunable */ | ||
502 | r = hdmi_read_reg(core_sys_base, HDMI_CORE_CTRL1); | ||
503 | r = FLD_MOD(r, HDMI_CORE_CTRL1_VEN_FOLLOWVSYNC, 5, 5); | ||
504 | r = FLD_MOD(r, HDMI_CORE_CTRL1_HEN_FOLLOWHSYNC, 4, 4); | ||
505 | r = FLD_MOD(r, HDMI_CORE_CTRL1_BSEL_24BITBUS, 2, 2); | ||
506 | r = FLD_MOD(r, HDMI_CORE_CTRL1_EDGE_RISINGEDGE, 1, 1); | ||
507 | hdmi_write_reg(core_sys_base, HDMI_CORE_CTRL1, r); | ||
508 | |||
509 | REG_FLD_MOD(core_sys_base, | ||
510 | HDMI_CORE_SYS_VID_ACEN, cfg->ip_bus_width, 7, 6); | ||
511 | |||
512 | /* Vid_Mode */ | ||
513 | r = hdmi_read_reg(core_sys_base, HDMI_CORE_SYS_VID_MODE); | ||
514 | |||
515 | /* dither truncation configuration */ | ||
516 | if (cfg->op_dither_truc > HDMI_OUTPUTTRUNCATION_12BIT) { | ||
517 | r = FLD_MOD(r, cfg->op_dither_truc - 3, 7, 6); | ||
518 | r = FLD_MOD(r, 1, 5, 5); | ||
519 | } else { | ||
520 | r = FLD_MOD(r, cfg->op_dither_truc, 7, 6); | ||
521 | r = FLD_MOD(r, 0, 5, 5); | ||
522 | } | ||
523 | hdmi_write_reg(core_sys_base, HDMI_CORE_SYS_VID_MODE, r); | ||
524 | |||
525 | /* HDMI_Ctrl */ | ||
526 | r = hdmi_read_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_HDMI_CTRL); | ||
527 | r = FLD_MOD(r, cfg->deep_color_pkt, 6, 6); | ||
528 | r = FLD_MOD(r, cfg->pkt_mode, 5, 3); | ||
529 | r = FLD_MOD(r, cfg->hdmi_dvi, 0, 0); | ||
530 | hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_HDMI_CTRL, r); | ||
531 | |||
532 | /* TMDS_CTRL */ | ||
533 | REG_FLD_MOD(core_sys_base, | ||
534 | HDMI_CORE_SYS_TMDS_CTRL, cfg->tclk_sel_clkmult, 6, 5); | ||
535 | } | ||
536 | |||
537 | static void hdmi_core_aux_infoframe_avi_config(struct hdmi_ip_data *ip_data, | ||
538 | struct hdmi_core_infoframe_avi info_avi) | ||
539 | { | ||
540 | u32 val; | ||
541 | char sum = 0, checksum = 0; | ||
542 | void __iomem *av_base = hdmi_av_base(ip_data); | ||
543 | |||
544 | sum += 0x82 + 0x002 + 0x00D; | ||
545 | hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_TYPE, 0x082); | ||
546 | hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_VERS, 0x002); | ||
547 | hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_LEN, 0x00D); | ||
548 | |||
549 | val = (info_avi.db1_format << 5) | | ||
550 | (info_avi.db1_active_info << 4) | | ||
551 | (info_avi.db1_bar_info_dv << 2) | | ||
552 | (info_avi.db1_scan_info); | ||
553 | hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(0), val); | ||
554 | sum += val; | ||
555 | |||
556 | val = (info_avi.db2_colorimetry << 6) | | ||
557 | (info_avi.db2_aspect_ratio << 4) | | ||
558 | (info_avi.db2_active_fmt_ar); | ||
559 | hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(1), val); | ||
560 | sum += val; | ||
561 | |||
562 | val = (info_avi.db3_itc << 7) | | ||
563 | (info_avi.db3_ec << 4) | | ||
564 | (info_avi.db3_q_range << 2) | | ||
565 | (info_avi.db3_nup_scaling); | ||
566 | hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(2), val); | ||
567 | sum += val; | ||
568 | |||
569 | hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(3), | ||
570 | info_avi.db4_videocode); | ||
571 | sum += info_avi.db4_videocode; | ||
572 | |||
573 | val = info_avi.db5_pixel_repeat; | ||
574 | hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(4), val); | ||
575 | sum += val; | ||
576 | |||
577 | val = info_avi.db6_7_line_eoftop & 0x00FF; | ||
578 | hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(5), val); | ||
579 | sum += val; | ||
580 | |||
581 | val = ((info_avi.db6_7_line_eoftop >> 8) & 0x00FF); | ||
582 | hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(6), val); | ||
583 | sum += val; | ||
584 | |||
585 | val = info_avi.db8_9_line_sofbottom & 0x00FF; | ||
586 | hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(7), val); | ||
587 | sum += val; | ||
588 | |||
589 | val = ((info_avi.db8_9_line_sofbottom >> 8) & 0x00FF); | ||
590 | hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(8), val); | ||
591 | sum += val; | ||
592 | |||
593 | val = info_avi.db10_11_pixel_eofleft & 0x00FF; | ||
594 | hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(9), val); | ||
595 | sum += val; | ||
596 | |||
597 | val = ((info_avi.db10_11_pixel_eofleft >> 8) & 0x00FF); | ||
598 | hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(10), val); | ||
599 | sum += val; | ||
600 | |||
601 | val = info_avi.db12_13_pixel_sofright & 0x00FF; | ||
602 | hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(11), val); | ||
603 | sum += val; | ||
604 | |||
605 | val = ((info_avi.db12_13_pixel_sofright >> 8) & 0x00FF); | ||
606 | hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(12), val); | ||
607 | sum += val; | ||
608 | |||
609 | checksum = 0x100 - sum; | ||
610 | hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_CHSUM, checksum); | ||
611 | } | ||
612 | |||
613 | static void hdmi_core_av_packet_config(struct hdmi_ip_data *ip_data, | ||
614 | struct hdmi_core_packet_enable_repeat repeat_cfg) | ||
615 | { | ||
616 | /* enable/repeat the infoframe */ | ||
617 | hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_PB_CTRL1, | ||
618 | (repeat_cfg.audio_pkt << 5) | | ||
619 | (repeat_cfg.audio_pkt_repeat << 4) | | ||
620 | (repeat_cfg.avi_infoframe << 1) | | ||
621 | (repeat_cfg.avi_infoframe_repeat)); | ||
622 | |||
623 | /* enable/repeat the packet */ | ||
624 | hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_PB_CTRL2, | ||
625 | (repeat_cfg.gen_cntrl_pkt << 3) | | ||
626 | (repeat_cfg.gen_cntrl_pkt_repeat << 2) | | ||
627 | (repeat_cfg.generic_pkt << 1) | | ||
628 | (repeat_cfg.generic_pkt_repeat)); | ||
629 | } | ||
630 | |||
631 | static void hdmi_wp_init(struct omap_video_timings *timings, | ||
632 | struct hdmi_video_format *video_fmt, | ||
633 | struct hdmi_video_interface *video_int) | ||
634 | { | ||
635 | pr_debug("Enter hdmi_wp_init\n"); | ||
636 | |||
637 | timings->hbp = 0; | ||
638 | timings->hfp = 0; | ||
639 | timings->hsw = 0; | ||
640 | timings->vbp = 0; | ||
641 | timings->vfp = 0; | ||
642 | timings->vsw = 0; | ||
643 | |||
644 | video_fmt->packing_mode = HDMI_PACK_10b_RGB_YUV444; | ||
645 | video_fmt->y_res = 0; | ||
646 | video_fmt->x_res = 0; | ||
647 | |||
648 | video_int->vsp = 0; | ||
649 | video_int->hsp = 0; | ||
650 | |||
651 | video_int->interlacing = 0; | ||
652 | video_int->tm = 0; /* HDMI_TIMING_SLAVE */ | ||
653 | |||
654 | } | ||
655 | |||
656 | void ti_hdmi_4xxx_wp_video_start(struct hdmi_ip_data *ip_data, bool start) | ||
657 | { | ||
658 | REG_FLD_MOD(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_CFG, start, 31, 31); | ||
659 | } | ||
660 | |||
661 | static void hdmi_wp_video_init_format(struct hdmi_video_format *video_fmt, | ||
662 | struct omap_video_timings *timings, struct hdmi_config *param) | ||
663 | { | ||
664 | pr_debug("Enter hdmi_wp_video_init_format\n"); | ||
665 | |||
666 | video_fmt->y_res = param->timings.timings.y_res; | ||
667 | video_fmt->x_res = param->timings.timings.x_res; | ||
668 | |||
669 | timings->hbp = param->timings.timings.hbp; | ||
670 | timings->hfp = param->timings.timings.hfp; | ||
671 | timings->hsw = param->timings.timings.hsw; | ||
672 | timings->vbp = param->timings.timings.vbp; | ||
673 | timings->vfp = param->timings.timings.vfp; | ||
674 | timings->vsw = param->timings.timings.vsw; | ||
675 | } | ||
676 | |||
677 | static void hdmi_wp_video_config_format(struct hdmi_ip_data *ip_data, | ||
678 | struct hdmi_video_format *video_fmt) | ||
679 | { | ||
680 | u32 l = 0; | ||
681 | |||
682 | REG_FLD_MOD(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_CFG, | ||
683 | video_fmt->packing_mode, 10, 8); | ||
684 | |||
685 | l |= FLD_VAL(video_fmt->y_res, 31, 16); | ||
686 | l |= FLD_VAL(video_fmt->x_res, 15, 0); | ||
687 | hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_SIZE, l); | ||
688 | } | ||
689 | |||
690 | static void hdmi_wp_video_config_interface(struct hdmi_ip_data *ip_data, | ||
691 | struct hdmi_video_interface *video_int) | ||
692 | { | ||
693 | u32 r; | ||
694 | pr_debug("Enter hdmi_wp_video_config_interface\n"); | ||
695 | |||
696 | r = hdmi_read_reg(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_CFG); | ||
697 | r = FLD_MOD(r, video_int->vsp, 7, 7); | ||
698 | r = FLD_MOD(r, video_int->hsp, 6, 6); | ||
699 | r = FLD_MOD(r, video_int->interlacing, 3, 3); | ||
700 | r = FLD_MOD(r, video_int->tm, 1, 0); | ||
701 | hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_CFG, r); | ||
702 | } | ||
703 | |||
704 | static void hdmi_wp_video_config_timing(struct hdmi_ip_data *ip_data, | ||
705 | struct omap_video_timings *timings) | ||
706 | { | ||
707 | u32 timing_h = 0; | ||
708 | u32 timing_v = 0; | ||
709 | |||
710 | pr_debug("Enter hdmi_wp_video_config_timing\n"); | ||
711 | |||
712 | timing_h |= FLD_VAL(timings->hbp, 31, 20); | ||
713 | timing_h |= FLD_VAL(timings->hfp, 19, 8); | ||
714 | timing_h |= FLD_VAL(timings->hsw, 7, 0); | ||
715 | hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_TIMING_H, timing_h); | ||
716 | |||
717 | timing_v |= FLD_VAL(timings->vbp, 31, 20); | ||
718 | timing_v |= FLD_VAL(timings->vfp, 19, 8); | ||
719 | timing_v |= FLD_VAL(timings->vsw, 7, 0); | ||
720 | hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_TIMING_V, timing_v); | ||
721 | } | ||
722 | |||
723 | void ti_hdmi_4xxx_basic_configure(struct hdmi_ip_data *ip_data) | ||
724 | { | ||
725 | /* HDMI */ | ||
726 | struct omap_video_timings video_timing; | ||
727 | struct hdmi_video_format video_format; | ||
728 | struct hdmi_video_interface video_interface; | ||
729 | /* HDMI core */ | ||
730 | struct hdmi_core_infoframe_avi avi_cfg; | ||
731 | struct hdmi_core_video_config v_core_cfg; | ||
732 | struct hdmi_core_packet_enable_repeat repeat_cfg; | ||
733 | struct hdmi_config *cfg = &ip_data->cfg; | ||
734 | |||
735 | hdmi_wp_init(&video_timing, &video_format, | ||
736 | &video_interface); | ||
737 | |||
738 | hdmi_core_init(&v_core_cfg, | ||
739 | &avi_cfg, | ||
740 | &repeat_cfg); | ||
741 | |||
742 | hdmi_wp_video_init_format(&video_format, &video_timing, cfg); | ||
743 | |||
744 | hdmi_wp_video_config_timing(ip_data, &video_timing); | ||
745 | |||
746 | /* video config */ | ||
747 | video_format.packing_mode = HDMI_PACK_24b_RGB_YUV444_YUV422; | ||
748 | |||
749 | hdmi_wp_video_config_format(ip_data, &video_format); | ||
750 | |||
751 | video_interface.vsp = cfg->timings.vsync_pol; | ||
752 | video_interface.hsp = cfg->timings.hsync_pol; | ||
753 | video_interface.interlacing = cfg->interlace; | ||
754 | video_interface.tm = 1 ; /* HDMI_TIMING_MASTER_24BIT */ | ||
755 | |||
756 | hdmi_wp_video_config_interface(ip_data, &video_interface); | ||
757 | |||
758 | /* | ||
759 | * configure core video part | ||
760 | * set software reset in the core | ||
761 | */ | ||
762 | hdmi_core_swreset_assert(ip_data); | ||
763 | |||
764 | /* power down off */ | ||
765 | hdmi_core_powerdown_disable(ip_data); | ||
766 | |||
767 | v_core_cfg.pkt_mode = HDMI_PACKETMODE24BITPERPIXEL; | ||
768 | v_core_cfg.hdmi_dvi = cfg->cm.mode; | ||
769 | |||
770 | hdmi_core_video_config(ip_data, &v_core_cfg); | ||
771 | |||
772 | /* release software reset in the core */ | ||
773 | hdmi_core_swreset_release(ip_data); | ||
774 | |||
775 | /* | ||
776 | * configure packet | ||
777 | * info frame video see doc CEA861-D page 65 | ||
778 | */ | ||
779 | avi_cfg.db1_format = HDMI_INFOFRAME_AVI_DB1Y_RGB; | ||
780 | avi_cfg.db1_active_info = | ||
781 | HDMI_INFOFRAME_AVI_DB1A_ACTIVE_FORMAT_OFF; | ||
782 | avi_cfg.db1_bar_info_dv = HDMI_INFOFRAME_AVI_DB1B_NO; | ||
783 | avi_cfg.db1_scan_info = HDMI_INFOFRAME_AVI_DB1S_0; | ||
784 | avi_cfg.db2_colorimetry = HDMI_INFOFRAME_AVI_DB2C_NO; | ||
785 | avi_cfg.db2_aspect_ratio = HDMI_INFOFRAME_AVI_DB2M_NO; | ||
786 | avi_cfg.db2_active_fmt_ar = HDMI_INFOFRAME_AVI_DB2R_SAME; | ||
787 | avi_cfg.db3_itc = HDMI_INFOFRAME_AVI_DB3ITC_NO; | ||
788 | avi_cfg.db3_ec = HDMI_INFOFRAME_AVI_DB3EC_XVYUV601; | ||
789 | avi_cfg.db3_q_range = HDMI_INFOFRAME_AVI_DB3Q_DEFAULT; | ||
790 | avi_cfg.db3_nup_scaling = HDMI_INFOFRAME_AVI_DB3SC_NO; | ||
791 | avi_cfg.db4_videocode = cfg->cm.code; | ||
792 | avi_cfg.db5_pixel_repeat = HDMI_INFOFRAME_AVI_DB5PR_NO; | ||
793 | avi_cfg.db6_7_line_eoftop = 0; | ||
794 | avi_cfg.db8_9_line_sofbottom = 0; | ||
795 | avi_cfg.db10_11_pixel_eofleft = 0; | ||
796 | avi_cfg.db12_13_pixel_sofright = 0; | ||
797 | |||
798 | hdmi_core_aux_infoframe_avi_config(ip_data, avi_cfg); | ||
799 | |||
800 | /* enable/repeat the infoframe */ | ||
801 | repeat_cfg.avi_infoframe = HDMI_PACKETENABLE; | ||
802 | repeat_cfg.avi_infoframe_repeat = HDMI_PACKETREPEATON; | ||
803 | /* wakeup */ | ||
804 | repeat_cfg.audio_pkt = HDMI_PACKETENABLE; | ||
805 | repeat_cfg.audio_pkt_repeat = HDMI_PACKETREPEATON; | ||
806 | hdmi_core_av_packet_config(ip_data, repeat_cfg); | ||
807 | } | ||
808 | |||
809 | void ti_hdmi_4xxx_wp_dump(struct hdmi_ip_data *ip_data, struct seq_file *s) | ||
810 | { | ||
811 | #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r,\ | ||
812 | hdmi_read_reg(hdmi_wp_base(ip_data), r)) | ||
813 | |||
814 | DUMPREG(HDMI_WP_REVISION); | ||
815 | DUMPREG(HDMI_WP_SYSCONFIG); | ||
816 | DUMPREG(HDMI_WP_IRQSTATUS_RAW); | ||
817 | DUMPREG(HDMI_WP_IRQSTATUS); | ||
818 | DUMPREG(HDMI_WP_PWR_CTRL); | ||
819 | DUMPREG(HDMI_WP_IRQENABLE_SET); | ||
820 | DUMPREG(HDMI_WP_VIDEO_CFG); | ||
821 | DUMPREG(HDMI_WP_VIDEO_SIZE); | ||
822 | DUMPREG(HDMI_WP_VIDEO_TIMING_H); | ||
823 | DUMPREG(HDMI_WP_VIDEO_TIMING_V); | ||
824 | DUMPREG(HDMI_WP_WP_CLK); | ||
825 | DUMPREG(HDMI_WP_AUDIO_CFG); | ||
826 | DUMPREG(HDMI_WP_AUDIO_CFG2); | ||
827 | DUMPREG(HDMI_WP_AUDIO_CTRL); | ||
828 | DUMPREG(HDMI_WP_AUDIO_DATA); | ||
829 | } | ||
830 | |||
831 | void ti_hdmi_4xxx_pll_dump(struct hdmi_ip_data *ip_data, struct seq_file *s) | ||
832 | { | ||
833 | #define DUMPPLL(r) seq_printf(s, "%-35s %08x\n", #r,\ | ||
834 | hdmi_read_reg(hdmi_pll_base(ip_data), r)) | ||
835 | |||
836 | DUMPPLL(PLLCTRL_PLL_CONTROL); | ||
837 | DUMPPLL(PLLCTRL_PLL_STATUS); | ||
838 | DUMPPLL(PLLCTRL_PLL_GO); | ||
839 | DUMPPLL(PLLCTRL_CFG1); | ||
840 | DUMPPLL(PLLCTRL_CFG2); | ||
841 | DUMPPLL(PLLCTRL_CFG3); | ||
842 | DUMPPLL(PLLCTRL_CFG4); | ||
843 | } | ||
844 | |||
845 | void ti_hdmi_4xxx_core_dump(struct hdmi_ip_data *ip_data, struct seq_file *s) | ||
846 | { | ||
847 | int i; | ||
848 | |||
849 | #define CORE_REG(i, name) name(i) | ||
850 | #define DUMPCORE(r) seq_printf(s, "%-35s %08x\n", #r,\ | ||
851 | hdmi_read_reg(hdmi_pll_base(ip_data), r)) | ||
852 | #define DUMPCOREAV(i, r) seq_printf(s, "%s[%d]%*s %08x\n", #r, i, \ | ||
853 | (i < 10) ? 32 - strlen(#r) : 31 - strlen(#r), " ", \ | ||
854 | hdmi_read_reg(hdmi_pll_base(ip_data), CORE_REG(i, r))) | ||
855 | |||
856 | DUMPCORE(HDMI_CORE_SYS_VND_IDL); | ||
857 | DUMPCORE(HDMI_CORE_SYS_DEV_IDL); | ||
858 | DUMPCORE(HDMI_CORE_SYS_DEV_IDH); | ||
859 | DUMPCORE(HDMI_CORE_SYS_DEV_REV); | ||
860 | DUMPCORE(HDMI_CORE_SYS_SRST); | ||
861 | DUMPCORE(HDMI_CORE_CTRL1); | ||
862 | DUMPCORE(HDMI_CORE_SYS_SYS_STAT); | ||
863 | DUMPCORE(HDMI_CORE_SYS_VID_ACEN); | ||
864 | DUMPCORE(HDMI_CORE_SYS_VID_MODE); | ||
865 | DUMPCORE(HDMI_CORE_SYS_INTR_STATE); | ||
866 | DUMPCORE(HDMI_CORE_SYS_INTR1); | ||
867 | DUMPCORE(HDMI_CORE_SYS_INTR2); | ||
868 | DUMPCORE(HDMI_CORE_SYS_INTR3); | ||
869 | DUMPCORE(HDMI_CORE_SYS_INTR4); | ||
870 | DUMPCORE(HDMI_CORE_SYS_UMASK1); | ||
871 | DUMPCORE(HDMI_CORE_SYS_TMDS_CTRL); | ||
872 | DUMPCORE(HDMI_CORE_SYS_DE_DLY); | ||
873 | DUMPCORE(HDMI_CORE_SYS_DE_CTRL); | ||
874 | DUMPCORE(HDMI_CORE_SYS_DE_TOP); | ||
875 | DUMPCORE(HDMI_CORE_SYS_DE_CNTL); | ||
876 | DUMPCORE(HDMI_CORE_SYS_DE_CNTH); | ||
877 | DUMPCORE(HDMI_CORE_SYS_DE_LINL); | ||
878 | DUMPCORE(HDMI_CORE_SYS_DE_LINH_1); | ||
879 | |||
880 | DUMPCORE(HDMI_CORE_DDC_CMD); | ||
881 | DUMPCORE(HDMI_CORE_DDC_STATUS); | ||
882 | DUMPCORE(HDMI_CORE_DDC_ADDR); | ||
883 | DUMPCORE(HDMI_CORE_DDC_OFFSET); | ||
884 | DUMPCORE(HDMI_CORE_DDC_COUNT1); | ||
885 | DUMPCORE(HDMI_CORE_DDC_COUNT2); | ||
886 | DUMPCORE(HDMI_CORE_DDC_DATA); | ||
887 | DUMPCORE(HDMI_CORE_DDC_SEGM); | ||
888 | |||
889 | DUMPCORE(HDMI_CORE_AV_HDMI_CTRL); | ||
890 | DUMPCORE(HDMI_CORE_AV_DPD); | ||
891 | DUMPCORE(HDMI_CORE_AV_PB_CTRL1); | ||
892 | DUMPCORE(HDMI_CORE_AV_PB_CTRL2); | ||
893 | DUMPCORE(HDMI_CORE_AV_AVI_TYPE); | ||
894 | DUMPCORE(HDMI_CORE_AV_AVI_VERS); | ||
895 | DUMPCORE(HDMI_CORE_AV_AVI_LEN); | ||
896 | DUMPCORE(HDMI_CORE_AV_AVI_CHSUM); | ||
897 | |||
898 | for (i = 0; i < HDMI_CORE_AV_AVI_DBYTE_NELEMS; i++) | ||
899 | DUMPCOREAV(i, HDMI_CORE_AV_AVI_DBYTE); | ||
900 | |||
901 | for (i = 0; i < HDMI_CORE_AV_SPD_DBYTE_NELEMS; i++) | ||
902 | DUMPCOREAV(i, HDMI_CORE_AV_SPD_DBYTE); | ||
903 | |||
904 | for (i = 0; i < HDMI_CORE_AV_AUD_DBYTE_NELEMS; i++) | ||
905 | DUMPCOREAV(i, HDMI_CORE_AV_AUD_DBYTE); | ||
906 | |||
907 | for (i = 0; i < HDMI_CORE_AV_MPEG_DBYTE_NELEMS; i++) | ||
908 | DUMPCOREAV(i, HDMI_CORE_AV_MPEG_DBYTE); | ||
909 | |||
910 | for (i = 0; i < HDMI_CORE_AV_GEN_DBYTE_NELEMS; i++) | ||
911 | DUMPCOREAV(i, HDMI_CORE_AV_GEN_DBYTE); | ||
912 | |||
913 | for (i = 0; i < HDMI_CORE_AV_GEN2_DBYTE_NELEMS; i++) | ||
914 | DUMPCOREAV(i, HDMI_CORE_AV_GEN2_DBYTE); | ||
915 | |||
916 | DUMPCORE(HDMI_CORE_AV_ACR_CTRL); | ||
917 | DUMPCORE(HDMI_CORE_AV_FREQ_SVAL); | ||
918 | DUMPCORE(HDMI_CORE_AV_N_SVAL1); | ||
919 | DUMPCORE(HDMI_CORE_AV_N_SVAL2); | ||
920 | DUMPCORE(HDMI_CORE_AV_N_SVAL3); | ||
921 | DUMPCORE(HDMI_CORE_AV_CTS_SVAL1); | ||
922 | DUMPCORE(HDMI_CORE_AV_CTS_SVAL2); | ||
923 | DUMPCORE(HDMI_CORE_AV_CTS_SVAL3); | ||
924 | DUMPCORE(HDMI_CORE_AV_CTS_HVAL1); | ||
925 | DUMPCORE(HDMI_CORE_AV_CTS_HVAL2); | ||
926 | DUMPCORE(HDMI_CORE_AV_CTS_HVAL3); | ||
927 | DUMPCORE(HDMI_CORE_AV_AUD_MODE); | ||
928 | DUMPCORE(HDMI_CORE_AV_SPDIF_CTRL); | ||
929 | DUMPCORE(HDMI_CORE_AV_HW_SPDIF_FS); | ||
930 | DUMPCORE(HDMI_CORE_AV_SWAP_I2S); | ||
931 | DUMPCORE(HDMI_CORE_AV_SPDIF_ERTH); | ||
932 | DUMPCORE(HDMI_CORE_AV_I2S_IN_MAP); | ||
933 | DUMPCORE(HDMI_CORE_AV_I2S_IN_CTRL); | ||
934 | DUMPCORE(HDMI_CORE_AV_I2S_CHST0); | ||
935 | DUMPCORE(HDMI_CORE_AV_I2S_CHST1); | ||
936 | DUMPCORE(HDMI_CORE_AV_I2S_CHST2); | ||
937 | DUMPCORE(HDMI_CORE_AV_I2S_CHST4); | ||
938 | DUMPCORE(HDMI_CORE_AV_I2S_CHST5); | ||
939 | DUMPCORE(HDMI_CORE_AV_ASRC); | ||
940 | DUMPCORE(HDMI_CORE_AV_I2S_IN_LEN); | ||
941 | DUMPCORE(HDMI_CORE_AV_HDMI_CTRL); | ||
942 | DUMPCORE(HDMI_CORE_AV_AUDO_TXSTAT); | ||
943 | DUMPCORE(HDMI_CORE_AV_AUD_PAR_BUSCLK_1); | ||
944 | DUMPCORE(HDMI_CORE_AV_AUD_PAR_BUSCLK_2); | ||
945 | DUMPCORE(HDMI_CORE_AV_AUD_PAR_BUSCLK_3); | ||
946 | DUMPCORE(HDMI_CORE_AV_TEST_TXCTRL); | ||
947 | DUMPCORE(HDMI_CORE_AV_DPD); | ||
948 | DUMPCORE(HDMI_CORE_AV_PB_CTRL1); | ||
949 | DUMPCORE(HDMI_CORE_AV_PB_CTRL2); | ||
950 | DUMPCORE(HDMI_CORE_AV_AVI_TYPE); | ||
951 | DUMPCORE(HDMI_CORE_AV_AVI_VERS); | ||
952 | DUMPCORE(HDMI_CORE_AV_AVI_LEN); | ||
953 | DUMPCORE(HDMI_CORE_AV_AVI_CHSUM); | ||
954 | DUMPCORE(HDMI_CORE_AV_SPD_TYPE); | ||
955 | DUMPCORE(HDMI_CORE_AV_SPD_VERS); | ||
956 | DUMPCORE(HDMI_CORE_AV_SPD_LEN); | ||
957 | DUMPCORE(HDMI_CORE_AV_SPD_CHSUM); | ||
958 | DUMPCORE(HDMI_CORE_AV_AUDIO_TYPE); | ||
959 | DUMPCORE(HDMI_CORE_AV_AUDIO_VERS); | ||
960 | DUMPCORE(HDMI_CORE_AV_AUDIO_LEN); | ||
961 | DUMPCORE(HDMI_CORE_AV_AUDIO_CHSUM); | ||
962 | DUMPCORE(HDMI_CORE_AV_MPEG_TYPE); | ||
963 | DUMPCORE(HDMI_CORE_AV_MPEG_VERS); | ||
964 | DUMPCORE(HDMI_CORE_AV_MPEG_LEN); | ||
965 | DUMPCORE(HDMI_CORE_AV_MPEG_CHSUM); | ||
966 | DUMPCORE(HDMI_CORE_AV_CP_BYTE1); | ||
967 | DUMPCORE(HDMI_CORE_AV_CEC_ADDR_ID); | ||
968 | } | ||
969 | |||
970 | void ti_hdmi_4xxx_phy_dump(struct hdmi_ip_data *ip_data, struct seq_file *s) | ||
971 | { | ||
972 | #define DUMPPHY(r) seq_printf(s, "%-35s %08x\n", #r,\ | ||
973 | hdmi_read_reg(hdmi_phy_base(ip_data), r)) | ||
974 | |||
975 | DUMPPHY(HDMI_TXPHY_TX_CTRL); | ||
976 | DUMPPHY(HDMI_TXPHY_DIGITAL_CTRL); | ||
977 | DUMPPHY(HDMI_TXPHY_POWER_CTRL); | ||
978 | DUMPPHY(HDMI_TXPHY_PAD_CFG_CTRL); | ||
979 | } | ||
980 | |||
981 | #if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \ | ||
982 | defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE) | ||
983 | void hdmi_wp_audio_config_format(struct hdmi_ip_data *ip_data, | ||
984 | struct hdmi_audio_format *aud_fmt) | ||
985 | { | ||
986 | u32 r; | ||
987 | |||
988 | DSSDBG("Enter hdmi_wp_audio_config_format\n"); | ||
989 | |||
990 | r = hdmi_read_reg(hdmi_wp_base(ip_data), HDMI_WP_AUDIO_CFG); | ||
991 | r = FLD_MOD(r, aud_fmt->stereo_channels, 26, 24); | ||
992 | r = FLD_MOD(r, aud_fmt->active_chnnls_msk, 23, 16); | ||
993 | r = FLD_MOD(r, aud_fmt->en_sig_blk_strt_end, 5, 5); | ||
994 | r = FLD_MOD(r, aud_fmt->type, 4, 4); | ||
995 | r = FLD_MOD(r, aud_fmt->justification, 3, 3); | ||
996 | r = FLD_MOD(r, aud_fmt->sample_order, 2, 2); | ||
997 | r = FLD_MOD(r, aud_fmt->samples_per_word, 1, 1); | ||
998 | r = FLD_MOD(r, aud_fmt->sample_size, 0, 0); | ||
999 | hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_AUDIO_CFG, r); | ||
1000 | } | ||
1001 | |||
1002 | void hdmi_wp_audio_config_dma(struct hdmi_ip_data *ip_data, | ||
1003 | struct hdmi_audio_dma *aud_dma) | ||
1004 | { | ||
1005 | u32 r; | ||
1006 | |||
1007 | DSSDBG("Enter hdmi_wp_audio_config_dma\n"); | ||
1008 | |||
1009 | r = hdmi_read_reg(hdmi_wp_base(ip_data), HDMI_WP_AUDIO_CFG2); | ||
1010 | r = FLD_MOD(r, aud_dma->transfer_size, 15, 8); | ||
1011 | r = FLD_MOD(r, aud_dma->block_size, 7, 0); | ||
1012 | hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_AUDIO_CFG2, r); | ||
1013 | |||
1014 | r = hdmi_read_reg(hdmi_wp_base(ip_data), HDMI_WP_AUDIO_CTRL); | ||
1015 | r = FLD_MOD(r, aud_dma->mode, 9, 9); | ||
1016 | r = FLD_MOD(r, aud_dma->fifo_threshold, 8, 0); | ||
1017 | hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_AUDIO_CTRL, r); | ||
1018 | } | ||
1019 | |||
1020 | void hdmi_core_audio_config(struct hdmi_ip_data *ip_data, | ||
1021 | struct hdmi_core_audio_config *cfg) | ||
1022 | { | ||
1023 | u32 r; | ||
1024 | void __iomem *av_base = hdmi_av_base(ip_data); | ||
1025 | |||
1026 | /* audio clock recovery parameters */ | ||
1027 | r = hdmi_read_reg(av_base, HDMI_CORE_AV_ACR_CTRL); | ||
1028 | r = FLD_MOD(r, cfg->use_mclk, 2, 2); | ||
1029 | r = FLD_MOD(r, cfg->en_acr_pkt, 1, 1); | ||
1030 | r = FLD_MOD(r, cfg->cts_mode, 0, 0); | ||
1031 | hdmi_write_reg(av_base, HDMI_CORE_AV_ACR_CTRL, r); | ||
1032 | |||
1033 | REG_FLD_MOD(av_base, HDMI_CORE_AV_N_SVAL1, cfg->n, 7, 0); | ||
1034 | REG_FLD_MOD(av_base, HDMI_CORE_AV_N_SVAL2, cfg->n >> 8, 7, 0); | ||
1035 | REG_FLD_MOD(av_base, HDMI_CORE_AV_N_SVAL3, cfg->n >> 16, 7, 0); | ||
1036 | |||
1037 | if (cfg->cts_mode == HDMI_AUDIO_CTS_MODE_SW) { | ||
1038 | REG_FLD_MOD(av_base, HDMI_CORE_AV_CTS_SVAL1, cfg->cts, 7, 0); | ||
1039 | REG_FLD_MOD(av_base, | ||
1040 | HDMI_CORE_AV_CTS_SVAL2, cfg->cts >> 8, 7, 0); | ||
1041 | REG_FLD_MOD(av_base, | ||
1042 | HDMI_CORE_AV_CTS_SVAL3, cfg->cts >> 16, 7, 0); | ||
1043 | } else { | ||
1044 | /* | ||
1045 | * HDMI IP uses this configuration to divide the MCLK to | ||
1046 | * update CTS value. | ||
1047 | */ | ||
1048 | REG_FLD_MOD(av_base, | ||
1049 | HDMI_CORE_AV_FREQ_SVAL, cfg->mclk_mode, 2, 0); | ||
1050 | |||
1051 | /* Configure clock for audio packets */ | ||
1052 | REG_FLD_MOD(av_base, HDMI_CORE_AV_AUD_PAR_BUSCLK_1, | ||
1053 | cfg->aud_par_busclk, 7, 0); | ||
1054 | REG_FLD_MOD(av_base, HDMI_CORE_AV_AUD_PAR_BUSCLK_2, | ||
1055 | (cfg->aud_par_busclk >> 8), 7, 0); | ||
1056 | REG_FLD_MOD(av_base, HDMI_CORE_AV_AUD_PAR_BUSCLK_3, | ||
1057 | (cfg->aud_par_busclk >> 16), 7, 0); | ||
1058 | } | ||
1059 | |||
1060 | /* Override of SPDIF sample frequency with value in I2S_CHST4 */ | ||
1061 | REG_FLD_MOD(av_base, HDMI_CORE_AV_SPDIF_CTRL, | ||
1062 | cfg->fs_override, 1, 1); | ||
1063 | |||
1064 | /* I2S parameters */ | ||
1065 | REG_FLD_MOD(av_base, HDMI_CORE_AV_I2S_CHST4, | ||
1066 | cfg->freq_sample, 3, 0); | ||
1067 | |||
1068 | r = hdmi_read_reg(av_base, HDMI_CORE_AV_I2S_IN_CTRL); | ||
1069 | r = FLD_MOD(r, cfg->i2s_cfg.en_high_bitrate_aud, 7, 7); | ||
1070 | r = FLD_MOD(r, cfg->i2s_cfg.sck_edge_mode, 6, 6); | ||
1071 | r = FLD_MOD(r, cfg->i2s_cfg.cbit_order, 5, 5); | ||
1072 | r = FLD_MOD(r, cfg->i2s_cfg.vbit, 4, 4); | ||
1073 | r = FLD_MOD(r, cfg->i2s_cfg.ws_polarity, 3, 3); | ||
1074 | r = FLD_MOD(r, cfg->i2s_cfg.justification, 2, 2); | ||
1075 | r = FLD_MOD(r, cfg->i2s_cfg.direction, 1, 1); | ||
1076 | r = FLD_MOD(r, cfg->i2s_cfg.shift, 0, 0); | ||
1077 | hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_IN_CTRL, r); | ||
1078 | |||
1079 | r = hdmi_read_reg(av_base, HDMI_CORE_AV_I2S_CHST5); | ||
1080 | r = FLD_MOD(r, cfg->freq_sample, 7, 4); | ||
1081 | r = FLD_MOD(r, cfg->i2s_cfg.word_length, 3, 1); | ||
1082 | r = FLD_MOD(r, cfg->i2s_cfg.word_max_length, 0, 0); | ||
1083 | hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_CHST5, r); | ||
1084 | |||
1085 | REG_FLD_MOD(av_base, HDMI_CORE_AV_I2S_IN_LEN, | ||
1086 | cfg->i2s_cfg.in_length_bits, 3, 0); | ||
1087 | |||
1088 | /* Audio channels and mode parameters */ | ||
1089 | REG_FLD_MOD(av_base, HDMI_CORE_AV_HDMI_CTRL, cfg->layout, 2, 1); | ||
1090 | r = hdmi_read_reg(av_base, HDMI_CORE_AV_AUD_MODE); | ||
1091 | r = FLD_MOD(r, cfg->i2s_cfg.active_sds, 7, 4); | ||
1092 | r = FLD_MOD(r, cfg->en_dsd_audio, 3, 3); | ||
1093 | r = FLD_MOD(r, cfg->en_parallel_aud_input, 2, 2); | ||
1094 | r = FLD_MOD(r, cfg->en_spdif, 1, 1); | ||
1095 | hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_MODE, r); | ||
1096 | } | ||
1097 | |||
1098 | void hdmi_core_audio_infoframe_config(struct hdmi_ip_data *ip_data, | ||
1099 | struct hdmi_core_infoframe_audio *info_aud) | ||
1100 | { | ||
1101 | u8 val; | ||
1102 | u8 sum = 0, checksum = 0; | ||
1103 | void __iomem *av_base = hdmi_av_base(ip_data); | ||
1104 | |||
1105 | /* | ||
1106 | * Set audio info frame type, version and length as | ||
1107 | * described in HDMI 1.4a Section 8.2.2 specification. | ||
1108 | * Checksum calculation is defined in Section 5.3.5. | ||
1109 | */ | ||
1110 | hdmi_write_reg(av_base, HDMI_CORE_AV_AUDIO_TYPE, 0x84); | ||
1111 | hdmi_write_reg(av_base, HDMI_CORE_AV_AUDIO_VERS, 0x01); | ||
1112 | hdmi_write_reg(av_base, HDMI_CORE_AV_AUDIO_LEN, 0x0a); | ||
1113 | sum += 0x84 + 0x001 + 0x00a; | ||
1114 | |||
1115 | val = (info_aud->db1_coding_type << 4) | ||
1116 | | (info_aud->db1_channel_count - 1); | ||
1117 | hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(0), val); | ||
1118 | sum += val; | ||
1119 | |||
1120 | val = (info_aud->db2_sample_freq << 2) | info_aud->db2_sample_size; | ||
1121 | hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(1), val); | ||
1122 | sum += val; | ||
1123 | |||
1124 | hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(2), 0x00); | ||
1125 | |||
1126 | val = info_aud->db4_channel_alloc; | ||
1127 | hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(3), val); | ||
1128 | sum += val; | ||
1129 | |||
1130 | val = (info_aud->db5_downmix_inh << 7) | (info_aud->db5_lsv << 3); | ||
1131 | hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(4), val); | ||
1132 | sum += val; | ||
1133 | |||
1134 | hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(5), 0x00); | ||
1135 | hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(6), 0x00); | ||
1136 | hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(7), 0x00); | ||
1137 | hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(8), 0x00); | ||
1138 | hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(9), 0x00); | ||
1139 | |||
1140 | checksum = 0x100 - sum; | ||
1141 | hdmi_write_reg(av_base, | ||
1142 | HDMI_CORE_AV_AUDIO_CHSUM, checksum); | ||
1143 | |||
1144 | /* | ||
1145 | * TODO: Add MPEG and SPD enable and repeat cfg when EDID parsing | ||
1146 | * is available. | ||
1147 | */ | ||
1148 | } | ||
1149 | |||
1150 | int hdmi_config_audio_acr(struct hdmi_ip_data *ip_data, | ||
1151 | u32 sample_freq, u32 *n, u32 *cts) | ||
1152 | { | ||
1153 | u32 r; | ||
1154 | u32 deep_color = 0; | ||
1155 | u32 pclk = ip_data->cfg.timings.timings.pixel_clock; | ||
1156 | |||
1157 | if (n == NULL || cts == NULL) | ||
1158 | return -EINVAL; | ||
1159 | /* | ||
1160 | * Obtain current deep color configuration. This needed | ||
1161 | * to calculate the TMDS clock based on the pixel clock. | ||
1162 | */ | ||
1163 | r = REG_GET(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_CFG, 1, 0); | ||
1164 | switch (r) { | ||
1165 | case 1: /* No deep color selected */ | ||
1166 | deep_color = 100; | ||
1167 | break; | ||
1168 | case 2: /* 10-bit deep color selected */ | ||
1169 | deep_color = 125; | ||
1170 | break; | ||
1171 | case 3: /* 12-bit deep color selected */ | ||
1172 | deep_color = 150; | ||
1173 | break; | ||
1174 | default: | ||
1175 | return -EINVAL; | ||
1176 | } | ||
1177 | |||
1178 | switch (sample_freq) { | ||
1179 | case 32000: | ||
1180 | if ((deep_color == 125) && ((pclk == 54054) | ||
1181 | || (pclk == 74250))) | ||
1182 | *n = 8192; | ||
1183 | else | ||
1184 | *n = 4096; | ||
1185 | break; | ||
1186 | case 44100: | ||
1187 | *n = 6272; | ||
1188 | break; | ||
1189 | case 48000: | ||
1190 | if ((deep_color == 125) && ((pclk == 54054) | ||
1191 | || (pclk == 74250))) | ||
1192 | *n = 8192; | ||
1193 | else | ||
1194 | *n = 6144; | ||
1195 | break; | ||
1196 | default: | ||
1197 | *n = 0; | ||
1198 | return -EINVAL; | ||
1199 | } | ||
1200 | |||
1201 | /* Calculate CTS. See HDMI 1.3a or 1.4a specifications */ | ||
1202 | *cts = pclk * (*n / 128) * deep_color / (sample_freq / 10); | ||
1203 | |||
1204 | return 0; | ||
1205 | } | ||
1206 | |||
1207 | int hdmi_audio_trigger(struct hdmi_ip_data *ip_data, | ||
1208 | struct snd_pcm_substream *substream, int cmd, | ||
1209 | struct snd_soc_dai *dai) | ||
1210 | { | ||
1211 | int err = 0; | ||
1212 | switch (cmd) { | ||
1213 | case SNDRV_PCM_TRIGGER_START: | ||
1214 | case SNDRV_PCM_TRIGGER_RESUME: | ||
1215 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
1216 | REG_FLD_MOD(hdmi_av_base(ip_data), | ||
1217 | HDMI_CORE_AV_AUD_MODE, 1, 0, 0); | ||
1218 | REG_FLD_MOD(hdmi_wp_base(ip_data), | ||
1219 | HDMI_WP_AUDIO_CTRL, 1, 31, 31); | ||
1220 | REG_FLD_MOD(hdmi_wp_base(ip_data), | ||
1221 | HDMI_WP_AUDIO_CTRL, 1, 30, 30); | ||
1222 | break; | ||
1223 | |||
1224 | case SNDRV_PCM_TRIGGER_STOP: | ||
1225 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
1226 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
1227 | REG_FLD_MOD(hdmi_av_base(ip_data), | ||
1228 | HDMI_CORE_AV_AUD_MODE, 0, 0, 0); | ||
1229 | REG_FLD_MOD(hdmi_wp_base(ip_data), | ||
1230 | HDMI_WP_AUDIO_CTRL, 0, 30, 30); | ||
1231 | REG_FLD_MOD(hdmi_wp_base(ip_data), | ||
1232 | HDMI_WP_AUDIO_CTRL, 0, 31, 31); | ||
1233 | break; | ||
1234 | default: | ||
1235 | err = -EINVAL; | ||
1236 | } | ||
1237 | return err; | ||
1238 | } | ||
1239 | #endif | ||
diff --git a/drivers/video/omap2/dss/hdmi.h b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h index c885f9cb0659..204095632d27 100644 --- a/drivers/video/omap2/dss/hdmi.h +++ b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * hdmi.h | 2 | * ti_hdmi_4xxx_ip.h |
3 | * | 3 | * |
4 | * HDMI driver definition for TI OMAP4 processors. | 4 | * HDMI header definition for DM81xx, DM38xx, TI OMAP4 etc processors. |
5 | * | 5 | * |
6 | * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/ | 6 | * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/ |
7 | * | 7 | * |
@@ -18,202 +18,177 @@ | |||
18 | * this program. If not, see <http://www.gnu.org/licenses/>. | 18 | * this program. If not, see <http://www.gnu.org/licenses/>. |
19 | */ | 19 | */ |
20 | 20 | ||
21 | #ifndef _OMAP4_DSS_HDMI_H_ | 21 | #ifndef _HDMI_TI_4xxx_H_ |
22 | #define _OMAP4_DSS_HDMI_H_ | 22 | #define _HDMI_TI_4xxx_H_ |
23 | 23 | ||
24 | #include <linux/string.h> | 24 | #include <linux/string.h> |
25 | #include <video/omapdss.h> | 25 | #include <video/omapdss.h> |
26 | 26 | #include "ti_hdmi.h" | |
27 | #define HDMI_WP 0x0 | 27 | #if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \ |
28 | #define HDMI_CORE_SYS 0x400 | 28 | defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE) |
29 | #define HDMI_CORE_AV 0x900 | 29 | #include <sound/soc.h> |
30 | #define HDMI_PLLCTRL 0x200 | 30 | #include <sound/pcm_params.h> |
31 | #define HDMI_PHY 0x300 | 31 | #endif |
32 | |||
33 | struct hdmi_reg { u16 idx; }; | ||
34 | |||
35 | #define HDMI_REG(idx) ((const struct hdmi_reg) { idx }) | ||
36 | 32 | ||
37 | /* HDMI Wrapper */ | 33 | /* HDMI Wrapper */ |
38 | #define HDMI_WP_REG(idx) HDMI_REG(HDMI_WP + idx) | 34 | |
39 | 35 | #define HDMI_WP_REVISION 0x0 | |
40 | #define HDMI_WP_REVISION HDMI_WP_REG(0x0) | 36 | #define HDMI_WP_SYSCONFIG 0x10 |
41 | #define HDMI_WP_SYSCONFIG HDMI_WP_REG(0x10) | 37 | #define HDMI_WP_IRQSTATUS_RAW 0x24 |
42 | #define HDMI_WP_IRQSTATUS_RAW HDMI_WP_REG(0x24) | 38 | #define HDMI_WP_IRQSTATUS 0x28 |
43 | #define HDMI_WP_IRQSTATUS HDMI_WP_REG(0x28) | 39 | #define HDMI_WP_PWR_CTRL 0x40 |
44 | #define HDMI_WP_PWR_CTRL HDMI_WP_REG(0x40) | 40 | #define HDMI_WP_IRQENABLE_SET 0x2C |
45 | #define HDMI_WP_IRQENABLE_SET HDMI_WP_REG(0x2C) | 41 | #define HDMI_WP_VIDEO_CFG 0x50 |
46 | #define HDMI_WP_VIDEO_CFG HDMI_WP_REG(0x50) | 42 | #define HDMI_WP_VIDEO_SIZE 0x60 |
47 | #define HDMI_WP_VIDEO_SIZE HDMI_WP_REG(0x60) | 43 | #define HDMI_WP_VIDEO_TIMING_H 0x68 |
48 | #define HDMI_WP_VIDEO_TIMING_H HDMI_WP_REG(0x68) | 44 | #define HDMI_WP_VIDEO_TIMING_V 0x6C |
49 | #define HDMI_WP_VIDEO_TIMING_V HDMI_WP_REG(0x6C) | 45 | #define HDMI_WP_WP_CLK 0x70 |
50 | #define HDMI_WP_WP_CLK HDMI_WP_REG(0x70) | 46 | #define HDMI_WP_AUDIO_CFG 0x80 |
51 | #define HDMI_WP_AUDIO_CFG HDMI_WP_REG(0x80) | 47 | #define HDMI_WP_AUDIO_CFG2 0x84 |
52 | #define HDMI_WP_AUDIO_CFG2 HDMI_WP_REG(0x84) | 48 | #define HDMI_WP_AUDIO_CTRL 0x88 |
53 | #define HDMI_WP_AUDIO_CTRL HDMI_WP_REG(0x88) | 49 | #define HDMI_WP_AUDIO_DATA 0x8C |
54 | #define HDMI_WP_AUDIO_DATA HDMI_WP_REG(0x8C) | ||
55 | 50 | ||
56 | /* HDMI IP Core System */ | 51 | /* HDMI IP Core System */ |
57 | #define HDMI_CORE_SYS_REG(idx) HDMI_REG(HDMI_CORE_SYS + idx) | 52 | |
58 | 53 | #define HDMI_CORE_SYS_VND_IDL 0x0 | |
59 | #define HDMI_CORE_SYS_VND_IDL HDMI_CORE_SYS_REG(0x0) | 54 | #define HDMI_CORE_SYS_DEV_IDL 0x8 |
60 | #define HDMI_CORE_SYS_DEV_IDL HDMI_CORE_SYS_REG(0x8) | 55 | #define HDMI_CORE_SYS_DEV_IDH 0xC |
61 | #define HDMI_CORE_SYS_DEV_IDH HDMI_CORE_SYS_REG(0xC) | 56 | #define HDMI_CORE_SYS_DEV_REV 0x10 |
62 | #define HDMI_CORE_SYS_DEV_REV HDMI_CORE_SYS_REG(0x10) | 57 | #define HDMI_CORE_SYS_SRST 0x14 |
63 | #define HDMI_CORE_SYS_SRST HDMI_CORE_SYS_REG(0x14) | 58 | #define HDMI_CORE_CTRL1 0x20 |
64 | #define HDMI_CORE_CTRL1 HDMI_CORE_SYS_REG(0x20) | 59 | #define HDMI_CORE_SYS_SYS_STAT 0x24 |
65 | #define HDMI_CORE_SYS_SYS_STAT HDMI_CORE_SYS_REG(0x24) | 60 | #define HDMI_CORE_SYS_VID_ACEN 0x124 |
66 | #define HDMI_CORE_SYS_VID_ACEN HDMI_CORE_SYS_REG(0x124) | 61 | #define HDMI_CORE_SYS_VID_MODE 0x128 |
67 | #define HDMI_CORE_SYS_VID_MODE HDMI_CORE_SYS_REG(0x128) | 62 | #define HDMI_CORE_SYS_INTR_STATE 0x1C0 |
68 | #define HDMI_CORE_SYS_INTR_STATE HDMI_CORE_SYS_REG(0x1C0) | 63 | #define HDMI_CORE_SYS_INTR1 0x1C4 |
69 | #define HDMI_CORE_SYS_INTR1 HDMI_CORE_SYS_REG(0x1C4) | 64 | #define HDMI_CORE_SYS_INTR2 0x1C8 |
70 | #define HDMI_CORE_SYS_INTR2 HDMI_CORE_SYS_REG(0x1C8) | 65 | #define HDMI_CORE_SYS_INTR3 0x1CC |
71 | #define HDMI_CORE_SYS_INTR3 HDMI_CORE_SYS_REG(0x1CC) | 66 | #define HDMI_CORE_SYS_INTR4 0x1D0 |
72 | #define HDMI_CORE_SYS_INTR4 HDMI_CORE_SYS_REG(0x1D0) | 67 | #define HDMI_CORE_SYS_UMASK1 0x1D4 |
73 | #define HDMI_CORE_SYS_UMASK1 HDMI_CORE_SYS_REG(0x1D4) | 68 | #define HDMI_CORE_SYS_TMDS_CTRL 0x208 |
74 | #define HDMI_CORE_SYS_TMDS_CTRL HDMI_CORE_SYS_REG(0x208) | 69 | #define HDMI_CORE_SYS_DE_DLY 0xC8 |
75 | #define HDMI_CORE_SYS_DE_DLY HDMI_CORE_SYS_REG(0xC8) | 70 | #define HDMI_CORE_SYS_DE_CTRL 0xCC |
76 | #define HDMI_CORE_SYS_DE_CTRL HDMI_CORE_SYS_REG(0xCC) | 71 | #define HDMI_CORE_SYS_DE_TOP 0xD0 |
77 | #define HDMI_CORE_SYS_DE_TOP HDMI_CORE_SYS_REG(0xD0) | 72 | #define HDMI_CORE_SYS_DE_CNTL 0xD8 |
78 | #define HDMI_CORE_SYS_DE_CNTL HDMI_CORE_SYS_REG(0xD8) | 73 | #define HDMI_CORE_SYS_DE_CNTH 0xDC |
79 | #define HDMI_CORE_SYS_DE_CNTH HDMI_CORE_SYS_REG(0xDC) | 74 | #define HDMI_CORE_SYS_DE_LINL 0xE0 |
80 | #define HDMI_CORE_SYS_DE_LINL HDMI_CORE_SYS_REG(0xE0) | 75 | #define HDMI_CORE_SYS_DE_LINH_1 0xE4 |
81 | #define HDMI_CORE_SYS_DE_LINH_1 HDMI_CORE_SYS_REG(0xE4) | ||
82 | #define HDMI_CORE_CTRL1_VEN_FOLLOWVSYNC 0x1 | 76 | #define HDMI_CORE_CTRL1_VEN_FOLLOWVSYNC 0x1 |
83 | #define HDMI_CORE_CTRL1_HEN_FOLLOWHSYNC 0x1 | 77 | #define HDMI_CORE_CTRL1_HEN_FOLLOWHSYNC 0x1 |
84 | #define HDMI_CORE_CTRL1_BSEL_24BITBUS 0x1 | 78 | #define HDMI_CORE_CTRL1_BSEL_24BITBUS 0x1 |
85 | #define HDMI_CORE_CTRL1_EDGE_RISINGEDGE 0x1 | 79 | #define HDMI_CORE_CTRL1_EDGE_RISINGEDGE 0x1 |
86 | 80 | ||
87 | /* HDMI DDC E-DID */ | 81 | /* HDMI DDC E-DID */ |
88 | #define HDMI_CORE_DDC_CMD HDMI_CORE_SYS_REG(0x3CC) | 82 | #define HDMI_CORE_DDC_CMD 0x3CC |
89 | #define HDMI_CORE_DDC_STATUS HDMI_CORE_SYS_REG(0x3C8) | 83 | #define HDMI_CORE_DDC_STATUS 0x3C8 |
90 | #define HDMI_CORE_DDC_ADDR HDMI_CORE_SYS_REG(0x3B4) | 84 | #define HDMI_CORE_DDC_ADDR 0x3B4 |
91 | #define HDMI_CORE_DDC_OFFSET HDMI_CORE_SYS_REG(0x3BC) | 85 | #define HDMI_CORE_DDC_OFFSET 0x3BC |
92 | #define HDMI_CORE_DDC_COUNT1 HDMI_CORE_SYS_REG(0x3C0) | 86 | #define HDMI_CORE_DDC_COUNT1 0x3C0 |
93 | #define HDMI_CORE_DDC_COUNT2 HDMI_CORE_SYS_REG(0x3C4) | 87 | #define HDMI_CORE_DDC_COUNT2 0x3C4 |
94 | #define HDMI_CORE_DDC_DATA HDMI_CORE_SYS_REG(0x3D0) | 88 | #define HDMI_CORE_DDC_DATA 0x3D0 |
95 | #define HDMI_CORE_DDC_SEGM HDMI_CORE_SYS_REG(0x3B8) | 89 | #define HDMI_CORE_DDC_SEGM 0x3B8 |
96 | 90 | ||
97 | /* HDMI IP Core Audio Video */ | 91 | /* HDMI IP Core Audio Video */ |
98 | #define HDMI_CORE_AV_REG(idx) HDMI_REG(HDMI_CORE_AV + idx) | 92 | |
99 | 93 | #define HDMI_CORE_AV_HDMI_CTRL 0xBC | |
100 | #define HDMI_CORE_AV_HDMI_CTRL HDMI_CORE_AV_REG(0xBC) | 94 | #define HDMI_CORE_AV_DPD 0xF4 |
101 | #define HDMI_CORE_AV_DPD HDMI_CORE_AV_REG(0xF4) | 95 | #define HDMI_CORE_AV_PB_CTRL1 0xF8 |
102 | #define HDMI_CORE_AV_PB_CTRL1 HDMI_CORE_AV_REG(0xF8) | 96 | #define HDMI_CORE_AV_PB_CTRL2 0xFC |
103 | #define HDMI_CORE_AV_PB_CTRL2 HDMI_CORE_AV_REG(0xFC) | 97 | #define HDMI_CORE_AV_AVI_TYPE 0x100 |
104 | #define HDMI_CORE_AV_AVI_TYPE HDMI_CORE_AV_REG(0x100) | 98 | #define HDMI_CORE_AV_AVI_VERS 0x104 |
105 | #define HDMI_CORE_AV_AVI_VERS HDMI_CORE_AV_REG(0x104) | 99 | #define HDMI_CORE_AV_AVI_LEN 0x108 |
106 | #define HDMI_CORE_AV_AVI_LEN HDMI_CORE_AV_REG(0x108) | 100 | #define HDMI_CORE_AV_AVI_CHSUM 0x10C |
107 | #define HDMI_CORE_AV_AVI_CHSUM HDMI_CORE_AV_REG(0x10C) | 101 | #define HDMI_CORE_AV_AVI_DBYTE(n) (n * 4 + 0x110) |
108 | #define HDMI_CORE_AV_AVI_DBYTE(n) HDMI_CORE_AV_REG(n * 4 + 0x110) | 102 | #define HDMI_CORE_AV_AVI_DBYTE_NELEMS 15 |
109 | #define HDMI_CORE_AV_AVI_DBYTE_NELEMS HDMI_CORE_AV_REG(15) | 103 | #define HDMI_CORE_AV_SPD_DBYTE(n) (n * 4 + 0x190) |
110 | #define HDMI_CORE_AV_SPD_DBYTE HDMI_CORE_AV_REG(0x190) | 104 | #define HDMI_CORE_AV_SPD_DBYTE_NELEMS 27 |
111 | #define HDMI_CORE_AV_SPD_DBYTE_NELEMS HDMI_CORE_AV_REG(27) | 105 | #define HDMI_CORE_AV_AUD_DBYTE(n) (n * 4 + 0x210) |
112 | #define HDMI_CORE_AV_AUD_DBYTE(n) HDMI_CORE_AV_REG(n * 4 + 0x210) | 106 | #define HDMI_CORE_AV_AUD_DBYTE_NELEMS 10 |
113 | #define HDMI_CORE_AV_AUD_DBYTE_NELEMS HDMI_CORE_AV_REG(10) | 107 | #define HDMI_CORE_AV_MPEG_DBYTE(n) (n * 4 + 0x290) |
114 | #define HDMI_CORE_AV_MPEG_DBYTE HDMI_CORE_AV_REG(0x290) | 108 | #define HDMI_CORE_AV_MPEG_DBYTE_NELEMS 27 |
115 | #define HDMI_CORE_AV_MPEG_DBYTE_NELEMS HDMI_CORE_AV_REG(27) | 109 | #define HDMI_CORE_AV_GEN_DBYTE(n) (n * 4 + 0x300) |
116 | #define HDMI_CORE_AV_GEN_DBYTE HDMI_CORE_AV_REG(0x300) | 110 | #define HDMI_CORE_AV_GEN_DBYTE_NELEMS 31 |
117 | #define HDMI_CORE_AV_GEN_DBYTE_NELEMS HDMI_CORE_AV_REG(31) | 111 | #define HDMI_CORE_AV_GEN2_DBYTE(n) (n * 4 + 0x380) |
118 | #define HDMI_CORE_AV_GEN2_DBYTE HDMI_CORE_AV_REG(0x380) | 112 | #define HDMI_CORE_AV_GEN2_DBYTE_NELEMS 31 |
119 | #define HDMI_CORE_AV_GEN2_DBYTE_NELEMS HDMI_CORE_AV_REG(31) | 113 | #define HDMI_CORE_AV_ACR_CTRL 0x4 |
120 | #define HDMI_CORE_AV_ACR_CTRL HDMI_CORE_AV_REG(0x4) | 114 | #define HDMI_CORE_AV_FREQ_SVAL 0x8 |
121 | #define HDMI_CORE_AV_FREQ_SVAL HDMI_CORE_AV_REG(0x8) | 115 | #define HDMI_CORE_AV_N_SVAL1 0xC |
122 | #define HDMI_CORE_AV_N_SVAL1 HDMI_CORE_AV_REG(0xC) | 116 | #define HDMI_CORE_AV_N_SVAL2 0x10 |
123 | #define HDMI_CORE_AV_N_SVAL2 HDMI_CORE_AV_REG(0x10) | 117 | #define HDMI_CORE_AV_N_SVAL3 0x14 |
124 | #define HDMI_CORE_AV_N_SVAL3 HDMI_CORE_AV_REG(0x14) | 118 | #define HDMI_CORE_AV_CTS_SVAL1 0x18 |
125 | #define HDMI_CORE_AV_CTS_SVAL1 HDMI_CORE_AV_REG(0x18) | 119 | #define HDMI_CORE_AV_CTS_SVAL2 0x1C |
126 | #define HDMI_CORE_AV_CTS_SVAL2 HDMI_CORE_AV_REG(0x1C) | 120 | #define HDMI_CORE_AV_CTS_SVAL3 0x20 |
127 | #define HDMI_CORE_AV_CTS_SVAL3 HDMI_CORE_AV_REG(0x20) | 121 | #define HDMI_CORE_AV_CTS_HVAL1 0x24 |
128 | #define HDMI_CORE_AV_CTS_HVAL1 HDMI_CORE_AV_REG(0x24) | 122 | #define HDMI_CORE_AV_CTS_HVAL2 0x28 |
129 | #define HDMI_CORE_AV_CTS_HVAL2 HDMI_CORE_AV_REG(0x28) | 123 | #define HDMI_CORE_AV_CTS_HVAL3 0x2C |
130 | #define HDMI_CORE_AV_CTS_HVAL3 HDMI_CORE_AV_REG(0x2C) | 124 | #define HDMI_CORE_AV_AUD_MODE 0x50 |
131 | #define HDMI_CORE_AV_AUD_MODE HDMI_CORE_AV_REG(0x50) | 125 | #define HDMI_CORE_AV_SPDIF_CTRL 0x54 |
132 | #define HDMI_CORE_AV_SPDIF_CTRL HDMI_CORE_AV_REG(0x54) | 126 | #define HDMI_CORE_AV_HW_SPDIF_FS 0x60 |
133 | #define HDMI_CORE_AV_HW_SPDIF_FS HDMI_CORE_AV_REG(0x60) | 127 | #define HDMI_CORE_AV_SWAP_I2S 0x64 |
134 | #define HDMI_CORE_AV_SWAP_I2S HDMI_CORE_AV_REG(0x64) | 128 | #define HDMI_CORE_AV_SPDIF_ERTH 0x6C |
135 | #define HDMI_CORE_AV_SPDIF_ERTH HDMI_CORE_AV_REG(0x6C) | 129 | #define HDMI_CORE_AV_I2S_IN_MAP 0x70 |
136 | #define HDMI_CORE_AV_I2S_IN_MAP HDMI_CORE_AV_REG(0x70) | 130 | #define HDMI_CORE_AV_I2S_IN_CTRL 0x74 |
137 | #define HDMI_CORE_AV_I2S_IN_CTRL HDMI_CORE_AV_REG(0x74) | 131 | #define HDMI_CORE_AV_I2S_CHST0 0x78 |
138 | #define HDMI_CORE_AV_I2S_CHST0 HDMI_CORE_AV_REG(0x78) | 132 | #define HDMI_CORE_AV_I2S_CHST1 0x7C |
139 | #define HDMI_CORE_AV_I2S_CHST1 HDMI_CORE_AV_REG(0x7C) | 133 | #define HDMI_CORE_AV_I2S_CHST2 0x80 |
140 | #define HDMI_CORE_AV_I2S_CHST2 HDMI_CORE_AV_REG(0x80) | 134 | #define HDMI_CORE_AV_I2S_CHST4 0x84 |
141 | #define HDMI_CORE_AV_I2S_CHST4 HDMI_CORE_AV_REG(0x84) | 135 | #define HDMI_CORE_AV_I2S_CHST5 0x88 |
142 | #define HDMI_CORE_AV_I2S_CHST5 HDMI_CORE_AV_REG(0x88) | 136 | #define HDMI_CORE_AV_ASRC 0x8C |
143 | #define HDMI_CORE_AV_ASRC HDMI_CORE_AV_REG(0x8C) | 137 | #define HDMI_CORE_AV_I2S_IN_LEN 0x90 |
144 | #define HDMI_CORE_AV_I2S_IN_LEN HDMI_CORE_AV_REG(0x90) | 138 | #define HDMI_CORE_AV_HDMI_CTRL 0xBC |
145 | #define HDMI_CORE_AV_HDMI_CTRL HDMI_CORE_AV_REG(0xBC) | 139 | #define HDMI_CORE_AV_AUDO_TXSTAT 0xC0 |
146 | #define HDMI_CORE_AV_AUDO_TXSTAT HDMI_CORE_AV_REG(0xC0) | 140 | #define HDMI_CORE_AV_AUD_PAR_BUSCLK_1 0xCC |
147 | #define HDMI_CORE_AV_AUD_PAR_BUSCLK_1 HDMI_CORE_AV_REG(0xCC) | 141 | #define HDMI_CORE_AV_AUD_PAR_BUSCLK_2 0xD0 |
148 | #define HDMI_CORE_AV_AUD_PAR_BUSCLK_2 HDMI_CORE_AV_REG(0xD0) | 142 | #define HDMI_CORE_AV_AUD_PAR_BUSCLK_3 0xD4 |
149 | #define HDMI_CORE_AV_AUD_PAR_BUSCLK_3 HDMI_CORE_AV_REG(0xD4) | 143 | #define HDMI_CORE_AV_TEST_TXCTRL 0xF0 |
150 | #define HDMI_CORE_AV_TEST_TXCTRL HDMI_CORE_AV_REG(0xF0) | 144 | #define HDMI_CORE_AV_DPD 0xF4 |
151 | #define HDMI_CORE_AV_DPD HDMI_CORE_AV_REG(0xF4) | 145 | #define HDMI_CORE_AV_PB_CTRL1 0xF8 |
152 | #define HDMI_CORE_AV_PB_CTRL1 HDMI_CORE_AV_REG(0xF8) | 146 | #define HDMI_CORE_AV_PB_CTRL2 0xFC |
153 | #define HDMI_CORE_AV_PB_CTRL2 HDMI_CORE_AV_REG(0xFC) | 147 | #define HDMI_CORE_AV_AVI_TYPE 0x100 |
154 | #define HDMI_CORE_AV_AVI_TYPE HDMI_CORE_AV_REG(0x100) | 148 | #define HDMI_CORE_AV_AVI_VERS 0x104 |
155 | #define HDMI_CORE_AV_AVI_VERS HDMI_CORE_AV_REG(0x104) | 149 | #define HDMI_CORE_AV_AVI_LEN 0x108 |
156 | #define HDMI_CORE_AV_AVI_LEN HDMI_CORE_AV_REG(0x108) | 150 | #define HDMI_CORE_AV_AVI_CHSUM 0x10C |
157 | #define HDMI_CORE_AV_AVI_CHSUM HDMI_CORE_AV_REG(0x10C) | 151 | #define HDMI_CORE_AV_SPD_TYPE 0x180 |
158 | #define HDMI_CORE_AV_SPD_TYPE HDMI_CORE_AV_REG(0x180) | 152 | #define HDMI_CORE_AV_SPD_VERS 0x184 |
159 | #define HDMI_CORE_AV_SPD_VERS HDMI_CORE_AV_REG(0x184) | 153 | #define HDMI_CORE_AV_SPD_LEN 0x188 |
160 | #define HDMI_CORE_AV_SPD_LEN HDMI_CORE_AV_REG(0x188) | 154 | #define HDMI_CORE_AV_SPD_CHSUM 0x18C |
161 | #define HDMI_CORE_AV_SPD_CHSUM HDMI_CORE_AV_REG(0x18C) | 155 | #define HDMI_CORE_AV_AUDIO_TYPE 0x200 |
162 | #define HDMI_CORE_AV_AUDIO_TYPE HDMI_CORE_AV_REG(0x200) | 156 | #define HDMI_CORE_AV_AUDIO_VERS 0x204 |
163 | #define HDMI_CORE_AV_AUDIO_VERS HDMI_CORE_AV_REG(0x204) | 157 | #define HDMI_CORE_AV_AUDIO_LEN 0x208 |
164 | #define HDMI_CORE_AV_AUDIO_LEN HDMI_CORE_AV_REG(0x208) | 158 | #define HDMI_CORE_AV_AUDIO_CHSUM 0x20C |
165 | #define HDMI_CORE_AV_AUDIO_CHSUM HDMI_CORE_AV_REG(0x20C) | 159 | #define HDMI_CORE_AV_MPEG_TYPE 0x280 |
166 | #define HDMI_CORE_AV_MPEG_TYPE HDMI_CORE_AV_REG(0x280) | 160 | #define HDMI_CORE_AV_MPEG_VERS 0x284 |
167 | #define HDMI_CORE_AV_MPEG_VERS HDMI_CORE_AV_REG(0x284) | 161 | #define HDMI_CORE_AV_MPEG_LEN 0x288 |
168 | #define HDMI_CORE_AV_MPEG_LEN HDMI_CORE_AV_REG(0x288) | 162 | #define HDMI_CORE_AV_MPEG_CHSUM 0x28C |
169 | #define HDMI_CORE_AV_MPEG_CHSUM HDMI_CORE_AV_REG(0x28C) | 163 | #define HDMI_CORE_AV_CP_BYTE1 0x37C |
170 | #define HDMI_CORE_AV_CP_BYTE1 HDMI_CORE_AV_REG(0x37C) | 164 | #define HDMI_CORE_AV_CEC_ADDR_ID 0x3FC |
171 | #define HDMI_CORE_AV_CEC_ADDR_ID HDMI_CORE_AV_REG(0x3FC) | ||
172 | #define HDMI_CORE_AV_SPD_DBYTE_ELSIZE 0x4 | 165 | #define HDMI_CORE_AV_SPD_DBYTE_ELSIZE 0x4 |
173 | #define HDMI_CORE_AV_GEN2_DBYTE_ELSIZE 0x4 | 166 | #define HDMI_CORE_AV_GEN2_DBYTE_ELSIZE 0x4 |
174 | #define HDMI_CORE_AV_MPEG_DBYTE_ELSIZE 0x4 | 167 | #define HDMI_CORE_AV_MPEG_DBYTE_ELSIZE 0x4 |
175 | #define HDMI_CORE_AV_GEN_DBYTE_ELSIZE 0x4 | 168 | #define HDMI_CORE_AV_GEN_DBYTE_ELSIZE 0x4 |
176 | 169 | ||
177 | /* PLL */ | 170 | /* PLL */ |
178 | #define HDMI_PLL_REG(idx) HDMI_REG(HDMI_PLLCTRL + idx) | ||
179 | 171 | ||
180 | #define PLLCTRL_PLL_CONTROL HDMI_PLL_REG(0x0) | 172 | #define PLLCTRL_PLL_CONTROL 0x0 |
181 | #define PLLCTRL_PLL_STATUS HDMI_PLL_REG(0x4) | 173 | #define PLLCTRL_PLL_STATUS 0x4 |
182 | #define PLLCTRL_PLL_GO HDMI_PLL_REG(0x8) | 174 | #define PLLCTRL_PLL_GO 0x8 |
183 | #define PLLCTRL_CFG1 HDMI_PLL_REG(0xC) | 175 | #define PLLCTRL_CFG1 0xC |
184 | #define PLLCTRL_CFG2 HDMI_PLL_REG(0x10) | 176 | #define PLLCTRL_CFG2 0x10 |
185 | #define PLLCTRL_CFG3 HDMI_PLL_REG(0x14) | 177 | #define PLLCTRL_CFG3 0x14 |
186 | #define PLLCTRL_CFG4 HDMI_PLL_REG(0x20) | 178 | #define PLLCTRL_CFG4 0x20 |
187 | 179 | ||
188 | /* HDMI PHY */ | 180 | /* HDMI PHY */ |
189 | #define HDMI_PHY_REG(idx) HDMI_REG(HDMI_PHY + idx) | ||
190 | |||
191 | #define HDMI_TXPHY_TX_CTRL HDMI_PHY_REG(0x0) | ||
192 | #define HDMI_TXPHY_DIGITAL_CTRL HDMI_PHY_REG(0x4) | ||
193 | #define HDMI_TXPHY_POWER_CTRL HDMI_PHY_REG(0x8) | ||
194 | #define HDMI_TXPHY_PAD_CFG_CTRL HDMI_PHY_REG(0xC) | ||
195 | |||
196 | /* HDMI EDID Length */ | ||
197 | #define HDMI_EDID_MAX_LENGTH 256 | ||
198 | #define EDID_TIMING_DESCRIPTOR_SIZE 0x12 | ||
199 | #define EDID_DESCRIPTOR_BLOCK0_ADDRESS 0x36 | ||
200 | #define EDID_DESCRIPTOR_BLOCK1_ADDRESS 0x80 | ||
201 | #define EDID_SIZE_BLOCK0_TIMING_DESCRIPTOR 4 | ||
202 | #define EDID_SIZE_BLOCK1_TIMING_DESCRIPTOR 4 | ||
203 | 181 | ||
204 | #define OMAP_HDMI_TIMINGS_NB 34 | 182 | #define HDMI_TXPHY_TX_CTRL 0x0 |
183 | #define HDMI_TXPHY_DIGITAL_CTRL 0x4 | ||
184 | #define HDMI_TXPHY_POWER_CTRL 0x8 | ||
185 | #define HDMI_TXPHY_PAD_CFG_CTRL 0xC | ||
205 | 186 | ||
206 | #define REG_FLD_MOD(idx, val, start, end) \ | 187 | #define REG_FLD_MOD(base, idx, val, start, end) \ |
207 | hdmi_write_reg(idx, FLD_MOD(hdmi_read_reg(idx), val, start, end)) | 188 | hdmi_write_reg(base, idx, FLD_MOD(hdmi_read_reg(base, idx),\ |
208 | #define REG_GET(idx, start, end) \ | 189 | val, start, end)) |
209 | FLD_GET(hdmi_read_reg(idx), start, end) | 190 | #define REG_GET(base, idx, start, end) \ |
210 | 191 | FLD_GET(hdmi_read_reg(base, idx), start, end) | |
211 | /* HDMI timing structure */ | ||
212 | struct hdmi_timings { | ||
213 | struct omap_video_timings timings; | ||
214 | int vsync_pol; | ||
215 | int hsync_pol; | ||
216 | }; | ||
217 | 192 | ||
218 | enum hdmi_phy_pwr { | 193 | enum hdmi_phy_pwr { |
219 | HDMI_PHYPWRCMD_OFF = 0, | 194 | HDMI_PHYPWRCMD_OFF = 0, |
@@ -221,20 +196,6 @@ enum hdmi_phy_pwr { | |||
221 | HDMI_PHYPWRCMD_TXON = 2 | 196 | HDMI_PHYPWRCMD_TXON = 2 |
222 | }; | 197 | }; |
223 | 198 | ||
224 | enum hdmi_pll_pwr { | ||
225 | HDMI_PLLPWRCMD_ALLOFF = 0, | ||
226 | HDMI_PLLPWRCMD_PLLONLY = 1, | ||
227 | HDMI_PLLPWRCMD_BOTHON_ALLCLKS = 2, | ||
228 | HDMI_PLLPWRCMD_BOTHON_NOPHYCLK = 3 | ||
229 | }; | ||
230 | |||
231 | enum hdmi_clk_refsel { | ||
232 | HDMI_REFSEL_PCLK = 0, | ||
233 | HDMI_REFSEL_REF1 = 1, | ||
234 | HDMI_REFSEL_REF2 = 2, | ||
235 | HDMI_REFSEL_SYSCLK = 3 | ||
236 | }; | ||
237 | |||
238 | enum hdmi_core_inputbus_width { | 199 | enum hdmi_core_inputbus_width { |
239 | HDMI_INPUT_8BIT = 0, | 200 | HDMI_INPUT_8BIT = 0, |
240 | HDMI_INPUT_10BIT = 1, | 201 | HDMI_INPUT_10BIT = 1, |
@@ -263,11 +224,6 @@ enum hdmi_core_packet_mode { | |||
263 | HDMI_PACKETMODE48BITPERPIXEL = 7 | 224 | HDMI_PACKETMODE48BITPERPIXEL = 7 |
264 | }; | 225 | }; |
265 | 226 | ||
266 | enum hdmi_core_hdmi_dvi { | ||
267 | HDMI_DVI = 0, | ||
268 | HDMI_HDMI = 1 | ||
269 | }; | ||
270 | |||
271 | enum hdmi_core_tclkselclkmult { | 227 | enum hdmi_core_tclkselclkmult { |
272 | HDMI_FPLL05IDCK = 0, | 228 | HDMI_FPLL05IDCK = 0, |
273 | HDMI_FPLL10IDCK = 1, | 229 | HDMI_FPLL10IDCK = 1, |
@@ -495,40 +451,40 @@ struct hdmi_core_video_config { | |||
495 | * details about infoframe databytes | 451 | * details about infoframe databytes |
496 | */ | 452 | */ |
497 | struct hdmi_core_infoframe_avi { | 453 | struct hdmi_core_infoframe_avi { |
454 | /* Y0, Y1 rgb,yCbCr */ | ||
498 | u8 db1_format; | 455 | u8 db1_format; |
499 | /* Y0, Y1 rgb,yCbCr */ | 456 | /* A0 Active information Present */ |
500 | u8 db1_active_info; | 457 | u8 db1_active_info; |
501 | /* A0 Active information Present */ | 458 | /* B0, B1 Bar info data valid */ |
502 | u8 db1_bar_info_dv; | 459 | u8 db1_bar_info_dv; |
503 | /* B0, B1 Bar info data valid */ | 460 | /* S0, S1 scan information */ |
504 | u8 db1_scan_info; | 461 | u8 db1_scan_info; |
505 | /* S0, S1 scan information */ | 462 | /* C0, C1 colorimetry */ |
506 | u8 db2_colorimetry; | 463 | u8 db2_colorimetry; |
507 | /* C0, C1 colorimetry */ | 464 | /* M0, M1 Aspect ratio (4:3, 16:9) */ |
508 | u8 db2_aspect_ratio; | 465 | u8 db2_aspect_ratio; |
509 | /* M0, M1 Aspect ratio (4:3, 16:9) */ | 466 | /* R0...R3 Active format aspect ratio */ |
510 | u8 db2_active_fmt_ar; | 467 | u8 db2_active_fmt_ar; |
511 | /* R0...R3 Active format aspect ratio */ | 468 | /* ITC IT content. */ |
512 | u8 db3_itc; | 469 | u8 db3_itc; |
513 | /* ITC IT content. */ | 470 | /* EC0, EC1, EC2 Extended colorimetry */ |
514 | u8 db3_ec; | 471 | u8 db3_ec; |
515 | /* EC0, EC1, EC2 Extended colorimetry */ | 472 | /* Q1, Q0 Quantization range */ |
516 | u8 db3_q_range; | 473 | u8 db3_q_range; |
517 | /* Q1, Q0 Quantization range */ | 474 | /* SC1, SC0 Non-uniform picture scaling */ |
518 | u8 db3_nup_scaling; | 475 | u8 db3_nup_scaling; |
519 | /* SC1, SC0 Non-uniform picture scaling */ | 476 | /* VIC0..6 Video format identification */ |
520 | u8 db4_videocode; | 477 | u8 db4_videocode; |
521 | /* VIC0..6 Video format identification */ | 478 | /* PR0..PR3 Pixel repetition factor */ |
522 | u8 db5_pixel_repeat; | 479 | u8 db5_pixel_repeat; |
523 | /* PR0..PR3 Pixel repetition factor */ | 480 | /* Line number end of top bar */ |
524 | u16 db6_7_line_eoftop; | 481 | u16 db6_7_line_eoftop; |
525 | /* Line number end of top bar */ | 482 | /* Line number start of bottom bar */ |
526 | u16 db8_9_line_sofbottom; | 483 | u16 db8_9_line_sofbottom; |
527 | /* Line number start of bottom bar */ | 484 | /* Pixel number end of left bar */ |
528 | u16 db10_11_pixel_eofleft; | 485 | u16 db10_11_pixel_eofleft; |
529 | /* Pixel number end of left bar */ | 486 | /* Pixel number start of right bar */ |
530 | u16 db12_13_pixel_sofright; | 487 | u16 db12_13_pixel_sofright; |
531 | /* Pixel number start of right bar */ | ||
532 | }; | 488 | }; |
533 | /* | 489 | /* |
534 | * Refer to section 8.2 in HDMI 1.3 specification for | 490 | * Refer to section 8.2 in HDMI 1.3 specification for |
@@ -568,17 +524,6 @@ struct hdmi_video_interface { | |||
568 | int tm; /* Timing mode */ | 524 | int tm; /* Timing mode */ |
569 | }; | 525 | }; |
570 | 526 | ||
571 | struct hdmi_cm { | ||
572 | int code; | ||
573 | int mode; | ||
574 | }; | ||
575 | |||
576 | struct hdmi_config { | ||
577 | struct hdmi_timings timings; | ||
578 | u16 interlace; | ||
579 | struct hdmi_cm cm; | ||
580 | }; | ||
581 | |||
582 | struct hdmi_audio_format { | 527 | struct hdmi_audio_format { |
583 | enum hdmi_stereo_channels stereo_channels; | 528 | enum hdmi_stereo_channels stereo_channels; |
584 | u8 active_chnnls_msk; | 529 | u8 active_chnnls_msk; |
@@ -628,4 +573,21 @@ struct hdmi_core_audio_config { | |||
628 | bool en_parallel_aud_input; | 573 | bool en_parallel_aud_input; |
629 | bool en_spdif; | 574 | bool en_spdif; |
630 | }; | 575 | }; |
576 | |||
577 | #if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \ | ||
578 | defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE) | ||
579 | int hdmi_audio_trigger(struct hdmi_ip_data *ip_data, | ||
580 | struct snd_pcm_substream *substream, int cmd, | ||
581 | struct snd_soc_dai *dai); | ||
582 | int hdmi_config_audio_acr(struct hdmi_ip_data *ip_data, | ||
583 | u32 sample_freq, u32 *n, u32 *cts); | ||
584 | void hdmi_core_audio_infoframe_config(struct hdmi_ip_data *ip_data, | ||
585 | struct hdmi_core_infoframe_audio *info_aud); | ||
586 | void hdmi_core_audio_config(struct hdmi_ip_data *ip_data, | ||
587 | struct hdmi_core_audio_config *cfg); | ||
588 | void hdmi_wp_audio_config_dma(struct hdmi_ip_data *ip_data, | ||
589 | struct hdmi_audio_dma *aud_dma); | ||
590 | void hdmi_wp_audio_config_format(struct hdmi_ip_data *ip_data, | ||
591 | struct hdmi_audio_format *aud_fmt); | ||
592 | #endif | ||
631 | #endif | 593 | #endif |
diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c index 173c66430dad..7533458ba4d2 100644 --- a/drivers/video/omap2/dss/venc.c +++ b/drivers/video/omap2/dss/venc.c | |||
@@ -295,7 +295,6 @@ static struct { | |||
295 | u32 wss_data; | 295 | u32 wss_data; |
296 | struct regulator *vdda_dac_reg; | 296 | struct regulator *vdda_dac_reg; |
297 | 297 | ||
298 | struct clk *tv_clk; | ||
299 | struct clk *tv_dac_clk; | 298 | struct clk *tv_dac_clk; |
300 | } venc; | 299 | } venc; |
301 | 300 | ||
@@ -464,9 +463,11 @@ static void venc_power_off(struct omap_dss_device *dssdev) | |||
464 | regulator_disable(venc.vdda_dac_reg); | 463 | regulator_disable(venc.vdda_dac_reg); |
465 | } | 464 | } |
466 | 465 | ||
467 | 466 | unsigned long venc_get_pixel_clock(void) | |
468 | 467 | { | |
469 | 468 | /* VENC Pixel Clock in Mhz */ | |
469 | return 13500000; | ||
470 | } | ||
470 | 471 | ||
471 | /* driver */ | 472 | /* driver */ |
472 | static int venc_panel_probe(struct omap_dss_device *dssdev) | 473 | static int venc_panel_probe(struct omap_dss_device *dssdev) |
@@ -732,22 +733,10 @@ static int venc_get_clocks(struct platform_device *pdev) | |||
732 | { | 733 | { |
733 | struct clk *clk; | 734 | struct clk *clk; |
734 | 735 | ||
735 | clk = clk_get(&pdev->dev, "fck"); | ||
736 | if (IS_ERR(clk)) { | ||
737 | DSSERR("can't get fck\n"); | ||
738 | return PTR_ERR(clk); | ||
739 | } | ||
740 | |||
741 | venc.tv_clk = clk; | ||
742 | |||
743 | if (dss_has_feature(FEAT_VENC_REQUIRES_TV_DAC_CLK)) { | 736 | if (dss_has_feature(FEAT_VENC_REQUIRES_TV_DAC_CLK)) { |
744 | if (cpu_is_omap34xx() || cpu_is_omap3630()) | 737 | clk = clk_get(&pdev->dev, "tv_dac_clk"); |
745 | clk = clk_get(&pdev->dev, "dss_96m_fck"); | ||
746 | else | ||
747 | clk = clk_get(&pdev->dev, "tv_dac_clk"); | ||
748 | if (IS_ERR(clk)) { | 738 | if (IS_ERR(clk)) { |
749 | DSSERR("can't get tv_dac_clk\n"); | 739 | DSSERR("can't get tv_dac_clk\n"); |
750 | clk_put(venc.tv_clk); | ||
751 | return PTR_ERR(clk); | 740 | return PTR_ERR(clk); |
752 | } | 741 | } |
753 | } else { | 742 | } else { |
@@ -761,8 +750,6 @@ static int venc_get_clocks(struct platform_device *pdev) | |||
761 | 750 | ||
762 | static void venc_put_clocks(void) | 751 | static void venc_put_clocks(void) |
763 | { | 752 | { |
764 | if (venc.tv_clk) | ||
765 | clk_put(venc.tv_clk); | ||
766 | if (venc.tv_dac_clk) | 753 | if (venc.tv_dac_clk) |
767 | clk_put(venc.tv_dac_clk); | 754 | clk_put(venc.tv_dac_clk); |
768 | } | 755 | } |
@@ -838,7 +825,6 @@ static int venc_runtime_suspend(struct device *dev) | |||
838 | { | 825 | { |
839 | if (venc.tv_dac_clk) | 826 | if (venc.tv_dac_clk) |
840 | clk_disable(venc.tv_dac_clk); | 827 | clk_disable(venc.tv_dac_clk); |
841 | clk_disable(venc.tv_clk); | ||
842 | 828 | ||
843 | dispc_runtime_put(); | 829 | dispc_runtime_put(); |
844 | dss_runtime_put(); | 830 | dss_runtime_put(); |
@@ -858,7 +844,6 @@ static int venc_runtime_resume(struct device *dev) | |||
858 | if (r < 0) | 844 | if (r < 0) |
859 | goto err_get_dispc; | 845 | goto err_get_dispc; |
860 | 846 | ||
861 | clk_enable(venc.tv_clk); | ||
862 | if (venc.tv_dac_clk) | 847 | if (venc.tv_dac_clk) |
863 | clk_enable(venc.tv_dac_clk); | 848 | clk_enable(venc.tv_dac_clk); |
864 | 849 | ||
diff --git a/drivers/video/omap2/omapfb/Kconfig b/drivers/video/omap2/omapfb/Kconfig index aa33386c81ff..83d3fe7ec9ae 100644 --- a/drivers/video/omap2/omapfb/Kconfig +++ b/drivers/video/omap2/omapfb/Kconfig | |||
@@ -1,5 +1,5 @@ | |||
1 | menuconfig FB_OMAP2 | 1 | menuconfig FB_OMAP2 |
2 | tristate "OMAP2+ frame buffer support (EXPERIMENTAL)" | 2 | tristate "OMAP2+ frame buffer support" |
3 | depends on FB && OMAP2_DSS | 3 | depends on FB && OMAP2_DSS |
4 | 4 | ||
5 | select OMAP2_VRAM | 5 | select OMAP2_VRAM |
diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c index 602b71a92d3c..70aa47de7146 100644 --- a/drivers/video/omap2/omapfb/omapfb-main.c +++ b/drivers/video/omap2/omapfb/omapfb-main.c | |||
@@ -808,19 +808,15 @@ static unsigned calc_rotation_offset_vrfb(const struct fb_var_screeninfo *var, | |||
808 | static void omapfb_calc_addr(const struct omapfb_info *ofbi, | 808 | static void omapfb_calc_addr(const struct omapfb_info *ofbi, |
809 | const struct fb_var_screeninfo *var, | 809 | const struct fb_var_screeninfo *var, |
810 | const struct fb_fix_screeninfo *fix, | 810 | const struct fb_fix_screeninfo *fix, |
811 | int rotation, u32 *paddr, void __iomem **vaddr) | 811 | int rotation, u32 *paddr) |
812 | { | 812 | { |
813 | u32 data_start_p; | 813 | u32 data_start_p; |
814 | void __iomem *data_start_v; | ||
815 | int offset; | 814 | int offset; |
816 | 815 | ||
817 | if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) { | 816 | if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) |
818 | data_start_p = omapfb_get_region_rot_paddr(ofbi, rotation); | 817 | data_start_p = omapfb_get_region_rot_paddr(ofbi, rotation); |
819 | data_start_v = NULL; | 818 | else |
820 | } else { | ||
821 | data_start_p = omapfb_get_region_paddr(ofbi); | 819 | data_start_p = omapfb_get_region_paddr(ofbi); |
822 | data_start_v = omapfb_get_region_vaddr(ofbi); | ||
823 | } | ||
824 | 820 | ||
825 | if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) | 821 | if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) |
826 | offset = calc_rotation_offset_vrfb(var, fix, rotation); | 822 | offset = calc_rotation_offset_vrfb(var, fix, rotation); |
@@ -828,16 +824,14 @@ static void omapfb_calc_addr(const struct omapfb_info *ofbi, | |||
828 | offset = calc_rotation_offset_dma(var, fix, rotation); | 824 | offset = calc_rotation_offset_dma(var, fix, rotation); |
829 | 825 | ||
830 | data_start_p += offset; | 826 | data_start_p += offset; |
831 | data_start_v += offset; | ||
832 | 827 | ||
833 | if (offset) | 828 | if (offset) |
834 | DBG("offset %d, %d = %d\n", | 829 | DBG("offset %d, %d = %d\n", |
835 | var->xoffset, var->yoffset, offset); | 830 | var->xoffset, var->yoffset, offset); |
836 | 831 | ||
837 | DBG("paddr %x, vaddr %p\n", data_start_p, data_start_v); | 832 | DBG("paddr %x\n", data_start_p); |
838 | 833 | ||
839 | *paddr = data_start_p; | 834 | *paddr = data_start_p; |
840 | *vaddr = data_start_v; | ||
841 | } | 835 | } |
842 | 836 | ||
843 | /* setup overlay according to the fb */ | 837 | /* setup overlay according to the fb */ |
@@ -850,7 +844,6 @@ int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl, | |||
850 | struct fb_fix_screeninfo *fix = &fbi->fix; | 844 | struct fb_fix_screeninfo *fix = &fbi->fix; |
851 | enum omap_color_mode mode = 0; | 845 | enum omap_color_mode mode = 0; |
852 | u32 data_start_p = 0; | 846 | u32 data_start_p = 0; |
853 | void __iomem *data_start_v = NULL; | ||
854 | struct omap_overlay_info info; | 847 | struct omap_overlay_info info; |
855 | int xres, yres; | 848 | int xres, yres; |
856 | int screen_width; | 849 | int screen_width; |
@@ -880,8 +873,7 @@ int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl, | |||
880 | } | 873 | } |
881 | 874 | ||
882 | if (ofbi->region->size) | 875 | if (ofbi->region->size) |
883 | omapfb_calc_addr(ofbi, var, fix, rotation, | 876 | omapfb_calc_addr(ofbi, var, fix, rotation, &data_start_p); |
884 | &data_start_p, &data_start_v); | ||
885 | 877 | ||
886 | r = fb_mode_to_dss_mode(var, &mode); | 878 | r = fb_mode_to_dss_mode(var, &mode); |
887 | if (r) { | 879 | if (r) { |
@@ -910,7 +902,6 @@ int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl, | |||
910 | mirror = ofbi->mirror; | 902 | mirror = ofbi->mirror; |
911 | 903 | ||
912 | info.paddr = data_start_p; | 904 | info.paddr = data_start_p; |
913 | info.vaddr = data_start_v; | ||
914 | info.screen_width = screen_width; | 905 | info.screen_width = screen_width; |
915 | info.width = xres; | 906 | info.width = xres; |
916 | info.height = yres; | 907 | info.height = yres; |
@@ -2276,6 +2267,87 @@ static int omapfb_parse_def_modes(struct omapfb2_device *fbdev) | |||
2276 | return r; | 2267 | return r; |
2277 | } | 2268 | } |
2278 | 2269 | ||
2270 | static void fb_videomode_to_omap_timings(struct fb_videomode *m, | ||
2271 | struct omap_video_timings *t) | ||
2272 | { | ||
2273 | t->x_res = m->xres; | ||
2274 | t->y_res = m->yres; | ||
2275 | t->pixel_clock = PICOS2KHZ(m->pixclock); | ||
2276 | t->hsw = m->hsync_len; | ||
2277 | t->hfp = m->right_margin; | ||
2278 | t->hbp = m->left_margin; | ||
2279 | t->vsw = m->vsync_len; | ||
2280 | t->vfp = m->lower_margin; | ||
2281 | t->vbp = m->upper_margin; | ||
2282 | } | ||
2283 | |||
2284 | static int omapfb_find_best_mode(struct omap_dss_device *display, | ||
2285 | struct omap_video_timings *timings) | ||
2286 | { | ||
2287 | struct fb_monspecs *specs; | ||
2288 | u8 *edid; | ||
2289 | int r, i, best_xres, best_idx, len; | ||
2290 | |||
2291 | if (!display->driver->read_edid) | ||
2292 | return -ENODEV; | ||
2293 | |||
2294 | len = 0x80 * 2; | ||
2295 | edid = kmalloc(len, GFP_KERNEL); | ||
2296 | |||
2297 | r = display->driver->read_edid(display, edid, len); | ||
2298 | if (r < 0) | ||
2299 | goto err1; | ||
2300 | |||
2301 | specs = kzalloc(sizeof(*specs), GFP_KERNEL); | ||
2302 | |||
2303 | fb_edid_to_monspecs(edid, specs); | ||
2304 | |||
2305 | if (edid[126] > 0) | ||
2306 | fb_edid_add_monspecs(edid + 0x80, specs); | ||
2307 | |||
2308 | best_xres = 0; | ||
2309 | best_idx = -1; | ||
2310 | |||
2311 | for (i = 0; i < specs->modedb_len; ++i) { | ||
2312 | struct fb_videomode *m; | ||
2313 | struct omap_video_timings t; | ||
2314 | |||
2315 | m = &specs->modedb[i]; | ||
2316 | |||
2317 | if (m->pixclock == 0) | ||
2318 | continue; | ||
2319 | |||
2320 | /* skip repeated pixel modes */ | ||
2321 | if (m->xres == 2880 || m->xres == 1440) | ||
2322 | continue; | ||
2323 | |||
2324 | fb_videomode_to_omap_timings(m, &t); | ||
2325 | |||
2326 | r = display->driver->check_timings(display, &t); | ||
2327 | if (r == 0 && best_xres < m->xres) { | ||
2328 | best_xres = m->xres; | ||
2329 | best_idx = i; | ||
2330 | } | ||
2331 | } | ||
2332 | |||
2333 | if (best_xres == 0) { | ||
2334 | r = -ENOENT; | ||
2335 | goto err2; | ||
2336 | } | ||
2337 | |||
2338 | fb_videomode_to_omap_timings(&specs->modedb[best_idx], timings); | ||
2339 | |||
2340 | r = 0; | ||
2341 | |||
2342 | err2: | ||
2343 | fb_destroy_modedb(specs->modedb); | ||
2344 | kfree(specs); | ||
2345 | err1: | ||
2346 | kfree(edid); | ||
2347 | |||
2348 | return r; | ||
2349 | } | ||
2350 | |||
2279 | static int omapfb_init_display(struct omapfb2_device *fbdev, | 2351 | static int omapfb_init_display(struct omapfb2_device *fbdev, |
2280 | struct omap_dss_device *dssdev) | 2352 | struct omap_dss_device *dssdev) |
2281 | { | 2353 | { |
@@ -2373,8 +2445,10 @@ static int omapfb_probe(struct platform_device *pdev) | |||
2373 | omap_dss_get_device(dssdev); | 2445 | omap_dss_get_device(dssdev); |
2374 | 2446 | ||
2375 | if (!dssdev->driver) { | 2447 | if (!dssdev->driver) { |
2376 | dev_err(&pdev->dev, "no driver for display\n"); | 2448 | dev_warn(&pdev->dev, "no driver for display: %s\n", |
2377 | r = -ENODEV; | 2449 | dssdev->name); |
2450 | omap_dss_put_device(dssdev); | ||
2451 | continue; | ||
2378 | } | 2452 | } |
2379 | 2453 | ||
2380 | d = &fbdev->displays[fbdev->num_displays++]; | 2454 | d = &fbdev->displays[fbdev->num_displays++]; |
@@ -2402,9 +2476,27 @@ static int omapfb_probe(struct platform_device *pdev) | |||
2402 | for (i = 0; i < fbdev->num_managers; i++) | 2476 | for (i = 0; i < fbdev->num_managers; i++) |
2403 | fbdev->managers[i] = omap_dss_get_overlay_manager(i); | 2477 | fbdev->managers[i] = omap_dss_get_overlay_manager(i); |
2404 | 2478 | ||
2479 | /* gfx overlay should be the default one. find a display | ||
2480 | * connected to that, and use it as default display */ | ||
2481 | ovl = omap_dss_get_overlay(0); | ||
2482 | if (ovl->manager && ovl->manager->device) { | ||
2483 | def_display = ovl->manager->device; | ||
2484 | } else { | ||
2485 | dev_warn(&pdev->dev, "cannot find default display\n"); | ||
2486 | def_display = NULL; | ||
2487 | } | ||
2488 | |||
2405 | if (def_mode && strlen(def_mode) > 0) { | 2489 | if (def_mode && strlen(def_mode) > 0) { |
2406 | if (omapfb_parse_def_modes(fbdev)) | 2490 | if (omapfb_parse_def_modes(fbdev)) |
2407 | dev_warn(&pdev->dev, "cannot parse default modes\n"); | 2491 | dev_warn(&pdev->dev, "cannot parse default modes\n"); |
2492 | } else if (def_display && def_display->driver->set_timings && | ||
2493 | def_display->driver->check_timings) { | ||
2494 | struct omap_video_timings t; | ||
2495 | |||
2496 | r = omapfb_find_best_mode(def_display, &t); | ||
2497 | |||
2498 | if (r == 0) | ||
2499 | def_display->driver->set_timings(def_display, &t); | ||
2408 | } | 2500 | } |
2409 | 2501 | ||
2410 | r = omapfb_create_framebuffers(fbdev); | 2502 | r = omapfb_create_framebuffers(fbdev); |
@@ -2421,16 +2513,6 @@ static int omapfb_probe(struct platform_device *pdev) | |||
2421 | 2513 | ||
2422 | DBG("mgr->apply'ed\n"); | 2514 | DBG("mgr->apply'ed\n"); |
2423 | 2515 | ||
2424 | /* gfx overlay should be the default one. find a display | ||
2425 | * connected to that, and use it as default display */ | ||
2426 | ovl = omap_dss_get_overlay(0); | ||
2427 | if (ovl->manager && ovl->manager->device) { | ||
2428 | def_display = ovl->manager->device; | ||
2429 | } else { | ||
2430 | dev_warn(&pdev->dev, "cannot find default display\n"); | ||
2431 | def_display = NULL; | ||
2432 | } | ||
2433 | |||
2434 | if (def_display) { | 2516 | if (def_display) { |
2435 | r = omapfb_init_display(fbdev, def_display); | 2517 | r = omapfb_init_display(fbdev, def_display); |
2436 | if (r) { | 2518 | if (r) { |
diff --git a/drivers/video/omap2/omapfb/omapfb-sysfs.c b/drivers/video/omap2/omapfb/omapfb-sysfs.c index 153bf1aceebc..1694d5148f32 100644 --- a/drivers/video/omap2/omapfb/omapfb-sysfs.c +++ b/drivers/video/omap2/omapfb/omapfb-sysfs.c | |||
@@ -104,16 +104,14 @@ static ssize_t store_mirror(struct device *dev, | |||
104 | { | 104 | { |
105 | struct fb_info *fbi = dev_get_drvdata(dev); | 105 | struct fb_info *fbi = dev_get_drvdata(dev); |
106 | struct omapfb_info *ofbi = FB2OFB(fbi); | 106 | struct omapfb_info *ofbi = FB2OFB(fbi); |
107 | int mirror; | 107 | bool mirror; |
108 | int r; | 108 | int r; |
109 | struct fb_var_screeninfo new_var; | 109 | struct fb_var_screeninfo new_var; |
110 | 110 | ||
111 | r = kstrtoint(buf, 0, &mirror); | 111 | r = strtobool(buf, &mirror); |
112 | if (r) | 112 | if (r) |
113 | return r; | 113 | return r; |
114 | 114 | ||
115 | mirror = !!mirror; | ||
116 | |||
117 | if (!lock_fb_info(fbi)) | 115 | if (!lock_fb_info(fbi)) |
118 | return -ENODEV; | 116 | return -ENODEV; |
119 | 117 | ||
diff --git a/drivers/video/platinumfb.c b/drivers/video/platinumfb.c index f27ae16ead2e..ae3caa6755c2 100644 --- a/drivers/video/platinumfb.c +++ b/drivers/video/platinumfb.c | |||
@@ -490,7 +490,7 @@ static int platinum_var_to_par(struct fb_var_screeninfo *var, | |||
490 | 490 | ||
491 | 491 | ||
492 | /* | 492 | /* |
493 | * Parse user speficied options (`video=platinumfb:') | 493 | * Parse user specified options (`video=platinumfb:') |
494 | */ | 494 | */ |
495 | static int __init platinumfb_setup(char *options) | 495 | static int __init platinumfb_setup(char *options) |
496 | { | 496 | { |
@@ -683,7 +683,7 @@ static struct platform_driver platinum_driver = | |||
683 | .of_match_table = platinumfb_match, | 683 | .of_match_table = platinumfb_match, |
684 | }, | 684 | }, |
685 | .probe = platinumfb_probe, | 685 | .probe = platinumfb_probe, |
686 | .remove = platinumfb_remove, | 686 | .remove = __devexit_p(platinumfb_remove), |
687 | }; | 687 | }; |
688 | 688 | ||
689 | static int __init platinumfb_init(void) | 689 | static int __init platinumfb_init(void) |
diff --git a/drivers/video/pm2fb.c b/drivers/video/pm2fb.c index 27f93aab6ddc..dc7bfa91e57a 100644 --- a/drivers/video/pm2fb.c +++ b/drivers/video/pm2fb.c | |||
@@ -973,8 +973,8 @@ static int pm2fb_pan_display(struct fb_var_screeninfo *var, | |||
973 | { | 973 | { |
974 | struct pm2fb_par *p = info->par; | 974 | struct pm2fb_par *p = info->par; |
975 | u32 base; | 975 | u32 base; |
976 | u32 depth = (var->bits_per_pixel + 7) & ~7; | 976 | u32 depth = (info->var.bits_per_pixel + 7) & ~7; |
977 | u32 xres = (var->xres + 31) & ~31; | 977 | u32 xres = (info->var.xres + 31) & ~31; |
978 | 978 | ||
979 | depth = (depth > 32) ? 32 : depth; | 979 | depth = (depth > 32) ? 32 : depth; |
980 | base = to3264(var->yoffset * xres + var->xoffset, depth, 1); | 980 | base = to3264(var->yoffset * xres + var->xoffset, depth, 1); |
@@ -1773,7 +1773,7 @@ MODULE_DEVICE_TABLE(pci, pm2fb_id_table); | |||
1773 | 1773 | ||
1774 | #ifndef MODULE | 1774 | #ifndef MODULE |
1775 | /** | 1775 | /** |
1776 | * Parse user speficied options. | 1776 | * Parse user specified options. |
1777 | * | 1777 | * |
1778 | * This is, comma-separated options following `video=pm2fb:'. | 1778 | * This is, comma-separated options following `video=pm2fb:'. |
1779 | */ | 1779 | */ |
diff --git a/drivers/video/pm3fb.c b/drivers/video/pm3fb.c index 6666f45a2f8c..6632ee5ecb7e 100644 --- a/drivers/video/pm3fb.c +++ b/drivers/video/pm3fb.c | |||
@@ -1147,9 +1147,9 @@ static int pm3fb_pan_display(struct fb_var_screeninfo *var, | |||
1147 | struct fb_info *info) | 1147 | struct fb_info *info) |
1148 | { | 1148 | { |
1149 | struct pm3_par *par = info->par; | 1149 | struct pm3_par *par = info->par; |
1150 | const u32 xres = (var->xres + 31) & ~31; | 1150 | const u32 xres = (info->var.xres + 31) & ~31; |
1151 | 1151 | ||
1152 | par->base = pm3fb_shift_bpp(var->bits_per_pixel, | 1152 | par->base = pm3fb_shift_bpp(info->var.bits_per_pixel, |
1153 | (var->yoffset * xres) | 1153 | (var->yoffset * xres) |
1154 | + var->xoffset); | 1154 | + var->xoffset); |
1155 | PM3_WAIT(par, 1); | 1155 | PM3_WAIT(par, 1); |
@@ -1525,7 +1525,7 @@ static int __init pm3fb_setup(char *options) | |||
1525 | { | 1525 | { |
1526 | char *this_opt; | 1526 | char *this_opt; |
1527 | 1527 | ||
1528 | /* Parse user speficied options (`video=pm3fb:') */ | 1528 | /* Parse user specified options (`video=pm3fb:') */ |
1529 | if (!options || !*options) | 1529 | if (!options || !*options) |
1530 | return 0; | 1530 | return 0; |
1531 | 1531 | ||
diff --git a/drivers/video/ps3fb.c b/drivers/video/ps3fb.c index 65560a1a0439..213fbbcf613b 100644 --- a/drivers/video/ps3fb.c +++ b/drivers/video/ps3fb.c | |||
@@ -1082,7 +1082,7 @@ static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev) | |||
1082 | } | 1082 | } |
1083 | 1083 | ||
1084 | retval = request_irq(ps3fb.irq_no, ps3fb_vsync_interrupt, | 1084 | retval = request_irq(ps3fb.irq_no, ps3fb_vsync_interrupt, |
1085 | IRQF_DISABLED, DEVICE_NAME, &dev->core); | 1085 | 0, DEVICE_NAME, &dev->core); |
1086 | if (retval) { | 1086 | if (retval) { |
1087 | dev_err(&dev->core, "%s: request_irq failed %d\n", __func__, | 1087 | dev_err(&dev->core, "%s: request_irq failed %d\n", __func__, |
1088 | retval); | 1088 | retval); |
diff --git a/drivers/video/pxa3xx-gcu.c b/drivers/video/pxa3xx-gcu.c index 0283c7021090..1ed8b366618d 100644 --- a/drivers/video/pxa3xx-gcu.c +++ b/drivers/video/pxa3xx-gcu.c | |||
@@ -31,8 +31,6 @@ | |||
31 | */ | 31 | */ |
32 | 32 | ||
33 | #include <linux/module.h> | 33 | #include <linux/module.h> |
34 | #include <linux/version.h> | ||
35 | |||
36 | #include <linux/platform_device.h> | 34 | #include <linux/platform_device.h> |
37 | #include <linux/dma-mapping.h> | 35 | #include <linux/dma-mapping.h> |
38 | #include <linux/miscdevice.h> | 36 | #include <linux/miscdevice.h> |
@@ -678,7 +676,7 @@ pxa3xx_gcu_probe(struct platform_device *dev) | |||
678 | } | 676 | } |
679 | 677 | ||
680 | ret = request_irq(irq, pxa3xx_gcu_handle_irq, | 678 | ret = request_irq(irq, pxa3xx_gcu_handle_irq, |
681 | IRQF_DISABLED, DRV_NAME, priv); | 679 | 0, DRV_NAME, priv); |
682 | if (ret) { | 680 | if (ret) { |
683 | dev_err(&dev->dev, "request_irq failed\n"); | 681 | dev_err(&dev->dev, "request_irq failed\n"); |
684 | ret = -EBUSY; | 682 | ret = -EBUSY; |
diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c index 0f4e8c942f9e..e89778f4081f 100644 --- a/drivers/video/pxafb.c +++ b/drivers/video/pxafb.c | |||
@@ -2191,7 +2191,7 @@ static int __devinit pxafb_probe(struct platform_device *dev) | |||
2191 | goto failed_free_mem; | 2191 | goto failed_free_mem; |
2192 | } | 2192 | } |
2193 | 2193 | ||
2194 | ret = request_irq(irq, pxafb_handle_irq, IRQF_DISABLED, "LCD", fbi); | 2194 | ret = request_irq(irq, pxafb_handle_irq, 0, "LCD", fbi); |
2195 | if (ret) { | 2195 | if (ret) { |
2196 | dev_err(&dev->dev, "request_irq failed: %d\n", ret); | 2196 | dev_err(&dev->dev, "request_irq failed: %d\n", ret); |
2197 | ret = -EBUSY; | 2197 | ret = -EBUSY; |
diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c index 4aecf213c9be..0753b1cfcb8b 100644 --- a/drivers/video/s3c-fb.c +++ b/drivers/video/s3c-fb.c | |||
@@ -81,6 +81,7 @@ struct s3c_fb; | |||
81 | * @palette: Address of palette memory, or 0 if none. | 81 | * @palette: Address of palette memory, or 0 if none. |
82 | * @has_prtcon: Set if has PRTCON register. | 82 | * @has_prtcon: Set if has PRTCON register. |
83 | * @has_shadowcon: Set if has SHADOWCON register. | 83 | * @has_shadowcon: Set if has SHADOWCON register. |
84 | * @has_clksel: Set if VIDCON0 register has CLKSEL bit. | ||
84 | */ | 85 | */ |
85 | struct s3c_fb_variant { | 86 | struct s3c_fb_variant { |
86 | unsigned int is_2443:1; | 87 | unsigned int is_2443:1; |
@@ -98,6 +99,7 @@ struct s3c_fb_variant { | |||
98 | 99 | ||
99 | unsigned int has_prtcon:1; | 100 | unsigned int has_prtcon:1; |
100 | unsigned int has_shadowcon:1; | 101 | unsigned int has_shadowcon:1; |
102 | unsigned int has_clksel:1; | ||
101 | }; | 103 | }; |
102 | 104 | ||
103 | /** | 105 | /** |
@@ -186,6 +188,7 @@ struct s3c_fb_vsync { | |||
186 | * @dev: The device that we bound to, for printing, etc. | 188 | * @dev: The device that we bound to, for printing, etc. |
187 | * @regs_res: The resource we claimed for the IO registers. | 189 | * @regs_res: The resource we claimed for the IO registers. |
188 | * @bus_clk: The clk (hclk) feeding our interface and possibly pixclk. | 190 | * @bus_clk: The clk (hclk) feeding our interface and possibly pixclk. |
191 | * @lcd_clk: The clk (sclk) feeding pixclk. | ||
189 | * @regs: The mapped hardware registers. | 192 | * @regs: The mapped hardware registers. |
190 | * @variant: Variant information for this hardware. | 193 | * @variant: Variant information for this hardware. |
191 | * @enabled: A bitmask of enabled hardware windows. | 194 | * @enabled: A bitmask of enabled hardware windows. |
@@ -200,6 +203,7 @@ struct s3c_fb { | |||
200 | struct device *dev; | 203 | struct device *dev; |
201 | struct resource *regs_res; | 204 | struct resource *regs_res; |
202 | struct clk *bus_clk; | 205 | struct clk *bus_clk; |
206 | struct clk *lcd_clk; | ||
203 | void __iomem *regs; | 207 | void __iomem *regs; |
204 | struct s3c_fb_variant variant; | 208 | struct s3c_fb_variant variant; |
205 | 209 | ||
@@ -336,10 +340,15 @@ static int s3c_fb_check_var(struct fb_var_screeninfo *var, | |||
336 | */ | 340 | */ |
337 | static int s3c_fb_calc_pixclk(struct s3c_fb *sfb, unsigned int pixclk) | 341 | static int s3c_fb_calc_pixclk(struct s3c_fb *sfb, unsigned int pixclk) |
338 | { | 342 | { |
339 | unsigned long clk = clk_get_rate(sfb->bus_clk); | 343 | unsigned long clk; |
340 | unsigned long long tmp; | 344 | unsigned long long tmp; |
341 | unsigned int result; | 345 | unsigned int result; |
342 | 346 | ||
347 | if (sfb->variant.has_clksel) | ||
348 | clk = clk_get_rate(sfb->bus_clk); | ||
349 | else | ||
350 | clk = clk_get_rate(sfb->lcd_clk); | ||
351 | |||
343 | tmp = (unsigned long long)clk; | 352 | tmp = (unsigned long long)clk; |
344 | tmp *= pixclk; | 353 | tmp *= pixclk; |
345 | 354 | ||
@@ -883,7 +892,7 @@ static int s3c_fb_pan_display(struct fb_var_screeninfo *var, | |||
883 | } | 892 | } |
884 | } | 893 | } |
885 | /* Offset in bytes to the end of the displayed area */ | 894 | /* Offset in bytes to the end of the displayed area */ |
886 | end_boff = start_boff + var->yres * info->fix.line_length; | 895 | end_boff = start_boff + info->var.yres * info->fix.line_length; |
887 | 896 | ||
888 | /* Temporarily turn off per-vsync update from shadow registers until | 897 | /* Temporarily turn off per-vsync update from shadow registers until |
889 | * both start and end addresses are updated to prevent corruption */ | 898 | * both start and end addresses are updated to prevent corruption */ |
@@ -1354,13 +1363,24 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev) | |||
1354 | 1363 | ||
1355 | clk_enable(sfb->bus_clk); | 1364 | clk_enable(sfb->bus_clk); |
1356 | 1365 | ||
1366 | if (!sfb->variant.has_clksel) { | ||
1367 | sfb->lcd_clk = clk_get(dev, "sclk_fimd"); | ||
1368 | if (IS_ERR(sfb->lcd_clk)) { | ||
1369 | dev_err(dev, "failed to get lcd clock\n"); | ||
1370 | ret = PTR_ERR(sfb->lcd_clk); | ||
1371 | goto err_bus_clk; | ||
1372 | } | ||
1373 | |||
1374 | clk_enable(sfb->lcd_clk); | ||
1375 | } | ||
1376 | |||
1357 | pm_runtime_enable(sfb->dev); | 1377 | pm_runtime_enable(sfb->dev); |
1358 | 1378 | ||
1359 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1379 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
1360 | if (!res) { | 1380 | if (!res) { |
1361 | dev_err(dev, "failed to find registers\n"); | 1381 | dev_err(dev, "failed to find registers\n"); |
1362 | ret = -ENOENT; | 1382 | ret = -ENOENT; |
1363 | goto err_clk; | 1383 | goto err_lcd_clk; |
1364 | } | 1384 | } |
1365 | 1385 | ||
1366 | sfb->regs_res = request_mem_region(res->start, resource_size(res), | 1386 | sfb->regs_res = request_mem_region(res->start, resource_size(res), |
@@ -1368,7 +1388,7 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev) | |||
1368 | if (!sfb->regs_res) { | 1388 | if (!sfb->regs_res) { |
1369 | dev_err(dev, "failed to claim register region\n"); | 1389 | dev_err(dev, "failed to claim register region\n"); |
1370 | ret = -ENOENT; | 1390 | ret = -ENOENT; |
1371 | goto err_clk; | 1391 | goto err_lcd_clk; |
1372 | } | 1392 | } |
1373 | 1393 | ||
1374 | sfb->regs = ioremap(res->start, resource_size(res)); | 1394 | sfb->regs = ioremap(res->start, resource_size(res)); |
@@ -1450,7 +1470,13 @@ err_ioremap: | |||
1450 | err_req_region: | 1470 | err_req_region: |
1451 | release_mem_region(sfb->regs_res->start, resource_size(sfb->regs_res)); | 1471 | release_mem_region(sfb->regs_res->start, resource_size(sfb->regs_res)); |
1452 | 1472 | ||
1453 | err_clk: | 1473 | err_lcd_clk: |
1474 | if (!sfb->variant.has_clksel) { | ||
1475 | clk_disable(sfb->lcd_clk); | ||
1476 | clk_put(sfb->lcd_clk); | ||
1477 | } | ||
1478 | |||
1479 | err_bus_clk: | ||
1454 | clk_disable(sfb->bus_clk); | 1480 | clk_disable(sfb->bus_clk); |
1455 | clk_put(sfb->bus_clk); | 1481 | clk_put(sfb->bus_clk); |
1456 | 1482 | ||
@@ -1481,6 +1507,11 @@ static int __devexit s3c_fb_remove(struct platform_device *pdev) | |||
1481 | 1507 | ||
1482 | iounmap(sfb->regs); | 1508 | iounmap(sfb->regs); |
1483 | 1509 | ||
1510 | if (!sfb->variant.has_clksel) { | ||
1511 | clk_disable(sfb->lcd_clk); | ||
1512 | clk_put(sfb->lcd_clk); | ||
1513 | } | ||
1514 | |||
1484 | clk_disable(sfb->bus_clk); | 1515 | clk_disable(sfb->bus_clk); |
1485 | clk_put(sfb->bus_clk); | 1516 | clk_put(sfb->bus_clk); |
1486 | 1517 | ||
@@ -1510,6 +1541,9 @@ static int s3c_fb_suspend(struct device *dev) | |||
1510 | s3c_fb_blank(FB_BLANK_POWERDOWN, win->fbinfo); | 1541 | s3c_fb_blank(FB_BLANK_POWERDOWN, win->fbinfo); |
1511 | } | 1542 | } |
1512 | 1543 | ||
1544 | if (!sfb->variant.has_clksel) | ||
1545 | clk_disable(sfb->lcd_clk); | ||
1546 | |||
1513 | clk_disable(sfb->bus_clk); | 1547 | clk_disable(sfb->bus_clk); |
1514 | return 0; | 1548 | return 0; |
1515 | } | 1549 | } |
@@ -1524,6 +1558,9 @@ static int s3c_fb_resume(struct device *dev) | |||
1524 | 1558 | ||
1525 | clk_enable(sfb->bus_clk); | 1559 | clk_enable(sfb->bus_clk); |
1526 | 1560 | ||
1561 | if (!sfb->variant.has_clksel) | ||
1562 | clk_enable(sfb->lcd_clk); | ||
1563 | |||
1527 | /* setup gpio and output polarity controls */ | 1564 | /* setup gpio and output polarity controls */ |
1528 | pd->setup_gpio(); | 1565 | pd->setup_gpio(); |
1529 | writel(pd->vidcon1, sfb->regs + VIDCON1); | 1566 | writel(pd->vidcon1, sfb->regs + VIDCON1); |
@@ -1569,6 +1606,9 @@ static int s3c_fb_runtime_suspend(struct device *dev) | |||
1569 | s3c_fb_blank(FB_BLANK_POWERDOWN, win->fbinfo); | 1606 | s3c_fb_blank(FB_BLANK_POWERDOWN, win->fbinfo); |
1570 | } | 1607 | } |
1571 | 1608 | ||
1609 | if (!sfb->variant.has_clksel) | ||
1610 | clk_disable(sfb->lcd_clk); | ||
1611 | |||
1572 | clk_disable(sfb->bus_clk); | 1612 | clk_disable(sfb->bus_clk); |
1573 | return 0; | 1613 | return 0; |
1574 | } | 1614 | } |
@@ -1583,6 +1623,9 @@ static int s3c_fb_runtime_resume(struct device *dev) | |||
1583 | 1623 | ||
1584 | clk_enable(sfb->bus_clk); | 1624 | clk_enable(sfb->bus_clk); |
1585 | 1625 | ||
1626 | if (!sfb->variant.has_clksel) | ||
1627 | clk_enable(sfb->lcd_clk); | ||
1628 | |||
1586 | /* setup gpio and output polarity controls */ | 1629 | /* setup gpio and output polarity controls */ |
1587 | pd->setup_gpio(); | 1630 | pd->setup_gpio(); |
1588 | writel(pd->vidcon1, sfb->regs + VIDCON1); | 1631 | writel(pd->vidcon1, sfb->regs + VIDCON1); |
@@ -1755,6 +1798,7 @@ static struct s3c_fb_driverdata s3c_fb_data_64xx = { | |||
1755 | }, | 1798 | }, |
1756 | 1799 | ||
1757 | .has_prtcon = 1, | 1800 | .has_prtcon = 1, |
1801 | .has_clksel = 1, | ||
1758 | }, | 1802 | }, |
1759 | .win[0] = &s3c_fb_data_64xx_wins[0], | 1803 | .win[0] = &s3c_fb_data_64xx_wins[0], |
1760 | .win[1] = &s3c_fb_data_64xx_wins[1], | 1804 | .win[1] = &s3c_fb_data_64xx_wins[1], |
@@ -1785,6 +1829,7 @@ static struct s3c_fb_driverdata s3c_fb_data_s5pc100 = { | |||
1785 | }, | 1829 | }, |
1786 | 1830 | ||
1787 | .has_prtcon = 1, | 1831 | .has_prtcon = 1, |
1832 | .has_clksel = 1, | ||
1788 | }, | 1833 | }, |
1789 | .win[0] = &s3c_fb_data_s5p_wins[0], | 1834 | .win[0] = &s3c_fb_data_s5p_wins[0], |
1790 | .win[1] = &s3c_fb_data_s5p_wins[1], | 1835 | .win[1] = &s3c_fb_data_s5p_wins[1], |
@@ -1815,6 +1860,37 @@ static struct s3c_fb_driverdata s3c_fb_data_s5pv210 = { | |||
1815 | }, | 1860 | }, |
1816 | 1861 | ||
1817 | .has_shadowcon = 1, | 1862 | .has_shadowcon = 1, |
1863 | .has_clksel = 1, | ||
1864 | }, | ||
1865 | .win[0] = &s3c_fb_data_s5p_wins[0], | ||
1866 | .win[1] = &s3c_fb_data_s5p_wins[1], | ||
1867 | .win[2] = &s3c_fb_data_s5p_wins[2], | ||
1868 | .win[3] = &s3c_fb_data_s5p_wins[3], | ||
1869 | .win[4] = &s3c_fb_data_s5p_wins[4], | ||
1870 | }; | ||
1871 | |||
1872 | static struct s3c_fb_driverdata s3c_fb_data_exynos4 = { | ||
1873 | .variant = { | ||
1874 | .nr_windows = 5, | ||
1875 | .vidtcon = VIDTCON0, | ||
1876 | .wincon = WINCON(0), | ||
1877 | .winmap = WINxMAP(0), | ||
1878 | .keycon = WKEYCON, | ||
1879 | .osd = VIDOSD_BASE, | ||
1880 | .osd_stride = 16, | ||
1881 | .buf_start = VIDW_BUF_START(0), | ||
1882 | .buf_size = VIDW_BUF_SIZE(0), | ||
1883 | .buf_end = VIDW_BUF_END(0), | ||
1884 | |||
1885 | .palette = { | ||
1886 | [0] = 0x2400, | ||
1887 | [1] = 0x2800, | ||
1888 | [2] = 0x2c00, | ||
1889 | [3] = 0x3000, | ||
1890 | [4] = 0x3400, | ||
1891 | }, | ||
1892 | |||
1893 | .has_shadowcon = 1, | ||
1818 | }, | 1894 | }, |
1819 | .win[0] = &s3c_fb_data_s5p_wins[0], | 1895 | .win[0] = &s3c_fb_data_s5p_wins[0], |
1820 | .win[1] = &s3c_fb_data_s5p_wins[1], | 1896 | .win[1] = &s3c_fb_data_s5p_wins[1], |
@@ -1843,6 +1919,7 @@ static struct s3c_fb_driverdata s3c_fb_data_s3c2443 = { | |||
1843 | [0] = 0x400, | 1919 | [0] = 0x400, |
1844 | [1] = 0x800, | 1920 | [1] = 0x800, |
1845 | }, | 1921 | }, |
1922 | .has_clksel = 1, | ||
1846 | }, | 1923 | }, |
1847 | .win[0] = &(struct s3c_fb_win_variant) { | 1924 | .win[0] = &(struct s3c_fb_win_variant) { |
1848 | .palette_sz = 256, | 1925 | .palette_sz = 256, |
@@ -1859,6 +1936,30 @@ static struct s3c_fb_driverdata s3c_fb_data_s3c2443 = { | |||
1859 | }, | 1936 | }, |
1860 | }; | 1937 | }; |
1861 | 1938 | ||
1939 | static struct s3c_fb_driverdata s3c_fb_data_s5p64x0 = { | ||
1940 | .variant = { | ||
1941 | .nr_windows = 3, | ||
1942 | .vidtcon = VIDTCON0, | ||
1943 | .wincon = WINCON(0), | ||
1944 | .winmap = WINxMAP(0), | ||
1945 | .keycon = WKEYCON, | ||
1946 | .osd = VIDOSD_BASE, | ||
1947 | .osd_stride = 16, | ||
1948 | .buf_start = VIDW_BUF_START(0), | ||
1949 | .buf_size = VIDW_BUF_SIZE(0), | ||
1950 | .buf_end = VIDW_BUF_END(0), | ||
1951 | |||
1952 | .palette = { | ||
1953 | [0] = 0x2400, | ||
1954 | [1] = 0x2800, | ||
1955 | [2] = 0x2c00, | ||
1956 | }, | ||
1957 | }, | ||
1958 | .win[0] = &s3c_fb_data_s5p_wins[0], | ||
1959 | .win[1] = &s3c_fb_data_s5p_wins[1], | ||
1960 | .win[2] = &s3c_fb_data_s5p_wins[2], | ||
1961 | }; | ||
1962 | |||
1862 | static struct platform_device_id s3c_fb_driver_ids[] = { | 1963 | static struct platform_device_id s3c_fb_driver_ids[] = { |
1863 | { | 1964 | { |
1864 | .name = "s3c-fb", | 1965 | .name = "s3c-fb", |
@@ -1870,8 +1971,14 @@ static struct platform_device_id s3c_fb_driver_ids[] = { | |||
1870 | .name = "s5pv210-fb", | 1971 | .name = "s5pv210-fb", |
1871 | .driver_data = (unsigned long)&s3c_fb_data_s5pv210, | 1972 | .driver_data = (unsigned long)&s3c_fb_data_s5pv210, |
1872 | }, { | 1973 | }, { |
1974 | .name = "exynos4-fb", | ||
1975 | .driver_data = (unsigned long)&s3c_fb_data_exynos4, | ||
1976 | }, { | ||
1873 | .name = "s3c2443-fb", | 1977 | .name = "s3c2443-fb", |
1874 | .driver_data = (unsigned long)&s3c_fb_data_s3c2443, | 1978 | .driver_data = (unsigned long)&s3c_fb_data_s3c2443, |
1979 | }, { | ||
1980 | .name = "s5p64x0-fb", | ||
1981 | .driver_data = (unsigned long)&s3c_fb_data_s5p64x0, | ||
1875 | }, | 1982 | }, |
1876 | {}, | 1983 | {}, |
1877 | }; | 1984 | }; |
diff --git a/drivers/video/s3c2410fb.c b/drivers/video/s3c2410fb.c index 0aa13761de6e..ee4c0df217f7 100644 --- a/drivers/video/s3c2410fb.c +++ b/drivers/video/s3c2410fb.c | |||
@@ -767,7 +767,6 @@ static irqreturn_t s3c2410fb_irq(int irq, void *dev_id) | |||
767 | static int s3c2410fb_cpufreq_transition(struct notifier_block *nb, | 767 | static int s3c2410fb_cpufreq_transition(struct notifier_block *nb, |
768 | unsigned long val, void *data) | 768 | unsigned long val, void *data) |
769 | { | 769 | { |
770 | struct cpufreq_freqs *freqs = data; | ||
771 | struct s3c2410fb_info *info; | 770 | struct s3c2410fb_info *info; |
772 | struct fb_info *fbinfo; | 771 | struct fb_info *fbinfo; |
773 | long delta_f; | 772 | long delta_f; |
@@ -911,7 +910,7 @@ static int __devinit s3c24xxfb_probe(struct platform_device *pdev, | |||
911 | for (i = 0; i < 256; i++) | 910 | for (i = 0; i < 256; i++) |
912 | info->palette_buffer[i] = PALETTE_BUFF_CLEAR; | 911 | info->palette_buffer[i] = PALETTE_BUFF_CLEAR; |
913 | 912 | ||
914 | ret = request_irq(irq, s3c2410fb_irq, IRQF_DISABLED, pdev->name, info); | 913 | ret = request_irq(irq, s3c2410fb_irq, 0, pdev->name, info); |
915 | if (ret) { | 914 | if (ret) { |
916 | dev_err(&pdev->dev, "cannot get irq %d - err %d\n", irq, ret); | 915 | dev_err(&pdev->dev, "cannot get irq %d - err %d\n", irq, ret); |
917 | ret = -EBUSY; | 916 | ret = -EBUSY; |
diff --git a/drivers/video/s3fb.c b/drivers/video/s3fb.c index 4ca5d0c8fe84..946a949f4c7d 100644 --- a/drivers/video/s3fb.c +++ b/drivers/video/s3fb.c | |||
@@ -1019,12 +1019,13 @@ static int s3fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) | |||
1019 | unsigned int offset; | 1019 | unsigned int offset; |
1020 | 1020 | ||
1021 | /* Calculate the offset */ | 1021 | /* Calculate the offset */ |
1022 | if (var->bits_per_pixel == 0) { | 1022 | if (info->var.bits_per_pixel == 0) { |
1023 | offset = (var->yoffset / 16) * (var->xres_virtual / 2) + (var->xoffset / 2); | 1023 | offset = (var->yoffset / 16) * (info->var.xres_virtual / 2) |
1024 | + (var->xoffset / 2); | ||
1024 | offset = offset >> 2; | 1025 | offset = offset >> 2; |
1025 | } else { | 1026 | } else { |
1026 | offset = (var->yoffset * info->fix.line_length) + | 1027 | offset = (var->yoffset * info->fix.line_length) + |
1027 | (var->xoffset * var->bits_per_pixel / 8); | 1028 | (var->xoffset * info->var.bits_per_pixel / 8); |
1028 | offset = offset >> 2; | 1029 | offset = offset >> 2; |
1029 | } | 1030 | } |
1030 | 1031 | ||
@@ -1504,7 +1505,7 @@ static struct pci_driver s3fb_pci_driver = { | |||
1504 | .resume = s3_pci_resume, | 1505 | .resume = s3_pci_resume, |
1505 | }; | 1506 | }; |
1506 | 1507 | ||
1507 | /* Parse user speficied options */ | 1508 | /* Parse user specified options */ |
1508 | 1509 | ||
1509 | #ifndef MODULE | 1510 | #ifndef MODULE |
1510 | static int __init s3fb_setup(char *options) | 1511 | static int __init s3fb_setup(char *options) |
diff --git a/drivers/video/sa1100fb.c b/drivers/video/sa1100fb.c index e8b76d65a070..98d55d0e2da5 100644 --- a/drivers/video/sa1100fb.c +++ b/drivers/video/sa1100fb.c | |||
@@ -1457,8 +1457,7 @@ static int __devinit sa1100fb_probe(struct platform_device *pdev) | |||
1457 | if (ret) | 1457 | if (ret) |
1458 | goto failed; | 1458 | goto failed; |
1459 | 1459 | ||
1460 | ret = request_irq(irq, sa1100fb_handle_irq, IRQF_DISABLED, | 1460 | ret = request_irq(irq, sa1100fb_handle_irq, 0, "LCD", fbi); |
1461 | "LCD", fbi); | ||
1462 | if (ret) { | 1461 | if (ret) { |
1463 | printk(KERN_ERR "sa1100fb: request_irq failed: %d\n", ret); | 1462 | printk(KERN_ERR "sa1100fb: request_irq failed: %d\n", ret); |
1464 | goto failed; | 1463 | goto failed; |
diff --git a/drivers/video/savage/savagefb_driver.c b/drivers/video/savage/savagefb_driver.c index 4de541ca9c52..beb495044b24 100644 --- a/drivers/video/savage/savagefb_driver.c +++ b/drivers/video/savage/savagefb_driver.c | |||
@@ -1477,15 +1477,9 @@ static void savagefb_set_par_int(struct savagefb_par *par, struct savage_reg *r | |||
1477 | vgaHWProtect(par, 0); | 1477 | vgaHWProtect(par, 0); |
1478 | } | 1478 | } |
1479 | 1479 | ||
1480 | static void savagefb_update_start(struct savagefb_par *par, | 1480 | static void savagefb_update_start(struct savagefb_par *par, int base) |
1481 | struct fb_var_screeninfo *var) | ||
1482 | { | 1481 | { |
1483 | int base; | 1482 | /* program the start address registers */ |
1484 | |||
1485 | base = ((var->yoffset * var->xres_virtual + (var->xoffset & ~1)) | ||
1486 | * ((var->bits_per_pixel+7) / 8)) >> 2; | ||
1487 | |||
1488 | /* now program the start address registers */ | ||
1489 | vga_out16(0x3d4, (base & 0x00ff00) | 0x0c, par); | 1483 | vga_out16(0x3d4, (base & 0x00ff00) | 0x0c, par); |
1490 | vga_out16(0x3d4, ((base & 0x00ff) << 8) | 0x0d, par); | 1484 | vga_out16(0x3d4, ((base & 0x00ff) << 8) | 0x0d, par); |
1491 | vga_out8(0x3d4, 0x69, par); | 1485 | vga_out8(0x3d4, 0x69, par); |
@@ -1550,8 +1544,12 @@ static int savagefb_pan_display(struct fb_var_screeninfo *var, | |||
1550 | struct fb_info *info) | 1544 | struct fb_info *info) |
1551 | { | 1545 | { |
1552 | struct savagefb_par *par = info->par; | 1546 | struct savagefb_par *par = info->par; |
1547 | int base; | ||
1548 | |||
1549 | base = (var->yoffset * info->fix.line_length | ||
1550 | + (var->xoffset & ~1) * ((info->var.bits_per_pixel+7) / 8)) >> 2; | ||
1553 | 1551 | ||
1554 | savagefb_update_start(par, var); | 1552 | savagefb_update_start(par, base); |
1555 | return 0; | 1553 | return 0; |
1556 | } | 1554 | } |
1557 | 1555 | ||
diff --git a/drivers/video/sh_mobile_hdmi.c b/drivers/video/sh_mobile_hdmi.c index 7d54e2c612f7..647ba984f00f 100644 --- a/drivers/video/sh_mobile_hdmi.c +++ b/drivers/video/sh_mobile_hdmi.c | |||
@@ -1111,6 +1111,7 @@ static long sh_hdmi_clk_configure(struct sh_hdmi *hdmi, unsigned long hdmi_rate, | |||
1111 | static void sh_hdmi_edid_work_fn(struct work_struct *work) | 1111 | static void sh_hdmi_edid_work_fn(struct work_struct *work) |
1112 | { | 1112 | { |
1113 | struct sh_hdmi *hdmi = container_of(work, struct sh_hdmi, edid_work.work); | 1113 | struct sh_hdmi *hdmi = container_of(work, struct sh_hdmi, edid_work.work); |
1114 | struct fb_info *info; | ||
1114 | struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data; | 1115 | struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data; |
1115 | struct sh_mobile_lcdc_chan *ch; | 1116 | struct sh_mobile_lcdc_chan *ch; |
1116 | int ret; | 1117 | int ret; |
@@ -1123,8 +1124,9 @@ static void sh_hdmi_edid_work_fn(struct work_struct *work) | |||
1123 | 1124 | ||
1124 | mutex_lock(&hdmi->mutex); | 1125 | mutex_lock(&hdmi->mutex); |
1125 | 1126 | ||
1127 | info = hdmi->info; | ||
1128 | |||
1126 | if (hdmi->hp_state == HDMI_HOTPLUG_CONNECTED) { | 1129 | if (hdmi->hp_state == HDMI_HOTPLUG_CONNECTED) { |
1127 | struct fb_info *info = hdmi->info; | ||
1128 | unsigned long parent_rate = 0, hdmi_rate; | 1130 | unsigned long parent_rate = 0, hdmi_rate; |
1129 | 1131 | ||
1130 | ret = sh_hdmi_read_edid(hdmi, &hdmi_rate, &parent_rate); | 1132 | ret = sh_hdmi_read_edid(hdmi, &hdmi_rate, &parent_rate); |
@@ -1148,42 +1150,45 @@ static void sh_hdmi_edid_work_fn(struct work_struct *work) | |||
1148 | 1150 | ||
1149 | ch = info->par; | 1151 | ch = info->par; |
1150 | 1152 | ||
1151 | console_lock(); | 1153 | if (lock_fb_info(info)) { |
1154 | console_lock(); | ||
1152 | 1155 | ||
1153 | /* HDMI plug in */ | 1156 | /* HDMI plug in */ |
1154 | if (!sh_hdmi_must_reconfigure(hdmi) && | 1157 | if (!sh_hdmi_must_reconfigure(hdmi) && |
1155 | info->state == FBINFO_STATE_RUNNING) { | 1158 | info->state == FBINFO_STATE_RUNNING) { |
1156 | /* | 1159 | /* |
1157 | * First activation with the default monitor - just turn | 1160 | * First activation with the default monitor - just turn |
1158 | * on, if we run a resume here, the logo disappears | 1161 | * on, if we run a resume here, the logo disappears |
1159 | */ | 1162 | */ |
1160 | if (lock_fb_info(info)) { | ||
1161 | info->var.width = hdmi->var.width; | 1163 | info->var.width = hdmi->var.width; |
1162 | info->var.height = hdmi->var.height; | 1164 | info->var.height = hdmi->var.height; |
1163 | sh_hdmi_display_on(hdmi, info); | 1165 | sh_hdmi_display_on(hdmi, info); |
1164 | unlock_fb_info(info); | 1166 | } else { |
1167 | /* New monitor or have to wake up */ | ||
1168 | fb_set_suspend(info, 0); | ||
1165 | } | 1169 | } |
1166 | } else { | ||
1167 | /* New monitor or have to wake up */ | ||
1168 | fb_set_suspend(info, 0); | ||
1169 | } | ||
1170 | 1170 | ||
1171 | console_unlock(); | 1171 | console_unlock(); |
1172 | unlock_fb_info(info); | ||
1173 | } | ||
1172 | } else { | 1174 | } else { |
1173 | ret = 0; | 1175 | ret = 0; |
1174 | if (!hdmi->info) | 1176 | if (!info) |
1175 | goto out; | 1177 | goto out; |
1176 | 1178 | ||
1177 | hdmi->monspec.modedb_len = 0; | 1179 | hdmi->monspec.modedb_len = 0; |
1178 | fb_destroy_modedb(hdmi->monspec.modedb); | 1180 | fb_destroy_modedb(hdmi->monspec.modedb); |
1179 | hdmi->monspec.modedb = NULL; | 1181 | hdmi->monspec.modedb = NULL; |
1180 | 1182 | ||
1181 | console_lock(); | 1183 | if (lock_fb_info(info)) { |
1184 | console_lock(); | ||
1182 | 1185 | ||
1183 | /* HDMI disconnect */ | 1186 | /* HDMI disconnect */ |
1184 | fb_set_suspend(hdmi->info, 1); | 1187 | fb_set_suspend(info, 1); |
1185 | 1188 | ||
1186 | console_unlock(); | 1189 | console_unlock(); |
1190 | unlock_fb_info(info); | ||
1191 | } | ||
1187 | } | 1192 | } |
1188 | 1193 | ||
1189 | out: | 1194 | out: |
diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c index b048417247e8..3a41c013d031 100644 --- a/drivers/video/sh_mobile_lcdcfb.c +++ b/drivers/video/sh_mobile_lcdcfb.c | |||
@@ -24,39 +24,14 @@ | |||
24 | #include <linux/backlight.h> | 24 | #include <linux/backlight.h> |
25 | #include <linux/gpio.h> | 25 | #include <linux/gpio.h> |
26 | #include <video/sh_mobile_lcdc.h> | 26 | #include <video/sh_mobile_lcdc.h> |
27 | #include <video/sh_mobile_meram.h> | ||
27 | #include <linux/atomic.h> | 28 | #include <linux/atomic.h> |
28 | 29 | ||
29 | #include "sh_mobile_lcdcfb.h" | 30 | #include "sh_mobile_lcdcfb.h" |
30 | #include "sh_mobile_meram.h" | ||
31 | 31 | ||
32 | #define SIDE_B_OFFSET 0x1000 | 32 | #define SIDE_B_OFFSET 0x1000 |
33 | #define MIRROR_OFFSET 0x2000 | 33 | #define MIRROR_OFFSET 0x2000 |
34 | 34 | ||
35 | /* shared registers */ | ||
36 | #define _LDDCKR 0x410 | ||
37 | #define _LDDCKSTPR 0x414 | ||
38 | #define _LDINTR 0x468 | ||
39 | #define _LDSR 0x46c | ||
40 | #define _LDCNT1R 0x470 | ||
41 | #define _LDCNT2R 0x474 | ||
42 | #define _LDRCNTR 0x478 | ||
43 | #define _LDDDSR 0x47c | ||
44 | #define _LDDWD0R 0x800 | ||
45 | #define _LDDRDR 0x840 | ||
46 | #define _LDDWAR 0x900 | ||
47 | #define _LDDRAR 0x904 | ||
48 | |||
49 | /* shared registers and their order for context save/restore */ | ||
50 | static int lcdc_shared_regs[] = { | ||
51 | _LDDCKR, | ||
52 | _LDDCKSTPR, | ||
53 | _LDINTR, | ||
54 | _LDDDSR, | ||
55 | _LDCNT1R, | ||
56 | _LDCNT2R, | ||
57 | }; | ||
58 | #define NR_SHARED_REGS ARRAY_SIZE(lcdc_shared_regs) | ||
59 | |||
60 | #define MAX_XRES 1920 | 35 | #define MAX_XRES 1920 |
61 | #define MAX_YRES 1080 | 36 | #define MAX_YRES 1080 |
62 | 37 | ||
@@ -98,22 +73,6 @@ static unsigned long lcdc_offs_sublcd[NR_CH_REGS] = { | |||
98 | [LDPMR] = 0x63c, | 73 | [LDPMR] = 0x63c, |
99 | }; | 74 | }; |
100 | 75 | ||
101 | #define START_LCDC 0x00000001 | ||
102 | #define LCDC_RESET 0x00000100 | ||
103 | #define DISPLAY_BEU 0x00000008 | ||
104 | #define LCDC_ENABLE 0x00000001 | ||
105 | #define LDINTR_FE 0x00000400 | ||
106 | #define LDINTR_VSE 0x00000200 | ||
107 | #define LDINTR_VEE 0x00000100 | ||
108 | #define LDINTR_FS 0x00000004 | ||
109 | #define LDINTR_VSS 0x00000002 | ||
110 | #define LDINTR_VES 0x00000001 | ||
111 | #define LDRCNTR_SRS 0x00020000 | ||
112 | #define LDRCNTR_SRC 0x00010000 | ||
113 | #define LDRCNTR_MRS 0x00000002 | ||
114 | #define LDRCNTR_MRC 0x00000001 | ||
115 | #define LDSR_MRS 0x00000100 | ||
116 | |||
117 | static const struct fb_videomode default_720p = { | 76 | static const struct fb_videomode default_720p = { |
118 | .name = "HDMI 720p", | 77 | .name = "HDMI 720p", |
119 | .xres = 1280, | 78 | .xres = 1280, |
@@ -141,7 +100,6 @@ struct sh_mobile_lcdc_priv { | |||
141 | unsigned long lddckr; | 100 | unsigned long lddckr; |
142 | struct sh_mobile_lcdc_chan ch[2]; | 101 | struct sh_mobile_lcdc_chan ch[2]; |
143 | struct notifier_block notifier; | 102 | struct notifier_block notifier; |
144 | unsigned long saved_shared_regs[NR_SHARED_REGS]; | ||
145 | int started; | 103 | int started; |
146 | int forced_bpp; /* 2 channel LCDC must share bpp setting */ | 104 | int forced_bpp; /* 2 channel LCDC must share bpp setting */ |
147 | struct sh_mobile_meram_info *meram_dev; | 105 | struct sh_mobile_meram_info *meram_dev; |
@@ -218,33 +176,36 @@ static void lcdc_sys_write_index(void *handle, unsigned long data) | |||
218 | { | 176 | { |
219 | struct sh_mobile_lcdc_chan *ch = handle; | 177 | struct sh_mobile_lcdc_chan *ch = handle; |
220 | 178 | ||
221 | lcdc_write(ch->lcdc, _LDDWD0R, data | 0x10000000); | 179 | lcdc_write(ch->lcdc, _LDDWD0R, data | LDDWDxR_WDACT); |
222 | lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0); | 180 | lcdc_wait_bit(ch->lcdc, _LDSR, LDSR_AS, 0); |
223 | lcdc_write(ch->lcdc, _LDDWAR, 1 | (lcdc_chan_is_sublcd(ch) ? 2 : 0)); | 181 | lcdc_write(ch->lcdc, _LDDWAR, LDDWAR_WA | |
224 | lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0); | 182 | (lcdc_chan_is_sublcd(ch) ? 2 : 0)); |
183 | lcdc_wait_bit(ch->lcdc, _LDSR, LDSR_AS, 0); | ||
225 | } | 184 | } |
226 | 185 | ||
227 | static void lcdc_sys_write_data(void *handle, unsigned long data) | 186 | static void lcdc_sys_write_data(void *handle, unsigned long data) |
228 | { | 187 | { |
229 | struct sh_mobile_lcdc_chan *ch = handle; | 188 | struct sh_mobile_lcdc_chan *ch = handle; |
230 | 189 | ||
231 | lcdc_write(ch->lcdc, _LDDWD0R, data | 0x11000000); | 190 | lcdc_write(ch->lcdc, _LDDWD0R, data | LDDWDxR_WDACT | LDDWDxR_RSW); |
232 | lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0); | 191 | lcdc_wait_bit(ch->lcdc, _LDSR, LDSR_AS, 0); |
233 | lcdc_write(ch->lcdc, _LDDWAR, 1 | (lcdc_chan_is_sublcd(ch) ? 2 : 0)); | 192 | lcdc_write(ch->lcdc, _LDDWAR, LDDWAR_WA | |
234 | lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0); | 193 | (lcdc_chan_is_sublcd(ch) ? 2 : 0)); |
194 | lcdc_wait_bit(ch->lcdc, _LDSR, LDSR_AS, 0); | ||
235 | } | 195 | } |
236 | 196 | ||
237 | static unsigned long lcdc_sys_read_data(void *handle) | 197 | static unsigned long lcdc_sys_read_data(void *handle) |
238 | { | 198 | { |
239 | struct sh_mobile_lcdc_chan *ch = handle; | 199 | struct sh_mobile_lcdc_chan *ch = handle; |
240 | 200 | ||
241 | lcdc_write(ch->lcdc, _LDDRDR, 0x01000000); | 201 | lcdc_write(ch->lcdc, _LDDRDR, LDDRDR_RSR); |
242 | lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0); | 202 | lcdc_wait_bit(ch->lcdc, _LDSR, LDSR_AS, 0); |
243 | lcdc_write(ch->lcdc, _LDDRAR, 1 | (lcdc_chan_is_sublcd(ch) ? 2 : 0)); | 203 | lcdc_write(ch->lcdc, _LDDRAR, LDDRAR_RA | |
204 | (lcdc_chan_is_sublcd(ch) ? 2 : 0)); | ||
244 | udelay(1); | 205 | udelay(1); |
245 | lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0); | 206 | lcdc_wait_bit(ch->lcdc, _LDSR, LDSR_AS, 0); |
246 | 207 | ||
247 | return lcdc_read(ch->lcdc, _LDDRDR) & 0x3ffff; | 208 | return lcdc_read(ch->lcdc, _LDDRDR) & LDDRDR_DRD_MASK; |
248 | } | 209 | } |
249 | 210 | ||
250 | struct sh_mobile_lcdc_sys_bus_ops sh_mobile_lcdc_sys_bus_ops = { | 211 | struct sh_mobile_lcdc_sys_bus_ops sh_mobile_lcdc_sys_bus_ops = { |
@@ -256,18 +217,22 @@ struct sh_mobile_lcdc_sys_bus_ops sh_mobile_lcdc_sys_bus_ops = { | |||
256 | static void sh_mobile_lcdc_clk_on(struct sh_mobile_lcdc_priv *priv) | 217 | static void sh_mobile_lcdc_clk_on(struct sh_mobile_lcdc_priv *priv) |
257 | { | 218 | { |
258 | if (atomic_inc_and_test(&priv->hw_usecnt)) { | 219 | if (atomic_inc_and_test(&priv->hw_usecnt)) { |
259 | pm_runtime_get_sync(priv->dev); | ||
260 | if (priv->dot_clk) | 220 | if (priv->dot_clk) |
261 | clk_enable(priv->dot_clk); | 221 | clk_enable(priv->dot_clk); |
222 | pm_runtime_get_sync(priv->dev); | ||
223 | if (priv->meram_dev && priv->meram_dev->pdev) | ||
224 | pm_runtime_get_sync(&priv->meram_dev->pdev->dev); | ||
262 | } | 225 | } |
263 | } | 226 | } |
264 | 227 | ||
265 | static void sh_mobile_lcdc_clk_off(struct sh_mobile_lcdc_priv *priv) | 228 | static void sh_mobile_lcdc_clk_off(struct sh_mobile_lcdc_priv *priv) |
266 | { | 229 | { |
267 | if (atomic_sub_return(1, &priv->hw_usecnt) == -1) { | 230 | if (atomic_sub_return(1, &priv->hw_usecnt) == -1) { |
231 | if (priv->meram_dev && priv->meram_dev->pdev) | ||
232 | pm_runtime_put_sync(&priv->meram_dev->pdev->dev); | ||
233 | pm_runtime_put(priv->dev); | ||
268 | if (priv->dot_clk) | 234 | if (priv->dot_clk) |
269 | clk_disable(priv->dot_clk); | 235 | clk_disable(priv->dot_clk); |
270 | pm_runtime_put(priv->dev); | ||
271 | } | 236 | } |
272 | } | 237 | } |
273 | 238 | ||
@@ -319,13 +284,13 @@ static void sh_mobile_lcdc_deferred_io(struct fb_info *info, | |||
319 | if (bcfg->start_transfer) | 284 | if (bcfg->start_transfer) |
320 | bcfg->start_transfer(bcfg->board_data, ch, | 285 | bcfg->start_transfer(bcfg->board_data, ch, |
321 | &sh_mobile_lcdc_sys_bus_ops); | 286 | &sh_mobile_lcdc_sys_bus_ops); |
322 | lcdc_write_chan(ch, LDSM2R, 1); | 287 | lcdc_write_chan(ch, LDSM2R, LDSM2R_OSTRG); |
323 | dma_unmap_sg(info->dev, ch->sglist, nr_pages, DMA_TO_DEVICE); | 288 | dma_unmap_sg(info->dev, ch->sglist, nr_pages, DMA_TO_DEVICE); |
324 | } else { | 289 | } else { |
325 | if (bcfg->start_transfer) | 290 | if (bcfg->start_transfer) |
326 | bcfg->start_transfer(bcfg->board_data, ch, | 291 | bcfg->start_transfer(bcfg->board_data, ch, |
327 | &sh_mobile_lcdc_sys_bus_ops); | 292 | &sh_mobile_lcdc_sys_bus_ops); |
328 | lcdc_write_chan(ch, LDSM2R, 1); | 293 | lcdc_write_chan(ch, LDSM2R, LDSM2R_OSTRG); |
329 | } | 294 | } |
330 | } | 295 | } |
331 | 296 | ||
@@ -341,22 +306,16 @@ static irqreturn_t sh_mobile_lcdc_irq(int irq, void *data) | |||
341 | { | 306 | { |
342 | struct sh_mobile_lcdc_priv *priv = data; | 307 | struct sh_mobile_lcdc_priv *priv = data; |
343 | struct sh_mobile_lcdc_chan *ch; | 308 | struct sh_mobile_lcdc_chan *ch; |
344 | unsigned long tmp; | ||
345 | unsigned long ldintr; | 309 | unsigned long ldintr; |
346 | int is_sub; | 310 | int is_sub; |
347 | int k; | 311 | int k; |
348 | 312 | ||
349 | /* acknowledge interrupt */ | 313 | /* Acknowledge interrupts and disable further VSYNC End IRQs. */ |
350 | ldintr = tmp = lcdc_read(priv, _LDINTR); | 314 | ldintr = lcdc_read(priv, _LDINTR); |
351 | /* | 315 | lcdc_write(priv, _LDINTR, (ldintr ^ LDINTR_STATUS_MASK) & ~LDINTR_VEE); |
352 | * disable further VSYNC End IRQs, preserve all other enabled IRQs, | ||
353 | * write 0 to bits 0-6 to ack all triggered IRQs. | ||
354 | */ | ||
355 | tmp &= 0xffffff00 & ~LDINTR_VEE; | ||
356 | lcdc_write(priv, _LDINTR, tmp); | ||
357 | 316 | ||
358 | /* figure out if this interrupt is for main or sub lcd */ | 317 | /* figure out if this interrupt is for main or sub lcd */ |
359 | is_sub = (lcdc_read(priv, _LDSR) & (1 << 10)) ? 1 : 0; | 318 | is_sub = (lcdc_read(priv, _LDSR) & LDSR_MSS) ? 1 : 0; |
360 | 319 | ||
361 | /* wake up channel and disable clocks */ | 320 | /* wake up channel and disable clocks */ |
362 | for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { | 321 | for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { |
@@ -365,7 +324,7 @@ static irqreturn_t sh_mobile_lcdc_irq(int irq, void *data) | |||
365 | if (!ch->enabled) | 324 | if (!ch->enabled) |
366 | continue; | 325 | continue; |
367 | 326 | ||
368 | /* Frame Start */ | 327 | /* Frame End */ |
369 | if (ldintr & LDINTR_FS) { | 328 | if (ldintr & LDINTR_FS) { |
370 | if (is_sub == lcdc_chan_is_sublcd(ch)) { | 329 | if (is_sub == lcdc_chan_is_sublcd(ch)) { |
371 | ch->frame_end = 1; | 330 | ch->frame_end = 1; |
@@ -391,16 +350,17 @@ static void sh_mobile_lcdc_start_stop(struct sh_mobile_lcdc_priv *priv, | |||
391 | 350 | ||
392 | /* start or stop the lcdc */ | 351 | /* start or stop the lcdc */ |
393 | if (start) | 352 | if (start) |
394 | lcdc_write(priv, _LDCNT2R, tmp | START_LCDC); | 353 | lcdc_write(priv, _LDCNT2R, tmp | LDCNT2R_DO); |
395 | else | 354 | else |
396 | lcdc_write(priv, _LDCNT2R, tmp & ~START_LCDC); | 355 | lcdc_write(priv, _LDCNT2R, tmp & ~LDCNT2R_DO); |
397 | 356 | ||
398 | /* wait until power is applied/stopped on all channels */ | 357 | /* wait until power is applied/stopped on all channels */ |
399 | for (k = 0; k < ARRAY_SIZE(priv->ch); k++) | 358 | for (k = 0; k < ARRAY_SIZE(priv->ch); k++) |
400 | if (lcdc_read(priv, _LDCNT2R) & priv->ch[k].enabled) | 359 | if (lcdc_read(priv, _LDCNT2R) & priv->ch[k].enabled) |
401 | while (1) { | 360 | while (1) { |
402 | tmp = lcdc_read_chan(&priv->ch[k], LDPMR) & 3; | 361 | tmp = lcdc_read_chan(&priv->ch[k], LDPMR) |
403 | if (start && tmp == 3) | 362 | & LDPMR_LPS; |
363 | if (start && tmp == LDPMR_LPS) | ||
404 | break; | 364 | break; |
405 | if (!start && tmp == 0) | 365 | if (!start && tmp == 0) |
406 | break; | 366 | break; |
@@ -418,13 +378,13 @@ static void sh_mobile_lcdc_geometry(struct sh_mobile_lcdc_chan *ch) | |||
418 | u32 tmp; | 378 | u32 tmp; |
419 | 379 | ||
420 | tmp = ch->ldmt1r_value; | 380 | tmp = ch->ldmt1r_value; |
421 | tmp |= (var->sync & FB_SYNC_VERT_HIGH_ACT) ? 0 : 1 << 28; | 381 | tmp |= (var->sync & FB_SYNC_VERT_HIGH_ACT) ? 0 : LDMT1R_VPOL; |
422 | tmp |= (var->sync & FB_SYNC_HOR_HIGH_ACT) ? 0 : 1 << 27; | 382 | tmp |= (var->sync & FB_SYNC_HOR_HIGH_ACT) ? 0 : LDMT1R_HPOL; |
423 | tmp |= (ch->cfg.flags & LCDC_FLAGS_DWPOL) ? 1 << 26 : 0; | 383 | tmp |= (ch->cfg.flags & LCDC_FLAGS_DWPOL) ? LDMT1R_DWPOL : 0; |
424 | tmp |= (ch->cfg.flags & LCDC_FLAGS_DIPOL) ? 1 << 25 : 0; | 384 | tmp |= (ch->cfg.flags & LCDC_FLAGS_DIPOL) ? LDMT1R_DIPOL : 0; |
425 | tmp |= (ch->cfg.flags & LCDC_FLAGS_DAPOL) ? 1 << 24 : 0; | 385 | tmp |= (ch->cfg.flags & LCDC_FLAGS_DAPOL) ? LDMT1R_DAPOL : 0; |
426 | tmp |= (ch->cfg.flags & LCDC_FLAGS_HSCNT) ? 1 << 17 : 0; | 386 | tmp |= (ch->cfg.flags & LCDC_FLAGS_HSCNT) ? LDMT1R_HSCNT : 0; |
427 | tmp |= (ch->cfg.flags & LCDC_FLAGS_DWCNT) ? 1 << 16 : 0; | 387 | tmp |= (ch->cfg.flags & LCDC_FLAGS_DWCNT) ? LDMT1R_DWCNT : 0; |
428 | lcdc_write_chan(ch, LDMT1R, tmp); | 388 | lcdc_write_chan(ch, LDMT1R, tmp); |
429 | 389 | ||
430 | /* setup SYS bus */ | 390 | /* setup SYS bus */ |
@@ -463,242 +423,239 @@ static void sh_mobile_lcdc_geometry(struct sh_mobile_lcdc_chan *ch) | |||
463 | lcdc_write_chan(ch, LDHAJR, tmp); | 423 | lcdc_write_chan(ch, LDHAJR, tmp); |
464 | } | 424 | } |
465 | 425 | ||
466 | static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv) | 426 | /* |
427 | * __sh_mobile_lcdc_start - Configure and tart the LCDC | ||
428 | * @priv: LCDC device | ||
429 | * | ||
430 | * Configure all enabled channels and start the LCDC device. All external | ||
431 | * devices (clocks, MERAM, panels, ...) are not touched by this function. | ||
432 | */ | ||
433 | static void __sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv) | ||
467 | { | 434 | { |
468 | struct sh_mobile_lcdc_chan *ch; | 435 | struct sh_mobile_lcdc_chan *ch; |
469 | struct sh_mobile_lcdc_board_cfg *board_cfg; | ||
470 | unsigned long tmp; | 436 | unsigned long tmp; |
471 | int bpp = 0; | 437 | int bpp = 0; |
472 | unsigned long ldddsr; | 438 | int k, m; |
473 | int k, m, ret; | ||
474 | 439 | ||
475 | /* enable clocks before accessing the hardware */ | 440 | /* Enable LCDC channels. Read data from external memory, avoid using the |
476 | for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { | 441 | * BEU for now. |
477 | if (priv->ch[k].enabled) { | 442 | */ |
478 | sh_mobile_lcdc_clk_on(priv); | 443 | lcdc_write(priv, _LDCNT2R, priv->ch[0].enabled | priv->ch[1].enabled); |
479 | if (!bpp) | ||
480 | bpp = priv->ch[k].info->var.bits_per_pixel; | ||
481 | } | ||
482 | } | ||
483 | |||
484 | /* reset */ | ||
485 | lcdc_write(priv, _LDCNT2R, lcdc_read(priv, _LDCNT2R) | LCDC_RESET); | ||
486 | lcdc_wait_bit(priv, _LDCNT2R, LCDC_RESET, 0); | ||
487 | |||
488 | /* enable LCDC channels */ | ||
489 | tmp = lcdc_read(priv, _LDCNT2R); | ||
490 | tmp |= priv->ch[0].enabled; | ||
491 | tmp |= priv->ch[1].enabled; | ||
492 | lcdc_write(priv, _LDCNT2R, tmp); | ||
493 | |||
494 | /* read data from external memory, avoid using the BEU for now */ | ||
495 | lcdc_write(priv, _LDCNT2R, lcdc_read(priv, _LDCNT2R) & ~DISPLAY_BEU); | ||
496 | 444 | ||
497 | /* stop the lcdc first */ | 445 | /* Stop the LCDC first and disable all interrupts. */ |
498 | sh_mobile_lcdc_start_stop(priv, 0); | 446 | sh_mobile_lcdc_start_stop(priv, 0); |
447 | lcdc_write(priv, _LDINTR, 0); | ||
499 | 448 | ||
500 | /* configure clocks */ | 449 | /* Configure power supply, dot clocks and start them. */ |
501 | tmp = priv->lddckr; | 450 | tmp = priv->lddckr; |
502 | for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { | 451 | for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { |
503 | ch = &priv->ch[k]; | 452 | ch = &priv->ch[k]; |
504 | 453 | if (!ch->enabled) | |
505 | if (!priv->ch[k].enabled) | ||
506 | continue; | 454 | continue; |
507 | 455 | ||
456 | if (!bpp) | ||
457 | bpp = ch->info->var.bits_per_pixel; | ||
458 | |||
459 | /* Power supply */ | ||
460 | lcdc_write_chan(ch, LDPMR, 0); | ||
461 | |||
508 | m = ch->cfg.clock_divider; | 462 | m = ch->cfg.clock_divider; |
509 | if (!m) | 463 | if (!m) |
510 | continue; | 464 | continue; |
511 | 465 | ||
512 | if (m == 1) | 466 | /* FIXME: sh7724 can only use 42, 48, 54 and 60 for the divider |
513 | m = 1 << 6; | 467 | * denominator. |
514 | tmp |= m << (lcdc_chan_is_sublcd(ch) ? 8 : 0); | 468 | */ |
515 | |||
516 | /* FIXME: sh7724 can only use 42, 48, 54 and 60 for the divider denominator */ | ||
517 | lcdc_write_chan(ch, LDDCKPAT1R, 0); | 469 | lcdc_write_chan(ch, LDDCKPAT1R, 0); |
518 | lcdc_write_chan(ch, LDDCKPAT2R, (1 << (m/2)) - 1); | 470 | lcdc_write_chan(ch, LDDCKPAT2R, (1 << (m/2)) - 1); |
471 | |||
472 | if (m == 1) | ||
473 | m = LDDCKR_MOSEL; | ||
474 | tmp |= m << (lcdc_chan_is_sublcd(ch) ? 8 : 0); | ||
519 | } | 475 | } |
520 | 476 | ||
521 | lcdc_write(priv, _LDDCKR, tmp); | 477 | lcdc_write(priv, _LDDCKR, tmp); |
522 | |||
523 | /* start dotclock again */ | ||
524 | lcdc_write(priv, _LDDCKSTPR, 0); | 478 | lcdc_write(priv, _LDDCKSTPR, 0); |
525 | lcdc_wait_bit(priv, _LDDCKSTPR, ~0, 0); | 479 | lcdc_wait_bit(priv, _LDDCKSTPR, ~0, 0); |
526 | 480 | ||
527 | /* interrupts are disabled to begin with */ | 481 | /* Setup geometry, format, frame buffer memory and operation mode. */ |
528 | lcdc_write(priv, _LDINTR, 0); | ||
529 | |||
530 | for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { | 482 | for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { |
531 | ch = &priv->ch[k]; | 483 | ch = &priv->ch[k]; |
532 | |||
533 | if (!ch->enabled) | 484 | if (!ch->enabled) |
534 | continue; | 485 | continue; |
535 | 486 | ||
536 | sh_mobile_lcdc_geometry(ch); | 487 | sh_mobile_lcdc_geometry(ch); |
537 | 488 | ||
538 | /* power supply */ | ||
539 | lcdc_write_chan(ch, LDPMR, 0); | ||
540 | |||
541 | board_cfg = &ch->cfg.board_cfg; | ||
542 | if (board_cfg->setup_sys) { | ||
543 | ret = board_cfg->setup_sys(board_cfg->board_data, | ||
544 | ch, &sh_mobile_lcdc_sys_bus_ops); | ||
545 | if (ret) | ||
546 | return ret; | ||
547 | } | ||
548 | } | ||
549 | |||
550 | /* word and long word swap */ | ||
551 | ldddsr = lcdc_read(priv, _LDDDSR); | ||
552 | if (priv->ch[0].info->var.nonstd) | ||
553 | lcdc_write(priv, _LDDDSR, ldddsr | 7); | ||
554 | else { | ||
555 | switch (bpp) { | ||
556 | case 16: | ||
557 | lcdc_write(priv, _LDDDSR, ldddsr | 6); | ||
558 | break; | ||
559 | case 24: | ||
560 | lcdc_write(priv, _LDDDSR, ldddsr | 7); | ||
561 | break; | ||
562 | case 32: | ||
563 | lcdc_write(priv, _LDDDSR, ldddsr | 4); | ||
564 | break; | ||
565 | } | ||
566 | } | ||
567 | |||
568 | for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { | ||
569 | unsigned long base_addr_y; | ||
570 | unsigned long base_addr_c = 0; | ||
571 | int pitch; | ||
572 | ch = &priv->ch[k]; | ||
573 | |||
574 | if (!priv->ch[k].enabled) | ||
575 | continue; | ||
576 | |||
577 | /* set bpp format in PKF[4:0] */ | ||
578 | tmp = lcdc_read_chan(ch, LDDFR); | ||
579 | tmp &= ~0x0003031f; | ||
580 | if (ch->info->var.nonstd) { | 489 | if (ch->info->var.nonstd) { |
581 | tmp |= (ch->info->var.nonstd << 16); | 490 | tmp = (ch->info->var.nonstd << 16); |
582 | switch (ch->info->var.bits_per_pixel) { | 491 | switch (ch->info->var.bits_per_pixel) { |
583 | case 12: | 492 | case 12: |
493 | tmp |= LDDFR_YF_420; | ||
584 | break; | 494 | break; |
585 | case 16: | 495 | case 16: |
586 | tmp |= (0x1 << 8); | 496 | tmp |= LDDFR_YF_422; |
587 | break; | 497 | break; |
588 | case 24: | 498 | case 24: |
589 | tmp |= (0x2 << 8); | 499 | default: |
500 | tmp |= LDDFR_YF_444; | ||
590 | break; | 501 | break; |
591 | } | 502 | } |
592 | } else { | 503 | } else { |
593 | switch (ch->info->var.bits_per_pixel) { | 504 | switch (ch->info->var.bits_per_pixel) { |
594 | case 16: | 505 | case 16: |
595 | tmp |= 0x03; | 506 | tmp = LDDFR_PKF_RGB16; |
596 | break; | 507 | break; |
597 | case 24: | 508 | case 24: |
598 | tmp |= 0x0b; | 509 | tmp = LDDFR_PKF_RGB24; |
599 | break; | 510 | break; |
600 | case 32: | 511 | case 32: |
512 | default: | ||
513 | tmp = LDDFR_PKF_ARGB32; | ||
601 | break; | 514 | break; |
602 | } | 515 | } |
603 | } | 516 | } |
517 | |||
604 | lcdc_write_chan(ch, LDDFR, tmp); | 518 | lcdc_write_chan(ch, LDDFR, tmp); |
519 | lcdc_write_chan(ch, LDMLSR, ch->pitch); | ||
520 | lcdc_write_chan(ch, LDSA1R, ch->base_addr_y); | ||
521 | if (ch->info->var.nonstd) | ||
522 | lcdc_write_chan(ch, LDSA2R, ch->base_addr_c); | ||
605 | 523 | ||
606 | base_addr_y = ch->info->fix.smem_start; | 524 | /* When using deferred I/O mode, configure the LCDC for one-shot |
607 | base_addr_c = base_addr_y + | 525 | * operation and enable the frame end interrupt. Otherwise use |
608 | ch->info->var.xres * | 526 | * continuous read mode. |
609 | ch->info->var.yres_virtual; | 527 | */ |
610 | pitch = ch->info->fix.line_length; | 528 | if (ch->ldmt1r_value & LDMT1R_IFM && |
529 | ch->cfg.sys_bus_cfg.deferred_io_msec) { | ||
530 | lcdc_write_chan(ch, LDSM1R, LDSM1R_OS); | ||
531 | lcdc_write(priv, _LDINTR, LDINTR_FE); | ||
532 | } else { | ||
533 | lcdc_write_chan(ch, LDSM1R, 0); | ||
534 | } | ||
535 | } | ||
611 | 536 | ||
612 | /* test if we can enable meram */ | 537 | /* Word and long word swap. */ |
613 | if (ch->cfg.meram_cfg && priv->meram_dev && | 538 | if (priv->ch[0].info->var.nonstd) |
614 | priv->meram_dev->ops) { | 539 | tmp = LDDDSR_LS | LDDDSR_WS | LDDDSR_BS; |
615 | struct sh_mobile_meram_cfg *cfg; | 540 | else { |
616 | struct sh_mobile_meram_info *mdev; | 541 | switch (bpp) { |
617 | unsigned long icb_addr_y, icb_addr_c; | 542 | case 16: |
618 | int icb_pitch; | 543 | tmp = LDDDSR_LS | LDDDSR_WS; |
619 | int pf; | 544 | break; |
545 | case 24: | ||
546 | tmp = LDDDSR_LS | LDDDSR_WS | LDDDSR_BS; | ||
547 | break; | ||
548 | case 32: | ||
549 | default: | ||
550 | tmp = LDDDSR_LS; | ||
551 | break; | ||
552 | } | ||
553 | } | ||
554 | lcdc_write(priv, _LDDDSR, tmp); | ||
620 | 555 | ||
621 | cfg = ch->cfg.meram_cfg; | 556 | /* Enable the display output. */ |
622 | mdev = priv->meram_dev; | 557 | lcdc_write(priv, _LDCNT1R, LDCNT1R_DE); |
623 | /* we need to de-init configured ICBs before we | 558 | sh_mobile_lcdc_start_stop(priv, 1); |
624 | * we can re-initialize them. | 559 | priv->started = 1; |
625 | */ | 560 | } |
626 | if (ch->meram_enabled) | ||
627 | mdev->ops->meram_unregister(mdev, cfg); | ||
628 | 561 | ||
629 | ch->meram_enabled = 0; | 562 | static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv) |
563 | { | ||
564 | struct sh_mobile_meram_info *mdev = priv->meram_dev; | ||
565 | struct sh_mobile_lcdc_board_cfg *board_cfg; | ||
566 | struct sh_mobile_lcdc_chan *ch; | ||
567 | unsigned long tmp; | ||
568 | int ret; | ||
569 | int k; | ||
630 | 570 | ||
631 | if (ch->info->var.nonstd) { | 571 | /* enable clocks before accessing the hardware */ |
632 | if (ch->info->var.bits_per_pixel == 24) | 572 | for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { |
633 | pf = SH_MOBILE_MERAM_PF_NV24; | 573 | if (priv->ch[k].enabled) |
634 | else | 574 | sh_mobile_lcdc_clk_on(priv); |
635 | pf = SH_MOBILE_MERAM_PF_NV; | 575 | } |
636 | } else { | ||
637 | pf = SH_MOBILE_MERAM_PF_RGB; | ||
638 | } | ||
639 | 576 | ||
640 | ret = mdev->ops->meram_register(mdev, cfg, pitch, | 577 | /* reset */ |
641 | ch->info->var.yres, | 578 | lcdc_write(priv, _LDCNT2R, lcdc_read(priv, _LDCNT2R) | LDCNT2R_BR); |
642 | pf, | 579 | lcdc_wait_bit(priv, _LDCNT2R, LDCNT2R_BR, 0); |
643 | base_addr_y, | ||
644 | base_addr_c, | ||
645 | &icb_addr_y, | ||
646 | &icb_addr_c, | ||
647 | &icb_pitch); | ||
648 | if (!ret) { | ||
649 | /* set LDSA1R value */ | ||
650 | base_addr_y = icb_addr_y; | ||
651 | pitch = icb_pitch; | ||
652 | |||
653 | /* set LDSA2R value if required */ | ||
654 | if (base_addr_c) | ||
655 | base_addr_c = icb_addr_c; | ||
656 | |||
657 | ch->meram_enabled = 1; | ||
658 | } | ||
659 | } | ||
660 | 580 | ||
661 | /* point out our frame buffer */ | 581 | for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { |
662 | lcdc_write_chan(ch, LDSA1R, base_addr_y); | 582 | ch = &priv->ch[k]; |
663 | if (ch->info->var.nonstd) | ||
664 | lcdc_write_chan(ch, LDSA2R, base_addr_c); | ||
665 | 583 | ||
666 | /* set line size */ | 584 | if (!ch->enabled) |
667 | lcdc_write_chan(ch, LDMLSR, pitch); | 585 | continue; |
668 | 586 | ||
669 | /* setup deferred io if SYS bus */ | 587 | board_cfg = &ch->cfg.board_cfg; |
670 | tmp = ch->cfg.sys_bus_cfg.deferred_io_msec; | 588 | if (board_cfg->setup_sys) { |
671 | if (ch->ldmt1r_value & (1 << 12) && tmp) { | 589 | ret = board_cfg->setup_sys(board_cfg->board_data, ch, |
672 | ch->defio.deferred_io = sh_mobile_lcdc_deferred_io; | 590 | &sh_mobile_lcdc_sys_bus_ops); |
673 | ch->defio.delay = msecs_to_jiffies(tmp); | 591 | if (ret) |
674 | ch->info->fbdefio = &ch->defio; | 592 | return ret; |
675 | fb_deferred_io_init(ch->info); | 593 | } |
594 | } | ||
676 | 595 | ||
677 | /* one-shot mode */ | 596 | /* Compute frame buffer base address and pitch for each channel. */ |
678 | lcdc_write_chan(ch, LDSM1R, 1); | 597 | for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { |
598 | struct sh_mobile_meram_cfg *cfg; | ||
599 | int pixelformat; | ||
679 | 600 | ||
680 | /* enable "Frame End Interrupt Enable" bit */ | 601 | ch = &priv->ch[k]; |
681 | lcdc_write(priv, _LDINTR, LDINTR_FE); | 602 | if (!ch->enabled) |
603 | continue; | ||
682 | 604 | ||
683 | } else { | 605 | ch->base_addr_y = ch->info->fix.smem_start; |
684 | /* continuous read mode */ | 606 | ch->base_addr_c = ch->base_addr_y |
685 | lcdc_write_chan(ch, LDSM1R, 0); | 607 | + ch->info->var.xres |
608 | * ch->info->var.yres_virtual; | ||
609 | ch->pitch = ch->info->fix.line_length; | ||
610 | |||
611 | /* Enable MERAM if possible. */ | ||
612 | cfg = ch->cfg.meram_cfg; | ||
613 | if (mdev == NULL || mdev->ops == NULL || cfg == NULL) | ||
614 | continue; | ||
615 | |||
616 | /* we need to de-init configured ICBs before we can | ||
617 | * re-initialize them. | ||
618 | */ | ||
619 | if (ch->meram_enabled) { | ||
620 | mdev->ops->meram_unregister(mdev, cfg); | ||
621 | ch->meram_enabled = 0; | ||
686 | } | 622 | } |
623 | |||
624 | if (!ch->info->var.nonstd) | ||
625 | pixelformat = SH_MOBILE_MERAM_PF_RGB; | ||
626 | else if (ch->info->var.bits_per_pixel == 24) | ||
627 | pixelformat = SH_MOBILE_MERAM_PF_NV24; | ||
628 | else | ||
629 | pixelformat = SH_MOBILE_MERAM_PF_NV; | ||
630 | |||
631 | ret = mdev->ops->meram_register(mdev, cfg, ch->pitch, | ||
632 | ch->info->var.yres, pixelformat, | ||
633 | ch->base_addr_y, ch->base_addr_c, | ||
634 | &ch->base_addr_y, &ch->base_addr_c, | ||
635 | &ch->pitch); | ||
636 | if (!ret) | ||
637 | ch->meram_enabled = 1; | ||
687 | } | 638 | } |
688 | 639 | ||
689 | /* display output */ | 640 | /* Start the LCDC. */ |
690 | lcdc_write(priv, _LDCNT1R, LCDC_ENABLE); | 641 | __sh_mobile_lcdc_start(priv); |
691 | 642 | ||
692 | /* start the lcdc */ | 643 | /* Setup deferred I/O, tell the board code to enable the panels, and |
693 | sh_mobile_lcdc_start_stop(priv, 1); | 644 | * turn backlight on. |
694 | priv->started = 1; | 645 | */ |
695 | |||
696 | /* tell the board code to enable the panel */ | ||
697 | for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { | 646 | for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { |
698 | ch = &priv->ch[k]; | 647 | ch = &priv->ch[k]; |
699 | if (!ch->enabled) | 648 | if (!ch->enabled) |
700 | continue; | 649 | continue; |
701 | 650 | ||
651 | tmp = ch->cfg.sys_bus_cfg.deferred_io_msec; | ||
652 | if (ch->ldmt1r_value & LDMT1R_IFM && tmp) { | ||
653 | ch->defio.deferred_io = sh_mobile_lcdc_deferred_io; | ||
654 | ch->defio.delay = msecs_to_jiffies(tmp); | ||
655 | ch->info->fbdefio = &ch->defio; | ||
656 | fb_deferred_io_init(ch->info); | ||
657 | } | ||
658 | |||
702 | board_cfg = &ch->cfg.board_cfg; | 659 | board_cfg = &ch->cfg.board_cfg; |
703 | if (board_cfg->display_on && try_module_get(board_cfg->owner)) { | 660 | if (board_cfg->display_on && try_module_get(board_cfg->owner)) { |
704 | board_cfg->display_on(board_cfg->board_data, ch->info); | 661 | board_cfg->display_on(board_cfg->board_data, ch->info); |
@@ -776,42 +733,42 @@ static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv) | |||
776 | 733 | ||
777 | static int sh_mobile_lcdc_check_interface(struct sh_mobile_lcdc_chan *ch) | 734 | static int sh_mobile_lcdc_check_interface(struct sh_mobile_lcdc_chan *ch) |
778 | { | 735 | { |
779 | int ifm, miftyp; | 736 | int interface_type = ch->cfg.interface_type; |
780 | 737 | ||
781 | switch (ch->cfg.interface_type) { | 738 | switch (interface_type) { |
782 | case RGB8: ifm = 0; miftyp = 0; break; | 739 | case RGB8: |
783 | case RGB9: ifm = 0; miftyp = 4; break; | 740 | case RGB9: |
784 | case RGB12A: ifm = 0; miftyp = 5; break; | 741 | case RGB12A: |
785 | case RGB12B: ifm = 0; miftyp = 6; break; | 742 | case RGB12B: |
786 | case RGB16: ifm = 0; miftyp = 7; break; | 743 | case RGB16: |
787 | case RGB18: ifm = 0; miftyp = 10; break; | 744 | case RGB18: |
788 | case RGB24: ifm = 0; miftyp = 11; break; | 745 | case RGB24: |
789 | case SYS8A: ifm = 1; miftyp = 0; break; | 746 | case SYS8A: |
790 | case SYS8B: ifm = 1; miftyp = 1; break; | 747 | case SYS8B: |
791 | case SYS8C: ifm = 1; miftyp = 2; break; | 748 | case SYS8C: |
792 | case SYS8D: ifm = 1; miftyp = 3; break; | 749 | case SYS8D: |
793 | case SYS9: ifm = 1; miftyp = 4; break; | 750 | case SYS9: |
794 | case SYS12: ifm = 1; miftyp = 5; break; | 751 | case SYS12: |
795 | case SYS16A: ifm = 1; miftyp = 7; break; | 752 | case SYS16A: |
796 | case SYS16B: ifm = 1; miftyp = 8; break; | 753 | case SYS16B: |
797 | case SYS16C: ifm = 1; miftyp = 9; break; | 754 | case SYS16C: |
798 | case SYS18: ifm = 1; miftyp = 10; break; | 755 | case SYS18: |
799 | case SYS24: ifm = 1; miftyp = 11; break; | 756 | case SYS24: |
800 | default: goto bad; | 757 | break; |
758 | default: | ||
759 | return -EINVAL; | ||
801 | } | 760 | } |
802 | 761 | ||
803 | /* SUBLCD only supports SYS interface */ | 762 | /* SUBLCD only supports SYS interface */ |
804 | if (lcdc_chan_is_sublcd(ch)) { | 763 | if (lcdc_chan_is_sublcd(ch)) { |
805 | if (ifm == 0) | 764 | if (!(interface_type & LDMT1R_IFM)) |
806 | goto bad; | 765 | return -EINVAL; |
807 | else | 766 | |
808 | ifm = 0; | 767 | interface_type &= ~LDMT1R_IFM; |
809 | } | 768 | } |
810 | 769 | ||
811 | ch->ldmt1r_value = (ifm << 12) | miftyp; | 770 | ch->ldmt1r_value = interface_type; |
812 | return 0; | 771 | return 0; |
813 | bad: | ||
814 | return -EINVAL; | ||
815 | } | 772 | } |
816 | 773 | ||
817 | static int sh_mobile_lcdc_setup_clocks(struct platform_device *pdev, | 774 | static int sh_mobile_lcdc_setup_clocks(struct platform_device *pdev, |
@@ -819,18 +776,24 @@ static int sh_mobile_lcdc_setup_clocks(struct platform_device *pdev, | |||
819 | struct sh_mobile_lcdc_priv *priv) | 776 | struct sh_mobile_lcdc_priv *priv) |
820 | { | 777 | { |
821 | char *str; | 778 | char *str; |
822 | int icksel; | ||
823 | 779 | ||
824 | switch (clock_source) { | 780 | switch (clock_source) { |
825 | case LCDC_CLK_BUS: str = "bus_clk"; icksel = 0; break; | 781 | case LCDC_CLK_BUS: |
826 | case LCDC_CLK_PERIPHERAL: str = "peripheral_clk"; icksel = 1; break; | 782 | str = "bus_clk"; |
827 | case LCDC_CLK_EXTERNAL: str = NULL; icksel = 2; break; | 783 | priv->lddckr = LDDCKR_ICKSEL_BUS; |
784 | break; | ||
785 | case LCDC_CLK_PERIPHERAL: | ||
786 | str = "peripheral_clk"; | ||
787 | priv->lddckr = LDDCKR_ICKSEL_MIPI; | ||
788 | break; | ||
789 | case LCDC_CLK_EXTERNAL: | ||
790 | str = NULL; | ||
791 | priv->lddckr = LDDCKR_ICKSEL_HDMI; | ||
792 | break; | ||
828 | default: | 793 | default: |
829 | return -EINVAL; | 794 | return -EINVAL; |
830 | } | 795 | } |
831 | 796 | ||
832 | priv->lddckr = icksel << 16; | ||
833 | |||
834 | if (str) { | 797 | if (str) { |
835 | priv->dot_clk = clk_get(&pdev->dev, str); | 798 | priv->dot_clk = clk_get(&pdev->dev, str); |
836 | if (IS_ERR(priv->dot_clk)) { | 799 | if (IS_ERR(priv->dot_clk)) { |
@@ -914,12 +877,12 @@ static int sh_mobile_fb_pan_display(struct fb_var_screeninfo *var, | |||
914 | unsigned long base_addr_y, base_addr_c; | 877 | unsigned long base_addr_y, base_addr_c; |
915 | unsigned long c_offset; | 878 | unsigned long c_offset; |
916 | 879 | ||
917 | if (!var->nonstd) | 880 | if (!info->var.nonstd) |
918 | new_pan_offset = (var->yoffset * info->fix.line_length) + | 881 | new_pan_offset = var->yoffset * info->fix.line_length |
919 | (var->xoffset * (info->var.bits_per_pixel / 8)); | 882 | + var->xoffset * (info->var.bits_per_pixel / 8); |
920 | else | 883 | else |
921 | new_pan_offset = (var->yoffset * info->fix.line_length) + | 884 | new_pan_offset = var->yoffset * info->fix.line_length |
922 | (var->xoffset); | 885 | + var->xoffset; |
923 | 886 | ||
924 | if (new_pan_offset == ch->pan_offset) | 887 | if (new_pan_offset == ch->pan_offset) |
925 | return 0; /* No change, do nothing */ | 888 | return 0; /* No change, do nothing */ |
@@ -928,44 +891,40 @@ static int sh_mobile_fb_pan_display(struct fb_var_screeninfo *var, | |||
928 | 891 | ||
929 | /* Set the source address for the next refresh */ | 892 | /* Set the source address for the next refresh */ |
930 | base_addr_y = ch->dma_handle + new_pan_offset; | 893 | base_addr_y = ch->dma_handle + new_pan_offset; |
931 | if (var->nonstd) { | 894 | if (info->var.nonstd) { |
932 | /* Set y offset */ | 895 | /* Set y offset */ |
933 | c_offset = (var->yoffset * | 896 | c_offset = var->yoffset * info->fix.line_length |
934 | info->fix.line_length * | 897 | * (info->var.bits_per_pixel - 8) / 8; |
935 | (info->var.bits_per_pixel - 8)) / 8; | 898 | base_addr_c = ch->dma_handle |
936 | base_addr_c = ch->dma_handle + var->xres * var->yres_virtual + | 899 | + info->var.xres * info->var.yres_virtual |
937 | c_offset; | 900 | + c_offset; |
938 | /* Set x offset */ | 901 | /* Set x offset */ |
939 | if (info->var.bits_per_pixel == 24) | 902 | if (info->var.bits_per_pixel == 24) |
940 | base_addr_c += 2 * var->xoffset; | 903 | base_addr_c += 2 * var->xoffset; |
941 | else | 904 | else |
942 | base_addr_c += var->xoffset; | 905 | base_addr_c += var->xoffset; |
943 | } else | 906 | } |
944 | base_addr_c = 0; | ||
945 | 907 | ||
946 | if (!ch->meram_enabled) { | 908 | if (ch->meram_enabled) { |
947 | lcdc_write_chan_mirror(ch, LDSA1R, base_addr_y); | ||
948 | if (base_addr_c) | ||
949 | lcdc_write_chan_mirror(ch, LDSA2R, base_addr_c); | ||
950 | } else { | ||
951 | struct sh_mobile_meram_cfg *cfg; | 909 | struct sh_mobile_meram_cfg *cfg; |
952 | struct sh_mobile_meram_info *mdev; | 910 | struct sh_mobile_meram_info *mdev; |
953 | unsigned long icb_addr_y, icb_addr_c; | ||
954 | int ret; | 911 | int ret; |
955 | 912 | ||
956 | cfg = ch->cfg.meram_cfg; | 913 | cfg = ch->cfg.meram_cfg; |
957 | mdev = priv->meram_dev; | 914 | mdev = priv->meram_dev; |
958 | ret = mdev->ops->meram_update(mdev, cfg, | 915 | ret = mdev->ops->meram_update(mdev, cfg, |
959 | base_addr_y, base_addr_c, | 916 | base_addr_y, base_addr_c, |
960 | &icb_addr_y, &icb_addr_c); | 917 | &base_addr_y, &base_addr_c); |
961 | if (ret) | 918 | if (ret) |
962 | return ret; | 919 | return ret; |
920 | } | ||
963 | 921 | ||
964 | lcdc_write_chan_mirror(ch, LDSA1R, icb_addr_y); | 922 | ch->base_addr_y = base_addr_y; |
965 | if (icb_addr_c) | 923 | ch->base_addr_c = base_addr_c; |
966 | lcdc_write_chan_mirror(ch, LDSA2R, icb_addr_c); | ||
967 | 924 | ||
968 | } | 925 | lcdc_write_chan_mirror(ch, LDSA1R, base_addr_y); |
926 | if (info->var.nonstd) | ||
927 | lcdc_write_chan_mirror(ch, LDSA2R, base_addr_c); | ||
969 | 928 | ||
970 | if (lcdc_chan_is_sublcd(ch)) | 929 | if (lcdc_chan_is_sublcd(ch)) |
971 | lcdc_write(ch->lcdc, _LDRCNTR, ldrcntr ^ LDRCNTR_SRS); | 930 | lcdc_write(ch->lcdc, _LDRCNTR, ldrcntr ^ LDRCNTR_SRS); |
@@ -985,9 +944,11 @@ static int sh_mobile_wait_for_vsync(struct fb_info *info) | |||
985 | unsigned long ldintr; | 944 | unsigned long ldintr; |
986 | int ret; | 945 | int ret; |
987 | 946 | ||
988 | /* Enable VSync End interrupt */ | 947 | /* Enable VSync End interrupt and be careful not to acknowledge any |
948 | * pending interrupt. | ||
949 | */ | ||
989 | ldintr = lcdc_read(ch->lcdc, _LDINTR); | 950 | ldintr = lcdc_read(ch->lcdc, _LDINTR); |
990 | ldintr |= LDINTR_VEE; | 951 | ldintr |= LDINTR_VEE | LDINTR_STATUS_MASK; |
991 | lcdc_write(ch->lcdc, _LDINTR, ldintr); | 952 | lcdc_write(ch->lcdc, _LDINTR, ldintr); |
992 | 953 | ||
993 | ret = wait_for_completion_interruptible_timeout(&ch->vsync_completion, | 954 | ret = wait_for_completion_interruptible_timeout(&ch->vsync_completion, |
@@ -1037,11 +998,6 @@ static void sh_mobile_fb_reconfig(struct fb_info *info) | |||
1037 | /* Couldn't reconfigure, hopefully, can continue as before */ | 998 | /* Couldn't reconfigure, hopefully, can continue as before */ |
1038 | return; | 999 | return; |
1039 | 1000 | ||
1040 | if (info->var.nonstd) | ||
1041 | info->fix.line_length = mode1.xres; | ||
1042 | else | ||
1043 | info->fix.line_length = mode1.xres * (ch->cfg.bpp / 8); | ||
1044 | |||
1045 | /* | 1001 | /* |
1046 | * fb_set_var() calls the notifier change internally, only if | 1002 | * fb_set_var() calls the notifier change internally, only if |
1047 | * FBINFO_MISC_USEREVENT flag is set. Since we do not want to fake a | 1003 | * FBINFO_MISC_USEREVENT flag is set. Since we do not want to fake a |
@@ -1094,30 +1050,126 @@ static int sh_mobile_check_var(struct fb_var_screeninfo *var, struct fb_info *in | |||
1094 | { | 1050 | { |
1095 | struct sh_mobile_lcdc_chan *ch = info->par; | 1051 | struct sh_mobile_lcdc_chan *ch = info->par; |
1096 | struct sh_mobile_lcdc_priv *p = ch->lcdc; | 1052 | struct sh_mobile_lcdc_priv *p = ch->lcdc; |
1053 | unsigned int best_dist = (unsigned int)-1; | ||
1054 | unsigned int best_xres = 0; | ||
1055 | unsigned int best_yres = 0; | ||
1056 | unsigned int i; | ||
1097 | 1057 | ||
1098 | if (var->xres > MAX_XRES || var->yres > MAX_YRES || | 1058 | if (var->xres > MAX_XRES || var->yres > MAX_YRES) |
1099 | var->xres * var->yres * (ch->cfg.bpp / 8) * 2 > info->fix.smem_len) { | ||
1100 | dev_warn(info->dev, "Invalid info: %u-%u-%u-%u x %u-%u-%u-%u @ %lukHz!\n", | ||
1101 | var->left_margin, var->xres, var->right_margin, var->hsync_len, | ||
1102 | var->upper_margin, var->yres, var->lower_margin, var->vsync_len, | ||
1103 | PICOS2KHZ(var->pixclock)); | ||
1104 | return -EINVAL; | 1059 | return -EINVAL; |
1060 | |||
1061 | /* If board code provides us with a list of available modes, make sure | ||
1062 | * we use one of them. Find the mode closest to the requested one. The | ||
1063 | * distance between two modes is defined as the size of the | ||
1064 | * non-overlapping parts of the two rectangles. | ||
1065 | */ | ||
1066 | for (i = 0; i < ch->cfg.num_cfg; ++i) { | ||
1067 | const struct fb_videomode *mode = &ch->cfg.lcd_cfg[i]; | ||
1068 | unsigned int dist; | ||
1069 | |||
1070 | /* We can only round up. */ | ||
1071 | if (var->xres > mode->xres || var->yres > mode->yres) | ||
1072 | continue; | ||
1073 | |||
1074 | dist = var->xres * var->yres + mode->xres * mode->yres | ||
1075 | - 2 * min(var->xres, mode->xres) | ||
1076 | * min(var->yres, mode->yres); | ||
1077 | |||
1078 | if (dist < best_dist) { | ||
1079 | best_xres = mode->xres; | ||
1080 | best_yres = mode->yres; | ||
1081 | best_dist = dist; | ||
1082 | } | ||
1083 | } | ||
1084 | |||
1085 | /* If no available mode can be used, return an error. */ | ||
1086 | if (ch->cfg.num_cfg != 0) { | ||
1087 | if (best_dist == (unsigned int)-1) | ||
1088 | return -EINVAL; | ||
1089 | |||
1090 | var->xres = best_xres; | ||
1091 | var->yres = best_yres; | ||
1105 | } | 1092 | } |
1106 | 1093 | ||
1094 | /* Make sure the virtual resolution is at least as big as the visible | ||
1095 | * resolution. | ||
1096 | */ | ||
1097 | if (var->xres_virtual < var->xres) | ||
1098 | var->xres_virtual = var->xres; | ||
1099 | if (var->yres_virtual < var->yres) | ||
1100 | var->yres_virtual = var->yres; | ||
1101 | |||
1102 | if (var->bits_per_pixel <= 16) { /* RGB 565 */ | ||
1103 | var->bits_per_pixel = 16; | ||
1104 | var->red.offset = 11; | ||
1105 | var->red.length = 5; | ||
1106 | var->green.offset = 5; | ||
1107 | var->green.length = 6; | ||
1108 | var->blue.offset = 0; | ||
1109 | var->blue.length = 5; | ||
1110 | var->transp.offset = 0; | ||
1111 | var->transp.length = 0; | ||
1112 | } else if (var->bits_per_pixel <= 24) { /* RGB 888 */ | ||
1113 | var->bits_per_pixel = 24; | ||
1114 | var->red.offset = 16; | ||
1115 | var->red.length = 8; | ||
1116 | var->green.offset = 8; | ||
1117 | var->green.length = 8; | ||
1118 | var->blue.offset = 0; | ||
1119 | var->blue.length = 8; | ||
1120 | var->transp.offset = 0; | ||
1121 | var->transp.length = 0; | ||
1122 | } else if (var->bits_per_pixel <= 32) { /* RGBA 888 */ | ||
1123 | var->bits_per_pixel = 32; | ||
1124 | var->red.offset = 16; | ||
1125 | var->red.length = 8; | ||
1126 | var->green.offset = 8; | ||
1127 | var->green.length = 8; | ||
1128 | var->blue.offset = 0; | ||
1129 | var->blue.length = 8; | ||
1130 | var->transp.offset = 24; | ||
1131 | var->transp.length = 8; | ||
1132 | } else | ||
1133 | return -EINVAL; | ||
1134 | |||
1135 | var->red.msb_right = 0; | ||
1136 | var->green.msb_right = 0; | ||
1137 | var->blue.msb_right = 0; | ||
1138 | var->transp.msb_right = 0; | ||
1139 | |||
1140 | /* Make sure we don't exceed our allocated memory. */ | ||
1141 | if (var->xres_virtual * var->yres_virtual * var->bits_per_pixel / 8 > | ||
1142 | info->fix.smem_len) | ||
1143 | return -EINVAL; | ||
1144 | |||
1107 | /* only accept the forced_bpp for dual channel configurations */ | 1145 | /* only accept the forced_bpp for dual channel configurations */ |
1108 | if (p->forced_bpp && p->forced_bpp != var->bits_per_pixel) | 1146 | if (p->forced_bpp && p->forced_bpp != var->bits_per_pixel) |
1109 | return -EINVAL; | 1147 | return -EINVAL; |
1110 | 1148 | ||
1111 | switch (var->bits_per_pixel) { | 1149 | return 0; |
1112 | case 16: /* PKF[4:0] = 00011 - RGB 565 */ | 1150 | } |
1113 | case 24: /* PKF[4:0] = 01011 - RGB 888 */ | 1151 | |
1114 | case 32: /* PKF[4:0] = 00000 - RGBA 888 */ | 1152 | static int sh_mobile_set_par(struct fb_info *info) |
1115 | break; | 1153 | { |
1116 | default: | 1154 | struct sh_mobile_lcdc_chan *ch = info->par; |
1117 | return -EINVAL; | 1155 | u32 line_length = info->fix.line_length; |
1156 | int ret; | ||
1157 | |||
1158 | sh_mobile_lcdc_stop(ch->lcdc); | ||
1159 | |||
1160 | if (info->var.nonstd) | ||
1161 | info->fix.line_length = info->var.xres; | ||
1162 | else | ||
1163 | info->fix.line_length = info->var.xres | ||
1164 | * info->var.bits_per_pixel / 8; | ||
1165 | |||
1166 | ret = sh_mobile_lcdc_start(ch->lcdc); | ||
1167 | if (ret < 0) { | ||
1168 | dev_err(info->dev, "%s: unable to restart LCDC\n", __func__); | ||
1169 | info->fix.line_length = line_length; | ||
1118 | } | 1170 | } |
1119 | 1171 | ||
1120 | return 0; | 1172 | return ret; |
1121 | } | 1173 | } |
1122 | 1174 | ||
1123 | /* | 1175 | /* |
@@ -1177,6 +1229,7 @@ static struct fb_ops sh_mobile_lcdc_ops = { | |||
1177 | .fb_open = sh_mobile_open, | 1229 | .fb_open = sh_mobile_open, |
1178 | .fb_release = sh_mobile_release, | 1230 | .fb_release = sh_mobile_release, |
1179 | .fb_check_var = sh_mobile_check_var, | 1231 | .fb_check_var = sh_mobile_check_var, |
1232 | .fb_set_par = sh_mobile_set_par, | ||
1180 | }; | 1233 | }; |
1181 | 1234 | ||
1182 | static int sh_mobile_lcdc_update_bl(struct backlight_device *bdev) | 1235 | static int sh_mobile_lcdc_update_bl(struct backlight_device *bdev) |
@@ -1238,66 +1291,6 @@ static void sh_mobile_lcdc_bl_remove(struct backlight_device *bdev) | |||
1238 | backlight_device_unregister(bdev); | 1291 | backlight_device_unregister(bdev); |
1239 | } | 1292 | } |
1240 | 1293 | ||
1241 | static int sh_mobile_lcdc_set_bpp(struct fb_var_screeninfo *var, int bpp, | ||
1242 | int nonstd) | ||
1243 | { | ||
1244 | if (nonstd) { | ||
1245 | switch (bpp) { | ||
1246 | case 12: | ||
1247 | case 16: | ||
1248 | case 24: | ||
1249 | var->bits_per_pixel = bpp; | ||
1250 | var->nonstd = nonstd; | ||
1251 | return 0; | ||
1252 | default: | ||
1253 | return -EINVAL; | ||
1254 | } | ||
1255 | } | ||
1256 | |||
1257 | switch (bpp) { | ||
1258 | case 16: /* PKF[4:0] = 00011 - RGB 565 */ | ||
1259 | var->red.offset = 11; | ||
1260 | var->red.length = 5; | ||
1261 | var->green.offset = 5; | ||
1262 | var->green.length = 6; | ||
1263 | var->blue.offset = 0; | ||
1264 | var->blue.length = 5; | ||
1265 | var->transp.offset = 0; | ||
1266 | var->transp.length = 0; | ||
1267 | break; | ||
1268 | |||
1269 | case 24: /* PKF[4:0] = 01011 - RGB 888 */ | ||
1270 | var->red.offset = 16; | ||
1271 | var->red.length = 8; | ||
1272 | var->green.offset = 8; | ||
1273 | var->green.length = 8; | ||
1274 | var->blue.offset = 0; | ||
1275 | var->blue.length = 8; | ||
1276 | var->transp.offset = 0; | ||
1277 | var->transp.length = 0; | ||
1278 | break; | ||
1279 | |||
1280 | case 32: /* PKF[4:0] = 00000 - RGBA 888 */ | ||
1281 | var->red.offset = 16; | ||
1282 | var->red.length = 8; | ||
1283 | var->green.offset = 8; | ||
1284 | var->green.length = 8; | ||
1285 | var->blue.offset = 0; | ||
1286 | var->blue.length = 8; | ||
1287 | var->transp.offset = 24; | ||
1288 | var->transp.length = 8; | ||
1289 | break; | ||
1290 | default: | ||
1291 | return -EINVAL; | ||
1292 | } | ||
1293 | var->bits_per_pixel = bpp; | ||
1294 | var->red.msb_right = 0; | ||
1295 | var->green.msb_right = 0; | ||
1296 | var->blue.msb_right = 0; | ||
1297 | var->transp.msb_right = 0; | ||
1298 | return 0; | ||
1299 | } | ||
1300 | |||
1301 | static int sh_mobile_lcdc_suspend(struct device *dev) | 1294 | static int sh_mobile_lcdc_suspend(struct device *dev) |
1302 | { | 1295 | { |
1303 | struct platform_device *pdev = to_platform_device(dev); | 1296 | struct platform_device *pdev = to_platform_device(dev); |
@@ -1316,47 +1309,20 @@ static int sh_mobile_lcdc_resume(struct device *dev) | |||
1316 | static int sh_mobile_lcdc_runtime_suspend(struct device *dev) | 1309 | static int sh_mobile_lcdc_runtime_suspend(struct device *dev) |
1317 | { | 1310 | { |
1318 | struct platform_device *pdev = to_platform_device(dev); | 1311 | struct platform_device *pdev = to_platform_device(dev); |
1319 | struct sh_mobile_lcdc_priv *p = platform_get_drvdata(pdev); | 1312 | struct sh_mobile_lcdc_priv *priv = platform_get_drvdata(pdev); |
1320 | struct sh_mobile_lcdc_chan *ch; | ||
1321 | int k, n; | ||
1322 | |||
1323 | /* save per-channel registers */ | ||
1324 | for (k = 0; k < ARRAY_SIZE(p->ch); k++) { | ||
1325 | ch = &p->ch[k]; | ||
1326 | if (!ch->enabled) | ||
1327 | continue; | ||
1328 | for (n = 0; n < NR_CH_REGS; n++) | ||
1329 | ch->saved_ch_regs[n] = lcdc_read_chan(ch, n); | ||
1330 | } | ||
1331 | |||
1332 | /* save shared registers */ | ||
1333 | for (n = 0; n < NR_SHARED_REGS; n++) | ||
1334 | p->saved_shared_regs[n] = lcdc_read(p, lcdc_shared_regs[n]); | ||
1335 | 1313 | ||
1336 | /* turn off LCDC hardware */ | 1314 | /* turn off LCDC hardware */ |
1337 | lcdc_write(p, _LDCNT1R, 0); | 1315 | lcdc_write(priv, _LDCNT1R, 0); |
1316 | |||
1338 | return 0; | 1317 | return 0; |
1339 | } | 1318 | } |
1340 | 1319 | ||
1341 | static int sh_mobile_lcdc_runtime_resume(struct device *dev) | 1320 | static int sh_mobile_lcdc_runtime_resume(struct device *dev) |
1342 | { | 1321 | { |
1343 | struct platform_device *pdev = to_platform_device(dev); | 1322 | struct platform_device *pdev = to_platform_device(dev); |
1344 | struct sh_mobile_lcdc_priv *p = platform_get_drvdata(pdev); | 1323 | struct sh_mobile_lcdc_priv *priv = platform_get_drvdata(pdev); |
1345 | struct sh_mobile_lcdc_chan *ch; | ||
1346 | int k, n; | ||
1347 | |||
1348 | /* restore per-channel registers */ | ||
1349 | for (k = 0; k < ARRAY_SIZE(p->ch); k++) { | ||
1350 | ch = &p->ch[k]; | ||
1351 | if (!ch->enabled) | ||
1352 | continue; | ||
1353 | for (n = 0; n < NR_CH_REGS; n++) | ||
1354 | lcdc_write_chan(ch, n, ch->saved_ch_regs[n]); | ||
1355 | } | ||
1356 | 1324 | ||
1357 | /* restore shared registers */ | 1325 | __sh_mobile_lcdc_start(priv); |
1358 | for (n = 0; n < NR_SHARED_REGS; n++) | ||
1359 | lcdc_write(p, lcdc_shared_regs[n], p->saved_shared_regs[n]); | ||
1360 | 1326 | ||
1361 | return 0; | 1327 | return 0; |
1362 | } | 1328 | } |
@@ -1408,17 +1374,187 @@ static int sh_mobile_lcdc_notify(struct notifier_block *nb, | |||
1408 | return NOTIFY_OK; | 1374 | return NOTIFY_OK; |
1409 | } | 1375 | } |
1410 | 1376 | ||
1411 | static int sh_mobile_lcdc_remove(struct platform_device *pdev); | 1377 | static int sh_mobile_lcdc_remove(struct platform_device *pdev) |
1378 | { | ||
1379 | struct sh_mobile_lcdc_priv *priv = platform_get_drvdata(pdev); | ||
1380 | struct fb_info *info; | ||
1381 | int i; | ||
1412 | 1382 | ||
1413 | static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev) | 1383 | fb_unregister_client(&priv->notifier); |
1384 | |||
1385 | for (i = 0; i < ARRAY_SIZE(priv->ch); i++) | ||
1386 | if (priv->ch[i].info && priv->ch[i].info->dev) | ||
1387 | unregister_framebuffer(priv->ch[i].info); | ||
1388 | |||
1389 | sh_mobile_lcdc_stop(priv); | ||
1390 | |||
1391 | for (i = 0; i < ARRAY_SIZE(priv->ch); i++) { | ||
1392 | info = priv->ch[i].info; | ||
1393 | |||
1394 | if (!info || !info->device) | ||
1395 | continue; | ||
1396 | |||
1397 | if (priv->ch[i].sglist) | ||
1398 | vfree(priv->ch[i].sglist); | ||
1399 | |||
1400 | if (info->screen_base) | ||
1401 | dma_free_coherent(&pdev->dev, info->fix.smem_len, | ||
1402 | info->screen_base, | ||
1403 | priv->ch[i].dma_handle); | ||
1404 | fb_dealloc_cmap(&info->cmap); | ||
1405 | framebuffer_release(info); | ||
1406 | } | ||
1407 | |||
1408 | for (i = 0; i < ARRAY_SIZE(priv->ch); i++) { | ||
1409 | if (priv->ch[i].bl) | ||
1410 | sh_mobile_lcdc_bl_remove(priv->ch[i].bl); | ||
1411 | } | ||
1412 | |||
1413 | if (priv->dot_clk) | ||
1414 | clk_put(priv->dot_clk); | ||
1415 | |||
1416 | if (priv->dev) | ||
1417 | pm_runtime_disable(priv->dev); | ||
1418 | |||
1419 | if (priv->base) | ||
1420 | iounmap(priv->base); | ||
1421 | |||
1422 | if (priv->irq) | ||
1423 | free_irq(priv->irq, priv); | ||
1424 | kfree(priv); | ||
1425 | return 0; | ||
1426 | } | ||
1427 | |||
1428 | static int __devinit sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_chan *ch, | ||
1429 | struct device *dev) | ||
1414 | { | 1430 | { |
1431 | struct sh_mobile_lcdc_chan_cfg *cfg = &ch->cfg; | ||
1432 | const struct fb_videomode *max_mode; | ||
1433 | const struct fb_videomode *mode; | ||
1434 | struct fb_var_screeninfo *var; | ||
1415 | struct fb_info *info; | 1435 | struct fb_info *info; |
1416 | struct sh_mobile_lcdc_priv *priv; | 1436 | unsigned int max_size; |
1437 | int num_cfg; | ||
1438 | void *buf; | ||
1439 | int ret; | ||
1440 | int i; | ||
1441 | |||
1442 | mutex_init(&ch->open_lock); | ||
1443 | |||
1444 | /* Allocate the frame buffer device. */ | ||
1445 | ch->info = framebuffer_alloc(0, dev); | ||
1446 | if (!ch->info) { | ||
1447 | dev_err(dev, "unable to allocate fb_info\n"); | ||
1448 | return -ENOMEM; | ||
1449 | } | ||
1450 | |||
1451 | info = ch->info; | ||
1452 | info->fbops = &sh_mobile_lcdc_ops; | ||
1453 | info->par = ch; | ||
1454 | info->pseudo_palette = &ch->pseudo_palette; | ||
1455 | info->flags = FBINFO_FLAG_DEFAULT; | ||
1456 | |||
1457 | /* Iterate through the modes to validate them and find the highest | ||
1458 | * resolution. | ||
1459 | */ | ||
1460 | max_mode = NULL; | ||
1461 | max_size = 0; | ||
1462 | |||
1463 | for (i = 0, mode = cfg->lcd_cfg; i < cfg->num_cfg; i++, mode++) { | ||
1464 | unsigned int size = mode->yres * mode->xres; | ||
1465 | |||
1466 | /* NV12 buffers must have even number of lines */ | ||
1467 | if ((cfg->nonstd) && cfg->bpp == 12 && | ||
1468 | (mode->yres & 0x1)) { | ||
1469 | dev_err(dev, "yres must be multiple of 2 for YCbCr420 " | ||
1470 | "mode.\n"); | ||
1471 | return -EINVAL; | ||
1472 | } | ||
1473 | |||
1474 | if (size > max_size) { | ||
1475 | max_mode = mode; | ||
1476 | max_size = size; | ||
1477 | } | ||
1478 | } | ||
1479 | |||
1480 | if (!max_size) | ||
1481 | max_size = MAX_XRES * MAX_YRES; | ||
1482 | else | ||
1483 | dev_dbg(dev, "Found largest videomode %ux%u\n", | ||
1484 | max_mode->xres, max_mode->yres); | ||
1485 | |||
1486 | /* Initialize fixed screen information. Restrict pan to 2 lines steps | ||
1487 | * for NV12. | ||
1488 | */ | ||
1489 | info->fix = sh_mobile_lcdc_fix; | ||
1490 | info->fix.smem_len = max_size * 2 * cfg->bpp / 8; | ||
1491 | if (cfg->nonstd && cfg->bpp == 12) | ||
1492 | info->fix.ypanstep = 2; | ||
1493 | |||
1494 | /* Create the mode list. */ | ||
1495 | if (cfg->lcd_cfg == NULL) { | ||
1496 | mode = &default_720p; | ||
1497 | num_cfg = 1; | ||
1498 | } else { | ||
1499 | mode = cfg->lcd_cfg; | ||
1500 | num_cfg = cfg->num_cfg; | ||
1501 | } | ||
1502 | |||
1503 | fb_videomode_to_modelist(mode, num_cfg, &info->modelist); | ||
1504 | |||
1505 | /* Initialize variable screen information using the first mode as | ||
1506 | * default. The default Y virtual resolution is twice the panel size to | ||
1507 | * allow for double-buffering. | ||
1508 | */ | ||
1509 | var = &info->var; | ||
1510 | fb_videomode_to_var(var, mode); | ||
1511 | var->bits_per_pixel = cfg->bpp; | ||
1512 | var->width = cfg->lcd_size_cfg.width; | ||
1513 | var->height = cfg->lcd_size_cfg.height; | ||
1514 | var->yres_virtual = var->yres * 2; | ||
1515 | var->activate = FB_ACTIVATE_NOW; | ||
1516 | |||
1517 | ret = sh_mobile_check_var(var, info); | ||
1518 | if (ret) | ||
1519 | return ret; | ||
1520 | |||
1521 | /* Allocate frame buffer memory and color map. */ | ||
1522 | buf = dma_alloc_coherent(dev, info->fix.smem_len, &ch->dma_handle, | ||
1523 | GFP_KERNEL); | ||
1524 | if (!buf) { | ||
1525 | dev_err(dev, "unable to allocate buffer\n"); | ||
1526 | return -ENOMEM; | ||
1527 | } | ||
1528 | |||
1529 | ret = fb_alloc_cmap(&info->cmap, PALETTE_NR, 0); | ||
1530 | if (ret < 0) { | ||
1531 | dev_err(dev, "unable to allocate cmap\n"); | ||
1532 | dma_free_coherent(dev, info->fix.smem_len, | ||
1533 | buf, ch->dma_handle); | ||
1534 | return ret; | ||
1535 | } | ||
1536 | |||
1537 | info->fix.smem_start = ch->dma_handle; | ||
1538 | if (var->nonstd) | ||
1539 | info->fix.line_length = var->xres; | ||
1540 | else | ||
1541 | info->fix.line_length = var->xres * (cfg->bpp / 8); | ||
1542 | |||
1543 | info->screen_base = buf; | ||
1544 | info->device = dev; | ||
1545 | ch->display_var = *var; | ||
1546 | |||
1547 | return 0; | ||
1548 | } | ||
1549 | |||
1550 | static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev) | ||
1551 | { | ||
1417 | struct sh_mobile_lcdc_info *pdata = pdev->dev.platform_data; | 1552 | struct sh_mobile_lcdc_info *pdata = pdev->dev.platform_data; |
1553 | struct sh_mobile_lcdc_priv *priv; | ||
1418 | struct resource *res; | 1554 | struct resource *res; |
1555 | int num_channels; | ||
1419 | int error; | 1556 | int error; |
1420 | void *buf; | 1557 | int i; |
1421 | int i, j; | ||
1422 | 1558 | ||
1423 | if (!pdata) { | 1559 | if (!pdata) { |
1424 | dev_err(&pdev->dev, "no platform data defined\n"); | 1560 | dev_err(&pdev->dev, "no platform data defined\n"); |
@@ -1440,7 +1576,7 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev) | |||
1440 | 1576 | ||
1441 | platform_set_drvdata(pdev, priv); | 1577 | platform_set_drvdata(pdev, priv); |
1442 | 1578 | ||
1443 | error = request_irq(i, sh_mobile_lcdc_irq, IRQF_DISABLED, | 1579 | error = request_irq(i, sh_mobile_lcdc_irq, 0, |
1444 | dev_name(&pdev->dev), priv); | 1580 | dev_name(&pdev->dev), priv); |
1445 | if (error) { | 1581 | if (error) { |
1446 | dev_err(&pdev->dev, "unable to request irq\n"); | 1582 | dev_err(&pdev->dev, "unable to request irq\n"); |
@@ -1450,9 +1586,8 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev) | |||
1450 | priv->irq = i; | 1586 | priv->irq = i; |
1451 | atomic_set(&priv->hw_usecnt, -1); | 1587 | atomic_set(&priv->hw_usecnt, -1); |
1452 | 1588 | ||
1453 | j = 0; | 1589 | for (i = 0, num_channels = 0; i < ARRAY_SIZE(pdata->ch); i++) { |
1454 | for (i = 0; i < ARRAY_SIZE(pdata->ch); i++) { | 1590 | struct sh_mobile_lcdc_chan *ch = priv->ch + num_channels; |
1455 | struct sh_mobile_lcdc_chan *ch = priv->ch + j; | ||
1456 | 1591 | ||
1457 | ch->lcdc = priv; | 1592 | ch->lcdc = priv; |
1458 | memcpy(&ch->cfg, &pdata->ch[i], sizeof(pdata->ch[i])); | 1593 | memcpy(&ch->cfg, &pdata->ch[i], sizeof(pdata->ch[i])); |
@@ -1472,26 +1607,26 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev) | |||
1472 | 1607 | ||
1473 | switch (pdata->ch[i].chan) { | 1608 | switch (pdata->ch[i].chan) { |
1474 | case LCDC_CHAN_MAINLCD: | 1609 | case LCDC_CHAN_MAINLCD: |
1475 | ch->enabled = 1 << 1; | 1610 | ch->enabled = LDCNT2R_ME; |
1476 | ch->reg_offs = lcdc_offs_mainlcd; | 1611 | ch->reg_offs = lcdc_offs_mainlcd; |
1477 | j++; | 1612 | num_channels++; |
1478 | break; | 1613 | break; |
1479 | case LCDC_CHAN_SUBLCD: | 1614 | case LCDC_CHAN_SUBLCD: |
1480 | ch->enabled = 1 << 2; | 1615 | ch->enabled = LDCNT2R_SE; |
1481 | ch->reg_offs = lcdc_offs_sublcd; | 1616 | ch->reg_offs = lcdc_offs_sublcd; |
1482 | j++; | 1617 | num_channels++; |
1483 | break; | 1618 | break; |
1484 | } | 1619 | } |
1485 | } | 1620 | } |
1486 | 1621 | ||
1487 | if (!j) { | 1622 | if (!num_channels) { |
1488 | dev_err(&pdev->dev, "no channels defined\n"); | 1623 | dev_err(&pdev->dev, "no channels defined\n"); |
1489 | error = -EINVAL; | 1624 | error = -EINVAL; |
1490 | goto err1; | 1625 | goto err1; |
1491 | } | 1626 | } |
1492 | 1627 | ||
1493 | /* for dual channel LCDC (MAIN + SUB) force shared bpp setting */ | 1628 | /* for dual channel LCDC (MAIN + SUB) force shared bpp setting */ |
1494 | if (j == 2) | 1629 | if (num_channels == 2) |
1495 | priv->forced_bpp = pdata->ch[0].bpp; | 1630 | priv->forced_bpp = pdata->ch[0].bpp; |
1496 | 1631 | ||
1497 | priv->base = ioremap_nocache(res->start, resource_size(res)); | 1632 | priv->base = ioremap_nocache(res->start, resource_size(res)); |
@@ -1506,125 +1641,23 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev) | |||
1506 | 1641 | ||
1507 | priv->meram_dev = pdata->meram_dev; | 1642 | priv->meram_dev = pdata->meram_dev; |
1508 | 1643 | ||
1509 | for (i = 0; i < j; i++) { | 1644 | for (i = 0; i < num_channels; i++) { |
1510 | struct fb_var_screeninfo *var; | ||
1511 | const struct fb_videomode *lcd_cfg, *max_cfg = NULL; | ||
1512 | struct sh_mobile_lcdc_chan *ch = priv->ch + i; | 1645 | struct sh_mobile_lcdc_chan *ch = priv->ch + i; |
1513 | struct sh_mobile_lcdc_chan_cfg *cfg = &ch->cfg; | ||
1514 | const struct fb_videomode *mode = cfg->lcd_cfg; | ||
1515 | unsigned long max_size = 0; | ||
1516 | int k; | ||
1517 | int num_cfg; | ||
1518 | |||
1519 | ch->info = framebuffer_alloc(0, &pdev->dev); | ||
1520 | if (!ch->info) { | ||
1521 | dev_err(&pdev->dev, "unable to allocate fb_info\n"); | ||
1522 | error = -ENOMEM; | ||
1523 | break; | ||
1524 | } | ||
1525 | |||
1526 | info = ch->info; | ||
1527 | var = &info->var; | ||
1528 | info->fbops = &sh_mobile_lcdc_ops; | ||
1529 | info->par = ch; | ||
1530 | |||
1531 | mutex_init(&ch->open_lock); | ||
1532 | |||
1533 | for (k = 0, lcd_cfg = mode; | ||
1534 | k < cfg->num_cfg && lcd_cfg; | ||
1535 | k++, lcd_cfg++) { | ||
1536 | unsigned long size = lcd_cfg->yres * lcd_cfg->xres; | ||
1537 | /* NV12 buffers must have even number of lines */ | ||
1538 | if ((cfg->nonstd) && cfg->bpp == 12 && | ||
1539 | (lcd_cfg->yres & 0x1)) { | ||
1540 | dev_err(&pdev->dev, "yres must be multiple of 2" | ||
1541 | " for YCbCr420 mode.\n"); | ||
1542 | error = -EINVAL; | ||
1543 | goto err1; | ||
1544 | } | ||
1545 | |||
1546 | if (size > max_size) { | ||
1547 | max_cfg = lcd_cfg; | ||
1548 | max_size = size; | ||
1549 | } | ||
1550 | } | ||
1551 | |||
1552 | if (!mode) | ||
1553 | max_size = MAX_XRES * MAX_YRES; | ||
1554 | else if (max_cfg) | ||
1555 | dev_dbg(&pdev->dev, "Found largest videomode %ux%u\n", | ||
1556 | max_cfg->xres, max_cfg->yres); | ||
1557 | 1646 | ||
1558 | info->fix = sh_mobile_lcdc_fix; | 1647 | error = sh_mobile_lcdc_channel_init(ch, &pdev->dev); |
1559 | info->fix.smem_len = max_size * 2 * cfg->bpp / 8; | ||
1560 | |||
1561 | /* Only pan in 2 line steps for NV12 */ | ||
1562 | if (cfg->nonstd && cfg->bpp == 12) | ||
1563 | info->fix.ypanstep = 2; | ||
1564 | |||
1565 | if (!mode) { | ||
1566 | mode = &default_720p; | ||
1567 | num_cfg = 1; | ||
1568 | } else { | ||
1569 | num_cfg = cfg->num_cfg; | ||
1570 | } | ||
1571 | |||
1572 | fb_videomode_to_modelist(mode, num_cfg, &info->modelist); | ||
1573 | |||
1574 | fb_videomode_to_var(var, mode); | ||
1575 | var->width = cfg->lcd_size_cfg.width; | ||
1576 | var->height = cfg->lcd_size_cfg.height; | ||
1577 | /* Default Y virtual resolution is 2x panel size */ | ||
1578 | var->yres_virtual = var->yres * 2; | ||
1579 | var->activate = FB_ACTIVATE_NOW; | ||
1580 | |||
1581 | error = sh_mobile_lcdc_set_bpp(var, cfg->bpp, cfg->nonstd); | ||
1582 | if (error) | 1648 | if (error) |
1583 | break; | 1649 | goto err1; |
1584 | |||
1585 | buf = dma_alloc_coherent(&pdev->dev, info->fix.smem_len, | ||
1586 | &ch->dma_handle, GFP_KERNEL); | ||
1587 | if (!buf) { | ||
1588 | dev_err(&pdev->dev, "unable to allocate buffer\n"); | ||
1589 | error = -ENOMEM; | ||
1590 | break; | ||
1591 | } | ||
1592 | |||
1593 | info->pseudo_palette = &ch->pseudo_palette; | ||
1594 | info->flags = FBINFO_FLAG_DEFAULT; | ||
1595 | |||
1596 | error = fb_alloc_cmap(&info->cmap, PALETTE_NR, 0); | ||
1597 | if (error < 0) { | ||
1598 | dev_err(&pdev->dev, "unable to allocate cmap\n"); | ||
1599 | dma_free_coherent(&pdev->dev, info->fix.smem_len, | ||
1600 | buf, ch->dma_handle); | ||
1601 | break; | ||
1602 | } | ||
1603 | |||
1604 | info->fix.smem_start = ch->dma_handle; | ||
1605 | if (var->nonstd) | ||
1606 | info->fix.line_length = var->xres; | ||
1607 | else | ||
1608 | info->fix.line_length = var->xres * (cfg->bpp / 8); | ||
1609 | |||
1610 | info->screen_base = buf; | ||
1611 | info->device = &pdev->dev; | ||
1612 | ch->display_var = *var; | ||
1613 | } | 1650 | } |
1614 | 1651 | ||
1615 | if (error) | ||
1616 | goto err1; | ||
1617 | |||
1618 | error = sh_mobile_lcdc_start(priv); | 1652 | error = sh_mobile_lcdc_start(priv); |
1619 | if (error) { | 1653 | if (error) { |
1620 | dev_err(&pdev->dev, "unable to start hardware\n"); | 1654 | dev_err(&pdev->dev, "unable to start hardware\n"); |
1621 | goto err1; | 1655 | goto err1; |
1622 | } | 1656 | } |
1623 | 1657 | ||
1624 | for (i = 0; i < j; i++) { | 1658 | for (i = 0; i < num_channels; i++) { |
1625 | struct sh_mobile_lcdc_chan *ch = priv->ch + i; | 1659 | struct sh_mobile_lcdc_chan *ch = priv->ch + i; |
1626 | 1660 | struct fb_info *info = ch->info; | |
1627 | info = ch->info; | ||
1628 | 1661 | ||
1629 | if (info->fbdefio) { | 1662 | if (info->fbdefio) { |
1630 | ch->sglist = vmalloc(sizeof(struct scatterlist) * | 1663 | ch->sglist = vmalloc(sizeof(struct scatterlist) * |
@@ -1665,57 +1698,6 @@ err1: | |||
1665 | return error; | 1698 | return error; |
1666 | } | 1699 | } |
1667 | 1700 | ||
1668 | static int sh_mobile_lcdc_remove(struct platform_device *pdev) | ||
1669 | { | ||
1670 | struct sh_mobile_lcdc_priv *priv = platform_get_drvdata(pdev); | ||
1671 | struct fb_info *info; | ||
1672 | int i; | ||
1673 | |||
1674 | fb_unregister_client(&priv->notifier); | ||
1675 | |||
1676 | for (i = 0; i < ARRAY_SIZE(priv->ch); i++) | ||
1677 | if (priv->ch[i].info && priv->ch[i].info->dev) | ||
1678 | unregister_framebuffer(priv->ch[i].info); | ||
1679 | |||
1680 | sh_mobile_lcdc_stop(priv); | ||
1681 | |||
1682 | for (i = 0; i < ARRAY_SIZE(priv->ch); i++) { | ||
1683 | info = priv->ch[i].info; | ||
1684 | |||
1685 | if (!info || !info->device) | ||
1686 | continue; | ||
1687 | |||
1688 | if (priv->ch[i].sglist) | ||
1689 | vfree(priv->ch[i].sglist); | ||
1690 | |||
1691 | if (info->screen_base) | ||
1692 | dma_free_coherent(&pdev->dev, info->fix.smem_len, | ||
1693 | info->screen_base, | ||
1694 | priv->ch[i].dma_handle); | ||
1695 | fb_dealloc_cmap(&info->cmap); | ||
1696 | framebuffer_release(info); | ||
1697 | } | ||
1698 | |||
1699 | for (i = 0; i < ARRAY_SIZE(priv->ch); i++) { | ||
1700 | if (priv->ch[i].bl) | ||
1701 | sh_mobile_lcdc_bl_remove(priv->ch[i].bl); | ||
1702 | } | ||
1703 | |||
1704 | if (priv->dot_clk) | ||
1705 | clk_put(priv->dot_clk); | ||
1706 | |||
1707 | if (priv->dev) | ||
1708 | pm_runtime_disable(priv->dev); | ||
1709 | |||
1710 | if (priv->base) | ||
1711 | iounmap(priv->base); | ||
1712 | |||
1713 | if (priv->irq) | ||
1714 | free_irq(priv->irq, priv); | ||
1715 | kfree(priv); | ||
1716 | return 0; | ||
1717 | } | ||
1718 | |||
1719 | static struct platform_driver sh_mobile_lcdc_driver = { | 1701 | static struct platform_driver sh_mobile_lcdc_driver = { |
1720 | .driver = { | 1702 | .driver = { |
1721 | .name = "sh_mobile_lcdc_fb", | 1703 | .name = "sh_mobile_lcdc_fb", |
diff --git a/drivers/video/sh_mobile_lcdcfb.h b/drivers/video/sh_mobile_lcdcfb.h index aeed6687e6a7..a58a0f38848b 100644 --- a/drivers/video/sh_mobile_lcdcfb.h +++ b/drivers/video/sh_mobile_lcdcfb.h | |||
@@ -18,6 +18,13 @@ struct sh_mobile_lcdc_priv; | |||
18 | struct fb_info; | 18 | struct fb_info; |
19 | struct backlight_device; | 19 | struct backlight_device; |
20 | 20 | ||
21 | /* | ||
22 | * struct sh_mobile_lcdc_chan - LCDC display channel | ||
23 | * | ||
24 | * @base_addr_y: Frame buffer viewport base address (luma component) | ||
25 | * @base_addr_c: Frame buffer viewport base address (chroma component) | ||
26 | * @pitch: Frame buffer line pitch | ||
27 | */ | ||
21 | struct sh_mobile_lcdc_chan { | 28 | struct sh_mobile_lcdc_chan { |
22 | struct sh_mobile_lcdc_priv *lcdc; | 29 | struct sh_mobile_lcdc_priv *lcdc; |
23 | unsigned long *reg_offs; | 30 | unsigned long *reg_offs; |
@@ -25,7 +32,6 @@ struct sh_mobile_lcdc_chan { | |||
25 | unsigned long enabled; /* ME and SE in LDCNT2R */ | 32 | unsigned long enabled; /* ME and SE in LDCNT2R */ |
26 | struct sh_mobile_lcdc_chan_cfg cfg; | 33 | struct sh_mobile_lcdc_chan_cfg cfg; |
27 | u32 pseudo_palette[PALETTE_NR]; | 34 | u32 pseudo_palette[PALETTE_NR]; |
28 | unsigned long saved_ch_regs[NR_CH_REGS]; | ||
29 | struct fb_info *info; | 35 | struct fb_info *info; |
30 | struct backlight_device *bl; | 36 | struct backlight_device *bl; |
31 | dma_addr_t dma_handle; | 37 | dma_addr_t dma_handle; |
@@ -40,6 +46,10 @@ struct sh_mobile_lcdc_chan { | |||
40 | int blank_status; | 46 | int blank_status; |
41 | struct mutex open_lock; /* protects the use counter */ | 47 | struct mutex open_lock; /* protects the use counter */ |
42 | int meram_enabled; | 48 | int meram_enabled; |
49 | |||
50 | unsigned long base_addr_y; | ||
51 | unsigned long base_addr_c; | ||
52 | unsigned int pitch; | ||
43 | }; | 53 | }; |
44 | 54 | ||
45 | #endif | 55 | #endif |
diff --git a/drivers/video/sh_mobile_meram.c b/drivers/video/sh_mobile_meram.c index cc7d7329dc15..4d63490209cd 100644 --- a/drivers/video/sh_mobile_meram.c +++ b/drivers/video/sh_mobile_meram.c | |||
@@ -12,29 +12,103 @@ | |||
12 | #include <linux/kernel.h> | 12 | #include <linux/kernel.h> |
13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
14 | #include <linux/device.h> | 14 | #include <linux/device.h> |
15 | #include <linux/pm_runtime.h> | ||
15 | #include <linux/io.h> | 16 | #include <linux/io.h> |
16 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
17 | #include <linux/platform_device.h> | 18 | #include <linux/platform_device.h> |
18 | 19 | #include <video/sh_mobile_meram.h> | |
19 | #include "sh_mobile_meram.h" | ||
20 | 20 | ||
21 | /* meram registers */ | 21 | /* meram registers */ |
22 | #define MExxCTL 0x0 | 22 | #define MEVCR1 0x4 |
23 | #define MExxBSIZE 0x4 | 23 | #define MEVCR1_RST (1 << 31) |
24 | #define MExxMNCF 0x8 | 24 | #define MEVCR1_WD (1 << 30) |
25 | #define MExxSARA 0x10 | 25 | #define MEVCR1_AMD1 (1 << 29) |
26 | #define MExxSARB 0x14 | 26 | #define MEVCR1_AMD0 (1 << 28) |
27 | #define MExxSBSIZE 0x18 | 27 | #define MEQSEL1 0x40 |
28 | 28 | #define MEQSEL2 0x44 | |
29 | #define MERAM_MExxCTL_VAL(ctl, next_icb, addr) \ | 29 | |
30 | ((ctl) | (((next_icb) & 0x1f) << 11) | (((addr) & 0x7ff) << 16)) | 30 | #define MExxCTL 0x400 |
31 | #define MERAM_MExxBSIZE_VAL(a, b, c) \ | 31 | #define MExxCTL_BV (1 << 31) |
32 | (((a) << 28) | ((b) << 16) | (c)) | 32 | #define MExxCTL_BSZ_SHIFT 28 |
33 | 33 | #define MExxCTL_MSAR_MASK (0x7ff << MExxCTL_MSAR_SHIFT) | |
34 | #define MEVCR1 0x4 | 34 | #define MExxCTL_MSAR_SHIFT 16 |
35 | #define MEACTS 0x10 | 35 | #define MExxCTL_NXT_MASK (0x1f << MExxCTL_NXT_SHIFT) |
36 | #define MEQSEL1 0x40 | 36 | #define MExxCTL_NXT_SHIFT 11 |
37 | #define MEQSEL2 0x44 | 37 | #define MExxCTL_WD1 (1 << 10) |
38 | #define MExxCTL_WD0 (1 << 9) | ||
39 | #define MExxCTL_WS (1 << 8) | ||
40 | #define MExxCTL_CB (1 << 7) | ||
41 | #define MExxCTL_WBF (1 << 6) | ||
42 | #define MExxCTL_WF (1 << 5) | ||
43 | #define MExxCTL_RF (1 << 4) | ||
44 | #define MExxCTL_CM (1 << 3) | ||
45 | #define MExxCTL_MD_READ (1 << 0) | ||
46 | #define MExxCTL_MD_WRITE (2 << 0) | ||
47 | #define MExxCTL_MD_ICB_WB (3 << 0) | ||
48 | #define MExxCTL_MD_ICB (4 << 0) | ||
49 | #define MExxCTL_MD_FB (7 << 0) | ||
50 | #define MExxCTL_MD_MASK (7 << 0) | ||
51 | #define MExxBSIZE 0x404 | ||
52 | #define MExxBSIZE_RCNT_SHIFT 28 | ||
53 | #define MExxBSIZE_YSZM1_SHIFT 16 | ||
54 | #define MExxBSIZE_XSZM1_SHIFT 0 | ||
55 | #define MExxMNCF 0x408 | ||
56 | #define MExxMNCF_KWBNM_SHIFT 28 | ||
57 | #define MExxMNCF_KRBNM_SHIFT 24 | ||
58 | #define MExxMNCF_BNM_SHIFT 16 | ||
59 | #define MExxMNCF_XBV (1 << 15) | ||
60 | #define MExxMNCF_CPL_YCBCR444 (1 << 12) | ||
61 | #define MExxMNCF_CPL_YCBCR420 (2 << 12) | ||
62 | #define MExxMNCF_CPL_YCBCR422 (3 << 12) | ||
63 | #define MExxMNCF_CPL_MSK (3 << 12) | ||
64 | #define MExxMNCF_BL (1 << 2) | ||
65 | #define MExxMNCF_LNM_SHIFT 0 | ||
66 | #define MExxSARA 0x410 | ||
67 | #define MExxSARB 0x414 | ||
68 | #define MExxSBSIZE 0x418 | ||
69 | #define MExxSBSIZE_HDV (1 << 31) | ||
70 | #define MExxSBSIZE_HSZ16 (0 << 28) | ||
71 | #define MExxSBSIZE_HSZ32 (1 << 28) | ||
72 | #define MExxSBSIZE_HSZ64 (2 << 28) | ||
73 | #define MExxSBSIZE_HSZ128 (3 << 28) | ||
74 | #define MExxSBSIZE_SBSIZZ_SHIFT 0 | ||
75 | |||
76 | #define MERAM_MExxCTL_VAL(next, addr) \ | ||
77 | ((((next) << MExxCTL_NXT_SHIFT) & MExxCTL_NXT_MASK) | \ | ||
78 | (((addr) << MExxCTL_MSAR_SHIFT) & MExxCTL_MSAR_MASK)) | ||
79 | #define MERAM_MExxBSIZE_VAL(rcnt, yszm1, xszm1) \ | ||
80 | (((rcnt) << MExxBSIZE_RCNT_SHIFT) | \ | ||
81 | ((yszm1) << MExxBSIZE_YSZM1_SHIFT) | \ | ||
82 | ((xszm1) << MExxBSIZE_XSZM1_SHIFT)) | ||
83 | |||
84 | #define SH_MOBILE_MERAM_ICB_NUM 32 | ||
85 | |||
86 | static unsigned long common_regs[] = { | ||
87 | MEVCR1, | ||
88 | MEQSEL1, | ||
89 | MEQSEL2, | ||
90 | }; | ||
91 | #define CMN_REGS_SIZE ARRAY_SIZE(common_regs) | ||
92 | |||
93 | static unsigned long icb_regs[] = { | ||
94 | MExxCTL, | ||
95 | MExxBSIZE, | ||
96 | MExxMNCF, | ||
97 | MExxSARA, | ||
98 | MExxSARB, | ||
99 | MExxSBSIZE, | ||
100 | }; | ||
101 | #define ICB_REGS_SIZE ARRAY_SIZE(icb_regs) | ||
102 | |||
103 | struct sh_mobile_meram_priv { | ||
104 | void __iomem *base; | ||
105 | struct mutex lock; | ||
106 | unsigned long used_icb; | ||
107 | int used_meram_cache_regions; | ||
108 | unsigned long used_meram_cache[SH_MOBILE_MERAM_ICB_NUM]; | ||
109 | unsigned long cmn_saved_regs[CMN_REGS_SIZE]; | ||
110 | unsigned long icb_saved_regs[ICB_REGS_SIZE * SH_MOBILE_MERAM_ICB_NUM]; | ||
111 | }; | ||
38 | 112 | ||
39 | /* settings */ | 113 | /* settings */ |
40 | #define MERAM_SEC_LINE 15 | 114 | #define MERAM_SEC_LINE 15 |
@@ -44,8 +118,7 @@ | |||
44 | * MERAM/ICB access functions | 118 | * MERAM/ICB access functions |
45 | */ | 119 | */ |
46 | 120 | ||
47 | #define MERAM_ICB_OFFSET(base, idx, off) \ | 121 | #define MERAM_ICB_OFFSET(base, idx, off) ((base) + (off) + (idx) * 0x20) |
48 | ((base) + (0x400 + ((idx) * 0x20) + (off))) | ||
49 | 122 | ||
50 | static inline void meram_write_icb(void __iomem *base, int idx, int off, | 123 | static inline void meram_write_icb(void __iomem *base, int idx, int off, |
51 | unsigned long val) | 124 | unsigned long val) |
@@ -280,17 +353,18 @@ static int meram_init(struct sh_mobile_meram_priv *priv, | |||
280 | /* | 353 | /* |
281 | * Set MERAM for framebuffer | 354 | * Set MERAM for framebuffer |
282 | * | 355 | * |
283 | * 0x70f: WD = 0x3, WS=0x1, CM=0x1, MD=FB mode | ||
284 | * we also chain the cache_icb and the marker_icb. | 356 | * we also chain the cache_icb and the marker_icb. |
285 | * we also split the allocated MERAM buffer between two ICBs. | 357 | * we also split the allocated MERAM buffer between two ICBs. |
286 | */ | 358 | */ |
287 | meram_write_icb(priv->base, icb->cache_icb, MExxCTL, | 359 | meram_write_icb(priv->base, icb->cache_icb, MExxCTL, |
288 | MERAM_MExxCTL_VAL(0x70f, icb->marker_icb, | 360 | MERAM_MExxCTL_VAL(icb->marker_icb, icb->meram_offset) | |
289 | icb->meram_offset)); | 361 | MExxCTL_WD1 | MExxCTL_WD0 | MExxCTL_WS | MExxCTL_CM | |
362 | MExxCTL_MD_FB); | ||
290 | meram_write_icb(priv->base, icb->marker_icb, MExxCTL, | 363 | meram_write_icb(priv->base, icb->marker_icb, MExxCTL, |
291 | MERAM_MExxCTL_VAL(0x70f, icb->cache_icb, | 364 | MERAM_MExxCTL_VAL(icb->cache_icb, icb->meram_offset + |
292 | icb->meram_offset + | 365 | icb->meram_size / 2) | |
293 | icb->meram_size / 2)); | 366 | MExxCTL_WD1 | MExxCTL_WD0 | MExxCTL_WS | MExxCTL_CM | |
367 | MExxCTL_MD_FB); | ||
294 | 368 | ||
295 | return 0; | 369 | return 0; |
296 | } | 370 | } |
@@ -299,8 +373,10 @@ static void meram_deinit(struct sh_mobile_meram_priv *priv, | |||
299 | struct sh_mobile_meram_icb *icb) | 373 | struct sh_mobile_meram_icb *icb) |
300 | { | 374 | { |
301 | /* disable ICB */ | 375 | /* disable ICB */ |
302 | meram_write_icb(priv->base, icb->cache_icb, MExxCTL, 0); | 376 | meram_write_icb(priv->base, icb->cache_icb, MExxCTL, |
303 | meram_write_icb(priv->base, icb->marker_icb, MExxCTL, 0); | 377 | MExxCTL_WBF | MExxCTL_WF | MExxCTL_RF); |
378 | meram_write_icb(priv->base, icb->marker_icb, MExxCTL, | ||
379 | MExxCTL_WBF | MExxCTL_WF | MExxCTL_RF); | ||
304 | icb->cache_unit = 0; | 380 | icb->cache_unit = 0; |
305 | } | 381 | } |
306 | 382 | ||
@@ -337,24 +413,22 @@ static int sh_mobile_meram_register(struct sh_mobile_meram_info *pdata, | |||
337 | xres, yres, (!pixelformat) ? "yuv" : "rgb", | 413 | xres, yres, (!pixelformat) ? "yuv" : "rgb", |
338 | base_addr_y, base_addr_c); | 414 | base_addr_y, base_addr_c); |
339 | 415 | ||
340 | mutex_lock(&priv->lock); | ||
341 | |||
342 | /* we can't handle wider than 8192px */ | 416 | /* we can't handle wider than 8192px */ |
343 | if (xres > 8192) { | 417 | if (xres > 8192) { |
344 | dev_err(&pdev->dev, "width exceeding the limit (> 8192)."); | 418 | dev_err(&pdev->dev, "width exceeding the limit (> 8192)."); |
345 | error = -EINVAL; | 419 | return -EINVAL; |
346 | goto err; | ||
347 | } | ||
348 | |||
349 | if (priv->used_meram_cache_regions + 2 > SH_MOBILE_MERAM_ICB_NUM) { | ||
350 | dev_err(&pdev->dev, "no more ICB available."); | ||
351 | error = -EINVAL; | ||
352 | goto err; | ||
353 | } | 420 | } |
354 | 421 | ||
355 | /* do we have at least one ICB config? */ | 422 | /* do we have at least one ICB config? */ |
356 | if (cfg->icb[0].marker_icb < 0 || cfg->icb[0].cache_icb < 0) { | 423 | if (cfg->icb[0].marker_icb < 0 || cfg->icb[0].cache_icb < 0) { |
357 | dev_err(&pdev->dev, "at least one ICB is required."); | 424 | dev_err(&pdev->dev, "at least one ICB is required."); |
425 | return -EINVAL; | ||
426 | } | ||
427 | |||
428 | mutex_lock(&priv->lock); | ||
429 | |||
430 | if (priv->used_meram_cache_regions + 2 > SH_MOBILE_MERAM_ICB_NUM) { | ||
431 | dev_err(&pdev->dev, "no more ICB available."); | ||
358 | error = -EINVAL; | 432 | error = -EINVAL; |
359 | goto err; | 433 | goto err; |
360 | } | 434 | } |
@@ -460,6 +534,57 @@ static int sh_mobile_meram_update(struct sh_mobile_meram_info *pdata, | |||
460 | return 0; | 534 | return 0; |
461 | } | 535 | } |
462 | 536 | ||
537 | static int sh_mobile_meram_runtime_suspend(struct device *dev) | ||
538 | { | ||
539 | struct platform_device *pdev = to_platform_device(dev); | ||
540 | struct sh_mobile_meram_priv *priv = platform_get_drvdata(pdev); | ||
541 | int k, j; | ||
542 | |||
543 | for (k = 0; k < CMN_REGS_SIZE; k++) | ||
544 | priv->cmn_saved_regs[k] = meram_read_reg(priv->base, | ||
545 | common_regs[k]); | ||
546 | |||
547 | for (j = 0; j < 32; j++) { | ||
548 | if (!test_bit(j, &priv->used_icb)) | ||
549 | continue; | ||
550 | for (k = 0; k < ICB_REGS_SIZE; k++) { | ||
551 | priv->icb_saved_regs[j * ICB_REGS_SIZE + k] = | ||
552 | meram_read_icb(priv->base, j, icb_regs[k]); | ||
553 | /* Reset ICB on resume */ | ||
554 | if (icb_regs[k] == MExxCTL) | ||
555 | priv->icb_saved_regs[j * ICB_REGS_SIZE + k] |= | ||
556 | MExxCTL_WBF | MExxCTL_WF | MExxCTL_RF; | ||
557 | } | ||
558 | } | ||
559 | return 0; | ||
560 | } | ||
561 | |||
562 | static int sh_mobile_meram_runtime_resume(struct device *dev) | ||
563 | { | ||
564 | struct platform_device *pdev = to_platform_device(dev); | ||
565 | struct sh_mobile_meram_priv *priv = platform_get_drvdata(pdev); | ||
566 | int k, j; | ||
567 | |||
568 | for (j = 0; j < 32; j++) { | ||
569 | if (!test_bit(j, &priv->used_icb)) | ||
570 | continue; | ||
571 | for (k = 0; k < ICB_REGS_SIZE; k++) { | ||
572 | meram_write_icb(priv->base, j, icb_regs[k], | ||
573 | priv->icb_saved_regs[j * ICB_REGS_SIZE + k]); | ||
574 | } | ||
575 | } | ||
576 | |||
577 | for (k = 0; k < CMN_REGS_SIZE; k++) | ||
578 | meram_write_reg(priv->base, common_regs[k], | ||
579 | priv->cmn_saved_regs[k]); | ||
580 | return 0; | ||
581 | } | ||
582 | |||
583 | static const struct dev_pm_ops sh_mobile_meram_dev_pm_ops = { | ||
584 | .runtime_suspend = sh_mobile_meram_runtime_suspend, | ||
585 | .runtime_resume = sh_mobile_meram_runtime_resume, | ||
586 | }; | ||
587 | |||
463 | static struct sh_mobile_meram_ops sh_mobile_meram_ops = { | 588 | static struct sh_mobile_meram_ops sh_mobile_meram_ops = { |
464 | .module = THIS_MODULE, | 589 | .module = THIS_MODULE, |
465 | .meram_register = sh_mobile_meram_register, | 590 | .meram_register = sh_mobile_meram_register, |
@@ -513,7 +638,9 @@ static int __devinit sh_mobile_meram_probe(struct platform_device *pdev) | |||
513 | 638 | ||
514 | /* initialize ICB addressing mode */ | 639 | /* initialize ICB addressing mode */ |
515 | if (pdata->addr_mode == SH_MOBILE_MERAM_MODE1) | 640 | if (pdata->addr_mode == SH_MOBILE_MERAM_MODE1) |
516 | meram_write_reg(priv->base, MEVCR1, 1 << 29); | 641 | meram_write_reg(priv->base, MEVCR1, MEVCR1_AMD1); |
642 | |||
643 | pm_runtime_enable(&pdev->dev); | ||
517 | 644 | ||
518 | dev_info(&pdev->dev, "sh_mobile_meram initialized."); | 645 | dev_info(&pdev->dev, "sh_mobile_meram initialized."); |
519 | 646 | ||
@@ -530,6 +657,8 @@ static int sh_mobile_meram_remove(struct platform_device *pdev) | |||
530 | { | 657 | { |
531 | struct sh_mobile_meram_priv *priv = platform_get_drvdata(pdev); | 658 | struct sh_mobile_meram_priv *priv = platform_get_drvdata(pdev); |
532 | 659 | ||
660 | pm_runtime_disable(&pdev->dev); | ||
661 | |||
533 | if (priv->base) | 662 | if (priv->base) |
534 | iounmap(priv->base); | 663 | iounmap(priv->base); |
535 | 664 | ||
@@ -544,6 +673,7 @@ static struct platform_driver sh_mobile_meram_driver = { | |||
544 | .driver = { | 673 | .driver = { |
545 | .name = "sh_mobile_meram", | 674 | .name = "sh_mobile_meram", |
546 | .owner = THIS_MODULE, | 675 | .owner = THIS_MODULE, |
676 | .pm = &sh_mobile_meram_dev_pm_ops, | ||
547 | }, | 677 | }, |
548 | .probe = sh_mobile_meram_probe, | 678 | .probe = sh_mobile_meram_probe, |
549 | .remove = sh_mobile_meram_remove, | 679 | .remove = sh_mobile_meram_remove, |
diff --git a/drivers/video/sh_mobile_meram.h b/drivers/video/sh_mobile_meram.h deleted file mode 100644 index 82c54fbce8bd..000000000000 --- a/drivers/video/sh_mobile_meram.h +++ /dev/null | |||
@@ -1,41 +0,0 @@ | |||
1 | #ifndef __sh_mobile_meram_h__ | ||
2 | #define __sh_mobile_meram_h__ | ||
3 | |||
4 | #include <linux/mutex.h> | ||
5 | #include <video/sh_mobile_meram.h> | ||
6 | |||
7 | /* | ||
8 | * MERAM private | ||
9 | */ | ||
10 | |||
11 | #define MERAM_ICB_Y 0x1 | ||
12 | #define MERAM_ICB_C 0x2 | ||
13 | |||
14 | /* MERAM cache size */ | ||
15 | #define SH_MOBILE_MERAM_ICB_NUM 32 | ||
16 | |||
17 | #define SH_MOBILE_MERAM_CACHE_OFFSET(p) ((p) >> 16) | ||
18 | #define SH_MOBILE_MERAM_CACHE_SIZE(p) ((p) & 0xffff) | ||
19 | |||
20 | struct sh_mobile_meram_priv { | ||
21 | void __iomem *base; | ||
22 | struct mutex lock; | ||
23 | unsigned long used_icb; | ||
24 | int used_meram_cache_regions; | ||
25 | unsigned long used_meram_cache[SH_MOBILE_MERAM_ICB_NUM]; | ||
26 | }; | ||
27 | |||
28 | int sh_mobile_meram_alloc_icb(const struct sh_mobile_meram_cfg *cfg, | ||
29 | int xres, | ||
30 | int yres, | ||
31 | unsigned int base_addr, | ||
32 | int yuv_mode, | ||
33 | int *marker_icb, | ||
34 | int *out_pitch); | ||
35 | |||
36 | void sh_mobile_meram_free_icb(int marker_icb); | ||
37 | |||
38 | #define SH_MOBILE_MERAM_START(ind, ab) \ | ||
39 | (0xC0000000 | ((ab & 0x1) << 23) | ((ind & 0x1F) << 24)) | ||
40 | |||
41 | #endif /* !__sh_mobile_meram_h__ */ | ||
diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c index 75259845933d..078ca2167d6f 100644 --- a/drivers/video/sis/sis_main.c +++ b/drivers/video/sis/sis_main.c | |||
@@ -1333,19 +1333,14 @@ sisfb_set_base_CRT2(struct sis_video_info *ivideo, unsigned int base) | |||
1333 | } | 1333 | } |
1334 | 1334 | ||
1335 | static int | 1335 | static int |
1336 | sisfb_pan_var(struct sis_video_info *ivideo, struct fb_var_screeninfo *var) | 1336 | sisfb_pan_var(struct sis_video_info *ivideo, struct fb_info *info, |
1337 | struct fb_var_screeninfo *var) | ||
1337 | { | 1338 | { |
1338 | if(var->xoffset > (var->xres_virtual - var->xres)) { | 1339 | ivideo->current_base = var->yoffset * info->var.xres_virtual |
1339 | return -EINVAL; | 1340 | + var->xoffset; |
1340 | } | ||
1341 | if(var->yoffset > (var->yres_virtual - var->yres)) { | ||
1342 | return -EINVAL; | ||
1343 | } | ||
1344 | |||
1345 | ivideo->current_base = (var->yoffset * var->xres_virtual) + var->xoffset; | ||
1346 | 1341 | ||
1347 | /* calculate base bpp dep. */ | 1342 | /* calculate base bpp dep. */ |
1348 | switch(var->bits_per_pixel) { | 1343 | switch (info->var.bits_per_pixel) { |
1349 | case 32: | 1344 | case 32: |
1350 | break; | 1345 | break; |
1351 | case 16: | 1346 | case 16: |
@@ -1635,20 +1630,15 @@ sisfb_pan_display(struct fb_var_screeninfo *var, struct fb_info* info) | |||
1635 | struct sis_video_info *ivideo = (struct sis_video_info *)info->par; | 1630 | struct sis_video_info *ivideo = (struct sis_video_info *)info->par; |
1636 | int err; | 1631 | int err; |
1637 | 1632 | ||
1638 | if(var->xoffset > (var->xres_virtual - var->xres)) | 1633 | if (var->vmode & FB_VMODE_YWRAP) |
1639 | return -EINVAL; | ||
1640 | |||
1641 | if(var->yoffset > (var->yres_virtual - var->yres)) | ||
1642 | return -EINVAL; | ||
1643 | |||
1644 | if(var->vmode & FB_VMODE_YWRAP) | ||
1645 | return -EINVAL; | 1634 | return -EINVAL; |
1646 | 1635 | ||
1647 | if(var->xoffset + info->var.xres > info->var.xres_virtual || | 1636 | if (var->xoffset + info->var.xres > info->var.xres_virtual || |
1648 | var->yoffset + info->var.yres > info->var.yres_virtual) | 1637 | var->yoffset + info->var.yres > info->var.yres_virtual) |
1649 | return -EINVAL; | 1638 | return -EINVAL; |
1650 | 1639 | ||
1651 | if((err = sisfb_pan_var(ivideo, var)) < 0) | 1640 | err = sisfb_pan_var(ivideo, info, var); |
1641 | if (err < 0) | ||
1652 | return err; | 1642 | return err; |
1653 | 1643 | ||
1654 | info->var.xoffset = var->xoffset; | 1644 | info->var.xoffset = var->xoffset; |
diff --git a/drivers/video/skeletonfb.c b/drivers/video/skeletonfb.c index 89158bc71da2..30f7a815a62b 100644 --- a/drivers/video/skeletonfb.c +++ b/drivers/video/skeletonfb.c | |||
@@ -989,7 +989,7 @@ static struct platform_device *xxxfb_device; | |||
989 | */ | 989 | */ |
990 | int __init xxxfb_setup(char *options) | 990 | int __init xxxfb_setup(char *options) |
991 | { | 991 | { |
992 | /* Parse user speficied options (`video=xxxfb:') */ | 992 | /* Parse user specified options (`video=xxxfb:') */ |
993 | } | 993 | } |
994 | #endif /* MODULE */ | 994 | #endif /* MODULE */ |
995 | 995 | ||
diff --git a/drivers/video/sm501fb.c b/drivers/video/sm501fb.c index 6294dca95500..a78254cf8e83 100644 --- a/drivers/video/sm501fb.c +++ b/drivers/video/sm501fb.c | |||
@@ -582,7 +582,7 @@ static int sm501fb_pan_crt(struct fb_var_screeninfo *var, | |||
582 | { | 582 | { |
583 | struct sm501fb_par *par = info->par; | 583 | struct sm501fb_par *par = info->par; |
584 | struct sm501fb_info *fbi = par->info; | 584 | struct sm501fb_info *fbi = par->info; |
585 | unsigned int bytes_pixel = var->bits_per_pixel / 8; | 585 | unsigned int bytes_pixel = info->var.bits_per_pixel / 8; |
586 | unsigned long reg; | 586 | unsigned long reg; |
587 | unsigned long xoffs; | 587 | unsigned long xoffs; |
588 | 588 | ||
@@ -614,10 +614,10 @@ static int sm501fb_pan_pnl(struct fb_var_screeninfo *var, | |||
614 | struct sm501fb_info *fbi = par->info; | 614 | struct sm501fb_info *fbi = par->info; |
615 | unsigned long reg; | 615 | unsigned long reg; |
616 | 616 | ||
617 | reg = var->xoffset | (var->xres_virtual << 16); | 617 | reg = var->xoffset | (info->var.xres_virtual << 16); |
618 | smc501_writel(reg, fbi->regs + SM501_DC_PANEL_FB_WIDTH); | 618 | smc501_writel(reg, fbi->regs + SM501_DC_PANEL_FB_WIDTH); |
619 | 619 | ||
620 | reg = var->yoffset | (var->yres_virtual << 16); | 620 | reg = var->yoffset | (info->var.yres_virtual << 16); |
621 | smc501_writel(reg, fbi->regs + SM501_DC_PANEL_FB_HEIGHT); | 621 | smc501_writel(reg, fbi->regs + SM501_DC_PANEL_FB_HEIGHT); |
622 | 622 | ||
623 | sm501fb_sync_regs(fbi); | 623 | sm501fb_sync_regs(fbi); |
diff --git a/drivers/video/smscufx.c b/drivers/video/smscufx.c new file mode 100644 index 000000000000..aaccffac67ab --- /dev/null +++ b/drivers/video/smscufx.c | |||
@@ -0,0 +1,1994 @@ | |||
1 | /* | ||
2 | * smscufx.c -- Framebuffer driver for SMSC UFX USB controller | ||
3 | * | ||
4 | * Copyright (C) 2011 Steve Glendinning <steve.glendinning@smsc.com> | ||
5 | * Copyright (C) 2009 Roberto De Ioris <roberto@unbit.it> | ||
6 | * Copyright (C) 2009 Jaya Kumar <jayakumar.lkml@gmail.com> | ||
7 | * Copyright (C) 2009 Bernie Thompson <bernie@plugable.com> | ||
8 | * | ||
9 | * This file is subject to the terms and conditions of the GNU General Public | ||
10 | * License v2. See the file COPYING in the main directory of this archive for | ||
11 | * more details. | ||
12 | * | ||
13 | * Based on udlfb, with work from Florian Echtler, Henrik Bjerregaard Pedersen, | ||
14 | * and others. | ||
15 | * | ||
16 | * Works well with Bernie Thompson's X DAMAGE patch to xf86-video-fbdev | ||
17 | * available from http://git.plugable.com | ||
18 | * | ||
19 | * Layout is based on skeletonfb by James Simmons and Geert Uytterhoeven, | ||
20 | * usb-skeleton by GregKH. | ||
21 | */ | ||
22 | |||
23 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
24 | |||
25 | #include <linux/module.h> | ||
26 | #include <linux/kernel.h> | ||
27 | #include <linux/init.h> | ||
28 | #include <linux/usb.h> | ||
29 | #include <linux/uaccess.h> | ||
30 | #include <linux/mm.h> | ||
31 | #include <linux/fb.h> | ||
32 | #include <linux/vmalloc.h> | ||
33 | #include <linux/slab.h> | ||
34 | #include <linux/delay.h> | ||
35 | #include "edid.h" | ||
36 | |||
37 | #define check_warn(status, fmt, args...) \ | ||
38 | ({ if (status < 0) pr_warn(fmt, ##args); }) | ||
39 | |||
40 | #define check_warn_return(status, fmt, args...) \ | ||
41 | ({ if (status < 0) { pr_warn(fmt, ##args); return status; } }) | ||
42 | |||
43 | #define check_warn_goto_error(status, fmt, args...) \ | ||
44 | ({ if (status < 0) { pr_warn(fmt, ##args); goto error; } }) | ||
45 | |||
46 | #define all_bits_set(x, bits) (((x) & (bits)) == (bits)) | ||
47 | |||
48 | #define USB_VENDOR_REQUEST_WRITE_REGISTER 0xA0 | ||
49 | #define USB_VENDOR_REQUEST_READ_REGISTER 0xA1 | ||
50 | |||
51 | /* | ||
52 | * TODO: Propose standard fb.h ioctl for reporting damage, | ||
53 | * using _IOWR() and one of the existing area structs from fb.h | ||
54 | * Consider these ioctls deprecated, but they're still used by the | ||
55 | * DisplayLink X server as yet - need both to be modified in tandem | ||
56 | * when new ioctl(s) are ready. | ||
57 | */ | ||
58 | #define UFX_IOCTL_RETURN_EDID (0xAD) | ||
59 | #define UFX_IOCTL_REPORT_DAMAGE (0xAA) | ||
60 | |||
61 | /* -BULK_SIZE as per usb-skeleton. Can we get full page and avoid overhead? */ | ||
62 | #define BULK_SIZE (512) | ||
63 | #define MAX_TRANSFER (PAGE_SIZE*16 - BULK_SIZE) | ||
64 | #define WRITES_IN_FLIGHT (4) | ||
65 | |||
66 | #define GET_URB_TIMEOUT (HZ) | ||
67 | #define FREE_URB_TIMEOUT (HZ*2) | ||
68 | |||
69 | #define BPP 2 | ||
70 | |||
71 | #define UFX_DEFIO_WRITE_DELAY 5 /* fb_deferred_io.delay in jiffies */ | ||
72 | #define UFX_DEFIO_WRITE_DISABLE (HZ*60) /* "disable" with long delay */ | ||
73 | |||
74 | struct dloarea { | ||
75 | int x, y; | ||
76 | int w, h; | ||
77 | }; | ||
78 | |||
79 | struct urb_node { | ||
80 | struct list_head entry; | ||
81 | struct ufx_data *dev; | ||
82 | struct delayed_work release_urb_work; | ||
83 | struct urb *urb; | ||
84 | }; | ||
85 | |||
86 | struct urb_list { | ||
87 | struct list_head list; | ||
88 | spinlock_t lock; | ||
89 | struct semaphore limit_sem; | ||
90 | int available; | ||
91 | int count; | ||
92 | size_t size; | ||
93 | }; | ||
94 | |||
95 | struct ufx_data { | ||
96 | struct usb_device *udev; | ||
97 | struct device *gdev; /* &udev->dev */ | ||
98 | struct fb_info *info; | ||
99 | struct urb_list urbs; | ||
100 | struct kref kref; | ||
101 | int fb_count; | ||
102 | bool virtualized; /* true when physical usb device not present */ | ||
103 | struct delayed_work free_framebuffer_work; | ||
104 | atomic_t usb_active; /* 0 = update virtual buffer, but no usb traffic */ | ||
105 | atomic_t lost_pixels; /* 1 = a render op failed. Need screen refresh */ | ||
106 | u8 *edid; /* null until we read edid from hw or get from sysfs */ | ||
107 | size_t edid_size; | ||
108 | u32 pseudo_palette[256]; | ||
109 | }; | ||
110 | |||
111 | static struct fb_fix_screeninfo ufx_fix = { | ||
112 | .id = "smscufx", | ||
113 | .type = FB_TYPE_PACKED_PIXELS, | ||
114 | .visual = FB_VISUAL_TRUECOLOR, | ||
115 | .xpanstep = 0, | ||
116 | .ypanstep = 0, | ||
117 | .ywrapstep = 0, | ||
118 | .accel = FB_ACCEL_NONE, | ||
119 | }; | ||
120 | |||
121 | static const u32 smscufx_info_flags = FBINFO_DEFAULT | FBINFO_READS_FAST | | ||
122 | FBINFO_VIRTFB | FBINFO_HWACCEL_IMAGEBLIT | FBINFO_HWACCEL_FILLRECT | | ||
123 | FBINFO_HWACCEL_COPYAREA | FBINFO_MISC_ALWAYS_SETPAR; | ||
124 | |||
125 | static struct usb_device_id id_table[] = { | ||
126 | {USB_DEVICE(0x0424, 0x9d00),}, | ||
127 | {USB_DEVICE(0x0424, 0x9d01),}, | ||
128 | {}, | ||
129 | }; | ||
130 | MODULE_DEVICE_TABLE(usb, id_table); | ||
131 | |||
132 | /* module options */ | ||
133 | static int console; /* Optionally allow fbcon to consume first framebuffer */ | ||
134 | static int fb_defio = true; /* Optionally enable fb_defio mmap support */ | ||
135 | |||
136 | /* ufx keeps a list of urbs for efficient bulk transfers */ | ||
137 | static void ufx_urb_completion(struct urb *urb); | ||
138 | static struct urb *ufx_get_urb(struct ufx_data *dev); | ||
139 | static int ufx_submit_urb(struct ufx_data *dev, struct urb * urb, size_t len); | ||
140 | static int ufx_alloc_urb_list(struct ufx_data *dev, int count, size_t size); | ||
141 | static void ufx_free_urb_list(struct ufx_data *dev); | ||
142 | |||
143 | /* reads a control register */ | ||
144 | static int ufx_reg_read(struct ufx_data *dev, u32 index, u32 *data) | ||
145 | { | ||
146 | u32 *buf = kmalloc(4, GFP_KERNEL); | ||
147 | int ret; | ||
148 | |||
149 | BUG_ON(!dev); | ||
150 | |||
151 | if (!buf) | ||
152 | return -ENOMEM; | ||
153 | |||
154 | ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), | ||
155 | USB_VENDOR_REQUEST_READ_REGISTER, | ||
156 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
157 | 00, index, buf, 4, USB_CTRL_GET_TIMEOUT); | ||
158 | |||
159 | le32_to_cpus(buf); | ||
160 | *data = *buf; | ||
161 | kfree(buf); | ||
162 | |||
163 | if (unlikely(ret < 0)) | ||
164 | pr_warn("Failed to read register index 0x%08x\n", index); | ||
165 | |||
166 | return ret; | ||
167 | } | ||
168 | |||
169 | /* writes a control register */ | ||
170 | static int ufx_reg_write(struct ufx_data *dev, u32 index, u32 data) | ||
171 | { | ||
172 | u32 *buf = kmalloc(4, GFP_KERNEL); | ||
173 | int ret; | ||
174 | |||
175 | BUG_ON(!dev); | ||
176 | |||
177 | if (!buf) | ||
178 | return -ENOMEM; | ||
179 | |||
180 | *buf = data; | ||
181 | cpu_to_le32s(buf); | ||
182 | |||
183 | ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), | ||
184 | USB_VENDOR_REQUEST_WRITE_REGISTER, | ||
185 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
186 | 00, index, buf, 4, USB_CTRL_SET_TIMEOUT); | ||
187 | |||
188 | kfree(buf); | ||
189 | |||
190 | if (unlikely(ret < 0)) | ||
191 | pr_warn("Failed to write register index 0x%08x with value " | ||
192 | "0x%08x\n", index, data); | ||
193 | |||
194 | return ret; | ||
195 | } | ||
196 | |||
197 | static int ufx_reg_clear_and_set_bits(struct ufx_data *dev, u32 index, | ||
198 | u32 bits_to_clear, u32 bits_to_set) | ||
199 | { | ||
200 | u32 data; | ||
201 | int status = ufx_reg_read(dev, index, &data); | ||
202 | check_warn_return(status, "ufx_reg_clear_and_set_bits error reading " | ||
203 | "0x%x", index); | ||
204 | |||
205 | data &= (~bits_to_clear); | ||
206 | data |= bits_to_set; | ||
207 | |||
208 | status = ufx_reg_write(dev, index, data); | ||
209 | check_warn_return(status, "ufx_reg_clear_and_set_bits error writing " | ||
210 | "0x%x", index); | ||
211 | |||
212 | return 0; | ||
213 | } | ||
214 | |||
215 | static int ufx_reg_set_bits(struct ufx_data *dev, u32 index, u32 bits) | ||
216 | { | ||
217 | return ufx_reg_clear_and_set_bits(dev, index, 0, bits); | ||
218 | } | ||
219 | |||
220 | static int ufx_reg_clear_bits(struct ufx_data *dev, u32 index, u32 bits) | ||
221 | { | ||
222 | return ufx_reg_clear_and_set_bits(dev, index, bits, 0); | ||
223 | } | ||
224 | |||
225 | static int ufx_lite_reset(struct ufx_data *dev) | ||
226 | { | ||
227 | int status; | ||
228 | u32 value; | ||
229 | |||
230 | status = ufx_reg_write(dev, 0x3008, 0x00000001); | ||
231 | check_warn_return(status, "ufx_lite_reset error writing 0x3008"); | ||
232 | |||
233 | status = ufx_reg_read(dev, 0x3008, &value); | ||
234 | check_warn_return(status, "ufx_lite_reset error reading 0x3008"); | ||
235 | |||
236 | return (value == 0) ? 0 : -EIO; | ||
237 | } | ||
238 | |||
239 | /* If display is unblanked, then blank it */ | ||
240 | static int ufx_blank(struct ufx_data *dev, bool wait) | ||
241 | { | ||
242 | u32 dc_ctrl, dc_sts; | ||
243 | int i; | ||
244 | |||
245 | int status = ufx_reg_read(dev, 0x2004, &dc_sts); | ||
246 | check_warn_return(status, "ufx_blank error reading 0x2004"); | ||
247 | |||
248 | status = ufx_reg_read(dev, 0x2000, &dc_ctrl); | ||
249 | check_warn_return(status, "ufx_blank error reading 0x2000"); | ||
250 | |||
251 | /* return success if display is already blanked */ | ||
252 | if ((dc_sts & 0x00000100) || (dc_ctrl & 0x00000100)) | ||
253 | return 0; | ||
254 | |||
255 | /* request the DC to blank the display */ | ||
256 | dc_ctrl |= 0x00000100; | ||
257 | status = ufx_reg_write(dev, 0x2000, dc_ctrl); | ||
258 | check_warn_return(status, "ufx_blank error writing 0x2000"); | ||
259 | |||
260 | /* return success immediately if we don't have to wait */ | ||
261 | if (!wait) | ||
262 | return 0; | ||
263 | |||
264 | for (i = 0; i < 250; i++) { | ||
265 | status = ufx_reg_read(dev, 0x2004, &dc_sts); | ||
266 | check_warn_return(status, "ufx_blank error reading 0x2004"); | ||
267 | |||
268 | if (dc_sts & 0x00000100) | ||
269 | return 0; | ||
270 | } | ||
271 | |||
272 | /* timed out waiting for display to blank */ | ||
273 | return -EIO; | ||
274 | } | ||
275 | |||
276 | /* If display is blanked, then unblank it */ | ||
277 | static int ufx_unblank(struct ufx_data *dev, bool wait) | ||
278 | { | ||
279 | u32 dc_ctrl, dc_sts; | ||
280 | int i; | ||
281 | |||
282 | int status = ufx_reg_read(dev, 0x2004, &dc_sts); | ||
283 | check_warn_return(status, "ufx_unblank error reading 0x2004"); | ||
284 | |||
285 | status = ufx_reg_read(dev, 0x2000, &dc_ctrl); | ||
286 | check_warn_return(status, "ufx_unblank error reading 0x2000"); | ||
287 | |||
288 | /* return success if display is already unblanked */ | ||
289 | if (((dc_sts & 0x00000100) == 0) || ((dc_ctrl & 0x00000100) == 0)) | ||
290 | return 0; | ||
291 | |||
292 | /* request the DC to unblank the display */ | ||
293 | dc_ctrl &= ~0x00000100; | ||
294 | status = ufx_reg_write(dev, 0x2000, dc_ctrl); | ||
295 | check_warn_return(status, "ufx_unblank error writing 0x2000"); | ||
296 | |||
297 | /* return success immediately if we don't have to wait */ | ||
298 | if (!wait) | ||
299 | return 0; | ||
300 | |||
301 | for (i = 0; i < 250; i++) { | ||
302 | status = ufx_reg_read(dev, 0x2004, &dc_sts); | ||
303 | check_warn_return(status, "ufx_unblank error reading 0x2004"); | ||
304 | |||
305 | if ((dc_sts & 0x00000100) == 0) | ||
306 | return 0; | ||
307 | } | ||
308 | |||
309 | /* timed out waiting for display to unblank */ | ||
310 | return -EIO; | ||
311 | } | ||
312 | |||
313 | /* If display is enabled, then disable it */ | ||
314 | static int ufx_disable(struct ufx_data *dev, bool wait) | ||
315 | { | ||
316 | u32 dc_ctrl, dc_sts; | ||
317 | int i; | ||
318 | |||
319 | int status = ufx_reg_read(dev, 0x2004, &dc_sts); | ||
320 | check_warn_return(status, "ufx_disable error reading 0x2004"); | ||
321 | |||
322 | status = ufx_reg_read(dev, 0x2000, &dc_ctrl); | ||
323 | check_warn_return(status, "ufx_disable error reading 0x2000"); | ||
324 | |||
325 | /* return success if display is already disabled */ | ||
326 | if (((dc_sts & 0x00000001) == 0) || ((dc_ctrl & 0x00000001) == 0)) | ||
327 | return 0; | ||
328 | |||
329 | /* request the DC to disable the display */ | ||
330 | dc_ctrl &= ~(0x00000001); | ||
331 | status = ufx_reg_write(dev, 0x2000, dc_ctrl); | ||
332 | check_warn_return(status, "ufx_disable error writing 0x2000"); | ||
333 | |||
334 | /* return success immediately if we don't have to wait */ | ||
335 | if (!wait) | ||
336 | return 0; | ||
337 | |||
338 | for (i = 0; i < 250; i++) { | ||
339 | status = ufx_reg_read(dev, 0x2004, &dc_sts); | ||
340 | check_warn_return(status, "ufx_disable error reading 0x2004"); | ||
341 | |||
342 | if ((dc_sts & 0x00000001) == 0) | ||
343 | return 0; | ||
344 | } | ||
345 | |||
346 | /* timed out waiting for display to disable */ | ||
347 | return -EIO; | ||
348 | } | ||
349 | |||
350 | /* If display is disabled, then enable it */ | ||
351 | static int ufx_enable(struct ufx_data *dev, bool wait) | ||
352 | { | ||
353 | u32 dc_ctrl, dc_sts; | ||
354 | int i; | ||
355 | |||
356 | int status = ufx_reg_read(dev, 0x2004, &dc_sts); | ||
357 | check_warn_return(status, "ufx_enable error reading 0x2004"); | ||
358 | |||
359 | status = ufx_reg_read(dev, 0x2000, &dc_ctrl); | ||
360 | check_warn_return(status, "ufx_enable error reading 0x2000"); | ||
361 | |||
362 | /* return success if display is already enabled */ | ||
363 | if ((dc_sts & 0x00000001) || (dc_ctrl & 0x00000001)) | ||
364 | return 0; | ||
365 | |||
366 | /* request the DC to enable the display */ | ||
367 | dc_ctrl |= 0x00000001; | ||
368 | status = ufx_reg_write(dev, 0x2000, dc_ctrl); | ||
369 | check_warn_return(status, "ufx_enable error writing 0x2000"); | ||
370 | |||
371 | /* return success immediately if we don't have to wait */ | ||
372 | if (!wait) | ||
373 | return 0; | ||
374 | |||
375 | for (i = 0; i < 250; i++) { | ||
376 | status = ufx_reg_read(dev, 0x2004, &dc_sts); | ||
377 | check_warn_return(status, "ufx_enable error reading 0x2004"); | ||
378 | |||
379 | if (dc_sts & 0x00000001) | ||
380 | return 0; | ||
381 | } | ||
382 | |||
383 | /* timed out waiting for display to enable */ | ||
384 | return -EIO; | ||
385 | } | ||
386 | |||
387 | static int ufx_config_sys_clk(struct ufx_data *dev) | ||
388 | { | ||
389 | int status = ufx_reg_write(dev, 0x700C, 0x8000000F); | ||
390 | check_warn_return(status, "error writing 0x700C"); | ||
391 | |||
392 | status = ufx_reg_write(dev, 0x7014, 0x0010024F); | ||
393 | check_warn_return(status, "error writing 0x7014"); | ||
394 | |||
395 | status = ufx_reg_write(dev, 0x7010, 0x00000000); | ||
396 | check_warn_return(status, "error writing 0x7010"); | ||
397 | |||
398 | status = ufx_reg_clear_bits(dev, 0x700C, 0x0000000A); | ||
399 | check_warn_return(status, "error clearing PLL1 bypass in 0x700C"); | ||
400 | msleep(1); | ||
401 | |||
402 | status = ufx_reg_clear_bits(dev, 0x700C, 0x80000000); | ||
403 | check_warn_return(status, "error clearing output gate in 0x700C"); | ||
404 | |||
405 | return 0; | ||
406 | } | ||
407 | |||
408 | static int ufx_config_ddr2(struct ufx_data *dev) | ||
409 | { | ||
410 | int status, i = 0; | ||
411 | u32 tmp; | ||
412 | |||
413 | status = ufx_reg_write(dev, 0x0004, 0x001F0F77); | ||
414 | check_warn_return(status, "error writing 0x0004"); | ||
415 | |||
416 | status = ufx_reg_write(dev, 0x0008, 0xFFF00000); | ||
417 | check_warn_return(status, "error writing 0x0008"); | ||
418 | |||
419 | status = ufx_reg_write(dev, 0x000C, 0x0FFF2222); | ||
420 | check_warn_return(status, "error writing 0x000C"); | ||
421 | |||
422 | status = ufx_reg_write(dev, 0x0010, 0x00030814); | ||
423 | check_warn_return(status, "error writing 0x0010"); | ||
424 | |||
425 | status = ufx_reg_write(dev, 0x0014, 0x00500019); | ||
426 | check_warn_return(status, "error writing 0x0014"); | ||
427 | |||
428 | status = ufx_reg_write(dev, 0x0018, 0x020D0F15); | ||
429 | check_warn_return(status, "error writing 0x0018"); | ||
430 | |||
431 | status = ufx_reg_write(dev, 0x001C, 0x02532305); | ||
432 | check_warn_return(status, "error writing 0x001C"); | ||
433 | |||
434 | status = ufx_reg_write(dev, 0x0020, 0x0B030905); | ||
435 | check_warn_return(status, "error writing 0x0020"); | ||
436 | |||
437 | status = ufx_reg_write(dev, 0x0024, 0x00000827); | ||
438 | check_warn_return(status, "error writing 0x0024"); | ||
439 | |||
440 | status = ufx_reg_write(dev, 0x0028, 0x00000000); | ||
441 | check_warn_return(status, "error writing 0x0028"); | ||
442 | |||
443 | status = ufx_reg_write(dev, 0x002C, 0x00000042); | ||
444 | check_warn_return(status, "error writing 0x002C"); | ||
445 | |||
446 | status = ufx_reg_write(dev, 0x0030, 0x09520000); | ||
447 | check_warn_return(status, "error writing 0x0030"); | ||
448 | |||
449 | status = ufx_reg_write(dev, 0x0034, 0x02223314); | ||
450 | check_warn_return(status, "error writing 0x0034"); | ||
451 | |||
452 | status = ufx_reg_write(dev, 0x0038, 0x00430043); | ||
453 | check_warn_return(status, "error writing 0x0038"); | ||
454 | |||
455 | status = ufx_reg_write(dev, 0x003C, 0xF00F000F); | ||
456 | check_warn_return(status, "error writing 0x003C"); | ||
457 | |||
458 | status = ufx_reg_write(dev, 0x0040, 0xF380F00F); | ||
459 | check_warn_return(status, "error writing 0x0040"); | ||
460 | |||
461 | status = ufx_reg_write(dev, 0x0044, 0xF00F0496); | ||
462 | check_warn_return(status, "error writing 0x0044"); | ||
463 | |||
464 | status = ufx_reg_write(dev, 0x0048, 0x03080406); | ||
465 | check_warn_return(status, "error writing 0x0048"); | ||
466 | |||
467 | status = ufx_reg_write(dev, 0x004C, 0x00001000); | ||
468 | check_warn_return(status, "error writing 0x004C"); | ||
469 | |||
470 | status = ufx_reg_write(dev, 0x005C, 0x00000007); | ||
471 | check_warn_return(status, "error writing 0x005C"); | ||
472 | |||
473 | status = ufx_reg_write(dev, 0x0100, 0x54F00012); | ||
474 | check_warn_return(status, "error writing 0x0100"); | ||
475 | |||
476 | status = ufx_reg_write(dev, 0x0104, 0x00004012); | ||
477 | check_warn_return(status, "error writing 0x0104"); | ||
478 | |||
479 | status = ufx_reg_write(dev, 0x0118, 0x40404040); | ||
480 | check_warn_return(status, "error writing 0x0118"); | ||
481 | |||
482 | status = ufx_reg_write(dev, 0x0000, 0x00000001); | ||
483 | check_warn_return(status, "error writing 0x0000"); | ||
484 | |||
485 | while (i++ < 500) { | ||
486 | status = ufx_reg_read(dev, 0x0000, &tmp); | ||
487 | check_warn_return(status, "error reading 0x0000"); | ||
488 | |||
489 | if (all_bits_set(tmp, 0xC0000000)) | ||
490 | return 0; | ||
491 | } | ||
492 | |||
493 | pr_err("DDR2 initialisation timed out, reg 0x0000=0x%08x", tmp); | ||
494 | return -ETIMEDOUT; | ||
495 | } | ||
496 | |||
497 | struct pll_values { | ||
498 | u32 div_r0; | ||
499 | u32 div_f0; | ||
500 | u32 div_q0; | ||
501 | u32 range0; | ||
502 | u32 div_r1; | ||
503 | u32 div_f1; | ||
504 | u32 div_q1; | ||
505 | u32 range1; | ||
506 | }; | ||
507 | |||
508 | static u32 ufx_calc_range(u32 ref_freq) | ||
509 | { | ||
510 | if (ref_freq >= 88000000) | ||
511 | return 7; | ||
512 | |||
513 | if (ref_freq >= 54000000) | ||
514 | return 6; | ||
515 | |||
516 | if (ref_freq >= 34000000) | ||
517 | return 5; | ||
518 | |||
519 | if (ref_freq >= 21000000) | ||
520 | return 4; | ||
521 | |||
522 | if (ref_freq >= 13000000) | ||
523 | return 3; | ||
524 | |||
525 | if (ref_freq >= 8000000) | ||
526 | return 2; | ||
527 | |||
528 | return 1; | ||
529 | } | ||
530 | |||
531 | /* calculates PLL divider settings for a desired target frequency */ | ||
532 | static void ufx_calc_pll_values(const u32 clk_pixel_pll, struct pll_values *asic_pll) | ||
533 | { | ||
534 | const u32 ref_clk = 25000000; | ||
535 | u32 div_r0, div_f0, div_q0, div_r1, div_f1, div_q1; | ||
536 | u32 min_error = clk_pixel_pll; | ||
537 | |||
538 | for (div_r0 = 1; div_r0 <= 32; div_r0++) { | ||
539 | u32 ref_freq0 = ref_clk / div_r0; | ||
540 | if (ref_freq0 < 5000000) | ||
541 | break; | ||
542 | |||
543 | if (ref_freq0 > 200000000) | ||
544 | continue; | ||
545 | |||
546 | for (div_f0 = 1; div_f0 <= 256; div_f0++) { | ||
547 | u32 vco_freq0 = ref_freq0 * div_f0; | ||
548 | |||
549 | if (vco_freq0 < 350000000) | ||
550 | continue; | ||
551 | |||
552 | if (vco_freq0 > 700000000) | ||
553 | break; | ||
554 | |||
555 | for (div_q0 = 0; div_q0 < 7; div_q0++) { | ||
556 | u32 pllout_freq0 = vco_freq0 / (1 << div_q0); | ||
557 | |||
558 | if (pllout_freq0 < 5000000) | ||
559 | break; | ||
560 | |||
561 | if (pllout_freq0 > 200000000) | ||
562 | continue; | ||
563 | |||
564 | for (div_r1 = 1; div_r1 <= 32; div_r1++) { | ||
565 | u32 ref_freq1 = pllout_freq0 / div_r1; | ||
566 | |||
567 | if (ref_freq1 < 5000000) | ||
568 | break; | ||
569 | |||
570 | for (div_f1 = 1; div_f1 <= 256; div_f1++) { | ||
571 | u32 vco_freq1 = ref_freq1 * div_f1; | ||
572 | |||
573 | if (vco_freq1 < 350000000) | ||
574 | continue; | ||
575 | |||
576 | if (vco_freq1 > 700000000) | ||
577 | break; | ||
578 | |||
579 | for (div_q1 = 0; div_q1 < 7; div_q1++) { | ||
580 | u32 pllout_freq1 = vco_freq1 / (1 << div_q1); | ||
581 | int error = abs(pllout_freq1 - clk_pixel_pll); | ||
582 | |||
583 | if (pllout_freq1 < 5000000) | ||
584 | break; | ||
585 | |||
586 | if (pllout_freq1 > 700000000) | ||
587 | continue; | ||
588 | |||
589 | if (error < min_error) { | ||
590 | min_error = error; | ||
591 | |||
592 | /* final returned value is equal to calculated value - 1 | ||
593 | * because a value of 0 = divide by 1 */ | ||
594 | asic_pll->div_r0 = div_r0 - 1; | ||
595 | asic_pll->div_f0 = div_f0 - 1; | ||
596 | asic_pll->div_q0 = div_q0; | ||
597 | asic_pll->div_r1 = div_r1 - 1; | ||
598 | asic_pll->div_f1 = div_f1 - 1; | ||
599 | asic_pll->div_q1 = div_q1; | ||
600 | |||
601 | asic_pll->range0 = ufx_calc_range(ref_freq0); | ||
602 | asic_pll->range1 = ufx_calc_range(ref_freq1); | ||
603 | |||
604 | if (min_error == 0) | ||
605 | return; | ||
606 | } | ||
607 | } | ||
608 | } | ||
609 | } | ||
610 | } | ||
611 | } | ||
612 | } | ||
613 | } | ||
614 | |||
615 | /* sets analog bit PLL configuration values */ | ||
616 | static int ufx_config_pix_clk(struct ufx_data *dev, u32 pixclock) | ||
617 | { | ||
618 | struct pll_values asic_pll = {0}; | ||
619 | u32 value, clk_pixel, clk_pixel_pll; | ||
620 | int status; | ||
621 | |||
622 | /* convert pixclock (in ps) to frequency (in Hz) */ | ||
623 | clk_pixel = PICOS2KHZ(pixclock) * 1000; | ||
624 | pr_debug("pixclock %d ps = clk_pixel %d Hz", pixclock, clk_pixel); | ||
625 | |||
626 | /* clk_pixel = 1/2 clk_pixel_pll */ | ||
627 | clk_pixel_pll = clk_pixel * 2; | ||
628 | |||
629 | ufx_calc_pll_values(clk_pixel_pll, &asic_pll); | ||
630 | |||
631 | /* Keep BYPASS and RESET signals asserted until configured */ | ||
632 | status = ufx_reg_write(dev, 0x7000, 0x8000000F); | ||
633 | check_warn_return(status, "error writing 0x7000"); | ||
634 | |||
635 | value = (asic_pll.div_f1 | (asic_pll.div_r1 << 8) | | ||
636 | (asic_pll.div_q1 << 16) | (asic_pll.range1 << 20)); | ||
637 | status = ufx_reg_write(dev, 0x7008, value); | ||
638 | check_warn_return(status, "error writing 0x7008"); | ||
639 | |||
640 | value = (asic_pll.div_f0 | (asic_pll.div_r0 << 8) | | ||
641 | (asic_pll.div_q0 << 16) | (asic_pll.range0 << 20)); | ||
642 | status = ufx_reg_write(dev, 0x7004, value); | ||
643 | check_warn_return(status, "error writing 0x7004"); | ||
644 | |||
645 | status = ufx_reg_clear_bits(dev, 0x7000, 0x00000005); | ||
646 | check_warn_return(status, | ||
647 | "error clearing PLL0 bypass bits in 0x7000"); | ||
648 | msleep(1); | ||
649 | |||
650 | status = ufx_reg_clear_bits(dev, 0x7000, 0x0000000A); | ||
651 | check_warn_return(status, | ||
652 | "error clearing PLL1 bypass bits in 0x7000"); | ||
653 | msleep(1); | ||
654 | |||
655 | status = ufx_reg_clear_bits(dev, 0x7000, 0x80000000); | ||
656 | check_warn_return(status, "error clearing gate bits in 0x7000"); | ||
657 | |||
658 | return 0; | ||
659 | } | ||
660 | |||
661 | static int ufx_set_vid_mode(struct ufx_data *dev, struct fb_var_screeninfo *var) | ||
662 | { | ||
663 | u32 temp; | ||
664 | u16 h_total, h_active, h_blank_start, h_blank_end, h_sync_start, h_sync_end; | ||
665 | u16 v_total, v_active, v_blank_start, v_blank_end, v_sync_start, v_sync_end; | ||
666 | |||
667 | int status = ufx_reg_write(dev, 0x8028, 0); | ||
668 | check_warn_return(status, "ufx_set_vid_mode error disabling RGB pad"); | ||
669 | |||
670 | status = ufx_reg_write(dev, 0x8024, 0); | ||
671 | check_warn_return(status, "ufx_set_vid_mode error disabling VDAC"); | ||
672 | |||
673 | /* shut everything down before changing timing */ | ||
674 | status = ufx_blank(dev, true); | ||
675 | check_warn_return(status, "ufx_set_vid_mode error blanking display"); | ||
676 | |||
677 | status = ufx_disable(dev, true); | ||
678 | check_warn_return(status, "ufx_set_vid_mode error disabling display"); | ||
679 | |||
680 | status = ufx_config_pix_clk(dev, var->pixclock); | ||
681 | check_warn_return(status, "ufx_set_vid_mode error configuring pixclock"); | ||
682 | |||
683 | status = ufx_reg_write(dev, 0x2000, 0x00000104); | ||
684 | check_warn_return(status, "ufx_set_vid_mode error writing 0x2000"); | ||
685 | |||
686 | /* set horizontal timings */ | ||
687 | h_total = var->xres + var->right_margin + var->hsync_len + var->left_margin; | ||
688 | h_active = var->xres; | ||
689 | h_blank_start = var->xres + var->right_margin; | ||
690 | h_blank_end = var->xres + var->right_margin + var->hsync_len; | ||
691 | h_sync_start = var->xres + var->right_margin; | ||
692 | h_sync_end = var->xres + var->right_margin + var->hsync_len; | ||
693 | |||
694 | temp = ((h_total - 1) << 16) | (h_active - 1); | ||
695 | status = ufx_reg_write(dev, 0x2008, temp); | ||
696 | check_warn_return(status, "ufx_set_vid_mode error writing 0x2008"); | ||
697 | |||
698 | temp = ((h_blank_start - 1) << 16) | (h_blank_end - 1); | ||
699 | status = ufx_reg_write(dev, 0x200C, temp); | ||
700 | check_warn_return(status, "ufx_set_vid_mode error writing 0x200C"); | ||
701 | |||
702 | temp = ((h_sync_start - 1) << 16) | (h_sync_end - 1); | ||
703 | status = ufx_reg_write(dev, 0x2010, temp); | ||
704 | check_warn_return(status, "ufx_set_vid_mode error writing 0x2010"); | ||
705 | |||
706 | /* set vertical timings */ | ||
707 | v_total = var->upper_margin + var->yres + var->lower_margin + var->vsync_len; | ||
708 | v_active = var->yres; | ||
709 | v_blank_start = var->yres + var->lower_margin; | ||
710 | v_blank_end = var->yres + var->lower_margin + var->vsync_len; | ||
711 | v_sync_start = var->yres + var->lower_margin; | ||
712 | v_sync_end = var->yres + var->lower_margin + var->vsync_len; | ||
713 | |||
714 | temp = ((v_total - 1) << 16) | (v_active - 1); | ||
715 | status = ufx_reg_write(dev, 0x2014, temp); | ||
716 | check_warn_return(status, "ufx_set_vid_mode error writing 0x2014"); | ||
717 | |||
718 | temp = ((v_blank_start - 1) << 16) | (v_blank_end - 1); | ||
719 | status = ufx_reg_write(dev, 0x2018, temp); | ||
720 | check_warn_return(status, "ufx_set_vid_mode error writing 0x2018"); | ||
721 | |||
722 | temp = ((v_sync_start - 1) << 16) | (v_sync_end - 1); | ||
723 | status = ufx_reg_write(dev, 0x201C, temp); | ||
724 | check_warn_return(status, "ufx_set_vid_mode error writing 0x201C"); | ||
725 | |||
726 | status = ufx_reg_write(dev, 0x2020, 0x00000000); | ||
727 | check_warn_return(status, "ufx_set_vid_mode error writing 0x2020"); | ||
728 | |||
729 | status = ufx_reg_write(dev, 0x2024, 0x00000000); | ||
730 | check_warn_return(status, "ufx_set_vid_mode error writing 0x2024"); | ||
731 | |||
732 | /* Set the frame length register (#pix * 2 bytes/pixel) */ | ||
733 | temp = var->xres * var->yres * 2; | ||
734 | temp = (temp + 7) & (~0x7); | ||
735 | status = ufx_reg_write(dev, 0x2028, temp); | ||
736 | check_warn_return(status, "ufx_set_vid_mode error writing 0x2028"); | ||
737 | |||
738 | /* enable desired output interface & disable others */ | ||
739 | status = ufx_reg_write(dev, 0x2040, 0); | ||
740 | check_warn_return(status, "ufx_set_vid_mode error writing 0x2040"); | ||
741 | |||
742 | status = ufx_reg_write(dev, 0x2044, 0); | ||
743 | check_warn_return(status, "ufx_set_vid_mode error writing 0x2044"); | ||
744 | |||
745 | status = ufx_reg_write(dev, 0x2048, 0); | ||
746 | check_warn_return(status, "ufx_set_vid_mode error writing 0x2048"); | ||
747 | |||
748 | /* set the sync polarities & enable bit */ | ||
749 | temp = 0x00000001; | ||
750 | if (var->sync & FB_SYNC_HOR_HIGH_ACT) | ||
751 | temp |= 0x00000010; | ||
752 | |||
753 | if (var->sync & FB_SYNC_VERT_HIGH_ACT) | ||
754 | temp |= 0x00000008; | ||
755 | |||
756 | status = ufx_reg_write(dev, 0x2040, temp); | ||
757 | check_warn_return(status, "ufx_set_vid_mode error writing 0x2040"); | ||
758 | |||
759 | /* start everything back up */ | ||
760 | status = ufx_enable(dev, true); | ||
761 | check_warn_return(status, "ufx_set_vid_mode error enabling display"); | ||
762 | |||
763 | /* Unblank the display */ | ||
764 | status = ufx_unblank(dev, true); | ||
765 | check_warn_return(status, "ufx_set_vid_mode error unblanking display"); | ||
766 | |||
767 | /* enable RGB pad */ | ||
768 | status = ufx_reg_write(dev, 0x8028, 0x00000003); | ||
769 | check_warn_return(status, "ufx_set_vid_mode error enabling RGB pad"); | ||
770 | |||
771 | /* enable VDAC */ | ||
772 | status = ufx_reg_write(dev, 0x8024, 0x00000007); | ||
773 | check_warn_return(status, "ufx_set_vid_mode error enabling VDAC"); | ||
774 | |||
775 | return 0; | ||
776 | } | ||
777 | |||
778 | static int ufx_ops_mmap(struct fb_info *info, struct vm_area_struct *vma) | ||
779 | { | ||
780 | unsigned long start = vma->vm_start; | ||
781 | unsigned long size = vma->vm_end - vma->vm_start; | ||
782 | unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; | ||
783 | unsigned long page, pos; | ||
784 | |||
785 | if (offset + size > info->fix.smem_len) | ||
786 | return -EINVAL; | ||
787 | |||
788 | pos = (unsigned long)info->fix.smem_start + offset; | ||
789 | |||
790 | pr_debug("mmap() framebuffer addr:%lu size:%lu\n", | ||
791 | pos, size); | ||
792 | |||
793 | while (size > 0) { | ||
794 | page = vmalloc_to_pfn((void *)pos); | ||
795 | if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) | ||
796 | return -EAGAIN; | ||
797 | |||
798 | start += PAGE_SIZE; | ||
799 | pos += PAGE_SIZE; | ||
800 | if (size > PAGE_SIZE) | ||
801 | size -= PAGE_SIZE; | ||
802 | else | ||
803 | size = 0; | ||
804 | } | ||
805 | |||
806 | vma->vm_flags |= VM_RESERVED; /* avoid to swap out this VMA */ | ||
807 | return 0; | ||
808 | } | ||
809 | |||
810 | static void ufx_raw_rect(struct ufx_data *dev, u16 *cmd, int x, int y, | ||
811 | int width, int height) | ||
812 | { | ||
813 | size_t packed_line_len = ALIGN((width * 2), 4); | ||
814 | size_t packed_rect_len = packed_line_len * height; | ||
815 | int line; | ||
816 | |||
817 | BUG_ON(!dev); | ||
818 | BUG_ON(!dev->info); | ||
819 | |||
820 | /* command word */ | ||
821 | *((u32 *)&cmd[0]) = cpu_to_le32(0x01); | ||
822 | |||
823 | /* length word */ | ||
824 | *((u32 *)&cmd[2]) = cpu_to_le32(packed_rect_len + 16); | ||
825 | |||
826 | cmd[4] = cpu_to_le16(x); | ||
827 | cmd[5] = cpu_to_le16(y); | ||
828 | cmd[6] = cpu_to_le16(width); | ||
829 | cmd[7] = cpu_to_le16(height); | ||
830 | |||
831 | /* frame base address */ | ||
832 | *((u32 *)&cmd[8]) = cpu_to_le32(0); | ||
833 | |||
834 | /* color mode and horizontal resolution */ | ||
835 | cmd[10] = cpu_to_le16(0x4000 | dev->info->var.xres); | ||
836 | |||
837 | /* vertical resolution */ | ||
838 | cmd[11] = cpu_to_le16(dev->info->var.yres); | ||
839 | |||
840 | /* packed data */ | ||
841 | for (line = 0; line < height; line++) { | ||
842 | const int line_offset = dev->info->fix.line_length * (y + line); | ||
843 | const int byte_offset = line_offset + (x * BPP); | ||
844 | memcpy(&cmd[(24 + (packed_line_len * line)) / 2], | ||
845 | (char *)dev->info->fix.smem_start + byte_offset, width * BPP); | ||
846 | } | ||
847 | } | ||
848 | |||
849 | int ufx_handle_damage(struct ufx_data *dev, int x, int y, | ||
850 | int width, int height) | ||
851 | { | ||
852 | size_t packed_line_len = ALIGN((width * 2), 4); | ||
853 | int len, status, urb_lines, start_line = 0; | ||
854 | |||
855 | if ((width <= 0) || (height <= 0) || | ||
856 | (x + width > dev->info->var.xres) || | ||
857 | (y + height > dev->info->var.yres)) | ||
858 | return -EINVAL; | ||
859 | |||
860 | if (!atomic_read(&dev->usb_active)) | ||
861 | return 0; | ||
862 | |||
863 | while (start_line < height) { | ||
864 | struct urb *urb = ufx_get_urb(dev); | ||
865 | if (!urb) { | ||
866 | pr_warn("ufx_handle_damage unable to get urb"); | ||
867 | return 0; | ||
868 | } | ||
869 | |||
870 | /* assume we have enough space to transfer at least one line */ | ||
871 | BUG_ON(urb->transfer_buffer_length < (24 + (width * 2))); | ||
872 | |||
873 | /* calculate the maximum number of lines we could fit in */ | ||
874 | urb_lines = (urb->transfer_buffer_length - 24) / packed_line_len; | ||
875 | |||
876 | /* but we might not need this many */ | ||
877 | urb_lines = min(urb_lines, (height - start_line)); | ||
878 | |||
879 | memset(urb->transfer_buffer, 0, urb->transfer_buffer_length); | ||
880 | |||
881 | ufx_raw_rect(dev, urb->transfer_buffer, x, (y + start_line), width, urb_lines); | ||
882 | len = 24 + (packed_line_len * urb_lines); | ||
883 | |||
884 | status = ufx_submit_urb(dev, urb, len); | ||
885 | check_warn_return(status, "Error submitting URB"); | ||
886 | |||
887 | start_line += urb_lines; | ||
888 | } | ||
889 | |||
890 | return 0; | ||
891 | } | ||
892 | |||
893 | /* Path triggered by usermode clients who write to filesystem | ||
894 | * e.g. cat filename > /dev/fb1 | ||
895 | * Not used by X Windows or text-mode console. But useful for testing. | ||
896 | * Slow because of extra copy and we must assume all pixels dirty. */ | ||
897 | static ssize_t ufx_ops_write(struct fb_info *info, const char __user *buf, | ||
898 | size_t count, loff_t *ppos) | ||
899 | { | ||
900 | ssize_t result; | ||
901 | struct ufx_data *dev = info->par; | ||
902 | u32 offset = (u32) *ppos; | ||
903 | |||
904 | result = fb_sys_write(info, buf, count, ppos); | ||
905 | |||
906 | if (result > 0) { | ||
907 | int start = max((int)(offset / info->fix.line_length) - 1, 0); | ||
908 | int lines = min((u32)((result / info->fix.line_length) + 1), | ||
909 | (u32)info->var.yres); | ||
910 | |||
911 | ufx_handle_damage(dev, 0, start, info->var.xres, lines); | ||
912 | } | ||
913 | |||
914 | return result; | ||
915 | } | ||
916 | |||
917 | static void ufx_ops_copyarea(struct fb_info *info, | ||
918 | const struct fb_copyarea *area) | ||
919 | { | ||
920 | |||
921 | struct ufx_data *dev = info->par; | ||
922 | |||
923 | sys_copyarea(info, area); | ||
924 | |||
925 | ufx_handle_damage(dev, area->dx, area->dy, | ||
926 | area->width, area->height); | ||
927 | } | ||
928 | |||
929 | static void ufx_ops_imageblit(struct fb_info *info, | ||
930 | const struct fb_image *image) | ||
931 | { | ||
932 | struct ufx_data *dev = info->par; | ||
933 | |||
934 | sys_imageblit(info, image); | ||
935 | |||
936 | ufx_handle_damage(dev, image->dx, image->dy, | ||
937 | image->width, image->height); | ||
938 | } | ||
939 | |||
940 | static void ufx_ops_fillrect(struct fb_info *info, | ||
941 | const struct fb_fillrect *rect) | ||
942 | { | ||
943 | struct ufx_data *dev = info->par; | ||
944 | |||
945 | sys_fillrect(info, rect); | ||
946 | |||
947 | ufx_handle_damage(dev, rect->dx, rect->dy, rect->width, | ||
948 | rect->height); | ||
949 | } | ||
950 | |||
951 | /* NOTE: fb_defio.c is holding info->fbdefio.mutex | ||
952 | * Touching ANY framebuffer memory that triggers a page fault | ||
953 | * in fb_defio will cause a deadlock, when it also tries to | ||
954 | * grab the same mutex. */ | ||
955 | static void ufx_dpy_deferred_io(struct fb_info *info, | ||
956 | struct list_head *pagelist) | ||
957 | { | ||
958 | struct page *cur; | ||
959 | struct fb_deferred_io *fbdefio = info->fbdefio; | ||
960 | struct ufx_data *dev = info->par; | ||
961 | |||
962 | if (!fb_defio) | ||
963 | return; | ||
964 | |||
965 | if (!atomic_read(&dev->usb_active)) | ||
966 | return; | ||
967 | |||
968 | /* walk the written page list and render each to device */ | ||
969 | list_for_each_entry(cur, &fbdefio->pagelist, lru) { | ||
970 | /* create a rectangle of full screen width that encloses the | ||
971 | * entire dirty framebuffer page */ | ||
972 | const int x = 0; | ||
973 | const int width = dev->info->var.xres; | ||
974 | const int y = (cur->index << PAGE_SHIFT) / (width * 2); | ||
975 | int height = (PAGE_SIZE / (width * 2)) + 1; | ||
976 | height = min(height, (int)(dev->info->var.yres - y)); | ||
977 | |||
978 | BUG_ON(y >= dev->info->var.yres); | ||
979 | BUG_ON((y + height) > dev->info->var.yres); | ||
980 | |||
981 | ufx_handle_damage(dev, x, y, width, height); | ||
982 | } | ||
983 | } | ||
984 | |||
985 | static int ufx_ops_ioctl(struct fb_info *info, unsigned int cmd, | ||
986 | unsigned long arg) | ||
987 | { | ||
988 | struct ufx_data *dev = info->par; | ||
989 | struct dloarea *area = NULL; | ||
990 | |||
991 | if (!atomic_read(&dev->usb_active)) | ||
992 | return 0; | ||
993 | |||
994 | /* TODO: Update X server to get this from sysfs instead */ | ||
995 | if (cmd == UFX_IOCTL_RETURN_EDID) { | ||
996 | u8 __user *edid = (u8 __user *)arg; | ||
997 | if (copy_to_user(edid, dev->edid, dev->edid_size)) | ||
998 | return -EFAULT; | ||
999 | return 0; | ||
1000 | } | ||
1001 | |||
1002 | /* TODO: Help propose a standard fb.h ioctl to report mmap damage */ | ||
1003 | if (cmd == UFX_IOCTL_REPORT_DAMAGE) { | ||
1004 | /* If we have a damage-aware client, turn fb_defio "off" | ||
1005 | * To avoid perf imact of unecessary page fault handling. | ||
1006 | * Done by resetting the delay for this fb_info to a very | ||
1007 | * long period. Pages will become writable and stay that way. | ||
1008 | * Reset to normal value when all clients have closed this fb. | ||
1009 | */ | ||
1010 | if (info->fbdefio) | ||
1011 | info->fbdefio->delay = UFX_DEFIO_WRITE_DISABLE; | ||
1012 | |||
1013 | area = (struct dloarea *)arg; | ||
1014 | |||
1015 | if (area->x < 0) | ||
1016 | area->x = 0; | ||
1017 | |||
1018 | if (area->x > info->var.xres) | ||
1019 | area->x = info->var.xres; | ||
1020 | |||
1021 | if (area->y < 0) | ||
1022 | area->y = 0; | ||
1023 | |||
1024 | if (area->y > info->var.yres) | ||
1025 | area->y = info->var.yres; | ||
1026 | |||
1027 | ufx_handle_damage(dev, area->x, area->y, area->w, area->h); | ||
1028 | } | ||
1029 | |||
1030 | return 0; | ||
1031 | } | ||
1032 | |||
1033 | /* taken from vesafb */ | ||
1034 | static int | ||
1035 | ufx_ops_setcolreg(unsigned regno, unsigned red, unsigned green, | ||
1036 | unsigned blue, unsigned transp, struct fb_info *info) | ||
1037 | { | ||
1038 | int err = 0; | ||
1039 | |||
1040 | if (regno >= info->cmap.len) | ||
1041 | return 1; | ||
1042 | |||
1043 | if (regno < 16) { | ||
1044 | if (info->var.red.offset == 10) { | ||
1045 | /* 1:5:5:5 */ | ||
1046 | ((u32 *) (info->pseudo_palette))[regno] = | ||
1047 | ((red & 0xf800) >> 1) | | ||
1048 | ((green & 0xf800) >> 6) | ((blue & 0xf800) >> 11); | ||
1049 | } else { | ||
1050 | /* 0:5:6:5 */ | ||
1051 | ((u32 *) (info->pseudo_palette))[regno] = | ||
1052 | ((red & 0xf800)) | | ||
1053 | ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11); | ||
1054 | } | ||
1055 | } | ||
1056 | |||
1057 | return err; | ||
1058 | } | ||
1059 | |||
1060 | /* It's common for several clients to have framebuffer open simultaneously. | ||
1061 | * e.g. both fbcon and X. Makes things interesting. | ||
1062 | * Assumes caller is holding info->lock (for open and release at least) */ | ||
1063 | static int ufx_ops_open(struct fb_info *info, int user) | ||
1064 | { | ||
1065 | struct ufx_data *dev = info->par; | ||
1066 | |||
1067 | /* fbcon aggressively connects to first framebuffer it finds, | ||
1068 | * preventing other clients (X) from working properly. Usually | ||
1069 | * not what the user wants. Fail by default with option to enable. */ | ||
1070 | if (user == 0 && !console) | ||
1071 | return -EBUSY; | ||
1072 | |||
1073 | /* If the USB device is gone, we don't accept new opens */ | ||
1074 | if (dev->virtualized) | ||
1075 | return -ENODEV; | ||
1076 | |||
1077 | dev->fb_count++; | ||
1078 | |||
1079 | kref_get(&dev->kref); | ||
1080 | |||
1081 | if (fb_defio && (info->fbdefio == NULL)) { | ||
1082 | /* enable defio at last moment if not disabled by client */ | ||
1083 | |||
1084 | struct fb_deferred_io *fbdefio; | ||
1085 | |||
1086 | fbdefio = kmalloc(sizeof(struct fb_deferred_io), GFP_KERNEL); | ||
1087 | |||
1088 | if (fbdefio) { | ||
1089 | fbdefio->delay = UFX_DEFIO_WRITE_DELAY; | ||
1090 | fbdefio->deferred_io = ufx_dpy_deferred_io; | ||
1091 | } | ||
1092 | |||
1093 | info->fbdefio = fbdefio; | ||
1094 | fb_deferred_io_init(info); | ||
1095 | } | ||
1096 | |||
1097 | pr_debug("open /dev/fb%d user=%d fb_info=%p count=%d", | ||
1098 | info->node, user, info, dev->fb_count); | ||
1099 | |||
1100 | return 0; | ||
1101 | } | ||
1102 | |||
1103 | /* | ||
1104 | * Called when all client interfaces to start transactions have been disabled, | ||
1105 | * and all references to our device instance (ufx_data) are released. | ||
1106 | * Every transaction must have a reference, so we know are fully spun down | ||
1107 | */ | ||
1108 | static void ufx_free(struct kref *kref) | ||
1109 | { | ||
1110 | struct ufx_data *dev = container_of(kref, struct ufx_data, kref); | ||
1111 | |||
1112 | /* this function will wait for all in-flight urbs to complete */ | ||
1113 | if (dev->urbs.count > 0) | ||
1114 | ufx_free_urb_list(dev); | ||
1115 | |||
1116 | pr_debug("freeing ufx_data %p", dev); | ||
1117 | |||
1118 | kfree(dev); | ||
1119 | } | ||
1120 | |||
1121 | static void ufx_release_urb_work(struct work_struct *work) | ||
1122 | { | ||
1123 | struct urb_node *unode = container_of(work, struct urb_node, | ||
1124 | release_urb_work.work); | ||
1125 | |||
1126 | up(&unode->dev->urbs.limit_sem); | ||
1127 | } | ||
1128 | |||
1129 | static void ufx_free_framebuffer_work(struct work_struct *work) | ||
1130 | { | ||
1131 | struct ufx_data *dev = container_of(work, struct ufx_data, | ||
1132 | free_framebuffer_work.work); | ||
1133 | struct fb_info *info = dev->info; | ||
1134 | int node = info->node; | ||
1135 | |||
1136 | unregister_framebuffer(info); | ||
1137 | |||
1138 | if (info->cmap.len != 0) | ||
1139 | fb_dealloc_cmap(&info->cmap); | ||
1140 | if (info->monspecs.modedb) | ||
1141 | fb_destroy_modedb(info->monspecs.modedb); | ||
1142 | if (info->screen_base) | ||
1143 | vfree(info->screen_base); | ||
1144 | |||
1145 | fb_destroy_modelist(&info->modelist); | ||
1146 | |||
1147 | dev->info = 0; | ||
1148 | |||
1149 | /* Assume info structure is freed after this point */ | ||
1150 | framebuffer_release(info); | ||
1151 | |||
1152 | pr_debug("fb_info for /dev/fb%d has been freed", node); | ||
1153 | |||
1154 | /* ref taken in probe() as part of registering framebfufer */ | ||
1155 | kref_put(&dev->kref, ufx_free); | ||
1156 | } | ||
1157 | |||
1158 | /* | ||
1159 | * Assumes caller is holding info->lock mutex (for open and release at least) | ||
1160 | */ | ||
1161 | static int ufx_ops_release(struct fb_info *info, int user) | ||
1162 | { | ||
1163 | struct ufx_data *dev = info->par; | ||
1164 | |||
1165 | dev->fb_count--; | ||
1166 | |||
1167 | /* We can't free fb_info here - fbmem will touch it when we return */ | ||
1168 | if (dev->virtualized && (dev->fb_count == 0)) | ||
1169 | schedule_delayed_work(&dev->free_framebuffer_work, HZ); | ||
1170 | |||
1171 | if ((dev->fb_count == 0) && (info->fbdefio)) { | ||
1172 | fb_deferred_io_cleanup(info); | ||
1173 | kfree(info->fbdefio); | ||
1174 | info->fbdefio = NULL; | ||
1175 | info->fbops->fb_mmap = ufx_ops_mmap; | ||
1176 | } | ||
1177 | |||
1178 | pr_debug("released /dev/fb%d user=%d count=%d", | ||
1179 | info->node, user, dev->fb_count); | ||
1180 | |||
1181 | kref_put(&dev->kref, ufx_free); | ||
1182 | |||
1183 | return 0; | ||
1184 | } | ||
1185 | |||
1186 | /* Check whether a video mode is supported by the chip | ||
1187 | * We start from monitor's modes, so don't need to filter that here */ | ||
1188 | static int ufx_is_valid_mode(struct fb_videomode *mode, | ||
1189 | struct fb_info *info) | ||
1190 | { | ||
1191 | if ((mode->xres * mode->yres) > (2048 * 1152)) { | ||
1192 | pr_debug("%dx%d too many pixels", | ||
1193 | mode->xres, mode->yres); | ||
1194 | return 0; | ||
1195 | } | ||
1196 | |||
1197 | if (mode->pixclock < 5000) { | ||
1198 | pr_debug("%dx%d %dps pixel clock too fast", | ||
1199 | mode->xres, mode->yres, mode->pixclock); | ||
1200 | return 0; | ||
1201 | } | ||
1202 | |||
1203 | pr_debug("%dx%d (pixclk %dps %dMHz) valid mode", mode->xres, mode->yres, | ||
1204 | mode->pixclock, (1000000 / mode->pixclock)); | ||
1205 | return 1; | ||
1206 | } | ||
1207 | |||
1208 | static void ufx_var_color_format(struct fb_var_screeninfo *var) | ||
1209 | { | ||
1210 | const struct fb_bitfield red = { 11, 5, 0 }; | ||
1211 | const struct fb_bitfield green = { 5, 6, 0 }; | ||
1212 | const struct fb_bitfield blue = { 0, 5, 0 }; | ||
1213 | |||
1214 | var->bits_per_pixel = 16; | ||
1215 | var->red = red; | ||
1216 | var->green = green; | ||
1217 | var->blue = blue; | ||
1218 | } | ||
1219 | |||
1220 | static int ufx_ops_check_var(struct fb_var_screeninfo *var, | ||
1221 | struct fb_info *info) | ||
1222 | { | ||
1223 | struct fb_videomode mode; | ||
1224 | |||
1225 | /* TODO: support dynamically changing framebuffer size */ | ||
1226 | if ((var->xres * var->yres * 2) > info->fix.smem_len) | ||
1227 | return -EINVAL; | ||
1228 | |||
1229 | /* set device-specific elements of var unrelated to mode */ | ||
1230 | ufx_var_color_format(var); | ||
1231 | |||
1232 | fb_var_to_videomode(&mode, var); | ||
1233 | |||
1234 | if (!ufx_is_valid_mode(&mode, info)) | ||
1235 | return -EINVAL; | ||
1236 | |||
1237 | return 0; | ||
1238 | } | ||
1239 | |||
1240 | static int ufx_ops_set_par(struct fb_info *info) | ||
1241 | { | ||
1242 | struct ufx_data *dev = info->par; | ||
1243 | int result; | ||
1244 | u16 *pix_framebuffer; | ||
1245 | int i; | ||
1246 | |||
1247 | pr_debug("set_par mode %dx%d", info->var.xres, info->var.yres); | ||
1248 | result = ufx_set_vid_mode(dev, &info->var); | ||
1249 | |||
1250 | if ((result == 0) && (dev->fb_count == 0)) { | ||
1251 | /* paint greenscreen */ | ||
1252 | pix_framebuffer = (u16 *) info->screen_base; | ||
1253 | for (i = 0; i < info->fix.smem_len / 2; i++) | ||
1254 | pix_framebuffer[i] = 0x37e6; | ||
1255 | |||
1256 | ufx_handle_damage(dev, 0, 0, info->var.xres, info->var.yres); | ||
1257 | } | ||
1258 | |||
1259 | /* re-enable defio if previously disabled by damage tracking */ | ||
1260 | if (info->fbdefio) | ||
1261 | info->fbdefio->delay = UFX_DEFIO_WRITE_DELAY; | ||
1262 | |||
1263 | return result; | ||
1264 | } | ||
1265 | |||
1266 | /* In order to come back from full DPMS off, we need to set the mode again */ | ||
1267 | static int ufx_ops_blank(int blank_mode, struct fb_info *info) | ||
1268 | { | ||
1269 | struct ufx_data *dev = info->par; | ||
1270 | ufx_set_vid_mode(dev, &info->var); | ||
1271 | return 0; | ||
1272 | } | ||
1273 | |||
1274 | static struct fb_ops ufx_ops = { | ||
1275 | .owner = THIS_MODULE, | ||
1276 | .fb_read = fb_sys_read, | ||
1277 | .fb_write = ufx_ops_write, | ||
1278 | .fb_setcolreg = ufx_ops_setcolreg, | ||
1279 | .fb_fillrect = ufx_ops_fillrect, | ||
1280 | .fb_copyarea = ufx_ops_copyarea, | ||
1281 | .fb_imageblit = ufx_ops_imageblit, | ||
1282 | .fb_mmap = ufx_ops_mmap, | ||
1283 | .fb_ioctl = ufx_ops_ioctl, | ||
1284 | .fb_open = ufx_ops_open, | ||
1285 | .fb_release = ufx_ops_release, | ||
1286 | .fb_blank = ufx_ops_blank, | ||
1287 | .fb_check_var = ufx_ops_check_var, | ||
1288 | .fb_set_par = ufx_ops_set_par, | ||
1289 | }; | ||
1290 | |||
1291 | /* Assumes &info->lock held by caller | ||
1292 | * Assumes no active clients have framebuffer open */ | ||
1293 | static int ufx_realloc_framebuffer(struct ufx_data *dev, struct fb_info *info) | ||
1294 | { | ||
1295 | int retval = -ENOMEM; | ||
1296 | int old_len = info->fix.smem_len; | ||
1297 | int new_len; | ||
1298 | unsigned char *old_fb = info->screen_base; | ||
1299 | unsigned char *new_fb; | ||
1300 | |||
1301 | pr_debug("Reallocating framebuffer. Addresses will change!"); | ||
1302 | |||
1303 | new_len = info->fix.line_length * info->var.yres; | ||
1304 | |||
1305 | if (PAGE_ALIGN(new_len) > old_len) { | ||
1306 | /* | ||
1307 | * Alloc system memory for virtual framebuffer | ||
1308 | */ | ||
1309 | new_fb = vmalloc(new_len); | ||
1310 | if (!new_fb) { | ||
1311 | pr_err("Virtual framebuffer alloc failed"); | ||
1312 | goto error; | ||
1313 | } | ||
1314 | |||
1315 | if (info->screen_base) { | ||
1316 | memcpy(new_fb, old_fb, old_len); | ||
1317 | vfree(info->screen_base); | ||
1318 | } | ||
1319 | |||
1320 | info->screen_base = new_fb; | ||
1321 | info->fix.smem_len = PAGE_ALIGN(new_len); | ||
1322 | info->fix.smem_start = (unsigned long) new_fb; | ||
1323 | info->flags = smscufx_info_flags; | ||
1324 | } | ||
1325 | |||
1326 | retval = 0; | ||
1327 | |||
1328 | error: | ||
1329 | return retval; | ||
1330 | } | ||
1331 | |||
1332 | /* sets up I2C Controller for 100 Kbps, std. speed, 7-bit addr, master, | ||
1333 | * restart enabled, but no start byte, enable controller */ | ||
1334 | static int ufx_i2c_init(struct ufx_data *dev) | ||
1335 | { | ||
1336 | u32 tmp; | ||
1337 | |||
1338 | /* disable the controller before it can be reprogrammed */ | ||
1339 | int status = ufx_reg_write(dev, 0x106C, 0x00); | ||
1340 | check_warn_return(status, "failed to disable I2C"); | ||
1341 | |||
1342 | /* Setup the clock count registers | ||
1343 | * (12+1) = 13 clks @ 2.5 MHz = 5.2 uS */ | ||
1344 | status = ufx_reg_write(dev, 0x1018, 12); | ||
1345 | check_warn_return(status, "error writing 0x1018"); | ||
1346 | |||
1347 | /* (6+8) = 14 clks @ 2.5 MHz = 5.6 uS */ | ||
1348 | status = ufx_reg_write(dev, 0x1014, 6); | ||
1349 | check_warn_return(status, "error writing 0x1014"); | ||
1350 | |||
1351 | status = ufx_reg_read(dev, 0x1000, &tmp); | ||
1352 | check_warn_return(status, "error reading 0x1000"); | ||
1353 | |||
1354 | /* set speed to std mode */ | ||
1355 | tmp &= ~(0x06); | ||
1356 | tmp |= 0x02; | ||
1357 | |||
1358 | /* 7-bit (not 10-bit) addressing */ | ||
1359 | tmp &= ~(0x10); | ||
1360 | |||
1361 | /* enable restart conditions and master mode */ | ||
1362 | tmp |= 0x21; | ||
1363 | |||
1364 | status = ufx_reg_write(dev, 0x1000, tmp); | ||
1365 | check_warn_return(status, "error writing 0x1000"); | ||
1366 | |||
1367 | /* Set normal tx using target address 0 */ | ||
1368 | status = ufx_reg_clear_and_set_bits(dev, 0x1004, 0xC00, 0x000); | ||
1369 | check_warn_return(status, "error setting TX mode bits in 0x1004"); | ||
1370 | |||
1371 | /* Enable the controller */ | ||
1372 | status = ufx_reg_write(dev, 0x106C, 0x01); | ||
1373 | check_warn_return(status, "failed to enable I2C"); | ||
1374 | |||
1375 | return 0; | ||
1376 | } | ||
1377 | |||
1378 | /* sets the I2C port mux and target address */ | ||
1379 | static int ufx_i2c_configure(struct ufx_data *dev) | ||
1380 | { | ||
1381 | int status = ufx_reg_write(dev, 0x106C, 0x00); | ||
1382 | check_warn_return(status, "failed to disable I2C"); | ||
1383 | |||
1384 | status = ufx_reg_write(dev, 0x3010, 0x00000000); | ||
1385 | check_warn_return(status, "failed to write 0x3010"); | ||
1386 | |||
1387 | /* A0h is std for any EDID, right shifted by one */ | ||
1388 | status = ufx_reg_clear_and_set_bits(dev, 0x1004, 0x3FF, (0xA0 >> 1)); | ||
1389 | check_warn_return(status, "failed to set TAR bits in 0x1004"); | ||
1390 | |||
1391 | status = ufx_reg_write(dev, 0x106C, 0x01); | ||
1392 | check_warn_return(status, "failed to enable I2C"); | ||
1393 | |||
1394 | return 0; | ||
1395 | } | ||
1396 | |||
1397 | /* wait for BUSY to clear, with a timeout of 50ms with 10ms sleeps. if no | ||
1398 | * monitor is connected, there is no error except for timeout */ | ||
1399 | static int ufx_i2c_wait_busy(struct ufx_data *dev) | ||
1400 | { | ||
1401 | u32 tmp; | ||
1402 | int i, status; | ||
1403 | |||
1404 | for (i = 0; i < 15; i++) { | ||
1405 | status = ufx_reg_read(dev, 0x1100, &tmp); | ||
1406 | check_warn_return(status, "0x1100 read failed"); | ||
1407 | |||
1408 | /* if BUSY is clear, check for error */ | ||
1409 | if ((tmp & 0x80000000) == 0) { | ||
1410 | if (tmp & 0x20000000) { | ||
1411 | pr_warn("I2C read failed, 0x1100=0x%08x", tmp); | ||
1412 | return -EIO; | ||
1413 | } | ||
1414 | |||
1415 | return 0; | ||
1416 | } | ||
1417 | |||
1418 | /* perform the first 10 retries without delay */ | ||
1419 | if (i >= 10) | ||
1420 | msleep(10); | ||
1421 | } | ||
1422 | |||
1423 | pr_warn("I2C access timed out, resetting I2C hardware"); | ||
1424 | status = ufx_reg_write(dev, 0x1100, 0x40000000); | ||
1425 | check_warn_return(status, "0x1100 write failed"); | ||
1426 | |||
1427 | return -ETIMEDOUT; | ||
1428 | } | ||
1429 | |||
1430 | /* reads a 128-byte EDID block from the currently selected port and TAR */ | ||
1431 | static int ufx_read_edid(struct ufx_data *dev, u8 *edid, int edid_len) | ||
1432 | { | ||
1433 | int i, j, status; | ||
1434 | u32 *edid_u32 = (u32 *)edid; | ||
1435 | |||
1436 | BUG_ON(edid_len != EDID_LENGTH); | ||
1437 | |||
1438 | status = ufx_i2c_configure(dev); | ||
1439 | if (status < 0) { | ||
1440 | pr_err("ufx_i2c_configure failed"); | ||
1441 | return status; | ||
1442 | } | ||
1443 | |||
1444 | memset(edid, 0xff, EDID_LENGTH); | ||
1445 | |||
1446 | /* Read the 128-byte EDID as 2 bursts of 64 bytes */ | ||
1447 | for (i = 0; i < 2; i++) { | ||
1448 | u32 temp = 0x28070000 | (63 << 20) | (((u32)(i * 64)) << 8); | ||
1449 | status = ufx_reg_write(dev, 0x1100, temp); | ||
1450 | check_warn_return(status, "Failed to write 0x1100"); | ||
1451 | |||
1452 | temp |= 0x80000000; | ||
1453 | status = ufx_reg_write(dev, 0x1100, temp); | ||
1454 | check_warn_return(status, "Failed to write 0x1100"); | ||
1455 | |||
1456 | status = ufx_i2c_wait_busy(dev); | ||
1457 | check_warn_return(status, "Timeout waiting for I2C BUSY to clear"); | ||
1458 | |||
1459 | for (j = 0; j < 16; j++) { | ||
1460 | u32 data_reg_addr = 0x1110 + (j * 4); | ||
1461 | status = ufx_reg_read(dev, data_reg_addr, edid_u32++); | ||
1462 | check_warn_return(status, "Error reading i2c data"); | ||
1463 | } | ||
1464 | } | ||
1465 | |||
1466 | /* all FF's in the first 16 bytes indicates nothing is connected */ | ||
1467 | for (i = 0; i < 16; i++) { | ||
1468 | if (edid[i] != 0xFF) { | ||
1469 | pr_debug("edid data read succesfully"); | ||
1470 | return EDID_LENGTH; | ||
1471 | } | ||
1472 | } | ||
1473 | |||
1474 | pr_warn("edid data contains all 0xff"); | ||
1475 | return -ETIMEDOUT; | ||
1476 | } | ||
1477 | |||
1478 | /* 1) use sw default | ||
1479 | * 2) Parse into various fb_info structs | ||
1480 | * 3) Allocate virtual framebuffer memory to back highest res mode | ||
1481 | * | ||
1482 | * Parses EDID into three places used by various parts of fbdev: | ||
1483 | * fb_var_screeninfo contains the timing of the monitor's preferred mode | ||
1484 | * fb_info.monspecs is full parsed EDID info, including monspecs.modedb | ||
1485 | * fb_info.modelist is a linked list of all monitor & VESA modes which work | ||
1486 | * | ||
1487 | * If EDID is not readable/valid, then modelist is all VESA modes, | ||
1488 | * monspecs is NULL, and fb_var_screeninfo is set to safe VESA mode | ||
1489 | * Returns 0 if successful */ | ||
1490 | static int ufx_setup_modes(struct ufx_data *dev, struct fb_info *info, | ||
1491 | char *default_edid, size_t default_edid_size) | ||
1492 | { | ||
1493 | const struct fb_videomode *default_vmode = NULL; | ||
1494 | u8 *edid; | ||
1495 | int i, result = 0, tries = 3; | ||
1496 | |||
1497 | if (info->dev) /* only use mutex if info has been registered */ | ||
1498 | mutex_lock(&info->lock); | ||
1499 | |||
1500 | edid = kmalloc(EDID_LENGTH, GFP_KERNEL); | ||
1501 | if (!edid) { | ||
1502 | result = -ENOMEM; | ||
1503 | goto error; | ||
1504 | } | ||
1505 | |||
1506 | fb_destroy_modelist(&info->modelist); | ||
1507 | memset(&info->monspecs, 0, sizeof(info->monspecs)); | ||
1508 | |||
1509 | /* Try to (re)read EDID from hardware first | ||
1510 | * EDID data may return, but not parse as valid | ||
1511 | * Try again a few times, in case of e.g. analog cable noise */ | ||
1512 | while (tries--) { | ||
1513 | i = ufx_read_edid(dev, edid, EDID_LENGTH); | ||
1514 | |||
1515 | if (i >= EDID_LENGTH) | ||
1516 | fb_edid_to_monspecs(edid, &info->monspecs); | ||
1517 | |||
1518 | if (info->monspecs.modedb_len > 0) { | ||
1519 | dev->edid = edid; | ||
1520 | dev->edid_size = i; | ||
1521 | break; | ||
1522 | } | ||
1523 | } | ||
1524 | |||
1525 | /* If that fails, use a previously returned EDID if available */ | ||
1526 | if (info->monspecs.modedb_len == 0) { | ||
1527 | pr_err("Unable to get valid EDID from device/display\n"); | ||
1528 | |||
1529 | if (dev->edid) { | ||
1530 | fb_edid_to_monspecs(dev->edid, &info->monspecs); | ||
1531 | if (info->monspecs.modedb_len > 0) | ||
1532 | pr_err("Using previously queried EDID\n"); | ||
1533 | } | ||
1534 | } | ||
1535 | |||
1536 | /* If that fails, use the default EDID we were handed */ | ||
1537 | if (info->monspecs.modedb_len == 0) { | ||
1538 | if (default_edid_size >= EDID_LENGTH) { | ||
1539 | fb_edid_to_monspecs(default_edid, &info->monspecs); | ||
1540 | if (info->monspecs.modedb_len > 0) { | ||
1541 | memcpy(edid, default_edid, default_edid_size); | ||
1542 | dev->edid = edid; | ||
1543 | dev->edid_size = default_edid_size; | ||
1544 | pr_err("Using default/backup EDID\n"); | ||
1545 | } | ||
1546 | } | ||
1547 | } | ||
1548 | |||
1549 | /* If we've got modes, let's pick a best default mode */ | ||
1550 | if (info->monspecs.modedb_len > 0) { | ||
1551 | |||
1552 | for (i = 0; i < info->monspecs.modedb_len; i++) { | ||
1553 | if (ufx_is_valid_mode(&info->monspecs.modedb[i], info)) | ||
1554 | fb_add_videomode(&info->monspecs.modedb[i], | ||
1555 | &info->modelist); | ||
1556 | else /* if we've removed top/best mode */ | ||
1557 | info->monspecs.misc &= ~FB_MISC_1ST_DETAIL; | ||
1558 | } | ||
1559 | |||
1560 | default_vmode = fb_find_best_display(&info->monspecs, | ||
1561 | &info->modelist); | ||
1562 | } | ||
1563 | |||
1564 | /* If everything else has failed, fall back to safe default mode */ | ||
1565 | if (default_vmode == NULL) { | ||
1566 | |||
1567 | struct fb_videomode fb_vmode = {0}; | ||
1568 | |||
1569 | /* Add the standard VESA modes to our modelist | ||
1570 | * Since we don't have EDID, there may be modes that | ||
1571 | * overspec monitor and/or are incorrect aspect ratio, etc. | ||
1572 | * But at least the user has a chance to choose | ||
1573 | */ | ||
1574 | for (i = 0; i < VESA_MODEDB_SIZE; i++) { | ||
1575 | if (ufx_is_valid_mode((struct fb_videomode *) | ||
1576 | &vesa_modes[i], info)) | ||
1577 | fb_add_videomode(&vesa_modes[i], | ||
1578 | &info->modelist); | ||
1579 | } | ||
1580 | |||
1581 | /* default to resolution safe for projectors | ||
1582 | * (since they are most common case without EDID) | ||
1583 | */ | ||
1584 | fb_vmode.xres = 800; | ||
1585 | fb_vmode.yres = 600; | ||
1586 | fb_vmode.refresh = 60; | ||
1587 | default_vmode = fb_find_nearest_mode(&fb_vmode, | ||
1588 | &info->modelist); | ||
1589 | } | ||
1590 | |||
1591 | /* If we have good mode and no active clients */ | ||
1592 | if ((default_vmode != NULL) && (dev->fb_count == 0)) { | ||
1593 | |||
1594 | fb_videomode_to_var(&info->var, default_vmode); | ||
1595 | ufx_var_color_format(&info->var); | ||
1596 | |||
1597 | /* with mode size info, we can now alloc our framebuffer */ | ||
1598 | memcpy(&info->fix, &ufx_fix, sizeof(ufx_fix)); | ||
1599 | info->fix.line_length = info->var.xres * | ||
1600 | (info->var.bits_per_pixel / 8); | ||
1601 | |||
1602 | result = ufx_realloc_framebuffer(dev, info); | ||
1603 | |||
1604 | } else | ||
1605 | result = -EINVAL; | ||
1606 | |||
1607 | error: | ||
1608 | if (edid && (dev->edid != edid)) | ||
1609 | kfree(edid); | ||
1610 | |||
1611 | if (info->dev) | ||
1612 | mutex_unlock(&info->lock); | ||
1613 | |||
1614 | return result; | ||
1615 | } | ||
1616 | |||
1617 | static int ufx_usb_probe(struct usb_interface *interface, | ||
1618 | const struct usb_device_id *id) | ||
1619 | { | ||
1620 | struct usb_device *usbdev; | ||
1621 | struct ufx_data *dev; | ||
1622 | struct fb_info *info = 0; | ||
1623 | int retval = -ENOMEM; | ||
1624 | u32 id_rev, fpga_rev; | ||
1625 | |||
1626 | /* usb initialization */ | ||
1627 | usbdev = interface_to_usbdev(interface); | ||
1628 | BUG_ON(!usbdev); | ||
1629 | |||
1630 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); | ||
1631 | if (dev == NULL) { | ||
1632 | dev_err(&usbdev->dev, "ufx_usb_probe: failed alloc of dev struct\n"); | ||
1633 | goto error; | ||
1634 | } | ||
1635 | |||
1636 | /* we need to wait for both usb and fbdev to spin down on disconnect */ | ||
1637 | kref_init(&dev->kref); /* matching kref_put in usb .disconnect fn */ | ||
1638 | kref_get(&dev->kref); /* matching kref_put in free_framebuffer_work */ | ||
1639 | |||
1640 | dev->udev = usbdev; | ||
1641 | dev->gdev = &usbdev->dev; /* our generic struct device * */ | ||
1642 | usb_set_intfdata(interface, dev); | ||
1643 | |||
1644 | dev_dbg(dev->gdev, "%s %s - serial #%s\n", | ||
1645 | usbdev->manufacturer, usbdev->product, usbdev->serial); | ||
1646 | dev_dbg(dev->gdev, "vid_%04x&pid_%04x&rev_%04x driver's ufx_data struct at %p\n", | ||
1647 | usbdev->descriptor.idVendor, usbdev->descriptor.idProduct, | ||
1648 | usbdev->descriptor.bcdDevice, dev); | ||
1649 | dev_dbg(dev->gdev, "console enable=%d\n", console); | ||
1650 | dev_dbg(dev->gdev, "fb_defio enable=%d\n", fb_defio); | ||
1651 | |||
1652 | if (!ufx_alloc_urb_list(dev, WRITES_IN_FLIGHT, MAX_TRANSFER)) { | ||
1653 | retval = -ENOMEM; | ||
1654 | dev_err(dev->gdev, "ufx_alloc_urb_list failed\n"); | ||
1655 | goto error; | ||
1656 | } | ||
1657 | |||
1658 | /* We don't register a new USB class. Our client interface is fbdev */ | ||
1659 | |||
1660 | /* allocates framebuffer driver structure, not framebuffer memory */ | ||
1661 | info = framebuffer_alloc(0, &usbdev->dev); | ||
1662 | if (!info) { | ||
1663 | retval = -ENOMEM; | ||
1664 | dev_err(dev->gdev, "framebuffer_alloc failed\n"); | ||
1665 | goto error; | ||
1666 | } | ||
1667 | |||
1668 | dev->info = info; | ||
1669 | info->par = dev; | ||
1670 | info->pseudo_palette = dev->pseudo_palette; | ||
1671 | info->fbops = &ufx_ops; | ||
1672 | |||
1673 | retval = fb_alloc_cmap(&info->cmap, 256, 0); | ||
1674 | if (retval < 0) { | ||
1675 | dev_err(dev->gdev, "fb_alloc_cmap failed %x\n", retval); | ||
1676 | goto error; | ||
1677 | } | ||
1678 | |||
1679 | INIT_DELAYED_WORK(&dev->free_framebuffer_work, | ||
1680 | ufx_free_framebuffer_work); | ||
1681 | |||
1682 | INIT_LIST_HEAD(&info->modelist); | ||
1683 | |||
1684 | retval = ufx_reg_read(dev, 0x3000, &id_rev); | ||
1685 | check_warn_goto_error(retval, "error %d reading 0x3000 register from device", retval); | ||
1686 | dev_dbg(dev->gdev, "ID_REV register value 0x%08x", id_rev); | ||
1687 | |||
1688 | retval = ufx_reg_read(dev, 0x3004, &fpga_rev); | ||
1689 | check_warn_goto_error(retval, "error %d reading 0x3004 register from device", retval); | ||
1690 | dev_dbg(dev->gdev, "FPGA_REV register value 0x%08x", fpga_rev); | ||
1691 | |||
1692 | dev_dbg(dev->gdev, "resetting device"); | ||
1693 | retval = ufx_lite_reset(dev); | ||
1694 | check_warn_goto_error(retval, "error %d resetting device", retval); | ||
1695 | |||
1696 | dev_dbg(dev->gdev, "configuring system clock"); | ||
1697 | retval = ufx_config_sys_clk(dev); | ||
1698 | check_warn_goto_error(retval, "error %d configuring system clock", retval); | ||
1699 | |||
1700 | dev_dbg(dev->gdev, "configuring DDR2 controller"); | ||
1701 | retval = ufx_config_ddr2(dev); | ||
1702 | check_warn_goto_error(retval, "error %d initialising DDR2 controller", retval); | ||
1703 | |||
1704 | dev_dbg(dev->gdev, "configuring I2C controller"); | ||
1705 | retval = ufx_i2c_init(dev); | ||
1706 | check_warn_goto_error(retval, "error %d initialising I2C controller", retval); | ||
1707 | |||
1708 | dev_dbg(dev->gdev, "selecting display mode"); | ||
1709 | retval = ufx_setup_modes(dev, info, NULL, 0); | ||
1710 | check_warn_goto_error(retval, "unable to find common mode for display and adapter"); | ||
1711 | |||
1712 | retval = ufx_reg_set_bits(dev, 0x4000, 0x00000001); | ||
1713 | check_warn_goto_error(retval, "error %d enabling graphics engine", retval); | ||
1714 | |||
1715 | /* ready to begin using device */ | ||
1716 | atomic_set(&dev->usb_active, 1); | ||
1717 | |||
1718 | dev_dbg(dev->gdev, "checking var"); | ||
1719 | retval = ufx_ops_check_var(&info->var, info); | ||
1720 | check_warn_goto_error(retval, "error %d ufx_ops_check_var", retval); | ||
1721 | |||
1722 | dev_dbg(dev->gdev, "setting par"); | ||
1723 | retval = ufx_ops_set_par(info); | ||
1724 | check_warn_goto_error(retval, "error %d ufx_ops_set_par", retval); | ||
1725 | |||
1726 | dev_dbg(dev->gdev, "registering framebuffer"); | ||
1727 | retval = register_framebuffer(info); | ||
1728 | check_warn_goto_error(retval, "error %d register_framebuffer", retval); | ||
1729 | |||
1730 | dev_info(dev->gdev, "SMSC UDX USB device /dev/fb%d attached. %dx%d resolution." | ||
1731 | " Using %dK framebuffer memory\n", info->node, | ||
1732 | info->var.xres, info->var.yres, info->fix.smem_len >> 10); | ||
1733 | |||
1734 | return 0; | ||
1735 | |||
1736 | error: | ||
1737 | if (dev) { | ||
1738 | if (info) { | ||
1739 | if (info->cmap.len != 0) | ||
1740 | fb_dealloc_cmap(&info->cmap); | ||
1741 | if (info->monspecs.modedb) | ||
1742 | fb_destroy_modedb(info->monspecs.modedb); | ||
1743 | if (info->screen_base) | ||
1744 | vfree(info->screen_base); | ||
1745 | |||
1746 | fb_destroy_modelist(&info->modelist); | ||
1747 | |||
1748 | framebuffer_release(info); | ||
1749 | } | ||
1750 | |||
1751 | kref_put(&dev->kref, ufx_free); /* ref for framebuffer */ | ||
1752 | kref_put(&dev->kref, ufx_free); /* last ref from kref_init */ | ||
1753 | |||
1754 | /* dev has been deallocated. Do not dereference */ | ||
1755 | } | ||
1756 | |||
1757 | return retval; | ||
1758 | } | ||
1759 | |||
1760 | static void ufx_usb_disconnect(struct usb_interface *interface) | ||
1761 | { | ||
1762 | struct ufx_data *dev; | ||
1763 | struct fb_info *info; | ||
1764 | |||
1765 | dev = usb_get_intfdata(interface); | ||
1766 | info = dev->info; | ||
1767 | |||
1768 | pr_debug("USB disconnect starting\n"); | ||
1769 | |||
1770 | /* we virtualize until all fb clients release. Then we free */ | ||
1771 | dev->virtualized = true; | ||
1772 | |||
1773 | /* When non-active we'll update virtual framebuffer, but no new urbs */ | ||
1774 | atomic_set(&dev->usb_active, 0); | ||
1775 | |||
1776 | usb_set_intfdata(interface, NULL); | ||
1777 | |||
1778 | /* if clients still have us open, will be freed on last close */ | ||
1779 | if (dev->fb_count == 0) | ||
1780 | schedule_delayed_work(&dev->free_framebuffer_work, 0); | ||
1781 | |||
1782 | /* release reference taken by kref_init in probe() */ | ||
1783 | kref_put(&dev->kref, ufx_free); | ||
1784 | |||
1785 | /* consider ufx_data freed */ | ||
1786 | } | ||
1787 | |||
1788 | static struct usb_driver ufx_driver = { | ||
1789 | .name = "smscufx", | ||
1790 | .probe = ufx_usb_probe, | ||
1791 | .disconnect = ufx_usb_disconnect, | ||
1792 | .id_table = id_table, | ||
1793 | }; | ||
1794 | |||
1795 | static int __init ufx_module_init(void) | ||
1796 | { | ||
1797 | int res; | ||
1798 | |||
1799 | res = usb_register(&ufx_driver); | ||
1800 | if (res) | ||
1801 | err("usb_register failed. Error number %d", res); | ||
1802 | |||
1803 | return res; | ||
1804 | } | ||
1805 | |||
1806 | static void __exit ufx_module_exit(void) | ||
1807 | { | ||
1808 | usb_deregister(&ufx_driver); | ||
1809 | } | ||
1810 | |||
1811 | module_init(ufx_module_init); | ||
1812 | module_exit(ufx_module_exit); | ||
1813 | |||
1814 | static void ufx_urb_completion(struct urb *urb) | ||
1815 | { | ||
1816 | struct urb_node *unode = urb->context; | ||
1817 | struct ufx_data *dev = unode->dev; | ||
1818 | unsigned long flags; | ||
1819 | |||
1820 | /* sync/async unlink faults aren't errors */ | ||
1821 | if (urb->status) { | ||
1822 | if (!(urb->status == -ENOENT || | ||
1823 | urb->status == -ECONNRESET || | ||
1824 | urb->status == -ESHUTDOWN)) { | ||
1825 | pr_err("%s - nonzero write bulk status received: %d\n", | ||
1826 | __func__, urb->status); | ||
1827 | atomic_set(&dev->lost_pixels, 1); | ||
1828 | } | ||
1829 | } | ||
1830 | |||
1831 | urb->transfer_buffer_length = dev->urbs.size; /* reset to actual */ | ||
1832 | |||
1833 | spin_lock_irqsave(&dev->urbs.lock, flags); | ||
1834 | list_add_tail(&unode->entry, &dev->urbs.list); | ||
1835 | dev->urbs.available++; | ||
1836 | spin_unlock_irqrestore(&dev->urbs.lock, flags); | ||
1837 | |||
1838 | /* When using fb_defio, we deadlock if up() is called | ||
1839 | * while another is waiting. So queue to another process */ | ||
1840 | if (fb_defio) | ||
1841 | schedule_delayed_work(&unode->release_urb_work, 0); | ||
1842 | else | ||
1843 | up(&dev->urbs.limit_sem); | ||
1844 | } | ||
1845 | |||
1846 | static void ufx_free_urb_list(struct ufx_data *dev) | ||
1847 | { | ||
1848 | int count = dev->urbs.count; | ||
1849 | struct list_head *node; | ||
1850 | struct urb_node *unode; | ||
1851 | struct urb *urb; | ||
1852 | int ret; | ||
1853 | unsigned long flags; | ||
1854 | |||
1855 | pr_debug("Waiting for completes and freeing all render urbs\n"); | ||
1856 | |||
1857 | /* keep waiting and freeing, until we've got 'em all */ | ||
1858 | while (count--) { | ||
1859 | /* Getting interrupted means a leak, but ok at shutdown*/ | ||
1860 | ret = down_interruptible(&dev->urbs.limit_sem); | ||
1861 | if (ret) | ||
1862 | break; | ||
1863 | |||
1864 | spin_lock_irqsave(&dev->urbs.lock, flags); | ||
1865 | |||
1866 | node = dev->urbs.list.next; /* have reserved one with sem */ | ||
1867 | list_del_init(node); | ||
1868 | |||
1869 | spin_unlock_irqrestore(&dev->urbs.lock, flags); | ||
1870 | |||
1871 | unode = list_entry(node, struct urb_node, entry); | ||
1872 | urb = unode->urb; | ||
1873 | |||
1874 | /* Free each separately allocated piece */ | ||
1875 | usb_free_coherent(urb->dev, dev->urbs.size, | ||
1876 | urb->transfer_buffer, urb->transfer_dma); | ||
1877 | usb_free_urb(urb); | ||
1878 | kfree(node); | ||
1879 | } | ||
1880 | } | ||
1881 | |||
1882 | static int ufx_alloc_urb_list(struct ufx_data *dev, int count, size_t size) | ||
1883 | { | ||
1884 | int i = 0; | ||
1885 | struct urb *urb; | ||
1886 | struct urb_node *unode; | ||
1887 | char *buf; | ||
1888 | |||
1889 | spin_lock_init(&dev->urbs.lock); | ||
1890 | |||
1891 | dev->urbs.size = size; | ||
1892 | INIT_LIST_HEAD(&dev->urbs.list); | ||
1893 | |||
1894 | while (i < count) { | ||
1895 | unode = kzalloc(sizeof(struct urb_node), GFP_KERNEL); | ||
1896 | if (!unode) | ||
1897 | break; | ||
1898 | unode->dev = dev; | ||
1899 | |||
1900 | INIT_DELAYED_WORK(&unode->release_urb_work, | ||
1901 | ufx_release_urb_work); | ||
1902 | |||
1903 | urb = usb_alloc_urb(0, GFP_KERNEL); | ||
1904 | if (!urb) { | ||
1905 | kfree(unode); | ||
1906 | break; | ||
1907 | } | ||
1908 | unode->urb = urb; | ||
1909 | |||
1910 | buf = usb_alloc_coherent(dev->udev, size, GFP_KERNEL, | ||
1911 | &urb->transfer_dma); | ||
1912 | if (!buf) { | ||
1913 | kfree(unode); | ||
1914 | usb_free_urb(urb); | ||
1915 | break; | ||
1916 | } | ||
1917 | |||
1918 | /* urb->transfer_buffer_length set to actual before submit */ | ||
1919 | usb_fill_bulk_urb(urb, dev->udev, usb_sndbulkpipe(dev->udev, 1), | ||
1920 | buf, size, ufx_urb_completion, unode); | ||
1921 | urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | ||
1922 | |||
1923 | list_add_tail(&unode->entry, &dev->urbs.list); | ||
1924 | |||
1925 | i++; | ||
1926 | } | ||
1927 | |||
1928 | sema_init(&dev->urbs.limit_sem, i); | ||
1929 | dev->urbs.count = i; | ||
1930 | dev->urbs.available = i; | ||
1931 | |||
1932 | pr_debug("allocated %d %d byte urbs\n", i, (int) size); | ||
1933 | |||
1934 | return i; | ||
1935 | } | ||
1936 | |||
1937 | static struct urb *ufx_get_urb(struct ufx_data *dev) | ||
1938 | { | ||
1939 | int ret = 0; | ||
1940 | struct list_head *entry; | ||
1941 | struct urb_node *unode; | ||
1942 | struct urb *urb = NULL; | ||
1943 | unsigned long flags; | ||
1944 | |||
1945 | /* Wait for an in-flight buffer to complete and get re-queued */ | ||
1946 | ret = down_timeout(&dev->urbs.limit_sem, GET_URB_TIMEOUT); | ||
1947 | if (ret) { | ||
1948 | atomic_set(&dev->lost_pixels, 1); | ||
1949 | pr_warn("wait for urb interrupted: %x available: %d\n", | ||
1950 | ret, dev->urbs.available); | ||
1951 | goto error; | ||
1952 | } | ||
1953 | |||
1954 | spin_lock_irqsave(&dev->urbs.lock, flags); | ||
1955 | |||
1956 | BUG_ON(list_empty(&dev->urbs.list)); /* reserved one with limit_sem */ | ||
1957 | entry = dev->urbs.list.next; | ||
1958 | list_del_init(entry); | ||
1959 | dev->urbs.available--; | ||
1960 | |||
1961 | spin_unlock_irqrestore(&dev->urbs.lock, flags); | ||
1962 | |||
1963 | unode = list_entry(entry, struct urb_node, entry); | ||
1964 | urb = unode->urb; | ||
1965 | |||
1966 | error: | ||
1967 | return urb; | ||
1968 | } | ||
1969 | |||
1970 | static int ufx_submit_urb(struct ufx_data *dev, struct urb *urb, size_t len) | ||
1971 | { | ||
1972 | int ret; | ||
1973 | |||
1974 | BUG_ON(len > dev->urbs.size); | ||
1975 | |||
1976 | urb->transfer_buffer_length = len; /* set to actual payload len */ | ||
1977 | ret = usb_submit_urb(urb, GFP_KERNEL); | ||
1978 | if (ret) { | ||
1979 | ufx_urb_completion(urb); /* because no one else will */ | ||
1980 | atomic_set(&dev->lost_pixels, 1); | ||
1981 | pr_err("usb_submit_urb error %x\n", ret); | ||
1982 | } | ||
1983 | return ret; | ||
1984 | } | ||
1985 | |||
1986 | module_param(console, bool, S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP); | ||
1987 | MODULE_PARM_DESC(console, "Allow fbcon to be used on this display"); | ||
1988 | |||
1989 | module_param(fb_defio, bool, S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP); | ||
1990 | MODULE_PARM_DESC(fb_defio, "Enable fb_defio mmap support"); | ||
1991 | |||
1992 | MODULE_AUTHOR("Steve Glendinning <steve.glendinning@smsc.com>"); | ||
1993 | MODULE_DESCRIPTION("SMSC UFX kernel framebuffer driver"); | ||
1994 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/video/tmiofb.c b/drivers/video/tmiofb.c index cd1c4dcef8fd..8e4a446b5ed1 100644 --- a/drivers/video/tmiofb.c +++ b/drivers/video/tmiofb.c | |||
@@ -744,7 +744,7 @@ static int __devinit tmiofb_probe(struct platform_device *dev) | |||
744 | goto err_ioremap_vram; | 744 | goto err_ioremap_vram; |
745 | } | 745 | } |
746 | 746 | ||
747 | retval = request_irq(irq, &tmiofb_irq, IRQF_DISABLED, | 747 | retval = request_irq(irq, &tmiofb_irq, 0, |
748 | dev_name(&dev->dev), info); | 748 | dev_name(&dev->dev), info); |
749 | 749 | ||
750 | if (retval) | 750 | if (retval) |
diff --git a/drivers/video/tridentfb.c b/drivers/video/tridentfb.c index c6c77562839d..34cf019bba44 100644 --- a/drivers/video/tridentfb.c +++ b/drivers/video/tridentfb.c | |||
@@ -987,8 +987,8 @@ static int tridentfb_pan_display(struct fb_var_screeninfo *var, | |||
987 | unsigned int offset; | 987 | unsigned int offset; |
988 | 988 | ||
989 | debug("enter\n"); | 989 | debug("enter\n"); |
990 | offset = (var->xoffset + (var->yoffset * var->xres_virtual)) | 990 | offset = (var->xoffset + (var->yoffset * info->var.xres_virtual)) |
991 | * var->bits_per_pixel / 32; | 991 | * info->var.bits_per_pixel / 32; |
992 | set_screen_start(par, offset); | 992 | set_screen_start(par, offset); |
993 | debug("exit\n"); | 993 | debug("exit\n"); |
994 | return 0; | 994 | return 0; |
diff --git a/drivers/video/udlfb.c b/drivers/video/udlfb.c index 087fc9960bb9..3473e75ce785 100644 --- a/drivers/video/udlfb.c +++ b/drivers/video/udlfb.c | |||
@@ -48,20 +48,30 @@ static const u32 udlfb_info_flags = FBINFO_DEFAULT | FBINFO_READS_FAST | | |||
48 | FBINFO_HWACCEL_COPYAREA | FBINFO_MISC_ALWAYS_SETPAR; | 48 | FBINFO_HWACCEL_COPYAREA | FBINFO_MISC_ALWAYS_SETPAR; |
49 | 49 | ||
50 | /* | 50 | /* |
51 | * There are many DisplayLink-based products, all with unique PIDs. We are able | 51 | * There are many DisplayLink-based graphics products, all with unique PIDs. |
52 | * to support all volume ones (circa 2009) with a single driver, so we match | 52 | * So we match on DisplayLink's VID + Vendor-Defined Interface Class (0xff) |
53 | * globally on VID. TODO: Probe() needs to detect when we might be running | 53 | * We also require a match on SubClass (0x00) and Protocol (0x00), |
54 | * "future" chips, and bail on those, so a compatible driver can match. | 54 | * which is compatible with all known USB 2.0 era graphics chips and firmware, |
55 | * but allows DisplayLink to increment those for any future incompatible chips | ||
55 | */ | 56 | */ |
56 | static struct usb_device_id id_table[] = { | 57 | static struct usb_device_id id_table[] = { |
57 | {.idVendor = 0x17e9, .match_flags = USB_DEVICE_ID_MATCH_VENDOR,}, | 58 | {.idVendor = 0x17e9, |
59 | .bInterfaceClass = 0xff, | ||
60 | .bInterfaceSubClass = 0x00, | ||
61 | .bInterfaceProtocol = 0x00, | ||
62 | .match_flags = USB_DEVICE_ID_MATCH_VENDOR | | ||
63 | USB_DEVICE_ID_MATCH_INT_CLASS | | ||
64 | USB_DEVICE_ID_MATCH_INT_SUBCLASS | | ||
65 | USB_DEVICE_ID_MATCH_INT_PROTOCOL, | ||
66 | }, | ||
58 | {}, | 67 | {}, |
59 | }; | 68 | }; |
60 | MODULE_DEVICE_TABLE(usb, id_table); | 69 | MODULE_DEVICE_TABLE(usb, id_table); |
61 | 70 | ||
62 | /* module options */ | 71 | /* module options */ |
63 | static int console; /* Optionally allow fbcon to consume first framebuffer */ | 72 | static int console = 1; /* Allow fbcon to open framebuffer */ |
64 | static int fb_defio; /* Optionally enable experimental fb_defio mmap support */ | 73 | static int fb_defio = 1; /* Detect mmap writes using page faults */ |
74 | static int shadow = 1; /* Optionally disable shadow framebuffer */ | ||
65 | 75 | ||
66 | /* dlfb keeps a list of urbs for efficient bulk transfers */ | 76 | /* dlfb keeps a list of urbs for efficient bulk transfers */ |
67 | static void dlfb_urb_completion(struct urb *urb); | 77 | static void dlfb_urb_completion(struct urb *urb); |
@@ -94,17 +104,39 @@ static char *dlfb_vidreg_unlock(char *buf) | |||
94 | } | 104 | } |
95 | 105 | ||
96 | /* | 106 | /* |
97 | * On/Off for driving the DisplayLink framebuffer to the display | 107 | * Map FB_BLANK_* to DisplayLink register |
98 | * 0x00 H and V sync on | 108 | * DLReg FB_BLANK_* |
99 | * 0x01 H and V sync off (screen blank but powered) | 109 | * ----- ----------------------------- |
100 | * 0x07 DPMS powerdown (requires modeset to come back) | 110 | * 0x00 FB_BLANK_UNBLANK (0) |
111 | * 0x01 FB_BLANK (1) | ||
112 | * 0x03 FB_BLANK_VSYNC_SUSPEND (2) | ||
113 | * 0x05 FB_BLANK_HSYNC_SUSPEND (3) | ||
114 | * 0x07 FB_BLANK_POWERDOWN (4) Note: requires modeset to come back | ||
101 | */ | 115 | */ |
102 | static char *dlfb_enable_hvsync(char *buf, bool enable) | 116 | static char *dlfb_blanking(char *buf, int fb_blank) |
103 | { | 117 | { |
104 | if (enable) | 118 | u8 reg; |
105 | return dlfb_set_register(buf, 0x1F, 0x00); | 119 | |
106 | else | 120 | switch (fb_blank) { |
107 | return dlfb_set_register(buf, 0x1F, 0x07); | 121 | case FB_BLANK_POWERDOWN: |
122 | reg = 0x07; | ||
123 | break; | ||
124 | case FB_BLANK_HSYNC_SUSPEND: | ||
125 | reg = 0x05; | ||
126 | break; | ||
127 | case FB_BLANK_VSYNC_SUSPEND: | ||
128 | reg = 0x03; | ||
129 | break; | ||
130 | case FB_BLANK_NORMAL: | ||
131 | reg = 0x01; | ||
132 | break; | ||
133 | default: | ||
134 | reg = 0x00; | ||
135 | } | ||
136 | |||
137 | buf = dlfb_set_register(buf, 0x1F, reg); | ||
138 | |||
139 | return buf; | ||
108 | } | 140 | } |
109 | 141 | ||
110 | static char *dlfb_set_color_depth(char *buf, u8 selection) | 142 | static char *dlfb_set_color_depth(char *buf, u8 selection) |
@@ -272,13 +304,15 @@ static int dlfb_set_video_mode(struct dlfb_data *dev, | |||
272 | wrptr = dlfb_set_base8bpp(wrptr, dev->info->fix.smem_len); | 304 | wrptr = dlfb_set_base8bpp(wrptr, dev->info->fix.smem_len); |
273 | 305 | ||
274 | wrptr = dlfb_set_vid_cmds(wrptr, var); | 306 | wrptr = dlfb_set_vid_cmds(wrptr, var); |
275 | wrptr = dlfb_enable_hvsync(wrptr, true); | 307 | wrptr = dlfb_blanking(wrptr, FB_BLANK_UNBLANK); |
276 | wrptr = dlfb_vidreg_unlock(wrptr); | 308 | wrptr = dlfb_vidreg_unlock(wrptr); |
277 | 309 | ||
278 | writesize = wrptr - buf; | 310 | writesize = wrptr - buf; |
279 | 311 | ||
280 | retval = dlfb_submit_urb(dev, urb, writesize); | 312 | retval = dlfb_submit_urb(dev, urb, writesize); |
281 | 313 | ||
314 | dev->blank_mode = FB_BLANK_UNBLANK; | ||
315 | |||
282 | return retval; | 316 | return retval; |
283 | } | 317 | } |
284 | 318 | ||
@@ -752,14 +786,13 @@ static int dlfb_ops_ioctl(struct fb_info *info, unsigned int cmd, | |||
752 | { | 786 | { |
753 | 787 | ||
754 | struct dlfb_data *dev = info->par; | 788 | struct dlfb_data *dev = info->par; |
755 | struct dloarea *area = NULL; | ||
756 | 789 | ||
757 | if (!atomic_read(&dev->usb_active)) | 790 | if (!atomic_read(&dev->usb_active)) |
758 | return 0; | 791 | return 0; |
759 | 792 | ||
760 | /* TODO: Update X server to get this from sysfs instead */ | 793 | /* TODO: Update X server to get this from sysfs instead */ |
761 | if (cmd == DLFB_IOCTL_RETURN_EDID) { | 794 | if (cmd == DLFB_IOCTL_RETURN_EDID) { |
762 | char *edid = (char *)arg; | 795 | void __user *edid = (void __user *)arg; |
763 | if (copy_to_user(edid, dev->edid, dev->edid_size)) | 796 | if (copy_to_user(edid, dev->edid, dev->edid_size)) |
764 | return -EFAULT; | 797 | return -EFAULT; |
765 | return 0; | 798 | return 0; |
@@ -767,6 +800,11 @@ static int dlfb_ops_ioctl(struct fb_info *info, unsigned int cmd, | |||
767 | 800 | ||
768 | /* TODO: Help propose a standard fb.h ioctl to report mmap damage */ | 801 | /* TODO: Help propose a standard fb.h ioctl to report mmap damage */ |
769 | if (cmd == DLFB_IOCTL_REPORT_DAMAGE) { | 802 | if (cmd == DLFB_IOCTL_REPORT_DAMAGE) { |
803 | struct dloarea area; | ||
804 | |||
805 | if (copy_from_user(&area, (void __user *)arg, | ||
806 | sizeof(struct dloarea))) | ||
807 | return -EFAULT; | ||
770 | 808 | ||
771 | /* | 809 | /* |
772 | * If we have a damage-aware client, turn fb_defio "off" | 810 | * If we have a damage-aware client, turn fb_defio "off" |
@@ -778,21 +816,19 @@ static int dlfb_ops_ioctl(struct fb_info *info, unsigned int cmd, | |||
778 | if (info->fbdefio) | 816 | if (info->fbdefio) |
779 | info->fbdefio->delay = DL_DEFIO_WRITE_DISABLE; | 817 | info->fbdefio->delay = DL_DEFIO_WRITE_DISABLE; |
780 | 818 | ||
781 | area = (struct dloarea *)arg; | 819 | if (area.x < 0) |
820 | area.x = 0; | ||
782 | 821 | ||
783 | if (area->x < 0) | 822 | if (area.x > info->var.xres) |
784 | area->x = 0; | 823 | area.x = info->var.xres; |
785 | 824 | ||
786 | if (area->x > info->var.xres) | 825 | if (area.y < 0) |
787 | area->x = info->var.xres; | 826 | area.y = 0; |
788 | 827 | ||
789 | if (area->y < 0) | 828 | if (area.y > info->var.yres) |
790 | area->y = 0; | 829 | area.y = info->var.yres; |
791 | 830 | ||
792 | if (area->y > info->var.yres) | 831 | dlfb_handle_damage(dev, area.x, area.y, area.w, area.h, |
793 | area->y = info->var.yres; | ||
794 | |||
795 | dlfb_handle_damage(dev, area->x, area->y, area->w, area->h, | ||
796 | info->screen_base); | 832 | info->screen_base); |
797 | } | 833 | } |
798 | 834 | ||
@@ -840,7 +876,7 @@ static int dlfb_ops_open(struct fb_info *info, int user) | |||
840 | * preventing other clients (X) from working properly. Usually | 876 | * preventing other clients (X) from working properly. Usually |
841 | * not what the user wants. Fail by default with option to enable. | 877 | * not what the user wants. Fail by default with option to enable. |
842 | */ | 878 | */ |
843 | if ((user == 0) & (!console)) | 879 | if ((user == 0) && (!console)) |
844 | return -EBUSY; | 880 | return -EBUSY; |
845 | 881 | ||
846 | /* If the USB device is gone, we don't accept new opens */ | 882 | /* If the USB device is gone, we don't accept new opens */ |
@@ -1039,32 +1075,57 @@ static int dlfb_ops_set_par(struct fb_info *info) | |||
1039 | return result; | 1075 | return result; |
1040 | } | 1076 | } |
1041 | 1077 | ||
1078 | /* To fonzi the jukebox (e.g. make blanking changes take effect) */ | ||
1079 | static char *dlfb_dummy_render(char *buf) | ||
1080 | { | ||
1081 | *buf++ = 0xAF; | ||
1082 | *buf++ = 0x6A; /* copy */ | ||
1083 | *buf++ = 0x00; /* from address*/ | ||
1084 | *buf++ = 0x00; | ||
1085 | *buf++ = 0x00; | ||
1086 | *buf++ = 0x01; /* one pixel */ | ||
1087 | *buf++ = 0x00; /* to address */ | ||
1088 | *buf++ = 0x00; | ||
1089 | *buf++ = 0x00; | ||
1090 | return buf; | ||
1091 | } | ||
1092 | |||
1042 | /* | 1093 | /* |
1043 | * In order to come back from full DPMS off, we need to set the mode again | 1094 | * In order to come back from full DPMS off, we need to set the mode again |
1044 | */ | 1095 | */ |
1045 | static int dlfb_ops_blank(int blank_mode, struct fb_info *info) | 1096 | static int dlfb_ops_blank(int blank_mode, struct fb_info *info) |
1046 | { | 1097 | { |
1047 | struct dlfb_data *dev = info->par; | 1098 | struct dlfb_data *dev = info->par; |
1099 | char *bufptr; | ||
1100 | struct urb *urb; | ||
1048 | 1101 | ||
1049 | if (blank_mode != FB_BLANK_UNBLANK) { | 1102 | pr_info("/dev/fb%d FB_BLANK mode %d --> %d\n", |
1050 | char *bufptr; | 1103 | info->node, dev->blank_mode, blank_mode); |
1051 | struct urb *urb; | ||
1052 | |||
1053 | urb = dlfb_get_urb(dev); | ||
1054 | if (!urb) | ||
1055 | return 0; | ||
1056 | 1104 | ||
1057 | bufptr = (char *) urb->transfer_buffer; | 1105 | if ((dev->blank_mode == FB_BLANK_POWERDOWN) && |
1058 | bufptr = dlfb_vidreg_lock(bufptr); | 1106 | (blank_mode != FB_BLANK_POWERDOWN)) { |
1059 | bufptr = dlfb_enable_hvsync(bufptr, false); | ||
1060 | bufptr = dlfb_vidreg_unlock(bufptr); | ||
1061 | 1107 | ||
1062 | dlfb_submit_urb(dev, urb, bufptr - | 1108 | /* returning from powerdown requires a fresh modeset */ |
1063 | (char *) urb->transfer_buffer); | ||
1064 | } else { | ||
1065 | dlfb_set_video_mode(dev, &info->var); | 1109 | dlfb_set_video_mode(dev, &info->var); |
1066 | } | 1110 | } |
1067 | 1111 | ||
1112 | urb = dlfb_get_urb(dev); | ||
1113 | if (!urb) | ||
1114 | return 0; | ||
1115 | |||
1116 | bufptr = (char *) urb->transfer_buffer; | ||
1117 | bufptr = dlfb_vidreg_lock(bufptr); | ||
1118 | bufptr = dlfb_blanking(bufptr, blank_mode); | ||
1119 | bufptr = dlfb_vidreg_unlock(bufptr); | ||
1120 | |||
1121 | /* seems like a render op is needed to have blank change take effect */ | ||
1122 | bufptr = dlfb_dummy_render(bufptr); | ||
1123 | |||
1124 | dlfb_submit_urb(dev, urb, bufptr - | ||
1125 | (char *) urb->transfer_buffer); | ||
1126 | |||
1127 | dev->blank_mode = blank_mode; | ||
1128 | |||
1068 | return 0; | 1129 | return 0; |
1069 | } | 1130 | } |
1070 | 1131 | ||
@@ -1097,7 +1158,7 @@ static int dlfb_realloc_framebuffer(struct dlfb_data *dev, struct fb_info *info) | |||
1097 | int new_len; | 1158 | int new_len; |
1098 | unsigned char *old_fb = info->screen_base; | 1159 | unsigned char *old_fb = info->screen_base; |
1099 | unsigned char *new_fb; | 1160 | unsigned char *new_fb; |
1100 | unsigned char *new_back; | 1161 | unsigned char *new_back = 0; |
1101 | 1162 | ||
1102 | pr_warn("Reallocating framebuffer. Addresses will change!\n"); | 1163 | pr_warn("Reallocating framebuffer. Addresses will change!\n"); |
1103 | 1164 | ||
@@ -1129,7 +1190,8 @@ static int dlfb_realloc_framebuffer(struct dlfb_data *dev, struct fb_info *info) | |||
1129 | * But with imperfect damage info we may send pixels over USB | 1190 | * But with imperfect damage info we may send pixels over USB |
1130 | * that were, in fact, unchanged - wasting limited USB bandwidth | 1191 | * that were, in fact, unchanged - wasting limited USB bandwidth |
1131 | */ | 1192 | */ |
1132 | new_back = vzalloc(new_len); | 1193 | if (shadow) |
1194 | new_back = vzalloc(new_len); | ||
1133 | if (!new_back) | 1195 | if (!new_back) |
1134 | pr_info("No shadow/backing buffer allocated\n"); | 1196 | pr_info("No shadow/backing buffer allocated\n"); |
1135 | else { | 1197 | else { |
@@ -1430,21 +1492,30 @@ static int dlfb_select_std_channel(struct dlfb_data *dev) | |||
1430 | } | 1492 | } |
1431 | 1493 | ||
1432 | static int dlfb_parse_vendor_descriptor(struct dlfb_data *dev, | 1494 | static int dlfb_parse_vendor_descriptor(struct dlfb_data *dev, |
1433 | struct usb_device *usbdev) | 1495 | struct usb_interface *interface) |
1434 | { | 1496 | { |
1435 | char *desc; | 1497 | char *desc; |
1436 | char *buf; | 1498 | char *buf; |
1437 | char *desc_end; | 1499 | char *desc_end; |
1438 | 1500 | ||
1439 | u8 total_len = 0; | 1501 | int total_len = 0; |
1440 | 1502 | ||
1441 | buf = kzalloc(MAX_VENDOR_DESCRIPTOR_SIZE, GFP_KERNEL); | 1503 | buf = kzalloc(MAX_VENDOR_DESCRIPTOR_SIZE, GFP_KERNEL); |
1442 | if (!buf) | 1504 | if (!buf) |
1443 | return false; | 1505 | return false; |
1444 | desc = buf; | 1506 | desc = buf; |
1445 | 1507 | ||
1446 | total_len = usb_get_descriptor(usbdev, 0x5f, /* vendor specific */ | 1508 | total_len = usb_get_descriptor(interface_to_usbdev(interface), |
1447 | 0, desc, MAX_VENDOR_DESCRIPTOR_SIZE); | 1509 | 0x5f, /* vendor specific */ |
1510 | 0, desc, MAX_VENDOR_DESCRIPTOR_SIZE); | ||
1511 | |||
1512 | /* if not found, look in configuration descriptor */ | ||
1513 | if (total_len < 0) { | ||
1514 | if (0 == usb_get_extra_descriptor(interface->cur_altsetting, | ||
1515 | 0x5f, &desc)) | ||
1516 | total_len = (int) desc[0]; | ||
1517 | } | ||
1518 | |||
1448 | if (total_len > 5) { | 1519 | if (total_len > 5) { |
1449 | pr_info("vendor descriptor length:%x data:%02x %02x %02x %02x" \ | 1520 | pr_info("vendor descriptor length:%x data:%02x %02x %02x %02x" \ |
1450 | "%02x %02x %02x %02x %02x %02x %02x\n", | 1521 | "%02x %02x %02x %02x %02x %02x %02x\n", |
@@ -1485,6 +1556,8 @@ static int dlfb_parse_vendor_descriptor(struct dlfb_data *dev, | |||
1485 | } | 1556 | } |
1486 | desc += length; | 1557 | desc += length; |
1487 | } | 1558 | } |
1559 | } else { | ||
1560 | pr_info("vendor descriptor not available (%d)\n", total_len); | ||
1488 | } | 1561 | } |
1489 | 1562 | ||
1490 | goto success; | 1563 | goto success; |
@@ -1531,10 +1604,11 @@ static int dlfb_usb_probe(struct usb_interface *interface, | |||
1531 | usbdev->descriptor.bcdDevice, dev); | 1604 | usbdev->descriptor.bcdDevice, dev); |
1532 | pr_info("console enable=%d\n", console); | 1605 | pr_info("console enable=%d\n", console); |
1533 | pr_info("fb_defio enable=%d\n", fb_defio); | 1606 | pr_info("fb_defio enable=%d\n", fb_defio); |
1607 | pr_info("shadow enable=%d\n", shadow); | ||
1534 | 1608 | ||
1535 | dev->sku_pixel_limit = 2048 * 1152; /* default to maximum */ | 1609 | dev->sku_pixel_limit = 2048 * 1152; /* default to maximum */ |
1536 | 1610 | ||
1537 | if (!dlfb_parse_vendor_descriptor(dev, usbdev)) { | 1611 | if (!dlfb_parse_vendor_descriptor(dev, interface)) { |
1538 | pr_err("firmware not recognized. Assume incompatible device\n"); | 1612 | pr_err("firmware not recognized. Assume incompatible device\n"); |
1539 | goto error; | 1613 | goto error; |
1540 | } | 1614 | } |
@@ -1548,7 +1622,7 @@ static int dlfb_usb_probe(struct usb_interface *interface, | |||
1548 | /* We don't register a new USB class. Our client interface is fbdev */ | 1622 | /* We don't register a new USB class. Our client interface is fbdev */ |
1549 | 1623 | ||
1550 | /* allocates framebuffer driver structure, not framebuffer memory */ | 1624 | /* allocates framebuffer driver structure, not framebuffer memory */ |
1551 | info = framebuffer_alloc(0, &usbdev->dev); | 1625 | info = framebuffer_alloc(0, &interface->dev); |
1552 | if (!info) { | 1626 | if (!info) { |
1553 | retval = -ENOMEM; | 1627 | retval = -ENOMEM; |
1554 | pr_err("framebuffer_alloc failed\n"); | 1628 | pr_err("framebuffer_alloc failed\n"); |
@@ -1883,10 +1957,13 @@ static int dlfb_submit_urb(struct dlfb_data *dev, struct urb *urb, size_t len) | |||
1883 | } | 1957 | } |
1884 | 1958 | ||
1885 | module_param(console, bool, S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP); | 1959 | module_param(console, bool, S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP); |
1886 | MODULE_PARM_DESC(console, "Allow fbcon to consume first framebuffer found"); | 1960 | MODULE_PARM_DESC(console, "Allow fbcon to open framebuffer"); |
1887 | 1961 | ||
1888 | module_param(fb_defio, bool, S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP); | 1962 | module_param(fb_defio, bool, S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP); |
1889 | MODULE_PARM_DESC(fb_defio, "Enable fb_defio mmap support. *Experimental*"); | 1963 | MODULE_PARM_DESC(fb_defio, "Page fault detection of mmap writes"); |
1964 | |||
1965 | module_param(shadow, bool, S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP); | ||
1966 | MODULE_PARM_DESC(shadow, "Shadow vid mem. Disable to save mem but lose perf"); | ||
1890 | 1967 | ||
1891 | MODULE_AUTHOR("Roberto De Ioris <roberto@unbit.it>, " | 1968 | MODULE_AUTHOR("Roberto De Ioris <roberto@unbit.it>, " |
1892 | "Jaya Kumar <jayakumar.lkml@gmail.com>, " | 1969 | "Jaya Kumar <jayakumar.lkml@gmail.com>, " |
diff --git a/drivers/video/valkyriefb.c b/drivers/video/valkyriefb.c index 6b52bf65f0b5..3f5a041601da 100644 --- a/drivers/video/valkyriefb.c +++ b/drivers/video/valkyriefb.c | |||
@@ -555,7 +555,7 @@ static int __init valkyrie_init_info(struct fb_info *info, | |||
555 | 555 | ||
556 | 556 | ||
557 | /* | 557 | /* |
558 | * Parse user speficied options (`video=valkyriefb:') | 558 | * Parse user specified options (`video=valkyriefb:') |
559 | */ | 559 | */ |
560 | int __init valkyriefb_setup(char *options) | 560 | int __init valkyriefb_setup(char *options) |
561 | { | 561 | { |
diff --git a/drivers/video/vfb.c b/drivers/video/vfb.c index bc67251f1a2f..bf2f78065cf9 100644 --- a/drivers/video/vfb.c +++ b/drivers/video/vfb.c | |||
@@ -395,8 +395,8 @@ static int vfb_pan_display(struct fb_var_screeninfo *var, | |||
395 | || var->xoffset) | 395 | || var->xoffset) |
396 | return -EINVAL; | 396 | return -EINVAL; |
397 | } else { | 397 | } else { |
398 | if (var->xoffset + var->xres > info->var.xres_virtual || | 398 | if (var->xoffset + info->var.xres > info->var.xres_virtual || |
399 | var->yoffset + var->yres > info->var.yres_virtual) | 399 | var->yoffset + info->var.yres > info->var.yres_virtual) |
400 | return -EINVAL; | 400 | return -EINVAL; |
401 | } | 401 | } |
402 | info->var.xoffset = var->xoffset; | 402 | info->var.xoffset = var->xoffset; |
diff --git a/drivers/video/vga16fb.c b/drivers/video/vga16fb.c index 305c975b1787..0267acd8dc83 100644 --- a/drivers/video/vga16fb.c +++ b/drivers/video/vga16fb.c | |||
@@ -207,7 +207,7 @@ static void vga16fb_pan_var(struct fb_info *info, | |||
207 | * granularity if someone supports xoffset in bit resolution */ | 207 | * granularity if someone supports xoffset in bit resolution */ |
208 | vga_io_r(VGA_IS1_RC); /* reset flip-flop */ | 208 | vga_io_r(VGA_IS1_RC); /* reset flip-flop */ |
209 | vga_io_w(VGA_ATT_IW, VGA_ATC_PEL); | 209 | vga_io_w(VGA_ATT_IW, VGA_ATC_PEL); |
210 | if (var->bits_per_pixel == 8) | 210 | if (info->var.bits_per_pixel == 8) |
211 | vga_io_w(VGA_ATT_IW, (xoffset & 3) << 1); | 211 | vga_io_w(VGA_ATT_IW, (xoffset & 3) << 1); |
212 | else | 212 | else |
213 | vga_io_w(VGA_ATT_IW, xoffset & 7); | 213 | vga_io_w(VGA_ATT_IW, xoffset & 7); |
diff --git a/drivers/video/via/dvi.c b/drivers/video/via/dvi.c index b1f364745ca0..9138e517267c 100644 --- a/drivers/video/via/dvi.c +++ b/drivers/video/via/dvi.c | |||
@@ -172,30 +172,20 @@ static int tmds_register_read_bytes(int index, u8 *buff, int buff_len) | |||
172 | } | 172 | } |
173 | 173 | ||
174 | /* DVI Set Mode */ | 174 | /* DVI Set Mode */ |
175 | void viafb_dvi_set_mode(struct VideoModeTable *mode, int mode_bpp, | 175 | void viafb_dvi_set_mode(const struct fb_var_screeninfo *var, int iga) |
176 | int set_iga) | ||
177 | { | 176 | { |
178 | struct VideoModeTable *rb_mode; | 177 | struct fb_var_screeninfo dvi_var = *var; |
179 | struct crt_mode_table *pDviTiming; | 178 | struct crt_mode_table *rb_mode; |
180 | unsigned long desirePixelClock, maxPixelClock; | 179 | int maxPixelClock; |
181 | pDviTiming = mode->crtc; | 180 | |
182 | desirePixelClock = pDviTiming->refresh_rate | 181 | maxPixelClock = viaparinfo->shared->tmds_setting_info.max_pixel_clock; |
183 | * pDviTiming->crtc.hor_total * pDviTiming->crtc.ver_total | 182 | if (maxPixelClock && PICOS2KHZ(var->pixclock) / 1000 > maxPixelClock) { |
184 | / 1000000; | 183 | rb_mode = viafb_get_best_rb_mode(var->xres, var->yres, 60); |
185 | maxPixelClock = (unsigned long)viaparinfo-> | 184 | if (rb_mode) |
186 | tmds_setting_info->max_pixel_clock; | 185 | viafb_fill_var_timing_info(&dvi_var, rb_mode); |
187 | |||
188 | DEBUG_MSG(KERN_INFO "\nDVI_set_mode!!\n"); | ||
189 | |||
190 | if ((maxPixelClock != 0) && (desirePixelClock > maxPixelClock)) { | ||
191 | rb_mode = viafb_get_rb_mode(mode->crtc[0].crtc.hor_addr, | ||
192 | mode->crtc[0].crtc.ver_addr); | ||
193 | if (rb_mode) { | ||
194 | mode = rb_mode; | ||
195 | pDviTiming = rb_mode->crtc; | ||
196 | } | ||
197 | } | 186 | } |
198 | viafb_fill_crtc_timing(pDviTiming, mode, mode_bpp / 8, set_iga); | 187 | |
188 | viafb_fill_crtc_timing(&dvi_var, iga); | ||
199 | } | 189 | } |
200 | 190 | ||
201 | /* Sense DVI Connector */ | 191 | /* Sense DVI Connector */ |
diff --git a/drivers/video/via/dvi.h b/drivers/video/via/dvi.h index f473dd010977..e2116aaf797a 100644 --- a/drivers/video/via/dvi.h +++ b/drivers/video/via/dvi.h | |||
@@ -59,7 +59,6 @@ void viafb_dvi_enable(void); | |||
59 | bool __devinit viafb_tmds_trasmitter_identify(void); | 59 | bool __devinit viafb_tmds_trasmitter_identify(void); |
60 | void __devinit viafb_init_dvi_size(struct tmds_chip_information *tmds_chip, | 60 | void __devinit viafb_init_dvi_size(struct tmds_chip_information *tmds_chip, |
61 | struct tmds_setting_information *tmds_setting); | 61 | struct tmds_setting_information *tmds_setting); |
62 | void viafb_dvi_set_mode(struct VideoModeTable *videoMode, int mode_bpp, | 62 | void viafb_dvi_set_mode(const struct fb_var_screeninfo *var, int iga); |
63 | int set_iga); | ||
64 | 63 | ||
65 | #endif /* __DVI_H__ */ | 64 | #endif /* __DVI_H__ */ |
diff --git a/drivers/video/via/global.c b/drivers/video/via/global.c index e10d8249534c..3102171c1674 100644 --- a/drivers/video/via/global.c +++ b/drivers/video/via/global.c | |||
@@ -35,6 +35,8 @@ int viafb_LCD_ON ; | |||
35 | int viafb_LCD2_ON; | 35 | int viafb_LCD2_ON; |
36 | int viafb_SAMM_ON; | 36 | int viafb_SAMM_ON; |
37 | int viafb_dual_fb; | 37 | int viafb_dual_fb; |
38 | unsigned int viafb_second_xres = 640; | ||
39 | unsigned int viafb_second_yres = 480; | ||
38 | int viafb_hotplug_Xres = 640; | 40 | int viafb_hotplug_Xres = 640; |
39 | int viafb_hotplug_Yres = 480; | 41 | int viafb_hotplug_Yres = 480; |
40 | int viafb_hotplug_bpp = 32; | 42 | int viafb_hotplug_bpp = 32; |
diff --git a/drivers/video/via/global.h b/drivers/video/via/global.h index ff969dc34593..275dbbbd6b81 100644 --- a/drivers/video/via/global.h +++ b/drivers/video/via/global.h | |||
@@ -67,6 +67,8 @@ extern int viafb_lcd_dsp_method; | |||
67 | extern int viafb_lcd_mode; | 67 | extern int viafb_lcd_mode; |
68 | 68 | ||
69 | extern int viafb_CRT_ON; | 69 | extern int viafb_CRT_ON; |
70 | extern unsigned int viafb_second_xres; | ||
71 | extern unsigned int viafb_second_yres; | ||
70 | extern int viafb_hotplug_Xres; | 72 | extern int viafb_hotplug_Xres; |
71 | extern int viafb_hotplug_Yres; | 73 | extern int viafb_hotplug_Yres; |
72 | extern int viafb_hotplug_bpp; | 74 | extern int viafb_hotplug_bpp; |
diff --git a/drivers/video/via/hw.c b/drivers/video/via/hw.c index 47b13535ed2b..d5aaca9cfa7e 100644 --- a/drivers/video/via/hw.c +++ b/drivers/video/via/hw.c | |||
@@ -191,67 +191,6 @@ static struct fetch_count fetch_count_reg = { | |||
191 | {IGA2_FETCH_COUNT_REG_NUM, {{CR65, 0, 7}, {CR67, 2, 3} } } | 191 | {IGA2_FETCH_COUNT_REG_NUM, {{CR65, 0, 7}, {CR67, 2, 3} } } |
192 | }; | 192 | }; |
193 | 193 | ||
194 | static struct iga1_crtc_timing iga1_crtc_reg = { | ||
195 | /* IGA1 Horizontal Total */ | ||
196 | {IGA1_HOR_TOTAL_REG_NUM, {{CR00, 0, 7}, {CR36, 3, 3} } }, | ||
197 | /* IGA1 Horizontal Addressable Video */ | ||
198 | {IGA1_HOR_ADDR_REG_NUM, {{CR01, 0, 7} } }, | ||
199 | /* IGA1 Horizontal Blank Start */ | ||
200 | {IGA1_HOR_BLANK_START_REG_NUM, {{CR02, 0, 7} } }, | ||
201 | /* IGA1 Horizontal Blank End */ | ||
202 | {IGA1_HOR_BLANK_END_REG_NUM, | ||
203 | {{CR03, 0, 4}, {CR05, 7, 7}, {CR33, 5, 5} } }, | ||
204 | /* IGA1 Horizontal Sync Start */ | ||
205 | {IGA1_HOR_SYNC_START_REG_NUM, {{CR04, 0, 7}, {CR33, 4, 4} } }, | ||
206 | /* IGA1 Horizontal Sync End */ | ||
207 | {IGA1_HOR_SYNC_END_REG_NUM, {{CR05, 0, 4} } }, | ||
208 | /* IGA1 Vertical Total */ | ||
209 | {IGA1_VER_TOTAL_REG_NUM, | ||
210 | {{CR06, 0, 7}, {CR07, 0, 0}, {CR07, 5, 5}, {CR35, 0, 0} } }, | ||
211 | /* IGA1 Vertical Addressable Video */ | ||
212 | {IGA1_VER_ADDR_REG_NUM, | ||
213 | {{CR12, 0, 7}, {CR07, 1, 1}, {CR07, 6, 6}, {CR35, 2, 2} } }, | ||
214 | /* IGA1 Vertical Blank Start */ | ||
215 | {IGA1_VER_BLANK_START_REG_NUM, | ||
216 | {{CR15, 0, 7}, {CR07, 3, 3}, {CR09, 5, 5}, {CR35, 3, 3} } }, | ||
217 | /* IGA1 Vertical Blank End */ | ||
218 | {IGA1_VER_BLANK_END_REG_NUM, {{CR16, 0, 7} } }, | ||
219 | /* IGA1 Vertical Sync Start */ | ||
220 | {IGA1_VER_SYNC_START_REG_NUM, | ||
221 | {{CR10, 0, 7}, {CR07, 2, 2}, {CR07, 7, 7}, {CR35, 1, 1} } }, | ||
222 | /* IGA1 Vertical Sync End */ | ||
223 | {IGA1_VER_SYNC_END_REG_NUM, {{CR11, 0, 3} } } | ||
224 | }; | ||
225 | |||
226 | static struct iga2_crtc_timing iga2_crtc_reg = { | ||
227 | /* IGA2 Horizontal Total */ | ||
228 | {IGA2_HOR_TOTAL_REG_NUM, {{CR50, 0, 7}, {CR55, 0, 3} } }, | ||
229 | /* IGA2 Horizontal Addressable Video */ | ||
230 | {IGA2_HOR_ADDR_REG_NUM, {{CR51, 0, 7}, {CR55, 4, 6} } }, | ||
231 | /* IGA2 Horizontal Blank Start */ | ||
232 | {IGA2_HOR_BLANK_START_REG_NUM, {{CR52, 0, 7}, {CR54, 0, 2} } }, | ||
233 | /* IGA2 Horizontal Blank End */ | ||
234 | {IGA2_HOR_BLANK_END_REG_NUM, | ||
235 | {{CR53, 0, 7}, {CR54, 3, 5}, {CR5D, 6, 6} } }, | ||
236 | /* IGA2 Horizontal Sync Start */ | ||
237 | {IGA2_HOR_SYNC_START_REG_NUM, | ||
238 | {{CR56, 0, 7}, {CR54, 6, 7}, {CR5C, 7, 7}, {CR5D, 7, 7} } }, | ||
239 | /* IGA2 Horizontal Sync End */ | ||
240 | {IGA2_HOR_SYNC_END_REG_NUM, {{CR57, 0, 7}, {CR5C, 6, 6} } }, | ||
241 | /* IGA2 Vertical Total */ | ||
242 | {IGA2_VER_TOTAL_REG_NUM, {{CR58, 0, 7}, {CR5D, 0, 2} } }, | ||
243 | /* IGA2 Vertical Addressable Video */ | ||
244 | {IGA2_VER_ADDR_REG_NUM, {{CR59, 0, 7}, {CR5D, 3, 5} } }, | ||
245 | /* IGA2 Vertical Blank Start */ | ||
246 | {IGA2_VER_BLANK_START_REG_NUM, {{CR5A, 0, 7}, {CR5C, 0, 2} } }, | ||
247 | /* IGA2 Vertical Blank End */ | ||
248 | {IGA2_VER_BLANK_END_REG_NUM, {{CR5B, 0, 7}, {CR5C, 3, 5} } }, | ||
249 | /* IGA2 Vertical Sync Start */ | ||
250 | {IGA2_VER_SYNC_START_REG_NUM, {{CR5E, 0, 7}, {CR5F, 5, 7} } }, | ||
251 | /* IGA2 Vertical Sync End */ | ||
252 | {IGA2_VER_SYNC_END_REG_NUM, {{CR5F, 0, 4} } } | ||
253 | }; | ||
254 | |||
255 | static struct rgbLUT palLUT_table[] = { | 194 | static struct rgbLUT palLUT_table[] = { |
256 | /* {R,G,B} */ | 195 | /* {R,G,B} */ |
257 | /* Index 0x00~0x03 */ | 196 | /* Index 0x00~0x03 */ |
@@ -1528,302 +1467,40 @@ void viafb_set_vclock(u32 clk, int set_iga) | |||
1528 | via_write_misc_reg_mask(0x0C, 0x0C); /* select external clock */ | 1467 | via_write_misc_reg_mask(0x0C, 0x0C); /* select external clock */ |
1529 | } | 1468 | } |
1530 | 1469 | ||
1531 | void viafb_load_crtc_timing(struct display_timing device_timing, | 1470 | static struct display_timing var_to_timing(const struct fb_var_screeninfo *var) |
1532 | int set_iga) | ||
1533 | { | 1471 | { |
1534 | int i; | 1472 | struct display_timing timing; |
1535 | int viafb_load_reg_num = 0; | 1473 | |
1536 | int reg_value = 0; | 1474 | timing.hor_addr = var->xres; |
1537 | struct io_register *reg = NULL; | 1475 | timing.hor_sync_start = timing.hor_addr + var->right_margin; |
1538 | 1476 | timing.hor_sync_end = timing.hor_sync_start + var->hsync_len; | |
1539 | viafb_unlock_crt(); | 1477 | timing.hor_total = timing.hor_sync_end + var->left_margin; |
1540 | 1478 | timing.hor_blank_start = timing.hor_addr; | |
1541 | for (i = 0; i < 12; i++) { | 1479 | timing.hor_blank_end = timing.hor_total; |
1542 | if (set_iga == IGA1) { | 1480 | timing.ver_addr = var->yres; |
1543 | switch (i) { | 1481 | timing.ver_sync_start = timing.ver_addr + var->lower_margin; |
1544 | case H_TOTAL_INDEX: | 1482 | timing.ver_sync_end = timing.ver_sync_start + var->vsync_len; |
1545 | reg_value = | 1483 | timing.ver_total = timing.ver_sync_end + var->upper_margin; |
1546 | IGA1_HOR_TOTAL_FORMULA(device_timing. | 1484 | timing.ver_blank_start = timing.ver_addr; |
1547 | hor_total); | 1485 | timing.ver_blank_end = timing.ver_total; |
1548 | viafb_load_reg_num = | 1486 | return timing; |
1549 | iga1_crtc_reg.hor_total.reg_num; | ||
1550 | reg = iga1_crtc_reg.hor_total.reg; | ||
1551 | break; | ||
1552 | case H_ADDR_INDEX: | ||
1553 | reg_value = | ||
1554 | IGA1_HOR_ADDR_FORMULA(device_timing. | ||
1555 | hor_addr); | ||
1556 | viafb_load_reg_num = | ||
1557 | iga1_crtc_reg.hor_addr.reg_num; | ||
1558 | reg = iga1_crtc_reg.hor_addr.reg; | ||
1559 | break; | ||
1560 | case H_BLANK_START_INDEX: | ||
1561 | reg_value = | ||
1562 | IGA1_HOR_BLANK_START_FORMULA | ||
1563 | (device_timing.hor_blank_start); | ||
1564 | viafb_load_reg_num = | ||
1565 | iga1_crtc_reg.hor_blank_start.reg_num; | ||
1566 | reg = iga1_crtc_reg.hor_blank_start.reg; | ||
1567 | break; | ||
1568 | case H_BLANK_END_INDEX: | ||
1569 | reg_value = | ||
1570 | IGA1_HOR_BLANK_END_FORMULA | ||
1571 | (device_timing.hor_blank_start, | ||
1572 | device_timing.hor_blank_end); | ||
1573 | viafb_load_reg_num = | ||
1574 | iga1_crtc_reg.hor_blank_end.reg_num; | ||
1575 | reg = iga1_crtc_reg.hor_blank_end.reg; | ||
1576 | break; | ||
1577 | case H_SYNC_START_INDEX: | ||
1578 | reg_value = | ||
1579 | IGA1_HOR_SYNC_START_FORMULA | ||
1580 | (device_timing.hor_sync_start); | ||
1581 | viafb_load_reg_num = | ||
1582 | iga1_crtc_reg.hor_sync_start.reg_num; | ||
1583 | reg = iga1_crtc_reg.hor_sync_start.reg; | ||
1584 | break; | ||
1585 | case H_SYNC_END_INDEX: | ||
1586 | reg_value = | ||
1587 | IGA1_HOR_SYNC_END_FORMULA | ||
1588 | (device_timing.hor_sync_start, | ||
1589 | device_timing.hor_sync_end); | ||
1590 | viafb_load_reg_num = | ||
1591 | iga1_crtc_reg.hor_sync_end.reg_num; | ||
1592 | reg = iga1_crtc_reg.hor_sync_end.reg; | ||
1593 | break; | ||
1594 | case V_TOTAL_INDEX: | ||
1595 | reg_value = | ||
1596 | IGA1_VER_TOTAL_FORMULA(device_timing. | ||
1597 | ver_total); | ||
1598 | viafb_load_reg_num = | ||
1599 | iga1_crtc_reg.ver_total.reg_num; | ||
1600 | reg = iga1_crtc_reg.ver_total.reg; | ||
1601 | break; | ||
1602 | case V_ADDR_INDEX: | ||
1603 | reg_value = | ||
1604 | IGA1_VER_ADDR_FORMULA(device_timing. | ||
1605 | ver_addr); | ||
1606 | viafb_load_reg_num = | ||
1607 | iga1_crtc_reg.ver_addr.reg_num; | ||
1608 | reg = iga1_crtc_reg.ver_addr.reg; | ||
1609 | break; | ||
1610 | case V_BLANK_START_INDEX: | ||
1611 | reg_value = | ||
1612 | IGA1_VER_BLANK_START_FORMULA | ||
1613 | (device_timing.ver_blank_start); | ||
1614 | viafb_load_reg_num = | ||
1615 | iga1_crtc_reg.ver_blank_start.reg_num; | ||
1616 | reg = iga1_crtc_reg.ver_blank_start.reg; | ||
1617 | break; | ||
1618 | case V_BLANK_END_INDEX: | ||
1619 | reg_value = | ||
1620 | IGA1_VER_BLANK_END_FORMULA | ||
1621 | (device_timing.ver_blank_start, | ||
1622 | device_timing.ver_blank_end); | ||
1623 | viafb_load_reg_num = | ||
1624 | iga1_crtc_reg.ver_blank_end.reg_num; | ||
1625 | reg = iga1_crtc_reg.ver_blank_end.reg; | ||
1626 | break; | ||
1627 | case V_SYNC_START_INDEX: | ||
1628 | reg_value = | ||
1629 | IGA1_VER_SYNC_START_FORMULA | ||
1630 | (device_timing.ver_sync_start); | ||
1631 | viafb_load_reg_num = | ||
1632 | iga1_crtc_reg.ver_sync_start.reg_num; | ||
1633 | reg = iga1_crtc_reg.ver_sync_start.reg; | ||
1634 | break; | ||
1635 | case V_SYNC_END_INDEX: | ||
1636 | reg_value = | ||
1637 | IGA1_VER_SYNC_END_FORMULA | ||
1638 | (device_timing.ver_sync_start, | ||
1639 | device_timing.ver_sync_end); | ||
1640 | viafb_load_reg_num = | ||
1641 | iga1_crtc_reg.ver_sync_end.reg_num; | ||
1642 | reg = iga1_crtc_reg.ver_sync_end.reg; | ||
1643 | break; | ||
1644 | |||
1645 | } | ||
1646 | } | ||
1647 | |||
1648 | if (set_iga == IGA2) { | ||
1649 | switch (i) { | ||
1650 | case H_TOTAL_INDEX: | ||
1651 | reg_value = | ||
1652 | IGA2_HOR_TOTAL_FORMULA(device_timing. | ||
1653 | hor_total); | ||
1654 | viafb_load_reg_num = | ||
1655 | iga2_crtc_reg.hor_total.reg_num; | ||
1656 | reg = iga2_crtc_reg.hor_total.reg; | ||
1657 | break; | ||
1658 | case H_ADDR_INDEX: | ||
1659 | reg_value = | ||
1660 | IGA2_HOR_ADDR_FORMULA(device_timing. | ||
1661 | hor_addr); | ||
1662 | viafb_load_reg_num = | ||
1663 | iga2_crtc_reg.hor_addr.reg_num; | ||
1664 | reg = iga2_crtc_reg.hor_addr.reg; | ||
1665 | break; | ||
1666 | case H_BLANK_START_INDEX: | ||
1667 | reg_value = | ||
1668 | IGA2_HOR_BLANK_START_FORMULA | ||
1669 | (device_timing.hor_blank_start); | ||
1670 | viafb_load_reg_num = | ||
1671 | iga2_crtc_reg.hor_blank_start.reg_num; | ||
1672 | reg = iga2_crtc_reg.hor_blank_start.reg; | ||
1673 | break; | ||
1674 | case H_BLANK_END_INDEX: | ||
1675 | reg_value = | ||
1676 | IGA2_HOR_BLANK_END_FORMULA | ||
1677 | (device_timing.hor_blank_start, | ||
1678 | device_timing.hor_blank_end); | ||
1679 | viafb_load_reg_num = | ||
1680 | iga2_crtc_reg.hor_blank_end.reg_num; | ||
1681 | reg = iga2_crtc_reg.hor_blank_end.reg; | ||
1682 | break; | ||
1683 | case H_SYNC_START_INDEX: | ||
1684 | reg_value = | ||
1685 | IGA2_HOR_SYNC_START_FORMULA | ||
1686 | (device_timing.hor_sync_start); | ||
1687 | if (UNICHROME_CN700 <= | ||
1688 | viaparinfo->chip_info->gfx_chip_name) | ||
1689 | viafb_load_reg_num = | ||
1690 | iga2_crtc_reg.hor_sync_start. | ||
1691 | reg_num; | ||
1692 | else | ||
1693 | viafb_load_reg_num = 3; | ||
1694 | reg = iga2_crtc_reg.hor_sync_start.reg; | ||
1695 | break; | ||
1696 | case H_SYNC_END_INDEX: | ||
1697 | reg_value = | ||
1698 | IGA2_HOR_SYNC_END_FORMULA | ||
1699 | (device_timing.hor_sync_start, | ||
1700 | device_timing.hor_sync_end); | ||
1701 | viafb_load_reg_num = | ||
1702 | iga2_crtc_reg.hor_sync_end.reg_num; | ||
1703 | reg = iga2_crtc_reg.hor_sync_end.reg; | ||
1704 | break; | ||
1705 | case V_TOTAL_INDEX: | ||
1706 | reg_value = | ||
1707 | IGA2_VER_TOTAL_FORMULA(device_timing. | ||
1708 | ver_total); | ||
1709 | viafb_load_reg_num = | ||
1710 | iga2_crtc_reg.ver_total.reg_num; | ||
1711 | reg = iga2_crtc_reg.ver_total.reg; | ||
1712 | break; | ||
1713 | case V_ADDR_INDEX: | ||
1714 | reg_value = | ||
1715 | IGA2_VER_ADDR_FORMULA(device_timing. | ||
1716 | ver_addr); | ||
1717 | viafb_load_reg_num = | ||
1718 | iga2_crtc_reg.ver_addr.reg_num; | ||
1719 | reg = iga2_crtc_reg.ver_addr.reg; | ||
1720 | break; | ||
1721 | case V_BLANK_START_INDEX: | ||
1722 | reg_value = | ||
1723 | IGA2_VER_BLANK_START_FORMULA | ||
1724 | (device_timing.ver_blank_start); | ||
1725 | viafb_load_reg_num = | ||
1726 | iga2_crtc_reg.ver_blank_start.reg_num; | ||
1727 | reg = iga2_crtc_reg.ver_blank_start.reg; | ||
1728 | break; | ||
1729 | case V_BLANK_END_INDEX: | ||
1730 | reg_value = | ||
1731 | IGA2_VER_BLANK_END_FORMULA | ||
1732 | (device_timing.ver_blank_start, | ||
1733 | device_timing.ver_blank_end); | ||
1734 | viafb_load_reg_num = | ||
1735 | iga2_crtc_reg.ver_blank_end.reg_num; | ||
1736 | reg = iga2_crtc_reg.ver_blank_end.reg; | ||
1737 | break; | ||
1738 | case V_SYNC_START_INDEX: | ||
1739 | reg_value = | ||
1740 | IGA2_VER_SYNC_START_FORMULA | ||
1741 | (device_timing.ver_sync_start); | ||
1742 | viafb_load_reg_num = | ||
1743 | iga2_crtc_reg.ver_sync_start.reg_num; | ||
1744 | reg = iga2_crtc_reg.ver_sync_start.reg; | ||
1745 | break; | ||
1746 | case V_SYNC_END_INDEX: | ||
1747 | reg_value = | ||
1748 | IGA2_VER_SYNC_END_FORMULA | ||
1749 | (device_timing.ver_sync_start, | ||
1750 | device_timing.ver_sync_end); | ||
1751 | viafb_load_reg_num = | ||
1752 | iga2_crtc_reg.ver_sync_end.reg_num; | ||
1753 | reg = iga2_crtc_reg.ver_sync_end.reg; | ||
1754 | break; | ||
1755 | |||
1756 | } | ||
1757 | } | ||
1758 | viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIACR); | ||
1759 | } | ||
1760 | |||
1761 | viafb_lock_crt(); | ||
1762 | } | 1487 | } |
1763 | 1488 | ||
1764 | void viafb_fill_crtc_timing(struct crt_mode_table *crt_table, | 1489 | void viafb_fill_crtc_timing(const struct fb_var_screeninfo *var, int iga) |
1765 | struct VideoModeTable *video_mode, int bpp_byte, int set_iga) | ||
1766 | { | 1490 | { |
1767 | struct display_timing crt_reg; | 1491 | struct display_timing crt_reg = var_to_timing(var); |
1768 | int i; | ||
1769 | int index = 0; | ||
1770 | int h_addr, v_addr; | ||
1771 | u32 clock, refresh = viafb_refresh; | ||
1772 | |||
1773 | if (viafb_SAMM_ON && set_iga == IGA2) | ||
1774 | refresh = viafb_refresh1; | ||
1775 | |||
1776 | for (i = 0; i < video_mode->mode_array; i++) { | ||
1777 | index = i; | ||
1778 | |||
1779 | if (crt_table[i].refresh_rate == refresh) | ||
1780 | break; | ||
1781 | } | ||
1782 | 1492 | ||
1783 | crt_reg = crt_table[index].crtc; | 1493 | if (iga == IGA1) |
1494 | via_set_primary_timing(&crt_reg); | ||
1495 | else if (iga == IGA2) | ||
1496 | via_set_secondary_timing(&crt_reg); | ||
1784 | 1497 | ||
1785 | /* Mode 640x480 has border, but LCD/DFP didn't have border. */ | 1498 | viafb_load_fetch_count_reg(var->xres, var->bits_per_pixel / 8, iga); |
1786 | /* So we would delete border. */ | 1499 | if (viaparinfo->chip_info->gfx_chip_name != UNICHROME_CLE266 |
1787 | if ((viafb_LCD_ON | viafb_DVI_ON) | 1500 | && viaparinfo->chip_info->gfx_chip_name != UNICHROME_K400) |
1788 | && video_mode->crtc[0].crtc.hor_addr == 640 | 1501 | viafb_load_FIFO_reg(iga, var->xres, var->yres); |
1789 | && video_mode->crtc[0].crtc.ver_addr == 480 | ||
1790 | && refresh == 60) { | ||
1791 | /* The border is 8 pixels. */ | ||
1792 | crt_reg.hor_blank_start = crt_reg.hor_blank_start - 8; | ||
1793 | |||
1794 | /* Blanking time should add left and right borders. */ | ||
1795 | crt_reg.hor_blank_end = crt_reg.hor_blank_end + 16; | ||
1796 | } | ||
1797 | |||
1798 | h_addr = crt_reg.hor_addr; | ||
1799 | v_addr = crt_reg.ver_addr; | ||
1800 | if (set_iga == IGA1) { | ||
1801 | viafb_unlock_crt(); | ||
1802 | viafb_write_reg_mask(CR17, VIACR, 0x00, BIT7); | ||
1803 | } | ||
1804 | |||
1805 | switch (set_iga) { | ||
1806 | case IGA1: | ||
1807 | viafb_load_crtc_timing(crt_reg, IGA1); | ||
1808 | break; | ||
1809 | case IGA2: | ||
1810 | viafb_load_crtc_timing(crt_reg, IGA2); | ||
1811 | break; | ||
1812 | } | ||
1813 | |||
1814 | viafb_lock_crt(); | ||
1815 | viafb_write_reg_mask(CR17, VIACR, 0x80, BIT7); | ||
1816 | viafb_load_fetch_count_reg(h_addr, bpp_byte, set_iga); | ||
1817 | |||
1818 | /* load FIFO */ | ||
1819 | if ((viaparinfo->chip_info->gfx_chip_name != UNICHROME_CLE266) | ||
1820 | && (viaparinfo->chip_info->gfx_chip_name != UNICHROME_K400)) | ||
1821 | viafb_load_FIFO_reg(set_iga, h_addr, v_addr); | ||
1822 | |||
1823 | clock = crt_reg.hor_total * crt_reg.ver_total | ||
1824 | * crt_table[index].refresh_rate; | ||
1825 | viafb_set_vclock(clock, set_iga); | ||
1826 | 1502 | ||
1503 | viafb_set_vclock(PICOS2KHZ(var->pixclock) * 1000, iga); | ||
1827 | } | 1504 | } |
1828 | 1505 | ||
1829 | void __devinit viafb_init_chip_info(int chip_type) | 1506 | void __devinit viafb_init_chip_info(int chip_type) |
@@ -2092,23 +1769,9 @@ static u8 get_sync(struct fb_info *info) | |||
2092 | return polarity; | 1769 | return polarity; |
2093 | } | 1770 | } |
2094 | 1771 | ||
2095 | int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp, | 1772 | static void hw_init(void) |
2096 | struct VideoModeTable *vmode_tbl1, int video_bpp1) | ||
2097 | { | 1773 | { |
2098 | int i, j; | 1774 | int i; |
2099 | int port; | ||
2100 | u32 devices = viaparinfo->shared->iga1_devices | ||
2101 | | viaparinfo->shared->iga2_devices; | ||
2102 | u8 value, index, mask; | ||
2103 | struct crt_mode_table *crt_timing; | ||
2104 | struct crt_mode_table *crt_timing1 = NULL; | ||
2105 | |||
2106 | device_screen_off(); | ||
2107 | crt_timing = vmode_tbl->crtc; | ||
2108 | |||
2109 | if (viafb_SAMM_ON == 1) { | ||
2110 | crt_timing1 = vmode_tbl1->crtc; | ||
2111 | } | ||
2112 | 1775 | ||
2113 | inb(VIAStatus); | 1776 | inb(VIAStatus); |
2114 | outb(0x00, VIAAR); | 1777 | outb(0x00, VIAAR); |
@@ -2147,9 +1810,8 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp, | |||
2147 | break; | 1810 | break; |
2148 | } | 1811 | } |
2149 | 1812 | ||
1813 | /* probably this should go to the scaling code one day */ | ||
2150 | viafb_write_regx(scaling_parameters, ARRAY_SIZE(scaling_parameters)); | 1814 | viafb_write_regx(scaling_parameters, ARRAY_SIZE(scaling_parameters)); |
2151 | device_off(); | ||
2152 | via_set_state(devices, VIA_STATE_OFF); | ||
2153 | 1815 | ||
2154 | /* Fill VPIT Parameters */ | 1816 | /* Fill VPIT Parameters */ |
2155 | /* Write Misc Register */ | 1817 | /* Write Misc Register */ |
@@ -2175,12 +1837,29 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp, | |||
2175 | inb(VIAStatus); | 1837 | inb(VIAStatus); |
2176 | outb(0x20, VIAAR); | 1838 | outb(0x20, VIAAR); |
2177 | 1839 | ||
1840 | load_fix_bit_crtc_reg(); | ||
1841 | } | ||
1842 | |||
1843 | int viafb_setmode(int video_bpp, int video_bpp1) | ||
1844 | { | ||
1845 | int j; | ||
1846 | int port; | ||
1847 | u32 devices = viaparinfo->shared->iga1_devices | ||
1848 | | viaparinfo->shared->iga2_devices; | ||
1849 | u8 value, index, mask; | ||
1850 | struct fb_var_screeninfo var2; | ||
1851 | |||
1852 | device_screen_off(); | ||
1853 | device_off(); | ||
1854 | via_set_state(devices, VIA_STATE_OFF); | ||
1855 | |||
1856 | hw_init(); | ||
1857 | |||
2178 | /* Update Patch Register */ | 1858 | /* Update Patch Register */ |
2179 | 1859 | ||
2180 | if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266 | 1860 | if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266 |
2181 | || viaparinfo->chip_info->gfx_chip_name == UNICHROME_K400) | 1861 | || viaparinfo->chip_info->gfx_chip_name == UNICHROME_K400) |
2182 | && vmode_tbl->crtc[0].crtc.hor_addr == 1024 | 1862 | && viafbinfo->var.xres == 1024 && viafbinfo->var.yres == 768) { |
2183 | && vmode_tbl->crtc[0].crtc.ver_addr == 768) { | ||
2184 | for (j = 0; j < res_patch_table[0].table_length; j++) { | 1863 | for (j = 0; j < res_patch_table[0].table_length; j++) { |
2185 | index = res_patch_table[0].io_reg_table[j].index; | 1864 | index = res_patch_table[0].io_reg_table[j].index; |
2186 | port = res_patch_table[0].io_reg_table[j].port; | 1865 | port = res_patch_table[0].io_reg_table[j].port; |
@@ -2190,7 +1869,6 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp, | |||
2190 | } | 1869 | } |
2191 | } | 1870 | } |
2192 | 1871 | ||
2193 | load_fix_bit_crtc_reg(); | ||
2194 | via_set_primary_pitch(viafbinfo->fix.line_length); | 1872 | via_set_primary_pitch(viafbinfo->fix.line_length); |
2195 | via_set_secondary_pitch(viafb_dual_fb ? viafbinfo1->fix.line_length | 1873 | via_set_secondary_pitch(viafb_dual_fb ? viafbinfo1->fix.line_length |
2196 | : viafbinfo->fix.line_length); | 1874 | : viafbinfo->fix.line_length); |
@@ -2208,23 +1886,28 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp, | |||
2208 | 1886 | ||
2209 | /* Clear On Screen */ | 1887 | /* Clear On Screen */ |
2210 | 1888 | ||
1889 | if (viafb_dual_fb) { | ||
1890 | var2 = viafbinfo1->var; | ||
1891 | } else if (viafb_SAMM_ON) { | ||
1892 | viafb_fill_var_timing_info(&var2, viafb_get_best_mode( | ||
1893 | viafb_second_xres, viafb_second_yres, viafb_refresh1)); | ||
1894 | var2.bits_per_pixel = viafbinfo->var.bits_per_pixel; | ||
1895 | } | ||
1896 | |||
2211 | /* CRT set mode */ | 1897 | /* CRT set mode */ |
2212 | if (viafb_CRT_ON) { | 1898 | if (viafb_CRT_ON) { |
2213 | if (viafb_SAMM_ON && | 1899 | if (viaparinfo->shared->iga2_devices & VIA_CRT |
2214 | viaparinfo->shared->iga2_devices & VIA_CRT) { | 1900 | && viafb_SAMM_ON) |
2215 | viafb_fill_crtc_timing(crt_timing1, vmode_tbl1, | 1901 | viafb_fill_crtc_timing(&var2, IGA2); |
2216 | video_bpp1 / 8, IGA2); | 1902 | else |
2217 | } else { | 1903 | viafb_fill_crtc_timing(&viafbinfo->var, |
2218 | viafb_fill_crtc_timing(crt_timing, vmode_tbl, | ||
2219 | video_bpp / 8, | ||
2220 | (viaparinfo->shared->iga1_devices & VIA_CRT) | 1904 | (viaparinfo->shared->iga1_devices & VIA_CRT) |
2221 | ? IGA1 : IGA2); | 1905 | ? IGA1 : IGA2); |
2222 | } | ||
2223 | 1906 | ||
2224 | /* Patch if set_hres is not 8 alignment (1366) to viafb_setmode | 1907 | /* Patch if set_hres is not 8 alignment (1366) to viafb_setmode |
2225 | to 8 alignment (1368),there is several pixels (2 pixels) | 1908 | to 8 alignment (1368),there is several pixels (2 pixels) |
2226 | on right side of screen. */ | 1909 | on right side of screen. */ |
2227 | if (vmode_tbl->crtc[0].crtc.hor_addr % 8) { | 1910 | if (viafbinfo->var.xres % 8) { |
2228 | viafb_unlock_crt(); | 1911 | viafb_unlock_crt(); |
2229 | viafb_write_reg(CR02, VIACR, | 1912 | viafb_write_reg(CR02, VIACR, |
2230 | viafb_read_reg(VIACR, CR02) - 1); | 1913 | viafb_read_reg(VIACR, CR02) - 1); |
@@ -2233,31 +1916,20 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp, | |||
2233 | } | 1916 | } |
2234 | 1917 | ||
2235 | if (viafb_DVI_ON) { | 1918 | if (viafb_DVI_ON) { |
2236 | if (viafb_SAMM_ON && | 1919 | if (viaparinfo->shared->tmds_setting_info.iga_path == IGA2 |
2237 | (viaparinfo->tmds_setting_info->iga_path == IGA2)) { | 1920 | && viafb_SAMM_ON) |
2238 | viafb_dvi_set_mode(viafb_get_mode | 1921 | viafb_dvi_set_mode(&var2, IGA2); |
2239 | (viaparinfo->tmds_setting_info->h_active, | 1922 | else |
2240 | viaparinfo->tmds_setting_info-> | 1923 | viafb_dvi_set_mode(&viafbinfo->var, |
2241 | v_active), | 1924 | viaparinfo->tmds_setting_info->iga_path); |
2242 | video_bpp1, viaparinfo-> | ||
2243 | tmds_setting_info->iga_path); | ||
2244 | } else { | ||
2245 | viafb_dvi_set_mode(viafb_get_mode | ||
2246 | (viaparinfo->tmds_setting_info->h_active, | ||
2247 | viaparinfo-> | ||
2248 | tmds_setting_info->v_active), | ||
2249 | video_bpp, viaparinfo-> | ||
2250 | tmds_setting_info->iga_path); | ||
2251 | } | ||
2252 | } | 1925 | } |
2253 | 1926 | ||
2254 | if (viafb_LCD_ON) { | 1927 | if (viafb_LCD_ON) { |
2255 | if (viafb_SAMM_ON && | 1928 | if (viafb_SAMM_ON && |
2256 | (viaparinfo->lvds_setting_info->iga_path == IGA2)) { | 1929 | (viaparinfo->lvds_setting_info->iga_path == IGA2)) { |
2257 | viaparinfo->lvds_setting_info->bpp = video_bpp1; | 1930 | viaparinfo->lvds_setting_info->bpp = video_bpp1; |
2258 | viafb_lcd_set_mode(crt_timing1, viaparinfo-> | 1931 | viafb_lcd_set_mode(viaparinfo->lvds_setting_info, |
2259 | lvds_setting_info, | 1932 | &viaparinfo->chip_info->lvds_chip_info); |
2260 | &viaparinfo->chip_info->lvds_chip_info); | ||
2261 | } else { | 1933 | } else { |
2262 | /* IGA1 doesn't have LCD scaling, so set it center. */ | 1934 | /* IGA1 doesn't have LCD scaling, so set it center. */ |
2263 | if (viaparinfo->lvds_setting_info->iga_path == IGA1) { | 1935 | if (viaparinfo->lvds_setting_info->iga_path == IGA1) { |
@@ -2265,18 +1937,16 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp, | |||
2265 | LCD_CENTERING; | 1937 | LCD_CENTERING; |
2266 | } | 1938 | } |
2267 | viaparinfo->lvds_setting_info->bpp = video_bpp; | 1939 | viaparinfo->lvds_setting_info->bpp = video_bpp; |
2268 | viafb_lcd_set_mode(crt_timing, viaparinfo-> | 1940 | viafb_lcd_set_mode(viaparinfo->lvds_setting_info, |
2269 | lvds_setting_info, | 1941 | &viaparinfo->chip_info->lvds_chip_info); |
2270 | &viaparinfo->chip_info->lvds_chip_info); | ||
2271 | } | 1942 | } |
2272 | } | 1943 | } |
2273 | if (viafb_LCD2_ON) { | 1944 | if (viafb_LCD2_ON) { |
2274 | if (viafb_SAMM_ON && | 1945 | if (viafb_SAMM_ON && |
2275 | (viaparinfo->lvds_setting_info2->iga_path == IGA2)) { | 1946 | (viaparinfo->lvds_setting_info2->iga_path == IGA2)) { |
2276 | viaparinfo->lvds_setting_info2->bpp = video_bpp1; | 1947 | viaparinfo->lvds_setting_info2->bpp = video_bpp1; |
2277 | viafb_lcd_set_mode(crt_timing1, viaparinfo-> | 1948 | viafb_lcd_set_mode(viaparinfo->lvds_setting_info2, |
2278 | lvds_setting_info2, | 1949 | &viaparinfo->chip_info->lvds_chip_info2); |
2279 | &viaparinfo->chip_info->lvds_chip_info2); | ||
2280 | } else { | 1950 | } else { |
2281 | /* IGA1 doesn't have LCD scaling, so set it center. */ | 1951 | /* IGA1 doesn't have LCD scaling, so set it center. */ |
2282 | if (viaparinfo->lvds_setting_info2->iga_path == IGA1) { | 1952 | if (viaparinfo->lvds_setting_info2->iga_path == IGA1) { |
@@ -2284,9 +1954,8 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp, | |||
2284 | LCD_CENTERING; | 1954 | LCD_CENTERING; |
2285 | } | 1955 | } |
2286 | viaparinfo->lvds_setting_info2->bpp = video_bpp; | 1956 | viaparinfo->lvds_setting_info2->bpp = video_bpp; |
2287 | viafb_lcd_set_mode(crt_timing, viaparinfo-> | 1957 | viafb_lcd_set_mode(viaparinfo->lvds_setting_info2, |
2288 | lvds_setting_info2, | 1958 | &viaparinfo->chip_info->lvds_chip_info2); |
2289 | &viaparinfo->chip_info->lvds_chip_info2); | ||
2290 | } | 1959 | } |
2291 | } | 1960 | } |
2292 | 1961 | ||
@@ -2296,8 +1965,8 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp, | |||
2296 | 1965 | ||
2297 | /* If set mode normally, save resolution information for hot-plug . */ | 1966 | /* If set mode normally, save resolution information for hot-plug . */ |
2298 | if (!viafb_hotplug) { | 1967 | if (!viafb_hotplug) { |
2299 | viafb_hotplug_Xres = vmode_tbl->crtc[0].crtc.hor_addr; | 1968 | viafb_hotplug_Xres = viafbinfo->var.xres; |
2300 | viafb_hotplug_Yres = vmode_tbl->crtc[0].crtc.ver_addr; | 1969 | viafb_hotplug_Yres = viafbinfo->var.yres; |
2301 | viafb_hotplug_bpp = video_bpp; | 1970 | viafb_hotplug_bpp = video_bpp; |
2302 | viafb_hotplug_refresh = viafb_refresh; | 1971 | viafb_hotplug_refresh = viafb_refresh; |
2303 | 1972 | ||
@@ -2348,42 +2017,14 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp, | |||
2348 | return 1; | 2017 | return 1; |
2349 | } | 2018 | } |
2350 | 2019 | ||
2351 | int viafb_get_pixclock(int hres, int vres, int vmode_refresh) | ||
2352 | { | ||
2353 | int i; | ||
2354 | struct crt_mode_table *best; | ||
2355 | struct VideoModeTable *vmode = viafb_get_mode(hres, vres); | ||
2356 | |||
2357 | if (!vmode) | ||
2358 | return RES_640X480_60HZ_PIXCLOCK; | ||
2359 | |||
2360 | best = &vmode->crtc[0]; | ||
2361 | for (i = 1; i < vmode->mode_array; i++) { | ||
2362 | if (abs(vmode->crtc[i].refresh_rate - vmode_refresh) | ||
2363 | < abs(best->refresh_rate - vmode_refresh)) | ||
2364 | best = &vmode->crtc[i]; | ||
2365 | } | ||
2366 | |||
2367 | return 1000000000 / (best->crtc.hor_total * best->crtc.ver_total) | ||
2368 | * 1000 / best->refresh_rate; | ||
2369 | } | ||
2370 | |||
2371 | int viafb_get_refresh(int hres, int vres, u32 long_refresh) | 2020 | int viafb_get_refresh(int hres, int vres, u32 long_refresh) |
2372 | { | 2021 | { |
2373 | int i; | ||
2374 | struct crt_mode_table *best; | 2022 | struct crt_mode_table *best; |
2375 | struct VideoModeTable *vmode = viafb_get_mode(hres, vres); | ||
2376 | 2023 | ||
2377 | if (!vmode) | 2024 | best = viafb_get_best_mode(hres, vres, long_refresh); |
2025 | if (!best) | ||
2378 | return 60; | 2026 | return 60; |
2379 | 2027 | ||
2380 | best = &vmode->crtc[0]; | ||
2381 | for (i = 1; i < vmode->mode_array; i++) { | ||
2382 | if (abs(vmode->crtc[i].refresh_rate - long_refresh) | ||
2383 | < abs(best->refresh_rate - long_refresh)) | ||
2384 | best = &vmode->crtc[i]; | ||
2385 | } | ||
2386 | |||
2387 | if (abs(best->refresh_rate - long_refresh) > 3) { | 2028 | if (abs(best->refresh_rate - long_refresh) > 3) { |
2388 | if (hres == 1200 && vres == 900) | 2029 | if (hres == 1200 && vres == 900) |
2389 | return 49; /* OLPC DCON only supports 50 Hz */ | 2030 | return 49; /* OLPC DCON only supports 50 Hz */ |
@@ -2485,21 +2126,14 @@ void viafb_set_dpa_gfx(int output_interface, struct GFX_DPA_SETTING\ | |||
2485 | } | 2126 | } |
2486 | 2127 | ||
2487 | /*According var's xres, yres fill var's other timing information*/ | 2128 | /*According var's xres, yres fill var's other timing information*/ |
2488 | void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, int refresh, | 2129 | void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, |
2489 | struct VideoModeTable *vmode_tbl) | 2130 | struct crt_mode_table *mode) |
2490 | { | 2131 | { |
2491 | struct crt_mode_table *crt_timing = NULL; | ||
2492 | struct display_timing crt_reg; | 2132 | struct display_timing crt_reg; |
2493 | int i = 0, index = 0; | ||
2494 | crt_timing = vmode_tbl->crtc; | ||
2495 | for (i = 0; i < vmode_tbl->mode_array; i++) { | ||
2496 | index = i; | ||
2497 | if (crt_timing[i].refresh_rate == refresh) | ||
2498 | break; | ||
2499 | } | ||
2500 | 2133 | ||
2501 | crt_reg = crt_timing[index].crtc; | 2134 | crt_reg = mode->crtc; |
2502 | var->pixclock = viafb_get_pixclock(var->xres, var->yres, refresh); | 2135 | var->pixclock = 1000000000 / (crt_reg.hor_total * crt_reg.ver_total) |
2136 | * 1000 / mode->refresh_rate; | ||
2503 | var->left_margin = | 2137 | var->left_margin = |
2504 | crt_reg.hor_total - (crt_reg.hor_sync_start + crt_reg.hor_sync_end); | 2138 | crt_reg.hor_total - (crt_reg.hor_sync_start + crt_reg.hor_sync_end); |
2505 | var->right_margin = crt_reg.hor_sync_start - crt_reg.hor_addr; | 2139 | var->right_margin = crt_reg.hor_sync_start - crt_reg.hor_addr; |
@@ -2509,8 +2143,8 @@ void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, int refresh, | |||
2509 | var->lower_margin = crt_reg.ver_sync_start - crt_reg.ver_addr; | 2143 | var->lower_margin = crt_reg.ver_sync_start - crt_reg.ver_addr; |
2510 | var->vsync_len = crt_reg.ver_sync_end; | 2144 | var->vsync_len = crt_reg.ver_sync_end; |
2511 | var->sync = 0; | 2145 | var->sync = 0; |
2512 | if (crt_timing[index].h_sync_polarity == POSITIVE) | 2146 | if (mode->h_sync_polarity == POSITIVE) |
2513 | var->sync |= FB_SYNC_HOR_HIGH_ACT; | 2147 | var->sync |= FB_SYNC_HOR_HIGH_ACT; |
2514 | if (crt_timing[index].v_sync_polarity == POSITIVE) | 2148 | if (mode->v_sync_polarity == POSITIVE) |
2515 | var->sync |= FB_SYNC_VERT_HIGH_ACT; | 2149 | var->sync |= FB_SYNC_VERT_HIGH_ACT; |
2516 | } | 2150 | } |
diff --git a/drivers/video/via/hw.h b/drivers/video/via/hw.h index c7239eb83bae..4db5b6e8d8d0 100644 --- a/drivers/video/via/hw.h +++ b/drivers/video/via/hw.h | |||
@@ -51,40 +51,6 @@ | |||
51 | #define VIA_HSYNC_NEGATIVE 0x01 | 51 | #define VIA_HSYNC_NEGATIVE 0x01 |
52 | #define VIA_VSYNC_NEGATIVE 0x02 | 52 | #define VIA_VSYNC_NEGATIVE 0x02 |
53 | 53 | ||
54 | /*************************************************** | ||
55 | * Definition IGA1 Design Method of CRTC Registers * | ||
56 | ****************************************************/ | ||
57 | #define IGA1_HOR_TOTAL_FORMULA(x) (((x)/8)-5) | ||
58 | #define IGA1_HOR_ADDR_FORMULA(x) (((x)/8)-1) | ||
59 | #define IGA1_HOR_BLANK_START_FORMULA(x) (((x)/8)-1) | ||
60 | #define IGA1_HOR_BLANK_END_FORMULA(x, y) (((x+y)/8)-1) | ||
61 | #define IGA1_HOR_SYNC_START_FORMULA(x) ((x)/8) | ||
62 | #define IGA1_HOR_SYNC_END_FORMULA(x, y) ((x+y)/8) | ||
63 | |||
64 | #define IGA1_VER_TOTAL_FORMULA(x) ((x)-2) | ||
65 | #define IGA1_VER_ADDR_FORMULA(x) ((x)-1) | ||
66 | #define IGA1_VER_BLANK_START_FORMULA(x) ((x)-1) | ||
67 | #define IGA1_VER_BLANK_END_FORMULA(x, y) ((x+y)-1) | ||
68 | #define IGA1_VER_SYNC_START_FORMULA(x) ((x)-1) | ||
69 | #define IGA1_VER_SYNC_END_FORMULA(x, y) ((x+y)-1) | ||
70 | |||
71 | /*************************************************** | ||
72 | ** Definition IGA2 Design Method of CRTC Registers * | ||
73 | ****************************************************/ | ||
74 | #define IGA2_HOR_TOTAL_FORMULA(x) ((x)-1) | ||
75 | #define IGA2_HOR_ADDR_FORMULA(x) ((x)-1) | ||
76 | #define IGA2_HOR_BLANK_START_FORMULA(x) ((x)-1) | ||
77 | #define IGA2_HOR_BLANK_END_FORMULA(x, y) ((x+y)-1) | ||
78 | #define IGA2_HOR_SYNC_START_FORMULA(x) ((x)-1) | ||
79 | #define IGA2_HOR_SYNC_END_FORMULA(x, y) ((x+y)-1) | ||
80 | |||
81 | #define IGA2_VER_TOTAL_FORMULA(x) ((x)-1) | ||
82 | #define IGA2_VER_ADDR_FORMULA(x) ((x)-1) | ||
83 | #define IGA2_VER_BLANK_START_FORMULA(x) ((x)-1) | ||
84 | #define IGA2_VER_BLANK_END_FORMULA(x, y) ((x+y)-1) | ||
85 | #define IGA2_VER_SYNC_START_FORMULA(x) ((x)-1) | ||
86 | #define IGA2_VER_SYNC_END_FORMULA(x, y) ((x+y)-1) | ||
87 | |||
88 | /**********************************************************/ | 54 | /**********************************************************/ |
89 | /* Definition IGA2 Design Method of CRTC Shadow Registers */ | 55 | /* Definition IGA2 Design Method of CRTC Shadow Registers */ |
90 | /**********************************************************/ | 56 | /**********************************************************/ |
@@ -97,33 +63,6 @@ | |||
97 | #define IGA2_VER_SYNC_START_SHADOW_FORMULA(x) (x) | 63 | #define IGA2_VER_SYNC_START_SHADOW_FORMULA(x) (x) |
98 | #define IGA2_VER_SYNC_END_SHADOW_FORMULA(x, y) (x+y) | 64 | #define IGA2_VER_SYNC_END_SHADOW_FORMULA(x, y) (x+y) |
99 | 65 | ||
100 | /* Define Register Number for IGA1 CRTC Timing */ | ||
101 | |||
102 | /* location: {CR00,0,7},{CR36,3,3} */ | ||
103 | #define IGA1_HOR_TOTAL_REG_NUM 2 | ||
104 | /* location: {CR01,0,7} */ | ||
105 | #define IGA1_HOR_ADDR_REG_NUM 1 | ||
106 | /* location: {CR02,0,7} */ | ||
107 | #define IGA1_HOR_BLANK_START_REG_NUM 1 | ||
108 | /* location: {CR03,0,4},{CR05,7,7},{CR33,5,5} */ | ||
109 | #define IGA1_HOR_BLANK_END_REG_NUM 3 | ||
110 | /* location: {CR04,0,7},{CR33,4,4} */ | ||
111 | #define IGA1_HOR_SYNC_START_REG_NUM 2 | ||
112 | /* location: {CR05,0,4} */ | ||
113 | #define IGA1_HOR_SYNC_END_REG_NUM 1 | ||
114 | /* location: {CR06,0,7},{CR07,0,0},{CR07,5,5},{CR35,0,0} */ | ||
115 | #define IGA1_VER_TOTAL_REG_NUM 4 | ||
116 | /* location: {CR12,0,7},{CR07,1,1},{CR07,6,6},{CR35,2,2} */ | ||
117 | #define IGA1_VER_ADDR_REG_NUM 4 | ||
118 | /* location: {CR15,0,7},{CR07,3,3},{CR09,5,5},{CR35,3,3} */ | ||
119 | #define IGA1_VER_BLANK_START_REG_NUM 4 | ||
120 | /* location: {CR16,0,7} */ | ||
121 | #define IGA1_VER_BLANK_END_REG_NUM 1 | ||
122 | /* location: {CR10,0,7},{CR07,2,2},{CR07,7,7},{CR35,1,1} */ | ||
123 | #define IGA1_VER_SYNC_START_REG_NUM 4 | ||
124 | /* location: {CR11,0,3} */ | ||
125 | #define IGA1_VER_SYNC_END_REG_NUM 1 | ||
126 | |||
127 | /* Define Register Number for IGA2 Shadow CRTC Timing */ | 66 | /* Define Register Number for IGA2 Shadow CRTC Timing */ |
128 | 67 | ||
129 | /* location: {CR6D,0,7},{CR71,3,3} */ | 68 | /* location: {CR6D,0,7},{CR71,3,3} */ |
@@ -143,37 +82,6 @@ | |||
143 | /* location: {CR76,0,3} */ | 82 | /* location: {CR76,0,3} */ |
144 | #define IGA2_SHADOW_VER_SYNC_END_REG_NUM 1 | 83 | #define IGA2_SHADOW_VER_SYNC_END_REG_NUM 1 |
145 | 84 | ||
146 | /* Define Register Number for IGA2 CRTC Timing */ | ||
147 | |||
148 | /* location: {CR50,0,7},{CR55,0,3} */ | ||
149 | #define IGA2_HOR_TOTAL_REG_NUM 2 | ||
150 | /* location: {CR51,0,7},{CR55,4,6} */ | ||
151 | #define IGA2_HOR_ADDR_REG_NUM 2 | ||
152 | /* location: {CR52,0,7},{CR54,0,2} */ | ||
153 | #define IGA2_HOR_BLANK_START_REG_NUM 2 | ||
154 | /* location: CLE266: {CR53,0,7},{CR54,3,5} => CLE266's CR5D[6] | ||
155 | is reserved, so it may have problem to set 1600x1200 on IGA2. */ | ||
156 | /* Others: {CR53,0,7},{CR54,3,5},{CR5D,6,6} */ | ||
157 | #define IGA2_HOR_BLANK_END_REG_NUM 3 | ||
158 | /* location: {CR56,0,7},{CR54,6,7},{CR5C,7,7} */ | ||
159 | /* VT3314 and Later: {CR56,0,7},{CR54,6,7},{CR5C,7,7}, {CR5D,7,7} */ | ||
160 | #define IGA2_HOR_SYNC_START_REG_NUM 4 | ||
161 | |||
162 | /* location: {CR57,0,7},{CR5C,6,6} */ | ||
163 | #define IGA2_HOR_SYNC_END_REG_NUM 2 | ||
164 | /* location: {CR58,0,7},{CR5D,0,2} */ | ||
165 | #define IGA2_VER_TOTAL_REG_NUM 2 | ||
166 | /* location: {CR59,0,7},{CR5D,3,5} */ | ||
167 | #define IGA2_VER_ADDR_REG_NUM 2 | ||
168 | /* location: {CR5A,0,7},{CR5C,0,2} */ | ||
169 | #define IGA2_VER_BLANK_START_REG_NUM 2 | ||
170 | /* location: {CR5E,0,7},{CR5C,3,5} */ | ||
171 | #define IGA2_VER_BLANK_END_REG_NUM 2 | ||
172 | /* location: {CR5E,0,7},{CR5F,5,7} */ | ||
173 | #define IGA2_VER_SYNC_START_REG_NUM 2 | ||
174 | /* location: {CR5F,0,4} */ | ||
175 | #define IGA2_VER_SYNC_END_REG_NUM 1 | ||
176 | |||
177 | /* Define Fetch Count Register*/ | 85 | /* Define Fetch Count Register*/ |
178 | 86 | ||
179 | /* location: {SR1C,0,7},{SR1D,0,1} */ | 87 | /* location: {SR1C,0,7},{SR1D,0,1} */ |
@@ -446,87 +354,12 @@ is reserved, so it may have problem to set 1600x1200 on IGA2. */ | |||
446 | /* location: {CR78,0,7},{CR79,6,7} */ | 354 | /* location: {CR78,0,7},{CR79,6,7} */ |
447 | #define LCD_VER_SCALING_FACTOR_REG_NUM_CLE 2 | 355 | #define LCD_VER_SCALING_FACTOR_REG_NUM_CLE 2 |
448 | 356 | ||
449 | /************************************************ | ||
450 | ***** Define IGA1 Display Timing ***** | ||
451 | ************************************************/ | ||
452 | struct io_register { | 357 | struct io_register { |
453 | u8 io_addr; | 358 | u8 io_addr; |
454 | u8 start_bit; | 359 | u8 start_bit; |
455 | u8 end_bit; | 360 | u8 end_bit; |
456 | }; | 361 | }; |
457 | 362 | ||
458 | /* IGA1 Horizontal Total */ | ||
459 | struct iga1_hor_total { | ||
460 | int reg_num; | ||
461 | struct io_register reg[IGA1_HOR_TOTAL_REG_NUM]; | ||
462 | }; | ||
463 | |||
464 | /* IGA1 Horizontal Addressable Video */ | ||
465 | struct iga1_hor_addr { | ||
466 | int reg_num; | ||
467 | struct io_register reg[IGA1_HOR_ADDR_REG_NUM]; | ||
468 | }; | ||
469 | |||
470 | /* IGA1 Horizontal Blank Start */ | ||
471 | struct iga1_hor_blank_start { | ||
472 | int reg_num; | ||
473 | struct io_register reg[IGA1_HOR_BLANK_START_REG_NUM]; | ||
474 | }; | ||
475 | |||
476 | /* IGA1 Horizontal Blank End */ | ||
477 | struct iga1_hor_blank_end { | ||
478 | int reg_num; | ||
479 | struct io_register reg[IGA1_HOR_BLANK_END_REG_NUM]; | ||
480 | }; | ||
481 | |||
482 | /* IGA1 Horizontal Sync Start */ | ||
483 | struct iga1_hor_sync_start { | ||
484 | int reg_num; | ||
485 | struct io_register reg[IGA1_HOR_SYNC_START_REG_NUM]; | ||
486 | }; | ||
487 | |||
488 | /* IGA1 Horizontal Sync End */ | ||
489 | struct iga1_hor_sync_end { | ||
490 | int reg_num; | ||
491 | struct io_register reg[IGA1_HOR_SYNC_END_REG_NUM]; | ||
492 | }; | ||
493 | |||
494 | /* IGA1 Vertical Total */ | ||
495 | struct iga1_ver_total { | ||
496 | int reg_num; | ||
497 | struct io_register reg[IGA1_VER_TOTAL_REG_NUM]; | ||
498 | }; | ||
499 | |||
500 | /* IGA1 Vertical Addressable Video */ | ||
501 | struct iga1_ver_addr { | ||
502 | int reg_num; | ||
503 | struct io_register reg[IGA1_VER_ADDR_REG_NUM]; | ||
504 | }; | ||
505 | |||
506 | /* IGA1 Vertical Blank Start */ | ||
507 | struct iga1_ver_blank_start { | ||
508 | int reg_num; | ||
509 | struct io_register reg[IGA1_VER_BLANK_START_REG_NUM]; | ||
510 | }; | ||
511 | |||
512 | /* IGA1 Vertical Blank End */ | ||
513 | struct iga1_ver_blank_end { | ||
514 | int reg_num; | ||
515 | struct io_register reg[IGA1_VER_BLANK_END_REG_NUM]; | ||
516 | }; | ||
517 | |||
518 | /* IGA1 Vertical Sync Start */ | ||
519 | struct iga1_ver_sync_start { | ||
520 | int reg_num; | ||
521 | struct io_register reg[IGA1_VER_SYNC_START_REG_NUM]; | ||
522 | }; | ||
523 | |||
524 | /* IGA1 Vertical Sync End */ | ||
525 | struct iga1_ver_sync_end { | ||
526 | int reg_num; | ||
527 | struct io_register reg[IGA1_VER_SYNC_END_REG_NUM]; | ||
528 | }; | ||
529 | |||
530 | /***************************************************** | 363 | /***************************************************** |
531 | ** Define IGA2 Shadow Display Timing **** | 364 | ** Define IGA2 Shadow Display Timing **** |
532 | *****************************************************/ | 365 | *****************************************************/ |
@@ -579,82 +412,6 @@ struct iga2_shadow_ver_sync_end { | |||
579 | struct io_register reg[IGA2_SHADOW_VER_SYNC_END_REG_NUM]; | 412 | struct io_register reg[IGA2_SHADOW_VER_SYNC_END_REG_NUM]; |
580 | }; | 413 | }; |
581 | 414 | ||
582 | /***************************************************** | ||
583 | ** Define IGA2 Display Timing **** | ||
584 | ******************************************************/ | ||
585 | |||
586 | /* IGA2 Horizontal Total */ | ||
587 | struct iga2_hor_total { | ||
588 | int reg_num; | ||
589 | struct io_register reg[IGA2_HOR_TOTAL_REG_NUM]; | ||
590 | }; | ||
591 | |||
592 | /* IGA2 Horizontal Addressable Video */ | ||
593 | struct iga2_hor_addr { | ||
594 | int reg_num; | ||
595 | struct io_register reg[IGA2_HOR_ADDR_REG_NUM]; | ||
596 | }; | ||
597 | |||
598 | /* IGA2 Horizontal Blank Start */ | ||
599 | struct iga2_hor_blank_start { | ||
600 | int reg_num; | ||
601 | struct io_register reg[IGA2_HOR_BLANK_START_REG_NUM]; | ||
602 | }; | ||
603 | |||
604 | /* IGA2 Horizontal Blank End */ | ||
605 | struct iga2_hor_blank_end { | ||
606 | int reg_num; | ||
607 | struct io_register reg[IGA2_HOR_BLANK_END_REG_NUM]; | ||
608 | }; | ||
609 | |||
610 | /* IGA2 Horizontal Sync Start */ | ||
611 | struct iga2_hor_sync_start { | ||
612 | int reg_num; | ||
613 | struct io_register reg[IGA2_HOR_SYNC_START_REG_NUM]; | ||
614 | }; | ||
615 | |||
616 | /* IGA2 Horizontal Sync End */ | ||
617 | struct iga2_hor_sync_end { | ||
618 | int reg_num; | ||
619 | struct io_register reg[IGA2_HOR_SYNC_END_REG_NUM]; | ||
620 | }; | ||
621 | |||
622 | /* IGA2 Vertical Total */ | ||
623 | struct iga2_ver_total { | ||
624 | int reg_num; | ||
625 | struct io_register reg[IGA2_VER_TOTAL_REG_NUM]; | ||
626 | }; | ||
627 | |||
628 | /* IGA2 Vertical Addressable Video */ | ||
629 | struct iga2_ver_addr { | ||
630 | int reg_num; | ||
631 | struct io_register reg[IGA2_VER_ADDR_REG_NUM]; | ||
632 | }; | ||
633 | |||
634 | /* IGA2 Vertical Blank Start */ | ||
635 | struct iga2_ver_blank_start { | ||
636 | int reg_num; | ||
637 | struct io_register reg[IGA2_VER_BLANK_START_REG_NUM]; | ||
638 | }; | ||
639 | |||
640 | /* IGA2 Vertical Blank End */ | ||
641 | struct iga2_ver_blank_end { | ||
642 | int reg_num; | ||
643 | struct io_register reg[IGA2_VER_BLANK_END_REG_NUM]; | ||
644 | }; | ||
645 | |||
646 | /* IGA2 Vertical Sync Start */ | ||
647 | struct iga2_ver_sync_start { | ||
648 | int reg_num; | ||
649 | struct io_register reg[IGA2_VER_SYNC_START_REG_NUM]; | ||
650 | }; | ||
651 | |||
652 | /* IGA2 Vertical Sync End */ | ||
653 | struct iga2_ver_sync_end { | ||
654 | int reg_num; | ||
655 | struct io_register reg[IGA2_VER_SYNC_END_REG_NUM]; | ||
656 | }; | ||
657 | |||
658 | /* IGA1 Fetch Count Register */ | 415 | /* IGA1 Fetch Count Register */ |
659 | struct iga1_fetch_count { | 416 | struct iga1_fetch_count { |
660 | int reg_num; | 417 | int reg_num; |
@@ -817,21 +574,6 @@ struct display_queue_expire_num { | |||
817 | iga2_display_queue_expire_num_reg; | 574 | iga2_display_queue_expire_num_reg; |
818 | }; | 575 | }; |
819 | 576 | ||
820 | struct iga1_crtc_timing { | ||
821 | struct iga1_hor_total hor_total; | ||
822 | struct iga1_hor_addr hor_addr; | ||
823 | struct iga1_hor_blank_start hor_blank_start; | ||
824 | struct iga1_hor_blank_end hor_blank_end; | ||
825 | struct iga1_hor_sync_start hor_sync_start; | ||
826 | struct iga1_hor_sync_end hor_sync_end; | ||
827 | struct iga1_ver_total ver_total; | ||
828 | struct iga1_ver_addr ver_addr; | ||
829 | struct iga1_ver_blank_start ver_blank_start; | ||
830 | struct iga1_ver_blank_end ver_blank_end; | ||
831 | struct iga1_ver_sync_start ver_sync_start; | ||
832 | struct iga1_ver_sync_end ver_sync_end; | ||
833 | }; | ||
834 | |||
835 | struct iga2_shadow_crtc_timing { | 577 | struct iga2_shadow_crtc_timing { |
836 | struct iga2_shadow_hor_total hor_total_shadow; | 578 | struct iga2_shadow_hor_total hor_total_shadow; |
837 | struct iga2_shadow_hor_blank_end hor_blank_end_shadow; | 579 | struct iga2_shadow_hor_blank_end hor_blank_end_shadow; |
@@ -843,21 +585,6 @@ struct iga2_shadow_crtc_timing { | |||
843 | struct iga2_shadow_ver_sync_end ver_sync_end_shadow; | 585 | struct iga2_shadow_ver_sync_end ver_sync_end_shadow; |
844 | }; | 586 | }; |
845 | 587 | ||
846 | struct iga2_crtc_timing { | ||
847 | struct iga2_hor_total hor_total; | ||
848 | struct iga2_hor_addr hor_addr; | ||
849 | struct iga2_hor_blank_start hor_blank_start; | ||
850 | struct iga2_hor_blank_end hor_blank_end; | ||
851 | struct iga2_hor_sync_start hor_sync_start; | ||
852 | struct iga2_hor_sync_end hor_sync_end; | ||
853 | struct iga2_ver_total ver_total; | ||
854 | struct iga2_ver_addr ver_addr; | ||
855 | struct iga2_ver_blank_start ver_blank_start; | ||
856 | struct iga2_ver_blank_end ver_blank_end; | ||
857 | struct iga2_ver_sync_start ver_sync_start; | ||
858 | struct iga2_ver_sync_end ver_sync_end; | ||
859 | }; | ||
860 | |||
861 | /* device ID */ | 588 | /* device ID */ |
862 | #define CLE266_FUNCTION3 0x3123 | 589 | #define CLE266_FUNCTION3 0x3123 |
863 | #define KM400_FUNCTION3 0x3205 | 590 | #define KM400_FUNCTION3 0x3205 |
@@ -910,9 +637,7 @@ extern int viafb_LCD_ON; | |||
910 | extern int viafb_DVI_ON; | 637 | extern int viafb_DVI_ON; |
911 | extern int viafb_hotplug; | 638 | extern int viafb_hotplug; |
912 | 639 | ||
913 | void viafb_fill_crtc_timing(struct crt_mode_table *crt_table, | 640 | void viafb_fill_crtc_timing(const struct fb_var_screeninfo *var, int iga); |
914 | struct VideoModeTable *video_mode, int bpp_byte, int set_iga); | ||
915 | |||
916 | void viafb_set_vclock(u32 CLK, int set_iga); | 641 | void viafb_set_vclock(u32 CLK, int set_iga); |
917 | void viafb_load_reg(int timing_value, int viafb_load_reg_num, | 642 | void viafb_load_reg(int timing_value, int viafb_load_reg_num, |
918 | struct io_register *reg, | 643 | struct io_register *reg, |
@@ -932,13 +657,11 @@ void viafb_load_FIFO_reg(int set_iga, int hor_active, int ver_active); | |||
932 | void viafb_set_dpa_gfx(int output_interface, struct GFX_DPA_SETTING\ | 657 | void viafb_set_dpa_gfx(int output_interface, struct GFX_DPA_SETTING\ |
933 | *p_gfx_dpa_setting); | 658 | *p_gfx_dpa_setting); |
934 | 659 | ||
935 | int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp, | 660 | int viafb_setmode(int video_bpp, int video_bpp1); |
936 | struct VideoModeTable *vmode_tbl1, int video_bpp1); | 661 | void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, |
937 | void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, int refresh, | 662 | struct crt_mode_table *mode); |
938 | struct VideoModeTable *vmode_tbl); | ||
939 | void __devinit viafb_init_chip_info(int chip_type); | 663 | void __devinit viafb_init_chip_info(int chip_type); |
940 | void __devinit viafb_init_dac(int set_iga); | 664 | void __devinit viafb_init_dac(int set_iga); |
941 | int viafb_get_pixclock(int hres, int vres, int vmode_refresh); | ||
942 | int viafb_get_refresh(int hres, int vres, u32 float_refresh); | 665 | int viafb_get_refresh(int hres, int vres, u32 float_refresh); |
943 | void viafb_update_device_setting(int hres, int vres, int bpp, int flag); | 666 | void viafb_update_device_setting(int hres, int vres, int bpp, int flag); |
944 | 667 | ||
diff --git a/drivers/video/via/lcd.c b/drivers/video/via/lcd.c index 6e06981d638b..5f3b4e394e82 100644 --- a/drivers/video/via/lcd.c +++ b/drivers/video/via/lcd.c | |||
@@ -548,9 +548,8 @@ static void lcd_patch_skew(struct lvds_setting_information | |||
548 | } | 548 | } |
549 | 549 | ||
550 | /* LCD Set Mode */ | 550 | /* LCD Set Mode */ |
551 | void viafb_lcd_set_mode(struct crt_mode_table *mode_crt_table, | 551 | void viafb_lcd_set_mode(struct lvds_setting_information *plvds_setting_info, |
552 | struct lvds_setting_information *plvds_setting_info, | 552 | struct lvds_chip_information *plvds_chip_info) |
553 | struct lvds_chip_information *plvds_chip_info) | ||
554 | { | 553 | { |
555 | int set_iga = plvds_setting_info->iga_path; | 554 | int set_iga = plvds_setting_info->iga_path; |
556 | int mode_bpp = plvds_setting_info->bpp; | 555 | int mode_bpp = plvds_setting_info->bpp; |
@@ -559,16 +558,15 @@ void viafb_lcd_set_mode(struct crt_mode_table *mode_crt_table, | |||
559 | int panel_hres = plvds_setting_info->lcd_panel_hres; | 558 | int panel_hres = plvds_setting_info->lcd_panel_hres; |
560 | int panel_vres = plvds_setting_info->lcd_panel_vres; | 559 | int panel_vres = plvds_setting_info->lcd_panel_vres; |
561 | u32 clock; | 560 | u32 clock; |
562 | struct display_timing mode_crt_reg, panel_crt_reg; | 561 | struct display_timing mode_crt_reg, panel_crt_reg, timing; |
563 | struct crt_mode_table *panel_crt_table = NULL; | 562 | struct crt_mode_table *mode_crt_table, *panel_crt_table; |
564 | struct VideoModeTable *vmode_tbl = viafb_get_mode(panel_hres, | ||
565 | panel_vres); | ||
566 | 563 | ||
567 | DEBUG_MSG(KERN_INFO "viafb_lcd_set_mode!!\n"); | 564 | DEBUG_MSG(KERN_INFO "viafb_lcd_set_mode!!\n"); |
568 | /* Get mode table */ | 565 | /* Get mode table */ |
566 | mode_crt_table = viafb_get_best_mode(set_hres, set_vres, 60); | ||
569 | mode_crt_reg = mode_crt_table->crtc; | 567 | mode_crt_reg = mode_crt_table->crtc; |
570 | /* Get panel table Pointer */ | 568 | /* Get panel table Pointer */ |
571 | panel_crt_table = vmode_tbl->crtc; | 569 | panel_crt_table = viafb_get_best_mode(panel_hres, panel_vres, 60); |
572 | panel_crt_reg = panel_crt_table->crtc; | 570 | panel_crt_reg = panel_crt_table->crtc; |
573 | DEBUG_MSG(KERN_INFO "bellow viafb_lcd_set_mode!!\n"); | 571 | DEBUG_MSG(KERN_INFO "bellow viafb_lcd_set_mode!!\n"); |
574 | if (VT1636_LVDS == plvds_chip_info->lvds_chip_name) | 572 | if (VT1636_LVDS == plvds_chip_info->lvds_chip_name) |
@@ -576,31 +574,28 @@ void viafb_lcd_set_mode(struct crt_mode_table *mode_crt_table, | |||
576 | clock = panel_crt_reg.hor_total * panel_crt_reg.ver_total | 574 | clock = panel_crt_reg.hor_total * panel_crt_reg.ver_total |
577 | * panel_crt_table->refresh_rate; | 575 | * panel_crt_table->refresh_rate; |
578 | plvds_setting_info->vclk = clock; | 576 | plvds_setting_info->vclk = clock; |
579 | if (set_iga == IGA1) { | 577 | |
580 | /* IGA1 doesn't have LCD scaling, so set it as centering. */ | 578 | if (set_iga == IGA2 && (set_hres < panel_hres || set_vres < panel_vres) |
581 | viafb_load_crtc_timing(lcd_centering_timging | 579 | && plvds_setting_info->display_method == LCD_EXPANDSION) { |
582 | (mode_crt_reg, panel_crt_reg), IGA1); | 580 | timing = panel_crt_reg; |
581 | load_lcd_scaling(set_hres, set_vres, panel_hres, panel_vres); | ||
583 | } else { | 582 | } else { |
584 | /* Expansion */ | 583 | timing = lcd_centering_timging(mode_crt_reg, panel_crt_reg); |
585 | if (plvds_setting_info->display_method == LCD_EXPANDSION | 584 | if (set_iga == IGA2) |
586 | && (set_hres < panel_hres || set_vres < panel_vres)) { | 585 | /* disable scaling */ |
587 | /* expansion timing IGA2 loaded panel set timing*/ | 586 | via_write_reg_mask(VIACR, 0x79, 0x00, |
588 | viafb_load_crtc_timing(panel_crt_reg, IGA2); | ||
589 | DEBUG_MSG(KERN_INFO "viafb_load_crtc_timing!!\n"); | ||
590 | load_lcd_scaling(set_hres, set_vres, panel_hres, | ||
591 | panel_vres); | ||
592 | DEBUG_MSG(KERN_INFO "load_lcd_scaling!!\n"); | ||
593 | } else { /* Centering */ | ||
594 | /* centering timing IGA2 always loaded panel | ||
595 | and mode releative timing */ | ||
596 | viafb_load_crtc_timing(lcd_centering_timging | ||
597 | (mode_crt_reg, panel_crt_reg), IGA2); | ||
598 | viafb_write_reg_mask(CR79, VIACR, 0x00, | ||
599 | BIT0 + BIT1 + BIT2); | 587 | BIT0 + BIT1 + BIT2); |
600 | /* LCD scaling disabled */ | ||
601 | } | ||
602 | } | 588 | } |
603 | 589 | ||
590 | timing.hor_blank_end += timing.hor_blank_start; | ||
591 | timing.hor_sync_end += timing.hor_sync_start; | ||
592 | timing.ver_blank_end += timing.ver_blank_start; | ||
593 | timing.ver_sync_end += timing.ver_sync_start; | ||
594 | if (set_iga == IGA1) | ||
595 | via_set_primary_timing(&timing); | ||
596 | else if (set_iga == IGA2) | ||
597 | via_set_secondary_timing(&timing); | ||
598 | |||
604 | /* Fetch count for IGA2 only */ | 599 | /* Fetch count for IGA2 only */ |
605 | viafb_load_fetch_count_reg(set_hres, mode_bpp / 8, set_iga); | 600 | viafb_load_fetch_count_reg(set_hres, mode_bpp / 8, set_iga); |
606 | 601 | ||
diff --git a/drivers/video/via/lcd.h b/drivers/video/via/lcd.h index 75f60a655b0e..77ca7b862e68 100644 --- a/drivers/video/via/lcd.h +++ b/drivers/video/via/lcd.h | |||
@@ -76,16 +76,13 @@ void __devinit viafb_init_lvds_output_interface(struct lvds_chip_information | |||
76 | *plvds_chip_info, | 76 | *plvds_chip_info, |
77 | struct lvds_setting_information | 77 | struct lvds_setting_information |
78 | *plvds_setting_info); | 78 | *plvds_setting_info); |
79 | void viafb_lcd_set_mode(struct crt_mode_table *mode_crt_table, | 79 | void viafb_lcd_set_mode(struct lvds_setting_information *plvds_setting_info, |
80 | struct lvds_setting_information *plvds_setting_info, | 80 | struct lvds_chip_information *plvds_chip_info); |
81 | struct lvds_chip_information *plvds_chip_info); | ||
82 | bool __devinit viafb_lvds_trasmitter_identify(void); | 81 | bool __devinit viafb_lvds_trasmitter_identify(void); |
83 | void viafb_init_lvds_output_interface(struct lvds_chip_information | 82 | void viafb_init_lvds_output_interface(struct lvds_chip_information |
84 | *plvds_chip_info, | 83 | *plvds_chip_info, |
85 | struct lvds_setting_information | 84 | struct lvds_setting_information |
86 | *plvds_setting_info); | 85 | *plvds_setting_info); |
87 | bool viafb_lcd_get_mobile_state(bool *mobile); | 86 | bool viafb_lcd_get_mobile_state(bool *mobile); |
88 | void viafb_load_crtc_timing(struct display_timing device_timing, | ||
89 | int set_iga); | ||
90 | 87 | ||
91 | #endif /* __LCD_H__ */ | 88 | #endif /* __LCD_H__ */ |
diff --git a/drivers/video/via/share.h b/drivers/video/via/share.h index 61b0bd596b85..69d882cbe709 100644 --- a/drivers/video/via/share.h +++ b/drivers/video/via/share.h | |||
@@ -22,6 +22,8 @@ | |||
22 | #ifndef __SHARE_H__ | 22 | #ifndef __SHARE_H__ |
23 | #define __SHARE_H__ | 23 | #define __SHARE_H__ |
24 | 24 | ||
25 | #include "via_modesetting.h" | ||
26 | |||
25 | /* Define Bit Field */ | 27 | /* Define Bit Field */ |
26 | #define BIT0 0x01 | 28 | #define BIT0 0x01 |
27 | #define BIT1 0x02 | 29 | #define BIT1 0x02 |
@@ -634,10 +636,6 @@ | |||
634 | #define V_SYNC_SATRT_SHADOW_INDEX 18 | 636 | #define V_SYNC_SATRT_SHADOW_INDEX 18 |
635 | #define V_SYNC_END_SHADOW_INDEX 19 | 637 | #define V_SYNC_END_SHADOW_INDEX 19 |
636 | 638 | ||
637 | /* Definition Video Mode Pixel Clock (picoseconds) | ||
638 | */ | ||
639 | #define RES_640X480_60HZ_PIXCLOCK 39722 | ||
640 | |||
641 | /* LCD display method | 639 | /* LCD display method |
642 | */ | 640 | */ |
643 | #define LCD_EXPANDSION 0x00 | 641 | #define LCD_EXPANDSION 0x00 |
@@ -648,23 +646,6 @@ | |||
648 | #define LCD_OPENLDI 0x00 | 646 | #define LCD_OPENLDI 0x00 |
649 | #define LCD_SPWG 0x01 | 647 | #define LCD_SPWG 0x01 |
650 | 648 | ||
651 | /* Define display timing | ||
652 | */ | ||
653 | struct display_timing { | ||
654 | u16 hor_total; | ||
655 | u16 hor_addr; | ||
656 | u16 hor_blank_start; | ||
657 | u16 hor_blank_end; | ||
658 | u16 hor_sync_start; | ||
659 | u16 hor_sync_end; | ||
660 | u16 ver_total; | ||
661 | u16 ver_addr; | ||
662 | u16 ver_blank_start; | ||
663 | u16 ver_blank_end; | ||
664 | u16 ver_sync_start; | ||
665 | u16 ver_sync_end; | ||
666 | }; | ||
667 | |||
668 | struct crt_mode_table { | 649 | struct crt_mode_table { |
669 | int refresh_rate; | 650 | int refresh_rate; |
670 | int h_sync_polarity; | 651 | int h_sync_polarity; |
diff --git a/drivers/video/via/via-core.c b/drivers/video/via/via-core.c index eb112b621735..dd58b530c0df 100644 --- a/drivers/video/via/via-core.c +++ b/drivers/video/via/via-core.c | |||
@@ -35,7 +35,7 @@ static struct via_port_cfg adap_configs[] = { | |||
35 | * The OLPC XO-1.5 puts the camera power and reset lines onto | 35 | * The OLPC XO-1.5 puts the camera power and reset lines onto |
36 | * GPIO 2C. | 36 | * GPIO 2C. |
37 | */ | 37 | */ |
38 | static const struct via_port_cfg olpc_adap_configs[] = { | 38 | static struct via_port_cfg olpc_adap_configs[] = { |
39 | [VIA_PORT_26] = { VIA_PORT_I2C, VIA_MODE_I2C, VIASR, 0x26 }, | 39 | [VIA_PORT_26] = { VIA_PORT_I2C, VIA_MODE_I2C, VIASR, 0x26 }, |
40 | [VIA_PORT_31] = { VIA_PORT_I2C, VIA_MODE_I2C, VIASR, 0x31 }, | 40 | [VIA_PORT_31] = { VIA_PORT_I2C, VIA_MODE_I2C, VIASR, 0x31 }, |
41 | [VIA_PORT_25] = { VIA_PORT_GPIO, VIA_MODE_GPIO, VIASR, 0x25 }, | 41 | [VIA_PORT_25] = { VIA_PORT_GPIO, VIA_MODE_GPIO, VIASR, 0x25 }, |
diff --git a/drivers/video/via/via_modesetting.c b/drivers/video/via/via_modesetting.c index 3cddcff88ab9..0e431aee17bb 100644 --- a/drivers/video/via/via_modesetting.c +++ b/drivers/video/via/via_modesetting.c | |||
@@ -29,6 +29,110 @@ | |||
29 | #include "share.h" | 29 | #include "share.h" |
30 | #include "debug.h" | 30 | #include "debug.h" |
31 | 31 | ||
32 | |||
33 | void via_set_primary_timing(const struct display_timing *timing) | ||
34 | { | ||
35 | struct display_timing raw; | ||
36 | |||
37 | raw.hor_total = timing->hor_total / 8 - 5; | ||
38 | raw.hor_addr = timing->hor_addr / 8 - 1; | ||
39 | raw.hor_blank_start = timing->hor_blank_start / 8 - 1; | ||
40 | raw.hor_blank_end = timing->hor_blank_end / 8 - 1; | ||
41 | raw.hor_sync_start = timing->hor_sync_start / 8; | ||
42 | raw.hor_sync_end = timing->hor_sync_end / 8; | ||
43 | raw.ver_total = timing->ver_total - 2; | ||
44 | raw.ver_addr = timing->ver_addr - 1; | ||
45 | raw.ver_blank_start = timing->ver_blank_start - 1; | ||
46 | raw.ver_blank_end = timing->ver_blank_end - 1; | ||
47 | raw.ver_sync_start = timing->ver_sync_start - 1; | ||
48 | raw.ver_sync_end = timing->ver_sync_end - 1; | ||
49 | |||
50 | /* unlock timing registers */ | ||
51 | via_write_reg_mask(VIACR, 0x11, 0x00, 0x80); | ||
52 | |||
53 | via_write_reg(VIACR, 0x00, raw.hor_total & 0xFF); | ||
54 | via_write_reg(VIACR, 0x01, raw.hor_addr & 0xFF); | ||
55 | via_write_reg(VIACR, 0x02, raw.hor_blank_start & 0xFF); | ||
56 | via_write_reg_mask(VIACR, 0x03, raw.hor_blank_end & 0x1F, 0x1F); | ||
57 | via_write_reg(VIACR, 0x04, raw.hor_sync_start & 0xFF); | ||
58 | via_write_reg_mask(VIACR, 0x05, (raw.hor_sync_end & 0x1F) | ||
59 | | (raw.hor_blank_end << (7 - 5) & 0x80), 0x9F); | ||
60 | via_write_reg(VIACR, 0x06, raw.ver_total & 0xFF); | ||
61 | via_write_reg_mask(VIACR, 0x07, (raw.ver_total >> 8 & 0x01) | ||
62 | | (raw.ver_addr >> (8 - 1) & 0x02) | ||
63 | | (raw.ver_sync_start >> (8 - 2) & 0x04) | ||
64 | | (raw.ver_blank_start >> (8 - 3) & 0x08) | ||
65 | | (raw.ver_total >> (9 - 5) & 0x20) | ||
66 | | (raw.ver_addr >> (9 - 6) & 0x40) | ||
67 | | (raw.ver_sync_start >> (9 - 7) & 0x80), 0xEF); | ||
68 | via_write_reg_mask(VIACR, 0x09, raw.ver_blank_start >> (9 - 5) & 0x20, | ||
69 | 0x20); | ||
70 | via_write_reg(VIACR, 0x10, raw.ver_sync_start & 0xFF); | ||
71 | via_write_reg_mask(VIACR, 0x11, raw.ver_sync_end & 0x0F, 0x0F); | ||
72 | via_write_reg(VIACR, 0x12, raw.ver_addr & 0xFF); | ||
73 | via_write_reg(VIACR, 0x15, raw.ver_blank_start & 0xFF); | ||
74 | via_write_reg(VIACR, 0x16, raw.ver_blank_end & 0xFF); | ||
75 | via_write_reg_mask(VIACR, 0x33, (raw.hor_sync_start >> (8 - 4) & 0x10) | ||
76 | | (raw.hor_blank_end >> (6 - 5) & 0x20), 0x30); | ||
77 | via_write_reg_mask(VIACR, 0x35, (raw.ver_total >> 10 & 0x01) | ||
78 | | (raw.ver_sync_start >> (10 - 1) & 0x02) | ||
79 | | (raw.ver_addr >> (10 - 2) & 0x04) | ||
80 | | (raw.ver_blank_start >> (10 - 3) & 0x08), 0x0F); | ||
81 | via_write_reg_mask(VIACR, 0x36, raw.hor_total >> (8 - 3) & 0x08, 0x08); | ||
82 | |||
83 | /* lock timing registers */ | ||
84 | via_write_reg_mask(VIACR, 0x11, 0x80, 0x80); | ||
85 | |||
86 | /* reset timing control */ | ||
87 | via_write_reg_mask(VIACR, 0x17, 0x00, 0x80); | ||
88 | via_write_reg_mask(VIACR, 0x17, 0x80, 0x80); | ||
89 | } | ||
90 | |||
91 | void via_set_secondary_timing(const struct display_timing *timing) | ||
92 | { | ||
93 | struct display_timing raw; | ||
94 | |||
95 | raw.hor_total = timing->hor_total - 1; | ||
96 | raw.hor_addr = timing->hor_addr - 1; | ||
97 | raw.hor_blank_start = timing->hor_blank_start - 1; | ||
98 | raw.hor_blank_end = timing->hor_blank_end - 1; | ||
99 | raw.hor_sync_start = timing->hor_sync_start - 1; | ||
100 | raw.hor_sync_end = timing->hor_sync_end - 1; | ||
101 | raw.ver_total = timing->ver_total - 1; | ||
102 | raw.ver_addr = timing->ver_addr - 1; | ||
103 | raw.ver_blank_start = timing->ver_blank_start - 1; | ||
104 | raw.ver_blank_end = timing->ver_blank_end - 1; | ||
105 | raw.ver_sync_start = timing->ver_sync_start - 1; | ||
106 | raw.ver_sync_end = timing->ver_sync_end - 1; | ||
107 | |||
108 | via_write_reg(VIACR, 0x50, raw.hor_total & 0xFF); | ||
109 | via_write_reg(VIACR, 0x51, raw.hor_addr & 0xFF); | ||
110 | via_write_reg(VIACR, 0x52, raw.hor_blank_start & 0xFF); | ||
111 | via_write_reg(VIACR, 0x53, raw.hor_blank_end & 0xFF); | ||
112 | via_write_reg(VIACR, 0x54, (raw.hor_blank_start >> 8 & 0x07) | ||
113 | | (raw.hor_blank_end >> (8 - 3) & 0x38) | ||
114 | | (raw.hor_sync_start >> (8 - 6) & 0xC0)); | ||
115 | via_write_reg_mask(VIACR, 0x55, (raw.hor_total >> 8 & 0x0F) | ||
116 | | (raw.hor_addr >> (8 - 4) & 0x70), 0x7F); | ||
117 | via_write_reg(VIACR, 0x56, raw.hor_sync_start & 0xFF); | ||
118 | via_write_reg(VIACR, 0x57, raw.hor_sync_end & 0xFF); | ||
119 | via_write_reg(VIACR, 0x58, raw.ver_total & 0xFF); | ||
120 | via_write_reg(VIACR, 0x59, raw.ver_addr & 0xFF); | ||
121 | via_write_reg(VIACR, 0x5A, raw.ver_blank_start & 0xFF); | ||
122 | via_write_reg(VIACR, 0x5B, raw.ver_blank_end & 0xFF); | ||
123 | via_write_reg(VIACR, 0x5C, (raw.ver_blank_start >> 8 & 0x07) | ||
124 | | (raw.ver_blank_end >> (8 - 3) & 0x38) | ||
125 | | (raw.hor_sync_end >> (8 - 6) & 0x40) | ||
126 | | (raw.hor_sync_start >> (10 - 7) & 0x80)); | ||
127 | via_write_reg(VIACR, 0x5D, (raw.ver_total >> 8 & 0x07) | ||
128 | | (raw.ver_addr >> (8 - 3) & 0x38) | ||
129 | | (raw.hor_blank_end >> (11 - 6) & 0x40) | ||
130 | | (raw.hor_sync_start >> (11 - 7) & 0x80)); | ||
131 | via_write_reg(VIACR, 0x5E, raw.ver_sync_start & 0xFF); | ||
132 | via_write_reg(VIACR, 0x5F, (raw.ver_sync_end & 0x1F) | ||
133 | | (raw.ver_sync_start >> (8 - 5) & 0xE0)); | ||
134 | } | ||
135 | |||
32 | void via_set_primary_address(u32 addr) | 136 | void via_set_primary_address(u32 addr) |
33 | { | 137 | { |
34 | DEBUG_MSG(KERN_DEBUG "via_set_primary_address(0x%08X)\n", addr); | 138 | DEBUG_MSG(KERN_DEBUG "via_set_primary_address(0x%08X)\n", addr); |
diff --git a/drivers/video/via/via_modesetting.h b/drivers/video/via/via_modesetting.h index ae35cfdeb37c..06e09fe351ae 100644 --- a/drivers/video/via/via_modesetting.h +++ b/drivers/video/via/via_modesetting.h | |||
@@ -28,6 +28,29 @@ | |||
28 | 28 | ||
29 | #include <linux/types.h> | 29 | #include <linux/types.h> |
30 | 30 | ||
31 | |||
32 | #define VIA_PITCH_SIZE (1<<3) | ||
33 | #define VIA_PITCH_MAX 0x3FF8 | ||
34 | |||
35 | |||
36 | struct display_timing { | ||
37 | u16 hor_total; | ||
38 | u16 hor_addr; | ||
39 | u16 hor_blank_start; | ||
40 | u16 hor_blank_end; | ||
41 | u16 hor_sync_start; | ||
42 | u16 hor_sync_end; | ||
43 | u16 ver_total; | ||
44 | u16 ver_addr; | ||
45 | u16 ver_blank_start; | ||
46 | u16 ver_blank_end; | ||
47 | u16 ver_sync_start; | ||
48 | u16 ver_sync_end; | ||
49 | }; | ||
50 | |||
51 | |||
52 | void via_set_primary_timing(const struct display_timing *timing); | ||
53 | void via_set_secondary_timing(const struct display_timing *timing); | ||
31 | void via_set_primary_address(u32 addr); | 54 | void via_set_primary_address(u32 addr); |
32 | void via_set_secondary_address(u32 addr); | 55 | void via_set_secondary_address(u32 addr); |
33 | void via_set_primary_pitch(u32 pitch); | 56 | void via_set_primary_pitch(u32 pitch); |
diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c index 53aa4430d86e..a13c258bd32f 100644 --- a/drivers/video/via/viafbdev.c +++ b/drivers/video/via/viafbdev.c | |||
@@ -38,8 +38,6 @@ static char *viafb_mode1; | |||
38 | static int viafb_bpp = 32; | 38 | static int viafb_bpp = 32; |
39 | static int viafb_bpp1 = 32; | 39 | static int viafb_bpp1 = 32; |
40 | 40 | ||
41 | static unsigned int viafb_second_xres = 640; | ||
42 | static unsigned int viafb_second_yres = 480; | ||
43 | static unsigned int viafb_second_offset; | 41 | static unsigned int viafb_second_offset; |
44 | static int viafb_second_size; | 42 | static int viafb_second_size; |
45 | 43 | ||
@@ -151,7 +149,8 @@ static void viafb_update_fix(struct fb_info *info) | |||
151 | 149 | ||
152 | info->fix.visual = | 150 | info->fix.visual = |
153 | bpp == 8 ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR; | 151 | bpp == 8 ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR; |
154 | info->fix.line_length = (info->var.xres_virtual * bpp / 8 + 7) & ~7; | 152 | info->fix.line_length = ALIGN(info->var.xres_virtual * bpp / 8, |
153 | VIA_PITCH_SIZE); | ||
155 | } | 154 | } |
156 | 155 | ||
157 | static void viafb_setup_fixinfo(struct fb_fix_screeninfo *fix, | 156 | static void viafb_setup_fixinfo(struct fb_fix_screeninfo *fix, |
@@ -200,7 +199,6 @@ static int viafb_check_var(struct fb_var_screeninfo *var, | |||
200 | struct fb_info *info) | 199 | struct fb_info *info) |
201 | { | 200 | { |
202 | int depth, refresh; | 201 | int depth, refresh; |
203 | struct VideoModeTable *vmode_entry; | ||
204 | struct viafb_par *ppar = info->par; | 202 | struct viafb_par *ppar = info->par; |
205 | u32 line; | 203 | u32 line; |
206 | 204 | ||
@@ -210,8 +208,10 @@ static int viafb_check_var(struct fb_var_screeninfo *var, | |||
210 | if (var->vmode & FB_VMODE_INTERLACED || var->vmode & FB_VMODE_DOUBLE) | 208 | if (var->vmode & FB_VMODE_INTERLACED || var->vmode & FB_VMODE_DOUBLE) |
211 | return -EINVAL; | 209 | return -EINVAL; |
212 | 210 | ||
213 | vmode_entry = viafb_get_mode(var->xres, var->yres); | 211 | /* the refresh rate is not important here, as we only want to know |
214 | if (!vmode_entry) { | 212 | * whether the resolution exists |
213 | */ | ||
214 | if (!viafb_get_best_mode(var->xres, var->yres, 60)) { | ||
215 | DEBUG_MSG(KERN_INFO | 215 | DEBUG_MSG(KERN_INFO |
216 | "viafb: Mode %dx%dx%d not supported!!\n", | 216 | "viafb: Mode %dx%dx%d not supported!!\n", |
217 | var->xres, var->yres, var->bits_per_pixel); | 217 | var->xres, var->yres, var->bits_per_pixel); |
@@ -238,8 +238,12 @@ static int viafb_check_var(struct fb_var_screeninfo *var, | |||
238 | depth = 24; | 238 | depth = 24; |
239 | 239 | ||
240 | viafb_fill_var_color_info(var, depth); | 240 | viafb_fill_var_color_info(var, depth); |
241 | line = (var->xres_virtual * var->bits_per_pixel / 8 + 7) & ~7; | 241 | if (var->xres_virtual < var->xres) |
242 | if (line * var->yres_virtual > ppar->memsize) | 242 | var->xres_virtual = var->xres; |
243 | |||
244 | line = ALIGN(var->xres_virtual * var->bits_per_pixel / 8, | ||
245 | VIA_PITCH_SIZE); | ||
246 | if (line > VIA_PITCH_MAX || line * var->yres_virtual > ppar->memsize) | ||
243 | return -EINVAL; | 247 | return -EINVAL; |
244 | 248 | ||
245 | /* Based on var passed in to calculate the refresh, | 249 | /* Based on var passed in to calculate the refresh, |
@@ -249,7 +253,8 @@ static int viafb_check_var(struct fb_var_screeninfo *var, | |||
249 | get_var_refresh(var)); | 253 | get_var_refresh(var)); |
250 | 254 | ||
251 | /* Adjust var according to our driver's own table */ | 255 | /* Adjust var according to our driver's own table */ |
252 | viafb_fill_var_timing_info(var, refresh, vmode_entry); | 256 | viafb_fill_var_timing_info(var, |
257 | viafb_get_best_mode(var->xres, var->yres, refresh)); | ||
253 | if (var->accel_flags & FB_ACCELF_TEXT && | 258 | if (var->accel_flags & FB_ACCELF_TEXT && |
254 | !ppar->shared->vdev->engine_mmio) | 259 | !ppar->shared->vdev->engine_mmio) |
255 | var->accel_flags = 0; | 260 | var->accel_flags = 0; |
@@ -260,7 +265,6 @@ static int viafb_check_var(struct fb_var_screeninfo *var, | |||
260 | static int viafb_set_par(struct fb_info *info) | 265 | static int viafb_set_par(struct fb_info *info) |
261 | { | 266 | { |
262 | struct viafb_par *viapar = info->par; | 267 | struct viafb_par *viapar = info->par; |
263 | struct VideoModeTable *vmode_entry, *vmode_entry1 = NULL; | ||
264 | int refresh; | 268 | int refresh; |
265 | DEBUG_MSG(KERN_INFO "viafb_set_par!\n"); | 269 | DEBUG_MSG(KERN_INFO "viafb_set_par!\n"); |
266 | 270 | ||
@@ -269,10 +273,7 @@ static int viafb_set_par(struct fb_info *info) | |||
269 | viafb_update_device_setting(viafbinfo->var.xres, viafbinfo->var.yres, | 273 | viafb_update_device_setting(viafbinfo->var.xres, viafbinfo->var.yres, |
270 | viafbinfo->var.bits_per_pixel, 0); | 274 | viafbinfo->var.bits_per_pixel, 0); |
271 | 275 | ||
272 | vmode_entry = viafb_get_mode(viafbinfo->var.xres, viafbinfo->var.yres); | ||
273 | if (viafb_dual_fb) { | 276 | if (viafb_dual_fb) { |
274 | vmode_entry1 = viafb_get_mode(viafbinfo1->var.xres, | ||
275 | viafbinfo1->var.yres); | ||
276 | viafb_update_device_setting(viafbinfo1->var.xres, | 277 | viafb_update_device_setting(viafbinfo1->var.xres, |
277 | viafbinfo1->var.yres, viafbinfo1->var.bits_per_pixel, | 278 | viafbinfo1->var.yres, viafbinfo1->var.bits_per_pixel, |
278 | 1); | 279 | 1); |
@@ -280,8 +281,6 @@ static int viafb_set_par(struct fb_info *info) | |||
280 | DEBUG_MSG(KERN_INFO | 281 | DEBUG_MSG(KERN_INFO |
281 | "viafb_second_xres = %d, viafb_second_yres = %d, bpp = %d\n", | 282 | "viafb_second_xres = %d, viafb_second_yres = %d, bpp = %d\n", |
282 | viafb_second_xres, viafb_second_yres, viafb_bpp1); | 283 | viafb_second_xres, viafb_second_yres, viafb_bpp1); |
283 | vmode_entry1 = viafb_get_mode(viafb_second_xres, | ||
284 | viafb_second_yres); | ||
285 | 284 | ||
286 | viafb_update_device_setting(viafb_second_xres, | 285 | viafb_update_device_setting(viafb_second_xres, |
287 | viafb_second_yres, viafb_bpp1, 1); | 286 | viafb_second_yres, viafb_bpp1, 1); |
@@ -289,7 +288,8 @@ static int viafb_set_par(struct fb_info *info) | |||
289 | 288 | ||
290 | refresh = viafb_get_refresh(info->var.xres, info->var.yres, | 289 | refresh = viafb_get_refresh(info->var.xres, info->var.yres, |
291 | get_var_refresh(&info->var)); | 290 | get_var_refresh(&info->var)); |
292 | if (vmode_entry) { | 291 | if (viafb_get_best_mode(viafbinfo->var.xres, viafbinfo->var.yres, |
292 | refresh)) { | ||
293 | if (viafb_dual_fb && viapar->iga_path == IGA2) { | 293 | if (viafb_dual_fb && viapar->iga_path == IGA2) { |
294 | viafb_bpp1 = info->var.bits_per_pixel; | 294 | viafb_bpp1 = info->var.bits_per_pixel; |
295 | viafb_refresh1 = refresh; | 295 | viafb_refresh1 = refresh; |
@@ -302,8 +302,7 @@ static int viafb_set_par(struct fb_info *info) | |||
302 | info->flags &= ~FBINFO_HWACCEL_DISABLED; | 302 | info->flags &= ~FBINFO_HWACCEL_DISABLED; |
303 | else | 303 | else |
304 | info->flags |= FBINFO_HWACCEL_DISABLED; | 304 | info->flags |= FBINFO_HWACCEL_DISABLED; |
305 | viafb_setmode(vmode_entry, info->var.bits_per_pixel, | 305 | viafb_setmode(info->var.bits_per_pixel, viafb_bpp1); |
306 | vmode_entry1, viafb_bpp1); | ||
307 | viafb_pan_display(&info->var, info); | 306 | viafb_pan_display(&info->var, info); |
308 | } | 307 | } |
309 | 308 | ||
@@ -348,8 +347,9 @@ static int viafb_pan_display(struct fb_var_screeninfo *var, | |||
348 | struct fb_info *info) | 347 | struct fb_info *info) |
349 | { | 348 | { |
350 | struct viafb_par *viapar = info->par; | 349 | struct viafb_par *viapar = info->par; |
351 | u32 vram_addr = (var->yoffset * var->xres_virtual + var->xoffset) | 350 | u32 vram_addr = viapar->vram_addr |
352 | * (var->bits_per_pixel / 8) + viapar->vram_addr; | 351 | + var->yoffset * info->fix.line_length |
352 | + var->xoffset * info->var.bits_per_pixel / 8; | ||
353 | 353 | ||
354 | DEBUG_MSG(KERN_DEBUG "viafb_pan_display, address = %d\n", vram_addr); | 354 | DEBUG_MSG(KERN_DEBUG "viafb_pan_display, address = %d\n", vram_addr); |
355 | if (!viafb_dual_fb) { | 355 | if (!viafb_dual_fb) { |
@@ -1158,7 +1158,8 @@ static ssize_t viafb_dvp0_proc_write(struct file *file, | |||
1158 | for (i = 0; i < 3; i++) { | 1158 | for (i = 0; i < 3; i++) { |
1159 | value = strsep(&pbuf, " "); | 1159 | value = strsep(&pbuf, " "); |
1160 | if (value != NULL) { | 1160 | if (value != NULL) { |
1161 | strict_strtoul(value, 0, (unsigned long *)®_val); | 1161 | if (kstrtou8(value, 0, ®_val) < 0) |
1162 | return -EINVAL; | ||
1162 | DEBUG_MSG(KERN_INFO "DVP0:reg_val[%l]=:%x\n", i, | 1163 | DEBUG_MSG(KERN_INFO "DVP0:reg_val[%l]=:%x\n", i, |
1163 | reg_val); | 1164 | reg_val); |
1164 | switch (i) { | 1165 | switch (i) { |
@@ -1228,7 +1229,8 @@ static ssize_t viafb_dvp1_proc_write(struct file *file, | |||
1228 | for (i = 0; i < 3; i++) { | 1229 | for (i = 0; i < 3; i++) { |
1229 | value = strsep(&pbuf, " "); | 1230 | value = strsep(&pbuf, " "); |
1230 | if (value != NULL) { | 1231 | if (value != NULL) { |
1231 | strict_strtoul(value, 0, (unsigned long *)®_val); | 1232 | if (kstrtou8(value, 0, ®_val) < 0) |
1233 | return -EINVAL; | ||
1232 | switch (i) { | 1234 | switch (i) { |
1233 | case 0: | 1235 | case 0: |
1234 | viafb_write_reg_mask(CR9B, VIACR, | 1236 | viafb_write_reg_mask(CR9B, VIACR, |
@@ -1286,7 +1288,8 @@ static ssize_t viafb_dfph_proc_write(struct file *file, | |||
1286 | if (copy_from_user(&buf[0], buffer, length)) | 1288 | if (copy_from_user(&buf[0], buffer, length)) |
1287 | return -EFAULT; | 1289 | return -EFAULT; |
1288 | buf[length - 1] = '\0'; /*Ensure end string */ | 1290 | buf[length - 1] = '\0'; /*Ensure end string */ |
1289 | strict_strtoul(&buf[0], 0, (unsigned long *)®_val); | 1291 | if (kstrtou8(buf, 0, ®_val) < 0) |
1292 | return -EINVAL; | ||
1290 | viafb_write_reg_mask(CR97, VIACR, reg_val, 0x0f); | 1293 | viafb_write_reg_mask(CR97, VIACR, reg_val, 0x0f); |
1291 | return count; | 1294 | return count; |
1292 | } | 1295 | } |
@@ -1325,7 +1328,8 @@ static ssize_t viafb_dfpl_proc_write(struct file *file, | |||
1325 | if (copy_from_user(&buf[0], buffer, length)) | 1328 | if (copy_from_user(&buf[0], buffer, length)) |
1326 | return -EFAULT; | 1329 | return -EFAULT; |
1327 | buf[length - 1] = '\0'; /*Ensure end string */ | 1330 | buf[length - 1] = '\0'; /*Ensure end string */ |
1328 | strict_strtoul(&buf[0], 0, (unsigned long *)®_val); | 1331 | if (kstrtou8(buf, 0, ®_val) < 0) |
1332 | return -EINVAL; | ||
1329 | viafb_write_reg_mask(CR99, VIACR, reg_val, 0x0f); | 1333 | viafb_write_reg_mask(CR99, VIACR, reg_val, 0x0f); |
1330 | return count; | 1334 | return count; |
1331 | } | 1335 | } |
@@ -1394,8 +1398,8 @@ static ssize_t viafb_vt1636_proc_write(struct file *file, | |||
1394 | for (i = 0; i < 2; i++) { | 1398 | for (i = 0; i < 2; i++) { |
1395 | value = strsep(&pbuf, " "); | 1399 | value = strsep(&pbuf, " "); |
1396 | if (value != NULL) { | 1400 | if (value != NULL) { |
1397 | strict_strtoul(value, 0, | 1401 | if (kstrtou8(value, 0, ®_val.Data) < 0) |
1398 | (unsigned long *)®_val.Data); | 1402 | return -EINVAL; |
1399 | switch (i) { | 1403 | switch (i) { |
1400 | case 0: | 1404 | case 0: |
1401 | reg_val.Index = 0x08; | 1405 | reg_val.Index = 0x08; |
@@ -1431,8 +1435,8 @@ static ssize_t viafb_vt1636_proc_write(struct file *file, | |||
1431 | for (i = 0; i < 2; i++) { | 1435 | for (i = 0; i < 2; i++) { |
1432 | value = strsep(&pbuf, " "); | 1436 | value = strsep(&pbuf, " "); |
1433 | if (value != NULL) { | 1437 | if (value != NULL) { |
1434 | strict_strtoul(value, 0, | 1438 | if (kstrtou8(value, 0, ®_val.Data) < 0) |
1435 | (unsigned long *)®_val.Data); | 1439 | return -EINVAL; |
1436 | switch (i) { | 1440 | switch (i) { |
1437 | case 0: | 1441 | case 0: |
1438 | reg_val.Index = 0x08; | 1442 | reg_val.Index = 0x08; |
@@ -1729,7 +1733,6 @@ static struct viafb_pm_hooks viafb_fb_pm_hooks = { | |||
1729 | int __devinit via_fb_pci_probe(struct viafb_dev *vdev) | 1733 | int __devinit via_fb_pci_probe(struct viafb_dev *vdev) |
1730 | { | 1734 | { |
1731 | u32 default_xres, default_yres; | 1735 | u32 default_xres, default_yres; |
1732 | struct VideoModeTable *vmode_entry; | ||
1733 | struct fb_var_screeninfo default_var; | 1736 | struct fb_var_screeninfo default_var; |
1734 | int rc; | 1737 | int rc; |
1735 | u32 viafb_par_length; | 1738 | u32 viafb_par_length; |
@@ -1802,7 +1805,6 @@ int __devinit via_fb_pci_probe(struct viafb_dev *vdev) | |||
1802 | } | 1805 | } |
1803 | 1806 | ||
1804 | parse_mode(viafb_mode, &default_xres, &default_yres); | 1807 | parse_mode(viafb_mode, &default_xres, &default_yres); |
1805 | vmode_entry = viafb_get_mode(default_xres, default_yres); | ||
1806 | if (viafb_SAMM_ON == 1) | 1808 | if (viafb_SAMM_ON == 1) |
1807 | parse_mode(viafb_mode1, &viafb_second_xres, | 1809 | parse_mode(viafb_mode1, &viafb_second_xres, |
1808 | &viafb_second_yres); | 1810 | &viafb_second_yres); |
@@ -1812,9 +1814,8 @@ int __devinit via_fb_pci_probe(struct viafb_dev *vdev) | |||
1812 | default_var.xres_virtual = default_xres; | 1814 | default_var.xres_virtual = default_xres; |
1813 | default_var.yres_virtual = default_yres; | 1815 | default_var.yres_virtual = default_yres; |
1814 | default_var.bits_per_pixel = viafb_bpp; | 1816 | default_var.bits_per_pixel = viafb_bpp; |
1815 | viafb_fill_var_timing_info(&default_var, viafb_get_refresh( | 1817 | viafb_fill_var_timing_info(&default_var, viafb_get_best_mode( |
1816 | default_var.xres, default_var.yres, viafb_refresh), | 1818 | default_var.xres, default_var.yres, viafb_refresh)); |
1817 | viafb_get_mode(default_var.xres, default_var.yres)); | ||
1818 | viafb_setup_fixinfo(&viafbinfo->fix, viaparinfo); | 1819 | viafb_setup_fixinfo(&viafbinfo->fix, viaparinfo); |
1819 | viafbinfo->var = default_var; | 1820 | viafbinfo->var = default_var; |
1820 | 1821 | ||
@@ -1853,9 +1854,8 @@ int __devinit via_fb_pci_probe(struct viafb_dev *vdev) | |||
1853 | default_var.xres_virtual = viafb_second_xres; | 1854 | default_var.xres_virtual = viafb_second_xres; |
1854 | default_var.yres_virtual = viafb_second_yres; | 1855 | default_var.yres_virtual = viafb_second_yres; |
1855 | default_var.bits_per_pixel = viafb_bpp1; | 1856 | default_var.bits_per_pixel = viafb_bpp1; |
1856 | viafb_fill_var_timing_info(&default_var, viafb_get_refresh( | 1857 | viafb_fill_var_timing_info(&default_var, viafb_get_best_mode( |
1857 | default_var.xres, default_var.yres, viafb_refresh1), | 1858 | default_var.xres, default_var.yres, viafb_refresh1)); |
1858 | viafb_get_mode(default_var.xres, default_var.yres)); | ||
1859 | 1859 | ||
1860 | viafb_setup_fixinfo(&viafbinfo1->fix, viaparinfo1); | 1860 | viafb_setup_fixinfo(&viafbinfo1->fix, viaparinfo1); |
1861 | viafb_check_var(&default_var, viafbinfo1); | 1861 | viafb_check_var(&default_var, viafbinfo1); |
@@ -1950,61 +1950,67 @@ static int __init viafb_setup(void) | |||
1950 | if (!*this_opt) | 1950 | if (!*this_opt) |
1951 | continue; | 1951 | continue; |
1952 | 1952 | ||
1953 | if (!strncmp(this_opt, "viafb_mode1=", 12)) | 1953 | if (!strncmp(this_opt, "viafb_mode1=", 12)) { |
1954 | viafb_mode1 = kstrdup(this_opt + 12, GFP_KERNEL); | 1954 | viafb_mode1 = kstrdup(this_opt + 12, GFP_KERNEL); |
1955 | else if (!strncmp(this_opt, "viafb_mode=", 11)) | 1955 | } else if (!strncmp(this_opt, "viafb_mode=", 11)) { |
1956 | viafb_mode = kstrdup(this_opt + 11, GFP_KERNEL); | 1956 | viafb_mode = kstrdup(this_opt + 11, GFP_KERNEL); |
1957 | else if (!strncmp(this_opt, "viafb_bpp1=", 11)) | 1957 | } else if (!strncmp(this_opt, "viafb_bpp1=", 11)) { |
1958 | strict_strtoul(this_opt + 11, 0, | 1958 | if (kstrtouint(this_opt + 11, 0, &viafb_bpp1) < 0) |
1959 | (unsigned long *)&viafb_bpp1); | 1959 | return -EINVAL; |
1960 | else if (!strncmp(this_opt, "viafb_bpp=", 10)) | 1960 | } else if (!strncmp(this_opt, "viafb_bpp=", 10)) { |
1961 | strict_strtoul(this_opt + 10, 0, | 1961 | if (kstrtouint(this_opt + 10, 0, &viafb_bpp) < 0) |
1962 | (unsigned long *)&viafb_bpp); | 1962 | return -EINVAL; |
1963 | else if (!strncmp(this_opt, "viafb_refresh1=", 15)) | 1963 | } else if (!strncmp(this_opt, "viafb_refresh1=", 15)) { |
1964 | strict_strtoul(this_opt + 15, 0, | 1964 | if (kstrtoint(this_opt + 15, 0, &viafb_refresh1) < 0) |
1965 | (unsigned long *)&viafb_refresh1); | 1965 | return -EINVAL; |
1966 | else if (!strncmp(this_opt, "viafb_refresh=", 14)) | 1966 | } else if (!strncmp(this_opt, "viafb_refresh=", 14)) { |
1967 | strict_strtoul(this_opt + 14, 0, | 1967 | if (kstrtoint(this_opt + 14, 0, &viafb_refresh) < 0) |
1968 | (unsigned long *)&viafb_refresh); | 1968 | return -EINVAL; |
1969 | else if (!strncmp(this_opt, "viafb_lcd_dsp_method=", 21)) | 1969 | } else if (!strncmp(this_opt, "viafb_lcd_dsp_method=", 21)) { |
1970 | strict_strtoul(this_opt + 21, 0, | 1970 | if (kstrtoint(this_opt + 21, 0, |
1971 | (unsigned long *)&viafb_lcd_dsp_method); | 1971 | &viafb_lcd_dsp_method) < 0) |
1972 | else if (!strncmp(this_opt, "viafb_lcd_panel_id=", 19)) | 1972 | return -EINVAL; |
1973 | strict_strtoul(this_opt + 19, 0, | 1973 | } else if (!strncmp(this_opt, "viafb_lcd_panel_id=", 19)) { |
1974 | (unsigned long *)&viafb_lcd_panel_id); | 1974 | if (kstrtoint(this_opt + 19, 0, |
1975 | else if (!strncmp(this_opt, "viafb_accel=", 12)) | 1975 | &viafb_lcd_panel_id) < 0) |
1976 | strict_strtoul(this_opt + 12, 0, | 1976 | return -EINVAL; |
1977 | (unsigned long *)&viafb_accel); | 1977 | } else if (!strncmp(this_opt, "viafb_accel=", 12)) { |
1978 | else if (!strncmp(this_opt, "viafb_SAMM_ON=", 14)) | 1978 | if (kstrtoint(this_opt + 12, 0, &viafb_accel) < 0) |
1979 | strict_strtoul(this_opt + 14, 0, | 1979 | return -EINVAL; |
1980 | (unsigned long *)&viafb_SAMM_ON); | 1980 | } else if (!strncmp(this_opt, "viafb_SAMM_ON=", 14)) { |
1981 | else if (!strncmp(this_opt, "viafb_active_dev=", 17)) | 1981 | if (kstrtoint(this_opt + 14, 0, &viafb_SAMM_ON) < 0) |
1982 | return -EINVAL; | ||
1983 | } else if (!strncmp(this_opt, "viafb_active_dev=", 17)) { | ||
1982 | viafb_active_dev = kstrdup(this_opt + 17, GFP_KERNEL); | 1984 | viafb_active_dev = kstrdup(this_opt + 17, GFP_KERNEL); |
1983 | else if (!strncmp(this_opt, | 1985 | } else if (!strncmp(this_opt, |
1984 | "viafb_display_hardware_layout=", 30)) | 1986 | "viafb_display_hardware_layout=", 30)) { |
1985 | strict_strtoul(this_opt + 30, 0, | 1987 | if (kstrtoint(this_opt + 30, 0, |
1986 | (unsigned long *)&viafb_display_hardware_layout); | 1988 | &viafb_display_hardware_layout) < 0) |
1987 | else if (!strncmp(this_opt, "viafb_second_size=", 18)) | 1989 | return -EINVAL; |
1988 | strict_strtoul(this_opt + 18, 0, | 1990 | } else if (!strncmp(this_opt, "viafb_second_size=", 18)) { |
1989 | (unsigned long *)&viafb_second_size); | 1991 | if (kstrtoint(this_opt + 18, 0, &viafb_second_size) < 0) |
1990 | else if (!strncmp(this_opt, | 1992 | return -EINVAL; |
1991 | "viafb_platform_epia_dvi=", 24)) | 1993 | } else if (!strncmp(this_opt, |
1992 | strict_strtoul(this_opt + 24, 0, | 1994 | "viafb_platform_epia_dvi=", 24)) { |
1993 | (unsigned long *)&viafb_platform_epia_dvi); | 1995 | if (kstrtoint(this_opt + 24, 0, |
1994 | else if (!strncmp(this_opt, | 1996 | &viafb_platform_epia_dvi) < 0) |
1995 | "viafb_device_lcd_dualedge=", 26)) | 1997 | return -EINVAL; |
1996 | strict_strtoul(this_opt + 26, 0, | 1998 | } else if (!strncmp(this_opt, |
1997 | (unsigned long *)&viafb_device_lcd_dualedge); | 1999 | "viafb_device_lcd_dualedge=", 26)) { |
1998 | else if (!strncmp(this_opt, "viafb_bus_width=", 16)) | 2000 | if (kstrtoint(this_opt + 26, 0, |
1999 | strict_strtoul(this_opt + 16, 0, | 2001 | &viafb_device_lcd_dualedge) < 0) |
2000 | (unsigned long *)&viafb_bus_width); | 2002 | return -EINVAL; |
2001 | else if (!strncmp(this_opt, "viafb_lcd_mode=", 15)) | 2003 | } else if (!strncmp(this_opt, "viafb_bus_width=", 16)) { |
2002 | strict_strtoul(this_opt + 15, 0, | 2004 | if (kstrtoint(this_opt + 16, 0, &viafb_bus_width) < 0) |
2003 | (unsigned long *)&viafb_lcd_mode); | 2005 | return -EINVAL; |
2004 | else if (!strncmp(this_opt, "viafb_lcd_port=", 15)) | 2006 | } else if (!strncmp(this_opt, "viafb_lcd_mode=", 15)) { |
2007 | if (kstrtoint(this_opt + 15, 0, &viafb_lcd_mode) < 0) | ||
2008 | return -EINVAL; | ||
2009 | } else if (!strncmp(this_opt, "viafb_lcd_port=", 15)) { | ||
2005 | viafb_lcd_port = kstrdup(this_opt + 15, GFP_KERNEL); | 2010 | viafb_lcd_port = kstrdup(this_opt + 15, GFP_KERNEL); |
2006 | else if (!strncmp(this_opt, "viafb_dvi_port=", 15)) | 2011 | } else if (!strncmp(this_opt, "viafb_dvi_port=", 15)) { |
2007 | viafb_dvi_port = kstrdup(this_opt + 15, GFP_KERNEL); | 2012 | viafb_dvi_port = kstrdup(this_opt + 15, GFP_KERNEL); |
2013 | } | ||
2008 | } | 2014 | } |
2009 | return 0; | 2015 | return 0; |
2010 | } | 2016 | } |
@@ -2028,9 +2034,9 @@ int __init viafb_init(void) | |||
2028 | return r; | 2034 | return r; |
2029 | #endif | 2035 | #endif |
2030 | if (parse_mode(viafb_mode, &dummy_x, &dummy_y) | 2036 | if (parse_mode(viafb_mode, &dummy_x, &dummy_y) |
2031 | || !viafb_get_mode(dummy_x, dummy_y) | 2037 | || !viafb_get_best_mode(dummy_x, dummy_y, viafb_refresh) |
2032 | || parse_mode(viafb_mode1, &dummy_x, &dummy_y) | 2038 | || parse_mode(viafb_mode1, &dummy_x, &dummy_y) |
2033 | || !viafb_get_mode(dummy_x, dummy_y) | 2039 | || !viafb_get_best_mode(dummy_x, dummy_y, viafb_refresh1) |
2034 | || viafb_bpp < 0 || viafb_bpp > 32 | 2040 | || viafb_bpp < 0 || viafb_bpp > 32 |
2035 | || viafb_bpp1 < 0 || viafb_bpp1 > 32 | 2041 | || viafb_bpp1 < 0 || viafb_bpp1 > 32 |
2036 | || parse_active_dev()) | 2042 | || parse_active_dev()) |
diff --git a/drivers/video/via/viamode.c b/drivers/video/via/viamode.c index 58df74e1417e..0911cac1b2ff 100644 --- a/drivers/video/via/viamode.c +++ b/drivers/video/via/viamode.c | |||
@@ -281,7 +281,7 @@ static struct crt_mode_table CRTM640x480[] = { | |||
281 | /*r_rate,hsp,vsp */ | 281 | /*r_rate,hsp,vsp */ |
282 | /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ | 282 | /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ |
283 | {REFRESH_60, M640X480_R60_HSP, M640X480_R60_VSP, | 283 | {REFRESH_60, M640X480_R60_HSP, M640X480_R60_VSP, |
284 | {800, 640, 648, 144, 656, 96, 525, 480, 480, 45, 490, 2} }, | 284 | {800, 640, 640, 160, 656, 96, 525, 480, 480, 45, 490, 2} }, |
285 | {REFRESH_75, M640X480_R75_HSP, M640X480_R75_VSP, | 285 | {REFRESH_75, M640X480_R75_HSP, M640X480_R75_VSP, |
286 | {840, 640, 640, 200, 656, 64, 500, 480, 480, 20, 481, 3} }, | 286 | {840, 640, 640, 200, 656, 64, 500, 480, 480, 20, 481, 3} }, |
287 | {REFRESH_85, M640X480_R85_HSP, M640X480_R85_VSP, | 287 | {REFRESH_85, M640X480_R85_HSP, M640X480_R85_VSP, |
@@ -863,26 +863,56 @@ int NUM_TOTAL_CLE266_ModeXregs = ARRAY_SIZE(CLE266_ModeXregs); | |||
863 | int NUM_TOTAL_PATCH_MODE = ARRAY_SIZE(res_patch_table); | 863 | int NUM_TOTAL_PATCH_MODE = ARRAY_SIZE(res_patch_table); |
864 | 864 | ||
865 | 865 | ||
866 | struct VideoModeTable *viafb_get_mode(int hres, int vres) | 866 | static struct VideoModeTable *get_modes(struct VideoModeTable *vmt, int n, |
867 | int hres, int vres) | ||
867 | { | 868 | { |
868 | u32 i; | 869 | int i; |
869 | for (i = 0; i < ARRAY_SIZE(viafb_modes); i++) | 870 | |
870 | if (viafb_modes[i].mode_array && | 871 | for (i = 0; i < n; i++) |
871 | viafb_modes[i].crtc[0].crtc.hor_addr == hres && | 872 | if (vmt[i].mode_array && |
872 | viafb_modes[i].crtc[0].crtc.ver_addr == vres) | 873 | vmt[i].crtc[0].crtc.hor_addr == hres && |
874 | vmt[i].crtc[0].crtc.ver_addr == vres) | ||
873 | return &viafb_modes[i]; | 875 | return &viafb_modes[i]; |
874 | 876 | ||
875 | return NULL; | 877 | return NULL; |
876 | } | 878 | } |
877 | 879 | ||
878 | struct VideoModeTable *viafb_get_rb_mode(int hres, int vres) | 880 | static struct crt_mode_table *get_best_mode(struct VideoModeTable *vmt, |
881 | int refresh) | ||
879 | { | 882 | { |
880 | u32 i; | 883 | struct crt_mode_table *best; |
881 | for (i = 0; i < ARRAY_SIZE(viafb_rb_modes); i++) | 884 | int i; |
882 | if (viafb_rb_modes[i].mode_array && | ||
883 | viafb_rb_modes[i].crtc[0].crtc.hor_addr == hres && | ||
884 | viafb_rb_modes[i].crtc[0].crtc.ver_addr == vres) | ||
885 | return &viafb_rb_modes[i]; | ||
886 | 885 | ||
887 | return NULL; | 886 | if (!vmt) |
887 | return NULL; | ||
888 | |||
889 | best = &vmt->crtc[0]; | ||
890 | for (i = 1; i < vmt->mode_array; i++) { | ||
891 | if (abs(vmt->crtc[i].refresh_rate - refresh) | ||
892 | < abs(best->refresh_rate - refresh)) | ||
893 | best = &vmt->crtc[i]; | ||
894 | } | ||
895 | |||
896 | return best; | ||
897 | } | ||
898 | |||
899 | static struct VideoModeTable *viafb_get_mode(int hres, int vres) | ||
900 | { | ||
901 | return get_modes(viafb_modes, ARRAY_SIZE(viafb_modes), hres, vres); | ||
902 | } | ||
903 | |||
904 | struct crt_mode_table *viafb_get_best_mode(int hres, int vres, int refresh) | ||
905 | { | ||
906 | return get_best_mode(viafb_get_mode(hres, vres), refresh); | ||
907 | } | ||
908 | |||
909 | static struct VideoModeTable *viafb_get_rb_mode(int hres, int vres) | ||
910 | { | ||
911 | return get_modes(viafb_rb_modes, ARRAY_SIZE(viafb_rb_modes), hres, | ||
912 | vres); | ||
913 | } | ||
914 | |||
915 | struct crt_mode_table *viafb_get_best_rb_mode(int hres, int vres, int refresh) | ||
916 | { | ||
917 | return get_best_mode(viafb_get_rb_mode(hres, vres), refresh); | ||
888 | } | 918 | } |
diff --git a/drivers/video/via/viamode.h b/drivers/video/via/viamode.h index 3751289eb450..5917a2b00e1b 100644 --- a/drivers/video/via/viamode.h +++ b/drivers/video/via/viamode.h | |||
@@ -60,7 +60,7 @@ extern struct io_reg PM1024x768[]; | |||
60 | extern struct patch_table res_patch_table[]; | 60 | extern struct patch_table res_patch_table[]; |
61 | extern struct VPITTable VPIT; | 61 | extern struct VPITTable VPIT; |
62 | 62 | ||
63 | struct VideoModeTable *viafb_get_mode(int hres, int vres); | 63 | struct crt_mode_table *viafb_get_best_mode(int hres, int vres, int refresh); |
64 | struct VideoModeTable *viafb_get_rb_mode(int hres, int vres); | 64 | struct crt_mode_table *viafb_get_best_rb_mode(int hres, int vres, int refresh); |
65 | 65 | ||
66 | #endif /* __VIAMODE_H__ */ | 66 | #endif /* __VIAMODE_H__ */ |
diff --git a/drivers/video/vt8500lcdfb.c b/drivers/video/vt8500lcdfb.c index 0e120d67eb65..777c21dd7a6b 100644 --- a/drivers/video/vt8500lcdfb.c +++ b/drivers/video/vt8500lcdfb.c | |||
@@ -210,8 +210,8 @@ static int vt8500lcd_pan_display(struct fb_var_screeninfo *var, | |||
210 | struct vt8500lcd_info *fbi = to_vt8500lcd_info(info); | 210 | struct vt8500lcd_info *fbi = to_vt8500lcd_info(info); |
211 | 211 | ||
212 | writel((1 << 31) | 212 | writel((1 << 31) |
213 | | (((var->xres_virtual - var->xres) * pixlen / 4) << 20) | 213 | | (((info->var.xres_virtual - info->var.xres) * pixlen / 4) << 20) |
214 | | (off >> 2), fbi->regbase + 0x20); | 214 | | (off >> 2), fbi->regbase + 0x20); |
215 | return 0; | 215 | return 0; |
216 | } | 216 | } |
217 | 217 | ||
@@ -355,7 +355,7 @@ static int __devinit vt8500lcd_probe(struct platform_device *pdev) | |||
355 | goto failed_free_palette; | 355 | goto failed_free_palette; |
356 | } | 356 | } |
357 | 357 | ||
358 | ret = request_irq(irq, vt8500lcd_handle_irq, IRQF_DISABLED, "LCD", fbi); | 358 | ret = request_irq(irq, vt8500lcd_handle_irq, 0, "LCD", fbi); |
359 | if (ret) { | 359 | if (ret) { |
360 | dev_err(&pdev->dev, "request_irq failed: %d\n", ret); | 360 | dev_err(&pdev->dev, "request_irq failed: %d\n", ret); |
361 | ret = -EBUSY; | 361 | ret = -EBUSY; |
diff --git a/drivers/video/vt8623fb.c b/drivers/video/vt8623fb.c index f9b3e3dc2421..4e74d262cf3e 100644 --- a/drivers/video/vt8623fb.c +++ b/drivers/video/vt8623fb.c | |||
@@ -620,13 +620,14 @@ static int vt8623fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *i | |||
620 | unsigned int offset; | 620 | unsigned int offset; |
621 | 621 | ||
622 | /* Calculate the offset */ | 622 | /* Calculate the offset */ |
623 | if (var->bits_per_pixel == 0) { | 623 | if (info->var.bits_per_pixel == 0) { |
624 | offset = (var->yoffset / 16) * var->xres_virtual + var->xoffset; | 624 | offset = (var->yoffset / 16) * info->var.xres_virtual |
625 | + var->xoffset; | ||
625 | offset = offset >> 3; | 626 | offset = offset >> 3; |
626 | } else { | 627 | } else { |
627 | offset = (var->yoffset * info->fix.line_length) + | 628 | offset = (var->yoffset * info->fix.line_length) + |
628 | (var->xoffset * var->bits_per_pixel / 8); | 629 | (var->xoffset * info->var.bits_per_pixel / 8); |
629 | offset = offset >> ((var->bits_per_pixel == 4) ? 2 : 1); | 630 | offset = offset >> ((info->var.bits_per_pixel == 4) ? 2 : 1); |
630 | } | 631 | } |
631 | 632 | ||
632 | /* Set the offset */ | 633 | /* Set the offset */ |
diff --git a/drivers/video/xilinxfb.c b/drivers/video/xilinxfb.c index 77dea015ff69..fcb6cd90f64d 100644 --- a/drivers/video/xilinxfb.c +++ b/drivers/video/xilinxfb.c | |||
@@ -23,7 +23,6 @@ | |||
23 | #include <linux/device.h> | 23 | #include <linux/device.h> |
24 | #include <linux/module.h> | 24 | #include <linux/module.h> |
25 | #include <linux/kernel.h> | 25 | #include <linux/kernel.h> |
26 | #include <linux/version.h> | ||
27 | #include <linux/errno.h> | 26 | #include <linux/errno.h> |
28 | #include <linux/string.h> | 27 | #include <linux/string.h> |
29 | #include <linux/mm.h> | 28 | #include <linux/mm.h> |
diff --git a/include/linux/fsl-diu-fb.h b/include/linux/fsl-diu-fb.h index daa9952d2174..11c16a1fb9e3 100644 --- a/include/linux/fsl-diu-fb.h +++ b/include/linux/fsl-diu-fb.h | |||
@@ -20,18 +20,8 @@ | |||
20 | #ifndef __FSL_DIU_FB_H__ | 20 | #ifndef __FSL_DIU_FB_H__ |
21 | #define __FSL_DIU_FB_H__ | 21 | #define __FSL_DIU_FB_H__ |
22 | 22 | ||
23 | /* Arbitrary threshold to determine the allocation method | ||
24 | * See mpc8610fb_set_par(), map_video_memory(), and unmap_video_memory() | ||
25 | */ | ||
26 | #define MEM_ALLOC_THRESHOLD (1024*768*4+32) | ||
27 | |||
28 | #include <linux/types.h> | 23 | #include <linux/types.h> |
29 | 24 | ||
30 | struct mfb_alpha { | ||
31 | int enable; | ||
32 | int alpha; | ||
33 | }; | ||
34 | |||
35 | struct mfb_chroma_key { | 25 | struct mfb_chroma_key { |
36 | int enable; | 26 | int enable; |
37 | __u8 red_max; | 27 | __u8 red_max; |
@@ -43,25 +33,29 @@ struct mfb_chroma_key { | |||
43 | }; | 33 | }; |
44 | 34 | ||
45 | struct aoi_display_offset { | 35 | struct aoi_display_offset { |
46 | int x_aoi_d; | 36 | __s32 x_aoi_d; |
47 | int y_aoi_d; | 37 | __s32 y_aoi_d; |
48 | }; | 38 | }; |
49 | 39 | ||
50 | #define MFB_SET_CHROMA_KEY _IOW('M', 1, struct mfb_chroma_key) | 40 | #define MFB_SET_CHROMA_KEY _IOW('M', 1, struct mfb_chroma_key) |
51 | #define MFB_SET_BRIGHTNESS _IOW('M', 3, __u8) | 41 | #define MFB_SET_BRIGHTNESS _IOW('M', 3, __u8) |
42 | #define MFB_SET_ALPHA _IOW('M', 0, __u8) | ||
43 | #define MFB_GET_ALPHA _IOR('M', 0, __u8) | ||
44 | #define MFB_SET_AOID _IOW('M', 4, struct aoi_display_offset) | ||
45 | #define MFB_GET_AOID _IOR('M', 4, struct aoi_display_offset) | ||
46 | #define MFB_SET_PIXFMT _IOW('M', 8, __u32) | ||
47 | #define MFB_GET_PIXFMT _IOR('M', 8, __u32) | ||
52 | 48 | ||
53 | #define MFB_SET_ALPHA 0x80014d00 | 49 | /* |
54 | #define MFB_GET_ALPHA 0x40014d00 | 50 | * The original definitions of MFB_SET_PIXFMT and MFB_GET_PIXFMT used the |
55 | #define MFB_SET_AOID 0x80084d04 | 51 | * wrong value for 'size' field of the ioctl. The current macros above use the |
56 | #define MFB_GET_AOID 0x40084d04 | 52 | * right size, but we still need to provide backwards compatibility, at least |
57 | #define MFB_SET_PIXFMT 0x80014d08 | 53 | * for a while. |
58 | #define MFB_GET_PIXFMT 0x40014d08 | 54 | */ |
59 | 55 | #define MFB_SET_PIXFMT_OLD 0x80014d08 | |
60 | #define FBIOGET_GWINFO 0x46E0 | 56 | #define MFB_GET_PIXFMT_OLD 0x40014d08 |
61 | #define FBIOPUT_GWINFO 0x46E1 | ||
62 | 57 | ||
63 | #ifdef __KERNEL__ | 58 | #ifdef __KERNEL__ |
64 | #include <linux/spinlock.h> | ||
65 | 59 | ||
66 | /* | 60 | /* |
67 | * These are the fields of area descriptor(in DDR memory) for every plane | 61 | * These are the fields of area descriptor(in DDR memory) for every plane |
@@ -159,58 +153,12 @@ struct diu { | |||
159 | __be32 plut; | 153 | __be32 plut; |
160 | } __attribute__ ((packed)); | 154 | } __attribute__ ((packed)); |
161 | 155 | ||
162 | struct diu_hw { | 156 | /* |
163 | struct diu *diu_reg; | 157 | * Modes of operation of DIU. The DIU supports five different modes, but |
164 | spinlock_t reg_lock; | 158 | * the driver only supports modes 0 and 1. |
165 | 159 | */ | |
166 | __u32 mode; /* DIU operation mode */ | ||
167 | }; | ||
168 | |||
169 | struct diu_addr { | ||
170 | __u8 __iomem *vaddr; /* Virtual address */ | ||
171 | dma_addr_t paddr; /* Physical address */ | ||
172 | __u32 offset; | ||
173 | }; | ||
174 | |||
175 | struct diu_pool { | ||
176 | struct diu_addr ad; | ||
177 | struct diu_addr gamma; | ||
178 | struct diu_addr pallete; | ||
179 | struct diu_addr cursor; | ||
180 | }; | ||
181 | |||
182 | #define FSL_DIU_BASE_OFFSET 0x2C000 /* Offset of DIU */ | ||
183 | #define INT_LCDC 64 /* DIU interrupt number */ | ||
184 | |||
185 | #define FSL_AOI_NUM 6 /* 5 AOIs and one dummy AOI */ | ||
186 | /* 1 for plane 0, 2 for plane 1&2 each */ | ||
187 | |||
188 | /* Minimum X and Y resolutions */ | ||
189 | #define MIN_XRES 64 | ||
190 | #define MIN_YRES 64 | ||
191 | |||
192 | /* HW cursor parameters */ | ||
193 | #define MAX_CURS 32 | ||
194 | |||
195 | /* Modes of operation of DIU */ | ||
196 | #define MFB_MODE0 0 /* DIU off */ | 160 | #define MFB_MODE0 0 /* DIU off */ |
197 | #define MFB_MODE1 1 /* All three planes output to display */ | 161 | #define MFB_MODE1 1 /* All three planes output to display */ |
198 | #define MFB_MODE2 2 /* Plane 1 to display, planes 2+3 written back*/ | ||
199 | #define MFB_MODE3 3 /* All three planes written back to memory */ | ||
200 | #define MFB_MODE4 4 /* Color bar generation */ | ||
201 | |||
202 | /* INT_STATUS/INT_MASK field descriptions */ | ||
203 | #define INT_VSYNC 0x01 /* Vsync interrupt */ | ||
204 | #define INT_VSYNC_WB 0x02 /* Vsync interrupt for write back operation */ | ||
205 | #define INT_UNDRUN 0x04 /* Under run exception interrupt */ | ||
206 | #define INT_PARERR 0x08 /* Display parameters error interrupt */ | ||
207 | #define INT_LS_BF_VS 0x10 /* Lines before vsync. interrupt */ | ||
208 | |||
209 | /* Panels'operation modes */ | ||
210 | #define MFB_TYPE_OUTPUT 0 /* Panel output to display */ | ||
211 | #define MFB_TYPE_OFF 1 /* Panel off */ | ||
212 | #define MFB_TYPE_WB 2 /* Panel written back to memory */ | ||
213 | #define MFB_TYPE_TEST 3 /* Panel generate color bar */ | ||
214 | 162 | ||
215 | #endif /* __KERNEL__ */ | 163 | #endif /* __KERNEL__ */ |
216 | #endif /* __FSL_DIU_FB_H__ */ | 164 | #endif /* __FSL_DIU_FB_H__ */ |
diff --git a/include/video/omap-panel-dvi.h b/include/video/omap-panel-dvi.h new file mode 100644 index 000000000000..87ad567b4229 --- /dev/null +++ b/include/video/omap-panel-dvi.h | |||
@@ -0,0 +1,37 @@ | |||
1 | /* | ||
2 | * Header for DVI output driver | ||
3 | * | ||
4 | * Copyright (C) 2011 Texas Instruments Inc | ||
5 | * Author: Tomi Valkeinen <tomi.valkeinen@ti.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify it | ||
8 | * under the terms of the GNU General Public License version 2 as published by | ||
9 | * the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
14 | * more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License along with | ||
17 | * this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | #ifndef __OMAP_PANEL_DVI_H | ||
21 | #define __OMAP_PANEL_DVI_H | ||
22 | |||
23 | struct omap_dss_device; | ||
24 | |||
25 | /** | ||
26 | * struct panel_dvi_platform_data - panel driver configuration data | ||
27 | * @platform_enable: platform specific panel enable function | ||
28 | * @platform_disable: platform specific panel disable function | ||
29 | * @i2c_bus_num: i2c bus id for the panel | ||
30 | */ | ||
31 | struct panel_dvi_platform_data { | ||
32 | int (*platform_enable)(struct omap_dss_device *dssdev); | ||
33 | void (*platform_disable)(struct omap_dss_device *dssdev); | ||
34 | u16 i2c_bus_num; | ||
35 | }; | ||
36 | |||
37 | #endif /* __OMAP_PANEL_DVI_H */ | ||
diff --git a/include/video/omap-panel-n8x0.h b/include/video/omap-panel-n8x0.h new file mode 100644 index 000000000000..50a1302e2cfd --- /dev/null +++ b/include/video/omap-panel-n8x0.h | |||
@@ -0,0 +1,15 @@ | |||
1 | #ifndef __OMAP_PANEL_N8X0_H | ||
2 | #define __OMAP_PANEL_N8X0_H | ||
3 | |||
4 | struct omap_dss_device; | ||
5 | |||
6 | struct panel_n8x0_data { | ||
7 | int (*platform_enable)(struct omap_dss_device *dssdev); | ||
8 | void (*platform_disable)(struct omap_dss_device *dssdev); | ||
9 | int panel_reset; | ||
10 | int ctrl_pwrdown; | ||
11 | |||
12 | int (*set_backlight)(struct omap_dss_device *dssdev, int level); | ||
13 | }; | ||
14 | |||
15 | #endif | ||
diff --git a/include/video/omap-panel-nokia-dsi.h b/include/video/omap-panel-nokia-dsi.h index 921ae9327228..7dc71f9c13e6 100644 --- a/include/video/omap-panel-nokia-dsi.h +++ b/include/video/omap-panel-nokia-dsi.h | |||
@@ -10,9 +10,7 @@ struct omap_dss_device; | |||
10 | * @ext_te_gpio: external TE GPIO | 10 | * @ext_te_gpio: external TE GPIO |
11 | * @esd_interval: interval of ESD checks, 0 = disabled (ms) | 11 | * @esd_interval: interval of ESD checks, 0 = disabled (ms) |
12 | * @ulps_timeout: time to wait before entering ULPS, 0 = disabled (ms) | 12 | * @ulps_timeout: time to wait before entering ULPS, 0 = disabled (ms) |
13 | * @max_backlight_level: maximum backlight level | 13 | * @use_dsi_backlight: true if panel uses DSI command to control backlight |
14 | * @set_backlight: pointer to backlight set function | ||
15 | * @get_backlight: pointer to backlight get function | ||
16 | */ | 14 | */ |
17 | struct nokia_dsi_panel_data { | 15 | struct nokia_dsi_panel_data { |
18 | const char *name; | 16 | const char *name; |
@@ -25,9 +23,7 @@ struct nokia_dsi_panel_data { | |||
25 | unsigned esd_interval; | 23 | unsigned esd_interval; |
26 | unsigned ulps_timeout; | 24 | unsigned ulps_timeout; |
27 | 25 | ||
28 | int max_backlight_level; | 26 | bool use_dsi_backlight; |
29 | int (*set_backlight)(struct omap_dss_device *dssdev, int level); | ||
30 | int (*get_backlight)(struct omap_dss_device *dssdev); | ||
31 | }; | 27 | }; |
32 | 28 | ||
33 | #endif /* __OMAP_NOKIA_DSI_PANEL_H */ | 29 | #endif /* __OMAP_NOKIA_DSI_PANEL_H */ |
diff --git a/include/video/omap-panel-picodlp.h b/include/video/omap-panel-picodlp.h new file mode 100644 index 000000000000..1c342ef6f3a1 --- /dev/null +++ b/include/video/omap-panel-picodlp.h | |||
@@ -0,0 +1,23 @@ | |||
1 | /* | ||
2 | * panel data for picodlp panel | ||
3 | * | ||
4 | * Copyright (C) 2011 Texas Instruments | ||
5 | * | ||
6 | * Author: Mayuresh Janorkar <mayur@ti.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | #ifndef __PANEL_PICODLP_H | ||
13 | #define __PANEL_PICODLP_H | ||
14 | /** | ||
15 | * struct : picodlp panel data | ||
16 | * picodlp_adapter_id: i2c_adapter number for picodlp | ||
17 | */ | ||
18 | struct picodlp_panel_data { | ||
19 | int picodlp_adapter_id; | ||
20 | int emu_done_gpio; | ||
21 | int pwrgood_gpio; | ||
22 | }; | ||
23 | #endif /* __PANEL_PICODLP_H */ | ||
diff --git a/include/video/omapdss.h b/include/video/omapdss.h index 3b55ef22f8db..b66ebb2032c6 100644 --- a/include/video/omapdss.h +++ b/include/video/omapdss.h | |||
@@ -41,8 +41,13 @@ | |||
41 | #define DISPC_IRQ_WAKEUP (1 << 16) | 41 | #define DISPC_IRQ_WAKEUP (1 << 16) |
42 | #define DISPC_IRQ_SYNC_LOST2 (1 << 17) | 42 | #define DISPC_IRQ_SYNC_LOST2 (1 << 17) |
43 | #define DISPC_IRQ_VSYNC2 (1 << 18) | 43 | #define DISPC_IRQ_VSYNC2 (1 << 18) |
44 | #define DISPC_IRQ_VID3_END_WIN (1 << 19) | ||
45 | #define DISPC_IRQ_VID3_FIFO_UNDERFLOW (1 << 20) | ||
44 | #define DISPC_IRQ_ACBIAS_COUNT_STAT2 (1 << 21) | 46 | #define DISPC_IRQ_ACBIAS_COUNT_STAT2 (1 << 21) |
45 | #define DISPC_IRQ_FRAMEDONE2 (1 << 22) | 47 | #define DISPC_IRQ_FRAMEDONE2 (1 << 22) |
48 | #define DISPC_IRQ_FRAMEDONEWB (1 << 23) | ||
49 | #define DISPC_IRQ_FRAMEDONETV (1 << 24) | ||
50 | #define DISPC_IRQ_WBBUFFEROVERFLOW (1 << 25) | ||
46 | 51 | ||
47 | struct omap_dss_device; | 52 | struct omap_dss_device; |
48 | struct omap_overlay_manager; | 53 | struct omap_overlay_manager; |
@@ -60,7 +65,8 @@ enum omap_display_type { | |||
60 | enum omap_plane { | 65 | enum omap_plane { |
61 | OMAP_DSS_GFX = 0, | 66 | OMAP_DSS_GFX = 0, |
62 | OMAP_DSS_VIDEO1 = 1, | 67 | OMAP_DSS_VIDEO1 = 1, |
63 | OMAP_DSS_VIDEO2 = 2 | 68 | OMAP_DSS_VIDEO2 = 2, |
69 | OMAP_DSS_VIDEO3 = 3, | ||
64 | }; | 70 | }; |
65 | 71 | ||
66 | enum omap_channel { | 72 | enum omap_channel { |
@@ -129,6 +135,18 @@ enum omap_dss_venc_type { | |||
129 | OMAP_DSS_VENC_TYPE_SVIDEO, | 135 | OMAP_DSS_VENC_TYPE_SVIDEO, |
130 | }; | 136 | }; |
131 | 137 | ||
138 | enum omap_dss_dsi_pixel_format { | ||
139 | OMAP_DSS_DSI_FMT_RGB888, | ||
140 | OMAP_DSS_DSI_FMT_RGB666, | ||
141 | OMAP_DSS_DSI_FMT_RGB666_PACKED, | ||
142 | OMAP_DSS_DSI_FMT_RGB565, | ||
143 | }; | ||
144 | |||
145 | enum omap_dss_dsi_mode { | ||
146 | OMAP_DSS_DSI_CMD_MODE = 0, | ||
147 | OMAP_DSS_DSI_VIDEO_MODE, | ||
148 | }; | ||
149 | |||
132 | enum omap_display_caps { | 150 | enum omap_display_caps { |
133 | OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE = 1 << 0, | 151 | OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE = 1 << 0, |
134 | OMAP_DSS_DISPLAY_CAP_TEAR_ELIM = 1 << 1, | 152 | OMAP_DSS_DISPLAY_CAP_TEAR_ELIM = 1 << 1, |
@@ -162,11 +180,13 @@ enum omap_dss_rotation_angle { | |||
162 | 180 | ||
163 | enum omap_overlay_caps { | 181 | enum omap_overlay_caps { |
164 | OMAP_DSS_OVL_CAP_SCALE = 1 << 0, | 182 | OMAP_DSS_OVL_CAP_SCALE = 1 << 0, |
165 | OMAP_DSS_OVL_CAP_DISPC = 1 << 1, | 183 | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA = 1 << 1, |
184 | OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA = 1 << 2, | ||
185 | OMAP_DSS_OVL_CAP_ZORDER = 1 << 3, | ||
166 | }; | 186 | }; |
167 | 187 | ||
168 | enum omap_overlay_manager_caps { | 188 | enum omap_overlay_manager_caps { |
169 | OMAP_DSS_OVL_MGR_CAP_DISPC = 1 << 0, | 189 | OMAP_DSS_DUMMY_VALUE, /* add a dummy value to prevent compiler error */ |
170 | }; | 190 | }; |
171 | 191 | ||
172 | enum omap_dss_clk_source { | 192 | enum omap_dss_clk_source { |
@@ -215,26 +235,67 @@ void rfbi_bus_lock(void); | |||
215 | void rfbi_bus_unlock(void); | 235 | void rfbi_bus_unlock(void); |
216 | 236 | ||
217 | /* DSI */ | 237 | /* DSI */ |
238 | |||
239 | struct omap_dss_dsi_videomode_data { | ||
240 | /* DSI video mode blanking data */ | ||
241 | /* Unit: byte clock cycles */ | ||
242 | u16 hsa; | ||
243 | u16 hfp; | ||
244 | u16 hbp; | ||
245 | /* Unit: line clocks */ | ||
246 | u16 vsa; | ||
247 | u16 vfp; | ||
248 | u16 vbp; | ||
249 | |||
250 | /* DSI blanking modes */ | ||
251 | int blanking_mode; | ||
252 | int hsa_blanking_mode; | ||
253 | int hbp_blanking_mode; | ||
254 | int hfp_blanking_mode; | ||
255 | |||
256 | /* Video port sync events */ | ||
257 | int vp_de_pol; | ||
258 | int vp_hsync_pol; | ||
259 | int vp_vsync_pol; | ||
260 | bool vp_vsync_end; | ||
261 | bool vp_hsync_end; | ||
262 | |||
263 | bool ddr_clk_always_on; | ||
264 | int window_sync; | ||
265 | }; | ||
266 | |||
218 | void dsi_bus_lock(struct omap_dss_device *dssdev); | 267 | void dsi_bus_lock(struct omap_dss_device *dssdev); |
219 | void dsi_bus_unlock(struct omap_dss_device *dssdev); | 268 | void dsi_bus_unlock(struct omap_dss_device *dssdev); |
220 | int dsi_vc_dcs_write(struct omap_dss_device *dssdev, int channel, u8 *data, | 269 | int dsi_vc_dcs_write(struct omap_dss_device *dssdev, int channel, u8 *data, |
221 | int len); | 270 | int len); |
222 | int dsi_vc_dcs_write_0(struct omap_dss_device *dssdev, int channel, | 271 | int dsi_vc_generic_write(struct omap_dss_device *dssdev, int channel, u8 *data, |
223 | u8 dcs_cmd); | 272 | int len); |
273 | int dsi_vc_dcs_write_0(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd); | ||
274 | int dsi_vc_generic_write_0(struct omap_dss_device *dssdev, int channel); | ||
224 | int dsi_vc_dcs_write_1(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd, | 275 | int dsi_vc_dcs_write_1(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd, |
225 | u8 param); | 276 | u8 param); |
277 | int dsi_vc_generic_write_1(struct omap_dss_device *dssdev, int channel, | ||
278 | u8 param); | ||
279 | int dsi_vc_generic_write_2(struct omap_dss_device *dssdev, int channel, | ||
280 | u8 param1, u8 param2); | ||
226 | int dsi_vc_dcs_write_nosync(struct omap_dss_device *dssdev, int channel, | 281 | int dsi_vc_dcs_write_nosync(struct omap_dss_device *dssdev, int channel, |
227 | u8 *data, int len); | 282 | u8 *data, int len); |
283 | int dsi_vc_generic_write_nosync(struct omap_dss_device *dssdev, int channel, | ||
284 | u8 *data, int len); | ||
228 | int dsi_vc_dcs_read(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd, | 285 | int dsi_vc_dcs_read(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd, |
229 | u8 *buf, int buflen); | 286 | u8 *buf, int buflen); |
230 | int dsi_vc_dcs_read_1(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd, | 287 | int dsi_vc_generic_read_0(struct omap_dss_device *dssdev, int channel, u8 *buf, |
231 | u8 *data); | 288 | int buflen); |
232 | int dsi_vc_dcs_read_2(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd, | 289 | int dsi_vc_generic_read_1(struct omap_dss_device *dssdev, int channel, u8 param, |
233 | u8 *data1, u8 *data2); | 290 | u8 *buf, int buflen); |
291 | int dsi_vc_generic_read_2(struct omap_dss_device *dssdev, int channel, | ||
292 | u8 param1, u8 param2, u8 *buf, int buflen); | ||
234 | int dsi_vc_set_max_rx_packet_size(struct omap_dss_device *dssdev, int channel, | 293 | int dsi_vc_set_max_rx_packet_size(struct omap_dss_device *dssdev, int channel, |
235 | u16 len); | 294 | u16 len); |
236 | int dsi_vc_send_null(struct omap_dss_device *dssdev, int channel); | 295 | int dsi_vc_send_null(struct omap_dss_device *dssdev, int channel); |
237 | int dsi_vc_send_bta_sync(struct omap_dss_device *dssdev, int channel); | 296 | int dsi_vc_send_bta_sync(struct omap_dss_device *dssdev, int channel); |
297 | int dsi_video_mode_enable(struct omap_dss_device *dssdev, int channel); | ||
298 | void dsi_video_mode_disable(struct omap_dss_device *dssdev, int channel); | ||
238 | 299 | ||
239 | /* Board specific data */ | 300 | /* Board specific data */ |
240 | struct omap_dss_board_info { | 301 | struct omap_dss_board_info { |
@@ -242,7 +303,8 @@ struct omap_dss_board_info { | |||
242 | int num_devices; | 303 | int num_devices; |
243 | struct omap_dss_device **devices; | 304 | struct omap_dss_device **devices; |
244 | struct omap_dss_device *default_device; | 305 | struct omap_dss_device *default_device; |
245 | void (*dsi_mux_pads)(bool enable); | 306 | int (*dsi_enable_pads)(int dsi_id, unsigned lane_mask); |
307 | void (*dsi_disable_pads)(int dsi_id, unsigned lane_mask); | ||
246 | }; | 308 | }; |
247 | 309 | ||
248 | #if defined(CONFIG_OMAP2_DSS_MODULE) || defined(CONFIG_OMAP2_DSS) | 310 | #if defined(CONFIG_OMAP2_DSS_MODULE) || defined(CONFIG_OMAP2_DSS) |
@@ -300,7 +362,6 @@ struct omap_overlay_info { | |||
300 | bool enabled; | 362 | bool enabled; |
301 | 363 | ||
302 | u32 paddr; | 364 | u32 paddr; |
303 | void __iomem *vaddr; | ||
304 | u32 p_uv_addr; /* for NV12 format */ | 365 | u32 p_uv_addr; /* for NV12 format */ |
305 | u16 screen_width; | 366 | u16 screen_width; |
306 | u16 width; | 367 | u16 width; |
@@ -316,6 +377,7 @@ struct omap_overlay_info { | |||
316 | u16 out_height; /* if 0, out_height == height */ | 377 | u16 out_height; /* if 0, out_height == height */ |
317 | u8 global_alpha; | 378 | u8 global_alpha; |
318 | u8 pre_mult_alpha; | 379 | u8 pre_mult_alpha; |
380 | u8 zorder; | ||
319 | }; | 381 | }; |
320 | 382 | ||
321 | struct omap_overlay { | 383 | struct omap_overlay { |
@@ -324,7 +386,7 @@ struct omap_overlay { | |||
324 | 386 | ||
325 | /* static fields */ | 387 | /* static fields */ |
326 | const char *name; | 388 | const char *name; |
327 | int id; | 389 | enum omap_plane id; |
328 | enum omap_color_mode supported_modes; | 390 | enum omap_color_mode supported_modes; |
329 | enum omap_overlay_caps caps; | 391 | enum omap_overlay_caps caps; |
330 | 392 | ||
@@ -332,6 +394,7 @@ struct omap_overlay { | |||
332 | struct omap_overlay_manager *manager; | 394 | struct omap_overlay_manager *manager; |
333 | struct omap_overlay_info info; | 395 | struct omap_overlay_info info; |
334 | 396 | ||
397 | bool manager_changed; | ||
335 | /* if true, info has been changed, but not applied() yet */ | 398 | /* if true, info has been changed, but not applied() yet */ |
336 | bool info_dirty; | 399 | bool info_dirty; |
337 | 400 | ||
@@ -354,7 +417,7 @@ struct omap_overlay_manager_info { | |||
354 | u32 trans_key; | 417 | u32 trans_key; |
355 | bool trans_enabled; | 418 | bool trans_enabled; |
356 | 419 | ||
357 | bool alpha_enabled; | 420 | bool partial_alpha_enabled; |
358 | 421 | ||
359 | bool cpr_enable; | 422 | bool cpr_enable; |
360 | struct omap_dss_cpr_coefs cpr_coefs; | 423 | struct omap_dss_cpr_coefs cpr_coefs; |
@@ -366,7 +429,7 @@ struct omap_overlay_manager { | |||
366 | 429 | ||
367 | /* static fields */ | 430 | /* static fields */ |
368 | const char *name; | 431 | const char *name; |
369 | int id; | 432 | enum omap_channel id; |
370 | enum omap_overlay_manager_caps caps; | 433 | enum omap_overlay_manager_caps caps; |
371 | int num_overlays; | 434 | int num_overlays; |
372 | struct omap_overlay **overlays; | 435 | struct omap_overlay **overlays; |
@@ -454,6 +517,7 @@ struct omap_dss_device { | |||
454 | } dispc; | 517 | } dispc; |
455 | 518 | ||
456 | struct { | 519 | struct { |
520 | /* regn is one greater than TRM's REGN value */ | ||
457 | u16 regn; | 521 | u16 regn; |
458 | u16 regm; | 522 | u16 regm; |
459 | u16 regm_dispc; | 523 | u16 regm_dispc; |
@@ -464,6 +528,7 @@ struct omap_dss_device { | |||
464 | } dsi; | 528 | } dsi; |
465 | 529 | ||
466 | struct { | 530 | struct { |
531 | /* regn is one greater than TRM's REGN value */ | ||
467 | u16 regn; | 532 | u16 regn; |
468 | u16 regm2; | 533 | u16 regm2; |
469 | } hdmi; | 534 | } hdmi; |
@@ -477,6 +542,10 @@ struct omap_dss_device { | |||
477 | int acb; /* ac-bias pin frequency */ | 542 | int acb; /* ac-bias pin frequency */ |
478 | 543 | ||
479 | enum omap_panel_config config; | 544 | enum omap_panel_config config; |
545 | |||
546 | enum omap_dss_dsi_pixel_format dsi_pix_fmt; | ||
547 | enum omap_dss_dsi_mode dsi_mode; | ||
548 | struct omap_dss_dsi_videomode_data dsi_vm_data; | ||
480 | } panel; | 549 | } panel; |
481 | 550 | ||
482 | struct { | 551 | struct { |
@@ -557,6 +626,9 @@ struct omap_dss_driver { | |||
557 | 626 | ||
558 | int (*set_wss)(struct omap_dss_device *dssdev, u32 wss); | 627 | int (*set_wss)(struct omap_dss_device *dssdev, u32 wss); |
559 | u32 (*get_wss)(struct omap_dss_device *dssdev); | 628 | u32 (*get_wss)(struct omap_dss_device *dssdev); |
629 | |||
630 | int (*read_edid)(struct omap_dss_device *dssdev, u8 *buf, int len); | ||
631 | bool (*detect)(struct omap_dss_device *dssdev); | ||
560 | }; | 632 | }; |
561 | 633 | ||
562 | int omap_dss_register_driver(struct omap_dss_driver *); | 634 | int omap_dss_register_driver(struct omap_dss_driver *); |
diff --git a/include/video/sh_mobile_lcdc.h b/include/video/sh_mobile_lcdc.h index d964e68fc61d..8101b726b48a 100644 --- a/include/video/sh_mobile_lcdc.h +++ b/include/video/sh_mobile_lcdc.h | |||
@@ -4,26 +4,123 @@ | |||
4 | #include <linux/fb.h> | 4 | #include <linux/fb.h> |
5 | #include <video/sh_mobile_meram.h> | 5 | #include <video/sh_mobile_meram.h> |
6 | 6 | ||
7 | /* Register definitions */ | ||
8 | #define _LDDCKR 0x410 | ||
9 | #define LDDCKR_ICKSEL_BUS (0 << 16) | ||
10 | #define LDDCKR_ICKSEL_MIPI (1 << 16) | ||
11 | #define LDDCKR_ICKSEL_HDMI (2 << 16) | ||
12 | #define LDDCKR_ICKSEL_EXT (3 << 16) | ||
13 | #define LDDCKR_ICKSEL_MASK (7 << 16) | ||
14 | #define LDDCKR_MOSEL (1 << 6) | ||
15 | #define _LDDCKSTPR 0x414 | ||
16 | #define _LDINTR 0x468 | ||
17 | #define LDINTR_FE (1 << 10) | ||
18 | #define LDINTR_VSE (1 << 9) | ||
19 | #define LDINTR_VEE (1 << 8) | ||
20 | #define LDINTR_FS (1 << 2) | ||
21 | #define LDINTR_VSS (1 << 1) | ||
22 | #define LDINTR_VES (1 << 0) | ||
23 | #define LDINTR_STATUS_MASK (0xff << 0) | ||
24 | #define _LDSR 0x46c | ||
25 | #define LDSR_MSS (1 << 10) | ||
26 | #define LDSR_MRS (1 << 8) | ||
27 | #define LDSR_AS (1 << 1) | ||
28 | #define _LDCNT1R 0x470 | ||
29 | #define LDCNT1R_DE (1 << 0) | ||
30 | #define _LDCNT2R 0x474 | ||
31 | #define LDCNT2R_BR (1 << 8) | ||
32 | #define LDCNT2R_MD (1 << 3) | ||
33 | #define LDCNT2R_SE (1 << 2) | ||
34 | #define LDCNT2R_ME (1 << 1) | ||
35 | #define LDCNT2R_DO (1 << 0) | ||
36 | #define _LDRCNTR 0x478 | ||
37 | #define LDRCNTR_SRS (1 << 17) | ||
38 | #define LDRCNTR_SRC (1 << 16) | ||
39 | #define LDRCNTR_MRS (1 << 1) | ||
40 | #define LDRCNTR_MRC (1 << 0) | ||
41 | #define _LDDDSR 0x47c | ||
42 | #define LDDDSR_LS (1 << 2) | ||
43 | #define LDDDSR_WS (1 << 1) | ||
44 | #define LDDDSR_BS (1 << 0) | ||
45 | |||
46 | #define LDMT1R_VPOL (1 << 28) | ||
47 | #define LDMT1R_HPOL (1 << 27) | ||
48 | #define LDMT1R_DWPOL (1 << 26) | ||
49 | #define LDMT1R_DIPOL (1 << 25) | ||
50 | #define LDMT1R_DAPOL (1 << 24) | ||
51 | #define LDMT1R_HSCNT (1 << 17) | ||
52 | #define LDMT1R_DWCNT (1 << 16) | ||
53 | #define LDMT1R_IFM (1 << 12) | ||
54 | #define LDMT1R_MIFTYP_RGB8 (0x0 << 0) | ||
55 | #define LDMT1R_MIFTYP_RGB9 (0x4 << 0) | ||
56 | #define LDMT1R_MIFTYP_RGB12A (0x5 << 0) | ||
57 | #define LDMT1R_MIFTYP_RGB12B (0x6 << 0) | ||
58 | #define LDMT1R_MIFTYP_RGB16 (0x7 << 0) | ||
59 | #define LDMT1R_MIFTYP_RGB18 (0xa << 0) | ||
60 | #define LDMT1R_MIFTYP_RGB24 (0xb << 0) | ||
61 | #define LDMT1R_MIFTYP_YCBCR (0xf << 0) | ||
62 | #define LDMT1R_MIFTYP_SYS8A (0x0 << 0) | ||
63 | #define LDMT1R_MIFTYP_SYS8B (0x1 << 0) | ||
64 | #define LDMT1R_MIFTYP_SYS8C (0x2 << 0) | ||
65 | #define LDMT1R_MIFTYP_SYS8D (0x3 << 0) | ||
66 | #define LDMT1R_MIFTYP_SYS9 (0x4 << 0) | ||
67 | #define LDMT1R_MIFTYP_SYS12 (0x5 << 0) | ||
68 | #define LDMT1R_MIFTYP_SYS16A (0x7 << 0) | ||
69 | #define LDMT1R_MIFTYP_SYS16B (0x8 << 0) | ||
70 | #define LDMT1R_MIFTYP_SYS16C (0x9 << 0) | ||
71 | #define LDMT1R_MIFTYP_SYS18 (0xa << 0) | ||
72 | #define LDMT1R_MIFTYP_SYS24 (0xb << 0) | ||
73 | #define LDMT1R_MIFTYP_MASK (0xf << 0) | ||
74 | |||
75 | #define LDDFR_CF1 (1 << 18) | ||
76 | #define LDDFR_CF0 (1 << 17) | ||
77 | #define LDDFR_CC (1 << 16) | ||
78 | #define LDDFR_YF_420 (0 << 8) | ||
79 | #define LDDFR_YF_422 (1 << 8) | ||
80 | #define LDDFR_YF_444 (2 << 8) | ||
81 | #define LDDFR_YF_MASK (3 << 8) | ||
82 | #define LDDFR_PKF_ARGB32 (0x00 << 0) | ||
83 | #define LDDFR_PKF_RGB16 (0x03 << 0) | ||
84 | #define LDDFR_PKF_RGB24 (0x0b << 0) | ||
85 | #define LDDFR_PKF_MASK (0x1f << 0) | ||
86 | |||
87 | #define LDSM1R_OS (1 << 0) | ||
88 | |||
89 | #define LDSM2R_OSTRG (1 << 0) | ||
90 | |||
91 | #define LDPMR_LPS (3 << 0) | ||
92 | |||
93 | #define _LDDWD0R 0x800 | ||
94 | #define LDDWDxR_WDACT (1 << 28) | ||
95 | #define LDDWDxR_RSW (1 << 24) | ||
96 | #define _LDDRDR 0x840 | ||
97 | #define LDDRDR_RSR (1 << 24) | ||
98 | #define LDDRDR_DRD_MASK (0x3ffff << 0) | ||
99 | #define _LDDWAR 0x900 | ||
100 | #define LDDWAR_WA (1 << 0) | ||
101 | #define _LDDRAR 0x904 | ||
102 | #define LDDRAR_RA (1 << 0) | ||
103 | |||
7 | enum { | 104 | enum { |
8 | RGB8, /* 24bpp, 8:8:8 */ | 105 | RGB8 = LDMT1R_MIFTYP_RGB8, /* 24bpp, 8:8:8 */ |
9 | RGB9, /* 18bpp, 9:9 */ | 106 | RGB9 = LDMT1R_MIFTYP_RGB9, /* 18bpp, 9:9 */ |
10 | RGB12A, /* 24bpp, 12:12 */ | 107 | RGB12A = LDMT1R_MIFTYP_RGB12A, /* 24bpp, 12:12 */ |
11 | RGB12B, /* 12bpp */ | 108 | RGB12B = LDMT1R_MIFTYP_RGB12B, /* 12bpp */ |
12 | RGB16, /* 16bpp */ | 109 | RGB16 = LDMT1R_MIFTYP_RGB16, /* 16bpp */ |
13 | RGB18, /* 18bpp */ | 110 | RGB18 = LDMT1R_MIFTYP_RGB18, /* 18bpp */ |
14 | RGB24, /* 24bpp */ | 111 | RGB24 = LDMT1R_MIFTYP_RGB24, /* 24bpp */ |
15 | YUV422, /* 16bpp */ | 112 | YUV422 = LDMT1R_MIFTYP_YCBCR, /* 16bpp */ |
16 | SYS8A, /* 24bpp, 8:8:8 */ | 113 | SYS8A = LDMT1R_IFM | LDMT1R_MIFTYP_SYS8A, /* 24bpp, 8:8:8 */ |
17 | SYS8B, /* 18bpp, 8:8:2 */ | 114 | SYS8B = LDMT1R_IFM | LDMT1R_MIFTYP_SYS8B, /* 18bpp, 8:8:2 */ |
18 | SYS8C, /* 18bpp, 2:8:8 */ | 115 | SYS8C = LDMT1R_IFM | LDMT1R_MIFTYP_SYS8C, /* 18bpp, 2:8:8 */ |
19 | SYS8D, /* 16bpp, 8:8 */ | 116 | SYS8D = LDMT1R_IFM | LDMT1R_MIFTYP_SYS8D, /* 16bpp, 8:8 */ |
20 | SYS9, /* 18bpp, 9:9 */ | 117 | SYS9 = LDMT1R_IFM | LDMT1R_MIFTYP_SYS9, /* 18bpp, 9:9 */ |
21 | SYS12, /* 24bpp, 12:12 */ | 118 | SYS12 = LDMT1R_IFM | LDMT1R_MIFTYP_SYS12, /* 24bpp, 12:12 */ |
22 | SYS16A, /* 16bpp */ | 119 | SYS16A = LDMT1R_IFM | LDMT1R_MIFTYP_SYS16A, /* 16bpp */ |
23 | SYS16B, /* 18bpp, 16:2 */ | 120 | SYS16B = LDMT1R_IFM | LDMT1R_MIFTYP_SYS16B, /* 18bpp, 16:2 */ |
24 | SYS16C, /* 18bpp, 2:16 */ | 121 | SYS16C = LDMT1R_IFM | LDMT1R_MIFTYP_SYS16C, /* 18bpp, 2:16 */ |
25 | SYS18, /* 18bpp */ | 122 | SYS18 = LDMT1R_IFM | LDMT1R_MIFTYP_SYS18, /* 18bpp */ |
26 | SYS24, /* 24bpp */ | 123 | SYS24 = LDMT1R_IFM | LDMT1R_MIFTYP_SYS24, /* 24bpp */ |
27 | }; | 124 | }; |
28 | 125 | ||
29 | enum { LCDC_CHAN_DISABLED = 0, | 126 | enum { LCDC_CHAN_DISABLED = 0, |
diff --git a/include/video/udlfb.h b/include/video/udlfb.h index 69d485a4a026..c41f308c9636 100644 --- a/include/video/udlfb.h +++ b/include/video/udlfb.h | |||
@@ -50,6 +50,7 @@ struct dlfb_data { | |||
50 | int base16; | 50 | int base16; |
51 | int base8; | 51 | int base8; |
52 | u32 pseudo_palette[256]; | 52 | u32 pseudo_palette[256]; |
53 | int blank_mode; /*one of FB_BLANK_ */ | ||
53 | /* blit-only rendering path metrics, exposed through sysfs */ | 54 | /* blit-only rendering path metrics, exposed through sysfs */ |
54 | atomic_t bytes_rendered; /* raw pixel-bytes driver asked to render */ | 55 | atomic_t bytes_rendered; /* raw pixel-bytes driver asked to render */ |
55 | atomic_t bytes_identical; /* saved effort with backbuffer comparison */ | 56 | atomic_t bytes_identical; /* saved effort with backbuffer comparison */ |