diff options
Diffstat (limited to 'drivers/video')
33 files changed, 705 insertions, 393 deletions
diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c index f8e711147501..fc65c02306dd 100644 --- a/drivers/video/atmel_lcdfb.c +++ b/drivers/video/atmel_lcdfb.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/fb.h> | 16 | #include <linux/fb.h> |
17 | #include <linux/init.h> | 17 | #include <linux/init.h> |
18 | #include <linux/delay.h> | 18 | #include <linux/delay.h> |
19 | #include <linux/backlight.h> | ||
19 | 20 | ||
20 | #include <asm/arch/board.h> | 21 | #include <asm/arch/board.h> |
21 | #include <asm/arch/cpu.h> | 22 | #include <asm/arch/cpu.h> |
@@ -69,6 +70,107 @@ static void atmel_lcdfb_update_dma2d(struct atmel_lcdfb_info *sinfo, | |||
69 | } | 70 | } |
70 | #endif | 71 | #endif |
71 | 72 | ||
73 | static const u32 contrast_ctr = ATMEL_LCDC_PS_DIV8 | ||
74 | | ATMEL_LCDC_POL_POSITIVE | ||
75 | | ATMEL_LCDC_ENA_PWMENABLE; | ||
76 | |||
77 | #ifdef CONFIG_BACKLIGHT_ATMEL_LCDC | ||
78 | |||
79 | /* some bl->props field just changed */ | ||
80 | static int atmel_bl_update_status(struct backlight_device *bl) | ||
81 | { | ||
82 | struct atmel_lcdfb_info *sinfo = bl_get_data(bl); | ||
83 | int power = sinfo->bl_power; | ||
84 | int brightness = bl->props.brightness; | ||
85 | |||
86 | /* REVISIT there may be a meaningful difference between | ||
87 | * fb_blank and power ... there seem to be some cases | ||
88 | * this doesn't handle correctly. | ||
89 | */ | ||
90 | if (bl->props.fb_blank != sinfo->bl_power) | ||
91 | power = bl->props.fb_blank; | ||
92 | else if (bl->props.power != sinfo->bl_power) | ||
93 | power = bl->props.power; | ||
94 | |||
95 | if (brightness < 0 && power == FB_BLANK_UNBLANK) | ||
96 | brightness = lcdc_readl(sinfo, ATMEL_LCDC_CONTRAST_VAL); | ||
97 | else if (power != FB_BLANK_UNBLANK) | ||
98 | brightness = 0; | ||
99 | |||
100 | lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_VAL, brightness); | ||
101 | lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, | ||
102 | brightness ? contrast_ctr : 0); | ||
103 | |||
104 | bl->props.fb_blank = bl->props.power = sinfo->bl_power = power; | ||
105 | |||
106 | return 0; | ||
107 | } | ||
108 | |||
109 | static int atmel_bl_get_brightness(struct backlight_device *bl) | ||
110 | { | ||
111 | struct atmel_lcdfb_info *sinfo = bl_get_data(bl); | ||
112 | |||
113 | return lcdc_readl(sinfo, ATMEL_LCDC_CONTRAST_VAL); | ||
114 | } | ||
115 | |||
116 | static struct backlight_ops atmel_lcdc_bl_ops = { | ||
117 | .update_status = atmel_bl_update_status, | ||
118 | .get_brightness = atmel_bl_get_brightness, | ||
119 | }; | ||
120 | |||
121 | static void init_backlight(struct atmel_lcdfb_info *sinfo) | ||
122 | { | ||
123 | struct backlight_device *bl; | ||
124 | |||
125 | sinfo->bl_power = FB_BLANK_UNBLANK; | ||
126 | |||
127 | if (sinfo->backlight) | ||
128 | return; | ||
129 | |||
130 | bl = backlight_device_register("backlight", &sinfo->pdev->dev, | ||
131 | sinfo, &atmel_lcdc_bl_ops); | ||
132 | if (IS_ERR(sinfo->backlight)) { | ||
133 | dev_err(&sinfo->pdev->dev, "error %ld on backlight register\n", | ||
134 | PTR_ERR(bl)); | ||
135 | return; | ||
136 | } | ||
137 | sinfo->backlight = bl; | ||
138 | |||
139 | bl->props.power = FB_BLANK_UNBLANK; | ||
140 | bl->props.fb_blank = FB_BLANK_UNBLANK; | ||
141 | bl->props.max_brightness = 0xff; | ||
142 | bl->props.brightness = atmel_bl_get_brightness(bl); | ||
143 | } | ||
144 | |||
145 | static void exit_backlight(struct atmel_lcdfb_info *sinfo) | ||
146 | { | ||
147 | if (sinfo->backlight) | ||
148 | backlight_device_unregister(sinfo->backlight); | ||
149 | } | ||
150 | |||
151 | #else | ||
152 | |||
153 | static void init_backlight(struct atmel_lcdfb_info *sinfo) | ||
154 | { | ||
155 | dev_warn(&sinfo->pdev->dev, "backlight control is not available\n"); | ||
156 | } | ||
157 | |||
158 | static void exit_backlight(struct atmel_lcdfb_info *sinfo) | ||
159 | { | ||
160 | } | ||
161 | |||
162 | #endif | ||
163 | |||
164 | static void init_contrast(struct atmel_lcdfb_info *sinfo) | ||
165 | { | ||
166 | /* have some default contrast/backlight settings */ | ||
167 | lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, contrast_ctr); | ||
168 | lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_VAL, ATMEL_LCDC_CVAL_DEFAULT); | ||
169 | |||
170 | if (sinfo->lcdcon_is_backlight) | ||
171 | init_backlight(sinfo); | ||
172 | } | ||
173 | |||
72 | 174 | ||
73 | static struct fb_fix_screeninfo atmel_lcdfb_fix __initdata = { | 175 | static struct fb_fix_screeninfo atmel_lcdfb_fix __initdata = { |
74 | .type = FB_TYPE_PACKED_PIXELS, | 176 | .type = FB_TYPE_PACKED_PIXELS, |
@@ -203,6 +305,26 @@ static int atmel_lcdfb_check_var(struct fb_var_screeninfo *var, | |||
203 | var->transp.offset = var->transp.length = 0; | 305 | var->transp.offset = var->transp.length = 0; |
204 | var->xoffset = var->yoffset = 0; | 306 | var->xoffset = var->yoffset = 0; |
205 | 307 | ||
308 | /* Saturate vertical and horizontal timings at maximum values */ | ||
309 | var->vsync_len = min_t(u32, var->vsync_len, | ||
310 | (ATMEL_LCDC_VPW >> ATMEL_LCDC_VPW_OFFSET) + 1); | ||
311 | var->upper_margin = min_t(u32, var->upper_margin, | ||
312 | ATMEL_LCDC_VBP >> ATMEL_LCDC_VBP_OFFSET); | ||
313 | var->lower_margin = min_t(u32, var->lower_margin, | ||
314 | ATMEL_LCDC_VFP); | ||
315 | var->right_margin = min_t(u32, var->right_margin, | ||
316 | (ATMEL_LCDC_HFP >> ATMEL_LCDC_HFP_OFFSET) + 1); | ||
317 | var->hsync_len = min_t(u32, var->hsync_len, | ||
318 | (ATMEL_LCDC_HPW >> ATMEL_LCDC_HPW_OFFSET) + 1); | ||
319 | var->left_margin = min_t(u32, var->left_margin, | ||
320 | ATMEL_LCDC_HBP + 1); | ||
321 | |||
322 | /* Some parameters can't be zero */ | ||
323 | var->vsync_len = max_t(u32, var->vsync_len, 1); | ||
324 | var->right_margin = max_t(u32, var->right_margin, 1); | ||
325 | var->hsync_len = max_t(u32, var->hsync_len, 1); | ||
326 | var->left_margin = max_t(u32, var->left_margin, 1); | ||
327 | |||
206 | switch (var->bits_per_pixel) { | 328 | switch (var->bits_per_pixel) { |
207 | case 1: | 329 | case 1: |
208 | case 2: | 330 | case 2: |
@@ -370,10 +492,6 @@ static int atmel_lcdfb_set_par(struct fb_info *info) | |||
370 | /* Disable all interrupts */ | 492 | /* Disable all interrupts */ |
371 | lcdc_writel(sinfo, ATMEL_LCDC_IDR, ~0UL); | 493 | lcdc_writel(sinfo, ATMEL_LCDC_IDR, ~0UL); |
372 | 494 | ||
373 | /* Set contrast */ | ||
374 | value = ATMEL_LCDC_PS_DIV8 | ATMEL_LCDC_POL_POSITIVE | ATMEL_LCDC_ENA_PWMENABLE; | ||
375 | lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, value); | ||
376 | lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_VAL, ATMEL_LCDC_CVAL_DEFAULT); | ||
377 | /* ...wait for DMA engine to become idle... */ | 495 | /* ...wait for DMA engine to become idle... */ |
378 | while (lcdc_readl(sinfo, ATMEL_LCDC_DMACON) & ATMEL_LCDC_DMABUSY) | 496 | while (lcdc_readl(sinfo, ATMEL_LCDC_DMACON) & ATMEL_LCDC_DMABUSY) |
379 | msleep(10); | 497 | msleep(10); |
@@ -577,6 +695,7 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev) | |||
577 | sinfo->default_monspecs = pdata_sinfo->default_monspecs; | 695 | sinfo->default_monspecs = pdata_sinfo->default_monspecs; |
578 | sinfo->atmel_lcdfb_power_control = pdata_sinfo->atmel_lcdfb_power_control; | 696 | sinfo->atmel_lcdfb_power_control = pdata_sinfo->atmel_lcdfb_power_control; |
579 | sinfo->guard_time = pdata_sinfo->guard_time; | 697 | sinfo->guard_time = pdata_sinfo->guard_time; |
698 | sinfo->lcdcon_is_backlight = pdata_sinfo->lcdcon_is_backlight; | ||
580 | } else { | 699 | } else { |
581 | dev_err(dev, "cannot get default configuration\n"); | 700 | dev_err(dev, "cannot get default configuration\n"); |
582 | goto free_info; | 701 | goto free_info; |
@@ -670,6 +789,9 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev) | |||
670 | goto release_mem; | 789 | goto release_mem; |
671 | } | 790 | } |
672 | 791 | ||
792 | /* Initialize PWM for contrast or backlight ("off") */ | ||
793 | init_contrast(sinfo); | ||
794 | |||
673 | /* interrupt */ | 795 | /* interrupt */ |
674 | ret = request_irq(sinfo->irq_base, atmel_lcdfb_interrupt, 0, pdev->name, info); | 796 | ret = request_irq(sinfo->irq_base, atmel_lcdfb_interrupt, 0, pdev->name, info); |
675 | if (ret) { | 797 | if (ret) { |
@@ -721,6 +843,7 @@ free_cmap: | |||
721 | unregister_irqs: | 843 | unregister_irqs: |
722 | free_irq(sinfo->irq_base, info); | 844 | free_irq(sinfo->irq_base, info); |
723 | unmap_mmio: | 845 | unmap_mmio: |
846 | exit_backlight(sinfo); | ||
724 | iounmap(sinfo->mmio); | 847 | iounmap(sinfo->mmio); |
725 | release_mem: | 848 | release_mem: |
726 | release_mem_region(info->fix.mmio_start, info->fix.mmio_len); | 849 | release_mem_region(info->fix.mmio_start, info->fix.mmio_len); |
@@ -755,6 +878,7 @@ static int __exit atmel_lcdfb_remove(struct platform_device *pdev) | |||
755 | if (!sinfo) | 878 | if (!sinfo) |
756 | return 0; | 879 | return 0; |
757 | 880 | ||
881 | exit_backlight(sinfo); | ||
758 | if (sinfo->atmel_lcdfb_power_control) | 882 | if (sinfo->atmel_lcdfb_power_control) |
759 | sinfo->atmel_lcdfb_power_control(0); | 883 | sinfo->atmel_lcdfb_power_control(0); |
760 | unregister_framebuffer(info); | 884 | unregister_framebuffer(info); |
@@ -781,6 +905,9 @@ static int __exit atmel_lcdfb_remove(struct platform_device *pdev) | |||
781 | 905 | ||
782 | static struct platform_driver atmel_lcdfb_driver = { | 906 | static struct platform_driver atmel_lcdfb_driver = { |
783 | .remove = __exit_p(atmel_lcdfb_remove), | 907 | .remove = __exit_p(atmel_lcdfb_remove), |
908 | |||
909 | // FIXME need suspend, resume | ||
910 | |||
784 | .driver = { | 911 | .driver = { |
785 | .name = "atmel_lcdfb", | 912 | .name = "atmel_lcdfb", |
786 | .owner = THIS_MODULE, | 913 | .owner = THIS_MODULE, |
diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig index 9609a6c676be..924e2551044a 100644 --- a/drivers/video/backlight/Kconfig +++ b/drivers/video/backlight/Kconfig | |||
@@ -50,6 +50,19 @@ config BACKLIGHT_CLASS_DEVICE | |||
50 | To have support for your specific LCD panel you will have to | 50 | To have support for your specific LCD panel you will have to |
51 | select the proper drivers which depend on this option. | 51 | select the proper drivers which depend on this option. |
52 | 52 | ||
53 | config BACKLIGHT_ATMEL_LCDC | ||
54 | bool "Atmel LCDC Contrast-as-Backlight control" | ||
55 | depends on BACKLIGHT_CLASS_DEVICE && FB_ATMEL | ||
56 | default y if MACH_SAM9261EK || MACH_SAM9263EK | ||
57 | help | ||
58 | This provides a backlight control internal to the Atmel LCDC | ||
59 | driver. If the LCD "contrast control" on your board is wired | ||
60 | so it controls the backlight brightness, select this option to | ||
61 | export this as a PWM-based backlight control. | ||
62 | |||
63 | If in doubt, it's safe to enable this option; it doesn't kick | ||
64 | in unless the board's description says it's wired that way. | ||
65 | |||
53 | config BACKLIGHT_CORGI | 66 | config BACKLIGHT_CORGI |
54 | tristate "Generic (aka Sharp Corgi) Backlight Driver" | 67 | tristate "Generic (aka Sharp Corgi) Backlight Driver" |
55 | depends on BACKLIGHT_CLASS_DEVICE | 68 | depends on BACKLIGHT_CLASS_DEVICE |
diff --git a/drivers/video/bf54x-lq043fb.c b/drivers/video/bf54x-lq043fb.c index c8e7427a0bc8..0ce791e6f79c 100644 --- a/drivers/video/bf54x-lq043fb.c +++ b/drivers/video/bf54x-lq043fb.c | |||
@@ -498,8 +498,7 @@ static struct lcd_device *lcd_dev; | |||
498 | 498 | ||
499 | static irqreturn_t bfin_bf54x_irq_error(int irq, void *dev_id) | 499 | static irqreturn_t bfin_bf54x_irq_error(int irq, void *dev_id) |
500 | { | 500 | { |
501 | 501 | /*struct bfin_bf54xfb_info *info = dev_id;*/ | |
502 | /*struct bfin_bf54xfb_info *info = (struct bfin_bf54xfb_info *)dev_id;*/ | ||
503 | 502 | ||
504 | u16 status = bfin_read_EPPI0_STATUS(); | 503 | u16 status = bfin_read_EPPI0_STATUS(); |
505 | 504 | ||
diff --git a/drivers/video/console/bitblit.c b/drivers/video/console/bitblit.c index 308850df16fe..69864b1b3f9e 100644 --- a/drivers/video/console/bitblit.c +++ b/drivers/video/console/bitblit.c | |||
@@ -63,7 +63,7 @@ static void bit_clear(struct vc_data *vc, struct fb_info *info, int sy, | |||
63 | int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; | 63 | int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; |
64 | struct fb_fillrect region; | 64 | struct fb_fillrect region; |
65 | 65 | ||
66 | region.color = attr_bgcol_ec(bgshift, vc); | 66 | region.color = attr_bgcol_ec(bgshift, vc, info); |
67 | region.dx = sx * vc->vc_font.width; | 67 | region.dx = sx * vc->vc_font.width; |
68 | region.dy = sy * vc->vc_font.height; | 68 | region.dy = sy * vc->vc_font.height; |
69 | region.width = width * vc->vc_font.width; | 69 | region.width = width * vc->vc_font.width; |
@@ -213,7 +213,7 @@ static void bit_clear_margins(struct vc_data *vc, struct fb_info *info, | |||
213 | unsigned int bs = info->var.yres - bh; | 213 | unsigned int bs = info->var.yres - bh; |
214 | struct fb_fillrect region; | 214 | struct fb_fillrect region; |
215 | 215 | ||
216 | region.color = attr_bgcol_ec(bgshift, vc); | 216 | region.color = attr_bgcol_ec(bgshift, vc, info); |
217 | region.rop = ROP_COPY; | 217 | region.rop = ROP_COPY; |
218 | 218 | ||
219 | if (rw && !bottom_only) { | 219 | if (rw && !bottom_only) { |
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index 0f32f4a00b2d..022282494d3f 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c | |||
@@ -84,7 +84,7 @@ | |||
84 | #ifdef CONFIG_MAC | 84 | #ifdef CONFIG_MAC |
85 | #include <asm/macints.h> | 85 | #include <asm/macints.h> |
86 | #endif | 86 | #endif |
87 | #if defined(__mc68000__) || defined(CONFIG_APUS) | 87 | #if defined(__mc68000__) |
88 | #include <asm/machdep.h> | 88 | #include <asm/machdep.h> |
89 | #include <asm/setup.h> | 89 | #include <asm/setup.h> |
90 | #endif | 90 | #endif |
@@ -147,7 +147,7 @@ static char fontname[40]; | |||
147 | static int info_idx = -1; | 147 | static int info_idx = -1; |
148 | 148 | ||
149 | /* console rotation */ | 149 | /* console rotation */ |
150 | static int rotate; | 150 | static int initial_rotation; |
151 | static int fbcon_has_sysfs; | 151 | static int fbcon_has_sysfs; |
152 | 152 | ||
153 | static const struct consw fb_con; | 153 | static const struct consw fb_con; |
@@ -334,10 +334,7 @@ static inline int get_color(struct vc_data *vc, struct fb_info *info, | |||
334 | switch (depth) { | 334 | switch (depth) { |
335 | case 1: | 335 | case 1: |
336 | { | 336 | { |
337 | int col = ~(0xfff << (max(info->var.green.length, | 337 | int col = mono_col(info); |
338 | max(info->var.red.length, | ||
339 | info->var.blue.length)))) & 0xff; | ||
340 | |||
341 | /* 0 or 1 */ | 338 | /* 0 or 1 */ |
342 | int fg = (info->fix.visual != FB_VISUAL_MONO01) ? col : 0; | 339 | int fg = (info->fix.visual != FB_VISUAL_MONO01) ? col : 0; |
343 | int bg = (info->fix.visual != FB_VISUAL_MONO01) ? 0 : col; | 340 | int bg = (info->fix.visual != FB_VISUAL_MONO01) ? 0 : col; |
@@ -537,9 +534,9 @@ static int __init fb_console_setup(char *this_opt) | |||
537 | if (!strncmp(options, "rotate:", 7)) { | 534 | if (!strncmp(options, "rotate:", 7)) { |
538 | options += 7; | 535 | options += 7; |
539 | if (*options) | 536 | if (*options) |
540 | rotate = simple_strtoul(options, &options, 0); | 537 | initial_rotation = simple_strtoul(options, &options, 0); |
541 | if (rotate > 3) | 538 | if (initial_rotation > 3) |
542 | rotate = 0; | 539 | initial_rotation = 0; |
543 | } | 540 | } |
544 | } | 541 | } |
545 | return 1; | 542 | return 1; |
@@ -989,7 +986,7 @@ static const char *fbcon_startup(void) | |||
989 | ops->graphics = 1; | 986 | ops->graphics = 1; |
990 | ops->cur_rotate = -1; | 987 | ops->cur_rotate = -1; |
991 | info->fbcon_par = ops; | 988 | info->fbcon_par = ops; |
992 | p->con_rotate = rotate; | 989 | p->con_rotate = initial_rotation; |
993 | set_blitting_type(vc, info); | 990 | set_blitting_type(vc, info); |
994 | 991 | ||
995 | if (info->fix.type != FB_TYPE_TEXT) { | 992 | if (info->fix.type != FB_TYPE_TEXT) { |
@@ -1176,7 +1173,7 @@ static void fbcon_init(struct vc_data *vc, int init) | |||
1176 | con_copy_unimap(vc, svc); | 1173 | con_copy_unimap(vc, svc); |
1177 | 1174 | ||
1178 | ops = info->fbcon_par; | 1175 | ops = info->fbcon_par; |
1179 | p->con_rotate = rotate; | 1176 | p->con_rotate = initial_rotation; |
1180 | set_blitting_type(vc, info); | 1177 | set_blitting_type(vc, info); |
1181 | 1178 | ||
1182 | cols = vc->vc_cols; | 1179 | cols = vc->vc_cols; |
@@ -2795,7 +2792,7 @@ static int fbcon_scrolldelta(struct vc_data *vc, int lines) | |||
2795 | { | 2792 | { |
2796 | struct fb_info *info = registered_fb[con2fb_map[fg_console]]; | 2793 | struct fb_info *info = registered_fb[con2fb_map[fg_console]]; |
2797 | struct fbcon_ops *ops = info->fbcon_par; | 2794 | struct fbcon_ops *ops = info->fbcon_par; |
2798 | struct display *p = &fb_display[fg_console]; | 2795 | struct display *disp = &fb_display[fg_console]; |
2799 | int offset, limit, scrollback_old; | 2796 | int offset, limit, scrollback_old; |
2800 | 2797 | ||
2801 | if (softback_top) { | 2798 | if (softback_top) { |
@@ -2833,7 +2830,7 @@ static int fbcon_scrolldelta(struct vc_data *vc, int lines) | |||
2833 | logo_shown = FBCON_LOGO_CANSHOW; | 2830 | logo_shown = FBCON_LOGO_CANSHOW; |
2834 | } | 2831 | } |
2835 | fbcon_cursor(vc, CM_ERASE | CM_SOFTBACK); | 2832 | fbcon_cursor(vc, CM_ERASE | CM_SOFTBACK); |
2836 | fbcon_redraw_softback(vc, p, lines); | 2833 | fbcon_redraw_softback(vc, disp, lines); |
2837 | fbcon_cursor(vc, CM_DRAW | CM_SOFTBACK); | 2834 | fbcon_cursor(vc, CM_DRAW | CM_SOFTBACK); |
2838 | return 0; | 2835 | return 0; |
2839 | } | 2836 | } |
@@ -2855,9 +2852,9 @@ static int fbcon_scrolldelta(struct vc_data *vc, int lines) | |||
2855 | 2852 | ||
2856 | fbcon_cursor(vc, CM_ERASE); | 2853 | fbcon_cursor(vc, CM_ERASE); |
2857 | 2854 | ||
2858 | offset = p->yscroll - scrollback_current; | 2855 | offset = disp->yscroll - scrollback_current; |
2859 | limit = p->vrows; | 2856 | limit = disp->vrows; |
2860 | switch (p->scrollmode) { | 2857 | switch (disp->scrollmode) { |
2861 | case SCROLL_WRAP_MOVE: | 2858 | case SCROLL_WRAP_MOVE: |
2862 | info->var.vmode |= FB_VMODE_YWRAP; | 2859 | info->var.vmode |= FB_VMODE_YWRAP; |
2863 | break; | 2860 | break; |
diff --git a/drivers/video/console/fbcon.h b/drivers/video/console/fbcon.h index 8e6ef4bc7a5c..3706307e70ed 100644 --- a/drivers/video/console/fbcon.h +++ b/drivers/video/console/fbcon.h | |||
@@ -93,10 +93,6 @@ struct fbcon_ops { | |||
93 | (((s) >> (fgshift)) & 0x0f) | 93 | (((s) >> (fgshift)) & 0x0f) |
94 | #define attr_bgcol(bgshift,s) \ | 94 | #define attr_bgcol(bgshift,s) \ |
95 | (((s) >> (bgshift)) & 0x0f) | 95 | (((s) >> (bgshift)) & 0x0f) |
96 | #define attr_bgcol_ec(bgshift,vc) \ | ||
97 | ((vc) ? (((vc)->vc_video_erase_char >> (bgshift)) & 0x0f) : 0) | ||
98 | #define attr_fgcol_ec(fgshift,vc) \ | ||
99 | ((vc) ? (((vc)->vc_video_erase_char >> (fgshift)) & 0x0f) : 0) | ||
100 | 96 | ||
101 | /* Monochrome */ | 97 | /* Monochrome */ |
102 | #define attr_bold(s) \ | 98 | #define attr_bold(s) \ |
@@ -108,6 +104,49 @@ struct fbcon_ops { | |||
108 | #define attr_blink(s) \ | 104 | #define attr_blink(s) \ |
109 | ((s) & 0x8000) | 105 | ((s) & 0x8000) |
110 | 106 | ||
107 | #define mono_col(info) \ | ||
108 | (~(0xfff << (max((info)->var.green.length, \ | ||
109 | max((info)->var.red.length, \ | ||
110 | (info)->var.blue.length)))) & 0xff) | ||
111 | |||
112 | static inline int attr_col_ec(int shift, struct vc_data *vc, | ||
113 | struct fb_info *info, int is_fg) | ||
114 | { | ||
115 | int is_mono01; | ||
116 | int col; | ||
117 | int fg; | ||
118 | int bg; | ||
119 | |||
120 | if (!vc) | ||
121 | return 0; | ||
122 | |||
123 | if (vc->vc_can_do_color) | ||
124 | return is_fg ? attr_fgcol(shift,vc->vc_video_erase_char) | ||
125 | : attr_bgcol(shift,vc->vc_video_erase_char); | ||
126 | |||
127 | if (!info) | ||
128 | return 0; | ||
129 | |||
130 | col = mono_col(info); | ||
131 | is_mono01 = info->fix.visual == FB_VISUAL_MONO01; | ||
132 | |||
133 | if (attr_reverse(vc->vc_video_erase_char)) { | ||
134 | fg = is_mono01 ? col : 0; | ||
135 | bg = is_mono01 ? 0 : col; | ||
136 | } | ||
137 | else { | ||
138 | fg = is_mono01 ? 0 : col; | ||
139 | bg = is_mono01 ? col : 0; | ||
140 | } | ||
141 | |||
142 | return is_fg ? fg : bg; | ||
143 | } | ||
144 | |||
145 | #define attr_bgcol_ec(bgshift,vc,info) \ | ||
146 | attr_col_ec(bgshift,vc,info,0); | ||
147 | #define attr_fgcol_ec(fgshift,vc,info) \ | ||
148 | attr_col_ec(fgshift,vc,info,1); | ||
149 | |||
111 | /* Font */ | 150 | /* Font */ |
112 | #define REFCOUNT(fd) (((int *)(fd))[-1]) | 151 | #define REFCOUNT(fd) (((int *)(fd))[-1]) |
113 | #define FNTSIZE(fd) (((int *)(fd))[-2]) | 152 | #define FNTSIZE(fd) (((int *)(fd))[-2]) |
diff --git a/drivers/video/console/fbcon_ccw.c b/drivers/video/console/fbcon_ccw.c index 825e6d6972a7..bdf913ecf001 100644 --- a/drivers/video/console/fbcon_ccw.c +++ b/drivers/video/console/fbcon_ccw.c | |||
@@ -84,7 +84,7 @@ static void ccw_clear(struct vc_data *vc, struct fb_info *info, int sy, | |||
84 | int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; | 84 | int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; |
85 | u32 vyres = GETVYRES(ops->p->scrollmode, info); | 85 | u32 vyres = GETVYRES(ops->p->scrollmode, info); |
86 | 86 | ||
87 | region.color = attr_bgcol_ec(bgshift,vc); | 87 | region.color = attr_bgcol_ec(bgshift,vc,info); |
88 | region.dx = sy * vc->vc_font.height; | 88 | region.dx = sy * vc->vc_font.height; |
89 | region.dy = vyres - ((sx + width) * vc->vc_font.width); | 89 | region.dy = vyres - ((sx + width) * vc->vc_font.width); |
90 | region.height = width * vc->vc_font.width; | 90 | region.height = width * vc->vc_font.width; |
@@ -198,7 +198,7 @@ static void ccw_clear_margins(struct vc_data *vc, struct fb_info *info, | |||
198 | struct fb_fillrect region; | 198 | struct fb_fillrect region; |
199 | int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; | 199 | int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; |
200 | 200 | ||
201 | region.color = attr_bgcol_ec(bgshift,vc); | 201 | region.color = attr_bgcol_ec(bgshift,vc,info); |
202 | region.rop = ROP_COPY; | 202 | region.rop = ROP_COPY; |
203 | 203 | ||
204 | if (rw && !bottom_only) { | 204 | if (rw && !bottom_only) { |
diff --git a/drivers/video/console/fbcon_cw.c b/drivers/video/console/fbcon_cw.c index c637e6318803..a6819b9d1770 100644 --- a/drivers/video/console/fbcon_cw.c +++ b/drivers/video/console/fbcon_cw.c | |||
@@ -70,7 +70,7 @@ static void cw_clear(struct vc_data *vc, struct fb_info *info, int sy, | |||
70 | int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; | 70 | int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; |
71 | u32 vxres = GETVXRES(ops->p->scrollmode, info); | 71 | u32 vxres = GETVXRES(ops->p->scrollmode, info); |
72 | 72 | ||
73 | region.color = attr_bgcol_ec(bgshift,vc); | 73 | region.color = attr_bgcol_ec(bgshift,vc,info); |
74 | region.dx = vxres - ((sy + height) * vc->vc_font.height); | 74 | region.dx = vxres - ((sy + height) * vc->vc_font.height); |
75 | region.dy = sx * vc->vc_font.width; | 75 | region.dy = sx * vc->vc_font.width; |
76 | region.height = width * vc->vc_font.width; | 76 | region.height = width * vc->vc_font.width; |
@@ -182,7 +182,7 @@ static void cw_clear_margins(struct vc_data *vc, struct fb_info *info, | |||
182 | struct fb_fillrect region; | 182 | struct fb_fillrect region; |
183 | int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; | 183 | int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; |
184 | 184 | ||
185 | region.color = attr_bgcol_ec(bgshift,vc); | 185 | region.color = attr_bgcol_ec(bgshift,vc,info); |
186 | region.rop = ROP_COPY; | 186 | region.rop = ROP_COPY; |
187 | 187 | ||
188 | if (rw && !bottom_only) { | 188 | if (rw && !bottom_only) { |
diff --git a/drivers/video/console/fbcon_ud.c b/drivers/video/console/fbcon_ud.c index 1473506df5d0..d9b5d6eb68a7 100644 --- a/drivers/video/console/fbcon_ud.c +++ b/drivers/video/console/fbcon_ud.c | |||
@@ -71,7 +71,7 @@ static void ud_clear(struct vc_data *vc, struct fb_info *info, int sy, | |||
71 | u32 vyres = GETVYRES(ops->p->scrollmode, info); | 71 | u32 vyres = GETVYRES(ops->p->scrollmode, info); |
72 | u32 vxres = GETVXRES(ops->p->scrollmode, info); | 72 | u32 vxres = GETVXRES(ops->p->scrollmode, info); |
73 | 73 | ||
74 | region.color = attr_bgcol_ec(bgshift,vc); | 74 | region.color = attr_bgcol_ec(bgshift,vc,info); |
75 | region.dy = vyres - ((sy + height) * vc->vc_font.height); | 75 | region.dy = vyres - ((sy + height) * vc->vc_font.height); |
76 | region.dx = vxres - ((sx + width) * vc->vc_font.width); | 76 | region.dx = vxres - ((sx + width) * vc->vc_font.width); |
77 | region.width = width * vc->vc_font.width; | 77 | region.width = width * vc->vc_font.width; |
@@ -228,7 +228,7 @@ static void ud_clear_margins(struct vc_data *vc, struct fb_info *info, | |||
228 | struct fb_fillrect region; | 228 | struct fb_fillrect region; |
229 | int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; | 229 | int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; |
230 | 230 | ||
231 | region.color = attr_bgcol_ec(bgshift,vc); | 231 | region.color = attr_bgcol_ec(bgshift,vc,info); |
232 | region.rop = ROP_COPY; | 232 | region.rop = ROP_COPY; |
233 | 233 | ||
234 | if (rw && !bottom_only) { | 234 | if (rw && !bottom_only) { |
diff --git a/drivers/video/console/fonts.c b/drivers/video/console/fonts.c index 96979c377518..d0c03fd70871 100644 --- a/drivers/video/console/fonts.c +++ b/drivers/video/console/fonts.c | |||
@@ -15,7 +15,7 @@ | |||
15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
16 | #include <linux/types.h> | 16 | #include <linux/types.h> |
17 | #include <linux/string.h> | 17 | #include <linux/string.h> |
18 | #if defined(__mc68000__) || defined(CONFIG_APUS) | 18 | #if defined(__mc68000__) |
19 | #include <asm/setup.h> | 19 | #include <asm/setup.h> |
20 | #endif | 20 | #endif |
21 | #include <linux/font.h> | 21 | #include <linux/font.h> |
@@ -120,7 +120,7 @@ const struct font_desc *get_default_font(int xres, int yres, u32 font_w, | |||
120 | for(i=0; i<num_fonts; i++) { | 120 | for(i=0; i<num_fonts; i++) { |
121 | f = fonts[i]; | 121 | f = fonts[i]; |
122 | c = f->pref; | 122 | c = f->pref; |
123 | #if defined(__mc68000__) || defined(CONFIG_APUS) | 123 | #if defined(__mc68000__) |
124 | #ifdef CONFIG_FONT_PEARL_8x8 | 124 | #ifdef CONFIG_FONT_PEARL_8x8 |
125 | if (MACH_IS_AMIGA && f->idx == PEARL8x8_IDX) | 125 | if (MACH_IS_AMIGA && f->idx == PEARL8x8_IDX) |
126 | c = 100; | 126 | c = 100; |
diff --git a/drivers/video/console/tileblit.c b/drivers/video/console/tileblit.c index d981fe4d86c6..0056a41e5c35 100644 --- a/drivers/video/console/tileblit.c +++ b/drivers/video/console/tileblit.c | |||
@@ -40,8 +40,8 @@ static void tile_clear(struct vc_data *vc, struct fb_info *info, int sy, | |||
40 | 40 | ||
41 | rect.index = vc->vc_video_erase_char & | 41 | rect.index = vc->vc_video_erase_char & |
42 | ((vc->vc_hi_font_mask) ? 0x1ff : 0xff); | 42 | ((vc->vc_hi_font_mask) ? 0x1ff : 0xff); |
43 | rect.fg = attr_fgcol_ec(fgshift, vc); | 43 | rect.fg = attr_fgcol_ec(fgshift, vc, info); |
44 | rect.bg = attr_bgcol_ec(bgshift, vc); | 44 | rect.bg = attr_bgcol_ec(bgshift, vc, info); |
45 | rect.sx = sx; | 45 | rect.sx = sx; |
46 | rect.sy = sy; | 46 | rect.sy = sy; |
47 | rect.width = width; | 47 | rect.width = width; |
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c index f65bcd314d54..6df29a62d720 100644 --- a/drivers/video/console/vgacon.c +++ b/drivers/video/console/vgacon.c | |||
@@ -1153,8 +1153,6 @@ static int vgacon_do_font_op(struct vgastate *state,char *arg,int set,int ch512) | |||
1153 | 1153 | ||
1154 | /* if 512 char mode is already enabled don't re-enable it. */ | 1154 | /* if 512 char mode is already enabled don't re-enable it. */ |
1155 | if ((set) && (ch512 != vga_512_chars)) { | 1155 | if ((set) && (ch512 != vga_512_chars)) { |
1156 | int i; | ||
1157 | |||
1158 | /* attribute controller */ | 1156 | /* attribute controller */ |
1159 | for (i = 0; i < MAX_NR_CONSOLES; i++) { | 1157 | for (i = 0; i < MAX_NR_CONSOLES; i++) { |
1160 | struct vc_data *c = vc_cons[i].d; | 1158 | struct vc_data *c = vc_cons[i].d; |
diff --git a/drivers/video/fb_defio.c b/drivers/video/fb_defio.c index a0c5d9d90d74..0f8cfb988c90 100644 --- a/drivers/video/fb_defio.c +++ b/drivers/video/fb_defio.c | |||
@@ -25,8 +25,8 @@ | |||
25 | #include <linux/pagemap.h> | 25 | #include <linux/pagemap.h> |
26 | 26 | ||
27 | /* this is to find and return the vmalloc-ed fb pages */ | 27 | /* this is to find and return the vmalloc-ed fb pages */ |
28 | static struct page* fb_deferred_io_nopage(struct vm_area_struct *vma, | 28 | static int fb_deferred_io_fault(struct vm_area_struct *vma, |
29 | unsigned long vaddr, int *type) | 29 | struct vm_fault *vmf) |
30 | { | 30 | { |
31 | unsigned long offset; | 31 | unsigned long offset; |
32 | struct page *page; | 32 | struct page *page; |
@@ -34,18 +34,17 @@ static struct page* fb_deferred_io_nopage(struct vm_area_struct *vma, | |||
34 | /* info->screen_base is in System RAM */ | 34 | /* info->screen_base is in System RAM */ |
35 | void *screen_base = (void __force *) info->screen_base; | 35 | void *screen_base = (void __force *) info->screen_base; |
36 | 36 | ||
37 | offset = (vaddr - vma->vm_start) + (vma->vm_pgoff << PAGE_SHIFT); | 37 | offset = vmf->pgoff << PAGE_SHIFT; |
38 | if (offset >= info->fix.smem_len) | 38 | if (offset >= info->fix.smem_len) |
39 | return NOPAGE_SIGBUS; | 39 | return VM_FAULT_SIGBUS; |
40 | 40 | ||
41 | page = vmalloc_to_page(screen_base + offset); | 41 | page = vmalloc_to_page(screen_base + offset); |
42 | if (!page) | 42 | if (!page) |
43 | return NOPAGE_OOM; | 43 | return VM_FAULT_SIGBUS; |
44 | 44 | ||
45 | get_page(page); | 45 | get_page(page); |
46 | if (type) | 46 | vmf->page = page; |
47 | *type = VM_FAULT_MINOR; | 47 | return 0; |
48 | return page; | ||
49 | } | 48 | } |
50 | 49 | ||
51 | int fb_deferred_io_fsync(struct file *file, struct dentry *dentry, int datasync) | 50 | int fb_deferred_io_fsync(struct file *file, struct dentry *dentry, int datasync) |
@@ -84,7 +83,7 @@ static int fb_deferred_io_mkwrite(struct vm_area_struct *vma, | |||
84 | } | 83 | } |
85 | 84 | ||
86 | static struct vm_operations_struct fb_deferred_io_vm_ops = { | 85 | static struct vm_operations_struct fb_deferred_io_vm_ops = { |
87 | .nopage = fb_deferred_io_nopage, | 86 | .fault = fb_deferred_io_fault, |
88 | .page_mkwrite = fb_deferred_io_mkwrite, | 87 | .page_mkwrite = fb_deferred_io_mkwrite, |
89 | }; | 88 | }; |
90 | 89 | ||
diff --git a/drivers/video/fb_draw.h b/drivers/video/fb_draw.h index cdafbe14ef1f..a2a0618d86a5 100644 --- a/drivers/video/fb_draw.h +++ b/drivers/video/fb_draw.h | |||
@@ -91,6 +91,7 @@ static inline unsigned long fb_rev_pixels_in_long(unsigned long val, | |||
91 | val = comp(val >> 2, val << 2, REV_PIXELS_MASK2); | 91 | val = comp(val >> 2, val << 2, REV_PIXELS_MASK2); |
92 | if (bswapmask & 3) | 92 | if (bswapmask & 3) |
93 | val = comp(val >> 4, val << 4, REV_PIXELS_MASK4); | 93 | val = comp(val >> 4, val << 4, REV_PIXELS_MASK4); |
94 | return val; | ||
94 | } | 95 | } |
95 | 96 | ||
96 | static inline u32 fb_shifted_pixels_mask_u32(u32 index, u32 bswapmask) | 97 | static inline u32 fb_shifted_pixels_mask_u32(u32 index, u32 bswapmask) |
diff --git a/drivers/video/fbmon.c b/drivers/video/fbmon.c index 4ba9c0894416..052e18058498 100644 --- a/drivers/video/fbmon.c +++ b/drivers/video/fbmon.c | |||
@@ -4,7 +4,7 @@ | |||
4 | * Copyright (C) 2002 James Simmons <jsimmons@users.sf.net> | 4 | * Copyright (C) 2002 James Simmons <jsimmons@users.sf.net> |
5 | * | 5 | * |
6 | * Credits: | 6 | * Credits: |
7 | * | 7 | * |
8 | * The EDID Parser is a conglomeration from the following sources: | 8 | * The EDID Parser is a conglomeration from the following sources: |
9 | * | 9 | * |
10 | * 1. SciTech SNAP Graphics Architecture | 10 | * 1. SciTech SNAP Graphics Architecture |
@@ -12,13 +12,13 @@ | |||
12 | * | 12 | * |
13 | * 2. XFree86 4.3.0, interpret_edid.c | 13 | * 2. XFree86 4.3.0, interpret_edid.c |
14 | * Copyright 1998 by Egbert Eich <Egbert.Eich@Physik.TU-Darmstadt.DE> | 14 | * Copyright 1998 by Egbert Eich <Egbert.Eich@Physik.TU-Darmstadt.DE> |
15 | * | 15 | * |
16 | * 3. John Fremlin <vii@users.sourceforge.net> and | 16 | * 3. John Fremlin <vii@users.sourceforge.net> and |
17 | * Ani Joshi <ajoshi@unixbox.com> | 17 | * Ani Joshi <ajoshi@unixbox.com> |
18 | * | 18 | * |
19 | * Generalized Timing Formula is derived from: | 19 | * Generalized Timing Formula is derived from: |
20 | * | 20 | * |
21 | * GTF Spreadsheet by Andy Morrish (1/5/97) | 21 | * GTF Spreadsheet by Andy Morrish (1/5/97) |
22 | * available at http://www.vesa.org | 22 | * available at http://www.vesa.org |
23 | * | 23 | * |
24 | * This file is subject to the terms and conditions of the GNU General Public | 24 | * This file is subject to the terms and conditions of the GNU General Public |
@@ -36,7 +36,7 @@ | |||
36 | #endif | 36 | #endif |
37 | #include "edid.h" | 37 | #include "edid.h" |
38 | 38 | ||
39 | /* | 39 | /* |
40 | * EDID parser | 40 | * EDID parser |
41 | */ | 41 | */ |
42 | 42 | ||
@@ -160,8 +160,8 @@ static int check_edid(unsigned char *edid) | |||
160 | for (i = 0; i < ARRAY_SIZE(brokendb); i++) { | 160 | for (i = 0; i < ARRAY_SIZE(brokendb); i++) { |
161 | if (!strncmp(manufacturer, brokendb[i].manufacturer, 4) && | 161 | if (!strncmp(manufacturer, brokendb[i].manufacturer, 4) && |
162 | brokendb[i].model == model) { | 162 | brokendb[i].model == model) { |
163 | fix = brokendb[i].fix; | 163 | fix = brokendb[i].fix; |
164 | break; | 164 | break; |
165 | } | 165 | } |
166 | } | 166 | } |
167 | 167 | ||
@@ -323,7 +323,7 @@ static void get_dpms_capabilities(unsigned char flags, | |||
323 | (flags & DPMS_SUSPEND) ? "yes" : "no", | 323 | (flags & DPMS_SUSPEND) ? "yes" : "no", |
324 | (flags & DPMS_STANDBY) ? "yes" : "no"); | 324 | (flags & DPMS_STANDBY) ? "yes" : "no"); |
325 | } | 325 | } |
326 | 326 | ||
327 | static void get_chroma(unsigned char *block, struct fb_monspecs *specs) | 327 | static void get_chroma(unsigned char *block, struct fb_monspecs *specs) |
328 | { | 328 | { |
329 | int tmp; | 329 | int tmp; |
@@ -365,7 +365,7 @@ static void get_chroma(unsigned char *block, struct fb_monspecs *specs) | |||
365 | tmp += 512; | 365 | tmp += 512; |
366 | specs->chroma.bluey = tmp/1024; | 366 | specs->chroma.bluey = tmp/1024; |
367 | DPRINTK("BlueY: 0.%03d\n", specs->chroma.bluey); | 367 | DPRINTK("BlueY: 0.%03d\n", specs->chroma.bluey); |
368 | 368 | ||
369 | tmp = ((block[6] & (3 << 2)) >> 2) | (block[0xd] << 2); | 369 | tmp = ((block[6] & (3 << 2)) >> 2) | (block[0xd] << 2); |
370 | tmp *= 1000; | 370 | tmp *= 1000; |
371 | tmp += 512; | 371 | tmp += 512; |
@@ -383,7 +383,7 @@ static void calc_mode_timings(int xres, int yres, int refresh, | |||
383 | struct fb_videomode *mode) | 383 | struct fb_videomode *mode) |
384 | { | 384 | { |
385 | struct fb_var_screeninfo *var; | 385 | struct fb_var_screeninfo *var; |
386 | 386 | ||
387 | var = kzalloc(sizeof(struct fb_var_screeninfo), GFP_KERNEL); | 387 | var = kzalloc(sizeof(struct fb_var_screeninfo), GFP_KERNEL); |
388 | 388 | ||
389 | if (var) { | 389 | if (var) { |
@@ -451,11 +451,11 @@ static int get_est_timing(unsigned char *block, struct fb_videomode *mode) | |||
451 | 451 | ||
452 | c = block[1]; | 452 | c = block[1]; |
453 | if (c&0x80) { | 453 | if (c&0x80) { |
454 | mode[num++] = vesa_modes[9]; | 454 | mode[num++] = vesa_modes[9]; |
455 | DPRINTK(" 800x600@72Hz\n"); | 455 | DPRINTK(" 800x600@72Hz\n"); |
456 | } | 456 | } |
457 | if (c&0x40) { | 457 | if (c&0x40) { |
458 | mode[num++] = vesa_modes[10]; | 458 | mode[num++] = vesa_modes[10]; |
459 | DPRINTK(" 800x600@75Hz\n"); | 459 | DPRINTK(" 800x600@75Hz\n"); |
460 | } | 460 | } |
461 | if (c&0x20) { | 461 | if (c&0x20) { |
@@ -495,7 +495,7 @@ static int get_est_timing(unsigned char *block, struct fb_videomode *mode) | |||
495 | static int get_std_timing(unsigned char *block, struct fb_videomode *mode) | 495 | static int get_std_timing(unsigned char *block, struct fb_videomode *mode) |
496 | { | 496 | { |
497 | int xres, yres = 0, refresh, ratio, i; | 497 | int xres, yres = 0, refresh, ratio, i; |
498 | 498 | ||
499 | xres = (block[0] + 31) * 8; | 499 | xres = (block[0] + 31) * 8; |
500 | if (xres <= 256) | 500 | if (xres <= 256) |
501 | return 0; | 501 | return 0; |
@@ -519,7 +519,7 @@ static int get_std_timing(unsigned char *block, struct fb_videomode *mode) | |||
519 | 519 | ||
520 | DPRINTK(" %dx%d@%dHz\n", xres, yres, refresh); | 520 | DPRINTK(" %dx%d@%dHz\n", xres, yres, refresh); |
521 | for (i = 0; i < VESA_MODEDB_SIZE; i++) { | 521 | for (i = 0; i < VESA_MODEDB_SIZE; i++) { |
522 | if (vesa_modes[i].xres == xres && | 522 | if (vesa_modes[i].xres == xres && |
523 | vesa_modes[i].yres == yres && | 523 | vesa_modes[i].yres == yres && |
524 | vesa_modes[i].refresh == refresh) { | 524 | vesa_modes[i].refresh == refresh) { |
525 | *mode = vesa_modes[i]; | 525 | *mode = vesa_modes[i]; |
@@ -536,13 +536,13 @@ static int get_dst_timing(unsigned char *block, | |||
536 | { | 536 | { |
537 | int j, num = 0; | 537 | int j, num = 0; |
538 | 538 | ||
539 | for (j = 0; j < 6; j++, block+= STD_TIMING_DESCRIPTION_SIZE) | 539 | for (j = 0; j < 6; j++, block += STD_TIMING_DESCRIPTION_SIZE) |
540 | num += get_std_timing(block, &mode[num]); | 540 | num += get_std_timing(block, &mode[num]); |
541 | 541 | ||
542 | return num; | 542 | return num; |
543 | } | 543 | } |
544 | 544 | ||
545 | static void get_detailed_timing(unsigned char *block, | 545 | static void get_detailed_timing(unsigned char *block, |
546 | struct fb_videomode *mode) | 546 | struct fb_videomode *mode) |
547 | { | 547 | { |
548 | mode->xres = H_ACTIVE; | 548 | mode->xres = H_ACTIVE; |
@@ -553,7 +553,7 @@ static void get_detailed_timing(unsigned char *block, | |||
553 | mode->right_margin = H_SYNC_OFFSET; | 553 | mode->right_margin = H_SYNC_OFFSET; |
554 | mode->left_margin = (H_ACTIVE + H_BLANKING) - | 554 | mode->left_margin = (H_ACTIVE + H_BLANKING) - |
555 | (H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH); | 555 | (H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH); |
556 | mode->upper_margin = V_BLANKING - V_SYNC_OFFSET - | 556 | mode->upper_margin = V_BLANKING - V_SYNC_OFFSET - |
557 | V_SYNC_WIDTH; | 557 | V_SYNC_WIDTH; |
558 | mode->lower_margin = V_SYNC_OFFSET; | 558 | mode->lower_margin = V_SYNC_OFFSET; |
559 | mode->hsync_len = H_SYNC_WIDTH; | 559 | mode->hsync_len = H_SYNC_WIDTH; |
@@ -597,7 +597,7 @@ static struct fb_videomode *fb_create_modedb(unsigned char *edid, int *dbsize) | |||
597 | if (mode == NULL) | 597 | if (mode == NULL) |
598 | return NULL; | 598 | return NULL; |
599 | 599 | ||
600 | if (edid == NULL || !edid_checksum(edid) || | 600 | if (edid == NULL || !edid_checksum(edid) || |
601 | !edid_check_header(edid)) { | 601 | !edid_check_header(edid)) { |
602 | kfree(mode); | 602 | kfree(mode); |
603 | return NULL; | 603 | return NULL; |
@@ -632,7 +632,7 @@ static struct fb_videomode *fb_create_modedb(unsigned char *edid, int *dbsize) | |||
632 | if (block[0] == 0x00 && block[1] == 0x00 && block[3] == 0xfa) | 632 | if (block[0] == 0x00 && block[1] == 0x00 && block[3] == 0xfa) |
633 | num += get_dst_timing(block + 5, &mode[num]); | 633 | num += get_dst_timing(block + 5, &mode[num]); |
634 | } | 634 | } |
635 | 635 | ||
636 | /* Yikes, EDID data is totally useless */ | 636 | /* Yikes, EDID data is totally useless */ |
637 | if (!num) { | 637 | if (!num) { |
638 | kfree(mode); | 638 | kfree(mode); |
@@ -686,7 +686,7 @@ static int fb_get_monitor_limits(unsigned char *edid, struct fb_monspecs *specs) | |||
686 | /* estimate monitor limits based on modes supported */ | 686 | /* estimate monitor limits based on modes supported */ |
687 | if (retval) { | 687 | if (retval) { |
688 | struct fb_videomode *modes, *mode; | 688 | struct fb_videomode *modes, *mode; |
689 | int num_modes, i, hz, hscan, pixclock; | 689 | int num_modes, hz, hscan, pixclock; |
690 | int vtotal, htotal; | 690 | int vtotal, htotal; |
691 | 691 | ||
692 | modes = fb_create_modedb(edid, &num_modes); | 692 | modes = fb_create_modedb(edid, &num_modes); |
@@ -713,7 +713,7 @@ static int fb_get_monitor_limits(unsigned char *edid, struct fb_monspecs *specs) | |||
713 | hscan = (pixclock + htotal / 2) / htotal; | 713 | hscan = (pixclock + htotal / 2) / htotal; |
714 | hscan = (hscan + 500) / 1000 * 1000; | 714 | hscan = (hscan + 500) / 1000 * 1000; |
715 | hz = (hscan + vtotal / 2) / vtotal; | 715 | hz = (hscan + vtotal / 2) / vtotal; |
716 | 716 | ||
717 | if (specs->dclkmax == 0 || specs->dclkmax < pixclock) | 717 | if (specs->dclkmax == 0 || specs->dclkmax < pixclock) |
718 | specs->dclkmax = pixclock; | 718 | specs->dclkmax = pixclock; |
719 | 719 | ||
@@ -966,8 +966,8 @@ void fb_edid_to_monspecs(unsigned char *edid, struct fb_monspecs *specs) | |||
966 | DPRINTK("========================================\n"); | 966 | DPRINTK("========================================\n"); |
967 | } | 967 | } |
968 | 968 | ||
969 | /* | 969 | /* |
970 | * VESA Generalized Timing Formula (GTF) | 970 | * VESA Generalized Timing Formula (GTF) |
971 | */ | 971 | */ |
972 | 972 | ||
973 | #define FLYBACK 550 | 973 | #define FLYBACK 550 |
@@ -996,7 +996,7 @@ struct __fb_timings { | |||
996 | * @hfreq: horizontal freq | 996 | * @hfreq: horizontal freq |
997 | * | 997 | * |
998 | * DESCRIPTION: | 998 | * DESCRIPTION: |
999 | * vblank = right_margin + vsync_len + left_margin | 999 | * vblank = right_margin + vsync_len + left_margin |
1000 | * | 1000 | * |
1001 | * given: right_margin = 1 (V_FRONTPORCH) | 1001 | * given: right_margin = 1 (V_FRONTPORCH) |
1002 | * vsync_len = 3 | 1002 | * vsync_len = 3 |
@@ -1010,12 +1010,12 @@ static u32 fb_get_vblank(u32 hfreq) | |||
1010 | { | 1010 | { |
1011 | u32 vblank; | 1011 | u32 vblank; |
1012 | 1012 | ||
1013 | vblank = (hfreq * FLYBACK)/1000; | 1013 | vblank = (hfreq * FLYBACK)/1000; |
1014 | vblank = (vblank + 500)/1000; | 1014 | vblank = (vblank + 500)/1000; |
1015 | return (vblank + V_FRONTPORCH); | 1015 | return (vblank + V_FRONTPORCH); |
1016 | } | 1016 | } |
1017 | 1017 | ||
1018 | /** | 1018 | /** |
1019 | * fb_get_hblank_by_freq - get horizontal blank time given hfreq | 1019 | * fb_get_hblank_by_freq - get horizontal blank time given hfreq |
1020 | * @hfreq: horizontal freq | 1020 | * @hfreq: horizontal freq |
1021 | * @xres: horizontal resolution in pixels | 1021 | * @xres: horizontal resolution in pixels |
@@ -1031,7 +1031,7 @@ static u32 fb_get_vblank(u32 hfreq) | |||
1031 | * | 1031 | * |
1032 | * where: C = ((offset - scale factor) * blank_scale) | 1032 | * where: C = ((offset - scale factor) * blank_scale) |
1033 | * -------------------------------------- + scale factor | 1033 | * -------------------------------------- + scale factor |
1034 | * 256 | 1034 | * 256 |
1035 | * M = blank_scale * gradient | 1035 | * M = blank_scale * gradient |
1036 | * | 1036 | * |
1037 | */ | 1037 | */ |
@@ -1039,7 +1039,7 @@ static u32 fb_get_hblank_by_hfreq(u32 hfreq, u32 xres) | |||
1039 | { | 1039 | { |
1040 | u32 c_val, m_val, duty_cycle, hblank; | 1040 | u32 c_val, m_val, duty_cycle, hblank; |
1041 | 1041 | ||
1042 | c_val = (((H_OFFSET - H_SCALEFACTOR) * H_BLANKSCALE)/256 + | 1042 | c_val = (((H_OFFSET - H_SCALEFACTOR) * H_BLANKSCALE)/256 + |
1043 | H_SCALEFACTOR) * 1000; | 1043 | H_SCALEFACTOR) * 1000; |
1044 | m_val = (H_BLANKSCALE * H_GRADIENT)/256; | 1044 | m_val = (H_BLANKSCALE * H_GRADIENT)/256; |
1045 | m_val = (m_val * 1000000)/hfreq; | 1045 | m_val = (m_val * 1000000)/hfreq; |
@@ -1048,7 +1048,7 @@ static u32 fb_get_hblank_by_hfreq(u32 hfreq, u32 xres) | |||
1048 | return (hblank); | 1048 | return (hblank); |
1049 | } | 1049 | } |
1050 | 1050 | ||
1051 | /** | 1051 | /** |
1052 | * fb_get_hblank_by_dclk - get horizontal blank time given pixelclock | 1052 | * fb_get_hblank_by_dclk - get horizontal blank time given pixelclock |
1053 | * @dclk: pixelclock in Hz | 1053 | * @dclk: pixelclock in Hz |
1054 | * @xres: horizontal resolution in pixels | 1054 | * @xres: horizontal resolution in pixels |
@@ -1061,7 +1061,7 @@ static u32 fb_get_hblank_by_hfreq(u32 hfreq, u32 xres) | |||
1061 | * | 1061 | * |
1062 | * duty cycle = percent of htotal assigned to inactive display | 1062 | * duty cycle = percent of htotal assigned to inactive display |
1063 | * duty cycle = C - (M * h_period) | 1063 | * duty cycle = C - (M * h_period) |
1064 | * | 1064 | * |
1065 | * where: h_period = SQRT(100 - C + (0.4 * xres * M)/dclk) + C - 100 | 1065 | * where: h_period = SQRT(100 - C + (0.4 * xres * M)/dclk) + C - 100 |
1066 | * ----------------------------------------------- | 1066 | * ----------------------------------------------- |
1067 | * 2 * M | 1067 | * 2 * M |
@@ -1077,11 +1077,11 @@ static u32 fb_get_hblank_by_dclk(u32 dclk, u32 xres) | |||
1077 | h_period = 100 - C_VAL; | 1077 | h_period = 100 - C_VAL; |
1078 | h_period *= h_period; | 1078 | h_period *= h_period; |
1079 | h_period += (M_VAL * xres * 2 * 1000)/(5 * dclk); | 1079 | h_period += (M_VAL * xres * 2 * 1000)/(5 * dclk); |
1080 | h_period *=10000; | 1080 | h_period *= 10000; |
1081 | 1081 | ||
1082 | h_period = int_sqrt(h_period); | 1082 | h_period = int_sqrt(h_period); |
1083 | h_period -= (100 - C_VAL) * 100; | 1083 | h_period -= (100 - C_VAL) * 100; |
1084 | h_period *= 1000; | 1084 | h_period *= 1000; |
1085 | h_period /= 2 * M_VAL; | 1085 | h_period /= 2 * M_VAL; |
1086 | 1086 | ||
1087 | duty_cycle = C_VAL * 1000 - (M_VAL * h_period)/100; | 1087 | duty_cycle = C_VAL * 1000 - (M_VAL * h_period)/100; |
@@ -1089,7 +1089,7 @@ static u32 fb_get_hblank_by_dclk(u32 dclk, u32 xres) | |||
1089 | hblank &= ~15; | 1089 | hblank &= ~15; |
1090 | return (hblank); | 1090 | return (hblank); |
1091 | } | 1091 | } |
1092 | 1092 | ||
1093 | /** | 1093 | /** |
1094 | * fb_get_hfreq - estimate hsync | 1094 | * fb_get_hfreq - estimate hsync |
1095 | * @vfreq: vertical refresh rate | 1095 | * @vfreq: vertical refresh rate |
@@ -1100,13 +1100,13 @@ static u32 fb_get_hblank_by_dclk(u32 dclk, u32 xres) | |||
1100 | * (yres + front_port) * vfreq * 1000000 | 1100 | * (yres + front_port) * vfreq * 1000000 |
1101 | * hfreq = ------------------------------------- | 1101 | * hfreq = ------------------------------------- |
1102 | * (1000000 - (vfreq * FLYBACK) | 1102 | * (1000000 - (vfreq * FLYBACK) |
1103 | * | 1103 | * |
1104 | */ | 1104 | */ |
1105 | 1105 | ||
1106 | static u32 fb_get_hfreq(u32 vfreq, u32 yres) | 1106 | static u32 fb_get_hfreq(u32 vfreq, u32 yres) |
1107 | { | 1107 | { |
1108 | u32 divisor, hfreq; | 1108 | u32 divisor, hfreq; |
1109 | 1109 | ||
1110 | divisor = (1000000 - (vfreq * FLYBACK))/1000; | 1110 | divisor = (1000000 - (vfreq * FLYBACK))/1000; |
1111 | hfreq = (yres + V_FRONTPORCH) * vfreq * 1000; | 1111 | hfreq = (yres + V_FRONTPORCH) * vfreq * 1000; |
1112 | return (hfreq/divisor); | 1112 | return (hfreq/divisor); |
@@ -1117,7 +1117,7 @@ static void fb_timings_vfreq(struct __fb_timings *timings) | |||
1117 | timings->hfreq = fb_get_hfreq(timings->vfreq, timings->vactive); | 1117 | timings->hfreq = fb_get_hfreq(timings->vfreq, timings->vactive); |
1118 | timings->vblank = fb_get_vblank(timings->hfreq); | 1118 | timings->vblank = fb_get_vblank(timings->hfreq); |
1119 | timings->vtotal = timings->vactive + timings->vblank; | 1119 | timings->vtotal = timings->vactive + timings->vblank; |
1120 | timings->hblank = fb_get_hblank_by_hfreq(timings->hfreq, | 1120 | timings->hblank = fb_get_hblank_by_hfreq(timings->hfreq, |
1121 | timings->hactive); | 1121 | timings->hactive); |
1122 | timings->htotal = timings->hactive + timings->hblank; | 1122 | timings->htotal = timings->hactive + timings->hblank; |
1123 | timings->dclk = timings->htotal * timings->hfreq; | 1123 | timings->dclk = timings->htotal * timings->hfreq; |
@@ -1128,7 +1128,7 @@ static void fb_timings_hfreq(struct __fb_timings *timings) | |||
1128 | timings->vblank = fb_get_vblank(timings->hfreq); | 1128 | timings->vblank = fb_get_vblank(timings->hfreq); |
1129 | timings->vtotal = timings->vactive + timings->vblank; | 1129 | timings->vtotal = timings->vactive + timings->vblank; |
1130 | timings->vfreq = timings->hfreq/timings->vtotal; | 1130 | timings->vfreq = timings->hfreq/timings->vtotal; |
1131 | timings->hblank = fb_get_hblank_by_hfreq(timings->hfreq, | 1131 | timings->hblank = fb_get_hblank_by_hfreq(timings->hfreq, |
1132 | timings->hactive); | 1132 | timings->hactive); |
1133 | timings->htotal = timings->hactive + timings->hblank; | 1133 | timings->htotal = timings->hactive + timings->hblank; |
1134 | timings->dclk = timings->htotal * timings->hfreq; | 1134 | timings->dclk = timings->htotal * timings->hfreq; |
@@ -1136,7 +1136,7 @@ static void fb_timings_hfreq(struct __fb_timings *timings) | |||
1136 | 1136 | ||
1137 | static void fb_timings_dclk(struct __fb_timings *timings) | 1137 | static void fb_timings_dclk(struct __fb_timings *timings) |
1138 | { | 1138 | { |
1139 | timings->hblank = fb_get_hblank_by_dclk(timings->dclk, | 1139 | timings->hblank = fb_get_hblank_by_dclk(timings->dclk, |
1140 | timings->hactive); | 1140 | timings->hactive); |
1141 | timings->htotal = timings->hactive + timings->hblank; | 1141 | timings->htotal = timings->hactive + timings->hblank; |
1142 | timings->hfreq = timings->dclk/timings->htotal; | 1142 | timings->hfreq = timings->dclk/timings->htotal; |
@@ -1156,29 +1156,29 @@ static void fb_timings_dclk(struct __fb_timings *timings) | |||
1156 | * @info: pointer to fb_info | 1156 | * @info: pointer to fb_info |
1157 | * | 1157 | * |
1158 | * DESCRIPTION: | 1158 | * DESCRIPTION: |
1159 | * Calculates video mode based on monitor specs using VESA GTF. | 1159 | * Calculates video mode based on monitor specs using VESA GTF. |
1160 | * The GTF is best for VESA GTF compliant monitors but is | 1160 | * The GTF is best for VESA GTF compliant monitors but is |
1161 | * specifically formulated to work for older monitors as well. | 1161 | * specifically formulated to work for older monitors as well. |
1162 | * | 1162 | * |
1163 | * If @flag==0, the function will attempt to maximize the | 1163 | * If @flag==0, the function will attempt to maximize the |
1164 | * refresh rate. Otherwise, it will calculate timings based on | 1164 | * refresh rate. Otherwise, it will calculate timings based on |
1165 | * the flag and accompanying value. | 1165 | * the flag and accompanying value. |
1166 | * | 1166 | * |
1167 | * If FB_IGNOREMON bit is set in @flags, monitor specs will be | 1167 | * If FB_IGNOREMON bit is set in @flags, monitor specs will be |
1168 | * ignored and @var will be filled with the calculated timings. | 1168 | * ignored and @var will be filled with the calculated timings. |
1169 | * | 1169 | * |
1170 | * All calculations are based on the VESA GTF Spreadsheet | 1170 | * All calculations are based on the VESA GTF Spreadsheet |
1171 | * available at VESA's public ftp (http://www.vesa.org). | 1171 | * available at VESA's public ftp (http://www.vesa.org). |
1172 | * | 1172 | * |
1173 | * NOTES: | 1173 | * NOTES: |
1174 | * The timings generated by the GTF will be different from VESA | 1174 | * The timings generated by the GTF will be different from VESA |
1175 | * DMT. It might be a good idea to keep a table of standard | 1175 | * DMT. It might be a good idea to keep a table of standard |
1176 | * VESA modes as well. The GTF may also not work for some displays, | 1176 | * VESA modes as well. The GTF may also not work for some displays, |
1177 | * such as, and especially, analog TV. | 1177 | * such as, and especially, analog TV. |
1178 | * | 1178 | * |
1179 | * REQUIRES: | 1179 | * REQUIRES: |
1180 | * A valid info->monspecs, otherwise 'safe numbers' will be used. | 1180 | * A valid info->monspecs, otherwise 'safe numbers' will be used. |
1181 | */ | 1181 | */ |
1182 | int fb_get_mode(int flags, u32 val, struct fb_var_screeninfo *var, struct fb_info *info) | 1182 | int fb_get_mode(int flags, u32 val, struct fb_var_screeninfo *var, struct fb_info *info) |
1183 | { | 1183 | { |
1184 | struct __fb_timings *timings; | 1184 | struct __fb_timings *timings; |
@@ -1191,7 +1191,7 @@ int fb_get_mode(int flags, u32 val, struct fb_var_screeninfo *var, struct fb_inf | |||
1191 | if (!timings) | 1191 | if (!timings) |
1192 | return -ENOMEM; | 1192 | return -ENOMEM; |
1193 | 1193 | ||
1194 | /* | 1194 | /* |
1195 | * If monspecs are invalid, use values that are enough | 1195 | * If monspecs are invalid, use values that are enough |
1196 | * for 640x480@60 | 1196 | * for 640x480@60 |
1197 | */ | 1197 | */ |
@@ -1214,7 +1214,7 @@ int fb_get_mode(int flags, u32 val, struct fb_var_screeninfo *var, struct fb_inf | |||
1214 | 1214 | ||
1215 | timings->hactive = var->xres; | 1215 | timings->hactive = var->xres; |
1216 | timings->vactive = var->yres; | 1216 | timings->vactive = var->yres; |
1217 | if (var->vmode & FB_VMODE_INTERLACED) { | 1217 | if (var->vmode & FB_VMODE_INTERLACED) { |
1218 | timings->vactive /= 2; | 1218 | timings->vactive /= 2; |
1219 | interlace = 2; | 1219 | interlace = 2; |
1220 | } | 1220 | } |
@@ -1250,9 +1250,9 @@ int fb_get_mode(int flags, u32 val, struct fb_var_screeninfo *var, struct fb_inf | |||
1250 | break; | 1250 | break; |
1251 | default: | 1251 | default: |
1252 | err = -EINVAL; | 1252 | err = -EINVAL; |
1253 | 1253 | ||
1254 | } | 1254 | } |
1255 | 1255 | ||
1256 | if (err || (!(flags & FB_IGNOREMON) && | 1256 | if (err || (!(flags & FB_IGNOREMON) && |
1257 | (timings->vfreq < vfmin || timings->vfreq > vfmax || | 1257 | (timings->vfreq < vfmin || timings->vfreq > vfmax || |
1258 | timings->hfreq < hfmin || timings->hfreq > hfmax || | 1258 | timings->hfreq < hfmin || timings->hfreq > hfmax || |
@@ -1269,7 +1269,7 @@ int fb_get_mode(int flags, u32 val, struct fb_var_screeninfo *var, struct fb_inf | |||
1269 | var->upper_margin = (timings->vblank * interlace)/dscan - | 1269 | var->upper_margin = (timings->vblank * interlace)/dscan - |
1270 | (var->vsync_len + var->lower_margin); | 1270 | (var->vsync_len + var->lower_margin); |
1271 | } | 1271 | } |
1272 | 1272 | ||
1273 | kfree(timings); | 1273 | kfree(timings); |
1274 | return err; | 1274 | return err; |
1275 | } | 1275 | } |
@@ -1291,7 +1291,7 @@ int fb_get_mode(int flags, u32 val, struct fb_var_screeninfo *var, | |||
1291 | return -EINVAL; | 1291 | return -EINVAL; |
1292 | } | 1292 | } |
1293 | #endif /* CONFIG_FB_MODE_HELPERS */ | 1293 | #endif /* CONFIG_FB_MODE_HELPERS */ |
1294 | 1294 | ||
1295 | /* | 1295 | /* |
1296 | * fb_validate_mode - validates var against monitor capabilities | 1296 | * fb_validate_mode - validates var against monitor capabilities |
1297 | * @var: pointer to fb_var_screeninfo | 1297 | * @var: pointer to fb_var_screeninfo |
@@ -1309,7 +1309,7 @@ int fb_validate_mode(const struct fb_var_screeninfo *var, struct fb_info *info) | |||
1309 | u32 hfreq, vfreq, htotal, vtotal, pixclock; | 1309 | u32 hfreq, vfreq, htotal, vtotal, pixclock; |
1310 | u32 hfmin, hfmax, vfmin, vfmax, dclkmin, dclkmax; | 1310 | u32 hfmin, hfmax, vfmin, vfmax, dclkmin, dclkmax; |
1311 | 1311 | ||
1312 | /* | 1312 | /* |
1313 | * If monspecs are invalid, use values that are enough | 1313 | * If monspecs are invalid, use values that are enough |
1314 | * for 640x480@60 | 1314 | * for 640x480@60 |
1315 | */ | 1315 | */ |
@@ -1333,10 +1333,10 @@ int fb_validate_mode(const struct fb_var_screeninfo *var, struct fb_info *info) | |||
1333 | if (!var->pixclock) | 1333 | if (!var->pixclock) |
1334 | return -EINVAL; | 1334 | return -EINVAL; |
1335 | pixclock = PICOS2KHZ(var->pixclock) * 1000; | 1335 | pixclock = PICOS2KHZ(var->pixclock) * 1000; |
1336 | 1336 | ||
1337 | htotal = var->xres + var->right_margin + var->hsync_len + | 1337 | htotal = var->xres + var->right_margin + var->hsync_len + |
1338 | var->left_margin; | 1338 | var->left_margin; |
1339 | vtotal = var->yres + var->lower_margin + var->vsync_len + | 1339 | vtotal = var->yres + var->lower_margin + var->vsync_len + |
1340 | var->upper_margin; | 1340 | var->upper_margin; |
1341 | 1341 | ||
1342 | if (var->vmode & FB_VMODE_INTERLACED) | 1342 | if (var->vmode & FB_VMODE_INTERLACED) |
@@ -1349,7 +1349,7 @@ int fb_validate_mode(const struct fb_var_screeninfo *var, struct fb_info *info) | |||
1349 | 1349 | ||
1350 | vfreq = hfreq/vtotal; | 1350 | vfreq = hfreq/vtotal; |
1351 | 1351 | ||
1352 | return (vfreq < vfmin || vfreq > vfmax || | 1352 | return (vfreq < vfmin || vfreq > vfmax || |
1353 | hfreq < hfmin || hfreq > hfmax || | 1353 | hfreq < hfmin || hfreq > hfmax || |
1354 | pixclock < dclkmin || pixclock > dclkmax) ? | 1354 | pixclock < dclkmin || pixclock > dclkmax) ? |
1355 | -EINVAL : 0; | 1355 | -EINVAL : 0; |
diff --git a/drivers/video/geode/lxfb_core.c b/drivers/video/geode/lxfb_core.c index 583185fd7c94..eb6b88171538 100644 --- a/drivers/video/geode/lxfb_core.c +++ b/drivers/video/geode/lxfb_core.c | |||
@@ -34,7 +34,7 @@ static int fbsize; | |||
34 | * we try to make it something sane - 640x480-60 is sane | 34 | * we try to make it something sane - 640x480-60 is sane |
35 | */ | 35 | */ |
36 | 36 | ||
37 | const struct fb_videomode geode_modedb[] __initdata = { | 37 | static const struct fb_videomode geode_modedb[] __initdata = { |
38 | /* 640x480-60 */ | 38 | /* 640x480-60 */ |
39 | { NULL, 60, 640, 480, 39682, 48, 8, 25, 2, 88, 2, | 39 | { NULL, 60, 640, 480, 39682, 48, 8, 25, 2, 88, 2, |
40 | FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, | 40 | FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, |
diff --git a/drivers/video/hpfb.c b/drivers/video/hpfb.c index b18486ad8e17..2eb4fb159084 100644 --- a/drivers/video/hpfb.c +++ b/drivers/video/hpfb.c | |||
@@ -207,7 +207,8 @@ static struct fb_ops hpfb_ops = { | |||
207 | #define HPFB_FBOMSB 0x5d /* Frame buffer offset */ | 207 | #define HPFB_FBOMSB 0x5d /* Frame buffer offset */ |
208 | #define HPFB_FBOLSB 0x5f | 208 | #define HPFB_FBOLSB 0x5f |
209 | 209 | ||
210 | static int __init hpfb_init_one(unsigned long phys_base, unsigned long virt_base) | 210 | static int __devinit hpfb_init_one(unsigned long phys_base, |
211 | unsigned long virt_base) | ||
211 | { | 212 | { |
212 | unsigned long fboff, fb_width, fb_height, fb_start; | 213 | unsigned long fboff, fb_width, fb_height, fb_start; |
213 | 214 | ||
diff --git a/drivers/video/i810/i810_main.c b/drivers/video/i810/i810_main.c index 1a7d7789d877..1d13dd099af8 100644 --- a/drivers/video/i810/i810_main.c +++ b/drivers/video/i810/i810_main.c | |||
@@ -1476,7 +1476,7 @@ static int i810fb_cursor(struct fb_info *info, struct fb_cursor *cursor) | |||
1476 | struct i810fb_par *par = info->par; | 1476 | struct i810fb_par *par = info->par; |
1477 | u8 __iomem *mmio = par->mmio_start_virtual; | 1477 | u8 __iomem *mmio = par->mmio_start_virtual; |
1478 | 1478 | ||
1479 | if (!par->dev_flags & LOCKUP) | 1479 | if (!(par->dev_flags & LOCKUP)) |
1480 | return -ENXIO; | 1480 | return -ENXIO; |
1481 | 1481 | ||
1482 | if (cursor->image.width > 64 || cursor->image.height > 64) | 1482 | if (cursor->image.width > 64 || cursor->image.height > 64) |
diff --git a/drivers/video/igafb.c b/drivers/video/igafb.c index b87ea21d3d78..3a81060137a2 100644 --- a/drivers/video/igafb.c +++ b/drivers/video/igafb.c | |||
@@ -400,6 +400,7 @@ int __init igafb_init(void) | |||
400 | info = kzalloc(size, GFP_ATOMIC); | 400 | info = kzalloc(size, GFP_ATOMIC); |
401 | if (!info) { | 401 | if (!info) { |
402 | printk("igafb_init: can't alloc fb_info\n"); | 402 | printk("igafb_init: can't alloc fb_info\n"); |
403 | pci_dev_put(pdev); | ||
403 | return -ENOMEM; | 404 | return -ENOMEM; |
404 | } | 405 | } |
405 | 406 | ||
@@ -409,12 +410,14 @@ int __init igafb_init(void) | |||
409 | if ((addr = pdev->resource[0].start) == 0) { | 410 | if ((addr = pdev->resource[0].start) == 0) { |
410 | printk("igafb_init: no memory start\n"); | 411 | printk("igafb_init: no memory start\n"); |
411 | kfree(info); | 412 | kfree(info); |
413 | pci_dev_put(pdev); | ||
412 | return -ENXIO; | 414 | return -ENXIO; |
413 | } | 415 | } |
414 | 416 | ||
415 | if ((info->screen_base = ioremap(addr, 1024*1024*2)) == 0) { | 417 | if ((info->screen_base = ioremap(addr, 1024*1024*2)) == 0) { |
416 | printk("igafb_init: can't remap %lx[2M]\n", addr); | 418 | printk("igafb_init: can't remap %lx[2M]\n", addr); |
417 | kfree(info); | 419 | kfree(info); |
420 | pci_dev_put(pdev); | ||
418 | return -ENXIO; | 421 | return -ENXIO; |
419 | } | 422 | } |
420 | 423 | ||
@@ -449,6 +452,7 @@ int __init igafb_init(void) | |||
449 | printk("igafb_init: can't remap %lx[4K]\n", igafb_fix.mmio_start); | 452 | printk("igafb_init: can't remap %lx[4K]\n", igafb_fix.mmio_start); |
450 | iounmap((void *)info->screen_base); | 453 | iounmap((void *)info->screen_base); |
451 | kfree(info); | 454 | kfree(info); |
455 | pci_dev_put(pdev); | ||
452 | return -ENXIO; | 456 | return -ENXIO; |
453 | } | 457 | } |
454 | 458 | ||
@@ -466,6 +470,7 @@ int __init igafb_init(void) | |||
466 | iounmap((void *)par->io_base); | 470 | iounmap((void *)par->io_base); |
467 | iounmap(info->screen_base); | 471 | iounmap(info->screen_base); |
468 | kfree(info); | 472 | kfree(info); |
473 | pci_dev_put(pdev); | ||
469 | return -ENOMEM; | 474 | return -ENOMEM; |
470 | } | 475 | } |
471 | 476 | ||
diff --git a/drivers/video/intelfb/intelfbhw.c b/drivers/video/intelfb/intelfbhw.c index 5f6fb7d2c408..fa1fff553565 100644 --- a/drivers/video/intelfb/intelfbhw.c +++ b/drivers/video/intelfb/intelfbhw.c | |||
@@ -1971,7 +1971,7 @@ void intelfbhw_cursor_reset(struct intelfb_info *dinfo) | |||
1971 | static irqreturn_t intelfbhw_irq(int irq, void *dev_id) | 1971 | static irqreturn_t intelfbhw_irq(int irq, void *dev_id) |
1972 | { | 1972 | { |
1973 | u16 tmp; | 1973 | u16 tmp; |
1974 | struct intelfb_info *dinfo = (struct intelfb_info *)dev_id; | 1974 | struct intelfb_info *dinfo = dev_id; |
1975 | 1975 | ||
1976 | spin_lock(&dinfo->int_lock); | 1976 | spin_lock(&dinfo->int_lock); |
1977 | 1977 | ||
diff --git a/drivers/video/neofb.c b/drivers/video/neofb.c index 4b6a99b5be0d..5246b0402d76 100644 --- a/drivers/video/neofb.c +++ b/drivers/video/neofb.c | |||
@@ -2066,40 +2066,49 @@ static struct fb_info *__devinit neo_alloc_fb_info(struct pci_dev *dev, const st | |||
2066 | 2066 | ||
2067 | switch (info->fix.accel) { | 2067 | switch (info->fix.accel) { |
2068 | case FB_ACCEL_NEOMAGIC_NM2070: | 2068 | case FB_ACCEL_NEOMAGIC_NM2070: |
2069 | sprintf(info->fix.id, "MagicGraph 128"); | 2069 | snprintf(info->fix.id, sizeof(info->fix.id), |
2070 | "MagicGraph 128"); | ||
2070 | break; | 2071 | break; |
2071 | case FB_ACCEL_NEOMAGIC_NM2090: | 2072 | case FB_ACCEL_NEOMAGIC_NM2090: |
2072 | sprintf(info->fix.id, "MagicGraph 128V"); | 2073 | snprintf(info->fix.id, sizeof(info->fix.id), |
2074 | "MagicGraph 128V"); | ||
2073 | break; | 2075 | break; |
2074 | case FB_ACCEL_NEOMAGIC_NM2093: | 2076 | case FB_ACCEL_NEOMAGIC_NM2093: |
2075 | sprintf(info->fix.id, "MagicGraph 128ZV"); | 2077 | snprintf(info->fix.id, sizeof(info->fix.id), |
2078 | "MagicGraph 128ZV"); | ||
2076 | break; | 2079 | break; |
2077 | case FB_ACCEL_NEOMAGIC_NM2097: | 2080 | case FB_ACCEL_NEOMAGIC_NM2097: |
2078 | sprintf(info->fix.id, "MagicGraph 128ZV+"); | 2081 | snprintf(info->fix.id, sizeof(info->fix.id), |
2082 | "MagicGraph 128ZV+"); | ||
2079 | break; | 2083 | break; |
2080 | case FB_ACCEL_NEOMAGIC_NM2160: | 2084 | case FB_ACCEL_NEOMAGIC_NM2160: |
2081 | sprintf(info->fix.id, "MagicGraph 128XD"); | 2085 | snprintf(info->fix.id, sizeof(info->fix.id), |
2086 | "MagicGraph 128XD"); | ||
2082 | break; | 2087 | break; |
2083 | case FB_ACCEL_NEOMAGIC_NM2200: | 2088 | case FB_ACCEL_NEOMAGIC_NM2200: |
2084 | sprintf(info->fix.id, "MagicGraph 256AV"); | 2089 | snprintf(info->fix.id, sizeof(info->fix.id), |
2090 | "MagicGraph 256AV"); | ||
2085 | info->flags |= FBINFO_HWACCEL_IMAGEBLIT | | 2091 | info->flags |= FBINFO_HWACCEL_IMAGEBLIT | |
2086 | FBINFO_HWACCEL_COPYAREA | | 2092 | FBINFO_HWACCEL_COPYAREA | |
2087 | FBINFO_HWACCEL_FILLRECT; | 2093 | FBINFO_HWACCEL_FILLRECT; |
2088 | break; | 2094 | break; |
2089 | case FB_ACCEL_NEOMAGIC_NM2230: | 2095 | case FB_ACCEL_NEOMAGIC_NM2230: |
2090 | sprintf(info->fix.id, "MagicGraph 256AV+"); | 2096 | snprintf(info->fix.id, sizeof(info->fix.id), |
2097 | "MagicGraph 256AV+"); | ||
2091 | info->flags |= FBINFO_HWACCEL_IMAGEBLIT | | 2098 | info->flags |= FBINFO_HWACCEL_IMAGEBLIT | |
2092 | FBINFO_HWACCEL_COPYAREA | | 2099 | FBINFO_HWACCEL_COPYAREA | |
2093 | FBINFO_HWACCEL_FILLRECT; | 2100 | FBINFO_HWACCEL_FILLRECT; |
2094 | break; | 2101 | break; |
2095 | case FB_ACCEL_NEOMAGIC_NM2360: | 2102 | case FB_ACCEL_NEOMAGIC_NM2360: |
2096 | sprintf(info->fix.id, "MagicGraph 256ZX"); | 2103 | snprintf(info->fix.id, sizeof(info->fix.id), |
2104 | "MagicGraph 256ZX"); | ||
2097 | info->flags |= FBINFO_HWACCEL_IMAGEBLIT | | 2105 | info->flags |= FBINFO_HWACCEL_IMAGEBLIT | |
2098 | FBINFO_HWACCEL_COPYAREA | | 2106 | FBINFO_HWACCEL_COPYAREA | |
2099 | FBINFO_HWACCEL_FILLRECT; | 2107 | FBINFO_HWACCEL_FILLRECT; |
2100 | break; | 2108 | break; |
2101 | case FB_ACCEL_NEOMAGIC_NM2380: | 2109 | case FB_ACCEL_NEOMAGIC_NM2380: |
2102 | sprintf(info->fix.id, "MagicGraph 256XL+"); | 2110 | snprintf(info->fix.id, sizeof(info->fix.id), |
2111 | "MagicGraph 256XL+"); | ||
2103 | info->flags |= FBINFO_HWACCEL_IMAGEBLIT | | 2112 | info->flags |= FBINFO_HWACCEL_IMAGEBLIT | |
2104 | FBINFO_HWACCEL_COPYAREA | | 2113 | FBINFO_HWACCEL_COPYAREA | |
2105 | FBINFO_HWACCEL_FILLRECT; | 2114 | FBINFO_HWACCEL_FILLRECT; |
diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c index 30e14eb1f51e..74517b1b26a6 100644 --- a/drivers/video/nvidia/nvidia.c +++ b/drivers/video/nvidia/nvidia.c | |||
@@ -849,9 +849,27 @@ static int nvidiafb_check_var(struct fb_var_screeninfo *var, | |||
849 | if (!mode_valid && info->monspecs.modedb_len) | 849 | if (!mode_valid && info->monspecs.modedb_len) |
850 | return -EINVAL; | 850 | return -EINVAL; |
851 | 851 | ||
852 | /* | ||
853 | * If we're on a flat panel, check if the mode is outside of the | ||
854 | * panel dimensions. If so, cap it and try for the next best mode | ||
855 | * before bailing out. | ||
856 | */ | ||
852 | if (par->fpWidth && par->fpHeight && (par->fpWidth < var->xres || | 857 | if (par->fpWidth && par->fpHeight && (par->fpWidth < var->xres || |
853 | par->fpHeight < var->yres)) | 858 | par->fpHeight < var->yres)) { |
854 | return -EINVAL; | 859 | const struct fb_videomode *mode; |
860 | |||
861 | var->xres = par->fpWidth; | ||
862 | var->yres = par->fpHeight; | ||
863 | |||
864 | mode = fb_find_best_mode(var, &info->modelist); | ||
865 | if (!mode) { | ||
866 | printk(KERN_ERR PFX "mode out of range of flat " | ||
867 | "panel dimensions\n"); | ||
868 | return -EINVAL; | ||
869 | } | ||
870 | |||
871 | fb_videomode_to_var(var, mode); | ||
872 | } | ||
855 | 873 | ||
856 | if (var->yres_virtual < var->yres) | 874 | if (var->yres_virtual < var->yres) |
857 | var->yres_virtual = var->yres; | 875 | var->yres_virtual = var->yres; |
diff --git a/drivers/video/pm2fb.c b/drivers/video/pm2fb.c index 5591dfb22b18..30181b593829 100644 --- a/drivers/video/pm2fb.c +++ b/drivers/video/pm2fb.c | |||
@@ -1159,6 +1159,11 @@ static void pm2fb_imageblit(struct fb_info *info, const struct fb_image *image) | |||
1159 | u32 fgx, bgx; | 1159 | u32 fgx, bgx; |
1160 | const u32 *src = (const u32 *)image->data; | 1160 | const u32 *src = (const u32 *)image->data; |
1161 | u32 xres = (info->var.xres + 31) & ~31; | 1161 | u32 xres = (info->var.xres + 31) & ~31; |
1162 | int raster_mode = 1; /* invert bits */ | ||
1163 | |||
1164 | #ifdef __LITTLE_ENDIAN | ||
1165 | raster_mode |= 3 << 7; /* reverse byte order */ | ||
1166 | #endif | ||
1162 | 1167 | ||
1163 | if (info->state != FBINFO_STATE_RUNNING) | 1168 | if (info->state != FBINFO_STATE_RUNNING) |
1164 | return; | 1169 | return; |
@@ -1208,9 +1213,8 @@ static void pm2fb_imageblit(struct fb_info *info, const struct fb_image *image) | |||
1208 | pm2_WR(par, PM2R_RENDER, | 1213 | pm2_WR(par, PM2R_RENDER, |
1209 | PM2F_RENDER_RECTANGLE | | 1214 | PM2F_RENDER_RECTANGLE | |
1210 | PM2F_INCREASE_X | PM2F_INCREASE_Y); | 1215 | PM2F_INCREASE_X | PM2F_INCREASE_Y); |
1211 | /* BitMapPackEachScanline & invert bits and byte order*/ | 1216 | /* BitMapPackEachScanline */ |
1212 | /* force background */ | 1217 | pm2_WR(par, PM2R_RASTERIZER_MODE, raster_mode | (1 << 9)); |
1213 | pm2_WR(par, PM2R_RASTERIZER_MODE, (1 << 9) | 1 | (3 << 7)); | ||
1214 | pm2_WR(par, PM2R_CONSTANT_COLOR, fgx); | 1218 | pm2_WR(par, PM2R_CONSTANT_COLOR, fgx); |
1215 | pm2_WR(par, PM2R_RENDER, | 1219 | pm2_WR(par, PM2R_RENDER, |
1216 | PM2F_RENDER_RECTANGLE | | 1220 | PM2F_RENDER_RECTANGLE | |
@@ -1224,8 +1228,7 @@ static void pm2fb_imageblit(struct fb_info *info, const struct fb_image *image) | |||
1224 | PM2F_RENDER_RECTANGLE | | 1228 | PM2F_RENDER_RECTANGLE | |
1225 | PM2F_RENDER_FASTFILL | | 1229 | PM2F_RENDER_FASTFILL | |
1226 | PM2F_INCREASE_X | PM2F_INCREASE_Y); | 1230 | PM2F_INCREASE_X | PM2F_INCREASE_Y); |
1227 | /* invert bits and byte order*/ | 1231 | pm2_WR(par, PM2R_RASTERIZER_MODE, raster_mode); |
1228 | pm2_WR(par, PM2R_RASTERIZER_MODE, 1 | (3 << 7)); | ||
1229 | pm2_WR(par, PM2R_FB_BLOCK_COLOR, fgx); | 1232 | pm2_WR(par, PM2R_FB_BLOCK_COLOR, fgx); |
1230 | pm2_WR(par, PM2R_RENDER, | 1233 | pm2_WR(par, PM2R_RENDER, |
1231 | PM2F_RENDER_RECTANGLE | | 1234 | PM2F_RENDER_RECTANGLE | |
diff --git a/drivers/video/pm3fb.c b/drivers/video/pm3fb.c index 070659992c18..5dba8cdd0517 100644 --- a/drivers/video/pm3fb.c +++ b/drivers/video/pm3fb.c | |||
@@ -1227,7 +1227,7 @@ static struct fb_ops pm3fb_ops = { | |||
1227 | 1227 | ||
1228 | /* mmio register are already mapped when this function is called */ | 1228 | /* mmio register are already mapped when this function is called */ |
1229 | /* the pm3fb_fix.smem_start is also set */ | 1229 | /* the pm3fb_fix.smem_start is also set */ |
1230 | static unsigned long pm3fb_size_memory(struct pm3_par *par) | 1230 | static unsigned long __devinit pm3fb_size_memory(struct pm3_par *par) |
1231 | { | 1231 | { |
1232 | unsigned long memsize = 0; | 1232 | unsigned long memsize = 0; |
1233 | unsigned long tempBypass, i, temp1, temp2; | 1233 | unsigned long tempBypass, i, temp1, temp2; |
diff --git a/drivers/video/pmag-aa-fb.c b/drivers/video/pmag-aa-fb.c index a864438b6008..6515ec11c16b 100644 --- a/drivers/video/pmag-aa-fb.c +++ b/drivers/video/pmag-aa-fb.c | |||
@@ -150,7 +150,7 @@ static int aafbcon_set_font(struct display *disp, int width, int height) | |||
150 | { | 150 | { |
151 | struct aafb_info *info = (struct aafb_info *)disp->fb_info; | 151 | struct aafb_info *info = (struct aafb_info *)disp->fb_info; |
152 | struct aafb_cursor *c = &info->cursor; | 152 | struct aafb_cursor *c = &info->cursor; |
153 | u8 fgc = ~attr_bgcol_ec(disp, disp->conp); | 153 | u8 fgc = ~attr_bgcol_ec(disp, disp->conp, &info->info); |
154 | 154 | ||
155 | if (width > 64 || height > 64 || width < 0 || height < 0) | 155 | if (width > 64 || height > 64 || width < 0 || height < 0) |
156 | return -EINVAL; | 156 | return -EINVAL; |
diff --git a/drivers/video/ps3fb.c b/drivers/video/ps3fb.c index 044a423a72cb..dc3af1c78c56 100644 --- a/drivers/video/ps3fb.c +++ b/drivers/video/ps3fb.c | |||
@@ -57,8 +57,6 @@ | |||
57 | #define GPU_ALIGN_UP(x) _ALIGN_UP((x), 64) | 57 | #define GPU_ALIGN_UP(x) _ALIGN_UP((x), 64) |
58 | #define GPU_MAX_LINE_LENGTH (65536 - 64) | 58 | #define GPU_MAX_LINE_LENGTH (65536 - 64) |
59 | 59 | ||
60 | #define PS3FB_FULL_MODE_BIT 0x80 | ||
61 | |||
62 | #define GPU_INTR_STATUS_VSYNC_0 0 /* vsync on head A */ | 60 | #define GPU_INTR_STATUS_VSYNC_0 0 /* vsync on head A */ |
63 | #define GPU_INTR_STATUS_VSYNC_1 1 /* vsync on head B */ | 61 | #define GPU_INTR_STATUS_VSYNC_1 1 /* vsync on head B */ |
64 | #define GPU_INTR_STATUS_FLIP_0 3 /* flip head A */ | 62 | #define GPU_INTR_STATUS_FLIP_0 3 /* flip head A */ |
@@ -118,8 +116,6 @@ struct ps3fb_priv { | |||
118 | unsigned int irq_no; | 116 | unsigned int irq_no; |
119 | 117 | ||
120 | u64 context_handle, memory_handle; | 118 | u64 context_handle, memory_handle; |
121 | void *xdr_ea; | ||
122 | size_t xdr_size; | ||
123 | struct gpu_driver_info *dinfo; | 119 | struct gpu_driver_info *dinfo; |
124 | 120 | ||
125 | u64 vblank_count; /* frame count */ | 121 | u64 vblank_count; /* frame count */ |
@@ -136,42 +132,19 @@ static struct ps3fb_priv ps3fb; | |||
136 | struct ps3fb_par { | 132 | struct ps3fb_par { |
137 | u32 pseudo_palette[16]; | 133 | u32 pseudo_palette[16]; |
138 | int mode_id, new_mode_id; | 134 | int mode_id, new_mode_id; |
139 | int res_index; | ||
140 | unsigned int num_frames; /* num of frame buffers */ | 135 | unsigned int num_frames; /* num of frame buffers */ |
141 | unsigned int width; | 136 | unsigned int width; |
142 | unsigned int height; | 137 | unsigned int height; |
143 | unsigned long full_offset; /* start of fullscreen DDR fb */ | 138 | unsigned int ddr_line_length; |
144 | unsigned long fb_offset; /* start of actual DDR fb */ | 139 | unsigned int ddr_frame_size; |
145 | unsigned long pan_offset; | 140 | unsigned int xdr_frame_size; |
141 | unsigned int full_offset; /* start of fullscreen DDR fb */ | ||
142 | unsigned int fb_offset; /* start of actual DDR fb */ | ||
143 | unsigned int pan_offset; | ||
146 | }; | 144 | }; |
147 | 145 | ||
148 | struct ps3fb_res_table { | 146 | |
149 | u32 xres; | 147 | #define FIRST_NATIVE_MODE_INDEX 10 |
150 | u32 yres; | ||
151 | u32 xoff; | ||
152 | u32 yoff; | ||
153 | u32 type; | ||
154 | }; | ||
155 | #define PS3FB_RES_FULL 1 | ||
156 | static const struct ps3fb_res_table ps3fb_res[] = { | ||
157 | /* res_x,y margin_x,y full */ | ||
158 | { 720, 480, 72, 48 , 0}, | ||
159 | { 720, 576, 72, 58 , 0}, | ||
160 | { 1280, 720, 78, 38 , 0}, | ||
161 | { 1920, 1080, 116, 58 , 0}, | ||
162 | /* full mode */ | ||
163 | { 720, 480, 0, 0 , PS3FB_RES_FULL}, | ||
164 | { 720, 576, 0, 0 , PS3FB_RES_FULL}, | ||
165 | { 1280, 720, 0, 0 , PS3FB_RES_FULL}, | ||
166 | { 1920, 1080, 0, 0 , PS3FB_RES_FULL}, | ||
167 | /* vesa: normally full mode */ | ||
168 | { 1280, 768, 0, 0 , 0}, | ||
169 | { 1280, 1024, 0, 0 , 0}, | ||
170 | { 1920, 1200, 0, 0 , 0}, | ||
171 | { 0, 0, 0, 0 , 0} }; | ||
172 | |||
173 | /* default resolution */ | ||
174 | #define GPU_RES_INDEX 0 /* 720 x 480 */ | ||
175 | 148 | ||
176 | static const struct fb_videomode ps3fb_modedb[] = { | 149 | static const struct fb_videomode ps3fb_modedb[] = { |
177 | /* 60 Hz broadcast modes (modes "1" to "5") */ | 150 | /* 60 Hz broadcast modes (modes "1" to "5") */ |
@@ -211,7 +184,7 @@ static const struct fb_videomode ps3fb_modedb[] = { | |||
211 | "720p", 50, 1124, 644, 13468, 298, 478, 57, 44, 80, 5, | 184 | "720p", 50, 1124, 644, 13468, 298, 478, 57, 44, 80, 5, |
212 | FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED | 185 | FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED |
213 | }, { | 186 | }, { |
214 | /* 1080 */ | 187 | /* 1080i */ |
215 | "1080i", 50, 1688, 964, 13468, 264, 600, 94, 62, 88, 5, | 188 | "1080i", 50, 1688, 964, 13468, 264, 600, 94, 62, 88, 5, |
216 | FB_SYNC_BROADCAST, FB_VMODE_INTERLACED | 189 | FB_SYNC_BROADCAST, FB_VMODE_INTERLACED |
217 | }, { | 190 | }, { |
@@ -220,24 +193,7 @@ static const struct fb_videomode ps3fb_modedb[] = { | |||
220 | FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED | 193 | FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED |
221 | }, | 194 | }, |
222 | 195 | ||
223 | /* VESA modes (modes "11" to "13") */ | 196 | [FIRST_NATIVE_MODE_INDEX] = |
224 | { | ||
225 | /* WXGA */ | ||
226 | "wxga", 60, 1280, 768, 12924, 160, 24, 29, 3, 136, 6, | ||
227 | 0, FB_VMODE_NONINTERLACED, | ||
228 | FB_MODE_IS_VESA | ||
229 | }, { | ||
230 | /* SXGA */ | ||
231 | "sxga", 60, 1280, 1024, 9259, 248, 48, 38, 1, 112, 3, | ||
232 | FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, | ||
233 | FB_MODE_IS_VESA | ||
234 | }, { | ||
235 | /* WUXGA */ | ||
236 | "wuxga", 60, 1920, 1200, 6494, 80, 48, 26, 3, 32, 6, | ||
237 | FB_SYNC_HOR_HIGH_ACT, FB_VMODE_NONINTERLACED, | ||
238 | FB_MODE_IS_VESA | ||
239 | }, | ||
240 | |||
241 | /* 60 Hz broadcast modes (full resolution versions of modes "1" to "5") */ | 197 | /* 60 Hz broadcast modes (full resolution versions of modes "1" to "5") */ |
242 | { | 198 | { |
243 | /* 480if */ | 199 | /* 480if */ |
@@ -276,12 +232,30 @@ static const struct fb_videomode ps3fb_modedb[] = { | |||
276 | FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED | 232 | FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED |
277 | }, { | 233 | }, { |
278 | /* 1080if */ | 234 | /* 1080if */ |
279 | "1080f", 50, 1920, 1080, 13468, 148, 484, 36, 4, 88, 5, | 235 | "1080if", 50, 1920, 1080, 13468, 148, 484, 36, 4, 88, 5, |
280 | FB_SYNC_BROADCAST, FB_VMODE_INTERLACED | 236 | FB_SYNC_BROADCAST, FB_VMODE_INTERLACED |
281 | }, { | 237 | }, { |
282 | /* 1080pf */ | 238 | /* 1080pf */ |
283 | "1080pf", 50, 1920, 1080, 6734, 148, 484, 36, 4, 88, 5, | 239 | "1080pf", 50, 1920, 1080, 6734, 148, 484, 36, 4, 88, 5, |
284 | FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED | 240 | FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED |
241 | }, | ||
242 | |||
243 | /* VESA modes (modes "11" to "13") */ | ||
244 | { | ||
245 | /* WXGA */ | ||
246 | "wxga", 60, 1280, 768, 12924, 160, 24, 29, 3, 136, 6, | ||
247 | 0, FB_VMODE_NONINTERLACED, | ||
248 | FB_MODE_IS_VESA | ||
249 | }, { | ||
250 | /* SXGA */ | ||
251 | "sxga", 60, 1280, 1024, 9259, 248, 48, 38, 1, 112, 3, | ||
252 | FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, | ||
253 | FB_MODE_IS_VESA | ||
254 | }, { | ||
255 | /* WUXGA */ | ||
256 | "wuxga", 60, 1920, 1200, 6494, 80, 48, 26, 3, 32, 6, | ||
257 | FB_SYNC_HOR_HIGH_ACT, FB_VMODE_NONINTERLACED, | ||
258 | FB_MODE_IS_VESA | ||
285 | } | 259 | } |
286 | }; | 260 | }; |
287 | 261 | ||
@@ -289,110 +263,188 @@ static const struct fb_videomode ps3fb_modedb[] = { | |||
289 | #define HEAD_A | 263 | #define HEAD_A |
290 | #define HEAD_B | 264 | #define HEAD_B |
291 | 265 | ||
292 | #define X_OFF(i) (ps3fb_res[i].xoff) /* left/right margin (pixel) */ | ||
293 | #define Y_OFF(i) (ps3fb_res[i].yoff) /* top/bottom margin (pixel) */ | ||
294 | #define WIDTH(i) (ps3fb_res[i].xres) /* width of FB */ | ||
295 | #define HEIGHT(i) (ps3fb_res[i].yres) /* height of FB */ | ||
296 | #define BPP 4 /* number of bytes per pixel */ | 266 | #define BPP 4 /* number of bytes per pixel */ |
297 | 267 | ||
298 | /* Start of the virtual frame buffer (relative to fullscreen ) */ | ||
299 | #define VP_OFF(i) ((WIDTH(i) * Y_OFF(i) + X_OFF(i)) * BPP) | ||
300 | |||
301 | 268 | ||
302 | static int ps3fb_mode; | 269 | static int ps3fb_mode; |
303 | module_param(ps3fb_mode, int, 0); | 270 | module_param(ps3fb_mode, int, 0); |
304 | 271 | ||
305 | static char *mode_option __devinitdata; | 272 | static char *mode_option __devinitdata; |
306 | 273 | ||
307 | static int ps3fb_get_res_table(u32 xres, u32 yres, int mode) | 274 | static int ps3fb_cmp_mode(const struct fb_videomode *vmode, |
275 | const struct fb_var_screeninfo *var) | ||
308 | { | 276 | { |
309 | int full_mode; | 277 | long xres, yres, left_margin, right_margin, upper_margin, lower_margin; |
310 | unsigned int i; | 278 | long dx, dy; |
311 | u32 x, y, f; | 279 | |
312 | 280 | /* maximum values */ | |
313 | full_mode = (mode & PS3FB_FULL_MODE_BIT) ? PS3FB_RES_FULL : 0; | 281 | if (var->xres > vmode->xres || var->yres > vmode->yres || |
314 | for (i = 0;; i++) { | 282 | var->pixclock > vmode->pixclock || |
315 | x = ps3fb_res[i].xres; | 283 | var->hsync_len > vmode->hsync_len || |
316 | y = ps3fb_res[i].yres; | 284 | var->vsync_len > vmode->vsync_len) |
317 | f = ps3fb_res[i].type; | 285 | return -1; |
318 | |||
319 | if (!x) { | ||
320 | pr_debug("ERROR: ps3fb_get_res_table()\n"); | ||
321 | return -1; | ||
322 | } | ||
323 | 286 | ||
324 | if (full_mode == PS3FB_RES_FULL && f != PS3FB_RES_FULL) | 287 | /* progressive/interlaced must match */ |
325 | continue; | 288 | if ((var->vmode & FB_VMODE_MASK) != vmode->vmode) |
289 | return -1; | ||
326 | 290 | ||
327 | if (x == xres && (yres == 0 || y == yres)) | 291 | /* minimum resolution */ |
328 | break; | 292 | xres = max(var->xres, 1U); |
293 | yres = max(var->yres, 1U); | ||
294 | |||
295 | /* minimum margins */ | ||
296 | left_margin = max(var->left_margin, vmode->left_margin); | ||
297 | right_margin = max(var->right_margin, vmode->right_margin); | ||
298 | upper_margin = max(var->upper_margin, vmode->upper_margin); | ||
299 | lower_margin = max(var->lower_margin, vmode->lower_margin); | ||
300 | |||
301 | /* resolution + margins may not exceed native parameters */ | ||
302 | dx = ((long)vmode->left_margin + (long)vmode->xres + | ||
303 | (long)vmode->right_margin) - | ||
304 | (left_margin + xres + right_margin); | ||
305 | if (dx < 0) | ||
306 | return -1; | ||
329 | 307 | ||
330 | x = x - 2 * ps3fb_res[i].xoff; | 308 | dy = ((long)vmode->upper_margin + (long)vmode->yres + |
331 | y = y - 2 * ps3fb_res[i].yoff; | 309 | (long)vmode->lower_margin) - |
332 | if (x == xres && (yres == 0 || y == yres)) | 310 | (upper_margin + yres + lower_margin); |
333 | break; | 311 | if (dy < 0) |
312 | return -1; | ||
313 | |||
314 | /* exact match */ | ||
315 | if (!dx && !dy) | ||
316 | return 0; | ||
317 | |||
318 | /* resolution difference */ | ||
319 | return (vmode->xres - xres) * (vmode->yres - yres); | ||
320 | } | ||
321 | |||
322 | static const struct fb_videomode *ps3fb_native_vmode(enum ps3av_mode_num id) | ||
323 | { | ||
324 | return &ps3fb_modedb[FIRST_NATIVE_MODE_INDEX + id - 1]; | ||
325 | } | ||
326 | |||
327 | static const struct fb_videomode *ps3fb_vmode(int id) | ||
328 | { | ||
329 | u32 mode = id & PS3AV_MODE_MASK; | ||
330 | |||
331 | if (mode < PS3AV_MODE_480I || mode > PS3AV_MODE_WUXGA) | ||
332 | return NULL; | ||
333 | |||
334 | if (mode <= PS3AV_MODE_1080P50 && !(id & PS3AV_MODE_FULL)) { | ||
335 | /* Non-fullscreen broadcast mode */ | ||
336 | return &ps3fb_modedb[mode - 1]; | ||
334 | } | 337 | } |
335 | return i; | 338 | |
339 | return ps3fb_native_vmode(mode); | ||
336 | } | 340 | } |
337 | 341 | ||
338 | static unsigned int ps3fb_find_mode(const struct fb_var_screeninfo *var, | 342 | static unsigned int ps3fb_find_mode(struct fb_var_screeninfo *var, |
339 | u32 *ddr_line_length, u32 *xdr_line_length) | 343 | u32 *ddr_line_length, u32 *xdr_line_length) |
340 | { | 344 | { |
341 | unsigned int i, mode; | 345 | unsigned int id, best_id; |
342 | 346 | int diff, best_diff; | |
343 | for (i = 0; i < ARRAY_SIZE(ps3fb_modedb); i++) | 347 | const struct fb_videomode *vmode; |
344 | if (var->xres == ps3fb_modedb[i].xres && | 348 | long gap; |
345 | var->yres == ps3fb_modedb[i].yres && | 349 | |
346 | var->pixclock == ps3fb_modedb[i].pixclock && | 350 | best_id = 0; |
347 | var->hsync_len == ps3fb_modedb[i].hsync_len && | 351 | best_diff = INT_MAX; |
348 | var->vsync_len == ps3fb_modedb[i].vsync_len && | 352 | pr_debug("%s: wanted %u [%u] %u x %u [%u] %u\n", __func__, |
349 | var->left_margin == ps3fb_modedb[i].left_margin && | 353 | var->left_margin, var->xres, var->right_margin, |
350 | var->right_margin == ps3fb_modedb[i].right_margin && | 354 | var->upper_margin, var->yres, var->lower_margin); |
351 | var->upper_margin == ps3fb_modedb[i].upper_margin && | 355 | for (id = PS3AV_MODE_480I; id <= PS3AV_MODE_WUXGA; id++) { |
352 | var->lower_margin == ps3fb_modedb[i].lower_margin && | 356 | vmode = ps3fb_native_vmode(id); |
353 | var->sync == ps3fb_modedb[i].sync && | 357 | diff = ps3fb_cmp_mode(vmode, var); |
354 | (var->vmode & FB_VMODE_MASK) == ps3fb_modedb[i].vmode) | 358 | pr_debug("%s: mode %u: %u [%u] %u x %u [%u] %u: diff = %d\n", |
355 | goto found; | 359 | __func__, id, vmode->left_margin, vmode->xres, |
356 | 360 | vmode->right_margin, vmode->upper_margin, | |
357 | pr_debug("ps3fb_find_mode: mode not found\n"); | 361 | vmode->yres, vmode->lower_margin, diff); |
358 | return 0; | 362 | if (diff < 0) |
363 | continue; | ||
364 | if (diff < best_diff) { | ||
365 | best_id = id; | ||
366 | if (!diff) | ||
367 | break; | ||
368 | best_diff = diff; | ||
369 | } | ||
370 | } | ||
359 | 371 | ||
360 | found: | 372 | if (!best_id) { |
361 | /* Cropped broadcast modes use the full line length */ | 373 | pr_debug("%s: no suitable mode found\n", __func__); |
362 | *ddr_line_length = ps3fb_modedb[i < 10 ? i + 13 : i].xres * BPP; | 374 | return 0; |
375 | } | ||
363 | 376 | ||
364 | if (ps3_compare_firmware_version(1, 9, 0) >= 0) { | 377 | id = best_id; |
365 | *xdr_line_length = GPU_ALIGN_UP(max(var->xres, | 378 | vmode = ps3fb_native_vmode(id); |
366 | var->xres_virtual) * BPP); | ||
367 | if (*xdr_line_length > GPU_MAX_LINE_LENGTH) | ||
368 | *xdr_line_length = GPU_MAX_LINE_LENGTH; | ||
369 | } else | ||
370 | *xdr_line_length = *ddr_line_length; | ||
371 | 379 | ||
372 | /* Full broadcast modes have the full mode bit set */ | 380 | *ddr_line_length = vmode->xres * BPP; |
373 | mode = i > 12 ? (i - 12) | PS3FB_FULL_MODE_BIT : i + 1; | ||
374 | 381 | ||
375 | pr_debug("ps3fb_find_mode: mode %u\n", mode); | 382 | /* minimum resolution */ |
383 | if (!var->xres) | ||
384 | var->xres = 1; | ||
385 | if (!var->yres) | ||
386 | var->yres = 1; | ||
376 | 387 | ||
377 | return mode; | 388 | /* minimum virtual resolution */ |
378 | } | 389 | if (var->xres_virtual < var->xres) |
390 | var->xres_virtual = var->xres; | ||
391 | if (var->yres_virtual < var->yres) | ||
392 | var->yres_virtual = var->yres; | ||
379 | 393 | ||
380 | static const struct fb_videomode *ps3fb_default_mode(int id) | 394 | /* minimum margins */ |
381 | { | 395 | if (var->left_margin < vmode->left_margin) |
382 | u32 mode = id & PS3AV_MODE_MASK; | 396 | var->left_margin = vmode->left_margin; |
383 | u32 flags; | 397 | if (var->right_margin < vmode->right_margin) |
398 | var->right_margin = vmode->right_margin; | ||
399 | if (var->upper_margin < vmode->upper_margin) | ||
400 | var->upper_margin = vmode->upper_margin; | ||
401 | if (var->lower_margin < vmode->lower_margin) | ||
402 | var->lower_margin = vmode->lower_margin; | ||
403 | |||
404 | /* extra margins */ | ||
405 | gap = ((long)vmode->left_margin + (long)vmode->xres + | ||
406 | (long)vmode->right_margin) - | ||
407 | ((long)var->left_margin + (long)var->xres + | ||
408 | (long)var->right_margin); | ||
409 | if (gap > 0) { | ||
410 | var->left_margin += gap/2; | ||
411 | var->right_margin += (gap+1)/2; | ||
412 | pr_debug("%s: rounded up H to %u [%u] %u\n", __func__, | ||
413 | var->left_margin, var->xres, var->right_margin); | ||
414 | } | ||
384 | 415 | ||
385 | if (mode < 1 || mode > 13) | 416 | gap = ((long)vmode->upper_margin + (long)vmode->yres + |
386 | return NULL; | 417 | (long)vmode->lower_margin) - |
418 | ((long)var->upper_margin + (long)var->yres + | ||
419 | (long)var->lower_margin); | ||
420 | if (gap > 0) { | ||
421 | var->upper_margin += gap/2; | ||
422 | var->lower_margin += (gap+1)/2; | ||
423 | pr_debug("%s: rounded up V to %u [%u] %u\n", __func__, | ||
424 | var->upper_margin, var->yres, var->lower_margin); | ||
425 | } | ||
426 | |||
427 | /* fixed fields */ | ||
428 | var->pixclock = vmode->pixclock; | ||
429 | var->hsync_len = vmode->hsync_len; | ||
430 | var->vsync_len = vmode->vsync_len; | ||
431 | var->sync = vmode->sync; | ||
387 | 432 | ||
388 | flags = id & ~PS3AV_MODE_MASK; | 433 | if (ps3_compare_firmware_version(1, 9, 0) >= 0) { |
434 | *xdr_line_length = GPU_ALIGN_UP(var->xres_virtual * BPP); | ||
435 | if (*xdr_line_length > GPU_MAX_LINE_LENGTH) | ||
436 | *xdr_line_length = GPU_MAX_LINE_LENGTH; | ||
437 | } else | ||
438 | *xdr_line_length = *ddr_line_length; | ||
389 | 439 | ||
390 | if (mode <= 10 && flags & PS3FB_FULL_MODE_BIT) { | 440 | if (vmode->sync & FB_SYNC_BROADCAST) { |
391 | /* Full broadcast mode */ | 441 | /* Full broadcast modes have the full mode bit set */ |
392 | return &ps3fb_modedb[mode + 12]; | 442 | if (vmode->xres == var->xres && vmode->yres == var->yres) |
443 | id |= PS3AV_MODE_FULL; | ||
393 | } | 444 | } |
394 | 445 | ||
395 | return &ps3fb_modedb[mode - 1]; | 446 | pr_debug("%s: mode %u\n", __func__, id); |
447 | return id; | ||
396 | } | 448 | } |
397 | 449 | ||
398 | static void ps3fb_sync_image(struct device *dev, u64 frame_offset, | 450 | static void ps3fb_sync_image(struct device *dev, u64 frame_offset, |
@@ -439,8 +491,7 @@ static void ps3fb_sync_image(struct device *dev, u64 frame_offset, | |||
439 | static int ps3fb_sync(struct fb_info *info, u32 frame) | 491 | static int ps3fb_sync(struct fb_info *info, u32 frame) |
440 | { | 492 | { |
441 | struct ps3fb_par *par = info->par; | 493 | struct ps3fb_par *par = info->par; |
442 | int i, error = 0; | 494 | int error = 0; |
443 | u32 ddr_line_length, xdr_line_length; | ||
444 | u64 ddr_base, xdr_base; | 495 | u64 ddr_base, xdr_base; |
445 | 496 | ||
446 | if (frame > par->num_frames - 1) { | 497 | if (frame > par->num_frames - 1) { |
@@ -450,16 +501,13 @@ static int ps3fb_sync(struct fb_info *info, u32 frame) | |||
450 | goto out; | 501 | goto out; |
451 | } | 502 | } |
452 | 503 | ||
453 | i = par->res_index; | 504 | xdr_base = frame * par->xdr_frame_size; |
454 | xdr_line_length = info->fix.line_length; | 505 | ddr_base = frame * par->ddr_frame_size; |
455 | ddr_line_length = ps3fb_res[i].xres * BPP; | ||
456 | xdr_base = frame * info->var.yres_virtual * xdr_line_length; | ||
457 | ddr_base = frame * ps3fb_res[i].yres * ddr_line_length; | ||
458 | 506 | ||
459 | ps3fb_sync_image(info->device, ddr_base + par->full_offset, | 507 | ps3fb_sync_image(info->device, ddr_base + par->full_offset, |
460 | ddr_base + par->fb_offset, xdr_base + par->pan_offset, | 508 | ddr_base + par->fb_offset, xdr_base + par->pan_offset, |
461 | par->width, par->height, ddr_line_length, | 509 | par->width, par->height, par->ddr_line_length, |
462 | xdr_line_length); | 510 | info->fix.line_length); |
463 | 511 | ||
464 | out: | 512 | out: |
465 | return error; | 513 | return error; |
@@ -498,22 +546,11 @@ static int ps3fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) | |||
498 | u32 xdr_line_length, ddr_line_length; | 546 | u32 xdr_line_length, ddr_line_length; |
499 | int mode; | 547 | int mode; |
500 | 548 | ||
501 | dev_dbg(info->device, "var->xres:%u info->var.xres:%u\n", var->xres, | ||
502 | info->var.xres); | ||
503 | dev_dbg(info->device, "var->yres:%u info->var.yres:%u\n", var->yres, | ||
504 | info->var.yres); | ||
505 | |||
506 | /* FIXME For now we do exact matches only */ | ||
507 | mode = ps3fb_find_mode(var, &ddr_line_length, &xdr_line_length); | 549 | mode = ps3fb_find_mode(var, &ddr_line_length, &xdr_line_length); |
508 | if (!mode) | 550 | if (!mode) |
509 | return -EINVAL; | 551 | return -EINVAL; |
510 | 552 | ||
511 | /* Virtual screen */ | 553 | /* Virtual screen */ |
512 | if (var->xres_virtual < var->xres) | ||
513 | var->xres_virtual = var->xres; | ||
514 | if (var->yres_virtual < var->yres) | ||
515 | var->yres_virtual = var->yres; | ||
516 | |||
517 | if (var->xres_virtual > xdr_line_length / BPP) { | 554 | if (var->xres_virtual > xdr_line_length / BPP) { |
518 | dev_dbg(info->device, | 555 | dev_dbg(info->device, |
519 | "Horizontal virtual screen size too large\n"); | 556 | "Horizontal virtual screen size too large\n"); |
@@ -559,7 +596,7 @@ static int ps3fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) | |||
559 | } | 596 | } |
560 | 597 | ||
561 | /* Memory limit */ | 598 | /* Memory limit */ |
562 | if (var->yres_virtual * xdr_line_length > ps3fb.xdr_size) { | 599 | if (var->yres_virtual * xdr_line_length > info->fix.smem_len) { |
563 | dev_dbg(info->device, "Not enough memory\n"); | 600 | dev_dbg(info->device, "Not enough memory\n"); |
564 | return -ENOMEM; | 601 | return -ENOMEM; |
565 | } | 602 | } |
@@ -578,39 +615,38 @@ static int ps3fb_set_par(struct fb_info *info) | |||
578 | { | 615 | { |
579 | struct ps3fb_par *par = info->par; | 616 | struct ps3fb_par *par = info->par; |
580 | unsigned int mode, ddr_line_length, xdr_line_length, lines, maxlines; | 617 | unsigned int mode, ddr_line_length, xdr_line_length, lines, maxlines; |
581 | int i; | 618 | unsigned int ddr_xoff, ddr_yoff, offset; |
582 | unsigned long offset; | 619 | const struct fb_videomode *vmode; |
583 | u64 dst; | 620 | u64 dst; |
584 | 621 | ||
585 | dev_dbg(info->device, "xres:%d xv:%d yres:%d yv:%d clock:%d\n", | ||
586 | info->var.xres, info->var.xres_virtual, | ||
587 | info->var.yres, info->var.yres_virtual, info->var.pixclock); | ||
588 | |||
589 | mode = ps3fb_find_mode(&info->var, &ddr_line_length, &xdr_line_length); | 622 | mode = ps3fb_find_mode(&info->var, &ddr_line_length, &xdr_line_length); |
590 | if (!mode) | 623 | if (!mode) |
591 | return -EINVAL; | 624 | return -EINVAL; |
592 | 625 | ||
593 | i = ps3fb_get_res_table(info->var.xres, info->var.yres, mode); | 626 | vmode = ps3fb_native_vmode(mode & PS3AV_MODE_MASK); |
594 | par->res_index = i; | ||
595 | 627 | ||
596 | info->fix.smem_start = virt_to_abs(ps3fb.xdr_ea); | ||
597 | info->fix.smem_len = ps3fb.xdr_size; | ||
598 | info->fix.xpanstep = info->var.xres_virtual > info->var.xres ? 1 : 0; | 628 | info->fix.xpanstep = info->var.xres_virtual > info->var.xres ? 1 : 0; |
599 | info->fix.ypanstep = info->var.yres_virtual > info->var.yres ? 1 : 0; | 629 | info->fix.ypanstep = info->var.yres_virtual > info->var.yres ? 1 : 0; |
600 | info->fix.line_length = xdr_line_length; | 630 | info->fix.line_length = xdr_line_length; |
601 | 631 | ||
602 | info->screen_base = (char __iomem *)ps3fb.xdr_ea; | 632 | par->ddr_line_length = ddr_line_length; |
633 | par->ddr_frame_size = vmode->yres * ddr_line_length; | ||
634 | par->xdr_frame_size = info->var.yres_virtual * xdr_line_length; | ||
603 | 635 | ||
604 | par->num_frames = ps3fb.xdr_size / | 636 | par->num_frames = info->fix.smem_len / |
605 | max(ps3fb_res[i].yres * ddr_line_length, | 637 | max(par->ddr_frame_size, par->xdr_frame_size); |
606 | info->var.yres_virtual * xdr_line_length); | ||
607 | 638 | ||
608 | /* Keep the special bits we cannot set using fb_var_screeninfo */ | 639 | /* Keep the special bits we cannot set using fb_var_screeninfo */ |
609 | par->new_mode_id = (par->new_mode_id & ~PS3AV_MODE_MASK) | mode; | 640 | par->new_mode_id = (par->new_mode_id & ~PS3AV_MODE_MASK) | mode; |
610 | 641 | ||
611 | par->width = info->var.xres; | 642 | par->width = info->var.xres; |
612 | par->height = info->var.yres; | 643 | par->height = info->var.yres; |
613 | offset = VP_OFF(i); | 644 | |
645 | /* Start of the virtual frame buffer (relative to fullscreen) */ | ||
646 | ddr_xoff = info->var.left_margin - vmode->left_margin; | ||
647 | ddr_yoff = info->var.upper_margin - vmode->upper_margin; | ||
648 | offset = ddr_yoff * ddr_line_length + ddr_xoff * BPP; | ||
649 | |||
614 | par->fb_offset = GPU_ALIGN_UP(offset); | 650 | par->fb_offset = GPU_ALIGN_UP(offset); |
615 | par->full_offset = par->fb_offset - offset; | 651 | par->full_offset = par->fb_offset - offset; |
616 | par->pan_offset = info->var.yoffset * xdr_line_length + | 652 | par->pan_offset = info->var.yoffset * xdr_line_length + |
@@ -625,16 +661,16 @@ static int ps3fb_set_par(struct fb_info *info) | |||
625 | } | 661 | } |
626 | 662 | ||
627 | /* Clear XDR frame buffer memory */ | 663 | /* Clear XDR frame buffer memory */ |
628 | memset(ps3fb.xdr_ea, 0, ps3fb.xdr_size); | 664 | memset((void __force *)info->screen_base, 0, info->fix.smem_len); |
629 | 665 | ||
630 | /* Clear DDR frame buffer memory */ | 666 | /* Clear DDR frame buffer memory */ |
631 | lines = ps3fb_res[i].yres * par->num_frames; | 667 | lines = vmode->yres * par->num_frames; |
632 | if (par->full_offset) | 668 | if (par->full_offset) |
633 | lines++; | 669 | lines++; |
634 | maxlines = ps3fb.xdr_size / ddr_line_length; | 670 | maxlines = info->fix.smem_len / ddr_line_length; |
635 | for (dst = 0; lines; dst += maxlines * ddr_line_length) { | 671 | for (dst = 0; lines; dst += maxlines * ddr_line_length) { |
636 | unsigned int l = min(lines, maxlines); | 672 | unsigned int l = min(lines, maxlines); |
637 | ps3fb_sync_image(info->device, 0, dst, 0, ps3fb_res[i].xres, l, | 673 | ps3fb_sync_image(info->device, 0, dst, 0, vmode->xres, l, |
638 | ddr_line_length, ddr_line_length); | 674 | ddr_line_length, ddr_line_length); |
639 | lines -= l; | 675 | lines -= l; |
640 | } | 676 | } |
@@ -797,7 +833,7 @@ static int ps3fb_ioctl(struct fb_info *info, unsigned int cmd, | |||
797 | case PS3FB_IOCTL_SETMODE: | 833 | case PS3FB_IOCTL_SETMODE: |
798 | { | 834 | { |
799 | struct ps3fb_par *par = info->par; | 835 | struct ps3fb_par *par = info->par; |
800 | const struct fb_videomode *mode; | 836 | const struct fb_videomode *vmode; |
801 | struct fb_var_screeninfo var; | 837 | struct fb_var_screeninfo var; |
802 | 838 | ||
803 | if (copy_from_user(&val, argp, sizeof(val))) | 839 | if (copy_from_user(&val, argp, sizeof(val))) |
@@ -810,10 +846,10 @@ static int ps3fb_ioctl(struct fb_info *info, unsigned int cmd, | |||
810 | } | 846 | } |
811 | dev_dbg(info->device, "PS3FB_IOCTL_SETMODE:%x\n", val); | 847 | dev_dbg(info->device, "PS3FB_IOCTL_SETMODE:%x\n", val); |
812 | retval = -EINVAL; | 848 | retval = -EINVAL; |
813 | mode = ps3fb_default_mode(val); | 849 | vmode = ps3fb_vmode(val); |
814 | if (mode) { | 850 | if (vmode) { |
815 | var = info->var; | 851 | var = info->var; |
816 | fb_videomode_to_var(&var, mode); | 852 | fb_videomode_to_var(&var, vmode); |
817 | acquire_console_sem(); | 853 | acquire_console_sem(); |
818 | info->flags |= FBINFO_MISC_USEREVENT; | 854 | info->flags |= FBINFO_MISC_USEREVENT; |
819 | /* Force, in case only special bits changed */ | 855 | /* Force, in case only special bits changed */ |
@@ -975,10 +1011,9 @@ static int ps3fb_xdr_settings(u64 xdr_lpar, struct device *dev) | |||
975 | __func__, status); | 1011 | __func__, status); |
976 | return -ENXIO; | 1012 | return -ENXIO; |
977 | } | 1013 | } |
978 | dev_dbg(dev, | 1014 | dev_dbg(dev, "video:%p ioif:%lx lpar:%lx size:%lx\n", |
979 | "video:%p xdr_ea:%p ioif:%lx lpar:%lx phys:%lx size:%lx\n", | 1015 | ps3fb_videomemory.address, GPU_IOIF, xdr_lpar, |
980 | ps3fb_videomemory.address, ps3fb.xdr_ea, GPU_IOIF, xdr_lpar, | 1016 | ps3fb_videomemory.size); |
981 | virt_to_abs(ps3fb.xdr_ea), ps3fb_videomemory.size); | ||
982 | 1017 | ||
983 | status = lv1_gpu_context_attribute(ps3fb.context_handle, | 1018 | status = lv1_gpu_context_attribute(ps3fb.context_handle, |
984 | L1GPU_CONTEXT_ATTRIBUTE_FB_SETUP, | 1019 | L1GPU_CONTEXT_ATTRIBUTE_FB_SETUP, |
@@ -1055,14 +1090,14 @@ static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev) | |||
1055 | struct fb_info *info; | 1090 | struct fb_info *info; |
1056 | struct ps3fb_par *par; | 1091 | struct ps3fb_par *par; |
1057 | int retval = -ENOMEM; | 1092 | int retval = -ENOMEM; |
1058 | u32 xres, yres; | ||
1059 | u64 ddr_lpar = 0; | 1093 | u64 ddr_lpar = 0; |
1060 | u64 lpar_dma_control = 0; | 1094 | u64 lpar_dma_control = 0; |
1061 | u64 lpar_driver_info = 0; | 1095 | u64 lpar_driver_info = 0; |
1062 | u64 lpar_reports = 0; | 1096 | u64 lpar_reports = 0; |
1063 | u64 lpar_reports_size = 0; | 1097 | u64 lpar_reports_size = 0; |
1064 | u64 xdr_lpar; | 1098 | u64 xdr_lpar; |
1065 | int status, res_index; | 1099 | void *fb_start; |
1100 | int status; | ||
1066 | struct task_struct *task; | 1101 | struct task_struct *task; |
1067 | unsigned long max_ps3fb_size; | 1102 | unsigned long max_ps3fb_size; |
1068 | 1103 | ||
@@ -1080,14 +1115,7 @@ static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev) | |||
1080 | 1115 | ||
1081 | if (!ps3fb_mode) | 1116 | if (!ps3fb_mode) |
1082 | ps3fb_mode = ps3av_get_mode(); | 1117 | ps3fb_mode = ps3av_get_mode(); |
1083 | dev_dbg(&dev->core, "ps3av_mode:%d\n", ps3fb_mode); | 1118 | dev_dbg(&dev->core, "ps3fb_mode: %d\n", ps3fb_mode); |
1084 | |||
1085 | if (ps3fb_mode > 0 && | ||
1086 | !ps3av_video_mode2res(ps3fb_mode, &xres, &yres)) { | ||
1087 | res_index = ps3fb_get_res_table(xres, yres, ps3fb_mode); | ||
1088 | dev_dbg(&dev->core, "res_index:%d\n", res_index); | ||
1089 | } else | ||
1090 | res_index = GPU_RES_INDEX; | ||
1091 | 1119 | ||
1092 | atomic_set(&ps3fb.f_count, -1); /* fbcon opens ps3fb */ | 1120 | atomic_set(&ps3fb.f_count, -1); /* fbcon opens ps3fb */ |
1093 | atomic_set(&ps3fb.ext_flip, 0); /* for flip with vsync */ | 1121 | atomic_set(&ps3fb.ext_flip, 0); /* for flip with vsync */ |
@@ -1124,7 +1152,7 @@ static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev) | |||
1124 | } | 1152 | } |
1125 | 1153 | ||
1126 | /* vsync interrupt */ | 1154 | /* vsync interrupt */ |
1127 | ps3fb.dinfo = ioremap(lpar_driver_info, 128 * 1024); | 1155 | ps3fb.dinfo = (void __force *)ioremap(lpar_driver_info, 128 * 1024); |
1128 | if (!ps3fb.dinfo) { | 1156 | if (!ps3fb.dinfo) { |
1129 | dev_err(&dev->core, "%s: ioremap failed\n", __func__); | 1157 | dev_err(&dev->core, "%s: ioremap failed\n", __func__); |
1130 | goto err_gpu_context_free; | 1158 | goto err_gpu_context_free; |
@@ -1134,22 +1162,10 @@ static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev) | |||
1134 | if (retval) | 1162 | if (retval) |
1135 | goto err_iounmap_dinfo; | 1163 | goto err_iounmap_dinfo; |
1136 | 1164 | ||
1137 | /* XDR frame buffer */ | ||
1138 | ps3fb.xdr_ea = ps3fb_videomemory.address; | ||
1139 | xdr_lpar = ps3_mm_phys_to_lpar(__pa(ps3fb.xdr_ea)); | ||
1140 | |||
1141 | /* Clear memory to prevent kernel info leakage into userspace */ | 1165 | /* Clear memory to prevent kernel info leakage into userspace */ |
1142 | memset(ps3fb.xdr_ea, 0, ps3fb_videomemory.size); | 1166 | memset(ps3fb_videomemory.address, 0, ps3fb_videomemory.size); |
1143 | |||
1144 | /* | ||
1145 | * The GPU command buffer is at the start of video memory | ||
1146 | * As we don't use the full command buffer, we can put the actual | ||
1147 | * frame buffer at offset GPU_FB_START and save some precious XDR | ||
1148 | * memory | ||
1149 | */ | ||
1150 | ps3fb.xdr_ea += GPU_FB_START; | ||
1151 | ps3fb.xdr_size = ps3fb_videomemory.size - GPU_FB_START; | ||
1152 | 1167 | ||
1168 | xdr_lpar = ps3_mm_phys_to_lpar(__pa(ps3fb_videomemory.address)); | ||
1153 | retval = ps3fb_xdr_settings(xdr_lpar, &dev->core); | 1169 | retval = ps3fb_xdr_settings(xdr_lpar, &dev->core); |
1154 | if (retval) | 1170 | if (retval) |
1155 | goto err_free_irq; | 1171 | goto err_free_irq; |
@@ -1161,15 +1177,22 @@ static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev) | |||
1161 | par = info->par; | 1177 | par = info->par; |
1162 | par->mode_id = ~ps3fb_mode; /* != ps3fb_mode, to trigger change */ | 1178 | par->mode_id = ~ps3fb_mode; /* != ps3fb_mode, to trigger change */ |
1163 | par->new_mode_id = ps3fb_mode; | 1179 | par->new_mode_id = ps3fb_mode; |
1164 | par->res_index = res_index; | ||
1165 | par->num_frames = 1; | 1180 | par->num_frames = 1; |
1166 | 1181 | ||
1167 | info->screen_base = (char __iomem *)ps3fb.xdr_ea; | ||
1168 | info->fbops = &ps3fb_ops; | 1182 | info->fbops = &ps3fb_ops; |
1169 | |||
1170 | info->fix = ps3fb_fix; | 1183 | info->fix = ps3fb_fix; |
1171 | info->fix.smem_start = virt_to_abs(ps3fb.xdr_ea); | 1184 | |
1172 | info->fix.smem_len = ps3fb.xdr_size; | 1185 | /* |
1186 | * The GPU command buffer is at the start of video memory | ||
1187 | * As we don't use the full command buffer, we can put the actual | ||
1188 | * frame buffer at offset GPU_FB_START and save some precious XDR | ||
1189 | * memory | ||
1190 | */ | ||
1191 | fb_start = ps3fb_videomemory.address + GPU_FB_START; | ||
1192 | info->screen_base = (char __force __iomem *)fb_start; | ||
1193 | info->fix.smem_start = virt_to_abs(fb_start); | ||
1194 | info->fix.smem_len = ps3fb_videomemory.size - GPU_FB_START; | ||
1195 | |||
1173 | info->pseudo_palette = par->pseudo_palette; | 1196 | info->pseudo_palette = par->pseudo_palette; |
1174 | info->flags = FBINFO_DEFAULT | FBINFO_READS_FAST | | 1197 | info->flags = FBINFO_DEFAULT | FBINFO_READS_FAST | |
1175 | FBINFO_HWACCEL_XPAN | FBINFO_HWACCEL_YPAN; | 1198 | FBINFO_HWACCEL_XPAN | FBINFO_HWACCEL_YPAN; |
@@ -1180,7 +1203,7 @@ static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev) | |||
1180 | 1203 | ||
1181 | if (!fb_find_mode(&info->var, info, mode_option, ps3fb_modedb, | 1204 | if (!fb_find_mode(&info->var, info, mode_option, ps3fb_modedb, |
1182 | ARRAY_SIZE(ps3fb_modedb), | 1205 | ARRAY_SIZE(ps3fb_modedb), |
1183 | ps3fb_default_mode(par->new_mode_id), 32)) { | 1206 | ps3fb_vmode(par->new_mode_id), 32)) { |
1184 | retval = -EINVAL; | 1207 | retval = -EINVAL; |
1185 | goto err_fb_dealloc; | 1208 | goto err_fb_dealloc; |
1186 | } | 1209 | } |
@@ -1194,9 +1217,9 @@ static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev) | |||
1194 | 1217 | ||
1195 | dev->core.driver_data = info; | 1218 | dev->core.driver_data = info; |
1196 | 1219 | ||
1197 | dev_info(info->device, "%s %s, using %lu KiB of video memory\n", | 1220 | dev_info(info->device, "%s %s, using %u KiB of video memory\n", |
1198 | dev_driver_string(info->dev), info->dev->bus_id, | 1221 | dev_driver_string(info->dev), info->dev->bus_id, |
1199 | ps3fb.xdr_size >> 10); | 1222 | info->fix.smem_len >> 10); |
1200 | 1223 | ||
1201 | task = kthread_run(ps3fbd, info, DEVICE_NAME); | 1224 | task = kthread_run(ps3fbd, info, DEVICE_NAME); |
1202 | if (IS_ERR(task)) { | 1225 | if (IS_ERR(task)) { |
@@ -1219,7 +1242,7 @@ err_free_irq: | |||
1219 | free_irq(ps3fb.irq_no, &dev->core); | 1242 | free_irq(ps3fb.irq_no, &dev->core); |
1220 | ps3_irq_plug_destroy(ps3fb.irq_no); | 1243 | ps3_irq_plug_destroy(ps3fb.irq_no); |
1221 | err_iounmap_dinfo: | 1244 | err_iounmap_dinfo: |
1222 | iounmap((u8 __iomem *)ps3fb.dinfo); | 1245 | iounmap((u8 __force __iomem *)ps3fb.dinfo); |
1223 | err_gpu_context_free: | 1246 | err_gpu_context_free: |
1224 | lv1_gpu_context_free(ps3fb.context_handle); | 1247 | lv1_gpu_context_free(ps3fb.context_handle); |
1225 | err_gpu_memory_free: | 1248 | err_gpu_memory_free: |
@@ -1254,7 +1277,7 @@ static int ps3fb_shutdown(struct ps3_system_bus_device *dev) | |||
1254 | framebuffer_release(info); | 1277 | framebuffer_release(info); |
1255 | info = dev->core.driver_data = NULL; | 1278 | info = dev->core.driver_data = NULL; |
1256 | } | 1279 | } |
1257 | iounmap((u8 __iomem *)ps3fb.dinfo); | 1280 | iounmap((u8 __force __iomem *)ps3fb.dinfo); |
1258 | 1281 | ||
1259 | status = lv1_gpu_context_free(ps3fb.context_handle); | 1282 | status = lv1_gpu_context_free(ps3fb.context_handle); |
1260 | if (status) | 1283 | if (status) |
diff --git a/drivers/video/s3c2410fb.c b/drivers/video/s3c2410fb.c index b3c31d9dc591..71fa6edb5c47 100644 --- a/drivers/video/s3c2410fb.c +++ b/drivers/video/s3c2410fb.c | |||
@@ -110,6 +110,11 @@ static int debug = 0; | |||
110 | 110 | ||
111 | /* useful functions */ | 111 | /* useful functions */ |
112 | 112 | ||
113 | static int is_s3c2412(struct s3c2410fb_info *fbi) | ||
114 | { | ||
115 | return (fbi->drv_type == DRV_S3C2412); | ||
116 | } | ||
117 | |||
113 | /* s3c2410fb_set_lcdaddr | 118 | /* s3c2410fb_set_lcdaddr |
114 | * | 119 | * |
115 | * initialise lcd controller address pointers | 120 | * initialise lcd controller address pointers |
@@ -501,7 +506,7 @@ static void schedule_palette_update(struct s3c2410fb_info *fbi, | |||
501 | { | 506 | { |
502 | unsigned long flags; | 507 | unsigned long flags; |
503 | unsigned long irqen; | 508 | unsigned long irqen; |
504 | void __iomem *regs = fbi->io; | 509 | void __iomem *irq_base = fbi->irq_base; |
505 | 510 | ||
506 | local_irq_save(flags); | 511 | local_irq_save(flags); |
507 | 512 | ||
@@ -511,9 +516,9 @@ static void schedule_palette_update(struct s3c2410fb_info *fbi, | |||
511 | fbi->palette_ready = 1; | 516 | fbi->palette_ready = 1; |
512 | 517 | ||
513 | /* enable IRQ */ | 518 | /* enable IRQ */ |
514 | irqen = readl(regs + S3C2410_LCDINTMSK); | 519 | irqen = readl(irq_base + S3C24XX_LCDINTMSK); |
515 | irqen &= ~S3C2410_LCDINT_FRSYNC; | 520 | irqen &= ~S3C2410_LCDINT_FRSYNC; |
516 | writel(irqen, regs + S3C2410_LCDINTMSK); | 521 | writel(irqen, irq_base + S3C24XX_LCDINTMSK); |
517 | } | 522 | } |
518 | 523 | ||
519 | local_irq_restore(flags); | 524 | local_irq_restore(flags); |
@@ -594,15 +599,17 @@ static int s3c2410fb_setcolreg(unsigned regno, | |||
594 | static int s3c2410fb_blank(int blank_mode, struct fb_info *info) | 599 | static int s3c2410fb_blank(int blank_mode, struct fb_info *info) |
595 | { | 600 | { |
596 | struct s3c2410fb_info *fbi = info->par; | 601 | struct s3c2410fb_info *fbi = info->par; |
597 | void __iomem *regs = fbi->io; | 602 | void __iomem *tpal_reg = fbi->io; |
598 | 603 | ||
599 | dprintk("blank(mode=%d, info=%p)\n", blank_mode, info); | 604 | dprintk("blank(mode=%d, info=%p)\n", blank_mode, info); |
600 | 605 | ||
606 | tpal_reg += is_s3c2412(fbi) ? S3C2412_TPAL : S3C2410_TPAL; | ||
607 | |||
601 | if (blank_mode == FB_BLANK_UNBLANK) | 608 | if (blank_mode == FB_BLANK_UNBLANK) |
602 | writel(0x0, regs + S3C2410_TPAL); | 609 | writel(0x0, tpal_reg); |
603 | else { | 610 | else { |
604 | dprintk("setting TPAL to output 0x000000\n"); | 611 | dprintk("setting TPAL to output 0x000000\n"); |
605 | writel(S3C2410_TPAL_EN, regs + S3C2410_TPAL); | 612 | writel(S3C2410_TPAL_EN, tpal_reg); |
606 | } | 613 | } |
607 | 614 | ||
608 | return 0; | 615 | return 0; |
@@ -663,7 +670,7 @@ static int __init s3c2410fb_map_video_memory(struct fb_info *info) | |||
663 | dma_addr_t map_dma; | 670 | dma_addr_t map_dma; |
664 | unsigned map_size = PAGE_ALIGN(info->fix.smem_len); | 671 | unsigned map_size = PAGE_ALIGN(info->fix.smem_len); |
665 | 672 | ||
666 | dprintk("map_video_memory(fbi=%p)\n", fbi); | 673 | dprintk("map_video_memory(fbi=%p) map_size %u\n", fbi, map_size); |
667 | 674 | ||
668 | info->screen_base = dma_alloc_writecombine(fbi->dev, map_size, | 675 | info->screen_base = dma_alloc_writecombine(fbi->dev, map_size, |
669 | &map_dma, GFP_KERNEL); | 676 | &map_dma, GFP_KERNEL); |
@@ -672,7 +679,7 @@ static int __init s3c2410fb_map_video_memory(struct fb_info *info) | |||
672 | /* prevent initial garbage on screen */ | 679 | /* prevent initial garbage on screen */ |
673 | dprintk("map_video_memory: clear %p:%08x\n", | 680 | dprintk("map_video_memory: clear %p:%08x\n", |
674 | info->screen_base, map_size); | 681 | info->screen_base, map_size); |
675 | memset(info->screen_base, 0xf0, map_size); | 682 | memset(info->screen_base, 0x00, map_size); |
676 | 683 | ||
677 | info->fix.smem_start = map_dma; | 684 | info->fix.smem_start = map_dma; |
678 | 685 | ||
@@ -709,6 +716,16 @@ static int s3c2410fb_init_registers(struct fb_info *info) | |||
709 | struct s3c2410fb_mach_info *mach_info = fbi->dev->platform_data; | 716 | struct s3c2410fb_mach_info *mach_info = fbi->dev->platform_data; |
710 | unsigned long flags; | 717 | unsigned long flags; |
711 | void __iomem *regs = fbi->io; | 718 | void __iomem *regs = fbi->io; |
719 | void __iomem *tpal; | ||
720 | void __iomem *lpcsel; | ||
721 | |||
722 | if (is_s3c2412(fbi)) { | ||
723 | tpal = regs + S3C2412_TPAL; | ||
724 | lpcsel = regs + S3C2412_TCONSEL; | ||
725 | } else { | ||
726 | tpal = regs + S3C2410_TPAL; | ||
727 | lpcsel = regs + S3C2410_LPCSEL; | ||
728 | } | ||
712 | 729 | ||
713 | /* Initialise LCD with values from haret */ | 730 | /* Initialise LCD with values from haret */ |
714 | 731 | ||
@@ -724,12 +741,12 @@ static int s3c2410fb_init_registers(struct fb_info *info) | |||
724 | local_irq_restore(flags); | 741 | local_irq_restore(flags); |
725 | 742 | ||
726 | dprintk("LPCSEL = 0x%08lx\n", mach_info->lpcsel); | 743 | dprintk("LPCSEL = 0x%08lx\n", mach_info->lpcsel); |
727 | writel(mach_info->lpcsel, regs + S3C2410_LPCSEL); | 744 | writel(mach_info->lpcsel, lpcsel); |
728 | 745 | ||
729 | dprintk("replacing TPAL %08x\n", readl(regs + S3C2410_TPAL)); | 746 | dprintk("replacing TPAL %08x\n", readl(tpal)); |
730 | 747 | ||
731 | /* ensure temporary palette disabled */ | 748 | /* ensure temporary palette disabled */ |
732 | writel(0x00, regs + S3C2410_TPAL); | 749 | writel(0x00, tpal); |
733 | 750 | ||
734 | return 0; | 751 | return 0; |
735 | } | 752 | } |
@@ -763,15 +780,15 @@ static void s3c2410fb_write_palette(struct s3c2410fb_info *fbi) | |||
763 | static irqreturn_t s3c2410fb_irq(int irq, void *dev_id) | 780 | static irqreturn_t s3c2410fb_irq(int irq, void *dev_id) |
764 | { | 781 | { |
765 | struct s3c2410fb_info *fbi = dev_id; | 782 | struct s3c2410fb_info *fbi = dev_id; |
766 | void __iomem *regs = fbi->io; | 783 | void __iomem *irq_base = fbi->irq_base; |
767 | unsigned long lcdirq = readl(regs + S3C2410_LCDINTPND); | 784 | unsigned long lcdirq = readl(irq_base + S3C24XX_LCDINTPND); |
768 | 785 | ||
769 | if (lcdirq & S3C2410_LCDINT_FRSYNC) { | 786 | if (lcdirq & S3C2410_LCDINT_FRSYNC) { |
770 | if (fbi->palette_ready) | 787 | if (fbi->palette_ready) |
771 | s3c2410fb_write_palette(fbi); | 788 | s3c2410fb_write_palette(fbi); |
772 | 789 | ||
773 | writel(S3C2410_LCDINT_FRSYNC, regs + S3C2410_LCDINTPND); | 790 | writel(S3C2410_LCDINT_FRSYNC, irq_base + S3C24XX_LCDINTPND); |
774 | writel(S3C2410_LCDINT_FRSYNC, regs + S3C2410_LCDSRCPND); | 791 | writel(S3C2410_LCDINT_FRSYNC, irq_base + S3C24XX_LCDSRCPND); |
775 | } | 792 | } |
776 | 793 | ||
777 | return IRQ_HANDLED; | 794 | return IRQ_HANDLED; |
@@ -779,7 +796,8 @@ static irqreturn_t s3c2410fb_irq(int irq, void *dev_id) | |||
779 | 796 | ||
780 | static char driver_name[] = "s3c2410fb"; | 797 | static char driver_name[] = "s3c2410fb"; |
781 | 798 | ||
782 | static int __init s3c2410fb_probe(struct platform_device *pdev) | 799 | static int __init s3c24xxfb_probe(struct platform_device *pdev, |
800 | enum s3c_drv_type drv_type) | ||
783 | { | 801 | { |
784 | struct s3c2410fb_info *info; | 802 | struct s3c2410fb_info *info; |
785 | struct s3c2410fb_display *display; | 803 | struct s3c2410fb_display *display; |
@@ -799,6 +817,12 @@ static int __init s3c2410fb_probe(struct platform_device *pdev) | |||
799 | return -EINVAL; | 817 | return -EINVAL; |
800 | } | 818 | } |
801 | 819 | ||
820 | if (mach_info->default_display >= mach_info->num_displays) { | ||
821 | dev_err(&pdev->dev, "default is %d but only %d displays\n", | ||
822 | mach_info->default_display, mach_info->num_displays); | ||
823 | return -EINVAL; | ||
824 | } | ||
825 | |||
802 | display = mach_info->displays + mach_info->default_display; | 826 | display = mach_info->displays + mach_info->default_display; |
803 | 827 | ||
804 | irq = platform_get_irq(pdev, 0); | 828 | irq = platform_get_irq(pdev, 0); |
@@ -815,6 +839,7 @@ static int __init s3c2410fb_probe(struct platform_device *pdev) | |||
815 | 839 | ||
816 | info = fbinfo->par; | 840 | info = fbinfo->par; |
817 | info->dev = &pdev->dev; | 841 | info->dev = &pdev->dev; |
842 | info->drv_type = drv_type; | ||
818 | 843 | ||
819 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 844 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
820 | if (res == NULL) { | 845 | if (res == NULL) { |
@@ -838,6 +863,8 @@ static int __init s3c2410fb_probe(struct platform_device *pdev) | |||
838 | goto release_mem; | 863 | goto release_mem; |
839 | } | 864 | } |
840 | 865 | ||
866 | info->irq_base = info->io + ((drv_type == DRV_S3C2412) ? S3C2412_LCDINTBASE : S3C2410_LCDINTBASE); | ||
867 | |||
841 | dprintk("devinit\n"); | 868 | dprintk("devinit\n"); |
842 | 869 | ||
843 | strcpy(fbinfo->fix.id, driver_name); | 870 | strcpy(fbinfo->fix.id, driver_name); |
@@ -946,6 +973,16 @@ dealloc_fb: | |||
946 | return ret; | 973 | return ret; |
947 | } | 974 | } |
948 | 975 | ||
976 | static int __init s3c2410fb_probe(struct platform_device *pdev) | ||
977 | { | ||
978 | return s3c24xxfb_probe(pdev, DRV_S3C2410); | ||
979 | } | ||
980 | |||
981 | static int __init s3c2412fb_probe(struct platform_device *pdev) | ||
982 | { | ||
983 | return s3c24xxfb_probe(pdev, DRV_S3C2412); | ||
984 | } | ||
985 | |||
949 | /* s3c2410fb_stop_lcd | 986 | /* s3c2410fb_stop_lcd |
950 | * | 987 | * |
951 | * shutdown the lcd controller | 988 | * shutdown the lcd controller |
@@ -1047,14 +1084,31 @@ static struct platform_driver s3c2410fb_driver = { | |||
1047 | }, | 1084 | }, |
1048 | }; | 1085 | }; |
1049 | 1086 | ||
1087 | static struct platform_driver s3c2412fb_driver = { | ||
1088 | .probe = s3c2412fb_probe, | ||
1089 | .remove = s3c2410fb_remove, | ||
1090 | .suspend = s3c2410fb_suspend, | ||
1091 | .resume = s3c2410fb_resume, | ||
1092 | .driver = { | ||
1093 | .name = "s3c2412-lcd", | ||
1094 | .owner = THIS_MODULE, | ||
1095 | }, | ||
1096 | }; | ||
1097 | |||
1050 | int __init s3c2410fb_init(void) | 1098 | int __init s3c2410fb_init(void) |
1051 | { | 1099 | { |
1052 | return platform_driver_register(&s3c2410fb_driver); | 1100 | int ret = platform_driver_register(&s3c2410fb_driver); |
1101 | |||
1102 | if (ret == 0) | ||
1103 | ret = platform_driver_register(&s3c2412fb_driver);; | ||
1104 | |||
1105 | return ret; | ||
1053 | } | 1106 | } |
1054 | 1107 | ||
1055 | static void __exit s3c2410fb_cleanup(void) | 1108 | static void __exit s3c2410fb_cleanup(void) |
1056 | { | 1109 | { |
1057 | platform_driver_unregister(&s3c2410fb_driver); | 1110 | platform_driver_unregister(&s3c2410fb_driver); |
1111 | platform_driver_unregister(&s3c2412fb_driver); | ||
1058 | } | 1112 | } |
1059 | 1113 | ||
1060 | module_init(s3c2410fb_init); | 1114 | module_init(s3c2410fb_init); |
diff --git a/drivers/video/s3c2410fb.h b/drivers/video/s3c2410fb.h index 6ce5dc26c5f7..dbb73b95e2ef 100644 --- a/drivers/video/s3c2410fb.h +++ b/drivers/video/s3c2410fb.h | |||
@@ -25,13 +25,20 @@ | |||
25 | #ifndef __S3C2410FB_H | 25 | #ifndef __S3C2410FB_H |
26 | #define __S3C2410FB_H | 26 | #define __S3C2410FB_H |
27 | 27 | ||
28 | enum s3c_drv_type { | ||
29 | DRV_S3C2410, | ||
30 | DRV_S3C2412, | ||
31 | }; | ||
32 | |||
28 | struct s3c2410fb_info { | 33 | struct s3c2410fb_info { |
29 | struct device *dev; | 34 | struct device *dev; |
30 | struct clk *clk; | 35 | struct clk *clk; |
31 | 36 | ||
32 | struct resource *mem; | 37 | struct resource *mem; |
33 | void __iomem *io; | 38 | void __iomem *io; |
39 | void __iomem *irq_base; | ||
34 | 40 | ||
41 | enum s3c_drv_type drv_type; | ||
35 | struct s3c2410fb_hw regs; | 42 | struct s3c2410fb_hw regs; |
36 | 43 | ||
37 | unsigned int palette_ready; | 44 | unsigned int palette_ready; |
diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c index 93ae747440cb..73803624c131 100644 --- a/drivers/video/sis/sis_main.c +++ b/drivers/video/sis/sis_main.c | |||
@@ -427,7 +427,7 @@ sisfb_interpret_edid(struct sisfb_monitor *monitor, u8 *buffer) | |||
427 | 427 | ||
428 | monitor->feature = buffer[0x18]; | 428 | monitor->feature = buffer[0x18]; |
429 | 429 | ||
430 | if(!buffer[0x14] & 0x80) { | 430 | if(!(buffer[0x14] & 0x80)) { |
431 | if(!(buffer[0x14] & 0x08)) { | 431 | if(!(buffer[0x14] & 0x08)) { |
432 | printk(KERN_INFO | 432 | printk(KERN_INFO |
433 | "sisfb: WARNING: Monitor does not support separate syncs\n"); | 433 | "sisfb: WARNING: Monitor does not support separate syncs\n"); |
@@ -4621,9 +4621,9 @@ sisfb_find_host_bridge(struct sis_video_info *ivideo, struct pci_dev *mypdev, | |||
4621 | 4621 | ||
4622 | while((pdev = pci_get_class(PCI_CLASS_BRIDGE_HOST, pdev))) { | 4622 | while((pdev = pci_get_class(PCI_CLASS_BRIDGE_HOST, pdev))) { |
4623 | temp = pdev->vendor; | 4623 | temp = pdev->vendor; |
4624 | pci_dev_put(pdev); | ||
4625 | if(temp == pcivendor) { | 4624 | if(temp == pcivendor) { |
4626 | ret = 1; | 4625 | ret = 1; |
4626 | pci_dev_put(pdev); | ||
4627 | break; | 4627 | break; |
4628 | } | 4628 | } |
4629 | } | 4629 | } |
diff --git a/drivers/video/sm501fb.c b/drivers/video/sm501fb.c index 58f200c69be3..e83dfba7e636 100644 --- a/drivers/video/sm501fb.c +++ b/drivers/video/sm501fb.c | |||
@@ -641,6 +641,7 @@ static void sm501fb_panel_power(struct sm501fb_info *fbi, int to) | |||
641 | { | 641 | { |
642 | unsigned long control; | 642 | unsigned long control; |
643 | void __iomem *ctrl_reg = fbi->regs + SM501_DC_PANEL_CONTROL; | 643 | void __iomem *ctrl_reg = fbi->regs + SM501_DC_PANEL_CONTROL; |
644 | struct sm501_platdata_fbsub *pd = fbi->pdata->fb_pnl; | ||
644 | 645 | ||
645 | control = readl(ctrl_reg); | 646 | control = readl(ctrl_reg); |
646 | 647 | ||
@@ -657,26 +658,34 @@ static void sm501fb_panel_power(struct sm501fb_info *fbi, int to) | |||
657 | sm501fb_sync_regs(fbi); | 658 | sm501fb_sync_regs(fbi); |
658 | mdelay(10); | 659 | mdelay(10); |
659 | 660 | ||
660 | control |= SM501_DC_PANEL_CONTROL_BIAS; /* VBIASEN */ | 661 | if (pd->flags & SM501FB_FLAG_PANEL_USE_VBIASEN) { |
661 | writel(control, ctrl_reg); | 662 | control |= SM501_DC_PANEL_CONTROL_BIAS; /* VBIASEN */ |
662 | sm501fb_sync_regs(fbi); | 663 | writel(control, ctrl_reg); |
663 | mdelay(10); | 664 | sm501fb_sync_regs(fbi); |
664 | 665 | mdelay(10); | |
665 | control |= SM501_DC_PANEL_CONTROL_FPEN; | 666 | } |
666 | writel(control, ctrl_reg); | ||
667 | 667 | ||
668 | if (pd->flags & SM501FB_FLAG_PANEL_USE_FPEN) { | ||
669 | control |= SM501_DC_PANEL_CONTROL_FPEN; | ||
670 | writel(control, ctrl_reg); | ||
671 | sm501fb_sync_regs(fbi); | ||
672 | mdelay(10); | ||
673 | } | ||
668 | } else if (!to && (control & SM501_DC_PANEL_CONTROL_VDD) != 0) { | 674 | } else if (!to && (control & SM501_DC_PANEL_CONTROL_VDD) != 0) { |
669 | /* disable panel power */ | 675 | /* disable panel power */ |
676 | if (pd->flags & SM501FB_FLAG_PANEL_USE_FPEN) { | ||
677 | control &= ~SM501_DC_PANEL_CONTROL_FPEN; | ||
678 | writel(control, ctrl_reg); | ||
679 | sm501fb_sync_regs(fbi); | ||
680 | mdelay(10); | ||
681 | } | ||
670 | 682 | ||
671 | control &= ~SM501_DC_PANEL_CONTROL_FPEN; | 683 | if (pd->flags & SM501FB_FLAG_PANEL_USE_VBIASEN) { |
672 | writel(control, ctrl_reg); | 684 | control &= ~SM501_DC_PANEL_CONTROL_BIAS; |
673 | sm501fb_sync_regs(fbi); | 685 | writel(control, ctrl_reg); |
674 | mdelay(10); | 686 | sm501fb_sync_regs(fbi); |
675 | 687 | mdelay(10); | |
676 | control &= ~SM501_DC_PANEL_CONTROL_BIAS; | 688 | } |
677 | writel(control, ctrl_reg); | ||
678 | sm501fb_sync_regs(fbi); | ||
679 | mdelay(10); | ||
680 | 689 | ||
681 | control &= ~SM501_DC_PANEL_CONTROL_DATA; | 690 | control &= ~SM501_DC_PANEL_CONTROL_DATA; |
682 | writel(control, ctrl_reg); | 691 | writel(control, ctrl_reg); |
@@ -1267,6 +1276,7 @@ static int sm501fb_start(struct sm501fb_info *info, | |||
1267 | { | 1276 | { |
1268 | struct resource *res; | 1277 | struct resource *res; |
1269 | struct device *dev; | 1278 | struct device *dev; |
1279 | int k; | ||
1270 | int ret; | 1280 | int ret; |
1271 | 1281 | ||
1272 | info->dev = dev = &pdev->dev; | 1282 | info->dev = dev = &pdev->dev; |
@@ -1328,6 +1338,13 @@ static int sm501fb_start(struct sm501fb_info *info, | |||
1328 | 1338 | ||
1329 | info->fbmem_len = (res->end - res->start)+1; | 1339 | info->fbmem_len = (res->end - res->start)+1; |
1330 | 1340 | ||
1341 | /* clear framebuffer memory - avoids garbage data on unused fb */ | ||
1342 | memset(info->fbmem, 0, info->fbmem_len); | ||
1343 | |||
1344 | /* clear palette ram - undefined at power on */ | ||
1345 | for (k = 0; k < (256 * 3); k++) | ||
1346 | writel(0, info->regs + SM501_DC_PANEL_PALETTE + (k * 4)); | ||
1347 | |||
1331 | /* enable display controller */ | 1348 | /* enable display controller */ |
1332 | sm501_unit_power(dev->parent, SM501_GATE_DISPLAY, 1); | 1349 | sm501_unit_power(dev->parent, SM501_GATE_DISPLAY, 1); |
1333 | 1350 | ||
@@ -1681,6 +1698,15 @@ static int sm501fb_suspend_fb(struct sm501fb_info *info, | |||
1681 | if (par->screen.size == 0) | 1698 | if (par->screen.size == 0) |
1682 | return 0; | 1699 | return 0; |
1683 | 1700 | ||
1701 | /* blank the relevant interface to ensure unit power minimised */ | ||
1702 | (par->ops.fb_blank)(FB_BLANK_POWERDOWN, fbi); | ||
1703 | |||
1704 | /* tell console/fb driver we are suspending */ | ||
1705 | |||
1706 | acquire_console_sem(); | ||
1707 | fb_set_suspend(fbi, 1); | ||
1708 | release_console_sem(); | ||
1709 | |||
1684 | /* backup copies in case chip is powered down over suspend */ | 1710 | /* backup copies in case chip is powered down over suspend */ |
1685 | 1711 | ||
1686 | par->store_fb = vmalloc(par->screen.size); | 1712 | par->store_fb = vmalloc(par->screen.size); |
@@ -1700,12 +1726,6 @@ static int sm501fb_suspend_fb(struct sm501fb_info *info, | |||
1700 | 1726 | ||
1701 | memcpy_fromio(par->store_fb, par->screen.k_addr, par->screen.size); | 1727 | memcpy_fromio(par->store_fb, par->screen.k_addr, par->screen.size); |
1702 | memcpy_fromio(par->store_cursor, par->cursor.k_addr, par->cursor.size); | 1728 | memcpy_fromio(par->store_cursor, par->cursor.k_addr, par->cursor.size); |
1703 | /* blank the relevant interface to ensure unit power minimised */ | ||
1704 | (par->ops.fb_blank)(FB_BLANK_POWERDOWN, fbi); | ||
1705 | |||
1706 | acquire_console_sem(); | ||
1707 | fb_set_suspend(fbi, 1); | ||
1708 | release_console_sem(); | ||
1709 | 1729 | ||
1710 | return 0; | 1730 | return 0; |
1711 | 1731 | ||
diff --git a/drivers/video/tdfxfb.c b/drivers/video/tdfxfb.c index 057bdd593800..71e179ea5f95 100644 --- a/drivers/video/tdfxfb.c +++ b/drivers/video/tdfxfb.c | |||
@@ -1342,7 +1342,7 @@ out_err: | |||
1342 | } | 1342 | } |
1343 | 1343 | ||
1344 | #ifndef MODULE | 1344 | #ifndef MODULE |
1345 | static void tdfxfb_setup(char *options) | 1345 | static void __init tdfxfb_setup(char *options) |
1346 | { | 1346 | { |
1347 | char *this_opt; | 1347 | char *this_opt; |
1348 | 1348 | ||
diff --git a/drivers/video/uvesafb.c b/drivers/video/uvesafb.c index a14ef894d571..be27b9c1ed72 100644 --- a/drivers/video/uvesafb.c +++ b/drivers/video/uvesafb.c | |||
@@ -2003,12 +2003,12 @@ static void __devexit uvesafb_exit(void) | |||
2003 | 2003 | ||
2004 | module_exit(uvesafb_exit); | 2004 | module_exit(uvesafb_exit); |
2005 | 2005 | ||
2006 | static inline int param_get_scroll(char *buffer, struct kernel_param *kp) | 2006 | static int param_get_scroll(char *buffer, struct kernel_param *kp) |
2007 | { | 2007 | { |
2008 | return 0; | 2008 | return 0; |
2009 | } | 2009 | } |
2010 | 2010 | ||
2011 | static inline int param_set_scroll(const char *val, struct kernel_param *kp) | 2011 | static int param_set_scroll(const char *val, struct kernel_param *kp) |
2012 | { | 2012 | { |
2013 | ypan = 0; | 2013 | ypan = 0; |
2014 | 2014 | ||
@@ -2022,11 +2022,11 @@ static inline int param_set_scroll(const char *val, struct kernel_param *kp) | |||
2022 | return 0; | 2022 | return 0; |
2023 | } | 2023 | } |
2024 | 2024 | ||
2025 | #define param_check_scroll(name, p) __param_check(name, p, void); | 2025 | #define param_check_scroll(name, p) __param_check(name, p, void) |
2026 | 2026 | ||
2027 | module_param_named(scroll, ypan, scroll, 0); | 2027 | module_param_named(scroll, ypan, scroll, 0); |
2028 | MODULE_PARM_DESC(scroll, | 2028 | MODULE_PARM_DESC(scroll, |
2029 | "Scrolling mode, set to 'redraw', ''ypan' or 'ywrap'"); | 2029 | "Scrolling mode, set to 'redraw', 'ypan', or 'ywrap'"); |
2030 | module_param_named(vgapal, pmi_setpal, invbool, 0); | 2030 | module_param_named(vgapal, pmi_setpal, invbool, 0); |
2031 | MODULE_PARM_DESC(vgapal, "Set palette using VGA registers"); | 2031 | MODULE_PARM_DESC(vgapal, "Set palette using VGA registers"); |
2032 | module_param_named(pmipal, pmi_setpal, bool, 0); | 2032 | module_param_named(pmipal, pmi_setpal, bool, 0); |
diff --git a/drivers/video/vermilion/vermilion.c b/drivers/video/vermilion/vermilion.c index 1c656667b937..2aa71eb67c2b 100644 --- a/drivers/video/vermilion/vermilion.c +++ b/drivers/video/vermilion/vermilion.c | |||
@@ -651,7 +651,7 @@ static int vmlfb_check_var_locked(struct fb_var_screeninfo *var, | |||
651 | return -EINVAL; | 651 | return -EINVAL; |
652 | } | 652 | } |
653 | 653 | ||
654 | pitch = __ALIGN_MASK((var->xres * var->bits_per_pixel) >> 3, 0x3F); | 654 | pitch = ALIGN((var->xres * var->bits_per_pixel) >> 3, 0x40); |
655 | mem = pitch * var->yres_virtual; | 655 | mem = pitch * var->yres_virtual; |
656 | if (mem > vinfo->vram_contig_size) { | 656 | if (mem > vinfo->vram_contig_size) { |
657 | return -ENOMEM; | 657 | return -ENOMEM; |
@@ -785,8 +785,7 @@ static int vmlfb_set_par_locked(struct vml_info *vinfo) | |||
785 | int clock; | 785 | int clock; |
786 | 786 | ||
787 | vinfo->bytes_per_pixel = var->bits_per_pixel >> 3; | 787 | vinfo->bytes_per_pixel = var->bits_per_pixel >> 3; |
788 | vinfo->stride = | 788 | vinfo->stride = ALIGN(var->xres_virtual * vinfo->bytes_per_pixel, 0x40); |
789 | __ALIGN_MASK(var->xres_virtual * vinfo->bytes_per_pixel, 0x3F); | ||
790 | info->fix.line_length = vinfo->stride; | 789 | info->fix.line_length = vinfo->stride; |
791 | 790 | ||
792 | if (!subsys) | 791 | if (!subsys) |